From 312f7da2824c82800ee78d6190f12854456957af Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Tue, 27 Sep 2005 17:38:03 +0800 Subject: [PATCH] libata: interrupt driven pio for libata-core - add PIO_ST_FIRST for the state before sending ATAPI CDB or sending "ATA PIO data out" first data block. - add ATA_TFLAG_POLLING and ATA_DFLAG_CDB_INTR flags - remove the ATA_FLAG_NOINTR flag since the interrupt handler is now aware of the states - modify ata_pio_sector() and atapi_pio_bytes() to work in the interrupt context - modify the ata_host_intr() to handle PIO interrupts - modify ata_qc_issue_prot() to initialize states - atapi_packet_task() changed to handle "ATA PIO data out" first data block - support the pre-ATA4 ATAPI device which raise interrupt when ready to receive CDB Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 333 ++++++++++++++++++++++++++++++++++++--------- include/linux/ata.h | 3 + include/linux/libata.h | 4 +- 3 files changed, 271 insertions(+), 69 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index c4fcdc30f18..cc2d1308826 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1292,6 +1292,9 @@ retry: ap->cdb_len = (unsigned int) rc; ap->host->max_cmd_len = (unsigned char) ap->cdb_len; + if (ata_id_cdb_intr(dev->id)) + dev->flags |= ATA_DFLAG_CDB_INTR; + /* print device info to dmesg */ printk(KERN_INFO "ata%u: dev %u ATAPI, max %s\n", ap->id, device, @@ -2405,7 +2408,6 @@ void ata_poll_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat) unsigned long flags; spin_lock_irqsave(&ap->host_set->lock, flags); - ap->flags &= ~ATA_FLAG_NOINTR; ata_irq_on(ap); ata_qc_complete(qc, drv_stat); spin_unlock_irqrestore(&ap->host_set->lock, flags); @@ -2660,6 +2662,7 @@ static void ata_pio_sector(struct ata_queued_cmd *qc) struct page *page; unsigned int offset; unsigned char *buf; + unsigned long flags; if (qc->cursect == (qc->nsect - 1)) ap->hsm_task_state = HSM_ST_LAST; @@ -2671,7 +2674,8 @@ static void ata_pio_sector(struct ata_queued_cmd *qc) page = nth_page(page, (offset >> PAGE_SHIFT)); offset %= PAGE_SIZE; - buf = kmap(page) + offset; + local_irq_save(flags); + buf = kmap_atomic(page, KM_IRQ0) + offset; qc->cursect++; qc->cursg_ofs++; @@ -2687,7 +2691,8 @@ static void ata_pio_sector(struct ata_queued_cmd *qc) do_write = (qc->tf.flags & ATA_TFLAG_WRITE); ata_data_xfer(ap, buf, ATA_SECT_SIZE, do_write); - kunmap(page); + kunmap_atomic(buf - offset, KM_IRQ0); + local_irq_restore(flags); } /** @@ -2710,6 +2715,7 @@ static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes) struct page *page; unsigned char *buf; unsigned int offset, count; + unsigned long flags; if (qc->curbytes + bytes >= qc->nbytes) ap->hsm_task_state = HSM_ST_LAST; @@ -2753,7 +2759,8 @@ next_sg: /* don't cross page boundaries */ count = min(count, (unsigned int)PAGE_SIZE - offset); - buf = kmap(page) + offset; + local_irq_save(flags); + buf = kmap_atomic(page, KM_IRQ0) + offset; bytes -= count; qc->curbytes += count; @@ -2769,7 +2776,8 @@ next_sg: /* do the actual data transfer */ ata_data_xfer(ap, buf, count, do_write); - kunmap(page); + kunmap_atomic(buf - offset, KM_IRQ0); + local_irq_restore(flags); if (bytes) goto next_sg; @@ -2808,6 +2816,8 @@ static void atapi_pio_bytes(struct ata_queued_cmd *qc) if (do_write != i_write) goto err_out; + VPRINTK("ata%u: xfering %d bytes\n", ap->id, bytes); + __atapi_pio_bytes(qc, bytes); return; @@ -3054,6 +3064,8 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc) printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x host_stat 0x%x\n", ap->id, qc->tf.command, drv_stat, host_stat); + ap->hsm_task_state = HSM_ST_IDLE; + /* complete taskfile transaction */ ata_qc_complete(qc, drv_stat); break; @@ -3344,43 +3356,96 @@ int ata_qc_issue_prot(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; + /* select the device */ ata_dev_select(ap, qc->dev->devno, 1, 0); + /* start the command */ switch (qc->tf.protocol) { case ATA_PROT_NODATA: + if (qc->tf.flags & ATA_TFLAG_POLLING) + ata_qc_set_polling(qc); + ata_tf_to_host_nolock(ap, &qc->tf); + ap->hsm_task_state = HSM_ST_LAST; + + if (qc->tf.flags & ATA_TFLAG_POLLING) + queue_work(ata_wq, &ap->pio_task); + break; case ATA_PROT_DMA: + assert(!(qc->tf.flags & ATA_TFLAG_POLLING)); + ap->ops->tf_load(ap, &qc->tf); /* load tf registers */ ap->ops->bmdma_setup(qc); /* set up bmdma */ ap->ops->bmdma_start(qc); /* initiate bmdma */ + ap->hsm_task_state = HSM_ST_LAST; break; - case ATA_PROT_PIO: /* load tf registers, initiate polling pio */ - ata_qc_set_polling(qc); + case ATA_PROT_PIO: + if (qc->tf.flags & ATA_TFLAG_POLLING) + ata_qc_set_polling(qc); + ata_tf_to_host_nolock(ap, &qc->tf); - ap->hsm_task_state = HSM_ST; - queue_work(ata_wq, &ap->pio_task); + + if (qc->tf.flags & ATA_TFLAG_POLLING) { + /* polling PIO */ + ap->hsm_task_state = HSM_ST; + queue_work(ata_wq, &ap->pio_task); + } else { + /* interrupt driven PIO */ + if (qc->tf.flags & ATA_TFLAG_WRITE) { + /* PIO data out protocol */ + ap->hsm_task_state = HSM_ST_FIRST; + queue_work(ata_wq, &ap->packet_task); + + /* send first data block by polling */ + } else { + /* PIO data in protocol */ + ap->hsm_task_state = HSM_ST; + + /* interrupt handler takes over from here */ + } + } + break; case ATA_PROT_ATAPI: - ata_qc_set_polling(qc); + if (qc->tf.flags & ATA_TFLAG_POLLING) + ata_qc_set_polling(qc); + ata_tf_to_host_nolock(ap, &qc->tf); - queue_work(ata_wq, &ap->packet_task); + ap->hsm_task_state = HSM_ST_FIRST; + + /* send cdb by polling if no cdb interrupt */ + if ((!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) || + (qc->tf.flags & ATA_TFLAG_POLLING)) + queue_work(ata_wq, &ap->packet_task); break; case ATA_PROT_ATAPI_NODATA: - ap->flags |= ATA_FLAG_NOINTR; + if (qc->tf.flags & ATA_TFLAG_POLLING) + ata_qc_set_polling(qc); + ata_tf_to_host_nolock(ap, &qc->tf); - queue_work(ata_wq, &ap->packet_task); + ap->hsm_task_state = HSM_ST_FIRST; + + /* send cdb by polling if no cdb interrupt */ + if ((!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) || + (qc->tf.flags & ATA_TFLAG_POLLING)) + queue_work(ata_wq, &ap->packet_task); break; case ATA_PROT_ATAPI_DMA: - ap->flags |= ATA_FLAG_NOINTR; + assert(!(qc->tf.flags & ATA_TFLAG_POLLING)); + ap->ops->tf_load(ap, &qc->tf); /* load tf registers */ ap->ops->bmdma_setup(qc); /* set up bmdma */ - queue_work(ata_wq, &ap->packet_task); + ap->hsm_task_state = HSM_ST_FIRST; + + /* send cdb by polling if no cdb interrupt */ + if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) + queue_work(ata_wq, &ap->packet_task); break; default: @@ -3622,6 +3687,42 @@ void ata_bmdma_stop(struct ata_queued_cmd *qc) ata_altstatus(ap); /* dummy read */ } +/** + * atapi_send_cdb - Write CDB bytes to hardware + * @ap: Port to which ATAPI device is attached. + * @qc: Taskfile currently active + * + * When device has indicated its readiness to accept + * a CDB, this function is called. Send the CDB. + * + * LOCKING: + * caller. + */ + +static void atapi_send_cdb(struct ata_port *ap, struct ata_queued_cmd *qc) +{ + /* send SCSI cdb */ + DPRINTK("send cdb\n"); + assert(ap->cdb_len >= 12); + + ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1); + ata_altstatus(ap); /* flush */ + + switch (qc->tf.protocol) { + case ATA_PROT_ATAPI: + ap->hsm_task_state = HSM_ST; + break; + case ATA_PROT_ATAPI_NODATA: + ap->hsm_task_state = HSM_ST_LAST; + break; + case ATA_PROT_ATAPI_DMA: + ap->hsm_task_state = HSM_ST_LAST; + /* initiate bmdma */ + ap->ops->bmdma_start(qc); + break; + } +} + /** * ata_host_intr - Handle host interrupt for given (port, task) * @ap: Port on which interrupt arrived (possibly...) @@ -3641,47 +3742,142 @@ void ata_bmdma_stop(struct ata_queued_cmd *qc) inline unsigned int ata_host_intr (struct ata_port *ap, struct ata_queued_cmd *qc) { - u8 status, host_stat; - - switch (qc->tf.protocol) { + u8 status, host_stat = 0; - case ATA_PROT_DMA: - case ATA_PROT_ATAPI_DMA: - case ATA_PROT_ATAPI: - /* check status of DMA engine */ - host_stat = ap->ops->bmdma_status(ap); - VPRINTK("ata%u: host_stat 0x%X\n", ap->id, host_stat); + VPRINTK("ata%u: protocol %d task_state %d\n", + ap->id, qc->tf.protocol, ap->hsm_task_state); - /* if it's not our irq... */ - if (!(host_stat & ATA_DMA_INTR)) + /* Check whether we are expecting interrupt in this state */ + switch (ap->hsm_task_state) { + case HSM_ST_FIRST: + /* Check the ATA_DFLAG_CDB_INTR flag is enough here. + * The flag was turned on only for atapi devices. + * No need to check is_atapi_taskfile(&qc->tf) again. + */ + if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) goto idle_irq; + break; + case HSM_ST_LAST: + if (qc->tf.protocol == ATA_PROT_DMA || + qc->tf.protocol == ATA_PROT_ATAPI_DMA) { + /* check status of DMA engine */ + host_stat = ap->ops->bmdma_status(ap); + VPRINTK("ata%u: host_stat 0x%X\n", ap->id, host_stat); + + /* if it's not our irq... */ + if (!(host_stat & ATA_DMA_INTR)) + goto idle_irq; + + /* before we do anything else, clear DMA-Start bit */ + ap->ops->bmdma_stop(qc); + } + break; + case HSM_ST: + break; + default: + goto idle_irq; + } - /* before we do anything else, clear DMA-Start bit */ - ap->ops->bmdma_stop(qc); + /* check altstatus */ + status = ata_altstatus(ap); + if (status & ATA_BUSY) + goto idle_irq; - /* fall through */ + /* check main status, clearing INTRQ */ + status = ata_chk_status(ap); + if (unlikely(status & ATA_BUSY)) + goto idle_irq; - case ATA_PROT_ATAPI_NODATA: - case ATA_PROT_NODATA: - /* check altstatus */ - status = ata_altstatus(ap); - if (status & ATA_BUSY) - goto idle_irq; + DPRINTK("ata%u: protocol %d task_state %d (dev_stat 0x%X)\n", + ap->id, qc->tf.protocol, ap->hsm_task_state, status); - /* check main status, clearing INTRQ */ - status = ata_chk_status(ap); - if (unlikely(status & ATA_BUSY)) - goto idle_irq; - DPRINTK("ata%u: protocol %d (dev_stat 0x%X)\n", - ap->id, qc->tf.protocol, status); + /* ack bmdma irq events */ + ap->ops->irq_clear(ap); - /* ack bmdma irq events */ - ap->ops->irq_clear(ap); + /* check error */ + if (unlikely((status & ATA_ERR) || (host_stat & ATA_DMA_ERR))) + ap->hsm_task_state = HSM_ST_ERR; + +fsm_start: + switch (ap->hsm_task_state) { + case HSM_ST_FIRST: + /* Some pre-ATAPI-4 devices assert INTRQ + * at this state when ready to receive CDB. + */ + + /* check device status */ + if (unlikely((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ)) { + /* Wrong status. Let EH handle this */ + ap->hsm_task_state = HSM_ST_ERR; + goto fsm_start; + } + + atapi_send_cdb(ap, qc); + + break; + + case HSM_ST: + /* complete command or read/write the data register */ + if (qc->tf.protocol == ATA_PROT_ATAPI) { + /* ATAPI PIO protocol */ + if ((status & ATA_DRQ) == 0) { + /* no more data to transfer */ + ap->hsm_task_state = HSM_ST_LAST; + goto fsm_start; + } + + atapi_pio_bytes(qc); + + if (unlikely(ap->hsm_task_state == HSM_ST_ERR)) + /* bad ireason reported by device */ + goto fsm_start; + + } else { + /* ATA PIO protocol */ + if (unlikely((status & ATA_DRQ) == 0)) { + /* handle BSY=0, DRQ=0 as error */ + ap->hsm_task_state = HSM_ST_ERR; + goto fsm_start; + } + + ata_pio_sector(qc); + + if (ap->hsm_task_state == HSM_ST_LAST && + (!(qc->tf.flags & ATA_TFLAG_WRITE))) { + /* all data read */ + ata_altstatus(ap); + status = ata_chk_status(ap); + goto fsm_start; + } + } + + ata_altstatus(ap); /* flush */ + break; + + case HSM_ST_LAST: + if (unlikely(status & ATA_DRQ)) { + /* handle DRQ=1 as error */ + ap->hsm_task_state = HSM_ST_ERR; + goto fsm_start; + } + + /* no more data to transfer */ + DPRINTK("ata%u: command complete, drv_stat 0x%x\n", + ap->id, status); + + ap->hsm_task_state = HSM_ST_IDLE; /* complete taskfile transaction */ ata_qc_complete(qc, status); break; + case HSM_ST_ERR: + printk(KERN_ERR "ata%u: command error, drv_stat 0x%x host_stat 0x%x\n", + ap->id, status, host_stat); + + ap->hsm_task_state = HSM_ST_IDLE; + ata_qc_complete(qc, status | ATA_ERR); + break; default: goto idle_irq; } @@ -3733,11 +3929,11 @@ irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs) ap = host_set->ports[i]; if (ap && - !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) { + !(ap->flags & ATA_FLAG_PORT_DISABLED)) { struct ata_queued_cmd *qc; qc = ata_qc_from_tag(ap, ap->active_tag); - if (qc && (!(qc->tf.ctl & ATA_NIEN)) && + if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)) && (qc->flags & ATA_QCFLAG_ACTIVE)) handled |= ata_host_intr(ap, qc); } @@ -3767,6 +3963,7 @@ static void atapi_packet_task(void *_data) struct ata_port *ap = _data; struct ata_queued_cmd *qc; u8 status; + unsigned long flags; qc = ata_qc_from_tag(ap, ap->active_tag); assert(qc != NULL); @@ -3782,38 +3979,40 @@ static void atapi_packet_task(void *_data) if ((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ) goto err_out; - /* send SCSI cdb */ - DPRINTK("send cdb\n"); - assert(ap->cdb_len >= 12); + /* Send the CDB (atapi) or the first data block (ata pio out). + * During the state transition, interrupt handler shouldn't + * be invoked before the data transfer is complete and + * hsm_task_state is changed. Hence, the following locking. + */ + spin_lock_irqsave(&ap->host_set->lock, flags); - if (qc->tf.protocol == ATA_PROT_ATAPI_DMA || - qc->tf.protocol == ATA_PROT_ATAPI_NODATA) { - unsigned long flags; + if (is_atapi_taskfile(&qc->tf)) { + /* send CDB */ + atapi_send_cdb(ap, qc); - /* Once we're done issuing command and kicking bmdma, - * irq handler takes over. To not lose irq, we need - * to clear NOINTR flag before sending cdb, but - * interrupt handler shouldn't be invoked before we're - * finished. Hence, the following locking. - */ - spin_lock_irqsave(&ap->host_set->lock, flags); - ap->flags &= ~ATA_FLAG_NOINTR; - ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1); - if (qc->tf.protocol == ATA_PROT_ATAPI_DMA) - ap->ops->bmdma_start(qc); /* initiate bmdma */ - spin_unlock_irqrestore(&ap->host_set->lock, flags); + if (qc->tf.flags & ATA_TFLAG_POLLING) + queue_work(ata_wq, &ap->pio_task); } else { - ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1); + /* PIO data out protocol. + * send first data block. + */ - /* PIO commands are handled by polling */ + /* ata_pio_sector() might change the state to HSM_ST_LAST. + * so, the state is changed here before ata_pio_sector(). + */ ap->hsm_task_state = HSM_ST; - queue_work(ata_wq, &ap->pio_task); + ata_pio_sector(qc); + ata_altstatus(ap); /* flush */ + + /* interrupt handler takes over from here */ } + spin_unlock_irqrestore(&ap->host_set->lock, flags); + return; err_out: - ata_poll_qc_complete(qc, ATA_ERR); + ata_pio_error(ap); } diff --git a/include/linux/ata.h b/include/linux/ata.h index a5b74efab06..6fec2f6f2d5 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -181,6 +181,7 @@ enum { ATA_TFLAG_ISADDR = (1 << 1), /* enable r/w to nsect/lba regs */ ATA_TFLAG_DEVICE = (1 << 2), /* enable r/w to device reg */ ATA_TFLAG_WRITE = (1 << 3), /* data dir: host->dev==1 (write) */ + ATA_TFLAG_POLLING = (1 << 4), /* set nIEN to 1 and use polling */ }; enum ata_tf_protocols { @@ -250,6 +251,8 @@ struct ata_taskfile { ((u64) (id)[(n) + 1] << 16) | \ ((u64) (id)[(n) + 0]) ) +#define ata_id_cdb_intr(id) (((id)[0] & 0x60) == 0x20) + static inline int atapi_cdb_len(u16 *dev_id) { u16 tmp = dev_id[0] & 0x3; diff --git a/include/linux/libata.h b/include/linux/libata.h index bb2d916bce4..9ac2b69df3c 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -97,6 +97,7 @@ enum { ATA_DFLAG_LBA48 = (1 << 0), /* device supports LBA48 */ ATA_DFLAG_PIO = (1 << 1), /* device currently in PIO mode */ ATA_DFLAG_LOCK_SECTORS = (1 << 2), /* don't adjust max_sectors */ + ATA_DFLAG_CDB_INTR = (1 << 3), /* device asserts INTRQ when ready for CDB */ ATA_DEV_UNKNOWN = 0, /* unknown device */ ATA_DEV_ATA = 1, /* ATA device */ @@ -115,8 +116,6 @@ enum { ATA_FLAG_MMIO = (1 << 6), /* use MMIO, not PIO */ ATA_FLAG_SATA_RESET = (1 << 7), /* use COMRESET */ ATA_FLAG_PIO_DMA = (1 << 8), /* PIO cmds via DMA */ - ATA_FLAG_NOINTR = (1 << 9), /* FIXME: Remove this once - * proper HSM is in place. */ ATA_QCFLAG_ACTIVE = (1 << 1), /* cmd not yet ack'd to scsi lyer */ ATA_QCFLAG_SG = (1 << 3), /* have s/g table? */ @@ -165,6 +164,7 @@ enum hsm_task_states { HSM_ST_LAST, HSM_ST_LAST_POLL, HSM_ST_ERR, + HSM_ST_FIRST, }; /* forward declarations */ -- cgit v1.2.3 From e50362eccd8809a224cda5f71714a088ba37b2ab Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Tue, 27 Sep 2005 17:39:50 +0800 Subject: [PATCH] libata: interrupt driven pio for LLD libata.h: libata-core: Add ATA_FLAG_PIO_POLLING flag for LLDs that expect interrupt for command completion only. sata_nv.c: sata_vsc.c: irq handler is wrapper around ata_host_intr(), can handle PIO interrupts. sata_promise.c: sata_sx4.c: sata_qstor.c: sata_mv.c: Private irq handler. Polling mode ATA_FLAG_PIO_POLLING used for compatibility. Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 19 +++++++++++++++++++ drivers/scsi/sata_mv.c | 7 +++++-- drivers/scsi/sata_nv.c | 4 ++-- drivers/scsi/sata_promise.c | 13 ++++++++----- drivers/scsi/sata_qstor.c | 11 +++++------ drivers/scsi/sata_sx4.c | 7 ++++--- drivers/scsi/sata_vsc.c | 6 +++--- include/linux/libata.h | 2 ++ 8 files changed, 48 insertions(+), 21 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index cc2d1308826..f8a590e59f1 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3356,6 +3356,25 @@ int ata_qc_issue_prot(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; + /* Use polling pio if the LLD doesn't handle + * interrupt driven pio and atapi CDB interrupt. + */ + if (ap->flags & ATA_FLAG_PIO_POLLING) { + switch (qc->tf.protocol) { + case ATA_PROT_PIO: + case ATA_PROT_ATAPI: + case ATA_PROT_ATAPI_NODATA: + qc->tf.flags |= ATA_TFLAG_POLLING; + break; + case ATA_PROT_ATAPI_DMA: + if (qc->dev->flags & ATA_DFLAG_CDB_INTR) + BUG(); + break; + default: + break; + } + } + /* select the device */ ata_dev_select(ap, qc->dev->devno, 1, 0); diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index ea76fe44585..b8f1f696317 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -241,7 +241,8 @@ static struct ata_port_info mv_port_info[] = { { /* chip_504x */ .sht = &mv_sht, .host_flags = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO), + ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO | + ATA_FLAG_PIO_POLLING), .pio_mask = 0x1f, /* pio4-0 */ .udma_mask = 0, /* 0x7f (udma6-0 disabled for now) */ .port_ops = &mv_ops, @@ -250,7 +251,7 @@ static struct ata_port_info mv_port_info[] = { .sht = &mv_sht, .host_flags = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO | - MV_FLAG_DUAL_HC), + ATA_FLAG_PIO_POLLING | MV_FLAG_DUAL_HC), .pio_mask = 0x1f, /* pio4-0 */ .udma_mask = 0, /* 0x7f (udma6-0 disabled for now) */ .port_ops = &mv_ops, @@ -259,6 +260,7 @@ static struct ata_port_info mv_port_info[] = { .sht = &mv_sht, .host_flags = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO | + ATA_FLAG_PIO_POLLING | MV_FLAG_IRQ_COALESCE | MV_FLAG_BDMA), .pio_mask = 0x1f, /* pio4-0 */ .udma_mask = 0, /* 0x7f (udma6-0 disabled for now) */ @@ -268,6 +270,7 @@ static struct ata_port_info mv_port_info[] = { .sht = &mv_sht, .host_flags = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO | + ATA_FLAG_PIO_POLLING | MV_FLAG_IRQ_COALESCE | MV_FLAG_DUAL_HC | MV_FLAG_BDMA), .pio_mask = 0x1f, /* pio4-0 */ diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c index c05653c7779..8b7e871ea0b 100644 --- a/drivers/scsi/sata_nv.c +++ b/drivers/scsi/sata_nv.c @@ -304,11 +304,11 @@ static irqreturn_t nv_interrupt (int irq, void *dev_instance, ap = host_set->ports[i]; if (ap && - !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) { + !(ap->flags & ATA_FLAG_PORT_DISABLED)) { struct ata_queued_cmd *qc; qc = ata_qc_from_tag(ap, ap->active_tag); - if (qc && (!(qc->tf.ctl & ATA_NIEN))) + if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) handled += ata_host_intr(ap, qc); } diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index def7e0d9dac..f67deb0a55c 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c @@ -162,7 +162,8 @@ static struct ata_port_info pdc_port_info[] = { { .sht = &pdc_ata_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_SRST | ATA_FLAG_MMIO, + ATA_FLAG_SRST | ATA_FLAG_MMIO | + ATA_FLAG_PIO_POLLING, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */ @@ -173,7 +174,8 @@ static struct ata_port_info pdc_port_info[] = { { .sht = &pdc_ata_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_SRST | ATA_FLAG_MMIO, + ATA_FLAG_SRST | ATA_FLAG_MMIO | + ATA_FLAG_PIO_POLLING, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */ @@ -184,7 +186,8 @@ static struct ata_port_info pdc_port_info[] = { { .sht = &pdc_ata_sht, .host_flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST | - ATA_FLAG_MMIO | ATA_FLAG_SLAVE_POSS, + ATA_FLAG_MMIO | ATA_FLAG_SLAVE_POSS | + ATA_FLAG_PIO_POLLING, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */ @@ -493,11 +496,11 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *r ap = host_set->ports[i]; tmp = mask & (1 << (i + 1)); if (tmp && ap && - !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) { + !(ap->flags & ATA_FLAG_PORT_DISABLED)) { struct ata_queued_cmd *qc; qc = ata_qc_from_tag(ap, ap->active_tag); - if (qc && (!(qc->tf.ctl & ATA_NIEN))) + if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) handled += pdc_host_intr(ap, qc); } } diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c index ffcdeb68641..a604afafaec 100644 --- a/drivers/scsi/sata_qstor.c +++ b/drivers/scsi/sata_qstor.c @@ -175,7 +175,7 @@ static struct ata_port_info qs_port_info[] = { .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_SATA_RESET | //FIXME ATA_FLAG_SRST | - ATA_FLAG_MMIO, + ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING, .pio_mask = 0x10, /* pio4 */ .udma_mask = 0x7f, /* udma0-6 */ .port_ops = &qs_ata_ops, @@ -389,14 +389,13 @@ static inline unsigned int qs_intr_pkt(struct ata_host_set *host_set) DPRINTK("SFF=%08x%08x: sCHAN=%u sHST=%d sDST=%02x\n", sff1, sff0, port_no, sHST, sDST); handled = 1; - if (ap && !(ap->flags & - (ATA_FLAG_PORT_DISABLED|ATA_FLAG_NOINTR))) { + if (ap && !(ap->flags & ATA_FLAG_PORT_DISABLED)) { struct ata_queued_cmd *qc; struct qs_port_priv *pp = ap->private_data; if (!pp || pp->state != qs_state_pkt) continue; qc = ata_qc_from_tag(ap, ap->active_tag); - if (qc && (!(qc->tf.ctl & ATA_NIEN))) { + if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) { switch (sHST) { case 0: /* sucessful CPB */ case 3: /* device error */ @@ -422,13 +421,13 @@ static inline unsigned int qs_intr_mmio(struct ata_host_set *host_set) struct ata_port *ap; ap = host_set->ports[port_no]; if (ap && - !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) { + !(ap->flags & ATA_FLAG_PORT_DISABLED)) { struct ata_queued_cmd *qc; struct qs_port_priv *pp = ap->private_data; if (!pp || pp->state != qs_state_mmio) continue; qc = ata_qc_from_tag(ap, ap->active_tag); - if (qc && (!(qc->tf.ctl & ATA_NIEN))) { + if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) { /* check main status, clearing INTRQ */ u8 status = ata_chk_status(ap); diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c index 540a8519117..a9f9f7685a5 100644 --- a/drivers/scsi/sata_sx4.c +++ b/drivers/scsi/sata_sx4.c @@ -219,7 +219,8 @@ static struct ata_port_info pdc_port_info[] = { { .sht = &pdc_sata_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_SRST | ATA_FLAG_MMIO, + ATA_FLAG_SRST | ATA_FLAG_MMIO | + ATA_FLAG_PIO_POLLING, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */ @@ -832,11 +833,11 @@ static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_re tmp = mask & (1 << i); VPRINTK("seq %u, port_no %u, ap %p, tmp %x\n", i, port_no, ap, tmp); if (tmp && ap && - !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) { + !(ap->flags & ATA_FLAG_PORT_DISABLED)) { struct ata_queued_cmd *qc; qc = ata_qc_from_tag(ap, ap->active_tag); - if (qc && (!(qc->tf.ctl & ATA_NIEN))) + if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) handled += pdc20621_host_intr(ap, qc, (i > 4), mmio_base); } diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c index cf94e0158a8..92378d768c8 100644 --- a/drivers/scsi/sata_vsc.c +++ b/drivers/scsi/sata_vsc.c @@ -193,12 +193,12 @@ static irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance, struct ata_port *ap; ap = host_set->ports[i]; - if (ap && !(ap->flags & - (ATA_FLAG_PORT_DISABLED|ATA_FLAG_NOINTR))) { + if (ap && + !(ap->flags & ATA_FLAG_PORT_DISABLED)) { struct ata_queued_cmd *qc; qc = ata_qc_from_tag(ap, ap->active_tag); - if (qc && (!(qc->tf.ctl & ATA_NIEN))) + if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) handled += ata_host_intr(ap, qc); } } diff --git a/include/linux/libata.h b/include/linux/libata.h index 9ac2b69df3c..ea8ab29aa92 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -116,6 +116,8 @@ enum { ATA_FLAG_MMIO = (1 << 6), /* use MMIO, not PIO */ ATA_FLAG_SATA_RESET = (1 << 7), /* use COMRESET */ ATA_FLAG_PIO_DMA = (1 << 8), /* PIO cmds via DMA */ + ATA_FLAG_PIO_POLLING = (1 << 9), /* use polling PIO if LLD + * doesn't handle PIO interrupts */ ATA_QCFLAG_ACTIVE = (1 << 1), /* cmd not yet ack'd to scsi lyer */ ATA_QCFLAG_SG = (1 << 3), /* have s/g table? */ -- cgit v1.2.3 From c56b14d2a3e32695e13cd49b417da889da744d1c Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Fri, 30 Sep 2005 19:07:39 +0800 Subject: [PATCH] libata irq-pio: add comments and cleanup Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 12 ------------ include/linux/libata.h | 19 ++++++++++--------- 2 files changed, 10 insertions(+), 21 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index f8a590e59f1..617836a313f 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3430,18 +3430,6 @@ int ata_qc_issue_prot(struct ata_queued_cmd *qc) break; case ATA_PROT_ATAPI: - if (qc->tf.flags & ATA_TFLAG_POLLING) - ata_qc_set_polling(qc); - - ata_tf_to_host_nolock(ap, &qc->tf); - ap->hsm_task_state = HSM_ST_FIRST; - - /* send cdb by polling if no cdb interrupt */ - if ((!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) || - (qc->tf.flags & ATA_TFLAG_POLLING)) - queue_work(ata_wq, &ap->packet_task); - break; - case ATA_PROT_ATAPI_NODATA: if (qc->tf.flags & ATA_TFLAG_POLLING) ata_qc_set_polling(qc); diff --git a/include/linux/libata.h b/include/linux/libata.h index ea8ab29aa92..1fcd0ef9e1c 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -158,15 +158,16 @@ enum { }; enum hsm_task_states { - HSM_ST_UNKNOWN, - HSM_ST_IDLE, - HSM_ST_POLL, - HSM_ST_TMOUT, - HSM_ST, - HSM_ST_LAST, - HSM_ST_LAST_POLL, - HSM_ST_ERR, - HSM_ST_FIRST, + HSM_ST_UNKNOWN, /* state unknown */ + HSM_ST_IDLE, /* no command on going */ + HSM_ST_POLL, /* same as HSM_ST, waits longer */ + HSM_ST_TMOUT, /* timeout */ + HSM_ST, /* (waiting the device to) transfer data */ + HSM_ST_LAST, /* (waiting the device to) complete command */ + HSM_ST_LAST_POLL, /* same as HSM_ST_LAST, waits longer */ + HSM_ST_ERR, /* error */ + HSM_ST_FIRST, /* (waiting the device to) + write CDB or first data block */ }; /* forward declarations */ -- cgit v1.2.3 From f9997be974be40e884e9e8157ded2f2f9aed454c Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Fri, 30 Sep 2005 19:09:31 +0800 Subject: [PATCH] libata irq-pio: rename atapi_packet_task() and comments Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 25 +++++++++++++------------ include/linux/libata.h | 6 +++--- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 617836a313f..a63758da489 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3416,7 +3416,7 @@ int ata_qc_issue_prot(struct ata_queued_cmd *qc) if (qc->tf.flags & ATA_TFLAG_WRITE) { /* PIO data out protocol */ ap->hsm_task_state = HSM_ST_FIRST; - queue_work(ata_wq, &ap->packet_task); + queue_work(ata_wq, &ap->dataout_task); /* send first data block by polling */ } else { @@ -3440,7 +3440,7 @@ int ata_qc_issue_prot(struct ata_queued_cmd *qc) /* send cdb by polling if no cdb interrupt */ if ((!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) || (qc->tf.flags & ATA_TFLAG_POLLING)) - queue_work(ata_wq, &ap->packet_task); + queue_work(ata_wq, &ap->dataout_task); break; case ATA_PROT_ATAPI_DMA: @@ -3452,7 +3452,7 @@ int ata_qc_issue_prot(struct ata_queued_cmd *qc) /* send cdb by polling if no cdb interrupt */ if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) - queue_work(ata_wq, &ap->packet_task); + queue_work(ata_wq, &ap->dataout_task); break; default: @@ -3952,20 +3952,21 @@ irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs) } /** - * atapi_packet_task - Write CDB bytes to hardware - * @_data: Port to which ATAPI device is attached. + * ata_dataout_task - Write first data block to hardware + * @_data: Port to which ATA/ATAPI device is attached. * * When device has indicated its readiness to accept - * a CDB, this function is called. Send the CDB. - * If DMA is to be performed, exit immediately. - * Otherwise, we are in polling mode, so poll - * status under operation succeeds or fails. + * the data, this function sends out the CDB or + * the first data block by PIO. + * After this, + * - If polling, ata_pio_task() handles the rest. + * - Otherwise, interrupt handler takes over. * * LOCKING: * Kernel thread context (may sleep) */ -static void atapi_packet_task(void *_data) +static void ata_dataout_task(void *_data) { struct ata_port *ap = _data; struct ata_queued_cmd *qc; @@ -3978,7 +3979,7 @@ static void atapi_packet_task(void *_data) /* sleep-wait for BSY to clear */ DPRINTK("busy wait\n"); - if (ata_busy_sleep(ap, ATA_TMOUT_CDB_QUICK, ATA_TMOUT_CDB)) + if (ata_busy_sleep(ap, ATA_TMOUT_DATAOUT_QUICK, ATA_TMOUT_DATAOUT)) goto err_out; /* make sure DRQ is set */ @@ -4141,7 +4142,7 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host, ap->active_tag = ATA_TAG_POISON; ap->last_ctl = 0xFF; - INIT_WORK(&ap->packet_task, atapi_packet_task, ap); + INIT_WORK(&ap->dataout_task, ata_dataout_task, ap); INIT_WORK(&ap->pio_task, ata_pio_task, ap); for (i = 0; i < ATA_MAX_DEVICES; i++) diff --git a/include/linux/libata.h b/include/linux/libata.h index 1fcd0ef9e1c..7e6feb97406 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -129,8 +129,8 @@ enum { ATA_TMOUT_PIO = 30 * HZ, ATA_TMOUT_BOOT = 30 * HZ, /* hueristic */ ATA_TMOUT_BOOT_QUICK = 7 * HZ, /* hueristic */ - ATA_TMOUT_CDB = 30 * HZ, - ATA_TMOUT_CDB_QUICK = 5 * HZ, + ATA_TMOUT_DATAOUT = 30 * HZ, + ATA_TMOUT_DATAOUT_QUICK = 5 * HZ, /* ATA bus states */ BUS_UNKNOWN = 0, @@ -319,7 +319,7 @@ struct ata_port { struct ata_host_stats stats; struct ata_host_set *host_set; - struct work_struct packet_task; + struct work_struct dataout_task; struct work_struct pio_task; unsigned int hsm_task_state; -- cgit v1.2.3 From 86a7397cda08a65bc4f306e812c846e2437b5347 Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Fri, 30 Sep 2005 19:11:35 +0800 Subject: [PATCH] libata irq-pio: simplify if condition in ata_dataout_task() - Use if (qc->tf.protocol == ATA_PROT_PIO) instead of if(is_atapi_taskfile()) in ata_dataout_task() Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index a63758da489..cf5a138cdde 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3994,13 +3994,7 @@ static void ata_dataout_task(void *_data) */ spin_lock_irqsave(&ap->host_set->lock, flags); - if (is_atapi_taskfile(&qc->tf)) { - /* send CDB */ - atapi_send_cdb(ap, qc); - - if (qc->tf.flags & ATA_TFLAG_POLLING) - queue_work(ata_wq, &ap->pio_task); - } else { + if (qc->tf.protocol == ATA_PROT_PIO) { /* PIO data out protocol. * send first data block. */ @@ -4013,6 +4007,12 @@ static void ata_dataout_task(void *_data) ata_altstatus(ap); /* flush */ /* interrupt handler takes over from here */ + } else { + /* send CDB */ + atapi_send_cdb(ap, qc); + + if (qc->tf.flags & ATA_TFLAG_POLLING) + queue_work(ata_wq, &ap->pio_task); } spin_unlock_irqrestore(&ap->host_set->lock, flags); -- cgit v1.2.3 From 54f00389563c80fa1de250a21256313ba01ca07d Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Fri, 30 Sep 2005 19:14:19 +0800 Subject: [PATCH] libata irq-pio: cleanup ata_qc_issue_prot() ata_qc_issue_prot(): - cleanup and let the PIO data out case always go through the ata_dataout_task() codepath. (Previously for PIO data out case, 2 code pathes were used - irq case goes through ata_data_out_task() codepath. - polling case jumps over the HSM_ST_FIRST state and goes to HSM_ST and ata_pio_task() directly.) ata_dataout_task(): - rearrange the queue_work() code to handle the PIO data out + polling case. Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index cf5a138cdde..02a7a9eb464 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3407,24 +3407,24 @@ int ata_qc_issue_prot(struct ata_queued_cmd *qc) ata_tf_to_host_nolock(ap, &qc->tf); - if (qc->tf.flags & ATA_TFLAG_POLLING) { - /* polling PIO */ - ap->hsm_task_state = HSM_ST; - queue_work(ata_wq, &ap->pio_task); + if (qc->tf.flags & ATA_TFLAG_WRITE) { + /* PIO data out protocol */ + ap->hsm_task_state = HSM_ST_FIRST; + queue_work(ata_wq, &ap->dataout_task); + + /* always send first data block using + * the ata_dataout_task() codepath. + */ } else { - /* interrupt driven PIO */ - if (qc->tf.flags & ATA_TFLAG_WRITE) { - /* PIO data out protocol */ - ap->hsm_task_state = HSM_ST_FIRST; - queue_work(ata_wq, &ap->dataout_task); - - /* send first data block by polling */ - } else { - /* PIO data in protocol */ - ap->hsm_task_state = HSM_ST; - - /* interrupt handler takes over from here */ - } + /* PIO data in protocol */ + ap->hsm_task_state = HSM_ST; + + if (qc->tf.flags & ATA_TFLAG_POLLING) + queue_work(ata_wq, &ap->pio_task); + + /* if polling, ata_pio_task() handles the rest. + * otherwise, interrupt handler takes over from here. + */ } break; @@ -4005,15 +4005,15 @@ static void ata_dataout_task(void *_data) ap->hsm_task_state = HSM_ST; ata_pio_sector(qc); ata_altstatus(ap); /* flush */ - - /* interrupt handler takes over from here */ - } else { + } else /* send CDB */ atapi_send_cdb(ap, qc); - if (qc->tf.flags & ATA_TFLAG_POLLING) - queue_work(ata_wq, &ap->pio_task); - } + /* if polling, ata_pio_task() handles the rest. + * otherwise, interrupt handler takes over from here. + */ + if (qc->tf.flags & ATA_TFLAG_POLLING) + queue_work(ata_wq, &ap->pio_task); spin_unlock_irqrestore(&ap->host_set->lock, flags); -- cgit v1.2.3 From c71c18576d0d8aa4db876c737c3c597c724cf02f Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Tue, 4 Oct 2005 06:03:45 -0400 Subject: libata: move atapi_send_cdb() and ata_dataout_task() to be near ata_pio_*() functions --- drivers/scsi/libata-core.c | 217 ++++++++++++++++++++++----------------------- 1 file changed, 108 insertions(+), 109 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 54633680257..ff291b36510 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2781,6 +2781,114 @@ static void ata_pio_sector(struct ata_queued_cmd *qc) local_irq_restore(flags); } +/** + * atapi_send_cdb - Write CDB bytes to hardware + * @ap: Port to which ATAPI device is attached. + * @qc: Taskfile currently active + * + * When device has indicated its readiness to accept + * a CDB, this function is called. Send the CDB. + * + * LOCKING: + * caller. + */ + +static void atapi_send_cdb(struct ata_port *ap, struct ata_queued_cmd *qc) +{ + /* send SCSI cdb */ + DPRINTK("send cdb\n"); + assert(ap->cdb_len >= 12); + + ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1); + ata_altstatus(ap); /* flush */ + + switch (qc->tf.protocol) { + case ATA_PROT_ATAPI: + ap->hsm_task_state = HSM_ST; + break; + case ATA_PROT_ATAPI_NODATA: + ap->hsm_task_state = HSM_ST_LAST; + break; + case ATA_PROT_ATAPI_DMA: + ap->hsm_task_state = HSM_ST_LAST; + /* initiate bmdma */ + ap->ops->bmdma_start(qc); + break; + } +} + +/** + * ata_dataout_task - Write first data block to hardware + * @_data: Port to which ATA/ATAPI device is attached. + * + * When device has indicated its readiness to accept + * the data, this function sends out the CDB or + * the first data block by PIO. + * After this, + * - If polling, ata_pio_task() handles the rest. + * - Otherwise, interrupt handler takes over. + * + * LOCKING: + * Kernel thread context (may sleep) + */ + +static void ata_dataout_task(void *_data) +{ + struct ata_port *ap = _data; + struct ata_queued_cmd *qc; + u8 status; + unsigned long flags; + + qc = ata_qc_from_tag(ap, ap->active_tag); + assert(qc != NULL); + assert(qc->flags & ATA_QCFLAG_ACTIVE); + + /* sleep-wait for BSY to clear */ + DPRINTK("busy wait\n"); + if (ata_busy_sleep(ap, ATA_TMOUT_DATAOUT_QUICK, ATA_TMOUT_DATAOUT)) + goto err_out; + + /* make sure DRQ is set */ + status = ata_chk_status(ap); + if ((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ) + goto err_out; + + /* Send the CDB (atapi) or the first data block (ata pio out). + * During the state transition, interrupt handler shouldn't + * be invoked before the data transfer is complete and + * hsm_task_state is changed. Hence, the following locking. + */ + spin_lock_irqsave(&ap->host_set->lock, flags); + + if (qc->tf.protocol == ATA_PROT_PIO) { + /* PIO data out protocol. + * send first data block. + */ + + /* ata_pio_sector() might change the state to HSM_ST_LAST. + * so, the state is changed here before ata_pio_sector(). + */ + ap->hsm_task_state = HSM_ST; + ata_pio_sector(qc); + ata_altstatus(ap); /* flush */ + } else + /* send CDB */ + atapi_send_cdb(ap, qc); + + /* if polling, ata_pio_task() handles the rest. + * otherwise, interrupt handler takes over from here. + */ + if (qc->tf.flags & ATA_TFLAG_POLLING) + queue_work(ata_wq, &ap->pio_task); + + spin_unlock_irqrestore(&ap->host_set->lock, flags); + + return; + +err_out: + ata_pio_error(ap); +} + /** * __atapi_pio_bytes - Transfer data from/to the ATAPI device. * @qc: Command on going @@ -3784,42 +3892,6 @@ void ata_bmdma_stop(struct ata_queued_cmd *qc) ata_altstatus(ap); /* dummy read */ } -/** - * atapi_send_cdb - Write CDB bytes to hardware - * @ap: Port to which ATAPI device is attached. - * @qc: Taskfile currently active - * - * When device has indicated its readiness to accept - * a CDB, this function is called. Send the CDB. - * - * LOCKING: - * caller. - */ - -static void atapi_send_cdb(struct ata_port *ap, struct ata_queued_cmd *qc) -{ - /* send SCSI cdb */ - DPRINTK("send cdb\n"); - assert(ap->cdb_len >= 12); - - ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1); - ata_altstatus(ap); /* flush */ - - switch (qc->tf.protocol) { - case ATA_PROT_ATAPI: - ap->hsm_task_state = HSM_ST; - break; - case ATA_PROT_ATAPI_NODATA: - ap->hsm_task_state = HSM_ST_LAST; - break; - case ATA_PROT_ATAPI_DMA: - ap->hsm_task_state = HSM_ST_LAST; - /* initiate bmdma */ - ap->ops->bmdma_start(qc); - break; - } -} - /** * ata_host_intr - Handle host interrupt for given (port, task) * @ap: Port on which interrupt arrived (possibly...) @@ -4041,79 +4113,6 @@ irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs) return IRQ_RETVAL(handled); } -/** - * ata_dataout_task - Write first data block to hardware - * @_data: Port to which ATA/ATAPI device is attached. - * - * When device has indicated its readiness to accept - * the data, this function sends out the CDB or - * the first data block by PIO. - * After this, - * - If polling, ata_pio_task() handles the rest. - * - Otherwise, interrupt handler takes over. - * - * LOCKING: - * Kernel thread context (may sleep) - */ - -static void ata_dataout_task(void *_data) -{ - struct ata_port *ap = _data; - struct ata_queued_cmd *qc; - u8 status; - unsigned long flags; - - qc = ata_qc_from_tag(ap, ap->active_tag); - assert(qc != NULL); - assert(qc->flags & ATA_QCFLAG_ACTIVE); - - /* sleep-wait for BSY to clear */ - DPRINTK("busy wait\n"); - if (ata_busy_sleep(ap, ATA_TMOUT_DATAOUT_QUICK, ATA_TMOUT_DATAOUT)) - goto err_out; - - /* make sure DRQ is set */ - status = ata_chk_status(ap); - if ((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ) - goto err_out; - - /* Send the CDB (atapi) or the first data block (ata pio out). - * During the state transition, interrupt handler shouldn't - * be invoked before the data transfer is complete and - * hsm_task_state is changed. Hence, the following locking. - */ - spin_lock_irqsave(&ap->host_set->lock, flags); - - if (qc->tf.protocol == ATA_PROT_PIO) { - /* PIO data out protocol. - * send first data block. - */ - - /* ata_pio_sector() might change the state to HSM_ST_LAST. - * so, the state is changed here before ata_pio_sector(). - */ - ap->hsm_task_state = HSM_ST; - ata_pio_sector(qc); - ata_altstatus(ap); /* flush */ - } else - /* send CDB */ - atapi_send_cdb(ap, qc); - - /* if polling, ata_pio_task() handles the rest. - * otherwise, interrupt handler takes over from here. - */ - if (qc->tf.flags & ATA_TFLAG_POLLING) - queue_work(ata_wq, &ap->pio_task); - - spin_unlock_irqrestore(&ap->host_set->lock, flags); - - return; - -err_out: - ata_pio_error(ap); -} - - /** * ata_port_start - Set port up for dma. * @ap: Port to initialize -- cgit v1.2.3 From 7282aa4b49d08254ff1dcefdf3a2fb01b02ebbe2 Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Sun, 9 Oct 2005 09:46:07 -0400 Subject: [libata irq-pio] reorganize ata_pio_sector() and __atapi_pio_bytes() - move some code out of the kmap_atomic() / kunmap_atomic() zone - remove the redundant "do_write = (qc->tf.flags & ATA_TFLAG_WRITE);" Signed-off-by: Albert Lee --- drivers/scsi/libata-core.c | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 2c9275e30cb..f8931265479 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2763,22 +2763,21 @@ static void ata_pio_sector(struct ata_queued_cmd *qc) local_irq_save(flags); buf = kmap_atomic(page, KM_IRQ0) + offset; - qc->cursect++; - qc->cursg_ofs++; - - if ((qc->cursg_ofs * ATA_SECT_SIZE) == (&sg[qc->cursg])->length) { - qc->cursg++; - qc->cursg_ofs = 0; - } - DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read"); /* do the actual data transfer */ - do_write = (qc->tf.flags & ATA_TFLAG_WRITE); ata_data_xfer(ap, buf, ATA_SECT_SIZE, do_write); kunmap_atomic(buf - offset, KM_IRQ0); local_irq_restore(flags); + + qc->cursect++; + qc->cursg_ofs++; + + if ((qc->cursg_ofs * ATA_SECT_SIZE) == (&sg[qc->cursg])->length) { + qc->cursg++; + qc->cursg_ofs = 0; + } } /** @@ -2956,6 +2955,14 @@ next_sg: local_irq_save(flags); buf = kmap_atomic(page, KM_IRQ0) + offset; + DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read"); + + /* do the actual data transfer */ + ata_data_xfer(ap, buf, count, do_write); + + kunmap_atomic(buf - offset, KM_IRQ0); + local_irq_restore(flags); + bytes -= count; qc->curbytes += count; qc->cursg_ofs += count; @@ -2965,14 +2972,6 @@ next_sg: qc->cursg_ofs = 0; } - DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read"); - - /* do the actual data transfer */ - ata_data_xfer(ap, buf, count, do_write); - - kunmap_atomic(buf - offset, KM_IRQ0); - local_irq_restore(flags); - if (bytes) goto next_sg; } -- cgit v1.2.3 From 083958d313f886dc7d00522f2972f90f55c40041 Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Sun, 9 Oct 2005 09:47:31 -0400 Subject: [libata irq-pio] reorganize "buf + offset" in ata_pio_sector() and __atapi_pio_bytes() - relocate DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read"); - buf + offset, buf - offset tidy up Signed-off-by: Albert Lee --- drivers/scsi/libata-core.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index f8931265479..35ee35e176c 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2760,15 +2760,15 @@ static void ata_pio_sector(struct ata_queued_cmd *qc) page = nth_page(page, (offset >> PAGE_SHIFT)); offset %= PAGE_SIZE; - local_irq_save(flags); - buf = kmap_atomic(page, KM_IRQ0) + offset; - DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read"); + local_irq_save(flags); + buf = kmap_atomic(page, KM_IRQ0); + /* do the actual data transfer */ - ata_data_xfer(ap, buf, ATA_SECT_SIZE, do_write); + ata_data_xfer(ap, buf + offset, ATA_SECT_SIZE, do_write); - kunmap_atomic(buf - offset, KM_IRQ0); + kunmap_atomic(buf, KM_IRQ0); local_irq_restore(flags); qc->cursect++; @@ -2952,15 +2952,15 @@ next_sg: /* don't cross page boundaries */ count = min(count, (unsigned int)PAGE_SIZE - offset); - local_irq_save(flags); - buf = kmap_atomic(page, KM_IRQ0) + offset; - DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read"); + local_irq_save(flags); + buf = kmap_atomic(page, KM_IRQ0); + /* do the actual data transfer */ - ata_data_xfer(ap, buf, count, do_write); + ata_data_xfer(ap, buf + offset, count, do_write); - kunmap_atomic(buf - offset, KM_IRQ0); + kunmap_atomic(buf, KM_IRQ0); local_irq_restore(flags); bytes -= count; -- cgit v1.2.3 From 91b8b3132e1870bfe3c4d3a999f13f20fc4e9726 Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Sun, 9 Oct 2005 09:48:44 -0400 Subject: [libata irq-pio] use PageHighMem() to optimize the kmap_atomic() usage as done in ide-scsi.c Signed-off-by: Albert Lee --- drivers/scsi/libata-core.c | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 35ee35e176c..5e750c33dd9 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2748,7 +2748,6 @@ static void ata_pio_sector(struct ata_queued_cmd *qc) struct page *page; unsigned int offset; unsigned char *buf; - unsigned long flags; if (qc->cursect == (qc->nsect - 1)) ap->hsm_task_state = HSM_ST_LAST; @@ -2762,14 +2761,21 @@ static void ata_pio_sector(struct ata_queued_cmd *qc) DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read"); - local_irq_save(flags); - buf = kmap_atomic(page, KM_IRQ0); + if (PageHighMem(page)) { + unsigned long flags; + + local_irq_save(flags); + buf = kmap_atomic(page, KM_IRQ0); - /* do the actual data transfer */ - ata_data_xfer(ap, buf + offset, ATA_SECT_SIZE, do_write); + /* do the actual data transfer */ + ata_data_xfer(ap, buf + offset, ATA_SECT_SIZE, do_write); - kunmap_atomic(buf, KM_IRQ0); - local_irq_restore(flags); + kunmap_atomic(buf, KM_IRQ0); + local_irq_restore(flags); + } else { + buf = page_address(page); + ata_data_xfer(ap, buf + offset, ATA_SECT_SIZE, do_write); + } qc->cursect++; qc->cursg_ofs++; @@ -2908,7 +2914,6 @@ static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes) struct page *page; unsigned char *buf; unsigned int offset, count; - unsigned long flags; if (qc->curbytes + bytes >= qc->nbytes) ap->hsm_task_state = HSM_ST_LAST; @@ -2954,14 +2959,21 @@ next_sg: DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read"); - local_irq_save(flags); - buf = kmap_atomic(page, KM_IRQ0); + if (PageHighMem(page)) { + unsigned long flags; + + local_irq_save(flags); + buf = kmap_atomic(page, KM_IRQ0); - /* do the actual data transfer */ - ata_data_xfer(ap, buf + offset, count, do_write); + /* do the actual data transfer */ + ata_data_xfer(ap, buf + offset, count, do_write); - kunmap_atomic(buf, KM_IRQ0); - local_irq_restore(flags); + kunmap_atomic(buf, KM_IRQ0); + local_irq_restore(flags); + } else { + buf = page_address(page); + ata_data_xfer(ap, buf + offset, count, do_write); + } bytes -= count; qc->curbytes += count; -- cgit v1.2.3 From e33b9dfa3008fcaa908dc0c8c472a812c400f839 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Sun, 9 Oct 2005 09:51:46 -0400 Subject: [libata irq-pio] build fix --- drivers/scsi/libata-core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 5e750c33dd9..9eb24d3f18d 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -72,6 +72,7 @@ static int ata_choose_xfer_mode(struct ata_port *ap, u8 *xfer_mode_out, unsigned int *xfer_shift_out); static void __ata_qc_complete(struct ata_queued_cmd *qc); +static void ata_pio_error(struct ata_port *ap); static unsigned int ata_unique_id = 1; static struct workqueue_struct *ata_wq; -- cgit v1.2.3 From be697c3f137c9ed808753bbbc5d7751c6e5303fc Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Tue, 18 Oct 2005 21:27:34 -0400 Subject: [libata pdc_adma] update for removal of ATA_FLAG_NOINTR --- drivers/scsi/pdc_adma.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c index 53b8db4be1a..f3ba6b447e8 100644 --- a/drivers/scsi/pdc_adma.c +++ b/drivers/scsi/pdc_adma.c @@ -481,13 +481,13 @@ static inline unsigned int adma_intr_mmio(struct ata_host_set *host_set) for (port_no = 0; port_no < host_set->n_ports; ++port_no) { struct ata_port *ap; ap = host_set->ports[port_no]; - if (ap && (!(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR)))) { + if (ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) { struct ata_queued_cmd *qc; struct adma_port_priv *pp = ap->private_data; if (!pp || pp->state != adma_state_mmio) continue; qc = ata_qc_from_tag(ap, ap->active_tag); - if (qc && (!(qc->tf.ctl & ATA_NIEN))) { + if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) { /* check main status, clearing INTRQ */ u8 status = ata_chk_status(ap); -- cgit v1.2.3 From 94ec1ef1cf29e137e5c79372e432b040c6604be6 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Sun, 30 Oct 2005 02:15:08 -0500 Subject: [libata pdc_adma] fix for new irq-driven PIO code --- drivers/scsi/pdc_adma.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c index 309b205820a..6a9d0dc085c 100644 --- a/drivers/scsi/pdc_adma.c +++ b/drivers/scsi/pdc_adma.c @@ -457,13 +457,13 @@ static inline unsigned int adma_intr_pkt(struct ata_host_set *host_set) continue; handled = 1; adma_enter_reg_mode(ap); - if (ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR)) + if (ap->flags & ATA_FLAG_PORT_DISABLED) continue; pp = ap->private_data; if (!pp || pp->state != adma_state_pkt) continue; qc = ata_qc_from_tag(ap, ap->active_tag); - if (qc && (!(qc->tf.ctl & ATA_NIEN))) { + if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) { if ((status & (aPERR | aPSD | aUIRQ))) drv_stat = ATA_ERR; else if (pp->pkt[0] != cDONE) -- cgit v1.2.3 From 467b16d4bebe8d251ca974eaa5da50b315206e9d Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Tue, 1 Nov 2005 19:19:01 +0800 Subject: [PATCH] libata irq-pio: misc fixes - ata_pio_block(): add ata_altstatus(ap) to prevent reading device status before it is valid - remove the unnecessary HSM_ST_IDLE state from ata_pio_task() - raise BUG() when unknown state is found in ata_pio_task() Signed-off-by: Albert Lee ============ Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index ce18de9705c..15736e3313f 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3317,6 +3317,8 @@ static void ata_pio_block(struct ata_port *ap) ata_pio_sector(qc); } + + ata_altstatus(ap); /* flush */ } static void ata_pio_error(struct ata_port *ap) @@ -3344,9 +3346,6 @@ fsm_start: qc_completed = 0; switch (ap->hsm_task_state) { - case HSM_ST_IDLE: - return; - case HSM_ST: ata_pio_block(ap); break; @@ -3364,6 +3363,10 @@ fsm_start: case HSM_ST_ERR: ata_pio_error(ap); return; + + default: + BUG(); + return; } if (timeout) -- cgit v1.2.3 From e27486db89ef04d5df1727c52362fa3d50cff241 Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Tue, 1 Nov 2005 19:24:49 +0800 Subject: [PATCH] libata irq-pio: merge the ata_dataout_task workqueue with ata_pio_task workqueue - remove ap->dataout_task from struct ata_port - let ata_pio_task() handle the HSM_ST_FIRST state. - rename ata_dataout_task() to ata_pio_first_block() - replace the ata_dataout_task workqueue with ata_pio_task workqueue Signed-off-by: Albert Lee ======== Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 20 +++++++++++--------- include/linux/libata.h | 2 -- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 15736e3313f..96b8bbaa763 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3056,8 +3056,8 @@ static void atapi_send_cdb(struct ata_port *ap, struct ata_queued_cmd *qc) } /** - * ata_dataout_task - Write first data block to hardware - * @_data: Port to which ATA/ATAPI device is attached. + * ata_pio_first_block - Write first data block to hardware + * @ap: Port to which ATA/ATAPI device is attached. * * When device has indicated its readiness to accept * the data, this function sends out the CDB or @@ -3070,9 +3070,8 @@ static void atapi_send_cdb(struct ata_port *ap, struct ata_queued_cmd *qc) * Kernel thread context (may sleep) */ -static void ata_dataout_task(void *_data) +static void ata_pio_first_block(struct ata_port *ap) { - struct ata_port *ap = _data; struct ata_queued_cmd *qc; u8 status; unsigned long flags; @@ -3346,6 +3345,10 @@ fsm_start: qc_completed = 0; switch (ap->hsm_task_state) { + case HSM_ST_FIRST: + ata_pio_first_block(ap); + return; + case HSM_ST: ata_pio_block(ap); break; @@ -3796,10 +3799,10 @@ int ata_qc_issue_prot(struct ata_queued_cmd *qc) if (qc->tf.flags & ATA_TFLAG_WRITE) { /* PIO data out protocol */ ap->hsm_task_state = HSM_ST_FIRST; - queue_work(ata_wq, &ap->dataout_task); + queue_work(ata_wq, &ap->pio_task); /* always send first data block using - * the ata_dataout_task() codepath. + * the ata_pio_task() codepath. */ } else { /* PIO data in protocol */ @@ -3826,7 +3829,7 @@ int ata_qc_issue_prot(struct ata_queued_cmd *qc) /* send cdb by polling if no cdb interrupt */ if ((!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) || (qc->tf.flags & ATA_TFLAG_POLLING)) - queue_work(ata_wq, &ap->dataout_task); + queue_work(ata_wq, &ap->pio_task); break; case ATA_PROT_ATAPI_DMA: @@ -3838,7 +3841,7 @@ int ata_qc_issue_prot(struct ata_queued_cmd *qc) /* send cdb by polling if no cdb interrupt */ if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) - queue_work(ata_wq, &ap->dataout_task); + queue_work(ata_wq, &ap->pio_task); break; default: @@ -4426,7 +4429,6 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host, ap->active_tag = ATA_TAG_POISON; ap->last_ctl = 0xFF; - INIT_WORK(&ap->dataout_task, ata_dataout_task, ap); INIT_WORK(&ap->pio_task, ata_pio_task, ap); for (i = 0; i < ATA_MAX_DEVICES; i++) diff --git a/include/linux/libata.h b/include/linux/libata.h index ad0451dfee1..70ae140dbf2 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -346,8 +346,6 @@ struct ata_port { struct ata_host_stats stats; struct ata_host_set *host_set; - struct work_struct dataout_task; - struct work_struct pio_task; unsigned int hsm_task_state; unsigned long pio_task_timeout; -- cgit v1.2.3 From fbcdd80b0d5bde06f3483b9a13f9599a0452431c Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Tue, 1 Nov 2005 19:30:05 +0800 Subject: [PATCH] libata irq-pio: eliminate unnecessary queuing in ata_pio_first_block() - change the return value of ata_pio_complete() 0 <-> 1 - add return value for ata_pio_first_block() - rename variable "qc_completed" to "has_next" in ata_pio_task() - use has_next to eliminate unnecessary queuing in ata_pio_first_block() Signed-off-by: Albert Lee ========== Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 53 +++++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 96b8bbaa763..2e0e6cca327 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2790,7 +2790,8 @@ static unsigned long ata_pio_poll(struct ata_port *ap) * None. (executing in kernel thread context) * * RETURNS: - * Non-zero if qc completed, zero otherwise. + * Zero if qc completed. + * Non-zero if has next. */ static int ata_pio_complete (struct ata_port *ap) @@ -2812,14 +2813,14 @@ static int ata_pio_complete (struct ata_port *ap) if (drv_stat & (ATA_BUSY | ATA_DRQ)) { ap->hsm_task_state = HSM_ST_LAST_POLL; ap->pio_task_timeout = jiffies + ATA_TMOUT_PIO; - return 0; + return 1; } } drv_stat = ata_wait_idle(ap); if (!ata_ok(drv_stat)) { ap->hsm_task_state = HSM_ST_ERR; - return 0; + return 1; } qc = ata_qc_from_tag(ap, ap->active_tag); @@ -2831,7 +2832,7 @@ static int ata_pio_complete (struct ata_port *ap) /* another command may start at this point */ - return 1; + return 0; } @@ -3068,27 +3069,42 @@ static void atapi_send_cdb(struct ata_port *ap, struct ata_queued_cmd *qc) * * LOCKING: * Kernel thread context (may sleep) + * + * RETURNS: + * Zero if irq handler takes over + * Non-zero if has next (polling). */ -static void ata_pio_first_block(struct ata_port *ap) +static int ata_pio_first_block(struct ata_port *ap) { struct ata_queued_cmd *qc; u8 status; unsigned long flags; + int has_next; qc = ata_qc_from_tag(ap, ap->active_tag); assert(qc != NULL); assert(qc->flags & ATA_QCFLAG_ACTIVE); + /* if polling, we will stay in the work queue after sending the data. + * otherwise, interrupt handler takes over after sending the data. + */ + has_next = (qc->tf.flags & ATA_TFLAG_POLLING); + /* sleep-wait for BSY to clear */ DPRINTK("busy wait\n"); - if (ata_busy_sleep(ap, ATA_TMOUT_DATAOUT_QUICK, ATA_TMOUT_DATAOUT)) + if (ata_busy_sleep(ap, ATA_TMOUT_DATAOUT_QUICK, ATA_TMOUT_DATAOUT)) { + ap->hsm_task_state = HSM_ST_TMOUT; goto err_out; + } /* make sure DRQ is set */ status = ata_chk_status(ap); - if ((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ) + if ((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ) { + /* device status error */ + ap->hsm_task_state = HSM_ST_ERR; goto err_out; + } /* Send the CDB (atapi) or the first data block (ata pio out). * During the state transition, interrupt handler shouldn't @@ -3112,18 +3128,15 @@ static void ata_pio_first_block(struct ata_port *ap) /* send CDB */ atapi_send_cdb(ap, qc); + spin_unlock_irqrestore(&ap->host_set->lock, flags); + /* if polling, ata_pio_task() handles the rest. * otherwise, interrupt handler takes over from here. */ - if (qc->tf.flags & ATA_TFLAG_POLLING) - queue_work(ata_wq, &ap->pio_task); - - spin_unlock_irqrestore(&ap->host_set->lock, flags); - - return; + return has_next; err_out: - ata_pio_error(ap); + return 1; /* has next */ } /** @@ -3338,23 +3351,23 @@ static void ata_pio_task(void *_data) { struct ata_port *ap = _data; unsigned long timeout; - int qc_completed; + int has_next; fsm_start: timeout = 0; - qc_completed = 0; + has_next = 1; switch (ap->hsm_task_state) { case HSM_ST_FIRST: - ata_pio_first_block(ap); - return; + has_next = ata_pio_first_block(ap); + break; case HSM_ST: ata_pio_block(ap); break; case HSM_ST_LAST: - qc_completed = ata_pio_complete(ap); + has_next = ata_pio_complete(ap); break; case HSM_ST_POLL: @@ -3374,7 +3387,7 @@ fsm_start: if (timeout) queue_delayed_work(ata_wq, &ap->pio_task, timeout); - else if (!qc_completed) + else if (has_next) goto fsm_start; } -- cgit v1.2.3 From 07f6f7d074e68d56d82e7cc5c65096033ac8dc56 Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Tue, 1 Nov 2005 19:33:20 +0800 Subject: [PATCH] libata irq-pio: add read/write multiple support - add is_multi_taskfile() to ata.h - initialize ata_device->multi_count with device identify data - use ata_pio_sectors() to support r/w multiple commands Signed-off-by: Albert Lee ======== Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 44 ++++++++++++++++++++++++++++++++++++++------ include/linux/ata.h | 8 ++++++++ 2 files changed, 46 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 2e0e6cca327..59a4a26bc13 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1261,6 +1261,12 @@ retry: } + if (dev->id[59] & 0x100) { + dev->multi_count = dev->id[59] & 0xff; + DPRINTK("ata%u: dev %u multi count %u\n", + ap->id, device, dev->multi_count); + } + ap->host->max_cmd_len = 16; } @@ -2804,7 +2810,7 @@ static int ata_pio_complete (struct ata_port *ap) * we enter, BSY will be cleared in a chk-status or two. If not, * the drive is probably seeking or something. Snooze for a couple * msecs, then chk-status again. If still busy, fall back to - * HSM_ST_POLL state. + * HSM_ST_LAST_POLL state. */ drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 10); if (drv_stat & (ATA_BUSY | ATA_DRQ)) { @@ -3020,6 +3026,32 @@ static void ata_pio_sector(struct ata_queued_cmd *qc) } } +/** + * ata_pio_sectors - Transfer one or many 512-byte sectors. + * @qc: Command on going + * + * Transfer one or many ATA_SECT_SIZE of data from/to the + * ATA device for the DRQ request. + * + * LOCKING: + * Inherited from caller. + */ + +static void ata_pio_sectors(struct ata_queued_cmd *qc) +{ + if (is_multi_taskfile(&qc->tf)) { + /* READ/WRITE MULTIPLE */ + unsigned int nsect; + + assert(qc->dev->multi_count); + + nsect = min(qc->nsect - qc->cursect, qc->dev->multi_count); + while (nsect--) + ata_pio_sector(qc); + } else + ata_pio_sector(qc); +} + /** * atapi_send_cdb - Write CDB bytes to hardware * @ap: Port to which ATAPI device is attached. @@ -3118,11 +3150,11 @@ static int ata_pio_first_block(struct ata_port *ap) * send first data block. */ - /* ata_pio_sector() might change the state to HSM_ST_LAST. - * so, the state is changed here before ata_pio_sector(). + /* ata_pio_sectors() might change the state to HSM_ST_LAST. + * so, the state is changed here before ata_pio_sectors(). */ ap->hsm_task_state = HSM_ST; - ata_pio_sector(qc); + ata_pio_sectors(qc); ata_altstatus(ap); /* flush */ } else /* send CDB */ @@ -3327,7 +3359,7 @@ static void ata_pio_block(struct ata_port *ap) return; } - ata_pio_sector(qc); + ata_pio_sectors(qc); } ata_altstatus(ap); /* flush */ @@ -4213,7 +4245,7 @@ fsm_start: goto fsm_start; } - ata_pio_sector(qc); + ata_pio_sectors(qc); if (ap->hsm_task_state == HSM_ST_LAST && (!(qc->tf.flags & ATA_TFLAG_WRITE))) { diff --git a/include/linux/ata.h b/include/linux/ata.h index d54da3306d2..f512104a1a3 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -293,6 +293,14 @@ static inline int is_atapi_taskfile(const struct ata_taskfile *tf) (tf->protocol == ATA_PROT_ATAPI_DMA); } +static inline int is_multi_taskfile(struct ata_taskfile *tf) +{ + return (tf->command == ATA_CMD_READ_MULTI) || + (tf->command == ATA_CMD_WRITE_MULTI) || + (tf->command == ATA_CMD_READ_MULTI_EXT) || + (tf->command == ATA_CMD_WRITE_MULTI_EXT); +} + static inline int ata_ok(u8 status) { return ((status & (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ | ATA_ERR)) -- cgit v1.2.3 From d67e7ebb2a15bf0429c55f2fc1c4b02808367874 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Fri, 18 Nov 2005 11:55:00 -0500 Subject: [libata sata_mv] IRQ PIO build fix --- drivers/scsi/sata_mv.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index 9687646d73e..6dc2a612ccb 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -1220,8 +1220,7 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant, handled++; } - if (ap && - (ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) + if (ap && (ap->flags & ATA_FLAG_PORT_DISABLED)) continue; err_mask = ac_err_mask(ata_status); @@ -1242,7 +1241,7 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant, VPRINTK("port %u IRQ found for qc, " "ata_status 0x%x\n", port,ata_status); /* mark qc status appropriately */ - if (!(qc->tf.ctl & ATA_NIEN)) + if (!(qc->tf.flags & ATA_TFLAG_POLLING)) ata_qc_complete(qc, err_mask); } } -- cgit v1.2.3 From 278efe950988e72e2d0cea35059438fc27035d13 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Tue, 6 Dec 2005 05:01:27 -0500 Subject: [libata] irq-pio: fix breakage related to err_mask merge --- drivers/scsi/libata-core.c | 3 ++- drivers/scsi/sata_mv.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 82f566cf75c..657537f96c3 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -4336,7 +4336,8 @@ fsm_start: ap->id, status, host_stat); ap->hsm_task_state = HSM_ST_IDLE; - ata_qc_complete(qc, status | ATA_ERR); + qc->err_mask |= __ac_err_mask(status); + ata_qc_complete(qc); break; default: goto idle_irq; diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index ef148acb5ee..17044168ebf 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -1244,7 +1244,7 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant, /* mark qc status appropriately */ if (!(qc->tf.flags & ATA_TFLAG_POLLING)) { qc->err_mask |= err_mask; - ata_qc_complete(qc, err_mask); + ata_qc_complete(qc); } } } -- cgit v1.2.3 From 3d0a59c02303df01848537b3bf938dc11e9a0ded Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Tue, 13 Dec 2005 22:28:19 -0500 Subject: [libata sata_promise] irq_pio: fix merge bug --- drivers/scsi/sata_promise.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index b4cbc9d6be1..e35838043b5 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c @@ -70,6 +70,10 @@ enum { PDC_HAS_PATA = (1 << 1), /* PDC20375 has PATA */ PDC_RESET = (1 << 11), /* HDMA reset */ + + PDC_COMMON_FLAGS = ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST | + ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI | + ATA_FLAG_PIO_POLLING, }; @@ -162,9 +166,7 @@ static const struct ata_port_info pdc_port_info[] = { /* board_2037x */ { .sht = &pdc_ata_sht, - .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_SRST | ATA_FLAG_MMIO | - ATA_FLAG_PIO_POLLING, + .host_flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */ @@ -174,9 +176,7 @@ static const struct ata_port_info pdc_port_info[] = { /* board_20319 */ { .sht = &pdc_ata_sht, - .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_SRST | ATA_FLAG_MMIO | - ATA_FLAG_PIO_POLLING, + .host_flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */ @@ -186,9 +186,7 @@ static const struct ata_port_info pdc_port_info[] = { /* board_20619 */ { .sht = &pdc_ata_sht, - .host_flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST | - ATA_FLAG_MMIO | ATA_FLAG_SLAVE_POSS | - ATA_FLAG_PIO_POLLING, + .host_flags = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */ -- cgit v1.2.3 From a4f16610081001640ffe0314024bc31c10f69757 Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Mon, 26 Dec 2005 16:40:53 +0800 Subject: [PATCH] libata-dev: determine err_mask when error is found Changes: - Determine err_mask directly when an error is found. - Remove "qc->err_mask |= __ac_err_mask(status);" in ata_host_intr() Signed-off-by: Albert Lee ============ Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 4a61061d0bd..41f76b9bf99 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3265,6 +3265,7 @@ static int ata_pio_first_block(struct ata_port *ap) /* sleep-wait for BSY to clear */ DPRINTK("busy wait\n"); if (ata_busy_sleep(ap, ATA_TMOUT_DATAOUT_QUICK, ATA_TMOUT_DATAOUT)) { + qc->err_mask |= AC_ERR_ATA_BUS; ap->hsm_task_state = HSM_ST_TMOUT; goto err_out; } @@ -3273,6 +3274,7 @@ static int ata_pio_first_block(struct ata_port *ap) status = ata_chk_status(ap); if ((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ) { /* device status error */ + qc->err_mask |= AC_ERR_ATA_BUS; ap->hsm_task_state = HSM_ST_ERR; goto err_out; } @@ -4288,6 +4290,12 @@ inline unsigned int ata_host_intr (struct ata_port *ap, /* before we do anything else, clear DMA-Start bit */ ap->ops->bmdma_stop(qc); + + if (unlikely(host_stat & ATA_DMA_ERR)) { + /* error when transfering data to/from memory */ + qc->err_mask |= AC_ERR_HOST_BUS; + ap->hsm_task_state = HSM_ST_ERR; + } } break; case HSM_ST: @@ -4313,8 +4321,10 @@ inline unsigned int ata_host_intr (struct ata_port *ap, ap->ops->irq_clear(ap); /* check error */ - if (unlikely((status & ATA_ERR) || (host_stat & ATA_DMA_ERR))) + if (unlikely(status & (ATA_ERR | ATA_DF))) { + qc->err_mask |= AC_ERR_DEV; ap->hsm_task_state = HSM_ST_ERR; + } fsm_start: switch (ap->hsm_task_state) { @@ -4326,6 +4336,7 @@ fsm_start: /* check device status */ if (unlikely((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ)) { /* Wrong status. Let EH handle this */ + qc->err_mask |= AC_ERR_ATA_BUS; ap->hsm_task_state = HSM_ST_ERR; goto fsm_start; } @@ -4354,6 +4365,7 @@ fsm_start: /* ATA PIO protocol */ if (unlikely((status & ATA_DRQ) == 0)) { /* handle BSY=0, DRQ=0 as error */ + qc->err_mask |= AC_ERR_ATA_BUS; ap->hsm_task_state = HSM_ST_ERR; goto fsm_start; } @@ -4375,6 +4387,7 @@ fsm_start: case HSM_ST_LAST: if (unlikely(status & ATA_DRQ)) { /* handle DRQ=1 as error */ + qc->err_mask |= AC_ERR_ATA_BUS; ap->hsm_task_state = HSM_ST_ERR; goto fsm_start; } @@ -4394,8 +4407,12 @@ fsm_start: printk(KERN_ERR "ata%u: command error, drv_stat 0x%x host_stat 0x%x\n", ap->id, status, host_stat); + /* make sure qc->err_mask is available to + * know what's wrong and recover + */ + assert(qc->err_mask); + ap->hsm_task_state = HSM_ST_IDLE; - qc->err_mask |= __ac_err_mask(status); ata_qc_complete(qc); break; default: -- cgit v1.2.3 From 000080c3499cd5037e60c08a8053efb9e48aa9c0 Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Mon, 26 Dec 2005 16:48:00 +0800 Subject: [PATCH] libata-dev: filter out noisy ATAPI error messages Changes: - Filter out ATAPI packet command error messages in ata_pio_error() - Filter out ATAPI packet command error messages in ata_host_intr() Signed-off-by: Albert Lee ====== Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 41f76b9bf99..911151db8c2 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3520,11 +3520,12 @@ static void ata_pio_error(struct ata_port *ap) { struct ata_queued_cmd *qc; - printk(KERN_WARNING "ata%u: PIO error\n", ap->id); - qc = ata_qc_from_tag(ap, ap->active_tag); assert(qc != NULL); + if (qc->tf.command != ATA_CMD_PACKET) + printk(KERN_WARNING "ata%u: PIO error\n", ap->id); + /* make sure qc->err_mask is available to * know what's wrong and recover */ @@ -4404,8 +4405,9 @@ fsm_start: break; case HSM_ST_ERR: - printk(KERN_ERR "ata%u: command error, drv_stat 0x%x host_stat 0x%x\n", - ap->id, status, host_stat); + if (qc->tf.command != ATA_CMD_PACKET) + printk(KERN_ERR "ata%u: command error, drv_stat 0x%x host_stat 0x%x\n", + ap->id, status, host_stat); /* make sure qc->err_mask is available to * know what's wrong and recover -- cgit v1.2.3 From ffd642e748c867a7339b57225b8bf8b9a0dcd9c5 Mon Sep 17 00:00:00 2001 From: David Shaohua Li Date: Wed, 8 Feb 2006 17:35:00 -0500 Subject: [ACPI] enable SMP C-states on x86_64 http://bugzilla.kernel.org/show_bug.cgi?id=5653 Signed-off-by: David Shaohua Li Signed-off-by: Len Brown --- arch/x86_64/kernel/acpi/Makefile | 1 + arch/x86_64/kernel/acpi/processor.c | 72 ------------------------------------- include/asm-x86_64/acpi.h | 2 ++ 3 files changed, 3 insertions(+), 72 deletions(-) delete mode 100644 arch/x86_64/kernel/acpi/processor.c diff --git a/arch/x86_64/kernel/acpi/Makefile b/arch/x86_64/kernel/acpi/Makefile index 4fe97071f29..080b9963f1b 100644 --- a/arch/x86_64/kernel/acpi/Makefile +++ b/arch/x86_64/kernel/acpi/Makefile @@ -4,5 +4,6 @@ obj-$(CONFIG_ACPI_SLEEP) += sleep.o wakeup.o ifneq ($(CONFIG_ACPI_PROCESSOR),) obj-y += processor.o +processor-y := ../../../i386/kernel/acpi/processor.o ../../../i386/kernel/acpi/cstate.o endif diff --git a/arch/x86_64/kernel/acpi/processor.c b/arch/x86_64/kernel/acpi/processor.c deleted file mode 100644 index 3bdc2baa5bb..00000000000 --- a/arch/x86_64/kernel/acpi/processor.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * arch/x86_64/kernel/acpi/processor.c - * - * Copyright (C) 2005 Intel Corporation - * Venkatesh Pallipadi - * - Added _PDC for platforms with Intel CPUs - */ - -#include -#include -#include -#include - -#include -#include - -static void init_intel_pdc(struct acpi_processor *pr, struct cpuinfo_x86 *c) -{ - struct acpi_object_list *obj_list; - union acpi_object *obj; - u32 *buf; - - /* allocate and initialize pdc. It will be used later. */ - obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL); - if (!obj_list) { - printk(KERN_ERR "Memory allocation error\n"); - return; - } - - obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL); - if (!obj) { - printk(KERN_ERR "Memory allocation error\n"); - kfree(obj_list); - return; - } - - buf = kmalloc(12, GFP_KERNEL); - if (!buf) { - printk(KERN_ERR "Memory allocation error\n"); - kfree(obj); - kfree(obj_list); - return; - } - - buf[0] = ACPI_PDC_REVISION_ID; - buf[1] = 1; - buf[2] = ACPI_PDC_EST_CAPABILITY_SMP; - - obj->type = ACPI_TYPE_BUFFER; - obj->buffer.length = 12; - obj->buffer.pointer = (u8 *) buf; - obj_list->count = 1; - obj_list->pointer = obj; - pr->pdc = obj_list; - - return; -} - -/* Initialize _PDC data based on the CPU vendor */ -void arch_acpi_processor_init_pdc(struct acpi_processor *pr) -{ - unsigned int cpu = pr->id; - struct cpuinfo_x86 *c = cpu_data + cpu; - - pr->pdc = NULL; - if (c->x86_vendor == X86_VENDOR_INTEL && cpu_has(c, X86_FEATURE_EST)) - init_intel_pdc(pr, c); - - return; -} - -EXPORT_SYMBOL(arch_acpi_processor_init_pdc); diff --git a/include/asm-x86_64/acpi.h b/include/asm-x86_64/acpi.h index aa1c7b2e438..2c95a319c05 100644 --- a/include/asm-x86_64/acpi.h +++ b/include/asm-x86_64/acpi.h @@ -162,6 +162,8 @@ extern int acpi_pci_disabled; extern u8 x86_acpiid_to_apicid[]; +#define ARCH_HAS_POWER_INIT 1 + extern int acpi_skip_timer_override; #endif /*__KERNEL__*/ -- cgit v1.2.3 From 3b2d99429e3386b6e2ac949fc72486509c8bbe36 Mon Sep 17 00:00:00 2001 From: Venkatesh Pallipadi Date: Wed, 14 Dec 2005 15:05:00 -0500 Subject: P-state software coordination for ACPI core http://bugzilla.kernel.org/show_bug.cgi?id=5737 Signed-off-by: Venkatesh Pallipadi Signed-off-by: Len Brown --- drivers/acpi/processor_perflib.c | 228 +++++++++++++++++++++++++++++++++++++++ include/acpi/processor.h | 27 ++++- include/linux/cpufreq.h | 4 + 3 files changed, 258 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index abbdb37a7f5..ffc5280334c 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -553,6 +553,234 @@ static void acpi_cpufreq_remove_file(struct acpi_processor *pr) } #endif /* CONFIG_X86_ACPI_CPUFREQ_PROC_INTF */ +static int acpi_processor_get_psd(struct acpi_processor *pr) +{ + int result = 0; + acpi_status status = AE_OK; + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + struct acpi_buffer format = {sizeof("NNNNN"), "NNNNN"}; + struct acpi_buffer state = {0, NULL}; + union acpi_object *psd = NULL; + struct acpi_psd_package *pdomain; + + ACPI_FUNCTION_TRACE("acpi_processor_get_psd"); + + status = acpi_evaluate_object(pr->handle, "_PSD", NULL, &buffer); + if (ACPI_FAILURE(status)) { + return_VALUE(-ENODEV); + } + + psd = (union acpi_object *) buffer.pointer; + if (!psd || (psd->type != ACPI_TYPE_PACKAGE)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n")); + result = -EFAULT; + goto end; + } + + if (psd->package.count != 1) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n")); + result = -EFAULT; + goto end; + } + + pdomain = &(pr->performance->domain_info); + + state.length = sizeof(struct acpi_psd_package); + state.pointer = pdomain; + + status = acpi_extract_package(&(psd->package.elements[0]), + &format, &state); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n")); + result = -EFAULT; + goto end; + } + + if (pdomain->num_entries != ACPI_PSD_REV0_ENTRIES) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _PSD:num_entries\n")); + result = -EFAULT; + goto end; + } + + if (pdomain->revision != ACPI_PSD_REV0_REVISION) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _PSD:revision\n")); + result = -EFAULT; + goto end; + } + +end: + acpi_os_free(buffer.pointer); + return_VALUE(result); +} + +int acpi_processor_preregister_performance( + struct acpi_processor_performance **performance) +{ + int count, count_target; + int retval = 0; + unsigned int i, j; + cpumask_t covered_cpus; + struct acpi_processor *pr; + struct acpi_psd_package *pdomain; + struct acpi_processor *match_pr; + struct acpi_psd_package *match_pdomain; + + ACPI_FUNCTION_TRACE("acpi_processor_preregister_performance"); + + down(&performance_sem); + + retval = 0; + + /* Call _PSD for all CPUs */ + for_each_cpu(i) { + pr = processors[i]; + if (!pr) { + /* Look only at processors in ACPI namespace */ + continue; + } + + if (pr->performance) { + retval = -EBUSY; + continue; + } + + if (!performance || !performance[i]) { + retval = -EINVAL; + continue; + } + + pr->performance = performance[i]; + cpu_set(i, pr->performance->shared_cpu_map); + if (acpi_processor_get_psd(pr)) { + retval = -EINVAL; + continue; + } + } + if (retval) + goto err_ret; + + /* + * Now that we have _PSD data from all CPUs, lets setup P-state + * domain info. + */ + for_each_cpu(i) { + pr = processors[i]; + if (!pr) + continue; + + /* Basic validity check for domain info */ + pdomain = &(pr->performance->domain_info); + if ((pdomain->revision != ACPI_PSD_REV0_REVISION) || + (pdomain->num_entries != ACPI_PSD_REV0_ENTRIES)) { + retval = -EINVAL; + goto err_ret; + } + if (pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ALL && + pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ANY && + pdomain->coord_type != DOMAIN_COORD_TYPE_HW_ALL) { + retval = -EINVAL; + goto err_ret; + } + } + + cpus_clear(covered_cpus); + for_each_cpu(i) { + pr = processors[i]; + if (!pr) + continue; + + if (cpu_isset(i, covered_cpus)) + continue; + + pdomain = &(pr->performance->domain_info); + cpu_set(i, pr->performance->shared_cpu_map); + cpu_set(i, covered_cpus); + if (pdomain->num_processors <= 1) + continue; + + /* Validate the Domain info */ + count_target = pdomain->num_processors; + count = 1; + if (pdomain->coord_type == DOMAIN_COORD_TYPE_SW_ALL || + pdomain->coord_type == DOMAIN_COORD_TYPE_HW_ALL) { + pr->performance->shared_type = CPUFREQ_SHARED_TYPE_ALL; + } else if (pdomain->coord_type == DOMAIN_COORD_TYPE_SW_ANY) { + pr->performance->shared_type = CPUFREQ_SHARED_TYPE_ANY; + } + + for_each_cpu(j) { + if (i == j) + continue; + + match_pr = processors[j]; + if (!match_pr) + continue; + + match_pdomain = &(match_pr->performance->domain_info); + if (match_pdomain->domain != pdomain->domain) + continue; + + /* Here i and j are in the same domain */ + + if (match_pdomain->num_processors != count_target) { + retval = -EINVAL; + goto err_ret; + } + + if (pdomain->coord_type != match_pdomain->coord_type) { + retval = -EINVAL; + goto err_ret; + } + + cpu_set(j, covered_cpus); + cpu_set(j, pr->performance->shared_cpu_map); + count++; + } + + for_each_cpu(j) { + if (i == j) + continue; + + match_pr = processors[j]; + if (!match_pr) + continue; + + match_pdomain = &(match_pr->performance->domain_info); + if (match_pdomain->domain != pdomain->domain) + continue; + + match_pr->performance->shared_type = + pr->performance->shared_type; + match_pr->performance->shared_cpu_map = + pr->performance->shared_cpu_map; + } + } + +err_ret: + if (retval) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error while parsing _PSD domain information. Assuming no coordination\n")); + } + + for_each_cpu(i) { + pr = processors[i]; + if (!pr || !pr->performance) + continue; + + /* Assume no coordination on any error parsing domain info */ + if (retval) { + cpus_clear(pr->performance->shared_cpu_map); + cpu_set(i, pr->performance->shared_cpu_map); + pr->performance->shared_type = CPUFREQ_SHARED_TYPE_ALL; + } + pr->performance = NULL; /* Will be set for real in register */ + } + + up(&performance_sem); + return_VALUE(retval); +} +EXPORT_SYMBOL(acpi_processor_preregister_performance); + + int acpi_processor_register_performance(struct acpi_processor_performance *performance, unsigned int cpu) diff --git a/include/acpi/processor.h b/include/acpi/processor.h index badf0277b1b..0c46d1b3dda 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -3,6 +3,7 @@ #include #include +#include #include @@ -18,6 +19,17 @@ #define ACPI_PDC_REVISION_ID 0x1 +#define ACPI_PSD_REV0_REVISION 0 /* Support for _PSD as in ACPI 3.0 */ +#define ACPI_PSD_REV0_ENTRIES 5 + +/* + * Types of coordination defined in ACPI 3.0. Same macros can be used across + * P, C and T states + */ +#define DOMAIN_COORD_TYPE_SW_ALL 0xfc +#define DOMAIN_COORD_TYPE_SW_ANY 0xfd +#define DOMAIN_COORD_TYPE_HW_ALL 0xfe + /* Power Management */ struct acpi_processor_cx; @@ -66,6 +78,14 @@ struct acpi_processor_power { /* Performance Management */ +struct acpi_psd_package { + acpi_integer num_entries; + acpi_integer revision; + acpi_integer domain; + acpi_integer coord_type; + acpi_integer num_processors; +} __attribute__ ((packed)); + struct acpi_pct_register { u8 descriptor; u16 length; @@ -92,7 +112,9 @@ struct acpi_processor_performance { struct acpi_pct_register status_register; unsigned int state_count; struct acpi_processor_px *states; - + struct acpi_psd_package domain_info; + cpumask_t shared_cpu_map; + unsigned int shared_type; }; /* Throttling Control */ @@ -161,6 +183,9 @@ struct acpi_processor_errata { } piix4; }; +extern int acpi_processor_preregister_performance( + struct acpi_processor_performance **performance); + extern int acpi_processor_register_performance(struct acpi_processor_performance *performance, unsigned int cpu); extern void acpi_processor_unregister_performance(struct diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 17866d7e2b7..f7d98836694 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -73,6 +73,8 @@ struct cpufreq_real_policy { struct cpufreq_policy { cpumask_t cpus; /* affected CPUs */ + unsigned int shared_type; /* ANY or ALL affected CPUs + should set cpufreq */ unsigned int cpu; /* cpu nr of registered CPU */ struct cpufreq_cpuinfo cpuinfo;/* see above */ @@ -99,6 +101,8 @@ struct cpufreq_policy { #define CPUFREQ_INCOMPATIBLE (1) #define CPUFREQ_NOTIFY (2) +#define CPUFREQ_SHARED_TYPE_ALL (0) /* All dependent CPUs should set freq */ +#define CPUFREQ_SHARED_TYPE_ANY (1) /* Freq can be set from any dependent CPU */ /******************** cpufreq transition notifiers *******************/ -- cgit v1.2.3 From 09b4d1ee881c8593bfad2a42f838d85070365c3e Mon Sep 17 00:00:00 2001 From: Venkatesh Pallipadi Date: Wed, 14 Dec 2005 15:05:00 -0500 Subject: P-state software coordination for acpi-cpufreq http://bugzilla.kernel.org/show_bug.cgi?id=5737 Signed-off-by: Venkatesh Pallipadi Signed-off-by: Len Brown --- arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c | 285 +++++++++++++++++++--------- 1 file changed, 197 insertions(+), 88 deletions(-) diff --git a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c index 3852d0a4c1b..4c7c6e089e8 100644 --- a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c @@ -48,12 +48,13 @@ MODULE_LICENSE("GPL"); struct cpufreq_acpi_io { - struct acpi_processor_performance acpi_data; + struct acpi_processor_performance *acpi_data; struct cpufreq_frequency_table *freq_table; unsigned int resume; }; static struct cpufreq_acpi_io *acpi_io_data[NR_CPUS]; +static struct acpi_processor_performance *acpi_perf_data[NR_CPUS]; static struct cpufreq_driver acpi_cpufreq_driver; @@ -104,64 +105,43 @@ acpi_processor_set_performance ( { u16 port = 0; u8 bit_width = 0; + int i = 0; int ret = 0; u32 value = 0; - int i = 0; - struct cpufreq_freqs cpufreq_freqs; - cpumask_t saved_mask; int retval; + struct acpi_processor_performance *perf; dprintk("acpi_processor_set_performance\n"); - /* - * TBD: Use something other than set_cpus_allowed. - * As set_cpus_allowed is a bit racy, - * with any other set_cpus_allowed for this process. - */ - saved_mask = current->cpus_allowed; - set_cpus_allowed(current, cpumask_of_cpu(cpu)); - if (smp_processor_id() != cpu) { - return (-EAGAIN); - } - - if (state == data->acpi_data.state) { + retval = 0; + perf = data->acpi_data; + if (state == perf->state) { if (unlikely(data->resume)) { dprintk("Called after resume, resetting to P%d\n", state); data->resume = 0; } else { dprintk("Already at target state (P%d)\n", state); - retval = 0; - goto migrate_end; + return (retval); } } - dprintk("Transitioning from P%d to P%d\n", - data->acpi_data.state, state); - - /* cpufreq frequency struct */ - cpufreq_freqs.cpu = cpu; - cpufreq_freqs.old = data->freq_table[data->acpi_data.state].frequency; - cpufreq_freqs.new = data->freq_table[state].frequency; - - /* notify cpufreq */ - cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE); + dprintk("Transitioning from P%d to P%d\n", perf->state, state); /* * First we write the target state's 'control' value to the * control_register. */ - port = data->acpi_data.control_register.address; - bit_width = data->acpi_data.control_register.bit_width; - value = (u32) data->acpi_data.states[state].control; + port = perf->control_register.address; + bit_width = perf->control_register.bit_width; + value = (u32) perf->states[state].control; dprintk("Writing 0x%08x to port 0x%04x\n", value, port); ret = acpi_processor_write_port(port, bit_width, value); if (ret) { dprintk("Invalid port width 0x%04x\n", bit_width); - retval = ret; - goto migrate_end; + return (ret); } /* @@ -177,49 +157,36 @@ acpi_processor_set_performance ( * before giving up. */ - port = data->acpi_data.status_register.address; - bit_width = data->acpi_data.status_register.bit_width; + port = perf->status_register.address; + bit_width = perf->status_register.bit_width; dprintk("Looking for 0x%08x from port 0x%04x\n", - (u32) data->acpi_data.states[state].status, port); + (u32) perf->states[state].status, port); - for (i=0; i<100; i++) { + for (i = 0; i < 100; i++) { ret = acpi_processor_read_port(port, bit_width, &value); if (ret) { dprintk("Invalid port width 0x%04x\n", bit_width); - retval = ret; - goto migrate_end; + return (ret); } - if (value == (u32) data->acpi_data.states[state].status) + if (value == (u32) perf->states[state].status) break; udelay(10); } } else { i = 0; - value = (u32) data->acpi_data.states[state].status; + value = (u32) perf->states[state].status; } - /* notify cpufreq */ - cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE); - - if (unlikely(value != (u32) data->acpi_data.states[state].status)) { - unsigned int tmp = cpufreq_freqs.new; - cpufreq_freqs.new = cpufreq_freqs.old; - cpufreq_freqs.old = tmp; - cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE); - cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE); + if (unlikely(value != (u32) perf->states[state].status)) { printk(KERN_WARNING "acpi-cpufreq: Transition failed\n"); retval = -ENODEV; - goto migrate_end; + return (retval); } dprintk("Transition successful after %d microseconds\n", i * 10); - data->acpi_data.state = state; - - retval = 0; -migrate_end: - set_cpus_allowed(current, saved_mask); + perf->state = state; return (retval); } @@ -231,8 +198,17 @@ acpi_cpufreq_target ( unsigned int relation) { struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu]; + struct acpi_processor_performance *perf; + struct cpufreq_freqs freqs; + cpumask_t online_policy_cpus; + cpumask_t saved_mask; + cpumask_t set_mask; + cpumask_t covered_cpus; + unsigned int cur_state = 0; unsigned int next_state = 0; unsigned int result = 0; + unsigned int j; + unsigned int tmp; dprintk("acpi_cpufreq_setpolicy\n"); @@ -241,11 +217,91 @@ acpi_cpufreq_target ( target_freq, relation, &next_state); - if (result) + if (unlikely(result)) return (result); - result = acpi_processor_set_performance (data, policy->cpu, next_state); + perf = data->acpi_data; + cur_state = perf->state; + freqs.old = data->freq_table[cur_state].frequency; + freqs.new = data->freq_table[next_state].frequency; + + /* cpufreq holds the hotplug lock, so we are safe from here on */ + cpus_and(online_policy_cpus, cpu_online_map, policy->cpus); + for_each_cpu_mask(j, online_policy_cpus) { + freqs.cpu = j; + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + } + + /* + * We need to call driver->target() on all or any CPU in + * policy->cpus, depending on policy->shared_type. + */ + saved_mask = current->cpus_allowed; + cpus_clear(covered_cpus); + for_each_cpu_mask(j, online_policy_cpus) { + /* + * Support for SMP systems. + * Make sure we are running on CPU that wants to change freq + */ + cpus_clear(set_mask); + if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) + cpus_or(set_mask, set_mask, online_policy_cpus); + else + cpu_set(j, set_mask); + + set_cpus_allowed(current, set_mask); + if (unlikely(!cpu_isset(smp_processor_id(), set_mask))) { + dprintk("couldn't limit to CPUs in this domain\n"); + result = -EAGAIN; + break; + } + + result = acpi_processor_set_performance (data, j, next_state); + if (result) { + result = -EAGAIN; + break; + } + + if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) + break; + + cpu_set(j, covered_cpus); + } + + for_each_cpu_mask(j, online_policy_cpus) { + freqs.cpu = j; + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + } + + if (unlikely(result)) { + /* + * We have failed halfway through the frequency change. + * We have sent callbacks to online_policy_cpus and + * acpi_processor_set_performance() has been called on + * coverd_cpus. Best effort undo.. + */ + + if (!cpus_empty(covered_cpus)) { + for_each_cpu_mask(j, covered_cpus) { + policy->cpu = j; + acpi_processor_set_performance (data, + j, + cur_state); + } + } + + tmp = freqs.new; + freqs.new = freqs.old; + freqs.old = tmp; + for_each_cpu_mask(j, online_policy_cpus) { + freqs.cpu = j; + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + } + } + + set_cpus_allowed(current, saved_mask); return (result); } @@ -271,30 +327,65 @@ acpi_cpufreq_guess_freq ( struct cpufreq_acpi_io *data, unsigned int cpu) { + struct acpi_processor_performance *perf = data->acpi_data; + if (cpu_khz) { /* search the closest match to cpu_khz */ unsigned int i; unsigned long freq; - unsigned long freqn = data->acpi_data.states[0].core_frequency * 1000; + unsigned long freqn = perf->states[0].core_frequency * 1000; - for (i=0; i < (data->acpi_data.state_count - 1); i++) { + for (i = 0; i < (perf->state_count - 1); i++) { freq = freqn; - freqn = data->acpi_data.states[i+1].core_frequency * 1000; + freqn = perf->states[i+1].core_frequency * 1000; if ((2 * cpu_khz) > (freqn + freq)) { - data->acpi_data.state = i; + perf->state = i; return (freq); } } - data->acpi_data.state = data->acpi_data.state_count - 1; + perf->state = perf->state_count - 1; return (freqn); - } else + } else { /* assume CPU is at P0... */ - data->acpi_data.state = 0; - return data->acpi_data.states[0].core_frequency * 1000; - + perf->state = 0; + return perf->states[0].core_frequency * 1000; + } } +/* + * acpi_cpufreq_early_init - initialize ACPI P-States library + * + * Initialize the ACPI P-States library (drivers/acpi/processor_perflib.c) + * in order to determine correct frequency and voltage pairings. We can + * do _PDC and _PSD and find out the processor dependency for the + * actual init that will happen later... + */ +static int acpi_cpufreq_early_init_acpi(void) +{ + struct acpi_processor_performance *data; + unsigned int i, j; + + dprintk("acpi_cpufreq_early_init\n"); + + for_each_cpu(i) { + data = kzalloc(sizeof(struct acpi_processor_performance), + GFP_KERNEL); + if (!data) { + for_each_cpu(j) { + kfree(acpi_perf_data[j]); + acpi_perf_data[j] = NULL; + } + return (-ENOMEM); + } + acpi_perf_data[i] = data; + } + + /* Do initialization in ACPI core */ + acpi_processor_preregister_performance(acpi_perf_data); + return 0; +} + static int acpi_cpufreq_cpu_init ( struct cpufreq_policy *policy) @@ -304,41 +395,51 @@ acpi_cpufreq_cpu_init ( struct cpufreq_acpi_io *data; unsigned int result = 0; struct cpuinfo_x86 *c = &cpu_data[policy->cpu]; + struct acpi_processor_performance *perf; dprintk("acpi_cpufreq_cpu_init\n"); + if (!acpi_perf_data[cpu]) + return (-ENODEV); + data = kzalloc(sizeof(struct cpufreq_acpi_io), GFP_KERNEL); if (!data) return (-ENOMEM); + data->acpi_data = acpi_perf_data[cpu]; acpi_io_data[cpu] = data; - result = acpi_processor_register_performance(&data->acpi_data, cpu); + result = acpi_processor_register_performance(data->acpi_data, cpu); if (result) goto err_free; + perf = data->acpi_data; + policy->cpus = perf->shared_cpu_map; + policy->shared_type = perf->shared_type; + if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) { acpi_cpufreq_driver.flags |= CPUFREQ_CONST_LOOPS; } /* capability check */ - if (data->acpi_data.state_count <= 1) { + if (perf->state_count <= 1) { dprintk("No P-States\n"); result = -ENODEV; goto err_unreg; } - if ((data->acpi_data.control_register.space_id != ACPI_ADR_SPACE_SYSTEM_IO) || - (data->acpi_data.status_register.space_id != ACPI_ADR_SPACE_SYSTEM_IO)) { + + if ((perf->control_register.space_id != ACPI_ADR_SPACE_SYSTEM_IO) || + (perf->status_register.space_id != ACPI_ADR_SPACE_SYSTEM_IO)) { dprintk("Unsupported address space [%d, %d]\n", - (u32) (data->acpi_data.control_register.space_id), - (u32) (data->acpi_data.status_register.space_id)); + (u32) (perf->control_register.space_id), + (u32) (perf->status_register.space_id)); result = -ENODEV; goto err_unreg; } /* alloc freq_table */ - data->freq_table = kmalloc(sizeof(struct cpufreq_frequency_table) * (data->acpi_data.state_count + 1), GFP_KERNEL); + data->freq_table = kmalloc(sizeof(struct cpufreq_frequency_table) * (perf->state_count + 1), GFP_KERNEL); if (!data->freq_table) { result = -ENOMEM; goto err_unreg; @@ -346,9 +447,9 @@ acpi_cpufreq_cpu_init ( /* detect transition latency */ policy->cpuinfo.transition_latency = 0; - for (i=0; iacpi_data.state_count; i++) { - if ((data->acpi_data.states[i].transition_latency * 1000) > policy->cpuinfo.transition_latency) - policy->cpuinfo.transition_latency = data->acpi_data.states[i].transition_latency * 1000; + for (i=0; istate_count; i++) { + if ((perf->states[i].transition_latency * 1000) > policy->cpuinfo.transition_latency) + policy->cpuinfo.transition_latency = perf->states[i].transition_latency * 1000; } policy->governor = CPUFREQ_DEFAULT_GOVERNOR; @@ -356,11 +457,11 @@ acpi_cpufreq_cpu_init ( policy->cur = acpi_cpufreq_guess_freq(data, policy->cpu); /* table init */ - for (i=0; i<=data->acpi_data.state_count; i++) + for (i=0; i<=perf->state_count; i++) { data->freq_table[i].index = i; - if (iacpi_data.state_count) - data->freq_table[i].frequency = data->acpi_data.states[i].core_frequency * 1000; + if (istate_count) + data->freq_table[i].frequency = perf->states[i].core_frequency * 1000; else data->freq_table[i].frequency = CPUFREQ_TABLE_END; } @@ -375,12 +476,12 @@ acpi_cpufreq_cpu_init ( printk(KERN_INFO "acpi-cpufreq: CPU%u - ACPI performance management activated.\n", cpu); - for (i = 0; i < data->acpi_data.state_count; i++) + for (i = 0; i < perf->state_count; i++) dprintk(" %cP%d: %d MHz, %d mW, %d uS\n", - (i == data->acpi_data.state?'*':' '), i, - (u32) data->acpi_data.states[i].core_frequency, - (u32) data->acpi_data.states[i].power, - (u32) data->acpi_data.states[i].transition_latency); + (i == perf->state?'*':' '), i, + (u32) perf->states[i].core_frequency, + (u32) perf->states[i].power, + (u32) perf->states[i].transition_latency); cpufreq_frequency_table_get_attr(data->freq_table, policy->cpu); @@ -395,7 +496,7 @@ acpi_cpufreq_cpu_init ( err_freqfree: kfree(data->freq_table); err_unreg: - acpi_processor_unregister_performance(&data->acpi_data, cpu); + acpi_processor_unregister_performance(perf, cpu); err_free: kfree(data); acpi_io_data[cpu] = NULL; @@ -416,7 +517,7 @@ acpi_cpufreq_cpu_exit ( if (data) { cpufreq_frequency_table_put_attr(policy->cpu); acpi_io_data[policy->cpu] = NULL; - acpi_processor_unregister_performance(&data->acpi_data, policy->cpu); + acpi_processor_unregister_performance(data->acpi_data, policy->cpu); kfree(data); } @@ -462,7 +563,10 @@ acpi_cpufreq_init (void) dprintk("acpi_cpufreq_init\n"); - result = cpufreq_register_driver(&acpi_cpufreq_driver); + result = acpi_cpufreq_early_init_acpi(); + + if (!result) + result = cpufreq_register_driver(&acpi_cpufreq_driver); return (result); } @@ -471,10 +575,15 @@ acpi_cpufreq_init (void) static void __exit acpi_cpufreq_exit (void) { + unsigned int i; dprintk("acpi_cpufreq_exit\n"); cpufreq_unregister_driver(&acpi_cpufreq_driver); + for_each_cpu(i) { + kfree(acpi_perf_data[i]); + acpi_perf_data[i] = NULL; + } return; } -- cgit v1.2.3 From c52851b60cc0aaaf974ff0e49989fb698220447d Mon Sep 17 00:00:00 2001 From: Venkatesh Pallipadi Date: Wed, 14 Dec 2005 15:05:00 -0500 Subject: P-state software coordination for speedstep-centrino http://bugzilla.kernel.org/show_bug.cgi?id=5737 Signed-off-by: Venkatesh Pallipadi Signed-off-by: Len Brown --- arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c | 246 ++++++++++++++++------ 1 file changed, 180 insertions(+), 66 deletions(-) diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c index c173c0fa117..37dee862f0d 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c @@ -351,7 +351,36 @@ static unsigned int get_cur_freq(unsigned int cpu) #ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI -static struct acpi_processor_performance p; +static struct acpi_processor_performance *acpi_perf_data[NR_CPUS]; + +/* + * centrino_cpu_early_init_acpi - Do the preregistering with ACPI P-States + * library + * + * Before doing the actual init, we need to do _PSD related setup whenever + * supported by the BIOS. These are handled by this early_init routine. + */ +static int centrino_cpu_early_init_acpi(void) +{ + unsigned int i, j; + struct acpi_processor_performance *data; + + for_each_cpu(i) { + data = kzalloc(sizeof(struct acpi_processor_performance), + GFP_KERNEL); + if (!data) { + for_each_cpu(j) { + kfree(acpi_perf_data[j]); + acpi_perf_data[j] = NULL; + } + return (-ENOMEM); + } + acpi_perf_data[i] = data; + } + + acpi_processor_preregister_performance(acpi_perf_data); + return 0; +} /* * centrino_cpu_init_acpi - register with ACPI P-States library @@ -365,46 +394,51 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy) unsigned long cur_freq; int result = 0, i; unsigned int cpu = policy->cpu; + struct acpi_processor_performance *p; + + p = acpi_perf_data[cpu]; /* register with ACPI core */ - if (acpi_processor_register_performance(&p, cpu)) { + if (acpi_processor_register_performance(p, cpu)) { dprintk(KERN_INFO PFX "obtaining ACPI data failed\n"); return -EIO; } + policy->cpus = p->shared_cpu_map; + policy->shared_type = p->shared_type; /* verify the acpi_data */ - if (p.state_count <= 1) { + if (p->state_count <= 1) { dprintk("No P-States\n"); result = -ENODEV; goto err_unreg; } - if ((p.control_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE) || - (p.status_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE)) { + if ((p->control_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE) || + (p->status_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE)) { dprintk("Invalid control/status registers (%x - %x)\n", - p.control_register.space_id, p.status_register.space_id); + p->control_register.space_id, p->status_register.space_id); result = -EIO; goto err_unreg; } - for (i=0; istate_count; i++) { + if (p->states[i].control != p->states[i].status) { dprintk("Different control (%llu) and status values (%llu)\n", - p.states[i].control, p.states[i].status); + p->states[i].control, p->states[i].status); result = -EINVAL; goto err_unreg; } - if (!p.states[i].core_frequency) { + if (!p->states[i].core_frequency) { dprintk("Zero core frequency for state %u\n", i); result = -EINVAL; goto err_unreg; } - if (p.states[i].core_frequency > p.states[0].core_frequency) { + if (p->states[i].core_frequency > p->states[0].core_frequency) { dprintk("P%u has larger frequency (%llu) than P0 (%llu), skipping\n", i, - p.states[i].core_frequency, p.states[0].core_frequency); - p.states[i].core_frequency = 0; + p->states[i].core_frequency, p->states[0].core_frequency); + p->states[i].core_frequency = 0; continue; } } @@ -416,26 +450,26 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy) } centrino_model[cpu]->model_name=NULL; - centrino_model[cpu]->max_freq = p.states[0].core_frequency * 1000; + centrino_model[cpu]->max_freq = p->states[0].core_frequency * 1000; centrino_model[cpu]->op_points = kmalloc(sizeof(struct cpufreq_frequency_table) * - (p.state_count + 1), GFP_KERNEL); + (p->state_count + 1), GFP_KERNEL); if (!centrino_model[cpu]->op_points) { result = -ENOMEM; goto err_kfree; } - for (i=0; iop_points[i].index = p.states[i].control; - centrino_model[cpu]->op_points[i].frequency = p.states[i].core_frequency * 1000; + for (i=0; istate_count; i++) { + centrino_model[cpu]->op_points[i].index = p->states[i].control; + centrino_model[cpu]->op_points[i].frequency = p->states[i].core_frequency * 1000; dprintk("adding state %i with frequency %u and control value %04x\n", i, centrino_model[cpu]->op_points[i].frequency, centrino_model[cpu]->op_points[i].index); } - centrino_model[cpu]->op_points[p.state_count].frequency = CPUFREQ_TABLE_END; + centrino_model[cpu]->op_points[p->state_count].frequency = CPUFREQ_TABLE_END; cur_freq = get_cur_freq(cpu); - for (i=0; istate_count; i++) { + if (!p->states[i].core_frequency) { dprintk("skipping state %u\n", i); centrino_model[cpu]->op_points[i].frequency = CPUFREQ_ENTRY_INVALID; continue; @@ -451,7 +485,7 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy) } if (cur_freq == centrino_model[cpu]->op_points[i].frequency) - p.state = i; + p->state = i; } /* notify BIOS that we exist */ @@ -464,12 +498,13 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy) err_kfree: kfree(centrino_model[cpu]); err_unreg: - acpi_processor_unregister_performance(&p, cpu); + acpi_processor_unregister_performance(p, cpu); dprintk(KERN_INFO PFX "invalid ACPI data\n"); return (result); } #else static inline int centrino_cpu_init_acpi(struct cpufreq_policy *policy) { return -ENODEV; } +static inline int centrino_cpu_early_init_acpi(void) { return 0; } #endif static int centrino_cpu_init(struct cpufreq_policy *policy) @@ -557,10 +592,15 @@ static int centrino_cpu_exit(struct cpufreq_policy *policy) #ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI if (!centrino_model[cpu]->model_name) { - dprintk("unregistering and freeing ACPI data\n"); - acpi_processor_unregister_performance(&p, cpu); - kfree(centrino_model[cpu]->op_points); - kfree(centrino_model[cpu]); + static struct acpi_processor_performance *p; + + if (acpi_perf_data[cpu]) { + p = acpi_perf_data[cpu]; + dprintk("unregistering and freeing ACPI data\n"); + acpi_processor_unregister_performance(p, cpu); + kfree(centrino_model[cpu]->op_points); + kfree(centrino_model[cpu]); + } } #endif @@ -594,63 +634,124 @@ static int centrino_target (struct cpufreq_policy *policy, unsigned int relation) { unsigned int newstate = 0; - unsigned int msr, oldmsr, h, cpu = policy->cpu; + unsigned int msr, oldmsr = 0, h = 0, cpu = policy->cpu; struct cpufreq_freqs freqs; + cpumask_t online_policy_cpus; cpumask_t saved_mask; - int retval; + cpumask_t set_mask; + cpumask_t covered_cpus; + int retval = 0; + unsigned int j, k, first_cpu, tmp; - if (centrino_model[cpu] == NULL) + if (unlikely(centrino_model[cpu] == NULL)) return -ENODEV; - /* - * Support for SMP systems. - * Make sure we are running on the CPU that wants to change frequency - */ - saved_mask = current->cpus_allowed; - set_cpus_allowed(current, policy->cpus); - if (!cpu_isset(smp_processor_id(), policy->cpus)) { - dprintk("couldn't limit to CPUs in this domain\n"); - return(-EAGAIN); + if (unlikely(cpufreq_frequency_table_target(policy, + centrino_model[cpu]->op_points, + target_freq, + relation, + &newstate))) { + return -EINVAL; } - if (cpufreq_frequency_table_target(policy, centrino_model[cpu]->op_points, target_freq, - relation, &newstate)) { - retval = -EINVAL; - goto migrate_end; - } + /* cpufreq holds the hotplug lock, so we are safe from here on */ + cpus_and(online_policy_cpus, cpu_online_map, policy->cpus); - msr = centrino_model[cpu]->op_points[newstate].index; - rdmsr(MSR_IA32_PERF_CTL, oldmsr, h); + saved_mask = current->cpus_allowed; + first_cpu = 1; + cpus_clear(covered_cpus); + for_each_cpu_mask(j, online_policy_cpus) { + /* + * Support for SMP systems. + * Make sure we are running on CPU that wants to change freq + */ + cpus_clear(set_mask); + if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) + cpus_or(set_mask, set_mask, online_policy_cpus); + else + cpu_set(j, set_mask); + + set_cpus_allowed(current, set_mask); + if (unlikely(!cpu_isset(smp_processor_id(), set_mask))) { + dprintk("couldn't limit to CPUs in this domain\n"); + retval = -EAGAIN; + if (first_cpu) { + /* We haven't started the transition yet. */ + goto migrate_end; + } + break; + } - if (msr == (oldmsr & 0xffff)) { - retval = 0; - dprintk("no change needed - msr was and needs to be %x\n", oldmsr); - goto migrate_end; - } + msr = centrino_model[cpu]->op_points[newstate].index; + + if (first_cpu) { + rdmsr(MSR_IA32_PERF_CTL, oldmsr, h); + if (msr == (oldmsr & 0xffff)) { + dprintk("no change needed - msr was and needs " + "to be %x\n", oldmsr); + retval = 0; + goto migrate_end; + } + + freqs.old = extract_clock(oldmsr, cpu, 0); + freqs.new = extract_clock(msr, cpu, 0); + + dprintk("target=%dkHz old=%d new=%d msr=%04x\n", + target_freq, freqs.old, freqs.new, msr); + + for_each_cpu_mask(k, online_policy_cpus) { + freqs.cpu = k; + cpufreq_notify_transition(&freqs, + CPUFREQ_PRECHANGE); + } + + first_cpu = 0; + /* all but 16 LSB are reserved, treat them with care */ + oldmsr &= ~0xffff; + msr &= 0xffff; + oldmsr |= msr; + } - freqs.cpu = cpu; - freqs.old = extract_clock(oldmsr, cpu, 0); - freqs.new = extract_clock(msr, cpu, 0); + wrmsr(MSR_IA32_PERF_CTL, oldmsr, h); + if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) + break; - dprintk("target=%dkHz old=%d new=%d msr=%04x\n", - target_freq, freqs.old, freqs.new, msr); + cpu_set(j, covered_cpus); + } - cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + for_each_cpu_mask(k, online_policy_cpus) { + freqs.cpu = k; + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + } - /* all but 16 LSB are "reserved", so treat them with - care */ - oldmsr &= ~0xffff; - msr &= 0xffff; - oldmsr |= msr; + if (unlikely(retval)) { + /* + * We have failed halfway through the frequency change. + * We have sent callbacks to policy->cpus and + * MSRs have already been written on coverd_cpus. + * Best effort undo.. + */ - wrmsr(MSR_IA32_PERF_CTL, oldmsr, h); + if (!cpus_empty(covered_cpus)) { + for_each_cpu_mask(j, covered_cpus) { + set_cpus_allowed(current, cpumask_of_cpu(j)); + wrmsr(MSR_IA32_PERF_CTL, oldmsr, h); + } + } - cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + tmp = freqs.new; + freqs.new = freqs.old; + freqs.old = tmp; + for_each_cpu_mask(j, online_policy_cpus) { + freqs.cpu = j; + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + } + } - retval = 0; migrate_end: set_cpus_allowed(current, saved_mask); - return (retval); + return 0; } static struct freq_attr* centrino_attr[] = { @@ -692,12 +793,25 @@ static int __init centrino_init(void) if (!cpu_has(cpu, X86_FEATURE_EST)) return -ENODEV; + centrino_cpu_early_init_acpi(); + return cpufreq_register_driver(¢rino_driver); } static void __exit centrino_exit(void) { +#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI + unsigned int j; +#endif + cpufreq_unregister_driver(¢rino_driver); + +#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI + for_each_cpu(j) { + kfree(acpi_perf_data[j]); + acpi_perf_data[j] = NULL; + } +#endif } MODULE_AUTHOR ("Jeremy Fitzhardinge "); -- cgit v1.2.3 From d52bb94d56676acd9bdac8e097257a87b4b1b2e1 Mon Sep 17 00:00:00 2001 From: Venkatesh Pallipadi Date: Wed, 14 Dec 2005 15:05:00 -0500 Subject: Enable P-state software coordination via _PDC http://bugzilla.kernel.org/show_bug.cgi?id=5737 Signed-off-by: Venkatesh Pallipadi Signed-off-by: Len Brown --- arch/i386/kernel/acpi/processor.c | 2 +- arch/x86_64/kernel/acpi/processor.c | 2 +- include/acpi/pdc_intel.h | 5 +++++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/i386/kernel/acpi/processor.c b/arch/i386/kernel/acpi/processor.c index 9f4cc02717e..b54fded4983 100644 --- a/arch/i386/kernel/acpi/processor.c +++ b/arch/i386/kernel/acpi/processor.c @@ -47,7 +47,7 @@ static void init_intel_pdc(struct acpi_processor *pr, struct cpuinfo_x86 *c) buf[2] = ACPI_PDC_C_CAPABILITY_SMP; if (cpu_has(c, X86_FEATURE_EST)) - buf[2] |= ACPI_PDC_EST_CAPABILITY_SMP; + buf[2] |= ACPI_PDC_EST_CAPABILITY_SWSMP; obj->type = ACPI_TYPE_BUFFER; obj->buffer.length = 12; diff --git a/arch/x86_64/kernel/acpi/processor.c b/arch/x86_64/kernel/acpi/processor.c index 3bdc2baa5bb..81fcb3f869f 100644 --- a/arch/x86_64/kernel/acpi/processor.c +++ b/arch/x86_64/kernel/acpi/processor.c @@ -44,7 +44,7 @@ static void init_intel_pdc(struct acpi_processor *pr, struct cpuinfo_x86 *c) buf[0] = ACPI_PDC_REVISION_ID; buf[1] = 1; - buf[2] = ACPI_PDC_EST_CAPABILITY_SMP; + buf[2] = ACPI_PDC_EST_CAPABILITY_SWSMP; obj->type = ACPI_TYPE_BUFFER; obj->buffer.length = 12; diff --git a/include/acpi/pdc_intel.h b/include/acpi/pdc_intel.h index 3fa81d55cd0..c5472be6f3a 100644 --- a/include/acpi/pdc_intel.h +++ b/include/acpi/pdc_intel.h @@ -18,6 +18,11 @@ ACPI_PDC_C_C1_HALT | \ ACPI_PDC_P_FFH) +#define ACPI_PDC_EST_CAPABILITY_SWSMP (ACPI_PDC_SMP_C1PT | \ + ACPI_PDC_C_C1_HALT | \ + ACPI_PDC_SMP_P_SWCOORD | \ + ACPI_PDC_P_FFH) + #define ACPI_PDC_C_CAPABILITY_SMP (ACPI_PDC_SMP_C2C3 | \ ACPI_PDC_SMP_C1PT | \ ACPI_PDC_C_C1_HALT) -- cgit v1.2.3 From aef9d533da2eb7a5700a8c8700f2597c35cc50d1 Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Wed, 8 Feb 2006 16:37:43 +0800 Subject: [PATCH] libata-dev: Fix array index value in ata_rwcmd_protocol() Signed-off-by: Albert Lee === Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 6daba4e2c3f..dab13ed6fa7 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -611,7 +611,7 @@ int ata_rwcmd_protocol(struct ata_queued_cmd *qc) } else if (lba48 && (qc->ap->flags & ATA_FLAG_PIO_LBA48)) { /* Unable to use DMA due to host limitation */ tf->protocol = ATA_PROT_PIO; - index = dev->multi_count ? 0 : 4; + index = dev->multi_count ? 0 : 8; } else { tf->protocol = ATA_PROT_DMA; index = 16; -- cgit v1.2.3 From 20ea079e5883ab2b82fa5e576957f52e4e5c252c Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Wed, 8 Feb 2006 16:48:49 +0800 Subject: [PATCH] libata-dev: Use new ata_queue_pio_task() for PIO polling task - Use new ata_queue_pio_task() for PIO polling task. - Remove the unused ata_queue_packet_task() function. (irq-pio had merged the 2 queues into one.) Signed-off-by: Albert Lee === Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index dab13ed6fa7..bbce1622eb7 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1072,12 +1072,6 @@ static unsigned int ata_pio_modes(const struct ata_device *adev) timing API will get this right anyway */ } -static inline void -ata_queue_packet_task(struct ata_port *ap) -{ - queue_work(ata_wq, &ap->packet_task); -} - static inline void ata_queue_pio_task(struct ata_port *ap) { @@ -3971,7 +3965,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc) ap->hsm_task_state = HSM_ST_LAST; if (qc->tf.flags & ATA_TFLAG_POLLING) - queue_work(ata_wq, &ap->pio_task); + ata_queue_pio_task(ap); break; @@ -4024,7 +4018,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc) /* send cdb by polling if no cdb interrupt */ if ((!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) || (qc->tf.flags & ATA_TFLAG_POLLING)) - ata_queue_packet_task(ap); + ata_queue_pio_task(ap); break; case ATA_PROT_ATAPI_DMA: @@ -4036,7 +4030,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc) /* send cdb by polling if no cdb interrupt */ if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) - ata_queue_packet_task(ap); + ata_queue_pio_task(ap); break; default: -- cgit v1.2.3 From 555a8965069b8e34292cbccc3ad8f619b96815fe Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Wed, 8 Feb 2006 16:50:29 +0800 Subject: [PATCH] libata-dev: Use new AC_ERR_* flags - Use new AC_ERR_* flags as done in Tejun's patches - In ata_qc_timeout(), replace ac_err_mask(drv_stat) with AC_ERR_TIMEOUT. This makes time out handler always report error to upper layer. Otherwise if the drv_stat looks good, libata might falsely report OK to the upper layer. Signed-off-by: Albert Lee === Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index bbce1622eb7..415c64f8114 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3315,7 +3315,7 @@ static int ata_pio_first_block(struct ata_port *ap) /* sleep-wait for BSY to clear */ DPRINTK("busy wait\n"); if (ata_busy_sleep(ap, ATA_TMOUT_DATAOUT_QUICK, ATA_TMOUT_DATAOUT)) { - qc->err_mask |= AC_ERR_ATA_BUS; + qc->err_mask |= AC_ERR_TIMEOUT; ap->hsm_task_state = HSM_ST_TMOUT; goto err_out; } @@ -3324,7 +3324,7 @@ static int ata_pio_first_block(struct ata_port *ap) status = ata_chk_status(ap); if ((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ) { /* device status error */ - qc->err_mask |= AC_ERR_ATA_BUS; + qc->err_mask |= AC_ERR_HSM; ap->hsm_task_state = HSM_ST_ERR; goto err_out; } @@ -3684,7 +3684,7 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc) ap->hsm_task_state = HSM_ST_IDLE; /* complete taskfile transaction */ - qc->err_mask |= ac_err_mask(drv_stat); + qc->err_mask |= AC_ERR_TIMEOUT; break; } @@ -4365,7 +4365,7 @@ fsm_start: /* check device status */ if (unlikely((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ)) { /* Wrong status. Let EH handle this */ - qc->err_mask |= AC_ERR_ATA_BUS; + qc->err_mask |= AC_ERR_HSM; ap->hsm_task_state = HSM_ST_ERR; goto fsm_start; } @@ -4394,7 +4394,7 @@ fsm_start: /* ATA PIO protocol */ if (unlikely((status & ATA_DRQ) == 0)) { /* handle BSY=0, DRQ=0 as error */ - qc->err_mask |= AC_ERR_ATA_BUS; + qc->err_mask |= AC_ERR_HSM; ap->hsm_task_state = HSM_ST_ERR; goto fsm_start; } @@ -4416,7 +4416,7 @@ fsm_start: case HSM_ST_LAST: if (unlikely(status & ATA_DRQ)) { /* handle DRQ=1 as error */ - qc->err_mask |= AC_ERR_ATA_BUS; + qc->err_mask |= AC_ERR_HSM; ap->hsm_task_state = HSM_ST_ERR; goto fsm_start; } -- cgit v1.2.3 From 332b5a52f2f96bc2d13bbe594a430318c0ee4425 Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Wed, 8 Feb 2006 16:51:34 +0800 Subject: [PATCH] libata-dev: Minor comment fix Signed-off-by: Albert Lee === Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 415c64f8114..ff31b0b6a6b 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -4510,19 +4510,6 @@ irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs) return IRQ_RETVAL(handled); } -/** - * ata_port_start - Set port up for dma. - * @ap: Port to initialize - * - * Called just after data structures for each port are - * initialized. Allocates space for PRD table. - * - * May be used as the port_start() entry in ata_port_operations. - * - * LOCKING: - * Inherited from caller. - */ - /* * Execute a 'simple' command, that only consists of the opcode 'cmd' itself, * without filling any other registers @@ -4613,6 +4600,19 @@ int ata_device_suspend(struct ata_port *ap, struct ata_device *dev) return 0; } +/** + * ata_port_start - Set port up for dma. + * @ap: Port to initialize + * + * Called just after data structures for each port are + * initialized. Allocates space for PRD table. + * + * May be used as the port_start() entry in ata_port_operations. + * + * LOCKING: + * Inherited from caller. + */ + int ata_port_start (struct ata_port *ap) { struct device *dev = ap->host_set->dev; -- cgit v1.2.3 From 41232d3ecac9df8eb94ff27330eb84b8baccc6b7 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Thu, 9 Feb 2006 04:52:55 -0500 Subject: [libata] build fix after merging some pre-packet_task-removal code --- drivers/scsi/libata-core.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index c93bb1bd333..59d8dd02510 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1087,10 +1087,10 @@ ata_queue_delayed_pio_task(struct ata_port *ap, unsigned long delay) } /** - * ata_flush_pio_tasks - Flush pio_task and packet_task + * ata_flush_pio_tasks - Flush pio_task * @ap: the target ata_port * - * After this function completes, pio_task and packet_task are + * After this function completes, pio_task is * guranteed not to be running or scheduled. * * LOCKING: @@ -1117,7 +1117,6 @@ static void ata_flush_pio_tasks(struct ata_port *ap) * Cancel and flush. */ tmp |= cancel_delayed_work(&ap->pio_task); - tmp |= cancel_delayed_work(&ap->packet_task); if (!tmp) { DPRINTK("flush #2\n"); flush_workqueue(ata_wq); -- cgit v1.2.3 From 587005de144acd3007b8e7f2a2a7c6add157c155 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Sat, 11 Feb 2006 18:17:32 -0500 Subject: [libata irq-pio] s/assert/WARN_ON/ --- drivers/scsi/libata-core.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 3fd55ef5410..bfe0a00b113 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3226,7 +3226,7 @@ static void ata_pio_sectors(struct ata_queued_cmd *qc) /* READ/WRITE MULTIPLE */ unsigned int nsect; - assert(qc->dev->multi_count); + WARN_ON(qc->dev->multi_count == 0); nsect = min(qc->nsect - qc->cursect, qc->dev->multi_count); while (nsect--) @@ -3251,7 +3251,7 @@ static void atapi_send_cdb(struct ata_port *ap, struct ata_queued_cmd *qc) { /* send SCSI cdb */ DPRINTK("send cdb\n"); - assert(ap->cdb_len >= 12); + WARN_ON(ap->cdb_len < 12); ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1); ata_altstatus(ap); /* flush */ @@ -3298,8 +3298,8 @@ static int ata_pio_first_block(struct ata_port *ap) int has_next; qc = ata_qc_from_tag(ap, ap->active_tag); - assert(qc != NULL); - assert(qc->flags & ATA_QCFLAG_ACTIVE); + WARN_ON(qc == NULL); + WARN_ON((qc->flags & ATA_QCFLAG_ACTIVE) == 0); /* if polling, we will stay in the work queue after sending the data. * otherwise, interrupt handler takes over after sending the data. @@ -3945,7 +3945,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc) break; case ATA_PROT_DMA: - assert(!(qc->tf.flags & ATA_TFLAG_POLLING)); + WARN_ON(qc->tf.flags & ATA_TFLAG_POLLING); ap->ops->tf_load(ap, &qc->tf); /* load tf registers */ ap->ops->bmdma_setup(qc); /* set up bmdma */ @@ -3997,7 +3997,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc) break; case ATA_PROT_ATAPI_DMA: - assert(!(qc->tf.flags & ATA_TFLAG_POLLING)); + WARN_ON(qc->tf.flags & ATA_TFLAG_POLLING); ap->ops->tf_load(ap, &qc->tf); /* load tf registers */ ap->ops->bmdma_setup(qc); /* set up bmdma */ @@ -4415,7 +4415,7 @@ fsm_start: /* make sure qc->err_mask is available to * know what's wrong and recover */ - assert(qc->err_mask); + WARN_ON(qc->err_mask == 0); ap->hsm_task_state = HSM_ST_IDLE; ata_qc_complete(qc); -- cgit v1.2.3 From db024d5398cd332023896caf70530564b15ec88e Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Mon, 13 Feb 2006 00:23:57 -0500 Subject: [libata] build fix after cdb_len move --- drivers/scsi/libata-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 5ab220e9907..d1803c91b81 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3282,9 +3282,9 @@ static void atapi_send_cdb(struct ata_port *ap, struct ata_queued_cmd *qc) { /* send SCSI cdb */ DPRINTK("send cdb\n"); - WARN_ON(ap->cdb_len < 12); + WARN_ON(qc->dev->cdb_len < 12); - ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1); + ata_data_xfer(ap, qc->cdb, qc->dev->cdb_len, 1); ata_altstatus(ap); /* flush */ switch (qc->tf.protocol) { -- cgit v1.2.3 From a5fd79ccd60b7c9cc0221dfaaa950933eff6af99 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Mon, 20 Feb 2006 05:21:14 -0500 Subject: sata_vsc build fix --- drivers/scsi/sata_vsc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c index 2d448e84889..5845758e9a6 100644 --- a/drivers/scsi/sata_vsc.c +++ b/drivers/scsi/sata_vsc.c @@ -229,7 +229,7 @@ static irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance, qc = ata_qc_from_tag(ap, ap->active_tag); if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) handled += ata_host_intr(ap, qc); - } else { + else { printk(KERN_DEBUG "%s: ignoring interrupt(s)\n", __FUNCTION__); ata_chk_status(ap); handled++; -- cgit v1.2.3 From c2956a3b0d1c17b38da369811a6ce93eb7a01a04 Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Fri, 3 Mar 2006 10:34:05 +0800 Subject: [PATCH] libata-dev: recognize WRITE_MULTI_FUA_EXT for r/w multiple Recognize ATA_CMD_WRITE_MULTI_FUA_EXT as r/w multiple commands. Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik --- include/linux/ata.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/linux/ata.h b/include/linux/ata.h index 469952366ed..e7b0c21f6cd 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -314,7 +314,8 @@ static inline int is_multi_taskfile(struct ata_taskfile *tf) return (tf->command == ATA_CMD_READ_MULTI) || (tf->command == ATA_CMD_WRITE_MULTI) || (tf->command == ATA_CMD_READ_MULTI_EXT) || - (tf->command == ATA_CMD_WRITE_MULTI_EXT); + (tf->command == ATA_CMD_WRITE_MULTI_EXT) || + (tf->command == ATA_CMD_WRITE_MULTI_FUA_EXT); } static inline int ata_ok(u8 status) -- cgit v1.2.3 From 46e202ec1feeac3cb722cd3410d62a9a00891388 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Sat, 11 Mar 2006 19:25:47 -0500 Subject: libata: irq-pio build fixes --- drivers/scsi/libata-core.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 5060a1a1ad2..1a00c80b96d 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3809,7 +3809,7 @@ fsm_start: if (timeout) ata_port_queue_task(ap, ata_pio_task, ap, timeout); - else if (!qc_completed) + else if (has_next) goto fsm_start; } @@ -3866,7 +3866,8 @@ static void atapi_packet_task(void *_data) * finished. Hence, the following locking. */ spin_lock_irqsave(&ap->host_set->lock, flags); - ap->flags &= ~ATA_FLAG_NOINTR; +#warning FIXME + /* ap->flags &= ~ATA_FLAG_NOINTR; */ ata_data_xfer(ap, qc->cdb, qc->dev->cdb_len, 1); if (qc->tf.protocol == ATA_PROT_ATAPI_DMA) ap->ops->bmdma_start(qc); /* initiate bmdma */ @@ -4200,7 +4201,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc) ap->hsm_task_state = HSM_ST_LAST; if (qc->tf.flags & ATA_TFLAG_POLLING) - ata_queue_pio_task(ap); + ata_port_queue_task(ap, ata_pio_task, ap, 0); break; -- cgit v1.2.3 From 200d5a7684cc49ef4be40e832daf3f217e70dfbb Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 15 Feb 2006 16:24:49 +0900 Subject: [PATCH] libata: increase LBA48 max sectors to 65535 max_hw_sectors/max_sectors separation patch made into the tree, increase max_sectors to its hardware limit. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-scsi.c | 2 +- include/linux/libata.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index dd954a23b35..b53ef494a20 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -678,7 +678,7 @@ static void ata_scsi_dev_config(struct scsi_device *sdev, */ max_sectors = ATA_MAX_SECTORS; if (dev->flags & ATA_DFLAG_LBA48) - max_sectors = 2048; + max_sectors = ATA_MAX_SECTORS_LBA48; if (dev->max_sectors) max_sectors = dev->max_sectors; diff --git a/include/linux/libata.h b/include/linux/libata.h index d81cecdda4f..4dff3cf9d38 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -110,6 +110,7 @@ enum { ATA_DEF_QUEUE = 1, ATA_MAX_QUEUE = 1, ATA_MAX_SECTORS = 200, /* FIXME */ + ATA_MAX_SECTORS_LBA48 = 65535, ATA_MAX_BUS = 2, ATA_DEF_BUSY_WAIT = 10000, ATA_SHORT_PAUSE = (HZ >> 6) + 1, -- cgit v1.2.3 From 84ac69e8bf9f36eb0166817373336d14fa58f5cc Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Fri, 24 Mar 2006 09:27:49 -0500 Subject: [libata] irq-pio: fix build breakage --- drivers/scsi/sata_vsc.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c index 8c818d47c1f..9f621a97c97 100644 --- a/drivers/scsi/sata_vsc.c +++ b/drivers/scsi/sata_vsc.c @@ -229,14 +229,13 @@ static irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance, handled++; } - if (ap && !(ap->flags & - (ATA_FLAG_PORT_DISABLED|ATA_FLAG_NOINTR))) { + if (ap && !(ap->flags & ATA_FLAG_PORT_DISABLED)) { struct ata_queued_cmd *qc; qc = ata_qc_from_tag(ap, ap->active_tag); if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) handled += ata_host_intr(ap, qc); - } else if (is_vsc_sata_int_err(i, int_status)) { + else if (is_vsc_sata_int_err(i, int_status)) { /* * On some chips (i.e. Intel 31244), an error * interrupt will sneak in at initialization -- cgit v1.2.3 From 9cfda2c94df61c9f859b474abe774c65a4464d0a Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Mon, 27 Mar 2006 02:24:32 -0500 Subject: [ACPI] fix "nolapic" flag in ACPI mode Signed-off-by: Len Brown --- arch/i386/kernel/acpi/boot.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c index 033066176b3..d0980c79a5d 100644 --- a/arch/i386/kernel/acpi/boot.c +++ b/arch/i386/kernel/acpi/boot.c @@ -215,7 +215,7 @@ static int __init acpi_parse_madt(unsigned long phys_addr, unsigned long size) { struct acpi_table_madt *madt = NULL; - if (!phys_addr || !size) + if (!phys_addr || !size || !cpu_has_apic) return -EINVAL; madt = (struct acpi_table_madt *)__acpi_map_table(phys_addr, size); @@ -751,6 +751,9 @@ static int __init acpi_parse_madt_ioapic_entries(void) return -ENODEV; } + if (!cpu_has_apic) + return -ENODEV; + /* * if "noapic" boot option, don't look for IO-APICs */ -- cgit v1.2.3 From cf2f7689f94ee02e52d5331bc1a87421a67a882c Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Sat, 25 Mar 2006 17:37:53 +0800 Subject: [PATCH] libata-dev: Remove trailing whitespaces Remove trailing whitespaces. Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index c3c4263fdb1..76418289aa7 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -4397,7 +4397,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap, fsm_start: switch (ap->hsm_task_state) { case HSM_ST_FIRST: - /* Some pre-ATAPI-4 devices assert INTRQ + /* Some pre-ATAPI-4 devices assert INTRQ * at this state when ready to receive CDB. */ @@ -4422,7 +4422,7 @@ fsm_start: ap->hsm_task_state = HSM_ST_LAST; goto fsm_start; } - + atapi_pio_bytes(qc); if (unlikely(ap->hsm_task_state == HSM_ST_ERR)) @@ -4476,7 +4476,7 @@ fsm_start: printk(KERN_ERR "ata%u: command error, drv_stat 0x%x host_stat 0x%x\n", ap->id, status, host_stat); - /* make sure qc->err_mask is available to + /* make sure qc->err_mask is available to * know what's wrong and recover */ WARN_ON(qc->err_mask == 0); -- cgit v1.2.3 From 13ee4628ce68d1e54df01cc31239c8887c59e65d Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Sat, 25 Mar 2006 17:39:34 +0800 Subject: [PATCH] libata-dev: Fix merge problem with upstream Fix merge problem with upstream. Changes: 1. add missing dev->cdb_len = 16 for ATA devices 2. use ata_pio_task instead of atapi_packet_task Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 76418289aa7..9ef5b8ab5b1 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1299,6 +1299,7 @@ static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev, ap->id, device, dev->multi_count); } + dev->cdb_len = 16; } /* ATAPI-specific feature tests */ @@ -4288,7 +4289,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc) /* send cdb by polling if no cdb interrupt */ if ((!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) || (qc->tf.flags & ATA_TFLAG_POLLING)) - ata_port_queue_task(ap, atapi_packet_task, ap, 0); + ata_port_queue_task(ap, ata_pio_task, ap, 0); break; case ATA_PROT_ATAPI_DMA: @@ -4300,7 +4301,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc) /* send cdb by polling if no cdb interrupt */ if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) - ata_port_queue_task(ap, atapi_packet_task, ap, 0); + ata_port_queue_task(ap, ata_pio_task, ap, 0); break; default: -- cgit v1.2.3 From 19d5d7309a928eb86f58b37165a2d501621ae3c0 Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Sat, 25 Mar 2006 17:41:43 +0800 Subject: [PATCH] libata-dev: Remove atapi_packet_task() atapi_packet_task() was replaced by ata_pio_task(). Remove the unused atapi_packet_task(). Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 73 ---------------------------------------------- 1 file changed, 73 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 9ef5b8ab5b1..0eb75e2dc0e 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3849,79 +3849,6 @@ fsm_start: goto fsm_start; } -/** - * atapi_packet_task - Write CDB bytes to hardware - * @_data: Port to which ATAPI device is attached. - * - * When device has indicated its readiness to accept - * a CDB, this function is called. Send the CDB. - * If DMA is to be performed, exit immediately. - * Otherwise, we are in polling mode, so poll - * status under operation succeeds or fails. - * - * LOCKING: - * Kernel thread context (may sleep) - */ - -static void atapi_packet_task(void *_data) -{ - struct ata_port *ap = _data; - struct ata_queued_cmd *qc; - u8 status; - - qc = ata_qc_from_tag(ap, ap->active_tag); - WARN_ON(qc == NULL); - WARN_ON(!(qc->flags & ATA_QCFLAG_ACTIVE)); - - /* sleep-wait for BSY to clear */ - DPRINTK("busy wait\n"); - if (ata_busy_sleep(ap, ATA_TMOUT_CDB_QUICK, ATA_TMOUT_CDB)) { - qc->err_mask |= AC_ERR_TIMEOUT; - goto err_out; - } - - /* make sure DRQ is set */ - status = ata_chk_status(ap); - if ((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ) { - qc->err_mask |= AC_ERR_HSM; - goto err_out; - } - - /* send SCSI cdb */ - DPRINTK("send cdb\n"); - WARN_ON(qc->dev->cdb_len < 12); - - if (qc->tf.protocol == ATA_PROT_ATAPI_DMA || - qc->tf.protocol == ATA_PROT_ATAPI_NODATA) { - unsigned long flags; - - /* Once we're done issuing command and kicking bmdma, - * irq handler takes over. To not lose irq, we need - * to clear NOINTR flag before sending cdb, but - * interrupt handler shouldn't be invoked before we're - * finished. Hence, the following locking. - */ - spin_lock_irqsave(&ap->host_set->lock, flags); -#warning FIXME - /* ap->flags &= ~ATA_FLAG_NOINTR; */ - ata_data_xfer(ap, qc->cdb, qc->dev->cdb_len, 1); - if (qc->tf.protocol == ATA_PROT_ATAPI_DMA) - ap->ops->bmdma_start(qc); /* initiate bmdma */ - spin_unlock_irqrestore(&ap->host_set->lock, flags); - } else { - ata_data_xfer(ap, qc->cdb, qc->dev->cdb_len, 1); - - /* PIO commands are handled by polling */ - ap->hsm_task_state = HSM_ST; - ata_port_queue_task(ap, ata_pio_task, ap, 0); - } - - return; - -err_out: - ata_poll_qc_complete(qc); -} - /** * ata_qc_timeout - Handle timeout of queued command * @qc: Command that timed out -- cgit v1.2.3 From e2cec77117a6e4fcbac2601e2f7b0b3f4f5a4c84 Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Sat, 25 Mar 2006 17:43:49 +0800 Subject: [PATCH] libata-dev: Move out the HSM code from ata_host_intr() Move out the irq-pio HSM code from ata_host_intr() to the new ata_hsm_move() function verbatim. Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 206 +++++++++++++++++++++++---------------------- 1 file changed, 106 insertions(+), 100 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 0eb75e2dc0e..7214530ac16 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3805,6 +3805,111 @@ static void ata_pio_error(struct ata_port *ap) ata_poll_qc_complete(qc); } +static void ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc, + u8 status) +{ + /* check error */ + if (unlikely(status & (ATA_ERR | ATA_DF))) { + qc->err_mask |= AC_ERR_DEV; + ap->hsm_task_state = HSM_ST_ERR; + } + +fsm_start: + switch (ap->hsm_task_state) { + case HSM_ST_FIRST: + /* Some pre-ATAPI-4 devices assert INTRQ + * at this state when ready to receive CDB. + */ + + /* check device status */ + if (unlikely((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ)) { + /* Wrong status. Let EH handle this */ + qc->err_mask |= AC_ERR_HSM; + ap->hsm_task_state = HSM_ST_ERR; + goto fsm_start; + } + + atapi_send_cdb(ap, qc); + + break; + + case HSM_ST: + /* complete command or read/write the data register */ + if (qc->tf.protocol == ATA_PROT_ATAPI) { + /* ATAPI PIO protocol */ + if ((status & ATA_DRQ) == 0) { + /* no more data to transfer */ + ap->hsm_task_state = HSM_ST_LAST; + goto fsm_start; + } + + atapi_pio_bytes(qc); + + if (unlikely(ap->hsm_task_state == HSM_ST_ERR)) + /* bad ireason reported by device */ + goto fsm_start; + + } else { + /* ATA PIO protocol */ + if (unlikely((status & ATA_DRQ) == 0)) { + /* handle BSY=0, DRQ=0 as error */ + qc->err_mask |= AC_ERR_HSM; + ap->hsm_task_state = HSM_ST_ERR; + goto fsm_start; + } + + ata_pio_sectors(qc); + + if (ap->hsm_task_state == HSM_ST_LAST && + (!(qc->tf.flags & ATA_TFLAG_WRITE))) { + /* all data read */ + ata_altstatus(ap); + status = ata_chk_status(ap); + goto fsm_start; + } + } + + ata_altstatus(ap); /* flush */ + break; + + case HSM_ST_LAST: + if (unlikely(status & ATA_DRQ)) { + /* handle DRQ=1 as error */ + qc->err_mask |= AC_ERR_HSM; + ap->hsm_task_state = HSM_ST_ERR; + goto fsm_start; + } + + /* no more data to transfer */ + DPRINTK("ata%u: command complete, drv_stat 0x%x\n", + ap->id, status); + + ap->hsm_task_state = HSM_ST_IDLE; + + /* complete taskfile transaction */ + qc->err_mask |= ac_err_mask(status); + ata_qc_complete(qc); + break; + + case HSM_ST_ERR: + if (qc->tf.command != ATA_CMD_PACKET) + printk(KERN_ERR "ata%u: command error, drv_stat 0x%x host_stat 0x%x\n", + ap->id, status, host_stat); + + /* make sure qc->err_mask is available to + * know what's wrong and recover + */ + WARN_ON(qc->err_mask == 0); + + ap->hsm_task_state = HSM_ST_IDLE; + ata_qc_complete(qc); + break; + default: + goto idle_irq; + } + +} + static void ata_pio_task(void *_data) { struct ata_port *ap = _data; @@ -4316,106 +4421,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap, /* ack bmdma irq events */ ap->ops->irq_clear(ap); - /* check error */ - if (unlikely(status & (ATA_ERR | ATA_DF))) { - qc->err_mask |= AC_ERR_DEV; - ap->hsm_task_state = HSM_ST_ERR; - } - -fsm_start: - switch (ap->hsm_task_state) { - case HSM_ST_FIRST: - /* Some pre-ATAPI-4 devices assert INTRQ - * at this state when ready to receive CDB. - */ - - /* check device status */ - if (unlikely((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ)) { - /* Wrong status. Let EH handle this */ - qc->err_mask |= AC_ERR_HSM; - ap->hsm_task_state = HSM_ST_ERR; - goto fsm_start; - } - - atapi_send_cdb(ap, qc); - - break; - - case HSM_ST: - /* complete command or read/write the data register */ - if (qc->tf.protocol == ATA_PROT_ATAPI) { - /* ATAPI PIO protocol */ - if ((status & ATA_DRQ) == 0) { - /* no more data to transfer */ - ap->hsm_task_state = HSM_ST_LAST; - goto fsm_start; - } - - atapi_pio_bytes(qc); - - if (unlikely(ap->hsm_task_state == HSM_ST_ERR)) - /* bad ireason reported by device */ - goto fsm_start; - - } else { - /* ATA PIO protocol */ - if (unlikely((status & ATA_DRQ) == 0)) { - /* handle BSY=0, DRQ=0 as error */ - qc->err_mask |= AC_ERR_HSM; - ap->hsm_task_state = HSM_ST_ERR; - goto fsm_start; - } - - ata_pio_sectors(qc); - - if (ap->hsm_task_state == HSM_ST_LAST && - (!(qc->tf.flags & ATA_TFLAG_WRITE))) { - /* all data read */ - ata_altstatus(ap); - status = ata_chk_status(ap); - goto fsm_start; - } - } - - ata_altstatus(ap); /* flush */ - break; - - case HSM_ST_LAST: - if (unlikely(status & ATA_DRQ)) { - /* handle DRQ=1 as error */ - qc->err_mask |= AC_ERR_HSM; - ap->hsm_task_state = HSM_ST_ERR; - goto fsm_start; - } - - /* no more data to transfer */ - DPRINTK("ata%u: command complete, drv_stat 0x%x\n", - ap->id, status); - - ap->hsm_task_state = HSM_ST_IDLE; - - /* complete taskfile transaction */ - qc->err_mask |= ac_err_mask(status); - ata_qc_complete(qc); - break; - - case HSM_ST_ERR: - if (qc->tf.command != ATA_CMD_PACKET) - printk(KERN_ERR "ata%u: command error, drv_stat 0x%x host_stat 0x%x\n", - ap->id, status, host_stat); - - /* make sure qc->err_mask is available to - * know what's wrong and recover - */ - WARN_ON(qc->err_mask == 0); - - ap->hsm_task_state = HSM_ST_IDLE; - ata_qc_complete(qc); - break; - default: - goto idle_irq; - } - + ata_hsm_move(ap, qc, status); return 1; /* irq handled */ idle_irq: -- cgit v1.2.3 From 6912ccd5a4a095d71fd7215ef2abea877c8fed6f Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Sat, 25 Mar 2006 17:45:49 +0800 Subject: [PATCH] libata-dev: Minor fix for ata_hsm_move() to work with ata_host_intr() Minor fix for ata_hsm_move() to work with ata_host_intr(). Changes: - WARN_ON() and comment fix - Make the HSM_ST_LAST device status checking more rigid. - Treat unknown HSM state as BUG(). Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 7214530ac16..094c7907534 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3808,6 +3808,8 @@ static void ata_pio_error(struct ata_port *ap) static void ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc, u8 status) { + WARN_ON((qc->flags & ATA_QCFLAG_ACTIVE) == 0); + /* check error */ if (unlikely(status & (ATA_ERR | ATA_DF))) { qc->err_mask |= AC_ERR_DEV; @@ -3817,10 +3819,6 @@ static void ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc, fsm_start: switch (ap->hsm_task_state) { case HSM_ST_FIRST: - /* Some pre-ATAPI-4 devices assert INTRQ - * at this state when ready to receive CDB. - */ - /* check device status */ if (unlikely((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ)) { /* Wrong status. Let EH handle this */ @@ -3873,9 +3871,8 @@ fsm_start: break; case HSM_ST_LAST: - if (unlikely(status & ATA_DRQ)) { - /* handle DRQ=1 as error */ - qc->err_mask |= AC_ERR_HSM; + if (unlikely(!ata_ok(status))) { + qc->err_mask |= __ac_err_mask(status); ap->hsm_task_state = HSM_ST_ERR; goto fsm_start; } @@ -3884,17 +3881,18 @@ fsm_start: DPRINTK("ata%u: command complete, drv_stat 0x%x\n", ap->id, status); + WARN_ON(qc->err_mask); + ap->hsm_task_state = HSM_ST_IDLE; /* complete taskfile transaction */ - qc->err_mask |= ac_err_mask(status); ata_qc_complete(qc); break; case HSM_ST_ERR: if (qc->tf.command != ATA_CMD_PACKET) - printk(KERN_ERR "ata%u: command error, drv_stat 0x%x host_stat 0x%x\n", - ap->id, status, host_stat); + printk(KERN_ERR "ata%u: command error, drv_stat 0x%x\n", + ap->id, status); /* make sure qc->err_mask is available to * know what's wrong and recover @@ -3905,7 +3903,7 @@ fsm_start: ata_qc_complete(qc); break; default: - goto idle_irq; + BUG(); } } @@ -4371,6 +4369,10 @@ inline unsigned int ata_host_intr (struct ata_port *ap, /* Check whether we are expecting interrupt in this state */ switch (ap->hsm_task_state) { case HSM_ST_FIRST: + /* Some pre-ATAPI-4 devices assert INTRQ + * at this state when ready to receive CDB. + */ + /* Check the ATA_DFLAG_CDB_INTR flag is enough here. * The flag was turned on only for atapi devices. * No need to check is_atapi_taskfile(&qc->tf) again. -- cgit v1.2.3 From bb5cb290f095f17f88c912e3da35adf5b2d9500b Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Sat, 25 Mar 2006 17:48:02 +0800 Subject: [PATCH] libata-dev: Let ata_hsm_move() work with both irq-pio and polling pio Let ata_hsm_move() work with both irq-pio and polling pio codepath. Changes: - add a new parameter "in_wq" for polling pio - add return value "poll_next" to tell polling pio task whether the HSM is finished - merge code from ata_pio_first_block() to the HSM_ST_FIRST state. - call ata_poll_qc_complete() if called from the workqueue Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 87 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 81 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 094c7907534..33b39d3ce2d 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3805,11 +3805,36 @@ static void ata_pio_error(struct ata_port *ap) ata_poll_qc_complete(qc); } -static void ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc, - u8 status) +/** + * ata_hsm_move - move the HSM to the next state. + * @ap: the target ata_port + * @qc: qc on going + * @status: current device status + * @in_wq: 1 if called from workqueue, 0 otherwise + * + * RETURNS: + * 1 when poll next status needed, 0 otherwise. + */ + +static int ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc, + u8 status, int in_wq) { + unsigned long flags = 0; + int poll_next; + WARN_ON((qc->flags & ATA_QCFLAG_ACTIVE) == 0); + /* Make sure ata_qc_issue_prot() does not throw things + * like DMA polling into the workqueue. Notice that + * in_wq is not equivalent to (qc->tf.flags & ATA_TFLAG_POLLING). + */ + WARN_ON(in_wq != ((qc->tf.flags & ATA_TFLAG_POLLING) || + (ap->hsm_task_state == HSM_ST_FIRST && + ((qc->tf.protocol == ATA_PROT_PIO && + (qc->tf.flags & ATA_TFLAG_WRITE)) || + (is_atapi_taskfile(&qc->tf) && + !(qc->dev->flags & ATA_DFLAG_CDB_INTR)))))); + /* check error */ if (unlikely(status & (ATA_ERR | ATA_DF))) { qc->err_mask |= AC_ERR_DEV; @@ -3819,6 +3844,14 @@ static void ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc, fsm_start: switch (ap->hsm_task_state) { case HSM_ST_FIRST: + /* Send first data block or PACKET CDB */ + + /* If polling, we will stay in the work queue after + * sending the data. Otherwise, interrupt handler + * takes over after sending the data. + */ + poll_next = (qc->tf.flags & ATA_TFLAG_POLLING); + /* check device status */ if (unlikely((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ)) { /* Wrong status. Let EH handle this */ @@ -3827,8 +3860,36 @@ fsm_start: goto fsm_start; } - atapi_send_cdb(ap, qc); + /* Send the CDB (atapi) or the first data block (ata pio out). + * During the state transition, interrupt handler shouldn't + * be invoked before the data transfer is complete and + * hsm_task_state is changed. Hence, the following locking. + */ + if (in_wq) + spin_lock_irqsave(&ap->host_set->lock, flags); + + if (qc->tf.protocol == ATA_PROT_PIO) { + /* PIO data out protocol. + * send first data block. + */ + /* ata_pio_sectors() might change the state + * to HSM_ST_LAST. so, the state is changed here + * before ata_pio_sectors(). + */ + ap->hsm_task_state = HSM_ST; + ata_pio_sectors(qc); + ata_altstatus(ap); /* flush */ + } else + /* send CDB */ + atapi_send_cdb(ap, qc); + + if (in_wq) + spin_unlock_irqrestore(&ap->host_set->lock, flags); + + /* if polling, ata_pio_task() handles the rest. + * otherwise, interrupt handler takes over from here. + */ break; case HSM_ST: @@ -3868,6 +3929,7 @@ fsm_start: } ata_altstatus(ap); /* flush */ + poll_next = 1; break; case HSM_ST_LAST: @@ -3886,7 +3948,12 @@ fsm_start: ap->hsm_task_state = HSM_ST_IDLE; /* complete taskfile transaction */ - ata_qc_complete(qc); + if (in_wq) + ata_poll_qc_complete(qc); + else + ata_qc_complete(qc); + + poll_next = 0; break; case HSM_ST_ERR: @@ -3900,12 +3967,20 @@ fsm_start: WARN_ON(qc->err_mask == 0); ap->hsm_task_state = HSM_ST_IDLE; - ata_qc_complete(qc); + + if (in_wq) + ata_poll_qc_complete(qc); + else + ata_qc_complete(qc); + + poll_next = 0; break; default: + poll_next = 0; BUG(); } + return poll_next; } static void ata_pio_task(void *_data) @@ -4423,7 +4498,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap, /* ack bmdma irq events */ ap->ops->irq_clear(ap); - ata_hsm_move(ap, qc, status); + ata_hsm_move(ap, qc, status, 0); return 1; /* irq handled */ idle_irq: -- cgit v1.2.3 From a1af37344f669d0fefa8c8a9e37eb6a7c086a2c2 Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Sat, 25 Mar 2006 17:50:15 +0800 Subject: [PATCH] libata-dev: Convert ata_pio_task() to use the new ata_hsm_move() Convert ata_pio_task() to use the new ata_hsm_move(). Changes: - refactor ata_pio_task() to poll device status register and - call the new ata_hsm_move() when device indicates it is not BSY. Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 60 ++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 32 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 33b39d3ce2d..eeeeda0481a 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3986,44 +3986,40 @@ fsm_start: static void ata_pio_task(void *_data) { struct ata_port *ap = _data; - unsigned long timeout; - int has_next; + struct ata_queued_cmd *qc; + u8 status; + int poll_next; fsm_start: - timeout = 0; - has_next = 1; + WARN_ON(ap->hsm_task_state == HSM_ST_IDLE); - switch (ap->hsm_task_state) { - case HSM_ST_FIRST: - has_next = ata_pio_first_block(ap); - break; - - case HSM_ST: - ata_pio_block(ap); - break; - - case HSM_ST_LAST: - has_next = ata_pio_complete(ap); - break; - - case HSM_ST_POLL: - case HSM_ST_LAST_POLL: - timeout = ata_pio_poll(ap); - break; - - case HSM_ST_TMOUT: - case HSM_ST_ERR: - ata_pio_error(ap); - return; + qc = ata_qc_from_tag(ap, ap->active_tag); + WARN_ON(qc == NULL); - default: - BUG(); - return; + /* + * This is purely heuristic. This is a fast path. + * Sometimes when we enter, BSY will be cleared in + * a chk-status or two. If not, the drive is probably seeking + * or something. Snooze for a couple msecs, then + * chk-status again. If still busy, queue delayed work. + */ + status = ata_busy_wait(ap, ATA_BUSY, 5); + if (status & ATA_BUSY) { + msleep(2); + status = ata_busy_wait(ap, ATA_BUSY, 10); + if (status & ATA_BUSY) { + ata_port_queue_task(ap, ata_pio_task, ap, ATA_SHORT_PAUSE); + return; + } } - if (timeout) - ata_port_queue_task(ap, ata_pio_task, ap, timeout); - else if (has_next) + /* move the HSM */ + poll_next = ata_hsm_move(ap, qc, status, 1); + + /* another command or interrupt handler + * may be running at this point. + */ + if (poll_next) goto fsm_start; } -- cgit v1.2.3 From 27cdadef6dfe0d0614653919a110fc75ab1650ce Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Sat, 25 Mar 2006 17:53:57 +0800 Subject: [PATCH] libata-dev: Cleanup unused enums/functions Cleanup the following unused functions: - ata_pio_poll() - ata_pio_complete() - ata_pio_first_block() - ata_pio_block() - ata_pio_error() ap->pio_task_timeout and other enums. Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 279 --------------------------------------------- include/linux/libata.h | 9 -- 2 files changed, 288 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index eeeeda0481a..ef0d0dd90e1 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -67,7 +67,6 @@ static void ata_set_mode(struct ata_port *ap); static unsigned int ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev); static void ata_dev_xfermask(struct ata_port *ap, struct ata_device *dev); -static void ata_pio_error(struct ata_port *ap); static unsigned int ata_unique_id = 1; static struct workqueue_struct *ata_wq; @@ -3131,114 +3130,6 @@ void ata_poll_qc_complete(struct ata_queued_cmd *qc) spin_unlock_irqrestore(&ap->host_set->lock, flags); } -/** - * ata_pio_poll - poll using PIO, depending on current state - * @ap: the target ata_port - * - * LOCKING: - * None. (executing in kernel thread context) - * - * RETURNS: - * timeout value to use - */ - -static unsigned long ata_pio_poll(struct ata_port *ap) -{ - struct ata_queued_cmd *qc; - u8 status; - unsigned int poll_state = HSM_ST_UNKNOWN; - unsigned int reg_state = HSM_ST_UNKNOWN; - - qc = ata_qc_from_tag(ap, ap->active_tag); - WARN_ON(qc == NULL); - - switch (ap->hsm_task_state) { - case HSM_ST: - case HSM_ST_POLL: - poll_state = HSM_ST_POLL; - reg_state = HSM_ST; - break; - case HSM_ST_LAST: - case HSM_ST_LAST_POLL: - poll_state = HSM_ST_LAST_POLL; - reg_state = HSM_ST_LAST; - break; - default: - BUG(); - break; - } - - status = ata_chk_status(ap); - if (status & ATA_BUSY) { - if (time_after(jiffies, ap->pio_task_timeout)) { - qc->err_mask |= AC_ERR_TIMEOUT; - ap->hsm_task_state = HSM_ST_TMOUT; - return 0; - } - ap->hsm_task_state = poll_state; - return ATA_SHORT_PAUSE; - } - - ap->hsm_task_state = reg_state; - return 0; -} - -/** - * ata_pio_complete - check if drive is busy or idle - * @ap: the target ata_port - * - * LOCKING: - * None. (executing in kernel thread context) - * - * RETURNS: - * Zero if qc completed. - * Non-zero if has next. - */ - -static int ata_pio_complete (struct ata_port *ap) -{ - struct ata_queued_cmd *qc; - u8 drv_stat; - - /* - * This is purely heuristic. This is a fast path. Sometimes when - * we enter, BSY will be cleared in a chk-status or two. If not, - * the drive is probably seeking or something. Snooze for a couple - * msecs, then chk-status again. If still busy, fall back to - * HSM_ST_LAST_POLL state. - */ - drv_stat = ata_busy_wait(ap, ATA_BUSY, 10); - if (drv_stat & ATA_BUSY) { - msleep(2); - drv_stat = ata_busy_wait(ap, ATA_BUSY, 10); - if (drv_stat & ATA_BUSY) { - ap->hsm_task_state = HSM_ST_LAST_POLL; - ap->pio_task_timeout = jiffies + ATA_TMOUT_PIO; - return 1; - } - } - - qc = ata_qc_from_tag(ap, ap->active_tag); - WARN_ON(qc == NULL); - - drv_stat = ata_wait_idle(ap); - if (!ata_ok(drv_stat)) { - qc->err_mask |= __ac_err_mask(drv_stat); - ap->hsm_task_state = HSM_ST_ERR; - return 1; - } - - ap->hsm_task_state = HSM_ST_IDLE; - - WARN_ON(qc->err_mask); - ata_poll_qc_complete(qc); - - /* another command may start at this point */ - - return 0; -} - - /** * swap_buf_le16 - swap halves of 16-bit words in place * @buf: Buffer to swap @@ -3496,91 +3387,6 @@ static void atapi_send_cdb(struct ata_port *ap, struct ata_queued_cmd *qc) } } -/** - * ata_pio_first_block - Write first data block to hardware - * @ap: Port to which ATA/ATAPI device is attached. - * - * When device has indicated its readiness to accept - * the data, this function sends out the CDB or - * the first data block by PIO. - * After this, - * - If polling, ata_pio_task() handles the rest. - * - Otherwise, interrupt handler takes over. - * - * LOCKING: - * Kernel thread context (may sleep) - * - * RETURNS: - * Zero if irq handler takes over - * Non-zero if has next (polling). - */ - -static int ata_pio_first_block(struct ata_port *ap) -{ - struct ata_queued_cmd *qc; - u8 status; - unsigned long flags; - int has_next; - - qc = ata_qc_from_tag(ap, ap->active_tag); - WARN_ON(qc == NULL); - WARN_ON((qc->flags & ATA_QCFLAG_ACTIVE) == 0); - - /* if polling, we will stay in the work queue after sending the data. - * otherwise, interrupt handler takes over after sending the data. - */ - has_next = (qc->tf.flags & ATA_TFLAG_POLLING); - - /* sleep-wait for BSY to clear */ - DPRINTK("busy wait\n"); - if (ata_busy_sleep(ap, ATA_TMOUT_DATAOUT_QUICK, ATA_TMOUT_DATAOUT)) { - qc->err_mask |= AC_ERR_TIMEOUT; - ap->hsm_task_state = HSM_ST_TMOUT; - goto err_out; - } - - /* make sure DRQ is set */ - status = ata_chk_status(ap); - if ((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ) { - /* device status error */ - qc->err_mask |= AC_ERR_HSM; - ap->hsm_task_state = HSM_ST_ERR; - goto err_out; - } - - /* Send the CDB (atapi) or the first data block (ata pio out). - * During the state transition, interrupt handler shouldn't - * be invoked before the data transfer is complete and - * hsm_task_state is changed. Hence, the following locking. - */ - spin_lock_irqsave(&ap->host_set->lock, flags); - - if (qc->tf.protocol == ATA_PROT_PIO) { - /* PIO data out protocol. - * send first data block. - */ - - /* ata_pio_sectors() might change the state to HSM_ST_LAST. - * so, the state is changed here before ata_pio_sectors(). - */ - ap->hsm_task_state = HSM_ST; - ata_pio_sectors(qc); - ata_altstatus(ap); /* flush */ - } else - /* send CDB */ - atapi_send_cdb(ap, qc); - - spin_unlock_irqrestore(&ap->host_set->lock, flags); - - /* if polling, ata_pio_task() handles the rest. - * otherwise, interrupt handler takes over from here. - */ - return has_next; - -err_out: - return 1; /* has next */ -} - /** * __atapi_pio_bytes - Transfer data from/to the ATAPI device. * @qc: Command on going @@ -3720,91 +3526,6 @@ err_out: ap->hsm_task_state = HSM_ST_ERR; } -/** - * ata_pio_block - start PIO on a block - * @ap: the target ata_port - * - * LOCKING: - * None. (executing in kernel thread context) - */ - -static void ata_pio_block(struct ata_port *ap) -{ - struct ata_queued_cmd *qc; - u8 status; - - /* - * This is purely heuristic. This is a fast path. - * Sometimes when we enter, BSY will be cleared in - * a chk-status or two. If not, the drive is probably seeking - * or something. Snooze for a couple msecs, then - * chk-status again. If still busy, fall back to - * HSM_ST_POLL state. - */ - status = ata_busy_wait(ap, ATA_BUSY, 5); - if (status & ATA_BUSY) { - msleep(2); - status = ata_busy_wait(ap, ATA_BUSY, 10); - if (status & ATA_BUSY) { - ap->hsm_task_state = HSM_ST_POLL; - ap->pio_task_timeout = jiffies + ATA_TMOUT_PIO; - return; - } - } - - qc = ata_qc_from_tag(ap, ap->active_tag); - WARN_ON(qc == NULL); - - /* check error */ - if (status & (ATA_ERR | ATA_DF)) { - qc->err_mask |= AC_ERR_DEV; - ap->hsm_task_state = HSM_ST_ERR; - return; - } - - /* transfer data if any */ - if (is_atapi_taskfile(&qc->tf)) { - /* DRQ=0 means no more data to transfer */ - if ((status & ATA_DRQ) == 0) { - ap->hsm_task_state = HSM_ST_LAST; - return; - } - - atapi_pio_bytes(qc); - } else { - /* handle BSY=0, DRQ=0 as error */ - if ((status & ATA_DRQ) == 0) { - qc->err_mask |= AC_ERR_HSM; - ap->hsm_task_state = HSM_ST_ERR; - return; - } - - ata_pio_sectors(qc); - } - - ata_altstatus(ap); /* flush */ -} - -static void ata_pio_error(struct ata_port *ap) -{ - struct ata_queued_cmd *qc; - - qc = ata_qc_from_tag(ap, ap->active_tag); - WARN_ON(qc == NULL); - - if (qc->tf.command != ATA_CMD_PACKET) - printk(KERN_WARNING "ata%u: PIO error\n", ap->id); - - /* make sure qc->err_mask is available to - * know what's wrong and recover - */ - WARN_ON(qc->err_mask == 0); - - ap->hsm_task_state = HSM_ST_IDLE; - - ata_poll_qc_complete(qc); -} - /** * ata_hsm_move - move the HSM to the next state. * @ap: the target ata_port diff --git a/include/linux/libata.h b/include/linux/libata.h index 70ca99bbc6c..0eb71c1773a 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -162,13 +162,8 @@ enum { ATA_QCFLAG_EH_SCHEDULED = (1 << 5), /* EH scheduled */ /* various lengths of time */ - ATA_TMOUT_PIO = 30 * HZ, ATA_TMOUT_BOOT = 30 * HZ, /* heuristic */ ATA_TMOUT_BOOT_QUICK = 7 * HZ, /* heuristic */ - ATA_TMOUT_DATAOUT = 30 * HZ, - ATA_TMOUT_DATAOUT_QUICK = 5 * HZ, - ATA_TMOUT_CDB = 30 * HZ, - ATA_TMOUT_CDB_QUICK = 5 * HZ, ATA_TMOUT_INTERNAL = 30 * HZ, ATA_TMOUT_INTERNAL_QUICK = 5 * HZ, @@ -216,11 +211,8 @@ enum { enum hsm_task_states { HSM_ST_UNKNOWN, /* state unknown */ HSM_ST_IDLE, /* no command on going */ - HSM_ST_POLL, /* same as HSM_ST, waits longer */ - HSM_ST_TMOUT, /* timeout */ HSM_ST, /* (waiting the device to) transfer data */ HSM_ST_LAST, /* (waiting the device to) complete command */ - HSM_ST_LAST_POLL, /* same as HSM_ST_LAST, waits longer */ HSM_ST_ERR, /* error */ HSM_ST_FIRST, /* (waiting the device to) write CDB or first data block */ @@ -409,7 +401,6 @@ struct ata_port { struct work_struct port_task; unsigned int hsm_task_state; - unsigned long pio_task_timeout; u32 msg_enable; struct list_head eh_done_q; -- cgit v1.2.3 From c2bbc551615c21a4c280c797987dbb50f2701594 Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Sat, 25 Mar 2006 17:56:55 +0800 Subject: [PATCH] libata-dev: ata_check_atapi_dma() fix for ATA_FLAG_PIO_POLLING LLDDs ata_check_atapi_dma() fix for LLDDs with the ATA_FLAG_PIO_POLLING flag. Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index ef0d0dd90e1..61c120dae74 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2883,6 +2883,15 @@ int ata_check_atapi_dma(struct ata_queued_cmd *qc) if (ap->ops->check_atapi_dma) rc = ap->ops->check_atapi_dma(qc); + /* We don't support polling DMA. + * Use PIO if the LLDD handles only interrupts in + * the HSM_ST_LAST state and the ATAPI device + * generates CDB interrupts. + */ + if ((ap->flags & ATA_FLAG_PIO_POLLING) && + (qc->dev->flags & ATA_DFLAG_CDB_INTR)) + rc = 1; + return rc; } /** @@ -4038,6 +4047,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc) break; case ATA_PROT_ATAPI_DMA: if (qc->dev->flags & ATA_DFLAG_CDB_INTR) + /* see ata_check_atapi_dma() */ BUG(); break; default: -- cgit v1.2.3 From c234fb00ea8999076728137d96603b713ad8b53f Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Sat, 25 Mar 2006 17:58:38 +0800 Subject: [PATCH] libata-dev: Make the the in_wq check as an inline function Make the the in_wq check easier to read as an inline function. Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 61c120dae74..27078c06119 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3535,6 +3535,33 @@ err_out: ap->hsm_task_state = HSM_ST_ERR; } +/** + * ata_hsm_ok_in_wq - Check if the qc can be handled in the workqueue. + * @ap: the target ata_port + * @qc: qc on going + * + * RETURNS: + * 1 if ok in workqueue, 0 otherwise. + */ + +static inline int ata_hsm_ok_in_wq(struct ata_port *ap, struct ata_queued_cmd *qc) +{ + if (qc->tf.flags & ATA_TFLAG_POLLING) + return 1; + + if (ap->hsm_task_state == HSM_ST_FIRST) { + if (qc->tf.protocol == ATA_PROT_PIO && + (qc->tf.flags & ATA_TFLAG_WRITE)) + return 1; + + if (is_atapi_taskfile(&qc->tf) && + !(qc->dev->flags & ATA_DFLAG_CDB_INTR)) + return 1; + } + + return 0; +} + /** * ata_hsm_move - move the HSM to the next state. * @ap: the target ata_port @@ -3558,12 +3585,7 @@ static int ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc, * like DMA polling into the workqueue. Notice that * in_wq is not equivalent to (qc->tf.flags & ATA_TFLAG_POLLING). */ - WARN_ON(in_wq != ((qc->tf.flags & ATA_TFLAG_POLLING) || - (ap->hsm_task_state == HSM_ST_FIRST && - ((qc->tf.protocol == ATA_PROT_PIO && - (qc->tf.flags & ATA_TFLAG_WRITE)) || - (is_atapi_taskfile(&qc->tf) && - !(qc->dev->flags & ATA_DFLAG_CDB_INTR)))))); + WARN_ON(in_wq != ata_hsm_ok_in_wq(ap, qc)); /* check error */ if (unlikely(status & (ATA_ERR | ATA_DF))) { -- cgit v1.2.3 From 999bb6f4260f9499fdeab3f8fdcd8b9013eca39e Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Sat, 25 Mar 2006 18:07:48 +0800 Subject: [PATCH] libata-dev: irq-pio minor fixes (respin) irq-pio minor fixes for printk() and comments. Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 27078c06119..d68f5d5b423 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1295,7 +1295,7 @@ static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev, if (dev->id[59] & 0x100) { dev->multi_count = dev->id[59] & 0xff; DPRINTK("ata%u: dev %u multi count %u\n", - ap->id, device, dev->multi_count); + ap->id, dev->devno, dev->multi_count); } dev->cdb_len = 16; @@ -3594,6 +3594,9 @@ static int ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc, } fsm_start: + DPRINTK("ata%u: protocol %d task_state %d (dev_stat 0x%X)\n", + ap->id, qc->tf.protocol, ap->hsm_task_state, status); + switch (ap->hsm_task_state) { case HSM_ST_FIRST: /* Send first data block or PACKET CDB */ @@ -3720,6 +3723,7 @@ fsm_start: ap->hsm_task_state = HSM_ST_IDLE; + /* complete taskfile transaction */ if (in_wq) ata_poll_qc_complete(qc); else @@ -4241,9 +4245,6 @@ inline unsigned int ata_host_intr (struct ata_port *ap, if (unlikely(status & ATA_BUSY)) goto idle_irq; - DPRINTK("ata%u: protocol %d task_state %d (dev_stat 0x%X)\n", - ap->id, qc->tf.protocol, ap->hsm_task_state, status); - /* ack bmdma irq events */ ap->ops->irq_clear(ap); -- cgit v1.2.3 From 71601958f73b952281f2b02e16d1f11c99ee0a8b Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Sat, 25 Mar 2006 18:11:12 +0800 Subject: [PATCH] libata-dev: fix the device err check sequence (respin) Current irq-pio checks ERR bit and stops on ERR before it does anything else. This behavior doesn't look right. The DRQ bit should take higher precedence than the ERR bit. Changes: - Let the HSM do the data transfer whenever the device asks for DRQ bit, even if the ERR bit is set. - For DRQ=1 ERR=1, don't trust the data Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 44 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index d68f5d5b423..59cb12993f9 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3587,12 +3587,6 @@ static int ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc, */ WARN_ON(in_wq != ata_hsm_ok_in_wq(ap, qc)); - /* check error */ - if (unlikely(status & (ATA_ERR | ATA_DF))) { - qc->err_mask |= AC_ERR_DEV; - ap->hsm_task_state = HSM_ST_ERR; - } - fsm_start: DPRINTK("ata%u: protocol %d task_state %d (dev_stat 0x%X)\n", ap->id, qc->tf.protocol, ap->hsm_task_state, status); @@ -3615,6 +3609,17 @@ fsm_start: goto fsm_start; } + /* Device should not ask for data transfer (DRQ=1) + * when it finds something wrong. + * Anyway, we respect DRQ here and let HSM go on + * without changing hsm_task_state to HSM_ST_ERR. + */ + if (unlikely(status & (ATA_ERR | ATA_DF))) { + printk(KERN_WARNING "ata%d: DRQ=1 with device error, dev_stat 0x%X\n", + ap->id, status); + qc->err_mask |= AC_ERR_DEV; + } + /* Send the CDB (atapi) or the first data block (ata pio out). * During the state transition, interrupt handler shouldn't * be invoked before the data transfer is complete and @@ -3657,6 +3662,17 @@ fsm_start: goto fsm_start; } + /* Device should not ask for data transfer (DRQ=1) + * when it finds something wrong. + * Anyway, we respect DRQ here and let HSM go on + * without changing hsm_task_state to HSM_ST_ERR. + */ + if (unlikely(status & (ATA_ERR | ATA_DF))) { + printk(KERN_WARNING "ata%d: DRQ=1 with device error, dev_stat 0x%X\n", + ap->id, status); + qc->err_mask |= AC_ERR_DEV; + } + atapi_pio_bytes(qc); if (unlikely(ap->hsm_task_state == HSM_ST_ERR)) @@ -3672,6 +3688,22 @@ fsm_start: goto fsm_start; } + /* Some devices may ask for data transfer (DRQ=1) + * alone with ERR=1 for PIO reads. + * We respect DRQ here and let HSM go on without + * changing hsm_task_state to HSM_ST_ERR. + */ + if (unlikely(status & (ATA_ERR | ATA_DF))) { + /* For writes, ERR=1 DRQ=1 doesn't make + * sense since the data block has been + * transferred to the device. + */ + WARN_ON(qc->tf.flags & ATA_TFLAG_WRITE); + + /* data might be corrputed */ + qc->err_mask |= AC_ERR_DEV; + } + ata_pio_sectors(qc); if (ap->hsm_task_state == HSM_ST_LAST && -- cgit v1.2.3 From 52a3220599647ba429fcbca2388ec35b850fa72f Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Sat, 25 Mar 2006 18:18:15 +0800 Subject: [PATCH] libata-dev: wait idle after reading the last data block Some CD-ROM drives are slow to clear DRQ, after the last data block is read by PIO. Use ata_wait_idle() after reading the last data block. Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 59cb12993f9..5fdc3143ed1 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3710,7 +3710,7 @@ fsm_start: (!(qc->tf.flags & ATA_TFLAG_WRITE))) { /* all data read */ ata_altstatus(ap); - status = ata_chk_status(ap); + status = ata_wait_idle(ap); goto fsm_start; } } -- cgit v1.2.3 From 0eacee585a89ce5827b572a73a024931506bef48 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Fri, 31 Mar 2006 00:37:23 -0500 Subject: ACPI: enable BIOS warning http://bugzilla.kernel.org/show_bug.cgi?id=5452 Signed-off-by: Len Brown --- drivers/acpi/processor_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 713b763884a..18d380f095b 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -558,8 +558,8 @@ static int acpi_processor_start(struct acpi_device *device) */ if (processor_device_array[pr->id] != NULL && processor_device_array[pr->id] != (void *)device) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "BIOS reporting wrong ACPI id" - "for the processor\n")); + printk(KERN_WARNING "BIOS reported wrong ACPI id" + "for the processor\n"); return_VALUE(-ENODEV); } processor_device_array[pr->id] = (void *)device; -- cgit v1.2.3 From 1fee94034917aa711fcbd4ebf4c36f7ebd9fa7d6 Mon Sep 17 00:00:00 2001 From: Irwan Djajadi Date: Fri, 20 Jan 2006 15:28:00 -0500 Subject: [ACPI] drivers/acpi/hotkey.c: check kmalloc return value Signed-off-by: Irwan Djajadi Signed-off-by: Alexey Dobriyan Signed-off-by: Len Brown --- drivers/acpi/hotkey.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/acpi/hotkey.c b/drivers/acpi/hotkey.c index 2e2e4051dfa..c25b2b92edc 100644 --- a/drivers/acpi/hotkey.c +++ b/drivers/acpi/hotkey.c @@ -723,6 +723,8 @@ get_parms(char *config_record, goto do_fail; count = tmp1 - tmp; *action_handle = (char *)kmalloc(count + 1, GFP_KERNEL); + if (!*action_handle) + goto do_fail; strncpy(*action_handle, tmp, count); *(*action_handle + count) = 0; -- cgit v1.2.3 From a1f9e65e2085e0a87f28a4d5a8ae43b32c087f24 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Wed, 25 Jan 2006 23:47:36 -0500 Subject: [ACPI] document cmdline acpi_os_name= This can sometimes be used to work around broken BIOS. Use "Microsoft Windows" to take the same path through the BIOS as Windows98 would. The default is "Microsoft Windows NT", which is what NT and later versions of Windows use, and is the most tested path through most BIOS. Set it to anything else, including "Linux", at your own risk, as it seems that virtually no BIOS has been tested with anything but the two options above. Note that this uses the legacy _OS interface, so we don't expect this to ever change. Signed-off-by: Len Brown --- Documentation/kernel-parameters.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index f8cb55c30b0..78eb66b8619 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -139,6 +139,9 @@ running once the system is up. acpi_irq_isa= [HW,ACPI] If irq_balance, mark listed IRQs used by ISA Format: ,... + acpi_os_name= [HW,ACPI] Tell ACPI BIOS the name of the OS + Format: To spoof as Windows 98: ="Microsoft Windows" + acpi_osi= [HW,ACPI] empty param disables _OSI acpi_serialize [HW,ACPI] force serialization of AML methods -- cgit v1.2.3 From fdc136ccd3332938e989439c025c363f8479f3e6 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 8 Mar 2006 22:12:00 -0500 Subject: [ACPI] fix possible acpi thermal leak in failure path Coverity: #601 Signed-off-by: Dave Jones Signed-off-by: Len Brown --- drivers/acpi/thermal.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 19f3ea48475..d0b44ce2ec5 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -942,8 +942,10 @@ acpi_thermal_write_trip_points(struct file *file, memset(limit_string, 0, ACPI_THERMAL_MAX_LIMIT_STR_LEN); active = kmalloc(ACPI_THERMAL_MAX_ACTIVE * sizeof(int), GFP_KERNEL); - if (!active) + if (!active) { + kfree(limit_string); return_VALUE(-ENOMEM); + } if (!tz || (count > ACPI_THERMAL_MAX_LIMIT_STR_LEN - 1)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid argument\n")); -- cgit v1.2.3 From 6665bda76461308868bd1e52caf627f4cb29ed32 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sat, 11 Mar 2006 10:12:00 -0500 Subject: [ACPI] drivers/acpi/video.c: fix error path NULL pointer dereference The Coverity checker spotted this bug in acpi_video_device_lcd_query_levels(). Signed-off-by: Adrian Bunk Signed-off-by: Len Brown --- drivers/acpi/video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index bd488751837..724149d72d9 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -323,7 +323,7 @@ acpi_video_device_lcd_query_levels(struct acpi_video_device *device, if (!ACPI_SUCCESS(status)) return_VALUE(status); obj = (union acpi_object *)buffer.pointer; - if (!obj && (obj->type != ACPI_TYPE_PACKAGE)) { + if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _BCL data\n")); status = -EFAULT; goto err; -- cgit v1.2.3 From 46358614ed5b031797522f1020e989c959a8d8a6 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Fri, 31 Mar 2006 02:16:19 -0500 Subject: Revert "[PATCH] ACPI: fix vendor resource length computation" fixed in a different way by a subsequent ACPICA patch This reverts 35b73ceb9a7d10c81bd9e79e8485f7079ef2b40e commit. --- drivers/acpi/resources/rscalc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/resources/rscalc.c b/drivers/acpi/resources/rscalc.c index 4038dbfa63a..7d6481d9fbe 100644 --- a/drivers/acpi/resources/rscalc.c +++ b/drivers/acpi/resources/rscalc.c @@ -391,7 +391,8 @@ acpi_rs_get_list_length(u8 * aml_buffer, * Ensure a 32-bit boundary for the structure */ extra_struct_bytes = - ACPI_ROUND_UP_to_32_bITS(resource_length); + ACPI_ROUND_UP_to_32_bITS(resource_length) - + resource_length; break; case ACPI_RESOURCE_NAME_END_TAG: @@ -407,7 +408,8 @@ acpi_rs_get_list_length(u8 * aml_buffer, * Add vendor data and ensure a 32-bit boundary for the structure */ extra_struct_bytes = - ACPI_ROUND_UP_to_32_bITS(resource_length); + ACPI_ROUND_UP_to_32_bITS(resource_length) - + resource_length; break; case ACPI_RESOURCE_NAME_ADDRESS32: -- cgit v1.2.3 From 52fc0b026e99b5d5d585095148d997d5634bbc25 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Mon, 2 Oct 2006 00:00:00 -0400 Subject: [ACPI] ACPICA 20060210 Removed a couple of extraneous ACPI_ERROR messages that appeared during normal execution. These became apparent after the conversion from ACPI_DEBUG_PRINT. Fixed a problem where the CreateField operator could hang if the BitIndex or NumBits parameter referred to a named object. From Valery Podrezov. http://bugzilla.kernel.org/show_bug.cgi?id=5359 Fixed a problem where a DeRefOf operation on a buffer object incorrectly failed with an exception. This also fixes a couple of related RefOf and DeRefOf issues. From Valery Podrezov. http://bugzilla.kernel.org/show_bug.cgi?id=5360 http://bugzilla.kernel.org/show_bug.cgi?id=5387 http://bugzilla.kernel.org/show_bug.cgi?id=5392 Fixed a problem where the AE_BUFFER_LIMIT exception was returned instead of AE_STRING_LIMIT on an out-of-bounds Index() operation. From Valery Podrezov. http://bugzilla.kernel.org/show_bug.cgi?id=5480 Implemented a memory cleanup at the end of the execution of each iteration of an AML While() loop, preventing the accumulation of outstanding objects. From Valery Podrezov. http://bugzilla.kernel.org/show_bug.cgi?id=5427 Eliminated a chunk of duplicate code in the object resolution code. From Valery Podrezov. http://bugzilla.kernel.org/show_bug.cgi?id=5336 Fixed several warnings during the 64-bit code generation. Signed-off-by: Bob Moore Signed-off-by: Len Brown --- drivers/acpi/dispatcher/dsfield.c | 1 + drivers/acpi/dispatcher/dsmethod.c | 5 +++ drivers/acpi/dispatcher/dsmthdat.c | 1 + drivers/acpi/dispatcher/dsobject.c | 6 +++ drivers/acpi/dispatcher/dsopcode.c | 4 ++ drivers/acpi/dispatcher/dsutils.c | 7 +++- drivers/acpi/dispatcher/dswexec.c | 3 ++ drivers/acpi/dispatcher/dswload.c | 9 +++++ drivers/acpi/dispatcher/dswscope.c | 2 + drivers/acpi/dispatcher/dswstate.c | 5 +++ drivers/acpi/events/evevent.c | 2 + drivers/acpi/events/evgpe.c | 5 +++ drivers/acpi/events/evgpeblk.c | 13 +++++++ drivers/acpi/events/evmisc.c | 6 +++ drivers/acpi/events/evregion.c | 10 +++++ drivers/acpi/events/evrgnini.c | 6 +++ drivers/acpi/events/evxface.c | 3 ++ drivers/acpi/events/evxfevnt.c | 1 + drivers/acpi/events/evxfregn.c | 2 + drivers/acpi/executer/exconfig.c | 5 +++ drivers/acpi/executer/exconvrt.c | 2 + drivers/acpi/executer/exdump.c | 2 + drivers/acpi/executer/exfield.c | 2 + drivers/acpi/executer/exfldio.c | 5 +++ drivers/acpi/executer/exmisc.c | 1 + drivers/acpi/executer/exmutex.c | 3 ++ drivers/acpi/executer/exnames.c | 6 +++ drivers/acpi/executer/exoparg1.c | 44 ++++++++++++++++++---- drivers/acpi/executer/exoparg2.c | 77 ++++++++++++++++++++++++-------------- drivers/acpi/executer/exoparg3.c | 2 + drivers/acpi/executer/exoparg6.c | 1 + drivers/acpi/executer/exregion.c | 1 + drivers/acpi/executer/exresnte.c | 5 +++ drivers/acpi/executer/exresolv.c | 43 +++++---------------- drivers/acpi/executer/exresop.c | 4 ++ drivers/acpi/executer/exstore.c | 2 + drivers/acpi/executer/exstoren.c | 3 ++ drivers/acpi/executer/exstorob.c | 3 ++ drivers/acpi/executer/exsystem.c | 2 + drivers/acpi/executer/exutils.c | 3 ++ drivers/acpi/hardware/hwgpe.c | 2 + drivers/acpi/hardware/hwregs.c | 1 + drivers/acpi/hardware/hwsleep.c | 1 + drivers/acpi/hardware/hwtimer.c | 1 + drivers/acpi/namespace/nsaccess.c | 7 ++++ drivers/acpi/namespace/nsalloc.c | 8 ++++ drivers/acpi/namespace/nsdump.c | 4 ++ drivers/acpi/namespace/nseval.c | 1 + drivers/acpi/namespace/nsinit.c | 5 +++ drivers/acpi/namespace/nsload.c | 3 ++ drivers/acpi/namespace/nsobject.c | 3 ++ drivers/acpi/namespace/nssearch.c | 3 ++ drivers/acpi/namespace/nsutils.c | 6 +++ drivers/acpi/namespace/nswalk.c | 4 ++ drivers/acpi/namespace/nsxfeval.c | 46 ++++++++++++----------- drivers/acpi/namespace/nsxfname.c | 1 + drivers/acpi/namespace/nsxfobj.c | 1 + drivers/acpi/parser/psargs.c | 7 ++++ drivers/acpi/parser/psloop.c | 6 +++ drivers/acpi/parser/psopcode.c | 2 + drivers/acpi/parser/psparse.c | 8 ++++ drivers/acpi/parser/psscope.c | 1 + drivers/acpi/parser/pstree.c | 7 ++++ drivers/acpi/parser/psutils.c | 1 + drivers/acpi/parser/pswalk.c | 3 ++ drivers/acpi/parser/psxface.c | 2 + drivers/acpi/resources/rscalc.c | 16 +++++--- drivers/acpi/resources/rslist.c | 3 ++ drivers/acpi/resources/rsmisc.c | 6 ++- drivers/acpi/resources/rsutils.c | 46 +++++++++++++---------- drivers/acpi/resources/rsxface.c | 2 + drivers/acpi/tables/tbconvrt.c | 3 ++ drivers/acpi/tables/tbget.c | 9 +++++ drivers/acpi/tables/tbgetall.c | 1 + drivers/acpi/tables/tbinstal.c | 1 + drivers/acpi/tables/tbrsdt.c | 1 + drivers/acpi/tables/tbutils.c | 2 + drivers/acpi/tables/tbxface.c | 3 ++ drivers/acpi/tables/tbxfroot.c | 11 ++++++ drivers/acpi/utilities/utalloc.c | 5 +++ drivers/acpi/utilities/utcache.c | 2 + drivers/acpi/utilities/utcopy.c | 1 + drivers/acpi/utilities/utdebug.c | 4 ++ drivers/acpi/utilities/utdelete.c | 3 ++ drivers/acpi/utilities/uteval.c | 4 ++ drivers/acpi/utilities/utglobal.c | 2 + drivers/acpi/utilities/utmisc.c | 31 +++------------ drivers/acpi/utilities/utobject.c | 2 + drivers/acpi/utilities/utresrc.c | 4 ++ drivers/acpi/utilities/utstate.c | 2 + include/acpi/acconfig.h | 2 +- include/acpi/acdisasm.h | 1 + include/acpi/acutils.h | 2 - 93 files changed, 466 insertions(+), 144 deletions(-) diff --git a/drivers/acpi/dispatcher/dsfield.c b/drivers/acpi/dispatcher/dsfield.c index 76bc0463f6d..3d33bcc9867 100644 --- a/drivers/acpi/dispatcher/dsfield.c +++ b/drivers/acpi/dispatcher/dsfield.c @@ -425,6 +425,7 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, * Walk the list of entries in the field_list */ while (arg) { + /* Ignore OFFSET and ACCESSAS terms here */ if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) { diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c index c475546535b..238916ce541 100644 --- a/drivers/acpi/dispatcher/dsmethod.c +++ b/drivers/acpi/dispatcher/dsmethod.c @@ -81,6 +81,7 @@ acpi_ds_method_error(acpi_status status, struct acpi_walk_state *walk_state) /* Invoke the global exception handler */ if (acpi_gbl_exception_handler) { + /* Exit the interpreter, allow handler to execute methods */ acpi_ex_exit_interpreter(); @@ -100,6 +101,7 @@ acpi_ds_method_error(acpi_status status, struct acpi_walk_state *walk_state) } #ifdef ACPI_DISASSEMBLER if (ACPI_FAILURE(status)) { + /* Display method locals/args if disassembler is present */ acpi_dm_dump_method_info(status, walk_state, walk_state->op); @@ -249,6 +251,7 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread, } if (!(obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY)) { + /* 1) Parse: Create a new walk state for the preempting walk */ next_walk_state = @@ -378,9 +381,11 @@ acpi_ds_restart_control_method(struct acpi_walk_state *walk_state, /* Did the called method return a value? */ if (return_desc) { + /* Are we actually going to use the return value? */ if (walk_state->return_used) { + /* Save the return value from the previous method */ status = acpi_ds_result_push(return_desc, walk_state); diff --git a/drivers/acpi/dispatcher/dsmthdat.c b/drivers/acpi/dispatcher/dsmthdat.c index c025674f938..f7cb5170aa1 100644 --- a/drivers/acpi/dispatcher/dsmthdat.c +++ b/drivers/acpi/dispatcher/dsmthdat.c @@ -701,6 +701,7 @@ acpi_ds_method_data_get_type(u16 opcode, object = acpi_ns_get_attached_object(node); if (!object) { + /* Uninitialized local/arg, return TYPE_ANY */ return_VALUE(ACPI_TYPE_ANY); diff --git a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c index 8b21f0f9e51..1f2d0c6ef36 100644 --- a/drivers/acpi/dispatcher/dsobject.c +++ b/drivers/acpi/dispatcher/dsobject.c @@ -103,6 +103,7 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, common. node))); if (ACPI_FAILURE(status)) { + /* Check if we are resolving a named reference within a package */ if ((status == AE_NOT_FOUND) @@ -195,6 +196,7 @@ acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state, */ obj_desc = *obj_desc_ptr; if (!obj_desc) { + /* Create a new buffer object */ obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER); @@ -355,6 +357,7 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, arg = arg->common.next; for (i = 0; arg; i++) { if (arg->common.aml_opcode == AML_INT_RETURN_VALUE_OP) { + /* Object (package or buffer) is already built */ obj_desc->package.elements[i] = @@ -408,6 +411,7 @@ acpi_ds_create_node(struct acpi_walk_state *walk_state, } if (!op->common.value.arg) { + /* No arguments, there is nothing to do */ return_ACPI_STATUS(AE_OK); @@ -469,6 +473,7 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state, obj_desc = *ret_obj_desc; op_info = acpi_ps_get_opcode_info(opcode); if (op_info->class == AML_CLASS_UNKNOWN) { + /* Unknown opcode */ return_ACPI_STATUS(AE_TYPE); @@ -626,6 +631,7 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state, default: /* Other literals, etc.. */ if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) { + /* Node was saved in Op */ obj_desc->reference.node = op->common.node; diff --git a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c index 6229c10674e..8a690a9963f 100644 --- a/drivers/acpi/dispatcher/dsopcode.c +++ b/drivers/acpi/dispatcher/dsopcode.c @@ -640,6 +640,7 @@ acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state, /* Initialize the Buffer Field */ if (op->common.aml_opcode == AML_CREATE_FIELD_OP) { + /* NOTE: Slightly different operands for this opcode */ status = @@ -984,6 +985,7 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state, ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", op)); if (walk_state->control_state->common.value) { + /* Predicate was true, go back and evaluate it again! */ status = AE_CTRL_PENDING; @@ -1014,6 +1016,7 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state, * has been bubbled up the tree */ if (op->common.value.arg) { + /* Since we have a real Return(), delete any implicit return */ acpi_ds_clear_implicit_return(walk_state); @@ -1047,6 +1050,7 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state, walk_state->return_desc = walk_state->operands[0]; } else if ((walk_state->results) && (walk_state->results->results.num_results > 0)) { + /* Since we have a real Return(), delete any implicit return */ acpi_ds_clear_implicit_return(walk_state); diff --git a/drivers/acpi/dispatcher/dsutils.c b/drivers/acpi/dispatcher/dsutils.c index 53356a591ac..3fbe17ebef5 100644 --- a/drivers/acpi/dispatcher/dsutils.c +++ b/drivers/acpi/dispatcher/dsutils.c @@ -202,6 +202,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op, */ if ((!op->common.parent) || (op->common.parent->common.aml_opcode == AML_SCOPE_OP)) { + /* No parent, the return value cannot possibly be used */ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, @@ -352,6 +353,7 @@ acpi_ds_delete_result_if_not_used(union acpi_parse_object *op, } if (!acpi_ds_is_result_used(op, walk_state)) { + /* Must pop the result stack (obj_desc should be equal to result_obj) */ status = acpi_ds_result_pop(&obj_desc, walk_state); @@ -498,7 +500,9 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, */ if ((walk_state->deferred_node) && (walk_state->deferred_node->type == ACPI_TYPE_BUFFER_FIELD) - && (arg_index != 0)) { + && (arg_index == + (u32) ((walk_state->opcode == + AML_CREATE_FIELD_OP) ? 3 : 2))) { obj_desc = ACPI_CAST_PTR(union acpi_operand_object, walk_state->deferred_node); @@ -521,6 +525,7 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, && (parent_op->common.aml_opcode != AML_REGION_OP) && (parent_op->common.aml_opcode != AML_INT_NAMEPATH_OP)) { + /* Enter name into namespace if not found */ interpreter_mode = ACPI_IMODE_LOAD_PASS2; diff --git a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c index f1af655ff11..198949f4104 100644 --- a/drivers/acpi/dispatcher/dswexec.c +++ b/drivers/acpi/dispatcher/dswexec.c @@ -409,6 +409,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) * being the object_type and size_of operators. */ if (!(walk_state->op_info->flags & AML_NO_OPERAND_RESOLVE)) { + /* Resolve all operands */ status = acpi_ex_resolve_operands(walk_state->opcode, @@ -548,6 +549,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) */ status = acpi_ds_resolve_operands(walk_state); if (ACPI_FAILURE(status)) { + /* On error, clear all resolved operands */ acpi_ds_clear_operands(walk_state); @@ -722,6 +724,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) cleanup: if (walk_state->result_obj) { + /* Break to debugger to display result */ ACPI_DEBUGGER_EXEC(acpi_db_display_result_object diff --git a/drivers/acpi/dispatcher/dswload.c b/drivers/acpi/dispatcher/dswload.c index d3d24da31c8..02b03126e14 100644 --- a/drivers/acpi/dispatcher/dswload.c +++ b/drivers/acpi/dispatcher/dswload.c @@ -261,6 +261,7 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, */ if (walk_state->deferred_node) { + /* This name is already in the namespace, get the node */ node = walk_state->deferred_node; @@ -311,6 +312,7 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, /* Common exit */ if (!op) { + /* Create a new op */ op = acpi_ps_alloc_op(walk_state->opcode); @@ -413,6 +415,7 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state) #endif if (op->common.aml_opcode == AML_NAME_OP) { + /* For Name opcode, get the object type from the argument */ if (op->common.value.arg) { @@ -521,6 +524,7 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, if ((walk_state->control_state) && (walk_state->control_state->common.state == ACPI_CONTROL_CONDITIONAL_EXECUTING)) { + /* We are executing a while loop outside of a method */ status = acpi_ds_exec_begin_op(walk_state, out_op); @@ -554,10 +558,12 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, /* Get the name we are going to enter or lookup in the namespace */ if (walk_state->opcode == AML_INT_NAMEPATH_OP) { + /* For Namepath op, get the path string */ buffer_ptr = op->common.value.string; if (!buffer_ptr) { + /* No name, just exit */ return_ACPI_STATUS(AE_OK); @@ -680,6 +686,7 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, /* All other opcodes */ if (op && op->common.node) { + /* This op/node was previously entered into the namespace */ node = op->common.node; @@ -705,6 +712,7 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, * Note: Name may already exist if we are executing a deferred opcode. */ if (walk_state->deferred_node) { + /* This name is already in the namespace, get the node */ node = walk_state->deferred_node; @@ -727,6 +735,7 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, } if (!op) { + /* Create a new op */ op = acpi_ps_alloc_op(walk_state->opcode); diff --git a/drivers/acpi/dispatcher/dswscope.c b/drivers/acpi/dispatcher/dswscope.c index ada21ef4a17..e2954fff8c5 100644 --- a/drivers/acpi/dispatcher/dswscope.c +++ b/drivers/acpi/dispatcher/dswscope.c @@ -66,6 +66,7 @@ void acpi_ds_scope_stack_clear(struct acpi_walk_state *walk_state) ACPI_FUNCTION_NAME("ds_scope_stack_clear"); while (walk_state->scope_info) { + /* Pop a scope off the stack */ scope_info = walk_state->scope_info; @@ -105,6 +106,7 @@ acpi_ds_scope_stack_push(struct acpi_namespace_node *node, ACPI_FUNCTION_TRACE("ds_scope_stack_push"); if (!node) { + /* Invalid scope */ ACPI_ERROR((AE_INFO, "Null scope parameter")); diff --git a/drivers/acpi/dispatcher/dswstate.c b/drivers/acpi/dispatcher/dswstate.c index fa78cb74ee3..5bc340b1b28 100644 --- a/drivers/acpi/dispatcher/dswstate.c +++ b/drivers/acpi/dispatcher/dswstate.c @@ -170,6 +170,7 @@ acpi_ds_result_pop(union acpi_operand_object ** object, state->results.num_results--; for (index = ACPI_OBJ_NUM_OPERANDS; index; index--) { + /* Check for a valid result object */ if (state->results.obj_desc[index - 1]) { @@ -448,6 +449,7 @@ acpi_ds_obj_stack_pop(u32 pop_count, struct acpi_walk_state * walk_state) ACPI_FUNCTION_NAME("ds_obj_stack_pop"); for (i = 0; i < pop_count; i++) { + /* Check for stack underflow */ if (walk_state->num_operands == 0) { @@ -494,6 +496,7 @@ acpi_ds_obj_stack_pop_and_delete(u32 pop_count, ACPI_FUNCTION_NAME("ds_obj_stack_pop_and_delete"); for (i = 0; i < pop_count; i++) { + /* Check for stack underflow */ if (walk_state->num_operands == 0) { @@ -598,6 +601,7 @@ struct acpi_walk_state *acpi_ds_pop_walk_state(struct acpi_thread_state *thread) walk_state = thread->walk_state_list; if (walk_state) { + /* Next walk state becomes the current walk state */ thread->walk_state_list = walk_state->next; @@ -778,6 +782,7 @@ acpi_ds_init_aml_walk(struct acpi_walk_state *walk_state, } if (parser_state->start_node) { + /* Push start scope on scope stack and make it current */ status = diff --git a/drivers/acpi/events/evevent.c b/drivers/acpi/events/evevent.c index c9ac05c4685..c8d9752e312 100644 --- a/drivers/acpi/events/evevent.c +++ b/drivers/acpi/events/evevent.c @@ -260,12 +260,14 @@ u32 acpi_ev_fixed_event_detect(void) * Check for all possible Fixed Events and dispatch those that are active */ for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) { + /* Both the status and enable bits must be on for this event */ if ((fixed_status & acpi_gbl_fixed_event_info[i]. status_bit_mask) && (fixed_enable & acpi_gbl_fixed_event_info[i]. enable_bit_mask)) { + /* Found an active (signalled) event */ int_status |= acpi_ev_fixed_event_dispatch((u32) i); diff --git a/drivers/acpi/events/evgpe.c b/drivers/acpi/events/evgpe.c index f64f977dd3d..7d7b81af972 100644 --- a/drivers/acpi/events/evgpe.c +++ b/drivers/acpi/events/evgpe.c @@ -207,6 +207,7 @@ acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info, ACPI_SET_BIT(gpe_event_info->flags, ACPI_GPE_RUN_ENABLED); if (write_to_hardware) { + /* Clear the GPE (of stale events), then enable it */ status = acpi_hw_clear_gpe(gpe_event_info); @@ -313,6 +314,7 @@ struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device, /* A NULL gpe_block means use the FADT-defined GPE block(s) */ if (!gpe_device) { + /* Examine GPE Block 0 and 1 (These blocks are permanent) */ for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++) { @@ -402,6 +404,7 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) * Find all currently active GP events. */ for (i = 0; i < gpe_block->register_count; i++) { + /* Get the next status/enable pair */ gpe_register_info = &gpe_block->register_info[i]; @@ -437,6 +440,7 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) enabled_status_byte = (u8) (status_reg & enable_reg); if (!enabled_status_byte) { + /* No active GPEs in this register, move on */ continue; @@ -445,6 +449,7 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) /* Now look at the individual GPEs in this byte register */ for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) { + /* Examine one GPE bit */ if (enabled_status_byte & diff --git a/drivers/acpi/events/evgpeblk.c b/drivers/acpi/events/evgpeblk.c index 0fd00b5ad65..87e77a138ff 100644 --- a/drivers/acpi/events/evgpeblk.c +++ b/drivers/acpi/events/evgpeblk.c @@ -146,10 +146,12 @@ acpi_status acpi_ev_walk_gpe_list(ACPI_GPE_CALLBACK gpe_walk_callback) gpe_xrupt_info = acpi_gbl_gpe_xrupt_list_head; while (gpe_xrupt_info) { + /* Walk all Gpe Blocks attached to this interrupt level */ gpe_block = gpe_xrupt_info->gpe_block_list_head; while (gpe_block) { + /* One callback per GPE block */ status = gpe_walk_callback(gpe_xrupt_info, gpe_block); @@ -195,6 +197,7 @@ acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info, /* Examine each GPE Register within the block */ for (i = 0; i < gpe_block->register_count; i++) { + /* Now look at the individual GPEs in this byte register */ for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) { @@ -289,6 +292,7 @@ acpi_ev_save_method_info(acpi_handle obj_handle, gpe_number = ACPI_STRTOUL(&name[2], NULL, 16); if (gpe_number == ACPI_UINT32_MAX) { + /* Conversion failed; invalid method, just ignore it */ ACPI_ERROR((AE_INFO, @@ -371,6 +375,7 @@ acpi_ev_match_prw_and_gpe(acpi_handle obj_handle, status = acpi_ut_evaluate_object(obj_handle, METHOD_NAME__PRW, ACPI_BTYPE_PACKAGE, &pkg_desc); if (ACPI_FAILURE(status)) { + /* Ignore all errors from _PRW, we don't want to abort the subsystem */ return_ACPI_STATUS(AE_OK); @@ -394,6 +399,7 @@ acpi_ev_match_prw_and_gpe(acpi_handle obj_handle, obj_desc = pkg_desc->package.elements[0]; if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { + /* Use FADT-defined GPE device (from definition of _PRW) */ target_gpe_device = acpi_gbl_fadt_gpe_device; @@ -402,6 +408,7 @@ acpi_ev_match_prw_and_gpe(acpi_handle obj_handle, gpe_number = (u32) obj_desc->integer.value; } else if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_PACKAGE) { + /* Package contains a GPE reference and GPE number within a GPE block */ if ((obj_desc->package.count < 2) || @@ -679,6 +686,7 @@ acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block) status = acpi_hw_disable_gpe_block(gpe_block->xrupt_block, gpe_block); if (!gpe_block->previous && !gpe_block->next) { + /* This is the last gpe_block on this interrupt */ status = acpi_ev_delete_gpe_xrupt(gpe_block->xrupt_block); @@ -780,6 +788,7 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block) this_event = gpe_event_info; for (i = 0; i < gpe_block->register_count; i++) { + /* Init the register_info for this GPE register (8 GPEs) */ this_register->base_gpe_number = @@ -1013,6 +1022,7 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device, for (i = 0; i < gpe_block->register_count; i++) { for (j = 0; j < 8; j++) { + /* Get the info block for this particular GPE */ gpe_event_info = @@ -1099,6 +1109,7 @@ acpi_status acpi_ev_gpe_initialize(void) * particular block is not supported. */ if (acpi_gbl_FADT->gpe0_blk_len && acpi_gbl_FADT->xgpe0_blk.address) { + /* GPE block 0 exists (has both length and address > 0) */ register_count0 = (u16) (acpi_gbl_FADT->gpe0_blk_len / 2); @@ -1121,6 +1132,7 @@ acpi_status acpi_ev_gpe_initialize(void) } if (acpi_gbl_FADT->gpe1_blk_len && acpi_gbl_FADT->xgpe1_blk.address) { + /* GPE block 1 exists (has both length and address > 0) */ register_count1 = (u16) (acpi_gbl_FADT->gpe1_blk_len / 2); @@ -1168,6 +1180,7 @@ acpi_status acpi_ev_gpe_initialize(void) /* Exit if there are no GPE registers */ if ((register_count0 + register_count1) == 0) { + /* GPEs are not required by ACPI, this is OK */ ACPI_DEBUG_PRINT((ACPI_DB_INIT, diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c index 0909ba69577..334407239f2 100644 --- a/drivers/acpi/events/evmisc.c +++ b/drivers/acpi/events/evmisc.c @@ -150,6 +150,7 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node, obj_desc = acpi_ns_get_attached_object(node); if (obj_desc) { + /* We have the notify object, Get the right handler */ switch (node->type) { @@ -240,6 +241,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context) * to the device. */ if (notify_info->notify.value <= ACPI_MAX_SYS_NOTIFY) { + /* Global system notification handler */ if (acpi_gbl_system_notify.handler) { @@ -297,6 +299,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_global_lock_thread(void *context) /* Signal threads that are waiting for the lock */ if (acpi_gbl_global_lock_thread_count) { + /* Send sufficient units to the semaphore */ status = @@ -335,6 +338,7 @@ static u32 acpi_ev_global_lock_handler(void *context) */ ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_common_fACS.global_lock, acquired); if (acquired) { + /* Got the lock, now wake all threads waiting for it */ acpi_gbl_global_lock_acquired = TRUE; @@ -439,6 +443,7 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout) ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_common_fACS.global_lock, acquired); if (acquired) { + /* We got the lock */ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, @@ -492,6 +497,7 @@ acpi_status acpi_ev_release_global_lock(void) acpi_gbl_global_lock_thread_count--; if (acpi_gbl_global_lock_thread_count) { + /* There are still some threads holding the lock, cannot release */ return_ACPI_STATUS(AE_OK); diff --git a/drivers/acpi/events/evregion.c b/drivers/acpi/events/evregion.c index 6da58e77641..b831ec4bcae 100644 --- a/drivers/acpi/events/evregion.c +++ b/drivers/acpi/events/evregion.c @@ -164,6 +164,7 @@ acpi_status acpi_ev_initialize_op_regions(void) * Run the _REG methods for op_regions in each default address space */ for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) { + /* TBD: Make sure handler is the DEFAULT handler, otherwise * _REG will have already been run. */ @@ -315,6 +316,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, */ region_setup = handler_desc->address_space.setup; if (!region_setup) { + /* No initialization routine, exit with error */ ACPI_ERROR((AE_INFO, @@ -361,6 +363,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, region_obj->region.flags |= AOPOBJ_SETUP_COMPLETE; if (region_obj2->extra.region_context) { + /* The handler for this region was already installed */ ACPI_MEM_FREE(region_context); @@ -463,6 +466,7 @@ acpi_ev_detach_region(union acpi_operand_object *region_obj, handler_obj = region_obj->region.handler; if (!handler_obj) { + /* This region has no handler, all done */ return_VOID; @@ -474,6 +478,7 @@ acpi_ev_detach_region(union acpi_operand_object *region_obj, last_obj_ptr = &handler_obj->address_space.region_list; while (obj_desc) { + /* Is this the correct Region? */ if (obj_desc == region_obj) { @@ -666,6 +671,7 @@ acpi_ev_install_handler(acpi_handle obj_handle, obj_desc = acpi_ns_get_attached_object(node); if (!obj_desc) { + /* No object, just exit */ return (AE_OK); @@ -674,10 +680,12 @@ acpi_ev_install_handler(acpi_handle obj_handle, /* Devices are handled different than regions */ if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_DEVICE) { + /* Check if this Device already has a handler for this address space */ next_handler_obj = obj_desc->device.handler; while (next_handler_obj) { + /* Found a handler, is it for the same address space? */ if (next_handler_obj->address_space.space_id == @@ -839,6 +847,7 @@ acpi_ev_install_space_handler(struct acpi_namespace_node * node, /* Walk the handler list for this device */ while (handler_obj) { + /* Same space_id indicates a handler already installed */ if (handler_obj->address_space.space_id == space_id) { @@ -1035,6 +1044,7 @@ acpi_ev_reg_run(acpi_handle obj_handle, obj_desc = acpi_ns_get_attached_object(node); if (!obj_desc) { + /* No object, just exit */ return (AE_OK); diff --git a/drivers/acpi/events/evrgnini.c b/drivers/acpi/events/evrgnini.c index baed8c1a1b9..a0bffc2a078 100644 --- a/drivers/acpi/events/evrgnini.c +++ b/drivers/acpi/events/evrgnini.c @@ -199,6 +199,7 @@ acpi_ev_pci_config_region_setup(acpi_handle handle, * handlers with that device. */ if (handler_obj->address_space.node == acpi_gbl_root_node) { + /* Start search from the parent object */ pci_root_node = parent_node; @@ -220,6 +221,7 @@ acpi_ev_pci_config_region_setup(acpi_handle handle, PCI_EXPRESS_ROOT_HID_STRING, sizeof(PCI_EXPRESS_ROOT_HID_STRING))))) { + /* Install a handler for this PCI root bridge */ status = @@ -478,11 +480,13 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj, * ie: acpi_gbl_root_node->parent_entry being set to NULL */ while (node) { + /* Check to see if a handler exists */ handler_obj = NULL; obj_desc = acpi_ns_get_attached_object(node); if (obj_desc) { + /* Can only be a handler if the object exists */ switch (node->type) { @@ -507,10 +511,12 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj, } while (handler_obj) { + /* Is this handler of the correct type? */ if (handler_obj->address_space.space_id == space_id) { + /* Found correct handler */ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, diff --git a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c index b38b39dde54..ba16fda3a15 100644 --- a/drivers/acpi/events/evxface.c +++ b/drivers/acpi/events/evxface.c @@ -275,6 +275,7 @@ acpi_install_notify_handler(acpi_handle device, * only one global handler can be regsitered (per notify type). */ if (device == ACPI_ROOT_OBJECT) { + /* Make sure the handler is not already installed */ if (((handler_type & ACPI_SYSTEM_NOTIFY) && @@ -317,6 +318,7 @@ acpi_install_notify_handler(acpi_handle device, obj_desc = acpi_ns_get_attached_object(node); if (obj_desc) { + /* Object exists - make sure there's no handler */ if (((handler_type & ACPI_SYSTEM_NOTIFY) && @@ -370,6 +372,7 @@ acpi_install_notify_handler(acpi_handle device, } if (handler_type == ACPI_ALL_NOTIFY) { + /* Extra ref if installed in both */ acpi_ut_add_reference(notify_obj); diff --git a/drivers/acpi/events/evxfevnt.c b/drivers/acpi/events/evxfevnt.c index ec9ce8429f1..babebb50140 100644 --- a/drivers/acpi/events/evxfevnt.c +++ b/drivers/acpi/events/evxfevnt.c @@ -636,6 +636,7 @@ acpi_install_gpe_block(acpi_handle gpe_device, obj_desc = acpi_ns_get_attached_object(node); if (!obj_desc) { + /* No object, create a new one */ obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE); diff --git a/drivers/acpi/events/evxfregn.c b/drivers/acpi/events/evxfregn.c index abf5caca9ae..368c8aa0094 100644 --- a/drivers/acpi/events/evxfregn.c +++ b/drivers/acpi/events/evxfregn.c @@ -176,9 +176,11 @@ acpi_remove_address_space_handler(acpi_handle device, handler_obj = obj_desc->device.handler; last_obj_ptr = &obj_desc->device.handler; while (handler_obj) { + /* We have a handler, see if user requested this one */ if (handler_obj->address_space.space_id == space_id) { + /* Matched space_id, first dereference this in the Regions */ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c index a29782fe3ec..864530f754c 100644 --- a/drivers/acpi/executer/exconfig.c +++ b/drivers/acpi/executer/exconfig.c @@ -110,6 +110,7 @@ acpi_ex_add_table(struct acpi_table_header *table, if (ACPI_FAILURE(status)) { if (status == AE_ALREADY_EXISTS) { + /* Table already exists, just return the handle */ return_ACPI_STATUS(AE_OK); @@ -121,6 +122,7 @@ acpi_ex_add_table(struct acpi_table_header *table, status = acpi_ns_load_table(table_info.installed_desc, parent_node); if (ACPI_FAILURE(status)) { + /* Uninstall table on error */ (void)acpi_tb_uninstall_table(table_info.installed_desc); @@ -169,6 +171,7 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, */ status = acpi_tb_match_signature(operand[0]->string.pointer, NULL); if (status == AE_OK) { + /* Signature matched -- don't allow override */ return_ACPI_STATUS(AE_ALREADY_EXISTS); @@ -252,6 +255,7 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, /* Parameter Data (optional) */ if (parameter_node) { + /* Store the parameter data into the optional parameter object */ status = acpi_ex_store(operand[5], @@ -424,6 +428,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, status = acpi_ex_add_table(table_ptr, acpi_gbl_root_node, &ddb_handle); if (ACPI_FAILURE(status)) { + /* On error, table_ptr was deallocated above */ return_ACPI_STATUS(status); diff --git a/drivers/acpi/executer/exconvrt.c b/drivers/acpi/executer/exconvrt.c index e6d52e12d77..a2c93c9ba07 100644 --- a/drivers/acpi/executer/exconvrt.c +++ b/drivers/acpi/executer/exconvrt.c @@ -319,6 +319,7 @@ acpi_ex_convert_to_ascii(acpi_integer integer, remainder = 0; for (i = decimal_length; i > 0; i--) { + /* Divide by nth factor of 10 */ digit = integer; @@ -346,6 +347,7 @@ acpi_ex_convert_to_ascii(acpi_integer integer, hex_length = (acpi_native_uint) ACPI_MUL_2(data_width); for (i = 0, j = (hex_length - 1); i < hex_length; i++, j--) { + /* Get one hex digit, most significant digits first */ string[k] = diff --git a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c index a7cca8d4f85..0a53d31e09d 100644 --- a/drivers/acpi/executer/exdump.c +++ b/drivers/acpi/executer/exdump.c @@ -463,6 +463,7 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) } if (!obj_desc) { + /* This could be a null element of a package */ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Null Object Descriptor\n")); @@ -532,6 +533,7 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) obj_desc->reference.offset); if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { + /* Value is an Integer */ acpi_os_printf(" value is [%8.8X%8.8x]", diff --git a/drivers/acpi/executer/exfield.c b/drivers/acpi/executer/exfield.c index e259201ce9a..215783a33c2 100644 --- a/drivers/acpi/executer/exfield.c +++ b/drivers/acpi/executer/exfield.c @@ -142,6 +142,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, length = (acpi_size) ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->field.bit_length); if (length > acpi_gbl_integer_byte_width) { + /* Field is too large for an Integer, create a Buffer instead */ buffer_desc = acpi_ut_create_buffer_object(length); @@ -329,6 +330,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length); if (length < required_length) { + /* We need to create a new buffer */ new_buffer = ACPI_MEM_CALLOCATE(required_length); diff --git a/drivers/acpi/executer/exfldio.c b/drivers/acpi/executer/exfldio.c index bd1af35f7fc..d5a4b2627c1 100644 --- a/drivers/acpi/executer/exfldio.c +++ b/drivers/acpi/executer/exfldio.c @@ -113,6 +113,7 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc, } if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS) { + /* SMBus has a non-linear address space */ return_ACPI_STATUS(AE_OK); @@ -491,6 +492,7 @@ acpi_ex_field_datum_io(union acpi_operand_object *obj_desc, value)); if (read_write == ACPI_READ) { + /* Read the datum from the data_register */ status = @@ -568,6 +570,7 @@ acpi_ex_write_with_update_rule(union acpi_operand_object *obj_desc, /* If the mask is all ones, we don't need to worry about the update rule */ if (mask != ACPI_INTEGER_MAX) { + /* Decode the update rule */ switch (obj_desc->common_field. @@ -704,6 +707,7 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc, /* Read the rest of the field */ for (i = 1; i < field_datum_count; i++) { + /* Get next input datum from the field */ field_offset += obj_desc->common_field.access_byte_width; @@ -817,6 +821,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, /* Write the entire field */ for (i = 1; i < field_datum_count; i++) { + /* Write merged datum to the target field */ merged_datum &= mask; diff --git a/drivers/acpi/executer/exmisc.c b/drivers/acpi/executer/exmisc.c index 48c18d29222..74f2c1a9bda 100644 --- a/drivers/acpi/executer/exmisc.c +++ b/drivers/acpi/executer/exmisc.c @@ -649,6 +649,7 @@ acpi_ex_do_logical_op(u16 opcode, /* Length and all bytes must be equal */ if ((length0 == length1) && (compare == 0)) { + /* Length and all bytes match ==> TRUE */ local_result = TRUE; diff --git a/drivers/acpi/executer/exmutex.c b/drivers/acpi/executer/exmutex.c index f843b22e20b..eaee1de5e90 100644 --- a/drivers/acpi/executer/exmutex.c +++ b/drivers/acpi/executer/exmutex.c @@ -173,6 +173,7 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc, /* Support for multiple acquires by the owning thread */ if (obj_desc->mutex.owner_thread) { + /* Special case for Global Lock, allow all threads */ if ((obj_desc->mutex.owner_thread->thread_id == @@ -192,6 +193,7 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc, status = acpi_ex_system_acquire_mutex(time_desc, obj_desc); if (ACPI_FAILURE(status)) { + /* Includes failure from a timeout on time_desc */ return_ACPI_STATUS(status); @@ -286,6 +288,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, obj_desc->mutex.acquisition_depth--; if (obj_desc->mutex.acquisition_depth != 0) { + /* Just decrement the depth and return */ return_ACPI_STATUS(AE_OK); diff --git a/drivers/acpi/executer/exnames.c b/drivers/acpi/executer/exnames.c index 054fe5e1a31..f9bc81c1b78 100644 --- a/drivers/acpi/executer/exnames.c +++ b/drivers/acpi/executer/exnames.c @@ -85,6 +85,7 @@ static char *acpi_ex_allocate_name_string(u32 prefix_count, u32 num_name_segs) * This may actually be somewhat longer than needed. */ if (prefix_count == ACPI_UINT32_MAX) { + /* Special case for root */ size_needed = 1 + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1; @@ -119,11 +120,13 @@ static char *acpi_ex_allocate_name_string(u32 prefix_count, u32 num_name_segs) /* Set up Dual or Multi prefixes if needed */ if (num_name_segs > 2) { + /* Set up multi prefixes */ *temp_ptr++ = AML_MULTI_NAME_PREFIX_OP; *temp_ptr++ = (char)num_name_segs; } else if (2 == num_name_segs) { + /* Set up dual prefixes */ *temp_ptr++ = AML_DUAL_NAME_PREFIX; @@ -184,6 +187,7 @@ static acpi_status acpi_ex_name_segment(u8 ** in_aml_address, char *name_string) /* Valid name segment */ if (index == 4) { + /* Found 4 valid characters */ char_buf[4] = '\0'; @@ -254,6 +258,7 @@ acpi_ex_get_name_string(acpi_object_type data_type, if (ACPI_TYPE_LOCAL_REGION_FIELD == data_type || ACPI_TYPE_LOCAL_BANK_FIELD == data_type || ACPI_TYPE_LOCAL_INDEX_FIELD == data_type) { + /* Disallow prefixes for types associated with field_unit names */ name_string = acpi_ex_allocate_name_string(0, 1); @@ -410,6 +415,7 @@ acpi_ex_get_name_string(acpi_object_type data_type, } if (AE_CTRL_PENDING == status && has_prefix) { + /* Ran out of segments after processing a prefix */ ACPI_ERROR((AE_INFO, "Malformed Name at %p", name_string)); diff --git a/drivers/acpi/executer/exoparg1.c b/drivers/acpi/executer/exoparg1.c index 23d0823bcd5..4f3627ee2b2 100644 --- a/drivers/acpi/executer/exoparg1.c +++ b/drivers/acpi/executer/exoparg1.c @@ -342,6 +342,7 @@ acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state) for (i = 0; (i < acpi_gbl_integer_nybble_width) && (digit > 0); i++) { + /* Get the least significant 4-bit BCD digit */ temp32 = ((u32) digit) & 0xF; @@ -487,6 +488,7 @@ acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state) status = acpi_ex_convert_to_string(operand[0], &return_desc, ACPI_EXPLICIT_CONVERT_DECIMAL); if (return_desc == operand[0]) { + /* No conversion performed, add ref to handle return value */ acpi_ut_add_reference(return_desc); } @@ -497,6 +499,7 @@ acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state) status = acpi_ex_convert_to_string(operand[0], &return_desc, ACPI_EXPLICIT_CONVERT_HEX); if (return_desc == operand[0]) { + /* No conversion performed, add ref to handle return value */ acpi_ut_add_reference(return_desc); } @@ -506,6 +509,7 @@ acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state) status = acpi_ex_convert_to_buffer(operand[0], &return_desc); if (return_desc == operand[0]) { + /* No conversion performed, add ref to handle return value */ acpi_ut_add_reference(return_desc); } @@ -516,6 +520,7 @@ acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state) status = acpi_ex_convert_to_integer(operand[0], &return_desc, ACPI_ANY_BASE); if (return_desc == operand[0]) { + /* No conversion performed, add ref to handle return value */ acpi_ut_add_reference(return_desc); } @@ -541,6 +546,7 @@ acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state) } if (ACPI_SUCCESS(status)) { + /* Store the return value computed above into the target object */ status = acpi_ex_store(return_desc, operand[1], walk_state); @@ -625,6 +631,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) temp_desc = operand[0]; if (ACPI_GET_DESCRIPTOR_TYPE(temp_desc) == ACPI_DESC_TYPE_OPERAND) { + /* Internal reference object - prevent deletion */ acpi_ut_add_reference(temp_desc); @@ -777,8 +784,25 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) /* Check for a method local or argument, or standalone String */ - if (ACPI_GET_DESCRIPTOR_TYPE(operand[0]) != + if (ACPI_GET_DESCRIPTOR_TYPE(operand[0]) == ACPI_DESC_TYPE_NAMED) { + temp_desc = + acpi_ns_get_attached_object((struct + acpi_namespace_node *) + operand[0]); + if (temp_desc + && + ((ACPI_GET_OBJECT_TYPE(temp_desc) == + ACPI_TYPE_STRING) + || (ACPI_GET_OBJECT_TYPE(temp_desc) == + ACPI_TYPE_LOCAL_REFERENCE))) { + operand[0] = temp_desc; + acpi_ut_add_reference(temp_desc); + } else { + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + } else { switch (ACPI_GET_OBJECT_TYPE(operand[0])) { case ACPI_TYPE_LOCAL_REFERENCE: /* @@ -827,13 +851,24 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) break; case ACPI_TYPE_STRING: + break; + default: + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + } + + if (ACPI_GET_DESCRIPTOR_TYPE(operand[0]) != + ACPI_DESC_TYPE_NAMED) { + if (ACPI_GET_OBJECT_TYPE(operand[0]) == + ACPI_TYPE_STRING) { /* * This is a deref_of (String). The string is a reference * to a named ACPI object. * * 1) Find the owning Node - * 2) Dereference the node to an actual object. Could be a + * 2) Dereference the node to an actual object. Could be a * Field, so we need to resolve the node to a value. */ status = @@ -857,11 +892,6 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) (struct acpi_namespace_node, &return_desc), walk_state); goto cleanup; - - default: - - status = AE_AML_OPERAND_TYPE; - goto cleanup; } } diff --git a/drivers/acpi/executer/exoparg2.c b/drivers/acpi/executer/exoparg2.c index e263a5ddd40..5e1abb12c74 100644 --- a/drivers/acpi/executer/exoparg2.c +++ b/drivers/acpi/executer/exoparg2.c @@ -138,6 +138,7 @@ acpi_status acpi_ex_opcode_2A_0T_0R(struct acpi_walk_state *walk_state) acpi_ev_check_for_wake_only_gpe(walk_state-> gpe_event_info); if (ACPI_FAILURE(status)) { + /* AE_WAKE_ONLY_GPE only error, means ignore this notify */ return_ACPI_STATUS(AE_OK) @@ -252,6 +253,7 @@ acpi_status acpi_ex_opcode_2A_2T_1R(struct acpi_walk_state *walk_state) acpi_ut_remove_reference(return_desc2); if (ACPI_FAILURE(status)) { + /* Delete the return object */ acpi_ut_remove_reference(return_desc1); @@ -287,6 +289,7 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state) /* Execute the opcode */ if (walk_state->op_info->flags & AML_MATH) { + /* All simple math opcodes (add, etc.) */ return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); @@ -383,54 +386,70 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state) goto cleanup; } + /* Initialize the Index reference object */ + index = operand[1]->integer.value; + return_desc->reference.offset = (u32) index; + return_desc->reference.opcode = AML_INDEX_OP; + return_desc->reference.object = operand[0]; - /* At this point, the Source operand is a Package, Buffer, or String */ + /* + * At this point, the Source operand is a String, Buffer, or Package. + * Verify that the index is within range. + */ + switch (ACPI_GET_OBJECT_TYPE(operand[0])) { + case ACPI_TYPE_STRING: - if (ACPI_GET_OBJECT_TYPE(operand[0]) == ACPI_TYPE_PACKAGE) { - /* Object to be indexed is a Package */ + if (index >= operand[0]->string.length) { + status = AE_AML_STRING_LIMIT; + } + + return_desc->reference.target_type = + ACPI_TYPE_BUFFER_FIELD; + break; + + case ACPI_TYPE_BUFFER: + + if (index >= operand[0]->buffer.length) { + status = AE_AML_BUFFER_LIMIT; + } + + return_desc->reference.target_type = + ACPI_TYPE_BUFFER_FIELD; + break; + + case ACPI_TYPE_PACKAGE: if (index >= operand[0]->package.count) { - ACPI_ERROR((AE_INFO, - "Index value (%X%8.8X) beyond package end (%X)", - ACPI_FORMAT_UINT64(index), - operand[0]->package.count)); status = AE_AML_PACKAGE_LIMIT; - goto cleanup; } return_desc->reference.target_type = ACPI_TYPE_PACKAGE; - return_desc->reference.object = operand[0]; return_desc->reference.where = &operand[0]->package.elements[index]; - } else { - /* Object to be indexed is a Buffer/String */ + break; - if (index >= operand[0]->buffer.length) { - ACPI_ERROR((AE_INFO, - "Index value (%X%8.8X) beyond end of buffer (%X)", - ACPI_FORMAT_UINT64(index), - operand[0]->buffer.length)); - status = AE_AML_BUFFER_LIMIT; - goto cleanup; - } + default: - return_desc->reference.target_type = - ACPI_TYPE_BUFFER_FIELD; - return_desc->reference.object = operand[0]; + status = AE_AML_INTERNAL; + goto cleanup; + } + + /* Failure means that the Index was beyond the end of the object */ + + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "Index (%X%8.8X) is beyond end of object", + ACPI_FORMAT_UINT64(index))); + goto cleanup; } /* * Add a reference to the target package/buffer/string for the life - * of the index. + * of the index */ acpi_ut_add_reference(operand[0]); - /* Complete the Index reference object */ - - return_desc->reference.opcode = AML_INDEX_OP; - return_desc->reference.offset = (u32) index; - /* Store the reference to the Target */ status = acpi_ex_store(return_desc, operand[2], walk_state); @@ -509,6 +528,7 @@ acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state) /* Execute the Opcode */ if (walk_state->op_info->flags & AML_LOGICAL_NUMERIC) { + /* logical_op (Operand0, Operand1) */ status = acpi_ex_do_logical_numeric_op(walk_state->opcode, @@ -518,6 +538,7 @@ acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state) value, &logical_result); goto store_logical_result; } else if (walk_state->op_info->flags & AML_LOGICAL) { + /* logical_op (Operand0, Operand1) */ status = acpi_ex_do_logical_op(walk_state->opcode, operand[0], diff --git a/drivers/acpi/executer/exoparg3.c b/drivers/acpi/executer/exoparg3.c index 6a3a883cb8a..8da794ec35b 100644 --- a/drivers/acpi/executer/exoparg3.c +++ b/drivers/acpi/executer/exoparg3.c @@ -208,6 +208,7 @@ acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state) /* If the requested length is zero, don't allocate a buffer */ if (length > 0) { + /* Allocate a new buffer for the Buffer */ buffer = ACPI_MEM_CALLOCATE(length); @@ -225,6 +226,7 @@ acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state) } if (buffer) { + /* We have a buffer, copy the portion requested */ ACPI_MEMCPY(buffer, operand[0]->string.pointer + index, diff --git a/drivers/acpi/executer/exoparg6.c b/drivers/acpi/executer/exoparg6.c index e043d924444..33e4fb1addc 100644 --- a/drivers/acpi/executer/exoparg6.c +++ b/drivers/acpi/executer/exoparg6.c @@ -276,6 +276,7 @@ acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state * walk_state) * match was found. */ for (; index < operand[0]->package.count; index++) { + /* Get the current package element */ this_element = operand[0]->package.elements[index]; diff --git a/drivers/acpi/executer/exregion.c b/drivers/acpi/executer/exregion.c index 6a4cfdff606..9db68d19253 100644 --- a/drivers/acpi/executer/exregion.c +++ b/drivers/acpi/executer/exregion.c @@ -135,6 +135,7 @@ acpi_ex_system_memory_space_handler(u32 function, * Delete the existing mapping and create a new one. */ if (mem_info->mapped_length) { + /* Valid mapping, delete it */ acpi_os_unmap_memory(mem_info->mapped_logical_address, diff --git a/drivers/acpi/executer/exresnte.c b/drivers/acpi/executer/exresnte.c index 01b26c80d22..417d914d9e1 100644 --- a/drivers/acpi/executer/exresnte.c +++ b/drivers/acpi/executer/exresnte.c @@ -103,6 +103,7 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, if ((entry_type == ACPI_TYPE_LOCAL_ALIAS) || (entry_type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) { + /* There is always exactly one level of indirection */ node = ACPI_CAST_PTR(struct acpi_namespace_node, node->object); @@ -141,6 +142,7 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, status = acpi_ds_get_package_arguments(source_desc); if (ACPI_SUCCESS(status)) { + /* Return an additional reference to the object */ obj_desc = source_desc; @@ -158,6 +160,7 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, status = acpi_ds_get_buffer_arguments(source_desc); if (ACPI_SUCCESS(status)) { + /* Return an additional reference to the object */ obj_desc = source_desc; @@ -240,6 +243,8 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, /* This is a ddb_handle */ /* Return an additional reference to the object */ + case AML_REF_OF_OP: + obj_desc = source_desc; acpi_ut_add_reference(obj_desc); break; diff --git a/drivers/acpi/executer/exresolv.c b/drivers/acpi/executer/exresolv.c index 1deed492fe8..22dabdd1060 100644 --- a/drivers/acpi/executer/exresolv.c +++ b/drivers/acpi/executer/exresolv.c @@ -382,10 +382,16 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, while (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_REFERENCE) { switch (obj_desc->reference.opcode) { case AML_REF_OF_OP: + case AML_INT_NAMEPATH_OP: /* Dereference the reference pointer */ - node = obj_desc->reference.object; + if (obj_desc->reference.opcode == AML_REF_OF_OP) { + node = obj_desc->reference.object; + } else { /* AML_INT_NAMEPATH_OP */ + + node = obj_desc->reference.node; + } /* All "References" point to a NS node */ @@ -401,6 +407,7 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, obj_desc = acpi_ns_get_attached_object(node); if (!obj_desc) { + /* No object, use the NS node type */ type = acpi_ns_get_type(node); @@ -432,6 +439,7 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, */ obj_desc = *(obj_desc->reference.where); if (!obj_desc) { + /* NULL package elements are allowed */ type = 0; /* Uninitialized */ @@ -439,39 +447,6 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, } break; - case AML_INT_NAMEPATH_OP: - - /* Dereference the reference pointer */ - - node = obj_desc->reference.node; - - /* All "References" point to a NS node */ - - if (ACPI_GET_DESCRIPTOR_TYPE(node) != - ACPI_DESC_TYPE_NAMED) { - ACPI_ERROR((AE_INFO, "Not a NS node %p [%s]", - node, - acpi_ut_get_descriptor_name(node))); - return_ACPI_STATUS(AE_AML_INTERNAL); - } - - /* Get the attached object */ - - obj_desc = acpi_ns_get_attached_object(node); - if (!obj_desc) { - /* No object, use the NS node type */ - - type = acpi_ns_get_type(node); - goto exit; - } - - /* Check for circular references */ - - if (obj_desc == operand) { - return_ACPI_STATUS(AE_AML_CIRCULAR_REFERENCE); - } - break; - case AML_LOCAL_OP: case AML_ARG_OP: diff --git a/drivers/acpi/executer/exresop.c b/drivers/acpi/executer/exresop.c index a1c000f5a41..42b9089dccc 100644 --- a/drivers/acpi/executer/exresop.c +++ b/drivers/acpi/executer/exresop.c @@ -77,6 +77,7 @@ acpi_ex_check_object_type(acpi_object_type type_needed, ACPI_FUNCTION_ENTRY(); if (type_needed == ACPI_TYPE_ANY) { + /* All types OK, so we don't perform any typechecks */ return (AE_OK); @@ -224,6 +225,7 @@ acpi_ex_resolve_operands(u16 opcode, } if (object_type == (u8) ACPI_TYPE_LOCAL_REFERENCE) { + /* Decode the Reference */ op_info = acpi_ps_get_opcode_info(opcode); @@ -332,6 +334,7 @@ acpi_ex_resolve_operands(u16 opcode, } if (obj_desc->reference.opcode == AML_NAME_OP) { + /* Convert a named reference to the actual named object */ temp_node = obj_desc->reference.object; @@ -662,6 +665,7 @@ acpi_ex_resolve_operands(u16 opcode, } if (target_op == AML_DEBUG_OP) { + /* Allow store of any object to the Debug object */ break; diff --git a/drivers/acpi/executer/exstore.c b/drivers/acpi/executer/exstore.c index 3f020c0e2b9..287476f319f 100644 --- a/drivers/acpi/executer/exstore.c +++ b/drivers/acpi/executer/exstore.c @@ -423,6 +423,7 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc, } if (obj_desc) { + /* Decrement reference count by the ref count of the parent package */ for (i = 0; i < ((union acpi_operand_object *) @@ -572,6 +573,7 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, /* If no implicit conversion, drop into the default case below */ if ((!implicit_conversion) || (walk_state->opcode == AML_COPY_OP)) { + /* Force execution of default (no implicit conversion) */ target_type = ACPI_TYPE_ANY; diff --git a/drivers/acpi/executer/exstoren.c b/drivers/acpi/executer/exstoren.c index 42967baf760..969f9cbbbee 100644 --- a/drivers/acpi/executer/exstoren.c +++ b/drivers/acpi/executer/exstoren.c @@ -97,6 +97,7 @@ acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr, */ if (ACPI_GET_OBJECT_TYPE(source_desc) == ACPI_TYPE_LOCAL_REFERENCE) { + /* Resolve a reference object first */ status = @@ -121,6 +122,7 @@ acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr, !((ACPI_GET_OBJECT_TYPE(source_desc) == ACPI_TYPE_LOCAL_REFERENCE) && (source_desc->reference.opcode == AML_LOAD_OP))) { + /* Conversion successful but still not a valid type */ ACPI_ERROR((AE_INFO, @@ -289,6 +291,7 @@ acpi_ex_store_object_to_object(union acpi_operand_object *source_desc, } if (actual_src_desc != source_desc) { + /* Delete the intermediate (temporary) source object */ acpi_ut_remove_reference(actual_src_desc); diff --git a/drivers/acpi/executer/exstorob.c b/drivers/acpi/executer/exstorob.c index 6ab70708775..41732d382bc 100644 --- a/drivers/acpi/executer/exstorob.c +++ b/drivers/acpi/executer/exstorob.c @@ -91,6 +91,7 @@ acpi_ex_store_buffer_to_buffer(union acpi_operand_object *source_desc, /* Copy source buffer to target buffer */ if (length <= target_desc->buffer.length) { + /* Clear existing buffer and copy in the new one */ ACPI_MEMSET(target_desc->buffer.pointer, 0, @@ -113,6 +114,7 @@ acpi_ex_store_buffer_to_buffer(union acpi_operand_object *source_desc, * copy must not truncate the original buffer. */ if (original_src_type == ACPI_TYPE_STRING) { + /* Set the new length of the target */ target_desc->buffer.length = length; @@ -183,6 +185,7 @@ acpi_ex_store_string_to_string(union acpi_operand_object *source_desc, */ if (target_desc->string.pointer && (!(target_desc->common.flags & AOPOBJ_STATIC_POINTER))) { + /* Only free if not a pointer into the DSDT */ ACPI_MEM_FREE(target_desc->string.pointer); diff --git a/drivers/acpi/executer/exsystem.c b/drivers/acpi/executer/exsystem.c index ea9144f42e1..6a2e47a0e11 100644 --- a/drivers/acpi/executer/exsystem.c +++ b/drivers/acpi/executer/exsystem.c @@ -76,6 +76,7 @@ acpi_status acpi_ex_system_wait_semaphore(acpi_handle semaphore, u16 timeout) } if (status == AE_TIME) { + /* We must wait, so unlock the interpreter */ acpi_ex_exit_interpreter(); @@ -90,6 +91,7 @@ acpi_status acpi_ex_system_wait_semaphore(acpi_handle semaphore, u16 timeout) status2 = acpi_ex_enter_interpreter(); if (ACPI_FAILURE(status2)) { + /* Report fatal error, could not acquire interpreter */ return_ACPI_STATUS(status2); diff --git a/drivers/acpi/executer/exutils.c b/drivers/acpi/executer/exutils.c index f73a61aeb7e..8543d1a0ed3 100644 --- a/drivers/acpi/executer/exutils.c +++ b/drivers/acpi/executer/exutils.c @@ -194,6 +194,7 @@ u8 acpi_ex_acquire_global_lock(u32 field_flags) /* Only attempt lock if the always_lock bit is set */ if (field_flags & AML_FIELD_LOCK_RULE_MASK) { + /* We should attempt to get the lock, wait forever */ status = acpi_ev_acquire_global_lock(ACPI_WAIT_FOREVER); @@ -230,10 +231,12 @@ void acpi_ex_release_global_lock(u8 locked_by_me) /* Only attempt unlock if the caller locked it */ if (locked_by_me) { + /* OK, now release the lock */ status = acpi_ev_release_global_lock(); if (ACPI_FAILURE(status)) { + /* Report the error, but there isn't much else we can do */ ACPI_EXCEPTION((AE_INFO, status, diff --git a/drivers/acpi/hardware/hwgpe.c b/drivers/acpi/hardware/hwgpe.c index d84942d22dd..729b68eb3e3 100644 --- a/drivers/acpi/hardware/hwgpe.c +++ b/drivers/acpi/hardware/hwgpe.c @@ -214,6 +214,7 @@ acpi_hw_disable_gpe_block(struct acpi_gpe_xrupt_info * gpe_xrupt_info, /* Examine each GPE Register within the block */ for (i = 0; i < gpe_block->register_count; i++) { + /* Disable all GPEs in this register */ status = acpi_hw_low_level_write(8, 0x00, @@ -250,6 +251,7 @@ acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info * gpe_xrupt_info, /* Examine each GPE Register within the block */ for (i = 0; i < gpe_block->register_count; i++) { + /* Clear status on all GPEs in this register */ status = acpi_hw_low_level_write(8, 0xFF, diff --git a/drivers/acpi/hardware/hwregs.c b/drivers/acpi/hardware/hwregs.c index e1fe7549841..95c4ccb3a37 100644 --- a/drivers/acpi/hardware/hwregs.c +++ b/drivers/acpi/hardware/hwregs.c @@ -295,6 +295,7 @@ acpi_status acpi_get_register(u32 register_id, u32 * return_value, u32 flags) } if (ACPI_SUCCESS(status)) { + /* Normalize the value that was read */ register_value = diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c index 89269272fd6..284a59ebcc2 100644 --- a/drivers/acpi/hardware/hwsleep.c +++ b/drivers/acpi/hardware/hwsleep.c @@ -490,6 +490,7 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state) ACPI_REGISTER_PM1_CONTROL, &PM1Acontrol); if (ACPI_SUCCESS(status)) { + /* Clear SLP_EN and SLP_TYP fields */ PM1Acontrol &= ~(sleep_type_reg_info->access_bit_mask | diff --git a/drivers/acpi/hardware/hwtimer.c b/drivers/acpi/hardware/hwtimer.c index fc10b7cb456..ef7c98e293a 100644 --- a/drivers/acpi/hardware/hwtimer.c +++ b/drivers/acpi/hardware/hwtimer.c @@ -155,6 +155,7 @@ acpi_get_timer_duration(u32 start_ticks, u32 end_ticks, u32 * time_elapsed) delta_ticks = end_ticks - start_ticks; } else if (start_ticks > end_ticks) { if (0 == acpi_gbl_FADT->tmr_val_ext) { + /* 24-bit Timer */ delta_ticks = diff --git a/drivers/acpi/namespace/nsaccess.c b/drivers/acpi/namespace/nsaccess.c index 1149bc18fb3..6bdad8bfcf0 100644 --- a/drivers/acpi/namespace/nsaccess.c +++ b/drivers/acpi/namespace/nsaccess.c @@ -98,6 +98,7 @@ acpi_status acpi_ns_root_initialize(void) "Entering predefined entries into namespace\n")); for (init_val = acpi_gbl_pre_defined_names; init_val->name; init_val++) { + /* _OSI is optional for now, will be permanent later */ if (!ACPI_STRCMP(init_val->name, "_OSI") @@ -365,6 +366,7 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, * Begin examination of the actual pathname */ if (!pathname) { + /* A Null name_path is allowed and refers to the root */ num_segments = 0; @@ -389,6 +391,7 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, * to the current scope). */ if (*path == (u8) AML_ROOT_PREFIX) { + /* Pathname is fully qualified, start from the root */ this_node = acpi_gbl_root_node; @@ -416,6 +419,7 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, this_node = prefix_node; num_carats = 0; while (*path == (u8) AML_PARENT_PREFIX) { + /* Name is fully qualified, no search rules apply */ search_parent_flag = ACPI_NS_NO_UPSEARCH; @@ -430,6 +434,7 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, num_carats++; this_node = acpi_ns_get_parent_node(this_node); if (!this_node) { + /* Current scope has no parent scope */ ACPI_ERROR((AE_INFO, @@ -569,6 +574,7 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, &this_node); if (ACPI_FAILURE(status)) { if (status == AE_NOT_FOUND) { + /* Name not found in ACPI namespace */ ACPI_DEBUG_PRINT((ACPI_DB_NAMES, @@ -602,6 +608,7 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, (type_to_check_for != ACPI_TYPE_LOCAL_SCOPE) && (this_node->type != ACPI_TYPE_ANY) && (this_node->type != type_to_check_for)) { + /* Complain about a type mismatch */ ACPI_WARNING((AE_INFO, diff --git a/drivers/acpi/namespace/nsalloc.c b/drivers/acpi/namespace/nsalloc.c index 9b871f38b61..cd26cb971a1 100644 --- a/drivers/acpi/namespace/nsalloc.c +++ b/drivers/acpi/namespace/nsalloc.c @@ -115,6 +115,7 @@ void acpi_ns_delete_node(struct acpi_namespace_node *node) } if (prev_node) { + /* Node is not first child, unlink it */ prev_node->peer = next_node->peer; @@ -125,6 +126,7 @@ void acpi_ns_delete_node(struct acpi_namespace_node *node) /* Node is first child (has no previous peer) */ if (next_node->flags & ANOBJ_END_OF_PEER_LIST) { + /* No peers at all */ parent_node->child = NULL; @@ -264,6 +266,7 @@ void acpi_ns_delete_children(struct acpi_namespace_node *parent_node) * Deallocate all children at this level */ do { + /* Get the things we need */ next_node = child_node->peer; @@ -352,11 +355,13 @@ void acpi_ns_delete_namespace_subtree(struct acpi_namespace_node *parent_node) * to where we started. */ while (level > 0) { + /* Get the next node in this scope (NULL if none) */ child_node = acpi_ns_get_next_node(ACPI_TYPE_ANY, parent_node, child_node); if (child_node) { + /* Found a child node - detach any attached object */ acpi_ns_detach_object(child_node); @@ -427,6 +432,7 @@ static void acpi_ns_remove_reference(struct acpi_namespace_node *node) */ this_node = node; while (this_node) { + /* Prepare to move up to parent */ parent_node = acpi_ns_get_parent_node(this_node); @@ -438,6 +444,7 @@ static void acpi_ns_remove_reference(struct acpi_namespace_node *node) /* Delete the node if no more references */ if (!this_node->reference_count) { + /* Delete all children and delete the node */ acpi_ns_delete_children(this_node); @@ -500,6 +507,7 @@ void acpi_ns_delete_namespace_by_owner(acpi_owner_id owner_id) if (child_node) { if (child_node->owner_id == owner_id) { + /* Found a matching child node - detach any attached object */ acpi_ns_detach_object(child_node); diff --git a/drivers/acpi/namespace/nsdump.c b/drivers/acpi/namespace/nsdump.c index a2807317a84..e275373b170 100644 --- a/drivers/acpi/namespace/nsdump.c +++ b/drivers/acpi/namespace/nsdump.c @@ -191,6 +191,7 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, } if (!(info->display_type & ACPI_DISPLAY_SHORT)) { + /* Indent the object according to the level */ acpi_os_printf("%2d%*s", (u32) level - 1, (int)level * 2, " "); @@ -226,6 +227,7 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, case ACPI_DISPLAY_SUMMARY: if (!obj_desc) { + /* No attached object, we are done */ acpi_os_printf("\n"); @@ -419,6 +421,7 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, acpi_os_printf("O:%p", obj_desc); if (!obj_desc) { + /* No attached object, we are done */ acpi_os_printf("\n"); @@ -682,6 +685,7 @@ void acpi_ns_dump_tables(acpi_handle search_base, u32 max_depth) } if (ACPI_NS_ALL == search_base) { + /* Entire namespace */ search_handle = acpi_gbl_root_node; diff --git a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c index 19d7b94d40c..80ef9554563 100644 --- a/drivers/acpi/namespace/nseval.c +++ b/drivers/acpi/namespace/nseval.c @@ -326,6 +326,7 @@ acpi_status acpi_ns_evaluate_by_handle(struct acpi_parameter_info *info) * Check if there is a return value on the stack that must be dealt with */ if (status == AE_CTRL_RETURN_VALUE) { + /* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */ status = AE_OK; diff --git a/drivers/acpi/namespace/nsinit.c b/drivers/acpi/namespace/nsinit.c index 9f929e479fd..9aa337c3388 100644 --- a/drivers/acpi/namespace/nsinit.c +++ b/drivers/acpi/namespace/nsinit.c @@ -366,6 +366,7 @@ acpi_ns_init_one_device(acpi_handle obj_handle, status = acpi_ns_search_node(*ACPI_CAST_PTR(u32, METHOD_NAME__INI), device_node, ACPI_TYPE_METHOD, &ini_node); if (ACPI_FAILURE(status)) { + /* No _INI method found - move on to next device */ return_ACPI_STATUS(AE_OK); @@ -386,6 +387,7 @@ acpi_ns_init_one_device(acpi_handle obj_handle, status = acpi_ut_execute_STA(pinfo.node, &flags); if (ACPI_FAILURE(status)) { + /* Ignore error and move on to next device */ return_ACPI_STATUS(AE_OK); @@ -396,6 +398,7 @@ acpi_ns_init_one_device(acpi_handle obj_handle, } if (!(flags & ACPI_STA_DEVICE_PRESENT)) { + /* Don't look at children of a not present device */ return_ACPI_STATUS(AE_CTRL_DEPTH); @@ -412,6 +415,7 @@ acpi_ns_init_one_device(acpi_handle obj_handle, pinfo.node = ini_node; status = acpi_ns_evaluate_by_handle(&pinfo); if (ACPI_FAILURE(status)) { + /* Ignore error and move on to next device */ #ifdef ACPI_DEBUG_OUTPUT @@ -435,6 +439,7 @@ acpi_ns_init_one_device(acpi_handle obj_handle, } if (acpi_gbl_init_handler) { + /* External initialization handler is present, call it */ status = diff --git a/drivers/acpi/namespace/nsload.c b/drivers/acpi/namespace/nsload.c index 4e0b0524c18..80acfd35f3e 100644 --- a/drivers/acpi/namespace/nsload.c +++ b/drivers/acpi/namespace/nsload.c @@ -84,6 +84,7 @@ acpi_ns_load_table(struct acpi_table_desc *table_desc, if (! (acpi_gbl_table_data[table_desc->type]. flags & ACPI_TABLE_EXECUTABLE)) { + /* Just ignore this table */ return_ACPI_STATUS(AE_OK); @@ -325,6 +326,7 @@ static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle) * to where we started. */ while (level > 0) { + /* Attempt to get the next object in this scope */ status = acpi_get_next_object(ACPI_TYPE_ANY, parent_handle, @@ -335,6 +337,7 @@ static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle) /* Did we get a new object? */ if (ACPI_SUCCESS(status)) { + /* Check if this object has any children */ if (ACPI_SUCCESS diff --git a/drivers/acpi/namespace/nsobject.c b/drivers/acpi/namespace/nsobject.c index 10ae6292bca..39dc87b228f 100644 --- a/drivers/acpi/namespace/nsobject.c +++ b/drivers/acpi/namespace/nsobject.c @@ -82,6 +82,7 @@ acpi_ns_attach_object(struct acpi_namespace_node *node, * Parameter validation */ if (!node) { + /* Invalid handle */ ACPI_ERROR((AE_INFO, "Null named_obj handle")); @@ -89,6 +90,7 @@ acpi_ns_attach_object(struct acpi_namespace_node *node, } if (!object && (ACPI_TYPE_ANY != type)) { + /* Null object */ ACPI_ERROR((AE_INFO, @@ -97,6 +99,7 @@ acpi_ns_attach_object(struct acpi_namespace_node *node, } if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) { + /* Not a name handle */ ACPI_ERROR((AE_INFO, "Invalid handle %p [%s]", diff --git a/drivers/acpi/namespace/nssearch.c b/drivers/acpi/namespace/nssearch.c index d64b78952f2..f73a3d56616 100644 --- a/drivers/acpi/namespace/nssearch.c +++ b/drivers/acpi/namespace/nssearch.c @@ -114,9 +114,11 @@ acpi_ns_search_node(u32 target_name, */ next_node = node->child; while (next_node) { + /* Check for match against the name */ if (next_node->name.integer == target_name) { + /* Resolve a control method alias if any */ if (acpi_ns_get_type(next_node) == @@ -146,6 +148,7 @@ acpi_ns_search_node(u32 target_name, * so a flag is used to indicate the end-of-list */ if (next_node->flags & ANOBJ_END_OF_PEER_LIST) { + /* Searched entire list, we are done */ break; diff --git a/drivers/acpi/namespace/nsutils.c b/drivers/acpi/namespace/nsutils.c index 3e7cad549a3..e8c779114be 100644 --- a/drivers/acpi/namespace/nsutils.c +++ b/drivers/acpi/namespace/nsutils.c @@ -83,6 +83,7 @@ acpi_ns_report_error(char *module_name, acpi_ut_report_error(module_name, line_number); if (lookup_status == AE_BAD_CHARACTER) { + /* There is a non-ascii character in the name */ acpi_os_printf("[0x%4.4X] (NON-ASCII)", @@ -267,6 +268,7 @@ u32 acpi_ns_local(acpi_object_type type) ACPI_FUNCTION_TRACE("ns_local"); if (!acpi_ut_valid_object_type(type)) { + /* Type code out of range */ ACPI_WARNING((AE_INFO, "Invalid Object Type %X", type)); @@ -411,6 +413,7 @@ acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info) for (i = 0; i < ACPI_NAME_SIZE; i++) { if (acpi_ns_valid_path_separator(*external_name) || (*external_name == 0)) { + /* Pad the segment with underscore(s) if segment is short */ result[i] = '_'; @@ -795,6 +798,7 @@ u32 acpi_ns_opens_scope(acpi_object_type type) ACPI_FUNCTION_TRACE_STR("ns_opens_scope", acpi_ut_get_type_name(type)); if (!acpi_ut_valid_object_type(type)) { + /* type code out of range */ ACPI_WARNING((AE_INFO, "Invalid Object Type %X", type)); @@ -838,6 +842,7 @@ acpi_ns_get_node_by_path(char *pathname, ACPI_FUNCTION_TRACE_PTR("ns_get_node_by_path", pathname); if (pathname) { + /* Convert path to internal representation */ status = acpi_ns_internalize_name(pathname, &internal_path); @@ -963,6 +968,7 @@ acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node * child_node) ACPI_FUNCTION_TRACE("ns_find_parent_name"); if (child_node) { + /* Valid entry. Get the parent Node */ parent_node = acpi_ns_get_parent_node(child_node); diff --git a/drivers/acpi/namespace/nswalk.c b/drivers/acpi/namespace/nswalk.c index fcab1e784b8..6bbc734bfee 100644 --- a/drivers/acpi/namespace/nswalk.c +++ b/drivers/acpi/namespace/nswalk.c @@ -76,6 +76,7 @@ struct acpi_namespace_node *acpi_ns_get_next_node(acpi_object_type type, ACPI_FUNCTION_ENTRY(); if (!child_node) { + /* It's really the parent's _scope_ that we want */ if (parent_node->child) { @@ -92,6 +93,7 @@ struct acpi_namespace_node *acpi_ns_get_next_node(acpi_object_type type, /* If any type is OK, we are done */ if (type == ACPI_TYPE_ANY) { + /* next_node is NULL if we are at the end-of-list */ return (next_node); @@ -100,6 +102,7 @@ struct acpi_namespace_node *acpi_ns_get_next_node(acpi_object_type type, /* Must search for the node -- but within this scope only */ while (next_node) { + /* If type matches, we are done */ if (next_node->type == type) { @@ -182,6 +185,7 @@ acpi_ns_walk_namespace(acpi_object_type type, * bubbled up to (and passed) the original parent handle (start_entry) */ while (level > 0) { + /* Get the next node in this scope. Null if not found */ status = AE_OK; diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c index a95f636dc35..71e7769d7da 100644 --- a/drivers/acpi/namespace/nsxfeval.c +++ b/drivers/acpi/namespace/nsxfeval.c @@ -110,6 +110,7 @@ acpi_evaluate_object_typed(acpi_handle handle, } if (return_buffer->length == 0) { + /* Error because caller specifically asked for a return value */ ACPI_ERROR((AE_INFO, "No return value")); @@ -131,6 +132,7 @@ acpi_evaluate_object_typed(acpi_handle handle, acpi_ut_get_type_name(return_type))); if (must_free) { + /* Caller used ACPI_ALLOCATE_BUFFER, free the return buffer */ acpi_os_free(return_buffer->pointer); @@ -224,9 +226,9 @@ acpi_evaluate_object(acpi_handle handle, * 3) Valid handle */ if ((pathname) && (acpi_ns_valid_root_prefix(pathname[0]))) { - /* - * The path is fully qualified, just evaluate by name - */ + + /* The path is fully qualified, just evaluate by name */ + status = acpi_ns_evaluate_by_name(pathname, &info); } else if (!handle) { /* @@ -235,11 +237,12 @@ acpi_evaluate_object(acpi_handle handle, * qualified names above, this is an error */ if (!pathname) { - ACPI_ERROR((AE_INFO, - "Both Handle and Pathname are NULL")); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Both Handle and Pathname are NULL")); } else { - ACPI_ERROR((AE_INFO, - "Handle is NULL and Pathname is relative")); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Null Handle with relative pathname [%s]", + pathname)); } status = AE_BAD_PARAMETER; @@ -256,9 +259,8 @@ acpi_evaluate_object(acpi_handle handle, */ status = acpi_ns_evaluate_by_handle(&info); } else { - /* - * Both a Handle and a relative Pathname - */ + /* Both a Handle and a relative Pathname */ + status = acpi_ns_evaluate_relative(pathname, &info); } } @@ -295,6 +297,7 @@ acpi_evaluate_object(acpi_handle handle, acpi_ut_get_object_size(info.return_object, &buffer_space_needed); if (ACPI_SUCCESS(status)) { + /* Validate/Allocate/Clear caller buffer */ status = @@ -303,7 +306,8 @@ acpi_evaluate_object(acpi_handle handle, buffer_space_needed); if (ACPI_FAILURE(status)) { /* - * Caller's buffer is too small or a new one can't be allocated + * Caller's buffer is too small or a new one can't + * be allocated */ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Needed buffer size %X, %s\n", @@ -312,9 +316,8 @@ acpi_evaluate_object(acpi_handle handle, acpi_format_exception (status))); } else { - /* - * We have enough space for the object, build it - */ + /* We have enough space for the object, build it */ + status = acpi_ut_copy_iobject_to_eobject (info.return_object, @@ -341,10 +344,10 @@ acpi_evaluate_object(acpi_handle handle, } } - /* - * Free the input parameter list (if we created one), - */ + /* Free the input parameter list (if we created one) */ + if (info.parameters) { + /* Free the allocated parameter block */ acpi_ut_delete_internal_object_list(info.parameters); @@ -473,6 +476,7 @@ acpi_ns_get_device_callback(acpi_handle obj_handle, } if (!(flags & ACPI_STA_DEVICE_PRESENT)) { + /* Don't examine children of the device if not present */ return (AE_CTRL_DEPTH); @@ -489,6 +493,7 @@ acpi_ns_get_device_callback(acpi_handle obj_handle, } if (ACPI_STRNCMP(hid.value, info->hid, sizeof(hid.value)) != 0) { + /* Get the list of Compatible IDs */ status = acpi_ut_execute_CID(node, &cid); @@ -563,9 +568,9 @@ acpi_get_devices(char *HID, * We're going to call their callback from OUR callback, so we need * to know what it is, and their context parameter. */ + info.hid = HID; info.context = context; info.user_function = user_function; - info.hid = HID; /* * Lock the namespace around the walk. @@ -578,9 +583,8 @@ acpi_get_devices(char *HID, return_ACPI_STATUS(status); } - status = acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, - ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, - ACPI_NS_WALK_UNLOCK, + status = acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, acpi_ns_get_device_callback, &info, return_value); diff --git a/drivers/acpi/namespace/nsxfname.c b/drivers/acpi/namespace/nsxfname.c index 8cd8675a47c..55d26624ab9 100644 --- a/drivers/acpi/namespace/nsxfname.c +++ b/drivers/acpi/namespace/nsxfname.c @@ -162,6 +162,7 @@ acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer * buffer) } if (name_type == ACPI_FULL_PATHNAME) { + /* Get the full pathname (From the namespace root) */ status = acpi_ns_handle_to_pathname(handle, buffer); diff --git a/drivers/acpi/namespace/nsxfobj.c b/drivers/acpi/namespace/nsxfobj.c index a0332595677..9c5f3302799 100644 --- a/drivers/acpi/namespace/nsxfobj.c +++ b/drivers/acpi/namespace/nsxfobj.c @@ -206,6 +206,7 @@ acpi_get_next_object(acpi_object_type type, /* If null handle, use the parent */ if (!child) { + /* Start search at the beginning of the specified scope */ parent_node = acpi_ns_map_handle_to_node(parent); diff --git a/drivers/acpi/parser/psargs.c b/drivers/acpi/parser/psargs.c index de573be5271..1c5934fe185 100644 --- a/drivers/acpi/parser/psargs.c +++ b/drivers/acpi/parser/psargs.c @@ -275,6 +275,7 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state, */ if (ACPI_SUCCESS(status) && possible_method_call && (node->type == ACPI_TYPE_METHOD)) { + /* This name is actually a control method invocation */ method_desc = acpi_ns_get_attached_object(node); @@ -319,6 +320,7 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state, * some not_found cases are allowed */ if (status == AE_NOT_FOUND) { + /* 1) not_found is ok during load pass 1/2 (allow forward references) */ if ((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) != @@ -354,6 +356,7 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state, if ((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) == ACPI_PARSE_EXECUTE) { + /* Report a control method execution error */ status = acpi_ds_method_error(status, walk_state); @@ -620,6 +623,7 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state, case ARGP_FIELDLIST: if (parser_state->aml < parser_state->pkg_end) { + /* Non-empty list */ while (parser_state->aml < parser_state->pkg_end) { @@ -645,6 +649,7 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state, case ARGP_BYTELIST: if (parser_state->aml < parser_state->pkg_end) { + /* Non-empty list */ arg = acpi_ps_alloc_op(AML_INT_BYTELIST_OP); @@ -673,6 +678,7 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state, if (subop == 0 || acpi_ps_is_leading_char(subop) || acpi_ps_is_prefix_char(subop)) { + /* null_name or name_string */ arg = acpi_ps_alloc_op(AML_INT_NAMEPATH_OP); @@ -703,6 +709,7 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state, case ARGP_OBJLIST: if (parser_state->aml < parser_state->pkg_end) { + /* Non-empty list of variable arguments, nothing returned */ walk_state->arg_count = ACPI_VAR_ARGS; diff --git a/drivers/acpi/parser/psloop.c b/drivers/acpi/parser/psloop.c index 00b072e15d1..42062d5abc9 100644 --- a/drivers/acpi/parser/psloop.c +++ b/drivers/acpi/parser/psloop.c @@ -95,6 +95,7 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) #if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY)) if (walk_state->walk_type & ACPI_WALK_METHOD_RESTART) { + /* We are restarting a preempted control method */ if (acpi_ps_has_completed_scope(parser_state)) { @@ -143,6 +144,7 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Popped scope, Op=%p\n", op)); } else if (walk_state->prev_op) { + /* We were in the middle of an op */ op = walk_state->prev_op; @@ -156,6 +158,7 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) while ((parser_state->aml < parser_state->aml_end) || (op)) { aml_op_start = parser_state->aml; if (!op) { + /* Get the next opcode from the AML stream */ walk_state->aml_offset = @@ -213,6 +216,7 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) /* Create Op structure and append to parent's argument list */ if (walk_state->op_info->flags & AML_NAMED) { + /* Allocate a new pre_op if necessary */ if (!pre_op) { @@ -388,6 +392,7 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) /* Are there any arguments that must be processed? */ if (walk_state->arg_types) { + /* Get arguments */ switch (op->common.aml_opcode) { @@ -853,6 +858,7 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) } else if (ACPI_FAILURE(status)) { + /* First error is most important */ (void) diff --git a/drivers/acpi/parser/psopcode.c b/drivers/acpi/parser/psopcode.c index 11d6351ab8b..9eb8d066388 100644 --- a/drivers/acpi/parser/psopcode.c +++ b/drivers/acpi/parser/psopcode.c @@ -731,6 +731,7 @@ const struct acpi_opcode_info *acpi_ps_get_opcode_info(u16 opcode) * Detect normal 8-bit opcode or extended 16-bit opcode */ if (!(opcode & 0xFF00)) { + /* Simple (8-bit) opcode: 0-255, can't index beyond table */ return (&acpi_gbl_aml_op_info @@ -739,6 +740,7 @@ const struct acpi_opcode_info *acpi_ps_get_opcode_info(u16 opcode) if (((opcode & 0xFF00) == AML_EXTENDED_OPCODE) && (((u8) opcode) <= MAX_EXTENDED_OPCODE)) { + /* Valid extended (16-bit) opcode */ return (&acpi_gbl_aml_op_info diff --git a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c index a9f3229f410..83d8916bc1a 100644 --- a/drivers/acpi/parser/psparse.c +++ b/drivers/acpi/parser/psparse.c @@ -106,6 +106,7 @@ u16 acpi_ps_peek_opcode(struct acpi_parse_state * parser_state) opcode = (u16) ACPI_GET8(aml); if (opcode == AML_EXTENDED_OP_PREFIX) { + /* Extended opcode, get the second opcode byte */ aml++; @@ -158,6 +159,7 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state, if (op->common.parent) { prev = op->common.parent->common.value.arg; if (!prev) { + /* Nothing more to do */ goto cleanup; @@ -245,6 +247,7 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state, /* We must unlink this op from the parent tree */ if (prev == op) { + /* This op is the first in the list */ if (replacement_op) { @@ -265,6 +268,7 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state, else while (prev) { + /* Traverse all siblings in the parent's argument list */ next = prev->common.next; @@ -510,6 +514,7 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state) } else if (status == AE_CTRL_TERMINATE) { status = AE_OK; } else if ((status != AE_OK) && (walk_state->method_desc)) { + /* Either the method parse or actual execution failed */ ACPI_ERROR_METHOD("Method parse/execution failed", @@ -551,6 +556,7 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state) if (((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) == ACPI_PARSE_EXECUTE) || (ACPI_FAILURE(status))) { if (walk_state->method_desc) { + /* Decrement the thread count on the method parse tree */ if (walk_state->method_desc->method. @@ -633,12 +639,14 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state) } } else { if (previous_walk_state->return_desc) { + /* Caller doesn't want it, must delete it */ acpi_ut_remove_reference(previous_walk_state-> return_desc); } if (previous_walk_state->implicit_return_obj) { + /* Caller doesn't want it, must delete it */ acpi_ut_remove_reference(previous_walk_state-> diff --git a/drivers/acpi/parser/psscope.c b/drivers/acpi/parser/psscope.c index bc6047caccd..edb7c9ba6ec 100644 --- a/drivers/acpi/parser/psscope.c +++ b/drivers/acpi/parser/psscope.c @@ -165,6 +165,7 @@ acpi_ps_push_scope(struct acpi_parse_state *parser_state, acpi_ut_push_generic_state(&parser_state->scope, scope); if (arg_count == ACPI_VAR_ARGS) { + /* Multiple arguments */ scope->parse_scope.arg_end = parser_state->pkg_end; diff --git a/drivers/acpi/parser/pstree.c b/drivers/acpi/parser/pstree.c index dd6f16726fc..6aa0012643c 100644 --- a/drivers/acpi/parser/pstree.c +++ b/drivers/acpi/parser/pstree.c @@ -77,6 +77,7 @@ union acpi_parse_object *acpi_ps_get_arg(union acpi_parse_object *op, u32 argn) op_info = acpi_ps_get_opcode_info(op->common.aml_opcode); if (op_info->class == AML_CLASS_UNKNOWN) { + /* Invalid opcode or ASCII character */ return (NULL); @@ -85,6 +86,7 @@ union acpi_parse_object *acpi_ps_get_arg(union acpi_parse_object *op, u32 argn) /* Check if this opcode requires argument sub-objects */ if (!(op_info->flags & AML_HAS_ARGS)) { + /* Has no linked argument objects */ return (NULL); @@ -130,6 +132,7 @@ acpi_ps_append_arg(union acpi_parse_object *op, union acpi_parse_object *arg) op_info = acpi_ps_get_opcode_info(op->common.aml_opcode); if (op_info->class == AML_CLASS_UNKNOWN) { + /* Invalid opcode */ ACPI_ERROR((AE_INFO, "Invalid AML Opcode: 0x%2.2X", @@ -140,6 +143,7 @@ acpi_ps_append_arg(union acpi_parse_object *op, union acpi_parse_object *arg) /* Check if this opcode requires argument sub-objects */ if (!(op_info->flags & AML_HAS_ARGS)) { + /* Has no linked argument objects */ return; @@ -148,6 +152,7 @@ acpi_ps_append_arg(union acpi_parse_object *op, union acpi_parse_object *arg) /* Append the argument to the linked argument list */ if (op->common.value.arg) { + /* Append to existing argument list */ prev_arg = op->common.value.arg; @@ -222,12 +227,14 @@ union acpi_parse_object *acpi_ps_get_depth_next(union acpi_parse_object *origin, } if (arg == origin) { + /* Reached parent of origin, end search */ return (NULL); } if (parent->common.next) { + /* Found sibling of parent */ return (parent->common.next); diff --git a/drivers/acpi/parser/psutils.c b/drivers/acpi/parser/psutils.c index 3e07cb9cb74..a4c33a4bfe3 100644 --- a/drivers/acpi/parser/psutils.c +++ b/drivers/acpi/parser/psutils.c @@ -135,6 +135,7 @@ union acpi_parse_object *acpi_ps_alloc_op(u16 opcode) /* Allocate the minimum required size object */ if (flags == ACPI_PARSEOP_GENERIC) { + /* The generic op (default) is by far the most common (16 to 1) */ op = acpi_os_acquire_object(acpi_gbl_ps_node_cache); diff --git a/drivers/acpi/parser/pswalk.c b/drivers/acpi/parser/pswalk.c index 06f05bfd761..3d08b8c6db4 100644 --- a/drivers/acpi/parser/pswalk.c +++ b/drivers/acpi/parser/pswalk.c @@ -69,13 +69,16 @@ void acpi_ps_delete_parse_tree(union acpi_parse_object *subtree_root) /* Visit all nodes in the subtree */ while (op) { + /* Check if we are not ascending */ if (op != parent) { + /* Look for an argument or child of the current op */ next = acpi_ps_get_arg(op, 0); if (next) { + /* Still going downward in tree (Op is not completed yet) */ op = next; diff --git a/drivers/acpi/parser/psxface.c b/drivers/acpi/parser/psxface.c index 2dd48cbb7c0..e09a820ee29 100644 --- a/drivers/acpi/parser/psxface.c +++ b/drivers/acpi/parser/psxface.c @@ -317,9 +317,11 @@ acpi_ps_update_parameter_list(struct acpi_parameter_info *info, u16 action) acpi_native_uint i; if ((info->parameter_type == ACPI_PARAM_ARGS) && (info->parameters)) { + /* Update reference count for each parameter */ for (i = 0; info->parameters[i]; i++) { + /* Ignore errors, just do them all */ (void)acpi_ut_update_object_reference(info-> diff --git a/drivers/acpi/resources/rscalc.c b/drivers/acpi/resources/rscalc.c index 7d6481d9fbe..223bdc49326 100644 --- a/drivers/acpi/resources/rscalc.c +++ b/drivers/acpi/resources/rscalc.c @@ -78,6 +78,7 @@ static u8 acpi_rs_count_set_bits(u16 bit_field) ACPI_FUNCTION_ENTRY(); for (bits_set = 0; bit_field; bits_set++) { + /* Zero the least significant bit that is set */ bit_field &= (bit_field - 1); @@ -154,6 +155,7 @@ acpi_rs_stream_option_length(u32 resource_length, * length, minus one byte for the resource_source_index itself. */ if (resource_length > minimum_aml_resource_length) { + /* Compute the length of the optional string */ string_length = @@ -162,7 +164,7 @@ acpi_rs_stream_option_length(u32 resource_length, /* Round up length to 32 bits for internal structure alignment */ - return (ACPI_ROUND_UP_to_32_bITS(string_length)); + return ((u32) ACPI_ROUND_UP_to_32_bITS(string_length)); } /******************************************************************************* @@ -191,6 +193,7 @@ acpi_rs_get_aml_length(struct acpi_resource * resource, acpi_size * size_needed) /* Traverse entire list of internal resource descriptors */ while (resource) { + /* Validate the descriptor type */ if (resource->type > ACPI_RESOURCE_TYPE_MAX) { @@ -214,6 +217,7 @@ acpi_rs_get_aml_length(struct acpi_resource * resource, acpi_size * size_needed) * is a Large Resource data type. */ if (resource->data.vendor.byte_length > 7) { + /* Base size of a Large resource descriptor */ total_size = @@ -346,6 +350,7 @@ acpi_rs_get_list_length(u8 * aml_buffer, /* Walk the list of AML resource descriptors */ while (aml_buffer < end_aml) { + /* Validate the Resource Type and Resource Length */ status = acpi_ut_validate_resource(aml_buffer, &resource_index); @@ -390,7 +395,7 @@ acpi_rs_get_list_length(u8 * aml_buffer, * Vendor Resource: * Ensure a 32-bit boundary for the structure */ - extra_struct_bytes = + extra_struct_bytes = (u32) ACPI_ROUND_UP_to_32_bITS(resource_length) - resource_length; break; @@ -407,7 +412,7 @@ acpi_rs_get_list_length(u8 * aml_buffer, * Vendor Resource: * Add vendor data and ensure a 32-bit boundary for the structure */ - extra_struct_bytes = + extra_struct_bytes = (u32) ACPI_ROUND_UP_to_32_bITS(resource_length) - resource_length; break; @@ -431,7 +436,7 @@ acpi_rs_get_list_length(u8 * aml_buffer, */ buffer++; - extra_struct_bytes = + extra_struct_bytes = (u32) /* * Add 4 bytes for each additional interrupt. Note: at * least one interrupt is required and is included in @@ -450,7 +455,7 @@ acpi_rs_get_list_length(u8 * aml_buffer, * Add the size of any optional data (resource_source) * Ensure a 64-bit boundary for the structure */ - extra_struct_bytes = + extra_struct_bytes = (u32) ACPI_ROUND_UP_to_64_bITS (acpi_rs_stream_option_length (resource_length, minimum_aml_resource_length)); @@ -525,6 +530,7 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object, top_object_list = package_object->package.elements; for (index = 0; index < number_of_elements; index++) { + /* Dereference the sub-package */ package_element = *top_object_list; diff --git a/drivers/acpi/resources/rslist.c b/drivers/acpi/resources/rslist.c index 1434e786477..c27dca64d5d 100644 --- a/drivers/acpi/resources/rslist.c +++ b/drivers/acpi/resources/rslist.c @@ -77,6 +77,7 @@ acpi_rs_convert_aml_to_resources(u8 * aml, u32 aml_length, u8 * output_buffer) /* Loop until end-of-buffer or an end_tag is found */ while (aml < end_aml) { + /* Validate the Resource Type and Resource Length */ status = acpi_ut_validate_resource(aml, &resource_index); @@ -155,6 +156,7 @@ acpi_rs_convert_resources_to_aml(struct acpi_resource *resource, /* Walk the resource descriptor list, convert each descriptor */ while (aml < end_aml) { + /* Validate the (internal) Resource Type */ if (resource->type > ACPI_RESOURCE_TYPE_MAX) { @@ -191,6 +193,7 @@ acpi_rs_convert_resources_to_aml(struct acpi_resource *resource, /* Check for end-of-list, normal exit */ if (resource->type == ACPI_RESOURCE_TYPE_END_TAG) { + /* An End Tag indicates the end of the input Resource Template */ return_ACPI_STATUS(AE_OK); diff --git a/drivers/acpi/resources/rsmisc.c b/drivers/acpi/resources/rsmisc.c index ed866cf1c6d..095730196a8 100644 --- a/drivers/acpi/resources/rsmisc.c +++ b/drivers/acpi/resources/rsmisc.c @@ -84,6 +84,7 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, ACPI_FUNCTION_TRACE("rs_get_resource"); if (((acpi_native_uint) resource) & 0x3) { + /* Each internal resource struct is expected to be 32-bit aligned */ ACPI_WARNING((AE_INFO, @@ -295,9 +296,11 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, exit: if (!flags_mode) { + /* Round the resource struct length up to the next 32-bit boundary */ - resource->length = ACPI_ROUND_UP_to_32_bITS(resource->length); + resource->length = + (u32) ACPI_ROUND_UP_to_32_bITS(resource->length); } return_ACPI_STATUS(AE_OK); } @@ -535,6 +538,7 @@ if (((aml->irq.flags & 0x09) == 0x00) || ((aml->irq.flags & 0x09) == 0x09)) { resource->data.extended_irq.interrupt_count = temp8; if (temp8 < 1) { + /* Must have at least one IRQ */ return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH); diff --git a/drivers/acpi/resources/rsutils.c b/drivers/acpi/resources/rsutils.c index 25b5aedd661..c5f7014929b 100644 --- a/drivers/acpi/resources/rsutils.c +++ b/drivers/acpi/resources/rsutils.c @@ -205,6 +205,7 @@ acpi_rs_set_resource_length(acpi_rsdesc_size total_length, /* Length is stored differently for large and small descriptors */ if (aml->small_header.descriptor_type & ACPI_RESOURCE_NAME_LARGE) { + /* Large descriptor -- bytes 1-2 contain the 16-bit length */ ACPI_MOVE_16_TO_16(&aml->large_header.resource_length, @@ -328,6 +329,7 @@ acpi_rs_get_resource_source(acpi_rs_length resource_length, * we add 1 to the minimum length. */ if (total_length > (acpi_rsdesc_size) (minimum_length + 1)) { + /* Get the resource_source_index */ resource_source->index = aml_resource_source[0]; @@ -351,16 +353,20 @@ acpi_rs_get_resource_source(acpi_rs_length resource_length, * Zero the entire area of the buffer. */ total_length = + (u32) ACPI_ROUND_UP_to_32_bITS(ACPI_STRLEN - ((char *)&aml_resource_source[1]) + - 1); + (ACPI_CAST_PTR + (char, + &aml_resource_source[1])) + 1); + ACPI_MEMSET(resource_source->string_ptr, 0, total_length); /* Copy the resource_source string to the destination */ resource_source->string_length = acpi_rs_strcpy(resource_source->string_ptr, - (char *)&aml_resource_source[1]); + ACPI_CAST_PTR(char, + &aml_resource_source[1])); return ((acpi_rs_length) total_length); } @@ -405,6 +411,7 @@ acpi_rs_set_resource_source(union aml_resource * aml, /* Non-zero string length indicates presence of a resource_source */ if (resource_source->string_length) { + /* Point to the end of the AML descriptor */ aml_resource_source = ACPI_ADD_PTR(u8, aml, minimum_length); @@ -415,7 +422,7 @@ acpi_rs_set_resource_source(union aml_resource * aml, /* Copy the resource_source string */ - ACPI_STRCPY((char *)&aml_resource_source[1], + ACPI_STRCPY(ACPI_CAST_PTR(char, &aml_resource_source[1]), resource_source->string_ptr); /* @@ -435,9 +442,9 @@ acpi_rs_set_resource_source(union aml_resource * aml, * * FUNCTION: acpi_rs_get_prt_method_data * - * PARAMETERS: Handle - a handle to the containing object - * ret_buffer - a pointer to a buffer structure for the - * results + * PARAMETERS: Handle - Handle to the containing object + * ret_buffer - Pointer to a buffer structure for the + * results * * RETURN: Status * @@ -483,9 +490,9 @@ acpi_rs_get_prt_method_data(acpi_handle handle, struct acpi_buffer * ret_buffer) * * FUNCTION: acpi_rs_get_crs_method_data * - * PARAMETERS: Handle - a handle to the containing object - * ret_buffer - a pointer to a buffer structure for the - * results + * PARAMETERS: Handle - Handle to the containing object + * ret_buffer - Pointer to a buffer structure for the + * results * * RETURN: Status * @@ -532,9 +539,9 @@ acpi_rs_get_crs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer) * * FUNCTION: acpi_rs_get_prs_method_data * - * PARAMETERS: Handle - a handle to the containing object - * ret_buffer - a pointer to a buffer structure for the - * results + * PARAMETERS: Handle - Handle to the containing object + * ret_buffer - Pointer to a buffer structure for the + * results * * RETURN: Status * @@ -583,10 +590,10 @@ acpi_rs_get_prs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer) * * FUNCTION: acpi_rs_get_method_data * - * PARAMETERS: Handle - a handle to the containing object + * PARAMETERS: Handle - Handle to the containing object * Path - Path to method, relative to Handle - * ret_buffer - a pointer to a buffer structure for the - * results + * ret_buffer - Pointer to a buffer structure for the + * results * * RETURN: Status * @@ -634,9 +641,9 @@ acpi_rs_get_method_data(acpi_handle handle, * * FUNCTION: acpi_rs_set_srs_method_data * - * PARAMETERS: Handle - a handle to the containing object - * in_buffer - a pointer to a buffer structure of the - * parameter + * PARAMETERS: Handle - Handle to the containing object + * in_buffer - Pointer to a buffer structure of the + * parameter * * RETURN: Status * @@ -696,6 +703,7 @@ acpi_rs_set_srs_method_data(acpi_handle handle, struct acpi_buffer *in_buffer) status = acpi_ns_evaluate_relative(METHOD_NAME__SRS, &info); if (ACPI_SUCCESS(status)) { + /* Delete any return object (especially if implicit_return is enabled) */ if (info.return_object) { diff --git a/drivers/acpi/resources/rsxface.c b/drivers/acpi/resources/rsxface.c index 88b67077aee..2e1bc71acd9 100644 --- a/drivers/acpi/resources/rsxface.c +++ b/drivers/acpi/resources/rsxface.c @@ -279,6 +279,7 @@ acpi_walk_resources(acpi_handle device_handle, /* Walk the resource list until the end_tag is found (or buffer end) */ while (resource < resource_end) { + /* Sanity check the resource */ if (resource->type > ACPI_RESOURCE_TYPE_MAX) { @@ -291,6 +292,7 @@ acpi_walk_resources(acpi_handle device_handle, status = user_function(resource, context); if (ACPI_FAILURE(status)) { if (status == AE_CTRL_TERMINATE) { + /* This is an OK termination by the user function */ status = AE_OK; diff --git a/drivers/acpi/tables/tbconvrt.c b/drivers/acpi/tables/tbconvrt.c index 03b37d2223b..254ebdbb7be 100644 --- a/drivers/acpi/tables/tbconvrt.c +++ b/drivers/acpi/tables/tbconvrt.c @@ -147,6 +147,7 @@ acpi_status acpi_tb_convert_to_xsdt(struct acpi_table_desc *table_info) /* Copy the table pointers */ for (i = 0; i < acpi_gbl_rsdt_table_count; i++) { + /* RSDT pointers are 32 bits, XSDT pointers are 64 bits */ if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) { @@ -515,6 +516,7 @@ acpi_status acpi_tb_convert_table_fadt(void) if (acpi_gbl_FADT->revision >= FADT2_REVISION_ID) { if (acpi_gbl_FADT->length < sizeof(struct fadt_descriptor_rev2)) { + /* Length is too short to be a V2.0 table */ ACPI_WARNING((AE_INFO, @@ -603,6 +605,7 @@ acpi_status acpi_tb_build_common_facs(struct acpi_table_desc *table_info) if ((acpi_gbl_RSDP->revision < 2) || (acpi_gbl_FACS->length < 32) || (!(acpi_gbl_FACS->xfirmware_waking_vector))) { + /* ACPI 1.0 FACS or short table or optional X_ field is zero */ acpi_gbl_common_fACS.firmware_waking_vector = ACPI_CAST_PTR(u64, diff --git a/drivers/acpi/tables/tbget.c b/drivers/acpi/tables/tbget.c index 09b4ee6dfd6..4615e1afe8d 100644 --- a/drivers/acpi/tables/tbget.c +++ b/drivers/acpi/tables/tbget.c @@ -148,6 +148,10 @@ acpi_tb_get_table_header(struct acpi_pointer *address, sizeof(struct acpi_table_header), (void *)&header); if (ACPI_FAILURE(status)) { + ACPI_ERROR((AE_INFO, + "Could not map memory at %8.8X%8.8X for table header", + ACPI_FORMAT_UINT64(address->pointer. + physical))); return_ACPI_STATUS(status); } @@ -208,6 +212,7 @@ acpi_tb_get_table_body(struct acpi_pointer *address, status = acpi_tb_table_override(header, table_info); if (ACPI_SUCCESS(status)) { + /* Table was overridden by the host OS */ return_ACPI_STATUS(status); @@ -250,6 +255,7 @@ acpi_tb_table_override(struct acpi_table_header *header, */ status = acpi_os_table_override(header, &new_table); if (ACPI_FAILURE(status)) { + /* Some severe error from the OSL, but we basically ignore it */ ACPI_EXCEPTION((AE_INFO, status, @@ -258,6 +264,7 @@ acpi_tb_table_override(struct acpi_table_header *header, } if (!new_table) { + /* No table override */ return_ACPI_STATUS(AE_NO_ACPI_TABLES); @@ -381,6 +388,7 @@ acpi_tb_get_this_table(struct acpi_pointer *address, #if (!ACPI_CHECKSUM_ABORT) if (ACPI_FAILURE(status)) { + /* Ignore the error if configuration says so */ status = AE_OK; @@ -440,6 +448,7 @@ acpi_tb_get_table_ptr(acpi_table_type table_type, * instance is always in the list head. */ if (instance == 1) { + /* Get the first */ *table_ptr_loc = NULL; diff --git a/drivers/acpi/tables/tbgetall.c b/drivers/acpi/tables/tbgetall.c index 134e5dce0bc..b4ec61d7cf0 100644 --- a/drivers/acpi/tables/tbgetall.c +++ b/drivers/acpi/tables/tbgetall.c @@ -223,6 +223,7 @@ acpi_status acpi_tb_get_required_tables(void) * any SSDTs. */ for (i = 0; i < acpi_gbl_rsdt_table_count; i++) { + /* Get the table address from the common internal XSDT */ address.pointer.value = acpi_gbl_XSDT->table_offset_entry[i]; diff --git a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c index 7ffd0fddb4e..ec2cb978b7c 100644 --- a/drivers/acpi/tables/tbinstal.c +++ b/drivers/acpi/tables/tbinstal.c @@ -84,6 +84,7 @@ acpi_tb_match_signature(char *signature, if (!ACPI_STRNCMP(signature, acpi_gbl_table_data[i].signature, acpi_gbl_table_data[i].sig_length)) { + /* Found a signature match, return index if requested */ if (table_info) { diff --git a/drivers/acpi/tables/tbrsdt.c b/drivers/acpi/tables/tbrsdt.c index 4d308220225..946d2f2d611 100644 --- a/drivers/acpi/tables/tbrsdt.c +++ b/drivers/acpi/tables/tbrsdt.c @@ -190,6 +190,7 @@ acpi_status acpi_tb_validate_rsdt(struct acpi_table_header *table_ptr) } if (no_match) { + /* Invalid RSDT or XSDT signature */ ACPI_ERROR((AE_INFO, diff --git a/drivers/acpi/tables/tbutils.c b/drivers/acpi/tables/tbutils.c index bc571592f08..b463d4b8882 100644 --- a/drivers/acpi/tables/tbutils.c +++ b/drivers/acpi/tables/tbutils.c @@ -96,6 +96,7 @@ acpi_status acpi_tb_is_table_installed(struct acpi_table_desc *new_table_desc) (!ACPI_MEMCMP (table_desc->pointer, new_table_desc->pointer, new_table_desc->pointer->length))) { + /* Match: this table is already installed */ ACPI_DEBUG_PRINT((ACPI_DB_TABLES, @@ -249,6 +250,7 @@ u8 acpi_tb_generate_checksum(void *buffer, u32 length) u8 sum = 0; if (buffer && length) { + /* Buffer and Length are valid */ end_buffer = ACPI_ADD_PTR(u8, buffer, length); diff --git a/drivers/acpi/tables/tbxface.c b/drivers/acpi/tables/tbxface.c index 9fe53c9d5b9..3e902cdb83e 100644 --- a/drivers/acpi/tables/tbxface.c +++ b/drivers/acpi/tables/tbxface.c @@ -174,6 +174,7 @@ acpi_status acpi_load_table(struct acpi_table_header *table_ptr) status = acpi_tb_install_table(&table_info); if (ACPI_FAILURE(status)) { if (status == AE_ALREADY_EXISTS) { + /* Table already exists, no error */ status = AE_OK; @@ -208,6 +209,7 @@ acpi_status acpi_load_table(struct acpi_table_header *table_ptr) } if (ACPI_FAILURE(status)) { + /* Uninstall table and free the buffer */ (void)acpi_tb_uninstall_table(table_info.installed_desc); @@ -397,6 +399,7 @@ acpi_get_table(acpi_table_type table_type, /* Get the table length */ if (table_type == ACPI_TABLE_RSDP) { + /* RSD PTR is the only "table" without a header */ table_length = sizeof(struct rsdp_descriptor); diff --git a/drivers/acpi/tables/tbxfroot.c b/drivers/acpi/tables/tbxfroot.c index a62db6af83c..7f68b759f15 100644 --- a/drivers/acpi/tables/tbxfroot.c +++ b/drivers/acpi/tables/tbxfroot.c @@ -75,6 +75,7 @@ acpi_status acpi_tb_validate_rsdp(struct rsdp_descriptor *rsdp) * The signature and checksum must both be correct */ if (ACPI_STRNCMP((char *)rsdp, RSDP_SIG, sizeof(RSDP_SIG) - 1) != 0) { + /* Nope, BAD Signature */ return (AE_BAD_SIGNATURE); @@ -217,6 +218,7 @@ acpi_get_firmware_table(acpi_string signature, /* Ensure that we have a RSDP */ if (!acpi_gbl_RSDP) { + /* Get the RSDP */ status = acpi_os_get_root_pointer(flags, &address); @@ -327,10 +329,12 @@ acpi_get_firmware_table(acpi_string signature, /* Compare table signatures and table instance */ if (!ACPI_STRNCMP(header->signature, signature, ACPI_NAME_SIZE)) { + /* An instance of the table was found */ j++; if (j >= instance) { + /* Found the correct instance, get the entire table */ status = @@ -434,12 +438,14 @@ static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length) for (mem_rover = start_address; mem_rover < end_address; mem_rover += ACPI_RSDP_SCAN_STEP) { + /* The RSDP signature and checksum must both be correct */ status = acpi_tb_validate_rsdp(ACPI_CAST_PTR (struct rsdp_descriptor, mem_rover)); if (ACPI_SUCCESS(status)) { + /* Sig and checksum valid, we have found a real RSDP */ ACPI_DEBUG_PRINT((ACPI_DB_INFO, @@ -495,6 +501,7 @@ acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags) * Scan supports either logical addressing or physical addressing */ if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) { + /* 1a) Get the location of the Extended BIOS Data Area (EBDA) */ status = acpi_os_map_memory((acpi_physical_address) @@ -542,6 +549,7 @@ acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags) acpi_os_unmap_memory(table_ptr, ACPI_EBDA_WINDOW_SIZE); if (mem_rover) { + /* Return the physical address */ physical_address += @@ -576,6 +584,7 @@ acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags) acpi_os_unmap_memory(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE); if (mem_rover) { + /* Return the physical address */ physical_address = @@ -609,6 +618,7 @@ acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags) (physical_address), ACPI_EBDA_WINDOW_SIZE); if (mem_rover) { + /* Return the physical address */ table_info->physical_address = @@ -624,6 +634,7 @@ acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags) (ACPI_HI_RSDP_WINDOW_BASE), ACPI_HI_RSDP_WINDOW_SIZE); if (mem_rover) { + /* Found it, return the physical address */ table_info->physical_address = diff --git a/drivers/acpi/utilities/utalloc.c b/drivers/acpi/utilities/utalloc.c index 03b0044974c..34de3791d4c 100644 --- a/drivers/acpi/utilities/utalloc.c +++ b/drivers/acpi/utilities/utalloc.c @@ -308,6 +308,7 @@ void *acpi_ut_allocate(acpi_size size, u32 component, char *module, u32 line) allocation = acpi_os_allocate(size); if (!allocation) { + /* Report allocation error */ ACPI_ERROR((module, line, @@ -351,6 +352,7 @@ void *acpi_ut_callocate(acpi_size size, u32 component, char *module, u32 line) allocation = acpi_os_allocate(size); if (!allocation) { + /* Report allocation error */ ACPI_ERROR((module, line, @@ -477,6 +479,7 @@ void *acpi_ut_callocate_and_track(acpi_size size, acpi_ut_callocate(size + sizeof(struct acpi_debug_mem_header), component, module, line); if (!allocation) { + /* Report allocation error */ ACPI_ERROR((module, line, @@ -681,6 +684,7 @@ acpi_ut_remove_allocation(struct acpi_debug_mem_block *allocation, mem_list = acpi_gbl_global_list; if (NULL == mem_list->list_head) { + /* No allocations! */ ACPI_ERROR((module, line, @@ -807,6 +811,7 @@ void acpi_ut_dump_allocations(u32 component, char *module) if ((element->component & component) && ((module == NULL) || (0 == ACPI_STRCMP(module, element->module)))) { + /* Ignore allocated objects that are in a cache */ descriptor = diff --git a/drivers/acpi/utilities/utcache.c b/drivers/acpi/utilities/utcache.c index 2177cb1ef2c..044c890e5b3 100644 --- a/drivers/acpi/utilities/utcache.c +++ b/drivers/acpi/utilities/utcache.c @@ -118,6 +118,7 @@ acpi_status acpi_os_purge_cache(struct acpi_memory_list * cache) /* Walk the list of objects in this cache */ while (cache->list_head) { + /* Delete and unlink one cached state object */ next = *(ACPI_CAST_INDIRECT_PTR(char, @@ -259,6 +260,7 @@ void *acpi_os_acquire_object(struct acpi_memory_list *cache) /* Check the cache first */ if (cache->list_head) { + /* There is an object available, use it */ object = cache->list_head; diff --git a/drivers/acpi/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c index df2d32096b7..47875935c3f 100644 --- a/drivers/acpi/utilities/utcopy.c +++ b/drivers/acpi/utilities/utcopy.c @@ -882,6 +882,7 @@ acpi_ut_copy_ipackage_to_ipackage(union acpi_operand_object *source_obj, acpi_ut_copy_ielement_to_ielement, walk_state); if (ACPI_FAILURE(status)) { + /* On failure, delete the destination package object */ acpi_ut_remove_reference(dest_obj); diff --git a/drivers/acpi/utilities/utdebug.c b/drivers/acpi/utilities/utdebug.c index 35f3d581e03..6e92b2a3c0f 100644 --- a/drivers/acpi/utilities/utdebug.c +++ b/drivers/acpi/utilities/utdebug.c @@ -123,12 +123,14 @@ static const char *acpi_ut_trim_function_name(const char *function_name) /* All Function names are longer than 4 chars, check is safe */ if (*(ACPI_CAST_PTR(u32, function_name)) == ACPI_PREFIX_MIXED) { + /* This is the case where the original source has not been modified */ return (function_name + 4); } if (*(ACPI_CAST_PTR(u32, function_name)) == ACPI_PREFIX_LOWER) { + /* This is the case where the source has been 'linuxized' */ return (function_name + 5); @@ -545,6 +547,7 @@ void acpi_ut_dump_buffer(u8 * buffer, u32 count, u32 display, u32 component_id) /* Nasty little dump buffer routine! */ while (i < count) { + /* Print current offset */ acpi_os_printf("%6.4X: ", (u32) i); @@ -553,6 +556,7 @@ void acpi_ut_dump_buffer(u8 * buffer, u32 count, u32 display, u32 component_id) for (j = 0; j < 16;) { if (i + j >= count) { + /* Dump fill spaces */ acpi_os_printf("%*s", ((display * 2) + 1), " "); diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c index 1db9695b002..dbae72121ce 100644 --- a/drivers/acpi/utilities/utdelete.c +++ b/drivers/acpi/utilities/utdelete.c @@ -96,6 +96,7 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object) /* Free the actual string buffer */ if (!(object->common.flags & AOPOBJ_STATIC_POINTER)) { + /* But only if it is NOT a pointer into an ACPI table */ obj_pointer = object->string.pointer; @@ -111,6 +112,7 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object) /* Free the actual buffer */ if (!(object->common.flags & AOPOBJ_STATIC_POINTER)) { + /* But only if it is NOT a pointer into an ACPI table */ obj_pointer = object->buffer.pointer; @@ -415,6 +417,7 @@ acpi_ut_update_object_reference(union acpi_operand_object * object, u16 action) ACPI_FUNCTION_TRACE_PTR("ut_update_object_reference", object); while (object) { + /* Make sure that this isn't a namespace handle */ if (ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_NAMED) { diff --git a/drivers/acpi/utilities/uteval.c b/drivers/acpi/utilities/uteval.c index 106cc97cb4a..952ffdea93a 100644 --- a/drivers/acpi/utilities/uteval.c +++ b/drivers/acpi/utilities/uteval.c @@ -98,6 +98,7 @@ acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state) ACPI_CAST_PTR(char, acpi_gbl_valid_osi_strings[i]))) { + /* This string is supported */ return_desc->integer.value = 0xFFFFFFFF; @@ -343,6 +344,7 @@ acpi_ut_execute_HID(struct acpi_namespace_node *device_node, } if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { + /* Convert the Numeric HID to string */ acpi_ex_eisa_id_to_string((u32) obj_desc->integer.value, @@ -479,6 +481,7 @@ acpi_ut_execute_CID(struct acpi_namespace_node * device_node, /* The _CID object can be either a single CID or a package (list) of CIDs */ if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_PACKAGE) { + /* Translate each package element */ for (i = 0; i < count; i++) { @@ -543,6 +546,7 @@ acpi_ut_execute_UID(struct acpi_namespace_node *device_node, } if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { + /* Convert the Numeric UID to string */ acpi_ex_unsigned_integer_to_string(obj_desc->integer.value, diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c index ffd13383a32..767c5e44a04 100644 --- a/drivers/acpi/utilities/utglobal.c +++ b/drivers/acpi/utilities/utglobal.c @@ -119,6 +119,7 @@ const char *acpi_format_exception(acpi_status status) } if (!exception) { + /* Exception code was not recognized */ ACPI_ERROR((AE_INFO, @@ -747,6 +748,7 @@ u8 acpi_ut_valid_object_type(acpi_object_type type) { if (type > ACPI_TYPE_LOCAL_MAX) { + /* Note: Assumes all TYPEs are contiguous (external/local) */ return (FALSE); diff --git a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c index 7364f5f8c9c..60f36130663 100644 --- a/drivers/acpi/utilities/utmisc.c +++ b/drivers/acpi/utilities/utmisc.c @@ -97,6 +97,7 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id) for (k = acpi_gbl_next_owner_id_offset; k < 32; k++) { if (acpi_gbl_owner_id_mask[j] == ACPI_UINT32_MAX) { + /* There are no free IDs in this mask */ break; @@ -273,6 +274,7 @@ void acpi_ut_print_string(char *string, u8 max_length) acpi_os_printf("\""); for (i = 0; string[i] && (i < max_length); i++) { + /* Escape sequences */ switch (string[i]) { @@ -601,11 +603,13 @@ acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer) while (*string) { if (ACPI_IS_DIGIT(*string)) { + /* Convert ASCII 0-9 to Decimal value */ this_digit = ((u8) * string) - '0'; } else { if (base == 10) { + /* Digit is out of range */ goto error_exit; @@ -613,6 +617,7 @@ acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer) this_digit = (u8) ACPI_TOUPPER(*string); if (ACPI_IS_XDIGIT((char)this_digit)) { + /* Convert ASCII Hex char to value */ this_digit = this_digit - 'A' + 10; @@ -727,6 +732,7 @@ acpi_ut_walk_package_tree(union acpi_operand_object * source_object, } while (state) { + /* Get one element of the package */ this_index = state->pkg.index; @@ -812,31 +818,6 @@ acpi_ut_walk_package_tree(union acpi_operand_object * source_object, return_ACPI_STATUS(AE_AML_INTERNAL); } -/******************************************************************************* - * - * FUNCTION: acpi_ut_generate_checksum - * - * PARAMETERS: Buffer - Buffer to be scanned - * Length - number of bytes to examine - * - * RETURN: The generated checksum - * - * DESCRIPTION: Generate a checksum on a raw buffer - * - ******************************************************************************/ - -u8 acpi_ut_generate_checksum(u8 * buffer, u32 length) -{ - u32 i; - signed char sum = 0; - - for (i = 0; i < length; i++) { - sum = (signed char)(sum + buffer[i]); - } - - return ((u8) (0 - sum)); -} - /******************************************************************************* * * FUNCTION: acpi_ut_error, acpi_ut_warning, acpi_ut_info diff --git a/drivers/acpi/utilities/utobject.c b/drivers/acpi/utilities/utobject.c index 7ee2d1d9807..b1205a58028 100644 --- a/drivers/acpi/utilities/utobject.c +++ b/drivers/acpi/utilities/utobject.c @@ -173,6 +173,7 @@ union acpi_operand_object *acpi_ut_create_buffer_object(acpi_size buffer_size) /* Create an actual buffer only if size > 0 */ if (buffer_size > 0) { + /* Allocate the actual buffer */ buffer = ACPI_MEM_CALLOCATE(buffer_size); @@ -397,6 +398,7 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object, length = sizeof(union acpi_object); if (ACPI_GET_DESCRIPTOR_TYPE(internal_object) == ACPI_DESC_TYPE_NAMED) { + /* Object is a named object (reference), just return the length */ *obj_length = ACPI_ROUND_UP_TO_NATIVE_WORD(length); diff --git a/drivers/acpi/utilities/utresrc.c b/drivers/acpi/utilities/utresrc.c index 16461317113..27158dd0f87 100644 --- a/drivers/acpi/utilities/utresrc.c +++ b/drivers/acpi/utilities/utresrc.c @@ -273,6 +273,7 @@ acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index) * Examine the large/small bit in the resource header */ if (resource_type & ACPI_RESOURCE_NAME_LARGE) { + /* Verify the large resource type (name) against the max */ if (resource_type > ACPI_RESOURCE_NAME_LARGE_MAX) { @@ -376,6 +377,7 @@ u8 acpi_ut_get_resource_type(void *aml) * Examine the large/small bit in the resource header */ if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) { + /* Large Resource Type -- bits 6:0 contain the name */ return (ACPI_GET8(aml)); @@ -411,6 +413,7 @@ u16 acpi_ut_get_resource_length(void *aml) * Examine the large/small bit in the resource header */ if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) { + /* Large Resource type -- bytes 1-2 contain the 16-bit length */ ACPI_MOVE_16_TO_16(&resource_length, ACPI_ADD_PTR(u8, aml, 1)); @@ -515,6 +518,7 @@ acpi_ut_get_resource_end_tag(union acpi_operand_object * obj_desc, /* Walk the resource template, one descriptor per iteration */ while (aml < end_aml) { + /* Validate the Resource Type and Resource Length */ status = acpi_ut_validate_resource(aml, NULL); diff --git a/drivers/acpi/utilities/utstate.c b/drivers/acpi/utilities/utstate.c index 4b134a72290..69f2bfdc26a 100644 --- a/drivers/acpi/utilities/utstate.c +++ b/drivers/acpi/utilities/utstate.c @@ -129,6 +129,7 @@ union acpi_generic_state *acpi_ut_pop_generic_state(union acpi_generic_state state = *list_head; if (state) { + /* Update the list head */ *list_head = state->common.next; @@ -158,6 +159,7 @@ union acpi_generic_state *acpi_ut_create_generic_state(void) state = acpi_os_acquire_object(acpi_gbl_state_cache); if (state) { + /* Initialize */ memset(state, 0, sizeof(union acpi_generic_state)); state->common.data_type = ACPI_DESC_TYPE_STATE; diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h index e27dc8f2997..28a6a23c863 100644 --- a/include/acpi/acconfig.h +++ b/include/acpi/acconfig.h @@ -63,7 +63,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20060127 +#define ACPI_CA_VERSION 0x20060210 /* * OS name, used for the _OS object. The _OS object is essentially obsolete, diff --git a/include/acpi/acdisasm.h b/include/acpi/acdisasm.h index 11a8fe39cb0..0727c132bd3 100644 --- a/include/acpi/acdisasm.h +++ b/include/acpi/acdisasm.h @@ -70,6 +70,7 @@ extern const char *acpi_gbl_match_ops[ACPI_NUM_MATCH_OPS]; struct acpi_op_walk_info { u32 level; u32 bit_offset; + u32 flags; struct acpi_walk_state *walk_state; }; diff --git a/include/acpi/acutils.h b/include/acpi/acutils.h index 0927765df6a..71ff78c7544 100644 --- a/include/acpi/acutils.h +++ b/include/acpi/acutils.h @@ -483,8 +483,6 @@ acpi_status acpi_ut_get_resource_end_tag(union acpi_operand_object *obj_desc, u8 ** end_tag); -u8 acpi_ut_generate_checksum(u8 * buffer, u32 length); - u32 acpi_ut_dword_byte_swap(u32 value); void acpi_ut_set_integer_width(u8 revision); -- cgit v1.2.3 From 08a556db919f67e1e4d33ae8d40f7222da34d994 Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Fri, 31 Mar 2006 13:29:04 +0800 Subject: [PATCH] libata-dev: print out information for ATAPI devices with CDB interrupts print out information for ATAPI devices with CDB interrupts Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index a14187e32d0..f18742e8d72 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1305,6 +1305,8 @@ static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev, /* ATAPI-specific feature tests */ else if (dev->class == ATA_DEV_ATAPI) { + char *cdb_intr_string = ""; + rc = atapi_cdb_len(id); if ((rc < 12) || (rc > ATAPI_CDB_LEN)) { printk(KERN_WARNING "ata%u: unsupported CDB len\n", ap->id); @@ -1313,13 +1315,16 @@ static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev, } dev->cdb_len = (unsigned int) rc; - if (ata_id_cdb_intr(dev->id)) + if (ata_id_cdb_intr(dev->id)) { dev->flags |= ATA_DFLAG_CDB_INTR; + cdb_intr_string = ", CDB intr"; + } /* print device info to dmesg */ if (print_info) - printk(KERN_INFO "ata%u: dev %u ATAPI, max %s\n", - ap->id, dev->devno, ata_mode_string(xfer_mask)); + printk(KERN_INFO "ata%u: dev %u ATAPI, max %s%s\n", + ap->id, dev->devno, ata_mode_string(xfer_mask), + cdb_intr_string); } ap->host->max_cmd_len = 0; -- cgit v1.2.3 From ea936b78f46cbe089a4ac363e1682dee7d427096 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Fri, 17 Feb 2006 00:00:00 -0500 Subject: ACPI: ACPICA 20060217 Implemented a change to the IndexField support to match the behavior of the Microsoft AML interpreter. The value written to the Index register is now a byte offset, no longer an index based upon the width of the Data register. This should fix IndexField problems seen on some machines where the Data register is not exactly one byte wide. The ACPI specification will be clarified on this point. Fixed a problem where several resource descriptor types could overrun the internal descriptor buffer due to size miscalculation: VendorShort, VendorLong, and Interrupt. This was noticed on IA64 machines, but could affect all platforms. Fixed a problem where individual resource descriptors were misaligned within the internal buffer, causing alignment faults on IA64 platforms. Signed-off-by: Bob Moore Signed-off-by: Len Brown --- drivers/acpi/executer/exprep.c | 17 +++++-- drivers/acpi/namespace/nsutils.c | 5 +- drivers/acpi/parser/psloop.c | 1 + drivers/acpi/resources/rscalc.c | 100 +++++++++++++++++--------------------- drivers/acpi/resources/rscreate.c | 2 +- drivers/acpi/resources/rslist.c | 15 ++++++ drivers/acpi/resources/rsmisc.c | 6 +-- drivers/acpi/resources/rsutils.c | 17 +++---- include/acpi/acconfig.h | 2 +- include/acpi/acmacros.h | 34 +++++++------ include/acpi/actypes.h | 10 ---- 11 files changed, 108 insertions(+), 101 deletions(-) diff --git a/drivers/acpi/executer/exprep.c b/drivers/acpi/executer/exprep.c index 7719ae5d4f1..916234bf811 100644 --- a/drivers/acpi/executer/exprep.c +++ b/drivers/acpi/executer/exprep.c @@ -519,13 +519,20 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) acpi_ut_add_reference(obj_desc->index_field.index_obj); /* + * February 2006: Changed to match MS behavior + * * The value written to the Index register is the byte offset of the - * target field - * Note: may change code to: ACPI_DIV_8 (Info->field_bit_position) + * target field. + * + * Previously, the value was calculated as an index in terms of the + * width of the Data register, as below: + * + * obj_desc->index_field.Value = (u32) + * (Info->field_bit_position / ACPI_MUL_8 ( + * obj_desc->Field.access_byte_width)); */ - obj_desc->index_field.value = (u32) - (info->field_bit_position / - ACPI_MUL_8(obj_desc->field.access_byte_width)); + obj_desc->index_field.value = + (u32) ACPI_DIV_8(info->field_bit_position); ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "index_field: bit_off %X, Off %X, Value %X, Gran %X, Index %p, Data %p\n", diff --git a/drivers/acpi/namespace/nsutils.c b/drivers/acpi/namespace/nsutils.c index e8c779114be..123f454b14a 100644 --- a/drivers/acpi/namespace/nsutils.c +++ b/drivers/acpi/namespace/nsutils.c @@ -78,6 +78,7 @@ acpi_ns_report_error(char *module_name, char *internal_name, acpi_status lookup_status) { acpi_status status; + u32 bad_name; char *name = NULL; acpi_ut_report_error(module_name, line_number); @@ -86,8 +87,8 @@ acpi_ns_report_error(char *module_name, /* There is a non-ascii character in the name */ - acpi_os_printf("[0x%4.4X] (NON-ASCII)", - *(ACPI_CAST_PTR(u32, internal_name))); + ACPI_MOVE_32_TO_32(&bad_name, internal_name); + acpi_os_printf("[0x%4.4X] (NON-ASCII)", bad_name); } else { /* Convert path to external format */ diff --git a/drivers/acpi/parser/psloop.c b/drivers/acpi/parser/psloop.c index 42062d5abc9..14052cb648c 100644 --- a/drivers/acpi/parser/psloop.c +++ b/drivers/acpi/parser/psloop.c @@ -767,6 +767,7 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) return_ACPI_STATUS(status2); } } + acpi_ps_pop_scope(parser_state, &op, &walk_state->arg_types, &walk_state->arg_count); diff --git a/drivers/acpi/resources/rscalc.c b/drivers/acpi/resources/rscalc.c index 223bdc49326..8e406d992f3 100644 --- a/drivers/acpi/resources/rscalc.c +++ b/drivers/acpi/resources/rscalc.c @@ -162,9 +162,11 @@ acpi_rs_stream_option_length(u32 resource_length, resource_length - minimum_aml_resource_length - 1; } - /* Round up length to 32 bits for internal structure alignment */ - - return ((u32) ACPI_ROUND_UP_to_32_bITS(string_length)); + /* + * Round the length up to a multiple of the native word in order to + * guarantee that the entire resource descriptor is native word aligned + */ + return ((u32) ACPI_ROUND_UP_TO_NATIVE_WORD(string_length)); } /******************************************************************************* @@ -336,7 +338,7 @@ acpi_rs_get_list_length(u8 * aml_buffer, acpi_status status; u8 *end_aml; u8 *buffer; - u32 buffer_size = 0; + u32 buffer_size; u16 temp16; u16 resource_length; u32 extra_struct_bytes; @@ -345,6 +347,7 @@ acpi_rs_get_list_length(u8 * aml_buffer, ACPI_FUNCTION_TRACE("rs_get_list_length"); + *size_needed = 0; end_aml = aml_buffer + aml_buffer_length; /* Walk the list of AML resource descriptors */ @@ -391,37 +394,28 @@ acpi_rs_get_list_length(u8 * aml_buffer, break; case ACPI_RESOURCE_NAME_VENDOR_SMALL: + case ACPI_RESOURCE_NAME_VENDOR_LARGE: /* * Vendor Resource: - * Ensure a 32-bit boundary for the structure + * Get the number of vendor data bytes */ - extra_struct_bytes = (u32) - ACPI_ROUND_UP_to_32_bITS(resource_length) - - resource_length; + extra_struct_bytes = resource_length; break; case ACPI_RESOURCE_NAME_END_TAG: /* - * End Tag: This is the normal exit, add size of end_tag + * End Tag: + * This is the normal exit, add size of end_tag */ - *size_needed = buffer_size + ACPI_RS_SIZE_MIN; + *size_needed += ACPI_RS_SIZE_MIN; return_ACPI_STATUS(AE_OK); - case ACPI_RESOURCE_NAME_VENDOR_LARGE: - /* - * Vendor Resource: - * Add vendor data and ensure a 32-bit boundary for the structure - */ - extra_struct_bytes = (u32) - ACPI_ROUND_UP_to_32_bITS(resource_length) - - resource_length; - break; - case ACPI_RESOURCE_NAME_ADDRESS32: case ACPI_RESOURCE_NAME_ADDRESS16: + case ACPI_RESOURCE_NAME_ADDRESS64: /* - * 32-Bit or 16-bit Address Resource: - * Add the size of any optional data (resource_source) + * Address Resource: + * Add the size of the optional resource_source */ extra_struct_bytes = acpi_rs_stream_option_length(resource_length, @@ -430,50 +424,46 @@ acpi_rs_get_list_length(u8 * aml_buffer, case ACPI_RESOURCE_NAME_EXTENDED_IRQ: /* - * Extended IRQ: - * Point past the interrupt_vector_flags to get the - * interrupt_table_length. + * Extended IRQ Resource: + * Using the interrupt_table_length, add 4 bytes for each additional + * interrupt. Note: at least one interrupt is required and is + * included in the minimum descriptor size (reason for the -1) */ - buffer++; - - extra_struct_bytes = (u32) - /* - * Add 4 bytes for each additional interrupt. Note: at - * least one interrupt is required and is included in - * the minimum descriptor size - */ - ((*buffer - 1) * sizeof(u32)) + - /* Add the size of any optional data (resource_source) */ + extra_struct_bytes = (buffer[1] - 1) * sizeof(u32); + + /* Add the size of the optional resource_source */ + + extra_struct_bytes += acpi_rs_stream_option_length(resource_length - extra_struct_bytes, minimum_aml_resource_length); break; - case ACPI_RESOURCE_NAME_ADDRESS64: - /* - * 64-Bit Address Resource: - * Add the size of any optional data (resource_source) - * Ensure a 64-bit boundary for the structure - */ - extra_struct_bytes = (u32) - ACPI_ROUND_UP_to_64_bITS - (acpi_rs_stream_option_length - (resource_length, minimum_aml_resource_length)); - break; - default: break; } - /* Update the required buffer size for the internal descriptor structs */ + /* + * Update the required buffer size for the internal descriptor structs + * + * Important: Round the size up for the appropriate alignment. This + * is a requirement on IA64. + */ + buffer_size = acpi_gbl_resource_struct_sizes[resource_index] + + extra_struct_bytes; + buffer_size = ACPI_ROUND_UP_TO_NATIVE_WORD(buffer_size); + + *size_needed += buffer_size; - temp16 = (u16) (acpi_gbl_resource_struct_sizes[resource_index] + - extra_struct_bytes); - buffer_size += (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(temp16); + ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, + "Type %.2X, Aml %.2X internal %.2X\n", + acpi_ut_get_resource_type(aml_buffer), + acpi_ut_get_descriptor_length(aml_buffer), + buffer_size)); /* - * Point to the next resource within the stream - * using the size of the header plus the length contained in the header + * Point to the next resource within the AML stream using the length + * contained in the resource descriptor header */ aml_buffer += acpi_ut_get_descriptor_length(aml_buffer); } @@ -589,7 +579,7 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object, /* Round up the size since each element must be aligned */ - temp_size_needed = ACPI_ROUND_UP_to_64_bITS(temp_size_needed); + temp_size_needed = ACPI_ROUND_UP_to_64_bIT(temp_size_needed); /* Point to the next union acpi_operand_object */ @@ -597,7 +587,7 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object, } /* - * Adding an extra element to the end of the list, essentially a + * Add an extra element to the end of the list, essentially a * NULL terminator */ *buffer_size_needed = diff --git a/drivers/acpi/resources/rscreate.c b/drivers/acpi/resources/rscreate.c index 8c128dea325..67c052af7bb 100644 --- a/drivers/acpi/resources/rscreate.c +++ b/drivers/acpi/resources/rscreate.c @@ -332,7 +332,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, /* Now align the current length */ user_prt->length = - (u32) ACPI_ROUND_UP_to_64_bITS(user_prt->length); + (u32) ACPI_ROUND_UP_to_64_bIT(user_prt->length); /* 4) Fourth subobject: Dereference the PRT.source_index */ diff --git a/drivers/acpi/resources/rslist.c b/drivers/acpi/resources/rslist.c index c27dca64d5d..6f2d8de3952 100644 --- a/drivers/acpi/resources/rslist.c +++ b/drivers/acpi/resources/rslist.c @@ -77,6 +77,15 @@ acpi_rs_convert_aml_to_resources(u8 * aml, u32 aml_length, u8 * output_buffer) /* Loop until end-of-buffer or an end_tag is found */ while (aml < end_aml) { + /* + * Check that the input buffer and all subsequent pointers into it + * are aligned on a native word boundary. Most important on IA64 + */ + if (ACPI_IS_MISALIGNED(resource)) { + ACPI_WARNING((AE_INFO, + "Misaligned resource pointer %p", + resource)); + } /* Validate the Resource Type and Resource Length */ @@ -101,6 +110,12 @@ acpi_rs_convert_aml_to_resources(u8 * aml, u32 aml_length, u8 * output_buffer) return_ACPI_STATUS(status); } + ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, + "Type %.2X, Aml %.2X internal %.2X\n", + acpi_ut_get_resource_type(aml), + acpi_ut_get_descriptor_length(aml), + resource->length)); + /* Normal exit on completion of an end_tag resource descriptor */ if (acpi_ut_get_resource_type(aml) == diff --git a/drivers/acpi/resources/rsmisc.c b/drivers/acpi/resources/rsmisc.c index 095730196a8..6a731f4028d 100644 --- a/drivers/acpi/resources/rsmisc.c +++ b/drivers/acpi/resources/rsmisc.c @@ -81,7 +81,7 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, u16 item_count = 0; u16 temp16 = 0; - ACPI_FUNCTION_TRACE("rs_get_resource"); + ACPI_FUNCTION_TRACE("rs_convert_aml_to_resource"); if (((acpi_native_uint) resource) & 0x3) { @@ -297,10 +297,10 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, exit: if (!flags_mode) { - /* Round the resource struct length up to the next 32-bit boundary */ + /* Round the resource struct length up to the next boundary (32 or 64) */ resource->length = - (u32) ACPI_ROUND_UP_to_32_bITS(resource->length); + (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(resource->length); } return_ACPI_STATUS(AE_OK); } diff --git a/drivers/acpi/resources/rsutils.c b/drivers/acpi/resources/rsutils.c index c5f7014929b..9bcf0b637d2 100644 --- a/drivers/acpi/resources/rsutils.c +++ b/drivers/acpi/resources/rsutils.c @@ -299,7 +299,8 @@ static u16 acpi_rs_strcpy(char *destination, char *source) * string_ptr - (optional) where to store the actual * resource_source string * - * RETURN: Length of the string plus NULL terminator, rounded up to 32 bit + * RETURN: Length of the string plus NULL terminator, rounded up to native + * word boundary * * DESCRIPTION: Copy the optional resource_source data from a raw AML descriptor * to an internal resource descriptor @@ -346,18 +347,16 @@ acpi_rs_get_resource_source(acpi_rs_length resource_length, } /* - * In order for the struct_size to fall on a 32-bit boundary, calculate - * the length of the string (+1 for the NULL terminator) and expand the - * struct_size to the next 32-bit boundary. + * In order for the Resource length to be a multiple of the native + * word, calculate the length of the string (+1 for NULL terminator) + * and expand to the next word multiple. * * Zero the entire area of the buffer. */ total_length = - (u32) - ACPI_ROUND_UP_to_32_bITS(ACPI_STRLEN - (ACPI_CAST_PTR - (char, - &aml_resource_source[1])) + 1); + ACPI_STRLEN(ACPI_CAST_PTR(char, &aml_resource_source[1])) + + 1; + total_length = (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(total_length); ACPI_MEMSET(resource_source->string_ptr, 0, total_length); diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h index 28a6a23c863..78850225622 100644 --- a/include/acpi/acconfig.h +++ b/include/acpi/acconfig.h @@ -63,7 +63,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20060210 +#define ACPI_CA_VERSION 0x20060217 /* * OS name, used for the _OS object. The _OS object is essentially obsolete, diff --git a/include/acpi/acmacros.h b/include/acpi/acmacros.h index f2be2a88173..dd5644dbe94 100644 --- a/include/acpi/acmacros.h +++ b/include/acpi/acmacros.h @@ -341,29 +341,33 @@ /* * Rounding macros (Power of two boundaries only) */ -#define ACPI_ROUND_DOWN(value,boundary) (((acpi_native_uint)(value)) & \ +#define ACPI_ROUND_DOWN(value,boundary) (((acpi_native_uint)(value)) & \ (~(((acpi_native_uint) boundary)-1))) -#define ACPI_ROUND_UP(value,boundary) ((((acpi_native_uint)(value)) + \ +#define ACPI_ROUND_UP(value,boundary) ((((acpi_native_uint)(value)) + \ (((acpi_native_uint) boundary)-1)) & \ (~(((acpi_native_uint) boundary)-1))) -#define ACPI_ROUND_DOWN_TO_32_BITS(a) ACPI_ROUND_DOWN(a,4) -#define ACPI_ROUND_DOWN_TO_64_BITS(a) ACPI_ROUND_DOWN(a,8) -#define ACPI_ROUND_DOWN_TO_NATIVE_WORD(a) ACPI_ROUND_DOWN(a,ALIGNED_ADDRESS_BOUNDARY) +/* Note: sizeof(acpi_native_uint) evaluates to either 2, 4, or 8 */ -#define ACPI_ROUND_UP_to_32_bITS(a) ACPI_ROUND_UP(a,4) -#define ACPI_ROUND_UP_to_64_bITS(a) ACPI_ROUND_UP(a,8) -#define ACPI_ROUND_UP_TO_NATIVE_WORD(a) ACPI_ROUND_UP(a,ALIGNED_ADDRESS_BOUNDARY) +#define ACPI_ROUND_DOWN_to_32_bIT(a) ACPI_ROUND_DOWN(a,4) +#define ACPI_ROUND_DOWN_to_64_bIT(a) ACPI_ROUND_DOWN(a,8) +#define ACPI_ROUND_DOWN_TO_NATIVE_WORD(a) ACPI_ROUND_DOWN(a,sizeof(acpi_native_uint)) -#define ACPI_ROUND_BITS_UP_TO_BYTES(a) ACPI_DIV_8((a) + 7) -#define ACPI_ROUND_BITS_DOWN_TO_BYTES(a) ACPI_DIV_8((a)) +#define ACPI_ROUND_UP_to_32_bIT(a) ACPI_ROUND_UP(a,4) +#define ACPI_ROUND_UP_to_64_bIT(a) ACPI_ROUND_UP(a,8) +#define ACPI_ROUND_UP_TO_NATIVE_WORD(a) ACPI_ROUND_UP(a,sizeof(acpi_native_uint)) -#define ACPI_ROUND_UP_TO_1K(a) (((a) + 1023) >> 10) +#define ACPI_ROUND_BITS_UP_TO_BYTES(a) ACPI_DIV_8((a) + 7) +#define ACPI_ROUND_BITS_DOWN_TO_BYTES(a) ACPI_DIV_8((a)) + +#define ACPI_ROUND_UP_TO_1K(a) (((a) + 1023) >> 10) /* Generic (non-power-of-two) rounding */ -#define ACPI_ROUND_UP_TO(value,boundary) (((value) + ((boundary)-1)) / (boundary)) +#define ACPI_ROUND_UP_TO(value,boundary) (((value) + ((boundary)-1)) / (boundary)) + +#define ACPI_IS_MISALIGNED(value) (((acpi_native_uint)value) & (sizeof(acpi_native_uint)-1)) /* * Bitmask creation @@ -371,10 +375,10 @@ * MASK_BITS_ABOVE creates a mask starting AT the position and above * MASK_BITS_BELOW creates a mask starting one bit BELOW the position */ -#define ACPI_MASK_BITS_ABOVE(position) (~((ACPI_INTEGER_MAX) << ((u32) (position)))) -#define ACPI_MASK_BITS_BELOW(position) ((ACPI_INTEGER_MAX) << ((u32) (position))) +#define ACPI_MASK_BITS_ABOVE(position) (~((ACPI_INTEGER_MAX) << ((u32) (position)))) +#define ACPI_MASK_BITS_BELOW(position) ((ACPI_INTEGER_MAX) << ((u32) (position))) -#define ACPI_IS_OCTAL_DIGIT(d) (((char)(d) >= '0') && ((char)(d) <= '7')) +#define ACPI_IS_OCTAL_DIGIT(d) (((char)(d) >= '0') && ((char)(d) <= '7')) /* Bitfields within ACPI registers */ diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index 7ca89cde706..95c3c8b6d61 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -154,7 +154,6 @@ typedef u64 acpi_physical_address; #define ACPI_MAX_PTR ACPI_UINT64_MAX #define ACPI_SIZE_MAX ACPI_UINT64_MAX -#define ALIGNED_ADDRESS_BOUNDARY 0x00000008 #define ACPI_USE_NATIVE_DIVIDE /* Has native 64-bit integer support */ /* @@ -195,8 +194,6 @@ typedef u64 acpi_physical_address; #define ACPI_MAX_PTR ACPI_UINT32_MAX #define ACPI_SIZE_MAX ACPI_UINT32_MAX -#define ALIGNED_ADDRESS_BOUNDARY 0x00000004 - /******************************************************************************* * * Types specific to 16-bit targets @@ -223,7 +220,6 @@ typedef char *acpi_physical_address; #define ACPI_MAX_PTR ACPI_UINT16_MAX #define ACPI_SIZE_MAX ACPI_UINT16_MAX -#define ALIGNED_ADDRESS_BOUNDARY 0x00000002 #define ACPI_USE_NATIVE_DIVIDE /* No 64-bit integers, ok to use native divide */ /* 64-bit integers cannot be supported */ @@ -1297,12 +1293,6 @@ struct acpi_resource { #define ACPI_NEXT_RESOURCE(res) (struct acpi_resource *)((u8 *) res + res->length) -#ifndef ACPI_MISALIGNMENT_NOT_SUPPORTED -#define ACPI_ALIGN_RESOURCE_SIZE(length) (length) -#else -#define ACPI_ALIGN_RESOURCE_SIZE(length) ACPI_ROUND_UP_TO_NATIVE_WORD(length) -#endif - /* * END: of definitions for Resource Attributes */ -- cgit v1.2.3 From 8313524a0d466f451a62709aaedf988d8257b21c Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Tue, 3 Oct 2006 00:00:00 -0400 Subject: ACPI: ACPICA 20060310 Tagged all external interfaces to the subsystem with the new ACPI_EXPORT_SYMBOL macro. This macro can be defined as necessary to assist kernel integration. For Linux, the macro resolves to the EXPORT_SYMBOL macro. The default definition is NULL. Added the ACPI_THREAD_ID type for the return value from acpi_os_get_thread_id(). This allows the host to define this as necessary to simplify kernel integration. The default definition is ACPI_NATIVE_UINT. Valery Podrezov fixed two interpreter problems related to error processing, the deletion of objects, and placing invalid pointers onto the internal operator result stack. http://bugzilla.kernel.org/show_bug.cgi?id=6028 http://bugzilla.kernel.org/show_bug.cgi?id=6151 Increased the reference count threshold where a warning is emitted for large reference counts in order to eliminate unnecessary warnings on systems with large namespaces (especially 64-bit.) Increased the value from 0x400 to 0x800. Due to universal disagreement as to the meaning of the 'c' in the calloc() function, the ACPI_MEM_CALLOCATE macro has been renamed to ACPI_ALLOCATE_ZEROED so that the purpose of the interface is 'clear'. ACPI_MEM_ALLOCATE and ACPI_MEM_FREE are renamed to ACPI_ALLOCATE and ACPI_FREE. Signed-off-by: Bob Moore Signed-off-by: Len Brown --- drivers/acpi/dispatcher/dsmthdat.c | 2 +- drivers/acpi/dispatcher/dsobject.c | 9 +++--- drivers/acpi/dispatcher/dsutils.c | 2 +- drivers/acpi/dispatcher/dswload.c | 1 - drivers/acpi/dispatcher/dswstate.c | 8 ++--- drivers/acpi/events/evgpeblk.c | 39 ++++++++++++------------ drivers/acpi/events/evregion.c | 2 +- drivers/acpi/events/evrgnini.c | 8 ++--- drivers/acpi/events/evxface.c | 32 ++++++++------------ drivers/acpi/events/evxfevnt.c | 40 ++++++++++++------------- drivers/acpi/events/evxfregn.c | 7 ++--- drivers/acpi/executer/exconfig.c | 4 +-- drivers/acpi/executer/exdump.c | 2 +- drivers/acpi/executer/exfield.c | 4 +-- drivers/acpi/executer/exnames.c | 4 +-- drivers/acpi/executer/exoparg1.c | 17 +++++++---- drivers/acpi/executer/exoparg2.c | 4 +-- drivers/acpi/executer/exoparg3.c | 9 +++--- drivers/acpi/executer/exregion.c | 10 +++---- drivers/acpi/executer/exstorob.c | 8 ++--- drivers/acpi/hardware/hwregs.c | 11 ++----- drivers/acpi/hardware/hwsleep.c | 18 ++++++----- drivers/acpi/hardware/hwtimer.c | 9 +++--- drivers/acpi/namespace/nsaccess.c | 19 +++++++----- drivers/acpi/namespace/nsalloc.c | 6 ++-- drivers/acpi/namespace/nsdumpdv.c | 2 +- drivers/acpi/namespace/nseval.c | 4 +-- drivers/acpi/namespace/nsinit.c | 2 +- drivers/acpi/namespace/nsnames.c | 10 ++----- drivers/acpi/namespace/nsparse.c | 2 +- drivers/acpi/namespace/nssearch.c | 2 +- drivers/acpi/namespace/nsutils.c | 12 ++++---- drivers/acpi/namespace/nsxfeval.c | 38 ++++++++++++------------ drivers/acpi/namespace/nsxfname.c | 16 ++++------ drivers/acpi/namespace/nsxfobj.c | 10 ++----- drivers/acpi/parser/pstree.c | 1 - drivers/acpi/resources/rsinfo.c | 1 + drivers/acpi/resources/rsxface.c | 29 ++++++++---------- drivers/acpi/tables/tbconvrt.c | 8 ++--- drivers/acpi/tables/tbget.c | 2 +- drivers/acpi/tables/tbinstal.c | 8 ++--- drivers/acpi/tables/tbxface.c | 15 +++++----- drivers/acpi/tables/tbxfroot.c | 22 ++++++-------- drivers/acpi/utilities/utalloc.c | 2 +- drivers/acpi/utilities/utcache.c | 8 ++--- drivers/acpi/utilities/utcopy.c | 24 +++++++-------- drivers/acpi/utilities/utdebug.c | 23 +++++--------- drivers/acpi/utilities/utdelete.c | 4 +-- drivers/acpi/utilities/uteval.c | 4 +-- drivers/acpi/utilities/utglobal.c | 6 ++-- drivers/acpi/utilities/utinit.c | 8 ++--- drivers/acpi/utilities/utmisc.c | 2 +- drivers/acpi/utilities/utmutex.c | 4 +-- drivers/acpi/utilities/utobject.c | 5 ++-- drivers/acpi/utilities/utxface.c | 24 ++++++++------- include/acpi/acconfig.h | 6 ++-- include/acpi/acdisasm.h | 23 ++++++++++++++ include/acpi/aclocal.h | 8 ++--- include/acpi/acmacros.h | 12 ++++---- include/acpi/acnamesp.h | 5 ++++ include/acpi/acpiosxf.h | 2 +- include/acpi/actypes.h | 15 ++++++++++ include/acpi/amlresrc.h | 61 +++++++++++++++++++------------------- include/acpi/platform/acenv.h | 6 ++-- include/acpi/platform/aclinux.h | 19 +++++------- 65 files changed, 367 insertions(+), 363 deletions(-) diff --git a/drivers/acpi/dispatcher/dsmthdat.c b/drivers/acpi/dispatcher/dsmthdat.c index f7cb5170aa1..2ed48439835 100644 --- a/drivers/acpi/dispatcher/dsmthdat.c +++ b/drivers/acpi/dispatcher/dsmthdat.c @@ -81,7 +81,7 @@ acpi_ds_method_data_get_type(u16 opcode, * special data types. * * NOTES: walk_state fields are initialized to zero by the - * ACPI_MEM_CALLOCATE(). + * ACPI_ALLOCATE_ZEROED(). * * A pseudo-Namespace Node is assigned to each argument and local * so that ref_of() can return a pointer to the Node. diff --git a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c index 1f2d0c6ef36..ce54715f13a 100644 --- a/drivers/acpi/dispatcher/dsobject.c +++ b/drivers/acpi/dispatcher/dsobject.c @@ -245,7 +245,7 @@ acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state, "Buffer defined with zero length in AML, creating\n")); } else { obj_desc->buffer.pointer = - ACPI_MEM_CALLOCATE(obj_desc->buffer.length); + ACPI_ALLOCATE_ZEROED(obj_desc->buffer.length); if (!obj_desc->buffer.pointer) { acpi_ut_delete_object_desc(obj_desc); return_ACPI_STATUS(AE_NO_MEMORY); @@ -341,9 +341,10 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, * individual objects). Add an extra pointer slot so * that the list is always null terminated. */ - obj_desc->package.elements = ACPI_MEM_CALLOCATE(((acpi_size) obj_desc-> - package.count + - 1) * sizeof(void *)); + obj_desc->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size) + obj_desc->package. + count + + 1) * sizeof(void *)); if (!obj_desc->package.elements) { acpi_ut_delete_object_desc(obj_desc); diff --git a/drivers/acpi/dispatcher/dsutils.c b/drivers/acpi/dispatcher/dsutils.c index 3fbe17ebef5..ab24aa88e2f 100644 --- a/drivers/acpi/dispatcher/dsutils.c +++ b/drivers/acpi/dispatcher/dsutils.c @@ -577,7 +577,7 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, /* Free the namestring created above */ - ACPI_MEM_FREE(name_string); + ACPI_FREE(name_string); /* Check status from the lookup */ diff --git a/drivers/acpi/dispatcher/dswload.c b/drivers/acpi/dispatcher/dswload.c index 02b03126e14..1ad7870101f 100644 --- a/drivers/acpi/dispatcher/dswload.c +++ b/drivers/acpi/dispatcher/dswload.c @@ -1113,7 +1113,6 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) ACPI_NS_DONT_OPEN_SCOPE, walk_state, &(new_node)); if (ACPI_SUCCESS(status)) { - /* * Make sure that what we found is indeed a method * We didn't search for a method on purpose, to see if the name diff --git a/drivers/acpi/dispatcher/dswstate.c b/drivers/acpi/dispatcher/dswstate.c index 5bc340b1b28..d2846ffc977 100644 --- a/drivers/acpi/dispatcher/dswstate.c +++ b/drivers/acpi/dispatcher/dswstate.c @@ -66,7 +66,6 @@ void *acpi_ds_obj_stack_get_value(u32 index, #endif #ifdef ACPI_FUTURE_USAGE - /******************************************************************************* * * FUNCTION: acpi_ds_result_remove @@ -128,7 +127,6 @@ acpi_ds_result_remove(union acpi_operand_object **object, return (AE_OK); } - #endif /* ACPI_FUTURE_USAGE */ /******************************************************************************* @@ -645,7 +643,7 @@ struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id, ACPI_FUNCTION_TRACE("ds_create_walk_state"); - walk_state = ACPI_MEM_CALLOCATE(sizeof(struct acpi_walk_state)); + walk_state = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_walk_state)); if (!walk_state) { return_PTR(NULL); } @@ -668,7 +666,7 @@ struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id, status = acpi_ds_result_stack_push(walk_state); if (ACPI_FAILURE(status)) { - ACPI_MEM_FREE(walk_state); + ACPI_FREE(walk_state); return_PTR(NULL); } @@ -859,7 +857,7 @@ void acpi_ds_delete_walk_state(struct acpi_walk_state *walk_state) acpi_ut_delete_generic_state(state); } - ACPI_MEM_FREE(walk_state); + ACPI_FREE(walk_state); return_VOID; } diff --git a/drivers/acpi/events/evgpeblk.c b/drivers/acpi/events/evgpeblk.c index 87e77a138ff..e8e72986f0d 100644 --- a/drivers/acpi/events/evgpeblk.c +++ b/drivers/acpi/events/evgpeblk.c @@ -207,7 +207,7 @@ acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info, if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_HANDLER) { - ACPI_MEM_FREE(gpe_event_info->dispatch.handler); + ACPI_FREE(gpe_event_info->dispatch.handler); gpe_event_info->dispatch.handler = NULL; gpe_event_info->flags &= ~ACPI_GPE_DISPATCH_MASK; @@ -504,7 +504,7 @@ static struct acpi_gpe_xrupt_info *acpi_ev_get_gpe_xrupt_block(u32 /* Not found, must allocate a new xrupt descriptor */ - gpe_xrupt = ACPI_MEM_CALLOCATE(sizeof(struct acpi_gpe_xrupt_info)); + gpe_xrupt = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_xrupt_info)); if (!gpe_xrupt) { return_PTR(NULL); } @@ -595,7 +595,7 @@ acpi_ev_delete_gpe_xrupt(struct acpi_gpe_xrupt_info *gpe_xrupt) /* Free the block */ - ACPI_MEM_FREE(gpe_xrupt); + ACPI_FREE(gpe_xrupt); return_ACPI_STATUS(AE_OK); } @@ -712,9 +712,9 @@ acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block) /* Free the gpe_block */ - ACPI_MEM_FREE(gpe_block->register_info); - ACPI_MEM_FREE(gpe_block->event_info); - ACPI_MEM_FREE(gpe_block); + ACPI_FREE(gpe_block->register_info); + ACPI_FREE(gpe_block->event_info); + ACPI_FREE(gpe_block); unlock_and_exit: status = acpi_ut_release_mutex(ACPI_MTX_EVENTS); @@ -748,10 +748,10 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block) /* Allocate the GPE register information block */ - gpe_register_info = ACPI_MEM_CALLOCATE((acpi_size) gpe_block-> - register_count * - sizeof(struct - acpi_gpe_register_info)); + gpe_register_info = ACPI_ALLOCATE_ZEROED((acpi_size) gpe_block-> + register_count * + sizeof(struct + acpi_gpe_register_info)); if (!gpe_register_info) { ACPI_ERROR((AE_INFO, "Could not allocate the gpe_register_info table")); @@ -762,10 +762,11 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block) * Allocate the GPE event_info block. There are eight distinct GPEs * per register. Initialization to zeros is sufficient. */ - gpe_event_info = ACPI_MEM_CALLOCATE(((acpi_size) gpe_block-> - register_count * - ACPI_GPE_REGISTER_WIDTH) * - sizeof(struct acpi_gpe_event_info)); + gpe_event_info = ACPI_ALLOCATE_ZEROED(((acpi_size) gpe_block-> + register_count * + ACPI_GPE_REGISTER_WIDTH) * + sizeof(struct + acpi_gpe_event_info)); if (!gpe_event_info) { ACPI_ERROR((AE_INFO, "Could not allocate the gpe_event_info table")); @@ -848,10 +849,10 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block) error_exit: if (gpe_register_info) { - ACPI_MEM_FREE(gpe_register_info); + ACPI_FREE(gpe_register_info); } if (gpe_event_info) { - ACPI_MEM_FREE(gpe_event_info); + ACPI_FREE(gpe_event_info); } return_ACPI_STATUS(status); @@ -895,7 +896,7 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, /* Allocate a new GPE block */ - gpe_block = ACPI_MEM_CALLOCATE(sizeof(struct acpi_gpe_block_info)); + gpe_block = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_block_info)); if (!gpe_block) { return_ACPI_STATUS(AE_NO_MEMORY); } @@ -915,7 +916,7 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, */ status = acpi_ev_create_gpe_info_blocks(gpe_block); if (ACPI_FAILURE(status)) { - ACPI_MEM_FREE(gpe_block); + ACPI_FREE(gpe_block); return_ACPI_STATUS(status); } @@ -923,7 +924,7 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, status = acpi_ev_install_gpe_block(gpe_block, interrupt_number); if (ACPI_FAILURE(status)) { - ACPI_MEM_FREE(gpe_block); + ACPI_FREE(gpe_block); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/events/evregion.c b/drivers/acpi/events/evregion.c index b831ec4bcae..2b900ef05fa 100644 --- a/drivers/acpi/events/evregion.c +++ b/drivers/acpi/events/evregion.c @@ -366,7 +366,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, /* The handler for this region was already installed */ - ACPI_MEM_FREE(region_context); + ACPI_FREE(region_context); } else { /* * Save the returned context for use in all accesses to diff --git a/drivers/acpi/events/evrgnini.c b/drivers/acpi/events/evrgnini.c index a0bffc2a078..db98747fe54 100644 --- a/drivers/acpi/events/evrgnini.c +++ b/drivers/acpi/events/evrgnini.c @@ -75,7 +75,7 @@ acpi_ev_system_memory_region_setup(acpi_handle handle, if (function == ACPI_REGION_DEACTIVATE) { if (*region_context) { - ACPI_MEM_FREE(*region_context); + ACPI_FREE(*region_context); *region_context = NULL; } return_ACPI_STATUS(AE_OK); @@ -84,7 +84,7 @@ acpi_ev_system_memory_region_setup(acpi_handle handle, /* Create a new context */ local_region_context = - ACPI_MEM_CALLOCATE(sizeof(struct acpi_mem_space_context)); + ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_mem_space_context)); if (!(local_region_context)) { return_ACPI_STATUS(AE_NO_MEMORY); } @@ -178,7 +178,7 @@ acpi_ev_pci_config_region_setup(acpi_handle handle, *region_context = NULL; if (function == ACPI_REGION_DEACTIVATE) { if (pci_id) { - ACPI_MEM_FREE(pci_id); + ACPI_FREE(pci_id); } return_ACPI_STATUS(status); } @@ -264,7 +264,7 @@ acpi_ev_pci_config_region_setup(acpi_handle handle, /* Region is still not initialized. Create a new context */ - pci_id = ACPI_MEM_CALLOCATE(sizeof(struct acpi_pci_id)); + pci_id = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pci_id)); if (!pci_id) { return_ACPI_STATUS(AE_NO_MEMORY); } diff --git a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c index ba16fda3a15..7d1cebc871f 100644 --- a/drivers/acpi/events/evxface.c +++ b/drivers/acpi/events/evxface.c @@ -41,8 +41,6 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include - #include #include #include @@ -90,6 +88,8 @@ acpi_status acpi_install_exception_handler(acpi_exception_handler handler) (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); return_ACPI_STATUS(status); } + +ACPI_EXPORT_SYMBOL(acpi_install_exception_handler) #endif /* ACPI_FUTURE_USAGE */ /******************************************************************************* @@ -107,7 +107,6 @@ acpi_status acpi_install_exception_handler(acpi_exception_handler handler) * event. * ******************************************************************************/ - acpi_status acpi_install_fixed_event_handler(u32 event, acpi_event_handler handler, void *context) @@ -161,7 +160,7 @@ acpi_install_fixed_event_handler(u32 event, return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_install_fixed_event_handler); +ACPI_EXPORT_SYMBOL(acpi_install_fixed_event_handler) /******************************************************************************* * @@ -175,7 +174,6 @@ EXPORT_SYMBOL(acpi_install_fixed_event_handler); * DESCRIPTION: Disables the event and unregisters the event handler. * ******************************************************************************/ - acpi_status acpi_remove_fixed_event_handler(u32 event, acpi_event_handler handler) { @@ -216,7 +214,7 @@ acpi_remove_fixed_event_handler(u32 event, acpi_event_handler handler) return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_remove_fixed_event_handler); +ACPI_EXPORT_SYMBOL(acpi_remove_fixed_event_handler) /******************************************************************************* * @@ -235,7 +233,6 @@ EXPORT_SYMBOL(acpi_remove_fixed_event_handler); * DESCRIPTION: Install a handler for notifies on an ACPI device * ******************************************************************************/ - acpi_status acpi_install_notify_handler(acpi_handle device, u32 handler_type, @@ -384,7 +381,7 @@ acpi_install_notify_handler(acpi_handle device, return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_install_notify_handler); +ACPI_EXPORT_SYMBOL(acpi_install_notify_handler) /******************************************************************************* * @@ -402,7 +399,6 @@ EXPORT_SYMBOL(acpi_install_notify_handler); * DESCRIPTION: Remove a handler for notifies on an ACPI device * ******************************************************************************/ - acpi_status acpi_remove_notify_handler(acpi_handle device, u32 handler_type, acpi_notify_handler handler) @@ -538,7 +534,7 @@ acpi_remove_notify_handler(acpi_handle device, return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_remove_notify_handler); +ACPI_EXPORT_SYMBOL(acpi_remove_notify_handler) /******************************************************************************* * @@ -557,7 +553,6 @@ EXPORT_SYMBOL(acpi_remove_notify_handler); * DESCRIPTION: Install a handler for a General Purpose Event. * ******************************************************************************/ - acpi_status acpi_install_gpe_handler(acpi_handle gpe_device, u32 gpe_number, @@ -599,7 +594,7 @@ acpi_install_gpe_handler(acpi_handle gpe_device, /* Allocate and init handler object */ - handler = ACPI_MEM_CALLOCATE(sizeof(struct acpi_handler_info)); + handler = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_handler_info)); if (!handler) { status = AE_NO_MEMORY; goto unlock_and_exit; @@ -633,7 +628,7 @@ acpi_install_gpe_handler(acpi_handle gpe_device, return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_install_gpe_handler); +ACPI_EXPORT_SYMBOL(acpi_install_gpe_handler) /******************************************************************************* * @@ -649,7 +644,6 @@ EXPORT_SYMBOL(acpi_install_gpe_handler); * DESCRIPTION: Remove a handler for a General Purpose acpi_event. * ******************************************************************************/ - acpi_status acpi_remove_gpe_handler(acpi_handle gpe_device, u32 gpe_number, acpi_event_handler address) @@ -727,14 +721,14 @@ acpi_remove_gpe_handler(acpi_handle gpe_device, /* Now we can free the handler object */ - ACPI_MEM_FREE(handler); + ACPI_FREE(handler); unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_remove_gpe_handler); +ACPI_EXPORT_SYMBOL(acpi_remove_gpe_handler) /******************************************************************************* * @@ -749,7 +743,6 @@ EXPORT_SYMBOL(acpi_remove_gpe_handler); * DESCRIPTION: Acquire the ACPI Global Lock * ******************************************************************************/ - acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle) { acpi_status status; @@ -774,7 +767,7 @@ acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle) return (status); } -EXPORT_SYMBOL(acpi_acquire_global_lock); +ACPI_EXPORT_SYMBOL(acpi_acquire_global_lock) /******************************************************************************* * @@ -787,7 +780,6 @@ EXPORT_SYMBOL(acpi_acquire_global_lock); * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid. * ******************************************************************************/ - acpi_status acpi_release_global_lock(u32 handle) { acpi_status status; @@ -800,4 +792,4 @@ acpi_status acpi_release_global_lock(u32 handle) return (status); } -EXPORT_SYMBOL(acpi_release_global_lock); +ACPI_EXPORT_SYMBOL(acpi_release_global_lock) diff --git a/drivers/acpi/events/evxfevnt.c b/drivers/acpi/events/evxfevnt.c index babebb50140..4a36559fa81 100644 --- a/drivers/acpi/events/evxfevnt.c +++ b/drivers/acpi/events/evxfevnt.c @@ -41,8 +41,6 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include - #include #include #include @@ -94,6 +92,8 @@ acpi_status acpi_enable(void) return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL(acpi_enable) + /******************************************************************************* * * FUNCTION: acpi_disable @@ -105,7 +105,6 @@ acpi_status acpi_enable(void) * DESCRIPTION: Transfers the system into LEGACY (non-ACPI) mode. * ******************************************************************************/ - acpi_status acpi_disable(void) { acpi_status status = AE_OK; @@ -137,6 +136,8 @@ acpi_status acpi_disable(void) return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL(acpi_disable) + /******************************************************************************* * * FUNCTION: acpi_enable_event @@ -149,7 +150,6 @@ acpi_status acpi_disable(void) * DESCRIPTION: Enable an ACPI event (fixed) * ******************************************************************************/ - acpi_status acpi_enable_event(u32 event, u32 flags) { acpi_status status = AE_OK; @@ -193,7 +193,7 @@ acpi_status acpi_enable_event(u32 event, u32 flags) return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_enable_event); +ACPI_EXPORT_SYMBOL(acpi_enable_event) /******************************************************************************* * @@ -208,7 +208,6 @@ EXPORT_SYMBOL(acpi_enable_event); * DESCRIPTION: Set the type of an individual GPE * ******************************************************************************/ - acpi_status acpi_set_gpe_type(acpi_handle gpe_device, u32 gpe_number, u8 type) { acpi_status status = AE_OK; @@ -236,7 +235,7 @@ acpi_status acpi_set_gpe_type(acpi_handle gpe_device, u32 gpe_number, u8 type) return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_set_gpe_type); +ACPI_EXPORT_SYMBOL(acpi_set_gpe_type) /******************************************************************************* * @@ -252,7 +251,6 @@ EXPORT_SYMBOL(acpi_set_gpe_type); * DESCRIPTION: Enable an ACPI event (general purpose) * ******************************************************************************/ - acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) { acpi_status status = AE_OK; @@ -288,7 +286,7 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_enable_gpe); +ACPI_EXPORT_SYMBOL(acpi_enable_gpe) /******************************************************************************* * @@ -304,7 +302,6 @@ EXPORT_SYMBOL(acpi_enable_gpe); * DESCRIPTION: Disable an ACPI event (general purpose) * ******************************************************************************/ - acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) { acpi_status status = AE_OK; @@ -338,6 +335,8 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL(acpi_disable_gpe) + /******************************************************************************* * * FUNCTION: acpi_disable_event @@ -350,7 +349,6 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) * DESCRIPTION: Disable an ACPI event (fixed) * ******************************************************************************/ - acpi_status acpi_disable_event(u32 event, u32 flags) { acpi_status status = AE_OK; @@ -392,7 +390,7 @@ acpi_status acpi_disable_event(u32 event, u32 flags) return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_disable_event); +ACPI_EXPORT_SYMBOL(acpi_disable_event) /******************************************************************************* * @@ -405,7 +403,6 @@ EXPORT_SYMBOL(acpi_disable_event); * DESCRIPTION: Clear an ACPI event (fixed) * ******************************************************************************/ - acpi_status acpi_clear_event(u32 event) { acpi_status status = AE_OK; @@ -429,7 +426,7 @@ acpi_status acpi_clear_event(u32 event) return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_clear_event); +ACPI_EXPORT_SYMBOL(acpi_clear_event) /******************************************************************************* * @@ -444,7 +441,6 @@ EXPORT_SYMBOL(acpi_clear_event); * DESCRIPTION: Clear an ACPI event (general purpose) * ******************************************************************************/ - acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) { acpi_status status = AE_OK; @@ -478,6 +474,8 @@ acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL(acpi_clear_gpe) + #ifdef ACPI_FUTURE_USAGE /******************************************************************************* * @@ -492,7 +490,6 @@ acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) * DESCRIPTION: Obtains and returns the current status of the event * ******************************************************************************/ - acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status) { acpi_status status = AE_OK; @@ -518,6 +515,8 @@ acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status) return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL(acpi_get_event_status) + /******************************************************************************* * * FUNCTION: acpi_get_gpe_status @@ -533,7 +532,6 @@ acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status) * DESCRIPTION: Get status of an event (general purpose) * ******************************************************************************/ - acpi_status acpi_get_gpe_status(acpi_handle gpe_device, u32 gpe_number, u32 flags, acpi_event_status * event_status) @@ -570,6 +568,8 @@ acpi_get_gpe_status(acpi_handle gpe_device, } return_ACPI_STATUS(status); } + +ACPI_EXPORT_SYMBOL(acpi_get_gpe_status) #endif /* ACPI_FUTURE_USAGE */ /******************************************************************************* @@ -586,7 +586,6 @@ acpi_get_gpe_status(acpi_handle gpe_device, * DESCRIPTION: Create and Install a block of GPE registers * ******************************************************************************/ - acpi_status acpi_install_gpe_block(acpi_handle gpe_device, struct acpi_generic_address *gpe_block_address, @@ -666,7 +665,7 @@ acpi_install_gpe_block(acpi_handle gpe_device, return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_install_gpe_block); +ACPI_EXPORT_SYMBOL(acpi_install_gpe_block) /******************************************************************************* * @@ -679,7 +678,6 @@ EXPORT_SYMBOL(acpi_install_gpe_block); * DESCRIPTION: Remove a previously installed block of GPE registers * ******************************************************************************/ - acpi_status acpi_remove_gpe_block(acpi_handle gpe_device) { union acpi_operand_object *obj_desc; @@ -722,4 +720,4 @@ acpi_status acpi_remove_gpe_block(acpi_handle gpe_device) return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_remove_gpe_block); +ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block) diff --git a/drivers/acpi/events/evxfregn.c b/drivers/acpi/events/evxfregn.c index 368c8aa0094..63a070bb9d1 100644 --- a/drivers/acpi/events/evxfregn.c +++ b/drivers/acpi/events/evxfregn.c @@ -42,8 +42,6 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include - #include #include #include @@ -114,7 +112,7 @@ acpi_install_address_space_handler(acpi_handle device, return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_install_address_space_handler); +ACPI_EXPORT_SYMBOL(acpi_install_address_space_handler) /******************************************************************************* * @@ -129,7 +127,6 @@ EXPORT_SYMBOL(acpi_install_address_space_handler); * DESCRIPTION: Remove a previously installed handler. * ******************************************************************************/ - acpi_status acpi_remove_address_space_handler(acpi_handle device, acpi_adr_space_type space_id, @@ -242,4 +239,4 @@ acpi_remove_address_space_handler(acpi_handle device, return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_remove_address_space_handler); +ACPI_EXPORT_SYMBOL(acpi_remove_address_space_handler) diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c index 864530f754c..e0deffb5679 100644 --- a/drivers/acpi/executer/exconfig.c +++ b/drivers/acpi/executer/exconfig.c @@ -349,7 +349,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, /* Allocate a buffer for the entire table */ - table_ptr = ACPI_MEM_ALLOCATE(table_header.length); + table_ptr = ACPI_ALLOCATE(table_header.length); if (!table_ptr) { return_ACPI_STATUS(AE_NO_MEMORY); } @@ -447,7 +447,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, cleanup: if (ACPI_FAILURE(status)) { - ACPI_MEM_FREE(table_ptr); + ACPI_FREE(table_ptr); } return_ACPI_STATUS(status); } diff --git a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c index 0a53d31e09d..502293c35af 100644 --- a/drivers/acpi/executer/exdump.c +++ b/drivers/acpi/executer/exdump.c @@ -903,7 +903,7 @@ static void acpi_ex_dump_reference_obj(union acpi_operand_object *obj_desc) acpi_os_printf("Could not convert name to pathname\n"); } else { acpi_os_printf("%s\n", (char *)ret_buf.pointer); - ACPI_MEM_FREE(ret_buf.pointer); + ACPI_FREE(ret_buf.pointer); } } else if (obj_desc->reference.object) { acpi_os_printf("\nReferenced Object: %p\n", diff --git a/drivers/acpi/executer/exfield.c b/drivers/acpi/executer/exfield.c index 215783a33c2..36c265a00c2 100644 --- a/drivers/acpi/executer/exfield.c +++ b/drivers/acpi/executer/exfield.c @@ -333,7 +333,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, /* We need to create a new buffer */ - new_buffer = ACPI_MEM_CALLOCATE(required_length); + new_buffer = ACPI_ALLOCATE_ZEROED(required_length); if (!new_buffer) { return_ACPI_STATUS(AE_NO_MEMORY); } @@ -377,7 +377,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, /* Free temporary buffer if we used one */ if (new_buffer) { - ACPI_MEM_FREE(new_buffer); + ACPI_FREE(new_buffer); } return_ACPI_STATUS(status); diff --git a/drivers/acpi/executer/exnames.c b/drivers/acpi/executer/exnames.c index f9bc81c1b78..80bbc20756a 100644 --- a/drivers/acpi/executer/exnames.c +++ b/drivers/acpi/executer/exnames.c @@ -98,7 +98,7 @@ static char *acpi_ex_allocate_name_string(u32 prefix_count, u32 num_name_segs) * Allocate a buffer for the name. * This buffer must be deleted by the caller! */ - name_string = ACPI_MEM_ALLOCATE(size_needed); + name_string = ACPI_ALLOCATE(size_needed); if (!name_string) { ACPI_ERROR((AE_INFO, "Could not allocate size %d", size_needed)); @@ -424,7 +424,7 @@ acpi_ex_get_name_string(acpi_object_type data_type, if (ACPI_FAILURE(status)) { if (name_string) { - ACPI_MEM_FREE(name_string); + ACPI_FREE(name_string); } return_ACPI_STATUS(status); } diff --git a/drivers/acpi/executer/exoparg1.c b/drivers/acpi/executer/exoparg1.c index 4f3627ee2b2..d00f766246f 100644 --- a/drivers/acpi/executer/exoparg1.c +++ b/drivers/acpi/executer/exoparg1.c @@ -554,16 +554,18 @@ acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state) cleanup: - if (!walk_state->result_obj) { - walk_state->result_obj = return_desc; - } - /* Delete return object on error */ if (ACPI_FAILURE(status)) { acpi_ut_remove_reference(return_desc); } + /* Save return object on success */ + + else if (!walk_state->result_obj) { + walk_state->result_obj = return_desc; + } + return_ACPI_STATUS(status); } @@ -1028,6 +1030,11 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) acpi_ut_remove_reference(return_desc); } - walk_state->result_obj = return_desc; + /* Save return object on success */ + + else { + walk_state->result_obj = return_desc; + } + return_ACPI_STATUS(status); } diff --git a/drivers/acpi/executer/exoparg2.c b/drivers/acpi/executer/exoparg2.c index 5e1abb12c74..690e43db0ab 100644 --- a/drivers/acpi/executer/exoparg2.c +++ b/drivers/acpi/executer/exoparg2.c @@ -391,7 +391,6 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state) index = operand[1]->integer.value; return_desc->reference.offset = (u32) index; return_desc->reference.opcode = AML_INDEX_OP; - return_desc->reference.object = operand[0]; /* * At this point, the Source operand is a String, Buffer, or Package. @@ -445,9 +444,10 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state) } /* - * Add a reference to the target package/buffer/string for the life + * Save the target object and add a reference to it for the life * of the index */ + return_desc->reference.object = operand[0]; acpi_ut_add_reference(operand[0]); /* Store the reference to the Target */ diff --git a/drivers/acpi/executer/exoparg3.c b/drivers/acpi/executer/exoparg3.c index 8da794ec35b..4897e6c3431 100644 --- a/drivers/acpi/executer/exoparg3.c +++ b/drivers/acpi/executer/exoparg3.c @@ -100,8 +100,7 @@ acpi_status acpi_ex_opcode_3A_0T_0R(struct acpi_walk_state *walk_state) (u32) operand[1]->integer.value, (u32) operand[2]->integer.value)); - fatal = - ACPI_MEM_ALLOCATE(sizeof(struct acpi_signal_fatal_info)); + fatal = ACPI_ALLOCATE(sizeof(struct acpi_signal_fatal_info)); if (fatal) { fatal->type = (u32) operand[0]->integer.value; fatal->code = (u32) operand[1]->integer.value; @@ -114,7 +113,7 @@ acpi_status acpi_ex_opcode_3A_0T_0R(struct acpi_walk_state *walk_state) /* Might return while OS is shutting down, just continue */ - ACPI_MEM_FREE(fatal); + ACPI_FREE(fatal); break; default: @@ -196,7 +195,7 @@ acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state) /* Always allocate a new buffer for the String */ - buffer = ACPI_MEM_CALLOCATE((acpi_size) length + 1); + buffer = ACPI_ALLOCATE_ZEROED((acpi_size) length + 1); if (!buffer) { status = AE_NO_MEMORY; goto cleanup; @@ -211,7 +210,7 @@ acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state) /* Allocate a new buffer for the Buffer */ - buffer = ACPI_MEM_CALLOCATE(length); + buffer = ACPI_ALLOCATE_ZEROED(length); if (!buffer) { status = AE_NO_MEMORY; goto cleanup; diff --git a/drivers/acpi/executer/exregion.c b/drivers/acpi/executer/exregion.c index 9db68d19253..fdeda7beae4 100644 --- a/drivers/acpi/executer/exregion.c +++ b/drivers/acpi/executer/exregion.c @@ -182,8 +182,8 @@ acpi_ex_system_memory_space_handler(u32 function, (acpi_integer) mem_info->mapped_physical_address); ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "system_memory %d (%d width) Address=%8.8X%8.8X\n", - function, bit_width, ACPI_FORMAT_UINT64(address))); + "System-Memory (width %d) R/W %d Address=%8.8X%8.8X\n", + bit_width, function, ACPI_FORMAT_UINT64(address))); /* * Perform the memory read or write @@ -287,8 +287,8 @@ acpi_ex_system_io_space_handler(u32 function, ACPI_FUNCTION_TRACE("ex_system_io_space_handler"); ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "system_iO %d (%d width) Address=%8.8X%8.8X\n", - function, bit_width, ACPI_FORMAT_UINT64(address))); + "System-IO (width %d) R/W %d Address=%8.8X%8.8X\n", + bit_width, function, ACPI_FORMAT_UINT64(address))); /* Decode the function parameter */ @@ -361,7 +361,7 @@ acpi_ex_pci_config_space_handler(u32 function, pci_register = (u16) (u32) address; ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "pci_config %d (%d) Seg(%04x) Bus(%04x) Dev(%04x) Func(%04x) Reg(%04x)\n", + "Pci-Config %d (%d) Seg(%04x) Bus(%04x) Dev(%04x) Func(%04x) Reg(%04x)\n", function, bit_width, pci_id->segment, pci_id->bus, pci_id->device, pci_id->function, pci_register)); diff --git a/drivers/acpi/executer/exstorob.c b/drivers/acpi/executer/exstorob.c index 41732d382bc..db42461101e 100644 --- a/drivers/acpi/executer/exstorob.c +++ b/drivers/acpi/executer/exstorob.c @@ -80,7 +80,7 @@ acpi_ex_store_buffer_to_buffer(union acpi_operand_object *source_desc, */ if ((target_desc->buffer.length == 0) || (target_desc->common.flags & AOPOBJ_STATIC_POINTER)) { - target_desc->buffer.pointer = ACPI_MEM_ALLOCATE(length); + target_desc->buffer.pointer = ACPI_ALLOCATE(length); if (!target_desc->buffer.pointer) { return_ACPI_STATUS(AE_NO_MEMORY); } @@ -188,11 +188,11 @@ acpi_ex_store_string_to_string(union acpi_operand_object *source_desc, /* Only free if not a pointer into the DSDT */ - ACPI_MEM_FREE(target_desc->string.pointer); + ACPI_FREE(target_desc->string.pointer); } - target_desc->string.pointer = ACPI_MEM_CALLOCATE((acpi_size) - length + 1); + target_desc->string.pointer = ACPI_ALLOCATE_ZEROED((acpi_size) + length + 1); if (!target_desc->string.pointer) { return_ACPI_STATUS(AE_NO_MEMORY); } diff --git a/drivers/acpi/hardware/hwregs.c b/drivers/acpi/hardware/hwregs.c index 95c4ccb3a37..3d1f41c6bfe 100644 --- a/drivers/acpi/hardware/hwregs.c +++ b/drivers/acpi/hardware/hwregs.c @@ -43,8 +43,6 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include - #include #include #include @@ -220,7 +218,7 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 * sleep_type_a, u8 * sleep_type_b) return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_get_sleep_type_data); +ACPI_EXPORT_SYMBOL(acpi_get_sleep_type_data) /******************************************************************************* * @@ -233,7 +231,6 @@ EXPORT_SYMBOL(acpi_get_sleep_type_data); * DESCRIPTION: Map register_id into a register bitmask. * ******************************************************************************/ - struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id) { ACPI_FUNCTION_ENTRY(); @@ -312,7 +309,7 @@ acpi_status acpi_get_register(u32 register_id, u32 * return_value, u32 flags) return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_get_register); +ACPI_EXPORT_SYMBOL(acpi_get_register) /******************************************************************************* * @@ -328,7 +325,6 @@ EXPORT_SYMBOL(acpi_get_register); * DESCRIPTION: ACPI Bit Register write function. * ******************************************************************************/ - acpi_status acpi_set_register(u32 register_id, u32 value, u32 flags) { u32 register_value = 0; @@ -475,7 +471,7 @@ acpi_status acpi_set_register(u32 register_id, u32 value, u32 flags) return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_set_register); +ACPI_EXPORT_SYMBOL(acpi_set_register) /****************************************************************************** * @@ -491,7 +487,6 @@ EXPORT_SYMBOL(acpi_set_register); * given offset. * ******************************************************************************/ - acpi_status acpi_hw_register_read(u8 use_lock, u32 register_id, u32 * return_value) { diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c index 284a59ebcc2..685debafbb7 100644 --- a/drivers/acpi/hardware/hwsleep.c +++ b/drivers/acpi/hardware/hwsleep.c @@ -42,7 +42,6 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include #include #define _COMPONENT ACPI_HARDWARE @@ -79,6 +78,8 @@ acpi_set_firmware_waking_vector(acpi_physical_address physical_address) return_ACPI_STATUS(AE_OK); } +ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector) + /******************************************************************************* * * FUNCTION: acpi_get_firmware_waking_vector @@ -92,7 +93,6 @@ acpi_set_firmware_waking_vector(acpi_physical_address physical_address) * DESCRIPTION: Access function for the firmware_waking_vector field in FACS * ******************************************************************************/ - #ifdef ACPI_FUTURE_USAGE acpi_status acpi_get_firmware_waking_vector(acpi_physical_address * physical_address) @@ -118,6 +118,8 @@ acpi_get_firmware_waking_vector(acpi_physical_address * physical_address) return_ACPI_STATUS(AE_OK); } + +ACPI_EXPORT_SYMBOL(acpi_get_firmware_waking_vector) #endif /******************************************************************************* @@ -134,7 +136,6 @@ acpi_get_firmware_waking_vector(acpi_physical_address * physical_address) * various OS-specific tasks between the two steps. * ******************************************************************************/ - acpi_status acpi_enter_sleep_state_prep(u8 sleep_state) { acpi_status status; @@ -206,6 +207,8 @@ acpi_status acpi_enter_sleep_state_prep(u8 sleep_state) return_ACPI_STATUS(AE_OK); } +ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep) + /******************************************************************************* * * FUNCTION: acpi_enter_sleep_state @@ -218,7 +221,6 @@ acpi_status acpi_enter_sleep_state_prep(u8 sleep_state) * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED * ******************************************************************************/ - acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) { u32 PM1Acontrol; @@ -378,7 +380,7 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) return_ACPI_STATUS(AE_OK); } -EXPORT_SYMBOL(acpi_enter_sleep_state); +ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state) /******************************************************************************* * @@ -392,7 +394,6 @@ EXPORT_SYMBOL(acpi_enter_sleep_state); * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED * ******************************************************************************/ - acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void) { u32 in_value; @@ -443,7 +444,7 @@ acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void) return_ACPI_STATUS(AE_OK); } -EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios); +ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios) /******************************************************************************* * @@ -457,7 +458,6 @@ EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios); * Called with interrupts ENABLED. * ******************************************************************************/ - acpi_status acpi_leave_sleep_state(u8 sleep_state) { struct acpi_object_list arg_list; @@ -584,3 +584,5 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state) return_ACPI_STATUS(status); } + +ACPI_EXPORT_SYMBOL(acpi_leave_sleep_state) diff --git a/drivers/acpi/hardware/hwtimer.c b/drivers/acpi/hardware/hwtimer.c index ef7c98e293a..9d53e46bc33 100644 --- a/drivers/acpi/hardware/hwtimer.c +++ b/drivers/acpi/hardware/hwtimer.c @@ -42,7 +42,6 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include #include #define _COMPONENT ACPI_HARDWARE @@ -76,6 +75,8 @@ acpi_status acpi_get_timer_resolution(u32 * resolution) return_ACPI_STATUS(AE_OK); } +ACPI_EXPORT_SYMBOL(acpi_get_timer_resolution) + /****************************************************************************** * * FUNCTION: acpi_get_timer @@ -87,7 +88,6 @@ acpi_status acpi_get_timer_resolution(u32 * resolution) * DESCRIPTION: Obtains current value of ACPI PM Timer (in ticks). * ******************************************************************************/ - acpi_status acpi_get_timer(u32 * ticks) { acpi_status status; @@ -103,7 +103,7 @@ acpi_status acpi_get_timer(u32 * ticks) return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_get_timer); +ACPI_EXPORT_SYMBOL(acpi_get_timer) /****************************************************************************** * @@ -133,7 +133,6 @@ EXPORT_SYMBOL(acpi_get_timer); * 2**32 Ticks / 3,600,000 Ticks/Sec = 1193 sec or 19.88 minutes * ******************************************************************************/ - acpi_status acpi_get_timer_duration(u32 start_ticks, u32 end_ticks, u32 * time_elapsed) { @@ -184,4 +183,4 @@ acpi_get_timer_duration(u32 start_ticks, u32 end_ticks, u32 * time_elapsed) return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_get_timer_duration); +ACPI_EXPORT_SYMBOL(acpi_get_timer_duration) diff --git a/drivers/acpi/namespace/nsaccess.c b/drivers/acpi/namespace/nsaccess.c index 6bdad8bfcf0..d4914fda6a3 100644 --- a/drivers/acpi/namespace/nsaccess.c +++ b/drivers/acpi/namespace/nsaccess.c @@ -347,14 +347,17 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, return_ACPI_STATUS(AE_AML_INTERNAL); } - /* - * This node might not be a actual "scope" node (such as a - * Device/Method, etc.) It could be a Package or other object node. - * Backup up the tree to find the containing scope node. - */ - while (!acpi_ns_opens_scope(prefix_node->type) && - prefix_node->type != ACPI_TYPE_ANY) { - prefix_node = acpi_ns_get_parent_node(prefix_node); + if (!(flags & ACPI_NS_PREFIX_IS_SCOPE)) { + /* + * This node might not be a actual "scope" node (such as a + * Device/Method, etc.) It could be a Package or other object node. + * Backup up the tree to find the containing scope node. + */ + while (!acpi_ns_opens_scope(prefix_node->type) && + prefix_node->type != ACPI_TYPE_ANY) { + prefix_node = + acpi_ns_get_parent_node(prefix_node); + } } } diff --git a/drivers/acpi/namespace/nsalloc.c b/drivers/acpi/namespace/nsalloc.c index cd26cb971a1..acd4b6732ac 100644 --- a/drivers/acpi/namespace/nsalloc.c +++ b/drivers/acpi/namespace/nsalloc.c @@ -68,7 +68,7 @@ struct acpi_namespace_node *acpi_ns_create_node(u32 name) ACPI_FUNCTION_TRACE("ns_create_node"); - node = ACPI_MEM_CALLOCATE(sizeof(struct acpi_namespace_node)); + node = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_namespace_node)); if (!node) { return_PTR(NULL); } @@ -142,7 +142,7 @@ void acpi_ns_delete_node(struct acpi_namespace_node *node) * Detach an object if there is one then delete the node */ acpi_ns_detach_object(node); - ACPI_MEM_FREE(node); + ACPI_FREE(node); return_VOID; } @@ -311,7 +311,7 @@ void acpi_ns_delete_children(struct acpi_namespace_node *parent_node) /* Now we can delete the node */ - ACPI_MEM_FREE(child_node); + ACPI_FREE(child_node); /* And move on to the next child in the list */ diff --git a/drivers/acpi/namespace/nsdumpdv.c b/drivers/acpi/namespace/nsdumpdv.c index aff899a935e..2b311da01ef 100644 --- a/drivers/acpi/namespace/nsdumpdv.c +++ b/drivers/acpi/namespace/nsdumpdv.c @@ -92,7 +92,7 @@ acpi_ns_dump_one_device(acpi_handle obj_handle, info->hardware_id.value, ACPI_FORMAT_UINT64(info->address), info->current_status)); - ACPI_MEM_FREE(info); + ACPI_FREE(info); } return (status); diff --git a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c index 80ef9554563..f5d8e71b82c 100644 --- a/drivers/acpi/namespace/nseval.c +++ b/drivers/acpi/namespace/nseval.c @@ -151,7 +151,7 @@ acpi_ns_evaluate_relative(char *pathname, struct acpi_parameter_info *info) acpi_ut_delete_generic_state(scope_info); cleanup1: - ACPI_MEM_FREE(internal_path); + ACPI_FREE(internal_path); return_ACPI_STATUS(status); } @@ -228,7 +228,7 @@ acpi_ns_evaluate_by_name(char *pathname, struct acpi_parameter_info *info) /* Cleanup */ if (internal_path) { - ACPI_MEM_FREE(internal_path); + ACPI_FREE(internal_path); } return_ACPI_STATUS(status); diff --git a/drivers/acpi/namespace/nsinit.c b/drivers/acpi/namespace/nsinit.c index 9aa337c3388..57b2537643c 100644 --- a/drivers/acpi/namespace/nsinit.c +++ b/drivers/acpi/namespace/nsinit.c @@ -424,7 +424,7 @@ acpi_ns_init_one_device(acpi_handle obj_handle, ACPI_WARNING((AE_INFO, "%s._INI failed: %s", scope_name, acpi_format_exception(status))); - ACPI_MEM_FREE(scope_name); + ACPI_FREE(scope_name); #endif } else { /* Delete any return object (especially if implicit_return is enabled) */ diff --git a/drivers/acpi/namespace/nsnames.c b/drivers/acpi/namespace/nsnames.c index 639f653b4b6..ba812f43897 100644 --- a/drivers/acpi/namespace/nsnames.c +++ b/drivers/acpi/namespace/nsnames.c @@ -48,11 +48,6 @@ #define _COMPONENT ACPI_NAMESPACE ACPI_MODULE_NAME("nsnames") -/* Local prototypes */ -static void -acpi_ns_build_external_path(struct acpi_namespace_node *node, - acpi_size size, char *name_buffer); - /******************************************************************************* * * FUNCTION: acpi_ns_build_external_path @@ -67,8 +62,7 @@ acpi_ns_build_external_path(struct acpi_namespace_node *node, * DESCRIPTION: Generate a full pathaname * ******************************************************************************/ - -static void +void acpi_ns_build_external_path(struct acpi_namespace_node *node, acpi_size size, char *name_buffer) { @@ -146,7 +140,7 @@ char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node) /* Allocate a buffer to be returned to caller */ - name_buffer = ACPI_MEM_CALLOCATE(size); + name_buffer = ACPI_ALLOCATE_ZEROED(size); if (!name_buffer) { ACPI_ERROR((AE_INFO, "Allocation failure")); return_PTR(NULL); diff --git a/drivers/acpi/namespace/nsparse.c b/drivers/acpi/namespace/nsparse.c index 232be430365..64daf3028de 100644 --- a/drivers/acpi/namespace/nsparse.c +++ b/drivers/acpi/namespace/nsparse.c @@ -62,7 +62,7 @@ ACPI_MODULE_NAME("nsparse") * ******************************************************************************/ acpi_status -acpi_ns_one_complete_parse(u8 pass_number, struct acpi_table_desc * table_desc) +acpi_ns_one_complete_parse(u8 pass_number, struct acpi_table_desc *table_desc) { union acpi_parse_object *parse_root; acpi_status status; diff --git a/drivers/acpi/namespace/nssearch.c b/drivers/acpi/namespace/nssearch.c index f73a3d56616..c929f45071c 100644 --- a/drivers/acpi/namespace/nssearch.c +++ b/drivers/acpi/namespace/nssearch.c @@ -103,7 +103,7 @@ acpi_ns_search_node(u32 target_name, &target_name), acpi_ut_get_type_name(type))); - ACPI_MEM_FREE(scope_name); + ACPI_FREE(scope_name); } } #endif diff --git a/drivers/acpi/namespace/nsutils.c b/drivers/acpi/namespace/nsutils.c index 123f454b14a..586014ecf24 100644 --- a/drivers/acpi/namespace/nsutils.c +++ b/drivers/acpi/namespace/nsutils.c @@ -104,7 +104,7 @@ acpi_ns_report_error(char *module_name, } if (name) { - ACPI_MEM_FREE(name); + ACPI_FREE(name); } } @@ -187,7 +187,7 @@ acpi_ns_print_node_pathname(struct acpi_namespace_node *node, char *message) } acpi_os_printf("[%s] (Node %p)", (char *)buffer.pointer, node); - ACPI_MEM_FREE(buffer.pointer); + ACPI_FREE(buffer.pointer); } } @@ -490,7 +490,7 @@ acpi_status acpi_ns_internalize_name(char *external_name, char **converted_name) /* We need a segment to store the internal name */ - internal_name = ACPI_MEM_CALLOCATE(info.length); + internal_name = ACPI_ALLOCATE_ZEROED(info.length); if (!internal_name) { return_ACPI_STATUS(AE_NO_MEMORY); } @@ -500,7 +500,7 @@ acpi_status acpi_ns_internalize_name(char *external_name, char **converted_name) info.internal_name = internal_name; status = acpi_ns_build_internal_name(&info); if (ACPI_FAILURE(status)) { - ACPI_MEM_FREE(internal_name); + ACPI_FREE(internal_name); return_ACPI_STATUS(status); } @@ -632,7 +632,7 @@ acpi_ns_externalize_name(u32 internal_name_length, /* * Build converted_name */ - *converted_name = ACPI_MEM_CALLOCATE(required_length); + *converted_name = ACPI_ALLOCATE_ZEROED(required_length); if (!(*converted_name)) { return_ACPI_STATUS(AE_NO_MEMORY); } @@ -879,7 +879,7 @@ acpi_ns_get_node_by_path(char *pathname, cleanup: if (internal_path) { - ACPI_MEM_FREE(internal_path); + ACPI_FREE(internal_path); } return_ACPI_STATUS(status); } diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c index 71e7769d7da..7cdedc96a40 100644 --- a/drivers/acpi/namespace/nsxfeval.c +++ b/drivers/acpi/namespace/nsxfeval.c @@ -42,8 +42,6 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include - #include #include #include @@ -51,6 +49,7 @@ #define _COMPONENT ACPI_NAMESPACE ACPI_MODULE_NAME("nsxfeval") +#ifdef ACPI_FUTURE_USAGE /******************************************************************************* * * FUNCTION: acpi_evaluate_object_typed @@ -71,12 +70,11 @@ ACPI_MODULE_NAME("nsxfeval") * be valid (non-null) * ******************************************************************************/ -#ifdef ACPI_FUTURE_USAGE acpi_status acpi_evaluate_object_typed(acpi_handle handle, acpi_string pathname, - struct acpi_object_list *external_params, - struct acpi_buffer *return_buffer, + struct acpi_object_list * external_params, + struct acpi_buffer * return_buffer, acpi_object_type return_type) { acpi_status status; @@ -142,6 +140,8 @@ acpi_evaluate_object_typed(acpi_handle handle, return_buffer->length = 0; return_ACPI_STATUS(AE_TYPE); } + +ACPI_EXPORT_SYMBOL(acpi_evaluate_object_typed) #endif /* ACPI_FUTURE_USAGE */ /******************************************************************************* @@ -163,7 +163,6 @@ acpi_evaluate_object_typed(acpi_handle handle, * be valid (non-null) * ******************************************************************************/ - acpi_status acpi_evaluate_object(acpi_handle handle, acpi_string pathname, @@ -193,9 +192,9 @@ acpi_evaluate_object(acpi_handle handle, * Allocate a new parameter block for the internal objects * Add 1 to count to allow for null terminated internal list */ - info.parameters = ACPI_MEM_CALLOCATE(((acpi_size) - external_params->count + - 1) * sizeof(void *)); + info.parameters = ACPI_ALLOCATE_ZEROED(((acpi_size) + external_params->count + + 1) * sizeof(void *)); if (!info.parameters) { return_ACPI_STATUS(AE_NO_MEMORY); } @@ -356,7 +355,7 @@ acpi_evaluate_object(acpi_handle handle, return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_evaluate_object); +ACPI_EXPORT_SYMBOL(acpi_evaluate_object) /******************************************************************************* * @@ -387,7 +386,6 @@ EXPORT_SYMBOL(acpi_evaluate_object); * function, etc. * ******************************************************************************/ - acpi_status acpi_walk_namespace(acpi_object_type type, acpi_handle start_object, @@ -424,7 +422,7 @@ acpi_walk_namespace(acpi_object_type type, return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_walk_namespace); +ACPI_EXPORT_SYMBOL(acpi_walk_namespace) /******************************************************************************* * @@ -439,7 +437,6 @@ EXPORT_SYMBOL(acpi_walk_namespace); * on that. * ******************************************************************************/ - static acpi_status acpi_ns_get_device_callback(acpi_handle obj_handle, u32 nesting_level, @@ -510,11 +507,11 @@ acpi_ns_get_device_callback(acpi_handle obj_handle, sizeof(struct acpi_compatible_id)) != 0) { - ACPI_MEM_FREE(cid); + ACPI_FREE(cid); return (AE_OK); } } - ACPI_MEM_FREE(cid); + ACPI_FREE(cid); } } @@ -592,7 +589,7 @@ acpi_get_devices(char *HID, return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_get_devices); +ACPI_EXPORT_SYMBOL(acpi_get_devices) /******************************************************************************* * @@ -607,7 +604,6 @@ EXPORT_SYMBOL(acpi_get_devices); * DESCRIPTION: Attach arbitrary data and handler to a namespace node. * ******************************************************************************/ - acpi_status acpi_attach_data(acpi_handle obj_handle, acpi_object_handler handler, void *data) @@ -641,6 +637,8 @@ acpi_attach_data(acpi_handle obj_handle, return (status); } +ACPI_EXPORT_SYMBOL(acpi_attach_data) + /******************************************************************************* * * FUNCTION: acpi_detach_data @@ -653,7 +651,6 @@ acpi_attach_data(acpi_handle obj_handle, * DESCRIPTION: Remove data that was previously attached to a node. * ******************************************************************************/ - acpi_status acpi_detach_data(acpi_handle obj_handle, acpi_object_handler handler) { @@ -686,6 +683,8 @@ acpi_detach_data(acpi_handle obj_handle, acpi_object_handler handler) return (status); } +ACPI_EXPORT_SYMBOL(acpi_detach_data) + /******************************************************************************* * * FUNCTION: acpi_get_data @@ -699,7 +698,6 @@ acpi_detach_data(acpi_handle obj_handle, acpi_object_handler handler) * DESCRIPTION: Retrieve data that was previously attached to a namespace node. * ******************************************************************************/ - acpi_status acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data) { @@ -731,3 +729,5 @@ acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data) (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return (status); } + +ACPI_EXPORT_SYMBOL(acpi_get_data) diff --git a/drivers/acpi/namespace/nsxfname.c b/drivers/acpi/namespace/nsxfname.c index 55d26624ab9..1303e2b062b 100644 --- a/drivers/acpi/namespace/nsxfname.c +++ b/drivers/acpi/namespace/nsxfname.c @@ -42,8 +42,6 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include - #include #include @@ -126,7 +124,7 @@ acpi_get_handle(acpi_handle parent, return (status); } -EXPORT_SYMBOL(acpi_get_handle); +ACPI_EXPORT_SYMBOL(acpi_get_handle) /****************************************************************************** * @@ -143,7 +141,6 @@ EXPORT_SYMBOL(acpi_get_handle); * complementary functions. * ******************************************************************************/ - acpi_status acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer * buffer) { @@ -204,7 +201,7 @@ acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer * buffer) return (status); } -EXPORT_SYMBOL(acpi_get_name); +ACPI_EXPORT_SYMBOL(acpi_get_name) /****************************************************************************** * @@ -220,7 +217,6 @@ EXPORT_SYMBOL(acpi_get_name); * control methods (Such as in the case of a device.) * ******************************************************************************/ - acpi_status acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer) { @@ -242,7 +238,7 @@ acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer) return (status); } - info = ACPI_MEM_CALLOCATE(sizeof(struct acpi_device_info)); + info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_device_info)); if (!info) { return (AE_NO_MEMORY); } @@ -346,11 +342,11 @@ acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer) } cleanup: - ACPI_MEM_FREE(info); + ACPI_FREE(info); if (cid_list) { - ACPI_MEM_FREE(cid_list); + ACPI_FREE(cid_list); } return (status); } -EXPORT_SYMBOL(acpi_get_object_info); +ACPI_EXPORT_SYMBOL(acpi_get_object_info) diff --git a/drivers/acpi/namespace/nsxfobj.c b/drivers/acpi/namespace/nsxfobj.c index 9c5f3302799..a163e1d3708 100644 --- a/drivers/acpi/namespace/nsxfobj.c +++ b/drivers/acpi/namespace/nsxfobj.c @@ -42,8 +42,6 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include - #include #include @@ -101,7 +99,7 @@ acpi_status acpi_get_type(acpi_handle handle, acpi_object_type * ret_type) return (status); } -EXPORT_SYMBOL(acpi_get_type); +ACPI_EXPORT_SYMBOL(acpi_get_type) /******************************************************************************* * @@ -116,7 +114,6 @@ EXPORT_SYMBOL(acpi_get_type); * Handle. * ******************************************************************************/ - acpi_status acpi_get_parent(acpi_handle handle, acpi_handle * ret_handle) { struct acpi_namespace_node *node; @@ -162,7 +159,7 @@ acpi_status acpi_get_parent(acpi_handle handle, acpi_handle * ret_handle) return (status); } -EXPORT_SYMBOL(acpi_get_parent); +ACPI_EXPORT_SYMBOL(acpi_get_parent) /******************************************************************************* * @@ -181,7 +178,6 @@ EXPORT_SYMBOL(acpi_get_parent); * Scope is returned. * ******************************************************************************/ - acpi_status acpi_get_next_object(acpi_object_type type, acpi_handle parent, @@ -243,4 +239,4 @@ acpi_get_next_object(acpi_object_type type, return (status); } -EXPORT_SYMBOL(acpi_get_next_object); +ACPI_EXPORT_SYMBOL(acpi_get_next_object) diff --git a/drivers/acpi/parser/pstree.c b/drivers/acpi/parser/pstree.c index 6aa0012643c..0015717ef09 100644 --- a/drivers/acpi/parser/pstree.c +++ b/drivers/acpi/parser/pstree.c @@ -306,5 +306,4 @@ union acpi_parse_object *acpi_ps_get_child(union acpi_parse_object *op) return (child); } #endif - #endif /* ACPI_FUTURE_USAGE */ diff --git a/drivers/acpi/resources/rsinfo.c b/drivers/acpi/resources/rsinfo.c index d9ae64b77bd..9e7ae2f8a1d 100644 --- a/drivers/acpi/resources/rsinfo.c +++ b/drivers/acpi/resources/rsinfo.c @@ -141,6 +141,7 @@ struct acpi_rsdump_info *acpi_gbl_dump_resource_dispatch[] = { acpi_rs_dump_generic_reg, /* ACPI_RESOURCE_TYPE_GENERIC_REGISTER */ }; #endif + #endif /* ACPI_FUTURE_USAGE */ /* * Base sizes for external AML resource descriptors, indexed by internal type. diff --git a/drivers/acpi/resources/rsxface.c b/drivers/acpi/resources/rsxface.c index 2e1bc71acd9..b3feebbd8ca 100644 --- a/drivers/acpi/resources/rsxface.c +++ b/drivers/acpi/resources/rsxface.c @@ -41,8 +41,6 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include - #include #include @@ -118,6 +116,8 @@ acpi_get_irq_routing_table(acpi_handle device_handle, return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL(acpi_get_irq_routing_table) + /******************************************************************************* * * FUNCTION: acpi_get_current_resources @@ -141,7 +141,6 @@ acpi_get_irq_routing_table(acpi_handle device_handle, * the object indicated by the passed device_handle. * ******************************************************************************/ - acpi_status acpi_get_current_resources(acpi_handle device_handle, struct acpi_buffer *ret_buffer) @@ -169,8 +168,9 @@ acpi_get_current_resources(acpi_handle device_handle, return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_get_current_resources); +ACPI_EXPORT_SYMBOL(acpi_get_current_resources) +#ifdef ACPI_FUTURE_USAGE /******************************************************************************* * * FUNCTION: acpi_get_possible_resources @@ -191,8 +191,6 @@ EXPORT_SYMBOL(acpi_get_current_resources); * and the value of ret_buffer is undefined. * ******************************************************************************/ - -#ifdef ACPI_FUTURE_USAGE acpi_status acpi_get_possible_resources(acpi_handle device_handle, struct acpi_buffer *ret_buffer) @@ -220,7 +218,7 @@ acpi_get_possible_resources(acpi_handle device_handle, return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_get_possible_resources); +ACPI_EXPORT_SYMBOL(acpi_get_possible_resources) #endif /* ACPI_FUTURE_USAGE */ /******************************************************************************* @@ -241,7 +239,6 @@ EXPORT_SYMBOL(acpi_get_possible_resources); * each resource in the list. * ******************************************************************************/ - acpi_status acpi_walk_resources(acpi_handle device_handle, char *name, @@ -313,11 +310,11 @@ acpi_walk_resources(acpi_handle device_handle, resource->length); } - ACPI_MEM_FREE(buffer.pointer); + ACPI_FREE(buffer.pointer); return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_walk_resources); +ACPI_EXPORT_SYMBOL(acpi_walk_resources) /******************************************************************************* * @@ -336,7 +333,6 @@ EXPORT_SYMBOL(acpi_walk_resources); * the buffer pointed to by the in_buffer variable. * ******************************************************************************/ - acpi_status acpi_set_current_resources(acpi_handle device_handle, struct acpi_buffer *in_buffer) @@ -356,7 +352,7 @@ acpi_set_current_resources(acpi_handle device_handle, return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_set_current_resources); +ACPI_EXPORT_SYMBOL(acpi_set_current_resources) /****************************************************************************** * @@ -375,7 +371,6 @@ EXPORT_SYMBOL(acpi_set_current_resources); * addresses. * ******************************************************************************/ - acpi_status acpi_resource_to_address64(struct acpi_resource *resource, struct acpi_resource_address64 *out) @@ -417,7 +412,7 @@ acpi_resource_to_address64(struct acpi_resource *resource, return (AE_OK); } -EXPORT_SYMBOL(acpi_resource_to_address64); +ACPI_EXPORT_SYMBOL(acpi_resource_to_address64) /******************************************************************************* * @@ -437,7 +432,6 @@ EXPORT_SYMBOL(acpi_resource_to_address64); * UUID subtype. Returns a struct acpi_resource of type Vendor. * ******************************************************************************/ - acpi_status acpi_get_vendor_resource(acpi_handle device_handle, char *name, @@ -469,6 +463,8 @@ acpi_get_vendor_resource(acpi_handle device_handle, return (info.status); } +ACPI_EXPORT_SYMBOL(acpi_get_vendor_resource) + /******************************************************************************* * * FUNCTION: acpi_rs_match_vendor_resource @@ -480,7 +476,6 @@ acpi_get_vendor_resource(acpi_handle device_handle, * DESCRIPTION: Match a vendor resource via the ACPI 3.0 UUID * ******************************************************************************/ - static acpi_status acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context) { @@ -528,3 +523,5 @@ acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context) info->status = AE_OK; return (AE_CTRL_TERMINATE); } + +ACPI_EXPORT_SYMBOL(acpi_rs_match_vendor_resource) diff --git a/drivers/acpi/tables/tbconvrt.c b/drivers/acpi/tables/tbconvrt.c index 254ebdbb7be..5155b27cf03 100644 --- a/drivers/acpi/tables/tbconvrt.c +++ b/drivers/acpi/tables/tbconvrt.c @@ -41,8 +41,6 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include - #include #include @@ -64,7 +62,7 @@ acpi_tb_convert_fadt2(struct fadt_descriptor_rev2 *local_fadt, struct fadt_descriptor_rev2 *original_fadt); u8 acpi_fadt_is_v1; -EXPORT_SYMBOL(acpi_fadt_is_v1); +ACPI_EXPORT_SYMBOL(acpi_fadt_is_v1) /******************************************************************************* * @@ -133,7 +131,7 @@ acpi_status acpi_tb_convert_to_xsdt(struct acpi_table_desc *table_info) /* Allocate an XSDT */ - new_table = ACPI_MEM_CALLOCATE(table_size); + new_table = ACPI_ALLOCATE_ZEROED(table_size); if (!new_table) { return (AE_NO_MEMORY); } @@ -509,7 +507,7 @@ acpi_status acpi_tb_convert_table_fadt(void) /* Allocate buffer for the ACPI 2.0(+) FADT */ - local_fadt = ACPI_MEM_CALLOCATE(sizeof(struct fadt_descriptor_rev2)); + local_fadt = ACPI_ALLOCATE_ZEROED(sizeof(struct fadt_descriptor_rev2)); if (!local_fadt) { return_ACPI_STATUS(AE_NO_MEMORY); } diff --git a/drivers/acpi/tables/tbget.c b/drivers/acpi/tables/tbget.c index 4615e1afe8d..b7bd20b9a75 100644 --- a/drivers/acpi/tables/tbget.c +++ b/drivers/acpi/tables/tbget.c @@ -330,7 +330,7 @@ acpi_tb_get_this_table(struct acpi_pointer *address, /* Pointer matches processor mode, copy the table to a new buffer */ - full_table = ACPI_MEM_ALLOCATE(header->length); + full_table = ACPI_ALLOCATE(header->length); if (!full_table) { ACPI_ERROR((AE_INFO, "Could not allocate table memory for [%4.4s] length %X", diff --git a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c index ec2cb978b7c..ce57a195577 100644 --- a/drivers/acpi/tables/tbinstal.c +++ b/drivers/acpi/tables/tbinstal.c @@ -248,7 +248,7 @@ acpi_tb_init_table_descriptor(acpi_table_type table_type, /* Allocate a descriptor for this table */ - table_desc = ACPI_MEM_CALLOCATE(sizeof(struct acpi_table_desc)); + table_desc = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_table_desc)); if (!table_desc) { return_ACPI_STATUS(AE_NO_MEMORY); } @@ -275,7 +275,7 @@ acpi_tb_init_table_descriptor(acpi_table_type table_type, * at this location, so return an error. */ if (list_head->next) { - ACPI_MEM_FREE(table_desc); + ACPI_FREE(table_desc); return_ACPI_STATUS(AE_ALREADY_EXISTS); } @@ -472,7 +472,7 @@ void acpi_tb_delete_single_table(struct acpi_table_desc *table_desc) case ACPI_MEM_ALLOCATED: - ACPI_MEM_FREE(table_desc->pointer); + ACPI_FREE(table_desc->pointer); break; case ACPI_MEM_MAPPED: @@ -531,7 +531,7 @@ struct acpi_table_desc *acpi_tb_uninstall_table(struct acpi_table_desc /* Free the table descriptor */ next_desc = table_desc->next; - ACPI_MEM_FREE(table_desc); + ACPI_FREE(table_desc); /* Return pointer to the next descriptor */ diff --git a/drivers/acpi/tables/tbxface.c b/drivers/acpi/tables/tbxface.c index 3e902cdb83e..53c627e401b 100644 --- a/drivers/acpi/tables/tbxface.c +++ b/drivers/acpi/tables/tbxface.c @@ -42,8 +42,6 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include - #include #include #include @@ -123,6 +121,8 @@ acpi_status acpi_load_tables(void) return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL(acpi_load_tables) + #ifdef ACPI_FUTURE_USAGE /******************************************************************************* * @@ -139,7 +139,6 @@ acpi_status acpi_load_tables(void) * is determined that the table is invalid, the call will fail. * ******************************************************************************/ - acpi_status acpi_load_table(struct acpi_table_header *table_ptr) { acpi_status status; @@ -218,6 +217,8 @@ acpi_status acpi_load_table(struct acpi_table_header *table_ptr) return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL(acpi_load_table) + /******************************************************************************* * * FUNCTION: acpi_unload_table @@ -229,7 +230,6 @@ acpi_status acpi_load_table(struct acpi_table_header *table_ptr) * DESCRIPTION: This routine is used to force the unload of a table * ******************************************************************************/ - acpi_status acpi_unload_table(acpi_table_type table_type) { struct acpi_table_desc *table_desc; @@ -263,6 +263,8 @@ acpi_status acpi_unload_table(acpi_table_type table_type) return_ACPI_STATUS(AE_OK); } +ACPI_EXPORT_SYMBOL(acpi_unload_table) + /******************************************************************************* * * FUNCTION: acpi_get_table_header @@ -283,7 +285,6 @@ acpi_status acpi_unload_table(acpi_table_type table_type) * have a standard header and is fixed length. * ******************************************************************************/ - acpi_status acpi_get_table_header(acpi_table_type table_type, u32 instance, struct acpi_table_header *out_table_header) @@ -327,6 +328,7 @@ acpi_get_table_header(acpi_table_type table_type, return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL(acpi_get_table_header) #endif /* ACPI_FUTURE_USAGE */ /******************************************************************************* @@ -351,7 +353,6 @@ acpi_get_table_header(acpi_table_type table_type, * a complete table including the header. * ******************************************************************************/ - acpi_status acpi_get_table(acpi_table_type table_type, u32 instance, struct acpi_buffer *ret_buffer) @@ -420,4 +421,4 @@ acpi_get_table(acpi_table_type table_type, return_ACPI_STATUS(AE_OK); } -EXPORT_SYMBOL(acpi_get_table); +ACPI_EXPORT_SYMBOL(acpi_get_table) diff --git a/drivers/acpi/tables/tbxfroot.c b/drivers/acpi/tables/tbxfroot.c index 7f68b759f15..1b6d8c510e9 100644 --- a/drivers/acpi/tables/tbxfroot.c +++ b/drivers/acpi/tables/tbxfroot.c @@ -41,8 +41,6 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include - #include #include @@ -263,7 +261,7 @@ acpi_get_firmware_table(acpi_string signature, /* Get and validate the RSDT */ - rsdt_info = ACPI_MEM_CALLOCATE(sizeof(struct acpi_table_desc)); + rsdt_info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_table_desc)); if (!rsdt_info) { return_ACPI_STATUS(AE_NO_MEMORY); } @@ -280,13 +278,13 @@ acpi_get_firmware_table(acpi_string signature, /* Allocate a scratch table header and table descriptor */ - header = ACPI_MEM_ALLOCATE(sizeof(struct acpi_table_header)); + header = ACPI_ALLOCATE(sizeof(struct acpi_table_header)); if (!header) { status = AE_NO_MEMORY; goto cleanup; } - table_info = ACPI_MEM_ALLOCATE(sizeof(struct acpi_table_desc)); + table_info = ACPI_ALLOCATE(sizeof(struct acpi_table_desc)); if (!table_info) { status = AE_NO_MEMORY; goto cleanup; @@ -359,23 +357,21 @@ acpi_get_firmware_table(acpi_string signature, acpi_os_unmap_memory(rsdt_info->pointer, (acpi_size) rsdt_info->pointer->length); } - ACPI_MEM_FREE(rsdt_info); + ACPI_FREE(rsdt_info); if (header) { - ACPI_MEM_FREE(header); + ACPI_FREE(header); } if (table_info) { - ACPI_MEM_FREE(table_info); + ACPI_FREE(table_info); } return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_get_firmware_table); +ACPI_EXPORT_SYMBOL(acpi_get_firmware_table) /* TBD: Move to a new file */ - #if ACPI_MACHINE_WIDTH != 16 - /******************************************************************************* * * FUNCTION: acpi_find_root_pointer @@ -388,7 +384,6 @@ EXPORT_SYMBOL(acpi_get_firmware_table); * DESCRIPTION: Find the RSDP * ******************************************************************************/ - acpi_status acpi_find_root_pointer(u32 flags, struct acpi_pointer *rsdp_address) { struct acpi_table_desc table_info; @@ -411,6 +406,8 @@ acpi_status acpi_find_root_pointer(u32 flags, struct acpi_pointer *rsdp_address) return_ACPI_STATUS(AE_OK); } +ACPI_EXPORT_SYMBOL(acpi_find_root_pointer) + /******************************************************************************* * * FUNCTION: acpi_tb_scan_memory_for_rsdp @@ -423,7 +420,6 @@ acpi_status acpi_find_root_pointer(u32 flags, struct acpi_pointer *rsdp_address) * DESCRIPTION: Search a block of memory for the RSDP signature * ******************************************************************************/ - static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length) { acpi_status status; diff --git a/drivers/acpi/utilities/utalloc.c b/drivers/acpi/utilities/utalloc.c index 34de3791d4c..7b35eb84d05 100644 --- a/drivers/acpi/utilities/utalloc.c +++ b/drivers/acpi/utilities/utalloc.c @@ -252,7 +252,7 @@ acpi_ut_initialize_buffer(struct acpi_buffer * buffer, /* Allocate a new buffer with local interface to allow tracking */ - buffer->pointer = ACPI_MEM_CALLOCATE(required_length); + buffer->pointer = ACPI_ALLOCATE_ZEROED(required_length); if (!buffer->pointer) { return (AE_NO_MEMORY); } diff --git a/drivers/acpi/utilities/utcache.c b/drivers/acpi/utilities/utcache.c index 044c890e5b3..5d2f4b2802a 100644 --- a/drivers/acpi/utilities/utcache.c +++ b/drivers/acpi/utilities/utcache.c @@ -125,7 +125,7 @@ acpi_status acpi_os_purge_cache(struct acpi_memory_list * cache) &(((char *)cache-> list_head)[cache-> link_offset]))); - ACPI_MEM_FREE(cache->list_head); + ACPI_FREE(cache->list_head); cache->list_head = next; cache->current_depth--; @@ -194,7 +194,7 @@ acpi_os_release_object(struct acpi_memory_list * cache, void *object) /* If cache is full, just free this object */ if (cache->current_depth >= cache->max_depth) { - ACPI_MEM_FREE(object); + ACPI_FREE(object); ACPI_MEM_TRACKING(cache->total_freed++); } @@ -289,14 +289,14 @@ void *acpi_os_acquire_object(struct acpi_memory_list *cache) ACPI_MEM_TRACKING(cache->total_allocated++); - /* Avoid deadlock with ACPI_MEM_CALLOCATE */ + /* Avoid deadlock with ACPI_ALLOCATE_ZEROED */ status = acpi_ut_release_mutex(ACPI_MTX_CACHES); if (ACPI_FAILURE(status)) { return (NULL); } - object = ACPI_MEM_CALLOCATE(cache->object_size); + object = ACPI_ALLOCATE_ZEROED(cache->object_size); if (!object) { return (NULL); } diff --git a/drivers/acpi/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c index 47875935c3f..371cddc0d57 100644 --- a/drivers/acpi/utilities/utcopy.c +++ b/drivers/acpi/utilities/utcopy.c @@ -472,8 +472,8 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object, case ACPI_TYPE_STRING: internal_object->string.pointer = - ACPI_MEM_CALLOCATE((acpi_size) external_object->string. - length + 1); + ACPI_ALLOCATE_ZEROED((acpi_size) external_object->string. + length + 1); if (!internal_object->string.pointer) { goto error_exit; } @@ -488,7 +488,7 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object, case ACPI_TYPE_BUFFER: internal_object->buffer.pointer = - ACPI_MEM_CALLOCATE(external_object->buffer.length); + ACPI_ALLOCATE_ZEROED(external_object->buffer.length); if (!internal_object->buffer.pointer) { goto error_exit; } @@ -676,7 +676,7 @@ acpi_ut_copy_simple_object(union acpi_operand_object *source_desc, if ((source_desc->buffer.pointer) && (source_desc->buffer.length)) { dest_desc->buffer.pointer = - ACPI_MEM_ALLOCATE(source_desc->buffer.length); + ACPI_ALLOCATE(source_desc->buffer.length); if (!dest_desc->buffer.pointer) { return (AE_NO_MEMORY); } @@ -697,8 +697,8 @@ acpi_ut_copy_simple_object(union acpi_operand_object *source_desc, */ if (source_desc->string.pointer) { dest_desc->string.pointer = - ACPI_MEM_ALLOCATE((acpi_size) source_desc->string. - length + 1); + ACPI_ALLOCATE((acpi_size) source_desc->string. + length + 1); if (!dest_desc->string.pointer) { return (AE_NO_MEMORY); } @@ -805,9 +805,7 @@ acpi_ut_copy_ielement_to_ielement(u8 object_type, /* * Create the object array */ - target_object->package.elements = - ACPI_MEM_CALLOCATE(((acpi_size) source_object->package. - count + 1) * sizeof(void *)); + target_object->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size) source_object->package.count + 1) * sizeof(void *)); if (!target_object->package.elements) { status = AE_NO_MEMORY; goto error_exit; @@ -865,10 +863,10 @@ acpi_ut_copy_ipackage_to_ipackage(union acpi_operand_object *source_obj, /* * Create the object array and walk the source package tree */ - dest_obj->package.elements = ACPI_MEM_CALLOCATE(((acpi_size) - source_obj->package. - count + - 1) * sizeof(void *)); + dest_obj->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size) + source_obj->package. + count + + 1) * sizeof(void *)); if (!dest_obj->package.elements) { ACPI_ERROR((AE_INFO, "Package allocation failure")); return_ACPI_STATUS(AE_NO_MEMORY); diff --git a/drivers/acpi/utilities/utdebug.c b/drivers/acpi/utilities/utdebug.c index 6e92b2a3c0f..a8c350643d5 100644 --- a/drivers/acpi/utilities/utdebug.c +++ b/drivers/acpi/utilities/utdebug.c @@ -41,8 +41,6 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include - #include #define _COMPONENT ACPI_UTILITIES @@ -164,7 +162,7 @@ acpi_ut_debug_print(u32 requested_debug_level, const char *function_name, char *module_name, u32 component_id, char *format, ...) { - u32 thread_id; + acpi_thread_id thread_id; va_list args; /* @@ -179,7 +177,6 @@ acpi_ut_debug_print(u32 requested_debug_level, * Thread tracking and context switch notification */ thread_id = acpi_os_get_thread_id(); - if (thread_id != acpi_gbl_prev_thread_id) { if (ACPI_LV_THREADS & acpi_dbg_level) { acpi_os_printf @@ -208,7 +205,7 @@ acpi_ut_debug_print(u32 requested_debug_level, acpi_os_vprintf(format, args); } -EXPORT_SYMBOL(acpi_ut_debug_print); +ACPI_EXPORT_SYMBOL(acpi_ut_debug_print) /******************************************************************************* * @@ -228,7 +225,6 @@ EXPORT_SYMBOL(acpi_ut_debug_print); * debug_print so that the same macros can be used. * ******************************************************************************/ - void ACPI_INTERNAL_VAR_XFACE acpi_ut_debug_print_raw(u32 requested_debug_level, u32 line_number, @@ -246,7 +242,7 @@ acpi_ut_debug_print_raw(u32 requested_debug_level, acpi_os_vprintf(format, args); } -EXPORT_SYMBOL(acpi_ut_debug_print_raw); +ACPI_EXPORT_SYMBOL(acpi_ut_debug_print_raw) /******************************************************************************* * @@ -263,7 +259,6 @@ EXPORT_SYMBOL(acpi_ut_debug_print_raw); * set in debug_level * ******************************************************************************/ - void acpi_ut_trace(u32 line_number, const char *function_name, char *module_name, u32 component_id) @@ -277,7 +272,7 @@ acpi_ut_trace(u32 line_number, component_id, "%s\n", acpi_gbl_fn_entry_str); } -EXPORT_SYMBOL(acpi_ut_trace); +ACPI_EXPORT_SYMBOL(acpi_ut_trace) /******************************************************************************* * @@ -295,7 +290,6 @@ EXPORT_SYMBOL(acpi_ut_trace); * set in debug_level * ******************************************************************************/ - void acpi_ut_trace_ptr(u32 line_number, const char *function_name, @@ -402,7 +396,7 @@ acpi_ut_exit(u32 line_number, acpi_gbl_nesting_level--; } -EXPORT_SYMBOL(acpi_ut_exit); +ACPI_EXPORT_SYMBOL(acpi_ut_exit) /******************************************************************************* * @@ -420,7 +414,6 @@ EXPORT_SYMBOL(acpi_ut_exit); * set in debug_level. Prints exit status also. * ******************************************************************************/ - void acpi_ut_status_exit(u32 line_number, const char *function_name, @@ -444,7 +437,7 @@ acpi_ut_status_exit(u32 line_number, acpi_gbl_nesting_level--; } -EXPORT_SYMBOL(acpi_ut_status_exit); +ACPI_EXPORT_SYMBOL(acpi_ut_status_exit) /******************************************************************************* * @@ -462,7 +455,6 @@ EXPORT_SYMBOL(acpi_ut_status_exit); * set in debug_level. Prints exit value also. * ******************************************************************************/ - void acpi_ut_value_exit(u32 line_number, const char *function_name, @@ -477,7 +469,7 @@ acpi_ut_value_exit(u32 line_number, acpi_gbl_nesting_level--; } -EXPORT_SYMBOL(acpi_ut_value_exit); +ACPI_EXPORT_SYMBOL(acpi_ut_value_exit) /******************************************************************************* * @@ -495,7 +487,6 @@ EXPORT_SYMBOL(acpi_ut_value_exit); * set in debug_level. Prints exit value also. * ******************************************************************************/ - void acpi_ut_ptr_exit(u32 line_number, const char *function_name, diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c index dbae72121ce..9c6867fcf00 100644 --- a/drivers/acpi/utilities/utdelete.c +++ b/drivers/acpi/utilities/utdelete.c @@ -236,7 +236,7 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object) if (obj_pointer) { ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Deleting Object Subptr %p\n", obj_pointer)); - ACPI_MEM_FREE(obj_pointer); + ACPI_FREE(obj_pointer); } /* Now the object can be safely deleted */ @@ -275,7 +275,7 @@ void acpi_ut_delete_internal_object_list(union acpi_operand_object **obj_list) /* Free the combined parameter pointer list and object array */ - ACPI_MEM_FREE(obj_list); + ACPI_FREE(obj_list); return_VOID; } diff --git a/drivers/acpi/utilities/uteval.c b/drivers/acpi/utilities/uteval.c index 952ffdea93a..68b9eff4b32 100644 --- a/drivers/acpi/utilities/uteval.c +++ b/drivers/acpi/utilities/uteval.c @@ -461,7 +461,7 @@ acpi_ut_execute_CID(struct acpi_namespace_node * device_node, size = (((count - 1) * sizeof(struct acpi_compatible_id)) + sizeof(struct acpi_compatible_id_list)); - cid_list = ACPI_MEM_CALLOCATE((acpi_size) size); + cid_list = ACPI_ALLOCATE_ZEROED((acpi_size) size); if (!cid_list) { return_ACPI_STATUS(AE_NO_MEMORY); } @@ -502,7 +502,7 @@ acpi_ut_execute_CID(struct acpi_namespace_node * device_node, /* Cleanup on error */ if (ACPI_FAILURE(status)) { - ACPI_MEM_FREE(cid_list); + ACPI_FREE(cid_list); } else { *return_cid_list = cid_list; } diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c index 767c5e44a04..5bc8da7acc6 100644 --- a/drivers/acpi/utilities/utglobal.c +++ b/drivers/acpi/utilities/utglobal.c @@ -43,7 +43,6 @@ #define DEFINE_ACPI_GLOBALS -#include #include #include @@ -144,12 +143,10 @@ const char *acpi_format_exception(acpi_status status) /* Debug switch - level and trace mask */ u32 acpi_dbg_level = ACPI_DEBUG_DEFAULT; -EXPORT_SYMBOL(acpi_dbg_level); /* Debug switch - layer (component) mask */ u32 acpi_dbg_layer = ACPI_COMPONENT_DEFAULT | ACPI_ALL_DRIVERS; -EXPORT_SYMBOL(acpi_dbg_layer); u32 acpi_gbl_nesting_level = 0; /* Debugger globals */ @@ -871,3 +868,6 @@ void acpi_ut_init_globals(void) return_VOID; } + +ACPI_EXPORT_SYMBOL(acpi_dbg_level) +ACPI_EXPORT_SYMBOL(acpi_dbg_layer) diff --git a/drivers/acpi/utilities/utinit.c b/drivers/acpi/utilities/utinit.c index ba771b4f39b..40313de6977 100644 --- a/drivers/acpi/utilities/utinit.c +++ b/drivers/acpi/utilities/utinit.c @@ -186,14 +186,14 @@ static void acpi_ut_terminate(void) gpe_block = gpe_xrupt_info->gpe_block_list_head; while (gpe_block) { next_gpe_block = gpe_block->next; - ACPI_MEM_FREE(gpe_block->event_info); - ACPI_MEM_FREE(gpe_block->register_info); - ACPI_MEM_FREE(gpe_block); + ACPI_FREE(gpe_block->event_info); + ACPI_FREE(gpe_block->register_info); + ACPI_FREE(gpe_block); gpe_block = next_gpe_block; } next_gpe_xrupt_info = gpe_xrupt_info->next; - ACPI_MEM_FREE(gpe_xrupt_info); + ACPI_FREE(gpe_xrupt_info); gpe_xrupt_info = next_gpe_xrupt_info; } diff --git a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c index 60f36130663..77268ba8629 100644 --- a/drivers/acpi/utilities/utmisc.c +++ b/drivers/acpi/utilities/utmisc.c @@ -463,7 +463,7 @@ acpi_ut_display_init_pathname(u8 type, } acpi_os_printf("\n"); - ACPI_MEM_FREE(buffer.pointer); + ACPI_FREE(buffer.pointer); } #endif diff --git a/drivers/acpi/utilities/utmutex.c b/drivers/acpi/utilities/utmutex.c index 45a7244df92..0ac6700a45f 100644 --- a/drivers/acpi/utilities/utmutex.c +++ b/drivers/acpi/utilities/utmutex.c @@ -192,7 +192,7 @@ static acpi_status acpi_ut_delete_mutex(acpi_mutex_handle mutex_id) acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id) { acpi_status status; - u32 this_thread_id; + acpi_thread_id this_thread_id; ACPI_FUNCTION_NAME("ut_acquire_mutex"); @@ -275,7 +275,7 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id) acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id) { acpi_status status; - u32 this_thread_id; + acpi_thread_id this_thread_id; ACPI_FUNCTION_NAME("ut_release_mutex"); diff --git a/drivers/acpi/utilities/utobject.c b/drivers/acpi/utilities/utobject.c index b1205a58028..8e3dcbd23f5 100644 --- a/drivers/acpi/utilities/utobject.c +++ b/drivers/acpi/utilities/utobject.c @@ -176,7 +176,7 @@ union acpi_operand_object *acpi_ut_create_buffer_object(acpi_size buffer_size) /* Allocate the actual buffer */ - buffer = ACPI_MEM_CALLOCATE(buffer_size); + buffer = ACPI_ALLOCATE_ZEROED(buffer_size); if (!buffer) { ACPI_ERROR((AE_INFO, "Could not allocate size %X", (u32) buffer_size)); @@ -228,7 +228,7 @@ union acpi_operand_object *acpi_ut_create_string_object(acpi_size string_size) * Allocate the actual string buffer -- (Size + 1) for NULL terminator. * NOTE: Zero-length strings are NULL terminated */ - string = ACPI_MEM_CALLOCATE(string_size + 1); + string = ACPI_ALLOCATE_ZEROED(string_size + 1); if (!string) { ACPI_ERROR((AE_INFO, "Could not allocate size %X", (u32) string_size)); @@ -320,6 +320,7 @@ void *acpi_ut_allocate_object_desc_dbg(char *module_name, } /* Mark the descriptor type */ + memset(object, 0, sizeof(union acpi_operand_object)); ACPI_SET_DESCRIPTOR_TYPE(object, ACPI_DESC_TYPE_OPERAND); diff --git a/drivers/acpi/utilities/utxface.c b/drivers/acpi/utilities/utxface.c index 308a960871b..ac90048a8a5 100644 --- a/drivers/acpi/utilities/utxface.c +++ b/drivers/acpi/utilities/utxface.c @@ -41,8 +41,6 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include - #include #include #include @@ -109,6 +107,8 @@ acpi_status acpi_initialize_subsystem(void) return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL(acpi_initialize_subsystem) + /******************************************************************************* * * FUNCTION: acpi_enable_subsystem @@ -121,7 +121,6 @@ acpi_status acpi_initialize_subsystem(void) * Puts system into ACPI mode if it isn't already. * ******************************************************************************/ - acpi_status acpi_enable_subsystem(u32 flags) { acpi_status status = AE_OK; @@ -229,6 +228,8 @@ acpi_status acpi_enable_subsystem(u32 flags) return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL(acpi_enable_subsystem) + /******************************************************************************* * * FUNCTION: acpi_initialize_objects @@ -241,7 +242,6 @@ acpi_status acpi_enable_subsystem(u32 flags) * objects and executing AML code for Regions, buffers, etc. * ******************************************************************************/ - acpi_status acpi_initialize_objects(u32 flags) { acpi_status status = AE_OK; @@ -305,6 +305,8 @@ acpi_status acpi_initialize_objects(u32 flags) return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL(acpi_initialize_objects) + /******************************************************************************* * * FUNCTION: acpi_terminate @@ -316,7 +318,6 @@ acpi_status acpi_initialize_objects(u32 flags) * DESCRIPTION: Shutdown the ACPI subsystem. Release all resources. * ******************************************************************************/ - acpi_status acpi_terminate(void) { acpi_status status; @@ -348,6 +349,8 @@ acpi_status acpi_terminate(void) return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL(acpi_terminate) + #ifdef ACPI_FUTURE_USAGE /******************************************************************************* * @@ -362,7 +365,6 @@ acpi_status acpi_terminate(void) * initialized successfully. * ******************************************************************************/ - acpi_status acpi_subsystem_status(void) { @@ -373,6 +375,8 @@ acpi_status acpi_subsystem_status(void) } } +ACPI_EXPORT_SYMBOL(acpi_subsystem_status) + /******************************************************************************* * * FUNCTION: acpi_get_system_info @@ -390,7 +394,6 @@ acpi_status acpi_subsystem_status(void) * and the value of out_buffer is undefined. * ******************************************************************************/ - acpi_status acpi_get_system_info(struct acpi_buffer * out_buffer) { struct acpi_system_info *info_ptr; @@ -456,7 +459,7 @@ acpi_status acpi_get_system_info(struct acpi_buffer * out_buffer) return_ACPI_STATUS(AE_OK); } -EXPORT_SYMBOL(acpi_get_system_info); +ACPI_EXPORT_SYMBOL(acpi_get_system_info) /***************************************************************************** * @@ -472,7 +475,6 @@ EXPORT_SYMBOL(acpi_get_system_info); * TBD: When a second function is added, must save the Function also. * ****************************************************************************/ - acpi_status acpi_install_initialization_handler(acpi_init_handler handler, u32 function) { @@ -489,6 +491,7 @@ acpi_install_initialization_handler(acpi_init_handler handler, u32 function) return AE_OK; } +ACPI_EXPORT_SYMBOL(acpi_install_initialization_handler) #endif /* ACPI_FUTURE_USAGE */ /***************************************************************************** @@ -502,7 +505,6 @@ acpi_install_initialization_handler(acpi_init_handler handler, u32 function) * DESCRIPTION: Empty all caches (delete the cached objects) * ****************************************************************************/ - acpi_status acpi_purge_cached_objects(void) { ACPI_FUNCTION_TRACE("acpi_purge_cached_objects"); @@ -513,3 +515,5 @@ acpi_status acpi_purge_cached_objects(void) (void)acpi_os_purge_cache(acpi_gbl_ps_node_ext_cache); return_ACPI_STATUS(AE_OK); } + +ACPI_EXPORT_SYMBOL(acpi_purge_cached_objects) diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h index 78850225622..ebe793fc137 100644 --- a/include/acpi/acconfig.h +++ b/include/acpi/acconfig.h @@ -63,7 +63,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20060217 +#define ACPI_CA_VERSION 0x20060310 /* * OS name, used for the _OS object. The _OS object is essentially obsolete, @@ -102,9 +102,9 @@ #define ACPI_MAX_SEMAPHORE_COUNT 256 -/* Max reference count (for debug only) */ +/* Maximum object reference count (detects object deletion issues) */ -#define ACPI_MAX_REFERENCE_COUNT 0x400 +#define ACPI_MAX_REFERENCE_COUNT 0x800 /* Size of cached memory mapping for system memory operation region */ diff --git a/include/acpi/acdisasm.h b/include/acpi/acdisasm.h index 0727c132bd3..f004461a775 100644 --- a/include/acpi/acdisasm.h +++ b/include/acpi/acdisasm.h @@ -50,6 +50,7 @@ #define BLOCK_PAREN 1 #define BLOCK_BRACE 2 #define BLOCK_COMMA_LIST 4 +#define ACPI_DEFAULT_RESNAME *(u32 *) "__RD" struct acpi_external_list { char *path; @@ -78,6 +79,11 @@ typedef acpi_status(*asl_walk_callback) (union acpi_parse_object * op, u32 level, void *context); +struct acpi_resource_tag { + u32 bit_index; + char *tag; +}; + /* * dmwalk */ @@ -85,6 +91,11 @@ void acpi_dm_disassemble(struct acpi_walk_state *walk_state, union acpi_parse_object *origin, u32 num_opcodes); +void +acpi_dm_walk_parse_tree(union acpi_parse_object *op, + asl_walk_callback descending_callback, + asl_walk_callback ascending_callback, void *context); + /* * dmopcode */ @@ -167,6 +178,7 @@ void acpi_dm_dump_integer64(u64 value, char *name); void acpi_dm_resource_template(struct acpi_op_walk_info *info, + union acpi_parse_object *op, u8 * byte_data, u32 byte_count); u8 acpi_dm_is_resource_template(union acpi_parse_object *op); @@ -177,6 +189,8 @@ void acpi_dm_bit_list(u16 mask); void acpi_dm_decode_attribute(u8 attribute); +void acpi_dm_descriptor_name(void); + /* * dmresrcl */ @@ -251,4 +265,13 @@ acpi_dm_vendor_small_descriptor(union aml_resource *resource, */ void acpi_dm_add_to_external_list(char *path); +/* + * dmrestag + */ +void acpi_dm_find_resources(union acpi_parse_object *root); + +void +acpi_dm_check_resource_reference(union acpi_parse_object *op, + struct acpi_walk_state *walk_state); + #endif /* __ACDISASM_H__ */ diff --git a/include/acpi/aclocal.h b/include/acpi/aclocal.h index 8361820d297..94fbf96ed3d 100644 --- a/include/acpi/aclocal.h +++ b/include/acpi/aclocal.h @@ -129,7 +129,7 @@ typedef u8 acpi_owner_id; struct acpi_mutex_info { acpi_mutex mutex; u32 use_count; - u32 thread_id; + acpi_thread_id thread_id; }; /* Lock flag parameter for various interfaces */ @@ -181,9 +181,9 @@ struct acpi_namespace_node { u8 owner_id; /* Who created this node */ u8 flags; - /* Fields used by the ASL compiler only */ + /* Fields used by the ASL compiler and disassembler only */ -#ifdef ACPI_ASL_COMPILER +#ifdef ACPI_LARGE_NAMESPACE_NODE u32 value; union acpi_parse_object *op; #endif @@ -479,7 +479,7 @@ struct acpi_pscope_state { struct acpi_thread_state { ACPI_STATE_COMMON struct acpi_walk_state *walk_state_list; /* Head of list of walk_states for this thread */ union acpi_operand_object *acquired_mutex_list; /* List of all currently acquired mutexes */ - u32 thread_id; /* Running thread ID */ + acpi_thread_id thread_id; /* Running thread ID */ u8 current_sync_level; /* Mutex Sync (nested acquire) level */ }; diff --git a/include/acpi/acmacros.h b/include/acpi/acmacros.h index dd5644dbe94..c8aa73fc6dd 100644 --- a/include/acpi/acmacros.h +++ b/include/acpi/acmacros.h @@ -713,18 +713,18 @@ /* Memory allocation */ -#define ACPI_MEM_ALLOCATE(a) acpi_ut_allocate((acpi_size)(a),_COMPONENT,_acpi_module_name,__LINE__) -#define ACPI_MEM_CALLOCATE(a) acpi_ut_callocate((acpi_size)(a), _COMPONENT,_acpi_module_name,__LINE__) -#define ACPI_MEM_FREE(a) acpi_os_free(a) +#define ACPI_ALLOCATE(a) acpi_ut_allocate((acpi_size)(a),_COMPONENT,_acpi_module_name,__LINE__) +#define ACPI_ALLOCATE_ZEROED(a) acpi_ut_callocate((acpi_size)(a), _COMPONENT,_acpi_module_name,__LINE__) +#define ACPI_FREE(a) acpi_os_free(a) #define ACPI_MEM_TRACKING(a) #else /* Memory allocation */ -#define ACPI_MEM_ALLOCATE(a) acpi_ut_allocate_and_track((acpi_size)(a),_COMPONENT,_acpi_module_name,__LINE__) -#define ACPI_MEM_CALLOCATE(a) acpi_ut_callocate_and_track((acpi_size)(a), _COMPONENT,_acpi_module_name,__LINE__) -#define ACPI_MEM_FREE(a) acpi_ut_free_and_track(a,_COMPONENT,_acpi_module_name,__LINE__) +#define ACPI_ALLOCATE(a) acpi_ut_allocate_and_track((acpi_size)(a),_COMPONENT,_acpi_module_name,__LINE__) +#define ACPI_ALLOCATE_ZEROED(a) acpi_ut_callocate_and_track((acpi_size)(a), _COMPONENT,_acpi_module_name,__LINE__) +#define ACPI_FREE(a) acpi_ut_free_and_track(a,_COMPONENT,_acpi_module_name,__LINE__) #define ACPI_MEM_TRACKING(a) a #endif /* ACPI_DBG_TRACK_ALLOCATIONS */ diff --git a/include/acpi/acnamesp.h b/include/acpi/acnamesp.h index b667a804fc8..132d64af24f 100644 --- a/include/acpi/acnamesp.h +++ b/include/acpi/acnamesp.h @@ -63,6 +63,7 @@ #define ACPI_NS_DONT_OPEN_SCOPE 0x02 #define ACPI_NS_NO_PEER_SEARCH 0x04 #define ACPI_NS_ERROR_IF_FOUND 0x08 +#define ACPI_NS_PREFIX_IS_SCOPE 0x10 #define ACPI_NS_WALK_UNLOCK TRUE #define ACPI_NS_WALK_NO_UNLOCK FALSE @@ -184,6 +185,10 @@ acpi_ns_evaluate_relative(char *pathname, struct acpi_parameter_info *info); */ u32 acpi_ns_opens_scope(acpi_object_type type); +void +acpi_ns_build_external_path(struct acpi_namespace_node *node, + acpi_size size, char *name_buffer); + char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node); char *acpi_ns_name_of_current_scope(struct acpi_walk_state *walk_state); diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h index 970e9a6372c..91c3cdff28b 100644 --- a/include/acpi/acpiosxf.h +++ b/include/acpi/acpiosxf.h @@ -161,7 +161,7 @@ acpi_os_remove_interrupt_handler(u32 gsi, acpi_osd_handler service_routine); /* * Threads and Scheduling */ -u32 acpi_os_get_thread_id(void); +acpi_thread_id acpi_os_get_thread_id(void); acpi_status acpi_os_queue_for_execution(u32 priority, diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index 95c3c8b6d61..520f315dd53 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -288,6 +288,21 @@ typedef acpi_native_uint acpi_size; #define ACPI_UNUSED_VAR #endif +/* + * All ACPICA functions that are available to the rest of the kernel are + * tagged with this macro which can be defined as appropriate for the host. + */ +#ifndef ACPI_EXPORT_SYMBOL +#define ACPI_EXPORT_SYMBOL(symbol) +#endif + +/* + * thread_id is returned by acpi_os_get_thread_id. + */ +#ifndef acpi_thread_id +#define acpi_thread_id acpi_native_uint +#endif + /******************************************************************************* * * Independent types diff --git a/include/acpi/amlresrc.h b/include/acpi/amlresrc.h index fb4735315ad..e5b42eb3819 100644 --- a/include/acpi/amlresrc.h +++ b/include/acpi/amlresrc.h @@ -45,36 +45,36 @@ #ifndef __AMLRESRC_H #define __AMLRESRC_H -#define ASL_RESNAME_ADDRESS "_ADR" -#define ASL_RESNAME_ALIGNMENT "_ALN" -#define ASL_RESNAME_ADDRESSSPACE "_ASI" -#define ASL_RESNAME_ACCESSSIZE "_ASZ" -#define ASL_RESNAME_TYPESPECIFICATTRIBUTES "_ATT" -#define ASL_RESNAME_BASEADDRESS "_BAS" -#define ASL_RESNAME_BUSMASTER "_BM_" /* Master(1), Slave(0) */ -#define ASL_RESNAME_DECODE "_DEC" -#define ASL_RESNAME_DMA "_DMA" -#define ASL_RESNAME_DMATYPE "_TYP" /* Compatible(0), A(1), B(2), F(3) */ -#define ASL_RESNAME_GRANULARITY "_GRA" -#define ASL_RESNAME_INTERRUPT "_INT" -#define ASL_RESNAME_INTERRUPTLEVEL "_LL_" /* active_lo(1), active_hi(0) */ -#define ASL_RESNAME_INTERRUPTSHARE "_SHR" /* Shareable(1), no_share(0) */ -#define ASL_RESNAME_INTERRUPTTYPE "_HE_" /* Edge(1), Level(0) */ -#define ASL_RESNAME_LENGTH "_LEN" -#define ASL_RESNAME_MEMATTRIBUTES "_MTP" /* Memory(0), Reserved(1), ACPI(2), NVS(3) */ -#define ASL_RESNAME_MEMTYPE "_MEM" /* non_cache(0), Cacheable(1) Cache+combine(2), Cache+prefetch(3) */ -#define ASL_RESNAME_MAXADDR "_MAX" -#define ASL_RESNAME_MINADDR "_MIN" -#define ASL_RESNAME_MAXTYPE "_MAF" -#define ASL_RESNAME_MINTYPE "_MIF" -#define ASL_RESNAME_REGISTERBITOFFSET "_RBO" -#define ASL_RESNAME_REGISTERBITWIDTH "_RBW" -#define ASL_RESNAME_RANGETYPE "_RNG" -#define ASL_RESNAME_READWRITETYPE "_RW_" /* read_only(0), Writeable (1) */ -#define ASL_RESNAME_TRANSLATION "_TRA" -#define ASL_RESNAME_TRANSTYPE "_TRS" /* Sparse(1), Dense(0) */ -#define ASL_RESNAME_TYPE "_TTP" /* Translation(1), Static (0) */ -#define ASL_RESNAME_XFERTYPE "_SIz" /* 8(0), 8_and16(1), 16(2) */ +#define ACPI_RESTAG_ADDRESS "_ADR" +#define ACPI_RESTAG_ALIGNMENT "_ALN" +#define ACPI_RESTAG_ADDRESSSPACE "_ASI" +#define ACPI_RESTAG_ACCESSSIZE "_ASZ" +#define ACPI_RESTAG_TYPESPECIFICATTRIBUTES "_ATT" +#define ACPI_RESTAG_BASEADDRESS "_BAS" +#define ACPI_RESTAG_BUSMASTER "_BM_" /* Master(1), Slave(0) */ +#define ACPI_RESTAG_DECODE "_DEC" +#define ACPI_RESTAG_DMA "_DMA" +#define ACPI_RESTAG_DMATYPE "_TYP" /* Compatible(0), A(1), B(2), F(3) */ +#define ACPI_RESTAG_GRANULARITY "_GRA" +#define ACPI_RESTAG_INTERRUPT "_INT" +#define ACPI_RESTAG_INTERRUPTLEVEL "_LL_" /* active_lo(1), active_hi(0) */ +#define ACPI_RESTAG_INTERRUPTSHARE "_SHR" /* Shareable(1), no_share(0) */ +#define ACPI_RESTAG_INTERRUPTTYPE "_HE_" /* Edge(1), Level(0) */ +#define ACPI_RESTAG_LENGTH "_LEN" +#define ACPI_RESTAG_MEMATTRIBUTES "_MTP" /* Memory(0), Reserved(1), ACPI(2), NVS(3) */ +#define ACPI_RESTAG_MEMTYPE "_MEM" /* non_cache(0), Cacheable(1) Cache+combine(2), Cache+prefetch(3) */ +#define ACPI_RESTAG_MAXADDR "_MAX" +#define ACPI_RESTAG_MINADDR "_MIN" +#define ACPI_RESTAG_MAXTYPE "_MAF" +#define ACPI_RESTAG_MINTYPE "_MIF" +#define ACPI_RESTAG_REGISTERBITOFFSET "_RBO" +#define ACPI_RESTAG_REGISTERBITWIDTH "_RBW" +#define ACPI_RESTAG_RANGETYPE "_RNG" +#define ACPI_RESTAG_READWRITETYPE "_RW_" /* read_only(0), Writeable (1) */ +#define ACPI_RESTAG_TRANSLATION "_TRA" +#define ACPI_RESTAG_TRANSTYPE "_TRS" /* Sparse(1), Dense(0) */ +#define ACPI_RESTAG_TYPE "_TTP" /* Translation(1), Static (0) */ +#define ACPI_RESTAG_XFERTYPE "_SIz" /* 8(0), 8_and16(1), 16(2) */ /* Default sizes for "small" resource descriptors */ @@ -266,6 +266,7 @@ struct aml_resource_generic_register { union aml_resource { /* Descriptor headers */ + u8 descriptor_type; struct aml_resource_small_header small_header; struct aml_resource_large_header large_header; diff --git a/include/acpi/platform/acenv.h b/include/acpi/platform/acenv.h index 223ec646710..d5a7f566c01 100644 --- a/include/acpi/platform/acenv.h +++ b/include/acpi/platform/acenv.h @@ -59,6 +59,7 @@ #define ACPI_APPLICATION #define ACPI_DISASSEMBLER #define ACPI_NO_METHOD_EXECUTION +#define ACPI_LARGE_NAMESPACE_NODE #endif #ifdef ACPI_EXEC_APP @@ -76,6 +77,7 @@ #define ACPI_APPLICATION #define ACPI_DISASSEMBLER #define ACPI_CONSTANT_EVAL_ONLY +#define ACPI_LARGE_NAMESPACE_NODE #endif #ifdef ACPI_APPLICATION @@ -271,8 +273,8 @@ typedef char *va_list; /* * Storage alignment properties */ -#define _AUPBND (sizeof (acpi_native_uint) - 1) -#define _ADNBND (sizeof (acpi_native_uint) - 1) +#define _AUPBND (sizeof (acpi_native_int) - 1) +#define _ADNBND (sizeof (acpi_native_int) - 1) /* * Variable argument list macro definitions diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h index 2e6d54569ee..2f5bb5bd76b 100644 --- a/include/acpi/platform/aclinux.h +++ b/include/acpi/platform/aclinux.h @@ -52,27 +52,22 @@ #include #include #include +#include #include #include #include #include #include +#include -#define strtoul simple_strtoul - -#define ACPI_MACHINE_WIDTH BITS_PER_LONG +/* Host-dependent types and defines */ -/* Type(s) for the OSL */ - -#ifdef ACPI_USE_LOCAL_CACHE -#define acpi_cache_t struct acpi_memory_list -#else -#include -#define acpi_cache_t kmem_cache_t -#endif +#define ACPI_MACHINE_WIDTH BITS_PER_LONG +#define acpi_cache_t kmem_cache_t +#define ACPI_EXPORT_SYMBOL(symbol) EXPORT_SYMBOL(symbol); +#define strtoul simple_strtoul /* Full namespace pathname length limit - arbitrary */ - #define ACPI_PATHNAME_MAX 256 #else /* !__KERNEL__ */ -- cgit v1.2.3 From ec7381d6bfd3e7b8d2880dd5e9d03b131b0603f6 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Sat, 1 Apr 2006 05:12:23 -0500 Subject: ACPI: inline trivial acpi_os_get_thread_id() acpi_os_get_thread_id() is used only for debugging code that is not enabled on Linux, so stub it out. Signed-off-by: Len Brown --- drivers/acpi/osl.c | 8 -------- include/acpi/platform/aclinux.h | 4 ++++ 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 13b5fd5854a..56d97f1d108 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -896,14 +896,6 @@ u8 acpi_os_writable(void *ptr, acpi_size len) } #endif -u32 acpi_os_get_thread_id(void) -{ - if (!in_atomic()) - return current->pid; - - return 0; -} - acpi_status acpi_os_signal(u32 function, void *info) { switch (function) { diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h index 2f5bb5bd76b..b5655a665ba 100644 --- a/include/acpi/platform/aclinux.h +++ b/include/acpi/platform/aclinux.h @@ -99,4 +99,8 @@ #define acpi_cpu_flags unsigned long +#define acpi_thread_id u32 + +static inline acpi_thread_id acpi_os_get_thread_id(void) { return 0; } + #endif /* __ACLINUX_H__ */ -- cgit v1.2.3 From 5bbc53f4cfd28bf1d0e476ed23bc3a094eff718a Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 1 Apr 2006 01:38:17 +0900 Subject: [PATCH] libata: fix ata_set_mode() return value Make ata_set_mode() return correct error value when ata_dev_set_mode() fails. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index e63c1ff1e10..8def7a5e436 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1856,7 +1856,8 @@ static void ata_set_mode(struct ata_port *ap) if (!ata_dev_present(dev)) continue; - if (ata_dev_set_mode(ap, dev)) + rc = ata_dev_set_mode(ap, dev); + if (rc) goto err_out; } -- cgit v1.2.3 From 96072e699be08af8e7c33c56759582ea89088a02 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 1 Apr 2006 01:38:17 +0900 Subject: [PATCH] libata: make ata_bus_probe() return negative errno on failure ata_bus_probe() uses unsigned int rc to receive negative errno and returns the converted unsigned int value. Convert temporary variables to int and make ata_bus_probe() return negative errno on failure. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 8def7a5e436..c7ba523fb1e 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1349,13 +1349,13 @@ err_out_nosup: * PCI/etc. bus probe sem. * * RETURNS: - * Zero on success, non-zero on error. + * Zero on success, negative errno otherwise. */ static int ata_bus_probe(struct ata_port *ap) { unsigned int classes[ATA_MAX_DEVICES]; - unsigned int i, rc, found = 0; + int i, rc, found = 0; ata_port_probe(ap); @@ -1421,7 +1421,7 @@ static int ata_bus_probe(struct ata_port *ap) err_out_disable: ap->ops->port_disable(ap); - return -1; + return -ENODEV; } /** -- cgit v1.2.3 From 4c360c81a6f8d4253f7fc2e69852305676fdfa72 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 1 Apr 2006 01:38:17 +0900 Subject: [PATCH] libata: separate out ata_spd_string() Separate out ata_spd_string() from sata_print_link_status(). This will be used by SATA spd configuration routines. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index c7ba523fb1e..6a336babf88 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -397,6 +397,18 @@ static const char *ata_mode_string(unsigned int xfer_mask) return ""; } +static const char *sata_spd_string(unsigned int spd) +{ + static const char * const spd_str[] = { + "1.5 Gbps", + "3.0 Gbps", + }; + + if (spd == 0 || (spd - 1) >= ARRAY_SIZE(spd_str)) + return ""; + return spd_str[spd - 1]; +} + static void ata_dev_disable(struct ata_port *ap, struct ata_device *dev) { if (ata_dev_present(dev)) { @@ -1452,7 +1464,6 @@ void ata_port_probe(struct ata_port *ap) static void sata_print_link_status(struct ata_port *ap) { u32 sstatus, tmp; - const char *speed; if (!ap->ops->scr_read) return; @@ -1461,14 +1472,8 @@ static void sata_print_link_status(struct ata_port *ap) if (sata_dev_present(ap)) { tmp = (sstatus >> 4) & 0xf; - if (tmp & (1 << 0)) - speed = "1.5"; - else if (tmp & (1 << 1)) - speed = "3.0"; - else - speed = ""; - printk(KERN_INFO "ata%u: SATA link up %s Gbps (SStatus %X)\n", - ap->id, speed, sstatus); + printk(KERN_INFO "ata%u: SATA link up %s (SStatus %X)\n", + ap->id, sata_spd_string(tmp), sstatus); } else { printk(KERN_INFO "ata%u: SATA link down (SStatus %X)\n", ap->id, sstatus); -- cgit v1.2.3 From 9974e7cc6c8b8ea796c92cdf28db93e4579a4000 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 1 Apr 2006 01:38:17 +0900 Subject: [PATCH] libata: convert do_probe_reset() to ata_do_reset() Make do_probe_reset() generic by pushing classification check into ata_drive_probe_reset() and rename it to ata_do_reset(). This will be used by EH reset. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 6a336babf88..559abe4ea4e 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2371,16 +2371,16 @@ int ata_std_probe_reset(struct ata_port *ap, unsigned int *classes) ata_std_postreset, classes); } -static int do_probe_reset(struct ata_port *ap, ata_reset_fn_t reset, - ata_postreset_fn_t postreset, - unsigned int *classes) +static int ata_do_reset(struct ata_port *ap, + ata_reset_fn_t reset, ata_postreset_fn_t postreset, + int verbose, unsigned int *classes) { int i, rc; for (i = 0; i < ATA_MAX_DEVICES; i++) classes[i] = ATA_DEV_UNKNOWN; - rc = reset(ap, 0, classes); + rc = reset(ap, verbose, classes); if (rc) return rc; @@ -2400,7 +2400,7 @@ static int do_probe_reset(struct ata_port *ap, ata_reset_fn_t reset, if (postreset) postreset(ap, classes); - return classes[0] != ATA_DEV_UNKNOWN ? 0 : -ENODEV; + return 0; } /** @@ -2445,21 +2445,24 @@ int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, probeinit(ap); if (softreset) { - rc = do_probe_reset(ap, softreset, postreset, classes); - if (rc == 0) - return 0; + rc = ata_do_reset(ap, softreset, postreset, 0, classes); + if (rc == 0 && classes[0] != ATA_DEV_UNKNOWN) + goto done; } if (!hardreset) - return rc; + goto done; - rc = do_probe_reset(ap, hardreset, postreset, classes); - if (rc == 0 || rc != -ENODEV) - return rc; + rc = ata_do_reset(ap, hardreset, postreset, 0, classes); + if (rc || classes[0] != ATA_DEV_UNKNOWN) + goto done; if (softreset) - rc = do_probe_reset(ap, softreset, postreset, classes); + rc = ata_do_reset(ap, softreset, postreset, 0, classes); + done: + if (rc == 0 && classes[0] == ATA_DEV_UNKNOWN) + rc = -ENODEV; return rc; } -- cgit v1.2.3 From e1211e3fa7fd05ff0d4f597fd37e40de8acc6784 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 1 Apr 2006 01:38:18 +0900 Subject: [PATCH] libata: implement ata_dev_enabled and disabled() This patch renames ata_dev_present() to ata_dev_enabled() and adds ata_dev_disabled(). This is to discern the state where a device is present but disabled from not-present state. This disctinction is necessary when configuring transfer mode because device selection timing must not be violated even if a device fails to configure. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 24 ++++++++++++------------ drivers/scsi/libata-scsi.c | 4 ++-- drivers/scsi/sata_mv.c | 2 +- drivers/scsi/sata_sil.c | 2 +- include/linux/libata.h | 16 +++++++++++++--- 5 files changed, 29 insertions(+), 19 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 559abe4ea4e..c10c550da38 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -411,7 +411,7 @@ static const char *sata_spd_string(unsigned int spd) static void ata_dev_disable(struct ata_port *ap, struct ata_device *dev) { - if (ata_dev_present(dev)) { + if (ata_dev_enabled(dev)) { printk(KERN_WARNING "ata%u: dev %u disabled\n", ap->id, dev->devno); dev->class++; @@ -1222,7 +1222,7 @@ static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev, unsigned int xfer_mask; int i, rc; - if (!ata_dev_present(dev)) { + if (!ata_dev_enabled(dev)) { DPRINTK("ENTER/EXIT (host %u, dev %u) -- nodev\n", ap->id, dev->devno); return 0; @@ -1401,7 +1401,7 @@ static int ata_bus_probe(struct ata_port *ap) dev->class = classes[i]; - if (!ata_dev_present(dev)) + if (!ata_dev_enabled(dev)) continue; WARN_ON(dev->id != NULL); @@ -1565,7 +1565,7 @@ void sata_phy_reset(struct ata_port *ap) struct ata_device *ata_dev_pair(struct ata_port *ap, struct ata_device *adev) { struct ata_device *pair = &ap->device[1 - adev->devno]; - if (!ata_dev_present(pair)) + if (!ata_dev_enabled(pair)) return NULL; return pair; } @@ -1778,7 +1778,7 @@ static int ata_host_set_pio(struct ata_port *ap) for (i = 0; i < ATA_MAX_DEVICES; i++) { struct ata_device *dev = &ap->device[i]; - if (!ata_dev_present(dev)) + if (!ata_dev_enabled(dev)) continue; if (!dev->pio_mode) { @@ -1802,7 +1802,7 @@ static void ata_host_set_dma(struct ata_port *ap) for (i = 0; i < ATA_MAX_DEVICES; i++) { struct ata_device *dev = &ap->device[i]; - if (!ata_dev_present(dev) || !dev->dma_mode) + if (!ata_dev_enabled(dev) || !dev->dma_mode) continue; dev->xfer_mode = dev->dma_mode; @@ -1830,7 +1830,7 @@ static void ata_set_mode(struct ata_port *ap) struct ata_device *dev = &ap->device[i]; unsigned int pio_mask, dma_mask; - if (!ata_dev_present(dev)) + if (!ata_dev_enabled(dev)) continue; ata_dev_xfermask(ap, dev); @@ -1858,7 +1858,7 @@ static void ata_set_mode(struct ata_port *ap) for (i = 0; i < ATA_MAX_DEVICES; i++) { struct ata_device *dev = &ap->device[i]; - if (!ata_dev_present(dev)) + if (!ata_dev_enabled(dev)) continue; rc = ata_dev_set_mode(ap, dev); @@ -2550,7 +2550,7 @@ int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev, u16 *id; int rc; - if (!ata_dev_present(dev)) + if (!ata_dev_enabled(dev)) return -ENODEV; class = dev->class; @@ -2679,7 +2679,7 @@ static void ata_dev_xfermask(struct ata_port *ap, struct ata_device *dev) /* FIXME: Use port-wide xfermask for now */ for (i = 0; i < ATA_MAX_DEVICES; i++) { struct ata_device *d = &ap->device[i]; - if (!ata_dev_present(d)) + if (!ata_dev_enabled(d)) continue; xfer_mask &= ata_pack_xfermask(d->pio_mask, d->mwdma_mask, d->udma_mask); @@ -4299,7 +4299,7 @@ int ata_device_resume(struct ata_port *ap, struct ata_device *dev) ap->flags &= ~ATA_FLAG_SUSPENDED; ata_set_mode(ap); } - if (!ata_dev_present(dev)) + if (!ata_dev_enabled(dev)) return 0; if (dev->class == ATA_DEV_ATA) ata_start_drive(ap, dev); @@ -4317,7 +4317,7 @@ int ata_device_resume(struct ata_port *ap, struct ata_device *dev) */ int ata_device_suspend(struct ata_port *ap, struct ata_device *dev, pm_message_t state) { - if (!ata_dev_present(dev)) + if (!ata_dev_enabled(dev)) return 0; if (dev->class == ATA_DEV_ATA) ata_flush_cache(ap, dev); diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 53f5b0d9161..c1a4b29a9ae 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -2349,7 +2349,7 @@ ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev) (scsidev->lun != 0))) return NULL; - if (unlikely(!ata_dev_present(dev))) + if (unlikely(!ata_dev_enabled(dev))) return NULL; if (!atapi_enabled || (ap->flags & ATA_FLAG_NO_ATAPI)) { @@ -2743,7 +2743,7 @@ void ata_scsi_scan_host(struct ata_port *ap) for (i = 0; i < ATA_MAX_DEVICES; i++) { dev = &ap->device[i]; - if (ata_dev_present(dev)) + if (ata_dev_enabled(dev)) scsi_scan_target(&ap->host->shost_gendev, 0, i, 0, 0); } } diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index fa901fd6508..0f7d334aadc 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -1991,7 +1991,7 @@ comreset_retry: tf.nsect = readb((void __iomem *) ap->ioaddr.nsect_addr); dev->class = ata_dev_classify(&tf); - if (!ata_dev_present(dev)) { + if (!ata_dev_enabled(dev)) { VPRINTK("Port disabled post-sig: No device present.\n"); ata_port_disable(ap); } diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index 18c296c5689..d6c7086a537 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -264,7 +264,7 @@ static void sil_post_set_mode (struct ata_port *ap) for (i = 0; i < 2; i++) { dev = &ap->device[i]; - if (!ata_dev_present(dev)) + if (!ata_dev_enabled(dev)) dev_mode[i] = 0; /* PIO0/1/2 */ else if (dev->flags & ATA_DFLAG_PIO) dev_mode[i] = 1; /* PIO3/4 */ diff --git a/include/linux/libata.h b/include/linux/libata.h index 0d61357604d..c6883ba8cba 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -672,14 +672,24 @@ static inline unsigned int ata_tag_valid(unsigned int tag) return (tag < ATA_MAX_QUEUE) ? 1 : 0; } -static inline unsigned int ata_class_present(unsigned int class) +static inline unsigned int ata_class_enabled(unsigned int class) { return class == ATA_DEV_ATA || class == ATA_DEV_ATAPI; } -static inline unsigned int ata_dev_present(const struct ata_device *dev) +static inline unsigned int ata_class_disabled(unsigned int class) { - return ata_class_present(dev->class); + return class == ATA_DEV_ATA_UNSUP || class == ATA_DEV_ATAPI_UNSUP; +} + +static inline unsigned int ata_dev_enabled(const struct ata_device *dev) +{ + return ata_class_enabled(dev->class); +} + +static inline unsigned int ata_dev_disabled(const struct ata_device *dev) +{ + return ata_class_disabled(dev->class); } static inline u8 ata_chk_status(struct ata_port *ap) -- cgit v1.2.3 From 4f65977df0b9a667fdcd85b95d457a220c94113f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 1 Apr 2006 01:38:18 +0900 Subject: [PATCH] libata: make ata_set_mode() handle no-device case properly Make ata_set_mode() return without doing anything if there is no device on the port. This is in preparation for ata_bus_probe() changes. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index c10c550da38..913e378eca7 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1823,7 +1823,7 @@ static void ata_host_set_dma(struct ata_port *ap) */ static void ata_set_mode(struct ata_port *ap) { - int i, rc, used_dma = 0; + int i, rc, used_dma = 0, found = 0; /* step 1: calculate xfer_mask */ for (i = 0; i < ATA_MAX_DEVICES; i++) { @@ -1842,9 +1842,12 @@ static void ata_set_mode(struct ata_port *ap) dev->pio_mode = ata_xfer_mask2mode(pio_mask); dev->dma_mode = ata_xfer_mask2mode(dma_mask); + found = 1; if (dev->dma_mode) used_dma = 1; } + if (!found) + return; /* step 2: always set host PIO timings */ rc = ata_host_set_pio(ap); -- cgit v1.2.3 From e8e0619f68bff8f39d98c46aac85ed1d4557ccfd Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 1 Apr 2006 01:38:18 +0900 Subject: [PATCH] libata: reorganize ata_set_mode() Merge ata_host_set_pio() and ata_host_set_dma() into ata_set_mode() and use function-level *dev to iterate over devices. This eases soon-to-follow ata_set_mode() interface change. While at it, kill an unnecessary comment and normalize others. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 91 ++++++++++++++++++---------------------------- 1 file changed, 35 insertions(+), 56 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 913e378eca7..f04561abf6d 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1771,47 +1771,6 @@ static int ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev) return 0; } -static int ata_host_set_pio(struct ata_port *ap) -{ - int i; - - for (i = 0; i < ATA_MAX_DEVICES; i++) { - struct ata_device *dev = &ap->device[i]; - - if (!ata_dev_enabled(dev)) - continue; - - if (!dev->pio_mode) { - printk(KERN_WARNING "ata%u: no PIO support for device %d.\n", ap->id, i); - return -1; - } - - dev->xfer_mode = dev->pio_mode; - dev->xfer_shift = ATA_SHIFT_PIO; - if (ap->ops->set_piomode) - ap->ops->set_piomode(ap, dev); - } - - return 0; -} - -static void ata_host_set_dma(struct ata_port *ap) -{ - int i; - - for (i = 0; i < ATA_MAX_DEVICES; i++) { - struct ata_device *dev = &ap->device[i]; - - if (!ata_dev_enabled(dev) || !dev->dma_mode) - continue; - - dev->xfer_mode = dev->dma_mode; - dev->xfer_shift = ata_xfer_mode2shift(dev->dma_mode); - if (ap->ops->set_dmamode) - ap->ops->set_dmamode(ap, dev); - } -} - /** * ata_set_mode - Program timings and issue SET FEATURES - XFER * @ap: port on which timings will be programmed @@ -1823,20 +1782,20 @@ static void ata_host_set_dma(struct ata_port *ap) */ static void ata_set_mode(struct ata_port *ap) { + struct ata_device *dev; int i, rc, used_dma = 0, found = 0; /* step 1: calculate xfer_mask */ for (i = 0; i < ATA_MAX_DEVICES; i++) { - struct ata_device *dev = &ap->device[i]; unsigned int pio_mask, dma_mask; + dev = &ap->device[i]; + if (!ata_dev_enabled(dev)) continue; ata_dev_xfermask(ap, dev); - /* TODO: let LLDD filter dev->*_mask here */ - pio_mask = ata_pack_xfermask(dev->pio_mask, 0, 0); dma_mask = ata_pack_xfermask(0, dev->mwdma_mask, dev->udma_mask); dev->pio_mode = ata_xfer_mask2mode(pio_mask); @@ -1850,16 +1809,40 @@ static void ata_set_mode(struct ata_port *ap) return; /* step 2: always set host PIO timings */ - rc = ata_host_set_pio(ap); - if (rc) - goto err_out; + for (i = 0; i < ATA_MAX_DEVICES; i++) { + dev = &ap->device[i]; + if (!ata_dev_enabled(dev)) + continue; + + if (!dev->pio_mode) { + printk(KERN_WARNING "ata%u: dev %u no PIO support\n", + ap->id, dev->devno); + rc = -EINVAL; + goto err_out; + } + + dev->xfer_mode = dev->pio_mode; + dev->xfer_shift = ATA_SHIFT_PIO; + if (ap->ops->set_piomode) + ap->ops->set_piomode(ap, dev); + } /* step 3: set host DMA timings */ - ata_host_set_dma(ap); + for (i = 0; i < ATA_MAX_DEVICES; i++) { + dev = &ap->device[i]; + + if (!ata_dev_enabled(dev) || !dev->dma_mode) + continue; + + dev->xfer_mode = dev->dma_mode; + dev->xfer_shift = ata_xfer_mode2shift(dev->dma_mode); + if (ap->ops->set_dmamode) + ap->ops->set_dmamode(ap, dev); + } /* step 4: update devices' xfer mode */ for (i = 0; i < ATA_MAX_DEVICES; i++) { - struct ata_device *dev = &ap->device[i]; + dev = &ap->device[i]; if (!ata_dev_enabled(dev)) continue; @@ -1869,17 +1852,13 @@ static void ata_set_mode(struct ata_port *ap) goto err_out; } - /* - * Record simplex status. If we selected DMA then the other - * host channels are not permitted to do so. + /* Record simplex status. If we selected DMA then the other + * host channels are not permitted to do so. */ - if (used_dma && (ap->host_set->flags & ATA_HOST_SIMPLEX)) ap->host_set->simplex_claimed = 1; - /* - * Chip specific finalisation - */ + /* step5: chip specific finalisation */ if (ap->ops->post_set_mode) ap->ops->post_set_mode(ap); -- cgit v1.2.3 From eee6c32f5f114f9b9f2d94862f0dc0d3ff523864 Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Sat, 1 Apr 2006 17:38:43 +0800 Subject: [PATCH] libata-dev: handle DRQ=1 ERR=1 (revised) Handle DRQ=1 ERR=1 situation. Revised according to what IDE try_to_flush_leftover_data() does. Changes: - For ATA PIO writes and ATAPI devices, just stop the HSM and let EH handle it. - For ATA PIO reads, read only one block of junk data and then let EH handle it. Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 46 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 6fc25f60db9..da13deccc0e 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3640,13 +3640,16 @@ fsm_start: /* Device should not ask for data transfer (DRQ=1) * when it finds something wrong. - * Anyway, we respect DRQ here and let HSM go on - * without changing hsm_task_state to HSM_ST_ERR. + * We ignore DRQ here and stop the HSM by + * changing hsm_task_state to HSM_ST_ERR and + * let the EH abort the command or reset the device. */ if (unlikely(status & (ATA_ERR | ATA_DF))) { printk(KERN_WARNING "ata%d: DRQ=1 with device error, dev_stat 0x%X\n", ap->id, status); qc->err_mask |= AC_ERR_DEV; + ap->hsm_task_state = HSM_ST_ERR; + goto fsm_start; } /* Send the CDB (atapi) or the first data block (ata pio out). @@ -3693,13 +3696,16 @@ fsm_start: /* Device should not ask for data transfer (DRQ=1) * when it finds something wrong. - * Anyway, we respect DRQ here and let HSM go on - * without changing hsm_task_state to HSM_ST_ERR. + * We ignore DRQ here and stop the HSM by + * changing hsm_task_state to HSM_ST_ERR and + * let the EH abort the command or reset the device. */ if (unlikely(status & (ATA_ERR | ATA_DF))) { printk(KERN_WARNING "ata%d: DRQ=1 with device error, dev_stat 0x%X\n", ap->id, status); qc->err_mask |= AC_ERR_DEV; + ap->hsm_task_state = HSM_ST_ERR; + goto fsm_start; } atapi_pio_bytes(qc); @@ -3717,20 +3723,32 @@ fsm_start: goto fsm_start; } - /* Some devices may ask for data transfer (DRQ=1) - * alone with ERR=1 for PIO reads. - * We respect DRQ here and let HSM go on without - * changing hsm_task_state to HSM_ST_ERR. + /* For PIO reads, some devices may ask for + * data transfer (DRQ=1) alone with ERR=1. + * We respect DRQ here and transfer one + * block of junk data before changing the + * hsm_task_state to HSM_ST_ERR. + * + * For PIO writes, ERR=1 DRQ=1 doesn't make + * sense since the data block has been + * transferred to the device. */ if (unlikely(status & (ATA_ERR | ATA_DF))) { - /* For writes, ERR=1 DRQ=1 doesn't make - * sense since the data block has been - * transferred to the device. - */ - WARN_ON(qc->tf.flags & ATA_TFLAG_WRITE); - /* data might be corrputed */ qc->err_mask |= AC_ERR_DEV; + + if (!(qc->tf.flags & ATA_TFLAG_WRITE)) { + ata_pio_sectors(qc); + ata_altstatus(ap); + status = ata_wait_idle(ap); + } + + /* ata_pio_sectors() might change the + * state to HSM_ST_LAST. so, the state + * is changed after ata_pio_sectors(). + */ + ap->hsm_task_state = HSM_ST_ERR; + goto fsm_start; } ata_pio_sectors(qc); -- cgit v1.2.3 From e82cbdb9a3791f781462c9d00e3486e8fb7e58a8 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 1 Apr 2006 01:38:18 +0900 Subject: [PATCH] libata: don't disable devices from ata_set_mode() When ata_set_mode() fails on a device, make ata_set_mode() return error code and pointer to the device instead of disabling it directly. This gives more control to higher level driving logic. This patch does not change the end result (configured transfer mode) although it may make libata repeat mode configuration to the peer of a failing device. Later ata_bus_probe() rewrite will make full use of this change. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 66 ++++++++++++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 26 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index f04561abf6d..061b0b6544c 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -65,7 +65,7 @@ static unsigned int ata_dev_init_params(struct ata_port *ap, struct ata_device *dev, u16 heads, u16 sectors); -static void ata_set_mode(struct ata_port *ap); +static int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev); static unsigned int ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev); static void ata_dev_xfermask(struct ata_port *ap, struct ata_device *dev); @@ -1368,6 +1368,7 @@ static int ata_bus_probe(struct ata_port *ap) { unsigned int classes[ATA_MAX_DEVICES]; int i, rc, found = 0; + struct ata_device *dev; ata_port_probe(ap); @@ -1397,8 +1398,7 @@ static int ata_bus_probe(struct ata_port *ap) /* read IDENTIFY page and configure devices */ for (i = 0; i < ATA_MAX_DEVICES; i++) { - struct ata_device *dev = &ap->device[i]; - + dev = &ap->device[i]; dev->class = classes[i]; if (!ata_dev_enabled(dev)) @@ -1418,20 +1418,26 @@ static int ata_bus_probe(struct ata_port *ap) found = 1; } - if (!found) - goto err_out_disable; - - if (ap->ops->set_mode) - ap->ops->set_mode(ap); - else - ata_set_mode(ap); - - if (ap->flags & ATA_FLAG_PORT_DISABLED) - goto err_out_disable; + /* configure transfer mode */ + if (ap->ops->set_mode) { + /* FIXME: make ->set_mode handle no device case and + * return error code and failing device on failure as + * ata_set_mode() does. + */ + if (found) + ap->ops->set_mode(ap); + rc = 0; + } else { + while (ata_set_mode(ap, &dev)) + ata_dev_disable(ap, dev); + } - return 0; + for (i = 0; i < ATA_MAX_DEVICES; i++) + if (ata_dev_enabled(&ap->device[i])) + return 0; -err_out_disable: + /* no device present, disable port */ + ata_port_disable(ap); ap->ops->port_disable(ap); return -ENODEV; } @@ -1774,16 +1780,22 @@ static int ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev) /** * ata_set_mode - Program timings and issue SET FEATURES - XFER * @ap: port on which timings will be programmed + * @r_failed_dev: out paramter for failed device * - * Set ATA device disk transfer mode (PIO3, UDMA6, etc.). + * Set ATA device disk transfer mode (PIO3, UDMA6, etc.). If + * ata_set_mode() fails, pointer to the failing device is + * returned in @r_failed_dev. * * LOCKING: * PCI/etc. bus probe sem. + * + * RETURNS: + * 0 on success, negative errno otherwise */ -static void ata_set_mode(struct ata_port *ap) +static int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev) { struct ata_device *dev; - int i, rc, used_dma = 0, found = 0; + int i, rc = 0, used_dma = 0, found = 0; /* step 1: calculate xfer_mask */ for (i = 0; i < ATA_MAX_DEVICES; i++) { @@ -1806,7 +1818,7 @@ static void ata_set_mode(struct ata_port *ap) used_dma = 1; } if (!found) - return; + goto out; /* step 2: always set host PIO timings */ for (i = 0; i < ATA_MAX_DEVICES; i++) { @@ -1818,7 +1830,7 @@ static void ata_set_mode(struct ata_port *ap) printk(KERN_WARNING "ata%u: dev %u no PIO support\n", ap->id, dev->devno); rc = -EINVAL; - goto err_out; + goto out; } dev->xfer_mode = dev->pio_mode; @@ -1849,7 +1861,7 @@ static void ata_set_mode(struct ata_port *ap) rc = ata_dev_set_mode(ap, dev); if (rc) - goto err_out; + goto out; } /* Record simplex status. If we selected DMA then the other @@ -1862,10 +1874,10 @@ static void ata_set_mode(struct ata_port *ap) if (ap->ops->post_set_mode) ap->ops->post_set_mode(ap); - return; - -err_out: - ata_port_disable(ap); + out: + if (rc) + *r_failed_dev = dev; + return rc; } /** @@ -4278,8 +4290,10 @@ static int ata_start_drive(struct ata_port *ap, struct ata_device *dev) int ata_device_resume(struct ata_port *ap, struct ata_device *dev) { if (ap->flags & ATA_FLAG_SUSPENDED) { + struct ata_device *failed_dev; ap->flags &= ~ATA_FLAG_SUSPENDED; - ata_set_mode(ap); + while (ata_set_mode(ap, &failed_dev)) + ata_dev_disable(ap, failed_dev); } if (!ata_dev_enabled(dev)) return 0; -- cgit v1.2.3 From 852ee16a914fb3ada2f81e222677c04defc2f15f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 1 Apr 2006 01:38:18 +0900 Subject: [PATCH] libata: preserve SATA SPD setting over hard resets Don't overwrite SPD setting during hard reset. This change has the (intended) side effect of honoring the BIOS configuration. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 061b0b6544c..3acf56200d8 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2132,9 +2132,11 @@ err_out: static int sata_phy_resume(struct ata_port *ap) { unsigned long timeout = jiffies + (HZ * 5); - u32 sstatus; + u32 scontrol, sstatus; - scr_write_flush(ap, SCR_CONTROL, 0x300); + scontrol = scr_read(ap, SCR_CONTROL); + scontrol = (scontrol & 0x0f0) | 0x300; + scr_write_flush(ap, SCR_CONTROL, scontrol); /* Wait for phy to become ready, if necessary. */ do { @@ -2247,10 +2249,14 @@ int ata_std_softreset(struct ata_port *ap, int verbose, unsigned int *classes) */ int sata_std_hardreset(struct ata_port *ap, int verbose, unsigned int *class) { + u32 scontrol; + DPRINTK("ENTER\n"); /* Issue phy wake/reset */ - scr_write_flush(ap, SCR_CONTROL, 0x301); + scontrol = scr_read(ap, SCR_CONTROL); + scontrol = (scontrol & 0x0f0) | 0x301; + scr_write_flush(ap, SCR_CONTROL, scontrol); /* * Couldn't find anything in SATA I/II specs, but AHCI-1.1 -- cgit v1.2.3 From 1300124f69cafc54331bc06e968a8dd67863f989 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 28 Mar 2006 17:04:00 -0500 Subject: ACPI: Kconfig: ACPI should depend on, not select PCI Otherwise, illegal configurations like X86_VOYAGER=y, PCI=y are possible. This patch also fixes the options select'ing ACPI to also select PCI. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- arch/ia64/Kconfig | 1 + arch/x86_64/Kconfig | 1 + drivers/acpi/Kconfig | 3 +-- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index edffe25a477..0046020e73b 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -77,6 +77,7 @@ choice config IA64_GENERIC bool "generic" select ACPI + select PCI select NUMA select ACPI_NUMA help diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index 4310b4a311a..299d8740177 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig @@ -289,6 +289,7 @@ config X86_64_ACPI_NUMA bool "ACPI NUMA detection" depends on NUMA select ACPI + select PCI select ACPI_NUMA default y help diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 5cb96300eb0..932583da43a 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -10,9 +10,8 @@ menu "ACPI (Advanced Configuration and Power Interface) Support" config ACPI bool "ACPI Support" depends on IA64 || X86 + depends on PCI select PM - select PCI - default y ---help--- Advanced Configuration and Power Interface (ACPI) support for -- cgit v1.2.3 From 7e1f19e50371e1d148226b64c8edc77fec47fa5b Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 28 Mar 2006 17:03:00 -0500 Subject: ACPI: UP build fix for bugzilla-5737 cpu_online_map doesn't exist if !CONFIG_SMP. Signed-off-by: Venkatesh Pallipadi Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c | 4 ++++ arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c index 4c7c6e089e8..11da3ca237e 100644 --- a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c @@ -225,8 +225,12 @@ acpi_cpufreq_target ( freqs.old = data->freq_table[cur_state].frequency; freqs.new = data->freq_table[next_state].frequency; +#ifdef CONFIG_HOTPLUG_CPU /* cpufreq holds the hotplug lock, so we are safe from here on */ cpus_and(online_policy_cpus, cpu_online_map, policy->cpus); +#else + online_policy_cpus = policy->cpus; +#endif for_each_cpu_mask(j, online_policy_cpus) { freqs.cpu = j; diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c index 37dee862f0d..9a65993396e 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c @@ -654,8 +654,12 @@ static int centrino_target (struct cpufreq_policy *policy, return -EINVAL; } +#ifdef CONFIG_HOTPLUG_CPU /* cpufreq holds the hotplug lock, so we are safe from here on */ cpus_and(online_policy_cpus, cpu_online_map, policy->cpus); +#else + online_policy_cpus = policy->cpus; +#endif saved_mask = current->cpus_allowed; first_cpu = 1; -- cgit v1.2.3 From 1acfb7f2b0d460ee86bdb25ad0679070ec8a5f0d Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 28 Mar 2006 17:03:00 -0500 Subject: PNPACPI: fix non-memory address space descriptor handling Fix resource_type handling for QWORD, DWORD, and WORD Address Space Descriptors. Previously we ignored the resource_type, so I/O ports and bus number ranges were incorrectly parsed as memory ranges. Sample PCI root bridge resources from HP rx2600 before this patch: # cat /sys/bus/pnp/devices/00:02/resources state = active mem 0x0-0x1f mem 0x0-0x3af mem 0x3e0-0x1fff mem 0x80000000-0x8fffffff With this patch: # cat /sys/bus/pnp/devices/00:02/resources state = active io 0x0-0x3af io 0x3e0-0x1fff mem 0x80000000-0x8fffffff mem 0x80004000000-0x80103fffffe Changes: 0x0-0x1f PCI bus number range was incorrectly reported as memory, now not reported at all 0x0-0x3af I/O port range was incorrectly reported as memory 0x3e0-0x1fff I/O port range was incorrectly reported as memory 0x80004000000-0x80103fffffe memory range wasn't reported at all because we only support PNP_MAX_MEM (4) memory resources Signed-off-by: Bjorn Helgaas Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/pnp/pnpacpi/rsparser.c | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index 407b4eaddcb..522d697cff0 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c @@ -120,7 +120,7 @@ pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table * res, u32 dma) static void pnpacpi_parse_allocated_ioresource(struct pnp_resource_table * res, - u32 io, u32 len) + u64 io, u64 len) { int i = 0; while (!(res->port_resource[i].flags & IORESOURCE_UNSET) && @@ -156,6 +156,27 @@ pnpacpi_parse_allocated_memresource(struct pnp_resource_table * res, } } +static void +pnpacpi_parse_allocated_address_space(struct pnp_resource_table *res_table, + struct acpi_resource *res) +{ + struct acpi_resource_address64 addr, *p = &addr; + acpi_status status; + + status = acpi_resource_to_address64(res, p); + if (!ACPI_SUCCESS(status)) { + pnp_warn("PnPACPI: failed to convert resource type %d", + res->type); + return; + } + + if (p->resource_type == ACPI_MEMORY_RANGE) + pnpacpi_parse_allocated_memresource(res_table, + p->minimum, p->address_length); + else if (p->resource_type == ACPI_IO_RANGE) + pnpacpi_parse_allocated_ioresource(res_table, + p->minimum, p->address_length); +} static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, void *data) @@ -221,19 +242,9 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, res->data.fixed_memory32.address_length); break; case ACPI_RESOURCE_TYPE_ADDRESS16: - pnpacpi_parse_allocated_memresource(res_table, - res->data.address16.minimum, - res->data.address16.address_length); - break; case ACPI_RESOURCE_TYPE_ADDRESS32: - pnpacpi_parse_allocated_memresource(res_table, - res->data.address32.minimum, - res->data.address32.address_length); - break; case ACPI_RESOURCE_TYPE_ADDRESS64: - pnpacpi_parse_allocated_memresource(res_table, - res->data.address64.minimum, - res->data.address64.address_length); + pnpacpi_parse_allocated_address_space(res_table, res); break; case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: -- cgit v1.2.3 From b5f2490b6e3317059e87ba40d4f659d1c30afc1f Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 28 Mar 2006 17:04:00 -0500 Subject: PNPACPI: remove some code duplication Factor out the duplicated switch from pnpacpi_count_resources() and pnpacpi_type_resources(). Remove the unnecessary re-initialization of resource->type and length from all the encode functions (id and length are originally set in the pnpacpi_build_resource_template() -> pnpacpi_type_resources() path). Signed-off-by: Bjorn Helgaas Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/pnp/pnpacpi/rsparser.c | 67 ++++++++++++------------------------------ 1 file changed, 18 insertions(+), 49 deletions(-) diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index 522d697cff0..b13f85e0bc3 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c @@ -647,13 +647,8 @@ acpi_status pnpacpi_parse_resource_option_data(acpi_handle handle, return status; } -/* - * Set resource - */ -static acpi_status pnpacpi_count_resources(struct acpi_resource *res, - void *data) +static int pnpacpi_supported_resource(struct acpi_resource *res) { - int *res_cnt = (int *)data; switch (res->type) { case ACPI_RESOURCE_TYPE_IRQ: case ACPI_RESOURCE_TYPE_DMA: @@ -666,15 +661,21 @@ static acpi_status pnpacpi_count_resources(struct acpi_resource *res, case ACPI_RESOURCE_TYPE_ADDRESS32: case ACPI_RESOURCE_TYPE_ADDRESS64: case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: - (*res_cnt) ++; - case ACPI_RESOURCE_TYPE_START_DEPENDENT: - case ACPI_RESOURCE_TYPE_END_DEPENDENT: - case ACPI_RESOURCE_TYPE_VENDOR: - case ACPI_RESOURCE_TYPE_END_TAG: - case ACPI_RESOURCE_TYPE_GENERIC_REGISTER: - default: - return AE_OK; + return 1; } + return 0; +} + +/* + * Set resource + */ +static acpi_status pnpacpi_count_resources(struct acpi_resource *res, + void *data) +{ + int *res_cnt = (int *)data; + + if (pnpacpi_supported_resource(res)) + (*res_cnt)++; return AE_OK; } @@ -682,27 +683,11 @@ static acpi_status pnpacpi_type_resources(struct acpi_resource *res, void *data) { struct acpi_resource **resource = (struct acpi_resource **)data; - switch (res->type) { - case ACPI_RESOURCE_TYPE_IRQ: - case ACPI_RESOURCE_TYPE_DMA: - case ACPI_RESOURCE_TYPE_IO: - case ACPI_RESOURCE_TYPE_FIXED_IO: - case ACPI_RESOURCE_TYPE_MEMORY24: - case ACPI_RESOURCE_TYPE_MEMORY32: - case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: - case ACPI_RESOURCE_TYPE_ADDRESS16: - case ACPI_RESOURCE_TYPE_ADDRESS32: - case ACPI_RESOURCE_TYPE_ADDRESS64: - case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: + + if (pnpacpi_supported_resource(res)) { (*resource)->type = res->type; + (*resource)->length = sizeof(struct acpi_resource); (*resource)++; - case ACPI_RESOURCE_TYPE_START_DEPENDENT: - case ACPI_RESOURCE_TYPE_END_DEPENDENT: - case ACPI_RESOURCE_TYPE_VENDOR: - case ACPI_RESOURCE_TYPE_END_TAG: - case ACPI_RESOURCE_TYPE_GENERIC_REGISTER: - default: - return AE_OK; } return AE_OK; @@ -749,8 +734,6 @@ static void pnpacpi_encode_irq(struct acpi_resource *resource, decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity); - resource->type = ACPI_RESOURCE_TYPE_IRQ; - resource->length = sizeof(struct acpi_resource); resource->data.irq.triggering = triggering; resource->data.irq.polarity = polarity; if (triggering == ACPI_EDGE_SENSITIVE) @@ -768,8 +751,6 @@ static void pnpacpi_encode_ext_irq(struct acpi_resource *resource, decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity); - resource->type = ACPI_RESOURCE_TYPE_EXTENDED_IRQ; - resource->length = sizeof(struct acpi_resource); resource->data.extended_irq.producer_consumer = ACPI_CONSUMER; resource->data.extended_irq.triggering = triggering; resource->data.extended_irq.polarity = polarity; @@ -784,8 +765,6 @@ static void pnpacpi_encode_ext_irq(struct acpi_resource *resource, static void pnpacpi_encode_dma(struct acpi_resource *resource, struct resource *p) { - resource->type = ACPI_RESOURCE_TYPE_DMA; - resource->length = sizeof(struct acpi_resource); /* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */ if (p->flags & IORESOURCE_DMA_COMPATIBLE) resource->data.dma.type = ACPI_COMPATIBILITY; @@ -809,8 +788,6 @@ static void pnpacpi_encode_dma(struct acpi_resource *resource, static void pnpacpi_encode_io(struct acpi_resource *resource, struct resource *p) { - resource->type = ACPI_RESOURCE_TYPE_IO; - resource->length = sizeof(struct acpi_resource); /* Note: pnp_assign_port will copy pnp_port->flags into p->flags */ resource->data.io.io_decode = (p->flags & PNP_PORT_FLAG_16BITADDR)? ACPI_DECODE_16 : ACPI_DECODE_10; @@ -823,8 +800,6 @@ static void pnpacpi_encode_io(struct acpi_resource *resource, static void pnpacpi_encode_fixed_io(struct acpi_resource *resource, struct resource *p) { - resource->type = ACPI_RESOURCE_TYPE_FIXED_IO; - resource->length = sizeof(struct acpi_resource); resource->data.fixed_io.address = p->start; resource->data.fixed_io.address_length = p->end - p->start + 1; } @@ -832,8 +807,6 @@ static void pnpacpi_encode_fixed_io(struct acpi_resource *resource, static void pnpacpi_encode_mem24(struct acpi_resource *resource, struct resource *p) { - resource->type = ACPI_RESOURCE_TYPE_MEMORY24; - resource->length = sizeof(struct acpi_resource); /* Note: pnp_assign_mem will copy pnp_mem->flags into p->flags */ resource->data.memory24.write_protect = (p->flags & IORESOURCE_MEM_WRITEABLE) ? @@ -847,8 +820,6 @@ static void pnpacpi_encode_mem24(struct acpi_resource *resource, static void pnpacpi_encode_mem32(struct acpi_resource *resource, struct resource *p) { - resource->type = ACPI_RESOURCE_TYPE_MEMORY32; - resource->length = sizeof(struct acpi_resource); resource->data.memory32.write_protect = (p->flags & IORESOURCE_MEM_WRITEABLE) ? ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; @@ -861,8 +832,6 @@ static void pnpacpi_encode_mem32(struct acpi_resource *resource, static void pnpacpi_encode_fixed_mem32(struct acpi_resource *resource, struct resource *p) { - resource->type = ACPI_RESOURCE_TYPE_FIXED_MEMORY32; - resource->length = sizeof(struct acpi_resource); resource->data.fixed_memory32.write_protect = (p->flags & IORESOURCE_MEM_WRITEABLE) ? ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; -- cgit v1.2.3 From 1c6e7d0aeecac38e66b1bb63e3eff07b2a1c2f2c Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 28 Mar 2006 17:04:00 -0500 Subject: PNPACPI: whitespace cleanup Tidy up whitespace. No functional change. Signed-off-by: Bjorn Helgaas Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/pnp/pnpacpi/rsparser.c | 97 ++++++++++++++++++++---------------------- 1 file changed, 47 insertions(+), 50 deletions(-) diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index b13f85e0bc3..3a4a644c268 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c @@ -36,13 +36,13 @@ static int irq_flags(int triggering, int polarity) { int flag; if (triggering == ACPI_LEVEL_SENSITIVE) { - if(polarity == ACPI_ACTIVE_LOW) + if (polarity == ACPI_ACTIVE_LOW) flag = IORESOURCE_IRQ_LOWLEVEL; else flag = IORESOURCE_IRQ_HIGHLEVEL; } else { - if(polarity == ACPI_ACTIVE_LOW) + if (polarity == ACPI_ACTIVE_LOW) flag = IORESOURCE_IRQ_LOWEDGE; else flag = IORESOURCE_IRQ_HIGHEDGE; @@ -57,7 +57,7 @@ static void decode_irq_flags(int flag, int *triggering, int *polarity) *triggering = ACPI_LEVEL_SENSITIVE; *polarity = ACPI_ACTIVE_LOW; break; - case IORESOURCE_IRQ_HIGHLEVEL: + case IORESOURCE_IRQ_HIGHLEVEL: *triggering = ACPI_LEVEL_SENSITIVE; *polarity = ACPI_ACTIVE_HIGH; break; @@ -73,7 +73,7 @@ static void decode_irq_flags(int flag, int *triggering, int *polarity) } static void -pnpacpi_parse_allocated_irqresource(struct pnp_resource_table * res, u32 gsi, +pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res, u32 gsi, int triggering, int polarity) { int i = 0; @@ -101,7 +101,7 @@ pnpacpi_parse_allocated_irqresource(struct pnp_resource_table * res, u32 gsi, } static void -pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table * res, u32 dma) +pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table *res, u32 dma) { int i = 0; while (i < PNP_MAX_DMA && @@ -119,7 +119,7 @@ pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table * res, u32 dma) } static void -pnpacpi_parse_allocated_ioresource(struct pnp_resource_table * res, +pnpacpi_parse_allocated_ioresource(struct pnp_resource_table *res, u64 io, u64 len) { int i = 0; @@ -138,7 +138,7 @@ pnpacpi_parse_allocated_ioresource(struct pnp_resource_table * res, } static void -pnpacpi_parse_allocated_memresource(struct pnp_resource_table * res, +pnpacpi_parse_allocated_memresource(struct pnp_resource_table *res, u64 mem, u64 len) { int i = 0; @@ -181,7 +181,7 @@ pnpacpi_parse_allocated_address_space(struct pnp_resource_table *res_table, static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, void *data) { - struct pnp_resource_table * res_table = (struct pnp_resource_table *)data; + struct pnp_resource_table *res_table = (struct pnp_resource_table *)data; int i; switch (res->type) { @@ -266,11 +266,11 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, pnp_warn("PnPACPI: unknown resource type %d", res->type); return AE_ERROR; } - + return AE_OK; } -acpi_status pnpacpi_parse_allocated_resource(acpi_handle handle, struct pnp_resource_table * res) +acpi_status pnpacpi_parse_allocated_resource(acpi_handle handle, struct pnp_resource_table *res) { /* Blank the resource table values */ pnp_init_resource_table(res); @@ -328,17 +328,17 @@ static void pnpacpi_parse_dma_option(struct pnp_option *option, struct acpi_reso pnp_err("Invalid DMA transfer type"); } - pnp_register_dma_resource(option,dma); + pnp_register_dma_resource(option, dma); return; } - + static void pnpacpi_parse_irq_option(struct pnp_option *option, struct acpi_resource_irq *p) { int i; - struct pnp_irq * irq; - + struct pnp_irq *irq; + if (p->interrupt_count == 0) return; irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL); @@ -358,7 +358,7 @@ static void pnpacpi_parse_ext_irq_option(struct pnp_option *option, struct acpi_resource_extended_irq *p) { int i; - struct pnp_irq * irq; + struct pnp_irq *irq; if (p->interrupt_count == 0) return; @@ -379,7 +379,7 @@ static void pnpacpi_parse_port_option(struct pnp_option *option, struct acpi_resource_io *io) { - struct pnp_port * port; + struct pnp_port *port; if (io->address_length == 0) return; @@ -392,7 +392,7 @@ pnpacpi_parse_port_option(struct pnp_option *option, port->size = io->address_length; port->flags = ACPI_DECODE_16 == io->io_decode ? PNP_PORT_FLAG_16BITADDR : 0; - pnp_register_port_resource(option,port); + pnp_register_port_resource(option, port); return; } @@ -400,7 +400,7 @@ static void pnpacpi_parse_fixed_port_option(struct pnp_option *option, struct acpi_resource_fixed_io *io) { - struct pnp_port * port; + struct pnp_port *port; if (io->address_length == 0) return; @@ -411,7 +411,7 @@ pnpacpi_parse_fixed_port_option(struct pnp_option *option, port->size = io->address_length; port->align = 0; port->flags = PNP_PORT_FLAG_FIXED; - pnp_register_port_resource(option,port); + pnp_register_port_resource(option, port); return; } @@ -419,7 +419,7 @@ static void pnpacpi_parse_mem24_option(struct pnp_option *option, struct acpi_resource_memory24 *p) { - struct pnp_mem * mem; + struct pnp_mem *mem; if (p->address_length == 0) return; @@ -434,7 +434,7 @@ pnpacpi_parse_mem24_option(struct pnp_option *option, mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ? IORESOURCE_MEM_WRITEABLE : 0; - pnp_register_mem_resource(option,mem); + pnp_register_mem_resource(option, mem); return; } @@ -442,7 +442,7 @@ static void pnpacpi_parse_mem32_option(struct pnp_option *option, struct acpi_resource_memory32 *p) { - struct pnp_mem * mem; + struct pnp_mem *mem; if (p->address_length == 0) return; @@ -457,7 +457,7 @@ pnpacpi_parse_mem32_option(struct pnp_option *option, mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ? IORESOURCE_MEM_WRITEABLE : 0; - pnp_register_mem_resource(option,mem); + pnp_register_mem_resource(option, mem); return; } @@ -465,7 +465,7 @@ static void pnpacpi_parse_fixed_mem32_option(struct pnp_option *option, struct acpi_resource_fixed_memory32 *p) { - struct pnp_mem * mem; + struct pnp_mem *mem; if (p->address_length == 0) return; @@ -479,7 +479,7 @@ pnpacpi_parse_fixed_mem32_option(struct pnp_option *option, mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ? IORESOURCE_MEM_WRITEABLE : 0; - pnp_register_mem_resource(option,mem); + pnp_register_mem_resource(option, mem); return; } @@ -488,8 +488,8 @@ pnpacpi_parse_address_option(struct pnp_option *option, struct acpi_resource *r) { struct acpi_resource_address64 addr, *p = &addr; acpi_status status; - struct pnp_mem * mem; - struct pnp_port * port; + struct pnp_mem *mem; + struct pnp_port *port; status = acpi_resource_to_address64(r, p); if (!ACPI_SUCCESS(status)) { @@ -509,7 +509,7 @@ pnpacpi_parse_address_option(struct pnp_option *option, struct acpi_resource *r) mem->align = 0; mem->flags = (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY) ? IORESOURCE_MEM_WRITEABLE : 0; - pnp_register_mem_resource(option,mem); + pnp_register_mem_resource(option, mem); } else if (p->resource_type == ACPI_IO_RANGE) { port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL); if (!port) @@ -518,7 +518,7 @@ pnpacpi_parse_address_option(struct pnp_option *option, struct acpi_resource *r) port->size = p->address_length; port->align = 0; port->flags = PNP_PORT_FLAG_FIXED; - pnp_register_port_resource(option,port); + pnp_register_port_resource(option, port); } } @@ -542,7 +542,7 @@ static acpi_status pnpacpi_option_resource(struct acpi_resource *res, break; case ACPI_RESOURCE_TYPE_DMA: - pnpacpi_parse_dma_option(option, &res->data.dma); + pnpacpi_parse_dma_option(option, &res->data.dma); break; case ACPI_RESOURCE_TYPE_START_DEPENDENT: @@ -550,7 +550,7 @@ static acpi_status pnpacpi_option_resource(struct acpi_resource *res, case ACPI_GOOD_CONFIGURATION: priority = PNP_RES_PRIORITY_PREFERRED; break; - + case ACPI_ACCEPTABLE_CONFIGURATION: priority = PNP_RES_PRIORITY_ACCEPTABLE; break; @@ -566,7 +566,7 @@ static acpi_status pnpacpi_option_resource(struct acpi_resource *res, option = pnp_register_dependent_option(dev, priority); if (!option) return AE_ERROR; - parse_data->option = option; + parse_data->option = option; break; case ACPI_RESOURCE_TYPE_END_DEPENDENT: @@ -626,7 +626,7 @@ static acpi_status pnpacpi_option_resource(struct acpi_resource *res, pnp_warn("PnPACPI: unknown resource type %d", res->type); return AE_ERROR; } - + return AE_OK; } @@ -679,10 +679,9 @@ static acpi_status pnpacpi_count_resources(struct acpi_resource *res, return AE_OK; } -static acpi_status pnpacpi_type_resources(struct acpi_resource *res, - void *data) +static acpi_status pnpacpi_type_resources(struct acpi_resource *res, void *data) { - struct acpi_resource **resource = (struct acpi_resource **)data; + struct acpi_resource **resource = (struct acpi_resource **)data; if (pnpacpi_supported_resource(res)) { (*resource)->type = res->type; @@ -731,9 +730,8 @@ static void pnpacpi_encode_irq(struct acpi_resource *resource, struct resource *p) { int triggering, polarity; - - decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, - &polarity); + + decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity); resource->data.irq.triggering = triggering; resource->data.irq.polarity = polarity; if (triggering == ACPI_EDGE_SENSITIVE) @@ -748,9 +746,8 @@ static void pnpacpi_encode_ext_irq(struct acpi_resource *resource, struct resource *p) { int triggering, polarity; - - decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, - &polarity); + + decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity); resource->data.extended_irq.producer_consumer = ACPI_CONSUMER; resource->data.extended_irq.triggering = triggering; resource->data.extended_irq.polarity = polarity; @@ -862,37 +859,37 @@ int pnpacpi_encode_resources(struct pnp_resource_table *res_table, pnp_dbg("Encode dma"); pnpacpi_encode_dma(resource, &res_table->dma_resource[dma]); - dma ++; + dma++; break; case ACPI_RESOURCE_TYPE_IO: pnp_dbg("Encode io"); pnpacpi_encode_io(resource, &res_table->port_resource[port]); - port ++; + port++; break; case ACPI_RESOURCE_TYPE_FIXED_IO: pnp_dbg("Encode fixed io"); pnpacpi_encode_fixed_io(resource, &res_table->port_resource[port]); - port ++; + port++; break; case ACPI_RESOURCE_TYPE_MEMORY24: pnp_dbg("Encode mem24"); pnpacpi_encode_mem24(resource, &res_table->mem_resource[mem]); - mem ++; + mem++; break; case ACPI_RESOURCE_TYPE_MEMORY32: pnp_dbg("Encode mem32"); pnpacpi_encode_mem32(resource, &res_table->mem_resource[mem]); - mem ++; + mem++; break; case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: pnp_dbg("Encode fixed mem32"); pnpacpi_encode_fixed_mem32(resource, &res_table->mem_resource[mem]); - mem ++; + mem++; break; case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: pnp_dbg("Encode ext irq"); @@ -913,8 +910,8 @@ int pnpacpi_encode_resources(struct pnp_resource_table *res_table, pnp_warn("unknown resource type %d", resource->type); return -EINVAL; } - resource ++; - i ++; + resource++; + i++; } return 0; } -- cgit v1.2.3 From 81507ea9cfa64e9851b53e0fefebfa776eda9ecb Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 28 Mar 2006 17:04:00 -0500 Subject: ACPI: request correct fixed hardware resource type (MMIO vs I/O port) ACPI supports fixed hardware (PM_TMR, GPE blocks, etc) in either I/O port or MMIO space, but used to always request the regions from I/O space because it didn't check the address_space_id. Sample ACPI fixed hardware in MMIO space (HP rx2600), was incorrectly reported in /proc/ioports, now reported in /proc/iomem: ff5c1004-ff5c1007 : PM_TMR ff5c1008-ff5c100b : PM1a_EVT_BLK ff5c100c-ff5c100d : PM1a_CNT_BLK ff5c1010-ff5c1013 : GPE0_BLK ff5c1014-ff5c1017 : GPE1_BLK Signed-off-by: Bjorn Helgaas Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/motherboard.c | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/drivers/acpi/motherboard.c b/drivers/acpi/motherboard.c index 468244147ec..14ffe68a094 100644 --- a/drivers/acpi/motherboard.c +++ b/drivers/acpi/motherboard.c @@ -123,41 +123,46 @@ static struct acpi_driver acpi_motherboard_driver2 = { }, }; +static void __init acpi_request_region (struct acpi_generic_address *addr, + unsigned int length, char *desc) +{ + if (!addr->address || !length) + return; + + if (addr->address_space_id == ACPI_ADR_SPACE_SYSTEM_IO) + request_region(addr->address, length, desc); + else if (addr->address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) + request_mem_region(addr->address, length, desc); +} + static void __init acpi_reserve_resources(void) { - if (acpi_gbl_FADT->xpm1a_evt_blk.address && acpi_gbl_FADT->pm1_evt_len) - request_region(acpi_gbl_FADT->xpm1a_evt_blk.address, + acpi_request_region(&acpi_gbl_FADT->xpm1a_evt_blk, acpi_gbl_FADT->pm1_evt_len, "PM1a_EVT_BLK"); - if (acpi_gbl_FADT->xpm1b_evt_blk.address && acpi_gbl_FADT->pm1_evt_len) - request_region(acpi_gbl_FADT->xpm1b_evt_blk.address, + acpi_request_region(&acpi_gbl_FADT->xpm1b_evt_blk, acpi_gbl_FADT->pm1_evt_len, "PM1b_EVT_BLK"); - if (acpi_gbl_FADT->xpm1a_cnt_blk.address && acpi_gbl_FADT->pm1_cnt_len) - request_region(acpi_gbl_FADT->xpm1a_cnt_blk.address, + acpi_request_region(&acpi_gbl_FADT->xpm1a_cnt_blk, acpi_gbl_FADT->pm1_cnt_len, "PM1a_CNT_BLK"); - if (acpi_gbl_FADT->xpm1b_cnt_blk.address && acpi_gbl_FADT->pm1_cnt_len) - request_region(acpi_gbl_FADT->xpm1b_cnt_blk.address, + acpi_request_region(&acpi_gbl_FADT->xpm1b_cnt_blk, acpi_gbl_FADT->pm1_cnt_len, "PM1b_CNT_BLK"); - if (acpi_gbl_FADT->xpm_tmr_blk.address && acpi_gbl_FADT->pm_tm_len == 4) - request_region(acpi_gbl_FADT->xpm_tmr_blk.address, 4, "PM_TMR"); + if (acpi_gbl_FADT->pm_tm_len == 4) + acpi_request_region(&acpi_gbl_FADT->xpm_tmr_blk, 4, "PM_TMR"); - if (acpi_gbl_FADT->xpm2_cnt_blk.address && acpi_gbl_FADT->pm2_cnt_len) - request_region(acpi_gbl_FADT->xpm2_cnt_blk.address, + acpi_request_region(&acpi_gbl_FADT->xpm2_cnt_blk, acpi_gbl_FADT->pm2_cnt_len, "PM2_CNT_BLK"); /* Length of GPE blocks must be a non-negative multiple of 2 */ - if (acpi_gbl_FADT->xgpe0_blk.address && acpi_gbl_FADT->gpe0_blk_len && - !(acpi_gbl_FADT->gpe0_blk_len & 0x1)) - request_region(acpi_gbl_FADT->xgpe0_blk.address, + if (!(acpi_gbl_FADT->gpe0_blk_len & 0x1)) + acpi_request_region(&acpi_gbl_FADT->xgpe0_blk, acpi_gbl_FADT->gpe0_blk_len, "GPE0_BLK"); - if (acpi_gbl_FADT->xgpe1_blk.address && acpi_gbl_FADT->gpe1_blk_len && - !(acpi_gbl_FADT->gpe1_blk_len & 0x1)) - request_region(acpi_gbl_FADT->xgpe1_blk.address, + if (!(acpi_gbl_FADT->gpe1_blk_len & 0x1)) + acpi_request_region(&acpi_gbl_FADT->xgpe1_blk, acpi_gbl_FADT->gpe1_blk_len, "GPE1_BLK"); } -- cgit v1.2.3 From cd090eedd85256829f762677d0752a846c1b88b9 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 28 Mar 2006 17:04:00 -0500 Subject: ACPI: Display "ACPI" to motherboard resources in /proc/io{mem,port} Add "ACPI" to motherboard resource allocation names, so people have a clue about where to look. And remove some trailing spaces. Changes these /proc/iomem entries from this: ff5c1004-ff5c1007 : PM_TMR ff5c1008-ff5c100b : PM1a_EVT_BLK ff5c100c-ff5c100d : PM1a_CNT_BLK ff5c1010-ff5c1013 : GPE0_BLK ff5c1014-ff5c1017 : GPE1_BLK to this: ff5c1004-ff5c1007 : ACPI PM_TMR ff5c1008-ff5c100b : ACPI PM1a_EVT_BLK ff5c100c-ff5c100d : ACPI PM1a_CNT_BLK ff5c1010-ff5c1013 : ACPI GPE0_BLK ff5c1014-ff5c1017 : ACPI GPE1_BLK Signed-off-by: Bjorn Helgaas Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/motherboard.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/acpi/motherboard.c b/drivers/acpi/motherboard.c index 14ffe68a094..d51d68f5dd8 100644 --- a/drivers/acpi/motherboard.c +++ b/drivers/acpi/motherboard.c @@ -37,7 +37,7 @@ ACPI_MODULE_NAME("acpi_motherboard") #define ACPI_MB_HID2 "PNP0C02" /** * Doesn't care about legacy IO ports, only IO ports beyond 0x1000 are reserved - * Doesn't care about the failure of 'request_region', since other may reserve + * Doesn't care about the failure of 'request_region', since other may reserve * the io ports as well */ #define IS_RESERVED_ADDR(base, len) \ @@ -46,7 +46,7 @@ ACPI_MODULE_NAME("acpi_motherboard") /* * Clearing the flag (IORESOURCE_BUSY) allows drivers to use * the io ports if they really know they can use it, while - * still preventing hotplug PCI devices from using it. + * still preventing hotplug PCI devices from using it. */ static acpi_status acpi_reserve_io_ranges(struct acpi_resource *res, void *data) { @@ -138,39 +138,39 @@ static void __init acpi_request_region (struct acpi_generic_address *addr, static void __init acpi_reserve_resources(void) { acpi_request_region(&acpi_gbl_FADT->xpm1a_evt_blk, - acpi_gbl_FADT->pm1_evt_len, "PM1a_EVT_BLK"); + acpi_gbl_FADT->pm1_evt_len, "ACPI PM1a_EVT_BLK"); acpi_request_region(&acpi_gbl_FADT->xpm1b_evt_blk, - acpi_gbl_FADT->pm1_evt_len, "PM1b_EVT_BLK"); + acpi_gbl_FADT->pm1_evt_len, "ACPI PM1b_EVT_BLK"); acpi_request_region(&acpi_gbl_FADT->xpm1a_cnt_blk, - acpi_gbl_FADT->pm1_cnt_len, "PM1a_CNT_BLK"); + acpi_gbl_FADT->pm1_cnt_len, "ACPI PM1a_CNT_BLK"); acpi_request_region(&acpi_gbl_FADT->xpm1b_cnt_blk, - acpi_gbl_FADT->pm1_cnt_len, "PM1b_CNT_BLK"); + acpi_gbl_FADT->pm1_cnt_len, "ACPI PM1b_CNT_BLK"); if (acpi_gbl_FADT->pm_tm_len == 4) - acpi_request_region(&acpi_gbl_FADT->xpm_tmr_blk, 4, "PM_TMR"); + acpi_request_region(&acpi_gbl_FADT->xpm_tmr_blk, 4, "ACPI PM_TMR"); acpi_request_region(&acpi_gbl_FADT->xpm2_cnt_blk, - acpi_gbl_FADT->pm2_cnt_len, "PM2_CNT_BLK"); + acpi_gbl_FADT->pm2_cnt_len, "ACPI PM2_CNT_BLK"); /* Length of GPE blocks must be a non-negative multiple of 2 */ if (!(acpi_gbl_FADT->gpe0_blk_len & 0x1)) acpi_request_region(&acpi_gbl_FADT->xgpe0_blk, - acpi_gbl_FADT->gpe0_blk_len, "GPE0_BLK"); + acpi_gbl_FADT->gpe0_blk_len, "ACPI GPE0_BLK"); if (!(acpi_gbl_FADT->gpe1_blk_len & 0x1)) acpi_request_region(&acpi_gbl_FADT->xgpe1_blk, - acpi_gbl_FADT->gpe1_blk_len, "GPE1_BLK"); + acpi_gbl_FADT->gpe1_blk_len, "ACPI GPE1_BLK"); } static int __init acpi_motherboard_init(void) { acpi_bus_register_driver(&acpi_motherboard_driver1); acpi_bus_register_driver(&acpi_motherboard_driver2); - /* + /* * Guarantee motherboard IO reservation first * This module must run after scan.c */ -- cgit v1.2.3 From 9d9f749b316ac21cb59ad3e595cbce469b409e1a Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 28 Mar 2006 17:04:00 -0500 Subject: ACPI: make acpi_bus_register_driver() return success/failure, not device count acpi_bus_register_driver() should not return the number of devices claimed. We're not asking to find devices, we're making a driver available to devices, including hot-pluggable devices that may appear in the future. I audited all callers of acpi_bus_register_driver(), and except asus_acpi.c and sonypi.c (fixed in previous patches), all either ignore the return value or test only for failure (<0). Signed-off-by: Bjorn Helgaas Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/scan.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index a0ab828b2cc..669553553fb 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -548,10 +548,9 @@ static int acpi_start_single_object(struct acpi_device *device) return_VALUE(result); } -static int acpi_driver_attach(struct acpi_driver *drv) +static void acpi_driver_attach(struct acpi_driver *drv) { struct list_head *node, *next; - int count = 0; ACPI_FUNCTION_TRACE("acpi_driver_attach"); @@ -568,7 +567,6 @@ static int acpi_driver_attach(struct acpi_driver *drv) if (!acpi_bus_driver_init(dev, drv)) { acpi_start_single_object(dev); atomic_inc(&drv->references); - count++; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found driver [%s] for device [%s]\n", drv->name, dev->pnp.bus_id)); @@ -577,7 +575,6 @@ static int acpi_driver_attach(struct acpi_driver *drv) spin_lock(&acpi_device_lock); } spin_unlock(&acpi_device_lock); - return_VALUE(count); } static int acpi_driver_detach(struct acpi_driver *drv) @@ -610,14 +607,11 @@ static int acpi_driver_detach(struct acpi_driver *drv) * @driver: driver being registered * * Registers a driver with the ACPI bus. Searches the namespace for all - * devices that match the driver's criteria and binds. Returns the - * number of devices that were claimed by the driver, or a negative - * error status for failure. + * devices that match the driver's criteria and binds. Returns zero for + * success or a negative error status for failure. */ int acpi_bus_register_driver(struct acpi_driver *driver) { - int count; - ACPI_FUNCTION_TRACE("acpi_bus_register_driver"); if (acpi_disabled) @@ -629,9 +623,9 @@ int acpi_bus_register_driver(struct acpi_driver *driver) spin_lock(&acpi_device_lock); list_add_tail(&driver->node, &acpi_bus_drivers); spin_unlock(&acpi_device_lock); - count = acpi_driver_attach(driver); + acpi_driver_attach(driver); - return_VALUE(count); + return_VALUE(0); } EXPORT_SYMBOL(acpi_bus_register_driver); -- cgit v1.2.3 From 578b333bfe8eb1360207a08a53c321822a8f40f3 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 28 Mar 2006 17:04:00 -0500 Subject: ACPI: update asus_acpi driver registration to unload on failure Remove the assumption that acpi_bus_register_driver() returns the number of devices claimed. Returning the count is unreliable because devices may be hot-plugged in the future (admittedly not applicable for this driver). Since the hardware for this driver is not hot-pluggable, determine whether the hardware is present by noticing calls to the .add() method. It would be better to probe the ACPI namespace for the ASUS HIDs, and load the driver only when we find one, but ACPI doesn't support that yet. I don't have an ASUS laptop to test on, but on my HP dl360, it does report the appropriate error when attempting to load the module: $ sudo insmod drivers/acpi/asus_acpi.ko insmod: error inserting 'drivers/acpi/asus_acpi.ko': -1 No such device Signed-off-by: Bjorn Helgaas Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/asus_acpi.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c index f4c87750dbf..523fff9cf14 100644 --- a/drivers/acpi/asus_acpi.c +++ b/drivers/acpi/asus_acpi.c @@ -1119,6 +1119,8 @@ static int __init asus_hotk_check(void) return result; } +static int asus_hotk_found; + static int __init asus_hotk_add(struct acpi_device *device) { acpi_status status = AE_OK; @@ -1180,6 +1182,8 @@ static int __init asus_hotk_add(struct acpi_device *device) } } + asus_hotk_found = 1; + end: if (result) { kfree(hotk); @@ -1226,7 +1230,19 @@ static int __init asus_acpi_init(void) asus_proc_dir->owner = THIS_MODULE; result = acpi_bus_register_driver(&asus_hotk_driver); - if (result < 1) { + if (result < 0) { + remove_proc_entry(PROC_ASUS, acpi_root_dir); + return -ENODEV; + } + + /* + * This is a bit of a kludge. We only want this module loaded + * for ASUS systems, but there's currently no way to probe the + * ACPI namespace for ASUS HIDs. So we just return failure if + * we didn't find one, which will cause the module to be + * unloaded. + */ + if (!asus_hotk_found) { acpi_bus_unregister_driver(&asus_hotk_driver); remove_proc_entry(PROC_ASUS, acpi_root_dir); return -ENODEV; -- cgit v1.2.3 From e4513a57ef719d3d6d1cee0ca4d9f4016aa452bb Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 28 Mar 2006 17:04:00 -0500 Subject: ACPI: fix sonypi ACPI driver registration to unregister on failure Remove the assumption that acpi_bus_register_driver() returns the number of devices claimed. Returning the count is unreliable because devices may be hot-plugged in the future (admittedly not applicable for this driver). This also fixes a bug: if sonypi_acpi_driver was registered but found no devices, sonypi_exit() did not unregister it. Signed-off-by: Bjorn Helgaas Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/char/sonypi.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index f8dd8527c6a..81ce5515b41 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c @@ -512,7 +512,7 @@ static struct sonypi_device { #ifdef CONFIG_ACPI static struct acpi_device *sonypi_acpi_device; -static int acpi_enabled; +static int acpi_driver_registered; #endif static int sonypi_ec_write(u8 addr, u8 value) @@ -869,7 +869,7 @@ found: sonypi_report_input_event(event); #ifdef CONFIG_ACPI - if (acpi_enabled) + if (sonypi_acpi_device) acpi_bus_generate_event(sonypi_acpi_device, 1, event); #endif @@ -1548,8 +1548,8 @@ static int __init sonypi_init(void) goto err_free_device; #ifdef CONFIG_ACPI - if (acpi_bus_register_driver(&sonypi_acpi_driver) > 0) - acpi_enabled = 1; + if (acpi_bus_register_driver(&sonypi_acpi_driver) >= 0) + acpi_driver_registered = 1; #endif return 0; @@ -1564,7 +1564,7 @@ static int __init sonypi_init(void) static void __exit sonypi_exit(void) { #ifdef CONFIG_ACPI - if (acpi_enabled) + if (acpi_driver_registered) acpi_bus_unregister_driver(&sonypi_acpi_driver); #endif platform_device_unregister(sonypi_platform_device); -- cgit v1.2.3 From 1a36561607abf1405b56a41aac2fd163429cd1f8 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 28 Mar 2006 17:04:00 -0500 Subject: ACPI: simplify scan.c coding No functional changes; just remove leftover, unused "buffer" and simplify control flow (no need to remember error values and goto the end, when we can simply return the value directly). Signed-off-by: Bjorn Helgaas Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/scan.c | 36 +++++++++++++----------------------- 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index a0ab828b2cc..08ba85cab2d 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -234,12 +234,9 @@ static int acpi_bus_get_power_flags(struct acpi_device *device) int acpi_match_ids(struct acpi_device *device, char *ids) { - int error = 0; - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - if (device->flags.hardware_id) if (strstr(ids, device->pnp.hardware_id)) - goto Done; + return 0; if (device->flags.compatible_ids) { struct acpi_compatible_id_list *cid_list = device->pnp.cid_list; @@ -248,15 +245,10 @@ int acpi_match_ids(struct acpi_device *device, char *ids) /* compare multiple _CID entries against driver ids */ for (i = 0; i < cid_list->count; i++) { if (strstr(ids, cid_list->id[i].value)) - goto Done; + return 0; } } - error = -ENOENT; - - Done: - if (buffer.pointer) - acpi_os_free(buffer.pointer); - return error; + return -ENOENT; } static acpi_status @@ -645,21 +637,19 @@ EXPORT_SYMBOL(acpi_bus_register_driver); */ int acpi_bus_unregister_driver(struct acpi_driver *driver) { - int error = 0; - ACPI_FUNCTION_TRACE("acpi_bus_unregister_driver"); - if (driver) { - acpi_driver_detach(driver); + if (!driver) + return_VALUE(-EINVAL); - if (!atomic_read(&driver->references)) { - spin_lock(&acpi_device_lock); - list_del_init(&driver->node); - spin_unlock(&acpi_device_lock); - } - } else - error = -EINVAL; - return_VALUE(error); + acpi_driver_detach(driver); + + if (!atomic_read(&driver->references)) { + spin_lock(&acpi_device_lock); + list_del_init(&driver->node); + spin_unlock(&acpi_device_lock); + } + return_VALUE(0); } EXPORT_SYMBOL(acpi_bus_unregister_driver); -- cgit v1.2.3 From 459c7266d7a5c1730169258217e25fdd1b7ca854 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 28 Mar 2006 17:04:00 -0500 Subject: ACPI: fix memory hotplug range length handling Address space descriptors contain _MIN, _MAX, and _LEN. _MIN and _MAX are the bounds within which the region can be moved (this is clarified in Table 6-38 of the ACPI 3.0 spec). We should use _LEN to determine the size of the region, not _MAX - _MIN + 1. Signed-off-by: Bjorn Helgaas Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/acpi_memhotplug.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index d882bf87fa9..e0a95ba7237 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c @@ -74,7 +74,7 @@ struct acpi_memory_device { unsigned short caching; /* memory cache attribute */ unsigned short write_protect; /* memory read/write attribute */ u64 start_addr; /* Memory Range start physical addr */ - u64 end_addr; /* Memory Range end physical addr */ + u64 length; /* Memory Range length */ }; static int @@ -97,12 +97,11 @@ acpi_memory_get_device_resources(struct acpi_memory_device *mem_device) if (ACPI_SUCCESS(status)) { if (address64.resource_type == ACPI_MEMORY_RANGE) { /* Populate the structure */ - mem_device->caching = - address64.info.mem.caching; + mem_device->caching = address64.info.mem.caching; mem_device->write_protect = address64.info.mem.write_protect; mem_device->start_addr = address64.minimum; - mem_device->end_addr = address64.maximum; + mem_device->length = address64.address_length; } } @@ -199,8 +198,7 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device) * Tell the VM there is more memory here... * Note: Assume that this function returns zero on success */ - result = add_memory(mem_device->start_addr, - (mem_device->end_addr - mem_device->start_addr) + 1); + result = add_memory(mem_device->start_addr, mem_device->length); if (result) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "\nadd_memory failed\n")); mem_device->state = MEMORY_INVALID_STATE; @@ -249,7 +247,7 @@ static int acpi_memory_disable_device(struct acpi_memory_device *mem_device) { int result; u64 start = mem_device->start_addr; - u64 len = mem_device->end_addr - start + 1; + u64 len = mem_device->length; ACPI_FUNCTION_TRACE("acpi_memory_disable_device"); -- cgit v1.2.3 From 9224a867c497053842dc595e594ca6d32112221f Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 28 Mar 2006 17:04:00 -0500 Subject: HPET: fix ACPI memory range length handling ACPI address space descriptors contain _MIN, _MAX, and _LEN. _MIN and _MAX are the bounds within which the region can be moved (this is clarified in Table 6-38 of the ACPI 3.0 spec). We should use _LEN to determine the size of the region, not _MAX - _MIN + 1. Signed-off-by: Bjorn Helgaas Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/char/hpet.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index ef140ebde11..07473cd8412 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -925,11 +925,8 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data) status = acpi_resource_to_address64(res, &addr); if (ACPI_SUCCESS(status)) { - unsigned long size; - - size = addr.maximum - addr.minimum + 1; hdp->hd_phys_address = addr.minimum; - hdp->hd_address = ioremap(addr.minimum, size); + hdp->hd_address = ioremap(addr.minimum, addr.address_length); if (hpet_is_known(hdp)) { printk(KERN_DEBUG "%s: 0x%lx is busy\n", -- cgit v1.2.3 From 200739c179c63d21804e9e8e2ced265243831579 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 28 Mar 2006 17:04:00 -0500 Subject: ACPI: remove __init/__exit from Asus .add()/.remove() methods Even though the devices claimed by asus_acpi.c can not be hot-plugged, the driver registration infrastructure allows the .add() and .remove() methods to be called at any time while the driver is registered. So remove __init and __exit from them. Signed-off-by: Bjorn Helgaas Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/asus_acpi.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c index f4c87750dbf..3f3c392d6be 100644 --- a/drivers/acpi/asus_acpi.c +++ b/drivers/acpi/asus_acpi.c @@ -817,7 +817,7 @@ typedef int (proc_writefunc) (struct file * file, const char __user * buffer, unsigned long count, void *data); static int -__init asus_proc_add(char *name, proc_writefunc * writefunc, +asus_proc_add(char *name, proc_writefunc * writefunc, proc_readfunc * readfunc, mode_t mode, struct acpi_device *device) { @@ -836,7 +836,7 @@ __init asus_proc_add(char *name, proc_writefunc * writefunc, return 0; } -static int __init asus_hotk_add_fs(struct acpi_device *device) +static int asus_hotk_add_fs(struct acpi_device *device) { struct proc_dir_entry *proc; mode_t mode; @@ -954,7 +954,7 @@ static void asus_hotk_notify(acpi_handle handle, u32 event, void *data) * This function is used to initialize the hotk with right values. In this * method, we can make all the detection we want, and modify the hotk struct */ -static int __init asus_hotk_get_info(void) +static int asus_hotk_get_info(void) { struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; struct acpi_buffer dsdt = { ACPI_ALLOCATE_BUFFER, NULL }; @@ -1101,7 +1101,7 @@ static int __init asus_hotk_get_info(void) return AE_OK; } -static int __init asus_hotk_check(void) +static int asus_hotk_check(void) { int result = 0; @@ -1119,7 +1119,7 @@ static int __init asus_hotk_check(void) return result; } -static int __init asus_hotk_add(struct acpi_device *device) +static int asus_hotk_add(struct acpi_device *device) { acpi_status status = AE_OK; int result; -- cgit v1.2.3 From df42baa0d8e54df18dd9366dd7c93d6be7d5d063 Mon Sep 17 00:00:00 2001 From: Ashok Raj Date: Tue, 28 Mar 2006 17:04:00 -0500 Subject: ACPI: build fix for u8 cpu_index Local apic entries are only 8 bits, but it seemed to not be caught with u8 return value result in the check cpu_index >= NR_CPUS becomming always false. drivers/acpi/processor_core.c: In function `acpi_processor_get_info': drivers/acpi/processor_core.c:483: warning: comparison is always false due to limited range of data type Signed-off-by: Ashok Raj Cc: Dave Jones Cc: Kenji Kaneshige Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/processor_core.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 713b763884a..e5041c4f3c2 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -388,7 +388,7 @@ static int acpi_processor_remove_fs(struct acpi_device *device) /* Use the acpiid in MADT to map cpus in case of SMP */ #ifndef CONFIG_SMP -#define convert_acpiid_to_cpu(acpi_id) (0xff) +#define convert_acpiid_to_cpu(acpi_id) (-1) #else #ifdef CONFIG_IA64 @@ -401,7 +401,7 @@ static int acpi_processor_remove_fs(struct acpi_device *device) #define ARCH_BAD_APICID (0xff) #endif -static u8 convert_acpiid_to_cpu(u8 acpi_id) +static int convert_acpiid_to_cpu(u8 acpi_id) { u16 apic_id; int i; @@ -427,7 +427,7 @@ static int acpi_processor_get_info(struct acpi_processor *pr) acpi_status status = 0; union acpi_object object = { 0 }; struct acpi_buffer buffer = { sizeof(union acpi_object), &object }; - u8 cpu_index; + int cpu_index; static int cpu0_initialized; ACPI_FUNCTION_TRACE("acpi_processor_get_info"); @@ -473,7 +473,7 @@ static int acpi_processor_get_info(struct acpi_processor *pr) cpu_index = convert_acpiid_to_cpu(pr->acpi_id); /* Handle UP system running SMP kernel, with no LAPIC in MADT */ - if (!cpu0_initialized && (cpu_index == 0xff) && + if (!cpu0_initialized && (cpu_index == -1) && (num_online_cpus() == 1)) { cpu_index = 0; } @@ -487,7 +487,7 @@ static int acpi_processor_get_info(struct acpi_processor *pr) * less than the max # of CPUs. They should be ignored _iff * they are physically not present. */ - if (cpu_index >= NR_CPUS) { + if (cpu_index == -1) { if (ACPI_FAILURE (acpi_processor_hotadd_init(pr->handle, &pr->id))) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, -- cgit v1.2.3 From ff2fc3e9e3edb918b6c6b288485c6cb267bc865e Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Tue, 28 Mar 2006 17:04:00 -0500 Subject: ACPI: EC acpi-ecdt-uid-hack On some boxes ecdt uid may be equal to 0, so do not test for uids equality, so that fake handler will be unconditionally removed to allow loading the real one. See http://bugzilla.kernel.org/show_bug.cgi?id=6111 Signed-off-by: Jiri Slaby Cc: Luming Yu Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/ec.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index eee0864ba30..e638168775b 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -991,7 +991,6 @@ static int acpi_ec_poll_add(struct acpi_device *device) int result = 0; acpi_status status = AE_OK; union acpi_ec *ec = NULL; - unsigned long uid; ACPI_FUNCTION_TRACE("acpi_ec_add"); @@ -1014,10 +1013,9 @@ static int acpi_ec_poll_add(struct acpi_device *device) acpi_evaluate_integer(ec->common.handle, "_GLK", NULL, &ec->common.global_lock); - /* If our UID matches the UID for the ECDT-enumerated EC, - we now have the *real* EC info, so kill the makeshift one. */ - acpi_evaluate_integer(ec->common.handle, "_UID", NULL, &uid); - if (ec_ecdt && ec_ecdt->common.uid == uid) { + /* XXX we don't test uids, because on some boxes ecdt uid = 0, see: + http://bugzilla.kernel.org/show_bug.cgi?id=6111 */ + if (ec_ecdt) { acpi_remove_address_space_handler(ACPI_ROOT_OBJECT, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler); @@ -1062,7 +1060,6 @@ static int acpi_ec_intr_add(struct acpi_device *device) int result = 0; acpi_status status = AE_OK; union acpi_ec *ec = NULL; - unsigned long uid; ACPI_FUNCTION_TRACE("acpi_ec_add"); @@ -1088,10 +1085,9 @@ static int acpi_ec_intr_add(struct acpi_device *device) acpi_evaluate_integer(ec->common.handle, "_GLK", NULL, &ec->common.global_lock); - /* If our UID matches the UID for the ECDT-enumerated EC, - we now have the *real* EC info, so kill the makeshift one. */ - acpi_evaluate_integer(ec->common.handle, "_UID", NULL, &uid); - if (ec_ecdt && ec_ecdt->common.uid == uid) { + /* XXX we don't test uids, because on some boxes ecdt uid = 0, see: + http://bugzilla.kernel.org/show_bug.cgi?id=6111 */ + if (ec_ecdt) { acpi_remove_address_space_handler(ACPI_ROOT_OBJECT, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler); -- cgit v1.2.3 From eefa27a93a0490902f33837ac86dbcf344b3aa29 Mon Sep 17 00:00:00 2001 From: Ashok Raj Date: Tue, 28 Mar 2006 17:04:00 -0500 Subject: ACPI: Allow hot-add of ejected processor acpi_eject_store() didn't trim processors, causing subsequent hot-add to fail. Signed-off-by: Ashok Raj Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/scan.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index a0ab828b2cc..95d5bc2acad 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -441,10 +441,7 @@ acpi_eject_store(struct acpi_device *device, const char *buf, size_t count) islockable = device->flags.lockable; handle = device->handle; - if (type == ACPI_TYPE_PROCESSOR) - result = acpi_bus_trim(device, 0); - else - result = acpi_bus_trim(device, 1); + result = acpi_bus_trim(device, 1); if (!result) result = acpi_eject_operation(handle, islockable); -- cgit v1.2.3 From c12ea918ee175ceb3a258cd81f1c43e897d0c0bc Mon Sep 17 00:00:00 2001 From: Ashok Raj Date: Tue, 28 Mar 2006 17:04:00 -0500 Subject: x86_64: Remove stale lapic definition from apicdef.h Signed-off-by: Ashok Raj Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- include/asm-i386/apicdef.h | 1 - include/asm-x86_64/apicdef.h | 2 -- 2 files changed, 3 deletions(-) diff --git a/include/asm-i386/apicdef.h b/include/asm-i386/apicdef.h index 5e4a35af292..9f6995341fd 100644 --- a/include/asm-i386/apicdef.h +++ b/include/asm-i386/apicdef.h @@ -121,7 +121,6 @@ */ #define u32 unsigned int -#define lapic ((volatile struct local_apic *)APIC_BASE) struct local_apic { diff --git a/include/asm-x86_64/apicdef.h b/include/asm-x86_64/apicdef.h index 5a48e9bcf21..1dd40067c67 100644 --- a/include/asm-x86_64/apicdef.h +++ b/include/asm-x86_64/apicdef.h @@ -137,8 +137,6 @@ */ #define u32 unsigned int -#define lapic ((volatile struct local_apic *)APIC_BASE) - struct local_apic { /*000*/ struct { u32 __reserved[4]; } __reserved_01; -- cgit v1.2.3 From 7f048801f4a6767433d1aeefd9c24372515265f8 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Sat, 1 Apr 2006 23:45:39 -0500 Subject: ACPI: ia64 buildfix Signed-off-by: Len Brown --- drivers/char/agp/hp-agp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c index 8c4c6ef748e..907fb66ec4a 100644 --- a/drivers/char/agp/hp-agp.c +++ b/drivers/char/agp/hp-agp.c @@ -497,7 +497,7 @@ zx1_gart_probe (acpi_handle obj, u32 depth, void *context, void **ret) info = buffer.pointer; info->hardware_id.value[sizeof(info->hardware_id)-1] = '\0'; match = (strcmp(info->hardware_id.value, "HWP0001") == 0); - ACPI_MEM_FREE(info); + kfree(info); if (match) { status = hp_acpi_csr_space(handle, &sba_hpa, &length); if (ACPI_SUCCESS(status)) -- cgit v1.2.3 From 144c87b4e03759214c362d267e01c2905f1ab095 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Sun, 2 Apr 2006 00:15:39 -0500 Subject: ACPI: ia64 buildfix arch/ia64/hp/common/sba_iommu.c used ACPI_MEM_FREE instead of kfree() Signed-off-by: Len Brown Date: Sun, 2 Apr 2006 17:54:46 +0900 Subject: [PATCH] libata: implement ata_dev_absent() For the time being we cannot use ata_dev_present() as it was renamed to ata_dev_enabled() but we still need presence test. Implement negation of the test. Conveniently, the negated result is needed in more places. This is suggested by Jeff Garzik. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- include/linux/libata.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/include/linux/libata.h b/include/linux/libata.h index c6883ba8cba..0f8e3720edd 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -682,6 +682,11 @@ static inline unsigned int ata_class_disabled(unsigned int class) return class == ATA_DEV_ATA_UNSUP || class == ATA_DEV_ATAPI_UNSUP; } +static inline unsigned int ata_class_absent(unsigned int class) +{ + return !ata_class_enabled(class) && !ata_class_disabled(class); +} + static inline unsigned int ata_dev_enabled(const struct ata_device *dev) { return ata_class_enabled(dev->class); @@ -692,6 +697,11 @@ static inline unsigned int ata_dev_disabled(const struct ata_device *dev) return ata_class_disabled(dev->class); } +static inline unsigned int ata_dev_absent(const struct ata_device *dev) +{ + return ata_class_absent(dev->class); +} + static inline u8 ata_chk_status(struct ata_port *ap) { return ap->ops->check_status(ap); -- cgit v1.2.3 From 1c3fae4d7eb121933341443c37d3bbee43c0fb68 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 2 Apr 2006 20:53:28 +0900 Subject: [PATCH] libata: implement ap->sata_spd_limit and helpers ap->sata_spd_limit contrains SATA PHY speed of the port. It is initialized to the configured value prior to probing thus preserving BIOS configured value. hardreset is responsible for applying SPD limit and sata_std_hardreset() is updated to do that. SATA SPD limit will be used to enhance failure handling during probing and later by EH. This patch also normalizes some comments around affected code. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 143 +++++++++++++++++++++++++++++++++++++++++++-- include/linux/libata.h | 1 + 2 files changed, 140 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 3acf56200d8..63488673765 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -65,6 +65,7 @@ static unsigned int ata_dev_init_params(struct ata_port *ap, struct ata_device *dev, u16 heads, u16 sectors); +static int ata_down_sata_spd_limit(struct ata_port *ap); static int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev); static unsigned int ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev); @@ -1596,6 +1597,120 @@ void ata_port_disable(struct ata_port *ap) ap->flags |= ATA_FLAG_PORT_DISABLED; } +/** + * ata_down_sata_spd_limit - adjust SATA spd limit downward + * @ap: Port to adjust SATA spd limit for + * + * Adjust SATA spd limit of @ap downward. Note that this + * function only adjusts the limit. The change must be applied + * using ata_set_sata_spd(). + * + * LOCKING: + * Inherited from caller. + * + * RETURNS: + * 0 on success, negative errno on failure + */ +static int ata_down_sata_spd_limit(struct ata_port *ap) +{ + u32 spd, mask; + int highbit; + + if (ap->cbl != ATA_CBL_SATA || !ap->ops->scr_read) + return -EOPNOTSUPP; + + mask = ap->sata_spd_limit; + if (mask <= 1) + return -EINVAL; + highbit = fls(mask) - 1; + mask &= ~(1 << highbit); + + spd = (scr_read(ap, SCR_STATUS) >> 4) & 0xf; + if (spd <= 1) + return -EINVAL; + spd--; + mask &= (1 << spd) - 1; + if (!mask) + return -EINVAL; + + ap->sata_spd_limit = mask; + + printk(KERN_WARNING "ata%u: limiting SATA link speed to %s\n", + ap->id, sata_spd_string(fls(mask))); + + return 0; +} + +static int __ata_set_sata_spd_needed(struct ata_port *ap, u32 *scontrol) +{ + u32 spd, limit; + + if (ap->sata_spd_limit == UINT_MAX) + limit = 0; + else + limit = fls(ap->sata_spd_limit); + + spd = (*scontrol >> 4) & 0xf; + *scontrol = (*scontrol & ~0xf0) | ((limit & 0xf) << 4); + + return spd != limit; +} + +/** + * ata_set_sata_spd_needed - is SATA spd configuration needed + * @ap: Port in question + * + * Test whether the spd limit in SControl matches + * @ap->sata_spd_limit. This function is used to determine + * whether hardreset is necessary to apply SATA spd + * configuration. + * + * LOCKING: + * Inherited from caller. + * + * RETURNS: + * 1 if SATA spd configuration is needed, 0 otherwise. + */ +static int ata_set_sata_spd_needed(struct ata_port *ap) +{ + u32 scontrol; + + if (ap->cbl != ATA_CBL_SATA || !ap->ops->scr_read) + return 0; + + scontrol = scr_read(ap, SCR_CONTROL); + + return __ata_set_sata_spd_needed(ap, &scontrol); +} + +/** + * ata_set_sata_spd - set SATA spd according to spd limit + * @ap: Port to set SATA spd for + * + * Set SATA spd of @ap according to sata_spd_limit. + * + * LOCKING: + * Inherited from caller. + * + * RETURNS: + * 0 if spd doesn't need to be changed, 1 if spd has been + * changed. -EOPNOTSUPP if SCR registers are inaccessible. + */ +static int ata_set_sata_spd(struct ata_port *ap) +{ + u32 scontrol; + + if (ap->cbl != ATA_CBL_SATA || !ap->ops->scr_read) + return -EOPNOTSUPP; + + scontrol = scr_read(ap, SCR_CONTROL); + if (!__ata_set_sata_spd_needed(ap, &scontrol)) + return 0; + + scr_write(ap, SCR_CONTROL, scontrol); + return 1; +} + /* * This mode timing computation functionality is ported over from * drivers/ide/ide-timing.h and was originally written by Vojtech Pavlik @@ -2165,7 +2280,14 @@ static int sata_phy_resume(struct ata_port *ap) void ata_std_probeinit(struct ata_port *ap) { if ((ap->flags & ATA_FLAG_SATA) && ap->ops->scr_read) { + u32 spd; + sata_phy_resume(ap); + + spd = (scr_read(ap, SCR_CONTROL) & 0xf0) >> 4; + if (spd) + ap->sata_spd_limit &= (1 << spd) - 1; + if (sata_dev_present(ap)) ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT); } @@ -2253,18 +2375,30 @@ int sata_std_hardreset(struct ata_port *ap, int verbose, unsigned int *class) DPRINTK("ENTER\n"); - /* Issue phy wake/reset */ + if (ata_set_sata_spd_needed(ap)) { + /* SATA spec says nothing about how to reconfigure + * spd. To be on the safe side, turn off phy during + * reconfiguration. This works for at least ICH7 AHCI + * and Sil3124. + */ + scontrol = scr_read(ap, SCR_CONTROL); + scontrol = (scontrol & 0x0f0) | 0x302; + scr_write_flush(ap, SCR_CONTROL, scontrol); + + ata_set_sata_spd(ap); + } + + /* issue phy wake/reset */ scontrol = scr_read(ap, SCR_CONTROL); scontrol = (scontrol & 0x0f0) | 0x301; scr_write_flush(ap, SCR_CONTROL, scontrol); - /* - * Couldn't find anything in SATA I/II specs, but AHCI-1.1 + /* Couldn't find anything in SATA I/II specs, but AHCI-1.1 * 10.4.2 says at least 1 ms. */ msleep(1); - /* Bring phy back */ + /* bring phy back */ sata_phy_resume(ap); /* TODO: phy layer with polling, timeouts, etc. */ @@ -4454,6 +4588,7 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host, ap->flags |= ent->host_flags; ap->ops = ent->port_ops; ap->cbl = ATA_CBL_NONE; + ap->sata_spd_limit = UINT_MAX; ap->active_tag = ATA_TAG_POISON; ap->last_ctl = 0xFF; diff --git a/include/linux/libata.h b/include/linux/libata.h index 0f8e3720edd..a5207e66ca5 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -397,6 +397,7 @@ struct ata_port { unsigned int mwdma_mask; unsigned int udma_mask; unsigned int cbl; /* cable type; ATA_CBL_xxx */ + unsigned int sata_spd_limit; /* SATA PHY speed limit */ struct ata_device device[ATA_MAX_DEVICES]; -- cgit v1.2.3 From 90dac02c08dabd471927f151b8393eb51e3e020e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 2 Apr 2006 17:54:46 +0900 Subject: [PATCH] libata: use SATA speed down in ata_drive_probe_reset() Make ata_drive_probe_reset() use SATA SPD configuration. Hardreset will be force if speed renegotiation is necessary. Also, if a hardreset fails, PHY speed is stepped down and hardreset is retried until the lowest speed is reached. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 63488673765..4fd24075afd 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2578,7 +2578,7 @@ int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, if (probeinit) probeinit(ap); - if (softreset) { + if (softreset && !ata_set_sata_spd_needed(ap)) { rc = ata_do_reset(ap, softreset, postreset, 0, classes); if (rc == 0 && classes[0] != ATA_DEV_UNKNOWN) goto done; @@ -2587,9 +2587,17 @@ int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, if (!hardreset) goto done; - rc = ata_do_reset(ap, hardreset, postreset, 0, classes); - if (rc || classes[0] != ATA_DEV_UNKNOWN) - goto done; + while (1) { + rc = ata_do_reset(ap, hardreset, postreset, 0, classes); + if (rc == 0) { + if (classes[0] != ATA_DEV_UNKNOWN) + goto done; + break; + } + + if (ata_down_sata_spd_limit(ap)) + goto done; + } if (softreset) rc = ata_do_reset(ap, softreset, postreset, 0, classes); -- cgit v1.2.3 From edbabd8679a39faef67def4438c9cbccb5c05c5d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 2 Apr 2006 20:55:02 +0900 Subject: [PATCH] libata: add 5s sleep between resets Some devices react badly if resets are performed back-to-back. Give devices some time to breath and tell user that we're taking a nap. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 4fd24075afd..3ddfbe1b86c 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2582,6 +2582,9 @@ int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, rc = ata_do_reset(ap, softreset, postreset, 0, classes); if (rc == 0 && classes[0] != ATA_DEV_UNKNOWN) goto done; + printk(KERN_INFO "ata%u: softreset failed, will try " + "hardreset in 5 secs\n", ap->id); + ssleep(5); } if (!hardreset) @@ -2597,10 +2600,20 @@ int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, if (ata_down_sata_spd_limit(ap)) goto done; + + printk(KERN_INFO "ata%u: hardreset failed, will retry " + "in 5 secs\n", ap->id); + ssleep(5); } - if (softreset) + if (softreset) { + printk(KERN_INFO "ata%u: hardreset succeeded without " + "classification, will retry softreset in 5 secs\n", + ap->id); + ssleep(5); + rc = ata_do_reset(ap, softreset, postreset, 0, classes); + } done: if (rc == 0 && classes[0] == ATA_DEV_UNKNOWN) -- cgit v1.2.3 From cf176e1aa92eb2a3faea8409e841396a66413937 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 2 Apr 2006 17:54:46 +0900 Subject: [PATCH] libata: implement ata_down_xfermask_limit() Implement ata_down_xfermask_limit(). This function manipulates @dev->pio/mwdma/udma_mask such that the next lower transfer mode is selected. This will be used to improve ata_bus_probe() failure handling and later by EH. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 3ddfbe1b86c..68fa64d2472 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -65,6 +65,8 @@ static unsigned int ata_dev_init_params(struct ata_port *ap, struct ata_device *dev, u16 heads, u16 sectors); +static int ata_down_xfermask_limit(struct ata_port *ap, struct ata_device *dev, + int force_pio0); static int ata_down_sata_spd_limit(struct ata_port *ap); static int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev); static unsigned int ata_dev_set_xfermode(struct ata_port *ap, @@ -1859,6 +1861,56 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed, return 0; } +/** + * ata_down_xfermask_limit - adjust dev xfer masks downward + * @ap: Port associated with device @dev + * @dev: Device to adjust xfer masks + * @force_pio0: Force PIO0 + * + * Adjust xfer masks of @dev downward. Note that this function + * does not apply the change. Invoking ata_set_mode() afterwards + * will apply the limit. + * + * LOCKING: + * Inherited from caller. + * + * RETURNS: + * 0 on success, negative errno on failure + */ +static int ata_down_xfermask_limit(struct ata_port *ap, struct ata_device *dev, + int force_pio0) +{ + unsigned long xfer_mask; + int highbit; + + xfer_mask = ata_pack_xfermask(dev->pio_mask, dev->mwdma_mask, + dev->udma_mask); + + if (!xfer_mask) + goto fail; + /* don't gear down to MWDMA from UDMA, go directly to PIO */ + if (xfer_mask & ATA_MASK_UDMA) + xfer_mask &= ~ATA_MASK_MWDMA; + + highbit = fls(xfer_mask) - 1; + xfer_mask &= ~(1 << highbit); + if (force_pio0) + xfer_mask &= 1 << ATA_SHIFT_PIO; + if (!xfer_mask) + goto fail; + + ata_unpack_xfermask(xfer_mask, &dev->pio_mask, &dev->mwdma_mask, + &dev->udma_mask); + + printk(KERN_WARNING "ata%u: dev %u limiting speed to %s\n", + ap->id, dev->devno, ata_mode_string(xfer_mask)); + + return 0; + + fail: + return -EINVAL; +} + static int ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev) { unsigned int err_mask; -- cgit v1.2.3 From 14d2bac1877ed4e2cc940d1680db1a4f29225811 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 2 Apr 2006 17:54:46 +0900 Subject: [PATCH] libata: improve ata_bus_probe() Improve ata_bus_probe() such that configuration failures are handled better. Each device is given ATA_PROBE_MAX_TRIES chances, but any non-transient error (revalidation failure with -ENODEV, configuration failure with -EINVAL...) disables the device directly. Any IO error results in SATA PHY speed down and ata_set_mode() failure lowers transfer mode. The last try always puts a device into PIO-0. After each failure, the whole port is reset to make sure that the controller and all the devices are in a known and stable state. The reset also applies SATA SPD configuration if necessary. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 65 ++++++++++++++++++++++++++++++++++------------ include/linux/libata.h | 3 +++ 2 files changed, 52 insertions(+), 16 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 68fa64d2472..33b5bff58cc 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1370,11 +1370,18 @@ err_out_nosup: static int ata_bus_probe(struct ata_port *ap) { unsigned int classes[ATA_MAX_DEVICES]; - int i, rc, found = 0; + int tries[ATA_MAX_DEVICES]; + int i, rc, down_xfermask; struct ata_device *dev; ata_port_probe(ap); + for (i = 0; i < ATA_MAX_DEVICES; i++) + tries[i] = ATA_PROBE_MAX_TRIES; + + retry: + down_xfermask = 0; + /* reset and determine device classes */ for (i = 0; i < ATA_MAX_DEVICES; i++) classes[i] = ATA_DEV_UNKNOWN; @@ -1404,21 +1411,23 @@ static int ata_bus_probe(struct ata_port *ap) dev = &ap->device[i]; dev->class = classes[i]; - if (!ata_dev_enabled(dev)) - continue; - - WARN_ON(dev->id != NULL); - if (ata_dev_read_id(ap, dev, &dev->class, 1, &dev->id)) { - dev->class = ATA_DEV_NONE; - continue; + if (!tries[i]) { + ata_down_xfermask_limit(ap, dev, 1); + ata_dev_disable(ap, dev); } - if (ata_dev_configure(ap, dev, 1)) { - ata_dev_disable(ap, dev); + if (!ata_dev_enabled(dev)) continue; - } - found = 1; + kfree(dev->id); + dev->id = NULL; + rc = ata_dev_read_id(ap, dev, &dev->class, 1, &dev->id); + if (rc) + goto fail; + + rc = ata_dev_configure(ap, dev, 1); + if (rc) + goto fail; } /* configure transfer mode */ @@ -1427,12 +1436,18 @@ static int ata_bus_probe(struct ata_port *ap) * return error code and failing device on failure as * ata_set_mode() does. */ - if (found) - ap->ops->set_mode(ap); + for (i = 0; i < ATA_MAX_DEVICES; i++) + if (ata_dev_enabled(&ap->device[i])) { + ap->ops->set_mode(ap); + break; + } rc = 0; } else { - while (ata_set_mode(ap, &dev)) - ata_dev_disable(ap, dev); + rc = ata_set_mode(ap, &dev); + if (rc) { + down_xfermask = 1; + goto fail; + } } for (i = 0; i < ATA_MAX_DEVICES; i++) @@ -1443,6 +1458,24 @@ static int ata_bus_probe(struct ata_port *ap) ata_port_disable(ap); ap->ops->port_disable(ap); return -ENODEV; + + fail: + switch (rc) { + case -EINVAL: + case -ENODEV: + tries[dev->devno] = 0; + break; + case -EIO: + ata_down_sata_spd_limit(ap); + /* fall through */ + default: + tries[dev->devno]--; + if (down_xfermask && + ata_down_xfermask_limit(ap, dev, tries[dev->devno] == 1)) + tries[dev->devno] = 0; + } + + goto retry; } /** diff --git a/include/linux/libata.h b/include/linux/libata.h index a5207e66ca5..a4a1e6304e7 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -211,6 +211,9 @@ enum { /* Masks for port functions */ ATA_PORT_PRIMARY = (1 << 0), ATA_PORT_SECONDARY = (1 << 1), + + /* how hard are we gonna try to probe/recover devices */ + ATA_PROBE_MAX_TRIES = 3, }; enum hsm_task_states { -- cgit v1.2.3 From 565083e1f14e7771aa6bac2d3d4aae0b08d48d78 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 2 Apr 2006 17:54:47 +0900 Subject: [PATCH] libata: consider disabled devices in ata_dev_xfermask() ata_bus_probe() now marks failed devices properly and leaves meaningful transfer mode masks. This patch makes ata_dev_xfermask() consider disable devices when determining PIO mode to avoid violating device selection timing. While at it, move port-wide resttriction out of device iteration loop and try to make the function look a bit prettier. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 33b5bff58cc..00018705582 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2913,23 +2913,34 @@ static void ata_dev_xfermask(struct ata_port *ap, struct ata_device *dev) unsigned long xfer_mask; int i; - xfer_mask = ata_pack_xfermask(ap->pio_mask, ap->mwdma_mask, - ap->udma_mask); + xfer_mask = ata_pack_xfermask(ap->pio_mask, + ap->mwdma_mask, ap->udma_mask); + + /* Apply cable rule here. Don't apply it early because when + * we handle hot plug the cable type can itself change. + */ + if (ap->cbl == ATA_CBL_PATA40) + xfer_mask &= ~(0xF8 << ATA_SHIFT_UDMA); /* FIXME: Use port-wide xfermask for now */ for (i = 0; i < ATA_MAX_DEVICES; i++) { struct ata_device *d = &ap->device[i]; - if (!ata_dev_enabled(d)) + + if (ata_dev_absent(d)) + continue; + + if (ata_dev_disabled(d)) { + /* to avoid violating device selection timing */ + xfer_mask &= ata_pack_xfermask(d->pio_mask, + UINT_MAX, UINT_MAX); continue; - xfer_mask &= ata_pack_xfermask(d->pio_mask, d->mwdma_mask, - d->udma_mask); + } + + xfer_mask &= ata_pack_xfermask(d->pio_mask, + d->mwdma_mask, d->udma_mask); xfer_mask &= ata_id_xfermask(d->id); if (ata_dma_blacklisted(d)) xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); - /* Apply cable rule here. Don't apply it early because when - we handle hot plug the cable type can itself change */ - if (ap->cbl == ATA_CBL_PATA40) - xfer_mask &= ~(0xF8 << ATA_SHIFT_UDMA); } if (ata_dma_blacklisted(dev)) @@ -2940,11 +2951,12 @@ static void ata_dev_xfermask(struct ata_port *ap, struct ata_device *dev) if (hs->simplex_claimed) xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); } + if (ap->ops->mode_filter) xfer_mask = ap->ops->mode_filter(ap, dev, xfer_mask); - ata_unpack_xfermask(xfer_mask, &dev->pio_mask, &dev->mwdma_mask, - &dev->udma_mask); + ata_unpack_xfermask(xfer_mask, &dev->pio_mask, + &dev->mwdma_mask, &dev->udma_mask); } /** -- cgit v1.2.3 From d63cb4a6365aa161341fc365df1edc87cd00c9c0 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 2 Apr 2006 18:51:52 +0900 Subject: [PATCH] libata: report device number when PIO fails Report device number on PIO failure. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 00018705582..15d6c24c8e5 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3909,7 +3909,8 @@ static void ata_pio_error(struct ata_port *ap) WARN_ON(qc == NULL); if (qc->tf.command != ATA_CMD_PACKET) - printk(KERN_WARNING "ata%u: PIO error\n", ap->id); + printk(KERN_WARNING "ata%u: dev %u PIO error\n", + ap->id, qc->dev->devno); /* make sure qc->err_mask is available to * know what's wrong and recover -- cgit v1.2.3 From 5eb45c02a9944e813a0b82457607557a1f2c64b5 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 2 Apr 2006 18:51:52 +0900 Subject: [PATCH] libata: ata_dev_revalidate() printk update Make sure ata_dev_revalidate() complains on failures and kill revalidation failure message printed from ata_dev_set_mode(). Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 15d6c24c8e5..f39352a3ac1 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1961,12 +1961,8 @@ static int ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev) } rc = ata_dev_revalidate(ap, dev, 0); - if (rc) { - printk(KERN_ERR - "ata%u: failed to revalidate after set xfermode\n", - ap->id); + if (rc) return rc; - } DPRINTK("xfer_shift=%u, xfer_mode=0x%x\n", dev->xfer_shift, (int)dev->xfer_mode); @@ -2786,15 +2782,14 @@ static int ata_dev_same_device(struct ata_port *ap, struct ata_device *dev, int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev, int post_reset) { - unsigned int class; - u16 *id; + unsigned int class = dev->class; + u16 *id = NULL; int rc; - if (!ata_dev_enabled(dev)) - return -ENODEV; - - class = dev->class; - id = NULL; + if (!ata_dev_enabled(dev)) { + rc = -ENODEV; + goto fail; + } /* allocate & read ID data */ rc = ata_dev_read_id(ap, dev, &class, post_reset, &id); @@ -2811,7 +2806,9 @@ int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev, dev->id = id; /* configure device according to the new ID */ - return ata_dev_configure(ap, dev, 0); + rc = ata_dev_configure(ap, dev, 0); + if (rc == 0) + return 0; fail: printk(KERN_ERR "ata%u: dev %u revalidation failed (errno=%d)\n", -- cgit v1.2.3 From c43c555c3a6db7f0b55fd9b66d7ecff16e827d4e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 2 Apr 2006 18:51:52 +0900 Subject: [PATCH] libata: ATA_FLAG_IN_EH is not used, kill it Kill unused flag ATA_FLAG_IN_EH. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-scsi.c | 17 ++++------------- include/linux/libata.h | 1 - 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index c1a4b29a9ae..bcbf71e9895 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -779,20 +779,15 @@ enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd) int ata_scsi_error(struct Scsi_Host *host) { - struct ata_port *ap; - unsigned long flags; + struct ata_port *ap = (struct ata_port *)&host->hostdata[0]; DPRINTK("ENTER\n"); - ap = (struct ata_port *) &host->hostdata[0]; + /* synchronize with IRQ handler and port task */ + spin_unlock_wait(&ap->host_set->lock); + ata_port_flush_task(ap); - spin_lock_irqsave(&ap->host_set->lock, flags); - WARN_ON(ap->flags & ATA_FLAG_IN_EH); - ap->flags |= ATA_FLAG_IN_EH; WARN_ON(ata_qc_from_tag(ap, ap->active_tag) == NULL); - spin_unlock_irqrestore(&ap->host_set->lock, flags); - - ata_port_flush_task(ap); ap->ops->eng_timeout(ap); @@ -800,10 +795,6 @@ int ata_scsi_error(struct Scsi_Host *host) scsi_eh_flush_done_q(&ap->eh_done_q); - spin_lock_irqsave(&ap->host_set->lock, flags); - ap->flags &= ~ATA_FLAG_IN_EH; - spin_unlock_irqrestore(&ap->host_set->lock, flags); - DPRINTK("EXIT\n"); return 0; } diff --git a/include/linux/libata.h b/include/linux/libata.h index a4a1e6304e7..e20b0bfbd5f 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -152,7 +152,6 @@ enum { ATA_FLAG_IRQ_MASK = (1 << 14), /* Mask IRQ in PIO xfers */ ATA_FLAG_FLUSH_PORT_TASK = (1 << 15), /* Flush port task */ - ATA_FLAG_IN_EH = (1 << 16), /* EH in progress */ ATA_QCFLAG_ACTIVE = (1 << 1), /* cmd not yet ack'd to scsi lyer */ ATA_QCFLAG_SG = (1 << 3), /* have s/g table? */ -- cgit v1.2.3 From 949b38af40a0b88b7267908b1554a45b97b5b737 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 2 Apr 2006 18:51:52 +0900 Subject: [PATCH] libata: clean up constants * Reorder ATA_DFLAG_* such that feature flags determined by ata_dev_configure() are on lower bits. Reserve lower eight bits for this purpose and allocate dynamic flags from bit 8. * Reorder ATA_FLAG_* such that feature flags determined during driver initiailization are on bits 0:15, dynamic flags on 16:23 and LLDD specific flags on 24:31. * Kill trailing white space and lower-case an one line comment for consistency. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- include/linux/libata.h | 61 ++++++++++++++++++++++++++------------------------ 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/include/linux/libata.h b/include/linux/libata.h index e20b0bfbd5f..b7488a31e32 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -120,9 +120,10 @@ enum { ATA_SHT_USE_CLUSTERING = 1, /* struct ata_device stuff */ - ATA_DFLAG_LBA48 = (1 << 0), /* device supports LBA48 */ - ATA_DFLAG_PIO = (1 << 1), /* device currently in PIO mode */ - ATA_DFLAG_LBA = (1 << 2), /* device supports LBA */ + ATA_DFLAG_LBA = (1 << 0), /* device supports LBA */ + ATA_DFLAG_LBA48 = (1 << 1), /* device supports LBA48 */ + + ATA_DFLAG_PIO = (1 << 8), /* device currently in PIO mode */ ATA_DEV_UNKNOWN = 0, /* unknown device */ ATA_DEV_ATA = 1, /* ATA device */ @@ -132,32 +133,34 @@ enum { ATA_DEV_NONE = 5, /* no device */ /* struct ata_port flags */ - ATA_FLAG_SLAVE_POSS = (1 << 1), /* host supports slave dev */ + ATA_FLAG_SLAVE_POSS = (1 << 0), /* host supports slave dev */ /* (doesn't imply presence) */ - ATA_FLAG_PORT_DISABLED = (1 << 2), /* port is disabled, ignore it */ - ATA_FLAG_SATA = (1 << 3), - ATA_FLAG_NO_LEGACY = (1 << 4), /* no legacy mode check */ - ATA_FLAG_SRST = (1 << 5), /* (obsolete) use ATA SRST, not E.D.D. */ - ATA_FLAG_MMIO = (1 << 6), /* use MMIO, not PIO */ - ATA_FLAG_SATA_RESET = (1 << 7), /* (obsolete) use COMRESET */ - ATA_FLAG_PIO_DMA = (1 << 8), /* PIO cmds via DMA */ - ATA_FLAG_NOINTR = (1 << 9), /* FIXME: Remove this once - * proper HSM is in place. */ - ATA_FLAG_DEBUGMSG = (1 << 10), - ATA_FLAG_NO_ATAPI = (1 << 11), /* No ATAPI support */ - - ATA_FLAG_SUSPENDED = (1 << 12), /* port is suspended */ - - ATA_FLAG_PIO_LBA48 = (1 << 13), /* Host DMA engine is LBA28 only */ - ATA_FLAG_IRQ_MASK = (1 << 14), /* Mask IRQ in PIO xfers */ - - ATA_FLAG_FLUSH_PORT_TASK = (1 << 15), /* Flush port task */ - - ATA_QCFLAG_ACTIVE = (1 << 1), /* cmd not yet ack'd to scsi lyer */ - ATA_QCFLAG_SG = (1 << 3), /* have s/g table? */ - ATA_QCFLAG_SINGLE = (1 << 4), /* no s/g, just a single buffer */ + ATA_FLAG_SATA = (1 << 1), + ATA_FLAG_NO_LEGACY = (1 << 2), /* no legacy mode check */ + ATA_FLAG_MMIO = (1 << 3), /* use MMIO, not PIO */ + ATA_FLAG_SRST = (1 << 4), /* (obsolete) use ATA SRST, not E.D.D. */ + ATA_FLAG_SATA_RESET = (1 << 5), /* (obsolete) use COMRESET */ + ATA_FLAG_NO_ATAPI = (1 << 6), /* No ATAPI support */ + ATA_FLAG_PIO_DMA = (1 << 7), /* PIO cmds via DMA */ + ATA_FLAG_PIO_LBA48 = (1 << 8), /* Host DMA engine is LBA28 only */ + ATA_FLAG_IRQ_MASK = (1 << 9), /* Mask IRQ in PIO xfers */ + + ATA_FLAG_NOINTR = (1 << 16), /* FIXME: Remove this once + * proper HSM is in place. */ + ATA_FLAG_DEBUGMSG = (1 << 17), + ATA_FLAG_FLUSH_PORT_TASK = (1 << 18), /* flush port task */ + + ATA_FLAG_PORT_DISABLED = (1 << 19), /* port is disabled, ignore it */ + ATA_FLAG_SUSPENDED = (1 << 20), /* port is suspended */ + + /* bits 24:31 of ap->flags are reserved for LLDD specific flags */ + + /* struct ata_queued_cmd flags */ + ATA_QCFLAG_ACTIVE = (1 << 0), /* cmd not yet ack'd to scsi lyer */ + ATA_QCFLAG_SG = (1 << 1), /* have s/g table? */ + ATA_QCFLAG_SINGLE = (1 << 2), /* no s/g, just a single buffer */ ATA_QCFLAG_DMAMAP = ATA_QCFLAG_SG | ATA_QCFLAG_SINGLE, - ATA_QCFLAG_EH_SCHEDULED = (1 << 5), /* EH scheduled */ + ATA_QCFLAG_EH_SCHEDULED = (1 << 3), /* EH scheduled */ /* host set flags */ ATA_HOST_SIMPLEX = (1 << 0), /* Host is simplex, one DMA channel per host_set only */ @@ -206,8 +209,8 @@ enum { /* size of buffer to pad xfers ending on unaligned boundaries */ ATA_DMA_PAD_SZ = 4, ATA_DMA_PAD_BUF_SZ = ATA_DMA_PAD_SZ * ATA_MAX_QUEUE, - - /* Masks for port functions */ + + /* masks for port functions */ ATA_PORT_PRIMARY = (1 << 0), ATA_PORT_SECONDARY = (1 << 1), -- cgit v1.2.3 From 198e0fed9e59461fc1890dd8b75ec72d14638873 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 2 Apr 2006 18:51:52 +0900 Subject: [PATCH] libata: rename ATA_FLAG_PORT_DISABLED to ATA_FLAG_DISABLED Rename ATA_FLAG_PORT_DISABLED to ATA_FLAG_DISABLED for consistency. (ATA_FLAG_* are always about ports). Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 18 +++++++++--------- drivers/scsi/libata-scsi.c | 2 +- drivers/scsi/pdc_adma.c | 4 ++-- drivers/scsi/sata_mv.c | 2 +- drivers/scsi/sata_nv.c | 2 +- drivers/scsi/sata_promise.c | 2 +- drivers/scsi/sata_qstor.c | 4 ++-- drivers/scsi/sata_sil24.c | 2 +- drivers/scsi/sata_sx4.c | 2 +- drivers/scsi/sata_vsc.c | 2 +- include/linux/libata.h | 2 +- 11 files changed, 21 insertions(+), 21 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index f39352a3ac1..53226b16355 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1045,7 +1045,7 @@ ata_exec_internal(struct ata_port *ap, struct ata_device *dev, * * Kill the following code as soon as those drivers are fixed. */ - if (ap->flags & ATA_FLAG_PORT_DISABLED) { + if (ap->flags & ATA_FLAG_DISABLED) { err_mask |= AC_ERR_SYSTEM; ata_port_probe(ap); } @@ -1395,7 +1395,7 @@ static int ata_bus_probe(struct ata_port *ap) } else { ap->ops->phy_reset(ap); - if (!(ap->flags & ATA_FLAG_PORT_DISABLED)) + if (!(ap->flags & ATA_FLAG_DISABLED)) for (i = 0; i < ATA_MAX_DEVICES; i++) classes[i] = ap->device[i].class; @@ -1491,7 +1491,7 @@ static int ata_bus_probe(struct ata_port *ap) void ata_port_probe(struct ata_port *ap) { - ap->flags &= ~ATA_FLAG_PORT_DISABLED; + ap->flags &= ~ATA_FLAG_DISABLED; } /** @@ -1565,7 +1565,7 @@ void __sata_phy_reset(struct ata_port *ap) else ata_port_disable(ap); - if (ap->flags & ATA_FLAG_PORT_DISABLED) + if (ap->flags & ATA_FLAG_DISABLED) return; if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) { @@ -1590,7 +1590,7 @@ void __sata_phy_reset(struct ata_port *ap) void sata_phy_reset(struct ata_port *ap) { __sata_phy_reset(ap); - if (ap->flags & ATA_FLAG_PORT_DISABLED) + if (ap->flags & ATA_FLAG_DISABLED) return; ata_bus_reset(ap); } @@ -1629,7 +1629,7 @@ void ata_port_disable(struct ata_port *ap) { ap->device[0].class = ATA_DEV_NONE; ap->device[1].class = ATA_DEV_NONE; - ap->flags |= ATA_FLAG_PORT_DISABLED; + ap->flags |= ATA_FLAG_DISABLED; } /** @@ -2251,7 +2251,7 @@ static unsigned int ata_bus_softreset(struct ata_port *ap, * Obtains host_set lock. * * SIDE EFFECTS: - * Sets ATA_FLAG_PORT_DISABLED if bus reset fails. + * Sets ATA_FLAG_DISABLED if bus reset fails. */ void ata_bus_reset(struct ata_port *ap) @@ -4468,7 +4468,7 @@ irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs) ap = host_set->ports[i]; if (ap && - !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) { + !(ap->flags & (ATA_FLAG_DISABLED | ATA_FLAG_NOINTR))) { struct ata_queued_cmd *qc; qc = ata_qc_from_tag(ap, ap->active_tag); @@ -4689,7 +4689,7 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host, host->unique_id = ata_unique_id++; host->max_cmd_len = 12; - ap->flags = ATA_FLAG_PORT_DISABLED; + ap->flags = ATA_FLAG_DISABLED; ap->id = host->unique_id; ap->host = host; ap->ctl = ATA_DEVCTL_OBS; diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index bcbf71e9895..096bdffbde1 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -2728,7 +2728,7 @@ void ata_scsi_scan_host(struct ata_port *ap) struct ata_device *dev; unsigned int i; - if (ap->flags & ATA_FLAG_PORT_DISABLED) + if (ap->flags & ATA_FLAG_DISABLED) return; for (i = 0; i < ATA_MAX_DEVICES; i++) { diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c index 3c85c4b66e1..d64073dd028 100644 --- a/drivers/scsi/pdc_adma.c +++ b/drivers/scsi/pdc_adma.c @@ -456,7 +456,7 @@ static inline unsigned int adma_intr_pkt(struct ata_host_set *host_set) continue; handled = 1; adma_enter_reg_mode(ap); - if (ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR)) + if (ap->flags & (ATA_FLAG_DISABLED | ATA_FLAG_NOINTR)) continue; pp = ap->private_data; if (!pp || pp->state != adma_state_pkt) @@ -481,7 +481,7 @@ static inline unsigned int adma_intr_mmio(struct ata_host_set *host_set) for (port_no = 0; port_no < host_set->n_ports; ++port_no) { struct ata_port *ap; ap = host_set->ports[port_no]; - if (ap && (!(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR)))) { + if (ap && (!(ap->flags & (ATA_FLAG_DISABLED | ATA_FLAG_NOINTR)))) { struct ata_queued_cmd *qc; struct adma_port_priv *pp = ap->private_data; if (!pp || pp->state != adma_state_mmio) diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index 0f7d334aadc..e9152f85000 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -1397,7 +1397,7 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant, } } - if (ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR)) + if (ap->flags & (ATA_FLAG_DISABLED | ATA_FLAG_NOINTR)) continue; err_mask = ac_err_mask(ata_status); diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c index f77bf183dfa..72721ac482d 100644 --- a/drivers/scsi/sata_nv.c +++ b/drivers/scsi/sata_nv.c @@ -280,7 +280,7 @@ static irqreturn_t nv_interrupt (int irq, void *dev_instance, ap = host_set->ports[i]; if (ap && - !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) { + !(ap->flags & (ATA_FLAG_DISABLED | ATA_FLAG_NOINTR))) { struct ata_queued_cmd *qc; qc = ata_qc_from_tag(ap, ap->active_tag); diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index cc928c68a47..9557c7aa45e 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c @@ -534,7 +534,7 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *r ap = host_set->ports[i]; tmp = mask & (1 << (i + 1)); if (tmp && ap && - !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) { + !(ap->flags & (ATA_FLAG_DISABLED | ATA_FLAG_NOINTR))) { struct ata_queued_cmd *qc; qc = ata_qc_from_tag(ap, ap->active_tag); diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c index 9ffe1ef0d20..8ef042a0944 100644 --- a/drivers/scsi/sata_qstor.c +++ b/drivers/scsi/sata_qstor.c @@ -396,7 +396,7 @@ static inline unsigned int qs_intr_pkt(struct ata_host_set *host_set) sff1, sff0, port_no, sHST, sDST); handled = 1; if (ap && !(ap->flags & - (ATA_FLAG_PORT_DISABLED|ATA_FLAG_NOINTR))) { + (ATA_FLAG_DISABLED|ATA_FLAG_NOINTR))) { struct ata_queued_cmd *qc; struct qs_port_priv *pp = ap->private_data; if (!pp || pp->state != qs_state_pkt) @@ -429,7 +429,7 @@ static inline unsigned int qs_intr_mmio(struct ata_host_set *host_set) struct ata_port *ap; ap = host_set->ports[port_no]; if (ap && - !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) { + !(ap->flags & (ATA_FLAG_DISABLED | ATA_FLAG_NOINTR))) { struct ata_queued_cmd *qc; struct qs_port_priv *pp = ap->private_data; if (!pp || pp->state != qs_state_mmio) diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 068c98a4111..c34f6dabf41 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -770,7 +770,7 @@ static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs * for (i = 0; i < host_set->n_ports; i++) if (status & (1 << i)) { struct ata_port *ap = host_set->ports[i]; - if (ap && !(ap->flags & ATA_FLAG_PORT_DISABLED)) { + if (ap && !(ap->flags & ATA_FLAG_DISABLED)) { sil24_host_intr(host_set->ports[i]); handled++; } else diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c index ae70f60c7c0..3af28ef76fd 100644 --- a/drivers/scsi/sata_sx4.c +++ b/drivers/scsi/sata_sx4.c @@ -834,7 +834,7 @@ static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_re tmp = mask & (1 << i); VPRINTK("seq %u, port_no %u, ap %p, tmp %x\n", i, port_no, ap, tmp); if (tmp && ap && - !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) { + !(ap->flags & (ATA_FLAG_DISABLED | ATA_FLAG_NOINTR))) { struct ata_queued_cmd *qc; qc = ata_qc_from_tag(ap, ap->active_tag); diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c index 836bbbb26ff..cecc1f76256 100644 --- a/drivers/scsi/sata_vsc.c +++ b/drivers/scsi/sata_vsc.c @@ -222,7 +222,7 @@ static irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance, ap = host_set->ports[i]; if (ap && !(ap->flags & - (ATA_FLAG_PORT_DISABLED|ATA_FLAG_NOINTR))) { + (ATA_FLAG_DISABLED|ATA_FLAG_NOINTR))) { struct ata_queued_cmd *qc; qc = ata_qc_from_tag(ap, ap->active_tag); diff --git a/include/linux/libata.h b/include/linux/libata.h index b7488a31e32..890262f44d0 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -150,7 +150,7 @@ enum { ATA_FLAG_DEBUGMSG = (1 << 17), ATA_FLAG_FLUSH_PORT_TASK = (1 << 18), /* flush port task */ - ATA_FLAG_PORT_DISABLED = (1 << 19), /* port is disabled, ignore it */ + ATA_FLAG_DISABLED = (1 << 19), /* port is disabled, ignore it */ ATA_FLAG_SUSPENDED = (1 << 20), /* port is suspended */ /* bits 24:31 of ap->flags are reserved for LLDD specific flags */ -- cgit v1.2.3 From ea1dd4e13010eb9dd5ffb4bfabbb472bc238bebb Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 2 Apr 2006 18:51:53 +0900 Subject: [PATCH] libata: clear only affected flags during ata_dev_configure() ata_dev_configure() should not clear dynamic device flags determined elsewhere. Lower eight bits are reserved for feature flags, define ATA_DFLAG_CFG_MASK and clear only those bits before configuring device. Without this patch, ATA_DFLAG_PIO gets turned off during revalidation making PIO mode unuseable. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 2 +- include/linux/libata.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 53226b16355..985283cbcbd 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1241,7 +1241,7 @@ static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev, id[84], id[85], id[86], id[87], id[88]); /* initialize to-be-configured parameters */ - dev->flags = 0; + dev->flags &= ~ATA_DFLAG_CFG_MASK; dev->max_sectors = 0; dev->cdb_len = 0; dev->n_sectors = 0; diff --git a/include/linux/libata.h b/include/linux/libata.h index 890262f44d0..cbbc821fe22 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -122,6 +122,7 @@ enum { /* struct ata_device stuff */ ATA_DFLAG_LBA = (1 << 0), /* device supports LBA */ ATA_DFLAG_LBA48 = (1 << 1), /* device supports LBA48 */ + ATA_DFLAG_CFG_MASK = (1 << 8) - 1, ATA_DFLAG_PIO = (1 << 8), /* device currently in PIO mode */ -- cgit v1.2.3 From e8384607d4f395985e3cc5f82d75fc73efc2ecf0 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 2 Apr 2006 18:51:53 +0900 Subject: [PATCH] libata: clear ATA_DFLAG_PIO before setting it ata_dev_set_mode() is now responsible for managing ATA_DFLAG_PIO. Clear it before setting it. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 985283cbcbd..007d1888804 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1949,6 +1949,7 @@ static int ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev) unsigned int err_mask; int rc; + dev->flags &= ~ATA_DFLAG_PIO; if (dev->xfer_shift == ATA_SHIFT_PIO) dev->flags |= ATA_DFLAG_PIO; -- cgit v1.2.3 From 2719736779da2c7fbb17d3de16c817b429bfeb9c Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 2 Apr 2006 18:51:53 +0900 Subject: [PATCH] libata: add ATA_QCFLAG_IO Add a new qc flag ATA_QCFLAG_IO. This flag gets set for normal IO commands originating from SCSI midlayer. This information will be used by EH to determine transfer speed reconfiguration. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-scsi.c | 1 + include/linux/libata.h | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 096bdffbde1..234e1cadb07 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -1188,6 +1188,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm u64 block; u32 n_block; + qc->flags |= ATA_QCFLAG_IO; tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; if (scsicmd[0] == WRITE_10 || scsicmd[0] == WRITE_6 || diff --git a/include/linux/libata.h b/include/linux/libata.h index cbbc821fe22..a6d829cb056 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -161,7 +161,8 @@ enum { ATA_QCFLAG_SG = (1 << 1), /* have s/g table? */ ATA_QCFLAG_SINGLE = (1 << 2), /* no s/g, just a single buffer */ ATA_QCFLAG_DMAMAP = ATA_QCFLAG_SG | ATA_QCFLAG_SINGLE, - ATA_QCFLAG_EH_SCHEDULED = (1 << 3), /* EH scheduled */ + ATA_QCFLAG_IO = (1 << 3), /* standard IO command */ + ATA_QCFLAG_EH_SCHEDULED = (1 << 4), /* EH scheduled */ /* host set flags */ ATA_HOST_SIMPLEX = (1 << 0), /* Host is simplex, one DMA channel per host_set only */ -- cgit v1.2.3 From c91af2c87e4048cdefcfc9f16fed8d728243c92d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 2 Apr 2006 18:51:53 +0900 Subject: [PATCH] libata: pass qc around intead of ap during PIO The current code passes pointer to ap around and repeatedly performs ata_qc_from_tag() to access the ongoing qc. This is unnatural and makes EH synchronization cumbersome. Make PIO codes deal with qc instead of ap. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 71 +++++++++++++++++----------------------------- 1 file changed, 26 insertions(+), 45 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 007d1888804..e9002a4174d 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3416,7 +3416,7 @@ void ata_poll_qc_complete(struct ata_queued_cmd *qc) /** * ata_pio_poll - poll using PIO, depending on current state - * @ap: the target ata_port + * @qc: qc in progress * * LOCKING: * None. (executing in kernel thread context) @@ -3424,17 +3424,13 @@ void ata_poll_qc_complete(struct ata_queued_cmd *qc) * RETURNS: * timeout value to use */ - -static unsigned long ata_pio_poll(struct ata_port *ap) +static unsigned long ata_pio_poll(struct ata_queued_cmd *qc) { - struct ata_queued_cmd *qc; + struct ata_port *ap = qc->ap; u8 status; unsigned int poll_state = HSM_ST_UNKNOWN; unsigned int reg_state = HSM_ST_UNKNOWN; - qc = ata_qc_from_tag(ap, ap->active_tag); - WARN_ON(qc == NULL); - switch (ap->hsm_task_state) { case HSM_ST: case HSM_ST_POLL: @@ -3468,7 +3464,7 @@ static unsigned long ata_pio_poll(struct ata_port *ap) /** * ata_pio_complete - check if drive is busy or idle - * @ap: the target ata_port + * @qc: qc to complete * * LOCKING: * None. (executing in kernel thread context) @@ -3476,10 +3472,9 @@ static unsigned long ata_pio_poll(struct ata_port *ap) * RETURNS: * Non-zero if qc completed, zero otherwise. */ - -static int ata_pio_complete (struct ata_port *ap) +static int ata_pio_complete(struct ata_queued_cmd *qc) { - struct ata_queued_cmd *qc; + struct ata_port *ap = qc->ap; u8 drv_stat; /* @@ -3500,9 +3495,6 @@ static int ata_pio_complete (struct ata_port *ap) } } - qc = ata_qc_from_tag(ap, ap->active_tag); - WARN_ON(qc == NULL); - drv_stat = ata_wait_idle(ap); if (!ata_ok(drv_stat)) { qc->err_mask |= __ac_err_mask(drv_stat); @@ -3838,15 +3830,14 @@ err_out: /** * ata_pio_block - start PIO on a block - * @ap: the target ata_port + * @qc: qc to transfer block for * * LOCKING: * None. (executing in kernel thread context) */ - -static void ata_pio_block(struct ata_port *ap) +static void ata_pio_block(struct ata_queued_cmd *qc) { - struct ata_queued_cmd *qc; + struct ata_port *ap = qc->ap; u8 status; /* @@ -3868,9 +3859,6 @@ static void ata_pio_block(struct ata_port *ap) } } - qc = ata_qc_from_tag(ap, ap->active_tag); - WARN_ON(qc == NULL); - /* check error */ if (status & (ATA_ERR | ATA_DF)) { qc->err_mask |= AC_ERR_DEV; @@ -3899,12 +3887,9 @@ static void ata_pio_block(struct ata_port *ap) } } -static void ata_pio_error(struct ata_port *ap) +static void ata_pio_error(struct ata_queued_cmd *qc) { - struct ata_queued_cmd *qc; - - qc = ata_qc_from_tag(ap, ap->active_tag); - WARN_ON(qc == NULL); + struct ata_port *ap = qc->ap; if (qc->tf.command != ATA_CMD_PACKET) printk(KERN_WARNING "ata%u: dev %u PIO error\n", @@ -3922,7 +3907,8 @@ static void ata_pio_error(struct ata_port *ap) static void ata_pio_task(void *_data) { - struct ata_port *ap = _data; + struct ata_queued_cmd *qc = _data; + struct ata_port *ap = qc->ap; unsigned long timeout; int qc_completed; @@ -3935,33 +3921,33 @@ fsm_start: return; case HSM_ST: - ata_pio_block(ap); + ata_pio_block(qc); break; case HSM_ST_LAST: - qc_completed = ata_pio_complete(ap); + qc_completed = ata_pio_complete(qc); break; case HSM_ST_POLL: case HSM_ST_LAST_POLL: - timeout = ata_pio_poll(ap); + timeout = ata_pio_poll(qc); break; case HSM_ST_TMOUT: case HSM_ST_ERR: - ata_pio_error(ap); + ata_pio_error(qc); return; } if (timeout) - ata_port_queue_task(ap, ata_pio_task, ap, timeout); + ata_port_queue_task(ap, ata_pio_task, qc, timeout); else if (!qc_completed) goto fsm_start; } /** * atapi_packet_task - Write CDB bytes to hardware - * @_data: Port to which ATAPI device is attached. + * @_data: qc in progress * * When device has indicated its readiness to accept * a CDB, this function is called. Send the CDB. @@ -3972,17 +3958,12 @@ fsm_start: * LOCKING: * Kernel thread context (may sleep) */ - static void atapi_packet_task(void *_data) { - struct ata_port *ap = _data; - struct ata_queued_cmd *qc; + struct ata_queued_cmd *qc = _data; + struct ata_port *ap = qc->ap; u8 status; - qc = ata_qc_from_tag(ap, ap->active_tag); - WARN_ON(qc == NULL); - WARN_ON(!(qc->flags & ATA_QCFLAG_ACTIVE)); - /* sleep-wait for BSY to clear */ DPRINTK("busy wait\n"); if (ata_busy_sleep(ap, ATA_TMOUT_CDB_QUICK, ATA_TMOUT_CDB)) { @@ -4022,7 +4003,7 @@ static void atapi_packet_task(void *_data) /* PIO commands are handled by polling */ ap->hsm_task_state = HSM_ST; - ata_port_queue_task(ap, ata_pio_task, ap, 0); + ata_port_queue_task(ap, ata_pio_task, qc, 0); } return; @@ -4328,26 +4309,26 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc) ata_qc_set_polling(qc); ata_tf_to_host(ap, &qc->tf); ap->hsm_task_state = HSM_ST; - ata_port_queue_task(ap, ata_pio_task, ap, 0); + ata_port_queue_task(ap, ata_pio_task, qc, 0); break; case ATA_PROT_ATAPI: ata_qc_set_polling(qc); ata_tf_to_host(ap, &qc->tf); - ata_port_queue_task(ap, atapi_packet_task, ap, 0); + ata_port_queue_task(ap, atapi_packet_task, qc, 0); break; case ATA_PROT_ATAPI_NODATA: ap->flags |= ATA_FLAG_NOINTR; ata_tf_to_host(ap, &qc->tf); - ata_port_queue_task(ap, atapi_packet_task, ap, 0); + ata_port_queue_task(ap, atapi_packet_task, qc, 0); break; case ATA_PROT_ATAPI_DMA: ap->flags |= ATA_FLAG_NOINTR; ap->ops->tf_load(ap, &qc->tf); /* load tf registers */ ap->ops->bmdma_setup(qc); /* set up bmdma */ - ata_port_queue_task(ap, atapi_packet_task, ap, 0); + ata_port_queue_task(ap, atapi_packet_task, qc, 0); break; default: -- cgit v1.2.3 From 058e55e120ca59d37392f9aa753da2d9ead24505 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 2 Apr 2006 18:51:53 +0900 Subject: [PATCH] libata: always generate sense if qc->err_mask is non-zero Current sense generation code does not generate sense error if status register value doesn't indicate error condition. However, LLDD's may indicate errors which 't show up in status register. Completing such qc's without generating sense results in successful completion of failed commands. Invoke ata_to_sense_error() regardless of status register if qc->err_mask is not zero such that ata_to_sense_error() generates default sense error. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-scsi.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 234e1cadb07..ec628cea386 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -555,7 +555,8 @@ void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc) * Use ata_to_sense_error() to map status register bits * onto sense key, asc & ascq. */ - if (tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) { + if (qc->err_mask || + tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) { ata_to_sense_error(qc->ap->id, tf->command, tf->feature, &sb[1], &sb[2], &sb[3]); sb[1] &= 0x0f; @@ -630,7 +631,8 @@ void ata_gen_fixed_sense(struct ata_queued_cmd *qc) * Use ata_to_sense_error() to map status register bits * onto sense key, asc & ascq. */ - if (tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) { + if (qc->err_mask || + tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) { ata_to_sense_error(qc->ap->id, tf->command, tf->feature, &sb[2], &sb[12], &sb[13]); sb[2] &= 0x0f; -- cgit v1.2.3 From 74e6c8c394ca2126a60e97bc1142ec2d91761e9a Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 2 Apr 2006 18:51:53 +0900 Subject: [PATCH] libata: don't read TF directly from sense generation functions TF register might not be directly accessible depending on errors. e.g. TF of failed NCQ command is in log page 10h. Make reading TF responsibility of error handlers. For the current EH, simply push TF reading into qc completion functions as they are practically part of EH. New EH will fill qc->tf with status registers before complting qcs. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-scsi.c | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index ec628cea386..28706521773 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -545,12 +545,6 @@ void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc) cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; - /* - * Read the controller registers. - */ - WARN_ON(qc->ap->ops->tf_read == NULL); - qc->ap->ops->tf_read(qc->ap, tf); - /* * Use ata_to_sense_error() to map status register bits * onto sense key, asc & ascq. @@ -621,12 +615,6 @@ void ata_gen_fixed_sense(struct ata_queued_cmd *qc) cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; - /* - * Read the controller registers. - */ - WARN_ON(qc->ap->ops->tf_read == NULL); - qc->ap->ops->tf_read(qc->ap, tf); - /* * Use ata_to_sense_error() to map status register bits * onto sense key, asc & ascq. @@ -1337,11 +1325,14 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) */ if (((cdb[0] == ATA_16) || (cdb[0] == ATA_12)) && ((cdb[2] & 0x20) || need_sense)) { + qc->ap->ops->tf_read(qc->ap, &qc->tf); ata_gen_ata_desc_sense(qc); } else { if (!need_sense) { cmd->result = SAM_STAT_GOOD; } else { + qc->ap->ops->tf_read(qc->ap, &qc->tf); + /* TODO: decide which descriptor format to use * for 48b LBA devices and call that here * instead of the fixed desc, which is only @@ -2133,13 +2124,15 @@ void ata_scsi_badcmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), u8 static void atapi_sense_complete(struct ata_queued_cmd *qc) { - if (qc->err_mask && ((qc->err_mask & AC_ERR_DEV) == 0)) + if (qc->err_mask && ((qc->err_mask & AC_ERR_DEV) == 0)) { /* FIXME: not quite right; we don't want the * translation of taskfile registers into * a sense descriptors, since that's only * correct for ATA, not ATAPI */ + qc->ap->ops->tf_read(qc->ap, &qc->tf); ata_gen_ata_desc_sense(qc); + } qc->scsidone(qc->scsicmd); ata_qc_free(qc); @@ -2207,17 +2200,15 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc) cmd->result = SAM_STAT_CHECK_CONDITION; atapi_request_sense(qc); return; - } - - else if (unlikely(err_mask)) + } else if (unlikely(err_mask)) { /* FIXME: not quite right; we don't want the * translation of taskfile registers into * a sense descriptors, since that's only * correct for ATA, not ATAPI */ + qc->ap->ops->tf_read(qc->ap, &qc->tf); ata_gen_ata_desc_sense(qc); - - else { + } else { u8 *scsicmd = cmd->cmnd; if ((scsicmd[0] == INQUIRY) && ((scsicmd[1] & 0x03) == 0)) { -- cgit v1.2.3 From d69cf37d5387801914bbf5297f070c7d2ee0206f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 2 Apr 2006 18:51:53 +0900 Subject: [PATCH] libata: add @cdb to ata_exec_internal() Add @cdb to ata_exec_internal(). It will be used by new EH. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index e9002a4174d..66b48b11fa0 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -964,6 +964,7 @@ void ata_qc_complete_internal(struct ata_queued_cmd *qc) * @ap: Port to which the command is sent * @dev: Device to which the command is sent * @tf: Taskfile registers for the command and the result + * @cdb: CDB for packet command * @dma_dir: Data tranfer direction of the command * @buf: Data buffer of the command * @buflen: Length of data buffer @@ -980,7 +981,7 @@ void ata_qc_complete_internal(struct ata_queued_cmd *qc) static unsigned ata_exec_internal(struct ata_port *ap, struct ata_device *dev, - struct ata_taskfile *tf, + struct ata_taskfile *tf, const u8 *cdb, int dma_dir, void *buf, unsigned int buflen) { u8 command = tf->command; @@ -995,6 +996,8 @@ ata_exec_internal(struct ata_port *ap, struct ata_device *dev, BUG_ON(qc == NULL); qc->tf = *tf; + if (cdb) + memcpy(qc->cdb, cdb, ATAPI_CDB_LEN); qc->dma_dir = dma_dir; if (dma_dir != DMA_NONE) { ata_sg_init_one(qc, buf, buflen); @@ -1144,7 +1147,7 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, tf.protocol = ATA_PROT_PIO; - err_mask = ata_exec_internal(ap, dev, &tf, DMA_FROM_DEVICE, + err_mask = ata_exec_internal(ap, dev, &tf, NULL, DMA_FROM_DEVICE, id, sizeof(id[0]) * ATA_ID_WORDS); if (err_mask) { rc = -EIO; @@ -2988,7 +2991,7 @@ static unsigned int ata_dev_set_xfermode(struct ata_port *ap, tf.protocol = ATA_PROT_NODATA; tf.nsect = dev->xfer_mode; - err_mask = ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0); + err_mask = ata_exec_internal(ap, dev, &tf, NULL, DMA_NONE, NULL, 0); DPRINTK("EXIT, err_mask=%x\n", err_mask); return err_mask; @@ -3028,7 +3031,7 @@ static unsigned int ata_dev_init_params(struct ata_port *ap, tf.nsect = sectors; tf.device |= (heads - 1) & 0x0f; /* max head = num. of heads - 1 */ - err_mask = ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0); + err_mask = ata_exec_internal(ap, dev, &tf, NULL, DMA_NONE, NULL, 0); DPRINTK("EXIT, err_mask=%x\n", err_mask); return err_mask; @@ -4482,7 +4485,7 @@ static int ata_do_simple_cmd(struct ata_port *ap, struct ata_device *dev, tf.flags |= ATA_TFLAG_DEVICE; tf.protocol = ATA_PROT_NODATA; - err = ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0); + err = ata_exec_internal(ap, dev, &tf, NULL, DMA_NONE, NULL, 0); if (err) printk(KERN_ERR "%s: ata command failed: %d\n", __FUNCTION__, err); -- cgit v1.2.3 From 35e86b53b1a38e78ff0d70dae4aeb25f4572e433 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 2 Apr 2006 18:51:53 +0900 Subject: [PATCH] libata: dec scmd->retries for qcs with zero err_mask qcs might get retried because of unrelated failure. e.g. NCQ command failure causes the whole command set to be aborted. Decrement scmd->retries for such retrials to avoid unnecessarily failing commands. Note that scmd->retries will be incremented the first time. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-scsi.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 28706521773..44008150d31 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -831,11 +831,14 @@ void ata_eh_qc_complete(struct ata_queued_cmd *qc) * should be retried. To be used from EH. * * SCSI midlayer limits the number of retries to scmd->allowed. - * This function might need to adjust scmd->retries for commands - * which get retried due to unrelated NCQ failures. + * scmd->retries is decremented for commands which get retried + * due to unrelated failures (qc->err_mask is zero). */ void ata_eh_qc_retry(struct ata_queued_cmd *qc) { + struct scsi_cmnd *scmd = qc->scsicmd; + if (!qc->err_mask && scmd->retries) + scmd->retries--; __ata_eh_qc_complete(qc); } -- cgit v1.2.3 From ece1d63619df010b8c4f08e43755e2a03f3b6eed Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 2 Apr 2006 18:51:53 +0900 Subject: [PATCH] libata: separate out libata-eh.c A lot of EH codes are about to be added to libata. Separate out libata-eh.c. ata_scsi_timed_out(), ata_scsi_error(), ata_qc_timeout(), ata_eng_timeout(), ata_eh_qc_complete() and ata_eh_qc_retry() are moved. No code is changed by this patch. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/Makefile | 2 +- drivers/scsi/libata-core.c | 102 +----------------- drivers/scsi/libata-eh.c | 264 +++++++++++++++++++++++++++++++++++++++++++++ drivers/scsi/libata-scsi.c | 130 ---------------------- drivers/scsi/libata.h | 4 +- include/linux/libata.h | 12 ++- 6 files changed, 281 insertions(+), 233 deletions(-) create mode 100644 drivers/scsi/libata-eh.c diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index e513c3158ad..503f189dab3 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -165,7 +165,7 @@ ncr53c8xx-flags-$(CONFIG_SCSI_ZALON) \ CFLAGS_ncr53c8xx.o := $(ncr53c8xx-flags-y) $(ncr53c8xx-flags-m) zalon7xx-objs := zalon.o ncr53c8xx.o NCR_Q720_mod-objs := NCR_Q720.o ncr53c8xx.o -libata-objs := libata-core.o libata-scsi.o libata-bmdma.o +libata-objs := libata-core.o libata-scsi.o libata-bmdma.o libata-eh.o oktagon_esp_mod-objs := oktagon_esp.o oktagon_io.o # Files generated that shall be removed upon make clean diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 66b48b11fa0..186a9ce4f07 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -4015,99 +4015,6 @@ err_out: ata_poll_qc_complete(qc); } -/** - * ata_qc_timeout - Handle timeout of queued command - * @qc: Command that timed out - * - * Some part of the kernel (currently, only the SCSI layer) - * has noticed that the active command on port @ap has not - * completed after a specified length of time. Handle this - * condition by disabling DMA (if necessary) and completing - * transactions, with error if necessary. - * - * This also handles the case of the "lost interrupt", where - * for some reason (possibly hardware bug, possibly driver bug) - * an interrupt was not delivered to the driver, even though the - * transaction completed successfully. - * - * LOCKING: - * Inherited from SCSI layer (none, can sleep) - */ - -static void ata_qc_timeout(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - struct ata_host_set *host_set = ap->host_set; - u8 host_stat = 0, drv_stat; - unsigned long flags; - - DPRINTK("ENTER\n"); - - ap->hsm_task_state = HSM_ST_IDLE; - - spin_lock_irqsave(&host_set->lock, flags); - - switch (qc->tf.protocol) { - - case ATA_PROT_DMA: - case ATA_PROT_ATAPI_DMA: - host_stat = ap->ops->bmdma_status(ap); - - /* before we do anything else, clear DMA-Start bit */ - ap->ops->bmdma_stop(qc); - - /* fall through */ - - default: - ata_altstatus(ap); - drv_stat = ata_chk_status(ap); - - /* ack bmdma irq events */ - ap->ops->irq_clear(ap); - - printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x host_stat 0x%x\n", - ap->id, qc->tf.command, drv_stat, host_stat); - - /* complete taskfile transaction */ - qc->err_mask |= ac_err_mask(drv_stat); - break; - } - - spin_unlock_irqrestore(&host_set->lock, flags); - - ata_eh_qc_complete(qc); - - DPRINTK("EXIT\n"); -} - -/** - * ata_eng_timeout - Handle timeout of queued command - * @ap: Port on which timed-out command is active - * - * Some part of the kernel (currently, only the SCSI layer) - * has noticed that the active command on port @ap has not - * completed after a specified length of time. Handle this - * condition by disabling DMA (if necessary) and completing - * transactions, with error if necessary. - * - * This also handles the case of the "lost interrupt", where - * for some reason (possibly hardware bug, possibly driver bug) - * an interrupt was not delivered to the driver, even though the - * transaction completed successfully. - * - * LOCKING: - * Inherited from SCSI layer (none, can sleep) - */ - -void ata_eng_timeout(struct ata_port *ap) -{ - DPRINTK("ENTER\n"); - - ata_qc_timeout(ata_qc_from_tag(ap, ap->active_tag)); - - DPRINTK("EXIT\n"); -} - /** * ata_qc_new - Request an available ATA command, for queueing * @ap: Port associated with device @dev @@ -5145,7 +5052,6 @@ EXPORT_SYMBOL_GPL(ata_sg_init); EXPORT_SYMBOL_GPL(ata_sg_init_one); EXPORT_SYMBOL_GPL(__ata_qc_complete); EXPORT_SYMBOL_GPL(ata_qc_issue_prot); -EXPORT_SYMBOL_GPL(ata_eng_timeout); EXPORT_SYMBOL_GPL(ata_tf_load); EXPORT_SYMBOL_GPL(ata_tf_read); EXPORT_SYMBOL_GPL(ata_noop_dev_select); @@ -5185,15 +5091,12 @@ EXPORT_SYMBOL_GPL(ata_busy_sleep); EXPORT_SYMBOL_GPL(ata_port_queue_task); EXPORT_SYMBOL_GPL(ata_scsi_ioctl); EXPORT_SYMBOL_GPL(ata_scsi_queuecmd); -EXPORT_SYMBOL_GPL(ata_scsi_error); EXPORT_SYMBOL_GPL(ata_scsi_slave_config); EXPORT_SYMBOL_GPL(ata_scsi_release); EXPORT_SYMBOL_GPL(ata_host_intr); EXPORT_SYMBOL_GPL(ata_id_string); EXPORT_SYMBOL_GPL(ata_id_c_string); EXPORT_SYMBOL_GPL(ata_scsi_simulate); -EXPORT_SYMBOL_GPL(ata_eh_qc_complete); -EXPORT_SYMBOL_GPL(ata_eh_qc_retry); EXPORT_SYMBOL_GPL(ata_pio_need_iordy); EXPORT_SYMBOL_GPL(ata_timing_compute); @@ -5215,3 +5118,8 @@ EXPORT_SYMBOL_GPL(ata_device_suspend); EXPORT_SYMBOL_GPL(ata_device_resume); EXPORT_SYMBOL_GPL(ata_scsi_device_suspend); EXPORT_SYMBOL_GPL(ata_scsi_device_resume); + +EXPORT_SYMBOL_GPL(ata_scsi_error); +EXPORT_SYMBOL_GPL(ata_eng_timeout); +EXPORT_SYMBOL_GPL(ata_eh_qc_complete); +EXPORT_SYMBOL_GPL(ata_eh_qc_retry); diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c new file mode 100644 index 00000000000..e73f5612aea --- /dev/null +++ b/drivers/scsi/libata-eh.c @@ -0,0 +1,264 @@ +/* + * libata-eh.c - libata error handling + * + * Maintained by: Jeff Garzik + * Please ALWAYS copy linux-ide@vger.kernel.org + * on emails. + * + * Copyright 2006 Tejun Heo + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, + * USA. + * + * + * libata documentation is available via 'make {ps|pdf}docs', + * as Documentation/DocBook/libata.* + * + * Hardware documentation available from http://www.t13.org/ and + * http://www.sata-io.org/ + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "libata.h" + +/** + * ata_scsi_timed_out - SCSI layer time out callback + * @cmd: timed out SCSI command + * + * Handles SCSI layer timeout. We race with normal completion of + * the qc for @cmd. If the qc is already gone, we lose and let + * the scsi command finish (EH_HANDLED). Otherwise, the qc has + * timed out and EH should be invoked. Prevent ata_qc_complete() + * from finishing it by setting EH_SCHEDULED and return + * EH_NOT_HANDLED. + * + * LOCKING: + * Called from timer context + * + * RETURNS: + * EH_HANDLED or EH_NOT_HANDLED + */ +enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd) +{ + struct Scsi_Host *host = cmd->device->host; + struct ata_port *ap = (struct ata_port *) &host->hostdata[0]; + unsigned long flags; + struct ata_queued_cmd *qc; + enum scsi_eh_timer_return ret = EH_HANDLED; + + DPRINTK("ENTER\n"); + + spin_lock_irqsave(&ap->host_set->lock, flags); + qc = ata_qc_from_tag(ap, ap->active_tag); + if (qc) { + WARN_ON(qc->scsicmd != cmd); + qc->flags |= ATA_QCFLAG_EH_SCHEDULED; + qc->err_mask |= AC_ERR_TIMEOUT; + ret = EH_NOT_HANDLED; + } + spin_unlock_irqrestore(&ap->host_set->lock, flags); + + DPRINTK("EXIT, ret=%d\n", ret); + return ret; +} + +/** + * ata_scsi_error - SCSI layer error handler callback + * @host: SCSI host on which error occurred + * + * Handles SCSI-layer-thrown error events. + * + * LOCKING: + * Inherited from SCSI layer (none, can sleep) + * + * RETURNS: + * Zero. + */ +int ata_scsi_error(struct Scsi_Host *host) +{ + struct ata_port *ap = (struct ata_port *)&host->hostdata[0]; + + DPRINTK("ENTER\n"); + + /* synchronize with IRQ handler and port task */ + spin_unlock_wait(&ap->host_set->lock); + ata_port_flush_task(ap); + + WARN_ON(ata_qc_from_tag(ap, ap->active_tag) == NULL); + + ap->ops->eng_timeout(ap); + + WARN_ON(host->host_failed || !list_empty(&host->eh_cmd_q)); + + scsi_eh_flush_done_q(&ap->eh_done_q); + + DPRINTK("EXIT\n"); + return 0; +} + +/** + * ata_qc_timeout - Handle timeout of queued command + * @qc: Command that timed out + * + * Some part of the kernel (currently, only the SCSI layer) + * has noticed that the active command on port @ap has not + * completed after a specified length of time. Handle this + * condition by disabling DMA (if necessary) and completing + * transactions, with error if necessary. + * + * This also handles the case of the "lost interrupt", where + * for some reason (possibly hardware bug, possibly driver bug) + * an interrupt was not delivered to the driver, even though the + * transaction completed successfully. + * + * LOCKING: + * Inherited from SCSI layer (none, can sleep) + */ +static void ata_qc_timeout(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + struct ata_host_set *host_set = ap->host_set; + u8 host_stat = 0, drv_stat; + unsigned long flags; + + DPRINTK("ENTER\n"); + + ap->hsm_task_state = HSM_ST_IDLE; + + spin_lock_irqsave(&host_set->lock, flags); + + switch (qc->tf.protocol) { + + case ATA_PROT_DMA: + case ATA_PROT_ATAPI_DMA: + host_stat = ap->ops->bmdma_status(ap); + + /* before we do anything else, clear DMA-Start bit */ + ap->ops->bmdma_stop(qc); + + /* fall through */ + + default: + ata_altstatus(ap); + drv_stat = ata_chk_status(ap); + + /* ack bmdma irq events */ + ap->ops->irq_clear(ap); + + printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x host_stat 0x%x\n", + ap->id, qc->tf.command, drv_stat, host_stat); + + /* complete taskfile transaction */ + qc->err_mask |= ac_err_mask(drv_stat); + break; + } + + spin_unlock_irqrestore(&host_set->lock, flags); + + ata_eh_qc_complete(qc); + + DPRINTK("EXIT\n"); +} + +/** + * ata_eng_timeout - Handle timeout of queued command + * @ap: Port on which timed-out command is active + * + * Some part of the kernel (currently, only the SCSI layer) + * has noticed that the active command on port @ap has not + * completed after a specified length of time. Handle this + * condition by disabling DMA (if necessary) and completing + * transactions, with error if necessary. + * + * This also handles the case of the "lost interrupt", where + * for some reason (possibly hardware bug, possibly driver bug) + * an interrupt was not delivered to the driver, even though the + * transaction completed successfully. + * + * LOCKING: + * Inherited from SCSI layer (none, can sleep) + */ +void ata_eng_timeout(struct ata_port *ap) +{ + DPRINTK("ENTER\n"); + + ata_qc_timeout(ata_qc_from_tag(ap, ap->active_tag)); + + DPRINTK("EXIT\n"); +} + +static void ata_eh_scsidone(struct scsi_cmnd *scmd) +{ + /* nada */ +} + +static void __ata_eh_qc_complete(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + struct scsi_cmnd *scmd = qc->scsicmd; + unsigned long flags; + + spin_lock_irqsave(&ap->host_set->lock, flags); + qc->scsidone = ata_eh_scsidone; + __ata_qc_complete(qc); + WARN_ON(ata_tag_valid(qc->tag)); + spin_unlock_irqrestore(&ap->host_set->lock, flags); + + scsi_eh_finish_cmd(scmd, &ap->eh_done_q); +} + +/** + * ata_eh_qc_complete - Complete an active ATA command from EH + * @qc: Command to complete + * + * Indicate to the mid and upper layers that an ATA command has + * completed. To be used from EH. + */ +void ata_eh_qc_complete(struct ata_queued_cmd *qc) +{ + struct scsi_cmnd *scmd = qc->scsicmd; + scmd->retries = scmd->allowed; + __ata_eh_qc_complete(qc); +} + +/** + * ata_eh_qc_retry - Tell midlayer to retry an ATA command after EH + * @qc: Command to retry + * + * Indicate to the mid and upper layers that an ATA command + * should be retried. To be used from EH. + * + * SCSI midlayer limits the number of retries to scmd->allowed. + * scmd->retries is decremented for commands which get retried + * due to unrelated failures (qc->err_mask is zero). + */ +void ata_eh_qc_retry(struct ata_queued_cmd *qc) +{ + struct scsi_cmnd *scmd = qc->scsicmd; + if (!qc->err_mask && scmd->retries) + scmd->retries--; + __ata_eh_qc_complete(qc); +} diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 44008150d31..745fc263fee 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -53,7 +53,6 @@ typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc, const u8 *scsicmd); static struct ata_device * ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev); -enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd); #define RW_RECOVERY_MPAGE 0x1 #define RW_RECOVERY_MPAGE_LEN 12 @@ -713,135 +712,6 @@ int ata_scsi_slave_config(struct scsi_device *sdev) return 0; /* scsi layer doesn't check return value, sigh */ } -/** - * ata_scsi_timed_out - SCSI layer time out callback - * @cmd: timed out SCSI command - * - * Handles SCSI layer timeout. We race with normal completion of - * the qc for @cmd. If the qc is already gone, we lose and let - * the scsi command finish (EH_HANDLED). Otherwise, the qc has - * timed out and EH should be invoked. Prevent ata_qc_complete() - * from finishing it by setting EH_SCHEDULED and return - * EH_NOT_HANDLED. - * - * LOCKING: - * Called from timer context - * - * RETURNS: - * EH_HANDLED or EH_NOT_HANDLED - */ -enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd) -{ - struct Scsi_Host *host = cmd->device->host; - struct ata_port *ap = (struct ata_port *) &host->hostdata[0]; - unsigned long flags; - struct ata_queued_cmd *qc; - enum scsi_eh_timer_return ret = EH_HANDLED; - - DPRINTK("ENTER\n"); - - spin_lock_irqsave(&ap->host_set->lock, flags); - qc = ata_qc_from_tag(ap, ap->active_tag); - if (qc) { - WARN_ON(qc->scsicmd != cmd); - qc->flags |= ATA_QCFLAG_EH_SCHEDULED; - qc->err_mask |= AC_ERR_TIMEOUT; - ret = EH_NOT_HANDLED; - } - spin_unlock_irqrestore(&ap->host_set->lock, flags); - - DPRINTK("EXIT, ret=%d\n", ret); - return ret; -} - -/** - * ata_scsi_error - SCSI layer error handler callback - * @host: SCSI host on which error occurred - * - * Handles SCSI-layer-thrown error events. - * - * LOCKING: - * Inherited from SCSI layer (none, can sleep) - * - * RETURNS: - * Zero. - */ - -int ata_scsi_error(struct Scsi_Host *host) -{ - struct ata_port *ap = (struct ata_port *)&host->hostdata[0]; - - DPRINTK("ENTER\n"); - - /* synchronize with IRQ handler and port task */ - spin_unlock_wait(&ap->host_set->lock); - ata_port_flush_task(ap); - - WARN_ON(ata_qc_from_tag(ap, ap->active_tag) == NULL); - - ap->ops->eng_timeout(ap); - - WARN_ON(host->host_failed || !list_empty(&host->eh_cmd_q)); - - scsi_eh_flush_done_q(&ap->eh_done_q); - - DPRINTK("EXIT\n"); - return 0; -} - -static void ata_eh_scsidone(struct scsi_cmnd *scmd) -{ - /* nada */ -} - -static void __ata_eh_qc_complete(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - struct scsi_cmnd *scmd = qc->scsicmd; - unsigned long flags; - - spin_lock_irqsave(&ap->host_set->lock, flags); - qc->scsidone = ata_eh_scsidone; - __ata_qc_complete(qc); - WARN_ON(ata_tag_valid(qc->tag)); - spin_unlock_irqrestore(&ap->host_set->lock, flags); - - scsi_eh_finish_cmd(scmd, &ap->eh_done_q); -} - -/** - * ata_eh_qc_complete - Complete an active ATA command from EH - * @qc: Command to complete - * - * Indicate to the mid and upper layers that an ATA command has - * completed. To be used from EH. - */ -void ata_eh_qc_complete(struct ata_queued_cmd *qc) -{ - struct scsi_cmnd *scmd = qc->scsicmd; - scmd->retries = scmd->allowed; - __ata_eh_qc_complete(qc); -} - -/** - * ata_eh_qc_retry - Tell midlayer to retry an ATA command after EH - * @qc: Command to retry - * - * Indicate to the mid and upper layers that an ATA command - * should be retried. To be used from EH. - * - * SCSI midlayer limits the number of retries to scmd->allowed. - * scmd->retries is decremented for commands which get retried - * due to unrelated failures (qc->err_mask is zero). - */ -void ata_eh_qc_retry(struct ata_queued_cmd *qc) -{ - struct scsi_cmnd *scmd = qc->scsicmd; - if (!qc->err_mask && scmd->retries) - scmd->retries--; - __ata_eh_qc_complete(qc); -} - /** * ata_scsi_start_stop_xlat - Translate SCSI START STOP UNIT command * @qc: Storage for translated ATA taskfile diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index 1c755b14521..75e9bd5833d 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -60,7 +60,6 @@ extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg); extern struct scsi_transport_template ata_scsi_transport_template; extern void ata_scsi_scan_host(struct ata_port *ap); -extern int ata_scsi_error(struct Scsi_Host *host); extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf, unsigned int buflen); @@ -90,4 +89,7 @@ extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args, unsigned int (*actor) (struct ata_scsi_args *args, u8 *rbuf, unsigned int buflen)); +/* libata-eh.c */ +extern enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd); + #endif /* __LIBATA_H__ */ diff --git a/include/linux/libata.h b/include/linux/libata.h index a6d829cb056..75bdee09c30 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -531,9 +531,6 @@ extern void ata_host_set_remove(struct ata_host_set *host_set); extern int ata_scsi_detect(struct scsi_host_template *sht); extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg); extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)); -extern int ata_scsi_error(struct Scsi_Host *host); -extern void ata_eh_qc_complete(struct ata_queued_cmd *qc); -extern void ata_eh_qc_retry(struct ata_queued_cmd *qc); extern int ata_scsi_release(struct Scsi_Host *host); extern unsigned int ata_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc); extern int ata_scsi_device_resume(struct scsi_device *); @@ -582,7 +579,6 @@ extern void ata_bmdma_stop(struct ata_queued_cmd *qc); extern u8 ata_bmdma_status(struct ata_port *ap); extern void ata_bmdma_irq_clear(struct ata_port *ap); extern void __ata_qc_complete(struct ata_queued_cmd *qc); -extern void ata_eng_timeout(struct ata_port *ap); extern void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev, struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)); @@ -637,6 +633,14 @@ extern int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bit extern unsigned long ata_pci_default_filter(const struct ata_port *, struct ata_device *, unsigned long); #endif /* CONFIG_PCI */ +/* + * EH + */ +extern int ata_scsi_error(struct Scsi_Host *host); +extern void ata_eng_timeout(struct ata_port *ap); +extern void ata_eh_qc_complete(struct ata_queued_cmd *qc); +extern void ata_eh_qc_retry(struct ata_queued_cmd *qc); + static inline int ata_sg_is_last(struct scatterlist *sg, struct ata_queued_cmd *qc) -- cgit v1.2.3 From 1ad8e7f9eb051b040880e45337ed74bfd916ef7f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 2 Apr 2006 18:51:53 +0900 Subject: [PATCH] libata: make some libata-core routines extern Make libata-core routines which will be used by EH implementation extern. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 29 ++++++++++++----------------- drivers/scsi/libata.h | 13 +++++++++++++ 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 186a9ce4f07..8beba3cd9a5 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -65,10 +65,6 @@ static unsigned int ata_dev_init_params(struct ata_port *ap, struct ata_device *dev, u16 heads, u16 sectors); -static int ata_down_xfermask_limit(struct ata_port *ap, struct ata_device *dev, - int force_pio0); -static int ata_down_sata_spd_limit(struct ata_port *ap); -static int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev); static unsigned int ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev); static void ata_dev_xfermask(struct ata_port *ap, struct ata_device *dev); @@ -412,7 +408,7 @@ static const char *sata_spd_string(unsigned int spd) return spd_str[spd - 1]; } -static void ata_dev_disable(struct ata_port *ap, struct ata_device *dev) +void ata_dev_disable(struct ata_port *ap, struct ata_device *dev) { if (ata_dev_enabled(dev)) { printk(KERN_WARNING "ata%u: dev %u disabled\n", @@ -979,10 +975,9 @@ void ata_qc_complete_internal(struct ata_queued_cmd *qc) * None. Should be called with kernel context, might sleep. */ -static unsigned -ata_exec_internal(struct ata_port *ap, struct ata_device *dev, - struct ata_taskfile *tf, const u8 *cdb, - int dma_dir, void *buf, unsigned int buflen) +unsigned ata_exec_internal(struct ata_port *ap, struct ata_device *dev, + struct ata_taskfile *tf, const u8 *cdb, + int dma_dir, void *buf, unsigned int buflen) { u8 command = tf->command; struct ata_queued_cmd *qc; @@ -1649,7 +1644,7 @@ void ata_port_disable(struct ata_port *ap) * RETURNS: * 0 on success, negative errno on failure */ -static int ata_down_sata_spd_limit(struct ata_port *ap) +int ata_down_sata_spd_limit(struct ata_port *ap) { u32 spd, mask; int highbit; @@ -1709,7 +1704,7 @@ static int __ata_set_sata_spd_needed(struct ata_port *ap, u32 *scontrol) * RETURNS: * 1 if SATA spd configuration is needed, 0 otherwise. */ -static int ata_set_sata_spd_needed(struct ata_port *ap) +int ata_set_sata_spd_needed(struct ata_port *ap) { u32 scontrol; @@ -1913,8 +1908,8 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed, * RETURNS: * 0 on success, negative errno on failure */ -static int ata_down_xfermask_limit(struct ata_port *ap, struct ata_device *dev, - int force_pio0) +int ata_down_xfermask_limit(struct ata_port *ap, struct ata_device *dev, + int force_pio0) { unsigned long xfer_mask; int highbit; @@ -1992,7 +1987,7 @@ static int ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev) * RETURNS: * 0 on success, negative errno otherwise */ -static int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev) +int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev) { struct ata_device *dev; int i, rc = 0, used_dma = 0, found = 0; @@ -2590,9 +2585,9 @@ int ata_std_probe_reset(struct ata_port *ap, unsigned int *classes) ata_std_postreset, classes); } -static int ata_do_reset(struct ata_port *ap, - ata_reset_fn_t reset, ata_postreset_fn_t postreset, - int verbose, unsigned int *classes) +int ata_do_reset(struct ata_port *ap, + ata_reset_fn_t reset, ata_postreset_fn_t postreset, + int verbose, unsigned int *classes) { int i, rc; diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index 75e9bd5833d..31efc2e60b6 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -45,7 +45,20 @@ extern int libata_fua; extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, struct ata_device *dev); extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc); +extern void ata_dev_disable(struct ata_port *ap, struct ata_device *dev); extern void ata_port_flush_task(struct ata_port *ap); +extern unsigned ata_exec_internal(struct ata_port *ap, struct ata_device *dev, + struct ata_taskfile *tf, const u8 *cdb, + int dma_dir, void *buf, unsigned int buflen); +extern int ata_down_sata_spd_limit(struct ata_port *ap); +extern int ata_set_sata_spd_needed(struct ata_port *ap); +extern int ata_down_xfermask_limit(struct ata_port *ap, struct ata_device *dev, + int force_pio0); +extern int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev); +extern int ata_do_reset(struct ata_port *ap, + ata_reset_fn_t reset, + ata_postreset_fn_t postreset, + int verbose, unsigned int *classes); extern void ata_qc_free(struct ata_queued_cmd *qc); extern void ata_qc_issue(struct ata_queued_cmd *qc); extern int ata_check_atapi_dma(struct ata_queued_cmd *qc); -- cgit v1.2.3 From c13b56a1130bbfacfb588de100e5a248383805a6 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Sun, 2 Apr 2006 10:34:24 -0400 Subject: [libata] irq-pio: Fix merge mistake --- drivers/scsi/libata-core.c | 95 ---------------------------------------------- drivers/scsi/libata-eh.c | 5 ++- 2 files changed, 4 insertions(+), 96 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 9de48dd4234..fc3e57f8426 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -4124,101 +4124,6 @@ fsm_start: goto fsm_start; } -/** - * ata_qc_timeout - Handle timeout of queued command - * @qc: Command that timed out - * - * Some part of the kernel (currently, only the SCSI layer) - * has noticed that the active command on port @ap has not - * completed after a specified length of time. Handle this - * condition by disabling DMA (if necessary) and completing - * transactions, with error if necessary. - * - * This also handles the case of the "lost interrupt", where - * for some reason (possibly hardware bug, possibly driver bug) - * an interrupt was not delivered to the driver, even though the - * transaction completed successfully. - * - * LOCKING: - * Inherited from SCSI layer (none, can sleep) - */ - -static void ata_qc_timeout(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - struct ata_host_set *host_set = ap->host_set; - u8 host_stat = 0, drv_stat; - unsigned long flags; - - DPRINTK("ENTER\n"); - - ap->hsm_task_state = HSM_ST_IDLE; - - spin_lock_irqsave(&host_set->lock, flags); - - switch (qc->tf.protocol) { - - case ATA_PROT_DMA: - case ATA_PROT_ATAPI_DMA: - host_stat = ap->ops->bmdma_status(ap); - - /* before we do anything else, clear DMA-Start bit */ - ap->ops->bmdma_stop(qc); - - /* fall through */ - - default: - ata_altstatus(ap); - drv_stat = ata_chk_status(ap); - - /* ack bmdma irq events */ - ap->ops->irq_clear(ap); - - printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x host_stat 0x%x\n", - ap->id, qc->tf.command, drv_stat, host_stat); - - ap->hsm_task_state = HSM_ST_IDLE; - - /* complete taskfile transaction */ - qc->err_mask |= AC_ERR_TIMEOUT; - break; - } - - spin_unlock_irqrestore(&host_set->lock, flags); - - ata_eh_qc_complete(qc); - - DPRINTK("EXIT\n"); -} - -/** - * ata_eng_timeout - Handle timeout of queued command - * @ap: Port on which timed-out command is active - * - * Some part of the kernel (currently, only the SCSI layer) - * has noticed that the active command on port @ap has not - * completed after a specified length of time. Handle this - * condition by disabling DMA (if necessary) and completing - * transactions, with error if necessary. - * - * This also handles the case of the "lost interrupt", where - * for some reason (possibly hardware bug, possibly driver bug) - * an interrupt was not delivered to the driver, even though the - * transaction completed successfully. - * - * LOCKING: - * Inherited from SCSI layer (none, can sleep) - */ - -void ata_eng_timeout(struct ata_port *ap) -{ - DPRINTK("ENTER\n"); - - ata_qc_timeout(ata_qc_from_tag(ap, ap->active_tag)); - - DPRINTK("EXIT\n"); -} - /** * ata_qc_new - Request an available ATA command, for queueing * @ap: Port associated with device @dev diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c index e73f5612aea..011e083b19e 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/scsi/libata-eh.c @@ -137,6 +137,7 @@ int ata_scsi_error(struct Scsi_Host *host) * LOCKING: * Inherited from SCSI layer (none, can sleep) */ + static void ata_qc_timeout(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; @@ -171,8 +172,10 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc) printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x host_stat 0x%x\n", ap->id, qc->tf.command, drv_stat, host_stat); + ap->hsm_task_state = HSM_ST_IDLE; + /* complete taskfile transaction */ - qc->err_mask |= ac_err_mask(drv_stat); + qc->err_mask |= AC_ERR_TIMEOUT; break; } -- cgit v1.2.3 From 6d5f9732a16a74d75f8cdba5b00557662e83f466 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 3 Apr 2006 00:09:41 +0900 Subject: [PATCH] libata: print SControl in SATA link status info message Now that libata mangles with SControl, it's helpful to print out SControl in link status message. Add it. Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 8beba3cd9a5..966be3034bf 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1503,20 +1503,23 @@ void ata_port_probe(struct ata_port *ap) */ static void sata_print_link_status(struct ata_port *ap) { - u32 sstatus, tmp; + u32 sstatus, scontrol, tmp; if (!ap->ops->scr_read) return; sstatus = scr_read(ap, SCR_STATUS); + scontrol = scr_read(ap, SCR_CONTROL); if (sata_dev_present(ap)) { tmp = (sstatus >> 4) & 0xf; - printk(KERN_INFO "ata%u: SATA link up %s (SStatus %X)\n", - ap->id, sata_spd_string(tmp), sstatus); + printk(KERN_INFO + "ata%u: SATA link up %s (SStatus %X SControl %X)\n", + ap->id, sata_spd_string(tmp), sstatus, scontrol); } else { - printk(KERN_INFO "ata%u: SATA link down (SStatus %X)\n", - ap->id, sstatus); + printk(KERN_INFO + "ata%u: SATA link down (SStatus %X SControl %X)\n", + ap->id, sstatus, scontrol); } } -- cgit v1.2.3 From 4bced2d40555eebf8d685f174aa6d58ace353655 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Sun, 2 Apr 2006 20:17:48 -0400 Subject: [libata] kill bogus cut-n-pasted comments in three drivers --- drivers/scsi/sata_promise.c | 4 ---- drivers/scsi/sata_sil.c | 4 ---- drivers/scsi/sata_sx4.c | 4 ---- 3 files changed, 12 deletions(-) diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index 9557c7aa45e..000844a4129 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c @@ -677,10 +677,6 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e if (!printed_version++) dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); - /* - * If this driver happens to only be useful on Apple's K2, then - * we should check that here as it has a normal Serverworks ID - */ rc = pci_enable_device(pdev); if (rc) return rc; diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index d6c7086a537..1aeb8136731 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -391,10 +391,6 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) if (!printed_version++) dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); - /* - * If this driver happens to only be useful on Apple's K2, then - * we should check that here as it has a normal Serverworks ID - */ rc = pci_enable_device(pdev); if (rc) return rc; diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c index 3af28ef76fd..be613958339 100644 --- a/drivers/scsi/sata_sx4.c +++ b/drivers/scsi/sata_sx4.c @@ -1376,10 +1376,6 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id * if (!printed_version++) dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); - /* - * If this driver happens to only be useful on Apple's K2, then - * we should check that here as it has a normal Serverworks ID - */ rc = pci_enable_device(pdev); if (rc) return rc; -- cgit v1.2.3 From af64371ada9452632c349563d688d30d94e918ba Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Sun, 2 Apr 2006 20:41:36 -0400 Subject: [libata] bump versions --- drivers/scsi/ahci.c | 2 +- drivers/scsi/ata_piix.c | 2 +- drivers/scsi/libata.h | 2 +- drivers/scsi/pdc_adma.c | 2 +- drivers/scsi/sata_nv.c | 2 +- drivers/scsi/sata_qstor.c | 2 +- drivers/scsi/sata_sil.c | 2 +- drivers/scsi/sata_sil24.c | 2 +- drivers/scsi/sata_sis.c | 2 +- drivers/scsi/sata_svw.c | 2 +- drivers/scsi/sata_sx4.c | 2 +- drivers/scsi/sata_uli.c | 2 +- drivers/scsi/sata_via.c | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 1bd82c4e52a..0c5f0c844d2 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -48,7 +48,7 @@ #include #define DRV_NAME "ahci" -#define DRV_VERSION "1.2" +#define DRV_VERSION "1.3" enum { diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index 24e71b55517..83839706f5e 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -93,7 +93,7 @@ #include #define DRV_NAME "ata_piix" -#define DRV_VERSION "1.05" +#define DRV_VERSION "1.10" enum { PIIX_IOCFG = 0x54, /* IDE I/O configuration register */ diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index 31efc2e60b6..e3bd1ddb538 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -29,7 +29,7 @@ #define __LIBATA_H__ #define DRV_NAME "libata" -#define DRV_VERSION "1.20" /* must be exactly four chars */ +#define DRV_VERSION "1.30" /* must be exactly four chars */ struct ata_scsi_args { struct ata_port *ap; diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c index d64073dd028..1364b1da9e2 100644 --- a/drivers/scsi/pdc_adma.c +++ b/drivers/scsi/pdc_adma.c @@ -46,7 +46,7 @@ #include #define DRV_NAME "pdc_adma" -#define DRV_VERSION "0.03" +#define DRV_VERSION "0.04" /* macro to calculate base address for ATA regs */ #define ADMA_ATA_REGS(base,port_no) ((base) + ((port_no) * 0x40)) diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c index 72721ac482d..c92fbd0989b 100644 --- a/drivers/scsi/sata_nv.c +++ b/drivers/scsi/sata_nv.c @@ -44,7 +44,7 @@ #include #define DRV_NAME "sata_nv" -#define DRV_VERSION "0.8" +#define DRV_VERSION "0.9" enum { NV_PORTS = 2, diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c index 8ef042a0944..0b5446ada5c 100644 --- a/drivers/scsi/sata_qstor.c +++ b/drivers/scsi/sata_qstor.c @@ -41,7 +41,7 @@ #include #define DRV_NAME "sata_qstor" -#define DRV_VERSION "0.05" +#define DRV_VERSION "0.06" enum { QS_PORTS = 4, diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index 1aeb8136731..f29c3e733a0 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -46,7 +46,7 @@ #include #define DRV_NAME "sata_sil" -#define DRV_VERSION "0.9" +#define DRV_VERSION "1.0" enum { /* diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index c34f6dabf41..646756abb10 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -31,7 +31,7 @@ #include #define DRV_NAME "sata_sil24" -#define DRV_VERSION "0.23" +#define DRV_VERSION "0.24" /* * Port request block (PRB) 32 bytes diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c index acc8439dea2..eb3cf5b534d 100644 --- a/drivers/scsi/sata_sis.c +++ b/drivers/scsi/sata_sis.c @@ -43,7 +43,7 @@ #include #define DRV_NAME "sata_sis" -#define DRV_VERSION "0.5" +#define DRV_VERSION "0.6" enum { sis_180 = 0, diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c index 724f0ed6a52..a20bc815475 100644 --- a/drivers/scsi/sata_svw.c +++ b/drivers/scsi/sata_svw.c @@ -54,7 +54,7 @@ #endif /* CONFIG_PPC_OF */ #define DRV_NAME "sata_svw" -#define DRV_VERSION "1.07" +#define DRV_VERSION "1.8" enum { /* Taskfile registers offsets */ diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c index be613958339..801ac3787d5 100644 --- a/drivers/scsi/sata_sx4.c +++ b/drivers/scsi/sata_sx4.c @@ -46,7 +46,7 @@ #include "sata_promise.h" #define DRV_NAME "sata_sx4" -#define DRV_VERSION "0.8" +#define DRV_VERSION "0.9" enum { diff --git a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c index 7ac5a5f5a90..513dd78ea6f 100644 --- a/drivers/scsi/sata_uli.c +++ b/drivers/scsi/sata_uli.c @@ -37,7 +37,7 @@ #include #define DRV_NAME "sata_uli" -#define DRV_VERSION "0.5" +#define DRV_VERSION "0.6" enum { uli_5289 = 0, diff --git a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c index 791bf652ba6..de4e0eb224b 100644 --- a/drivers/scsi/sata_via.c +++ b/drivers/scsi/sata_via.c @@ -47,7 +47,7 @@ #include #define DRV_NAME "sata_via" -#define DRV_VERSION "1.1" +#define DRV_VERSION "1.2" enum board_ids_enum { vt6420, -- cgit v1.2.3 From e6f1f3c54974a30c65ea0b699809d12f0aa04272 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 3 Apr 2006 13:14:00 -0400 Subject: ACPI: Don't print internal BIOS names of wakeup devices Internal BIOS names like these should be exposed to the user as little as possible: ACPI wakeup devices: C069 C0CE C1D1 C0DE C1D4 Eventually, the "wakeup" property of a device should be exported via the device tree, not by a printk of an internal BIOS name. For the hard-core, these are still available in /proc/acpi/wakeup_devices, just not printed to dmesg. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/sleep/wakeup.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/acpi/sleep/wakeup.c b/drivers/acpi/sleep/wakeup.c index 85df0ceda2a..af1dbabaf0b 100644 --- a/drivers/acpi/sleep/wakeup.c +++ b/drivers/acpi/sleep/wakeup.c @@ -155,7 +155,6 @@ static int __init acpi_wakeup_device_init(void) if (acpi_disabled) return 0; - printk("ACPI wakeup devices: \n"); spin_lock(&acpi_device_lock); list_for_each_safe(node, next, &acpi_wakeup_device_list) { @@ -174,10 +173,8 @@ static int __init acpi_wakeup_device_init(void) dev->wakeup.state.enabled = 1; spin_lock(&acpi_device_lock); } - printk("%4s ", dev->pnp.bus_id); } spin_unlock(&acpi_device_lock); - printk("\n"); return 0; } -- cgit v1.2.3 From 4332a771f4d2f23a6d3beff3dd5405e79775a211 Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Mon, 3 Apr 2006 17:43:24 +0800 Subject: [PATCH] libata-dev: irq-pio minor fix irq-pio minor fix: - remove the redundant hsm_task_state = HSM_ST_IDLE - add devno to printk() as done in upstream Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 8 ++++---- drivers/scsi/libata-eh.c | 3 --- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 56537293ad4..d270b23a03b 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -4043,8 +4043,8 @@ fsm_start: } /* no more data to transfer */ - DPRINTK("ata%u: command complete, drv_stat 0x%x\n", - ap->id, status); + DPRINTK("ata%u: dev %u command complete, drv_stat 0x%x\n", + ap->id, qc->dev->devno, status); WARN_ON(qc->err_mask); @@ -4061,8 +4061,8 @@ fsm_start: case HSM_ST_ERR: if (qc->tf.command != ATA_CMD_PACKET) - printk(KERN_ERR "ata%u: command error, drv_stat 0x%x\n", - ap->id, status); + printk(KERN_ERR "ata%u: dev %u command error, drv_stat 0x%x\n", + ap->id, qc->dev->devno, status); /* make sure qc->err_mask is available to * know what's wrong and recover diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c index 011e083b19e..9a8eea11b0b 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/scsi/libata-eh.c @@ -137,7 +137,6 @@ int ata_scsi_error(struct Scsi_Host *host) * LOCKING: * Inherited from SCSI layer (none, can sleep) */ - static void ata_qc_timeout(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; @@ -172,8 +171,6 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc) printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x host_stat 0x%x\n", ap->id, qc->tf.command, drv_stat, host_stat); - ap->hsm_task_state = HSM_ST_IDLE; - /* complete taskfile transaction */ qc->err_mask |= AC_ERR_TIMEOUT; break; -- cgit v1.2.3 From 31ce6daefe2d312e31ee06b0b3301b1cb7878c04 Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Mon, 3 Apr 2006 18:31:44 +0800 Subject: [PATCH] libata-dev: irq-pio minor fix 2 irq-pio minor fix 2: - Use qc as data for ata_pio_task(). Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index d270b23a03b..57b3240ee86 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -4097,9 +4097,6 @@ static void ata_pio_task(void *_data) fsm_start: WARN_ON(ap->hsm_task_state == HSM_ST_IDLE); - qc = ata_qc_from_tag(ap, ap->active_tag); - WARN_ON(qc == NULL); - /* * This is purely heuristic. This is a fast path. * Sometimes when we enter, BSY will be cleared in @@ -4112,7 +4109,7 @@ fsm_start: msleep(2); status = ata_busy_wait(ap, ATA_BUSY, 10); if (status & ATA_BUSY) { - ata_port_queue_task(ap, ata_pio_task, ap, ATA_SHORT_PAUSE); + ata_port_queue_task(ap, ata_pio_task, qc, ATA_SHORT_PAUSE); return; } } @@ -4347,7 +4344,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc) ap->hsm_task_state = HSM_ST_LAST; if (qc->tf.flags & ATA_TFLAG_POLLING) - ata_port_queue_task(ap, ata_pio_task, ap, 0); + ata_port_queue_task(ap, ata_pio_task, qc, 0); break; @@ -4369,7 +4366,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc) if (qc->tf.flags & ATA_TFLAG_WRITE) { /* PIO data out protocol */ ap->hsm_task_state = HSM_ST_FIRST; - ata_port_queue_task(ap, ata_pio_task, ap, 0); + ata_port_queue_task(ap, ata_pio_task, qc, 0); /* always send first data block using * the ata_pio_task() codepath. @@ -4379,7 +4376,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc) ap->hsm_task_state = HSM_ST; if (qc->tf.flags & ATA_TFLAG_POLLING) - ata_port_queue_task(ap, ata_pio_task, ap, 0); + ata_port_queue_task(ap, ata_pio_task, qc, 0); /* if polling, ata_pio_task() handles the rest. * otherwise, interrupt handler takes over from here. @@ -4400,7 +4397,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc) /* send cdb by polling if no cdb interrupt */ if ((!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) || (qc->tf.flags & ATA_TFLAG_POLLING)) - ata_port_queue_task(ap, ata_pio_task, ap, 0); + ata_port_queue_task(ap, ata_pio_task, qc, 0); break; case ATA_PROT_ATAPI_DMA: @@ -4412,7 +4409,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc) /* send cdb by polling if no cdb interrupt */ if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) - ata_port_queue_task(ap, ata_pio_task, ap, 0); + ata_port_queue_task(ap, ata_pio_task, qc, 0); break; default: -- cgit v1.2.3 From 95de719adc94392a95c3c4d0a2d6b8b1ea39d236 Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Tue, 4 Apr 2006 10:57:18 +0800 Subject: [PATCH] libata: convert ATAPI_ENABLE_DMADIR to module parameter Convert the ATAPI_ENABLE_DMADIR compile time option needed by some SATA-PATA bridge to runtime module parameter. Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 4 ++++ drivers/scsi/libata-scsi.c | 6 ++---- drivers/scsi/libata.h | 1 + include/linux/libata.h | 1 - 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 966be3034bf..3387fe35c54 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -76,6 +76,10 @@ int atapi_enabled = 1; module_param(atapi_enabled, int, 0444); MODULE_PARM_DESC(atapi_enabled, "Enable discovery of ATAPI devices (0=off, 1=on)"); +int atapi_dmadir = 0; +module_param(atapi_dmadir, int, 0444); +MODULE_PARM_DESC(atapi_dmadir, "Enable ATAPI DMADIR bridge support (0=off, 1=on)"); + int libata_fua = 0; module_param_named(fua, libata_fua, int, 0444); MODULE_PARM_DESC(fua, "FUA support (0=off, 1=on)"); diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 745fc263fee..c9c00149029 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -2163,11 +2163,9 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd) qc->tf.protocol = ATA_PROT_ATAPI_DMA; qc->tf.feature |= ATAPI_PKT_DMA; -#ifdef ATAPI_ENABLE_DMADIR - /* some SATA bridges need us to indicate data xfer direction */ - if (cmd->sc_data_direction != DMA_TO_DEVICE) + if (atapi_dmadir && (cmd->sc_data_direction != DMA_TO_DEVICE)) + /* some SATA bridges need us to indicate data xfer direction */ qc->tf.feature |= ATAPI_DMADIR; -#endif } qc->nbytes = cmd->bufflen; diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index e3bd1ddb538..652c08e3808 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -41,6 +41,7 @@ struct ata_scsi_args { /* libata-core.c */ extern int atapi_enabled; +extern int atapi_dmadir; extern int libata_fua; extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, struct ata_device *dev); diff --git a/include/linux/libata.h b/include/linux/libata.h index 75bdee09c30..03231cb6b40 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -44,7 +44,6 @@ #undef ATA_NDEBUG /* define to disable quick runtime checks */ #undef ATA_ENABLE_PATA /* define to enable PATA support in some * low-level drivers */ -#undef ATAPI_ENABLE_DMADIR /* enables ATAPI DMADIR bridge support */ /* note: prints function name for you */ -- cgit v1.2.3 From c2a6585296009379e0f4eff39cdcb108b457ebf2 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 3 Apr 2006 01:58:06 +0900 Subject: [PATCH] ahci: do not fail softreset if PHY reports no device All softreset methods are responsible for detecting device presence and succeed softreset in such cases. AHCI didn't use to check for device presence before proceeding with softreset and this caused unnecessary reset retrials during probing. This patch adds presence detection to AHCI softreset. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/ahci.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 0c5f0c844d2..ff48066d4c4 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -549,6 +549,12 @@ static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class) DPRINTK("ENTER\n"); + if (!sata_dev_present(ap)) { + DPRINTK("PHY reports no device\n"); + *class = ATA_DEV_NONE; + return 0; + } + /* prepare for SRST (AHCI-1.1 10.4.1) */ rc = ahci_stop_engine(ap); if (rc) { -- cgit v1.2.3 From 591f0a4287d0de243493fd0c133c862e1d1f1c97 Mon Sep 17 00:00:00 2001 From: Andy Fleming Date: Sun, 2 Apr 2006 17:42:40 -0500 Subject: Add 85xx CDS to arch/powerpc This patch adds support for 85xx CDS support to arch/powerpc Signed-off-by: Andy Fleming Signed-off-by: Kumar Gala --- arch/powerpc/configs/mpc85xx_cds_defconfig | 846 +++++++++++++++++++++++++++++ arch/powerpc/platforms/85xx/Kconfig | 9 +- arch/powerpc/platforms/85xx/Makefile | 1 + arch/powerpc/platforms/85xx/mpc85xx_cds.c | 359 ++++++++++++ arch/powerpc/platforms/85xx/mpc85xx_cds.h | 43 ++ include/asm-ppc/mpc85xx.h | 3 + 6 files changed, 1260 insertions(+), 1 deletion(-) create mode 100644 arch/powerpc/configs/mpc85xx_cds_defconfig create mode 100644 arch/powerpc/platforms/85xx/mpc85xx_cds.c create mode 100644 arch/powerpc/platforms/85xx/mpc85xx_cds.h diff --git a/arch/powerpc/configs/mpc85xx_cds_defconfig b/arch/powerpc/configs/mpc85xx_cds_defconfig new file mode 100644 index 00000000000..9bb022a523f --- /dev/null +++ b/arch/powerpc/configs/mpc85xx_cds_defconfig @@ -0,0 +1,846 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.16 +# Sun Apr 2 11:23:42 2006 +# +# CONFIG_PPC64 is not set +CONFIG_PPC32=y +CONFIG_PPC_MERGE=y +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_PPC=y +CONFIG_EARLY_PRINTK=y +CONFIG_GENERIC_NVRAM=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_PPC_OF=y +CONFIG_PPC_UDBG_16550=y +# CONFIG_GENERIC_TBSYNC is not set +# CONFIG_DEFAULT_UIMAGE is not set + +# +# Processor support +# +# CONFIG_CLASSIC32 is not set +# CONFIG_PPC_52xx is not set +# CONFIG_PPC_82xx is not set +# CONFIG_PPC_83xx is not set +CONFIG_PPC_85xx=y +# CONFIG_40x is not set +# CONFIG_44x is not set +# CONFIG_8xx is not set +# CONFIG_E200 is not set +CONFIG_85xx=y +CONFIG_E500=y +CONFIG_BOOKE=y +CONFIG_FSL_BOOKE=y +# CONFIG_PHYS_64BIT is not set +CONFIG_SPE=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +# CONFIG_RELAY is not set +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# Block layer +# +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" +CONFIG_MPIC=y +# CONFIG_WANT_EARLY_SERIAL is not set + +# +# Platform support +# +# CONFIG_MPC8540_ADS is not set +CONFIG_MPC85xx_CDS=y +CONFIG_MPC8540=y +CONFIG_PPC_INDIRECT_PCI_BE=y + +# +# Kernel options +# +# CONFIG_HIGHMEM is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=y +CONFIG_MATH_EMULATION=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_PROC_DEVICETREE=y +# CONFIG_CMDLINE_BOOL is not set +# CONFIG_PM is not set +# CONFIG_SOFTWARE_SUSPEND is not set +# CONFIG_SECCOMP is not set +CONFIG_ISA_DMA_API=y + +# +# Bus options +# +CONFIG_PPC_I8259=y +CONFIG_PPC_INDIRECT_PCI=y +CONFIG_FSL_SOC=y +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +# CONFIG_PCI_DEBUG is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# PCI Hotplug Support +# +# CONFIG_HOTPLUG_PCI is not set + +# +# Advanced setup +# +# CONFIG_ADVANCED_OPTIONS is not set + +# +# Default settings for advanced configuration options are used +# +CONFIG_HIGHMEM_START=0xfe000000 +CONFIG_LOWMEM_SIZE=0x30000000 +CONFIG_KERNEL_START=0xc0000000 +CONFIG_TASK_SIZE=0x80000000 +CONFIG_BOOT_LOAD=0x00800000 + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_DEBUG_DRIVER is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=32768 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +# CONFIG_BLK_DEV_IDEDISK is not set +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_IDE_TASK_IOCTL is not set + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_IDEPCI_SHARE_IRQ=y +# CONFIG_BLK_DEV_OFFBOARD is not set +CONFIG_BLK_DEV_GENERIC=y +# CONFIG_BLK_DEV_OPTI621 is not set +# CONFIG_BLK_DEV_SL82C105 is not set +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +# CONFIG_IDEDMA_PCI_AUTO is not set +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_BLK_DEV_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD74XX is not set +# CONFIG_BLK_DEV_CMD64X is not set +# CONFIG_BLK_DEV_TRIFLEX is not set +# CONFIG_BLK_DEV_CY82C693 is not set +# CONFIG_BLK_DEV_CS5520 is not set +# CONFIG_BLK_DEV_CS5530 is not set +# CONFIG_BLK_DEV_HPT34X is not set +# CONFIG_BLK_DEV_HPT366 is not set +# CONFIG_BLK_DEV_SC1200 is not set +# CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_IT821X is not set +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_PDC202XX_OLD is not set +# CONFIG_BLK_DEV_PDC202XX_NEW is not set +# CONFIG_BLK_DEV_SVWKS is not set +# CONFIG_BLK_DEV_SIIMAGE is not set +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +CONFIG_BLK_DEV_VIA82CXXX=y +# CONFIG_IDE_ARM is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Macintosh device drivers +# +# CONFIG_WINDFARM is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_NET_PCI is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +CONFIG_E1000=y +CONFIG_E1000_NAPI=y +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set +CONFIG_GIANFAR=y +CONFIG_GFAR_NAPI=y + +# +# Ethernet (10000 Mbit) +# +# CONFIG_CHELSIO_T1 is not set +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +CONFIG_GEN_RTC=y +# CONFIG_GEN_RTC_X is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +# CONFIG_USB is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# InfiniBand support +# +# CONFIG_INFINIBAND is not set + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# + +# +# Real Time Clock +# +# CONFIG_RTC_CLASS is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +# CONFIG_MSDOS_PARTITION is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set + +# +# Instrumentation Support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +# CONFIG_MAGIC_SYSRQ is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_UNWIND_INFO is not set +CONFIG_FORCED_INLINING=y +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_DEBUGGER is not set +# CONFIG_BDI_SWITCH is not set +# CONFIG_BOOTX_TEXT is not set +# CONFIG_PPC_EARLY_DEBUG_LPAR is not set +# CONFIG_PPC_EARLY_DEBUG_G5 is not set +# CONFIG_PPC_EARLY_DEBUG_RTAS is not set +# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set +# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Hardware crypto devices +# diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig index 06e371282f5..454fc53289a 100644 --- a/arch/powerpc/platforms/85xx/Kconfig +++ b/arch/powerpc/platforms/85xx/Kconfig @@ -11,13 +11,20 @@ config MPC8540_ADS help This option enables support for the MPC 8540 ADS board +config MPC85xx_CDS + bool "Freescale MPC85xx CDS" + select DEFAULT_UIMAGE + select PPC_I8259 if PCI + help + This option enables support for the MPC85xx CDS board + endchoice config MPC8540 bool select PPC_UDBG_16550 select PPC_INDIRECT_PCI - default y if MPC8540_ADS + default y if MPC8540_ADS || MPC85xx_CDS config PPC_INDIRECT_PCI_BE bool diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile index ffc4139cb21..7615aa59c78 100644 --- a/arch/powerpc/platforms/85xx/Makefile +++ b/arch/powerpc/platforms/85xx/Makefile @@ -3,3 +3,4 @@ # obj-$(CONFIG_PPC_85xx) += misc.o pci.o obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads.o +obj-$(CONFIG_MPC85xx_CDS) += mpc85xx_cds.o diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c new file mode 100644 index 00000000000..18e6e11f702 --- /dev/null +++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.c @@ -0,0 +1,359 @@ +/* + * MPC85xx setup and early boot code plus other random bits. + * + * Maintained by Kumar Gala (see MAINTAINERS for contact information) + * + * Copyright 2005 Freescale Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "mpc85xx.h" + +#ifndef CONFIG_PCI +unsigned long isa_io_base = 0; +unsigned long isa_mem_base = 0; +#endif + +static int cds_pci_slot = 2; +static volatile u8 *cadmus; + +/* + * Internal interrupts are all Level Sensitive, and Positive Polarity + * + * Note: Likely, this table and the following function should be + * obtained and derived from the OF Device Tree. + */ +static u_char mpc85xx_cds_openpic_initsenses[] __initdata = { + MPC85XX_INTERNAL_IRQ_SENSES, +#if defined(CONFIG_PCI) + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Ext 0: PCI slot 0 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext 1: PCI slot 1 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext 2: PCI slot 2 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext 3: PCI slot 3 */ +#else + 0x0, /* External 0: */ + 0x0, /* External 1: */ + 0x0, /* External 2: */ + 0x0, /* External 3: */ +#endif + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 5: PHY */ + 0x0, /* External 6: */ + 0x0, /* External 7: */ + 0x0, /* External 8: */ + 0x0, /* External 9: */ + 0x0, /* External 10: */ +#ifdef CONFIG_PCI + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext 11: PCI2 slot 0 */ +#else + 0x0, /* External 11: */ +#endif +}; + + +#ifdef CONFIG_PCI +/* + * interrupt routing + */ +int +mpc85xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) +{ + struct pci_controller *hose = pci_bus_to_hose(dev->bus->number); + + if (!hose->index) + { + /* Handle PCI1 interrupts */ + char pci_irq_table[][4] = + /* + * PCI IDSEL/INTPIN->INTLINE + * A B C D + */ + + /* Note IRQ assignment for slots is based on which slot the elysium is + * in -- in this setup elysium is in slot #2 (this PIRQA as first + * interrupt on slot */ + { + { 0, 1, 2, 3 }, /* 16 - PMC */ + { 0, 1, 2, 3 }, /* 17 P2P (Tsi320) */ + { 0, 1, 2, 3 }, /* 18 - Slot 1 */ + { 1, 2, 3, 0 }, /* 19 - Slot 2 */ + { 2, 3, 0, 1 }, /* 20 - Slot 3 */ + { 3, 0, 1, 2 }, /* 21 - Slot 4 */ + }; + + const long min_idsel = 16, max_idsel = 21, irqs_per_slot = 4; + int i, j; + + for (i = 0; i < 6; i++) + for (j = 0; j < 4; j++) + pci_irq_table[i][j] = + ((pci_irq_table[i][j] + 5 - + cds_pci_slot) & 0x3) + PIRQ0A; + + return PCI_IRQ_TABLE_LOOKUP; + } else { + /* Handle PCI2 interrupts (if we have one) */ + char pci_irq_table[][4] = + { + /* + * We only have one slot and one interrupt + * going to PIRQA - PIRQD */ + { PIRQ1A, PIRQ1A, PIRQ1A, PIRQ1A }, /* 21 - slot 0 */ + }; + + const long min_idsel = 21, max_idsel = 21, irqs_per_slot = 4; + + return PCI_IRQ_TABLE_LOOKUP; + } +} + +#define ARCADIA_HOST_BRIDGE_IDSEL 17 +#define ARCADIA_2ND_BRIDGE_IDSEL 3 + +extern int mpc85xx_pci2_busno; + +int +mpc85xx_exclude_device(u_char bus, u_char devfn) +{ + if (bus == 0 && PCI_SLOT(devfn) == 0) + return PCIBIOS_DEVICE_NOT_FOUND; + if (mpc85xx_pci2_busno) + if (bus == (mpc85xx_pci2_busno) && PCI_SLOT(devfn) == 0) + return PCIBIOS_DEVICE_NOT_FOUND; + /* We explicitly do not go past the Tundra 320 Bridge */ + if ((bus == 1) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL)) + return PCIBIOS_DEVICE_NOT_FOUND; + if ((bus == 0) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL)) + return PCIBIOS_DEVICE_NOT_FOUND; + else + return PCIBIOS_SUCCESSFUL; +} + +void __init +mpc85xx_cds_pcibios_fixup(void) +{ + struct pci_dev *dev; + u_char c; + + if ((dev = pci_get_device(PCI_VENDOR_ID_VIA, + PCI_DEVICE_ID_VIA_82C586_1, NULL))) { + /* + * U-Boot does not set the enable bits + * for the IDE device. Force them on here. + */ + pci_read_config_byte(dev, 0x40, &c); + c |= 0x03; /* IDE: Chip Enable Bits */ + pci_write_config_byte(dev, 0x40, c); + + /* + * Since only primary interface works, force the + * IDE function to standard primary IDE interrupt + * w/ 8259 offset + */ + dev->irq = 14; + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); + pci_dev_put(dev); + } + + /* + * Force legacy USB interrupt routing + */ + if ((dev = pci_get_device(PCI_VENDOR_ID_VIA, + PCI_DEVICE_ID_VIA_82C586_2, NULL))) { + dev->irq = 10; + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 10); + pci_dev_put(dev); + } + + if ((dev = pci_get_device(PCI_VENDOR_ID_VIA, + PCI_DEVICE_ID_VIA_82C586_2, dev))) { + dev->irq = 11; + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11); + pci_dev_put(dev); + } +} +#endif /* CONFIG_PCI */ + +void __init mpc85xx_cds_pic_init(void) +{ + struct mpic *mpic1; + phys_addr_t OpenPIC_PAddr; + + /* Determine the Physical Address of the OpenPIC regs */ + OpenPIC_PAddr = get_immrbase() + MPC85xx_OPENPIC_OFFSET; + + mpic1 = mpic_alloc(OpenPIC_PAddr, + MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, + 4, MPC85xx_OPENPIC_IRQ_OFFSET, 0, 250, + mpc85xx_cds_openpic_initsenses, + sizeof(mpc85xx_cds_openpic_initsenses), " OpenPIC "); + BUG_ON(mpic1 == NULL); + mpic_assign_isu(mpic1, 0, OpenPIC_PAddr + 0x10200); + mpic_assign_isu(mpic1, 1, OpenPIC_PAddr + 0x10280); + mpic_assign_isu(mpic1, 2, OpenPIC_PAddr + 0x10300); + mpic_assign_isu(mpic1, 3, OpenPIC_PAddr + 0x10380); + mpic_assign_isu(mpic1, 4, OpenPIC_PAddr + 0x10400); + mpic_assign_isu(mpic1, 5, OpenPIC_PAddr + 0x10480); + mpic_assign_isu(mpic1, 6, OpenPIC_PAddr + 0x10500); + mpic_assign_isu(mpic1, 7, OpenPIC_PAddr + 0x10580); + + /* dummy mappings to get to 48 */ + mpic_assign_isu(mpic1, 8, OpenPIC_PAddr + 0x10600); + mpic_assign_isu(mpic1, 9, OpenPIC_PAddr + 0x10680); + mpic_assign_isu(mpic1, 10, OpenPIC_PAddr + 0x10700); + mpic_assign_isu(mpic1, 11, OpenPIC_PAddr + 0x10780); + + /* External ints */ + mpic_assign_isu(mpic1, 12, OpenPIC_PAddr + 0x10000); + mpic_assign_isu(mpic1, 13, OpenPIC_PAddr + 0x10080); + mpic_assign_isu(mpic1, 14, OpenPIC_PAddr + 0x10100); + + mpic_init(mpic1); + +#ifdef CONFIG_PCI + mpic_setup_cascade(PIRQ0A, i8259_irq_cascade, NULL); + + i8259_init(0,0); +#endif +} + + +/* + * Setup the architecture + */ +static void __init +mpc85xx_cds_setup_arch(void) +{ + struct device_node *cpu; +#ifdef CONFIG_PCI + struct device_node *np; +#endif + + if (ppc_md.progress) + ppc_md.progress("mpc85xx_cds_setup_arch()", 0); + + cpu = of_find_node_by_type(NULL, "cpu"); + if (cpu != 0) { + unsigned int *fp; + + fp = (int *)get_property(cpu, "clock-frequency", NULL); + if (fp != 0) + loops_per_jiffy = *fp / HZ; + else + loops_per_jiffy = 500000000 / HZ; + of_node_put(cpu); + } + + cadmus = ioremap(CADMUS_BASE, CADMUS_SIZE); + cds_pci_slot = ((cadmus[CM_CSR] >> 6) & 0x3) + 1; + + if (ppc_md.progress) { + char buf[40]; + snprintf(buf, 40, "CDS Version = 0x%x in slot %d\n", + cadmus[CM_VER], cds_pci_slot); + ppc_md.progress(buf, 0); + } + +#ifdef CONFIG_PCI + for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) + add_bridge(np); + + ppc_md.pcibios_fixup = mpc85xx_cds_pcibios_fixup; + ppc_md.pci_swizzle = common_swizzle; + ppc_md.pci_map_irq = mpc85xx_map_irq; + ppc_md.pci_exclude_device = mpc85xx_exclude_device; +#endif + +#ifdef CONFIG_ROOT_NFS + ROOT_DEV = Root_NFS; +#else + ROOT_DEV = Root_HDA1; +#endif +} + + +void +mpc85xx_cds_show_cpuinfo(struct seq_file *m) +{ + uint pvid, svid, phid1; + uint memsize = total_memory; + + pvid = mfspr(SPRN_PVR); + svid = mfspr(SPRN_SVR); + + seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n"); + seq_printf(m, "Machine\t\t: MPC85xx CDS (0x%x)\n", cadmus[CM_VER]); + seq_printf(m, "PVR\t\t: 0x%x\n", pvid); + seq_printf(m, "SVR\t\t: 0x%x\n", svid); + + /* Display cpu Pll setting */ + phid1 = mfspr(SPRN_HID1); + seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); + + /* Display the amount of memory */ + seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); +} + + +/* + * Called very early, device-tree isn't unflattened + */ +static int __init mpc85xx_cds_probe(void) +{ + /* We always match for now, eventually we should look at + * the flat dev tree to ensure this is the board we are + * supposed to run on + */ + return 1; +} + +define_machine(mpc85xx_cds) { + .name = "MPC85xx CDS", + .probe = mpc85xx_cds_probe, + .setup_arch = mpc85xx_cds_setup_arch, + .init_IRQ = mpc85xx_cds_pic_init, + .show_cpuinfo = mpc85xx_cds_show_cpuinfo, + .get_irq = mpic_get_irq, + .restart = mpc85xx_restart, + .calibrate_decr = generic_calibrate_decr, + .progress = udbg_progress, +}; diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.h b/arch/powerpc/platforms/85xx/mpc85xx_cds.h new file mode 100644 index 00000000000..671f54ff185 --- /dev/null +++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.h @@ -0,0 +1,43 @@ +/* + * arch/ppc/platforms/85xx/mpc85xx_cds_common.h + * + * MPC85xx CDS board definitions + * + * Maintainer: Kumar Gala + * + * Copyright 2004 Freescale Semiconductor, Inc + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#ifndef __MACH_MPC85XX_CDS_H__ +#define __MACH_MPC85XX_CDS_H__ + +/* CADMUS info */ +#define CADMUS_BASE (0xf8004000) +#define CADMUS_SIZE (256) +#define CM_VER (0) +#define CM_CSR (1) +#define CM_RST (2) + +/* CDS NVRAM/RTC */ +#define CDS_RTC_ADDR (0xf8000000) +#define CDS_RTC_SIZE (8 * 1024) + +/* PCI interrupt controller */ +#define PIRQ0A MPC85xx_IRQ_EXT0 +#define PIRQ0B MPC85xx_IRQ_EXT1 +#define PIRQ0C MPC85xx_IRQ_EXT2 +#define PIRQ0D MPC85xx_IRQ_EXT3 +#define PIRQ1A MPC85xx_IRQ_EXT11 + +#define NR_8259_INTS 16 +#define CPM_IRQ_OFFSET NR_8259_INTS + +#define MPC85xx_OPENPIC_IRQ_OFFSET 80 + +#endif /* __MACH_MPC85XX_CDS_H__ */ diff --git a/include/asm-ppc/mpc85xx.h b/include/asm-ppc/mpc85xx.h index f47002a60ed..4f844ebe766 100644 --- a/include/asm-ppc/mpc85xx.h +++ b/include/asm-ppc/mpc85xx.h @@ -28,6 +28,9 @@ #if defined(CONFIG_MPC8555_CDS) || defined(CONFIG_MPC8548_CDS) #include #endif +#ifdef CONFIG_MPC85xx_CDS +#include +#endif #ifdef CONFIG_MPC8560_ADS #include #endif -- cgit v1.2.3 From 381544bba3ae6f2f1004b267da34f840b469033c Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Tue, 11 Apr 2006 13:04:39 -0400 Subject: libata: Fix EH merge difference between this branch and upstream. --- drivers/scsi/libata-eh.c | 3 +-- drivers/scsi/libata.h | 1 + include/linux/libata.h | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c index e73f5612aea..b518654b9d6 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/scsi/libata-eh.c @@ -97,7 +97,7 @@ enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd) * RETURNS: * Zero. */ -int ata_scsi_error(struct Scsi_Host *host) +void ata_scsi_error(struct Scsi_Host *host) { struct ata_port *ap = (struct ata_port *)&host->hostdata[0]; @@ -116,7 +116,6 @@ int ata_scsi_error(struct Scsi_Host *host) scsi_eh_flush_done_q(&ap->eh_done_q); DPRINTK("EXIT\n"); - return 0; } /** diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index 652c08e3808..b18d377588d 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -105,5 +105,6 @@ extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args, /* libata-eh.c */ extern enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd); +extern void ata_scsi_error(struct Scsi_Host *host); #endif /* __LIBATA_H__ */ diff --git a/include/linux/libata.h b/include/linux/libata.h index a7161d42d18..2564bc514bc 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -637,7 +637,6 @@ extern unsigned long ata_pci_default_filter(const struct ata_port *, struct ata_ /* * EH */ -extern int ata_scsi_error(struct Scsi_Host *host); extern void ata_eng_timeout(struct ata_port *ap); extern void ata_eh_qc_complete(struct ata_queued_cmd *qc); extern void ata_eh_qc_retry(struct ata_queued_cmd *qc); -- cgit v1.2.3 From 35bb94b116e1fd4959ef0d3187458b5820eac8c4 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Tue, 11 Apr 2006 13:12:34 -0400 Subject: libata: Add helper ata_shost_to_port() --- drivers/scsi/libata-core.c | 4 ++-- drivers/scsi/libata-eh.c | 4 ++-- drivers/scsi/libata-scsi.c | 8 ++++---- drivers/scsi/sata_svw.c | 2 +- include/linux/libata.h | 6 ++++++ 5 files changed, 15 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 3387fe35c54..6420062f2c1 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -4659,7 +4659,7 @@ static struct ata_port * ata_host_add(const struct ata_probe_ent *ent, host->transportt = &ata_scsi_transport_template; - ap = (struct ata_port *) &host->hostdata[0]; + ap = ata_shost_to_port(host); ata_host_init(ap, host, host_set, ent, port_no); @@ -4872,7 +4872,7 @@ void ata_host_set_remove(struct ata_host_set *host_set) int ata_scsi_release(struct Scsi_Host *host) { - struct ata_port *ap = (struct ata_port *) &host->hostdata[0]; + struct ata_port *ap = ata_shost_to_port(host); int i; DPRINTK("ENTER\n"); diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c index b518654b9d6..c31b13fd530 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/scsi/libata-eh.c @@ -64,7 +64,7 @@ enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd) { struct Scsi_Host *host = cmd->device->host; - struct ata_port *ap = (struct ata_port *) &host->hostdata[0]; + struct ata_port *ap = ata_shost_to_port(host); unsigned long flags; struct ata_queued_cmd *qc; enum scsi_eh_timer_return ret = EH_HANDLED; @@ -99,7 +99,7 @@ enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd) */ void ata_scsi_error(struct Scsi_Host *host) { - struct ata_port *ap = (struct ata_port *)&host->hostdata[0]; + struct ata_port *ap = ata_shost_to_port(host); DPRINTK("ENTER\n"); diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 5ae7613bc15..9871f8272df 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -395,7 +395,7 @@ void ata_dump_status(unsigned id, struct ata_taskfile *tf) int ata_scsi_device_resume(struct scsi_device *sdev) { - struct ata_port *ap = (struct ata_port *) &sdev->host->hostdata[0]; + struct ata_port *ap = ata_shost_to_port(sdev->host); struct ata_device *dev = &ap->device[sdev->id]; return ata_device_resume(ap, dev); @@ -403,7 +403,7 @@ int ata_scsi_device_resume(struct scsi_device *sdev) int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t state) { - struct ata_port *ap = (struct ata_port *) &sdev->host->hostdata[0]; + struct ata_port *ap = ata_shost_to_port(sdev->host); struct ata_device *dev = &ap->device[sdev->id]; return ata_device_suspend(ap, dev, state); @@ -704,7 +704,7 @@ int ata_scsi_slave_config(struct scsi_device *sdev) struct ata_port *ap; struct ata_device *dev; - ap = (struct ata_port *) &sdev->host->hostdata[0]; + ap = ata_shost_to_port(sdev->host); dev = &ap->device[sdev->id]; ata_scsi_dev_config(sdev, dev); @@ -2478,7 +2478,7 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) struct scsi_device *scsidev = cmd->device; struct Scsi_Host *shost = scsidev->host; - ap = (struct ata_port *) &shost->hostdata[0]; + ap = ata_shost_to_port(shost); spin_unlock(shost->host_lock); spin_lock(&ap->host_set->lock); diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c index e15c693e053..d5eb5375e26 100644 --- a/drivers/scsi/sata_svw.c +++ b/drivers/scsi/sata_svw.c @@ -257,7 +257,7 @@ static int k2_sata_proc_info(struct Scsi_Host *shost, char *page, char **start, int len, index; /* Find the ata_port */ - ap = (struct ata_port *) &shost->hostdata[0]; + ap = ata_shost_to_port(shost); if (ap == NULL) return 0; diff --git a/include/linux/libata.h b/include/linux/libata.h index 2564bc514bc..fe0a1dcc76c 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -33,6 +33,7 @@ #include #include #include +#include /* * compile-time options: to be removed as soon as all the drivers are @@ -977,4 +978,9 @@ static inline void ata_pad_free(struct ata_port *ap, struct device *dev) dma_free_coherent(dev, ATA_DMA_PAD_BUF_SZ, ap->pad, ap->pad_dma); } +static inline struct ata_port *ata_shost_to_port(struct Scsi_Host *host) +{ + return (struct ata_port *) &host->hostdata[0]; +} + #endif /* __LINUX_LIBATA_H__ */ -- cgit v1.2.3 From db70fef0750e5f8dbb64f9fadb333d2c7caf26a1 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 11 Apr 2006 22:16:44 +0900 Subject: [PATCH] libata: set default cbl in probeinit Make setting CBL type responsibility of probeinit. This allows using only ap->cbl == ATA_CBL_SATA test in all other parts. Without this, ata_down_sata_spd_limit() doesn't work during probe reset. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 6420062f2c1..f37179623ef 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2369,12 +2369,16 @@ void ata_std_probeinit(struct ata_port *ap) if ((ap->flags & ATA_FLAG_SATA) && ap->ops->scr_read) { u32 spd; + /* set cable type and resume link */ + ap->cbl = ATA_CBL_SATA; sata_phy_resume(ap); + /* init sata_spd_limit to the current value */ spd = (scr_read(ap, SCR_CONTROL) & 0xf0) >> 4; if (spd) ap->sata_spd_limit &= (1 << spd) - 1; + /* wait for device */ if (sata_dev_present(ap)) ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT); } @@ -2531,10 +2535,6 @@ void ata_std_postreset(struct ata_port *ap, unsigned int *classes) { DPRINTK("ENTER\n"); - /* set cable type if it isn't already set */ - if (ap->cbl == ATA_CBL_NONE && ap->flags & ATA_FLAG_SATA) - ap->cbl = ATA_CBL_SATA; - /* print link status */ if (ap->cbl == ATA_CBL_SATA) sata_print_link_status(ap); @@ -2584,7 +2584,7 @@ int ata_std_probe_reset(struct ata_port *ap, unsigned int *classes) ata_reset_fn_t hardreset; hardreset = NULL; - if (ap->flags & ATA_FLAG_SATA && ap->ops->scr_read) + if (ap->cbl == ATA_CBL_SATA && ap->ops->scr_read) hardreset = sata_std_hardreset; return ata_drive_probe_reset(ap, ata_std_probeinit, -- cgit v1.2.3 From 2bf2cb26b2512c6a609bb152982c388329bedff6 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 11 Apr 2006 22:16:45 +0900 Subject: [PATCH] libata: kill @verbose from ata_reset_fn_t @verbose was added to ata_reset_fn_t because AHCI complained during probing if no device was attached to the port. However, muting failure message isn't the correct approach. Reset methods are responsible for detecting no device condition and finishing successfully. Now that AHCI softreset is fixed, kill @verbose. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/ahci.c | 13 +++++-------- drivers/scsi/libata-core.c | 36 ++++++++++++------------------------ drivers/scsi/libata.h | 6 ++---- drivers/scsi/sata_sil24.c | 8 +++----- include/linux/libata.h | 8 +++----- 5 files changed, 25 insertions(+), 46 deletions(-) diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 20fc0846e0b..0e7fb9bf2cd 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -534,7 +534,7 @@ static int ahci_poll_register(void __iomem *reg, u32 mask, u32 val, return -1; } -static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class) +static int ahci_softreset(struct ata_port *ap, unsigned int *class) { struct ahci_host_priv *hpriv = ap->host_set->private_data; struct ahci_port_priv *pp = ap->private_data; @@ -646,22 +646,19 @@ static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class) fail_restart: ahci_start_engine(ap); fail: - if (verbose) - printk(KERN_ERR "ata%u: softreset failed (%s)\n", - ap->id, reason); - else - DPRINTK("EXIT, rc=%d reason=\"%s\"\n", rc, reason); + printk(KERN_ERR "ata%u: softreset failed (%s)\n", + ap->id, reason); return rc; } -static int ahci_hardreset(struct ata_port *ap, int verbose, unsigned int *class) +static int ahci_hardreset(struct ata_port *ap, unsigned int *class) { int rc; DPRINTK("ENTER\n"); ahci_stop_engine(ap); - rc = sata_std_hardreset(ap, verbose, class); + rc = sata_std_hardreset(ap, class); ahci_start_engine(ap); if (rc == 0) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index f37179623ef..92b5077ac05 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2387,7 +2387,6 @@ void ata_std_probeinit(struct ata_port *ap) /** * ata_std_softreset - reset host port via ATA SRST * @ap: port to reset - * @verbose: fail verbosely * @classes: resulting classes of attached devices * * Reset host port using ATA SRST. This function is to be used @@ -2399,7 +2398,7 @@ void ata_std_probeinit(struct ata_port *ap) * RETURNS: * 0 on success, -errno otherwise. */ -int ata_std_softreset(struct ata_port *ap, int verbose, unsigned int *classes) +int ata_std_softreset(struct ata_port *ap, unsigned int *classes) { unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS; unsigned int devmask = 0, err_mask; @@ -2425,12 +2424,8 @@ int ata_std_softreset(struct ata_port *ap, int verbose, unsigned int *classes) DPRINTK("about to softreset, devmask=%x\n", devmask); err_mask = ata_bus_softreset(ap, devmask); if (err_mask) { - if (verbose) - printk(KERN_ERR "ata%u: SRST failed (err_mask=0x%x)\n", - ap->id, err_mask); - else - DPRINTK("EXIT, softreset failed (err_mask=0x%x)\n", - err_mask); + printk(KERN_ERR "ata%u: SRST failed (err_mask=0x%x)\n", + ap->id, err_mask); return -EIO; } @@ -2447,7 +2442,6 @@ int ata_std_softreset(struct ata_port *ap, int verbose, unsigned int *classes) /** * sata_std_hardreset - reset host port via SATA phy reset * @ap: port to reset - * @verbose: fail verbosely * @class: resulting class of attached device * * SATA phy-reset host port using DET bits of SControl register. @@ -2460,7 +2454,7 @@ int ata_std_softreset(struct ata_port *ap, int verbose, unsigned int *classes) * RETURNS: * 0 on success, -errno otherwise. */ -int sata_std_hardreset(struct ata_port *ap, int verbose, unsigned int *class) +int sata_std_hardreset(struct ata_port *ap, unsigned int *class) { u32 scontrol; @@ -2500,11 +2494,8 @@ int sata_std_hardreset(struct ata_port *ap, int verbose, unsigned int *class) } if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) { - if (verbose) - printk(KERN_ERR "ata%u: COMRESET failed " - "(device not ready)\n", ap->id); - else - DPRINTK("EXIT, device not ready\n"); + printk(KERN_ERR "ata%u: COMRESET failed " + "(device not ready)\n", ap->id); return -EIO; } @@ -2592,16 +2583,15 @@ int ata_std_probe_reset(struct ata_port *ap, unsigned int *classes) ata_std_postreset, classes); } -int ata_do_reset(struct ata_port *ap, - ata_reset_fn_t reset, ata_postreset_fn_t postreset, - int verbose, unsigned int *classes) +int ata_do_reset(struct ata_port *ap, ata_reset_fn_t reset, + ata_postreset_fn_t postreset, unsigned int *classes) { int i, rc; for (i = 0; i < ATA_MAX_DEVICES; i++) classes[i] = ATA_DEV_UNKNOWN; - rc = reset(ap, verbose, classes); + rc = reset(ap, classes); if (rc) return rc; @@ -2645,8 +2635,6 @@ int ata_do_reset(struct ata_port *ap, * - If classification is supported, fill classes[] with * recognized class codes. * - If classification is not supported, leave classes[] alone. - * - If verbose is non-zero, print error message on failure; - * otherwise, shut up. * * LOCKING: * Kernel thread context (may sleep) @@ -2666,7 +2654,7 @@ int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, probeinit(ap); if (softreset && !ata_set_sata_spd_needed(ap)) { - rc = ata_do_reset(ap, softreset, postreset, 0, classes); + rc = ata_do_reset(ap, softreset, postreset, classes); if (rc == 0 && classes[0] != ATA_DEV_UNKNOWN) goto done; printk(KERN_INFO "ata%u: softreset failed, will try " @@ -2678,7 +2666,7 @@ int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, goto done; while (1) { - rc = ata_do_reset(ap, hardreset, postreset, 0, classes); + rc = ata_do_reset(ap, hardreset, postreset, classes); if (rc == 0) { if (classes[0] != ATA_DEV_UNKNOWN) goto done; @@ -2699,7 +2687,7 @@ int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, ap->id); ssleep(5); - rc = ata_do_reset(ap, softreset, postreset, 0, classes); + rc = ata_do_reset(ap, softreset, postreset, classes); } done: diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index b18d377588d..3f8b0a86378 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -56,10 +56,8 @@ extern int ata_set_sata_spd_needed(struct ata_port *ap); extern int ata_down_xfermask_limit(struct ata_port *ap, struct ata_device *dev, int force_pio0); extern int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev); -extern int ata_do_reset(struct ata_port *ap, - ata_reset_fn_t reset, - ata_postreset_fn_t postreset, - int verbose, unsigned int *classes); +extern int ata_do_reset(struct ata_port *ap, ata_reset_fn_t reset, + ata_postreset_fn_t postreset, unsigned int *classes); extern void ata_qc_free(struct ata_queued_cmd *qc); extern void ata_qc_issue(struct ata_queued_cmd *qc); extern int ata_check_atapi_dma(struct ata_queued_cmd *qc); diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 9aa7493ea14..26d84e094b1 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -426,8 +426,7 @@ static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf) *tf = pp->tf; } -static int sil24_softreset(struct ata_port *ap, int verbose, - unsigned int *class) +static int sil24_softreset(struct ata_port *ap, unsigned int *class) { void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; struct sil24_port_priv *pp = ap->private_data; @@ -489,13 +488,12 @@ static int sil24_softreset(struct ata_port *ap, int verbose, return 0; } -static int sil24_hardreset(struct ata_port *ap, int verbose, - unsigned int *class) +static int sil24_hardreset(struct ata_port *ap, unsigned int *class) { unsigned int dummy_class; /* sil24 doesn't report device signature after hard reset */ - return sata_std_hardreset(ap, verbose, &dummy_class); + return sata_std_hardreset(ap, &dummy_class); } static int sil24_probe_reset(struct ata_port *ap, unsigned int *classes) diff --git a/include/linux/libata.h b/include/linux/libata.h index fe0a1dcc76c..d5fd5c06e75 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -252,7 +252,7 @@ struct ata_queued_cmd; /* typedefs */ typedef void (*ata_qc_cb_t) (struct ata_queued_cmd *qc); typedef void (*ata_probeinit_fn_t)(struct ata_port *); -typedef int (*ata_reset_fn_t)(struct ata_port *, int, unsigned int *); +typedef int (*ata_reset_fn_t)(struct ata_port *, unsigned int *); typedef void (*ata_postreset_fn_t)(struct ata_port *ap, unsigned int *); struct ata_ioports { @@ -509,10 +509,8 @@ extern int ata_drive_probe_reset(struct ata_port *ap, ata_reset_fn_t softreset, ata_reset_fn_t hardreset, ata_postreset_fn_t postreset, unsigned int *classes); extern void ata_std_probeinit(struct ata_port *ap); -extern int ata_std_softreset(struct ata_port *ap, int verbose, - unsigned int *classes); -extern int sata_std_hardreset(struct ata_port *ap, int verbose, - unsigned int *class); +extern int ata_std_softreset(struct ata_port *ap, unsigned int *classes); +extern int sata_std_hardreset(struct ata_port *ap, unsigned int *class); extern void ata_std_postreset(struct ata_port *ap, unsigned int *classes); extern int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev, int post_reset); -- cgit v1.2.3 From 987d2f05b396760517eef7cba66b2f415ac484f5 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 11 Apr 2006 22:16:45 +0900 Subject: [PATCH] libata: make reset methods complain when they fail Make reset methods complain loud when they fail. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 8 +++++--- drivers/scsi/sata_sil24.c | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 92b5077ac05..2d76ce23728 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2232,8 +2232,10 @@ static unsigned int ata_bus_softreset(struct ata_port *ap, * the bus shows 0xFF because the odd clown forgets the D7 * pulldown resistor. */ - if (ata_check_status(ap) == 0xFF) + if (ata_check_status(ap) == 0xFF) { + printk(KERN_ERR "ata%u: SRST failed (status 0xFF)\n", ap->id); return AC_ERR_OTHER; + } ata_bus_post_reset(ap, devmask); @@ -2494,8 +2496,8 @@ int sata_std_hardreset(struct ata_port *ap, unsigned int *class) } if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) { - printk(KERN_ERR "ata%u: COMRESET failed " - "(device not ready)\n", ap->id); + printk(KERN_ERR + "ata%u: COMRESET failed (device not ready)\n", ap->id); return -EIO; } diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 26d84e094b1..a9506adadb6 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -473,7 +473,7 @@ static int sil24_softreset(struct ata_port *ap, unsigned int *class) writel(irq_enable, port + PORT_IRQ_ENABLE_SET); if (!(irq_stat & PORT_IRQ_COMPLETE)) { - DPRINTK("EXIT, srst failed\n"); + printk(KERN_ERR "ata%u: softreset failed (timeout)\n", ap->id); return -EIO; } -- cgit v1.2.3 From 1c1d832cea1ab851a3f9b9d83245f5bc8b5b04b6 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 11 Apr 2006 22:22:29 +0900 Subject: [PATCH] sata_sil24: fix timeout calculation in sil24_softreset sil24_softreset calculated timeout by adding ATA_TMOUT_BOOT * HZ to jiffies; however, as ATA_TMOUT_BOOT is already in jiffies, multiplying by HZ makes the value way off. Fix it. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/sata_sil24.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index a9506adadb6..24eed37a063 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -432,7 +432,7 @@ static int sil24_softreset(struct ata_port *ap, unsigned int *class) struct sil24_port_priv *pp = ap->private_data; struct sil24_prb *prb = &pp->cmd_block[0].ata.prb; dma_addr_t paddr = pp->cmd_block_dma; - unsigned long timeout = jiffies + ATA_TMOUT_BOOT * HZ; + unsigned long timeout = jiffies + ATA_TMOUT_BOOT; u32 irq_enable, irq_stat; DPRINTK("ENTER\n"); -- cgit v1.2.3 From 643be977f9feba8c3c1e768fc06cac84596ec6f8 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 11 Apr 2006 22:22:29 +0900 Subject: [PATCH] sata_sil24: better error message from softreset Improve softreset error message. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/sata_sil24.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 24eed37a063..d6cfd8eb29b 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -434,6 +434,7 @@ static int sil24_softreset(struct ata_port *ap, unsigned int *class) dma_addr_t paddr = pp->cmd_block_dma; unsigned long timeout = jiffies + ATA_TMOUT_BOOT; u32 irq_enable, irq_stat; + const char *reason; DPRINTK("ENTER\n"); @@ -473,8 +474,11 @@ static int sil24_softreset(struct ata_port *ap, unsigned int *class) writel(irq_enable, port + PORT_IRQ_ENABLE_SET); if (!(irq_stat & PORT_IRQ_COMPLETE)) { - printk(KERN_ERR "ata%u: softreset failed (timeout)\n", ap->id); - return -EIO; + if (irq_stat & PORT_IRQ_ERROR) + reason = "SRST command error"; + else + reason = "timeout"; + goto err; } sil24_update_tf(ap); @@ -486,6 +490,10 @@ static int sil24_softreset(struct ata_port *ap, unsigned int *class) out: DPRINTK("EXIT, class=%u\n", *class); return 0; + + err: + printk(KERN_ERR "ata%u: softreset failed (%s)\n", ap->id, reason); + return -EIO; } static int sil24_hardreset(struct ata_port *ap, unsigned int *class) -- cgit v1.2.3 From c22daff41001e9ccead87179ac0547f85447139e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 11 Apr 2006 22:22:29 +0900 Subject: [PATCH] libata: implement ata_wait_register() As waiting for some register bits to change seems to be a common operation shared by some controllers, implement helper function ata_wait_register(). This function also takes care of register write flushing. Note that the condition is inverted, the wait is over when the masked value does NOT match @val. As we're waiting for bits to change, this test is more powerful and allows the function to be used in more places. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++ include/linux/libata.h | 3 +++ 2 files changed, 50 insertions(+) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 2d76ce23728..0075fe7404d 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -5029,6 +5029,52 @@ int ata_ratelimit(void) return rc; } +/** + * ata_wait_register - wait until register value changes + * @reg: IO-mapped register + * @mask: Mask to apply to read register value + * @val: Wait condition + * @interval_msec: polling interval in milliseconds + * @timeout_msec: timeout in milliseconds + * + * Waiting for some bits of register to change is a common + * operation for ATA controllers. This function reads 32bit LE + * IO-mapped register @reg and tests for the following condition. + * + * (*@reg & mask) != val + * + * If the condition is met, it returns; otherwise, the process is + * repeated after @interval_msec until timeout. + * + * LOCKING: + * Kernel thread context (may sleep) + * + * RETURNS: + * The final register value. + */ +u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val, + unsigned long interval_msec, + unsigned long timeout_msec) +{ + unsigned long timeout; + u32 tmp; + + tmp = ioread32(reg); + + /* Calculate timeout _after_ the first read to make sure + * preceding writes reach the controller before starting to + * eat away the timeout. + */ + timeout = jiffies + (timeout_msec * HZ) / 1000; + + while ((tmp & mask) == val && time_before(jiffies, timeout)) { + msleep(interval_msec); + tmp = ioread32(reg); + } + + return tmp; +} + /* * libata is essentially a library of internal helper functions for * low-level ATA host controller drivers. As such, the API/ABI is @@ -5079,6 +5125,7 @@ EXPORT_SYMBOL_GPL(ata_dev_classify); EXPORT_SYMBOL_GPL(ata_dev_pair); EXPORT_SYMBOL_GPL(ata_port_disable); EXPORT_SYMBOL_GPL(ata_ratelimit); +EXPORT_SYMBOL_GPL(ata_wait_register); EXPORT_SYMBOL_GPL(ata_busy_sleep); EXPORT_SYMBOL_GPL(ata_port_queue_task); EXPORT_SYMBOL_GPL(ata_scsi_ioctl); diff --git a/include/linux/libata.h b/include/linux/libata.h index d5fd5c06e75..dd5bcb5d29b 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -543,6 +543,9 @@ extern unsigned int ata_busy_sleep(struct ata_port *ap, unsigned long timeout); extern void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *), void *data, unsigned long delay); +extern u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val, + unsigned long interval_msec, + unsigned long timeout_msec); /* * Default driver ops implementations -- cgit v1.2.3 From 75fe18069a55c78f553643b4e3a24c6864d71d87 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 11 Apr 2006 22:22:29 +0900 Subject: [PATCH] ahci: use ata_wait_register() Replace ahci_poll_register() with ata_wait_register(). Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/ahci.c | 31 ++++++------------------------- 1 file changed, 6 insertions(+), 25 deletions(-) diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 0e7fb9bf2cd..1b8429cb3c9 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -516,24 +516,6 @@ static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, u32 opts) pp->cmd_slot[0].tbl_addr_hi = cpu_to_le32((pp->cmd_tbl_dma >> 16) >> 16); } -static int ahci_poll_register(void __iomem *reg, u32 mask, u32 val, - unsigned long interval_msec, - unsigned long timeout_msec) -{ - unsigned long timeout; - u32 tmp; - - timeout = jiffies + (timeout_msec * HZ) / 1000; - do { - tmp = readl(reg); - if ((tmp & mask) == val) - return 0; - msleep(interval_msec); - } while (time_before(jiffies, timeout)); - - return -1; -} - static int ahci_softreset(struct ata_port *ap, unsigned int *class) { struct ahci_host_priv *hpriv = ap->host_set->private_data; @@ -543,6 +525,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class) const u32 cmd_fis_len = 5; /* five dwords */ const char *reason = NULL; struct ata_taskfile tf; + u32 tmp; u8 *fis; int rc; @@ -564,8 +547,6 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class) /* check BUSY/DRQ, perform Command List Override if necessary */ ahci_tf_read(ap, &tf); if (tf.command & (ATA_BUSY | ATA_DRQ)) { - u32 tmp; - if (!(hpriv->cap & HOST_CAP_CLO)) { rc = -EIO; reason = "port busy but no CLO"; @@ -575,10 +556,10 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class) tmp = readl(port_mmio + PORT_CMD); tmp |= PORT_CMD_CLO; writel(tmp, port_mmio + PORT_CMD); - readl(port_mmio + PORT_CMD); /* flush */ - if (ahci_poll_register(port_mmio + PORT_CMD, PORT_CMD_CLO, 0x0, - 1, 500)) { + tmp = ata_wait_register(port_mmio + PORT_CMD, + PORT_CMD_CLO, PORT_CMD_CLO, 1, 500); + if (tmp & PORT_CMD_CLO) { rc = -EIO; reason = "CLO failed"; goto fail_restart; @@ -599,9 +580,9 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class) fis[1] &= ~(1 << 7); /* turn off Command FIS bit */ writel(1, port_mmio + PORT_CMD_ISSUE); - readl(port_mmio + PORT_CMD_ISSUE); /* flush */ - if (ahci_poll_register(port_mmio + PORT_CMD_ISSUE, 0x1, 0x0, 1, 500)) { + tmp = ata_wait_register(port_mmio + PORT_CMD_ISSUE, 0x1, 0x1, 1, 500); + if (tmp & 0x1) { rc = -EIO; reason = "1st FIS failed"; goto fail; -- cgit v1.2.3 From 7dd29dd629bd5a4e6d8a164a9886da01f291ecf2 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 11 Apr 2006 22:22:30 +0900 Subject: [PATCH] sata_sil24: use ata_wait_register() Replace hard-coded waiting loops in sata_sil24 to ata_wait_register(). Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/sata_sil24.c | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index d6cfd8eb29b..286c46e1f21 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -432,8 +432,7 @@ static int sil24_softreset(struct ata_port *ap, unsigned int *class) struct sil24_port_priv *pp = ap->private_data; struct sil24_prb *prb = &pp->cmd_block[0].ata.prb; dma_addr_t paddr = pp->cmd_block_dma; - unsigned long timeout = jiffies + ATA_TMOUT_BOOT; - u32 irq_enable, irq_stat; + u32 mask, irq_enable, irq_stat; const char *reason; DPRINTK("ENTER\n"); @@ -459,16 +458,12 @@ static int sil24_softreset(struct ata_port *ap, unsigned int *class) writel((u32)paddr, port + PORT_CMD_ACTIVATE); - do { - irq_stat = readl(port + PORT_IRQ_STAT); - writel(irq_stat, port + PORT_IRQ_STAT); /* clear irq */ + mask = (PORT_IRQ_COMPLETE | PORT_IRQ_ERROR) << PORT_IRQ_RAW_SHIFT; + irq_stat = ata_wait_register(port + PORT_IRQ_STAT, mask, 0x0, + 100, ATA_TMOUT_BOOT / HZ * 1000); - irq_stat >>= PORT_IRQ_RAW_SHIFT; - if (irq_stat & (PORT_IRQ_COMPLETE | PORT_IRQ_ERROR)) - break; - - msleep(100); - } while (time_before(jiffies, timeout)); + writel(irq_stat, port + PORT_IRQ_STAT); /* clear IRQs */ + irq_stat >>= PORT_IRQ_RAW_SHIFT; /* restore IRQs */ writel(irq_enable, port + PORT_IRQ_ENABLE_SET); @@ -937,14 +932,13 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) /* GPIO off */ writel(0, host_base + HOST_FLASH_CMD); - /* Mask interrupts during initialization */ + /* clear global reset & mask interrupts during initialization */ writel(0, host_base + HOST_CTRL); for (i = 0; i < probe_ent->n_ports; i++) { void __iomem *port = port_base + i * PORT_REGS_SIZE; unsigned long portu = (unsigned long)port; u32 tmp; - int cnt; probe_ent->port[i].cmd_addr = portu + PORT_PRB; probe_ent->port[i].scr_addr = portu + PORT_SCONTROL; @@ -958,13 +952,9 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) tmp = readl(port + PORT_CTRL_STAT); if (tmp & PORT_CS_PORT_RST) { writel(PORT_CS_PORT_RST, port + PORT_CTRL_CLR); - readl(port + PORT_CTRL_STAT); /* sync */ - for (cnt = 0; cnt < 10; cnt++) { - msleep(10); - tmp = readl(port + PORT_CTRL_STAT); - if (!(tmp & PORT_CS_PORT_RST)) - break; - } + tmp = ata_wait_register(port + PORT_CTRL_STAT, + PORT_CS_PORT_RST, + PORT_CS_PORT_RST, 10, 100); if (tmp & PORT_CS_PORT_RST) dev_printk(KERN_ERR, &pdev->dev, "failed to clear port RST\n"); -- cgit v1.2.3 From ec573755fcd7975aae6b0d536dbcd74a6eed029c Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 11 Apr 2006 22:26:29 +0900 Subject: [PATCH] libata: disable failed devices only once in ata_bus_probe() Devices which consumed all their changes used to be disabled every iteration. This causes unnecessary noise in the console output. Disable once and leave alone. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 0075fe7404d..9194e4a6a55 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1411,12 +1411,9 @@ static int ata_bus_probe(struct ata_port *ap) /* read IDENTIFY page and configure devices */ for (i = 0; i < ATA_MAX_DEVICES; i++) { dev = &ap->device[i]; - dev->class = classes[i]; - if (!tries[i]) { - ata_down_xfermask_limit(ap, dev, 1); - ata_dev_disable(ap, dev); - } + if (tries[i]) + dev->class = classes[i]; if (!ata_dev_enabled(dev)) continue; @@ -1477,6 +1474,11 @@ static int ata_bus_probe(struct ata_port *ap) tries[dev->devno] = 0; } + if (!tries[dev->devno]) { + ata_down_xfermask_limit(ap, dev, 1); + ata_dev_disable(ap, dev); + } + goto retry; } -- cgit v1.2.3 From 51713d359ae274fa4dd4b199ba3a6b0c21ef99e0 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 11 Apr 2006 22:26:29 +0900 Subject: [PATCH] libata: cosmetic update to ata_bus_probe() Move ata_set_mode() failure handling outside of ap->ops->set_mode if clause such that it can handle ap->ops->set_mode failures after it's updated. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 9194e4a6a55..588578dc6ca 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1441,12 +1441,12 @@ static int ata_bus_probe(struct ata_port *ap) break; } rc = 0; - } else { + } else rc = ata_set_mode(ap, &dev); - if (rc) { - down_xfermask = 1; - goto fail; - } + + if (rc) { + down_xfermask = 1; + goto fail; } for (i = 0; i < ATA_MAX_DEVICES; i++) -- cgit v1.2.3 From 499a86af41cf5a4bf811726841bbc49c0e96fd35 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 11 Apr 2006 22:32:18 +0900 Subject: [PATCH] libata: export ata_set_sata_spd() This will be used by LLDD hardreset implementation. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 3 ++- include/linux/libata.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 588578dc6ca..509178c3700 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1738,7 +1738,7 @@ int ata_set_sata_spd_needed(struct ata_port *ap) * 0 if spd doesn't need to be changed, 1 if spd has been * changed. -EOPNOTSUPP if SCR registers are inaccessible. */ -static int ata_set_sata_spd(struct ata_port *ap) +int ata_set_sata_spd(struct ata_port *ap) { u32 scontrol; @@ -5113,6 +5113,7 @@ EXPORT_SYMBOL_GPL(ata_bmdma_irq_clear); EXPORT_SYMBOL_GPL(ata_bmdma_status); EXPORT_SYMBOL_GPL(ata_bmdma_stop); EXPORT_SYMBOL_GPL(ata_port_probe); +EXPORT_SYMBOL_GPL(ata_set_sata_spd); EXPORT_SYMBOL_GPL(sata_phy_reset); EXPORT_SYMBOL_GPL(__sata_phy_reset); EXPORT_SYMBOL_GPL(ata_bus_reset); diff --git a/include/linux/libata.h b/include/linux/libata.h index dd5bcb5d29b..d35b1e3bb7e 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -504,6 +504,7 @@ extern void ata_port_probe(struct ata_port *); extern void __sata_phy_reset(struct ata_port *ap); extern void sata_phy_reset(struct ata_port *ap); extern void ata_bus_reset(struct ata_port *ap); +extern int ata_set_sata_spd(struct ata_port *ap); extern int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, ata_reset_fn_t softreset, ata_reset_fn_t hardreset, -- cgit v1.2.3 From 640088024dbf19553bb4b53d81e919cdf570f3b0 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 11 Apr 2006 22:32:18 +0900 Subject: [PATCH] sata_sil24: typo fix Type fix. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/sata_sil24.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 286c46e1f21..e9c5c2f6390 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -174,7 +174,7 @@ enum { PORT_CERR_CMD_PCIPERR = 27, /* ctrl[15:13] 110 - PCI parity err while fetching PRB */ PORT_CERR_XFR_UNDEF = 32, /* PSD ecode 00 - undefined */ PORT_CERR_XFR_TGTABRT = 33, /* PSD ecode 01 - target abort */ - PORT_CERR_XFR_MSGABRT = 34, /* PSD ecode 10 - master abort */ + PORT_CERR_XFR_MSTABRT = 34, /* PSD ecode 10 - master abort */ PORT_CERR_XFR_PCIPERR = 35, /* PSD ecode 11 - PCI prity err during transfer */ PORT_CERR_SENDSERVICE = 36, /* FIS received while sending service */ -- cgit v1.2.3 From 3b9f1d0fb3fd68419ee3fa3e0833c6a05462150d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 11 Apr 2006 22:32:18 +0900 Subject: [PATCH] sata_sil24: rename PORT_IRQ_SDB_FIS to PORT_IRQ_SDB_NOTIFY Rename PORT_IRQ_SDB_FIS to more proper PORT_IRQ_SDB_NOTIFY. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/sata_sil24.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index e9c5c2f6390..a5ea9f6df8e 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -143,7 +143,7 @@ enum { PORT_IRQ_PHYRDY_CHG = (1 << 4), /* PHY ready change */ PORT_IRQ_COMWAKE = (1 << 5), /* COMWAKE received */ PORT_IRQ_UNK_FIS = (1 << 6), /* Unknown FIS received */ - PORT_IRQ_SDB_FIS = (1 << 11), /* SDB FIS received */ + PORT_IRQ_SDB_NOTIFY = (1 << 11), /* SDB notify received */ /* bits[27:16] are unmasked (raw) */ PORT_IRQ_RAW_SHIFT = 16, @@ -974,8 +974,8 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) /* Configure interrupts */ writel(0xffff, port + PORT_IRQ_ENABLE_CLR); - writel(PORT_IRQ_COMPLETE | PORT_IRQ_ERROR | PORT_IRQ_SDB_FIS, - port + PORT_IRQ_ENABLE_SET); + writel(PORT_IRQ_COMPLETE | PORT_IRQ_ERROR | + PORT_IRQ_SDB_NOTIFY, port + PORT_IRQ_ENABLE_SET); /* Clear interrupts */ writel(0x0fff0fff, port + PORT_IRQ_STAT); -- cgit v1.2.3 From 7dafc3fd9a9e34e4a02ee6d141fd391ad5bdcd90 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 11 Apr 2006 22:32:18 +0900 Subject: [PATCH] sata_sil24: add more constants Add HOST_CTRL_* and more PORT_IRQ_* bits. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/sata_sil24.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index a5ea9f6df8e..1b648d67db1 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -86,6 +86,13 @@ enum { /* HOST_SLOT_STAT bits */ HOST_SSTAT_ATTN = (1 << 31), + /* HOST_CTRL bits */ + HOST_CTRL_M66EN = (1 << 16), /* M66EN PCI bus signal */ + HOST_CTRL_TRDY = (1 << 17), /* latched PCI TRDY */ + HOST_CTRL_STOP = (1 << 18), /* latched PCI STOP */ + HOST_CTRL_DEVSEL = (1 << 19), /* latched PCI DEVSEL */ + HOST_CTRL_REQ64 = (1 << 20), /* latched PCI REQ64 */ + /* * Port registers * (8192 bytes @ +0x0000, +0x2000, +0x4000 and +0x6000 @ BAR2) @@ -142,7 +149,11 @@ enum { PORT_IRQ_PWR_CHG = (1 << 3), /* power management change */ PORT_IRQ_PHYRDY_CHG = (1 << 4), /* PHY ready change */ PORT_IRQ_COMWAKE = (1 << 5), /* COMWAKE received */ - PORT_IRQ_UNK_FIS = (1 << 6), /* Unknown FIS received */ + PORT_IRQ_UNK_FIS = (1 << 6), /* unknown FIS received */ + PORT_IRQ_DEV_XCHG = (1 << 7), /* device exchanged */ + PORT_IRQ_8B10B = (1 << 8), /* 8b/10b decode error threshold */ + PORT_IRQ_CRC = (1 << 9), /* CRC error threshold */ + PORT_IRQ_HANDSHAKE = (1 << 10), /* handshake error threshold */ PORT_IRQ_SDB_NOTIFY = (1 << 11), /* SDB notify received */ /* bits[27:16] are unmasked (raw) */ -- cgit v1.2.3 From 9466d85bb2c80b1aa169dda638b535f2f19714e4 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 11 Apr 2006 22:32:18 +0900 Subject: [PATCH] sata_sil24: consolidate host flags into SIL24_COMMON_FLAGS All sil24 controllers share the same host flags except for NPORTS. Consolidate them into SIL24_COMMON_FLAGS. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/sata_sil24.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 1b648d67db1..50c2c6bcba6 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -218,6 +218,10 @@ enum { BID_SIL3132 = 1, BID_SIL3131 = 2, + /* host flags */ + SIL24_COMMON_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | + ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA, + IRQ_STAT_4PORTS = 0xf, }; @@ -344,9 +348,7 @@ static struct ata_port_info sil24_port_info[] = { /* sil_3124 */ { .sht = &sil24_sht, - .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | - SIL24_NPORTS2FLAG(4), + .host_flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(4), .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x3f, /* udma0-5 */ @@ -355,9 +357,7 @@ static struct ata_port_info sil24_port_info[] = { /* sil_3132 */ { .sht = &sil24_sht, - .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | - SIL24_NPORTS2FLAG(2), + .host_flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(2), .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x3f, /* udma0-5 */ @@ -366,9 +366,7 @@ static struct ata_port_info sil24_port_info[] = { /* sil_3131/sil_3531 */ { .sht = &sil24_sht, - .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | - SIL24_NPORTS2FLAG(1), + .host_flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(1), .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x3f, /* udma0-5 */ -- cgit v1.2.3 From 37024e8ee0d8dbcd0c2634192cb3836549db054e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 11 Apr 2006 22:32:19 +0900 Subject: [PATCH] sata_sil24: implement loss of completion interrupt on PCI-X errta fix SiI3124 might lose completion interrupt if completion interrupt occurs shortly after SLOT_STAT register is read for the previous completion interrupt if it is operating in PCI-X mode. This currently doesn't trigger as libata never queues more than one command, but it will with NCQ changes. This patch implements the workaround - turning on WoC and explicitly clearing interrupt. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/sata_sil24.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 50c2c6bcba6..c535607e995 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -221,6 +221,7 @@ enum { /* host flags */ SIL24_COMMON_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA, + SIL24_FLAG_PCIX_IRQ_WOC = (1 << 24), /* IRQ loss errata on PCI-X */ IRQ_STAT_4PORTS = 0xf, }; @@ -348,7 +349,8 @@ static struct ata_port_info sil24_port_info[] = { /* sil_3124 */ { .sht = &sil24_sht, - .host_flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(4), + .host_flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(4) | + SIL24_FLAG_PCIX_IRQ_WOC, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x3f, /* udma0-5 */ @@ -737,6 +739,10 @@ static inline void sil24_host_intr(struct ata_port *ap) slot_stat = readl(port + PORT_SLOT_STAT); if (!(slot_stat & HOST_SSTAT_ATTN)) { struct sil24_port_priv *pp = ap->private_data; + + if (ap->flags & SIL24_FLAG_PCIX_IRQ_WOC) + writel(PORT_IRQ_COMPLETE, port + PORT_IRQ_STAT); + /* * !HOST_SSAT_ATTN guarantees successful completion, * so reading back tf registers is unnecessary for @@ -868,6 +874,7 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) void __iomem *host_base = NULL; void __iomem *port_base = NULL; int i, rc; + u32 tmp; if (!printed_version++) dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); @@ -941,13 +948,23 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) /* GPIO off */ writel(0, host_base + HOST_FLASH_CMD); + /* Apply workaround for completion IRQ loss on PCI-X errata */ + if (probe_ent->host_flags & SIL24_FLAG_PCIX_IRQ_WOC) { + tmp = readl(host_base + HOST_CTRL); + if (tmp & (HOST_CTRL_TRDY | HOST_CTRL_STOP | HOST_CTRL_DEVSEL)) + dev_printk(KERN_INFO, &pdev->dev, + "Applying completion IRQ loss on PCI-X " + "errata fix\n"); + else + probe_ent->host_flags &= ~SIL24_FLAG_PCIX_IRQ_WOC; + } + /* clear global reset & mask interrupts during initialization */ writel(0, host_base + HOST_CTRL); for (i = 0; i < probe_ent->n_ports; i++) { void __iomem *port = port_base + i * PORT_REGS_SIZE; unsigned long portu = (unsigned long)port; - u32 tmp; probe_ent->port[i].cmd_addr = portu + PORT_PRB; probe_ent->port[i].scr_addr = portu + PORT_SCONTROL; @@ -969,6 +986,12 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) "failed to clear port RST\n"); } + /* Configure IRQ WoC */ + if (probe_ent->host_flags & SIL24_FLAG_PCIX_IRQ_WOC) + writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_STAT); + else + writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_CLR); + /* Zero error counters. */ writel(0x8000, port + PORT_DECODE_ERR_THRESH); writel(0x8000, port + PORT_CRC_ERR_THRESH); -- cgit v1.2.3 From b5bc421c96ca56a9abaad4619da01fe0071904a2 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 11 Apr 2006 22:32:19 +0900 Subject: [PATCH] sata_sil24: implement sil24_init_port() Implement sil24_init_port which performs port initialization via PORT_CS_INIT. To be used later by softreset and EH. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/sata_sil24.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index c535607e995..8199527966e 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -437,6 +437,22 @@ static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf) *tf = pp->tf; } +static int sil24_init_port(struct ata_port *ap) +{ + void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; + u32 tmp; + + writel(PORT_CS_INIT, port + PORT_CTRL_STAT); + ata_wait_register(port + PORT_CTRL_STAT, + PORT_CS_INIT, PORT_CS_INIT, 10, 100); + tmp = ata_wait_register(port + PORT_CTRL_STAT, + PORT_CS_RDY, 0, 10, 100); + + if ((tmp & (PORT_CS_INIT | PORT_CS_RDY)) != PORT_CS_RDY) + return -EIO; + return 0; +} + static int sil24_softreset(struct ata_port *ap, unsigned int *class) { void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; -- cgit v1.2.3 From 2555d6c268240fb3f5f335bd62d0518025343c0f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 11 Apr 2006 22:32:19 +0900 Subject: [PATCH] sata_sil24: put port into known state before softresetting Make sure the controller has no pending commands and ready for command before issuing SRST. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/sata_sil24.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 8199527966e..bfbd630a889 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -474,6 +474,12 @@ static int sil24_softreset(struct ata_port *ap, unsigned int *class) irq_enable = readl(port + PORT_IRQ_ENABLE_SET); writel(irq_enable, port + PORT_IRQ_ENABLE_CLR); + /* put the port into known state */ + if (sil24_init_port(ap)) { + reason ="port not ready"; + goto err; + } + /* * XXX: Not sure whether the following sleep is needed or not. * The original driver had it. So.... -- cgit v1.2.3 From 0eaa6058a6a664ce692e3dc38c6891a74ca47f59 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 11 Apr 2006 22:32:19 +0900 Subject: [PATCH] sata_sil24: kill 10ms sleep in softreset Nothing, not the datasheet nor the errats, says this delay is necessary and with the previous PORT_CS_INIT change, we know the controller is in good state. Kill 10ms sleep. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/sata_sil24.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index bfbd630a889..be4817e6502 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -480,12 +480,7 @@ static int sil24_softreset(struct ata_port *ap, unsigned int *class) goto err; } - /* - * XXX: Not sure whether the following sleep is needed or not. - * The original driver had it. So.... - */ - msleep(10); - + /* do SRST */ prb->ctrl = PRB_CTRL_SRST; prb->fis[1] = 0; /* no PM yet */ -- cgit v1.2.3 From ecc2e2b9c97719592b3078d5a5a8666551c91115 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 11 Apr 2006 22:32:19 +0900 Subject: [PATCH] sata_sil24: reimplement hardreset Reimplement hardreset according to the datasheet. The old hardreset didn't reset controller status and the controller might not be ready after reset. Also, as SStatus is a bit flakey after hardreset, sata_std_hardrset() didn't use to wait long enough before proceeding. Note that as we're not depending on SStatus, DET==1 condition cannot be used to wait for link, so use shorter timeout for no device case. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/sata_sil24.c | 43 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index be4817e6502..4180c81f639 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -521,10 +521,47 @@ static int sil24_softreset(struct ata_port *ap, unsigned int *class) static int sil24_hardreset(struct ata_port *ap, unsigned int *class) { - unsigned int dummy_class; + void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; + const char *reason; + int tout_msec; + u32 tmp; + + /* sil24 does the right thing(tm) without any protection */ + ata_set_sata_spd(ap); + + tout_msec = 100; + if (sata_dev_present(ap)) + tout_msec = 5000; + + writel(PORT_CS_DEV_RST, port + PORT_CTRL_STAT); + tmp = ata_wait_register(port + PORT_CTRL_STAT, + PORT_CS_DEV_RST, PORT_CS_DEV_RST, 10, tout_msec); + + /* SStatus oscillates between zero and valid status for short + * duration after DEV_RST, give it time to settle. + */ + msleep(100); + + if (tmp & PORT_CS_DEV_RST) { + if (!sata_dev_present(ap)) + return 0; + reason = "link not ready"; + goto err; + } + + if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) { + reason = "device not ready"; + goto err; + } - /* sil24 doesn't report device signature after hard reset */ - return sata_std_hardreset(ap, &dummy_class); + /* sil24 doesn't report device class code after hardreset, + * leave *class alone. + */ + return 0; + + err: + printk(KERN_ERR "ata%u: hardreset failed (%s)\n", ap->id, reason); + return -EIO; } static int sil24_probe_reset(struct ata_port *ap, unsigned int *classes) -- cgit v1.2.3 From a5b4c47a2731f1dd685f28b79464e4442f3682ec Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 11 Apr 2006 22:32:19 +0900 Subject: [PATCH] sata_sil24: don't do hardreset during driver initialization There's no need to perform hardreset during driver initialization. It's already done during host reset and even if the controller is in some wacky state, we now have proper hardreset to back us up. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/sata_sil24.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 4180c81f639..a8328a88e8c 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -1069,11 +1069,6 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) /* Clear port multiplier enable and resume bits */ writel(PORT_CS_PM_EN | PORT_CS_RESUME, port + PORT_CTRL_CLR); - - /* Reset itself */ - if (__sil24_reset_controller(port)) - dev_printk(KERN_ERR, &pdev->dev, - "failed to reset controller\n"); } /* Turn on interrupts */ -- cgit v1.2.3 From bad28a37f5e4ab1db5c5f01b77664597b02b257f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 11 Apr 2006 22:32:19 +0900 Subject: [PATCH] sata_sil24: fix on-memory structure byteorder Data structures residing on memory and fetched by the controller should have LE ordering. Fix it. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/sata_sil24.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index a8328a88e8c..8ef51d0dcda 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -481,7 +481,7 @@ static int sil24_softreset(struct ata_port *ap, unsigned int *class) } /* do SRST */ - prb->ctrl = PRB_CTRL_SRST; + prb->ctrl = cpu_to_le16(PRB_CTRL_SRST); prb->fis[1] = 0; /* no PM yet */ writel((u32)paddr, port + PORT_CMD_ACTIVATE); @@ -597,6 +597,7 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc) union sil24_cmd_block *cb = pp->cmd_block + qc->tag; struct sil24_prb *prb; struct sil24_sge *sge; + u16 ctrl = 0; switch (qc->tf.protocol) { case ATA_PROT_PIO: @@ -604,7 +605,6 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc) case ATA_PROT_NODATA: prb = &cb->ata.prb; sge = cb->ata.sge; - prb->ctrl = 0; break; case ATA_PROT_ATAPI: @@ -617,12 +617,10 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc) if (qc->tf.protocol != ATA_PROT_ATAPI_NODATA) { if (qc->tf.flags & ATA_TFLAG_WRITE) - prb->ctrl = PRB_CTRL_PACKET_WRITE; + ctrl = PRB_CTRL_PACKET_WRITE; else - prb->ctrl = PRB_CTRL_PACKET_READ; - } else - prb->ctrl = 0; - + ctrl = PRB_CTRL_PACKET_READ; + } break; default: @@ -631,6 +629,7 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc) BUG(); } + prb->ctrl = cpu_to_le16(ctrl); ata_tf_to_fis(&qc->tf, prb->fis, 0); if (qc->flags & ATA_QCFLAG_DMAMAP) -- cgit v1.2.3 From 26ec634c31a11a003040e10b4d650495158632fd Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 11 Apr 2006 22:32:19 +0900 Subject: [PATCH] sata_sil24: enable 64bit Enable 64bit. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/sata_sil24.c | 47 ++++++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 8ef51d0dcda..e9fd869140c 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -485,6 +485,7 @@ static int sil24_softreset(struct ata_port *ap, unsigned int *class) prb->fis[1] = 0; /* no PM yet */ writel((u32)paddr, port + PORT_CMD_ACTIVATE); + writel((u64)paddr >> 32, port + PORT_CMD_ACTIVATE + 4); mask = (PORT_IRQ_COMPLETE | PORT_IRQ_ERROR) << PORT_IRQ_RAW_SHIFT; irq_stat = ata_wait_register(port + PORT_IRQ_STAT, mask, 0x0, @@ -644,6 +645,8 @@ static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc) dma_addr_t paddr = pp->cmd_block_dma + qc->tag * sizeof(*pp->cmd_block); writel((u32)paddr, port + PORT_CMD_ACTIVATE); + writel((u64)paddr >> 32, port + PORT_CMD_ACTIVATE + 4); + return 0; } @@ -980,22 +983,29 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) /* * Configure the device */ - /* - * FIXME: This device is certainly 64-bit capable. We just - * don't know how to use it. After fixing 32bit activation in - * this function, enable 64bit masks here. - */ - rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); - if (rc) { - dev_printk(KERN_ERR, &pdev->dev, - "32-bit DMA enable failed\n"); - goto out_free; - } - rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); - if (rc) { - dev_printk(KERN_ERR, &pdev->dev, - "32-bit consistent DMA enable failed\n"); - goto out_free; + if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) { + rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); + if (rc) { + rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); + if (rc) { + dev_printk(KERN_ERR, &pdev->dev, + "64-bit DMA enable failed\n"); + goto out_free; + } + } + } else { + rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); + if (rc) { + dev_printk(KERN_ERR, &pdev->dev, + "32-bit DMA enable failed\n"); + goto out_free; + } + rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); + if (rc) { + dev_printk(KERN_ERR, &pdev->dev, + "32-bit consistent DMA enable failed\n"); + goto out_free; + } } /* GPIO off */ @@ -1053,9 +1063,8 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) writel(0x0000, port + PORT_CRC_ERR_CNT); writel(0x0000, port + PORT_HSHK_ERR_CNT); - /* FIXME: 32bit activation? */ - writel(0, port + PORT_ACTIVATE_UPPER_ADDR); - writel(PORT_CS_32BIT_ACTV, port + PORT_CTRL_STAT); + /* Always use 64bit activation */ + writel(PORT_CS_32BIT_ACTV, port + PORT_CTRL_CLR); /* Configure interrupts */ writel(0xffff, port + PORT_IRQ_ENABLE_CLR); -- cgit v1.2.3 From 4186ab1973758190916703eb8889ebe8002c5c8f Mon Sep 17 00:00:00 2001 From: Kurt Garloff Date: Mon, 3 Apr 2006 15:16:48 +0200 Subject: [SCSI] Try LUN 1 and use bflags Some devices report a peripheral qualifier of 3 for LUN 0; with the original code, we would still try a REPORT_LUNS scan (if SCSI level is >= 3 or if we have the BLIST_REPORTLUNS2 passed in), but NOT any sequential scan. Also, the device at LUN 0 (which is not connected according to the PQ) is not registered with the OS. Unfortunately, SANs exist that are SCSI-2 and do NOT support REPORT_LUNS, but report a unknown device with PQ 3 on LUN 0. We still need to scan them, and most probably we even need BLIST_SPARSELUN (and BLIST_LARGELUN). See the bug reference for an infamous example. This is patch 1/3: If we end up in sequential scan, at least try LUN 1 for devices that reported a PQ of 3 for LUN 0. Also return blacklist flags, even for PQ3 devices. Signed-off-by: Kurt Garloff Signed-off-by: James Bottomley --- drivers/scsi/scsi_scan.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index f14945996ed..820c4ad7b58 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -872,6 +872,8 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, if (scsi_probe_lun(sdev, result, result_len, &bflags)) goto out_free_result; + if (bflagsp) + *bflagsp = bflags; /* * result contains valid SCSI INQUIRY data. */ @@ -912,8 +914,6 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, sdev->lockable = 0; scsi_unlock_floptical(sdev, result); } - if (bflagsp) - *bflagsp = bflags; } out_free_result: @@ -938,7 +938,6 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, * scsi_sequential_lun_scan - sequentially scan a SCSI target * @starget: pointer to target structure to scan * @bflags: black/white list flag for LUN 0 - * @lun0_res: result of scanning LUN 0 * * Description: * Generally, scan from LUN 1 (LUN 0 is assumed to already have been @@ -948,8 +947,7 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, * Modifies sdevscan->lun. **/ static void scsi_sequential_lun_scan(struct scsi_target *starget, - int bflags, int lun0_res, int scsi_level, - int rescan) + int bflags, int scsi_level, int rescan) { unsigned int sparse_lun, lun, max_dev_lun; struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); @@ -969,13 +967,6 @@ static void scsi_sequential_lun_scan(struct scsi_target *starget, } else sparse_lun = 0; - /* - * If not sparse lun and no device attached at LUN 0 do not scan - * any further. - */ - if (!sparse_lun && (lun0_res != SCSI_SCAN_LUN_PRESENT)) - return; - /* * If less than SCSI_1_CSS, and no special lun scaning, stop * scanning; this matches 2.4 behaviour, but could just be a bug @@ -1384,7 +1375,7 @@ static void __scsi_scan_target(struct device *parent, unsigned int channel, * do a sequential scan. */ scsi_sequential_lun_scan(starget, bflags, - res, starget->scsi_level, rescan); + starget->scsi_level, rescan); } out_reap: -- cgit v1.2.3 From 6c7154c97e20c0ea28547240dc86731c0cee1b2f Mon Sep 17 00:00:00 2001 From: Kurt Garloff Date: Mon, 3 Apr 2006 15:18:35 +0200 Subject: [SCSI] Better log messages for PQ3 devs Some devices report a peripheral qualifier of 3 for LUN 0; with the original code, we would still try a REPORT_LUNS scan (if SCSI level is >= 3 or if we have the BLIST_REPORTLUNS2 passed in), but NOT any sequential scan. Also, the device at LUN 0 (which is not connected according to the PQ) is not registered with the OS. Unfortunately, SANs exist that are SCSI-2 and do NOT support REPORT_LUNS, but report a unknown device with PQ 3 on LUN 0. We still need to scan them, and most probably we even need BLIST_SPARSELUN (and BLIST_LARGELUN). See the bug reference for an infamous example. This patch 2/3: If a PQ3 device is found, log a message that describes the device (INQUIRY DATA and C:B:T:U tuple) and make a suggestion for blacklisting it. Signed-off-by: Kurt Garloff Signed-off-by: James Bottomley --- drivers/scsi/scsi_scan.c | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 820c4ad7b58..5603dc6eca4 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -808,6 +808,29 @@ static inline void scsi_destroy_sdev(struct scsi_device *sdev) put_device(&sdev->sdev_gendev); } +/** + * scsi_inq_str - print INQUIRY data from min to max index, + * strip trailing whitespace + * @buf: Output buffer with at least end-first+1 bytes of space + * @inq: Inquiry buffer (input) + * @first: Offset of string into inq + * @end: Index after last character in inq + */ +static unsigned char* scsi_inq_str(unsigned char* buf, unsigned char *inq, + unsigned first, unsigned end) +{ + unsigned term = 0, idx; + for (idx = 0; idx+first < end && idx+first < inq[4]+5; ++idx) { + if (inq[idx+first] > 0x20) { + buf[idx] = inq[idx+first]; + term = idx+1; + } else { + buf[idx] = ' '; + } + } + buf[term] = 0; + return buf; +} /** * scsi_probe_and_add_lun - probe a LUN, if a LUN is found add it @@ -888,9 +911,18 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, * logical disk configured at sdev->lun, but there * is a target id responding. */ - SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO - "scsi scan: peripheral qualifier of 3," - " no device added\n")); + SCSI_LOG_SCAN_BUS(2, sdev_printk(KERN_INFO, sdev, "scsi scan:" + " peripheral qualifier of 3, device not" + " added\n")) + if (lun == 0) { + unsigned char vend[9], mod[17]; + SCSI_LOG_SCAN_BUS(1, sdev_printk(KERN_INFO, sdev, + "scsi scan: consider passing scsi_mod." + "dev_flags=%s:%s:0x240 or 0x800240\n", + scsi_inq_str(vend, result, 8, 16), + scsi_inq_str(mod, result, 16, 32))); + } + res = SCSI_SCAN_TARGET_PRESENT; goto out_free_result; } -- cgit v1.2.3 From 13f7e5acc8b329080672c13f05f252ace5b79825 Mon Sep 17 00:00:00 2001 From: Kurt Garloff Date: Mon, 3 Apr 2006 15:20:08 +0200 Subject: [SCSI] BLIST_ATTACH_PQ3 flags Some devices report a peripheral qualifier of 3 for LUN 0; with the original code, we would still try a REPORT_LUNS scan (if SCSI level is >= 3 or if we have the BLIST_REPORTLUNS2 passed in), but NOT any sequential scan. Also, the device at LUN 0 (which is not connected according to the PQ) is not registered with the OS. Unfortunately, SANs exist that are SCSI-2 and do NOT support REPORT_LUNS, but report a unknown device with PQ 3 on LUN 0. We still need to scan them, and most probably we even need BLIST_SPARSELUN (and BLIST_LARGELUN). See the bug reference for an infamous example. This is patch 3/3: 3. Implement the blacklist flag BLIST_ATTACH_PQ3 that makes the scsi scanning code register PQ3 devices and continues scanning; only sg will attach thanks to scsi_bus_match(). Signed-off-by: Kurt Garloff Signed-off-by: James Bottomley --- drivers/scsi/scsi_devinfo.c | 2 ++ drivers/scsi/scsi_scan.c | 2 +- include/scsi/scsi_devinfo.h | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c index 84c3937ae8f..6f46b338c99 100644 --- a/drivers/scsi/scsi_devinfo.c +++ b/drivers/scsi/scsi_devinfo.c @@ -155,6 +155,8 @@ static struct { {"HITACHI", "DF400", "*", BLIST_SPARSELUN}, {"HITACHI", "DF500", "*", BLIST_SPARSELUN}, {"HITACHI", "DF600", "*", BLIST_SPARSELUN}, + {"HITACHI", "DISK-SUBSYSTEM", "*", BLIST_ATTACH_PQ3 | BLIST_SPARSELUN | BLIST_LARGELUN}, + {"HITACHI", "OPEN-E", "*", BLIST_ATTACH_PQ3 | BLIST_SPARSELUN | BLIST_LARGELUN}, {"HP", "A6189A", NULL, BLIST_SPARSELUN | BLIST_LARGELUN}, /* HP VA7400 */ {"HP", "OPEN-", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, /* HP XP Arrays */ {"HP", "NetRAID-4M", NULL, BLIST_FORCELUN}, diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 5603dc6eca4..7d31a4b0f80 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -900,7 +900,7 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, /* * result contains valid SCSI INQUIRY data. */ - if ((result[0] >> 5) == 3) { + if (((result[0] >> 5) == 3) && !(bflags & BLIST_ATTACH_PQ3)) { /* * For a Peripheral qualifier 3 (011b), the SCSI * spec says: The device server is not capable of diff --git a/include/scsi/scsi_devinfo.h b/include/scsi/scsi_devinfo.h index 174101b2069..59996689820 100644 --- a/include/scsi/scsi_devinfo.h +++ b/include/scsi/scsi_devinfo.h @@ -28,4 +28,5 @@ #define BLIST_NO_ULD_ATTACH 0x100000 /* device is actually for RAID config */ #define BLIST_SELECT_NO_ATN 0x200000 /* select without ATN */ #define BLIST_RETRY_HWERROR 0x400000 /* retry HARDWARE_ERROR */ +#define BLIST_ATTACH_PQ3 0x800000 /* Scan: Attach to PQ3 devices */ #endif -- cgit v1.2.3 From b5c7a12dc29ae0990d9e867749bdd717a3160325 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Thu, 6 Apr 2006 21:13:33 -0500 Subject: [SCSI] iscsi: rm kernel iscsi handles usage for session and connection from hare@suse.de and michaelc@cs.wisc.edu hw iscsi like qla4xxx does not allocate a host per session and for userspace it is difficult to restart iscsid using the "iscsi handles" for the session and connection, so this patch just has the class or userspace allocate the id for the session and connection. Note: this breaks userspace and requires users to upgrade to the newest open-iscsi tools. Sorry about his but open-iscsi is still too new to say we have a stable user-kernel api and we were not good nough designers to know that other hw iscsi drivers and iscsid itself would need such changes. Actually we sorta did but at the time we did not have the HW available to us so we could only guess. Luckily, the only tools hooking into the class are the open-iscsi ones or other tools like iscsitart hook into the open-iscsi engine from userspace or prgroams like anaconda call our tools so they are not affected. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/iscsi_tcp.c | 5 +- drivers/scsi/scsi_transport_iscsi.c | 106 +++++++++++++++++++++++++----------- include/scsi/iscsi_if.h | 37 ++++++++----- include/scsi/scsi_transport_iscsi.h | 7 ++- 4 files changed, 105 insertions(+), 50 deletions(-) diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 2068b66822b..6ecb4baa37e 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -3254,7 +3254,7 @@ static struct iscsi_transport iscsi_tcp_transport; static struct iscsi_cls_session * iscsi_session_create(struct scsi_transport_template *scsit, - uint32_t initial_cmdsn, uint32_t *sid) + uint32_t initial_cmdsn, uint32_t *hostno) { struct Scsi_Host *shost; struct iscsi_session *session; @@ -3274,7 +3274,8 @@ iscsi_session_create(struct scsi_transport_template *scsit, session->exp_cmdsn = initial_cmdsn + 1; session->max_cmdsn = initial_cmdsn + 1; session->max_r2t = 1; - *sid = shost->host_no; + + *hostno = shost->host_no; /* initialize SCSI PDU commands pool */ if (iscsi_pool_init(&session->cmdpool, session->cmds_max, diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 2730d507e58..10ff0f0210b 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -56,6 +56,8 @@ struct iscsi_internal { struct class_device_attribute *session_attrs[ISCSI_SESSION_ATTRS + 1]; }; +static int iscsi_session_nr; /* sysfs session id for next new session */ + /* * list of registered transports and lock that must * be held while accessing list. The iscsi_transport_lock must @@ -165,14 +167,23 @@ static DEFINE_SPINLOCK(sesslock); static LIST_HEAD(connlist); static DEFINE_SPINLOCK(connlock); -static struct iscsi_cls_session *iscsi_session_lookup(uint64_t handle) +static uint32_t iscsi_conn_get_sid(struct iscsi_cls_conn *conn) +{ + struct iscsi_cls_session *sess = iscsi_dev_to_session(conn->dev.parent); + return sess->sid; +} + +/* + * Returns the matching session to a given sid + */ +static struct iscsi_cls_session *iscsi_session_lookup(uint32_t sid) { unsigned long flags; struct iscsi_cls_session *sess; spin_lock_irqsave(&sesslock, flags); list_for_each_entry(sess, &sesslist, sess_list) { - if (sess == iscsi_ptr(handle)) { + if (sess->sid == sid) { spin_unlock_irqrestore(&sesslock, flags); return sess; } @@ -181,14 +192,17 @@ static struct iscsi_cls_session *iscsi_session_lookup(uint64_t handle) return NULL; } -static struct iscsi_cls_conn *iscsi_conn_lookup(uint64_t handle) +/* + * Returns the matching connection to a given sid / cid tuple + */ +static struct iscsi_cls_conn *iscsi_conn_lookup(uint32_t sid, uint32_t cid) { unsigned long flags; struct iscsi_cls_conn *conn; spin_lock_irqsave(&connlock, flags); list_for_each_entry(conn, &connlist, conn_list) { - if (conn == iscsi_ptr(handle)) { + if ((conn->cid == cid) && (iscsi_conn_get_sid(conn) == sid)) { spin_unlock_irqrestore(&connlock, flags); return conn; } @@ -223,7 +237,7 @@ static int iscsi_is_session_dev(const struct device *dev) * @shost: scsi host * @transport: iscsi transport * - * This can be called from a LLD or iscsi_transport + * This can be called from a LLD or iscsi_transport. **/ struct iscsi_cls_session * iscsi_create_session(struct Scsi_Host *shost, struct iscsi_transport *transport) @@ -234,14 +248,20 @@ iscsi_create_session(struct Scsi_Host *shost, struct iscsi_transport *transport) if (!try_module_get(transport->owner)) return NULL; - session = kzalloc(sizeof(*session), GFP_KERNEL); + session = kzalloc(sizeof(*session) + transport->sessiondata_size, + GFP_KERNEL); if (!session) goto module_put; session->transport = transport; + if (transport->sessiondata_size) + session->dd_data = &session[1]; + /* this is released in the dev's release function */ scsi_host_get(shost); - snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u", shost->host_no); + session->sid = iscsi_session_nr++; + snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u", + session->sid); session->dev.parent = &shost->shost_gendev; session->dev.release = iscsi_session_release; err = device_register(&session->dev); @@ -301,12 +321,16 @@ static int iscsi_is_conn_dev(const struct device *dev) * This can be called from a LLD or iscsi_transport. The connection * is child of the session so cid must be unique for all connections * on the session. + * + * Since we do not support MCS, cid will normally be zero. In some cases + * for software iscsi we could be trying to preallocate a connection struct + * in which case there could be two connection structs and cid would be + * non-zero. **/ struct iscsi_cls_conn * iscsi_create_conn(struct iscsi_cls_session *session, uint32_t cid) { struct iscsi_transport *transport = session->transport; - struct Scsi_Host *shost = iscsi_session_to_shost(session); struct iscsi_cls_conn *conn; int err; @@ -319,12 +343,14 @@ iscsi_create_conn(struct iscsi_cls_session *session, uint32_t cid) INIT_LIST_HEAD(&conn->conn_list); conn->transport = transport; + conn->cid = cid; /* this is released in the dev's release function */ if (!get_device(&session->dev)) goto free_conn; + snprintf(conn->dev.bus_id, BUS_ID_SIZE, "connection%d:%u", - shost->host_no, cid); + session->sid, cid); conn->dev.parent = &session->dev; conn->dev.release = iscsi_conn_release; err = device_register(&conn->dev); @@ -607,7 +633,8 @@ int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr, ev->type = ISCSI_KEVENT_RECV_PDU; if (atomic_read(&conn->z_pdu->allocated) >= conn->z_pdu->hiwat) ev->iferror = -ENOMEM; - ev->r.recv_req.conn_handle = iscsi_handle(conn); + ev->r.recv_req.cid = conn->cid; + ev->r.recv_req.sid = iscsi_conn_get_sid(conn); pdu = (char*)ev + sizeof(*ev); memcpy(pdu, hdr, sizeof(struct iscsi_hdr)); memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size); @@ -639,7 +666,8 @@ void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error) if (atomic_read(&conn->z_error->allocated) >= conn->z_error->hiwat) ev->iferror = -ENOMEM; ev->r.connerror.error = error; - ev->r.connerror.conn_handle = iscsi_handle(conn); + ev->r.connerror.cid = conn->cid; + ev->r.connerror.sid = iscsi_conn_get_sid(conn); iscsi_unicast_skb(conn->z_error, skb); @@ -689,7 +717,7 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh) ISCSI_STATS_CUSTOM_MAX); int err = 0; - conn = iscsi_conn_lookup(ev->u.get_stats.conn_handle); + conn = iscsi_conn_lookup(ev->u.get_stats.sid, ev->u.get_stats.cid); if (!conn) return -EEXIST; @@ -713,8 +741,10 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh) evstat->type = nlh->nlmsg_type; if (atomic_read(&conn->z_pdu->allocated) >= conn->z_pdu->hiwat) evstat->iferror = -ENOMEM; - evstat->u.get_stats.conn_handle = - ev->u.get_stats.conn_handle; + evstat->u.get_stats.cid = + ev->u.get_stats.cid; + evstat->u.get_stats.sid = + ev->u.get_stats.sid; stats = (struct iscsi_stats *) ((char*)evstat + sizeof(*evstat)); memset(stats, 0, sizeof(*stats)); @@ -740,16 +770,16 @@ iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev) { struct iscsi_transport *transport = priv->iscsi_transport; struct iscsi_cls_session *session; - uint32_t sid; + uint32_t hostno; session = transport->create_session(&priv->t, ev->u.c_session.initial_cmdsn, - &sid); + &hostno); if (!session) return -ENOMEM; - ev->r.c_session_ret.session_handle = iscsi_handle(session); - ev->r.c_session_ret.sid = sid; + ev->r.c_session_ret.host_no = hostno; + ev->r.c_session_ret.sid = session->sid; return 0; } @@ -760,13 +790,20 @@ iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev) struct iscsi_cls_session *session; unsigned long flags; - session = iscsi_session_lookup(ev->u.c_conn.session_handle); - if (!session) + session = iscsi_session_lookup(ev->u.c_conn.sid); + if (!session) { + printk(KERN_ERR "iscsi: invalid session %d\n", + ev->u.c_conn.sid); return -EINVAL; + } conn = transport->create_conn(session, ev->u.c_conn.cid); - if (!conn) + if (!conn) { + printk(KERN_ERR "iscsi: couldn't create a new " + "connection for session %d\n", + session->sid); return -ENOMEM; + } conn->z_pdu = mempool_zone_init(Z_MAX_PDU, NLMSG_SPACE(sizeof(struct iscsi_uevent) + @@ -788,7 +825,8 @@ iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev) goto free_pdu_pool; } - ev->r.handle = iscsi_handle(conn); + ev->r.c_conn_ret.sid = session->sid; + ev->r.c_conn_ret.cid = conn->cid; spin_lock_irqsave(&connlock, flags); list_add(&conn->conn_list, &connlist); @@ -812,7 +850,7 @@ iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev struct iscsi_cls_conn *conn; struct mempool_zone *z_error, *z_pdu; - conn = iscsi_conn_lookup(ev->u.d_conn.conn_handle); + conn = iscsi_conn_lookup(ev->u.d_conn.sid, ev->u.d_conn.cid); if (!conn) return -EINVAL; spin_lock_irqsave(&connlock, flags); @@ -855,7 +893,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) err = iscsi_if_create_session(priv, ev); break; case ISCSI_UEVENT_DESTROY_SESSION: - session = iscsi_session_lookup(ev->u.d_session.session_handle); + session = iscsi_session_lookup(ev->u.d_session.sid); if (session) transport->destroy_session(session); else @@ -868,8 +906,8 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) err = iscsi_if_destroy_conn(transport, ev); break; case ISCSI_UEVENT_BIND_CONN: - session = iscsi_session_lookup(ev->u.b_conn.session_handle); - conn = iscsi_conn_lookup(ev->u.b_conn.conn_handle); + session = iscsi_session_lookup(ev->u.b_conn.sid); + conn = iscsi_conn_lookup(ev->u.b_conn.sid, ev->u.b_conn.cid); if (session && conn) ev->r.retcode = transport->bind_conn(session, conn, @@ -879,7 +917,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) err = -EINVAL; break; case ISCSI_UEVENT_SET_PARAM: - conn = iscsi_conn_lookup(ev->u.set_param.conn_handle); + conn = iscsi_conn_lookup(ev->u.set_param.sid, ev->u.set_param.cid); if (conn) ev->r.retcode = transport->set_param(conn, ev->u.set_param.param, ev->u.set_param.value); @@ -887,7 +925,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) err = -EINVAL; break; case ISCSI_UEVENT_START_CONN: - conn = iscsi_conn_lookup(ev->u.start_conn.conn_handle); + conn = iscsi_conn_lookup(ev->u.start_conn.sid, ev->u.start_conn.cid); if (conn) ev->r.retcode = transport->start_conn(conn); else @@ -895,14 +933,14 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) break; case ISCSI_UEVENT_STOP_CONN: - conn = iscsi_conn_lookup(ev->u.stop_conn.conn_handle); + conn = iscsi_conn_lookup(ev->u.stop_conn.sid, ev->u.stop_conn.cid); if (conn) transport->stop_conn(conn, ev->u.stop_conn.flag); else err = -EINVAL; break; case ISCSI_UEVENT_SEND_PDU: - conn = iscsi_conn_lookup(ev->u.send_pdu.conn_handle); + conn = iscsi_conn_lookup(ev->u.send_pdu.sid, ev->u.send_pdu.cid); if (conn) ev->r.retcode = transport->send_pdu(conn, (struct iscsi_hdr*)((char*)ev + sizeof(*ev)), @@ -923,9 +961,11 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) return err; } -/* Get message from skb (based on rtnetlink_rcv_skb). Each message is - * processed by iscsi_if_recv_msg. Malformed skbs with wrong length are - * or invalid creds discarded silently. */ +/* + * Get message from skb (based on rtnetlink_rcv_skb). Each message is + * processed by iscsi_if_recv_msg. Malformed skbs with wrong lengths or + * invalid creds are discarded silently. + */ static void iscsi_if_rx(struct sock *sk, int len) { diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h index e5618b90996..933a91b1474 100644 --- a/include/scsi/iscsi_if.h +++ b/include/scsi/iscsi_if.h @@ -60,59 +60,68 @@ struct iscsi_uevent { uint32_t initial_cmdsn; } c_session; struct msg_destroy_session { - uint64_t session_handle; uint32_t sid; } d_session; struct msg_create_conn { - uint64_t session_handle; - uint32_t cid; uint32_t sid; + uint32_t cid; } c_conn; struct msg_bind_conn { - uint64_t session_handle; - uint64_t conn_handle; + uint32_t sid; + uint32_t cid; uint32_t transport_fd; uint32_t is_leading; } b_conn; struct msg_destroy_conn { - uint64_t conn_handle; + uint32_t sid; uint32_t cid; } d_conn; struct msg_send_pdu { + uint32_t sid; + uint32_t cid; uint32_t hdr_size; uint32_t data_size; - uint64_t conn_handle; } send_pdu; struct msg_set_param { - uint64_t conn_handle; + uint32_t sid; + uint32_t cid; uint32_t param; /* enum iscsi_param */ uint32_t value; } set_param; struct msg_start_conn { - uint64_t conn_handle; + uint32_t sid; + uint32_t cid; } start_conn; struct msg_stop_conn { + uint32_t sid; + uint32_t cid; uint64_t conn_handle; uint32_t flag; } stop_conn; struct msg_get_stats { - uint64_t conn_handle; + uint32_t sid; + uint32_t cid; } get_stats; } u; union { /* messages k -> u */ - uint64_t handle; int retcode; struct msg_create_session_ret { - uint64_t session_handle; uint32_t sid; + uint32_t host_no; } c_session_ret; + struct msg_create_conn_ret { + uint32_t sid; + uint32_t cid; + } c_conn_ret; struct msg_recv_req { + uint32_t sid; + uint32_t cid; uint64_t recv_handle; - uint64_t conn_handle; } recv_req; struct msg_conn_error { - uint64_t conn_handle; + uint32_t sid; + uint32_t cid; uint32_t error; /* enum iscsi_err */ } connerror; } r; diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index b41cf077e54..631463cd489 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -60,11 +60,13 @@ struct iscsi_transport { int ihostdata_size; /* LLD connection data size */ int conndata_size; + /* LLD session data size */ + int sessiondata_size; int max_lun; unsigned int max_conn; unsigned int max_cmd_len; struct iscsi_cls_session *(*create_session) - (struct scsi_transport_template *t, uint32_t sn, uint32_t *sid); + (struct scsi_transport_template *t, uint32_t sn, uint32_t *hn); void (*destroy_session) (struct iscsi_cls_session *session); struct iscsi_cls_conn *(*create_conn) (struct iscsi_cls_session *sess, uint32_t cid); @@ -104,6 +106,7 @@ struct iscsi_cls_conn { struct list_head conn_list; /* item in connlist */ void *dd_data; /* LLD private data */ struct iscsi_transport *transport; + uint32_t cid; /* connection id */ int active; /* must be accessed with the connlock */ struct device dev; /* sysfs transport/container device */ struct mempool_zone *z_error; @@ -117,6 +120,8 @@ struct iscsi_cls_conn { struct iscsi_cls_session { struct list_head sess_list; /* item in session_list */ struct iscsi_transport *transport; + int sid; /* session id */ + void *dd_data; /* LLD private data */ struct device dev; /* sysfs transport/container device */ }; -- cgit v1.2.3 From fd7255f51a13ea915099c7e488001dfbbeb05104 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Thu, 6 Apr 2006 21:13:36 -0500 Subject: [SCSI] iscsi: add sysfs attrs for uspace sync up For iscsi boot when going from initramfs to the real root we need to stop the userpsace iscsi daemon. To later restart it iscsid needs to be able to rebuild itself and part of that process is matching a session running the kernel with the iscsid representation. To do this the attached patch adds several required iscsi values. If the LLD does not provide them becuase, login is done in userspace, then the transport class and userspace set ths up for the LLD. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/iscsi_tcp.c | 68 +++++++++- drivers/scsi/scsi_transport_iscsi.c | 262 ++++++++++++++++++++++++++++-------- include/scsi/iscsi_if.h | 64 ++++++--- include/scsi/scsi_transport_iscsi.h | 24 +++- 4 files changed, 342 insertions(+), 76 deletions(-) diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 6ecb4baa37e..6e510f3cfbf 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -3536,7 +3536,7 @@ iscsi_session_get_param(struct iscsi_cls_session *cls_session, *value = session->ofmarker_en; break; default: - return ISCSI_ERR_PARAM_NOT_FOUND; + return -EINVAL; } return 0; @@ -3547,6 +3547,7 @@ iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param, uint32_t *value) { struct iscsi_conn *conn = cls_conn->dd_data; + struct inet_sock *inet; switch(param) { case ISCSI_PARAM_MAX_RECV_DLENGTH: @@ -3561,13 +3562,61 @@ iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn, case ISCSI_PARAM_DATADGST_EN: *value = conn->datadgst_en; break; + case ISCSI_PARAM_CONN_PORT: + mutex_lock(&conn->xmitmutex); + if (!conn->sock) { + mutex_unlock(&conn->xmitmutex); + return -EINVAL; + } + + inet = inet_sk(conn->sock->sk); + *value = be16_to_cpu(inet->dport); + mutex_unlock(&conn->xmitmutex); default: - return ISCSI_ERR_PARAM_NOT_FOUND; + return -EINVAL; } return 0; } +static int +iscsi_conn_get_str_param(struct iscsi_cls_conn *cls_conn, + enum iscsi_param param, char *buf) +{ + struct iscsi_conn *conn = cls_conn->dd_data; + struct sock *sk; + struct inet_sock *inet; + struct ipv6_pinfo *np; + int len = 0; + + switch (param) { + case ISCSI_PARAM_CONN_ADDRESS: + mutex_lock(&conn->xmitmutex); + if (!conn->sock) { + mutex_unlock(&conn->xmitmutex); + return -EINVAL; + } + + sk = conn->sock->sk; + if (sk->sk_family == PF_INET) { + inet = inet_sk(sk); + len = sprintf(buf, "%u.%u.%u.%u\n", + NIPQUAD(inet->daddr)); + } else { + np = inet6_sk(sk); + len = sprintf(buf, + "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", + NIP6(np->daddr)); + } + mutex_unlock(&conn->xmitmutex); + break; + default: + return -EINVAL; + } + + return len; +} + static void iscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats) { @@ -3610,6 +3659,20 @@ static struct iscsi_transport iscsi_tcp_transport = { .name = "tcp", .caps = CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST | CAP_DATADGST, + .param_mask = ISCSI_MAX_RECV_DLENGTH | + ISCSI_MAX_XMIT_DLENGTH | + ISCSI_HDRDGST_EN | + ISCSI_DATADGST_EN | + ISCSI_INITIAL_R2T_EN | + ISCSI_MAX_R2T | + ISCSI_IMM_DATA_EN | + ISCSI_FIRST_BURST | + ISCSI_MAX_BURST | + ISCSI_PDU_INORDER_EN | + ISCSI_DATASEQ_INORDER_EN | + ISCSI_ERL | + ISCSI_CONN_PORT | + ISCSI_CONN_ADDRESS, .host_template = &iscsi_sht, .hostdata_size = sizeof(struct iscsi_session), .conndata_size = sizeof(struct iscsi_conn), @@ -3622,6 +3685,7 @@ static struct iscsi_transport iscsi_tcp_transport = { .destroy_conn = iscsi_conn_destroy, .set_param = iscsi_conn_set_param, .get_conn_param = iscsi_conn_get_param, + .get_conn_str_param = iscsi_conn_get_str_param, .get_session_param = iscsi_session_get_param, .start_conn = iscsi_conn_start, .stop_conn = iscsi_conn_stop, diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 10ff0f0210b..72a71ebc9d0 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -31,21 +31,13 @@ #include #include -#define ISCSI_SESSION_ATTRS 8 -#define ISCSI_CONN_ATTRS 6 +#define ISCSI_SESSION_ATTRS 10 +#define ISCSI_CONN_ATTRS 10 struct iscsi_internal { struct scsi_transport_template t; struct iscsi_transport *iscsi_transport; struct list_head list; - /* - * based on transport capabilities, at register time we set these - * bits to tell the transport class it wants attributes displayed - * in sysfs or that it can support different iSCSI Data-Path - * capabilities - */ - uint32_t param_mask; - struct class_device cdev; /* * We do not have any private or other attrs. @@ -223,6 +215,7 @@ static void iscsi_session_release(struct device *dev) shost = iscsi_session_to_shost(session); scsi_host_put(shost); + kfree(session->targetname); kfree(session); module_put(transport->owner); } @@ -304,6 +297,7 @@ static void iscsi_conn_release(struct device *dev) struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev); struct device *parent = conn->dev.parent; + kfree(conn->persistent_address); kfree(conn); put_device(parent); } @@ -870,6 +864,67 @@ iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev return 0; } +static void +iscsi_copy_param(struct iscsi_uevent *ev, uint32_t *value, char *data) +{ + if (ev->u.set_param.len != sizeof(uint32_t)) + BUG(); + memcpy(value, data, min_t(uint32_t, sizeof(uint32_t), + ev->u.set_param.len)); +} + +static int +iscsi_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev) +{ + char *data = (char*)ev + sizeof(*ev); + struct iscsi_cls_conn *conn; + struct iscsi_cls_session *session; + int err = 0; + uint32_t value = 0; + + session = iscsi_session_lookup(ev->u.set_param.sid); + conn = iscsi_conn_lookup(ev->u.set_param.sid, ev->u.set_param.cid); + if (!conn || !session) + return -EINVAL; + + switch (ev->u.set_param.param) { + case ISCSI_PARAM_TARGET_NAME: + /* this should not change between logins */ + if (session->targetname) + return 0; + + session->targetname = kstrdup(data, GFP_KERNEL); + if (!session->targetname) + return -ENOMEM; + break; + case ISCSI_PARAM_TPGT: + iscsi_copy_param(ev, &value, data); + session->tpgt = value; + break; + case ISCSI_PARAM_PERSISTENT_PORT: + iscsi_copy_param(ev, &value, data); + conn->persistent_port = value; + break; + case ISCSI_PARAM_PERSISTENT_ADDRESS: + /* + * this is the address returned in discovery so it should + * not change between logins. + */ + if (conn->persistent_address) + return 0; + + conn->persistent_address = kstrdup(data, GFP_KERNEL); + if (!conn->persistent_address) + return -ENOMEM; + break; + default: + iscsi_copy_param(ev, &value, data); + err = transport->set_param(conn, ev->u.set_param.param, value); + } + + return err; +} + static int iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) { @@ -917,12 +972,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) err = -EINVAL; break; case ISCSI_UEVENT_SET_PARAM: - conn = iscsi_conn_lookup(ev->u.set_param.sid, ev->u.set_param.cid); - if (conn) - ev->r.retcode = transport->set_param(conn, - ev->u.set_param.param, ev->u.set_param.value); - else - err = -EINVAL; + err = iscsi_set_param(transport, ev); break; case ISCSI_UEVENT_START_CONN: conn = iscsi_conn_lookup(ev->u.start_conn.sid, ev->u.start_conn.cid); @@ -1028,6 +1078,10 @@ free_skb: #define iscsi_cdev_to_conn(_cdev) \ iscsi_dev_to_conn(_cdev->dev) +#define ISCSI_CLASS_ATTR(_prefix,_name,_mode,_show,_store) \ +struct class_device_attribute class_device_attr_##_prefix##_##_name = \ + __ATTR(_name,_mode,_show,_store) + /* * iSCSI connection attrs */ @@ -1045,7 +1099,8 @@ show_conn_int_param_##param(struct class_device *cdev, char *buf) \ #define iscsi_conn_int_attr(field, param, format) \ iscsi_conn_int_attr_show(param, format) \ -static CLASS_DEVICE_ATTR(field, S_IRUGO, show_conn_int_param_##param, NULL); +static ISCSI_CLASS_ATTR(conn, field, S_IRUGO, show_conn_int_param_##param, \ + NULL); iscsi_conn_int_attr(max_recv_dlength, ISCSI_PARAM_MAX_RECV_DLENGTH, "%u"); iscsi_conn_int_attr(max_xmit_dlength, ISCSI_PARAM_MAX_XMIT_DLENGTH, "%u"); @@ -1053,6 +1108,25 @@ iscsi_conn_int_attr(header_digest, ISCSI_PARAM_HDRDGST_EN, "%d"); iscsi_conn_int_attr(data_digest, ISCSI_PARAM_DATADGST_EN, "%d"); iscsi_conn_int_attr(ifmarker, ISCSI_PARAM_IFMARKER_EN, "%d"); iscsi_conn_int_attr(ofmarker, ISCSI_PARAM_OFMARKER_EN, "%d"); +iscsi_conn_int_attr(persistent_port, ISCSI_PARAM_PERSISTENT_PORT, "%d"); +iscsi_conn_int_attr(port, ISCSI_PARAM_CONN_PORT, "%d"); + +#define iscsi_conn_str_attr_show(param) \ +static ssize_t \ +show_conn_str_param_##param(struct class_device *cdev, char *buf) \ +{ \ + struct iscsi_cls_conn *conn = iscsi_cdev_to_conn(cdev); \ + struct iscsi_transport *t = conn->transport; \ + return t->get_conn_str_param(conn, param, buf); \ +} + +#define iscsi_conn_str_attr(field, param) \ + iscsi_conn_str_attr_show(param) \ +static ISCSI_CLASS_ATTR(conn, field, S_IRUGO, show_conn_str_param_##param, \ + NULL); + +iscsi_conn_str_attr(persistent_address, ISCSI_PARAM_PERSISTENT_ADDRESS); +iscsi_conn_str_attr(address, ISCSI_PARAM_CONN_ADDRESS); #define iscsi_cdev_to_session(_cdev) \ iscsi_dev_to_session(_cdev->dev) @@ -1074,7 +1148,8 @@ show_session_int_param_##param(struct class_device *cdev, char *buf) \ #define iscsi_session_int_attr(field, param, format) \ iscsi_session_int_attr_show(param, format) \ -static CLASS_DEVICE_ATTR(field, S_IRUGO, show_session_int_param_##param, NULL); +static ISCSI_CLASS_ATTR(sess, field, S_IRUGO, show_session_int_param_##param, \ + NULL); iscsi_session_int_attr(initial_r2t, ISCSI_PARAM_INITIAL_R2T_EN, "%d"); iscsi_session_int_attr(max_outstanding_r2t, ISCSI_PARAM_MAX_R2T, "%hu"); @@ -1084,18 +1159,88 @@ iscsi_session_int_attr(max_burst_len, ISCSI_PARAM_MAX_BURST, "%u"); iscsi_session_int_attr(data_pdu_in_order, ISCSI_PARAM_PDU_INORDER_EN, "%d"); iscsi_session_int_attr(data_seq_in_order, ISCSI_PARAM_DATASEQ_INORDER_EN, "%d"); iscsi_session_int_attr(erl, ISCSI_PARAM_ERL, "%d"); +iscsi_session_int_attr(tpgt, ISCSI_PARAM_TPGT, "%d"); -#define SETUP_SESSION_RD_ATTR(field, param) \ - if (priv->param_mask & (1 << param)) { \ - priv->session_attrs[count] = &class_device_attr_##field;\ - count++; \ - } +#define iscsi_session_str_attr_show(param) \ +static ssize_t \ +show_session_str_param_##param(struct class_device *cdev, char *buf) \ +{ \ + struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \ + struct iscsi_transport *t = session->transport; \ + return t->get_session_str_param(session, param, buf); \ +} + +#define iscsi_session_str_attr(field, param) \ + iscsi_session_str_attr_show(param) \ +static ISCSI_CLASS_ATTR(sess, field, S_IRUGO, show_session_str_param_##param, \ + NULL); + +iscsi_session_str_attr(targetname, ISCSI_PARAM_TARGET_NAME); -#define SETUP_CONN_RD_ATTR(field, param) \ - if (priv->param_mask & (1 << param)) { \ - priv->conn_attrs[count] = &class_device_attr_##field; \ +/* + * Private session and conn attrs. userspace uses several iscsi values + * to identify each session between reboots. Some of these values may not + * be present in the iscsi_transport/LLD driver becuase userspace handles + * login (and failback for login redirect) so for these type of drivers + * the class manages the attrs and values for the iscsi_transport/LLD + */ +#define iscsi_priv_session_attr_show(field, format) \ +static ssize_t \ +show_priv_session_##field(struct class_device *cdev, char *buf) \ +{ \ + struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \ + return sprintf(buf, format"\n", session->field); \ +} + +#define iscsi_priv_session_attr(field, format) \ + iscsi_priv_session_attr_show(field, format) \ +static ISCSI_CLASS_ATTR(priv_sess, field, S_IRUGO, show_priv_session_##field, \ + NULL) +iscsi_priv_session_attr(targetname, "%s"); +iscsi_priv_session_attr(tpgt, "%d"); + +#define iscsi_priv_conn_attr_show(field, format) \ +static ssize_t \ +show_priv_conn_##field(struct class_device *cdev, char *buf) \ +{ \ + struct iscsi_cls_conn *conn = iscsi_cdev_to_conn(cdev); \ + return sprintf(buf, format"\n", conn->field); \ +} + +#define iscsi_priv_conn_attr(field, format) \ + iscsi_priv_conn_attr_show(field, format) \ +static ISCSI_CLASS_ATTR(priv_conn, field, S_IRUGO, show_priv_conn_##field, \ + NULL) +iscsi_priv_conn_attr(persistent_address, "%s"); +iscsi_priv_conn_attr(persistent_port, "%d"); + +#define SETUP_PRIV_SESSION_RD_ATTR(field) \ +do { \ + priv->session_attrs[count] = &class_device_attr_priv_sess_##field; \ + count++; \ +} while (0) + +#define SETUP_SESSION_RD_ATTR(field, param_flag) \ +do { \ + if (tt->param_mask & param_flag) { \ + priv->session_attrs[count] = &class_device_attr_sess_##field; \ count++; \ - } + } \ +} while (0) + +#define SETUP_PRIV_CONN_RD_ATTR(field) \ +do { \ + priv->conn_attrs[count] = &class_device_attr_priv_conn_##field; \ + count++; \ +} while (0) + +#define SETUP_CONN_RD_ATTR(field, param_flag) \ +do { \ + if (tt->param_mask & param_flag) { \ + priv->conn_attrs[count] = &class_device_attr_conn_##field; \ + count++; \ + } \ +} while (0) static int iscsi_session_match(struct attribute_container *cont, struct device *dev) @@ -1173,31 +1318,30 @@ iscsi_register_transport(struct iscsi_transport *tt) if (err) goto unregister_cdev; - /* setup parameters mask */ - priv->param_mask = 0xFFFFFFFF; - if (!(tt->caps & CAP_MULTI_R2T)) - priv->param_mask &= ~(1 << ISCSI_PARAM_MAX_R2T); - if (!(tt->caps & CAP_HDRDGST)) - priv->param_mask &= ~(1 << ISCSI_PARAM_HDRDGST_EN); - if (!(tt->caps & CAP_DATADGST)) - priv->param_mask &= ~(1 << ISCSI_PARAM_DATADGST_EN); - if (!(tt->caps & CAP_MARKERS)) { - priv->param_mask &= ~(1 << ISCSI_PARAM_IFMARKER_EN); - priv->param_mask &= ~(1 << ISCSI_PARAM_OFMARKER_EN); - } - /* connection parameters */ priv->conn_cont.ac.attrs = &priv->conn_attrs[0]; priv->conn_cont.ac.class = &iscsi_connection_class.class; priv->conn_cont.ac.match = iscsi_conn_match; transport_container_register(&priv->conn_cont); - SETUP_CONN_RD_ATTR(max_recv_dlength, ISCSI_PARAM_MAX_RECV_DLENGTH); - SETUP_CONN_RD_ATTR(max_xmit_dlength, ISCSI_PARAM_MAX_XMIT_DLENGTH); - SETUP_CONN_RD_ATTR(header_digest, ISCSI_PARAM_HDRDGST_EN); - SETUP_CONN_RD_ATTR(data_digest, ISCSI_PARAM_DATADGST_EN); - SETUP_CONN_RD_ATTR(ifmarker, ISCSI_PARAM_IFMARKER_EN); - SETUP_CONN_RD_ATTR(ofmarker, ISCSI_PARAM_OFMARKER_EN); + SETUP_CONN_RD_ATTR(max_recv_dlength, ISCSI_MAX_RECV_DLENGTH); + SETUP_CONN_RD_ATTR(max_xmit_dlength, ISCSI_MAX_XMIT_DLENGTH); + SETUP_CONN_RD_ATTR(header_digest, ISCSI_HDRDGST_EN); + SETUP_CONN_RD_ATTR(data_digest, ISCSI_DATADGST_EN); + SETUP_CONN_RD_ATTR(ifmarker, ISCSI_IFMARKER_EN); + SETUP_CONN_RD_ATTR(ofmarker, ISCSI_OFMARKER_EN); + SETUP_CONN_RD_ATTR(address, ISCSI_CONN_ADDRESS); + SETUP_CONN_RD_ATTR(port, ISCSI_CONN_PORT); + + if (tt->param_mask & ISCSI_PERSISTENT_ADDRESS) + SETUP_CONN_RD_ATTR(persistent_address, ISCSI_PERSISTENT_ADDRESS); + else + SETUP_PRIV_CONN_RD_ATTR(persistent_address); + + if (tt->param_mask & ISCSI_PERSISTENT_PORT) + SETUP_CONN_RD_ATTR(persistent_port, ISCSI_PERSISTENT_PORT); + else + SETUP_PRIV_CONN_RD_ATTR(persistent_port); BUG_ON(count > ISCSI_CONN_ATTRS); priv->conn_attrs[count] = NULL; @@ -1209,14 +1353,24 @@ iscsi_register_transport(struct iscsi_transport *tt) priv->session_cont.ac.match = iscsi_session_match; transport_container_register(&priv->session_cont); - SETUP_SESSION_RD_ATTR(initial_r2t, ISCSI_PARAM_INITIAL_R2T_EN); - SETUP_SESSION_RD_ATTR(max_outstanding_r2t, ISCSI_PARAM_MAX_R2T); - SETUP_SESSION_RD_ATTR(immediate_data, ISCSI_PARAM_IMM_DATA_EN); - SETUP_SESSION_RD_ATTR(first_burst_len, ISCSI_PARAM_FIRST_BURST); - SETUP_SESSION_RD_ATTR(max_burst_len, ISCSI_PARAM_MAX_BURST); - SETUP_SESSION_RD_ATTR(data_pdu_in_order, ISCSI_PARAM_PDU_INORDER_EN); - SETUP_SESSION_RD_ATTR(data_seq_in_order,ISCSI_PARAM_DATASEQ_INORDER_EN) - SETUP_SESSION_RD_ATTR(erl, ISCSI_PARAM_ERL); + SETUP_SESSION_RD_ATTR(initial_r2t, ISCSI_INITIAL_R2T_EN); + SETUP_SESSION_RD_ATTR(max_outstanding_r2t, ISCSI_MAX_R2T); + SETUP_SESSION_RD_ATTR(immediate_data, ISCSI_IMM_DATA_EN); + SETUP_SESSION_RD_ATTR(first_burst_len, ISCSI_FIRST_BURST); + SETUP_SESSION_RD_ATTR(max_burst_len, ISCSI_MAX_BURST); + SETUP_SESSION_RD_ATTR(data_pdu_in_order, ISCSI_PDU_INORDER_EN); + SETUP_SESSION_RD_ATTR(data_seq_in_order, ISCSI_DATASEQ_INORDER_EN); + SETUP_SESSION_RD_ATTR(erl, ISCSI_ERL); + + if (tt->param_mask & ISCSI_TARGET_NAME) + SETUP_SESSION_RD_ATTR(targetname, ISCSI_TARGET_NAME); + else + SETUP_PRIV_SESSION_RD_ATTR(targetname); + + if (tt->param_mask & ISCSI_TPGT) + SETUP_SESSION_RD_ATTR(tpgt, ISCSI_TPGT); + else + SETUP_PRIV_SESSION_RD_ATTR(tpgt); BUG_ON(count > ISCSI_SESSION_ATTRS); priv->session_attrs[count] = NULL; diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h index 933a91b1474..2c3a89b64e7 100644 --- a/include/scsi/iscsi_if.h +++ b/include/scsi/iscsi_if.h @@ -86,7 +86,7 @@ struct iscsi_uevent { uint32_t sid; uint32_t cid; uint32_t param; /* enum iscsi_param */ - uint32_t value; + uint32_t len; } set_param; struct msg_start_conn { uint32_t sid; @@ -155,22 +155,54 @@ enum iscsi_err { * iSCSI Parameters (RFC3720) */ enum iscsi_param { - ISCSI_PARAM_MAX_RECV_DLENGTH = 0, - ISCSI_PARAM_MAX_XMIT_DLENGTH = 1, - ISCSI_PARAM_HDRDGST_EN = 2, - ISCSI_PARAM_DATADGST_EN = 3, - ISCSI_PARAM_INITIAL_R2T_EN = 4, - ISCSI_PARAM_MAX_R2T = 5, - ISCSI_PARAM_IMM_DATA_EN = 6, - ISCSI_PARAM_FIRST_BURST = 7, - ISCSI_PARAM_MAX_BURST = 8, - ISCSI_PARAM_PDU_INORDER_EN = 9, - ISCSI_PARAM_DATASEQ_INORDER_EN = 10, - ISCSI_PARAM_ERL = 11, - ISCSI_PARAM_IFMARKER_EN = 12, - ISCSI_PARAM_OFMARKER_EN = 13, + /* passed in using netlink set param */ + ISCSI_PARAM_MAX_RECV_DLENGTH, + ISCSI_PARAM_MAX_XMIT_DLENGTH, + ISCSI_PARAM_HDRDGST_EN, + ISCSI_PARAM_DATADGST_EN, + ISCSI_PARAM_INITIAL_R2T_EN, + ISCSI_PARAM_MAX_R2T, + ISCSI_PARAM_IMM_DATA_EN, + ISCSI_PARAM_FIRST_BURST, + ISCSI_PARAM_MAX_BURST, + ISCSI_PARAM_PDU_INORDER_EN, + ISCSI_PARAM_DATASEQ_INORDER_EN, + ISCSI_PARAM_ERL, + ISCSI_PARAM_IFMARKER_EN, + ISCSI_PARAM_OFMARKER_EN, + ISCSI_PARAM_TARGET_NAME, + ISCSI_PARAM_TPGT, + ISCSI_PARAM_PERSISTENT_ADDRESS, + ISCSI_PARAM_PERSISTENT_PORT, + + /* pased in through bind conn using transport_fd */ + ISCSI_PARAM_CONN_PORT, + ISCSI_PARAM_CONN_ADDRESS, + + /* must always be last */ + ISCSI_PARAM_MAX, }; -#define ISCSI_PARAM_MAX 14 + +#define ISCSI_MAX_RECV_DLENGTH (1 << ISCSI_PARAM_MAX_RECV_DLENGTH) +#define ISCSI_MAX_XMIT_DLENGTH (1 << ISCSI_PARAM_MAX_XMIT_DLENGTH) +#define ISCSI_HDRDGST_EN (1 << ISCSI_PARAM_HDRDGST_EN) +#define ISCSI_DATADGST_EN (1 << ISCSI_PARAM_DATADGST_EN) +#define ISCSI_INITIAL_R2T_EN (1 << ISCSI_PARAM_INITIAL_R2T_EN) +#define ISCSI_MAX_R2T (1 << ISCSI_PARAM_MAX_R2T) +#define ISCSI_IMM_DATA_EN (1 << ISCSI_PARAM_IMM_DATA_EN) +#define ISCSI_FIRST_BURST (1 << ISCSI_PARAM_FIRST_BURST) +#define ISCSI_MAX_BURST (1 << ISCSI_PARAM_MAX_BURST) +#define ISCSI_PDU_INORDER_EN (1 << ISCSI_PARAM_PDU_INORDER_EN) +#define ISCSI_DATASEQ_INORDER_EN (1 << ISCSI_PARAM_DATASEQ_INORDER_EN) +#define ISCSI_ERL (1 << ISCSI_PARAM_ERL) +#define ISCSI_IFMARKER_EN (1 << ISCSI_PARAM_IFMARKER_EN) +#define ISCSI_OFMARKER_EN (1 << ISCSI_PARAM_OFMARKER_EN) +#define ISCSI_TARGET_NAME (1 << ISCSI_PARAM_TARGET_NAME) +#define ISCSI_TPGT (1 << ISCSI_PARAM_TPGT) +#define ISCSI_PERSISTENT_ADDRESS (1 << ISCSI_PARAM_PERSISTENT_ADDRESS) +#define ISCSI_PERSISTENT_PORT (1 << ISCSI_PARAM_PERSISTENT_PORT) +#define ISCSI_CONN_PORT (1 << ISCSI_PARAM_CONN_PORT) +#define ISCSI_CONN_ADDRESS (1 << ISCSI_PARAM_CONN_ADDRESS) #define iscsi_ptr(_handle) ((void*)(unsigned long)_handle) #define iscsi_handle(_ptr) ((uint64_t)(unsigned long)_ptr) diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index 631463cd489..4b200645c84 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -53,11 +53,11 @@ struct iscsi_transport { struct module *owner; char *name; unsigned int caps; + /* LLD sets this to indicate what values it can export to sysfs */ + unsigned int param_mask; struct scsi_host_template *host_template; /* LLD session/scsi_host data size */ int hostdata_size; - /* LLD iscsi_host data size */ - int ihostdata_size; /* LLD connection data size */ int conndata_size; /* LLD session data size */ @@ -79,10 +79,13 @@ struct iscsi_transport { int (*set_param) (struct iscsi_cls_conn *conn, enum iscsi_param param, uint32_t value); int (*get_conn_param) (struct iscsi_cls_conn *conn, - enum iscsi_param param, - uint32_t *value); + enum iscsi_param param, uint32_t *value); int (*get_session_param) (struct iscsi_cls_session *session, enum iscsi_param param, uint32_t *value); + int (*get_conn_str_param) (struct iscsi_cls_conn *conn, + enum iscsi_param param, char *buf); + int (*get_session_str_param) (struct iscsi_cls_session *session, + enum iscsi_param param, char *buf); int (*send_pdu) (struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr, char *data, uint32_t data_size); void (*get_stats) (struct iscsi_cls_conn *conn, @@ -107,6 +110,14 @@ struct iscsi_cls_conn { void *dd_data; /* LLD private data */ struct iscsi_transport *transport; uint32_t cid; /* connection id */ + + /* portal/group values we got during discovery */ + char *persistent_address; + int persistent_port; + /* portal/group values we are currently using */ + char *address; + int port; + int active; /* must be accessed with the connlock */ struct device dev; /* sysfs transport/container device */ struct mempool_zone *z_error; @@ -120,6 +131,11 @@ struct iscsi_cls_conn { struct iscsi_cls_session { struct list_head sess_list; /* item in session_list */ struct iscsi_transport *transport; + + /* iSCSI values used as unique id by userspace. */ + char *targetname; + int tpgt; + int sid; /* session id */ void *dd_data; /* LLD private data */ struct device dev; /* sysfs transport/container device */ -- cgit v1.2.3 From 30a6c65236f9d26e3325cae468f330b833a3878c Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Thu, 6 Apr 2006 21:13:39 -0500 Subject: [SCSI] iscsi: fix up iscsi eh The current iscsi_tcp eh is not nicely setup for dm-multipath and performs some extra task management functions when they are not needed. The attached patch: - Fixes the TMF issues. If a session is rebuilt then we do not send aborts. - Fixes the problem where if the host reset fired, we would return SUCCESS even though we had not really done anything yet. This ends up causing problem with scsi_error.c's TUR. - If someone has turned on the userspace nop daemon code to try and detect network problems before the scsi command timeout we can now drop and clean up the session before the scsi command timesout and fires the eh speeding up the time it takes for a command to go from one patch to another. For network problems we fail the command with DID_BUS_BUSY so if failfast is set scsi_decide_disposition fails the command up to dm for it to try on another path. - And we had to add some basic iscsi session block code. Previously if we were trying to repair a session we would retrun a MLQUEUE code in the queuecommand. This worked but it was not the most efficient or pretty thing to do since it would take a while to relogin to the target. For iscsi_tcp/open-iscsi a lot of the iscsi error handler is in userspace the block code is pretty bare. We will be adding to that for qla4xxx. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/iscsi_tcp.c | 659 +++++++++++++++++++++--------------- drivers/scsi/iscsi_tcp.h | 3 + drivers/scsi/scsi_transport_iscsi.c | 152 ++++++++- include/scsi/iscsi_if.h | 2 + include/scsi/scsi_transport_iscsi.h | 19 +- 5 files changed, 561 insertions(+), 274 deletions(-) diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 6e510f3cfbf..aca3e23b1b9 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -82,6 +82,9 @@ module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO); /* global data */ static kmem_cache_t *taskcache; +#define session_to_cls(_sess) \ + hostdata_session(_sess->host->hostdata) + static inline void iscsi_buf_init_virt(struct iscsi_buf *ibuf, char *vbuf, int size) { @@ -230,17 +233,19 @@ iscsi_hdr_extract(struct iscsi_conn *conn) return 0; } -static inline void -iscsi_ctask_cleanup(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) +/* + * must be called with session lock + */ +static void +__iscsi_ctask_cleanup(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { - struct scsi_cmnd *sc = ctask->sc; struct iscsi_session *session = conn->session; + struct scsi_cmnd *sc; - spin_lock(&session->lock); - if (unlikely(!sc)) { - spin_unlock(&session->lock); + sc = ctask->sc; + if (unlikely(!sc)) return; - } + if (sc->sc_data_direction == DMA_TO_DEVICE) { struct iscsi_data_task *dtask, *n; /* WRITE: cleanup Data-Out's if any */ @@ -252,7 +257,20 @@ iscsi_ctask_cleanup(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) ctask->xmstate = XMSTATE_IDLE; ctask->r2t = NULL; ctask->sc = NULL; + list_del(&ctask->running); + __kfifo_put(session->cmdpool.queue, (void*)&ctask, sizeof(void*)); + + sc->scsi_done(sc); +} + +static void +iscsi_ctask_cleanup(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) +{ + struct iscsi_session *session = conn->session; + + spin_lock(&session->lock); + __iscsi_ctask_cleanup(conn, ctask); spin_unlock(&session->lock); } @@ -311,7 +329,6 @@ out: (long)sc, sc->result, ctask->itt); conn->scsirsp_pdus_cnt++; iscsi_ctask_cleanup(conn, ctask); - sc->scsi_done(sc); return rc; } @@ -395,6 +412,7 @@ iscsi_solicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, dtask = mempool_alloc(ctask->datapool, GFP_ATOMIC); BUG_ON(!dtask); + INIT_LIST_HEAD(&dtask->item); hdr = &dtask->hdr; memset(hdr, 0, sizeof(struct iscsi_data)); hdr->ttt = r2t->ttt; @@ -710,8 +728,6 @@ iscsi_hdr_recv(struct iscsi_conn *conn) conn->tmfrsp_pdus_cnt++; spin_lock(&session->lock); if (conn->tmabort_state == TMABORT_INITIAL) { - __kfifo_put(session->mgmtpool.queue, - (void*)&mtask, sizeof(void*)); conn->tmabort_state = ((struct iscsi_tm_rsp *)hdr)-> response == ISCSI_TMF_RSP_COMPLETE ? @@ -986,7 +1002,6 @@ done: (long)sc, sc->result, ctask->itt); conn->scsirsp_pdus_cnt++; iscsi_ctask_cleanup(conn, ctask); - sc->scsi_done(sc); } return rc; @@ -1460,6 +1475,7 @@ iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, dtask = mempool_alloc(ctask->datapool, GFP_ATOMIC); BUG_ON(!dtask); + INIT_LIST_HEAD(&dtask->item); hdr = &dtask->hdr; memset(hdr, 0, sizeof(struct iscsi_data)); hdr->ttt = r2t->ttt; @@ -1506,6 +1522,7 @@ iscsi_unsolicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) dtask = mempool_alloc(ctask->datapool, GFP_ATOMIC); BUG_ON(!dtask); + INIT_LIST_HEAD(&dtask->item); hdr = &dtask->hdr; memset(hdr, 0, sizeof(struct iscsi_data)); hdr->ttt = cpu_to_be32(ISCSI_RESERVED_TAG); @@ -1550,6 +1567,7 @@ iscsi_cmd_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, BUG_ON(__kfifo_len(ctask->r2tqueue)); + INIT_LIST_HEAD(&ctask->running); ctask->sc = sc; ctask->conn = conn; ctask->hdr.opcode = ISCSI_OP_SCSI_CMD; @@ -1680,7 +1698,7 @@ iscsi_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) if (mtask->data_count) mtask->xmstate |= XMSTATE_IMM_DATA; if (conn->c_stage != ISCSI_CONN_INITIAL_STAGE && - conn->stop_stage != STOP_CONN_RECOVER && + conn->stop_stage != STOP_CONN_RECOVER && conn->hdrdgst_en) iscsi_hdr_digest(conn, &mtask->headbuf, (u8*)mtask->hdrext); @@ -2226,6 +2244,7 @@ iscsi_data_xmit(struct iscsi_conn *conn) /* process command queue */ while (__kfifo_get(conn->xmitqueue, (void*)&conn->ctask, sizeof(void*))) { + list_add_tail(&conn->ctask->running, &conn->run_list); if (iscsi_ctask_xmit(conn, conn->ctask)) goto again; } @@ -2277,11 +2296,14 @@ iscsi_xmitworker(void *data) mutex_unlock(&conn->xmitmutex); } -#define FAILURE_BAD_HOST 1 -#define FAILURE_SESSION_FAILED 2 -#define FAILURE_SESSION_FREED 3 -#define FAILURE_WINDOW_CLOSED 4 -#define FAILURE_SESSION_TERMINATE 5 +enum { + FAILURE_BAD_HOST = 1, + FAILURE_SESSION_FAILED, + FAILURE_SESSION_FREED, + FAILURE_WINDOW_CLOSED, + FAILURE_SESSION_TERMINATE, + FAILURE_SESSION_RECOVERY_TIMEOUT, +}; static int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) @@ -2297,12 +2319,14 @@ iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) host = sc->device->host; session = iscsi_hostdata(host->hostdata); - BUG_ON(host != session->host); spin_lock(&session->lock); if (session->state != ISCSI_STATE_LOGGED_IN) { - if (session->state == ISCSI_STATE_FAILED) { + if (session->recovery_failed) { + reason = FAILURE_SESSION_RECOVERY_TIMEOUT; + goto fault; + } else if (session->state == ISCSI_STATE_FAILED) { reason = FAILURE_SESSION_FAILED; goto reject; } else if (session->state == ISCSI_STATE_TERMINATE) { @@ -2350,11 +2374,6 @@ fault: spin_unlock(&session->lock); printk(KERN_ERR "iscsi_tcp: cmd 0x%x is not queued (%d)\n", sc->cmnd[0], reason); - sc->sense_buffer[0] = 0x70; - sc->sense_buffer[2] = NOT_READY; - sc->sense_buffer[7] = 0x6; - sc->sense_buffer[12] = 0x08; - sc->sense_buffer[13] = 0x00; sc->result = (DID_NO_CONNECT << 16); sc->resid = sc->request_bufflen; sc->scsi_done(sc); @@ -2445,6 +2464,7 @@ iscsi_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx) conn->id = conn_idx; conn->exp_statsn = 0; conn->tmabort_state = TMABORT_INITIAL; + INIT_LIST_HEAD(&conn->run_list); /* initial operational parameters */ conn->hdr_size = sizeof(struct iscsi_hdr); @@ -2701,6 +2721,22 @@ iscsi_conn_bind(struct iscsi_cls_session *cls_session, return 0; } +static void +iscsi_session_recovery_timedout(struct iscsi_cls_session *csession) +{ + struct Scsi_Host *shost = iscsi_session_to_shost(csession); + struct iscsi_session *session = iscsi_hostdata(shost->hostdata); + struct iscsi_conn *conn = session->leadconn; + + spin_lock_bh(&session->lock); + if (session->state != ISCSI_STATE_LOGGED_IN) { + session->recovery_failed = 1; + if (conn) + wake_up(&conn->ehwait); + } + spin_unlock_bh(&session->lock); +} + static int iscsi_conn_start(struct iscsi_cls_conn *cls_conn) { @@ -2716,7 +2752,6 @@ iscsi_conn_start(struct iscsi_cls_conn *cls_conn) } sk = conn->sock->sk; - write_lock_bh(&sk->sk_callback_lock); spin_lock_bh(&session->lock); conn->c_stage = ISCSI_CONN_STARTED; @@ -2732,8 +2767,13 @@ iscsi_conn_start(struct iscsi_cls_conn *cls_conn) conn->stop_stage = 0; conn->tmabort_state = TMABORT_INITIAL; session->age++; + session->recovery_failed = 0; + spin_unlock_bh(&session->lock); + write_unlock_bh(&sk->sk_callback_lock); + + iscsi_unblock_session(session_to_cls(session)); wake_up(&conn->ehwait); - break; + return 0; case STOP_CONN_TERM: session->conn_cnt++; conn->stop_stage = 0; @@ -2752,105 +2792,199 @@ iscsi_conn_start(struct iscsi_cls_conn *cls_conn) return 0; } -static void -iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) +static int +iscsi_ctask_mtask_cleanup(struct iscsi_cmd_task *ctask) { - struct iscsi_conn *conn = cls_conn->dd_data; + struct iscsi_conn *conn = ctask->conn; struct iscsi_session *session = conn->session; + struct iscsi_mgmt_task *mtask; + + if (!ctask->mtask) + return -EINVAL; + + while (__kfifo_get(conn->immqueue, (void*)&mtask, sizeof(void*))) { + if (mtask == ctask->mtask) + break; + __kfifo_put(conn->immqueue, (void*)&mtask, sizeof(void*)); + } + + __kfifo_put(session->mgmtpool.queue, (void*)&ctask->mtask, + sizeof(void*)); + ctask->mtask = NULL; + return 0; +} + +static void +fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, int err) +{ + struct iscsi_r2t_info *r2t; + struct scsi_cmnd *sc; + + /* flush ctask's r2t queues */ + while (__kfifo_get(ctask->r2tqueue, (void*)&r2t, sizeof(void*))) + __kfifo_put(ctask->r2tpool.queue, (void*)&r2t, sizeof(void*)); + + iscsi_ctask_mtask_cleanup(ctask); + + sc = ctask->sc; + if (!sc) + return; + + sc->result = err; + sc->resid = sc->request_bufflen; + + __iscsi_ctask_cleanup(conn, ctask); +} + +/* Fail commands. Mutex and session lock held */ +static void +fail_all_commands(struct iscsi_session *session, struct iscsi_conn *conn) +{ + struct iscsi_cmd_task *ctask, *tmp; + + /* flush pending */ + while (__kfifo_get(conn->xmitqueue, (void*)&ctask, sizeof(void*))) { + debug_scsi("failing pending sc %p itt 0x%x\n", ctask->sc, + ctask->itt); + fail_command(conn, ctask, DID_BUS_BUSY << 16); + } + + /* fail running */ + list_for_each_entry_safe(ctask, tmp, &conn->run_list, running) { + debug_scsi("failing in progress sc %p itt 0x%x\n", + ctask->sc, ctask->itt); + fail_command(conn, ctask, DID_BUS_BUSY << 16); + } + + conn->ctask = NULL; +} + +static void +flush_control_queues(struct iscsi_session *session, struct iscsi_conn *conn) +{ + struct iscsi_mgmt_task *mtask; + + /* TODO: handle running pdus */ + while (__kfifo_get(conn->immqueue, (void*)&mtask, sizeof(void*)) || + __kfifo_get(conn->mgmtqueue, (void*)&mtask, sizeof(void*))) { + if (mtask == conn->login_mtask) + continue; + __kfifo_put(session->mgmtpool.queue, (void*)&mtask, + sizeof(void*)); + } + + if (conn->mtask && conn->mtask != conn->login_mtask) + __kfifo_put(session->mgmtpool.queue, (void*)&conn->mtask, + sizeof(void*)); + conn->mtask = NULL; +} + +static void +iscsi_suspend_conn_rx(struct iscsi_conn *conn) +{ struct sock *sk; - unsigned long flags; BUG_ON(!conn->sock); sk = conn->sock->sk; write_lock_bh(&sk->sk_callback_lock); set_bit(SUSPEND_BIT, &conn->suspend_rx); write_unlock_bh(&sk->sk_callback_lock); +} - mutex_lock(&conn->xmitmutex); - - spin_lock_irqsave(session->host->host_lock, flags); - spin_lock(&session->lock); +static void +iscsi_start_session_recovery(struct iscsi_session *session, + struct iscsi_conn *conn, int flag) +{ + spin_lock_bh(&session->lock); + if (conn->stop_stage == STOP_CONN_RECOVER || + conn->stop_stage == STOP_CONN_TERM) { + spin_unlock_bh(&session->lock); + return; + } conn->stop_stage = flag; + spin_unlock_bh(&session->lock); + + iscsi_suspend_conn_rx(conn); + + mutex_lock(&conn->xmitmutex); + spin_lock_bh(&session->lock); conn->c_stage = ISCSI_CONN_STOPPED; set_bit(SUSPEND_BIT, &conn->suspend_tx); - if (flag != STOP_CONN_SUSPEND) - session->conn_cnt--; - + session->conn_cnt--; if (session->conn_cnt == 0 || session->leadconn == conn) session->state = ISCSI_STATE_FAILED; - spin_unlock(&session->lock); - spin_unlock_irqrestore(session->host->host_lock, flags); - - if (flag == STOP_CONN_TERM || flag == STOP_CONN_RECOVER) { - struct iscsi_cmd_task *ctask; - struct iscsi_mgmt_task *mtask; + spin_unlock_bh(&session->lock); - /* - * Socket must go now. - */ - sock_hold(conn->sock->sk); - iscsi_conn_restore_callbacks(conn); - sock_put(conn->sock->sk); + /* + * Socket must go now. + */ + sock_hold(conn->sock->sk); + iscsi_conn_restore_callbacks(conn); + sock_put(conn->sock->sk); - /* - * flush xmit queues. - */ - spin_lock_bh(&session->lock); - while (__kfifo_get(conn->writequeue, (void*)&ctask, - sizeof(void*)) || - __kfifo_get(conn->xmitqueue, (void*)&ctask, - sizeof(void*))) { - struct iscsi_r2t_info *r2t; - - /* - * flush ctask's r2t queues - */ - while (__kfifo_get(ctask->r2tqueue, (void*)&r2t, - sizeof(void*))) - __kfifo_put(ctask->r2tpool.queue, (void*)&r2t, - sizeof(void*)); + /* + * flush queues. + */ + spin_lock_bh(&session->lock); + fail_all_commands(session, conn); + flush_control_queues(session, conn); + spin_unlock_bh(&session->lock); - spin_unlock_bh(&session->lock); - local_bh_disable(); - iscsi_ctask_cleanup(conn, ctask); - local_bh_enable(); - spin_lock_bh(&session->lock); - } - conn->ctask = NULL; - while (__kfifo_get(conn->immqueue, (void*)&mtask, - sizeof(void*)) || - __kfifo_get(conn->mgmtqueue, (void*)&mtask, - sizeof(void*))) { - __kfifo_put(session->mgmtpool.queue, - (void*)&mtask, sizeof(void*)); - } - conn->mtask = NULL; - spin_unlock_bh(&session->lock); + /* + * release socket only after we stopped data_xmit() + * activity and flushed all outstandings + */ + sock_release(conn->sock); + conn->sock = NULL; - /* - * release socket only after we stopped data_xmit() - * activity and flushed all outstandings - */ - sock_release(conn->sock); - conn->sock = NULL; + /* + * for connection level recovery we should not calculate + * header digest. conn->hdr_size used for optimization + * in hdr_extract() and will be re-negotiated at + * set_param() time. + */ + if (flag == STOP_CONN_RECOVER) { + conn->hdr_size = sizeof(struct iscsi_hdr); + conn->hdrdgst_en = 0; + conn->datadgst_en = 0; - /* - * for connection level recovery we should not calculate - * header digest. conn->hdr_size used for optimization - * in hdr_extract() and will be re-negotiated at - * set_param() time. - */ - if (flag == STOP_CONN_RECOVER) { - conn->hdr_size = sizeof(struct iscsi_hdr); - conn->hdrdgst_en = 0; - conn->datadgst_en = 0; - } + if (session->state == ISCSI_STATE_FAILED) + iscsi_block_session(session_to_cls(session)); } mutex_unlock(&conn->xmitmutex); } +static void +iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) +{ + struct iscsi_conn *conn = cls_conn->dd_data; + struct iscsi_session *session = conn->session; + + switch (flag) { + case STOP_CONN_RECOVER: + case STOP_CONN_TERM: + iscsi_start_session_recovery(session, conn, flag); + return; + case STOP_CONN_SUSPEND: + iscsi_suspend_conn_rx(conn); + + mutex_lock(&conn->xmitmutex); + spin_lock_bh(&session->lock); + + conn->stop_stage = flag; + conn->c_stage = ISCSI_CONN_STOPPED; + set_bit(SUSPEND_BIT, &conn->suspend_tx); + + spin_unlock_bh(&session->lock); + mutex_unlock(&conn->xmitmutex); + break; + default: + printk(KERN_ERR "invalid stop flag %d\n", flag); + } +} + static int iscsi_conn_send_generic(struct iscsi_conn *conn, struct iscsi_hdr *hdr, char *data, uint32_t data_size) @@ -2940,23 +3074,54 @@ iscsi_conn_send_generic(struct iscsi_conn *conn, struct iscsi_hdr *hdr, static int iscsi_eh_host_reset(struct scsi_cmnd *sc) { - struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)sc->SCp.ptr; - struct iscsi_conn *conn = ctask->conn; - struct iscsi_session *session = conn->session; + struct Scsi_Host *host = sc->device->host; + struct iscsi_session *session = iscsi_hostdata(host->hostdata); + struct iscsi_conn *conn = session->leadconn; + int fail_session = 0; spin_lock_bh(&session->lock); if (session->state == ISCSI_STATE_TERMINATE) { +failed: debug_scsi("failing host reset: session terminated " "[CID %d age %d]", conn->id, session->age); spin_unlock_bh(&session->lock); return FAILED; } + + if (sc->SCp.phase == session->age) { + debug_scsi("failing connection CID %d due to SCSI host reset", + conn->id); + fail_session = 1; + } spin_unlock_bh(&session->lock); - debug_scsi("failing connection CID %d due to SCSI host reset " - "[itt 0x%x age %d]", conn->id, ctask->itt, - session->age); - iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); + /* + * we drop the lock here but the leadconn cannot be destoyed while + * we are in the scsi eh + */ + if (fail_session) { + iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); + /* + * if userspace cannot respond then we must kick this off + * here for it + */ + iscsi_start_session_recovery(session, conn, STOP_CONN_RECOVER); + } + + debug_scsi("iscsi_eh_host_reset wait for relogin\n"); + wait_event_interruptible(conn->ehwait, + session->state == ISCSI_STATE_TERMINATE || + session->state == ISCSI_STATE_LOGGED_IN || + session->recovery_failed); + if (signal_pending(current)) + flush_signals(current); + + spin_lock_bh(&session->lock); + if (session->state == ISCSI_STATE_LOGGED_IN) + printk(KERN_INFO "host reset succeeded\n"); + else + goto failed; + spin_unlock_bh(&session->lock); return SUCCESS; } @@ -2970,8 +3135,6 @@ iscsi_tmabort_timedout(unsigned long data) spin_lock(&session->lock); if (conn->tmabort_state == TMABORT_INITIAL) { - __kfifo_put(session->mgmtpool.queue, - (void*)&ctask->mtask, sizeof(void*)); conn->tmabort_state = TMABORT_TIMEDOUT; debug_scsi("tmabort timedout [sc %lx itt 0x%x]\n", (long)ctask->sc, ctask->itt); @@ -2981,186 +3144,163 @@ iscsi_tmabort_timedout(unsigned long data) spin_unlock(&session->lock); } +/* must be called with the mutex lock */ static int -iscsi_eh_abort(struct scsi_cmnd *sc) +iscsi_exec_abort_task(struct scsi_cmnd *sc, struct iscsi_cmd_task *ctask) { - int rc; - struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)sc->SCp.ptr; struct iscsi_conn *conn = ctask->conn; struct iscsi_session *session = conn->session; - - conn->eh_abort_cnt++; - debug_scsi("aborting [sc %lx itt 0x%x]\n", (long)sc, ctask->itt); + struct iscsi_tm *hdr = &conn->tmhdr; + int rc; /* - * two cases for ERL=0 here: - * - * 1) connection-level failure; - * 2) recovery due protocol error; + * ctask timed out but session is OK requests must be serialized. */ - mutex_lock(&conn->xmitmutex); - spin_lock_bh(&session->lock); - if (session->state != ISCSI_STATE_LOGGED_IN) { - if (session->state == ISCSI_STATE_TERMINATE) { - spin_unlock_bh(&session->lock); - mutex_unlock(&conn->xmitmutex); - goto failed; - } - spin_unlock_bh(&session->lock); - } else { - struct iscsi_tm *hdr = &conn->tmhdr; + memset(hdr, 0, sizeof(struct iscsi_tm)); + hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE; + hdr->flags = ISCSI_TM_FUNC_ABORT_TASK; + hdr->flags |= ISCSI_FLAG_CMD_FINAL; + memcpy(hdr->lun, ctask->hdr.lun, sizeof(hdr->lun)); + hdr->rtt = ctask->hdr.itt; + hdr->refcmdsn = ctask->hdr.cmdsn; - /* - * Still LOGGED_IN... - */ + rc = iscsi_conn_send_generic(conn, (struct iscsi_hdr *)hdr, + NULL, 0); + if (rc) { + iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); + debug_scsi("abort sent failure [itt 0x%x] %d", ctask->itt, rc); + return rc; + } - if (!ctask->sc || sc->SCp.phase != session->age) { - /* - * 1) ctask completed before time out. But session - * is still ok => Happy Retry. - * 2) session was re-open during time out of ctask. - */ - spin_unlock_bh(&session->lock); - mutex_unlock(&conn->xmitmutex); - goto success; - } - conn->tmabort_state = TMABORT_INITIAL; - spin_unlock_bh(&session->lock); + debug_scsi("abort sent [itt 0x%x]\n", ctask->itt); - /* - * ctask timed out but session is OK - * ERL=0 requires task mgmt abort to be issued on each - * failed command. requests must be serialized. - */ - memset(hdr, 0, sizeof(struct iscsi_tm)); - hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE; - hdr->flags = ISCSI_TM_FUNC_ABORT_TASK; - hdr->flags |= ISCSI_FLAG_CMD_FINAL; - memcpy(hdr->lun, ctask->hdr.lun, sizeof(hdr->lun)); - hdr->rtt = ctask->hdr.itt; - hdr->refcmdsn = ctask->hdr.cmdsn; - - rc = iscsi_conn_send_generic(conn, (struct iscsi_hdr *)hdr, - NULL, 0); - if (rc) { - iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); - debug_scsi("abort sent failure [itt 0x%x]", ctask->itt); - } else { - struct iscsi_r2t_info *r2t; - - /* - * TMF abort vs. TMF response race logic - */ - spin_lock_bh(&session->lock); - ctask->mtask = (struct iscsi_mgmt_task *) - session->mgmt_cmds[(hdr->itt & ITT_MASK) - - ISCSI_MGMT_ITT_OFFSET]; - /* - * have to flush r2tqueue to avoid r2t leaks - */ - while (__kfifo_get(ctask->r2tqueue, (void*)&r2t, - sizeof(void*))) { - __kfifo_put(ctask->r2tpool.queue, (void*)&r2t, - sizeof(void*)); - } - if (conn->tmabort_state == TMABORT_INITIAL) { - conn->tmfcmd_pdus_cnt++; - conn->tmabort_timer.expires = 3*HZ + jiffies; - conn->tmabort_timer.function = - iscsi_tmabort_timedout; - conn->tmabort_timer.data = (unsigned long)ctask; - add_timer(&conn->tmabort_timer); - debug_scsi("abort sent [itt 0x%x]", ctask->itt); - } else { - if (!ctask->sc || - conn->tmabort_state == TMABORT_SUCCESS) { - conn->tmabort_state = TMABORT_INITIAL; - spin_unlock_bh(&session->lock); - mutex_unlock(&conn->xmitmutex); - goto success; - } - conn->tmabort_state = TMABORT_INITIAL; - iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); - } - spin_unlock_bh(&session->lock); - } + spin_lock_bh(&session->lock); + ctask->mtask = (struct iscsi_mgmt_task *) + session->mgmt_cmds[(hdr->itt & ITT_MASK) - + ISCSI_MGMT_ITT_OFFSET]; + + if (conn->tmabort_state == TMABORT_INITIAL) { + conn->tmfcmd_pdus_cnt++; + conn->tmabort_timer.expires = 10*HZ + jiffies; + conn->tmabort_timer.function = iscsi_tmabort_timedout; + conn->tmabort_timer.data = (unsigned long)ctask; + add_timer(&conn->tmabort_timer); + debug_scsi("abort set timeout [itt 0x%x]", ctask->itt); } + spin_unlock_bh(&session->lock); mutex_unlock(&conn->xmitmutex); - /* * block eh thread until: * - * 1) abort response; - * 2) abort timeout; - * 3) session re-opened; - * 4) session terminated; + * 1) abort response + * 2) abort timeout + * 3) session is terminated or restarted or userspace has + * given up on recovery */ - for (;;) { - int p_state = session->state; - - rc = wait_event_interruptible(conn->ehwait, - (p_state == ISCSI_STATE_LOGGED_IN ? - (session->state == ISCSI_STATE_TERMINATE || - conn->tmabort_state != TMABORT_INITIAL) : - (session->state == ISCSI_STATE_TERMINATE || - session->state == ISCSI_STATE_LOGGED_IN))); - if (rc) { - /* shutdown.. */ - session->state = ISCSI_STATE_TERMINATE; - goto failed; - } + wait_event_interruptible(conn->ehwait, + sc->SCp.phase != session->age || + session->state != ISCSI_STATE_LOGGED_IN || + conn->tmabort_state != TMABORT_INITIAL || + session->recovery_failed); + if (signal_pending(current)) + flush_signals(current); + del_timer_sync(&conn->tmabort_timer); - if (signal_pending(current)) - flush_signals(current); + mutex_lock(&conn->xmitmutex); + return 0; +} - if (session->state == ISCSI_STATE_TERMINATE) - goto failed; +static int +iscsi_eh_abort(struct scsi_cmnd *sc) +{ + struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)sc->SCp.ptr; + struct iscsi_cmd_task *tmp_ctask; + struct iscsi_conn *conn = ctask->conn; + struct iscsi_session *session = conn->session; + int rc; - spin_lock_bh(&session->lock); - if (sc->SCp.phase == session->age && - (conn->tmabort_state == TMABORT_TIMEDOUT || - conn->tmabort_state == TMABORT_FAILED)) { - conn->tmabort_state = TMABORT_INITIAL; - if (!ctask->sc) { - /* - * ctask completed before tmf abort response or - * time out. - * But session is still ok => Happy Retry. - */ - spin_unlock_bh(&session->lock); - break; - } - spin_unlock_bh(&session->lock); - iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); - continue; + conn->eh_abort_cnt++; + debug_scsi("aborting [sc %p itt 0x%x]\n", sc, ctask->itt); + + mutex_lock(&conn->xmitmutex); + spin_lock_bh(&session->lock); + + /* + * If we are not logged in or we have started a new session + * then let the host reset code handle this + */ + if (session->state != ISCSI_STATE_LOGGED_IN || + sc->SCp.phase != session->age) + goto failed; + + /* ctask completed before time out */ + if (!ctask->sc) + goto success; + + /* what should we do here ? */ + if (conn->ctask == ctask) { + printk(KERN_INFO "sc %p itt 0x%x partially sent. Failing " + "abort\n", sc, ctask->itt); + goto failed; + } + + /* check for the easy pending cmd abort */ + while (__kfifo_get(conn->xmitqueue, (void*)&tmp_ctask, sizeof(void*))) { + if (tmp_ctask->itt == ctask->itt) { + debug_scsi("found pending task\n"); + goto success; } + __kfifo_put(conn->xmitqueue, (void*)&tmp_ctask, sizeof(void*)); + } + + conn->tmabort_state = TMABORT_INITIAL; + + spin_unlock_bh(&session->lock); + rc = iscsi_exec_abort_task(sc, ctask); + spin_lock_bh(&session->lock); + + iscsi_ctask_mtask_cleanup(ctask); + if (rc || sc->SCp.phase != session->age || + session->state != ISCSI_STATE_LOGGED_IN) + goto failed; + + /* ctask completed before tmf abort response */ + if (!ctask->sc) { + debug_scsi("sc completed while abort in progress\n"); + goto success; + } + + if (conn->tmabort_state != TMABORT_SUCCESS) { spin_unlock_bh(&session->lock); - break; + iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); + spin_lock_bh(&session->lock); + goto failed; } success: debug_scsi("abort success [sc %lx itt 0x%x]\n", (long)sc, ctask->itt); - rc = SUCCESS; - goto exit; - -failed: - debug_scsi("abort failed [sc %lx itt 0x%x]\n", (long)sc, ctask->itt); - rc = FAILED; - -exit: - del_timer_sync(&conn->tmabort_timer); + spin_unlock_bh(&session->lock); - mutex_lock(&conn->xmitmutex); + /* clean up task if aborted */ if (conn->sock) { struct sock *sk = conn->sock->sk; write_lock_bh(&sk->sk_callback_lock); - iscsi_ctask_cleanup(conn, ctask); + spin_lock(&session->lock); + fail_command(conn, ctask, DRIVER_TIMEOUT << 24); + spin_unlock(&session->lock); write_unlock_bh(&sk->sk_callback_lock); } mutex_unlock(&conn->xmitmutex); - return rc; + return SUCCESS; + +failed: + spin_unlock_bh(&session->lock); + mutex_unlock(&conn->xmitmutex); + + debug_scsi("abort failed [sc %lx itt 0x%x]\n", (long)sc, ctask->itt); + return FAILED; } static int @@ -3359,16 +3499,6 @@ iscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param, struct iscsi_conn *conn = cls_conn->dd_data; struct iscsi_session *session = conn->session; - spin_lock_bh(&session->lock); - if (conn->c_stage != ISCSI_CONN_INITIAL_STAGE && - conn->stop_stage != STOP_CONN_RECOVER) { - printk(KERN_ERR "iscsi_tcp: can not change parameter [%d]\n", - param); - spin_unlock_bh(&session->lock); - return 0; - } - spin_unlock_bh(&session->lock); - switch(param) { case ISCSI_PARAM_MAX_RECV_DLENGTH: { char *saveptr = conn->data; @@ -3691,6 +3821,7 @@ static struct iscsi_transport iscsi_tcp_transport = { .stop_conn = iscsi_conn_stop, .send_pdu = iscsi_conn_send_pdu, .get_stats = iscsi_conn_get_stats, + .session_recovery_timedout = iscsi_session_recovery_timedout, }; static int __init diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h index ba26741ac15..12ef64179b4 100644 --- a/drivers/scsi/iscsi_tcp.h +++ b/drivers/scsi/iscsi_tcp.h @@ -159,6 +159,7 @@ struct iscsi_conn { struct kfifo *immqueue; /* immediate xmit queue */ struct kfifo *mgmtqueue; /* mgmt (control) xmit queue */ struct kfifo *xmitqueue; /* data-path cmd queue */ + struct list_head run_list; /* list of cmds in progress */ struct work_struct xmitwork; /* per-conn. xmit workqueue */ struct mutex xmitmutex; /* serializes connection xmit, * access to kfifos: * @@ -228,6 +229,7 @@ struct iscsi_session { * - mgmtpool, * * - r2tpool */ int state; /* session state */ + int recovery_failed; struct list_head item; void *auth_client; int conn_cnt; @@ -310,6 +312,7 @@ struct iscsi_cmd_task { struct iscsi_conn *conn; /* used connection */ struct iscsi_mgmt_task *mtask; /* tmf mtask in progr */ + struct list_head running; /* running cmd list */ struct iscsi_r2t_info *r2t; /* in progress R2T */ struct iscsi_queue r2tpool; struct kfifo *r2tqueue; diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 72a71ebc9d0..e2b67e34d92 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -31,17 +31,17 @@ #include #include -#define ISCSI_SESSION_ATTRS 10 +#define ISCSI_SESSION_ATTRS 11 #define ISCSI_CONN_ATTRS 10 +#define ISCSI_HOST_ATTRS 0 struct iscsi_internal { struct scsi_transport_template t; struct iscsi_transport *iscsi_transport; struct list_head list; struct class_device cdev; - /* - * We do not have any private or other attrs. - */ + + struct class_device_attribute *host_attrs[ISCSI_HOST_ATTRS + 1]; struct transport_container conn_cont; struct class_device_attribute *conn_attrs[ISCSI_CONN_ATTRS + 1]; struct transport_container session_cont; @@ -114,6 +114,24 @@ static struct attribute_group iscsi_transport_group = { .attrs = iscsi_transport_attrs, }; +static int iscsi_setup_host(struct transport_container *tc, struct device *dev, + struct class_device *cdev) +{ + struct Scsi_Host *shost = dev_to_shost(dev); + struct iscsi_host *ihost = shost->shost_data; + + memset(ihost, 0, sizeof(*ihost)); + INIT_LIST_HEAD(&ihost->sessions); + mutex_init(&ihost->mutex); + return 0; +} + +static DECLARE_TRANSPORT_CLASS(iscsi_host_class, + "iscsi_host", + iscsi_setup_host, + NULL, + NULL); + static DECLARE_TRANSPORT_CLASS(iscsi_session_class, "iscsi_session", NULL, @@ -225,6 +243,54 @@ static int iscsi_is_session_dev(const struct device *dev) return dev->release == iscsi_session_release; } +static int iscsi_user_scan(struct Scsi_Host *shost, uint channel, + uint id, uint lun) +{ + struct iscsi_host *ihost = shost->shost_data; + struct iscsi_cls_session *session; + + mutex_lock(&ihost->mutex); + list_for_each_entry(session, &ihost->sessions, host_list) { + if ((channel == SCAN_WILD_CARD || + channel == session->channel) && + (id == SCAN_WILD_CARD || id == session->target_id)) + scsi_scan_target(&session->dev, session->channel, + session->target_id, lun, 1); + } + mutex_unlock(&ihost->mutex); + + return 0; +} + +static void session_recovery_timedout(void *data) +{ + struct iscsi_cls_session *session = data; + + dev_printk(KERN_INFO, &session->dev, "session recovery timed out " + "after %d secs\n", session->recovery_tmo); + + if (session->transport->session_recovery_timedout) + session->transport->session_recovery_timedout(session); + + scsi_target_unblock(&session->dev); +} + +void iscsi_unblock_session(struct iscsi_cls_session *session) +{ + if (!cancel_delayed_work(&session->recovery_work)) + flush_scheduled_work(); + scsi_target_unblock(&session->dev); +} +EXPORT_SYMBOL_GPL(iscsi_unblock_session); + +void iscsi_block_session(struct iscsi_cls_session *session) +{ + scsi_target_block(&session->dev); + schedule_delayed_work(&session->recovery_work, + session->recovery_tmo * HZ); +} +EXPORT_SYMBOL_GPL(iscsi_block_session); + /** * iscsi_create_session - create iscsi class session * @shost: scsi host @@ -233,8 +299,10 @@ static int iscsi_is_session_dev(const struct device *dev) * This can be called from a LLD or iscsi_transport. **/ struct iscsi_cls_session * -iscsi_create_session(struct Scsi_Host *shost, struct iscsi_transport *transport) +iscsi_create_session(struct Scsi_Host *shost, + struct iscsi_transport *transport, int channel) { + struct iscsi_host *ihost; struct iscsi_cls_session *session; int err; @@ -246,13 +314,22 @@ iscsi_create_session(struct Scsi_Host *shost, struct iscsi_transport *transport) if (!session) goto module_put; session->transport = transport; + session->recovery_tmo = 120; + INIT_WORK(&session->recovery_work, session_recovery_timedout, session); + INIT_LIST_HEAD(&session->host_list); + INIT_LIST_HEAD(&session->sess_list); if (transport->sessiondata_size) session->dd_data = &session[1]; /* this is released in the dev's release function */ scsi_host_get(shost); + ihost = shost->shost_data; + session->sid = iscsi_session_nr++; + session->channel = channel; + session->target_id = ihost->next_target_id++; + snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u", session->sid); session->dev.parent = &shost->shost_gendev; @@ -265,6 +342,10 @@ iscsi_create_session(struct Scsi_Host *shost, struct iscsi_transport *transport) } transport_register_device(&session->dev); + mutex_lock(&ihost->mutex); + list_add(&session->host_list, &ihost->sessions); + mutex_unlock(&ihost->mutex); + return session; free_session: @@ -285,6 +366,16 @@ EXPORT_SYMBOL_GPL(iscsi_create_session); **/ int iscsi_destroy_session(struct iscsi_cls_session *session) { + struct Scsi_Host *shost = iscsi_session_to_shost(session); + struct iscsi_host *ihost = shost->shost_data; + + if (!cancel_delayed_work(&session->recovery_work)) + flush_scheduled_work(); + + mutex_lock(&ihost->mutex); + list_del(&session->host_list); + mutex_unlock(&ihost->mutex); + transport_unregister_device(&session->dev); device_unregister(&session->dev); return 0; @@ -435,7 +526,7 @@ iscsi_transport_create_session(struct scsi_transport_template *scsit, if (scsi_add_host(shost, NULL)) goto free_host; - session = iscsi_create_session(shost, transport); + session = iscsi_create_session(shost, transport, 0); if (!session) goto remove_host; @@ -466,12 +557,13 @@ int iscsi_transport_destroy_session(struct Scsi_Host *shost) struct iscsi_cls_session *session; unsigned long flags; - scsi_remove_host(shost); session = hostdata_session(shost->hostdata); spin_lock_irqsave(&sesslock, flags); list_del(&session->sess_list); spin_unlock_irqrestore(&sesslock, flags); iscsi_destroy_session(session); + + scsi_remove_host(shost); /* ref from host alloc */ scsi_host_put(shost); return 0; @@ -594,6 +686,7 @@ iscsi_unicast_skb(struct mempool_zone *zone, struct sk_buff *skb) } spin_lock_irqsave(&zone->freelock, flags); + INIT_LIST_HEAD(skb_to_lh(skb)); list_add(skb_to_lh(skb), &zone->freequeue); spin_unlock_irqrestore(&zone->freelock, flags); @@ -888,6 +981,11 @@ iscsi_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev) return -EINVAL; switch (ev->u.set_param.param) { + case ISCSI_PARAM_SESS_RECOVERY_TMO: + iscsi_copy_param(ev, &value, data); + if (value != 0) + session->recovery_tmo = value; + break; case ISCSI_PARAM_TARGET_NAME: /* this should not change between logins */ if (session->targetname) @@ -980,7 +1078,6 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) ev->r.retcode = transport->start_conn(conn); else err = -EINVAL; - break; case ISCSI_UEVENT_STOP_CONN: conn = iscsi_conn_lookup(ev->u.stop_conn.sid, ev->u.stop_conn.cid); @@ -1198,6 +1295,7 @@ static ISCSI_CLASS_ATTR(priv_sess, field, S_IRUGO, show_priv_session_##field, \ NULL) iscsi_priv_session_attr(targetname, "%s"); iscsi_priv_session_attr(tpgt, "%d"); +iscsi_priv_session_attr(recovery_tmo, "%d"); #define iscsi_priv_conn_attr_show(field, format) \ static ssize_t \ @@ -1289,6 +1387,24 @@ static int iscsi_conn_match(struct attribute_container *cont, return &priv->conn_cont.ac == cont; } +static int iscsi_host_match(struct attribute_container *cont, + struct device *dev) +{ + struct Scsi_Host *shost; + struct iscsi_internal *priv; + + if (!scsi_is_host_device(dev)) + return 0; + + shost = dev_to_shost(dev); + if (!shost->transportt || + shost->transportt->host_attrs.ac.class != &iscsi_host_class.class) + return 0; + + priv = to_iscsi_internal(shost->transportt); + return &priv->t.host_attrs.ac == cont; +} + struct scsi_transport_template * iscsi_register_transport(struct iscsi_transport *tt) { @@ -1307,6 +1423,7 @@ iscsi_register_transport(struct iscsi_transport *tt) return NULL; INIT_LIST_HEAD(&priv->list); priv->iscsi_transport = tt; + priv->t.user_scan = iscsi_user_scan; priv->cdev.class = &iscsi_transport_class; snprintf(priv->cdev.class_id, BUS_ID_SIZE, "%s", tt->name); @@ -1318,6 +1435,14 @@ iscsi_register_transport(struct iscsi_transport *tt) if (err) goto unregister_cdev; + /* host parameters */ + priv->t.host_attrs.ac.attrs = &priv->host_attrs[0]; + priv->t.host_attrs.ac.class = &iscsi_host_class.class; + priv->t.host_attrs.ac.match = iscsi_host_match; + priv->t.host_size = sizeof(struct iscsi_host); + priv->host_attrs[0] = NULL; + transport_container_register(&priv->t.host_attrs); + /* connection parameters */ priv->conn_cont.ac.attrs = &priv->conn_attrs[0]; priv->conn_cont.ac.class = &iscsi_connection_class.class; @@ -1361,6 +1486,7 @@ iscsi_register_transport(struct iscsi_transport *tt) SETUP_SESSION_RD_ATTR(data_pdu_in_order, ISCSI_PDU_INORDER_EN); SETUP_SESSION_RD_ATTR(data_seq_in_order, ISCSI_DATASEQ_INORDER_EN); SETUP_SESSION_RD_ATTR(erl, ISCSI_ERL); + SETUP_PRIV_SESSION_RD_ATTR(recovery_tmo); if (tt->param_mask & ISCSI_TARGET_NAME) SETUP_SESSION_RD_ATTR(targetname, ISCSI_TARGET_NAME); @@ -1408,6 +1534,7 @@ int iscsi_unregister_transport(struct iscsi_transport *tt) transport_container_unregister(&priv->conn_cont); transport_container_unregister(&priv->session_cont); + transport_container_unregister(&priv->t.host_attrs); sysfs_remove_group(&priv->cdev.kobj, &iscsi_transport_group); class_device_unregister(&priv->cdev); @@ -1451,10 +1578,14 @@ static __init int iscsi_transport_init(void) if (err) return err; - err = transport_class_register(&iscsi_connection_class); + err = transport_class_register(&iscsi_host_class); if (err) goto unregister_transport_class; + err = transport_class_register(&iscsi_connection_class); + if (err) + goto unregister_host_class; + err = transport_class_register(&iscsi_session_class); if (err) goto unregister_conn_class; @@ -1482,6 +1613,8 @@ unregister_session_class: transport_class_unregister(&iscsi_session_class); unregister_conn_class: transport_class_unregister(&iscsi_connection_class); +unregister_host_class: + transport_class_unregister(&iscsi_host_class); unregister_transport_class: class_unregister(&iscsi_transport_class); return err; @@ -1494,6 +1627,7 @@ static void __exit iscsi_transport_exit(void) netlink_unregister_notifier(&iscsi_nl_notifier); transport_class_unregister(&iscsi_connection_class); transport_class_unregister(&iscsi_session_class); + transport_class_unregister(&iscsi_host_class); class_unregister(&iscsi_transport_class); } diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h index 2c3a89b64e7..eebe2b15161 100644 --- a/include/scsi/iscsi_if.h +++ b/include/scsi/iscsi_if.h @@ -174,6 +174,7 @@ enum iscsi_param { ISCSI_PARAM_TPGT, ISCSI_PARAM_PERSISTENT_ADDRESS, ISCSI_PARAM_PERSISTENT_PORT, + ISCSI_PARAM_SESS_RECOVERY_TMO, /* pased in through bind conn using transport_fd */ ISCSI_PARAM_CONN_PORT, @@ -201,6 +202,7 @@ enum iscsi_param { #define ISCSI_TPGT (1 << ISCSI_PARAM_TPGT) #define ISCSI_PERSISTENT_ADDRESS (1 << ISCSI_PARAM_PERSISTENT_ADDRESS) #define ISCSI_PERSISTENT_PORT (1 << ISCSI_PARAM_PERSISTENT_PORT) +#define ISCSI_SESS_RECOVERY_TMO (1 << ISCSI_PARAM_SESS_RECOVERY_TMO) #define ISCSI_CONN_PORT (1 << ISCSI_PARAM_CONN_PORT) #define ISCSI_CONN_ADDRESS (1 << ISCSI_PARAM_CONN_ADDRESS) diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index 4b200645c84..9d2b99159ee 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -90,6 +90,7 @@ struct iscsi_transport { char *data, uint32_t data_size); void (*get_stats) (struct iscsi_cls_conn *conn, struct iscsi_stats *stats); + void (*session_recovery_timedout) (struct iscsi_cls_session *session); }; /* @@ -130,12 +131,20 @@ struct iscsi_cls_conn { struct iscsi_cls_session { struct list_head sess_list; /* item in session_list */ + struct list_head host_list; struct iscsi_transport *transport; /* iSCSI values used as unique id by userspace. */ char *targetname; int tpgt; + /* recovery fields */ + int recovery_tmo; + struct work_struct recovery_work; + + int target_id; + int channel; + int sid; /* session id */ void *dd_data; /* LLD private data */ struct device dev; /* sysfs transport/container device */ @@ -147,15 +156,23 @@ struct iscsi_cls_session { #define iscsi_session_to_shost(_session) \ dev_to_shost(_session->dev.parent) +struct iscsi_host { + int next_target_id; + struct list_head sessions; + struct mutex mutex; +}; + /* * session and connection functions that can be used by HW iSCSI LLDs */ extern struct iscsi_cls_session *iscsi_create_session(struct Scsi_Host *shost, - struct iscsi_transport *t); + struct iscsi_transport *t, int channel); extern int iscsi_destroy_session(struct iscsi_cls_session *session); extern struct iscsi_cls_conn *iscsi_create_conn(struct iscsi_cls_session *sess, uint32_t cid); extern int iscsi_destroy_conn(struct iscsi_cls_conn *conn); +extern void iscsi_unblock_session(struct iscsi_cls_session *session); +extern void iscsi_block_session(struct iscsi_cls_session *session); /* * session functions used by software iscsi -- cgit v1.2.3 From 7996a778ff8c717cb1a7a294475c59cc8f1e9fb8 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Thu, 6 Apr 2006 21:13:41 -0500 Subject: [SCSI] iscsi: add libiscsi There is a lot of code duplcited between iscsi_tcp and the upcoming iscsi_iser driver. This patch puts the duplicated code in a lib. There is more code to move around but this takes care of the basics. For iscsi_offload if they use the lib we will probably move some things around. For example in the queuecommand we will not assume that the LLD wants to do queue_work, but it is better to handle that later when we know for sure what iscsi_offload looks like (we could probably do this for iscsi_iser though to). Ideally I would like to get the iscsi_transports modules to a place where all they really have to do is put data on the wire, but how to do that will hopefully be more clear when we see other modules like iscsi_offload. Or maybe iscsi_offload will not use the lib and it will just be iscsi_iser and iscsi_tcp and maybe the iscsi_tcp_tgt if that is allowed in mainline. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/Makefile | 2 +- drivers/scsi/libiscsi.c | 1697 +++++++++++++++++++++++++++++++++++ drivers/scsi/scsi_transport_iscsi.c | 116 +-- include/scsi/iscsi_if.h | 3 +- include/scsi/libiscsi.h | 286 ++++++ include/scsi/scsi_transport_iscsi.h | 59 +- 6 files changed, 2045 insertions(+), 118 deletions(-) create mode 100644 drivers/scsi/libiscsi.c create mode 100644 include/scsi/libiscsi.h diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index e513c3158ad..efdff61c580 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -33,7 +33,7 @@ obj-$(CONFIG_SCSI_FC_ATTRS) += scsi_transport_fc.o obj-$(CONFIG_SCSI_ISCSI_ATTRS) += scsi_transport_iscsi.o obj-$(CONFIG_SCSI_SAS_ATTRS) += scsi_transport_sas.o -obj-$(CONFIG_ISCSI_TCP) += iscsi_tcp.o +obj-$(CONFIG_ISCSI_TCP) += libiscsi.o iscsi_tcp.o obj-$(CONFIG_SCSI_AMIGA7XX) += amiga7xx.o 53c7xx.o obj-$(CONFIG_A3000_SCSI) += a3000.o wd33c93.o obj-$(CONFIG_A2091_SCSI) += a2091.o wd33c93.o diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c new file mode 100644 index 00000000000..274a1374ab6 --- /dev/null +++ b/drivers/scsi/libiscsi.c @@ -0,0 +1,1697 @@ +/* + * iSCSI lib functions + * + * Copyright (C) 2006 Red Hat, Inc. All rights reserved. + * Copyright (C) 2004 - 2006 Mike Christie + * Copyright (C) 2004 - 2005 Dmitry Yusupov + * Copyright (C) 2004 - 2005 Alex Aizman + * maintained by open-iscsi@googlegroups.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct iscsi_session * +class_to_transport_session(struct iscsi_cls_session *cls_session) +{ + struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); + return iscsi_hostdata(shost->hostdata); +} +EXPORT_SYMBOL_GPL(class_to_transport_session); + +#define INVALID_SN_DELTA 0xffff + +int +iscsi_check_assign_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr) +{ + uint32_t max_cmdsn = be32_to_cpu(hdr->max_cmdsn); + uint32_t exp_cmdsn = be32_to_cpu(hdr->exp_cmdsn); + + if (max_cmdsn < exp_cmdsn -1 && + max_cmdsn > exp_cmdsn - INVALID_SN_DELTA) + return ISCSI_ERR_MAX_CMDSN; + if (max_cmdsn > session->max_cmdsn || + max_cmdsn < session->max_cmdsn - INVALID_SN_DELTA) + session->max_cmdsn = max_cmdsn; + if (exp_cmdsn > session->exp_cmdsn || + exp_cmdsn < session->exp_cmdsn - INVALID_SN_DELTA) + session->exp_cmdsn = exp_cmdsn; + + return 0; +} +EXPORT_SYMBOL_GPL(iscsi_check_assign_cmdsn); + +void iscsi_prep_unsolicit_data_pdu(struct iscsi_cmd_task *ctask, + struct iscsi_data *hdr, + int transport_data_cnt) +{ + struct iscsi_conn *conn = ctask->conn; + + memset(hdr, 0, sizeof(struct iscsi_data)); + hdr->ttt = cpu_to_be32(ISCSI_RESERVED_TAG); + hdr->datasn = cpu_to_be32(ctask->unsol_datasn); + ctask->unsol_datasn++; + hdr->opcode = ISCSI_OP_SCSI_DATA_OUT; + memcpy(hdr->lun, ctask->hdr->lun, sizeof(hdr->lun)); + + hdr->itt = ctask->hdr->itt; + hdr->exp_statsn = cpu_to_be32(conn->exp_statsn); + + hdr->offset = cpu_to_be32(ctask->total_length - + transport_data_cnt - + ctask->unsol_count); + + if (ctask->unsol_count > conn->max_xmit_dlength) { + hton24(hdr->dlength, conn->max_xmit_dlength); + ctask->data_count = conn->max_xmit_dlength; + hdr->flags = 0; + } else { + hton24(hdr->dlength, ctask->unsol_count); + ctask->data_count = ctask->unsol_count; + hdr->flags = ISCSI_FLAG_CMD_FINAL; + } +} +EXPORT_SYMBOL_GPL(iscsi_prep_unsolicit_data_pdu); + +/** + * iscsi_prep_scsi_cmd_pdu - prep iscsi scsi cmd pdu + * @ctask: iscsi cmd task + * + * Prep basic iSCSI PDU fields for a scsi cmd pdu. The LLD should set + * fields like dlength or final based on how much data it sends + */ +static void iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask) +{ + struct iscsi_conn *conn = ctask->conn; + struct iscsi_session *session = conn->session; + struct iscsi_cmd *hdr = ctask->hdr; + struct scsi_cmnd *sc = ctask->sc; + + hdr->opcode = ISCSI_OP_SCSI_CMD; + hdr->flags = ISCSI_ATTR_SIMPLE; + int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun); + hdr->itt = ctask->itt | (conn->id << ISCSI_CID_SHIFT) | + (session->age << ISCSI_AGE_SHIFT); + hdr->data_length = cpu_to_be32(sc->request_bufflen); + hdr->cmdsn = cpu_to_be32(session->cmdsn); + session->cmdsn++; + hdr->exp_statsn = cpu_to_be32(conn->exp_statsn); + memcpy(hdr->cdb, sc->cmnd, sc->cmd_len); + memset(&hdr->cdb[sc->cmd_len], 0, MAX_COMMAND_SIZE - sc->cmd_len); + + if (sc->sc_data_direction == DMA_TO_DEVICE) { + hdr->flags |= ISCSI_FLAG_CMD_WRITE; + /* + * Write counters: + * + * imm_count bytes to be sent right after + * SCSI PDU Header + * + * unsol_count bytes(as Data-Out) to be sent + * without R2T ack right after + * immediate data + * + * r2t_data_count bytes to be sent via R2T ack's + * + * pad_count bytes to be sent as zero-padding + */ + ctask->imm_count = 0; + ctask->unsol_count = 0; + ctask->unsol_datasn = 0; + + if (session->imm_data_en) { + if (ctask->total_length >= session->first_burst) + ctask->imm_count = min(session->first_burst, + conn->max_xmit_dlength); + else + ctask->imm_count = min(ctask->total_length, + conn->max_xmit_dlength); + hton24(ctask->hdr->dlength, ctask->imm_count); + } else + zero_data(ctask->hdr->dlength); + + if (!session->initial_r2t_en) + ctask->unsol_count = min(session->first_burst, + ctask->total_length) - ctask->imm_count; + if (!ctask->unsol_count) + /* No unsolicit Data-Out's */ + ctask->hdr->flags |= ISCSI_FLAG_CMD_FINAL; + } else { + ctask->datasn = 0; + hdr->flags |= ISCSI_FLAG_CMD_FINAL; + zero_data(hdr->dlength); + + if (sc->sc_data_direction == DMA_FROM_DEVICE) + hdr->flags |= ISCSI_FLAG_CMD_READ; + } + + conn->scsicmd_pdus_cnt++; +} +EXPORT_SYMBOL_GPL(iscsi_prep_scsi_cmd_pdu); + +/** + * iscsi_complete_command - return command back to scsi-ml + * @session: iscsi session + * @ctask: iscsi cmd task + * + * Must be called with session lock. + * This function returns the scsi command to scsi-ml and returns + * the cmd task to the pool of available cmd tasks. + */ +static void iscsi_complete_command(struct iscsi_session *session, + struct iscsi_cmd_task *ctask) +{ + struct scsi_cmnd *sc = ctask->sc; + + ctask->sc = NULL; + list_del_init(&ctask->running); + __kfifo_put(session->cmdpool.queue, (void*)&ctask, sizeof(void*)); + sc->scsi_done(sc); +} + +/** + * iscsi_cmd_rsp - SCSI Command Response processing + * @conn: iscsi connection + * @hdr: iscsi header + * @ctask: scsi command task + * @data: cmd data buffer + * @datalen: len of buffer + * + * iscsi_cmd_rsp sets up the scsi_cmnd fields based on the PDU and + * then completes the command and task. + **/ +static int iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr, + struct iscsi_cmd_task *ctask, char *data, + int datalen) +{ + int rc; + struct iscsi_cmd_rsp *rhdr = (struct iscsi_cmd_rsp *)hdr; + struct iscsi_session *session = conn->session; + struct scsi_cmnd *sc = ctask->sc; + + rc = iscsi_check_assign_cmdsn(session, (struct iscsi_nopin*)rhdr); + if (rc) { + sc->result = DID_ERROR << 16; + goto out; + } + + conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1; + + sc->result = (DID_OK << 16) | rhdr->cmd_status; + + if (rhdr->response != ISCSI_STATUS_CMD_COMPLETED) { + sc->result = DID_ERROR << 16; + goto out; + } + + if (rhdr->cmd_status == SAM_STAT_CHECK_CONDITION) { + int senselen; + + if (datalen < 2) { +invalid_datalen: + printk(KERN_ERR "Got CHECK_CONDITION but invalid " + "data buffer size of %d\n", datalen); + sc->result = DID_BAD_TARGET << 16; + goto out; + } + + senselen = (data[0] << 8) | data[1]; + if (datalen < senselen) + goto invalid_datalen; + + memcpy(sc->sense_buffer, data + 2, + min(senselen, SCSI_SENSE_BUFFERSIZE)); + debug_scsi("copied %d bytes of sense\n", + min(senselen, SCSI_SENSE_BUFFERSIZE)); + } + + if (sc->sc_data_direction == DMA_TO_DEVICE) + goto out; + + if (rhdr->flags & ISCSI_FLAG_CMD_UNDERFLOW) { + int res_count = be32_to_cpu(rhdr->residual_count); + + if (res_count > 0 && res_count <= sc->request_bufflen) + sc->resid = res_count; + else + sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status; + } else if (rhdr->flags & ISCSI_FLAG_CMD_BIDI_UNDERFLOW) + sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status; + else if (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW) + sc->resid = be32_to_cpu(rhdr->residual_count); + +out: + debug_scsi("done [sc %lx res %d itt 0x%x]\n", + (long)sc, sc->result, ctask->itt); + conn->scsirsp_pdus_cnt++; + + iscsi_complete_command(conn->session, ctask); + return rc; +} + +/** + * __iscsi_complete_pdu - complete pdu + * @conn: iscsi conn + * @hdr: iscsi header + * @data: data buffer + * @datalen: len of data buffer + * + * Completes pdu processing by freeing any resources allocated at + * queuecommand or send generic. session lock must be held and verify + * itt must have been called. + */ +int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, + char *data, int datalen) +{ + struct iscsi_session *session = conn->session; + int opcode = hdr->opcode & ISCSI_OPCODE_MASK, rc = 0; + struct iscsi_cmd_task *ctask; + struct iscsi_mgmt_task *mtask; + uint32_t itt; + + if (hdr->itt != cpu_to_be32(ISCSI_RESERVED_TAG)) + itt = hdr->itt & ISCSI_ITT_MASK; + else + itt = hdr->itt; + + if (itt < session->cmds_max) { + ctask = session->cmds[itt]; + + debug_scsi("cmdrsp [op 0x%x cid %d itt 0x%x len %d]\n", + opcode, conn->id, ctask->itt, datalen); + + switch(opcode) { + case ISCSI_OP_SCSI_CMD_RSP: + BUG_ON((void*)ctask != ctask->sc->SCp.ptr); + rc = iscsi_scsi_cmd_rsp(conn, hdr, ctask, data, + datalen); + break; + case ISCSI_OP_SCSI_DATA_IN: + BUG_ON((void*)ctask != ctask->sc->SCp.ptr); + if (hdr->flags & ISCSI_FLAG_DATA_STATUS) { + conn->scsirsp_pdus_cnt++; + iscsi_complete_command(session, ctask); + } + break; + case ISCSI_OP_R2T: + /* LLD handles this for now */ + break; + default: + rc = ISCSI_ERR_BAD_OPCODE; + break; + } + } else if (itt >= ISCSI_MGMT_ITT_OFFSET && + itt < ISCSI_MGMT_ITT_OFFSET + session->mgmtpool_max) { + mtask = session->mgmt_cmds[itt - ISCSI_MGMT_ITT_OFFSET]; + + debug_scsi("immrsp [op 0x%x cid %d itt 0x%x len %d]\n", + opcode, conn->id, mtask->itt, datalen); + + switch(opcode) { + case ISCSI_OP_LOGIN_RSP: + case ISCSI_OP_TEXT_RSP: + case ISCSI_OP_LOGOUT_RSP: + rc = iscsi_check_assign_cmdsn(session, + (struct iscsi_nopin*)hdr); + if (rc) + break; + + rc = iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen); + list_del(&mtask->running); + if (conn->login_mtask != mtask) + __kfifo_put(session->mgmtpool.queue, + (void*)&mtask, sizeof(void*)); + break; + case ISCSI_OP_SCSI_TMFUNC_RSP: + rc = iscsi_check_assign_cmdsn(session, + (struct iscsi_nopin*)hdr); + if (rc) + break; + + if (datalen) { + rc = ISCSI_ERR_PROTO; + break; + } + conn->tmfrsp_pdus_cnt++; + if (conn->tmabort_state == TMABORT_INITIAL) { + conn->tmabort_state = + ((struct iscsi_tm_rsp *)hdr)-> + response == ISCSI_TMF_RSP_COMPLETE ? + TMABORT_SUCCESS:TMABORT_FAILED; + /* unblock eh_abort() */ + wake_up(&conn->ehwait); + } + break; + case ISCSI_OP_NOOP_IN: + if (hdr->ttt != ISCSI_RESERVED_TAG) { + rc = ISCSI_ERR_PROTO; + break; + } + rc = iscsi_check_assign_cmdsn(session, + (struct iscsi_nopin*)hdr); + if (rc) + break; + conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; + + rc = iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen); + list_del(&mtask->running); + if (conn->login_mtask != mtask) + __kfifo_put(session->mgmtpool.queue, + (void*)&mtask, sizeof(void*)); + break; + default: + rc = ISCSI_ERR_BAD_OPCODE; + break; + } + } else if (itt == ISCSI_RESERVED_TAG) { + switch(opcode) { + case ISCSI_OP_NOOP_IN: + if (!datalen) { + rc = iscsi_check_assign_cmdsn(session, + (struct iscsi_nopin*)hdr); + if (!rc && hdr->ttt != ISCSI_RESERVED_TAG) + rc = iscsi_recv_pdu(conn->cls_conn, + hdr, NULL, 0); + } else + rc = ISCSI_ERR_PROTO; + break; + case ISCSI_OP_REJECT: + /* we need sth like iscsi_reject_rsp()*/ + case ISCSI_OP_ASYNC_EVENT: + /* we need sth like iscsi_async_event_rsp() */ + rc = ISCSI_ERR_BAD_OPCODE; + break; + default: + rc = ISCSI_ERR_BAD_OPCODE; + break; + } + } else + rc = ISCSI_ERR_BAD_ITT; + + return rc; +} +EXPORT_SYMBOL_GPL(__iscsi_complete_pdu); + +int iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, + char *data, int datalen) +{ + int rc; + + spin_lock(&conn->session->lock); + rc = __iscsi_complete_pdu(conn, hdr, data, datalen); + spin_unlock(&conn->session->lock); + return rc; +} +EXPORT_SYMBOL_GPL(iscsi_complete_pdu); + +/* verify itt (itt encoding: age+cid+itt) */ +int iscsi_verify_itt(struct iscsi_conn *conn, struct iscsi_hdr *hdr, + uint32_t *ret_itt) +{ + struct iscsi_session *session = conn->session; + struct iscsi_cmd_task *ctask; + uint32_t itt; + + if (hdr->itt != cpu_to_be32(ISCSI_RESERVED_TAG)) { + if ((hdr->itt & ISCSI_AGE_MASK) != + (session->age << ISCSI_AGE_SHIFT)) { + printk(KERN_ERR "iscsi_tcp: received itt %x expected " + "session age (%x)\n", hdr->itt, + session->age & ISCSI_AGE_MASK); + return ISCSI_ERR_BAD_ITT; + } + + if ((hdr->itt & ISCSI_CID_MASK) != + (conn->id << ISCSI_CID_SHIFT)) { + printk(KERN_ERR "iscsi_tcp: received itt %x, expected " + "CID (%x)\n", hdr->itt, conn->id); + return ISCSI_ERR_BAD_ITT; + } + itt = hdr->itt & ISCSI_ITT_MASK; + } else + itt = hdr->itt; + + if (itt < session->cmds_max) { + ctask = session->cmds[itt]; + + if (!ctask->sc) { + printk(KERN_INFO "iscsi_tcp: dropping ctask with " + "itt 0x%x\n", ctask->itt); + /* force drop */ + return ISCSI_ERR_NO_SCSI_CMD; + } + + if (ctask->sc->SCp.phase != session->age) { + printk(KERN_ERR "iscsi_tcp: ctask's session age %d, " + "expected %d\n", ctask->sc->SCp.phase, + session->age); + return ISCSI_ERR_SESSION_FAILED; + } + } + + *ret_itt = itt; + return 0; +} +EXPORT_SYMBOL_GPL(iscsi_verify_itt); + +void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err) +{ + struct iscsi_session *session = conn->session; + unsigned long flags; + + spin_lock_irqsave(&session->lock, flags); + if (session->conn_cnt == 1 || session->leadconn == conn) + session->state = ISCSI_STATE_FAILED; + spin_unlock_irqrestore(&session->lock, flags); + set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); + set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx); + iscsi_conn_error(conn->cls_conn, err); +} +EXPORT_SYMBOL_GPL(iscsi_conn_failure); + +/** + * iscsi_data_xmit - xmit any command into the scheduled connection + * @conn: iscsi connection + * + * Notes: + * The function can return -EAGAIN in which case the caller must + * re-schedule it again later or recover. '0' return code means + * successful xmit. + **/ +static int iscsi_data_xmit(struct iscsi_conn *conn) +{ + struct iscsi_transport *tt; + + if (unlikely(conn->suspend_tx)) { + debug_scsi("conn %d Tx suspended!\n", conn->id); + return 0; + } + tt = conn->session->tt; + + /* + * Transmit in the following order: + * + * 1) un-finished xmit (ctask or mtask) + * 2) immediate control PDUs + * 3) write data + * 4) SCSI commands + * 5) non-immediate control PDUs + * + * No need to lock around __kfifo_get as long as + * there's one producer and one consumer. + */ + + BUG_ON(conn->ctask && conn->mtask); + + if (conn->ctask) { + if (tt->xmit_cmd_task(conn, conn->ctask)) + goto again; + /* done with this in-progress ctask */ + conn->ctask = NULL; + } + if (conn->mtask) { + if (tt->xmit_mgmt_task(conn, conn->mtask)) + goto again; + /* done with this in-progress mtask */ + conn->mtask = NULL; + } + + /* process immediate first */ + if (unlikely(__kfifo_len(conn->immqueue))) { + while (__kfifo_get(conn->immqueue, (void*)&conn->mtask, + sizeof(void*))) { + list_add_tail(&conn->mtask->running, + &conn->mgmt_run_list); + if (tt->xmit_mgmt_task(conn, conn->mtask)) + goto again; + } + /* done with this mtask */ + conn->mtask = NULL; + } + + /* process command queue */ + while (__kfifo_get(conn->xmitqueue, (void*)&conn->ctask, + sizeof(void*))) { + /* + * iscsi tcp may readd the task to the xmitqueue to send + * write data + */ + if (list_empty(&conn->ctask->running)) + list_add_tail(&conn->ctask->running, &conn->run_list); + if (tt->xmit_cmd_task(conn, conn->ctask)) + goto again; + } + /* done with this ctask */ + conn->ctask = NULL; + + /* process the rest control plane PDUs, if any */ + if (unlikely(__kfifo_len(conn->mgmtqueue))) { + while (__kfifo_get(conn->mgmtqueue, (void*)&conn->mtask, + sizeof(void*))) { + list_add_tail(&conn->mtask->running, + &conn->mgmt_run_list); + if (tt->xmit_mgmt_task(conn, conn->mtask)) + goto again; + } + /* done with this mtask */ + conn->mtask = NULL; + } + + return 0; + +again: + if (unlikely(conn->suspend_tx)) + return 0; + + return -EAGAIN; +} + +static void iscsi_xmitworker(void *data) +{ + struct iscsi_conn *conn = data; + + /* + * serialize Xmit worker on a per-connection basis. + */ + mutex_lock(&conn->xmitmutex); + if (iscsi_data_xmit(conn)) + scsi_queue_work(conn->session->host, &conn->xmitwork); + mutex_unlock(&conn->xmitmutex); +} + +enum { + FAILURE_BAD_HOST = 1, + FAILURE_SESSION_FAILED, + FAILURE_SESSION_FREED, + FAILURE_WINDOW_CLOSED, + FAILURE_SESSION_TERMINATE, + FAILURE_SESSION_RECOVERY_TIMEOUT, +}; + +int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) +{ + struct Scsi_Host *host; + int reason = 0; + struct iscsi_session *session; + struct iscsi_conn *conn; + struct iscsi_cmd_task *ctask = NULL; + + sc->scsi_done = done; + sc->result = 0; + + host = sc->device->host; + session = iscsi_hostdata(host->hostdata); + + spin_lock(&session->lock); + + if (session->state != ISCSI_STATE_LOGGED_IN) { + if (session->recovery_failed) { + reason = FAILURE_SESSION_RECOVERY_TIMEOUT; + goto fault; + } else if (session->state == ISCSI_STATE_FAILED) { + reason = FAILURE_SESSION_FAILED; + goto reject; + } else if (session->state == ISCSI_STATE_TERMINATE) { + reason = FAILURE_SESSION_TERMINATE; + goto fault; + } + reason = FAILURE_SESSION_FREED; + goto fault; + } + + /* + * Check for iSCSI window and take care of CmdSN wrap-around + */ + if ((int)(session->max_cmdsn - session->cmdsn) < 0) { + reason = FAILURE_WINDOW_CLOSED; + goto reject; + } + + conn = session->leadconn; + + __kfifo_get(session->cmdpool.queue, (void*)&ctask, sizeof(void*)); + sc->SCp.phase = session->age; + sc->SCp.ptr = (char *)ctask; + + ctask->mtask = NULL; + ctask->conn = conn; + ctask->sc = sc; + INIT_LIST_HEAD(&ctask->running); + ctask->total_length = sc->request_bufflen; + iscsi_prep_scsi_cmd_pdu(ctask); + + session->tt->init_cmd_task(ctask); + + __kfifo_put(conn->xmitqueue, (void*)&ctask, sizeof(void*)); + debug_scsi( + "ctask enq [%s cid %d sc %lx itt 0x%x len %d cmdsn %d win %d]\n", + sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read", + conn->id, (long)sc, ctask->itt, sc->request_bufflen, + session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1); + spin_unlock(&session->lock); + + scsi_queue_work(host, &conn->xmitwork); + return 0; + +reject: + spin_unlock(&session->lock); + debug_scsi("cmd 0x%x rejected (%d)\n", sc->cmnd[0], reason); + return SCSI_MLQUEUE_HOST_BUSY; + +fault: + spin_unlock(&session->lock); + printk(KERN_ERR "iscsi_tcp: cmd 0x%x is not queued (%d)\n", + sc->cmnd[0], reason); + sc->result = (DID_NO_CONNECT << 16); + sc->resid = sc->request_bufflen; + sc->scsi_done(sc); + return 0; +} +EXPORT_SYMBOL_GPL(iscsi_queuecommand); + +int iscsi_change_queue_depth(struct scsi_device *sdev, int depth) +{ + if (depth > ISCSI_MAX_CMD_PER_LUN) + depth = ISCSI_MAX_CMD_PER_LUN; + scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth); + return sdev->queue_depth; +} +EXPORT_SYMBOL_GPL(iscsi_change_queue_depth); + +static int +iscsi_conn_send_generic(struct iscsi_conn *conn, struct iscsi_hdr *hdr, + char *data, uint32_t data_size) +{ + struct iscsi_session *session = conn->session; + struct iscsi_nopout *nop = (struct iscsi_nopout *)hdr; + struct iscsi_mgmt_task *mtask; + + spin_lock_bh(&session->lock); + if (session->state == ISCSI_STATE_TERMINATE) { + spin_unlock_bh(&session->lock); + return -EPERM; + } + if (hdr->opcode == (ISCSI_OP_LOGIN | ISCSI_OP_IMMEDIATE) || + hdr->opcode == (ISCSI_OP_TEXT | ISCSI_OP_IMMEDIATE)) + /* + * Login and Text are sent serially, in + * request-followed-by-response sequence. + * Same mtask can be used. Same ITT must be used. + * Note that login_mtask is preallocated at conn_create(). + */ + mtask = conn->login_mtask; + else { + BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE); + BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED); + + if (!__kfifo_get(session->mgmtpool.queue, + (void*)&mtask, sizeof(void*))) { + spin_unlock_bh(&session->lock); + return -ENOSPC; + } + } + + /* + * pre-format CmdSN and ExpStatSN for outgoing PDU. + */ + if (hdr->itt != cpu_to_be32(ISCSI_RESERVED_TAG)) { + hdr->itt = mtask->itt | (conn->id << ISCSI_CID_SHIFT) | + (session->age << ISCSI_AGE_SHIFT); + nop->cmdsn = cpu_to_be32(session->cmdsn); + if (conn->c_stage == ISCSI_CONN_STARTED && + !(hdr->opcode & ISCSI_OP_IMMEDIATE)) + session->cmdsn++; + } else + /* do not advance CmdSN */ + nop->cmdsn = cpu_to_be32(session->cmdsn); + + nop->exp_statsn = cpu_to_be32(conn->exp_statsn); + + if (data_size) { + memcpy(mtask->data, data, data_size); + mtask->data_count = data_size; + } else + mtask->data_count = 0; + + INIT_LIST_HEAD(&mtask->running); + memcpy(mtask->hdr, hdr, sizeof(struct iscsi_hdr)); + if (session->tt->init_mgmt_task) + session->tt->init_mgmt_task(conn, mtask, data, data_size); + spin_unlock_bh(&session->lock); + + debug_scsi("mgmtpdu [op 0x%x hdr->itt 0x%x datalen %d]\n", + hdr->opcode, hdr->itt, data_size); + + /* + * since send_pdu() could be called at least from two contexts, + * we need to serialize __kfifo_put, so we don't have to take + * additional lock on fast data-path + */ + if (hdr->opcode & ISCSI_OP_IMMEDIATE) + __kfifo_put(conn->immqueue, (void*)&mtask, sizeof(void*)); + else + __kfifo_put(conn->mgmtqueue, (void*)&mtask, sizeof(void*)); + + scsi_queue_work(session->host, &conn->xmitwork); + return 0; +} + +int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr, + char *data, uint32_t data_size) +{ + struct iscsi_conn *conn = cls_conn->dd_data; + int rc; + + mutex_lock(&conn->xmitmutex); + rc = iscsi_conn_send_generic(conn, hdr, data, data_size); + mutex_unlock(&conn->xmitmutex); + + return rc; +} +EXPORT_SYMBOL_GPL(iscsi_conn_send_pdu); + +void iscsi_session_recovery_timedout(struct iscsi_cls_session *cls_session) +{ + struct iscsi_session *session = class_to_transport_session(cls_session); + struct iscsi_conn *conn = session->leadconn; + + spin_lock_bh(&session->lock); + if (session->state != ISCSI_STATE_LOGGED_IN) { + session->recovery_failed = 1; + if (conn) + wake_up(&conn->ehwait); + } + spin_unlock_bh(&session->lock); +} +EXPORT_SYMBOL_GPL(iscsi_session_recovery_timedout); + +int iscsi_eh_host_reset(struct scsi_cmnd *sc) +{ + struct Scsi_Host *host = sc->device->host; + struct iscsi_session *session = iscsi_hostdata(host->hostdata); + struct iscsi_conn *conn = session->leadconn; + int fail_session = 0; + + spin_lock_bh(&session->lock); + if (session->state == ISCSI_STATE_TERMINATE) { +failed: + debug_scsi("failing host reset: session terminated " + "[CID %d age %d]", conn->id, session->age); + spin_unlock_bh(&session->lock); + return FAILED; + } + + if (sc->SCp.phase == session->age) { + debug_scsi("failing connection CID %d due to SCSI host reset", + conn->id); + fail_session = 1; + } + spin_unlock_bh(&session->lock); + + /* + * we drop the lock here but the leadconn cannot be destoyed while + * we are in the scsi eh + */ + if (fail_session) { + iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); + /* + * if userspace cannot respond then we must kick this off + * here for it + */ + iscsi_start_session_recovery(session, conn, STOP_CONN_RECOVER); + } + + debug_scsi("iscsi_eh_host_reset wait for relogin\n"); + wait_event_interruptible(conn->ehwait, + session->state == ISCSI_STATE_TERMINATE || + session->state == ISCSI_STATE_LOGGED_IN || + session->recovery_failed); + if (signal_pending(current)) + flush_signals(current); + + spin_lock_bh(&session->lock); + if (session->state == ISCSI_STATE_LOGGED_IN) + printk(KERN_INFO "host reset succeeded\n"); + else + goto failed; + spin_unlock_bh(&session->lock); + + return SUCCESS; +} +EXPORT_SYMBOL_GPL(iscsi_eh_host_reset); + +static void iscsi_tmabort_timedout(unsigned long data) +{ + struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)data; + struct iscsi_conn *conn = ctask->conn; + struct iscsi_session *session = conn->session; + + spin_lock(&session->lock); + if (conn->tmabort_state == TMABORT_INITIAL) { + conn->tmabort_state = TMABORT_TIMEDOUT; + debug_scsi("tmabort timedout [sc %p itt 0x%x]\n", + ctask->sc, ctask->itt); + /* unblock eh_abort() */ + wake_up(&conn->ehwait); + } + spin_unlock(&session->lock); +} + +/* must be called with the mutex lock */ +static int iscsi_exec_abort_task(struct scsi_cmnd *sc, + struct iscsi_cmd_task *ctask) +{ + struct iscsi_conn *conn = ctask->conn; + struct iscsi_session *session = conn->session; + struct iscsi_tm *hdr = &conn->tmhdr; + int rc; + + /* + * ctask timed out but session is OK requests must be serialized. + */ + memset(hdr, 0, sizeof(struct iscsi_tm)); + hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE; + hdr->flags = ISCSI_TM_FUNC_ABORT_TASK; + hdr->flags |= ISCSI_FLAG_CMD_FINAL; + memcpy(hdr->lun, ctask->hdr->lun, sizeof(hdr->lun)); + hdr->rtt = ctask->hdr->itt; + hdr->refcmdsn = ctask->hdr->cmdsn; + + rc = iscsi_conn_send_generic(conn, (struct iscsi_hdr *)hdr, + NULL, 0); + if (rc) { + iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); + debug_scsi("abort sent failure [itt 0x%x] %d", ctask->itt, rc); + return rc; + } + + debug_scsi("abort sent [itt 0x%x]\n", ctask->itt); + + spin_lock_bh(&session->lock); + ctask->mtask = (struct iscsi_mgmt_task *) + session->mgmt_cmds[(hdr->itt & ISCSI_ITT_MASK) - + ISCSI_MGMT_ITT_OFFSET]; + + if (conn->tmabort_state == TMABORT_INITIAL) { + conn->tmfcmd_pdus_cnt++; + conn->tmabort_timer.expires = 10*HZ + jiffies; + conn->tmabort_timer.function = iscsi_tmabort_timedout; + conn->tmabort_timer.data = (unsigned long)ctask; + add_timer(&conn->tmabort_timer); + debug_scsi("abort set timeout [itt 0x%x]", ctask->itt); + } + spin_unlock_bh(&session->lock); + mutex_unlock(&conn->xmitmutex); + + /* + * block eh thread until: + * + * 1) abort response + * 2) abort timeout + * 3) session is terminated or restarted or userspace has + * given up on recovery + */ + wait_event_interruptible(conn->ehwait, + sc->SCp.phase != session->age || + session->state != ISCSI_STATE_LOGGED_IN || + conn->tmabort_state != TMABORT_INITIAL || + session->recovery_failed); + if (signal_pending(current)) + flush_signals(current); + del_timer_sync(&conn->tmabort_timer); + + mutex_lock(&conn->xmitmutex); + return 0; +} + +/* + * xmit mutex and session lock must be held + */ +#define iscsi_remove_task(tasktype) \ +static struct iscsi_##tasktype * \ +iscsi_remove_##tasktype(struct kfifo *fifo, uint32_t itt) \ +{ \ + int i, nr_tasks = __kfifo_len(fifo) / sizeof(void*); \ + struct iscsi_##tasktype *task; \ + \ + debug_scsi("searching %d tasks\n", nr_tasks); \ + \ + for (i = 0; i < nr_tasks; i++) { \ + __kfifo_get(fifo, (void*)&task, sizeof(void*)); \ + debug_scsi("check task %u\n", task->itt); \ + \ + if (task->itt == itt) { \ + debug_scsi("matched task\n"); \ + break; \ + } \ + \ + __kfifo_put(fifo, (void*)&task, sizeof(void*)); \ + } \ + return NULL; \ +} + +iscsi_remove_task(mgmt_task); +iscsi_remove_task(cmd_task); + +static int iscsi_ctask_mtask_cleanup(struct iscsi_cmd_task *ctask) +{ + struct iscsi_conn *conn = ctask->conn; + struct iscsi_session *session = conn->session; + + if (!ctask->mtask) + return -EINVAL; + + if (!iscsi_remove_mgmt_task(conn->immqueue, ctask->mtask->itt)) + list_del(&ctask->mtask->running); + __kfifo_put(session->mgmtpool.queue, (void*)&ctask->mtask, + sizeof(void*)); + ctask->mtask = NULL; + return 0; +} + +/* + * session lock and xmitmutex must be held + */ +static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, + int err) +{ + struct scsi_cmnd *sc; + + conn->session->tt->cleanup_cmd_task(conn, ctask); + iscsi_ctask_mtask_cleanup(ctask); + + sc = ctask->sc; + if (!sc) + return; + sc->result = err; + sc->resid = sc->request_bufflen; + iscsi_complete_command(conn->session, ctask); +} + +int iscsi_eh_abort(struct scsi_cmnd *sc) +{ + struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)sc->SCp.ptr; + struct iscsi_conn *conn = ctask->conn; + struct iscsi_session *session = conn->session; + struct iscsi_cmd_task *pending_ctask; + int rc; + + conn->eh_abort_cnt++; + debug_scsi("aborting [sc %p itt 0x%x]\n", sc, ctask->itt); + + mutex_lock(&conn->xmitmutex); + spin_lock_bh(&session->lock); + + /* + * If we are not logged in or we have started a new session + * then let the host reset code handle this + */ + if (session->state != ISCSI_STATE_LOGGED_IN || + sc->SCp.phase != session->age) + goto failed; + + /* ctask completed before time out */ + if (!ctask->sc) + goto success; + + /* what should we do here ? */ + if (conn->ctask == ctask) { + printk(KERN_INFO "sc %p itt 0x%x partially sent. Failing " + "abort\n", sc, ctask->itt); + goto failed; + } + + /* check for the easy pending cmd abort */ + pending_ctask = iscsi_remove_cmd_task(conn->xmitqueue, ctask->itt); + if (pending_ctask) { + /* iscsi_tcp queues write transfers on the xmitqueue */ + if (list_empty(&pending_ctask->running)) { + debug_scsi("found pending task\n"); + goto success; + } else + __kfifo_put(conn->xmitqueue, (void*)&pending_ctask, + sizeof(void*)); + } + + conn->tmabort_state = TMABORT_INITIAL; + + spin_unlock_bh(&session->lock); + rc = iscsi_exec_abort_task(sc, ctask); + spin_lock_bh(&session->lock); + + iscsi_ctask_mtask_cleanup(ctask); + if (rc || sc->SCp.phase != session->age || + session->state != ISCSI_STATE_LOGGED_IN) + goto failed; + + /* ctask completed before tmf abort response */ + if (!ctask->sc) { + debug_scsi("sc completed while abort in progress\n"); + goto success; + } + + if (conn->tmabort_state != TMABORT_SUCCESS) { + spin_unlock_bh(&session->lock); + iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); + spin_lock_bh(&session->lock); + goto failed; + } + +success: + debug_scsi("abort success [sc %lx itt 0x%x]\n", (long)sc, ctask->itt); + spin_unlock_bh(&session->lock); + + /* + * clean up task if aborted. we have the xmitmutex so grab + * the recv lock as a writer + */ + write_lock_bh(conn->recv_lock); + spin_lock(&session->lock); + fail_command(conn, ctask, DID_ABORT << 16); + spin_unlock(&session->lock); + write_unlock_bh(conn->recv_lock); + + mutex_unlock(&conn->xmitmutex); + return SUCCESS; + +failed: + spin_unlock_bh(&session->lock); + mutex_unlock(&conn->xmitmutex); + + debug_scsi("abort failed [sc %lx itt 0x%x]\n", (long)sc, ctask->itt); + return FAILED; +} +EXPORT_SYMBOL_GPL(iscsi_eh_abort); + +int +iscsi_pool_init(struct iscsi_queue *q, int max, void ***items, int item_size) +{ + int i; + + *items = kmalloc(max * sizeof(void*), GFP_KERNEL); + if (*items == NULL) + return -ENOMEM; + + q->max = max; + q->pool = kmalloc(max * sizeof(void*), GFP_KERNEL); + if (q->pool == NULL) { + kfree(*items); + return -ENOMEM; + } + + q->queue = kfifo_init((void*)q->pool, max * sizeof(void*), + GFP_KERNEL, NULL); + if (q->queue == ERR_PTR(-ENOMEM)) { + kfree(q->pool); + kfree(*items); + return -ENOMEM; + } + + for (i = 0; i < max; i++) { + q->pool[i] = kmalloc(item_size, GFP_KERNEL); + if (q->pool[i] == NULL) { + int j; + + for (j = 0; j < i; j++) + kfree(q->pool[j]); + + kfifo_free(q->queue); + kfree(q->pool); + kfree(*items); + return -ENOMEM; + } + memset(q->pool[i], 0, item_size); + (*items)[i] = q->pool[i]; + __kfifo_put(q->queue, (void*)&q->pool[i], sizeof(void*)); + } + return 0; +} +EXPORT_SYMBOL_GPL(iscsi_pool_init); + +void iscsi_pool_free(struct iscsi_queue *q, void **items) +{ + int i; + + for (i = 0; i < q->max; i++) + kfree(items[i]); + kfree(q->pool); + kfree(items); +} +EXPORT_SYMBOL_GPL(iscsi_pool_free); + +/* + * iSCSI Session's hostdata organization: + * + * *------------------* <== hostdata_session(host->hostdata) + * | ptr to class sess| + * |------------------| <== iscsi_hostdata(host->hostdata) + * | iscsi_session | + * *------------------* + */ + +#define hostdata_privsize(_sz) (sizeof(unsigned long) + _sz + \ + _sz % sizeof(unsigned long)) + +#define hostdata_session(_hostdata) (iscsi_ptr(*(unsigned long *)_hostdata)) + +/** + * iscsi_session_setup - create iscsi cls session and host and session + * @scsit: scsi transport template + * @iscsit: iscsi transport template + * @initial_cmdsn: initial CmdSN + * @hostno: host no allocated + * + * This can be used by software iscsi_transports that allocate + * a session per scsi host. + **/ +struct iscsi_cls_session * +iscsi_session_setup(struct iscsi_transport *iscsit, + struct scsi_transport_template *scsit, + int cmd_task_size, int mgmt_task_size, + uint32_t initial_cmdsn, uint32_t *hostno) +{ + struct Scsi_Host *shost; + struct iscsi_session *session; + struct iscsi_cls_session *cls_session; + int cmd_i; + + shost = scsi_host_alloc(iscsit->host_template, + hostdata_privsize(sizeof(*session))); + if (!shost) + return NULL; + + shost->max_id = 1; + shost->max_channel = 0; + shost->max_lun = iscsit->max_lun; + shost->max_cmd_len = iscsit->max_cmd_len; + shost->transportt = scsit; + shost->transportt->create_work_queue = 1; + *hostno = shost->host_no; + + session = iscsi_hostdata(shost->hostdata); + memset(session, 0, sizeof(struct iscsi_session)); + session->host = shost; + session->state = ISCSI_STATE_FREE; + session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX; + session->cmds_max = ISCSI_XMIT_CMDS_MAX; + session->cmdsn = initial_cmdsn; + session->exp_cmdsn = initial_cmdsn + 1; + session->max_cmdsn = initial_cmdsn + 1; + session->max_r2t = 1; + session->tt = iscsit; + + /* initialize SCSI PDU commands pool */ + if (iscsi_pool_init(&session->cmdpool, session->cmds_max, + (void***)&session->cmds, + cmd_task_size + sizeof(struct iscsi_cmd_task))) + goto cmdpool_alloc_fail; + + /* pre-format cmds pool with ITT */ + for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) { + struct iscsi_cmd_task *ctask = session->cmds[cmd_i]; + + if (cmd_task_size) + ctask->dd_data = &ctask[1]; + ctask->itt = cmd_i; + } + + spin_lock_init(&session->lock); + INIT_LIST_HEAD(&session->connections); + + /* initialize immediate command pool */ + if (iscsi_pool_init(&session->mgmtpool, session->mgmtpool_max, + (void***)&session->mgmt_cmds, + mgmt_task_size + sizeof(struct iscsi_mgmt_task))) + goto mgmtpool_alloc_fail; + + + /* pre-format immediate cmds pool with ITT */ + for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) { + struct iscsi_mgmt_task *mtask = session->mgmt_cmds[cmd_i]; + + if (mgmt_task_size) + mtask->dd_data = &mtask[1]; + mtask->itt = ISCSI_MGMT_ITT_OFFSET + cmd_i; + mtask->data = kmalloc(DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH, + GFP_KERNEL); + if (!mtask->data) { + int j; + + for (j = 0; j < cmd_i; j++) + kfree(session->mgmt_cmds[j]->data); + goto immdata_alloc_fail; + } + } + + if (scsi_add_host(shost, NULL)) + goto add_host_fail; + + cls_session = iscsi_create_session(shost, iscsit, 0); + if (!cls_session) + goto cls_session_fail; + *(unsigned long*)shost->hostdata = (unsigned long)cls_session; + + return cls_session; + +cls_session_fail: + scsi_remove_host(shost); +add_host_fail: + for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) + kfree(session->mgmt_cmds[cmd_i]->data); +immdata_alloc_fail: + iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds); +mgmtpool_alloc_fail: + iscsi_pool_free(&session->cmdpool, (void**)session->cmds); +cmdpool_alloc_fail: + scsi_host_put(shost); + return NULL; +} +EXPORT_SYMBOL_GPL(iscsi_session_setup); + +/** + * iscsi_session_teardown - destroy session, host, and cls_session + * shost: scsi host + * + * This can be used by software iscsi_transports that allocate + * a session per scsi host. + **/ +void iscsi_session_teardown(struct iscsi_cls_session *cls_session) +{ + struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); + struct iscsi_session *session = iscsi_hostdata(shost->hostdata); + int cmd_i; + + scsi_remove_host(shost); + + for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) + kfree(session->mgmt_cmds[cmd_i]->data); + + iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds); + iscsi_pool_free(&session->cmdpool, (void**)session->cmds); + + iscsi_destroy_session(cls_session); + scsi_host_put(shost); +} +EXPORT_SYMBOL_GPL(iscsi_session_teardown); + +/** + * iscsi_conn_setup - create iscsi_cls_conn and iscsi_conn + * @cls_session: iscsi_cls_session + * @conn_idx: cid + **/ +struct iscsi_cls_conn * +iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx) +{ + struct iscsi_session *session = class_to_transport_session(cls_session); + struct iscsi_conn *conn; + struct iscsi_cls_conn *cls_conn; + + cls_conn = iscsi_create_conn(cls_session, conn_idx); + if (!cls_conn) + return NULL; + conn = cls_conn->dd_data; + memset(conn, 0, sizeof(*conn)); + + conn->session = session; + conn->cls_conn = cls_conn; + conn->c_stage = ISCSI_CONN_INITIAL_STAGE; + conn->id = conn_idx; + conn->exp_statsn = 0; + conn->tmabort_state = TMABORT_INITIAL; + INIT_LIST_HEAD(&conn->run_list); + INIT_LIST_HEAD(&conn->mgmt_run_list); + + /* initialize general xmit PDU commands queue */ + conn->xmitqueue = kfifo_alloc(session->cmds_max * sizeof(void*), + GFP_KERNEL, NULL); + if (conn->xmitqueue == ERR_PTR(-ENOMEM)) + goto xmitqueue_alloc_fail; + + /* initialize general immediate & non-immediate PDU commands queue */ + conn->immqueue = kfifo_alloc(session->mgmtpool_max * sizeof(void*), + GFP_KERNEL, NULL); + if (conn->immqueue == ERR_PTR(-ENOMEM)) + goto immqueue_alloc_fail; + + conn->mgmtqueue = kfifo_alloc(session->mgmtpool_max * sizeof(void*), + GFP_KERNEL, NULL); + if (conn->mgmtqueue == ERR_PTR(-ENOMEM)) + goto mgmtqueue_alloc_fail; + + INIT_WORK(&conn->xmitwork, iscsi_xmitworker, conn); + + /* allocate login_mtask used for the login/text sequences */ + spin_lock_bh(&session->lock); + if (!__kfifo_get(session->mgmtpool.queue, + (void*)&conn->login_mtask, + sizeof(void*))) { + spin_unlock_bh(&session->lock); + goto login_mtask_alloc_fail; + } + spin_unlock_bh(&session->lock); + + init_timer(&conn->tmabort_timer); + mutex_init(&conn->xmitmutex); + init_waitqueue_head(&conn->ehwait); + + return cls_conn; + +login_mtask_alloc_fail: + kfifo_free(conn->mgmtqueue); +mgmtqueue_alloc_fail: + kfifo_free(conn->immqueue); +immqueue_alloc_fail: + kfifo_free(conn->xmitqueue); +xmitqueue_alloc_fail: + iscsi_destroy_conn(cls_conn); + return NULL; +} +EXPORT_SYMBOL_GPL(iscsi_conn_setup); + +/** + * iscsi_conn_teardown - teardown iscsi connection + * cls_conn: iscsi class connection + * + * TODO: we may need to make this into a two step process + * like scsi-mls remove + put host + */ +void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) +{ + struct iscsi_conn *conn = cls_conn->dd_data; + struct iscsi_session *session = conn->session; + unsigned long flags; + + mutex_lock(&conn->xmitmutex); + set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); + if (conn->c_stage == ISCSI_CONN_INITIAL_STAGE) { + if (session->tt->suspend_conn_recv) + session->tt->suspend_conn_recv(conn); + + session->tt->terminate_conn(conn); + } + + spin_lock_bh(&session->lock); + conn->c_stage = ISCSI_CONN_CLEANUP_WAIT; + if (session->leadconn == conn) { + /* + * leading connection? then give up on recovery. + */ + session->state = ISCSI_STATE_TERMINATE; + wake_up(&conn->ehwait); + } + spin_unlock_bh(&session->lock); + + mutex_unlock(&conn->xmitmutex); + + /* + * Block until all in-progress commands for this connection + * time out or fail. + */ + for (;;) { + spin_lock_irqsave(session->host->host_lock, flags); + if (!session->host->host_busy) { /* OK for ERL == 0 */ + spin_unlock_irqrestore(session->host->host_lock, flags); + break; + } + spin_unlock_irqrestore(session->host->host_lock, flags); + msleep_interruptible(500); + printk("conn_destroy(): host_busy %d host_failed %d\n", + session->host->host_busy, session->host->host_failed); + /* + * force eh_abort() to unblock + */ + wake_up(&conn->ehwait); + } + + spin_lock_bh(&session->lock); + __kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask, + sizeof(void*)); + list_del(&conn->item); + if (list_empty(&session->connections)) + session->leadconn = NULL; + if (session->leadconn && session->leadconn == conn) + session->leadconn = container_of(session->connections.next, + struct iscsi_conn, item); + + if (session->leadconn == NULL) + /* no connections exits.. reset sequencing */ + session->cmdsn = session->max_cmdsn = session->exp_cmdsn = 1; + spin_unlock_bh(&session->lock); + + kfifo_free(conn->xmitqueue); + kfifo_free(conn->immqueue); + kfifo_free(conn->mgmtqueue); + + iscsi_destroy_conn(cls_conn); +} +EXPORT_SYMBOL_GPL(iscsi_conn_teardown); + +int iscsi_conn_start(struct iscsi_cls_conn *cls_conn) +{ + struct iscsi_conn *conn = cls_conn->dd_data; + struct iscsi_session *session = conn->session; + + if (session == NULL) { + printk(KERN_ERR "iscsi: can't start unbound connection\n"); + return -EPERM; + } + + spin_lock_bh(&session->lock); + conn->c_stage = ISCSI_CONN_STARTED; + session->state = ISCSI_STATE_LOGGED_IN; + + switch(conn->stop_stage) { + case STOP_CONN_RECOVER: + /* + * unblock eh_abort() if it is blocked. re-try all + * commands after successful recovery + */ + session->conn_cnt++; + conn->stop_stage = 0; + conn->tmabort_state = TMABORT_INITIAL; + session->age++; + session->recovery_failed = 0; + spin_unlock_bh(&session->lock); + + iscsi_unblock_session(session_to_cls(session)); + wake_up(&conn->ehwait); + return 0; + case STOP_CONN_TERM: + session->conn_cnt++; + conn->stop_stage = 0; + break; + case STOP_CONN_SUSPEND: + conn->stop_stage = 0; + clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx); + clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); + break; + default: + break; + } + spin_unlock_bh(&session->lock); + + return 0; +} +EXPORT_SYMBOL_GPL(iscsi_conn_start); + +static void +flush_control_queues(struct iscsi_session *session, struct iscsi_conn *conn) +{ + struct iscsi_mgmt_task *mtask, *tmp; + + /* handle pending */ + while (__kfifo_get(conn->immqueue, (void*)&mtask, sizeof(void*)) || + __kfifo_get(conn->mgmtqueue, (void*)&mtask, sizeof(void*))) { + if (mtask == conn->login_mtask) + continue; + debug_scsi("flushing pending mgmt task itt 0x%x\n", mtask->itt); + __kfifo_put(session->mgmtpool.queue, (void*)&mtask, + sizeof(void*)); + } + + /* handle running */ + list_for_each_entry_safe(mtask, tmp, &conn->mgmt_run_list, running) { + debug_scsi("flushing running mgmt task itt 0x%x\n", mtask->itt); + if (mtask == conn->login_mtask) + continue; + list_del(&mtask->running); + __kfifo_put(session->mgmtpool.queue, (void*)&conn->mtask, + sizeof(void*)); + } + + conn->mtask = NULL; +} + +/* Fail commands. Mutex and session lock held and recv side suspended */ +static void fail_all_commands(struct iscsi_conn *conn) +{ + struct iscsi_cmd_task *ctask, *tmp; + + /* flush pending */ + while (__kfifo_get(conn->xmitqueue, (void*)&ctask, sizeof(void*))) { + debug_scsi("failing pending sc %p itt 0x%x\n", ctask->sc, + ctask->itt); + fail_command(conn, ctask, DID_BUS_BUSY << 16); + } + + /* fail all other running */ + list_for_each_entry_safe(ctask, tmp, &conn->run_list, running) { + debug_scsi("failing in progress sc %p itt 0x%x\n", + ctask->sc, ctask->itt); + fail_command(conn, ctask, DID_BUS_BUSY << 16); + } + + conn->ctask = NULL; +} + +void iscsi_start_session_recovery(struct iscsi_session *session, + struct iscsi_conn *conn, int flag) +{ + spin_lock_bh(&session->lock); + if (conn->stop_stage == STOP_CONN_RECOVER || + conn->stop_stage == STOP_CONN_TERM) { + spin_unlock_bh(&session->lock); + return; + } + conn->stop_stage = flag; + spin_unlock_bh(&session->lock); + + if (session->tt->suspend_conn_recv) + session->tt->suspend_conn_recv(conn); + + mutex_lock(&conn->xmitmutex); + spin_lock_bh(&session->lock); + conn->c_stage = ISCSI_CONN_STOPPED; + set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); + + session->conn_cnt--; + if (session->conn_cnt == 0 || session->leadconn == conn) + session->state = ISCSI_STATE_FAILED; + + spin_unlock_bh(&session->lock); + + session->tt->terminate_conn(conn); + /* + * flush queues. + */ + spin_lock_bh(&session->lock); + fail_all_commands(conn); + flush_control_queues(session, conn); + spin_unlock_bh(&session->lock); + + /* + * for connection level recovery we should not calculate + * header digest. conn->hdr_size used for optimization + * in hdr_extract() and will be re-negotiated at + * set_param() time. + */ + if (flag == STOP_CONN_RECOVER) { + conn->hdrdgst_en = 0; + conn->datadgst_en = 0; + + if (session->state == ISCSI_STATE_FAILED) + iscsi_block_session(session_to_cls(session)); + } + mutex_unlock(&conn->xmitmutex); +} +EXPORT_SYMBOL_GPL(iscsi_start_session_recovery); + +void iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) +{ + struct iscsi_conn *conn = cls_conn->dd_data; + struct iscsi_session *session = conn->session; + + switch (flag) { + case STOP_CONN_RECOVER: + case STOP_CONN_TERM: + iscsi_start_session_recovery(session, conn, flag); + return; + case STOP_CONN_SUSPEND: + if (session->tt->suspend_conn_recv) + session->tt->suspend_conn_recv(conn); + + mutex_lock(&conn->xmitmutex); + spin_lock_bh(&session->lock); + + conn->stop_stage = flag; + conn->c_stage = ISCSI_CONN_STOPPED; + set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); + + spin_unlock_bh(&session->lock); + mutex_unlock(&conn->xmitmutex); + break; + default: + printk(KERN_ERR "invalid stop flag %d\n", flag); + } +} +EXPORT_SYMBOL_GPL(iscsi_conn_stop); + +int iscsi_conn_bind(struct iscsi_cls_session *cls_session, + struct iscsi_cls_conn *cls_conn, int is_leading) +{ + struct iscsi_session *session = class_to_transport_session(cls_session); + struct iscsi_conn *tmp = ERR_PTR(-EEXIST), *conn = cls_conn->dd_data; + + /* lookup for existing connection */ + spin_lock_bh(&session->lock); + list_for_each_entry(tmp, &session->connections, item) { + if (tmp == conn) { + if (conn->c_stage != ISCSI_CONN_STOPPED || + conn->stop_stage == STOP_CONN_TERM) { + printk(KERN_ERR "iscsi_tcp: can't bind " + "non-stopped connection (%d:%d)\n", + conn->c_stage, conn->stop_stage); + spin_unlock_bh(&session->lock); + return -EIO; + } + break; + } + } + if (tmp != conn) { + /* bind new iSCSI connection to session */ + conn->session = session; + list_add(&conn->item, &session->connections); + } + spin_unlock_bh(&session->lock); + + if (is_leading) + session->leadconn = conn; + + /* + * Unblock xmitworker(), Login Phase will pass through. + */ + clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx); + clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); + return 0; +} +EXPORT_SYMBOL_GPL(iscsi_conn_bind); + +MODULE_AUTHOR("Mike Christie"); +MODULE_DESCRIPTION("iSCSI library functions"); +MODULE_LICENSE("GPL"); diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index e2b67e34d92..bc9071d2d21 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -471,106 +471,6 @@ int iscsi_destroy_conn(struct iscsi_cls_conn *conn) EXPORT_SYMBOL_GPL(iscsi_destroy_conn); -/* - * These functions are used only by software iscsi_transports - * which do not allocate and more their scsi_hosts since this - * is initiated from userspace. - */ - -/* - * iSCSI Session's hostdata organization: - * - * *------------------* <== hostdata_session(host->hostdata) - * | ptr to class sess| - * |------------------| <== iscsi_hostdata(host->hostdata) - * | transport's data | - * *------------------* - */ - -#define hostdata_privsize(_t) (sizeof(unsigned long) + _t->hostdata_size + \ - _t->hostdata_size % sizeof(unsigned long)) - -#define hostdata_session(_hostdata) (iscsi_ptr(*(unsigned long *)_hostdata)) - -/** - * iscsi_transport_create_session - create iscsi cls session and host - * scsit: scsi transport template - * transport: iscsi transport template - * - * This can be used by software iscsi_transports that allocate - * a session per scsi host. - **/ -struct Scsi_Host * -iscsi_transport_create_session(struct scsi_transport_template *scsit, - struct iscsi_transport *transport) -{ - struct iscsi_cls_session *session; - struct Scsi_Host *shost; - unsigned long flags; - - shost = scsi_host_alloc(transport->host_template, - hostdata_privsize(transport)); - if (!shost) { - printk(KERN_ERR "iscsi: can not allocate SCSI host for " - "session\n"); - return NULL; - } - - shost->max_id = 1; - shost->max_channel = 0; - shost->max_lun = transport->max_lun; - shost->max_cmd_len = transport->max_cmd_len; - shost->transportt = scsit; - shost->transportt->create_work_queue = 1; - - if (scsi_add_host(shost, NULL)) - goto free_host; - - session = iscsi_create_session(shost, transport, 0); - if (!session) - goto remove_host; - - *(unsigned long*)shost->hostdata = (unsigned long)session; - spin_lock_irqsave(&sesslock, flags); - list_add(&session->sess_list, &sesslist); - spin_unlock_irqrestore(&sesslock, flags); - return shost; - -remove_host: - scsi_remove_host(shost); -free_host: - scsi_host_put(shost); - return NULL; -} - -EXPORT_SYMBOL_GPL(iscsi_transport_create_session); - -/** - * iscsi_transport_destroy_session - destroy session and scsi host - * shost: scsi host - * - * This can be used by software iscsi_transports that allocate - * a session per scsi host. - **/ -int iscsi_transport_destroy_session(struct Scsi_Host *shost) -{ - struct iscsi_cls_session *session; - unsigned long flags; - - session = hostdata_session(shost->hostdata); - spin_lock_irqsave(&sesslock, flags); - list_del(&session->sess_list); - spin_unlock_irqrestore(&sesslock, flags); - iscsi_destroy_session(session); - - scsi_remove_host(shost); - /* ref from host alloc */ - scsi_host_put(shost); - return 0; -} - -EXPORT_SYMBOL_GPL(iscsi_transport_destroy_session); - /* * iscsi interface functions */ @@ -857,14 +757,19 @@ iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev) { struct iscsi_transport *transport = priv->iscsi_transport; struct iscsi_cls_session *session; + unsigned long flags; uint32_t hostno; - session = transport->create_session(&priv->t, + session = transport->create_session(transport, &priv->t, ev->u.c_session.initial_cmdsn, &hostno); if (!session) return -ENOMEM; + spin_lock_irqsave(&sesslock, flags); + list_add(&session->sess_list, &sesslist); + spin_unlock_irqrestore(&sesslock, flags); + ev->r.c_session_ret.host_no = hostno; ev->r.c_session_ret.sid = session->sid; return 0; @@ -1032,6 +937,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) struct iscsi_internal *priv; struct iscsi_cls_session *session; struct iscsi_cls_conn *conn; + unsigned long flags; priv = iscsi_if_transport_lookup(iscsi_ptr(ev->transport_handle)); if (!priv) @@ -1047,9 +953,13 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) break; case ISCSI_UEVENT_DESTROY_SESSION: session = iscsi_session_lookup(ev->u.d_session.sid); - if (session) + if (session) { + spin_lock_irqsave(&sesslock, flags); + list_del(&session->sess_list); + spin_unlock_irqrestore(&sesslock, flags); + transport->destroy_session(session); - else + } else err = -EINVAL; break; case ISCSI_UEVENT_CREATE_CONN: diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h index eebe2b15161..47524c726ee 100644 --- a/include/scsi/iscsi_if.h +++ b/include/scsi/iscsi_if.h @@ -148,7 +148,8 @@ enum iscsi_err { ISCSI_ERR_SESSION_FAILED = ISCSI_ERR_BASE + 13, ISCSI_ERR_HDR_DGST = ISCSI_ERR_BASE + 14, ISCSI_ERR_DATA_DGST = ISCSI_ERR_BASE + 15, - ISCSI_ERR_PARAM_NOT_FOUND = ISCSI_ERR_BASE + 16 + ISCSI_ERR_PARAM_NOT_FOUND = ISCSI_ERR_BASE + 16, + ISCSI_ERR_NO_SCSI_CMD = ISCSI_ERR_BASE + 17, }; /* diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h new file mode 100644 index 00000000000..830700a4ed6 --- /dev/null +++ b/include/scsi/libiscsi.h @@ -0,0 +1,286 @@ +/* + * iSCSI lib definitions + * + * Copyright (C) 2006 Red Hat, Inc. All rights reserved. + * Copyright (C) 2004 - 2006 Mike Christie + * Copyright (C) 2004 - 2005 Dmitry Yusupov + * Copyright (C) 2004 - 2005 Alex Aizman + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +#ifndef LIBISCSI_H +#define LIBISCSI_H + +#include +#include +#include +#include + +struct scsi_transport_template; +struct scsi_device; +struct Scsi_Host; +struct scsi_cmnd; +struct socket; +struct iscsi_transport; +struct iscsi_cls_session; +struct iscsi_cls_conn; +struct iscsi_session; +struct iscsi_nopin; + +/* #define DEBUG_SCSI */ +#ifdef DEBUG_SCSI +#define debug_scsi(fmt...) printk(KERN_INFO "scsi: " fmt) +#else +#define debug_scsi(fmt...) +#endif + +#define ISCSI_XMIT_CMDS_MAX 128 /* must be power of 2 */ +#define ISCSI_MGMT_CMDS_MAX 32 /* must be power of 2 */ +#define ISCSI_CONN_MAX 1 + +#define ISCSI_MGMT_ITT_OFFSET 0xa00 + +#define ISCSI_DEF_CMD_PER_LUN 32 +#define ISCSI_MAX_CMD_PER_LUN 128 + +/* Task Mgmt states */ +#define TMABORT_INITIAL 0x0 +#define TMABORT_SUCCESS 0x1 +#define TMABORT_FAILED 0x2 +#define TMABORT_TIMEDOUT 0x3 + +/* Connection suspend "bit" */ +#define ISCSI_SUSPEND_BIT 1 + +#define ISCSI_ITT_MASK (0xfff) +#define ISCSI_CID_SHIFT 12 +#define ISCSI_CID_MASK (0xffff << ISCSI_CID_SHIFT) +#define ISCSI_AGE_SHIFT 28 +#define ISCSI_AGE_MASK (0xf << ISCSI_AGE_SHIFT) + +struct iscsi_mgmt_task { + /* + * Becuae LLDs allocate their hdr differently, this is a pointer to + * that storage. It must be setup at session creation time. + */ + struct iscsi_hdr *hdr; + char *data; /* mgmt payload */ + int data_count; /* counts data to be sent */ + uint32_t itt; /* this ITT */ + void *dd_data; /* driver/transport data */ + struct list_head running; +}; + +struct iscsi_cmd_task { + /* + * Becuae LLDs allocate their hdr differently, this is a pointer to + * that storage. It must be setup at session creation time. + */ + struct iscsi_cmd *hdr; + int itt; /* this ITT */ + int datasn; /* DataSN */ + + uint32_t unsol_datasn; + int imm_count; /* imm-data (bytes) */ + int unsol_count; /* unsolicited (bytes)*/ + int data_count; /* remaining Data-Out */ + struct scsi_cmnd *sc; /* associated SCSI cmd*/ + int total_length; + struct iscsi_conn *conn; /* used connection */ + struct iscsi_mgmt_task *mtask; /* tmf mtask in progr */ + + struct list_head running; /* running cmd list */ + void *dd_data; /* driver/transport data */ +}; + +struct iscsi_conn { + struct iscsi_cls_conn *cls_conn; /* ptr to class connection */ + void *dd_data; /* iscsi_transport data */ + struct iscsi_session *session; /* parent session */ + /* + * LLDs should set this lock. It protects the transport recv + * code + */ + rwlock_t *recv_lock; + /* + * conn_stop() flag: stop to recover, stop to terminate + */ + int stop_stage; + + /* iSCSI connection-wide sequencing */ + uint32_t exp_statsn; + + /* control data */ + int id; /* CID */ + struct list_head item; /* maintains list of conns */ + int c_stage; /* connection state */ + struct iscsi_mgmt_task *login_mtask; /* mtask used for login/text */ + struct iscsi_mgmt_task *mtask; /* xmit mtask in progress */ + struct iscsi_cmd_task *ctask; /* xmit ctask in progress */ + + /* xmit */ + struct kfifo *immqueue; /* immediate xmit queue */ + struct kfifo *mgmtqueue; /* mgmt (control) xmit queue */ + struct list_head mgmt_run_list; /* list of control tasks */ + struct kfifo *xmitqueue; /* data-path cmd queue */ + struct list_head run_list; /* list of cmds in progress */ + struct work_struct xmitwork; /* per-conn. xmit workqueue */ + /* + * serializes connection xmit, access to kfifos: + * xmitqueue, immqueue, mgmtqueue + */ + struct mutex xmitmutex; + + unsigned long suspend_tx; /* suspend Tx */ + unsigned long suspend_rx; /* suspend Rx */ + + /* abort */ + wait_queue_head_t ehwait; /* used in eh_abort() */ + struct iscsi_tm tmhdr; + struct timer_list tmabort_timer; + int tmabort_state; /* see TMABORT_INITIAL, etc.*/ + + /* negotiated params */ + int max_recv_dlength; /* initiator_max_recv_dsl*/ + int max_xmit_dlength; /* target_max_recv_dsl */ + int hdrdgst_en; + int datadgst_en; + + /* MIB-statistics */ + uint64_t txdata_octets; + uint64_t rxdata_octets; + uint32_t scsicmd_pdus_cnt; + uint32_t dataout_pdus_cnt; + uint32_t scsirsp_pdus_cnt; + uint32_t datain_pdus_cnt; + uint32_t r2t_pdus_cnt; + uint32_t tmfcmd_pdus_cnt; + int32_t tmfrsp_pdus_cnt; + + /* custom statistics */ + uint32_t eh_abort_cnt; +}; + +struct iscsi_queue { + struct kfifo *queue; /* FIFO Queue */ + void **pool; /* Pool of elements */ + int max; /* Max number of elements */ +}; + +struct iscsi_session { + /* iSCSI session-wide sequencing */ + uint32_t cmdsn; + uint32_t exp_cmdsn; + uint32_t max_cmdsn; + + /* configuration */ + int initial_r2t_en; + int max_r2t; + int imm_data_en; + int first_burst; + int max_burst; + int time2wait; + int time2retain; + int pdu_inorder_en; + int dataseq_inorder_en; + int erl; + int ifmarker_en; + int ofmarker_en; + + /* control data */ + struct iscsi_transport *tt; + struct Scsi_Host *host; + struct iscsi_conn *leadconn; /* leading connection */ + spinlock_t lock; /* protects session state, * + * sequence numbers, * + * session resources: * + * - cmdpool, * + * - mgmtpool, * + * - r2tpool */ + int state; /* session state */ + int recovery_failed; + struct list_head item; + int conn_cnt; + int age; /* counts session re-opens */ + + struct list_head connections; /* list of connections */ + int cmds_max; /* size of cmds array */ + struct iscsi_cmd_task **cmds; /* Original Cmds arr */ + struct iscsi_queue cmdpool; /* PDU's pool */ + int mgmtpool_max; /* size of mgmt array */ + struct iscsi_mgmt_task **mgmt_cmds; /* Original mgmt arr */ + struct iscsi_queue mgmtpool; /* Mgmt PDU's pool */ +}; + +/* + * scsi host template + */ +extern int iscsi_change_queue_depth(struct scsi_device *sdev, int depth); +extern int iscsi_eh_abort(struct scsi_cmnd *sc); +extern int iscsi_eh_host_reset(struct scsi_cmnd *sc); +extern int iscsi_queuecommand(struct scsi_cmnd *sc, + void (*done)(struct scsi_cmnd *)); + +/* + * session management + */ +extern struct iscsi_cls_session * +iscsi_session_setup(struct iscsi_transport *, struct scsi_transport_template *, + int, int, uint32_t, uint32_t *); +extern void iscsi_session_teardown(struct iscsi_cls_session *); +extern struct iscsi_session *class_to_transport_session(struct iscsi_cls_session *); +extern void iscsi_start_session_recovery(struct iscsi_session *, + struct iscsi_conn *, int); +extern void iscsi_session_recovery_timedout(struct iscsi_cls_session *); + +#define session_to_cls(_sess) \ + hostdata_session(_sess->host->hostdata) + +/* + * connection management + */ +extern struct iscsi_cls_conn *iscsi_conn_setup(struct iscsi_cls_session *, + uint32_t); +extern void iscsi_conn_teardown(struct iscsi_cls_conn *); +extern int iscsi_conn_start(struct iscsi_cls_conn *); +extern void iscsi_conn_stop(struct iscsi_cls_conn *, int); +extern int iscsi_conn_bind(struct iscsi_cls_session *, struct iscsi_cls_conn *, + int); +extern void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err); + +/* + * pdu and task processing + */ +extern int iscsi_check_assign_cmdsn(struct iscsi_session *, + struct iscsi_nopin *); +extern void iscsi_prep_unsolicit_data_pdu(struct iscsi_cmd_task *, + struct iscsi_data *hdr, + int transport_data_cnt); +extern int iscsi_conn_send_pdu(struct iscsi_cls_conn *, struct iscsi_hdr *, + char *, uint32_t); +extern int iscsi_complete_pdu(struct iscsi_conn *, struct iscsi_hdr *, + char *, int); +extern int __iscsi_complete_pdu(struct iscsi_conn *, struct iscsi_hdr *, + char *, int); +extern int iscsi_verify_itt(struct iscsi_conn *, struct iscsi_hdr *, + uint32_t *); + +/* + * generic helpers + */ +extern void iscsi_pool_free(struct iscsi_queue *, void **); +extern int iscsi_pool_init(struct iscsi_queue *, int, void ***, int); + +#endif diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index 9d2b99159ee..b332d6e839f 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -2,7 +2,7 @@ * iSCSI transport class definitions * * Copyright (C) IBM Corporation, 2004 - * Copyright (C) Mike Christie, 2004 - 2005 + * Copyright (C) Mike Christie, 2004 - 2006 * Copyright (C) Dmitry Yusupov, 2004 - 2005 * Copyright (C) Alex Aizman, 2004 - 2005 * @@ -27,9 +27,13 @@ #include struct scsi_transport_template; +struct iscsi_transport; struct Scsi_Host; struct mempool_zone; struct iscsi_cls_conn; +struct iscsi_conn; +struct iscsi_cmd_task; +struct iscsi_mgmt_task; /** * struct iscsi_transport - iSCSI Transport template @@ -46,6 +50,20 @@ struct iscsi_cls_conn; * @start_conn: set connection to be operational * @stop_conn: suspend/recover/terminate connection * @send_pdu: send iSCSI PDU, Login, Logout, NOP-Out, Reject, Text. + * @session_recovery_timedout: notify LLD a block during recovery timed out + * @suspend_conn_recv: susepend the recv side of the connection + * @termincate_conn: destroy socket connection. Called with mutex lock. + * @init_cmd_task: Initialize a iscsi_cmd_task and any internal structs. + * Called from queuecommand with session lock held. + * @init_mgmt_task: Initialize a iscsi_mgmt_task and any internal structs. + * Called from iscsi_conn_send_generic with xmitmutex. + * @xmit_cmd_task: requests LLD to transfer cmd task + * @xmit_mgmt_task: requests LLD to transfer mgmt task + * @cleanup_cmd_task: requests LLD to fail cmd task. Called with xmitmutex + * and session->lock after the connection has been + * suspended and terminated during recovery. If called + * from abort task then connection is not suspended + * or terminated but sk_callback_lock is held * * Template API provided by iSCSI Transport */ @@ -56,8 +74,6 @@ struct iscsi_transport { /* LLD sets this to indicate what values it can export to sysfs */ unsigned int param_mask; struct scsi_host_template *host_template; - /* LLD session/scsi_host data size */ - int hostdata_size; /* LLD connection data size */ int conndata_size; /* LLD session data size */ @@ -65,8 +81,8 @@ struct iscsi_transport { int max_lun; unsigned int max_conn; unsigned int max_cmd_len; - struct iscsi_cls_session *(*create_session) - (struct scsi_transport_template *t, uint32_t sn, uint32_t *hn); + struct iscsi_cls_session *(*create_session) (struct iscsi_transport *it, + struct scsi_transport_template *t, uint32_t sn, uint32_t *hn); void (*destroy_session) (struct iscsi_cls_session *session); struct iscsi_cls_conn *(*create_conn) (struct iscsi_cls_session *sess, uint32_t cid); @@ -90,6 +106,18 @@ struct iscsi_transport { char *data, uint32_t data_size); void (*get_stats) (struct iscsi_cls_conn *conn, struct iscsi_stats *stats); + void (*suspend_conn_recv) (struct iscsi_conn *conn); + void (*terminate_conn) (struct iscsi_conn *conn); + void (*init_cmd_task) (struct iscsi_cmd_task *ctask); + void (*init_mgmt_task) (struct iscsi_conn *conn, + struct iscsi_mgmt_task *mtask, + char *data, uint32_t data_size); + int (*xmit_cmd_task) (struct iscsi_conn *conn, + struct iscsi_cmd_task *ctask); + void (*cleanup_cmd_task) (struct iscsi_conn *conn, + struct iscsi_cmd_task *ctask); + int (*xmit_mgmt_task) (struct iscsi_conn *conn, + struct iscsi_mgmt_task *mtask); void (*session_recovery_timedout) (struct iscsi_cls_session *session); }; @@ -106,6 +134,13 @@ extern void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error); extern int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr, char *data, uint32_t data_size); + +/* Connection's states */ +#define ISCSI_CONN_INITIAL_STAGE 0 +#define ISCSI_CONN_STARTED 1 +#define ISCSI_CONN_STOPPED 2 +#define ISCSI_CONN_CLEANUP_WAIT 3 + struct iscsi_cls_conn { struct list_head conn_list; /* item in connlist */ void *dd_data; /* LLD private data */ @@ -129,6 +164,12 @@ struct iscsi_cls_conn { #define iscsi_dev_to_conn(_dev) \ container_of(_dev, struct iscsi_cls_conn, dev) +/* Session's states */ +#define ISCSI_STATE_FREE 1 +#define ISCSI_STATE_LOGGED_IN 2 +#define ISCSI_STATE_FAILED 3 +#define ISCSI_STATE_TERMINATE 4 + struct iscsi_cls_session { struct list_head sess_list; /* item in session_list */ struct list_head host_list; @@ -174,12 +215,4 @@ extern int iscsi_destroy_conn(struct iscsi_cls_conn *conn); extern void iscsi_unblock_session(struct iscsi_cls_session *session); extern void iscsi_block_session(struct iscsi_cls_session *session); -/* - * session functions used by software iscsi - */ -extern struct Scsi_Host * -iscsi_transport_create_session(struct scsi_transport_template *scsit, - struct iscsi_transport *transport); -extern int iscsi_transport_destroy_session(struct Scsi_Host *shost); - #endif -- cgit v1.2.3 From 5bb0b55a3283369f1cd8ac76a6d8bda8e7a77055 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Thu, 6 Apr 2006 21:26:46 -0500 Subject: [SCSI] iscsi: convert iscsi tcp to libiscsi This just converts iscsi_tcp to the lib Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/iscsi_tcp.c | 2893 +++++++++++++--------------------------------- drivers/scsi/iscsi_tcp.h | 182 +-- 2 files changed, 841 insertions(+), 2234 deletions(-) diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index aca3e23b1b9..fe00a3f6d20 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -3,7 +3,8 @@ * * Copyright (C) 2004 Dmitry Yusupov * Copyright (C) 2004 Alex Aizman - * Copyright (C) 2005 Mike Christie + * Copyright (C) 2005 - 2006 Mike Christie + * Copyright (C) 2006 Red Hat, Inc. All rights reserved. * maintained by open-iscsi@googlegroups.com * * This program is free software; you can redistribute it and/or modify @@ -36,10 +37,6 @@ #include #include #include -#include -#include -#include -#include #include #include #include @@ -52,21 +49,14 @@ MODULE_DESCRIPTION("iSCSI/TCP data-path"); MODULE_LICENSE("GPL"); MODULE_VERSION("0:4.445"); /* #define DEBUG_TCP */ -/* #define DEBUG_SCSI */ #define DEBUG_ASSERT #ifdef DEBUG_TCP -#define debug_tcp(fmt...) printk(KERN_DEBUG "tcp: " fmt) +#define debug_tcp(fmt...) printk(KERN_INFO "tcp: " fmt) #else #define debug_tcp(fmt...) #endif -#ifdef DEBUG_SCSI -#define debug_scsi(fmt...) printk(KERN_DEBUG "scsi: " fmt) -#else -#define debug_scsi(fmt...) -#endif - #ifndef DEBUG_ASSERT #ifdef BUG_ON #undef BUG_ON @@ -74,17 +64,12 @@ MODULE_VERSION("0:4.445"); #define BUG_ON(expr) #endif -#define INVALID_SN_DELTA 0xffff - static unsigned int iscsi_max_lun = 512; module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO); /* global data */ static kmem_cache_t *taskcache; -#define session_to_cls(_sess) \ - hostdata_session(_sess->host->hostdata) - static inline void iscsi_buf_init_virt(struct iscsi_buf *ibuf, char *vbuf, int size) { @@ -133,68 +118,39 @@ static inline void iscsi_hdr_digest(struct iscsi_conn *conn, struct iscsi_buf *buf, u8* crc) { - crypto_digest_digest(conn->tx_tfm, &buf->sg, 1, crc); - buf->sg.length += sizeof(uint32_t); -} + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; -static void -iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err) -{ - struct iscsi_session *session = conn->session; - unsigned long flags; - - spin_lock_irqsave(&session->lock, flags); - if (session->conn_cnt == 1 || session->leadconn == conn) - session->state = ISCSI_STATE_FAILED; - spin_unlock_irqrestore(&session->lock, flags); - set_bit(SUSPEND_BIT, &conn->suspend_tx); - set_bit(SUSPEND_BIT, &conn->suspend_rx); - iscsi_conn_error(conn->cls_conn, err); + crypto_digest_digest(tcp_conn->tx_tfm, &buf->sg, 1, crc); + buf->sg.length += sizeof(uint32_t); } static inline int -iscsi_check_assign_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr) +iscsi_hdr_extract(struct iscsi_tcp_conn *tcp_conn) { - uint32_t max_cmdsn = be32_to_cpu(hdr->max_cmdsn); - uint32_t exp_cmdsn = be32_to_cpu(hdr->exp_cmdsn); - - if (max_cmdsn < exp_cmdsn -1 && - max_cmdsn > exp_cmdsn - INVALID_SN_DELTA) - return ISCSI_ERR_MAX_CMDSN; - if (max_cmdsn > session->max_cmdsn || - max_cmdsn < session->max_cmdsn - INVALID_SN_DELTA) - session->max_cmdsn = max_cmdsn; - if (exp_cmdsn > session->exp_cmdsn || - exp_cmdsn < session->exp_cmdsn - INVALID_SN_DELTA) - session->exp_cmdsn = exp_cmdsn; - - return 0; -} + struct sk_buff *skb = tcp_conn->in.skb; -static inline int -iscsi_hdr_extract(struct iscsi_conn *conn) -{ - struct sk_buff *skb = conn->in.skb; + tcp_conn->in.zero_copy_hdr = 0; - if (conn->in.copy >= conn->hdr_size && - conn->in_progress == IN_PROGRESS_WAIT_HEADER) { + if (tcp_conn->in.copy >= tcp_conn->hdr_size && + tcp_conn->in_progress == IN_PROGRESS_WAIT_HEADER) { /* * Zero-copy PDU Header: using connection context * to store header pointer. */ if (skb_shinfo(skb)->frag_list == NULL && - !skb_shinfo(skb)->nr_frags) - conn->in.hdr = (struct iscsi_hdr *) - ((char*)skb->data + conn->in.offset); - else { + !skb_shinfo(skb)->nr_frags) { + tcp_conn->in.hdr = (struct iscsi_hdr *) + ((char*)skb->data + tcp_conn->in.offset); + tcp_conn->in.zero_copy_hdr = 1; + } else { /* ignoring return code since we checked * in.copy before */ - skb_copy_bits(skb, conn->in.offset, - &conn->hdr, conn->hdr_size); - conn->in.hdr = &conn->hdr; + skb_copy_bits(skb, tcp_conn->in.offset, + &tcp_conn->hdr, tcp_conn->hdr_size); + tcp_conn->in.hdr = &tcp_conn->hdr; } - conn->in.offset += conn->hdr_size; - conn->in.copy -= conn->hdr_size; + tcp_conn->in.offset += tcp_conn->hdr_size; + tcp_conn->in.copy -= tcp_conn->hdr_size; } else { int hdr_remains; int copylen; @@ -204,30 +160,31 @@ iscsi_hdr_extract(struct iscsi_conn *conn) * copying it... This'll happen quite rarely. */ - if (conn->in_progress == IN_PROGRESS_WAIT_HEADER) - conn->in.hdr_offset = 0; + if (tcp_conn->in_progress == IN_PROGRESS_WAIT_HEADER) + tcp_conn->in.hdr_offset = 0; - hdr_remains = conn->hdr_size - conn->in.hdr_offset; + hdr_remains = tcp_conn->hdr_size - tcp_conn->in.hdr_offset; BUG_ON(hdr_remains <= 0); - copylen = min(conn->in.copy, hdr_remains); - skb_copy_bits(skb, conn->in.offset, - (char*)&conn->hdr + conn->in.hdr_offset, copylen); + copylen = min(tcp_conn->in.copy, hdr_remains); + skb_copy_bits(skb, tcp_conn->in.offset, + (char*)&tcp_conn->hdr + tcp_conn->in.hdr_offset, + copylen); debug_tcp("PDU gather offset %d bytes %d in.offset %d " - "in.copy %d\n", conn->in.hdr_offset, copylen, - conn->in.offset, conn->in.copy); + "in.copy %d\n", tcp_conn->in.hdr_offset, copylen, + tcp_conn->in.offset, tcp_conn->in.copy); - conn->in.offset += copylen; - conn->in.copy -= copylen; + tcp_conn->in.offset += copylen; + tcp_conn->in.copy -= copylen; if (copylen < hdr_remains) { - conn->in_progress = IN_PROGRESS_HEADER_GATHER; - conn->in.hdr_offset += copylen; + tcp_conn->in_progress = IN_PROGRESS_HEADER_GATHER; + tcp_conn->in.hdr_offset += copylen; return -EAGAIN; } - conn->in.hdr = &conn->hdr; - conn->discontiguous_hdr_cnt++; - conn->in_progress = IN_PROGRESS_WAIT_HEADER; + tcp_conn->in.hdr = &tcp_conn->hdr; + tcp_conn->discontiguous_hdr_cnt++; + tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER; } return 0; @@ -239,7 +196,7 @@ iscsi_hdr_extract(struct iscsi_conn *conn) static void __iscsi_ctask_cleanup(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { - struct iscsi_session *session = conn->session; + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; struct scsi_cmnd *sc; sc = ctask->sc; @@ -248,88 +205,16 @@ __iscsi_ctask_cleanup(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) if (sc->sc_data_direction == DMA_TO_DEVICE) { struct iscsi_data_task *dtask, *n; + /* WRITE: cleanup Data-Out's if any */ - list_for_each_entry_safe(dtask, n, &ctask->dataqueue, item) { + list_for_each_entry_safe(dtask, n, &tcp_ctask->dataqueue, + item) { list_del(&dtask->item); - mempool_free(dtask, ctask->datapool); + mempool_free(dtask, tcp_ctask->datapool); } } - ctask->xmstate = XMSTATE_IDLE; - ctask->r2t = NULL; - ctask->sc = NULL; - list_del(&ctask->running); - - __kfifo_put(session->cmdpool.queue, (void*)&ctask, sizeof(void*)); - - sc->scsi_done(sc); -} - -static void -iscsi_ctask_cleanup(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) -{ - struct iscsi_session *session = conn->session; - - spin_lock(&session->lock); - __iscsi_ctask_cleanup(conn, ctask); - spin_unlock(&session->lock); -} - -/** - * iscsi_cmd_rsp - SCSI Command Response processing - * @conn: iscsi connection - * @ctask: scsi command task - **/ -static int -iscsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) -{ - int rc; - struct iscsi_cmd_rsp *rhdr = (struct iscsi_cmd_rsp *)conn->in.hdr; - struct iscsi_session *session = conn->session; - struct scsi_cmnd *sc = ctask->sc; - - rc = iscsi_check_assign_cmdsn(session, (struct iscsi_nopin*)rhdr); - if (rc) { - sc->result = (DID_ERROR << 16); - goto out; - } - - conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1; - - sc->result = (DID_OK << 16) | rhdr->cmd_status; - - if (rhdr->response != ISCSI_STATUS_CMD_COMPLETED) { - sc->result = (DID_ERROR << 16); - goto out; - } - - if (rhdr->cmd_status == SAM_STAT_CHECK_CONDITION && conn->senselen) { - int sensecopy = min(conn->senselen, SCSI_SENSE_BUFFERSIZE); - - memcpy(sc->sense_buffer, conn->data + 2, sensecopy); - debug_scsi("copied %d bytes of sense\n", sensecopy); - } - - if (sc->sc_data_direction == DMA_TO_DEVICE) - goto out; - - if (rhdr->flags & ISCSI_FLAG_CMD_UNDERFLOW) { - int res_count = be32_to_cpu(rhdr->residual_count); - - if (res_count > 0 && res_count <= sc->request_bufflen) - sc->resid = res_count; - else - sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status; - } else if (rhdr->flags & ISCSI_FLAG_CMD_BIDI_UNDERFLOW) - sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status; - else if (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW) - sc->resid = be32_to_cpu(rhdr->residual_count); - -out: - debug_scsi("done [sc %lx res %d itt 0x%x]\n", - (long)sc, sc->result, ctask->itt); - conn->scsirsp_pdus_cnt++; - iscsi_ctask_cleanup(conn, ctask); - return rc; + tcp_ctask->xmstate = XMSTATE_IDLE; + tcp_ctask->r2t = NULL; } /** @@ -341,7 +226,9 @@ static int iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { int rc; - struct iscsi_data_rsp *rhdr = (struct iscsi_data_rsp *)conn->in.hdr; + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; + struct iscsi_data_rsp *rhdr = (struct iscsi_data_rsp *)tcp_conn->in.hdr; struct iscsi_session *session = conn->session; int datasn = be32_to_cpu(rhdr->datasn); @@ -351,9 +238,9 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) /* * setup Data-In byte counter (gets decremented..) */ - ctask->data_count = conn->in.datalen; + ctask->data_count = tcp_conn->in.datalen; - if (conn->in.datalen == 0) + if (tcp_conn->in.datalen == 0) return 0; if (ctask->datasn != datasn) @@ -361,8 +248,8 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) ctask->datasn++; - ctask->data_offset = be32_to_cpu(rhdr->offset); - if (ctask->data_offset + conn->in.datalen > ctask->total_length) + tcp_ctask->data_offset = be32_to_cpu(rhdr->offset); + if (tcp_ctask->data_offset + tcp_conn->in.datalen > ctask->total_length) return ISCSI_ERR_DATA_OFFSET; if (rhdr->flags & ISCSI_FLAG_DATA_STATUS) { @@ -409,8 +296,9 @@ iscsi_solicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, struct iscsi_data *hdr; struct iscsi_data_task *dtask; struct scsi_cmnd *sc = ctask->sc; + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; - dtask = mempool_alloc(ctask->datapool, GFP_ATOMIC); + dtask = mempool_alloc(tcp_ctask->datapool, GFP_ATOMIC); BUG_ON(!dtask); INIT_LIST_HEAD(&dtask->item); hdr = &dtask->hdr; @@ -419,8 +307,8 @@ iscsi_solicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, hdr->datasn = cpu_to_be32(r2t->solicit_datasn); r2t->solicit_datasn++; hdr->opcode = ISCSI_OP_SCSI_DATA_OUT; - memcpy(hdr->lun, ctask->hdr.lun, sizeof(hdr->lun)); - hdr->itt = ctask->hdr.itt; + memcpy(hdr->lun, ctask->hdr->lun, sizeof(hdr->lun)); + hdr->itt = ctask->hdr->itt; hdr->exp_statsn = r2t->exp_statsn; hdr->offset = cpu_to_be32(r2t->data_offset); if (r2t->data_length > conn->max_xmit_dlength) { @@ -469,11 +357,11 @@ iscsi_solicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, } BUG_ON(r2t->sg == NULL); } else - iscsi_buf_init_iov(&ctask->sendbuf, + iscsi_buf_init_iov(&tcp_ctask->sendbuf, (char*)sc->request_buffer + r2t->data_offset, r2t->data_count); - list_add(&dtask->item, &ctask->dataqueue); + list_add(&dtask->item, &tcp_ctask->dataqueue); } /** @@ -486,17 +374,16 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { struct iscsi_r2t_info *r2t; struct iscsi_session *session = conn->session; - struct iscsi_r2t_rsp *rhdr = (struct iscsi_r2t_rsp *)conn->in.hdr; + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; + struct iscsi_r2t_rsp *rhdr = (struct iscsi_r2t_rsp *)tcp_conn->in.hdr; int r2tsn = be32_to_cpu(rhdr->r2tsn); int rc; - if (conn->in.ahslen) - return ISCSI_ERR_AHSLEN; - - if (conn->in.datalen) + if (tcp_conn->in.datalen) return ISCSI_ERR_DATALEN; - if (ctask->exp_r2tsn && ctask->exp_r2tsn != r2tsn) + if (tcp_ctask->exp_r2tsn && tcp_ctask->exp_r2tsn != r2tsn) return ISCSI_ERR_R2TSN; rc = iscsi_check_assign_cmdsn(session, (struct iscsi_nopin*)rhdr); @@ -514,7 +401,7 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) spin_unlock(&session->lock); return 0; } - rc = __kfifo_get(ctask->r2tpool.queue, (void*)&r2t, sizeof(void*)); + rc = __kfifo_get(tcp_ctask->r2tpool.queue, (void*)&r2t, sizeof(void*)); BUG_ON(!rc); r2t->exp_statsn = rhdr->statsn; @@ -536,10 +423,10 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) iscsi_solicit_data_init(conn, ctask, r2t); - ctask->exp_r2tsn = r2tsn + 1; - ctask->xmstate |= XMSTATE_SOL_HDR; - __kfifo_put(ctask->r2tqueue, (void*)&r2t, sizeof(void*)); - __kfifo_put(conn->writequeue, (void*)&ctask, sizeof(void*)); + tcp_ctask->exp_r2tsn = r2tsn + 1; + tcp_ctask->xmstate |= XMSTATE_SOL_HDR; + __kfifo_put(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*)); + __kfifo_put(conn->xmitqueue, (void*)&ctask, sizeof(void*)); scsi_queue_work(session->host, &conn->xmitwork); conn->r2t_pdus_cnt++; @@ -549,256 +436,136 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) } static int -iscsi_hdr_recv(struct iscsi_conn *conn) +iscsi_tcp_hdr_recv(struct iscsi_conn *conn) { - int rc = 0; + int rc = 0, opcode, ahslen; struct iscsi_hdr *hdr; - struct iscsi_cmd_task *ctask; struct iscsi_session *session = conn->session; - uint32_t cdgst, rdgst = 0; + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; + uint32_t cdgst, rdgst = 0, itt; - hdr = conn->in.hdr; + hdr = tcp_conn->in.hdr; /* verify PDU length */ - conn->in.datalen = ntoh24(hdr->dlength); - if (conn->in.datalen > conn->max_recv_dlength) { + tcp_conn->in.datalen = ntoh24(hdr->dlength); + if (tcp_conn->in.datalen > conn->max_recv_dlength) { printk(KERN_ERR "iscsi_tcp: datalen %d > %d\n", - conn->in.datalen, conn->max_recv_dlength); + tcp_conn->in.datalen, conn->max_recv_dlength); return ISCSI_ERR_DATALEN; } - conn->data_copied = 0; + tcp_conn->data_copied = 0; /* read AHS */ - conn->in.ahslen = hdr->hlength * 4; - conn->in.offset += conn->in.ahslen; - conn->in.copy -= conn->in.ahslen; - if (conn->in.copy < 0) { + ahslen = hdr->hlength << 2; + tcp_conn->in.offset += ahslen; + tcp_conn->in.copy -= ahslen; + if (tcp_conn->in.copy < 0) { printk(KERN_ERR "iscsi_tcp: can't handle AHS with length " - "%d bytes\n", conn->in.ahslen); + "%d bytes\n", ahslen); return ISCSI_ERR_AHSLEN; } /* calculate read padding */ - conn->in.padding = conn->in.datalen & (ISCSI_PAD_LEN-1); - if (conn->in.padding) { - conn->in.padding = ISCSI_PAD_LEN - conn->in.padding; - debug_scsi("read padding %d bytes\n", conn->in.padding); + tcp_conn->in.padding = tcp_conn->in.datalen & (ISCSI_PAD_LEN-1); + if (tcp_conn->in.padding) { + tcp_conn->in.padding = ISCSI_PAD_LEN - tcp_conn->in.padding; + debug_scsi("read padding %d bytes\n", tcp_conn->in.padding); } if (conn->hdrdgst_en) { struct scatterlist sg; sg_init_one(&sg, (u8 *)hdr, - sizeof(struct iscsi_hdr) + conn->in.ahslen); - crypto_digest_digest(conn->rx_tfm, &sg, 1, (u8 *)&cdgst); + sizeof(struct iscsi_hdr) + ahslen); + crypto_digest_digest(tcp_conn->rx_tfm, &sg, 1, (u8 *)&cdgst); rdgst = *(uint32_t*)((char*)hdr + sizeof(struct iscsi_hdr) + - conn->in.ahslen); + ahslen); if (cdgst != rdgst) { - printk(KERN_ERR "iscsi_tcp: itt %x: hdrdgst error " - "recv 0x%x calc 0x%x\n", conn->in.itt, rdgst, - cdgst); + printk(KERN_ERR "iscsi_tcp: hdrdgst error " + "recv 0x%x calc 0x%x\n", rdgst, cdgst); return ISCSI_ERR_HDR_DGST; } } - /* save opcode for later */ - conn->in.opcode = hdr->opcode & ISCSI_OPCODE_MASK; - + opcode = hdr->opcode & ISCSI_OPCODE_MASK; /* verify itt (itt encoding: age+cid+itt) */ - if (hdr->itt != cpu_to_be32(ISCSI_RESERVED_TAG)) { - if ((hdr->itt & AGE_MASK) != - (session->age << AGE_SHIFT)) { - printk(KERN_ERR "iscsi_tcp: received itt %x expected " - "session age (%x)\n", hdr->itt, - session->age & AGE_MASK); - return ISCSI_ERR_BAD_ITT; - } - - if ((hdr->itt & CID_MASK) != (conn->id << CID_SHIFT)) { - printk(KERN_ERR "iscsi_tcp: received itt %x, expected " - "CID (%x)\n", hdr->itt, conn->id); - return ISCSI_ERR_BAD_ITT; - } - conn->in.itt = hdr->itt & ITT_MASK; - } else - conn->in.itt = hdr->itt; + rc = iscsi_verify_itt(conn, hdr, &itt); + if (rc == ISCSI_ERR_NO_SCSI_CMD) { + tcp_conn->in.datalen = 0; /* force drop */ + return 0; + } else if (rc) + return rc; debug_tcp("opcode 0x%x offset %d copy %d ahslen %d datalen %d\n", - hdr->opcode, conn->in.offset, conn->in.copy, - conn->in.ahslen, conn->in.datalen); - - if (conn->in.itt < session->cmds_max) { - ctask = (struct iscsi_cmd_task *)session->cmds[conn->in.itt]; - - if (!ctask->sc) { - printk(KERN_INFO "iscsi_tcp: dropping ctask with " - "itt 0x%x\n", ctask->itt); - conn->in.datalen = 0; /* force drop */ - return 0; - } - - if (ctask->sc->SCp.phase != session->age) { - printk(KERN_ERR "iscsi_tcp: ctask's session age %d, " - "expected %d\n", ctask->sc->SCp.phase, - session->age); - return ISCSI_ERR_SESSION_FAILED; - } - - conn->in.ctask = ctask; - - debug_scsi("rsp [op 0x%x cid %d sc %lx itt 0x%x len %d]\n", - hdr->opcode, conn->id, (long)ctask->sc, - ctask->itt, conn->in.datalen); - - switch(conn->in.opcode) { - case ISCSI_OP_SCSI_CMD_RSP: - BUG_ON((void*)ctask != ctask->sc->SCp.ptr); - if (!conn->in.datalen) - rc = iscsi_cmd_rsp(conn, ctask); - else - /* - * got sense or response data; copying PDU - * Header to the connection's header - * placeholder - */ - memcpy(&conn->hdr, hdr, - sizeof(struct iscsi_hdr)); - break; - case ISCSI_OP_SCSI_DATA_IN: - BUG_ON((void*)ctask != ctask->sc->SCp.ptr); - /* save flags for non-exceptional status */ - conn->in.flags = hdr->flags; - /* save cmd_status for sense data */ - conn->in.cmd_status = - ((struct iscsi_data_rsp*)hdr)->cmd_status; - rc = iscsi_data_rsp(conn, ctask); - break; - case ISCSI_OP_R2T: - BUG_ON((void*)ctask != ctask->sc->SCp.ptr); - if (ctask->sc->sc_data_direction == DMA_TO_DEVICE) - rc = iscsi_r2t_rsp(conn, ctask); - else - rc = ISCSI_ERR_PROTO; - break; - default: - rc = ISCSI_ERR_BAD_OPCODE; - break; - } - } else if (conn->in.itt >= ISCSI_MGMT_ITT_OFFSET && - conn->in.itt < ISCSI_MGMT_ITT_OFFSET + - session->mgmtpool_max) { - struct iscsi_mgmt_task *mtask = (struct iscsi_mgmt_task *) - session->mgmt_cmds[conn->in.itt - - ISCSI_MGMT_ITT_OFFSET]; - - debug_scsi("immrsp [op 0x%x cid %d itt 0x%x len %d]\n", - conn->in.opcode, conn->id, mtask->itt, - conn->in.datalen); - - switch(conn->in.opcode) { - case ISCSI_OP_LOGIN_RSP: - case ISCSI_OP_TEXT_RSP: - case ISCSI_OP_LOGOUT_RSP: - rc = iscsi_check_assign_cmdsn(session, - (struct iscsi_nopin*)hdr); - if (rc) - break; + opcode, tcp_conn->in.offset, tcp_conn->in.copy, + ahslen, tcp_conn->in.datalen); - if (!conn->in.datalen) { - rc = iscsi_recv_pdu(conn->cls_conn, hdr, - NULL, 0); - if (conn->login_mtask != mtask) { - spin_lock(&session->lock); - __kfifo_put(session->mgmtpool.queue, - (void*)&mtask, sizeof(void*)); - spin_unlock(&session->lock); - } - } - break; - case ISCSI_OP_SCSI_TMFUNC_RSP: - rc = iscsi_check_assign_cmdsn(session, - (struct iscsi_nopin*)hdr); - if (rc) - break; + switch(opcode) { + case ISCSI_OP_SCSI_DATA_IN: + tcp_conn->in.ctask = session->cmds[itt]; + rc = iscsi_data_rsp(conn, tcp_conn->in.ctask); + /* fall through */ + case ISCSI_OP_SCSI_CMD_RSP: + tcp_conn->in.ctask = session->cmds[itt]; + if (tcp_conn->in.datalen) + goto copy_hdr; - if (conn->in.datalen || conn->in.ahslen) { - rc = ISCSI_ERR_PROTO; - break; - } - conn->tmfrsp_pdus_cnt++; - spin_lock(&session->lock); - if (conn->tmabort_state == TMABORT_INITIAL) { - conn->tmabort_state = - ((struct iscsi_tm_rsp *)hdr)-> - response == ISCSI_TMF_RSP_COMPLETE ? - TMABORT_SUCCESS:TMABORT_FAILED; - /* unblock eh_abort() */ - wake_up(&conn->ehwait); - } - spin_unlock(&session->lock); - break; - case ISCSI_OP_NOOP_IN: - if (hdr->ttt != ISCSI_RESERVED_TAG) { - rc = ISCSI_ERR_PROTO; - break; - } - rc = iscsi_check_assign_cmdsn(session, - (struct iscsi_nopin*)hdr); - if (rc) - break; - conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; - - if (!conn->in.datalen) { - struct iscsi_mgmt_task *mtask; - - rc = iscsi_recv_pdu(conn->cls_conn, hdr, - NULL, 0); - mtask = (struct iscsi_mgmt_task *) - session->mgmt_cmds[conn->in.itt - - ISCSI_MGMT_ITT_OFFSET]; - if (conn->login_mtask != mtask) { - spin_lock(&session->lock); - __kfifo_put(session->mgmtpool.queue, - (void*)&mtask, sizeof(void*)); - spin_unlock(&session->lock); - } - } - break; - default: - rc = ISCSI_ERR_BAD_OPCODE; - break; - } - } else if (conn->in.itt == ISCSI_RESERVED_TAG) { - switch(conn->in.opcode) { - case ISCSI_OP_NOOP_IN: - if (!conn->in.datalen) { - rc = iscsi_check_assign_cmdsn(session, - (struct iscsi_nopin*)hdr); - if (!rc && hdr->ttt != ISCSI_RESERVED_TAG) - rc = iscsi_recv_pdu(conn->cls_conn, - hdr, NULL, 0); - } else - rc = ISCSI_ERR_PROTO; - break; - case ISCSI_OP_REJECT: - /* we need sth like iscsi_reject_rsp()*/ - case ISCSI_OP_ASYNC_EVENT: - /* we need sth like iscsi_async_event_rsp() */ - rc = ISCSI_ERR_BAD_OPCODE; - break; - default: - rc = ISCSI_ERR_BAD_OPCODE; - break; - } - } else - rc = ISCSI_ERR_BAD_ITT; + spin_lock(&session->lock); + __iscsi_ctask_cleanup(conn, tcp_conn->in.ctask); + rc = __iscsi_complete_pdu(conn, hdr, NULL, 0); + spin_unlock(&session->lock); + break; + case ISCSI_OP_R2T: + tcp_conn->in.ctask = session->cmds[itt]; + if (ahslen) + rc = ISCSI_ERR_AHSLEN; + else if (tcp_conn->in.ctask->sc->sc_data_direction == + DMA_TO_DEVICE) + rc = iscsi_r2t_rsp(conn, tcp_conn->in.ctask); + else + rc = ISCSI_ERR_PROTO; + break; + case ISCSI_OP_LOGIN_RSP: + case ISCSI_OP_TEXT_RSP: + case ISCSI_OP_LOGOUT_RSP: + case ISCSI_OP_NOOP_IN: + case ISCSI_OP_REJECT: + case ISCSI_OP_ASYNC_EVENT: + if (tcp_conn->in.datalen) + goto copy_hdr; + /* fall through */ + case ISCSI_OP_SCSI_TMFUNC_RSP: + rc = iscsi_complete_pdu(conn, hdr, NULL, 0); + break; + default: + rc = ISCSI_ERR_BAD_OPCODE; + break; + } return rc; + +copy_hdr: + /* + * if we did zero copy for the header but we will need multiple + * skbs to complete the command then we have to copy the header + * for later use + */ + if (tcp_conn->in.zero_copy_hdr && tcp_conn->in.copy < + (tcp_conn->in.datalen + tcp_conn->in.padding + + (conn->datadgst_en ? 4 : 0))) { + debug_tcp("Copying header for later use. in.copy %d in.datalen" + " %d\n", tcp_conn->in.copy, tcp_conn->in.datalen); + memcpy(&tcp_conn->hdr, tcp_conn->in.hdr, + sizeof(struct iscsi_hdr)); + tcp_conn->in.hdr = &tcp_conn->hdr; + tcp_conn->in.zero_copy_hdr = 0; + } + return 0; } /** * iscsi_ctask_copy - copy skb bits to the destanation cmd task - * @conn: iscsi connection + * @conn: iscsi tcp connection * @ctask: scsi command task * @buf: buffer to copy to * @buf_size: size of buffer @@ -820,110 +587,113 @@ iscsi_hdr_recv(struct iscsi_conn *conn) * buf_left left to copy from in progress buffer **/ static inline int -iscsi_ctask_copy(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, +iscsi_ctask_copy(struct iscsi_tcp_conn *tcp_conn, struct iscsi_cmd_task *ctask, void *buf, int buf_size, int offset) { - int buf_left = buf_size - (conn->data_copied + offset); - int size = min(conn->in.copy, buf_left); + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; + int buf_left = buf_size - (tcp_conn->data_copied + offset); + int size = min(tcp_conn->in.copy, buf_left); int rc; size = min(size, ctask->data_count); debug_tcp("ctask_copy %d bytes at offset %d copied %d\n", - size, conn->in.offset, conn->in.copied); + size, tcp_conn->in.offset, tcp_conn->in.copied); BUG_ON(size <= 0); - BUG_ON(ctask->sent + size > ctask->total_length); + BUG_ON(tcp_ctask->sent + size > ctask->total_length); - rc = skb_copy_bits(conn->in.skb, conn->in.offset, - (char*)buf + (offset + conn->data_copied), size); + rc = skb_copy_bits(tcp_conn->in.skb, tcp_conn->in.offset, + (char*)buf + (offset + tcp_conn->data_copied), size); /* must fit into skb->len */ BUG_ON(rc); - conn->in.offset += size; - conn->in.copy -= size; - conn->in.copied += size; - conn->data_copied += size; - ctask->sent += size; + tcp_conn->in.offset += size; + tcp_conn->in.copy -= size; + tcp_conn->in.copied += size; + tcp_conn->data_copied += size; + tcp_ctask->sent += size; ctask->data_count -= size; - BUG_ON(conn->in.copy < 0); + BUG_ON(tcp_conn->in.copy < 0); BUG_ON(ctask->data_count < 0); - if (buf_size != (conn->data_copied + offset)) { + if (buf_size != (tcp_conn->data_copied + offset)) { if (!ctask->data_count) { - BUG_ON(buf_size - conn->data_copied < 0); + BUG_ON(buf_size - tcp_conn->data_copied < 0); /* done with this PDU */ - return buf_size - conn->data_copied; + return buf_size - tcp_conn->data_copied; } return -EAGAIN; } /* done with this buffer or with both - PDU and buffer */ - conn->data_copied = 0; + tcp_conn->data_copied = 0; return 0; } /** * iscsi_tcp_copy - copy skb bits to the destanation buffer - * @conn: iscsi connection - * @buf: buffer to copy to - * @buf_size: number of bytes to copy + * @conn: iscsi tcp connection * * Notes: * The function calls skb_copy_bits() and updates per-connection * byte counters. **/ static inline int -iscsi_tcp_copy(struct iscsi_conn *conn, void *buf, int buf_size) +iscsi_tcp_copy(struct iscsi_tcp_conn *tcp_conn) { - int buf_left = buf_size - conn->data_copied; - int size = min(conn->in.copy, buf_left); + void *buf = tcp_conn->data; + int buf_size = tcp_conn->in.datalen; + int buf_left = buf_size - tcp_conn->data_copied; + int size = min(tcp_conn->in.copy, buf_left); int rc; debug_tcp("tcp_copy %d bytes at offset %d copied %d\n", - size, conn->in.offset, conn->data_copied); + size, tcp_conn->in.offset, tcp_conn->data_copied); BUG_ON(size <= 0); - rc = skb_copy_bits(conn->in.skb, conn->in.offset, - (char*)buf + conn->data_copied, size); + rc = skb_copy_bits(tcp_conn->in.skb, tcp_conn->in.offset, + (char*)buf + tcp_conn->data_copied, size); BUG_ON(rc); - conn->in.offset += size; - conn->in.copy -= size; - conn->in.copied += size; - conn->data_copied += size; + tcp_conn->in.offset += size; + tcp_conn->in.copy -= size; + tcp_conn->in.copied += size; + tcp_conn->data_copied += size; - if (buf_size != conn->data_copied) + if (buf_size != tcp_conn->data_copied) return -EAGAIN; return 0; } static inline void -partial_sg_digest_update(struct iscsi_conn *conn, struct scatterlist *sg, - int offset, int length) +partial_sg_digest_update(struct iscsi_tcp_conn *tcp_conn, + struct scatterlist *sg, int offset, int length) { struct scatterlist temp; memcpy(&temp, sg, sizeof(struct scatterlist)); temp.offset = offset; temp.length = length; - crypto_digest_update(conn->data_rx_tfm, &temp, 1); + crypto_digest_update(tcp_conn->data_rx_tfm, &temp, 1); } static void -iscsi_recv_digest_update(struct iscsi_conn *conn, char* buf, int len) +iscsi_recv_digest_update(struct iscsi_tcp_conn *tcp_conn, char* buf, int len) { struct scatterlist tmp; sg_init_one(&tmp, buf, len); - crypto_digest_update(conn->data_rx_tfm, &tmp, 1); + crypto_digest_update(tcp_conn->data_rx_tfm, &tmp, 1); } static int iscsi_scsi_data_in(struct iscsi_conn *conn) { - struct iscsi_cmd_task *ctask = conn->in.ctask; + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; + struct iscsi_cmd_task *ctask = tcp_conn->in.ctask; + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; struct scsi_cmnd *sc = ctask->sc; struct scatterlist *sg; int i, offset, rc = 0; @@ -935,31 +705,33 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn) */ if (!sc->use_sg) { i = ctask->data_count; - rc = iscsi_ctask_copy(conn, ctask, sc->request_buffer, - sc->request_bufflen, ctask->data_offset); + rc = iscsi_ctask_copy(tcp_conn, ctask, sc->request_buffer, + sc->request_bufflen, + tcp_ctask->data_offset); if (rc == -EAGAIN) return rc; if (conn->datadgst_en) - iscsi_recv_digest_update(conn, sc->request_buffer, i); + iscsi_recv_digest_update(tcp_conn, sc->request_buffer, + i); rc = 0; goto done; } - offset = ctask->data_offset; + offset = tcp_ctask->data_offset; sg = sc->request_buffer; - if (ctask->data_offset) - for (i = 0; i < ctask->sg_count; i++) + if (tcp_ctask->data_offset) + for (i = 0; i < tcp_ctask->sg_count; i++) offset -= sg[i].length; /* we've passed through partial sg*/ if (offset < 0) offset = 0; - for (i = ctask->sg_count; i < sc->use_sg; i++) { + for (i = tcp_ctask->sg_count; i < sc->use_sg; i++) { char *dest; dest = kmap_atomic(sg[i].page, KM_SOFTIRQ0); - rc = iscsi_ctask_copy(conn, ctask, dest + sg[i].offset, + rc = iscsi_ctask_copy(tcp_conn, ctask, dest + sg[i].offset, sg[i].length, offset); kunmap_atomic(dest, KM_SOFTIRQ0); if (rc == -EAGAIN) @@ -968,15 +740,17 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn) if (!rc) { if (conn->datadgst_en) { if (!offset) - crypto_digest_update(conn->data_rx_tfm, - &sg[i], 1); + crypto_digest_update( + tcp_conn->data_rx_tfm, + &sg[i], 1); else - partial_sg_digest_update(conn, &sg[i], + partial_sg_digest_update(tcp_conn, + &sg[i], sg[i].offset + offset, sg[i].length - offset); } offset = 0; - ctask->sg_count++; + tcp_ctask->sg_count++; } if (!ctask->data_count) { @@ -984,24 +758,26 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn) /* * data-in is complete, but buffer not... */ - partial_sg_digest_update(conn, &sg[i], + partial_sg_digest_update(tcp_conn, &sg[i], sg[i].offset, sg[i].length-rc); rc = 0; break; } - if (!conn->in.copy) + if (!tcp_conn->in.copy) return -EAGAIN; } BUG_ON(ctask->data_count); done: /* check for non-exceptional status */ - if (conn->in.flags & ISCSI_FLAG_DATA_STATUS) { + if (tcp_conn->in.hdr->flags & ISCSI_FLAG_DATA_STATUS) { debug_scsi("done [sc %lx res %d itt 0x%x]\n", (long)sc, sc->result, ctask->itt); - conn->scsirsp_pdus_cnt++; - iscsi_ctask_cleanup(conn, ctask); + spin_lock(&conn->session->lock); + __iscsi_ctask_cleanup(conn, ctask); + __iscsi_complete_pdu(conn, tcp_conn->in.hdr, NULL, 0); + spin_unlock(&conn->session->lock); } return rc; @@ -1010,71 +786,38 @@ done: static int iscsi_data_recv(struct iscsi_conn *conn) { - struct iscsi_session *session = conn->session; - int rc = 0; + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; + int rc = 0, opcode; - switch(conn->in.opcode) { + opcode = tcp_conn->in.hdr->opcode & ISCSI_OPCODE_MASK; + switch (opcode) { case ISCSI_OP_SCSI_DATA_IN: rc = iscsi_scsi_data_in(conn); break; - case ISCSI_OP_SCSI_CMD_RSP: { - /* - * SCSI Sense Data: - * copying the entire Data Segment. - */ - if (iscsi_tcp_copy(conn, conn->data, conn->in.datalen)) { - rc = -EAGAIN; - goto exit; - } - - /* - * check for sense - */ - conn->in.hdr = &conn->hdr; - conn->senselen = (conn->data[0] << 8) | conn->data[1]; - rc = iscsi_cmd_rsp(conn, conn->in.ctask); - if (!rc && conn->datadgst_en) - iscsi_recv_digest_update(conn, conn->data, - conn->in.datalen); - } - break; + case ISCSI_OP_SCSI_CMD_RSP: + spin_lock(&conn->session->lock); + __iscsi_ctask_cleanup(conn, tcp_conn->in.ctask); + spin_unlock(&conn->session->lock); case ISCSI_OP_TEXT_RSP: case ISCSI_OP_LOGIN_RSP: - case ISCSI_OP_NOOP_IN: { - struct iscsi_mgmt_task *mtask = NULL; - - if (conn->in.itt != ISCSI_RESERVED_TAG) - mtask = (struct iscsi_mgmt_task *) - session->mgmt_cmds[conn->in.itt - - ISCSI_MGMT_ITT_OFFSET]; - + case ISCSI_OP_NOOP_IN: + case ISCSI_OP_ASYNC_EVENT: + case ISCSI_OP_REJECT: /* * Collect data segment to the connection's data * placeholder */ - if (iscsi_tcp_copy(conn, conn->data, conn->in.datalen)) { + if (iscsi_tcp_copy(tcp_conn)) { rc = -EAGAIN; goto exit; } - rc = iscsi_recv_pdu(conn->cls_conn, conn->in.hdr, - conn->data, conn->in.datalen); - - if (!rc && conn->datadgst_en && - conn->in.opcode != ISCSI_OP_LOGIN_RSP) - iscsi_recv_digest_update(conn, conn->data, - conn->in.datalen); - - if (mtask && conn->login_mtask != mtask) { - spin_lock(&session->lock); - __kfifo_put(session->mgmtpool.queue, (void*)&mtask, - sizeof(void*)); - spin_unlock(&session->lock); - } - } - break; - case ISCSI_OP_ASYNC_EVENT: - case ISCSI_OP_REJECT: + rc = iscsi_complete_pdu(conn, tcp_conn->in.hdr, tcp_conn->data, + tcp_conn->in.datalen); + if (!rc && conn->datadgst_en && opcode != ISCSI_OP_LOGIN_RSP) + iscsi_recv_digest_update(tcp_conn, tcp_conn->data, + tcp_conn->in.datalen); + break; default: BUG_ON(1); } @@ -1095,6 +838,7 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, { int rc; struct iscsi_conn *conn = rd_desc->arg.data; + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; int processed; char pad[ISCSI_PAD_LEN]; struct scatterlist sg; @@ -1103,15 +847,15 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, * Save current SKB and its offset in the corresponding * connection context. */ - conn->in.copy = skb->len - offset; - conn->in.offset = offset; - conn->in.skb = skb; - conn->in.len = conn->in.copy; - BUG_ON(conn->in.copy <= 0); - debug_tcp("in %d bytes\n", conn->in.copy); + tcp_conn->in.copy = skb->len - offset; + tcp_conn->in.offset = offset; + tcp_conn->in.skb = skb; + tcp_conn->in.len = tcp_conn->in.copy; + BUG_ON(tcp_conn->in.copy <= 0); + debug_tcp("in %d bytes\n", tcp_conn->in.copy); more: - conn->in.copied = 0; + tcp_conn->in.copied = 0; rc = 0; if (unlikely(conn->suspend_rx)) { @@ -1119,9 +863,9 @@ more: return 0; } - if (conn->in_progress == IN_PROGRESS_WAIT_HEADER || - conn->in_progress == IN_PROGRESS_HEADER_GATHER) { - rc = iscsi_hdr_extract(conn); + if (tcp_conn->in_progress == IN_PROGRESS_WAIT_HEADER || + tcp_conn->in_progress == IN_PROGRESS_HEADER_GATHER) { + rc = iscsi_hdr_extract(tcp_conn); if (rc) { if (rc == -EAGAIN) goto nomore; @@ -1134,90 +878,94 @@ more: /* * Verify and process incoming PDU header. */ - rc = iscsi_hdr_recv(conn); - if (!rc && conn->in.datalen) { + rc = iscsi_tcp_hdr_recv(conn); + if (!rc && tcp_conn->in.datalen) { if (conn->datadgst_en) { - BUG_ON(!conn->data_rx_tfm); - crypto_digest_init(conn->data_rx_tfm); + BUG_ON(!tcp_conn->data_rx_tfm); + crypto_digest_init(tcp_conn->data_rx_tfm); } - conn->in_progress = IN_PROGRESS_DATA_RECV; + tcp_conn->in_progress = IN_PROGRESS_DATA_RECV; } else if (rc) { iscsi_conn_failure(conn, rc); return 0; } } - if (conn->in_progress == IN_PROGRESS_DDIGEST_RECV) { + if (tcp_conn->in_progress == IN_PROGRESS_DDIGEST_RECV) { uint32_t recv_digest; + debug_tcp("extra data_recv offset %d copy %d\n", - conn->in.offset, conn->in.copy); - skb_copy_bits(conn->in.skb, conn->in.offset, + tcp_conn->in.offset, tcp_conn->in.copy); + skb_copy_bits(tcp_conn->in.skb, tcp_conn->in.offset, &recv_digest, 4); - conn->in.offset += 4; - conn->in.copy -= 4; - if (recv_digest != conn->in.datadgst) { + tcp_conn->in.offset += 4; + tcp_conn->in.copy -= 4; + if (recv_digest != tcp_conn->in.datadgst) { debug_tcp("iscsi_tcp: data digest error!" "0x%x != 0x%x\n", recv_digest, - conn->in.datadgst); + tcp_conn->in.datadgst); iscsi_conn_failure(conn, ISCSI_ERR_DATA_DGST); return 0; } else { debug_tcp("iscsi_tcp: data digest match!" "0x%x == 0x%x\n", recv_digest, - conn->in.datadgst); - conn->in_progress = IN_PROGRESS_WAIT_HEADER; + tcp_conn->in.datadgst); + tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER; } } - if (conn->in_progress == IN_PROGRESS_DATA_RECV && conn->in.copy) { + if (tcp_conn->in_progress == IN_PROGRESS_DATA_RECV && + tcp_conn->in.copy) { debug_tcp("data_recv offset %d copy %d\n", - conn->in.offset, conn->in.copy); + tcp_conn->in.offset, tcp_conn->in.copy); rc = iscsi_data_recv(conn); if (rc) { if (rc == -EAGAIN) { - rd_desc->count = conn->in.datalen - - conn->in.ctask->data_count; + rd_desc->count = tcp_conn->in.datalen - + tcp_conn->in.ctask->data_count; goto again; } iscsi_conn_failure(conn, rc); return 0; } - conn->in.copy -= conn->in.padding; - conn->in.offset += conn->in.padding; + tcp_conn->in.copy -= tcp_conn->in.padding; + tcp_conn->in.offset += tcp_conn->in.padding; if (conn->datadgst_en) { - if (conn->in.padding) { - debug_tcp("padding -> %d\n", conn->in.padding); - memset(pad, 0, conn->in.padding); - sg_init_one(&sg, pad, conn->in.padding); - crypto_digest_update(conn->data_rx_tfm, &sg, 1); + if (tcp_conn->in.padding) { + debug_tcp("padding -> %d\n", + tcp_conn->in.padding); + memset(pad, 0, tcp_conn->in.padding); + sg_init_one(&sg, pad, tcp_conn->in.padding); + crypto_digest_update(tcp_conn->data_rx_tfm, + &sg, 1); } - crypto_digest_final(conn->data_rx_tfm, - (u8 *) & conn->in.datadgst); - debug_tcp("rx digest 0x%x\n", conn->in.datadgst); - conn->in_progress = IN_PROGRESS_DDIGEST_RECV; + crypto_digest_final(tcp_conn->data_rx_tfm, + (u8 *) & tcp_conn->in.datadgst); + debug_tcp("rx digest 0x%x\n", tcp_conn->in.datadgst); + tcp_conn->in_progress = IN_PROGRESS_DDIGEST_RECV; } else - conn->in_progress = IN_PROGRESS_WAIT_HEADER; + tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER; } debug_tcp("f, processed %d from out of %d padding %d\n", - conn->in.offset - offset, (int)len, conn->in.padding); - BUG_ON(conn->in.offset - offset > len); + tcp_conn->in.offset - offset, (int)len, tcp_conn->in.padding); + BUG_ON(tcp_conn->in.offset - offset > len); - if (conn->in.offset - offset != len) { + if (tcp_conn->in.offset - offset != len) { debug_tcp("continue to process %d bytes\n", - (int)len - (conn->in.offset - offset)); + (int)len - (tcp_conn->in.offset - offset)); goto more; } nomore: - processed = conn->in.offset - offset; + processed = tcp_conn->in.offset - offset; BUG_ON(processed == 0); return processed; again: - processed = conn->in.offset - offset; + processed = tcp_conn->in.offset - offset; debug_tcp("c, processed %d from out of %d rd_desc_cnt %d\n", processed, (int)len, (int)rd_desc->count); BUG_ON(processed == 0); @@ -1246,6 +994,7 @@ iscsi_tcp_data_ready(struct sock *sk, int flag) static void iscsi_tcp_state_change(struct sock *sk) { + struct iscsi_tcp_conn *tcp_conn; struct iscsi_conn *conn; struct iscsi_session *session; void (*old_state_change)(struct sock *); @@ -1262,7 +1011,8 @@ iscsi_tcp_state_change(struct sock *sk) iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); } - old_state_change = conn->old_state_change; + tcp_conn = conn->dd_data; + old_state_change = tcp_conn->old_state_change; read_unlock(&sk->sk_callback_lock); @@ -1277,23 +1027,26 @@ static void iscsi_write_space(struct sock *sk) { struct iscsi_conn *conn = (struct iscsi_conn*)sk->sk_user_data; - conn->old_write_space(sk); + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; + + tcp_conn->old_write_space(sk); debug_tcp("iscsi_write_space: cid %d\n", conn->id); - clear_bit(SUSPEND_BIT, &conn->suspend_tx); + clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); scsi_queue_work(conn->session->host, &conn->xmitwork); } static void iscsi_conn_set_callbacks(struct iscsi_conn *conn) { - struct sock *sk = conn->sock->sk; + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; + struct sock *sk = tcp_conn->sock->sk; /* assign new callbacks */ write_lock_bh(&sk->sk_callback_lock); sk->sk_user_data = conn; - conn->old_data_ready = sk->sk_data_ready; - conn->old_state_change = sk->sk_state_change; - conn->old_write_space = sk->sk_write_space; + tcp_conn->old_data_ready = sk->sk_data_ready; + tcp_conn->old_state_change = sk->sk_state_change; + tcp_conn->old_write_space = sk->sk_write_space; sk->sk_data_ready = iscsi_tcp_data_ready; sk->sk_state_change = iscsi_tcp_state_change; sk->sk_write_space = iscsi_write_space; @@ -1303,14 +1056,15 @@ iscsi_conn_set_callbacks(struct iscsi_conn *conn) static void iscsi_conn_restore_callbacks(struct iscsi_conn *conn) { - struct sock *sk = conn->sock->sk; + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; + struct sock *sk = tcp_conn->sock->sk; /* restore socket callbacks, see also: iscsi_conn_set_callbacks() */ write_lock_bh(&sk->sk_callback_lock); sk->sk_user_data = NULL; - sk->sk_data_ready = conn->old_data_ready; - sk->sk_state_change = conn->old_state_change; - sk->sk_write_space = conn->old_write_space; + sk->sk_data_ready = tcp_conn->old_data_ready; + sk->sk_state_change = tcp_conn->old_state_change; + sk->sk_write_space = tcp_conn->old_write_space; sk->sk_no_check = 0; write_unlock_bh(&sk->sk_callback_lock); } @@ -1325,7 +1079,8 @@ iscsi_conn_restore_callbacks(struct iscsi_conn *conn) static inline int iscsi_send(struct iscsi_conn *conn, struct iscsi_buf *buf, int size, int flags) { - struct socket *sk = conn->sock; + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; + struct socket *sk = tcp_conn->sock; int offset = buf->sg.offset + buf->sent; /* @@ -1339,7 +1094,8 @@ iscsi_send(struct iscsi_conn *conn, struct iscsi_buf *buf, int size, int flags) if (buf->use_sendmsg) return sock_no_sendpage(sk, buf->sg.page, offset, size, flags); else - return conn->sendpage(sk, buf->sg.page, offset, size, flags); + return tcp_conn->sendpage(sk, buf->sg.page, offset, size, + flags); } /** @@ -1354,6 +1110,7 @@ iscsi_send(struct iscsi_conn *conn, struct iscsi_buf *buf, int size, int flags) static inline int iscsi_sendhdr(struct iscsi_conn *conn, struct iscsi_buf *buf, int datalen) { + struct iscsi_tcp_conn *tcp_conn; int flags = 0; /* MSG_DONTWAIT; */ int res, size; @@ -1371,8 +1128,9 @@ iscsi_sendhdr(struct iscsi_conn *conn, struct iscsi_buf *buf, int datalen) return -EAGAIN; return 0; } else if (res == -EAGAIN) { - conn->sendpage_failures_cnt++; - set_bit(SUSPEND_BIT, &conn->suspend_tx); + tcp_conn = conn->dd_data; + tcp_conn->sendpage_failures_cnt++; + set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); } else if (res == -EPIPE) iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); @@ -1393,6 +1151,7 @@ static inline int iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf, int *count, int *sent) { + struct iscsi_tcp_conn *tcp_conn; int flags = 0; /* MSG_DONTWAIT; */ int res, size; @@ -1415,8 +1174,9 @@ iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf, return -EAGAIN; return 0; } else if (res == -EAGAIN) { - conn->sendpage_failures_cnt++; - set_bit(SUSPEND_BIT, &conn->suspend_tx); + tcp_conn = conn->dd_data; + tcp_conn->sendpage_failures_cnt++; + set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); } else if (res == -EPIPE) iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); @@ -1424,30 +1184,35 @@ iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf, } static inline void -iscsi_data_digest_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) +iscsi_data_digest_init(struct iscsi_tcp_conn *tcp_conn, + struct iscsi_cmd_task *ctask) { - BUG_ON(!conn->data_tx_tfm); - crypto_digest_init(conn->data_tx_tfm); - ctask->digest_count = 4; + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; + + BUG_ON(!tcp_conn->data_tx_tfm); + crypto_digest_init(tcp_conn->data_tx_tfm); + tcp_ctask->digest_count = 4; } static int iscsi_digest_final_send(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, struct iscsi_buf *buf, uint32_t *digest, int final) { + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; int rc = 0; int sent = 0; if (final) - crypto_digest_final(conn->data_tx_tfm, (u8*)digest); + crypto_digest_final(tcp_conn->data_tx_tfm, (u8*)digest); iscsi_buf_init_virt(buf, (char*)digest, 4); - rc = iscsi_sendpage(conn, buf, &ctask->digest_count, &sent); + rc = iscsi_sendpage(conn, buf, &tcp_ctask->digest_count, &sent); if (rc) { - ctask->datadigest = *digest; - ctask->xmstate |= XMSTATE_DATA_DIGEST; + tcp_ctask->datadigest = *digest; + tcp_ctask->xmstate |= XMSTATE_DATA_DIGEST; } else - ctask->digest_count = 4; + tcp_ctask->digest_count = 4; return rc; } @@ -1468,12 +1233,13 @@ static void iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, struct iscsi_r2t_info *r2t, int left) { + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; struct iscsi_data *hdr; struct iscsi_data_task *dtask; struct scsi_cmnd *sc = ctask->sc; int new_offset; - dtask = mempool_alloc(ctask->datapool, GFP_ATOMIC); + dtask = mempool_alloc(tcp_ctask->datapool, GFP_ATOMIC); BUG_ON(!dtask); INIT_LIST_HEAD(&dtask->item); hdr = &dtask->hdr; @@ -1482,8 +1248,8 @@ iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, hdr->datasn = cpu_to_be32(r2t->solicit_datasn); r2t->solicit_datasn++; hdr->opcode = ISCSI_OP_SCSI_DATA_OUT; - memcpy(hdr->lun, ctask->hdr.lun, sizeof(hdr->lun)); - hdr->itt = ctask->hdr.itt; + memcpy(hdr->lun, ctask->hdr->lun, sizeof(hdr->lun)); + hdr->itt = ctask->hdr->itt; hdr->exp_statsn = r2t->exp_statsn; new_offset = r2t->data_offset + r2t->sent; hdr->offset = cpu_to_be32(new_offset); @@ -1503,177 +1269,102 @@ iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, r2t->dtask = dtask; if (sc->use_sg && !iscsi_buf_left(&r2t->sendbuf)) { - BUG_ON(ctask->bad_sg == r2t->sg); + BUG_ON(tcp_ctask->bad_sg == r2t->sg); iscsi_buf_init_sg(&r2t->sendbuf, r2t->sg); r2t->sg += 1; } else - iscsi_buf_init_iov(&ctask->sendbuf, + iscsi_buf_init_iov(&tcp_ctask->sendbuf, (char*)sc->request_buffer + new_offset, r2t->data_count); - list_add(&dtask->item, &ctask->dataqueue); + list_add(&dtask->item, &tcp_ctask->dataqueue); } static void iscsi_unsolicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { - struct iscsi_data *hdr; + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; struct iscsi_data_task *dtask; - dtask = mempool_alloc(ctask->datapool, GFP_ATOMIC); + dtask = mempool_alloc(tcp_ctask->datapool, GFP_ATOMIC); BUG_ON(!dtask); INIT_LIST_HEAD(&dtask->item); - hdr = &dtask->hdr; - memset(hdr, 0, sizeof(struct iscsi_data)); - hdr->ttt = cpu_to_be32(ISCSI_RESERVED_TAG); - hdr->datasn = cpu_to_be32(ctask->unsol_datasn); - ctask->unsol_datasn++; - hdr->opcode = ISCSI_OP_SCSI_DATA_OUT; - memcpy(hdr->lun, ctask->hdr.lun, sizeof(hdr->lun)); - hdr->itt = ctask->hdr.itt; - hdr->exp_statsn = cpu_to_be32(conn->exp_statsn); - hdr->offset = cpu_to_be32(ctask->total_length - - ctask->r2t_data_count - - ctask->unsol_count); - if (ctask->unsol_count > conn->max_xmit_dlength) { - hton24(hdr->dlength, conn->max_xmit_dlength); - ctask->data_count = conn->max_xmit_dlength; - hdr->flags = 0; - } else { - hton24(hdr->dlength, ctask->unsol_count); - ctask->data_count = ctask->unsol_count; - hdr->flags = ISCSI_FLAG_CMD_FINAL; - } - iscsi_buf_init_virt(&ctask->headbuf, (char*)hdr, + iscsi_prep_unsolicit_data_pdu(ctask, &dtask->hdr, + tcp_ctask->r2t_data_count); + iscsi_buf_init_virt(&tcp_ctask->headbuf, (char*)&dtask->hdr, sizeof(struct iscsi_hdr)); - list_add(&dtask->item, &ctask->dataqueue); - - ctask->dtask = dtask; + list_add(&dtask->item, &tcp_ctask->dataqueue); + tcp_ctask->dtask = dtask; } /** - * iscsi_cmd_init - Initialize iSCSI SCSI_READ or SCSI_WRITE commands + * iscsi_tcp_cmd_init - Initialize iSCSI SCSI_READ or SCSI_WRITE commands * @conn: iscsi connection * @ctask: scsi command task * @sc: scsi command **/ static void -iscsi_cmd_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, - struct scsi_cmnd *sc) +iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask) { - struct iscsi_session *session = conn->session; - - BUG_ON(__kfifo_len(ctask->r2tqueue)); - - INIT_LIST_HEAD(&ctask->running); - ctask->sc = sc; - ctask->conn = conn; - ctask->hdr.opcode = ISCSI_OP_SCSI_CMD; - ctask->hdr.flags = ISCSI_ATTR_SIMPLE; - int_to_scsilun(sc->device->lun, (struct scsi_lun *)ctask->hdr.lun); - ctask->hdr.itt = ctask->itt | (conn->id << CID_SHIFT) | - (session->age << AGE_SHIFT); - ctask->hdr.data_length = cpu_to_be32(sc->request_bufflen); - ctask->hdr.cmdsn = cpu_to_be32(session->cmdsn); session->cmdsn++; - ctask->hdr.exp_statsn = cpu_to_be32(conn->exp_statsn); - memcpy(ctask->hdr.cdb, sc->cmnd, sc->cmd_len); - memset(&ctask->hdr.cdb[sc->cmd_len], 0, MAX_COMMAND_SIZE - sc->cmd_len); + struct scsi_cmnd *sc = ctask->sc; + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; - ctask->mtask = NULL; - ctask->sent = 0; - ctask->sg_count = 0; + BUG_ON(__kfifo_len(tcp_ctask->r2tqueue)); - ctask->total_length = sc->request_bufflen; + tcp_ctask->sent = 0; + tcp_ctask->sg_count = 0; if (sc->sc_data_direction == DMA_TO_DEVICE) { - ctask->exp_r2tsn = 0; - ctask->hdr.flags |= ISCSI_FLAG_CMD_WRITE; + tcp_ctask->xmstate = XMSTATE_W_HDR; + tcp_ctask->exp_r2tsn = 0; BUG_ON(ctask->total_length == 0); + if (sc->use_sg) { struct scatterlist *sg = sc->request_buffer; - iscsi_buf_init_sg(&ctask->sendbuf, - &sg[ctask->sg_count++]); - ctask->sg = sg; - ctask->bad_sg = sg + sc->use_sg; - } else { - iscsi_buf_init_iov(&ctask->sendbuf, sc->request_buffer, - sc->request_bufflen); - } + iscsi_buf_init_sg(&tcp_ctask->sendbuf, + &sg[tcp_ctask->sg_count++]); + tcp_ctask->sg = sg; + tcp_ctask->bad_sg = sg + sc->use_sg; + } else + iscsi_buf_init_iov(&tcp_ctask->sendbuf, + sc->request_buffer, + sc->request_bufflen); - /* - * Write counters: - * - * imm_count bytes to be sent right after - * SCSI PDU Header - * - * unsol_count bytes(as Data-Out) to be sent - * without R2T ack right after - * immediate data - * - * r2t_data_count bytes to be sent via R2T ack's - * - * pad_count bytes to be sent as zero-padding - */ - ctask->imm_count = 0; - ctask->unsol_count = 0; - ctask->unsol_datasn = 0; - ctask->xmstate = XMSTATE_W_HDR; - /* calculate write padding */ - ctask->pad_count = ctask->total_length & (ISCSI_PAD_LEN-1); - if (ctask->pad_count) { - ctask->pad_count = ISCSI_PAD_LEN - ctask->pad_count; + if (ctask->imm_count) + tcp_ctask->xmstate |= XMSTATE_IMM_DATA; + + tcp_ctask->pad_count = ctask->total_length & (ISCSI_PAD_LEN-1); + if (tcp_ctask->pad_count) { + tcp_ctask->pad_count = ISCSI_PAD_LEN - + tcp_ctask->pad_count; debug_scsi("write padding %d bytes\n", - ctask->pad_count); - ctask->xmstate |= XMSTATE_W_PAD; + tcp_ctask->pad_count); + tcp_ctask->xmstate |= XMSTATE_W_PAD; } - if (session->imm_data_en) { - if (ctask->total_length >= session->first_burst) - ctask->imm_count = min(session->first_burst, - conn->max_xmit_dlength); - else - ctask->imm_count = min(ctask->total_length, - conn->max_xmit_dlength); - hton24(ctask->hdr.dlength, ctask->imm_count); - ctask->xmstate |= XMSTATE_IMM_DATA; - } else - zero_data(ctask->hdr.dlength); - - if (!session->initial_r2t_en) - ctask->unsol_count = min(session->first_burst, - ctask->total_length) - ctask->imm_count; - if (!ctask->unsol_count) - /* No unsolicit Data-Out's */ - ctask->hdr.flags |= ISCSI_FLAG_CMD_FINAL; - else - ctask->xmstate |= XMSTATE_UNS_HDR | XMSTATE_UNS_INIT; - ctask->r2t_data_count = ctask->total_length - + if (ctask->unsol_count) + tcp_ctask->xmstate |= XMSTATE_UNS_HDR | + XMSTATE_UNS_INIT; + tcp_ctask->r2t_data_count = ctask->total_length - ctask->imm_count - ctask->unsol_count; debug_scsi("cmd [itt %x total %d imm %d imm_data %d " "r2t_data %d]\n", ctask->itt, ctask->total_length, ctask->imm_count, - ctask->unsol_count, ctask->r2t_data_count); - } else { - ctask->hdr.flags |= ISCSI_FLAG_CMD_FINAL; - if (sc->sc_data_direction == DMA_FROM_DEVICE) - ctask->hdr.flags |= ISCSI_FLAG_CMD_READ; - ctask->datasn = 0; - ctask->xmstate = XMSTATE_R_HDR; - zero_data(ctask->hdr.dlength); - } + ctask->unsol_count, tcp_ctask->r2t_data_count); + } else + tcp_ctask->xmstate = XMSTATE_R_HDR; - iscsi_buf_init_virt(&ctask->headbuf, (char*)&ctask->hdr, + iscsi_buf_init_virt(&tcp_ctask->headbuf, (char*)ctask->hdr, sizeof(struct iscsi_hdr)); - conn->scsicmd_pdus_cnt++; } /** - * iscsi_mtask_xmit - xmit management(immediate) task + * iscsi_tcp_mtask_xmit - xmit management(immediate) task * @conn: iscsi connection * @mtask: task management task * @@ -1687,70 +1378,87 @@ iscsi_cmd_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, * IN_PROGRESS_IMM_DATA - PDU Data xmit in progress **/ static int -iscsi_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) +iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) { + struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data; debug_scsi("mtask deq [cid %d state %x itt 0x%x]\n", - conn->id, mtask->xmstate, mtask->itt); + conn->id, tcp_mtask->xmstate, mtask->itt); - if (mtask->xmstate & XMSTATE_IMM_HDR) { - mtask->xmstate &= ~XMSTATE_IMM_HDR; + if (tcp_mtask->xmstate & XMSTATE_IMM_HDR) { + tcp_mtask->xmstate &= ~XMSTATE_IMM_HDR; if (mtask->data_count) - mtask->xmstate |= XMSTATE_IMM_DATA; + tcp_mtask->xmstate |= XMSTATE_IMM_DATA; if (conn->c_stage != ISCSI_CONN_INITIAL_STAGE && conn->stop_stage != STOP_CONN_RECOVER && conn->hdrdgst_en) - iscsi_hdr_digest(conn, &mtask->headbuf, - (u8*)mtask->hdrext); - if (iscsi_sendhdr(conn, &mtask->headbuf, mtask->data_count)) { - mtask->xmstate |= XMSTATE_IMM_HDR; + iscsi_hdr_digest(conn, &tcp_mtask->headbuf, + (u8*)tcp_mtask->hdrext); + if (iscsi_sendhdr(conn, &tcp_mtask->headbuf, + mtask->data_count)) { + tcp_mtask->xmstate |= XMSTATE_IMM_HDR; if (mtask->data_count) - mtask->xmstate &= ~XMSTATE_IMM_DATA; + tcp_mtask->xmstate &= ~XMSTATE_IMM_DATA; return -EAGAIN; } } - if (mtask->xmstate & XMSTATE_IMM_DATA) { + if (tcp_mtask->xmstate & XMSTATE_IMM_DATA) { BUG_ON(!mtask->data_count); - mtask->xmstate &= ~XMSTATE_IMM_DATA; + tcp_mtask->xmstate &= ~XMSTATE_IMM_DATA; /* FIXME: implement. * Virtual buffer could be spreaded across multiple pages... */ do { - if (iscsi_sendpage(conn, &mtask->sendbuf, - &mtask->data_count, &mtask->sent)) { - mtask->xmstate |= XMSTATE_IMM_DATA; + if (iscsi_sendpage(conn, &tcp_mtask->sendbuf, + &mtask->data_count, &tcp_mtask->sent)) { + tcp_mtask->xmstate |= XMSTATE_IMM_DATA; return -EAGAIN; } } while (mtask->data_count); } - BUG_ON(mtask->xmstate != XMSTATE_IDLE); + BUG_ON(tcp_mtask->xmstate != XMSTATE_IDLE); + if (mtask->hdr->itt == cpu_to_be32(ISCSI_RESERVED_TAG)) { + struct iscsi_session *session = conn->session; + + spin_lock_bh(&session->lock); + list_del(&conn->mtask->running); + __kfifo_put(session->mgmtpool.queue, (void*)&conn->mtask, + sizeof(void*)); + spin_unlock_bh(&session->lock); + } return 0; } static inline int -handle_xmstate_r_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) +handle_xmstate_r_hdr(struct iscsi_conn *conn, + struct iscsi_tcp_cmd_task *tcp_ctask) { - ctask->xmstate &= ~XMSTATE_R_HDR; + tcp_ctask->xmstate &= ~XMSTATE_R_HDR; if (conn->hdrdgst_en) - iscsi_hdr_digest(conn, &ctask->headbuf, (u8*)ctask->hdrext); - if (!iscsi_sendhdr(conn, &ctask->headbuf, 0)) { - BUG_ON(ctask->xmstate != XMSTATE_IDLE); + iscsi_hdr_digest(conn, &tcp_ctask->headbuf, + (u8*)tcp_ctask->hdrext); + if (!iscsi_sendhdr(conn, &tcp_ctask->headbuf, 0)) { + BUG_ON(tcp_ctask->xmstate != XMSTATE_IDLE); return 0; /* wait for Data-In */ } - ctask->xmstate |= XMSTATE_R_HDR; + tcp_ctask->xmstate |= XMSTATE_R_HDR; return -EAGAIN; } static inline int -handle_xmstate_w_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) +handle_xmstate_w_hdr(struct iscsi_conn *conn, + struct iscsi_cmd_task *ctask) { - ctask->xmstate &= ~XMSTATE_W_HDR; + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; + + tcp_ctask->xmstate &= ~XMSTATE_W_HDR; if (conn->hdrdgst_en) - iscsi_hdr_digest(conn, &ctask->headbuf, (u8*)ctask->hdrext); - if (iscsi_sendhdr(conn, &ctask->headbuf, ctask->imm_count)) { - ctask->xmstate |= XMSTATE_W_HDR; + iscsi_hdr_digest(conn, &tcp_ctask->headbuf, + (u8*)tcp_ctask->hdrext); + if (iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->imm_count)) { + tcp_ctask->xmstate |= XMSTATE_W_HDR; return -EAGAIN; } return 0; @@ -1760,13 +1468,15 @@ static inline int handle_xmstate_data_digest(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { - ctask->xmstate &= ~XMSTATE_DATA_DIGEST; - debug_tcp("resent data digest 0x%x\n", ctask->datadigest); - if (iscsi_digest_final_send(conn, ctask, &ctask->immbuf, - &ctask->datadigest, 0)) { - ctask->xmstate |= XMSTATE_DATA_DIGEST; + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; + + tcp_ctask->xmstate &= ~XMSTATE_DATA_DIGEST; + debug_tcp("resent data digest 0x%x\n", tcp_ctask->datadigest); + if (iscsi_digest_final_send(conn, ctask, &tcp_ctask->immbuf, + &tcp_ctask->datadigest, 0)) { + tcp_ctask->xmstate |= XMSTATE_DATA_DIGEST; debug_tcp("resent data digest 0x%x fail!\n", - ctask->datadigest); + tcp_ctask->datadigest); return -EAGAIN; } return 0; @@ -1775,44 +1485,47 @@ handle_xmstate_data_digest(struct iscsi_conn *conn, static inline int handle_xmstate_imm_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; + BUG_ON(!ctask->imm_count); - ctask->xmstate &= ~XMSTATE_IMM_DATA; + tcp_ctask->xmstate &= ~XMSTATE_IMM_DATA; if (conn->datadgst_en) { - iscsi_data_digest_init(conn, ctask); - ctask->immdigest = 0; + iscsi_data_digest_init(tcp_conn, ctask); + tcp_ctask->immdigest = 0; } for (;;) { - if (iscsi_sendpage(conn, &ctask->sendbuf, &ctask->imm_count, - &ctask->sent)) { - ctask->xmstate |= XMSTATE_IMM_DATA; + if (iscsi_sendpage(conn, &tcp_ctask->sendbuf, &ctask->imm_count, + &tcp_ctask->sent)) { + tcp_ctask->xmstate |= XMSTATE_IMM_DATA; if (conn->datadgst_en) { - crypto_digest_final(conn->data_tx_tfm, - (u8*)&ctask->immdigest); + crypto_digest_final(tcp_conn->data_tx_tfm, + (u8*)&tcp_ctask->immdigest); debug_tcp("tx imm sendpage fail 0x%x\n", - ctask->datadigest); + tcp_ctask->datadigest); } return -EAGAIN; } if (conn->datadgst_en) - crypto_digest_update(conn->data_tx_tfm, - &ctask->sendbuf.sg, 1); + crypto_digest_update(tcp_conn->data_tx_tfm, + &tcp_ctask->sendbuf.sg, 1); if (!ctask->imm_count) break; - iscsi_buf_init_sg(&ctask->sendbuf, - &ctask->sg[ctask->sg_count++]); + iscsi_buf_init_sg(&tcp_ctask->sendbuf, + &tcp_ctask->sg[tcp_ctask->sg_count++]); } - if (conn->datadgst_en && !(ctask->xmstate & XMSTATE_W_PAD)) { - if (iscsi_digest_final_send(conn, ctask, &ctask->immbuf, - &ctask->immdigest, 1)) { + if (conn->datadgst_en && !(tcp_ctask->xmstate & XMSTATE_W_PAD)) { + if (iscsi_digest_final_send(conn, ctask, &tcp_ctask->immbuf, + &tcp_ctask->immdigest, 1)) { debug_tcp("sending imm digest 0x%x fail!\n", - ctask->immdigest); + tcp_ctask->immdigest); return -EAGAIN; } - debug_tcp("sending imm digest 0x%x\n", ctask->immdigest); + debug_tcp("sending imm digest 0x%x\n", tcp_ctask->immdigest); } return 0; @@ -1821,52 +1534,55 @@ handle_xmstate_imm_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) static inline int handle_xmstate_uns_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; struct iscsi_data_task *dtask; - ctask->xmstate |= XMSTATE_UNS_DATA; - if (ctask->xmstate & XMSTATE_UNS_INIT) { + tcp_ctask->xmstate |= XMSTATE_UNS_DATA; + if (tcp_ctask->xmstate & XMSTATE_UNS_INIT) { iscsi_unsolicit_data_init(conn, ctask); - BUG_ON(!ctask->dtask); - dtask = ctask->dtask; + BUG_ON(!tcp_ctask->dtask); + dtask = tcp_ctask->dtask; if (conn->hdrdgst_en) - iscsi_hdr_digest(conn, &ctask->headbuf, + iscsi_hdr_digest(conn, &tcp_ctask->headbuf, (u8*)dtask->hdrext); - ctask->xmstate &= ~XMSTATE_UNS_INIT; + tcp_ctask->xmstate &= ~XMSTATE_UNS_INIT; } - if (iscsi_sendhdr(conn, &ctask->headbuf, ctask->data_count)) { - ctask->xmstate &= ~XMSTATE_UNS_DATA; - ctask->xmstate |= XMSTATE_UNS_HDR; + if (iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->data_count)) { + tcp_ctask->xmstate &= ~XMSTATE_UNS_DATA; + tcp_ctask->xmstate |= XMSTATE_UNS_HDR; return -EAGAIN; } debug_scsi("uns dout [itt 0x%x dlen %d sent %d]\n", - ctask->itt, ctask->unsol_count, ctask->sent); + ctask->itt, ctask->unsol_count, tcp_ctask->sent); return 0; } static inline int handle_xmstate_uns_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { - struct iscsi_data_task *dtask = ctask->dtask; + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; + struct iscsi_data_task *dtask = tcp_ctask->dtask; + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; BUG_ON(!ctask->data_count); - ctask->xmstate &= ~XMSTATE_UNS_DATA; + tcp_ctask->xmstate &= ~XMSTATE_UNS_DATA; if (conn->datadgst_en) { - iscsi_data_digest_init(conn, ctask); + iscsi_data_digest_init(tcp_conn, ctask); dtask->digest = 0; } for (;;) { - int start = ctask->sent; + int start = tcp_ctask->sent; - if (iscsi_sendpage(conn, &ctask->sendbuf, &ctask->data_count, - &ctask->sent)) { - ctask->unsol_count -= ctask->sent - start; - ctask->xmstate |= XMSTATE_UNS_DATA; + if (iscsi_sendpage(conn, &tcp_ctask->sendbuf, + &ctask->data_count, &tcp_ctask->sent)) { + ctask->unsol_count -= tcp_ctask->sent - start; + tcp_ctask->xmstate |= XMSTATE_UNS_DATA; /* will continue with this ctask later.. */ if (conn->datadgst_en) { - crypto_digest_final(conn->data_tx_tfm, + crypto_digest_final(tcp_conn->data_tx_tfm, (u8 *)&dtask->digest); debug_tcp("tx uns data fail 0x%x\n", dtask->digest); @@ -1874,21 +1590,21 @@ handle_xmstate_uns_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) return -EAGAIN; } - BUG_ON(ctask->sent > ctask->total_length); - ctask->unsol_count -= ctask->sent - start; + BUG_ON(tcp_ctask->sent > ctask->total_length); + ctask->unsol_count -= tcp_ctask->sent - start; /* * XXX:we may run here with un-initial sendbuf. * so pass it */ - if (conn->datadgst_en && ctask->sent - start > 0) - crypto_digest_update(conn->data_tx_tfm, - &ctask->sendbuf.sg, 1); + if (conn->datadgst_en && tcp_ctask->sent - start > 0) + crypto_digest_update(tcp_conn->data_tx_tfm, + &tcp_ctask->sendbuf.sg, 1); if (!ctask->data_count) break; - iscsi_buf_init_sg(&ctask->sendbuf, - &ctask->sg[ctask->sg_count++]); + iscsi_buf_init_sg(&tcp_ctask->sendbuf, + &tcp_ctask->sg[tcp_ctask->sg_count++]); } BUG_ON(ctask->unsol_count < 0); @@ -1908,11 +1624,11 @@ handle_xmstate_uns_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) debug_tcp("sending uns digest 0x%x, more uns\n", dtask->digest); } - ctask->xmstate |= XMSTATE_UNS_INIT; + tcp_ctask->xmstate |= XMSTATE_UNS_INIT; return 1; } - if (conn->datadgst_en && !(ctask->xmstate & XMSTATE_W_PAD)) { + if (conn->datadgst_en && !(tcp_ctask->xmstate & XMSTATE_W_PAD)) { if (iscsi_digest_final_send(conn, ctask, &dtask->digestbuf, &dtask->digest, 1)) { @@ -1930,15 +1646,17 @@ static inline int handle_xmstate_sol_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { struct iscsi_session *session = conn->session; - struct iscsi_r2t_info *r2t = ctask->r2t; + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; + struct iscsi_r2t_info *r2t = tcp_ctask->r2t; struct iscsi_data_task *dtask = r2t->dtask; int left; - ctask->xmstate &= ~XMSTATE_SOL_DATA; - ctask->dtask = dtask; + tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA; + tcp_ctask->dtask = dtask; if (conn->datadgst_en) { - iscsi_data_digest_init(conn, ctask); + iscsi_data_digest_init(tcp_conn, ctask); dtask->digest = 0; } solicit_again: @@ -1949,10 +1667,10 @@ solicit_again: goto data_out_done; if (iscsi_sendpage(conn, &r2t->sendbuf, &r2t->data_count, &r2t->sent)) { - ctask->xmstate |= XMSTATE_SOL_DATA; + tcp_ctask->xmstate |= XMSTATE_SOL_DATA; /* will continue with this ctask later.. */ if (conn->datadgst_en) { - crypto_digest_final(conn->data_tx_tfm, + crypto_digest_final(tcp_conn->data_tx_tfm, (u8 *)&dtask->digest); debug_tcp("r2t data send fail 0x%x\n", dtask->digest); } @@ -1961,12 +1679,13 @@ solicit_again: BUG_ON(r2t->data_count < 0); if (conn->datadgst_en) - crypto_digest_update(conn->data_tx_tfm, &r2t->sendbuf.sg, 1); + crypto_digest_update(tcp_conn->data_tx_tfm, &r2t->sendbuf.sg, + 1); if (r2t->data_count) { BUG_ON(ctask->sc->use_sg == 0); if (!iscsi_buf_left(&r2t->sendbuf)) { - BUG_ON(ctask->bad_sg == r2t->sg); + BUG_ON(tcp_ctask->bad_sg == r2t->sg); iscsi_buf_init_sg(&r2t->sendbuf, r2t->sg); r2t->sg += 1; } @@ -1993,8 +1712,8 @@ data_out_done: dtask->digest); } iscsi_solicit_data_cont(conn, ctask, r2t, left); - ctask->xmstate |= XMSTATE_SOL_DATA; - ctask->xmstate &= ~XMSTATE_SOL_HDR; + tcp_ctask->xmstate |= XMSTATE_SOL_DATA; + tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR; return 1; } @@ -2002,7 +1721,7 @@ data_out_done: * Done with this R2T. Check if there are more * outstanding R2Ts ready to be processed. */ - BUG_ON(ctask->r2t_data_count - r2t->data_length < 0); + BUG_ON(tcp_ctask->r2t_data_count - r2t->data_length < 0); if (conn->datadgst_en) { if (iscsi_digest_final_send(conn, ctask, &dtask->digestbuf, &dtask->digest, 1)) { @@ -2013,15 +1732,15 @@ data_out_done: debug_tcp("r2t done dout digest 0x%x\n", dtask->digest); } - ctask->r2t_data_count -= r2t->data_length; - ctask->r2t = NULL; + tcp_ctask->r2t_data_count -= r2t->data_length; + tcp_ctask->r2t = NULL; spin_lock_bh(&session->lock); - __kfifo_put(ctask->r2tpool.queue, (void*)&r2t, sizeof(void*)); + __kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t, sizeof(void*)); spin_unlock_bh(&session->lock); - if (__kfifo_get(ctask->r2tqueue, (void*)&r2t, sizeof(void*))) { - ctask->r2t = r2t; - ctask->xmstate |= XMSTATE_SOL_DATA; - ctask->xmstate &= ~XMSTATE_SOL_HDR; + if (__kfifo_get(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*))) { + tcp_ctask->r2t = r2t; + tcp_ctask->xmstate |= XMSTATE_SOL_DATA; + tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR; return 1; } @@ -2031,29 +1750,34 @@ data_out_done: static inline int handle_xmstate_w_pad(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { - struct iscsi_data_task *dtask = ctask->dtask; + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; + struct iscsi_data_task *dtask = tcp_ctask->dtask; int sent; - ctask->xmstate &= ~XMSTATE_W_PAD; - iscsi_buf_init_virt(&ctask->sendbuf, (char*)&ctask->pad, - ctask->pad_count); - if (iscsi_sendpage(conn, &ctask->sendbuf, &ctask->pad_count, &sent)) { - ctask->xmstate |= XMSTATE_W_PAD; + tcp_ctask->xmstate &= ~XMSTATE_W_PAD; + iscsi_buf_init_virt(&tcp_ctask->sendbuf, (char*)&tcp_ctask->pad, + tcp_ctask->pad_count); + if (iscsi_sendpage(conn, &tcp_ctask->sendbuf, &tcp_ctask->pad_count, + &sent)) { + tcp_ctask->xmstate |= XMSTATE_W_PAD; return -EAGAIN; } if (conn->datadgst_en) { - crypto_digest_update(conn->data_tx_tfm, &ctask->sendbuf.sg, 1); + crypto_digest_update(tcp_conn->data_tx_tfm, + &tcp_ctask->sendbuf.sg, 1); /* imm data? */ if (!dtask) { - if (iscsi_digest_final_send(conn, ctask, &ctask->immbuf, - &ctask->immdigest, 1)) { + if (iscsi_digest_final_send(conn, ctask, + &tcp_ctask->immbuf, + &tcp_ctask->immdigest, 1)) { debug_tcp("send padding digest 0x%x" - "fail!\n", ctask->immdigest); + "fail!\n", tcp_ctask->immdigest); return -EAGAIN; } debug_tcp("done with padding, digest 0x%x\n", - ctask->datadigest); + tcp_ctask->datadigest); } else { if (iscsi_digest_final_send(conn, ctask, &dtask->digestbuf, @@ -2071,12 +1795,13 @@ handle_xmstate_w_pad(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) } static int -iscsi_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) +iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; int rc = 0; debug_scsi("ctask deq [cid %d xmstate %x itt 0x%x]\n", - conn->id, ctask->xmstate, ctask->itt); + conn->id, tcp_ctask->xmstate, ctask->itt); /* * serialize with TMF AbortTask @@ -2084,40 +1809,40 @@ iscsi_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) if (ctask->mtask) return rc; - if (ctask->xmstate & XMSTATE_R_HDR) { - rc = handle_xmstate_r_hdr(conn, ctask); + if (tcp_ctask->xmstate & XMSTATE_R_HDR) { + rc = handle_xmstate_r_hdr(conn, tcp_ctask); return rc; } - if (ctask->xmstate & XMSTATE_W_HDR) { + if (tcp_ctask->xmstate & XMSTATE_W_HDR) { rc = handle_xmstate_w_hdr(conn, ctask); if (rc) return rc; } /* XXX: for data digest xmit recover */ - if (ctask->xmstate & XMSTATE_DATA_DIGEST) { + if (tcp_ctask->xmstate & XMSTATE_DATA_DIGEST) { rc = handle_xmstate_data_digest(conn, ctask); if (rc) return rc; } - if (ctask->xmstate & XMSTATE_IMM_DATA) { + if (tcp_ctask->xmstate & XMSTATE_IMM_DATA) { rc = handle_xmstate_imm_data(conn, ctask); if (rc) return rc; } - if (ctask->xmstate & XMSTATE_UNS_HDR) { + if (tcp_ctask->xmstate & XMSTATE_UNS_HDR) { BUG_ON(!ctask->unsol_count); - ctask->xmstate &= ~XMSTATE_UNS_HDR; + tcp_ctask->xmstate &= ~XMSTATE_UNS_HDR; unsolicit_head_again: rc = handle_xmstate_uns_hdr(conn, ctask); if (rc) return rc; } - if (ctask->xmstate & XMSTATE_UNS_DATA) { + if (tcp_ctask->xmstate & XMSTATE_UNS_DATA) { rc = handle_xmstate_uns_data(conn, ctask); if (rc == 1) goto unsolicit_head_again; @@ -2126,22 +1851,22 @@ unsolicit_head_again: goto done; } - if (ctask->xmstate & XMSTATE_SOL_HDR) { + if (tcp_ctask->xmstate & XMSTATE_SOL_HDR) { struct iscsi_r2t_info *r2t; - ctask->xmstate &= ~XMSTATE_SOL_HDR; - ctask->xmstate |= XMSTATE_SOL_DATA; - if (!ctask->r2t) - __kfifo_get(ctask->r2tqueue, (void*)&ctask->r2t, + tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR; + tcp_ctask->xmstate |= XMSTATE_SOL_DATA; + if (!tcp_ctask->r2t) + __kfifo_get(tcp_ctask->r2tqueue, (void*)&tcp_ctask->r2t, sizeof(void*)); solicit_head_again: - r2t = ctask->r2t; + r2t = tcp_ctask->r2t; if (conn->hdrdgst_en) iscsi_hdr_digest(conn, &r2t->headbuf, (u8*)r2t->dtask->hdrext); if (iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count)) { - ctask->xmstate &= ~XMSTATE_SOL_DATA; - ctask->xmstate |= XMSTATE_SOL_HDR; + tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA; + tcp_ctask->xmstate |= XMSTATE_SOL_HDR; return -EAGAIN; } @@ -2150,7 +1875,7 @@ solicit_head_again: r2t->sent); } - if (ctask->xmstate & XMSTATE_SOL_DATA) { + if (tcp_ctask->xmstate & XMSTATE_SOL_DATA) { rc = handle_xmstate_sol_data(conn, ctask); if (rc == 1) goto solicit_head_again; @@ -2163,529 +1888,116 @@ done: * Last thing to check is whether we need to send write * padding. Note that we check for xmstate equality, not just the bit. */ - if (ctask->xmstate == XMSTATE_W_PAD) + if (tcp_ctask->xmstate == XMSTATE_W_PAD) rc = handle_xmstate_w_pad(conn, ctask); return rc; } -/** - * iscsi_data_xmit - xmit any command into the scheduled connection - * @conn: iscsi connection - * - * Notes: - * The function can return -EAGAIN in which case the caller must - * re-schedule it again later or recover. '0' return code means - * successful xmit. - **/ -static int -iscsi_data_xmit(struct iscsi_conn *conn) +static struct iscsi_cls_conn * +iscsi_tcp_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx) { - if (unlikely(conn->suspend_tx)) { - debug_tcp("conn %d Tx suspended!\n", conn->id); - return 0; - } + struct iscsi_conn *conn; + struct iscsi_cls_conn *cls_conn; + struct iscsi_tcp_conn *tcp_conn; + cls_conn = iscsi_conn_setup(cls_session, conn_idx); + if (!cls_conn) + return NULL; + conn = cls_conn->dd_data; /* - * Transmit in the following order: - * - * 1) un-finished xmit (ctask or mtask) - * 2) immediate control PDUs - * 3) write data - * 4) SCSI commands - * 5) non-immediate control PDUs - * - * No need to lock around __kfifo_get as long as - * there's one producer and one consumer. + * due to strange issues with iser these are not set + * in iscsi_conn_setup */ + conn->max_recv_dlength = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH; - BUG_ON(conn->ctask && conn->mtask); - - if (conn->ctask) { - if (iscsi_ctask_xmit(conn, conn->ctask)) - goto again; - /* done with this in-progress ctask */ - conn->ctask = NULL; - } - if (conn->mtask) { - if (iscsi_mtask_xmit(conn, conn->mtask)) - goto again; - /* done with this in-progress mtask */ - conn->mtask = NULL; - } - - /* process immediate first */ - if (unlikely(__kfifo_len(conn->immqueue))) { - struct iscsi_session *session = conn->session; - while (__kfifo_get(conn->immqueue, (void*)&conn->mtask, - sizeof(void*))) { - if (iscsi_mtask_xmit(conn, conn->mtask)) - goto again; - - if (conn->mtask->hdr.itt == - cpu_to_be32(ISCSI_RESERVED_TAG)) { - spin_lock_bh(&session->lock); - __kfifo_put(session->mgmtpool.queue, - (void*)&conn->mtask, sizeof(void*)); - spin_unlock_bh(&session->lock); - } - } - /* done with this mtask */ - conn->mtask = NULL; - } - - /* process write queue */ - while (__kfifo_get(conn->writequeue, (void*)&conn->ctask, - sizeof(void*))) { - if (iscsi_ctask_xmit(conn, conn->ctask)) - goto again; - } - - /* process command queue */ - while (__kfifo_get(conn->xmitqueue, (void*)&conn->ctask, - sizeof(void*))) { - list_add_tail(&conn->ctask->running, &conn->run_list); - if (iscsi_ctask_xmit(conn, conn->ctask)) - goto again; - } - /* done with this ctask */ - conn->ctask = NULL; - - /* process the rest control plane PDUs, if any */ - if (unlikely(__kfifo_len(conn->mgmtqueue))) { - struct iscsi_session *session = conn->session; - - while (__kfifo_get(conn->mgmtqueue, (void*)&conn->mtask, - sizeof(void*))) { - if (iscsi_mtask_xmit(conn, conn->mtask)) - goto again; + tcp_conn = kzalloc(sizeof(*tcp_conn), GFP_KERNEL); + if (!tcp_conn) + goto tcp_conn_alloc_fail; - if (conn->mtask->hdr.itt == - cpu_to_be32(ISCSI_RESERVED_TAG)) { - spin_lock_bh(&session->lock); - __kfifo_put(session->mgmtpool.queue, - (void*)&conn->mtask, - sizeof(void*)); - spin_unlock_bh(&session->lock); - } - } - /* done with this mtask */ - conn->mtask = NULL; - } + conn->dd_data = tcp_conn; + tcp_conn->iscsi_conn = conn; + tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER; + /* initial operational parameters */ + tcp_conn->hdr_size = sizeof(struct iscsi_hdr); + tcp_conn->data_size = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH; - return 0; + /* allocate initial PDU receive place holder */ + if (tcp_conn->data_size <= PAGE_SIZE) + tcp_conn->data = kmalloc(tcp_conn->data_size, GFP_KERNEL); + else + tcp_conn->data = (void*)__get_free_pages(GFP_KERNEL, + get_order(tcp_conn->data_size)); + if (!tcp_conn->data) + goto max_recv_dlenght_alloc_fail; -again: - if (unlikely(conn->suspend_tx)) - return 0; + return cls_conn; - return -EAGAIN; +max_recv_dlenght_alloc_fail: + kfree(tcp_conn); +tcp_conn_alloc_fail: + iscsi_conn_teardown(cls_conn); + return NULL; } static void -iscsi_xmitworker(void *data) +iscsi_tcp_conn_destroy(struct iscsi_cls_conn *cls_conn) { - struct iscsi_conn *conn = data; - - /* - * serialize Xmit worker on a per-connection basis. - */ - mutex_lock(&conn->xmitmutex); - if (iscsi_data_xmit(conn)) - scsi_queue_work(conn->session->host, &conn->xmitwork); - mutex_unlock(&conn->xmitmutex); -} + struct iscsi_conn *conn = cls_conn->dd_data; + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; + int digest = 0; -enum { - FAILURE_BAD_HOST = 1, - FAILURE_SESSION_FAILED, - FAILURE_SESSION_FREED, - FAILURE_WINDOW_CLOSED, - FAILURE_SESSION_TERMINATE, - FAILURE_SESSION_RECOVERY_TIMEOUT, -}; + if (conn->hdrdgst_en || conn->datadgst_en) + digest = 1; -static int -iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) -{ - struct Scsi_Host *host; - int reason = 0; - struct iscsi_session *session; - struct iscsi_conn *conn = NULL; - struct iscsi_cmd_task *ctask = NULL; + iscsi_conn_teardown(cls_conn); - sc->scsi_done = done; - sc->result = 0; + /* now free tcp_conn */ + if (digest) { + if (tcp_conn->tx_tfm) + crypto_free_tfm(tcp_conn->tx_tfm); + if (tcp_conn->rx_tfm) + crypto_free_tfm(tcp_conn->rx_tfm); + if (tcp_conn->data_tx_tfm) + crypto_free_tfm(tcp_conn->data_tx_tfm); + if (tcp_conn->data_rx_tfm) + crypto_free_tfm(tcp_conn->data_rx_tfm); + } - host = sc->device->host; - session = iscsi_hostdata(host->hostdata); + /* free conn->data, size = MaxRecvDataSegmentLength */ + if (tcp_conn->data_size <= PAGE_SIZE) + kfree(tcp_conn->data); + else + free_pages((unsigned long)tcp_conn->data, + get_order(tcp_conn->data_size)); + kfree(tcp_conn); +} - spin_lock(&session->lock); +static int +iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session, + struct iscsi_cls_conn *cls_conn, uint32_t transport_fd, + int is_leading) +{ + struct iscsi_conn *conn = cls_conn->dd_data; + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; + struct sock *sk; + struct socket *sock; + int err; - if (session->state != ISCSI_STATE_LOGGED_IN) { - if (session->recovery_failed) { - reason = FAILURE_SESSION_RECOVERY_TIMEOUT; - goto fault; - } else if (session->state == ISCSI_STATE_FAILED) { - reason = FAILURE_SESSION_FAILED; - goto reject; - } else if (session->state == ISCSI_STATE_TERMINATE) { - reason = FAILURE_SESSION_TERMINATE; - goto fault; - } - reason = FAILURE_SESSION_FREED; - goto fault; + /* lookup for existing socket */ + sock = sockfd_lookup(transport_fd, &err); + if (!sock) { + printk(KERN_ERR "iscsi_tcp: sockfd_lookup failed %d\n", err); + return -EEXIST; } - /* - * Check for iSCSI window and take care of CmdSN wrap-around - */ - if ((int)(session->max_cmdsn - session->cmdsn) < 0) { - reason = FAILURE_WINDOW_CLOSED; - goto reject; - } + err = iscsi_conn_bind(cls_session, cls_conn, is_leading); + if (err) + return err; - conn = session->leadconn; - - __kfifo_get(session->cmdpool.queue, (void*)&ctask, sizeof(void*)); - BUG_ON(ctask->sc); - - sc->SCp.phase = session->age; - sc->SCp.ptr = (char*)ctask; - iscsi_cmd_init(conn, ctask, sc); - - __kfifo_put(conn->xmitqueue, (void*)&ctask, sizeof(void*)); - debug_scsi( - "ctask enq [%s cid %d sc %lx itt 0x%x len %d cmdsn %d win %d]\n", - sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read", - conn->id, (long)sc, ctask->itt, sc->request_bufflen, - session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1); - spin_unlock(&session->lock); - - scsi_queue_work(host, &conn->xmitwork); - return 0; - -reject: - spin_unlock(&session->lock); - debug_scsi("cmd 0x%x rejected (%d)\n", sc->cmnd[0], reason); - return SCSI_MLQUEUE_HOST_BUSY; - -fault: - spin_unlock(&session->lock); - printk(KERN_ERR "iscsi_tcp: cmd 0x%x is not queued (%d)\n", - sc->cmnd[0], reason); - sc->result = (DID_NO_CONNECT << 16); - sc->resid = sc->request_bufflen; - sc->scsi_done(sc); - return 0; -} - -static int -iscsi_change_queue_depth(struct scsi_device *sdev, int depth) -{ - if (depth > ISCSI_MAX_CMD_PER_LUN) - depth = ISCSI_MAX_CMD_PER_LUN; - scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth); - return sdev->queue_depth; -} - -static int -iscsi_pool_init(struct iscsi_queue *q, int max, void ***items, int item_size) -{ - int i; - - *items = kmalloc(max * sizeof(void*), GFP_KERNEL); - if (*items == NULL) - return -ENOMEM; - - q->max = max; - q->pool = kmalloc(max * sizeof(void*), GFP_KERNEL); - if (q->pool == NULL) { - kfree(*items); - return -ENOMEM; - } - - q->queue = kfifo_init((void*)q->pool, max * sizeof(void*), - GFP_KERNEL, NULL); - if (q->queue == ERR_PTR(-ENOMEM)) { - kfree(q->pool); - kfree(*items); - return -ENOMEM; - } - - for (i = 0; i < max; i++) { - q->pool[i] = kmalloc(item_size, GFP_KERNEL); - if (q->pool[i] == NULL) { - int j; - - for (j = 0; j < i; j++) - kfree(q->pool[j]); - - kfifo_free(q->queue); - kfree(q->pool); - kfree(*items); - return -ENOMEM; - } - memset(q->pool[i], 0, item_size); - (*items)[i] = q->pool[i]; - __kfifo_put(q->queue, (void*)&q->pool[i], sizeof(void*)); - } - return 0; -} - -static void -iscsi_pool_free(struct iscsi_queue *q, void **items) -{ - int i; - - for (i = 0; i < q->max; i++) - kfree(items[i]); - kfree(q->pool); - kfree(items); -} - -static struct iscsi_cls_conn * -iscsi_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx) -{ - struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); - struct iscsi_session *session = iscsi_hostdata(shost->hostdata); - struct iscsi_conn *conn; - struct iscsi_cls_conn *cls_conn; - - cls_conn = iscsi_create_conn(cls_session, conn_idx); - if (!cls_conn) - return NULL; - conn = cls_conn->dd_data; - memset(conn, 0, sizeof(*conn)); - - conn->cls_conn = cls_conn; - conn->c_stage = ISCSI_CONN_INITIAL_STAGE; - conn->in_progress = IN_PROGRESS_WAIT_HEADER; - conn->id = conn_idx; - conn->exp_statsn = 0; - conn->tmabort_state = TMABORT_INITIAL; - INIT_LIST_HEAD(&conn->run_list); - - /* initial operational parameters */ - conn->hdr_size = sizeof(struct iscsi_hdr); - conn->data_size = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH; - conn->max_recv_dlength = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH; - - /* initialize general xmit PDU commands queue */ - conn->xmitqueue = kfifo_alloc(session->cmds_max * sizeof(void*), - GFP_KERNEL, NULL); - if (conn->xmitqueue == ERR_PTR(-ENOMEM)) - goto xmitqueue_alloc_fail; - - /* initialize write response PDU commands queue */ - conn->writequeue = kfifo_alloc(session->cmds_max * sizeof(void*), - GFP_KERNEL, NULL); - if (conn->writequeue == ERR_PTR(-ENOMEM)) - goto writequeue_alloc_fail; - - /* initialize general immediate & non-immediate PDU commands queue */ - conn->immqueue = kfifo_alloc(session->mgmtpool_max * sizeof(void*), - GFP_KERNEL, NULL); - if (conn->immqueue == ERR_PTR(-ENOMEM)) - goto immqueue_alloc_fail; - - conn->mgmtqueue = kfifo_alloc(session->mgmtpool_max * sizeof(void*), - GFP_KERNEL, NULL); - if (conn->mgmtqueue == ERR_PTR(-ENOMEM)) - goto mgmtqueue_alloc_fail; - - INIT_WORK(&conn->xmitwork, iscsi_xmitworker, conn); - - /* allocate login_mtask used for the login/text sequences */ - spin_lock_bh(&session->lock); - if (!__kfifo_get(session->mgmtpool.queue, - (void*)&conn->login_mtask, - sizeof(void*))) { - spin_unlock_bh(&session->lock); - goto login_mtask_alloc_fail; - } - spin_unlock_bh(&session->lock); - - /* allocate initial PDU receive place holder */ - if (conn->data_size <= PAGE_SIZE) - conn->data = kmalloc(conn->data_size, GFP_KERNEL); - else - conn->data = (void*)__get_free_pages(GFP_KERNEL, - get_order(conn->data_size)); - if (!conn->data) - goto max_recv_dlenght_alloc_fail; - - init_timer(&conn->tmabort_timer); - mutex_init(&conn->xmitmutex); - init_waitqueue_head(&conn->ehwait); - - return cls_conn; - -max_recv_dlenght_alloc_fail: - spin_lock_bh(&session->lock); - __kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask, - sizeof(void*)); - spin_unlock_bh(&session->lock); -login_mtask_alloc_fail: - kfifo_free(conn->mgmtqueue); -mgmtqueue_alloc_fail: - kfifo_free(conn->immqueue); -immqueue_alloc_fail: - kfifo_free(conn->writequeue); -writequeue_alloc_fail: - kfifo_free(conn->xmitqueue); -xmitqueue_alloc_fail: - iscsi_destroy_conn(cls_conn); - return NULL; -} - -static void -iscsi_conn_destroy(struct iscsi_cls_conn *cls_conn) -{ - struct iscsi_conn *conn = cls_conn->dd_data; - struct iscsi_session *session = conn->session; - unsigned long flags; - - mutex_lock(&conn->xmitmutex); - set_bit(SUSPEND_BIT, &conn->suspend_tx); - if (conn->c_stage == ISCSI_CONN_INITIAL_STAGE && conn->sock) { - struct sock *sk = conn->sock->sk; - - /* - * conn_start() has never been called! - * need to cleanup the socket. - */ - write_lock_bh(&sk->sk_callback_lock); - set_bit(SUSPEND_BIT, &conn->suspend_rx); - write_unlock_bh(&sk->sk_callback_lock); - - sock_hold(conn->sock->sk); - iscsi_conn_restore_callbacks(conn); - sock_put(conn->sock->sk); - sock_release(conn->sock); - conn->sock = NULL; - } - - spin_lock_bh(&session->lock); - conn->c_stage = ISCSI_CONN_CLEANUP_WAIT; - if (session->leadconn == conn) { - /* - * leading connection? then give up on recovery. - */ - session->state = ISCSI_STATE_TERMINATE; - wake_up(&conn->ehwait); - } - spin_unlock_bh(&session->lock); - - mutex_unlock(&conn->xmitmutex); - - /* - * Block until all in-progress commands for this connection - * time out or fail. - */ - for (;;) { - spin_lock_irqsave(session->host->host_lock, flags); - if (!session->host->host_busy) { /* OK for ERL == 0 */ - spin_unlock_irqrestore(session->host->host_lock, flags); - break; - } - spin_unlock_irqrestore(session->host->host_lock, flags); - msleep_interruptible(500); - printk("conn_destroy(): host_busy %d host_failed %d\n", - session->host->host_busy, session->host->host_failed); - /* - * force eh_abort() to unblock - */ - wake_up(&conn->ehwait); - } - - /* now free crypto */ - if (conn->hdrdgst_en || conn->datadgst_en) { - if (conn->tx_tfm) - crypto_free_tfm(conn->tx_tfm); - if (conn->rx_tfm) - crypto_free_tfm(conn->rx_tfm); - if (conn->data_tx_tfm) - crypto_free_tfm(conn->data_tx_tfm); - if (conn->data_rx_tfm) - crypto_free_tfm(conn->data_rx_tfm); - } - - /* free conn->data, size = MaxRecvDataSegmentLength */ - if (conn->data_size <= PAGE_SIZE) - kfree(conn->data); - else - free_pages((unsigned long)conn->data, - get_order(conn->data_size)); - - spin_lock_bh(&session->lock); - __kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask, - sizeof(void*)); - list_del(&conn->item); - if (list_empty(&session->connections)) - session->leadconn = NULL; - if (session->leadconn && session->leadconn == conn) - session->leadconn = container_of(session->connections.next, - struct iscsi_conn, item); - - if (session->leadconn == NULL) - /* none connections exits.. reset sequencing */ - session->cmdsn = session->max_cmdsn = session->exp_cmdsn = 1; - spin_unlock_bh(&session->lock); - - kfifo_free(conn->xmitqueue); - kfifo_free(conn->writequeue); - kfifo_free(conn->immqueue); - kfifo_free(conn->mgmtqueue); - - iscsi_destroy_conn(cls_conn); -} - -static int -iscsi_conn_bind(struct iscsi_cls_session *cls_session, - struct iscsi_cls_conn *cls_conn, uint32_t transport_fd, - int is_leading) -{ - struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); - struct iscsi_session *session = iscsi_hostdata(shost->hostdata); - struct iscsi_conn *tmp = ERR_PTR(-EEXIST), *conn = cls_conn->dd_data; - struct sock *sk; - struct socket *sock; - int err; - - /* lookup for existing socket */ - sock = sockfd_lookup(transport_fd, &err); - if (!sock) { - printk(KERN_ERR "iscsi_tcp: sockfd_lookup failed %d\n", err); - return -EEXIST; - } - - /* lookup for existing connection */ - spin_lock_bh(&session->lock); - list_for_each_entry(tmp, &session->connections, item) { - if (tmp == conn) { - if (conn->c_stage != ISCSI_CONN_STOPPED || - conn->stop_stage == STOP_CONN_TERM) { - printk(KERN_ERR "iscsi_tcp: can't bind " - "non-stopped connection (%d:%d)\n", - conn->c_stage, conn->stop_stage); - spin_unlock_bh(&session->lock); - return -EIO; - } - break; - } - } - if (tmp != conn) { - /* bind new iSCSI connection to session */ - conn->session = session; - - list_add(&conn->item, &session->connections); - } - spin_unlock_bh(&session->lock); - - if (conn->stop_stage != STOP_CONN_SUSPEND) { - /* bind iSCSI connection and socket */ - conn->sock = sock; + if (conn->stop_stage != STOP_CONN_SUSPEND) { + /* bind iSCSI connection and socket */ + tcp_conn->sock = sock; /* setup Socket parameters */ sk = sock->sk; @@ -2699,608 +2011,78 @@ iscsi_conn_bind(struct iscsi_cls_session *cls_session, * Intercept TCP callbacks for sendfile like receive * processing. */ + conn->recv_lock = &sk->sk_callback_lock; iscsi_conn_set_callbacks(conn); - - conn->sendpage = conn->sock->ops->sendpage; - + tcp_conn->sendpage = tcp_conn->sock->ops->sendpage; /* * set receive state machine into initial state */ - conn->in_progress = IN_PROGRESS_WAIT_HEADER; + tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER; } - if (is_leading) - session->leadconn = conn; - - /* - * Unblock xmitworker(), Login Phase will pass through. - */ - clear_bit(SUSPEND_BIT, &conn->suspend_rx); - clear_bit(SUSPEND_BIT, &conn->suspend_tx); - return 0; } static void -iscsi_session_recovery_timedout(struct iscsi_cls_session *csession) -{ - struct Scsi_Host *shost = iscsi_session_to_shost(csession); - struct iscsi_session *session = iscsi_hostdata(shost->hostdata); - struct iscsi_conn *conn = session->leadconn; - - spin_lock_bh(&session->lock); - if (session->state != ISCSI_STATE_LOGGED_IN) { - session->recovery_failed = 1; - if (conn) - wake_up(&conn->ehwait); - } - spin_unlock_bh(&session->lock); -} - -static int -iscsi_conn_start(struct iscsi_cls_conn *cls_conn) -{ - struct iscsi_conn *conn = cls_conn->dd_data; - struct iscsi_session *session = conn->session; - struct sock *sk; - - /* FF phase warming up... */ - - if (session == NULL) { - printk(KERN_ERR "iscsi_tcp: can't start unbound connection\n"); - return -EPERM; - } - - sk = conn->sock->sk; - write_lock_bh(&sk->sk_callback_lock); - spin_lock_bh(&session->lock); - conn->c_stage = ISCSI_CONN_STARTED; - session->state = ISCSI_STATE_LOGGED_IN; - - switch(conn->stop_stage) { - case STOP_CONN_RECOVER: - /* - * unblock eh_abort() if it is blocked. re-try all - * commands after successful recovery - */ - session->conn_cnt++; - conn->stop_stage = 0; - conn->tmabort_state = TMABORT_INITIAL; - session->age++; - session->recovery_failed = 0; - spin_unlock_bh(&session->lock); - write_unlock_bh(&sk->sk_callback_lock); - - iscsi_unblock_session(session_to_cls(session)); - wake_up(&conn->ehwait); - return 0; - case STOP_CONN_TERM: - session->conn_cnt++; - conn->stop_stage = 0; - break; - case STOP_CONN_SUSPEND: - conn->stop_stage = 0; - clear_bit(SUSPEND_BIT, &conn->suspend_rx); - clear_bit(SUSPEND_BIT, &conn->suspend_tx); - break; - default: - break; - } - spin_unlock_bh(&session->lock); - write_unlock_bh(&sk->sk_callback_lock); - - return 0; -} - -static int -iscsi_ctask_mtask_cleanup(struct iscsi_cmd_task *ctask) -{ - struct iscsi_conn *conn = ctask->conn; - struct iscsi_session *session = conn->session; - struct iscsi_mgmt_task *mtask; - - if (!ctask->mtask) - return -EINVAL; - - while (__kfifo_get(conn->immqueue, (void*)&mtask, sizeof(void*))) { - if (mtask == ctask->mtask) - break; - __kfifo_put(conn->immqueue, (void*)&mtask, sizeof(void*)); - } - - __kfifo_put(session->mgmtpool.queue, (void*)&ctask->mtask, - sizeof(void*)); - ctask->mtask = NULL; - return 0; -} - -static void -fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, int err) +iscsi_tcp_cleanup_ctask(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; struct iscsi_r2t_info *r2t; - struct scsi_cmnd *sc; /* flush ctask's r2t queues */ - while (__kfifo_get(ctask->r2tqueue, (void*)&r2t, sizeof(void*))) - __kfifo_put(ctask->r2tpool.queue, (void*)&r2t, sizeof(void*)); - - iscsi_ctask_mtask_cleanup(ctask); - - sc = ctask->sc; - if (!sc) - return; - - sc->result = err; - sc->resid = sc->request_bufflen; - - __iscsi_ctask_cleanup(conn, ctask); -} - -/* Fail commands. Mutex and session lock held */ -static void -fail_all_commands(struct iscsi_session *session, struct iscsi_conn *conn) -{ - struct iscsi_cmd_task *ctask, *tmp; - - /* flush pending */ - while (__kfifo_get(conn->xmitqueue, (void*)&ctask, sizeof(void*))) { - debug_scsi("failing pending sc %p itt 0x%x\n", ctask->sc, - ctask->itt); - fail_command(conn, ctask, DID_BUS_BUSY << 16); - } - - /* fail running */ - list_for_each_entry_safe(ctask, tmp, &conn->run_list, running) { - debug_scsi("failing in progress sc %p itt 0x%x\n", - ctask->sc, ctask->itt); - fail_command(conn, ctask, DID_BUS_BUSY << 16); - } - - conn->ctask = NULL; -} - -static void -flush_control_queues(struct iscsi_session *session, struct iscsi_conn *conn) -{ - struct iscsi_mgmt_task *mtask; - - /* TODO: handle running pdus */ - while (__kfifo_get(conn->immqueue, (void*)&mtask, sizeof(void*)) || - __kfifo_get(conn->mgmtqueue, (void*)&mtask, sizeof(void*))) { - if (mtask == conn->login_mtask) - continue; - __kfifo_put(session->mgmtpool.queue, (void*)&mtask, + while (__kfifo_get(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*))) + __kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t, sizeof(void*)); - } - if (conn->mtask && conn->mtask != conn->login_mtask) - __kfifo_put(session->mgmtpool.queue, (void*)&conn->mtask, - sizeof(void*)); - conn->mtask = NULL; + __iscsi_ctask_cleanup(conn, ctask); } static void -iscsi_suspend_conn_rx(struct iscsi_conn *conn) +iscsi_tcp_suspend_conn_rx(struct iscsi_conn *conn) { + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; struct sock *sk; - BUG_ON(!conn->sock); - sk = conn->sock->sk; + if (!tcp_conn->sock) + return; + + sk = tcp_conn->sock->sk; write_lock_bh(&sk->sk_callback_lock); - set_bit(SUSPEND_BIT, &conn->suspend_rx); + set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx); write_unlock_bh(&sk->sk_callback_lock); } static void -iscsi_start_session_recovery(struct iscsi_session *session, - struct iscsi_conn *conn, int flag) +iscsi_tcp_terminate_conn(struct iscsi_conn *conn) { - spin_lock_bh(&session->lock); - if (conn->stop_stage == STOP_CONN_RECOVER || - conn->stop_stage == STOP_CONN_TERM) { - spin_unlock_bh(&session->lock); - return; - } - conn->stop_stage = flag; - spin_unlock_bh(&session->lock); - - iscsi_suspend_conn_rx(conn); - - mutex_lock(&conn->xmitmutex); - spin_lock_bh(&session->lock); - conn->c_stage = ISCSI_CONN_STOPPED; - set_bit(SUSPEND_BIT, &conn->suspend_tx); + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; - session->conn_cnt--; - if (session->conn_cnt == 0 || session->leadconn == conn) - session->state = ISCSI_STATE_FAILED; - - spin_unlock_bh(&session->lock); + if (!tcp_conn->sock) + return; - /* - * Socket must go now. - */ - sock_hold(conn->sock->sk); + sock_hold(tcp_conn->sock->sk); iscsi_conn_restore_callbacks(conn); - sock_put(conn->sock->sk); + sock_put(tcp_conn->sock->sk); - /* - * flush queues. - */ - spin_lock_bh(&session->lock); - fail_all_commands(session, conn); - flush_control_queues(session, conn); - spin_unlock_bh(&session->lock); - - /* - * release socket only after we stopped data_xmit() - * activity and flushed all outstandings - */ - sock_release(conn->sock); - conn->sock = NULL; - - /* - * for connection level recovery we should not calculate - * header digest. conn->hdr_size used for optimization - * in hdr_extract() and will be re-negotiated at - * set_param() time. - */ - if (flag == STOP_CONN_RECOVER) { - conn->hdr_size = sizeof(struct iscsi_hdr); - conn->hdrdgst_en = 0; - conn->datadgst_en = 0; - - if (session->state == ISCSI_STATE_FAILED) - iscsi_block_session(session_to_cls(session)); - } - mutex_unlock(&conn->xmitmutex); + sock_release(tcp_conn->sock); + tcp_conn->sock = NULL; + conn->recv_lock = NULL; } +/* called with host lock */ static void -iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) -{ - struct iscsi_conn *conn = cls_conn->dd_data; - struct iscsi_session *session = conn->session; - - switch (flag) { - case STOP_CONN_RECOVER: - case STOP_CONN_TERM: - iscsi_start_session_recovery(session, conn, flag); - return; - case STOP_CONN_SUSPEND: - iscsi_suspend_conn_rx(conn); - - mutex_lock(&conn->xmitmutex); - spin_lock_bh(&session->lock); - - conn->stop_stage = flag; - conn->c_stage = ISCSI_CONN_STOPPED; - set_bit(SUSPEND_BIT, &conn->suspend_tx); - - spin_unlock_bh(&session->lock); - mutex_unlock(&conn->xmitmutex); - break; - default: - printk(KERN_ERR "invalid stop flag %d\n", flag); - } -} - -static int -iscsi_conn_send_generic(struct iscsi_conn *conn, struct iscsi_hdr *hdr, - char *data, uint32_t data_size) +iscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask, + char *data, uint32_t data_size) { - struct iscsi_session *session = conn->session; - struct iscsi_nopout *nop = (struct iscsi_nopout *)hdr; - struct iscsi_mgmt_task *mtask; - - spin_lock_bh(&session->lock); - if (session->state == ISCSI_STATE_TERMINATE) { - spin_unlock_bh(&session->lock); - return -EPERM; - } - if (hdr->opcode == (ISCSI_OP_LOGIN | ISCSI_OP_IMMEDIATE) || - hdr->opcode == (ISCSI_OP_TEXT | ISCSI_OP_IMMEDIATE)) - /* - * Login and Text are sent serially, in - * request-followed-by-response sequence. - * Same mtask can be used. Same ITT must be used. - * Note that login_mtask is preallocated at conn_create(). - */ - mtask = conn->login_mtask; - else { - BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE); - BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED); - - if (!__kfifo_get(session->mgmtpool.queue, - (void*)&mtask, sizeof(void*))) { - spin_unlock_bh(&session->lock); - return -ENOSPC; - } - } + struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data; - /* - * pre-format CmdSN and ExpStatSN for outgoing PDU. - */ - if (hdr->itt != cpu_to_be32(ISCSI_RESERVED_TAG)) { - hdr->itt = mtask->itt | (conn->id << CID_SHIFT) | - (session->age << AGE_SHIFT); - nop->cmdsn = cpu_to_be32(session->cmdsn); - if (conn->c_stage == ISCSI_CONN_STARTED && - !(hdr->opcode & ISCSI_OP_IMMEDIATE)) - session->cmdsn++; - } else - /* do not advance CmdSN */ - nop->cmdsn = cpu_to_be32(session->cmdsn); - - nop->exp_statsn = cpu_to_be32(conn->exp_statsn); - - memcpy(&mtask->hdr, hdr, sizeof(struct iscsi_hdr)); - - iscsi_buf_init_virt(&mtask->headbuf, (char*)&mtask->hdr, + iscsi_buf_init_virt(&tcp_mtask->headbuf, (char*)mtask->hdr, sizeof(struct iscsi_hdr)); + tcp_mtask->xmstate = XMSTATE_IMM_HDR; - spin_unlock_bh(&session->lock); - - if (data_size) { - memcpy(mtask->data, data, data_size); - mtask->data_count = data_size; - } else - mtask->data_count = 0; - - mtask->xmstate = XMSTATE_IMM_HDR; - - if (mtask->data_count) { - iscsi_buf_init_iov(&mtask->sendbuf, (char*)mtask->data, + if (mtask->data_count) + iscsi_buf_init_iov(&tcp_mtask->sendbuf, (char*)mtask->data, mtask->data_count); - } - - debug_scsi("mgmtpdu [op 0x%x hdr->itt 0x%x datalen %d]\n", - hdr->opcode, hdr->itt, data_size); - - /* - * since send_pdu() could be called at least from two contexts, - * we need to serialize __kfifo_put, so we don't have to take - * additional lock on fast data-path - */ - if (hdr->opcode & ISCSI_OP_IMMEDIATE) - __kfifo_put(conn->immqueue, (void*)&mtask, sizeof(void*)); - else - __kfifo_put(conn->mgmtqueue, (void*)&mtask, sizeof(void*)); - - scsi_queue_work(session->host, &conn->xmitwork); - return 0; -} - -static int -iscsi_eh_host_reset(struct scsi_cmnd *sc) -{ - struct Scsi_Host *host = sc->device->host; - struct iscsi_session *session = iscsi_hostdata(host->hostdata); - struct iscsi_conn *conn = session->leadconn; - int fail_session = 0; - - spin_lock_bh(&session->lock); - if (session->state == ISCSI_STATE_TERMINATE) { -failed: - debug_scsi("failing host reset: session terminated " - "[CID %d age %d]", conn->id, session->age); - spin_unlock_bh(&session->lock); - return FAILED; - } - - if (sc->SCp.phase == session->age) { - debug_scsi("failing connection CID %d due to SCSI host reset", - conn->id); - fail_session = 1; - } - spin_unlock_bh(&session->lock); - - /* - * we drop the lock here but the leadconn cannot be destoyed while - * we are in the scsi eh - */ - if (fail_session) { - iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); - /* - * if userspace cannot respond then we must kick this off - * here for it - */ - iscsi_start_session_recovery(session, conn, STOP_CONN_RECOVER); - } - - debug_scsi("iscsi_eh_host_reset wait for relogin\n"); - wait_event_interruptible(conn->ehwait, - session->state == ISCSI_STATE_TERMINATE || - session->state == ISCSI_STATE_LOGGED_IN || - session->recovery_failed); - if (signal_pending(current)) - flush_signals(current); - - spin_lock_bh(&session->lock); - if (session->state == ISCSI_STATE_LOGGED_IN) - printk(KERN_INFO "host reset succeeded\n"); - else - goto failed; - spin_unlock_bh(&session->lock); - - return SUCCESS; -} - -static void -iscsi_tmabort_timedout(unsigned long data) -{ - struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)data; - struct iscsi_conn *conn = ctask->conn; - struct iscsi_session *session = conn->session; - - spin_lock(&session->lock); - if (conn->tmabort_state == TMABORT_INITIAL) { - conn->tmabort_state = TMABORT_TIMEDOUT; - debug_scsi("tmabort timedout [sc %lx itt 0x%x]\n", - (long)ctask->sc, ctask->itt); - /* unblock eh_abort() */ - wake_up(&conn->ehwait); - } - spin_unlock(&session->lock); -} - -/* must be called with the mutex lock */ -static int -iscsi_exec_abort_task(struct scsi_cmnd *sc, struct iscsi_cmd_task *ctask) -{ - struct iscsi_conn *conn = ctask->conn; - struct iscsi_session *session = conn->session; - struct iscsi_tm *hdr = &conn->tmhdr; - int rc; - - /* - * ctask timed out but session is OK requests must be serialized. - */ - memset(hdr, 0, sizeof(struct iscsi_tm)); - hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE; - hdr->flags = ISCSI_TM_FUNC_ABORT_TASK; - hdr->flags |= ISCSI_FLAG_CMD_FINAL; - memcpy(hdr->lun, ctask->hdr.lun, sizeof(hdr->lun)); - hdr->rtt = ctask->hdr.itt; - hdr->refcmdsn = ctask->hdr.cmdsn; - - rc = iscsi_conn_send_generic(conn, (struct iscsi_hdr *)hdr, - NULL, 0); - if (rc) { - iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); - debug_scsi("abort sent failure [itt 0x%x] %d", ctask->itt, rc); - return rc; - } - - debug_scsi("abort sent [itt 0x%x]\n", ctask->itt); - - spin_lock_bh(&session->lock); - ctask->mtask = (struct iscsi_mgmt_task *) - session->mgmt_cmds[(hdr->itt & ITT_MASK) - - ISCSI_MGMT_ITT_OFFSET]; - - if (conn->tmabort_state == TMABORT_INITIAL) { - conn->tmfcmd_pdus_cnt++; - conn->tmabort_timer.expires = 10*HZ + jiffies; - conn->tmabort_timer.function = iscsi_tmabort_timedout; - conn->tmabort_timer.data = (unsigned long)ctask; - add_timer(&conn->tmabort_timer); - debug_scsi("abort set timeout [itt 0x%x]", ctask->itt); - } - spin_unlock_bh(&session->lock); - mutex_unlock(&conn->xmitmutex); - - /* - * block eh thread until: - * - * 1) abort response - * 2) abort timeout - * 3) session is terminated or restarted or userspace has - * given up on recovery - */ - wait_event_interruptible(conn->ehwait, - sc->SCp.phase != session->age || - session->state != ISCSI_STATE_LOGGED_IN || - conn->tmabort_state != TMABORT_INITIAL || - session->recovery_failed); - if (signal_pending(current)) - flush_signals(current); - del_timer_sync(&conn->tmabort_timer); - - mutex_lock(&conn->xmitmutex); - return 0; -} - -static int -iscsi_eh_abort(struct scsi_cmnd *sc) -{ - struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)sc->SCp.ptr; - struct iscsi_cmd_task *tmp_ctask; - struct iscsi_conn *conn = ctask->conn; - struct iscsi_session *session = conn->session; - int rc; - - conn->eh_abort_cnt++; - debug_scsi("aborting [sc %p itt 0x%x]\n", sc, ctask->itt); - - mutex_lock(&conn->xmitmutex); - spin_lock_bh(&session->lock); - - /* - * If we are not logged in or we have started a new session - * then let the host reset code handle this - */ - if (session->state != ISCSI_STATE_LOGGED_IN || - sc->SCp.phase != session->age) - goto failed; - - /* ctask completed before time out */ - if (!ctask->sc) - goto success; - - /* what should we do here ? */ - if (conn->ctask == ctask) { - printk(KERN_INFO "sc %p itt 0x%x partially sent. Failing " - "abort\n", sc, ctask->itt); - goto failed; - } - - /* check for the easy pending cmd abort */ - while (__kfifo_get(conn->xmitqueue, (void*)&tmp_ctask, sizeof(void*))) { - if (tmp_ctask->itt == ctask->itt) { - debug_scsi("found pending task\n"); - goto success; - } - __kfifo_put(conn->xmitqueue, (void*)&tmp_ctask, sizeof(void*)); - } - - conn->tmabort_state = TMABORT_INITIAL; - - spin_unlock_bh(&session->lock); - rc = iscsi_exec_abort_task(sc, ctask); - spin_lock_bh(&session->lock); - - iscsi_ctask_mtask_cleanup(ctask); - if (rc || sc->SCp.phase != session->age || - session->state != ISCSI_STATE_LOGGED_IN) - goto failed; - - /* ctask completed before tmf abort response */ - if (!ctask->sc) { - debug_scsi("sc completed while abort in progress\n"); - goto success; - } - - if (conn->tmabort_state != TMABORT_SUCCESS) { - spin_unlock_bh(&session->lock); - iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); - spin_lock_bh(&session->lock); - goto failed; - } - -success: - debug_scsi("abort success [sc %lx itt 0x%x]\n", (long)sc, ctask->itt); - spin_unlock_bh(&session->lock); - - /* clean up task if aborted */ - if (conn->sock) { - struct sock *sk = conn->sock->sk; - - write_lock_bh(&sk->sk_callback_lock); - spin_lock(&session->lock); - fail_command(conn, ctask, DRIVER_TIMEOUT << 24); - spin_unlock(&session->lock); - write_unlock_bh(&sk->sk_callback_lock); - } - mutex_unlock(&conn->xmitmutex); - return SUCCESS; - -failed: - spin_unlock_bh(&session->lock); - mutex_unlock(&conn->xmitmutex); - - debug_scsi("abort failed [sc %lx itt 0x%x]\n", (long)sc, ctask->itt); - return FAILED; } static int @@ -3314,6 +2096,7 @@ iscsi_r2tpool_alloc(struct iscsi_session *session) */ for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) { struct iscsi_cmd_task *ctask = session->cmds[cmd_i]; + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; /* * pre-allocated x4 as much r2ts to handle race when @@ -3322,16 +2105,18 @@ iscsi_r2tpool_alloc(struct iscsi_session *session) */ /* R2T pool */ - if (iscsi_pool_init(&ctask->r2tpool, session->max_r2t * 4, - (void***)&ctask->r2ts, sizeof(struct iscsi_r2t_info))) { + if (iscsi_pool_init(&tcp_ctask->r2tpool, session->max_r2t * 4, + (void***)&tcp_ctask->r2ts, + sizeof(struct iscsi_r2t_info))) { goto r2t_alloc_fail; } /* R2T xmit queue */ - ctask->r2tqueue = kfifo_alloc( + tcp_ctask->r2tqueue = kfifo_alloc( session->max_r2t * 4 * sizeof(void*), GFP_KERNEL, NULL); - if (ctask->r2tqueue == ERR_PTR(-ENOMEM)) { - iscsi_pool_free(&ctask->r2tpool, (void**)ctask->r2ts); + if (tcp_ctask->r2tqueue == ERR_PTR(-ENOMEM)) { + iscsi_pool_free(&tcp_ctask->r2tpool, + (void**)tcp_ctask->r2ts); goto r2t_alloc_fail; } @@ -3340,24 +2125,28 @@ iscsi_r2tpool_alloc(struct iscsi_session *session) * Data-Out PDU's within R2T-sequence can be quite big; * using mempool */ - ctask->datapool = mempool_create_slab_pool(ISCSI_DTASK_DEFAULT_MAX, - taskcache); - if (ctask->datapool == NULL) { - kfifo_free(ctask->r2tqueue); - iscsi_pool_free(&ctask->r2tpool, (void**)ctask->r2ts); + tcp_ctask->datapool = mempool_create_slab_pool(ISCSI_DTASK_DEFAULT_MAX, + taskcache); + if (tcp_ctask->datapool == NULL) { + kfifo_free(tcp_ctask->r2tqueue); + iscsi_pool_free(&tcp_ctask->r2tpool, + (void**)tcp_ctask->r2ts); goto r2t_alloc_fail; } - INIT_LIST_HEAD(&ctask->dataqueue); + INIT_LIST_HEAD(&tcp_ctask->dataqueue); } return 0; r2t_alloc_fail: for (i = 0; i < cmd_i; i++) { - mempool_destroy(session->cmds[i]->datapool); - kfifo_free(session->cmds[i]->r2tqueue); - iscsi_pool_free(&session->cmds[i]->r2tpool, - (void**)session->cmds[i]->r2ts); + struct iscsi_cmd_task *ctask = session->cmds[i]; + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; + + mempool_destroy(tcp_ctask->datapool); + kfifo_free(tcp_ctask->r2tqueue); + iscsi_pool_free(&tcp_ctask->r2tpool, + (void**)tcp_ctask->r2ts); } return -ENOMEM; } @@ -3368,128 +2157,14 @@ iscsi_r2tpool_free(struct iscsi_session *session) int i; for (i = 0; i < session->cmds_max; i++) { - mempool_destroy(session->cmds[i]->datapool); - kfifo_free(session->cmds[i]->r2tqueue); - iscsi_pool_free(&session->cmds[i]->r2tpool, - (void**)session->cmds[i]->r2ts); - } -} + struct iscsi_cmd_task *ctask = session->cmds[i]; + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; -static struct scsi_host_template iscsi_sht = { - .name = "iSCSI Initiator over TCP/IP, v." - ISCSI_VERSION_STR, - .queuecommand = iscsi_queuecommand, - .change_queue_depth = iscsi_change_queue_depth, - .can_queue = ISCSI_XMIT_CMDS_MAX - 1, - .sg_tablesize = ISCSI_SG_TABLESIZE, - .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN, - .eh_abort_handler = iscsi_eh_abort, - .eh_host_reset_handler = iscsi_eh_host_reset, - .use_clustering = DISABLE_CLUSTERING, - .proc_name = "iscsi_tcp", - .this_id = -1, -}; - -static struct iscsi_transport iscsi_tcp_transport; - -static struct iscsi_cls_session * -iscsi_session_create(struct scsi_transport_template *scsit, - uint32_t initial_cmdsn, uint32_t *hostno) -{ - struct Scsi_Host *shost; - struct iscsi_session *session; - int cmd_i; - - shost = iscsi_transport_create_session(scsit, &iscsi_tcp_transport); - if (!shost) - return NULL; - - session = iscsi_hostdata(shost->hostdata); - memset(session, 0, sizeof(struct iscsi_session)); - session->host = shost; - session->state = ISCSI_STATE_FREE; - session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX; - session->cmds_max = ISCSI_XMIT_CMDS_MAX; - session->cmdsn = initial_cmdsn; - session->exp_cmdsn = initial_cmdsn + 1; - session->max_cmdsn = initial_cmdsn + 1; - session->max_r2t = 1; - - *hostno = shost->host_no; - - /* initialize SCSI PDU commands pool */ - if (iscsi_pool_init(&session->cmdpool, session->cmds_max, - (void***)&session->cmds, sizeof(struct iscsi_cmd_task))) - goto cmdpool_alloc_fail; - - /* pre-format cmds pool with ITT */ - for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) - session->cmds[cmd_i]->itt = cmd_i; - - spin_lock_init(&session->lock); - INIT_LIST_HEAD(&session->connections); - - /* initialize immediate command pool */ - if (iscsi_pool_init(&session->mgmtpool, session->mgmtpool_max, - (void***)&session->mgmt_cmds, sizeof(struct iscsi_mgmt_task))) - goto mgmtpool_alloc_fail; - - - /* pre-format immediate cmds pool with ITT */ - for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) { - session->mgmt_cmds[cmd_i]->itt = ISCSI_MGMT_ITT_OFFSET + cmd_i; - session->mgmt_cmds[cmd_i]->data = kmalloc( - DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH, GFP_KERNEL); - if (!session->mgmt_cmds[cmd_i]->data) { - int j; - - for (j = 0; j < cmd_i; j++) - kfree(session->mgmt_cmds[j]->data); - goto immdata_alloc_fail; - } + mempool_destroy(tcp_ctask->datapool); + kfifo_free(tcp_ctask->r2tqueue); + iscsi_pool_free(&tcp_ctask->r2tpool, + (void**)tcp_ctask->r2ts); } - - if (iscsi_r2tpool_alloc(session)) - goto r2tpool_alloc_fail; - - return hostdata_session(shost->hostdata); - -r2tpool_alloc_fail: - for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) - kfree(session->mgmt_cmds[cmd_i]->data); -immdata_alloc_fail: - iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds); -mgmtpool_alloc_fail: - iscsi_pool_free(&session->cmdpool, (void**)session->cmds); -cmdpool_alloc_fail: - iscsi_transport_destroy_session(shost); - return NULL; -} - -static void -iscsi_session_destroy(struct iscsi_cls_session *cls_session) -{ - struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); - struct iscsi_session *session = iscsi_hostdata(shost->hostdata); - int cmd_i; - struct iscsi_data_task *dtask, *n; - - for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) { - struct iscsi_cmd_task *ctask = session->cmds[cmd_i]; - list_for_each_entry_safe(dtask, n, &ctask->dataqueue, item) { - list_del(&dtask->item); - mempool_free(dtask, ctask->datapool); - } - } - - for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) - kfree(session->mgmt_cmds[cmd_i]->data); - - iscsi_r2tpool_free(session); - iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds); - iscsi_pool_free(&session->cmdpool, (void**)session->cmds); - - iscsi_transport_destroy_session(shost); } static int @@ -3498,13 +2173,14 @@ iscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param, { struct iscsi_conn *conn = cls_conn->dd_data; struct iscsi_session *session = conn->session; + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; switch(param) { case ISCSI_PARAM_MAX_RECV_DLENGTH: { - char *saveptr = conn->data; + char *saveptr = tcp_conn->data; gfp_t flags = GFP_KERNEL; - if (conn->data_size >= value) { + if (tcp_conn->data_size >= value) { conn->max_recv_dlength = value; break; } @@ -3515,21 +2191,21 @@ iscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param, spin_unlock_bh(&session->lock); if (value <= PAGE_SIZE) - conn->data = kmalloc(value, flags); + tcp_conn->data = kmalloc(value, flags); else - conn->data = (void*)__get_free_pages(flags, + tcp_conn->data = (void*)__get_free_pages(flags, get_order(value)); - if (conn->data == NULL) { - conn->data = saveptr; + if (tcp_conn->data == NULL) { + tcp_conn->data = saveptr; return -ENOMEM; } - if (conn->data_size <= PAGE_SIZE) + if (tcp_conn->data_size <= PAGE_SIZE) kfree(saveptr); else free_pages((unsigned long)saveptr, - get_order(conn->data_size)); + get_order(tcp_conn->data_size)); conn->max_recv_dlength = value; - conn->data_size = value; + tcp_conn->data_size = value; } break; case ISCSI_PARAM_MAX_XMIT_DLENGTH: @@ -3537,49 +2213,51 @@ iscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param, break; case ISCSI_PARAM_HDRDGST_EN: conn->hdrdgst_en = value; - conn->hdr_size = sizeof(struct iscsi_hdr); + tcp_conn->hdr_size = sizeof(struct iscsi_hdr); if (conn->hdrdgst_en) { - conn->hdr_size += sizeof(__u32); - if (!conn->tx_tfm) - conn->tx_tfm = crypto_alloc_tfm("crc32c", 0); - if (!conn->tx_tfm) + tcp_conn->hdr_size += sizeof(__u32); + if (!tcp_conn->tx_tfm) + tcp_conn->tx_tfm = crypto_alloc_tfm("crc32c", + 0); + if (!tcp_conn->tx_tfm) return -ENOMEM; - if (!conn->rx_tfm) - conn->rx_tfm = crypto_alloc_tfm("crc32c", 0); - if (!conn->rx_tfm) { - crypto_free_tfm(conn->tx_tfm); + if (!tcp_conn->rx_tfm) + tcp_conn->rx_tfm = crypto_alloc_tfm("crc32c", + 0); + if (!tcp_conn->rx_tfm) { + crypto_free_tfm(tcp_conn->tx_tfm); return -ENOMEM; } } else { - if (conn->tx_tfm) - crypto_free_tfm(conn->tx_tfm); - if (conn->rx_tfm) - crypto_free_tfm(conn->rx_tfm); + if (tcp_conn->tx_tfm) + crypto_free_tfm(tcp_conn->tx_tfm); + if (tcp_conn->rx_tfm) + crypto_free_tfm(tcp_conn->rx_tfm); } break; case ISCSI_PARAM_DATADGST_EN: conn->datadgst_en = value; if (conn->datadgst_en) { - if (!conn->data_tx_tfm) - conn->data_tx_tfm = + if (!tcp_conn->data_tx_tfm) + tcp_conn->data_tx_tfm = crypto_alloc_tfm("crc32c", 0); - if (!conn->data_tx_tfm) + if (!tcp_conn->data_tx_tfm) return -ENOMEM; - if (!conn->data_rx_tfm) - conn->data_rx_tfm = + if (!tcp_conn->data_rx_tfm) + tcp_conn->data_rx_tfm = crypto_alloc_tfm("crc32c", 0); - if (!conn->data_rx_tfm) { - crypto_free_tfm(conn->data_tx_tfm); + if (!tcp_conn->data_rx_tfm) { + crypto_free_tfm(tcp_conn->data_tx_tfm); return -ENOMEM; } } else { - if (conn->data_tx_tfm) - crypto_free_tfm(conn->data_tx_tfm); - if (conn->data_rx_tfm) - crypto_free_tfm(conn->data_rx_tfm); + if (tcp_conn->data_tx_tfm) + crypto_free_tfm(tcp_conn->data_tx_tfm); + if (tcp_conn->data_rx_tfm) + crypto_free_tfm(tcp_conn->data_rx_tfm); } - conn->sendpage = conn->datadgst_en ? - sock_no_sendpage : conn->sock->ops->sendpage; + tcp_conn->sendpage = conn->datadgst_en ? + sock_no_sendpage : tcp_conn->sock->ops->sendpage; break; case ISCSI_PARAM_INITIAL_R2T_EN: session->initial_r2t_en = value; @@ -3677,6 +2355,7 @@ iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param, uint32_t *value) { struct iscsi_conn *conn = cls_conn->dd_data; + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; struct inet_sock *inet; switch(param) { @@ -3694,12 +2373,12 @@ iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn, break; case ISCSI_PARAM_CONN_PORT: mutex_lock(&conn->xmitmutex); - if (!conn->sock) { + if (!tcp_conn->sock) { mutex_unlock(&conn->xmitmutex); return -EINVAL; } - inet = inet_sk(conn->sock->sk); + inet = inet_sk(tcp_conn->sock->sk); *value = be16_to_cpu(inet->dport); mutex_unlock(&conn->xmitmutex); default: @@ -3714,6 +2393,7 @@ iscsi_conn_get_str_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param, char *buf) { struct iscsi_conn *conn = cls_conn->dd_data; + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; struct sock *sk; struct inet_sock *inet; struct ipv6_pinfo *np; @@ -3722,12 +2402,12 @@ iscsi_conn_get_str_param(struct iscsi_cls_conn *cls_conn, switch (param) { case ISCSI_PARAM_CONN_ADDRESS: mutex_lock(&conn->xmitmutex); - if (!conn->sock) { + if (!tcp_conn->sock) { mutex_unlock(&conn->xmitmutex); return -EINVAL; } - sk = conn->sock->sk; + sk = tcp_conn->sock->sk; if (sk->sk_family == PF_INET) { inet = inet_sk(sk); len = sprintf(buf, "%u.%u.%u.%u\n", @@ -3751,6 +2431,7 @@ static void iscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats) { struct iscsi_conn *conn = cls_conn->dd_data; + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; stats->txdata_octets = conn->txdata_octets; stats->rxdata_octets = conn->rxdata_octets; @@ -3763,27 +2444,92 @@ iscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats) stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt; stats->custom_length = 3; strcpy(stats->custom[0].desc, "tx_sendpage_failures"); - stats->custom[0].value = conn->sendpage_failures_cnt; + stats->custom[0].value = tcp_conn->sendpage_failures_cnt; strcpy(stats->custom[1].desc, "rx_discontiguous_hdr"); - stats->custom[1].value = conn->discontiguous_hdr_cnt; + stats->custom[1].value = tcp_conn->discontiguous_hdr_cnt; strcpy(stats->custom[2].desc, "eh_abort_cnt"); stats->custom[2].value = conn->eh_abort_cnt; } -static int -iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr, - char *data, uint32_t data_size) +static struct iscsi_cls_session * +iscsi_tcp_session_create(struct iscsi_transport *iscsit, + struct scsi_transport_template *scsit, + uint32_t initial_cmdsn, uint32_t *hostno) { - struct iscsi_conn *conn = cls_conn->dd_data; - int rc; + struct iscsi_cls_session *cls_session; + struct iscsi_session *session; + uint32_t hn; + int cmd_i; - mutex_lock(&conn->xmitmutex); - rc = iscsi_conn_send_generic(conn, hdr, data, data_size); - mutex_unlock(&conn->xmitmutex); + cls_session = iscsi_session_setup(iscsit, scsit, + sizeof(struct iscsi_tcp_cmd_task), + sizeof(struct iscsi_tcp_mgmt_task), + initial_cmdsn, &hn); + if (!cls_session) + return NULL; + *hostno = hn; - return rc; + session = class_to_transport_session(cls_session); + for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) { + struct iscsi_cmd_task *ctask = session->cmds[cmd_i]; + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; + + ctask->hdr = &tcp_ctask->hdr; + } + + for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) { + struct iscsi_mgmt_task *mtask = session->mgmt_cmds[cmd_i]; + struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data; + + mtask->hdr = &tcp_mtask->hdr; + } + + if (iscsi_r2tpool_alloc(class_to_transport_session(cls_session))) + goto r2tpool_alloc_fail; + + return cls_session; + +r2tpool_alloc_fail: + iscsi_session_teardown(cls_session); + return NULL; +} + +static void iscsi_tcp_session_destroy(struct iscsi_cls_session *cls_session) +{ + struct iscsi_session *session = class_to_transport_session(cls_session); + struct iscsi_data_task *dtask, *n; + int cmd_i; + + for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) { + struct iscsi_cmd_task *ctask = session->cmds[cmd_i]; + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; + + list_for_each_entry_safe(dtask, n, &tcp_ctask->dataqueue, + item) { + list_del(&dtask->item); + mempool_free(dtask, tcp_ctask->datapool); + } + } + + iscsi_r2tpool_free(class_to_transport_session(cls_session)); + iscsi_session_teardown(cls_session); } +static struct scsi_host_template iscsi_sht = { + .name = "iSCSI Initiator over TCP/IP, v." + ISCSI_VERSION_STR, + .queuecommand = iscsi_queuecommand, + .change_queue_depth = iscsi_change_queue_depth, + .can_queue = ISCSI_XMIT_CMDS_MAX - 1, + .sg_tablesize = ISCSI_SG_TABLESIZE, + .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN, + .eh_abort_handler = iscsi_eh_abort, + .eh_host_reset_handler = iscsi_eh_host_reset, + .use_clustering = DISABLE_CLUSTERING, + .proc_name = "iscsi_tcp", + .this_id = -1, +}; + static struct iscsi_transport iscsi_tcp_transport = { .owner = THIS_MODULE, .name = "tcp", @@ -3804,23 +2550,34 @@ static struct iscsi_transport iscsi_tcp_transport = { ISCSI_CONN_PORT | ISCSI_CONN_ADDRESS, .host_template = &iscsi_sht, - .hostdata_size = sizeof(struct iscsi_session), .conndata_size = sizeof(struct iscsi_conn), .max_conn = 1, .max_cmd_len = ISCSI_TCP_MAX_CMD_LEN, - .create_session = iscsi_session_create, - .destroy_session = iscsi_session_destroy, - .create_conn = iscsi_conn_create, - .bind_conn = iscsi_conn_bind, - .destroy_conn = iscsi_conn_destroy, + /* session management */ + .create_session = iscsi_tcp_session_create, + .destroy_session = iscsi_tcp_session_destroy, + /* connection management */ + .create_conn = iscsi_tcp_conn_create, + .bind_conn = iscsi_tcp_conn_bind, + .destroy_conn = iscsi_tcp_conn_destroy, .set_param = iscsi_conn_set_param, .get_conn_param = iscsi_conn_get_param, .get_conn_str_param = iscsi_conn_get_str_param, .get_session_param = iscsi_session_get_param, .start_conn = iscsi_conn_start, .stop_conn = iscsi_conn_stop, + /* these are called as part of conn recovery */ + .suspend_conn_recv = iscsi_tcp_suspend_conn_rx, + .terminate_conn = iscsi_tcp_terminate_conn, + /* IO */ .send_pdu = iscsi_conn_send_pdu, .get_stats = iscsi_conn_get_stats, + .init_cmd_task = iscsi_tcp_cmd_init, + .init_mgmt_task = iscsi_tcp_mgmt_init, + .xmit_cmd_task = iscsi_tcp_ctask_xmit, + .xmit_mgmt_task = iscsi_tcp_mtask_xmit, + .cleanup_cmd_task = iscsi_tcp_cleanup_ctask, + /* recovery */ .session_recovery_timedout = iscsi_session_recovery_timedout, }; diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h index 12ef64179b4..c5918854d59 100644 --- a/drivers/scsi/iscsi_tcp.h +++ b/drivers/scsi/iscsi_tcp.h @@ -2,7 +2,8 @@ * iSCSI Initiator TCP Transport * Copyright (C) 2004 Dmitry Yusupov * Copyright (C) 2004 Alex Aizman - * Copyright (C) 2005 Mike Christie + * Copyright (C) 2005 - 2006 Mike Christie + * Copyright (C) 2006 Red Hat, Inc. All rights reserved. * maintained by open-iscsi@googlegroups.com * * This program is free software; you can redistribute it and/or modify @@ -21,20 +22,7 @@ #ifndef ISCSI_TCP_H #define ISCSI_TCP_H -/* Session's states */ -#define ISCSI_STATE_FREE 1 -#define ISCSI_STATE_LOGGED_IN 2 -#define ISCSI_STATE_FAILED 3 -#define ISCSI_STATE_TERMINATE 4 - -/* Connection's states */ -#define ISCSI_CONN_INITIAL_STAGE 0 -#define ISCSI_CONN_STARTED 1 -#define ISCSI_CONN_STOPPED 2 -#define ISCSI_CONN_CLEANUP_WAIT 3 - -/* Connection suspend "bit" */ -#define SUSPEND_BIT 1 +#include /* Socket's Receive state machine */ #define IN_PROGRESS_WAIT_HEADER 0x0 @@ -42,12 +30,6 @@ #define IN_PROGRESS_DATA_RECV 0x2 #define IN_PROGRESS_DDIGEST_RECV 0x3 -/* Task Mgmt states */ -#define TMABORT_INITIAL 0x0 -#define TMABORT_SUCCESS 0x1 -#define TMABORT_FAILED 0x2 -#define TMABORT_TIMEDOUT 0x3 - /* xmit state machine */ #define XMSTATE_IDLE 0x0 #define XMSTATE_R_HDR 0x1 @@ -62,34 +44,14 @@ #define XMSTATE_W_PAD 0x200 #define XMSTATE_DATA_DIGEST 0x400 -#define ISCSI_CONN_MAX 1 #define ISCSI_CONN_RCVBUF_MIN 262144 #define ISCSI_CONN_SNDBUF_MIN 262144 #define ISCSI_PAD_LEN 4 #define ISCSI_R2T_MAX 16 -#define ISCSI_XMIT_CMDS_MAX 128 /* must be power of 2 */ -#define ISCSI_MGMT_CMDS_MAX 32 /* must be power of 2 */ -#define ISCSI_MGMT_ITT_OFFSET 0xa00 #define ISCSI_SG_TABLESIZE SG_ALL -#define ISCSI_DEF_CMD_PER_LUN 32 -#define ISCSI_MAX_CMD_PER_LUN 128 #define ISCSI_TCP_MAX_CMD_LEN 16 -#define ITT_MASK (0xfff) -#define CID_SHIFT 12 -#define CID_MASK (0xffff< Date: Fri, 7 Apr 2006 19:10:03 +0900 Subject: [SCSI] ibmvscsi: convert kmalloc + memset to kcalloc Convert kmalloc + memset to kcalloc in ibmvscsi Signed-off-by: FUJITA Tomonori Acked-by: Dave Boutcher Signed-off-by: James Bottomley --- drivers/scsi/ibmvscsi/ibmvscsi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index 0a8ad37ae89..12cb743d0ce 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c @@ -121,10 +121,9 @@ static int initialize_event_pool(struct event_pool *pool, pool->size = size; pool->next = 0; - pool->events = kmalloc(pool->size * sizeof(*pool->events), GFP_KERNEL); + pool->events = kcalloc(pool->size, sizeof(*pool->events), GFP_KERNEL); if (!pool->events) return -ENOMEM; - memset(pool->events, 0x00, pool->size * sizeof(*pool->events)); pool->iu_storage = dma_alloc_coherent(hostdata->dev, -- cgit v1.2.3 From cdb8c2a6d848deb9eeefffff42974478fbb51b8c Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Sun, 2 Apr 2006 21:57:43 +0200 Subject: [SCSI] dc395x: dynamically map scatter-gather for PIO The current dc395x driver uses PIO to transfer up to 4 bytes which do not get transferred by DMA (under unclear circumstances). For this the driver uses page_address() which is broken on highmem. Apart from this the actual calculation of the virtual address is wrong (even without highmem). So, e.g., for reading it reads bytes from the driver to a wrong address and returns wrong data, I guess, for writing it would just output random data to the device. The proper fix, as suggested by many, is to dynamically map data using kmap_atomic(page, KM_BIO_SRC_IRQ) / kunmap_atomic(virt). The reason why it has not been done until now, although I've done some preliminary patches more than a year ago was that nobody interested in fixing this problem was able to reliably reproduce it. Now it changed - with the help from Sebastian Frei (CC'ed) I was able to trigger the PIO path. Thus, I was also able to test and debug it. There are 4 cases when PIO is used in dc395x - data-in / -out with and without scatter-gather. I was able to reproduce and test only data-in with and without SG. So, the data-out path is still untested, but it is also somewhat simpler than the data-in. Fredrik Roubert (also CC'ed) also had PIO triggering on his system, and in his case it was data-out without SG. It would be great if he could test the attached patch on his system, but even if he cannot, I would still request to apply the patch and just wait if anybody cries... Implementation: I put 2 new functions in scsi_lib.c and their declarations in scsi_cmnd.h. I exported them without _GPL, although, I don't feel strongly about that - not many drivers are likely to use them. But there is at least one more - I want to use them in tmscsim.c. Whether these are the right files for the functions and their declarations - not sure either. Actually, they are not scsi-specific, so, might go somewhere around other scattergather magic? They are not platform specific either, and most SG functions are defined under arch/*/... As these issues were discussed previously there were some more routines suggested to manipulate scattergather buffers, I think, some of them were needed around crypto code... So, might be a common place reasonable, like lib/scattergather.c? I am open here. Signed-off-by: James Bottomley --- drivers/scsi/dc395x.c | 217 +++++++++++++++++++++++++---------------------- drivers/scsi/scsi_lib.c | 57 +++++++++++++ include/scsi/scsi_cmnd.h | 4 + 3 files changed, 176 insertions(+), 102 deletions(-) diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c index cbf825263f3..0c56095f814 100644 --- a/drivers/scsi/dc395x.c +++ b/drivers/scsi/dc395x.c @@ -230,13 +230,12 @@ struct ScsiReqBlk { struct scsi_cmnd *cmd; struct SGentry *segment_x; /* Linear array of hw sg entries (up to 64 entries) */ - u32 sg_bus_addr; /* Bus address of sg list (ie, of segment_x) */ + dma_addr_t sg_bus_addr; /* Bus address of sg list (ie, of segment_x) */ u8 sg_count; /* No of HW sg entries for this request */ u8 sg_index; /* Index of HW sg entry for this request */ - u32 total_xfer_length; /* Total number of bytes remaining to be transfered */ - unsigned char *virt_addr; /* Virtual address of current transfer position */ - + size_t total_xfer_length; /* Total number of bytes remaining to be transfered */ + size_t request_length; /* Total number of bytes in this request */ /* * The sense buffer handling function, request_sense, uses * the first hw sg entry (segment_x[0]) and the transfer @@ -246,8 +245,7 @@ struct ScsiReqBlk { * total_xfer_length in xferred. These values are restored in * pci_unmap_srb_sense. This is the only place xferred is used. */ - unsigned char *virt_addr_req; /* Saved virtual address of the request buffer */ - u32 xferred; /* Saved copy of total_xfer_length */ + size_t xferred; /* Saved copy of total_xfer_length */ u16 state; @@ -977,17 +975,6 @@ static void send_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb) } } -static inline void pio_trigger(void) -{ - static int feedback_requested; - - if (!feedback_requested) { - feedback_requested = 1; - printk(KERN_WARNING "%s: Please, contact " - "to help improve support for your system.\n", __FILE__); - } -} - /* Prepare SRB for being sent to Device DCB w/ command *cmd */ static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb) @@ -1001,7 +988,6 @@ static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb, srb->sg_count = 0; srb->total_xfer_length = 0; srb->sg_bus_addr = 0; - srb->virt_addr = NULL; srb->sg_index = 0; srb->adapter_status = 0; srb->target_status = 0; @@ -1032,7 +1018,6 @@ static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb, reqlen, cmd->request_buffer, cmd->use_sg, srb->sg_count); - srb->virt_addr = page_address(sl->page); for (i = 0; i < srb->sg_count; i++) { u32 busaddr = (u32)sg_dma_address(&sl[i]); u32 seglen = (u32)sl[i].length; @@ -1077,12 +1062,14 @@ static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb, srb->total_xfer_length++; srb->segment_x[0].length = srb->total_xfer_length; - srb->virt_addr = cmd->request_buffer; + dprintkdbg(DBG_0, "build_srb: [1] len=%d buf=%p use_sg=%d map=%08x\n", srb->total_xfer_length, cmd->request_buffer, cmd->use_sg, srb->segment_x[0].address); } + + srb->request_length = srb->total_xfer_length; } @@ -1414,10 +1401,10 @@ static int dc395x_eh_abort(struct scsi_cmnd *cmd) } srb = find_cmd(cmd, &dcb->srb_going_list); if (srb) { - dprintkl(KERN_DEBUG, "eh_abort: Command in progress"); + dprintkl(KERN_DEBUG, "eh_abort: Command in progress\n"); /* XXX: Should abort the command here */ } else { - dprintkl(KERN_DEBUG, "eh_abort: Command not found"); + dprintkl(KERN_DEBUG, "eh_abort: Command not found\n"); } return FAILED; } @@ -1976,14 +1963,11 @@ static void sg_verify_length(struct ScsiReqBlk *srb) /* * Compute the next Scatter Gather list index and adjust its length - * and address if necessary; also compute virt_addr + * and address if necessary */ static void sg_update_list(struct ScsiReqBlk *srb, u32 left) { u8 idx; - struct scatterlist *sg; - struct scsi_cmnd *cmd = srb->cmd; - int segment = cmd->use_sg; u32 xferred = srb->total_xfer_length - left; /* bytes transfered */ struct SGentry *psge = srb->segment_x + srb->sg_index; @@ -2016,29 +2000,6 @@ static void sg_update_list(struct ScsiReqBlk *srb, u32 left) psge++; } sg_verify_length(srb); - - /* we need the corresponding virtual address */ - if (!segment || (srb->flag & AUTO_REQSENSE)) { - srb->virt_addr += xferred; - return; - } - - /* We have to walk the scatterlist to find it */ - sg = (struct scatterlist *)cmd->request_buffer; - while (segment--) { - unsigned long mask = - ~((unsigned long)sg->length - 1) & PAGE_MASK; - if ((sg_dma_address(sg) & mask) == (psge->address & mask)) { - srb->virt_addr = (page_address(sg->page) - + psge->address - - (psge->address & PAGE_MASK)); - return; - } - ++sg; - } - - dprintkl(KERN_ERR, "sg_update_list: sg_to_virt failed\n"); - srb->virt_addr = NULL; } @@ -2050,15 +2011,7 @@ static void sg_update_list(struct ScsiReqBlk *srb, u32 left) */ static void sg_subtract_one(struct ScsiReqBlk *srb) { - srb->total_xfer_length--; - srb->segment_x[srb->sg_index].length--; - if (srb->total_xfer_length && - !srb->segment_x[srb->sg_index].length) { - if (debug_enabled(DBG_PIO)) - printk(" (next segment)"); - srb->sg_index++; - sg_update_list(srb, srb->total_xfer_length); - } + sg_update_list(srb, srb->total_xfer_length - 1); } @@ -2118,7 +2071,7 @@ static void data_out_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, * If we need more data, the DMA SG list will be freshly set up, anyway */ dprintkdbg(DBG_PIO, "data_out_phase0: " - "DMA{fifcnt=0x%02x fifostat=0x%02x} " + "DMA{fifocnt=0x%02x fifostat=0x%02x} " "SCSI{fifocnt=0x%02x cnt=0x%06x status=0x%04x} total=0x%06x\n", DC395x_read8(acb, TRM_S1040_DMA_FIFOCNT), DC395x_read8(acb, TRM_S1040_DMA_FIFOSTAT), @@ -2239,12 +2192,11 @@ static void data_out_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, data_io_transfer(acb, srb, XFERDATAOUT); } - static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status) { u16 scsi_status = *pscsi_status; - u32 d_left_counter = 0; + dprintkdbg(DBG_0, "data_in_phase0: (pid#%li) <%02i-%i>\n", srb->cmd->pid, srb->cmd->device->id, srb->cmd->device->lun); @@ -2262,6 +2214,9 @@ static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, * seem to be a bad idea, actually. */ if (!(srb->state & SRB_XFERPAD)) { + u32 d_left_counter; + unsigned int sc, fc; + if (scsi_status & PARITYERROR) { dprintkl(KERN_INFO, "data_in_phase0: (pid#%li) " "Parity Error\n", srb->cmd->pid); @@ -2298,18 +2253,19 @@ static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, DC395x_read8(acb, TRM_S1040_DMA_FIFOSTAT)); } /* Now: Check remainig data: The SCSI counters should tell us ... */ - d_left_counter = DC395x_read32(acb, TRM_S1040_SCSI_COUNTER) - + ((DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT) & 0x1f) + sc = DC395x_read32(acb, TRM_S1040_SCSI_COUNTER); + fc = DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT); + d_left_counter = sc + ((fc & 0x1f) << ((srb->dcb->sync_period & WIDE_SYNC) ? 1 : 0)); dprintkdbg(DBG_KG, "data_in_phase0: " "SCSI{fifocnt=0x%02x%s ctr=0x%08x} " "DMA{fifocnt=0x%02x fifostat=0x%02x ctr=0x%08x} " "Remain{totxfer=%i scsi_fifo+ctr=%i}\n", - DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT), + fc, (srb->dcb->sync_period & WIDE_SYNC) ? "words" : "bytes", - DC395x_read32(acb, TRM_S1040_SCSI_COUNTER), - DC395x_read8(acb, TRM_S1040_DMA_FIFOCNT), + sc, + fc, DC395x_read8(acb, TRM_S1040_DMA_FIFOSTAT), DC395x_read32(acb, TRM_S1040_DMA_CXCNT), srb->total_xfer_length, d_left_counter); @@ -2317,40 +2273,79 @@ static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, /* KG: Less than or equal to 4 bytes can not be transfered via DMA, it seems. */ if (d_left_counter && srb->total_xfer_length <= DC395x_LASTPIO) { + size_t left_io = srb->total_xfer_length; + /*u32 addr = (srb->segment_x[srb->sg_index].address); */ /*sg_update_list (srb, d_left_counter); */ - dprintkdbg(DBG_PIO, "data_in_phase0: PIO (%i %s) to " - "%p for remaining %i bytes:", - DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT) & 0x1f, + dprintkdbg(DBG_PIO, "data_in_phase0: PIO (%i %s) " + "for remaining %i bytes:", + fc & 0x1f, (srb->dcb->sync_period & WIDE_SYNC) ? "words" : "bytes", - srb->virt_addr, srb->total_xfer_length); if (srb->dcb->sync_period & WIDE_SYNC) DC395x_write8(acb, TRM_S1040_SCSI_CONFIG2, CFG2_WIDEFIFO); - while (DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT) != 0x40) { - u8 byte = DC395x_read8(acb, TRM_S1040_SCSI_FIFO); - pio_trigger(); - *(srb->virt_addr)++ = byte; - if (debug_enabled(DBG_PIO)) - printk(" %02x", byte); - d_left_counter--; - sg_subtract_one(srb); - } - if (srb->dcb->sync_period & WIDE_SYNC) { -#if 1 - /* Read the last byte ... */ - if (srb->total_xfer_length > 0) { - u8 byte = DC395x_read8(acb, TRM_S1040_SCSI_FIFO); - pio_trigger(); - *(srb->virt_addr)++ = byte; - srb->total_xfer_length--; + while (left_io) { + unsigned char *virt, *base = NULL; + unsigned long flags = 0; + size_t len = left_io; + + if (srb->cmd->use_sg) { + size_t offset = srb->request_length - left_io; + local_irq_save(flags); + /* Assumption: it's inside one page as it's at most 4 bytes and + I just assume it's on a 4-byte boundary */ + base = scsi_kmap_atomic_sg((struct scatterlist *)srb->cmd->request_buffer, + srb->sg_count, &offset, &len); + virt = base + offset; + } else { + virt = srb->cmd->request_buffer + srb->cmd->request_bufflen - left_io; + len = left_io; + } + left_io -= len; + + while (len) { + u8 byte; + byte = DC395x_read8(acb, TRM_S1040_SCSI_FIFO); + *virt++ = byte; + if (debug_enabled(DBG_PIO)) printk(" %02x", byte); + + d_left_counter--; + sg_subtract_one(srb); + + len--; + + fc = DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT); + + if (fc == 0x40) { + left_io = 0; + break; + } + } + + WARN_ON((fc != 0x40) == !d_left_counter); + + if (fc == 0x40 && (srb->dcb->sync_period & WIDE_SYNC)) { + /* Read the last byte ... */ + if (srb->total_xfer_length > 0) { + u8 byte = DC395x_read8(acb, TRM_S1040_SCSI_FIFO); + + *virt++ = byte; + srb->total_xfer_length--; + if (debug_enabled(DBG_PIO)) + printk(" %02x", byte); + } + + DC395x_write8(acb, TRM_S1040_SCSI_CONFIG2, 0); + } + + if (srb->cmd->use_sg) { + scsi_kunmap_atomic_sg(base); + local_irq_restore(flags); } -#endif - DC395x_write8(acb, TRM_S1040_SCSI_CONFIG2, 0); } /*printk(" %08x", *(u32*)(bus_to_virt (addr))); */ /*srb->total_xfer_length = 0; */ @@ -2509,22 +2504,43 @@ static void data_io_transfer(struct AdapterCtlBlk *acb, SCMD_FIFO_IN); } else { /* write */ int ln = srb->total_xfer_length; + size_t left_io = srb->total_xfer_length; + if (srb->dcb->sync_period & WIDE_SYNC) DC395x_write8(acb, TRM_S1040_SCSI_CONFIG2, CFG2_WIDEFIFO); - dprintkdbg(DBG_PIO, - "data_io_transfer: PIO %i bytes from %p:", - srb->total_xfer_length, srb->virt_addr); - while (srb->total_xfer_length) { - if (debug_enabled(DBG_PIO)) - printk(" %02x", (unsigned char) *(srb->virt_addr)); + while (left_io) { + unsigned char *virt, *base = NULL; + unsigned long flags = 0; + size_t len = left_io; + + if (srb->cmd->use_sg) { + size_t offset = srb->request_length - left_io; + local_irq_save(flags); + /* Again, max 4 bytes */ + base = scsi_kmap_atomic_sg((struct scatterlist *)srb->cmd->request_buffer, + srb->sg_count, &offset, &len); + virt = base + offset; + } else { + virt = srb->cmd->request_buffer + srb->cmd->request_bufflen - left_io; + len = left_io; + } + left_io -= len; + + while (len--) { + if (debug_enabled(DBG_PIO)) + printk(" %02x", *virt); - pio_trigger(); - DC395x_write8(acb, TRM_S1040_SCSI_FIFO, - *(srb->virt_addr)++); + DC395x_write8(acb, TRM_S1040_SCSI_FIFO, *virt++); - sg_subtract_one(srb); + sg_subtract_one(srb); + } + + if (srb->cmd->use_sg) { + scsi_kunmap_atomic_sg(base); + local_irq_restore(flags); + } } if (srb->dcb->sync_period & WIDE_SYNC) { if (ln % 2) { @@ -3319,7 +3335,6 @@ static void pci_unmap_srb_sense(struct AdapterCtlBlk *acb, srb->segment_x[DC395x_MAX_SG_LISTENTRY - 1].address; srb->segment_x[0].length = srb->segment_x[DC395x_MAX_SG_LISTENTRY - 1].length; - srb->virt_addr = srb->virt_addr_req; } @@ -3713,8 +3728,6 @@ static void request_sense(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, srb->xferred = srb->total_xfer_length; /* srb->segment_x : a one entry of S/G list table */ srb->total_xfer_length = sizeof(cmd->sense_buffer); - srb->virt_addr_req = srb->virt_addr; - srb->virt_addr = cmd->sense_buffer; srb->segment_x[0].length = sizeof(cmd->sense_buffer); /* Map sense buffer */ srb->segment_x[0].address = diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 7b0f9a3810d..57453ca0970 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -2350,3 +2350,60 @@ scsi_target_unblock(struct device *dev) device_for_each_child(dev, NULL, target_unblock); } EXPORT_SYMBOL_GPL(scsi_target_unblock); + +/** + * scsi_kmap_atomic_sg - find and atomically map an sg-elemnt + * @sg: scatter-gather list + * @sg_count: number of segments in sg + * @offset: offset in bytes into sg, on return offset into the mapped area + * @len: bytes to map, on return number of bytes mapped + * + * Returns virtual address of the start of the mapped page + */ +void *scsi_kmap_atomic_sg(struct scatterlist *sg, int sg_count, + size_t *offset, size_t *len) +{ + int i; + size_t sg_len = 0, len_complete = 0; + struct page *page; + + for (i = 0; i < sg_count; i++) { + len_complete = sg_len; /* Complete sg-entries */ + sg_len += sg[i].length; + if (sg_len > *offset) + break; + } + + if (unlikely(i == sg_count)) { + printk(KERN_ERR "%s: Bytes in sg: %u, requested offset %u, elements %d\n", + __FUNCTION__, sg_len, *offset, sg_count); + WARN_ON(1); + return NULL; + } + + /* Offset starting from the beginning of first page in this sg-entry */ + *offset = *offset - len_complete + sg[i].offset; + + /* Assumption: contiguous pages can be accessed as "page + i" */ + page = nth_page(sg[i].page, (*offset >> PAGE_SHIFT)); + *offset &= ~PAGE_MASK; + + /* Bytes in this sg-entry from *offset to the end of the page */ + sg_len = PAGE_SIZE - *offset; + if (*len > sg_len) + *len = sg_len; + + return kmap_atomic(page, KM_BIO_SRC_IRQ); +} +EXPORT_SYMBOL(scsi_kmap_atomic_sg); + +/** + * scsi_kunmap_atomic_sg - atomically unmap a virtual address, previously + * mapped with scsi_kmap_atomic_sg + * @virt: virtual address to be unmapped + */ +void scsi_kunmap_atomic_sg(void *virt) +{ + kunmap_atomic(virt, KM_BIO_SRC_IRQ); +} +EXPORT_SYMBOL(scsi_kunmap_atomic_sg); diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index 1ace1b9fe53..7602b9b15a0 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -152,4 +152,8 @@ extern void scsi_put_command(struct scsi_cmnd *); extern void scsi_io_completion(struct scsi_cmnd *, unsigned int, unsigned int); extern void scsi_finish_command(struct scsi_cmnd *cmd); +extern void *scsi_kmap_atomic_sg(struct scatterlist *sg, int sg_count, + size_t *offset, size_t *len); +extern void scsi_kunmap_atomic_sg(void *virt); + #endif /* _SCSI_SCSI_CMND_H */ -- cgit v1.2.3 From c5f2e6404c65e8380c9ba80a7d58a27d2642743b Mon Sep 17 00:00:00 2001 From: "akpm@osdl.org" Date: Sat, 15 Apr 2006 00:30:24 -0700 Subject: [SCSI] scsi_scan.c: fix compile warnings drivers/scsi/scsi_scan.c: In function `scsi_probe_and_add_lun': drivers/scsi/scsi_scan.c:926: warning: unused variable `vend' drivers/scsi/scsi_scan.c:926: warning: unused variable `mod' drivers/scsi/scsi_scan.c: At top level: drivers/scsi/scsi_scan.c:829: warning: `scsi_inq_str' defined but not used Fix those, tighten up the (somewhat poorly-designed) logging macro and fix some coding-style warts. Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/scsi/scsi_logging.h | 8 +++++--- drivers/scsi/scsi_scan.c | 19 +++++++++++++------ 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/scsi_logging.h b/drivers/scsi/scsi_logging.h index e1722ba9458..a3e2af6a846 100644 --- a/drivers/scsi/scsi_logging.h +++ b/drivers/scsi/scsi_logging.h @@ -45,10 +45,12 @@ extern unsigned int scsi_logging_level; ((scsi_logging_level >> (SHIFT)) & ((1 << (BITS)) - 1)) #define SCSI_CHECK_LOGGING(SHIFT, BITS, LEVEL, CMD) \ -{ \ +do { \ if (unlikely((SCSI_LOG_LEVEL(SHIFT, BITS)) > (LEVEL))) \ - (CMD); \ -} + do { \ + CMD; \ + } while (0); \ +} while (0) #else #define SCSI_CHECK_LOGGING(SHIFT, BITS, LEVEL, CMD) #endif /* CONFIG_SCSI_LOGGING */ diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 5c7e51f9efe..f85d9100f55 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -816,6 +816,7 @@ static inline void scsi_destroy_sdev(struct scsi_device *sdev) put_device(&sdev->sdev_gendev); } +#ifdef CONFIG_SCSI_LOGGING /** * scsi_inq_str - print INQUIRY data from min to max index, * strip trailing whitespace @@ -824,12 +825,13 @@ static inline void scsi_destroy_sdev(struct scsi_device *sdev) * @first: Offset of string into inq * @end: Index after last character in inq */ -static unsigned char* scsi_inq_str(unsigned char* buf, unsigned char *inq, +static unsigned char *scsi_inq_str(unsigned char *buf, unsigned char *inq, unsigned first, unsigned end) { unsigned term = 0, idx; - for (idx = 0; idx+first < end && idx+first < inq[4]+5; ++idx) { - if (inq[idx+first] > 0x20) { + + for (idx = 0; idx + first < end && idx + first < inq[4] + 5; idx++) { + if (inq[idx+first] > ' ') { buf[idx] = inq[idx+first]; term = idx+1; } else { @@ -839,6 +841,7 @@ static unsigned char* scsi_inq_str(unsigned char* buf, unsigned char *inq, buf[term] = 0; return buf; } +#endif /** * scsi_probe_and_add_lun - probe a LUN, if a LUN is found add it @@ -923,12 +926,16 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, " peripheral qualifier of 3, device not" " added\n")) if (lun == 0) { - unsigned char vend[9], mod[17]; - SCSI_LOG_SCAN_BUS(1, sdev_printk(KERN_INFO, sdev, + SCSI_LOG_SCAN_BUS(1, { + unsigned char vend[9]; + unsigned char mod[17]; + + sdev_printk(KERN_INFO, sdev, "scsi scan: consider passing scsi_mod." "dev_flags=%s:%s:0x240 or 0x800240\n", scsi_inq_str(vend, result, 8, 16), - scsi_inq_str(mod, result, 16, 32))); + scsi_inq_str(mod, result, 16, 32)); + }); } res = SCSI_SCAN_TARGET_PRESENT; -- cgit v1.2.3 From 169e1a2a8a789fa84254695ec6a56fc410bb19a9 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 18 Apr 2006 21:09:08 -0700 Subject: [SCSI] scsi_lib.c: fix warning in scsi_kmap_atomic_sg drivers/scsi/scsi_lib.c: In function `scsi_kmap_atomic_sg': drivers/scsi/scsi_lib.c:2394: warning: unsigned int format, different type arg (arg 3) drivers/scsi/scsi_lib.c:2394: warning: unsigned int format, different type arg (arg 4) Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/scsi/scsi_lib.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 57453ca0970..68d413c444f 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -2375,7 +2375,8 @@ void *scsi_kmap_atomic_sg(struct scatterlist *sg, int sg_count, } if (unlikely(i == sg_count)) { - printk(KERN_ERR "%s: Bytes in sg: %u, requested offset %u, elements %d\n", + printk(KERN_ERR "%s: Bytes in sg: %zu, requested offset %zu, " + "elements %d\n", __FUNCTION__, sg_len, *offset, sg_count); WARN_ON(1); return NULL; -- cgit v1.2.3 From bf2af2a2027e52b653882fbca840620e896ae081 Mon Sep 17 00:00:00 2001 From: Bastiaan Jacques Date: Mon, 17 Apr 2006 14:17:59 +0200 Subject: [PATCH] ahci: add support for VIA VT8251 Adds AHCI support for the VIA VT8251. Includes a workaround for a hardware bug which requires a Command List Override before softreset. Signed-off-by: Bastiaan Jacques Signed-off-by: Jeff Garzik --- drivers/scsi/ahci.c | 64 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 49 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 1b8429cb3c9..d23f00230a7 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -73,6 +73,7 @@ enum { RX_FIS_D2H_REG = 0x40, /* offset of D2H Register FIS data */ board_ahci = 0, + board_ahci_vt8251 = 1, /* global controller registers */ HOST_CAP = 0x00, /* host capabilities */ @@ -153,6 +154,9 @@ enum { /* hpriv->flags bits */ AHCI_FLAG_MSI = (1 << 0), + + /* ap->flags bits */ + AHCI_FLAG_RESET_NEEDS_CLO = (1 << 24), }; struct ahci_cmd_hdr { @@ -255,6 +259,16 @@ static const struct ata_port_info ahci_port_info[] = { .udma_mask = 0x7f, /* udma0-6 ; FIXME */ .port_ops = &ahci_ops, }, + /* board_ahci_vt8251 */ + { + .sht = &ahci_sht, + .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | + ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | + AHCI_FLAG_RESET_NEEDS_CLO, + .pio_mask = 0x1f, /* pio0-4 */ + .udma_mask = 0x7f, /* udma0-6 ; FIXME */ + .port_ops = &ahci_ops, + }, }; static const struct pci_device_id ahci_pci_tbl[] = { @@ -296,6 +310,8 @@ static const struct pci_device_id ahci_pci_tbl[] = { board_ahci }, /* ATI SB600 non-raid */ { PCI_VENDOR_ID_ATI, 0x4381, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_ahci }, /* ATI SB600 raid */ + { PCI_VENDOR_ID_VIA, 0x3349, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_ahci_vt8251 }, /* VIA VT8251 */ { } /* terminate list */ }; @@ -516,9 +532,29 @@ static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, u32 opts) pp->cmd_slot[0].tbl_addr_hi = cpu_to_le32((pp->cmd_tbl_dma >> 16) >> 16); } -static int ahci_softreset(struct ata_port *ap, unsigned int *class) +static int ahci_clo(struct ata_port *ap) { + void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr; struct ahci_host_priv *hpriv = ap->host_set->private_data; + u32 tmp; + + if (!(hpriv->cap & HOST_CAP_CLO)) + return -EOPNOTSUPP; + + tmp = readl(port_mmio + PORT_CMD); + tmp |= PORT_CMD_CLO; + writel(tmp, port_mmio + PORT_CMD); + + tmp = ata_wait_register(port_mmio + PORT_CMD, + PORT_CMD_CLO, PORT_CMD_CLO, 1, 500); + if (tmp & PORT_CMD_CLO) + return -EIO; + + return 0; +} + +static int ahci_softreset(struct ata_port *ap, unsigned int *class) +{ struct ahci_port_priv *pp = ap->private_data; void __iomem *mmio = ap->host_set->mmio_base; void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); @@ -547,21 +583,13 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class) /* check BUSY/DRQ, perform Command List Override if necessary */ ahci_tf_read(ap, &tf); if (tf.command & (ATA_BUSY | ATA_DRQ)) { - if (!(hpriv->cap & HOST_CAP_CLO)) { - rc = -EIO; - reason = "port busy but no CLO"; - goto fail_restart; - } - - tmp = readl(port_mmio + PORT_CMD); - tmp |= PORT_CMD_CLO; - writel(tmp, port_mmio + PORT_CMD); + rc = ahci_clo(ap); - tmp = ata_wait_register(port_mmio + PORT_CMD, - PORT_CMD_CLO, PORT_CMD_CLO, 1, 500); - if (tmp & PORT_CMD_CLO) { - rc = -EIO; - reason = "CLO failed"; + if (rc == -EOPNOTSUPP) { + reason = "port busy but CLO unavailable"; + goto fail_restart; + } else if (rc) { + reason = "port busy but CLO failed"; goto fail_restart; } } @@ -672,6 +700,12 @@ static void ahci_postreset(struct ata_port *ap, unsigned int *class) static int ahci_probe_reset(struct ata_port *ap, unsigned int *classes) { + if ((ap->flags & AHCI_FLAG_RESET_NEEDS_CLO) && + (ata_busy_wait(ap, ATA_BUSY, 1000) & ATA_BUSY)) { + /* ATA_BUSY hasn't cleared, so send a CLO */ + ahci_clo(ap); + } + return ata_drive_probe_reset(ap, ata_std_probeinit, ahci_softreset, ahci_hardreset, ahci_postreset, classes); -- cgit v1.2.3 From d6c1a9081080c6c4658acf2a06d851feb2855933 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 4 Apr 2006 13:43:01 +0200 Subject: [PATCH] powerpc: Disable and EOI interrupts in machine_crash_shutdown() We've seen several bugs caused by interrupt weirdness in the kdump kernel. Panicking from an interrupt handler means we fail to EOI the interrupt, and so the second kernel never gets that interrupt ever again. We also see hangs on JS20 where we take interrupts in the second kernel early during boot. This patch fixes both those problems, and although it adds more code to the crash path I think it is the best solution. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/crash.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c index 778f22fd85d..dbcb85994f4 100644 --- a/arch/powerpc/kernel/crash.c +++ b/arch/powerpc/kernel/crash.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -174,6 +175,8 @@ static void crash_kexec_prepare_cpus(void) void default_machine_crash_shutdown(struct pt_regs *regs) { + unsigned int irq; + /* * This function is only called after the system * has paniced or is otherwise in a critical state. @@ -186,6 +189,16 @@ void default_machine_crash_shutdown(struct pt_regs *regs) */ local_irq_disable(); + for_each_irq(irq) { + struct irq_desc *desc = irq_descp(irq); + + if (desc->status & IRQ_INPROGRESS) + desc->handler->end(irq); + + if (!(desc->status & IRQ_DISABLED)) + desc->handler->disable(irq); + } + if (ppc_md.kexec_cpu_down) ppc_md.kexec_cpu_down(1, 0); -- cgit v1.2.3 From 81bbbe92949b069c101e13d3acbd4bc7d088cb79 Mon Sep 17 00:00:00 2001 From: Haren Myneni Date: Wed, 5 Apr 2006 21:10:18 -0600 Subject: [PATCH] powerpc: clear IPIs on kdump In some crash scenarios, the kexec CPU is not responding to an IPI sent by secondary CPU after init thread is forked, causing the system to drop into xmon during kdump boot. This problem can be reproduced each time when the debugger is enabled and soft-reset is used to invoke kdump boot. The first CPU sends an IPI - setting the IPI priority for all secondary cpus (xics_cause_ipi()). But some CPUs will enter into the xmon via soft-reset, i.e, not executing xics_ipi_action(). Hence, IPI is not cleared. When exited from the debugger, one of these CPUs could become the primary kexec CPU. Since the IPI is not cleared, causing this issue in kdump boot. This patch clears and EOI IPI for kexec CPU as well before the kdump boot started. Signed-off-by: Haren Myneni Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/pseries/xics.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index 2d60ea30fed..6c17df5814b 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c @@ -641,23 +641,26 @@ void xics_teardown_cpu(int secondary) ops->cppr_info(cpu, 0x00); iosync(); + /* Clear IPI */ + ops->qirr_info(cpu, 0xff); + + /* + * we need to EOI the IPI if we got here from kexec down IPI + * + * probably need to check all the other interrupts too + * should we be flagging idle loop instead? + * or creating some task to be scheduled? + */ + ops->xirr_info_set(cpu, XICS_IPI); + /* * Some machines need to have at least one cpu in the GIQ, * so leave the master cpu in the group. */ - if (secondary) { - /* - * we need to EOI the IPI if we got here from kexec down IPI - * - * probably need to check all the other interrupts too - * should we be flagging idle loop instead? - * or creating some task to be scheduled? - */ - ops->xirr_info_set(cpu, XICS_IPI); + if (secondary) rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE, (1UL << interrupt_server_size) - 1 - default_distrib_server, 0); - } } #ifdef CONFIG_HOTPLUG_CPU -- cgit v1.2.3 From c256f4b9598c71afd8eb0b7d3d3790a38734cf43 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Fri, 7 Apr 2006 15:23:03 +1000 Subject: [PATCH] powerpc: remove io_page_mask Cleanup patch which removes the io_page_mask. It fixes the reset on some e1000 devices which is needed for clean kexec reboots. The legacy devices which broke with this patch (parallel port and PC speaker) have now been fixed in Linus' tree. Signed-off-by: Anton Blanchard Acked-by: Michael Neuling Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/iomap.c | 2 -- arch/powerpc/kernel/pci_64.c | 30 +++--------------------------- arch/powerpc/platforms/iseries/pci.c | 3 --- arch/powerpc/platforms/maple/pci.c | 3 --- arch/powerpc/platforms/powermac/pci.c | 3 --- include/asm-powerpc/eeh.h | 15 +++------------ include/asm-powerpc/io.h | 6 ------ 7 files changed, 6 insertions(+), 56 deletions(-) diff --git a/arch/powerpc/kernel/iomap.c b/arch/powerpc/kernel/iomap.c index fd8214caede..a13a93dfc65 100644 --- a/arch/powerpc/kernel/iomap.c +++ b/arch/powerpc/kernel/iomap.c @@ -106,8 +106,6 @@ EXPORT_SYMBOL(iowrite32_rep); void __iomem *ioport_map(unsigned long port, unsigned int len) { - if (!_IO_IS_VALID(port)) - return NULL; return (void __iomem *) (port+pci_io_base); } diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 4c4449be81c..18cc15468fd 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -42,14 +42,6 @@ unsigned long pci_probe_only = 1; int pci_assign_all_buses = 0; -/* - * legal IO pages under MAX_ISA_PORT. This is to ensure we don't touch - * devices we don't have access to. - */ -unsigned long io_page_mask; - -EXPORT_SYMBOL(io_page_mask); - #ifdef CONFIG_PPC_MULTIPLATFORM static void fixup_resource(struct resource *res, struct pci_dev *dev); static void do_bus_setup(struct pci_bus *bus); @@ -1104,8 +1096,6 @@ void __init pci_setup_phb_io(struct pci_controller *hose, int primary) pci_process_ISA_OF_ranges(isa_dn, hose->io_base_phys, hose->io_base_virt); of_node_put(isa_dn); - /* Allow all IO */ - io_page_mask = -1; } } @@ -1232,27 +1222,13 @@ static void phbs_remap_io(void) static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev) { struct pci_controller *hose = pci_bus_to_host(dev->bus); - unsigned long start, end, mask, offset; + unsigned long offset; if (res->flags & IORESOURCE_IO) { offset = (unsigned long)hose->io_base_virt - pci_io_base; - start = res->start += offset; - end = res->end += offset; - - /* Need to allow IO access to pages that are in the - ISA range */ - if (start < MAX_ISA_PORT) { - if (end > MAX_ISA_PORT) - end = MAX_ISA_PORT; - - start >>= PAGE_SHIFT; - end >>= PAGE_SHIFT; - - /* get the range of pages for the map */ - mask = ((1 << (end+1)) - 1) ^ ((1 << start) - 1); - io_page_mask |= mask; - } + res->start += offset; + res->end += offset; } else if (res->flags & IORESOURCE_MEM) { res->start += hose->pci_mem_offset; res->end += hose->pci_mem_offset; diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c index a19833b880e..5a61c6fdb33 100644 --- a/arch/powerpc/platforms/iseries/pci.c +++ b/arch/powerpc/platforms/iseries/pci.c @@ -45,8 +45,6 @@ #include "call_pci.h" #include "iommu.h" -extern unsigned long io_page_mask; - /* * Forward declares of prototypes. */ @@ -277,7 +275,6 @@ void iSeries_pcibios_init(void) { iomm_table_initialize(); find_and_init_phbs(); - io_page_mask = -1; } /* diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c index 85d6c93659c..9a4efc0c3b2 100644 --- a/arch/powerpc/platforms/maple/pci.c +++ b/arch/powerpc/platforms/maple/pci.c @@ -437,9 +437,6 @@ void __init maple_pci_init(void) /* Tell pci.c to not change any resource allocations. */ pci_probe_only = 1; - - /* Allow all IO */ - io_page_mask = -1; } int maple_pci_get_legacy_ide_irq(struct pci_dev *pdev, int channel) diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c index f5d8d15d74f..3212618e790 100644 --- a/arch/powerpc/platforms/powermac/pci.c +++ b/arch/powerpc/platforms/powermac/pci.c @@ -1068,9 +1068,6 @@ void __init pmac_pci_init(void) /* Tell pci.c to not use the common resource allocation mechanism */ pci_probe_only = 1; - /* Allow all IO */ - io_page_mask = -1; - #else /* CONFIG_PPC64 */ init_p2pbridge(); fixup_nec_usb2(); diff --git a/include/asm-powerpc/eeh.h b/include/asm-powerpc/eeh.h index 868c7139dbf..2c3dc4a2b12 100644 --- a/include/asm-powerpc/eeh.h +++ b/include/asm-powerpc/eeh.h @@ -293,8 +293,6 @@ static inline void eeh_memcpy_toio(volatile void __iomem *dest, const void *src, static inline u8 eeh_inb(unsigned long port) { u8 val; - if (!_IO_IS_VALID(port)) - return ~0; val = in_8((u8 __iomem *)(port+pci_io_base)); if (EEH_POSSIBLE_ERROR(val, u8)) return eeh_check_failure((void __iomem *)(port), val); @@ -303,15 +301,12 @@ static inline u8 eeh_inb(unsigned long port) static inline void eeh_outb(u8 val, unsigned long port) { - if (_IO_IS_VALID(port)) - out_8((u8 __iomem *)(port+pci_io_base), val); + out_8((u8 __iomem *)(port+pci_io_base), val); } static inline u16 eeh_inw(unsigned long port) { u16 val; - if (!_IO_IS_VALID(port)) - return ~0; val = in_le16((u16 __iomem *)(port+pci_io_base)); if (EEH_POSSIBLE_ERROR(val, u16)) return eeh_check_failure((void __iomem *)(port), val); @@ -320,15 +315,12 @@ static inline u16 eeh_inw(unsigned long port) static inline void eeh_outw(u16 val, unsigned long port) { - if (_IO_IS_VALID(port)) - out_le16((u16 __iomem *)(port+pci_io_base), val); + out_le16((u16 __iomem *)(port+pci_io_base), val); } static inline u32 eeh_inl(unsigned long port) { u32 val; - if (!_IO_IS_VALID(port)) - return ~0; val = in_le32((u32 __iomem *)(port+pci_io_base)); if (EEH_POSSIBLE_ERROR(val, u32)) return eeh_check_failure((void __iomem *)(port), val); @@ -337,8 +329,7 @@ static inline u32 eeh_inl(unsigned long port) static inline void eeh_outl(u32 val, unsigned long port) { - if (_IO_IS_VALID(port)) - out_le32((u32 __iomem *)(port+pci_io_base), val); + out_le32((u32 __iomem *)(port+pci_io_base), val); } /* in-string eeh macros */ diff --git a/include/asm-powerpc/io.h b/include/asm-powerpc/io.h index 68efbea379c..4840fbf89c3 100644 --- a/include/asm-powerpc/io.h +++ b/include/asm-powerpc/io.h @@ -37,12 +37,6 @@ extern unsigned long isa_io_base; extern unsigned long pci_io_base; -extern unsigned long io_page_mask; - -#define MAX_ISA_PORT 0x10000 - -#define _IO_IS_VALID(port) ((port) >= MAX_ISA_PORT || (1 << (port>>PAGE_SHIFT)) \ - & io_page_mask) #ifdef CONFIG_PPC_ISERIES /* __raw_* accessors aren't supported on iSeries */ -- cgit v1.2.3 From 8b6a7b2ea2ab18d46bc9e0e76b614d8c155291ad Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Wed, 12 Apr 2006 15:19:50 -0500 Subject: [PATCH] powerpc: Quiet HVSI boot output There's no real need to print the number of found HVSI devices on the console at every boot. Signed-off-by: Olof Johansson Signed-off-by: Paul Mackerras --- drivers/char/hvsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c index a9522189fc9..a0370ed752c 100644 --- a/drivers/char/hvsi.c +++ b/drivers/char/hvsi.c @@ -1179,7 +1179,7 @@ static int __init hvsi_init(void) if (tty_register_driver(hvsi_driver)) panic("Couldn't register hvsi console driver\n"); - printk(KERN_INFO "HVSI: registered %i devices\n", hvsi_count); + printk(KERN_DEBUG "HVSI: registered %i devices\n", hvsi_count); return 0; } -- cgit v1.2.3 From 224ad80ac0de102d7bede8d36afbd5ef0a64019f Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Wed, 12 Apr 2006 15:20:27 -0500 Subject: [PATCH] powerpc: Quiet time init output Move time_init console output to KERN_DEBUG prink level. No need to print it at every boot. Signed-off-by: Olof Johansson Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/time.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 24e3ad756de..b861ddcf86b 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -945,9 +945,9 @@ void __init time_init(void) } else { /* Normal PowerPC with timebase register */ ppc_md.calibrate_decr(); - printk(KERN_INFO "time_init: decrementer frequency = %lu.%.6lu MHz\n", + printk(KERN_DEBUG "time_init: decrementer frequency = %lu.%.6lu MHz\n", ppc_tb_freq / 1000000, ppc_tb_freq % 1000000); - printk(KERN_INFO "time_init: processor frequency = %lu.%.6lu MHz\n", + printk(KERN_DEBUG "time_init: processor frequency = %lu.%.6lu MHz\n", ppc_proc_freq / 1000000, ppc_proc_freq % 1000000); tb_last_stamp = tb_last_jiffy = get_tb(); } -- cgit v1.2.3 From f430c02b13f00146106fedcace810e61b4493d8c Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Wed, 12 Apr 2006 15:21:06 -0500 Subject: [PATCH] powerpc: Quiet page order output No need to always print page orders. Signed-off-by: Olof Johansson Signed-off-by: Paul Mackerras --- arch/powerpc/mm/hash_utils_64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index c006d903963..b43ed92ef47 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -319,7 +319,7 @@ static void __init htab_init_page_sizes(void) mmu_virtual_psize = MMU_PAGE_64K; #endif - printk(KERN_INFO "Page orders: linear mapping = %d, others = %d\n", + printk(KERN_DEBUG "Page orders: linear mapping = %d, others = %d\n", mmu_psize_defs[mmu_linear_psize].shift, mmu_psize_defs[mmu_virtual_psize].shift); -- cgit v1.2.3 From f98baffb82710803005c19897f1a55af91da5685 Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Wed, 12 Apr 2006 15:22:29 -0500 Subject: [PATCH] powerpc: Quiet VETH version printk ibmveth_printk() is only used to print the driver version when the module initializes, which means on all machines as long as it's compiled in. If it's really only needed for debugging, boot with loglevel=8, or get it from dmesg instead. Signed-off-by: Olof Johansson Signed-off-by: Paul Mackerras --- drivers/net/ibmveth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index 52d01027d9e..37965dc78ee 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -61,7 +61,7 @@ #undef DEBUG #define ibmveth_printk(fmt, args...) \ - printk(KERN_INFO "%s: " fmt, __FILE__, ## args) + printk(KERN_DEBUG "%s: " fmt, __FILE__, ## args) #define ibmveth_error_printk(fmt, args...) \ printk(KERN_ERR "(%s:%3.3d ua:%x) ERROR: " fmt, __FILE__, __LINE__ , adapter->vdev->unit_address, ## args) -- cgit v1.2.3 From 4baaf0cfda7279e1adaedc203d7a09e8e44597ab Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Wed, 12 Apr 2006 15:23:22 -0500 Subject: [PATCH] powerpc: Don't print chosen idle loop at every boot No need to write out what idle loop is used on every boot. Signed-off-by: Olof Johansson Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/setup.c | 4 ++-- arch/powerpc/platforms/maple/setup.c | 2 +- arch/powerpc/platforms/powermac/feature.c | 2 +- arch/powerpc/platforms/pseries/setup.c | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index a6fd9bedb07..0f5110659e6 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -536,10 +536,10 @@ static void __init iSeries_setup_arch(void) { if (get_lppaca()->shared_proc) { ppc_md.idle_loop = iseries_shared_idle; - printk(KERN_INFO "Using shared processor idle loop\n"); + printk(KERN_DEBUG "Using shared processor idle loop\n"); } else { ppc_md.idle_loop = iseries_dedicated_idle; - printk(KERN_INFO "Using dedicated idle loop\n"); + printk(KERN_DEBUG "Using dedicated idle loop\n"); } /* Setup the Lp Event Queue */ diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c index 24c0aef4ea3..a0505ea48a8 100644 --- a/arch/powerpc/platforms/maple/setup.c +++ b/arch/powerpc/platforms/maple/setup.c @@ -189,7 +189,7 @@ void __init maple_setup_arch(void) conswitchp = &dummy_con; #endif - printk(KERN_INFO "Using native/NAP idle loop\n"); + printk(KERN_DEBUG "Using native/NAP idle loop\n"); } /* diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c index a5063cd675c..85e00cb0006 100644 --- a/arch/powerpc/platforms/powermac/feature.c +++ b/arch/powerpc/platforms/powermac/feature.c @@ -2510,7 +2510,7 @@ found: if (get_property(np, "flush-on-lock", NULL)) break; powersave_nap = 1; - printk(KERN_INFO "Processor NAP mode on idle enabled.\n"); + printk(KERN_DEBUG "Processor NAP mode on idle enabled.\n"); break; } diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 5eb55ef1c91..9118d79b7b4 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -235,14 +235,14 @@ static void __init pSeries_setup_arch(void) if (firmware_has_feature(FW_FEATURE_SPLPAR)) { vpa_init(boot_cpuid); if (get_lppaca()->shared_proc) { - printk(KERN_INFO "Using shared processor idle loop\n"); + printk(KERN_DEBUG "Using shared processor idle loop\n"); ppc_md.power_save = pseries_shared_idle_sleep; } else { - printk(KERN_INFO "Using dedicated idle loop\n"); + printk(KERN_DEBUG "Using dedicated idle loop\n"); ppc_md.power_save = pseries_dedicated_idle_sleep; } } else { - printk(KERN_INFO "Using default idle loop\n"); + printk(KERN_DEBUG "Using default idle loop\n"); } if (firmware_has_feature(FW_FEATURE_LPAR)) -- cgit v1.2.3 From e110b281dc93e3b4587a3d0440bb7ae38daddfde Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Wed, 12 Apr 2006 15:25:01 -0500 Subject: [PATCH] powerpc: Less verbose mem configuration output Quieten some of the debug ram config output. we already print out available memory at KERN_INFO level. Signed-off-by: Olof Johansson Signed-off-by: Paul Mackerras --- arch/powerpc/mm/mem.c | 6 +++--- arch/powerpc/mm/numa.c | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 741dd8802d4..69f3b9a20be 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -299,9 +299,9 @@ void __init paging_init(void) kmap_prot = PAGE_KERNEL; #endif /* CONFIG_HIGHMEM */ - printk(KERN_INFO "Top of RAM: 0x%lx, Total RAM: 0x%lx\n", + printk(KERN_DEBUG "Top of RAM: 0x%lx, Total RAM: 0x%lx\n", top_of_ram, total_ram); - printk(KERN_INFO "Memory hole size: %ldMB\n", + printk(KERN_DEBUG "Memory hole size: %ldMB\n", (top_of_ram - total_ram) >> 20); /* * All pages are DMA-able so we put them all in the DMA zone. @@ -380,7 +380,7 @@ void __init mem_init(void) totalhigh_pages++; } totalram_pages += totalhigh_pages; - printk(KERN_INFO "High memory: %luk\n", + printk(KERN_DEBUG "High memory: %luk\n", totalhigh_pages << (PAGE_SHIFT-10)); } #endif /* CONFIG_HIGHMEM */ diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 0a335f34974..ea816c618a7 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -465,9 +465,9 @@ static void __init setup_nonnuma(void) unsigned long total_ram = lmb_phys_mem_size(); unsigned int i; - printk(KERN_INFO "Top of RAM: 0x%lx, Total RAM: 0x%lx\n", + printk(KERN_DEBUG "Top of RAM: 0x%lx, Total RAM: 0x%lx\n", top_of_ram, total_ram); - printk(KERN_INFO "Memory hole size: %ldMB\n", + printk(KERN_DEBUG "Memory hole size: %ldMB\n", (top_of_ram - total_ram) >> 20); for (i = 0; i < lmb.memory.cnt; ++i) @@ -485,7 +485,7 @@ void __init dump_numa_cpu_topology(void) return; for_each_online_node(node) { - printk(KERN_INFO "Node %d CPUs:", node); + printk(KERN_DEBUG "Node %d CPUs:", node); count = 0; /* @@ -521,7 +521,7 @@ static void __init dump_numa_memory_topology(void) for_each_online_node(node) { unsigned long i; - printk(KERN_INFO "Node %d Memory:", node); + printk(KERN_DEBUG "Node %d Memory:", node); count = 0; -- cgit v1.2.3 From cc98f70557bd08f2eea7b955dd918692a655d72e Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Wed, 12 Apr 2006 15:26:00 -0500 Subject: [PATCH] powerpc: Lack of ISA interrupts on XICS isn't dangerous This isn't really a dangerous thing any more; most systems lack ISA interrupt controllers. Signed-off-by: Olof Johansson Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/pseries/xics.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index 6c17df5814b..b14f9b5c114 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c @@ -522,7 +522,7 @@ nextnode: np = of_find_node_by_type(NULL, "interrupt-controller"); if (!np) { - printk(KERN_WARNING "xics: no ISA interrupt controller\n"); + printk(KERN_DEBUG "xics: no ISA interrupt controller\n"); xics_irq_8259_cascade_real = -1; xics_irq_8259_cascade = -1; } else { -- cgit v1.2.3 From e884e9c5f28c747ac2c3e1056e1fd655a79e950d Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Wed, 12 Apr 2006 15:26:59 -0500 Subject: [PATCH] powerpc: Quiet PCI init printouts Quiet some of the more debug related output from the pci probe routines. Signed-off-by: Olof Johansson Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/pci_64.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 18cc15468fd..e1b3b3ef191 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -597,7 +597,7 @@ static int __init pcibios_init(void) iSeries_pcibios_init(); #endif - printk("PCI: Probing PCI hardware\n"); + printk(KERN_DEBUG "PCI: Probing PCI hardware\n"); /* Scan all of the recorded PCI controllers. */ list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { @@ -622,14 +622,14 @@ static int __init pcibios_init(void) /* Cache the location of the ISA bridge (if we have one) */ ppc64_isabridge_dev = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL); if (ppc64_isabridge_dev != NULL) - printk("ISA bridge at %s\n", pci_name(ppc64_isabridge_dev)); + printk(KERN_DEBUG "ISA bridge at %s\n", pci_name(ppc64_isabridge_dev)); #ifdef CONFIG_PPC_MULTIPLATFORM /* map in PCI I/O space */ phbs_remap_io(); #endif - printk("PCI: Probing PCI hardware done\n"); + printk(KERN_DEBUG "PCI: Probing PCI hardware done\n"); return 0; } @@ -796,7 +796,7 @@ static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp, else prot |= _PAGE_GUARDED; - printk("PCI map for %s:%lx, prot: %lx\n", pci_name(dev), rp->start, + printk(KERN_DEBUG "PCI map for %s:%lx, prot: %lx\n", pci_name(dev), rp->start, prot); return __pgprot(prot); @@ -1202,7 +1202,7 @@ int remap_bus_range(struct pci_bus *bus) return 1; if (start_phys == 0) return 1; - printk("mapping IO %lx -> %lx, size: %lx\n", start_phys, start_virt, size); + printk(KERN_DEBUG "mapping IO %lx -> %lx, size: %lx\n", start_phys, start_virt, size); if (__ioremap_explicit(start_phys, start_virt, size, _PAGE_NO_CACHE | _PAGE_GUARDED)) return 1; -- cgit v1.2.3 From 90ddfebec1b450258f85d42f043cfbae450fe47e Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Wed, 12 Apr 2006 15:28:13 -0500 Subject: [PATCH] powerpc: Quiet rtasd output at boot Most users won't really know the difference between a started RTAS daemon and a missing event-scan. Move it to debug levels. Signed-off-by: Olof Johansson Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/pseries/rtasd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/platforms/pseries/rtasd.c b/arch/powerpc/platforms/pseries/rtasd.c index e0000ce769e..2e4e04042d8 100644 --- a/arch/powerpc/platforms/pseries/rtasd.c +++ b/arch/powerpc/platforms/pseries/rtasd.c @@ -348,7 +348,7 @@ static int enable_surveillance(int timeout) return 0; if (error == -EINVAL) { - printk(KERN_INFO "rtasd: surveillance not supported\n"); + printk(KERN_DEBUG "rtasd: surveillance not supported\n"); return 0; } @@ -440,7 +440,7 @@ static int rtasd(void *unused) goto error; } - printk(KERN_INFO "RTAS daemon started\n"); + printk(KERN_DEBUG "RTAS daemon started\n"); DEBUG("will sleep for %d milliseconds\n", (30000/rtas_event_scan_rate)); @@ -487,7 +487,7 @@ static int __init rtas_init(void) /* No RTAS */ if (rtas_token("event-scan") == RTAS_UNKNOWN_SERVICE) { - printk(KERN_INFO "rtasd: no event-scan on system\n"); + printk(KERN_DEBUG "rtasd: no event-scan on system\n"); return -ENODEV; } -- cgit v1.2.3 From 5e1415c3f7d3ad133edb7ce9ca90641cf0f5fe79 Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Wed, 12 Apr 2006 15:29:00 -0500 Subject: [PATCH] powerpc: Quiet oprofile output at boot No need to always print out which performance monitoring type is used on the console at every boot. Signed-off-by: Olof Johansson Signed-off-by: Paul Mackerras --- arch/powerpc/oprofile/common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/oprofile/common.c b/arch/powerpc/oprofile/common.c index 5b1de7e8041..38a2f9c1718 100644 --- a/arch/powerpc/oprofile/common.c +++ b/arch/powerpc/oprofile/common.c @@ -162,7 +162,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) ops->stop = op_powerpc_stop; ops->backtrace = op_powerpc_backtrace; - printk(KERN_INFO "oprofile: using %s performance monitoring.\n", + printk(KERN_DEBUG "oprofile: using %s performance monitoring.\n", ops->cpu_type); return 0; -- cgit v1.2.3 From 4bd174fe1cca738f53cf8bb9ac3cb327b1f516ed Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Tue, 18 Apr 2006 11:25:53 -0500 Subject: [PATCH] powerpc: Remove stale iseries global Not even the iSeries maintainer seems to have access to this legendary piranha simulator. It adds a bit of ugliness in the common time init code, and if it's no longer used we might as well be done with it and remove the bloat. Signed-off-by: Olof Johansson Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/time.c | 6 +----- arch/powerpc/platforms/iseries/mf.c | 9 +-------- arch/powerpc/platforms/iseries/setup.c | 5 ----- 3 files changed, 2 insertions(+), 18 deletions(-) diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index b861ddcf86b..528e7f84cb6 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -76,7 +76,6 @@ /* keep track of when we need to update the rtc */ time_t last_rtc_update; -extern int piranha_simulator; #ifdef CONFIG_PPC_ISERIES unsigned long iSeries_recal_titan = 0; unsigned long iSeries_recal_tb = 0; @@ -1010,10 +1009,7 @@ void __init time_init(void) tb_to_ns_scale = scale; tb_to_ns_shift = shift; -#ifdef CONFIG_PPC_ISERIES - if (!piranha_simulator) -#endif - tm = get_boot_time(); + tm = get_boot_time(); write_seqlock_irqsave(&xtime_lock, flags); diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c index d771b8ee857..1a2c2a50f92 100644 --- a/arch/powerpc/platforms/iseries/mf.c +++ b/arch/powerpc/platforms/iseries/mf.c @@ -45,7 +45,6 @@ #include "setup.h" -extern int piranha_simulator; static int mf_initialized; /* @@ -658,7 +657,7 @@ static void mf_clear_src(void) void __init mf_display_progress(u16 value) { - if (piranha_simulator || !mf_initialized) + if (!mf_initialized) return; if (0xFFFF == value) @@ -1295,9 +1294,6 @@ __initcall(mf_proc_init); */ void iSeries_get_rtc_time(struct rtc_time *rtc_tm) { - if (piranha_simulator) - return; - mf_get_rtc(rtc_tm); rtc_tm->tm_mon--; } @@ -1316,9 +1312,6 @@ unsigned long iSeries_get_boot_time(void) { struct rtc_time tm; - if (piranha_simulator) - return 0; - mf_get_boot_rtc(&tm); return mktime(tm.tm_year + 1900, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 0f5110659e6..3c51448a185 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -81,9 +81,6 @@ extern void iSeries_pci_final_fixup(void); static void iSeries_pci_final_fixup(void) { } #endif -/* Global Variables */ -int piranha_simulator; - extern int rd_size; /* Defined in drivers/block/rd.c */ extern unsigned long embedded_sysmap_start; extern unsigned long embedded_sysmap_end; @@ -340,8 +337,6 @@ static void __init iSeries_init_early(void) #ifdef CONFIG_SMP smp_init_iSeries(); #endif - if (itLpNaca.xPirEnvironMode == 0) - piranha_simulator = 1; /* Associate Lp Event Queue 0 with processor 0 */ HvCallEvent_setLpEventQueueInterruptProc(0, 0); -- cgit v1.2.3 From ac325acd50013fa8f4953208cbb96504dec9b12a Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Tue, 18 Apr 2006 21:05:21 -0700 Subject: [PATCH] powerpc/pseries: clear PCI failure counter if no new failures The current PCI error recovery system keeps track of the number of PCI card resets, and refuses to bring a card back up if this number is too large. The goal of doing this was to avoid an infinite loop of resets if a card is obviously dead. However, if the failures are rare, but the machine has a high uptime, this mechanism might still be triggered; this is too harsh. This patch will avoids this problem by decrementing the fail count after an hour. Thus, as long as a pci card BSOD's less than 6 times an hour, it will continue to be reset indefinitely. If it's failure rate is greater than that, it will be taken off-line permanently. This patch is larger than it might otherwise be because it changes indentation by removing a pointless while-loop. The while loop is not needed, as the handler is invoked once fo each event (by schedule_work()); the loop is leftover cruft from an earlier implementation. Signed-off-by: Linas Vepstas Signed-off-by: Andrew Morton Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/pseries/eeh_driver.c | 13 ++++---- arch/powerpc/platforms/pseries/eeh_event.c | 50 ++++++++++++++++------------- include/asm-powerpc/eeh_event.h | 10 +++--- 3 files changed, 40 insertions(+), 33 deletions(-) diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c index 1fba695e32e..2a9eb263073 100644 --- a/arch/powerpc/platforms/pseries/eeh_driver.c +++ b/arch/powerpc/platforms/pseries/eeh_driver.c @@ -23,9 +23,8 @@ * */ #include -#include #include -#include +#include #include #include #include @@ -250,7 +249,7 @@ static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus) */ #define MAX_WAIT_FOR_RECOVERY 15 -void handle_eeh_events (struct eeh_event *event) +struct pci_dn * handle_eeh_events (struct eeh_event *event) { struct device_node *frozen_dn; struct pci_dn *frozen_pdn; @@ -265,7 +264,7 @@ void handle_eeh_events (struct eeh_event *event) if (!frozen_dn) { printk(KERN_ERR "EEH: Error: Cannot find partition endpoint for %s\n", pci_name(event->dev)); - return; + return NULL; } /* There are two different styles for coming up with the PE. @@ -280,7 +279,7 @@ void handle_eeh_events (struct eeh_event *event) if (!frozen_bus) { printk(KERN_ERR "EEH: Cannot find PCI bus for %s\n", frozen_dn->full_name); - return; + return NULL; } #if 0 @@ -355,7 +354,7 @@ void handle_eeh_events (struct eeh_event *event) /* Tell all device drivers that they can resume operations */ pci_walk_bus(frozen_bus, eeh_report_resume, NULL); - return; + return frozen_pdn; excess_failures: /* @@ -384,6 +383,8 @@ perm_error: /* Shut down the device drivers for good. */ pcibios_remove_pci_devices(frozen_bus); + + return NULL; } /* ---------- end of file ---------- */ diff --git a/arch/powerpc/platforms/pseries/eeh_event.c b/arch/powerpc/platforms/pseries/eeh_event.c index a1bda6f96fd..a0b39640a00 100644 --- a/arch/powerpc/platforms/pseries/eeh_event.c +++ b/arch/powerpc/platforms/pseries/eeh_event.c @@ -18,6 +18,7 @@ * Copyright (c) 2005 Linas Vepstas */ +#include #include #include #include @@ -56,38 +57,43 @@ static int eeh_event_handler(void * dummy) { unsigned long flags; struct eeh_event *event; + struct pci_dn *pdn; daemonize ("eehd"); + set_current_state(TASK_INTERRUPTIBLE); - while (1) { - set_current_state(TASK_INTERRUPTIBLE); + spin_lock_irqsave(&eeh_eventlist_lock, flags); + event = NULL; - spin_lock_irqsave(&eeh_eventlist_lock, flags); - event = NULL; + /* Unqueue the event, get ready to process. */ + if (!list_empty(&eeh_eventlist)) { + event = list_entry(eeh_eventlist.next, struct eeh_event, list); + list_del(&event->list); + } + spin_unlock_irqrestore(&eeh_eventlist_lock, flags); - /* Unqueue the event, get ready to process. */ - if (!list_empty(&eeh_eventlist)) { - event = list_entry(eeh_eventlist.next, struct eeh_event, list); - list_del(&event->list); - } - spin_unlock_irqrestore(&eeh_eventlist_lock, flags); + if (event == NULL) + return 0; - if (event == NULL) - break; + /* Serialize processing of EEH events */ + mutex_lock(&eeh_event_mutex); + eeh_mark_slot(event->dn, EEH_MODE_RECOVERING); - /* Serialize processing of EEH events */ - mutex_lock(&eeh_event_mutex); - eeh_mark_slot(event->dn, EEH_MODE_RECOVERING); + printk(KERN_INFO "EEH: Detected PCI bus error on device %s\n", + pci_name(event->dev)); - printk(KERN_INFO "EEH: Detected PCI bus error on device %s\n", - pci_name(event->dev)); + pdn = handle_eeh_events(event); - handle_eeh_events(event); + eeh_clear_slot(event->dn, EEH_MODE_RECOVERING); + pci_dev_put(event->dev); + kfree(event); + mutex_unlock(&eeh_event_mutex); - eeh_clear_slot(event->dn, EEH_MODE_RECOVERING); - pci_dev_put(event->dev); - kfree(event); - mutex_unlock(&eeh_event_mutex); + /* If there are no new errors after an hour, clear the counter. */ + if (pdn && pdn->eeh_freeze_count>0) { + msleep_interruptible (3600*1000); + if (pdn->eeh_freeze_count>0) + pdn->eeh_freeze_count--; } return 0; diff --git a/include/asm-powerpc/eeh_event.h b/include/asm-powerpc/eeh_event.h index 93d55a2bebf..dc6bf0ffb79 100644 --- a/include/asm-powerpc/eeh_event.h +++ b/include/asm-powerpc/eeh_event.h @@ -18,8 +18,8 @@ * Copyright (c) 2005 Linas Vepstas */ -#ifndef ASM_PPC64_EEH_EVENT_H -#define ASM_PPC64_EEH_EVENT_H +#ifndef ASM_POWERPC_EEH_EVENT_H +#define ASM_POWERPC_EEH_EVENT_H #ifdef __KERNEL__ /** EEH event -- structure holding pci controller data that describes @@ -39,7 +39,7 @@ struct eeh_event { * @dev pci device * * This routine builds a PCI error event which will be delivered - * to all listeners on the peh_notifier_chain. + * to all listeners on the eeh_notifier_chain. * * This routine can be called within an interrupt context; * the actual event will be delivered in a normal context @@ -51,7 +51,7 @@ int eeh_send_failure_event (struct device_node *dn, int time_unavail); /* Main recovery function */ -void handle_eeh_events (struct eeh_event *); +struct pci_dn * handle_eeh_events (struct eeh_event *); #endif /* __KERNEL__ */ -#endif /* ASM_PPC64_EEH_EVENT_H */ +#endif /* ASM_POWERPC_EEH_EVENT_H */ -- cgit v1.2.3 From 95a1ca6cd8e702a19ee56efae522a5816a56a205 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Thu, 27 Apr 2006 17:09:02 +1000 Subject: [PATCH] powerpc: add all the iSeries virtual devices to the device tree We do this by putting them in the flattened device tree at setup time. This required the flattened device tree blob to be made bigger. Currenly we don't do anything with these. Also make a function static. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/setup.c | 88 +++++++++++++++++++++++++++++++++- arch/powerpc/platforms/iseries/vio.c | 2 +- 2 files changed, 88 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 3c51448a185..4862b8e7c78 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -28,6 +28,7 @@ #include #include #include +#include /* ETH_ALEN */ #include #include @@ -45,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -710,7 +712,7 @@ define_machine(iseries) { }; struct blob { - unsigned char data[PAGE_SIZE]; + unsigned char data[PAGE_SIZE * 2]; unsigned long next; }; @@ -911,6 +913,88 @@ void dt_model(struct iseries_flat_dt *dt) dt_prop_str(dt, "compatible", "IBM,iSeries"); } +void dt_vdevices(struct iseries_flat_dt *dt) +{ + u32 reg = 0; + HvLpIndexMap vlan_map; + int i; + char buf[32]; + + dt_start_node(dt, "vdevice"); + dt_prop_u32(dt, "#address-cells", 1); + dt_prop_u32(dt, "#size-cells", 0); + + snprintf(buf, sizeof(buf), "viocons@%08x", reg); + dt_start_node(dt, buf); + dt_prop_str(dt, "device_type", "serial"); + dt_prop_empty(dt, "compatible"); + dt_prop_u32(dt, "reg", reg); + dt_end_node(dt); + reg++; + + snprintf(buf, sizeof(buf), "v-scsi@%08x", reg); + dt_start_node(dt, buf); + dt_prop_str(dt, "device_type", "vscsi"); + dt_prop_str(dt, "compatible", "IBM,v-scsi"); + dt_prop_u32(dt, "reg", reg); + dt_end_node(dt); + reg++; + + vlan_map = HvLpConfig_getVirtualLanIndexMap(); + for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) { + unsigned char mac_addr[ETH_ALEN]; + + if ((vlan_map & (0x8000 >> i)) == 0) + continue; + snprintf(buf, 32, "vlan@%08x", reg + i); + dt_start_node(dt, buf); + dt_prop_str(dt, "device_type", "vlan"); + dt_prop_empty(dt, "compatible"); + dt_prop_u32(dt, "reg", reg + i); + + mac_addr[0] = 0x02; + mac_addr[1] = 0x01; + mac_addr[2] = 0xff; + mac_addr[3] = i; + mac_addr[4] = 0xff; + mac_addr[5] = HvLpConfig_getLpIndex_outline(); + dt_prop(dt, "local-mac-address", (char *)mac_addr, ETH_ALEN); + dt_prop(dt, "mac-address", (char *)mac_addr, ETH_ALEN); + + dt_end_node(dt); + } + reg += HVMAXARCHITECTEDVIRTUALLANS; + + for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++) { + snprintf(buf, 32, "viodasd@%08x", reg + i); + dt_start_node(dt, buf); + dt_prop_str(dt, "device_type", "viodasd"); + dt_prop_empty(dt, "compatible"); + dt_prop_u32(dt, "reg", reg + i); + dt_end_node(dt); + } + reg += HVMAXARCHITECTEDVIRTUALDISKS; + for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++) { + snprintf(buf, 32, "viocd@%08x", reg + i); + dt_start_node(dt, buf); + dt_prop_str(dt, "device_type", "viocd"); + dt_prop_empty(dt, "compatible"); + dt_prop_u32(dt, "reg", reg + i); + dt_end_node(dt); + } + reg += HVMAXARCHITECTEDVIRTUALCDROMS; + for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++) { + snprintf(buf, 32, "viotape@%08x", reg + i); + dt_start_node(dt, buf); + dt_prop_str(dt, "device_type", "viotape"); + dt_prop_empty(dt, "compatible"); + dt_prop_u32(dt, "reg", reg + i); + dt_end_node(dt); + } + + dt_end_node(dt); +} + void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size) { u64 tmp[2]; @@ -941,6 +1025,8 @@ void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size) dt_cpus(dt); + dt_vdevices(dt); + dt_end_node(dt); dt_push_u32(dt, OF_DT_END); diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c index ad36ab0639f..22045a2829a 100644 --- a/arch/powerpc/platforms/iseries/vio.c +++ b/arch/powerpc/platforms/iseries/vio.c @@ -71,7 +71,7 @@ static struct vio_dev *__init vio_register_device_iseries(char *type, return viodev; } -void __init probe_bus_iseries(void) +static void __init probe_bus_iseries(void) { HvLpIndexMap vlan_map; struct vio_dev *viodev; -- cgit v1.2.3 From e10fa77368dff31140451fac04d78d9f51f0f3ac Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Thu, 27 Apr 2006 17:18:21 +1000 Subject: [PATCH] powerpc: use the device tree for the iSeries vio bus probe As an added bonus, since every vio_dev now has a device_node associated with it, hotplug now works. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/vio.c | 171 +++++++++++++++++++++++++++------ arch/powerpc/platforms/iseries/setup.c | 4 + arch/powerpc/platforms/iseries/vio.c | 70 ++------------ arch/powerpc/platforms/pseries/vio.c | 147 ++-------------------------- include/asm-powerpc/vio.h | 9 +- 5 files changed, 169 insertions(+), 232 deletions(-) diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index 971020cf3f7..9b46eed5e63 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c @@ -22,9 +22,7 @@ #include #include #include - -static const struct vio_device_id *vio_match_device( - const struct vio_device_id *, const struct vio_dev *); +#include struct vio_dev vio_bus_device = { /* fake "parent" device */ .name = vio_bus_device.dev.bus_id, @@ -35,6 +33,27 @@ struct vio_dev vio_bus_device = { /* fake "parent" device */ static struct vio_bus_ops vio_bus_ops; +/** + * vio_match_device: - Tell if a VIO device has a matching + * VIO device id structure. + * @ids: array of VIO device id structures to search in + * @dev: the VIO device structure to match against + * + * Used by a driver to check whether a VIO device present in the + * system is in its list of supported devices. Returns the matching + * vio_device_id structure or NULL if there is no match. + */ +static const struct vio_device_id *vio_match_device( + const struct vio_device_id *ids, const struct vio_dev *dev) +{ + while (ids->type[0] != '\0') { + if (vio_bus_ops.match(ids, dev)) + return ids; + ids++; + } + return NULL; +} + /* * Convert from struct device to struct vio_dev and pass to driver. * dev->driver has already been set by generic code because vio_bus_match @@ -107,25 +126,76 @@ void vio_unregister_driver(struct vio_driver *viodrv) EXPORT_SYMBOL(vio_unregister_driver); /** - * vio_match_device: - Tell if a VIO device has a matching - * VIO device id structure. - * @ids: array of VIO device id structures to search in - * @dev: the VIO device structure to match against + * vio_register_device_node: - Register a new vio device. + * @of_node: The OF node for this device. * - * Used by a driver to check whether a VIO device present in the - * system is in its list of supported devices. Returns the matching - * vio_device_id structure or NULL if there is no match. + * Creates and initializes a vio_dev structure from the data in + * of_node (dev.platform_data) and adds it to the list of virtual devices. + * Returns a pointer to the created vio_dev or NULL if node has + * NULL device_type or compatible fields. */ -static const struct vio_device_id *vio_match_device( - const struct vio_device_id *ids, const struct vio_dev *dev) +struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node) { - while (ids->type[0] != '\0') { - if (vio_bus_ops.match(ids, dev)) - return ids; - ids++; + struct vio_dev *viodev; + unsigned int *unit_address; + unsigned int *irq_p; + + /* we need the 'device_type' property, in order to match with drivers */ + if (of_node->type == NULL) { + printk(KERN_WARNING "%s: node %s missing 'device_type'\n", + __FUNCTION__, + of_node->name ? of_node->name : ""); + return NULL; } - return NULL; + + unit_address = (unsigned int *)get_property(of_node, "reg", NULL); + if (unit_address == NULL) { + printk(KERN_WARNING "%s: node %s missing 'reg'\n", + __FUNCTION__, + of_node->name ? of_node->name : ""); + return NULL; + } + + /* allocate a vio_dev for this node */ + viodev = kzalloc(sizeof(struct vio_dev), GFP_KERNEL); + if (viodev == NULL) + return NULL; + + viodev->dev.platform_data = of_node_get(of_node); + + viodev->irq = NO_IRQ; + irq_p = (unsigned int *)get_property(of_node, "interrupts", NULL); + if (irq_p) { + int virq = virt_irq_create_mapping(*irq_p); + if (virq == NO_IRQ) { + printk(KERN_ERR "Unable to allocate interrupt " + "number for %s\n", of_node->full_name); + } else + viodev->irq = irq_offset_up(virq); + } + + snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%x", *unit_address); + viodev->name = of_node->name; + viodev->type = of_node->type; + viodev->unit_address = *unit_address; + if (firmware_has_feature(FW_FEATURE_ISERIES)) { + unit_address = (unsigned int *)get_property(of_node, + "linux,unit_address", NULL); + if (unit_address != NULL) + viodev->unit_address = *unit_address; + } + viodev->iommu_table = vio_bus_ops.build_iommu_table(viodev); + + /* register with generic device framework */ + if (vio_register_device(viodev) == NULL) { + /* XXX free TCE table */ + kfree(viodev); + return NULL; + } + + return viodev; } +EXPORT_SYMBOL(vio_register_device_node); /** * vio_bus_init: - Initialize the virtual IO bus @@ -133,6 +203,7 @@ static const struct vio_device_id *vio_match_device( int __init vio_bus_init(struct vio_bus_ops *ops) { int err; + struct device_node *node_vroot; vio_bus_ops = *ops; @@ -153,23 +224,54 @@ int __init vio_bus_init(struct vio_bus_ops *ops) return err; } + node_vroot = find_devices("vdevice"); + if (node_vroot) { + struct device_node *of_node; + + /* + * Create struct vio_devices for each virtual device in + * the device tree. Drivers will associate with them later. + */ + for (of_node = node_vroot->child; of_node != NULL; + of_node = of_node->sibling) { + printk(KERN_DEBUG "%s: processing %p\n", + __FUNCTION__, of_node); + vio_register_device_node(of_node); + } + } + return 0; } /* vio_dev refcount hit 0 */ static void __devinit vio_dev_release(struct device *dev) { - if (vio_bus_ops.release_device) - vio_bus_ops.release_device(dev); + if (dev->platform_data) { + /* XXX free TCE table */ + of_node_put(dev->platform_data); + } kfree(to_vio_dev(dev)); } -static ssize_t viodev_show_name(struct device *dev, +static ssize_t name_show(struct device *dev, struct device_attribute *attr, char *buf) { return sprintf(buf, "%s\n", to_vio_dev(dev)->name); } -DEVICE_ATTR(name, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_name, NULL); + +static ssize_t devspec_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct device_node *of_node = dev->platform_data; + + return sprintf(buf, "%s\n", of_node ? of_node->full_name : "none"); +} + +static struct device_attribute vio_dev_attrs[] = { + __ATTR_RO(name), + __ATTR_RO(devspec), + __ATTR_NULL +}; struct vio_dev * __devinit vio_register_device(struct vio_dev *viodev) { @@ -184,16 +286,12 @@ struct vio_dev * __devinit vio_register_device(struct vio_dev *viodev) __FUNCTION__, viodev->dev.bus_id); return NULL; } - device_create_file(&viodev->dev, &dev_attr_name); return viodev; } void __devinit vio_unregister_device(struct vio_dev *viodev) { - if (vio_bus_ops.unregister_device) - vio_bus_ops.unregister_device(viodev); - device_remove_file(&viodev->dev, &dev_attr_name); device_unregister(&viodev->dev); } EXPORT_SYMBOL(vio_unregister_device); @@ -267,22 +365,23 @@ static int vio_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size) { const struct vio_dev *vio_dev = to_vio_dev(dev); + struct device_node *dn = dev->platform_data; char *cp; int length; if (!num_envp) return -ENOMEM; - if (!vio_dev->dev.platform_data) + if (!dn) return -ENODEV; - cp = (char *)get_property(vio_dev->dev.platform_data, "compatible", &length); + cp = (char *)get_property(dn, "compatible", &length); if (!cp) return -ENODEV; envp[0] = buffer; length = scnprintf(buffer, buffer_size, "MODALIAS=vio:T%sS%s", vio_dev->type, cp); - if (buffer_size - length <= 0) + if ((buffer_size - length) <= 0) return -ENOMEM; envp[1] = NULL; return 0; @@ -290,9 +389,25 @@ static int vio_hotplug(struct device *dev, char **envp, int num_envp, struct bus_type vio_bus_type = { .name = "vio", + .dev_attrs = vio_dev_attrs, .uevent = vio_hotplug, .match = vio_bus_match, .probe = vio_bus_probe, .remove = vio_bus_remove, .shutdown = vio_bus_shutdown, }; + +/** + * vio_get_attribute: - get attribute for virtual device + * @vdev: The vio device to get property. + * @which: The property/attribute to be extracted. + * @length: Pointer to length of returned data size (unused if NULL). + * + * Calls prom.c's get_property() to return the value of the + * attribute specified by @which +*/ +const void *vio_get_attribute(struct vio_dev *vdev, char *which, int *length) +{ + return get_property(vdev->dev.platform_data, which, length); +} +EXPORT_SYMBOL(vio_get_attribute); diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 4862b8e7c78..901acbcc088 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -951,6 +951,7 @@ void dt_vdevices(struct iseries_flat_dt *dt) dt_prop_str(dt, "device_type", "vlan"); dt_prop_empty(dt, "compatible"); dt_prop_u32(dt, "reg", reg + i); + dt_prop_u32(dt, "linux,unit_address", i); mac_addr[0] = 0x02; mac_addr[1] = 0x01; @@ -971,6 +972,7 @@ void dt_vdevices(struct iseries_flat_dt *dt) dt_prop_str(dt, "device_type", "viodasd"); dt_prop_empty(dt, "compatible"); dt_prop_u32(dt, "reg", reg + i); + dt_prop_u32(dt, "linux,unit_address", i); dt_end_node(dt); } reg += HVMAXARCHITECTEDVIRTUALDISKS; @@ -980,6 +982,7 @@ void dt_vdevices(struct iseries_flat_dt *dt) dt_prop_str(dt, "device_type", "viocd"); dt_prop_empty(dt, "compatible"); dt_prop_u32(dt, "reg", reg + i); + dt_prop_u32(dt, "linux,unit_address", i); dt_end_node(dt); } reg += HVMAXARCHITECTEDVIRTUALCDROMS; @@ -989,6 +992,7 @@ void dt_vdevices(struct iseries_flat_dt *dt) dt_prop_str(dt, "device_type", "viotape"); dt_prop_empty(dt, "compatible"); dt_prop_u32(dt, "reg", reg + i); + dt_prop_u32(dt, "linux,unit_address", i); dt_end_node(dt); } diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c index 22045a2829a..a689da6f2b0 100644 --- a/arch/powerpc/platforms/iseries/vio.c +++ b/arch/powerpc/platforms/iseries/vio.c @@ -43,58 +43,11 @@ static void __init iommu_vio_init(void) printk("Virtual Bus VIO TCE table failed.\n"); } -/** - * vio_register_device_iseries: - Register a new iSeries vio device. - * @voidev: The device to register. - */ -static struct vio_dev *__init vio_register_device_iseries(char *type, - uint32_t unit_num) +static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev) { - struct vio_dev *viodev; - - /* allocate a vio_dev for this device */ - viodev = kmalloc(sizeof(struct vio_dev), GFP_KERNEL); - if (!viodev) - return NULL; - memset(viodev, 0, sizeof(struct vio_dev)); - - snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%s%d", type, unit_num); - - viodev->name = viodev->dev.bus_id; - viodev->type = type; - viodev->unit_address = unit_num; - viodev->iommu_table = &vio_iommu_table; - if (vio_register_device(viodev) == NULL) { - kfree(viodev); - return NULL; - } - return viodev; -} - -static void __init probe_bus_iseries(void) -{ - HvLpIndexMap vlan_map; - struct vio_dev *viodev; - int i; - - /* there is only one of each of these */ - vio_register_device_iseries("viocons", 0); - vio_register_device_iseries("vscsi", 0); - - vlan_map = HvLpConfig_getVirtualLanIndexMap(); - for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) { - if ((vlan_map & (0x8000 >> i)) == 0) - continue; - viodev = vio_register_device_iseries("vlan", i); - /* veth is special and has it own iommu_table */ - viodev->iommu_table = &veth_iommu_table; - } - for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++) - vio_register_device_iseries("viodasd", i); - for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++) - vio_register_device_iseries("viocd", i); - for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++) - vio_register_device_iseries("viotape", i); + if (strcmp(dev->type, "vlan") == 0) + return &veth_iommu_table; + return &vio_iommu_table; } /** @@ -109,6 +62,7 @@ static int vio_match_device_iseries(const struct vio_device_id *id, static struct vio_bus_ops vio_bus_ops_iseries = { .match = vio_match_device_iseries, + .build_iommu_table = vio_build_iommu_table, }; /** @@ -116,16 +70,10 @@ static struct vio_bus_ops vio_bus_ops_iseries = { */ static int __init vio_bus_init_iseries(void) { - int err; - - err = vio_bus_init(&vio_bus_ops_iseries); - if (err == 0) { - iommu_vio_init(); - vio_bus_device.iommu_table = &vio_iommu_table; - iSeries_vio_dev = &vio_bus_device.dev; - probe_bus_iseries(); - } - return err; + iommu_vio_init(); + vio_bus_device.iommu_table = &vio_iommu_table; + iSeries_vio_dev = &vio_bus_device.dev; + return vio_bus_init(&vio_bus_ops_iseries); } __initcall(vio_bus_init_iseries); diff --git a/arch/powerpc/platforms/pseries/vio.c b/arch/powerpc/platforms/pseries/vio.c index 8e53e04ada8..b3925aefdac 100644 --- a/arch/powerpc/platforms/pseries/vio.c +++ b/arch/powerpc/platforms/pseries/vio.c @@ -26,26 +26,6 @@ extern struct subsystem devices_subsys; /* needed for vio_find_name() */ -static void probe_bus_pseries(void) -{ - struct device_node *node_vroot, *of_node; - - node_vroot = find_devices("vdevice"); - if ((node_vroot == NULL) || (node_vroot->child == NULL)) - /* this machine doesn't do virtual IO, and that's ok */ - return; - - /* - * Create struct vio_devices for each virtual device in the device tree. - * Drivers will associate with them later. - */ - for (of_node = node_vroot->child; of_node != NULL; - of_node = of_node->sibling) { - printk(KERN_DEBUG "%s: processing %p\n", __FUNCTION__, of_node); - vio_register_device_node(of_node); - } -} - /** * vio_match_device_pseries: - Tell if a pSeries VIO device matches a * vio_device_id @@ -57,47 +37,6 @@ static int vio_match_device_pseries(const struct vio_device_id *id, device_is_compatible(dev->dev.platform_data, id->compat); } -static void vio_release_device_pseries(struct device *dev) -{ - /* XXX free TCE table */ - of_node_put(dev->platform_data); -} - -static ssize_t viodev_show_devspec(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct device_node *of_node = dev->platform_data; - - return sprintf(buf, "%s\n", of_node->full_name); -} -DEVICE_ATTR(devspec, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_devspec, NULL); - -static void vio_unregister_device_pseries(struct vio_dev *viodev) -{ - device_remove_file(&viodev->dev, &dev_attr_devspec); -} - -static struct vio_bus_ops vio_bus_ops_pseries = { - .match = vio_match_device_pseries, - .unregister_device = vio_unregister_device_pseries, - .release_device = vio_release_device_pseries, -}; - -/** - * vio_bus_init_pseries: - Initialize the pSeries virtual IO bus - */ -static int __init vio_bus_init_pseries(void) -{ - int err; - - err = vio_bus_init(&vio_bus_ops_pseries); - if (err == 0) - probe_bus_pseries(); - return err; -} - -__initcall(vio_bus_init_pseries); - /** * vio_build_iommu_table: - gets the dma information from OF and * builds the TCE tree. @@ -136,88 +75,20 @@ static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev) return iommu_init_table(newTceTable); } +static struct vio_bus_ops vio_bus_ops_pseries = { + .match = vio_match_device_pseries, + .build_iommu_table = vio_build_iommu_table, +}; + /** - * vio_register_device_node: - Register a new vio device. - * @of_node: The OF node for this device. - * - * Creates and initializes a vio_dev structure from the data in - * of_node (dev.platform_data) and adds it to the list of virtual devices. - * Returns a pointer to the created vio_dev or NULL if node has - * NULL device_type or compatible fields. + * vio_bus_init_pseries: - Initialize the pSeries virtual IO bus */ -struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node) +static int __init vio_bus_init_pseries(void) { - struct vio_dev *viodev; - unsigned int *unit_address; - unsigned int *irq_p; - - /* we need the 'device_type' property, in order to match with drivers */ - if ((NULL == of_node->type)) { - printk(KERN_WARNING - "%s: node %s missing 'device_type'\n", __FUNCTION__, - of_node->name ? of_node->name : ""); - return NULL; - } - - unit_address = (unsigned int *)get_property(of_node, "reg", NULL); - if (!unit_address) { - printk(KERN_WARNING "%s: node %s missing 'reg'\n", __FUNCTION__, - of_node->name ? of_node->name : ""); - return NULL; - } - - /* allocate a vio_dev for this node */ - viodev = kmalloc(sizeof(struct vio_dev), GFP_KERNEL); - if (!viodev) { - return NULL; - } - memset(viodev, 0, sizeof(struct vio_dev)); - - viodev->dev.platform_data = of_node_get(of_node); - - viodev->irq = NO_IRQ; - irq_p = (unsigned int *)get_property(of_node, "interrupts", NULL); - if (irq_p) { - int virq = virt_irq_create_mapping(*irq_p); - if (virq == NO_IRQ) { - printk(KERN_ERR "Unable to allocate interrupt " - "number for %s\n", of_node->full_name); - } else - viodev->irq = irq_offset_up(virq); - } - - snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%x", *unit_address); - viodev->name = of_node->name; - viodev->type = of_node->type; - viodev->unit_address = *unit_address; - viodev->iommu_table = vio_build_iommu_table(viodev); - - /* register with generic device framework */ - if (vio_register_device(viodev) == NULL) { - /* XXX free TCE table */ - kfree(viodev); - return NULL; - } - device_create_file(&viodev->dev, &dev_attr_devspec); - - return viodev; + return vio_bus_init(&vio_bus_ops_pseries); } -EXPORT_SYMBOL(vio_register_device_node); -/** - * vio_get_attribute: - get attribute for virtual device - * @vdev: The vio device to get property. - * @which: The property/attribute to be extracted. - * @length: Pointer to length of returned data size (unused if NULL). - * - * Calls prom.c's get_property() to return the value of the - * attribute specified by the preprocessor constant @which -*/ -const void * vio_get_attribute(struct vio_dev *vdev, void* which, int* length) -{ - return get_property(vdev->dev.platform_data, (char*)which, length); -} -EXPORT_SYMBOL(vio_get_attribute); +__initcall(vio_bus_init_pseries); /* vio_find_name() - internal because only vio.c knows how we formatted the * kobject name diff --git a/include/asm-powerpc/vio.h b/include/asm-powerpc/vio.h index 0544ece5176..0055d8e6102 100644 --- a/include/asm-powerpc/vio.h +++ b/include/asm-powerpc/vio.h @@ -66,8 +66,7 @@ struct vio_driver { struct vio_bus_ops { int (*match)(const struct vio_device_id *id, const struct vio_dev *dev); - void (*unregister_device)(struct vio_dev *); - void (*release_device)(struct device *); + struct iommu_table *(*build_iommu_table)(struct vio_dev *dev); }; extern struct dma_mapping_ops vio_dma_ops; @@ -82,14 +81,14 @@ extern void __devinit vio_unregister_device(struct vio_dev *dev); extern int vio_bus_init(struct vio_bus_ops *); -#ifdef CONFIG_PPC_PSERIES struct device_node; extern struct vio_dev * __devinit vio_register_device_node( struct device_node *node_vdev); -extern struct vio_dev *vio_find_node(struct device_node *vnode); -extern const void *vio_get_attribute(struct vio_dev *vdev, void *which, +extern const void *vio_get_attribute(struct vio_dev *vdev, char *which, int *length); +#ifdef CONFIG_PPC_PSERIES +extern struct vio_dev *vio_find_node(struct device_node *vnode); extern int vio_enable_interrupts(struct vio_dev *dev); extern int vio_disable_interrupts(struct vio_dev *dev); #endif -- cgit v1.2.3 From dd721ffd95d5e1516380da0b254ef737582a258f Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Thu, 27 Apr 2006 17:21:46 +1000 Subject: [PATCH] powerpc: use a common vio_match_device routine This requires the compatible properties having vaules that are empty strings instead of just being empty properties. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/vio.c | 3 ++- arch/powerpc/platforms/iseries/setup.c | 10 +++++----- arch/powerpc/platforms/iseries/vio.c | 12 ------------ arch/powerpc/platforms/pseries/vio.c | 12 ------------ include/asm-powerpc/vio.h | 1 - 5 files changed, 7 insertions(+), 31 deletions(-) diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index 9b46eed5e63..19529297a2d 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c @@ -47,7 +47,8 @@ static const struct vio_device_id *vio_match_device( const struct vio_device_id *ids, const struct vio_dev *dev) { while (ids->type[0] != '\0') { - if (vio_bus_ops.match(ids, dev)) + if ((strncmp(dev->type, ids->type, strlen(ids->type)) == 0) && + device_is_compatible(dev->dev.platform_data, ids->compat)) return ids; ids++; } diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 901acbcc088..befd36af7e3 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -927,7 +927,7 @@ void dt_vdevices(struct iseries_flat_dt *dt) snprintf(buf, sizeof(buf), "viocons@%08x", reg); dt_start_node(dt, buf); dt_prop_str(dt, "device_type", "serial"); - dt_prop_empty(dt, "compatible"); + dt_prop_str(dt, "compatible", ""); dt_prop_u32(dt, "reg", reg); dt_end_node(dt); reg++; @@ -949,7 +949,7 @@ void dt_vdevices(struct iseries_flat_dt *dt) snprintf(buf, 32, "vlan@%08x", reg + i); dt_start_node(dt, buf); dt_prop_str(dt, "device_type", "vlan"); - dt_prop_empty(dt, "compatible"); + dt_prop_str(dt, "compatible", ""); dt_prop_u32(dt, "reg", reg + i); dt_prop_u32(dt, "linux,unit_address", i); @@ -970,7 +970,7 @@ void dt_vdevices(struct iseries_flat_dt *dt) snprintf(buf, 32, "viodasd@%08x", reg + i); dt_start_node(dt, buf); dt_prop_str(dt, "device_type", "viodasd"); - dt_prop_empty(dt, "compatible"); + dt_prop_str(dt, "compatible", ""); dt_prop_u32(dt, "reg", reg + i); dt_prop_u32(dt, "linux,unit_address", i); dt_end_node(dt); @@ -980,7 +980,7 @@ void dt_vdevices(struct iseries_flat_dt *dt) snprintf(buf, 32, "viocd@%08x", reg + i); dt_start_node(dt, buf); dt_prop_str(dt, "device_type", "viocd"); - dt_prop_empty(dt, "compatible"); + dt_prop_str(dt, "compatible", ""); dt_prop_u32(dt, "reg", reg + i); dt_prop_u32(dt, "linux,unit_address", i); dt_end_node(dt); @@ -990,7 +990,7 @@ void dt_vdevices(struct iseries_flat_dt *dt) snprintf(buf, 32, "viotape@%08x", reg + i); dt_start_node(dt, buf); dt_prop_str(dt, "device_type", "viotape"); - dt_prop_empty(dt, "compatible"); + dt_prop_str(dt, "compatible", ""); dt_prop_u32(dt, "reg", reg + i); dt_prop_u32(dt, "linux,unit_address", i); dt_end_node(dt); diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c index a689da6f2b0..bdd2b7d97d1 100644 --- a/arch/powerpc/platforms/iseries/vio.c +++ b/arch/powerpc/platforms/iseries/vio.c @@ -50,18 +50,7 @@ static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev) return &vio_iommu_table; } -/** - * vio_match_device_iseries: - Tell if a iSeries VIO device matches a - * vio_device_id - */ -static int vio_match_device_iseries(const struct vio_device_id *id, - const struct vio_dev *dev) -{ - return strncmp(dev->type, id->type, strlen(id->type)) == 0; -} - static struct vio_bus_ops vio_bus_ops_iseries = { - .match = vio_match_device_iseries, .build_iommu_table = vio_build_iommu_table, }; @@ -75,5 +64,4 @@ static int __init vio_bus_init_iseries(void) iSeries_vio_dev = &vio_bus_device.dev; return vio_bus_init(&vio_bus_ops_iseries); } - __initcall(vio_bus_init_iseries); diff --git a/arch/powerpc/platforms/pseries/vio.c b/arch/powerpc/platforms/pseries/vio.c index b3925aefdac..d2891661d87 100644 --- a/arch/powerpc/platforms/pseries/vio.c +++ b/arch/powerpc/platforms/pseries/vio.c @@ -26,17 +26,6 @@ extern struct subsystem devices_subsys; /* needed for vio_find_name() */ -/** - * vio_match_device_pseries: - Tell if a pSeries VIO device matches a - * vio_device_id - */ -static int vio_match_device_pseries(const struct vio_device_id *id, - const struct vio_dev *dev) -{ - return (strncmp(dev->type, id->type, strlen(id->type)) == 0) && - device_is_compatible(dev->dev.platform_data, id->compat); -} - /** * vio_build_iommu_table: - gets the dma information from OF and * builds the TCE tree. @@ -76,7 +65,6 @@ static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev) } static struct vio_bus_ops vio_bus_ops_pseries = { - .match = vio_match_device_pseries, .build_iommu_table = vio_build_iommu_table, }; diff --git a/include/asm-powerpc/vio.h b/include/asm-powerpc/vio.h index 0055d8e6102..9c09a8ffa12 100644 --- a/include/asm-powerpc/vio.h +++ b/include/asm-powerpc/vio.h @@ -65,7 +65,6 @@ struct vio_driver { }; struct vio_bus_ops { - int (*match)(const struct vio_device_id *id, const struct vio_dev *dev); struct iommu_table *(*build_iommu_table)(struct vio_dev *dev); }; -- cgit v1.2.3 From c7f0e8cb5654a50986c6097b3c0cca972e406899 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Thu, 27 Apr 2006 17:23:32 +1000 Subject: [PATCH] powerpc: merge the rest of the vio code Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/vio.c | 198 ++++++++++++++++++++++++++------ arch/powerpc/platforms/iseries/Makefile | 1 - arch/powerpc/platforms/iseries/iommu.c | 3 +- arch/powerpc/platforms/iseries/iommu.h | 35 ------ arch/powerpc/platforms/iseries/pci.c | 2 +- arch/powerpc/platforms/iseries/vio.c | 67 ----------- arch/powerpc/platforms/pseries/Makefile | 1 - arch/powerpc/platforms/pseries/vio.c | 133 --------------------- include/asm-powerpc/iseries/iommu.h | 35 ++++++ include/asm-powerpc/vio.h | 8 -- 10 files changed, 201 insertions(+), 282 deletions(-) delete mode 100644 arch/powerpc/platforms/iseries/iommu.h delete mode 100644 arch/powerpc/platforms/iseries/vio.c delete mode 100644 arch/powerpc/platforms/pseries/vio.c create mode 100644 include/asm-powerpc/iseries/iommu.h diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index 19529297a2d..ac5c7bf907f 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c @@ -13,25 +13,102 @@ * 2 of the License, or (at your option) any later version. */ +#include +#include #include #include #include #include #include +#include + #include #include #include #include #include - -struct vio_dev vio_bus_device = { /* fake "parent" device */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern struct subsystem devices_subsys; /* needed for vio_find_name() */ + +static struct vio_dev vio_bus_device = { /* fake "parent" device */ .name = vio_bus_device.dev.bus_id, .type = "", .dev.bus_id = "vio", .dev.bus = &vio_bus_type, }; -static struct vio_bus_ops vio_bus_ops; +#ifdef CONFIG_PPC_ISERIES +struct device *iSeries_vio_dev = &vio_bus_device.dev; +EXPORT_SYMBOL(iSeries_vio_dev); + +static struct iommu_table veth_iommu_table; +static struct iommu_table vio_iommu_table; + +static void __init iommu_vio_init(void) +{ + iommu_table_getparms_iSeries(255, 0, 0xff, &veth_iommu_table); + veth_iommu_table.it_size /= 2; + vio_iommu_table = veth_iommu_table; + vio_iommu_table.it_offset += veth_iommu_table.it_size; + + if (!iommu_init_table(&veth_iommu_table)) + printk("Virtual Bus VETH TCE table failed.\n"); + if (!iommu_init_table(&vio_iommu_table)) + printk("Virtual Bus VIO TCE table failed.\n"); +} +#endif + +static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev) +{ +#ifdef CONFIG_PPC_ISERIES + if (firmware_has_feature(FW_FEATURE_ISERIES)) { + if (strcmp(dev->type, "vlan") == 0) + return &veth_iommu_table; + return &vio_iommu_table; + } else +#endif + { + unsigned int *dma_window; + struct iommu_table *newTceTable; + unsigned long offset; + int dma_window_property_size; + + dma_window = (unsigned int *)get_property( + dev->dev.platform_data, "ibm,my-dma-window", + &dma_window_property_size); + if (!dma_window) + return NULL; + + newTceTable = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); + + /* + * There should be some code to extract the phys-encoded + * offset using prom_n_addr_cells(). However, according to + * a comment on earlier versions, it's always zero, so we + * don't bother + */ + offset = dma_window[1] >> PAGE_SHIFT; + + /* TCE table size - measured in tce entries */ + newTceTable->it_size = dma_window[4] >> PAGE_SHIFT; + /* offset for VIO should always be 0 */ + newTceTable->it_offset = offset; + newTceTable->it_busno = 0; + newTceTable->it_index = (unsigned long)dma_window[0]; + newTceTable->it_type = TCE_VB; + + return iommu_init_table(newTceTable); + } +} /** * vio_match_device: - Tell if a VIO device has a matching @@ -126,6 +203,16 @@ void vio_unregister_driver(struct vio_driver *viodrv) } EXPORT_SYMBOL(vio_unregister_driver); +/* vio_dev refcount hit 0 */ +static void __devinit vio_dev_release(struct device *dev) +{ + if (dev->platform_data) { + /* XXX free TCE table */ + of_node_put(dev->platform_data); + } + kfree(to_vio_dev(dev)); +} + /** * vio_register_device_node: - Register a new vio device. * @of_node: The OF node for this device. @@ -185,10 +272,17 @@ struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node) if (unit_address != NULL) viodev->unit_address = *unit_address; } - viodev->iommu_table = vio_bus_ops.build_iommu_table(viodev); + viodev->iommu_table = vio_build_iommu_table(viodev); + + /* init generic 'struct device' fields: */ + viodev->dev.parent = &vio_bus_device.dev; + viodev->dev.bus = &vio_bus_type; + viodev->dev.release = vio_dev_release; /* register with generic device framework */ - if (vio_register_device(viodev) == NULL) { + if (device_register(&viodev->dev)) { + printk(KERN_ERR "%s: failed to register device %s\n", + __FUNCTION__, viodev->dev.bus_id); /* XXX free TCE table */ kfree(viodev); return NULL; @@ -201,12 +295,18 @@ EXPORT_SYMBOL(vio_register_device_node); /** * vio_bus_init: - Initialize the virtual IO bus */ -int __init vio_bus_init(struct vio_bus_ops *ops) +static int __init vio_bus_init(void) { int err; struct device_node *node_vroot; - vio_bus_ops = *ops; +#ifdef CONFIG_PPC_ISERIES + if (firmware_has_feature(FW_FEATURE_ISERIES)) { + iommu_vio_init(); + vio_bus_device.iommu_table = &vio_iommu_table; + iSeries_vio_dev = &vio_bus_device.dev; + } +#endif err = bus_register(&vio_bus_type); if (err) { @@ -243,16 +343,7 @@ int __init vio_bus_init(struct vio_bus_ops *ops) return 0; } - -/* vio_dev refcount hit 0 */ -static void __devinit vio_dev_release(struct device *dev) -{ - if (dev->platform_data) { - /* XXX free TCE table */ - of_node_put(dev->platform_data); - } - kfree(to_vio_dev(dev)); -} +__initcall(vio_bus_init); static ssize_t name_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -274,23 +365,6 @@ static struct device_attribute vio_dev_attrs[] = { __ATTR_NULL }; -struct vio_dev * __devinit vio_register_device(struct vio_dev *viodev) -{ - /* init generic 'struct device' fields: */ - viodev->dev.parent = &vio_bus_device.dev; - viodev->dev.bus = &vio_bus_type; - viodev->dev.release = vio_dev_release; - - /* register with generic device framework */ - if (device_register(&viodev->dev)) { - printk(KERN_ERR "%s: failed to register device %s\n", - __FUNCTION__, viodev->dev.bus_id); - return NULL; - } - - return viodev; -} - void __devinit vio_unregister_device(struct vio_dev *viodev) { device_unregister(&viodev->dev); @@ -412,3 +486,59 @@ const void *vio_get_attribute(struct vio_dev *vdev, char *which, int *length) return get_property(vdev->dev.platform_data, which, length); } EXPORT_SYMBOL(vio_get_attribute); + +#ifdef CONFIG_PPC_PSERIES +/* vio_find_name() - internal because only vio.c knows how we formatted the + * kobject name + * XXX once vio_bus_type.devices is actually used as a kset in + * drivers/base/bus.c, this function should be removed in favor of + * "device_find(kobj_name, &vio_bus_type)" + */ +static struct vio_dev *vio_find_name(const char *kobj_name) +{ + struct kobject *found; + + found = kset_find_obj(&devices_subsys.kset, kobj_name); + if (!found) + return NULL; + + return to_vio_dev(container_of(found, struct device, kobj)); +} + +/** + * vio_find_node - find an already-registered vio_dev + * @vnode: device_node of the virtual device we're looking for + */ +struct vio_dev *vio_find_node(struct device_node *vnode) +{ + uint32_t *unit_address; + char kobj_name[BUS_ID_SIZE]; + + /* construct the kobject name from the device node */ + unit_address = (uint32_t *)get_property(vnode, "reg", NULL); + if (!unit_address) + return NULL; + snprintf(kobj_name, BUS_ID_SIZE, "%x", *unit_address); + + return vio_find_name(kobj_name); +} +EXPORT_SYMBOL(vio_find_node); + +int vio_enable_interrupts(struct vio_dev *dev) +{ + int rc = h_vio_signal(dev->unit_address, VIO_IRQ_ENABLE); + if (rc != H_SUCCESS) + printk(KERN_ERR "vio: Error 0x%x enabling interrupts\n", rc); + return rc; +} +EXPORT_SYMBOL(vio_enable_interrupts); + +int vio_disable_interrupts(struct vio_dev *dev) +{ + int rc = h_vio_signal(dev->unit_address, VIO_IRQ_DISABLE); + if (rc != H_SUCCESS) + printk(KERN_ERR "vio: Error 0x%x disabling interrupts\n", rc); + return rc; +} +EXPORT_SYMBOL(vio_disable_interrupts); +#endif /* CONFIG_PPC_PSERIES */ diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile index ce8c0b943fa..7e67a20c18a 100644 --- a/arch/powerpc/platforms/iseries/Makefile +++ b/arch/powerpc/platforms/iseries/Makefile @@ -3,7 +3,6 @@ EXTRA_CFLAGS += -mno-minimal-toc obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o mf.o lpevents.o \ hvcall.o proc.o htab.o iommu.o misc.o irq.o obj-$(CONFIG_PCI) += pci.o vpdinfo.o -obj-$(CONFIG_IBMVIO) += vio.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_VIOPATH) += viopath.o obj-$(CONFIG_MODULES) += ksyms.o diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c index bea0b703f40..a8d96314c98 100644 --- a/arch/powerpc/platforms/iseries/iommu.c +++ b/arch/powerpc/platforms/iseries/iommu.c @@ -33,8 +33,7 @@ #include #include #include - -#include "iommu.h" +#include extern struct list_head iSeries_Global_Device_List; diff --git a/arch/powerpc/platforms/iseries/iommu.h b/arch/powerpc/platforms/iseries/iommu.h deleted file mode 100644 index cb5658fbe65..00000000000 --- a/arch/powerpc/platforms/iseries/iommu.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef _PLATFORMS_ISERIES_IOMMU_H -#define _PLATFORMS_ISERIES_IOMMU_H - -/* - * Copyright (C) 2005 Stephen Rothwell, IBM Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - */ - -struct device_node; -struct iommu_table; - -/* Creates table for an individual device node */ -extern void iommu_devnode_init_iSeries(struct device_node *dn); - -/* Get table parameters from HV */ -extern void iommu_table_getparms_iSeries(unsigned long busno, - unsigned char slotno, unsigned char virtbus, - struct iommu_table *tbl); - -#endif /* _PLATFORMS_ISERIES_IOMMU_H */ diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c index 5a61c6fdb33..428ffb5cf04 100644 --- a/arch/powerpc/platforms/iseries/pci.c +++ b/arch/powerpc/platforms/iseries/pci.c @@ -37,13 +37,13 @@ #include #include +#include #include #include "irq.h" #include "pci.h" #include "call_pci.h" -#include "iommu.h" /* * Forward declares of prototypes. diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c deleted file mode 100644 index bdd2b7d97d1..00000000000 --- a/arch/powerpc/platforms/iseries/vio.c +++ /dev/null @@ -1,67 +0,0 @@ -/* - * IBM PowerPC iSeries Virtual I/O Infrastructure Support. - * - * Copyright (c) 2005 Stephen Rothwell, IBM Corp. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "iommu.h" - -struct device *iSeries_vio_dev = &vio_bus_device.dev; -EXPORT_SYMBOL(iSeries_vio_dev); - -static struct iommu_table veth_iommu_table; -static struct iommu_table vio_iommu_table; - -static void __init iommu_vio_init(void) -{ - iommu_table_getparms_iSeries(255, 0, 0xff, &veth_iommu_table); - veth_iommu_table.it_size /= 2; - vio_iommu_table = veth_iommu_table; - vio_iommu_table.it_offset += veth_iommu_table.it_size; - - if (!iommu_init_table(&veth_iommu_table)) - printk("Virtual Bus VETH TCE table failed.\n"); - if (!iommu_init_table(&vio_iommu_table)) - printk("Virtual Bus VIO TCE table failed.\n"); -} - -static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev) -{ - if (strcmp(dev->type, "vlan") == 0) - return &veth_iommu_table; - return &vio_iommu_table; -} - -static struct vio_bus_ops vio_bus_ops_iseries = { - .build_iommu_table = vio_build_iommu_table, -}; - -/** - * vio_bus_init_iseries: - Initialize the iSeries virtual IO bus - */ -static int __init vio_bus_init_iseries(void) -{ - iommu_vio_init(); - vio_bus_device.iommu_table = &vio_iommu_table; - iSeries_vio_dev = &vio_bus_device.dev; - return vio_bus_init(&vio_bus_ops_iseries); -} -__initcall(vio_bus_init_iseries); diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index 930898635c9..b46ce3b9bb3 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile @@ -2,7 +2,6 @@ obj-y := pci.o lpar.o hvCall.o nvram.o reconfig.o \ setup.o iommu.o ras.o rtasd.o pci_dlpar.o \ firmware.o obj-$(CONFIG_SMP) += smp.o -obj-$(CONFIG_IBMVIO) += vio.o obj-$(CONFIG_XICS) += xics.o obj-$(CONFIG_SCANLOG) += scanlog.o obj-$(CONFIG_EEH) += eeh.o eeh_cache.o eeh_driver.o eeh_event.o diff --git a/arch/powerpc/platforms/pseries/vio.c b/arch/powerpc/platforms/pseries/vio.c deleted file mode 100644 index d2891661d87..00000000000 --- a/arch/powerpc/platforms/pseries/vio.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * IBM PowerPC pSeries Virtual I/O Infrastructure Support. - * - * Copyright (c) 2003-2005 IBM Corp. - * Dave Engebretsen engebret@us.ibm.com - * Santiago Leon santil@us.ibm.com - * Hollis Blanchard - * Stephen Rothwell - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -extern struct subsystem devices_subsys; /* needed for vio_find_name() */ - -/** - * vio_build_iommu_table: - gets the dma information from OF and - * builds the TCE tree. - * @dev: the virtual device. - * - * Returns a pointer to the built tce tree, or NULL if it can't - * find property. -*/ -static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev) -{ - unsigned int *dma_window; - struct iommu_table *newTceTable; - unsigned long offset; - int dma_window_property_size; - - dma_window = (unsigned int *) get_property(dev->dev.platform_data, "ibm,my-dma-window", &dma_window_property_size); - if(!dma_window) { - return NULL; - } - - newTceTable = (struct iommu_table *) kmalloc(sizeof(struct iommu_table), GFP_KERNEL); - - /* There should be some code to extract the phys-encoded offset - using prom_n_addr_cells(). However, according to a comment - on earlier versions, it's always zero, so we don't bother */ - offset = dma_window[1] >> PAGE_SHIFT; - - /* TCE table size - measured in tce entries */ - newTceTable->it_size = dma_window[4] >> PAGE_SHIFT; - /* offset for VIO should always be 0 */ - newTceTable->it_offset = offset; - newTceTable->it_busno = 0; - newTceTable->it_index = (unsigned long)dma_window[0]; - newTceTable->it_type = TCE_VB; - - return iommu_init_table(newTceTable); -} - -static struct vio_bus_ops vio_bus_ops_pseries = { - .build_iommu_table = vio_build_iommu_table, -}; - -/** - * vio_bus_init_pseries: - Initialize the pSeries virtual IO bus - */ -static int __init vio_bus_init_pseries(void) -{ - return vio_bus_init(&vio_bus_ops_pseries); -} - -__initcall(vio_bus_init_pseries); - -/* vio_find_name() - internal because only vio.c knows how we formatted the - * kobject name - * XXX once vio_bus_type.devices is actually used as a kset in - * drivers/base/bus.c, this function should be removed in favor of - * "device_find(kobj_name, &vio_bus_type)" - */ -static struct vio_dev *vio_find_name(const char *kobj_name) -{ - struct kobject *found; - - found = kset_find_obj(&devices_subsys.kset, kobj_name); - if (!found) - return NULL; - - return to_vio_dev(container_of(found, struct device, kobj)); -} - -/** - * vio_find_node - find an already-registered vio_dev - * @vnode: device_node of the virtual device we're looking for - */ -struct vio_dev *vio_find_node(struct device_node *vnode) -{ - uint32_t *unit_address; - char kobj_name[BUS_ID_SIZE]; - - /* construct the kobject name from the device node */ - unit_address = (uint32_t *)get_property(vnode, "reg", NULL); - if (!unit_address) - return NULL; - snprintf(kobj_name, BUS_ID_SIZE, "%x", *unit_address); - - return vio_find_name(kobj_name); -} -EXPORT_SYMBOL(vio_find_node); - -int vio_enable_interrupts(struct vio_dev *dev) -{ - int rc = h_vio_signal(dev->unit_address, VIO_IRQ_ENABLE); - if (rc != H_SUCCESS) - printk(KERN_ERR "vio: Error 0x%x enabling interrupts\n", rc); - return rc; -} -EXPORT_SYMBOL(vio_enable_interrupts); - -int vio_disable_interrupts(struct vio_dev *dev) -{ - int rc = h_vio_signal(dev->unit_address, VIO_IRQ_DISABLE); - if (rc != H_SUCCESS) - printk(KERN_ERR "vio: Error 0x%x disabling interrupts\n", rc); - return rc; -} -EXPORT_SYMBOL(vio_disable_interrupts); diff --git a/include/asm-powerpc/iseries/iommu.h b/include/asm-powerpc/iseries/iommu.h new file mode 100644 index 00000000000..0edbfe10cb3 --- /dev/null +++ b/include/asm-powerpc/iseries/iommu.h @@ -0,0 +1,35 @@ +#ifndef _ASM_POWERPC_ISERIES_IOMMU_H +#define _ASM_POWERPC_ISERIES_IOMMU_H + +/* + * Copyright (C) 2005 Stephen Rothwell, IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + */ + +struct device_node; +struct iommu_table; + +/* Creates table for an individual device node */ +extern void iommu_devnode_init_iSeries(struct device_node *dn); + +/* Get table parameters from HV */ +extern void iommu_table_getparms_iSeries(unsigned long busno, + unsigned char slotno, unsigned char virtbus, + struct iommu_table *tbl); + +#endif /* _ASM_POWERPC_ISERIES_IOMMU_H */ diff --git a/include/asm-powerpc/vio.h b/include/asm-powerpc/vio.h index 9c09a8ffa12..10da7f3af93 100644 --- a/include/asm-powerpc/vio.h +++ b/include/asm-powerpc/vio.h @@ -64,22 +64,14 @@ struct vio_driver { struct device_driver driver; }; -struct vio_bus_ops { - struct iommu_table *(*build_iommu_table)(struct vio_dev *dev); -}; - extern struct dma_mapping_ops vio_dma_ops; extern struct bus_type vio_bus_type; -extern struct vio_dev vio_bus_device; extern int vio_register_driver(struct vio_driver *drv); extern void vio_unregister_driver(struct vio_driver *drv); -extern struct vio_dev * __devinit vio_register_device(struct vio_dev *viodev); extern void __devinit vio_unregister_device(struct vio_dev *dev); -extern int vio_bus_init(struct vio_bus_ops *); - struct device_node; extern struct vio_dev * __devinit vio_register_device_node( -- cgit v1.2.3 From bc97ce951cfb697eaac9d5b6a2fbe4544fdf1a7c Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Fri, 28 Apr 2006 22:51:59 -0500 Subject: [PATCH] powerpc: kill union tce_entry It's been long overdue to kill the union tce_entry in the pSeries/iSeries TCE code, especially since I asked the Summit guys to do it on the code they copied from us. Also, while I was at it, I cleaned up some whitespace. Built and booted on pSeries, built on iSeries. Signed-off-by: Olof Johansson Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/iommu.c | 21 +++--- arch/powerpc/platforms/pseries/iommu.c | 122 ++++++++++++++------------------- include/asm-powerpc/tce.h | 35 +++------- 3 files changed, 71 insertions(+), 107 deletions(-) diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c index a8d96314c98..3ac22065c42 100644 --- a/arch/powerpc/platforms/iseries/iommu.c +++ b/arch/powerpc/platforms/iseries/iommu.c @@ -4,6 +4,7 @@ * Rewrite, cleanup: * * Copyright (C) 2004 Olof Johansson , IBM Corporation + * Copyright (C) 2006 Olof Johansson * * Dynamic DMA mapping support, iSeries-specific parts. * @@ -42,30 +43,28 @@ static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages, unsigned long uaddr, enum dma_data_direction direction) { u64 rc; - union tce_entry tce; + u64 tce, rpn; index <<= TCE_PAGE_FACTOR; npages <<= TCE_PAGE_FACTOR; while (npages--) { - tce.te_word = 0; - tce.te_bits.tb_rpn = virt_to_abs(uaddr) >> TCE_SHIFT; + rpn = virt_to_abs(uaddr) >> TCE_SHIFT; + tce = (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT; if (tbl->it_type == TCE_VB) { /* Virtual Bus */ - tce.te_bits.tb_valid = 1; - tce.te_bits.tb_allio = 1; + tce |= TCE_VALID|TCE_ALLIO; if (direction != DMA_TO_DEVICE) - tce.te_bits.tb_rdwr = 1; + tce |= TCE_VB_WRITE; } else { /* PCI Bus */ - tce.te_bits.tb_rdwr = 1; /* Read allowed */ + tce |= TCE_PCI_READ; /* Read allowed */ if (direction != DMA_TO_DEVICE) - tce.te_bits.tb_pciwr = 1; + tce |= TCE_PCI_WRITE; } - rc = HvCallXm_setTce((u64)tbl->it_index, (u64)index, - tce.te_word); + rc = HvCallXm_setTce((u64)tbl->it_index, (u64)index, tce); if (rc) panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%lx\n", rc); @@ -123,7 +122,7 @@ void iommu_table_getparms_iSeries(unsigned long busno, /* itc_size is in pages worth of table, it_size is in # of entries */ tbl->it_size = ((parms->itc_size * TCE_PAGE_SIZE) / - sizeof(union tce_entry)) >> TCE_PAGE_FACTOR; + TCE_ENTRY_SIZE) >> TCE_PAGE_FACTOR; tbl->it_busno = parms->itc_busno; tbl->it_offset = parms->itc_offset >> TCE_PAGE_FACTOR; tbl->it_index = parms->itc_index; diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 2643078433f..ed102f39068 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -1,23 +1,24 @@ /* * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation * - * Rewrite, cleanup: + * Rewrite, cleanup: * * Copyright (C) 2004 Olof Johansson , IBM Corporation + * Copyright (C) 2006 Olof Johansson * * Dynamic DMA mapping support, pSeries-specific parts, both SMP and LPAR. * - * + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA @@ -49,52 +50,46 @@ #define DBG(fmt...) -static void tce_build_pSeries(struct iommu_table *tbl, long index, - long npages, unsigned long uaddr, +static void tce_build_pSeries(struct iommu_table *tbl, long index, + long npages, unsigned long uaddr, enum dma_data_direction direction) { - union tce_entry t; - union tce_entry *tp; + u64 proto_tce; + u64 *tcep; + u64 rpn; index <<= TCE_PAGE_FACTOR; npages <<= TCE_PAGE_FACTOR; - t.te_word = 0; - t.te_rdwr = 1; // Read allowed + proto_tce = TCE_PCI_READ; // Read allowed if (direction != DMA_TO_DEVICE) - t.te_pciwr = 1; + proto_tce |= TCE_PCI_WRITE; - tp = ((union tce_entry *)tbl->it_base) + index; + tcep = ((u64 *)tbl->it_base) + index; while (npages--) { /* can't move this out since we might cross LMB boundary */ - t.te_rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT; - - tp->te_word = t.te_word; + rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT; + *tcep = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT; uaddr += TCE_PAGE_SIZE; - tp++; + tcep++; } } static void tce_free_pSeries(struct iommu_table *tbl, long index, long npages) { - union tce_entry t; - union tce_entry *tp; + u64 *tcep; npages <<= TCE_PAGE_FACTOR; index <<= TCE_PAGE_FACTOR; - t.te_word = 0; - tp = ((union tce_entry *)tbl->it_base) + index; - - while (npages--) { - tp->te_word = t.te_word; - - tp++; - } + tcep = ((u64 *)tbl->it_base) + index; + + while (npages--) + *(tcep++) = 0; } @@ -103,43 +98,44 @@ static void tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum, enum dma_data_direction direction) { u64 rc; - union tce_entry tce; + u64 proto_tce, tce; + u64 rpn; tcenum <<= TCE_PAGE_FACTOR; npages <<= TCE_PAGE_FACTOR; - tce.te_word = 0; - tce.te_rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT; - tce.te_rdwr = 1; + rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT; + proto_tce = TCE_PCI_READ; if (direction != DMA_TO_DEVICE) - tce.te_pciwr = 1; + proto_tce |= TCE_PCI_WRITE; while (npages--) { - rc = plpar_tce_put((u64)tbl->it_index, - (u64)tcenum << 12, - tce.te_word ); - + tce = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT; + rc = plpar_tce_put((u64)tbl->it_index, (u64)tcenum << 12, tce); + if (rc && printk_ratelimit()) { printk("tce_build_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc); printk("\tindex = 0x%lx\n", (u64)tbl->it_index); printk("\ttcenum = 0x%lx\n", (u64)tcenum); - printk("\ttce val = 0x%lx\n", tce.te_word ); + printk("\ttce val = 0x%lx\n", tce ); show_stack(current, (unsigned long *)__get_SP()); } - + tcenum++; - tce.te_rpn++; + rpn++; } } -static DEFINE_PER_CPU(void *, tce_page) = NULL; +static DEFINE_PER_CPU(u64 *, tce_page) = NULL; static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages, unsigned long uaddr, enum dma_data_direction direction) { u64 rc; - union tce_entry tce, *tcep; + u64 proto_tce; + u64 *tcep; + u64 rpn; long l, limit; if (TCE_PAGE_FACTOR == 0 && npages == 1) @@ -152,7 +148,7 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, * from iommu_alloc{,_sg}() */ if (!tcep) { - tcep = (void *)__get_free_page(GFP_ATOMIC); + tcep = (u64 *)__get_free_page(GFP_ATOMIC); /* If allocation fails, fall back to the loop implementation */ if (!tcep) return tce_build_pSeriesLP(tbl, tcenum, npages, @@ -163,11 +159,10 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, tcenum <<= TCE_PAGE_FACTOR; npages <<= TCE_PAGE_FACTOR; - tce.te_word = 0; - tce.te_rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT; - tce.te_rdwr = 1; + rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT; + proto_tce = TCE_PCI_READ; if (direction != DMA_TO_DEVICE) - tce.te_pciwr = 1; + proto_tce |= TCE_PCI_WRITE; /* We can map max one pageful of TCEs at a time */ do { @@ -175,11 +170,11 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, * Set up the page with TCE data, looping through and setting * the values. */ - limit = min_t(long, npages, 4096/sizeof(union tce_entry)); + limit = min_t(long, npages, 4096/TCE_ENTRY_SIZE); for (l = 0; l < limit; l++) { - tcep[l] = tce; - tce.te_rpn++; + tcep[l] = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT; + rpn++; } rc = plpar_tce_put_indirect((u64)tbl->it_index, @@ -195,7 +190,7 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, printk("tce_buildmulti_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc); printk("\tindex = 0x%lx\n", (u64)tbl->it_index); printk("\tnpages = 0x%lx\n", (u64)npages); - printk("\ttce[0] val = 0x%lx\n", tcep[0].te_word); + printk("\ttce[0] val = 0x%lx\n", tcep[0]); show_stack(current, (unsigned long *)__get_SP()); } } @@ -203,23 +198,17 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages) { u64 rc; - union tce_entry tce; tcenum <<= TCE_PAGE_FACTOR; npages <<= TCE_PAGE_FACTOR; - tce.te_word = 0; - while (npages--) { - rc = plpar_tce_put((u64)tbl->it_index, - (u64)tcenum << 12, - tce.te_word); + rc = plpar_tce_put((u64)tbl->it_index, (u64)tcenum << 12, 0); if (rc && printk_ratelimit()) { printk("tce_free_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc); printk("\tindex = 0x%lx\n", (u64)tbl->it_index); printk("\ttcenum = 0x%lx\n", (u64)tcenum); - printk("\ttce val = 0x%lx\n", tce.te_word ); show_stack(current, (unsigned long *)__get_SP()); } @@ -231,31 +220,24 @@ static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages static void tce_freemulti_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages) { u64 rc; - union tce_entry tce; tcenum <<= TCE_PAGE_FACTOR; npages <<= TCE_PAGE_FACTOR; - tce.te_word = 0; - - rc = plpar_tce_stuff((u64)tbl->it_index, - (u64)tcenum << 12, - tce.te_word, - npages); + rc = plpar_tce_stuff((u64)tbl->it_index, (u64)tcenum << 12, 0, npages); if (rc && printk_ratelimit()) { printk("tce_freemulti_pSeriesLP: plpar_tce_stuff failed\n"); printk("\trc = %ld\n", rc); printk("\tindex = 0x%lx\n", (u64)tbl->it_index); printk("\tnpages = 0x%lx\n", (u64)npages); - printk("\ttce val = 0x%lx\n", tce.te_word ); show_stack(current, (unsigned long *)__get_SP()); } } static void iommu_table_setparms(struct pci_controller *phb, struct device_node *dn, - struct iommu_table *tbl) + struct iommu_table *tbl) { struct device_node *node; unsigned long *basep; @@ -275,16 +257,16 @@ static void iommu_table_setparms(struct pci_controller *phb, memset((void *)tbl->it_base, 0, *sizep); tbl->it_busno = phb->bus->number; - + /* Units of tce entries */ tbl->it_offset = phb->dma_window_base_cur >> PAGE_SHIFT; - + /* Test if we are going over 2GB of DMA space */ if (phb->dma_window_base_cur + phb->dma_window_size > 0x80000000ul) { udbg_printf("PCI_DMA: Unexpected number of IOAs under this PHB.\n"); - panic("PCI_DMA: Unexpected number of IOAs under this PHB.\n"); + panic("PCI_DMA: Unexpected number of IOAs under this PHB.\n"); } - + phb->dma_window_base_cur += phb->dma_window_size; /* Set the tce table size - measured in entries */ @@ -442,7 +424,7 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus) tbl = (struct iommu_table *)kmalloc(sizeof(struct iommu_table), GFP_KERNEL); - + iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window); ppci->iommu_table = iommu_init_table(tbl); diff --git a/include/asm-powerpc/tce.h b/include/asm-powerpc/tce.h index 6fa200ad7a7..c9483adbf59 100644 --- a/include/asm-powerpc/tce.h +++ b/include/asm-powerpc/tce.h @@ -35,32 +35,15 @@ #define TCE_PAGE_SIZE (1 << TCE_SHIFT) #define TCE_PAGE_FACTOR (PAGE_SHIFT - TCE_SHIFT) - -/* tce_entry - * Used by pSeries (SMP) and iSeries/pSeries LPAR, but there it's - * abstracted so layout is irrelevant. - */ -union tce_entry { - unsigned long te_word; - struct { - unsigned int tb_cacheBits :6; /* Cache hash bits - not used */ - unsigned int tb_rsvd :6; - unsigned long tb_rpn :40; /* Real page number */ - unsigned int tb_valid :1; /* Tce is valid (vb only) */ - unsigned int tb_allio :1; /* Tce is valid for all lps (vb only) */ - unsigned int tb_lpindex :8; /* LpIndex for user of TCE (vb only) */ - unsigned int tb_pciwr :1; /* Write allowed (pci only) */ - unsigned int tb_rdwr :1; /* Read allowed (pci), Write allowed (vb) */ - } te_bits; -#define te_cacheBits te_bits.tb_cacheBits -#define te_rpn te_bits.tb_rpn -#define te_valid te_bits.tb_valid -#define te_allio te_bits.tb_allio -#define te_lpindex te_bits.tb_lpindex -#define te_pciwr te_bits.tb_pciwr -#define te_rdwr te_bits.tb_rdwr -}; - +#define TCE_ENTRY_SIZE 8 /* each TCE is 64 bits */ + +#define TCE_RPN_MASK 0xfffffffffful /* 40-bit RPN (4K pages) */ +#define TCE_RPN_SHIFT 12 +#define TCE_VALID 0x800 /* TCE valid */ +#define TCE_ALLIO 0x400 /* TCE valid for all lpars */ +#define TCE_PCI_WRITE 0x2 /* write from PCI allowed */ +#define TCE_PCI_READ 0x1 /* read from PCI allowed */ +#define TCE_VB_WRITE 0x1 /* write from VB allowed */ #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_TCE_H */ -- cgit v1.2.3 From a74e5e5facb854ab4be9e0320e0f65074012df9b Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Fri, 28 Apr 2006 08:57:09 -0500 Subject: [PATCH] powerpc iommu: minor cleanup A couple of minor renames: * The iommu_table is no longer a part of the device node structure, so devnode_table is misleading * Rename struct device *-variables to hwdev Signed-off-by: Olof Johansson Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/pci_iommu.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/arch/powerpc/kernel/pci_iommu.c b/arch/powerpc/kernel/pci_iommu.c index c1d95e14bbe..48aa82d0162 100644 --- a/arch/powerpc/kernel/pci_iommu.c +++ b/arch/powerpc/kernel/pci_iommu.c @@ -44,16 +44,16 @@ */ #define PCI_GET_DN(dev) ((struct device_node *)((dev)->sysdata)) -static inline struct iommu_table *devnode_table(struct device *dev) +static inline struct iommu_table *device_to_table(struct device *hwdev) { struct pci_dev *pdev; - if (!dev) { + if (!hwdev) { pdev = ppc64_isabridge_dev; if (!pdev) return NULL; } else - pdev = to_pci_dev(dev); + pdev = to_pci_dev(hwdev); return PCI_DN(PCI_GET_DN(pdev))->iommu_table; } @@ -85,14 +85,14 @@ static inline unsigned long device_to_mask(struct device *hwdev) static void *pci_iommu_alloc_coherent(struct device *hwdev, size_t size, dma_addr_t *dma_handle, gfp_t flag) { - return iommu_alloc_coherent(devnode_table(hwdev), size, dma_handle, + return iommu_alloc_coherent(device_to_table(hwdev), size, dma_handle, device_to_mask(hwdev), flag); } static void pci_iommu_free_coherent(struct device *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle) { - iommu_free_coherent(devnode_table(hwdev), size, vaddr, dma_handle); + iommu_free_coherent(device_to_table(hwdev), size, vaddr, dma_handle); } /* Creates TCEs for a user provided buffer. The user buffer must be @@ -104,7 +104,7 @@ static void pci_iommu_free_coherent(struct device *hwdev, size_t size, static dma_addr_t pci_iommu_map_single(struct device *hwdev, void *vaddr, size_t size, enum dma_data_direction direction) { - return iommu_map_single(devnode_table(hwdev), vaddr, size, + return iommu_map_single(device_to_table(hwdev), vaddr, size, device_to_mask(hwdev), direction); } @@ -112,27 +112,27 @@ static dma_addr_t pci_iommu_map_single(struct device *hwdev, void *vaddr, static void pci_iommu_unmap_single(struct device *hwdev, dma_addr_t dma_handle, size_t size, enum dma_data_direction direction) { - iommu_unmap_single(devnode_table(hwdev), dma_handle, size, direction); + iommu_unmap_single(device_to_table(hwdev), dma_handle, size, direction); } static int pci_iommu_map_sg(struct device *pdev, struct scatterlist *sglist, int nelems, enum dma_data_direction direction) { - return iommu_map_sg(pdev, devnode_table(pdev), sglist, + return iommu_map_sg(pdev, device_to_table(pdev), sglist, nelems, device_to_mask(pdev), direction); } static void pci_iommu_unmap_sg(struct device *pdev, struct scatterlist *sglist, int nelems, enum dma_data_direction direction) { - iommu_unmap_sg(devnode_table(pdev), sglist, nelems, direction); + iommu_unmap_sg(device_to_table(pdev), sglist, nelems, direction); } /* We support DMA to/from any memory page via the iommu */ static int pci_iommu_dma_supported(struct device *dev, u64 mask) { - struct iommu_table *tbl = devnode_table(dev); + struct iommu_table *tbl = device_to_table(dev); if (!tbl || tbl->it_offset > mask) { printk(KERN_INFO "Warning: IOMMU table offset too big for device mask\n"); -- cgit v1.2.3 From c5c4591375a10f6bc1bc55d86af7764033b10367 Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Fri, 28 Apr 2006 16:37:47 +0800 Subject: [PATCH] powerpc: cell: use kzalloc in alloc_spu_context() Use kzalloc when allocating a new spu context, rather than kmalloc + zeroing. Booted & tested on cell. Signed-off-by: Jeremy Kerr Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spufs/context.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c index 8bb33abfad1..36439c5e9f2 100644 --- a/arch/powerpc/platforms/cell/spufs/context.c +++ b/arch/powerpc/platforms/cell/spufs/context.c @@ -30,7 +30,7 @@ struct spu_context *alloc_spu_context(void) { struct spu_context *ctx; - ctx = kmalloc(sizeof *ctx, GFP_KERNEL); + ctx = kzalloc(sizeof *ctx, GFP_KERNEL); if (!ctx) goto out; /* Binding to physical processor deferred @@ -48,17 +48,7 @@ struct spu_context *alloc_spu_context(void) init_waitqueue_head(&ctx->wbox_wq); init_waitqueue_head(&ctx->stop_wq); init_waitqueue_head(&ctx->mfc_wq); - ctx->ibox_fasync = NULL; - ctx->wbox_fasync = NULL; - ctx->mfc_fasync = NULL; - ctx->mfc = NULL; - ctx->tagwait = 0; ctx->state = SPU_STATE_SAVED; - ctx->local_store = NULL; - ctx->cntl = NULL; - ctx->signal1 = NULL; - ctx->signal2 = NULL; - ctx->spu = NULL; ctx->ops = &spu_backing_ops; ctx->owner = get_task_mm(current); goto out; -- cgit v1.2.3 From 5a43ee65620d628ba04deecf241b63b2410b97f2 Mon Sep 17 00:00:00 2001 From: Will Schmidt Date: Wed, 26 Apr 2006 11:09:46 -0500 Subject: [PATCH] nvram_print_partitions cosmetic fixup This is a cosmetic fixup. When printing the nvram partition table, the first couple entries have a shorter 'index' value than the others, so table is a bit askew. This change makes the table look pretty. Tested on pseries and g5. Footnote: yes, this table is normally hidden behind a DEBUG_NVRAM #define. Signed-off-by: Will Schmidt Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/nvram_64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c index ada50aa5b60..6960f090991 100644 --- a/arch/powerpc/kernel/nvram_64.c +++ b/arch/powerpc/kernel/nvram_64.c @@ -204,7 +204,7 @@ static void nvram_print_partitions(char * label) printk(KERN_WARNING "indx\t\tsig\tchks\tlen\tname\n"); list_for_each(p, &nvram_part->partition) { tmp_part = list_entry(p, struct nvram_partition, partition); - printk(KERN_WARNING "%d \t%02x\t%02x\t%d\t%s\n", + printk(KERN_WARNING "%4d \t%02x\t%02x\t%d\t%s\n", tmp_part->index, tmp_part->header.signature, tmp_part->header.checksum, tmp_part->header.length, tmp_part->header.name); -- cgit v1.2.3 From 7e990266c845d7f712c96013891aaf74baef198f Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Fri, 5 May 2006 00:02:08 -0500 Subject: powerpc: provide ppc_md.panic() for both ppc32 & ppc64 Allow boards to provide a panic callback on ppc32. Moved the code to sets this up into setup-common.c so its shared between ppc32 & ppc64. Also moved do_init_bootmem prototype into setup.h. Signed-off-by: Kumar Gala --- arch/powerpc/kernel/setup-common.c | 17 +++++++++++++++++ arch/powerpc/kernel/setup.h | 2 ++ arch/powerpc/kernel/setup_32.c | 5 +++-- arch/powerpc/kernel/setup_64.c | 18 +----------------- 4 files changed, 23 insertions(+), 19 deletions(-) diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index 684ab1d49c6..88de557fe04 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c @@ -524,3 +524,20 @@ int check_legacy_ioport(unsigned long base_port) return ppc_md.check_legacy_ioport(base_port); } EXPORT_SYMBOL(check_legacy_ioport); + +static int ppc_panic_event(struct notifier_block *this, + unsigned long event, void *ptr) +{ + ppc_md.panic(ptr); /* May not return */ + return NOTIFY_DONE; +} + +static struct notifier_block ppc_panic_block = { + .notifier_call = ppc_panic_event, + .priority = INT_MIN /* may not return; must be done last */ +}; + +void __init setup_panic(void) +{ + atomic_notifier_chain_register(&panic_notifier_list, &ppc_panic_block); +} diff --git a/arch/powerpc/kernel/setup.h b/arch/powerpc/kernel/setup.h index 2ebba755272..e67066c1933 100644 --- a/arch/powerpc/kernel/setup.h +++ b/arch/powerpc/kernel/setup.h @@ -2,5 +2,7 @@ #define _POWERPC_KERNEL_SETUP_H void check_for_initrd(void); +void do_init_bootmem(void); +void setup_panic(void); #endif /* _POWERPC_KERNEL_SETUP_H */ diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index 69ac2570134..88832b3ee66 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c @@ -235,8 +235,6 @@ arch_initcall(ppc_init); /* Warning, IO base is not yet inited */ void __init setup_arch(char **cmdline_p) { - extern void do_init_bootmem(void); - /* so udelay does something sensible, assume <= 1000 bogomips */ loops_per_jiffy = 500000000 / HZ; @@ -285,6 +283,9 @@ void __init setup_arch(char **cmdline_p) /* reboot on panic */ panic_timeout = 180; + if (ppc_md.panic) + setup_panic(); + init_mm.start_code = PAGE_OFFSET; init_mm.end_code = (unsigned long) _etext; init_mm.end_data = (unsigned long) _edata; diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 4467c49903b..ab6ea37a77a 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -100,12 +100,6 @@ unsigned long SYSRQ_KEY; #endif /* CONFIG_MAGIC_SYSRQ */ -static int ppc64_panic_event(struct notifier_block *, unsigned long, void *); -static struct notifier_block ppc64_panic_block = { - .notifier_call = ppc64_panic_event, - .priority = INT_MIN /* may not return; must be done last */ -}; - #ifdef CONFIG_SMP static int smt_enabled_cmdline; @@ -456,13 +450,6 @@ void __init setup_system(void) DBG(" <- setup_system()\n"); } -static int ppc64_panic_event(struct notifier_block *this, - unsigned long event, void *ptr) -{ - ppc_md.panic((char *)ptr); /* May not return */ - return NOTIFY_DONE; -} - #ifdef CONFIG_IRQSTACKS static void __init irqstack_early_init(void) { @@ -517,8 +504,6 @@ static void __init emergency_stack_init(void) */ void __init setup_arch(char **cmdline_p) { - extern void do_init_bootmem(void); - ppc64_boot_msg(0x12, "Setup Arch"); *cmdline_p = cmd_line; @@ -535,8 +520,7 @@ void __init setup_arch(char **cmdline_p) panic_timeout = 180; if (ppc_md.panic) - atomic_notifier_chain_register(&panic_notifier_list, - &ppc64_panic_block); + setup_panic(); init_mm.start_code = PAGE_OFFSET; init_mm.end_code = (unsigned long) _etext; -- cgit v1.2.3 From 32e62c636a728cb39c0b3bd191286f2ca65d4028 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 5 May 2006 17:19:50 -0600 Subject: [IA64] rework memory attribute aliasing This closes a couple holes in our attribute aliasing avoidance scheme: - The current kernel fails mmaps of some /dev/mem MMIO regions because they don't appear in the EFI memory map. This keeps X from working on the Intel Tiger box. - The current kernel allows UC mmap of the 0-1MB region of /sys/.../legacy_mem even when the chipset doesn't support UC access. This causes an MCA when starting X on HP rx7620 and rx8620 boxes in the default configuration. There's more detail in the Documentation/ia64/aliasing.txt file this adds, but the general idea is that if a region might be covered by a granule-sized kernel identity mapping, any access via /dev/mem or mmap must use the same attribute as the identity mapping. Otherwise, we fall back to using an attribute that is supported according to the EFI memory map, or to using UC if the EFI memory map doesn't mention the region. Signed-off-by: Bjorn Helgaas Signed-off-by: Tony Luck --- Documentation/ia64/aliasing.txt | 208 ++++++++++++++++++++++++++++++++++++++++ arch/ia64/kernel/efi.c | 156 +++++++++++++++++++----------- arch/ia64/mm/ioremap.c | 27 +++++- arch/ia64/pci/pci.c | 17 +++- include/asm-ia64/io.h | 1 + include/asm-ia64/pgtable.h | 22 ++--- include/linux/efi.h | 1 + 7 files changed, 359 insertions(+), 73 deletions(-) create mode 100644 Documentation/ia64/aliasing.txt diff --git a/Documentation/ia64/aliasing.txt b/Documentation/ia64/aliasing.txt new file mode 100644 index 00000000000..38f9a52d182 --- /dev/null +++ b/Documentation/ia64/aliasing.txt @@ -0,0 +1,208 @@ + MEMORY ATTRIBUTE ALIASING ON IA-64 + + Bjorn Helgaas + + May 4, 2006 + + +MEMORY ATTRIBUTES + + Itanium supports several attributes for virtual memory references. + The attribute is part of the virtual translation, i.e., it is + contained in the TLB entry. The ones of most interest to the Linux + kernel are: + + WB Write-back (cacheable) + UC Uncacheable + WC Write-coalescing + + System memory typically uses the WB attribute. The UC attribute is + used for memory-mapped I/O devices. The WC attribute is uncacheable + like UC is, but writes may be delayed and combined to increase + performance for things like frame buffers. + + The Itanium architecture requires that we avoid accessing the same + page with both a cacheable mapping and an uncacheable mapping[1]. + + The design of the chipset determines which attributes are supported + on which regions of the address space. For example, some chipsets + support either WB or UC access to main memory, while others support + only WB access. + +MEMORY MAP + + Platform firmware describes the physical memory map and the + supported attributes for each region. At boot-time, the kernel uses + the EFI GetMemoryMap() interface. ACPI can also describe memory + devices and the attributes they support, but Linux/ia64 currently + doesn't use this information. + + The kernel uses the efi_memmap table returned from GetMemoryMap() to + learn the attributes supported by each region of physical address + space. Unfortunately, this table does not completely describe the + address space because some machines omit some or all of the MMIO + regions from the map. + + The kernel maintains another table, kern_memmap, which describes the + memory Linux is actually using and the attribute for each region. + This contains only system memory; it does not contain MMIO space. + + The kern_memmap table typically contains only a subset of the system + memory described by the efi_memmap. Linux/ia64 can't use all memory + in the system because of constraints imposed by the identity mapping + scheme. + + The efi_memmap table is preserved unmodified because the original + boot-time information is required for kexec. + +KERNEL IDENTITY MAPPINGS + + Linux/ia64 identity mappings are done with large pages, currently + either 16MB or 64MB, referred to as "granules." Cacheable mappings + are speculative[2], so the processor can read any location in the + page at any time, independent of the programmer's intentions. This + means that to avoid attribute aliasing, Linux can create a cacheable + identity mapping only when the entire granule supports cacheable + access. + + Therefore, kern_memmap contains only full granule-sized regions that + can referenced safely by an identity mapping. + + Uncacheable mappings are not speculative, so the processor will + generate UC accesses only to locations explicitly referenced by + software. This allows UC identity mappings to cover granules that + are only partially populated, or populated with a combination of UC + and WB regions. + +USER MAPPINGS + + User mappings are typically done with 16K or 64K pages. The smaller + page size allows more flexibility because only 16K or 64K has to be + homogeneous with respect to memory attributes. + +POTENTIAL ATTRIBUTE ALIASING CASES + + There are several ways the kernel creates new mappings: + + mmap of /dev/mem + + This uses remap_pfn_range(), which creates user mappings. These + mappings may be either WB or UC. If the region being mapped + happens to be in kern_memmap, meaning that it may also be mapped + by a kernel identity mapping, the user mapping must use the same + attribute as the kernel mapping. + + If the region is not in kern_memmap, the user mapping should use + an attribute reported as being supported in the EFI memory map. + + Since the EFI memory map does not describe MMIO on some + machines, this should use an uncacheable mapping as a fallback. + + mmap of /sys/class/pci_bus/.../legacy_mem + + This is very similar to mmap of /dev/mem, except that legacy_mem + only allows mmap of the one megabyte "legacy MMIO" area for a + specific PCI bus. Typically this is the first megabyte of + physical address space, but it may be different on machines with + several VGA devices. + + "X" uses this to access VGA frame buffers. Using legacy_mem + rather than /dev/mem allows multiple instances of X to talk to + different VGA cards. + + The /dev/mem mmap constraints apply. + + However, since this is for mapping legacy MMIO space, WB access + does not make sense. This matters on machines without legacy + VGA support: these machines may have WB memory for the entire + first megabyte (or even the entire first granule). + + On these machines, we could mmap legacy_mem as WB, which would + be safe in terms of attribute aliasing, but X has no way of + knowing that it is accessing regular memory, not a frame buffer, + so the kernel should fail the mmap rather than doing it with WB. + + read/write of /dev/mem + + This uses copy_from_user(), which implicitly uses a kernel + identity mapping. This is obviously safe for things in + kern_memmap. + + There may be corner cases of things that are not in kern_memmap, + but could be accessed this way. For example, registers in MMIO + space are not in kern_memmap, but could be accessed with a UC + mapping. This would not cause attribute aliasing. But + registers typically can be accessed only with four-byte or + eight-byte accesses, and the copy_from_user() path doesn't allow + any control over the access size, so this would be dangerous. + + ioremap() + + This returns a kernel identity mapping for use inside the + kernel. + + If the region is in kern_memmap, we should use the attribute + specified there. Otherwise, if the EFI memory map reports that + the entire granule supports WB, we should use that (granules + that are partially reserved or occupied by firmware do not appear + in kern_memmap). Otherwise, we should use a UC mapping. + +PAST PROBLEM CASES + + mmap of various MMIO regions from /dev/mem by "X" on Intel platforms + + The EFI memory map may not report these MMIO regions. + + These must be allowed so that X will work. This means that + when the EFI memory map is incomplete, every /dev/mem mmap must + succeed. It may create either WB or UC user mappings, depending + on whether the region is in kern_memmap or the EFI memory map. + + mmap of 0x0-0xA0000 /dev/mem by "hwinfo" on HP sx1000 with VGA enabled + + See https://bugzilla.novell.com/show_bug.cgi?id=140858. + + The EFI memory map reports the following attributes: + 0x00000-0x9FFFF WB only + 0xA0000-0xBFFFF UC only (VGA frame buffer) + 0xC0000-0xFFFFF WB only + + This mmap is done with user pages, not kernel identity mappings, + so it is safe to use WB mappings. + + The kernel VGA driver may ioremap the VGA frame buffer at 0xA0000, + which will use a granule-sized UC mapping covering 0-0xFFFFF. This + granule covers some WB-only memory, but since UC is non-speculative, + the processor will never generate an uncacheable reference to the + WB-only areas unless the driver explicitly touches them. + + mmap of 0x0-0xFFFFF legacy_mem by "X" + + If the EFI memory map reports this entire range as WB, there + is no VGA MMIO hole, and the mmap should fail or be done with + a WB mapping. + + There's no easy way for X to determine whether the 0xA0000-0xBFFFF + region is a frame buffer or just memory, so I think it's best to + just fail this mmap request rather than using a WB mapping. As + far as I know, there's no need to map legacy_mem with WB + mappings. + + Otherwise, a UC mapping of the entire region is probably safe. + The VGA hole means the region will not be in kern_memmap. The + HP sx1000 chipset doesn't support UC access to the memory surrounding + the VGA hole, but X doesn't need that area anyway and should not + reference it. + + mmap of 0xA0000-0xBFFFF legacy_mem by "X" on HP sx1000 with VGA disabled + + The EFI memory map reports the following attributes: + 0x00000-0xFFFFF WB only (no VGA MMIO hole) + + This is a special case of the previous case, and the mmap should + fail for the same reason as above. + +NOTES + + [1] SDM rev 2.2, vol 2, sec 4.4.1. + [2] SDM rev 2.2, vol 2, sec 4.4.6. diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c index 12cfedce73b..c33d0ba7e30 100644 --- a/arch/ia64/kernel/efi.c +++ b/arch/ia64/kernel/efi.c @@ -8,6 +8,8 @@ * Copyright (C) 1999-2003 Hewlett-Packard Co. * David Mosberger-Tang * Stephane Eranian + * (c) Copyright 2006 Hewlett-Packard Development Company, L.P. + * Bjorn Helgaas * * All EFI Runtime Services are not implemented yet as EFI only * supports physical mode addressing on SoftSDV. This is to be fixed @@ -622,28 +624,20 @@ efi_get_iobase (void) return 0; } -static efi_memory_desc_t * -efi_memory_descriptor (unsigned long phys_addr) +static struct kern_memdesc * +kern_memory_descriptor (unsigned long phys_addr) { - void *efi_map_start, *efi_map_end, *p; - efi_memory_desc_t *md; - u64 efi_desc_size; - - efi_map_start = __va(ia64_boot_param->efi_memmap); - efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; - efi_desc_size = ia64_boot_param->efi_memdesc_size; + struct kern_memdesc *md; - for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { - md = p; - - if (phys_addr - md->phys_addr < (md->num_pages << EFI_PAGE_SHIFT)) + for (md = kern_memmap; md->start != ~0UL; md++) { + if (phys_addr - md->start < (md->num_pages << EFI_PAGE_SHIFT)) return md; } return 0; } -static int -efi_memmap_has_mmio (void) +static efi_memory_desc_t * +efi_memory_descriptor (unsigned long phys_addr) { void *efi_map_start, *efi_map_end, *p; efi_memory_desc_t *md; @@ -656,8 +650,8 @@ efi_memmap_has_mmio (void) for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { md = p; - if (md->type == EFI_MEMORY_MAPPED_IO) - return 1; + if (phys_addr - md->phys_addr < (md->num_pages << EFI_PAGE_SHIFT)) + return md; } return 0; } @@ -683,71 +677,125 @@ efi_mem_attributes (unsigned long phys_addr) } EXPORT_SYMBOL(efi_mem_attributes); -/* - * Determines whether the memory at phys_addr supports the desired - * attribute (WB, UC, etc). If this returns 1, the caller can safely - * access size bytes at phys_addr with the specified attribute. - */ -int -efi_mem_attribute_range (unsigned long phys_addr, unsigned long size, u64 attr) +u64 +efi_mem_attribute (unsigned long phys_addr, unsigned long size) { unsigned long end = phys_addr + size; efi_memory_desc_t *md = efi_memory_descriptor(phys_addr); + u64 attr; + + if (!md) + return 0; + + /* + * EFI_MEMORY_RUNTIME is not a memory attribute; it just tells + * the kernel that firmware needs this region mapped. + */ + attr = md->attribute & ~EFI_MEMORY_RUNTIME; + do { + unsigned long md_end = efi_md_end(md); + + if (end <= md_end) + return attr; + + md = efi_memory_descriptor(md_end); + if (!md || (md->attribute & ~EFI_MEMORY_RUNTIME) != attr) + return 0; + } while (md); + return 0; +} + +u64 +kern_mem_attribute (unsigned long phys_addr, unsigned long size) +{ + unsigned long end = phys_addr + size; + struct kern_memdesc *md; + u64 attr; /* - * Some firmware doesn't report MMIO regions in the EFI memory - * map. The Intel BigSur (a.k.a. HP i2000) has this problem. - * On those platforms, we have to assume UC is valid everywhere. + * This is a hack for ioremap calls before we set up kern_memmap. + * Maybe we should do efi_memmap_init() earlier instead. */ - if (!md || (md->attribute & attr) != attr) { - if (attr == EFI_MEMORY_UC && !efi_memmap_has_mmio()) - return 1; + if (!kern_memmap) { + attr = efi_mem_attribute(phys_addr, size); + if (attr & EFI_MEMORY_WB) + return EFI_MEMORY_WB; return 0; } + md = kern_memory_descriptor(phys_addr); + if (!md) + return 0; + + attr = md->attribute; do { - unsigned long md_end = efi_md_end(md); + unsigned long md_end = kmd_end(md); if (end <= md_end) - return 1; + return attr; - md = efi_memory_descriptor(md_end); - if (!md || (md->attribute & attr) != attr) + md = kern_memory_descriptor(md_end); + if (!md || md->attribute != attr) return 0; } while (md); return 0; } +EXPORT_SYMBOL(kern_mem_attribute); -/* - * For /dev/mem, we only allow read & write system calls to access - * write-back memory, because read & write don't allow the user to - * control access size. - */ int valid_phys_addr_range (unsigned long phys_addr, unsigned long size) { - return efi_mem_attribute_range(phys_addr, size, EFI_MEMORY_WB); + u64 attr; + + /* + * /dev/mem reads and writes use copy_to_user(), which implicitly + * uses a granule-sized kernel identity mapping. It's really + * only safe to do this for regions in kern_memmap. For more + * details, see Documentation/ia64/aliasing.txt. + */ + attr = kern_mem_attribute(phys_addr, size); + if (attr & EFI_MEMORY_WB || attr & EFI_MEMORY_UC) + return 1; + return 0; } -/* - * We allow mmap of anything in the EFI memory map that supports - * either write-back or uncacheable access. For uncacheable regions, - * the supported access sizes are system-dependent, and the user is - * responsible for using the correct size. - * - * Note that this doesn't currently allow access to hot-added memory, - * because that doesn't appear in the boot-time EFI memory map. - */ int valid_mmap_phys_addr_range (unsigned long phys_addr, unsigned long size) { - if (efi_mem_attribute_range(phys_addr, size, EFI_MEMORY_WB)) - return 1; + /* + * MMIO regions are often missing from the EFI memory map. + * We must allow mmap of them for programs like X, so we + * currently can't do any useful validation. + */ + return 1; +} - if (efi_mem_attribute_range(phys_addr, size, EFI_MEMORY_UC)) - return 1; +pgprot_t +phys_mem_access_prot(struct file *file, unsigned long pfn, unsigned long size, + pgprot_t vma_prot) +{ + unsigned long phys_addr = pfn << PAGE_SHIFT; + u64 attr; - return 0; + /* + * For /dev/mem mmap, we use user mappings, but if the region is + * in kern_memmap (and hence may be covered by a kernel mapping), + * we must use the same attribute as the kernel mapping. + */ + attr = kern_mem_attribute(phys_addr, size); + if (attr & EFI_MEMORY_WB) + return pgprot_cacheable(vma_prot); + else if (attr & EFI_MEMORY_UC) + return pgprot_noncached(vma_prot); + + /* + * Some chipsets don't support UC access to memory. If + * WB is supported, we prefer that. + */ + if (efi_mem_attribute(phys_addr, size) & EFI_MEMORY_WB) + return pgprot_cacheable(vma_prot); + + return pgprot_noncached(vma_prot); } int __init diff --git a/arch/ia64/mm/ioremap.c b/arch/ia64/mm/ioremap.c index 643ccc6960c..07bd02b6c37 100644 --- a/arch/ia64/mm/ioremap.c +++ b/arch/ia64/mm/ioremap.c @@ -11,6 +11,7 @@ #include #include #include +#include static inline void __iomem * __ioremap (unsigned long offset, unsigned long size) @@ -21,16 +22,29 @@ __ioremap (unsigned long offset, unsigned long size) void __iomem * ioremap (unsigned long offset, unsigned long size) { - if (efi_mem_attribute_range(offset, size, EFI_MEMORY_WB)) - return phys_to_virt(offset); + u64 attr; + unsigned long gran_base, gran_size; - if (efi_mem_attribute_range(offset, size, EFI_MEMORY_UC)) + /* + * For things in kern_memmap, we must use the same attribute + * as the rest of the kernel. For more details, see + * Documentation/ia64/aliasing.txt. + */ + attr = kern_mem_attribute(offset, size); + if (attr & EFI_MEMORY_WB) + return phys_to_virt(offset); + else if (attr & EFI_MEMORY_UC) return __ioremap(offset, size); /* - * Someday this should check ACPI resources so we - * can do the right thing for hot-plugged regions. + * Some chipsets don't support UC access to memory. If + * WB is supported for the whole granule, we prefer that. */ + gran_base = GRANULEROUNDDOWN(offset); + gran_size = GRANULEROUNDUP(offset + size) - gran_base; + if (efi_mem_attribute(gran_base, gran_size) & EFI_MEMORY_WB) + return phys_to_virt(offset); + return __ioremap(offset, size); } EXPORT_SYMBOL(ioremap); @@ -38,6 +52,9 @@ EXPORT_SYMBOL(ioremap); void __iomem * ioremap_nocache (unsigned long offset, unsigned long size) { + if (kern_mem_attribute(offset, size) & EFI_MEMORY_WB) + return 0; + return __ioremap(offset, size); } EXPORT_SYMBOL(ioremap_nocache); diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index ab829a22f8a..30d148f3404 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -645,18 +645,31 @@ char *ia64_pci_get_legacy_mem(struct pci_bus *bus) int pci_mmap_legacy_page_range(struct pci_bus *bus, struct vm_area_struct *vma) { + unsigned long size = vma->vm_end - vma->vm_start; + pgprot_t prot; char *addr; + /* + * Avoid attribute aliasing. See Documentation/ia64/aliasing.txt + * for more details. + */ + if (!valid_mmap_phys_addr_range(vma->vm_pgoff << PAGE_SHIFT, size)) + return -EINVAL; + prot = phys_mem_access_prot(NULL, vma->vm_pgoff, size, + vma->vm_page_prot); + if (pgprot_val(prot) != pgprot_val(pgprot_noncached(vma->vm_page_prot))) + return -EINVAL; + addr = pci_get_legacy_mem(bus); if (IS_ERR(addr)) return PTR_ERR(addr); vma->vm_pgoff += (unsigned long)addr >> PAGE_SHIFT; - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + vma->vm_page_prot = prot; vma->vm_flags |= (VM_SHM | VM_RESERVED | VM_IO); if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, - vma->vm_end - vma->vm_start, vma->vm_page_prot)) + size, vma->vm_page_prot)) return -EAGAIN; return 0; diff --git a/include/asm-ia64/io.h b/include/asm-ia64/io.h index c2e3742108b..781ee2c7e8c 100644 --- a/include/asm-ia64/io.h +++ b/include/asm-ia64/io.h @@ -88,6 +88,7 @@ phys_to_virt (unsigned long address) } #define ARCH_HAS_VALID_PHYS_ADDR_RANGE +extern u64 kern_mem_attribute (unsigned long phys_addr, unsigned long size); extern int valid_phys_addr_range (unsigned long addr, size_t count); /* efi.c */ extern int valid_mmap_phys_addr_range (unsigned long addr, size_t count); diff --git a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h index c0f8144f234..90f3a232923 100644 --- a/include/asm-ia64/pgtable.h +++ b/include/asm-ia64/pgtable.h @@ -317,22 +317,20 @@ ia64_phys_addr_valid (unsigned long addr) #define pte_mkhuge(pte) (__pte(pte_val(pte))) /* - * Macro to a page protection value as "uncacheable". Note that "protection" is really a - * misnomer here as the protection value contains the memory attribute bits, dirty bits, - * and various other bits as well. + * Make page protection values cacheable, uncacheable, or write- + * combining. Note that "protection" is really a misnomer here as the + * protection value contains the memory attribute bits, dirty bits, and + * various other bits as well. */ +#define pgprot_cacheable(prot) __pgprot((pgprot_val(prot) & ~_PAGE_MA_MASK) | _PAGE_MA_WB) #define pgprot_noncached(prot) __pgprot((pgprot_val(prot) & ~_PAGE_MA_MASK) | _PAGE_MA_UC) - -/* - * Macro to make mark a page protection value as "write-combining". - * Note that "protection" is really a misnomer here as the protection - * value contains the memory attribute bits, dirty bits, and various - * other bits as well. Accesses through a write-combining translation - * works bypasses the caches, but does allow for consecutive writes to - * be combined into single (but larger) write transactions. - */ #define pgprot_writecombine(prot) __pgprot((pgprot_val(prot) & ~_PAGE_MA_MASK) | _PAGE_MA_WC) +struct file; +extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, + unsigned long size, pgprot_t vma_prot); +#define __HAVE_PHYS_MEM_ACCESS_PROT + static inline unsigned long pgd_index (unsigned long address) { diff --git a/include/linux/efi.h b/include/linux/efi.h index e203613d3ae..66d621dbcb6 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -294,6 +294,7 @@ extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if pos extern u64 efi_get_iobase (void); extern u32 efi_mem_type (unsigned long phys_addr); extern u64 efi_mem_attributes (unsigned long phys_addr); +extern u64 efi_mem_attribute (unsigned long phys_addr, unsigned long size); extern int efi_mem_attribute_range (unsigned long phys_addr, unsigned long size, u64 attr); extern int __init efi_uart_console_only (void); -- cgit v1.2.3 From 264faaaa12544e7914928ad57ccba21907cad56b Mon Sep 17 00:00:00 2001 From: Or Gerlitz Date: Tue, 2 May 2006 19:46:36 -0500 Subject: [SCSI] iscsi: add transport end point callbacks add transport end point callbacks so iscsi drivers that cannot connect from userspace, like iscsi tcp, using sockets do not have to implement their own socket infrastructure. Signed-off-by: Or Gerlitz Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/iscsi_tcp.c | 4 ++-- drivers/scsi/scsi_transport_iscsi.c | 41 ++++++++++++++++++++++++++++++++++++- include/scsi/iscsi_if.h | 19 ++++++++++++++++- include/scsi/scsi_transport_iscsi.h | 6 +++++- 4 files changed, 65 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index fe00a3f6d20..ac507daacfe 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -1975,7 +1975,7 @@ iscsi_tcp_conn_destroy(struct iscsi_cls_conn *cls_conn) static int iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session, - struct iscsi_cls_conn *cls_conn, uint32_t transport_fd, + struct iscsi_cls_conn *cls_conn, uint64_t transport_eph, int is_leading) { struct iscsi_conn *conn = cls_conn->dd_data; @@ -1985,7 +1985,7 @@ iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session, int err; /* lookup for existing socket */ - sock = sockfd_lookup(transport_fd, &err); + sock = sockfd_lookup((int)transport_eph, &err); if (!sock) { printk(KERN_ERR "iscsi_tcp: sockfd_lookup failed %d\n", err); return -EEXIST; diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index bc9071d2d21..7b7a194822d 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -928,6 +928,40 @@ iscsi_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev) return err; } +static int +iscsi_if_transport_ep(struct iscsi_transport *transport, + struct iscsi_uevent *ev, int msg_type) +{ + struct sockaddr *dst_addr; + int rc = 0; + + switch (msg_type) { + case ISCSI_UEVENT_TRANSPORT_EP_CONNECT: + if (!transport->ep_connect) + return -EINVAL; + + dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev)); + rc = transport->ep_connect(dst_addr, + ev->u.ep_connect.non_blocking, + &ev->r.ep_connect_ret.handle); + break; + case ISCSI_UEVENT_TRANSPORT_EP_POLL: + if (!transport->ep_poll) + return -EINVAL; + + ev->r.retcode = transport->ep_poll(ev->u.ep_poll.ep_handle, + ev->u.ep_poll.timeout_ms); + break; + case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT: + if (!transport->ep_disconnect) + return -EINVAL; + + transport->ep_disconnect(ev->u.ep_disconnect.ep_handle); + break; + } + return rc; +} + static int iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) { @@ -974,7 +1008,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) if (session && conn) ev->r.retcode = transport->bind_conn(session, conn, - ev->u.b_conn.transport_fd, + ev->u.b_conn.transport_eph, ev->u.b_conn.is_leading); else err = -EINVAL; @@ -1009,6 +1043,11 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) case ISCSI_UEVENT_GET_STATS: err = iscsi_if_get_stats(transport, nlh); break; + case ISCSI_UEVENT_TRANSPORT_EP_CONNECT: + case ISCSI_UEVENT_TRANSPORT_EP_POLL: + case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT: + err = iscsi_if_transport_ep(transport, ev, nlh->nlmsg_type); + break; default: err = -EINVAL; break; diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h index 47524c726ee..feff74e544b 100644 --- a/include/scsi/iscsi_if.h +++ b/include/scsi/iscsi_if.h @@ -43,6 +43,10 @@ enum iscsi_uevent_e { ISCSI_UEVENT_GET_STATS = UEVENT_BASE + 10, ISCSI_UEVENT_GET_PARAM = UEVENT_BASE + 11, + ISCSI_UEVENT_TRANSPORT_EP_CONNECT = UEVENT_BASE + 12, + ISCSI_UEVENT_TRANSPORT_EP_POLL = UEVENT_BASE + 13, + ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT = UEVENT_BASE + 14, + /* up events */ ISCSI_KEVENT_RECV_PDU = KEVENT_BASE + 1, ISCSI_KEVENT_CONN_ERROR = KEVENT_BASE + 2, @@ -69,7 +73,7 @@ struct iscsi_uevent { struct msg_bind_conn { uint32_t sid; uint32_t cid; - uint32_t transport_fd; + uint64_t transport_eph; uint32_t is_leading; } b_conn; struct msg_destroy_conn { @@ -102,6 +106,16 @@ struct iscsi_uevent { uint32_t sid; uint32_t cid; } get_stats; + struct msg_transport_connect { + uint32_t non_blocking; + } ep_connect; + struct msg_transport_poll { + uint64_t ep_handle; + uint32_t timeout_ms; + } ep_poll; + struct msg_transport_disconnect { + uint64_t ep_handle; + } ep_disconnect; } u; union { /* messages k -> u */ @@ -124,6 +138,9 @@ struct iscsi_uevent { uint32_t cid; uint32_t error; /* enum iscsi_err */ } connerror; + struct msg_transport_connect_ret { + uint64_t handle; + } ep_connect_ret; } r; } __attribute__ ((aligned (sizeof(uint64_t)))); diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index b332d6e839f..c9e9475c6df 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -88,7 +88,7 @@ struct iscsi_transport { uint32_t cid); int (*bind_conn) (struct iscsi_cls_session *session, struct iscsi_cls_conn *cls_conn, - uint32_t transport_fd, int is_leading); + uint64_t transport_eph, int is_leading); int (*start_conn) (struct iscsi_cls_conn *conn); void (*stop_conn) (struct iscsi_cls_conn *conn, int flag); void (*destroy_conn) (struct iscsi_cls_conn *conn); @@ -119,6 +119,10 @@ struct iscsi_transport { int (*xmit_mgmt_task) (struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask); void (*session_recovery_timedout) (struct iscsi_cls_session *session); + int (*ep_connect) (struct sockaddr *dst_addr, int non_blocking, + uint64_t *ep_handle); + int (*ep_poll) (uint64_t ep_handle, int timeout_ms); + void (*ep_disconnect) (uint64_t ep_handle); }; /* -- cgit v1.2.3 From ed2abc7ff19dc99c6242a70f8578a17b2ff0d0ce Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Tue, 2 May 2006 19:46:40 -0500 Subject: [SCSI] iscsi: fix manamgement task oops from patmans@us.ibm.com and michaelc@cs.wisc.edu Fix bugs when forcing a mgmt task to fail and allow session recovery to cleanup the session/connection of any running mgmt tasks. When called during the in login state. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/libiscsi.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 274a1374ab6..8c51f6c3666 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -1538,10 +1538,11 @@ flush_control_queues(struct iscsi_session *session, struct iscsi_conn *conn) /* handle running */ list_for_each_entry_safe(mtask, tmp, &conn->mgmt_run_list, running) { debug_scsi("flushing running mgmt task itt 0x%x\n", mtask->itt); + list_del(&mtask->running); + if (mtask == conn->login_mtask) continue; - list_del(&mtask->running); - __kfifo_put(session->mgmtpool.queue, (void*)&conn->mtask, + __kfifo_put(session->mgmtpool.queue, (void*)&mtask, sizeof(void*)); } @@ -1573,12 +1574,22 @@ static void fail_all_commands(struct iscsi_conn *conn) void iscsi_start_session_recovery(struct iscsi_session *session, struct iscsi_conn *conn, int flag) { + int old_stop_stage; + spin_lock_bh(&session->lock); - if (conn->stop_stage == STOP_CONN_RECOVER || - conn->stop_stage == STOP_CONN_TERM) { + if (conn->stop_stage == STOP_CONN_TERM) { spin_unlock_bh(&session->lock); return; } + + /* + * When this is called for the in_login state, we only want to clean + * up the login task and connection. + */ + if (conn->stop_stage != STOP_CONN_RECOVER) + session->conn_cnt--; + + old_stop_stage = conn->stop_stage; conn->stop_stage = flag; spin_unlock_bh(&session->lock); @@ -1590,7 +1601,6 @@ void iscsi_start_session_recovery(struct iscsi_session *session, conn->c_stage = ISCSI_CONN_STOPPED; set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); - session->conn_cnt--; if (session->conn_cnt == 0 || session->leadconn == conn) session->state = ISCSI_STATE_FAILED; @@ -1615,7 +1625,12 @@ void iscsi_start_session_recovery(struct iscsi_session *session, conn->hdrdgst_en = 0; conn->datadgst_en = 0; - if (session->state == ISCSI_STATE_FAILED) + /* + * if this is called from the eh and and from userspace + * then we only need to block once. + */ + if (session->state == ISCSI_STATE_FAILED && + old_stop_stage != STOP_CONN_RECOVER) iscsi_block_session(session_to_cls(session)); } mutex_unlock(&conn->xmitmutex); -- cgit v1.2.3 From be2df72e7ec5fa5e6e1ccccab6cef97ecbb9c191 Mon Sep 17 00:00:00 2001 From: Or Gerlitz Date: Tue, 2 May 2006 19:46:43 -0500 Subject: [SCSI] iscsi: align printks align printk output Signed-off-by: Or Gerlitz Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/iscsi_tcp.c | 3 ++- drivers/scsi/libiscsi.c | 29 +++++++++++++++-------------- drivers/scsi/scsi_transport_iscsi.c | 4 ++-- include/scsi/libiscsi.h | 2 +- 4 files changed, 20 insertions(+), 18 deletions(-) diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index ac507daacfe..41f4bb557ea 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -2585,7 +2585,8 @@ static int __init iscsi_tcp_init(void) { if (iscsi_max_lun < 1) { - printk(KERN_ERR "Invalid max_lun value of %u\n", iscsi_max_lun); + printk(KERN_ERR "iscsi_tcp: Invalid max_lun value of %u\n", + iscsi_max_lun); return -EINVAL; } iscsi_tcp_transport.max_lun = iscsi_max_lun; diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 8c51f6c3666..a99f2ef44e8 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -235,8 +235,8 @@ static int iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr, if (datalen < 2) { invalid_datalen: - printk(KERN_ERR "Got CHECK_CONDITION but invalid " - "data buffer size of %d\n", datalen); + printk(KERN_ERR "iscsi: Got CHECK_CONDITION but " + "invalid data buffer size of %d\n", datalen); sc->result = DID_BAD_TARGET << 16; goto out; } @@ -441,7 +441,7 @@ int iscsi_verify_itt(struct iscsi_conn *conn, struct iscsi_hdr *hdr, if (hdr->itt != cpu_to_be32(ISCSI_RESERVED_TAG)) { if ((hdr->itt & ISCSI_AGE_MASK) != (session->age << ISCSI_AGE_SHIFT)) { - printk(KERN_ERR "iscsi_tcp: received itt %x expected " + printk(KERN_ERR "iscsi: received itt %x expected " "session age (%x)\n", hdr->itt, session->age & ISCSI_AGE_MASK); return ISCSI_ERR_BAD_ITT; @@ -449,7 +449,7 @@ int iscsi_verify_itt(struct iscsi_conn *conn, struct iscsi_hdr *hdr, if ((hdr->itt & ISCSI_CID_MASK) != (conn->id << ISCSI_CID_SHIFT)) { - printk(KERN_ERR "iscsi_tcp: received itt %x, expected " + printk(KERN_ERR "iscsi: received itt %x, expected " "CID (%x)\n", hdr->itt, conn->id); return ISCSI_ERR_BAD_ITT; } @@ -461,14 +461,14 @@ int iscsi_verify_itt(struct iscsi_conn *conn, struct iscsi_hdr *hdr, ctask = session->cmds[itt]; if (!ctask->sc) { - printk(KERN_INFO "iscsi_tcp: dropping ctask with " + printk(KERN_INFO "iscsi: dropping ctask with " "itt 0x%x\n", ctask->itt); /* force drop */ return ISCSI_ERR_NO_SCSI_CMD; } if (ctask->sc->SCp.phase != session->age) { - printk(KERN_ERR "iscsi_tcp: ctask's session age %d, " + printk(KERN_ERR "iscsi: ctask's session age %d, " "expected %d\n", ctask->sc->SCp.phase, session->age); return ISCSI_ERR_SESSION_FAILED; @@ -686,7 +686,7 @@ reject: fault: spin_unlock(&session->lock); - printk(KERN_ERR "iscsi_tcp: cmd 0x%x is not queued (%d)\n", + printk(KERN_ERR "iscsi: cmd 0x%x is not queued (%d)\n", sc->cmnd[0], reason); sc->result = (DID_NO_CONNECT << 16); sc->resid = sc->request_bufflen; @@ -857,7 +857,7 @@ failed: spin_lock_bh(&session->lock); if (session->state == ISCSI_STATE_LOGGED_IN) - printk(KERN_INFO "host reset succeeded\n"); + printk(KERN_INFO "iscsi: host reset succeeded\n"); else goto failed; spin_unlock_bh(&session->lock); @@ -1042,8 +1042,8 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) /* what should we do here ? */ if (conn->ctask == ctask) { - printk(KERN_INFO "sc %p itt 0x%x partially sent. Failing " - "abort\n", sc, ctask->itt); + printk(KERN_INFO "iscsi: sc %p itt 0x%x partially sent. " + "Failing abort\n", sc, ctask->itt); goto failed; } @@ -1441,8 +1441,9 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) } spin_unlock_irqrestore(session->host->host_lock, flags); msleep_interruptible(500); - printk("conn_destroy(): host_busy %d host_failed %d\n", - session->host->host_busy, session->host->host_failed); + printk(KERN_INFO "iscsi: scsi conn_destroy(): host_busy %d " + "host_failed %d\n", session->host->host_busy, + session->host->host_failed); /* * force eh_abort() to unblock */ @@ -1662,7 +1663,7 @@ void iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) mutex_unlock(&conn->xmitmutex); break; default: - printk(KERN_ERR "invalid stop flag %d\n", flag); + printk(KERN_ERR "iscsi: invalid stop flag %d\n", flag); } } EXPORT_SYMBOL_GPL(iscsi_conn_stop); @@ -1679,7 +1680,7 @@ int iscsi_conn_bind(struct iscsi_cls_session *cls_session, if (tmp == conn) { if (conn->c_stage != ISCSI_CONN_STOPPED || conn->stop_stage == STOP_CONN_TERM) { - printk(KERN_ERR "iscsi_tcp: can't bind " + printk(KERN_ERR "iscsi: can't bind " "non-stopped connection (%d:%d)\n", conn->c_stage, conn->stop_stage); spin_unlock_bh(&session->lock); diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 7b7a194822d..1b96f7c4ce7 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -266,8 +266,8 @@ static void session_recovery_timedout(void *data) { struct iscsi_cls_session *session = data; - dev_printk(KERN_INFO, &session->dev, "session recovery timed out " - "after %d secs\n", session->recovery_tmo); + dev_printk(KERN_INFO, &session->dev, "iscsi: session recovery timed " + "out after %d secs\n", session->recovery_tmo); if (session->transport->session_recovery_timedout) session->transport->session_recovery_timedout(session); diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index 830700a4ed6..2dba929a2a0 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h @@ -41,7 +41,7 @@ struct iscsi_nopin; /* #define DEBUG_SCSI */ #ifdef DEBUG_SCSI -#define debug_scsi(fmt...) printk(KERN_INFO "scsi: " fmt) +#define debug_scsi(fmt...) printk(KERN_INFO "iscsi: " fmt) #else #define debug_scsi(fmt...) #endif -- cgit v1.2.3 From 8d2860b3c3e933304f49171770658c00ed26fd79 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Tue, 2 May 2006 19:46:47 -0500 Subject: [SCSI] iscsi: increment expstatsn during login debugged by Ming and Rohan: The problem Ming and Rohan debugged was that during a normal session login, open-iscsi is not incrementing the exp_statsn counter. It was stuck at zero. From the RFC, it looks like if the login response PDU has a successful status then we should be incrementing that value. Also from the RFC, it looks like if when we drop a connection then reconnect, we should be using the exp_statsn from the old connection in the next relogin attempt. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/iscsi_tcp.c | 9 ++++++++- drivers/scsi/libiscsi.c | 38 ++++++++++++++++++------------------- drivers/scsi/scsi_transport_iscsi.c | 4 +++- include/scsi/iscsi_if.h | 2 ++ 4 files changed, 32 insertions(+), 21 deletions(-) diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 41f4bb557ea..c0ce6ab81a9 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -2298,6 +2298,9 @@ iscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param, BUG_ON(value); session->ofmarker_en = value; break; + case ISCSI_PARAM_EXP_STATSN: + conn->exp_statsn = value; + break; default: break; } @@ -2381,6 +2384,9 @@ iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn, inet = inet_sk(tcp_conn->sock->sk); *value = be16_to_cpu(inet->dport); mutex_unlock(&conn->xmitmutex); + case ISCSI_PARAM_EXP_STATSN: + *value = conn->exp_statsn; + break; default: return -EINVAL; } @@ -2548,7 +2554,8 @@ static struct iscsi_transport iscsi_tcp_transport = { ISCSI_DATASEQ_INORDER_EN | ISCSI_ERL | ISCSI_CONN_PORT | - ISCSI_CONN_ADDRESS, + ISCSI_CONN_ADDRESS | + ISCSI_EXP_STATSN, .host_template = &iscsi_sht, .conndata_size = sizeof(struct iscsi_conn), .max_conn = 1, diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index a99f2ef44e8..4750d488810 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -333,15 +333,21 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, debug_scsi("immrsp [op 0x%x cid %d itt 0x%x len %d]\n", opcode, conn->id, mtask->itt, datalen); + rc = iscsi_check_assign_cmdsn(session, + (struct iscsi_nopin*)hdr); + if (rc) + goto done; + switch(opcode) { + case ISCSI_OP_LOGOUT_RSP: + conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; + /* fall through */ case ISCSI_OP_LOGIN_RSP: case ISCSI_OP_TEXT_RSP: - case ISCSI_OP_LOGOUT_RSP: - rc = iscsi_check_assign_cmdsn(session, - (struct iscsi_nopin*)hdr); - if (rc) - break; - + /* + * login related PDU's exp_statsn is handled in + * userspace + */ rc = iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen); list_del(&mtask->running); if (conn->login_mtask != mtask) @@ -349,15 +355,12 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, (void*)&mtask, sizeof(void*)); break; case ISCSI_OP_SCSI_TMFUNC_RSP: - rc = iscsi_check_assign_cmdsn(session, - (struct iscsi_nopin*)hdr); - if (rc) - break; - if (datalen) { rc = ISCSI_ERR_PROTO; break; } + + conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; conn->tmfrsp_pdus_cnt++; if (conn->tmabort_state == TMABORT_INITIAL) { conn->tmabort_state = @@ -373,10 +376,6 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, rc = ISCSI_ERR_PROTO; break; } - rc = iscsi_check_assign_cmdsn(session, - (struct iscsi_nopin*)hdr); - if (rc) - break; conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; rc = iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen); @@ -404,6 +403,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, case ISCSI_OP_REJECT: /* we need sth like iscsi_reject_rsp()*/ case ISCSI_OP_ASYNC_EVENT: + conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; /* we need sth like iscsi_async_event_rsp() */ rc = ISCSI_ERR_BAD_OPCODE; break; @@ -414,6 +414,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, } else rc = ISCSI_ERR_BAD_ITT; +done: return rc; } EXPORT_SYMBOL_GPL(__iscsi_complete_pdu); @@ -730,6 +731,7 @@ iscsi_conn_send_generic(struct iscsi_conn *conn, struct iscsi_hdr *hdr, BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE); BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED); + nop->exp_statsn = cpu_to_be32(conn->exp_statsn); if (!__kfifo_get(session->mgmtpool.queue, (void*)&mtask, sizeof(void*))) { spin_unlock_bh(&session->lock); @@ -738,7 +740,7 @@ iscsi_conn_send_generic(struct iscsi_conn *conn, struct iscsi_hdr *hdr, } /* - * pre-format CmdSN and ExpStatSN for outgoing PDU. + * pre-format CmdSN for outgoing PDU. */ if (hdr->itt != cpu_to_be32(ISCSI_RESERVED_TAG)) { hdr->itt = mtask->itt | (conn->id << ISCSI_CID_SHIFT) | @@ -751,8 +753,6 @@ iscsi_conn_send_generic(struct iscsi_conn *conn, struct iscsi_hdr *hdr, /* do not advance CmdSN */ nop->cmdsn = cpu_to_be32(session->cmdsn); - nop->exp_statsn = cpu_to_be32(conn->exp_statsn); - if (data_size) { memcpy(mtask->data, data, data_size); mtask->data_count = data_size; @@ -1647,7 +1647,7 @@ void iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) case STOP_CONN_RECOVER: case STOP_CONN_TERM: iscsi_start_session_recovery(session, conn, flag); - return; + break; case STOP_CONN_SUSPEND: if (session->tt->suspend_conn_recv) session->tt->suspend_conn_recv(conn); diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 1b96f7c4ce7..44adafac861 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -32,7 +32,7 @@ #include #define ISCSI_SESSION_ATTRS 11 -#define ISCSI_CONN_ATTRS 10 +#define ISCSI_CONN_ATTRS 11 #define ISCSI_HOST_ATTRS 0 struct iscsi_internal { @@ -1156,6 +1156,7 @@ iscsi_conn_int_attr(ifmarker, ISCSI_PARAM_IFMARKER_EN, "%d"); iscsi_conn_int_attr(ofmarker, ISCSI_PARAM_OFMARKER_EN, "%d"); iscsi_conn_int_attr(persistent_port, ISCSI_PARAM_PERSISTENT_PORT, "%d"); iscsi_conn_int_attr(port, ISCSI_PARAM_CONN_PORT, "%d"); +iscsi_conn_int_attr(exp_statsn, ISCSI_PARAM_EXP_STATSN, "%u"); #define iscsi_conn_str_attr_show(param) \ static ssize_t \ @@ -1406,6 +1407,7 @@ iscsi_register_transport(struct iscsi_transport *tt) SETUP_CONN_RD_ATTR(ofmarker, ISCSI_OFMARKER_EN); SETUP_CONN_RD_ATTR(address, ISCSI_CONN_ADDRESS); SETUP_CONN_RD_ATTR(port, ISCSI_CONN_PORT); + SETUP_CONN_RD_ATTR(exp_statsn, ISCSI_EXP_STATSN); if (tt->param_mask & ISCSI_PERSISTENT_ADDRESS) SETUP_CONN_RD_ATTR(persistent_address, ISCSI_PERSISTENT_ADDRESS); diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h index feff74e544b..253797c6009 100644 --- a/include/scsi/iscsi_if.h +++ b/include/scsi/iscsi_if.h @@ -188,6 +188,7 @@ enum iscsi_param { ISCSI_PARAM_ERL, ISCSI_PARAM_IFMARKER_EN, ISCSI_PARAM_OFMARKER_EN, + ISCSI_PARAM_EXP_STATSN, ISCSI_PARAM_TARGET_NAME, ISCSI_PARAM_TPGT, ISCSI_PARAM_PERSISTENT_ADDRESS, @@ -216,6 +217,7 @@ enum iscsi_param { #define ISCSI_ERL (1 << ISCSI_PARAM_ERL) #define ISCSI_IFMARKER_EN (1 << ISCSI_PARAM_IFMARKER_EN) #define ISCSI_OFMARKER_EN (1 << ISCSI_PARAM_OFMARKER_EN) +#define ISCSI_EXP_STATSN (1 << ISCSI_PARAM_EXP_STATSN) #define ISCSI_TARGET_NAME (1 << ISCSI_PARAM_TARGET_NAME) #define ISCSI_TPGT (1 << ISCSI_PARAM_TPGT) #define ISCSI_PERSISTENT_ADDRESS (1 << ISCSI_PARAM_PERSISTENT_ADDRESS) -- cgit v1.2.3 From 665b44aee34e9f2c64558df4ec01d40576e45651 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Tue, 2 May 2006 19:46:49 -0500 Subject: [SCSI] iscsi: dequeue all buffers from queue debugged by wrwhitehead@novell.com patch and analysis by fujita.tomonori@lab.ntt.co.jp Only tcp_read_sock and recv_actor (iscsi_tcp_data_recv for us) see desc.count. It is is used just for permitting tcp_read_sock to read the portion of data in the socket. When iscsi_tcp_data_recv sees a partial header, it sets desc.count. However, it is possible that the next skb (containing the rest of the header) still does not come. So I'm not sure that this scheme is completely correct. Ideally, we should use the exact length of the data in the socket for desc.count. However, it is not so simple (see SIOCINQ in tcp_ioctl). So I think that iscsi_tcp_data_recv can just stop playing with desc.count and tell tcp_read_sock to read the all skbs. As proposed already, if iscsi_tcp_data_ready sets desc.count to non-zero, tcp_read_sock does that. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/iscsi_tcp.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index c0ce6ab81a9..d94038eafb9 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -922,11 +922,8 @@ more: rc = iscsi_data_recv(conn); if (rc) { - if (rc == -EAGAIN) { - rd_desc->count = tcp_conn->in.datalen - - tcp_conn->in.ctask->data_count; + if (rc == -EAGAIN) goto again; - } iscsi_conn_failure(conn, rc); return 0; } @@ -983,9 +980,14 @@ iscsi_tcp_data_ready(struct sock *sk, int flag) read_lock(&sk->sk_callback_lock); - /* use rd_desc to pass 'conn' to iscsi_tcp_data_recv */ + /* + * Use rd_desc to pass 'conn' to iscsi_tcp_data_recv. + * We set count to 1 because we want the network layer to + * hand us all the skbs that are available. iscsi_tcp_data_recv + * handled pdus that cross buffers or pdus that still need data. + */ rd_desc.arg.data = conn; - rd_desc.count = 0; + rd_desc.count = 1; tcp_read_sock(sk, &rd_desc, iscsi_tcp_data_recv); read_unlock(&sk->sk_callback_lock); -- cgit v1.2.3 From 2ca48a132167f9f12efba179382979aafde0ab36 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Thu, 27 Apr 2006 14:07:49 -0500 Subject: [SCSI] fix proc_scsi_write to return "length" on success with remove-single-device case Problem spotted by: Suzuki K P A zero return on success isn't correct for filesystem write functions. They should either return negative error or the length of bytes consumed. Add code to convert our zero on success error return to return the length of bytes passed in. This fixes the following: $ echo "scsi remove-single-device 0 0 3 0" > /proc/scsi/scsi bash: echo: write error: No such device or address" Signed-off-by: James Bottomley --- drivers/scsi/scsi_proc.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c index 07be62bbaae..55200e4fdf1 100644 --- a/drivers/scsi/scsi_proc.c +++ b/drivers/scsi/scsi_proc.c @@ -266,8 +266,6 @@ static ssize_t proc_scsi_write(struct file *file, const char __user *buf, lun = simple_strtoul(p + 1, &p, 0); err = scsi_add_single_device(host, channel, id, lun); - if (err >= 0) - err = length; /* * Usage: echo "scsi remove-single-device 0 1 2 3" >/proc/scsi/scsi @@ -284,6 +282,13 @@ static ssize_t proc_scsi_write(struct file *file, const char __user *buf, err = scsi_remove_single_device(host, channel, id, lun); } + /* + * convert success returns so that we return the + * number of bytes consumed. + */ + if (!err) + err = length; + out: free_page((unsigned long)buffer); return err; -- cgit v1.2.3 From 9011bff4bdc0fef1f9a782d7415c306ee61826c9 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Thu, 11 May 2006 00:28:12 -0400 Subject: ACPI: delete newly added debugging macros in processor_perflib.c Signed-off-by: Len Brown --- drivers/acpi/processor_perflib.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index ffc5280334c..431a8450346 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -563,11 +563,9 @@ static int acpi_processor_get_psd(struct acpi_processor *pr) union acpi_object *psd = NULL; struct acpi_psd_package *pdomain; - ACPI_FUNCTION_TRACE("acpi_processor_get_psd"); - status = acpi_evaluate_object(pr->handle, "_PSD", NULL, &buffer); if (ACPI_FAILURE(status)) { - return_VALUE(-ENODEV); + return -ENODEV; } psd = (union acpi_object *) buffer.pointer; @@ -610,7 +608,7 @@ static int acpi_processor_get_psd(struct acpi_processor *pr) end: acpi_os_free(buffer.pointer); - return_VALUE(result); + return result; } int acpi_processor_preregister_performance( @@ -625,8 +623,6 @@ int acpi_processor_preregister_performance( struct acpi_processor *match_pr; struct acpi_psd_package *match_pdomain; - ACPI_FUNCTION_TRACE("acpi_processor_preregister_performance"); - down(&performance_sem); retval = 0; @@ -776,7 +772,7 @@ err_ret: } up(&performance_sem); - return_VALUE(retval); + return retval; } EXPORT_SYMBOL(acpi_processor_preregister_performance); -- cgit v1.2.3 From 5810452d00ae5fed7f720185d02d79ec9d15b91e Mon Sep 17 00:00:00 2001 From: Len Brown Date: Sat, 13 May 2006 01:12:15 -0400 Subject: ACPI: silence ia64 build warning When building sim_defconfig, which does not define CONFIG_ACPI arch/ia64/kernel/acpi.c:71: warning: 'acpi_madt_rev' defined but not used really acpi.c should not be built when CONFIG_ACPI=n... Signed-off-by: Len Brown --- arch/ia64/kernel/acpi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index 58c93a30348..f97cc6c7f13 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -68,8 +68,6 @@ EXPORT_SYMBOL(pm_power_off); unsigned char acpi_kbd_controller_present = 1; unsigned char acpi_legacy_devices; -static unsigned int __initdata acpi_madt_rev; - unsigned int acpi_cpei_override; unsigned int acpi_cpei_phys_cpuid; @@ -243,6 +241,8 @@ acpi_parse_iosapic(acpi_table_entry_header * header, const unsigned long end) return iosapic_init(iosapic->address, iosapic->global_irq_base); } +static unsigned int __initdata acpi_madt_rev; + static int __init acpi_parse_plat_int_src(acpi_table_entry_header * header, const unsigned long end) -- cgit v1.2.3 From 65c19bbd28cba587d9bd24feccf7272da18481a7 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Thu, 27 Apr 2006 05:25:00 -0400 Subject: sem2mutex: drivers/acpi/processor_perflib.c Semaphore to mutex conversion. The conversion was generated via scripts, and the result was validated automatically via a script as well. Signed-off-by: Arjan van de Ven Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/processor_perflib.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index abbdb37a7f5..7c6f97e9c72 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -34,6 +34,7 @@ #ifdef CONFIG_X86_ACPI_CPUFREQ_PROC_INTF #include #include +#include #include #endif @@ -48,7 +49,7 @@ #define _COMPONENT ACPI_PROCESSOR_COMPONENT ACPI_MODULE_NAME("acpi_processor") -static DECLARE_MUTEX(performance_sem); +static DEFINE_MUTEX(performance_mutex); /* * _PPC support is implemented as a CPUfreq policy notifier: @@ -72,7 +73,7 @@ static int acpi_processor_ppc_notifier(struct notifier_block *nb, struct acpi_processor *pr; unsigned int ppc = 0; - down(&performance_sem); + mutex_lock(&performance_mutex); if (event != CPUFREQ_INCOMPATIBLE) goto out; @@ -93,7 +94,7 @@ static int acpi_processor_ppc_notifier(struct notifier_block *nb, core_frequency * 1000); out: - up(&performance_sem); + mutex_unlock(&performance_mutex); return 0; } @@ -564,16 +565,16 @@ acpi_processor_register_performance(struct acpi_processor_performance if (!(acpi_processor_ppc_status & PPC_REGISTERED)) return_VALUE(-EINVAL); - down(&performance_sem); + mutex_lock(&performance_mutex); pr = processors[cpu]; if (!pr) { - up(&performance_sem); + mutex_unlock(&performance_mutex); return_VALUE(-ENODEV); } if (pr->performance) { - up(&performance_sem); + mutex_unlock(&performance_mutex); return_VALUE(-EBUSY); } @@ -581,13 +582,13 @@ acpi_processor_register_performance(struct acpi_processor_performance if (acpi_processor_get_performance_info(pr)) { pr->performance = NULL; - up(&performance_sem); + mutex_unlock(&performance_mutex); return_VALUE(-EIO); } acpi_cpufreq_add_file(pr); - up(&performance_sem); + mutex_unlock(&performance_mutex); return_VALUE(0); } @@ -601,11 +602,11 @@ acpi_processor_unregister_performance(struct acpi_processor_performance ACPI_FUNCTION_TRACE("acpi_processor_unregister_performance"); - down(&performance_sem); + mutex_lock(&performance_mutex); pr = processors[cpu]; if (!pr) { - up(&performance_sem); + mutex_unlock(&performance_mutex); return_VOID; } @@ -614,7 +615,7 @@ acpi_processor_unregister_performance(struct acpi_processor_performance acpi_cpufreq_remove_file(pr); - up(&performance_sem); + mutex_unlock(&performance_mutex); return_VOID; } -- cgit v1.2.3 From 415d320a2384bb80d2be98b1dfa41594e085012d Mon Sep 17 00:00:00 2001 From: Len Brown Date: Sat, 13 May 2006 21:35:56 -0400 Subject: ACPI: delete unused acpi_bus_drivers_lock acpi_bus_drivers is protected by acpi_device_lock Signed-off-by: Len Brown --- drivers/acpi/scan.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index a0ab828b2cc..2cb3b0916eb 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -471,7 +471,6 @@ static int acpi_bus_get_perf_flags(struct acpi_device *device) -------------------------------------------------------------------------- */ static LIST_HEAD(acpi_bus_drivers); -static DECLARE_MUTEX(acpi_bus_drivers_lock); /** * acpi_bus_match - match device IDs to driver's supported IDs -- cgit v1.2.3 From 36e430951af0b0d1bdfd50ce22e70079d02646df Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 27 Apr 2006 05:25:00 -0400 Subject: sem2mutex: acpi, acpi_link_lock Semaphore to mutex conversion. The conversion was generated via scripts, and the result was validated automatically via a script as well. Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/pci_link.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index 07bc6dfe662..b55ad1add1b 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -91,7 +92,7 @@ static struct { int count; struct list_head entries; } acpi_link; -DECLARE_MUTEX(acpi_link_lock); +DEFINE_MUTEX(acpi_link_lock); /* -------------------------------------------------------------------------- PCI Link Device Management @@ -641,19 +642,19 @@ acpi_pci_link_allocate_irq(acpi_handle handle, return_VALUE(-1); } - down(&acpi_link_lock); + mutex_lock(&acpi_link_lock); if (acpi_pci_link_allocate(link)) { - up(&acpi_link_lock); + mutex_unlock(&acpi_link_lock); return_VALUE(-1); } if (!link->irq.active) { - up(&acpi_link_lock); + mutex_unlock(&acpi_link_lock); ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link active IRQ is 0!\n")); return_VALUE(-1); } link->refcnt++; - up(&acpi_link_lock); + mutex_unlock(&acpi_link_lock); if (triggering) *triggering = link->irq.triggering; @@ -691,9 +692,9 @@ int acpi_pci_link_free_irq(acpi_handle handle) return_VALUE(-1); } - down(&acpi_link_lock); + mutex_lock(&acpi_link_lock); if (!link->irq.initialized) { - up(&acpi_link_lock); + mutex_unlock(&acpi_link_lock); ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link isn't initialized\n")); return_VALUE(-1); } @@ -716,7 +717,7 @@ int acpi_pci_link_free_irq(acpi_handle handle) if (link->refcnt == 0) { acpi_ut_evaluate_object(link->handle, "_DIS", 0, NULL); } - up(&acpi_link_lock); + mutex_unlock(&acpi_link_lock); return_VALUE(link->irq.active); } @@ -747,7 +748,7 @@ static int acpi_pci_link_add(struct acpi_device *device) strcpy(acpi_device_class(device), ACPI_PCI_LINK_CLASS); acpi_driver_data(device) = link; - down(&acpi_link_lock); + mutex_lock(&acpi_link_lock); result = acpi_pci_link_get_possible(link); if (result) goto end; @@ -782,7 +783,7 @@ static int acpi_pci_link_add(struct acpi_device *device) end: /* disable all links -- to be activated on use */ acpi_ut_evaluate_object(link->handle, "_DIS", 0, NULL); - up(&acpi_link_lock); + mutex_unlock(&acpi_link_lock); if (result) kfree(link); @@ -837,9 +838,9 @@ static int acpi_pci_link_remove(struct acpi_device *device, int type) link = (struct acpi_pci_link *)acpi_driver_data(device); - down(&acpi_link_lock); + mutex_lock(&acpi_link_lock); list_del(&link->node); - up(&acpi_link_lock); + mutex_unlock(&acpi_link_lock); kfree(link); -- cgit v1.2.3 From 193de0c79da580eb33a66113b62e2378fc1fb629 Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Thu, 27 Apr 2006 05:25:00 -0400 Subject: ACPI: use for_each_possible_cpu() instead of for_each_cpu() for_each_cpu() actually iterates across all possible CPUs. We've had mistakes in the past where people were using for_each_cpu() where they should have been iterating across only online or present CPUs. This is inefficient and possibly buggy. We're renaming for_each_cpu() to for_each_possible_cpu() to avoid this in the future. Signed-off-by: KAMEZAWA Hiroyuki Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/processor_perflib.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 431a8450346..cf6167003d8 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -628,7 +628,7 @@ int acpi_processor_preregister_performance( retval = 0; /* Call _PSD for all CPUs */ - for_each_cpu(i) { + for_each_possible_cpu(i) { pr = processors[i]; if (!pr) { /* Look only at processors in ACPI namespace */ @@ -659,7 +659,7 @@ int acpi_processor_preregister_performance( * Now that we have _PSD data from all CPUs, lets setup P-state * domain info. */ - for_each_cpu(i) { + for_each_possible_cpu(i) { pr = processors[i]; if (!pr) continue; @@ -680,7 +680,7 @@ int acpi_processor_preregister_performance( } cpus_clear(covered_cpus); - for_each_cpu(i) { + for_each_possible_cpu(i) { pr = processors[i]; if (!pr) continue; @@ -704,7 +704,7 @@ int acpi_processor_preregister_performance( pr->performance->shared_type = CPUFREQ_SHARED_TYPE_ANY; } - for_each_cpu(j) { + for_each_possible_cpu(j) { if (i == j) continue; @@ -733,7 +733,7 @@ int acpi_processor_preregister_performance( count++; } - for_each_cpu(j) { + for_each_possible_cpu(j) { if (i == j) continue; @@ -757,7 +757,7 @@ err_ret: ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error while parsing _PSD domain information. Assuming no coordination\n")); } - for_each_cpu(i) { + for_each_possible_cpu(i) { pr = processors[i]; if (!pr || !pr->performance) continue; -- cgit v1.2.3 From 06ea8e08ae7e7e450b6a78e7ce5e10b3c5f954ea Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 27 Apr 2006 05:25:00 -0400 Subject: ACPI: acpi_bus_unregister_driver() returns void Nobody looks at the return value, and this brings it into line with pci_unregister_driver(), etc. Also removed validation of the driver pointer passed in to register and unregister. More consistent, and we'll find bugs faster if we fault rather than returning an error that's ignored. Also makes internal functions acpi_device_unregister() and acpi_driver_detach() void, since nobody uses their returns either. Signed-off-by: Bjorn Helgaas Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/scan.c | 32 ++++++++++---------------------- include/acpi/acpi_bus.h | 2 +- 2 files changed, 11 insertions(+), 23 deletions(-) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 669553553fb..e8efaac71e7 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -142,7 +142,7 @@ static void acpi_device_register(struct acpi_device *device, create_sysfs_device_files(device); } -static int acpi_device_unregister(struct acpi_device *device, int type) +static void acpi_device_unregister(struct acpi_device *device, int type) { spin_lock(&acpi_device_lock); if (device->parent) { @@ -158,7 +158,6 @@ static int acpi_device_unregister(struct acpi_device *device, int type) acpi_detach_data(device->handle, acpi_bus_data_handler); remove_sysfs_device_files(device); kobject_unregister(&device->kobj); - return 0; } void acpi_bus_data_handler(acpi_handle handle, u32 function, void *context) @@ -577,7 +576,7 @@ static void acpi_driver_attach(struct acpi_driver *drv) spin_unlock(&acpi_device_lock); } -static int acpi_driver_detach(struct acpi_driver *drv) +static void acpi_driver_detach(struct acpi_driver *drv) { struct list_head *node, *next; @@ -599,7 +598,6 @@ static int acpi_driver_detach(struct acpi_driver *drv) } } spin_unlock(&acpi_device_lock); - return_VALUE(0); } /** @@ -617,9 +615,6 @@ int acpi_bus_register_driver(struct acpi_driver *driver) if (acpi_disabled) return_VALUE(-ENODEV); - if (!driver) - return_VALUE(-EINVAL); - spin_lock(&acpi_device_lock); list_add_tail(&driver->node, &acpi_bus_drivers); spin_unlock(&acpi_device_lock); @@ -637,23 +632,16 @@ EXPORT_SYMBOL(acpi_bus_register_driver); * Unregisters a driver with the ACPI bus. Searches the namespace for all * devices that match the driver's criteria and unbinds. */ -int acpi_bus_unregister_driver(struct acpi_driver *driver) +void acpi_bus_unregister_driver(struct acpi_driver *driver) { - int error = 0; - - ACPI_FUNCTION_TRACE("acpi_bus_unregister_driver"); - - if (driver) { - acpi_driver_detach(driver); + acpi_driver_detach(driver); - if (!atomic_read(&driver->references)) { - spin_lock(&acpi_device_lock); - list_del_init(&driver->node); - spin_unlock(&acpi_device_lock); - } - } else - error = -EINVAL; - return_VALUE(error); + if (!atomic_read(&driver->references)) { + spin_lock(&acpi_device_lock); + list_del_init(&driver->node); + spin_unlock(&acpi_device_lock); + } + return; } EXPORT_SYMBOL(acpi_bus_unregister_driver); diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 6dca3d54208..809eb501a22 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -327,7 +327,7 @@ int acpi_bus_set_power(acpi_handle handle, int state); int acpi_bus_generate_event(struct acpi_device *device, u8 type, int data); int acpi_bus_receive_event(struct acpi_bus_event *event); int acpi_bus_register_driver(struct acpi_driver *driver); -int acpi_bus_unregister_driver(struct acpi_driver *driver); +void acpi_bus_unregister_driver(struct acpi_driver *driver); int acpi_bus_add(struct acpi_device **child, struct acpi_device *parent, acpi_handle handle, int type); int acpi_bus_trim(struct acpi_device *start, int rmdevice); -- cgit v1.2.3 From 64385f2fd8bc9d8803c8d10dcd391871cb126b77 Mon Sep 17 00:00:00 2001 From: Vasily Averin Date: Thu, 27 Apr 2006 05:25:00 -0400 Subject: ACPI: fix potential memory leak in acpi_evaluate_integer() error path Signed-off-by: Vasily Averin Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/utils.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index 6458c47f7ac..6b516852ac1 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -273,11 +273,13 @@ acpi_evaluate_integer(acpi_handle handle, status = acpi_evaluate_object(handle, pathname, arguments, &buffer); if (ACPI_FAILURE(status)) { acpi_util_eval_error(handle, pathname, status); + kfree(element); return_ACPI_STATUS(status); } if (element->type != ACPI_TYPE_INTEGER) { acpi_util_eval_error(handle, pathname, AE_BAD_DATA); + kfree(element); return_ACPI_STATUS(AE_BAD_DATA); } -- cgit v1.2.3 From 09047e75f69428dcfa977b326256085154068b65 Mon Sep 17 00:00:00 2001 From: Vasily Averin Date: Thu, 27 Apr 2006 05:25:00 -0400 Subject: ACPI: fix memory leak in acpi_thermal_add() error path Signed-off-by: Vasily Averin Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/thermal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 19f3ea48475..82389b17813 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -1342,7 +1342,7 @@ static int acpi_thermal_add(struct acpi_device *device) result = acpi_thermal_add_fs(device); if (result) - return_VALUE(result); + goto end; init_timer(&tz->timer); -- cgit v1.2.3 From b6835052a6aa00536343b6d2127fc65cd814a040 Mon Sep 17 00:00:00 2001 From: Andreas Mohr Date: Thu, 27 Apr 2006 05:25:00 -0400 Subject: ACPI: apply "__read_mostly" to processor_idle.c loop module parameters and friends make pm_idle_save, nocst and bm_history __read_mostly remove initializer from static 'first_run'. Signed-off-by: Andreas Mohr Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/processor_idle.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 80fa43471f4..3b97a5eae9e 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -54,10 +54,10 @@ ACPI_MODULE_NAME("acpi_processor") #define US_TO_PM_TIMER_TICKS(t) ((t * (PM_TIMER_FREQUENCY/1000)) / 1000) #define C2_OVERHEAD 4 /* 1us (3.579 ticks per us) */ #define C3_OVERHEAD 4 /* 1us (3.579 ticks per us) */ -static void (*pm_idle_save) (void); +static void (*pm_idle_save) (void) __read_mostly; module_param(max_cstate, uint, 0644); -static unsigned int nocst = 0; +static unsigned int nocst __read_mostly; module_param(nocst, uint, 0000); /* @@ -67,7 +67,7 @@ module_param(nocst, uint, 0000); * 100 HZ: 0x0000000F: 4 jiffies = 40ms * reduce history for more aggressive entry into C3 */ -static unsigned int bm_history = +static unsigned int bm_history __read_mostly = (HZ >= 800 ? 0xFFFFFFFF : ((1U << (HZ / 25)) - 1)); module_param(bm_history, uint, 0644); /* -------------------------------------------------------------------------- @@ -1081,7 +1081,7 @@ int acpi_processor_power_init(struct acpi_processor *pr, struct acpi_device *device) { acpi_status status = 0; - static int first_run = 0; + static int first_run; struct proc_dir_entry *entry = NULL; unsigned int i; -- cgit v1.2.3 From ebd5f2ca811b75f7145fa487748f26430c584a72 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 13 May 2006 22:56:00 -0400 Subject: ACPI: asus_acpi_init(): propagate correct return value Cc: Bjorn Helgaas Acked-by: Francois Romieu Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/asus_acpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c index f4c87750dbf..fccbf938ea0 100644 --- a/drivers/acpi/asus_acpi.c +++ b/drivers/acpi/asus_acpi.c @@ -1229,7 +1229,7 @@ static int __init asus_acpi_init(void) if (result < 1) { acpi_bus_unregister_driver(&asus_hotk_driver); remove_proc_entry(PROC_ASUS, acpi_root_dir); - return -ENODEV; + return result; } return 0; -- cgit v1.2.3 From 973bf491a55b825740f0d8d300b50bcd3d6fb8de Mon Sep 17 00:00:00 2001 From: "Yu, Luming" Date: Thu, 27 Apr 2006 05:25:00 -0400 Subject: ACPI: fix potential memory leaks in driver/acpi/video.c acpi_video_bus_get_one_device() and other functions in driver/acpi/video.c do not release allocated memory on remove and on the error path. Signed-off-by: "Yu, Luming" Signed-off-by: Vasily Averin Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/video.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index bd488751837..fcefcb104b3 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -1294,7 +1294,7 @@ acpi_video_bus_get_one_device(struct acpi_device *device, struct acpi_video_bus *video) { unsigned long device_id; - int status, result; + int status; struct acpi_video_device *data; ACPI_FUNCTION_TRACE("acpi_video_bus_get_one_device"); @@ -1346,8 +1346,11 @@ acpi_video_bus_get_one_device(struct acpi_device *device, if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error installing notify handler\n")); - result = -ENODEV; - goto end; + if(data->brightness) + kfree(data->brightness->levels); + kfree(data->brightness); + kfree(data); + return -ENODEV; } down(&video->sem); @@ -1359,7 +1362,6 @@ acpi_video_bus_get_one_device(struct acpi_device *device, return_VALUE(0); } - end: return_VALUE(-ENOENT); } @@ -1643,8 +1645,9 @@ static int acpi_video_bus_put_devices(struct acpi_video_bus *video) printk(KERN_WARNING PREFIX "hhuuhhuu bug in acpi video driver.\n"); + if (data->brightness); + kfree(data->brightness->levels); kfree(data->brightness); - kfree(data); } @@ -1785,6 +1788,10 @@ static int acpi_video_bus_add(struct acpi_device *device) if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error installing notify handler\n")); + acpi_video_bus_stop_devices(video); + acpi_video_bus_put_devices(video); + kfree(video->attached_array); + acpi_video_bus_remove_fs(device); result = -ENODEV; goto end; } @@ -1796,10 +1803,8 @@ static int acpi_video_bus_add(struct acpi_device *device) video->flags.post ? "yes" : "no"); end: - if (result) { - acpi_video_bus_remove_fs(device); + if (result) kfree(video); - } return_VALUE(result); } -- cgit v1.2.3 From 9c576ff1bc9ab42d06457e68e39c121481138562 Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Thu, 27 Apr 2006 05:25:00 -0400 Subject: ACPI add ia64 exports to build acpi_memhotplug as a module Signed-off-by: KAMEZAWA Hiroyuki Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- arch/ia64/mm/init.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c index cafa8776a53..11f08001f8c 100644 --- a/arch/ia64/mm/init.c +++ b/arch/ia64/mm/init.c @@ -671,9 +671,11 @@ int add_memory(u64 start, u64 size) return ret; } +EXPORT_SYMBOL_GPL(add_memory); int remove_memory(u64 start, u64 size) { return -EINVAL; } +EXPORT_SYMBOL_GPL(remove_memory); #endif -- cgit v1.2.3 From 5b3272655a8e8a9a6e2503bc5a88fc9d9c8292a4 Mon Sep 17 00:00:00 2001 From: Patrick Mochel Date: Wed, 10 May 2006 10:33:00 -0400 Subject: ACPI: create acpi_device_suspend()/acpi_device_resume() updated and tested by Konstantin Karasyov http://bugzilla.kernel.org/show_bug.cgi?id=5000 Signed-off-by: Patrick Mochel Signed-off-by: Konstantin Karasyov Signed-off-by: Len Brown --- drivers/acpi/scan.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++++ include/acpi/acpi_bus.h | 3 +- 2 files changed, 120 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index a0ab828b2cc..19ae9ff1021 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1371,6 +1371,108 @@ static int acpi_bus_scan_fixed(struct acpi_device *root) return_VALUE(result); } + +static struct acpi_device * to_acpi_dev(struct device * dev) +{ + return container_of(dev, struct acpi_device, dev); +} + + +static int root_suspend(struct acpi_device * acpi_dev) +{ + struct acpi_device * dev, * next; + int result; + + spin_lock(&acpi_device_lock); + list_for_each_entry_safe_reverse(dev, next, &acpi_device_list, g_list) { + if (dev->driver && dev->driver->ops.suspend) { + spin_unlock(&acpi_device_lock); + + /* TBD: What suspend state should be passed + * to device? + */ + result = dev->driver->ops.suspend(dev, 0); + if (result) { + printk(KERN_ERR PREFIX "[%s - %s] Suspend failed: %d\n", + acpi_device_name(dev), + acpi_device_bid(dev), result); + } + spin_lock(&acpi_device_lock); + } + } + spin_unlock(&acpi_device_lock); + return 0; +} + + +static int acpi_device_suspend(struct device * dev, pm_message_t state) +{ + struct acpi_device * acpi_dev = to_acpi_dev(dev); + + /* + * For now, we should only register 1 generic device - + * the ACPI root device - and from there, we walk the + * tree of ACPI devices to suspend each one using the + * ACPI driver methods. + */ + if (acpi_dev->handle == ACPI_ROOT_OBJECT) + root_suspend(acpi_dev); + return 0; +} + + + +static int root_resume(struct acpi_device * acpi_dev) +{ + struct acpi_device * dev, * next; + int result; + + spin_lock(&acpi_device_lock); + list_for_each_entry_safe(dev, next, &acpi_device_list, g_list) { + if (dev->driver && dev->driver->ops.resume) { + spin_unlock(&acpi_device_lock); + + /* TBD: What suspend state should be passed + * to device? + */ + result = dev->driver->ops.resume(dev, 0); + if (result) { + printk(KERN_ERR PREFIX "[%s - %s] resume failed: %d\n", + acpi_device_name(dev), + acpi_device_bid(dev), result); + } + spin_lock(&acpi_device_lock); + } + } + spin_unlock(&acpi_device_lock); + return 0; +} + + +static int acpi_device_resume(struct device * dev) +{ + struct acpi_device * acpi_dev = to_acpi_dev(dev); + + /* + * For now, we should only register 1 generic device - + * the ACPI root device - and from there, we walk the + * tree of ACPI devices to resume each one using the + * ACPI driver methods. + */ + if (acpi_dev->handle == ACPI_ROOT_OBJECT) + root_resume(acpi_dev); + return 0; +} + + +struct bus_type acpi_bus_type = { + .name = "acpi", + .suspend = acpi_device_suspend, + .resume = acpi_device_resume, +}; + + + static int __init acpi_scan_init(void) { int result; @@ -1383,6 +1485,12 @@ static int __init acpi_scan_init(void) kset_register(&acpi_namespace_kset); + result = bus_register(&acpi_bus_type); + if (result) { + /* We don't want to quit even if we failed to add suspend/resume */ + printk(KERN_ERR PREFIX "Could not register bus type\n"); + } + /* * Create the root device in the bus's device tree */ @@ -1392,6 +1500,16 @@ static int __init acpi_scan_init(void) goto Done; result = acpi_start_single_object(acpi_root); + if (result) + goto Done; + + acpi_root->dev.bus = &acpi_bus_type; + snprintf(acpi_root->dev.bus_id, BUS_ID_SIZE, "%s", acpi_bus_type.name); + result = device_register(&acpi_root->dev); + if (result) { + /* We don't want to quit even if we failed to add suspend/resume */ + printk(KERN_ERR PREFIX "Could not register device\n"); + } /* * Enumerate devices in the ACPI namespace. diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 6dca3d54208..0de199aa6b9 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -26,7 +26,7 @@ #ifndef __ACPI_BUS_H__ #define __ACPI_BUS_H__ -#include +#include #include @@ -296,6 +296,7 @@ struct acpi_device { struct acpi_driver *driver; void *driver_data; struct kobject kobj; + struct device dev; }; #define acpi_driver_data(d) ((d)->driver_data) -- cgit v1.2.3 From 531881d665ca011326bb466b97b07c95dee8d0a1 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Mon, 15 May 2006 03:06:41 -0400 Subject: ACPI: pass pm_message_t from acpi_device_suspend() to root_suspend() in case we want to decode it for future use in acpi_op_suspend(..., state) also, inline new 1-liner static function http://bugzilla.kernel.org/show_bug.cgi?id=5000 Signed-off-by: Len Brown --- drivers/acpi/scan.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 19ae9ff1021..eee58393eb4 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1372,13 +1372,13 @@ static int acpi_bus_scan_fixed(struct acpi_device *root) } -static struct acpi_device * to_acpi_dev(struct device * dev) +static inline struct acpi_device * to_acpi_dev(struct device * dev) { return container_of(dev, struct acpi_device, dev); } -static int root_suspend(struct acpi_device * acpi_dev) +static int root_suspend(struct acpi_device * acpi_dev, pm_message_t state) { struct acpi_device * dev, * next; int result; @@ -1387,10 +1387,6 @@ static int root_suspend(struct acpi_device * acpi_dev) list_for_each_entry_safe_reverse(dev, next, &acpi_device_list, g_list) { if (dev->driver && dev->driver->ops.suspend) { spin_unlock(&acpi_device_lock); - - /* TBD: What suspend state should be passed - * to device? - */ result = dev->driver->ops.suspend(dev, 0); if (result) { printk(KERN_ERR PREFIX "[%s - %s] Suspend failed: %d\n", @@ -1416,7 +1412,7 @@ static int acpi_device_suspend(struct device * dev, pm_message_t state) * ACPI driver methods. */ if (acpi_dev->handle == ACPI_ROOT_OBJECT) - root_suspend(acpi_dev); + root_suspend(acpi_dev, state); return 0; } @@ -1431,10 +1427,6 @@ static int root_resume(struct acpi_device * acpi_dev) list_for_each_entry_safe(dev, next, &acpi_device_list, g_list) { if (dev->driver && dev->driver->ops.resume) { spin_unlock(&acpi_device_lock); - - /* TBD: What suspend state should be passed - * to device? - */ result = dev->driver->ops.resume(dev, 0); if (result) { printk(KERN_ERR PREFIX "[%s - %s] resume failed: %d\n", -- cgit v1.2.3 From 0feabb01d93e5801d1127416a66cfc3963280bca Mon Sep 17 00:00:00 2001 From: Konstantin Karasyov Date: Mon, 8 May 2006 00:00:00 -0400 Subject: ACPI: create acpi_fan_suspend()/acpi_fan_resume() http://bugzilla.kernel.org/show_bug.cgi?id=5000 Signed-off-by: Len Brown --- drivers/acpi/bus.c | 14 ++++++++------ drivers/acpi/fan.c | 40 ++++++++++++++++++++++++++++++++++++++++ include/acpi/acpi_bus.h | 3 ++- 3 files changed, 50 insertions(+), 7 deletions(-) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 606f8733a77..eff696f2b6b 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -205,12 +205,14 @@ int acpi_bus_set_power(acpi_handle handle, int state) * Get device's current power state if it's unknown * This means device power state isn't initialized or previous setting failed */ - if (device->power.state == ACPI_STATE_UNKNOWN) - acpi_bus_get_power(device->handle, &device->power.state); - if (state == device->power.state) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n", - state)); - return_VALUE(0); + if (!device->flags.force_power_state) { + if (device->power.state == ACPI_STATE_UNKNOWN) + acpi_bus_get_power(device->handle, &device->power.state); + if (state == device->power.state) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n", + state)); + return_VALUE(0); + } } if (!device->power.states[state].flags.valid) { ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Device does not support D%d\n", diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index e8165c4f162..1cd25784b7a 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -48,6 +48,8 @@ MODULE_LICENSE("GPL"); static int acpi_fan_add(struct acpi_device *device); static int acpi_fan_remove(struct acpi_device *device, int type); +static int acpi_fan_suspend(struct acpi_device *device, int state); +static int acpi_fan_resume(struct acpi_device *device, int state); static struct acpi_driver acpi_fan_driver = { .name = ACPI_FAN_DRIVER_NAME, @@ -56,6 +58,8 @@ static struct acpi_driver acpi_fan_driver = { .ops = { .add = acpi_fan_add, .remove = acpi_fan_remove, + .suspend = acpi_fan_suspend, + .resume = acpi_fan_resume, }, }; @@ -206,6 +210,10 @@ static int acpi_fan_add(struct acpi_device *device) goto end; } + device->flags.force_power_state = 1; + acpi_bus_set_power(device->handle, state); + device->flags.force_power_state = 0; + result = acpi_fan_add_fs(device); if (result) goto end; @@ -239,6 +247,38 @@ static int acpi_fan_remove(struct acpi_device *device, int type) return_VALUE(0); } +static int acpi_fan_suspend(struct acpi_device *device, int state) +{ + if (!device) + return -EINVAL; + + acpi_bus_set_power(device->handle, ACPI_STATE_D0); + + return AE_OK; +} + +static int acpi_fan_resume(struct acpi_device *device, int state) +{ + int result = 0; + int power_state = 0; + + if (!device) + return -EINVAL; + + result = acpi_bus_get_power(device->handle, &power_state); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error reading fan power state\n")); + return result; + } + + device->flags.force_power_state = 1; + acpi_bus_set_power(device->handle, power_state); + device->flags.force_power_state = 0; + + return result; +} + static int __init acpi_fan_init(void) { int result = 0; diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 0de199aa6b9..7f8ed9dbc7b 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -169,7 +169,8 @@ struct acpi_device_flags { u32 power_manageable:1; u32 performance_manageable:1; u32 wake_capable:1; /* Wakeup(_PRW) supported? */ - u32 reserved:20; + u32 force_power_state:1; + u32 reserved:19; }; /* File System */ -- cgit v1.2.3 From 74ce1468128e299fe6a85e7e78e528e45e72d6d9 Mon Sep 17 00:00:00 2001 From: Konstantin Karasyov Date: Mon, 8 May 2006 08:32:00 -0400 Subject: ACPI: create acpi_thermal_resume() http://bugzilla.kernel.org/show_bug.cgi?id=4364 Signed-off-by: Konstantin Karasyov Signed-off-by: Len Brown --- drivers/acpi/thermal.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 19f3ea48475..928dcf9e77c 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -82,6 +82,7 @@ MODULE_PARM_DESC(tzp, "Thermal zone polling frequency, in 1/10 seconds.\n"); static int acpi_thermal_add(struct acpi_device *device); static int acpi_thermal_remove(struct acpi_device *device, int type); +static int acpi_thermal_resume(struct acpi_device *device, int state); static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file); static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file); static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file); @@ -103,6 +104,7 @@ static struct acpi_driver acpi_thermal_driver = { .ops = { .add = acpi_thermal_add, .remove = acpi_thermal_remove, + .resume = acpi_thermal_resume, }, }; @@ -1416,6 +1418,20 @@ static int acpi_thermal_remove(struct acpi_device *device, int type) return_VALUE(0); } +static int acpi_thermal_resume(struct acpi_device *device, int state) +{ + struct acpi_thermal *tz = NULL; + + if (!device || !acpi_driver_data(device)) + return_VALUE(-EINVAL); + + tz = (struct acpi_thermal *)acpi_driver_data(device); + + acpi_thermal_check(tz); + + return AE_OK; +} + static int __init acpi_thermal_init(void) { int result = 0; -- cgit v1.2.3 From 89f48c4d67dd875cf2216d4402bf77eda41fbdd9 Mon Sep 17 00:00:00 2001 From: Luben Tuikov Date: Mon, 15 May 2006 20:57:18 +0900 Subject: [PATCH] SCSI: Introduce scsi_req_abort_cmd (REPOST) Introduce scsi_req_abort_cmd(struct scsi_cmnd *). This function requests that SCSI Core start recovery for the command by deleting the timer and adding the command to the eh queue. It can be called by either LLDDs or SCSI Core. LLDDs who implement their own error recovery MAY ignore the timeout event if they generated scsi_req_abort_cmd. First post: http://marc.theaimsgroup.com/?l=linux-scsi&m=113833937421677&w=2 Signed-off-by: Luben Tuikov Signed-off-by: Tejun Heo --- drivers/scsi/scsi.c | 18 ++++++++++++++++++ include/scsi/scsi_cmnd.h | 1 + 2 files changed, 19 insertions(+) diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 73994e2ac2c..dae4f08adde 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -719,6 +719,24 @@ void scsi_init_cmd_from_req(struct scsi_cmnd *cmd, struct scsi_request *sreq) */ static DEFINE_PER_CPU(struct list_head, scsi_done_q); +/** + * scsi_req_abort_cmd -- Request command recovery for the specified command + * cmd: pointer to the SCSI command of interest + * + * This function requests that SCSI Core start recovery for the + * command by deleting the timer and adding the command to the eh + * queue. It can be called by either LLDDs or SCSI Core. LLDDs who + * implement their own error recovery MAY ignore the timeout event if + * they generated scsi_req_abort_cmd. + */ +void scsi_req_abort_cmd(struct scsi_cmnd *cmd) +{ + if (!scsi_delete_timer(cmd)) + return; + scsi_times_out(cmd); +} +EXPORT_SYMBOL(scsi_req_abort_cmd); + /** * scsi_done - Enqueue the finished SCSI command into the done queue. * @cmd: The SCSI Command for which a low-level device driver (LLDD) gives diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index 1ace1b9fe53..88c6c4da6c0 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -151,5 +151,6 @@ extern struct scsi_cmnd *scsi_get_command(struct scsi_device *, gfp_t); extern void scsi_put_command(struct scsi_cmnd *); extern void scsi_io_completion(struct scsi_cmnd *, unsigned int, unsigned int); extern void scsi_finish_command(struct scsi_cmnd *cmd); +extern void scsi_req_abort_cmd(struct scsi_cmnd *cmd); #endif /* _SCSI_SCSI_CMND_H */ -- cgit v1.2.3 From ee7863bc68fa6ad6fe7cfcc0e5ebe9efe0c0664e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:57:20 +0900 Subject: [PATCH] SCSI: implement shost->host_eh_scheduled libata needs to invoke EH without scmd. This patch adds shost->host_eh_scheduled to implement such behavior. Currently the only user of this feature is libata and no general interface is defined. This patch simply adds handling for host_eh_scheduled where needed and exports scsi_eh_wakeup() to modules. The rest is upto libata. This is the result of the following discussion. http://thread.gmane.org/gmane.linux.scsi/23853/focus=9760 In short, SCSI host is not supposed to know about exceptions unrelated to specific device or command. Such exceptions should be handled by transport layer proper. However, the distinction is not essential to ATA and libata is planning to depart from SCSI, so, for the time being, libata will be using SCSI EH to handle such exceptions. Signed-off-by: Tejun Heo --- drivers/scsi/scsi_error.c | 3 ++- drivers/scsi/scsi_lib.c | 2 +- drivers/scsi/scsi_priv.h | 1 - include/scsi/scsi_eh.h | 1 + include/scsi/scsi_host.h | 1 + 5 files changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 1c75646f968..9ca71cbefce 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -56,6 +56,7 @@ void scsi_eh_wakeup(struct Scsi_Host *shost) printk("Waking error handler thread\n")); } } +EXPORT_SYMBOL_GPL(scsi_eh_wakeup); /** * scsi_eh_scmd_add - add scsi cmd to error handling. @@ -1517,7 +1518,7 @@ int scsi_error_handler(void *data) */ set_current_state(TASK_INTERRUPTIBLE); while (!kthread_should_stop()) { - if (shost->host_failed == 0 || + if ((shost->host_failed == 0 && shost->host_eh_scheduled == 0) || shost->host_failed != shost->host_busy) { SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler scsi_eh_%d sleeping\n", diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 7b0f9a3810d..c55d195b6f4 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -566,7 +566,7 @@ void scsi_device_unbusy(struct scsi_device *sdev) spin_lock_irqsave(shost->host_lock, flags); shost->host_busy--; if (unlikely(scsi_host_in_recovery(shost) && - shost->host_failed)) + (shost->host_failed || shost->host_eh_scheduled))) scsi_eh_wakeup(shost); spin_unlock(shost->host_lock); spin_lock(sdev->request_queue->queue_lock); diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index 27c48274e8c..0b39081113b 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -63,7 +63,6 @@ extern int scsi_delete_timer(struct scsi_cmnd *); extern void scsi_times_out(struct scsi_cmnd *cmd); extern int scsi_error_handler(void *host); extern int scsi_decide_disposition(struct scsi_cmnd *cmd); -extern void scsi_eh_wakeup(struct Scsi_Host *shost); extern int scsi_eh_scmd_add(struct scsi_cmnd *, int); /* scsi_lib.c */ diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h index d160880b2a8..212c983a6a1 100644 --- a/include/scsi/scsi_eh.h +++ b/include/scsi/scsi_eh.h @@ -35,6 +35,7 @@ static inline int scsi_sense_valid(struct scsi_sense_hdr *sshdr) } +extern void scsi_eh_wakeup(struct Scsi_Host *shost); extern void scsi_eh_finish_cmd(struct scsi_cmnd *scmd, struct list_head *done_q); extern void scsi_eh_flush_done_q(struct list_head *done_q); diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index de6ce541a04..a42efd6e4be 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -472,6 +472,7 @@ struct Scsi_Host { */ unsigned int host_busy; /* commands actually active on low-level */ unsigned int host_failed; /* commands that failed. */ + unsigned int host_eh_scheduled; /* EH scheduled without command */ unsigned short host_no; /* Used for IOCTL_GET_IDLUN, /proc/scsi et al. */ int resetting; /* if set, it means that last_reset is a valid value */ -- cgit v1.2.3 From c44078c03f018c8cc9d7463b0db4c6c7fb316792 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:57:21 +0900 Subject: [PATCH] libata: silly fix in ata_scsi_start_stop_xlat() Don't directly access &qc->tf when tf == &qc->tf. Signed-off-by: Tejun Heo --- drivers/scsi/libata-scsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 9871f8272df..b0c83c28d57 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -748,7 +748,7 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc, tf->nsect = 1; /* 1 sector, lba=0 */ if (qc->dev->flags & ATA_DFLAG_LBA) { - qc->tf.flags |= ATA_TFLAG_LBA; + tf->flags |= ATA_TFLAG_LBA; tf->lbah = 0x0; tf->lbam = 0x0; -- cgit v1.2.3 From 3c567b7d1137633f3ff67cd1df94abc5fd497a85 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:57:23 +0900 Subject: [PATCH] libata: rename ata_down_sata_spd_limit() and friends Rename ata_down_sata_spd_limit() and friends to sata_down_spd_limit() and likewise for simplicity & consistency. Signed-off-by: Tejun Heo --- drivers/scsi/libata-core.c | 32 ++++++++++++++++---------------- drivers/scsi/libata.h | 4 ++-- drivers/scsi/sata_sil24.c | 2 +- include/linux/libata.h | 2 +- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 509178c3700..196c09ff5e7 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1465,7 +1465,7 @@ static int ata_bus_probe(struct ata_port *ap) tries[dev->devno] = 0; break; case -EIO: - ata_down_sata_spd_limit(ap); + sata_down_spd_limit(ap); /* fall through */ default: tries[dev->devno]--; @@ -1640,12 +1640,12 @@ void ata_port_disable(struct ata_port *ap) } /** - * ata_down_sata_spd_limit - adjust SATA spd limit downward + * sata_down_spd_limit - adjust SATA spd limit downward * @ap: Port to adjust SATA spd limit for * * Adjust SATA spd limit of @ap downward. Note that this * function only adjusts the limit. The change must be applied - * using ata_set_sata_spd(). + * using sata_set_spd(). * * LOCKING: * Inherited from caller. @@ -1653,7 +1653,7 @@ void ata_port_disable(struct ata_port *ap) * RETURNS: * 0 on success, negative errno on failure */ -int ata_down_sata_spd_limit(struct ata_port *ap) +int sata_down_spd_limit(struct ata_port *ap) { u32 spd, mask; int highbit; @@ -1683,7 +1683,7 @@ int ata_down_sata_spd_limit(struct ata_port *ap) return 0; } -static int __ata_set_sata_spd_needed(struct ata_port *ap, u32 *scontrol) +static int __sata_set_spd_needed(struct ata_port *ap, u32 *scontrol) { u32 spd, limit; @@ -1699,7 +1699,7 @@ static int __ata_set_sata_spd_needed(struct ata_port *ap, u32 *scontrol) } /** - * ata_set_sata_spd_needed - is SATA spd configuration needed + * sata_set_spd_needed - is SATA spd configuration needed * @ap: Port in question * * Test whether the spd limit in SControl matches @@ -1713,7 +1713,7 @@ static int __ata_set_sata_spd_needed(struct ata_port *ap, u32 *scontrol) * RETURNS: * 1 if SATA spd configuration is needed, 0 otherwise. */ -int ata_set_sata_spd_needed(struct ata_port *ap) +int sata_set_spd_needed(struct ata_port *ap) { u32 scontrol; @@ -1722,11 +1722,11 @@ int ata_set_sata_spd_needed(struct ata_port *ap) scontrol = scr_read(ap, SCR_CONTROL); - return __ata_set_sata_spd_needed(ap, &scontrol); + return __sata_set_spd_needed(ap, &scontrol); } /** - * ata_set_sata_spd - set SATA spd according to spd limit + * sata_set_spd - set SATA spd according to spd limit * @ap: Port to set SATA spd for * * Set SATA spd of @ap according to sata_spd_limit. @@ -1738,7 +1738,7 @@ int ata_set_sata_spd_needed(struct ata_port *ap) * 0 if spd doesn't need to be changed, 1 if spd has been * changed. -EOPNOTSUPP if SCR registers are inaccessible. */ -int ata_set_sata_spd(struct ata_port *ap) +int sata_set_spd(struct ata_port *ap) { u32 scontrol; @@ -1746,7 +1746,7 @@ int ata_set_sata_spd(struct ata_port *ap) return -EOPNOTSUPP; scontrol = scr_read(ap, SCR_CONTROL); - if (!__ata_set_sata_spd_needed(ap, &scontrol)) + if (!__sata_set_spd_needed(ap, &scontrol)) return 0; scr_write(ap, SCR_CONTROL, scontrol); @@ -2464,7 +2464,7 @@ int sata_std_hardreset(struct ata_port *ap, unsigned int *class) DPRINTK("ENTER\n"); - if (ata_set_sata_spd_needed(ap)) { + if (sata_set_spd_needed(ap)) { /* SATA spec says nothing about how to reconfigure * spd. To be on the safe side, turn off phy during * reconfiguration. This works for at least ICH7 AHCI @@ -2474,7 +2474,7 @@ int sata_std_hardreset(struct ata_port *ap, unsigned int *class) scontrol = (scontrol & 0x0f0) | 0x302; scr_write_flush(ap, SCR_CONTROL, scontrol); - ata_set_sata_spd(ap); + sata_set_spd(ap); } /* issue phy wake/reset */ @@ -2657,7 +2657,7 @@ int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, if (probeinit) probeinit(ap); - if (softreset && !ata_set_sata_spd_needed(ap)) { + if (softreset && !sata_set_spd_needed(ap)) { rc = ata_do_reset(ap, softreset, postreset, classes); if (rc == 0 && classes[0] != ATA_DEV_UNKNOWN) goto done; @@ -2677,7 +2677,7 @@ int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, break; } - if (ata_down_sata_spd_limit(ap)) + if (sata_down_spd_limit(ap)) goto done; printk(KERN_INFO "ata%u: hardreset failed, will retry " @@ -5113,7 +5113,7 @@ EXPORT_SYMBOL_GPL(ata_bmdma_irq_clear); EXPORT_SYMBOL_GPL(ata_bmdma_status); EXPORT_SYMBOL_GPL(ata_bmdma_stop); EXPORT_SYMBOL_GPL(ata_port_probe); -EXPORT_SYMBOL_GPL(ata_set_sata_spd); +EXPORT_SYMBOL_GPL(sata_set_spd); EXPORT_SYMBOL_GPL(sata_phy_reset); EXPORT_SYMBOL_GPL(__sata_phy_reset); EXPORT_SYMBOL_GPL(ata_bus_reset); diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index 3f8b0a86378..26975df9a3f 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -51,8 +51,8 @@ extern void ata_port_flush_task(struct ata_port *ap); extern unsigned ata_exec_internal(struct ata_port *ap, struct ata_device *dev, struct ata_taskfile *tf, const u8 *cdb, int dma_dir, void *buf, unsigned int buflen); -extern int ata_down_sata_spd_limit(struct ata_port *ap); -extern int ata_set_sata_spd_needed(struct ata_port *ap); +extern int sata_down_spd_limit(struct ata_port *ap); +extern int sata_set_spd_needed(struct ata_port *ap); extern int ata_down_xfermask_limit(struct ata_port *ap, struct ata_device *dev, int force_pio0); extern int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev); diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index e9fd869140c..8c167250f4c 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -528,7 +528,7 @@ static int sil24_hardreset(struct ata_port *ap, unsigned int *class) u32 tmp; /* sil24 does the right thing(tm) without any protection */ - ata_set_sata_spd(ap); + sata_set_spd(ap); tout_msec = 100; if (sata_dev_present(ap)) diff --git a/include/linux/libata.h b/include/linux/libata.h index d35b1e3bb7e..0b67aafd387 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -504,7 +504,7 @@ extern void ata_port_probe(struct ata_port *); extern void __sata_phy_reset(struct ata_port *ap); extern void sata_phy_reset(struct ata_port *ap); extern void ata_bus_reset(struct ata_port *ap); -extern int ata_set_sata_spd(struct ata_port *ap); +extern int sata_set_spd(struct ata_port *ap); extern int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, ata_reset_fn_t softreset, ata_reset_fn_t hardreset, -- cgit v1.2.3 From e4fac92ae744cd5d5c3c1774825788e6b91a5965 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:57:25 +0900 Subject: [PATCH] ahci: hardreset classification fix AHCI calls ata_dev_classify() even when no device is attached which results in false class code. Fix it. Signed-off-by: Tejun Heo --- drivers/scsi/ahci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index d23f00230a7..c33255404ee 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -670,7 +670,7 @@ static int ahci_hardreset(struct ata_port *ap, unsigned int *class) rc = sata_std_hardreset(ap, class); ahci_start_engine(ap); - if (rc == 0) + if (rc == 0 && sata_dev_present(ap)) *class = ahci_dev_classify(ap); if (*class == ATA_DEV_UNKNOWN) *class = ATA_DEV_NONE; -- cgit v1.2.3 From e23befe9018319dc218e2e51c20ce480e6b45eeb Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:57:27 +0900 Subject: [PATCH] libata: unexport ata_scsi_error() While moving ata_scsi_error() from LLDD sht to libata transportt, EXPORT_SYMBOL_GPL() entry was left out. Kill it. Signed-off-by: Tejun Heo --- drivers/scsi/libata-core.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 196c09ff5e7..85a00429007 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -5161,7 +5161,6 @@ EXPORT_SYMBOL_GPL(ata_device_resume); EXPORT_SYMBOL_GPL(ata_scsi_device_suspend); EXPORT_SYMBOL_GPL(ata_scsi_device_resume); -EXPORT_SYMBOL_GPL(ata_scsi_error); EXPORT_SYMBOL_GPL(ata_eng_timeout); EXPORT_SYMBOL_GPL(ata_eh_qc_complete); EXPORT_SYMBOL_GPL(ata_eh_qc_retry); -- cgit v1.2.3 From 6cd727b14f1a6cdcb088d1067c1ba0ba124806a7 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:57:28 +0900 Subject: [PATCH] libata: kill duplicate prototypes Kill duplicate prototypes for ata_eh_qc_complete/retry() in libata.h. Signed-off-by: Tejun Heo --- include/linux/libata.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/linux/libata.h b/include/linux/libata.h index 0b67aafd387..220b9d7bfc2 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -530,8 +530,6 @@ extern void ata_host_set_remove(struct ata_host_set *host_set); extern int ata_scsi_detect(struct scsi_host_template *sht); extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg); extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)); -extern void ata_eh_qc_complete(struct ata_queued_cmd *qc); -extern void ata_eh_qc_retry(struct ata_queued_cmd *qc); extern int ata_scsi_release(struct Scsi_Host *host); extern unsigned int ata_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc); extern int ata_scsi_device_resume(struct scsi_device *); -- cgit v1.2.3 From f8c2c4202d86e14ca03b7adc7ebcb30fc74b24e1 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:57:30 +0900 Subject: [PATCH] libata: fix ->phy_reset class code handling in ata_bus_probe() ata_bus_probe() doesn't clear dev->class after ->phy_reset(). This can result in falsely enabled devices if probing fails. Clear dev->class to ATA_DEV_UNKNOWN after fetching it. Signed-off-by: Tejun Heo --- drivers/scsi/libata-core.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 85a00429007..1669dae53ce 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1397,9 +1397,11 @@ static int ata_bus_probe(struct ata_port *ap) } else { ap->ops->phy_reset(ap); - if (!(ap->flags & ATA_FLAG_DISABLED)) - for (i = 0; i < ATA_MAX_DEVICES; i++) + for (i = 0; i < ATA_MAX_DEVICES; i++) { + if (!(ap->flags & ATA_FLAG_DISABLED)) classes[i] = ap->device[i].class; + ap->device[i].class = ATA_DEV_UNKNOWN; + } ata_port_probe(ap); } -- cgit v1.2.3 From 7401abf2f44695ef44eef47d5deba1c20214a063 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:57:32 +0900 Subject: [PATCH] libata: clear ap->active_tag atomically w.r.t. command completion ap->active_tag was cleared in ata_qc_free(). This left ap->active_tag dangling after ata_qc_complete(). Spurious interrupts inbetween could incorrectly access the qc. Clear active_tag in ata_qc_complete(). This change is necessary for later EH changes. Signed-off-by: Tejun Heo --- drivers/scsi/libata-core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 1669dae53ce..86cd0e0895d 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -4083,8 +4083,6 @@ void ata_qc_free(struct ata_queued_cmd *qc) qc->flags = 0; tag = qc->tag; if (likely(ata_tag_valid(tag))) { - if (tag == ap->active_tag) - ap->active_tag = ATA_TAG_POISON; qc->tag = ATA_TAG_POISON; clear_bit(tag, &ap->qactive); } @@ -4098,6 +4096,9 @@ void __ata_qc_complete(struct ata_queued_cmd *qc) if (likely(qc->flags & ATA_QCFLAG_DMAMAP)) ata_sg_clean(qc); + /* command should be marked inactive atomically with qc completion */ + qc->ap->active_tag = ATA_TAG_POISON; + /* atapi: mark qc as inactive to prevent the interrupt handler * from completing the command twice later, before the error handler * is called. (when rc != 0 and atapi request sense is needed) -- cgit v1.2.3 From 158693031d7c58a355ec1852052a4fca75fd3bda Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:57:33 +0900 Subject: [PATCH] libata: hold host_set lock while finishing internal qc Hold host_set lock while finishing internal qc. Signed-off-by: Tejun Heo --- drivers/scsi/libata-core.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 86cd0e0895d..13bce43f191 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1031,6 +1031,9 @@ unsigned ata_exec_internal(struct ata_port *ap, struct ata_device *dev, spin_unlock_irqrestore(&ap->host_set->lock, flags); } + /* finish up */ + spin_lock_irqsave(&ap->host_set->lock, flags); + *tf = qc->tf; err_mask = qc->err_mask; @@ -1052,6 +1055,8 @@ unsigned ata_exec_internal(struct ata_port *ap, struct ata_device *dev, ata_port_probe(ap); } + spin_unlock_irqrestore(&ap->host_set->lock, flags); + return err_mask; } -- cgit v1.2.3 From fe635c7e91036282e4fd0cc5b4eebc712e43270d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:57:35 +0900 Subject: [PATCH] libata: use preallocated buffers It's not a very good idea to allocate memory during EH. Use statically allocated buffer for dev->id[] and add 512byte buffer ap->sector_buf. This buffer is owned by EH (or probing) and to be used as temporary buffer for various purposes (IDENTIFY, NCQ log page 10h, PM GSCR block). Signed-off-by: Tejun Heo --- drivers/scsi/libata-core.c | 32 ++++++++------------------------ include/linux/libata.h | 4 +++- 2 files changed, 11 insertions(+), 25 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 13bce43f191..af55861a96e 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1099,7 +1099,7 @@ unsigned int ata_pio_need_iordy(const struct ata_device *adev) * @dev: target device * @p_class: pointer to class of the target device (may be changed) * @post_reset: is this read ID post-reset? - * @p_id: read IDENTIFY page (newly allocated) + * @id: buffer to read IDENTIFY data into * * Read ID data from the specified device. ATA_CMD_ID_ATA is * performed on ATA devices and ATA_CMD_ID_ATAPI on ATAPI @@ -1113,12 +1113,11 @@ unsigned int ata_pio_need_iordy(const struct ata_device *adev) * 0 on success, -errno otherwise. */ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, - unsigned int *p_class, int post_reset, u16 **p_id) + unsigned int *p_class, int post_reset, u16 *id) { unsigned int class = *p_class; struct ata_taskfile tf; unsigned int err_mask = 0; - u16 *id; const char *reason; int rc; @@ -1126,13 +1125,6 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */ - id = kmalloc(sizeof(id[0]) * ATA_ID_WORDS, GFP_KERNEL); - if (id == NULL) { - rc = -ENOMEM; - reason = "out of memory"; - goto err_out; - } - retry: ata_tf_init(ap, &tf, dev->devno); @@ -1194,13 +1186,12 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, } *p_class = class; - *p_id = id; + return 0; err_out: printk(KERN_WARNING "ata%u: dev %u failed to IDENTIFY (%s)\n", ap->id, dev->devno, reason); - kfree(id); return rc; } @@ -1425,9 +1416,7 @@ static int ata_bus_probe(struct ata_port *ap) if (!ata_dev_enabled(dev)) continue; - kfree(dev->id); - dev->id = NULL; - rc = ata_dev_read_id(ap, dev, &dev->class, 1, &dev->id); + rc = ata_dev_read_id(ap, dev, &dev->class, 1, dev->id); if (rc) goto fail; @@ -2788,7 +2777,7 @@ int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev, int post_reset) { unsigned int class = dev->class; - u16 *id = NULL; + u16 *id = (void *)ap->sector_buf; int rc; if (!ata_dev_enabled(dev)) { @@ -2796,8 +2785,8 @@ int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev, goto fail; } - /* allocate & read ID data */ - rc = ata_dev_read_id(ap, dev, &class, post_reset, &id); + /* read ID data */ + rc = ata_dev_read_id(ap, dev, &class, post_reset, id); if (rc) goto fail; @@ -2807,8 +2796,7 @@ int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev, goto fail; } - kfree(dev->id); - dev->id = id; + memcpy(dev->id, id, sizeof(id[0]) * ATA_ID_WORDS); /* configure device according to the new ID */ rc = ata_dev_configure(ap, dev, 0); @@ -2818,7 +2806,6 @@ int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev, fail: printk(KERN_ERR "ata%u: dev %u revalidation failed (errno=%d)\n", ap->id, dev->devno, rc); - kfree(id); return rc; } @@ -4873,14 +4860,11 @@ void ata_host_set_remove(struct ata_host_set *host_set) int ata_scsi_release(struct Scsi_Host *host) { struct ata_port *ap = ata_shost_to_port(host); - int i; DPRINTK("ENTER\n"); ap->ops->port_disable(ap); ata_host_remove(ap, 0); - for (i = 0; i < ATA_MAX_DEVICES; i++) - kfree(ap->device[i].id); DPRINTK("EXIT\n"); return 1; diff --git a/include/linux/libata.h b/include/linux/libata.h index 220b9d7bfc2..0e1a3be3947 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -360,7 +360,7 @@ struct ata_device { unsigned long flags; /* ATA_DFLAG_xxx */ unsigned int class; /* ATA_DEV_xxx */ unsigned int devno; /* 0 or 1 */ - u16 *id; /* IDENTIFY xxx DEVICE data */ + u16 id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */ u8 pio_mode; u8 dma_mode; u8 xfer_mode; @@ -425,6 +425,8 @@ struct ata_port { struct list_head eh_done_q; void *private_data; + + u8 sector_buf[ATA_SECT_SIZE]; /* owned by EH */ }; struct ata_port_operations { -- cgit v1.2.3 From 3adcebb2b59d590d572844815c906ca30477b14a Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:57:37 +0900 Subject: [PATCH] libata: move ->set_mode() handling into ata_set_mode() Move ->set_mode() handlng into ata_set_mode(). Signed-off-by: Tejun Heo --- drivers/scsi/libata-core.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index af55861a96e..1efe8a1ba81 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1426,20 +1426,7 @@ static int ata_bus_probe(struct ata_port *ap) } /* configure transfer mode */ - if (ap->ops->set_mode) { - /* FIXME: make ->set_mode handle no device case and - * return error code and failing device on failure as - * ata_set_mode() does. - */ - for (i = 0; i < ATA_MAX_DEVICES; i++) - if (ata_dev_enabled(&ap->device[i])) { - ap->ops->set_mode(ap); - break; - } - rc = 0; - } else - rc = ata_set_mode(ap, &dev); - + rc = ata_set_mode(ap, &dev); if (rc) { down_xfermask = 1; goto fail; @@ -1997,6 +1984,20 @@ int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev) struct ata_device *dev; int i, rc = 0, used_dma = 0, found = 0; + /* has private set_mode? */ + if (ap->ops->set_mode) { + /* FIXME: make ->set_mode handle no device case and + * return error code and failing device on failure. + */ + for (i = 0; i < ATA_MAX_DEVICES; i++) { + if (ata_dev_enabled(&ap->device[i])) { + ap->ops->set_mode(ap); + break; + } + } + return 0; + } + /* step 1: calculate xfer_mask */ for (i = 0; i < ATA_MAX_DEVICES; i++) { unsigned int pio_mask, dma_mask; -- cgit v1.2.3 From 96bd39ec295e49443c8b0c25a6b69fdace18780f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:57:38 +0900 Subject: [PATCH] libata: remove postreset handling from ata_do_reset() Make ata_do_reset() deal only with reset. postreset is now the responsibility of the caller. This is simpler and eases later prereset addition. Signed-off-by: Tejun Heo --- drivers/scsi/libata-core.c | 19 ++++++++++--------- drivers/scsi/libata.h | 2 +- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 1efe8a1ba81..19ae3fa1cfc 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2585,7 +2585,7 @@ int ata_std_probe_reset(struct ata_port *ap, unsigned int *classes) } int ata_do_reset(struct ata_port *ap, ata_reset_fn_t reset, - ata_postreset_fn_t postreset, unsigned int *classes) + unsigned int *classes) { int i, rc; @@ -2609,9 +2609,6 @@ int ata_do_reset(struct ata_port *ap, ata_reset_fn_t reset, if (classes[i] == ATA_DEV_UNKNOWN) classes[i] = ATA_DEV_NONE; - if (postreset) - postreset(ap, classes); - return 0; } @@ -2655,7 +2652,7 @@ int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, probeinit(ap); if (softreset && !sata_set_spd_needed(ap)) { - rc = ata_do_reset(ap, softreset, postreset, classes); + rc = ata_do_reset(ap, softreset, classes); if (rc == 0 && classes[0] != ATA_DEV_UNKNOWN) goto done; printk(KERN_INFO "ata%u: softreset failed, will try " @@ -2667,7 +2664,7 @@ int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, goto done; while (1) { - rc = ata_do_reset(ap, hardreset, postreset, classes); + rc = ata_do_reset(ap, hardreset, classes); if (rc == 0) { if (classes[0] != ATA_DEV_UNKNOWN) goto done; @@ -2688,12 +2685,16 @@ int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, ap->id); ssleep(5); - rc = ata_do_reset(ap, softreset, postreset, classes); + rc = ata_do_reset(ap, softreset, classes); } done: - if (rc == 0 && classes[0] == ATA_DEV_UNKNOWN) - rc = -ENODEV; + if (rc == 0) { + if (postreset) + postreset(ap, classes); + if (classes[0] == ATA_DEV_UNKNOWN) + rc = -ENODEV; + } return rc; } diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index 26975df9a3f..6442c2f1a80 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -57,7 +57,7 @@ extern int ata_down_xfermask_limit(struct ata_port *ap, struct ata_device *dev, int force_pio0); extern int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev); extern int ata_do_reset(struct ata_port *ap, ata_reset_fn_t reset, - ata_postreset_fn_t postreset, unsigned int *classes); + unsigned int *classes); extern void ata_qc_free(struct ata_queued_cmd *qc); extern void ata_qc_issue(struct ata_queued_cmd *qc); extern int ata_check_atapi_dma(struct ata_queued_cmd *qc); -- cgit v1.2.3 From e61e067227bc76b4d9411a50d735c9d87f27b0e2 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:57:40 +0900 Subject: [PATCH] libata: implement qc->result_tf Add qc->result_tf and ATA_QCFLAG_RESULT_TF. This moves the responsibility of loading result TF from post-compltion path to qc execution path. qc->result_tf is loaded if explicitly requested or the qc failsa. This allows more efficient completion implementation and correct handling of result TF for controllers which don't have global TF representation such as sil3124/32. Signed-off-by: Tejun Heo --- drivers/scsi/libata-core.c | 4 ++-- drivers/scsi/libata-scsi.c | 18 +++++++----------- include/linux/libata.h | 16 ++++++++++++++-- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 19ae3fa1cfc..51cb9ca5519 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -955,7 +955,6 @@ void ata_qc_complete_internal(struct ata_queued_cmd *qc) { struct completion *waiting = qc->private_data; - qc->ap->ops->tf_read(qc->ap, &qc->tf); complete(waiting); } @@ -997,6 +996,7 @@ unsigned ata_exec_internal(struct ata_port *ap, struct ata_device *dev, qc->tf = *tf; if (cdb) memcpy(qc->cdb, cdb, ATAPI_CDB_LEN); + qc->flags |= ATA_QCFLAG_RESULT_TF; qc->dma_dir = dma_dir; if (dma_dir != DMA_NONE) { ata_sg_init_one(qc, buf, buflen); @@ -1034,7 +1034,7 @@ unsigned ata_exec_internal(struct ata_port *ap, struct ata_device *dev, /* finish up */ spin_lock_irqsave(&ap->host_set->lock, flags); - *tf = qc->tf; + *tf = qc->result_tf; err_mask = qc->err_mask; ata_qc_free(qc); diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index b0c83c28d57..ce90b6352a8 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -537,7 +537,7 @@ void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc, void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc) { struct scsi_cmnd *cmd = qc->scsicmd; - struct ata_taskfile *tf = &qc->tf; + struct ata_taskfile *tf = &qc->result_tf; unsigned char *sb = cmd->sense_buffer; unsigned char *desc = sb + 8; @@ -608,7 +608,7 @@ void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc) void ata_gen_fixed_sense(struct ata_queued_cmd *qc) { struct scsi_cmnd *cmd = qc->scsicmd; - struct ata_taskfile *tf = &qc->tf; + struct ata_taskfile *tf = &qc->result_tf; unsigned char *sb = cmd->sense_buffer; memset(sb, 0, SCSI_SENSE_BUFFERSIZE); @@ -1199,14 +1199,11 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) */ if (((cdb[0] == ATA_16) || (cdb[0] == ATA_12)) && ((cdb[2] & 0x20) || need_sense)) { - qc->ap->ops->tf_read(qc->ap, &qc->tf); ata_gen_ata_desc_sense(qc); } else { if (!need_sense) { cmd->result = SAM_STAT_GOOD; } else { - qc->ap->ops->tf_read(qc->ap, &qc->tf); - /* TODO: decide which descriptor format to use * for 48b LBA devices and call that here * instead of the fixed desc, which is only @@ -1217,10 +1214,8 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) } } - if (need_sense) { - /* The ata_gen_..._sense routines fill in tf */ - ata_dump_status(qc->ap->id, &qc->tf); - } + if (need_sense) + ata_dump_status(qc->ap->id, &qc->result_tf); qc->scsidone(cmd); @@ -2004,7 +1999,6 @@ static void atapi_sense_complete(struct ata_queued_cmd *qc) * a sense descriptors, since that's only * correct for ATA, not ATAPI */ - qc->ap->ops->tf_read(qc->ap, &qc->tf); ata_gen_ata_desc_sense(qc); } @@ -2080,7 +2074,6 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc) * a sense descriptors, since that's only * correct for ATA, not ATAPI */ - qc->ap->ops->tf_read(qc->ap, &qc->tf); ata_gen_ata_desc_sense(qc); } else { u8 *scsicmd = cmd->cmnd; @@ -2361,6 +2354,9 @@ ata_scsi_pass_thru(struct ata_queued_cmd *qc, const u8 *scsicmd) */ qc->nsect = cmd->bufflen / ATA_SECT_SIZE; + /* request result TF */ + qc->flags |= ATA_QCFLAG_RESULT_TF; + return 0; invalid_fld: diff --git a/include/linux/libata.h b/include/linux/libata.h index 0e1a3be3947..a4b8a419caa 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -162,7 +162,9 @@ enum { ATA_QCFLAG_SINGLE = (1 << 2), /* no s/g, just a single buffer */ ATA_QCFLAG_DMAMAP = ATA_QCFLAG_SG | ATA_QCFLAG_SINGLE, ATA_QCFLAG_IO = (1 << 3), /* standard IO command */ - ATA_QCFLAG_EH_SCHEDULED = (1 << 4), /* EH scheduled */ + ATA_QCFLAG_RESULT_TF = (1 << 4), /* result TF requested */ + + ATA_QCFLAG_EH_SCHEDULED = (1 << 16), /* EH scheduled */ /* host set flags */ ATA_HOST_SIMPLEX = (1 << 0), /* Host is simplex, one DMA channel per host_set only */ @@ -343,7 +345,7 @@ struct ata_queued_cmd { struct scatterlist *__sg; unsigned int err_mask; - + struct ata_taskfile result_tf; ata_qc_cb_t complete_fn; void *private_data; @@ -824,6 +826,10 @@ static inline void ata_qc_reinit(struct ata_queued_cmd *qc) qc->err_mask = 0; ata_tf_init(qc->ap, &qc->tf, qc->dev->devno); + + /* init result_tf such that it indicates normal completion */ + qc->result_tf.command = ATA_DRDY; + qc->result_tf.feature = 0; } /** @@ -839,9 +845,15 @@ static inline void ata_qc_reinit(struct ata_queued_cmd *qc) */ static inline void ata_qc_complete(struct ata_queued_cmd *qc) { + struct ata_port *ap = qc->ap; + if (unlikely(qc->flags & ATA_QCFLAG_EH_SCHEDULED)) return; + /* read result TF if failed or requested */ + if (qc->err_mask || qc->flags & ATA_QCFLAG_RESULT_TF) + ap->ops->tf_read(ap, &qc->result_tf); + __ata_qc_complete(qc); } -- cgit v1.2.3 From ce5f7f3d0cab82d6c16fcb64def8bfc0a3a85dd6 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:57:42 +0900 Subject: [PATCH] sata_sil24: update TF image only when necessary Update TF image (pp->tf) only when necessary. Signed-off-by: Tejun Heo --- drivers/scsi/sata_sil24.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 8c167250f4c..45b9e37c191 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -799,17 +799,9 @@ static inline void sil24_host_intr(struct ata_port *ap) if (ap->flags & SIL24_FLAG_PCIX_IRQ_WOC) writel(PORT_IRQ_COMPLETE, port + PORT_IRQ_STAT); - /* - * !HOST_SSAT_ATTN guarantees successful completion, - * so reading back tf registers is unnecessary for - * most commands. TODO: read tf registers for - * commands which require these values on successful - * completion (EXECUTE DEVICE DIAGNOSTIC, CHECK POWER, - * DEVICE RESET and READ PORT MULTIPLIER (any more?). - */ - sil24_update_tf(ap); - if (qc) { + if (qc->flags & ATA_QCFLAG_RESULT_TF) + sil24_update_tf(ap); qc->err_mask |= ac_err_mask(pp->tf.command); ata_qc_complete(qc); } -- cgit v1.2.3 From 838df6284c54447efae956fb9c243d8ba4ab0f47 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:57:44 +0900 Subject: [PATCH] libata: init ap->cbl to ATA_CBL_SATA early Init ap->cbl to ATA_CBL_SATA in ata_host_init(). This is necessary for soon-to-follow SCR handling function changes. LLDDs are free to change ap->cbl during probing. Signed-off-by: Tejun Heo --- drivers/scsi/libata-core.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 51cb9ca5519..f29d43cb699 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2370,8 +2370,7 @@ void ata_std_probeinit(struct ata_port *ap) if ((ap->flags & ATA_FLAG_SATA) && ap->ops->scr_read) { u32 spd; - /* set cable type and resume link */ - ap->cbl = ATA_CBL_SATA; + /* resume link */ sata_phy_resume(ap); /* init sata_spd_limit to the current value */ @@ -4586,7 +4585,6 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host, ap->udma_mask = ent->udma_mask; ap->flags |= ent->host_flags; ap->ops = ent->port_ops; - ap->cbl = ATA_CBL_NONE; ap->sata_spd_limit = UINT_MAX; ap->active_tag = ATA_TAG_POISON; ap->last_ctl = 0xFF; @@ -4594,6 +4592,11 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host, INIT_WORK(&ap->port_task, NULL, NULL); INIT_LIST_HEAD(&ap->eh_done_q); + /* set cable type */ + ap->cbl = ATA_CBL_NONE; + if (ap->flags & ATA_FLAG_SATA) + ap->cbl = ATA_CBL_SATA; + for (i = 0; i < ATA_MAX_DEVICES; i++) { struct ata_device *dev = &ap->device[i]; dev->devno = i; -- cgit v1.2.3 From 34bf21704c848fe00c516d1c8f163db08b70b137 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:57:46 +0900 Subject: [PATCH] libata: implement new SCR handling and port on/offline functions Implement ata_scr_{valid|read|write|write_flush}() and ata_port_{online|offline}(). These functions replace scr_{read|write}() and sata_dev_present(). Major difference between between the new SCR functions and the old ones is that the new ones have a way to signal error to the caller. This makes handling SCR-available and SCR-unavailable cases in the same path easier. Also, it eases later PM implementation where SCR access can fail due to various reasons. ata_port_{online|offline}() functions return 1 only when they are affirmitive of the condition. e.g. if SCR is unaccessible or presence cannot be determined for other reasons, these functions return 0. So, ata_port_online() != !ata_port_offline(). This distinction is useful in many exception handling cases. Signed-off-by: Tejun Heo --- drivers/scsi/libata-core.c | 143 +++++++++++++++++++++++++++++++++++++++++++++ include/linux/libata.h | 6 ++ 2 files changed, 149 insertions(+) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index f29d43cb699..b9c5cbf0b78 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -4365,6 +4365,143 @@ irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs) return IRQ_RETVAL(handled); } +/** + * sata_scr_valid - test whether SCRs are accessible + * @ap: ATA port to test SCR accessibility for + * + * Test whether SCRs are accessible for @ap. + * + * LOCKING: + * None. + * + * RETURNS: + * 1 if SCRs are accessible, 0 otherwise. + */ +int sata_scr_valid(struct ata_port *ap) +{ + return ap->cbl == ATA_CBL_SATA && ap->ops->scr_read; +} + +/** + * sata_scr_read - read SCR register of the specified port + * @ap: ATA port to read SCR for + * @reg: SCR to read + * @val: Place to store read value + * + * Read SCR register @reg of @ap into *@val. This function is + * guaranteed to succeed if the cable type of the port is SATA + * and the port implements ->scr_read. + * + * LOCKING: + * None. + * + * RETURNS: + * 0 on success, negative errno on failure. + */ +int sata_scr_read(struct ata_port *ap, int reg, u32 *val) +{ + if (sata_scr_valid(ap)) { + *val = ap->ops->scr_read(ap, reg); + return 0; + } + return -EOPNOTSUPP; +} + +/** + * sata_scr_write - write SCR register of the specified port + * @ap: ATA port to write SCR for + * @reg: SCR to write + * @val: value to write + * + * Write @val to SCR register @reg of @ap. This function is + * guaranteed to succeed if the cable type of the port is SATA + * and the port implements ->scr_read. + * + * LOCKING: + * None. + * + * RETURNS: + * 0 on success, negative errno on failure. + */ +int sata_scr_write(struct ata_port *ap, int reg, u32 val) +{ + if (sata_scr_valid(ap)) { + ap->ops->scr_write(ap, reg, val); + return 0; + } + return -EOPNOTSUPP; +} + +/** + * sata_scr_write_flush - write SCR register of the specified port and flush + * @ap: ATA port to write SCR for + * @reg: SCR to write + * @val: value to write + * + * This function is identical to sata_scr_write() except that this + * function performs flush after writing to the register. + * + * LOCKING: + * None. + * + * RETURNS: + * 0 on success, negative errno on failure. + */ +int sata_scr_write_flush(struct ata_port *ap, int reg, u32 val) +{ + if (sata_scr_valid(ap)) { + ap->ops->scr_write(ap, reg, val); + ap->ops->scr_read(ap, reg); + return 0; + } + return -EOPNOTSUPP; +} + +/** + * ata_port_online - test whether the given port is online + * @ap: ATA port to test + * + * Test whether @ap is online. Note that this function returns 0 + * if online status of @ap cannot be obtained, so + * ata_port_online(ap) != !ata_port_offline(ap). + * + * LOCKING: + * None. + * + * RETURNS: + * 1 if the port online status is available and online. + */ +int ata_port_online(struct ata_port *ap) +{ + u32 sstatus; + + if (!sata_scr_read(ap, SCR_STATUS, &sstatus) && (sstatus & 0xf) == 0x3) + return 1; + return 0; +} + +/** + * ata_port_offline - test whether the given port is offline + * @ap: ATA port to test + * + * Test whether @ap is offline. Note that this function returns + * 0 if offline status of @ap cannot be obtained, so + * ata_port_online(ap) != !ata_port_offline(ap). + * + * LOCKING: + * None. + * + * RETURNS: + * 1 if the port offline status is available and offline. + */ +int ata_port_offline(struct ata_port *ap) +{ + u32 sstatus; + + if (!sata_scr_read(ap, SCR_STATUS, &sstatus) && (sstatus & 0xf) != 0x3) + return 1; + return 0; +} /* * Execute a 'simple' command, that only consists of the opcode 'cmd' itself, @@ -5133,6 +5270,12 @@ EXPORT_SYMBOL_GPL(ata_scsi_queuecmd); EXPORT_SYMBOL_GPL(ata_scsi_slave_config); EXPORT_SYMBOL_GPL(ata_scsi_release); EXPORT_SYMBOL_GPL(ata_host_intr); +EXPORT_SYMBOL_GPL(sata_scr_valid); +EXPORT_SYMBOL_GPL(sata_scr_read); +EXPORT_SYMBOL_GPL(sata_scr_write); +EXPORT_SYMBOL_GPL(sata_scr_write_flush); +EXPORT_SYMBOL_GPL(ata_port_online); +EXPORT_SYMBOL_GPL(ata_port_offline); EXPORT_SYMBOL_GPL(ata_id_string); EXPORT_SYMBOL_GPL(ata_id_c_string); EXPORT_SYMBOL_GPL(ata_scsi_simulate); diff --git a/include/linux/libata.h b/include/linux/libata.h index a4b8a419caa..47b97157995 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -536,6 +536,12 @@ extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg); extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)); extern int ata_scsi_release(struct Scsi_Host *host); extern unsigned int ata_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc); +extern int sata_scr_valid(struct ata_port *ap); +extern int sata_scr_read(struct ata_port *ap, int reg, u32 *val); +extern int sata_scr_write(struct ata_port *ap, int reg, u32 val); +extern int sata_scr_write_flush(struct ata_port *ap, int reg, u32 val); +extern int ata_port_online(struct ata_port *ap); +extern int ata_port_offline(struct ata_port *ap); extern int ata_scsi_device_resume(struct scsi_device *); extern int ata_scsi_device_suspend(struct scsi_device *, pm_message_t state); extern int ata_device_resume(struct ata_port *, struct ata_device *); -- cgit v1.2.3 From 81952c5497b40ae56835bd0d6537f8c6bdea07e7 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:57:47 +0900 Subject: [PATCH] libata: use new SCR and on/offline functions Use new SCR and on/offline functions. Note that for LLDD which know it implements SCR callbacks, SCR functions are guaranteed to succeed and ata_port_online() == !ata_port_offline(). Signed-off-by: Tejun Heo --- drivers/scsi/ahci.c | 6 +-- drivers/scsi/libata-core.c | 107 +++++++++++++++++++++++++-------------------- drivers/scsi/sata_mv.c | 16 ++++--- drivers/scsi/sata_sil24.c | 6 +-- 4 files changed, 75 insertions(+), 60 deletions(-) diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index c33255404ee..c2298fb131d 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -567,7 +567,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class) DPRINTK("ENTER\n"); - if (!sata_dev_present(ap)) { + if (ata_port_offline(ap)) { DPRINTK("PHY reports no device\n"); *class = ATA_DEV_NONE; return 0; @@ -640,7 +640,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class) msleep(150); *class = ATA_DEV_NONE; - if (sata_dev_present(ap)) { + if (ata_port_online(ap)) { if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) { rc = -EIO; reason = "device not ready"; @@ -670,7 +670,7 @@ static int ahci_hardreset(struct ata_port *ap, unsigned int *class) rc = sata_std_hardreset(ap, class); ahci_start_engine(ap); - if (rc == 0 && sata_dev_present(ap)) + if (rc == 0 && ata_port_online(ap)) *class = ahci_dev_classify(ap); if (*class == ATA_DEV_UNKNOWN) *class = ATA_DEV_NONE; diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index b9c5cbf0b78..56f0af20834 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1494,13 +1494,11 @@ static void sata_print_link_status(struct ata_port *ap) { u32 sstatus, scontrol, tmp; - if (!ap->ops->scr_read) + if (sata_scr_read(ap, SCR_STATUS, &sstatus)) return; + sata_scr_read(ap, SCR_CONTROL, &scontrol); - sstatus = scr_read(ap, SCR_STATUS); - scontrol = scr_read(ap, SCR_CONTROL); - - if (sata_dev_present(ap)) { + if (ata_port_online(ap)) { tmp = (sstatus >> 4) & 0xf; printk(KERN_INFO "ata%u: SATA link up %s (SStatus %X SControl %X)\n", @@ -1531,17 +1529,18 @@ void __sata_phy_reset(struct ata_port *ap) if (ap->flags & ATA_FLAG_SATA_RESET) { /* issue phy wake/reset */ - scr_write_flush(ap, SCR_CONTROL, 0x301); + sata_scr_write_flush(ap, SCR_CONTROL, 0x301); /* Couldn't find anything in SATA I/II specs, but * AHCI-1.1 10.4.2 says at least 1 ms. */ mdelay(1); } - scr_write_flush(ap, SCR_CONTROL, 0x300); /* phy wake/clear reset */ + /* phy wake/clear reset */ + sata_scr_write_flush(ap, SCR_CONTROL, 0x300); /* wait for phy to become ready, if necessary */ do { msleep(200); - sstatus = scr_read(ap, SCR_STATUS); + sata_scr_read(ap, SCR_STATUS, &sstatus); if ((sstatus & 0xf) != 1) break; } while (time_before(jiffies, timeout)); @@ -1550,7 +1549,7 @@ void __sata_phy_reset(struct ata_port *ap) sata_print_link_status(ap); /* TODO: phy layer with polling, timeouts, etc. */ - if (sata_dev_present(ap)) + if (!ata_port_offline(ap)) ata_port_probe(ap); else ata_port_disable(ap); @@ -1638,11 +1637,12 @@ void ata_port_disable(struct ata_port *ap) */ int sata_down_spd_limit(struct ata_port *ap) { - u32 spd, mask; - int highbit; + u32 sstatus, spd, mask; + int rc, highbit; - if (ap->cbl != ATA_CBL_SATA || !ap->ops->scr_read) - return -EOPNOTSUPP; + rc = sata_scr_read(ap, SCR_STATUS, &sstatus); + if (rc) + return rc; mask = ap->sata_spd_limit; if (mask <= 1) @@ -1650,7 +1650,7 @@ int sata_down_spd_limit(struct ata_port *ap) highbit = fls(mask) - 1; mask &= ~(1 << highbit); - spd = (scr_read(ap, SCR_STATUS) >> 4) & 0xf; + spd = (sstatus >> 4) & 0xf; if (spd <= 1) return -EINVAL; spd--; @@ -1700,11 +1700,9 @@ int sata_set_spd_needed(struct ata_port *ap) { u32 scontrol; - if (ap->cbl != ATA_CBL_SATA || !ap->ops->scr_read) + if (sata_scr_read(ap, SCR_CONTROL, &scontrol)) return 0; - scontrol = scr_read(ap, SCR_CONTROL); - return __sata_set_spd_needed(ap, &scontrol); } @@ -1719,20 +1717,22 @@ int sata_set_spd_needed(struct ata_port *ap) * * RETURNS: * 0 if spd doesn't need to be changed, 1 if spd has been - * changed. -EOPNOTSUPP if SCR registers are inaccessible. + * changed. Negative errno if SCR registers are inaccessible. */ int sata_set_spd(struct ata_port *ap) { u32 scontrol; + int rc; - if (ap->cbl != ATA_CBL_SATA || !ap->ops->scr_read) - return -EOPNOTSUPP; + if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol))) + return rc; - scontrol = scr_read(ap, SCR_CONTROL); if (!__sata_set_spd_needed(ap, &scontrol)) return 0; - scr_write(ap, SCR_CONTROL, scontrol); + if ((rc = sata_scr_write(ap, SCR_CONTROL, scontrol))) + return rc; + return 1; } @@ -2336,20 +2336,26 @@ static int sata_phy_resume(struct ata_port *ap) { unsigned long timeout = jiffies + (HZ * 5); u32 scontrol, sstatus; + int rc; + + if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol))) + return rc; - scontrol = scr_read(ap, SCR_CONTROL); scontrol = (scontrol & 0x0f0) | 0x300; - scr_write_flush(ap, SCR_CONTROL, scontrol); + + if ((rc = sata_scr_write(ap, SCR_CONTROL, scontrol))) + return rc; /* Wait for phy to become ready, if necessary. */ do { msleep(200); - sstatus = scr_read(ap, SCR_STATUS); + if ((rc = sata_scr_read(ap, SCR_STATUS, &sstatus))) + return rc; if ((sstatus & 0xf) != 1) return 0; } while (time_before(jiffies, timeout)); - return -1; + return -EBUSY; } /** @@ -2367,21 +2373,20 @@ static int sata_phy_resume(struct ata_port *ap) */ void ata_std_probeinit(struct ata_port *ap) { - if ((ap->flags & ATA_FLAG_SATA) && ap->ops->scr_read) { - u32 spd; - - /* resume link */ - sata_phy_resume(ap); + u32 scontrol; - /* init sata_spd_limit to the current value */ - spd = (scr_read(ap, SCR_CONTROL) & 0xf0) >> 4; - if (spd) - ap->sata_spd_limit &= (1 << spd) - 1; + /* resume link */ + sata_phy_resume(ap); - /* wait for device */ - if (sata_dev_present(ap)) - ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT); + /* init sata_spd_limit to the current value */ + if (sata_scr_read(ap, SCR_CONTROL, &scontrol) == 0) { + int spd = (scontrol >> 4) & 0xf; + ap->sata_spd_limit &= (1 << spd) - 1; } + + /* wait for device */ + if (ata_port_online(ap)) + ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT); } /** @@ -2406,7 +2411,7 @@ int ata_std_softreset(struct ata_port *ap, unsigned int *classes) DPRINTK("ENTER\n"); - if (ap->ops->scr_read && !sata_dev_present(ap)) { + if (ata_port_offline(ap)) { classes[0] = ATA_DEV_NONE; goto out; } @@ -2457,6 +2462,7 @@ int ata_std_softreset(struct ata_port *ap, unsigned int *classes) int sata_std_hardreset(struct ata_port *ap, unsigned int *class) { u32 scontrol; + int rc; DPRINTK("ENTER\n"); @@ -2466,17 +2472,25 @@ int sata_std_hardreset(struct ata_port *ap, unsigned int *class) * reconfiguration. This works for at least ICH7 AHCI * and Sil3124. */ - scontrol = scr_read(ap, SCR_CONTROL); + if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol))) + return rc; + scontrol = (scontrol & 0x0f0) | 0x302; - scr_write_flush(ap, SCR_CONTROL, scontrol); + + if ((rc = sata_scr_write(ap, SCR_CONTROL, scontrol))) + return rc; sata_set_spd(ap); } /* issue phy wake/reset */ - scontrol = scr_read(ap, SCR_CONTROL); + if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol))) + return rc; + scontrol = (scontrol & 0x0f0) | 0x301; - scr_write_flush(ap, SCR_CONTROL, scontrol); + + if ((rc = sata_scr_write_flush(ap, SCR_CONTROL, scontrol))) + return rc; /* Couldn't find anything in SATA I/II specs, but AHCI-1.1 * 10.4.2 says at least 1 ms. @@ -2487,7 +2501,7 @@ int sata_std_hardreset(struct ata_port *ap, unsigned int *class) sata_phy_resume(ap); /* TODO: phy layer with polling, timeouts, etc. */ - if (!sata_dev_present(ap)) { + if (ata_port_offline(ap)) { *class = ATA_DEV_NONE; DPRINTK("EXIT, link offline\n"); return 0; @@ -2527,8 +2541,7 @@ void ata_std_postreset(struct ata_port *ap, unsigned int *classes) DPRINTK("ENTER\n"); /* print link status */ - if (ap->cbl == ATA_CBL_SATA) - sata_print_link_status(ap); + sata_print_link_status(ap); /* re-enable interrupts */ if (ap->ioaddr.ctl_addr) /* FIXME: hack. create a hook instead */ @@ -2575,7 +2588,7 @@ int ata_std_probe_reset(struct ata_port *ap, unsigned int *classes) ata_reset_fn_t hardreset; hardreset = NULL; - if (ap->cbl == ATA_CBL_SATA && ap->ops->scr_read) + if (sata_scr_valid(ap)) hardreset = sata_std_hardreset; return ata_drive_probe_reset(ap, ata_std_probeinit, diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index 181917ac042..748569b615f 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -1309,8 +1309,8 @@ static void mv_err_intr(struct ata_port *ap) edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS); if (EDMA_ERR_SERR & edma_err_cause) { - serr = scr_read(ap, SCR_ERROR); - scr_write_flush(ap, SCR_ERROR, serr); + sata_scr_read(ap, SCR_ERROR, &serr); + sata_scr_write_flush(ap, SCR_ERROR, serr); } if (EDMA_ERR_SELF_DIS & edma_err_cause) { struct mv_port_priv *pp = ap->private_data; @@ -1934,15 +1934,16 @@ static void __mv_phy_reset(struct ata_port *ap, int can_sleep) /* Issue COMRESET via SControl */ comreset_retry: - scr_write_flush(ap, SCR_CONTROL, 0x301); + sata_scr_write_flush(ap, SCR_CONTROL, 0x301); __msleep(1, can_sleep); - scr_write_flush(ap, SCR_CONTROL, 0x300); + sata_scr_write_flush(ap, SCR_CONTROL, 0x300); __msleep(20, can_sleep); timeout = jiffies + msecs_to_jiffies(200); do { - sstatus = scr_read(ap, SCR_STATUS) & 0x3; + sata_scr_read(ap, SCR_STATUS, &sstatus); + sstatus &= 0x3; if ((sstatus == 3) || (sstatus == 0)) break; @@ -1959,11 +1960,12 @@ comreset_retry: "SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS), mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL)); - if (sata_dev_present(ap)) { + if (ata_port_online(ap)) { ata_port_probe(ap); } else { + sata_scr_read(ap, SCR_STATUS, &sstatus); printk(KERN_INFO "ata%u: no device found (phy stat %08x)\n", - ap->id, scr_read(ap, SCR_STATUS)); + ap->id, sstatus); ata_port_disable(ap); return; } diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 45b9e37c191..bedc787dafd 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -464,7 +464,7 @@ static int sil24_softreset(struct ata_port *ap, unsigned int *class) DPRINTK("ENTER\n"); - if (!sata_dev_present(ap)) { + if (ata_port_offline(ap)) { DPRINTK("PHY reports no device\n"); *class = ATA_DEV_NONE; goto out; @@ -531,7 +531,7 @@ static int sil24_hardreset(struct ata_port *ap, unsigned int *class) sata_set_spd(ap); tout_msec = 100; - if (sata_dev_present(ap)) + if (ata_port_online(ap)) tout_msec = 5000; writel(PORT_CS_DEV_RST, port + PORT_CTRL_STAT); @@ -544,7 +544,7 @@ static int sil24_hardreset(struct ata_port *ap, unsigned int *class) msleep(100); if (tmp & PORT_CS_DEV_RST) { - if (!sata_dev_present(ap)) + if (ata_port_offline(ap)) return 0; reason = "link not ready"; goto err; -- cgit v1.2.3 From a0ab51cefc95cb7756c4914603fea2b1a0f813c5 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:57:49 +0900 Subject: [PATCH] libata: kill old SCR functions and sata_dev_present() Kill now unused scr_{read|write|write_flush}() and sata_dev_present(). Signed-off-by: Tejun Heo --- include/linux/libata.h | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/include/linux/libata.h b/include/linux/libata.h index 47b97157995..cd467cd5447 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -939,28 +939,6 @@ static inline u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq) return status; } -static inline u32 scr_read(struct ata_port *ap, unsigned int reg) -{ - return ap->ops->scr_read(ap, reg); -} - -static inline void scr_write(struct ata_port *ap, unsigned int reg, u32 val) -{ - ap->ops->scr_write(ap, reg, val); -} - -static inline void scr_write_flush(struct ata_port *ap, unsigned int reg, - u32 val) -{ - ap->ops->scr_write(ap, reg, val); - (void) ap->ops->scr_read(ap, reg); -} - -static inline unsigned int sata_dev_present(struct ata_port *ap) -{ - return ((scr_read(ap, SCR_STATUS) & 0xf) == 0x3) ? 1 : 0; -} - static inline int ata_try_flush_cache(const struct ata_device *dev) { return ata_id_wcache_enabled(dev->id) || -- cgit v1.2.3 From 38d87234d6c47ca487fc6344100323d5adc6f32c Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:57:51 +0900 Subject: [PATCH] libata: add dev->ap Add dev->ap which points back to the port the device belongs to. This makes it unnecessary to pass @ap for silly reasons (e.g. printks). Also, this change is necessary to accomodate later PM support which will introduce ATA link inbetween port and device. Signed-off-by: Tejun Heo --- drivers/scsi/libata-core.c | 1 + include/linux/libata.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 56f0af20834..31b65e0da0b 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -4749,6 +4749,7 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host, for (i = 0; i < ATA_MAX_DEVICES; i++) { struct ata_device *dev = &ap->device[i]; + dev->ap = ap; dev->devno = i; dev->pio_mask = UINT_MAX; dev->mwdma_mask = UINT_MAX; diff --git a/include/linux/libata.h b/include/linux/libata.h index cd467cd5447..ac2d2cc78b1 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -358,6 +358,7 @@ struct ata_host_stats { }; struct ata_device { + struct ata_port *ap; u64 n_sectors; /* size of device, if ATA */ unsigned long flags; /* ATA_DFLAG_xxx */ unsigned int class; /* ATA_DEV_xxx */ -- cgit v1.2.3 From 3373efd89dead4ce7818d685729e0431448357c9 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:57:53 +0900 Subject: [PATCH] libata: use dev->ap Use dev->ap where possible and eliminate superflous @ap from functions and structures. Signed-off-by: Tejun Heo --- drivers/scsi/ahci.c | 2 +- drivers/scsi/libata-core.c | 160 +++++++++++++++++++++------------------------ drivers/scsi/libata-scsi.c | 40 +++++------- drivers/scsi/libata.h | 11 ++-- include/linux/libata.h | 21 +++--- 5 files changed, 106 insertions(+), 128 deletions(-) diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index c2298fb131d..f6e4c8ea74e 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -597,7 +597,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class) /* restart engine */ ahci_start_engine(ap); - ata_tf_init(ap, &tf, 0); + ata_tf_init(ap->device, &tf); fis = pp->cmd_tbl; /* issue the first D2H Register FIS */ diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 31b65e0da0b..4ced962db81 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -61,13 +61,10 @@ #include "libata.h" -static unsigned int ata_dev_init_params(struct ata_port *ap, - struct ata_device *dev, - u16 heads, - u16 sectors); -static unsigned int ata_dev_set_xfermode(struct ata_port *ap, - struct ata_device *dev); -static void ata_dev_xfermask(struct ata_port *ap, struct ata_device *dev); +static unsigned int ata_dev_init_params(struct ata_device *dev, + u16 heads, u16 sectors); +static unsigned int ata_dev_set_xfermode(struct ata_device *dev); +static void ata_dev_xfermask(struct ata_device *dev); static unsigned int ata_unique_id = 1; static struct workqueue_struct *ata_wq; @@ -412,11 +409,11 @@ static const char *sata_spd_string(unsigned int spd) return spd_str[spd - 1]; } -void ata_dev_disable(struct ata_port *ap, struct ata_device *dev) +void ata_dev_disable(struct ata_device *dev) { if (ata_dev_enabled(dev)) { printk(KERN_WARNING "ata%u: dev %u disabled\n", - ap->id, dev->devno); + dev->ap->id, dev->devno); dev->class++; } } @@ -960,7 +957,6 @@ void ata_qc_complete_internal(struct ata_queued_cmd *qc) /** * ata_exec_internal - execute libata internal command - * @ap: Port to which the command is sent * @dev: Device to which the command is sent * @tf: Taskfile registers for the command and the result * @cdb: CDB for packet command @@ -978,10 +974,11 @@ void ata_qc_complete_internal(struct ata_queued_cmd *qc) * None. Should be called with kernel context, might sleep. */ -unsigned ata_exec_internal(struct ata_port *ap, struct ata_device *dev, +unsigned ata_exec_internal(struct ata_device *dev, struct ata_taskfile *tf, const u8 *cdb, int dma_dir, void *buf, unsigned int buflen) { + struct ata_port *ap = dev->ap; u8 command = tf->command; struct ata_queued_cmd *qc; DECLARE_COMPLETION(wait); @@ -990,7 +987,7 @@ unsigned ata_exec_internal(struct ata_port *ap, struct ata_device *dev, spin_lock_irqsave(&ap->host_set->lock, flags); - qc = ata_qc_new_init(ap, dev); + qc = ata_qc_new_init(dev); BUG_ON(qc == NULL); qc->tf = *tf; @@ -1095,7 +1092,6 @@ unsigned int ata_pio_need_iordy(const struct ata_device *adev) /** * ata_dev_read_id - Read ID data from the specified device - * @ap: port on which target device resides * @dev: target device * @p_class: pointer to class of the target device (may be changed) * @post_reset: is this read ID post-reset? @@ -1112,9 +1108,10 @@ unsigned int ata_pio_need_iordy(const struct ata_device *adev) * RETURNS: * 0 on success, -errno otherwise. */ -static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, - unsigned int *p_class, int post_reset, u16 *id) +static int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, + int post_reset, u16 *id) { + struct ata_port *ap = dev->ap; unsigned int class = *p_class; struct ata_taskfile tf; unsigned int err_mask = 0; @@ -1126,7 +1123,7 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */ retry: - ata_tf_init(ap, &tf, dev->devno); + ata_tf_init(dev, &tf); switch (class) { case ATA_DEV_ATA: @@ -1143,7 +1140,7 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, tf.protocol = ATA_PROT_PIO; - err_mask = ata_exec_internal(ap, dev, &tf, NULL, DMA_FROM_DEVICE, + err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE, id, sizeof(id[0]) * ATA_ID_WORDS); if (err_mask) { rc = -EIO; @@ -1170,7 +1167,7 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, * Some drives were very specific about that exact sequence. */ if (ata_id_major_version(id) < 4 || !ata_id_has_lba(id)) { - err_mask = ata_dev_init_params(ap, dev, id[3], id[6]); + err_mask = ata_dev_init_params(dev, id[3], id[6]); if (err_mask) { rc = -EIO; reason = "INIT_DEV_PARAMS failed"; @@ -1195,15 +1192,13 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, return rc; } -static inline u8 ata_dev_knobble(const struct ata_port *ap, - struct ata_device *dev) +static inline u8 ata_dev_knobble(struct ata_device *dev) { - return ((ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(dev->id))); + return ((dev->ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(dev->id))); } /** * ata_dev_configure - Configure the specified ATA/ATAPI device - * @ap: Port on which target device resides * @dev: Target device to configure * @print_info: Enable device info printout * @@ -1216,9 +1211,9 @@ static inline u8 ata_dev_knobble(const struct ata_port *ap, * RETURNS: * 0 on success, -errno otherwise */ -static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev, - int print_info) +static int ata_dev_configure(struct ata_device *dev, int print_info) { + struct ata_port *ap = dev->ap; const u16 *id = dev->id; unsigned int xfer_mask; int i, rc; @@ -1331,7 +1326,7 @@ static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev, ap->device[i].cdb_len); /* limit bridge transfers to udma5, 200 sectors */ - if (ata_dev_knobble(ap, dev)) { + if (ata_dev_knobble(dev)) { if (print_info) printk(KERN_INFO "ata%u(%u): applying bridge limits\n", ap->id, dev->devno); @@ -1416,11 +1411,11 @@ static int ata_bus_probe(struct ata_port *ap) if (!ata_dev_enabled(dev)) continue; - rc = ata_dev_read_id(ap, dev, &dev->class, 1, dev->id); + rc = ata_dev_read_id(dev, &dev->class, 1, dev->id); if (rc) goto fail; - rc = ata_dev_configure(ap, dev, 1); + rc = ata_dev_configure(dev, 1); if (rc) goto fail; } @@ -1453,13 +1448,13 @@ static int ata_bus_probe(struct ata_port *ap) default: tries[dev->devno]--; if (down_xfermask && - ata_down_xfermask_limit(ap, dev, tries[dev->devno] == 1)) + ata_down_xfermask_limit(dev, tries[dev->devno] == 1)) tries[dev->devno] = 0; } if (!tries[dev->devno]) { - ata_down_xfermask_limit(ap, dev, 1); - ata_dev_disable(ap, dev); + ata_down_xfermask_limit(dev, 1); + ata_dev_disable(dev); } goto retry; @@ -1586,15 +1581,15 @@ void sata_phy_reset(struct ata_port *ap) /** * ata_dev_pair - return other device on cable - * @ap: port * @adev: device * * Obtain the other device on the same cable, or if none is * present NULL is returned */ -struct ata_device *ata_dev_pair(struct ata_port *ap, struct ata_device *adev) +struct ata_device *ata_dev_pair(struct ata_device *adev) { + struct ata_port *ap = adev->ap; struct ata_device *pair = &ap->device[1 - adev->devno]; if (!ata_dev_enabled(pair)) return NULL; @@ -1886,7 +1881,6 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed, /** * ata_down_xfermask_limit - adjust dev xfer masks downward - * @ap: Port associated with device @dev * @dev: Device to adjust xfer masks * @force_pio0: Force PIO0 * @@ -1900,9 +1894,9 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed, * RETURNS: * 0 on success, negative errno on failure */ -int ata_down_xfermask_limit(struct ata_port *ap, struct ata_device *dev, - int force_pio0) +int ata_down_xfermask_limit(struct ata_device *dev, int force_pio0) { + struct ata_port *ap = dev->ap; unsigned long xfer_mask; int highbit; @@ -1934,8 +1928,9 @@ int ata_down_xfermask_limit(struct ata_port *ap, struct ata_device *dev, return -EINVAL; } -static int ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev) +static int ata_dev_set_mode(struct ata_device *dev) { + struct ata_port *ap = dev->ap; unsigned int err_mask; int rc; @@ -1943,7 +1938,7 @@ static int ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev) if (dev->xfer_shift == ATA_SHIFT_PIO) dev->flags |= ATA_DFLAG_PIO; - err_mask = ata_dev_set_xfermode(ap, dev); + err_mask = ata_dev_set_xfermode(dev); if (err_mask) { printk(KERN_ERR "ata%u: failed to set xfermode (err_mask=0x%x)\n", @@ -1951,7 +1946,7 @@ static int ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev) return -EIO; } - rc = ata_dev_revalidate(ap, dev, 0); + rc = ata_dev_revalidate(dev, 0); if (rc) return rc; @@ -2007,7 +2002,7 @@ int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev) if (!ata_dev_enabled(dev)) continue; - ata_dev_xfermask(ap, dev); + ata_dev_xfermask(dev); pio_mask = ata_pack_xfermask(dev->pio_mask, 0, 0); dma_mask = ata_pack_xfermask(0, dev->mwdma_mask, dev->udma_mask); @@ -2060,7 +2055,7 @@ int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev) if (!ata_dev_enabled(dev)) continue; - rc = ata_dev_set_mode(ap, dev); + rc = ata_dev_set_mode(dev); if (rc) goto out; } @@ -2712,7 +2707,6 @@ int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, /** * ata_dev_same_device - Determine whether new ID matches configured device - * @ap: port on which the device to compare against resides * @dev: device to compare against * @new_class: class of the new device * @new_id: IDENTIFY page of the new device @@ -2727,9 +2721,10 @@ int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, * RETURNS: * 1 if @dev matches @new_class and @new_id, 0 otherwise. */ -static int ata_dev_same_device(struct ata_port *ap, struct ata_device *dev, - unsigned int new_class, const u16 *new_id) +static int ata_dev_same_device(struct ata_device *dev, unsigned int new_class, + const u16 *new_id) { + struct ata_port *ap = dev->ap; const u16 *old_id = dev->id; unsigned char model[2][41], serial[2][21]; u64 new_n_sectors; @@ -2774,7 +2769,6 @@ static int ata_dev_same_device(struct ata_port *ap, struct ata_device *dev, /** * ata_dev_revalidate - Revalidate ATA device - * @ap: port on which the device to revalidate resides * @dev: device to revalidate * @post_reset: is this revalidation after reset? * @@ -2787,9 +2781,9 @@ static int ata_dev_same_device(struct ata_port *ap, struct ata_device *dev, * RETURNS: * 0 on success, negative errno otherwise */ -int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev, - int post_reset) +int ata_dev_revalidate(struct ata_device *dev, int post_reset) { + struct ata_port *ap = dev->ap; unsigned int class = dev->class; u16 *id = (void *)ap->sector_buf; int rc; @@ -2800,12 +2794,12 @@ int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev, } /* read ID data */ - rc = ata_dev_read_id(ap, dev, &class, post_reset, id); + rc = ata_dev_read_id(dev, &class, post_reset, id); if (rc) goto fail; /* is the device still there? */ - if (!ata_dev_same_device(ap, dev, class, id)) { + if (!ata_dev_same_device(dev, class, id)) { rc = -ENODEV; goto fail; } @@ -2813,7 +2807,7 @@ int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev, memcpy(dev->id, id, sizeof(id[0]) * ATA_ID_WORDS); /* configure device according to the new ID */ - rc = ata_dev_configure(ap, dev, 0); + rc = ata_dev_configure(dev, 0); if (rc == 0) return 0; @@ -2895,7 +2889,6 @@ static int ata_dma_blacklisted(const struct ata_device *dev) /** * ata_dev_xfermask - Compute supported xfermask of the given device - * @ap: Port on which the device to compute xfermask for resides * @dev: Device to compute xfermask for * * Compute supported xfermask of @dev and store it in @@ -2910,8 +2903,9 @@ static int ata_dma_blacklisted(const struct ata_device *dev) * LOCKING: * None. */ -static void ata_dev_xfermask(struct ata_port *ap, struct ata_device *dev) +static void ata_dev_xfermask(struct ata_device *dev) { + struct ata_port *ap = dev->ap; struct ata_host_set *hs = ap->host_set; unsigned long xfer_mask; int i; @@ -2964,7 +2958,6 @@ static void ata_dev_xfermask(struct ata_port *ap, struct ata_device *dev) /** * ata_dev_set_xfermode - Issue SET FEATURES - XFER MODE command - * @ap: Port associated with device @dev * @dev: Device to which command will be sent * * Issue SET FEATURES - XFER MODE command to device @dev @@ -2977,8 +2970,7 @@ static void ata_dev_xfermask(struct ata_port *ap, struct ata_device *dev) * 0 on success, AC_ERR_* mask otherwise. */ -static unsigned int ata_dev_set_xfermode(struct ata_port *ap, - struct ata_device *dev) +static unsigned int ata_dev_set_xfermode(struct ata_device *dev) { struct ata_taskfile tf; unsigned int err_mask; @@ -2986,14 +2978,14 @@ static unsigned int ata_dev_set_xfermode(struct ata_port *ap, /* set up set-features taskfile */ DPRINTK("set features - xfer mode\n"); - ata_tf_init(ap, &tf, dev->devno); + ata_tf_init(dev, &tf); tf.command = ATA_CMD_SET_FEATURES; tf.feature = SETFEATURES_XFER; tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; tf.protocol = ATA_PROT_NODATA; tf.nsect = dev->xfer_mode; - err_mask = ata_exec_internal(ap, dev, &tf, NULL, DMA_NONE, NULL, 0); + err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0); DPRINTK("EXIT, err_mask=%x\n", err_mask); return err_mask; @@ -3001,8 +2993,9 @@ static unsigned int ata_dev_set_xfermode(struct ata_port *ap, /** * ata_dev_init_params - Issue INIT DEV PARAMS command - * @ap: Port associated with device @dev * @dev: Device to which command will be sent + * @heads: Number of heads + * @sectors: Number of sectors * * LOCKING: * Kernel thread context (may sleep) @@ -3010,11 +3003,8 @@ static unsigned int ata_dev_set_xfermode(struct ata_port *ap, * RETURNS: * 0 on success, AC_ERR_* mask otherwise. */ - -static unsigned int ata_dev_init_params(struct ata_port *ap, - struct ata_device *dev, - u16 heads, - u16 sectors) +static unsigned int ata_dev_init_params(struct ata_device *dev, + u16 heads, u16 sectors) { struct ata_taskfile tf; unsigned int err_mask; @@ -3026,14 +3016,14 @@ static unsigned int ata_dev_init_params(struct ata_port *ap, /* set up init dev params taskfile */ DPRINTK("init dev params \n"); - ata_tf_init(ap, &tf, dev->devno); + ata_tf_init(dev, &tf); tf.command = ATA_CMD_INIT_DEV_PARAMS; tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; tf.protocol = ATA_PROT_NODATA; tf.nsect = sectors; tf.device |= (heads - 1) & 0x0f; /* max head = num. of heads - 1 */ - err_mask = ata_exec_internal(ap, dev, &tf, NULL, DMA_NONE, NULL, 0); + err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0); DPRINTK("EXIT, err_mask=%x\n", err_mask); return err_mask; @@ -4045,16 +4035,15 @@ static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap) /** * ata_qc_new_init - Request an available ATA command, and initialize it - * @ap: Port associated with device @dev * @dev: Device from whom we request an available command structure * * LOCKING: * None. */ -struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, - struct ata_device *dev) +struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev) { + struct ata_port *ap = dev->ap; struct ata_queued_cmd *qc; qc = ata_qc_new(ap); @@ -4520,19 +4509,18 @@ int ata_port_offline(struct ata_port *ap) * Execute a 'simple' command, that only consists of the opcode 'cmd' itself, * without filling any other registers */ -static int ata_do_simple_cmd(struct ata_port *ap, struct ata_device *dev, - u8 cmd) +static int ata_do_simple_cmd(struct ata_device *dev, u8 cmd) { struct ata_taskfile tf; int err; - ata_tf_init(ap, &tf, dev->devno); + ata_tf_init(dev, &tf); tf.command = cmd; tf.flags |= ATA_TFLAG_DEVICE; tf.protocol = ATA_PROT_NODATA; - err = ata_exec_internal(ap, dev, &tf, NULL, DMA_NONE, NULL, 0); + err = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0); if (err) printk(KERN_ERR "%s: ata command failed: %d\n", __FUNCTION__, err); @@ -4540,7 +4528,7 @@ static int ata_do_simple_cmd(struct ata_port *ap, struct ata_device *dev, return err; } -static int ata_flush_cache(struct ata_port *ap, struct ata_device *dev) +static int ata_flush_cache(struct ata_device *dev) { u8 cmd; @@ -4552,22 +4540,21 @@ static int ata_flush_cache(struct ata_port *ap, struct ata_device *dev) else cmd = ATA_CMD_FLUSH; - return ata_do_simple_cmd(ap, dev, cmd); + return ata_do_simple_cmd(dev, cmd); } -static int ata_standby_drive(struct ata_port *ap, struct ata_device *dev) +static int ata_standby_drive(struct ata_device *dev) { - return ata_do_simple_cmd(ap, dev, ATA_CMD_STANDBYNOW1); + return ata_do_simple_cmd(dev, ATA_CMD_STANDBYNOW1); } -static int ata_start_drive(struct ata_port *ap, struct ata_device *dev) +static int ata_start_drive(struct ata_device *dev) { - return ata_do_simple_cmd(ap, dev, ATA_CMD_IDLEIMMEDIATE); + return ata_do_simple_cmd(dev, ATA_CMD_IDLEIMMEDIATE); } /** * ata_device_resume - wakeup a previously suspended devices - * @ap: port the device is connected to * @dev: the device to resume * * Kick the drive back into action, by sending it an idle immediate @@ -4575,39 +4562,42 @@ static int ata_start_drive(struct ata_port *ap, struct ata_device *dev) * and host. * */ -int ata_device_resume(struct ata_port *ap, struct ata_device *dev) +int ata_device_resume(struct ata_device *dev) { + struct ata_port *ap = dev->ap; + if (ap->flags & ATA_FLAG_SUSPENDED) { struct ata_device *failed_dev; ap->flags &= ~ATA_FLAG_SUSPENDED; while (ata_set_mode(ap, &failed_dev)) - ata_dev_disable(ap, failed_dev); + ata_dev_disable(failed_dev); } if (!ata_dev_enabled(dev)) return 0; if (dev->class == ATA_DEV_ATA) - ata_start_drive(ap, dev); + ata_start_drive(dev); return 0; } /** * ata_device_suspend - prepare a device for suspend - * @ap: port the device is connected to * @dev: the device to suspend * * Flush the cache on the drive, if appropriate, then issue a * standbynow command. */ -int ata_device_suspend(struct ata_port *ap, struct ata_device *dev, pm_message_t state) +int ata_device_suspend(struct ata_device *dev, pm_message_t state) { + struct ata_port *ap = dev->ap; + if (!ata_dev_enabled(dev)) return 0; if (dev->class == ATA_DEV_ATA) - ata_flush_cache(ap, dev); + ata_flush_cache(dev); if (state.event != PM_EVENT_FREEZE) - ata_standby_drive(ap, dev); + ata_standby_drive(dev); ap->flags |= ATA_FLAG_SUSPENDED; return 0; } diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index ce90b6352a8..fcbf64e741b 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -302,7 +302,6 @@ int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg) /** * ata_scsi_qc_new - acquire new ata_queued_cmd reference - * @ap: ATA port to which the new command is attached * @dev: ATA device to which the new command is attached * @cmd: SCSI command that originated this ATA command * @done: SCSI command completion function @@ -321,14 +320,13 @@ int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg) * RETURNS: * Command allocated, or %NULL if none available. */ -struct ata_queued_cmd *ata_scsi_qc_new(struct ata_port *ap, - struct ata_device *dev, +struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev, struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) { struct ata_queued_cmd *qc; - qc = ata_qc_new_init(ap, dev); + qc = ata_qc_new_init(dev); if (qc) { qc->scsicmd = cmd; qc->scsidone = done; @@ -398,7 +396,7 @@ int ata_scsi_device_resume(struct scsi_device *sdev) struct ata_port *ap = ata_shost_to_port(sdev->host); struct ata_device *dev = &ap->device[sdev->id]; - return ata_device_resume(ap, dev); + return ata_device_resume(dev); } int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t state) @@ -406,7 +404,7 @@ int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t state) struct ata_port *ap = ata_shost_to_port(sdev->host); struct ata_device *dev = &ap->device[sdev->id]; - return ata_device_suspend(ap, dev, state); + return ata_device_suspend(dev, state); } /** @@ -1224,7 +1222,6 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) /** * ata_scsi_translate - Translate then issue SCSI command to ATA device - * @ap: ATA port to which the command is addressed * @dev: ATA device to which the command is addressed * @cmd: SCSI command to execute * @done: SCSI command completion function @@ -1247,17 +1244,16 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) * spin_lock_irqsave(host_set lock) */ -static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev, - struct scsi_cmnd *cmd, - void (*done)(struct scsi_cmnd *), - ata_xlat_func_t xlat_func) +static void ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cmd, + void (*done)(struct scsi_cmnd *), + ata_xlat_func_t xlat_func) { struct ata_queued_cmd *qc; u8 *scsicmd = cmd->cmnd; VPRINTK("ENTER\n"); - qc = ata_scsi_qc_new(ap, dev, cmd, done); + qc = ata_scsi_qc_new(dev, cmd, done); if (!qc) goto err_mem; @@ -1266,7 +1262,7 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev, cmd->sc_data_direction == DMA_TO_DEVICE) { if (unlikely(cmd->request_bufflen < 1)) { printk(KERN_WARNING "ata%u(%u): WARNING: zero len r/w req\n", - ap->id, dev->devno); + dev->ap->id, dev->devno); goto err_did; } @@ -2433,19 +2429,20 @@ static inline void ata_scsi_dump_cdb(struct ata_port *ap, #endif } -static inline void __ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), - struct ata_port *ap, struct ata_device *dev) +static inline void __ata_scsi_queuecmd(struct scsi_cmnd *cmd, + void (*done)(struct scsi_cmnd *), + struct ata_device *dev) { if (dev->class == ATA_DEV_ATA) { ata_xlat_func_t xlat_func = ata_get_xlat_func(dev, cmd->cmnd[0]); if (xlat_func) - ata_scsi_translate(ap, dev, cmd, done, xlat_func); + ata_scsi_translate(dev, cmd, done, xlat_func); else - ata_scsi_simulate(ap, dev, cmd, done); + ata_scsi_simulate(dev, cmd, done); } else - ata_scsi_translate(ap, dev, cmd, done, atapi_xlat); + ata_scsi_translate(dev, cmd, done, atapi_xlat); } /** @@ -2483,7 +2480,7 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) dev = ata_scsi_find_dev(ap, scsidev); if (likely(dev)) - __ata_scsi_queuecmd(cmd, done, ap, dev); + __ata_scsi_queuecmd(cmd, done, dev); else { cmd->result = (DID_BAD_TARGET << 16); done(cmd); @@ -2496,7 +2493,6 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) /** * ata_scsi_simulate - simulate SCSI command on ATA device - * @ap: port the device is connected to * @dev: the target device * @cmd: SCSI command being sent to device. * @done: SCSI command completion function. @@ -2508,14 +2504,12 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) * spin_lock_irqsave(host_set lock) */ -void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev, - struct scsi_cmnd *cmd, +void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) { struct ata_scsi_args args; const u8 *scsicmd = cmd->cmnd; - args.ap = ap; args.dev = dev; args.id = dev->id; args.cmd = cmd; diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index 6442c2f1a80..c9ff83bbcfa 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -32,7 +32,6 @@ #define DRV_VERSION "1.30" /* must be exactly four chars */ struct ata_scsi_args { - struct ata_port *ap; struct ata_device *dev; u16 *id; struct scsi_cmnd *cmd; @@ -43,18 +42,16 @@ struct ata_scsi_args { extern int atapi_enabled; extern int atapi_dmadir; extern int libata_fua; -extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, - struct ata_device *dev); +extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev); extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc); -extern void ata_dev_disable(struct ata_port *ap, struct ata_device *dev); +extern void ata_dev_disable(struct ata_device *dev); extern void ata_port_flush_task(struct ata_port *ap); -extern unsigned ata_exec_internal(struct ata_port *ap, struct ata_device *dev, +extern unsigned ata_exec_internal(struct ata_device *dev, struct ata_taskfile *tf, const u8 *cdb, int dma_dir, void *buf, unsigned int buflen); extern int sata_down_spd_limit(struct ata_port *ap); extern int sata_set_spd_needed(struct ata_port *ap); -extern int ata_down_xfermask_limit(struct ata_port *ap, struct ata_device *dev, - int force_pio0); +extern int ata_down_xfermask_limit(struct ata_device *dev, int force_pio0); extern int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev); extern int ata_do_reset(struct ata_port *ap, ata_reset_fn_t reset, unsigned int *classes); diff --git a/include/linux/libata.h b/include/linux/libata.h index ac2d2cc78b1..8154b366bbd 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -518,8 +518,7 @@ extern void ata_std_probeinit(struct ata_port *ap); extern int ata_std_softreset(struct ata_port *ap, unsigned int *classes); extern int sata_std_hardreset(struct ata_port *ap, unsigned int *class); extern void ata_std_postreset(struct ata_port *ap, unsigned int *classes); -extern int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev, - int post_reset); +extern int ata_dev_revalidate(struct ata_device *dev, int post_reset); extern void ata_port_disable(struct ata_port *); extern void ata_std_ports(struct ata_ioports *ioaddr); #ifdef CONFIG_PCI @@ -545,8 +544,8 @@ extern int ata_port_online(struct ata_port *ap); extern int ata_port_offline(struct ata_port *ap); extern int ata_scsi_device_resume(struct scsi_device *); extern int ata_scsi_device_suspend(struct scsi_device *, pm_message_t state); -extern int ata_device_resume(struct ata_port *, struct ata_device *); -extern int ata_device_suspend(struct ata_port *, struct ata_device *, pm_message_t state); +extern int ata_device_resume(struct ata_device *); +extern int ata_device_suspend(struct ata_device *, pm_message_t state); extern int ata_ratelimit(void); extern unsigned int ata_busy_sleep(struct ata_port *ap, unsigned long timeout_pat, @@ -592,15 +591,13 @@ extern void ata_bmdma_stop(struct ata_queued_cmd *qc); extern u8 ata_bmdma_status(struct ata_port *ap); extern void ata_bmdma_irq_clear(struct ata_port *ap); extern void __ata_qc_complete(struct ata_queued_cmd *qc); -extern void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev, - struct scsi_cmnd *cmd, +extern void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)); extern int ata_std_bios_param(struct scsi_device *sdev, struct block_device *bdev, sector_t capacity, int geom[]); extern int ata_scsi_slave_config(struct scsi_device *sdev); -extern struct ata_device *ata_dev_pair(struct ata_port *ap, - struct ata_device *adev); +extern struct ata_device *ata_dev_pair(struct ata_device *adev); /* * Timing helpers @@ -812,12 +809,12 @@ static inline struct ata_queued_cmd *ata_qc_from_tag (struct ata_port *ap, return NULL; } -static inline void ata_tf_init(struct ata_port *ap, struct ata_taskfile *tf, unsigned int device) +static inline void ata_tf_init(struct ata_device *dev, struct ata_taskfile *tf) { memset(tf, 0, sizeof(*tf)); - tf->ctl = ap->ctl; - if (device == 0) + tf->ctl = dev->ap->ctl; + if (dev->devno == 0) tf->device = ATA_DEVICE_OBS; else tf->device = ATA_DEVICE_OBS | ATA_DEV1; @@ -832,7 +829,7 @@ static inline void ata_qc_reinit(struct ata_queued_cmd *qc) qc->nbytes = qc->curbytes = 0; qc->err_mask = 0; - ata_tf_init(qc->ap, &qc->tf, qc->dev->devno); + ata_tf_init(qc->dev, &qc->tf); /* init result_tf such that it indicates normal completion */ qc->result_tf.command = ATA_DRDY; -- cgit v1.2.3 From 61440db61fe4945ad9f7b32b4d6a22b17174aa1f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:57:55 +0900 Subject: [PATCH] libata: implement ATA printk helpers Implement ata_{port|dev}_printk() which prefixes the message with proper identification string. This change is necessary for later PM support because devices and links should be identified differently depending on how they are attached. This also helps unifying device id strings. Currently, there are two forms in use (P is the port number D device number) - 'ataP(D):', and 'ataP: dev D '. These macros also make it harder to forget proper ID string (e.g. printing only port number when a device is in question). Debug message handling can be integrated into these printk macros by passing debug type and level via @lv. Signed-off-by: Tejun Heo --- include/linux/libata.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/include/linux/libata.h b/include/linux/libata.h index 8154b366bbd..91e10e6b756 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -650,7 +650,18 @@ extern void ata_eng_timeout(struct ata_port *ap); extern void ata_eh_qc_complete(struct ata_queued_cmd *qc); extern void ata_eh_qc_retry(struct ata_queued_cmd *qc); +/* + * printk helpers + */ +#define ata_port_printk(ap, lv, fmt, args...) \ + printk(lv"ata%u: "fmt, (ap)->id , ##args) + +#define ata_dev_printk(dev, lv, fmt, args...) \ + printk(lv"ata%u.%02u: "fmt, (dev)->ap->id, (dev)->devno , ##args) +/* + * qc helpers + */ static inline int ata_sg_is_last(struct scatterlist *sg, struct ata_queued_cmd *qc) { -- cgit v1.2.3 From f15a1dafed22d5037e0feea7528e1eeb28a1a7a3 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:57:56 +0900 Subject: [PATCH] libata: use ATA printk helpers Use ATA printk helpers. Signed-off-by: Tejun Heo --- drivers/scsi/ahci.c | 8 +- drivers/scsi/ata_piix.c | 4 +- drivers/scsi/libata-core.c | 199 ++++++++++++++++++++------------------------ drivers/scsi/libata-eh.c | 5 +- drivers/scsi/libata-scsi.c | 9 +- drivers/scsi/sata_mv.c | 8 +- drivers/scsi/sata_promise.c | 7 +- drivers/scsi/sata_sil.c | 8 +- drivers/scsi/sata_sil24.c | 6 +- drivers/scsi/sata_sx4.c | 7 +- 10 files changed, 124 insertions(+), 137 deletions(-) diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index f6e4c8ea74e..a4fb8d0a6c0 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -655,8 +655,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class) fail_restart: ahci_start_engine(ap); fail: - printk(KERN_ERR "ata%u: softreset failed (%s)\n", - ap->id, reason); + ata_port_printk(ap, KERN_ERR, "softreset failed (%s)\n", reason); return rc; } @@ -798,9 +797,8 @@ static void ahci_restart_port(struct ata_port *ap, u32 irq_stat) if ((ap->device[0].class != ATA_DEV_ATAPI) || ((irq_stat & PORT_IRQ_TF_ERR) == 0)) - printk(KERN_WARNING "ata%u: port reset, " + ata_port_printk(ap, KERN_WARNING, "port reset, " "p_is %x is %x pis %x cmd %x tf %x ss %x se %x\n", - ap->id, irq_stat, readl(mmio + HOST_IRQ_STAT), readl(port_mmio + PORT_IRQ_STAT), @@ -840,7 +838,7 @@ static void ahci_eng_timeout(struct ata_port *ap) struct ata_queued_cmd *qc; unsigned long flags; - printk(KERN_WARNING "ata%u: handling error/timeout\n", ap->id); + ata_port_printk(ap, KERN_WARNING, "handling error/timeout\n"); spin_lock_irqsave(&host_set->lock, flags); diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index 62dabf74188..af1d46e3610 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -484,7 +484,7 @@ static int piix_pata_probe_reset(struct ata_port *ap, unsigned int *classes) struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->hard_port_no])) { - printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); + ata_port_printk(ap, KERN_INFO, "port disabled. ignoring.\n"); return 0; } @@ -565,7 +565,7 @@ static unsigned int piix_sata_probe (struct ata_port *ap) static int piix_sata_probe_reset(struct ata_port *ap, unsigned int *classes) { if (!piix_sata_probe(ap)) { - printk(KERN_INFO "ata%u: SATA port has no device.\n", ap->id); + ata_port_printk(ap, KERN_INFO, "SATA port has no device.\n"); return 0; } diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 4ced962db81..9a97ebd5920 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -412,8 +412,7 @@ static const char *sata_spd_string(unsigned int spd) void ata_dev_disable(struct ata_device *dev) { if (ata_dev_enabled(dev)) { - printk(KERN_WARNING "ata%u: dev %u disabled\n", - dev->ap->id, dev->devno); + ata_dev_printk(dev, KERN_WARNING, "disabled\n"); dev->class++; } } @@ -1021,8 +1020,9 @@ unsigned ata_exec_internal(struct ata_device *dev, if (qc->flags & ATA_QCFLAG_ACTIVE) { qc->err_mask = AC_ERR_TIMEOUT; ata_qc_complete(qc); - printk(KERN_WARNING "ata%u: qc timeout (cmd 0x%x)\n", - ap->id, command); + + ata_dev_printk(dev, KERN_WARNING, + "qc timeout (cmd 0x%x)\n", command); } spin_unlock_irqrestore(&ap->host_set->lock, flags); @@ -1187,8 +1187,8 @@ static int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, return 0; err_out: - printk(KERN_WARNING "ata%u: dev %u failed to IDENTIFY (%s)\n", - ap->id, dev->devno, reason); + ata_dev_printk(dev, KERN_WARNING, "failed to IDENTIFY " + "(%s, err_mask=0x%x)\n", reason, err_mask); return rc; } @@ -1228,10 +1228,10 @@ static int ata_dev_configure(struct ata_device *dev, int print_info) /* print device capabilities */ if (print_info) - printk(KERN_DEBUG "ata%u: dev %u cfg 49:%04x 82:%04x 83:%04x " - "84:%04x 85:%04x 86:%04x 87:%04x 88:%04x\n", - ap->id, dev->devno, id[49], id[82], id[83], - id[84], id[85], id[86], id[87], id[88]); + ata_dev_printk(dev, KERN_DEBUG, "cfg 49:%04x 82:%04x 83:%04x " + "84:%04x 85:%04x 86:%04x 87:%04x 88:%04x\n", + id[49], id[82], id[83], id[84], + id[85], id[86], id[87], id[88]); /* initialize to-be-configured parameters */ dev->flags &= ~ATA_DFLAG_CFG_MASK; @@ -1267,13 +1267,12 @@ static int ata_dev_configure(struct ata_device *dev, int print_info) /* print device info to dmesg */ if (print_info) - printk(KERN_INFO "ata%u: dev %u ATA-%d, " - "max %s, %Lu sectors: %s\n", - ap->id, dev->devno, - ata_id_major_version(id), - ata_mode_string(xfer_mask), - (unsigned long long)dev->n_sectors, - lba_desc); + ata_dev_printk(dev, KERN_INFO, "ATA-%d, " + "max %s, %Lu sectors: %s\n", + ata_id_major_version(id), + ata_mode_string(xfer_mask), + (unsigned long long)dev->n_sectors, + lba_desc); } else { /* CHS */ @@ -1291,13 +1290,12 @@ static int ata_dev_configure(struct ata_device *dev, int print_info) /* print device info to dmesg */ if (print_info) - printk(KERN_INFO "ata%u: dev %u ATA-%d, " - "max %s, %Lu sectors: CHS %u/%u/%u\n", - ap->id, dev->devno, - ata_id_major_version(id), - ata_mode_string(xfer_mask), - (unsigned long long)dev->n_sectors, - dev->cylinders, dev->heads, dev->sectors); + ata_dev_printk(dev, KERN_INFO, "ATA-%d, " + "max %s, %Lu sectors: CHS %u/%u/%u\n", + ata_id_major_version(id), + ata_mode_string(xfer_mask), + (unsigned long long)dev->n_sectors, + dev->cylinders, dev->heads, dev->sectors); } dev->cdb_len = 16; @@ -1307,7 +1305,8 @@ static int ata_dev_configure(struct ata_device *dev, int print_info) else if (dev->class == ATA_DEV_ATAPI) { rc = atapi_cdb_len(id); if ((rc < 12) || (rc > ATAPI_CDB_LEN)) { - printk(KERN_WARNING "ata%u: unsupported CDB len\n", ap->id); + ata_dev_printk(dev, KERN_WARNING, + "unsupported CDB len\n"); rc = -EINVAL; goto err_out_nosup; } @@ -1315,8 +1314,8 @@ static int ata_dev_configure(struct ata_device *dev, int print_info) /* print device info to dmesg */ if (print_info) - printk(KERN_INFO "ata%u: dev %u ATAPI, max %s\n", - ap->id, dev->devno, ata_mode_string(xfer_mask)); + ata_dev_printk(dev, KERN_INFO, "ATAPI, max %s\n", + ata_mode_string(xfer_mask)); } ap->host->max_cmd_len = 0; @@ -1328,8 +1327,8 @@ static int ata_dev_configure(struct ata_device *dev, int print_info) /* limit bridge transfers to udma5, 200 sectors */ if (ata_dev_knobble(dev)) { if (print_info) - printk(KERN_INFO "ata%u(%u): applying bridge limits\n", - ap->id, dev->devno); + ata_dev_printk(dev, KERN_INFO, + "applying bridge limits\n"); dev->udma_mask &= ATA_UDMA5; dev->max_sectors = ATA_MAX_SECTORS; } @@ -1382,7 +1381,8 @@ static int ata_bus_probe(struct ata_port *ap) if (ap->ops->probe_reset) { rc = ap->ops->probe_reset(ap, classes); if (rc) { - printk("ata%u: reset failed (errno=%d)\n", ap->id, rc); + ata_port_printk(ap, KERN_ERR, + "reset failed (errno=%d)\n", rc); return rc; } } else { @@ -1495,13 +1495,13 @@ static void sata_print_link_status(struct ata_port *ap) if (ata_port_online(ap)) { tmp = (sstatus >> 4) & 0xf; - printk(KERN_INFO - "ata%u: SATA link up %s (SStatus %X SControl %X)\n", - ap->id, sata_spd_string(tmp), sstatus, scontrol); + ata_port_printk(ap, KERN_INFO, + "SATA link up %s (SStatus %X SControl %X)\n", + sata_spd_string(tmp), sstatus, scontrol); } else { - printk(KERN_INFO - "ata%u: SATA link down (SStatus %X SControl %X)\n", - ap->id, sstatus, scontrol); + ata_port_printk(ap, KERN_INFO, + "SATA link down (SStatus %X SControl %X)\n", + sstatus, scontrol); } } @@ -1655,8 +1655,8 @@ int sata_down_spd_limit(struct ata_port *ap) ap->sata_spd_limit = mask; - printk(KERN_WARNING "ata%u: limiting SATA link speed to %s\n", - ap->id, sata_spd_string(fls(mask))); + ata_port_printk(ap, KERN_WARNING, "limiting SATA link speed to %s\n", + sata_spd_string(fls(mask))); return 0; } @@ -1896,7 +1896,6 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed, */ int ata_down_xfermask_limit(struct ata_device *dev, int force_pio0) { - struct ata_port *ap = dev->ap; unsigned long xfer_mask; int highbit; @@ -1919,8 +1918,8 @@ int ata_down_xfermask_limit(struct ata_device *dev, int force_pio0) ata_unpack_xfermask(xfer_mask, &dev->pio_mask, &dev->mwdma_mask, &dev->udma_mask); - printk(KERN_WARNING "ata%u: dev %u limiting speed to %s\n", - ap->id, dev->devno, ata_mode_string(xfer_mask)); + ata_dev_printk(dev, KERN_WARNING, "limiting speed to %s\n", + ata_mode_string(xfer_mask)); return 0; @@ -1930,7 +1929,6 @@ int ata_down_xfermask_limit(struct ata_device *dev, int force_pio0) static int ata_dev_set_mode(struct ata_device *dev) { - struct ata_port *ap = dev->ap; unsigned int err_mask; int rc; @@ -1940,9 +1938,8 @@ static int ata_dev_set_mode(struct ata_device *dev) err_mask = ata_dev_set_xfermode(dev); if (err_mask) { - printk(KERN_ERR - "ata%u: failed to set xfermode (err_mask=0x%x)\n", - ap->id, err_mask); + ata_dev_printk(dev, KERN_ERR, "failed to set xfermode " + "(err_mask=0x%x)\n", err_mask); return -EIO; } @@ -1953,9 +1950,8 @@ static int ata_dev_set_mode(struct ata_device *dev) DPRINTK("xfer_shift=%u, xfer_mode=0x%x\n", dev->xfer_shift, (int)dev->xfer_mode); - printk(KERN_INFO "ata%u: dev %u configured for %s\n", - ap->id, dev->devno, - ata_mode_string(ata_xfer_mode2mask(dev->xfer_mode))); + ata_dev_printk(dev, KERN_INFO, "configured for %s\n", + ata_mode_string(ata_xfer_mode2mask(dev->xfer_mode))); return 0; } @@ -2023,8 +2019,7 @@ int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev) continue; if (!dev->pio_mode) { - printk(KERN_WARNING "ata%u: dev %u no PIO support\n", - ap->id, dev->devno); + ata_dev_printk(dev, KERN_WARNING, "no PIO support\n"); rc = -EINVAL; goto out; } @@ -2123,8 +2118,8 @@ unsigned int ata_busy_sleep (struct ata_port *ap, } if (status & ATA_BUSY) - printk(KERN_WARNING "ata%u is slow to respond, " - "please be patient\n", ap->id); + ata_port_printk(ap, KERN_WARNING, + "port is slow to respond, please be patient\n"); timeout = timer_start + tmout; while ((status & ATA_BUSY) && (time_before(jiffies, timeout))) { @@ -2133,8 +2128,8 @@ unsigned int ata_busy_sleep (struct ata_port *ap, } if (status & ATA_BUSY) { - printk(KERN_ERR "ata%u failed to respond (%lu secs)\n", - ap->id, tmout / HZ); + ata_port_printk(ap, KERN_ERR, "port failed to respond " + "(%lu secs)\n", tmout / HZ); return 1; } @@ -2227,7 +2222,7 @@ static unsigned int ata_bus_softreset(struct ata_port *ap, * pulldown resistor. */ if (ata_check_status(ap) == 0xFF) { - printk(KERN_ERR "ata%u: SRST failed (status 0xFF)\n", ap->id); + ata_port_printk(ap, KERN_ERR, "SRST failed (status 0xFF)\n"); return AC_ERR_OTHER; } @@ -2321,7 +2316,7 @@ void ata_bus_reset(struct ata_port *ap) return; err_out: - printk(KERN_ERR "ata%u: disabling port\n", ap->id); + ata_port_printk(ap, KERN_ERR, "disabling port\n"); ap->ops->port_disable(ap); DPRINTK("EXIT\n"); @@ -2424,8 +2419,8 @@ int ata_std_softreset(struct ata_port *ap, unsigned int *classes) DPRINTK("about to softreset, devmask=%x\n", devmask); err_mask = ata_bus_softreset(ap, devmask); if (err_mask) { - printk(KERN_ERR "ata%u: SRST failed (err_mask=0x%x)\n", - ap->id, err_mask); + ata_port_printk(ap, KERN_ERR, "SRST failed (err_mask=0x%x)\n", + err_mask); return -EIO; } @@ -2503,8 +2498,8 @@ int sata_std_hardreset(struct ata_port *ap, unsigned int *class) } if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) { - printk(KERN_ERR - "ata%u: COMRESET failed (device not ready)\n", ap->id); + ata_port_printk(ap, KERN_ERR, + "COMRESET failed (device not ready)\n"); return -EIO; } @@ -2662,8 +2657,8 @@ int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, rc = ata_do_reset(ap, softreset, classes); if (rc == 0 && classes[0] != ATA_DEV_UNKNOWN) goto done; - printk(KERN_INFO "ata%u: softreset failed, will try " - "hardreset in 5 secs\n", ap->id); + ata_port_printk(ap, KERN_INFO, "softreset failed, " + "will try hardreset in 5 secs\n"); ssleep(5); } @@ -2681,15 +2676,15 @@ int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, if (sata_down_spd_limit(ap)) goto done; - printk(KERN_INFO "ata%u: hardreset failed, will retry " - "in 5 secs\n", ap->id); + ata_port_printk(ap, KERN_INFO, "hardreset failed, " + "will retry in 5 secs\n"); ssleep(5); } if (softreset) { - printk(KERN_INFO "ata%u: hardreset succeeded without " - "classification, will retry softreset in 5 secs\n", - ap->id); + ata_port_printk(ap, KERN_INFO, + "hardreset succeeded without classification, " + "will retry softreset in 5 secs\n"); ssleep(5); rc = ata_do_reset(ap, softreset, classes); @@ -2724,15 +2719,13 @@ int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, static int ata_dev_same_device(struct ata_device *dev, unsigned int new_class, const u16 *new_id) { - struct ata_port *ap = dev->ap; const u16 *old_id = dev->id; unsigned char model[2][41], serial[2][21]; u64 new_n_sectors; if (dev->class != new_class) { - printk(KERN_INFO - "ata%u: dev %u class mismatch %d != %d\n", - ap->id, dev->devno, dev->class, new_class); + ata_dev_printk(dev, KERN_INFO, "class mismatch %d != %d\n", + dev->class, new_class); return 0; } @@ -2743,24 +2736,22 @@ static int ata_dev_same_device(struct ata_device *dev, unsigned int new_class, new_n_sectors = ata_id_n_sectors(new_id); if (strcmp(model[0], model[1])) { - printk(KERN_INFO - "ata%u: dev %u model number mismatch '%s' != '%s'\n", - ap->id, dev->devno, model[0], model[1]); + ata_dev_printk(dev, KERN_INFO, "model number mismatch " + "'%s' != '%s'\n", model[0], model[1]); return 0; } if (strcmp(serial[0], serial[1])) { - printk(KERN_INFO - "ata%u: dev %u serial number mismatch '%s' != '%s'\n", - ap->id, dev->devno, serial[0], serial[1]); + ata_dev_printk(dev, KERN_INFO, "serial number mismatch " + "'%s' != '%s'\n", serial[0], serial[1]); return 0; } if (dev->class == ATA_DEV_ATA && dev->n_sectors != new_n_sectors) { - printk(KERN_INFO - "ata%u: dev %u n_sectors mismatch %llu != %llu\n", - ap->id, dev->devno, (unsigned long long)dev->n_sectors, - (unsigned long long)new_n_sectors); + ata_dev_printk(dev, KERN_INFO, "n_sectors mismatch " + "%llu != %llu\n", + (unsigned long long)dev->n_sectors, + (unsigned long long)new_n_sectors); return 0; } @@ -2783,9 +2774,8 @@ static int ata_dev_same_device(struct ata_device *dev, unsigned int new_class, */ int ata_dev_revalidate(struct ata_device *dev, int post_reset) { - struct ata_port *ap = dev->ap; unsigned int class = dev->class; - u16 *id = (void *)ap->sector_buf; + u16 *id = (void *)dev->ap->sector_buf; int rc; if (!ata_dev_enabled(dev)) { @@ -2812,8 +2802,7 @@ int ata_dev_revalidate(struct ata_device *dev, int post_reset) return 0; fail: - printk(KERN_ERR "ata%u: dev %u revalidation failed (errno=%d)\n", - ap->id, dev->devno, rc); + ata_dev_printk(dev, KERN_ERR, "revalidation failed (errno=%d)\n", rc); return rc; } @@ -2941,8 +2930,8 @@ static void ata_dev_xfermask(struct ata_device *dev) } if (ata_dma_blacklisted(dev)) - printk(KERN_WARNING "ata%u: dev %u is on DMA blacklist, " - "disabling DMA\n", ap->id, dev->devno); + ata_dev_printk(dev, KERN_WARNING, + "device is on DMA blacklist, disabling DMA\n"); if (hs->flags & ATA_HOST_SIMPLEX) { if (hs->simplex_claimed) @@ -3733,8 +3722,8 @@ next_sg: unsigned int i; if (words) /* warning if bytes > 1 */ - printk(KERN_WARNING "ata%u: %u bytes trailing data\n", - ap->id, bytes); + ata_dev_printk(qc->dev, KERN_WARNING, + "%u bytes trailing data\n", bytes); for (i = 0; i < words; i++) ata_data_xfer(ap, (unsigned char*)pad_buf, 2, do_write); @@ -3817,8 +3806,7 @@ static void atapi_pio_bytes(struct ata_queued_cmd *qc) return; err_out: - printk(KERN_INFO "ata%u: dev %u: ATAPI check failed\n", - ap->id, dev->devno); + ata_dev_printk(dev, KERN_INFO, "ATAPI check failed\n"); qc->err_mask |= AC_ERR_HSM; ap->hsm_task_state = HSM_ST_ERR; } @@ -3887,8 +3875,7 @@ static void ata_pio_error(struct ata_queued_cmd *qc) struct ata_port *ap = qc->ap; if (qc->tf.command != ATA_CMD_PACKET) - printk(KERN_WARNING "ata%u: dev %u PIO error\n", - ap->id, qc->dev->devno); + ata_dev_printk(qc->dev, KERN_WARNING, "PIO error\n"); /* make sure qc->err_mask is available to * know what's wrong and recover @@ -4314,7 +4301,7 @@ idle_irq: #ifdef ATA_IRQ_TRAP if ((ap->stats.idle_irq % 1000) == 0) { ata_irq_ack(ap, 0); /* debug trap */ - printk(KERN_WARNING "ata%d: irq trap\n", ap->id); + ata_port_printk(ap, KERN_WARNING, "irq trap\n"); return 1; } #endif @@ -4522,8 +4509,8 @@ static int ata_do_simple_cmd(struct ata_device *dev, u8 cmd) err = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0); if (err) - printk(KERN_ERR "%s: ata command failed: %d\n", - __FUNCTION__, err); + ata_dev_printk(dev, KERN_ERR, "%s: ata command failed: %d\n", + __FUNCTION__, err); return err; } @@ -4863,15 +4850,14 @@ int ata_device_add(const struct ata_probe_ent *ent) (ap->pio_mask << ATA_SHIFT_PIO); /* print per-port info to dmesg */ - printk(KERN_INFO "ata%u: %cATA max %s cmd 0x%lX ctl 0x%lX " - "bmdma 0x%lX irq %lu\n", - ap->id, - ap->flags & ATA_FLAG_SATA ? 'S' : 'P', - ata_mode_string(xfer_mode_mask), - ap->ioaddr.cmd_addr, - ap->ioaddr.ctl_addr, - ap->ioaddr.bmdma_addr, - ent->irq); + ata_port_printk(ap, KERN_INFO, "%cATA max %s cmd 0x%lX " + "ctl 0x%lX bmdma 0x%lX irq %lu\n", + ap->flags & ATA_FLAG_SATA ? 'S' : 'P', + ata_mode_string(xfer_mode_mask), + ap->ioaddr.cmd_addr, + ap->ioaddr.ctl_addr, + ap->ioaddr.bmdma_addr, + ent->irq); ata_chk_status(ap); host_set->ops->irq_clear(ap); @@ -4909,8 +4895,7 @@ int ata_device_add(const struct ata_probe_ent *ent) rc = scsi_add_host(ap->host, dev); if (rc) { - printk(KERN_ERR "ata%u: scsi_add_host failed\n", - ap->id); + ata_port_printk(ap, KERN_ERR, "scsi_add_host failed\n"); /* FIXME: do something useful here */ /* FIXME: handle unconditional calls to * scsi_scan_host and ata_host_remove, below, diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c index c31b13fd530..959a1cdffac 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/scsi/libata-eh.c @@ -167,8 +167,9 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc) /* ack bmdma irq events */ ap->ops->irq_clear(ap); - printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x host_stat 0x%x\n", - ap->id, qc->tf.command, drv_stat, host_stat); + ata_dev_printk(qc->dev, KERN_ERR, "command 0x%x timeout, " + "stat 0x%x host_stat 0x%x\n", + qc->tf.command, drv_stat, host_stat); /* complete taskfile transaction */ qc->err_mask |= ac_err_mask(drv_stat); diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index fcbf64e741b..a9b4083a4f6 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -1261,8 +1261,8 @@ static void ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cmd, if (cmd->sc_data_direction == DMA_FROM_DEVICE || cmd->sc_data_direction == DMA_TO_DEVICE) { if (unlikely(cmd->request_bufflen < 1)) { - printk(KERN_WARNING "ata%u(%u): WARNING: zero len r/w req\n", - dev->ap->id, dev->devno); + ata_dev_printk(dev, KERN_WARNING, + "WARNING: zero len r/w req\n"); goto err_did; } @@ -2200,8 +2200,9 @@ ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev) if (!atapi_enabled || (ap->flags & ATA_FLAG_NO_ATAPI)) { if (unlikely(dev->class == ATA_DEV_ATAPI)) { - printk(KERN_WARNING "ata%u(%u): WARNING: ATAPI is %s, device ignored.\n", - ap->id, dev->devno, atapi_enabled ? "not supported with this driver" : "disabled"); + ata_dev_printk(dev, KERN_WARNING, + "WARNING: ATAPI is %s, device ignored.\n", + atapi_enabled ? "not supported with this driver" : "disabled"); return NULL; } } diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index 748569b615f..e8d00f0efdf 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -680,7 +680,7 @@ static void mv_stop_dma(struct ata_port *ap) } if (EDMA_EN & reg) { - printk(KERN_ERR "ata%u: Unable to stop eDMA\n", ap->id); + ata_port_printk(ap, KERN_ERR, "Unable to stop eDMA\n"); /* FIXME: Consider doing a reset here to recover */ } } @@ -1964,8 +1964,8 @@ comreset_retry: ata_port_probe(ap); } else { sata_scr_read(ap, SCR_STATUS, &sstatus); - printk(KERN_INFO "ata%u: no device found (phy stat %08x)\n", - ap->id, sstatus); + ata_port_printk(ap, KERN_INFO, + "no device found (phy stat %08x)\n", sstatus); ata_port_disable(ap); return; } @@ -2023,7 +2023,7 @@ static void mv_eng_timeout(struct ata_port *ap) { struct ata_queued_cmd *qc; - printk(KERN_ERR "ata%u: Entering mv_eng_timeout\n",ap->id); + ata_port_printk(ap, KERN_ERR, "Entering mv_eng_timeout\n"); DPRINTK("All regs @ start of eng_timeout\n"); mv_dump_all_regs(ap->host_set->mmio_base, ap->port_no, to_pci_dev(ap->host_set->dev)); diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index ddbc0c6dd9f..e9d61bc2b24 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c @@ -435,7 +435,7 @@ static void pdc_eng_timeout(struct ata_port *ap) switch (qc->tf.protocol) { case ATA_PROT_DMA: case ATA_PROT_NODATA: - printk(KERN_ERR "ata%u: command timeout\n", ap->id); + ata_port_printk(ap, KERN_ERR, "command timeout\n"); drv_stat = ata_wait_idle(ap); qc->err_mask |= __ac_err_mask(drv_stat); break; @@ -443,8 +443,9 @@ static void pdc_eng_timeout(struct ata_port *ap) default: drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); - printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n", - ap->id, qc->tf.command, drv_stat); + ata_port_printk(ap, KERN_ERR, + "unknown timeout, cmd 0x%x stat 0x%x\n", + qc->tf.command, drv_stat); qc->err_mask |= ac_err_mask(drv_stat); break; diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index c9333577330..bfcece18a7c 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -360,16 +360,16 @@ static void sil_dev_config(struct ata_port *ap, struct ata_device *dev) if (slow_down || ((ap->flags & SIL_FLAG_MOD15WRITE) && (quirks & SIL_QUIRK_MOD15WRITE))) { - printk(KERN_INFO "ata%u(%u): applying Seagate errata fix (mod15write workaround)\n", - ap->id, dev->devno); + ata_dev_printk(dev, KERN_INFO, "applying Seagate errata fix " + "(mod15write workaround)\n"); dev->max_sectors = 15; return; } /* limit to udma5 */ if (quirks & SIL_QUIRK_UDMA5MAX) { - printk(KERN_INFO "ata%u(%u): applying Maxtor errata fix %s\n", - ap->id, dev->devno, model_num); + ata_dev_printk(dev, KERN_INFO, + "applying Maxtor errata fix %s\n", model_num); dev->udma_mask &= ATA_UDMA5; return; } diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index bedc787dafd..ff96724b1e3 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -516,7 +516,7 @@ static int sil24_softreset(struct ata_port *ap, unsigned int *class) return 0; err: - printk(KERN_ERR "ata%u: softreset failed (%s)\n", ap->id, reason); + ata_port_printk(ap, KERN_ERR, "softreset failed (%s)\n", reason); return -EIO; } @@ -561,7 +561,7 @@ static int sil24_hardreset(struct ata_port *ap, unsigned int *class) return 0; err: - printk(KERN_ERR "ata%u: hardreset failed (%s)\n", ap->id, reason); + ata_port_printk(ap, KERN_ERR, "hardreset failed (%s)\n", reason); return -EIO; } @@ -721,7 +721,7 @@ static void sil24_eng_timeout(struct ata_port *ap) qc = ata_qc_from_tag(ap, ap->active_tag); - printk(KERN_ERR "ata%u: command timeout\n", ap->id); + ata_port_printk(ap, KERN_ERR, "command timeout\n"); qc->err_mask |= AC_ERR_TIMEOUT; ata_eh_qc_complete(qc); diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c index a669d058988..96d7b73f5fd 100644 --- a/drivers/scsi/sata_sx4.c +++ b/drivers/scsi/sata_sx4.c @@ -868,15 +868,16 @@ static void pdc_eng_timeout(struct ata_port *ap) switch (qc->tf.protocol) { case ATA_PROT_DMA: case ATA_PROT_NODATA: - printk(KERN_ERR "ata%u: command timeout\n", ap->id); + ata_port_printk(ap, KERN_ERR, "command timeout\n"); qc->err_mask |= __ac_err_mask(ata_wait_idle(ap)); break; default: drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); - printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n", - ap->id, qc->tf.command, drv_stat); + ata_port_printk(ap, KERN_ERR, + "unknown timeout, cmd 0x%x stat 0x%x\n", + qc->tf.command, drv_stat); qc->err_mask |= ac_err_mask(drv_stat); break; -- cgit v1.2.3 From 9ec957f2002bd2994be659bbc0ec28397fa251ee Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:57:58 +0900 Subject: [PATCH] libata-eh-fw: add flags and operations for new EH Add ATA_FLAG_EH_{PENDING|FROZEN}, ATA_ATA_QCFLAG_{FAILED|SENSE_VALID} and ops->freeze, thaw, error_handler, post_internal_cmd() for new EH. Signed-off-by: Tejun Heo --- include/linux/libata.h | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/include/linux/libata.h b/include/linux/libata.h index 91e10e6b756..e5d6d7f8e6d 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -146,13 +146,16 @@ enum { ATA_FLAG_PIO_LBA48 = (1 << 8), /* Host DMA engine is LBA28 only */ ATA_FLAG_IRQ_MASK = (1 << 9), /* Mask IRQ in PIO xfers */ - ATA_FLAG_NOINTR = (1 << 16), /* FIXME: Remove this once + ATA_FLAG_NOINTR = (1 << 13), /* FIXME: Remove this once * proper HSM is in place. */ - ATA_FLAG_DEBUGMSG = (1 << 17), - ATA_FLAG_FLUSH_PORT_TASK = (1 << 18), /* flush port task */ + ATA_FLAG_DEBUGMSG = (1 << 14), + ATA_FLAG_FLUSH_PORT_TASK = (1 << 15), /* flush port task */ - ATA_FLAG_DISABLED = (1 << 19), /* port is disabled, ignore it */ - ATA_FLAG_SUSPENDED = (1 << 20), /* port is suspended */ + ATA_FLAG_EH_PENDING = (1 << 16), /* EH pending */ + ATA_FLAG_FROZEN = (1 << 17), /* port is frozen */ + + ATA_FLAG_DISABLED = (1 << 22), /* port is disabled, ignore it */ + ATA_FLAG_SUSPENDED = (1 << 23), /* port is suspended (power) */ /* bits 24:31 of ap->flags are reserved for LLDD specific flags */ @@ -164,7 +167,9 @@ enum { ATA_QCFLAG_IO = (1 << 3), /* standard IO command */ ATA_QCFLAG_RESULT_TF = (1 << 4), /* result TF requested */ - ATA_QCFLAG_EH_SCHEDULED = (1 << 16), /* EH scheduled */ + ATA_QCFLAG_FAILED = (1 << 16), /* cmd failed and is owned by EH */ + ATA_QCFLAG_SENSE_VALID = (1 << 17), /* sense data valid */ + ATA_QCFLAG_EH_SCHEDULED = (1 << 18), /* EH scheduled (obsolete) */ /* host set flags */ ATA_HOST_SIMPLEX = (1 << 0), /* Host is simplex, one DMA channel per host_set only */ @@ -463,7 +468,15 @@ struct ata_port_operations { void (*qc_prep) (struct ata_queued_cmd *qc); unsigned int (*qc_issue) (struct ata_queued_cmd *qc); - void (*eng_timeout) (struct ata_port *ap); + /* Error handlers. ->error_handler overrides ->eng_timeout and + * indicates that new-style EH is in place. + */ + void (*eng_timeout) (struct ata_port *ap); /* obsolete */ + + void (*freeze) (struct ata_port *ap); + void (*thaw) (struct ata_port *ap); + void (*error_handler) (struct ata_port *ap); + void (*post_internal_cmd) (struct ata_queued_cmd *qc); irqreturn_t (*irq_handler)(int, void *, struct pt_regs *); void (*irq_clear) (struct ata_port *); -- cgit v1.2.3 From dc2b3515868a254b3d653d77844bff93c5d4c095 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:58:00 +0900 Subject: [PATCH] libata-eh-fw: clear SError in ata_std_postreset() Clear SError in ata_std_postreset(). This is to clear SError bits which get set during reset. Signed-off-by: Tejun Heo --- drivers/scsi/libata-core.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 9a97ebd5920..de2cd61a264 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2528,11 +2528,17 @@ int sata_std_hardreset(struct ata_port *ap, unsigned int *class) */ void ata_std_postreset(struct ata_port *ap, unsigned int *classes) { + u32 serror; + DPRINTK("ENTER\n"); /* print link status */ sata_print_link_status(ap); + /* clear SError */ + if (sata_scr_read(ap, SCR_ERROR, &serror) == 0) + sata_scr_write(ap, SCR_ERROR, serror); + /* re-enable interrupts */ if (ap->ioaddr.ctl_addr) /* FIXME: hack. create a hook instead */ ata_irq_on(ap); -- cgit v1.2.3 From 2ab7db1ff1d64a2ba389d0692d532f42a15f1f72 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:58:02 +0900 Subject: [PATCH] libata-eh-fw: use special reserved tag and qc for internal commands New EH may issue internal commands to recover from error while failed qc's are still hanging around. To allow such usage, reserve tag ATA_MAX_QUEUE-1 for internal command. This also makes it easy to tell whether a qc is for internal command or not. ata_tag_internal() test implements this test. To avoid breaking existing drivers, ata_exec_internal() uses ATA_TAG_INTERNAL only for drivers which implement ->error_handler. For drivers using old EH, tag 0 is used. Note that this makes ata_tag_internal() test valid only when ->error_handler is implemented. This is okay as drivers on old EH should not and does not have any reason to use ata_tag_internal(). Signed-off-by: Tejun Heo --- drivers/scsi/libata-core.c | 32 +++++++++++++++++++++++++++++--- include/linux/libata.h | 9 ++++++++- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index de2cd61a264..966abb5f423 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -980,15 +980,39 @@ unsigned ata_exec_internal(struct ata_device *dev, struct ata_port *ap = dev->ap; u8 command = tf->command; struct ata_queued_cmd *qc; + unsigned int tag, preempted_tag; DECLARE_COMPLETION(wait); unsigned long flags; unsigned int err_mask; spin_lock_irqsave(&ap->host_set->lock, flags); - qc = ata_qc_new_init(dev); - BUG_ON(qc == NULL); + /* initialize internal qc */ + /* XXX: Tag 0 is used for drivers with legacy EH as some + * drivers choke if any other tag is given. This breaks + * ata_tag_internal() test for those drivers. Don't use new + * EH stuff without converting to it. + */ + if (ap->ops->error_handler) + tag = ATA_TAG_INTERNAL; + else + tag = 0; + + if (test_and_set_bit(tag, &ap->qactive)) + BUG(); + qc = ata_qc_from_tag(ap, tag); + + qc->tag = tag; + qc->scsicmd = NULL; + qc->ap = ap; + qc->dev = dev; + ata_qc_reinit(qc); + + preempted_tag = ap->active_tag; + ap->active_tag = ATA_TAG_POISON; + + /* prepare & issue qc */ qc->tf = *tf; if (cdb) memcpy(qc->cdb, cdb, ATAPI_CDB_LEN); @@ -1035,6 +1059,7 @@ unsigned ata_exec_internal(struct ata_device *dev, err_mask = qc->err_mask; ata_qc_free(qc); + ap->active_tag = preempted_tag; /* XXX - Some LLDDs (sata_mv) disable port on command failure. * Until those drivers are fixed, we detect the condition @@ -4014,7 +4039,8 @@ static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap) struct ata_queued_cmd *qc = NULL; unsigned int i; - for (i = 0; i < ATA_MAX_QUEUE; i++) + /* the last tag is reserved for internal command. */ + for (i = 0; i < ATA_MAX_QUEUE - 1; i++) if (!test_and_set_bit(i, &ap->qactive)) { qc = ata_qc_from_tag(ap, i); break; diff --git a/include/linux/libata.h b/include/linux/libata.h index e5d6d7f8e6d..5a403e434ff 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -108,7 +108,9 @@ enum { LIBATA_MAX_PRD = ATA_MAX_PRD / 2, ATA_MAX_PORTS = 8, ATA_DEF_QUEUE = 1, - ATA_MAX_QUEUE = 1, + /* tag ATA_MAX_QUEUE - 1 is reserved for internal commands */ + ATA_MAX_QUEUE = 2, + ATA_TAG_INTERNAL = ATA_MAX_QUEUE - 1, ATA_MAX_SECTORS = 200, /* FIXME */ ATA_MAX_BUS = 2, ATA_DEF_BUSY_WAIT = 10000, @@ -717,6 +719,11 @@ static inline unsigned int ata_tag_valid(unsigned int tag) return (tag < ATA_MAX_QUEUE) ? 1 : 0; } +static inline unsigned int ata_tag_internal(unsigned int tag) +{ + return tag == ATA_MAX_QUEUE - 1; +} + static inline unsigned int ata_class_enabled(unsigned int class) { return class == ATA_DEV_ATA || class == ATA_DEV_ATAPI; -- cgit v1.2.3 From f69499f42caf74194df678c9c293f2ee0fe90bc3 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:58:03 +0900 Subject: [PATCH] libata-eh-fw: update ata_qc_from_tag() to enforce normal/EH qc ownership New EH framework has clear distinction about who owns a qc. Every qc starts owned by normal execution path - PIO, interrupt or whatever. When an exception condition occurs which affects the qc, the qc gets scheduled for EH. Note that some events (say, link lost and regained, command timeout) may schedule qc's which are not directly related but could have been affected for EH too. Scheduling for EH is atomic w.r.t. ap->host_set->lock and once schedule for EH, normal execution path is not allowed to access the qc in whatever way. (PIO synchronization acts a bit different and will be dealt with later) This patch make ata_qc_from_tag() check whether a qc is active and owned by normal path before returning it. If conditions don't match, NULL is returned and thus access to the qc is denied. __ata_qc_from_tag() is the original ata_qc_from_tag() and is used by libata core/EH layers to access inactive/failed qc's. This change is applied only if the associated LLDD implements new EH as indicated by non-NULL ->error_handler Signed-off-by: Tejun Heo --- drivers/scsi/libata-core.c | 4 ++-- include/linux/libata.h | 19 +++++++++++++++++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 966abb5f423..1c34c1427aa 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1001,7 +1001,7 @@ unsigned ata_exec_internal(struct ata_device *dev, if (test_and_set_bit(tag, &ap->qactive)) BUG(); - qc = ata_qc_from_tag(ap, tag); + qc = __ata_qc_from_tag(ap, tag); qc->tag = tag; qc->scsicmd = NULL; @@ -4042,7 +4042,7 @@ static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap) /* the last tag is reserved for internal command. */ for (i = 0; i < ATA_MAX_QUEUE - 1; i++) if (!test_and_set_bit(i, &ap->qactive)) { - qc = ata_qc_from_tag(ap, i); + qc = __ata_qc_from_tag(ap, i); break; } diff --git a/include/linux/libata.h b/include/linux/libata.h index 5a403e434ff..bfcefdca061 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -832,14 +832,29 @@ static inline void ata_qc_set_polling(struct ata_queued_cmd *qc) qc->tf.ctl |= ATA_NIEN; } -static inline struct ata_queued_cmd *ata_qc_from_tag (struct ata_port *ap, - unsigned int tag) +static inline struct ata_queued_cmd *__ata_qc_from_tag(struct ata_port *ap, + unsigned int tag) { if (likely(ata_tag_valid(tag))) return &ap->qcmd[tag]; return NULL; } +static inline struct ata_queued_cmd *ata_qc_from_tag(struct ata_port *ap, + unsigned int tag) +{ + struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag); + + if (unlikely(!qc) || !ap->ops->error_handler) + return qc; + + if ((qc->flags & (ATA_QCFLAG_ACTIVE | + ATA_QCFLAG_FAILED)) == ATA_QCFLAG_ACTIVE) + return qc; + + return NULL; +} + static inline void ata_tf_init(struct ata_device *dev, struct ata_taskfile *tf) { memset(tf, 0, sizeof(*tf)); -- cgit v1.2.3 From f686bcb8078ac7505ec88818886c2c72639f4fc5 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:58:05 +0900 Subject: [PATCH] libata-eh-fw: implement new EH scheduling via error completion There are several ways a qc can get schedule for EH in new EH. This patch implements one of them - completing a qc with ATA_QCFLAG_FAILED set or with non-zero qc->err_mask. ALL such qc's are examined by EH. New EH schedules a qc for EH from completion iff ->error_handler is implemented, qc is marked as failed or qc->err_mask is non-zero and the command is not an internal command (internal cmd is handled via ->post_internal_cmd). The EH scheduling itself is performed by asking SCSI midlayer to schedule EH for the specified scmd. For drivers implementing old-EH, nothing changes. As this change makes ata_qc_complete() rather large, it's not inlined anymore and __ata_qc_complete() is exported to other parts of libata for later use. Signed-off-by: Tejun Heo --- drivers/scsi/libata-core.c | 62 +++++++++++++++++++++++++++++++++++++++++++++- drivers/scsi/libata-eh.c | 27 ++++++++++++++++++++ drivers/scsi/libata.h | 2 ++ include/linux/libata.h | 27 +------------------- 4 files changed, 91 insertions(+), 27 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 1c34c1427aa..1f5c3270992 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -4123,6 +4123,66 @@ void __ata_qc_complete(struct ata_queued_cmd *qc) qc->complete_fn(qc); } +/** + * ata_qc_complete - Complete an active ATA command + * @qc: Command to complete + * @err_mask: ATA Status register contents + * + * Indicate to the mid and upper layers that an ATA + * command has completed, with either an ok or not-ok status. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ +void ata_qc_complete(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + + /* XXX: New EH and old EH use different mechanisms to + * synchronize EH with regular execution path. + * + * In new EH, a failed qc is marked with ATA_QCFLAG_FAILED. + * Normal execution path is responsible for not accessing a + * failed qc. libata core enforces the rule by returning NULL + * from ata_qc_from_tag() for failed qcs. + * + * Old EH depends on ata_qc_complete() nullifying completion + * requests if ATA_QCFLAG_EH_SCHEDULED is set. Old EH does + * not synchronize with interrupt handler. Only PIO task is + * taken care of. + */ + if (ap->ops->error_handler) { + WARN_ON(ap->flags & ATA_FLAG_FROZEN); + + if (unlikely(qc->err_mask)) + qc->flags |= ATA_QCFLAG_FAILED; + + if (unlikely(qc->flags & ATA_QCFLAG_FAILED)) { + if (!ata_tag_internal(qc->tag)) { + /* always fill result TF for failed qc */ + ap->ops->tf_read(ap, &qc->result_tf); + ata_qc_schedule_eh(qc); + return; + } + } + + /* read result TF if requested */ + if (qc->flags & ATA_QCFLAG_RESULT_TF) + ap->ops->tf_read(ap, &qc->result_tf); + + __ata_qc_complete(qc); + } else { + if (qc->flags & ATA_QCFLAG_EH_SCHEDULED) + return; + + /* read result TF if failed or requested */ + if (qc->err_mask || qc->flags & ATA_QCFLAG_RESULT_TF) + ap->ops->tf_read(ap, &qc->result_tf); + + __ata_qc_complete(qc); + } +} + static inline int ata_should_dma_map(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; @@ -5245,7 +5305,7 @@ EXPORT_SYMBOL_GPL(ata_device_add); EXPORT_SYMBOL_GPL(ata_host_set_remove); EXPORT_SYMBOL_GPL(ata_sg_init); EXPORT_SYMBOL_GPL(ata_sg_init_one); -EXPORT_SYMBOL_GPL(__ata_qc_complete); +EXPORT_SYMBOL_GPL(ata_qc_complete); EXPORT_SYMBOL_GPL(ata_qc_issue_prot); EXPORT_SYMBOL_GPL(ata_tf_load); EXPORT_SYMBOL_GPL(ata_tf_read); diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c index 959a1cdffac..471846fe4b7 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/scsi/libata-eh.c @@ -210,6 +210,33 @@ void ata_eng_timeout(struct ata_port *ap) DPRINTK("EXIT\n"); } +/** + * ata_qc_schedule_eh - schedule qc for error handling + * @qc: command to schedule error handling for + * + * Schedule error handling for @qc. EH will kick in as soon as + * other commands are drained. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ +void ata_qc_schedule_eh(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + + WARN_ON(!ap->ops->error_handler); + + qc->flags |= ATA_QCFLAG_FAILED; + qc->ap->flags |= ATA_FLAG_EH_PENDING; + + /* The following will fail if timeout has already expired. + * ata_scsi_error() takes care of such scmds on EH entry. + * Note that ATA_QCFLAG_FAILED is unconditionally set after + * this function completes. + */ + scsi_req_abort_cmd(qc->scsicmd); +} + static void ata_eh_scsidone(struct scsi_cmnd *scmd) { /* nada */ diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index c9ff83bbcfa..52622b7f8a9 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -57,6 +57,7 @@ extern int ata_do_reset(struct ata_port *ap, ata_reset_fn_t reset, unsigned int *classes); extern void ata_qc_free(struct ata_queued_cmd *qc); extern void ata_qc_issue(struct ata_queued_cmd *qc); +extern void __ata_qc_complete(struct ata_queued_cmd *qc); extern int ata_check_atapi_dma(struct ata_queued_cmd *qc); extern void ata_dev_select(struct ata_port *ap, unsigned int device, unsigned int wait, unsigned int can_sleep); @@ -101,5 +102,6 @@ extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args, /* libata-eh.c */ extern enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd); extern void ata_scsi_error(struct Scsi_Host *host); +extern void ata_qc_schedule_eh(struct ata_queued_cmd *qc); #endif /* __LIBATA_H__ */ diff --git a/include/linux/libata.h b/include/linux/libata.h index bfcefdca061..6023f324e68 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -605,7 +605,7 @@ extern void ata_bmdma_start (struct ata_queued_cmd *qc); extern void ata_bmdma_stop(struct ata_queued_cmd *qc); extern u8 ata_bmdma_status(struct ata_port *ap); extern void ata_bmdma_irq_clear(struct ata_port *ap); -extern void __ata_qc_complete(struct ata_queued_cmd *qc); +extern void ata_qc_complete(struct ata_queued_cmd *qc); extern void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)); extern int ata_std_bios_param(struct scsi_device *sdev, @@ -882,31 +882,6 @@ static inline void ata_qc_reinit(struct ata_queued_cmd *qc) qc->result_tf.feature = 0; } -/** - * ata_qc_complete - Complete an active ATA command - * @qc: Command to complete - * @err_mask: ATA Status register contents - * - * Indicate to the mid and upper layers that an ATA - * command has completed, with either an ok or not-ok status. - * - * LOCKING: - * spin_lock_irqsave(host_set lock) - */ -static inline void ata_qc_complete(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - - if (unlikely(qc->flags & ATA_QCFLAG_EH_SCHEDULED)) - return; - - /* read result TF if failed or requested */ - if (qc->err_mask || qc->flags & ATA_QCFLAG_RESULT_TF) - ap->ops->tf_read(ap, &qc->result_tf); - - __ata_qc_complete(qc); -} - /** * ata_irq_on - Enable interrupts on a port. * @ap: Port on which interrupts are enabled. -- cgit v1.2.3 From 7b70fc039824bc7303e4007a5f758f832de56611 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:58:07 +0900 Subject: [PATCH] libata-eh-fw: implement ata_port_schedule_eh() and ata_port_abort() ata_port_schedule_eh() directly schedules EH for @ap without associated qc. Once EH scheduled, no further qc is allowed and EH kicks in as soon as all currently active qc's are drained. ata_port_abort() schedules all currently active commands for EH by qc_completing them with ATA_QCFLAG_FAILED set. If ata_port_abort() doesn't find any qc to abort, it directly schedule EH using ata_port_schedule_eh(). These two functions provide ways to invoke EH for conditions which aren't directly related to any specfic qc. Signed-off-by: Tejun Heo --- drivers/scsi/libata-core.c | 2 ++ drivers/scsi/libata-eh.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/scsi/libata-scsi.c | 23 ++++++++++++++++++++ drivers/scsi/libata.h | 1 + include/linux/libata.h | 4 ++++ 5 files changed, 84 insertions(+) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 1f5c3270992..9c97783462d 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -5383,5 +5383,7 @@ EXPORT_SYMBOL_GPL(ata_scsi_device_suspend); EXPORT_SYMBOL_GPL(ata_scsi_device_resume); EXPORT_SYMBOL_GPL(ata_eng_timeout); +EXPORT_SYMBOL_GPL(ata_port_schedule_eh); +EXPORT_SYMBOL_GPL(ata_port_abort); EXPORT_SYMBOL_GPL(ata_eh_qc_complete); EXPORT_SYMBOL_GPL(ata_eh_qc_retry); diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c index 471846fe4b7..037a561809f 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/scsi/libata-eh.c @@ -237,6 +237,60 @@ void ata_qc_schedule_eh(struct ata_queued_cmd *qc) scsi_req_abort_cmd(qc->scsicmd); } +/** + * ata_port_schedule_eh - schedule error handling without a qc + * @ap: ATA port to schedule EH for + * + * Schedule error handling for @ap. EH will kick in as soon as + * all commands are drained. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ +void ata_port_schedule_eh(struct ata_port *ap) +{ + WARN_ON(!ap->ops->error_handler); + + ap->flags |= ATA_FLAG_EH_PENDING; + ata_schedule_scsi_eh(ap->host); + + DPRINTK("port EH scheduled\n"); +} + +/** + * ata_port_abort - abort all qc's on the port + * @ap: ATA port to abort qc's for + * + * Abort all active qc's of @ap and schedule EH. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + * + * RETURNS: + * Number of aborted qc's. + */ +int ata_port_abort(struct ata_port *ap) +{ + int tag, nr_aborted = 0; + + WARN_ON(!ap->ops->error_handler); + + for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { + struct ata_queued_cmd *qc = ata_qc_from_tag(ap, tag); + + if (qc) { + qc->flags |= ATA_QCFLAG_FAILED; + ata_qc_complete(qc); + nr_aborted++; + } + } + + if (!nr_aborted) + ata_port_schedule_eh(ap); + + return nr_aborted; +} + static void ata_eh_scsidone(struct scsi_cmnd *scmd) { /* nada */ diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index a9b4083a4f6..fd7064b9697 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -2596,3 +2596,26 @@ void ata_scsi_scan_host(struct ata_port *ap) } } +/** + * ata_schedule_scsi_eh - schedule EH for SCSI host + * @shost: SCSI host to invoke error handling on. + * + * Schedule SCSI EH without scmd. This is a hack. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + **/ +void ata_schedule_scsi_eh(struct Scsi_Host *shost) +{ + unsigned long flags; + + spin_lock_irqsave(shost->host_lock, flags); + + if (scsi_host_set_state(shost, SHOST_RECOVERY) == 0 || + scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY) == 0) { + shost->host_eh_scheduled++; + scsi_eh_wakeup(shost); + } + + spin_unlock_irqrestore(shost->host_lock, flags); +} diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index 52622b7f8a9..b76ad7d7062 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -98,6 +98,7 @@ extern void ata_scsi_set_sense(struct scsi_cmnd *cmd, extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args, unsigned int (*actor) (struct ata_scsi_args *args, u8 *rbuf, unsigned int buflen)); +extern void ata_schedule_scsi_eh(struct Scsi_Host *shost); /* libata-eh.c */ extern enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd); diff --git a/include/linux/libata.h b/include/linux/libata.h index 6023f324e68..086e1469095 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -662,6 +662,10 @@ extern unsigned long ata_pci_default_filter(const struct ata_port *, struct ata_ * EH */ extern void ata_eng_timeout(struct ata_port *ap); + +extern void ata_port_schedule_eh(struct ata_port *ap); +extern int ata_port_abort(struct ata_port *ap); + extern void ata_eh_qc_complete(struct ata_queued_cmd *qc); extern void ata_eh_qc_retry(struct ata_queued_cmd *qc); -- cgit v1.2.3 From e318049949b07152d851dbfebbd93e560af45ebe Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:58:09 +0900 Subject: [PATCH] libata-eh-fw: implement freeze/thaw Freezing is performed atomic w.r.t. host_set->lock and once frozen LLDD is not allowed to access the port or any qc on it. Also, libata makes sure that no new qc gets issued to a frozen port. A frozen port is thawed after a reset operation completes successfully, so reset methods must do its job while the port is frozen. During initialization all ports get frozen before requesting IRQ, so reset methods are always invoked on a frozen port. Optional ->freeze and ->thaw operations notify LLDD that the port is being frozen and thawed, respectively. LLDD can disable/enable hardware interrupt in these callbacks if the controller's IRQ mask can be changed dynamically. If the controller doesn't allow such operation, LLDD can check for frozen state in the interrupt handler and ack/clear interrupts unconditionally while frozen. Signed-off-by: Tejun Heo --- drivers/scsi/libata-core.c | 26 +++++++++++- drivers/scsi/libata-eh.c | 103 +++++++++++++++++++++++++++++++++++++++++++++ include/linux/libata.h | 4 ++ 3 files changed, 131 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 9c97783462d..63857a90ac2 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -987,6 +987,12 @@ unsigned ata_exec_internal(struct ata_device *dev, spin_lock_irqsave(&ap->host_set->lock, flags); + /* no internal command while frozen */ + if (ap->flags & ATA_FLAG_FROZEN) { + spin_unlock_irqrestore(&ap->host_set->lock, flags); + return AC_ERR_SYSTEM; + } + /* initialize internal qc */ /* XXX: Tag 0 is used for drivers with legacy EH as some @@ -2565,8 +2571,11 @@ void ata_std_postreset(struct ata_port *ap, unsigned int *classes) sata_scr_write(ap, SCR_ERROR, serror); /* re-enable interrupts */ - if (ap->ioaddr.ctl_addr) /* FIXME: hack. create a hook instead */ - ata_irq_on(ap); + if (!ap->ops->error_handler) { + /* FIXME: hack. create a hook instead */ + if (ap->ioaddr.ctl_addr) + ata_irq_on(ap); + } /* is double-select really necessary? */ if (classes[0] != ATA_DEV_NONE) @@ -2681,6 +2690,8 @@ int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, { int rc = -EINVAL; + ata_eh_freeze_port(ap); + if (probeinit) probeinit(ap); @@ -2725,6 +2736,9 @@ int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, if (rc == 0) { if (postreset) postreset(ap, classes); + + ata_eh_thaw_port(ap); + if (classes[0] == ATA_DEV_UNKNOWN) rc = -ENODEV; } @@ -4039,6 +4053,10 @@ static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap) struct ata_queued_cmd *qc = NULL; unsigned int i; + /* no command while frozen */ + if (unlikely(ap->flags & ATA_FLAG_FROZEN)) + return NULL; + /* the last tag is reserved for internal command. */ for (i = 0; i < ATA_MAX_QUEUE - 1; i++) if (!test_and_set_bit(i, &ap->qactive)) { @@ -4953,6 +4971,7 @@ int ata_device_add(const struct ata_probe_ent *ent) ata_chk_status(ap); host_set->ops->irq_clear(ap); + ata_eh_freeze_port(ap); /* freeze port before requesting IRQ */ count++; } @@ -5385,5 +5404,8 @@ EXPORT_SYMBOL_GPL(ata_scsi_device_resume); EXPORT_SYMBOL_GPL(ata_eng_timeout); EXPORT_SYMBOL_GPL(ata_port_schedule_eh); EXPORT_SYMBOL_GPL(ata_port_abort); +EXPORT_SYMBOL_GPL(ata_port_freeze); +EXPORT_SYMBOL_GPL(ata_eh_freeze_port); +EXPORT_SYMBOL_GPL(ata_eh_thaw_port); EXPORT_SYMBOL_GPL(ata_eh_qc_complete); EXPORT_SYMBOL_GPL(ata_eh_qc_retry); diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c index 037a561809f..cb4e2b8d32d 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/scsi/libata-eh.c @@ -291,6 +291,109 @@ int ata_port_abort(struct ata_port *ap) return nr_aborted; } +/** + * __ata_port_freeze - freeze port + * @ap: ATA port to freeze + * + * This function is called when HSM violation or some other + * condition disrupts normal operation of the port. Frozen port + * is not allowed to perform any operation until the port is + * thawed, which usually follows a successful reset. + * + * ap->ops->freeze() callback can be used for freezing the port + * hardware-wise (e.g. mask interrupt and stop DMA engine). If a + * port cannot be frozen hardware-wise, the interrupt handler + * must ack and clear interrupts unconditionally while the port + * is frozen. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ +static void __ata_port_freeze(struct ata_port *ap) +{ + WARN_ON(!ap->ops->error_handler); + + if (ap->ops->freeze) + ap->ops->freeze(ap); + + ap->flags |= ATA_FLAG_FROZEN; + + DPRINTK("ata%u port frozen\n", ap->id); +} + +/** + * ata_port_freeze - abort & freeze port + * @ap: ATA port to freeze + * + * Abort and freeze @ap. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + * + * RETURNS: + * Number of aborted commands. + */ +int ata_port_freeze(struct ata_port *ap) +{ + int nr_aborted; + + WARN_ON(!ap->ops->error_handler); + + nr_aborted = ata_port_abort(ap); + __ata_port_freeze(ap); + + return nr_aborted; +} + +/** + * ata_eh_freeze_port - EH helper to freeze port + * @ap: ATA port to freeze + * + * Freeze @ap. + * + * LOCKING: + * None. + */ +void ata_eh_freeze_port(struct ata_port *ap) +{ + unsigned long flags; + + if (!ap->ops->error_handler) + return; + + spin_lock_irqsave(&ap->host_set->lock, flags); + __ata_port_freeze(ap); + spin_unlock_irqrestore(&ap->host_set->lock, flags); +} + +/** + * ata_port_thaw_port - EH helper to thaw port + * @ap: ATA port to thaw + * + * Thaw frozen port @ap. + * + * LOCKING: + * None. + */ +void ata_eh_thaw_port(struct ata_port *ap) +{ + unsigned long flags; + + if (!ap->ops->error_handler) + return; + + spin_lock_irqsave(&ap->host_set->lock, flags); + + ap->flags &= ~ATA_FLAG_FROZEN; + + if (ap->ops->thaw) + ap->ops->thaw(ap); + + spin_unlock_irqrestore(&ap->host_set->lock, flags); + + DPRINTK("ata%u port thawed\n", ap->id); +} + static void ata_eh_scsidone(struct scsi_cmnd *scmd) { /* nada */ diff --git a/include/linux/libata.h b/include/linux/libata.h index 086e1469095..6758b4d374a 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -665,6 +665,10 @@ extern void ata_eng_timeout(struct ata_port *ap); extern void ata_port_schedule_eh(struct ata_port *ap); extern int ata_port_abort(struct ata_port *ap); +extern int ata_port_freeze(struct ata_port *ap); + +extern void ata_eh_freeze_port(struct ata_port *ap); +extern void ata_eh_thaw_port(struct ata_port *ap); extern void ata_eh_qc_complete(struct ata_queued_cmd *qc); extern void ata_eh_qc_retry(struct ata_queued_cmd *qc); -- cgit v1.2.3 From dafadcde8d4dc5ea8c742faa7ff4403336b542b8 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:58:11 +0900 Subject: [PATCH] libata-eh-fw: implement new EH scheduling from PIO PIO executes without holding host_set lock, so it cannot be synchronized using the same mechanism as interrupt driven execution. port_task framework makes sure that EH is not entered until PIO task is flushed, so PIO task can be sure the qc in progress won't go away underneath it. One thing it cannot be sure of is whether the qc has already been scheduled for EH by another exception condition while host_set lock was released. This patch makes ata_poll_qc-complete() handle such conditions properly and make it freeze the port if HSM violation is detected during PIO execution. Signed-off-by: Tejun Heo --- drivers/scsi/libata-core.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 63857a90ac2..35ae5b41f66 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3430,16 +3430,31 @@ skip_map: * LOCKING: * None. (grabs host lock) */ - void ata_poll_qc_complete(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; unsigned long flags; spin_lock_irqsave(&ap->host_set->lock, flags); - ap->flags &= ~ATA_FLAG_NOINTR; - ata_irq_on(ap); - ata_qc_complete(qc); + + if (ap->ops->error_handler) { + /* EH might have kicked in while host_set lock is released */ + qc = ata_qc_from_tag(ap, qc->tag); + if (qc) { + if (!(qc->err_mask & AC_ERR_HSM)) { + ap->flags &= ~ATA_FLAG_NOINTR; + ata_irq_on(ap); + ata_qc_complete(qc); + } else + ata_port_freeze(ap); + } + } else { + /* old EH */ + ap->flags &= ~ATA_FLAG_NOINTR; + ata_irq_on(ap); + ata_qc_complete(qc); + } + spin_unlock_irqrestore(&ap->host_set->lock, flags); } -- cgit v1.2.3 From ad9e27624479bd167dd7eac0cea4bb3ad13bc926 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:58:12 +0900 Subject: [PATCH] libata-eh-fw: update ata_scsi_error() for new EH Update ata_scsi_error() for new EH. ata_scsi_error() is responsible for claiming timed out qcs and invoking ->error_handler in safe and synchronized manner. As the state of the controller is unknown if a qc has timed out, the port is frozen in such cases. Note that ata_scsi_timed_out() isn't used for new EH. This is because a timed out qc cannot be claimed by EH without freezing the port and freezing the port in ata_scsi_timed_out() results in unnecessary abortion of other active qcs. ata_scsi_timed_out() can be removed once all drivers are converted to new EH. While at it, add 'TODO: kill' comments to old EH functions. Signed-off-by: Tejun Heo --- drivers/scsi/libata-eh.c | 136 +++++++++++++++++++++++++++++++++++++++++++++-- include/linux/libata.h | 3 ++ 2 files changed, 134 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c index cb4e2b8d32d..0803231f657 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/scsi/libata-eh.c @@ -44,6 +44,8 @@ #include "libata.h" +static void __ata_port_freeze(struct ata_port *ap); + /** * ata_scsi_timed_out - SCSI layer time out callback * @cmd: timed out SCSI command @@ -55,6 +57,8 @@ * from finishing it by setting EH_SCHEDULED and return * EH_NOT_HANDLED. * + * TODO: kill this function once old EH is gone. + * * LOCKING: * Called from timer context * @@ -67,10 +71,16 @@ enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd) struct ata_port *ap = ata_shost_to_port(host); unsigned long flags; struct ata_queued_cmd *qc; - enum scsi_eh_timer_return ret = EH_HANDLED; + enum scsi_eh_timer_return ret; DPRINTK("ENTER\n"); + if (ap->ops->error_handler) { + ret = EH_NOT_HANDLED; + goto out; + } + + ret = EH_HANDLED; spin_lock_irqsave(&ap->host_set->lock, flags); qc = ata_qc_from_tag(ap, ap->active_tag); if (qc) { @@ -81,6 +91,7 @@ enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd) } spin_unlock_irqrestore(&ap->host_set->lock, flags); + out: DPRINTK("EXIT, ret=%d\n", ret); return ret; } @@ -100,21 +111,132 @@ enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd) void ata_scsi_error(struct Scsi_Host *host) { struct ata_port *ap = ata_shost_to_port(host); + spinlock_t *hs_lock = &ap->host_set->lock; + int i, repeat_cnt = ATA_EH_MAX_REPEAT; + unsigned long flags; DPRINTK("ENTER\n"); - /* synchronize with IRQ handler and port task */ - spin_unlock_wait(&ap->host_set->lock); + /* synchronize with port task */ ata_port_flush_task(ap); - WARN_ON(ata_qc_from_tag(ap, ap->active_tag) == NULL); + /* synchronize with host_set lock and sort out timeouts */ + + /* For new EH, all qcs are finished in one of three ways - + * normal completion, error completion, and SCSI timeout. + * Both cmpletions can race against SCSI timeout. When normal + * completion wins, the qc never reaches EH. When error + * completion wins, the qc has ATA_QCFLAG_FAILED set. + * + * When SCSI timeout wins, things are a bit more complex. + * Normal or error completion can occur after the timeout but + * before this point. In such cases, both types of + * completions are honored. A scmd is determined to have + * timed out iff its associated qc is active and not failed. + */ + if (ap->ops->error_handler) { + struct scsi_cmnd *scmd, *tmp; + int nr_timedout = 0; + + spin_lock_irqsave(hs_lock, flags); + + list_for_each_entry_safe(scmd, tmp, &host->eh_cmd_q, eh_entry) { + struct ata_queued_cmd *qc; + + for (i = 0; i < ATA_MAX_QUEUE; i++) { + qc = __ata_qc_from_tag(ap, i); + if (qc->flags & ATA_QCFLAG_ACTIVE && + qc->scsicmd == scmd) + break; + } + + if (i < ATA_MAX_QUEUE) { + /* the scmd has an associated qc */ + if (!(qc->flags & ATA_QCFLAG_FAILED)) { + /* which hasn't failed yet, timeout */ + qc->err_mask |= AC_ERR_TIMEOUT; + qc->flags |= ATA_QCFLAG_FAILED; + nr_timedout++; + } + } else { + /* Normal completion occurred after + * SCSI timeout but before this point. + * Successfully complete it. + */ + scmd->retries = scmd->allowed; + scsi_eh_finish_cmd(scmd, &ap->eh_done_q); + } + } + + /* If we have timed out qcs. They belong to EH from + * this point but the state of the controller is + * unknown. Freeze the port to make sure the IRQ + * handler doesn't diddle with those qcs. This must + * be done atomically w.r.t. setting QCFLAG_FAILED. + */ + if (nr_timedout) + __ata_port_freeze(ap); + + spin_unlock_irqrestore(hs_lock, flags); + } else + spin_unlock_wait(hs_lock); + + repeat: + /* invoke error handler */ + if (ap->ops->error_handler) { + /* clear EH pending */ + spin_lock_irqsave(hs_lock, flags); + ap->flags &= ~ATA_FLAG_EH_PENDING; + spin_unlock_irqrestore(hs_lock, flags); + + /* invoke EH */ + ap->ops->error_handler(ap); + + /* Exception might have happend after ->error_handler + * recovered the port but before this point. Repeat + * EH in such case. + */ + spin_lock_irqsave(hs_lock, flags); + + if (ap->flags & ATA_FLAG_EH_PENDING) { + if (--repeat_cnt) { + ata_port_printk(ap, KERN_INFO, + "EH pending after completion, " + "repeating EH (cnt=%d)\n", repeat_cnt); + spin_unlock_irqrestore(hs_lock, flags); + goto repeat; + } + ata_port_printk(ap, KERN_ERR, "EH pending after %d " + "tries, giving up\n", ATA_EH_MAX_REPEAT); + } - ap->ops->eng_timeout(ap); + /* Clear host_eh_scheduled while holding hs_lock such + * that if exception occurs after this point but + * before EH completion, SCSI midlayer will + * re-initiate EH. + */ + host->host_eh_scheduled = 0; + + spin_unlock_irqrestore(hs_lock, flags); + } else { + WARN_ON(ata_qc_from_tag(ap, ap->active_tag) == NULL); + ap->ops->eng_timeout(ap); + } + /* finish or retry handled scmd's and clean up */ WARN_ON(host->host_failed || !list_empty(&host->eh_cmd_q)); scsi_eh_flush_done_q(&ap->eh_done_q); + /* clean up */ + spin_lock_irqsave(hs_lock, flags); + + if (ap->flags & ATA_FLAG_RECOVERED) + ata_port_printk(ap, KERN_INFO, "EH complete\n"); + ap->flags &= ~ATA_FLAG_RECOVERED; + + spin_unlock_irqrestore(hs_lock, flags); + DPRINTK("EXIT\n"); } @@ -133,6 +255,8 @@ void ata_scsi_error(struct Scsi_Host *host) * an interrupt was not delivered to the driver, even though the * transaction completed successfully. * + * TODO: kill this function once old EH is gone. + * * LOCKING: * Inherited from SCSI layer (none, can sleep) */ @@ -198,6 +322,8 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc) * an interrupt was not delivered to the driver, even though the * transaction completed successfully. * + * TODO: kill this function once old EH is gone. + * * LOCKING: * Inherited from SCSI layer (none, can sleep) */ diff --git a/include/linux/libata.h b/include/linux/libata.h index 6758b4d374a..5ad50163c8e 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -225,6 +225,9 @@ enum { ATA_PORT_PRIMARY = (1 << 0), ATA_PORT_SECONDARY = (1 << 1), + /* max repeat if error condition is still set after ->error_handler */ + ATA_EH_MAX_REPEAT = 5, + /* how hard are we gonna try to probe/recover devices */ ATA_PROBE_MAX_TRIES = 3, }; -- cgit v1.2.3 From d95a717f579e81061830a308125c89f5858f740a Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:58:14 +0900 Subject: [PATCH] libata-eh-fw: update ata_exec_internal() for new EH Update ata_exec_internal() such that it uses new EH framework. ->post_internal_cmd() is always invoked regardless of completion status. Also, when ata_exec_internal() detects a timeout condition and new EH is in place, it freezes the port as timeout for normal commands would do. Note that ata_port_flush_task() is called regardless of wait_for_completion status. This is necessary as exceptions unrelated to the qc can abort the qc, in which case PIO task could still be running after the wait for completion returns. Signed-off-by: Tejun Heo --- drivers/scsi/libata-core.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 35ae5b41f66..4def48ed6f4 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -984,6 +984,7 @@ unsigned ata_exec_internal(struct ata_device *dev, DECLARE_COMPLETION(wait); unsigned long flags; unsigned int err_mask; + int rc; spin_lock_irqsave(&ap->host_set->lock, flags); @@ -1036,20 +1037,25 @@ unsigned ata_exec_internal(struct ata_device *dev, spin_unlock_irqrestore(&ap->host_set->lock, flags); - if (!wait_for_completion_timeout(&wait, ATA_TMOUT_INTERNAL)) { - ata_port_flush_task(ap); + rc = wait_for_completion_timeout(&wait, ATA_TMOUT_INTERNAL); + + ata_port_flush_task(ap); + if (!rc) { spin_lock_irqsave(&ap->host_set->lock, flags); /* We're racing with irq here. If we lose, the * following test prevents us from completing the qc - * again. If completion irq occurs after here but - * before the caller cleans up, it will result in a - * spurious interrupt. We can live with that. + * twice. If we win, the port is frozen and will be + * cleaned up by ->post_internal_cmd(). */ if (qc->flags & ATA_QCFLAG_ACTIVE) { - qc->err_mask = AC_ERR_TIMEOUT; - ata_qc_complete(qc); + qc->err_mask |= AC_ERR_TIMEOUT; + + if (ap->ops->error_handler) + ata_port_freeze(ap); + else + ata_qc_complete(qc); ata_dev_printk(dev, KERN_WARNING, "qc timeout (cmd 0x%x)\n", command); @@ -1058,6 +1064,16 @@ unsigned ata_exec_internal(struct ata_device *dev, spin_unlock_irqrestore(&ap->host_set->lock, flags); } + /* do post_internal_cmd */ + if (ap->ops->post_internal_cmd) + ap->ops->post_internal_cmd(qc); + + if (qc->flags & ATA_QCFLAG_FAILED && !qc->err_mask) { + ata_dev_printk(dev, KERN_WARNING, "zero err_mask for failed " + "internal command, assuming AC_ERR_OTHER\n"); + qc->err_mask |= AC_ERR_OTHER; + } + /* finish up */ spin_lock_irqsave(&ap->host_set->lock, flags); -- cgit v1.2.3 From 246619da308c6910a3ae30e7e5fbf46139619efe Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:58:16 +0900 Subject: [PATCH] libata-eh-fw: update SCSI command completion path for new EH SCSI command completion path used to do some part of EH including printing messages and obtaining sense data. With new EH, all these are responsibilities of the EH, update SCSI command completion path to reflect this. Signed-off-by: Tejun Heo --- drivers/scsi/libata-scsi.c | 48 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index fd7064b9697..e61cc357ae4 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -415,6 +415,7 @@ int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t state) * @sk: the sense key we'll fill out * @asc: the additional sense code we'll fill out * @ascq: the additional sense code qualifier we'll fill out + * @verbose: be verbose * * Converts an ATA error into a SCSI error. Fill out pointers to * SK, ASC, and ASCQ bytes for later use in fixed or descriptor @@ -424,7 +425,7 @@ int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t state) * spin_lock_irqsave(host_set lock) */ void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc, - u8 *ascq) + u8 *ascq, int verbose) { int i; @@ -489,8 +490,9 @@ void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc, } } /* No immediate match */ - printk(KERN_WARNING "ata%u: no sense translation for " - "error 0x%02x\n", id, drv_err); + if (verbose) + printk(KERN_WARNING "ata%u: no sense translation for " + "error 0x%02x\n", id, drv_err); } /* Fall back to interpreting status bits */ @@ -503,8 +505,9 @@ void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc, } } /* No error? Undecoded? */ - printk(KERN_WARNING "ata%u: no sense translation for status: 0x%02x\n", - id, drv_stat); + if (verbose) + printk(KERN_WARNING "ata%u: no sense translation for " + "status: 0x%02x\n", id, drv_stat); /* We need a sensible error return here, which is tricky, and one that won't cause people to do things like return a disk wrongly */ @@ -513,9 +516,10 @@ void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc, *ascq = 0x00; translate_done: - printk(KERN_ERR "ata%u: translated ATA stat/err 0x%02x/%02x to " - "SCSI SK/ASC/ASCQ 0x%x/%02x/%02x\n", id, drv_stat, drv_err, - *sk, *asc, *ascq); + if (verbose) + printk(KERN_ERR "ata%u: translated ATA stat/err 0x%02x/%02x " + "to SCSI SK/ASC/ASCQ 0x%x/%02x/%02x\n", + id, drv_stat, drv_err, *sk, *asc, *ascq); return; } @@ -538,6 +542,7 @@ void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc) struct ata_taskfile *tf = &qc->result_tf; unsigned char *sb = cmd->sense_buffer; unsigned char *desc = sb + 8; + int verbose = qc->ap->ops->error_handler == NULL; memset(sb, 0, SCSI_SENSE_BUFFERSIZE); @@ -550,7 +555,7 @@ void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc) if (qc->err_mask || tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) { ata_to_sense_error(qc->ap->id, tf->command, tf->feature, - &sb[1], &sb[2], &sb[3]); + &sb[1], &sb[2], &sb[3], verbose); sb[1] &= 0x0f; } @@ -608,6 +613,7 @@ void ata_gen_fixed_sense(struct ata_queued_cmd *qc) struct scsi_cmnd *cmd = qc->scsicmd; struct ata_taskfile *tf = &qc->result_tf; unsigned char *sb = cmd->sense_buffer; + int verbose = qc->ap->ops->error_handler == NULL; memset(sb, 0, SCSI_SENSE_BUFFERSIZE); @@ -620,7 +626,7 @@ void ata_gen_fixed_sense(struct ata_queued_cmd *qc) if (qc->err_mask || tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) { ata_to_sense_error(qc->ap->id, tf->command, tf->feature, - &sb[2], &sb[12], &sb[13]); + &sb[2], &sb[12], &sb[13], verbose); sb[2] &= 0x0f; } @@ -1212,7 +1218,7 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) } } - if (need_sense) + if (need_sense && !qc->ap->ops->error_handler) ata_dump_status(qc->ap->id, &qc->result_tf); qc->scsidone(cmd); @@ -2060,6 +2066,26 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc) VPRINTK("ENTER, err_mask 0x%X\n", err_mask); + /* handle completion from new EH */ + if (unlikely(qc->ap->ops->error_handler && + (err_mask || qc->flags & ATA_QCFLAG_SENSE_VALID))) { + + if (!(qc->flags & ATA_QCFLAG_SENSE_VALID)) { + /* FIXME: not quite right; we don't want the + * translation of taskfile registers into a + * sense descriptors, since that's only + * correct for ATA, not ATAPI + */ + ata_gen_ata_desc_sense(qc); + } + + qc->scsicmd->result = SAM_STAT_CHECK_CONDITION; + qc->scsidone(cmd); + ata_qc_free(qc); + return; + } + + /* successful completion or old EH failure path */ if (unlikely(err_mask & AC_ERR_DEV)) { cmd->result = SAM_STAT_CHECK_CONDITION; atapi_request_sense(qc); -- cgit v1.2.3 From 9be1e979f2e1e57a091a658fa88dac266f9fd6fe Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:58:17 +0900 Subject: [PATCH] libata-eh: add ATA and libata flags for new EH Add ATA and libata flags to be used by new EH. Signed-off-by: Tejun Heo --- include/linux/ata.h | 13 +++++++++++++ include/linux/libata.h | 8 ++++++++ 2 files changed, 21 insertions(+) diff --git a/include/linux/ata.h b/include/linux/ata.h index 312a2c0c64e..a7c41f3df8f 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -97,6 +97,9 @@ enum { ATA_DRQ = (1 << 3), /* data request i/o */ ATA_ERR = (1 << 0), /* have an error */ ATA_SRST = (1 << 2), /* software reset */ + ATA_ICRC = (1 << 7), /* interface CRC error */ + ATA_UNC = (1 << 6), /* uncorrectable media error */ + ATA_IDNF = (1 << 4), /* ID not found */ ATA_ABORTED = (1 << 2), /* command aborted */ /* ATA command block registers */ @@ -192,6 +195,16 @@ enum { SCR_ACTIVE = 3, SCR_NOTIFICATION = 4, + /* SError bits */ + SERR_DATA_RECOVERED = (1 << 0), /* recovered data error */ + SERR_COMM_RECOVERED = (1 << 1), /* recovered comm failure */ + SERR_DATA = (1 << 8), /* unrecovered data error */ + SERR_PERSISTENT = (1 << 9), /* persistent data/comm error */ + SERR_PROTOCOL = (1 << 10), /* protocol violation */ + SERR_INTERNAL = (1 << 11), /* host internal error */ + SERR_PHYRDY_CHG = (1 << 16), /* PHY RDY changed */ + SERR_DEV_XCHG = (1 << 26), /* device exchanged */ + /* struct ata_taskfile flags */ ATA_TFLAG_LBA48 = (1 << 0), /* enable 48-bit LBA and "HOB" */ ATA_TFLAG_ISADDR = (1 << 1), /* enable r/w to nsect/lba regs */ diff --git a/include/linux/libata.h b/include/linux/libata.h index 5ad50163c8e..6fe5ed8eabf 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -155,6 +155,7 @@ enum { ATA_FLAG_EH_PENDING = (1 << 16), /* EH pending */ ATA_FLAG_FROZEN = (1 << 17), /* port is frozen */ + ATA_FLAG_RECOVERED = (1 << 18), /* recovery action performed */ ATA_FLAG_DISABLED = (1 << 22), /* port is disabled, ignore it */ ATA_FLAG_SUSPENDED = (1 << 23), /* port is suspended (power) */ @@ -225,6 +226,13 @@ enum { ATA_PORT_PRIMARY = (1 << 0), ATA_PORT_SECONDARY = (1 << 1), + /* reset / recovery action types */ + ATA_EH_REVALIDATE = (1 << 0), + ATA_EH_SOFTRESET = (1 << 1), + ATA_EH_HARDRESET = (1 << 2), + + ATA_EH_RESET_MASK = ATA_EH_SOFTRESET | ATA_EH_HARDRESET, + /* max repeat if error condition is still set after ->error_handler */ ATA_EH_MAX_REPEAT = 5, -- cgit v1.2.3 From 0c247c559cd70f85ba9f0764ce13ae00e20fcad8 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:58:19 +0900 Subject: [PATCH] libata-eh: implement dev->ering This patch implements ata_ering and uses it to define dev->ering. ata_ering is a ring buffer which records libata errors - whether a command was for normar IO request, err_mask and timestamp. Errors are recorded per-device in dev->ering. This will be used by EH to determine recovery actions. Signed-off-by: Tejun Heo --- drivers/scsi/libata-eh.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ include/linux/libata.h | 17 +++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c index 0803231f657..71ad18b7cff 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/scsi/libata-eh.c @@ -46,6 +46,51 @@ static void __ata_port_freeze(struct ata_port *ap); +static void ata_ering_record(struct ata_ering *ering, int is_io, + unsigned int err_mask) +{ + struct ata_ering_entry *ent; + + WARN_ON(!err_mask); + + ering->cursor++; + ering->cursor %= ATA_ERING_SIZE; + + ent = &ering->ring[ering->cursor]; + ent->is_io = is_io; + ent->err_mask = err_mask; + ent->timestamp = get_jiffies_64(); +} + +static struct ata_ering_entry * ata_ering_top(struct ata_ering *ering) +{ + struct ata_ering_entry *ent = &ering->ring[ering->cursor]; + if (!ent->err_mask) + return NULL; + return ent; +} + +static int ata_ering_map(struct ata_ering *ering, + int (*map_fn)(struct ata_ering_entry *, void *), + void *arg) +{ + int idx, rc = 0; + struct ata_ering_entry *ent; + + idx = ering->cursor; + do { + ent = &ering->ring[idx]; + if (!ent->err_mask) + break; + rc = map_fn(ent, arg); + if (rc) + break; + idx = (idx - 1 + ATA_ERING_SIZE) % ATA_ERING_SIZE; + } while (idx != ering->cursor); + + return rc; +} + /** * ata_scsi_timed_out - SCSI layer time out callback * @cmd: timed out SCSI command diff --git a/include/linux/libata.h b/include/linux/libata.h index 6fe5ed8eabf..f5cea13599c 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -226,6 +226,9 @@ enum { ATA_PORT_PRIMARY = (1 << 0), ATA_PORT_SECONDARY = (1 << 1), + /* ering size */ + ATA_ERING_SIZE = 32, + /* reset / recovery action types */ ATA_EH_REVALIDATE = (1 << 0), ATA_EH_SOFTRESET = (1 << 1), @@ -375,6 +378,17 @@ struct ata_host_stats { unsigned long rw_reqbuf; }; +struct ata_ering_entry { + int is_io; + unsigned int err_mask; + u64 timestamp; +}; + +struct ata_ering { + int cursor; + struct ata_ering_entry ring[ATA_ERING_SIZE]; +}; + struct ata_device { struct ata_port *ap; u64 n_sectors; /* size of device, if ATA */ @@ -401,6 +415,9 @@ struct ata_device { u16 cylinders; /* Number of cylinders */ u16 heads; /* Number of heads */ u16 sectors; /* Number of sectors per track */ + + /* error history */ + struct ata_ering ering; }; struct ata_port { -- cgit v1.2.3 From f3e81b19aac23c0e8c55d5961324ef7de44c23bb Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:58:21 +0900 Subject: [PATCH] libata-eh: implement ata_eh_info and ata_eh_context struct ata_eh_info serves as the communication channel between execution path and EH. Execution path describes detected error condition in ap->eh_info and EH recovers the port using it. To avoid missing error conditions detected during EH, EH makes its own copy of eh_info and clears it on entry allowing error info to accumulate during EH. Most EH states including EH's copy of eh_info are stored in ap->eh_context (struct ata_eh_context) which is owned by EH and thus doesn't require any synchronization to access and alter. This standardized context makes it easy to integrate various parts of EH and extend EH to handle multiple links (for PM). Signed-off-by: Tejun Heo --- drivers/scsi/libata-eh.c | 11 ++++++++++- include/linux/libata.h | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c index 71ad18b7cff..1968f2d140f 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/scsi/libata-eh.c @@ -229,9 +229,15 @@ void ata_scsi_error(struct Scsi_Host *host) repeat: /* invoke error handler */ if (ap->ops->error_handler) { - /* clear EH pending */ + /* fetch & clear EH info */ spin_lock_irqsave(hs_lock, flags); + + memset(&ap->eh_context, 0, sizeof(ap->eh_context)); + ap->eh_context.i = ap->eh_info; + memset(&ap->eh_info, 0, sizeof(ap->eh_info)); + ap->flags &= ~ATA_FLAG_EH_PENDING; + spin_unlock_irqrestore(hs_lock, flags); /* invoke EH */ @@ -255,6 +261,9 @@ void ata_scsi_error(struct Scsi_Host *host) "tries, giving up\n", ATA_EH_MAX_REPEAT); } + /* this run is complete, make sure EH info is clear */ + memset(&ap->eh_info, 0, sizeof(ap->eh_info)); + /* Clear host_eh_scheduled while holding hs_lock such * that if exception occurs after this point but * before EH completion, SCSI midlayer will diff --git a/include/linux/libata.h b/include/linux/libata.h index f5cea13599c..298f9918e37 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -229,6 +229,9 @@ enum { /* ering size */ ATA_ERING_SIZE = 32, + /* desc_len for ata_eh_info and context */ + ATA_EH_DESC_LEN = 80, + /* reset / recovery action types */ ATA_EH_REVALIDATE = (1 << 0), ATA_EH_SOFTRESET = (1 << 1), @@ -236,6 +239,9 @@ enum { ATA_EH_RESET_MASK = ATA_EH_SOFTRESET | ATA_EH_HARDRESET, + /* ata_eh_info->flags */ + ATA_EHI_DID_RESET = (1 << 0), /* already reset this port */ + /* max repeat if error condition is still set after ->error_handler */ ATA_EH_MAX_REPEAT = 5, @@ -420,6 +426,21 @@ struct ata_device { struct ata_ering ering; }; +struct ata_eh_info { + struct ata_device *dev; /* offending device */ + u32 serror; /* SError from LLDD */ + unsigned int err_mask; /* port-wide err_mask */ + unsigned int action; /* ATA_EH_* action mask */ + unsigned int flags; /* ATA_EHI_* flags */ + char desc[ATA_EH_DESC_LEN]; + int desc_len; +}; + +struct ata_eh_context { + struct ata_eh_info i; + int tries[ATA_MAX_DEVICES]; +}; + struct ata_port { struct Scsi_Host *host; /* our co-allocated scsi host */ const struct ata_port_operations *ops; @@ -444,6 +465,11 @@ struct ata_port { unsigned int cbl; /* cable type; ATA_CBL_xxx */ unsigned int sata_spd_limit; /* SATA PHY speed limit */ + /* record runtime error info, protected by host_set lock */ + struct ata_eh_info eh_info; + /* EH context owned by EH */ + struct ata_eh_context eh_context; + struct ata_device device[ATA_MAX_DEVICES]; struct ata_queued_cmd qcmd[ATA_MAX_QUEUE]; @@ -710,6 +736,20 @@ extern void ata_eh_qc_retry(struct ata_queued_cmd *qc); #define ata_dev_printk(dev, lv, fmt, args...) \ printk(lv"ata%u.%02u: "fmt, (dev)->ap->id, (dev)->devno , ##args) +/* + * ata_eh_info helpers + */ +#define ata_ehi_push_desc(ehi, fmt, args...) do { \ + (ehi)->desc_len += scnprintf((ehi)->desc + (ehi)->desc_len, \ + ATA_EH_DESC_LEN - (ehi)->desc_len, \ + fmt , ##args); \ +} while (0) + +#define ata_ehi_clear_desc(ehi) do { \ + (ehi)->desc[0] = '\0'; \ + (ehi)->desc_len = 0; \ +} while (0) + /* * qc helpers */ -- cgit v1.2.3 From 022bdb075b9e1f224088a0b268de56268d7bc5b6 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:58:22 +0900 Subject: [PATCH] libata-eh: implement new EH Implement new EH. The exported interface is ata_do_eh() which is to be called from ->error_handler and performs the following steps to recover the failed port. ata_eh_autopsy() : analyze SError/TF, determine the cause of failure and required recovery actions and record it in ap->eh_context ata_eh_report() : report the failure to user ata_eh_recover() : perform recovery actions described in ap->eh_context ata_eh_finish() : finish failed qcs LLDDs can customize error handling by modifying eh_context before calling ata_do_eh() or, if necessary, doing so inbetween each major steps by calling each step explicitly. Signed-off-by: Tejun Heo --- drivers/scsi/libata-core.c | 1 + drivers/scsi/libata-eh.c | 775 +++++++++++++++++++++++++++++++++++++++++++++ include/linux/libata.h | 5 + 3 files changed, 781 insertions(+) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 4def48ed6f4..ddc47097d37 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -5440,3 +5440,4 @@ EXPORT_SYMBOL_GPL(ata_eh_freeze_port); EXPORT_SYMBOL_GPL(ata_eh_thaw_port); EXPORT_SYMBOL_GPL(ata_eh_qc_complete); EXPORT_SYMBOL_GPL(ata_eh_qc_retry); +EXPORT_SYMBOL_GPL(ata_do_eh); diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c index 1968f2d140f..cd133f83e59 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/scsi/libata-eh.c @@ -626,3 +626,778 @@ void ata_eh_qc_retry(struct ata_queued_cmd *qc) scmd->retries--; __ata_eh_qc_complete(qc); } + +/** + * ata_eh_about_to_do - about to perform eh_action + * @ap: target ATA port + * @action: action about to be performed + * + * Called just before performing EH actions to clear related bits + * in @ap->eh_info such that eh actions are not unnecessarily + * repeated. + * + * LOCKING: + * None. + */ +static void ata_eh_about_to_do(struct ata_port *ap, unsigned int action) +{ + unsigned long flags; + + spin_lock_irqsave(&ap->host_set->lock, flags); + ap->eh_info.action &= ~action; + ap->flags |= ATA_FLAG_RECOVERED; + spin_unlock_irqrestore(&ap->host_set->lock, flags); +} + +/** + * ata_err_string - convert err_mask to descriptive string + * @err_mask: error mask to convert to string + * + * Convert @err_mask to descriptive string. Errors are + * prioritized according to severity and only the most severe + * error is reported. + * + * LOCKING: + * None. + * + * RETURNS: + * Descriptive string for @err_mask + */ +static const char * ata_err_string(unsigned int err_mask) +{ + if (err_mask & AC_ERR_HOST_BUS) + return "host bus error"; + if (err_mask & AC_ERR_ATA_BUS) + return "ATA bus error"; + if (err_mask & AC_ERR_TIMEOUT) + return "timeout"; + if (err_mask & AC_ERR_HSM) + return "HSM violation"; + if (err_mask & AC_ERR_SYSTEM) + return "internal error"; + if (err_mask & AC_ERR_MEDIA) + return "media error"; + if (err_mask & AC_ERR_INVALID) + return "invalid argument"; + if (err_mask & AC_ERR_DEV) + return "device error"; + return "unknown error"; +} + +/** + * atapi_eh_request_sense - perform ATAPI REQUEST_SENSE + * @dev: device to perform REQUEST_SENSE to + * @sense_buf: result sense data buffer (SCSI_SENSE_BUFFERSIZE bytes long) + * + * Perform ATAPI REQUEST_SENSE after the device reported CHECK + * SENSE. This function is EH helper. + * + * LOCKING: + * Kernel thread context (may sleep). + * + * RETURNS: + * 0 on success, AC_ERR_* mask on failure + */ +static unsigned int atapi_eh_request_sense(struct ata_device *dev, + unsigned char *sense_buf) +{ + struct ata_port *ap = dev->ap; + struct ata_taskfile tf; + u8 cdb[ATAPI_CDB_LEN]; + + DPRINTK("ATAPI request sense\n"); + + ata_tf_init(dev, &tf); + + /* FIXME: is this needed? */ + memset(sense_buf, 0, SCSI_SENSE_BUFFERSIZE); + + /* XXX: why tf_read here? */ + ap->ops->tf_read(ap, &tf); + + /* fill these in, for the case where they are -not- overwritten */ + sense_buf[0] = 0x70; + sense_buf[2] = tf.feature >> 4; + + memset(cdb, 0, ATAPI_CDB_LEN); + cdb[0] = REQUEST_SENSE; + cdb[4] = SCSI_SENSE_BUFFERSIZE; + + tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; + tf.command = ATA_CMD_PACKET; + + /* is it pointless to prefer PIO for "safety reasons"? */ + if (ap->flags & ATA_FLAG_PIO_DMA) { + tf.protocol = ATA_PROT_ATAPI_DMA; + tf.feature |= ATAPI_PKT_DMA; + } else { + tf.protocol = ATA_PROT_ATAPI; + tf.lbam = (8 * 1024) & 0xff; + tf.lbah = (8 * 1024) >> 8; + } + + return ata_exec_internal(dev, &tf, cdb, DMA_FROM_DEVICE, + sense_buf, SCSI_SENSE_BUFFERSIZE); +} + +/** + * ata_eh_analyze_serror - analyze SError for a failed port + * @ap: ATA port to analyze SError for + * + * Analyze SError if available and further determine cause of + * failure. + * + * LOCKING: + * None. + */ +static void ata_eh_analyze_serror(struct ata_port *ap) +{ + struct ata_eh_context *ehc = &ap->eh_context; + u32 serror = ehc->i.serror; + unsigned int err_mask = 0, action = 0; + + if (serror & SERR_PERSISTENT) { + err_mask |= AC_ERR_ATA_BUS; + action |= ATA_EH_HARDRESET; + } + if (serror & + (SERR_DATA_RECOVERED | SERR_COMM_RECOVERED | SERR_DATA)) { + err_mask |= AC_ERR_ATA_BUS; + action |= ATA_EH_SOFTRESET; + } + if (serror & SERR_PROTOCOL) { + err_mask |= AC_ERR_HSM; + action |= ATA_EH_SOFTRESET; + } + if (serror & SERR_INTERNAL) { + err_mask |= AC_ERR_SYSTEM; + action |= ATA_EH_SOFTRESET; + } + if (serror & (SERR_PHYRDY_CHG | SERR_DEV_XCHG)) { + err_mask |= AC_ERR_ATA_BUS; + action |= ATA_EH_HARDRESET; + } + + ehc->i.err_mask |= err_mask; + ehc->i.action |= action; +} + +/** + * ata_eh_analyze_tf - analyze taskfile of a failed qc + * @qc: qc to analyze + * @tf: Taskfile registers to analyze + * + * Analyze taskfile of @qc and further determine cause of + * failure. This function also requests ATAPI sense data if + * avaliable. + * + * LOCKING: + * Kernel thread context (may sleep). + * + * RETURNS: + * Determined recovery action + */ +static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc, + const struct ata_taskfile *tf) +{ + unsigned int tmp, action = 0; + u8 stat = tf->command, err = tf->feature; + + if ((stat & (ATA_BUSY | ATA_DRQ | ATA_DRDY)) != ATA_DRDY) { + qc->err_mask |= AC_ERR_HSM; + return ATA_EH_SOFTRESET; + } + + if (!(qc->err_mask & AC_ERR_DEV)) + return 0; + + switch (qc->dev->class) { + case ATA_DEV_ATA: + if (err & ATA_ICRC) + qc->err_mask |= AC_ERR_ATA_BUS; + if (err & ATA_UNC) + qc->err_mask |= AC_ERR_MEDIA; + if (err & ATA_IDNF) + qc->err_mask |= AC_ERR_INVALID; + break; + + case ATA_DEV_ATAPI: + tmp = atapi_eh_request_sense(qc->dev, + qc->scsicmd->sense_buffer); + if (!tmp) { + /* ATA_QCFLAG_SENSE_VALID is used to tell + * atapi_qc_complete() that sense data is + * already valid. + * + * TODO: interpret sense data and set + * appropriate err_mask. + */ + qc->flags |= ATA_QCFLAG_SENSE_VALID; + } else + qc->err_mask |= tmp; + } + + if (qc->err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT | AC_ERR_ATA_BUS)) + action |= ATA_EH_SOFTRESET; + + return action; +} + +static int ata_eh_categorize_ering_entry(struct ata_ering_entry *ent) +{ + if (ent->err_mask & (AC_ERR_ATA_BUS | AC_ERR_TIMEOUT)) + return 1; + + if (ent->is_io) { + if (ent->err_mask & AC_ERR_HSM) + return 1; + if ((ent->err_mask & + (AC_ERR_DEV|AC_ERR_MEDIA|AC_ERR_INVALID)) == AC_ERR_DEV) + return 2; + } + + return 0; +} + +struct speed_down_needed_arg { + u64 since; + int nr_errors[3]; +}; + +static int speed_down_needed_cb(struct ata_ering_entry *ent, void *void_arg) +{ + struct speed_down_needed_arg *arg = void_arg; + + if (ent->timestamp < arg->since) + return -1; + + arg->nr_errors[ata_eh_categorize_ering_entry(ent)]++; + return 0; +} + +/** + * ata_eh_speed_down_needed - Determine wheter speed down is necessary + * @dev: Device of interest + * + * This function examines error ring of @dev and determines + * whether speed down is necessary. Speed down is necessary if + * there have been more than 3 of Cat-1 errors or 10 of Cat-2 + * errors during last 15 minutes. + * + * Cat-1 errors are ATA_BUS, TIMEOUT for any command and HSM + * violation for known supported commands. + * + * Cat-2 errors are unclassified DEV error for known supported + * command. + * + * LOCKING: + * Inherited from caller. + * + * RETURNS: + * 1 if speed down is necessary, 0 otherwise + */ +static int ata_eh_speed_down_needed(struct ata_device *dev) +{ + const u64 interval = 15LLU * 60 * HZ; + static const int err_limits[3] = { -1, 3, 10 }; + struct speed_down_needed_arg arg; + struct ata_ering_entry *ent; + int err_cat; + u64 j64; + + ent = ata_ering_top(&dev->ering); + if (!ent) + return 0; + + err_cat = ata_eh_categorize_ering_entry(ent); + if (err_cat == 0) + return 0; + + memset(&arg, 0, sizeof(arg)); + + j64 = get_jiffies_64(); + if (j64 >= interval) + arg.since = j64 - interval; + else + arg.since = 0; + + ata_ering_map(&dev->ering, speed_down_needed_cb, &arg); + + return arg.nr_errors[err_cat] > err_limits[err_cat]; +} + +/** + * ata_eh_speed_down - record error and speed down if necessary + * @dev: Failed device + * @is_io: Did the device fail during normal IO? + * @err_mask: err_mask of the error + * + * Record error and examine error history to determine whether + * adjusting transmission speed is necessary. It also sets + * transmission limits appropriately if such adjustment is + * necessary. + * + * LOCKING: + * Kernel thread context (may sleep). + * + * RETURNS: + * 0 on success, -errno otherwise + */ +static int ata_eh_speed_down(struct ata_device *dev, int is_io, + unsigned int err_mask) +{ + if (!err_mask) + return 0; + + /* record error and determine whether speed down is necessary */ + ata_ering_record(&dev->ering, is_io, err_mask); + + if (!ata_eh_speed_down_needed(dev)) + return 0; + + /* speed down SATA link speed if possible */ + if (sata_down_spd_limit(dev->ap) == 0) + return ATA_EH_HARDRESET; + + /* lower transfer mode */ + if (ata_down_xfermask_limit(dev, 0) == 0) + return ATA_EH_SOFTRESET; + + ata_dev_printk(dev, KERN_ERR, + "speed down requested but no transfer mode left\n"); + return 0; +} + +/** + * ata_eh_autopsy - analyze error and determine recovery action + * @ap: ATA port to perform autopsy on + * + * Analyze why @ap failed and determine which recovery action is + * needed. This function also sets more detailed AC_ERR_* values + * and fills sense data for ATAPI CHECK SENSE. + * + * LOCKING: + * Kernel thread context (may sleep). + */ +static void ata_eh_autopsy(struct ata_port *ap) +{ + struct ata_eh_context *ehc = &ap->eh_context; + unsigned int action = ehc->i.action; + struct ata_device *failed_dev = NULL; + unsigned int all_err_mask = 0; + int tag, is_io = 0; + u32 serror; + int rc; + + DPRINTK("ENTER\n"); + + /* obtain and analyze SError */ + rc = sata_scr_read(ap, SCR_ERROR, &serror); + if (rc == 0) { + ehc->i.serror |= serror; + ata_eh_analyze_serror(ap); + } else if (rc != -EOPNOTSUPP) + action |= ATA_EH_HARDRESET; + + /* any real error trumps AC_ERR_OTHER */ + if (ehc->i.err_mask & ~AC_ERR_OTHER) + ehc->i.err_mask &= ~AC_ERR_OTHER; + + all_err_mask |= ehc->i.err_mask; + + for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { + struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag); + + if (!(qc->flags & ATA_QCFLAG_FAILED)) + continue; + + /* inherit upper level err_mask */ + qc->err_mask |= ehc->i.err_mask; + + if (qc->err_mask & AC_ERR_TIMEOUT) + action |= ATA_EH_SOFTRESET; + + /* analyze TF */ + action |= ata_eh_analyze_tf(qc, &qc->result_tf); + + /* DEV errors are probably spurious in case of ATA_BUS error */ + if (qc->err_mask & AC_ERR_ATA_BUS) + qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_MEDIA | + AC_ERR_INVALID); + + /* any real error trumps unknown error */ + if (qc->err_mask & ~AC_ERR_OTHER) + qc->err_mask &= ~AC_ERR_OTHER; + + /* SENSE_VALID trumps dev/unknown error and revalidation */ + if (qc->flags & ATA_QCFLAG_SENSE_VALID) { + qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_OTHER); + action &= ~ATA_EH_REVALIDATE; + } + + /* accumulate error info */ + failed_dev = qc->dev; + all_err_mask |= qc->err_mask; + if (qc->flags & ATA_QCFLAG_IO) + is_io = 1; + } + + /* speed down iff command was in progress */ + if (failed_dev) + action |= ata_eh_speed_down(failed_dev, is_io, all_err_mask); + + if (all_err_mask) + action |= ATA_EH_REVALIDATE; + + ehc->i.dev = failed_dev; + ehc->i.action = action; + + DPRINTK("EXIT\n"); +} + +/** + * ata_eh_report - report error handling to user + * @ap: ATA port EH is going on + * + * Report EH to user. + * + * LOCKING: + * None. + */ +static void ata_eh_report(struct ata_port *ap) +{ + struct ata_eh_context *ehc = &ap->eh_context; + const char *frozen, *desc; + int tag, nr_failed = 0; + + desc = NULL; + if (ehc->i.desc[0] != '\0') + desc = ehc->i.desc; + + for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { + struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag); + + if (!(qc->flags & ATA_QCFLAG_FAILED)) + continue; + if (qc->flags & ATA_QCFLAG_SENSE_VALID && !qc->err_mask) + continue; + + nr_failed++; + } + + if (!nr_failed && !ehc->i.err_mask) + return; + + frozen = ""; + if (ap->flags & ATA_FLAG_FROZEN) + frozen = " frozen"; + + if (ehc->i.dev) { + ata_dev_printk(ehc->i.dev, KERN_ERR, + "exception Emask 0x%x SErr 0x%x action 0x%x%s\n", + ehc->i.err_mask, ehc->i.serror, ehc->i.action, + frozen); + if (desc) + ata_dev_printk(ehc->i.dev, KERN_ERR, "(%s)\n", desc); + } else { + ata_port_printk(ap, KERN_ERR, + "exception Emask 0x%x SErr 0x%x action 0x%x%s\n", + ehc->i.err_mask, ehc->i.serror, ehc->i.action, + frozen); + if (desc) + ata_port_printk(ap, KERN_ERR, "(%s)\n", desc); + } + + for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { + struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag); + + if (!(qc->flags & ATA_QCFLAG_FAILED) || !qc->err_mask) + continue; + + ata_dev_printk(qc->dev, KERN_ERR, "tag %d cmd 0x%x " + "Emask 0x%x stat 0x%x err 0x%x (%s)\n", + qc->tag, qc->tf.command, qc->err_mask, + qc->result_tf.command, qc->result_tf.feature, + ata_err_string(qc->err_mask)); + } +} + +static int ata_eh_reset(struct ata_port *ap, ata_reset_fn_t softreset, + ata_reset_fn_t hardreset, ata_postreset_fn_t postreset) +{ + struct ata_eh_context *ehc = &ap->eh_context; + unsigned int classes[ATA_MAX_DEVICES]; + int tries = ATA_EH_RESET_TRIES; + ata_reset_fn_t reset; + int rc; + + if (softreset && (!hardreset || (!sata_set_spd_needed(ap) && + !(ehc->i.action & ATA_EH_HARDRESET)))) + reset = softreset; + else + reset = hardreset; + + retry: + ata_port_printk(ap, KERN_INFO, "%s resetting port\n", + reset == softreset ? "soft" : "hard"); + + /* reset */ + ata_eh_about_to_do(ap, ATA_EH_RESET_MASK); + ehc->i.flags |= ATA_EHI_DID_RESET; + + rc = ata_do_reset(ap, reset, classes); + + if (rc && --tries) { + ata_port_printk(ap, KERN_WARNING, + "%sreset failed, retrying in 5 secs\n", + reset == softreset ? "soft" : "hard"); + ssleep(5); + + if (reset == hardreset) + sata_down_spd_limit(ap); + if (hardreset) + reset = hardreset; + goto retry; + } + + if (rc == 0) { + if (postreset) + postreset(ap, classes); + + /* reset successful, schedule revalidation */ + ehc->i.dev = NULL; + ehc->i.action &= ~ATA_EH_RESET_MASK; + ehc->i.action |= ATA_EH_REVALIDATE; + } + + return rc; +} + +static int ata_eh_revalidate(struct ata_port *ap, + struct ata_device **r_failed_dev) +{ + struct ata_eh_context *ehc = &ap->eh_context; + struct ata_device *dev; + int i, rc = 0; + + DPRINTK("ENTER\n"); + + for (i = 0; i < ATA_MAX_DEVICES; i++) { + dev = &ap->device[i]; + + if (ehc->i.action & ATA_EH_REVALIDATE && ata_dev_enabled(dev) && + (!ehc->i.dev || ehc->i.dev == dev)) { + if (ata_port_offline(ap)) { + rc = -EIO; + break; + } + + ata_eh_about_to_do(ap, ATA_EH_REVALIDATE); + rc = ata_dev_revalidate(dev, + ehc->i.flags & ATA_EHI_DID_RESET); + if (rc) + break; + + ehc->i.action &= ~ATA_EH_REVALIDATE; + } + } + + if (rc) + *r_failed_dev = dev; + + DPRINTK("EXIT\n"); + return rc; +} + +static int ata_port_nr_enabled(struct ata_port *ap) +{ + int i, cnt = 0; + + for (i = 0; i < ATA_MAX_DEVICES; i++) + if (ata_dev_enabled(&ap->device[i])) + cnt++; + return cnt; +} + +/** + * ata_eh_recover - recover host port after error + * @ap: host port to recover + * @softreset: softreset method (can be NULL) + * @hardreset: hardreset method (can be NULL) + * @postreset: postreset method (can be NULL) + * + * This is the alpha and omega, eum and yang, heart and soul of + * libata exception handling. On entry, actions required to + * recover each devices are recorded in eh_context. This + * function executes all the operations with appropriate retrials + * and fallbacks to resurrect failed devices. + * + * LOCKING: + * Kernel thread context (may sleep). + * + * RETURNS: + * 0 on success, -errno on failure. + */ +static int ata_eh_recover(struct ata_port *ap, ata_reset_fn_t softreset, + ata_reset_fn_t hardreset, + ata_postreset_fn_t postreset) +{ + struct ata_eh_context *ehc = &ap->eh_context; + struct ata_device *dev; + int down_xfermask, i, rc; + + DPRINTK("ENTER\n"); + + /* prep for recovery */ + for (i = 0; i < ATA_MAX_DEVICES; i++) { + dev = &ap->device[i]; + + ehc->tries[dev->devno] = ATA_EH_DEV_TRIES; + } + + retry: + down_xfermask = 0; + rc = 0; + + /* skip EH if possible. */ + if (!ata_port_nr_enabled(ap) && !(ap->flags & ATA_FLAG_FROZEN)) + ehc->i.action = 0; + + /* reset */ + if (ehc->i.action & ATA_EH_RESET_MASK) { + ata_eh_freeze_port(ap); + + rc = ata_eh_reset(ap, softreset, hardreset, postreset); + if (rc) { + ata_port_printk(ap, KERN_ERR, + "reset failed, giving up\n"); + goto out; + } + + ata_eh_thaw_port(ap); + } + + /* revalidate existing devices */ + rc = ata_eh_revalidate(ap, &dev); + if (rc) + goto dev_fail; + + /* configure transfer mode if the port has been reset */ + if (ehc->i.flags & ATA_EHI_DID_RESET) { + rc = ata_set_mode(ap, &dev); + if (rc) { + down_xfermask = 1; + goto dev_fail; + } + } + + goto out; + + dev_fail: + switch (rc) { + case -ENODEV: + case -EINVAL: + ehc->tries[dev->devno] = 0; + break; + case -EIO: + sata_down_spd_limit(ap); + default: + ehc->tries[dev->devno]--; + if (down_xfermask && + ata_down_xfermask_limit(dev, ehc->tries[dev->devno] == 1)) + ehc->tries[dev->devno] = 0; + } + + /* disable device if it has used up all its chances */ + if (ata_dev_enabled(dev) && !ehc->tries[dev->devno]) + ata_dev_disable(dev); + + /* soft didn't work? be haaaaard */ + if (ehc->i.flags & ATA_EHI_DID_RESET) + ehc->i.action |= ATA_EH_HARDRESET; + else + ehc->i.action |= ATA_EH_SOFTRESET; + + if (ata_port_nr_enabled(ap)) { + ata_port_printk(ap, KERN_WARNING, "failed to recover some " + "devices, retrying in 5 secs\n"); + ssleep(5); + } else { + /* no device left, repeat fast */ + msleep(500); + } + + goto retry; + + out: + if (rc) { + for (i = 0; i < ATA_MAX_DEVICES; i++) + ata_dev_disable(&ap->device[i]); + } + + DPRINTK("EXIT, rc=%d\n", rc); + return rc; +} + +/** + * ata_eh_finish - finish up EH + * @ap: host port to finish EH for + * + * Recovery is complete. Clean up EH states and retry or finish + * failed qcs. + * + * LOCKING: + * None. + */ +static void ata_eh_finish(struct ata_port *ap) +{ + int tag; + + /* retry or finish qcs */ + for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { + struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag); + + if (!(qc->flags & ATA_QCFLAG_FAILED)) + continue; + + if (qc->err_mask) { + /* FIXME: Once EH migration is complete, + * generate sense data in this function, + * considering both err_mask and tf. + */ + if (qc->err_mask & AC_ERR_INVALID) + ata_eh_qc_complete(qc); + else + ata_eh_qc_retry(qc); + } else { + if (qc->flags & ATA_QCFLAG_SENSE_VALID) { + ata_eh_qc_complete(qc); + } else { + /* feed zero TF to sense generation */ + memset(&qc->result_tf, 0, sizeof(qc->result_tf)); + ata_eh_qc_retry(qc); + } + } + } +} + +/** + * ata_do_eh - do standard error handling + * @ap: host port to handle error for + * @softreset: softreset method (can be NULL) + * @hardreset: hardreset method (can be NULL) + * @postreset: postreset method (can be NULL) + * + * Perform standard error handling sequence. + * + * LOCKING: + * Kernel thread context (may sleep). + */ +void ata_do_eh(struct ata_port *ap, ata_reset_fn_t softreset, + ata_reset_fn_t hardreset, ata_postreset_fn_t postreset) +{ + ata_eh_autopsy(ap); + ata_eh_report(ap); + ata_eh_recover(ap, softreset, hardreset, postreset); + ata_eh_finish(ap); +} diff --git a/include/linux/libata.h b/include/linux/libata.h index 298f9918e37..9fe46073cf8 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -247,6 +247,8 @@ enum { /* how hard are we gonna try to probe/recover devices */ ATA_PROBE_MAX_TRIES = 3, + ATA_EH_RESET_TRIES = 3, + ATA_EH_DEV_TRIES = 3, }; enum hsm_task_states { @@ -727,6 +729,9 @@ extern void ata_eh_thaw_port(struct ata_port *ap); extern void ata_eh_qc_complete(struct ata_queued_cmd *qc); extern void ata_eh_qc_retry(struct ata_queued_cmd *qc); +extern void ata_do_eh(struct ata_port *ap, ata_reset_fn_t softreset, + ata_reset_fn_t hardreset, ata_postreset_fn_t postreset); + /* * printk helpers */ -- cgit v1.2.3 From 6d97dbd72da31a0e334f251fa9df4be9fab6fde2 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:58:24 +0900 Subject: [PATCH] libata-eh: implement BMDMA EH Implement stock BMDMA error handling methods. Signed-off-by: Tejun Heo --- drivers/scsi/libata-bmdma.c | 144 ++++++++++++++++++++++++++++++++++++++++++++ drivers/scsi/libata-core.c | 5 ++ include/linux/libata.h | 8 +++ 3 files changed, 157 insertions(+) diff --git a/drivers/scsi/libata-bmdma.c b/drivers/scsi/libata-bmdma.c index 835dff0bafd..49eff18a67e 100644 --- a/drivers/scsi/libata-bmdma.c +++ b/drivers/scsi/libata-bmdma.c @@ -652,6 +652,150 @@ void ata_bmdma_stop(struct ata_queued_cmd *qc) ata_altstatus(ap); /* dummy read */ } +/** + * ata_bmdma_freeze - Freeze BMDMA controller port + * @ap: port to freeze + * + * Freeze BMDMA controller port. + * + * LOCKING: + * Inherited from caller. + */ +void ata_bmdma_freeze(struct ata_port *ap) +{ + struct ata_ioports *ioaddr = &ap->ioaddr; + + ap->ctl |= ATA_NIEN; + ap->last_ctl = ap->ctl; + + if (ap->flags & ATA_FLAG_MMIO) + writeb(ap->ctl, (void __iomem *)ioaddr->ctl_addr); + else + outb(ap->ctl, ioaddr->ctl_addr); +} + +/** + * ata_bmdma_thaw - Thaw BMDMA controller port + * @ap: port to thaw + * + * Thaw BMDMA controller port. + * + * LOCKING: + * Inherited from caller. + */ +void ata_bmdma_thaw(struct ata_port *ap) +{ + /* clear & re-enable interrupts */ + ata_chk_status(ap); + ap->ops->irq_clear(ap); + if (ap->ioaddr.ctl_addr) /* FIXME: hack. create a hook instead */ + ata_irq_on(ap); +} + +/** + * ata_bmdma_drive_eh - Perform EH with given methods for BMDMA controller + * @ap: port to handle error for + * @softreset: softreset method (can be NULL) + * @hardreset: hardreset method (can be NULL) + * @postreset: postreset method (can be NULL) + * + * Handle error for ATA BMDMA controller. It can handle both + * PATA and SATA controllers. Many controllers should be able to + * use this EH as-is or with some added handling before and + * after. + * + * This function is intended to be used for constructing + * ->error_handler callback by low level drivers. + * + * LOCKING: + * Kernel thread context (may sleep) + */ +void ata_bmdma_drive_eh(struct ata_port *ap, ata_reset_fn_t softreset, + ata_reset_fn_t hardreset, ata_postreset_fn_t postreset) +{ + struct ata_host_set *host_set = ap->host_set; + struct ata_eh_context *ehc = &ap->eh_context; + struct ata_queued_cmd *qc; + unsigned long flags; + int thaw = 0; + + qc = __ata_qc_from_tag(ap, ap->active_tag); + if (qc && !(qc->flags & ATA_QCFLAG_FAILED)) + qc = NULL; + + /* reset PIO HSM and stop DMA engine */ + spin_lock_irqsave(&host_set->lock, flags); + + ap->flags &= ~ATA_FLAG_NOINTR; + ap->hsm_task_state = HSM_ST_IDLE; + + if (qc && (qc->tf.protocol == ATA_PROT_DMA || + qc->tf.protocol == ATA_PROT_ATAPI_DMA)) { + u8 host_stat; + + host_stat = ata_bmdma_status(ap); + + ata_ehi_push_desc(&ehc->i, "BMDMA stat 0x%x", host_stat); + + /* BMDMA controllers indicate host bus error by + * setting DMA_ERR bit and timing out. As it wasn't + * really a timeout event, adjust error mask and + * cancel frozen state. + */ + if (qc->err_mask == AC_ERR_TIMEOUT && host_stat & ATA_DMA_ERR) { + qc->err_mask = AC_ERR_HOST_BUS; + thaw = 1; + } + + ap->ops->bmdma_stop(qc); + } + + ata_altstatus(ap); + ata_chk_status(ap); + ap->ops->irq_clear(ap); + + spin_unlock_irqrestore(&host_set->lock, flags); + + if (thaw) + ata_eh_thaw_port(ap); + + /* PIO and DMA engines have been stopped, perform recovery */ + ata_do_eh(ap, softreset, hardreset, postreset); +} + +/** + * ata_bmdma_error_handler - Stock error handler for BMDMA controller + * @ap: port to handle error for + * + * Stock error handler for BMDMA controller. + * + * LOCKING: + * Kernel thread context (may sleep) + */ +void ata_bmdma_error_handler(struct ata_port *ap) +{ + ata_reset_fn_t hardreset; + + hardreset = NULL; + if (sata_scr_valid(ap)) + hardreset = sata_std_hardreset; + + ata_bmdma_drive_eh(ap, ata_std_softreset, hardreset, ata_std_postreset); +} + +/** + * ata_bmdma_post_internal_cmd - Stock post_internal_cmd for + * BMDMA controller + * @qc: internal command to clean up + * + * LOCKING: + * Kernel thread context (may sleep) + */ +void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc) +{ + ata_bmdma_stop(qc); +} + #ifdef CONFIG_PCI static struct ata_probe_ent * ata_probe_ent_alloc(struct device *dev, const struct ata_port_info *port) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index ddc47097d37..2969599ec0b 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -5377,6 +5377,11 @@ EXPORT_SYMBOL_GPL(ata_bmdma_start); EXPORT_SYMBOL_GPL(ata_bmdma_irq_clear); EXPORT_SYMBOL_GPL(ata_bmdma_status); EXPORT_SYMBOL_GPL(ata_bmdma_stop); +EXPORT_SYMBOL_GPL(ata_bmdma_freeze); +EXPORT_SYMBOL_GPL(ata_bmdma_thaw); +EXPORT_SYMBOL_GPL(ata_bmdma_drive_eh); +EXPORT_SYMBOL_GPL(ata_bmdma_error_handler); +EXPORT_SYMBOL_GPL(ata_bmdma_post_internal_cmd); EXPORT_SYMBOL_GPL(ata_port_probe); EXPORT_SYMBOL_GPL(sata_set_spd); EXPORT_SYMBOL_GPL(sata_phy_reset); diff --git a/include/linux/libata.h b/include/linux/libata.h index 9fe46073cf8..6ccacbf889e 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -661,6 +661,14 @@ extern void ata_bmdma_start (struct ata_queued_cmd *qc); extern void ata_bmdma_stop(struct ata_queued_cmd *qc); extern u8 ata_bmdma_status(struct ata_port *ap); extern void ata_bmdma_irq_clear(struct ata_port *ap); +extern void ata_bmdma_freeze(struct ata_port *ap); +extern void ata_bmdma_thaw(struct ata_port *ap); +extern void ata_bmdma_drive_eh(struct ata_port *ap, + ata_reset_fn_t softreset, + ata_reset_fn_t hardreset, + ata_postreset_fn_t postreset); +extern void ata_bmdma_error_handler(struct ata_port *ap); +extern void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc); extern void ata_qc_complete(struct ata_queued_cmd *qc); extern void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)); -- cgit v1.2.3 From 3f037db0ba043022e43e8e7266e698d4af264851 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:58:25 +0900 Subject: [PATCH] ata_piix: convert to new EH ata_piix can use stock BMDMA EH routines. Convert to new EH. Signed-off-by: Tejun Heo --- drivers/scsi/ata_piix.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index af1d46e3610..e3184a77a60 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -243,7 +243,10 @@ static const struct ata_port_operations piix_pata_ops = { .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, + .freeze = ata_bmdma_freeze, + .thaw = ata_bmdma_thaw, + .error_handler = ata_bmdma_error_handler, + .post_internal_cmd = ata_bmdma_post_internal_cmd, .irq_handler = ata_interrupt, .irq_clear = ata_bmdma_irq_clear, @@ -271,7 +274,10 @@ static const struct ata_port_operations piix_sata_ops = { .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, + .freeze = ata_bmdma_freeze, + .thaw = ata_bmdma_thaw, + .error_handler = ata_bmdma_error_handler, + .post_internal_cmd = ata_bmdma_post_internal_cmd, .irq_handler = ata_interrupt, .irq_clear = ata_bmdma_irq_clear, -- cgit v1.2.3 From f6aae27ed002ba9c0a98aff811dbde32ce749d28 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:58:27 +0900 Subject: [PATCH] sata_sil: convert to new EH Convert sata_sil to new EH. As these controllers have hardware interrupt mask and are known to have screaming interrupts issues, use hardware IRQ masking for freezing. sil_freeze() masks interrupts for the port and sil_thaw() unmasks them. As ports are automatically frozen before probing reset, there is no need to initialize interrupt masks sil_init_onde(). Remove related code. Other than freezing, sata_sil uses stock BMDMA EH routines. Signed-off-by: Tejun Heo --- drivers/scsi/sata_sil.c | 49 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index bfcece18a7c..aa63044eed2 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -96,6 +96,8 @@ static void sil_dev_config(struct ata_port *ap, struct ata_device *dev); static u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg); static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); static void sil_post_set_mode (struct ata_port *ap); +static void sil_freeze(struct ata_port *ap); +static void sil_thaw(struct ata_port *ap); static const struct pci_device_id sil_pci_tbl[] = { @@ -174,7 +176,10 @@ static const struct ata_port_operations sil_ops = { .bmdma_status = ata_bmdma_status, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, + .freeze = sil_freeze, + .thaw = sil_thaw, + .error_handler = ata_bmdma_error_handler, + .post_internal_cmd = ata_bmdma_post_internal_cmd, .irq_handler = ata_interrupt, .irq_clear = ata_bmdma_irq_clear, .scr_read = sil_scr_read, @@ -314,6 +319,33 @@ static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val) writel(val, mmio); } +static void sil_freeze(struct ata_port *ap) +{ + void __iomem *mmio_base = ap->host_set->mmio_base; + u32 tmp; + + /* plug IRQ */ + tmp = readl(mmio_base + SIL_SYSCFG); + tmp |= SIL_MASK_IDE0_INT << ap->port_no; + writel(tmp, mmio_base + SIL_SYSCFG); + readl(mmio_base + SIL_SYSCFG); /* flush */ +} + +static void sil_thaw(struct ata_port *ap) +{ + void __iomem *mmio_base = ap->host_set->mmio_base; + u32 tmp; + + /* clear IRQ */ + ata_chk_status(ap); + ata_bmdma_irq_clear(ap); + + /* turn on IRQ */ + tmp = readl(mmio_base + SIL_SYSCFG); + tmp &= ~(SIL_MASK_IDE0_INT << ap->port_no); + writel(tmp, mmio_base + SIL_SYSCFG); +} + /** * sil_dev_config - Apply device/host-specific errata fixups * @ap: Port containing device to be examined @@ -384,7 +416,7 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) int rc; unsigned int i; int pci_dev_busy = 0; - u32 tmp, irq_mask; + u32 tmp; u8 cls; if (!printed_version++) @@ -474,24 +506,11 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) } if (ent->driver_data == sil_3114) { - irq_mask = SIL_MASK_4PORT; - /* flip the magic "make 4 ports work" bit */ tmp = readl(mmio_base + sil_port[2].bmdma); if ((tmp & SIL_INTR_STEERING) == 0) writel(tmp | SIL_INTR_STEERING, mmio_base + sil_port[2].bmdma); - - } else { - irq_mask = SIL_MASK_2PORT; - } - - /* make sure IDE0/1/2/3 interrupts are not masked */ - tmp = readl(mmio_base + SIL_SYSCFG); - if (tmp & irq_mask) { - tmp &= ~irq_mask; - writel(tmp, mmio_base + SIL_SYSCFG); - readl(mmio_base + SIL_SYSCFG); /* flush */ } /* mask all SATA phy-related interrupts */ -- cgit v1.2.3 From 78cd52d02fa0735949a9fa30a6b79bf02c94c250 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:58:29 +0900 Subject: [PATCH] ahci: convert to new EH Convert AHCI to new EH. Unfortunately, ICH7 AHCI reacts badly if IRQ mask is diddled during operation. So, freezing is implemented by unconditionally clearing interrupt conditions while frozen. * Interrupts are categorized according to required action. e.g. Connection status or unknown FIS error requires freezing the port while TF or HBUS_DATA don't. * Only CONNECT (reflects SErr.X) interrupt is taken into account not PHYRDY (SErr.N), as CONNECT is better cue for starting EH. * AHCI may be invoked without any active command. e.g. CONNECT irq occuring while no qc in progress still triggers EH and will reset the port and revalidate attached device. Signed-off-by: Tejun Heo --- drivers/scsi/ahci.c | 237 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 137 insertions(+), 100 deletions(-) diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index a4fb8d0a6c0..d6894bd6798 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -71,6 +71,7 @@ enum { AHCI_CMD_CLR_BUSY = (1 << 10), RX_FIS_D2H_REG = 0x40, /* offset of D2H Register FIS data */ + RX_FIS_UNK = 0x60, /* offset of Unknown FIS data */ board_ahci = 0, board_ahci_vt8251 = 1, @@ -128,15 +129,16 @@ enum { PORT_IRQ_PIOS_FIS = (1 << 1), /* PIO Setup FIS rx'd */ PORT_IRQ_D2H_REG_FIS = (1 << 0), /* D2H Register FIS rx'd */ - PORT_IRQ_FATAL = PORT_IRQ_TF_ERR | - PORT_IRQ_HBUS_ERR | - PORT_IRQ_HBUS_DATA_ERR | - PORT_IRQ_IF_ERR, - DEF_PORT_IRQ = PORT_IRQ_FATAL | PORT_IRQ_PHYRDY | - PORT_IRQ_CONNECT | PORT_IRQ_SG_DONE | - PORT_IRQ_UNK_FIS | PORT_IRQ_SDB_FIS | - PORT_IRQ_DMAS_FIS | PORT_IRQ_PIOS_FIS | - PORT_IRQ_D2H_REG_FIS, + PORT_IRQ_FREEZE = PORT_IRQ_HBUS_ERR | + PORT_IRQ_IF_ERR | + PORT_IRQ_CONNECT | + PORT_IRQ_UNK_FIS, + PORT_IRQ_ERROR = PORT_IRQ_FREEZE | + PORT_IRQ_TF_ERR | + PORT_IRQ_HBUS_DATA_ERR, + DEF_PORT_IRQ = PORT_IRQ_ERROR | PORT_IRQ_SG_DONE | + PORT_IRQ_SDB_FIS | PORT_IRQ_DMAS_FIS | + PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS, /* PORT_CMD bits */ PORT_CMD_ATAPI = (1 << 24), /* Device is ATAPI */ @@ -197,13 +199,15 @@ static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc); static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *regs); static int ahci_probe_reset(struct ata_port *ap, unsigned int *classes); static void ahci_irq_clear(struct ata_port *ap); -static void ahci_eng_timeout(struct ata_port *ap); static int ahci_port_start(struct ata_port *ap); static void ahci_port_stop(struct ata_port *ap); static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf); static void ahci_qc_prep(struct ata_queued_cmd *qc); static u8 ahci_check_status(struct ata_port *ap); -static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc); +static void ahci_freeze(struct ata_port *ap); +static void ahci_thaw(struct ata_port *ap); +static void ahci_error_handler(struct ata_port *ap); +static void ahci_post_internal_cmd(struct ata_queued_cmd *qc); static void ahci_remove_one (struct pci_dev *pdev); static struct scsi_host_template ahci_sht = { @@ -237,14 +241,18 @@ static const struct ata_port_operations ahci_ops = { .qc_prep = ahci_qc_prep, .qc_issue = ahci_qc_issue, - .eng_timeout = ahci_eng_timeout, - .irq_handler = ahci_interrupt, .irq_clear = ahci_irq_clear, .scr_read = ahci_scr_read, .scr_write = ahci_scr_write, + .freeze = ahci_freeze, + .thaw = ahci_thaw, + + .error_handler = ahci_error_handler, + .post_internal_cmd = ahci_post_internal_cmd, + .port_start = ahci_port_start, .port_stop = ahci_port_stop, }; @@ -789,108 +797,97 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc) ahci_fill_cmd_slot(pp, opts); } -static void ahci_restart_port(struct ata_port *ap, u32 irq_stat) +static void ahci_error_intr(struct ata_port *ap, u32 irq_stat) { - void __iomem *mmio = ap->host_set->mmio_base; - void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); - u32 tmp; + struct ahci_port_priv *pp = ap->private_data; + struct ata_eh_info *ehi = &ap->eh_info; + unsigned int err_mask = 0, action = 0; + struct ata_queued_cmd *qc; + u32 serror; - if ((ap->device[0].class != ATA_DEV_ATAPI) || - ((irq_stat & PORT_IRQ_TF_ERR) == 0)) - ata_port_printk(ap, KERN_WARNING, "port reset, " - "p_is %x is %x pis %x cmd %x tf %x ss %x se %x\n", - irq_stat, - readl(mmio + HOST_IRQ_STAT), - readl(port_mmio + PORT_IRQ_STAT), - readl(port_mmio + PORT_CMD), - readl(port_mmio + PORT_TFDATA), - readl(port_mmio + PORT_SCR_STAT), - readl(port_mmio + PORT_SCR_ERR)); - - /* stop DMA */ - ahci_stop_engine(ap); + ata_ehi_clear_desc(ehi); - /* clear SATA phy error, if any */ - tmp = readl(port_mmio + PORT_SCR_ERR); - writel(tmp, port_mmio + PORT_SCR_ERR); + /* AHCI needs SError cleared; otherwise, it might lock up */ + serror = ahci_scr_read(ap, SCR_ERROR); + ahci_scr_write(ap, SCR_ERROR, serror); - /* if DRQ/BSY is set, device needs to be reset. - * if so, issue COMRESET - */ - tmp = readl(port_mmio + PORT_TFDATA); - if (tmp & (ATA_BUSY | ATA_DRQ)) { - writel(0x301, port_mmio + PORT_SCR_CTL); - readl(port_mmio + PORT_SCR_CTL); /* flush */ - udelay(10); - writel(0x300, port_mmio + PORT_SCR_CTL); - readl(port_mmio + PORT_SCR_CTL); /* flush */ + /* analyze @irq_stat */ + ata_ehi_push_desc(ehi, "irq_stat 0x%08x", irq_stat); + + if (irq_stat & PORT_IRQ_TF_ERR) + err_mask |= AC_ERR_DEV; + + if (irq_stat & (PORT_IRQ_HBUS_ERR | PORT_IRQ_HBUS_DATA_ERR)) { + err_mask |= AC_ERR_HOST_BUS; + action |= ATA_EH_SOFTRESET; } - /* re-start DMA */ - ahci_start_engine(ap); -} + if (irq_stat & PORT_IRQ_IF_ERR) { + err_mask |= AC_ERR_ATA_BUS; + action |= ATA_EH_SOFTRESET; + ata_ehi_push_desc(ehi, ", interface fatal error"); + } -static void ahci_eng_timeout(struct ata_port *ap) -{ - struct ata_host_set *host_set = ap->host_set; - void __iomem *mmio = host_set->mmio_base; - void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); - struct ata_queued_cmd *qc; - unsigned long flags; + if (irq_stat & (PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY)) { + err_mask |= AC_ERR_ATA_BUS; + action |= ATA_EH_SOFTRESET; + ata_ehi_push_desc(ehi, ", %s", irq_stat & PORT_IRQ_CONNECT ? + "connection status changed" : "PHY RDY changed"); + } + + if (irq_stat & PORT_IRQ_UNK_FIS) { + u32 *unk = (u32 *)(pp->rx_fis + RX_FIS_UNK); - ata_port_printk(ap, KERN_WARNING, "handling error/timeout\n"); + err_mask |= AC_ERR_HSM; + action |= ATA_EH_SOFTRESET; + ata_ehi_push_desc(ehi, ", unknown FIS %08x %08x %08x %08x", + unk[0], unk[1], unk[2], unk[3]); + } - spin_lock_irqsave(&host_set->lock, flags); + /* okay, let's hand over to EH */ + ehi->serror |= serror; + ehi->action |= action; - ahci_restart_port(ap, readl(port_mmio + PORT_IRQ_STAT)); qc = ata_qc_from_tag(ap, ap->active_tag); - qc->err_mask |= AC_ERR_TIMEOUT; - - spin_unlock_irqrestore(&host_set->lock, flags); + if (qc) + qc->err_mask |= err_mask; + else + ehi->err_mask |= err_mask; - ata_eh_qc_complete(qc); + if (irq_stat & PORT_IRQ_FREEZE) + ata_port_freeze(ap); + else + ata_port_abort(ap); } -static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc) +static void ahci_host_intr(struct ata_port *ap) { void __iomem *mmio = ap->host_set->mmio_base; void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); - u32 status, serr, ci; - - serr = readl(port_mmio + PORT_SCR_ERR); - writel(serr, port_mmio + PORT_SCR_ERR); + struct ata_queued_cmd *qc; + u32 status, ci; status = readl(port_mmio + PORT_IRQ_STAT); writel(status, port_mmio + PORT_IRQ_STAT); - ci = readl(port_mmio + PORT_CMD_ISSUE); - if (likely((ci & 0x1) == 0)) { - if (qc) { - WARN_ON(qc->err_mask); - ata_qc_complete(qc); - qc = NULL; - } + if (unlikely(status & PORT_IRQ_ERROR)) { + ahci_error_intr(ap, status); + return; } - if (status & PORT_IRQ_FATAL) { - unsigned int err_mask; - if (status & PORT_IRQ_TF_ERR) - err_mask = AC_ERR_DEV; - else if (status & PORT_IRQ_IF_ERR) - err_mask = AC_ERR_ATA_BUS; - else - err_mask = AC_ERR_HOST_BUS; - - /* command processing has stopped due to error; restart */ - ahci_restart_port(ap, status); - - if (qc) { - qc->err_mask |= err_mask; + if ((qc = ata_qc_from_tag(ap, ap->active_tag))) { + ci = readl(port_mmio + PORT_CMD_ISSUE); + if ((ci & 0x1) == 0) { ata_qc_complete(qc); + return; } } - return 1; + /* spurious interrupt */ + if (ata_ratelimit()) + ata_port_printk(ap, KERN_INFO, "spurious interrupt " + "(irq_stat 0x%x active_tag %d)\n", + status, ap->active_tag); } static void ahci_irq_clear(struct ata_port *ap) @@ -927,14 +924,7 @@ static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs * ap = host_set->ports[i]; if (ap) { - struct ata_queued_cmd *qc; - qc = ata_qc_from_tag(ap, ap->active_tag); - if (!ahci_host_intr(ap, qc)) - if (ata_ratelimit()) - dev_printk(KERN_WARNING, host_set->dev, - "unhandled interrupt on port %u\n", - i); - + ahci_host_intr(ap); VPRINTK("port %u\n", i); } else { VPRINTK("port %u (no irq)\n", i); @@ -951,7 +941,7 @@ static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs * handled = 1; } - spin_unlock(&host_set->lock); + spin_unlock(&host_set->lock); VPRINTK("EXIT\n"); @@ -969,6 +959,56 @@ static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc) return 0; } +static void ahci_freeze(struct ata_port *ap) +{ + void __iomem *mmio = ap->host_set->mmio_base; + void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); + + /* turn IRQ off */ + writel(0, port_mmio + PORT_IRQ_MASK); +} + +static void ahci_thaw(struct ata_port *ap) +{ + void __iomem *mmio = ap->host_set->mmio_base; + void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); + u32 tmp; + + /* clear IRQ */ + tmp = readl(port_mmio + PORT_IRQ_STAT); + writel(tmp, port_mmio + PORT_IRQ_STAT); + writel(1 << ap->id, mmio + HOST_IRQ_STAT); + + /* turn IRQ back on */ + writel(DEF_PORT_IRQ, port_mmio + PORT_IRQ_MASK); +} + +static void ahci_error_handler(struct ata_port *ap) +{ + if (!(ap->flags & ATA_FLAG_FROZEN)) { + /* restart engine */ + ahci_stop_engine(ap); + ahci_start_engine(ap); + } + + /* perform recovery */ + ata_do_eh(ap, ahci_softreset, ahci_hardreset, ahci_postreset); +} + +static void ahci_post_internal_cmd(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + + if (qc->flags & ATA_QCFLAG_FAILED) + qc->err_mask |= AC_ERR_OTHER; + + if (qc->err_mask) { + /* make DMA engine forget about the failed command */ + ahci_stop_engine(ap); + ahci_start_engine(ap); + } +} + static void ahci_setup_port(struct ata_ioports *port, unsigned long base, unsigned int port_idx) { @@ -1113,9 +1153,6 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent) writel(tmp, port_mmio + PORT_IRQ_STAT); writel(1 << i, mmio + HOST_IRQ_STAT); - - /* set irq mask (enables interrupts) */ - writel(DEF_PORT_IRQ, port_mmio + PORT_IRQ_MASK); } tmp = readl(mmio + HOST_CTL); -- cgit v1.2.3 From 2a3917a8bb40a2cb75b458da9c356e8557e8fbed Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:58:30 +0900 Subject: [PATCH] ahci: add PIOS interim interrupt handling During multiblock PIO, multiple PIOS interrupts are generated before qc compltion. Current code prints unnecessary message for such cases. This is exposed when new EH slows down attached device into PIO mode. Signed-off-by: Tejun Heo --- drivers/scsi/ahci.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index d6894bd6798..35487e30b0f 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -883,7 +883,18 @@ static void ahci_host_intr(struct ata_port *ap) } } - /* spurious interrupt */ + /* hmmm... a spurious interupt */ + + /* ignore interim PIO setup fis interrupts */ + if (ata_tag_valid(ap->active_tag)) { + struct ata_queued_cmd *qc = + ata_qc_from_tag(ap, ap->active_tag); + + if (qc && qc->tf.protocol == ATA_PROT_PIO && + (status & PORT_IRQ_PIOS_FIS)) + return; + } + if (ata_ratelimit()) ata_port_printk(ap, KERN_INFO, "spurious interrupt " "(irq_stat 0x%x active_tag %d)\n", -- cgit v1.2.3 From 88ce7550c38f46c8697f53727a571bf838bee398 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:58:32 +0900 Subject: [PATCH] sata_sil24: convert to new EH Convert sata_sil24 to new EH. * When port is frozen, IRQ for the port is masked. * sil24_softreset() doesn't need to mangle with IRQ mask anymore. libata ensures that the port is frozen during reset. * Only turn on interrupts which are handled by interrupt handler and EH. As we don't handle SDB notify yet, turn it off. DEV_XCHG and UNK_FIS are handled by EH and thus turned on. * sil24_softreset() usually fails to recover the port after DEV_XCHG. ATA_PORT_HARDRESET is used as recovery action for DEV_XCHG. * sil24 may be invoked without any active command. e.g. DEV_XCHG irq occuring while no qc in progress still triggers EH and will reset the port and revalidate attached device. Signed-off-by: Tejun Heo --- drivers/scsi/sata_sil24.c | 328 ++++++++++++++++++++++++++-------------------- 1 file changed, 187 insertions(+), 141 deletions(-) diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index ff96724b1e3..6e7728cfaf6 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -156,6 +156,9 @@ enum { PORT_IRQ_HANDSHAKE = (1 << 10), /* handshake error threshold */ PORT_IRQ_SDB_NOTIFY = (1 << 11), /* SDB notify received */ + DEF_PORT_IRQ = PORT_IRQ_COMPLETE | PORT_IRQ_ERROR | + PORT_IRQ_DEV_XCHG | PORT_IRQ_UNK_FIS, + /* bits[27:16] are unmasked (raw) */ PORT_IRQ_RAW_SHIFT = 16, PORT_IRQ_MASKED_MASK = 0x7ff, @@ -242,6 +245,58 @@ union sil24_cmd_block { struct sil24_atapi_block atapi; }; +static struct sil24_cerr_info { + unsigned int err_mask, action; + const char *desc; +} sil24_cerr_db[] = { + [0] = { AC_ERR_DEV, ATA_EH_REVALIDATE, + "device error" }, + [PORT_CERR_DEV] = { AC_ERR_DEV, ATA_EH_REVALIDATE, + "device error via D2H FIS" }, + [PORT_CERR_SDB] = { AC_ERR_DEV, ATA_EH_REVALIDATE, + "device error via SDB FIS" }, + [PORT_CERR_DATA] = { AC_ERR_ATA_BUS, ATA_EH_SOFTRESET, + "error in data FIS" }, + [PORT_CERR_SEND] = { AC_ERR_ATA_BUS, ATA_EH_SOFTRESET, + "failed to transmit command FIS" }, + [PORT_CERR_INCONSISTENT] = { AC_ERR_HSM, ATA_EH_SOFTRESET, + "protocol mismatch" }, + [PORT_CERR_DIRECTION] = { AC_ERR_HSM, ATA_EH_SOFTRESET, + "data directon mismatch" }, + [PORT_CERR_UNDERRUN] = { AC_ERR_HSM, ATA_EH_SOFTRESET, + "ran out of SGEs while writing" }, + [PORT_CERR_OVERRUN] = { AC_ERR_HSM, ATA_EH_SOFTRESET, + "ran out of SGEs while reading" }, + [PORT_CERR_PKT_PROT] = { AC_ERR_HSM, ATA_EH_SOFTRESET, + "invalid data directon for ATAPI CDB" }, + [PORT_CERR_SGT_BOUNDARY] = { AC_ERR_SYSTEM, ATA_EH_SOFTRESET, + "SGT no on qword boundary" }, + [PORT_CERR_SGT_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET, + "PCI target abort while fetching SGT" }, + [PORT_CERR_SGT_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET, + "PCI master abort while fetching SGT" }, + [PORT_CERR_SGT_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET, + "PCI parity error while fetching SGT" }, + [PORT_CERR_CMD_BOUNDARY] = { AC_ERR_SYSTEM, ATA_EH_SOFTRESET, + "PRB not on qword boundary" }, + [PORT_CERR_CMD_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET, + "PCI target abort while fetching PRB" }, + [PORT_CERR_CMD_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET, + "PCI master abort while fetching PRB" }, + [PORT_CERR_CMD_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET, + "PCI parity error while fetching PRB" }, + [PORT_CERR_XFR_UNDEF] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET, + "undefined error while transferring data" }, + [PORT_CERR_XFR_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET, + "PCI target abort while transferring data" }, + [PORT_CERR_XFR_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET, + "PCI master abort while transferring data" }, + [PORT_CERR_XFR_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET, + "PCI parity error while transferring data" }, + [PORT_CERR_SENDSERVICE] = { AC_ERR_HSM, ATA_EH_SOFTRESET, + "FIS received while sending service FIS" }, +}; + /* * ap->private_data * @@ -269,8 +324,11 @@ static int sil24_probe_reset(struct ata_port *ap, unsigned int *classes); static void sil24_qc_prep(struct ata_queued_cmd *qc); static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc); static void sil24_irq_clear(struct ata_port *ap); -static void sil24_eng_timeout(struct ata_port *ap); static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *regs); +static void sil24_freeze(struct ata_port *ap); +static void sil24_thaw(struct ata_port *ap); +static void sil24_error_handler(struct ata_port *ap); +static void sil24_post_internal_cmd(struct ata_queued_cmd *qc); static int sil24_port_start(struct ata_port *ap); static void sil24_port_stop(struct ata_port *ap); static void sil24_host_stop(struct ata_host_set *host_set); @@ -325,14 +383,17 @@ static const struct ata_port_operations sil24_ops = { .qc_prep = sil24_qc_prep, .qc_issue = sil24_qc_issue, - .eng_timeout = sil24_eng_timeout, - .irq_handler = sil24_interrupt, .irq_clear = sil24_irq_clear, .scr_read = sil24_scr_read, .scr_write = sil24_scr_write, + .freeze = sil24_freeze, + .thaw = sil24_thaw, + .error_handler = sil24_error_handler, + .post_internal_cmd = sil24_post_internal_cmd, + .port_start = sil24_port_start, .port_stop = sil24_port_stop, .host_stop = sil24_host_stop, @@ -459,7 +520,7 @@ static int sil24_softreset(struct ata_port *ap, unsigned int *class) struct sil24_port_priv *pp = ap->private_data; struct sil24_prb *prb = &pp->cmd_block[0].ata.prb; dma_addr_t paddr = pp->cmd_block_dma; - u32 mask, irq_enable, irq_stat; + u32 mask, irq_stat; const char *reason; DPRINTK("ENTER\n"); @@ -470,10 +531,6 @@ static int sil24_softreset(struct ata_port *ap, unsigned int *class) goto out; } - /* temporarily turn off IRQs during SRST */ - irq_enable = readl(port + PORT_IRQ_ENABLE_SET); - writel(irq_enable, port + PORT_IRQ_ENABLE_CLR); - /* put the port into known state */ if (sil24_init_port(ap)) { reason ="port not ready"; @@ -494,9 +551,6 @@ static int sil24_softreset(struct ata_port *ap, unsigned int *class) writel(irq_stat, port + PORT_IRQ_STAT); /* clear IRQs */ irq_stat >>= PORT_IRQ_RAW_SHIFT; - /* restore IRQs */ - writel(irq_enable, port + PORT_IRQ_ENABLE_SET); - if (!(irq_stat & PORT_IRQ_COMPLETE)) { if (irq_stat & PORT_IRQ_ERROR) reason = "SRST command error"; @@ -655,158 +709,134 @@ static void sil24_irq_clear(struct ata_port *ap) /* unused */ } -static int __sil24_restart_controller(void __iomem *port) +static void sil24_freeze(struct ata_port *ap) { - u32 tmp; - int cnt; - - writel(PORT_CS_INIT, port + PORT_CTRL_STAT); - - /* Max ~10ms */ - for (cnt = 0; cnt < 10000; cnt++) { - tmp = readl(port + PORT_CTRL_STAT); - if (tmp & PORT_CS_RDY) - return 0; - udelay(1); - } - - return -1; -} + void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; -static void sil24_restart_controller(struct ata_port *ap) -{ - if (__sil24_restart_controller((void __iomem *)ap->ioaddr.cmd_addr)) - printk(KERN_ERR DRV_NAME - " ata%u: failed to restart controller\n", ap->id); + /* Port-wide IRQ mask in HOST_CTRL doesn't really work, clear + * PORT_IRQ_ENABLE instead. + */ + writel(0xffff, port + PORT_IRQ_ENABLE_CLR); } -static int __sil24_reset_controller(void __iomem *port) +static void sil24_thaw(struct ata_port *ap) { - int cnt; + void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; u32 tmp; - /* Reset controller state. Is this correct? */ - writel(PORT_CS_DEV_RST, port + PORT_CTRL_STAT); - readl(port + PORT_CTRL_STAT); /* sync */ - - /* Max ~100ms */ - for (cnt = 0; cnt < 1000; cnt++) { - udelay(100); - tmp = readl(port + PORT_CTRL_STAT); - if (!(tmp & PORT_CS_DEV_RST)) - break; - } - - if (tmp & PORT_CS_DEV_RST) - return -1; - - if (tmp & PORT_CS_RDY) - return 0; - - return __sil24_restart_controller(port); -} - -static void sil24_reset_controller(struct ata_port *ap) -{ - printk(KERN_NOTICE DRV_NAME - " ata%u: resetting controller...\n", ap->id); - if (__sil24_reset_controller((void __iomem *)ap->ioaddr.cmd_addr)) - printk(KERN_ERR DRV_NAME - " ata%u: failed to reset controller\n", ap->id); -} - -static void sil24_eng_timeout(struct ata_port *ap) -{ - struct ata_queued_cmd *qc; - - qc = ata_qc_from_tag(ap, ap->active_tag); - - ata_port_printk(ap, KERN_ERR, "command timeout\n"); - qc->err_mask |= AC_ERR_TIMEOUT; - ata_eh_qc_complete(qc); + /* clear IRQ */ + tmp = readl(port + PORT_IRQ_STAT); + writel(tmp, port + PORT_IRQ_STAT); - sil24_reset_controller(ap); + /* turn IRQ back on */ + writel(DEF_PORT_IRQ, port + PORT_IRQ_ENABLE_SET); } -static void sil24_error_intr(struct ata_port *ap, u32 slot_stat) +static void sil24_error_intr(struct ata_port *ap) { - struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag); - struct sil24_port_priv *pp = ap->private_data; void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; - u32 irq_stat, cmd_err, sstatus, serror; - unsigned int err_mask; + struct ata_eh_info *ehi = &ap->eh_info; + int freeze = 0; + u32 irq_stat; + /* on error, we need to clear IRQ explicitly */ irq_stat = readl(port + PORT_IRQ_STAT); - writel(irq_stat, port + PORT_IRQ_STAT); /* clear irq */ + writel(irq_stat, port + PORT_IRQ_STAT); - if (!(irq_stat & PORT_IRQ_ERROR)) { - /* ignore non-completion, non-error irqs for now */ - printk(KERN_WARNING DRV_NAME - "ata%u: non-error exception irq (irq_stat %x)\n", - ap->id, irq_stat); - return; - } + /* first, analyze and record host port events */ + ata_ehi_clear_desc(ehi); - cmd_err = readl(port + PORT_CMD_ERR); - sstatus = readl(port + PORT_SSTATUS); - serror = readl(port + PORT_SERROR); - if (serror) - writel(serror, port + PORT_SERROR); + ata_ehi_push_desc(ehi, "irq_stat 0x%08x", irq_stat); - /* - * Don't log ATAPI device errors. They're supposed to happen - * and any serious errors will be logged using sense data by - * the SCSI layer. - */ - if (ap->device[0].class != ATA_DEV_ATAPI || cmd_err > PORT_CERR_SDB) - printk("ata%u: error interrupt on port%d\n" - " stat=0x%x irq=0x%x cmd_err=%d sstatus=0x%x serror=0x%x\n", - ap->id, ap->port_no, slot_stat, irq_stat, cmd_err, sstatus, serror); - - if (cmd_err == PORT_CERR_DEV || cmd_err == PORT_CERR_SDB) { - /* - * Device is reporting error, tf registers are valid. + if (irq_stat & PORT_IRQ_DEV_XCHG) { + ehi->err_mask |= AC_ERR_ATA_BUS; + /* sil24 doesn't recover very well from phy + * disconnection with a softreset. Force hardreset. */ - sil24_update_tf(ap); - err_mask = ac_err_mask(pp->tf.command); - sil24_restart_controller(ap); - } else { - /* - * Other errors. libata currently doesn't have any - * mechanism to report these errors. Just turn on - * ATA_ERR. - */ - err_mask = AC_ERR_OTHER; - sil24_reset_controller(ap); + ehi->action |= ATA_EH_HARDRESET; + ata_ehi_push_desc(ehi, ", device_exchanged"); + freeze = 1; } - if (qc) { - qc->err_mask |= err_mask; - ata_qc_complete(qc); + if (irq_stat & PORT_IRQ_UNK_FIS) { + ehi->err_mask |= AC_ERR_HSM; + ehi->action |= ATA_EH_SOFTRESET; + ata_ehi_push_desc(ehi , ", unknown FIS"); + freeze = 1; + } + + /* deal with command error */ + if (irq_stat & PORT_IRQ_ERROR) { + struct sil24_cerr_info *ci = NULL; + unsigned int err_mask = 0, action = 0; + struct ata_queued_cmd *qc; + u32 cerr; + + /* analyze CMD_ERR */ + cerr = readl(port + PORT_CMD_ERR); + if (cerr < ARRAY_SIZE(sil24_cerr_db)) + ci = &sil24_cerr_db[cerr]; + + if (ci && ci->desc) { + err_mask |= ci->err_mask; + action |= ci->action; + ata_ehi_push_desc(ehi, ", %s", ci->desc); + } else { + err_mask |= AC_ERR_OTHER; + action |= ATA_EH_SOFTRESET; + ata_ehi_push_desc(ehi, ", unknown command error %d", + cerr); + } + + /* record error info */ + qc = ata_qc_from_tag(ap, ap->active_tag); + if (qc) { + int tag = qc->tag; + if (unlikely(ata_tag_internal(tag))) + tag = 0; + sil24_update_tf(ap); + qc->err_mask |= err_mask; + } else + ehi->err_mask |= err_mask; + + ehi->action |= action; } + + /* freeze or abort */ + if (freeze) + ata_port_freeze(ap); + else + ata_port_abort(ap); } static inline void sil24_host_intr(struct ata_port *ap) { - struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag); void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; + struct ata_queued_cmd *qc; u32 slot_stat; slot_stat = readl(port + PORT_SLOT_STAT); - if (!(slot_stat & HOST_SSTAT_ATTN)) { - struct sil24_port_priv *pp = ap->private_data; - if (ap->flags & SIL24_FLAG_PCIX_IRQ_WOC) - writel(PORT_IRQ_COMPLETE, port + PORT_IRQ_STAT); + if (unlikely(slot_stat & HOST_SSTAT_ATTN)) { + sil24_error_intr(ap); + return; + } + + if (ap->flags & SIL24_FLAG_PCIX_IRQ_WOC) + writel(PORT_IRQ_COMPLETE, port + PORT_IRQ_STAT); - if (qc) { - if (qc->flags & ATA_QCFLAG_RESULT_TF) - sil24_update_tf(ap); - qc->err_mask |= ac_err_mask(pp->tf.command); - ata_qc_complete(qc); - } - } else - sil24_error_intr(ap, slot_stat); + qc = ata_qc_from_tag(ap, ap->active_tag); + if (qc) { + if (qc->flags & ATA_QCFLAG_RESULT_TF) + sil24_update_tf(ap); + ata_qc_complete(qc); + return; + } + + if (ata_ratelimit()) + ata_port_printk(ap, KERN_INFO, "spurious interrupt " + "(slot_stat 0x%x active_tag %d)\n", + slot_stat, ap->active_tag); } static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *regs) @@ -846,6 +876,31 @@ static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs * return IRQ_RETVAL(handled); } +static void sil24_error_handler(struct ata_port *ap) +{ + struct ata_eh_context *ehc = &ap->eh_context; + + if (sil24_init_port(ap)) { + ata_eh_freeze_port(ap); + ehc->i.action |= ATA_EH_HARDRESET; + } + + /* perform recovery */ + ata_do_eh(ap, sil24_softreset, sil24_hardreset, ata_std_postreset); +} + +static void sil24_post_internal_cmd(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + + if (qc->flags & ATA_QCFLAG_FAILED) + qc->err_mask |= AC_ERR_OTHER; + + /* make DMA engine forget about the failed command */ + if (qc->err_mask) + sil24_init_port(ap); +} + static inline void sil24_cblk_free(struct sil24_port_priv *pp, struct device *dev) { const size_t cb_size = sizeof(*pp->cmd_block); @@ -1058,15 +1113,6 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) /* Always use 64bit activation */ writel(PORT_CS_32BIT_ACTV, port + PORT_CTRL_CLR); - /* Configure interrupts */ - writel(0xffff, port + PORT_IRQ_ENABLE_CLR); - writel(PORT_IRQ_COMPLETE | PORT_IRQ_ERROR | - PORT_IRQ_SDB_NOTIFY, port + PORT_IRQ_ENABLE_SET); - - /* Clear interrupts */ - writel(0x0fff0fff, port + PORT_IRQ_STAT); - writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_CLR); - /* Clear port multiplier enable and resume bits */ writel(PORT_CS_PM_EN | PORT_CS_RESUME, port + PORT_CTRL_CLR); } -- cgit v1.2.3 From c17ea20d9a689d7335e97e09354865cdd9f873e1 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:59:29 +0900 Subject: [PATCH] libata: fix irq-pio merge * kill ata_poll_qc_complete() and implement/use ata_hsm_qc_complete() which completes qcs in new EH compliant manner from HSM * don't print error message from ata_hsm_move(). it's responsibility of EH. * kill ATA_FLAG_NOINTR usage in bmdma EH Signed-off-by: Tejun Heo --- drivers/scsi/libata-bmdma.c | 1 - drivers/scsi/libata-core.c | 98 ++++++++++++++++++++++++--------------------- 2 files changed, 52 insertions(+), 47 deletions(-) diff --git a/drivers/scsi/libata-bmdma.c b/drivers/scsi/libata-bmdma.c index 49eff18a67e..6d30d2c5296 100644 --- a/drivers/scsi/libata-bmdma.c +++ b/drivers/scsi/libata-bmdma.c @@ -726,7 +726,6 @@ void ata_bmdma_drive_eh(struct ata_port *ap, ata_reset_fn_t softreset, /* reset PIO HSM and stop DMA engine */ spin_lock_irqsave(&host_set->lock, flags); - ap->flags &= ~ATA_FLAG_NOINTR; ap->hsm_task_state = HSM_ST_IDLE; if (qc && (qc->tf.protocol == ATA_PROT_DMA || diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index c859b96b891..487b8f22981 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3461,40 +3461,6 @@ skip_map: return 0; } -/** - * ata_poll_qc_complete - turn irq back on and finish qc - * @qc: Command to complete - * @err_mask: ATA status register content - * - * LOCKING: - * None. (grabs host lock) - */ -void ata_poll_qc_complete(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - unsigned long flags; - - spin_lock_irqsave(&ap->host_set->lock, flags); - - if (ap->ops->error_handler) { - /* EH might have kicked in while host_set lock is released */ - qc = ata_qc_from_tag(ap, qc->tag); - if (qc) { - if (!(qc->err_mask & AC_ERR_HSM)) { - ata_irq_on(ap); - ata_qc_complete(qc); - } else - ata_port_freeze(ap); - } - } else { - /* old EH */ - ata_irq_on(ap); - ata_qc_complete(qc); - } - - spin_unlock_irqrestore(&ap->host_set->lock, flags); -} - /** * swap_buf_le16 - swap halves of 16-bit words in place * @buf: Buffer to swap @@ -3917,6 +3883,56 @@ static inline int ata_hsm_ok_in_wq(struct ata_port *ap, struct ata_queued_cmd *q return 0; } +/** + * ata_hsm_qc_complete - finish a qc running on standard HSM + * @qc: Command to complete + * @in_wq: 1 if called from workqueue, 0 otherwise + * + * Finish @qc which is running on standard HSM. + * + * LOCKING: + * If @in_wq is zero, spin_lock_irqsave(host_set lock). + * Otherwise, none on entry and grabs host lock. + */ +static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq) +{ + struct ata_port *ap = qc->ap; + unsigned long flags; + + if (ap->ops->error_handler) { + if (in_wq) { + spin_lock_irqsave(&ap->host_set->lock, flags); + + /* EH might have kicked in while host_set lock + * is released. + */ + qc = ata_qc_from_tag(ap, qc->tag); + if (qc) { + if (likely(!(qc->err_mask & AC_ERR_HSM))) { + ata_irq_on(ap); + ata_qc_complete(qc); + } else + ata_port_freeze(ap); + } + + spin_unlock_irqrestore(&ap->host_set->lock, flags); + } else { + if (likely(!(qc->err_mask & AC_ERR_HSM))) + ata_qc_complete(qc); + else + ata_port_freeze(ap); + } + } else { + if (in_wq) { + spin_lock_irqsave(&ap->host_set->lock, flags); + ata_irq_on(ap); + ata_qc_complete(qc); + spin_unlock_irqrestore(&ap->host_set->lock, flags); + } else + ata_qc_complete(qc); + } +} + /** * ata_hsm_move - move the HSM to the next state. * @ap: the target ata_port @@ -4108,19 +4124,12 @@ fsm_start: ap->hsm_task_state = HSM_ST_IDLE; /* complete taskfile transaction */ - if (in_wq) - ata_poll_qc_complete(qc); - else - ata_qc_complete(qc); + ata_hsm_qc_complete(qc, in_wq); poll_next = 0; break; case HSM_ST_ERR: - if (qc->tf.command != ATA_CMD_PACKET) - printk(KERN_ERR "ata%u: dev %u command error, drv_stat 0x%x\n", - ap->id, qc->dev->devno, status); - /* make sure qc->err_mask is available to * know what's wrong and recover */ @@ -4129,10 +4138,7 @@ fsm_start: ap->hsm_task_state = HSM_ST_IDLE; /* complete taskfile transaction */ - if (in_wq) - ata_poll_qc_complete(qc); - else - ata_qc_complete(qc); + ata_hsm_qc_complete(qc, in_wq); poll_next = 0; break; -- cgit v1.2.3 From 88e490340ea4c3a2ebc0187a4339912e2fc1a081 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 21:03:38 +0900 Subject: [PATCH] libata-ncq: add NCQ related ATA/libata constants and macros Add NCQ related ATA/libata constants and macros. Signed-off-by: Tejun Heo --- include/linux/ata.h | 9 +++++++++ include/linux/libata.h | 2 ++ 2 files changed, 11 insertions(+) diff --git a/include/linux/ata.h b/include/linux/ata.h index 1cbeb434af9..c494e1c0531 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -133,6 +133,8 @@ enum { ATA_CMD_WRITE = 0xCA, ATA_CMD_WRITE_EXT = 0x35, ATA_CMD_WRITE_FUA_EXT = 0x3D, + ATA_CMD_FPDMA_READ = 0x60, + ATA_CMD_FPDMA_WRITE = 0x61, ATA_CMD_PIO_READ = 0x20, ATA_CMD_PIO_READ_EXT = 0x24, ATA_CMD_PIO_WRITE = 0x30, @@ -151,6 +153,10 @@ enum { ATA_CMD_INIT_DEV_PARAMS = 0x91, ATA_CMD_READ_NATIVE_MAX = 0xF8, ATA_CMD_READ_NATIVE_MAX_EXT = 0x27, + ATA_CMD_READ_LOG_EXT = 0x2f, + + /* READ_LOG_EXT pages */ + ATA_LOG_SATA_NCQ = 0x10, /* SETFEATURES stuff */ SETFEATURES_XFER = 0x03, @@ -221,6 +227,7 @@ enum ata_tf_protocols { ATA_PROT_NODATA, /* no data */ ATA_PROT_PIO, /* PIO single sector */ ATA_PROT_DMA, /* DMA */ + ATA_PROT_NCQ, /* NCQ */ ATA_PROT_ATAPI, /* packet command, PIO data xfer*/ ATA_PROT_ATAPI_NODATA, /* packet command, no data */ ATA_PROT_ATAPI_DMA, /* packet command with special DMA sauce */ @@ -276,6 +283,8 @@ struct ata_taskfile { #define ata_id_has_pm(id) ((id)[82] & (1 << 3)) #define ata_id_has_lba(id) ((id)[49] & (1 << 9)) #define ata_id_has_dma(id) ((id)[49] & (1 << 8)) +#define ata_id_has_ncq(id) ((id)[76] & (1 << 8)) +#define ata_id_queue_depth(id) (((id)[75] & 0x1f) + 1) #define ata_id_removeable(id) ((id)[0] & (1 << 7)) #define ata_id_has_dword_io(id) ((id)[50] & (1 << 0)) #define ata_id_u32(id,n) \ diff --git a/include/linux/libata.h b/include/linux/libata.h index db17723e23f..7c9e280a482 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -125,6 +125,7 @@ enum { ATA_DFLAG_LBA = (1 << 0), /* device supports LBA */ ATA_DFLAG_LBA48 = (1 << 1), /* device supports LBA48 */ ATA_DFLAG_CDB_INTR = (1 << 2), /* device asserts INTRQ when ready for CDB */ + ATA_DFLAG_NCQ = (1 << 3), /* device supports NCQ */ ATA_DFLAG_CFG_MASK = (1 << 8) - 1, ATA_DFLAG_PIO = (1 << 8), /* device currently in PIO mode */ @@ -150,6 +151,7 @@ enum { ATA_FLAG_IRQ_MASK = (1 << 9), /* Mask IRQ in PIO xfers */ ATA_FLAG_PIO_POLLING = (1 << 10), /* use polling PIO if LLD * doesn't handle PIO interrupts */ + ATA_FLAG_NCQ = (1 << 11), /* host supports NCQ */ ATA_FLAG_DEBUGMSG = (1 << 14), ATA_FLAG_FLUSH_PORT_TASK = (1 << 15), /* flush port task */ -- cgit v1.2.3 From 2115ea94a2d11fbd228b049e667ec2d3e91ca371 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 21:03:39 +0900 Subject: [PATCH] libata-ncq: pass ata_scsi_translate() return value to SCSI midlayer ata_scsi_translate() will need to return SCSI_ML_QUEUE_DEVICE_BUSY to achieve exlusion between NCQ and non-NCQ commands or among non-NCQ commands. Pass its return value upward to SCSI midlayer. Signed-off-by: Tejun Heo --- drivers/scsi/libata-scsi.c | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index e61cc357ae4..96517ca021e 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -1248,11 +1248,14 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) * * LOCKING: * spin_lock_irqsave(host_set lock) + * + * RETURNS: + * 0 on success, SCSI_ML_QUEUE_DEVICE_BUSY if the command + * needs to be deferred. */ - -static void ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cmd, - void (*done)(struct scsi_cmnd *), - ata_xlat_func_t xlat_func) +static int ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cmd, + void (*done)(struct scsi_cmnd *), + ata_xlat_func_t xlat_func) { struct ata_queued_cmd *qc; u8 *scsicmd = cmd->cmnd; @@ -1290,13 +1293,13 @@ static void ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cmd, ata_qc_issue(qc); VPRINTK("EXIT\n"); - return; + return 0; early_finish: ata_qc_free(qc); done(cmd); DPRINTK("EXIT - early finish (good or error)\n"); - return; + return 0; err_did: ata_qc_free(qc); @@ -1304,7 +1307,7 @@ err_mem: cmd->result = (DID_ERROR << 16); done(cmd); DPRINTK("EXIT - internal\n"); - return; + return 0; } /** @@ -2456,20 +2459,24 @@ static inline void ata_scsi_dump_cdb(struct ata_port *ap, #endif } -static inline void __ata_scsi_queuecmd(struct scsi_cmnd *cmd, - void (*done)(struct scsi_cmnd *), - struct ata_device *dev) +static inline int __ata_scsi_queuecmd(struct scsi_cmnd *cmd, + void (*done)(struct scsi_cmnd *), + struct ata_device *dev) { + int rc = 0; + if (dev->class == ATA_DEV_ATA) { ata_xlat_func_t xlat_func = ata_get_xlat_func(dev, cmd->cmnd[0]); if (xlat_func) - ata_scsi_translate(dev, cmd, done, xlat_func); + rc = ata_scsi_translate(dev, cmd, done, xlat_func); else ata_scsi_simulate(dev, cmd, done); } else - ata_scsi_translate(dev, cmd, done, atapi_xlat); + rc = ata_scsi_translate(dev, cmd, done, atapi_xlat); + + return rc; } /** @@ -2488,15 +2495,16 @@ static inline void __ata_scsi_queuecmd(struct scsi_cmnd *cmd, * Releases scsi-layer-held lock, and obtains host_set lock. * * RETURNS: - * Zero. + * Return value from __ata_scsi_queuecmd() if @cmd can be queued, + * 0 otherwise. */ - int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) { struct ata_port *ap; struct ata_device *dev; struct scsi_device *scsidev = cmd->device; struct Scsi_Host *shost = scsidev->host; + int rc = 0; ap = ata_shost_to_port(shost); @@ -2507,7 +2515,7 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) dev = ata_scsi_find_dev(ap, scsidev); if (likely(dev)) - __ata_scsi_queuecmd(cmd, done, dev); + rc = __ata_scsi_queuecmd(cmd, done, dev); else { cmd->result = (DID_BAD_TARGET << 16); done(cmd); @@ -2515,7 +2523,7 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) spin_unlock(&ap->host_set->lock); spin_lock(shost->host_lock); - return 0; + return rc; } /** -- cgit v1.2.3 From 6cec4a3943bdfe46e2952bc246f17670f747be8d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 21:03:41 +0900 Subject: [PATCH] libata-ncq: rename ap->qactive to ap->qc_allocated Rename ap->qactive to ap->qc_allocated. This is to accomodate addition of ap->qc_active, mask of active qcs. Signed-off-by: Tejun Heo --- drivers/scsi/libata-core.c | 6 +++--- include/linux/libata.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 487b8f22981..f8401800dc1 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1006,7 +1006,7 @@ unsigned ata_exec_internal(struct ata_device *dev, else tag = 0; - if (test_and_set_bit(tag, &ap->qactive)) + if (test_and_set_bit(tag, &ap->qc_allocated)) BUG(); qc = __ata_qc_from_tag(ap, tag); @@ -4207,7 +4207,7 @@ static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap) /* the last tag is reserved for internal command. */ for (i = 0; i < ATA_MAX_QUEUE - 1; i++) - if (!test_and_set_bit(i, &ap->qactive)) { + if (!test_and_set_bit(i, &ap->qc_allocated)) { qc = __ata_qc_from_tag(ap, i); break; } @@ -4264,7 +4264,7 @@ void ata_qc_free(struct ata_queued_cmd *qc) tag = qc->tag; if (likely(ata_tag_valid(tag))) { qc->tag = ATA_TAG_POISON; - clear_bit(tag, &ap->qactive); + clear_bit(tag, &ap->qc_allocated); } } diff --git a/include/linux/libata.h b/include/linux/libata.h index 7c9e280a482..b3a4f8bea82 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -474,7 +474,7 @@ struct ata_port { struct ata_device device[ATA_MAX_DEVICES]; struct ata_queued_cmd qcmd[ATA_MAX_QUEUE]; - unsigned long qactive; + unsigned long qc_allocated; unsigned int active_tag; struct ata_host_stats stats; -- cgit v1.2.3 From dedaf2b0365ccec50714fbde0b3215e7e94fa47c Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 21:03:43 +0900 Subject: [PATCH] libata-ncq: implement ap->qc_active, ap->sactive and complete helper Add ap->qc_active and ap->sactive, mask of all active qcs and libata's view of the SActive register, respectively. Also, implement ata_qc_complete_multiple() which takes new qc_active mask and complete multiple qcs according to the mask. These will be used to track NCQ commands and complete them. The distinction between ap->qc_active and ap->sactive is also useful for later PM implementation. Signed-off-by: Tejun Heo --- drivers/scsi/libata-core.c | 81 ++++++++++++++++++++++++++++++++++++++++++++-- include/linux/libata.h | 5 +++ 2 files changed, 84 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index f8401800dc1..eea1fe9c8b7 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -981,6 +981,7 @@ unsigned ata_exec_internal(struct ata_device *dev, u8 command = tf->command; struct ata_queued_cmd *qc; unsigned int tag, preempted_tag; + u32 preempted_sactive, preempted_qc_active; DECLARE_COMPLETION(wait); unsigned long flags; unsigned int err_mask; @@ -1017,7 +1018,11 @@ unsigned ata_exec_internal(struct ata_device *dev, ata_qc_reinit(qc); preempted_tag = ap->active_tag; + preempted_sactive = ap->sactive; + preempted_qc_active = ap->qc_active; ap->active_tag = ATA_TAG_POISON; + ap->sactive = 0; + ap->qc_active = 0; /* prepare & issue qc */ qc->tf = *tf; @@ -1082,6 +1087,8 @@ unsigned ata_exec_internal(struct ata_device *dev, ata_qc_free(qc); ap->active_tag = preempted_tag; + ap->sactive = preempted_sactive; + ap->qc_active = preempted_qc_active; /* XXX - Some LLDDs (sata_mv) disable port on command failure. * Until those drivers are fixed, we detect the condition @@ -4270,6 +4277,8 @@ void ata_qc_free(struct ata_queued_cmd *qc) void __ata_qc_complete(struct ata_queued_cmd *qc) { + struct ata_port *ap = qc->ap; + WARN_ON(qc == NULL); /* ata_qc_from_tag _might_ return NULL */ WARN_ON(!(qc->flags & ATA_QCFLAG_ACTIVE)); @@ -4277,13 +4286,17 @@ void __ata_qc_complete(struct ata_queued_cmd *qc) ata_sg_clean(qc); /* command should be marked inactive atomically with qc completion */ - qc->ap->active_tag = ATA_TAG_POISON; + if (qc->tf.protocol == ATA_PROT_NCQ) + ap->sactive &= ~(1 << qc->tag); + else + ap->active_tag = ATA_TAG_POISON; /* atapi: mark qc as inactive to prevent the interrupt handler * from completing the command twice later, before the error handler * is called. (when rc != 0 and atapi request sense is needed) */ qc->flags &= ~ATA_QCFLAG_ACTIVE; + ap->qc_active &= ~(1 << qc->tag); /* call completion callback */ qc->complete_fn(qc); @@ -4349,6 +4362,55 @@ void ata_qc_complete(struct ata_queued_cmd *qc) } } +/** + * ata_qc_complete_multiple - Complete multiple qcs successfully + * @ap: port in question + * @qc_active: new qc_active mask + * @finish_qc: LLDD callback invoked before completing a qc + * + * Complete in-flight commands. This functions is meant to be + * called from low-level driver's interrupt routine to complete + * requests normally. ap->qc_active and @qc_active is compared + * and commands are completed accordingly. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + * + * RETURNS: + * Number of completed commands on success, -errno otherwise. + */ +int ata_qc_complete_multiple(struct ata_port *ap, u32 qc_active, + void (*finish_qc)(struct ata_queued_cmd *)) +{ + int nr_done = 0; + u32 done_mask; + int i; + + done_mask = ap->qc_active ^ qc_active; + + if (unlikely(done_mask & qc_active)) { + ata_port_printk(ap, KERN_ERR, "illegal qc_active transition " + "(%08x->%08x)\n", ap->qc_active, qc_active); + return -EINVAL; + } + + for (i = 0; i < ATA_MAX_QUEUE; i++) { + struct ata_queued_cmd *qc; + + if (!(done_mask & (1 << i))) + continue; + + if ((qc = ata_qc_from_tag(ap, i))) { + if (finish_qc) + finish_qc(qc); + ata_qc_complete(qc); + nr_done++; + } + } + + return nr_done; +} + static inline int ata_should_dma_map(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; @@ -4388,8 +4450,22 @@ void ata_qc_issue(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; - qc->ap->active_tag = qc->tag; + /* Make sure only one non-NCQ command is outstanding. The + * check is skipped for old EH because it reuses active qc to + * request ATAPI sense. + */ + WARN_ON(ap->ops->error_handler && ata_tag_valid(ap->active_tag)); + + if (qc->tf.protocol == ATA_PROT_NCQ) { + WARN_ON(ap->sactive & (1 << qc->tag)); + ap->sactive |= 1 << qc->tag; + } else { + WARN_ON(ap->sactive); + ap->active_tag = qc->tag; + } + qc->flags |= ATA_QCFLAG_ACTIVE; + ap->qc_active |= 1 << qc->tag; if (ata_should_dma_map(qc)) { if (qc->flags & ATA_QCFLAG_SG) { @@ -5549,6 +5625,7 @@ EXPORT_SYMBOL_GPL(ata_host_set_remove); EXPORT_SYMBOL_GPL(ata_sg_init); EXPORT_SYMBOL_GPL(ata_sg_init_one); EXPORT_SYMBOL_GPL(ata_qc_complete); +EXPORT_SYMBOL_GPL(ata_qc_complete_multiple); EXPORT_SYMBOL_GPL(ata_qc_issue_prot); EXPORT_SYMBOL_GPL(ata_tf_load); EXPORT_SYMBOL_GPL(ata_tf_read); diff --git a/include/linux/libata.h b/include/linux/libata.h index b3a4f8bea82..dd0db2d21bc 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -475,7 +475,10 @@ struct ata_port { struct ata_queued_cmd qcmd[ATA_MAX_QUEUE]; unsigned long qc_allocated; + unsigned int qc_active; + unsigned int active_tag; + u32 sactive; struct ata_host_stats stats; struct ata_host_set *host_set; @@ -668,6 +671,8 @@ extern void ata_bmdma_drive_eh(struct ata_port *ap, extern void ata_bmdma_error_handler(struct ata_port *ap); extern void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc); extern void ata_qc_complete(struct ata_queued_cmd *qc); +extern int ata_qc_complete_multiple(struct ata_port *ap, u32 qc_active, + void (*finish_qc)(struct ata_queued_cmd *)); extern void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)); extern int ata_std_bios_param(struct scsi_device *sdev, -- cgit v1.2.3 From 3dc1d88193b9c65b01b64fb2dc730e486306649f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 21:03:45 +0900 Subject: [PATCH] libata-ncq: implement NCQ command translation and exclusion This patch implements NCQ command translation and exclusion. Note that NCQ commands don't use ata_rwcmd_protocol() to choose ATA command. This is because, unlike non-NCQ RW commands, NCQ commands can only be used for NCQ protocol and FUA handling is done with a flag rather than separate command. NCQ enabled device will have queue depth larger than one but no two non-NCQ commands can be issued simultaneously, neither can a non-NCQ command and NCQ commands. This patch makes ata_scsi_translate() return SCSI_MLQUEUE_DEVICE_BUSY if such exclusion is necessary. SCSI midlayer will retry the command later. As SCSI midlayer always retries once a command completes, this doesn't incur unnecessary delays and as most commands will be NCQ ones for NCQ device, so the overhead should be negligible. Initial implementation is from Jens Axboe and using SCSI_MLQUEUE_DEVICE_BUSY for exclusion is suggested by Jeff Garzik. Signed-off-by: Tejun Heo --- drivers/scsi/libata-core.c | 1 + drivers/scsi/libata-scsi.c | 72 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index eea1fe9c8b7..14ffb5264b6 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -4416,6 +4416,7 @@ static inline int ata_should_dma_map(struct ata_queued_cmd *qc) struct ata_port *ap = qc->ap; switch (qc->tf.protocol) { + case ATA_PROT_NCQ: case ATA_PROT_DMA: case ATA_PROT_ATAPI_DMA: return 1; diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 96517ca021e..9bef68c7c1d 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -1103,7 +1103,36 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm */ goto nothing_to_do; - if (dev->flags & ATA_DFLAG_LBA) { + if ((dev->flags & (ATA_DFLAG_PIO | ATA_DFLAG_NCQ)) == ATA_DFLAG_NCQ) { + /* yay, NCQ */ + if (!lba_48_ok(block, n_block)) + goto out_of_range; + + tf->protocol = ATA_PROT_NCQ; + tf->flags |= ATA_TFLAG_LBA | ATA_TFLAG_LBA48; + + if (tf->flags & ATA_TFLAG_WRITE) + tf->command = ATA_CMD_FPDMA_WRITE; + else + tf->command = ATA_CMD_FPDMA_READ; + + qc->nsect = n_block; + + tf->nsect = qc->tag << 3; + tf->hob_feature = (n_block >> 8) & 0xff; + tf->feature = n_block & 0xff; + + tf->hob_lbah = (block >> 40) & 0xff; + tf->hob_lbam = (block >> 32) & 0xff; + tf->hob_lbal = (block >> 24) & 0xff; + tf->lbah = (block >> 16) & 0xff; + tf->lbam = (block >> 8) & 0xff; + tf->lbal = block & 0xff; + + tf->device = 1 << 6; + if (tf->flags & ATA_TFLAG_FUA) + tf->device |= 1 << 7; + } else if (dev->flags & ATA_DFLAG_LBA) { tf->flags |= ATA_TFLAG_LBA; if (lba_28_ok(block, n_block)) { @@ -1226,6 +1255,39 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) ata_qc_free(qc); } +/** + * ata_scmd_need_defer - Check whether we need to defer scmd + * @dev: ATA device to which the command is addressed + * @is_io: Is the command IO (and thus possibly NCQ)? + * + * NCQ and non-NCQ commands cannot run together. As upper layer + * only knows the queue depth, we are responsible for maintaining + * exclusion. This function checks whether a new command can be + * issued to @dev. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + * + * RETURNS: + * 1 if deferring is needed, 0 otherwise. + */ +static int ata_scmd_need_defer(struct ata_device *dev, int is_io) +{ + struct ata_port *ap = dev->ap; + + if (!(dev->flags & ATA_DFLAG_NCQ)) + return 0; + + if (is_io) { + if (!ata_tag_valid(ap->active_tag)) + return 0; + } else { + if (!ata_tag_valid(ap->active_tag) && !ap->sactive) + return 0; + } + return 1; +} + /** * ata_scsi_translate - Translate then issue SCSI command to ATA device * @dev: ATA device to which the command is addressed @@ -1259,9 +1321,13 @@ static int ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cmd, { struct ata_queued_cmd *qc; u8 *scsicmd = cmd->cmnd; + int is_io = xlat_func == ata_scsi_rw_xlat; VPRINTK("ENTER\n"); + if (unlikely(ata_scmd_need_defer(dev, is_io))) + goto defer; + qc = ata_scsi_qc_new(dev, cmd, done); if (!qc) goto err_mem; @@ -1308,6 +1374,10 @@ err_mem: done(cmd); DPRINTK("EXIT - internal\n"); return 0; + +defer: + DPRINTK("EXIT - defer\n"); + return SCSI_MLQUEUE_DEVICE_BUSY; } /** -- cgit v1.2.3 From e8ee84518c159a663c07bf691ace187527380f61 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 21:03:46 +0900 Subject: [PATCH] libata-ncq: update EH to handle NCQ Update EH to handle NCQ. ata_eh_autopsy() is updated to call ata_eh_analyze_ncq_error() which reads log page 10h on NCQ device error and updates eh_context accordingly. ata_eh_report() is updated to report SActive. Signed-off-by: Tejun Heo --- drivers/scsi/libata-eh.c | 171 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 163 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c index e401f353f84..7244caff13a 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/scsi/libata-eh.c @@ -684,6 +684,98 @@ static const char * ata_err_string(unsigned int err_mask) return "unknown error"; } +/** + * ata_read_log_page - read a specific log page + * @dev: target device + * @page: page to read + * @buf: buffer to store read page + * @sectors: number of sectors to read + * + * Read log page using READ_LOG_EXT command. + * + * LOCKING: + * Kernel thread context (may sleep). + * + * RETURNS: + * 0 on success, AC_ERR_* mask otherwise. + */ +static unsigned int ata_read_log_page(struct ata_device *dev, + u8 page, void *buf, unsigned int sectors) +{ + struct ata_taskfile tf; + unsigned int err_mask; + + DPRINTK("read log page - page %d\n", page); + + ata_tf_init(dev, &tf); + tf.command = ATA_CMD_READ_LOG_EXT; + tf.lbal = page; + tf.nsect = sectors; + tf.hob_nsect = sectors >> 8; + tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_LBA48 | ATA_TFLAG_DEVICE; + tf.protocol = ATA_PROT_PIO; + + err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE, + buf, sectors * ATA_SECT_SIZE); + + DPRINTK("EXIT, err_mask=%x\n", err_mask); + return err_mask; +} + +/** + * ata_eh_read_log_10h - Read log page 10h for NCQ error details + * @dev: Device to read log page 10h from + * @tag: Resulting tag of the failed command + * @tf: Resulting taskfile registers of the failed command + * + * Read log page 10h to obtain NCQ error details and clear error + * condition. + * + * LOCKING: + * Kernel thread context (may sleep). + * + * RETURNS: + * 0 on success, -errno otherwise. + */ +static int ata_eh_read_log_10h(struct ata_device *dev, + int *tag, struct ata_taskfile *tf) +{ + u8 *buf = dev->ap->sector_buf; + unsigned int err_mask; + u8 csum; + int i; + + err_mask = ata_read_log_page(dev, ATA_LOG_SATA_NCQ, buf, 1); + if (err_mask) + return -EIO; + + csum = 0; + for (i = 0; i < ATA_SECT_SIZE; i++) + csum += buf[i]; + if (csum) + ata_dev_printk(dev, KERN_WARNING, + "invalid checksum 0x%x on log page 10h\n", csum); + + if (buf[0] & 0x80) + return -ENOENT; + + *tag = buf[0] & 0x1f; + + tf->command = buf[2]; + tf->feature = buf[3]; + tf->lbal = buf[4]; + tf->lbam = buf[5]; + tf->lbah = buf[6]; + tf->device = buf[7]; + tf->hob_lbal = buf[8]; + tf->hob_lbam = buf[9]; + tf->hob_lbah = buf[10]; + tf->nsect = buf[12]; + tf->hob_nsect = buf[13]; + + return 0; +} + /** * atapi_eh_request_sense - perform ATAPI REQUEST_SENSE * @dev: device to perform REQUEST_SENSE to @@ -782,6 +874,66 @@ static void ata_eh_analyze_serror(struct ata_port *ap) ehc->i.action |= action; } +/** + * ata_eh_analyze_ncq_error - analyze NCQ error + * @ap: ATA port to analyze NCQ error for + * + * Read log page 10h, determine the offending qc and acquire + * error status TF. For NCQ device errors, all LLDDs have to do + * is setting AC_ERR_DEV in ehi->err_mask. This function takes + * care of the rest. + * + * LOCKING: + * Kernel thread context (may sleep). + */ +static void ata_eh_analyze_ncq_error(struct ata_port *ap) +{ + struct ata_eh_context *ehc = &ap->eh_context; + struct ata_device *dev = ap->device; + struct ata_queued_cmd *qc; + struct ata_taskfile tf; + int tag, rc; + + /* if frozen, we can't do much */ + if (ap->flags & ATA_FLAG_FROZEN) + return; + + /* is it NCQ device error? */ + if (!ap->sactive || !(ehc->i.err_mask & AC_ERR_DEV)) + return; + + /* has LLDD analyzed already? */ + for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { + qc = __ata_qc_from_tag(ap, tag); + + if (!(qc->flags & ATA_QCFLAG_FAILED)) + continue; + + if (qc->err_mask) + return; + } + + /* okay, this error is ours */ + rc = ata_eh_read_log_10h(dev, &tag, &tf); + if (rc) { + ata_port_printk(ap, KERN_ERR, "failed to read log page 10h " + "(errno=%d)\n", rc); + return; + } + + if (!(ap->sactive & (1 << tag))) { + ata_port_printk(ap, KERN_ERR, "log page 10h reported " + "inactive tag %d\n", tag); + return; + } + + /* we've got the perpetrator, condemn it */ + qc = __ata_qc_from_tag(ap, tag); + memcpy(&qc->result_tf, &tf, sizeof(tf)); + qc->err_mask |= AC_ERR_DEV; + ehc->i.err_mask &= ~AC_ERR_DEV; +} + /** * ata_eh_analyze_tf - analyze taskfile of a failed qc * @qc: qc to analyze @@ -999,6 +1151,9 @@ static void ata_eh_autopsy(struct ata_port *ap) } else if (rc != -EOPNOTSUPP) action |= ATA_EH_HARDRESET; + /* analyze NCQ failure */ + ata_eh_analyze_ncq_error(ap); + /* any real error trumps AC_ERR_OTHER */ if (ehc->i.err_mask & ~AC_ERR_OTHER) ehc->i.err_mask &= ~AC_ERR_OTHER; @@ -1093,17 +1248,17 @@ static void ata_eh_report(struct ata_port *ap) frozen = " frozen"; if (ehc->i.dev) { - ata_dev_printk(ehc->i.dev, KERN_ERR, - "exception Emask 0x%x SErr 0x%x action 0x%x%s\n", - ehc->i.err_mask, ehc->i.serror, ehc->i.action, - frozen); + ata_dev_printk(ehc->i.dev, KERN_ERR, "exception Emask 0x%x " + "SAct 0x%x SErr 0x%x action 0x%x%s\n", + ehc->i.err_mask, ap->sactive, ehc->i.serror, + ehc->i.action, frozen); if (desc) ata_dev_printk(ehc->i.dev, KERN_ERR, "(%s)\n", desc); } else { - ata_port_printk(ap, KERN_ERR, - "exception Emask 0x%x SErr 0x%x action 0x%x%s\n", - ehc->i.err_mask, ehc->i.serror, ehc->i.action, - frozen); + ata_port_printk(ap, KERN_ERR, "exception Emask 0x%x " + "SAct 0x%x SErr 0x%x action 0x%x%s\n", + ehc->i.err_mask, ap->sactive, ehc->i.serror, + ehc->i.action, frozen); if (desc) ata_port_printk(ap, KERN_ERR, "(%s)\n", desc); } -- cgit v1.2.3 From a6e6ce8e8dc907a2cf2b994b0ea4099423f046bf Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 21:03:48 +0900 Subject: [PATCH] libata-ncq: implement NCQ device configuration Now that all NCQ related stuff are in place, implement NCQ device configuration and bump ATA_MAX_QUEUE to 32 thus activating NCQ support. Original implementation is from Jens Axboe. Signed-off-by: Tejun Heo --- drivers/scsi/libata-core.c | 31 +++++++++++++++++++++++++++++-- drivers/scsi/libata-scsi.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ include/linux/libata.h | 4 +++- 3 files changed, 78 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 14ffb5264b6..9051b6821c1 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1251,6 +1251,28 @@ static inline u8 ata_dev_knobble(struct ata_device *dev) return ((dev->ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(dev->id))); } +static void ata_dev_config_ncq(struct ata_device *dev, + char *desc, size_t desc_sz) +{ + struct ata_port *ap = dev->ap; + int hdepth = 0, ddepth = ata_id_queue_depth(dev->id); + + if (!ata_id_has_ncq(dev->id)) { + desc[0] = '\0'; + return; + } + + if (ap->flags & ATA_FLAG_NCQ) { + hdepth = min(ap->host->can_queue, ATA_MAX_QUEUE - 1); + dev->flags |= ATA_DFLAG_NCQ; + } + + if (hdepth >= ddepth) + snprintf(desc, desc_sz, "NCQ (depth %d)", ddepth); + else + snprintf(desc, desc_sz, "NCQ (depth %d/%d)", hdepth, ddepth); +} + /** * ata_dev_configure - Configure the specified ATA/ATAPI device * @dev: Target device to configure @@ -1311,6 +1333,7 @@ static int ata_dev_configure(struct ata_device *dev, int print_info) if (ata_id_has_lba(id)) { const char *lba_desc; + char ncq_desc[20]; lba_desc = "LBA"; dev->flags |= ATA_DFLAG_LBA; @@ -1319,14 +1342,17 @@ static int ata_dev_configure(struct ata_device *dev, int print_info) lba_desc = "LBA48"; } + /* config NCQ */ + ata_dev_config_ncq(dev, ncq_desc, sizeof(ncq_desc)); + /* print device info to dmesg */ if (print_info) ata_dev_printk(dev, KERN_INFO, "ATA-%d, " - "max %s, %Lu sectors: %s\n", + "max %s, %Lu sectors: %s %s\n", ata_id_major_version(id), ata_mode_string(xfer_mask), (unsigned long long)dev->n_sectors, - lba_desc); + lba_desc, ncq_desc); } else { /* CHS */ @@ -5675,6 +5701,7 @@ EXPORT_SYMBOL_GPL(ata_port_queue_task); EXPORT_SYMBOL_GPL(ata_scsi_ioctl); EXPORT_SYMBOL_GPL(ata_scsi_queuecmd); EXPORT_SYMBOL_GPL(ata_scsi_slave_config); +EXPORT_SYMBOL_GPL(ata_scsi_change_queue_depth); EXPORT_SYMBOL_GPL(ata_scsi_release); EXPORT_SYMBOL_GPL(ata_host_intr); EXPORT_SYMBOL_GPL(sata_scr_valid); diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 9bef68c7c1d..996058af1bc 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -684,6 +685,14 @@ static void ata_scsi_dev_config(struct scsi_device *sdev, request_queue_t *q = sdev->request_queue; blk_queue_max_hw_segments(q, q->max_hw_segments - 1); } + + if (dev->flags & ATA_DFLAG_NCQ) { + int depth; + + depth = min(sdev->host->can_queue, ata_id_queue_depth(dev->id)); + depth = min(ATA_MAX_QUEUE - 1, depth); + scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, depth); + } } /** @@ -717,6 +726,43 @@ int ata_scsi_slave_config(struct scsi_device *sdev) return 0; /* scsi layer doesn't check return value, sigh */ } +/** + * ata_scsi_change_queue_depth - SCSI callback for queue depth config + * @sdev: SCSI device to configure queue depth for + * @queue_depth: new queue depth + * + * This is libata standard hostt->change_queue_depth callback. + * SCSI will call into this callback when user tries to set queue + * depth via sysfs. + * + * LOCKING: + * SCSI layer (we don't care) + * + * RETURNS: + * Newly configured queue depth. + */ +int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth) +{ + struct ata_port *ap = ata_shost_to_port(sdev->host); + struct ata_device *dev; + int max_depth; + + if (queue_depth < 1) + return sdev->queue_depth; + + dev = ata_scsi_find_dev(ap, sdev); + if (!dev || !ata_dev_enabled(dev)) + return sdev->queue_depth; + + max_depth = min(sdev->host->can_queue, ata_id_queue_depth(dev->id)); + max_depth = min(ATA_MAX_QUEUE - 1, max_depth); + if (queue_depth > max_depth) + queue_depth = max_depth; + + scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, queue_depth); + return queue_depth; +} + /** * ata_scsi_start_stop_xlat - Translate SCSI START STOP UNIT command * @qc: Storage for translated ATA taskfile diff --git a/include/linux/libata.h b/include/linux/libata.h index dd0db2d21bc..fcdd798bb08 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -109,7 +109,7 @@ enum { ATA_MAX_PORTS = 8, ATA_DEF_QUEUE = 1, /* tag ATA_MAX_QUEUE - 1 is reserved for internal commands */ - ATA_MAX_QUEUE = 2, + ATA_MAX_QUEUE = 32, ATA_TAG_INTERNAL = ATA_MAX_QUEUE - 1, ATA_MAX_SECTORS = 200, /* FIXME */ ATA_MAX_BUS = 2, @@ -679,6 +679,8 @@ extern int ata_std_bios_param(struct scsi_device *sdev, struct block_device *bdev, sector_t capacity, int geom[]); extern int ata_scsi_slave_config(struct scsi_device *sdev); +extern int ata_scsi_change_queue_depth(struct scsi_device *sdev, + int queue_depth); extern struct ata_device *ata_dev_pair(struct ata_device *adev); /* -- cgit v1.2.3 From dd410ff12925fc49df3174b18e43598b2b2b621f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 21:03:50 +0900 Subject: [PATCH] ahci: clean up AHCI constants in preparation for NCQ * Rename CMD_TBL_HDR to CMD_TBL_HDR_SZ as it's size not offset. * Define MAX_CMDS and CMD_SZ and use them in calculation of other constants. * Define CMD_TBL_AR_SZ as product of CMD_TBL_SZ and MAX_CMDS, and use it when calculating PRIV_DMA_SZ. * CMD_SLOT_SZ is also dependent on MAX_CMDS but hasn't been changed because I didn't want to change the value used by the original code (32 commands). Later NCQ change will bump MAX_CMDS to 32 anyway and the hard coded 32 can be changed to MAX_CMDS then. * Reorder HOST_CAP_* flags. Signed-off-by: Tejun Heo --- drivers/scsi/ahci.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 35487e30b0f..b25373f530a 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -56,12 +56,15 @@ enum { AHCI_MAX_SG = 168, /* hardware max is 64K */ AHCI_DMA_BOUNDARY = 0xffffffff, AHCI_USE_CLUSTERING = 0, - AHCI_CMD_SLOT_SZ = 32 * 32, + AHCI_MAX_CMDS = 1, + AHCI_CMD_SZ = 32, + AHCI_CMD_SLOT_SZ = 32 * AHCI_CMD_SZ, AHCI_RX_FIS_SZ = 256, - AHCI_CMD_TBL_HDR = 0x80, AHCI_CMD_TBL_CDB = 0x40, - AHCI_CMD_TBL_SZ = AHCI_CMD_TBL_HDR + (AHCI_MAX_SG * 16), - AHCI_PORT_PRIV_DMA_SZ = AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_SZ + + AHCI_CMD_TBL_HDR_SZ = 0x80, + AHCI_CMD_TBL_SZ = AHCI_CMD_TBL_HDR_SZ + (AHCI_MAX_SG * 16), + AHCI_CMD_TBL_AR_SZ = AHCI_CMD_TBL_SZ * AHCI_MAX_CMDS, + AHCI_PORT_PRIV_DMA_SZ = AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_AR_SZ + AHCI_RX_FIS_SZ, AHCI_IRQ_ON_SG = (1 << 31), AHCI_CMD_ATAPI = (1 << 5), @@ -89,8 +92,8 @@ enum { HOST_AHCI_EN = (1 << 31), /* AHCI enabled */ /* HOST_CAP bits */ - HOST_CAP_64 = (1 << 31), /* PCI DAC (64-bit DMA) support */ HOST_CAP_CLO = (1 << 24), /* Command List Override support */ + HOST_CAP_64 = (1 << 31), /* PCI DAC (64-bit DMA) support */ /* registers for each SATA port */ PORT_LST_ADDR = 0x00, /* command list DMA addr */ @@ -398,7 +401,7 @@ static int ahci_port_start(struct ata_port *ap) pp->cmd_tbl = mem; pp->cmd_tbl_dma = mem_dma; - pp->cmd_tbl_sg = mem + AHCI_CMD_TBL_HDR; + pp->cmd_tbl_sg = mem + AHCI_CMD_TBL_HDR_SZ; ap->private_data = pp; -- cgit v1.2.3 From 979db803b8fd120d4ed5216520e9d1815e18bc38 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 21:03:52 +0900 Subject: [PATCH] ahci: add HOST_CAP_NCQ constant Add HOST_CAP_NCQ. Signed-off-by: Tejun Heo --- drivers/scsi/ahci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index b25373f530a..740e7d86d5f 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -93,6 +93,7 @@ enum { /* HOST_CAP bits */ HOST_CAP_CLO = (1 << 24), /* Command List Override support */ + HOST_CAP_NCQ = (1 << 30), /* Native Command Queueing */ HOST_CAP_64 = (1 << 31), /* PCI DAC (64-bit DMA) support */ /* registers for each SATA port */ -- cgit v1.2.3 From a9764c2bb5b6d3c9df91f2977a2a640f55de0dc2 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 21:03:53 +0900 Subject: [PATCH] ahci: kill pp->cmd_tbl_sg With NCQ, there are multiple sg tables, so pp->cmd_tbl_sg doesn't cut it. Directly calculate sg table address from pp->cmd_tbl. Signed-off-by: Tejun Heo --- drivers/scsi/ahci.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 740e7d86d5f..9f974dbcd7e 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -191,7 +191,6 @@ struct ahci_port_priv { dma_addr_t cmd_slot_dma; void *cmd_tbl; dma_addr_t cmd_tbl_dma; - struct ahci_sg *cmd_tbl_sg; void *rx_fis; dma_addr_t rx_fis_dma; }; @@ -402,8 +401,6 @@ static int ahci_port_start(struct ata_port *ap) pp->cmd_tbl = mem; pp->cmd_tbl_dma = mem_dma; - pp->cmd_tbl_sg = mem + AHCI_CMD_TBL_HDR_SZ; - ap->private_data = pp; if (hpriv->cap & HOST_CAP_64) @@ -749,7 +746,7 @@ static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc) /* * Next, the S/G list. */ - ahci_sg = pp->cmd_tbl_sg; + ahci_sg = pp->cmd_tbl + AHCI_CMD_TBL_HDR_SZ; ata_for_each_sg(sg, qc) { dma_addr_t addr = sg_dma_address(sg); u32 sg_len = sg_dma_len(sg); -- cgit v1.2.3 From 12fad3f965830d71f6454f02b2af002a64cec4d3 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 21:03:55 +0900 Subject: [PATCH] ahci: implement NCQ suppport Implement NCQ support. Original implementation is from Jens Axboe. Signed-off-by: Tejun Heo --- drivers/scsi/ahci.c | 89 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 58 insertions(+), 31 deletions(-) diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 9f974dbcd7e..45fd71d8012 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -56,9 +56,9 @@ enum { AHCI_MAX_SG = 168, /* hardware max is 64K */ AHCI_DMA_BOUNDARY = 0xffffffff, AHCI_USE_CLUSTERING = 0, - AHCI_MAX_CMDS = 1, + AHCI_MAX_CMDS = 32, AHCI_CMD_SZ = 32, - AHCI_CMD_SLOT_SZ = 32 * AHCI_CMD_SZ, + AHCI_CMD_SLOT_SZ = AHCI_MAX_CMDS * AHCI_CMD_SZ, AHCI_RX_FIS_SZ = 256, AHCI_CMD_TBL_CDB = 0x40, AHCI_CMD_TBL_HDR_SZ = 0x80, @@ -218,7 +218,8 @@ static struct scsi_host_template ahci_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, + .change_queue_depth = ata_scsi_change_queue_depth, + .can_queue = AHCI_MAX_CMDS - 1, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = AHCI_MAX_SG, .cmd_per_lun = ATA_SHT_CMD_PER_LUN, @@ -533,12 +534,17 @@ static unsigned int ahci_dev_classify(struct ata_port *ap) return ata_dev_classify(&tf); } -static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, u32 opts) +static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag, + u32 opts) { - pp->cmd_slot[0].opts = cpu_to_le32(opts); - pp->cmd_slot[0].status = 0; - pp->cmd_slot[0].tbl_addr = cpu_to_le32(pp->cmd_tbl_dma & 0xffffffff); - pp->cmd_slot[0].tbl_addr_hi = cpu_to_le32((pp->cmd_tbl_dma >> 16) >> 16); + dma_addr_t cmd_tbl_dma; + + cmd_tbl_dma = pp->cmd_tbl_dma + tag * AHCI_CMD_TBL_SZ; + + pp->cmd_slot[tag].opts = cpu_to_le32(opts); + pp->cmd_slot[tag].status = 0; + pp->cmd_slot[tag].tbl_addr = cpu_to_le32(cmd_tbl_dma & 0xffffffff); + pp->cmd_slot[tag].tbl_addr_hi = cpu_to_le32((cmd_tbl_dma >> 16) >> 16); } static int ahci_clo(struct ata_port *ap) @@ -610,7 +616,8 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class) fis = pp->cmd_tbl; /* issue the first D2H Register FIS */ - ahci_fill_cmd_slot(pp, cmd_fis_len | AHCI_CMD_RESET | AHCI_CMD_CLR_BUSY); + ahci_fill_cmd_slot(pp, 0, + cmd_fis_len | AHCI_CMD_RESET | AHCI_CMD_CLR_BUSY); tf.ctl |= ATA_SRST; ata_tf_to_fis(&tf, fis, 0); @@ -629,7 +636,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class) msleep(1); /* issue the second D2H Register FIS */ - ahci_fill_cmd_slot(pp, cmd_fis_len); + ahci_fill_cmd_slot(pp, 0, cmd_fis_len); tf.ctl &= ~ATA_SRST; ata_tf_to_fis(&tf, fis, 0); @@ -734,9 +741,8 @@ static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf) ata_tf_from_fis(d2h_fis, tf); } -static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc) +static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl) { - struct ahci_port_priv *pp = qc->ap->private_data; struct scatterlist *sg; struct ahci_sg *ahci_sg; unsigned int n_sg = 0; @@ -746,7 +752,7 @@ static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc) /* * Next, the S/G list. */ - ahci_sg = pp->cmd_tbl + AHCI_CMD_TBL_HDR_SZ; + ahci_sg = cmd_tbl + AHCI_CMD_TBL_HDR_SZ; ata_for_each_sg(sg, qc) { dma_addr_t addr = sg_dma_address(sg); u32 sg_len = sg_dma_len(sg); @@ -767,6 +773,7 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc) struct ata_port *ap = qc->ap; struct ahci_port_priv *pp = ap->private_data; int is_atapi = is_atapi_taskfile(&qc->tf); + void *cmd_tbl; u32 opts; const u32 cmd_fis_len = 5; /* five dwords */ unsigned int n_elem; @@ -775,16 +782,17 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc) * Fill in command table information. First, the header, * a SATA Register - Host to Device command FIS. */ - ata_tf_to_fis(&qc->tf, pp->cmd_tbl, 0); + cmd_tbl = pp->cmd_tbl + qc->tag * AHCI_CMD_TBL_SZ; + + ata_tf_to_fis(&qc->tf, cmd_tbl, 0); if (is_atapi) { - memset(pp->cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32); - memcpy(pp->cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, - qc->dev->cdb_len); + memset(cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32); + memcpy(cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, qc->dev->cdb_len); } n_elem = 0; if (qc->flags & ATA_QCFLAG_DMAMAP) - n_elem = ahci_fill_sg(qc); + n_elem = ahci_fill_sg(qc, cmd_tbl); /* * Fill in command slot information. @@ -795,7 +803,7 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc) if (is_atapi) opts |= AHCI_CMD_ATAPI | AHCI_CMD_PREFETCH; - ahci_fill_cmd_slot(pp, opts); + ahci_fill_cmd_slot(pp, qc->tag, opts); } static void ahci_error_intr(struct ata_port *ap, u32 irq_stat) @@ -865,8 +873,9 @@ static void ahci_host_intr(struct ata_port *ap) { void __iomem *mmio = ap->host_set->mmio_base; void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); - struct ata_queued_cmd *qc; - u32 status, ci; + struct ata_eh_info *ehi = &ap->eh_info; + u32 status, qc_active; + int rc; status = readl(port_mmio + PORT_IRQ_STAT); writel(status, port_mmio + PORT_IRQ_STAT); @@ -876,16 +885,27 @@ static void ahci_host_intr(struct ata_port *ap) return; } - if ((qc = ata_qc_from_tag(ap, ap->active_tag))) { - ci = readl(port_mmio + PORT_CMD_ISSUE); - if ((ci & 0x1) == 0) { - ata_qc_complete(qc); - return; - } + if (ap->sactive) + qc_active = readl(port_mmio + PORT_SCR_ACT); + else + qc_active = readl(port_mmio + PORT_CMD_ISSUE); + + rc = ata_qc_complete_multiple(ap, qc_active, NULL); + if (rc > 0) + return; + if (rc < 0) { + ehi->err_mask |= AC_ERR_HSM; + ehi->action |= ATA_EH_SOFTRESET; + ata_port_freeze(ap); + return; } /* hmmm... a spurious interupt */ + /* some devices send D2H reg with I bit set during NCQ command phase */ + if (ap->sactive && status & PORT_IRQ_D2H_REG_FIS) + return; + /* ignore interim PIO setup fis interrupts */ if (ata_tag_valid(ap->active_tag)) { struct ata_queued_cmd *qc = @@ -898,8 +918,8 @@ static void ahci_host_intr(struct ata_port *ap) if (ata_ratelimit()) ata_port_printk(ap, KERN_INFO, "spurious interrupt " - "(irq_stat 0x%x active_tag %d)\n", - status, ap->active_tag); + "(irq_stat 0x%x active_tag %d sactive 0x%x)\n", + status, ap->active_tag, ap->sactive); } static void ahci_irq_clear(struct ata_port *ap) @@ -907,7 +927,7 @@ static void ahci_irq_clear(struct ata_port *ap) /* TODO */ } -static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *regs) +static irqreturn_t ahci_interrupt(int irq, void *dev_instance, struct pt_regs *regs) { struct ata_host_set *host_set = dev_instance; struct ahci_host_priv *hpriv; @@ -965,7 +985,9 @@ static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc) struct ata_port *ap = qc->ap; void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr; - writel(1, port_mmio + PORT_CMD_ISSUE); + if (qc->tf.protocol == ATA_PROT_NCQ) + writel(1 << qc->tag, port_mmio + PORT_SCR_ACT); + writel(1 << qc->tag, port_mmio + PORT_CMD_ISSUE); readl(port_mmio + PORT_CMD_ISSUE); /* flush */ return 0; @@ -1262,6 +1284,8 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) VPRINTK("ENTER\n"); + WARN_ON(ATA_MAX_QUEUE > AHCI_MAX_CMDS); + if (!printed_version++) dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); @@ -1329,6 +1353,9 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) if (rc) goto err_out_hpriv; + if (hpriv->cap & HOST_CAP_NCQ) + probe_ent->host_flags |= ATA_FLAG_NCQ; + ahci_print_info(probe_ent); /* FIXME: check ata_device_add return value */ -- cgit v1.2.3 From aee10a03eb3e240bfd1a6f91e06ce82df47c5c58 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 21:03:56 +0900 Subject: [PATCH] sata_sil24: implement NCQ support Implement NCQ support. Sil24 has 31 command slots and all of them are used for NCQ command queueing. libata guarantees that no other command is in progress when it issues an internal command, so always use tag 0 for internal commands. Signed-off-by: Tejun Heo --- drivers/scsi/sata_sil24.c | 68 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 21 deletions(-) diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 6e7728cfaf6..4c76f05d9b6 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -216,6 +216,8 @@ enum { SGE_DRD = (1 << 29), /* discard data read (/dev/null) data address ignored */ + SIL24_MAX_CMDS = 31, + /* board id */ BID_SIL3124 = 0, BID_SIL3132 = 1, @@ -223,7 +225,8 @@ enum { /* host flags */ SIL24_COMMON_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA, + ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | + ATA_FLAG_NCQ, SIL24_FLAG_PCIX_IRQ_WOC = (1 << 24), /* IRQ loss errata on PCI-X */ IRQ_STAT_4PORTS = 0xf, @@ -355,7 +358,8 @@ static struct scsi_host_template sil24_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, + .change_queue_depth = ata_scsi_change_queue_depth, + .can_queue = SIL24_MAX_CMDS, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = LIBATA_MAX_PRD, .cmd_per_lun = ATA_SHT_CMD_PER_LUN, @@ -437,6 +441,13 @@ static struct ata_port_info sil24_port_info[] = { }, }; +static int sil24_tag(int tag) +{ + if (unlikely(ata_tag_internal(tag))) + return 0; + return tag; +} + static void sil24_dev_config(struct ata_port *ap, struct ata_device *dev) { void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; @@ -649,14 +660,17 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; struct sil24_port_priv *pp = ap->private_data; - union sil24_cmd_block *cb = pp->cmd_block + qc->tag; + union sil24_cmd_block *cb; struct sil24_prb *prb; struct sil24_sge *sge; u16 ctrl = 0; + cb = &pp->cmd_block[sil24_tag(qc->tag)]; + switch (qc->tf.protocol) { case ATA_PROT_PIO: case ATA_PROT_DMA: + case ATA_PROT_NCQ: case ATA_PROT_NODATA: prb = &cb->ata.prb; sge = cb->ata.sge; @@ -694,12 +708,17 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc) static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; - void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; struct sil24_port_priv *pp = ap->private_data; - dma_addr_t paddr = pp->cmd_block_dma + qc->tag * sizeof(*pp->cmd_block); + void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; + unsigned int tag = sil24_tag(qc->tag); + dma_addr_t paddr; + void __iomem *activate; - writel((u32)paddr, port + PORT_CMD_ACTIVATE); - writel((u64)paddr >> 32, port + PORT_CMD_ACTIVATE + 4); + paddr = pp->cmd_block_dma + tag * sizeof(*pp->cmd_block); + activate = port + PORT_CMD_ACTIVATE + tag * 8; + + writel((u32)paddr, activate); + writel((u64)paddr >> 32, activate + 4); return 0; } @@ -791,9 +810,6 @@ static void sil24_error_intr(struct ata_port *ap) /* record error info */ qc = ata_qc_from_tag(ap, ap->active_tag); if (qc) { - int tag = qc->tag; - if (unlikely(ata_tag_internal(tag))) - tag = 0; sil24_update_tf(ap); qc->err_mask |= err_mask; } else @@ -809,11 +825,17 @@ static void sil24_error_intr(struct ata_port *ap) ata_port_abort(ap); } +static void sil24_finish_qc(struct ata_queued_cmd *qc) +{ + if (qc->flags & ATA_QCFLAG_RESULT_TF) + sil24_update_tf(qc->ap); +} + static inline void sil24_host_intr(struct ata_port *ap) { void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; - struct ata_queued_cmd *qc; - u32 slot_stat; + u32 slot_stat, qc_active; + int rc; slot_stat = readl(port + PORT_SLOT_STAT); @@ -825,18 +847,22 @@ static inline void sil24_host_intr(struct ata_port *ap) if (ap->flags & SIL24_FLAG_PCIX_IRQ_WOC) writel(PORT_IRQ_COMPLETE, port + PORT_IRQ_STAT); - qc = ata_qc_from_tag(ap, ap->active_tag); - if (qc) { - if (qc->flags & ATA_QCFLAG_RESULT_TF) - sil24_update_tf(ap); - ata_qc_complete(qc); + qc_active = slot_stat & ~HOST_SSTAT_ATTN; + rc = ata_qc_complete_multiple(ap, qc_active, sil24_finish_qc); + if (rc > 0) + return; + if (rc < 0) { + struct ata_eh_info *ehi = &ap->eh_info; + ehi->err_mask |= AC_ERR_HSM; + ehi->action |= ATA_EH_SOFTRESET; + ata_port_freeze(ap); return; } if (ata_ratelimit()) ata_port_printk(ap, KERN_INFO, "spurious interrupt " - "(slot_stat 0x%x active_tag %d)\n", - slot_stat, ap->active_tag); + "(slot_stat 0x%x active_tag %d sactive 0x%x)\n", + slot_stat, ap->active_tag, ap->sactive); } static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *regs) @@ -903,7 +929,7 @@ static void sil24_post_internal_cmd(struct ata_queued_cmd *qc) static inline void sil24_cblk_free(struct sil24_port_priv *pp, struct device *dev) { - const size_t cb_size = sizeof(*pp->cmd_block); + const size_t cb_size = sizeof(*pp->cmd_block) * SIL24_MAX_CMDS; dma_free_coherent(dev, cb_size, pp->cmd_block, pp->cmd_block_dma); } @@ -913,7 +939,7 @@ static int sil24_port_start(struct ata_port *ap) struct device *dev = ap->host_set->dev; struct sil24_port_priv *pp; union sil24_cmd_block *cb; - size_t cb_size = sizeof(*cb); + size_t cb_size = sizeof(*cb) * SIL24_MAX_CMDS; dma_addr_t cb_dma; int rc = -ENOMEM; -- cgit v1.2.3 From 4240545661fc0ac25122f166e96633527150300c Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 28 Apr 2006 17:39:38 -0500 Subject: [PATCH] powerpc/pseries: Increment fail counter in PCI recovery When a PCI device driver does not support PCI error recovery, the powerpc/pseries code takes a walk through a branch of code that resets the failure counter. Because of this, if a broken PCI card is present, the kernel will attempt to reset it an infinite number of times. (This is annoying but mostly harmless: each reset takes about 10-20 seconds, and uses almost no CPU time). This patch preserves the failure count across resets. Signed-off-by: Linas Vepstas Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/pseries/eeh_driver.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c index 2a9eb263073..4d45347afab 100644 --- a/arch/powerpc/platforms/pseries/eeh_driver.c +++ b/arch/powerpc/platforms/pseries/eeh_driver.c @@ -201,7 +201,11 @@ static void eeh_report_failure(struct pci_dev *dev, void *userdata) static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus) { - int rc; + int cnt, rc; + + /* pcibios will clear the counter; save the value */ + cnt = pe_dn->eeh_freeze_count; + if (bus) pcibios_remove_pci_devices(bus); @@ -240,6 +244,7 @@ static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus) ssleep (5); pcibios_add_pci_devices(bus); } + pe_dn->eeh_freeze_count = cnt; return 0; } -- cgit v1.2.3 From b26f100d89c87060b561c3108582b7cb81521df8 Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Fri, 19 May 2006 14:24:18 +1000 Subject: [PATCH] powerpc: remove do-nothing cpu setup routines Removed the do-nothing routines __setup_cpu_power3 and __setup_cpu_power4 and replaced them with a null pointer check in the caller. Also removed the Cell processor specific routine __setup_cpu_be which improperly accessed the hypervisor page size configuration at SPR HID6. Signed-off-by: Geoff Levand Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/cpu_setup_power4.S | 17 ----------------- arch/powerpc/kernel/cputable.c | 19 +------------------ arch/powerpc/kernel/misc_32.S | 2 +- arch/powerpc/kernel/misc_64.S | 5 ++--- 4 files changed, 4 insertions(+), 39 deletions(-) diff --git a/arch/powerpc/kernel/cpu_setup_power4.S b/arch/powerpc/kernel/cpu_setup_power4.S index b61d86e7ceb..271418308d5 100644 --- a/arch/powerpc/kernel/cpu_setup_power4.S +++ b/arch/powerpc/kernel/cpu_setup_power4.S @@ -73,23 +73,6 @@ _GLOBAL(__970_cpu_preinit) isync blr -_GLOBAL(__setup_cpu_power4) - blr - -_GLOBAL(__setup_cpu_be) - /* Set large page sizes LP=0: 16MB, LP=1: 64KB */ - addi r3, 0, 0 - ori r3, r3, HID6_LB - sldi r3, r3, 32 - nor r3, r3, r3 - mfspr r4, SPRN_HID6 - and r4, r4, r3 - addi r3, 0, 0x02000 - sldi r3, r3, 32 - or r4, r4, r3 - mtspr SPRN_HID6, r4 - blr - _GLOBAL(__setup_cpu_ppc970) mfspr r0,SPRN_HID0 li r11,5 /* clear DOZE and SLEEP */ diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 3f7182db9ed..0c487ee4d48 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -30,11 +30,7 @@ EXPORT_SYMBOL(cur_cpu_spec); * part of the cputable though. That has to be fixed for both ppc32 * and ppc64 */ -#ifdef CONFIG_PPC64 -extern void __setup_cpu_power3(unsigned long offset, struct cpu_spec* spec); -extern void __setup_cpu_power4(unsigned long offset, struct cpu_spec* spec); -extern void __setup_cpu_be(unsigned long offset, struct cpu_spec* spec); -#else +#ifdef CONFIG_PPC32 extern void __setup_cpu_603(unsigned long offset, struct cpu_spec* spec); extern void __setup_cpu_604(unsigned long offset, struct cpu_spec* spec); extern void __setup_cpu_750(unsigned long offset, struct cpu_spec* spec); @@ -82,7 +78,6 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 8, - .cpu_setup = __setup_cpu_power3, .oprofile_cpu_type = "ppc64/power3", .oprofile_type = PPC_OPROFILE_RS64, .platform = "power3", @@ -96,7 +91,6 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 8, - .cpu_setup = __setup_cpu_power3, .oprofile_cpu_type = "ppc64/power3", .oprofile_type = PPC_OPROFILE_RS64, .platform = "power3", @@ -110,7 +104,6 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 8, - .cpu_setup = __setup_cpu_power3, .oprofile_cpu_type = "ppc64/rs64", .oprofile_type = PPC_OPROFILE_RS64, .platform = "rs64", @@ -124,7 +117,6 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 8, - .cpu_setup = __setup_cpu_power3, .oprofile_cpu_type = "ppc64/rs64", .oprofile_type = PPC_OPROFILE_RS64, .platform = "rs64", @@ -138,7 +130,6 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 8, - .cpu_setup = __setup_cpu_power3, .oprofile_cpu_type = "ppc64/rs64", .oprofile_type = PPC_OPROFILE_RS64, .platform = "rs64", @@ -152,7 +143,6 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 8, - .cpu_setup = __setup_cpu_power3, .oprofile_cpu_type = "ppc64/rs64", .oprofile_type = PPC_OPROFILE_RS64, .platform = "rs64", @@ -166,7 +156,6 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 8, - .cpu_setup = __setup_cpu_power4, .oprofile_cpu_type = "ppc64/power4", .oprofile_type = PPC_OPROFILE_POWER4, .platform = "power4", @@ -180,7 +169,6 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 8, - .cpu_setup = __setup_cpu_power4, .oprofile_cpu_type = "ppc64/power4", .oprofile_type = PPC_OPROFILE_POWER4, .platform = "power4", @@ -246,7 +234,6 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 6, - .cpu_setup = __setup_cpu_power4, .oprofile_cpu_type = "ppc64/power5", .oprofile_type = PPC_OPROFILE_POWER4, .platform = "power5", @@ -260,7 +247,6 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 6, - .cpu_setup = __setup_cpu_power4, .oprofile_cpu_type = "ppc64/power5+", .oprofile_type = PPC_OPROFILE_POWER4, .platform = "power5+", @@ -274,7 +260,6 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 6, - .cpu_setup = __setup_cpu_power4, .oprofile_cpu_type = "ppc64/power6", .oprofile_type = PPC_OPROFILE_POWER4, .platform = "power6", @@ -289,7 +274,6 @@ struct cpu_spec cpu_specs[] = { PPC_FEATURE_SMT, .icache_bsize = 128, .dcache_bsize = 128, - .cpu_setup = __setup_cpu_be, .platform = "ppc-cell-be", }, { /* default match */ @@ -301,7 +285,6 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 6, - .cpu_setup = __setup_cpu_power4, .platform = "power4", } #endif /* CONFIG_PPC64 */ diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index be982023409..01d3916c4cb 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S @@ -216,7 +216,7 @@ _GLOBAL(call_setup_cpu) lwz r4,0(r4) add r4,r4,r3 lwz r5,CPU_SPEC_SETUP(r4) - cmpi 0,r5,0 + cmpwi 0,r5,0 add r5,r5,r3 beqlr mtctr r5 diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S index 2778cce058e..e8883d42c43 100644 --- a/arch/powerpc/kernel/misc_64.S +++ b/arch/powerpc/kernel/misc_64.S @@ -482,7 +482,9 @@ _GLOBAL(identify_cpu) sub r0,r3,r5 std r0,0(r4) ld r4,CPU_SPEC_SETUP(r3) + cmpdi 0,r4,0 add r4,r4,r5 + beqlr ld r4,0(r4) add r4,r4,r5 mtctr r4 @@ -768,9 +770,6 @@ _GLOBAL(giveup_altivec) #endif /* CONFIG_ALTIVEC */ -_GLOBAL(__setup_cpu_power3) - blr - _GLOBAL(execve) li r0,__NR_execve sc -- cgit v1.2.3 From 485a2d54dbc7cf939bd0c22daad74e2cf6f001d7 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 9 May 2006 16:03:51 +1000 Subject: [PATCH] powerpc: Make early debugging options behave with oldconfig If you undefine all the early debugging options and then run make oldconfig, you don't get prompted to see if you want to enable any of them. This is annoying. AFAICT we can't do this just with a choice, because the choice is either optional, in which case we don't get prompted, or not in which case we _must_ select early debugging. So add a bool which controls whether we have early debugging at all, and then if that's enabled provide the choice. The extra bool will actually be useful in another patch I have lying around, so this is a win-win. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/Kconfig.debug | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug index 8d48e9e7162..c69006ae824 100644 --- a/arch/powerpc/Kconfig.debug +++ b/arch/powerpc/Kconfig.debug @@ -110,13 +110,16 @@ config SERIAL_TEXT_DEBUG depends on 4xx || LOPEC || MV64X60 || PPLUS || PRPMC800 || \ PPC_GEN550 || PPC_MPC52xx +config PPC_EARLY_DEBUG + bool "Early debugging (dangerous)" + choice - prompt "Early debugging (dangerous)" - bool - optional + prompt "Early debugging console" + depends on PPC_EARLY_DEBUG help - Enable early debugging. Careful, if you enable debugging for the - wrong type of machine your kernel _will not boot_. + Use the selected console for early debugging. Careful, if you + enable debugging for the wrong type of machine your kernel + _will not boot_. config PPC_EARLY_DEBUG_LPAR bool "LPAR HV Console" -- cgit v1.2.3 From d6b89a196dfb03fdfbe3d574ab6773fe14a1d2c6 Mon Sep 17 00:00:00 2001 From: Michael Neuling Date: Tue, 9 May 2006 11:33:38 -0500 Subject: [PATCH] powerpc: whitespace cleanup in reg.h In reg.h we mostly have #define but there are a few #define around. Clean these up so we use space exclusively. Signed-off-by: Michael Neuling Signed-off-by: Paul Mackerras --- include/asm-powerpc/reg.h | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/include/asm-powerpc/reg.h b/include/asm-powerpc/reg.h index bd467bf5cf5..0257189d501 100644 --- a/include/asm-powerpc/reg.h +++ b/include/asm-powerpc/reg.h @@ -153,7 +153,7 @@ #define SPRN_DABR 0x3F5 /* Data Address Breakpoint Register */ #define DABR_TRANSLATION (1UL << 2) #define SPRN_DAR 0x013 /* Data Address Register */ -#define SPRN_DSISR 0x012 /* Data Storage Interrupt Status Register */ +#define SPRN_DSISR 0x012 /* Data Storage Interrupt Status Register */ #define DSISR_NOHPTE 0x40000000 /* no translation found */ #define DSISR_PROTFAULT 0x08000000 /* protection fault */ #define DSISR_ISSTORE 0x02000000 /* access was a store */ @@ -258,16 +258,16 @@ #define SPRN_IABR 0x3F2 /* Instruction Address Breakpoint Register */ #define SPRN_HID4 0x3F4 /* 970 HID4 */ #define SPRN_HID5 0x3F6 /* 970 HID5 */ -#define SPRN_HID6 0x3F9 /* BE HID 6 */ -#define HID6_LB (0x0F<<12) /* Concurrent Large Page Modes */ -#define HID6_DLP (1<<20) /* Disable all large page modes (4K only) */ -#define SPRN_TSC_CELL 0x399 /* Thread switch control on Cell */ -#define TSC_CELL_DEC_ENABLE_0 0x400000 /* Decrementer Interrupt */ -#define TSC_CELL_DEC_ENABLE_1 0x200000 /* Decrementer Interrupt */ -#define TSC_CELL_EE_ENABLE 0x100000 /* External Interrupt */ -#define TSC_CELL_EE_BOOST 0x080000 /* External Interrupt Boost */ -#define SPRN_TSC 0x3FD /* Thread switch control on others */ -#define SPRN_TST 0x3FC /* Thread switch timeout on others */ +#define SPRN_HID6 0x3F9 /* BE HID 6 */ +#define HID6_LB (0x0F<<12) /* Concurrent Large Page Modes */ +#define HID6_DLP (1<<20) /* Disable all large page modes (4K only) */ +#define SPRN_TSC_CELL 0x399 /* Thread switch control on Cell */ +#define TSC_CELL_DEC_ENABLE_0 0x400000 /* Decrementer Interrupt */ +#define TSC_CELL_DEC_ENABLE_1 0x200000 /* Decrementer Interrupt */ +#define TSC_CELL_EE_ENABLE 0x100000 /* External Interrupt */ +#define TSC_CELL_EE_BOOST 0x080000 /* External Interrupt Boost */ +#define SPRN_TSC 0x3FD /* Thread switch control on others */ +#define SPRN_TST 0x3FC /* Thread switch timeout on others */ #if !defined(SPRN_IAC1) && !defined(SPRN_IAC2) #define SPRN_IAC1 0x3F4 /* Instruction Address Compare 1 */ #define SPRN_IAC2 0x3F5 /* Instruction Address Compare 2 */ @@ -362,7 +362,7 @@ #endif #define SPRN_PTEHI 0x3D5 /* 981 7450 PTE HI word (S/W TLB load) */ #define SPRN_PTELO 0x3D6 /* 982 7450 PTE LO word (S/W TLB load) */ -#define SPRN_PURR 0x135 /* Processor Utilization of Resources Reg */ +#define SPRN_PURR 0x135 /* Processor Utilization of Resources Reg */ #define SPRN_PVR 0x11F /* Processor Version Register */ #define SPRN_RPA 0x3D6 /* Required Physical Address Register */ #define SPRN_SDA 0x3BF /* Sampled Data Address Register */ @@ -559,20 +559,20 @@ /* 64-bit processors */ /* XXX the prefix should be PVR_, we'll do a global sweep to fix it one day */ -#define PV_NORTHSTAR 0x0033 -#define PV_PULSAR 0x0034 -#define PV_POWER4 0x0035 -#define PV_ICESTAR 0x0036 -#define PV_SSTAR 0x0037 -#define PV_POWER4p 0x0038 +#define PV_NORTHSTAR 0x0033 +#define PV_PULSAR 0x0034 +#define PV_POWER4 0x0035 +#define PV_ICESTAR 0x0036 +#define PV_SSTAR 0x0037 +#define PV_POWER4p 0x0038 #define PV_970 0x0039 -#define PV_POWER5 0x003A +#define PV_POWER5 0x003A #define PV_POWER5p 0x003B #define PV_970FX 0x003C -#define PV_630 0x0040 -#define PV_630p 0x0041 -#define PV_970MP 0x0044 -#define PV_BE 0x0070 +#define PV_630 0x0040 +#define PV_630p 0x0041 +#define PV_970MP 0x0044 +#define PV_BE 0x0070 /* * Number of entries in the SLB. If this ever changes we should handle -- cgit v1.2.3 From 07fb3f454cc9e0f656e378a6feb5bdd6cac4bd41 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Mon, 15 May 2006 13:39:47 +1000 Subject: [PATCH] powerpc: update iseries_veth device-tree information Make the device-tree information more generic and more like the pSeries virtual lan device. Also use the MAC address from the device tree. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/setup.c | 8 +++++--- drivers/net/iseries_veth.c | 27 +++++++++++++++++---------- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index befd36af7e3..0a082578193 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -946,10 +946,10 @@ void dt_vdevices(struct iseries_flat_dt *dt) if ((vlan_map & (0x8000 >> i)) == 0) continue; - snprintf(buf, 32, "vlan@%08x", reg + i); + snprintf(buf, 32, "l-lan@%08x", reg + i); dt_start_node(dt, buf); - dt_prop_str(dt, "device_type", "vlan"); - dt_prop_str(dt, "compatible", ""); + dt_prop_str(dt, "device_type", "network"); + dt_prop_str(dt, "compatible", "IBM,iSeries-l-lan"); dt_prop_u32(dt, "reg", reg + i); dt_prop_u32(dt, "linux,unit_address", i); @@ -961,6 +961,8 @@ void dt_vdevices(struct iseries_flat_dt *dt) mac_addr[5] = HvLpConfig_getLpIndex_outline(); dt_prop(dt, "local-mac-address", (char *)mac_addr, ETH_ALEN); dt_prop(dt, "mac-address", (char *)mac_addr, ETH_ALEN); + dt_prop_u32(dt, "max-frame-size", 9000); + dt_prop_u32(dt, "address-bits", 48); dt_end_node(dt); } diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c index f0f04be989d..93394d76587 100644 --- a/drivers/net/iseries_veth.c +++ b/drivers/net/iseries_veth.c @@ -69,6 +69,7 @@ #include #include #include +#include #include #include @@ -1035,11 +1036,22 @@ static struct ethtool_ops ops = { .get_link = veth_get_link, }; -static struct net_device * __init veth_probe_one(int vlan, struct device *vdev) +static struct net_device * __init veth_probe_one(int vlan, + struct vio_dev *vio_dev) { struct net_device *dev; struct veth_port *port; + struct device *vdev = &vio_dev->dev; int i, rc; + const unsigned char *mac_addr; + + mac_addr = vio_get_attribute(vio_dev, "local-mac-address", NULL); + if (mac_addr == NULL) + mac_addr = vio_get_attribute(vio_dev, "mac-address", NULL); + if (mac_addr == NULL) { + veth_error("Unable to fetch MAC address from device tree.\n"); + return NULL; + } dev = alloc_etherdev(sizeof (struct veth_port)); if (! dev) { @@ -1064,16 +1076,11 @@ static struct net_device * __init veth_probe_one(int vlan, struct device *vdev) } port->dev = vdev; - dev->dev_addr[0] = 0x02; - dev->dev_addr[1] = 0x01; - dev->dev_addr[2] = 0xff; - dev->dev_addr[3] = vlan; - dev->dev_addr[4] = 0xff; - dev->dev_addr[5] = this_lp; + memcpy(dev->dev_addr, mac_addr, ETH_ALEN); dev->mtu = VETH_MAX_MTU; - memcpy(&port->mac_addr, dev->dev_addr, 6); + memcpy(&port->mac_addr, mac_addr, ETH_ALEN); dev->open = veth_open; dev->hard_start_xmit = veth_start_xmit; @@ -1608,7 +1615,7 @@ static int veth_probe(struct vio_dev *vdev, const struct vio_device_id *id) struct net_device *dev; struct veth_port *port; - dev = veth_probe_one(i, &vdev->dev); + dev = veth_probe_one(i, vdev); if (dev == NULL) { veth_remove(vdev); return 1; @@ -1641,7 +1648,7 @@ static int veth_probe(struct vio_dev *vdev, const struct vio_device_id *id) * support. */ static struct vio_device_id veth_device_table[] __devinitdata = { - { "vlan", "" }, + { "network", "IBM,iSeries-l-lan" }, { "", "" } }; MODULE_DEVICE_TABLE(vio, veth_device_table); -- cgit v1.2.3 From fbabeb60ba783bf7a43858ecefc5066ac1f07162 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Mon, 15 May 2006 13:41:22 +1000 Subject: [PATCH] powerpc: update iSeries viodasd device-tree entries These devices should have device_type block and a unique compatible entry. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/setup.c | 4 ++-- drivers/block/viodasd.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 0a082578193..285f2b2e7d8 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -971,8 +971,8 @@ void dt_vdevices(struct iseries_flat_dt *dt) for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++) { snprintf(buf, 32, "viodasd@%08x", reg + i); dt_start_node(dt, buf); - dt_prop_str(dt, "device_type", "viodasd"); - dt_prop_str(dt, "compatible", ""); + dt_prop_str(dt, "device_type", "block"); + dt_prop_str(dt, "compatible", "IBM,iSeries-viodasd"); dt_prop_u32(dt, "reg", reg + i); dt_prop_u32(dt, "linux,unit_address", i); dt_end_node(dt); diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c index f63e07bd9f9..b0df4f5ab97 100644 --- a/drivers/block/viodasd.c +++ b/drivers/block/viodasd.c @@ -747,7 +747,7 @@ static int viodasd_remove(struct vio_dev *vdev) * support. */ static struct vio_device_id viodasd_device_table[] __devinitdata = { - { "viodasd", "" }, + { "block", "IBM,iSeries-viodasd" }, { "", "" } }; MODULE_DEVICE_TABLE(vio, viodasd_device_table); -- cgit v1.2.3 From dc3c9b8ca2ec15cf56d071b85f3734a07bf5f808 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Mon, 15 May 2006 13:42:29 +1000 Subject: [PATCH] powerpc: update iSeries vdevice Make it look more like the pSeries vdevice tree. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/setup.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 285f2b2e7d8..d3f94b4f28a 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -921,13 +921,14 @@ void dt_vdevices(struct iseries_flat_dt *dt) char buf[32]; dt_start_node(dt, "vdevice"); + dt_prop_str(dt, "device_type", "vdevice"); + dt_prop_str(dt, "compatible", "IBM,iSeries-vdevice"); dt_prop_u32(dt, "#address-cells", 1); dt_prop_u32(dt, "#size-cells", 0); - snprintf(buf, sizeof(buf), "viocons@%08x", reg); + snprintf(buf, sizeof(buf), "vty@%08x", reg); dt_start_node(dt, buf); dt_prop_str(dt, "device_type", "serial"); - dt_prop_str(dt, "compatible", ""); dt_prop_u32(dt, "reg", reg); dt_end_node(dt); reg++; -- cgit v1.2.3 From de0fe3b83f4bb47a0a6b47897bb3800862194016 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Mon, 15 May 2006 13:44:01 +1000 Subject: [PATCH] powerpc: update iSeries viocd and viotape device-tree Make their device_type entries more generic and their compatible entries more specific. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/setup.c | 8 ++++---- drivers/cdrom/viocd.c | 2 +- drivers/char/viotape.c | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index d3f94b4f28a..074d1d94970 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -982,8 +982,8 @@ void dt_vdevices(struct iseries_flat_dt *dt) for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++) { snprintf(buf, 32, "viocd@%08x", reg + i); dt_start_node(dt, buf); - dt_prop_str(dt, "device_type", "viocd"); - dt_prop_str(dt, "compatible", ""); + dt_prop_str(dt, "device_type", "block"); + dt_prop_str(dt, "compatible", "IBM,iSeries-viocd"); dt_prop_u32(dt, "reg", reg + i); dt_prop_u32(dt, "linux,unit_address", i); dt_end_node(dt); @@ -992,8 +992,8 @@ void dt_vdevices(struct iseries_flat_dt *dt) for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++) { snprintf(buf, 32, "viotape@%08x", reg + i); dt_start_node(dt, buf); - dt_prop_str(dt, "device_type", "viotape"); - dt_prop_str(dt, "compatible", ""); + dt_prop_str(dt, "device_type", "byte"); + dt_prop_str(dt, "compatible", "IBM,iSeries-viotape"); dt_prop_u32(dt, "reg", reg + i); dt_prop_u32(dt, "linux,unit_address", i); dt_end_node(dt); diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c index c0f817ba7ad..af6b3bfd169 100644 --- a/drivers/cdrom/viocd.c +++ b/drivers/cdrom/viocd.c @@ -731,7 +731,7 @@ static int viocd_remove(struct vio_dev *vdev) * support. */ static struct vio_device_id viocd_device_table[] __devinitdata = { - { "viocd", "" }, + { "block", "IBM,iSeries-viocd" }, { "", "" } }; MODULE_DEVICE_TABLE(vio, viocd_device_table); diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c index 60aabdb4a04..11c7e9de595 100644 --- a/drivers/char/viotape.c +++ b/drivers/char/viotape.c @@ -989,7 +989,7 @@ static int viotape_remove(struct vio_dev *vdev) * support. */ static struct vio_device_id viotape_device_table[] __devinitdata = { - { "viotape", "" }, + { "byte", "IBM,iSeries-viotape" }, { "", "" } }; MODULE_DEVICE_TABLE(vio, viotape_device_table); -- cgit v1.2.3 From 9dabbfbab312909782b26580d71e3977622fab6e Mon Sep 17 00:00:00 2001 From: "mostrows@watson.ibm.com" Date: Mon, 15 May 2006 08:51:07 -0400 Subject: [PATCH] powerpc: Create /proc/rtas, /proc/ppc64/rtas if RTAS exists. Use the existence of RTAS device tree node to determine if /proc/rtas. /proc/ppc64/rtas are to be created. Using machine type is not reliable (i.e. Maple-like machines may have RTAS). Signed-off-by: Michal Ostrowski Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/proc_ppc64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/kernel/proc_ppc64.c b/arch/powerpc/kernel/proc_ppc64.c index 3c2cf661f6d..2b87f82df13 100644 --- a/arch/powerpc/kernel/proc_ppc64.c +++ b/arch/powerpc/kernel/proc_ppc64.c @@ -52,7 +52,7 @@ static int __init proc_ppc64_create(void) if (!root) return 1; - if (!machine_is(pseries) && !machine_is(cell)) + if (!of_find_node_by_path("/rtas")) return 0; if (!proc_mkdir("rtas", root)) -- cgit v1.2.3 From f9a6ee1afb84fd767508428ec5d1df4fb60a03ad Mon Sep 17 00:00:00 2001 From: Rich Townsend Date: Mon, 19 Dec 2005 23:07:00 -0500 Subject: ACPI: replace spin_lock_irq with mutex for ec poll mode http://bugzilla.kernel.org/show_bug.cgi?id=5764 Signed-off-by: Luming Yu Signed-off-by: Len Brown --- drivers/acpi/ec.c | 51 +++++++++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index eee0864ba30..d2638209c60 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -116,7 +116,7 @@ union acpi_ec { struct acpi_generic_address command_addr; struct acpi_generic_address data_addr; unsigned long global_lock; - spinlock_t lock; + struct semaphore sem; } poll; }; @@ -323,7 +323,6 @@ static int acpi_ec_poll_read(union acpi_ec *ec, u8 address, u32 * data) { acpi_status status = AE_OK; int result = 0; - unsigned long flags = 0; u32 glk = 0; ACPI_FUNCTION_TRACE("acpi_ec_read"); @@ -339,8 +338,11 @@ static int acpi_ec_poll_read(union acpi_ec *ec, u8 address, u32 * data) return_VALUE(-ENODEV); } - spin_lock_irqsave(&ec->poll.lock, flags); - + if (down_interruptible(&ec->poll.sem)) { + result = -ERESTARTSYS; + goto end_nosem; + } + acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, &ec->common.command_addr); result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); @@ -358,8 +360,8 @@ static int acpi_ec_poll_read(union acpi_ec *ec, u8 address, u32 * data) *data, address)); end: - spin_unlock_irqrestore(&ec->poll.lock, flags); - + up(&ec->poll.sem); +end_nosem: if (ec->common.global_lock) acpi_release_global_lock(glk); @@ -370,7 +372,6 @@ static int acpi_ec_poll_write(union acpi_ec *ec, u8 address, u8 data) { int result = 0; acpi_status status = AE_OK; - unsigned long flags = 0; u32 glk = 0; ACPI_FUNCTION_TRACE("acpi_ec_write"); @@ -384,8 +385,11 @@ static int acpi_ec_poll_write(union acpi_ec *ec, u8 address, u8 data) return_VALUE(-ENODEV); } - spin_lock_irqsave(&ec->poll.lock, flags); - + if (down_interruptible(&ec->poll.sem)) { + result = -ERESTARTSYS; + goto end_nosem; + } + acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, &ec->common.command_addr); result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); @@ -406,8 +410,8 @@ static int acpi_ec_poll_write(union acpi_ec *ec, u8 address, u8 data) data, address)); end: - spin_unlock_irqrestore(&ec->poll.lock, flags); - + up(&ec->poll.sem); +end_nosem: if (ec->common.global_lock) acpi_release_global_lock(glk); @@ -568,7 +572,6 @@ static int acpi_ec_poll_query(union acpi_ec *ec, u32 * data) { int result = 0; acpi_status status = AE_OK; - unsigned long flags = 0; u32 glk = 0; ACPI_FUNCTION_TRACE("acpi_ec_query"); @@ -589,8 +592,11 @@ static int acpi_ec_poll_query(union acpi_ec *ec, u32 * data) * Note that successful completion of the query causes the ACPI_EC_SCI * bit to be cleared (and thus clearing the interrupt source). */ - spin_lock_irqsave(&ec->poll.lock, flags); - + if (down_interruptible(&ec->poll.sem)) { + result = -ERESTARTSYS; + goto end_nosem; + } + acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, &ec->common.command_addr); result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); @@ -602,8 +608,8 @@ static int acpi_ec_poll_query(union acpi_ec *ec, u32 * data) result = -ENODATA; end: - spin_unlock_irqrestore(&ec->poll.lock, flags); - + up(&ec->poll.sem); +end_nosem: if (ec->common.global_lock) acpi_release_global_lock(glk); @@ -680,7 +686,6 @@ static void acpi_ec_gpe_poll_query(void *ec_cxt) { union acpi_ec *ec = (union acpi_ec *)ec_cxt; u32 value = 0; - unsigned long flags = 0; static char object_name[5] = { '_', 'Q', '0', '0', '\0' }; const char hex[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' @@ -691,9 +696,11 @@ static void acpi_ec_gpe_poll_query(void *ec_cxt) if (!ec_cxt) goto end; - spin_lock_irqsave(&ec->poll.lock, flags); + if (down_interruptible (&ec->poll.sem)) { + return_VOID; + } acpi_hw_low_level_read(8, &value, &ec->common.command_addr); - spin_unlock_irqrestore(&ec->poll.lock, flags); + up(&ec->poll.sem); /* TBD: Implement asynch events! * NOTE: All we care about are EC-SCI's. Other EC events are @@ -1005,7 +1012,7 @@ static int acpi_ec_poll_add(struct acpi_device *device) ec->common.handle = device->handle; ec->common.uid = -1; - spin_lock_init(&ec->poll.lock); + init_MUTEX(&ec->poll.sem); strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_EC_CLASS); acpi_driver_data(device) = ec; @@ -1300,7 +1307,7 @@ acpi_fake_ecdt_poll_callback(acpi_handle handle, &ec_ecdt->common.gpe_bit); if (ACPI_FAILURE(status)) return status; - spin_lock_init(&ec_ecdt->poll.lock); + init_MUTEX(&ec_ecdt->poll.sem); ec_ecdt->common.global_lock = TRUE; ec_ecdt->common.handle = handle; @@ -1416,7 +1423,7 @@ static int __init acpi_ec_poll_get_real_ecdt(void) ec_ecdt->common.status_addr = ecdt_ptr->ec_control; ec_ecdt->common.data_addr = ecdt_ptr->ec_data; ec_ecdt->common.gpe_bit = ecdt_ptr->gpe_bit; - spin_lock_init(&ec_ecdt->poll.lock); + init_MUTEX(&ec_ecdt->poll.sem); /* use the GL just to be safe */ ec_ecdt->common.global_lock = TRUE; ec_ecdt->common.uid = ecdt_ptr->uid; -- cgit v1.2.3 From 480f6f35a149802a94ad5c1a2673ed6ec8d2c158 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Wed, 17 May 2006 18:00:41 +1000 Subject: [PATCH] powerpc: Make early xmon logic immune to location of early parsing Currently early_xmon() calls directly into debugger() if xmon=early is passed. This ties the invocation of early xmon to the location of parse_early_param(), which might change. Tested on P5 LPAR and F50. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/setup-common.c | 3 ++- arch/powerpc/kernel/setup.h | 1 + arch/powerpc/kernel/setup_32.c | 3 +++ arch/powerpc/kernel/setup_64.c | 3 +++ 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index 88de557fe04..bd328123af7 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c @@ -443,6 +443,7 @@ void __init smp_setup_cpu_maps(void) } #endif /* CONFIG_SMP */ +int __initdata do_early_xmon; #ifdef CONFIG_XMON static int __init early_xmon(char *p) { @@ -456,7 +457,7 @@ static int __init early_xmon(char *p) return 0; } xmon_init(1); - debugger(NULL); + do_early_xmon = 1; return 0; } diff --git a/arch/powerpc/kernel/setup.h b/arch/powerpc/kernel/setup.h index e67066c1933..4c67ad7fae0 100644 --- a/arch/powerpc/kernel/setup.h +++ b/arch/powerpc/kernel/setup.h @@ -4,5 +4,6 @@ void check_for_initrd(void); void do_init_bootmem(void); void setup_panic(void); +extern int do_early_xmon; #endif /* _POWERPC_KERNEL_SETUP_H */ diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index 88832b3ee66..2b6cacb6946 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c @@ -297,6 +297,9 @@ void __init setup_arch(char **cmdline_p) parse_early_param(); + if (do_early_xmon) + debugger(NULL); + /* set up the bootmem stuff with available memory */ do_init_bootmem(); if ( ppc_md.progress ) ppc_md.progress("setup_arch: bootmem", 0x3eab); diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index ab6ea37a77a..a1923d917b3 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -419,6 +419,9 @@ void __init setup_system(void) parse_early_param(); + if (do_early_xmon) + debugger(NULL); + check_smt_enabled(); smp_setup_cpu_maps(); -- cgit v1.2.3 From 846f77b08c8301682ded5ce127c56397327a60d0 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Wed, 17 May 2006 18:00:45 +1000 Subject: [PATCH] powerpc: Parse early parameters earlier Currently we have call parse_early_param() earliyish, but not really very early. In particular, it's not early enough to do things like mem=x or crashkernel=blah, which is annoying. So do it earlier. I've checked all the early param handlers, and none of them look like they should have any trouble with this. I haven't tested the booke_wdt ones though. On 32-bit we were doing the CONFIG_CMDLINE logic twice, so don't. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/prom.c | 5 +++++ arch/powerpc/kernel/setup_32.c | 14 ++------------ arch/powerpc/kernel/setup_64.c | 5 ----- 3 files changed, 7 insertions(+), 17 deletions(-) diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 9a07f97f071..4ca608c9cd7 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -1292,6 +1292,11 @@ void __init early_init_devtree(void *params) lmb_init(); of_scan_flat_dt(early_init_dt_scan_root, NULL); of_scan_flat_dt(early_init_dt_scan_memory, NULL); + + /* Save command line for /proc/cmdline and then parse parameters */ + strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE); + parse_early_param(); + lmb_enforce_memory_limit(memory_limit); lmb_analyze(); diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index 2b6cacb6946..e5a44812441 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c @@ -131,12 +131,6 @@ void __init machine_init(unsigned long dt_ptr, unsigned long phys) /* Do some early initialization based on the flat device tree */ early_init_devtree(__va(dt_ptr)); - /* Check default command line */ -#ifdef CONFIG_CMDLINE - if (cmd_line[0] == 0) - strlcpy(cmd_line, CONFIG_CMDLINE, sizeof(cmd_line)); -#endif /* CONFIG_CMDLINE */ - probe_machine(); #ifdef CONFIG_6xx @@ -235,6 +229,8 @@ arch_initcall(ppc_init); /* Warning, IO base is not yet inited */ void __init setup_arch(char **cmdline_p) { + *cmdline_p = cmd_line; + /* so udelay does something sensible, assume <= 1000 bogomips */ loops_per_jiffy = 500000000 / HZ; @@ -291,12 +287,6 @@ void __init setup_arch(char **cmdline_p) init_mm.end_data = (unsigned long) _edata; init_mm.brk = klimit; - /* Save unparsed command line copy for /proc/cmdline */ - strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE); - *cmdline_p = cmd_line; - - parse_early_param(); - if (do_early_xmon) debugger(NULL); diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index a1923d917b3..6224624c3d3 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -414,11 +414,6 @@ void __init setup_system(void) */ register_early_udbg_console(); - /* Save unparsed command line copy for /proc/cmdline */ - strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE); - - parse_early_param(); - if (do_early_xmon) debugger(NULL); -- cgit v1.2.3 From 2babf5c2ec2f2d5de3e38d20f7df7fd815fd10c9 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Wed, 17 May 2006 18:00:46 +1000 Subject: [PATCH] powerpc: Unify mem= handling We currently do mem= handling in three seperate places. And as benh pointed out I wrote two of them. Now that we parse command line parameters earlier we can clean this mess up. Moving the parsing out of prom_init means the device tree might be allocated above the memory limit. If that happens we'd have to move it. As it happens we already have logic to do that for kdump, so just genericise it. This also means we might have reserved regions above the memory limit, if we do the bootmem allocator will blow up, so we have to modify lmb_enforce_memory_limit() to truncate the reserves as well. Tested on P5 LPAR, iSeries, F50, 44p. Tested moving device tree on P5 and 44p and F50. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/machine_kexec_64.c | 5 ++ arch/powerpc/kernel/prom.c | 89 ++++++++++++++++++---------------- arch/powerpc/kernel/prom_init.c | 55 ++------------------- arch/powerpc/kernel/setup_64.c | 3 -- arch/powerpc/mm/lmb.c | 43 +++++++++++----- arch/powerpc/platforms/iseries/setup.c | 22 --------- include/asm-powerpc/kexec.h | 13 ++++- 7 files changed, 100 insertions(+), 130 deletions(-) diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c index ee166c58664..1ccb188ba40 100644 --- a/arch/powerpc/kernel/machine_kexec_64.c +++ b/arch/powerpc/kernel/machine_kexec_64.c @@ -339,3 +339,8 @@ void __init kexec_setup(void) { export_htab_values(); } + +int overlaps_crashkernel(unsigned long start, unsigned long size) +{ + return (start + size) > crashk_res.start && start <= crashk_res.end; +} diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 4ca608c9cd7..a04f726d3ba 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -50,6 +50,7 @@ #include #include #include +#include #ifdef DEBUG #define DBG(fmt...) printk(KERN_ERR fmt) @@ -836,6 +837,42 @@ static unsigned long __init unflatten_dt_node(unsigned long mem, return mem; } +static int __init early_parse_mem(char *p) +{ + if (!p) + return 1; + + memory_limit = PAGE_ALIGN(memparse(p, &p)); + DBG("memory limit = 0x%lx\n", memory_limit); + + return 0; +} +early_param("mem", early_parse_mem); + +/* + * The device tree may be allocated below our memory limit, or inside the + * crash kernel region for kdump. If so, move it out now. + */ +static void move_device_tree(void) +{ + unsigned long start, size; + void *p; + + DBG("-> move_device_tree\n"); + + start = __pa(initial_boot_params); + size = initial_boot_params->totalsize; + + if ((memory_limit && (start + size) > memory_limit) || + overlaps_crashkernel(start, size)) { + p = __va(lmb_alloc_base(size, PAGE_SIZE, lmb.rmo_size)); + memcpy(p, initial_boot_params, size); + initial_boot_params = (struct boot_param_header *)p; + DBG("Moved device tree to 0x%p\n", p); + } + + DBG("<- move_device_tree\n"); +} /** * unflattens the device-tree passed by the firmware, creating the @@ -1070,6 +1107,7 @@ static int __init early_init_dt_scan_chosen(unsigned long node, iommu_force_on = 1; #endif + /* mem=x on the command line is the preferred mechanism */ lprop = of_get_flat_dt_prop(node, "linux,memory-limit", NULL); if (lprop) memory_limit = *lprop; @@ -1123,17 +1161,6 @@ static int __init early_init_dt_scan_chosen(unsigned long node, DBG("Command line is: %s\n", cmd_line); - if (strstr(cmd_line, "mem=")) { - char *p, *q; - - for (q = cmd_line; (p = strstr(q, "mem=")) != 0; ) { - q = p + 4; - if (p > cmd_line && p[-1] != ' ') - continue; - memory_limit = memparse(q, &q); - } - } - /* break now */ return 1; } @@ -1297,11 +1324,6 @@ void __init early_init_devtree(void *params) strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE); parse_early_param(); - lmb_enforce_memory_limit(memory_limit); - lmb_analyze(); - - DBG("Phys. mem: %lx\n", lmb_phys_mem_size()); - /* Reserve LMB regions used by kernel, initrd, dt, etc... */ lmb_reserve(PHYSICAL_START, __pa(klimit) - PHYSICAL_START); #ifdef CONFIG_CRASH_DUMP @@ -1309,6 +1331,15 @@ void __init early_init_devtree(void *params) #endif early_reserve_mem(); + lmb_enforce_memory_limit(memory_limit); + lmb_analyze(); + + DBG("Phys. mem: %lx\n", lmb_phys_mem_size()); + + /* We may need to relocate the flat tree, do it now. + * FIXME .. and the initrd too? */ + move_device_tree(); + DBG("Scanning CPUs ...\n"); /* Retreive CPU related informations from the flat tree @@ -2058,29 +2089,3 @@ int prom_update_property(struct device_node *np, return 0; } -#ifdef CONFIG_KEXEC -/* We may have allocated the flat device tree inside the crash kernel region - * in prom_init. If so we need to move it out into regular memory. */ -void kdump_move_device_tree(void) -{ - unsigned long start, end; - struct boot_param_header *new; - - start = __pa((unsigned long)initial_boot_params); - end = start + initial_boot_params->totalsize; - - if (end < crashk_res.start || start > crashk_res.end) - return; - - new = (struct boot_param_header*) - __va(lmb_alloc(initial_boot_params->totalsize, PAGE_SIZE)); - - memcpy(new, initial_boot_params, initial_boot_params->totalsize); - - initial_boot_params = new; - - DBG("Flat device tree blob moved to %p\n", initial_boot_params); - - /* XXX should we unreserve the old DT? */ -} -#endif /* CONFIG_KEXEC */ diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 078fb553354..a52377c68fc 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -194,8 +194,6 @@ static int __initdata of_platform; static char __initdata prom_cmd_line[COMMAND_LINE_SIZE]; -static unsigned long __initdata prom_memory_limit; - static unsigned long __initdata alloc_top; static unsigned long __initdata alloc_top_high; static unsigned long __initdata alloc_bottom; @@ -594,16 +592,6 @@ static void __init early_cmdline_parse(void) } #endif - opt = strstr(RELOC(prom_cmd_line), RELOC("mem=")); - if (opt) { - opt += 4; - RELOC(prom_memory_limit) = prom_memparse(opt, (const char **)&opt); -#ifdef CONFIG_PPC64 - /* Align to 16 MB == size of ppc64 large page */ - RELOC(prom_memory_limit) = ALIGN(RELOC(prom_memory_limit), 0x1000000); -#endif - } - #ifdef CONFIG_KEXEC /* * crashkernel=size@addr specifies the location to reserve for @@ -1114,29 +1102,6 @@ static void __init prom_init_mem(void) RELOC(alloc_bottom) = PAGE_ALIGN(RELOC(prom_initrd_end)); } - /* - * If prom_memory_limit is set we reduce the upper limits *except* for - * alloc_top_high. This must be the real top of RAM so we can put - * TCE's up there. - */ - - RELOC(alloc_top_high) = RELOC(ram_top); - - if (RELOC(prom_memory_limit)) { - if (RELOC(prom_memory_limit) <= RELOC(alloc_bottom)) { - prom_printf("Ignoring mem=%x <= alloc_bottom.\n", - RELOC(prom_memory_limit)); - RELOC(prom_memory_limit) = 0; - } else if (RELOC(prom_memory_limit) >= RELOC(ram_top)) { - prom_printf("Ignoring mem=%x >= ram_top.\n", - RELOC(prom_memory_limit)); - RELOC(prom_memory_limit) = 0; - } else { - RELOC(ram_top) = RELOC(prom_memory_limit); - RELOC(rmo_top) = min(RELOC(rmo_top), RELOC(prom_memory_limit)); - } - } - /* * Setup our top alloc point, that is top of RMO or top of * segment 0 when running non-LPAR. @@ -1149,9 +1114,9 @@ static void __init prom_init_mem(void) RELOC(rmo_top) = RELOC(ram_top); RELOC(rmo_top) = min(0x30000000ul, RELOC(rmo_top)); RELOC(alloc_top) = RELOC(rmo_top); + RELOC(alloc_top_high) = RELOC(ram_top); prom_printf("memory layout at init:\n"); - prom_printf(" memory_limit : %x (16 MB aligned)\n", RELOC(prom_memory_limit)); prom_printf(" alloc_bottom : %x\n", RELOC(alloc_bottom)); prom_printf(" alloc_top : %x\n", RELOC(alloc_top)); prom_printf(" alloc_top_hi : %x\n", RELOC(alloc_top_high)); @@ -1348,16 +1313,10 @@ static void __init prom_initialize_tce_table(void) reserve_mem(local_alloc_bottom, local_alloc_top - local_alloc_bottom); - if (RELOC(prom_memory_limit)) { - /* - * We align the start to a 16MB boundary so we can map - * the TCE area using large pages if possible. - * The end should be the top of RAM so no need to align it. - */ - RELOC(prom_tce_alloc_start) = _ALIGN_DOWN(local_alloc_bottom, - 0x1000000); - RELOC(prom_tce_alloc_end) = local_alloc_top; - } + /* These are only really needed if there is a memory limit in + * effect, but we don't know so export them always. */ + RELOC(prom_tce_alloc_start) = local_alloc_bottom; + RELOC(prom_tce_alloc_end) = local_alloc_top; /* Flag the first invalid entry */ prom_debug("ending prom_initialize_tce_table\n"); @@ -2265,10 +2224,6 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, /* * Fill in some infos for use by the kernel later on */ - if (RELOC(prom_memory_limit)) - prom_setprop(_prom->chosen, "/chosen", "linux,memory-limit", - &RELOC(prom_memory_limit), - sizeof(prom_memory_limit)); #ifdef CONFIG_PPC64 if (RELOC(ppc64_iommu_off)) prom_setprop(_prom->chosen, "/chosen", "linux,iommu-off", diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 6224624c3d3..59773d9044b 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -347,9 +347,6 @@ void __init setup_system(void) { DBG(" -> setup_system()\n"); -#ifdef CONFIG_KEXEC - kdump_move_device_tree(); -#endif /* * Unflatten the device-tree passed by prom_init or kexec */ diff --git a/arch/powerpc/mm/lmb.c b/arch/powerpc/mm/lmb.c index 417d5851855..8b6f522655a 100644 --- a/arch/powerpc/mm/lmb.c +++ b/arch/powerpc/mm/lmb.c @@ -89,20 +89,25 @@ static long __init lmb_regions_adjacent(struct lmb_region *rgn, return lmb_addrs_adjacent(base1, size1, base2, size2); } -/* Assumption: base addr of region 1 < base addr of region 2 */ -static void __init lmb_coalesce_regions(struct lmb_region *rgn, - unsigned long r1, unsigned long r2) +static void __init lmb_remove_region(struct lmb_region *rgn, unsigned long r) { unsigned long i; - rgn->region[r1].size += rgn->region[r2].size; - for (i=r2; i < rgn->cnt-1; i++) { - rgn->region[i].base = rgn->region[i+1].base; - rgn->region[i].size = rgn->region[i+1].size; + for (i = r; i < rgn->cnt - 1; i++) { + rgn->region[i].base = rgn->region[i + 1].base; + rgn->region[i].size = rgn->region[i + 1].size; } rgn->cnt--; } +/* Assumption: base addr of region 1 < base addr of region 2 */ +static void __init lmb_coalesce_regions(struct lmb_region *rgn, + unsigned long r1, unsigned long r2) +{ + rgn->region[r1].size += rgn->region[r2].size; + lmb_remove_region(rgn, r2); +} + /* This routine called with relocation disabled. */ void __init lmb_init(void) { @@ -294,17 +299,16 @@ unsigned long __init lmb_end_of_DRAM(void) return (lmb.memory.region[idx].base + lmb.memory.region[idx].size); } -/* - * Truncate the lmb list to memory_limit if it's set - * You must call lmb_analyze() after this. - */ +/* You must call lmb_analyze() after this. */ void __init lmb_enforce_memory_limit(unsigned long memory_limit) { unsigned long i, limit; + struct lmb_property *p; if (! memory_limit) return; + /* Truncate the lmb regions to satisfy the memory limit. */ limit = memory_limit; for (i = 0; i < lmb.memory.cnt; i++) { if (limit > lmb.memory.region[i].size) { @@ -316,4 +320,21 @@ void __init lmb_enforce_memory_limit(unsigned long memory_limit) lmb.memory.cnt = i + 1; break; } + + lmb.rmo_size = lmb.memory.region[0].size; + + /* And truncate any reserves above the limit also. */ + for (i = 0; i < lmb.reserved.cnt; i++) { + p = &lmb.reserved.region[i]; + + if (p->base > memory_limit) + p->size = 0; + else if ((p->base + p->size) > memory_limit) + p->size = memory_limit - p->base; + + if (p->size == 0) { + lmb_remove_region(&lmb.reserved, i); + i--; + } + } } diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 074d1d94970..fd6d0ebe8dd 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -90,8 +90,6 @@ extern unsigned long embedded_sysmap_end; extern unsigned long iSeries_recal_tb; extern unsigned long iSeries_recal_titan; -static unsigned long cmd_mem_limit; - struct MemoryBlock { unsigned long absStart; unsigned long absEnd; @@ -1026,8 +1024,6 @@ void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size) /* /chosen */ dt_start_node(dt, "chosen"); dt_prop_str(dt, "bootargs", cmd_line); - if (cmd_mem_limit) - dt_prop_u64(dt, "linux,memory-limit", cmd_mem_limit); dt_end_node(dt); dt_cpus(dt); @@ -1053,29 +1049,11 @@ void * __init iSeries_early_setup(void) iSeries_get_cmdline(); - /* Save unparsed command line copy for /proc/cmdline */ - strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE); - - /* Parse early parameters, in particular mem=x */ - parse_early_param(); - build_flat_dt(&iseries_dt, phys_mem_size); return (void *) __pa(&iseries_dt); } -/* - * On iSeries we just parse the mem=X option from the command line. - * On pSeries it's a bit more complicated, see prom_init_mem() - */ -static int __init early_parsemem(char *p) -{ - if (p) - cmd_mem_limit = ALIGN(memparse(p, &p), PAGE_SIZE); - return 0; -} -early_param("mem", early_parsemem); - static void hvputc(char c) { if (c == '\n') diff --git a/include/asm-powerpc/kexec.h b/include/asm-powerpc/kexec.h index 6a2af2f6853..0a1afced173 100644 --- a/include/asm-powerpc/kexec.h +++ b/include/asm-powerpc/kexec.h @@ -31,9 +31,10 @@ #define KEXEC_ARCH KEXEC_ARCH_PPC #endif +#ifndef __ASSEMBLY__ + #ifdef CONFIG_KEXEC -#ifndef __ASSEMBLY__ #ifdef __powerpc64__ /* * This function is responsible for capturing register states if coming @@ -123,8 +124,16 @@ extern int default_machine_kexec_prepare(struct kimage *image); extern void default_machine_crash_shutdown(struct pt_regs *regs); extern void machine_kexec_simple(struct kimage *image); +extern int overlaps_crashkernel(unsigned long start, unsigned long size); + +#else /* !CONFIG_KEXEC */ + +static inline int overlaps_crashkernel(unsigned long start, unsigned long size) +{ + return 0; +} -#endif /* ! __ASSEMBLY__ */ #endif /* CONFIG_KEXEC */ +#endif /* ! __ASSEMBLY__ */ #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_KEXEC_H */ -- cgit v1.2.3 From 473104134b35ce1c3ca77b738c561d6c215adc1b Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Wed, 17 May 2006 18:00:49 +1000 Subject: [PATCH] powerpc: Kdump header cleanup We need to know the base address of the kdump kernel even when we're not a kdump kernel, so add a #define for it. Move the logic that sets the kdump kernelbase into kdump.h instead of page.h. Rename kdump_setup() to setup_kdump_trampoline() to make it clearer what it's doing, and add an empty definition for the !CRASH_DUMP case to avoid a Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/crash_dump.c | 11 ++++++++--- arch/powerpc/kernel/prom.c | 4 +--- arch/powerpc/kernel/setup_64.c | 4 +--- include/asm-powerpc/kdump.h | 29 +++++++++++++++++++++++++++-- include/asm-powerpc/page.h | 8 +------- 5 files changed, 38 insertions(+), 18 deletions(-) diff --git a/arch/powerpc/kernel/crash_dump.c b/arch/powerpc/kernel/crash_dump.c index 764d0732971..371973be8d7 100644 --- a/arch/powerpc/kernel/crash_dump.c +++ b/arch/powerpc/kernel/crash_dump.c @@ -25,6 +25,11 @@ #define DBG(fmt...) #endif +void reserve_kdump_trampoline(void) +{ + lmb_reserve(0, KDUMP_RESERVE_LIMIT); +} + static void __init create_trampoline(unsigned long addr) { /* The maximum range of a single instruction branch, is the current @@ -39,11 +44,11 @@ static void __init create_trampoline(unsigned long addr) create_branch(addr + 4, addr + PHYSICAL_START, 0); } -void __init kdump_setup(void) +void __init setup_kdump_trampoline(void) { unsigned long i; - DBG(" -> kdump_setup()\n"); + DBG(" -> setup_kdump_trampoline()\n"); for (i = KDUMP_TRAMPOLINE_START; i < KDUMP_TRAMPOLINE_END; i += 8) { create_trampoline(i); @@ -52,7 +57,7 @@ void __init kdump_setup(void) create_trampoline(__pa(system_reset_fwnmi) - PHYSICAL_START); create_trampoline(__pa(machine_check_fwnmi) - PHYSICAL_START); - DBG(" <- kdump_setup()\n"); + DBG(" <- setup_kdump_trampoline()\n"); } #ifdef CONFIG_PROC_VMCORE diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index a04f726d3ba..2498afeef29 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -1326,9 +1326,7 @@ void __init early_init_devtree(void *params) /* Reserve LMB regions used by kernel, initrd, dt, etc... */ lmb_reserve(PHYSICAL_START, __pa(klimit) - PHYSICAL_START); -#ifdef CONFIG_CRASH_DUMP - lmb_reserve(0, KDUMP_RESERVE_LIMIT); -#endif + reserve_kdump_trampoline(); early_reserve_mem(); lmb_enforce_memory_limit(memory_limit); diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 59773d9044b..78f3a5fd43f 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -193,9 +193,7 @@ void __init early_setup(unsigned long dt_ptr) /* Probe the machine type */ probe_machine(); -#ifdef CONFIG_CRASH_DUMP - kdump_setup(); -#endif + setup_kdump_trampoline(); DBG("Found, Initializing memory management...\n"); diff --git a/include/asm-powerpc/kdump.h b/include/asm-powerpc/kdump.h index a87aed00d61..5a5c3b5ab1e 100644 --- a/include/asm-powerpc/kdump.h +++ b/include/asm-powerpc/kdump.h @@ -1,13 +1,38 @@ #ifndef _PPC64_KDUMP_H #define _PPC64_KDUMP_H +/* Kdump kernel runs at 32 MB, change at your peril. */ +#define KDUMP_KERNELBASE 0x2000000 + /* How many bytes to reserve at zero for kdump. The reserve limit should - * be greater or equal to the trampoline's end address. */ + * be greater or equal to the trampoline's end address. + * Reserve to the end of the FWNMI area, see head_64.S */ #define KDUMP_RESERVE_LIMIT 0x8000 +#ifdef CONFIG_CRASH_DUMP + +#define PHYSICAL_START KDUMP_KERNELBASE #define KDUMP_TRAMPOLINE_START 0x0100 #define KDUMP_TRAMPOLINE_END 0x3000 -extern void kdump_setup(void); +#else /* !CONFIG_CRASH_DUMP */ + +#define PHYSICAL_START 0x0 + +#endif /* CONFIG_CRASH_DUMP */ + +#ifndef __ASSEMBLY__ +#ifdef CONFIG_CRASH_DUMP + +extern void reserve_kdump_trampoline(void); +extern void setup_kdump_trampoline(void); + +#else /* !CONFIG_CRASH_DUMP */ + +static inline void reserve_kdump_trampoline(void) { ; } +static inline void setup_kdump_trampoline(void) { ; } + +#endif /* CONFIG_CRASH_DUMP */ +#endif /* __ASSEMBLY__ */ #endif /* __PPC64_KDUMP_H */ diff --git a/include/asm-powerpc/page.h b/include/asm-powerpc/page.h index 2fbecebe1c9..ae610b62048 100644 --- a/include/asm-powerpc/page.h +++ b/include/asm-powerpc/page.h @@ -13,6 +13,7 @@ #ifdef __KERNEL__ #include #include +#include /* * On PPC32 page size is 4K. For PPC64 we support either 4K or 64K software @@ -52,13 +53,6 @@ * If you want to test if something's a kernel address, use is_kernel_addr(). */ -#ifdef CONFIG_CRASH_DUMP -/* Kdump kernel runs at 32 MB, change at your peril. */ -#define PHYSICAL_START 0x2000000 -#else -#define PHYSICAL_START 0x0 -#endif - #define PAGE_OFFSET ASM_CONST(CONFIG_KERNEL_START) #define KERNELBASE (PAGE_OFFSET + PHYSICAL_START) -- cgit v1.2.3 From 35dd54326e857f1648c7cc1028e8d5e1dbe04992 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 18 May 2006 11:16:11 +1000 Subject: [PATCH] powerpc: Move crashkernel= handling into the kernel. This was missing a quilt ref. Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/machine_kexec_64.c | 94 ++++++++++++++++++++++++++++++++++ arch/powerpc/kernel/prom.c | 1 + arch/powerpc/kernel/prom_init.c | 54 ------------------- include/asm-powerpc/kexec.h | 3 ++ 4 files changed, 98 insertions(+), 54 deletions(-) diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c index 1ccb188ba40..a8fa04ef27c 100644 --- a/arch/powerpc/kernel/machine_kexec_64.c +++ b/arch/powerpc/kernel/machine_kexec_64.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include /* _end */ #include @@ -335,9 +336,102 @@ static void __init export_htab_values(void) of_node_put(node); } +static struct property crashk_base_prop = { + .name = "linux,crashkernel-base", + .length = sizeof(unsigned long), + .value = (unsigned char *)&crashk_res.start, +}; + +static unsigned long crashk_size; + +static struct property crashk_size_prop = { + .name = "linux,crashkernel-size", + .length = sizeof(unsigned long), + .value = (unsigned char *)&crashk_size, +}; + +static void __init export_crashk_values(void) +{ + struct device_node *node; + struct property *prop; + + node = of_find_node_by_path("/chosen"); + if (!node) + return; + + /* There might be existing crash kernel properties, but we can't + * be sure what's in them, so remove them. */ + prop = of_find_property(node, "linux,crashkernel-base", NULL); + if (prop) + prom_remove_property(node, prop); + + prop = of_find_property(node, "linux,crashkernel-size", NULL); + if (prop) + prom_remove_property(node, prop); + + if (crashk_res.start != 0) { + prom_add_property(node, &crashk_base_prop); + crashk_size = crashk_res.end - crashk_res.start + 1; + prom_add_property(node, &crashk_size_prop); + } + + of_node_put(node); +} + void __init kexec_setup(void) { export_htab_values(); + export_crashk_values(); +} + +static int __init early_parse_crashk(char *p) +{ + unsigned long size; + + if (!p) + return 1; + + size = memparse(p, &p); + + if (*p == '@') + crashk_res.start = memparse(p + 1, &p); + else + crashk_res.start = KDUMP_KERNELBASE; + + crashk_res.end = crashk_res.start + size - 1; + + return 0; +} +early_param("crashkernel", early_parse_crashk); + +void __init reserve_crashkernel(void) +{ + unsigned long size; + + if (crashk_res.start == 0) + return; + + /* We might have got these values via the command line or the + * device tree, either way sanitise them now. */ + + size = crashk_res.end - crashk_res.start + 1; + + if (crashk_res.start != KDUMP_KERNELBASE) + printk("Crash kernel location must be 0x%x\n", + KDUMP_KERNELBASE); + + crashk_res.start = KDUMP_KERNELBASE; + size = PAGE_ALIGN(size); + crashk_res.end = crashk_res.start + size - 1; + + /* Crash kernel trumps memory limit */ + if (memory_limit && memory_limit <= crashk_res.end) { + memory_limit = crashk_res.end + 1; + printk("Adjusted memory limit for crashkernel, now 0x%lx\n", + memory_limit); + } + + lmb_reserve(crashk_res.start, size); } int overlaps_crashkernel(unsigned long start, unsigned long size) diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 2498afeef29..8d0415b080b 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -1327,6 +1327,7 @@ void __init early_init_devtree(void *params) /* Reserve LMB regions used by kernel, initrd, dt, etc... */ lmb_reserve(PHYSICAL_START, __pa(klimit) - PHYSICAL_START); reserve_kdump_trampoline(); + reserve_crashkernel(); early_reserve_mem(); lmb_enforce_memory_limit(memory_limit); diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index a52377c68fc..2442361772e 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -200,11 +200,6 @@ static unsigned long __initdata alloc_bottom; static unsigned long __initdata rmo_top; static unsigned long __initdata ram_top; -#ifdef CONFIG_KEXEC -static unsigned long __initdata prom_crashk_base; -static unsigned long __initdata prom_crashk_size; -#endif - static struct mem_map_entry __initdata mem_reserve_map[MEM_RESERVE_MAP_SIZE]; static int __initdata mem_reserve_cnt; @@ -591,35 +586,6 @@ static void __init early_cmdline_parse(void) RELOC(iommu_force_on) = 1; } #endif - -#ifdef CONFIG_KEXEC - /* - * crashkernel=size@addr specifies the location to reserve for - * crash kernel. - */ - opt = strstr(RELOC(prom_cmd_line), RELOC("crashkernel=")); - if (opt) { - opt += 12; - RELOC(prom_crashk_size) = - prom_memparse(opt, (const char **)&opt); - - if (ALIGN(RELOC(prom_crashk_size), 0x1000000) != - RELOC(prom_crashk_size)) { - prom_printf("Warning: crashkernel size is not " - "aligned to 16MB\n"); - } - - /* - * At present, the crash kernel always run at 32MB. - * Just ignore whatever user passed. - */ - RELOC(prom_crashk_base) = 0x2000000; - if (*opt == '@') { - prom_printf("Warning: PPC64 kdump kernel always runs " - "at 32 MB\n"); - } - } -#endif } #ifdef CONFIG_PPC_PSERIES @@ -1122,12 +1088,6 @@ static void __init prom_init_mem(void) prom_printf(" alloc_top_hi : %x\n", RELOC(alloc_top_high)); prom_printf(" rmo_top : %x\n", RELOC(rmo_top)); prom_printf(" ram_top : %x\n", RELOC(ram_top)); -#ifdef CONFIG_KEXEC - if (RELOC(prom_crashk_base)) { - prom_printf(" crashk_base : %x\n", RELOC(prom_crashk_base)); - prom_printf(" crashk_size : %x\n", RELOC(prom_crashk_size)); - } -#endif } @@ -2187,10 +2147,6 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, */ prom_init_mem(); -#ifdef CONFIG_KEXEC - if (RELOC(prom_crashk_base)) - reserve_mem(RELOC(prom_crashk_base), RELOC(prom_crashk_size)); -#endif /* * Determine which cpu is actually running right _now_ */ @@ -2243,16 +2199,6 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, } #endif -#ifdef CONFIG_KEXEC - if (RELOC(prom_crashk_base)) { - prom_setprop(_prom->chosen, "/chosen", "linux,crashkernel-base", - PTRRELOC(&prom_crashk_base), - sizeof(RELOC(prom_crashk_base))); - prom_setprop(_prom->chosen, "/chosen", "linux,crashkernel-size", - PTRRELOC(&prom_crashk_size), - sizeof(RELOC(prom_crashk_size))); - } -#endif /* * Fixup any known bugs in the device-tree */ diff --git a/include/asm-powerpc/kexec.h b/include/asm-powerpc/kexec.h index 0a1afced173..efe8872ec58 100644 --- a/include/asm-powerpc/kexec.h +++ b/include/asm-powerpc/kexec.h @@ -125,6 +125,7 @@ extern void default_machine_crash_shutdown(struct pt_regs *regs); extern void machine_kexec_simple(struct kimage *image); extern int overlaps_crashkernel(unsigned long start, unsigned long size); +extern void reserve_crashkernel(void); #else /* !CONFIG_KEXEC */ @@ -133,6 +134,8 @@ static inline int overlaps_crashkernel(unsigned long start, unsigned long size) return 0; } +static inline void reserve_crashkernel(void) { ; } + #endif /* CONFIG_KEXEC */ #endif /* ! __ASSEMBLY__ */ #endif /* __KERNEL__ */ -- cgit v1.2.3 From 8ae5b2801a0beb10a55a7ebd5140482e2f84c3fa Mon Sep 17 00:00:00 2001 From: "jimix@watson.ibm.com" Date: Wed, 17 May 2006 12:00:35 -0400 Subject: [PATCH] powerpc: udbg_printf() formatting attribute This patch allows the compiler to catch any printf-like mismatches for udbg_printf(). After some brute force building I've only found issues with my own code and lparcfg.c It could break some developers, but IMHO that would be goodness. Signed-off-by: Jimi Xenidis Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/lparcfg.c | 4 ++-- include/asm-powerpc/udbg.h | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c index 2cbde865d4f..c02deaab26c 100644 --- a/arch/powerpc/kernel/lparcfg.c +++ b/arch/powerpc/kernel/lparcfg.c @@ -521,10 +521,10 @@ static ssize_t lparcfg_write(struct file *file, const char __user * buf, current_weight = (resource >> 5 * 8) & 0xFF; - pr_debug("%s: current_entitled = %lu, current_weight = %lu\n", + pr_debug("%s: current_entitled = %lu, current_weight = %u\n", __FUNCTION__, current_entitled, current_weight); - pr_debug("%s: new_entitled = %lu, new_weight = %lu\n", + pr_debug("%s: new_entitled = %lu, new_weight = %u\n", __FUNCTION__, *new_entitled_ptr, *new_weight_ptr); retval = plpar_hcall_norets(H_SET_PPP, *new_entitled_ptr, diff --git a/include/asm-powerpc/udbg.h b/include/asm-powerpc/udbg.h index 5c4236c342b..19a1517ac43 100644 --- a/include/asm-powerpc/udbg.h +++ b/include/asm-powerpc/udbg.h @@ -23,7 +23,8 @@ extern int udbg_write(const char *s, int n); extern int udbg_read(char *buf, int buflen); extern void register_early_udbg_console(void); -extern void udbg_printf(const char *fmt, ...); +extern void udbg_printf(const char *fmt, ...) + __attribute__ ((format (printf, 1, 2))); extern void udbg_progress(char *s, unsigned short hex); extern void udbg_init_uart(void __iomem *comport, unsigned int speed, -- cgit v1.2.3 From d4ad66faecc4dd9f3db14e0b013741a6f867b089 Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Thu, 18 May 2006 18:05:15 +1000 Subject: [PATCH] powerpc: Add of_parse_dma_window() Add a function for generic parsing of dma-window properties (ie, ibm,dma-window and ibm,my-dma-window) of pci and virtual device nodes. This function will also be used by cell. Signed-off-by: Jeremy Kerr Acked-by: Olof Johansson Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/prom_parse.c | 22 ++++++++++++++++++++++ include/asm-powerpc/prom.h | 6 ++++++ 2 files changed, 28 insertions(+) diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c index 3934c227549..23bb060330e 100644 --- a/arch/powerpc/kernel/prom_parse.c +++ b/arch/powerpc/kernel/prom_parse.c @@ -548,3 +548,25 @@ int of_pci_address_to_resource(struct device_node *dev, int bar, return __of_address_to_resource(dev, addrp, size, flags, r); } EXPORT_SYMBOL_GPL(of_pci_address_to_resource); + +void of_parse_dma_window(struct device_node *dn, unsigned char *dma_window_prop, + unsigned long *busno, unsigned long *phys, unsigned long *size) +{ + u32 *dma_window, cells; + unsigned char *prop; + + dma_window = (u32 *)dma_window_prop; + + /* busno is always one cell */ + *busno = *(dma_window++); + + prop = get_property(dn, "ibm,#dma-address-cells", NULL); + cells = prop ? *(u32 *)prop : prom_n_addr_cells(dn); + *phys = of_read_addr(dma_window, cells); + + dma_window += cells; + + prop = get_property(dn, "ibm,#dma-size-cells", NULL); + cells = prop ? *(u32 *)prop : prom_n_size_cells(dn); + *size = of_read_addr(dma_window, cells); +} diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h index 97ef1cd71a4..c79d58ab744 100644 --- a/include/asm-powerpc/prom.h +++ b/include/asm-powerpc/prom.h @@ -230,6 +230,12 @@ extern int of_address_to_resource(struct device_node *dev, int index, extern int of_pci_address_to_resource(struct device_node *dev, int bar, struct resource *r); +/* Parse the ibm,dma-window property of an OF node into the busno, phys and + * size parameters. + */ +void of_parse_dma_window(struct device_node *dn, unsigned char *dma_window_prop, + unsigned long *busno, unsigned long *phys, unsigned long *size); + extern void kdump_move_device_tree(void); #endif /* __KERNEL__ */ -- cgit v1.2.3 From 4c76e0bcdeac27b45d55955f073a97ff8452a42f Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Thu, 18 May 2006 18:06:37 +1000 Subject: [PATCH] powerpc: pseries: Use generic dma-window parsing function Change the pseries iommu init code to use the new of_parse_dma_window() to parse the ibm,dma-window and ibm,my-dma-window properties of pci and virtual device nodes. Also, clean up vio_build_iommu_table() a little. Tested on pseries, with both vio and pci devices. Signed-off-by: Jeremy Kerr Acked-by: Olof Johansson Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/vio.c | 36 +++++++++++++--------------------- arch/powerpc/platforms/pseries/iommu.c | 29 ++++++++++----------------- 2 files changed, 24 insertions(+), 41 deletions(-) diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index ac5c7bf907f..2cda65b8171 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c @@ -77,36 +77,28 @@ static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev) } else #endif { - unsigned int *dma_window; - struct iommu_table *newTceTable; - unsigned long offset; - int dma_window_property_size; - - dma_window = (unsigned int *)get_property( - dev->dev.platform_data, "ibm,my-dma-window", - &dma_window_property_size); + unsigned char *dma_window; + struct iommu_table *tbl; + unsigned long offset, size; + + dma_window = get_property(dev->dev.platform_data, + "ibm,my-dma-window", NULL); if (!dma_window) return NULL; - newTceTable = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); + tbl = kmalloc(sizeof(*tbl), GFP_KERNEL); - /* - * There should be some code to extract the phys-encoded - * offset using prom_n_addr_cells(). However, according to - * a comment on earlier versions, it's always zero, so we - * don't bother - */ - offset = dma_window[1] >> PAGE_SHIFT; + of_parse_dma_window(dev->dev.platform_data, dma_window, + &tbl->it_index, &offset, &size); /* TCE table size - measured in tce entries */ - newTceTable->it_size = dma_window[4] >> PAGE_SHIFT; + tbl->it_size = size >> PAGE_SHIFT; /* offset for VIO should always be 0 */ - newTceTable->it_offset = offset; - newTceTable->it_busno = 0; - newTceTable->it_index = (unsigned long)dma_window[0]; - newTceTable->it_type = TCE_VB; + tbl->it_offset = offset >> PAGE_SHIFT; + tbl->it_busno = 0; + tbl->it_type = TCE_VB; - return iommu_init_table(newTceTable); + return iommu_init_table(tbl); } } diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index ed102f39068..44a507e6fb3 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -281,30 +281,22 @@ static void iommu_table_setparms(struct pci_controller *phb, * iommu_table_setparms_lpar * * Function: On pSeries LPAR systems, return TCE table info, given a pci bus. - * - * ToDo: properly interpret the ibm,dma-window property. The definition is: - * logical-bus-number (1 word) - * phys-address (#address-cells words) - * size (#cell-size words) - * - * Currently we hard code these sizes (more or less). */ static void iommu_table_setparms_lpar(struct pci_controller *phb, struct device_node *dn, struct iommu_table *tbl, - unsigned int *dma_window) + unsigned char *dma_window) { + unsigned long offset, size; + tbl->it_busno = PCI_DN(dn)->bussubno; + of_parse_dma_window(dn, dma_window, &tbl->it_index, &offset, &size); - /* TODO: Parse field size properties properly. */ - tbl->it_size = (((unsigned long)dma_window[4] << 32) | - (unsigned long)dma_window[5]) >> PAGE_SHIFT; - tbl->it_offset = (((unsigned long)dma_window[2] << 32) | - (unsigned long)dma_window[3]) >> PAGE_SHIFT; tbl->it_base = 0; - tbl->it_index = dma_window[0]; tbl->it_blocksize = 16; tbl->it_type = TCE_PCI; + tbl->it_offset = offset >> PAGE_SHIFT; + tbl->it_size = size >> PAGE_SHIFT; } static void iommu_bus_setup_pSeries(struct pci_bus *bus) @@ -396,7 +388,7 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus) struct iommu_table *tbl; struct device_node *dn, *pdn; struct pci_dn *ppci; - unsigned int *dma_window = NULL; + unsigned char *dma_window = NULL; DBG("iommu_bus_setup_pSeriesLP, bus %p, bus->self %p\n", bus, bus->self); @@ -404,7 +396,7 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus) /* Find nearest ibm,dma-window, walking up the device tree */ for (pdn = dn; pdn != NULL; pdn = pdn->parent) { - dma_window = (unsigned int *)get_property(pdn, "ibm,dma-window", NULL); + dma_window = get_property(pdn, "ibm,dma-window", NULL); if (dma_window != NULL) break; } @@ -498,7 +490,7 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev) { struct device_node *pdn, *dn; struct iommu_table *tbl; - int *dma_window = NULL; + unsigned char *dma_window = NULL; struct pci_dn *pci; DBG("iommu_dev_setup_pSeriesLP, dev %p (%s)\n", dev, pci_name(dev)); @@ -513,8 +505,7 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev) for (pdn = dn; pdn && PCI_DN(pdn) && !PCI_DN(pdn)->iommu_table; pdn = pdn->parent) { - dma_window = (unsigned int *) - get_property(pdn, "ibm,dma-window", NULL); + dma_window = get_property(pdn, "ibm,dma-window", NULL); if (dma_window) break; } -- cgit v1.2.3 From 1dc461f0b03fab309eb9214df1c9b586aeaf3b22 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Thu, 18 May 2006 17:21:26 +1000 Subject: [PATCH] powerpc: the iSeries vio lan driver changed device type So the IOMMU table building code needs to match. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/vio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index 2cda65b8171..fe92727aca3 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c @@ -71,7 +71,7 @@ static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev) { #ifdef CONFIG_PPC_ISERIES if (firmware_has_feature(FW_FEATURE_ISERIES)) { - if (strcmp(dev->type, "vlan") == 0) + if (strcmp(dev->type, "network") == 0) return &veth_iommu_table; return &vio_iommu_table; } else -- cgit v1.2.3 From 4d1f3f25d9c303d1ce63b42cc94c54ac0ab2e950 Mon Sep 17 00:00:00 2001 From: Jimi Xenidis Date: Thu, 18 May 2006 17:03:05 -0500 Subject: [PATCH] powerpc: Auto reserve of device tree blob A devtree compiler (dtc) generated devtree blob is "relocatable" and so does not contain a reserved_map entry for the blob itself. This means that if passed to Linux, Linux will not get lmb_reserve() the blob and it could be over. The following patch will explicitly reserve the "blob" as it was given to us and stops prom_init.c from creating a reserved mapping for the blob. NOTE: that the dtc/kexec should not generate the blob reservation entry. Although if they do, LMB reserver handles overlaps. Signed-off-by: Acked-by: Michael Neuling Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/prom.c | 5 +++++ arch/powerpc/kernel/prom_init.c | 9 ++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 8d0415b080b..969f4abcc0b 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -1267,6 +1267,11 @@ static void __init early_reserve_mem(void) reserve_map = (u64 *)(((unsigned long)initial_boot_params) + initial_boot_params->off_mem_rsvmap); + + /* before we do anything, lets reserve the dt blob */ + lmb_reserve(__pa((unsigned long)initial_boot_params), + initial_boot_params->totalsize); + #ifdef CONFIG_PPC32 /* * Handle the case where we might be booting from an old kexec diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 2442361772e..98e201c38d2 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -1950,11 +1950,7 @@ static void __init flatten_device_tree(void) /* Version 16 is not backward compatible */ hdr->last_comp_version = 0x10; - /* Reserve the whole thing and copy the reserve map in, we - * also bump mem_reserve_cnt to cause further reservations to - * fail since it's too late. - */ - reserve_mem(RELOC(dt_header_start), hdr->totalsize); + /* Copy the reserve map in */ memcpy(rsvmap, RELOC(mem_reserve_map), sizeof(mem_reserve_map)); #ifdef DEBUG_PROM @@ -1967,6 +1963,9 @@ static void __init flatten_device_tree(void) RELOC(mem_reserve_map)[i].size); } #endif + /* Bump mem_reserve_cnt to cause further reservations to fail + * since it's too late. + */ RELOC(mem_reserve_cnt) = MEM_RESERVE_MAP_SIZE; prom_printf("Device tree strings 0x%x -> 0x%x\n", -- cgit v1.2.3 From 3655d1d323386e001c786af10f0a3f39f438f03b Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Fri, 19 May 2006 11:43:04 +0800 Subject: [PATCH] libata: Fix the HSM error_mask mapping (was: Re: libata-tj and SMART) Fix the HSM error_mask mapping. Changes: - Better mapping in ac_err_mask() - In HSM_ST_FIRST ans HSM_ST state, check ATA_ERR|ATA_DF and map it to AC_ERR_DEV instead of AC_ERR_HSM. - In HSM_ST_FIRST and HSM_ST state, map DRQ=1 ERR=1 to AC_ERR_HSM. - For PIO data in and DRQ=1 ERR=1, add check after the junk data block is read. Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 31 ++++++++++++++++++++++++------- include/linux/libata.h | 2 +- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 00881226f8d..aa38ed3e59a 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -4009,9 +4009,15 @@ fsm_start: poll_next = (qc->tf.flags & ATA_TFLAG_POLLING); /* check device status */ - if (unlikely((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ)) { - /* Wrong status. Let EH handle this */ - qc->err_mask |= AC_ERR_HSM; + if (unlikely((status & ATA_DRQ) == 0)) { + /* handle BSY=0, DRQ=0 as error */ + if (likely(status & (ATA_ERR | ATA_DF))) + /* device stops HSM for abort/error */ + qc->err_mask |= AC_ERR_DEV; + else + /* HSM violation. Let EH handle this */ + qc->err_mask |= AC_ERR_HSM; + ap->hsm_task_state = HSM_ST_ERR; goto fsm_start; } @@ -4025,7 +4031,7 @@ fsm_start: if (unlikely(status & (ATA_ERR | ATA_DF))) { printk(KERN_WARNING "ata%d: DRQ=1 with device error, dev_stat 0x%X\n", ap->id, status); - qc->err_mask |= AC_ERR_DEV; + qc->err_mask |= AC_ERR_HSM; ap->hsm_task_state = HSM_ST_ERR; goto fsm_start; } @@ -4067,7 +4073,9 @@ fsm_start: if (qc->tf.protocol == ATA_PROT_ATAPI) { /* ATAPI PIO protocol */ if ((status & ATA_DRQ) == 0) { - /* no more data to transfer */ + /* No more data to transfer or device error. + * Device error will be tagged in HSM_ST_LAST. + */ ap->hsm_task_state = HSM_ST_LAST; goto fsm_start; } @@ -4081,7 +4089,7 @@ fsm_start: if (unlikely(status & (ATA_ERR | ATA_DF))) { printk(KERN_WARNING "ata%d: DRQ=1 with device error, dev_stat 0x%X\n", ap->id, status); - qc->err_mask |= AC_ERR_DEV; + qc->err_mask |= AC_ERR_HSM; ap->hsm_task_state = HSM_ST_ERR; goto fsm_start; } @@ -4096,7 +4104,13 @@ fsm_start: /* ATA PIO protocol */ if (unlikely((status & ATA_DRQ) == 0)) { /* handle BSY=0, DRQ=0 as error */ - qc->err_mask |= AC_ERR_HSM; + if (likely(status & (ATA_ERR | ATA_DF))) + /* device stops HSM for abort/error */ + qc->err_mask |= AC_ERR_DEV; + else + /* HSM violation. Let EH handle this */ + qc->err_mask |= AC_ERR_HSM; + ap->hsm_task_state = HSM_ST_ERR; goto fsm_start; } @@ -4121,6 +4135,9 @@ fsm_start: status = ata_wait_idle(ap); } + if (status & (ATA_BUSY | ATA_DRQ)) + qc->err_mask |= AC_ERR_HSM; + /* ata_pio_sectors() might change the * state to HSM_ST_LAST. so, the state * is changed after ata_pio_sectors(). diff --git a/include/linux/libata.h b/include/linux/libata.h index 2803ab8e924..c51502c047a 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -1062,7 +1062,7 @@ static inline int ata_try_flush_cache(const struct ata_device *dev) static inline unsigned int ac_err_mask(u8 status) { - if (status & ATA_BUSY) + if (status & (ATA_BUSY | ATA_DRQ)) return AC_ERR_HSM; if (status & (ATA_ERR | ATA_DF)) return AC_ERR_DEV; -- cgit v1.2.3 From eec4c3f317991dc85c786ffccd9c1a8620c41b18 Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Thu, 18 May 2006 17:51:10 +0800 Subject: [PATCH] libata: use qc->result_tf for temp taskfile storage Use qc->result_tf for temp taskfile storage. Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index aa38ed3e59a..bf00d2b2e40 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3865,10 +3865,16 @@ static void atapi_pio_bytes(struct ata_queued_cmd *qc) unsigned int ireason, bc_lo, bc_hi, bytes; int i_write, do_write = (qc->tf.flags & ATA_TFLAG_WRITE) ? 1 : 0; - ap->ops->tf_read(ap, &qc->tf); - ireason = qc->tf.nsect; - bc_lo = qc->tf.lbam; - bc_hi = qc->tf.lbah; + /* Abuse qc->result_tf for temp storage of intermediate TF + * here to save some kernel stack usage. + * For normal completion, qc->result_tf is not relevant. For + * error, qc->result_tf is later overwritten by ata_qc_complete(). + * So, the correctness of qc->result_tf is not affected. + */ + ap->ops->tf_read(ap, &qc->result_tf); + ireason = qc->result_tf.nsect; + bc_lo = qc->result_tf.lbam; + bc_hi = qc->result_tf.lbah; bytes = (bc_hi << 8) | bc_lo; /* shall be cleared to zero, indicating xfer of data */ -- cgit v1.2.3 From a20f33ffde8ba5fb27666aa1e228a45b7e3b8dcb Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 16 May 2006 12:58:24 +0900 Subject: [PATCH] libata: enforce default EH actions LLDDs rely on libata that certain EH actions are automatically taken on some errors. If the port is frozen or one or more qc's have failed with HSM violation or timeout, softreset is enforced (LLDD can ask for storonger EH action at will). If any other error condition exists, libata EH always revalidates. This behavior existed in earlier revisions of new EH but lost during development process. This patch restores it. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-eh.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c index 7244caff13a..750e734d1c0 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/scsi/libata-eh.c @@ -1169,9 +1169,6 @@ static void ata_eh_autopsy(struct ata_port *ap) /* inherit upper level err_mask */ qc->err_mask |= ehc->i.err_mask; - if (qc->err_mask & AC_ERR_TIMEOUT) - action |= ATA_EH_SOFTRESET; - /* analyze TF */ action |= ata_eh_analyze_tf(qc, &qc->result_tf); @@ -1201,9 +1198,14 @@ static void ata_eh_autopsy(struct ata_port *ap) if (failed_dev) action |= ata_eh_speed_down(failed_dev, is_io, all_err_mask); - if (all_err_mask) + /* enforce default EH actions */ + if (ap->flags & ATA_FLAG_FROZEN || + all_err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT)) + action |= ATA_EH_SOFTRESET; + else if (all_err_mask) action |= ATA_EH_REVALIDATE; + /* record autopsy result */ ehc->i.dev = failed_dev; ehc->i.action = action; -- cgit v1.2.3 From f8bbfc247efb0e5fa69094614380768ce79afe17 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 19 May 2006 21:07:05 +0900 Subject: [PATCH] SCSI: make scsi_implement_eh() generic API for SCSI transports libata implemented a feature to schedule EH without an associated EH by manipulating shost->host_eh_scheduled in ata_scsi_schedule_eh() directly. Move this function to scsi_error.c and rename it to scsi_schedule_eh(). It is now an exported API for SCSI transports and exported via new header file drivers/scsi/scsi_transport_api.h This patch also de-export scsi_eh_wakeup() which was exported specifically for ata_scsi_schedule_eh(). Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-eh.c | 3 ++- drivers/scsi/libata-scsi.c | 24 ------------------------ drivers/scsi/scsi_error.c | 23 ++++++++++++++++++++++- drivers/scsi/scsi_priv.h | 1 + drivers/scsi/scsi_transport_api.h | 6 ++++++ include/scsi/scsi_eh.h | 1 - 6 files changed, 31 insertions(+), 27 deletions(-) create mode 100644 drivers/scsi/scsi_transport_api.h diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c index 750e734d1c0..71b45ad2c12 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/scsi/libata-eh.c @@ -39,6 +39,7 @@ #include #include #include +#include "scsi_transport_api.h" #include @@ -432,7 +433,7 @@ void ata_port_schedule_eh(struct ata_port *ap) WARN_ON(!ap->ops->error_handler); ap->flags |= ATA_FLAG_EH_PENDING; - ata_schedule_scsi_eh(ap->host); + scsi_schedule_eh(ap->host); DPRINTK("port EH scheduled\n"); } diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index f036ae4b8af..2007b4b6e1b 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -2745,27 +2745,3 @@ void ata_scsi_scan_host(struct ata_port *ap) scsi_scan_target(&ap->host->shost_gendev, 0, i, 0, 0); } } - -/** - * ata_schedule_scsi_eh - schedule EH for SCSI host - * @shost: SCSI host to invoke error handling on. - * - * Schedule SCSI EH without scmd. This is a hack. - * - * LOCKING: - * spin_lock_irqsave(host_set lock) - **/ -void ata_schedule_scsi_eh(struct Scsi_Host *shost) -{ - unsigned long flags; - - spin_lock_irqsave(shost->host_lock, flags); - - if (scsi_host_set_state(shost, SHOST_RECOVERY) == 0 || - scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY) == 0) { - shost->host_eh_scheduled++; - scsi_eh_wakeup(shost); - } - - spin_unlock_irqrestore(shost->host_lock, flags); -} diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 9ca71cbefce..346ab72ebf8 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -56,7 +56,28 @@ void scsi_eh_wakeup(struct Scsi_Host *shost) printk("Waking error handler thread\n")); } } -EXPORT_SYMBOL_GPL(scsi_eh_wakeup); + +/** + * scsi_schedule_eh - schedule EH for SCSI host + * @shost: SCSI host to invoke error handling on. + * + * Schedule SCSI EH without scmd. + **/ +void scsi_schedule_eh(struct Scsi_Host *shost) +{ + unsigned long flags; + + spin_lock_irqsave(shost->host_lock, flags); + + if (scsi_host_set_state(shost, SHOST_RECOVERY) == 0 || + scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY) == 0) { + shost->host_eh_scheduled++; + scsi_eh_wakeup(shost); + } + + spin_unlock_irqrestore(shost->host_lock, flags); +} +EXPORT_SYMBOL_GPL(scsi_schedule_eh); /** * scsi_eh_scmd_add - add scsi cmd to error handling. diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index 0b39081113b..27c48274e8c 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -63,6 +63,7 @@ extern int scsi_delete_timer(struct scsi_cmnd *); extern void scsi_times_out(struct scsi_cmnd *cmd); extern int scsi_error_handler(void *host); extern int scsi_decide_disposition(struct scsi_cmnd *cmd); +extern void scsi_eh_wakeup(struct Scsi_Host *shost); extern int scsi_eh_scmd_add(struct scsi_cmnd *, int); /* scsi_lib.c */ diff --git a/drivers/scsi/scsi_transport_api.h b/drivers/scsi/scsi_transport_api.h new file mode 100644 index 00000000000..934f0e62bb5 --- /dev/null +++ b/drivers/scsi/scsi_transport_api.h @@ -0,0 +1,6 @@ +#ifndef _SCSI_TRANSPORT_API_H +#define _SCSI_TRANSPORT_API_H + +void scsi_schedule_eh(struct Scsi_Host *shost); + +#endif /* _SCSI_TRANSPORT_API_H */ diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h index 212c983a6a1..d160880b2a8 100644 --- a/include/scsi/scsi_eh.h +++ b/include/scsi/scsi_eh.h @@ -35,7 +35,6 @@ static inline int scsi_sense_valid(struct scsi_sense_hdr *sshdr) } -extern void scsi_eh_wakeup(struct Scsi_Host *shost); extern void scsi_eh_finish_cmd(struct scsi_cmnd *scmd, struct list_head *done_q); extern void scsi_eh_flush_done_q(struct list_head *done_q); -- cgit v1.2.3 From b74ba22f030eb7ab88f7d8954ad18ecc0ac5ce3c Mon Sep 17 00:00:00 2001 From: Thomas Glanzmann Date: Fri, 12 May 2006 10:00:41 +0200 Subject: [PATCH] Add PCI ID for the Intel IDE Controller which is in the Intel Mac Minis shipped in first quarter 2006 Signed-off-by: Thomas Glanzmann Signed-off-by: Jeff Garzik --- drivers/scsi/ata_piix.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index e3184a77a60..28bd8cae52c 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -159,6 +159,7 @@ static const struct pci_device_id piix_pci_tbl[] = { { 0x8086, 0x7111, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix4_pata }, { 0x8086, 0x24db, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_pata }, { 0x8086, 0x25a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_pata }, + { 0x8086, 0x27df, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_pata }, #endif /* NOTE: The following PCI ids must be kept in sync with the -- cgit v1.2.3 From edb527ce35b0c86e72ed518af255f02e1cecb3b7 Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Wed, 10 May 2006 09:11:38 -0700 Subject: [SCSI] aacraid: remove unneeded locking Received From Mark Salyzyn Since new commands to the card are quiesced, respect the changes in the SCSI error path which dropped locking around the hba reset handler and similarly drop the lock requirement in the driver's path. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley --- drivers/scsi/aacraid/linit.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 6ef89c99dd1..9647dabc661 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -453,15 +453,10 @@ static int aac_eh_reset(struct scsi_cmnd* cmd) printk(KERN_ERR "%s: Host adapter reset request. SCSI hang ?\n", AAC_DRIVERNAME); - - - spin_lock_irq(host->host_lock); - aac = (struct aac_dev *)host->hostdata; if (aac_adapter_check_health(aac)) { printk(KERN_ERR "%s: Host adapter appears dead\n", AAC_DRIVERNAME); - spin_unlock_irq(host->host_lock); return -ENODEV; } /* @@ -487,13 +482,10 @@ static int aac_eh_reset(struct scsi_cmnd* cmd) /* * We can exit If all the commands are complete */ - spin_unlock_irq(host->host_lock); if (active == 0) return SUCCESS; ssleep(1); - spin_lock_irq(host->host_lock); } - spin_unlock_irq(host->host_lock); printk(KERN_ERR "%s: SCSI bus appears hung\n", AAC_DRIVERNAME); return -ETIMEDOUT; } -- cgit v1.2.3 From 3c1e0cca9469bd19590ade25f6d9f94da2710d5b Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Wed, 10 May 2006 09:12:05 -0700 Subject: [SCSI] aacraid: optimize sg alloc Received From Mark Salyzyn Slight space and speed efficiency improvement. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley --- drivers/scsi/aacraid/aachba.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 642a3b4e593..5d2989754c9 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -2218,15 +2218,15 @@ static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* psg) } } else if(scsicmd->request_bufflen) { - dma_addr_t addr; - addr = pci_map_single(dev->pdev, + u32 addr; + scsicmd->SCp.dma_handle = pci_map_single(dev->pdev, scsicmd->request_buffer, scsicmd->request_bufflen, scsicmd->sc_data_direction); + addr = scsicmd->SCp.dma_handle; psg->count = cpu_to_le32(1); psg->sg[0].addr = cpu_to_le32(addr); psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen); - scsicmd->SCp.dma_handle = addr; byte_count = scsicmd->request_bufflen; } return byte_count; -- cgit v1.2.3 From 404d9a900b5bc83a3780ec337ca6fdcb04b766c0 Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Wed, 10 May 2006 09:12:48 -0700 Subject: [SCSI] aacraid: adjustable timeouts Received From Mark Salyzyn Add the ability to adjust for unusual corner case failures. Both of these additional module parameters deal with embedded, non-intel or complicated system scenarios. Aif_timeout can be increased past the default 2 minute timeout to drop application registrations when a system has an unusually high event load resulting from continuing management requests, or simultaneous builds, or sluggish user space as a result of system load. Startup_timeout can be increased past the default 3 minute timeout to drop an adapter initialization for systems that have a very large number of targets, or slow to spin-up targets, or a complicated set of array configurations that extend the time for the firmware to declare that it is operational. This timeout would only have an affect on non-intel based systems, as the (more patient) BIOS would generally be where the startup delay would be dealt with. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley --- drivers/scsi/aacraid/aachba.c | 6 ++++++ drivers/scsi/aacraid/aacraid.h | 2 ++ drivers/scsi/aacraid/commsup.c | 2 +- drivers/scsi/aacraid/rkt.c | 4 ++-- drivers/scsi/aacraid/rx.c | 4 ++-- drivers/scsi/aacraid/sa.c | 4 ++-- 6 files changed, 15 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 5d2989754c9..be8dde4c0f0 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -148,6 +148,8 @@ static int nondasd = -1; static int dacmode = -1; static int commit = -1; +int startup_timeout = 180; +int aif_timeout = 120; module_param(nondasd, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(nondasd, "Control scanning of hba for nondasd devices. 0=off, 1=on"); @@ -155,6 +157,10 @@ module_param(dacmode, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(dacmode, "Control whether dma addressing is using 64 bit DAC. 0=off, 1=on"); module_param(commit, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(commit, "Control whether a COMMIT_CONFIG is issued to the adapter for foreign arrays.\nThis is typically needed in systems that do not have a BIOS. 0=off, 1=on"); +module_param(startup_timeout, int, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(startup_timeout, "The duration of time in seconds to wait for adapter to have it's kernel up and\nrunning. This is typically adjusted for large systems that do not have a BIOS."); +module_param(aif_timeout, int, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(aif_timeout, "The duration of time in seconds to wait for applications to pick up AIFs before\nderegistering them. This is typically adjusted for heavily burdened systems."); int numacb = -1; module_param(numacb, int, S_IRUGO|S_IWUSR); diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index f773b0dcfc9..ff5c380eae3 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -1815,3 +1815,5 @@ int aac_probe_container(struct aac_dev *dev, int cid); extern int numacb; extern int acbsize; extern char aac_driver_version[]; +extern int startup_timeout; +extern int aif_timeout; diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 9f9f4aae23c..1c83af3d0f3 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -1214,7 +1214,7 @@ int aac_command_thread(void *data) * since the last read off * the queue? */ - if ((time_now - time_last) > 120) { + if ((time_now - time_last) > aif_timeout) { entry = entry->next; aac_close_fib_context(dev, fibctx); continue; diff --git a/drivers/scsi/aacraid/rkt.c b/drivers/scsi/aacraid/rkt.c index 7a23e027eb7..5b52966bbbf 100644 --- a/drivers/scsi/aacraid/rkt.c +++ b/drivers/scsi/aacraid/rkt.c @@ -444,14 +444,14 @@ int aac_rkt_init(struct aac_dev *dev) */ while (!(rkt_readl(dev, MUnit.OMRx[0]) & KERNEL_UP_AND_RUNNING)) { - if(time_after(jiffies, start+180*HZ)) + if(time_after(jiffies, start+startup_timeout*HZ)) { status = rkt_readl(dev, MUnit.OMRx[0]); printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n", dev->name, instance, status); goto error_iounmap; } - schedule_timeout_uninterruptible(1); + msleep(1); } if (request_irq(dev->scsi_host_ptr->irq, aac_rkt_intr, SA_SHIRQ|SA_INTERRUPT, "aacraid", (void *)dev)<0) { diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c index 729b9eb268c..9dadfb28b3f 100644 --- a/drivers/scsi/aacraid/rx.c +++ b/drivers/scsi/aacraid/rx.c @@ -444,14 +444,14 @@ int aac_rx_init(struct aac_dev *dev) while ((!(rx_readl(dev, IndexRegs.Mailbox[7]) & KERNEL_UP_AND_RUNNING)) || (!(rx_readl(dev, MUnit.OMRx[0]) & KERNEL_UP_AND_RUNNING))) { - if(time_after(jiffies, start+180*HZ)) + if(time_after(jiffies, start+startup_timeout*HZ)) { status = rx_readl(dev, IndexRegs.Mailbox[7]); printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n", dev->name, instance, status); goto error_iounmap; } - schedule_timeout_uninterruptible(1); + msleep(1); } if (request_irq(dev->scsi_host_ptr->irq, aac_rx_intr, SA_SHIRQ|SA_INTERRUPT, "aacraid", (void *)dev)<0) { diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c index a5345490820..ecc47b605c5 100644 --- a/drivers/scsi/aacraid/sa.c +++ b/drivers/scsi/aacraid/sa.c @@ -318,13 +318,13 @@ int aac_sa_init(struct aac_dev *dev) * Wait for the adapter to be up and running. Wait up to 3 minutes. */ while (!(sa_readl(dev, Mailbox7) & KERNEL_UP_AND_RUNNING)) { - if (time_after(jiffies, start+180*HZ)) { + if (time_after(jiffies, start+startup_timeout*HZ)) { status = sa_readl(dev, Mailbox7); printk(KERN_WARNING "%s%d: adapter kernel failed to start, init status = %lx.\n", name, instance, status); goto error_iounmap; } - schedule_timeout_uninterruptible(1); + msleep(1); } if (request_irq(dev->scsi_host_ptr->irq, aac_sa_intr, SA_SHIRQ|SA_INTERRUPT, "aacraid", (void *)dev ) < 0) { -- cgit v1.2.3 From df3b7668715f9acfe6ff37dd886f68e46ccd677e Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Wed, 10 May 2006 09:13:11 -0700 Subject: [SCSI] aacraid: sa race condition fix Received From Mark Salyzyn A race condition existed that could result in a lost completion of a command to the ppc based cards. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley --- drivers/scsi/aacraid/sa.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c index ecc47b605c5..88d400fccc9 100644 --- a/drivers/scsi/aacraid/sa.c +++ b/drivers/scsi/aacraid/sa.c @@ -66,11 +66,11 @@ static irqreturn_t aac_sa_intr(int irq, void *dev_id, struct pt_regs *regs) sa_writew(dev, DoorbellClrReg_p, PrintfReady); /* clear PrintfReady */ sa_writew(dev, DoorbellReg_s, PrintfDone); } else if (intstat & DOORBELL_1) { // dev -> Host Normal Command Ready - aac_command_normal(&dev->queues->queue[HostNormCmdQueue]); sa_writew(dev, DoorbellClrReg_p, DOORBELL_1); + aac_command_normal(&dev->queues->queue[HostNormCmdQueue]); } else if (intstat & DOORBELL_2) { // dev -> Host Normal Response Ready - aac_response_normal(&dev->queues->queue[HostNormRespQueue]); sa_writew(dev, DoorbellClrReg_p, DOORBELL_2); + aac_response_normal(&dev->queues->queue[HostNormRespQueue]); } else if (intstat & DOORBELL_3) { // dev -> Host Normal Command Not Full sa_writew(dev, DoorbellClrReg_p, DOORBELL_3); } else if (intstat & DOORBELL_4) { // dev -> Host Normal Response Not Full -- cgit v1.2.3 From 5b9851b5511833a96fea2196971b5709ef019136 Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Wed, 10 May 2006 09:13:37 -0700 Subject: [SCSI] aacraid: remove unneeded list Received From Mark Salyzyn The queue tracking is just not being used, not even for debugging. Information about outstanding commands can be acquired from the scsi structures. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley --- drivers/scsi/aacraid/aacraid.h | 2 -- drivers/scsi/aacraid/comminit.c | 1 - drivers/scsi/aacraid/commsup.c | 4 ---- drivers/scsi/aacraid/dpcsup.c | 2 -- 4 files changed, 9 deletions(-) diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index ff5c380eae3..e6b41dbbec8 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -563,7 +563,6 @@ struct aac_queue { spinlock_t lockdata; /* Actual lock (used only on one side of the lock) */ struct list_head cmdq; /* A queue of FIBs which need to be prcessed by the FS thread. This is */ /* only valid for command queues which receive entries from the adapter. */ - struct list_head pendingq; /* A queue of outstanding fib's to the adapter. */ u32 numpending; /* Number of entries on outstanding queue. */ struct aac_dev * dev; /* Back pointer to adapter structure */ }; @@ -826,7 +825,6 @@ struct fib { * The following is used to put this fib context onto the * Outstanding I/O queue. */ - struct list_head queue; /* * And for the internal issue/reply queues (we may be able * to merge these two) diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c index 19397453bae..1d43c17642c 100644 --- a/drivers/scsi/aacraid/comminit.c +++ b/drivers/scsi/aacraid/comminit.c @@ -159,7 +159,6 @@ static void aac_queue_init(struct aac_dev * dev, struct aac_queue * q, u32 *mem, { q->numpending = 0; q->dev = dev; - INIT_LIST_HEAD(&q->pendingq); init_waitqueue_head(&q->cmdready); INIT_LIST_HEAD(&q->cmdq); init_waitqueue_head(&q->qfull); diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 1c83af3d0f3..d2ef17ea44f 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -472,7 +472,6 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, spin_lock_irqsave(q->lock, qflags); if (dev->new_comm_interface) { unsigned long count = 10000000L; /* 50 seconds */ - list_add_tail(&fibptr->queue, &q->pendingq); q->numpending++; spin_unlock_irqrestore(q->lock, qflags); while (aac_adapter_send(fibptr) != 0) { @@ -481,7 +480,6 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, spin_unlock_irqrestore(&fibptr->event_lock, flags); spin_lock_irqsave(q->lock, qflags); q->numpending--; - list_del(&fibptr->queue); spin_unlock_irqrestore(q->lock, qflags); return -ETIMEDOUT; } @@ -492,7 +490,6 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, unsigned long nointr = 0; aac_queue_get( dev, &index, AdapNormCmdQueue, hw_fib, 1, fibptr, &nointr); - list_add_tail(&fibptr->queue, &q->pendingq); q->numpending++; *(q->headers.producer) = cpu_to_le32(index + 1); spin_unlock_irqrestore(q->lock, qflags); @@ -520,7 +517,6 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, if (--count == 0) { spin_lock_irqsave(q->lock, qflags); q->numpending--; - list_del(&fibptr->queue); spin_unlock_irqrestore(q->lock, qflags); if (wait == -1) { printk(KERN_ERR "aacraid: aac_fib_send: first asynchronous command timed out.\n" diff --git a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c index f6bcb9486f8..bd6a67dd250 100644 --- a/drivers/scsi/aacraid/dpcsup.c +++ b/drivers/scsi/aacraid/dpcsup.c @@ -86,7 +86,6 @@ unsigned int aac_response_normal(struct aac_queue * q) * the fib timed out. */ if (!(fib->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) { - list_del(&fib->queue); dev->queues->queue[AdapNormCmdQueue].numpending--; } else { printk(KERN_WARNING "aacraid: FIB timeout (%x).\n", fib->flags); @@ -284,7 +283,6 @@ unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index) return 0; } - list_del(&fib->queue); dev->queues->queue[AdapNormCmdQueue].numpending--; if (fast) { -- cgit v1.2.3 From 07fb75a50600c0c480b40c6d11dbc993f21bc2bc Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Sun, 14 May 2006 00:39:38 +0200 Subject: [SCSI] fix (unlikely) memory leak in DAC960 driver The Coverity checker found a memory leak (bug nr. 1245) in drivers/block/DAC960.c::DAC960_V2_ProcessCompletedCommand() The leak is pretty unlikely since it requires that the first of two successive kmalloc() calls fail while the second one succeeds. But it can still happen even if it's unlikely. If the first call that allocates 'PhysicalDeviceInfo' fails but the one that allocates 'InquiryUnitSerialNumber' succeeds, then we will leak the memory allocated to 'InquiryUnitSerialNumber' when the variable goes out of scope. A simple fix for this is to change the existing code that frees 'PhysicalDeviceInfo' if that one was allocated but 'InquiryUnitSerialNumber' was not, into a check for either pointer being NULL and if so just free both. This is safe since kfree() can deal with being passed a NULL pointer and it avoids the leak. While I was there I also removed the casts of the kmalloc() return value since it's pointless. I also updated the driver version since this patch changes the workings of the code (however slightly). This issue could probably be fixed a lot more elegantly, but the code is a big mess IMHO and I just took the least intrusive route to a fix that I could find instead of starting on a cleanup as well (that can come later). Please consider for inclusion. Signed-off-by: Jesper Juhl Signed-off-by: James Bottomley --- drivers/block/DAC960.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c index 45bcda54488..dd8a1501142 100644 --- a/drivers/block/DAC960.c +++ b/drivers/block/DAC960.c @@ -17,8 +17,8 @@ */ -#define DAC960_DriverVersion "2.5.47" -#define DAC960_DriverDate "14 November 2002" +#define DAC960_DriverVersion "2.5.48" +#define DAC960_DriverDate "14 May 2006" #include @@ -4780,15 +4780,16 @@ static void DAC960_V2_ProcessCompletedCommand(DAC960_Command_T *Command) (NewPhysicalDeviceInfo->LogicalUnit != PhysicalDeviceInfo->LogicalUnit)) { - PhysicalDeviceInfo = (DAC960_V2_PhysicalDeviceInfo_T *) + PhysicalDeviceInfo = kmalloc(sizeof(DAC960_V2_PhysicalDeviceInfo_T), GFP_ATOMIC); InquiryUnitSerialNumber = - (DAC960_SCSI_Inquiry_UnitSerialNumber_T *) kmalloc(sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T), GFP_ATOMIC); - if (InquiryUnitSerialNumber == NULL && - PhysicalDeviceInfo != NULL) + if (InquiryUnitSerialNumber == NULL || + PhysicalDeviceInfo == NULL) { + kfree(InquiryUnitSerialNumber); + InquiryUnitSerialNumber = NULL; kfree(PhysicalDeviceInfo); PhysicalDeviceInfo = NULL; } -- cgit v1.2.3 From 6e458cc943dd494ac68b570418f187883e555362 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Thu, 18 May 2006 20:31:31 -0500 Subject: [SCSI] iscsi: dont use sendpage for iscsi headers From Zhen and ported by Mike: Don't use sendpage for the headers. sendpage for the pdu headers does not seem to have a performance impact, makes life harder for mutiple data pdus to be in flight and still trips up some network cards when it is from slab mem. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/iscsi_tcp.c | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index d94038eafb9..7c2ed7bb7e9 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -70,14 +70,6 @@ module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO); /* global data */ static kmem_cache_t *taskcache; -static inline void -iscsi_buf_init_virt(struct iscsi_buf *ibuf, char *vbuf, int size) -{ - sg_init_one(&ibuf->sg, (u8 *)vbuf, size); - ibuf->sent = 0; - ibuf->use_sendmsg = 0; -} - static inline void iscsi_buf_init_iov(struct iscsi_buf *ibuf, char *vbuf, int size) { @@ -324,7 +316,7 @@ iscsi_solicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, r2t->sent = 0; - iscsi_buf_init_virt(&r2t->headbuf, (char*)hdr, + iscsi_buf_init_iov(&r2t->headbuf, (char*)hdr, sizeof(struct iscsi_hdr)); r2t->dtask = dtask; @@ -1208,7 +1200,7 @@ iscsi_digest_final_send(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, if (final) crypto_digest_final(tcp_conn->data_tx_tfm, (u8*)digest); - iscsi_buf_init_virt(buf, (char*)digest, 4); + iscsi_buf_init_iov(buf, (char*)digest, 4); rc = iscsi_sendpage(conn, buf, &tcp_ctask->digest_count, &sent); if (rc) { tcp_ctask->datadigest = *digest; @@ -1265,7 +1257,7 @@ iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, } conn->dataout_pdus_cnt++; - iscsi_buf_init_virt(&r2t->headbuf, (char*)hdr, + iscsi_buf_init_iov(&r2t->headbuf, (char*)hdr, sizeof(struct iscsi_hdr)); r2t->dtask = dtask; @@ -1294,7 +1286,7 @@ iscsi_unsolicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) iscsi_prep_unsolicit_data_pdu(ctask, &dtask->hdr, tcp_ctask->r2t_data_count); - iscsi_buf_init_virt(&tcp_ctask->headbuf, (char*)&dtask->hdr, + iscsi_buf_init_iov(&tcp_ctask->headbuf, (char*)&dtask->hdr, sizeof(struct iscsi_hdr)); list_add(&dtask->item, &tcp_ctask->dataqueue); @@ -1361,7 +1353,7 @@ iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask) } else tcp_ctask->xmstate = XMSTATE_R_HDR; - iscsi_buf_init_virt(&tcp_ctask->headbuf, (char*)ctask->hdr, + iscsi_buf_init_iov(&tcp_ctask->headbuf, (char*)ctask->hdr, sizeof(struct iscsi_hdr)); } @@ -1758,7 +1750,7 @@ handle_xmstate_w_pad(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) int sent; tcp_ctask->xmstate &= ~XMSTATE_W_PAD; - iscsi_buf_init_virt(&tcp_ctask->sendbuf, (char*)&tcp_ctask->pad, + iscsi_buf_init_iov(&tcp_ctask->sendbuf, (char*)&tcp_ctask->pad, tcp_ctask->pad_count); if (iscsi_sendpage(conn, &tcp_ctask->sendbuf, &tcp_ctask->pad_count, &sent)) { @@ -2078,8 +2070,8 @@ iscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask, { struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data; - iscsi_buf_init_virt(&tcp_mtask->headbuf, (char*)mtask->hdr, - sizeof(struct iscsi_hdr)); + iscsi_buf_init_iov(&tcp_mtask->headbuf, (char*)mtask->hdr, + sizeof(struct iscsi_hdr)); tcp_mtask->xmstate = XMSTATE_IMM_HDR; if (mtask->data_count) -- cgit v1.2.3 From d36ab6f3212053b260214bc915687765e2fd1178 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Thu, 18 May 2006 20:31:34 -0500 Subject: [SCSI] iscsi: only preallocate login buffer We only use the mtask data buffer for login tasks so we do not need to preallocate a buffer for every mtask. This saves 8 * 31 KB. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/libiscsi.c | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 4750d488810..580c0505603 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -1258,15 +1258,6 @@ iscsi_session_setup(struct iscsi_transport *iscsit, if (mgmt_task_size) mtask->dd_data = &mtask[1]; mtask->itt = ISCSI_MGMT_ITT_OFFSET + cmd_i; - mtask->data = kmalloc(DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH, - GFP_KERNEL); - if (!mtask->data) { - int j; - - for (j = 0; j < cmd_i; j++) - kfree(session->mgmt_cmds[j]->data); - goto immdata_alloc_fail; - } } if (scsi_add_host(shost, NULL)) @@ -1282,9 +1273,6 @@ iscsi_session_setup(struct iscsi_transport *iscsit, cls_session_fail: scsi_remove_host(shost); add_host_fail: - for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) - kfree(session->mgmt_cmds[cmd_i]->data); -immdata_alloc_fail: iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds); mgmtpool_alloc_fail: iscsi_pool_free(&session->cmdpool, (void**)session->cmds); @@ -1305,13 +1293,9 @@ void iscsi_session_teardown(struct iscsi_cls_session *cls_session) { struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); struct iscsi_session *session = iscsi_hostdata(shost->hostdata); - int cmd_i; scsi_remove_host(shost); - for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) - kfree(session->mgmt_cmds[cmd_i]->data); - iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds); iscsi_pool_free(&session->cmdpool, (void**)session->cmds); @@ -1331,6 +1315,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx) struct iscsi_session *session = class_to_transport_session(cls_session); struct iscsi_conn *conn; struct iscsi_cls_conn *cls_conn; + char *data; cls_conn = iscsi_create_conn(cls_session, conn_idx); if (!cls_conn) @@ -1376,12 +1361,20 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx) } spin_unlock_bh(&session->lock); + data = kmalloc(DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH, GFP_KERNEL); + if (!data) + goto login_mtask_data_alloc_fail; + conn->login_mtask->data = data; + init_timer(&conn->tmabort_timer); mutex_init(&conn->xmitmutex); init_waitqueue_head(&conn->ehwait); return cls_conn; +login_mtask_data_alloc_fail: + __kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask, + sizeof(void*)); login_mtask_alloc_fail: kfifo_free(conn->mgmtqueue); mgmtqueue_alloc_fail: @@ -1451,6 +1444,7 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) } spin_lock_bh(&session->lock); + kfree(conn->login_mtask->data); __kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask, sizeof(void*)); list_del(&conn->item); -- cgit v1.2.3 From ffbfe92533810bf1bb76fd275400825ef8898ed9 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Thu, 18 May 2006 20:31:36 -0500 Subject: [SCSI] iscsi: kill dtask mempools Discovered by steven@hayter.me.uk and patch by michaelc@cs.wisc.edu The dtask mempool is reserving 261120 items per session! Since we are now sending headers with sendmsg there is no reason for the mempool and that was causing us to us carzy amounts of mem. We can preallicate a header in the r2t and task struct and reuse them Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/iscsi_tcp.c | 87 ++++-------------------------------------------- drivers/scsi/iscsi_tcp.h | 11 +++--- 2 files changed, 10 insertions(+), 88 deletions(-) diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 7c2ed7bb7e9..08357a6c7e0 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -67,9 +67,6 @@ MODULE_VERSION("0:4.445"); static unsigned int iscsi_max_lun = 512; module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO); -/* global data */ -static kmem_cache_t *taskcache; - static inline void iscsi_buf_init_iov(struct iscsi_buf *ibuf, char *vbuf, int size) { @@ -195,16 +192,6 @@ __iscsi_ctask_cleanup(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) if (unlikely(!sc)) return; - if (sc->sc_data_direction == DMA_TO_DEVICE) { - struct iscsi_data_task *dtask, *n; - - /* WRITE: cleanup Data-Out's if any */ - list_for_each_entry_safe(dtask, n, &tcp_ctask->dataqueue, - item) { - list_del(&dtask->item); - mempool_free(dtask, tcp_ctask->datapool); - } - } tcp_ctask->xmstate = XMSTATE_IDLE; tcp_ctask->r2t = NULL; } @@ -286,14 +273,10 @@ iscsi_solicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, struct iscsi_r2t_info *r2t) { struct iscsi_data *hdr; - struct iscsi_data_task *dtask; struct scsi_cmnd *sc = ctask->sc; struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; - dtask = mempool_alloc(tcp_ctask->datapool, GFP_ATOMIC); - BUG_ON(!dtask); - INIT_LIST_HEAD(&dtask->item); - hdr = &dtask->hdr; + hdr = &r2t->dtask.hdr; memset(hdr, 0, sizeof(struct iscsi_data)); hdr->ttt = r2t->ttt; hdr->datasn = cpu_to_be32(r2t->solicit_datasn); @@ -319,8 +302,6 @@ iscsi_solicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, iscsi_buf_init_iov(&r2t->headbuf, (char*)hdr, sizeof(struct iscsi_hdr)); - r2t->dtask = dtask; - if (sc->use_sg) { int i, sg_count = 0; struct scatterlist *sg = sc->request_buffer; @@ -352,8 +333,6 @@ iscsi_solicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, iscsi_buf_init_iov(&tcp_ctask->sendbuf, (char*)sc->request_buffer + r2t->data_offset, r2t->data_count); - - list_add(&dtask->item, &tcp_ctask->dataqueue); } /** @@ -1229,14 +1208,10 @@ iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, { struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; struct iscsi_data *hdr; - struct iscsi_data_task *dtask; struct scsi_cmnd *sc = ctask->sc; int new_offset; - dtask = mempool_alloc(tcp_ctask->datapool, GFP_ATOMIC); - BUG_ON(!dtask); - INIT_LIST_HEAD(&dtask->item); - hdr = &dtask->hdr; + hdr = &r2t->dtask.hdr; memset(hdr, 0, sizeof(struct iscsi_data)); hdr->ttt = r2t->ttt; hdr->datasn = cpu_to_be32(r2t->solicit_datasn); @@ -1260,8 +1235,6 @@ iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, iscsi_buf_init_iov(&r2t->headbuf, (char*)hdr, sizeof(struct iscsi_hdr)); - r2t->dtask = dtask; - if (sc->use_sg && !iscsi_buf_left(&r2t->sendbuf)) { BUG_ON(tcp_ctask->bad_sg == r2t->sg); iscsi_buf_init_sg(&r2t->sendbuf, r2t->sg); @@ -1270,8 +1243,6 @@ iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, iscsi_buf_init_iov(&tcp_ctask->sendbuf, (char*)sc->request_buffer + new_offset, r2t->data_count); - - list_add(&dtask->item, &tcp_ctask->dataqueue); } static void @@ -1280,17 +1251,11 @@ iscsi_unsolicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; struct iscsi_data_task *dtask; - dtask = mempool_alloc(tcp_ctask->datapool, GFP_ATOMIC); - BUG_ON(!dtask); - INIT_LIST_HEAD(&dtask->item); - + dtask = tcp_ctask->dtask = &tcp_ctask->unsol_dtask; iscsi_prep_unsolicit_data_pdu(ctask, &dtask->hdr, tcp_ctask->r2t_data_count); iscsi_buf_init_iov(&tcp_ctask->headbuf, (char*)&dtask->hdr, sizeof(struct iscsi_hdr)); - - list_add(&dtask->item, &tcp_ctask->dataqueue); - tcp_ctask->dtask = dtask; } /** @@ -1534,7 +1499,6 @@ handle_xmstate_uns_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) tcp_ctask->xmstate |= XMSTATE_UNS_DATA; if (tcp_ctask->xmstate & XMSTATE_UNS_INIT) { iscsi_unsolicit_data_init(conn, ctask); - BUG_ON(!tcp_ctask->dtask); dtask = tcp_ctask->dtask; if (conn->hdrdgst_en) iscsi_hdr_digest(conn, &tcp_ctask->headbuf, @@ -1643,7 +1607,7 @@ handle_xmstate_sol_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) struct iscsi_tcp_conn *tcp_conn = conn->dd_data; struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; struct iscsi_r2t_info *r2t = tcp_ctask->r2t; - struct iscsi_data_task *dtask = r2t->dtask; + struct iscsi_data_task *dtask = &r2t->dtask; int left; tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA; @@ -1857,7 +1821,7 @@ solicit_head_again: r2t = tcp_ctask->r2t; if (conn->hdrdgst_en) iscsi_hdr_digest(conn, &r2t->headbuf, - (u8*)r2t->dtask->hdrext); + (u8*)r2t->dtask.hdrext); if (iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count)) { tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA; tcp_ctask->xmstate |= XMSTATE_SOL_HDR; @@ -2113,21 +2077,6 @@ iscsi_r2tpool_alloc(struct iscsi_session *session) (void**)tcp_ctask->r2ts); goto r2t_alloc_fail; } - - /* - * number of - * Data-Out PDU's within R2T-sequence can be quite big; - * using mempool - */ - tcp_ctask->datapool = mempool_create_slab_pool(ISCSI_DTASK_DEFAULT_MAX, - taskcache); - if (tcp_ctask->datapool == NULL) { - kfifo_free(tcp_ctask->r2tqueue); - iscsi_pool_free(&tcp_ctask->r2tpool, - (void**)tcp_ctask->r2ts); - goto r2t_alloc_fail; - } - INIT_LIST_HEAD(&tcp_ctask->dataqueue); } return 0; @@ -2137,7 +2086,6 @@ r2t_alloc_fail: struct iscsi_cmd_task *ctask = session->cmds[i]; struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; - mempool_destroy(tcp_ctask->datapool); kfifo_free(tcp_ctask->r2tqueue); iscsi_pool_free(&tcp_ctask->r2tpool, (void**)tcp_ctask->r2ts); @@ -2154,7 +2102,6 @@ iscsi_r2tpool_free(struct iscsi_session *session) struct iscsi_cmd_task *ctask = session->cmds[i]; struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; - mempool_destroy(tcp_ctask->datapool); kfifo_free(tcp_ctask->r2tqueue); iscsi_pool_free(&tcp_ctask->r2tpool, (void**)tcp_ctask->r2ts); @@ -2496,21 +2443,6 @@ r2tpool_alloc_fail: static void iscsi_tcp_session_destroy(struct iscsi_cls_session *cls_session) { - struct iscsi_session *session = class_to_transport_session(cls_session); - struct iscsi_data_task *dtask, *n; - int cmd_i; - - for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) { - struct iscsi_cmd_task *ctask = session->cmds[cmd_i]; - struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; - - list_for_each_entry_safe(dtask, n, &tcp_ctask->dataqueue, - item) { - list_del(&dtask->item); - mempool_free(dtask, tcp_ctask->datapool); - } - } - iscsi_r2tpool_free(class_to_transport_session(cls_session)); iscsi_session_teardown(cls_session); } @@ -2592,14 +2524,8 @@ iscsi_tcp_init(void) } iscsi_tcp_transport.max_lun = iscsi_max_lun; - taskcache = kmem_cache_create("iscsi_taskcache", - sizeof(struct iscsi_data_task), 0, - SLAB_HWCACHE_ALIGN, NULL, NULL); - if (!taskcache) - return -ENOMEM; - if (!iscsi_register_transport(&iscsi_tcp_transport)) - kmem_cache_destroy(taskcache); + return -ENODEV; return 0; } @@ -2608,7 +2534,6 @@ static void __exit iscsi_tcp_exit(void) { iscsi_unregister_transport(&iscsi_tcp_transport); - kmem_cache_destroy(taskcache); } module_init(iscsi_tcp_init); diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h index c5918854d59..808302832e6 100644 --- a/drivers/scsi/iscsi_tcp.h +++ b/drivers/scsi/iscsi_tcp.h @@ -118,11 +118,9 @@ struct iscsi_buf { struct iscsi_data_task { struct iscsi_data hdr; /* PDU */ char hdrext[sizeof(__u32)]; /* Header-Digest */ - struct list_head item; /* data queue item */ struct iscsi_buf digestbuf; /* digest buffer */ uint32_t digest; /* data digest */ }; -#define ISCSI_DTASK_DEFAULT_MAX ISCSI_SG_TABLESIZE * PAGE_SIZE / 512 struct iscsi_tcp_mgmt_task { struct iscsi_hdr hdr; @@ -144,7 +142,7 @@ struct iscsi_r2t_info { int data_count; /* DATA-Out payload progress */ struct scatterlist *sg; /* per-R2T SG list */ int solicit_datasn; - struct iscsi_data_task *dtask; /* which data task */ + struct iscsi_data_task dtask; /* which data task */ }; struct iscsi_tcp_cmd_task { @@ -167,14 +165,13 @@ struct iscsi_tcp_cmd_task { struct iscsi_queue r2tpool; struct kfifo *r2tqueue; struct iscsi_r2t_info **r2ts; - struct list_head dataqueue; /* Data-Out dataqueue */ - mempool_t *datapool; uint32_t datadigest; /* for recover digest */ int digest_count; uint32_t immdigest; /* for imm data */ struct iscsi_buf immbuf; /* for imm data digest */ - struct iscsi_data_task *dtask; /* data task in progress*/ - int digest_offset; /* for partial buff digest */ + struct iscsi_data_task *dtask; /* data task in progress*/ + struct iscsi_data_task unsol_dtask; /* unsol data task */ + int digest_offset; /* for partial buff digest */ }; #endif /* ISCSI_H */ -- cgit v1.2.3 From 790f39a2d5f03623b027f340b945f135d006ceba Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Thu, 18 May 2006 20:31:39 -0500 Subject: [SCSI] iscsi: support mutiple daemons Patch from david.somayajulu@qlogic.com and cleaned up by Tomo. qla4xxx is going to have a different daemon so this patch just routes the events to the right daemon. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_iscsi.c | 38 ++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 44adafac861..5569fdcfd62 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -36,6 +36,7 @@ #define ISCSI_HOST_ATTRS 0 struct iscsi_internal { + int daemon_pid; struct scsi_transport_template t; struct iscsi_transport *iscsi_transport; struct list_head list; @@ -145,7 +146,6 @@ static DECLARE_TRANSPORT_CLASS(iscsi_connection_class, NULL); static struct sock *nls; -static int daemon_pid; static DEFINE_MUTEX(rx_queue_mutex); struct mempool_zone { @@ -572,13 +572,13 @@ mempool_zone_get_skb(struct mempool_zone *zone) } static int -iscsi_unicast_skb(struct mempool_zone *zone, struct sk_buff *skb) +iscsi_unicast_skb(struct mempool_zone *zone, struct sk_buff *skb, int pid) { unsigned long flags; int rc; skb_get(skb); - rc = netlink_unicast(nls, skb, daemon_pid, MSG_DONTWAIT); + rc = netlink_unicast(nls, skb, pid, MSG_DONTWAIT); if (rc < 0) { mempool_free(skb, zone->pool); printk(KERN_ERR "iscsi: can not unicast skb (%d)\n", rc); @@ -600,9 +600,14 @@ int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr, struct sk_buff *skb; struct iscsi_uevent *ev; char *pdu; + struct iscsi_internal *priv; int len = NLMSG_SPACE(sizeof(*ev) + sizeof(struct iscsi_hdr) + data_size); + priv = iscsi_if_transport_lookup(conn->transport); + if (!priv) + return -EINVAL; + mempool_zone_complete(conn->z_pdu); skb = mempool_zone_get_skb(conn->z_pdu); @@ -613,7 +618,7 @@ int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr, return -ENOMEM; } - nlh = __nlmsg_put(skb, daemon_pid, 0, 0, (len - sizeof(*nlh)), 0); + nlh = __nlmsg_put(skb, priv->daemon_pid, 0, 0, (len - sizeof(*nlh)), 0); ev = NLMSG_DATA(nlh); memset(ev, 0, sizeof(*ev)); ev->transport_handle = iscsi_handle(conn->transport); @@ -626,7 +631,7 @@ int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr, memcpy(pdu, hdr, sizeof(struct iscsi_hdr)); memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size); - return iscsi_unicast_skb(conn->z_pdu, skb); + return iscsi_unicast_skb(conn->z_pdu, skb, priv->daemon_pid); } EXPORT_SYMBOL_GPL(iscsi_recv_pdu); @@ -635,8 +640,13 @@ void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error) struct nlmsghdr *nlh; struct sk_buff *skb; struct iscsi_uevent *ev; + struct iscsi_internal *priv; int len = NLMSG_SPACE(sizeof(*ev)); + priv = iscsi_if_transport_lookup(conn->transport); + if (!priv) + return; + mempool_zone_complete(conn->z_error); skb = mempool_zone_get_skb(conn->z_error); @@ -646,7 +656,7 @@ void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error) return; } - nlh = __nlmsg_put(skb, daemon_pid, 0, 0, (len - sizeof(*nlh)), 0); + nlh = __nlmsg_put(skb, priv->daemon_pid, 0, 0, (len - sizeof(*nlh)), 0); ev = NLMSG_DATA(nlh); ev->transport_handle = iscsi_handle(conn->transport); ev->type = ISCSI_KEVENT_CONN_ERROR; @@ -656,7 +666,7 @@ void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error) ev->r.connerror.cid = conn->cid; ev->r.connerror.sid = iscsi_conn_get_sid(conn); - iscsi_unicast_skb(conn->z_error, skb); + iscsi_unicast_skb(conn->z_error, skb, priv->daemon_pid); dev_printk(KERN_INFO, &conn->dev, "iscsi: detected conn error (%d)\n", error); @@ -686,7 +696,7 @@ iscsi_if_send_reply(int pid, int seq, int type, int done, int multi, nlh = __nlmsg_put(skb, pid, seq, t, (len - sizeof(*nlh)), 0); nlh->nlmsg_flags = flags; memcpy(NLMSG_DATA(nlh), payload, size); - return iscsi_unicast_skb(z_reply, skb); + return iscsi_unicast_skb(z_reply, skb, pid); } static int @@ -698,12 +708,17 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh) struct iscsi_cls_conn *conn; struct nlmsghdr *nlhstat; struct iscsi_uevent *evstat; + struct iscsi_internal *priv; int len = NLMSG_SPACE(sizeof(*ev) + sizeof(struct iscsi_stats) + sizeof(struct iscsi_stats_custom) * ISCSI_STATS_CUSTOM_MAX); int err = 0; + priv = iscsi_if_transport_lookup(transport); + if (!priv) + return -EINVAL; + conn = iscsi_conn_lookup(ev->u.get_stats.sid, ev->u.get_stats.cid); if (!conn) return -EEXIST; @@ -720,7 +735,7 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh) return -ENOMEM; } - nlhstat = __nlmsg_put(skbstat, daemon_pid, 0, 0, + nlhstat = __nlmsg_put(skbstat, priv->daemon_pid, 0, 0, (len - sizeof(*nlhstat)), 0); evstat = NLMSG_DATA(nlhstat); memset(evstat, 0, sizeof(*evstat)); @@ -746,7 +761,7 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh) skb_trim(skbstat, NLMSG_ALIGN(actual_size)); nlhstat->nlmsg_len = actual_size; - err = iscsi_unicast_skb(conn->z_pdu, skbstat); + err = iscsi_unicast_skb(conn->z_pdu, skbstat, priv->daemon_pid); } while (err < 0 && err != -ECONNREFUSED); return err; @@ -981,6 +996,8 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) if (!try_module_get(transport->owner)) return -EINVAL; + priv->daemon_pid = NETLINK_CREDS(skb)->pid; + switch (nlh->nlmsg_type) { case ISCSI_UEVENT_CREATE_SESSION: err = iscsi_if_create_session(priv, ev); @@ -1073,7 +1090,6 @@ iscsi_if_rx(struct sock *sk, int len) skb_pull(skb, skb->len); goto free_skb; } - daemon_pid = NETLINK_CREDS(skb)->pid; while (skb->len >= NLMSG_SPACE(0)) { int err; -- cgit v1.2.3 From 656cffc95f0cb8211aa75eaca249e6ff4f59ec83 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Thu, 18 May 2006 20:31:42 -0500 Subject: [SCSI] iscsi: fix command requeues during iscsi recovery Do not flush queues then block session. This will cause commands to needlessly swing around on us and remove goofy recovery_failed field and replace with state value. And do not start recovery from within the host reset function. This causeis too many problems becuase open-iscsi was desinged to call out to userspace then have userpscae decide if we should go into recovery or kill the session. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/libiscsi.c | 87 ++++++++++++++++++++----------------- include/scsi/libiscsi.h | 3 -- include/scsi/scsi_transport_iscsi.h | 2 + 3 files changed, 50 insertions(+), 42 deletions(-) diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 580c0505603..d810acae45f 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -487,6 +487,11 @@ void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err) unsigned long flags; spin_lock_irqsave(&session->lock, flags); + if (session->state == ISCSI_STATE_FAILED) { + spin_unlock_irqrestore(&session->lock, flags); + return; + } + if (session->conn_cnt == 1 || session->leadconn == conn) session->state = ISCSI_STATE_FAILED; spin_unlock_irqrestore(&session->lock, flags); @@ -612,6 +617,7 @@ enum { FAILURE_SESSION_FREED, FAILURE_WINDOW_CLOSED, FAILURE_SESSION_TERMINATE, + FAILURE_SESSION_IN_RECOVERY, FAILURE_SESSION_RECOVERY_TIMEOUT, }; @@ -631,18 +637,30 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) spin_lock(&session->lock); - if (session->state != ISCSI_STATE_LOGGED_IN) { - if (session->recovery_failed) { - reason = FAILURE_SESSION_RECOVERY_TIMEOUT; - goto fault; - } else if (session->state == ISCSI_STATE_FAILED) { - reason = FAILURE_SESSION_FAILED; - goto reject; - } else if (session->state == ISCSI_STATE_TERMINATE) { - reason = FAILURE_SESSION_TERMINATE; + /* + * ISCSI_STATE_FAILED is a temp. state. The recovery + * code will decide what is best to do with command queued + * during this time + */ + if (session->state != ISCSI_STATE_LOGGED_IN && + session->state != ISCSI_STATE_FAILED) { + /* + * to handle the race between when we set the recovery state + * and block the session we requeue here (commands could + * be entering our queuecommand while a block is starting + * up because the block code is not locked) + */ + if (session->state == ISCSI_STATE_IN_RECOVERY) { + reason = FAILURE_SESSION_IN_RECOVERY; goto fault; } - reason = FAILURE_SESSION_FREED; + + if (session->state == ISCSI_STATE_RECOVERY_FAILED) + reason = FAILURE_SESSION_RECOVERY_TIMEOUT; + else if (session->state == ISCSI_STATE_TERMINATE) + reason = FAILURE_SESSION_TERMINATE; + else + reason = FAILURE_SESSION_FREED; goto fault; } @@ -728,8 +746,8 @@ iscsi_conn_send_generic(struct iscsi_conn *conn, struct iscsi_hdr *hdr, */ mtask = conn->login_mtask; else { - BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE); - BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED); + BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE); + BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED); nop->exp_statsn = cpu_to_be32(conn->exp_statsn); if (!__kfifo_get(session->mgmtpool.queue, @@ -803,7 +821,7 @@ void iscsi_session_recovery_timedout(struct iscsi_cls_session *cls_session) spin_lock_bh(&session->lock); if (session->state != ISCSI_STATE_LOGGED_IN) { - session->recovery_failed = 1; + session->state = ISCSI_STATE_RECOVERY_FAILED; if (conn) wake_up(&conn->ehwait); } @@ -838,20 +856,14 @@ failed: * we drop the lock here but the leadconn cannot be destoyed while * we are in the scsi eh */ - if (fail_session) { + if (fail_session) iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); - /* - * if userspace cannot respond then we must kick this off - * here for it - */ - iscsi_start_session_recovery(session, conn, STOP_CONN_RECOVER); - } debug_scsi("iscsi_eh_host_reset wait for relogin\n"); wait_event_interruptible(conn->ehwait, session->state == ISCSI_STATE_TERMINATE || session->state == ISCSI_STATE_LOGGED_IN || - session->recovery_failed); + session->state == ISCSI_STATE_RECOVERY_FAILED); if (signal_pending(current)) flush_signals(current); @@ -940,8 +952,7 @@ static int iscsi_exec_abort_task(struct scsi_cmnd *sc, wait_event_interruptible(conn->ehwait, sc->SCp.phase != session->age || session->state != ISCSI_STATE_LOGGED_IN || - conn->tmabort_state != TMABORT_INITIAL || - session->recovery_failed); + conn->tmabort_state != TMABORT_INITIAL); if (signal_pending(current)) flush_signals(current); del_timer_sync(&conn->tmabort_timer); @@ -1491,7 +1502,6 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn) conn->stop_stage = 0; conn->tmabort_state = TMABORT_INITIAL; session->age++; - session->recovery_failed = 0; spin_unlock_bh(&session->lock); iscsi_unblock_session(session_to_cls(session)); @@ -1566,8 +1576,8 @@ static void fail_all_commands(struct iscsi_conn *conn) conn->ctask = NULL; } -void iscsi_start_session_recovery(struct iscsi_session *session, - struct iscsi_conn *conn, int flag) +static void iscsi_start_session_recovery(struct iscsi_session *session, + struct iscsi_conn *conn, int flag) { int old_stop_stage; @@ -1597,19 +1607,10 @@ void iscsi_start_session_recovery(struct iscsi_session *session, set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); if (session->conn_cnt == 0 || session->leadconn == conn) - session->state = ISCSI_STATE_FAILED; + session->state = ISCSI_STATE_IN_RECOVERY; spin_unlock_bh(&session->lock); - session->tt->terminate_conn(conn); - /* - * flush queues. - */ - spin_lock_bh(&session->lock); - fail_all_commands(conn); - flush_control_queues(session, conn); - spin_unlock_bh(&session->lock); - /* * for connection level recovery we should not calculate * header digest. conn->hdr_size used for optimization @@ -1619,18 +1620,26 @@ void iscsi_start_session_recovery(struct iscsi_session *session, if (flag == STOP_CONN_RECOVER) { conn->hdrdgst_en = 0; conn->datadgst_en = 0; - /* * if this is called from the eh and and from userspace * then we only need to block once. */ - if (session->state == ISCSI_STATE_FAILED && + if (session->state == ISCSI_STATE_IN_RECOVERY && old_stop_stage != STOP_CONN_RECOVER) iscsi_block_session(session_to_cls(session)); } + + session->tt->terminate_conn(conn); + /* + * flush queues. + */ + spin_lock_bh(&session->lock); + fail_all_commands(conn); + flush_control_queues(session, conn); + spin_unlock_bh(&session->lock); + mutex_unlock(&conn->xmitmutex); } -EXPORT_SYMBOL_GPL(iscsi_start_session_recovery); void iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) { diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index 2dba929a2a0..17b28f08b69 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h @@ -210,7 +210,6 @@ struct iscsi_session { * - mgmtpool, * * - r2tpool */ int state; /* session state */ - int recovery_failed; struct list_head item; int conn_cnt; int age; /* counts session re-opens */ @@ -241,8 +240,6 @@ iscsi_session_setup(struct iscsi_transport *, struct scsi_transport_template *, int, int, uint32_t, uint32_t *); extern void iscsi_session_teardown(struct iscsi_cls_session *); extern struct iscsi_session *class_to_transport_session(struct iscsi_cls_session *); -extern void iscsi_start_session_recovery(struct iscsi_session *, - struct iscsi_conn *, int); extern void iscsi_session_recovery_timedout(struct iscsi_cls_session *); #define session_to_cls(_sess) \ diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index c9e9475c6df..92129b97d31 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -173,6 +173,8 @@ struct iscsi_cls_conn { #define ISCSI_STATE_LOGGED_IN 2 #define ISCSI_STATE_FAILED 3 #define ISCSI_STATE_TERMINATE 4 +#define ISCSI_STATE_IN_RECOVERY 5 +#define ISCSI_STATE_RECOVERY_FAILED 6 struct iscsi_cls_session { struct list_head sess_list; /* item in session_list */ -- cgit v1.2.3 From e0ecae8da26d94dd878ff1d939c5aa4224df18a4 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Thu, 18 May 2006 20:31:43 -0500 Subject: [SCSI] iscsi: update version update version Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/iscsi_tcp.c | 8 +++++--- include/scsi/iscsi_proto.h | 2 -- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 08357a6c7e0..c66faee07ca 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -43,11 +43,13 @@ #include "iscsi_tcp.h" +#define ISCSI_TCP_VERSION "1.0-574" + MODULE_AUTHOR("Dmitry Yusupov , " "Alex Aizman "); MODULE_DESCRIPTION("iSCSI/TCP data-path"); MODULE_LICENSE("GPL"); -MODULE_VERSION("0:4.445"); +MODULE_VERSION(ISCSI_TCP_VERSION); /* #define DEBUG_TCP */ #define DEBUG_ASSERT @@ -2448,8 +2450,8 @@ static void iscsi_tcp_session_destroy(struct iscsi_cls_session *cls_session) } static struct scsi_host_template iscsi_sht = { - .name = "iSCSI Initiator over TCP/IP, v." - ISCSI_VERSION_STR, + .name = "iSCSI Initiator over TCP/IP, v" + ISCSI_TCP_VERSION, .queuecommand = iscsi_queuecommand, .change_queue_depth = iscsi_change_queue_depth, .can_queue = ISCSI_XMIT_CMDS_MAX - 1, diff --git a/include/scsi/iscsi_proto.h b/include/scsi/iscsi_proto.h index 4feda05fdf2..02f6e4b9e69 100644 --- a/include/scsi/iscsi_proto.h +++ b/include/scsi/iscsi_proto.h @@ -21,8 +21,6 @@ #ifndef ISCSI_PROTO_H #define ISCSI_PROTO_H -#define ISCSI_VERSION_STR "0.3" -#define ISCSI_DATE_STR "22-Apr-2005" #define ISCSI_DRAFT20_VERSION 0x00 /* default iSCSI listen port for incoming connections */ -- cgit v1.2.3 From 57680080baf3a8e289fad7f9e3c43ed58309e1eb Mon Sep 17 00:00:00 2001 From: Ravi Anand Date: Wed, 17 May 2006 15:08:44 -0700 Subject: [SCSI] qla2xxx: Don't wait for loop transition to complete if LOOP_DEAD state is attained. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_os.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 017729c59a4..fbf3b03aba6 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -577,6 +577,10 @@ qla2x00_wait_for_loop_ready(scsi_qla_host_t *ha) while ((!atomic_read(&ha->loop_down_timer) && atomic_read(&ha->loop_state) == LOOP_DOWN) || atomic_read(&ha->loop_state) != LOOP_READY) { + if (atomic_read(&ha->loop_state) == LOOP_DEAD) { + return_status = QLA_FUNCTION_FAILED; + break; + } msleep(1000); if (time_after_eq(jiffies, loop_timeout)) { return_status = QLA_FUNCTION_FAILED; -- cgit v1.2.3 From 45aeaf1e8e4552ef82d3ff7a06e526e6d635f767 Mon Sep 17 00:00:00 2001 From: Ravi Anand Date: Wed, 17 May 2006 15:08:49 -0700 Subject: [SCSI] qla2xxx: Add support for new flash part. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_def.h | 2 + drivers/scsi/qla2xxx/qla_sup.c | 93 ++++++++++++++++++++++++++++++++++++------ 2 files changed, 83 insertions(+), 12 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 53508f3c4ae..488124258e8 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -270,6 +270,8 @@ struct device_reg_2xxx { #define NVR_SELECT BIT_1 #define NVR_CLOCK BIT_0 +#define NVR_WAIT_CNT 20000 + union { struct { uint16_t mailbox0; diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index 8b0121dceb0..c71dbd5bd54 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c @@ -97,7 +97,7 @@ qla2x00_write_nvram_word(scsi_qla_host_t *ha, uint32_t addr, uint16_t data) { int count; uint16_t word; - uint32_t nv_cmd; + uint32_t nv_cmd, wait_cnt; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; qla2x00_nv_write(ha, NVR_DATA_OUT); @@ -127,7 +127,13 @@ qla2x00_write_nvram_word(scsi_qla_host_t *ha, uint32_t addr, uint16_t data) /* Wait for NVRAM to become ready */ WRT_REG_WORD(®->nvram, NVR_SELECT); RD_REG_WORD(®->nvram); /* PCI Posting. */ + wait_cnt = NVR_WAIT_CNT; do { + if (!--wait_cnt) { + DEBUG9_10(printk("%s(%ld): NVRAM didn't go ready...\n", + __func__, ha->host_no)); + break; + } NVRAM_DELAY(); word = RD_REG_WORD(®->nvram); } while ((word & NVR_DATA_IN) == 0); @@ -301,16 +307,17 @@ qla2x00_clear_nvram_protection(scsi_qla_host_t *ha) { int ret, stat; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; - uint32_t word; + uint32_t word, wait_cnt; uint16_t wprot, wprot_old; /* Clear NVRAM write protection. */ ret = QLA_FUNCTION_FAILED; - wprot_old = cpu_to_le16(qla2x00_get_nvram_word(ha, 0)); - stat = qla2x00_write_nvram_word_tmo(ha, 0, + + wprot_old = cpu_to_le16(qla2x00_get_nvram_word(ha, ha->nvram_base)); + stat = qla2x00_write_nvram_word_tmo(ha, ha->nvram_base, __constant_cpu_to_le16(0x1234), 100000); - wprot = cpu_to_le16(qla2x00_get_nvram_word(ha, 0)); - if (stat != QLA_SUCCESS || wprot != __constant_cpu_to_le16(0x1234)) { + wprot = cpu_to_le16(qla2x00_get_nvram_word(ha, ha->nvram_base)); + if (stat != QLA_SUCCESS || wprot != 0x1234) { /* Write enable. */ qla2x00_nv_write(ha, NVR_DATA_OUT); qla2x00_nv_write(ha, 0); @@ -341,14 +348,22 @@ qla2x00_clear_nvram_protection(scsi_qla_host_t *ha) /* Wait for NVRAM to become ready. */ WRT_REG_WORD(®->nvram, NVR_SELECT); RD_REG_WORD(®->nvram); /* PCI Posting. */ + wait_cnt = NVR_WAIT_CNT; do { + if (!--wait_cnt) { + DEBUG9_10(printk("%s(%ld): NVRAM didn't go " + "ready...\n", __func__, + ha->host_no)); + break; + } NVRAM_DELAY(); word = RD_REG_WORD(®->nvram); } while ((word & NVR_DATA_IN) == 0); - ret = QLA_SUCCESS; + if (wait_cnt) + ret = QLA_SUCCESS; } else - qla2x00_write_nvram_word(ha, 0, wprot_old); + qla2x00_write_nvram_word(ha, ha->nvram_base, wprot_old); return ret; } @@ -357,7 +372,7 @@ static void qla2x00_set_nvram_protection(scsi_qla_host_t *ha, int stat) { struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; - uint32_t word; + uint32_t word, wait_cnt; if (stat != QLA_SUCCESS) return; @@ -393,7 +408,13 @@ qla2x00_set_nvram_protection(scsi_qla_host_t *ha, int stat) /* Wait for NVRAM to become ready. */ WRT_REG_WORD(®->nvram, NVR_SELECT); RD_REG_WORD(®->nvram); /* PCI Posting. */ + wait_cnt = NVR_WAIT_CNT; do { + if (!--wait_cnt) { + DEBUG9_10(printk("%s(%ld): NVRAM didn't go ready...\n", + __func__, ha->host_no)); + break; + } NVRAM_DELAY(); word = RD_REG_WORD(®->nvram); } while ((word & NVR_DATA_IN) == 0); @@ -500,6 +521,20 @@ qla24xx_get_flash_manufacturer(scsi_qla_host_t *ha, uint8_t *man_id, ids = qla24xx_read_flash_dword(ha, flash_data_to_access_addr(0xd03ab)); *man_id = LSB(ids); *flash_id = MSB(ids); + + /* Check if man_id and flash_id are valid. */ + if (ids != 0xDEADDEAD && (*man_id == 0 || *flash_id == 0)) { + /* Read information using 0x9f opcode + * Device ID, Mfg ID would be read in the format: + * + * Example: ATMEL 0x00 01 45 1F + * Extract MFG and Dev ID from last two bytes. + */ + ids = qla24xx_read_flash_dword(ha, + flash_data_to_access_addr(0xd009f)); + *man_id = LSB(ids); + *flash_id = MSB(ids); + } } int @@ -508,8 +543,8 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr, { int ret; uint32_t liter; - uint32_t sec_mask, rest_addr, conf_addr; - uint32_t fdata; + uint32_t sec_mask, rest_addr, conf_addr, sec_end_mask; + uint32_t fdata, findex ; uint8_t man_id, flash_id; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; @@ -519,6 +554,7 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr, DEBUG9(printk("%s(%ld): Flash man_id=%d flash_id=%d\n", __func__, ha->host_no, man_id, flash_id)); + sec_end_mask = 0; conf_addr = flash_conf_to_access_addr(0x03d8); switch (man_id) { case 0xbf: /* STT flash. */ @@ -531,6 +567,12 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr, rest_addr = 0x3fff; sec_mask = 0x3c000; break; + case 0x1f: // Atmel 26DF081A + rest_addr = 0x0fff; + sec_mask = 0xff000; + sec_end_mask = 0x003ff; + conf_addr = flash_conf_to_access_addr(0x0320); + break; default: /* Default to 64 kb sector size. */ rest_addr = 0x3fff; @@ -545,11 +587,30 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr, /* Disable flash write-protection. */ qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0); + /* Some flash parts need an additional zero-write to clear bits.*/ + qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0); do { /* Loop once to provide quick error exit. */ for (liter = 0; liter < dwords; liter++, faddr++, dwptr++) { + if (man_id == 0x1f) { + findex = faddr << 2; + fdata = findex & sec_mask; + } else { + findex = faddr; + fdata = (findex & sec_mask) << 2; + } + /* Are we at the beginning of a sector? */ - if ((faddr & rest_addr) == 0) { + if ((findex & rest_addr) == 0) { + /* + * Do sector unprotect at 4K boundry for Atmel + * part. + */ + if (man_id == 0x1f) + qla24xx_write_flash_dword(ha, + flash_conf_to_access_addr(0x0339), + (fdata & 0xff00) | ((fdata << 16) & + 0xff0000) | ((fdata >> 16) & 0xff)); fdata = (faddr & sec_mask) << 2; ret = qla24xx_write_flash_dword(ha, conf_addr, (fdata & 0xff00) |((fdata << 16) & @@ -570,6 +631,14 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr, ha->host_no, faddr, *dwptr)); break; } + + /* Do sector protect at 4K boundry for Atmel part. */ + if (man_id == 0x1f && + ((faddr & sec_end_mask) == 0x3ff)) + qla24xx_write_flash_dword(ha, + flash_conf_to_access_addr(0x0336), + (fdata & 0xff00) | ((fdata << 16) & + 0xff0000) | ((fdata >> 16) & 0xff)); } } while (0); -- cgit v1.2.3 From ed17c71b5d11327efd40666fd621486f964fae4f Mon Sep 17 00:00:00 2001 From: Ravi Anand Date: Wed, 17 May 2006 15:08:55 -0700 Subject: [SCSI] qla2xxx: Use FW calculated residual count for underrun handling. With ISP24XX and ISP54XX parts. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_fw.h | 2 +- drivers/scsi/qla2xxx/qla_isr.c | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h index 1ee58ad2f4d..d2f5870628d 100644 --- a/drivers/scsi/qla2xxx/qla_fw.h +++ b/drivers/scsi/qla2xxx/qla_fw.h @@ -463,7 +463,7 @@ struct sts_entry_24xx { uint16_t comp_status; /* Completion status. */ uint16_t ox_id; /* OX_ID used by the firmware. */ - uint32_t residual_len; /* Residual transfer length. */ + uint32_t residual_len; /* FW calc residual transfer length. */ uint16_t reserved_1; uint16_t state_flags; /* State flags. */ diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 2003dbb7057..40325ec7005 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -805,7 +805,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) uint16_t scsi_status; uint8_t lscsi_status; int32_t resid; - uint32_t sense_len, rsp_info_len, resid_len; + uint32_t sense_len, rsp_info_len, resid_len, fw_resid_len; uint8_t *rsp_info, *sense_data; sts = (sts_entry_t *) pkt; @@ -859,11 +859,12 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) fcport = sp->fcport; - sense_len = rsp_info_len = resid_len = 0; + sense_len = rsp_info_len = resid_len = fw_resid_len = 0; if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { sense_len = le32_to_cpu(sts24->sense_len); rsp_info_len = le32_to_cpu(sts24->rsp_data_len); resid_len = le32_to_cpu(sts24->rsp_residual_count); + fw_resid_len = le32_to_cpu(sts24->residual_len); rsp_info = sts24->data; sense_data = sts24->data; host_to_fcp_swap(sts24->data, sizeof(sts24->data)); @@ -963,14 +964,21 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) case CS_DATA_UNDERRUN: resid = resid_len; + /* Use F/W calculated residual length. */ + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) + resid = fw_resid_len; + if (scsi_status & SS_RESIDUAL_UNDER) { cp->resid = resid; CMD_RESID_LEN(cp) = resid; } else { DEBUG2(printk(KERN_INFO "scsi(%ld:%d:%d) UNDERRUN status detected " - "0x%x-0x%x.\n", ha->host_no, cp->device->id, - cp->device->lun, comp_status, scsi_status)); + "0x%x-0x%x. resid=0x%x fw_resid=0x%x cdb=0x%x " + "os_underflow=0x%x\n", ha->host_no, + cp->device->id, cp->device->lun, comp_status, + scsi_status, resid_len, resid, cp->cmnd[0], + cp->underflow)); } -- cgit v1.2.3 From d1c61909c05ead100f855e640fba53925d0665ac Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Wed, 17 May 2006 15:09:00 -0700 Subject: [SCSI] qla2xxx: Update ISP24xx firwmare loading heuristics. If firmware image is unavailable via request_firwmare(), then attempt to load the image (likely out-of-date) stored in flash memory. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_init.c | 176 +++++++++++++++++++++------------------- 1 file changed, 93 insertions(+), 83 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 89a3fc0595b..1cf27fe92f4 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -3498,6 +3498,88 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) return (rval); } +int +qla24xx_load_risc_flash(scsi_qla_host_t *ha, uint32_t *srisc_addr) +{ + int rval; + int segments, fragment; + uint32_t faddr; + uint32_t *dcode, dlen; + uint32_t risc_addr; + uint32_t risc_size; + uint32_t i; + + rval = QLA_SUCCESS; + + segments = FA_RISC_CODE_SEGMENTS; + faddr = FA_RISC_CODE_ADDR; + dcode = (uint32_t *)ha->request_ring; + *srisc_addr = 0; + + /* Validate firmware image by checking version. */ + qla24xx_read_flash_data(ha, dcode, faddr + 4, 4); + for (i = 0; i < 4; i++) + dcode[i] = be32_to_cpu(dcode[i]); + if ((dcode[0] == 0xffffffff && dcode[1] == 0xffffffff && + dcode[2] == 0xffffffff && dcode[3] == 0xffffffff) || + (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 && + dcode[3] == 0)) { + qla_printk(KERN_WARNING, ha, + "Unable to verify integrity of flash firmware image!\n"); + qla_printk(KERN_WARNING, ha, + "Firmware data: %08x %08x %08x %08x!\n", dcode[0], + dcode[1], dcode[2], dcode[3]); + + return QLA_FUNCTION_FAILED; + } + + while (segments && rval == QLA_SUCCESS) { + /* Read segment's load information. */ + qla24xx_read_flash_data(ha, dcode, faddr, 4); + + risc_addr = be32_to_cpu(dcode[2]); + *srisc_addr = *srisc_addr == 0 ? risc_addr : *srisc_addr; + risc_size = be32_to_cpu(dcode[3]); + + fragment = 0; + while (risc_size > 0 && rval == QLA_SUCCESS) { + dlen = (uint32_t)(ha->fw_transfer_size >> 2); + if (dlen > risc_size) + dlen = risc_size; + + DEBUG7(printk("scsi(%ld): Loading risc segment@ risc " + "addr %x, number of dwords 0x%x, offset 0x%x.\n", + ha->host_no, risc_addr, dlen, faddr)); + + qla24xx_read_flash_data(ha, dcode, faddr, dlen); + for (i = 0; i < dlen; i++) + dcode[i] = swab32(dcode[i]); + + rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr, + dlen); + if (rval) { + DEBUG(printk("scsi(%ld):[ERROR] Failed to load " + "segment %d of firmware\n", ha->host_no, + fragment)); + qla_printk(KERN_WARNING, ha, + "[ERROR] Failed to load segment %d of " + "firmware\n", fragment); + break; + } + + faddr += dlen; + risc_addr += dlen; + risc_size -= dlen; + fragment++; + } + + /* Next segment. */ + segments--; + } + + return rval; +} + #if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) int @@ -3625,90 +3707,10 @@ qla24xx_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) return rval; } -int -qla24xx_load_risc_flash(scsi_qla_host_t *ha, uint32_t *srisc_addr) -{ - int rval; - int segments, fragment; - uint32_t faddr; - uint32_t *dcode, dlen; - uint32_t risc_addr; - uint32_t risc_size; - uint32_t i; - - rval = QLA_SUCCESS; - - segments = FA_RISC_CODE_SEGMENTS; - faddr = FA_RISC_CODE_ADDR; - dcode = (uint32_t *)ha->request_ring; - *srisc_addr = 0; - - /* Validate firmware image by checking version. */ - qla24xx_read_flash_data(ha, dcode, faddr + 4, 4); - for (i = 0; i < 4; i++) - dcode[i] = be32_to_cpu(dcode[i]); - if ((dcode[0] == 0xffffffff && dcode[1] == 0xffffffff && - dcode[2] == 0xffffffff && dcode[3] == 0xffffffff) || - (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 && - dcode[3] == 0)) { - qla_printk(KERN_WARNING, ha, - "Unable to verify integrity of flash firmware image!\n"); - qla_printk(KERN_WARNING, ha, - "Firmware data: %08x %08x %08x %08x!\n", dcode[0], - dcode[1], dcode[2], dcode[3]); - - return QLA_FUNCTION_FAILED; - } - - while (segments && rval == QLA_SUCCESS) { - /* Read segment's load information. */ - qla24xx_read_flash_data(ha, dcode, faddr, 4); - - risc_addr = be32_to_cpu(dcode[2]); - *srisc_addr = *srisc_addr == 0 ? risc_addr : *srisc_addr; - risc_size = be32_to_cpu(dcode[3]); - - fragment = 0; - while (risc_size > 0 && rval == QLA_SUCCESS) { - dlen = (uint32_t)(ha->fw_transfer_size >> 2); - if (dlen > risc_size) - dlen = risc_size; - - DEBUG7(printk("scsi(%ld): Loading risc segment@ risc " - "addr %x, number of dwords 0x%x, offset 0x%x.\n", - ha->host_no, risc_addr, dlen, faddr)); - - qla24xx_read_flash_data(ha, dcode, faddr, dlen); - for (i = 0; i < dlen; i++) - dcode[i] = swab32(dcode[i]); - - rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr, - dlen); - if (rval) { - DEBUG(printk("scsi(%ld):[ERROR] Failed to load " - "segment %d of firmware\n", ha->host_no, - fragment)); - qla_printk(KERN_WARNING, ha, - "[ERROR] Failed to load segment %d of " - "firmware\n", fragment); - break; - } - - faddr += dlen; - risc_addr += dlen; - risc_size -= dlen; - fragment++; - } - - /* Next segment. */ - segments--; - } - - return rval; -} - #else /* !defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) */ +#define QLA_FW_URL "ftp://ftp.qlogic.com/outgoing/linux/firmware/" + int qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) { @@ -3722,6 +3724,8 @@ qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) blob = qla2x00_request_firmware(ha); if (!blob) { qla_printk(KERN_ERR, ha, "Firmware image unavailable.\n"); + qla_printk(KERN_ERR, ha, "Firmware images can be retrieved " + "from: " QLA_FW_URL ".\n"); return QLA_FUNCTION_FAILED; } @@ -3823,7 +3827,13 @@ qla24xx_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) blob = qla2x00_request_firmware(ha); if (!blob) { qla_printk(KERN_ERR, ha, "Firmware image unavailable.\n"); - return QLA_FUNCTION_FAILED; + qla_printk(KERN_ERR, ha, "Firmware images can be retrieved " + "from: " QLA_FW_URL ".\n"); + + /* Try to load RISC code from flash. */ + qla_printk(KERN_ERR, ha, "Attempting to load (potentially " + "outdated) firmware from flash.\n"); + return qla24xx_load_risc_flash(ha, srisc_addr); } rval = QLA_SUCCESS; -- cgit v1.2.3 From ffb39f0324b56bacaabac26133143cf861d0e9f9 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Wed, 17 May 2006 15:09:06 -0700 Subject: [SCSI] qla2xxx: ABBA lock ordering fix. In qla2x00_reset_chip the driver first takes the hardware lock, and then later on takes the mbx lock. In the mailbox_command code.. it goes the other way around. Discovered with the lock validator. Cc: Ingo Molnar Cc: Arjan van de Ven Signed-off-by: Andrew Morton Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_init.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 1cf27fe92f4..1289a18e7ad 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -411,7 +411,6 @@ qla2x00_reset_chip(scsi_qla_host_t *ha) unsigned long flags = 0; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; uint32_t cnt; - unsigned long mbx_flags = 0; uint16_t cmd; ha->isp_ops.disable_intrs(ha); @@ -519,20 +518,8 @@ qla2x00_reset_chip(scsi_qla_host_t *ha) if (IS_QLA2100(ha) || IS_QLA2200(ha) || IS_QLA2300(ha)) { for (cnt = 0; cnt < 30000; cnt++) { - if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) - spin_lock_irqsave(&ha->mbx_reg_lock, mbx_flags); - - if (RD_MAILBOX_REG(ha, reg, 0) != MBS_BUSY) { - if (!(test_bit(ABORT_ISP_ACTIVE, - &ha->dpc_flags))) - spin_unlock_irqrestore( - &ha->mbx_reg_lock, mbx_flags); + if (RD_MAILBOX_REG(ha, reg, 0) != MBS_BUSY) break; - } - - if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) - spin_unlock_irqrestore(&ha->mbx_reg_lock, - mbx_flags); udelay(100); } -- cgit v1.2.3 From fd0e7e4dd507cd21d714d34a1cc1a620d01e9772 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Wed, 17 May 2006 15:09:11 -0700 Subject: [SCSI] qla2xxx: Correct endianess comparisons during ISP24xx NVRAM configuration. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_init.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 1289a18e7ad..7a5d52f23f5 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -3371,7 +3371,7 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) strcpy(ha->model_number, "QLA2462"); /* Prepare nodename */ - if ((icb->firmware_options_1 & BIT_14) == 0) { + if ((icb->firmware_options_1 & __constant_cpu_to_le32(BIT_14)) == 0) { /* * Firmware will apply the following mask if the nodename was * not provided. @@ -3387,8 +3387,8 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) ha->flags.enable_target_reset = 1; ha->flags.enable_led_scheme = 0; - ha->operating_mode = - (icb->firmware_options_2 & (BIT_6 | BIT_5 | BIT_4)) >> 4; + ha->operating_mode = (le32_to_cpu(icb->firmware_options_2) & + (BIT_6 | BIT_5 | BIT_4)) >> 4; memcpy(ha->fw_seriallink_options24, nv->seriallink_options, sizeof(ha->fw_seriallink_options24)); -- cgit v1.2.3 From 5341e868fb2e98090a68860a35bf4c11d7f8e5da Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Wed, 17 May 2006 15:09:16 -0700 Subject: [SCSI] qla2xxx: Add support for alternate WWN NVRAM setting. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_init.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 7a5d52f23f5..b1b20f43d72 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1532,6 +1532,12 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) while (cnt--) *dptr1++ = *dptr2++; + /* Use alternate WWN? */ + if (nv->host_p[1] & BIT_7) { + memcpy(icb->node_name, nv->alternate_node_name, WWN_SIZE); + memcpy(icb->port_name, nv->alternate_port_name, WWN_SIZE); + } + /* Prepare nodename */ if ((icb->firmware_options[1] & BIT_6) == 0) { /* @@ -3370,6 +3376,12 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) } else strcpy(ha->model_number, "QLA2462"); + /* Use alternate WWN? */ + if (nv->host_p & __constant_cpu_to_le32(BIT_15)) { + memcpy(icb->node_name, nv->alternate_node_name, WWN_SIZE); + memcpy(icb->port_name, nv->alternate_port_name, WWN_SIZE); + } + /* Prepare nodename */ if ((icb->firmware_options_1 & __constant_cpu_to_le32(BIT_14)) == 0) { /* -- cgit v1.2.3 From 75bc4190701d3c6bdffdc21c8a9e17751de9f77a Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Wed, 17 May 2006 15:09:22 -0700 Subject: [SCSI] qla2xxx: Drop unused driver cruft. - structure definitions. - structure members. - #define's. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_dbg.c | 1 - drivers/scsi/qla2xxx/qla_def.h | 116 ------------------------------------ drivers/scsi/qla2xxx/qla_gbl.h | 2 - drivers/scsi/qla2xxx/qla_init.c | 17 ------ drivers/scsi/qla2xxx/qla_iocb.c | 2 - drivers/scsi/qla2xxx/qla_isr.c | 5 +- drivers/scsi/qla2xxx/qla_os.c | 30 +--------- drivers/scsi/qla2xxx/qla_rscn.c | 1 - drivers/scsi/qla2xxx/qla_settings.h | 1 - 9 files changed, 5 insertions(+), 170 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 2d9b12ffe09..e8120fb7f88 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -1995,7 +1995,6 @@ qla2x00_print_scsi_cmd(struct scsi_cmnd * cmd) return; printk(" sp flags=0x%x\n", sp->flags); - printk(" state=%d\n", sp->state); } void diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 488124258e8..4bd67e9c284 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -189,22 +189,13 @@ typedef struct srb { struct scsi_cmnd *cmd; /* Linux SCSI command pkt */ - struct timer_list timer; /* Command timer */ - atomic_t ref_count; /* Reference count for this structure */ uint16_t flags; - /* Request state */ - uint16_t state; - /* Single transfer DMA context */ dma_addr_t dma_handle; uint32_t request_sense_length; uint8_t *request_sense_ptr; - - /* SRB magic number */ - uint16_t magic; -#define SRB_MAGIC 0x10CB } srb_t; /* @@ -225,21 +216,6 @@ typedef struct srb { #define SRB_IOCTL BIT_10 /* IOCTL command. */ #define SRB_TAPE BIT_11 /* FCP2 (Tape) command. */ -/* - * SRB state definitions - */ -#define SRB_FREE_STATE 0 /* returned back */ -#define SRB_PENDING_STATE 1 /* queued in LUN Q */ -#define SRB_ACTIVE_STATE 2 /* in Active Array */ -#define SRB_DONE_STATE 3 /* queued in Done Queue */ -#define SRB_RETRY_STATE 4 /* in Retry Queue */ -#define SRB_SUSPENDED_STATE 5 /* in suspended state */ -#define SRB_NO_QUEUE_STATE 6 /* is in between states */ -#define SRB_ACTIVE_TIMEOUT_STATE 7 /* in Active Array but timed out */ -#define SRB_FAILOVER_STATE 8 /* in Failover Queue */ -#define SRB_SCSI_RETRY_STATE 9 /* in Scsi Retry Queue */ - - /* * ISP I/O Register Set structure definitions. */ @@ -1515,62 +1491,6 @@ typedef struct { uint8_t port_name[WWN_SIZE]; } sw_info_t; -/* - * Inquiry command structure. - */ -#define INQ_DATA_SIZE 36 - -/* - * Inquiry mailbox IOCB packet definition. - */ -typedef struct { - union { - cmd_a64_entry_t cmd; - sts_entry_t rsp; - struct cmd_type_7 cmd24; - struct sts_entry_24xx rsp24; - } p; - uint8_t inq[INQ_DATA_SIZE]; -} inq_cmd_rsp_t; - -/* - * Report LUN command structure. - */ -#define CHAR_TO_SHORT(a, b) (uint16_t)((uint8_t)b << 8 | (uint8_t)a) - -typedef struct { - uint32_t len; - uint32_t rsrv; -} rpt_hdr_t; - -typedef struct { - struct { - uint8_t b : 6; - uint8_t address_method : 2; - } msb; - uint8_t lsb; - uint8_t unused[6]; -} rpt_lun_t; - -typedef struct { - rpt_hdr_t hdr; - rpt_lun_t lst[MAX_LUNS]; -} rpt_lun_lst_t; - -/* - * Report Lun mailbox IOCB packet definition. - */ -typedef struct { - union { - cmd_a64_entry_t cmd; - sts_entry_t rsp; - struct cmd_type_7 cmd24; - struct sts_entry_24xx rsp24; - } p; - rpt_lun_lst_t list; -} rpt_lun_cmd_rsp_t; - - /* * Fibre channel port type. */ @@ -1589,7 +1509,6 @@ typedef struct { typedef struct fc_port { struct list_head list; struct scsi_qla_host *ha; - struct scsi_qla_host *vis_ha; /* only used when suspending lun */ uint8_t node_name[WWN_SIZE]; uint8_t port_name[WWN_SIZE]; @@ -1610,17 +1529,9 @@ typedef struct fc_port { int login_retry; atomic_t port_down_timer; - uint8_t device_type; - uint8_t unused; - - uint8_t mp_byte; /* multi-path byte (not used) */ - uint8_t cur_path; /* current path id */ - spinlock_t rport_lock; struct fc_rport *rport, *drport; u32 supported_classes; - struct work_struct rport_add_work; - struct work_struct rport_del_work; } fc_port_t; /* @@ -2305,9 +2216,6 @@ typedef struct scsi_qla_host { uint32_t current_outstanding_cmd; srb_t *status_srb; /* Status continuation entry. */ - uint16_t revision; - uint8_t ports; - /* ISP configuration data. */ uint16_t loop_id; /* Host adapter loop id */ uint16_t fb_rev; @@ -2397,9 +2305,6 @@ typedef struct scsi_qla_host { struct gid_list_info *gid_list; int gid_list_info_size; - dma_addr_t rlc_rsp_dma; - rpt_lun_cmd_rsp_t *rlc_rsp; - /* Small DMA pool allocations -- maximum 256 bytes in length. */ #define DMA_POOL_SIZE 256 struct dma_pool *s_dma_pool; @@ -2505,8 +2410,6 @@ typedef struct scsi_qla_host { test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) || \ atomic_read(&ha->loop_state) == LOOP_DOWN) -#define TGT_Q(ha, t) (ha->otgt[t]) - #define to_qla_host(x) ((scsi_qla_host_t *) (x)->hostdata) #define qla_printk(level, ha, format, arg...) \ @@ -2539,19 +2442,6 @@ typedef struct scsi_qla_host { #define QLA_RSCNS_HANDLED 0x108 #define QLA_ALREADY_REGISTERED 0x109 -/* -* Stat info for all adpaters -*/ -struct _qla2x00stats { - unsigned long mboxtout; /* mailbox timeouts */ - unsigned long mboxerr; /* mailbox errors */ - unsigned long ispAbort; /* ISP aborts */ - unsigned long debugNo; - unsigned long loop_resync; - unsigned long outarray_full; - unsigned long retry_q_cnt; -}; - #define NVRAM_DELAY() udelay(10) #define INVALID_HANDLE (MAX_OUTSTANDING_COMMANDS+1) @@ -2567,12 +2457,6 @@ struct _qla2x00stats { #include "qla_dbg.h" #include "qla_inline.h" -/* -* String arrays -*/ -#define LINESIZE 256 -#define MAXARGS 26 - #define CMD_SP(Cmnd) ((Cmnd)->SCp.ptr) #define CMD_COMPL_STATUS(Cmnd) ((Cmnd)->SCp.this_residual) #define CMD_RESID_LEN(Cmnd) ((Cmnd)->SCp.buffers_residual) diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 91e83e2c1eb..26d1181b338 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -70,8 +70,6 @@ extern void qla2x00_sp_compl(scsi_qla_host_t *, srb_t *); extern char *qla2x00_get_fw_version_str(struct scsi_qla_host *, char *); -extern void qla2x00_cmd_timeout(srb_t *); - extern void qla2x00_mark_device_lost(scsi_qla_host_t *, fc_port_t *, int, int); extern void qla2x00_mark_all_devices_lost(scsi_qla_host_t *, int); diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index b1b20f43d72..7e18b9c1265 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -194,7 +194,6 @@ qla2100_pci_config(scsi_qla_host_t *ha) mwi = 0; if (pci_set_mwi(ha->pdev)) mwi = PCI_COMMAND_INVALIDATE; - pci_read_config_word(ha->pdev, PCI_REVISION_ID, &ha->revision); pci_read_config_word(ha->pdev, PCI_COMMAND, &w); w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); @@ -232,7 +231,6 @@ qla2300_pci_config(scsi_qla_host_t *ha) mwi = 0; if (pci_set_mwi(ha->pdev)) mwi = PCI_COMMAND_INVALIDATE; - pci_read_config_word(ha->pdev, PCI_REVISION_ID, &ha->revision); pci_read_config_word(ha->pdev, PCI_COMMAND, &w); w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); @@ -320,7 +318,6 @@ qla24xx_pci_config(scsi_qla_host_t *ha) mwi = 0; if (pci_set_mwi(ha->pdev)) mwi = PCI_COMMAND_INVALIDATE; - pci_read_config_word(ha->pdev, PCI_REVISION_ID, &ha->revision); pci_read_config_word(ha->pdev, PCI_COMMAND, &w); w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); @@ -1674,14 +1671,6 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) return (rval); } -static void -qla2x00_rport_add(void *data) -{ - fc_port_t *fcport = data; - - qla2x00_reg_remote_port(fcport->ha, fcport); -} - static void qla2x00_rport_del(void *data) { @@ -1724,8 +1713,6 @@ qla2x00_alloc_fcport(scsi_qla_host_t *ha, gfp_t flags) fcport->flags = FCF_RLC_SUPPORT; fcport->supported_classes = FC_COS_UNSPECIFIED; spin_lock_init(&fcport->rport_lock); - INIT_WORK(&fcport->rport_add_work, qla2x00_rport_add, fcport); - INIT_WORK(&fcport->rport_del_work, qla2x00_rport_del, fcport); return (fcport); } @@ -2048,10 +2035,6 @@ qla2x00_update_fcport(scsi_qla_host_t *ha, fc_port_t *fcport) PORT_RETRY_TIME); fcport->flags &= ~FCF_LOGIN_NEEDED; - if (fcport->port_type == FCT_INITIATOR || - fcport->port_type == FCT_BROADCAST) - fcport->device_type = TYPE_PROCESSOR; - atomic_set(&fcport->state, FCS_ONLINE); if (ha->flags.init_done) diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 8f0f4a29835..8c769cfaa14 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -408,7 +408,6 @@ qla2x00_start_scsi(srb_t *sp) ha->request_ring_ptr++; sp->flags |= SRB_DMA_VALID; - sp->state = SRB_ACTIVE_STATE; /* Set chip new ring index. */ WRT_REG_WORD(ISP_REQ_Q_IN(ha, reg), ha->req_ring_index); @@ -838,7 +837,6 @@ qla24xx_start_scsi(srb_t *sp) ha->request_ring_ptr++; sp->flags |= SRB_DMA_VALID; - sp->state = SRB_ACTIVE_STATE; /* Set chip new ring index. */ WRT_REG_DWORD(®->req_q_in, ha->req_ring_index); diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 40325ec7005..39b5082eb3b 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -844,8 +844,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) cp = sp->cmd; if (cp == NULL) { DEBUG2(printk("scsi(%ld): Command already returned back to OS " - "pkt->handle=%d sp=%p sp->state:%d\n", - ha->host_no, sts->handle, sp, sp->state)); + "pkt->handle=%d sp=%p.\n", ha->host_no, sts->handle, sp)); qla_printk(KERN_WARNING, ha, "Command is NULL: already returned to OS (sp=%p)\n", sp); @@ -1189,7 +1188,7 @@ qla2x00_status_cont_entry(scsi_qla_host_t *ha, sts_cont_entry_t *pkt) cp = sp->cmd; if (cp == NULL) { DEBUG2(printk("%s(): Cmd already returned back to OS " - "sp=%p sp->state:%d\n", __func__, sp, sp->state)); + "sp=%p.\n", __func__, sp)); qla_printk(KERN_INFO, ha, "cmd is NULL: already returned to OS (sp=%p)\n", sp); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index fbf3b03aba6..77e67e1429e 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -340,7 +340,6 @@ qla2x00_get_new_sp(scsi_qla_host_t *ha, fc_port_t *fcport, if (!sp) return sp; - atomic_set(&sp->ref_count, 1); sp->ha = ha; sp->fcport = fcport; sp->cmd = cmd; @@ -634,9 +633,8 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) if (sp->cmd != cmd) continue; - DEBUG2(printk("%s(%ld): aborting sp %p from RISC. pid=%ld " - "sp->state=%x\n", __func__, ha->host_no, sp, serial, - sp->state)); + DEBUG2(printk("%s(%ld): aborting sp %p from RISC. pid=%ld.\n", + __func__, ha->host_no, sp, serial)); DEBUG3(qla2x00_print_scsi_cmd(cmd);) spin_unlock_irqrestore(&ha->hardware_lock, flags); @@ -1377,7 +1375,6 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) spin_lock_init(&ha->hardware_lock); ha->prev_topology = 0; - ha->ports = MAX_BUSES; ha->init_cb_size = sizeof(init_cb_t); ha->mgmt_svr_loop_id = MANAGEMENT_SERVER; ha->link_data_rate = LDR_UNKNOWN; @@ -1544,7 +1541,7 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) host->cmd_per_lun = 3; host->unique_id = ha->instance; host->max_cmd_len = MAX_CMDSZ; - host->max_channel = ha->ports - 1; + host->max_channel = MAX_BUSES - 1; host->max_lun = MAX_LUNS; host->transportt = qla2xxx_transport_template; @@ -1885,18 +1882,6 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha) continue; } - ha->rlc_rsp = dma_alloc_coherent(&ha->pdev->dev, - sizeof(rpt_lun_cmd_rsp_t), &ha->rlc_rsp_dma, GFP_KERNEL); - if (ha->rlc_rsp == NULL) { - qla_printk(KERN_WARNING, ha, - "Memory Allocation failed - rlc"); - - qla2x00_mem_free(ha); - msleep(100); - - continue; - } - snprintf(name, sizeof(name), "qla2xxx_%ld", ha->host_no); ha->s_dma_pool = dma_pool_create(name, &ha->pdev->dev, DMA_POOL_SIZE, 8, 0); @@ -2072,11 +2057,6 @@ qla2x00_mem_free(scsi_qla_host_t *ha) if (ha->s_dma_pool) dma_pool_destroy(ha->s_dma_pool); - if (ha->rlc_rsp) - dma_free_coherent(&ha->pdev->dev, - sizeof(rpt_lun_cmd_rsp_t), ha->rlc_rsp, - ha->rlc_rsp_dma); - if (ha->gid_list) dma_free_coherent(&ha->pdev->dev, GID_LIST_SIZE, ha->gid_list, ha->gid_list_dma); @@ -2104,8 +2084,6 @@ qla2x00_mem_free(scsi_qla_host_t *ha) ha->s_dma_pool = NULL; - ha->rlc_rsp = NULL; - ha->rlc_rsp_dma = 0; ha->gid_list = NULL; ha->gid_list_dma = 0; @@ -2149,8 +2127,6 @@ qla2x00_mem_free(scsi_qla_host_t *ha) * * Context: * Kernel context. - * - * Note: Sets the ref_count for non Null sp to one. */ static int qla2x00_allocate_sp_pool(scsi_qla_host_t *ha) diff --git a/drivers/scsi/qla2xxx/qla_rscn.c b/drivers/scsi/qla2xxx/qla_rscn.c index b70bebe18c0..33e287b4f17 100644 --- a/drivers/scsi/qla2xxx/qla_rscn.c +++ b/drivers/scsi/qla2xxx/qla_rscn.c @@ -318,7 +318,6 @@ qla2x00_update_login_fcport(scsi_qla_host_t *ha, struct mbx_entry *mbxstat, fcport->flags &= ~FCF_FAILOVER_NEEDED; fcport->iodesc_idx_sent = IODESC_INVALID_INDEX; atomic_set(&fcport->state, FCS_ONLINE); - schedule_work(&fcport->rport_add_work); } diff --git a/drivers/scsi/qla2xxx/qla_settings.h b/drivers/scsi/qla2xxx/qla_settings.h index 363205c0e84..249e4d90fdc 100644 --- a/drivers/scsi/qla2xxx/qla_settings.h +++ b/drivers/scsi/qla2xxx/qla_settings.h @@ -16,7 +16,6 @@ /* Max time to wait for the loop to be in LOOP_READY state */ #define MAX_LOOP_TIMEOUT (60 * 5) -#define EH_ACTIVE 1 /* Error handler active */ /* * Some vendor subsystems do not recover properly after a device reset. Define -- cgit v1.2.3 From 4971cd221ad3f1266b87aa0e996d082d91bac2a6 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Wed, 17 May 2006 15:09:27 -0700 Subject: [SCSI] qla2xxx: Remove unused port-type RSCN handling code. Expandind on the previous commit: commit 79f89a4296ff22f09baf538d4ff2a6d0c3097a73 Author: andrew.vasquez@qlogic.com Date: Fri Jan 13 17:05:58 2006 -0800 [SCSI] qla2xxx: Disable port-type RSCN handling via driver state-machine. and given: - the process-context requirements of the FC transport rport-APIs. - lack of port-type RSCN processing logic for ISP24xx and newer chips. it's time now to remove the state-machine logic from mainline. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/Makefile | 2 +- drivers/scsi/qla2xxx/qla_def.h | 37 - drivers/scsi/qla2xxx/qla_gbl.h | 10 - drivers/scsi/qla2xxx/qla_init.c | 17 - drivers/scsi/qla2xxx/qla_isr.c | 60 -- drivers/scsi/qla2xxx/qla_os.c | 31 - drivers/scsi/qla2xxx/qla_rscn.c | 1425 --------------------------------------- 7 files changed, 1 insertion(+), 1581 deletions(-) delete mode 100644 drivers/scsi/qla2xxx/qla_rscn.c diff --git a/drivers/scsi/qla2xxx/Makefile b/drivers/scsi/qla2xxx/Makefile index c8f670ee60b..6ff7bb0d8e2 100644 --- a/drivers/scsi/qla2xxx/Makefile +++ b/drivers/scsi/qla2xxx/Makefile @@ -1,7 +1,7 @@ EXTRA_CFLAGS += -DUNIQUE_FW_NAME qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \ - qla_dbg.o qla_sup.o qla_rscn.o qla_attr.o + qla_dbg.o qla_sup.o qla_attr.o obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx.o diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 4bd67e9c284..4c67494e9f7 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -1523,8 +1523,6 @@ typedef struct fc_port { unsigned int os_target_id; - uint16_t iodesc_idx_sent; - int port_login_retry_count; int login_retry; atomic_t port_down_timer; @@ -1940,34 +1938,6 @@ struct sns_cmd_pkt { } p; }; -/* IO descriptors */ -#define MAX_IO_DESCRIPTORS 32 - -#define ABORT_IOCB_CB 0 -#define ADISC_PORT_IOCB_CB 1 -#define LOGOUT_PORT_IOCB_CB 2 -#define LOGIN_PORT_IOCB_CB 3 -#define LAST_IOCB_CB 4 - -#define IODESC_INVALID_INDEX 0xFFFF -#define IODESC_ADISC_NEEDED 0xFFFE -#define IODESC_LOGIN_NEEDED 0xFFFD - -struct io_descriptor { - uint16_t used:1; - uint16_t idx:11; - uint16_t cb_idx:4; - - struct timer_list timer; - - struct scsi_qla_host *ha; - - port_id_t d_id; - fc_port_t *remote_fcport; - - uint32_t signature; -}; - struct qla_fw_info { unsigned short addressing; /* addressing method used to load fw */ #define FW_INFO_ADDR_NORMAL 0 @@ -2271,10 +2241,6 @@ typedef struct scsi_qla_host { /* Fibre Channel Device List. */ struct list_head fcports; - struct list_head rscn_fcports; - - struct io_descriptor io_descriptors[MAX_IO_DESCRIPTORS]; - uint16_t iodesc_signature; /* RSCN queue. */ uint32_t rscn_queue[MAX_RSCN_COUNT]; @@ -2313,9 +2279,6 @@ typedef struct scsi_qla_host { init_cb_t *init_cb; int init_cb_size; - dma_addr_t iodesc_pd_dma; - port_database_t *iodesc_pd; - /* These are used by mailbox operations. */ volatile uint16_t mailbox_out[MAILBOX_REGISTER_COUNT]; diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 26d1181b338..02922299871 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -64,7 +64,6 @@ extern int qlport_down_retry; extern int ql2xplogiabsentdevice; extern int ql2xloginretrycount; extern int ql2xfdmienable; -extern int ql2xprocessrscn; extern void qla2x00_sp_compl(scsi_qla_host_t *, srb_t *); @@ -283,15 +282,6 @@ extern void *qla2x00_prep_ms_fdmi_iocb(scsi_qla_host_t *, uint32_t, uint32_t); extern void *qla24xx_prep_ms_fdmi_iocb(scsi_qla_host_t *, uint32_t, uint32_t); extern int qla2x00_fdmi_register(scsi_qla_host_t *); -/* - * Global Function Prototypes in qla_rscn.c source file. - */ -extern fc_port_t *qla2x00_alloc_rscn_fcport(scsi_qla_host_t *, gfp_t); -extern int qla2x00_handle_port_rscn(scsi_qla_host_t *, uint32_t, fc_port_t *, - int); -extern void qla2x00_process_iodesc(scsi_qla_host_t *, struct mbx_entry *); -extern void qla2x00_cancel_io_descriptors(scsi_qla_host_t *); - /* * Global Function Prototypes in qla_xioctl.c source file. */ diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 7e18b9c1265..7b48c655b76 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1708,7 +1708,6 @@ qla2x00_alloc_fcport(scsi_qla_host_t *ha, gfp_t flags) fcport->ha = ha; fcport->port_type = FCT_UNKNOWN; fcport->loop_id = FC_NO_LOOP_ID; - fcport->iodesc_idx_sent = IODESC_INVALID_INDEX; atomic_set(&fcport->state, FCS_UNCONFIGURED); fcport->flags = FCF_RLC_SUPPORT; fcport->supported_classes = FC_COS_UNSPECIFIED; @@ -2563,7 +2562,6 @@ static int qla2x00_device_resync(scsi_qla_host_t *ha) { int rval; - int rval2; uint32_t mask; fc_port_t *fcport; uint32_t rscn_entry; @@ -2619,17 +2617,6 @@ qla2x00_device_resync(scsi_qla_host_t *ha) switch (format) { case 0: - if (ql2xprocessrscn && - !IS_QLA2100(ha) && !IS_QLA2200(ha) && - !IS_QLA6312(ha) && !IS_QLA6322(ha) && - !IS_QLA24XX(ha) && !IS_QLA54XX(ha) && - ha->flags.init_done) { - /* Handle port RSCN via asyncronous IOCBs */ - rval2 = qla2x00_handle_port_rscn(ha, rscn_entry, - NULL, 0); - if (rval2 == QLA_SUCCESS) - continue; - } mask = 0xffffff; break; case 1: @@ -2647,10 +2634,6 @@ qla2x00_device_resync(scsi_qla_host_t *ha) rval = QLA_SUCCESS; - /* Abort any outstanding IO descriptors. */ - if (!IS_QLA2100(ha) && !IS_QLA2200(ha)) - qla2x00_cancel_io_descriptors(ha); - list_for_each_entry(fcport, &ha->fcports, list) { if ((fcport->flags & FCF_FABRIC_DEVICE) == 0 || (fcport->d_id.b24 & mask) != d_id.b24 || diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 39b5082eb3b..b28ac0a27e2 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -514,47 +514,6 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) break; case MBA_PORT_UPDATE: /* Port database update */ - /* - * If a single remote port just logged into (or logged out of) - * us, create a new entry in our rscn fcports list and handle - * the event like an RSCN. - */ - if (ql2xprocessrscn && - !IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA6312(ha) && - !IS_QLA6322(ha) && !IS_QLA24XX(ha) && !IS_QLA54XX(ha) && - ha->flags.init_done && mb[1] != 0xffff && - ((ha->operating_mode == P2P && mb[1] != 0) || - (ha->operating_mode != P2P && mb[1] != - SNS_FIRST_LOOP_ID)) && (mb[2] == 6 || mb[2] == 7)) { - int rval; - fc_port_t *rscn_fcport; - - /* Create new fcport for login. */ - rscn_fcport = qla2x00_alloc_rscn_fcport(ha, GFP_ATOMIC); - if (rscn_fcport) { - DEBUG14(printk("scsi(%ld): Port Update -- " - "creating RSCN fcport %p for %x/%x/%x.\n", - ha->host_no, rscn_fcport, mb[1], mb[2], - mb[3])); - - rscn_fcport->loop_id = mb[1]; - rscn_fcport->d_id.b24 = INVALID_PORT_ID; - atomic_set(&rscn_fcport->state, - FCS_DEVICE_LOST); - list_add_tail(&rscn_fcport->list, - &ha->rscn_fcports); - - rval = qla2x00_handle_port_rscn(ha, 0, - rscn_fcport, 1); - if (rval == QLA_SUCCESS) - break; - } else { - DEBUG14(printk("scsi(%ld): Port Update -- " - "-- unable to allocate RSCN fcport " - "login.\n", ha->host_no)); - } - } - /* * If PORT UPDATE is global (recieved LIP_OCCURED/LIP_RESET * event etc. earlier indicating loop is down) then process @@ -753,25 +712,6 @@ qla2x00_process_response_queue(struct scsi_qla_host *ha) case MS_IOCB_TYPE: qla2x00_ms_entry(ha, (ms_iocb_entry_t *)pkt); break; - case MBX_IOCB_TYPE: - if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && - !IS_QLA6312(ha) && !IS_QLA6322(ha)) { - if (pkt->sys_define == SOURCE_ASYNC_IOCB) { - qla2x00_process_iodesc(ha, - (struct mbx_entry *)pkt); - } else { - /* MBX IOCB Type Not Supported. */ - DEBUG4(printk(KERN_WARNING - "scsi(%ld): Received unknown MBX " - "IOCB response pkt type=%x " - "source=%x entry status=%x.\n", - ha->host_no, pkt->entry_type, - pkt->sys_define, - pkt->entry_status)); - } - break; - } - /* Fallthrough. */ default: /* Type Not Supported. */ DEBUG4(printk(KERN_WARNING diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 77e67e1429e..22e8714a91f 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -71,12 +71,6 @@ MODULE_PARM_DESC(ql2xfdmienable, "Enables FDMI registratons " "Default is 0 - no FDMI. 1 - perfom FDMI."); -int ql2xprocessrscn; -module_param(ql2xprocessrscn, int, S_IRUGO|S_IRUSR); -MODULE_PARM_DESC(ql2xprocessrscn, - "Option to enable port RSCN handling via a series of less" - "fabric intrusive ADISCs and PLOGIs."); - /* * SCSI host template entry points */ @@ -1492,7 +1486,6 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) INIT_LIST_HEAD(&ha->list); INIT_LIST_HEAD(&ha->fcports); - INIT_LIST_HEAD(&ha->rscn_fcports); /* * These locks are used to prevent more than one CPU @@ -1669,10 +1662,6 @@ EXPORT_SYMBOL_GPL(qla2x00_remove_one); static void qla2x00_free_device(scsi_qla_host_t *ha) { - /* Abort any outstanding IO descriptors. */ - if (!IS_QLA2100(ha) && !IS_QLA2200(ha)) - qla2x00_cancel_io_descriptors(ha); - /* Disable timer */ if (ha->timer_active) qla2x00_stop_timer(ha); @@ -1909,21 +1898,6 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha) } memset(ha->init_cb, 0, ha->init_cb_size); - /* Get consistent memory allocated for Get Port Database cmd */ - ha->iodesc_pd = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, - &ha->iodesc_pd_dma); - if (ha->iodesc_pd == NULL) { - /* error */ - qla_printk(KERN_WARNING, ha, - "Memory Allocation failed - iodesc_pd\n"); - - qla2x00_mem_free(ha); - msleep(100); - - continue; - } - memset(ha->iodesc_pd, 0, PORT_DATABASE_SIZE); - /* Allocate ioctl related memory. */ if (qla2x00_alloc_ioctl_mem(ha)) { qla_printk(KERN_WARNING, ha, @@ -2048,9 +2022,6 @@ qla2x00_mem_free(scsi_qla_host_t *ha) if (ha->ms_iocb) dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma); - if (ha->iodesc_pd) - dma_pool_free(ha->s_dma_pool, ha->iodesc_pd, ha->iodesc_pd_dma); - if (ha->init_cb) dma_pool_free(ha->s_dma_pool, ha->init_cb, ha->init_cb_dma); @@ -2077,8 +2048,6 @@ qla2x00_mem_free(scsi_qla_host_t *ha) ha->ct_sns_dma = 0; ha->ms_iocb = NULL; ha->ms_iocb_dma = 0; - ha->iodesc_pd = NULL; - ha->iodesc_pd_dma = 0; ha->init_cb = NULL; ha->init_cb_dma = 0; diff --git a/drivers/scsi/qla2xxx/qla_rscn.c b/drivers/scsi/qla2xxx/qla_rscn.c deleted file mode 100644 index 33e287b4f17..00000000000 --- a/drivers/scsi/qla2xxx/qla_rscn.c +++ /dev/null @@ -1,1425 +0,0 @@ -/* - * QLogic Fibre Channel HBA Driver - * Copyright (c) 2003-2005 QLogic Corporation - * - * See LICENSE.qla2xxx for copyright and licensing details. - */ -#include "qla_def.h" - -/** - * IO descriptor handle definitions. - * - * Signature form: - * - * |31------28|27-------------------12|11-------0| - * | Type | Rolling Signature | Index | - * |----------|-----------------------|----------| - * - **/ - -#define HDL_TYPE_SCSI 0 -#define HDL_TYPE_ASYNC_IOCB 0x0A - -#define HDL_INDEX_BITS 12 -#define HDL_ITER_BITS 16 -#define HDL_TYPE_BITS 4 - -#define HDL_INDEX_MASK ((1UL << HDL_INDEX_BITS) - 1) -#define HDL_ITER_MASK ((1UL << HDL_ITER_BITS) - 1) -#define HDL_TYPE_MASK ((1UL << HDL_TYPE_BITS) - 1) - -#define HDL_INDEX_SHIFT 0 -#define HDL_ITER_SHIFT (HDL_INDEX_SHIFT + HDL_INDEX_BITS) -#define HDL_TYPE_SHIFT (HDL_ITER_SHIFT + HDL_ITER_BITS) - -/* Local Prototypes. */ -static inline uint32_t qla2x00_to_handle(uint16_t, uint16_t, uint16_t); -static inline uint16_t qla2x00_handle_to_idx(uint32_t); -static inline uint32_t qla2x00_iodesc_to_handle(struct io_descriptor *); -static inline struct io_descriptor *qla2x00_handle_to_iodesc(scsi_qla_host_t *, - uint32_t); - -static inline struct io_descriptor *qla2x00_alloc_iodesc(scsi_qla_host_t *); -static inline void qla2x00_free_iodesc(struct io_descriptor *); -static inline void qla2x00_init_io_descriptors(scsi_qla_host_t *); - -static void qla2x00_iodesc_timeout(unsigned long); -static inline void qla2x00_add_iodesc_timer(struct io_descriptor *); -static inline void qla2x00_remove_iodesc_timer(struct io_descriptor *); - -static inline void qla2x00_update_login_fcport(scsi_qla_host_t *, - struct mbx_entry *, fc_port_t *); - -static int qla2x00_send_abort_iocb(scsi_qla_host_t *, struct io_descriptor *, - uint32_t, int); -static int qla2x00_send_abort_iocb_cb(scsi_qla_host_t *, struct io_descriptor *, - struct mbx_entry *); - -static int qla2x00_send_adisc_iocb(scsi_qla_host_t *, struct io_descriptor *, - int); -static int qla2x00_send_adisc_iocb_cb(scsi_qla_host_t *, struct io_descriptor *, - struct mbx_entry *); - -static int qla2x00_send_logout_iocb(scsi_qla_host_t *, struct io_descriptor *, - int); -static int qla2x00_send_logout_iocb_cb(scsi_qla_host_t *, - struct io_descriptor *, struct mbx_entry *); - -static int qla2x00_send_login_iocb(scsi_qla_host_t *, struct io_descriptor *, - port_id_t *, int); -static int qla2x00_send_login_iocb_cb(scsi_qla_host_t *, struct io_descriptor *, - struct mbx_entry *); - -/** - * Mailbox IOCB callback array. - **/ -static int (*iocb_function_cb_list[LAST_IOCB_CB]) - (scsi_qla_host_t *, struct io_descriptor *, struct mbx_entry *) = { - - qla2x00_send_abort_iocb_cb, - qla2x00_send_adisc_iocb_cb, - qla2x00_send_logout_iocb_cb, - qla2x00_send_login_iocb_cb, -}; - - -/** - * Generic IO descriptor handle routines. - **/ - -/** - * qla2x00_to_handle() - Create a descriptor handle. - * @type: descriptor type - * @iter: descriptor rolling signature - * @idx: index to the descriptor array - * - * Returns a composite handle based in the @type, @iter, and @idx. - */ -static inline uint32_t -qla2x00_to_handle(uint16_t type, uint16_t iter, uint16_t idx) -{ - return ((uint32_t)(((uint32_t)type << HDL_TYPE_SHIFT) | - ((uint32_t)iter << HDL_ITER_SHIFT) | - ((uint32_t)idx << HDL_INDEX_SHIFT))); -} - -/** - * qla2x00_handle_to_idx() - Retrive the index for a given handle. - * @handle: descriptor handle - * - * Returns the index specified by the @handle. - */ -static inline uint16_t -qla2x00_handle_to_idx(uint32_t handle) -{ - return ((uint16_t)(((handle) >> HDL_INDEX_SHIFT) & HDL_INDEX_MASK)); -} - -/** - * qla2x00_iodesc_to_handle() - Convert an IO descriptor to a unique handle. - * @iodesc: io descriptor - * - * Returns a unique handle for @iodesc. - */ -static inline uint32_t -qla2x00_iodesc_to_handle(struct io_descriptor *iodesc) -{ - uint32_t handle; - - handle = qla2x00_to_handle(HDL_TYPE_ASYNC_IOCB, - ++iodesc->ha->iodesc_signature, iodesc->idx); - iodesc->signature = handle; - - return (handle); -} - -/** - * qla2x00_handle_to_iodesc() - Retrieve an IO descriptor given a unique handle. - * @ha: HA context - * @handle: handle to io descriptor - * - * Returns a pointer to the io descriptor, or NULL, if the io descriptor does - * not exist or the io descriptors signature does not @handle. - */ -static inline struct io_descriptor * -qla2x00_handle_to_iodesc(scsi_qla_host_t *ha, uint32_t handle) -{ - uint16_t idx; - struct io_descriptor *iodesc; - - idx = qla2x00_handle_to_idx(handle); - iodesc = &ha->io_descriptors[idx]; - if (iodesc) - if (iodesc->signature != handle) - iodesc = NULL; - - return (iodesc); -} - - -/** - * IO descriptor allocation routines. - **/ - -/** - * qla2x00_alloc_iodesc() - Allocate an IO descriptor from the pool. - * @ha: HA context - * - * Returns a pointer to the allocated io descriptor, or NULL, if none available. - */ -static inline struct io_descriptor * -qla2x00_alloc_iodesc(scsi_qla_host_t *ha) -{ - uint16_t iter; - struct io_descriptor *iodesc; - - iodesc = NULL; - for (iter = 0; iter < MAX_IO_DESCRIPTORS; iter++) { - if (ha->io_descriptors[iter].used) - continue; - - iodesc = &ha->io_descriptors[iter]; - iodesc->used = 1; - iodesc->idx = iter; - init_timer(&iodesc->timer); - iodesc->ha = ha; - iodesc->signature = qla2x00_iodesc_to_handle(iodesc); - break; - } - - return (iodesc); -} - -/** - * qla2x00_free_iodesc() - Free an IO descriptor. - * @iodesc: io descriptor - * - * NOTE: The io descriptors timer *must* be stopped before it can be free'd. - */ -static inline void -qla2x00_free_iodesc(struct io_descriptor *iodesc) -{ - iodesc->used = 0; - iodesc->signature = 0; -} - -/** - * qla2x00_remove_iodesc_timer() - Remove an active timer from an IO descriptor. - * @iodesc: io descriptor - */ -static inline void -qla2x00_remove_iodesc_timer(struct io_descriptor *iodesc) -{ - if (iodesc->timer.function != NULL) { - del_timer_sync(&iodesc->timer); - iodesc->timer.data = (unsigned long) NULL; - iodesc->timer.function = NULL; - } -} - -/** - * qla2x00_init_io_descriptors() - Initialize the pool of IO descriptors. - * @ha: HA context - */ -static inline void -qla2x00_init_io_descriptors(scsi_qla_host_t *ha) -{ - uint16_t iter; - - for (iter = 0; iter < MAX_IO_DESCRIPTORS; iter++) { - if (!ha->io_descriptors[iter].used) - continue; - - qla2x00_remove_iodesc_timer(&ha->io_descriptors[iter]); - qla2x00_free_iodesc(&ha->io_descriptors[iter]); - } -} - - -/** - * IO descriptor timer routines. - **/ - -/** - * qla2x00_iodesc_timeout() - Timeout IO descriptor handler. - * @data: io descriptor - */ -static void -qla2x00_iodesc_timeout(unsigned long data) -{ - struct io_descriptor *iodesc; - - iodesc = (struct io_descriptor *) data; - - DEBUG14(printk("scsi(%ld): IO descriptor timeout, index=%x " - "signature=%08x, scheduling ISP abort.\n", iodesc->ha->host_no, - iodesc->idx, iodesc->signature)); - - qla2x00_free_iodesc(iodesc); - - qla_printk(KERN_WARNING, iodesc->ha, - "IO descriptor timeout. Scheduling ISP abort.\n"); - set_bit(ISP_ABORT_NEEDED, &iodesc->ha->dpc_flags); -} - -/** - * qla2x00_add_iodesc_timer() - Add and start a timer for an IO descriptor. - * @iodesc: io descriptor - * - * NOTE: - * The firmware shall timeout an outstanding mailbox IOCB in 2 * R_A_TOV (in - * tenths of a second) after it hits the wire. But, if there are any request - * resource contraints (i.e. during heavy I/O), exchanges can be held off for - * at most R_A_TOV. Therefore, the driver will wait 4 * R_A_TOV before - * scheduling a recovery (big hammer). - */ -static inline void -qla2x00_add_iodesc_timer(struct io_descriptor *iodesc) -{ - unsigned long timeout; - - timeout = (iodesc->ha->r_a_tov * 4) / 10; - init_timer(&iodesc->timer); - iodesc->timer.data = (unsigned long) iodesc; - iodesc->timer.expires = jiffies + (timeout * HZ); - iodesc->timer.function = - (void (*) (unsigned long)) qla2x00_iodesc_timeout; - add_timer(&iodesc->timer); -} - -/** - * IO descriptor support routines. - **/ - -/** - * qla2x00_update_login_fcport() - Update fcport data after login processing. - * @ha: HA context - * @mbxstat: Mailbox command status IOCB - * @fcport: port to update - */ -static inline void -qla2x00_update_login_fcport(scsi_qla_host_t *ha, struct mbx_entry *mbxstat, - fc_port_t *fcport) -{ - if (le16_to_cpu(mbxstat->mb1) & BIT_0) { - fcport->port_type = FCT_INITIATOR; - } else { - fcport->port_type = FCT_TARGET; - if (le16_to_cpu(mbxstat->mb1) & BIT_1) { - fcport->flags |= FCF_TAPE_PRESENT; - } - } - fcport->login_retry = 0; - fcport->port_login_retry_count = ha->port_down_retry_count * - PORT_RETRY_TIME; - atomic_set(&fcport->port_down_timer, ha->port_down_retry_count * - PORT_RETRY_TIME); - fcport->flags |= FCF_FABRIC_DEVICE; - fcport->flags &= ~FCF_FAILOVER_NEEDED; - fcport->iodesc_idx_sent = IODESC_INVALID_INDEX; - atomic_set(&fcport->state, FCS_ONLINE); -} - - -/** - * Mailbox IOCB commands. - **/ - -/** - * qla2x00_get_mbx_iocb_entry() - Retrieve an IOCB from the request queue. - * @ha: HA context - * @handle: handle to io descriptor - * - * Returns a pointer to the reqest entry, or NULL, if none were available. - */ -static inline struct mbx_entry * -qla2x00_get_mbx_iocb_entry(scsi_qla_host_t *ha, uint32_t handle) -{ - uint16_t cnt; - struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; - struct mbx_entry *mbxentry; - - mbxentry = NULL; - - if (ha->req_q_cnt < 3) { - cnt = qla2x00_debounce_register(ISP_REQ_Q_OUT(ha, reg)); - if (ha->req_ring_index < cnt) - ha->req_q_cnt = cnt - ha->req_ring_index; - else - ha->req_q_cnt = ha->request_q_length - - (ha->req_ring_index - cnt); - } - if (ha->req_q_cnt >= 3) { - mbxentry = (struct mbx_entry *)ha->request_ring_ptr; - - memset(mbxentry, 0, sizeof(struct mbx_entry)); - mbxentry->entry_type = MBX_IOCB_TYPE; - mbxentry->entry_count = 1; - mbxentry->sys_define1 = SOURCE_ASYNC_IOCB; - mbxentry->handle = handle; - } - return (mbxentry); -} - -/** - * qla2x00_send_abort_iocb() - Issue an abort IOCB to the firmware. - * @ha: HA context - * @iodesc: io descriptor - * @handle_to_abort: firmware handle to abort - * @ha_locked: is function called with the hardware lock - * - * Returns QLA_SUCCESS if the IOCB was issued. - */ -static int -qla2x00_send_abort_iocb(scsi_qla_host_t *ha, struct io_descriptor *iodesc, - uint32_t handle_to_abort, int ha_locked) -{ - unsigned long flags = 0; - struct mbx_entry *mbxentry; - - /* Send marker if required. */ - if (qla2x00_issue_marker(ha, ha_locked) != QLA_SUCCESS) - return (QLA_FUNCTION_FAILED); - - if (!ha_locked) - spin_lock_irqsave(&ha->hardware_lock, flags); - - /* Build abort mailbox IOCB. */ - mbxentry = qla2x00_get_mbx_iocb_entry(ha, iodesc->signature); - if (mbxentry == NULL) { - if (!ha_locked) - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - return (QLA_FUNCTION_FAILED); - } - mbxentry->mb0 = __constant_cpu_to_le16(MBC_ABORT_COMMAND); - mbxentry->mb1 = mbxentry->loop_id.extended = - cpu_to_le16(iodesc->remote_fcport->loop_id); - mbxentry->mb2 = LSW(handle_to_abort); - mbxentry->mb3 = MSW(handle_to_abort); - wmb(); - - qla2x00_add_iodesc_timer(iodesc); - - /* Issue command to ISP. */ - qla2x00_isp_cmd(ha); - - if (!ha_locked) - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - DEBUG14(printk("scsi(%ld): Sending Abort IOCB (%08x) to [%x], aborting " - "%08x.\n", ha->host_no, iodesc->signature, - iodesc->remote_fcport->loop_id, handle_to_abort)); - - return (QLA_SUCCESS); -} - -/** - * qla2x00_send_abort_iocb_cb() - Abort IOCB callback. - * @ha: HA context - * @iodesc: io descriptor - * @mbxstat: mailbox status IOCB - * - * Returns QLA_SUCCESS if @iodesc can be freed by the caller, else, @iodesc - * will be used for a retry. - */ -static int -qla2x00_send_abort_iocb_cb(scsi_qla_host_t *ha, struct io_descriptor *iodesc, - struct mbx_entry *mbxstat) -{ - DEBUG14(printk("scsi(%ld): Abort IOCB -- sent to [%x/%02x%02x%02x], " - "status=%x mb0=%x.\n", ha->host_no, iodesc->remote_fcport->loop_id, - iodesc->d_id.b.domain, iodesc->d_id.b.area, iodesc->d_id.b.al_pa, - le16_to_cpu(mbxstat->status), le16_to_cpu(mbxstat->mb0))); - - return (QLA_SUCCESS); -} - - -/** - * qla2x00_send_adisc_iocb() - Issue a Get Port Database IOCB to the firmware. - * @ha: HA context - * @iodesc: io descriptor - * @ha_locked: is function called with the hardware lock - * - * Returns QLA_SUCCESS if the IOCB was issued. - */ -static int -qla2x00_send_adisc_iocb(scsi_qla_host_t *ha, struct io_descriptor *iodesc, - int ha_locked) -{ - unsigned long flags = 0; - struct mbx_entry *mbxentry; - - /* Send marker if required. */ - if (qla2x00_issue_marker(ha, ha_locked) != QLA_SUCCESS) - return (QLA_FUNCTION_FAILED); - - if (!ha_locked) - spin_lock_irqsave(&ha->hardware_lock, flags); - - /* Build Get Port Database IOCB. */ - mbxentry = qla2x00_get_mbx_iocb_entry(ha, iodesc->signature); - if (mbxentry == NULL) { - if (!ha_locked) - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - return (QLA_FUNCTION_FAILED); - } - mbxentry->mb0 = __constant_cpu_to_le16(MBC_GET_PORT_DATABASE); - mbxentry->mb1 = mbxentry->loop_id.extended = - cpu_to_le16(iodesc->remote_fcport->loop_id); - mbxentry->mb2 = cpu_to_le16(MSW(LSD(ha->iodesc_pd_dma))); - mbxentry->mb3 = cpu_to_le16(LSW(LSD(ha->iodesc_pd_dma))); - mbxentry->mb6 = cpu_to_le16(MSW(MSD(ha->iodesc_pd_dma))); - mbxentry->mb7 = cpu_to_le16(LSW(MSD(ha->iodesc_pd_dma))); - mbxentry->mb10 = __constant_cpu_to_le16(BIT_0); - wmb(); - - qla2x00_add_iodesc_timer(iodesc); - - /* Issue command to ISP. */ - qla2x00_isp_cmd(ha); - - if (!ha_locked) - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - DEBUG14(printk("scsi(%ld): Sending Adisc IOCB (%08x) to [%x].\n", - ha->host_no, iodesc->signature, iodesc->remote_fcport->loop_id)); - - return (QLA_SUCCESS); -} - -/** - * qla2x00_send_adisc_iocb_cb() - Get Port Database IOCB callback. - * @ha: HA context - * @iodesc: io descriptor - * @mbxstat: mailbox status IOCB - * - * Returns QLA_SUCCESS if @iodesc can be freed by the caller, else, @iodesc - * will be used for a retry. - */ -static int -qla2x00_send_adisc_iocb_cb(scsi_qla_host_t *ha, struct io_descriptor *iodesc, - struct mbx_entry *mbxstat) -{ - fc_port_t *remote_fcport; - - remote_fcport = iodesc->remote_fcport; - - /* Ensure the port IDs are consistent. */ - if (remote_fcport->d_id.b24 != iodesc->d_id.b24) { - DEBUG14(printk("scsi(%ld): Adisc IOCB -- ignoring, remote port " - "id changed from [%02x%02x%02x] to [%02x%02x%02x].\n", - ha->host_no, remote_fcport->d_id.b.domain, - remote_fcport->d_id.b.area, remote_fcport->d_id.b.al_pa, - iodesc->d_id.b.domain, iodesc->d_id.b.area, - iodesc->d_id.b.al_pa)); - - return (QLA_SUCCESS); - } - - /* Only process the last command. */ - if (remote_fcport->iodesc_idx_sent != iodesc->idx) { - DEBUG14(printk("scsi(%ld): Adisc IOCB -- ignoring, sent to " - "[%02x%02x%02x], expected %x, received %x.\n", ha->host_no, - iodesc->d_id.b.domain, iodesc->d_id.b.area, - iodesc->d_id.b.al_pa, remote_fcport->iodesc_idx_sent, - iodesc->idx)); - - return (QLA_SUCCESS); - } - - if (le16_to_cpu(mbxstat->status) == CS_COMPLETE) { - DEBUG14(printk("scsi(%ld): Adisc IOCB -- marking " - "[%x/%02x%02x%02x] online.\n", ha->host_no, - remote_fcport->loop_id, remote_fcport->d_id.b.domain, - remote_fcport->d_id.b.area, remote_fcport->d_id.b.al_pa)); - - atomic_set(&remote_fcport->state, FCS_ONLINE); - } else { - DEBUG14(printk("scsi(%ld): Adisc IOCB -- marking " - "[%x/%02x%02x%02x] lost, status=%x mb0=%x.\n", ha->host_no, - remote_fcport->loop_id, remote_fcport->d_id.b.domain, - remote_fcport->d_id.b.area, remote_fcport->d_id.b.al_pa, - le16_to_cpu(mbxstat->status), le16_to_cpu(mbxstat->mb0))); - - if (atomic_read(&remote_fcport->state) != FCS_DEVICE_DEAD) - atomic_set(&remote_fcport->state, FCS_DEVICE_LOST); - } - remote_fcport->iodesc_idx_sent = IODESC_INVALID_INDEX; - - return (QLA_SUCCESS); -} - - -/** - * qla2x00_send_logout_iocb() - Issue a fabric port logout IOCB to the firmware. - * @ha: HA context - * @iodesc: io descriptor - * @ha_locked: is function called with the hardware lock - * - * Returns QLA_SUCCESS if the IOCB was issued. - */ -static int -qla2x00_send_logout_iocb(scsi_qla_host_t *ha, struct io_descriptor *iodesc, - int ha_locked) -{ - unsigned long flags = 0; - struct mbx_entry *mbxentry; - - /* Send marker if required. */ - if (qla2x00_issue_marker(ha, ha_locked) != QLA_SUCCESS) - return (QLA_FUNCTION_FAILED); - - if (!ha_locked) - spin_lock_irqsave(&ha->hardware_lock, flags); - - /* Build fabric port logout mailbox IOCB. */ - mbxentry = qla2x00_get_mbx_iocb_entry(ha, iodesc->signature); - if (mbxentry == NULL) { - if (!ha_locked) - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - return (QLA_FUNCTION_FAILED); - } - mbxentry->mb0 = __constant_cpu_to_le16(MBC_LOGOUT_FABRIC_PORT); - mbxentry->mb1 = mbxentry->loop_id.extended = - cpu_to_le16(iodesc->remote_fcport->loop_id); - wmb(); - - qla2x00_add_iodesc_timer(iodesc); - - /* Issue command to ISP. */ - qla2x00_isp_cmd(ha); - - if (!ha_locked) - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - DEBUG14(printk("scsi(%ld): Sending Logout IOCB (%08x) to [%x].\n", - ha->host_no, iodesc->signature, iodesc->remote_fcport->loop_id)); - - return (QLA_SUCCESS); -} - -/** - * qla2x00_send_logout_iocb_cb() - Fabric port logout IOCB callback. - * @ha: HA context - * @iodesc: io descriptor - * @mbxstat: mailbox status IOCB - * - * Returns QLA_SUCCESS if @iodesc can be freed by the caller, else, @iodesc - * will be used for a retry. - */ -static int -qla2x00_send_logout_iocb_cb(scsi_qla_host_t *ha, struct io_descriptor *iodesc, - struct mbx_entry *mbxstat) -{ - DEBUG14(printk("scsi(%ld): Logout IOCB -- sent to [%x/%02x%02x%02x], " - "status=%x mb0=%x mb1=%x.\n", ha->host_no, - iodesc->remote_fcport->loop_id, - iodesc->remote_fcport->d_id.b.domain, - iodesc->remote_fcport->d_id.b.area, - iodesc->remote_fcport->d_id.b.al_pa, le16_to_cpu(mbxstat->status), - le16_to_cpu(mbxstat->mb0), le16_to_cpu(mbxstat->mb1))); - - return (QLA_SUCCESS); -} - - -/** - * qla2x00_send_login_iocb() - Issue a fabric port login IOCB to the firmware. - * @ha: HA context - * @iodesc: io descriptor - * @d_id: port id for device - * @ha_locked: is function called with the hardware lock - * - * Returns QLA_SUCCESS if the IOCB was issued. - */ -static int -qla2x00_send_login_iocb(scsi_qla_host_t *ha, struct io_descriptor *iodesc, - port_id_t *d_id, int ha_locked) -{ - unsigned long flags = 0; - struct mbx_entry *mbxentry; - - /* Send marker if required. */ - if (qla2x00_issue_marker(ha, ha_locked) != QLA_SUCCESS) - return (QLA_FUNCTION_FAILED); - - if (!ha_locked) - spin_lock_irqsave(&ha->hardware_lock, flags); - - /* Build fabric port login mailbox IOCB. */ - mbxentry = qla2x00_get_mbx_iocb_entry(ha, iodesc->signature); - if (mbxentry == NULL) { - if (!ha_locked) - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - return (QLA_FUNCTION_FAILED); - } - mbxentry->mb0 = __constant_cpu_to_le16(MBC_LOGIN_FABRIC_PORT); - mbxentry->mb1 = mbxentry->loop_id.extended = - cpu_to_le16(iodesc->remote_fcport->loop_id); - mbxentry->mb2 = cpu_to_le16(d_id->b.domain); - mbxentry->mb3 = cpu_to_le16(d_id->b.area << 8 | d_id->b.al_pa); - mbxentry->mb10 = __constant_cpu_to_le16(BIT_0); - wmb(); - - qla2x00_add_iodesc_timer(iodesc); - - /* Issue command to ISP. */ - qla2x00_isp_cmd(ha); - - if (!ha_locked) - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - DEBUG14(printk("scsi(%ld): Sending Login IOCB (%08x) to " - "[%x/%02x%02x%02x].\n", ha->host_no, iodesc->signature, - iodesc->remote_fcport->loop_id, d_id->b.domain, d_id->b.area, - d_id->b.al_pa)); - - return (QLA_SUCCESS); -} - -/** - * qla2x00_send_login_iocb_cb() - Fabric port logout IOCB callback. - * @ha: HA context - * @iodesc: io descriptor - * @mbxstat: mailbox status IOCB - * - * Returns QLA_SUCCESS if @iodesc can be freed by the caller, else, @iodesc - * will be used for a retry. - */ -static int -qla2x00_send_login_iocb_cb(scsi_qla_host_t *ha, struct io_descriptor *iodesc, - struct mbx_entry *mbxstat) -{ - int rval; - fc_port_t *fcport, *remote_fcport, *exist_fcport; - struct io_descriptor *abort_iodesc, *login_iodesc; - uint16_t status, mb[8]; - uint16_t reuse; - uint16_t remote_loopid; - port_id_t remote_did, inuse_did; - - remote_fcport = iodesc->remote_fcport; - - /* Only process the last command. */ - if (remote_fcport->iodesc_idx_sent != iodesc->idx) { - DEBUG14(printk("scsi(%ld): Login IOCB -- ignoring, sent to " - "[%02x%02x%02x], expected %x, received %x.\n", - ha->host_no, iodesc->d_id.b.domain, iodesc->d_id.b.area, - iodesc->d_id.b.al_pa, remote_fcport->iodesc_idx_sent, - iodesc->idx)); - - /* Free RSCN fcport resources. */ - if (remote_fcport->port_type == FCT_RSCN) { - DEBUG14(printk("scsi(%ld): Login IOCB -- Freeing RSCN " - "fcport %p [%x/%02x%02x%02x] given ignored Login " - "IOCB.\n", ha->host_no, remote_fcport, - remote_fcport->loop_id, - remote_fcport->d_id.b.domain, - remote_fcport->d_id.b.area, - remote_fcport->d_id.b.al_pa)); - - list_del(&remote_fcport->list); - kfree(remote_fcport); - } - return (QLA_SUCCESS); - } - - status = le16_to_cpu(mbxstat->status); - mb[0] = le16_to_cpu(mbxstat->mb0); - mb[1] = le16_to_cpu(mbxstat->mb1); - mb[2] = le16_to_cpu(mbxstat->mb2); - mb[6] = le16_to_cpu(mbxstat->mb6); - mb[7] = le16_to_cpu(mbxstat->mb7); - - /* Good status? */ - if ((status == CS_COMPLETE || status == CS_COMPLETE_CHKCOND) && - mb[0] == MBS_COMMAND_COMPLETE) { - - DEBUG14(printk("scsi(%ld): Login IOCB -- status=%x mb1=%x pn=" - "%02x%02x%02x%02x%02x%02x%02x%02x.\n", ha->host_no, status, - mb[1], mbxstat->port_name[0], mbxstat->port_name[1], - mbxstat->port_name[2], mbxstat->port_name[3], - mbxstat->port_name[4], mbxstat->port_name[5], - mbxstat->port_name[6], mbxstat->port_name[7])); - - memcpy(remote_fcport->node_name, mbxstat->node_name, WWN_SIZE); - memcpy(remote_fcport->port_name, mbxstat->port_name, WWN_SIZE); - - /* Is the device already in our fcports list? */ - if (remote_fcport->port_type != FCT_RSCN) { - DEBUG14(printk("scsi(%ld): Login IOCB -- marking " - "[%x/%02x%02x%02x] online.\n", ha->host_no, - remote_fcport->loop_id, - remote_fcport->d_id.b.domain, - remote_fcport->d_id.b.area, - remote_fcport->d_id.b.al_pa)); - - qla2x00_update_login_fcport(ha, mbxstat, remote_fcport); - - return (QLA_SUCCESS); - } - - /* Does the RSCN portname already exist in our fcports list? */ - exist_fcport = NULL; - list_for_each_entry(fcport, &ha->fcports, list) { - if (memcmp(remote_fcport->port_name, fcport->port_name, - WWN_SIZE) == 0) { - exist_fcport = fcport; - break; - } - } - if (exist_fcport != NULL) { - DEBUG14(printk("scsi(%ld): Login IOCB -- found RSCN " - "fcport in fcports list [%p].\n", ha->host_no, - exist_fcport)); - - /* Abort any ADISC that could have been sent. */ - if (exist_fcport->iodesc_idx_sent != iodesc->idx && - exist_fcport->iodesc_idx_sent < - MAX_IO_DESCRIPTORS && - ha->io_descriptors[exist_fcport->iodesc_idx_sent]. - cb_idx == ADISC_PORT_IOCB_CB) { - - abort_iodesc = qla2x00_alloc_iodesc(ha); - if (abort_iodesc) { - DEBUG14(printk("scsi(%ld): Login IOCB " - "-- issuing abort to outstanding " - "Adisc [%x/%02x%02x%02x].\n", - ha->host_no, remote_fcport->loop_id, - exist_fcport->d_id.b.domain, - exist_fcport->d_id.b.area, - exist_fcport->d_id.b.al_pa)); - - abort_iodesc->cb_idx = ABORT_IOCB_CB; - abort_iodesc->d_id.b24 = - exist_fcport->d_id.b24; - abort_iodesc->remote_fcport = - exist_fcport; - exist_fcport->iodesc_idx_sent = - abort_iodesc->idx; - qla2x00_send_abort_iocb(ha, - abort_iodesc, ha->io_descriptors[ - exist_fcport->iodesc_idx_sent]. - signature, 1); - } else { - DEBUG14(printk("scsi(%ld): Login IOCB " - "-- unable to abort outstanding " - "Adisc [%x/%02x%02x%02x].\n", - ha->host_no, remote_fcport->loop_id, - exist_fcport->d_id.b.domain, - exist_fcport->d_id.b.area, - exist_fcport->d_id.b.al_pa)); - } - } - - /* - * If the existing fcport is waiting to send an ADISC - * or LOGIN, then reuse remote fcport (RSCN) to - * continue waiting. - */ - reuse = 0; - remote_loopid = remote_fcport->loop_id; - remote_did.b24 = remote_fcport->d_id.b24; - if (exist_fcport->iodesc_idx_sent == - IODESC_ADISC_NEEDED || - exist_fcport->iodesc_idx_sent == - IODESC_LOGIN_NEEDED) { - DEBUG14(printk("scsi(%ld): Login IOCB -- " - "existing fcport [%x/%02x%02x%02x] " - "waiting for IO descriptor, reuse RSCN " - "fcport.\n", ha->host_no, - exist_fcport->loop_id, - exist_fcport->d_id.b.domain, - exist_fcport->d_id.b.area, - exist_fcport->d_id.b.al_pa)); - - reuse++; - remote_fcport->iodesc_idx_sent = - exist_fcport->iodesc_idx_sent; - exist_fcport->iodesc_idx_sent = - IODESC_INVALID_INDEX; - remote_fcport->loop_id = exist_fcport->loop_id; - remote_fcport->d_id.b24 = - exist_fcport->d_id.b24; - } - - /* Logout the old loopid. */ - if (!reuse && - exist_fcport->loop_id != remote_fcport->loop_id && - exist_fcport->loop_id != FC_NO_LOOP_ID) { - login_iodesc = qla2x00_alloc_iodesc(ha); - if (login_iodesc) { - DEBUG14(printk("scsi(%ld): Login IOCB " - "-- issuing logout to free old " - "loop id [%x/%02x%02x%02x].\n", - ha->host_no, exist_fcport->loop_id, - exist_fcport->d_id.b.domain, - exist_fcport->d_id.b.area, - exist_fcport->d_id.b.al_pa)); - - login_iodesc->cb_idx = - LOGOUT_PORT_IOCB_CB; - login_iodesc->d_id.b24 = - exist_fcport->d_id.b24; - login_iodesc->remote_fcport = - exist_fcport; - exist_fcport->iodesc_idx_sent = - login_iodesc->idx; - qla2x00_send_logout_iocb(ha, - login_iodesc, 1); - } else { - /* Ran out of IO descriptiors. */ - DEBUG14(printk("scsi(%ld): Login IOCB " - "-- unable to logout to free old " - "loop id [%x/%02x%02x%02x].\n", - ha->host_no, exist_fcport->loop_id, - exist_fcport->d_id.b.domain, - exist_fcport->d_id.b.area, - exist_fcport->d_id.b.al_pa)); - - exist_fcport->iodesc_idx_sent = - IODESC_INVALID_INDEX; - } - - } - - /* Update existing fcport with remote fcport info. */ - DEBUG14(printk("scsi(%ld): Login IOCB -- marking " - "existing fcport [%x/%02x%02x%02x] online.\n", - ha->host_no, remote_loopid, remote_did.b.domain, - remote_did.b.area, remote_did.b.al_pa)); - - memcpy(exist_fcport->node_name, - remote_fcport->node_name, WWN_SIZE); - exist_fcport->loop_id = remote_loopid; - exist_fcport->d_id.b24 = remote_did.b24; - qla2x00_update_login_fcport(ha, mbxstat, exist_fcport); - - /* Finally, free the remote (RSCN) fcport. */ - if (!reuse) { - DEBUG14(printk("scsi(%ld): Login IOCB -- " - "Freeing RSCN fcport %p " - "[%x/%02x%02x%02x].\n", ha->host_no, - remote_fcport, remote_fcport->loop_id, - remote_fcport->d_id.b.domain, - remote_fcport->d_id.b.area, - remote_fcport->d_id.b.al_pa)); - - list_del(&remote_fcport->list); - kfree(remote_fcport); - } - - return (QLA_SUCCESS); - } - - /* - * A new device has been added, move the RSCN fcport to our - * fcports list. - */ - DEBUG14(printk("scsi(%ld): Login IOCB -- adding RSCN fcport " - "[%x/%02x%02x%02x] to fcports list.\n", ha->host_no, - remote_fcport->loop_id, remote_fcport->d_id.b.domain, - remote_fcport->d_id.b.area, remote_fcport->d_id.b.al_pa)); - - list_del(&remote_fcport->list); - remote_fcport->flags = (FCF_RLC_SUPPORT | FCF_RESCAN_NEEDED); - qla2x00_update_login_fcport(ha, mbxstat, remote_fcport); - list_add_tail(&remote_fcport->list, &ha->fcports); - set_bit(FCPORT_RESCAN_NEEDED, &ha->dpc_flags); - } else { - /* Handle login failure. */ - if (remote_fcport->login_retry != 0) { - if (mb[0] == MBS_LOOP_ID_USED) { - inuse_did.b.domain = LSB(mb[1]); - inuse_did.b.area = MSB(mb[2]); - inuse_did.b.al_pa = LSB(mb[2]); - - DEBUG14(printk("scsi(%ld): Login IOCB -- loop " - "id [%x] used by port id [%02x%02x%02x].\n", - ha->host_no, remote_fcport->loop_id, - inuse_did.b.domain, inuse_did.b.area, - inuse_did.b.al_pa)); - - if (remote_fcport->d_id.b24 == - INVALID_PORT_ID) { - /* - * Invalid port id means we are trying - * to login to a remote port with just - * a loop id without knowing about the - * port id. Copy the port id and try - * again. - */ - remote_fcport->d_id.b24 = inuse_did.b24; - iodesc->d_id.b24 = inuse_did.b24; - } else { - remote_fcport->loop_id++; - rval = qla2x00_find_new_loop_id(ha, - remote_fcport); - if (rval == QLA_FUNCTION_FAILED) { - /* No more loop ids. */ - return (QLA_SUCCESS); - } - } - } else if (mb[0] == MBS_PORT_ID_USED) { - /* - * Device has another loop ID. The firmware - * group recommends the driver perform an - * implicit login with the specified ID. - */ - DEBUG14(printk("scsi(%ld): Login IOCB -- port " - "id [%02x%02x%02x] already assigned to " - "loop id [%x].\n", ha->host_no, - iodesc->d_id.b.domain, iodesc->d_id.b.area, - iodesc->d_id.b.al_pa, mb[1])); - - remote_fcport->loop_id = mb[1]; - - } else { - /* Unable to perform login, try again. */ - DEBUG14(printk("scsi(%ld): Login IOCB -- " - "failed login [%x/%02x%02x%02x], status=%x " - "mb0=%x mb1=%x mb2=%x mb6=%x mb7=%x.\n", - ha->host_no, remote_fcport->loop_id, - iodesc->d_id.b.domain, iodesc->d_id.b.area, - iodesc->d_id.b.al_pa, status, mb[0], mb[1], - mb[2], mb[6], mb[7])); - } - - /* Reissue Login with the same IO descriptor. */ - iodesc->signature = - qla2x00_iodesc_to_handle(iodesc); - iodesc->cb_idx = LOGIN_PORT_IOCB_CB; - iodesc->d_id.b24 = remote_fcport->d_id.b24; - remote_fcport->iodesc_idx_sent = iodesc->idx; - remote_fcport->login_retry--; - - DEBUG14(printk("scsi(%ld): Login IOCB -- retrying " - "login to [%x/%02x%02x%02x] (%d).\n", ha->host_no, - remote_fcport->loop_id, - remote_fcport->d_id.b.domain, - remote_fcport->d_id.b.area, - remote_fcport->d_id.b.al_pa, - remote_fcport->login_retry)); - - qla2x00_send_login_iocb(ha, iodesc, - &remote_fcport->d_id, 1); - - return (QLA_FUNCTION_FAILED); - } else { - /* No more logins, mark device dead. */ - DEBUG14(printk("scsi(%ld): Login IOCB -- failed " - "login [%x/%02x%02x%02x] after retries, status=%x " - "mb0=%x mb1=%x mb2=%x mb6=%x mb7=%x.\n", - ha->host_no, remote_fcport->loop_id, - iodesc->d_id.b.domain, iodesc->d_id.b.area, - iodesc->d_id.b.al_pa, status, mb[0], mb[1], - mb[2], mb[6], mb[7])); - - atomic_set(&remote_fcport->state, FCS_DEVICE_DEAD); - if (remote_fcport->port_type == FCT_RSCN) { - DEBUG14(printk("scsi(%ld): Login IOCB -- " - "Freeing dead RSCN fcport %p " - "[%x/%02x%02x%02x].\n", ha->host_no, - remote_fcport, remote_fcport->loop_id, - remote_fcport->d_id.b.domain, - remote_fcport->d_id.b.area, - remote_fcport->d_id.b.al_pa)); - - list_del(&remote_fcport->list); - kfree(remote_fcport); - } - } - } - - return (QLA_SUCCESS); -} - - -/** - * IO descriptor processing routines. - **/ - -/** - * qla2x00_alloc_rscn_fcport() - Allocate an RSCN type fcport. - * @ha: HA context - * @flags: allocation flags - * - * Returns a pointer to the allocated RSCN fcport, or NULL, if none available. - */ -fc_port_t * -qla2x00_alloc_rscn_fcport(scsi_qla_host_t *ha, gfp_t flags) -{ - fc_port_t *fcport; - - fcport = qla2x00_alloc_fcport(ha, flags); - if (fcport == NULL) - return (fcport); - - /* Setup RSCN fcport structure. */ - fcport->port_type = FCT_RSCN; - - return (fcport); -} - -/** - * qla2x00_handle_port_rscn() - Handle port RSCN. - * @ha: HA context - * @rscn_entry: RSCN entry - * @fcport: fcport entry to updated - * - * Returns QLA_SUCCESS if the port RSCN was handled. - */ -int -qla2x00_handle_port_rscn(scsi_qla_host_t *ha, uint32_t rscn_entry, - fc_port_t *known_fcport, int ha_locked) -{ - int rval; - port_id_t rscn_pid; - fc_port_t *fcport, *remote_fcport, *rscn_fcport; - struct io_descriptor *iodesc; - - remote_fcport = NULL; - rscn_fcport = NULL; - - /* Prepare port id based on incoming entries. */ - if (known_fcport) { - rscn_pid.b24 = known_fcport->d_id.b24; - remote_fcport = known_fcport; - - DEBUG14(printk("scsi(%ld): Handle RSCN -- process RSCN for " - "fcport [%02x%02x%02x].\n", ha->host_no, - remote_fcport->d_id.b.domain, remote_fcport->d_id.b.area, - remote_fcport->d_id.b.al_pa)); - } else { - rscn_pid.b.domain = LSB(MSW(rscn_entry)); - rscn_pid.b.area = MSB(LSW(rscn_entry)); - rscn_pid.b.al_pa = LSB(LSW(rscn_entry)); - - DEBUG14(printk("scsi(%ld): Handle RSCN -- process RSCN for " - "port id [%02x%02x%02x].\n", ha->host_no, - rscn_pid.b.domain, rscn_pid.b.area, rscn_pid.b.al_pa)); - - /* - * Search fcport lists for a known entry at the specified port - * ID. - */ - list_for_each_entry(fcport, &ha->fcports, list) { - if (rscn_pid.b24 == fcport->d_id.b24) { - remote_fcport = fcport; - break; - } - } - list_for_each_entry(fcport, &ha->rscn_fcports, list) { - if (rscn_pid.b24 == fcport->d_id.b24) { - rscn_fcport = fcport; - break; - } - } - if (remote_fcport == NULL) - remote_fcport = rscn_fcport; - } - - /* - * If the port is already in our fcport list and online, send an ADISC - * to see if it's still alive. Issue login if a new fcport or the known - * fcport is currently offline. - */ - if (remote_fcport) { - /* - * No need to send request if the remote fcport is currently - * waiting for an available io descriptor. - */ - if (known_fcport == NULL && - (remote_fcport->iodesc_idx_sent == IODESC_ADISC_NEEDED || - remote_fcport->iodesc_idx_sent == IODESC_LOGIN_NEEDED)) { - /* - * If previous waiting io descriptor is an ADISC, then - * the new RSCN may come from a new remote fcport being - * plugged into the same location. - */ - if (remote_fcport->port_type == FCT_RSCN) { - remote_fcport->iodesc_idx_sent = - IODESC_LOGIN_NEEDED; - } else if (remote_fcport->iodesc_idx_sent == - IODESC_ADISC_NEEDED) { - fc_port_t *new_fcport; - - remote_fcport->iodesc_idx_sent = - IODESC_INVALID_INDEX; - - /* Create new fcport for later login. */ - new_fcport = qla2x00_alloc_rscn_fcport(ha, - ha_locked ? GFP_ATOMIC: GFP_KERNEL); - if (new_fcport) { - DEBUG14(printk("scsi(%ld): Handle RSCN " - "-- creating RSCN fcport %p for " - "future login.\n", ha->host_no, - new_fcport)); - - new_fcport->d_id.b24 = - remote_fcport->d_id.b24; - new_fcport->iodesc_idx_sent = - IODESC_LOGIN_NEEDED; - - list_add_tail(&new_fcport->list, - &ha->rscn_fcports); - set_bit(IODESC_PROCESS_NEEDED, - &ha->dpc_flags); - } else { - DEBUG14(printk("scsi(%ld): Handle RSCN " - "-- unable to allocate RSCN fcport " - "for future login.\n", - ha->host_no)); - } - } - return (QLA_SUCCESS); - } - - /* Send ADISC if the fcport is online */ - if (atomic_read(&remote_fcport->state) == FCS_ONLINE || - remote_fcport->iodesc_idx_sent == IODESC_ADISC_NEEDED) { - - atomic_set(&remote_fcport->state, FCS_DEVICE_LOST); - - iodesc = qla2x00_alloc_iodesc(ha); - if (iodesc == NULL) { - /* Mark fcport for later adisc processing */ - DEBUG14(printk("scsi(%ld): Handle RSCN -- not " - "enough IO descriptors for Adisc, flag " - "for later processing.\n", ha->host_no)); - - remote_fcport->iodesc_idx_sent = - IODESC_ADISC_NEEDED; - set_bit(IODESC_PROCESS_NEEDED, &ha->dpc_flags); - - return (QLA_SUCCESS); - } - - iodesc->cb_idx = ADISC_PORT_IOCB_CB; - iodesc->d_id.b24 = rscn_pid.b24; - iodesc->remote_fcport = remote_fcport; - remote_fcport->iodesc_idx_sent = iodesc->idx; - qla2x00_send_adisc_iocb(ha, iodesc, ha_locked); - - return (QLA_SUCCESS); - } else if (remote_fcport->iodesc_idx_sent < - MAX_IO_DESCRIPTORS && - ha->io_descriptors[remote_fcport->iodesc_idx_sent].cb_idx == - ADISC_PORT_IOCB_CB) { - /* - * Receiving another RSCN while an ADISC is pending, - * abort the IOCB. Use the same descriptor for the - * abort. - */ - uint32_t handle_to_abort; - - iodesc = &ha->io_descriptors[ - remote_fcport->iodesc_idx_sent]; - qla2x00_remove_iodesc_timer(iodesc); - handle_to_abort = iodesc->signature; - iodesc->signature = qla2x00_iodesc_to_handle(iodesc); - iodesc->cb_idx = ABORT_IOCB_CB; - iodesc->d_id.b24 = remote_fcport->d_id.b24; - iodesc->remote_fcport = remote_fcport; - remote_fcport->iodesc_idx_sent = iodesc->idx; - - DEBUG14(printk("scsi(%ld): Handle RSCN -- issuing " - "abort to outstanding Adisc [%x/%02x%02x%02x].\n", - ha->host_no, remote_fcport->loop_id, - iodesc->d_id.b.domain, iodesc->d_id.b.area, - iodesc->d_id.b.al_pa)); - - qla2x00_send_abort_iocb(ha, iodesc, handle_to_abort, - ha_locked); - } - } - - /* We need to login to the remote port, find it. */ - if (known_fcport) { - remote_fcport = known_fcport; - } else if (rscn_fcport && rscn_fcport->d_id.b24 != INVALID_PORT_ID && - rscn_fcport->iodesc_idx_sent < MAX_IO_DESCRIPTORS && - ha->io_descriptors[rscn_fcport->iodesc_idx_sent].cb_idx == - LOGIN_PORT_IOCB_CB) { - /* - * Ignore duplicate RSCN on fcport which has already - * initiated a login IOCB. - */ - DEBUG14(printk("scsi(%ld): Handle RSCN -- ignoring, login " - "already sent to [%02x%02x%02x].\n", ha->host_no, - rscn_fcport->d_id.b.domain, rscn_fcport->d_id.b.area, - rscn_fcport->d_id.b.al_pa)); - - return (QLA_SUCCESS); - } else if (rscn_fcport && rscn_fcport->d_id.b24 != INVALID_PORT_ID && - rscn_fcport != remote_fcport) { - /* Reuse same rscn fcport. */ - DEBUG14(printk("scsi(%ld): Handle RSCN -- reusing RSCN fcport " - "[%02x%02x%02x].\n", ha->host_no, - rscn_fcport->d_id.b.domain, rscn_fcport->d_id.b.area, - rscn_fcport->d_id.b.al_pa)); - - remote_fcport = rscn_fcport; - } else { - /* Create new fcport for later login. */ - remote_fcport = qla2x00_alloc_rscn_fcport(ha, - ha_locked ? GFP_ATOMIC: GFP_KERNEL); - list_add_tail(&remote_fcport->list, &ha->rscn_fcports); - } - if (remote_fcport == NULL) - return (QLA_SUCCESS); - - /* Prepare fcport for login. */ - atomic_set(&remote_fcport->state, FCS_DEVICE_LOST); - remote_fcport->login_retry = 3; /* ha->login_retry_count; */ - remote_fcport->d_id.b24 = rscn_pid.b24; - - iodesc = qla2x00_alloc_iodesc(ha); - if (iodesc == NULL) { - /* Mark fcport for later adisc processing. */ - DEBUG14(printk("scsi(%ld): Handle RSCN -- not enough IO " - "descriptors for Login, flag for later processing.\n", - ha->host_no)); - - remote_fcport->iodesc_idx_sent = IODESC_LOGIN_NEEDED; - set_bit(IODESC_PROCESS_NEEDED, &ha->dpc_flags); - - return (QLA_SUCCESS); - } - - if (known_fcport == NULL || rscn_pid.b24 != INVALID_PORT_ID) { - remote_fcport->loop_id = ha->min_external_loopid; - - rval = qla2x00_find_new_loop_id(ha, remote_fcport); - if (rval == QLA_FUNCTION_FAILED) { - /* No more loop ids, failed. */ - DEBUG14(printk("scsi(%ld): Handle RSCN -- no available " - "loop id to perform Login, failed.\n", - ha->host_no)); - - return (rval); - } - } - - iodesc->cb_idx = LOGIN_PORT_IOCB_CB; - iodesc->d_id.b24 = rscn_pid.b24; - iodesc->remote_fcport = remote_fcport; - remote_fcport->iodesc_idx_sent = iodesc->idx; - - DEBUG14(printk("scsi(%ld): Handle RSCN -- attempting login to " - "[%x/%02x%02x%02x].\n", ha->host_no, remote_fcport->loop_id, - iodesc->d_id.b.domain, iodesc->d_id.b.area, iodesc->d_id.b.al_pa)); - - qla2x00_send_login_iocb(ha, iodesc, &rscn_pid, ha_locked); - - return (QLA_SUCCESS); -} - -/** - * qla2x00_process_iodesc() - Complete IO descriptor processing. - * @ha: HA context - * @mbxstat: Mailbox IOCB status - */ -void -qla2x00_process_iodesc(scsi_qla_host_t *ha, struct mbx_entry *mbxstat) -{ - int rval; - uint32_t signature; - fc_port_t *fcport; - struct io_descriptor *iodesc; - - signature = mbxstat->handle; - - DEBUG14(printk("scsi(%ld): Process IODesc -- processing %08x.\n", - ha->host_no, signature)); - - /* Retrieve proper IO descriptor. */ - iodesc = qla2x00_handle_to_iodesc(ha, signature); - if (iodesc == NULL) { - DEBUG14(printk("scsi(%ld): Process IODesc -- ignoring, " - "incorrect signature %08x.\n", ha->host_no, signature)); - - return; - } - - /* Stop IO descriptor timer. */ - qla2x00_remove_iodesc_timer(iodesc); - - /* Verify signature match. */ - if (iodesc->signature != signature) { - DEBUG14(printk("scsi(%ld): Process IODesc -- ignoring, " - "signature mismatch, sent %08x, received %08x.\n", - ha->host_no, iodesc->signature, signature)); - - return; - } - - /* Go with IOCB callback. */ - rval = iocb_function_cb_list[iodesc->cb_idx](ha, iodesc, mbxstat); - if (rval != QLA_SUCCESS) { - /* IO descriptor reused by callback. */ - return; - } - - qla2x00_free_iodesc(iodesc); - - if (test_bit(IODESC_PROCESS_NEEDED, &ha->dpc_flags)) { - /* Scan our fcports list for any RSCN requests. */ - list_for_each_entry(fcport, &ha->fcports, list) { - if (fcport->iodesc_idx_sent == IODESC_ADISC_NEEDED || - fcport->iodesc_idx_sent == IODESC_LOGIN_NEEDED) { - qla2x00_handle_port_rscn(ha, 0, fcport, 1); - return; - } - } - - /* Scan our RSCN fcports list for any RSCN requests. */ - list_for_each_entry(fcport, &ha->rscn_fcports, list) { - if (fcport->iodesc_idx_sent == IODESC_ADISC_NEEDED || - fcport->iodesc_idx_sent == IODESC_LOGIN_NEEDED) { - qla2x00_handle_port_rscn(ha, 0, fcport, 1); - return; - } - } - } - clear_bit(IODESC_PROCESS_NEEDED, &ha->dpc_flags); -} - -/** - * qla2x00_cancel_io_descriptors() - Cancel all outstanding io descriptors. - * @ha: HA context - * - * This routine will also delete any RSCN entries related to the outstanding - * IO descriptors. - */ -void -qla2x00_cancel_io_descriptors(scsi_qla_host_t *ha) -{ - fc_port_t *fcport, *fcptemp; - - clear_bit(IODESC_PROCESS_NEEDED, &ha->dpc_flags); - - /* Abort all IO descriptors. */ - qla2x00_init_io_descriptors(ha); - - /* Reset all pending IO descriptors in fcports list. */ - list_for_each_entry(fcport, &ha->fcports, list) { - fcport->iodesc_idx_sent = IODESC_INVALID_INDEX; - } - - /* Reset all pending IO descriptors in rscn fcports list. */ - list_for_each_entry_safe(fcport, fcptemp, &ha->rscn_fcports, list) { - DEBUG14(printk("scsi(%ld): Cancel IOs -- Freeing RSCN fcport " - "%p [%x/%02x%02x%02x].\n", ha->host_no, fcport, - fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area, - fcport->d_id.b.al_pa)); - - list_del(&fcport->list); - kfree(fcport); - } -} -- cgit v1.2.3 From 441d1072040823feb4950a21094860bfddd310c0 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Wed, 17 May 2006 15:09:34 -0700 Subject: [SCSI] qla2xxx: Remove obsolete firmware-loader-module support. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/Kconfig | 45 - drivers/scsi/qla2xxx/Makefile | 14 - drivers/scsi/qla2xxx/ql2100.c | 91 - drivers/scsi/qla2xxx/ql2100_fw.c | 4848 --------------- drivers/scsi/qla2xxx/ql2200.c | 91 - drivers/scsi/qla2xxx/ql2200_fw.c | 5333 ---------------- drivers/scsi/qla2xxx/ql2300.c | 114 - drivers/scsi/qla2xxx/ql2300_fw.c | 7746 ----------------------- drivers/scsi/qla2xxx/ql2322.c | 119 - drivers/scsi/qla2xxx/ql2322_fw.c | 8376 ------------------------- drivers/scsi/qla2xxx/ql2400.c | 138 - drivers/scsi/qla2xxx/ql2400_fw.c | 12346 ------------------------------------- drivers/scsi/qla2xxx/qla_def.h | 25 +- drivers/scsi/qla2xxx/qla_fw.h | 1 - drivers/scsi/qla2xxx/qla_gbl.h | 3 - drivers/scsi/qla2xxx/qla_init.c | 134 +- drivers/scsi/qla2xxx/qla_os.c | 54 +- 17 files changed, 22 insertions(+), 39456 deletions(-) delete mode 100644 drivers/scsi/qla2xxx/ql2100.c delete mode 100644 drivers/scsi/qla2xxx/ql2100_fw.c delete mode 100644 drivers/scsi/qla2xxx/ql2200.c delete mode 100644 drivers/scsi/qla2xxx/ql2200_fw.c delete mode 100644 drivers/scsi/qla2xxx/ql2300.c delete mode 100644 drivers/scsi/qla2xxx/ql2300_fw.c delete mode 100644 drivers/scsi/qla2xxx/ql2322.c delete mode 100644 drivers/scsi/qla2xxx/ql2322_fw.c delete mode 100644 drivers/scsi/qla2xxx/ql2400.c delete mode 100644 drivers/scsi/qla2xxx/ql2400_fw.c diff --git a/drivers/scsi/qla2xxx/Kconfig b/drivers/scsi/qla2xxx/Kconfig index ff40906c66f..8c865b9e02b 100644 --- a/drivers/scsi/qla2xxx/Kconfig +++ b/drivers/scsi/qla2xxx/Kconfig @@ -24,48 +24,3 @@ config SCSI_QLA_FC Firmware images can be retrieved from: ftp://ftp.qlogic.com/outgoing/linux/firmware/ - - NOTE: The original method of building firmware-loader - modules has been deprecated as the firmware-images will - be removed from the kernel sources. - -config SCSI_QLA2XXX_EMBEDDED_FIRMWARE - bool " Use firmware-loader modules (DEPRECATED)" - depends on SCSI_QLA_FC - help - This option offers you the deprecated firmware-loader - modules that have been obsoleted by the usage of the - Firmware Loader interface in the qla2xxx driver. - -config SCSI_QLA21XX - tristate " Build QLogic ISP2100 firmware-module" - depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE - ---help--- - This driver supports the QLogic 21xx (ISP2100) host adapter family. - -config SCSI_QLA22XX - tristate " Build QLogic ISP2200 firmware-module" - depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE - ---help--- - This driver supports the QLogic 22xx (ISP2200) host adapter family. - -config SCSI_QLA2300 - tristate " Build QLogic ISP2300/ISP6312 firmware-module" - depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE - ---help--- - This driver supports the QLogic 2300 (ISP2300, ISP2312 and - ISP6312) host adapter family. - -config SCSI_QLA2322 - tristate " Build QLogic ISP2322/ISP6322 firmware-module" - depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE - ---help--- - This driver supports the QLogic 2322 (ISP2322 and ISP6322) host - adapter family. - -config SCSI_QLA24XX - tristate " Build QLogic ISP24xx firmware-module" - depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE - ---help--- - This driver supports the QLogic 24xx (ISP2422 and ISP2432) host - adapter family. diff --git a/drivers/scsi/qla2xxx/Makefile b/drivers/scsi/qla2xxx/Makefile index 6ff7bb0d8e2..411663af7bb 100644 --- a/drivers/scsi/qla2xxx/Makefile +++ b/drivers/scsi/qla2xxx/Makefile @@ -1,18 +1,4 @@ -EXTRA_CFLAGS += -DUNIQUE_FW_NAME - qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \ qla_dbg.o qla_sup.o qla_attr.o obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx.o - -qla2100-y := ql2100.o ql2100_fw.o -qla2200-y := ql2200.o ql2200_fw.o -qla2300-y := ql2300.o ql2300_fw.o -qla2322-y := ql2322.o ql2322_fw.o -qla2400-y := ql2400.o ql2400_fw.o - -obj-$(CONFIG_SCSI_QLA21XX) += qla2xxx.o qla2100.o -obj-$(CONFIG_SCSI_QLA22XX) += qla2xxx.o qla2200.o -obj-$(CONFIG_SCSI_QLA2300) += qla2xxx.o qla2300.o -obj-$(CONFIG_SCSI_QLA2322) += qla2xxx.o qla2322.o -obj-$(CONFIG_SCSI_QLA24XX) += qla2xxx.o qla2400.o diff --git a/drivers/scsi/qla2xxx/ql2100.c b/drivers/scsi/qla2xxx/ql2100.c deleted file mode 100644 index f5db2235e43..00000000000 --- a/drivers/scsi/qla2xxx/ql2100.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * QLogic Fibre Channel HBA Driver - * Copyright (C) 2003 Christoph Hellwig. - * Copyright (c) 2003-2005 QLogic Corporation - * - * See LICENSE.qla2xxx for copyright and licensing details. - */ -#include -#include -#include - -#include "qla_def.h" - -static char qla_driver_name[] = "qla2100"; - -extern unsigned char fw2100tp_version[]; -extern unsigned char fw2100tp_version_str[]; -extern unsigned short fw2100tp_addr01; -extern unsigned short fw2100tp_code01[]; -extern unsigned short fw2100tp_length01; - -static struct qla_fw_info qla_fw_tbl[] = { - { - .addressing = FW_INFO_ADDR_NORMAL, - .fwcode = &fw2100tp_code01[0], - .fwlen = &fw2100tp_length01, - .fwstart = &fw2100tp_addr01, - }, - - { FW_INFO_ADDR_NOMORE, }, -}; - -static struct qla_board_info qla_board_tbl = { - .drv_name = qla_driver_name, - - .isp_name = "ISP2100", - .fw_info = qla_fw_tbl, -}; - -static struct pci_device_id qla2100_pci_tbl[] = { - { - .vendor = PCI_VENDOR_ID_QLOGIC, - .device = PCI_DEVICE_ID_QLOGIC_ISP2100, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = (unsigned long)&qla_board_tbl, - }, - - {0, 0}, -}; -MODULE_DEVICE_TABLE(pci, qla2100_pci_tbl); - -static int __devinit -qla2100_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) -{ - return qla2x00_probe_one(pdev, - (struct qla_board_info *)id->driver_data); -} - -static void __devexit -qla2100_remove_one(struct pci_dev *pdev) -{ - qla2x00_remove_one(pdev); -} - -static struct pci_driver qla2100_pci_driver = { - .name = "qla2100", - .id_table = qla2100_pci_tbl, - .probe = qla2100_probe_one, - .remove = __devexit_p(qla2100_remove_one), -}; - -static int __init -qla2100_init(void) -{ - return pci_module_init(&qla2100_pci_driver); -} - -static void __exit -qla2100_exit(void) -{ - pci_unregister_driver(&qla2100_pci_driver); -} - -module_init(qla2100_init); -module_exit(qla2100_exit); - -MODULE_AUTHOR("QLogic Corporation"); -MODULE_DESCRIPTION("QLogic ISP21xx FC-SCSI Host Bus Adapter driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(QLA2XXX_VERSION); diff --git a/drivers/scsi/qla2xxx/ql2100_fw.c b/drivers/scsi/qla2xxx/ql2100_fw.c deleted file mode 100644 index 56006162da4..00000000000 --- a/drivers/scsi/qla2xxx/ql2100_fw.c +++ /dev/null @@ -1,4848 +0,0 @@ -/* - * QLogic Fibre Channel HBA Driver - * Copyright (c) 2003-2005 QLogic Corporation - * - * See LICENSE.qla2xxx for copyright and licensing details. - */ - -/* - * Firmware Version 1.19.25 (13:12 Dec 10, 2003) - */ - -#ifdef UNIQUE_FW_NAME -unsigned short fw2100tp_version = 1*1024+19; -#else -unsigned short risc_code_version = 1*1024+19; -#endif - -#ifdef UNIQUE_FW_NAME -unsigned char fw2100tp_version_str[] = {1,19,25}; -#else -unsigned char firmware_version[] = {1,19,25}; -#endif - -#ifdef UNIQUE_FW_NAME -#define fw2100tp_VERSION_STRING "1.19.25" -#else -#define FW_VERSION_STRING "1.19.25" -#endif - -#ifdef UNIQUE_FW_NAME -unsigned short fw2100tp_addr01 = 0x1000 ; -#else -unsigned short risc_code_addr01 = 0x1000 ; -#endif - -#ifdef UNIQUE_FW_NAME -unsigned short fw2100tp_code01[] = { -#else -unsigned short risc_code01[] = { -#endif - 0x0078, 0x102d, 0x0000, 0x9601, 0x0000, 0x0001, 0x0013, 0x0019, - 0x0017, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2032, 0x3030, - 0x3120, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241, - 0x5449, 0x4f4e, 0x2049, 0x5350, 0x3231, 0x3030, 0x2046, 0x6972, - 0x6d77, 0x6172, 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030, - 0x312e, 0x3139, 0x2020, 0x2020, 0x2400, 0x2091, 0x2000, 0x20c1, - 0x0021, 0x2039, 0xffff, 0x2019, 0xaaaa, 0x2760, 0x2069, 0x7fff, - 0x20c1, 0x0020, 0x2c2c, 0x2d34, 0x2762, 0x236a, 0x2c24, 0x2d04, - 0x266a, 0x2562, 0xa406, 0x00c0, 0x1052, 0x20c1, 0x0021, 0x2c2c, - 0x2362, 0x2c04, 0x2562, 0xa306, 0x0040, 0x1052, 0x20c1, 0x0020, - 0x2039, 0x8fff, 0x20a1, 0xae00, 0x2708, 0x810d, 0x810d, 0x810d, - 0x810d, 0xa18c, 0x000f, 0x2001, 0x000a, 0xa112, 0xa00e, 0x21a8, - 0x41a4, 0x3400, 0x8211, 0x00c0, 0x105f, 0x2708, 0x3400, 0xa102, - 0x0040, 0x106f, 0x0048, 0x106f, 0x20a8, 0xa00e, 0x41a4, 0x20a1, - 0xa601, 0x2009, 0x0000, 0x20a9, 0x07ff, 0x41a4, 0x3400, 0x20c9, - 0xabff, 0x2059, 0x0000, 0x2b78, 0x7823, 0x0004, 0x2089, 0x25c7, - 0x2051, 0xa700, 0x2a70, 0x7762, 0xa786, 0x8fff, 0x0040, 0x1092, - 0x705f, 0xce00, 0x705b, 0xcdf1, 0x7067, 0x0200, 0x706b, 0x0200, - 0x0078, 0x109a, 0x705b, 0xbe01, 0x7067, 0x0100, 0x706b, 0x0100, - 0x705f, 0xbe00, 0x1078, 0x12df, 0x1078, 0x13ca, 0x1078, 0x1577, - 0x1078, 0x1ce9, 0x1078, 0x42ec, 0x1078, 0x76bf, 0x1078, 0x1355, - 0x1078, 0x2ac0, 0x1078, 0x4e93, 0x1078, 0x49a3, 0x1078, 0x594a, - 0x1078, 0x2263, 0x1078, 0x5c43, 0x1078, 0x5485, 0x1078, 0x2162, - 0x1078, 0x2240, 0x2091, 0x3009, 0x7823, 0x0000, 0x0090, 0x10cf, - 0x7820, 0xa086, 0x0002, 0x00c0, 0x10cf, 0x7823, 0x4000, 0x0068, - 0x10c7, 0x781b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2a70, - 0x7003, 0x0000, 0x2001, 0x017f, 0x2003, 0x0000, 0x2a70, 0x7000, - 0xa08e, 0x0003, 0x00c0, 0x10ef, 0x1078, 0x365e, 0x1078, 0x2ae8, - 0x1078, 0x4ee3, 0x1078, 0x4b66, 0x2009, 0x0100, 0x2104, 0xa082, - 0x0002, 0x0048, 0x10f3, 0x1078, 0x5966, 0x0078, 0x10d6, 0x1079, - 0x10f7, 0x0078, 0x10dc, 0x1078, 0x7197, 0x0078, 0x10eb, 0x1101, - 0x1102, 0x11be, 0x10ff, 0x1246, 0x12dc, 0x12dd, 0x12de, 0x1078, - 0x1332, 0x007c, 0x127e, 0x0f7e, 0x2091, 0x8000, 0x7000, 0xa086, - 0x0001, 0x00c0, 0x1198, 0x1078, 0x3aec, 0x2079, 0x0100, 0x7844, - 0xa005, 0x00c0, 0x1198, 0x2011, 0x41dc, 0x1078, 0x5a45, 0x1078, - 0x1adf, 0x780f, 0x00ff, 0x7840, 0xa084, 0xfffb, 0x7842, 0x2011, - 0x8010, 0x73c4, 0x1078, 0x361b, 0x2001, 0xffff, 0x1078, 0x5ae6, - 0x723c, 0xc284, 0x723e, 0x2001, 0xa70c, 0x2014, 0xc2ac, 0x2202, - 0x1078, 0x6f9f, 0x2011, 0x0004, 0x1078, 0x8d2b, 0x1078, 0x489e, - 0x1078, 0x42d4, 0x0040, 0x1144, 0x7087, 0x0001, 0x70bf, 0x0000, - 0x1078, 0x3c9e, 0x0078, 0x1198, 0x1078, 0x4967, 0x0040, 0x114d, - 0x7a0c, 0xc2b4, 0x7a0e, 0x0078, 0x1159, 0x1078, 0x90b6, 0x70cc, - 0xd09c, 0x00c0, 0x1159, 0x7098, 0xa005, 0x0040, 0x1159, 0x1078, - 0x42b8, 0x70d7, 0x0000, 0x70d3, 0x0000, 0x72cc, 0x2079, 0xa752, - 0x7804, 0xd0ac, 0x0040, 0x1165, 0xc295, 0x72ce, 0xa296, 0x0004, - 0x0040, 0x1186, 0x2011, 0x0001, 0x1078, 0x8d2b, 0x7093, 0x0000, - 0x7097, 0xffff, 0x7003, 0x0002, 0x0f7f, 0x1078, 0x2677, 0x2011, - 0x0005, 0x1078, 0x70e0, 0x1078, 0x62d1, 0x0c7e, 0x2061, 0x0100, - 0x60e3, 0x0008, 0x0c7f, 0x127f, 0x0078, 0x119a, 0x7093, 0x0000, - 0x7097, 0xffff, 0x7003, 0x0002, 0x2011, 0x0005, 0x1078, 0x70e0, - 0x1078, 0x62d1, 0x0c7e, 0x2061, 0x0100, 0x60e3, 0x0008, 0x0c7f, - 0x0f7f, 0x127f, 0x007c, 0x0c7e, 0x20a9, 0x0082, 0x2009, 0x007e, - 0x017e, 0x027e, 0x037e, 0x2110, 0x027e, 0x2019, 0x0029, 0x1078, - 0x73d0, 0x027f, 0x1078, 0xa501, 0x037f, 0x027f, 0x017f, 0x1078, - 0x298e, 0x8108, 0x00f0, 0x11a0, 0x0c7f, 0x706f, 0x0000, 0x7070, - 0xa084, 0x00ff, 0x7072, 0x709b, 0x0000, 0x007c, 0x127e, 0x2091, - 0x8000, 0x7000, 0xa086, 0x0002, 0x00c0, 0x1244, 0x7094, 0xa086, - 0xffff, 0x0040, 0x11d1, 0x1078, 0x2677, 0x1078, 0x62d1, 0x0078, - 0x1244, 0x70cc, 0xd09c, 0x0040, 0x11fd, 0xd084, 0x0040, 0x11fd, - 0x0f7e, 0x2079, 0x0100, 0x790c, 0xc1b5, 0x790e, 0x0f7f, 0xd08c, - 0x0040, 0x11fd, 0x70d0, 0xa086, 0xffff, 0x0040, 0x11f9, 0x1078, - 0x27f7, 0x1078, 0x62d1, 0x70cc, 0xd094, 0x00c0, 0x1244, 0x2011, - 0x0001, 0x2019, 0x0000, 0x1078, 0x282f, 0x1078, 0x62d1, 0x0078, - 0x1244, 0x70d4, 0xa005, 0x00c0, 0x1244, 0x7090, 0xa005, 0x00c0, - 0x1244, 0x1078, 0x4967, 0x00c0, 0x1244, 0x2001, 0xa753, 0x2004, - 0xd0ac, 0x0040, 0x1227, 0x157e, 0x0c7e, 0x20a9, 0x007f, 0x2009, - 0x0000, 0x017e, 0x1078, 0x45c4, 0x00c0, 0x121a, 0x6000, 0xd0ec, - 0x00c0, 0x1222, 0x017f, 0x8108, 0x00f0, 0x1211, 0x0c7f, 0x157f, - 0x0078, 0x1227, 0x017f, 0x0c7f, 0x157f, 0x0078, 0x1244, 0x7003, - 0x0003, 0x7097, 0xffff, 0x2001, 0x0000, 0x1078, 0x24e8, 0x1078, - 0x3699, 0x2001, 0xa9b2, 0x2004, 0xa086, 0x0005, 0x00c0, 0x123c, - 0x2011, 0x0000, 0x1078, 0x70e0, 0x2011, 0x0000, 0x1078, 0x70ea, - 0x1078, 0x62d1, 0x1078, 0x639b, 0x127f, 0x007c, 0x017e, 0x0f7e, - 0x127e, 0x2091, 0x8000, 0x2079, 0x0100, 0x2009, 0x00f7, 0x1078, - 0x42a1, 0x7940, 0xa18c, 0x0010, 0x7942, 0x7924, 0xd1b4, 0x0040, - 0x125b, 0x7827, 0x0040, 0xd19c, 0x0040, 0x1260, 0x7827, 0x0008, - 0x007e, 0x037e, 0x157e, 0xa006, 0x1078, 0x5ae6, 0x7900, 0xa18a, - 0x0003, 0x0050, 0x1289, 0x7954, 0xd1ac, 0x00c0, 0x1289, 0x2009, - 0x00f8, 0x1078, 0x42a1, 0x7843, 0x0090, 0x7843, 0x0010, 0x20a9, - 0x09c4, 0x7820, 0xd09c, 0x00c0, 0x1281, 0x7824, 0xd0ac, 0x00c0, - 0x12ca, 0x00f0, 0x1279, 0x2001, 0x0001, 0x1078, 0x24e8, 0x0078, - 0x12d5, 0x7853, 0x0000, 0x782f, 0x0020, 0x20a9, 0x0050, 0x00e0, - 0x128f, 0x2091, 0x6000, 0x00f0, 0x128f, 0x7853, 0x0400, 0x782f, - 0x0000, 0x2009, 0x00f8, 0x1078, 0x42a1, 0x20a9, 0x000e, 0x0005, - 0x00f0, 0x129f, 0x7853, 0x1400, 0x7843, 0x0090, 0x7843, 0x0010, - 0x2019, 0x61a8, 0x7854, 0x0005, 0x0005, 0xd08c, 0x0040, 0x12b4, - 0x7824, 0xd0ac, 0x00c0, 0x12ca, 0x8319, 0x00c0, 0x12aa, 0x2009, - 0xa732, 0x2104, 0x8000, 0x200a, 0xa084, 0xfff0, 0x0040, 0x12c4, - 0x200b, 0x0000, 0x1078, 0x2588, 0x2001, 0x0001, 0x1078, 0x24e8, - 0x0078, 0x12d3, 0x2001, 0xa732, 0x2003, 0x0000, 0x7828, 0xc09d, - 0x782a, 0x7827, 0x0048, 0x7853, 0x0400, 0x157f, 0x037f, 0x007f, - 0x127f, 0x0f7f, 0x017f, 0x007c, 0x007c, 0x007c, 0x007c, 0x2a70, - 0x2061, 0xa9ad, 0x2063, 0x0001, 0x6007, 0x0013, 0x600b, 0x0019, - 0x600f, 0x0017, 0x2009, 0x0100, 0x2104, 0xa082, 0x0002, 0x0048, - 0x12f5, 0x7053, 0xffff, 0x0078, 0x12f7, 0x7053, 0x0000, 0x7057, - 0xffff, 0x706f, 0x0000, 0x7073, 0x0000, 0x1078, 0x90b6, 0x2061, - 0xa98d, 0x6003, 0x0909, 0x6007, 0x0000, 0x600b, 0x8800, 0x600f, - 0x0200, 0x6013, 0x00ff, 0x6017, 0x0003, 0x601b, 0x0000, 0x601f, - 0x07d0, 0x2061, 0xa995, 0x6003, 0x8000, 0x6007, 0x0000, 0x600b, - 0x0000, 0x600f, 0x0200, 0x6013, 0x00ff, 0x6017, 0x0000, 0x601b, - 0x0001, 0x601f, 0x0000, 0x2061, 0xa9a5, 0x6003, 0x514c, 0x6007, - 0x4f47, 0x600b, 0x4943, 0x600f, 0x2020, 0x2001, 0xa726, 0x2003, - 0x0000, 0x007c, 0x2091, 0x8000, 0x0068, 0x1334, 0x007e, 0x017e, - 0x2079, 0x0000, 0x7818, 0xd084, 0x00c0, 0x133a, 0x017f, 0x792e, - 0x007f, 0x782a, 0x007f, 0x7826, 0x3900, 0x783a, 0x7823, 0x8002, - 0x781b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2079, 0xa700, - 0x7803, 0x0005, 0x0078, 0x1352, 0x007c, 0x2071, 0xa700, 0x715c, - 0x712e, 0x2021, 0x0001, 0xa190, 0x002d, 0xa298, 0x002d, 0x0048, - 0x136b, 0x7060, 0xa302, 0x00c8, 0x136b, 0x220a, 0x2208, 0x2310, - 0x8420, 0x0078, 0x135d, 0x200b, 0x0000, 0x74aa, 0x74ae, 0x007c, - 0x0e7e, 0x127e, 0x2091, 0x8000, 0x2071, 0xa700, 0x70ac, 0xa0ea, - 0x0010, 0x00c8, 0x137e, 0xa06e, 0x0078, 0x1388, 0x8001, 0x70ae, - 0x702c, 0x2068, 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, 0x0000, - 0x127f, 0x0e7f, 0x007c, 0x0e7e, 0x2071, 0xa700, 0x127e, 0x2091, - 0x8000, 0x70ac, 0x8001, 0x00c8, 0x1398, 0xa06e, 0x0078, 0x13a1, - 0x70ae, 0x702c, 0x2068, 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, - 0x0000, 0x127f, 0x0e7f, 0x007c, 0x0e7e, 0x127e, 0x2091, 0x8000, - 0x2071, 0xa700, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70ac, 0x8000, - 0x70ae, 0x127f, 0x0e7f, 0x007c, 0x8dff, 0x0040, 0x13c0, 0x6804, - 0x6807, 0x0000, 0x007e, 0x1078, 0x13a4, 0x0d7f, 0x0078, 0x13b4, - 0x007c, 0x0e7e, 0x2071, 0xa700, 0x70ac, 0xa08a, 0x0010, 0xa00d, - 0x0e7f, 0x007c, 0x0e7e, 0x2071, 0xa9d6, 0x7007, 0x0000, 0x701b, - 0x0000, 0x701f, 0x0000, 0x2071, 0x0000, 0x7010, 0xa085, 0x8004, - 0x7012, 0x0e7f, 0x007c, 0x127e, 0x2091, 0x8000, 0x0e7e, 0x2270, - 0x700b, 0x0000, 0x2071, 0xa9d6, 0x7018, 0xa088, 0xa9df, 0x220a, - 0x8000, 0xa084, 0x0007, 0x701a, 0x7004, 0xa005, 0x00c0, 0x13f6, - 0x0f7e, 0x2079, 0x0010, 0x1078, 0x1408, 0x0f7f, 0x0e7f, 0x127f, - 0x007c, 0x0e7e, 0x2071, 0xa9d6, 0x7004, 0xa005, 0x00c0, 0x1406, - 0x0f7e, 0x2079, 0x0010, 0x1078, 0x1408, 0x0f7f, 0x0e7f, 0x007c, - 0x7000, 0x0079, 0x140b, 0x140f, 0x1479, 0x1496, 0x1496, 0x7018, - 0x711c, 0xa106, 0x00c0, 0x1417, 0x7007, 0x0000, 0x007c, 0x0d7e, - 0xa180, 0xa9df, 0x2004, 0x700a, 0x2068, 0x8108, 0xa18c, 0x0007, - 0x711e, 0x7803, 0x0026, 0x6824, 0x7832, 0x6828, 0x7836, 0x682c, - 0x783a, 0x6830, 0x783e, 0x6810, 0x700e, 0x680c, 0x7016, 0x6804, - 0x0d7f, 0xd084, 0x0040, 0x1439, 0x7007, 0x0001, 0x1078, 0x143e, - 0x007c, 0x7007, 0x0002, 0x1078, 0x1454, 0x007c, 0x017e, 0x027e, - 0x710c, 0x2011, 0x0040, 0xa182, 0x0040, 0x00c8, 0x1449, 0x2110, - 0xa006, 0x700e, 0x7212, 0x8203, 0x7822, 0x7803, 0x0020, 0x7803, - 0x0041, 0x027f, 0x017f, 0x007c, 0x017e, 0x027e, 0x137e, 0x147e, - 0x157e, 0x7014, 0x2098, 0x20a1, 0x0014, 0x7803, 0x0026, 0x710c, - 0x2011, 0x0040, 0xa182, 0x0040, 0x00c8, 0x1468, 0x2110, 0xa006, - 0x700e, 0x22a8, 0x53a6, 0x8203, 0x7822, 0x7803, 0x0020, 0x3300, - 0x7016, 0x7803, 0x0001, 0x157f, 0x147f, 0x137f, 0x027f, 0x017f, - 0x007c, 0x137e, 0x147e, 0x157e, 0x2099, 0xa7fa, 0x20a1, 0x0018, - 0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x127e, 0x2091, 0x8000, - 0x7803, 0x0041, 0x7007, 0x0003, 0x7000, 0xc084, 0x7002, 0x700b, - 0xa7f5, 0x127f, 0x157f, 0x147f, 0x137f, 0x007c, 0x137e, 0x147e, - 0x157e, 0x2001, 0xa829, 0x209c, 0x20a1, 0x0014, 0x7803, 0x0026, - 0x2001, 0xa82a, 0x20ac, 0x53a6, 0x2099, 0xa82b, 0x20a1, 0x0018, - 0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x127e, 0x2091, 0x8000, - 0x7803, 0x0001, 0x7007, 0x0004, 0x7000, 0xc08c, 0x7002, 0x700b, - 0xa826, 0x127f, 0x157f, 0x147f, 0x137f, 0x007c, 0x017e, 0x0e7e, - 0x2071, 0xa9d6, 0x0f7e, 0x2079, 0x0010, 0x7904, 0x7803, 0x0002, - 0xd1fc, 0x0040, 0x14d0, 0xa18c, 0x0700, 0x7004, 0x1079, 0x14d4, - 0x0f7f, 0x0e7f, 0x017f, 0x007c, 0x1408, 0x14dc, 0x1509, 0x1531, - 0x1564, 0x14da, 0x0078, 0x14da, 0xa18c, 0x0700, 0x00c0, 0x1502, - 0x137e, 0x147e, 0x157e, 0x7014, 0x20a0, 0x2099, 0x0014, 0x7803, - 0x0040, 0x7010, 0x20a8, 0x53a5, 0x3400, 0x7016, 0x157f, 0x147f, - 0x137f, 0x700c, 0xa005, 0x0040, 0x151e, 0x1078, 0x143e, 0x007c, - 0x7008, 0xa080, 0x0002, 0x2003, 0x0100, 0x7007, 0x0000, 0x1078, - 0x1408, 0x007c, 0x7008, 0xa080, 0x0002, 0x2003, 0x0200, 0x0078, - 0x14fd, 0xa18c, 0x0700, 0x00c0, 0x1514, 0x700c, 0xa005, 0x0040, - 0x151e, 0x1078, 0x1454, 0x007c, 0x7008, 0xa080, 0x0002, 0x2003, - 0x0200, 0x7007, 0x0000, 0x1078, 0x1408, 0x007c, 0x0d7e, 0x7008, - 0x2068, 0x7830, 0x6826, 0x7834, 0x682a, 0x7838, 0x682e, 0x783c, - 0x6832, 0x680b, 0x0100, 0x0d7f, 0x7007, 0x0000, 0x1078, 0x1408, - 0x007c, 0xa18c, 0x0700, 0x00c0, 0x155e, 0x137e, 0x147e, 0x157e, - 0x2001, 0xa7f8, 0x2004, 0xa080, 0x000d, 0x20a0, 0x2099, 0x0014, - 0x7803, 0x0040, 0x20a9, 0x0020, 0x53a5, 0x2001, 0xa7fa, 0x2004, - 0xd0bc, 0x0040, 0x1554, 0x2001, 0xa803, 0x2004, 0xa080, 0x000d, - 0x20a0, 0x20a9, 0x0020, 0x53a5, 0x157f, 0x147f, 0x137f, 0x7007, - 0x0000, 0x1078, 0x4f8c, 0x1078, 0x1408, 0x007c, 0x2011, 0x8003, - 0x1078, 0x361b, 0x0078, 0x1562, 0xa18c, 0x0700, 0x00c0, 0x1571, - 0x2001, 0xa828, 0x2003, 0x0100, 0x7007, 0x0000, 0x1078, 0x1408, - 0x007c, 0x2011, 0x8004, 0x1078, 0x361b, 0x0078, 0x1575, 0x127e, - 0x2091, 0x2100, 0x2079, 0x0030, 0x2071, 0xa9e7, 0x7803, 0x0004, - 0x7003, 0x0000, 0x700f, 0xa9ed, 0x7013, 0xa9ed, 0x780f, 0x0076, - 0x7803, 0x0004, 0x127f, 0x007c, 0x6934, 0xa184, 0x0007, 0x0079, - 0x1591, 0x1599, 0x15df, 0x1599, 0x1599, 0x1599, 0x15c4, 0x15a8, - 0x159d, 0xa085, 0x0001, 0x0078, 0x15f9, 0x684c, 0xd0bc, 0x0040, - 0x1599, 0x6860, 0x682e, 0x685c, 0x682a, 0x6858, 0x0078, 0x15e7, - 0xa18c, 0x00ff, 0xa186, 0x001e, 0x00c0, 0x1599, 0x684c, 0xd0bc, - 0x0040, 0x1599, 0x6860, 0x682e, 0x685c, 0x682a, 0x6804, 0x681a, - 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x206a, 0x2004, - 0x6832, 0x6858, 0x0078, 0x15ef, 0xa18c, 0x00ff, 0xa186, 0x0015, - 0x00c0, 0x1599, 0x684c, 0xd0ac, 0x0040, 0x1599, 0x6804, 0x681a, - 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x206a, 0x2004, - 0x6832, 0xa006, 0x682e, 0x682a, 0x6858, 0x0078, 0x15ef, 0x684c, - 0xd0ac, 0x0040, 0x1599, 0xa006, 0x682e, 0x682a, 0x6858, 0xa18c, - 0x000f, 0xa188, 0x206a, 0x210c, 0x6932, 0x2d08, 0x691a, 0x6826, - 0x684c, 0xc0dd, 0x684e, 0xa006, 0x680a, 0x697c, 0x6912, 0x6980, - 0x6916, 0x007c, 0x20e1, 0x0007, 0x20e1, 0x2000, 0x2001, 0x020a, - 0x2004, 0x82ff, 0x0040, 0x161c, 0xa280, 0x0004, 0x0d7e, 0x206c, - 0x684c, 0xd0dc, 0x00c0, 0x1618, 0x1078, 0x158c, 0x0040, 0x1618, - 0x0d7f, 0xa280, 0x0000, 0x2003, 0x0002, 0xa016, 0x0078, 0x161c, - 0x6808, 0x8000, 0x680a, 0x0d7f, 0x127e, 0x047e, 0x037e, 0x027e, - 0x2091, 0x2100, 0x027f, 0x037f, 0x047f, 0x7000, 0xa005, 0x00c0, - 0x1630, 0x7206, 0x2001, 0x1651, 0x007e, 0x2260, 0x0078, 0x17e0, - 0x710c, 0x220a, 0x8108, 0x230a, 0x8108, 0x240a, 0x8108, 0xa182, - 0xaa08, 0x0048, 0x163d, 0x2009, 0xa9ed, 0x710e, 0x7010, 0xa102, - 0xa082, 0x0009, 0x0040, 0x1648, 0xa080, 0x001b, 0x00c0, 0x164b, - 0x2009, 0x0138, 0x200a, 0x7000, 0xa005, 0x00c0, 0x1651, 0x1078, - 0x17c1, 0x127f, 0x007c, 0x127e, 0x027e, 0x037e, 0x0c7e, 0x007e, - 0x2091, 0x2100, 0x007f, 0x047f, 0x037f, 0x027f, 0x0d7e, 0x0c7e, - 0x2460, 0x6110, 0x2168, 0x6a62, 0x6b5e, 0xa005, 0x0040, 0x16dd, - 0x6808, 0xa005, 0x0040, 0x174a, 0x7000, 0xa005, 0x00c0, 0x1672, - 0x0078, 0x16d2, 0x700c, 0x7110, 0xa106, 0x00c0, 0x1753, 0x7004, - 0xa406, 0x00c0, 0x16d2, 0x2001, 0x0005, 0x2004, 0xd08c, 0x0040, - 0x168f, 0x047e, 0x1078, 0x1913, 0x047f, 0x2460, 0x6010, 0xa080, - 0x0002, 0x2004, 0xa005, 0x0040, 0x174a, 0x0078, 0x166c, 0x2001, - 0x0207, 0x2004, 0xd09c, 0x00c0, 0x167b, 0x7804, 0xa084, 0x6000, - 0x0040, 0x16a0, 0xa086, 0x6000, 0x0040, 0x16a0, 0x0078, 0x167b, - 0x7100, 0xa186, 0x0002, 0x00c0, 0x16c0, 0x0e7e, 0x2b68, 0x6818, - 0x2060, 0x1078, 0x203f, 0x2804, 0xac70, 0x6034, 0xd09c, 0x00c0, - 0x16b5, 0x7108, 0x720c, 0x0078, 0x16b7, 0x7110, 0x7214, 0x6810, - 0xa100, 0x6812, 0x6814, 0xa201, 0x6816, 0x0e7f, 0x0078, 0x16c4, - 0xa186, 0x0001, 0x00c0, 0x16cc, 0x7820, 0x6910, 0xa100, 0x6812, - 0x7824, 0x6914, 0xa101, 0x6816, 0x7803, 0x0004, 0x7003, 0x0000, - 0x7004, 0x2060, 0x6100, 0xa18e, 0x0004, 0x00c0, 0x1753, 0x2009, - 0x0048, 0x1078, 0x775c, 0x0078, 0x1753, 0x6808, 0xa005, 0x0040, - 0x174a, 0x7000, 0xa005, 0x00c0, 0x16e7, 0x0078, 0x174a, 0x700c, - 0x7110, 0xa106, 0x00c0, 0x16f0, 0x7004, 0xa406, 0x00c0, 0x174a, - 0x2001, 0x0005, 0x2004, 0xd08c, 0x0040, 0x1704, 0x047e, 0x1078, - 0x1913, 0x047f, 0x2460, 0x6010, 0xa080, 0x0002, 0x2004, 0xa005, - 0x0040, 0x174a, 0x0078, 0x16e1, 0x2001, 0x0207, 0x2004, 0xd09c, - 0x00c0, 0x16f0, 0x2001, 0x0005, 0x2004, 0xd08c, 0x00c0, 0x16f6, - 0x7804, 0xa084, 0x6000, 0x0040, 0x171b, 0xa086, 0x6000, 0x0040, - 0x171b, 0x0078, 0x16f0, 0x7007, 0x0000, 0xa016, 0x2218, 0x7000, - 0xa08e, 0x0001, 0x0040, 0x173c, 0xa08e, 0x0002, 0x00c0, 0x174a, - 0x0c7e, 0x0e7e, 0x6818, 0x2060, 0x1078, 0x203f, 0x2804, 0xac70, - 0x6034, 0xd09c, 0x00c0, 0x1738, 0x7308, 0x720c, 0x0078, 0x173a, - 0x7310, 0x7214, 0x0e7f, 0x0c7f, 0x7820, 0xa318, 0x7824, 0xa211, - 0x6810, 0xa300, 0x6812, 0x6814, 0xa201, 0x6816, 0x7803, 0x0004, - 0x7003, 0x0000, 0x6100, 0xa18e, 0x0004, 0x00c0, 0x1753, 0x2009, - 0x0048, 0x1078, 0x775c, 0x0c7f, 0x0d7f, 0x127f, 0x007c, 0x0f7e, - 0x0e7e, 0x027e, 0x037e, 0x047e, 0x057e, 0x2071, 0xa9e7, 0x7000, - 0xa086, 0x0000, 0x0040, 0x17ba, 0x7004, 0xac06, 0x00c0, 0x17ab, - 0x2079, 0x0030, 0x7000, 0xa086, 0x0003, 0x0040, 0x17ab, 0x7804, - 0xd0fc, 0x00c0, 0x17a7, 0x20e1, 0x6000, 0x2011, 0x0032, 0x2001, - 0x0208, 0x200c, 0x2001, 0x0209, 0x2004, 0xa106, 0x00c0, 0x176f, - 0x8211, 0x00c0, 0x1777, 0x7804, 0xd0fc, 0x00c0, 0x17a7, 0x1078, - 0x1b22, 0x027e, 0x057e, 0x7803, 0x0004, 0x7804, 0xd0ac, 0x00c0, - 0x178d, 0x7803, 0x0002, 0x7803, 0x0009, 0x7003, 0x0003, 0x7007, - 0x0000, 0x057f, 0x027f, 0x2001, 0x015d, 0x2003, 0x0000, 0x2001, - 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x0078, 0x17ab, 0x1078, - 0x1913, 0x0078, 0x175f, 0x157e, 0x20a9, 0x0009, 0x2009, 0xa9ed, - 0x2104, 0xac06, 0x00c0, 0x17b5, 0x200a, 0xa188, 0x0003, 0x00f0, - 0x17b0, 0x157f, 0x057f, 0x047f, 0x037f, 0x027f, 0x0e7f, 0x0f7f, - 0x007c, 0x700c, 0x7110, 0xa106, 0x00c0, 0x17c9, 0x7003, 0x0000, - 0x007c, 0x2104, 0x7006, 0x2060, 0x8108, 0x211c, 0x8108, 0x2124, - 0x8108, 0xa182, 0xaa08, 0x0048, 0x17d7, 0x2009, 0xa9ed, 0x7112, - 0x700c, 0xa106, 0x00c0, 0x17e0, 0x2001, 0x0138, 0x2003, 0x0008, - 0x8cff, 0x00c0, 0x17e7, 0x1078, 0x1b4d, 0x0078, 0x1854, 0x6010, - 0x2068, 0x2d58, 0x6828, 0xa406, 0x00c0, 0x17f2, 0x682c, 0xa306, - 0x0040, 0x182f, 0x601c, 0xa086, 0x0008, 0x0040, 0x182f, 0x6024, - 0xd0f4, 0x00c0, 0x181c, 0xd0d4, 0x0040, 0x1818, 0x6038, 0xa402, - 0x6034, 0xa303, 0x0040, 0x1806, 0x00c8, 0x1818, 0x643a, 0x6336, - 0x6c2a, 0x6b2e, 0x047e, 0x037e, 0x2400, 0x6c7c, 0xa402, 0x6812, - 0x2300, 0x6b80, 0xa303, 0x6816, 0x037f, 0x047f, 0x0078, 0x181c, - 0x1078, 0x9063, 0x0040, 0x17e3, 0x2001, 0xa774, 0x2004, 0xd0b4, - 0x00c0, 0x182b, 0x6018, 0x2004, 0xd0bc, 0x00c0, 0x182b, 0x6817, - 0x7fff, 0x6813, 0xffff, 0x1078, 0x208a, 0x00c0, 0x17e3, 0x0c7e, - 0x7004, 0x2060, 0x6024, 0xc0d4, 0x6026, 0x0c7f, 0x684c, 0xd0f4, - 0x0040, 0x1840, 0x6817, 0xffff, 0x6813, 0xffff, 0x0078, 0x17e3, - 0x6824, 0x2050, 0x6818, 0x2060, 0x6830, 0x2040, 0x6034, 0xa0cc, - 0x000f, 0x2009, 0x0011, 0x1078, 0x1855, 0x0040, 0x1853, 0x2009, - 0x0001, 0x1078, 0x1855, 0x2d58, 0x007c, 0x8aff, 0x0040, 0x18ec, - 0xa03e, 0x2730, 0x6850, 0xd0fc, 0x00c0, 0x1877, 0xd0f4, 0x00c0, - 0x1887, 0x0d7e, 0x2804, 0xac68, 0x2900, 0x0079, 0x1867, 0x18ce, - 0x188e, 0x188e, 0x18ce, 0x18ce, 0x18c6, 0x18ce, 0x188e, 0x18ce, - 0x1894, 0x1894, 0x18ce, 0x18ce, 0x18ce, 0x18bd, 0x1894, 0xc0fc, - 0x6852, 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, 0x0d7e, 0xd99c, 0x0040, - 0x18d1, 0x2804, 0xac68, 0x6f08, 0x6e0c, 0x0078, 0x18d1, 0xc0f4, - 0x6852, 0x6b6c, 0x6a70, 0x0d7e, 0x0078, 0x18d8, 0x6b08, 0x6a0c, - 0x6d00, 0x6c04, 0x0078, 0x18d1, 0x7b0c, 0xd3bc, 0x0040, 0x18b5, - 0x7004, 0x0e7e, 0x2070, 0x701c, 0x0e7f, 0xa086, 0x0008, 0x00c0, - 0x18b5, 0x7b08, 0xa39c, 0x0fff, 0x2d20, 0x0d7f, 0x0d7e, 0x6a14, - 0x82ff, 0x00c0, 0x18b0, 0x6810, 0xa302, 0x0048, 0x18b0, 0x6b10, - 0x2011, 0x0000, 0x2468, 0x0078, 0x18b7, 0x6b10, 0x6a14, 0x6d00, - 0x6c04, 0x6f08, 0x6e0c, 0x0078, 0x18d1, 0x0d7f, 0x0d7e, 0x6834, - 0xa084, 0x00ff, 0xa086, 0x001e, 0x00c0, 0x18ce, 0x0d7f, 0x1078, - 0x2026, 0x00c0, 0x1855, 0xa00e, 0x0078, 0x18ec, 0x0d7f, 0x1078, - 0x1332, 0x7b22, 0x7a26, 0x7d32, 0x7c36, 0x7f3a, 0x7e3e, 0x7902, - 0x7000, 0x8000, 0x7002, 0x0d7f, 0x6828, 0xa300, 0x682a, 0x682c, - 0xa201, 0x682e, 0x2300, 0x6b10, 0xa302, 0x6812, 0x2200, 0x6a14, - 0xa203, 0x6816, 0x1078, 0x2026, 0x007c, 0x1078, 0x1332, 0x1078, - 0x1c97, 0x7004, 0x2060, 0x0d7e, 0x6010, 0x2068, 0x7003, 0x0000, - 0x1078, 0x1af4, 0x1078, 0x8d16, 0x0040, 0x190c, 0x6808, 0x8001, - 0x680a, 0x697c, 0x6912, 0x6980, 0x6916, 0x682b, 0xffff, 0x682f, - 0xffff, 0x6850, 0xc0bd, 0x6852, 0x0d7f, 0x1078, 0x8a11, 0x0078, - 0x1adb, 0x1078, 0x1332, 0x127e, 0x2091, 0x2100, 0x007e, 0x017e, - 0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184, 0x0700, - 0x00c0, 0x18ef, 0xa184, 0x0003, 0xa086, 0x0003, 0x0040, 0x1911, - 0x7000, 0x0079, 0x192b, 0x1933, 0x1935, 0x1a34, 0x1ab2, 0x1ac9, - 0x1933, 0x1933, 0x1933, 0x1078, 0x1332, 0x8001, 0x7002, 0xa184, - 0x0880, 0x00c0, 0x194a, 0x8aff, 0x0040, 0x19d4, 0x2009, 0x0001, - 0x1078, 0x1855, 0x0040, 0x1adb, 0x2009, 0x0001, 0x1078, 0x1855, - 0x0078, 0x1adb, 0x7803, 0x0004, 0x7003, 0x0000, 0xd1bc, 0x00c0, - 0x19b2, 0x027e, 0x037e, 0x017e, 0x7808, 0xd0ec, 0x00c0, 0x1962, - 0x7c20, 0x7d24, 0x7e30, 0x7f34, 0x7803, 0x0009, 0x7003, 0x0004, - 0x0078, 0x1964, 0x1078, 0x1bd7, 0x017f, 0xd194, 0x0040, 0x196b, - 0x8aff, 0x0040, 0x19a1, 0x6b28, 0x6a2c, 0x2400, 0x686e, 0xa31a, - 0x2500, 0x6872, 0xa213, 0x6b2a, 0x6a2e, 0x0c7e, 0x7004, 0x2060, - 0x6024, 0xd0f4, 0x00c0, 0x197e, 0x633a, 0x6236, 0x0c7f, 0x2400, - 0x6910, 0xa100, 0x6812, 0x2500, 0x6914, 0xa101, 0x6816, 0x037f, - 0x027f, 0x2600, 0x681e, 0x2700, 0x6822, 0x1078, 0x203f, 0x2a00, - 0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x6850, 0xc0fd, 0x6852, - 0x6808, 0x8001, 0x680a, 0x00c0, 0x19a7, 0x684c, 0xd0e4, 0x0040, - 0x19a7, 0x7004, 0x2060, 0x2009, 0x0048, 0x1078, 0x775c, 0x7000, - 0xa086, 0x0004, 0x0040, 0x1adb, 0x7003, 0x0000, 0x1078, 0x17c1, - 0x0078, 0x1adb, 0x057e, 0x7d0c, 0xd5bc, 0x00c0, 0x19b9, 0x1078, - 0xa58e, 0x057f, 0x1078, 0x1af4, 0x0f7e, 0x7004, 0x2078, 0x1078, - 0x4963, 0x0040, 0x19c6, 0x7824, 0xc0f5, 0x7826, 0x0f7f, 0x682b, - 0xffff, 0x682f, 0xffff, 0x6808, 0x8001, 0x680a, 0x697c, 0x6912, - 0x6980, 0x6916, 0x0078, 0x1adb, 0x7004, 0x0c7e, 0x2060, 0x6024, - 0x0c7f, 0xd0f4, 0x0040, 0x19e1, 0x6808, 0x8001, 0x680a, 0x0078, - 0x19f5, 0x684c, 0xc0f5, 0x684e, 0x7814, 0xa005, 0x00c0, 0x19f9, - 0x7003, 0x0000, 0x6808, 0x8001, 0x680a, 0x00c0, 0x19f5, 0x7004, - 0x2060, 0x2009, 0x0048, 0x1078, 0x775c, 0x1078, 0x17c1, 0x0078, - 0x1adb, 0x7814, 0x6910, 0xa102, 0x6812, 0x6914, 0xa183, 0x0000, - 0x6816, 0x7814, 0x7908, 0xa18c, 0x0fff, 0xa192, 0x0841, 0x00c8, - 0x18ef, 0xa188, 0x0007, 0x8114, 0x8214, 0x8214, 0xa10a, 0x8104, - 0x8004, 0x8004, 0xa20a, 0x810b, 0x810b, 0x810b, 0x1078, 0x1b5e, - 0x7803, 0x0004, 0x780f, 0xffff, 0x7803, 0x0001, 0x7804, 0xd0fc, - 0x0040, 0x1a1e, 0x7803, 0x0002, 0x7803, 0x0004, 0x780f, 0x0076, - 0x7004, 0x7007, 0x0000, 0x2060, 0x2009, 0x0048, 0x1078, 0x775c, - 0x1078, 0x1b92, 0x0040, 0x19f5, 0x8001, 0x7002, 0xd194, 0x0040, - 0x1a46, 0x7804, 0xd0fc, 0x00c0, 0x191b, 0x8aff, 0x0040, 0x1adb, - 0x2009, 0x0001, 0x1078, 0x1855, 0x0078, 0x1adb, 0xa184, 0x0880, - 0x00c0, 0x1a53, 0x8aff, 0x0040, 0x1adb, 0x2009, 0x0001, 0x1078, - 0x1855, 0x0078, 0x1adb, 0x7803, 0x0004, 0x7003, 0x0000, 0xd1bc, - 0x00c0, 0x1a93, 0x027e, 0x037e, 0x7808, 0xd0ec, 0x00c0, 0x1a66, - 0x7803, 0x0009, 0x7003, 0x0004, 0x0078, 0x1a68, 0x1078, 0x1bd7, - 0x6b28, 0x6a2c, 0x1078, 0x203f, 0x0d7e, 0x0f7e, 0x2d78, 0x2804, - 0xac68, 0x6034, 0xd09c, 0x00c0, 0x1a83, 0x6808, 0x2008, 0xa31a, - 0x680c, 0xa213, 0x7810, 0xa100, 0x7812, 0x690c, 0x7814, 0xa101, - 0x7816, 0x0078, 0x1a8f, 0x6810, 0x2008, 0xa31a, 0x6814, 0xa213, - 0x7810, 0xa100, 0x7812, 0x6914, 0x7814, 0xa101, 0x7816, 0x0f7f, - 0x0d7f, 0x0078, 0x196d, 0x057e, 0x7d0c, 0x1078, 0xa58e, 0x057f, - 0x1078, 0x1af4, 0x0f7e, 0x7004, 0x2078, 0x1078, 0x4963, 0x0040, - 0x1aa4, 0x7824, 0xc0f5, 0x7826, 0x0f7f, 0x682b, 0xffff, 0x682f, - 0xffff, 0x6808, 0x8001, 0x680a, 0x697c, 0x6912, 0x6980, 0x6916, - 0x0078, 0x1adb, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0xa00d, - 0x0040, 0x1ac5, 0x6808, 0x8001, 0x680a, 0x00c0, 0x1ac5, 0x7004, - 0x2060, 0x2009, 0x0048, 0x1078, 0x775c, 0x1078, 0x17c1, 0x0078, - 0x1adb, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, 0x6010, - 0xa005, 0x0040, 0x1ac5, 0x2068, 0x6808, 0x8000, 0x680a, 0x6c28, - 0x6b2c, 0x1078, 0x17e0, 0x017f, 0x007f, 0x127f, 0x007c, 0x127e, - 0x2091, 0x2100, 0x7000, 0xa086, 0x0003, 0x00c0, 0x1af2, 0x700c, - 0x7110, 0xa106, 0x0040, 0x1af2, 0x20e1, 0x9028, 0x700f, 0xa9ed, - 0x7013, 0xa9ed, 0x127f, 0x007c, 0x0c7e, 0x1078, 0x1b22, 0x20e1, - 0x9028, 0x700c, 0x7110, 0xa106, 0x0040, 0x1b19, 0x2104, 0xa005, - 0x0040, 0x1b08, 0x2060, 0x6010, 0x2060, 0x6008, 0x8001, 0x600a, - 0xa188, 0x0003, 0xa182, 0xaa08, 0x0048, 0x1b10, 0x2009, 0xa9ed, - 0x7112, 0x700c, 0xa106, 0x00c0, 0x1af9, 0x2011, 0x0008, 0x0078, - 0x1af9, 0x2001, 0x015d, 0x2003, 0x0000, 0x2001, 0x0138, 0x2202, - 0x0c7f, 0x007c, 0x2001, 0x0138, 0x2014, 0x2003, 0x0000, 0x2021, - 0xb015, 0x2001, 0x0141, 0x201c, 0xd3dc, 0x00c0, 0x1b3f, 0x2001, - 0x0109, 0x201c, 0xa39c, 0x0048, 0x00c0, 0x1b3f, 0x2001, 0x0111, - 0x201c, 0x83ff, 0x00c0, 0x1b3f, 0x8421, 0x00c0, 0x1b29, 0x007c, - 0x2011, 0x0201, 0x2009, 0x003c, 0x2204, 0xa005, 0x00c0, 0x1b4c, - 0x8109, 0x00c0, 0x1b44, 0x007c, 0x007c, 0x1078, 0x1b40, 0x0040, - 0x1b55, 0x780c, 0xd0a4, 0x0040, 0x1b5b, 0x1078, 0x1af4, 0xa085, - 0x0001, 0x0078, 0x1b5d, 0x1078, 0x1b92, 0x007c, 0x0e7e, 0x2071, - 0x0200, 0x7808, 0xa084, 0xf000, 0xa10d, 0x1078, 0x1b22, 0x2019, - 0x5000, 0x8319, 0x0040, 0x1b7c, 0x2001, 0xaa08, 0x2004, 0xa086, - 0x0000, 0x0040, 0x1b7c, 0x2001, 0x0021, 0xd0fc, 0x0040, 0x1b69, - 0x1078, 0x1eaa, 0x0078, 0x1b67, 0x20e1, 0x7000, 0x7324, 0x7420, - 0x7028, 0x7028, 0x7426, 0x7037, 0x0001, 0x810f, 0x712e, 0x702f, - 0x0100, 0x7037, 0x0008, 0x7326, 0x7422, 0x2001, 0x0138, 0x2202, - 0x0e7f, 0x007c, 0x027e, 0x2001, 0x015d, 0x2001, 0x0000, 0x7908, - 0xa18c, 0x0fff, 0xa182, 0x0ffd, 0x0048, 0x1ba0, 0x2009, 0x0000, - 0xa190, 0x0007, 0xa294, 0x1ff8, 0x8214, 0x8214, 0x8214, 0x2001, - 0x020a, 0x82ff, 0x0040, 0x1bb5, 0x20e1, 0x6000, 0x200c, 0x200c, - 0x200c, 0x200c, 0x8211, 0x00c0, 0x1bae, 0x20e1, 0x7000, 0x200c, - 0x200c, 0x7003, 0x0000, 0x20e1, 0x6000, 0x2001, 0x0208, 0x200c, - 0x2001, 0x0209, 0x2004, 0xa106, 0x0040, 0x1bd4, 0x1078, 0x1b40, - 0x0040, 0x1bd2, 0x7908, 0xd1ec, 0x00c0, 0x1bd4, 0x790c, 0xd1a4, - 0x0040, 0x1b97, 0x1078, 0x1af4, 0xa006, 0x027f, 0x007c, 0x7c20, - 0x7d24, 0x7e30, 0x7f34, 0x700c, 0x7110, 0xa106, 0x0040, 0x1c69, - 0x7004, 0x017e, 0x210c, 0xa106, 0x017f, 0x0040, 0x1c69, 0x0d7e, - 0x0c7e, 0x216c, 0x2d00, 0xa005, 0x0040, 0x1c67, 0x681c, 0xa086, - 0x0008, 0x0040, 0x1c67, 0x6824, 0xd0d4, 0x00c0, 0x1c67, 0x6810, - 0x2068, 0x6850, 0xd0fc, 0x0040, 0x1c29, 0x8108, 0x2104, 0x6b2c, - 0xa306, 0x00c0, 0x1c67, 0x8108, 0x2104, 0x6a28, 0xa206, 0x00c0, - 0x1c67, 0x6850, 0xc0fc, 0xc0f5, 0x6852, 0x686c, 0x7822, 0x6870, - 0x7826, 0x681c, 0x7832, 0x6820, 0x7836, 0x6818, 0x2060, 0x6034, - 0xd09c, 0x0040, 0x1c24, 0x6830, 0x2004, 0xac68, 0x6808, 0x783a, - 0x680c, 0x783e, 0x0078, 0x1c65, 0xa006, 0x783a, 0x783e, 0x0078, - 0x1c65, 0x8108, 0x2104, 0xa005, 0x00c0, 0x1c67, 0x6b2c, 0xa306, - 0x00c0, 0x1c67, 0x8108, 0x2104, 0xa005, 0x00c0, 0x1c67, 0x6a28, - 0xa206, 0x00c0, 0x1c67, 0x6850, 0xc0f5, 0x6852, 0x6830, 0x2004, - 0x6918, 0xa160, 0xa180, 0x000d, 0x2004, 0xd09c, 0x00c0, 0x1c57, - 0x6008, 0x7822, 0x686e, 0x600c, 0x7826, 0x6872, 0x6000, 0x7832, - 0x6004, 0x7836, 0xa006, 0x783a, 0x783e, 0x0078, 0x1c65, 0x6010, - 0x7822, 0x686e, 0x6014, 0x7826, 0x6872, 0x6000, 0x7832, 0x6004, - 0x7836, 0x6008, 0x783a, 0x600c, 0x783e, 0x7803, 0x0011, 0x0c7f, - 0x0d7f, 0x007c, 0x0f7e, 0x0e7e, 0x017e, 0x027e, 0x2071, 0xa9e7, - 0x2079, 0x0030, 0x2011, 0x0050, 0x7000, 0xa086, 0x0000, 0x0040, - 0x1c92, 0x8211, 0x0040, 0x1c90, 0x2001, 0x0005, 0x2004, 0xd08c, - 0x0040, 0x1c79, 0x7904, 0xa18c, 0x0780, 0x017e, 0x1078, 0x1913, - 0x017f, 0x81ff, 0x00c0, 0x1c90, 0x2011, 0x0050, 0x0078, 0x1c74, - 0xa085, 0x0001, 0x027f, 0x017f, 0x0e7f, 0x0f7f, 0x007c, 0x7803, - 0x0004, 0x2009, 0x0064, 0x7804, 0xd0ac, 0x0040, 0x1ce8, 0x8109, - 0x00c0, 0x1c9b, 0x2009, 0x0100, 0x210c, 0xa18a, 0x0003, 0x1048, - 0x1332, 0x1078, 0x1fca, 0x0e7e, 0x0f7e, 0x2071, 0xa9d6, 0x2079, - 0x0010, 0x7004, 0xa086, 0x0000, 0x0040, 0x1ce0, 0x7800, 0x007e, - 0x7820, 0x007e, 0x7830, 0x007e, 0x7834, 0x007e, 0x7838, 0x007e, - 0x783c, 0x007e, 0x7803, 0x0004, 0x7823, 0x0000, 0x0005, 0x0005, - 0x2079, 0x0030, 0x7804, 0xd0ac, 0x10c0, 0x1332, 0x2079, 0x0010, - 0x007f, 0x783e, 0x007f, 0x783a, 0x007f, 0x7836, 0x007f, 0x7832, - 0x007f, 0x7822, 0x007f, 0x7802, 0x0f7f, 0x0e7f, 0x0078, 0x1ce6, - 0x0f7f, 0x0e7f, 0x7804, 0xd0ac, 0x10c0, 0x1332, 0x1078, 0x639b, - 0x007c, 0x0e7e, 0x2071, 0xaa08, 0x7003, 0x0000, 0x0e7f, 0x007c, - 0x0d7e, 0xa280, 0x0004, 0x206c, 0x694c, 0xd1dc, 0x00c0, 0x1d6b, - 0x6934, 0xa184, 0x0007, 0x0079, 0x1cfd, 0x1d05, 0x1d56, 0x1d05, - 0x1d05, 0x1d05, 0x1d3b, 0x1d18, 0x1d07, 0x1078, 0x1332, 0x684c, - 0xd0b4, 0x0040, 0x1e79, 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, - 0x6812, 0x687c, 0x680a, 0x6880, 0x680e, 0x6958, 0x0078, 0x1d5e, - 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, 0x00c0, 0x1d05, 0x684c, - 0xd0b4, 0x0040, 0x1e79, 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, - 0x6812, 0x687c, 0x680a, 0x6880, 0x680e, 0x6804, 0x681a, 0xa080, - 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x206a, 0x2004, 0x6832, - 0x6958, 0x0078, 0x1d67, 0xa18c, 0x00ff, 0xa186, 0x0015, 0x00c0, - 0x1d6b, 0x684c, 0xd0b4, 0x0040, 0x1e79, 0x6804, 0x681a, 0xa080, - 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x206a, 0x2004, 0x6832, - 0x6958, 0xa006, 0x682e, 0x682a, 0x0078, 0x1d67, 0x684c, 0xd0b4, - 0x0040, 0x18ed, 0x6958, 0xa006, 0x682e, 0x682a, 0x2d00, 0x681a, - 0x6834, 0xa084, 0x000f, 0xa080, 0x206a, 0x2004, 0x6832, 0x6926, - 0x684c, 0xc0dd, 0x684e, 0x0d7f, 0x007c, 0x0f7e, 0x2079, 0x0020, - 0x7804, 0xd0fc, 0x10c0, 0x1eaa, 0x0e7e, 0x0d7e, 0x2071, 0xaa08, - 0x7000, 0xa005, 0x00c0, 0x1df0, 0x0c7e, 0x7206, 0xa280, 0x0004, - 0x205c, 0x7004, 0x2068, 0x7803, 0x0004, 0x6818, 0x0d7e, 0x2068, - 0x686c, 0x7812, 0x6890, 0x0f7e, 0x20e1, 0x9040, 0x2079, 0x0200, - 0x781a, 0x2079, 0x0100, 0x8004, 0x78d6, 0x0f7f, 0x0d7f, 0x2b68, - 0x6824, 0x2050, 0x6818, 0x2060, 0x6830, 0x2040, 0x6034, 0xa0cc, - 0x000f, 0x6908, 0x2001, 0x04fd, 0x2004, 0xa086, 0x0007, 0x0040, - 0x1db2, 0xa184, 0x0007, 0x0040, 0x1db2, 0x017e, 0x2009, 0x0008, - 0xa102, 0x017f, 0xa108, 0x791a, 0x7116, 0x701e, 0x680c, 0xa081, - 0x0000, 0x781e, 0x701a, 0xa006, 0x700e, 0x7012, 0x7004, 0x692c, - 0x6814, 0xa106, 0x00c0, 0x1dc9, 0x6928, 0x6810, 0xa106, 0x0040, - 0x1dd6, 0x037e, 0x047e, 0x6b14, 0x6c10, 0x1078, 0x208a, 0x047f, - 0x037f, 0x0040, 0x1dd6, 0x0c7f, 0x0078, 0x1df0, 0x8aff, 0x00c0, - 0x1dde, 0x0c7f, 0xa085, 0x0001, 0x0078, 0x1df0, 0x127e, 0x2091, - 0x8000, 0x2079, 0x0020, 0x2009, 0x0001, 0x1078, 0x1df4, 0x0040, - 0x1ded, 0x2009, 0x0001, 0x1078, 0x1df4, 0x127f, 0x0c7f, 0xa006, - 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x077e, 0x067e, 0x057e, 0x047e, - 0x037e, 0x027e, 0x8aff, 0x0040, 0x1e72, 0x700c, 0x7214, 0xa23a, - 0x7010, 0x7218, 0xa203, 0x0048, 0x1e71, 0xa705, 0x0040, 0x1e71, - 0xa03e, 0x2730, 0x6850, 0xd0fc, 0x00c0, 0x1e24, 0x0d7e, 0x2804, - 0xac68, 0x2900, 0x0079, 0x1e14, 0x1e53, 0x1e34, 0x1e34, 0x1e53, - 0x1e53, 0x1e4b, 0x1e53, 0x1e34, 0x1e53, 0x1e3a, 0x1e3a, 0x1e53, - 0x1e53, 0x1e53, 0x1e42, 0x1e3a, 0xc0fc, 0x6852, 0x6b6c, 0x6a70, - 0x6d1c, 0x6c20, 0xd99c, 0x0040, 0x1e57, 0x0d7e, 0x2804, 0xac68, - 0x6f08, 0x6e0c, 0x0078, 0x1e56, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, - 0x0078, 0x1e56, 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, - 0x0078, 0x1e56, 0x0d7f, 0x0d7e, 0x6834, 0xa084, 0x00ff, 0xa086, - 0x001e, 0x00c0, 0x1e53, 0x0d7f, 0x1078, 0x2026, 0x00c0, 0x1dfa, - 0xa00e, 0x0078, 0x1e72, 0x0d7f, 0x1078, 0x1332, 0x0d7f, 0x7b22, - 0x7a26, 0x7d32, 0x7c36, 0x7f3a, 0x7e3e, 0x7902, 0x7000, 0x8000, - 0x7002, 0x6828, 0xa300, 0x682a, 0x682c, 0xa201, 0x682e, 0x700c, - 0xa300, 0x700e, 0x7010, 0xa201, 0x7012, 0x1078, 0x2026, 0x0078, - 0x1e72, 0xa006, 0x027f, 0x037f, 0x047f, 0x057f, 0x067f, 0x077f, - 0x007c, 0x1078, 0x1332, 0x027e, 0x2001, 0x0105, 0x2003, 0x0010, - 0x20e1, 0x9040, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, - 0x0d7e, 0x6010, 0x2068, 0x1078, 0x8d16, 0x0040, 0x1e92, 0x6850, - 0xc0bd, 0x6852, 0x0d7f, 0x0c7e, 0x1078, 0x8a11, 0x0c7f, 0x2001, - 0xa9c0, 0x2004, 0xac06, 0x00c0, 0x1ea7, 0x20e1, 0x9040, 0x1078, - 0x738a, 0x2011, 0x0000, 0x1078, 0x70ea, 0x1078, 0x639b, 0x027f, - 0x0078, 0x1f76, 0x127e, 0x2091, 0x2200, 0x007e, 0x017e, 0x0f7e, - 0x0e7e, 0x0d7e, 0x0c7e, 0x2079, 0x0020, 0x2071, 0xaa08, 0x2b68, - 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184, 0x0700, 0x00c0, - 0x1e7b, 0x7000, 0x0079, 0x1ec4, 0x1f76, 0x1ec8, 0x1f43, 0x1f74, - 0x8001, 0x7002, 0xd19c, 0x00c0, 0x1edc, 0x8aff, 0x0040, 0x1efb, - 0x2009, 0x0001, 0x1078, 0x1df4, 0x0040, 0x1f76, 0x2009, 0x0001, - 0x1078, 0x1df4, 0x0078, 0x1f76, 0x7803, 0x0004, 0xd194, 0x0040, - 0x1eec, 0x6850, 0xc0fc, 0x6852, 0x8aff, 0x00c0, 0x1ef1, 0x684c, - 0xc0f5, 0x684e, 0x0078, 0x1ef1, 0x1078, 0x203f, 0x6850, 0xc0fd, - 0x6852, 0x2a00, 0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x7003, - 0x0000, 0x0078, 0x1f76, 0x711c, 0x81ff, 0x0040, 0x1f11, 0x7918, - 0x7922, 0x7827, 0x0000, 0x7803, 0x0001, 0x7000, 0x8000, 0x7002, - 0x700c, 0xa100, 0x700e, 0x7010, 0xa081, 0x0000, 0x7012, 0x0078, - 0x1f76, 0x0f7e, 0x027e, 0x781c, 0x007e, 0x7818, 0x007e, 0x2079, - 0x0100, 0x7a14, 0xa284, 0x0004, 0xa085, 0x0012, 0x7816, 0x037e, - 0x2019, 0x1000, 0x8319, 0x1040, 0x1332, 0x7820, 0xd0bc, 0x00c0, - 0x1f22, 0x037f, 0x79c8, 0x007f, 0xa102, 0x017f, 0x007e, 0x017e, - 0x79c4, 0x007f, 0xa103, 0x78c6, 0x007f, 0x78ca, 0xa284, 0x0004, - 0xa085, 0x0012, 0x7816, 0x027f, 0x0f7f, 0x7803, 0x0008, 0x7003, - 0x0000, 0x0078, 0x1f76, 0x8001, 0x7002, 0xd194, 0x0040, 0x1f58, - 0x7804, 0xd0fc, 0x00c0, 0x1eba, 0xd19c, 0x00c0, 0x1f72, 0x8aff, - 0x0040, 0x1f76, 0x2009, 0x0001, 0x1078, 0x1df4, 0x0078, 0x1f76, - 0x027e, 0x037e, 0x6b28, 0x6a2c, 0x1078, 0x203f, 0x0d7e, 0x2804, - 0xac68, 0x6034, 0xd09c, 0x00c0, 0x1f6b, 0x6808, 0xa31a, 0x680c, - 0xa213, 0x0078, 0x1f6f, 0x6810, 0xa31a, 0x6814, 0xa213, 0x0d7f, - 0x0078, 0x1eec, 0x0078, 0x1eec, 0x1078, 0x1332, 0x0c7f, 0x0d7f, - 0x0e7f, 0x0f7f, 0x017f, 0x007f, 0x127f, 0x007c, 0x0f7e, 0x0e7e, - 0x2071, 0xaa08, 0x7000, 0xa086, 0x0000, 0x0040, 0x1fc7, 0x2079, - 0x0020, 0x017e, 0x2009, 0x0207, 0x210c, 0xd194, 0x0040, 0x1fa4, - 0x2009, 0x020c, 0x210c, 0xa184, 0x0003, 0x0040, 0x1fa4, 0x1078, - 0xa5e2, 0x2001, 0x0133, 0x2004, 0xa005, 0x1040, 0x1332, 0x20e1, - 0x9040, 0x2001, 0x020c, 0x2102, 0x2009, 0x0206, 0x2104, 0x2009, - 0x0203, 0x210c, 0xa106, 0x00c0, 0x1faf, 0x20e1, 0x9040, 0x7804, - 0xd0fc, 0x0040, 0x1f8a, 0x1078, 0x1eaa, 0x7000, 0xa086, 0x0000, - 0x00c0, 0x1f8a, 0x017f, 0x7803, 0x0004, 0x7804, 0xd0ac, 0x00c0, - 0x1fbd, 0x20e1, 0x9040, 0x7803, 0x0002, 0x7003, 0x0000, 0x0e7f, - 0x0f7f, 0x007c, 0x027e, 0x0c7e, 0x0d7e, 0x0e7e, 0x0f7e, 0x2071, - 0xaa08, 0x2079, 0x0020, 0x7000, 0xa086, 0x0000, 0x0040, 0x2003, - 0x7004, 0x2060, 0x6010, 0x2068, 0x1078, 0x8d16, 0x0040, 0x1fed, - 0x6850, 0xc0b5, 0x6852, 0x680c, 0x7a1c, 0xa206, 0x00c0, 0x1fed, - 0x6808, 0x7a18, 0xa206, 0x0040, 0x2009, 0x2001, 0x0105, 0x2003, - 0x0010, 0x20e1, 0x9040, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, - 0x2060, 0x1078, 0x8a11, 0x20e1, 0x9040, 0x1078, 0x738a, 0x2011, - 0x0000, 0x1078, 0x70ea, 0x0f7f, 0x0e7f, 0x0d7f, 0x0c7f, 0x027f, - 0x007c, 0x6810, 0x6a14, 0xa205, 0x00c0, 0x1fed, 0x684c, 0xc0dc, - 0x684e, 0x2c10, 0x1078, 0x1cf0, 0x2001, 0x0105, 0x2003, 0x0010, - 0x20e1, 0x9040, 0x7803, 0x0004, 0x7003, 0x0000, 0x2069, 0xa9b1, - 0x6833, 0x0000, 0x683f, 0x0000, 0x0078, 0x2003, 0x8840, 0x2804, - 0xa005, 0x00c0, 0x203a, 0x6004, 0xa005, 0x0040, 0x203c, 0x681a, - 0x2060, 0x6034, 0xa084, 0x000f, 0xa080, 0x206a, 0x2044, 0x88ff, - 0x1040, 0x1332, 0x8a51, 0x007c, 0x2051, 0x0000, 0x007c, 0x8a50, - 0x8841, 0x2804, 0xa005, 0x00c0, 0x2059, 0x2c00, 0xad06, 0x0040, - 0x204e, 0x6000, 0xa005, 0x00c0, 0x204e, 0x2d00, 0x2060, 0x681a, - 0x6034, 0xa084, 0x000f, 0xa080, 0x207a, 0x2044, 0x88ff, 0x1040, - 0x1332, 0x007c, 0x0000, 0x0011, 0x0015, 0x0019, 0x001d, 0x0021, - 0x0025, 0x0029, 0x0000, 0x000f, 0x0015, 0x001b, 0x0021, 0x0027, - 0x0000, 0x0000, 0x0000, 0x205f, 0x205b, 0x0000, 0x0000, 0x2069, - 0x0000, 0x205f, 0x0000, 0x2066, 0x2063, 0x0000, 0x0000, 0x0000, - 0x2069, 0x2066, 0x0000, 0x2061, 0x2061, 0x0000, 0x0000, 0x2069, - 0x0000, 0x2061, 0x0000, 0x2067, 0x2067, 0x0000, 0x0000, 0x0000, - 0x2069, 0x2067, 0x0a7e, 0x097e, 0x087e, 0x6b2e, 0x6c2a, 0x6858, - 0xa055, 0x0040, 0x212d, 0x2d60, 0x6034, 0xa0cc, 0x000f, 0xa9c0, - 0x206a, 0xa986, 0x0007, 0x0040, 0x20a5, 0xa986, 0x000e, 0x0040, - 0x20a5, 0xa986, 0x000f, 0x00c0, 0x20a9, 0x605c, 0xa422, 0x6060, - 0xa31b, 0x2804, 0xa045, 0x00c0, 0x20b7, 0x0050, 0x20b1, 0x0078, - 0x212d, 0x6004, 0xa065, 0x0040, 0x212d, 0x0078, 0x2094, 0x2804, - 0xa005, 0x0040, 0x20d5, 0xac68, 0xd99c, 0x00c0, 0x20c5, 0x6808, - 0xa422, 0x680c, 0xa31b, 0x0078, 0x20c9, 0x6810, 0xa422, 0x6814, - 0xa31b, 0x0048, 0x20f4, 0x2300, 0xa405, 0x0040, 0x20db, 0x8a51, - 0x0040, 0x212d, 0x8840, 0x0078, 0x20b7, 0x6004, 0xa065, 0x0040, - 0x212d, 0x0078, 0x2094, 0x8a51, 0x0040, 0x212d, 0x8840, 0x2804, - 0xa005, 0x00c0, 0x20ee, 0x6004, 0xa065, 0x0040, 0x212d, 0x6034, - 0xa0cc, 0x000f, 0xa9c0, 0x206a, 0x2804, 0x2040, 0x2b68, 0x6850, - 0xc0fc, 0x6852, 0x0078, 0x2121, 0x8422, 0x8420, 0x831a, 0xa399, - 0x0000, 0x0d7e, 0x2b68, 0x6c6e, 0x6b72, 0x0d7f, 0xd99c, 0x00c0, - 0x210f, 0x6908, 0x2400, 0xa122, 0x690c, 0x2300, 0xa11b, 0x1048, - 0x1332, 0x6800, 0xa420, 0x6804, 0xa319, 0x0078, 0x211b, 0x6910, - 0x2400, 0xa122, 0x6914, 0x2300, 0xa11b, 0x1048, 0x1332, 0x6800, - 0xa420, 0x6804, 0xa319, 0x2b68, 0x6c1e, 0x6b22, 0x6850, 0xc0fd, - 0x6852, 0x2c00, 0x681a, 0x2800, 0x6832, 0x2a00, 0x6826, 0x007f, - 0x007f, 0x007f, 0xa006, 0x0078, 0x2132, 0x087f, 0x097f, 0x0a7f, - 0xa085, 0x0001, 0x007c, 0x2001, 0x0005, 0x2004, 0xa084, 0x0007, - 0x0079, 0x213a, 0x2142, 0x2143, 0x2146, 0x2149, 0x214e, 0x2151, - 0x2156, 0x215b, 0x007c, 0x1078, 0x1eaa, 0x007c, 0x1078, 0x1913, - 0x007c, 0x1078, 0x1913, 0x1078, 0x1eaa, 0x007c, 0x1078, 0x14be, - 0x007c, 0x1078, 0x1eaa, 0x1078, 0x14be, 0x007c, 0x1078, 0x1913, - 0x1078, 0x14be, 0x007c, 0x1078, 0x1913, 0x1078, 0x1eaa, 0x1078, - 0x14be, 0x007c, 0x127e, 0x2091, 0x2300, 0x2079, 0x0200, 0x2071, - 0xac80, 0x2069, 0xa700, 0x2009, 0x0004, 0x7912, 0x7817, 0x0004, - 0x1078, 0x251f, 0x781b, 0x0002, 0x20e1, 0x8700, 0x127f, 0x007c, - 0x127e, 0x2091, 0x2300, 0x781c, 0xa084, 0x0007, 0x0079, 0x2180, - 0x21a4, 0x2188, 0x218c, 0x2190, 0x2196, 0x219a, 0x219e, 0x21a2, - 0x1078, 0x548e, 0x0078, 0x21a4, 0x1078, 0x54da, 0x0078, 0x21a4, - 0x1078, 0x548e, 0x1078, 0x54da, 0x0078, 0x21a4, 0x1078, 0x21a6, - 0x0078, 0x21a4, 0x1078, 0x21a6, 0x0078, 0x21a4, 0x1078, 0x21a6, - 0x0078, 0x21a4, 0x1078, 0x21a6, 0x127f, 0x007c, 0x007e, 0x017e, - 0x027e, 0x1078, 0xa5e2, 0x7930, 0xa184, 0x0003, 0x0040, 0x21c9, - 0x2001, 0xa9c0, 0x2004, 0xa005, 0x0040, 0x21c5, 0x2001, 0x0133, - 0x2004, 0xa005, 0x1040, 0x1332, 0x0c7e, 0x2001, 0xa9c0, 0x2064, - 0x1078, 0x8a11, 0x0c7f, 0x0078, 0x21f2, 0x20e1, 0x9040, 0x0078, - 0x21f2, 0xa184, 0x0030, 0x0040, 0x21da, 0x6a00, 0xa286, 0x0003, - 0x00c0, 0x21d4, 0x0078, 0x21d6, 0x1078, 0x4224, 0x20e1, 0x9010, - 0x0078, 0x21f2, 0xa184, 0x00c0, 0x0040, 0x21ec, 0x0e7e, 0x037e, - 0x047e, 0x057e, 0x2071, 0xa9e7, 0x1078, 0x1af4, 0x057f, 0x047f, - 0x037f, 0x0e7f, 0x0078, 0x21f2, 0xa184, 0x0300, 0x0040, 0x21f2, - 0x20e1, 0x9020, 0x7932, 0x027f, 0x017f, 0x007f, 0x007c, 0x017e, - 0x0e7e, 0x0f7e, 0x2071, 0xa700, 0x7128, 0x2001, 0xa990, 0x2102, - 0x2001, 0xa998, 0x2102, 0xa182, 0x0211, 0x00c8, 0x220b, 0x2009, - 0x0008, 0x0078, 0x2235, 0xa182, 0x0259, 0x00c8, 0x2213, 0x2009, - 0x0007, 0x0078, 0x2235, 0xa182, 0x02c1, 0x00c8, 0x221b, 0x2009, - 0x0006, 0x0078, 0x2235, 0xa182, 0x0349, 0x00c8, 0x2223, 0x2009, - 0x0005, 0x0078, 0x2235, 0xa182, 0x0421, 0x00c8, 0x222b, 0x2009, - 0x0004, 0x0078, 0x2235, 0xa182, 0x0581, 0x00c8, 0x2233, 0x2009, - 0x0003, 0x0078, 0x2235, 0x2009, 0x0002, 0x2079, 0x0200, 0x7912, - 0x7817, 0x0004, 0x1078, 0x251f, 0x0f7f, 0x0e7f, 0x017f, 0x007c, - 0x127e, 0x2091, 0x2200, 0x2061, 0x0100, 0x2071, 0xa700, 0x6024, - 0x6026, 0x6053, 0x0030, 0x6033, 0x00ef, 0x60e7, 0x0000, 0x60eb, - 0x00ef, 0x60e3, 0x0008, 0x604b, 0xf7f7, 0x6043, 0x0000, 0x602f, - 0x0080, 0x602f, 0x0000, 0x6007, 0x0eaf, 0x600f, 0x00ff, 0x602b, - 0x002f, 0x127f, 0x007c, 0x2001, 0xa730, 0x2003, 0x0000, 0x2001, - 0xa72f, 0x2003, 0x0001, 0x007c, 0x127e, 0x2091, 0x2200, 0x007e, - 0x017e, 0x027e, 0x6124, 0xa184, 0x002c, 0x00c0, 0x227b, 0xa184, - 0x0007, 0x0079, 0x2281, 0xa195, 0x0004, 0xa284, 0x0007, 0x0079, - 0x2281, 0x22ad, 0x2289, 0x228d, 0x2291, 0x2297, 0x229b, 0x22a1, - 0x22a7, 0x1078, 0x5c56, 0x0078, 0x22ad, 0x1078, 0x5d45, 0x0078, - 0x22ad, 0x1078, 0x5d45, 0x1078, 0x5c56, 0x0078, 0x22ad, 0x1078, - 0x22b2, 0x0078, 0x22ad, 0x1078, 0x5c56, 0x1078, 0x22b2, 0x0078, - 0x22ad, 0x1078, 0x5d45, 0x1078, 0x22b2, 0x0078, 0x22ad, 0x1078, - 0x5d45, 0x1078, 0x5c56, 0x1078, 0x22b2, 0x027f, 0x017f, 0x007f, - 0x127f, 0x007c, 0x6124, 0xd1ac, 0x0040, 0x23ac, 0x017e, 0x047e, - 0x0c7e, 0x644c, 0xa486, 0xf0f0, 0x00c0, 0x22c5, 0x2061, 0x0100, - 0x644a, 0x6043, 0x0090, 0x6043, 0x0010, 0x74c6, 0xa48c, 0xff00, - 0x7034, 0xd084, 0x0040, 0x22dd, 0xa186, 0xf800, 0x00c0, 0x22dd, - 0x703c, 0xd084, 0x00c0, 0x22dd, 0xc085, 0x703e, 0x037e, 0x2418, - 0x2011, 0x8016, 0x1078, 0x361b, 0x037f, 0xa196, 0xff00, 0x0040, - 0x231f, 0x6030, 0xa084, 0x00ff, 0x810f, 0xa116, 0x0040, 0x231f, - 0x7130, 0xd184, 0x00c0, 0x231f, 0x2011, 0xa753, 0x2214, 0xd2ec, - 0x0040, 0x22fa, 0xc18d, 0x7132, 0x2011, 0xa753, 0x2214, 0xd2ac, - 0x00c0, 0x231f, 0x6240, 0xa294, 0x0010, 0x0040, 0x2306, 0x6248, - 0xa294, 0xff00, 0xa296, 0xff00, 0x0040, 0x231f, 0x7030, 0xd08c, - 0x0040, 0x2371, 0x7034, 0xd08c, 0x00c0, 0x2316, 0x2001, 0xa70c, - 0x200c, 0xd1ac, 0x00c0, 0x2371, 0xc1ad, 0x2102, 0x037e, 0x73c4, - 0x2011, 0x8013, 0x1078, 0x361b, 0x037f, 0x0078, 0x2371, 0x7034, - 0xd08c, 0x00c0, 0x232b, 0x2001, 0xa70c, 0x200c, 0xd1ac, 0x00c0, - 0x2371, 0xc1ad, 0x2102, 0x037e, 0x73c4, 0x2011, 0x8013, 0x1078, - 0x361b, 0x037f, 0x7130, 0xc185, 0x7132, 0x2011, 0xa753, 0x220c, - 0xd1a4, 0x0040, 0x2355, 0x017e, 0x2009, 0x0001, 0x2011, 0x0100, - 0x1078, 0x5bf1, 0x2019, 0x000e, 0x1078, 0xa1a5, 0xa484, 0x00ff, - 0xa080, 0x29c0, 0x200c, 0xa18c, 0xff00, 0x810f, 0x8127, 0xa006, - 0x2009, 0x000e, 0x1078, 0xa22d, 0x017f, 0xd1ac, 0x00c0, 0x2362, - 0x017e, 0x2009, 0x0000, 0x2019, 0x0004, 0x1078, 0x284f, 0x017f, - 0x0078, 0x2371, 0x157e, 0x20a9, 0x007f, 0x2009, 0x0000, 0x1078, - 0x45c4, 0x00c0, 0x236d, 0x1078, 0x42f8, 0x8108, 0x00f0, 0x2367, - 0x157f, 0x0c7f, 0x047f, 0x0f7e, 0x2079, 0xa9c4, 0x783c, 0xa086, - 0x0000, 0x0040, 0x2383, 0x6027, 0x0004, 0x783f, 0x0000, 0x2079, - 0x0140, 0x7803, 0x0000, 0x0f7f, 0x2011, 0x0003, 0x1078, 0x70e0, - 0x2011, 0x0002, 0x1078, 0x70ea, 0x1078, 0x6fc4, 0x037e, 0x2019, - 0x0000, 0x1078, 0x7058, 0x037f, 0x60e3, 0x0000, 0x017f, 0x2001, - 0xa700, 0x2014, 0xa296, 0x0004, 0x00c0, 0x23a4, 0xd19c, 0x00c0, - 0x23ac, 0x6228, 0xc29d, 0x622a, 0x2003, 0x0001, 0x2001, 0xa722, - 0x2003, 0x0000, 0x6027, 0x0020, 0xd194, 0x0040, 0x2490, 0x0f7e, - 0x2079, 0xa9c4, 0x783c, 0xa086, 0x0001, 0x00c0, 0x23d0, 0x017e, - 0x6027, 0x0004, 0x783f, 0x0000, 0x2079, 0x0140, 0x7803, 0x1000, - 0x7803, 0x0000, 0x2079, 0xa9b1, 0x7807, 0x0000, 0x7833, 0x0000, - 0x1078, 0x62d1, 0x1078, 0x639b, 0x017f, 0x0f7f, 0x0078, 0x2490, - 0x0f7f, 0x017e, 0x3900, 0xa082, 0xaae3, 0x00c8, 0x23db, 0x017e, - 0x1078, 0x747a, 0x017f, 0x6220, 0xd2b4, 0x0040, 0x2446, 0x1078, - 0x5acb, 0x1078, 0x6e0f, 0x6027, 0x0004, 0x0f7e, 0x2019, 0xa9ba, - 0x2304, 0xa07d, 0x0040, 0x241c, 0x7804, 0xa086, 0x0032, 0x00c0, - 0x241c, 0x0d7e, 0x0c7e, 0x0e7e, 0x2069, 0x0140, 0x618c, 0x6288, - 0x7818, 0x608e, 0x7808, 0x608a, 0x6043, 0x0002, 0x2001, 0x0003, - 0x8001, 0x00c0, 0x2400, 0x6043, 0x0000, 0x6803, 0x1000, 0x6803, - 0x0000, 0x618e, 0x628a, 0x1078, 0x61cd, 0x1078, 0x62d1, 0x7810, - 0x2070, 0x7037, 0x0103, 0x2f60, 0x1078, 0x772d, 0x0e7f, 0x0c7f, - 0x0d7f, 0x0f7f, 0x017f, 0x007c, 0x0f7f, 0x0d7e, 0x2069, 0x0140, - 0x6804, 0xa084, 0x4000, 0x0040, 0x2429, 0x6803, 0x1000, 0x6803, - 0x0000, 0x0d7f, 0x0c7e, 0x2061, 0xa9b1, 0x6028, 0xa09a, 0x00c8, - 0x00c8, 0x2439, 0x8000, 0x602a, 0x0c7f, 0x1078, 0x6e01, 0x0078, - 0x248f, 0x2019, 0xa9ba, 0x2304, 0xa065, 0x0040, 0x2443, 0x2009, - 0x0027, 0x1078, 0x775c, 0x0c7f, 0x0078, 0x248f, 0xd2bc, 0x0040, - 0x248f, 0x1078, 0x5ad8, 0x6017, 0x0010, 0x6027, 0x0004, 0x0d7e, - 0x2069, 0x0140, 0x6804, 0xa084, 0x4000, 0x0040, 0x245b, 0x6803, - 0x1000, 0x6803, 0x0000, 0x0d7f, 0x0c7e, 0x2061, 0xa9b1, 0x6044, - 0xa09a, 0x00c8, 0x00c8, 0x247e, 0x8000, 0x6046, 0x603c, 0x0c7f, - 0xa005, 0x0040, 0x248f, 0x2009, 0x07d0, 0x1078, 0x5ad0, 0xa080, - 0x0007, 0x2004, 0xa086, 0x0006, 0x00c0, 0x247a, 0x6017, 0x0012, - 0x0078, 0x248f, 0x6017, 0x0016, 0x0078, 0x248f, 0x037e, 0x2019, - 0x0001, 0x1078, 0x7058, 0x037f, 0x2019, 0xa9c0, 0x2304, 0xa065, - 0x0040, 0x248e, 0x2009, 0x004f, 0x1078, 0x775c, 0x0c7f, 0x017f, - 0xd19c, 0x0040, 0x24e4, 0x7034, 0xd0ac, 0x00c0, 0x24c1, 0x017e, - 0x157e, 0x6027, 0x0008, 0x602f, 0x0020, 0x20a9, 0x000a, 0x00f0, - 0x249f, 0x602f, 0x0000, 0x6150, 0xa185, 0x1400, 0x6052, 0x20a9, - 0x0320, 0x00e0, 0x24a9, 0x2091, 0x6000, 0x6020, 0xd09c, 0x00c0, - 0x24b8, 0x157f, 0x6152, 0x017f, 0x6027, 0x0008, 0x0078, 0x24e4, - 0x1078, 0x2577, 0x00f0, 0x24a9, 0x157f, 0x6152, 0x017f, 0x6027, - 0x0008, 0x017e, 0x6028, 0xc09c, 0x602a, 0x2011, 0x0003, 0x1078, - 0x70e0, 0x2011, 0x0002, 0x1078, 0x70ea, 0x1078, 0x6fc4, 0x037e, - 0x2019, 0x0000, 0x1078, 0x7058, 0x037f, 0x60e3, 0x0000, 0x1078, - 0xa5bd, 0x1078, 0xa5db, 0x2001, 0xa700, 0x2003, 0x0004, 0x6027, - 0x0008, 0x1078, 0x1246, 0x017f, 0xa18c, 0xffd0, 0x6126, 0x007c, - 0x007e, 0x017e, 0x027e, 0x0e7e, 0x0f7e, 0x127e, 0x2091, 0x8000, - 0x2071, 0xa700, 0x71bc, 0x70be, 0xa116, 0x0040, 0x2518, 0x81ff, - 0x0040, 0x2500, 0x2011, 0x8011, 0x1078, 0x361b, 0x0078, 0x2518, - 0x2011, 0x8012, 0x1078, 0x361b, 0x2001, 0xa772, 0x2004, 0xd0fc, - 0x00c0, 0x2518, 0x037e, 0x0c7e, 0x1078, 0x6f9f, 0x2061, 0x0100, - 0x2019, 0x0028, 0x2009, 0x0000, 0x1078, 0x284f, 0x0c7f, 0x037f, - 0x127f, 0x0f7f, 0x0e7f, 0x027f, 0x017f, 0x007f, 0x007c, 0x0c7e, - 0x0f7e, 0x007e, 0x027e, 0x2061, 0x0100, 0xa190, 0x253b, 0x2204, - 0x60f2, 0x2011, 0x2548, 0x6000, 0xa082, 0x0003, 0x00c8, 0x2534, - 0x2001, 0x00ff, 0x0078, 0x2535, 0x2204, 0x60ee, 0x027f, 0x007f, - 0x0f7f, 0x0c7f, 0x007c, 0x0840, 0x0840, 0x0840, 0x0580, 0x0420, - 0x0348, 0x02c0, 0x0258, 0x0210, 0x01a8, 0x01a8, 0x01a8, 0x01a8, - 0x0140, 0x00f8, 0x00d0, 0x00b0, 0x00a0, 0x2028, 0xa18c, 0x00ff, - 0x2130, 0xa094, 0xff00, 0x00c0, 0x2558, 0x81ff, 0x0040, 0x255c, - 0x1078, 0x5761, 0x0078, 0x2563, 0xa080, 0x29c0, 0x200c, 0xa18c, - 0xff00, 0x810f, 0xa006, 0x007c, 0xa080, 0x29c0, 0x200c, 0xa18c, - 0x00ff, 0x007c, 0x0c7e, 0x2061, 0xa700, 0x6030, 0x0040, 0x2573, - 0xc09d, 0x0078, 0x2574, 0xc09c, 0x6032, 0x0c7f, 0x007c, 0x007e, - 0x157e, 0x0f7e, 0x2079, 0x0100, 0x20a9, 0x000a, 0x7854, 0xd08c, - 0x00c0, 0x2584, 0x00f0, 0x257e, 0x0f7f, 0x157f, 0x007f, 0x007c, - 0x0c7e, 0x007e, 0x2061, 0x0100, 0x6030, 0x007e, 0x6048, 0x007e, - 0x60e4, 0x007e, 0x60e8, 0x007e, 0x6050, 0x007e, 0x60f0, 0x007e, - 0x60ec, 0x007e, 0x600c, 0x007e, 0x6004, 0x007e, 0x6028, 0x007e, - 0x60e0, 0x007e, 0x602f, 0x0100, 0x602f, 0x0000, 0x0005, 0x0005, - 0x0005, 0x0005, 0x602f, 0x0040, 0x602f, 0x0000, 0x007f, 0x60e2, - 0x007f, 0x602a, 0x007f, 0x6006, 0x007f, 0x600e, 0x007f, 0x60ee, - 0x007f, 0x60f2, 0x007f, 0x6052, 0x007f, 0x60ea, 0x007f, 0x60e6, - 0x007f, 0x604a, 0x007f, 0x6032, 0x007f, 0x0c7f, 0x007c, 0x25e7, - 0x25eb, 0x25ef, 0x25f5, 0x25fb, 0x2601, 0x2607, 0x260f, 0x2617, - 0x261d, 0x2623, 0x262b, 0x2633, 0x263b, 0x2643, 0x264d, 0x2657, - 0x2657, 0x2657, 0x2657, 0x2657, 0x2657, 0x2657, 0x2657, 0x2657, - 0x2657, 0x2657, 0x2657, 0x2657, 0x2657, 0x2657, 0x2657, 0x107e, - 0x007e, 0x0078, 0x2670, 0x107e, 0x007e, 0x0078, 0x2670, 0x107e, - 0x007e, 0x1078, 0x226c, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078, - 0x226c, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078, 0x2133, 0x0078, - 0x2670, 0x107e, 0x007e, 0x1078, 0x2133, 0x0078, 0x2670, 0x107e, - 0x007e, 0x1078, 0x226c, 0x1078, 0x2133, 0x0078, 0x2670, 0x107e, - 0x007e, 0x1078, 0x226c, 0x1078, 0x2133, 0x0078, 0x2670, 0x107e, - 0x007e, 0x1078, 0x2178, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078, - 0x2178, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078, 0x226c, 0x1078, - 0x2178, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078, 0x226c, 0x1078, - 0x2178, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078, 0x2133, 0x1078, - 0x2178, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078, 0x2133, 0x1078, - 0x2178, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078, 0x226c, 0x1078, - 0x2133, 0x1078, 0x2178, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078, - 0x226c, 0x1078, 0x2133, 0x1078, 0x2178, 0x0078, 0x2670, 0x0005, - 0x0078, 0x2657, 0xb084, 0x003c, 0x8004, 0x8004, 0x0079, 0x2660, - 0x2670, 0x25ed, 0x25f1, 0x25f7, 0x25fd, 0x2603, 0x2609, 0x2611, - 0x2619, 0x261f, 0x2625, 0x262d, 0x2635, 0x263d, 0x2645, 0x264f, - 0x0008, 0x265a, 0x007f, 0x107f, 0x2091, 0x8001, 0x007c, 0x0c7e, - 0x027e, 0x047e, 0x2021, 0x0000, 0x1078, 0x4967, 0x00c0, 0x2772, - 0x70cc, 0xd09c, 0x0040, 0x268e, 0xd084, 0x00c0, 0x268e, 0xd0bc, - 0x00c0, 0x2772, 0x1078, 0x2776, 0x0078, 0x2772, 0xd0cc, 0x00c0, - 0x2772, 0xd094, 0x0040, 0x2698, 0x7097, 0xffff, 0x0078, 0x2772, - 0x2001, 0x010c, 0x203c, 0x7284, 0xd284, 0x0040, 0x2701, 0xd28c, - 0x00c0, 0x2701, 0x037e, 0x7394, 0xa38e, 0xffff, 0x0040, 0x26ab, - 0x83ff, 0x00c0, 0x26ad, 0x2019, 0x0001, 0x8314, 0xa2e0, 0xadc0, - 0x2c04, 0xa38c, 0x0001, 0x0040, 0x26ba, 0xa084, 0xff00, 0x8007, - 0x0078, 0x26bc, 0xa084, 0x00ff, 0xa70e, 0x0040, 0x26f6, 0xa08e, - 0x0000, 0x0040, 0x26f6, 0xa08e, 0x00ff, 0x00c0, 0x26d3, 0x7230, - 0xd284, 0x00c0, 0x26fc, 0x7284, 0xc28d, 0x7286, 0x7097, 0xffff, - 0x037f, 0x0078, 0x2701, 0x2009, 0x0000, 0x1078, 0x254d, 0x1078, - 0x455c, 0x00c0, 0x26f9, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, - 0x00c0, 0x26f0, 0x7030, 0xd08c, 0x0040, 0x26ea, 0x6000, 0xd0bc, - 0x0040, 0x26f0, 0x1078, 0x278c, 0x0040, 0x26f9, 0x0078, 0x26f6, - 0x1078, 0x28c4, 0x1078, 0x27b9, 0x0040, 0x26f9, 0x8318, 0x0078, - 0x26ad, 0x7396, 0x0078, 0x26fe, 0x7097, 0xffff, 0x037f, 0x0078, - 0x2772, 0xa780, 0x29c0, 0x203c, 0xa7bc, 0xff00, 0x873f, 0x2041, - 0x007e, 0x7094, 0xa096, 0xffff, 0x00c0, 0x2713, 0x2009, 0x0000, - 0x28a8, 0x0078, 0x271f, 0xa812, 0x0048, 0x271b, 0x2008, 0xa802, - 0x20a8, 0x0078, 0x271f, 0x7097, 0xffff, 0x0078, 0x2772, 0x2700, - 0x157e, 0x017e, 0xa106, 0x0040, 0x2766, 0xc484, 0x1078, 0x45c4, - 0x0040, 0x2730, 0x1078, 0x455c, 0x00c0, 0x276f, 0x0078, 0x2731, - 0xc485, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x2740, - 0x7030, 0xd08c, 0x0040, 0x275e, 0x6000, 0xd0bc, 0x00c0, 0x275e, - 0x7284, 0xd28c, 0x0040, 0x2756, 0x6004, 0xa084, 0x00ff, 0xa082, - 0x0006, 0x0048, 0x2766, 0xd484, 0x00c0, 0x2752, 0x1078, 0x457f, - 0x0078, 0x2754, 0x1078, 0x298e, 0x0078, 0x2766, 0x1078, 0x28c4, - 0x1078, 0x27b9, 0x0040, 0x276f, 0x0078, 0x2766, 0x1078, 0x2959, - 0x0040, 0x2766, 0x1078, 0x278c, 0x0040, 0x276f, 0x017f, 0x8108, - 0x157f, 0x00f0, 0x271f, 0x7097, 0xffff, 0x0078, 0x2772, 0x017f, - 0x157f, 0x7196, 0x047f, 0x027f, 0x0c7f, 0x007c, 0x0c7e, 0x017e, - 0x7097, 0x0001, 0x2009, 0x007e, 0x1078, 0x455c, 0x00c0, 0x2789, - 0x1078, 0x28c4, 0x1078, 0x27b9, 0x0040, 0x2789, 0x70cc, 0xc0bd, - 0x70ce, 0x017f, 0x0c7f, 0x007c, 0x017e, 0x077e, 0x0d7e, 0x0c7e, - 0x2c68, 0x2001, 0xa757, 0x2004, 0xa084, 0x00ff, 0x6842, 0x1078, - 0x76c7, 0x0040, 0x27b4, 0x2d00, 0x601a, 0x601f, 0x0001, 0x2001, - 0x0000, 0x1078, 0x44ee, 0x2001, 0x0000, 0x1078, 0x4502, 0x127e, - 0x2091, 0x8000, 0x7090, 0x8000, 0x7092, 0x127f, 0x2009, 0x0004, - 0x1078, 0x775c, 0xa085, 0x0001, 0x0c7f, 0x0d7f, 0x077f, 0x017f, - 0x007c, 0x017e, 0x077e, 0x0d7e, 0x0c7e, 0x2c68, 0x2001, 0xa757, - 0x2004, 0xa084, 0x00ff, 0x6842, 0x1078, 0x9197, 0x0040, 0x27f2, - 0x2d00, 0x601a, 0x6800, 0xc0c4, 0x6802, 0x68a0, 0xa086, 0x007e, - 0x0040, 0x27db, 0x6804, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, - 0x27db, 0x1078, 0x2880, 0x601f, 0x0001, 0x2001, 0x0000, 0x1078, - 0x44ee, 0x2001, 0x0002, 0x1078, 0x4502, 0x127e, 0x2091, 0x8000, - 0x7090, 0x8000, 0x7092, 0x127f, 0x2009, 0x0002, 0x1078, 0x775c, - 0xa085, 0x0001, 0x0c7f, 0x0d7f, 0x077f, 0x017f, 0x007c, 0x0c7e, - 0x027e, 0x2009, 0x0080, 0x1078, 0x455c, 0x00c0, 0x2805, 0x1078, - 0x2808, 0x0040, 0x2805, 0x70d3, 0xffff, 0x027f, 0x0c7f, 0x007c, - 0x017e, 0x077e, 0x0d7e, 0x0c7e, 0x2c68, 0x1078, 0x76c7, 0x0040, - 0x282a, 0x2d00, 0x601a, 0x601f, 0x0001, 0x2001, 0x0000, 0x1078, - 0x44ee, 0x2001, 0x0002, 0x1078, 0x4502, 0x127e, 0x2091, 0x8000, - 0x70d4, 0x8000, 0x70d6, 0x127f, 0x2009, 0x0002, 0x1078, 0x775c, - 0xa085, 0x0001, 0x0c7f, 0x0d7f, 0x077f, 0x017f, 0x007c, 0x0c7e, - 0x0d7e, 0x127e, 0x2091, 0x8000, 0x2009, 0x007f, 0x1078, 0x455c, - 0x00c0, 0x284b, 0x2c68, 0x1078, 0x76c7, 0x0040, 0x284b, 0x2d00, - 0x601a, 0x6312, 0x601f, 0x0001, 0x620a, 0x2009, 0x0022, 0x1078, - 0x775c, 0xa085, 0x0001, 0x127f, 0x0d7f, 0x0c7f, 0x007c, 0x0e7e, - 0x0c7e, 0x067e, 0x037e, 0x027e, 0x1078, 0x5f0e, 0x1078, 0x5eae, - 0x1078, 0x8068, 0x2130, 0x81ff, 0x0040, 0x2864, 0x20a9, 0x007e, - 0x2009, 0x0000, 0x0078, 0x2868, 0x20a9, 0x007f, 0x2009, 0x0000, - 0x017e, 0x1078, 0x45c4, 0x00c0, 0x2871, 0x1078, 0x47e9, 0x1078, - 0x42f8, 0x017f, 0x8108, 0x00f0, 0x2868, 0x86ff, 0x00c0, 0x287a, - 0x1078, 0x119b, 0x027f, 0x037f, 0x067f, 0x0c7f, 0x0e7f, 0x007c, - 0x0e7e, 0x0c7e, 0x037e, 0x027e, 0x017e, 0x6218, 0x2270, 0x72a0, - 0x027e, 0x2019, 0x0029, 0x1078, 0x5f01, 0x077e, 0x2039, 0x0000, - 0x1078, 0x5e0a, 0x2c08, 0x1078, 0x9f9b, 0x077f, 0x017f, 0x2e60, - 0x1078, 0x47e9, 0x6210, 0x6314, 0x1078, 0x42f8, 0x6212, 0x6316, - 0x017f, 0x027f, 0x037f, 0x0c7f, 0x0e7f, 0x007c, 0x0e7e, 0x007e, - 0x6018, 0xa080, 0x0028, 0x2004, 0xd0bc, 0x00c0, 0x28ba, 0x2071, - 0xa700, 0x7090, 0xa005, 0x0040, 0x28b7, 0x8001, 0x7092, 0x007f, - 0x0e7f, 0x007c, 0x2071, 0xa700, 0x70d4, 0xa005, 0x0040, 0x28b7, - 0x8001, 0x70d6, 0x0078, 0x28b7, 0x6000, 0xc08c, 0x6002, 0x007c, - 0x0f7e, 0x0e7e, 0x0c7e, 0x037e, 0x027e, 0x017e, 0x157e, 0x2178, - 0x81ff, 0x00c0, 0x28d7, 0x20a9, 0x0001, 0x0078, 0x28f2, 0x2001, - 0xa753, 0x2004, 0xd0c4, 0x0040, 0x28ee, 0xd0a4, 0x0040, 0x28ee, - 0x047e, 0x6018, 0xa080, 0x0028, 0x2024, 0xa4a4, 0x00ff, 0x8427, - 0xa006, 0x2009, 0x002d, 0x1078, 0xa22d, 0x047f, 0x20a9, 0x00ff, - 0x2011, 0x0000, 0x027e, 0xa28e, 0x007e, 0x0040, 0x2936, 0xa28e, - 0x007f, 0x0040, 0x2936, 0xa28e, 0x0080, 0x0040, 0x2936, 0xa288, - 0xa835, 0x210c, 0x81ff, 0x0040, 0x2936, 0x8fff, 0x1040, 0x2942, - 0x0c7e, 0x2160, 0x2001, 0x0001, 0x1078, 0x4972, 0x0c7f, 0x2019, - 0x0029, 0x1078, 0x5f01, 0x077e, 0x2039, 0x0000, 0x1078, 0x5e0a, - 0x0c7e, 0x027e, 0x2160, 0x6204, 0xa294, 0x00ff, 0xa286, 0x0006, - 0x00c0, 0x2926, 0x6007, 0x0404, 0x0078, 0x292b, 0x2001, 0x0004, - 0x8007, 0xa215, 0x6206, 0x027f, 0x0c7f, 0x017e, 0x2c08, 0x1078, - 0x9f9b, 0x017f, 0x077f, 0x2160, 0x1078, 0x47e9, 0x027f, 0x8210, - 0x00f0, 0x28f2, 0x157f, 0x017f, 0x027f, 0x037f, 0x0c7f, 0x0e7f, - 0x0f7f, 0x007c, 0x047e, 0x027e, 0x017e, 0x2001, 0xa753, 0x2004, - 0xd0c4, 0x0040, 0x2955, 0xd0a4, 0x0040, 0x2955, 0xa006, 0x2220, - 0x8427, 0x2009, 0x0029, 0x1078, 0xa22d, 0x017f, 0x027f, 0x047f, - 0x007c, 0x017e, 0x027e, 0x037e, 0x0c7e, 0x7284, 0x82ff, 0x0040, - 0x2987, 0xa290, 0xa753, 0x2214, 0xd2ac, 0x00c0, 0x2987, 0x2100, - 0x1078, 0x2564, 0x81ff, 0x0040, 0x2989, 0x2019, 0x0001, 0x8314, - 0xa2e0, 0xadc0, 0x2c04, 0xd384, 0x0040, 0x297b, 0xa084, 0xff00, - 0x8007, 0x0078, 0x297d, 0xa084, 0x00ff, 0xa116, 0x0040, 0x2989, - 0xa096, 0x00ff, 0x0040, 0x2987, 0x8318, 0x0078, 0x296f, 0xa085, - 0x0001, 0x0c7f, 0x037f, 0x027f, 0x017f, 0x007c, 0x017e, 0x0c7e, - 0x127e, 0x2091, 0x8000, 0x017e, 0x027e, 0x037e, 0x2110, 0x027e, - 0x2019, 0x0029, 0x1078, 0x73d0, 0x027f, 0x1078, 0xa501, 0x037f, - 0x027f, 0x017f, 0xa180, 0xa835, 0x2004, 0xa065, 0x0040, 0x29b7, - 0x017e, 0x0c7e, 0x1078, 0x9197, 0x017f, 0x1040, 0x1332, 0x611a, - 0x1078, 0x2880, 0x1078, 0x772d, 0x017f, 0x1078, 0x457f, 0x127f, - 0x0c7f, 0x017f, 0x007c, 0x2001, 0xa733, 0x2004, 0xd0cc, 0x007c, - 0x7eef, 0x7de8, 0x7ce4, 0x80e2, 0x7be1, 0x80e0, 0x80dc, 0x80da, - 0x7ad9, 0x80d6, 0x80d5, 0x80d4, 0x80d3, 0x80d2, 0x80d1, 0x79ce, - 0x78cd, 0x80cc, 0x80cb, 0x80ca, 0x80c9, 0x80c7, 0x80c6, 0x77c5, - 0x76c3, 0x80bc, 0x80ba, 0x75b9, 0x80b6, 0x74b5, 0x73b4, 0x72b3, - 0x80b2, 0x80b1, 0x80ae, 0x71ad, 0x80ac, 0x70ab, 0x6faa, 0x6ea9, - 0x80a7, 0x6da6, 0x6ca5, 0x6ba3, 0x6a9f, 0x699e, 0x689d, 0x809b, - 0x8098, 0x6797, 0x6690, 0x658f, 0x6488, 0x6384, 0x6282, 0x8081, - 0x8080, 0x617c, 0x607a, 0x8079, 0x5f76, 0x8075, 0x8074, 0x8073, - 0x8072, 0x8071, 0x806e, 0x5e6d, 0x806c, 0x5d6b, 0x5c6a, 0x5b69, - 0x8067, 0x5a66, 0x5965, 0x5863, 0x575c, 0x565a, 0x5559, 0x8056, - 0x8055, 0x5454, 0x5353, 0x5252, 0x5151, 0x504e, 0x4f4d, 0x804c, - 0x804b, 0x4e4a, 0x4d49, 0x8047, 0x4c46, 0x8045, 0x8043, 0x803c, - 0x803a, 0x8039, 0x8036, 0x4b35, 0x8034, 0x4a33, 0x4932, 0x4831, - 0x802e, 0x472d, 0x462c, 0x452b, 0x442a, 0x4329, 0x4227, 0x8026, - 0x8025, 0x4123, 0x401f, 0x3f1e, 0x3e1d, 0x3d1b, 0x3c18, 0x8017, - 0x8010, 0x3b0f, 0x3a08, 0x8004, 0x3902, 0x8001, 0x8000, 0x8000, - 0x3800, 0x3700, 0x3600, 0x8000, 0x3500, 0x8000, 0x8000, 0x8000, - 0x3400, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3300, - 0x3200, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3100, - 0x3000, 0x8000, 0x8000, 0x2f00, 0x8000, 0x2e00, 0x2d00, 0x2c00, - 0x8000, 0x8000, 0x8000, 0x2b00, 0x8000, 0x2a00, 0x2900, 0x2800, - 0x8000, 0x2700, 0x2600, 0x2500, 0x2400, 0x2300, 0x2200, 0x8000, - 0x8000, 0x2100, 0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00, 0x8000, - 0x8000, 0x1b00, 0x1a00, 0x8000, 0x1900, 0x8000, 0x8000, 0x8000, - 0x8000, 0x8000, 0x8000, 0x1800, 0x8000, 0x1700, 0x1600, 0x1500, - 0x8000, 0x1400, 0x1300, 0x1200, 0x1100, 0x1000, 0x0f00, 0x8000, - 0x8000, 0x0e00, 0x0d00, 0x0c00, 0x0b00, 0x0a00, 0x0900, 0x8000, - 0x8000, 0x0800, 0x0700, 0x8000, 0x0600, 0x8000, 0x8000, 0x8000, - 0x0500, 0x0400, 0x0300, 0x8000, 0x0200, 0x8000, 0x8000, 0x8000, - 0x0100, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x0000, - 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, - 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, - 0x2071, 0xa782, 0x7003, 0x0002, 0xa006, 0x7012, 0x7016, 0x703a, - 0x703e, 0x7033, 0xa792, 0x7037, 0xa792, 0x7007, 0x0001, 0x2061, - 0xa7d2, 0x6003, 0x0002, 0x007c, 0x0090, 0x2ae7, 0x0068, 0x2ae7, - 0x2071, 0xa782, 0x2b78, 0x7818, 0xd084, 0x00c0, 0x2ae7, 0x2a60, - 0x7820, 0xa08e, 0x0069, 0x00c0, 0x2bd7, 0x0079, 0x2b6b, 0x007c, - 0x2071, 0xa782, 0x7004, 0x0079, 0x2aed, 0x2af1, 0x2af2, 0x2afc, - 0x2b0e, 0x007c, 0x0090, 0x2afb, 0x0068, 0x2afb, 0x2b78, 0x7818, - 0xd084, 0x0040, 0x2b1a, 0x007c, 0x2b78, 0x2061, 0xa7d2, 0x6008, - 0xa08e, 0x0100, 0x0040, 0x2b09, 0xa086, 0x0200, 0x0040, 0x2bcf, - 0x007c, 0x7014, 0x2068, 0x2a60, 0x7018, 0x007a, 0x7010, 0x2068, - 0x6834, 0xa086, 0x0103, 0x0040, 0x2b16, 0x007c, 0x2a60, 0x2b78, - 0x7018, 0x007a, 0x2a60, 0x7820, 0xa08a, 0x0040, 0x00c8, 0x2b23, - 0x61bc, 0x0079, 0x2b2b, 0x2100, 0xa08a, 0x003f, 0x00c8, 0x2bcb, - 0x61bc, 0x0079, 0x2b6b, 0x2bad, 0x2bdf, 0x2be7, 0x2beb, 0x2bf3, - 0x2bf9, 0x2bfd, 0x2c09, 0x2c0d, 0x2c17, 0x2c1b, 0x2bcb, 0x2bcb, - 0x2bcb, 0x2c1f, 0x2bcb, 0x2c2f, 0x2c46, 0x2c5d, 0x2cdd, 0x2ce2, - 0x2d0f, 0x2d69, 0x2d7a, 0x2d98, 0x2dd9, 0x2de3, 0x2df0, 0x2e03, - 0x2e22, 0x2e2b, 0x2e68, 0x2e6e, 0x2bcb, 0x2e8a, 0x2bcb, 0x2bcb, - 0x2bcb, 0x2bcb, 0x2bcb, 0x2e91, 0x2e9b, 0x2bcb, 0x2bcb, 0x2bcb, - 0x2bcb, 0x2bcb, 0x2bcb, 0x2bcb, 0x2bcb, 0x2ea3, 0x2bcb, 0x2bcb, - 0x2bcb, 0x2bcb, 0x2bcb, 0x2eb5, 0x2ece, 0x2bcb, 0x2bcb, 0x2bcb, - 0x2bcb, 0x2bcb, 0x2bcb, 0x2ee0, 0x2f37, 0x2f95, 0x2fa9, 0x2bcb, - 0x2bcb, 0x2bcb, 0x398e, 0x2bcb, 0x2bcb, 0x2bcb, 0x2bcb, 0x2bcb, - 0x2bcb, 0x2bcb, 0x2bcb, 0x2c17, 0x2c1b, 0x2fc0, 0x2bcb, 0x2fcd, - 0x3a26, 0x3a83, 0x2bcb, 0x2bcb, 0x2bcb, 0x2bcb, 0x2bcb, 0x2bcb, - 0x2bcb, 0x2bcb, 0x2bcb, 0x301a, 0x314f, 0x316b, 0x3177, 0x31da, - 0x3233, 0x323e, 0x327d, 0x328c, 0x329b, 0x329e, 0x2fd1, 0x32c2, - 0x331e, 0x332b, 0x343c, 0x356f, 0x3599, 0x36a6, 0x2bcb, 0x36b6, - 0x36f0, 0x37bf, 0x2bcb, 0x2bcb, 0x2bcb, 0x2bcb, 0x3827, 0x3843, - 0x38bd, 0x3977, 0x713c, 0x0078, 0x2bad, 0x2021, 0x4000, 0x1078, - 0x35f5, 0x127e, 0x2091, 0x8000, 0x0068, 0x2bba, 0x7818, 0xd084, - 0x0040, 0x2bbd, 0x127f, 0x0078, 0x2bb1, 0x7c22, 0x7926, 0x7a2a, - 0x7b2e, 0x781b, 0x0001, 0x2091, 0x4080, 0x7007, 0x0001, 0x2091, - 0x5000, 0x127f, 0x007c, 0x2021, 0x4001, 0x0078, 0x2baf, 0x2021, - 0x4002, 0x0078, 0x2baf, 0x2021, 0x4003, 0x0078, 0x2baf, 0x2021, - 0x4005, 0x0078, 0x2baf, 0x2021, 0x4006, 0x0078, 0x2baf, 0xa02e, - 0x2520, 0x7b28, 0x7a2c, 0x7824, 0x7930, 0x0078, 0x3604, 0x7823, - 0x0004, 0x7824, 0x007a, 0xa02e, 0x2520, 0x7b28, 0x7a2c, 0x7824, - 0x7930, 0x0078, 0x3608, 0x7924, 0x7828, 0x2114, 0x200a, 0x0078, - 0x2bad, 0x7924, 0x2114, 0x0078, 0x2bad, 0x2099, 0x0009, 0x20a1, - 0x0009, 0x20a9, 0x0007, 0x53a3, 0x7924, 0x7a28, 0x7b2c, 0x0078, - 0x2bad, 0x7824, 0x2060, 0x0078, 0x2c21, 0x2009, 0x0001, 0x2011, - 0x0013, 0x2019, 0x0019, 0x783b, 0x0017, 0x0078, 0x2bad, 0x7d38, - 0x7c3c, 0x0078, 0x2be1, 0x7d38, 0x7c3c, 0x0078, 0x2bed, 0x2061, - 0x1000, 0x610c, 0xa006, 0x2c14, 0xa200, 0x8c60, 0x8109, 0x00c0, - 0x2c23, 0x2010, 0xa005, 0x0040, 0x2bad, 0x0078, 0x2bd3, 0x2069, - 0xa752, 0x7824, 0x7930, 0xa11a, 0x00c8, 0x2bdb, 0x8019, 0x0040, - 0x2bdb, 0x684a, 0x6942, 0x782c, 0x6852, 0x7828, 0x6856, 0xa006, - 0x685a, 0x685e, 0x1078, 0x4eae, 0x0078, 0x2bad, 0x2069, 0xa752, - 0x7824, 0x7934, 0xa11a, 0x00c8, 0x2bdb, 0x8019, 0x0040, 0x2bdb, - 0x684e, 0x6946, 0x782c, 0x6862, 0x7828, 0x6866, 0xa006, 0x686a, - 0x686e, 0x1078, 0x4a3e, 0x0078, 0x2bad, 0xa02e, 0x2520, 0x81ff, - 0x00c0, 0x2bd7, 0x7924, 0x7b28, 0x7a2c, 0x20a9, 0x0005, 0x20a1, - 0xa789, 0x41a1, 0x1078, 0x35ba, 0x0040, 0x2bd7, 0x2009, 0x0020, - 0x1078, 0x3604, 0x701b, 0x2c75, 0x007c, 0x6834, 0x2008, 0xa084, - 0x00ff, 0xa096, 0x0011, 0x0040, 0x2c85, 0xa096, 0x0019, 0x0040, - 0x2c85, 0xa096, 0x0015, 0x00c0, 0x2bd7, 0x810f, 0xa18c, 0x00ff, - 0x0040, 0x2bd7, 0x710e, 0x700c, 0x8001, 0x0040, 0x2cb6, 0x700e, - 0x1078, 0x35ba, 0x0040, 0x2bd7, 0x2009, 0x0020, 0x2061, 0xa7d2, - 0x6224, 0x6328, 0x642c, 0x6530, 0xa290, 0x0040, 0xa399, 0x0000, - 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x1078, 0x3604, 0x701b, 0x2ca9, - 0x007c, 0x6834, 0xa084, 0x00ff, 0xa096, 0x0002, 0x0040, 0x2cb4, - 0xa096, 0x000a, 0x00c0, 0x2bd7, 0x0078, 0x2c8b, 0x7010, 0x2068, - 0x6838, 0xc0fd, 0x683a, 0x1078, 0x4431, 0x00c0, 0x2cc4, 0x7007, - 0x0003, 0x701b, 0x2cc6, 0x007c, 0x1078, 0x4b51, 0x127e, 0x2091, - 0x8000, 0x20a9, 0x0005, 0x2099, 0xa789, 0x530a, 0x2100, 0xa210, - 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0xad80, 0x000d, - 0x2009, 0x0020, 0x127f, 0x0078, 0x3608, 0x61a4, 0x7824, 0x60a6, - 0x0078, 0x2bad, 0x2091, 0x8000, 0x7823, 0x4000, 0x7827, 0x4953, - 0x782b, 0x5020, 0x782f, 0x2020, 0x2009, 0x017f, 0x2104, 0x7832, - 0x3f00, 0x7836, 0x2061, 0x0100, 0x6200, 0x2061, 0x0200, 0x603c, - 0x8007, 0xa205, 0x783a, 0x2009, 0x04fd, 0x2104, 0x783e, 0x781b, - 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2071, 0x0010, 0x20c1, - 0x00f0, 0xa08a, 0x0003, 0x00c8, 0x0427, 0x0078, 0x0423, 0x81ff, - 0x00c0, 0x2bd7, 0x7924, 0x810f, 0xa18c, 0x00ff, 0x1078, 0x45c4, - 0x00c0, 0x2bdb, 0x7e38, 0xa684, 0x3fff, 0xa082, 0x4000, 0x0048, - 0x2d23, 0x0078, 0x2bdb, 0x7c28, 0x7d2c, 0x1078, 0x47a4, 0xd28c, - 0x00c0, 0x2d2e, 0x1078, 0x4736, 0x0078, 0x2d30, 0x1078, 0x4772, - 0x00c0, 0x2d5a, 0x2061, 0xae00, 0x127e, 0x2091, 0x8000, 0x6000, - 0xa086, 0x0000, 0x0040, 0x2d48, 0x6010, 0xa06d, 0x0040, 0x2d48, - 0x683c, 0xa406, 0x00c0, 0x2d48, 0x6840, 0xa506, 0x0040, 0x2d53, - 0x127f, 0xace0, 0x0010, 0x2001, 0xa716, 0x2004, 0xac02, 0x00c8, - 0x2bd7, 0x0078, 0x2d34, 0x1078, 0x8a11, 0x127f, 0x0040, 0x2bd7, - 0x0078, 0x2bad, 0xa00e, 0x2001, 0x0005, 0x1078, 0x4b51, 0x127e, - 0x2091, 0x8000, 0x1078, 0x8f95, 0x1078, 0x4a73, 0x127f, 0x0078, - 0x2bad, 0x81ff, 0x00c0, 0x2bd7, 0x1078, 0x35d2, 0x0040, 0x2bdb, - 0x1078, 0x4673, 0x0040, 0x2bd7, 0x1078, 0x47b2, 0x0040, 0x2bd7, - 0x0078, 0x2bad, 0x81ff, 0x00c0, 0x2bd7, 0x1078, 0x35e4, 0x0040, - 0x2bdb, 0x1078, 0x482f, 0x0040, 0x2bd7, 0x2019, 0x0005, 0x1078, - 0x47d3, 0x0040, 0x2bd7, 0x7828, 0xa08a, 0x1000, 0x00c8, 0x2bdb, - 0x8003, 0x800b, 0x810b, 0xa108, 0x1078, 0x5a52, 0x0078, 0x2bad, - 0x127e, 0x2091, 0x8000, 0x81ff, 0x0040, 0x2da2, 0x2009, 0x0001, - 0x0078, 0x2dd3, 0x2029, 0x00ff, 0x6450, 0x2400, 0xa506, 0x0040, - 0x2dcd, 0x2508, 0x1078, 0x45c4, 0x00c0, 0x2dcd, 0x1078, 0x482f, - 0x00c0, 0x2db8, 0x2009, 0x0002, 0x62ac, 0x2518, 0x0078, 0x2dd3, - 0x2019, 0x0004, 0x1078, 0x47d3, 0x00c0, 0x2dc2, 0x2009, 0x0006, - 0x0078, 0x2dd3, 0x7824, 0xa08a, 0x1000, 0x00c8, 0x2dd6, 0x8003, - 0x800b, 0x810b, 0xa108, 0x1078, 0x5a52, 0x8529, 0x00c8, 0x2da5, - 0x127f, 0x0078, 0x2bad, 0x127f, 0x0078, 0x2bd7, 0x127f, 0x0078, - 0x2bdb, 0x1078, 0x35d2, 0x0040, 0x2bdb, 0x1078, 0x46e7, 0x1078, - 0x47a4, 0x0078, 0x2bad, 0x81ff, 0x00c0, 0x2bd7, 0x1078, 0x35d2, - 0x0040, 0x2bdb, 0x1078, 0x46d6, 0x1078, 0x47a4, 0x0078, 0x2bad, - 0x81ff, 0x00c0, 0x2bd7, 0x1078, 0x35d2, 0x0040, 0x2bdb, 0x1078, - 0x4775, 0x0040, 0x2bd7, 0x1078, 0x4484, 0x1078, 0x472f, 0x1078, - 0x47a4, 0x0078, 0x2bad, 0x1078, 0x35d2, 0x0040, 0x2bdb, 0x1078, - 0x4673, 0x0040, 0x2bd7, 0x62a0, 0x2019, 0x0005, 0x0c7e, 0x1078, - 0x47e9, 0x0c7f, 0x1078, 0x5f01, 0x077e, 0x2039, 0x0000, 0x1078, - 0x5e0a, 0x2009, 0x0000, 0x1078, 0x9f9b, 0x077f, 0x1078, 0x47a4, - 0x0078, 0x2bad, 0x1078, 0x35d2, 0x0040, 0x2bdb, 0x1078, 0x47a4, - 0x2208, 0x0078, 0x2bad, 0x157e, 0x0d7e, 0x0e7e, 0x2069, 0xa814, - 0x6810, 0x6914, 0xa10a, 0x00c8, 0x2e37, 0x2009, 0x0000, 0x6816, - 0x2011, 0x0000, 0x2019, 0x0000, 0x20a9, 0x00ff, 0x2069, 0xa835, - 0x2d04, 0xa075, 0x0040, 0x2e4c, 0x704c, 0x1078, 0x2e56, 0xa210, - 0x7080, 0x1078, 0x2e56, 0xa318, 0x8d68, 0x00f0, 0x2e40, 0x2300, - 0xa218, 0x0e7f, 0x0d7f, 0x157f, 0x0078, 0x2bad, 0x0f7e, 0x017e, - 0xa07d, 0x0040, 0x2e65, 0x2001, 0x0000, 0x8000, 0x2f0c, 0x81ff, - 0x0040, 0x2e65, 0x2178, 0x0078, 0x2e5d, 0x017f, 0x0f7f, 0x007c, - 0x2069, 0xa814, 0x6910, 0x62a8, 0x0078, 0x2bad, 0x81ff, 0x00c0, - 0x2bd7, 0x6150, 0xa190, 0x29c0, 0x2214, 0xa294, 0x00ff, 0x6070, - 0xa084, 0xff00, 0xa215, 0x636c, 0x67cc, 0xd79c, 0x0040, 0x2e84, - 0x2031, 0x0001, 0x0078, 0x2e86, 0x2031, 0x0000, 0x7e3a, 0x7f3e, - 0x0078, 0x2bad, 0x6140, 0x6244, 0x2019, 0xa9a2, 0x231c, 0x0078, - 0x2bad, 0x127e, 0x2091, 0x8000, 0x6134, 0x6338, 0xa006, 0x2010, - 0x127f, 0x0078, 0x2bad, 0x1078, 0x35e4, 0x0040, 0x2bdb, 0x6244, - 0x6338, 0x0078, 0x2bad, 0x6140, 0x6244, 0x7824, 0x6042, 0x7b28, - 0x6346, 0x2069, 0xa752, 0x831f, 0xa305, 0x6816, 0x782c, 0x2069, - 0xa9a2, 0x2d1c, 0x206a, 0x0078, 0x2bad, 0x017e, 0x127e, 0x2091, - 0x8000, 0x7824, 0x6036, 0xd094, 0x0040, 0x2ec8, 0x7828, 0xa085, - 0x0001, 0x2009, 0xa9ab, 0x200a, 0x2001, 0xffff, 0x1078, 0x5ae6, - 0x782c, 0x603a, 0x127f, 0x017f, 0x0078, 0x2bad, 0x1078, 0x35e4, - 0x0040, 0x2bdb, 0x7828, 0xa00d, 0x0040, 0x2bdb, 0x782c, 0xa005, - 0x0040, 0x2bdb, 0x6244, 0x6146, 0x6338, 0x603a, 0x0078, 0x2bad, - 0x2001, 0xa700, 0x2004, 0xa086, 0x0003, 0x00c0, 0x2bd7, 0x0c7e, - 0x2061, 0x0100, 0x7924, 0x810f, 0xa18c, 0x00ff, 0xa196, 0x00ff, - 0x00c0, 0x2ef7, 0x6030, 0xa085, 0xff00, 0x0078, 0x2f06, 0xa182, - 0x007f, 0x00c8, 0x2f30, 0xa188, 0x29c0, 0x210c, 0xa18c, 0x00ff, - 0x6030, 0xa116, 0x0040, 0x2f30, 0x810f, 0xa105, 0x127e, 0x2091, - 0x8000, 0x007e, 0x1078, 0x76c7, 0x007f, 0x0040, 0x2f2c, 0x601a, - 0x600b, 0xbc09, 0x601f, 0x0001, 0x1078, 0x35ba, 0x0040, 0x2f33, - 0x6837, 0x0000, 0x7007, 0x0003, 0x6833, 0x0000, 0x6838, 0xc0fd, - 0x683a, 0x701b, 0x2f8e, 0x2d00, 0x6012, 0x2009, 0x0032, 0x1078, - 0x775c, 0x127f, 0x0c7f, 0x007c, 0x127f, 0x0c7f, 0x0078, 0x2bd7, - 0x0c7f, 0x0078, 0x2bdb, 0x1078, 0x772d, 0x0078, 0x2f2c, 0x2001, - 0xa700, 0x2004, 0xa086, 0x0003, 0x00c0, 0x2bd7, 0x0c7e, 0x2061, - 0x0100, 0x7924, 0x810f, 0xa18c, 0x00ff, 0xa196, 0x00ff, 0x00c0, - 0x2f4e, 0x6030, 0xa085, 0xff00, 0x0078, 0x2f5d, 0xa182, 0x007f, - 0x00c8, 0x2f87, 0xa188, 0x29c0, 0x210c, 0xa18c, 0x00ff, 0x6030, - 0xa116, 0x0040, 0x2f87, 0x810f, 0xa105, 0x127e, 0x2091, 0x8000, - 0x007e, 0x1078, 0x76c7, 0x007f, 0x0040, 0x2f83, 0x601a, 0x600b, - 0xbc05, 0x601f, 0x0001, 0x1078, 0x35ba, 0x0040, 0x2f8a, 0x6837, - 0x0000, 0x7007, 0x0003, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, - 0x701b, 0x2f8e, 0x2d00, 0x6012, 0x2009, 0x0032, 0x1078, 0x775c, - 0x127f, 0x0c7f, 0x007c, 0x127f, 0x0c7f, 0x0078, 0x2bd7, 0x0c7f, - 0x0078, 0x2bdb, 0x1078, 0x772d, 0x0078, 0x2f83, 0x6830, 0xa086, - 0x0100, 0x0040, 0x2bd7, 0x0078, 0x2bad, 0x2061, 0xaa33, 0x127e, - 0x2091, 0x8000, 0x6000, 0xd084, 0x0040, 0x2fa6, 0x6104, 0x6208, - 0x2019, 0xa712, 0x231c, 0x127f, 0x0078, 0x2bad, 0x127f, 0x0078, - 0x2bdb, 0x81ff, 0x00c0, 0x2bd7, 0x127e, 0x2091, 0x8000, 0x6248, - 0x6064, 0xa202, 0x0048, 0x2fbd, 0xa085, 0x0001, 0x1078, 0x256a, - 0x1078, 0x3c9e, 0x127f, 0x0078, 0x2bad, 0x127f, 0x0078, 0x2bdb, - 0x127e, 0x2091, 0x8000, 0x20a9, 0x0012, 0x2001, 0xa740, 0x20a0, - 0xa006, 0x40a4, 0x127f, 0x0078, 0x2bad, 0x7d38, 0x7c3c, 0x0078, - 0x2c5f, 0x7824, 0xa09c, 0x00ff, 0xa39a, 0x0003, 0x00c8, 0x2bd7, - 0x6250, 0xa084, 0xff00, 0x8007, 0xa206, 0x00c0, 0x2fe9, 0x2001, - 0xa740, 0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0078, - 0x3608, 0x81ff, 0x00c0, 0x2bd7, 0x1078, 0x35e4, 0x0040, 0x2bdb, - 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x2bd7, 0x0c7e, - 0x1078, 0x35ba, 0x0c7f, 0x0040, 0x2bd7, 0x6837, 0x0000, 0x6838, - 0xc0fd, 0x683a, 0x1078, 0x8e5a, 0x0040, 0x2bd7, 0x7007, 0x0003, - 0x701b, 0x300b, 0x007c, 0x6830, 0xa086, 0x0100, 0x0040, 0x2bd7, - 0xad80, 0x000e, 0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, - 0x0078, 0x3608, 0x1078, 0x35ba, 0x0040, 0x2bd7, 0x1078, 0x42dd, - 0x2009, 0x001c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x3604, - 0x701b, 0x302b, 0x007c, 0xade8, 0x000d, 0x6800, 0xa005, 0x0040, - 0x2bdb, 0x6804, 0xd0ac, 0x0040, 0x3038, 0xd0a4, 0x0040, 0x2bdb, - 0xd094, 0x0040, 0x3043, 0x0c7e, 0x2061, 0x0100, 0x6104, 0xa18c, - 0xffdf, 0x6106, 0x0c7f, 0xd08c, 0x0040, 0x304e, 0x0c7e, 0x2061, - 0x0100, 0x6104, 0xa18d, 0x0010, 0x6106, 0x0c7f, 0x2009, 0x0100, - 0x210c, 0xa18a, 0x0002, 0x0048, 0x3063, 0xd084, 0x0040, 0x3063, - 0x6a28, 0xa28a, 0x007f, 0x00c8, 0x2bdb, 0xa288, 0x29c0, 0x210c, - 0xa18c, 0x00ff, 0x6156, 0xd0dc, 0x0040, 0x306c, 0x6828, 0xa08a, - 0x007f, 0x00c8, 0x2bdb, 0x6052, 0x6808, 0xa08a, 0x0100, 0x0048, - 0x2bdb, 0xa08a, 0x0841, 0x00c8, 0x2bdb, 0xa084, 0x0007, 0x00c0, - 0x2bdb, 0x680c, 0xa005, 0x0040, 0x2bdb, 0x6810, 0xa005, 0x0040, - 0x2bdb, 0x6848, 0x6940, 0xa10a, 0x00c8, 0x2bdb, 0x8001, 0x0040, - 0x2bdb, 0x684c, 0x6944, 0xa10a, 0x00c8, 0x2bdb, 0x8001, 0x0040, - 0x2bdb, 0x6804, 0xd0fc, 0x0040, 0x30c2, 0x1078, 0x35ba, 0x0040, - 0x2bd7, 0x2009, 0x0014, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0xa290, - 0x0038, 0xa399, 0x0000, 0x1078, 0x3604, 0x701b, 0x30a8, 0x007c, - 0xade8, 0x000d, 0x20a9, 0x0014, 0x2d98, 0x2069, 0xa76e, 0x2da0, - 0x53a3, 0x7010, 0xa0e8, 0x000d, 0x2001, 0xa772, 0x200c, 0xd1e4, - 0x0040, 0x30c2, 0x0c7e, 0x2061, 0x0100, 0x6004, 0xa085, 0x0b00, - 0x6006, 0x0c7f, 0x20a9, 0x001c, 0x2d98, 0x2069, 0xa752, 0x2da0, - 0x53a3, 0x6814, 0xa08c, 0x00ff, 0x6142, 0x8007, 0xa084, 0x00ff, - 0x6046, 0x1078, 0x4eae, 0x1078, 0x49ce, 0x1078, 0x4a3e, 0x6000, - 0xa086, 0x0000, 0x00c0, 0x314d, 0x6808, 0x602a, 0x1078, 0x21f7, - 0x6818, 0x691c, 0x6a20, 0x6b24, 0x8007, 0x810f, 0x8217, 0x831f, - 0x6016, 0x611a, 0x621e, 0x6322, 0x6c04, 0xd4f4, 0x0040, 0x30fa, - 0x6830, 0x6934, 0x6a38, 0x6b3c, 0x8007, 0x810f, 0x8217, 0x831f, - 0x0078, 0x30fc, 0xa084, 0xf0ff, 0x6006, 0x610a, 0x620e, 0x6312, - 0x1078, 0x5b19, 0x6904, 0xd1fc, 0x0040, 0x312f, 0x0c7e, 0x2009, - 0x0000, 0x20a9, 0x0001, 0x6b70, 0xd384, 0x0040, 0x312c, 0x0078, - 0x3116, 0x839d, 0x00c8, 0x312c, 0x3508, 0x8109, 0x1078, 0x5480, - 0x6878, 0x6016, 0x6874, 0x2008, 0xa084, 0xff00, 0x8007, 0x600a, - 0xa184, 0x00ff, 0x6006, 0x8108, 0x00c0, 0x312a, 0x6003, 0x0003, - 0x0078, 0x312c, 0x6003, 0x0001, 0x00f0, 0x3111, 0x0c7f, 0x0c7e, - 0x2061, 0x0100, 0x602f, 0x0040, 0x602f, 0x0000, 0x0c7f, 0x1078, - 0x3819, 0x0040, 0x313d, 0x1078, 0x256a, 0x60c0, 0xa005, 0x0040, - 0x3149, 0x6003, 0x0001, 0x2091, 0x301d, 0x1078, 0x4224, 0x0078, - 0x314d, 0x6003, 0x0004, 0x2091, 0x301d, 0x0078, 0x2bad, 0x6000, - 0xa086, 0x0000, 0x0040, 0x2bd7, 0x2069, 0xa752, 0x7830, 0x6842, - 0x7834, 0x6846, 0x6804, 0xd0fc, 0x0040, 0x3162, 0x2009, 0x0030, - 0x0078, 0x3164, 0x2009, 0x001c, 0x2d00, 0x7a2c, 0x7b28, 0x7c3c, - 0x7d38, 0x0078, 0x3608, 0xa006, 0x1078, 0x256a, 0x81ff, 0x00c0, - 0x2bd7, 0x1078, 0x42dd, 0x1078, 0x4224, 0x0078, 0x2bad, 0x81ff, - 0x00c0, 0x2bd7, 0x6184, 0x81ff, 0x0040, 0x3191, 0x703f, 0x0000, - 0x2001, 0xadc0, 0x2009, 0x0040, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, - 0x127e, 0x2091, 0x8000, 0x1078, 0x3608, 0x701b, 0x2baa, 0x127f, - 0x007c, 0x703f, 0x0001, 0x0d7e, 0x2069, 0xadc0, 0x20a9, 0x0040, - 0x20a1, 0xadc0, 0x2019, 0xffff, 0x43a4, 0x6550, 0xa588, 0x29c0, - 0x210c, 0xa18c, 0x00ff, 0x216a, 0xa00e, 0x2011, 0x0002, 0x2100, - 0xa506, 0x0040, 0x31c3, 0x1078, 0x45c4, 0x00c0, 0x31c3, 0x6014, - 0x821c, 0x0048, 0x31bb, 0xa398, 0xadc0, 0xa085, 0xff00, 0x8007, - 0x201a, 0x0078, 0x31c2, 0xa398, 0xadc0, 0x2324, 0xa4a4, 0xff00, - 0xa405, 0x201a, 0x8210, 0x8108, 0xa182, 0x0080, 0x00c8, 0x31ca, - 0x0078, 0x31a7, 0x8201, 0x8007, 0x2d0c, 0xa105, 0x206a, 0x0d7f, - 0x20a9, 0x0040, 0x20a1, 0xadc0, 0x2099, 0xadc0, 0x1078, 0x4281, - 0x0078, 0x3180, 0x1078, 0x35e4, 0x0040, 0x2bdb, 0x0c7e, 0x1078, - 0x35ba, 0x0c7f, 0x00c0, 0x31e8, 0x2009, 0x0002, 0x0078, 0x2bd7, - 0x2001, 0xa753, 0x2004, 0xd0b4, 0x0040, 0x320f, 0x6000, 0xd08c, - 0x00c0, 0x320f, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, - 0x320f, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x1078, 0x8eae, - 0x00c0, 0x3206, 0x2009, 0x0003, 0x0078, 0x2bd7, 0x7007, 0x0003, - 0x701b, 0x320b, 0x007c, 0x1078, 0x35e4, 0x0040, 0x2bdb, 0x20a9, - 0x002b, 0x2c98, 0xade8, 0x0002, 0x2da0, 0x53a3, 0x20a9, 0x0004, - 0xac80, 0x0006, 0x2098, 0xad80, 0x0006, 0x20a0, 0x1078, 0x4281, - 0x20a9, 0x0004, 0xac80, 0x000a, 0x2098, 0xad80, 0x000a, 0x20a0, - 0x1078, 0x4281, 0x2d00, 0x2009, 0x002b, 0x7a2c, 0x7b28, 0x7c3c, - 0x7d38, 0x0078, 0x3608, 0x81ff, 0x00c0, 0x2bd7, 0x1078, 0x35d2, - 0x0040, 0x2bdb, 0x1078, 0x47bd, 0x0078, 0x2bad, 0x81ff, 0x00c0, - 0x2bd7, 0x7828, 0xa08a, 0x1000, 0x00c8, 0x2bdb, 0x1078, 0x35e4, - 0x0040, 0x2bdb, 0x1078, 0x482f, 0x0040, 0x2bd7, 0x2019, 0x0004, - 0x1078, 0x47d3, 0x7924, 0x810f, 0x7a28, 0x1078, 0x3259, 0x0078, - 0x2bad, 0xa186, 0x00ff, 0x0040, 0x3261, 0x1078, 0x3271, 0x0078, - 0x3270, 0x2029, 0x007e, 0x2061, 0xa700, 0x6450, 0x2400, 0xa506, - 0x0040, 0x326d, 0x2508, 0x1078, 0x3271, 0x8529, 0x00c8, 0x3266, - 0x007c, 0x1078, 0x45c4, 0x00c0, 0x327c, 0x2200, 0x8003, 0x800b, - 0x810b, 0xa108, 0x1078, 0x5a52, 0x007c, 0x81ff, 0x00c0, 0x2bd7, - 0x1078, 0x35d2, 0x0040, 0x2bdb, 0x1078, 0x4673, 0x0040, 0x2bd7, - 0x1078, 0x47c8, 0x0078, 0x2bad, 0x81ff, 0x00c0, 0x2bd7, 0x1078, - 0x35d2, 0x0040, 0x2bdb, 0x1078, 0x4673, 0x0040, 0x2bd7, 0x1078, - 0x47b2, 0x0078, 0x2bad, 0x6100, 0x0078, 0x2bad, 0x1078, 0x35e4, - 0x0040, 0x2bdb, 0x2001, 0xa700, 0x2004, 0xa086, 0x0003, 0x00c0, - 0x2bd7, 0x0d7e, 0xace8, 0x000a, 0x7924, 0xd184, 0x0040, 0x32b2, - 0xace8, 0x0006, 0x680c, 0x8007, 0x783e, 0x6808, 0x8007, 0x783a, - 0x6b04, 0x831f, 0x6a00, 0x8217, 0x0d7f, 0x6100, 0xa18c, 0x0200, - 0x0078, 0x2bad, 0xa006, 0x1078, 0x256a, 0x7824, 0xa084, 0x00ff, - 0xa086, 0x00ff, 0x0040, 0x32cf, 0x81ff, 0x00c0, 0x2bd7, 0x1078, - 0x42dd, 0x7828, 0xa08a, 0x1000, 0x00c8, 0x2bdb, 0x7924, 0xa18c, - 0xff00, 0x810f, 0xa186, 0x00ff, 0x0040, 0x32e5, 0xa182, 0x007f, - 0x00c8, 0x2bdb, 0x2100, 0x1078, 0x2564, 0x027e, 0x0c7e, 0x127e, - 0x2091, 0x8000, 0x2061, 0xa9c4, 0x601b, 0x0000, 0x601f, 0x0000, - 0x2011, 0x0003, 0x1078, 0x70e0, 0x2011, 0x0002, 0x1078, 0x70ea, - 0x1078, 0x6fc4, 0x037e, 0x2019, 0x0000, 0x1078, 0x7058, 0x037f, - 0x2061, 0x0100, 0x6030, 0xa084, 0x00ff, 0x810f, 0xa105, 0x604a, - 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0x002d, 0x2011, 0x4259, - 0x1078, 0x5add, 0x7924, 0xa18c, 0xff00, 0x810f, 0x7a28, 0x1078, - 0x3259, 0x127f, 0x0c7f, 0x027f, 0x0078, 0x2bad, 0x7924, 0xa18c, - 0xff00, 0x810f, 0x0c7e, 0x1078, 0x455c, 0x2c08, 0x0c7f, 0x00c0, - 0x2bdb, 0x0078, 0x2bad, 0x81ff, 0x0040, 0x3332, 0x2009, 0x0001, - 0x0078, 0x2bd7, 0x60cc, 0xd09c, 0x00c0, 0x333a, 0x2009, 0x0005, - 0x0078, 0x2bd7, 0x1078, 0x35ba, 0x00c0, 0x3342, 0x2009, 0x0002, - 0x0078, 0x2bd7, 0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, - 0x3604, 0x701b, 0x334c, 0x007c, 0x2009, 0x0080, 0x1078, 0x45c4, - 0x00c0, 0x3359, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x0040, - 0x335d, 0x2021, 0x400a, 0x0078, 0x2baf, 0x0d7e, 0xade8, 0x000d, - 0x6900, 0x6a08, 0x6b0c, 0x6c10, 0x6d14, 0x6e18, 0x6820, 0xa0be, - 0x0100, 0x0040, 0x33d0, 0xa0be, 0x0112, 0x0040, 0x33d0, 0xa0be, - 0x0113, 0x0040, 0x33d0, 0xa0be, 0x0114, 0x0040, 0x33d0, 0xa0be, - 0x0117, 0x0040, 0x33d0, 0xa0be, 0x011a, 0x0040, 0x33d0, 0xa0be, - 0x0121, 0x0040, 0x33c6, 0xa0be, 0x0131, 0x0040, 0x33c6, 0xa0be, - 0x0171, 0x0040, 0x33d0, 0xa0be, 0x0173, 0x0040, 0x33d0, 0xa0be, - 0x01a1, 0x00c0, 0x3398, 0x6830, 0x8007, 0x6832, 0x0078, 0x33d6, - 0xa0be, 0x0212, 0x0040, 0x33cc, 0xa0be, 0x0213, 0x0040, 0x33cc, - 0xa0be, 0x0214, 0x0040, 0x33be, 0xa0be, 0x0217, 0x0040, 0x33b8, - 0xa0be, 0x021a, 0x00c0, 0x33b1, 0x6838, 0x8007, 0x683a, 0x0078, - 0x33d0, 0xa0be, 0x0300, 0x0040, 0x33d0, 0x0d7f, 0x0078, 0x2bdb, - 0xad80, 0x0010, 0x20a9, 0x0007, 0x1078, 0x3418, 0xad80, 0x000e, - 0x20a9, 0x0001, 0x1078, 0x3418, 0x0078, 0x33d0, 0xad80, 0x000c, - 0x1078, 0x3426, 0x0078, 0x33d6, 0xad80, 0x000e, 0x1078, 0x3426, - 0xad80, 0x000c, 0x20a9, 0x0001, 0x1078, 0x3418, 0x0c7e, 0x1078, - 0x35ba, 0x0040, 0x3409, 0x6838, 0xc0fd, 0x683a, 0x6837, 0x0119, - 0x6853, 0x0000, 0x684f, 0x0020, 0x685b, 0x0001, 0x810b, 0x697e, - 0x6883, 0x0000, 0x6a86, 0x6b8a, 0x6c8e, 0x6d92, 0x6996, 0x689b, - 0x0000, 0x0c7f, 0x0d7f, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, - 0x6823, 0x0000, 0x6804, 0x2068, 0x1078, 0x8e76, 0x00c0, 0x3404, - 0x2009, 0x0003, 0x0078, 0x2bd7, 0x7007, 0x0003, 0x701b, 0x340f, - 0x007c, 0x0c7f, 0x0d7f, 0x2009, 0x0002, 0x0078, 0x2bd7, 0x6820, - 0xa086, 0x8001, 0x00c0, 0x2bad, 0x2009, 0x0004, 0x0078, 0x2bd7, - 0x017e, 0x2008, 0x2044, 0x8000, 0x204c, 0x8000, 0x290a, 0x8108, - 0x280a, 0x8108, 0x00f0, 0x341a, 0x017f, 0x007c, 0x017e, 0x0a7e, - 0x0b7e, 0x2008, 0x2044, 0x8000, 0x204c, 0x8000, 0x2054, 0x8000, - 0x205c, 0x2b0a, 0x8108, 0x2a0a, 0x8108, 0x290a, 0x8108, 0x280a, - 0x0b7f, 0x0a7f, 0x017f, 0x007c, 0x81ff, 0x0040, 0x3443, 0x2009, - 0x0001, 0x0078, 0x2bd7, 0x60cc, 0xd09c, 0x00c0, 0x344b, 0x2009, - 0x0005, 0x0078, 0x2bd7, 0x7924, 0x2140, 0xa18c, 0xff00, 0x810f, - 0xa182, 0x0080, 0x0048, 0x2bdb, 0xa182, 0x00ff, 0x00c8, 0x2bdb, - 0x7a2c, 0x7b28, 0x606c, 0xa306, 0x00c0, 0x3466, 0x6070, 0xa24e, - 0x0040, 0x2bdb, 0xa9cc, 0xff00, 0x0040, 0x2bdb, 0x0c7e, 0x1078, - 0x350f, 0x2c68, 0x0c7f, 0x0040, 0x349e, 0xa0c6, 0x4000, 0x00c0, - 0x3484, 0x0c7e, 0x007e, 0x2d60, 0x2009, 0x0000, 0x1078, 0x489b, - 0x00c0, 0x347b, 0xc185, 0x6000, 0xd0bc, 0x0040, 0x3480, 0xc18d, - 0x007f, 0x0c7f, 0x0078, 0x349b, 0xa0c6, 0x4007, 0x00c0, 0x348b, - 0x2408, 0x0078, 0x349b, 0xa0c6, 0x4008, 0x00c0, 0x3493, 0x2708, - 0x2610, 0x0078, 0x349b, 0xa0c6, 0x4009, 0x00c0, 0x3499, 0x0078, - 0x349b, 0x2001, 0x4006, 0x2020, 0x0078, 0x2baf, 0x2d00, 0x7022, - 0x017e, 0x0b7e, 0x0c7e, 0x0e7e, 0x2c70, 0x1078, 0x76c7, 0x0040, - 0x34e4, 0x2d00, 0x601a, 0x2001, 0xa757, 0x2004, 0xa084, 0x00ff, - 0x6842, 0x2e58, 0x0e7f, 0x0e7e, 0x0c7e, 0x1078, 0x35ba, 0x0c7f, - 0x2b70, 0x00c0, 0x34c5, 0x1078, 0x772d, 0x0e7f, 0x0c7f, 0x0b7f, - 0x017f, 0x2009, 0x0002, 0x0078, 0x2bd7, 0x6837, 0x0000, 0x2d00, - 0x6012, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x127e, 0x2091, - 0x8000, 0x1078, 0x2880, 0x127f, 0x601f, 0x0001, 0x2001, 0x0000, - 0x1078, 0x44ee, 0x2001, 0x0002, 0x1078, 0x4502, 0x2009, 0x0002, - 0x1078, 0x775c, 0xa085, 0x0001, 0x0e7f, 0x0c7f, 0x0b7f, 0x017f, - 0x00c0, 0x34ee, 0x2009, 0x0003, 0x0078, 0x2bd7, 0x7007, 0x0003, - 0x701b, 0x34f3, 0x007c, 0x6830, 0xa086, 0x0100, 0x7020, 0x2060, - 0x00c0, 0x3501, 0x2009, 0x0004, 0x6204, 0xa294, 0x00ff, 0x0078, - 0x2bd7, 0x2009, 0x0000, 0x1078, 0x489b, 0x00c0, 0x3508, 0xc185, - 0x6000, 0xd0bc, 0x0040, 0x350d, 0xc18d, 0x0078, 0x2bad, 0x0e7e, - 0x0d7e, 0x2029, 0x0000, 0x2021, 0x0080, 0x20a9, 0x007f, 0x2071, - 0xa8b5, 0x2e04, 0xa005, 0x00c0, 0x3524, 0x2100, 0xa406, 0x00c0, - 0x3555, 0x2428, 0x0078, 0x3555, 0x2068, 0x6f10, 0x2700, 0xa306, - 0x00c0, 0x3546, 0x6e14, 0x2600, 0xa206, 0x00c0, 0x3546, 0x2400, - 0xa106, 0x00c0, 0x3542, 0x2d60, 0xd884, 0x0040, 0x356a, 0x6004, - 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x356a, 0x2001, 0x4000, - 0x0078, 0x356b, 0x2001, 0x4007, 0x0078, 0x356b, 0x2400, 0xa106, - 0x00c0, 0x3555, 0x6e14, 0x87ff, 0x00c0, 0x3551, 0x86ff, 0x0040, - 0x3521, 0x2001, 0x4008, 0x0078, 0x356b, 0x8420, 0x8e70, 0x00f0, - 0x3519, 0x85ff, 0x00c0, 0x3564, 0x2001, 0x4009, 0x0078, 0x356b, - 0x2001, 0x0001, 0x0078, 0x356b, 0x1078, 0x455c, 0x00c0, 0x3560, - 0x6312, 0x6216, 0xa006, 0xa005, 0x0d7f, 0x0e7f, 0x007c, 0x81ff, - 0x00c0, 0x2bd7, 0x1078, 0x35ba, 0x0040, 0x2bd7, 0x6837, 0x0000, - 0x6838, 0xc0fd, 0x683a, 0x7824, 0xa005, 0x0040, 0x2bdb, 0xa096, - 0x00ff, 0x0040, 0x3587, 0xa092, 0x0004, 0x00c8, 0x2bdb, 0x2010, - 0x2d18, 0x1078, 0x282f, 0x0040, 0x2bd7, 0x7007, 0x0003, 0x701b, - 0x3592, 0x007c, 0x6830, 0xa086, 0x0100, 0x0040, 0x2bd7, 0x0078, - 0x2bad, 0x7924, 0xa18c, 0xff00, 0x810f, 0xa182, 0x0080, 0x0048, - 0x2bdb, 0xa182, 0x00ff, 0x00c8, 0x2bdb, 0x127e, 0x2091, 0x8000, - 0x1078, 0x8d5b, 0x00c0, 0x35b7, 0xa190, 0xa835, 0x2204, 0xa065, - 0x0040, 0x35b7, 0x1078, 0x42f8, 0x127f, 0x0078, 0x2bad, 0x127f, - 0x0078, 0x2bd7, 0x1078, 0x138b, 0x0040, 0x35d1, 0xa006, 0x6802, - 0x7010, 0xa005, 0x00c0, 0x35c9, 0x2d00, 0x7012, 0x7016, 0x0078, - 0x35cf, 0x7014, 0x6802, 0x2060, 0x2d00, 0x6006, 0x7016, 0xad80, - 0x000d, 0x007c, 0x7924, 0x810f, 0xa18c, 0x00ff, 0x1078, 0x45c4, - 0x00c0, 0x35e1, 0x7e28, 0xa684, 0x3fff, 0xa082, 0x4000, 0x0048, - 0x35e2, 0xa066, 0x8cff, 0x007c, 0x7e24, 0x860f, 0xa18c, 0x00ff, - 0x1078, 0x45c4, 0x00c0, 0x35f2, 0xa6b4, 0x00ff, 0xa682, 0x4000, - 0x0048, 0x35f3, 0xa066, 0x8cff, 0x007c, 0x017e, 0x7110, 0x81ff, - 0x0040, 0x3600, 0x2168, 0x6904, 0x1078, 0x13a4, 0x0078, 0x35f7, - 0x7112, 0x7116, 0x017f, 0x007c, 0x2031, 0x0001, 0x0078, 0x360a, - 0x2031, 0x0000, 0x2061, 0xa7d2, 0x6606, 0x6112, 0x600e, 0x6226, - 0x632a, 0x642e, 0x6532, 0x2c10, 0x1078, 0x13db, 0x7007, 0x0002, - 0x701b, 0x2bad, 0x007c, 0x0f7e, 0x127e, 0x2091, 0x8000, 0x2079, - 0x0000, 0x2001, 0xa790, 0x2004, 0xa005, 0x00c0, 0x3636, 0x0068, - 0x3636, 0x7818, 0xd084, 0x00c0, 0x3636, 0x7a22, 0x7b26, 0x7c2a, - 0x781b, 0x0001, 0x2091, 0x4080, 0x0078, 0x365b, 0x017e, 0x0c7e, - 0x0e7e, 0x2071, 0xa782, 0x7138, 0xa182, 0x0008, 0x0048, 0x3644, - 0x7030, 0x2060, 0x0078, 0x3655, 0x7030, 0xa0e0, 0x0008, 0xac82, - 0xa7d2, 0x0048, 0x364d, 0x2061, 0xa792, 0x2c00, 0x7032, 0x81ff, - 0x00c0, 0x3653, 0x7036, 0x8108, 0x713a, 0x2262, 0x6306, 0x640a, - 0x0e7f, 0x0c7f, 0x017f, 0x127f, 0x0f7f, 0x007c, 0x0e7e, 0x2071, - 0xa782, 0x7038, 0xa005, 0x0040, 0x3697, 0x127e, 0x2091, 0x8000, - 0x0068, 0x3696, 0x0f7e, 0x2079, 0x0000, 0x7818, 0xd084, 0x00c0, - 0x3695, 0x0c7e, 0x7034, 0x2060, 0x2c04, 0x7822, 0x6004, 0x7826, - 0x6008, 0x782a, 0x781b, 0x0001, 0x2091, 0x4080, 0x7038, 0x8001, - 0x703a, 0xa005, 0x00c0, 0x368b, 0x7033, 0xa792, 0x7037, 0xa792, - 0x0c7f, 0x0078, 0x3695, 0xac80, 0x0008, 0xa0fa, 0xa7d2, 0x0048, - 0x3693, 0x2001, 0xa792, 0x7036, 0x0c7f, 0x0f7f, 0x127f, 0x0e7f, - 0x007c, 0x027e, 0x2001, 0xa753, 0x2004, 0xd0c4, 0x0040, 0x36a4, - 0x2011, 0x8014, 0x1078, 0x361b, 0x027f, 0x007c, 0x81ff, 0x00c0, - 0x2bd7, 0x127e, 0x2091, 0x8000, 0x6030, 0xc08d, 0xc085, 0xc0ac, - 0x6032, 0x1078, 0x4224, 0x127f, 0x0078, 0x2bad, 0x81ff, 0x00c0, - 0x2bd7, 0x6000, 0xa086, 0x0003, 0x00c0, 0x2bd7, 0x2001, 0xa753, - 0x2004, 0xd0ac, 0x00c0, 0x2bd7, 0x1078, 0x35e4, 0x0040, 0x2bdb, - 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x36d3, 0x7828, - 0xa005, 0x0040, 0x2bad, 0x0c7e, 0x1078, 0x35ba, 0x0c7f, 0x0040, - 0x2bd7, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, - 0x1078, 0x8f22, 0x0040, 0x2bd7, 0x7007, 0x0003, 0x701b, 0x36e9, - 0x007c, 0x6830, 0xa086, 0x0100, 0x0040, 0x2bd7, 0x0078, 0x2bad, - 0x2001, 0xa700, 0x2004, 0xa086, 0x0003, 0x00c0, 0x2bd7, 0x7f24, - 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x35ba, 0x0040, 0x2bd7, - 0x2009, 0x0000, 0x2031, 0x0000, 0x7023, 0x0000, 0x702f, 0x0000, - 0xad80, 0x0005, 0x7026, 0x20a0, 0x1078, 0x45c4, 0x00c0, 0x376d, - 0x6004, 0xa0c4, 0x00ff, 0xa8c6, 0x0006, 0x0040, 0x371d, 0xa0c4, - 0xff00, 0xa8c6, 0x0600, 0x00c0, 0x376d, 0x2001, 0xa753, 0x2004, - 0xd0ac, 0x00c0, 0x372a, 0x1078, 0x489b, 0x00c0, 0x372a, 0xd79c, - 0x0040, 0x376d, 0xd794, 0x00c0, 0x3730, 0xd784, 0x0040, 0x373c, - 0xac80, 0x0006, 0x2098, 0x3400, 0x20a9, 0x0004, 0x53a3, 0x1078, - 0x3426, 0xd794, 0x0040, 0x3745, 0xac80, 0x000a, 0x2098, 0x3400, - 0x20a9, 0x0004, 0x53a3, 0x1078, 0x3426, 0x21a2, 0xd794, 0x0040, - 0x3765, 0xac80, 0x0000, 0x2098, 0x94a0, 0x20a9, 0x0002, 0x53a3, - 0xac80, 0x0003, 0x20a6, 0x94a0, 0xac80, 0x0004, 0x2098, 0x3400, - 0x20a9, 0x0002, 0x53a3, 0x1078, 0x3418, 0xac80, 0x0026, 0x2098, - 0x20a9, 0x0002, 0x53a3, 0x0078, 0x3766, 0x94a0, 0xd794, 0x0040, - 0x376b, 0xa6b0, 0x000b, 0xa6b0, 0x0005, 0x8108, 0xd78c, 0x0040, - 0x3777, 0xa186, 0x0100, 0x0040, 0x3788, 0x0078, 0x377b, 0xa186, - 0x007e, 0x0040, 0x3788, 0xd794, 0x0040, 0x3782, 0xa686, 0x0020, - 0x0078, 0x3784, 0xa686, 0x0028, 0x0040, 0x3791, 0x0078, 0x370c, - 0x86ff, 0x00c0, 0x378f, 0x7120, 0x810b, 0x0078, 0x2bad, 0x702f, - 0x0001, 0x711e, 0x7020, 0xa600, 0x7022, 0x772a, 0x2061, 0xa7d2, - 0x6007, 0x0000, 0x6612, 0x7024, 0x600e, 0x6226, 0x632a, 0x642e, - 0x6532, 0x2c10, 0x1078, 0x13db, 0x7007, 0x0002, 0x701b, 0x37a9, - 0x007c, 0x702c, 0xa005, 0x00c0, 0x37bb, 0x711c, 0x7024, 0x20a0, - 0x7728, 0x2031, 0x0000, 0x2061, 0xa7d2, 0x6224, 0x6328, 0x642c, - 0x6530, 0x0078, 0x370c, 0x7120, 0x810b, 0x0078, 0x2bad, 0x2029, - 0x007e, 0x7924, 0x7a28, 0x7b2c, 0x7c38, 0xa184, 0xff00, 0x8007, - 0xa0e2, 0x0020, 0x0048, 0x2bdb, 0xa502, 0x0048, 0x2bdb, 0xa184, - 0x00ff, 0xa0e2, 0x0020, 0x0048, 0x2bdb, 0xa502, 0x0048, 0x2bdb, - 0xa284, 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0048, 0x2bdb, 0xa502, - 0x0048, 0x2bdb, 0xa284, 0x00ff, 0xa0e2, 0x0020, 0x0048, 0x2bdb, - 0xa502, 0x0048, 0x2bdb, 0xa384, 0xff00, 0x8007, 0xa0e2, 0x0020, - 0x0048, 0x2bdb, 0xa502, 0x0048, 0x2bdb, 0xa384, 0x00ff, 0xa0e2, - 0x0020, 0x0048, 0x2bdb, 0xa502, 0x0048, 0x2bdb, 0xa484, 0xff00, - 0x8007, 0xa0e2, 0x0020, 0x0048, 0x2bdb, 0xa502, 0x0048, 0x2bdb, - 0xa484, 0x00ff, 0xa0e2, 0x0020, 0x0048, 0x2bdb, 0xa502, 0x0048, - 0x2bdb, 0x2061, 0xa9a5, 0x6102, 0x6206, 0x630a, 0x640e, 0x0078, - 0x2bad, 0x007e, 0x2001, 0xa753, 0x2004, 0xd0cc, 0x007f, 0x007c, - 0x007e, 0x2001, 0xa772, 0x2004, 0xd0bc, 0x007f, 0x007c, 0x6164, - 0x7a24, 0x6300, 0x82ff, 0x00c0, 0x3830, 0x7926, 0x0078, 0x2bad, - 0x83ff, 0x00c0, 0x2bdb, 0x2001, 0xfff0, 0xa200, 0x00c8, 0x2bdb, - 0x2019, 0xffff, 0x6068, 0xa302, 0xa200, 0x0048, 0x2bdb, 0x7926, - 0x6266, 0x0078, 0x2bad, 0x2001, 0xa700, 0x2004, 0xa086, 0x0003, - 0x00c0, 0x2bd7, 0x7c28, 0x7d24, 0x7e38, 0x7f2c, 0x1078, 0x35ba, - 0x0040, 0x2bd7, 0x2009, 0x0000, 0x2019, 0x0000, 0x7023, 0x0000, - 0x702f, 0x0000, 0xad80, 0x0003, 0x7026, 0x20a0, 0xa1e0, 0xa835, - 0x2c64, 0x8cff, 0x0040, 0x387d, 0x6004, 0xa084, 0x00ff, 0xa086, - 0x0006, 0x0040, 0x3872, 0x6004, 0xa084, 0xff00, 0xa086, 0x0600, - 0x00c0, 0x387d, 0x6014, 0x20a2, 0x94a0, 0x6010, 0x8007, 0xa105, - 0x8007, 0x20a2, 0x94a0, 0xa398, 0x0002, 0x8108, 0xa182, 0x00ff, - 0x0040, 0x3888, 0xa386, 0x002a, 0x0040, 0x3891, 0x0078, 0x385e, - 0x83ff, 0x00c0, 0x388f, 0x7120, 0x810c, 0x0078, 0x2bad, 0x702f, - 0x0001, 0x711e, 0x7020, 0xa300, 0x7022, 0x2061, 0xa7d2, 0x6007, - 0x0000, 0x6312, 0x7024, 0x600e, 0x6426, 0x652a, 0x662e, 0x6732, - 0x2c10, 0x1078, 0x13db, 0x7007, 0x0002, 0x701b, 0x38a8, 0x007c, - 0x702c, 0xa005, 0x00c0, 0x38b9, 0x711c, 0x7024, 0x20a0, 0x2019, - 0x0000, 0x2061, 0xa7d2, 0x6424, 0x6528, 0x662c, 0x6730, 0x0078, - 0x385e, 0x7120, 0x810c, 0x0078, 0x2bad, 0x81ff, 0x00c0, 0x2bd7, - 0x60cc, 0xd09c, 0x0040, 0x2bd7, 0x1078, 0x35ba, 0x0040, 0x2bd7, - 0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x3604, 0x701b, - 0x38d2, 0x007c, 0x0d7e, 0xade8, 0x000d, 0x6828, 0xa0be, 0x7000, - 0x0040, 0x38e5, 0xa0be, 0x7100, 0x0040, 0x38e5, 0xa0be, 0x7200, - 0x0040, 0x38e5, 0x0d7f, 0x0078, 0x2bdb, 0x6820, 0x6924, 0x1078, - 0x254d, 0x00c0, 0x3910, 0x1078, 0x455c, 0x00c0, 0x3910, 0x7122, - 0x6612, 0x6516, 0x6e18, 0x0c7e, 0x1078, 0x35ba, 0x0040, 0x3910, - 0x1078, 0x35ba, 0x0040, 0x3910, 0x0c7f, 0x0d7f, 0x6837, 0x0000, - 0x6838, 0xc0fd, 0x683a, 0x6823, 0x0000, 0x6804, 0x2068, 0x1078, - 0x8e92, 0x0040, 0x2bd7, 0x7007, 0x0003, 0x701b, 0x3913, 0x007c, - 0x0d7f, 0x0078, 0x2bd7, 0x7120, 0x1078, 0x298e, 0x6820, 0xa086, - 0x8001, 0x0040, 0x2bd7, 0x2d00, 0x701e, 0x6804, 0xa080, 0x0002, - 0x007e, 0x20a9, 0x002a, 0x2098, 0x20a0, 0x1078, 0x4281, 0x007f, - 0xade8, 0x000d, 0x6a08, 0x6b0c, 0x6c10, 0x6d14, 0x2061, 0xa7d2, - 0x6007, 0x0000, 0x6e00, 0x6f28, 0xa7c6, 0x7000, 0x00c0, 0x393a, - 0x0078, 0x393e, 0xa7c6, 0x7100, 0x00c0, 0x3946, 0xa6c2, 0x0004, - 0x0048, 0x2bdb, 0x2009, 0x0004, 0x0078, 0x3608, 0xa7c6, 0x7200, - 0x00c0, 0x2bdb, 0xa6c2, 0x0054, 0x0048, 0x2bdb, 0x600e, 0x6013, - 0x002a, 0x6226, 0x632a, 0x642e, 0x6532, 0x2c10, 0x1078, 0x13db, - 0x7007, 0x0002, 0x701b, 0x395d, 0x007c, 0x701c, 0x2068, 0x6804, - 0xa080, 0x0001, 0x2004, 0xa080, 0x0002, 0x007e, 0x20a9, 0x002a, - 0x2098, 0x20a0, 0x1078, 0x4281, 0x007f, 0x2009, 0x002a, 0x2061, - 0xa7d2, 0x6224, 0x6328, 0x642c, 0x6530, 0x0078, 0x3608, 0x81ff, - 0x00c0, 0x2bd7, 0x792c, 0x2001, 0xa99d, 0x2102, 0x1078, 0x35d2, - 0x0040, 0x2bdb, 0x1078, 0x4673, 0x0040, 0x2bd7, 0x127e, 0x2091, - 0x8000, 0x1078, 0x47de, 0x127f, 0x0078, 0x2bad, 0x7824, 0xd08c, - 0x00c0, 0x3995, 0xd084, 0x0040, 0x31da, 0x1078, 0x35e4, 0x0040, - 0x2bdb, 0x0c7e, 0x1078, 0x35ba, 0x0c7f, 0x00c0, 0x39a3, 0x2009, - 0x0002, 0x0078, 0x2bd7, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, - 0x0040, 0x39b0, 0xa08e, 0x0004, 0x0040, 0x39b0, 0xa08e, 0x0005, - 0x00c0, 0x39dd, 0x7824, 0xd08c, 0x0040, 0x39bb, 0x6000, 0xc08c, - 0x6002, 0x0078, 0x39c5, 0x2001, 0xa753, 0x2004, 0xd0b4, 0x0040, - 0x320f, 0x6000, 0xd08c, 0x00c0, 0x320f, 0x6837, 0x0000, 0x6838, - 0xc0fd, 0x683a, 0x1078, 0x8eae, 0x00c0, 0x39d2, 0x2009, 0x0003, - 0x0078, 0x2bd7, 0x7007, 0x0003, 0x701b, 0x39d7, 0x007c, 0x1078, - 0x35e4, 0x0040, 0x2bdb, 0x0078, 0x320f, 0x2009, 0xa72f, 0x210c, - 0x81ff, 0x0040, 0x39e7, 0x2009, 0x0001, 0x0078, 0x2bd7, 0x2001, - 0xa700, 0x2004, 0xa086, 0x0003, 0x0040, 0x39f2, 0x2009, 0x0007, - 0x0078, 0x2bd7, 0x2001, 0xa753, 0x2004, 0xd0ac, 0x0040, 0x39fc, - 0x2009, 0x0008, 0x0078, 0x2bd7, 0x609c, 0xd0a4, 0x00c0, 0x3a03, - 0xd0ac, 0x00c0, 0x320f, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, - 0xc0fd, 0x683a, 0x1078, 0x8f22, 0x00c0, 0x3a12, 0x2009, 0x0003, - 0x0078, 0x2bd7, 0x7007, 0x0003, 0x701b, 0x3a17, 0x007c, 0x6830, - 0xa086, 0x0100, 0x00c0, 0x3a20, 0x2009, 0x0004, 0x0078, 0x2bd7, - 0x1078, 0x35e4, 0x0040, 0x2bdb, 0x0078, 0x39b2, 0x81ff, 0x2009, - 0x0001, 0x00c0, 0x2bd7, 0x6000, 0xa086, 0x0003, 0x2009, 0x0007, - 0x00c0, 0x2bd7, 0x2001, 0xa753, 0x2004, 0xd0ac, 0x2009, 0x0008, - 0x00c0, 0x2bd7, 0x1078, 0x35e4, 0x0040, 0x2bdb, 0x6004, 0xa084, - 0x00ff, 0xa086, 0x0006, 0x2009, 0x0009, 0x00c0, 0x2bd7, 0x0c7e, - 0x1078, 0x35ba, 0x0c7f, 0x2009, 0x0002, 0x0040, 0x2bd7, 0x6837, - 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x7928, 0xa194, - 0xff00, 0xa18c, 0x00ff, 0xa006, 0x82ff, 0x00c0, 0x3a65, 0xc0ed, - 0x6952, 0x792c, 0x6956, 0x0078, 0x3a6e, 0xa28e, 0x0100, 0x00c0, - 0x2bdb, 0xc0e5, 0x6853, 0x0000, 0x6857, 0x0000, 0x683e, 0x1078, - 0x90cd, 0x2009, 0x0003, 0x0040, 0x2bd7, 0x7007, 0x0003, 0x701b, - 0x3a7a, 0x007c, 0x6830, 0xa086, 0x0100, 0x2009, 0x0004, 0x0040, - 0x2bd7, 0x0078, 0x2bad, 0x81ff, 0x2009, 0x0001, 0x00c0, 0x2bd7, - 0x6000, 0xa086, 0x0003, 0x2009, 0x0007, 0x00c0, 0x2bd7, 0x1078, - 0x35e4, 0x0040, 0x2bdb, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, - 0x2009, 0x0009, 0x00c0, 0x2bd7, 0x0c7e, 0x1078, 0x35ba, 0x0c7f, - 0x2009, 0x0002, 0x0040, 0x2bd7, 0xad80, 0x000f, 0x2009, 0x0008, - 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x3604, 0x701b, 0x3ab1, - 0x007c, 0x0d7e, 0xade8, 0x000f, 0x6800, 0xa086, 0x0500, 0x00c0, - 0x3ac4, 0x6804, 0xa005, 0x00c0, 0x3ac4, 0x6808, 0xa084, 0xff00, - 0x00c0, 0x3ac4, 0x0078, 0x3ac7, 0x0d7f, 0x00c0, 0x2bdb, 0x0d7f, - 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x0c7e, - 0x1078, 0x35e4, 0x00c0, 0x3ad7, 0x0c7f, 0x0078, 0x2bdb, 0x1078, - 0x9129, 0x2009, 0x0003, 0x0c7f, 0x0040, 0x2bd7, 0x7007, 0x0003, - 0x701b, 0x3ae3, 0x007c, 0x6830, 0xa086, 0x0100, 0x2009, 0x0004, - 0x0040, 0x2bd7, 0x0078, 0x2bad, 0x127e, 0x0c7e, 0x0e7e, 0x2061, - 0x0100, 0x2071, 0xa700, 0x6044, 0xd0a4, 0x00c0, 0x3b15, 0xd084, - 0x0040, 0x3afe, 0x1078, 0x3c75, 0x0078, 0x3b11, 0xd08c, 0x0040, - 0x3b05, 0x1078, 0x3b8c, 0x0078, 0x3b11, 0xd094, 0x0040, 0x3b0c, - 0x1078, 0x3b60, 0x0078, 0x3b11, 0xd09c, 0x0040, 0x3b11, 0x1078, - 0x3b1f, 0x0e7f, 0x0c7f, 0x127f, 0x007c, 0x017e, 0x6128, 0xd19c, - 0x00c0, 0x3b1c, 0xc19d, 0x612a, 0x017f, 0x0078, 0x3b11, 0x624c, - 0xa286, 0xf0f0, 0x00c0, 0x3b30, 0x6048, 0xa086, 0xf0f0, 0x0040, - 0x3b30, 0x624a, 0x6043, 0x0090, 0x6043, 0x0010, 0x0078, 0x3b5f, - 0xa294, 0xff00, 0xa296, 0xf700, 0x0040, 0x3b45, 0x7134, 0xd1a4, - 0x00c0, 0x3b45, 0x6240, 0xa294, 0x0010, 0x0040, 0x3b45, 0x2009, - 0x00f7, 0x1078, 0x42a1, 0x0078, 0x3b5f, 0x6043, 0x0040, 0x6043, - 0x0000, 0x7077, 0x0000, 0x708f, 0x0001, 0x70b3, 0x0000, 0x70cf, - 0x0000, 0x2009, 0xadc0, 0x200b, 0x0000, 0x7087, 0x0000, 0x707b, - 0x000f, 0x2009, 0x000f, 0x2011, 0x41d5, 0x1078, 0x5add, 0x007c, - 0x157e, 0x7078, 0xa005, 0x00c0, 0x3b8a, 0x2011, 0x41d5, 0x1078, - 0x5a45, 0x6040, 0xa094, 0x0010, 0xa285, 0x0020, 0x6042, 0x20a9, - 0x00c8, 0x6044, 0xd08c, 0x00c0, 0x3b83, 0x00f0, 0x3b71, 0x6242, - 0x708b, 0x0000, 0x6040, 0xa094, 0x0010, 0xa285, 0x0080, 0x6042, - 0x6242, 0x0078, 0x3b8a, 0x6242, 0x708b, 0x0000, 0x707f, 0x0000, - 0x0078, 0x3b8a, 0x157f, 0x007c, 0x707c, 0xa08a, 0x0003, 0x00c8, - 0x3b95, 0x1079, 0x3b98, 0x0078, 0x3b97, 0x1078, 0x1332, 0x007c, - 0x3b9b, 0x3bea, 0x3c74, 0x0f7e, 0x707f, 0x0001, 0x20e1, 0xa000, - 0x20e1, 0x8700, 0x1078, 0x21f7, 0x20e1, 0x9080, 0x20e1, 0x4000, - 0x2079, 0xac00, 0x207b, 0x2200, 0x7807, 0x00ef, 0x780b, 0x0000, - 0x780f, 0x00ef, 0x7813, 0x0138, 0x7817, 0x0000, 0x781b, 0x0000, - 0x781f, 0x0000, 0x7823, 0xffff, 0x7827, 0xffff, 0x782b, 0x0000, - 0x782f, 0x0000, 0x2079, 0xac0c, 0x207b, 0x1101, 0x7807, 0x0000, - 0x2099, 0xa705, 0x20a1, 0xac0e, 0x20a9, 0x0004, 0x53a3, 0x2079, - 0xac12, 0x207b, 0x0000, 0x7807, 0x0000, 0x2099, 0xac00, 0x20a1, - 0x020b, 0x20a9, 0x0014, 0x53a6, 0x60c3, 0x000c, 0x600f, 0x0000, - 0x1078, 0x420b, 0x0f7f, 0x7083, 0x0000, 0x6043, 0x0008, 0x6043, - 0x0000, 0x007c, 0x0d7e, 0x7080, 0x7083, 0x0000, 0xa025, 0x0040, - 0x3c5e, 0x6020, 0xd0b4, 0x00c0, 0x3c5c, 0x718c, 0x81ff, 0x0040, - 0x3c4b, 0xa486, 0x000c, 0x00c0, 0x3c56, 0xa480, 0x0018, 0x8004, - 0x20a8, 0x2011, 0xac80, 0x2019, 0xac00, 0x220c, 0x2304, 0xa106, - 0x00c0, 0x3c22, 0x8210, 0x8318, 0x00f0, 0x3c05, 0x6043, 0x0004, - 0x608b, 0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0006, 0x707f, 0x0002, - 0x708b, 0x0002, 0x2009, 0x07d0, 0x2011, 0x41dc, 0x1078, 0x5add, - 0x0078, 0x3c5c, 0x2069, 0xac80, 0x6930, 0xa18e, 0x1101, 0x00c0, - 0x3c56, 0x6834, 0xa005, 0x00c0, 0x3c56, 0x6900, 0xa18c, 0x00ff, - 0x00c0, 0x3c36, 0x6804, 0xa005, 0x0040, 0x3c4b, 0x2011, 0xac8e, - 0x2019, 0xa705, 0x20a9, 0x0004, 0x220c, 0x2304, 0xa102, 0x0048, - 0x3c49, 0x00c0, 0x3c56, 0x8210, 0x8318, 0x00f0, 0x3c3c, 0x0078, - 0x3c56, 0x708f, 0x0000, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, - 0xac80, 0x20a1, 0x020b, 0x20a9, 0x0014, 0x53a6, 0x6043, 0x0008, - 0x6043, 0x0000, 0x0078, 0x3c5e, 0x0d7f, 0x007c, 0x6020, 0xd0b4, - 0x00c0, 0x3c5c, 0x60c3, 0x000c, 0x2011, 0xa9bb, 0x2013, 0x0000, - 0x7083, 0x0000, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, - 0x1078, 0x6e06, 0x0078, 0x3c5c, 0x007c, 0x7088, 0xa08a, 0x001d, - 0x00c8, 0x3c7e, 0x1079, 0x3c81, 0x0078, 0x3c80, 0x1078, 0x1332, - 0x007c, 0x3cab, 0x3cba, 0x3ce9, 0x3d02, 0x3d2e, 0x3d5a, 0x3d86, - 0x3dbc, 0x3de8, 0x3e10, 0x3e53, 0x3e7d, 0x3e9f, 0x3eb5, 0x3edb, - 0x3eee, 0x3ef7, 0x3f2b, 0x3f57, 0x3f83, 0x3faf, 0x3fe5, 0x4030, - 0x405f, 0x4081, 0x40c3, 0x40e9, 0x4102, 0x4103, 0x0c7e, 0x2061, - 0xa700, 0x6003, 0x0007, 0x2061, 0x0100, 0x6004, 0xa084, 0xfff9, - 0x6006, 0x0c7f, 0x007c, 0x608b, 0xbc94, 0x608f, 0xf0f0, 0x6043, - 0x0002, 0x708b, 0x0001, 0x2009, 0x07d0, 0x2011, 0x41dc, 0x1078, - 0x5add, 0x007c, 0x0f7e, 0x7080, 0xa086, 0x0014, 0x00c0, 0x3ce7, - 0x6043, 0x0000, 0x6020, 0xd0b4, 0x00c0, 0x3ce7, 0x2079, 0xac80, - 0x7a30, 0xa296, 0x1102, 0x00c0, 0x3ce5, 0x7834, 0xa005, 0x00c0, - 0x3ce5, 0x7a38, 0xd2fc, 0x0040, 0x3cdb, 0x70b0, 0xa005, 0x00c0, - 0x3cdb, 0x70b3, 0x0001, 0x2011, 0x41dc, 0x1078, 0x5a45, 0x708b, - 0x0010, 0x1078, 0x3ef7, 0x0078, 0x3ce7, 0x1078, 0x4224, 0x0f7f, - 0x007c, 0x708b, 0x0003, 0x6043, 0x0004, 0x2011, 0x41dc, 0x1078, - 0x5a45, 0x1078, 0x4289, 0x20a3, 0x1102, 0x20a3, 0x0000, 0x20a9, - 0x000a, 0x20a3, 0x0000, 0x00f0, 0x3cf9, 0x60c3, 0x0014, 0x1078, - 0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005, 0x0040, 0x3d2c, 0x2011, - 0x41dc, 0x1078, 0x5a45, 0xa086, 0x0014, 0x00c0, 0x3d2a, 0x2079, - 0xac80, 0x7a30, 0xa296, 0x1102, 0x00c0, 0x3d2a, 0x7834, 0xa005, - 0x00c0, 0x3d2a, 0x7a38, 0xd2fc, 0x0040, 0x3d24, 0x70b0, 0xa005, - 0x00c0, 0x3d24, 0x70b3, 0x0001, 0x708b, 0x0004, 0x1078, 0x3d2e, - 0x0078, 0x3d2c, 0x1078, 0x4224, 0x0f7f, 0x007c, 0x708b, 0x0005, - 0x1078, 0x4289, 0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430, 0x2011, - 0xac8e, 0x1078, 0x42d4, 0x00c0, 0x3d4c, 0x7074, 0xa005, 0x00c0, - 0x3d4c, 0x7150, 0xa186, 0xffff, 0x0040, 0x3d4c, 0x1078, 0x419d, - 0x0040, 0x3d4c, 0x1078, 0x42b8, 0x20a9, 0x0008, 0x2298, 0x26a0, - 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, - 0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005, 0x0040, 0x3d84, 0x2011, - 0x41dc, 0x1078, 0x5a45, 0xa086, 0x0014, 0x00c0, 0x3d82, 0x2079, - 0xac80, 0x7a30, 0xa296, 0x1103, 0x00c0, 0x3d82, 0x7834, 0xa005, - 0x00c0, 0x3d82, 0x7a38, 0xd2fc, 0x0040, 0x3d7c, 0x70b0, 0xa005, - 0x00c0, 0x3d7c, 0x70b3, 0x0001, 0x708b, 0x0006, 0x1078, 0x3d86, - 0x0078, 0x3d84, 0x1078, 0x4224, 0x0f7f, 0x007c, 0x708b, 0x0007, - 0x1078, 0x4289, 0x20a3, 0x1104, 0x20a3, 0x0000, 0x3430, 0x2011, - 0xac8e, 0x1078, 0x42d4, 0x00c0, 0x3dae, 0x7074, 0xa005, 0x00c0, - 0x3dae, 0x7154, 0xa186, 0xffff, 0x0040, 0x3dae, 0xa180, 0x29c0, - 0x200c, 0xa18c, 0xff00, 0x810f, 0x1078, 0x419d, 0x0040, 0x3dae, - 0x1078, 0x3820, 0x0040, 0x3dae, 0x1078, 0x256a, 0x20a9, 0x0008, - 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, - 0x0014, 0x1078, 0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005, 0x0040, - 0x3de6, 0x2011, 0x41dc, 0x1078, 0x5a45, 0xa086, 0x0014, 0x00c0, - 0x3de4, 0x2079, 0xac80, 0x7a30, 0xa296, 0x1104, 0x00c0, 0x3de4, - 0x7834, 0xa005, 0x00c0, 0x3de4, 0x7a38, 0xd2fc, 0x0040, 0x3dde, - 0x70b0, 0xa005, 0x00c0, 0x3dde, 0x70b3, 0x0001, 0x708b, 0x0008, - 0x1078, 0x3de8, 0x0078, 0x3de6, 0x1078, 0x4224, 0x0f7f, 0x007c, - 0x708b, 0x0009, 0x1078, 0x4289, 0x20a3, 0x1105, 0x20a3, 0x0100, - 0x3430, 0x1078, 0x42d4, 0x00c0, 0x3e01, 0x7074, 0xa005, 0x00c0, - 0x3e01, 0x1078, 0x4104, 0x00c0, 0x3e0b, 0xa085, 0x0001, 0x1078, - 0x256a, 0x20a9, 0x0008, 0x2099, 0xac8e, 0x26a0, 0x53a6, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x420b, 0x007c, - 0x0f7e, 0x7080, 0xa005, 0x0040, 0x3e51, 0x2011, 0x41dc, 0x1078, - 0x5a45, 0xa086, 0x0014, 0x00c0, 0x3e4f, 0x2079, 0xac80, 0x7a30, - 0xa296, 0x1105, 0x00c0, 0x3e4f, 0x7834, 0x2011, 0x0100, 0xa21e, - 0x00c0, 0x3e3a, 0x7a38, 0xd2fc, 0x0040, 0x3e34, 0x70b0, 0xa005, - 0x00c0, 0x3e34, 0x70b3, 0x0001, 0x708b, 0x000a, 0x1078, 0x3e53, - 0x0078, 0x3e51, 0xa005, 0x00c0, 0x3e4f, 0x7a38, 0xd2fc, 0x0040, - 0x3e47, 0x70b0, 0xa005, 0x00c0, 0x3e47, 0x70b3, 0x0001, 0x7087, - 0x0000, 0x708b, 0x000e, 0x1078, 0x3edb, 0x0078, 0x3e51, 0x1078, - 0x4224, 0x0f7f, 0x007c, 0x708b, 0x000b, 0x2011, 0xac0e, 0x22a0, - 0x20a9, 0x0040, 0x2019, 0xffff, 0x43a4, 0x20a9, 0x0002, 0x2009, - 0x0000, 0x41a4, 0x1078, 0x4289, 0x20a3, 0x1106, 0x20a3, 0x0000, - 0x1078, 0x42d4, 0x0040, 0x3e70, 0x2013, 0x0000, 0x0078, 0x3e74, - 0x6030, 0xa085, 0x0100, 0x2012, 0x2298, 0x20a9, 0x0042, 0x53a6, - 0x60c3, 0x0084, 0x1078, 0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005, - 0x0040, 0x3e9d, 0x2011, 0x41dc, 0x1078, 0x5a45, 0xa086, 0x0084, - 0x00c0, 0x3e9b, 0x2079, 0xac80, 0x7a30, 0xa296, 0x1106, 0x00c0, - 0x3e9b, 0x7834, 0xa005, 0x00c0, 0x3e9b, 0x708b, 0x000c, 0x1078, - 0x3e9f, 0x0078, 0x3e9d, 0x1078, 0x4224, 0x0f7f, 0x007c, 0x708b, - 0x000d, 0x1078, 0x4289, 0x20a3, 0x1107, 0x20a3, 0x0000, 0x2099, - 0xac8e, 0x20a9, 0x0040, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x60c3, 0x0084, 0x1078, 0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005, - 0x0040, 0x3ed9, 0x2011, 0x41dc, 0x1078, 0x5a45, 0xa086, 0x0084, - 0x00c0, 0x3ed7, 0x2079, 0xac80, 0x7a30, 0xa296, 0x1107, 0x00c0, - 0x3ed7, 0x7834, 0xa005, 0x00c0, 0x3ed7, 0x7087, 0x0001, 0x1078, - 0x427b, 0x708b, 0x000e, 0x1078, 0x3edb, 0x0078, 0x3ed9, 0x1078, - 0x4224, 0x0f7f, 0x007c, 0x708b, 0x000f, 0x7083, 0x0000, 0x608b, - 0xbc85, 0x608f, 0xb5b5, 0x6043, 0x0005, 0x6043, 0x0004, 0x2009, - 0x07d0, 0x2011, 0x41dc, 0x1078, 0x5a38, 0x007c, 0x7080, 0xa005, - 0x0040, 0x3ef6, 0x2011, 0x41dc, 0x1078, 0x5a45, 0x007c, 0x708b, - 0x0011, 0x1078, 0x42d4, 0x00c0, 0x3f14, 0x716c, 0x81ff, 0x0040, - 0x3f14, 0x2009, 0x0000, 0x7070, 0xa084, 0x00ff, 0x1078, 0x254d, - 0xa186, 0x007e, 0x0040, 0x3f14, 0xa186, 0x0080, 0x0040, 0x3f14, - 0x2011, 0xac8e, 0x1078, 0x419d, 0x20e1, 0x9080, 0x20e1, 0x4000, - 0x2099, 0xac80, 0x20a1, 0x020b, 0x7480, 0xa480, 0x0018, 0xa080, - 0x0007, 0xa084, 0x03f8, 0x8004, 0x20a8, 0x53a6, 0x60c3, 0x0014, - 0x1078, 0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005, 0x0040, 0x3f55, - 0x2011, 0x41dc, 0x1078, 0x5a45, 0xa086, 0x0014, 0x00c0, 0x3f53, - 0x2079, 0xac80, 0x7a30, 0xa296, 0x1103, 0x00c0, 0x3f53, 0x7834, - 0xa005, 0x00c0, 0x3f53, 0x7a38, 0xd2fc, 0x0040, 0x3f4d, 0x70b0, - 0xa005, 0x00c0, 0x3f4d, 0x70b3, 0x0001, 0x708b, 0x0012, 0x1078, - 0x3f57, 0x0078, 0x3f55, 0x1078, 0x4224, 0x0f7f, 0x007c, 0x708b, - 0x0013, 0x1078, 0x4295, 0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430, - 0x2011, 0xac8e, 0x1078, 0x42d4, 0x00c0, 0x3f75, 0x7074, 0xa005, - 0x00c0, 0x3f75, 0x7150, 0xa186, 0xffff, 0x0040, 0x3f75, 0x1078, - 0x419d, 0x0040, 0x3f75, 0x1078, 0x42b8, 0x20a9, 0x0008, 0x2298, - 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, - 0x1078, 0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005, 0x0040, 0x3fad, - 0x2011, 0x41dc, 0x1078, 0x5a45, 0xa086, 0x0014, 0x00c0, 0x3fab, - 0x2079, 0xac80, 0x7a30, 0xa296, 0x1104, 0x00c0, 0x3fab, 0x7834, - 0xa005, 0x00c0, 0x3fab, 0x7a38, 0xd2fc, 0x0040, 0x3fa5, 0x70b0, - 0xa005, 0x00c0, 0x3fa5, 0x70b3, 0x0001, 0x708b, 0x0014, 0x1078, - 0x3faf, 0x0078, 0x3fad, 0x1078, 0x4224, 0x0f7f, 0x007c, 0x708b, - 0x0015, 0x1078, 0x4295, 0x20a3, 0x1104, 0x20a3, 0x0000, 0x3430, - 0x2011, 0xac8e, 0x1078, 0x42d4, 0x00c0, 0x3fd7, 0x7074, 0xa005, - 0x00c0, 0x3fd7, 0x7154, 0xa186, 0xffff, 0x0040, 0x3fd7, 0xa180, - 0x29c0, 0x200c, 0xa18c, 0xff00, 0x810f, 0x1078, 0x419d, 0x0040, - 0x3fd7, 0x1078, 0x3820, 0x0040, 0x3fd7, 0x1078, 0x256a, 0x20a9, - 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x60c3, 0x0014, 0x1078, 0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005, - 0x0040, 0x402e, 0x2011, 0x41dc, 0x1078, 0x5a45, 0xa086, 0x0014, - 0x00c0, 0x402c, 0x2079, 0xac80, 0x7a30, 0xa296, 0x1105, 0x00c0, - 0x402c, 0x7834, 0x2011, 0x0100, 0xa21e, 0x00c0, 0x400b, 0x7a38, - 0xd2fc, 0x0040, 0x4009, 0x70b0, 0xa005, 0x00c0, 0x4009, 0x70b3, - 0x0001, 0x0078, 0x401a, 0xa005, 0x00c0, 0x402c, 0x7a38, 0xd2fc, - 0x0040, 0x4018, 0x70b0, 0xa005, 0x00c0, 0x4018, 0x70b3, 0x0001, - 0x7087, 0x0000, 0x7a38, 0xd2f4, 0x0040, 0x4026, 0x2001, 0xa774, - 0x2004, 0xd0a4, 0x00c0, 0x4026, 0x70cf, 0x0008, 0x708b, 0x0016, - 0x1078, 0x4030, 0x0078, 0x402e, 0x1078, 0x4224, 0x0f7f, 0x007c, - 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xac80, 0x20a1, 0x020b, - 0x20a9, 0x000e, 0x53a6, 0x3430, 0x2011, 0xac8e, 0x708b, 0x0017, - 0x1078, 0x42d4, 0x00c0, 0x4050, 0x7074, 0xa005, 0x00c0, 0x4050, - 0x1078, 0x4104, 0x00c0, 0x405a, 0xa085, 0x0001, 0x1078, 0x256a, - 0x20a9, 0x0008, 0x2099, 0xac8e, 0x26a0, 0x53a6, 0x20a3, 0x0000, - 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x420b, 0x007c, 0x0f7e, - 0x7080, 0xa005, 0x0040, 0x407f, 0x2011, 0x41dc, 0x1078, 0x5a45, - 0xa086, 0x0084, 0x00c0, 0x407d, 0x2079, 0xac80, 0x7a30, 0xa296, - 0x1106, 0x00c0, 0x407d, 0x7834, 0xa005, 0x00c0, 0x407d, 0x708b, - 0x0018, 0x1078, 0x4081, 0x0078, 0x407f, 0x1078, 0x4224, 0x0f7f, - 0x007c, 0x708b, 0x0019, 0x1078, 0x4295, 0x20a3, 0x1106, 0x20a3, - 0x0000, 0x3430, 0x2099, 0xac8e, 0x2039, 0xac0e, 0x27a0, 0x20a9, - 0x0040, 0x53a3, 0x1078, 0x42d4, 0x00c0, 0x40b5, 0x2728, 0x2514, - 0x8207, 0xa084, 0x00ff, 0x8000, 0x2018, 0xa294, 0x00ff, 0x8007, - 0xa205, 0x202a, 0x6030, 0x2310, 0x8214, 0xa2a0, 0xac0e, 0x2414, - 0xa38c, 0x0001, 0x0040, 0x40b0, 0xa294, 0xff00, 0x0078, 0x40b3, - 0xa294, 0x00ff, 0x8007, 0xa215, 0x2222, 0x2798, 0x26a0, 0x20a9, - 0x0040, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0084, - 0x1078, 0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005, 0x0040, 0x40e7, - 0x2011, 0x41dc, 0x1078, 0x5a45, 0xa086, 0x0084, 0x00c0, 0x40e5, - 0x2079, 0xac80, 0x7a30, 0xa296, 0x1107, 0x00c0, 0x40e5, 0x7834, - 0xa005, 0x00c0, 0x40e5, 0x7087, 0x0001, 0x1078, 0x427b, 0x708b, - 0x001a, 0x1078, 0x40e9, 0x0078, 0x40e7, 0x1078, 0x4224, 0x0f7f, - 0x007c, 0x708b, 0x001b, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, - 0xac80, 0x20a1, 0x020b, 0x7480, 0xa480, 0x0018, 0xa080, 0x0007, - 0xa084, 0x03f8, 0x8004, 0x20a8, 0x53a6, 0x60c3, 0x0084, 0x1078, - 0x420b, 0x007c, 0x007c, 0x007c, 0x087e, 0x097e, 0x2029, 0xa753, - 0x252c, 0x20a9, 0x0008, 0x2041, 0xac0e, 0x28a0, 0x2099, 0xac8e, - 0x53a3, 0x20a9, 0x0008, 0x2011, 0x0007, 0xd5d4, 0x0040, 0x411a, - 0x2011, 0x0000, 0x2800, 0xa200, 0x200c, 0xa1a6, 0xffff, 0x00c0, - 0x412c, 0xd5d4, 0x0040, 0x4127, 0x8210, 0x0078, 0x4128, 0x8211, - 0x00f0, 0x411a, 0x0078, 0x4194, 0x82ff, 0x00c0, 0x413e, 0xd5d4, - 0x0040, 0x4138, 0xa1a6, 0x3fff, 0x0040, 0x4124, 0x0078, 0x413c, - 0xa1a6, 0x3fff, 0x0040, 0x4194, 0xa18d, 0xc000, 0x20a9, 0x0010, - 0x2019, 0x0001, 0xd5d4, 0x0040, 0x4147, 0x2019, 0x0010, 0x2120, - 0xd5d4, 0x0040, 0x414e, 0x8423, 0x0078, 0x414f, 0x8424, 0x00c8, - 0x415c, 0xd5d4, 0x0040, 0x4157, 0x8319, 0x0078, 0x4158, 0x8318, - 0x00f0, 0x4148, 0x0078, 0x4194, 0x23a8, 0x2021, 0x0001, 0x8426, - 0x8425, 0x00f0, 0x4160, 0x2328, 0x8529, 0xa2be, 0x0007, 0x0040, - 0x4174, 0x007e, 0x2039, 0x0007, 0x2200, 0xa73a, 0x007f, 0x27a8, - 0xa5a8, 0x0010, 0x00f0, 0x4170, 0x7552, 0xa5c8, 0x29c0, 0x292c, - 0xa5ac, 0x00ff, 0x6532, 0x60e7, 0x0000, 0x65ea, 0x706f, 0x0000, - 0x7572, 0x2018, 0x2304, 0xa405, 0x201a, 0x7077, 0x0001, 0x26a0, - 0x2898, 0x20a9, 0x0008, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0xa085, 0x0001, 0x0078, 0x419a, 0xa006, 0x0078, 0x419a, 0xa006, - 0x1078, 0x1332, 0x097f, 0x087f, 0x007c, 0x2118, 0x2021, 0x0000, - 0x2001, 0x0007, 0xa39a, 0x0010, 0x0048, 0x41aa, 0x8420, 0x8001, - 0x0078, 0x41a2, 0x2118, 0x84ff, 0x0040, 0x41b3, 0xa39a, 0x0010, - 0x8421, 0x00c0, 0x41ae, 0x2021, 0x0001, 0x83ff, 0x0040, 0x41bc, - 0x8423, 0x8319, 0x00c0, 0x41b8, 0xa238, 0x2704, 0xa42c, 0x00c0, - 0x41d4, 0xa405, 0x203a, 0x7152, 0xa1a0, 0x29c0, 0x242c, 0xa5ac, - 0x00ff, 0x6532, 0x60e7, 0x0000, 0x65ea, 0x706f, 0x0000, 0x7572, - 0x7077, 0x0001, 0xa084, 0x0000, 0x007c, 0x0e7e, 0x2071, 0xa700, - 0x707b, 0x0000, 0x0e7f, 0x007c, 0x0e7e, 0x0f7e, 0x2001, 0x0002, - 0x1078, 0x5ae6, 0x2079, 0x0100, 0x2071, 0x0140, 0x1078, 0x6e0f, - 0x7004, 0xa084, 0x4000, 0x0040, 0x41f1, 0x7003, 0x1000, 0x7003, - 0x0000, 0x127e, 0x2091, 0x8000, 0x2071, 0xa722, 0x2073, 0x0000, - 0x7840, 0x027e, 0x017e, 0x2009, 0x00f7, 0x1078, 0x42a1, 0x017f, - 0xa094, 0x0010, 0xa285, 0x0080, 0x7842, 0x7a42, 0x027f, 0x127f, - 0x0f7f, 0x0e7f, 0x007c, 0x127e, 0x2091, 0x8000, 0x2011, 0xa9bb, - 0x2013, 0x0000, 0x7083, 0x0000, 0x127f, 0x20e1, 0x9080, 0x60a3, - 0x0056, 0x60a7, 0x9575, 0x1078, 0x6e06, 0x2009, 0x07d0, 0x2011, - 0x41dc, 0x1078, 0x5add, 0x007c, 0x017e, 0x027e, 0x0c7e, 0x127e, - 0x2091, 0x8000, 0x2011, 0x0003, 0x1078, 0x70e0, 0x2011, 0x0002, - 0x1078, 0x70ea, 0x1078, 0x6fc4, 0x037e, 0x2019, 0x0000, 0x1078, - 0x7058, 0x037f, 0x2009, 0x00f7, 0x1078, 0x42a1, 0x2061, 0xa9c4, - 0x601b, 0x0000, 0x601f, 0x0000, 0x2061, 0xa700, 0x6003, 0x0001, - 0x2061, 0x0100, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0x002d, - 0x2011, 0x4259, 0x1078, 0x5a38, 0x127f, 0x0c7f, 0x027f, 0x017f, - 0x007c, 0x0e7e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2001, 0x0001, - 0x1078, 0x5ae6, 0x2071, 0x0100, 0x1078, 0x6e0f, 0x2071, 0x0140, - 0x7004, 0xa084, 0x4000, 0x0040, 0x4271, 0x7003, 0x1000, 0x7003, - 0x0000, 0x2001, 0x0001, 0x1078, 0x24e8, 0x1078, 0x4224, 0x127f, - 0x007f, 0x0e7f, 0x007c, 0x20a9, 0x0040, 0x20a1, 0xadc0, 0x2099, - 0xac8e, 0x3304, 0x8007, 0x20a2, 0x9398, 0x94a0, 0x00f0, 0x4281, - 0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xac00, 0x20a1, - 0x020b, 0x20a9, 0x000c, 0x53a6, 0x007c, 0x20e1, 0x9080, 0x20e1, - 0x4000, 0x2099, 0xac80, 0x20a1, 0x020b, 0x20a9, 0x000c, 0x53a6, - 0x007c, 0x0c7e, 0x007e, 0x2061, 0x0100, 0x810f, 0x2001, 0xa72f, - 0x2004, 0xa005, 0x00c0, 0x42b2, 0x6030, 0xa084, 0x00ff, 0xa105, - 0x0078, 0x42b4, 0xa185, 0x00f7, 0x604a, 0x007f, 0x0c7f, 0x007c, - 0x017e, 0x047e, 0x2001, 0xa753, 0x2004, 0xd0a4, 0x0040, 0x42cb, - 0xa006, 0x2020, 0x2009, 0x002a, 0x1078, 0xa22d, 0x2001, 0xa70c, - 0x200c, 0xc195, 0x2102, 0x2019, 0x002a, 0x2009, 0x0000, 0x1078, - 0x284f, 0x047f, 0x017f, 0x007c, 0x007e, 0x2001, 0xa70c, 0x2004, - 0xd09c, 0x0040, 0x42db, 0x007f, 0x007c, 0x007e, 0x017e, 0x127e, - 0x2091, 0x8000, 0x2001, 0x0101, 0x200c, 0xa18d, 0x0006, 0x2102, - 0x127f, 0x017f, 0x007f, 0x007c, 0x157e, 0x20a9, 0x00ff, 0x2009, - 0xa835, 0xa006, 0x200a, 0x8108, 0x00f0, 0x42f2, 0x157f, 0x007c, - 0x0d7e, 0x037e, 0x157e, 0x137e, 0x147e, 0x2069, 0xa752, 0xa006, - 0x6002, 0x6007, 0x0707, 0x600a, 0x600e, 0x6012, 0xa198, 0x29c0, - 0x231c, 0xa39c, 0x00ff, 0x6316, 0x20a9, 0x0004, 0xac98, 0x0006, - 0x23a0, 0x40a4, 0x20a9, 0x0004, 0xac98, 0x000a, 0x23a0, 0x40a4, - 0x603e, 0x6042, 0x604e, 0x6052, 0x6056, 0x605a, 0x605e, 0x6062, - 0x6066, 0x606a, 0x606e, 0x6072, 0x6076, 0x607a, 0x607e, 0x6082, - 0x6086, 0x608a, 0x608e, 0x6092, 0x6096, 0x609a, 0x609e, 0x60ae, - 0x61a2, 0x0d7e, 0x60a4, 0xa06d, 0x0040, 0x4338, 0x1078, 0x13a4, - 0x60a7, 0x0000, 0x60a8, 0xa06d, 0x0040, 0x4340, 0x1078, 0x13a4, - 0x60ab, 0x0000, 0x0d7f, 0xa006, 0x604a, 0x6810, 0x603a, 0x680c, - 0x6046, 0x6814, 0xa084, 0x00ff, 0x6042, 0x147f, 0x137f, 0x157f, - 0x037f, 0x0d7f, 0x007c, 0x127e, 0x2091, 0x8000, 0x6944, 0x6e48, - 0xa684, 0x3fff, 0xa082, 0x4000, 0x00c8, 0x4424, 0xa18c, 0xff00, - 0x810f, 0xa182, 0x00ff, 0x00c8, 0x442a, 0x2001, 0xa70c, 0x2004, - 0xa084, 0x0003, 0x0040, 0x4385, 0x2001, 0xa70c, 0x2004, 0xd084, - 0x00c0, 0x4405, 0xa188, 0xa835, 0x2104, 0xa065, 0x0040, 0x4405, - 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, 0x00c0, 0x4405, 0x6000, - 0xd0c4, 0x0040, 0x4405, 0x0078, 0x4392, 0xa188, 0xa835, 0x2104, - 0xa065, 0x0040, 0x43e9, 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, - 0x00c0, 0x43ef, 0x60a4, 0xa00d, 0x0040, 0x439a, 0x1078, 0x4817, - 0x0040, 0x43e3, 0x60a8, 0xa00d, 0x0040, 0x43b4, 0x1078, 0x486a, - 0x00c0, 0x43b4, 0x694c, 0xd1fc, 0x00c0, 0x43aa, 0x1078, 0x44df, - 0x0078, 0x43de, 0x1078, 0x4484, 0x694c, 0xd1ec, 0x00c0, 0x43de, - 0x1078, 0x46d6, 0x0078, 0x43de, 0x694c, 0xa184, 0xa000, 0x0040, - 0x43ce, 0xd1ec, 0x0040, 0x43c7, 0xd1fc, 0x0040, 0x43c3, 0x1078, - 0x46e7, 0x0078, 0x43ca, 0x1078, 0x46e7, 0x0078, 0x43ce, 0xd1fc, - 0x0040, 0x43ce, 0x1078, 0x4484, 0x0078, 0x43de, 0x6050, 0xa00d, - 0x0040, 0x43d9, 0x2d00, 0x200a, 0x6803, 0x0000, 0x6052, 0x0078, - 0x43de, 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x1078, 0x5da9, - 0xa006, 0x127f, 0x007c, 0x2001, 0x0005, 0x2009, 0x0000, 0x0078, - 0x442e, 0x2001, 0x0028, 0x2009, 0x0000, 0x0078, 0x442e, 0xa082, - 0x0006, 0x00c8, 0x4405, 0x60a0, 0xd0bc, 0x00c0, 0x4401, 0x6100, - 0xd1fc, 0x0040, 0x4392, 0x2001, 0x0029, 0x2009, 0x1000, 0x0078, - 0x442e, 0x2001, 0x0028, 0x0078, 0x4420, 0x2009, 0xa70c, 0x210c, - 0xd18c, 0x0040, 0x440f, 0x2001, 0x0004, 0x0078, 0x4420, 0xd184, - 0x0040, 0x4416, 0x2001, 0x0004, 0x0078, 0x4420, 0x2001, 0x0029, - 0x6100, 0xd1fc, 0x0040, 0x4420, 0x2009, 0x1000, 0x0078, 0x442e, - 0x2009, 0x0000, 0x0078, 0x442e, 0x2001, 0x0029, 0x2009, 0x0000, - 0x0078, 0x442e, 0x2001, 0x0029, 0x2009, 0x0000, 0xa005, 0x127f, - 0x007c, 0x6944, 0x6e48, 0xa684, 0x3fff, 0xa082, 0x4000, 0x00c8, - 0x447e, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, 0x00c8, 0x4464, - 0xa188, 0xa835, 0x2104, 0xa065, 0x0040, 0x4464, 0x6004, 0xa084, - 0x00ff, 0xa08e, 0x0006, 0x00c0, 0x446a, 0x684c, 0xd0ec, 0x0040, - 0x4457, 0x1078, 0x46e7, 0x1078, 0x4484, 0x0078, 0x445f, 0x1078, - 0x4484, 0x684c, 0xd0fc, 0x0040, 0x445f, 0x1078, 0x46d6, 0x1078, - 0x472f, 0xa006, 0x0078, 0x4482, 0x2001, 0x0028, 0x2009, 0x0000, - 0x0078, 0x4482, 0xa082, 0x0006, 0x00c8, 0x4478, 0x6100, 0xd1fc, - 0x0040, 0x444d, 0x2001, 0x0029, 0x2009, 0x1000, 0x0078, 0x4482, - 0x2001, 0x0029, 0x2009, 0x0000, 0x0078, 0x4482, 0x2001, 0x0029, - 0x2009, 0x0000, 0xa005, 0x007c, 0x127e, 0x2091, 0x8000, 0x6050, - 0xa00d, 0x0040, 0x4492, 0x2d00, 0x200a, 0x6803, 0x0000, 0x6052, - 0x127f, 0x007c, 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x0078, - 0x4490, 0x127e, 0x2091, 0x8000, 0x604c, 0xa005, 0x0040, 0x44af, - 0x0e7e, 0x2071, 0xa9b1, 0x7004, 0xa086, 0x0002, 0x0040, 0x44b6, - 0x0e7f, 0x604c, 0x6802, 0x2d00, 0x604e, 0x127f, 0x007c, 0x2d00, - 0x6052, 0x604e, 0x6803, 0x0000, 0x0078, 0x44ad, 0x701c, 0xac06, - 0x00c0, 0x44a8, 0x604c, 0x2070, 0x7000, 0x6802, 0x2d00, 0x7002, - 0x0e7f, 0x127f, 0x007c, 0x127e, 0x2091, 0x8000, 0x604c, 0xa06d, - 0x0040, 0x44d1, 0x6800, 0xa005, 0x00c0, 0x44cf, 0x6052, 0x604e, - 0xad05, 0x127f, 0x007c, 0x604c, 0xa06d, 0x0040, 0x44de, 0x6800, - 0xa005, 0x00c0, 0x44dc, 0x6052, 0x604e, 0xad05, 0x007c, 0x6803, - 0x0000, 0x6084, 0xa00d, 0x0040, 0x44e9, 0x2d00, 0x200a, 0x6086, - 0x007c, 0x2d00, 0x6086, 0x6082, 0x0078, 0x44e8, 0x127e, 0x0c7e, - 0x027e, 0x2091, 0x8000, 0x6218, 0x2260, 0x6200, 0xa005, 0x0040, - 0x44fc, 0xc285, 0x0078, 0x44fd, 0xc284, 0x6202, 0x027f, 0x0c7f, - 0x127f, 0x007c, 0x127e, 0x0c7e, 0x2091, 0x8000, 0x6218, 0x2260, - 0x6204, 0x007e, 0xa086, 0x0006, 0x00c0, 0x4521, 0x609c, 0xd0ac, - 0x0040, 0x4521, 0x2001, 0xa753, 0x2004, 0xd0a4, 0x0040, 0x4521, - 0xa284, 0xff00, 0x8007, 0xa086, 0x0007, 0x00c0, 0x4521, 0x2011, - 0x0600, 0x007f, 0xa294, 0xff00, 0xa215, 0x6206, 0x007e, 0xa086, - 0x0006, 0x00c0, 0x4531, 0x6290, 0x82ff, 0x00c0, 0x4531, 0x1078, - 0x1332, 0x007f, 0x0c7f, 0x127f, 0x007c, 0x127e, 0x0c7e, 0x2091, - 0x8000, 0x6218, 0x2260, 0x6204, 0x007e, 0xa086, 0x0006, 0x00c0, - 0x4553, 0x609c, 0xd0a4, 0x0040, 0x4553, 0x2001, 0xa753, 0x2004, - 0xd0ac, 0x00c0, 0x4553, 0xa284, 0x00ff, 0xa086, 0x0007, 0x00c0, - 0x4553, 0x2011, 0x0006, 0x007f, 0xa294, 0x00ff, 0x8007, 0xa215, - 0x6206, 0x0c7f, 0x127f, 0x007c, 0x027e, 0xa182, 0x00ff, 0x0048, - 0x4565, 0xa085, 0x0001, 0x0078, 0x457d, 0xa190, 0xa835, 0x2204, - 0xa065, 0x00c0, 0x457c, 0x017e, 0x0d7e, 0x1078, 0x1370, 0x2d60, - 0x0d7f, 0x017f, 0x0040, 0x4561, 0x2c00, 0x2012, 0x60a7, 0x0000, - 0x60ab, 0x0000, 0x1078, 0x42f8, 0xa006, 0x027f, 0x007c, 0x127e, - 0x2091, 0x8000, 0x027e, 0xa182, 0x00ff, 0x0048, 0x458b, 0xa085, - 0x0001, 0x0078, 0x45c1, 0x0d7e, 0xa190, 0xa835, 0x2204, 0xa06d, - 0x0040, 0x45bf, 0x2013, 0x0000, 0x0d7e, 0x0c7e, 0x2d60, 0x60a4, - 0xa06d, 0x0040, 0x459d, 0x1078, 0x13a4, 0x60a8, 0xa06d, 0x0040, - 0x45a3, 0x1078, 0x13a4, 0x0c7f, 0x0d7f, 0x0d7e, 0x0c7e, 0x68ac, - 0x2060, 0x8cff, 0x0040, 0x45bb, 0x600c, 0x007e, 0x6010, 0x2068, - 0x1078, 0x8d16, 0x0040, 0x45b6, 0x1078, 0x13b4, 0x1078, 0x772d, - 0x0c7f, 0x0078, 0x45a9, 0x0c7f, 0x0d7f, 0x1078, 0x13a4, 0x0d7f, - 0xa006, 0x027f, 0x127f, 0x007c, 0x017e, 0xa182, 0x00ff, 0x0048, - 0x45cd, 0xa085, 0x0001, 0x0078, 0x45d4, 0xa188, 0xa835, 0x2104, - 0xa065, 0x0040, 0x45c9, 0xa006, 0x017f, 0x007c, 0x0d7e, 0x157e, - 0x137e, 0x147e, 0x600b, 0x0000, 0x600f, 0x0000, 0x6000, 0xc08c, - 0x6002, 0x2069, 0xac8e, 0x6808, 0x605e, 0x6810, 0x6062, 0x6138, - 0xa10a, 0x0048, 0x45ec, 0x603a, 0x6814, 0x6066, 0x2099, 0xac96, - 0xac88, 0x000a, 0x21a0, 0x20a9, 0x0004, 0x53a3, 0x2099, 0xac9a, - 0xac88, 0x0006, 0x21a0, 0x20a9, 0x0004, 0x53a3, 0x2069, 0xacae, - 0x6808, 0x606a, 0x690c, 0x616e, 0x6810, 0x6072, 0x6818, 0x6076, - 0x60a0, 0xa086, 0x007e, 0x00c0, 0x4611, 0x2069, 0xac8e, 0x690c, - 0x616e, 0xa182, 0x0211, 0x00c8, 0x4619, 0x2009, 0x0008, 0x0078, - 0x4643, 0xa182, 0x0259, 0x00c8, 0x4621, 0x2009, 0x0007, 0x0078, - 0x4643, 0xa182, 0x02c1, 0x00c8, 0x4629, 0x2009, 0x0006, 0x0078, - 0x4643, 0xa182, 0x0349, 0x00c8, 0x4631, 0x2009, 0x0005, 0x0078, - 0x4643, 0xa182, 0x0421, 0x00c8, 0x4639, 0x2009, 0x0004, 0x0078, - 0x4643, 0xa182, 0x0581, 0x00c8, 0x4641, 0x2009, 0x0003, 0x0078, - 0x4643, 0x2009, 0x0002, 0x6192, 0x147f, 0x137f, 0x157f, 0x0d7f, - 0x007c, 0x017e, 0x027e, 0x0e7e, 0x2071, 0xac8d, 0x2e04, 0x6896, - 0x2071, 0xac8e, 0x7004, 0x689a, 0x701c, 0x689e, 0x6a00, 0x2009, - 0xa772, 0x210c, 0xd0bc, 0x0040, 0x4663, 0xd1ec, 0x0040, 0x4663, - 0xc2ad, 0x0078, 0x4664, 0xc2ac, 0xd0c4, 0x0040, 0x466d, 0xd1e4, - 0x0040, 0x466d, 0xc2bd, 0x0078, 0x466e, 0xc2bc, 0x6a02, 0x0e7f, - 0x027f, 0x017f, 0x007c, 0x0d7e, 0x127e, 0x2091, 0x8000, 0x60a4, - 0xa06d, 0x0040, 0x4697, 0x6900, 0x81ff, 0x00c0, 0x46ab, 0x6a04, - 0xa282, 0x0010, 0x00c8, 0x46b0, 0xad88, 0x0004, 0x20a9, 0x0010, - 0x2104, 0xa086, 0xffff, 0x0040, 0x4692, 0x8108, 0x00f0, 0x4688, - 0x1078, 0x1332, 0x260a, 0x8210, 0x6a06, 0x0078, 0x46ab, 0x1078, - 0x138b, 0x0040, 0x46b0, 0x2d00, 0x60a6, 0x6803, 0x0000, 0xad88, - 0x0004, 0x20a9, 0x0010, 0x200b, 0xffff, 0x8108, 0x00f0, 0x46a3, - 0x6807, 0x0001, 0x6e12, 0xa085, 0x0001, 0x127f, 0x0d7f, 0x007c, - 0xa006, 0x0078, 0x46ad, 0x127e, 0x2091, 0x8000, 0x0d7e, 0x60a4, - 0xa00d, 0x0040, 0x46d3, 0x2168, 0x6800, 0xa005, 0x00c0, 0x46cf, - 0x1078, 0x4817, 0x00c0, 0x46d3, 0x200b, 0xffff, 0x6804, 0xa08a, - 0x0002, 0x0048, 0x46cf, 0x8001, 0x6806, 0x0078, 0x46d3, 0x1078, - 0x13a4, 0x60a7, 0x0000, 0x0d7f, 0x127f, 0x007c, 0x127e, 0x2091, - 0x8000, 0x1078, 0x487f, 0x0078, 0x46df, 0x1078, 0x4484, 0x1078, - 0x4775, 0x00c0, 0x46dd, 0x1078, 0x472f, 0x127f, 0x007c, 0x0d7e, - 0x127e, 0x2091, 0x8000, 0x60a8, 0xa06d, 0x0040, 0x470b, 0x6950, - 0x81ff, 0x00c0, 0x471f, 0x6a54, 0xa282, 0x0010, 0x00c8, 0x472c, - 0xad88, 0x0018, 0x20a9, 0x0010, 0x2104, 0xa086, 0xffff, 0x0040, - 0x4706, 0x8108, 0x00f0, 0x46fc, 0x1078, 0x1332, 0x260a, 0x8210, - 0x6a56, 0x0078, 0x471f, 0x1078, 0x138b, 0x0040, 0x472c, 0x2d00, - 0x60aa, 0x6853, 0x0000, 0xad88, 0x0018, 0x20a9, 0x0010, 0x200b, - 0xffff, 0x8108, 0x00f0, 0x4717, 0x6857, 0x0001, 0x6e62, 0x0078, - 0x4723, 0x1078, 0x44df, 0x1078, 0x4739, 0x00c0, 0x4721, 0xa085, - 0x0001, 0x127f, 0x0d7f, 0x007c, 0xa006, 0x0078, 0x4729, 0x127e, - 0x2091, 0x8000, 0x1078, 0x5da9, 0x127f, 0x007c, 0xa01e, 0x0078, - 0x473b, 0x2019, 0x0001, 0xa00e, 0x127e, 0x2091, 0x8000, 0x604c, - 0x2068, 0x6000, 0xd0dc, 0x00c0, 0x4759, 0x8dff, 0x0040, 0x4770, - 0x83ff, 0x0040, 0x4751, 0x6848, 0xa606, 0x0040, 0x475e, 0x0078, - 0x4759, 0x683c, 0xa406, 0x00c0, 0x4759, 0x6840, 0xa506, 0x0040, - 0x475e, 0x2d08, 0x6800, 0x2068, 0x0078, 0x4745, 0x1078, 0x7233, - 0x6a00, 0x604c, 0xad06, 0x00c0, 0x4768, 0x624e, 0x0078, 0x476b, - 0xa180, 0x0000, 0x2202, 0x82ff, 0x00c0, 0x4770, 0x6152, 0x8dff, - 0x127f, 0x007c, 0xa01e, 0x0078, 0x4777, 0x2019, 0x0001, 0xa00e, - 0x6080, 0x2068, 0x8dff, 0x0040, 0x47a3, 0x83ff, 0x0040, 0x4786, - 0x6848, 0xa606, 0x0040, 0x4793, 0x0078, 0x478e, 0x683c, 0xa406, - 0x00c0, 0x478e, 0x6840, 0xa506, 0x0040, 0x4793, 0x2d08, 0x6800, - 0x2068, 0x0078, 0x477a, 0x6a00, 0x6080, 0xad06, 0x00c0, 0x479b, - 0x6282, 0x0078, 0x479e, 0xa180, 0x0000, 0x2202, 0x82ff, 0x00c0, - 0x47a3, 0x6186, 0x8dff, 0x007c, 0xa016, 0x1078, 0x4810, 0x00c0, - 0x47ab, 0x2011, 0x0001, 0x1078, 0x4863, 0x00c0, 0x47b1, 0xa295, - 0x0002, 0x007c, 0x1078, 0x489b, 0x0040, 0x47ba, 0x1078, 0x8dda, - 0x0078, 0x47bc, 0xa085, 0x0001, 0x007c, 0x1078, 0x489b, 0x0040, - 0x47c5, 0x1078, 0x8d72, 0x0078, 0x47c7, 0xa085, 0x0001, 0x007c, - 0x1078, 0x489b, 0x0040, 0x47d0, 0x1078, 0x8dbc, 0x0078, 0x47d2, - 0xa085, 0x0001, 0x007c, 0x1078, 0x489b, 0x0040, 0x47db, 0x1078, - 0x8d8e, 0x0078, 0x47dd, 0xa085, 0x0001, 0x007c, 0x1078, 0x489b, - 0x0040, 0x47e6, 0x1078, 0x8df8, 0x0078, 0x47e8, 0xa085, 0x0001, - 0x007c, 0x127e, 0x007e, 0x0d7e, 0x2091, 0x8000, 0x6080, 0xa06d, - 0x0040, 0x4808, 0x6800, 0x007e, 0x6837, 0x0103, 0x6b4a, 0x6847, - 0x0000, 0x1078, 0x8f8d, 0x007e, 0x6000, 0xd0fc, 0x0040, 0x4802, - 0x1078, 0xa4fd, 0x007f, 0x1078, 0x4a73, 0x007f, 0x0078, 0x47ef, - 0x6083, 0x0000, 0x6087, 0x0000, 0x0d7f, 0x007f, 0x127f, 0x007c, - 0x60a4, 0xa00d, 0x00c0, 0x4817, 0xa085, 0x0001, 0x007c, 0x0e7e, - 0x2170, 0x7000, 0xa005, 0x00c0, 0x482c, 0x20a9, 0x0010, 0xae88, - 0x0004, 0x2104, 0xa606, 0x0040, 0x482c, 0x8108, 0x00f0, 0x4821, - 0xa085, 0x0001, 0x0078, 0x482d, 0xa006, 0x0e7f, 0x007c, 0x0d7e, - 0x127e, 0x2091, 0x8000, 0x60a4, 0xa06d, 0x00c0, 0x483d, 0x1078, - 0x138b, 0x0040, 0x484f, 0x2d00, 0x60a6, 0x6803, 0x0001, 0x6807, - 0x0000, 0xad88, 0x0004, 0x20a9, 0x0010, 0x200b, 0xffff, 0x8108, - 0x00f0, 0x4845, 0xa085, 0x0001, 0x127f, 0x0d7f, 0x007c, 0xa006, - 0x0078, 0x484c, 0x0d7e, 0x127e, 0x2091, 0x8000, 0x60a4, 0xa06d, - 0x0040, 0x4860, 0x60a7, 0x0000, 0x1078, 0x13a4, 0xa085, 0x0001, - 0x127f, 0x0d7f, 0x007c, 0x60a8, 0xa00d, 0x00c0, 0x486a, 0xa085, - 0x0001, 0x007c, 0x0e7e, 0x2170, 0x7050, 0xa005, 0x00c0, 0x487d, - 0x20a9, 0x0010, 0xae88, 0x0018, 0x2104, 0xa606, 0x0040, 0x487d, - 0x8108, 0x00f0, 0x4874, 0xa085, 0x0001, 0x0e7f, 0x007c, 0x127e, - 0x2091, 0x8000, 0x1078, 0x4863, 0x00c0, 0x4899, 0x200b, 0xffff, - 0x0d7e, 0x60a8, 0x2068, 0x6854, 0xa08a, 0x0002, 0x0048, 0x4894, - 0x8001, 0x6856, 0x0078, 0x4898, 0x1078, 0x13a4, 0x60ab, 0x0000, - 0x0d7f, 0x127f, 0x007c, 0x609c, 0xd0a4, 0x007c, 0x0f7e, 0x71b0, - 0x81ff, 0x00c0, 0x48b9, 0x71cc, 0xd19c, 0x0040, 0x48b9, 0x2001, - 0x007e, 0xa080, 0xa835, 0x2004, 0xa07d, 0x0040, 0x48b9, 0x7804, - 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x48b9, 0x7800, 0xc0ed, - 0x7802, 0x2079, 0xa752, 0x7804, 0xd0a4, 0x0040, 0x48df, 0x157e, - 0x0c7e, 0x20a9, 0x007f, 0x2009, 0x0000, 0x017e, 0x1078, 0x45c4, - 0x00c0, 0x48d9, 0x6004, 0xa084, 0xff00, 0x8007, 0xa096, 0x0004, - 0x0040, 0x48d6, 0xa086, 0x0006, 0x00c0, 0x48d9, 0x6000, 0xc0ed, - 0x6002, 0x017f, 0x8108, 0x00f0, 0x48c5, 0x0c7f, 0x157f, 0x1078, - 0x4967, 0x0040, 0x48e8, 0x2001, 0xa9a1, 0x200c, 0x0078, 0x48f0, - 0x2079, 0xa752, 0x7804, 0xd0a4, 0x0040, 0x48f4, 0x2009, 0x07d0, - 0x2011, 0x48f6, 0x1078, 0x5add, 0x0f7f, 0x007c, 0x2011, 0x48f6, - 0x1078, 0x5a45, 0x1078, 0x4967, 0x0040, 0x491e, 0x2001, 0xa8b3, - 0x2004, 0xa080, 0x0000, 0x200c, 0xc1ec, 0x2102, 0x2001, 0xa753, - 0x2004, 0xd0a4, 0x0040, 0x4912, 0x2009, 0x07d0, 0x2011, 0x48f6, - 0x1078, 0x5add, 0x0e7e, 0x2071, 0xa700, 0x706f, 0x0000, 0x7073, - 0x0000, 0x1078, 0x2677, 0x0e7f, 0x0078, 0x4956, 0x157e, 0x0c7e, - 0x20a9, 0x007f, 0x2009, 0x0000, 0x017e, 0x1078, 0x45c4, 0x00c0, - 0x4950, 0x6000, 0xd0ec, 0x0040, 0x4950, 0x047e, 0x62a0, 0xa294, - 0x00ff, 0x8227, 0xa006, 0x2009, 0x0029, 0x1078, 0xa22d, 0x6000, - 0xc0e5, 0xc0ec, 0x6002, 0x6004, 0xa084, 0x00ff, 0xa085, 0x0700, - 0x6006, 0x2019, 0x0029, 0x1078, 0x5f01, 0x077e, 0x2039, 0x0000, - 0x1078, 0x5e0a, 0x2009, 0x0000, 0x1078, 0x9f9b, 0x077f, 0x047f, - 0x017f, 0x8108, 0x00f0, 0x4924, 0x0c7f, 0x157f, 0x007c, 0x0c7e, - 0x6018, 0x2060, 0x6000, 0xc0ec, 0x6002, 0x0c7f, 0x007c, 0x7818, - 0x2004, 0xd0ac, 0x007c, 0x7818, 0x2004, 0xd0bc, 0x007c, 0x0f7e, - 0x2001, 0xa8b3, 0x2004, 0xa07d, 0x0040, 0x4970, 0x7800, 0xd0ec, - 0x0f7f, 0x007c, 0x127e, 0x027e, 0x2091, 0x8000, 0x007e, 0x62a0, - 0xa290, 0xa835, 0x2204, 0xac06, 0x10c0, 0x1332, 0x007f, 0x6200, - 0xa005, 0x0040, 0x4986, 0xc2fd, 0x0078, 0x4987, 0xc2fc, 0x6202, - 0x027f, 0x127f, 0x007c, 0x2011, 0xa733, 0x2204, 0xd0cc, 0x0040, - 0x4998, 0x2001, 0xa99f, 0x200c, 0x2011, 0x4999, 0x1078, 0x5add, - 0x007c, 0x2011, 0x4999, 0x1078, 0x5a45, 0x2011, 0xa733, 0x2204, - 0xc0cc, 0x2012, 0x007c, 0x2071, 0xa814, 0x7003, 0x0001, 0x7007, - 0x0000, 0x7013, 0x0000, 0x7017, 0x0000, 0x701b, 0x0000, 0x701f, - 0x0000, 0x700b, 0x0000, 0x704b, 0x0001, 0x704f, 0x0000, 0x705b, - 0x0020, 0x705f, 0x0040, 0x707f, 0x0000, 0x2071, 0xa97d, 0x7003, - 0xa814, 0x7007, 0x0000, 0x700b, 0x0000, 0x700f, 0xa95d, 0x7013, - 0x0020, 0x7017, 0x0040, 0x7037, 0x0000, 0x007c, 0x017e, 0x0e7e, - 0x2071, 0xa935, 0xa00e, 0x7186, 0x718a, 0x7097, 0x0001, 0x2001, - 0xa753, 0x2004, 0xd0fc, 0x00c0, 0x49e8, 0x2001, 0xa753, 0x2004, - 0xa00e, 0xd09c, 0x0040, 0x49e5, 0x8108, 0x7102, 0x0078, 0x4a3b, - 0x2001, 0xa772, 0x200c, 0xa184, 0x000f, 0x2009, 0xa773, 0x210c, - 0x0079, 0x49f2, 0x49dd, 0x4a13, 0x4a1b, 0x4a26, 0x4a2c, 0x49dd, - 0x49dd, 0x49dd, 0x4a02, 0x49dd, 0x49dd, 0x49dd, 0x49dd, 0x49dd, - 0x49dd, 0x49dd, 0x7003, 0x0004, 0x137e, 0x147e, 0x157e, 0x2099, - 0xa776, 0x20a1, 0xa986, 0x20a9, 0x0004, 0x53a3, 0x157f, 0x147f, - 0x137f, 0x0078, 0x4a3b, 0x708f, 0x0005, 0x7007, 0x0122, 0x2001, - 0x0002, 0x0078, 0x4a21, 0x708f, 0x0002, 0x7007, 0x0121, 0x2001, - 0x0003, 0x7002, 0x7097, 0x0001, 0x0078, 0x4a38, 0x7007, 0x0122, - 0x2001, 0x0002, 0x0078, 0x4a30, 0x7007, 0x0121, 0x2001, 0x0003, - 0x7002, 0xa006, 0x7096, 0x708e, 0xa184, 0xff00, 0x8007, 0x709a, - 0xa184, 0x00ff, 0x7092, 0x0e7f, 0x017f, 0x007c, 0x0e7e, 0x2071, - 0xa814, 0x684c, 0xa005, 0x00c0, 0x4a4c, 0x7028, 0xc085, 0x702a, - 0xa085, 0x0001, 0x0078, 0x4a71, 0x6a60, 0x7236, 0x6b64, 0x733a, - 0x6868, 0x703e, 0x7076, 0x686c, 0x7042, 0x707a, 0x684c, 0x702e, - 0x6844, 0x7032, 0x2009, 0x000d, 0x200a, 0x700b, 0x0000, 0x8007, - 0x8006, 0x8006, 0xa08c, 0x003f, 0xa084, 0xffc0, 0xa210, 0x2100, - 0xa319, 0x726e, 0x7372, 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, - 0xa006, 0x0e7f, 0x007c, 0x0e7e, 0x027e, 0x6838, 0xd0fc, 0x00c0, - 0x4ac9, 0x6804, 0xa00d, 0x0040, 0x4a8f, 0x0d7e, 0x2071, 0xa700, - 0xa016, 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, - 0x00c0, 0x4a82, 0x702e, 0x70ac, 0xa200, 0x70ae, 0x0d7f, 0x2071, - 0xa814, 0x701c, 0xa005, 0x00c0, 0x4adb, 0x0068, 0x4ad9, 0x2071, - 0xa935, 0x7200, 0x82ff, 0x0040, 0x4ad9, 0x6934, 0xa186, 0x0103, - 0x00c0, 0x4aec, 0x6948, 0x6844, 0xa105, 0x00c0, 0x4acc, 0x2009, - 0x8020, 0x2200, 0x0079, 0x4aac, 0x4ad9, 0x4ab1, 0x4b09, 0x4b17, - 0x4ad9, 0x2071, 0x0000, 0x7018, 0xd084, 0x00c0, 0x4ad9, 0x7122, - 0x683c, 0x7026, 0x6840, 0x702a, 0x701b, 0x0001, 0x2091, 0x4080, - 0x2071, 0xa700, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70ac, 0x8000, - 0x70ae, 0x027f, 0x0e7f, 0x007c, 0x6844, 0xa086, 0x0100, 0x00c0, - 0x4ad9, 0x6868, 0xa005, 0x00c0, 0x4ad9, 0x2009, 0x8020, 0x0078, - 0x4aa9, 0x2071, 0xa814, 0x2d08, 0x206b, 0x0000, 0x7010, 0x8000, - 0x7012, 0x7018, 0xa06d, 0x711a, 0x0040, 0x4ae9, 0x6902, 0x0078, - 0x4aea, 0x711e, 0x0078, 0x4ac9, 0xa18c, 0x00ff, 0xa186, 0x0017, - 0x0040, 0x4afa, 0xa186, 0x001e, 0x0040, 0x4afa, 0xa18e, 0x001f, - 0x00c0, 0x4ad9, 0x684c, 0xd0cc, 0x0040, 0x4ad9, 0x6850, 0xa084, - 0x00ff, 0xa086, 0x0001, 0x00c0, 0x4ad9, 0x2009, 0x8021, 0x0078, - 0x4aa9, 0x7084, 0x8008, 0xa092, 0x001e, 0x00c8, 0x4ad9, 0x7186, - 0xae90, 0x0003, 0xa210, 0x683c, 0x2012, 0x0078, 0x4b27, 0x7084, - 0x8008, 0xa092, 0x000f, 0x00c8, 0x4ad9, 0x7186, 0xae90, 0x0003, - 0x8003, 0xa210, 0x683c, 0x2012, 0x8210, 0x6840, 0x2012, 0x7088, - 0xa10a, 0x0048, 0x4ac0, 0x718c, 0x7084, 0xa10a, 0x0048, 0x4ac0, - 0x2071, 0x0000, 0x7018, 0xd084, 0x00c0, 0x4ac0, 0x2071, 0xa935, - 0x7000, 0xa086, 0x0002, 0x00c0, 0x4b47, 0x1078, 0x4dc3, 0x2071, - 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0078, 0x4ac0, 0x1078, - 0x4dee, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0078, - 0x4ac0, 0x007e, 0x684c, 0x007e, 0x6837, 0x0103, 0x20a9, 0x001c, - 0xad80, 0x0011, 0x20a0, 0x2001, 0x0000, 0x40a4, 0x007f, 0xa084, - 0x00ff, 0x684e, 0x007f, 0x684a, 0x6952, 0x007c, 0x2071, 0xa814, - 0x7004, 0x0079, 0x4b6b, 0x4b75, 0x4b86, 0x4d94, 0x4d95, 0x4dbc, - 0x4dc2, 0x4b76, 0x4d82, 0x4d23, 0x4da5, 0x007c, 0x127e, 0x2091, - 0x8000, 0x0068, 0x4b85, 0x2009, 0x000d, 0x7030, 0x200a, 0x2091, - 0x4080, 0x7007, 0x0001, 0x700b, 0x0000, 0x127f, 0x2069, 0xa9c4, - 0x6844, 0xa005, 0x0050, 0x4bae, 0x00c0, 0x4bae, 0x127e, 0x2091, - 0x8000, 0x2069, 0x0000, 0x6934, 0x2001, 0xa820, 0x2004, 0xa10a, - 0x0040, 0x4ba9, 0x0068, 0x4bad, 0x2069, 0x0000, 0x6818, 0xd084, - 0x00c0, 0x4bad, 0x2009, 0x8040, 0x6922, 0x681b, 0x0001, 0x2091, - 0x4080, 0x2069, 0xa9c4, 0x6847, 0xffff, 0x127f, 0x2069, 0xa700, - 0x6848, 0x6964, 0xa102, 0x2069, 0xa935, 0x688a, 0x6984, 0x701c, - 0xa06d, 0x0040, 0x4bc0, 0x81ff, 0x0040, 0x4c08, 0x0078, 0x4bd6, - 0x81ff, 0x0040, 0x4cda, 0x2071, 0xa935, 0x7184, 0x7088, 0xa10a, - 0x00c8, 0x4bd6, 0x7190, 0x2071, 0xa9c4, 0x7040, 0xa005, 0x0040, - 0x4bd6, 0x00d0, 0x4cda, 0x7142, 0x0078, 0x4cda, 0x2071, 0xa935, - 0x718c, 0x127e, 0x2091, 0x8000, 0x7084, 0xa10a, 0x0048, 0x4cf7, - 0x0068, 0x4c8c, 0x2071, 0x0000, 0x7018, 0xd084, 0x00c0, 0x4c8c, - 0x2001, 0xffff, 0x2071, 0xa9c4, 0x7042, 0x2071, 0xa935, 0x7000, - 0xa086, 0x0002, 0x00c0, 0x4bfe, 0x1078, 0x4dc3, 0x2071, 0x0000, - 0x701b, 0x0001, 0x2091, 0x4080, 0x0078, 0x4c8c, 0x1078, 0x4dee, - 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0078, 0x4c8c, - 0x2071, 0xa935, 0x7000, 0xa005, 0x0040, 0x4cb9, 0x6934, 0xa186, - 0x0103, 0x00c0, 0x4c8f, 0x684c, 0xd0bc, 0x00c0, 0x4cb9, 0x6948, - 0x6844, 0xa105, 0x00c0, 0x4cac, 0x2009, 0x8020, 0x2071, 0xa935, - 0x7000, 0x0079, 0x4c23, 0x4cb9, 0x4c71, 0x4c49, 0x4c5b, 0x4c28, - 0x137e, 0x147e, 0x157e, 0x2099, 0xa776, 0x20a1, 0xa986, 0x20a9, - 0x0004, 0x53a3, 0x157f, 0x147f, 0x137f, 0x2071, 0xa97d, 0xad80, - 0x000f, 0x700e, 0x7013, 0x0002, 0x7007, 0x0002, 0x700b, 0x0000, - 0x2e10, 0x1078, 0x13db, 0x2071, 0xa814, 0x7007, 0x0009, 0x0078, - 0x4cda, 0x7084, 0x8008, 0xa092, 0x001e, 0x00c8, 0x4cda, 0xae90, - 0x0003, 0xa210, 0x683c, 0x2012, 0x7186, 0x2071, 0xa814, 0x1078, - 0x4e4c, 0x0078, 0x4cda, 0x7084, 0x8008, 0xa092, 0x000f, 0x00c8, - 0x4cda, 0xae90, 0x0003, 0x8003, 0xa210, 0x683c, 0x2012, 0x8210, - 0x6840, 0x2012, 0x7186, 0x2071, 0xa814, 0x1078, 0x4e4c, 0x0078, - 0x4cda, 0x127e, 0x2091, 0x8000, 0x0068, 0x4c8c, 0x2071, 0x0000, - 0x7018, 0xd084, 0x00c0, 0x4c8c, 0x7122, 0x683c, 0x7026, 0x6840, - 0x702a, 0x701b, 0x0001, 0x2091, 0x4080, 0x127f, 0x2071, 0xa814, - 0x1078, 0x4e4c, 0x0078, 0x4cda, 0x127f, 0x0078, 0x4cda, 0xa18c, - 0x00ff, 0xa186, 0x0017, 0x0040, 0x4c9d, 0xa186, 0x001e, 0x0040, - 0x4c9d, 0xa18e, 0x001f, 0x00c0, 0x4cb9, 0x684c, 0xd0cc, 0x0040, - 0x4cb9, 0x6850, 0xa084, 0x00ff, 0xa086, 0x0001, 0x00c0, 0x4cb9, - 0x2009, 0x8021, 0x0078, 0x4c1e, 0x6844, 0xa086, 0x0100, 0x00c0, - 0x4cb9, 0x6868, 0xa005, 0x00c0, 0x4cb9, 0x2009, 0x8020, 0x0078, - 0x4c1e, 0x2071, 0xa814, 0x1078, 0x4e60, 0x0040, 0x4cda, 0x2071, - 0xa814, 0x700f, 0x0001, 0x6934, 0xa184, 0x00ff, 0xa086, 0x0003, - 0x00c0, 0x4cd1, 0x810f, 0xa18c, 0x00ff, 0x8101, 0x0040, 0x4cd1, - 0x710e, 0x7007, 0x0003, 0x1078, 0x4e80, 0x7050, 0xa086, 0x0100, - 0x0040, 0x4d95, 0x127e, 0x2091, 0x8000, 0x2071, 0xa814, 0x7008, - 0xa086, 0x0001, 0x00c0, 0x4cf5, 0x0068, 0x4cf5, 0x2009, 0x000d, - 0x7030, 0x200a, 0x2091, 0x4080, 0x700b, 0x0000, 0x7004, 0xa086, - 0x0006, 0x00c0, 0x4cf5, 0x7007, 0x0001, 0x127f, 0x007c, 0x2071, - 0xa814, 0x1078, 0x4e60, 0x0040, 0x4d20, 0x2071, 0xa935, 0x7084, - 0x700a, 0x20a9, 0x0020, 0x2099, 0xa936, 0x20a1, 0xa95d, 0x53a3, - 0x7087, 0x0000, 0x2071, 0xa814, 0x2069, 0xa97d, 0x706c, 0x6826, - 0x7070, 0x682a, 0x7074, 0x682e, 0x7078, 0x6832, 0x2d10, 0x1078, - 0x13db, 0x7007, 0x0008, 0x2001, 0xffff, 0x2071, 0xa9c4, 0x7042, - 0x127f, 0x0078, 0x4cda, 0x2069, 0xa97d, 0x6808, 0xa08e, 0x0000, - 0x0040, 0x4d81, 0xa08e, 0x0200, 0x0040, 0x4d7f, 0xa08e, 0x0100, - 0x00c0, 0x4d81, 0x127e, 0x2091, 0x8000, 0x0068, 0x4d7c, 0x2069, - 0x0000, 0x6818, 0xd084, 0x00c0, 0x4d7c, 0x702c, 0x7130, 0x8108, - 0xa102, 0x0048, 0x4d4a, 0xa00e, 0x7034, 0x706e, 0x7038, 0x7072, - 0x0078, 0x4d54, 0x706c, 0xa080, 0x0040, 0x706e, 0x00c8, 0x4d54, - 0x7070, 0xa081, 0x0000, 0x7072, 0x7132, 0x6936, 0x700b, 0x0000, - 0x2001, 0xa95a, 0x2004, 0xa005, 0x00c0, 0x4d73, 0x6934, 0x2069, - 0xa935, 0x689c, 0x699e, 0x2069, 0xa9c4, 0xa102, 0x00c0, 0x4d6c, - 0x6844, 0xa005, 0x00d0, 0x4d7a, 0x2001, 0xa95b, 0x200c, 0x810d, - 0x6946, 0x0078, 0x4d7a, 0x2009, 0x8040, 0x6922, 0x681b, 0x0001, - 0x2091, 0x4080, 0x7007, 0x0001, 0x127f, 0x0078, 0x4d81, 0x7007, - 0x0005, 0x007c, 0x701c, 0xa06d, 0x0040, 0x4d93, 0x1078, 0x4e60, - 0x0040, 0x4d93, 0x7007, 0x0003, 0x1078, 0x4e80, 0x7050, 0xa086, - 0x0100, 0x0040, 0x4d95, 0x007c, 0x007c, 0x7050, 0xa09e, 0x0100, - 0x00c0, 0x4d9e, 0x7007, 0x0004, 0x0078, 0x4dbc, 0xa086, 0x0200, - 0x00c0, 0x4da4, 0x7007, 0x0005, 0x007c, 0x2001, 0xa97f, 0x2004, - 0xa08e, 0x0100, 0x00c0, 0x4db1, 0x7007, 0x0001, 0x1078, 0x4e4c, - 0x007c, 0xa08e, 0x0000, 0x0040, 0x4db0, 0xa08e, 0x0200, 0x00c0, - 0x4db0, 0x7007, 0x0005, 0x007c, 0x1078, 0x4e16, 0x7006, 0x1078, - 0x4e4c, 0x007c, 0x007c, 0x0e7e, 0x157e, 0x2071, 0xa935, 0x7184, - 0x81ff, 0x0040, 0x4deb, 0xa006, 0x7086, 0xae80, 0x0003, 0x2071, - 0x0000, 0x21a8, 0x2014, 0x7226, 0x8000, 0x0070, 0x4de8, 0x2014, - 0x722a, 0x8000, 0x0070, 0x4de8, 0x2014, 0x722e, 0x8000, 0x0070, - 0x4de8, 0x2014, 0x723a, 0x8000, 0x0070, 0x4de8, 0x2014, 0x723e, - 0xa180, 0x8030, 0x7022, 0x157f, 0x0e7f, 0x007c, 0x0e7e, 0x157e, - 0x2071, 0xa935, 0x7184, 0x81ff, 0x0040, 0x4e13, 0xa006, 0x7086, - 0xae80, 0x0003, 0x2071, 0x0000, 0x21a8, 0x2014, 0x7226, 0x8000, - 0x2014, 0x722a, 0x8000, 0x0070, 0x4e0c, 0x2014, 0x723a, 0x8000, - 0x2014, 0x723e, 0x0078, 0x4e10, 0x2001, 0x8020, 0x0078, 0x4e12, - 0x2001, 0x8042, 0x7022, 0x157f, 0x0e7f, 0x007c, 0x702c, 0x7130, - 0x8108, 0xa102, 0x0048, 0x4e23, 0xa00e, 0x7034, 0x706e, 0x7038, - 0x7072, 0x0078, 0x4e2d, 0x706c, 0xa080, 0x0040, 0x706e, 0x00c8, - 0x4e2d, 0x7070, 0xa081, 0x0000, 0x7072, 0x7132, 0x700c, 0x8001, - 0x700e, 0x00c0, 0x4e43, 0x127e, 0x2091, 0x8000, 0x0068, 0x4e46, - 0x2001, 0x000d, 0x2102, 0x2091, 0x4080, 0x2001, 0x0001, 0x700b, - 0x0000, 0x127f, 0x007c, 0x2001, 0x0007, 0x007c, 0x2001, 0x0006, - 0x700b, 0x0001, 0x127f, 0x007c, 0x701c, 0xa06d, 0x0040, 0x4e5f, - 0x127e, 0x2091, 0x8000, 0x7010, 0x8001, 0x7012, 0x2d04, 0x701e, - 0xa005, 0x00c0, 0x4e5c, 0x701a, 0x127f, 0x1078, 0x13a4, 0x007c, - 0x2019, 0x000d, 0x2304, 0x230c, 0xa10e, 0x0040, 0x4e6f, 0x2304, - 0x230c, 0xa10e, 0x0040, 0x4e6f, 0xa006, 0x0078, 0x4e7f, 0x732c, - 0x8319, 0x7130, 0xa102, 0x00c0, 0x4e79, 0x2300, 0xa005, 0x0078, - 0x4e7f, 0x0048, 0x4e7e, 0xa302, 0x0078, 0x4e7f, 0x8002, 0x007c, - 0x2d00, 0x7026, 0xa080, 0x000d, 0x7056, 0x7053, 0x0000, 0x127e, - 0x2091, 0x8000, 0x2009, 0xa9d6, 0x2104, 0xc08d, 0x200a, 0x127f, - 0x1078, 0x13f9, 0x007c, 0x2071, 0xa7e2, 0x7003, 0x0000, 0x7007, - 0x0000, 0x700f, 0x0000, 0x702b, 0x0001, 0x704f, 0x0000, 0x7053, - 0x0001, 0x705f, 0x0020, 0x7063, 0x0040, 0x7083, 0x0000, 0x708b, - 0x0000, 0x708f, 0x0001, 0x70bf, 0x0000, 0x007c, 0x0e7e, 0x2071, - 0xa7e2, 0x6848, 0xa005, 0x00c0, 0x4ebc, 0x7028, 0xc085, 0x702a, - 0xa085, 0x0001, 0x0078, 0x4ee1, 0x6a50, 0x7236, 0x6b54, 0x733a, - 0x6858, 0x703e, 0x707a, 0x685c, 0x7042, 0x707e, 0x6848, 0x702e, - 0x6840, 0x7032, 0x2009, 0x000c, 0x200a, 0x8007, 0x8006, 0x8006, - 0xa08c, 0x003f, 0xa084, 0xffc0, 0xa210, 0x2100, 0xa319, 0x7272, - 0x7376, 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0x700f, 0x0000, - 0xa006, 0x0e7f, 0x007c, 0x2b78, 0x2071, 0xa7e2, 0x7004, 0x1079, - 0x4f41, 0x700c, 0x0079, 0x4eec, 0x4ef1, 0x4ee6, 0x4ee6, 0x4ee6, - 0x4ee6, 0x007c, 0x700c, 0x0079, 0x4ef5, 0x4efa, 0x4f3f, 0x4f3f, - 0x4f40, 0x4f40, 0x7830, 0x7930, 0xa106, 0x0040, 0x4f04, 0x7830, - 0x7930, 0xa106, 0x00c0, 0x4f2a, 0x7030, 0xa10a, 0x0040, 0x4f2a, - 0x00c8, 0x4f0c, 0x712c, 0xa10a, 0xa18a, 0x0002, 0x00c8, 0x4f2b, - 0x1078, 0x1370, 0x0040, 0x4f2a, 0x2d00, 0x705a, 0x7063, 0x0040, - 0x2001, 0x0003, 0x7057, 0x0000, 0x127e, 0x007e, 0x2091, 0x8000, - 0x2009, 0xa9d6, 0x2104, 0xc085, 0x200a, 0x007f, 0x700e, 0x127f, - 0x1078, 0x13f9, 0x007c, 0x1078, 0x1370, 0x0040, 0x4f2a, 0x2d00, - 0x705a, 0x1078, 0x1370, 0x00c0, 0x4f37, 0x0078, 0x4f16, 0x2d00, - 0x7086, 0x7063, 0x0080, 0x2001, 0x0004, 0x0078, 0x4f1a, 0x007c, - 0x007c, 0x4f52, 0x4f53, 0x4f8a, 0x4f8b, 0x4f3f, 0x4fc1, 0x4fc6, - 0x4ffd, 0x4ffe, 0x5019, 0x501a, 0x501b, 0x501c, 0x501d, 0x501e, - 0x509e, 0x50c8, 0x007c, 0x700c, 0x0079, 0x4f56, 0x4f5b, 0x4f5e, - 0x4f6e, 0x4f89, 0x4f89, 0x1078, 0x4ef2, 0x007c, 0x127e, 0x8001, - 0x700e, 0x7058, 0x007e, 0x1078, 0x5464, 0x0040, 0x4f6b, 0x2091, - 0x8000, 0x1078, 0x4ef2, 0x0d7f, 0x0078, 0x4f77, 0x127e, 0x8001, - 0x700e, 0x1078, 0x5464, 0x7058, 0x2068, 0x7084, 0x705a, 0x6803, - 0x0000, 0x6807, 0x0000, 0x6834, 0xa084, 0x00ff, 0xa08a, 0x0020, - 0x00c8, 0x4f86, 0x1079, 0x4fa1, 0x127f, 0x007c, 0x127f, 0x1078, - 0x501f, 0x007c, 0x007c, 0x007c, 0x0e7e, 0x2071, 0xa7e2, 0x700c, - 0x0079, 0x4f92, 0x4f97, 0x4f97, 0x4f97, 0x4f99, 0x4f9d, 0x0e7f, - 0x007c, 0x700f, 0x0001, 0x0078, 0x4f9f, 0x700f, 0x0002, 0x0e7f, - 0x007c, 0x501f, 0x501f, 0x503b, 0x501f, 0x5171, 0x501f, 0x501f, - 0x501f, 0x501f, 0x501f, 0x503b, 0x51bb, 0x5208, 0x5261, 0x5277, - 0x501f, 0x501f, 0x5057, 0x503b, 0x501f, 0x501f, 0x5078, 0x5338, - 0x5356, 0x501f, 0x5057, 0x501f, 0x501f, 0x501f, 0x501f, 0x506d, - 0x5356, 0x7020, 0x2068, 0x1078, 0x13a4, 0x007c, 0x700c, 0x0079, - 0x4fc9, 0x4fce, 0x4fd1, 0x4fe1, 0x4ffc, 0x4ffc, 0x1078, 0x4ef2, - 0x007c, 0x127e, 0x8001, 0x700e, 0x7058, 0x007e, 0x1078, 0x5464, - 0x0040, 0x4fde, 0x2091, 0x8000, 0x1078, 0x4ef2, 0x0d7f, 0x0078, - 0x4fea, 0x127e, 0x8001, 0x700e, 0x1078, 0x5464, 0x7058, 0x2068, - 0x7084, 0x705a, 0x6803, 0x0000, 0x6807, 0x0000, 0x6834, 0xa084, - 0x00ff, 0xa08a, 0x001a, 0x00c8, 0x4ff9, 0x1079, 0x4fff, 0x127f, - 0x007c, 0x127f, 0x1078, 0x501f, 0x007c, 0x007c, 0x007c, 0x501f, - 0x503b, 0x515b, 0x501f, 0x503b, 0x501f, 0x503b, 0x503b, 0x501f, - 0x503b, 0x515b, 0x503b, 0x503b, 0x503b, 0x503b, 0x503b, 0x501f, - 0x503b, 0x515b, 0x501f, 0x501f, 0x503b, 0x501f, 0x501f, 0x501f, - 0x503b, 0x007c, 0x007c, 0x007c, 0x007c, 0x007c, 0x007c, 0x7007, - 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0d5, 0x683a, 0x127e, 0x2091, - 0x8000, 0x1078, 0x4a73, 0x127f, 0x007c, 0x7007, 0x0001, 0x6838, - 0xa084, 0x00ff, 0xc0e5, 0x683a, 0x127e, 0x2091, 0x8000, 0x1078, - 0x4a73, 0x127f, 0x007c, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, - 0xc0ed, 0x683a, 0x127e, 0x2091, 0x8000, 0x1078, 0x4a73, 0x127f, - 0x007c, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0dd, 0x683a, - 0x127e, 0x2091, 0x8000, 0x1078, 0x4a73, 0x127f, 0x007c, 0x6834, - 0x8007, 0xa084, 0x00ff, 0x0040, 0x502d, 0x8001, 0x00c0, 0x5064, - 0x7007, 0x0001, 0x0078, 0x513a, 0x7007, 0x0006, 0x7012, 0x2d00, - 0x7016, 0x701a, 0x704b, 0x513a, 0x007c, 0x684c, 0xa084, 0x00c0, - 0xa086, 0x00c0, 0x00c0, 0x5078, 0x7007, 0x0001, 0x0078, 0x5373, - 0x2d00, 0x7016, 0x701a, 0x20a9, 0x0004, 0xa080, 0x0024, 0x2098, - 0x20a1, 0xa80d, 0x53a3, 0x6858, 0x7012, 0xa082, 0x0401, 0x00c8, - 0x5049, 0x6884, 0xa08a, 0x0002, 0x00c8, 0x5049, 0x82ff, 0x00c0, - 0x509a, 0x6888, 0x698c, 0xa105, 0x0040, 0x509a, 0x2001, 0x510a, - 0x0078, 0x509d, 0xa280, 0x5100, 0x2004, 0x70c6, 0x7010, 0xa015, - 0x0040, 0x50e8, 0x1078, 0x1370, 0x00c0, 0x50a9, 0x7007, 0x000f, - 0x007c, 0x2d00, 0x7022, 0x70c4, 0x2060, 0x6000, 0x6836, 0x6004, - 0xad00, 0x7096, 0x6008, 0xa20a, 0x00c8, 0x50b8, 0xa00e, 0x2200, - 0x7112, 0x620c, 0x8003, 0x800b, 0xa296, 0x0004, 0x0040, 0x50c1, - 0xa108, 0x719a, 0x810b, 0x719e, 0xae90, 0x0022, 0x1078, 0x13db, - 0x7090, 0xa08e, 0x0100, 0x0040, 0x50dc, 0xa086, 0x0200, 0x0040, - 0x50d4, 0x7007, 0x0010, 0x007c, 0x7020, 0x2068, 0x1078, 0x13a4, - 0x7014, 0x2068, 0x0078, 0x5049, 0x7020, 0x2068, 0x7018, 0x6802, - 0x6807, 0x0000, 0x2d08, 0x2068, 0x6906, 0x711a, 0x0078, 0x509e, - 0x7014, 0x2068, 0x7007, 0x0001, 0x6884, 0xa005, 0x00c0, 0x50f7, - 0x6888, 0x698c, 0xa105, 0x0040, 0x50f7, 0x1078, 0x510e, 0x6834, - 0xa084, 0x00ff, 0xa086, 0x001e, 0x0040, 0x5373, 0x0078, 0x513a, - 0x5102, 0x5106, 0x0002, 0x0011, 0x0007, 0x0004, 0x000a, 0x000f, - 0x0005, 0x0006, 0x000a, 0x0011, 0x0005, 0x0004, 0x0f7e, 0x0e7e, - 0x0c7e, 0x077e, 0x067e, 0x6f88, 0x6e8c, 0x6804, 0x2060, 0xacf0, - 0x0021, 0xacf8, 0x0027, 0x2009, 0x0005, 0x700c, 0x7816, 0x7008, - 0x7812, 0x7004, 0x7806, 0x7000, 0x7802, 0x7e0e, 0x7f0a, 0x8109, - 0x0040, 0x5130, 0xaef2, 0x0004, 0xaffa, 0x0006, 0x0078, 0x511d, - 0x6004, 0xa065, 0x00c0, 0x5117, 0x067f, 0x077f, 0x0c7f, 0x0e7f, - 0x0f7f, 0x007c, 0x2009, 0xa72f, 0x210c, 0x81ff, 0x00c0, 0x5155, - 0x6838, 0xa084, 0x00ff, 0x683a, 0x1078, 0x4353, 0x00c0, 0x5149, - 0x007c, 0x1078, 0x4b51, 0x127e, 0x2091, 0x8000, 0x1078, 0x8f8d, - 0x1078, 0x4a73, 0x127f, 0x0078, 0x5148, 0x2001, 0x0028, 0x2009, - 0x0000, 0x0078, 0x5149, 0x7018, 0x6802, 0x2d08, 0x2068, 0x6906, - 0x711a, 0x7010, 0x8001, 0x7012, 0x0040, 0x516a, 0x7007, 0x0006, - 0x0078, 0x5170, 0x7014, 0x2068, 0x7007, 0x0001, 0x7048, 0x107a, - 0x007c, 0x7007, 0x0001, 0x6944, 0x810f, 0xa18c, 0x00ff, 0x6848, - 0xa084, 0x00ff, 0x20a9, 0x0001, 0xa096, 0x0001, 0x0040, 0x519a, - 0x2009, 0x0000, 0x20a9, 0x00ff, 0xa096, 0x0002, 0x0040, 0x519a, - 0xa005, 0x00c0, 0x51ad, 0x6944, 0x810f, 0xa18c, 0x00ff, 0x1078, - 0x45c4, 0x00c0, 0x51ad, 0x067e, 0x6e50, 0x1078, 0x46b3, 0x067f, - 0x0078, 0x51ad, 0x047e, 0x2011, 0xa70c, 0x2224, 0xc484, 0xc48c, - 0x2412, 0x047f, 0x0c7e, 0x1078, 0x45c4, 0x00c0, 0x51a9, 0x1078, - 0x4852, 0x8108, 0x00f0, 0x51a3, 0x0c7f, 0x684c, 0xd084, 0x00c0, - 0x51b4, 0x1078, 0x13a4, 0x007c, 0x127e, 0x2091, 0x8000, 0x1078, - 0x4a73, 0x127f, 0x007c, 0x127e, 0x2091, 0x8000, 0x7007, 0x0001, - 0x2001, 0xa753, 0x2004, 0xd0a4, 0x0040, 0x51ff, 0x2061, 0xaa33, - 0x6100, 0xd184, 0x0040, 0x51df, 0x6858, 0xa084, 0x00ff, 0x00c0, - 0x5202, 0x6000, 0xd084, 0x0040, 0x51ff, 0x6004, 0xa005, 0x00c0, - 0x5205, 0x6003, 0x0000, 0x600b, 0x0000, 0x0078, 0x51fc, 0x2011, - 0x0001, 0x6860, 0xa005, 0x00c0, 0x51e7, 0x2001, 0x001e, 0x8000, - 0x6016, 0x6858, 0xa084, 0x00ff, 0x0040, 0x51ff, 0x6006, 0x6858, - 0x8007, 0xa084, 0x00ff, 0x0040, 0x51ff, 0x600a, 0x6858, 0x8000, - 0x00c0, 0x51fb, 0xc28d, 0x6202, 0x127f, 0x0078, 0x5453, 0x127f, - 0x0078, 0x544b, 0x127f, 0x0078, 0x5443, 0x127f, 0x0078, 0x5447, - 0x127e, 0x2091, 0x8000, 0x7007, 0x0001, 0x2001, 0xa753, 0x2004, - 0xd0a4, 0x0040, 0x525e, 0x2061, 0xaa33, 0x6000, 0xd084, 0x0040, - 0x525e, 0x6204, 0x6308, 0xd08c, 0x00c0, 0x5250, 0x6c48, 0xa484, - 0x0003, 0x0040, 0x5236, 0x6958, 0xa18c, 0x00ff, 0x8001, 0x00c0, - 0x522f, 0x2100, 0xa210, 0x0048, 0x525b, 0x0078, 0x5236, 0x8001, - 0x00c0, 0x525b, 0x2100, 0xa212, 0x0048, 0x525b, 0xa484, 0x000c, - 0x0040, 0x5250, 0x6958, 0x810f, 0xa18c, 0x00ff, 0xa082, 0x0004, - 0x00c0, 0x5248, 0x2100, 0xa318, 0x0048, 0x525b, 0x0078, 0x5250, - 0xa082, 0x0004, 0x00c0, 0x525b, 0x2100, 0xa31a, 0x0048, 0x525b, - 0x6860, 0xa005, 0x0040, 0x5256, 0x8000, 0x6016, 0x6206, 0x630a, - 0x127f, 0x0078, 0x5453, 0x127f, 0x0078, 0x544f, 0x127f, 0x0078, - 0x544b, 0x127e, 0x2091, 0x8000, 0x7007, 0x0001, 0x2061, 0xaa33, - 0x6300, 0xd38c, 0x00c0, 0x5271, 0x6308, 0x8318, 0x0048, 0x5274, - 0x630a, 0x127f, 0x0078, 0x5461, 0x127f, 0x0078, 0x544f, 0x127e, - 0x0c7e, 0x2091, 0x8000, 0x7007, 0x0001, 0x684c, 0xd0ac, 0x0040, - 0x528b, 0x0c7e, 0x2061, 0xaa33, 0x6000, 0xa084, 0xfcff, 0x6002, - 0x0c7f, 0x0078, 0x52ba, 0x6858, 0xa005, 0x0040, 0x52d1, 0x685c, - 0xa065, 0x0040, 0x52cd, 0x2001, 0xa72f, 0x2004, 0xa005, 0x0040, - 0x529d, 0x1078, 0x8ed6, 0x0078, 0x52ab, 0x6013, 0x0400, 0x6037, - 0x0000, 0x694c, 0xd1a4, 0x0040, 0x52a7, 0x6950, 0x6136, 0x2009, - 0x0041, 0x1078, 0x775c, 0x6958, 0xa18c, 0xff00, 0xa186, 0x2000, - 0x00c0, 0x52ba, 0x027e, 0x2009, 0x0000, 0x2011, 0xfdff, 0x1078, - 0x5bf1, 0x027f, 0x684c, 0xd0c4, 0x0040, 0x52c9, 0x2061, 0xaa33, - 0x6000, 0xd08c, 0x00c0, 0x52c9, 0x6008, 0x8000, 0x0048, 0x52cd, - 0x600a, 0x0c7f, 0x127f, 0x0078, 0x5453, 0x0c7f, 0x127f, 0x0078, - 0x544b, 0x6954, 0xa186, 0x0045, 0x0040, 0x5306, 0xa186, 0x002a, - 0x00c0, 0x52e1, 0x2001, 0xa70c, 0x200c, 0xc194, 0x2102, 0x0078, - 0x52ba, 0xa186, 0x0020, 0x0040, 0x52fa, 0xa186, 0x0029, 0x0040, - 0x52ed, 0xa186, 0x002d, 0x00c0, 0x52cd, 0x6944, 0xa18c, 0xff00, - 0x810f, 0x1078, 0x45c4, 0x00c0, 0x52ba, 0x6000, 0xc0e4, 0x6002, - 0x0078, 0x52ba, 0x685c, 0xa065, 0x0040, 0x52cd, 0x6007, 0x0024, - 0x2001, 0xa9a3, 0x2004, 0x6016, 0x0078, 0x52ba, 0x685c, 0xa065, - 0x0040, 0x52cd, 0x0e7e, 0x6860, 0xa075, 0x2001, 0xa72f, 0x2004, - 0xa005, 0x0040, 0x531e, 0x1078, 0x8ed6, 0x8eff, 0x0040, 0x531b, - 0x2e60, 0x1078, 0x8ed6, 0x0e7f, 0x0078, 0x52ba, 0x6024, 0xc0dc, - 0xc0d5, 0x6026, 0x2e60, 0x6007, 0x003a, 0x6870, 0xa005, 0x0040, - 0x532f, 0x6007, 0x003b, 0x6874, 0x602a, 0x6878, 0x6012, 0x6003, - 0x0001, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0e7f, 0x0078, 0x52ba, - 0x2061, 0xaa33, 0x6000, 0xd084, 0x0040, 0x5352, 0xd08c, 0x00c0, - 0x5461, 0x2091, 0x8000, 0x6204, 0x8210, 0x0048, 0x534c, 0x6206, - 0x2091, 0x8001, 0x0078, 0x5461, 0x2091, 0x8001, 0x6853, 0x0016, - 0x0078, 0x545a, 0x6853, 0x0007, 0x0078, 0x545a, 0x6834, 0x8007, - 0xa084, 0x00ff, 0x00c0, 0x5360, 0x1078, 0x502d, 0x0078, 0x5372, - 0x2030, 0x8001, 0x00c0, 0x536a, 0x7007, 0x0001, 0x1078, 0x5373, - 0x0078, 0x5372, 0x7007, 0x0006, 0x7012, 0x2d00, 0x7016, 0x701a, - 0x704b, 0x5373, 0x007c, 0x0e7e, 0x127e, 0x2091, 0x8000, 0xa03e, - 0x2009, 0xa72f, 0x210c, 0x81ff, 0x00c0, 0x53ff, 0x2009, 0xa70c, - 0x210c, 0xd194, 0x00c0, 0x5431, 0x6848, 0x2070, 0xae82, 0xae00, - 0x0048, 0x53ef, 0x2001, 0xa716, 0x2004, 0xae02, 0x00c8, 0x53ef, - 0x2061, 0xaa33, 0x6100, 0xa184, 0x0301, 0xa086, 0x0001, 0x00c0, - 0x53d2, 0x711c, 0xa186, 0x0006, 0x00c0, 0x53da, 0x7018, 0xa005, - 0x0040, 0x53ff, 0x2004, 0xd0e4, 0x00c0, 0x542b, 0x7024, 0xd0dc, - 0x00c0, 0x5435, 0x6853, 0x0000, 0x6803, 0x0000, 0x2d08, 0x7010, - 0xa005, 0x00c0, 0x53be, 0x7112, 0x684c, 0xd0f4, 0x00c0, 0x5439, - 0x2e60, 0x1078, 0x5b27, 0x127f, 0x0e7f, 0x007c, 0x2068, 0x6800, - 0xa005, 0x00c0, 0x53be, 0x6902, 0x2168, 0x684c, 0xd0f4, 0x00c0, - 0x5439, 0x127f, 0x0e7f, 0x007c, 0x127f, 0x0e7f, 0x6853, 0x0006, - 0x0078, 0x545a, 0xd184, 0x0040, 0x53cc, 0xd1c4, 0x00c0, 0x53f3, - 0x0078, 0x53f7, 0x6944, 0xa18c, 0xff00, 0x810f, 0x1078, 0x45c4, - 0x00c0, 0x542b, 0x6000, 0xd0e4, 0x00c0, 0x542b, 0x711c, 0xa186, - 0x0007, 0x00c0, 0x53ef, 0x6853, 0x0002, 0x0078, 0x542d, 0x6853, - 0x0008, 0x0078, 0x542d, 0x6853, 0x000e, 0x0078, 0x542d, 0x6853, - 0x0017, 0x0078, 0x542d, 0x6853, 0x0035, 0x0078, 0x542d, 0x2001, - 0xa772, 0x2004, 0xd0fc, 0x0040, 0x5427, 0x6848, 0x2070, 0xae82, - 0xae00, 0x0048, 0x5427, 0x6058, 0xae02, 0x00c8, 0x5427, 0x711c, - 0xa186, 0x0006, 0x00c0, 0x5427, 0x7018, 0xa005, 0x0040, 0x5427, - 0x2004, 0xd0bc, 0x0040, 0x5427, 0x2039, 0x0001, 0x7000, 0xa086, - 0x0007, 0x00c0, 0x537e, 0x7003, 0x0002, 0x0078, 0x537e, 0x6853, - 0x0028, 0x0078, 0x542d, 0x6853, 0x0029, 0x127f, 0x0e7f, 0x0078, - 0x545a, 0x6853, 0x002a, 0x0078, 0x542d, 0x6853, 0x0045, 0x0078, - 0x542d, 0x2e60, 0x2019, 0x0002, 0x6017, 0x0014, 0x1078, 0x9dd7, - 0x127f, 0x0e7f, 0x007c, 0x2009, 0x003e, 0x0078, 0x5455, 0x2009, - 0x0004, 0x0078, 0x5455, 0x2009, 0x0006, 0x0078, 0x5455, 0x2009, - 0x0016, 0x0078, 0x5455, 0x2009, 0x0001, 0x6854, 0xa084, 0xff00, - 0xa105, 0x6856, 0x2091, 0x8000, 0x1078, 0x4a73, 0x2091, 0x8001, - 0x007c, 0x1078, 0x13a4, 0x007c, 0x702c, 0x7130, 0x8108, 0xa102, - 0x0048, 0x5471, 0xa00e, 0x7034, 0x7072, 0x7038, 0x7076, 0x0078, - 0x547d, 0x7070, 0xa080, 0x0040, 0x7072, 0x00c8, 0x547d, 0x7074, - 0xa081, 0x0000, 0x7076, 0xa085, 0x0001, 0x7932, 0x7132, 0x007c, - 0x0d7e, 0x1078, 0x5b1e, 0x0d7f, 0x007c, 0x0d7e, 0x2011, 0x0004, - 0x2204, 0xa085, 0x8002, 0x2012, 0x0d7f, 0x007c, 0x20e1, 0x0002, - 0x3d08, 0x20e1, 0x2000, 0x3d00, 0xa084, 0x7000, 0x0040, 0x549c, - 0xa086, 0x1000, 0x00c0, 0x54d3, 0x20e1, 0x0000, 0x3d00, 0xa094, - 0xff00, 0x8217, 0xa084, 0xf000, 0xa086, 0x3000, 0x00c0, 0x54b7, - 0xa184, 0xff00, 0x8007, 0xa086, 0x0008, 0x00c0, 0x54d3, 0x1078, - 0x29bb, 0x00c0, 0x54d3, 0x1078, 0x56b2, 0x0078, 0x54ce, 0x20e1, - 0x0004, 0x3d60, 0xd1bc, 0x00c0, 0x54be, 0x3e60, 0xac84, 0x000f, - 0x00c0, 0x54d3, 0xac82, 0xae00, 0x0048, 0x54d3, 0x6858, 0xac02, - 0x00c8, 0x54d3, 0x2009, 0x0047, 0x1078, 0x775c, 0x7a1c, 0xd284, - 0x00c0, 0x548e, 0x007c, 0xa016, 0x1078, 0x15fa, 0x0078, 0x54ce, - 0x0078, 0x54d3, 0x781c, 0xd08c, 0x0040, 0x5502, 0x157e, 0x137e, - 0x147e, 0x20e1, 0x3000, 0x3d20, 0x3e28, 0xa584, 0x0076, 0x00c0, - 0x5518, 0xa484, 0x7000, 0xa086, 0x1000, 0x00c0, 0x5507, 0x1078, - 0x554e, 0x0040, 0x5518, 0x20e1, 0x3000, 0x7828, 0x7828, 0x1078, - 0x556c, 0x147f, 0x137f, 0x157f, 0x2009, 0xa9b9, 0x2104, 0xa005, - 0x00c0, 0x5503, 0x007c, 0x1078, 0x62d1, 0x0078, 0x5502, 0xa484, - 0x7000, 0x00c0, 0x5518, 0x1078, 0x554e, 0x0040, 0x552c, 0x7000, - 0xa084, 0xff00, 0xa086, 0x8100, 0x0040, 0x54f3, 0x0078, 0x552c, - 0x1078, 0xa55f, 0xd5a4, 0x0040, 0x5528, 0x047e, 0x1078, 0x1b22, - 0x047f, 0x20e1, 0x9010, 0x2001, 0x0138, 0x2202, 0x0078, 0x5530, - 0x1078, 0x554e, 0x6883, 0x0000, 0x20e1, 0x3000, 0x7828, 0x7828, - 0x1078, 0x5537, 0x147f, 0x137f, 0x157f, 0x0078, 0x5502, 0x2001, - 0xa70e, 0x2004, 0xd08c, 0x0040, 0x554d, 0x2001, 0xa700, 0x2004, - 0xa086, 0x0003, 0x00c0, 0x554d, 0x027e, 0x037e, 0x2011, 0x8048, - 0x2518, 0x1078, 0x361b, 0x037f, 0x027f, 0x007c, 0xa484, 0x01ff, - 0x6882, 0xa005, 0x0040, 0x5560, 0xa080, 0x001f, 0xa084, 0x03f8, - 0x80ac, 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5, 0x007c, - 0x20a9, 0x000c, 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5, - 0xa085, 0x0001, 0x0078, 0x555f, 0x7000, 0xa084, 0xff00, 0xa08c, - 0xf000, 0x8007, 0xa196, 0x0000, 0x00c0, 0x5579, 0x0078, 0x57ba, - 0x007c, 0xa196, 0x2000, 0x00c0, 0x558a, 0x6900, 0xa18e, 0x0001, - 0x00c0, 0x5586, 0x1078, 0x3aec, 0x0078, 0x5578, 0x1078, 0x5592, - 0x0078, 0x5578, 0xa196, 0x8000, 0x00c0, 0x5578, 0x1078, 0x5871, - 0x0078, 0x5578, 0x0c7e, 0x7110, 0xa18c, 0xff00, 0x810f, 0xa196, - 0x0001, 0x0040, 0x559f, 0xa196, 0x0023, 0x00c0, 0x56aa, 0xa08e, - 0x0023, 0x00c0, 0x55d4, 0x1078, 0x591d, 0x0040, 0x56aa, 0x7124, - 0x610a, 0x7030, 0xa08e, 0x0200, 0x00c0, 0x55b8, 0x7034, 0xa005, - 0x00c0, 0x56aa, 0x2009, 0x0015, 0x1078, 0x775c, 0x0078, 0x56aa, - 0xa08e, 0x0214, 0x0040, 0x55c0, 0xa08e, 0x0210, 0x00c0, 0x55c6, - 0x2009, 0x0015, 0x1078, 0x775c, 0x0078, 0x56aa, 0xa08e, 0x0100, - 0x00c0, 0x56aa, 0x7034, 0xa005, 0x00c0, 0x56aa, 0x2009, 0x0016, - 0x1078, 0x775c, 0x0078, 0x56aa, 0xa08e, 0x0022, 0x00c0, 0x56aa, - 0x7030, 0xa08e, 0x0300, 0x00c0, 0x55e5, 0x7034, 0xa005, 0x00c0, - 0x56aa, 0x2009, 0x0017, 0x0078, 0x5676, 0xa08e, 0x0500, 0x00c0, - 0x55f1, 0x7034, 0xa005, 0x00c0, 0x56aa, 0x2009, 0x0018, 0x0078, - 0x5676, 0xa08e, 0x2010, 0x00c0, 0x55f9, 0x2009, 0x0019, 0x0078, - 0x5676, 0xa08e, 0x2110, 0x00c0, 0x5601, 0x2009, 0x001a, 0x0078, - 0x5676, 0xa08e, 0x5200, 0x00c0, 0x560d, 0x7034, 0xa005, 0x00c0, - 0x56aa, 0x2009, 0x001b, 0x0078, 0x5676, 0xa08e, 0x5000, 0x00c0, - 0x5619, 0x7034, 0xa005, 0x00c0, 0x56aa, 0x2009, 0x001c, 0x0078, - 0x5676, 0xa08e, 0x1300, 0x00c0, 0x5621, 0x2009, 0x0034, 0x0078, - 0x5676, 0xa08e, 0x1200, 0x00c0, 0x562d, 0x7034, 0xa005, 0x00c0, - 0x56aa, 0x2009, 0x0024, 0x0078, 0x5676, 0xa08c, 0xff00, 0xa18e, - 0x2400, 0x00c0, 0x5637, 0x2009, 0x002d, 0x0078, 0x5676, 0xa08c, - 0xff00, 0xa18e, 0x5300, 0x00c0, 0x5641, 0x2009, 0x002a, 0x0078, - 0x5676, 0xa08e, 0x0f00, 0x00c0, 0x5649, 0x2009, 0x0020, 0x0078, - 0x5676, 0xa08e, 0x5300, 0x00c0, 0x564f, 0x0078, 0x566c, 0xa08e, - 0x6104, 0x00c0, 0x566c, 0x2011, 0xac8d, 0x8208, 0x2204, 0xa082, - 0x0004, 0x20a8, 0x95ac, 0x95ac, 0x2011, 0x8015, 0x211c, 0x8108, - 0x047e, 0x2124, 0x1078, 0x361b, 0x047f, 0x8108, 0x00f0, 0x565c, - 0x2009, 0x0023, 0x0078, 0x5676, 0xa08e, 0x6000, 0x00c0, 0x5674, - 0x2009, 0x003f, 0x0078, 0x5676, 0x2009, 0x001d, 0x017e, 0x2011, - 0xac83, 0x2204, 0x8211, 0x220c, 0x1078, 0x254d, 0x00c0, 0x56ac, - 0x1078, 0x455c, 0x00c0, 0x56ac, 0x6612, 0x6516, 0x86ff, 0x0040, - 0x569c, 0x017f, 0x017e, 0xa186, 0x0017, 0x00c0, 0x569c, 0x686c, - 0xa606, 0x00c0, 0x569c, 0x6870, 0xa506, 0xa084, 0xff00, 0x00c0, - 0x569c, 0x6000, 0xc0f5, 0x6002, 0x0c7e, 0x1078, 0x76c7, 0x0040, - 0x56af, 0x017f, 0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0x017f, - 0x1078, 0x775c, 0x0c7f, 0x007c, 0x017f, 0x0078, 0x56aa, 0x0c7f, - 0x0078, 0x56ac, 0x0c7e, 0x1078, 0x570f, 0x00c0, 0x570d, 0xa28e, - 0x0033, 0x00c0, 0x56de, 0x1078, 0x591d, 0x0040, 0x570d, 0x7124, - 0x610a, 0x7030, 0xa08e, 0x0200, 0x00c0, 0x56d0, 0x7034, 0xa005, - 0x00c0, 0x570d, 0x2009, 0x0015, 0x1078, 0x775c, 0x0078, 0x570d, - 0xa08e, 0x0100, 0x00c0, 0x570d, 0x7034, 0xa005, 0x00c0, 0x570d, - 0x2009, 0x0016, 0x1078, 0x775c, 0x0078, 0x570d, 0xa28e, 0x0032, - 0x00c0, 0x570d, 0x7030, 0xa08e, 0x1400, 0x00c0, 0x570d, 0x2009, - 0x0038, 0x017e, 0x2011, 0xac83, 0x2204, 0x8211, 0x220c, 0x1078, - 0x254d, 0x00c0, 0x570c, 0x1078, 0x455c, 0x00c0, 0x570c, 0x6612, - 0x6516, 0x0c7e, 0x1078, 0x76c7, 0x0040, 0x570b, 0x017f, 0x611a, - 0x601f, 0x0004, 0x7120, 0x610a, 0x017f, 0x1078, 0x775c, 0x1078, - 0x62d1, 0x0078, 0x570d, 0x0c7f, 0x017f, 0x0c7f, 0x007c, 0x0f7e, - 0x0d7e, 0x027e, 0x017e, 0x137e, 0x147e, 0x157e, 0x3c00, 0x007e, - 0x2079, 0x0030, 0x2069, 0x0200, 0x1078, 0x1c6a, 0x00c0, 0x5750, - 0x1078, 0x1b40, 0x0040, 0x575d, 0x7908, 0xa18c, 0x1fff, 0xa182, - 0x0011, 0x00c8, 0x575a, 0x20a9, 0x000c, 0x20e1, 0x0000, 0x2ea0, - 0x2099, 0x020a, 0x53a5, 0x20e1, 0x2000, 0x2001, 0x020a, 0x2004, - 0x7a0c, 0x7808, 0xa080, 0x0007, 0xa084, 0x1ff8, 0xa08a, 0x0140, - 0x10c8, 0x1332, 0x80ac, 0x20e1, 0x6000, 0x2099, 0x020a, 0x53a5, - 0x20e1, 0x7000, 0x6828, 0x6828, 0x7803, 0x0004, 0xa294, 0x0070, - 0x007f, 0x20e0, 0x157f, 0x147f, 0x137f, 0x017f, 0x027f, 0x0d7f, - 0x0f7f, 0x007c, 0xa016, 0x1078, 0x15fa, 0xa085, 0x0001, 0x0078, - 0x5750, 0x047e, 0x0e7e, 0x0d7e, 0x2028, 0x2130, 0xa696, 0x00ff, - 0x00c0, 0x5782, 0xa596, 0xfffd, 0x00c0, 0x5772, 0x2009, 0x007f, - 0x0078, 0x57b5, 0xa596, 0xfffe, 0x00c0, 0x577a, 0x2009, 0x007e, - 0x0078, 0x57b5, 0xa596, 0xfffc, 0x00c0, 0x5782, 0x2009, 0x0080, - 0x0078, 0x57b5, 0x2011, 0x0000, 0x2021, 0x0081, 0x20a9, 0x007e, - 0x2071, 0xa8b6, 0x2e1c, 0x83ff, 0x00c0, 0x5794, 0x82ff, 0x00c0, - 0x57a9, 0x2410, 0x0078, 0x57a9, 0x2368, 0x6f10, 0x007e, 0x2100, - 0xa706, 0x007f, 0x6b14, 0x00c0, 0x57a3, 0xa346, 0x00c0, 0x57a3, - 0x2408, 0x0078, 0x57b5, 0x87ff, 0x00c0, 0x57a9, 0x83ff, 0x0040, - 0x578e, 0x8420, 0x8e70, 0x00f0, 0x578a, 0x82ff, 0x00c0, 0x57b4, - 0xa085, 0x0001, 0x0078, 0x57b6, 0x2208, 0xa006, 0x0d7f, 0x0e7f, - 0x047f, 0x007c, 0xa084, 0x0007, 0x0079, 0x57bf, 0x007c, 0x57c7, - 0x57c7, 0x57c7, 0x5933, 0x57c7, 0x57c8, 0x57e1, 0x5858, 0x007c, - 0x7110, 0xd1bc, 0x0040, 0x57e0, 0x7120, 0x2160, 0xac8c, 0x000f, - 0x00c0, 0x57e0, 0xac8a, 0xae00, 0x0048, 0x57e0, 0x6858, 0xac02, - 0x00c8, 0x57e0, 0x7124, 0x610a, 0x2009, 0x0046, 0x1078, 0x775c, - 0x007c, 0x0c7e, 0xa484, 0x01ff, 0x0040, 0x5833, 0x7110, 0xd1bc, - 0x00c0, 0x5833, 0x2011, 0xac83, 0x2204, 0x8211, 0x220c, 0x1078, - 0x254d, 0x00c0, 0x5833, 0x1078, 0x455c, 0x00c0, 0x5833, 0x6612, - 0x6516, 0x6000, 0xd0ec, 0x00c0, 0x5833, 0x6204, 0xa294, 0xff00, - 0x8217, 0xa286, 0x0006, 0x00c0, 0x5818, 0x0c7e, 0x1078, 0x76c7, - 0x017f, 0x0040, 0x5835, 0x611a, 0x601f, 0x0006, 0x7120, 0x610a, - 0x7130, 0x6122, 0x2009, 0x0044, 0x1078, 0x775c, 0x0078, 0x5833, - 0x0c7e, 0x1078, 0x76c7, 0x017f, 0x0040, 0x5833, 0x611a, 0x601f, - 0x0004, 0x7120, 0x610a, 0xa286, 0x0004, 0x00c0, 0x582b, 0x6007, - 0x0005, 0x0078, 0x582d, 0x6007, 0x0001, 0x6003, 0x0001, 0x1078, - 0x5dd7, 0x1078, 0x62d1, 0x0c7f, 0x007c, 0x2001, 0xa70d, 0x2004, - 0xd0ec, 0x0040, 0x583f, 0x2011, 0x8049, 0x1078, 0x361b, 0x0c7e, - 0x1078, 0x9197, 0x017f, 0x0040, 0x5833, 0x611a, 0x601f, 0x0006, - 0x7120, 0x610a, 0x7130, 0x6122, 0x6013, 0x0300, 0x6003, 0x0001, - 0x6007, 0x0041, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0078, 0x5833, - 0x7110, 0xd1bc, 0x0040, 0x5870, 0x7020, 0x2060, 0xac84, 0x000f, - 0x00c0, 0x5870, 0xac82, 0xae00, 0x0048, 0x5870, 0x6858, 0xac02, - 0x00c8, 0x5870, 0x7124, 0x610a, 0x2009, 0x0045, 0x1078, 0x775c, - 0x007c, 0x007e, 0x1078, 0x29bb, 0x007f, 0x00c0, 0x5887, 0x7110, - 0xa18c, 0xff00, 0x810f, 0xa18e, 0x0000, 0x00c0, 0x5887, 0xa084, - 0x000f, 0xa08a, 0x0006, 0x00c8, 0x5887, 0x1079, 0x5888, 0x007c, - 0x588e, 0x588f, 0x588e, 0x588e, 0x58ff, 0x590e, 0x007c, 0x7110, - 0xd1bc, 0x0040, 0x5897, 0x702c, 0xd084, 0x0040, 0x58fe, 0x700c, - 0x7108, 0x1078, 0x254d, 0x00c0, 0x58fe, 0x1078, 0x455c, 0x00c0, - 0x58fe, 0x6612, 0x6516, 0x6204, 0x7110, 0xd1bc, 0x0040, 0x58c9, - 0xa28c, 0x00ff, 0xa186, 0x0004, 0x0040, 0x58b2, 0xa186, 0x0006, - 0x00c0, 0x58ef, 0x0c7e, 0x1078, 0x591d, 0x0c7f, 0x0040, 0x58fe, - 0x0c7e, 0x1078, 0x76c7, 0x017f, 0x0040, 0x58fe, 0x611a, 0x601f, - 0x0002, 0x7120, 0x610a, 0x2009, 0x0088, 0x1078, 0x775c, 0x0078, - 0x58fe, 0xa28c, 0x00ff, 0xa186, 0x0006, 0x0040, 0x58de, 0xa186, - 0x0004, 0x0040, 0x58de, 0xa294, 0xff00, 0x8217, 0xa286, 0x0004, - 0x0040, 0x58de, 0xa286, 0x0006, 0x00c0, 0x58ef, 0x0c7e, 0x1078, - 0x76c7, 0x017f, 0x0040, 0x58fe, 0x611a, 0x601f, 0x0005, 0x7120, - 0x610a, 0x2009, 0x0088, 0x1078, 0x775c, 0x0078, 0x58fe, 0x0c7e, - 0x1078, 0x76c7, 0x017f, 0x0040, 0x58fe, 0x611a, 0x601f, 0x0004, - 0x7120, 0x610a, 0x2009, 0x0001, 0x1078, 0x775c, 0x007c, 0x7110, - 0xd1bc, 0x0040, 0x590d, 0x1078, 0x591d, 0x0040, 0x590d, 0x7124, - 0x610a, 0x2009, 0x0089, 0x1078, 0x775c, 0x007c, 0x7110, 0xd1bc, - 0x0040, 0x591c, 0x1078, 0x591d, 0x0040, 0x591c, 0x7124, 0x610a, - 0x2009, 0x008a, 0x1078, 0x775c, 0x007c, 0x7020, 0x2060, 0xac84, - 0x000f, 0x00c0, 0x5930, 0xac82, 0xae00, 0x0048, 0x5930, 0x2001, - 0xa716, 0x2004, 0xac02, 0x00c8, 0x5930, 0xa085, 0x0001, 0x007c, - 0xa006, 0x0078, 0x592f, 0x7110, 0xd1bc, 0x00c0, 0x5949, 0x7024, - 0x2060, 0xac84, 0x000f, 0x00c0, 0x5949, 0xac82, 0xae00, 0x0048, - 0x5949, 0x6858, 0xac02, 0x00c8, 0x5949, 0x2009, 0x0051, 0x1078, - 0x775c, 0x007c, 0x2071, 0xa9c4, 0x7003, 0x0003, 0x700f, 0x0361, - 0xa006, 0x701a, 0x7012, 0x7017, 0xae00, 0x7007, 0x0000, 0x7026, - 0x702b, 0x6e1c, 0x7032, 0x7037, 0x6e70, 0x703b, 0x0002, 0x703f, - 0x0000, 0x7043, 0xffff, 0x7047, 0xffff, 0x007c, 0x2071, 0xa9c4, - 0x00e0, 0x5a32, 0x2091, 0x6000, 0x700c, 0x8001, 0x700e, 0x00c0, - 0x59de, 0x700f, 0x0361, 0x7007, 0x0001, 0x127e, 0x2091, 0x8000, - 0x7138, 0x8109, 0x713a, 0x00c0, 0x59dc, 0x703b, 0x0002, 0x2009, - 0x0100, 0x2104, 0xa082, 0x0003, 0x00c8, 0x59dc, 0x703c, 0xa086, - 0x0001, 0x00c0, 0x59b9, 0x0d7e, 0x2069, 0x0140, 0x6804, 0xa084, - 0x4000, 0x0040, 0x5997, 0x6803, 0x1000, 0x0078, 0x599e, 0x6804, - 0xa084, 0x1000, 0x0040, 0x599e, 0x6803, 0x0100, 0x6803, 0x0000, - 0x703f, 0x0000, 0x2069, 0xa9b1, 0x6804, 0xa082, 0x0006, 0x00c0, - 0x59ab, 0x6807, 0x0000, 0x6830, 0xa082, 0x0003, 0x00c0, 0x59b2, - 0x6833, 0x0000, 0x1078, 0x62d1, 0x1078, 0x639b, 0x0d7f, 0x0078, - 0x59dc, 0x0d7e, 0x2069, 0xa700, 0x6948, 0x6864, 0xa102, 0x00c8, - 0x59db, 0x2069, 0xa9b1, 0x6804, 0xa086, 0x0000, 0x00c0, 0x59db, - 0x6830, 0xa086, 0x0000, 0x00c0, 0x59db, 0x703f, 0x0001, 0x6807, - 0x0006, 0x6833, 0x0003, 0x2069, 0x0100, 0x6830, 0x689e, 0x2069, - 0x0140, 0x6803, 0x0600, 0x0d7f, 0x0078, 0x59e1, 0x127e, 0x2091, - 0x8000, 0x7024, 0xa00d, 0x0040, 0x59f9, 0x7020, 0x8001, 0x7022, - 0x00c0, 0x59f9, 0x7023, 0x0009, 0x8109, 0x7126, 0xa186, 0x03e8, - 0x00c0, 0x59f4, 0x7028, 0x107a, 0x81ff, 0x00c0, 0x59f9, 0x7028, - 0x107a, 0x7030, 0xa00d, 0x0040, 0x5a10, 0x702c, 0x8001, 0x702e, - 0x00c0, 0x5a10, 0x702f, 0x0009, 0x8109, 0x7132, 0x0040, 0x5a0e, - 0xa184, 0x007f, 0x1040, 0x6ea2, 0x0078, 0x5a10, 0x7034, 0x107a, - 0x7040, 0xa005, 0x0040, 0x5a18, 0x0050, 0x5a18, 0x8001, 0x7042, - 0x7044, 0xa005, 0x0040, 0x5a20, 0x0050, 0x5a20, 0x8001, 0x7046, - 0x7018, 0xa00d, 0x0040, 0x5a31, 0x7008, 0x8001, 0x700a, 0x00c0, - 0x5a31, 0x700b, 0x0009, 0x8109, 0x711a, 0x00c0, 0x5a31, 0x701c, - 0x107a, 0x127f, 0x7004, 0x0079, 0x5a35, 0x5a5c, 0x5a5d, 0x5a79, - 0x0e7e, 0x2071, 0xa9c4, 0x7018, 0xa005, 0x00c0, 0x5a43, 0x711a, - 0x721e, 0x700b, 0x0009, 0x0e7f, 0x007c, 0x0e7e, 0x007e, 0x2071, - 0xa9c4, 0x701c, 0xa206, 0x00c0, 0x5a4f, 0x701a, 0x701e, 0x007f, - 0x0e7f, 0x007c, 0x0e7e, 0x2071, 0xa9c4, 0x6088, 0xa102, 0x0048, - 0x5a5a, 0x618a, 0x0e7f, 0x007c, 0x007c, 0x7110, 0x1078, 0x45c4, - 0x00c0, 0x5a6f, 0x6088, 0x8001, 0x0048, 0x5a6f, 0x608a, 0x00c0, - 0x5a6f, 0x127e, 0x2091, 0x8000, 0x1078, 0x62d1, 0x127f, 0x8108, - 0xa182, 0x00ff, 0x0048, 0x5a77, 0xa00e, 0x7007, 0x0002, 0x7112, - 0x007c, 0x7014, 0x2060, 0x127e, 0x2091, 0x8000, 0x603c, 0xa005, - 0x0040, 0x5a88, 0x8001, 0x603e, 0x00c0, 0x5a88, 0x1078, 0x8fac, - 0x6014, 0xa005, 0x0040, 0x5ab2, 0x8001, 0x6016, 0x00c0, 0x5ab2, - 0x611c, 0xa186, 0x0003, 0x0040, 0x5a99, 0xa186, 0x0006, 0x00c0, - 0x5ab0, 0x6010, 0x2068, 0x6854, 0xa08a, 0x199a, 0x0048, 0x5ab0, - 0xa082, 0x1999, 0x6856, 0xa08a, 0x199a, 0x0048, 0x5aa9, 0x2001, - 0x1999, 0x8003, 0x800b, 0x810b, 0xa108, 0x6116, 0x0078, 0x5ab2, - 0x1078, 0x8ace, 0x127f, 0xac88, 0x0010, 0x7116, 0x2001, 0xce00, - 0xa102, 0x0048, 0x5abf, 0x7017, 0xae00, 0x7007, 0x0000, 0x007c, - 0x0e7e, 0x2071, 0xa9c4, 0x7027, 0x07d0, 0x7023, 0x0009, 0x703b, - 0x0002, 0x0e7f, 0x007c, 0x2001, 0xa9cd, 0x2003, 0x0000, 0x007c, - 0x0e7e, 0x2071, 0xa9c4, 0x7132, 0x702f, 0x0009, 0x0e7f, 0x007c, - 0x2011, 0xa9d0, 0x2013, 0x0000, 0x007c, 0x0e7e, 0x2071, 0xa9c4, - 0x711a, 0x721e, 0x700b, 0x0009, 0x0e7f, 0x007c, 0x027e, 0x0e7e, - 0x0f7e, 0x2079, 0xa700, 0x7a34, 0xd294, 0x0040, 0x5b15, 0x2071, - 0xa9ac, 0x2e14, 0xa0fe, 0x0000, 0x0040, 0x5b02, 0xa0fe, 0x0001, - 0x0040, 0x5b06, 0xa0fe, 0x0002, 0x00c0, 0x5b11, 0xa292, 0x0085, - 0x0078, 0x5b08, 0xa292, 0x0005, 0x0078, 0x5b08, 0xa292, 0x0002, - 0x2272, 0x0040, 0x5b0d, 0x00c8, 0x5b15, 0x2011, 0x8037, 0x1078, - 0x361b, 0x2011, 0xa9ab, 0x2204, 0x2072, 0x0f7f, 0x0e7f, 0x027f, - 0x007c, 0x0c7e, 0x2061, 0xaa33, 0x0c7f, 0x007c, 0xa184, 0x000f, - 0x8003, 0x8003, 0x8003, 0xa080, 0xaa33, 0x2060, 0x007c, 0x6854, - 0xa08a, 0x199a, 0x0048, 0x5b2e, 0x2001, 0x1999, 0xa005, 0x00c0, - 0x5b3d, 0x0c7e, 0x2061, 0xaa33, 0x6014, 0x0c7f, 0xa005, 0x00c0, - 0x5b42, 0x2001, 0x001e, 0x0078, 0x5b42, 0xa08e, 0xffff, 0x00c0, - 0x5b42, 0xa006, 0x8003, 0x800b, 0x810b, 0xa108, 0x6116, 0x684c, - 0xa08c, 0x00c0, 0xa18e, 0x00c0, 0x0040, 0x5b9e, 0xd0b4, 0x00c0, - 0x5b59, 0xd0bc, 0x00c0, 0x5b8b, 0x2009, 0x0006, 0x1078, 0x5bc3, - 0x007c, 0xd0fc, 0x0040, 0x5b64, 0xa084, 0x0003, 0x0040, 0x5b64, - 0xa086, 0x0003, 0x00c0, 0x5bbc, 0x6024, 0xd0d4, 0x0040, 0x5b6e, - 0xc0d4, 0x6026, 0x6860, 0x602a, 0x685c, 0x602e, 0x2009, 0xa774, - 0x2104, 0xd084, 0x0040, 0x5b83, 0x6118, 0xa188, 0x0027, 0x2104, - 0xd08c, 0x00c0, 0x5b83, 0x87ff, 0x00c0, 0x5b82, 0x2009, 0x0042, - 0x1078, 0x775c, 0x007c, 0x87ff, 0x00c0, 0x5b8a, 0x2009, 0x0043, - 0x1078, 0x775c, 0x007c, 0xd0fc, 0x0040, 0x5b96, 0xa084, 0x0003, - 0x0040, 0x5b96, 0xa086, 0x0003, 0x00c0, 0x5bbc, 0x87ff, 0x00c0, - 0x5b9d, 0x2009, 0x0042, 0x1078, 0x775c, 0x007c, 0xd0fc, 0x0040, - 0x5baf, 0xa084, 0x0003, 0xa08e, 0x0002, 0x0040, 0x5bb3, 0x87ff, - 0x00c0, 0x5bae, 0x2009, 0x0041, 0x1078, 0x775c, 0x007c, 0x1078, - 0x5bc1, 0x0078, 0x5bae, 0x87ff, 0x00c0, 0x5bae, 0x2009, 0x0043, - 0x1078, 0x775c, 0x0078, 0x5bae, 0x2009, 0x0004, 0x1078, 0x5bc3, - 0x007c, 0x2009, 0x0001, 0x0d7e, 0x6010, 0xa0ec, 0xf000, 0x0040, - 0x5bef, 0x2068, 0x6952, 0x6800, 0x6012, 0xa186, 0x0001, 0x00c0, - 0x5be5, 0x694c, 0xa18c, 0x8100, 0xa18e, 0x8100, 0x00c0, 0x5be5, - 0x0c7e, 0x2061, 0xaa33, 0x6200, 0xd28c, 0x00c0, 0x5be4, 0x6204, - 0x8210, 0x0048, 0x5be4, 0x6206, 0x0c7f, 0x1078, 0x4a73, 0x6010, - 0xa06d, 0x077e, 0x2039, 0x0000, 0x10c0, 0x5b27, 0x077f, 0x0d7f, - 0x007c, 0x157e, 0x0c7e, 0x2061, 0xaa33, 0x6000, 0x81ff, 0x0040, - 0x5bfc, 0xa205, 0x0078, 0x5bfd, 0xa204, 0x6002, 0x0c7f, 0x157f, - 0x007c, 0x6800, 0xd08c, 0x00c0, 0x5c0d, 0x6808, 0xa005, 0x0040, - 0x5c0d, 0x8001, 0x680a, 0xa085, 0x0001, 0x007c, 0x20a9, 0x0010, - 0xa006, 0x8004, 0x8086, 0x818e, 0x00c8, 0x5c17, 0xa200, 0x00f0, - 0x5c12, 0x8086, 0x818e, 0x007c, 0x157e, 0x20a9, 0x0010, 0xa005, - 0x0040, 0x5c3d, 0xa11a, 0x00c8, 0x5c3d, 0x8213, 0x818d, 0x0048, - 0x5c30, 0xa11a, 0x00c8, 0x5c31, 0x00f0, 0x5c25, 0x0078, 0x5c35, - 0xa11a, 0x2308, 0x8210, 0x00f0, 0x5c25, 0x007e, 0x3200, 0xa084, - 0xf7ff, 0x2080, 0x007f, 0x157f, 0x007c, 0x007e, 0x3200, 0xa085, - 0x0800, 0x0078, 0x5c39, 0x127e, 0x2091, 0x2200, 0x2079, 0xa9b1, - 0x127f, 0x0d7e, 0x2069, 0xa9b1, 0x6803, 0x0005, 0x2069, 0x0004, - 0x2d04, 0xa085, 0x8001, 0x206a, 0x0d7f, 0x007c, 0x0c7e, 0x6027, - 0x0001, 0x7804, 0xa084, 0x0007, 0x0079, 0x5c5e, 0x5c68, 0x5c8d, - 0x5ce8, 0x5c6e, 0x5c8d, 0x5c68, 0x5c66, 0x5c66, 0x1078, 0x1332, - 0x1078, 0x5acb, 0x1078, 0x62d1, 0x0c7f, 0x007c, 0x62c0, 0x82ff, - 0x00c0, 0x5c74, 0x0c7f, 0x007c, 0x2011, 0x41dc, 0x1078, 0x5a45, - 0x7828, 0xa092, 0x00c8, 0x00c8, 0x5c83, 0x8000, 0x782a, 0x1078, - 0x421b, 0x0078, 0x5c72, 0x1078, 0x41dc, 0x7807, 0x0003, 0x7827, - 0x0000, 0x782b, 0x0000, 0x0078, 0x5c72, 0x1078, 0x5acb, 0x3c00, - 0x007e, 0x2011, 0x0209, 0x20e1, 0x4000, 0x2214, 0x007f, 0x20e0, - 0x82ff, 0x0040, 0x5cab, 0x62c0, 0x82ff, 0x00c0, 0x5cab, 0x782b, - 0x0000, 0x7824, 0xa065, 0x1040, 0x1332, 0x2009, 0x0013, 0x1078, - 0x775c, 0x0c7f, 0x007c, 0x3900, 0xa082, 0xaae3, 0x00c8, 0x5cb2, - 0x1078, 0x747a, 0x0c7e, 0x7824, 0xa065, 0x1040, 0x1332, 0x7804, - 0xa086, 0x0004, 0x0040, 0x5d2d, 0x7828, 0xa092, 0x2710, 0x00c8, - 0x5cc8, 0x8000, 0x782a, 0x0c7f, 0x1078, 0x6e01, 0x0078, 0x5ca9, - 0x6104, 0xa186, 0x0003, 0x00c0, 0x5cdf, 0x0e7e, 0x2071, 0xa700, - 0x70d8, 0x0e7f, 0xd08c, 0x0040, 0x5cdf, 0x0c7e, 0x0e7e, 0x2061, - 0x0100, 0x2071, 0xa700, 0x1078, 0x4224, 0x0e7f, 0x0c7f, 0x1078, - 0xa5d4, 0x2009, 0x0014, 0x1078, 0x775c, 0x0c7f, 0x0078, 0x5ca9, - 0x2001, 0xa9cd, 0x2003, 0x0000, 0x62c0, 0x82ff, 0x00c0, 0x5cfc, - 0x782b, 0x0000, 0x7824, 0xa065, 0x1040, 0x1332, 0x2009, 0x0013, - 0x1078, 0x77b3, 0x0c7f, 0x007c, 0x0c7e, 0x0d7e, 0x3900, 0xa082, - 0xaae3, 0x00c8, 0x5d05, 0x1078, 0x747a, 0x7824, 0xa005, 0x1040, - 0x1332, 0x781c, 0xa06d, 0x1040, 0x1332, 0x6800, 0xc0dc, 0x6802, - 0x7924, 0x2160, 0x1078, 0x772d, 0x693c, 0x81ff, 0x1040, 0x1332, - 0x8109, 0x693e, 0x6854, 0xa015, 0x0040, 0x5d21, 0x7a1e, 0x0078, - 0x5d23, 0x7918, 0x791e, 0x7807, 0x0000, 0x7827, 0x0000, 0x0d7f, - 0x0c7f, 0x1078, 0x62d1, 0x0078, 0x5cfa, 0x6104, 0xa186, 0x0002, - 0x0040, 0x5d38, 0xa186, 0x0004, 0x0040, 0x5d38, 0x0078, 0x5cbc, - 0x7808, 0xac06, 0x0040, 0x5cbc, 0x1078, 0x61cd, 0x1078, 0x5dd7, - 0x0c7f, 0x1078, 0x62d1, 0x0078, 0x5ca9, 0x0c7e, 0x6027, 0x0002, - 0x62c8, 0x82ff, 0x00c0, 0x5d61, 0x62c4, 0x82ff, 0x00c0, 0x5d61, - 0x793c, 0xa1e5, 0x0000, 0x0040, 0x5d5b, 0x2009, 0x0049, 0x1078, - 0x775c, 0x0c7f, 0x007c, 0x2011, 0xa9d0, 0x2013, 0x0000, 0x0078, - 0x5d59, 0x3908, 0xa192, 0xaae3, 0x00c8, 0x5d68, 0x1078, 0x747a, - 0x6017, 0x0010, 0x793c, 0x81ff, 0x0040, 0x5d5b, 0x7944, 0xa192, - 0x7530, 0x00c8, 0x5d85, 0x8108, 0x7946, 0x793c, 0xa188, 0x0007, - 0x210c, 0xa18e, 0x0006, 0x00c0, 0x5d81, 0x6017, 0x0012, 0x0078, - 0x5d59, 0x6017, 0x0016, 0x0078, 0x5d59, 0x7848, 0xc085, 0x784a, - 0x0078, 0x5d59, 0x007e, 0x017e, 0x0c7e, 0x127e, 0x2091, 0x8000, - 0x600f, 0x0000, 0x2c08, 0x2061, 0xa9b1, 0x6020, 0x8000, 0x6022, - 0x6010, 0xa005, 0x0040, 0x5da5, 0xa080, 0x0003, 0x2102, 0x6112, - 0x127f, 0x0c7f, 0x017f, 0x007f, 0x007c, 0x6116, 0x6112, 0x0078, - 0x5da0, 0x0d7e, 0x2069, 0xa9b1, 0x6000, 0xd0d4, 0x0040, 0x5dbe, - 0x6820, 0x8000, 0x6822, 0xa086, 0x0001, 0x00c0, 0x5db9, 0x2c00, - 0x681e, 0x6804, 0xa084, 0x0007, 0x0079, 0x62d9, 0xc0d5, 0x6002, - 0x6818, 0xa005, 0x0040, 0x5dd0, 0x6056, 0x605b, 0x0000, 0x007e, - 0x2c00, 0x681a, 0x0d7f, 0x685a, 0x2069, 0xa9b1, 0x0078, 0x5db0, - 0x6056, 0x605a, 0x2c00, 0x681a, 0x681e, 0x0078, 0x5db0, 0x007e, - 0x017e, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, - 0x2061, 0xa9b1, 0x6020, 0x8000, 0x6022, 0x6008, 0xa005, 0x0040, - 0x5df2, 0xa080, 0x0003, 0x2102, 0x610a, 0x127f, 0x0c7f, 0x017f, - 0x007f, 0x007c, 0x610e, 0x610a, 0x0078, 0x5ded, 0x0c7e, 0x600f, - 0x0000, 0x2c08, 0x2061, 0xa9b1, 0x6034, 0xa005, 0x0040, 0x5e06, - 0xa080, 0x0003, 0x2102, 0x6136, 0x0c7f, 0x007c, 0x613a, 0x6136, - 0x0078, 0x5e04, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x057e, - 0x037e, 0x027e, 0x017e, 0x007e, 0x127e, 0xa02e, 0x2071, 0xa9b1, - 0x7638, 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, 0x0040, 0x5e8c, - 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x00c0, 0x5e87, 0x87ff, - 0x0040, 0x5e2e, 0x6020, 0xa106, 0x00c0, 0x5e87, 0x703c, 0xac06, - 0x00c0, 0x5e44, 0x037e, 0x2019, 0x0001, 0x1078, 0x7058, 0x7033, - 0x0000, 0x703f, 0x0000, 0x7043, 0x0000, 0x7047, 0x0000, 0x704b, - 0x0000, 0x037f, 0x2029, 0x0001, 0x7038, 0xac36, 0x00c0, 0x5e4a, - 0x660c, 0x763a, 0x7034, 0xac36, 0x00c0, 0x5e58, 0x2c00, 0xaf36, - 0x0040, 0x5e56, 0x2f00, 0x7036, 0x0078, 0x5e58, 0x7037, 0x0000, - 0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040, 0x5e61, 0x7e0e, 0x0078, - 0x5e62, 0x2678, 0x600f, 0x0000, 0x1078, 0x8d16, 0x0040, 0x5e82, - 0x6010, 0x2068, 0x601c, 0xa086, 0x0003, 0x00c0, 0x5e9d, 0x6837, - 0x0103, 0x6b4a, 0x6847, 0x0000, 0x017e, 0x037e, 0x077e, 0x1078, - 0x8f8d, 0x1078, 0xa4f2, 0x1078, 0x4a73, 0x077f, 0x037f, 0x017f, - 0x1078, 0x8ec9, 0x1078, 0x8ed6, 0x0c7f, 0x0078, 0x5e1d, 0x2c78, - 0x600c, 0x2060, 0x0078, 0x5e1d, 0x85ff, 0x0040, 0x5e91, 0x1078, - 0x639b, 0x127f, 0x007f, 0x017f, 0x027f, 0x037f, 0x057f, 0x067f, - 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x601c, 0xa086, 0x0006, - 0x00c0, 0x5e6f, 0x017e, 0x037e, 0x077e, 0x1078, 0xa4f2, 0x1078, - 0xa1da, 0x077f, 0x037f, 0x017f, 0x0078, 0x5e82, 0x007e, 0x067e, - 0x0c7e, 0x0d7e, 0x0f7e, 0x2031, 0x0000, 0x127e, 0x2091, 0x8000, - 0x2079, 0xa9b1, 0x7838, 0xa065, 0x0040, 0x5eef, 0x600c, 0x007e, - 0x600f, 0x0000, 0x783c, 0xac06, 0x00c0, 0x5ed6, 0x037e, 0x2019, - 0x0001, 0x1078, 0x7058, 0x7833, 0x0000, 0x783f, 0x0000, 0x7843, - 0x0000, 0x7847, 0x0000, 0x784b, 0x0000, 0x037f, 0x1078, 0x8d16, - 0x0040, 0x5eea, 0x6010, 0x2068, 0x601c, 0xa086, 0x0003, 0x00c0, - 0x5ef8, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x4a73, - 0x1078, 0x8ec9, 0x1078, 0x8ed6, 0x007f, 0x0078, 0x5ebb, 0x7e3a, - 0x7e36, 0x127f, 0x0f7f, 0x0d7f, 0x0c7f, 0x067f, 0x007f, 0x007c, - 0x601c, 0xa086, 0x0006, 0x00c0, 0x5ee1, 0x1078, 0xa1da, 0x0078, - 0x5eea, 0x017e, 0x027e, 0x087e, 0x2041, 0x0000, 0x1078, 0x5f1b, - 0x1078, 0x5fdb, 0x087f, 0x027f, 0x017f, 0x007c, 0x0f7e, 0x127e, - 0x2079, 0xa9b1, 0x2091, 0x8000, 0x1078, 0x6076, 0x1078, 0x60ec, - 0x127f, 0x0f7f, 0x007c, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, - 0x017e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071, 0xa9b1, 0x7614, - 0x2660, 0x2678, 0x8cff, 0x0040, 0x5fb5, 0x6018, 0xa080, 0x0028, - 0x2004, 0xa206, 0x00c0, 0x5fb0, 0x88ff, 0x0040, 0x5f3b, 0x6020, - 0xa106, 0x00c0, 0x5fb0, 0x7024, 0xac06, 0x00c0, 0x5f6b, 0x2069, - 0x0100, 0x68c0, 0xa005, 0x0040, 0x5f66, 0x1078, 0x5acb, 0x1078, - 0x6e0f, 0x68c3, 0x0000, 0x1078, 0x7378, 0x7027, 0x0000, 0x037e, - 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0040, 0x5f5b, 0x6803, - 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0040, - 0x5f63, 0x6827, 0x0001, 0x037f, 0x0078, 0x5f6b, 0x6003, 0x0009, - 0x630a, 0x0078, 0x5fb0, 0x7014, 0xac36, 0x00c0, 0x5f71, 0x660c, - 0x7616, 0x7010, 0xac36, 0x00c0, 0x5f7f, 0x2c00, 0xaf36, 0x0040, - 0x5f7d, 0x2f00, 0x7012, 0x0078, 0x5f7f, 0x7013, 0x0000, 0x660c, - 0x067e, 0x2c00, 0xaf06, 0x0040, 0x5f88, 0x7e0e, 0x0078, 0x5f89, - 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x1078, 0x8d16, 0x0040, - 0x5fa9, 0x601c, 0xa086, 0x0003, 0x00c0, 0x5fbe, 0x6837, 0x0103, - 0x6b4a, 0x6847, 0x0000, 0x017e, 0x037e, 0x087e, 0x1078, 0x8f8d, - 0x1078, 0xa4f2, 0x1078, 0x4a73, 0x087f, 0x037f, 0x017f, 0x1078, - 0x8ec9, 0x1078, 0x8ed6, 0x1078, 0x7233, 0x0c7f, 0x0078, 0x5f2a, - 0x2c78, 0x600c, 0x2060, 0x0078, 0x5f2a, 0x127f, 0x007f, 0x017f, - 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x601c, 0xa086, - 0x0006, 0x00c0, 0x5fcf, 0x017e, 0x037e, 0x087e, 0x1078, 0xa4f2, - 0x1078, 0xa1da, 0x087f, 0x037f, 0x017f, 0x0078, 0x5fa9, 0x601c, - 0xa086, 0x0002, 0x00c0, 0x5fa9, 0x6004, 0xa086, 0x0085, 0x0040, - 0x5f96, 0x0078, 0x5fa9, 0x0c7e, 0x007e, 0x127e, 0x2091, 0x8000, - 0xa280, 0xa835, 0x2004, 0xa065, 0x0040, 0x6072, 0x0f7e, 0x0e7e, - 0x0d7e, 0x067e, 0x2071, 0xa9b1, 0x6654, 0x7018, 0xac06, 0x00c0, - 0x5ff2, 0x761a, 0x701c, 0xac06, 0x00c0, 0x5ffe, 0x86ff, 0x00c0, - 0x5ffd, 0x7018, 0x701e, 0x0078, 0x5ffe, 0x761e, 0x6058, 0xa07d, - 0x0040, 0x6003, 0x7e56, 0xa6ed, 0x0000, 0x0040, 0x6009, 0x2f00, - 0x685a, 0x6057, 0x0000, 0x605b, 0x0000, 0x6000, 0xc0d4, 0xc0dc, - 0x6002, 0x1078, 0x44d3, 0x0040, 0x606e, 0x7624, 0x86ff, 0x0040, - 0x605c, 0xa680, 0x0004, 0x2004, 0xad06, 0x00c0, 0x605c, 0x0d7e, - 0x2069, 0x0100, 0x68c0, 0xa005, 0x0040, 0x6053, 0x1078, 0x5acb, - 0x1078, 0x6e0f, 0x68c3, 0x0000, 0x1078, 0x7378, 0x7027, 0x0000, - 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0040, 0x603c, - 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, - 0x0040, 0x6044, 0x6827, 0x0001, 0x037f, 0x0d7f, 0x0c7e, 0x603c, - 0xa005, 0x0040, 0x604d, 0x8001, 0x603e, 0x2660, 0x1078, 0x8ed6, - 0x0c7f, 0x0078, 0x605c, 0x0d7f, 0x0c7e, 0x2660, 0x6003, 0x0009, - 0x630a, 0x0c7f, 0x0078, 0x6011, 0x8dff, 0x0040, 0x606a, 0x6837, - 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x8f8d, 0x1078, 0xa4f2, - 0x1078, 0x4a73, 0x1078, 0x7233, 0x0078, 0x6011, 0x067f, 0x0d7f, - 0x0e7f, 0x0f7f, 0x127f, 0x007f, 0x0c7f, 0x007c, 0x007e, 0x067e, - 0x0c7e, 0x0d7e, 0x2031, 0x0000, 0x7814, 0xa065, 0x0040, 0x60d0, - 0x600c, 0x007e, 0x600f, 0x0000, 0x7824, 0xac06, 0x00c0, 0x60b5, - 0x2069, 0x0100, 0x68c0, 0xa005, 0x0040, 0x60af, 0x1078, 0x5acb, - 0x1078, 0x6e0f, 0x68c3, 0x0000, 0x1078, 0x7378, 0x7827, 0x0000, - 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0040, 0x60a4, - 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, - 0x0040, 0x60ac, 0x6827, 0x0001, 0x037f, 0x0078, 0x60b5, 0x6003, - 0x0009, 0x630a, 0x2c30, 0x0078, 0x60cd, 0x6010, 0x2068, 0x1078, - 0x8d16, 0x0040, 0x60c9, 0x601c, 0xa086, 0x0003, 0x00c0, 0x60d7, - 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x4a73, 0x1078, - 0x8ec9, 0x1078, 0x8ed6, 0x1078, 0x7233, 0x007f, 0x0078, 0x607d, - 0x7e16, 0x7e12, 0x0d7f, 0x0c7f, 0x067f, 0x007f, 0x007c, 0x601c, - 0xa086, 0x0006, 0x00c0, 0x60e0, 0x1078, 0xa1da, 0x0078, 0x60c9, - 0x601c, 0xa086, 0x0002, 0x00c0, 0x60c9, 0x6004, 0xa086, 0x0085, - 0x0040, 0x60c0, 0x0078, 0x60c9, 0x007e, 0x067e, 0x0c7e, 0x0d7e, - 0x7818, 0xa065, 0x0040, 0x615a, 0x6054, 0x007e, 0x6057, 0x0000, - 0x605b, 0x0000, 0x6000, 0xc0d4, 0xc0dc, 0x6002, 0x1078, 0x44d3, - 0x0040, 0x6157, 0x7e24, 0x86ff, 0x0040, 0x6149, 0xa680, 0x0004, - 0x2004, 0xad06, 0x00c0, 0x6149, 0x0d7e, 0x2069, 0x0100, 0x68c0, - 0xa005, 0x0040, 0x6140, 0x1078, 0x5acb, 0x1078, 0x6e0f, 0x68c3, - 0x0000, 0x1078, 0x7378, 0x7827, 0x0000, 0x037e, 0x2069, 0x0140, - 0x6b04, 0xa384, 0x1000, 0x0040, 0x6129, 0x6803, 0x0100, 0x6803, - 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0040, 0x6131, 0x6827, - 0x0001, 0x037f, 0x0d7f, 0x0c7e, 0x603c, 0xa005, 0x0040, 0x613a, - 0x8001, 0x603e, 0x2660, 0x1078, 0x8ed6, 0x0c7f, 0x0078, 0x6149, - 0x0d7f, 0x0c7e, 0x2660, 0x6003, 0x0009, 0x630a, 0x0c7f, 0x0078, - 0x60fe, 0x8dff, 0x0040, 0x6153, 0x6837, 0x0103, 0x6b4a, 0x6847, - 0x0000, 0x1078, 0x4a73, 0x1078, 0x7233, 0x0078, 0x60fe, 0x007f, - 0x0078, 0x60f1, 0x781e, 0x781a, 0x0d7f, 0x0c7f, 0x067f, 0x007f, - 0x007c, 0x0e7e, 0x0d7e, 0x067e, 0x6000, 0xd0dc, 0x0040, 0x6181, - 0x604c, 0xa06d, 0x0040, 0x6181, 0x6848, 0xa606, 0x00c0, 0x6181, - 0x2071, 0xa9b1, 0x7024, 0xa035, 0x0040, 0x6181, 0xa080, 0x0004, - 0x2004, 0xad06, 0x00c0, 0x6181, 0x6000, 0xc0dc, 0x6002, 0x1078, - 0x6185, 0x067f, 0x0d7f, 0x0e7f, 0x007c, 0x0f7e, 0x2079, 0x0100, - 0x78c0, 0xa005, 0x00c0, 0x6194, 0x0c7e, 0x2660, 0x6003, 0x0009, - 0x630a, 0x0c7f, 0x0078, 0x61cb, 0x1078, 0x6e0f, 0x78c3, 0x0000, - 0x1078, 0x7378, 0x7027, 0x0000, 0x037e, 0x2079, 0x0140, 0x7b04, - 0xa384, 0x1000, 0x0040, 0x61a8, 0x7803, 0x0100, 0x7803, 0x0000, - 0x2079, 0x0100, 0x7824, 0xd084, 0x0040, 0x61b0, 0x7827, 0x0001, - 0x1078, 0x7378, 0x037f, 0x1078, 0x44d3, 0x0c7e, 0x603c, 0xa005, - 0x0040, 0x61bc, 0x8001, 0x603e, 0x2660, 0x1078, 0x772d, 0x0c7f, - 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x8f8d, 0x1078, - 0x4a73, 0x1078, 0x7233, 0x0f7f, 0x007c, 0x0e7e, 0x0c7e, 0x2071, - 0xa9b1, 0x7004, 0xa084, 0x0007, 0x0079, 0x61d6, 0x61e0, 0x61e3, - 0x61fc, 0x6218, 0x6262, 0x61e0, 0x61e0, 0x61de, 0x1078, 0x1332, - 0x0c7f, 0x0e7f, 0x007c, 0x7024, 0xa065, 0x0040, 0x61f1, 0x7020, - 0x8001, 0x7022, 0x600c, 0xa015, 0x0040, 0x61f8, 0x7216, 0x600f, - 0x0000, 0x7007, 0x0000, 0x7027, 0x0000, 0x0c7f, 0x0e7f, 0x007c, - 0x7216, 0x7212, 0x0078, 0x61f1, 0x6018, 0x2060, 0x1078, 0x44d3, - 0x6000, 0xc0dc, 0x6002, 0x7020, 0x8001, 0x7022, 0x0040, 0x620d, - 0x6054, 0xa015, 0x0040, 0x6214, 0x721e, 0x7007, 0x0000, 0x7027, - 0x0000, 0x0c7f, 0x0e7f, 0x007c, 0x7218, 0x721e, 0x0078, 0x620d, - 0x7024, 0xa065, 0x0040, 0x625f, 0x700c, 0xac06, 0x00c0, 0x622f, - 0x1078, 0x7233, 0x600c, 0xa015, 0x0040, 0x622b, 0x720e, 0x600f, - 0x0000, 0x0078, 0x625d, 0x720e, 0x720a, 0x0078, 0x625d, 0x7014, - 0xac06, 0x00c0, 0x6242, 0x1078, 0x7233, 0x600c, 0xa015, 0x0040, - 0x623e, 0x7216, 0x600f, 0x0000, 0x0078, 0x625d, 0x7216, 0x7212, - 0x0078, 0x625d, 0x601c, 0xa086, 0x0003, 0x00c0, 0x625d, 0x6018, - 0x2060, 0x1078, 0x44d3, 0x6000, 0xc0dc, 0x6002, 0x1078, 0x7233, - 0x701c, 0xa065, 0x0040, 0x625d, 0x6054, 0xa015, 0x0040, 0x625b, - 0x721e, 0x0078, 0x625d, 0x7218, 0x721e, 0x7027, 0x0000, 0x0c7f, - 0x0e7f, 0x007c, 0x7024, 0xa065, 0x0040, 0x626f, 0x1078, 0x7233, - 0x600c, 0xa015, 0x0040, 0x6276, 0x720e, 0x600f, 0x0000, 0x1078, - 0x7378, 0x7027, 0x0000, 0x0c7f, 0x0e7f, 0x007c, 0x720e, 0x720a, - 0x0078, 0x626f, 0x0d7e, 0x2069, 0xa9b1, 0x6830, 0xa084, 0x0003, - 0x0079, 0x6282, 0x6288, 0x628a, 0x62b4, 0x6288, 0x1078, 0x1332, - 0x0d7f, 0x007c, 0x0c7e, 0x6840, 0xa086, 0x0001, 0x0040, 0x62aa, - 0x683c, 0xa065, 0x0040, 0x629b, 0x600c, 0xa015, 0x0040, 0x62a6, - 0x6a3a, 0x600f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, 0x2011, - 0xa9d0, 0x2013, 0x0000, 0x0c7f, 0x0d7f, 0x007c, 0x683a, 0x6836, - 0x0078, 0x629b, 0x6843, 0x0000, 0x6838, 0xa065, 0x0040, 0x629b, - 0x6003, 0x0003, 0x0078, 0x629b, 0x0c7e, 0x6843, 0x0000, 0x6847, - 0x0000, 0x684b, 0x0000, 0x683c, 0xa065, 0x0040, 0x62ce, 0x600c, - 0xa015, 0x0040, 0x62ca, 0x6a3a, 0x600f, 0x0000, 0x683f, 0x0000, - 0x0078, 0x62ce, 0x683f, 0x0000, 0x683a, 0x6836, 0x0c7f, 0x0d7f, - 0x007c, 0x0d7e, 0x2069, 0xa9b1, 0x6804, 0xa084, 0x0007, 0x0079, - 0x62d9, 0x62e3, 0x638a, 0x638a, 0x638a, 0x638a, 0x638c, 0x638a, - 0x62e1, 0x1078, 0x1332, 0x6820, 0xa005, 0x00c0, 0x62e9, 0x0d7f, - 0x007c, 0x0c7e, 0x680c, 0xa065, 0x0040, 0x62f8, 0x6807, 0x0004, - 0x6826, 0x682b, 0x0000, 0x1078, 0x63d4, 0x0c7f, 0x0d7f, 0x007c, - 0x6814, 0xa065, 0x0040, 0x6306, 0x6807, 0x0001, 0x6826, 0x682b, - 0x0000, 0x1078, 0x63d4, 0x0c7f, 0x0d7f, 0x007c, 0x0e7e, 0x037e, - 0x6a1c, 0xa2f5, 0x0000, 0x0040, 0x6385, 0x704c, 0xa00d, 0x0040, - 0x6315, 0x7088, 0xa005, 0x0040, 0x632d, 0x7054, 0xa075, 0x0040, - 0x631e, 0xa20e, 0x0040, 0x6385, 0x0078, 0x6323, 0x6818, 0xa20e, - 0x0040, 0x6385, 0x2070, 0x704c, 0xa00d, 0x0040, 0x6315, 0x7088, - 0xa005, 0x00c0, 0x6315, 0x2e00, 0x681e, 0x733c, 0x7038, 0xa302, - 0x00c8, 0x6315, 0x1078, 0x76fc, 0x0040, 0x6385, 0x8318, 0x733e, - 0x6112, 0x2e10, 0x621a, 0xa180, 0x0014, 0x2004, 0xa084, 0x00ff, - 0x6032, 0xa180, 0x0014, 0x2003, 0x0000, 0xa180, 0x0015, 0x2004, - 0xa08a, 0x199a, 0x0048, 0x634e, 0x2001, 0x1999, 0x8003, 0x801b, - 0x831b, 0xa318, 0x6316, 0x037f, 0x0f7e, 0x2c78, 0x71a0, 0xd1bc, - 0x0040, 0x6367, 0x7100, 0xd1f4, 0x0040, 0x6363, 0x7114, 0xa18c, - 0x00ff, 0x0078, 0x636c, 0x2009, 0x0000, 0x0078, 0x636c, 0xa1e0, - 0x29c0, 0x2c0c, 0xa18c, 0x00ff, 0x2061, 0x0100, 0x619a, 0x1078, - 0x6965, 0x7300, 0xc3dd, 0x7302, 0x6807, 0x0002, 0x2f18, 0x6b26, - 0x682b, 0x0000, 0x781f, 0x0003, 0x7803, 0x0001, 0x7807, 0x0040, - 0x0f7f, 0x0e7f, 0x0c7f, 0x0d7f, 0x007c, 0x037f, 0x0e7f, 0x0c7f, - 0x0078, 0x6383, 0x0d7f, 0x007c, 0x0c7e, 0x680c, 0xa065, 0x0040, - 0x6398, 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, 0x1078, 0x63d4, - 0x0c7f, 0x0d7f, 0x007c, 0x0f7e, 0x0d7e, 0x2069, 0xa9b1, 0x6830, - 0xa086, 0x0000, 0x00c0, 0x63bb, 0x6838, 0xa07d, 0x0040, 0x63bb, - 0x6833, 0x0001, 0x683e, 0x6847, 0x0000, 0x684b, 0x0000, 0x127e, - 0x0f7e, 0x2091, 0x2200, 0x027f, 0x1078, 0x1d6d, 0x00c0, 0x63be, - 0x127f, 0x1078, 0x6cb3, 0x0d7f, 0x0f7f, 0x007c, 0x127f, 0x6843, - 0x0000, 0x7803, 0x0002, 0x780c, 0xa015, 0x0040, 0x63d0, 0x6a3a, - 0x780f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, 0x0078, 0x63bb, - 0x683a, 0x6836, 0x0078, 0x63ca, 0x601c, 0xa084, 0x000f, 0x1079, - 0x63da, 0x007c, 0x63e3, 0x63e8, 0x6809, 0x6922, 0x63e8, 0x6809, - 0x6922, 0x63e3, 0x63e8, 0x1078, 0x61cd, 0x1078, 0x62d1, 0x007c, - 0x157e, 0x137e, 0x147e, 0x0c7e, 0x0f7e, 0x6004, 0xa08a, 0x0044, - 0x10c8, 0x1332, 0x6118, 0x2178, 0x79a0, 0xd1bc, 0x0040, 0x6405, - 0x7900, 0xd1f4, 0x0040, 0x6401, 0x7914, 0xa18c, 0x00ff, 0x0078, - 0x640a, 0x2009, 0x0000, 0x0078, 0x640a, 0xa1f8, 0x29c0, 0x2f0c, - 0xa18c, 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, 0xa08a, 0x0040, - 0x00c8, 0x645c, 0x1079, 0x641a, 0x0f7f, 0x0c7f, 0x147f, 0x137f, - 0x157f, 0x007c, 0x64c2, 0x650a, 0x6532, 0x65cd, 0x65fd, 0x6605, - 0x662c, 0x663d, 0x664e, 0x6656, 0x666e, 0x6656, 0x66d9, 0x663d, - 0x66fa, 0x6702, 0x664e, 0x6702, 0x6713, 0x645a, 0x645a, 0x645a, - 0x645a, 0x645a, 0x645a, 0x645a, 0x645a, 0x645a, 0x645a, 0x645a, - 0x6eef, 0x6f14, 0x6f29, 0x6f4c, 0x6f6d, 0x662c, 0x645a, 0x662c, - 0x6656, 0x645a, 0x6532, 0x65cd, 0x645a, 0x749c, 0x6656, 0x645a, - 0x74bc, 0x6656, 0x645a, 0x645a, 0x64bd, 0x646b, 0x645a, 0x74e1, - 0x7558, 0x7640, 0x645a, 0x7651, 0x6626, 0x766d, 0x645a, 0x6f82, - 0x645a, 0x645a, 0x1078, 0x1332, 0x2100, 0x1079, 0x6465, 0x0f7f, - 0x0c7f, 0x147f, 0x137f, 0x157f, 0x007c, 0x6469, 0x6469, 0x6469, - 0x649f, 0x1078, 0x1332, 0x0d7e, 0x20a1, 0x020b, 0x1078, 0x6731, - 0x7810, 0x2068, 0x20a3, 0x2414, 0x20a3, 0x0018, 0x20a3, 0x0800, - 0x683c, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x20a3, 0x0000, 0x6850, 0x20a2, 0x6854, 0x20a2, 0x20a3, 0x0000, - 0x20a3, 0x0000, 0x60c3, 0x0018, 0x1078, 0x6dfb, 0x0d7f, 0x007c, - 0x0d7e, 0x7818, 0x2068, 0x68a0, 0xa082, 0x007e, 0x0048, 0x649c, - 0xa085, 0x0001, 0x0d7f, 0x007c, 0xa006, 0x0078, 0x649a, 0x0d7e, - 0x20a1, 0x020b, 0x1078, 0x6731, 0x20a3, 0x0500, 0x20a3, 0x0000, - 0x7810, 0xa0e8, 0x000f, 0x6808, 0x20a2, 0x680c, 0x20a2, 0x6810, - 0x20a2, 0x6814, 0x20a2, 0x6818, 0x20a2, 0x681c, 0x20a2, 0x60c3, - 0x0010, 0x1078, 0x6dfb, 0x0d7f, 0x007c, 0x6030, 0x609a, 0x1078, - 0x6dfb, 0x007c, 0x20a1, 0x020b, 0x1078, 0x6731, 0x20a3, 0x5200, - 0x20a3, 0x0000, 0x0d7e, 0x2069, 0xa752, 0x6804, 0xd084, 0x0040, - 0x64dc, 0x6828, 0x20a3, 0x0000, 0x017e, 0x1078, 0x2564, 0x21a2, - 0x017f, 0x0d7f, 0x0078, 0x64e1, 0x0d7f, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x20a9, 0x0004, 0x2099, 0xa705, 0x53a6, 0x20a9, 0x0004, - 0x2099, 0xa701, 0x53a6, 0x7818, 0xa080, 0x0028, 0x2004, 0xa082, - 0x007f, 0x0048, 0x64fb, 0x2001, 0xa71b, 0x20a6, 0x2001, 0xa71c, - 0x20a6, 0x0078, 0x6501, 0x20a3, 0x0000, 0x6030, 0xa084, 0x00ff, - 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x001c, 0x1078, - 0x6dfb, 0x007c, 0x20a1, 0x020b, 0x1078, 0x6731, 0x20a3, 0x0500, - 0x20a3, 0x0000, 0x7818, 0xa080, 0x0028, 0x2004, 0xa082, 0x007f, - 0x0048, 0x6522, 0x2001, 0xa71b, 0x20a6, 0x2001, 0xa71c, 0x20a6, - 0x0078, 0x6528, 0x20a3, 0x0000, 0x6030, 0xa084, 0x00ff, 0x20a2, - 0x20a9, 0x0004, 0x2099, 0xa705, 0x53a6, 0x60c3, 0x0010, 0x1078, - 0x6dfb, 0x007c, 0x20a1, 0x020b, 0x1078, 0x6731, 0x0c7e, 0x7818, - 0x2060, 0x2001, 0x0000, 0x1078, 0x4972, 0x0c7f, 0x7818, 0xa080, - 0x0028, 0x2004, 0xa086, 0x007e, 0x00c0, 0x654d, 0x20a3, 0x0400, - 0x620c, 0xc2b4, 0x620e, 0x0078, 0x654f, 0x20a3, 0x0300, 0x20a3, - 0x0000, 0x7818, 0xa080, 0x0028, 0x2004, 0xa086, 0x007e, 0x00c0, - 0x659c, 0x2099, 0xa98d, 0x33a6, 0x9398, 0x33a6, 0x9398, 0x3304, - 0xa084, 0x3fff, 0x20a2, 0x9398, 0x33a6, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a9, 0x0004, 0x2099, - 0xa705, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xa701, 0x53a6, 0x20a9, - 0x0010, 0x20a3, 0x0000, 0x00f0, 0x6579, 0x2099, 0xa995, 0x3304, - 0xc0dd, 0x20a2, 0x2001, 0xa772, 0x2004, 0xd0e4, 0x0040, 0x6594, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x9398, 0x9398, 0x9398, 0x33a6, - 0x20a9, 0x0004, 0x0078, 0x6596, 0x20a9, 0x0007, 0x20a3, 0x0000, - 0x00f0, 0x6596, 0x0078, 0x65bc, 0x2099, 0xa98d, 0x20a9, 0x0008, - 0x53a6, 0x20a9, 0x0004, 0x2099, 0xa705, 0x53a6, 0x20a9, 0x0004, - 0x2099, 0xa701, 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x00f0, - 0x65ad, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x00f0, 0x65b3, 0x2099, - 0xa995, 0x20a9, 0x0008, 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, - 0x00f0, 0x65be, 0x20a9, 0x000a, 0x20a3, 0x0000, 0x00f0, 0x65c4, - 0x60c3, 0x0074, 0x1078, 0x6dfb, 0x007c, 0x20a1, 0x020b, 0x1078, - 0x6731, 0x20a3, 0x2010, 0x20a3, 0x0014, 0x20a3, 0x0800, 0x20a3, - 0x2000, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x0f7e, - 0x2079, 0xa752, 0x7904, 0x0f7f, 0xd1ac, 0x00c0, 0x65e9, 0xa085, - 0x0020, 0xd1a4, 0x0040, 0x65ee, 0xa085, 0x0010, 0xa085, 0x0002, - 0x0d7e, 0x0078, 0x66b7, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x60c3, 0x0014, 0x1078, 0x6dfb, 0x007c, 0x20a1, 0x020b, 0x1078, - 0x6731, 0x20a3, 0x5000, 0x0078, 0x654f, 0x20a1, 0x020b, 0x1078, - 0x6731, 0x20a3, 0x2110, 0x20a3, 0x0014, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x60c3, 0x0014, 0x1078, 0x6dfb, 0x007c, 0x20a1, 0x020b, - 0x1078, 0x67b9, 0x0078, 0x6630, 0x20a1, 0x020b, 0x1078, 0x67c2, - 0x20a3, 0x0200, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x60c3, 0x0004, 0x1078, 0x6dfb, 0x007c, 0x20a1, 0x020b, 0x1078, - 0x67c2, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003, 0x20a3, - 0x2a00, 0x60c3, 0x0008, 0x1078, 0x6dfb, 0x007c, 0x20a1, 0x020b, - 0x1078, 0x67c2, 0x20a3, 0x0200, 0x0078, 0x654f, 0x20a1, 0x020b, - 0x1078, 0x67c2, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x7828, 0xa005, - 0x0040, 0x6665, 0x20a2, 0x0078, 0x6667, 0x20a3, 0x0003, 0x7810, - 0x20a2, 0x60c3, 0x0008, 0x1078, 0x6dfb, 0x007c, 0x0d7e, 0x20a1, - 0x020b, 0x1078, 0x67c2, 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3, - 0x0800, 0x7818, 0x2068, 0x6894, 0xa086, 0x0014, 0x00c0, 0x6694, - 0x6998, 0xa184, 0xc000, 0x00c0, 0x6690, 0xd1ec, 0x0040, 0x668c, - 0x20a3, 0x2100, 0x0078, 0x6696, 0x20a3, 0x0100, 0x0078, 0x6696, - 0x20a3, 0x0400, 0x0078, 0x6696, 0x20a3, 0x0700, 0xa006, 0x20a2, - 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x0f7e, 0x2079, 0xa752, 0x7904, - 0x0f7f, 0xd1ac, 0x00c0, 0x66a6, 0xa085, 0x0020, 0xd1a4, 0x0040, - 0x66ab, 0xa085, 0x0010, 0x2009, 0xa774, 0x210c, 0xd184, 0x0040, - 0x66b5, 0x699c, 0xd18c, 0x0040, 0x66b7, 0xa085, 0x0002, 0x027e, - 0x2009, 0xa772, 0x210c, 0xd1e4, 0x0040, 0x66c5, 0xc0c5, 0xa094, - 0x0030, 0xa296, 0x0010, 0x0040, 0x66cf, 0xd1ec, 0x0040, 0x66cf, - 0xa094, 0x0030, 0xa296, 0x0010, 0x0040, 0x66cf, 0xc0bd, 0x027f, - 0x20a2, 0x20a2, 0x20a2, 0x60c3, 0x0014, 0x1078, 0x6dfb, 0x0d7f, - 0x007c, 0x20a1, 0x020b, 0x1078, 0x67c2, 0x20a3, 0x0210, 0x20a3, - 0x0014, 0x20a3, 0x0000, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, - 0x6dfb, 0x007c, 0x20a1, 0x020b, 0x1078, 0x67c2, 0x20a3, 0x0200, - 0x0078, 0x64c8, 0x20a1, 0x020b, 0x1078, 0x67c2, 0x20a3, 0x0100, - 0x20a3, 0x0000, 0x20a3, 0x0003, 0x20a3, 0x2a00, 0x60c3, 0x0008, - 0x1078, 0x6dfb, 0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a1, - 0x020b, 0x1078, 0x67c2, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, - 0x000b, 0x20a3, 0x0000, 0x60c3, 0x0008, 0x1078, 0x6dfb, 0x007c, - 0x027e, 0x037e, 0x047e, 0x2019, 0x3200, 0x2021, 0x0800, 0x0078, - 0x6738, 0x027e, 0x037e, 0x047e, 0x2019, 0x2200, 0x2021, 0x0100, - 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2014, - 0xa286, 0x007e, 0x00c0, 0x674b, 0xa385, 0x00ff, 0x20a2, 0x20a3, - 0xfffe, 0x0078, 0x6780, 0xa286, 0x007f, 0x00c0, 0x6757, 0x0d7e, - 0xa385, 0x00ff, 0x20a2, 0x20a3, 0xfffd, 0x0078, 0x676e, 0xd2bc, - 0x0040, 0x6776, 0xa286, 0x0080, 0x0d7e, 0x00c0, 0x6766, 0xa385, - 0x00ff, 0x20a2, 0x20a3, 0xfffc, 0x0078, 0x676e, 0xa2e8, 0xa835, - 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa71b, - 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x6784, 0x0d7e, 0xa2e8, - 0xa835, 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x0d7f, - 0x20a3, 0x0000, 0x6230, 0x22a2, 0xa485, 0x0029, 0x20a2, 0x047f, - 0x037f, 0x20a3, 0x0000, 0x1078, 0x6dea, 0x22a2, 0x20a3, 0x0000, - 0x2fa2, 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f, - 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a3, 0x02ff, - 0x2011, 0xfffc, 0x22a2, 0x0d7e, 0x2069, 0xa71b, 0x2da6, 0x8d68, - 0x2da6, 0x0d7f, 0x20a3, 0x2029, 0x20a3, 0x0000, 0x0078, 0x678b, - 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0xfc02, 0x20a3, 0x0000, - 0x007c, 0x027e, 0x037e, 0x047e, 0x2019, 0x3300, 0x2021, 0x0800, - 0x0078, 0x67c9, 0x027e, 0x037e, 0x047e, 0x2019, 0x2300, 0x2021, - 0x0100, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, - 0x2004, 0xa092, 0x007e, 0x0048, 0x67e6, 0x0d7e, 0xa0e8, 0xa835, - 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa71b, - 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x67f4, 0x0d7e, 0xa0e8, - 0xa835, 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x0d7f, - 0x20a3, 0x0000, 0x6230, 0x22a2, 0xa485, 0x0098, 0x20a2, 0x20a3, - 0x0000, 0x047f, 0x037f, 0x1078, 0x6dea, 0x22a2, 0x20a3, 0x0000, - 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f, - 0x007c, 0x0c7e, 0x0f7e, 0x6004, 0xa08a, 0x0085, 0x1048, 0x1332, - 0xa08a, 0x008c, 0x10c8, 0x1332, 0x6118, 0x2178, 0x79a0, 0xd1bc, - 0x0040, 0x6827, 0x7900, 0xd1f4, 0x0040, 0x6823, 0x7914, 0xa18c, - 0x00ff, 0x0078, 0x682c, 0x2009, 0x0000, 0x0078, 0x682c, 0xa1f8, - 0x29c0, 0x2f0c, 0xa18c, 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, - 0xa082, 0x0085, 0x1079, 0x6837, 0x0f7f, 0x0c7f, 0x007c, 0x6840, - 0x684b, 0x6866, 0x683e, 0x683e, 0x683e, 0x6840, 0x1078, 0x1332, - 0x147e, 0x20a1, 0x020b, 0x1078, 0x6879, 0x60c3, 0x0000, 0x1078, - 0x6dfb, 0x147f, 0x007c, 0x147e, 0x20a1, 0x020b, 0x1078, 0x68ad, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2, 0x7810, 0x20a2, - 0x20a3, 0x0000, 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x60c3, 0x000c, 0x1078, 0x6dfb, 0x147f, 0x007c, 0x147e, 0x20a1, - 0x020b, 0x1078, 0x68ee, 0x20a3, 0x0003, 0x20a3, 0x0300, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0004, 0x1078, 0x6dfb, 0x147f, - 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, - 0x0028, 0x2004, 0xa092, 0x007e, 0x0048, 0x6898, 0x0d7e, 0xa0e8, - 0xa835, 0x2d6c, 0x6810, 0xa085, 0x8100, 0x20a2, 0x6814, 0x20a2, - 0x2069, 0xa71b, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x68a7, - 0x0d7e, 0xa0e8, 0xa835, 0x2d6c, 0x6810, 0xa085, 0x8100, 0x20a2, - 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, - 0x0009, 0x20a3, 0x0000, 0x0078, 0x678b, 0x027e, 0x20e1, 0x9080, - 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0xa092, 0x007e, - 0x0048, 0x68cc, 0x0d7e, 0xa0e8, 0xa835, 0x2d6c, 0x6810, 0xa085, - 0x8400, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa71b, 0x2da6, 0x8d68, - 0x2da6, 0x0d7f, 0x0078, 0x68db, 0x0d7e, 0xa0e8, 0xa835, 0x2d6c, - 0x6810, 0xa085, 0x8400, 0x20a2, 0x6814, 0x20a2, 0x0d7f, 0x20a3, - 0x0000, 0x6230, 0x22a2, 0x20a3, 0x0099, 0x20a3, 0x0000, 0x1078, - 0x6dea, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x7a10, 0x22a2, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f, 0x007c, 0x027e, 0x20e1, - 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0xa092, - 0x007e, 0x0048, 0x690d, 0x0d7e, 0xa0e8, 0xa835, 0x2d6c, 0x6810, - 0xa085, 0x8500, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa71b, 0x2da6, - 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x691c, 0x0d7e, 0xa0e8, 0xa835, - 0x2d6c, 0x6810, 0xa085, 0x8500, 0x20a2, 0x6814, 0x20a2, 0x0d7f, - 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, 0x0099, 0x20a3, 0x0000, - 0x0078, 0x68df, 0x0c7e, 0x0f7e, 0x2c78, 0x7804, 0xa08a, 0x0040, - 0x1048, 0x1332, 0xa08a, 0x0053, 0x10c8, 0x1332, 0x7918, 0x2160, - 0x61a0, 0xd1bc, 0x0040, 0x6941, 0x6100, 0xd1f4, 0x0040, 0x693d, - 0x6114, 0xa18c, 0x00ff, 0x0078, 0x6946, 0x2009, 0x0000, 0x0078, - 0x6946, 0xa1e0, 0x29c0, 0x2c0c, 0xa18c, 0x00ff, 0x2061, 0x0100, - 0x619a, 0xa082, 0x0040, 0x1079, 0x6950, 0x0f7f, 0x0c7f, 0x007c, - 0x6965, 0x6a73, 0x6a14, 0x6c27, 0x6963, 0x6963, 0x6963, 0x6963, - 0x6963, 0x6963, 0x6963, 0x714c, 0x715d, 0x716e, 0x717f, 0x6963, - 0x767e, 0x6963, 0x713b, 0x1078, 0x1332, 0x0d7e, 0x157e, 0x147e, - 0x780b, 0xffff, 0x20a1, 0x020b, 0x1078, 0x69d0, 0x7910, 0x2168, - 0x6948, 0x7922, 0x21a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x694c, - 0xa184, 0x000f, 0x00c0, 0x6980, 0x2001, 0x0005, 0x0078, 0x698a, - 0xd184, 0x0040, 0x6987, 0x2001, 0x0004, 0x0078, 0x698a, 0xa084, - 0x0006, 0x8004, 0x017e, 0x2008, 0x7830, 0xa084, 0x00ff, 0x8007, - 0xa105, 0x017f, 0x20a2, 0xd1ac, 0x0040, 0x699a, 0x20a3, 0x0002, - 0x0078, 0x69a6, 0xd1b4, 0x0040, 0x69a1, 0x20a3, 0x0001, 0x0078, - 0x69a6, 0x20a3, 0x0000, 0x2230, 0x0078, 0x69a8, 0x6a80, 0x6e7c, - 0x20a9, 0x0008, 0xad80, 0x0017, 0x200c, 0x810f, 0x21a2, 0x8000, - 0x00f0, 0x69ac, 0x22a2, 0x26a2, 0x60c3, 0x0020, 0x20e1, 0x9080, - 0x6014, 0xa084, 0x0004, 0xa085, 0x0009, 0x6016, 0x2001, 0xa9cd, - 0x2003, 0x07d0, 0x2001, 0xa9cc, 0x2003, 0x0009, 0x2001, 0xa9d2, - 0x2003, 0x0002, 0x1078, 0x158c, 0x147f, 0x157f, 0x0d7f, 0x007c, - 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7a18, 0xa280, 0x0023, 0x2014, - 0x8210, 0xa294, 0x00ff, 0x2202, 0x8217, 0x7818, 0xa080, 0x0028, - 0x2004, 0xd0bc, 0x0040, 0x69f6, 0x0d7e, 0xa0e8, 0xa835, 0x2d6c, - 0x6810, 0xa085, 0x0600, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa71b, - 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x6a05, 0x0d7e, 0xa0e8, - 0xa835, 0x2d6c, 0x6810, 0xa085, 0x0600, 0x20a2, 0x6814, 0x20a2, - 0x0d7f, 0x20a3, 0x0000, 0x6130, 0x21a2, 0x20a3, 0x0829, 0x20a3, - 0x0000, 0x22a2, 0x20a3, 0x0000, 0x2fa2, 0x20a3, 0xffff, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x007c, 0x0d7e, 0x157e, 0x137e, 0x147e, - 0x20a1, 0x020b, 0x1078, 0x6a34, 0x7810, 0x2068, 0x6860, 0x20a2, - 0x685c, 0x20a2, 0x6880, 0x20a2, 0x687c, 0x20a2, 0xa006, 0x20a2, - 0x20a2, 0x20a2, 0x20a2, 0x60c3, 0x000c, 0x1078, 0x6dfb, 0x147f, - 0x137f, 0x157f, 0x0d7f, 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1, - 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040, 0x6a52, - 0x0d7e, 0xa0e8, 0xa835, 0x2d6c, 0x6810, 0xa085, 0x0500, 0x20a2, - 0x6814, 0x20a2, 0x2069, 0xa71b, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, - 0x0078, 0x6a61, 0x0d7e, 0xa0e8, 0xa835, 0x2d6c, 0x6810, 0xa085, - 0x0500, 0x20a2, 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000, 0x6230, - 0x22a2, 0x20a3, 0x0889, 0x20a3, 0x0000, 0x1078, 0x6dea, 0x22a2, - 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x027f, 0x007c, 0x0d7e, 0x157e, 0x137e, 0x147e, 0x7810, - 0xa0ec, 0xf000, 0x0040, 0x6a8b, 0xa06d, 0x1078, 0x495f, 0x0040, - 0x6a8b, 0x684c, 0xa084, 0x2020, 0xa086, 0x2020, 0x00c0, 0x6a8b, - 0x7824, 0xc0cd, 0x7826, 0x20a1, 0x020b, 0x1078, 0x6be0, 0xa016, - 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x7810, 0xa084, 0xf000, - 0x00c0, 0x6aa2, 0x7810, 0xa084, 0x0700, 0x8007, 0x1079, 0x6aaa, - 0x0078, 0x6aa5, 0xa006, 0x1079, 0x6aaa, 0x147f, 0x137f, 0x157f, - 0x0d7f, 0x007c, 0x6ab4, 0x6b4c, 0x6b57, 0x6b81, 0x6b95, 0x6bb1, - 0x6bbc, 0x6ab2, 0x1078, 0x1332, 0x017e, 0x037e, 0x694c, 0xa18c, - 0x0003, 0x0040, 0x6abf, 0xa186, 0x0003, 0x00c0, 0x6ace, 0x6b78, - 0x7824, 0xd0cc, 0x0040, 0x6ac5, 0xc3e5, 0x23a2, 0x6868, 0x20a2, - 0x6864, 0x20a2, 0x037f, 0x017f, 0x0078, 0x6b8c, 0xa186, 0x0001, - 0x10c0, 0x1332, 0x6b78, 0x7824, 0xd0cc, 0x0040, 0x6ad8, 0xc3e5, - 0x23a2, 0x6868, 0x20a2, 0x6864, 0x20a2, 0x22a2, 0x6874, 0x20a2, - 0x22a2, 0x687c, 0x20a2, 0x2009, 0x0018, 0xa384, 0x0300, 0x0040, - 0x6b46, 0xd3c4, 0x0040, 0x6aee, 0x687c, 0xa108, 0xd3cc, 0x0040, - 0x6af3, 0x6874, 0xa108, 0x157e, 0x20a9, 0x000d, 0xad80, 0x0020, - 0x201c, 0x831f, 0x23a2, 0x8000, 0x00f0, 0x6af8, 0x157f, 0x22a2, - 0x22a2, 0x22a2, 0xa184, 0x0003, 0x0040, 0x6b46, 0x20a1, 0x020b, - 0x20e1, 0x9080, 0x20e1, 0x4000, 0x007e, 0x7818, 0xa080, 0x0028, - 0x2004, 0xd0bc, 0x0040, 0x6b26, 0x0d7e, 0xa0e8, 0xa835, 0x2d6c, - 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa71b, - 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x6b35, 0x0d7e, 0xa0e8, - 0xa835, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, - 0x0d7f, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x007f, 0x7b24, 0xd3cc, - 0x0040, 0x6b3e, 0x20a3, 0x0889, 0x0078, 0x6b40, 0x20a3, 0x0898, - 0x20a2, 0x1078, 0x6dea, 0x22a2, 0x20a3, 0x0000, 0x61c2, 0x037f, - 0x017f, 0x1078, 0x6dfb, 0x007c, 0x2011, 0x0008, 0x7824, 0xd0cc, - 0x0040, 0x6b53, 0xc2e5, 0x22a2, 0xa016, 0x0078, 0x6b8a, 0x2011, - 0x0302, 0x7824, 0xd0cc, 0x0040, 0x6b5e, 0xc2e5, 0x22a2, 0xa016, - 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x0012, 0x22a2, 0x20a3, 0x0008, - 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x7000, 0x20a3, 0x0500, - 0x22a2, 0x20a3, 0x000a, 0x22a2, 0x22a2, 0x20a3, 0x2500, 0x22a2, - 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0032, 0x1078, 0x6dfb, - 0x007c, 0x2011, 0x0028, 0x7824, 0xd0cc, 0x0040, 0x6b88, 0xc2e5, - 0x22a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, - 0x60c3, 0x0018, 0x1078, 0x6dfb, 0x007c, 0x2011, 0x0100, 0x7824, - 0xd0cc, 0x0040, 0x6b9c, 0xc2e5, 0x22a2, 0xa016, 0x22a2, 0x22a2, - 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x0008, 0x22a2, 0x7834, 0xa084, - 0x00ff, 0x20a2, 0x22a2, 0x22a2, 0x60c3, 0x0020, 0x1078, 0x6dfb, - 0x007c, 0x2011, 0x0008, 0x7824, 0xd0cc, 0x0040, 0x6bb8, 0xc2e5, - 0x22a2, 0xa016, 0x0078, 0x6b8a, 0x037e, 0x7b10, 0xa384, 0xff00, - 0x7812, 0xa384, 0x00ff, 0x8001, 0x00c0, 0x6bcf, 0x7824, 0xd0cc, - 0x0040, 0x6bcb, 0xc2e5, 0x22a2, 0x037f, 0x0078, 0x6b8a, 0x047e, - 0x2021, 0x0800, 0x007e, 0x7824, 0xd0cc, 0x007f, 0x0040, 0x6bd9, - 0xc4e5, 0x24a2, 0x047f, 0x22a2, 0x20a2, 0x037f, 0x0078, 0x6b8c, - 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, - 0x2004, 0xd0bc, 0x0040, 0x6bfe, 0x0d7e, 0xa0e8, 0xa835, 0x2d6c, - 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa71b, - 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x6c0d, 0x0d7e, 0xa0e8, - 0xa835, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, - 0x0d7f, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x7824, 0xd0cc, 0x0040, - 0x6c15, 0x20a3, 0x0889, 0x0078, 0x6c17, 0x20a3, 0x0898, 0x20a3, - 0x0000, 0x1078, 0x6dea, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, - 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f, 0x007c, 0x0d7e, - 0x157e, 0x137e, 0x147e, 0x017e, 0x037e, 0x7810, 0xa084, 0x0700, - 0x8007, 0x1079, 0x6c3a, 0x037f, 0x017f, 0x147f, 0x137f, 0x157f, - 0x0d7f, 0x007c, 0x6c42, 0x6c42, 0x6c44, 0x6c42, 0x6c42, 0x6c42, - 0x6c69, 0x6c42, 0x1078, 0x1332, 0x7910, 0xa18c, 0xf8ff, 0xa18d, - 0x0600, 0x7912, 0x20a1, 0x020b, 0x2009, 0x0003, 0x1078, 0x6c73, - 0x0d7e, 0x2069, 0xa752, 0x6804, 0xd0bc, 0x0040, 0x6c5e, 0x682c, - 0xa084, 0x00ff, 0x8007, 0x20a2, 0x0078, 0x6c60, 0x20a3, 0x3f00, - 0x0d7f, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0001, 0x1078, 0x6dfb, - 0x007c, 0x20a1, 0x020b, 0x2009, 0x0003, 0x1078, 0x6c73, 0x20a3, - 0x7f00, 0x0078, 0x6c61, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, - 0x7818, 0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040, 0x6c91, 0x0d7e, - 0xa0e8, 0xa835, 0x2d6c, 0x6810, 0xa085, 0x0100, 0x20a2, 0x6814, - 0x20a2, 0x2069, 0xa71b, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, - 0x6ca0, 0x0d7e, 0xa0e8, 0xa835, 0x2d6c, 0x6810, 0xa085, 0x0100, - 0x20a2, 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000, 0x6230, 0x22a2, - 0x20a3, 0x0888, 0xa18d, 0x0008, 0x21a2, 0x1078, 0x6dea, 0x22a2, - 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x027f, 0x007c, 0x0e7e, 0x0d7e, 0x0c7e, 0x057e, 0x047e, - 0x037e, 0x2061, 0x0100, 0x2071, 0xa700, 0x6130, 0x7818, 0x2068, - 0x68a0, 0x2028, 0xd0bc, 0x00c0, 0x6cca, 0x6910, 0x6a14, 0x6430, - 0x0078, 0x6cce, 0x6910, 0x6a14, 0x736c, 0x7470, 0x781c, 0xa086, - 0x0006, 0x0040, 0x6d2d, 0xd5bc, 0x0040, 0x6cde, 0xa185, 0x0100, - 0x6062, 0x6266, 0x636a, 0x646e, 0x0078, 0x6ce5, 0xa185, 0x0100, - 0x6062, 0x6266, 0x606b, 0x0000, 0x646e, 0x6073, 0x0809, 0x6077, - 0x0008, 0x688c, 0x8000, 0xa084, 0x00ff, 0x688e, 0x8007, 0x607a, - 0x607f, 0x0000, 0x2f00, 0x6082, 0x7808, 0x6086, 0x7810, 0x2070, - 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6, 0x7008, 0x60ca, - 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5, 0x60d7, 0x0000, - 0xa582, 0x0080, 0x0048, 0x6d17, 0x6a00, 0xd2f4, 0x0040, 0x6d15, - 0x6a14, 0xa294, 0x00ff, 0x0078, 0x6d17, 0x2011, 0x0000, 0x629e, - 0x6017, 0x0016, 0x2009, 0x07d0, 0x60c4, 0xa084, 0xfff0, 0xa005, - 0x0040, 0x6d24, 0x2009, 0x1b58, 0x1078, 0x5ad0, 0x037f, 0x047f, - 0x057f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, 0x7810, 0x2070, 0x704c, - 0xa084, 0x0003, 0xa086, 0x0002, 0x0040, 0x6d85, 0xd5bc, 0x0040, - 0x6d41, 0xa185, 0x0100, 0x6062, 0x6266, 0x636a, 0x646e, 0x0078, - 0x6d48, 0xa185, 0x0100, 0x6062, 0x6266, 0x606b, 0x0000, 0x646e, - 0x6073, 0x0880, 0x6077, 0x0008, 0x688c, 0x8000, 0xa084, 0x00ff, - 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6086, 0x7808, - 0x6082, 0x7060, 0x608a, 0x705c, 0x608e, 0x7080, 0x60c6, 0x707c, - 0x60ca, 0x707c, 0x792c, 0xa108, 0x792e, 0x7080, 0x7928, 0xa109, - 0x792a, 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5, 0x60d7, - 0x0000, 0xa582, 0x0080, 0x0048, 0x6d80, 0x6a00, 0xd2f4, 0x0040, - 0x6d7e, 0x6a14, 0xa294, 0x00ff, 0x0078, 0x6d80, 0x2011, 0x0000, - 0x629e, 0x6017, 0x0012, 0x0078, 0x6d1a, 0xd5bc, 0x0040, 0x6d90, - 0xa185, 0x0700, 0x6062, 0x6266, 0x636a, 0x646e, 0x0078, 0x6d97, - 0xa185, 0x0700, 0x6062, 0x6266, 0x606b, 0x0000, 0x646e, 0x1078, - 0x495f, 0x0040, 0x6dad, 0x0d7e, 0x7810, 0xa06d, 0x684c, 0x0d7f, - 0xa084, 0x2020, 0xa086, 0x2020, 0x00c0, 0x6dad, 0x7824, 0xc0cd, - 0x7826, 0x6073, 0x0889, 0x0078, 0x6daf, 0x6073, 0x0898, 0x6077, - 0x0000, 0x688c, 0x8000, 0xa084, 0x00ff, 0x688e, 0x8007, 0x607a, - 0x607f, 0x0000, 0x2f00, 0x6086, 0x7808, 0x6082, 0x7014, 0x608a, - 0x7010, 0x608e, 0x700c, 0x60c6, 0x7008, 0x60ca, 0x686c, 0x60ce, - 0x60ab, 0x0036, 0x60af, 0x95d5, 0x60d7, 0x0000, 0xa582, 0x0080, - 0x0048, 0x6ddd, 0x6a00, 0xd2f4, 0x0040, 0x6ddb, 0x6a14, 0xa294, - 0x00ff, 0x0078, 0x6ddd, 0x2011, 0x0000, 0x629e, 0x7824, 0xd0cc, - 0x0040, 0x6de6, 0x6017, 0x0016, 0x0078, 0x6d1a, 0x6017, 0x0012, - 0x0078, 0x6d1a, 0x7a18, 0xa280, 0x0023, 0x2014, 0x8210, 0xa294, - 0x00ff, 0x2202, 0x8217, 0x007c, 0x0d7e, 0x2069, 0xa9b1, 0x6843, - 0x0001, 0x0d7f, 0x007c, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, - 0x9575, 0x1078, 0x6e06, 0x1078, 0x5ac0, 0x007c, 0x007e, 0x6014, - 0xa084, 0x0004, 0xa085, 0x0009, 0x6016, 0x007f, 0x007c, 0x007e, - 0x0c7e, 0x2061, 0x0100, 0x6014, 0xa084, 0x0004, 0xa085, 0x0008, - 0x6016, 0x0c7f, 0x007f, 0x007c, 0x0c7e, 0x0d7e, 0x017e, 0x027e, - 0x2061, 0x0100, 0x2069, 0x0140, 0x6904, 0xa194, 0x4000, 0x0040, - 0x6e59, 0x1078, 0x6e0f, 0x6803, 0x1000, 0x6803, 0x0000, 0x0c7e, - 0x2061, 0xa9b1, 0x6128, 0xa192, 0x00c8, 0x00c8, 0x6e44, 0x8108, - 0x612a, 0x6124, 0x0c7f, 0x81ff, 0x0040, 0x6e54, 0x1078, 0x5ac0, - 0x1078, 0x6e06, 0x0078, 0x6e54, 0x6124, 0xa1e5, 0x0000, 0x0040, - 0x6e51, 0x1078, 0xa5d4, 0x1078, 0x5acb, 0x2009, 0x0014, 0x1078, - 0x775c, 0x0c7f, 0x0078, 0x6e54, 0x027f, 0x017f, 0x0d7f, 0x0c7f, - 0x007c, 0x2001, 0xa9cd, 0x2004, 0xa005, 0x00c0, 0x6e54, 0x0c7e, - 0x2061, 0xa9b1, 0x6128, 0xa192, 0x0003, 0x00c8, 0x6e44, 0x8108, - 0x612a, 0x0c7f, 0x1078, 0x5ac0, 0x1078, 0x4224, 0x0078, 0x6e54, - 0x0c7e, 0x0d7e, 0x0e7e, 0x017e, 0x027e, 0x1078, 0x5ad8, 0x2071, - 0xa9b1, 0x713c, 0x81ff, 0x0040, 0x6e9a, 0x2061, 0x0100, 0x2069, - 0x0140, 0x6904, 0xa194, 0x4000, 0x0040, 0x6ea0, 0x6803, 0x1000, - 0x6803, 0x0000, 0x037e, 0x2019, 0x0001, 0x1078, 0x7058, 0x037f, - 0x713c, 0x2160, 0x1078, 0xa5d4, 0x2009, 0x004a, 0x1078, 0x775c, - 0x0078, 0x6e9a, 0x027f, 0x017f, 0x0e7f, 0x0d7f, 0x0c7f, 0x007c, - 0x0078, 0x6e8a, 0x0e7e, 0x2071, 0xa9b1, 0x7048, 0xd084, 0x0040, - 0x6ebc, 0x713c, 0x81ff, 0x0040, 0x6ebc, 0x2071, 0x0100, 0xa188, - 0x0007, 0x210c, 0xa18e, 0x0006, 0x00c0, 0x6eba, 0x7017, 0x0012, - 0x0078, 0x6ebc, 0x7017, 0x0016, 0x0e7f, 0x007c, 0x0e7e, 0x0d7e, - 0x0c7e, 0x067e, 0x057e, 0x047e, 0x007e, 0x127e, 0x2091, 0x8000, - 0x6018, 0x2068, 0x6ca0, 0x2071, 0xa9b1, 0x7018, 0x2068, 0x8dff, - 0x0040, 0x6ee6, 0x68a0, 0xa406, 0x0040, 0x6eda, 0x6854, 0x2068, - 0x0078, 0x6ecf, 0x6010, 0x2060, 0x643c, 0x6540, 0x6648, 0x2d60, - 0x1078, 0x4736, 0x0040, 0x6ee6, 0xa085, 0x0001, 0x127f, 0x007f, - 0x047f, 0x057f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, 0x20a1, - 0x020b, 0x1078, 0x6731, 0x20a3, 0x1200, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x781c, 0xa086, 0x0004, 0x00c0, 0x6f01, 0x6098, 0x0078, - 0x6f02, 0x6030, 0x20a2, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x20a9, - 0x0010, 0xa006, 0x20a2, 0x00f0, 0x6f0a, 0x20a2, 0x20a2, 0x60c3, - 0x002c, 0x1078, 0x6dfb, 0x007c, 0x157e, 0x147e, 0x20a1, 0x020b, - 0x1078, 0x6731, 0x20a3, 0x0f00, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x7808, 0x20a2, 0x60c3, 0x0008, 0x1078, 0x6dfb, 0x147f, 0x157f, - 0x007c, 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078, 0x67c2, 0x20a3, - 0x0200, 0x20a3, 0x0000, 0x20a9, 0x0006, 0x2011, 0xa740, 0x2019, - 0xa741, 0x23a6, 0x22a6, 0xa398, 0x0002, 0xa290, 0x0002, 0x00f0, - 0x6f39, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x001c, 0x1078, - 0x6dfb, 0x147f, 0x157f, 0x007c, 0x157e, 0x147e, 0x017e, 0x027e, - 0x20a1, 0x020b, 0x1078, 0x6799, 0x1078, 0x67b0, 0x7810, 0xa080, - 0x0000, 0x2004, 0xa080, 0x0015, 0x2098, 0x7808, 0xa088, 0x0002, - 0x21a8, 0x53a6, 0xa080, 0x0004, 0x8003, 0x60c2, 0x1078, 0x6dfb, - 0x027f, 0x017f, 0x147f, 0x157f, 0x007c, 0x157e, 0x147e, 0x20a1, - 0x020b, 0x1078, 0x6731, 0x20a3, 0x6200, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x7808, 0x20a2, 0x60c3, 0x0008, 0x1078, 0x6dfb, 0x147f, - 0x157f, 0x007c, 0x157e, 0x147e, 0x017e, 0x027e, 0x20a1, 0x020b, - 0x1078, 0x6731, 0x7810, 0xa080, 0x0000, 0x2004, 0xa080, 0x0017, - 0x2098, 0x7808, 0xa088, 0x0002, 0x21a8, 0x53a6, 0x8003, 0x60c2, - 0x1078, 0x6dfb, 0x027f, 0x017f, 0x147f, 0x157f, 0x007c, 0x0e7e, - 0x0c7e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071, 0xa9b1, 0x700c, - 0x2060, 0x8cff, 0x0040, 0x6fbb, 0x1078, 0x8f10, 0x00c0, 0x6fb2, - 0x1078, 0x7c83, 0x600c, 0x007e, 0x1078, 0x772d, 0x1078, 0x7233, - 0x0c7f, 0x0078, 0x6fa9, 0x700f, 0x0000, 0x700b, 0x0000, 0x127f, - 0x007f, 0x0c7f, 0x0e7f, 0x007c, 0x127e, 0x157e, 0x0f7e, 0x0e7e, - 0x0d7e, 0x0c7e, 0x027e, 0x017e, 0x007e, 0x2091, 0x8000, 0x2069, - 0x0100, 0x2079, 0x0140, 0x2071, 0xa9b1, 0x7024, 0x2060, 0x8cff, - 0x0040, 0x7014, 0x1078, 0x6e0f, 0x68c3, 0x0000, 0x1078, 0x5acb, - 0x2009, 0x0013, 0x1078, 0x775c, 0x20a9, 0x01f4, 0x6824, 0xd094, - 0x0040, 0x6ff7, 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x0040, - 0x7009, 0x7803, 0x1000, 0x7803, 0x0000, 0x0078, 0x7009, 0xd084, - 0x0040, 0x6ffe, 0x6827, 0x0001, 0x0078, 0x7000, 0x00f0, 0x6fe6, - 0x7804, 0xa084, 0x1000, 0x0040, 0x7009, 0x7803, 0x0100, 0x7803, - 0x0000, 0x6824, 0x007f, 0x017f, 0x027f, 0x0c7f, 0x0d7f, 0x0e7f, - 0x0f7f, 0x157f, 0x127f, 0x007c, 0x2001, 0xa700, 0x2004, 0xa096, - 0x0001, 0x0040, 0x704e, 0xa096, 0x0004, 0x0040, 0x704e, 0x1078, - 0x5acb, 0x6817, 0x0008, 0x68c3, 0x0000, 0x2011, 0x41dc, 0x1078, - 0x5a45, 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0040, 0x703c, 0x6827, - 0x0004, 0x7804, 0xa084, 0x4000, 0x0040, 0x704e, 0x7803, 0x1000, - 0x7803, 0x0000, 0x0078, 0x704e, 0xd084, 0x0040, 0x7043, 0x6827, - 0x0001, 0x0078, 0x7045, 0x00f0, 0x702b, 0x7804, 0xa084, 0x1000, - 0x0040, 0x704e, 0x7803, 0x0100, 0x7803, 0x0000, 0x007f, 0x017f, - 0x027f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x157f, 0x127f, 0x007c, - 0x127e, 0x157e, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x027e, 0x017e, - 0x007e, 0x2091, 0x8000, 0x2069, 0x0100, 0x2079, 0x0140, 0x2071, - 0xa9b1, 0x703c, 0x2060, 0x8cff, 0x0040, 0x70d6, 0x68af, 0x95f5, - 0x6817, 0x0010, 0x2009, 0x00fa, 0x8109, 0x00c0, 0x7074, 0x68c7, - 0x0000, 0x68cb, 0x0008, 0x1078, 0x5ad8, 0x1078, 0x1f7e, 0x047e, - 0x057e, 0x2009, 0x017f, 0x212c, 0x200b, 0x00a5, 0x2021, 0x0169, - 0x2404, 0xa084, 0x000f, 0xa086, 0x0004, 0x00c0, 0x70a5, 0x68c7, - 0x0000, 0x68cb, 0x0008, 0x0e7e, 0x0f7e, 0x2079, 0x0020, 0x2071, - 0xaa08, 0x6814, 0xa084, 0x0004, 0xa085, 0x0012, 0x6816, 0x7803, - 0x0008, 0x7003, 0x0000, 0x0f7f, 0x0e7f, 0x250a, 0x057f, 0x047f, - 0xa39d, 0x0000, 0x00c0, 0x70b0, 0x2009, 0x0049, 0x1078, 0x775c, - 0x20a9, 0x03e8, 0x6824, 0xd094, 0x0040, 0x70c3, 0x6827, 0x0004, - 0x7804, 0xa084, 0x4000, 0x0040, 0x70d5, 0x7803, 0x1000, 0x7803, - 0x0000, 0x0078, 0x70d5, 0xd08c, 0x0040, 0x70ca, 0x6827, 0x0002, - 0x0078, 0x70cc, 0x00f0, 0x70b2, 0x7804, 0xa084, 0x1000, 0x0040, - 0x70d5, 0x7803, 0x0100, 0x7803, 0x0000, 0x6824, 0x007f, 0x017f, - 0x027f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x157f, 0x127f, 0x007c, - 0x0d7e, 0x127e, 0x2091, 0x8000, 0x2069, 0xa9b1, 0x6a06, 0x127f, - 0x0d7f, 0x007c, 0x0d7e, 0x127e, 0x2091, 0x8000, 0x2069, 0xa9b1, - 0x6a32, 0x127f, 0x0d7f, 0x007c, 0x0f7e, 0x0e7e, 0x0c7e, 0x067e, - 0x007e, 0x127e, 0x2071, 0xa9b1, 0x7614, 0x2660, 0x2678, 0x2091, - 0x8000, 0x8cff, 0x0040, 0x7134, 0x601c, 0xa206, 0x00c0, 0x712f, - 0x7014, 0xac36, 0x00c0, 0x710e, 0x660c, 0x7616, 0x7010, 0xac36, - 0x00c0, 0x711c, 0x2c00, 0xaf36, 0x0040, 0x711a, 0x2f00, 0x7012, - 0x0078, 0x711c, 0x7013, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06, - 0x0040, 0x7125, 0x7e0e, 0x0078, 0x7126, 0x2678, 0x600f, 0x0000, - 0x1078, 0x8ed6, 0x1078, 0x7233, 0x0c7f, 0x0078, 0x7101, 0x2c78, - 0x600c, 0x2060, 0x0078, 0x7101, 0x127f, 0x007f, 0x067f, 0x0c7f, - 0x0e7f, 0x0f7f, 0x007c, 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078, - 0x69d0, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, - 0x20a3, 0x1000, 0x0078, 0x718e, 0x157e, 0x147e, 0x20a1, 0x020b, - 0x1078, 0x69d0, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, - 0x20a2, 0x20a3, 0x4000, 0x0078, 0x718e, 0x157e, 0x147e, 0x20a1, - 0x020b, 0x1078, 0x69d0, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2, - 0x20a2, 0x20a2, 0x20a3, 0x2000, 0x0078, 0x718e, 0x157e, 0x147e, - 0x20a1, 0x020b, 0x1078, 0x69d0, 0x7810, 0x20a2, 0xa006, 0x20a2, - 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0400, 0x0078, 0x718e, 0x157e, - 0x147e, 0x20a1, 0x020b, 0x1078, 0x69d0, 0x7810, 0x20a2, 0xa006, - 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0200, 0x1078, 0x723e, - 0x60c3, 0x0020, 0x1078, 0x6dfb, 0x147f, 0x157f, 0x007c, 0x127e, - 0x0c7e, 0x2091, 0x8000, 0x2061, 0x0100, 0x6120, 0xd1b4, 0x00c0, - 0x71a6, 0xd1bc, 0x00c0, 0x71f0, 0x0078, 0x7230, 0x2009, 0x017f, - 0x200b, 0x00a1, 0x157e, 0x007e, 0x0d7e, 0x2069, 0x0140, 0x20a9, - 0x001e, 0x2009, 0x0169, 0x6804, 0xa084, 0x4000, 0x0040, 0x71e7, - 0x6020, 0xd0b4, 0x0040, 0x71e7, 0x6024, 0xd094, 0x00c0, 0x71e7, - 0x2104, 0xa084, 0x000f, 0xa086, 0x0004, 0x00c0, 0x71e7, 0x00f0, - 0x71b3, 0x027e, 0x6198, 0xa18c, 0x00ff, 0x8107, 0x6130, 0xa18c, - 0x00ff, 0xa10d, 0x6088, 0x628c, 0x618e, 0x608b, 0xbc91, 0x6043, - 0x0001, 0x6043, 0x0000, 0x608a, 0x628e, 0x6024, 0xd094, 0x00c0, - 0x71e6, 0x6a04, 0xa294, 0x4000, 0x00c0, 0x71dd, 0x027f, 0x0d7f, - 0x007f, 0x157f, 0x2009, 0x017f, 0x200b, 0x0000, 0x0078, 0x7230, - 0x2009, 0x017f, 0x200b, 0x00a1, 0x157e, 0x007e, 0x0d7e, 0x2069, - 0x0140, 0x20a9, 0x001e, 0x2009, 0x0169, 0x6804, 0xa084, 0x4000, - 0x0040, 0x7229, 0x6020, 0xd0bc, 0x0040, 0x7229, 0x2104, 0xa084, - 0x000f, 0xa086, 0x0004, 0x00c0, 0x7229, 0x00f0, 0x71fd, 0x027e, - 0x6164, 0xa18c, 0x00ff, 0x8107, 0x6130, 0xa18c, 0x00ff, 0xa10d, - 0x6088, 0x628c, 0x608b, 0xbc91, 0x618e, 0x6043, 0x0001, 0x6043, - 0x0000, 0x608a, 0x628e, 0x6a04, 0xa294, 0x4000, 0x00c0, 0x7223, - 0x027f, 0x0d7f, 0x007f, 0x157f, 0x2009, 0x017f, 0x200b, 0x0000, - 0x0c7f, 0x127f, 0x007c, 0x0e7e, 0x2071, 0xa9b1, 0x7020, 0xa005, - 0x0040, 0x723c, 0x8001, 0x7022, 0x0e7f, 0x007c, 0x20a9, 0x0008, - 0x20a2, 0x00f0, 0x7240, 0x20a2, 0x20a2, 0x007c, 0x0f7e, 0x0e7e, - 0x0d7e, 0x0c7e, 0x077e, 0x067e, 0x007e, 0x127e, 0x2091, 0x8000, - 0x2071, 0xa9b1, 0x7614, 0x2660, 0x2678, 0x2039, 0x0001, 0x87ff, - 0x0040, 0x72e2, 0x8cff, 0x0040, 0x72e2, 0x601c, 0xa086, 0x0006, - 0x00c0, 0x72dd, 0x88ff, 0x0040, 0x726d, 0x2800, 0xac06, 0x00c0, - 0x72dd, 0x2039, 0x0000, 0x0078, 0x7278, 0x6018, 0xa206, 0x00c0, - 0x72dd, 0x85ff, 0x0040, 0x7278, 0x6020, 0xa106, 0x00c0, 0x72dd, - 0x7024, 0xac06, 0x00c0, 0x72a8, 0x2069, 0x0100, 0x68c0, 0xa005, - 0x0040, 0x72a3, 0x1078, 0x5acb, 0x6817, 0x0008, 0x68c3, 0x0000, - 0x1078, 0x7378, 0x7027, 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04, - 0xa384, 0x1000, 0x0040, 0x7298, 0x6803, 0x0100, 0x6803, 0x0000, - 0x2069, 0x0100, 0x6824, 0xd084, 0x0040, 0x72a0, 0x6827, 0x0001, - 0x037f, 0x0078, 0x72a8, 0x6003, 0x0009, 0x630a, 0x0078, 0x72dd, - 0x7014, 0xac36, 0x00c0, 0x72ae, 0x660c, 0x7616, 0x7010, 0xac36, - 0x00c0, 0x72bc, 0x2c00, 0xaf36, 0x0040, 0x72ba, 0x2f00, 0x7012, - 0x0078, 0x72bc, 0x7013, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06, - 0x0040, 0x72c5, 0x7e0e, 0x0078, 0x72c6, 0x2678, 0x89ff, 0x00c0, - 0x72d5, 0x600f, 0x0000, 0x6010, 0x2068, 0x1078, 0x8d16, 0x0040, - 0x72d3, 0x1078, 0xa1da, 0x1078, 0x8ed6, 0x1078, 0x7233, 0x88ff, - 0x00c0, 0x72ec, 0x0c7f, 0x0078, 0x7257, 0x2c78, 0x600c, 0x2060, - 0x0078, 0x7257, 0xa006, 0x127f, 0x007f, 0x067f, 0x077f, 0x0c7f, - 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x6017, 0x0000, 0x0c7f, 0xa8c5, - 0x0001, 0x0078, 0x72e3, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, - 0x027e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071, 0xa9b1, 0x7638, - 0x2660, 0x2678, 0x8cff, 0x0040, 0x7367, 0x601c, 0xa086, 0x0006, - 0x00c0, 0x7362, 0x87ff, 0x0040, 0x7313, 0x2700, 0xac06, 0x00c0, - 0x7362, 0x0078, 0x731e, 0x6018, 0xa206, 0x00c0, 0x7362, 0x85ff, - 0x0040, 0x731e, 0x6020, 0xa106, 0x00c0, 0x7362, 0x703c, 0xac06, - 0x00c0, 0x7332, 0x037e, 0x2019, 0x0001, 0x1078, 0x7058, 0x7033, - 0x0000, 0x703f, 0x0000, 0x7043, 0x0000, 0x7047, 0x0000, 0x704b, - 0x0000, 0x037f, 0x7038, 0xac36, 0x00c0, 0x7338, 0x660c, 0x763a, - 0x7034, 0xac36, 0x00c0, 0x7346, 0x2c00, 0xaf36, 0x0040, 0x7344, - 0x2f00, 0x7036, 0x0078, 0x7346, 0x7037, 0x0000, 0x660c, 0x067e, - 0x2c00, 0xaf06, 0x0040, 0x734f, 0x7e0e, 0x0078, 0x7350, 0x2678, - 0x600f, 0x0000, 0x6010, 0x2068, 0x1078, 0x8d16, 0x0040, 0x735a, - 0x1078, 0xa1da, 0x1078, 0x8ed6, 0x87ff, 0x00c0, 0x7371, 0x0c7f, - 0x0078, 0x7302, 0x2c78, 0x600c, 0x2060, 0x0078, 0x7302, 0xa006, - 0x127f, 0x007f, 0x027f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, - 0x007c, 0x6017, 0x0000, 0x0c7f, 0xa7bd, 0x0001, 0x0078, 0x7368, - 0x0e7e, 0x2071, 0xa9b1, 0x2001, 0xa700, 0x2004, 0xa086, 0x0002, - 0x00c0, 0x7386, 0x7007, 0x0005, 0x0078, 0x7388, 0x7007, 0x0000, - 0x0e7f, 0x007c, 0x0f7e, 0x0e7e, 0x0c7e, 0x067e, 0x027e, 0x007e, - 0x127e, 0x2091, 0x8000, 0x2071, 0xa9b1, 0x2c10, 0x7638, 0x2660, - 0x2678, 0x8cff, 0x0040, 0x73c8, 0x2200, 0xac06, 0x00c0, 0x73c3, - 0x7038, 0xac36, 0x00c0, 0x73a6, 0x660c, 0x763a, 0x7034, 0xac36, - 0x00c0, 0x73b4, 0x2c00, 0xaf36, 0x0040, 0x73b2, 0x2f00, 0x7036, - 0x0078, 0x73b4, 0x7037, 0x0000, 0x660c, 0x2c00, 0xaf06, 0x0040, - 0x73bc, 0x7e0e, 0x0078, 0x73bd, 0x2678, 0x600f, 0x0000, 0xa085, - 0x0001, 0x0078, 0x73c8, 0x2c78, 0x600c, 0x2060, 0x0078, 0x7399, - 0x127f, 0x007f, 0x027f, 0x067f, 0x0c7f, 0x0e7f, 0x0f7f, 0x007c, - 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x007e, 0x127e, 0x2091, - 0x8000, 0x2071, 0xa9b1, 0x760c, 0x2660, 0x2678, 0x8cff, 0x0040, - 0x7469, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x00c0, 0x7464, - 0x7024, 0xac06, 0x00c0, 0x740f, 0x2069, 0x0100, 0x68c0, 0xa005, - 0x0040, 0x743d, 0x1078, 0x6e0f, 0x68c3, 0x0000, 0x1078, 0x7378, - 0x7027, 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, - 0x0040, 0x7406, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, - 0x6824, 0xd084, 0x0040, 0x740e, 0x6827, 0x0001, 0x037f, 0x700c, - 0xac36, 0x00c0, 0x7415, 0x660c, 0x760e, 0x7008, 0xac36, 0x00c0, - 0x7423, 0x2c00, 0xaf36, 0x0040, 0x7421, 0x2f00, 0x700a, 0x0078, - 0x7423, 0x700b, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040, - 0x742c, 0x7e0e, 0x0078, 0x742d, 0x2678, 0x600f, 0x0000, 0x1078, - 0x8efc, 0x00c0, 0x7441, 0x1078, 0x28a6, 0x1078, 0x8f10, 0x00c0, - 0x745d, 0x1078, 0x7c83, 0x0078, 0x745d, 0x1078, 0x7378, 0x0078, - 0x740f, 0x1078, 0x8f10, 0x00c0, 0x7449, 0x1078, 0x7c83, 0x0078, - 0x745d, 0x6010, 0x2068, 0x1078, 0x8d16, 0x0040, 0x745d, 0x601c, - 0xa086, 0x0003, 0x00c0, 0x7471, 0x6837, 0x0103, 0x6b4a, 0x6847, - 0x0000, 0x1078, 0x4a73, 0x1078, 0x8ec9, 0x1078, 0x8ed6, 0x1078, - 0x7233, 0x0c7f, 0x0078, 0x73de, 0x2c78, 0x600c, 0x2060, 0x0078, - 0x73de, 0x127f, 0x007f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, - 0x007c, 0x601c, 0xa086, 0x0006, 0x00c0, 0x745d, 0x1078, 0xa1da, - 0x0078, 0x745d, 0x037e, 0x157e, 0x137e, 0x147e, 0x3908, 0xa006, - 0xa190, 0x0020, 0x221c, 0xa39e, 0x2676, 0x00c0, 0x748b, 0x8210, - 0x8000, 0x0078, 0x7482, 0xa005, 0x0040, 0x7497, 0x20a9, 0x0020, - 0x2198, 0x8211, 0xa282, 0x0020, 0x20c8, 0x20a0, 0x53a3, 0x147f, - 0x137f, 0x157f, 0x037f, 0x007c, 0x0d7e, 0x20a1, 0x020b, 0x1078, - 0x67c2, 0x20a3, 0x0200, 0x20a3, 0x0014, 0x60c3, 0x0014, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x2099, 0xa9a5, 0x20a9, 0x0004, 0x53a6, - 0x20a3, 0x0004, 0x20a3, 0x7878, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x1078, 0x6dfb, 0x0d7f, 0x007c, 0x20a1, 0x020b, 0x1078, 0x67c2, - 0x20a3, 0x0214, 0x20a3, 0x0018, 0x20a3, 0x0800, 0x7810, 0xa084, - 0xff00, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x20a3, 0x0000, 0x7810, 0xa084, 0x00ff, 0x20a2, 0x7828, 0x20a2, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0018, 0x1078, 0x6dfb, - 0x007c, 0x0d7e, 0x017e, 0x2f68, 0x2009, 0x0035, 0x1078, 0x91cc, - 0x00c0, 0x7551, 0x20a1, 0x020b, 0x1078, 0x6731, 0x20a3, 0x1300, - 0x20a3, 0x0000, 0x7828, 0x2068, 0x681c, 0xa086, 0x0003, 0x0040, - 0x752d, 0x7818, 0xa080, 0x0028, 0x2014, 0xa286, 0x007e, 0x00c0, - 0x7507, 0x20a3, 0x00ff, 0x20a3, 0xfffe, 0x0078, 0x7542, 0xa286, - 0x007f, 0x00c0, 0x7511, 0x20a3, 0x00ff, 0x20a3, 0xfffd, 0x0078, - 0x7542, 0xd2bc, 0x0040, 0x7527, 0xa286, 0x0080, 0x00c0, 0x751e, - 0x20a3, 0x00ff, 0x20a3, 0xfffc, 0x0078, 0x7542, 0xa2e8, 0xa835, - 0x2d6c, 0x6810, 0x20a2, 0x6814, 0x20a2, 0x0078, 0x7542, 0x20a3, - 0x0000, 0x6098, 0x20a2, 0x0078, 0x7542, 0x7818, 0xa080, 0x0028, - 0x2004, 0xa082, 0x007e, 0x0048, 0x753e, 0x0d7e, 0x2069, 0xa71b, - 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x7542, 0x20a3, 0x0000, - 0x6030, 0x20a2, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x20a3, 0x0000, - 0x20a3, 0x0000, 0x60c3, 0x000c, 0x1078, 0x6dfb, 0x017f, 0x0d7f, - 0x007c, 0x7817, 0x0001, 0x7803, 0x0006, 0x017f, 0x0d7f, 0x007c, - 0x0d7e, 0x027e, 0x7928, 0x2168, 0x691c, 0xa186, 0x0006, 0x0040, - 0x757a, 0xa186, 0x0003, 0x0040, 0x75d5, 0xa186, 0x0005, 0x0040, - 0x75b8, 0xa186, 0x0004, 0x0040, 0x75a8, 0xa186, 0x0008, 0x0040, - 0x75c2, 0x7807, 0x0037, 0x7813, 0x1700, 0x1078, 0x7640, 0x027f, - 0x0d7f, 0x007c, 0x1078, 0x75fd, 0x2009, 0x4000, 0x6800, 0x0079, - 0x7581, 0x7594, 0x75a2, 0x7596, 0x75a2, 0x759d, 0x7594, 0x7594, - 0x75a2, 0x75a2, 0x75a2, 0x75a2, 0x7594, 0x7594, 0x7594, 0x7594, - 0x7594, 0x75a2, 0x7594, 0x75a2, 0x1078, 0x1332, 0x6824, 0xd0e4, - 0x0040, 0x759d, 0xd0cc, 0x0040, 0x75a0, 0xa00e, 0x0078, 0x75a2, - 0x2009, 0x2000, 0x6828, 0x20a2, 0x682c, 0x20a2, 0x0078, 0x75f3, - 0x1078, 0x75fd, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x2009, 0x4000, - 0x6a00, 0xa286, 0x0002, 0x00c0, 0x75b6, 0xa00e, 0x0078, 0x75f3, - 0x1078, 0x75fd, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x2009, 0x4000, - 0x0078, 0x75f3, 0x1078, 0x75fd, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x2009, 0x4000, 0xa286, 0x0005, 0x0040, 0x75d2, 0xa286, 0x0002, - 0x00c0, 0x75d3, 0xa00e, 0x0078, 0x75f3, 0x1078, 0x75fd, 0x6810, - 0x2068, 0x697c, 0x6810, 0xa112, 0x6980, 0x6814, 0xa103, 0x20a2, - 0x22a2, 0x7928, 0xa180, 0x0000, 0x2004, 0xa08e, 0x0002, 0x0040, - 0x75f1, 0xa08e, 0x0004, 0x0040, 0x75f1, 0x2009, 0x4000, 0x0078, - 0x75f3, 0x2009, 0x0000, 0x21a2, 0x20a3, 0x0000, 0x60c3, 0x0018, - 0x1078, 0x6dfb, 0x027f, 0x0d7f, 0x007c, 0x037e, 0x047e, 0x057e, - 0x067e, 0x20a1, 0x020b, 0x1078, 0x67c2, 0xa006, 0x20a3, 0x0200, - 0x20a2, 0x7934, 0x21a2, 0x7938, 0x21a2, 0x7818, 0xa080, 0x0028, - 0x2004, 0xa092, 0x007e, 0x0048, 0x7623, 0x0d7e, 0x2069, 0xa71b, - 0x2d2c, 0x8d68, 0x2d34, 0xa0e8, 0xa835, 0x2d6c, 0x6b10, 0x6c14, - 0x0d7f, 0x0078, 0x7629, 0x2019, 0x0000, 0x6498, 0x2029, 0x0000, - 0x6630, 0x7828, 0xa080, 0x0007, 0x2004, 0xa086, 0x0003, 0x00c0, - 0x7637, 0x25a2, 0x26a2, 0x23a2, 0x24a2, 0x0078, 0x763b, 0x23a2, - 0x24a2, 0x25a2, 0x26a2, 0x067f, 0x057f, 0x047f, 0x037f, 0x007c, - 0x20a1, 0x020b, 0x1078, 0x67c2, 0x20a3, 0x0100, 0x20a3, 0x0000, - 0x20a3, 0x0009, 0x7810, 0x20a2, 0x60c3, 0x0008, 0x1078, 0x6dfb, - 0x007c, 0x20a1, 0x020b, 0x1078, 0x6728, 0x20a3, 0x1400, 0x20a3, - 0x0000, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x7828, 0x20a2, 0x782c, - 0x20a2, 0x7830, 0xa084, 0x00ff, 0x8007, 0x20a2, 0x20a3, 0x0000, - 0x60c3, 0x0010, 0x1078, 0x6dfb, 0x007c, 0x20a1, 0x020b, 0x1078, - 0x67b9, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x7828, 0x20a2, 0x7810, - 0x20a2, 0x60c3, 0x0008, 0x1078, 0x6dfb, 0x007c, 0x147e, 0x20a1, - 0x020b, 0x1078, 0x7689, 0x60c3, 0x0000, 0x1078, 0x6dfb, 0x147f, - 0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, - 0x2004, 0xd0bc, 0x0040, 0x76a6, 0x0d7e, 0xa0e8, 0xa835, 0x2d6c, - 0x6810, 0xa085, 0x0300, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa71b, - 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x76ae, 0x20a3, 0x0300, - 0x6298, 0x22a2, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, 0x0819, - 0x20a3, 0x0000, 0x1078, 0x6dea, 0x22a2, 0x20a3, 0x0000, 0x2fa2, - 0x7a08, 0x22a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x007c, 0x2061, - 0xae00, 0x2a70, 0x7064, 0x704a, 0x704f, 0xae00, 0x007c, 0x0e7e, - 0x127e, 0x2071, 0xa700, 0x2091, 0x8000, 0x7548, 0xa582, 0x0010, - 0x0048, 0x76f9, 0x704c, 0x2060, 0x6000, 0xa086, 0x0000, 0x0040, - 0x76e5, 0xace0, 0x0010, 0x7058, 0xac02, 0x00c8, 0x76e1, 0x0078, - 0x76d4, 0x2061, 0xae00, 0x0078, 0x76d4, 0x6003, 0x0008, 0x8529, - 0x754a, 0xaca8, 0x0010, 0x7058, 0xa502, 0x00c8, 0x76f5, 0x754e, - 0xa085, 0x0001, 0x127f, 0x0e7f, 0x007c, 0x704f, 0xae00, 0x0078, - 0x76f0, 0xa006, 0x0078, 0x76f2, 0x0e7e, 0x2071, 0xa700, 0x7548, - 0xa582, 0x0010, 0x0048, 0x772a, 0x704c, 0x2060, 0x6000, 0xa086, - 0x0000, 0x0040, 0x7717, 0xace0, 0x0010, 0x7058, 0xac02, 0x00c8, - 0x7713, 0x0078, 0x7706, 0x2061, 0xae00, 0x0078, 0x7706, 0x6003, - 0x0008, 0x8529, 0x754a, 0xaca8, 0x0010, 0x7058, 0xa502, 0x00c8, - 0x7726, 0x754e, 0xa085, 0x0001, 0x0e7f, 0x007c, 0x704f, 0xae00, - 0x0078, 0x7722, 0xa006, 0x0078, 0x7724, 0xac82, 0xae00, 0x1048, - 0x1332, 0x2001, 0xa716, 0x2004, 0xac02, 0x10c8, 0x1332, 0xa006, - 0x6006, 0x600a, 0x600e, 0x6012, 0x6016, 0x601a, 0x601f, 0x0000, - 0x6003, 0x0000, 0x6022, 0x6026, 0x602a, 0x602e, 0x6032, 0x6036, - 0x603a, 0x603e, 0x2061, 0xa700, 0x6048, 0x8000, 0x604a, 0xa086, - 0x0001, 0x0040, 0x7754, 0x007c, 0x127e, 0x2091, 0x8000, 0x1078, - 0x62d1, 0x127f, 0x0078, 0x7753, 0x601c, 0xa084, 0x000f, 0x0079, - 0x7761, 0x776a, 0x777b, 0x7797, 0x77b3, 0x921e, 0x923a, 0x9256, - 0x776a, 0x777b, 0xa186, 0x0013, 0x00c0, 0x7773, 0x1078, 0x61cd, - 0x1078, 0x62d1, 0x007c, 0xa18e, 0x0047, 0x00c0, 0x777a, 0xa016, - 0x1078, 0x15fa, 0x007c, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8, - 0x1332, 0x1079, 0x7785, 0x067f, 0x007c, 0x7795, 0x7b00, 0x7cb2, - 0x7795, 0x7d36, 0x77cf, 0x7795, 0x7795, 0x7a92, 0x80f6, 0x7795, - 0x7795, 0x7795, 0x7795, 0x7795, 0x7795, 0x1078, 0x1332, 0x067e, - 0x6000, 0xa0b2, 0x0010, 0x10c8, 0x1332, 0x1079, 0x77a1, 0x067f, - 0x007c, 0x77b1, 0x87d3, 0x77b1, 0x77b1, 0x77b1, 0x77b1, 0x77b1, - 0x77b1, 0x8776, 0x8961, 0x77b1, 0x8803, 0x8889, 0x8803, 0x8889, - 0x77b1, 0x1078, 0x1332, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8, - 0x1332, 0x1079, 0x77bd, 0x067f, 0x007c, 0x77cd, 0x813d, 0x820e, - 0x8372, 0x84f1, 0x77cd, 0x77cd, 0x77cd, 0x8116, 0x871e, 0x8722, - 0x77cd, 0x77cd, 0x77cd, 0x77cd, 0x8752, 0x1078, 0x1332, 0xa1b6, - 0x0015, 0x00c0, 0x77d7, 0x1078, 0x772d, 0x0078, 0x77dd, 0xa1b6, - 0x0016, 0x10c0, 0x1332, 0x1078, 0x772d, 0x007c, 0x20a9, 0x000e, - 0x2e98, 0x6010, 0x20a0, 0x53a3, 0x20a9, 0x0006, 0x3310, 0x3420, - 0x9398, 0x94a0, 0x3318, 0x3428, 0x222e, 0x2326, 0xa290, 0x0002, - 0xa5a8, 0x0002, 0xa398, 0x0002, 0xa4a0, 0x0002, 0x00f0, 0x77ec, - 0x0e7e, 0x1078, 0x8d16, 0x0040, 0x7803, 0x6010, 0x2070, 0x7007, - 0x0000, 0x7037, 0x0103, 0x0e7f, 0x1078, 0x772d, 0x007c, 0x0d7e, - 0x037e, 0x7330, 0xa386, 0x0200, 0x00c0, 0x7814, 0x6018, 0x2068, - 0x6813, 0x00ff, 0x6817, 0xfffd, 0x6010, 0xa005, 0x0040, 0x781e, - 0x2068, 0x6807, 0x0000, 0x6837, 0x0103, 0x6b32, 0x1078, 0x772d, - 0x037f, 0x0d7f, 0x007c, 0x017e, 0x20a9, 0x002a, 0xae80, 0x000c, - 0x2098, 0x6010, 0xa080, 0x0002, 0x20a0, 0x53a3, 0x20a9, 0x002a, - 0x6010, 0xa080, 0x0001, 0x2004, 0xa080, 0x0002, 0x20a0, 0x53a3, - 0x0e7e, 0x6010, 0x2004, 0x2070, 0x7037, 0x0103, 0x0e7f, 0x1078, - 0x772d, 0x017f, 0x007c, 0x0e7e, 0x0d7e, 0x603f, 0x0000, 0x2c68, - 0x017e, 0x2009, 0x0035, 0x1078, 0x91cc, 0x017f, 0x00c0, 0x785f, - 0x027e, 0x6228, 0x2268, 0x027f, 0x2071, 0xac8c, 0x6b1c, 0xa386, - 0x0003, 0x0040, 0x7863, 0xa386, 0x0006, 0x0040, 0x7867, 0x1078, - 0x772d, 0x0078, 0x7869, 0x1078, 0x786c, 0x0078, 0x7869, 0x1078, - 0x7938, 0x0d7f, 0x0e7f, 0x007c, 0x0f7e, 0x6810, 0x2078, 0xa186, - 0x0015, 0x0040, 0x791d, 0xa18e, 0x0016, 0x00c0, 0x7936, 0x700c, - 0xa08c, 0xff00, 0xa186, 0x1700, 0x0040, 0x7882, 0xa186, 0x0300, - 0x00c0, 0x78f8, 0x8fff, 0x00c0, 0x788c, 0x6800, 0xa086, 0x000f, - 0x0040, 0x78db, 0x0078, 0x7934, 0x6808, 0xa086, 0xffff, 0x00c0, - 0x7921, 0x784c, 0xa084, 0x0060, 0xa086, 0x0020, 0x00c0, 0x78a2, - 0x797c, 0x7810, 0xa106, 0x00c0, 0x7921, 0x7980, 0x7814, 0xa106, - 0x00c0, 0x7921, 0x1078, 0x8ec9, 0x6830, 0x7852, 0x784c, 0xc0dc, - 0xc0f4, 0xc0d4, 0x784e, 0x027e, 0xa00e, 0x6a14, 0x2001, 0x000a, - 0x1078, 0x5c1c, 0x7854, 0xa20a, 0x0048, 0x78b7, 0x8011, 0x7a56, - 0x82ff, 0x027f, 0x00c0, 0x78c3, 0x0c7e, 0x2d60, 0x1078, 0x8af0, - 0x0c7f, 0x0078, 0x7934, 0x0c7e, 0x0d7e, 0x2f68, 0x6838, 0xd0fc, - 0x00c0, 0x78ce, 0x1078, 0x4353, 0x0078, 0x78d0, 0x1078, 0x4431, - 0x0d7f, 0x0c7f, 0x00c0, 0x7921, 0x0c7e, 0x2d60, 0x1078, 0x772d, - 0x0c7f, 0x0078, 0x7934, 0x0c7e, 0x1078, 0x9197, 0x0040, 0x78f1, - 0x6013, 0x0000, 0x6818, 0x601a, 0x601f, 0x0003, 0x6904, 0x0c7e, - 0x2d60, 0x1078, 0x772d, 0x0c7f, 0x1078, 0x775c, 0x0c7f, 0x0078, - 0x7934, 0x2001, 0xa9a4, 0x2004, 0x683e, 0x0c7f, 0x0078, 0x7934, - 0x7008, 0xa086, 0x000b, 0x00c0, 0x7912, 0x6018, 0x200c, 0xc1bc, - 0x2102, 0x0c7e, 0x2d60, 0x7853, 0x0003, 0x6007, 0x0085, 0x6003, - 0x000b, 0x601f, 0x0002, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0c7f, - 0x0078, 0x7934, 0x700c, 0xa086, 0x2a00, 0x00c0, 0x7921, 0x2001, - 0xa9a4, 0x2004, 0x683e, 0x0078, 0x7934, 0x1078, 0x7953, 0x0078, - 0x7936, 0x8fff, 0x1040, 0x1332, 0x0c7e, 0x0d7e, 0x2d60, 0x2f68, - 0x6837, 0x0103, 0x684b, 0x0003, 0x1078, 0x89df, 0x1078, 0x8ec9, - 0x1078, 0x8ed6, 0x0d7f, 0x0c7f, 0x1078, 0x772d, 0x0f7f, 0x007c, - 0xa186, 0x0015, 0x00c0, 0x7942, 0x2001, 0xa9a4, 0x2004, 0x683e, - 0x0078, 0x7950, 0xa18e, 0x0016, 0x00c0, 0x7952, 0x0c7e, 0x2d00, - 0x2060, 0x1078, 0xa4a5, 0x1078, 0x5bc1, 0x1078, 0x772d, 0x0c7f, - 0x1078, 0x772d, 0x007c, 0x027e, 0x037e, 0x047e, 0x7228, 0x7c80, - 0x7b7c, 0xd2f4, 0x0040, 0x7962, 0x2001, 0xa9a4, 0x2004, 0x683e, - 0x0078, 0x79c6, 0x0c7e, 0x2d60, 0x1078, 0x8a03, 0x0c7f, 0x6804, - 0xa086, 0x0050, 0x00c0, 0x797a, 0x0c7e, 0x2d00, 0x2060, 0x6003, - 0x0001, 0x6007, 0x0050, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0c7f, - 0x0078, 0x79c6, 0x6800, 0xa086, 0x000f, 0x0040, 0x799c, 0x8fff, - 0x1040, 0x1332, 0x6824, 0xd0dc, 0x00c0, 0x799c, 0x6800, 0xa086, - 0x0004, 0x00c0, 0x79a1, 0x784c, 0xd0ac, 0x0040, 0x79a1, 0x784c, - 0xc0dc, 0xc0f4, 0x784e, 0x7850, 0xc0f4, 0xc0fc, 0x7852, 0x2001, - 0x0001, 0x682e, 0x0078, 0x79c0, 0x2001, 0x0007, 0x682e, 0x0078, - 0x79c0, 0x784c, 0xd0b4, 0x00c0, 0x79ae, 0xd0ac, 0x0040, 0x799c, - 0x784c, 0xd0f4, 0x00c0, 0x799c, 0x0078, 0x798f, 0xd2ec, 0x00c0, - 0x799c, 0x7024, 0xa306, 0x00c0, 0x79b9, 0x7020, 0xa406, 0x0040, - 0x799c, 0x7020, 0x6836, 0x7024, 0x683a, 0x2001, 0x0005, 0x682e, - 0x1078, 0x9000, 0x1078, 0x62d1, 0x0078, 0x79c8, 0x1078, 0x772d, - 0x047f, 0x037f, 0x027f, 0x007c, 0x0e7e, 0x0d7e, 0x027e, 0x6034, - 0x2068, 0x6a1c, 0xa286, 0x0007, 0x0040, 0x7a35, 0xa286, 0x0002, - 0x0040, 0x7a35, 0xa286, 0x0000, 0x0040, 0x7a35, 0x6808, 0x6338, - 0xa306, 0x00c0, 0x7a35, 0x2071, 0xac8c, 0xa186, 0x0015, 0x0040, - 0x7a2f, 0xa18e, 0x0016, 0x00c0, 0x7a02, 0x6030, 0xa084, 0x00ff, - 0xa086, 0x0001, 0x00c0, 0x7a02, 0x700c, 0xa086, 0x2a00, 0x00c0, - 0x7a02, 0x6034, 0xa080, 0x0009, 0x200c, 0xc1dd, 0xc1f5, 0x2102, - 0x0078, 0x7a2f, 0x0c7e, 0x6034, 0x2060, 0x6104, 0xa186, 0x004b, - 0x0040, 0x7a22, 0xa186, 0x004c, 0x0040, 0x7a22, 0xa186, 0x004d, - 0x0040, 0x7a22, 0xa186, 0x004e, 0x0040, 0x7a22, 0xa186, 0x0052, - 0x0040, 0x7a22, 0x6010, 0x2068, 0x1078, 0x8d16, 0x1040, 0x1332, - 0x6853, 0x0003, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, - 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0c7f, 0x0078, 0x7a35, 0x6034, - 0x2068, 0x2001, 0xa9a4, 0x2004, 0x683e, 0x1078, 0x772d, 0x027f, - 0x0d7f, 0x0e7f, 0x007c, 0x0d7e, 0x20a9, 0x000e, 0x2e98, 0x6010, - 0x20a0, 0x53a3, 0xa1b6, 0x0015, 0x00c0, 0x7a73, 0x6018, 0x2068, - 0x157e, 0x037e, 0x027e, 0xae90, 0x000c, 0xa290, 0x0004, 0x20a9, - 0x0004, 0xad98, 0x000a, 0x1078, 0x80de, 0x027f, 0x037f, 0x157f, - 0x00c0, 0x7a76, 0x157e, 0x037e, 0x027e, 0xae90, 0x000c, 0xa290, - 0x0008, 0x20a9, 0x0004, 0xad98, 0x0006, 0x1078, 0x80de, 0x027f, - 0x037f, 0x157f, 0x00c0, 0x7a76, 0x7038, 0x680a, 0x703c, 0x680e, - 0x6800, 0xc08d, 0x6802, 0x0d7f, 0x0078, 0x77f8, 0x1078, 0x2880, - 0x0c7e, 0x1078, 0x76c7, 0x2f00, 0x601a, 0x6013, 0x0000, 0x601f, - 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x2001, 0x0007, 0x1078, - 0x4502, 0x1078, 0x4535, 0x1078, 0x5dd7, 0x1078, 0x62d1, 0x0c7f, - 0x0078, 0x7a73, 0x2100, 0xa1b2, 0x0044, 0x10c8, 0x1332, 0xa1b2, - 0x0040, 0x00c8, 0x7af7, 0x0079, 0x7a9d, 0x7aeb, 0x7adf, 0x7aeb, - 0x7aeb, 0x7aeb, 0x7aeb, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, - 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, - 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, - 0x7add, 0x7add, 0x7add, 0x7add, 0x7aeb, 0x7add, 0x7aeb, 0x7aeb, - 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7aeb, 0x7add, 0x7add, - 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7aeb, - 0x7aeb, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, - 0x7add, 0x7add, 0x7aeb, 0x7add, 0x7add, 0x1078, 0x1332, 0x6003, - 0x0001, 0x6106, 0x1078, 0x5dd7, 0x127e, 0x2091, 0x8000, 0x1078, - 0x62d1, 0x127f, 0x007c, 0x6003, 0x0001, 0x6106, 0x1078, 0x5dd7, - 0x127e, 0x2091, 0x8000, 0x1078, 0x62d1, 0x127f, 0x007c, 0x2600, - 0x0079, 0x7afa, 0x7afe, 0x7afe, 0x7afe, 0x7aeb, 0x1078, 0x1332, - 0x6004, 0xa0b2, 0x0044, 0x10c8, 0x1332, 0xa1b6, 0x0013, 0x00c0, - 0x7b10, 0xa0b2, 0x0040, 0x00c8, 0x7c79, 0x2008, 0x0079, 0x7bbf, - 0xa1b6, 0x0027, 0x00c0, 0x7b7c, 0x1078, 0x61cd, 0x6004, 0x1078, - 0x8efc, 0x0040, 0x7b2d, 0x1078, 0x8f10, 0x0040, 0x7b74, 0xa08e, - 0x0021, 0x0040, 0x7b78, 0xa08e, 0x0022, 0x0040, 0x7b74, 0xa08e, - 0x003d, 0x0040, 0x7b78, 0x0078, 0x7b6f, 0x1078, 0x28a6, 0x2001, - 0x0007, 0x1078, 0x4502, 0x6018, 0xa080, 0x0028, 0x200c, 0x1078, - 0x7c83, 0xa186, 0x007e, 0x00c0, 0x7b42, 0x2001, 0xa733, 0x2014, - 0xc285, 0x2202, 0x017e, 0x027e, 0x037e, 0x2110, 0x027e, 0x2019, - 0x0028, 0x1078, 0x73d0, 0x027f, 0x1078, 0xa501, 0x037f, 0x027f, - 0x017f, 0x017e, 0x027e, 0x037e, 0x2110, 0x2019, 0x0028, 0x1078, - 0x5f01, 0x077e, 0x2039, 0x0000, 0x1078, 0x5e0a, 0x0c7e, 0x6018, - 0xa065, 0x0040, 0x7b65, 0x1078, 0x47e9, 0x0c7f, 0x2c08, 0x1078, - 0x9f9b, 0x077f, 0x037f, 0x027f, 0x017f, 0x1078, 0x457f, 0x1078, - 0x772d, 0x1078, 0x62d1, 0x007c, 0x1078, 0x7c83, 0x0078, 0x7b6f, - 0x1078, 0x7ca6, 0x0078, 0x7b6f, 0xa186, 0x0014, 0x00c0, 0x7b73, - 0x1078, 0x61cd, 0x1078, 0x2880, 0x1078, 0x8efc, 0x00c0, 0x7b9b, - 0x1078, 0x28a6, 0x6018, 0xa080, 0x0028, 0x200c, 0x1078, 0x7c83, - 0xa186, 0x007e, 0x00c0, 0x7b99, 0x2001, 0xa733, 0x200c, 0xc185, - 0x2102, 0x0078, 0x7b6f, 0x1078, 0x8f10, 0x00c0, 0x7ba3, 0x1078, - 0x7c83, 0x0078, 0x7b6f, 0x6004, 0xa08e, 0x0032, 0x00c0, 0x7bb4, - 0x0e7e, 0x0f7e, 0x2071, 0xa782, 0x2079, 0x0000, 0x1078, 0x2bd7, - 0x0f7f, 0x0e7f, 0x0078, 0x7b6f, 0x6004, 0xa08e, 0x0021, 0x0040, - 0x7b9f, 0xa08e, 0x0022, 0x1040, 0x7c83, 0x0078, 0x7b6f, 0x7c01, - 0x7c03, 0x7c07, 0x7c0b, 0x7c0f, 0x7c13, 0x7bff, 0x7bff, 0x7bff, - 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, - 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, - 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7c17, 0x7c29, 0x7bff, - 0x7c2b, 0x7c29, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7c29, - 0x7c29, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, - 0x7bff, 0x7c5c, 0x7c29, 0x7bff, 0x7c23, 0x7bff, 0x7bff, 0x7bff, - 0x7c25, 0x7bff, 0x7bff, 0x7bff, 0x7c29, 0x7bff, 0x7bff, 0x1078, - 0x1332, 0x0078, 0x7c29, 0x2001, 0x000b, 0x0078, 0x7c36, 0x2001, - 0x0003, 0x0078, 0x7c36, 0x2001, 0x0005, 0x0078, 0x7c36, 0x2001, - 0x0001, 0x0078, 0x7c36, 0x2001, 0x0009, 0x0078, 0x7c36, 0x1078, - 0x61cd, 0x6003, 0x0005, 0x2001, 0xa9a4, 0x2004, 0x603e, 0x1078, - 0x62d1, 0x0078, 0x7c35, 0x0078, 0x7c29, 0x0078, 0x7c29, 0x1078, - 0x4502, 0x0078, 0x7c6e, 0x1078, 0x61cd, 0x6003, 0x0004, 0x2001, - 0xa9a2, 0x2004, 0x6016, 0x1078, 0x62d1, 0x007c, 0x1078, 0x4502, - 0x1078, 0x61cd, 0x2001, 0xa9a4, 0x2004, 0x603e, 0x6003, 0x0002, - 0x037e, 0x2019, 0xa75d, 0x2304, 0xa084, 0xff00, 0x00c0, 0x7c4d, - 0x2019, 0xa9a2, 0x231c, 0x0078, 0x7c56, 0x8007, 0xa09a, 0x0004, - 0x0048, 0x7c48, 0x8003, 0x801b, 0x831b, 0xa318, 0x6316, 0x037f, - 0x1078, 0x62d1, 0x0078, 0x7c35, 0x0e7e, 0x0f7e, 0x2071, 0xa782, - 0x2079, 0x0000, 0x1078, 0x2bd7, 0x0f7f, 0x0e7f, 0x1078, 0x61cd, - 0x1078, 0x772d, 0x1078, 0x62d1, 0x0078, 0x7c35, 0x1078, 0x61cd, - 0x6003, 0x0002, 0x2001, 0xa9a2, 0x2004, 0x6016, 0x1078, 0x62d1, - 0x007c, 0x2600, 0x2008, 0x0079, 0x7c7d, 0x7c81, 0x7c81, 0x7c81, - 0x7c6e, 0x1078, 0x1332, 0x0e7e, 0x1078, 0x8d16, 0x0040, 0x7c9f, - 0x6010, 0x2070, 0x7038, 0xd0fc, 0x0040, 0x7c9f, 0x7007, 0x0000, - 0x017e, 0x6004, 0xa08e, 0x0021, 0x0040, 0x7ca1, 0xa08e, 0x003d, - 0x0040, 0x7ca1, 0x017f, 0x7037, 0x0103, 0x7033, 0x0100, 0x0e7f, - 0x007c, 0x017f, 0x1078, 0x7ca6, 0x0078, 0x7c9f, 0x0e7e, 0xacf0, - 0x0004, 0x2e74, 0x7000, 0x2070, 0x7037, 0x0103, 0x7023, 0x8001, - 0x0e7f, 0x007c, 0x0d7e, 0x6618, 0x2668, 0x6804, 0xa084, 0x00ff, - 0x0d7f, 0xa0b2, 0x000c, 0x10c8, 0x1332, 0x6604, 0xa6b6, 0x0043, - 0x00c0, 0x7cc6, 0x1078, 0x9144, 0x0078, 0x7d25, 0x6604, 0xa6b6, - 0x0033, 0x00c0, 0x7ccf, 0x1078, 0x90e8, 0x0078, 0x7d25, 0x6604, - 0xa6b6, 0x0028, 0x00c0, 0x7cd8, 0x1078, 0x8f3f, 0x0078, 0x7d25, - 0x6604, 0xa6b6, 0x0029, 0x00c0, 0x7ce1, 0x1078, 0x8f59, 0x0078, - 0x7d25, 0x6604, 0xa6b6, 0x001f, 0x00c0, 0x7cea, 0x1078, 0x77de, - 0x0078, 0x7d25, 0x6604, 0xa6b6, 0x0000, 0x00c0, 0x7cf3, 0x1078, - 0x7a3b, 0x0078, 0x7d25, 0x6604, 0xa6b6, 0x0022, 0x00c0, 0x7cfc, - 0x1078, 0x7807, 0x0078, 0x7d25, 0x6604, 0xa6b6, 0x0035, 0x00c0, - 0x7d05, 0x1078, 0x7843, 0x0078, 0x7d25, 0x6604, 0xa6b6, 0x0039, - 0x00c0, 0x7d0e, 0x1078, 0x79cc, 0x0078, 0x7d25, 0x6604, 0xa6b6, - 0x003d, 0x00c0, 0x7d17, 0x1078, 0x7823, 0x0078, 0x7d25, 0xa1b6, - 0x0015, 0x00c0, 0x7d1f, 0x1079, 0x7d2a, 0x0078, 0x7d25, 0xa1b6, - 0x0016, 0x00c0, 0x7d26, 0x1079, 0x7e7f, 0x007c, 0x1078, 0x7773, - 0x0078, 0x7d25, 0x7d4e, 0x7d51, 0x7d4e, 0x7d9c, 0x7d4e, 0x7e13, - 0x7e8b, 0x7d4e, 0x7d4e, 0x7e57, 0x7d4e, 0x7e6d, 0xa1b6, 0x0048, - 0x0040, 0x7d42, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x1078, - 0x15fa, 0x007c, 0x0e7e, 0xacf0, 0x0004, 0x2e74, 0x7000, 0x2070, - 0x7037, 0x0103, 0x0e7f, 0x1078, 0x772d, 0x007c, 0x0005, 0x0005, - 0x007c, 0x0e7e, 0x2071, 0xa700, 0x7080, 0xa086, 0x0074, 0x00c0, - 0x7d85, 0x1078, 0x9f6f, 0x00c0, 0x7d77, 0x0d7e, 0x6018, 0x2068, - 0x7030, 0xd08c, 0x0040, 0x7d6a, 0x6800, 0xd0bc, 0x0040, 0x7d6a, - 0xc0c5, 0x6802, 0x1078, 0x7d89, 0x0d7f, 0x2001, 0x0006, 0x1078, - 0x4502, 0x1078, 0x28a6, 0x1078, 0x772d, 0x0078, 0x7d87, 0x2001, - 0x000a, 0x1078, 0x4502, 0x1078, 0x28a6, 0x6003, 0x0001, 0x6007, - 0x0001, 0x1078, 0x5dd7, 0x0078, 0x7d87, 0x1078, 0x7dff, 0x0e7f, - 0x007c, 0x6800, 0xd084, 0x0040, 0x7d9b, 0x2001, 0x0000, 0x1078, - 0x44ee, 0x2069, 0xa752, 0x6804, 0xd0a4, 0x0040, 0x7d9b, 0x2001, - 0x0006, 0x1078, 0x4535, 0x007c, 0x0d7e, 0x2011, 0xa720, 0x2204, - 0xa086, 0x0074, 0x00c0, 0x7dfb, 0x6018, 0x2068, 0x6aa0, 0xa286, - 0x007e, 0x00c0, 0x7daf, 0x1078, 0x7f9b, 0x0078, 0x7dfd, 0x1078, - 0x7f91, 0x6018, 0x2068, 0xa080, 0x0028, 0x2014, 0xa286, 0x0080, - 0x00c0, 0x7dd3, 0x6813, 0x00ff, 0x6817, 0xfffc, 0x6010, 0xa005, - 0x0040, 0x7dc9, 0x2068, 0x6807, 0x0000, 0x6837, 0x0103, 0x6833, - 0x0200, 0x2001, 0x0006, 0x1078, 0x4502, 0x1078, 0x28a6, 0x1078, - 0x772d, 0x0078, 0x7dfd, 0x0e7e, 0x2071, 0xa733, 0x2e04, 0xd09c, - 0x0040, 0x7dee, 0x2071, 0xac80, 0x7108, 0x720c, 0xa18c, 0x00ff, - 0x00c0, 0x7de6, 0xa284, 0xff00, 0x0040, 0x7dee, 0x6018, 0x2070, - 0x70a0, 0xd0bc, 0x00c0, 0x7dee, 0x7112, 0x7216, 0x0e7f, 0x2001, - 0x0004, 0x1078, 0x4502, 0x6003, 0x0001, 0x6007, 0x0003, 0x1078, - 0x5dd7, 0x0078, 0x7dfd, 0x1078, 0x7dff, 0x0d7f, 0x007c, 0x2001, - 0x0007, 0x1078, 0x4502, 0x2001, 0xa700, 0x2004, 0xa086, 0x0003, - 0x00c0, 0x7e0e, 0x2001, 0x0007, 0x1078, 0x4535, 0x1078, 0x28a6, - 0x1078, 0x772d, 0x007c, 0x0e7e, 0x2071, 0xa700, 0x7080, 0xa086, - 0x0014, 0x00c0, 0x7e51, 0x7000, 0xa086, 0x0003, 0x00c0, 0x7e26, - 0x6010, 0xa005, 0x00c0, 0x7e26, 0x1078, 0x3699, 0x0d7e, 0x6018, - 0x2068, 0x1078, 0x4649, 0x1078, 0x7d89, 0x0d7f, 0x1078, 0x8043, - 0x00c0, 0x7e51, 0x0d7e, 0x6018, 0x2068, 0x6890, 0x0d7f, 0xa005, - 0x0040, 0x7e51, 0x2001, 0x0006, 0x1078, 0x4502, 0x0e7e, 0x6010, - 0xa005, 0x0040, 0x7e4a, 0x2070, 0x7007, 0x0000, 0x7037, 0x0103, - 0x7033, 0x0200, 0x0e7f, 0x1078, 0x28a6, 0x1078, 0x772d, 0x0078, - 0x7e55, 0x1078, 0x7c83, 0x1078, 0x7dff, 0x0e7f, 0x007c, 0x2011, - 0xa720, 0x2204, 0xa086, 0x0014, 0x00c0, 0x7e6a, 0x2001, 0x0002, - 0x1078, 0x4502, 0x6003, 0x0001, 0x6007, 0x0001, 0x1078, 0x5dd7, - 0x0078, 0x7e6c, 0x1078, 0x7dff, 0x007c, 0x2011, 0xa720, 0x2204, - 0xa086, 0x0004, 0x00c0, 0x7e7c, 0x2001, 0x0007, 0x1078, 0x4502, - 0x1078, 0x772d, 0x0078, 0x7e7e, 0x1078, 0x7dff, 0x007c, 0x7d4e, - 0x7e97, 0x7d4e, 0x7ed2, 0x7d4e, 0x7f44, 0x7e8b, 0x7d4e, 0x7d4e, - 0x7f59, 0x7d4e, 0x7f6c, 0x6604, 0xa686, 0x0003, 0x0040, 0x7e13, - 0xa6b6, 0x001e, 0x00c0, 0x7e96, 0x1078, 0x772d, 0x007c, 0x0d7e, - 0x0c7e, 0x1078, 0x7f7f, 0x00c0, 0x7ead, 0x2001, 0x0000, 0x1078, - 0x44ee, 0x2001, 0x0002, 0x1078, 0x4502, 0x6003, 0x0001, 0x6007, - 0x0002, 0x1078, 0x5dd7, 0x0078, 0x7ecf, 0x2009, 0xac8e, 0x2104, - 0xa086, 0x0009, 0x00c0, 0x7ec2, 0x6018, 0x2068, 0x6840, 0xa084, - 0x00ff, 0xa005, 0x0040, 0x7ecd, 0x8001, 0x6842, 0x6017, 0x000a, - 0x0078, 0x7ecf, 0x2009, 0xac8f, 0x2104, 0xa084, 0xff00, 0xa086, - 0x1900, 0x00c0, 0x7ecd, 0x0078, 0x7ea1, 0x1078, 0x7dff, 0x0c7f, - 0x0d7f, 0x007c, 0x1078, 0x7f8e, 0x00c0, 0x7ee6, 0x2001, 0x0000, - 0x1078, 0x44ee, 0x2001, 0x0002, 0x1078, 0x4502, 0x6003, 0x0001, - 0x6007, 0x0002, 0x1078, 0x5dd7, 0x0078, 0x7f12, 0x1078, 0x7c83, - 0x2009, 0xac8e, 0x2134, 0xa6b4, 0x00ff, 0xa686, 0x0005, 0x0040, - 0x7f13, 0xa686, 0x000b, 0x0040, 0x7f10, 0x2009, 0xac8f, 0x2104, - 0xa084, 0xff00, 0x00c0, 0x7f00, 0xa686, 0x0009, 0x0040, 0x7f13, - 0xa086, 0x1900, 0x00c0, 0x7f10, 0xa686, 0x0009, 0x0040, 0x7f13, - 0x2001, 0x0004, 0x1078, 0x4502, 0x1078, 0x772d, 0x0078, 0x7f12, - 0x1078, 0x7dff, 0x007c, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x8d16, - 0x0040, 0x7f21, 0x6838, 0xd0fc, 0x0040, 0x7f21, 0x0d7f, 0x0078, - 0x7f10, 0x6018, 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0040, - 0x7f32, 0x8001, 0x6842, 0x6017, 0x000a, 0x6007, 0x0016, 0x0d7f, - 0x0078, 0x7f12, 0x68a0, 0xa086, 0x007e, 0x00c0, 0x7f3f, 0x0e7e, - 0x2071, 0xa700, 0x1078, 0x42b8, 0x0e7f, 0x0078, 0x7f41, 0x1078, - 0x2880, 0x0d7f, 0x0078, 0x7f10, 0x1078, 0x7f8e, 0x00c0, 0x7f54, - 0x2001, 0x0004, 0x1078, 0x4502, 0x6003, 0x0001, 0x6007, 0x0003, - 0x1078, 0x5dd7, 0x0078, 0x7f58, 0x1078, 0x7c83, 0x1078, 0x7dff, - 0x007c, 0x1078, 0x7f8e, 0x00c0, 0x7f69, 0x2001, 0x0008, 0x1078, - 0x4502, 0x6003, 0x0001, 0x6007, 0x0005, 0x1078, 0x5dd7, 0x0078, - 0x7f6b, 0x1078, 0x7dff, 0x007c, 0x1078, 0x7f8e, 0x00c0, 0x7f7c, - 0x2001, 0x000a, 0x1078, 0x4502, 0x6003, 0x0001, 0x6007, 0x0001, - 0x1078, 0x5dd7, 0x0078, 0x7f7e, 0x1078, 0x7dff, 0x007c, 0x2009, - 0xac8e, 0x2104, 0xa086, 0x0003, 0x00c0, 0x7f8d, 0x2009, 0xac8f, - 0x2104, 0xa084, 0xff00, 0xa086, 0x2a00, 0x007c, 0xa085, 0x0001, - 0x007c, 0x0c7e, 0x017e, 0xac88, 0x0006, 0x2164, 0x1078, 0x45d6, - 0x017f, 0x0c7f, 0x007c, 0x0f7e, 0x0e7e, 0x0d7e, 0x037e, 0x017e, - 0x6018, 0x2068, 0x2071, 0xa733, 0x2e04, 0xa085, 0x0003, 0x2072, - 0x1078, 0x8014, 0x0040, 0x7fd9, 0x2009, 0xa733, 0x2104, 0xc0cd, - 0x200a, 0x2001, 0xa753, 0x2004, 0xd0a4, 0x0040, 0x7fc2, 0xa006, - 0x2020, 0x2009, 0x002a, 0x1078, 0xa22d, 0x2001, 0xa70c, 0x200c, - 0xc195, 0x2102, 0x2019, 0x002a, 0x2009, 0x0001, 0x1078, 0x284f, - 0x2071, 0xa700, 0x1078, 0x2677, 0x0c7e, 0x157e, 0x20a9, 0x0081, - 0x2009, 0x007f, 0x1078, 0x298e, 0x8108, 0x00f0, 0x7fd2, 0x157f, - 0x0c7f, 0x1078, 0x7f91, 0x6813, 0x00ff, 0x6817, 0xfffe, 0x2071, - 0xac80, 0x2079, 0x0100, 0x2e04, 0xa084, 0x00ff, 0x2069, 0xa71b, - 0x206a, 0x78e6, 0x007e, 0x8e70, 0x2e04, 0x2069, 0xa71c, 0x206a, - 0x78ea, 0xa084, 0xff00, 0x017f, 0xa105, 0x2009, 0xa726, 0x200a, - 0x2069, 0xac8e, 0x2071, 0xa99e, 0x6810, 0x2072, 0x6814, 0x7006, - 0x6818, 0x700a, 0x681c, 0x700e, 0x1078, 0x907e, 0x2001, 0x0006, - 0x1078, 0x4502, 0x1078, 0x28a6, 0x1078, 0x772d, 0x017f, 0x037f, - 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x027e, 0x037e, 0x0e7e, 0x157e, - 0x2019, 0xa726, 0x231c, 0x83ff, 0x0040, 0x803e, 0x2071, 0xac80, - 0x2e14, 0xa294, 0x00ff, 0x7004, 0xa084, 0xff00, 0xa205, 0xa306, - 0x00c0, 0x803e, 0x2011, 0xac96, 0xad98, 0x000a, 0x20a9, 0x0004, - 0x1078, 0x80de, 0x00c0, 0x803e, 0x2011, 0xac9a, 0xad98, 0x0006, - 0x20a9, 0x0004, 0x1078, 0x80de, 0x00c0, 0x803e, 0x157f, 0x0e7f, - 0x037f, 0x027f, 0x007c, 0x0e7e, 0x2071, 0xac8c, 0x7004, 0xa086, - 0x0014, 0x00c0, 0x8066, 0x7008, 0xa086, 0x0800, 0x00c0, 0x8066, - 0x700c, 0xd0ec, 0x0040, 0x8064, 0xa084, 0x0f00, 0xa086, 0x0100, - 0x00c0, 0x8064, 0x7024, 0xd0a4, 0x00c0, 0x8061, 0xd0ac, 0x0040, - 0x8064, 0xa006, 0x0078, 0x8066, 0xa085, 0x0001, 0x0e7f, 0x007c, - 0x0e7e, 0x0d7e, 0x0c7e, 0x077e, 0x057e, 0x047e, 0x027e, 0x007e, - 0x127e, 0x2091, 0x8000, 0x2029, 0xa9ba, 0x252c, 0x2021, 0xa9c0, - 0x2424, 0x2061, 0xae00, 0x2071, 0xa700, 0x7248, 0x7064, 0xa202, - 0x00c8, 0x80cc, 0x1078, 0xa252, 0x0040, 0x80c4, 0x671c, 0xa786, - 0x0001, 0x0040, 0x80c4, 0xa786, 0x0007, 0x0040, 0x80c4, 0x2500, - 0xac06, 0x0040, 0x80c4, 0x2400, 0xac06, 0x0040, 0x80c4, 0x0c7e, - 0x6000, 0xa086, 0x0004, 0x00c0, 0x809f, 0x1078, 0x1757, 0xa786, - 0x0008, 0x00c0, 0x80ae, 0x1078, 0x8f10, 0x00c0, 0x80ae, 0x0c7f, - 0x1078, 0x7c83, 0x1078, 0x8ed6, 0x0078, 0x80c4, 0x6010, 0x2068, - 0x1078, 0x8d16, 0x0040, 0x80c1, 0xa786, 0x0003, 0x00c0, 0x80d6, - 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x4a73, 0x1078, - 0x8ec9, 0x1078, 0x8ed6, 0x0c7f, 0xace0, 0x0010, 0x7058, 0xac02, - 0x00c8, 0x80cc, 0x0078, 0x807d, 0x127f, 0x007f, 0x027f, 0x047f, - 0x057f, 0x077f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, 0xa786, 0x0006, - 0x00c0, 0x80b8, 0x1078, 0xa1da, 0x0078, 0x80c1, 0x220c, 0x2304, - 0xa106, 0x00c0, 0x80e9, 0x8210, 0x8318, 0x00f0, 0x80de, 0xa006, - 0x007c, 0x2304, 0xa102, 0x0048, 0x80f1, 0x2001, 0x0001, 0x0078, - 0x80f3, 0x2001, 0x0000, 0xa18d, 0x0001, 0x007c, 0x6004, 0xa08a, - 0x0044, 0x10c8, 0x1332, 0x1078, 0x8efc, 0x0040, 0x8105, 0x1078, - 0x8f10, 0x0040, 0x8112, 0x0078, 0x810b, 0x1078, 0x28a6, 0x1078, - 0x8f10, 0x0040, 0x8112, 0x1078, 0x61cd, 0x1078, 0x772d, 0x1078, - 0x62d1, 0x007c, 0x1078, 0x7c83, 0x0078, 0x810b, 0xa182, 0x0040, - 0x0079, 0x811a, 0x812d, 0x812d, 0x812d, 0x812d, 0x812d, 0x812d, - 0x812d, 0x812d, 0x812d, 0x812d, 0x812d, 0x812f, 0x812f, 0x812f, - 0x812f, 0x812d, 0x812d, 0x812d, 0x812f, 0x1078, 0x1332, 0x600b, - 0xffff, 0x6003, 0x0001, 0x6106, 0x1078, 0x5d8a, 0x127e, 0x2091, - 0x8000, 0x1078, 0x62d1, 0x127f, 0x007c, 0xa186, 0x0013, 0x00c0, - 0x8146, 0x6004, 0xa082, 0x0040, 0x0079, 0x81d1, 0xa186, 0x0027, - 0x00c0, 0x8168, 0x1078, 0x61cd, 0x1078, 0x2880, 0x0d7e, 0x6110, - 0x2168, 0x1078, 0x8d16, 0x0040, 0x8162, 0x6837, 0x0103, 0x684b, - 0x0029, 0x6847, 0x0000, 0x694c, 0xc1c5, 0x694e, 0x1078, 0x4a73, - 0x1078, 0x8ec9, 0x0d7f, 0x1078, 0x772d, 0x1078, 0x62d1, 0x007c, - 0xa186, 0x0014, 0x00c0, 0x8171, 0x6004, 0xa082, 0x0040, 0x0079, - 0x8199, 0xa186, 0x0046, 0x0040, 0x817d, 0xa186, 0x0045, 0x0040, - 0x817d, 0xa186, 0x0047, 0x10c0, 0x1332, 0x2001, 0x0109, 0x2004, - 0xd084, 0x0040, 0x8196, 0x127e, 0x2091, 0x2200, 0x007e, 0x017e, - 0x027e, 0x1078, 0x5c56, 0x027f, 0x017f, 0x007f, 0x127f, 0x6000, - 0xa086, 0x0002, 0x00c0, 0x8196, 0x0078, 0x820e, 0x1078, 0x7773, - 0x007c, 0x81ae, 0x81ac, 0x81ac, 0x81ac, 0x81ac, 0x81ac, 0x81ac, - 0x81ac, 0x81ac, 0x81ac, 0x81ac, 0x81ca, 0x81ca, 0x81ca, 0x81ca, - 0x81ac, 0x81ca, 0x81ac, 0x81ca, 0x1078, 0x1332, 0x1078, 0x61cd, - 0x0d7e, 0x6110, 0x2168, 0x1078, 0x8d16, 0x0040, 0x81c4, 0x6837, - 0x0103, 0x684b, 0x0006, 0x6847, 0x0000, 0x6850, 0xc0ec, 0x6852, - 0x1078, 0x4a73, 0x1078, 0x8ec9, 0x0d7f, 0x1078, 0x772d, 0x1078, - 0x62d1, 0x007c, 0x1078, 0x61cd, 0x1078, 0x772d, 0x1078, 0x62d1, - 0x007c, 0x81e6, 0x81e4, 0x81e4, 0x81e4, 0x81e4, 0x81e4, 0x81e4, - 0x81e4, 0x81e4, 0x81e4, 0x81e4, 0x81f8, 0x81f8, 0x81f8, 0x81f8, - 0x81e4, 0x8207, 0x81e4, 0x81f8, 0x1078, 0x1332, 0x1078, 0x61cd, - 0x2001, 0xa9a4, 0x2004, 0x603e, 0x6003, 0x0002, 0x1078, 0x62d1, - 0x6010, 0xa088, 0x0013, 0x2104, 0xa085, 0x0400, 0x200a, 0x007c, - 0x1078, 0x61cd, 0x2001, 0xa9a2, 0x2004, 0x6016, 0x2001, 0xa9a4, - 0x2004, 0x603e, 0x6003, 0x000f, 0x1078, 0x62d1, 0x007c, 0x1078, - 0x61cd, 0x1078, 0x772d, 0x1078, 0x62d1, 0x007c, 0xa182, 0x0040, - 0x0079, 0x8212, 0x8225, 0x8225, 0x8225, 0x8225, 0x8225, 0x8227, - 0x8331, 0x8363, 0x8225, 0x8225, 0x8225, 0x8225, 0x8225, 0x8225, - 0x8225, 0x8225, 0x8225, 0x8225, 0x8225, 0x1078, 0x1332, 0x0e7e, - 0x0d7e, 0x603f, 0x0000, 0x2071, 0xac80, 0x7124, 0x610a, 0x2071, - 0xac8c, 0x6110, 0x2168, 0x7614, 0xa6b4, 0x0fff, 0x86ff, 0x0040, - 0x82f0, 0xa68c, 0x0c00, 0x0040, 0x8265, 0x0f7e, 0x2c78, 0x1078, - 0x4963, 0x0f7f, 0x0040, 0x8261, 0x684c, 0xd0ac, 0x0040, 0x8261, - 0x6024, 0xd0dc, 0x00c0, 0x8261, 0x6850, 0xd0bc, 0x00c0, 0x8261, - 0x7318, 0x6814, 0xa306, 0x00c0, 0x8308, 0x731c, 0x6810, 0xa31e, - 0x0040, 0x8261, 0xd6d4, 0x0040, 0x8308, 0x6b14, 0xa305, 0x00c0, - 0x8308, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186, - 0x0002, 0x0040, 0x8298, 0xa186, 0x0028, 0x00c0, 0x8275, 0x1078, - 0x8eea, 0x684b, 0x001c, 0x0078, 0x829a, 0xd6dc, 0x0040, 0x8291, - 0x684b, 0x0015, 0x684c, 0xd0ac, 0x0040, 0x828f, 0x6914, 0x6a10, - 0x2100, 0xa205, 0x0040, 0x828f, 0x7018, 0xa106, 0x00c0, 0x828c, - 0x701c, 0xa206, 0x0040, 0x828f, 0x6962, 0x6a5e, 0xc6dc, 0x0078, - 0x829a, 0xd6d4, 0x0040, 0x8298, 0x684b, 0x0007, 0x0078, 0x829a, - 0x684b, 0x0000, 0x6837, 0x0103, 0x6e46, 0xa01e, 0xd6c4, 0x0040, - 0x82c3, 0xa686, 0x0100, 0x00c0, 0x82ae, 0x2001, 0xac99, 0x2004, - 0xa005, 0x00c0, 0x82ae, 0xc6c4, 0x0078, 0x8236, 0x7328, 0x732c, - 0x6b56, 0x83ff, 0x0040, 0x82c3, 0xa38a, 0x0009, 0x0048, 0x82ba, - 0x2019, 0x0008, 0x037e, 0x2308, 0x2019, 0xac98, 0xad90, 0x0019, - 0x1078, 0x89f2, 0x037f, 0xd6cc, 0x0040, 0x831e, 0x7124, 0x695a, - 0x81ff, 0x0040, 0x831e, 0xa192, 0x0021, 0x00c8, 0x82dc, 0x2071, - 0xac98, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x1078, 0x89f2, - 0x1078, 0x9204, 0x0078, 0x831e, 0x6838, 0xd0fc, 0x0040, 0x82e5, - 0x2009, 0x0020, 0x695a, 0x0078, 0x82cf, 0x0f7e, 0x2d78, 0x1078, - 0x898a, 0x0f7f, 0x1078, 0x9204, 0x1078, 0x89df, 0x0078, 0x8320, - 0x0f7e, 0x2c78, 0x1078, 0x4963, 0x0f7f, 0x0040, 0x830e, 0x684c, - 0xd0ac, 0x0040, 0x830e, 0x6024, 0xd0dc, 0x00c0, 0x830e, 0x6850, - 0xd0bc, 0x00c0, 0x830e, 0x6810, 0x6914, 0xa105, 0x0040, 0x830e, - 0x1078, 0x8fcf, 0x0d7f, 0x0e7f, 0x0078, 0x8330, 0x684b, 0x0000, - 0x6837, 0x0103, 0x6e46, 0x684c, 0xd0ac, 0x0040, 0x831e, 0x6810, - 0x6914, 0xa115, 0x0040, 0x831e, 0x1078, 0x84e2, 0x1078, 0x4a73, - 0x6218, 0x2268, 0x6a3c, 0x82ff, 0x0040, 0x8328, 0x8211, 0x6a3e, - 0x1078, 0x8f99, 0x0d7f, 0x0e7f, 0x00c0, 0x8330, 0x1078, 0x772d, - 0x007c, 0x0f7e, 0x6003, 0x0003, 0x2079, 0xac8c, 0x7c04, 0x7b00, - 0x7e0c, 0x7d08, 0x6010, 0x2078, 0x784c, 0xd0ac, 0x0040, 0x8348, - 0x6003, 0x0002, 0x0f7f, 0x007c, 0x2130, 0x2228, 0x0078, 0x8354, - 0x2400, 0x797c, 0xa10a, 0x2300, 0x7a80, 0xa213, 0x2600, 0xa102, - 0x2500, 0xa203, 0x0048, 0x8344, 0x7c12, 0x7b16, 0x7e0a, 0x7d0e, - 0x0f7f, 0x603f, 0x0000, 0x2c10, 0x1078, 0x1cf0, 0x1078, 0x5df6, - 0x1078, 0x639b, 0x007c, 0x2001, 0xa9a4, 0x2004, 0x603e, 0x6003, - 0x0004, 0x6110, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x1078, - 0x15fa, 0x007c, 0xa182, 0x0040, 0x0079, 0x8376, 0x8389, 0x8389, - 0x8389, 0x8389, 0x8389, 0x838b, 0x8431, 0x8389, 0x8389, 0x8447, - 0x84b8, 0x8389, 0x8389, 0x8389, 0x8389, 0x84c7, 0x8389, 0x8389, - 0x8389, 0x1078, 0x1332, 0x077e, 0x0f7e, 0x0e7e, 0x0d7e, 0x2071, - 0xac8c, 0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, 0x7e46, 0x7f4c, - 0xc7e5, 0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x82ff, 0x0040, 0x83a2, - 0x8211, 0x6a3e, 0x86ff, 0x0040, 0x842c, 0xa694, 0xff00, 0xa284, - 0x0c00, 0x0040, 0x83af, 0x7018, 0x7862, 0x701c, 0x785e, 0xa284, - 0x0300, 0x0040, 0x842c, 0x1078, 0x138b, 0x1040, 0x1332, 0x2d00, - 0x784a, 0x7f4c, 0xc7cd, 0x7f4e, 0x6837, 0x0103, 0x7838, 0x683a, - 0x783c, 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x0c00, 0x0040, - 0x83cd, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186, - 0x0002, 0x0040, 0x83e9, 0xa186, 0x0028, 0x00c0, 0x83db, 0x684b, - 0x001c, 0x0078, 0x83eb, 0xd6dc, 0x0040, 0x83e2, 0x684b, 0x0015, - 0x0078, 0x83eb, 0xd6d4, 0x0040, 0x83e9, 0x684b, 0x0007, 0x0078, - 0x83eb, 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854, 0x6856, - 0xa01e, 0xd6c4, 0x0040, 0x8409, 0x7328, 0x732c, 0x6b56, 0x83ff, - 0x0040, 0x8409, 0xa38a, 0x0009, 0x0048, 0x8400, 0x2019, 0x0008, - 0x037e, 0x2308, 0x2019, 0xac98, 0xad90, 0x0019, 0x1078, 0x89f2, - 0x037f, 0xd6cc, 0x0040, 0x842c, 0x7124, 0x695a, 0x81ff, 0x0040, - 0x842c, 0xa192, 0x0021, 0x00c8, 0x8420, 0x2071, 0xac98, 0x831c, - 0x2300, 0xae18, 0xad90, 0x001d, 0x1078, 0x89f2, 0x0078, 0x842c, - 0x7838, 0xd0fc, 0x0040, 0x8429, 0x2009, 0x0020, 0x695a, 0x0078, - 0x8415, 0x2d78, 0x1078, 0x898a, 0x0d7f, 0x0e7f, 0x0f7f, 0x077f, - 0x007c, 0x0f7e, 0x6003, 0x0003, 0x2079, 0xac8c, 0x7c04, 0x7b00, - 0x7e0c, 0x7d08, 0x6010, 0x2078, 0x7c12, 0x7b16, 0x7e0a, 0x7d0e, - 0x0f7f, 0x2c10, 0x1078, 0x1cf0, 0x1078, 0x6df4, 0x007c, 0x0d7e, - 0x0f7e, 0x2c78, 0x1078, 0x4963, 0x0f7f, 0x0040, 0x8453, 0x2001, - 0xa9a4, 0x2004, 0x603e, 0x6003, 0x0002, 0x1078, 0x627a, 0x1078, - 0x639b, 0x6110, 0x2168, 0x694c, 0xd1e4, 0x0040, 0x84b6, 0xd1cc, - 0x0040, 0x848d, 0x6948, 0x6838, 0xd0fc, 0x0040, 0x8485, 0x017e, - 0x684c, 0x007e, 0x6850, 0x007e, 0xad90, 0x000d, 0xa198, 0x000d, - 0x2009, 0x0020, 0x157e, 0x21a8, 0x2304, 0x2012, 0x8318, 0x8210, - 0x00f0, 0x8474, 0x157f, 0x007f, 0x6852, 0x007f, 0x684e, 0x017f, - 0x2168, 0x1078, 0x13b4, 0x0078, 0x84b0, 0x017e, 0x1078, 0x13b4, - 0x0d7f, 0x1078, 0x89df, 0x0078, 0x84b0, 0x6837, 0x0103, 0x6944, - 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x0040, 0x84ac, 0xa086, 0x0028, - 0x00c0, 0x849e, 0x684b, 0x001c, 0x0078, 0x84ae, 0xd1dc, 0x0040, - 0x84a5, 0x684b, 0x0015, 0x0078, 0x84ae, 0xd1d4, 0x0040, 0x84ac, - 0x684b, 0x0007, 0x0078, 0x84ae, 0x684b, 0x0000, 0x1078, 0x4a73, - 0x1078, 0x8f99, 0x00c0, 0x84b6, 0x1078, 0x772d, 0x0d7f, 0x007c, - 0x2019, 0x0001, 0x1078, 0x7058, 0x6003, 0x0002, 0x2001, 0xa9a4, - 0x2004, 0x603e, 0x1078, 0x627a, 0x1078, 0x639b, 0x007c, 0x1078, - 0x627a, 0x1078, 0x2880, 0x0d7e, 0x6110, 0x2168, 0x1078, 0x8d16, - 0x0040, 0x84dc, 0x6837, 0x0103, 0x684b, 0x0029, 0x6847, 0x0000, - 0x1078, 0x4a73, 0x1078, 0x8ec9, 0x0d7f, 0x1078, 0x772d, 0x1078, - 0x639b, 0x007c, 0x684b, 0x0015, 0xd1fc, 0x0040, 0x84ee, 0x684b, - 0x0007, 0x8002, 0x8000, 0x810a, 0xa189, 0x0000, 0x6962, 0x685e, - 0x007c, 0xa182, 0x0040, 0x0079, 0x84f5, 0x8508, 0x8508, 0x8508, - 0x8508, 0x8508, 0x850a, 0x8508, 0x85e0, 0x85ec, 0x8508, 0x8508, - 0x8508, 0x8508, 0x8508, 0x8508, 0x8508, 0x8508, 0x8508, 0x8508, - 0x1078, 0x1332, 0x077e, 0x0f7e, 0x0e7e, 0x0d7e, 0x2071, 0xac8c, - 0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, 0x0f7e, 0x2c78, 0x1078, - 0x4963, 0x0f7f, 0x0040, 0x8528, 0xa684, 0x00ff, 0x00c0, 0x8528, - 0x6024, 0xd0f4, 0x0040, 0x8528, 0x1078, 0x8fcf, 0x0078, 0x85db, - 0x7e46, 0x7f4c, 0xc7e5, 0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x82ff, - 0x0040, 0x8534, 0x8211, 0x6a3e, 0x86ff, 0x0040, 0x85d0, 0xa694, - 0xff00, 0xa284, 0x0c00, 0x0040, 0x8541, 0x7018, 0x7862, 0x701c, - 0x785e, 0xa284, 0x0300, 0x0040, 0x85cd, 0xa686, 0x0100, 0x00c0, - 0x8553, 0x2001, 0xac99, 0x2004, 0xa005, 0x00c0, 0x8553, 0xc6c4, - 0x7e46, 0x0078, 0x8534, 0x1078, 0x138b, 0x1040, 0x1332, 0x2d00, - 0x784a, 0x7f4c, 0xa7bd, 0x0200, 0x7f4e, 0x6837, 0x0103, 0x7838, - 0x683a, 0x783c, 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x0c00, - 0x0040, 0x856e, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, - 0xa186, 0x0002, 0x0040, 0x858a, 0xa186, 0x0028, 0x00c0, 0x857c, - 0x684b, 0x001c, 0x0078, 0x858c, 0xd6dc, 0x0040, 0x8583, 0x684b, - 0x0015, 0x0078, 0x858c, 0xd6d4, 0x0040, 0x858a, 0x684b, 0x0007, - 0x0078, 0x858c, 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854, - 0x6856, 0xa01e, 0xd6c4, 0x0040, 0x85aa, 0x7328, 0x732c, 0x6b56, - 0x83ff, 0x0040, 0x85aa, 0xa38a, 0x0009, 0x0048, 0x85a1, 0x2019, - 0x0008, 0x037e, 0x2308, 0x2019, 0xac98, 0xad90, 0x0019, 0x1078, - 0x89f2, 0x037f, 0xd6cc, 0x0040, 0x85cd, 0x7124, 0x695a, 0x81ff, - 0x0040, 0x85cd, 0xa192, 0x0021, 0x00c8, 0x85c1, 0x2071, 0xac98, - 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x1078, 0x89f2, 0x0078, - 0x85cd, 0x7838, 0xd0fc, 0x0040, 0x85ca, 0x2009, 0x0020, 0x695a, - 0x0078, 0x85b6, 0x2d78, 0x1078, 0x898a, 0xd6dc, 0x00c0, 0x85d3, - 0xa006, 0x0078, 0x85d9, 0x2001, 0x0001, 0x2071, 0xac8c, 0x7218, - 0x731c, 0x1078, 0x1653, 0x0d7f, 0x0e7f, 0x0f7f, 0x077f, 0x007c, - 0x2001, 0xa9a4, 0x2004, 0x603e, 0x20e1, 0x0005, 0x3d18, 0x3e20, - 0x2c10, 0x1078, 0x15fa, 0x007c, 0x2001, 0xa9a4, 0x2004, 0x603e, - 0x0d7e, 0x6003, 0x0002, 0x6110, 0x2168, 0x694c, 0xd1e4, 0x0040, - 0x871c, 0x603f, 0x0000, 0x0f7e, 0x2c78, 0x1078, 0x4963, 0x0f7f, - 0x0040, 0x8632, 0x6814, 0x6910, 0xa115, 0x0040, 0x8632, 0x6a60, - 0xa206, 0x00c0, 0x860f, 0x685c, 0xa106, 0x0040, 0x8632, 0x684c, - 0xc0e4, 0x684e, 0x6847, 0x0000, 0x6863, 0x0000, 0x685f, 0x0000, - 0x6024, 0xd0f4, 0x00c0, 0x8627, 0x697c, 0x6810, 0xa102, 0x603a, - 0x6980, 0x6814, 0xa103, 0x6036, 0x6024, 0xc0f5, 0x6026, 0x0d7e, - 0x6018, 0x2068, 0x683c, 0x8000, 0x683e, 0x0d7f, 0x1078, 0x8fcf, - 0x0078, 0x871c, 0x694c, 0xd1cc, 0x0040, 0x86e1, 0x6948, 0x6838, - 0xd0fc, 0x0040, 0x8699, 0x017e, 0x684c, 0x007e, 0x6850, 0x007e, - 0x0f7e, 0x2178, 0x7944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x0040, - 0x866c, 0xa086, 0x0028, 0x00c0, 0x8653, 0x684b, 0x001c, 0x784b, - 0x001c, 0x0078, 0x8677, 0xd1dc, 0x0040, 0x8663, 0x684b, 0x0015, - 0x784b, 0x0015, 0x1078, 0x917c, 0x0040, 0x8661, 0x7944, 0xc1dc, - 0x7946, 0x0078, 0x8677, 0xd1d4, 0x0040, 0x866c, 0x684b, 0x0007, - 0x784b, 0x0007, 0x0078, 0x8677, 0x684c, 0xd0ac, 0x0040, 0x8677, - 0x6810, 0x6914, 0xa115, 0x0040, 0x8677, 0x1078, 0x84e2, 0x6848, - 0x784a, 0x6860, 0x7862, 0x685c, 0x785e, 0xad90, 0x000d, 0xaf98, - 0x000d, 0x2009, 0x0020, 0x157e, 0x21a8, 0x2304, 0x2012, 0x8318, - 0x8210, 0x00f0, 0x8685, 0x157f, 0x0f7f, 0x007f, 0x6852, 0x007f, - 0x684e, 0x1078, 0x9204, 0x017f, 0x2168, 0x1078, 0x13b4, 0x0078, - 0x8716, 0x017e, 0x0f7e, 0x2178, 0x7944, 0xa184, 0x00ff, 0xa0b6, - 0x0002, 0x0040, 0x86c6, 0xa086, 0x0028, 0x00c0, 0x86ad, 0x684b, - 0x001c, 0x784b, 0x001c, 0x0078, 0x86d1, 0xd1dc, 0x0040, 0x86bd, - 0x684b, 0x0015, 0x784b, 0x0015, 0x1078, 0x917c, 0x0040, 0x86bb, - 0x7944, 0xc1dc, 0x7946, 0x0078, 0x86d1, 0xd1d4, 0x0040, 0x86c6, - 0x684b, 0x0007, 0x784b, 0x0007, 0x0078, 0x86d1, 0x684c, 0xd0ac, - 0x0040, 0x86d1, 0x6810, 0x6914, 0xa115, 0x0040, 0x86d1, 0x1078, - 0x84e2, 0x6860, 0x7862, 0x685c, 0x785e, 0x684c, 0x784e, 0x0f7f, - 0x1078, 0x13b4, 0x0d7f, 0x1078, 0x9204, 0x1078, 0x89df, 0x0078, - 0x8716, 0x6837, 0x0103, 0x6944, 0xa184, 0x00ff, 0xa0b6, 0x0002, - 0x0040, 0x8707, 0xa086, 0x0028, 0x00c0, 0x86f2, 0x684b, 0x001c, - 0x0078, 0x8714, 0xd1dc, 0x0040, 0x8700, 0x684b, 0x0015, 0x1078, - 0x917c, 0x0040, 0x86fe, 0x6944, 0xc1dc, 0x6946, 0x0078, 0x8714, - 0xd1d4, 0x0040, 0x8707, 0x684b, 0x0007, 0x0078, 0x8714, 0x684b, - 0x0000, 0x684c, 0xd0ac, 0x0040, 0x8714, 0x6810, 0x6914, 0xa115, - 0x0040, 0x8714, 0x1078, 0x84e2, 0x1078, 0x4a73, 0x1078, 0x8f99, - 0x00c0, 0x871c, 0x1078, 0x772d, 0x0d7f, 0x007c, 0x1078, 0x61cd, - 0x0078, 0x8724, 0x1078, 0x627a, 0x1078, 0x8d16, 0x0040, 0x8743, - 0x0d7e, 0x6110, 0x2168, 0x6837, 0x0103, 0x2009, 0xa70c, 0x210c, - 0xd18c, 0x00c0, 0x874e, 0xd184, 0x00c0, 0x874a, 0x6108, 0x694a, - 0xa18e, 0x0029, 0x00c0, 0x873e, 0x1078, 0xa4f2, 0x6847, 0x0000, - 0x1078, 0x4a73, 0x0d7f, 0x1078, 0x772d, 0x1078, 0x62d1, 0x1078, - 0x639b, 0x007c, 0x684b, 0x0004, 0x0078, 0x873e, 0x684b, 0x0004, - 0x0078, 0x873e, 0xa182, 0x0040, 0x0079, 0x8756, 0x8769, 0x8769, - 0x8769, 0x8769, 0x8769, 0x876b, 0x8769, 0x876e, 0x8769, 0x8769, - 0x8769, 0x8769, 0x8769, 0x8769, 0x8769, 0x8769, 0x8769, 0x8769, - 0x8769, 0x1078, 0x1332, 0x1078, 0x772d, 0x007c, 0x007e, 0x027e, - 0xa016, 0x1078, 0x15fa, 0x027f, 0x007f, 0x007c, 0xa182, 0x0085, - 0x0079, 0x877a, 0x8783, 0x8781, 0x8781, 0x878f, 0x8781, 0x8781, - 0x8781, 0x1078, 0x1332, 0x6003, 0x0001, 0x6106, 0x1078, 0x5d8a, - 0x127e, 0x2091, 0x8000, 0x1078, 0x62d1, 0x127f, 0x007c, 0x027e, - 0x057e, 0x0d7e, 0x0e7e, 0x2071, 0xac80, 0x7224, 0x6212, 0x7220, - 0x1078, 0x8d02, 0x0040, 0x87b4, 0x2268, 0x6800, 0xa086, 0x0000, - 0x0040, 0x87b4, 0x6018, 0x6d18, 0xa52e, 0x00c0, 0x87b4, 0x0c7e, - 0x2d60, 0x1078, 0x8a03, 0x0c7f, 0x0040, 0x87b4, 0x6803, 0x0002, - 0x6007, 0x0086, 0x0078, 0x87b6, 0x6007, 0x0087, 0x6003, 0x0001, - 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0f7e, 0x2278, 0x1078, 0x4963, - 0x0f7f, 0x0040, 0x87ce, 0x6824, 0xd0ec, 0x0040, 0x87ce, 0x0c7e, - 0x2260, 0x603f, 0x0000, 0x1078, 0x8fcf, 0x0c7f, 0x0e7f, 0x0d7f, - 0x057f, 0x027f, 0x007c, 0xa186, 0x0013, 0x00c0, 0x87e4, 0x6004, - 0xa08a, 0x0085, 0x1048, 0x1332, 0xa08a, 0x008c, 0x10c8, 0x1332, - 0xa082, 0x0085, 0x0079, 0x87f3, 0xa186, 0x0027, 0x0040, 0x87ec, - 0xa186, 0x0014, 0x10c0, 0x1332, 0x1078, 0x61cd, 0x1078, 0x8ed6, - 0x1078, 0x62d1, 0x007c, 0x87fa, 0x87fc, 0x87fc, 0x87fa, 0x87fa, - 0x87fa, 0x87fa, 0x1078, 0x1332, 0x1078, 0x61cd, 0x1078, 0x8ed6, - 0x1078, 0x62d1, 0x007c, 0xa186, 0x0013, 0x00c0, 0x880d, 0x6004, - 0xa082, 0x0085, 0x2008, 0x0078, 0x8848, 0xa186, 0x0027, 0x00c0, - 0x8830, 0x1078, 0x61cd, 0x1078, 0x2880, 0x0d7e, 0x6010, 0x2068, - 0x1078, 0x8d16, 0x0040, 0x8826, 0x6837, 0x0103, 0x6847, 0x0000, - 0x684b, 0x0029, 0x1078, 0x4a73, 0x1078, 0x8ec9, 0x0d7f, 0x1078, - 0x772d, 0x1078, 0x62d1, 0x007c, 0x1078, 0x7773, 0x0078, 0x882b, - 0xa186, 0x0014, 0x00c0, 0x882c, 0x1078, 0x61cd, 0x0d7e, 0x6010, - 0x2068, 0x1078, 0x8d16, 0x0040, 0x8826, 0x6837, 0x0103, 0x6847, - 0x0000, 0x684b, 0x0006, 0x6850, 0xc0ec, 0x6852, 0x0078, 0x8822, - 0x0079, 0x884a, 0x8853, 0x8851, 0x8851, 0x8851, 0x8851, 0x8851, - 0x886e, 0x1078, 0x1332, 0x1078, 0x61cd, 0x6030, 0xa08c, 0xff00, - 0x810f, 0xa186, 0x0039, 0x0040, 0x8861, 0xa186, 0x0035, 0x00c0, - 0x8865, 0x2001, 0xa9a2, 0x0078, 0x8867, 0x2001, 0xa9a3, 0x2004, - 0x6016, 0x6003, 0x000c, 0x1078, 0x62d1, 0x007c, 0x1078, 0x61cd, - 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0040, 0x887c, - 0xa186, 0x0035, 0x00c0, 0x8880, 0x2001, 0xa9a2, 0x0078, 0x8882, - 0x2001, 0xa9a3, 0x2004, 0x6016, 0x6003, 0x000e, 0x1078, 0x62d1, - 0x007c, 0xa182, 0x008c, 0x00c8, 0x8893, 0xa182, 0x0085, 0x0048, - 0x8893, 0x0079, 0x8896, 0x1078, 0x7773, 0x007c, 0x889d, 0x889d, - 0x889d, 0x889d, 0x889f, 0x88fc, 0x889d, 0x1078, 0x1332, 0x0f7e, - 0x2c78, 0x1078, 0x4963, 0x0f7f, 0x0040, 0x88b2, 0x6030, 0xa08c, - 0xff00, 0x810f, 0xa186, 0x0039, 0x0040, 0x8913, 0xa186, 0x0035, - 0x0040, 0x8913, 0x0d7e, 0x1078, 0x8d16, 0x00c0, 0x88bb, 0x1078, - 0x8ec9, 0x0078, 0x88de, 0x6010, 0x2068, 0x684c, 0xd0e4, 0x00c0, - 0x88c3, 0x1078, 0x8ec9, 0x6837, 0x0103, 0x6850, 0xd0b4, 0x0040, - 0x88cf, 0x684b, 0x0006, 0xc0ec, 0x6852, 0x0078, 0x88da, 0xd0bc, - 0x0040, 0x88d6, 0x684b, 0x0002, 0x0078, 0x88da, 0x684b, 0x0005, - 0x1078, 0x8f95, 0x6847, 0x0000, 0x1078, 0x4a73, 0x2c68, 0x1078, - 0x76c7, 0x0040, 0x88f7, 0x6003, 0x0001, 0x6007, 0x001e, 0x2009, - 0xac8e, 0x210c, 0x6136, 0x2009, 0xac8f, 0x210c, 0x613a, 0x6918, - 0x611a, 0x6920, 0x6122, 0x601f, 0x0001, 0x1078, 0x5d8a, 0x2d60, - 0x1078, 0x772d, 0x0d7f, 0x007c, 0x0f7e, 0x2c78, 0x1078, 0x4963, - 0x0f7f, 0x0040, 0x8939, 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, - 0x0035, 0x0040, 0x8913, 0xa186, 0x001e, 0x0040, 0x8913, 0xa186, - 0x0039, 0x00c0, 0x8939, 0x0d7e, 0x2c68, 0x1078, 0x91cc, 0x00c0, - 0x895d, 0x1078, 0x76c7, 0x0040, 0x8936, 0x6106, 0x6003, 0x0001, - 0x601f, 0x0001, 0x6918, 0x611a, 0x6928, 0x612a, 0x692c, 0x612e, - 0x6930, 0xa18c, 0x00ff, 0x6132, 0x6934, 0x6136, 0x6938, 0x613a, - 0x6920, 0x6122, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x2d60, 0x0078, - 0x895d, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x8d16, 0x0040, 0x895d, - 0x6837, 0x0103, 0x6850, 0xd0b4, 0x0040, 0x894c, 0xc0ec, 0x6852, - 0x684b, 0x0006, 0x0078, 0x8957, 0xd0bc, 0x0040, 0x8953, 0x684b, - 0x0002, 0x0078, 0x8957, 0x684b, 0x0005, 0x1078, 0x8f95, 0x6847, - 0x0000, 0x1078, 0x4a73, 0x1078, 0x8ec9, 0x0d7f, 0x1078, 0x772d, - 0x007c, 0x017e, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x8d16, 0x0040, - 0x8971, 0x6837, 0x0103, 0x684b, 0x0028, 0x6847, 0x0000, 0x1078, - 0x4a73, 0x0d7f, 0x017f, 0xa186, 0x0013, 0x0040, 0x8983, 0xa186, - 0x0014, 0x0040, 0x8983, 0xa186, 0x0027, 0x0040, 0x8983, 0x1078, - 0x7773, 0x0078, 0x8989, 0x1078, 0x61cd, 0x1078, 0x8ed6, 0x1078, - 0x62d1, 0x007c, 0x057e, 0x067e, 0x0d7e, 0x0f7e, 0x2029, 0x0001, - 0xa182, 0x0101, 0x00c8, 0x8996, 0x0078, 0x8998, 0x2009, 0x0100, - 0x2130, 0x2069, 0xac98, 0x831c, 0x2300, 0xad18, 0x2009, 0x0020, - 0xaf90, 0x001d, 0x1078, 0x89f2, 0xa6b2, 0x0020, 0x7804, 0xa06d, - 0x0040, 0x89ac, 0x1078, 0x13b4, 0x1078, 0x138b, 0x0040, 0x89d6, - 0x8528, 0x6837, 0x0110, 0x683b, 0x0000, 0x2d20, 0x7c06, 0xa68a, - 0x003d, 0x00c8, 0x89c2, 0x2608, 0xad90, 0x000f, 0x1078, 0x89f2, - 0x0078, 0x89d6, 0xa6b2, 0x003c, 0x2009, 0x003c, 0x2d78, 0xad90, - 0x000f, 0x1078, 0x89f2, 0x0078, 0x89ac, 0x0f7f, 0x852f, 0xa5ad, - 0x0003, 0x7d36, 0xa5ac, 0x0000, 0x0078, 0x89db, 0x0f7f, 0x852f, - 0xa5ad, 0x0003, 0x7d36, 0x0d7f, 0x067f, 0x057f, 0x007c, 0x0f7e, - 0x8dff, 0x0040, 0x89f0, 0x6804, 0xa07d, 0x0040, 0x89ee, 0x6807, - 0x0000, 0x1078, 0x4a73, 0x2f68, 0x0078, 0x89e3, 0x1078, 0x4a73, - 0x0f7f, 0x007c, 0x157e, 0xa184, 0x0001, 0x0040, 0x89f8, 0x8108, - 0x810c, 0x21a8, 0x2304, 0x8007, 0x2012, 0x8318, 0x8210, 0x00f0, - 0x89fa, 0x157f, 0x007c, 0x067e, 0x127e, 0x2091, 0x8000, 0x2031, - 0x0001, 0x601c, 0xa084, 0x000f, 0x1079, 0x8a1f, 0x127f, 0x067f, - 0x007c, 0x127e, 0x2091, 0x8000, 0x067e, 0x2031, 0x0000, 0x601c, - 0xa084, 0x000f, 0x1079, 0x8a1f, 0x067f, 0x127f, 0x007c, 0x8a39, - 0x8a27, 0x8a34, 0x8a55, 0x8a27, 0x8a34, 0x8a55, 0x8a34, 0x1078, - 0x1332, 0x037e, 0x2019, 0x0010, 0x1078, 0x9dd7, 0x601f, 0x0006, - 0x6003, 0x0007, 0x037f, 0x007c, 0xa006, 0x007c, 0xa085, 0x0001, - 0x007c, 0x0d7e, 0x86ff, 0x00c0, 0x8a50, 0x6010, 0x2068, 0x1078, - 0x8d16, 0x0040, 0x8a52, 0xa00e, 0x2001, 0x0005, 0x1078, 0x4b51, - 0x1078, 0x8f95, 0x1078, 0x4a73, 0x1078, 0x772d, 0xa085, 0x0001, - 0x0d7f, 0x007c, 0xa006, 0x0078, 0x8a50, 0x6000, 0xa08a, 0x0010, - 0x10c8, 0x1332, 0x1079, 0x8a5d, 0x007c, 0x8a6d, 0x8a92, 0x8a6f, - 0x8ab5, 0x8a8e, 0x8a6d, 0x8a34, 0x8a39, 0x8a39, 0x8a34, 0x8a34, - 0x8a34, 0x8a34, 0x8a34, 0x8a34, 0x8a34, 0x1078, 0x1332, 0x86ff, - 0x00c0, 0x8a8b, 0x601c, 0xa086, 0x0006, 0x0040, 0x8a8b, 0x0d7e, - 0x6010, 0x2068, 0x1078, 0x8d16, 0x0040, 0x8a80, 0x1078, 0x8f95, - 0x0d7f, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x1078, - 0x5d8a, 0x1078, 0x62d1, 0xa085, 0x0001, 0x007c, 0x1078, 0x1757, - 0x0078, 0x8a6f, 0x0e7e, 0x2071, 0xa9b1, 0x7024, 0xac06, 0x00c0, - 0x8a9b, 0x1078, 0x6fc4, 0x601c, 0xa084, 0x000f, 0xa086, 0x0006, - 0x00c0, 0x8aad, 0x087e, 0x097e, 0x2049, 0x0001, 0x2c40, 0x1078, - 0x7246, 0x097f, 0x087f, 0x0078, 0x8aaf, 0x1078, 0x6ebe, 0x0e7f, - 0x00c0, 0x8a6f, 0x1078, 0x8a34, 0x007c, 0x037e, 0x0e7e, 0x2071, - 0xa9b1, 0x703c, 0xac06, 0x00c0, 0x8ac5, 0x2019, 0x0000, 0x1078, - 0x7058, 0x0e7f, 0x037f, 0x0078, 0x8a6f, 0x1078, 0x738a, 0x0e7f, - 0x037f, 0x00c0, 0x8a6f, 0x1078, 0x8a34, 0x007c, 0x0c7e, 0x601c, - 0xa084, 0x000f, 0x1079, 0x8ad6, 0x0c7f, 0x007c, 0x8ae5, 0x8b57, - 0x8c8f, 0x8af0, 0x8ed6, 0x8ae5, 0x9dc8, 0x772d, 0x8b57, 0x1078, - 0x8f10, 0x00c0, 0x8ae5, 0x1078, 0x7c83, 0x007c, 0x1078, 0x61cd, - 0x1078, 0x62d1, 0x1078, 0x772d, 0x007c, 0x6017, 0x0001, 0x007c, - 0x1078, 0x8d16, 0x0040, 0x8af8, 0x6010, 0xa080, 0x0019, 0x2c02, - 0x6000, 0xa08a, 0x0010, 0x10c8, 0x1332, 0x1079, 0x8b00, 0x007c, - 0x8b10, 0x8b12, 0x8b34, 0x8b46, 0x8b53, 0x8b10, 0x8ae5, 0x8ae5, - 0x8ae5, 0x8b46, 0x8b46, 0x8b10, 0x8b10, 0x8b10, 0x8b10, 0x8b50, - 0x1078, 0x1332, 0x0e7e, 0x6010, 0x2070, 0x7050, 0xc0b5, 0x7052, - 0x2071, 0xa9b1, 0x7024, 0xac06, 0x0040, 0x8b30, 0x1078, 0x6ebe, - 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x2001, 0xa9a3, - 0x2004, 0x6016, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0e7f, 0x007c, - 0x6017, 0x0001, 0x0078, 0x8b2e, 0x0d7e, 0x6010, 0x2068, 0x6850, - 0xc0b5, 0x6852, 0x0d7f, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, - 0x0002, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x007c, 0x0d7e, 0x6017, - 0x0001, 0x6010, 0x2068, 0x6850, 0xc0b5, 0x6852, 0x0d7f, 0x007c, - 0x1078, 0x772d, 0x007c, 0x1078, 0x1757, 0x0078, 0x8b34, 0x6000, - 0xa08a, 0x0010, 0x10c8, 0x1332, 0x1079, 0x8b5f, 0x007c, 0x8b6f, - 0x8aed, 0x8b71, 0x8b6f, 0x8b71, 0x8b71, 0x8ae6, 0x8b6f, 0x8adf, - 0x8adf, 0x8b6f, 0x8b6f, 0x8b6f, 0x8b6f, 0x8b6f, 0x8b6f, 0x1078, - 0x1332, 0x0d7e, 0x6018, 0x2068, 0x6804, 0xa084, 0x00ff, 0x0d7f, - 0xa08a, 0x000c, 0x10c8, 0x1332, 0x1079, 0x8b7f, 0x007c, 0x8b8b, - 0x8c33, 0x8b8d, 0x8bcd, 0x8b8d, 0x8bcd, 0x8b8d, 0x8b9a, 0x8b8b, - 0x8bcd, 0x8b8b, 0x8bb7, 0x1078, 0x1332, 0x6004, 0xa08e, 0x0016, - 0x0040, 0x8bc8, 0xa08e, 0x0004, 0x0040, 0x8bc8, 0xa08e, 0x0002, - 0x0040, 0x8bc8, 0x6004, 0x1078, 0x8f10, 0x0040, 0x8c4e, 0xa08e, - 0x0021, 0x0040, 0x8c52, 0xa08e, 0x0022, 0x0040, 0x8c4e, 0xa08e, - 0x003d, 0x0040, 0x8c52, 0xa08e, 0x0039, 0x0040, 0x8c56, 0xa08e, - 0x0035, 0x0040, 0x8c56, 0xa08e, 0x001e, 0x0040, 0x8bca, 0xa08e, - 0x0001, 0x00c0, 0x8bc6, 0x0d7e, 0x6018, 0x2068, 0x6804, 0xa084, - 0x00ff, 0x0d7f, 0xa086, 0x0006, 0x0040, 0x8bc8, 0x1078, 0x2880, - 0x1078, 0x7c83, 0x1078, 0x8ed6, 0x007c, 0x0c7e, 0x0d7e, 0x6104, - 0xa186, 0x0016, 0x0040, 0x8c23, 0xa186, 0x0002, 0x00c0, 0x8bf6, - 0x6018, 0x2068, 0x68a0, 0xd0bc, 0x00c0, 0x8c7a, 0x6840, 0xa084, - 0x00ff, 0xa005, 0x0040, 0x8bf6, 0x8001, 0x6842, 0x6013, 0x0000, - 0x601f, 0x0007, 0x6017, 0x0398, 0x1078, 0x76c7, 0x0040, 0x8bf6, - 0x2d00, 0x601a, 0x601f, 0x0001, 0x0078, 0x8c23, 0x0d7f, 0x0c7f, - 0x6004, 0xa08e, 0x0002, 0x00c0, 0x8c14, 0x6018, 0xa080, 0x0028, - 0x2004, 0xa086, 0x007e, 0x00c0, 0x8c14, 0x2009, 0xa733, 0x2104, - 0xc085, 0x200a, 0x0e7e, 0x2071, 0xa700, 0x1078, 0x42b8, 0x0e7f, - 0x1078, 0x7c83, 0x0078, 0x8c18, 0x1078, 0x7c83, 0x1078, 0x2880, - 0x0e7e, 0x127e, 0x2091, 0x8000, 0x1078, 0x28a6, 0x127f, 0x0e7f, - 0x1078, 0x8ed6, 0x007c, 0x2001, 0x0002, 0x1078, 0x4502, 0x6003, - 0x0001, 0x6007, 0x0002, 0x1078, 0x5dd7, 0x1078, 0x62d1, 0x0d7f, - 0x0c7f, 0x0078, 0x8c22, 0x0c7e, 0x0d7e, 0x6104, 0xa186, 0x0016, - 0x0040, 0x8c23, 0x6018, 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, - 0x0040, 0x8bf6, 0x8001, 0x6842, 0x6003, 0x0001, 0x1078, 0x5dd7, - 0x1078, 0x62d1, 0x0d7f, 0x0c7f, 0x0078, 0x8c22, 0x1078, 0x7c83, - 0x0078, 0x8bca, 0x1078, 0x7ca6, 0x0078, 0x8bca, 0x0d7e, 0x2c68, - 0x6104, 0x1078, 0x91cc, 0x0d7f, 0x0040, 0x8c62, 0x1078, 0x772d, - 0x0078, 0x8c79, 0x6004, 0x8007, 0x6130, 0xa18c, 0x00ff, 0xa105, - 0x6032, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x6038, - 0x600a, 0x2001, 0xa9a3, 0x2004, 0x6016, 0x1078, 0x5d8a, 0x1078, - 0x62d1, 0x007c, 0x0d7f, 0x0c7f, 0x1078, 0x7c83, 0x1078, 0x2880, - 0x0e7e, 0x127e, 0x2091, 0x8000, 0x1078, 0x28a6, 0x6013, 0x0000, - 0x601f, 0x0007, 0x6017, 0x0398, 0x127f, 0x0e7f, 0x007c, 0x6000, - 0xa08a, 0x0010, 0x10c8, 0x1332, 0x1079, 0x8c97, 0x007c, 0x8ca7, - 0x8ca7, 0x8ca7, 0x8ca7, 0x8ca7, 0x8ca7, 0x8ca7, 0x8ca7, 0x8ca7, - 0x8ae5, 0x8ca7, 0x8aed, 0x8ca9, 0x8aed, 0x8cb7, 0x8ca7, 0x1078, - 0x1332, 0x6004, 0xa086, 0x008b, 0x0040, 0x8cb7, 0x6007, 0x008b, - 0x6003, 0x000d, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x007c, 0x1078, - 0x8ec9, 0x1078, 0x8d16, 0x0040, 0x8cef, 0x1078, 0x2880, 0x0d7e, - 0x1078, 0x8d16, 0x0040, 0x8cd1, 0x6010, 0x2068, 0x6837, 0x0103, - 0x684b, 0x0006, 0x6847, 0x0000, 0x6850, 0xc0ed, 0x6852, 0x1078, - 0x4a73, 0x2c68, 0x1078, 0x76c7, 0x0040, 0x8cdf, 0x6818, 0x601a, - 0x0c7e, 0x2d60, 0x1078, 0x8ed6, 0x0c7f, 0x0078, 0x8ce0, 0x2d60, - 0x0d7f, 0x6013, 0x0000, 0x601f, 0x0001, 0x6007, 0x0001, 0x6003, - 0x0001, 0x1078, 0x5dd7, 0x1078, 0x62d1, 0x0078, 0x8d01, 0x6030, - 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0040, 0x8cfb, 0xa186, - 0x0035, 0x00c0, 0x8cff, 0x1078, 0x2880, 0x0078, 0x8cd1, 0x1078, - 0x8ed6, 0x007c, 0xa284, 0x000f, 0x00c0, 0x8d13, 0xa282, 0xae00, - 0x0048, 0x8d13, 0x2001, 0xa716, 0x2004, 0xa202, 0x00c8, 0x8d13, - 0xa085, 0x0001, 0x007c, 0xa006, 0x0078, 0x8d12, 0x027e, 0x0e7e, - 0x2071, 0xa700, 0x6210, 0x705c, 0xa202, 0x0048, 0x8d28, 0x7060, - 0xa202, 0x00c8, 0x8d28, 0xa085, 0x0001, 0x0e7f, 0x027f, 0x007c, - 0xa006, 0x0078, 0x8d25, 0x0e7e, 0x0c7e, 0x037e, 0x007e, 0x127e, - 0x2091, 0x8000, 0x2061, 0xae00, 0x2071, 0xa700, 0x7348, 0x7064, - 0xa302, 0x00c8, 0x8d55, 0x601c, 0xa206, 0x00c0, 0x8d4d, 0x1078, - 0x903b, 0x0040, 0x8d4d, 0x1078, 0x8f10, 0x00c0, 0x8d49, 0x1078, - 0x7c83, 0x0c7e, 0x1078, 0x772d, 0x0c7f, 0xace0, 0x0010, 0x7058, - 0xac02, 0x00c8, 0x8d55, 0x0078, 0x8d36, 0x127f, 0x007f, 0x037f, - 0x0c7f, 0x0e7f, 0x007c, 0x0e7e, 0x0c7e, 0x017e, 0xa188, 0xa835, - 0x210c, 0x81ff, 0x0040, 0x8d69, 0x2061, 0xaab3, 0x611a, 0x1078, - 0x2880, 0xa006, 0x0078, 0x8d6e, 0xa085, 0x0001, 0x017f, 0x0c7f, - 0x0e7f, 0x007c, 0x0c7e, 0x057e, 0x127e, 0x2091, 0x8000, 0x0c7e, - 0x1078, 0x76c7, 0x057f, 0x0040, 0x8d8b, 0x6612, 0x651a, 0x601f, - 0x0003, 0x2009, 0x004b, 0x1078, 0x775c, 0xa085, 0x0001, 0x127f, - 0x057f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x8d87, 0x0c7e, 0x057e, - 0x127e, 0x2091, 0x8000, 0x62a0, 0x0c7e, 0x1078, 0x76c7, 0x057f, - 0x0040, 0x8db9, 0x6013, 0x0000, 0x651a, 0x601f, 0x0003, 0x0c7e, - 0x2560, 0x1078, 0x47e9, 0x0c7f, 0x1078, 0x5f01, 0x077e, 0x2039, - 0x0000, 0x1078, 0x5e0a, 0x2c08, 0x1078, 0x9f9b, 0x077f, 0x2009, - 0x004c, 0x1078, 0x775c, 0xa085, 0x0001, 0x127f, 0x057f, 0x0c7f, - 0x007c, 0xa006, 0x0078, 0x8db5, 0x0f7e, 0x0c7e, 0x047e, 0x0c7e, - 0x1078, 0x76c7, 0x2c78, 0x0c7f, 0x0040, 0x8dd6, 0x7e12, 0x2c00, - 0x781a, 0x781f, 0x0003, 0x2021, 0x0005, 0x1078, 0x8e21, 0x2f60, - 0x2009, 0x004d, 0x1078, 0x775c, 0xa085, 0x0001, 0x047f, 0x0c7f, - 0x0f7f, 0x007c, 0x0f7e, 0x0c7e, 0x047e, 0x0c7e, 0x1078, 0x76c7, - 0x2c78, 0x0c7f, 0x0040, 0x8df4, 0x7e12, 0x2c00, 0x781a, 0x781f, - 0x0003, 0x2021, 0x0005, 0x1078, 0x8e21, 0x2f60, 0x2009, 0x004e, - 0x1078, 0x775c, 0xa085, 0x0001, 0x047f, 0x0c7f, 0x0f7f, 0x007c, - 0x0f7e, 0x0c7e, 0x047e, 0x0c7e, 0x1078, 0x76c7, 0x2c78, 0x0c7f, - 0x0040, 0x8e1d, 0x7e12, 0x2c00, 0x781a, 0x781f, 0x0003, 0x2021, - 0x0004, 0x1078, 0x8e21, 0x2001, 0xa99d, 0x2004, 0xd0fc, 0x0040, - 0x8e16, 0x2f60, 0x1078, 0x772d, 0x0078, 0x8e1b, 0x2f60, 0x2009, - 0x0052, 0x1078, 0x775c, 0xa085, 0x0001, 0x047f, 0x0c7f, 0x0f7f, - 0x007c, 0x097e, 0x077e, 0x127e, 0x2091, 0x8000, 0x1078, 0x4775, - 0x0040, 0x8e2e, 0x2001, 0x8e26, 0x0078, 0x8e34, 0x1078, 0x4739, - 0x0040, 0x8e3d, 0x2001, 0x8e2e, 0x007e, 0xa00e, 0x2400, 0x1078, - 0x4b51, 0x1078, 0x4a73, 0x007f, 0x007a, 0x2418, 0x1078, 0x6161, - 0x62a0, 0x087e, 0x2041, 0x0001, 0x2039, 0x0001, 0x2608, 0x1078, - 0x5f1b, 0x087f, 0x1078, 0x5e0a, 0x2f08, 0x2648, 0x1078, 0x9f9b, - 0x613c, 0x81ff, 0x1040, 0x5fdb, 0x1078, 0x62d1, 0x127f, 0x077f, - 0x097f, 0x007c, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078, - 0x76c7, 0x017f, 0x0040, 0x8e73, 0x660a, 0x611a, 0x601f, 0x0001, - 0x2d00, 0x6012, 0x2009, 0x001f, 0x1078, 0x775c, 0xa085, 0x0001, - 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x8e70, 0x0c7e, 0x127e, - 0x2091, 0x8000, 0x0c7e, 0x1078, 0x76c7, 0x017f, 0x0040, 0x8e8f, - 0x660a, 0x611a, 0x601f, 0x0008, 0x2d00, 0x6012, 0x2009, 0x0021, - 0x1078, 0x775c, 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, - 0x0078, 0x8e8c, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078, - 0x76c7, 0x017f, 0x0040, 0x8eab, 0x660a, 0x611a, 0x601f, 0x0001, - 0x2d00, 0x6012, 0x2009, 0x003d, 0x1078, 0x775c, 0xa085, 0x0001, - 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x8ea8, 0x0c7e, 0x127e, - 0x2091, 0x8000, 0x0c7e, 0x1078, 0x76c7, 0x017f, 0x0040, 0x8ec6, - 0x611a, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x0000, 0x1078, - 0x775c, 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078, - 0x8ec3, 0x027e, 0x0d7e, 0x6218, 0x2268, 0x6a3c, 0x82ff, 0x0040, - 0x8ed3, 0x8211, 0x6a3e, 0x0d7f, 0x027f, 0x007c, 0x007e, 0x6000, - 0xa086, 0x0000, 0x0040, 0x8ee8, 0x6013, 0x0000, 0x601f, 0x0007, - 0x2001, 0xa9a3, 0x2004, 0x6016, 0x1078, 0xa4a5, 0x603f, 0x0000, - 0x007f, 0x007c, 0x067e, 0x0c7e, 0x0d7e, 0x2031, 0xa753, 0x2634, - 0xd6e4, 0x0040, 0x8ef8, 0x6618, 0x2660, 0x6e48, 0x1078, 0x46e7, - 0x0d7f, 0x0c7f, 0x067f, 0x007c, 0x007e, 0x017e, 0x6004, 0xa08e, - 0x0002, 0x0040, 0x8f0d, 0xa08e, 0x0003, 0x0040, 0x8f0d, 0xa08e, - 0x0004, 0x0040, 0x8f0d, 0xa085, 0x0001, 0x017f, 0x007f, 0x007c, - 0x007e, 0x0d7e, 0x6010, 0xa06d, 0x0040, 0x8f1d, 0x6838, 0xd0fc, - 0x0040, 0x8f1d, 0xa006, 0x0078, 0x8f1f, 0xa085, 0x0001, 0x0d7f, - 0x007f, 0x007c, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078, - 0x76c7, 0x017f, 0x0040, 0x8f3c, 0x611a, 0x601f, 0x0001, 0x2d00, - 0x6012, 0x1078, 0x2880, 0x2009, 0x0028, 0x1078, 0x775c, 0xa085, - 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x8f39, 0xa186, - 0x0015, 0x00c0, 0x8f54, 0x2011, 0xa720, 0x2204, 0xa086, 0x0074, - 0x00c0, 0x8f54, 0x1078, 0x7f91, 0x6003, 0x0001, 0x6007, 0x0029, - 0x1078, 0x5dd7, 0x0078, 0x8f58, 0x1078, 0x7c83, 0x1078, 0x772d, - 0x007c, 0xa186, 0x0016, 0x00c0, 0x8f63, 0x2001, 0x0004, 0x1078, - 0x4502, 0x0078, 0x8f84, 0xa186, 0x0015, 0x00c0, 0x8f88, 0x2011, - 0xa720, 0x2204, 0xa086, 0x0014, 0x00c0, 0x8f88, 0x0d7e, 0x6018, - 0x2068, 0x1078, 0x4649, 0x0d7f, 0x1078, 0x8043, 0x00c0, 0x8f88, - 0x0d7e, 0x6018, 0x2068, 0x6890, 0x0d7f, 0xa005, 0x0040, 0x8f88, - 0x2001, 0x0006, 0x1078, 0x4502, 0x1078, 0x77f8, 0x0078, 0x8f8c, - 0x1078, 0x7c83, 0x1078, 0x772d, 0x007c, 0x6848, 0xa086, 0x0005, - 0x00c0, 0x8f94, 0x1078, 0x8f95, 0x007c, 0x6850, 0xc0ad, 0x6852, - 0x007c, 0x0e7e, 0x2071, 0xac8c, 0x7014, 0xd0e4, 0x0040, 0x8faa, - 0x6013, 0x0000, 0x6003, 0x0001, 0x6007, 0x0050, 0x1078, 0x5d8a, - 0x1078, 0x62d1, 0x0e7f, 0x007c, 0x0c7e, 0x0f7e, 0x2c78, 0x1078, - 0x4963, 0x0f7f, 0x0040, 0x8fb9, 0x601c, 0xa084, 0x000f, 0x1079, - 0x8fbb, 0x0c7f, 0x007c, 0x8ae5, 0x8fc6, 0x8fc9, 0x8fcc, 0xa26d, - 0xa289, 0xa28c, 0x8ae5, 0x8ae5, 0x1078, 0x1332, 0x0005, 0x0005, - 0x007c, 0x0005, 0x0005, 0x007c, 0x1078, 0x8fcf, 0x007c, 0x0f7e, - 0x2c78, 0x1078, 0x4963, 0x0040, 0x8ffe, 0x1078, 0x76c7, 0x00c0, - 0x8fdf, 0x2001, 0xa9a4, 0x2004, 0x783e, 0x0078, 0x8ffe, 0x7818, - 0x601a, 0x781c, 0xa086, 0x0003, 0x0040, 0x8fec, 0x7808, 0x6036, - 0x2f00, 0x603a, 0x0078, 0x8ff0, 0x7808, 0x603a, 0x2f00, 0x6036, - 0x602a, 0x601f, 0x0001, 0x6007, 0x0035, 0x6003, 0x0001, 0x7920, - 0x6122, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x2f60, 0x0f7f, 0x007c, - 0x017e, 0x0f7e, 0x682c, 0x6032, 0xa08e, 0x0001, 0x0040, 0x9011, - 0xa086, 0x0005, 0x0040, 0x9015, 0xa006, 0x602a, 0x602e, 0x0078, - 0x9026, 0x6824, 0xc0f4, 0xc0d5, 0x6826, 0x6810, 0x2078, 0x787c, - 0x6938, 0xa102, 0x7880, 0x6934, 0xa103, 0x00c8, 0x900c, 0x6834, - 0x602a, 0x6838, 0xa084, 0xfffc, 0x683a, 0x602e, 0x2d00, 0x6036, - 0x6808, 0x603a, 0x6918, 0x611a, 0x6920, 0x6122, 0x601f, 0x0001, - 0x6007, 0x0039, 0x6003, 0x0001, 0x1078, 0x5d8a, 0x6803, 0x0002, - 0x0f7f, 0x017f, 0x007c, 0x007e, 0x017e, 0x6004, 0xa08e, 0x0034, - 0x0040, 0x9060, 0xa08e, 0x0035, 0x0040, 0x9060, 0xa08e, 0x0036, - 0x0040, 0x9060, 0xa08e, 0x0037, 0x0040, 0x9060, 0xa08e, 0x0038, - 0x0040, 0x9060, 0xa08e, 0x0039, 0x0040, 0x9060, 0xa08e, 0x003a, - 0x0040, 0x9060, 0xa08e, 0x003b, 0x0040, 0x9060, 0xa085, 0x0001, - 0x017f, 0x007f, 0x007c, 0x0f7e, 0x2c78, 0x1078, 0x4963, 0x00c0, - 0x906d, 0xa085, 0x0001, 0x0078, 0x907c, 0x6024, 0xd0f4, 0x00c0, - 0x907b, 0xc0f5, 0x6026, 0x6010, 0x2078, 0x7828, 0x603a, 0x782c, - 0x6036, 0x1078, 0x1757, 0xa006, 0x0f7f, 0x007c, 0x007e, 0x017e, - 0x027e, 0x037e, 0x0e7e, 0x2001, 0xa99e, 0x200c, 0x8000, 0x2014, - 0x2001, 0x0032, 0x1078, 0x5c1c, 0x2001, 0xa9a2, 0x82ff, 0x00c0, - 0x9093, 0x2011, 0x0014, 0x2202, 0x2001, 0xa9a0, 0x200c, 0x8000, - 0x2014, 0x2071, 0xa98d, 0x711a, 0x721e, 0x2001, 0x0064, 0x1078, - 0x5c1c, 0x2001, 0xa9a3, 0x82ff, 0x00c0, 0x90a8, 0x2011, 0x0014, - 0x2202, 0x2009, 0xa9a4, 0xa280, 0x000a, 0x200a, 0x1078, 0x498b, - 0x0e7f, 0x037f, 0x027f, 0x017f, 0x007f, 0x007c, 0x007e, 0x0e7e, - 0x2001, 0xa9a2, 0x2003, 0x0028, 0x2001, 0xa9a3, 0x2003, 0x0014, - 0x2071, 0xa98d, 0x701b, 0x0000, 0x701f, 0x07d0, 0x2001, 0xa9a4, - 0x2003, 0x001e, 0x0e7f, 0x007f, 0x007c, 0x0c7e, 0x127e, 0x2091, - 0x8000, 0x0c7e, 0x1078, 0x76c7, 0x017f, 0x0040, 0x90e5, 0x611a, - 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x0033, 0x1078, 0x775c, - 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x90e2, - 0x0d7e, 0x0e7e, 0x0f7e, 0x2071, 0xa700, 0xa186, 0x0015, 0x00c0, - 0x9117, 0x7080, 0xa086, 0x0018, 0x00c0, 0x9117, 0x6010, 0x2068, - 0x6a3c, 0xd2e4, 0x00c0, 0x910b, 0x2c78, 0x1078, 0x6490, 0x0040, - 0x911f, 0x706c, 0x6a50, 0xa206, 0x00c0, 0x9113, 0x7070, 0x6a54, - 0xa206, 0x00c0, 0x9113, 0x6218, 0xa290, 0x0028, 0x2214, 0x2009, - 0x0000, 0x1078, 0x28c8, 0x1078, 0x77f8, 0x0078, 0x911b, 0x1078, - 0x7c83, 0x1078, 0x772d, 0x0f7f, 0x0e7f, 0x0d7f, 0x007c, 0x7050, - 0xa080, 0x29c0, 0x2004, 0x6a54, 0xa206, 0x0040, 0x910b, 0x0078, - 0x9113, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078, 0x76c7, - 0x017f, 0x0040, 0x9141, 0x611a, 0x601f, 0x0001, 0x2d00, 0x6012, - 0x2009, 0x0043, 0x1078, 0x775c, 0xa085, 0x0001, 0x127f, 0x0c7f, - 0x007c, 0xa006, 0x0078, 0x913e, 0x0d7e, 0x0e7e, 0x0f7e, 0x2071, - 0xa700, 0xa186, 0x0015, 0x00c0, 0x916a, 0x7080, 0xa086, 0x0004, - 0x00c0, 0x916a, 0x6010, 0xa0e8, 0x000f, 0x2c78, 0x1078, 0x6490, - 0x0040, 0x9172, 0x706c, 0x6a08, 0xa206, 0x00c0, 0x9166, 0x7070, - 0x6a0c, 0xa206, 0x00c0, 0x9166, 0x1078, 0x2880, 0x1078, 0x77f8, - 0x0078, 0x916e, 0x1078, 0x7c83, 0x1078, 0x772d, 0x0f7f, 0x0e7f, - 0x0d7f, 0x007c, 0x7050, 0xa080, 0x29c0, 0x2004, 0x6a0c, 0xa206, - 0x0040, 0x9164, 0x0078, 0x9166, 0x017e, 0x027e, 0x684c, 0xd0ac, - 0x0040, 0x9194, 0x6914, 0x6a10, 0x2100, 0xa205, 0x0040, 0x9194, - 0x6860, 0xa106, 0x00c0, 0x9190, 0x685c, 0xa206, 0x0040, 0x9194, - 0x6962, 0x6a5e, 0xa085, 0x0001, 0x027f, 0x017f, 0x007c, 0x0e7e, - 0x127e, 0x2071, 0xa700, 0x2091, 0x8000, 0x7548, 0xa582, 0x0001, - 0x0048, 0x91c9, 0x704c, 0x2060, 0x6000, 0xa086, 0x0000, 0x0040, - 0x91b5, 0xace0, 0x0010, 0x7058, 0xac02, 0x00c8, 0x91b1, 0x0078, - 0x91a4, 0x2061, 0xae00, 0x0078, 0x91a4, 0x6003, 0x0008, 0x8529, - 0x754a, 0xaca8, 0x0010, 0x7058, 0xa502, 0x00c8, 0x91c5, 0x754e, - 0xa085, 0x0001, 0x127f, 0x0e7f, 0x007c, 0x704f, 0xae00, 0x0078, - 0x91c0, 0xa006, 0x0078, 0x91c2, 0x0c7e, 0x027e, 0x017e, 0xa186, - 0x0035, 0x0040, 0x91d6, 0x6a34, 0x0078, 0x91d7, 0x6a28, 0x1078, - 0x8d02, 0x0040, 0x9200, 0x2260, 0x611c, 0xa186, 0x0003, 0x0040, - 0x91e5, 0xa186, 0x0006, 0x00c0, 0x91fc, 0x6834, 0xa206, 0x0040, - 0x91f4, 0x6838, 0xa206, 0x00c0, 0x91fc, 0x6108, 0x6834, 0xa106, - 0x00c0, 0x91fc, 0x0078, 0x91f9, 0x6008, 0x6938, 0xa106, 0x00c0, - 0x91fc, 0x6018, 0x6918, 0xa106, 0x017f, 0x027f, 0x0c7f, 0x007c, - 0xa085, 0x0001, 0x0078, 0x91fc, 0x6944, 0xd1cc, 0x0040, 0x921d, - 0xa18c, 0x00ff, 0xa18e, 0x0002, 0x00c0, 0x921d, 0xad88, 0x001e, - 0x210c, 0xa18c, 0x0f00, 0x810f, 0xa18e, 0x0001, 0x00c0, 0x921d, - 0x6810, 0x6914, 0xa115, 0x10c0, 0x84e2, 0x007c, 0x067e, 0x6000, - 0xa0b2, 0x0010, 0x10c8, 0x1332, 0x1079, 0x9228, 0x067f, 0x007c, - 0x9238, 0x96ef, 0x980b, 0x9238, 0x9238, 0x9238, 0x9238, 0x9238, - 0x9272, 0x989e, 0x9238, 0x9238, 0x9238, 0x9238, 0x9238, 0x9238, - 0x1078, 0x1332, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8, 0x1332, - 0x1079, 0x9244, 0x067f, 0x007c, 0x9254, 0x9d63, 0x9254, 0x9254, - 0x9254, 0x9254, 0x9254, 0x9254, 0x9d21, 0x9db1, 0x9254, 0xa3c0, - 0xa3f4, 0xa3c0, 0xa3f4, 0x9254, 0x1078, 0x1332, 0x067e, 0x6000, - 0xa0b2, 0x0010, 0x10c8, 0x1332, 0x1079, 0x9260, 0x067f, 0x007c, - 0x9270, 0x99fb, 0x9ad7, 0x9b05, 0x9b80, 0x9270, 0x9c86, 0x9c2e, - 0x98aa, 0x9cf5, 0x9d0b, 0x9270, 0x9270, 0x9270, 0x9270, 0x9270, - 0x1078, 0x1332, 0xa1b2, 0x0044, 0x10c8, 0x1332, 0x2100, 0x0079, - 0x9279, 0x92b9, 0x94a8, 0x92b9, 0x92b9, 0x92b9, 0x94b0, 0x92b9, - 0x92b9, 0x92b9, 0x92b9, 0x92b9, 0x92b9, 0x92b9, 0x92b9, 0x92b9, - 0x92b9, 0x92b9, 0x92b9, 0x92b9, 0x92b9, 0x92b9, 0x92b9, 0x92b9, - 0x92bb, 0x9321, 0x9330, 0x9387, 0x93a6, 0x9425, 0x9495, 0x92b9, - 0x92b9, 0x94b4, 0x92b9, 0x92b9, 0x94c7, 0x94d2, 0x92b9, 0x92b9, - 0x92b9, 0x92b9, 0x92b9, 0x950a, 0x92b9, 0x92b9, 0x9519, 0x92b9, - 0x92b9, 0x92b9, 0x92b9, 0x92b9, 0x92b9, 0x9532, 0x92b9, 0x92b9, - 0x92b9, 0x95bf, 0x92b9, 0x92b9, 0x92b9, 0x92b9, 0x92b9, 0x92b9, - 0x9639, 0x1078, 0x1332, 0x1078, 0x4967, 0x00c0, 0x92cb, 0x2001, - 0xa733, 0x2004, 0xd0cc, 0x00c0, 0x92cb, 0xa084, 0x0009, 0xa086, - 0x0008, 0x00c0, 0x92d3, 0x6007, 0x0009, 0x602b, 0x0009, 0x6013, - 0x0000, 0x0078, 0x94a3, 0x1078, 0x4957, 0x0e7e, 0x0c7e, 0x037e, - 0x027e, 0x017e, 0x6218, 0x2270, 0x72a0, 0x027e, 0x2019, 0x0029, - 0x1078, 0x5f01, 0x077e, 0x2039, 0x0000, 0x1078, 0x5e0a, 0x2c08, - 0x1078, 0x9f9b, 0x077f, 0x017f, 0x2e60, 0x1078, 0x47e9, 0x017f, - 0x027f, 0x037f, 0x0c7f, 0x0e7f, 0x6618, 0x0c7e, 0x2660, 0x1078, - 0x45d6, 0x0c7f, 0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, - 0x0006, 0x0048, 0x9313, 0x1078, 0x9ecf, 0x00c0, 0x9381, 0x1078, - 0x9e60, 0x00c0, 0x930f, 0x6007, 0x0008, 0x0078, 0x94a3, 0x6007, - 0x0009, 0x0078, 0x94a3, 0x1078, 0xa0af, 0x0040, 0x931d, 0x1078, - 0x9ecf, 0x0040, 0x9307, 0x0078, 0x9381, 0x6013, 0x1900, 0x0078, - 0x930f, 0x1078, 0x29bb, 0x00c0, 0x9674, 0x6106, 0x1078, 0x9e15, - 0x6007, 0x0006, 0x0078, 0x94a3, 0x6007, 0x0007, 0x0078, 0x94a3, - 0x1078, 0xa42c, 0x00c0, 0x9674, 0x1078, 0x29bb, 0x00c0, 0x9674, - 0x0d7e, 0x6618, 0x2668, 0x6e04, 0xa684, 0x00ff, 0xa082, 0x0006, - 0x00c8, 0x9346, 0x2001, 0x0001, 0x1078, 0x44ee, 0xa6b4, 0xff00, - 0x8637, 0xa686, 0x0006, 0x0040, 0x9363, 0xa686, 0x0004, 0x0040, - 0x9363, 0x6e04, 0xa6b4, 0x00ff, 0xa686, 0x0006, 0x0040, 0x9363, - 0xa686, 0x0004, 0x0040, 0x9363, 0xa686, 0x0005, 0x0040, 0x9363, - 0x0d7f, 0x0078, 0x9381, 0x1078, 0x9f35, 0x00c0, 0x937c, 0xa686, - 0x0006, 0x00c0, 0x9375, 0x027e, 0x6218, 0xa290, 0x0028, 0x2214, - 0x2009, 0x0000, 0x1078, 0x28c8, 0x027f, 0x1078, 0x4649, 0x6007, - 0x000a, 0x0d7f, 0x0078, 0x94a3, 0x6007, 0x000b, 0x0d7f, 0x0078, - 0x94a3, 0x1078, 0x2880, 0x6007, 0x0001, 0x0078, 0x94a3, 0x1078, - 0xa42c, 0x00c0, 0x9674, 0x1078, 0x29bb, 0x00c0, 0x9674, 0x6618, - 0x0d7e, 0x2668, 0x6e04, 0x0d7f, 0xa686, 0x0707, 0x0040, 0x9381, - 0x027e, 0x6218, 0xa290, 0x0028, 0x2214, 0x2009, 0x0000, 0x1078, - 0x28c8, 0x027f, 0x6007, 0x000c, 0x0078, 0x94a3, 0x1078, 0x4967, - 0x00c0, 0x93b3, 0x2001, 0xa733, 0x2004, 0xa084, 0x0009, 0xa086, - 0x0008, 0x00c0, 0x93bb, 0x6007, 0x0009, 0x602b, 0x0009, 0x6013, - 0x0000, 0x0078, 0x94a3, 0x1078, 0x4957, 0x6618, 0xa6b0, 0x0001, - 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x0048, 0x93ff, 0xa6b4, - 0xff00, 0x8637, 0xa686, 0x0004, 0x0040, 0x93d2, 0xa686, 0x0006, - 0x00c0, 0x9381, 0x1078, 0x9f44, 0x00c0, 0x93da, 0x6007, 0x000e, - 0x0078, 0x94a3, 0x047e, 0x6418, 0xa4a0, 0x0028, 0x2424, 0xa4a4, - 0x00ff, 0x8427, 0x047e, 0x1078, 0x2880, 0x047f, 0x017e, 0xa006, - 0x2009, 0xa753, 0x210c, 0xd1a4, 0x0040, 0x93f9, 0x2009, 0x0029, - 0x1078, 0xa22d, 0x6018, 0x0d7e, 0x2068, 0x6800, 0xc0e5, 0x6802, - 0x0d7f, 0x017f, 0x047f, 0x6007, 0x0001, 0x0078, 0x94a3, 0x2001, - 0x0001, 0x1078, 0x44ee, 0x157e, 0x017e, 0x027e, 0x037e, 0x20a9, - 0x0004, 0x2019, 0xa705, 0x2011, 0xac90, 0x1078, 0x80de, 0x037f, - 0x027f, 0x017f, 0x157f, 0xa005, 0x0040, 0x941f, 0xa6b4, 0xff00, - 0x8637, 0xa686, 0x0006, 0x0040, 0x93d2, 0x0078, 0x9381, 0x6013, - 0x1900, 0x6007, 0x0009, 0x0078, 0x94a3, 0x1078, 0x4967, 0x00c0, - 0x9432, 0x2001, 0xa733, 0x2004, 0xa084, 0x0009, 0xa086, 0x0008, - 0x00c0, 0x943a, 0x6007, 0x0009, 0x602b, 0x0009, 0x6013, 0x0000, - 0x0078, 0x94a3, 0x1078, 0x4957, 0x6618, 0xa6b0, 0x0001, 0x2634, - 0xa684, 0x00ff, 0xa082, 0x0006, 0x0048, 0x9482, 0xa6b4, 0xff00, - 0x8637, 0xa686, 0x0004, 0x0040, 0x9451, 0xa686, 0x0006, 0x00c0, - 0x9381, 0x1078, 0x9f6f, 0x00c0, 0x945d, 0x1078, 0x9e60, 0x00c0, - 0x945d, 0x6007, 0x0010, 0x0078, 0x94a3, 0x047e, 0x6418, 0xa4a0, - 0x0028, 0x2424, 0xa4a4, 0x00ff, 0x8427, 0x047e, 0x1078, 0x2880, - 0x047f, 0x017e, 0xa006, 0x2009, 0xa753, 0x210c, 0xd1a4, 0x0040, - 0x947c, 0x2009, 0x0029, 0x1078, 0xa22d, 0x6018, 0x0d7e, 0x2068, - 0x6800, 0xc0e5, 0x6802, 0x0d7f, 0x017f, 0x047f, 0x6007, 0x0001, - 0x0078, 0x94a3, 0x1078, 0xa0af, 0x0040, 0x948f, 0xa6b4, 0xff00, - 0x8637, 0xa686, 0x0006, 0x0040, 0x9451, 0x0078, 0x9381, 0x6013, - 0x1900, 0x6007, 0x0009, 0x0078, 0x94a3, 0x1078, 0x29bb, 0x00c0, - 0x9674, 0x1078, 0xa42c, 0x00c0, 0x9674, 0x1078, 0x9677, 0x00c0, - 0x9381, 0x6007, 0x0012, 0x6003, 0x0001, 0x1078, 0x5dd7, 0x007c, - 0x6007, 0x0001, 0x6003, 0x0001, 0x1078, 0x5dd7, 0x0078, 0x94a7, - 0x6007, 0x0005, 0x0078, 0x94aa, 0x1078, 0xa42c, 0x00c0, 0x9674, - 0x1078, 0x29bb, 0x00c0, 0x9674, 0x1078, 0x9677, 0x00c0, 0x9381, - 0x6007, 0x0020, 0x6003, 0x0001, 0x1078, 0x5dd7, 0x007c, 0x1078, - 0x29bb, 0x00c0, 0x9674, 0x6007, 0x0023, 0x6003, 0x0001, 0x1078, - 0x5dd7, 0x007c, 0x1078, 0xa42c, 0x00c0, 0x9674, 0x1078, 0x29bb, - 0x00c0, 0x9674, 0x1078, 0x9677, 0x00c0, 0x9381, 0x017e, 0x027e, - 0x2011, 0xac90, 0x2214, 0x2c08, 0xa006, 0x1078, 0xa1f6, 0x00c0, - 0x94f9, 0x2160, 0x6007, 0x0026, 0x6013, 0x1700, 0x2011, 0xac89, - 0x2214, 0xa296, 0xffff, 0x00c0, 0x9503, 0x6007, 0x0025, 0x0078, - 0x9503, 0x6004, 0xa086, 0x0024, 0x00c0, 0x9500, 0x1078, 0x772d, - 0x2160, 0x6007, 0x0025, 0x6003, 0x0001, 0x1078, 0x5dd7, 0x027f, - 0x017f, 0x007c, 0x1078, 0x29bb, 0x00c0, 0x9674, 0x6106, 0x1078, - 0x9697, 0x6007, 0x002b, 0x0078, 0x94a3, 0x6007, 0x002c, 0x0078, - 0x94a3, 0x1078, 0xa42c, 0x00c0, 0x9674, 0x1078, 0x29bb, 0x00c0, - 0x9674, 0x1078, 0x9677, 0x00c0, 0x9381, 0x6106, 0x1078, 0x969c, - 0x00c0, 0x952e, 0x6007, 0x002e, 0x0078, 0x94a3, 0x6007, 0x002f, - 0x0078, 0x94a3, 0x1078, 0x29bb, 0x00c0, 0x9674, 0x0e7e, 0x0d7e, - 0x0c7e, 0x6018, 0xa080, 0x0001, 0x200c, 0xa184, 0x00ff, 0xa086, - 0x0006, 0x0040, 0x954f, 0xa184, 0xff00, 0x8007, 0xa086, 0x0006, - 0x0040, 0x954f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0078, 0x94a8, 0x2001, - 0xa772, 0x2004, 0xd0e4, 0x0040, 0x95bb, 0x2071, 0xac8c, 0x7010, - 0x6036, 0x7014, 0x603a, 0x7108, 0x720c, 0x2001, 0xa753, 0x2004, - 0xd0a4, 0x0040, 0x956d, 0x6018, 0x2068, 0x6810, 0xa106, 0x00c0, - 0x956d, 0x6814, 0xa206, 0x0040, 0x9591, 0x2001, 0xa753, 0x2004, - 0xd0ac, 0x00c0, 0x95af, 0x2069, 0xa700, 0x6870, 0xa206, 0x00c0, - 0x95af, 0x686c, 0xa106, 0x00c0, 0x95af, 0x7210, 0x1078, 0x8d02, - 0x0040, 0x95b5, 0x1078, 0xa29e, 0x0040, 0x95b5, 0x622a, 0x6007, - 0x0036, 0x6003, 0x0001, 0x1078, 0x5d8a, 0x0c7f, 0x0d7f, 0x0e7f, - 0x007c, 0x7214, 0xa286, 0xffff, 0x0040, 0x95a3, 0x1078, 0x8d02, - 0x0040, 0x95b5, 0xa280, 0x0002, 0x2004, 0x7110, 0xa106, 0x00c0, - 0x95b5, 0x0078, 0x957e, 0x7210, 0x2c08, 0xa085, 0x0001, 0x1078, - 0xa1f6, 0x2c10, 0x2160, 0x0040, 0x95b5, 0x0078, 0x957e, 0x6007, - 0x0037, 0x6013, 0x1500, 0x0078, 0x9589, 0x6007, 0x0037, 0x6013, - 0x1700, 0x0078, 0x9589, 0x6007, 0x0012, 0x0078, 0x9589, 0x1078, - 0x29bb, 0x00c0, 0x9674, 0x6018, 0xa080, 0x0001, 0x2004, 0xa084, - 0xff00, 0x8007, 0xa086, 0x0006, 0x00c0, 0x94a8, 0x0e7e, 0x0d7e, - 0x0c7e, 0x2001, 0xa772, 0x2004, 0xd0e4, 0x0040, 0x9631, 0x2069, - 0xa700, 0x2071, 0xac8c, 0x7008, 0x6036, 0x720c, 0x623a, 0xa286, - 0xffff, 0x00c0, 0x95ee, 0x7208, 0x0c7e, 0x2c08, 0xa085, 0x0001, - 0x1078, 0xa1f6, 0x2c10, 0x0c7f, 0x0040, 0x9625, 0x1078, 0x8d02, - 0x0040, 0x9625, 0x0c7e, 0x027e, 0x2260, 0x1078, 0x8a03, 0x027f, - 0x0c7f, 0x7118, 0xa18c, 0xff00, 0x810f, 0xa186, 0x0001, 0x0040, - 0x960f, 0xa186, 0x0005, 0x0040, 0x9609, 0xa186, 0x0007, 0x00c0, - 0x9619, 0xa280, 0x0004, 0x2004, 0xa005, 0x0040, 0x9619, 0x057e, - 0x7510, 0x7614, 0x1078, 0xa2b3, 0x057f, 0x0c7f, 0x0d7f, 0x0e7f, - 0x007c, 0x6007, 0x003b, 0x602b, 0x0009, 0x6013, 0x2a00, 0x6003, - 0x0001, 0x1078, 0x5d8a, 0x0078, 0x9615, 0x6007, 0x003b, 0x602b, - 0x0009, 0x6013, 0x1700, 0x6003, 0x0001, 0x1078, 0x5d8a, 0x0078, - 0x9615, 0x6007, 0x003b, 0x602b, 0x000b, 0x6013, 0x0000, 0x0078, - 0x9589, 0x0e7e, 0x027e, 0x1078, 0x4967, 0x0040, 0x966e, 0x1078, - 0x4957, 0x1078, 0xa4b9, 0x00c0, 0x966c, 0x2071, 0xa700, 0x70cc, - 0xc085, 0x70ce, 0x0f7e, 0x2079, 0x0100, 0x7298, 0xa284, 0x00ff, - 0x706e, 0x78e6, 0xa284, 0xff00, 0x7270, 0xa205, 0x7072, 0x78ea, - 0x0f7f, 0x70d7, 0x0000, 0x2001, 0xa753, 0x2004, 0xd0a4, 0x0040, - 0x9665, 0x2011, 0xa9ca, 0x2013, 0x07d0, 0xd0ac, 0x00c0, 0x966e, - 0x1078, 0x2677, 0x0078, 0x966e, 0x1078, 0xa4e9, 0x027f, 0x0e7f, - 0x1078, 0x772d, 0x0078, 0x94a7, 0x1078, 0x772d, 0x007c, 0x0d7e, - 0x067e, 0x6618, 0x2668, 0x6e04, 0xa6b4, 0xff00, 0x8637, 0xa686, - 0x0006, 0x0040, 0x9694, 0xa686, 0x0004, 0x0040, 0x9694, 0x6e04, - 0xa6b4, 0x00ff, 0xa686, 0x0006, 0x0040, 0x9694, 0xa686, 0x0004, - 0x0040, 0x9694, 0xa085, 0x0001, 0x067f, 0x0d7f, 0x007c, 0x0d7e, - 0x1078, 0x96cb, 0x0d7f, 0x007c, 0x0d7e, 0x1078, 0x96da, 0x00c0, - 0x96c4, 0x680c, 0xa08c, 0xff00, 0x6820, 0xa084, 0x00ff, 0xa115, - 0x6212, 0x6824, 0x602a, 0xd1e4, 0x0040, 0x96b2, 0x2009, 0x0001, - 0x0078, 0x96c0, 0xd1ec, 0x0040, 0x96c4, 0x6920, 0xa18c, 0x00ff, - 0x6824, 0x1078, 0x254d, 0x00c0, 0x96c4, 0x2110, 0x2009, 0x0000, - 0x1078, 0x28c8, 0x0078, 0x96c8, 0xa085, 0x0001, 0x0078, 0x96c9, - 0xa006, 0x0d7f, 0x007c, 0x2069, 0xac8d, 0x6800, 0xa082, 0x0010, - 0x00c8, 0x96d8, 0x6013, 0x0000, 0xa085, 0x0001, 0x0078, 0x96d9, - 0xa006, 0x007c, 0x6013, 0x0000, 0x2069, 0xac8c, 0x6808, 0xa084, - 0xff00, 0xa086, 0x0800, 0x00c0, 0x96ee, 0x6800, 0xa084, 0x00ff, - 0xa08e, 0x0014, 0x0040, 0x96ee, 0xa08e, 0x0010, 0x007c, 0x6004, - 0xa0b2, 0x0044, 0x10c8, 0x1332, 0xa1b6, 0x0013, 0x00c0, 0x96fb, - 0x2008, 0x0079, 0x970e, 0xa1b6, 0x0027, 0x0040, 0x9703, 0xa1b6, - 0x0014, 0x10c0, 0x1332, 0x2001, 0x0007, 0x1078, 0x4535, 0x1078, - 0x61cd, 0x1078, 0x8ed6, 0x1078, 0x62d1, 0x007c, 0x974e, 0x9750, - 0x974e, 0x974e, 0x974e, 0x9750, 0x975c, 0x97e6, 0x97a9, 0x97e6, - 0x97bd, 0x97e6, 0x975c, 0x97e6, 0x97de, 0x97e6, 0x97de, 0x97e6, - 0x97e6, 0x974e, 0x974e, 0x974e, 0x974e, 0x974e, 0x974e, 0x974e, - 0x974e, 0x974e, 0x974e, 0x974e, 0x9750, 0x974e, 0x97e6, 0x974e, - 0x974e, 0x97e6, 0x974e, 0x97e6, 0x97e6, 0x974e, 0x974e, 0x974e, - 0x974e, 0x97e6, 0x97e6, 0x974e, 0x97e6, 0x97e6, 0x974e, 0x974e, - 0x974e, 0x974e, 0x974e, 0x9750, 0x97e6, 0x97e6, 0x974e, 0x974e, - 0x97e6, 0x97e6, 0x974e, 0x974e, 0x974e, 0x974e, 0x1078, 0x1332, - 0x1078, 0x61cd, 0x2001, 0xa9a2, 0x2004, 0x6016, 0x6003, 0x0002, - 0x1078, 0x62d1, 0x0078, 0x97ec, 0x0f7e, 0x2079, 0xa752, 0x7804, - 0x0f7f, 0xd0ac, 0x00c0, 0x97e6, 0x2001, 0x0000, 0x1078, 0x44ee, - 0x6018, 0xa080, 0x0004, 0x2004, 0xa086, 0x00ff, 0x0040, 0x97e6, - 0x0c7e, 0x6018, 0x2060, 0x6000, 0xd0f4, 0x00c0, 0x9780, 0x6010, - 0xa005, 0x0040, 0x9780, 0x0c7f, 0x1078, 0x3699, 0x0078, 0x97e6, - 0x0c7f, 0x2001, 0xa700, 0x2004, 0xa086, 0x0002, 0x00c0, 0x978f, - 0x0f7e, 0x2079, 0xa700, 0x7890, 0x8000, 0x7892, 0x0f7f, 0x2001, - 0x0002, 0x1078, 0x4502, 0x1078, 0x61cd, 0x601f, 0x0001, 0x6003, - 0x0001, 0x6007, 0x0002, 0x1078, 0x5dd7, 0x1078, 0x62d1, 0x0c7e, - 0x6118, 0x2160, 0x2009, 0x0001, 0x1078, 0x5a52, 0x0c7f, 0x0078, - 0x97ec, 0x6618, 0x0d7e, 0x2668, 0x6e04, 0x0d7f, 0xa6b4, 0xff00, - 0x8637, 0xa686, 0x0006, 0x0040, 0x97e6, 0xa686, 0x0004, 0x0040, - 0x97e6, 0x2001, 0x0004, 0x0078, 0x97e4, 0x2001, 0xa700, 0x2004, - 0xa086, 0x0003, 0x00c0, 0x97c6, 0x1078, 0x3699, 0x2001, 0x0006, - 0x1078, 0x97ed, 0x6618, 0x0d7e, 0x2668, 0x6e04, 0x0d7f, 0xa6b4, - 0xff00, 0x8637, 0xa686, 0x0006, 0x0040, 0x97e6, 0x2001, 0x0006, - 0x0078, 0x97e4, 0x2001, 0x0004, 0x0078, 0x97e4, 0x2001, 0x0006, - 0x1078, 0x97ed, 0x0078, 0x97e6, 0x1078, 0x4535, 0x1078, 0x61cd, - 0x1078, 0x772d, 0x1078, 0x62d1, 0x007c, 0x017e, 0x0d7e, 0x6118, - 0x2168, 0x6900, 0xd184, 0x0040, 0x9808, 0x6104, 0xa18e, 0x000a, - 0x00c0, 0x9800, 0x699c, 0xd1a4, 0x00c0, 0x9800, 0x2001, 0x0007, - 0x1078, 0x4502, 0x2001, 0x0000, 0x1078, 0x44ee, 0x1078, 0x28a6, - 0x0d7f, 0x017f, 0x007c, 0x0d7e, 0x6618, 0x2668, 0x6804, 0xa084, - 0xff00, 0x8007, 0x0d7f, 0xa0b2, 0x000c, 0x10c8, 0x1332, 0xa1b6, - 0x0015, 0x00c0, 0x981f, 0x1079, 0x9826, 0x0078, 0x9825, 0xa1b6, - 0x0016, 0x10c0, 0x1332, 0x1079, 0x9832, 0x007c, 0x7d4e, 0x7d4e, - 0x7d4e, 0x7d4e, 0x7d4e, 0x7d4e, 0x9887, 0x983e, 0x7d4e, 0x7d4e, - 0x7d4e, 0x7d4e, 0x7d4e, 0x7d4e, 0x7d4e, 0x7d4e, 0x7d4e, 0x7d4e, - 0x9887, 0x988f, 0x7d4e, 0x7d4e, 0x7d4e, 0x7d4e, 0x0f7e, 0x2079, - 0xa752, 0x7804, 0xd0ac, 0x00c0, 0x9865, 0x6018, 0xa07d, 0x0040, - 0x9865, 0x7800, 0xd0f4, 0x00c0, 0x9851, 0x7810, 0xa005, 0x00c0, - 0x9865, 0x2001, 0x0000, 0x1078, 0x44ee, 0x2001, 0x0002, 0x1078, - 0x4502, 0x601f, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x1078, - 0x5dd7, 0x1078, 0x62d1, 0x0078, 0x9885, 0x2011, 0xac83, 0x2204, - 0x8211, 0x220c, 0x1078, 0x254d, 0x00c0, 0x9885, 0x0c7e, 0x1078, - 0x45c4, 0x0040, 0x9878, 0x0c7f, 0x1078, 0x772d, 0x0078, 0x9885, - 0x6010, 0x007e, 0x6014, 0x007e, 0x1078, 0x42f8, 0x007f, 0x6016, - 0x007f, 0x6012, 0x0c7f, 0x1078, 0x772d, 0x0f7f, 0x007c, 0x6604, - 0xa6b6, 0x001e, 0x00c0, 0x988e, 0x1078, 0x772d, 0x007c, 0x1078, - 0x7f8e, 0x00c0, 0x989b, 0x6003, 0x0001, 0x6007, 0x0001, 0x1078, - 0x5dd7, 0x0078, 0x989d, 0x1078, 0x772d, 0x007c, 0x6004, 0xa08a, - 0x0044, 0x10c8, 0x1332, 0x1078, 0x61cd, 0x1078, 0x8ed6, 0x1078, - 0x62d1, 0x007c, 0xa182, 0x0040, 0x0079, 0x98ae, 0x98c1, 0x98c1, - 0x98c1, 0x98c1, 0x98c3, 0x98c1, 0x98c1, 0x98c1, 0x98c1, 0x98c1, - 0x98c1, 0x98c1, 0x98c1, 0x98c1, 0x98c1, 0x98c1, 0x98c1, 0x98c1, - 0x98c1, 0x1078, 0x1332, 0x0d7e, 0x0e7e, 0x0f7e, 0x157e, 0x047e, - 0x027e, 0x6218, 0xa280, 0x002b, 0x2004, 0xa005, 0x0040, 0x98d4, - 0x2021, 0x0000, 0x1078, 0xa482, 0x6106, 0x2071, 0xac80, 0x7444, - 0xa4a4, 0xff00, 0x0040, 0x992b, 0xa486, 0x2000, 0x00c0, 0x98e6, - 0x2009, 0x0001, 0x2011, 0x0200, 0x1078, 0x5bf1, 0x1078, 0x138b, - 0x1040, 0x1332, 0x6003, 0x0007, 0x2d00, 0x6837, 0x010d, 0x6803, - 0x0000, 0x683b, 0x0000, 0x6c5a, 0x2c00, 0x685e, 0x6008, 0x68b2, - 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130, 0x694a, 0x017e, 0xa084, - 0xff00, 0x6846, 0x684f, 0x0000, 0x6857, 0x0036, 0x1078, 0x4a73, - 0x017f, 0xa486, 0x2000, 0x00c0, 0x9913, 0x2019, 0x0017, 0x1078, - 0xa1a5, 0x0078, 0x998d, 0xa486, 0x0400, 0x00c0, 0x991d, 0x2019, - 0x0002, 0x1078, 0xa156, 0x0078, 0x998d, 0xa486, 0x0200, 0x00c0, - 0x9923, 0x1078, 0xa13b, 0xa486, 0x1000, 0x00c0, 0x9929, 0x1078, - 0xa18a, 0x0078, 0x998d, 0x2069, 0xaa33, 0x6a00, 0xd284, 0x0040, - 0x99f7, 0xa284, 0x0300, 0x00c0, 0x99ef, 0x6804, 0xa005, 0x0040, - 0x99d5, 0x2d78, 0x6003, 0x0007, 0x1078, 0x1370, 0x0040, 0x9994, - 0x7800, 0xd08c, 0x00c0, 0x9947, 0x7804, 0x8001, 0x7806, 0x6013, - 0x0000, 0x6803, 0x0000, 0x6837, 0x0116, 0x683b, 0x0000, 0x6008, - 0x68b2, 0x2c00, 0x684a, 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130, - 0x6986, 0x6846, 0x7928, 0x698a, 0x792c, 0x698e, 0x7930, 0x6992, - 0x7934, 0x6996, 0x6853, 0x003d, 0x7244, 0xa294, 0x0003, 0xa286, - 0x0002, 0x00c0, 0x996f, 0x684f, 0x0040, 0x0078, 0x9979, 0xa286, - 0x0001, 0x00c0, 0x9977, 0x684f, 0x0080, 0x0078, 0x9979, 0x684f, - 0x0000, 0x20a9, 0x000a, 0x2001, 0xac90, 0xad90, 0x0015, 0x200c, - 0x810f, 0x2112, 0x8000, 0x8210, 0x00f0, 0x997f, 0x200c, 0x6982, - 0x8000, 0x200c, 0x697e, 0x1078, 0x4a73, 0x027f, 0x047f, 0x157f, - 0x0f7f, 0x0e7f, 0x0d7f, 0x007c, 0x2001, 0xa70e, 0x2004, 0xd084, - 0x0040, 0x999e, 0x1078, 0x138b, 0x00c0, 0x9940, 0x6013, 0x0100, - 0x6003, 0x0001, 0x6007, 0x0041, 0x1078, 0x5d8a, 0x1078, 0x62d1, - 0x0078, 0x998d, 0x2069, 0xac92, 0x2d04, 0xa084, 0xff00, 0xa086, - 0x1200, 0x00c0, 0x99c9, 0x2069, 0xac80, 0x686c, 0xa084, 0x00ff, - 0x017e, 0x6110, 0xa18c, 0x0700, 0xa10d, 0x6112, 0x017f, 0x6003, - 0x0001, 0x6007, 0x0043, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0078, - 0x998d, 0x6013, 0x0200, 0x6003, 0x0001, 0x6007, 0x0041, 0x1078, - 0x5d8a, 0x1078, 0x62d1, 0x0078, 0x998d, 0x2001, 0xa70d, 0x2004, - 0xd0ec, 0x0040, 0x99df, 0x2011, 0x8049, 0x1078, 0x361b, 0x6013, - 0x0300, 0x0078, 0x99e5, 0x6013, 0x0100, 0x6003, 0x0001, 0x6007, - 0x0041, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0078, 0x998d, 0x6013, - 0x0500, 0x0078, 0x99e5, 0x6013, 0x0600, 0x0078, 0x99aa, 0x6013, - 0x0200, 0x0078, 0x99aa, 0xa186, 0x0013, 0x00c0, 0x9a0d, 0x6004, - 0xa08a, 0x0040, 0x1048, 0x1332, 0xa08a, 0x0053, 0x10c8, 0x1332, - 0xa082, 0x0040, 0x2008, 0x0079, 0x9a92, 0xa186, 0x0051, 0x0040, - 0x9a1a, 0xa186, 0x0047, 0x00c0, 0x9a33, 0x6004, 0xa086, 0x0041, - 0x0040, 0x9a41, 0x2001, 0x0109, 0x2004, 0xd084, 0x0040, 0x9a41, - 0x127e, 0x2091, 0x2200, 0x007e, 0x017e, 0x027e, 0x1078, 0x5c56, - 0x027f, 0x017f, 0x007f, 0x127f, 0x6000, 0xa086, 0x0002, 0x00c0, - 0x9a41, 0x0078, 0x9ad7, 0xa186, 0x0027, 0x0040, 0x9a3b, 0xa186, - 0x0014, 0x10c0, 0x1332, 0x6004, 0xa082, 0x0040, 0x2008, 0x0079, - 0x9a44, 0x1078, 0x7773, 0x007c, 0x9a57, 0x9a59, 0x9a59, 0x9a81, - 0x9a57, 0x9a57, 0x9a57, 0x9a57, 0x9a57, 0x9a57, 0x9a57, 0x9a57, - 0x9a57, 0x9a57, 0x9a57, 0x9a57, 0x9a57, 0x9a57, 0x9a57, 0x1078, - 0x1332, 0x1078, 0x61cd, 0x1078, 0x62d1, 0x037e, 0x0d7e, 0x6010, - 0xa06d, 0x0040, 0x9a7e, 0xad84, 0xf000, 0x0040, 0x9a7e, 0x6003, - 0x0002, 0x6018, 0x2004, 0xd0bc, 0x00c0, 0x9a7e, 0x2019, 0x0004, - 0x1078, 0xa1da, 0x6013, 0x0000, 0x6014, 0xa005, 0x00c0, 0x9a7c, - 0x2001, 0xa9a3, 0x2004, 0x6016, 0x6003, 0x0007, 0x0d7f, 0x037f, - 0x007c, 0x0d7e, 0x1078, 0x61cd, 0x1078, 0x62d1, 0x1078, 0x8d16, - 0x0040, 0x9a8e, 0x6010, 0x2068, 0x1078, 0x13a4, 0x1078, 0x8ed6, - 0x0d7f, 0x007c, 0x9aa5, 0x9ac4, 0x9aae, 0x9ad1, 0x9aa5, 0x9aa5, - 0x9aa5, 0x9aa5, 0x9aa5, 0x9aa5, 0x9aa5, 0x9aa5, 0x9aa5, 0x9aa5, - 0x9aa5, 0x9aa5, 0x9aa5, 0x9aa5, 0x9aa5, 0x1078, 0x1332, 0x6010, - 0xa088, 0x0013, 0x2104, 0xa085, 0x0400, 0x200a, 0x1078, 0x61cd, - 0x6010, 0xa080, 0x0013, 0x2004, 0xd0b4, 0x0040, 0x9abf, 0x6003, - 0x0007, 0x2009, 0x0043, 0x1078, 0x775c, 0x0078, 0x9ac1, 0x6003, - 0x0002, 0x1078, 0x62d1, 0x007c, 0x1078, 0x61cd, 0x1078, 0xa433, - 0x00c0, 0x9ace, 0x1078, 0x5bc1, 0x1078, 0x772d, 0x1078, 0x62d1, - 0x007c, 0x1078, 0x61cd, 0x2009, 0x0041, 0x0078, 0x9c2e, 0xa182, - 0x0040, 0x0079, 0x9adb, 0x9aee, 0x9af0, 0x9aee, 0x9aee, 0x9aee, - 0x9aee, 0x9aee, 0x9af1, 0x9aee, 0x9aee, 0x9aee, 0x9aee, 0x9aee, - 0x9aee, 0x9aee, 0x9aee, 0x9aee, 0x9afc, 0x9aee, 0x1078, 0x1332, - 0x007c, 0x6003, 0x0004, 0x6110, 0x20e1, 0x0005, 0x3d18, 0x3e20, - 0x2c10, 0x1078, 0x15fa, 0x007c, 0x0d7e, 0x1078, 0x5bc1, 0x0d7f, - 0x1078, 0xa4a5, 0x1078, 0x772d, 0x007c, 0xa182, 0x0040, 0x0079, - 0x9b09, 0x9b1c, 0x9b1c, 0x9b1c, 0x9b1c, 0x9b1c, 0x9b1c, 0x9b1c, - 0x9b1e, 0x9b1c, 0x9b21, 0x9b4c, 0x9b1c, 0x9b1c, 0x9b1c, 0x9b1c, - 0x9b4c, 0x9b1c, 0x9b1c, 0x9b1c, 0x1078, 0x1332, 0x1078, 0x7773, - 0x007c, 0x1078, 0x627a, 0x1078, 0x639b, 0x6010, 0x0d7e, 0x2068, - 0x684c, 0xd0fc, 0x0040, 0x9b37, 0xa08c, 0x0003, 0xa18e, 0x0002, - 0x0040, 0x9b3f, 0x2009, 0x0041, 0x0d7f, 0x0078, 0x9c2e, 0x6003, - 0x0007, 0x6017, 0x0000, 0x1078, 0x5bc1, 0x0d7f, 0x007c, 0x1078, - 0xa433, 0x0040, 0x9b45, 0x0d7f, 0x007c, 0x1078, 0x5bc1, 0x1078, - 0x772d, 0x0d7f, 0x0078, 0x9b3e, 0x037e, 0x1078, 0x627a, 0x1078, - 0x639b, 0x6010, 0x0d7e, 0x2068, 0x6018, 0x2004, 0xd0bc, 0x0040, - 0x9b6c, 0x684c, 0xa084, 0x0003, 0xa086, 0x0002, 0x0040, 0x9b68, - 0x687c, 0x632c, 0xa31a, 0x632e, 0x6880, 0x6328, 0xa31b, 0x632a, - 0x6003, 0x0002, 0x0078, 0x9b7d, 0x2019, 0x0004, 0x1078, 0xa1da, - 0x6014, 0xa005, 0x00c0, 0x9b79, 0x2001, 0xa9a3, 0x2004, 0x8003, - 0x6016, 0x6013, 0x0000, 0x6003, 0x0007, 0x0d7f, 0x037f, 0x007c, - 0xa186, 0x0013, 0x00c0, 0x9b8e, 0x6004, 0xa086, 0x0042, 0x10c0, - 0x1332, 0x1078, 0x61cd, 0x1078, 0x62d1, 0x007c, 0xa186, 0x0027, - 0x0040, 0x9b96, 0xa186, 0x0014, 0x00c0, 0x9ba6, 0x6004, 0xa086, - 0x0042, 0x10c0, 0x1332, 0x2001, 0x0007, 0x1078, 0x4535, 0x1078, - 0x61cd, 0x1078, 0x8ed6, 0x1078, 0x62d1, 0x007c, 0xa182, 0x0040, - 0x0079, 0x9baa, 0x9bbd, 0x9bbd, 0x9bbd, 0x9bbd, 0x9bbd, 0x9bbd, - 0x9bbd, 0x9bbf, 0x9bcb, 0x9bbd, 0x9bbd, 0x9bbd, 0x9bbd, 0x9bbd, - 0x9bbd, 0x9bbd, 0x9bbd, 0x9bbd, 0x9bbd, 0x1078, 0x1332, 0x037e, - 0x047e, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x1078, 0x15fa, - 0x047f, 0x037f, 0x007c, 0x6010, 0x0d7e, 0x2068, 0x6810, 0x6a14, - 0x6118, 0x210c, 0xd1bc, 0x0040, 0x9bea, 0x6124, 0xd1f4, 0x00c0, - 0x9bea, 0x007e, 0x047e, 0x057e, 0x6c7c, 0xa422, 0x6d80, 0x2200, - 0xa52b, 0x602c, 0xa420, 0x642e, 0x6028, 0xa529, 0x652a, 0x057f, - 0x047f, 0x007f, 0xa20d, 0x00c0, 0x9bfe, 0x684c, 0xd0fc, 0x0040, - 0x9bf6, 0x2009, 0x0041, 0x0d7f, 0x0078, 0x9c2e, 0x6003, 0x0007, - 0x6017, 0x0000, 0x1078, 0x5bc1, 0x0d7f, 0x007c, 0x007e, 0x0f7e, - 0x2c78, 0x1078, 0x4963, 0x0f7f, 0x007f, 0x0040, 0x9c0b, 0x6003, - 0x0002, 0x0d7f, 0x007c, 0x2009, 0xa70d, 0x210c, 0xd19c, 0x0040, - 0x9c15, 0x6003, 0x0007, 0x0078, 0x9c17, 0x6003, 0x0006, 0x1078, - 0x9c1d, 0x1078, 0x5bc3, 0x0d7f, 0x007c, 0xd2fc, 0x0040, 0x9c29, - 0x8002, 0x8000, 0x8212, 0xa291, 0x0000, 0x2009, 0x0009, 0x0078, - 0x9c2b, 0x2009, 0x0015, 0x6a6a, 0x6866, 0x007c, 0xa182, 0x0040, - 0x0048, 0x9c34, 0x0079, 0x9c41, 0xa186, 0x0013, 0x0040, 0x9c3c, - 0xa186, 0x0014, 0x10c0, 0x1332, 0x6024, 0xd0dc, 0x1040, 0x1332, - 0x007c, 0x9c54, 0x9c5b, 0x9c67, 0x9c73, 0x9c54, 0x9c54, 0x9c54, - 0x9c82, 0x9c54, 0x9c56, 0x9c56, 0x9c54, 0x9c54, 0x9c54, 0x9c54, - 0x9c54, 0x9c54, 0x9c54, 0x9c54, 0x1078, 0x1332, 0x6024, 0xd0dc, - 0x1040, 0x1332, 0x007c, 0x6003, 0x0001, 0x6106, 0x1078, 0x5d8a, - 0x127e, 0x2091, 0x8000, 0x1078, 0x62d1, 0x127f, 0x007c, 0x6003, - 0x0001, 0x6106, 0x1078, 0x5d8a, 0x127e, 0x2091, 0x8000, 0x1078, - 0x62d1, 0x127f, 0x007c, 0x6003, 0x0003, 0x6106, 0x2c10, 0x1078, - 0x1cf0, 0x127e, 0x2091, 0x8000, 0x1078, 0x5df6, 0x1078, 0x639b, - 0x127f, 0x007c, 0xa016, 0x1078, 0x15fa, 0x007c, 0x127e, 0x2091, - 0x8000, 0x037e, 0x0d7e, 0xa182, 0x0040, 0x1079, 0x9c93, 0x0d7f, - 0x037f, 0x127f, 0x007c, 0x9ca3, 0x9ca5, 0x9cba, 0x9cd9, 0x9ca3, - 0x9ca3, 0x9ca3, 0x9cf1, 0x9ca3, 0x9ca3, 0x9ca3, 0x9ca3, 0x9ca3, - 0x9ca3, 0x9ca3, 0x9ca3, 0x1078, 0x1332, 0x6010, 0x2068, 0x684c, - 0xd0fc, 0x0040, 0x9ccf, 0xa09c, 0x0003, 0xa39e, 0x0003, 0x0040, - 0x9ccf, 0x6003, 0x0001, 0x6106, 0x1078, 0x5d8a, 0x1078, 0x62d1, - 0x0078, 0x9cf4, 0x6010, 0x2068, 0x684c, 0xd0fc, 0x0040, 0x9ccf, - 0xa09c, 0x0003, 0xa39e, 0x0003, 0x0040, 0x9ccf, 0x6003, 0x0001, - 0x6106, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0078, 0x9cf4, 0x6013, - 0x0000, 0x6017, 0x0000, 0x2019, 0x0004, 0x1078, 0xa1da, 0x0078, - 0x9cf4, 0x6010, 0x2068, 0x684c, 0xd0fc, 0x0040, 0x9ccf, 0xa09c, - 0x0003, 0xa39e, 0x0003, 0x0040, 0x9ccf, 0x6003, 0x0003, 0x6106, - 0x2c10, 0x1078, 0x1cf0, 0x1078, 0x5df6, 0x1078, 0x639b, 0x0078, - 0x9cf4, 0xa016, 0x1078, 0x15fa, 0x007c, 0x1078, 0x61cd, 0x6110, - 0x81ff, 0x0040, 0x9d06, 0x0d7e, 0x2168, 0x1078, 0xa4f2, 0x037e, - 0x2019, 0x0029, 0x1078, 0xa1da, 0x037f, 0x0d7f, 0x1078, 0x8ed6, - 0x1078, 0x62d1, 0x007c, 0x1078, 0x627a, 0x6110, 0x81ff, 0x0040, - 0x9d1c, 0x0d7e, 0x2168, 0x1078, 0xa4f2, 0x037e, 0x2019, 0x0029, - 0x1078, 0xa1da, 0x037f, 0x0d7f, 0x1078, 0x8ed6, 0x1078, 0x639b, - 0x007c, 0xa182, 0x0085, 0x0079, 0x9d25, 0x9d2e, 0x9d2c, 0x9d2c, - 0x9d3a, 0x9d2c, 0x9d2c, 0x9d2c, 0x1078, 0x1332, 0x6003, 0x000b, - 0x6106, 0x1078, 0x5d8a, 0x127e, 0x2091, 0x8000, 0x1078, 0x62d1, - 0x127f, 0x007c, 0x027e, 0x0e7e, 0x1078, 0xa42c, 0x0040, 0x9d44, - 0x1078, 0x772d, 0x0078, 0x9d60, 0x2071, 0xac80, 0x7224, 0x6212, - 0x7220, 0x1078, 0xa079, 0x0040, 0x9d51, 0x6007, 0x0086, 0x0078, - 0x9d5a, 0x6007, 0x0087, 0x7224, 0xa296, 0xffff, 0x00c0, 0x9d5a, - 0x6007, 0x0086, 0x6003, 0x0001, 0x1078, 0x5d8a, 0x1078, 0x62d1, - 0x0e7f, 0x027f, 0x007c, 0xa186, 0x0013, 0x00c0, 0x9d74, 0x6004, - 0xa08a, 0x0085, 0x1048, 0x1332, 0xa08a, 0x008c, 0x10c8, 0x1332, - 0xa082, 0x0085, 0x0079, 0x9d8b, 0xa186, 0x0027, 0x0040, 0x9d80, - 0xa186, 0x0014, 0x0040, 0x9d80, 0x1078, 0x7773, 0x0078, 0x9d8a, - 0x2001, 0x0007, 0x1078, 0x4535, 0x1078, 0x61cd, 0x1078, 0x8ed6, - 0x1078, 0x62d1, 0x007c, 0x9d92, 0x9d94, 0x9d94, 0x9d92, 0x9d92, - 0x9d92, 0x9d92, 0x1078, 0x1332, 0x1078, 0x61cd, 0x1078, 0x8ed6, - 0x1078, 0x62d1, 0x007c, 0xa182, 0x0085, 0x1048, 0x1332, 0xa182, - 0x008c, 0x10c8, 0x1332, 0xa182, 0x0085, 0x0079, 0x9da7, 0x9dae, - 0x9dae, 0x9dae, 0x9db0, 0x9dae, 0x9dae, 0x9dae, 0x1078, 0x1332, - 0x007c, 0xa186, 0x0013, 0x0040, 0x9dc1, 0xa186, 0x0014, 0x0040, - 0x9dc1, 0xa186, 0x0027, 0x0040, 0x9dc1, 0x1078, 0x7773, 0x0078, - 0x9dc7, 0x1078, 0x61cd, 0x1078, 0x8ed6, 0x1078, 0x62d1, 0x007c, - 0x037e, 0x1078, 0xa4a5, 0x603f, 0x0000, 0x2019, 0x000b, 0x1078, - 0x9dd7, 0x601f, 0x0006, 0x6003, 0x0007, 0x037f, 0x007c, 0x127e, - 0x037e, 0x2091, 0x8000, 0x087e, 0x2c40, 0x097e, 0x2049, 0x0000, - 0x1078, 0x7246, 0x097f, 0x087f, 0x00c0, 0x9e12, 0x077e, 0x2c38, - 0x1078, 0x72f3, 0x077f, 0x00c0, 0x9e12, 0x6000, 0xa086, 0x0000, - 0x0040, 0x9e12, 0x601c, 0xa086, 0x0007, 0x0040, 0x9e12, 0x0d7e, - 0x6000, 0xa086, 0x0004, 0x00c0, 0x9e03, 0x1078, 0xa4a5, 0x601f, - 0x0007, 0x1078, 0x1757, 0x6010, 0x2068, 0x1078, 0x8d16, 0x0040, - 0x9e0b, 0x1078, 0xa1da, 0x0d7f, 0x6013, 0x0000, 0x1078, 0xa4a5, - 0x601f, 0x0007, 0x037f, 0x127f, 0x007c, 0x0f7e, 0x0c7e, 0x037e, - 0x157e, 0x2079, 0xac80, 0x7938, 0x783c, 0x1078, 0x254d, 0x00c0, - 0x9e59, 0x017e, 0x0c7e, 0x1078, 0x45c4, 0x00c0, 0x9e59, 0x017f, - 0x027f, 0x027e, 0x017e, 0x2019, 0x0029, 0x1078, 0x73d0, 0x1078, - 0x5f01, 0x077e, 0x2039, 0x0000, 0x1078, 0x5e0a, 0x077f, 0x017f, - 0x077e, 0x2039, 0x0000, 0x1078, 0x9f9b, 0x077f, 0x1078, 0x47e9, - 0x027e, 0x6204, 0xa294, 0xff00, 0x8217, 0xa286, 0x0006, 0x0040, - 0x9e4d, 0xa286, 0x0004, 0x00c0, 0x9e50, 0x62a0, 0x1078, 0x2942, - 0x027f, 0x017f, 0x1078, 0x42f8, 0x6612, 0x6516, 0xa006, 0x0078, - 0x9e5b, 0x0c7f, 0x017f, 0x157f, 0x037f, 0x0c7f, 0x0f7f, 0x007c, - 0x0c7e, 0x0d7e, 0x0e7e, 0x017e, 0x2009, 0xa720, 0x2104, 0xa086, - 0x0074, 0x00c0, 0x9ec3, 0x2069, 0xac8e, 0x690c, 0xa182, 0x0100, - 0x0048, 0x9eb3, 0x6908, 0xa184, 0x8000, 0x0040, 0x9ebf, 0x6018, - 0x2070, 0x7010, 0xa084, 0x00ff, 0x0040, 0x9e82, 0x7000, 0xd0f4, - 0x0040, 0x9e86, 0xa184, 0x0800, 0x0040, 0x9ebf, 0x6910, 0xa18a, - 0x0001, 0x0048, 0x9eb7, 0x6914, 0x2069, 0xacae, 0x6904, 0x81ff, - 0x00c0, 0x9eab, 0x690c, 0xa182, 0x0100, 0x0048, 0x9eb3, 0x6908, - 0x81ff, 0x00c0, 0x9eaf, 0x6910, 0xa18a, 0x0001, 0x0048, 0x9eb7, - 0x6918, 0xa18a, 0x0001, 0x0048, 0x9ebf, 0x0078, 0x9ec9, 0x6013, - 0x0100, 0x0078, 0x9ec5, 0x6013, 0x0300, 0x0078, 0x9ec5, 0x6013, - 0x0500, 0x0078, 0x9ec5, 0x6013, 0x0700, 0x0078, 0x9ec5, 0x6013, - 0x0900, 0x0078, 0x9ec5, 0x6013, 0x0b00, 0x0078, 0x9ec5, 0x6013, - 0x0f00, 0x0078, 0x9ec5, 0x6013, 0x2d00, 0xa085, 0x0001, 0x0078, - 0x9eca, 0xa006, 0x017f, 0x0e7f, 0x0d7f, 0x0c7f, 0x007c, 0x0c7e, - 0x0d7e, 0x027e, 0x037e, 0x157e, 0x6218, 0x2268, 0x6b04, 0xa394, - 0x00ff, 0xa286, 0x0006, 0x0040, 0x9ef3, 0xa286, 0x0004, 0x0040, - 0x9ef3, 0xa394, 0xff00, 0x8217, 0xa286, 0x0006, 0x0040, 0x9ef3, - 0xa286, 0x0004, 0x0040, 0x9ef3, 0x0c7e, 0x2d60, 0x1078, 0x45d6, - 0x0c7f, 0x0078, 0x9f2e, 0x2011, 0xac96, 0xad98, 0x000a, 0x20a9, - 0x0004, 0x1078, 0x80de, 0x00c0, 0x9f2f, 0x2011, 0xac9a, 0xad98, - 0x0006, 0x20a9, 0x0004, 0x1078, 0x80de, 0x00c0, 0x9f2f, 0x047e, - 0x017e, 0x6aa0, 0xa294, 0x00ff, 0x8227, 0xa006, 0x2009, 0xa753, - 0x210c, 0xd1a4, 0x0040, 0x9f1b, 0x2009, 0x0029, 0x1078, 0xa22d, - 0x6800, 0xc0e5, 0x6802, 0x2019, 0x0029, 0x1078, 0x5f01, 0x077e, - 0x2039, 0x0000, 0x1078, 0x5e0a, 0x2c08, 0x1078, 0x9f9b, 0x077f, - 0x2001, 0x0007, 0x1078, 0x4535, 0x017f, 0x047f, 0xa006, 0x157f, - 0x037f, 0x027f, 0x0d7f, 0x0c7f, 0x007c, 0x0d7e, 0x2069, 0xac8e, - 0x6800, 0xa086, 0x0800, 0x0040, 0x9f41, 0x6013, 0x0000, 0x0078, - 0x9f42, 0xa006, 0x0d7f, 0x007c, 0x0c7e, 0x0f7e, 0x017e, 0x027e, - 0x037e, 0x157e, 0x2079, 0xac8c, 0x7930, 0x7834, 0x1078, 0x254d, - 0x00c0, 0x9f68, 0x1078, 0x45c4, 0x00c0, 0x9f68, 0x2011, 0xac90, - 0xac98, 0x000a, 0x20a9, 0x0004, 0x1078, 0x80de, 0x00c0, 0x9f68, - 0x2011, 0xac94, 0xac98, 0x0006, 0x20a9, 0x0004, 0x1078, 0x80de, - 0x157f, 0x037f, 0x027f, 0x017f, 0x0f7f, 0x0c7f, 0x007c, 0x0c7e, - 0x007e, 0x017e, 0x027e, 0x037e, 0x157e, 0x2011, 0xac83, 0x2204, - 0x8211, 0x220c, 0x1078, 0x254d, 0x00c0, 0x9f94, 0x1078, 0x45c4, - 0x00c0, 0x9f94, 0x2011, 0xac96, 0xac98, 0x000a, 0x20a9, 0x0004, - 0x1078, 0x80de, 0x00c0, 0x9f94, 0x2011, 0xac9a, 0xac98, 0x0006, - 0x20a9, 0x0004, 0x1078, 0x80de, 0x157f, 0x037f, 0x027f, 0x017f, - 0x007f, 0x0c7f, 0x007c, 0x0e7e, 0x0c7e, 0x087e, 0x077e, 0x067e, - 0x057e, 0x047e, 0x027e, 0x127e, 0x2091, 0x8000, 0x2740, 0x2029, - 0xa9ba, 0x252c, 0x2021, 0xa9c0, 0x2424, 0x2061, 0xae00, 0x2071, - 0xa700, 0x7648, 0x7064, 0x81ff, 0x0040, 0x9fc2, 0x007e, 0xa186, - 0xaab3, 0x007f, 0x0040, 0x9fc2, 0x8001, 0xa602, 0x00c8, 0xa02c, - 0x0078, 0x9fc5, 0xa606, 0x0040, 0xa02c, 0x2100, 0xac06, 0x0040, - 0xa022, 0x1078, 0xa252, 0x0040, 0xa022, 0x671c, 0xa786, 0x0001, - 0x0040, 0xa047, 0xa786, 0x0004, 0x0040, 0xa047, 0xa786, 0x0007, - 0x0040, 0xa022, 0x2500, 0xac06, 0x0040, 0xa022, 0x2400, 0xac06, - 0x0040, 0xa022, 0x1078, 0xa266, 0x00c0, 0xa022, 0x88ff, 0x0040, - 0x9fed, 0x6020, 0xa906, 0x00c0, 0xa022, 0x0d7e, 0x6000, 0xa086, - 0x0004, 0x00c0, 0x9ff7, 0x017e, 0x1078, 0x1757, 0x017f, 0xa786, - 0x0008, 0x00c0, 0xa006, 0x1078, 0x8f10, 0x00c0, 0xa006, 0x1078, - 0x7c83, 0x0d7f, 0x1078, 0x8ed6, 0x0078, 0xa022, 0x6010, 0x2068, - 0x1078, 0x8d16, 0x0040, 0xa01f, 0xa786, 0x0003, 0x00c0, 0xa036, - 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0xa4f2, 0x017e, - 0x1078, 0x8f8d, 0x1078, 0x4a73, 0x017f, 0x1078, 0x8ec9, 0x0d7f, - 0x1078, 0x8ed6, 0xace0, 0x0010, 0x2001, 0xa716, 0x2004, 0xac02, - 0x00c8, 0xa02c, 0x0078, 0x9faf, 0x127f, 0x027f, 0x047f, 0x057f, - 0x067f, 0x077f, 0x087f, 0x0c7f, 0x0e7f, 0x007c, 0xa786, 0x0006, - 0x00c0, 0xa010, 0xa386, 0x0005, 0x0040, 0xa044, 0x1078, 0xa4f2, - 0x1078, 0xa1da, 0x0078, 0xa01f, 0x0d7f, 0x0078, 0xa022, 0x1078, - 0xa266, 0x00c0, 0xa022, 0x81ff, 0x0040, 0xa022, 0xa180, 0x0001, - 0x2004, 0xa086, 0x0018, 0x0040, 0xa05c, 0xa180, 0x0001, 0x2004, - 0xa086, 0x002d, 0x00c0, 0xa022, 0x6000, 0xa086, 0x0002, 0x00c0, - 0xa022, 0x1078, 0x8efc, 0x0040, 0xa06d, 0x1078, 0x8f10, 0x00c0, - 0xa022, 0x1078, 0x7c83, 0x0078, 0xa075, 0x1078, 0x28a6, 0x1078, - 0x8f10, 0x00c0, 0xa075, 0x1078, 0x7c83, 0x1078, 0x8ed6, 0x0078, - 0xa022, 0x0c7e, 0x0e7e, 0x017e, 0x2c08, 0x2170, 0xa006, 0x1078, - 0xa1f6, 0x017f, 0x0040, 0xa089, 0x601c, 0xa084, 0x000f, 0x1079, - 0xa08c, 0x0e7f, 0x0c7f, 0x007c, 0xa094, 0xa094, 0xa094, 0xa094, - 0xa094, 0xa094, 0xa096, 0xa094, 0xa006, 0x007c, 0x047e, 0x017e, - 0x7018, 0xa080, 0x0028, 0x2024, 0xa4a4, 0x00ff, 0x8427, 0x2c00, - 0x2009, 0x0020, 0x1078, 0xa22d, 0x017f, 0x047f, 0x037e, 0x2019, - 0x0002, 0x1078, 0x9dd7, 0x037f, 0xa085, 0x0001, 0x007c, 0x2001, - 0x0001, 0x1078, 0x44ee, 0x157e, 0x017e, 0x027e, 0x037e, 0x20a9, - 0x0004, 0x2019, 0xa705, 0x2011, 0xac96, 0x1078, 0x80de, 0x037f, - 0x027f, 0x017f, 0x157f, 0xa005, 0x007c, 0x0f7e, 0x0e7e, 0x0c7e, - 0x087e, 0x077e, 0x067e, 0x027e, 0x127e, 0x2091, 0x8000, 0x2740, - 0x2061, 0xae00, 0x2079, 0x0001, 0x8fff, 0x0040, 0xa12d, 0x2071, - 0xa700, 0x7648, 0x7064, 0x8001, 0xa602, 0x00c8, 0xa12d, 0x88ff, - 0x0040, 0xa0e8, 0x2800, 0xac06, 0x00c0, 0xa123, 0x2079, 0x0000, - 0x1078, 0xa252, 0x0040, 0xa123, 0x2400, 0xac06, 0x0040, 0xa123, - 0x671c, 0xa786, 0x0006, 0x00c0, 0xa123, 0xa786, 0x0007, 0x0040, - 0xa123, 0x88ff, 0x00c0, 0xa107, 0x6018, 0xa206, 0x00c0, 0xa123, - 0x85ff, 0x0040, 0xa107, 0x6020, 0xa106, 0x00c0, 0xa123, 0x0d7e, - 0x6000, 0xa086, 0x0004, 0x00c0, 0xa113, 0x1078, 0xa4a5, 0x601f, - 0x0007, 0x1078, 0x1757, 0x6010, 0x2068, 0x1078, 0x8d16, 0x0040, - 0xa11d, 0x047e, 0x1078, 0xa1da, 0x047f, 0x0d7f, 0x1078, 0x8ed6, - 0x88ff, 0x00c0, 0xa137, 0xace0, 0x0010, 0x2001, 0xa716, 0x2004, - 0xac02, 0x00c8, 0xa12d, 0x0078, 0xa0d4, 0xa006, 0x127f, 0x027f, - 0x067f, 0x077f, 0x087f, 0x0c7f, 0x0e7f, 0x0f7f, 0x007c, 0xa8c5, - 0x0001, 0x0078, 0xa12e, 0x077e, 0x057e, 0x087e, 0x2041, 0x0000, - 0x2029, 0x0001, 0x2c20, 0x2019, 0x0002, 0x6218, 0x097e, 0x2049, - 0x0000, 0x1078, 0x7246, 0x097f, 0x087f, 0x2039, 0x0000, 0x1078, - 0x72f3, 0x1078, 0xa0c5, 0x057f, 0x077f, 0x007c, 0x027e, 0x047e, - 0x057e, 0x077e, 0x0c7e, 0x157e, 0x2c20, 0x2128, 0x20a9, 0x007f, - 0x2009, 0x0000, 0x017e, 0x037e, 0x1078, 0x45c4, 0x00c0, 0xa17e, - 0x2c10, 0x057e, 0x087e, 0x2041, 0x0000, 0x2508, 0x2029, 0x0001, - 0x097e, 0x2049, 0x0000, 0x1078, 0x7246, 0x097f, 0x087f, 0x2039, - 0x0000, 0x1078, 0x72f3, 0x1078, 0xa0c5, 0x057f, 0x037f, 0x017f, - 0x8108, 0x00f0, 0xa162, 0x157f, 0x0c7f, 0x077f, 0x057f, 0x047f, - 0x027f, 0x007c, 0x077e, 0x057e, 0x6218, 0x087e, 0x2041, 0x0000, - 0x2029, 0x0001, 0x2019, 0x0048, 0x097e, 0x2049, 0x0000, 0x1078, - 0x7246, 0x097f, 0x087f, 0x2039, 0x0000, 0x1078, 0x72f3, 0x2c20, - 0x1078, 0xa0c5, 0x057f, 0x077f, 0x007c, 0x027e, 0x047e, 0x057e, - 0x077e, 0x0c7e, 0x157e, 0x2c20, 0x20a9, 0x007f, 0x2009, 0x0000, - 0x017e, 0x037e, 0x1078, 0x45c4, 0x00c0, 0xa1ce, 0x2c10, 0x087e, - 0x2041, 0x0000, 0x2828, 0x047e, 0x2021, 0x0001, 0x1078, 0xa482, - 0x047f, 0x097e, 0x2049, 0x0000, 0x1078, 0x7246, 0x097f, 0x087f, - 0x2039, 0x0000, 0x1078, 0x72f3, 0x1078, 0xa0c5, 0x037f, 0x017f, - 0x8108, 0x00f0, 0xa1b0, 0x157f, 0x0c7f, 0x077f, 0x057f, 0x047f, - 0x027f, 0x007c, 0x017e, 0x0f7e, 0xad82, 0xce00, 0x0048, 0xa1f3, - 0xad82, 0xffff, 0x00c8, 0xa1f3, 0x6800, 0xa07d, 0x0040, 0xa1f0, - 0x6803, 0x0000, 0x6b52, 0x1078, 0x4a73, 0x2f68, 0x0078, 0xa1e4, - 0x6b52, 0x1078, 0x4a73, 0x0f7f, 0x017f, 0x007c, 0x0e7e, 0x047e, - 0x037e, 0x2061, 0xae00, 0xa005, 0x00c0, 0xa206, 0x2071, 0xa700, - 0x7448, 0x7064, 0x8001, 0xa402, 0x00c8, 0xa228, 0x2100, 0xac06, - 0x0040, 0xa21a, 0x6000, 0xa086, 0x0000, 0x0040, 0xa21a, 0x6008, - 0xa206, 0x00c0, 0xa21a, 0x6018, 0xa1a0, 0x0006, 0x2424, 0xa406, - 0x0040, 0xa224, 0xace0, 0x0010, 0x2001, 0xa716, 0x2004, 0xac02, - 0x00c8, 0xa228, 0x0078, 0xa206, 0xa085, 0x0001, 0x0078, 0xa229, - 0xa006, 0x037f, 0x047f, 0x0e7f, 0x007c, 0x0d7e, 0x007e, 0x1078, - 0x138b, 0x007f, 0x1040, 0x1332, 0x6837, 0x010d, 0x685e, 0x027e, - 0x2010, 0x1078, 0x8d02, 0x2001, 0x0000, 0x0040, 0xa243, 0x2200, - 0xa080, 0x0008, 0x2004, 0x027f, 0x684a, 0x6956, 0x6c46, 0x684f, - 0x0000, 0xa006, 0x68b2, 0x6802, 0x683a, 0x685a, 0x1078, 0x4a73, - 0x0d7f, 0x007c, 0x6700, 0xa786, 0x0000, 0x0040, 0xa265, 0xa786, - 0x0001, 0x0040, 0xa265, 0xa786, 0x000a, 0x0040, 0xa265, 0xa786, - 0x0009, 0x0040, 0xa265, 0xa085, 0x0001, 0x007c, 0x0e7e, 0x6018, - 0x2070, 0x70a0, 0xa206, 0x0e7f, 0x007c, 0x017e, 0x6004, 0xa08e, - 0x001e, 0x00c0, 0xa287, 0x8007, 0x6130, 0xa18c, 0x00ff, 0xa105, - 0x6032, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0005, 0x2001, - 0xa9a3, 0x2004, 0x6016, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x017f, - 0x007c, 0x0005, 0x0005, 0x007c, 0x6024, 0xd0e4, 0x0040, 0xa29d, - 0xd0cc, 0x0040, 0xa297, 0x1078, 0x8fcf, 0x0078, 0xa29d, 0x1078, - 0xa4a5, 0x1078, 0x5bc1, 0x1078, 0x772d, 0x007c, 0xa280, 0x0007, - 0x2004, 0xa084, 0x000f, 0x0079, 0xa2a5, 0xa2ae, 0xa2ae, 0xa2ae, - 0xa2b0, 0xa2ae, 0xa2b0, 0xa2b0, 0xa2ae, 0xa2b0, 0xa006, 0x007c, - 0xa085, 0x0001, 0x007c, 0xa280, 0x0007, 0x2004, 0xa084, 0x000f, - 0x0079, 0xa2ba, 0xa2c3, 0xa2c3, 0xa2c3, 0xa2c3, 0xa2c3, 0xa2c3, - 0xa2ce, 0xa2c3, 0xa2c3, 0x6007, 0x003b, 0x602b, 0x0009, 0x6013, - 0x2a00, 0x6003, 0x0001, 0x1078, 0x5d8a, 0x007c, 0x0c7e, 0x2260, - 0x1078, 0xa4a5, 0x603f, 0x0000, 0x6024, 0xc0f4, 0xc0cc, 0x6026, - 0x0c7f, 0x0d7e, 0x2268, 0xa186, 0x0007, 0x00c0, 0xa32f, 0x6810, - 0xa005, 0x0040, 0xa2ec, 0xa080, 0x0013, 0x2004, 0xd0fc, 0x00c0, - 0xa2ec, 0x0d7f, 0x0078, 0xa2c3, 0x6007, 0x003a, 0x6003, 0x0001, - 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0c7e, 0x2d60, 0x6100, 0xa186, - 0x0002, 0x00c0, 0xa3bd, 0x6010, 0xa005, 0x00c0, 0xa306, 0x6000, - 0xa086, 0x0007, 0x10c0, 0x1332, 0x0078, 0xa3bd, 0xa08c, 0xf000, - 0x00c0, 0xa312, 0x0078, 0xa312, 0x2068, 0x6800, 0xa005, 0x00c0, - 0xa30c, 0x2d00, 0xa080, 0x0013, 0x2004, 0xa084, 0x0003, 0xa086, - 0x0002, 0x00c0, 0xa32b, 0x6010, 0x2068, 0x684c, 0xc0dc, 0xc0f4, - 0x684e, 0x6850, 0xc0f4, 0xc0fc, 0x6852, 0x2009, 0x0043, 0x1078, - 0x9c2e, 0x0078, 0xa3bd, 0x2009, 0x0041, 0x0078, 0xa3b7, 0xa186, - 0x0005, 0x00c0, 0xa376, 0x6810, 0xa080, 0x0013, 0x2004, 0xd0bc, - 0x00c0, 0xa33d, 0x0d7f, 0x0078, 0xa2c3, 0xd0b4, 0x0040, 0xa345, - 0xd0fc, 0x1040, 0x1332, 0x0078, 0xa2df, 0x6007, 0x003a, 0x6003, - 0x0001, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0c7e, 0x2d60, 0x6100, - 0xa186, 0x0002, 0x0040, 0xa358, 0xa186, 0x0004, 0x00c0, 0xa3bd, - 0x2071, 0xa9e7, 0x7000, 0xa086, 0x0003, 0x00c0, 0xa365, 0x7004, - 0xac06, 0x00c0, 0xa365, 0x7003, 0x0000, 0x6810, 0xa080, 0x0013, - 0x200c, 0xc1f4, 0xc1dc, 0x2102, 0x8000, 0x200c, 0xc1f4, 0xc1fc, - 0xc1bc, 0x2102, 0x2009, 0x0042, 0x0078, 0xa3b7, 0x037e, 0x0d7e, - 0x0d7e, 0x1078, 0x138b, 0x037f, 0x1040, 0x1332, 0x6837, 0x010d, - 0x6803, 0x0000, 0x683b, 0x0000, 0x685b, 0x0000, 0x6b5e, 0x6857, - 0x0045, 0x2c00, 0x6862, 0x6034, 0x6872, 0x2360, 0x6024, 0xc0dd, - 0x6026, 0x6018, 0xa080, 0x0028, 0x2004, 0xa084, 0x00ff, 0x8007, - 0x6320, 0x6b4a, 0x6846, 0x684f, 0x0000, 0x6d6a, 0x6e66, 0x686f, - 0x0001, 0x1078, 0x4a73, 0x2019, 0x0045, 0x6008, 0x2068, 0x1078, - 0x9dd7, 0x2d00, 0x600a, 0x601f, 0x0006, 0x6003, 0x0007, 0x6017, - 0x0000, 0x603f, 0x0000, 0x0d7f, 0x037f, 0x0078, 0xa3be, 0x603f, - 0x0000, 0x6003, 0x0007, 0x1078, 0x9c2e, 0x0c7f, 0x0d7f, 0x007c, - 0xa186, 0x0013, 0x00c0, 0xa3ca, 0x6004, 0xa082, 0x0085, 0x2008, - 0x0079, 0xa3e4, 0xa186, 0x0027, 0x00c0, 0xa3dd, 0x1078, 0x61cd, - 0x037e, 0x0d7e, 0x6010, 0x2068, 0x2019, 0x0004, 0x1078, 0xa1da, - 0x0d7f, 0x037f, 0x1078, 0x62d1, 0x007c, 0xa186, 0x0014, 0x0040, - 0xa3ce, 0x1078, 0x7773, 0x007c, 0xa3ed, 0xa3eb, 0xa3eb, 0xa3eb, - 0xa3eb, 0xa3eb, 0xa3ed, 0x1078, 0x1332, 0x1078, 0x61cd, 0x6003, - 0x000c, 0x1078, 0x62d1, 0x007c, 0xa182, 0x008c, 0x00c8, 0xa3fe, - 0xa182, 0x0085, 0x0048, 0xa3fe, 0x0079, 0xa401, 0x1078, 0x7773, - 0x007c, 0xa408, 0xa408, 0xa408, 0xa408, 0xa40a, 0xa429, 0xa408, - 0x1078, 0x1332, 0x0d7e, 0x2c68, 0x1078, 0x76c7, 0x0040, 0xa424, - 0x6003, 0x0001, 0x6007, 0x001e, 0x2009, 0xac8e, 0x210c, 0x6136, - 0x2009, 0xac8f, 0x210c, 0x613a, 0x600b, 0xffff, 0x6918, 0x611a, - 0x601f, 0x0004, 0x1078, 0x5d8a, 0x2d60, 0x1078, 0x772d, 0x0d7f, - 0x007c, 0x1078, 0x772d, 0x007c, 0x0e7e, 0x6018, 0x2070, 0x7000, - 0xd0ec, 0x0e7f, 0x007c, 0x6010, 0xa08c, 0xf000, 0x0040, 0xa481, - 0xa080, 0x0013, 0x200c, 0xd1ec, 0x0040, 0xa481, 0x2001, 0xa772, - 0x2004, 0xd0ec, 0x0040, 0xa481, 0x6003, 0x0002, 0x6024, 0xc0e5, - 0x6026, 0xd1ac, 0x0040, 0xa45f, 0x0f7e, 0x2c78, 0x1078, 0x495f, - 0x0f7f, 0x0040, 0xa45f, 0x2001, 0xa9a4, 0x2004, 0x603e, 0x2009, - 0xa772, 0x210c, 0xd1f4, 0x00c0, 0xa47f, 0x0078, 0xa471, 0x2009, - 0xa772, 0x210c, 0xd1f4, 0x0040, 0xa46b, 0x6024, 0xc0e4, 0x6026, - 0xa006, 0x0078, 0xa481, 0x2001, 0xa9a4, 0x200c, 0x8103, 0xa100, - 0x603e, 0x6018, 0xa088, 0x002b, 0x2104, 0xa005, 0x0040, 0xa47c, - 0xa088, 0x0003, 0x0078, 0xa474, 0x2c0a, 0x600f, 0x0000, 0xa085, - 0x0001, 0x007c, 0x017e, 0x0c7e, 0x0e7e, 0x6120, 0xa2f0, 0x002b, - 0x2e04, 0x2060, 0x8cff, 0x0040, 0xa4a1, 0x84ff, 0x00c0, 0xa494, - 0x6020, 0xa106, 0x00c0, 0xa49c, 0x600c, 0x2072, 0x1078, 0x5bc1, - 0x1078, 0x772d, 0x0078, 0xa49e, 0xacf0, 0x0003, 0x2e64, 0x0078, - 0xa48a, 0x0e7f, 0x0c7f, 0x017f, 0x007c, 0x0d7e, 0x6018, 0xa0e8, - 0x002b, 0x2d04, 0xa005, 0x0040, 0xa4b7, 0xac06, 0x0040, 0xa4b5, - 0x2d04, 0xa0e8, 0x0003, 0x0078, 0xa4a9, 0x600c, 0x206a, 0x0d7f, - 0x007c, 0x027e, 0x037e, 0x157e, 0x2011, 0xa726, 0x2204, 0xa084, - 0x00ff, 0x2019, 0xac8e, 0x2334, 0xa636, 0x00c0, 0xa4e5, 0x8318, - 0x2334, 0x2204, 0xa084, 0xff00, 0xa636, 0x00c0, 0xa4e5, 0x2011, - 0xac90, 0x6018, 0xa098, 0x000a, 0x20a9, 0x0004, 0x1078, 0x80de, - 0x00c0, 0xa4e5, 0x2011, 0xac94, 0x6018, 0xa098, 0x0006, 0x20a9, - 0x0004, 0x1078, 0x80de, 0x00c0, 0xa4e5, 0x157f, 0x037f, 0x027f, - 0x007c, 0x0e7e, 0x2071, 0xa700, 0x1078, 0x42b8, 0x1078, 0x2677, - 0x0e7f, 0x007c, 0x0e7e, 0x6018, 0x2070, 0x7000, 0xd0fc, 0x0040, - 0xa4fb, 0x1078, 0xa4fd, 0x0e7f, 0x007c, 0x6850, 0xc0e5, 0x6852, - 0x007c, 0x0e7e, 0x0c7e, 0x077e, 0x067e, 0x057e, 0x047e, 0x027e, - 0x017e, 0x127e, 0x2091, 0x8000, 0x2029, 0xa9ba, 0x252c, 0x2021, - 0xa9c0, 0x2424, 0x2061, 0xae00, 0x2071, 0xa700, 0x7648, 0x7064, - 0xa606, 0x0040, 0xa555, 0x671c, 0xa786, 0x0001, 0x0040, 0xa524, - 0xa786, 0x0008, 0x00c0, 0xa54b, 0x2500, 0xac06, 0x0040, 0xa54b, - 0x2400, 0xac06, 0x0040, 0xa54b, 0x1078, 0xa252, 0x0040, 0xa54b, - 0x1078, 0xa266, 0x00c0, 0xa54b, 0x6000, 0xa086, 0x0004, 0x00c0, - 0xa53d, 0x017e, 0x1078, 0x1757, 0x017f, 0x1078, 0x8efc, 0x00c0, - 0xa543, 0x1078, 0x28a6, 0x1078, 0x8f10, 0x00c0, 0xa549, 0x1078, - 0x7c83, 0x1078, 0x8ed6, 0xace0, 0x0010, 0x2001, 0xa716, 0x2004, - 0xac02, 0x00c8, 0xa555, 0x0078, 0xa514, 0x127f, 0x017f, 0x027f, - 0x047f, 0x057f, 0x067f, 0x077f, 0x0c7f, 0x0e7f, 0x007c, 0x127e, - 0x007e, 0x0e7e, 0x017e, 0x2091, 0x8000, 0x2071, 0xa740, 0xd5a4, - 0x0040, 0xa56d, 0x7034, 0x8000, 0x7036, 0xd5b4, 0x0040, 0xa573, - 0x7030, 0x8000, 0x7032, 0xd5ac, 0x0040, 0xa589, 0x2500, 0xa084, - 0x0007, 0xa08e, 0x0003, 0x0040, 0xa589, 0xa08e, 0x0004, 0x0040, - 0xa589, 0xa08e, 0x0005, 0x0040, 0xa589, 0x2071, 0xa74a, 0x1078, - 0xa5ca, 0x017f, 0x0e7f, 0x007f, 0x127f, 0x007c, 0x127e, 0x007e, - 0x0e7e, 0x017e, 0x2091, 0x8000, 0x2071, 0xa740, 0xd5a4, 0x0040, - 0xa59c, 0x7034, 0x8000, 0x7036, 0xd5b4, 0x0040, 0xa5a2, 0x7030, - 0x8000, 0x7032, 0xd5ac, 0x0040, 0xa5b8, 0x2500, 0xa084, 0x0007, - 0xa08e, 0x0003, 0x0040, 0xa5b8, 0xa08e, 0x0004, 0x0040, 0xa5b8, - 0xa08e, 0x0005, 0x0040, 0xa5b8, 0x2071, 0xa74a, 0x1078, 0xa5ca, - 0x017f, 0x0e7f, 0x007f, 0x127f, 0x007c, 0x127e, 0x007e, 0x0e7e, - 0x2091, 0x8000, 0x2071, 0xa742, 0x1078, 0xa5ca, 0x0e7f, 0x007f, - 0x127f, 0x007c, 0x2e04, 0x8000, 0x2072, 0x00c8, 0xa5d3, 0x8e70, - 0x2e04, 0x8000, 0x2072, 0x007c, 0x0e7e, 0x2071, 0xa740, 0x1078, - 0xa5ca, 0x0e7f, 0x007c, 0x0e7e, 0x2071, 0xa744, 0x1078, 0xa5ca, - 0x0e7f, 0x007c, 0x127e, 0x007e, 0x0e7e, 0x2091, 0x8000, 0x2071, - 0xa740, 0x7044, 0x8000, 0x7046, 0x0e7f, 0x007f, 0x127f, 0x007c, - 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, - 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, - 0x4811 -}; -#ifdef UNIQUE_FW_NAME -unsigned short fw2100tp_length01 = 0x9601; -#else -unsigned short risc_code_length01 = 0x9601; -#endif - diff --git a/drivers/scsi/qla2xxx/ql2200.c b/drivers/scsi/qla2xxx/ql2200.c deleted file mode 100644 index 0eef72dc8da..00000000000 --- a/drivers/scsi/qla2xxx/ql2200.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * QLogic Fibre Channel HBA Driver - * Copyright (C) 2003 Christoph Hellwig. - * Copyright (c) 2003-2005 QLogic Corporation - * - * See LICENSE.qla2xxx for copyright and licensing details. - */ -#include -#include -#include - -#include "qla_def.h" - -static char qla_driver_name[] = "qla2200"; - -extern unsigned char fw2200tp_version[]; -extern unsigned char fw2200tp_version_str[]; -extern unsigned short fw2200tp_addr01; -extern unsigned short fw2200tp_code01[]; -extern unsigned short fw2200tp_length01; - -static struct qla_fw_info qla_fw_tbl[] = { - { - .addressing = FW_INFO_ADDR_NORMAL, - .fwcode = &fw2200tp_code01[0], - .fwlen = &fw2200tp_length01, - .fwstart = &fw2200tp_addr01, - }, - - { FW_INFO_ADDR_NOMORE, }, -}; - -static struct qla_board_info qla_board_tbl = { - .drv_name = qla_driver_name, - - .isp_name = "ISP2200", - .fw_info = qla_fw_tbl, -}; - -static struct pci_device_id qla2200_pci_tbl[] = { - { - .vendor = PCI_VENDOR_ID_QLOGIC, - .device = PCI_DEVICE_ID_QLOGIC_ISP2200, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = (unsigned long)&qla_board_tbl, - }, - - {0, 0}, -}; -MODULE_DEVICE_TABLE(pci, qla2200_pci_tbl); - -static int __devinit -qla2200_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) -{ - return qla2x00_probe_one(pdev, - (struct qla_board_info *)id->driver_data); -} - -static void __devexit -qla2200_remove_one(struct pci_dev *pdev) -{ - qla2x00_remove_one(pdev); -} - -static struct pci_driver qla2200_pci_driver = { - .name = "qla2200", - .id_table = qla2200_pci_tbl, - .probe = qla2200_probe_one, - .remove = __devexit_p(qla2200_remove_one), -}; - -static int __init -qla2200_init(void) -{ - return pci_module_init(&qla2200_pci_driver); -} - -static void __exit -qla2200_exit(void) -{ - pci_unregister_driver(&qla2200_pci_driver); -} - -module_init(qla2200_init); -module_exit(qla2200_exit); - -MODULE_AUTHOR("QLogic Corporation"); -MODULE_DESCRIPTION("QLogic ISP22xx FC-SCSI Host Bus Adapter driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(QLA2XXX_VERSION); diff --git a/drivers/scsi/qla2xxx/ql2200_fw.c b/drivers/scsi/qla2xxx/ql2200_fw.c deleted file mode 100644 index ac07e18abb1..00000000000 --- a/drivers/scsi/qla2xxx/ql2200_fw.c +++ /dev/null @@ -1,5333 +0,0 @@ -/* - * QLogic Fibre Channel HBA Driver - * Copyright (c) 2003-2005 QLogic Corporation - * - * See LICENSE.qla2xxx for copyright and licensing details. - */ - -/* - * Firmware Version 2.02.08 (17:06 Mar 22, 2005) - */ - -#ifdef UNIQUE_FW_NAME -unsigned short fw2200tp_version = 2*1024+2; -#else -unsigned short risc_code_version = 2*1024+2; -#endif - -#ifdef UNIQUE_FW_NAME -unsigned char fw2200tp_version_str[] = {2,2,8}; -#else -unsigned char firmware_version[] = {2,2,8}; -#endif - -#ifdef UNIQUE_FW_NAME -#define fw2200tp_VERSION_STRING "2.02.08" -#else -#define FW_VERSION_STRING "2.02.08" -#endif - -#ifdef UNIQUE_FW_NAME -unsigned short fw2200tp_addr01 = 0x1000 ; -#else -unsigned short risc_code_addr01 = 0x1000 ; -#endif - -#ifdef UNIQUE_FW_NAME -unsigned short fw2200tp_code01[] = { -#else -unsigned short risc_code01[] = { -#endif - 0x0470, 0x0000, 0x0000, 0xa52b, 0x0000, 0x0002, 0x0002, 0x0008, - 0x0017, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2032, 0x3030, - 0x3120, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241, - 0x5449, 0x4f4e, 0x2049, 0x5350, 0x3232, 0x3030, 0x2046, 0x6972, - 0x6d77, 0x6172, 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030, - 0x322e, 0x3032, 0x2e30, 0x3820, 0x2020, 0x2020, 0x2400, 0x20c1, - 0x0005, 0x2001, 0x017f, 0x2003, 0x0000, 0x20c9, 0xbbff, 0x2091, - 0x2000, 0x2059, 0x0000, 0x2b78, 0x7823, 0x0004, 0x2089, 0x299f, - 0x2051, 0xb600, 0x2a70, 0x2029, 0xee00, 0x2031, 0xffff, 0x2039, - 0xede9, 0x2021, 0x0200, 0x0804, 0x146d, 0x20a1, 0xb52b, 0xa00e, - 0x20a9, 0x08d5, 0x41a4, 0x3400, 0x7562, 0x7666, 0x775e, 0x746a, - 0x746e, 0x20a1, 0xbe00, 0x7164, 0x810d, 0x810d, 0x810d, 0x810d, - 0xa18c, 0x000f, 0x2001, 0x000b, 0xa112, 0xa00e, 0x21a8, 0x41a4, - 0x3400, 0x8211, 0x1dd8, 0x7164, 0x3400, 0xa102, 0x0120, 0x0218, - 0x20a8, 0xa00e, 0x41a4, 0x3800, 0xd08c, 0x01d8, 0x2009, 0xb600, - 0x810d, 0x810d, 0x810d, 0x810d, 0xa18c, 0x000f, 0x2001, 0x0001, - 0xa112, 0x20a1, 0x1000, 0xa00e, 0x21a8, 0x41a4, 0x8211, 0x1de0, - 0x2009, 0xb600, 0x3400, 0xa102, 0x0120, 0x0218, 0x20a8, 0xa00e, - 0x41a4, 0x080c, 0x1416, 0x080c, 0x1637, 0x080c, 0x17d4, 0x080c, - 0x1fbe, 0x080c, 0x4c72, 0x080c, 0x8646, 0x080c, 0x15c0, 0x080c, - 0x2ef9, 0x080c, 0x5dfc, 0x080c, 0x53b3, 0x080c, 0x6940, 0x080c, - 0x2545, 0x080c, 0x6bd3, 0x080c, 0x642d, 0x080c, 0x23ff, 0x080c, - 0x2513, 0x2091, 0x3009, 0x7823, 0x0000, 0x1004, 0x10c5, 0x7820, - 0xa086, 0x0002, 0x1150, 0x7823, 0x4000, 0x0e04, 0x10bd, 0x781b, - 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2a70, 0x7003, 0x0000, - 0x2a70, 0x7000, 0xa08e, 0x0003, 0x1158, 0x080c, 0x3f4f, 0x080c, - 0x2f20, 0x080c, 0x5e4a, 0x080c, 0x5562, 0x080c, 0x696b, 0x0c80, - 0x000b, 0x0c98, 0x10e4, 0x10e5, 0x1215, 0x10e2, 0x12e2, 0x1413, - 0x1414, 0x1415, 0x080c, 0x151a, 0x0005, 0x0126, 0x00f6, 0x2091, - 0x8000, 0x7000, 0xa086, 0x0001, 0x1904, 0x11f2, 0x080c, 0x158d, - 0x080c, 0x5b41, 0x0150, 0x080c, 0x5b67, 0x15c0, 0x2079, 0x0100, - 0x7828, 0xa085, 0x1800, 0x782a, 0x0488, 0x080c, 0x5a79, 0x7000, - 0xa086, 0x0001, 0x1904, 0x11f2, 0x708c, 0xa086, 0x0028, 0x1904, - 0x11f2, 0x2001, 0x0161, 0x2003, 0x0001, 0x2079, 0x0100, 0x7827, - 0xffff, 0x7a28, 0xa295, 0x1e2f, 0x7a2a, 0x2011, 0x5a14, 0x080c, - 0x6a0e, 0x2011, 0x5a07, 0x080c, 0x6ace, 0x2011, 0x5a56, 0x080c, - 0x6a0e, 0x2011, 0x4b23, 0x080c, 0x6a0e, 0x2011, 0x8030, 0x2019, - 0x0000, 0x708b, 0x0000, 0x080c, 0x1e05, 0x00e8, 0x080c, 0x44d6, - 0x2079, 0x0100, 0x7844, 0xa005, 0x1904, 0x11f2, 0x2011, 0x4b23, - 0x080c, 0x6a0e, 0x2011, 0x5a56, 0x080c, 0x6a0e, 0x080c, 0x1e05, - 0x2001, 0xb88d, 0x2004, 0x780e, 0x7840, 0xa084, 0xfffb, 0x7842, - 0x2011, 0x8010, 0x73cc, 0x080c, 0x3f13, 0x723c, 0xc284, 0x723e, - 0x2001, 0xb60c, 0x200c, 0xc1ac, 0x2102, 0x080c, 0x7fbc, 0x2011, - 0x0004, 0x080c, 0x9d1c, 0x080c, 0x52bf, 0x080c, 0x5b41, 0x0158, - 0x080c, 0x4c4a, 0x0140, 0x708b, 0x0001, 0x70c7, 0x0000, 0x080c, - 0x4673, 0x0804, 0x11f2, 0x080c, 0x537b, 0x0120, 0x7a0c, 0xc2b4, - 0x7a0e, 0x0060, 0x7073, 0x0000, 0x080c, 0xa0c4, 0x70d4, 0xd09c, - 0x1128, 0x70a0, 0xa005, 0x0110, 0x080c, 0x4c28, 0x70df, 0x0000, - 0x70db, 0x0000, 0x72d4, 0x080c, 0x5b41, 0x1180, 0x2011, 0x0000, - 0x0016, 0x080c, 0x2920, 0x2019, 0xb88f, 0x211a, 0x001e, 0x7053, - 0xffff, 0x7057, 0x00ef, 0x7077, 0x0000, 0x0020, 0x2019, 0xb88f, - 0x201b, 0x0000, 0x2079, 0xb652, 0x7804, 0xd0ac, 0x0108, 0xc295, - 0x72d6, 0x080c, 0x5b41, 0x0118, 0xa296, 0x0004, 0x0548, 0x2011, - 0x0001, 0x080c, 0x9d1c, 0x709b, 0x0000, 0x709f, 0xffff, 0x7003, - 0x0002, 0x2079, 0x0100, 0x7827, 0x0003, 0x7828, 0xa085, 0x0003, - 0x782a, 0x00fe, 0x080c, 0x2aed, 0x2011, 0x0005, 0x080c, 0x80fc, - 0x080c, 0x71e5, 0x080c, 0x5b41, 0x0148, 0x00c6, 0x2061, 0x0100, - 0x0016, 0x080c, 0x2920, 0x61e2, 0x001e, 0x00ce, 0x012e, 0x0420, - 0x709b, 0x0000, 0x709f, 0xffff, 0x7003, 0x0002, 0x00f6, 0x2079, - 0x0100, 0x7827, 0x0003, 0x7828, 0xa085, 0x0003, 0x782a, 0x00fe, - 0x2011, 0x0005, 0x080c, 0x80fc, 0x080c, 0x71e5, 0x080c, 0x5b41, - 0x0148, 0x00c6, 0x2061, 0x0100, 0x0016, 0x080c, 0x2920, 0x61e2, - 0x001e, 0x00ce, 0x00fe, 0x012e, 0x0005, 0x00c6, 0x080c, 0x5b41, - 0x1118, 0x20a9, 0x0100, 0x0010, 0x20a9, 0x0082, 0x080c, 0x5b41, - 0x1118, 0x2009, 0x0000, 0x0010, 0x2009, 0x007e, 0x080c, 0x2dcc, - 0x8108, 0x1f04, 0x1206, 0x00ce, 0x7073, 0x0000, 0x7074, 0xa084, - 0x00ff, 0x7076, 0x70a3, 0x0000, 0x0005, 0x0126, 0x2091, 0x8000, - 0x7000, 0xa086, 0x0002, 0x1904, 0x12e0, 0x709c, 0xa086, 0xffff, - 0x0130, 0x080c, 0x2aed, 0x080c, 0x71e5, 0x0804, 0x12e0, 0x70d4, - 0xd0ac, 0x1110, 0xd09c, 0x0540, 0xd084, 0x0530, 0x0006, 0x0016, - 0x2001, 0x0103, 0x2009, 0xb88d, 0x210c, 0x2102, 0x001e, 0x000e, - 0xd08c, 0x01d0, 0x70d8, 0xa086, 0xffff, 0x0190, 0x080c, 0x2c4c, - 0x080c, 0x71e5, 0x70d4, 0xd094, 0x1904, 0x12e0, 0x2011, 0x0001, - 0x2019, 0x0000, 0x080c, 0x2c84, 0x080c, 0x71e5, 0x0804, 0x12e0, - 0x70dc, 0xa005, 0x1904, 0x12e0, 0x7098, 0xa005, 0x1904, 0x12e0, - 0x70d4, 0xd0a4, 0x0118, 0xd0b4, 0x0904, 0x12e0, 0x080c, 0x537b, - 0x1904, 0x12e0, 0x2001, 0xb653, 0x2004, 0xd0ac, 0x01c8, 0x0156, - 0x00c6, 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, 0x501b, - 0x1118, 0x6000, 0xd0ec, 0x1138, 0x001e, 0x8108, 0x1f04, 0x126d, - 0x00ce, 0x015e, 0x0028, 0x001e, 0x00ce, 0x015e, 0x0804, 0x12e0, - 0x0006, 0x0016, 0x2001, 0x0103, 0x2009, 0xb88d, 0x210c, 0x2102, - 0x001e, 0x000e, 0x71a8, 0x81ff, 0x11b0, 0xa006, 0x2009, 0x0200, - 0x20a9, 0x0002, 0x20a1, 0xb8df, 0x40a1, 0x2009, 0x0700, 0x20a9, - 0x0002, 0x20a1, 0xb8cf, 0x40a1, 0x7070, 0x8007, 0x7174, 0x810f, - 0x20a9, 0x0002, 0x40a1, 0x20a1, 0xb8d3, 0x2009, 0x0000, 0x080c, - 0x1500, 0x2001, 0x0000, 0x810f, 0x20a9, 0x0002, 0x40a1, 0x7030, - 0xc08c, 0x7032, 0x7003, 0x0003, 0x709f, 0xffff, 0x080c, 0x1586, - 0xa006, 0x080c, 0x27f8, 0x080c, 0x3f85, 0x00f6, 0x2079, 0x0100, - 0x080c, 0x5b67, 0x0150, 0x080c, 0x5b41, 0x7828, 0x0118, 0xa084, - 0xe1ff, 0x0010, 0xa084, 0xffdf, 0x782a, 0x00fe, 0x2001, 0xb8e2, - 0x2004, 0xa086, 0x0005, 0x1120, 0x2011, 0x0000, 0x080c, 0x80fc, - 0x2011, 0x0000, 0x080c, 0x8106, 0x080c, 0x71e5, 0x080c, 0x72a2, - 0x012e, 0x0005, 0x0016, 0x0046, 0x00f6, 0x0126, 0x2091, 0x8000, - 0x2079, 0x0100, 0x2009, 0xb634, 0x2104, 0xa005, 0x1110, 0x080c, - 0x294c, 0x2009, 0x00f7, 0x080c, 0x4c11, 0x7940, 0xa18c, 0x0010, - 0x7942, 0x7924, 0xd1b4, 0x0110, 0x7827, 0x0040, 0xd19c, 0x0110, - 0x7827, 0x0008, 0x0006, 0x0036, 0x0156, 0x7954, 0xd1ac, 0x1904, - 0x1350, 0x080c, 0x5b53, 0x0158, 0x080c, 0x5b67, 0x1128, 0x2001, - 0xb89e, 0x2003, 0x0000, 0x0070, 0x080c, 0x5b49, 0x0dc0, 0x2001, - 0xb89e, 0x2003, 0xaaaa, 0x2001, 0xb89f, 0x2003, 0x0001, 0x080c, - 0x5a79, 0x0058, 0x080c, 0x5b41, 0x0140, 0x2009, 0x00f8, 0x080c, - 0x4c11, 0x7843, 0x0090, 0x7843, 0x0010, 0x20a9, 0x09c4, 0x7820, - 0xd09c, 0x1138, 0x080c, 0x5b41, 0x0138, 0x7824, 0xd0ac, 0x1904, - 0x13fa, 0x1f04, 0x132f, 0x0070, 0x7824, 0x080c, 0x5b5d, 0x0118, - 0xd0ac, 0x1904, 0x13fa, 0xa084, 0x1800, 0x0d98, 0x7003, 0x0001, - 0x0804, 0x13fa, 0x2001, 0x0001, 0x080c, 0x27f8, 0x0804, 0x1409, - 0x7850, 0xa084, 0x0180, 0x7852, 0x782f, 0x0020, 0x20a9, 0x0046, - 0x1d04, 0x1358, 0x080c, 0x6ab6, 0x1f04, 0x1358, 0x7850, 0xa084, - 0x0180, 0xa085, 0x0400, 0x7852, 0x782f, 0x0000, 0x080c, 0x5b53, - 0x0158, 0x080c, 0x5b67, 0x1128, 0x2001, 0xb89e, 0x2003, 0x0000, - 0x0070, 0x080c, 0x5b49, 0x0dc0, 0x2001, 0xb89e, 0x2003, 0xaaaa, - 0x2001, 0xb89f, 0x2003, 0x0001, 0x080c, 0x5a79, 0x0020, 0x2009, - 0x00f8, 0x080c, 0x4c11, 0x20a9, 0x000e, 0xe000, 0x1f04, 0x1385, - 0x7850, 0xa084, 0x0180, 0xa085, 0x1400, 0x7852, 0x080c, 0x5b41, - 0x0120, 0x7843, 0x0090, 0x7843, 0x0010, 0x2021, 0xe678, 0x2019, - 0xea60, 0x7820, 0xd09c, 0x1558, 0x080c, 0x5b41, 0x05d8, 0x7824, - 0xd0ac, 0x1904, 0x13fa, 0x080c, 0x5b67, 0x1508, 0x0046, 0x2021, - 0x0190, 0x8421, 0x1df0, 0x004e, 0x8421, 0x11c8, 0x7827, 0x0048, - 0x20a9, 0x01f4, 0x1d04, 0x13b2, 0x080c, 0x6ab6, 0x1f04, 0x13b2, - 0x7824, 0xa084, 0x0068, 0x15c8, 0x2001, 0xb89e, 0x2003, 0xaaaa, - 0x2001, 0xb89f, 0x2003, 0x0001, 0x7003, 0x0001, 0x0498, 0x1d04, - 0x13cb, 0x080c, 0x6ab6, 0x8319, 0x1960, 0x2009, 0xb634, 0x2104, - 0x8000, 0x200a, 0xa084, 0xfff0, 0x0120, 0x200b, 0x0000, 0x080c, - 0x294c, 0x00d8, 0x080c, 0x5b53, 0x1140, 0xa4a2, 0x0064, 0x1128, - 0x080c, 0x5b18, 0x7003, 0x0001, 0x00a8, 0x7827, 0x1800, 0xe000, - 0xe000, 0x7824, 0x080c, 0x5b5d, 0x0110, 0xd0ac, 0x1158, 0xa084, - 0x1800, 0x09a8, 0x7003, 0x0001, 0x0028, 0x2001, 0x0001, 0x080c, - 0x27f8, 0x0048, 0x2001, 0xb634, 0x2003, 0x0000, 0x7827, 0x0048, - 0x7828, 0xc09d, 0x782a, 0x7850, 0xa084, 0x0180, 0xa085, 0x0400, - 0x7852, 0x015e, 0x003e, 0x000e, 0x080c, 0x155d, 0x012e, 0x00fe, - 0x004e, 0x001e, 0x0005, 0x0005, 0x0005, 0x0005, 0x2a70, 0x2061, - 0xb8c2, 0x2063, 0x0002, 0x6007, 0x0002, 0x600b, 0x0008, 0x600f, - 0x0017, 0x2001, 0xb89e, 0x2003, 0x0000, 0x708b, 0x0000, 0x2009, - 0x0100, 0x2104, 0xa082, 0x0002, 0x0218, 0x7053, 0xffff, 0x0010, - 0x7053, 0x0000, 0x705b, 0xffff, 0x7073, 0x0000, 0x7077, 0x0000, - 0x080c, 0xa0c4, 0x2061, 0xb88e, 0x6003, 0x0909, 0x6007, 0x0000, - 0x600b, 0x8800, 0x600f, 0x0200, 0x6013, 0x00ff, 0x6017, 0x000f, - 0x601b, 0x0000, 0x601f, 0x07d0, 0x2061, 0xb896, 0x6003, 0x8000, - 0x6007, 0x0000, 0x600b, 0x0000, 0x600f, 0x0200, 0x6013, 0x00ff, - 0x6017, 0x0000, 0x601b, 0x0001, 0x601f, 0x0000, 0x2061, 0xb8b9, - 0x6003, 0x514c, 0x6007, 0x4f47, 0x600b, 0x4943, 0x600f, 0x2020, - 0x2001, 0xb628, 0x2003, 0x0000, 0x0005, 0x04a0, 0x2011, 0x0000, - 0x81ff, 0x0570, 0xa186, 0x0001, 0x1148, 0x2031, 0x8fff, 0x2039, - 0xd601, 0x2021, 0x0100, 0x2029, 0xd600, 0x00e8, 0xa186, 0x0002, - 0x1118, 0x2011, 0x0000, 0x00b8, 0xa186, 0x0005, 0x1118, 0x2011, - 0x0001, 0x0088, 0xa186, 0x0009, 0x1118, 0x2011, 0x0002, 0x0058, - 0xa186, 0x000a, 0x1118, 0x2011, 0x0002, 0x0028, 0xa186, 0x0055, - 0x1110, 0x2011, 0x0003, 0x3800, 0xa084, 0xfffc, 0xa205, 0x20c0, - 0x0804, 0x104d, 0xa00e, 0x2011, 0x0003, 0x2019, 0x14a9, 0x0804, - 0x14fa, 0x2019, 0xaaaa, 0x2061, 0xffff, 0x2c14, 0x2362, 0xe000, - 0xe000, 0x2c04, 0xa306, 0x2262, 0x1110, 0xc1b5, 0xc1a5, 0x2011, - 0x0000, 0x2019, 0x14bc, 0x04f0, 0x2019, 0xaaaa, 0x2061, 0xffff, - 0x2c14, 0x2362, 0xe000, 0xe000, 0x2c1c, 0x2061, 0x7fff, 0xe000, - 0xe000, 0x2c04, 0x2061, 0xffff, 0x2262, 0xa306, 0x0110, 0xc18d, - 0x0008, 0xc185, 0x2011, 0x0002, 0x2019, 0x14d7, 0x0418, 0x2061, - 0xffff, 0x2019, 0xaaaa, 0x2c14, 0x2362, 0xe000, 0xe000, 0x2c04, - 0x2262, 0xa306, 0x1180, 0x2c14, 0x2362, 0xe000, 0xe000, 0x2c1c, - 0x2061, 0x7fff, 0x2c04, 0x2061, 0xffff, 0x2262, 0xa306, 0x1110, - 0xc195, 0x0008, 0xc19d, 0x2011, 0x0001, 0x2019, 0x14f8, 0x0010, - 0x0804, 0x146e, 0x3800, 0xa084, 0xfffc, 0xa205, 0x20c0, 0x0837, - 0x2011, 0x0000, 0x080c, 0x501b, 0x1178, 0x6004, 0xa0c4, 0x00ff, - 0xa8c6, 0x0006, 0x0128, 0xa0c4, 0xff00, 0xa8c6, 0x0600, 0x1120, - 0xa186, 0x0080, 0x0108, 0x8210, 0x8108, 0xa186, 0x0100, 0x1d50, - 0x2208, 0x0005, 0x2091, 0x8000, 0x0e04, 0x151c, 0x0006, 0x0016, - 0x2079, 0x0000, 0x7818, 0xd084, 0x1de8, 0x001e, 0x792e, 0x000e, - 0x782a, 0x000e, 0x7826, 0x3900, 0x783a, 0x7823, 0x8002, 0x781b, - 0x0001, 0x2091, 0x5000, 0x0126, 0x0156, 0x0146, 0x20a9, 0x0010, - 0x20a1, 0xba0d, 0x2091, 0x2000, 0x40a1, 0x20a9, 0x0010, 0x2091, - 0x2200, 0x40a1, 0x20a9, 0x0010, 0x2091, 0x2400, 0x40a1, 0x20a9, - 0x0010, 0x2091, 0x2600, 0x40a1, 0x20a9, 0x0010, 0x2091, 0x2800, - 0x40a1, 0x014e, 0x015e, 0x012e, 0x2079, 0xb600, 0x7803, 0x0005, - 0x2091, 0x4080, 0x04c9, 0x0cf8, 0x0005, 0x0006, 0x080c, 0x15a8, - 0x1518, 0x00f6, 0x2079, 0xb624, 0x2f04, 0x8000, 0x207a, 0xa082, - 0x000f, 0x0258, 0xa006, 0x207a, 0x2079, 0xb626, 0x2f04, 0xa084, - 0x0001, 0xa086, 0x0001, 0x207a, 0x0070, 0x2079, 0xb626, 0x2f7c, - 0x8fff, 0x1128, 0x2001, 0x0c03, 0x2003, 0x0040, 0x0020, 0x2001, - 0x0c03, 0x2003, 0x00c0, 0x00fe, 0x000e, 0x0005, 0x0409, 0x1120, - 0x2001, 0x0c03, 0x2003, 0x0080, 0x0005, 0x00d1, 0x1120, 0x2001, - 0x0c03, 0x2003, 0x0040, 0x0005, 0x0006, 0x0091, 0x1178, 0x2001, - 0x0c03, 0x2003, 0x0040, 0x2009, 0x0fff, 0x00a1, 0x2001, 0x0c03, - 0x2003, 0x0080, 0x2009, 0x0fff, 0x0069, 0x0c88, 0x000e, 0x0005, - 0x00c6, 0x2061, 0x0c00, 0x2c04, 0xa084, 0x00ff, 0xa086, 0x00aa, - 0x00ce, 0x0005, 0x0156, 0x0126, 0xa18c, 0x0fff, 0x21a8, 0x1d04, - 0x15b7, 0x2091, 0x6000, 0x1f04, 0x15b7, 0x012e, 0x015e, 0x0005, - 0x2071, 0xb600, 0x7160, 0x712e, 0x2021, 0x0001, 0xa190, 0x0030, - 0xa298, 0x0030, 0x0240, 0x7064, 0xa302, 0x1228, 0x220a, 0x2208, - 0x2310, 0x8420, 0x0ca8, 0x3800, 0xd08c, 0x0148, 0x7064, 0xa086, - 0xb600, 0x0128, 0x7067, 0xb600, 0x2011, 0x1000, 0x0c48, 0x200b, - 0x0000, 0x74b2, 0x74b6, 0x0005, 0x00e6, 0x0126, 0x2091, 0x8000, - 0x2071, 0xb600, 0x70b4, 0xa0ea, 0x0010, 0x0268, 0x8001, 0x70b6, - 0x702c, 0x2068, 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, 0x0000, - 0x012e, 0x00ee, 0x0005, 0xa06e, 0x0cd8, 0x00e6, 0x2071, 0xb600, - 0x0126, 0x2091, 0x8000, 0x70b4, 0x8001, 0x0260, 0x70b6, 0x702c, - 0x2068, 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, 0x0000, 0x012e, - 0x00ee, 0x0005, 0xa06e, 0x0cd8, 0x00e6, 0x0126, 0x2091, 0x8000, - 0x2071, 0xb600, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70b4, 0x8000, - 0x70b6, 0x012e, 0x00ee, 0x0005, 0x8dff, 0x0138, 0x6804, 0x6807, - 0x0000, 0x0006, 0x0c49, 0x00de, 0x0cb8, 0x0005, 0x00e6, 0x2071, - 0xb600, 0x70b4, 0xa08a, 0x0010, 0xa00d, 0x00ee, 0x0005, 0x00e6, - 0x2071, 0xb913, 0x7007, 0x0000, 0x701b, 0x0000, 0x701f, 0x0000, - 0x2071, 0x0000, 0x7010, 0xa085, 0x8004, 0x7012, 0x00ee, 0x0005, - 0x0126, 0x2091, 0x8000, 0x00e6, 0x2270, 0x700b, 0x0000, 0x2071, - 0xb913, 0x7018, 0xa088, 0xb91c, 0x220a, 0x8000, 0xa084, 0x0007, - 0x701a, 0x7004, 0xa005, 0x1128, 0x00f6, 0x2079, 0x0010, 0x0089, - 0x00fe, 0x00ee, 0x012e, 0x0005, 0x00e6, 0x2071, 0xb913, 0x7004, - 0xa005, 0x1128, 0x00f6, 0x2079, 0x0010, 0x0019, 0x00fe, 0x00ee, - 0x0005, 0x7000, 0x0002, 0x1677, 0x16db, 0x16f8, 0x16f8, 0x7018, - 0x711c, 0xa106, 0x1118, 0x7007, 0x0000, 0x0005, 0x00d6, 0xa180, - 0xb91c, 0x2004, 0x700a, 0x2068, 0x8108, 0xa18c, 0x0007, 0x711e, - 0x7803, 0x0026, 0x6824, 0x7832, 0x6828, 0x7836, 0x682c, 0x783a, - 0x6830, 0x783e, 0x6810, 0x700e, 0x680c, 0x7016, 0x6804, 0x00de, - 0xd084, 0x0120, 0x7007, 0x0001, 0x0029, 0x0005, 0x7007, 0x0002, - 0x00b1, 0x0005, 0x0016, 0x0026, 0x710c, 0x2011, 0x0040, 0xa182, - 0x0040, 0x1210, 0x2110, 0xa006, 0x700e, 0x7212, 0x8203, 0x7822, - 0x7803, 0x0020, 0x7803, 0x0041, 0x002e, 0x001e, 0x0005, 0x0016, - 0x0026, 0x0136, 0x0146, 0x0156, 0x7014, 0x2098, 0x20a1, 0x0014, - 0x7803, 0x0026, 0x710c, 0x2011, 0x0040, 0xa182, 0x0040, 0x1210, - 0x2110, 0xa006, 0x700e, 0x22a8, 0x53a6, 0x8203, 0x7822, 0x7803, - 0x0020, 0x3300, 0x7016, 0x7803, 0x0001, 0x015e, 0x014e, 0x013e, - 0x002e, 0x001e, 0x0005, 0x0136, 0x0146, 0x0156, 0x2099, 0xb6fa, - 0x20a1, 0x0018, 0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x0126, - 0x2091, 0x8000, 0x7803, 0x0041, 0x7007, 0x0003, 0x7000, 0xc084, - 0x7002, 0x700b, 0xb6f5, 0x012e, 0x015e, 0x014e, 0x013e, 0x0005, - 0x0136, 0x0146, 0x0156, 0x2001, 0xb729, 0x209c, 0x20a1, 0x0014, - 0x7803, 0x0026, 0x2001, 0xb72a, 0x20ac, 0x53a6, 0x2099, 0xb72b, - 0x20a1, 0x0018, 0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x0126, - 0x2091, 0x8000, 0x7803, 0x0001, 0x7007, 0x0004, 0x7000, 0xc08c, - 0x7002, 0x700b, 0xb726, 0x012e, 0x015e, 0x014e, 0x013e, 0x0005, - 0x0016, 0x00e6, 0x2071, 0xb913, 0x00f6, 0x2079, 0x0010, 0x7904, - 0x7803, 0x0002, 0xd1fc, 0x0120, 0xa18c, 0x0700, 0x7004, 0x0023, - 0x00fe, 0x00ee, 0x001e, 0x0005, 0x1671, 0x173b, 0x1769, 0x1793, - 0x17c3, 0x173a, 0x0cf8, 0xa18c, 0x0700, 0x1528, 0x0136, 0x0146, - 0x0156, 0x7014, 0x20a0, 0x2099, 0x0014, 0x7803, 0x0040, 0x7010, - 0x20a8, 0x53a5, 0x3400, 0x7016, 0x015e, 0x014e, 0x013e, 0x700c, - 0xa005, 0x0570, 0x7830, 0x7832, 0x7834, 0x7836, 0x080c, 0x16a2, - 0x0005, 0x7008, 0xa080, 0x0002, 0x2003, 0x0100, 0x7007, 0x0000, - 0x080c, 0x1671, 0x0005, 0x7008, 0xa080, 0x0002, 0x2003, 0x0200, - 0x0ca8, 0xa18c, 0x0700, 0x1150, 0x700c, 0xa005, 0x0188, 0x7830, - 0x7832, 0x7834, 0x7836, 0x080c, 0x16b7, 0x0005, 0x7008, 0xa080, - 0x0002, 0x2003, 0x0200, 0x7007, 0x0000, 0x080c, 0x1671, 0x0005, - 0x00d6, 0x7008, 0x2068, 0x7830, 0x6826, 0x7834, 0x682a, 0x7838, - 0x682e, 0x783c, 0x6832, 0x680b, 0x0100, 0x00de, 0x7007, 0x0000, - 0x080c, 0x1671, 0x0005, 0xa18c, 0x0700, 0x1540, 0x0136, 0x0146, - 0x0156, 0x2001, 0xb6f8, 0x2004, 0xa080, 0x000d, 0x20a0, 0x2099, - 0x0014, 0x7803, 0x0040, 0x20a9, 0x0020, 0x53a5, 0x2001, 0xb6fa, - 0x2004, 0xd0bc, 0x0148, 0x2001, 0xb703, 0x2004, 0xa080, 0x000d, - 0x20a0, 0x20a9, 0x0020, 0x53a5, 0x015e, 0x014e, 0x013e, 0x7007, - 0x0000, 0x080c, 0x5ee1, 0x080c, 0x1671, 0x0005, 0x2011, 0x8003, - 0x080c, 0x3f13, 0x0cf8, 0xa18c, 0x0700, 0x1148, 0x2001, 0xb728, - 0x2003, 0x0100, 0x7007, 0x0000, 0x080c, 0x1671, 0x0005, 0x2011, - 0x8004, 0x080c, 0x3f13, 0x0cf8, 0x0126, 0x2091, 0x2200, 0x2079, - 0x0030, 0x2071, 0xb924, 0x7003, 0x0000, 0x700f, 0xb930, 0x7013, - 0xb930, 0x780f, 0x00f6, 0x7803, 0x0004, 0x012e, 0x0005, 0x6934, - 0xa184, 0x0007, 0x0002, 0x17f3, 0x1831, 0x17f3, 0x17f3, 0x17f3, - 0x1819, 0x1800, 0x17f7, 0xa085, 0x0001, 0x0804, 0x184b, 0x684c, - 0xd0bc, 0x0dc8, 0x6860, 0x682e, 0x685c, 0x682a, 0x6858, 0x04c8, - 0xa18c, 0x00ff, 0xa186, 0x001e, 0x1d70, 0x684c, 0xd0bc, 0x0d58, - 0x6860, 0x682e, 0x685c, 0x682a, 0x6804, 0x681a, 0xa080, 0x000d, - 0x2004, 0xa084, 0x000f, 0xa080, 0x2308, 0x2005, 0x6832, 0x6858, - 0x0440, 0xa18c, 0x00ff, 0xa186, 0x0015, 0x19a8, 0x684c, 0xd0ac, - 0x0990, 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, - 0xa080, 0x2308, 0x2005, 0x6832, 0xa006, 0x682e, 0x682a, 0x6858, - 0x0080, 0x684c, 0xd0ac, 0x0904, 0x17f3, 0xa006, 0x682e, 0x682a, - 0x6858, 0xa18c, 0x000f, 0xa188, 0x2308, 0x210d, 0x6932, 0x2d08, - 0x691a, 0x6826, 0x684c, 0xc0dd, 0x684e, 0xa006, 0x680a, 0x697c, - 0x6912, 0x6980, 0x6916, 0x0005, 0x684c, 0xd0ac, 0x090c, 0x151a, - 0x6833, 0x2305, 0x2d08, 0x691a, 0x6858, 0x8001, 0x6826, 0x684c, - 0xc0dd, 0x684e, 0xa006, 0x680a, 0x682e, 0x682a, 0x697c, 0x6912, - 0x6980, 0x6916, 0x0005, 0x20e1, 0x0007, 0x20e1, 0x2000, 0x2001, - 0x020a, 0x2004, 0x82ff, 0x01e8, 0xa280, 0x0004, 0x00d6, 0x206c, - 0x684c, 0xd0dc, 0x1190, 0xa280, 0x0007, 0x2004, 0xa086, 0x000a, - 0x1110, 0x0891, 0x0010, 0x080c, 0x17e7, 0x0138, 0x00de, 0xa280, - 0x0000, 0x2003, 0x0002, 0xa016, 0x0020, 0x6808, 0x8000, 0x680a, - 0x00de, 0x0126, 0x0046, 0x0036, 0x0026, 0x2091, 0x2200, 0x002e, - 0x003e, 0x004e, 0x7000, 0xa005, 0x01d0, 0x710c, 0x220a, 0x8108, - 0x230a, 0x8108, 0x240a, 0x8108, 0xa182, 0xb94b, 0x0210, 0x2009, - 0xb930, 0x710e, 0x7010, 0xa102, 0xa082, 0x0009, 0x0118, 0xa080, - 0x001b, 0x1118, 0x2009, 0x0138, 0x200a, 0x012e, 0x0005, 0x7206, - 0x2001, 0x18ad, 0x0006, 0x2260, 0x0804, 0x19da, 0x0126, 0x0026, - 0x0036, 0x00c6, 0x0006, 0x2091, 0x2200, 0x000e, 0x004e, 0x003e, - 0x002e, 0x00d6, 0x00c6, 0x2460, 0x6110, 0x2168, 0x6a62, 0x6b5e, - 0xa005, 0x0904, 0x190f, 0x6808, 0xa005, 0x0904, 0x1946, 0x7000, - 0xa005, 0x1108, 0x0488, 0x700c, 0x7110, 0xa106, 0x1904, 0x194e, - 0x7004, 0xa406, 0x1548, 0x2001, 0x0005, 0x2004, 0xd08c, 0x0168, - 0x0046, 0x080c, 0x1b22, 0x004e, 0x2460, 0x6010, 0xa080, 0x0002, - 0x2004, 0xa005, 0x0904, 0x1946, 0x0c10, 0x2001, 0x0207, 0x2004, - 0xd09c, 0x1d48, 0x7804, 0xa084, 0x6000, 0x0120, 0xa086, 0x6000, - 0x0108, 0x0c08, 0x7818, 0x6812, 0x781c, 0x6816, 0x7803, 0x0004, - 0x7003, 0x0000, 0x7004, 0x2060, 0x6100, 0xa18e, 0x0004, 0x1904, - 0x194e, 0x2009, 0x0048, 0x080c, 0x86d3, 0x0804, 0x194e, 0x6808, - 0xa005, 0x05a0, 0x7000, 0xa005, 0x0588, 0x700c, 0x7110, 0xa106, - 0x1118, 0x7004, 0xa406, 0x1550, 0x2001, 0x0005, 0x2004, 0xd08c, - 0x0160, 0x0046, 0x080c, 0x1b22, 0x004e, 0x2460, 0x6010, 0xa080, - 0x0002, 0x2004, 0xa005, 0x01d0, 0x0c28, 0x2001, 0x0207, 0x2004, - 0xd09c, 0x1d50, 0x2001, 0x0005, 0x2004, 0xd08c, 0x1d50, 0x7804, - 0xa084, 0x6000, 0x0118, 0xa086, 0x6000, 0x19f0, 0x7818, 0x6812, - 0x781c, 0x6816, 0x7803, 0x0004, 0x7003, 0x0000, 0x6100, 0xa18e, - 0x0004, 0x1120, 0x2009, 0x0048, 0x080c, 0x86d3, 0x00ce, 0x00de, - 0x012e, 0x0005, 0x00f6, 0x00e6, 0x0026, 0x0036, 0x0046, 0x0056, - 0x2071, 0xb924, 0x7000, 0xa086, 0x0000, 0x0904, 0x19b8, 0x7004, - 0xac06, 0x1904, 0x19aa, 0x2079, 0x0030, 0x7000, 0xa086, 0x0003, - 0x0904, 0x19aa, 0x7804, 0xd0fc, 0x15c8, 0x20e1, 0x6000, 0x2011, - 0x0032, 0x2001, 0x0208, 0x200c, 0x2001, 0x0209, 0x2004, 0xa106, - 0x1d88, 0x8211, 0x1db0, 0x7804, 0xd0fc, 0x1540, 0x080c, 0x1e8a, - 0x0026, 0x0056, 0x7803, 0x0004, 0x7804, 0xd0ac, 0x1de8, 0x7803, - 0x0002, 0x7803, 0x0009, 0x7003, 0x0003, 0x7007, 0x0000, 0x005e, - 0x002e, 0x2001, 0x015d, 0x2003, 0x0000, 0x080c, 0x5b41, 0x1138, - 0x0066, 0x2031, 0x0001, 0x080c, 0x5bc3, 0x006e, 0x0058, 0x2001, - 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x0020, 0x080c, 0x1b22, - 0x0804, 0x195a, 0x0156, 0x20a9, 0x0009, 0x2009, 0xb930, 0x2104, - 0xac06, 0x1108, 0x200a, 0xa188, 0x0003, 0x1f04, 0x19af, 0x015e, - 0x005e, 0x004e, 0x003e, 0x002e, 0x00ee, 0x00fe, 0x0005, 0x700c, - 0x7110, 0xa106, 0x0904, 0x1a4e, 0x2104, 0x7006, 0x2060, 0x8108, - 0x211c, 0x8108, 0x2124, 0x8108, 0xa182, 0xb94b, 0x0210, 0x2009, - 0xb930, 0x7112, 0x700c, 0xa106, 0x1128, 0x080c, 0x2920, 0x2001, - 0x0138, 0x2102, 0x8cff, 0x0598, 0x6010, 0x2068, 0x2d58, 0x6828, - 0xa406, 0x1590, 0x682c, 0xa306, 0x1578, 0x7004, 0x2060, 0x6020, - 0xc0d4, 0x6022, 0x684c, 0xd0f4, 0x0128, 0x6817, 0xffff, 0x6813, - 0xffff, 0x00e8, 0x6850, 0xd0f4, 0x1130, 0x7803, 0x0004, 0x6810, - 0x781a, 0x6814, 0x781e, 0x6824, 0x2050, 0x6818, 0x2060, 0x6830, - 0x2040, 0x6034, 0xa0cc, 0x000f, 0x2009, 0x0011, 0x080c, 0x1a51, - 0x0120, 0x2009, 0x0001, 0x080c, 0x1a51, 0x2d58, 0x0005, 0x080c, - 0x1df9, 0x0904, 0x19bf, 0x0cd0, 0x6020, 0xd0f4, 0x11e0, 0xd0d4, - 0x01b8, 0x6038, 0xa402, 0x6034, 0xa303, 0x0108, 0x1288, 0x643a, - 0x6336, 0x6c2a, 0x6b2e, 0x0046, 0x0036, 0x2400, 0x6c7c, 0xa402, - 0x6812, 0x2300, 0x6b80, 0xa303, 0x6816, 0x003e, 0x004e, 0x0018, - 0x080c, 0xa056, 0x09e0, 0x601c, 0xa08e, 0x0008, 0x0904, 0x19e5, - 0xa08e, 0x000a, 0x0904, 0x19e5, 0x2001, 0xb674, 0x2004, 0xd0b4, - 0x1140, 0x6018, 0x2004, 0xd0bc, 0x1120, 0x6817, 0x7fff, 0x6813, - 0xffff, 0x080c, 0x2328, 0x1918, 0x0804, 0x19e5, 0x7003, 0x0000, - 0x0005, 0x8aff, 0x0904, 0x1afc, 0xa03e, 0x2730, 0xc9fc, 0x6850, - 0xd0fc, 0x11b8, 0xd0f4, 0x1588, 0x00d6, 0x2805, 0xac68, 0x2900, - 0x0002, 0x1aba, 0x1a93, 0x1a93, 0x1aba, 0x1aba, 0x1ab2, 0x1aba, - 0x1a93, 0x1aba, 0x1a9b, 0x1a9b, 0x1aba, 0x1aba, 0x1aba, 0x1aaa, - 0x1a9b, 0x7803, 0x0004, 0xc0fc, 0x6852, 0x6b6c, 0x6a70, 0x6d1c, - 0x6c20, 0x00d6, 0xd99c, 0x0140, 0x2805, 0xac68, 0x6f08, 0x6e0c, - 0x080c, 0x23ed, 0x0120, 0x04d0, 0x080c, 0x23ed, 0x15b0, 0x6850, - 0xc0fd, 0x6852, 0x00de, 0xa006, 0x0005, 0xc0f4, 0x6852, 0x6b6c, - 0x6a70, 0x00d6, 0x04c0, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x080c, - 0x23ed, 0x0d80, 0x0410, 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, - 0x6e0c, 0x080c, 0x23ed, 0x0d30, 0x00c8, 0x6d00, 0x6c04, 0x6f08, - 0x6e0c, 0x00a0, 0x00de, 0x00d6, 0x6834, 0xa084, 0x00ff, 0xa086, - 0x001e, 0x1140, 0x00de, 0x080c, 0x22ca, 0x1904, 0x1a51, 0xa00e, - 0x0804, 0x1afc, 0x00de, 0x080c, 0x151a, 0xc9fd, 0x7b22, 0x7a26, - 0x7d32, 0x7c36, 0x7f3a, 0x7e3e, 0x7316, 0x721a, 0x751e, 0x7422, - 0x7726, 0x762a, 0x7902, 0x7100, 0x8108, 0x7102, 0x00de, 0x6828, - 0xa300, 0x682a, 0x682c, 0xa201, 0x682e, 0x8109, 0x2d08, 0x1500, - 0xd9fc, 0x0160, 0xc9fc, 0x080c, 0x22ca, 0x01e8, 0x2805, 0xac68, - 0x6800, 0xa506, 0x11c0, 0x6804, 0xa406, 0x00a8, 0xc9fc, 0x080c, - 0x22ca, 0x0188, 0x2805, 0xac68, 0x6800, 0xa506, 0x1160, 0x6804, - 0xa406, 0x1148, 0x6808, 0xa706, 0x1130, 0x680c, 0xa606, 0x0018, - 0xc9fc, 0x080c, 0x22ca, 0x2168, 0x0005, 0x080c, 0x151a, 0x080c, - 0x1f71, 0x7004, 0x2060, 0x00d6, 0x6010, 0x2068, 0x7003, 0x0000, - 0x080c, 0x1e1a, 0x080c, 0x9d16, 0x0170, 0x6808, 0x8001, 0x680a, - 0x697c, 0x6912, 0x6980, 0x6916, 0x682b, 0xffff, 0x682f, 0xffff, - 0x6850, 0xc0bd, 0x6852, 0x00de, 0x080c, 0x99e6, 0x0804, 0x1d47, - 0x080c, 0x151a, 0x0126, 0x2091, 0x2200, 0x0006, 0x0016, 0x2b68, - 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184, 0x0700, 0x1978, - 0xa184, 0x0003, 0xa086, 0x0003, 0x0d58, 0x7000, 0x0002, 0x1b3f, - 0x1b45, 0x1c56, 0x1d22, 0x1d36, 0x1b3f, 0x1b3f, 0x1b3f, 0x7804, - 0xd09c, 0x1904, 0x1d47, 0x080c, 0x151a, 0x8001, 0x7002, 0xd1bc, - 0x11a0, 0xd19c, 0x1904, 0x1bda, 0xd1dc, 0x1178, 0x8aff, 0x0904, - 0x1bda, 0x2009, 0x0001, 0x080c, 0x1a51, 0x0904, 0x1d47, 0x2009, - 0x0001, 0x080c, 0x1a51, 0x0804, 0x1d47, 0x7803, 0x0004, 0x7003, - 0x0000, 0xd1bc, 0x1904, 0x1bba, 0x0026, 0x0036, 0x7c20, 0x7d24, - 0x7e30, 0x7f34, 0x7818, 0x6812, 0x781c, 0x6816, 0x2001, 0x0201, - 0x2004, 0xa005, 0x0140, 0x7808, 0xd0ec, 0x1128, 0x7803, 0x0009, - 0x7003, 0x0004, 0x0010, 0x080c, 0x1d4b, 0x6b28, 0x6a2c, 0x2400, - 0x686e, 0xa31a, 0x2500, 0x6872, 0xa213, 0x6b2a, 0x6a2e, 0x00c6, - 0x7004, 0x2060, 0x6020, 0xd0f4, 0x1110, 0x633a, 0x6236, 0x00ce, - 0x003e, 0x002e, 0x6e1e, 0x6f22, 0x2500, 0xa405, 0x0128, 0x080c, - 0x22e0, 0x6850, 0xc0fd, 0x6852, 0x2a00, 0x6826, 0x2c00, 0x681a, - 0x2800, 0x6832, 0x6808, 0x8001, 0x680a, 0x1148, 0x684c, 0xd0e4, - 0x0130, 0x7004, 0x2060, 0x2009, 0x0048, 0x080c, 0x86d3, 0x7000, - 0xa086, 0x0004, 0x0904, 0x1d47, 0x7003, 0x0000, 0x080c, 0x19bf, - 0x0804, 0x1d47, 0x0056, 0x7d0c, 0xd5bc, 0x1110, 0x080c, 0xb4c3, - 0x005e, 0x080c, 0x1e1a, 0x00f6, 0x7004, 0x2078, 0x080c, 0x5377, - 0x0118, 0x7820, 0xc0f5, 0x7822, 0x00fe, 0x682b, 0xffff, 0x682f, - 0xffff, 0x6808, 0x8001, 0x680a, 0x697c, 0x791a, 0x6980, 0x791e, - 0x0804, 0x1d47, 0x7004, 0x00c6, 0x2060, 0x6020, 0x00ce, 0xd0f4, - 0x0120, 0x6808, 0x8001, 0x680a, 0x04c0, 0x7818, 0x6812, 0x7a1c, - 0x6a16, 0xd19c, 0x0160, 0xa205, 0x0150, 0x7004, 0xa080, 0x0007, - 0x2004, 0xa084, 0xfffd, 0xa086, 0x0008, 0x1904, 0x1b5d, 0x684c, - 0xc0f5, 0x684e, 0x7814, 0xa005, 0x1520, 0x7003, 0x0000, 0x6808, - 0x8001, 0x680a, 0x01a0, 0x7004, 0x2060, 0x601c, 0xa086, 0x000a, - 0x11a0, 0x0156, 0x20a9, 0x0009, 0x2009, 0xb930, 0x2104, 0xac06, - 0x1108, 0x200a, 0xa188, 0x0003, 0x1f04, 0x1c0e, 0x015e, 0x7004, - 0x2060, 0x2009, 0x0048, 0x080c, 0x86d3, 0x080c, 0x19bf, 0x0804, - 0x1d47, 0x7818, 0x6812, 0x781c, 0x6816, 0x7814, 0x7908, 0xa18c, - 0x0fff, 0xa192, 0x0841, 0x1a04, 0x1aff, 0xa188, 0x0007, 0x8114, - 0x8214, 0x8214, 0xa10a, 0x8104, 0x8004, 0x8004, 0xa20a, 0x810b, - 0x810b, 0x810b, 0x080c, 0x1eb5, 0x7803, 0x0004, 0x780f, 0xffff, - 0x7803, 0x0001, 0x7804, 0xd0fc, 0x0de8, 0x7803, 0x0002, 0x7803, - 0x0004, 0x780f, 0x00f6, 0x7004, 0x7007, 0x0000, 0x2060, 0x2009, - 0x0048, 0x080c, 0x86d3, 0x080c, 0x1f0b, 0x0838, 0x8001, 0x7002, - 0xd194, 0x01b0, 0x7804, 0xd0fc, 0x1904, 0x1cf2, 0xd09c, 0x0138, - 0x7804, 0xd0fc, 0x1904, 0x1cf2, 0xd09c, 0x1904, 0x1cf6, 0x8aff, - 0x0904, 0x1d47, 0x2009, 0x0001, 0x080c, 0x1a51, 0x0804, 0x1d47, - 0xa184, 0x0888, 0x1148, 0x8aff, 0x0904, 0x1d47, 0x2009, 0x0001, - 0x080c, 0x1a51, 0x0804, 0x1d47, 0x7818, 0x6812, 0x7a1c, 0x6a16, - 0xa205, 0x0904, 0x1bf7, 0x7803, 0x0004, 0x7003, 0x0000, 0xd1bc, - 0x1904, 0x1cd4, 0x6834, 0xa084, 0x00ff, 0xa086, 0x0029, 0x1118, - 0xd19c, 0x1904, 0x1bf7, 0x0026, 0x0036, 0x7c20, 0x7d24, 0x7e30, - 0x7f34, 0x7818, 0x6812, 0x781c, 0x6816, 0x2001, 0x0201, 0x2004, - 0xa005, 0x0140, 0x7808, 0xd0ec, 0x1128, 0x7803, 0x0009, 0x7003, - 0x0004, 0x0020, 0x0016, 0x080c, 0x1d4b, 0x001e, 0x6b28, 0x6a2c, - 0x080c, 0x22e0, 0x00d6, 0x2805, 0xac68, 0x6034, 0xd09c, 0x1128, - 0x6808, 0xa31a, 0x680c, 0xa213, 0x0020, 0x6810, 0xa31a, 0x6814, - 0xa213, 0x00de, 0xd194, 0x0904, 0x1b7f, 0x2a00, 0x6826, 0x2c00, - 0x681a, 0x2800, 0x6832, 0x6808, 0x8001, 0x680a, 0x6b2a, 0x6a2e, - 0x003e, 0x002e, 0x0804, 0x1c1d, 0x0056, 0x7d0c, 0x080c, 0xb4c3, - 0x005e, 0x080c, 0x1e1a, 0x00f6, 0x7004, 0x2078, 0x080c, 0x5377, - 0x0118, 0x7820, 0xc0f5, 0x7822, 0x00fe, 0x682b, 0xffff, 0x682f, - 0xffff, 0x6808, 0x8001, 0x680a, 0x697c, 0x791a, 0x6980, 0x791e, - 0x0804, 0x1d47, 0x7804, 0xd09c, 0x0904, 0x1b2a, 0x7c20, 0x7824, - 0xa405, 0x1904, 0x1b2a, 0x7818, 0x6812, 0x7c1c, 0x6c16, 0xa405, - 0x1120, 0x7803, 0x0002, 0x0804, 0x1bf7, 0x751c, 0x7420, 0x7724, - 0x7628, 0x7014, 0xa528, 0x7018, 0xa421, 0xa7b9, 0x0000, 0xa6b1, - 0x0000, 0x7830, 0xa506, 0x1150, 0x7834, 0xa406, 0x1138, 0x7838, - 0xa706, 0x1120, 0x783c, 0xa606, 0x0904, 0x1b2a, 0x7803, 0x0002, - 0x0804, 0x1c83, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0xa00d, - 0x0150, 0x6808, 0x8001, 0x680a, 0x1130, 0x7004, 0x2060, 0x2009, - 0x0048, 0x080c, 0x86d3, 0x080c, 0x19bf, 0x0088, 0x7803, 0x0004, - 0x7003, 0x0000, 0x7004, 0x2060, 0x6010, 0xa005, 0x0da0, 0x2068, - 0x6808, 0x8000, 0x680a, 0x6c28, 0x6b2c, 0x080c, 0x19da, 0x001e, - 0x000e, 0x012e, 0x0005, 0x700c, 0x7110, 0xa106, 0x0904, 0x1ded, - 0x7004, 0x0016, 0x210c, 0xa106, 0x001e, 0x0904, 0x1ded, 0x00d6, - 0x00c6, 0x216c, 0x2d00, 0xa005, 0x0904, 0x1deb, 0x681c, 0xa086, - 0x0008, 0x0904, 0x1deb, 0x6820, 0xd0d4, 0x1904, 0x1deb, 0x6810, - 0x2068, 0x6850, 0xd0fc, 0x05a8, 0x8108, 0x2104, 0x6b2c, 0xa306, - 0x1904, 0x1deb, 0x8108, 0x2104, 0x6a28, 0xa206, 0x1904, 0x1deb, - 0x6850, 0xc0fc, 0xc0f5, 0x6852, 0x686c, 0x7822, 0x7016, 0x6870, - 0x7826, 0x701a, 0x681c, 0x7832, 0x701e, 0x6820, 0x7836, 0x7022, - 0x6818, 0x2060, 0x6034, 0xd09c, 0x0168, 0x6830, 0x2005, 0x00d6, - 0xac68, 0x6808, 0x783a, 0x7026, 0x680c, 0x783e, 0x702a, 0x00de, - 0x0804, 0x1de5, 0xa006, 0x783a, 0x783e, 0x7026, 0x702a, 0x0804, - 0x1de5, 0x8108, 0x2104, 0xa005, 0x1904, 0x1deb, 0x6b2c, 0xa306, - 0x1904, 0x1deb, 0x8108, 0x2104, 0xa005, 0x15e8, 0x6a28, 0xa206, - 0x15d0, 0x6850, 0xc0f5, 0x6852, 0x6830, 0x2005, 0x6918, 0xa160, - 0xa180, 0x000d, 0x2004, 0xd09c, 0x11a0, 0x6008, 0x7822, 0x7016, - 0x686e, 0x600c, 0x7826, 0x701a, 0x6872, 0x6000, 0x7832, 0x701e, - 0x6004, 0x7836, 0x7022, 0xa006, 0x783a, 0x783e, 0x7026, 0x702a, - 0x00a0, 0x6010, 0x7822, 0x7016, 0x686e, 0x6014, 0x7826, 0x701a, - 0x6872, 0x6000, 0x7832, 0x701e, 0x6004, 0x7836, 0x7022, 0x6008, - 0x783a, 0x7026, 0x600c, 0x783e, 0x702a, 0x6810, 0x781a, 0x6814, - 0x781e, 0x7803, 0x0011, 0x00ce, 0x00de, 0x0005, 0x2011, 0x0201, - 0x2009, 0x003c, 0x2204, 0xa005, 0x1118, 0x8109, 0x1dd8, 0x0005, - 0x0005, 0x0ca1, 0x0118, 0x780c, 0xd0a4, 0x0120, 0x00d9, 0xa085, - 0x0001, 0x0010, 0x080c, 0x1f0b, 0x0005, 0x0126, 0x2091, 0x2200, - 0x7000, 0xa086, 0x0003, 0x1160, 0x700c, 0x7110, 0xa106, 0x0140, - 0x080c, 0x2991, 0x20e1, 0x9028, 0x700f, 0xb930, 0x7013, 0xb930, - 0x012e, 0x0005, 0x00c6, 0x080c, 0x5b41, 0x11b8, 0x2001, 0x0160, - 0x2003, 0x0000, 0x2001, 0x0138, 0x2003, 0x0000, 0x2011, 0x00c8, - 0xe000, 0xe000, 0x8211, 0x1de0, 0x04b1, 0x0066, 0x2031, 0x0000, - 0x080c, 0x5bc3, 0x006e, 0x00ce, 0x0005, 0x080c, 0x1e8a, 0x080c, - 0x2991, 0x20e1, 0x9028, 0x700c, 0x7110, 0xa106, 0x01c0, 0x2104, - 0xa005, 0x0130, 0x2060, 0x6010, 0x2060, 0x6008, 0x8001, 0x600a, - 0xa188, 0x0003, 0xa182, 0xb94b, 0x0210, 0x2009, 0xb930, 0x7112, - 0x700c, 0xa106, 0x1d40, 0x080c, 0x2920, 0x2110, 0x0c20, 0x2001, - 0x015d, 0x2003, 0x0000, 0x2001, 0x0160, 0x2502, 0x2001, 0x0138, - 0x2202, 0x00ce, 0x0005, 0x080c, 0x2991, 0x20e1, 0x9028, 0x2001, - 0x015d, 0x2003, 0x0000, 0x00e6, 0x00c6, 0x0016, 0x2071, 0xb924, - 0x700c, 0x7110, 0xa106, 0x0190, 0x2104, 0xa005, 0x0130, 0x2060, - 0x6010, 0x2060, 0x6008, 0x8001, 0x600a, 0xa188, 0x0003, 0xa182, - 0xb94b, 0x0210, 0x2009, 0xb930, 0x7112, 0x0c50, 0x001e, 0x00ce, - 0x00ee, 0x0005, 0x2001, 0x0138, 0x2014, 0x2003, 0x0000, 0x2001, - 0x0160, 0x202c, 0x2003, 0x0000, 0x080c, 0x5b41, 0x1148, 0x2021, - 0x0002, 0x1d04, 0x1e99, 0x2091, 0x6000, 0x8421, 0x1dd0, 0x0005, - 0x2021, 0xb015, 0x2001, 0x0141, 0x201c, 0xd3dc, 0x1168, 0x2001, - 0x0109, 0x201c, 0xa39c, 0x0048, 0x1138, 0x2001, 0x0111, 0x201c, - 0x83ff, 0x1110, 0x8421, 0x1d70, 0x0005, 0x00e6, 0x2071, 0x0200, - 0x7808, 0xa084, 0xf000, 0xa10d, 0x0869, 0x2001, 0x0105, 0x2004, - 0xa084, 0x0003, 0x1130, 0x2001, 0xb94b, 0x2004, 0xa086, 0x0000, - 0x0548, 0xa026, 0x2019, 0xf000, 0x8319, 0x1148, 0x2001, 0x012b, - 0x2003, 0x95f5, 0x2001, 0x0129, 0x2003, 0x95f5, 0x00d8, 0x2001, - 0x0105, 0x2004, 0xa084, 0x0003, 0x1130, 0x2001, 0xb94b, 0x2004, - 0xa086, 0x0000, 0x0178, 0x2001, 0x0132, 0x2004, 0xa436, 0x0110, - 0x2020, 0x0c00, 0x2001, 0x0021, 0x2004, 0xd0fc, 0x09e8, 0x080c, - 0x216d, 0x08c0, 0x20e1, 0x7000, 0x7324, 0x7420, 0x7028, 0x7028, - 0x7426, 0x7037, 0x0001, 0x810f, 0x712e, 0x702f, 0x0100, 0x7037, - 0x0008, 0x7326, 0x7422, 0x2001, 0x0160, 0x2502, 0x2001, 0x0138, - 0x2202, 0x00ee, 0x0005, 0x0026, 0x2001, 0x015d, 0x2003, 0x0000, - 0x7908, 0xa18c, 0x0fff, 0xa182, 0x0ffd, 0x0210, 0x2009, 0x0000, - 0xa190, 0x0007, 0xa294, 0x1ff8, 0x8214, 0x8214, 0x8214, 0x2001, - 0x020a, 0x82ff, 0x0140, 0x20e1, 0x6000, 0x200c, 0x200c, 0x200c, - 0x200c, 0x8211, 0x1dd0, 0x20e1, 0x7000, 0x200c, 0x200c, 0x7003, - 0x0000, 0x20e1, 0x6000, 0x2001, 0x0208, 0x200c, 0x2001, 0x0209, - 0x2004, 0xa106, 0x0158, 0x080c, 0x1dee, 0x0130, 0x7908, 0xd1ec, - 0x1128, 0x790c, 0xd1a4, 0x0960, 0x080c, 0x1e1a, 0xa006, 0x002e, - 0x0005, 0x00f6, 0x00e6, 0x0016, 0x0026, 0x2071, 0xb924, 0x2079, - 0x0030, 0x2011, 0x0050, 0x7000, 0xa086, 0x0000, 0x01a8, 0x8211, - 0x0188, 0x2001, 0x0005, 0x2004, 0xd08c, 0x0dc8, 0x7904, 0xa18c, - 0x0780, 0x0016, 0x080c, 0x1b22, 0x001e, 0x81ff, 0x1118, 0x2011, - 0x0050, 0x0c48, 0xa085, 0x0001, 0x002e, 0x001e, 0x00ee, 0x00fe, - 0x0005, 0x7803, 0x0004, 0x2009, 0x0064, 0x7804, 0xd0ac, 0x0904, - 0x1fbd, 0x8109, 0x1dd0, 0x2009, 0x0100, 0x210c, 0xa18a, 0x0003, - 0x0a0c, 0x151a, 0x080c, 0x2274, 0x00e6, 0x00f6, 0x2071, 0xb913, - 0x2079, 0x0010, 0x7004, 0xa086, 0x0000, 0x0538, 0x7800, 0x0006, - 0x7820, 0x0006, 0x7830, 0x0006, 0x7834, 0x0006, 0x7838, 0x0006, - 0x783c, 0x0006, 0x7803, 0x0004, 0xe000, 0xe000, 0x2079, 0x0030, - 0x7804, 0xd0ac, 0x190c, 0x151a, 0x2079, 0x0010, 0x000e, 0x783e, - 0x000e, 0x783a, 0x000e, 0x7836, 0x000e, 0x7832, 0x000e, 0x7822, - 0x000e, 0x7802, 0x00fe, 0x00ee, 0x0030, 0x00fe, 0x00ee, 0x7804, - 0xd0ac, 0x190c, 0x151a, 0x080c, 0x72a2, 0x0005, 0x00e6, 0x2071, - 0xb94b, 0x7003, 0x0000, 0x00ee, 0x0005, 0x00d6, 0xa280, 0x0004, - 0x206c, 0x694c, 0xd1dc, 0x1904, 0x203b, 0x6934, 0xa184, 0x0007, - 0x0002, 0x1fd9, 0x2026, 0x1fd9, 0x1fd9, 0x1fd9, 0x200d, 0x1fec, - 0x1fdb, 0x080c, 0x151a, 0x684c, 0xd0b4, 0x0904, 0x212a, 0x6860, - 0x682e, 0x6816, 0x685c, 0x682a, 0x6812, 0x687c, 0x680a, 0x6880, - 0x680e, 0x6958, 0x0804, 0x202e, 0x6834, 0xa084, 0x00ff, 0xa086, - 0x001e, 0x1d38, 0x684c, 0xd0b4, 0x0904, 0x212a, 0x6860, 0x682e, - 0x6816, 0x685c, 0x682a, 0x6812, 0x687c, 0x680a, 0x6880, 0x680e, - 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, - 0x2308, 0x2005, 0x6832, 0x6958, 0x0450, 0xa18c, 0x00ff, 0xa186, - 0x0015, 0x1548, 0x684c, 0xd0b4, 0x0904, 0x212a, 0x6804, 0x681a, - 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x2308, 0x2005, - 0x6832, 0x6958, 0xa006, 0x682e, 0x682a, 0x0088, 0x684c, 0xd0b4, - 0x0904, 0x1afd, 0x6958, 0xa006, 0x682e, 0x682a, 0x2d00, 0x681a, - 0x6834, 0xa084, 0x000f, 0xa080, 0x2308, 0x2005, 0x6832, 0x6926, - 0x684c, 0xc0dd, 0x684e, 0x00de, 0x0005, 0x00f6, 0x2079, 0x0020, - 0x7804, 0xd0fc, 0x190c, 0x216d, 0x00e6, 0x00d6, 0x2071, 0xb94b, - 0x7000, 0xa005, 0x1904, 0x20aa, 0x00c6, 0x7206, 0xa280, 0x0004, - 0x205c, 0x7004, 0x2068, 0x7803, 0x0004, 0x6818, 0x00d6, 0x2068, - 0x686c, 0x7812, 0x6890, 0x00f6, 0x20e1, 0x9040, 0x2079, 0x0200, - 0x781a, 0x2079, 0x0100, 0x8004, 0x78d6, 0x00fe, 0x00de, 0x2b68, - 0x6824, 0x2050, 0x6818, 0x2060, 0x6830, 0x2040, 0x6034, 0xa0cc, - 0x000f, 0x6908, 0x791a, 0x7116, 0x680c, 0x781e, 0x701a, 0xa006, - 0x700e, 0x7012, 0x7004, 0x692c, 0x6814, 0xa106, 0x1120, 0x6928, - 0x6810, 0xa106, 0x0190, 0x2001, 0xb674, 0x2004, 0xd0cc, 0x0110, - 0x00ce, 0x0400, 0x0036, 0x0046, 0x6b14, 0x6c10, 0x080c, 0x2328, - 0x004e, 0x003e, 0x0110, 0x00ce, 0x00a8, 0x8aff, 0x1120, 0x00ce, - 0xa085, 0x0001, 0x0078, 0x0126, 0x2091, 0x8000, 0x2079, 0x0020, - 0x2009, 0x0001, 0x0059, 0x0118, 0x2009, 0x0001, 0x0039, 0x012e, - 0x00ce, 0xa006, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x0076, 0x0066, - 0x0056, 0x0046, 0x0036, 0x0026, 0x8aff, 0x0904, 0x2123, 0x700c, - 0x7214, 0xa23a, 0x7010, 0x7218, 0xa203, 0x0a04, 0x2122, 0xa705, - 0x0904, 0x2122, 0xa03e, 0x2730, 0x6850, 0xd0fc, 0x11a8, 0x00d6, - 0x2805, 0xac68, 0x2900, 0x0002, 0x2105, 0x20ea, 0x20ea, 0x2105, - 0x2105, 0x20fe, 0x2105, 0x20ea, 0x2105, 0x20ef, 0x20ef, 0x2105, - 0x2105, 0x2105, 0x20f6, 0x20ef, 0xc0fc, 0x6852, 0x6b6c, 0x6a70, - 0x6d1c, 0x6c20, 0xd99c, 0x0528, 0x00d6, 0x2805, 0xac68, 0x6f08, - 0x6e0c, 0x00f0, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x00c8, 0x6b10, - 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x0090, 0x00de, 0x00d6, - 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, 0x1138, 0x00de, 0x080c, - 0x22ca, 0x1904, 0x20b4, 0xa00e, 0x00f0, 0x00de, 0x080c, 0x151a, - 0x00de, 0x7b22, 0x7a26, 0x7d32, 0x7c36, 0x7f3a, 0x7e3e, 0x7902, - 0x7000, 0x8000, 0x7002, 0x6828, 0xa300, 0x682a, 0x682c, 0xa201, - 0x682e, 0x700c, 0xa300, 0x700e, 0x7010, 0xa201, 0x7012, 0x080c, - 0x22ca, 0x0008, 0xa006, 0x002e, 0x003e, 0x004e, 0x005e, 0x006e, - 0x007e, 0x0005, 0x080c, 0x151a, 0x0026, 0x2001, 0x0105, 0x2003, - 0x0010, 0x20e1, 0x9040, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, - 0x2060, 0x00d6, 0x6010, 0x2068, 0x080c, 0x9d16, 0x0118, 0x6850, - 0xc0bd, 0x6852, 0x601c, 0xa086, 0x0006, 0x1180, 0x2061, 0x0100, - 0x62c8, 0x2001, 0x00fa, 0x8001, 0x1df0, 0x60c8, 0xa206, 0x1dc0, - 0x60c4, 0x686a, 0x60c8, 0x6866, 0x7004, 0x2060, 0x00de, 0x00c6, - 0x080c, 0x99e6, 0x00ce, 0x2001, 0xb8f0, 0x2004, 0xac06, 0x1150, - 0x20e1, 0x9040, 0x080c, 0x82e4, 0x2011, 0x0000, 0x080c, 0x8106, - 0x080c, 0x72a2, 0x002e, 0x0804, 0x2227, 0x0126, 0x2091, 0x2400, - 0x0006, 0x0016, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x2079, 0x0020, - 0x2071, 0xb94b, 0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, - 0xa184, 0x0700, 0x1904, 0x212c, 0x7000, 0x0002, 0x2227, 0x218a, - 0x21fa, 0x2225, 0x8001, 0x7002, 0xd19c, 0x1170, 0x8aff, 0x05d0, - 0x2009, 0x0001, 0x080c, 0x20ae, 0x0904, 0x2227, 0x2009, 0x0001, - 0x080c, 0x20ae, 0x0804, 0x2227, 0x7803, 0x0004, 0xd194, 0x0148, - 0x6850, 0xc0fc, 0x6852, 0x8aff, 0x11d8, 0x684c, 0xc0f5, 0x684e, - 0x00b8, 0x0026, 0x0036, 0x6b28, 0x6a2c, 0x7820, 0x686e, 0xa31a, - 0x7824, 0x6872, 0xa213, 0x7830, 0x681e, 0x7834, 0x6822, 0x6b2a, - 0x6a2e, 0x003e, 0x002e, 0x080c, 0x22e0, 0x6850, 0xc0fd, 0x6852, - 0x2a00, 0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x7003, 0x0000, - 0x0804, 0x2227, 0x00f6, 0x0026, 0x781c, 0x0006, 0x7818, 0x0006, - 0x2079, 0x0100, 0x7a14, 0xa284, 0x0184, 0xa085, 0x0012, 0x7816, - 0x0036, 0x2019, 0x1000, 0x8319, 0x090c, 0x151a, 0x7820, 0xd0bc, - 0x1dd0, 0x003e, 0x79c8, 0x000e, 0xa102, 0x001e, 0x0006, 0x0016, - 0x79c4, 0x000e, 0xa103, 0x78c6, 0x000e, 0x78ca, 0xa284, 0x0184, - 0xa085, 0x0012, 0x7816, 0x002e, 0x00fe, 0x7803, 0x0008, 0x7003, - 0x0000, 0x0468, 0x8001, 0x7002, 0xd194, 0x0168, 0x7804, 0xd0fc, - 0x1904, 0x217d, 0xd19c, 0x11f8, 0x8aff, 0x0508, 0x2009, 0x0001, - 0x080c, 0x20ae, 0x00e0, 0x0026, 0x0036, 0x6b28, 0x6a2c, 0x080c, - 0x22e0, 0x00d6, 0x2805, 0xac68, 0x6034, 0xd09c, 0x1128, 0x6808, - 0xa31a, 0x680c, 0xa213, 0x0020, 0x6810, 0xa31a, 0x6814, 0xa213, - 0x00de, 0x0804, 0x21ad, 0x0804, 0x21a9, 0x080c, 0x151a, 0x00ce, - 0x00de, 0x00ee, 0x00fe, 0x001e, 0x000e, 0x012e, 0x0005, 0x00f6, - 0x00e6, 0x2071, 0xb94b, 0x7000, 0xa086, 0x0000, 0x05d0, 0x2079, - 0x0020, 0x0016, 0x2009, 0x0207, 0x210c, 0xd194, 0x0198, 0x2009, - 0x020c, 0x210c, 0xa184, 0x0003, 0x0168, 0x080c, 0xb50c, 0x2001, - 0x0133, 0x2004, 0xa005, 0x090c, 0x151a, 0x20e1, 0x9040, 0x2001, - 0x020c, 0x2102, 0x2009, 0x0206, 0x2104, 0x2009, 0x0203, 0x210c, - 0xa106, 0x1110, 0x20e1, 0x9040, 0x7804, 0xd0fc, 0x09d8, 0x080c, - 0x216d, 0x7000, 0xa086, 0x0000, 0x19a8, 0x001e, 0x7803, 0x0004, - 0x7804, 0xd0ac, 0x1de8, 0x20e1, 0x9040, 0x7803, 0x0002, 0x7003, - 0x0000, 0x00ee, 0x00fe, 0x0005, 0x0026, 0x00c6, 0x00d6, 0x00e6, - 0x00f6, 0x2071, 0xb94b, 0x2079, 0x0020, 0x7000, 0xa086, 0x0000, - 0x0540, 0x7004, 0x2060, 0x6010, 0x2068, 0x080c, 0x9d16, 0x0158, - 0x6850, 0xc0b5, 0x6852, 0x680c, 0x7a1c, 0xa206, 0x1120, 0x6808, - 0x7a18, 0xa206, 0x01e0, 0x2001, 0x0105, 0x2003, 0x0010, 0x20e1, - 0x9040, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, 0x080c, - 0x99e6, 0x20e1, 0x9040, 0x080c, 0x82e4, 0x2011, 0x0000, 0x080c, - 0x8106, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x002e, 0x0005, 0x6810, - 0x6a14, 0xa205, 0x1d00, 0x684c, 0xc0dc, 0x684e, 0x2c10, 0x080c, - 0x1fc5, 0x2001, 0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, 0x7803, - 0x0004, 0x7003, 0x0000, 0x2069, 0xb8e1, 0x6833, 0x0000, 0x683f, - 0x0000, 0x08f8, 0x8840, 0x2805, 0xa005, 0x1170, 0x6004, 0xa005, - 0x0168, 0x681a, 0x2060, 0x6034, 0xa084, 0x000f, 0xa080, 0x2308, - 0x2045, 0x88ff, 0x090c, 0x151a, 0x8a51, 0x0005, 0x2050, 0x0005, - 0x8a50, 0x8841, 0x2805, 0xa005, 0x1190, 0x2c00, 0xad06, 0x0120, - 0x6000, 0xa005, 0x1108, 0x2d00, 0x2060, 0x681a, 0x6034, 0xa084, - 0x000f, 0xa080, 0x2318, 0x2045, 0x88ff, 0x090c, 0x151a, 0x0005, - 0x0000, 0x0011, 0x0015, 0x0019, 0x001d, 0x0021, 0x0025, 0x0029, - 0x0000, 0x000f, 0x0015, 0x001b, 0x0021, 0x0027, 0x0000, 0x0000, - 0x0000, 0x22fd, 0x22f9, 0x0000, 0x0000, 0x2307, 0x0000, 0x22fd, - 0x0000, 0x2304, 0x2301, 0x0000, 0x0000, 0x0000, 0x2307, 0x2304, - 0x0000, 0x22ff, 0x22ff, 0x0000, 0x0000, 0x2307, 0x0000, 0x22ff, - 0x0000, 0x2305, 0x2305, 0x0000, 0x0000, 0x0000, 0x2307, 0x2305, - 0x00a6, 0x0096, 0x0086, 0x6b2e, 0x6c2a, 0x6858, 0xa055, 0x0904, - 0x23b9, 0x2d60, 0x6034, 0xa0cc, 0x000f, 0xa9c0, 0x2308, 0xa986, - 0x0007, 0x0130, 0xa986, 0x000e, 0x0118, 0xa986, 0x000f, 0x1120, - 0x605c, 0xa422, 0x6060, 0xa31b, 0x2805, 0xa045, 0x1140, 0x0310, - 0x0804, 0x23b9, 0x6004, 0xa065, 0x0904, 0x23b9, 0x0c18, 0x2805, - 0xa005, 0x01a8, 0xac68, 0xd99c, 0x1128, 0x6808, 0xa422, 0x680c, - 0xa31b, 0x0020, 0x6810, 0xa422, 0x6814, 0xa31b, 0x0620, 0x2300, - 0xa405, 0x0150, 0x8a51, 0x0904, 0x23b9, 0x8840, 0x0c40, 0x6004, - 0xa065, 0x0904, 0x23b9, 0x0830, 0x8a51, 0x0904, 0x23b9, 0x8840, - 0x2805, 0xa005, 0x1158, 0x6004, 0xa065, 0x0904, 0x23b9, 0x6034, - 0xa0cc, 0x000f, 0xa9c0, 0x2308, 0x2805, 0x2040, 0x2b68, 0x6850, - 0xc0fc, 0x6852, 0x0458, 0x8422, 0x8420, 0x831a, 0xa399, 0x0000, - 0x00d6, 0x2b68, 0x6c6e, 0x6b72, 0x00de, 0xd99c, 0x1168, 0x6908, - 0x2400, 0xa122, 0x690c, 0x2300, 0xa11b, 0x0a0c, 0x151a, 0x6800, - 0xa420, 0x6804, 0xa319, 0x0060, 0x6910, 0x2400, 0xa122, 0x6914, - 0x2300, 0xa11b, 0x0a0c, 0x151a, 0x6800, 0xa420, 0x6804, 0xa319, - 0x2b68, 0x6c1e, 0x6b22, 0x6850, 0xc0fd, 0x6852, 0x2c00, 0x681a, - 0x2800, 0x6832, 0x2a00, 0x6826, 0x000e, 0x000e, 0x000e, 0xa006, - 0x0028, 0x008e, 0x009e, 0x00ae, 0xa085, 0x0001, 0x0005, 0x2001, - 0x0005, 0x2004, 0xa084, 0x0007, 0x0002, 0x23cd, 0x23ce, 0x23d1, - 0x23d4, 0x23d9, 0x23dc, 0x23e1, 0x23e6, 0x0005, 0x080c, 0x216d, - 0x0005, 0x080c, 0x1b22, 0x0005, 0x080c, 0x1b22, 0x080c, 0x216d, - 0x0005, 0x080c, 0x1720, 0x0005, 0x080c, 0x216d, 0x080c, 0x1720, - 0x0005, 0x080c, 0x1b22, 0x080c, 0x1720, 0x0005, 0x080c, 0x1b22, - 0x080c, 0x216d, 0x080c, 0x1720, 0x0005, 0x0006, 0x7000, 0xa086, - 0x0001, 0x1158, 0x701c, 0xa506, 0x1140, 0x7020, 0xa406, 0x1128, - 0x7024, 0xa706, 0x1110, 0x7028, 0xa606, 0x000e, 0x0005, 0x0126, - 0x2091, 0x2600, 0x2079, 0x0200, 0x2071, 0xbc80, 0x2069, 0xb600, - 0x080c, 0x24f5, 0x080c, 0x24e5, 0x2009, 0x0004, 0x7912, 0x7817, - 0x0004, 0x080c, 0x282d, 0x781b, 0x0002, 0x20e1, 0x9080, 0x20e1, - 0x4000, 0x20a9, 0x0080, 0x782f, 0x0000, 0x1f04, 0x241b, 0x20e1, - 0x9080, 0x783b, 0x001f, 0x20e1, 0x8700, 0x012e, 0x0005, 0x0126, - 0x2091, 0x2600, 0x781c, 0xd0a4, 0x190c, 0x24e2, 0xa084, 0x0007, - 0x0002, 0x244b, 0x2439, 0x243c, 0x243f, 0x2444, 0x2446, 0x2448, - 0x244a, 0x080c, 0x6436, 0x0078, 0x080c, 0x6475, 0x0060, 0x080c, - 0x6436, 0x080c, 0x6475, 0x0038, 0x0041, 0x0028, 0x0031, 0x0018, - 0x0021, 0x0008, 0x0011, 0x012e, 0x0005, 0x0006, 0x0016, 0x0026, - 0x080c, 0xb50c, 0x7930, 0xa184, 0x0003, 0x01b0, 0x2001, 0xb8f0, - 0x2004, 0xa005, 0x0170, 0x2001, 0x0133, 0x2004, 0xa005, 0x090c, - 0x151a, 0x00c6, 0x2001, 0xb8f0, 0x2064, 0x080c, 0x99e6, 0x00ce, - 0x04b8, 0x20e1, 0x9040, 0x04a0, 0xa184, 0x0030, 0x01e0, 0x6a00, - 0xa286, 0x0003, 0x1108, 0x00a0, 0x080c, 0x5b41, 0x1178, 0x2001, - 0xb89f, 0x2003, 0x0001, 0x2001, 0xb600, 0x2003, 0x0001, 0xa085, - 0x0001, 0x080c, 0x5b85, 0x080c, 0x5a79, 0x0010, 0x080c, 0x4b7b, - 0x080c, 0x24e5, 0x00a8, 0xa184, 0x00c0, 0x0168, 0x00e6, 0x0036, - 0x0046, 0x0056, 0x2071, 0xb924, 0x080c, 0x1e1a, 0x005e, 0x004e, - 0x003e, 0x00ee, 0x0028, 0xa184, 0x0300, 0x0110, 0x20e1, 0x9020, - 0x7932, 0x002e, 0x001e, 0x000e, 0x0005, 0x0016, 0x00e6, 0x00f6, - 0x2071, 0xb600, 0x7128, 0x2001, 0xb891, 0x2102, 0x2001, 0xb899, - 0x2102, 0xa182, 0x0211, 0x1218, 0x2009, 0x0008, 0x0400, 0xa182, - 0x0259, 0x1218, 0x2009, 0x0007, 0x00d0, 0xa182, 0x02c1, 0x1218, - 0x2009, 0x0006, 0x00a0, 0xa182, 0x0349, 0x1218, 0x2009, 0x0005, - 0x0070, 0xa182, 0x0421, 0x1218, 0x2009, 0x0004, 0x0040, 0xa182, - 0x0581, 0x1218, 0x2009, 0x0003, 0x0010, 0x2009, 0x0002, 0x2079, - 0x0200, 0x7912, 0x7817, 0x0004, 0x080c, 0x282d, 0x00fe, 0x00ee, - 0x001e, 0x0005, 0x7938, 0x080c, 0x151a, 0x00e6, 0x0026, 0x2071, - 0x0200, 0x20e1, 0x1000, 0x7220, 0x7028, 0x7020, 0xa206, 0x0de0, - 0x20e1, 0x9010, 0x002e, 0x00ee, 0x0005, 0x20e1, 0xa000, 0x7837, - 0x0001, 0x782f, 0x0000, 0x782f, 0x0000, 0x782f, 0x0000, 0x782f, - 0x0000, 0x7837, 0x0005, 0x20a9, 0x0210, 0x7830, 0xd0bc, 0x1110, - 0x1f04, 0x2505, 0x7837, 0x0001, 0x7837, 0x0000, 0xe000, 0xe000, - 0x20e1, 0xa000, 0x0005, 0x0126, 0x2091, 0x2800, 0x2061, 0x0100, - 0x2071, 0xb600, 0x6024, 0x6026, 0x6053, 0x0030, 0x080c, 0x286c, - 0x6050, 0xa084, 0xfe7f, 0x6052, 0x2009, 0x00ef, 0x6132, 0x6136, - 0x080c, 0x287c, 0x60e7, 0x0000, 0x61ea, 0x60e3, 0x0008, 0x604b, - 0xf7f7, 0x6043, 0x0000, 0x602f, 0x0080, 0x602f, 0x0000, 0x6007, - 0x0e9f, 0x601b, 0x001e, 0x600f, 0x00ff, 0x2001, 0xb88d, 0x2003, - 0x00ff, 0x602b, 0x002f, 0x012e, 0x0005, 0x2001, 0xb632, 0x2003, - 0x0000, 0x2001, 0xb631, 0x2003, 0x0001, 0x0005, 0x0126, 0x2091, - 0x2800, 0x0006, 0x0016, 0x0026, 0x6124, 0xa184, 0x1e2c, 0x1118, - 0xa184, 0x0007, 0x002a, 0xa195, 0x0004, 0xa284, 0x0007, 0x0002, - 0x2582, 0x2568, 0x256b, 0x256e, 0x2573, 0x2575, 0x2579, 0x257d, - 0x080c, 0x6be6, 0x00b8, 0x080c, 0x6cc1, 0x00a0, 0x080c, 0x6cc1, - 0x080c, 0x6be6, 0x0078, 0x0099, 0x0068, 0x080c, 0x6be6, 0x0079, - 0x0048, 0x080c, 0x6cc1, 0x0059, 0x0028, 0x080c, 0x6cc1, 0x080c, - 0x6be6, 0x0029, 0x002e, 0x001e, 0x000e, 0x012e, 0x0005, 0x6124, - 0x6028, 0xd09c, 0x0118, 0xd19c, 0x1904, 0x279b, 0x080c, 0x5b41, - 0x0578, 0x7000, 0xa086, 0x0003, 0x0198, 0x6024, 0xa084, 0x1800, - 0x0178, 0x080c, 0x5b67, 0x0118, 0x080c, 0x5b53, 0x1148, 0x6027, - 0x0020, 0x6043, 0x0000, 0x2001, 0xb89e, 0x2003, 0xaaaa, 0x0458, - 0x080c, 0x5b67, 0x15d0, 0x6024, 0xa084, 0x1800, 0x1108, 0x04a8, - 0x2001, 0xb89e, 0x2003, 0xaaaa, 0x2001, 0xb89f, 0x2003, 0x0001, - 0x2001, 0xb600, 0x2003, 0x0001, 0x080c, 0x5a79, 0x0804, 0x279b, - 0xd1ac, 0x1518, 0x6024, 0xd0dc, 0x1170, 0xd0e4, 0x1188, 0xd0d4, - 0x11a0, 0xd0cc, 0x0130, 0x708c, 0xa086, 0x0028, 0x1110, 0x080c, - 0x5cd0, 0x0804, 0x279b, 0x2001, 0xb89f, 0x2003, 0x0000, 0x0048, - 0x2001, 0xb89f, 0x2003, 0x0002, 0x0020, 0x080c, 0x5c43, 0x0804, - 0x279b, 0x080c, 0x5d75, 0x0804, 0x279b, 0xd1ac, 0x0904, 0x26e3, - 0x080c, 0x5b41, 0x11d8, 0x6027, 0x0020, 0x0006, 0x0026, 0x0036, - 0x080c, 0x5b5d, 0x1170, 0x2001, 0xb89f, 0x2003, 0x0001, 0x2001, - 0xb600, 0x2003, 0x0001, 0x080c, 0x5a79, 0x003e, 0x002e, 0x000e, - 0x0005, 0x003e, 0x002e, 0x000e, 0x080c, 0x5b18, 0x0016, 0x0046, - 0x00c6, 0x644c, 0xa486, 0xf0f0, 0x1138, 0x2061, 0x0100, 0x644a, - 0x6043, 0x0090, 0x6043, 0x0010, 0x74ce, 0xa48c, 0xff00, 0x7034, - 0xd084, 0x0178, 0xa186, 0xf800, 0x1160, 0x703c, 0xd084, 0x1148, - 0xc085, 0x703e, 0x0036, 0x2418, 0x2011, 0x8016, 0x080c, 0x3f13, - 0x003e, 0xa196, 0xff00, 0x05b8, 0x7054, 0xa084, 0x00ff, 0x810f, - 0xa116, 0x0588, 0x7130, 0xd184, 0x1570, 0x2011, 0xb653, 0x2214, - 0xd2ec, 0x0138, 0xc18d, 0x7132, 0x2011, 0xb653, 0x2214, 0xd2ac, - 0x1510, 0x6240, 0xa294, 0x0010, 0x0130, 0x6248, 0xa294, 0xff00, - 0xa296, 0xff00, 0x01c0, 0x7030, 0xd08c, 0x0904, 0x26b0, 0x7034, - 0xd08c, 0x1140, 0x2001, 0xb60c, 0x200c, 0xd1ac, 0x1904, 0x26b0, - 0xc1ad, 0x2102, 0x0036, 0x73cc, 0x2011, 0x8013, 0x080c, 0x3f13, - 0x003e, 0x0804, 0x26b0, 0x7034, 0xd08c, 0x1140, 0x2001, 0xb60c, - 0x200c, 0xd1ac, 0x1904, 0x26b0, 0xc1ad, 0x2102, 0x0036, 0x73cc, - 0x2011, 0x8013, 0x080c, 0x3f13, 0x003e, 0x7130, 0xc185, 0x7132, - 0x2011, 0xb653, 0x220c, 0xd1a4, 0x01d0, 0x0016, 0x2009, 0x0001, - 0x2011, 0x0100, 0x080c, 0x6b8c, 0x2019, 0x000e, 0x080c, 0xb121, - 0xa484, 0x00ff, 0xa080, 0x2df9, 0x200d, 0xa18c, 0xff00, 0x810f, - 0x8127, 0xa006, 0x2009, 0x000e, 0x080c, 0xb1a4, 0x001e, 0xd1ac, - 0x1148, 0x0016, 0x2009, 0x0000, 0x2019, 0x0004, 0x080c, 0x2ca4, - 0x001e, 0x0070, 0x0156, 0x20a9, 0x007f, 0x2009, 0x0000, 0x080c, - 0x501b, 0x1110, 0x080c, 0x4c7e, 0x8108, 0x1f04, 0x26a7, 0x015e, - 0x00ce, 0x004e, 0x2011, 0x0003, 0x080c, 0x80fc, 0x2011, 0x0002, - 0x080c, 0x8106, 0x080c, 0x7fe0, 0x0036, 0x2019, 0x0000, 0x080c, - 0x806b, 0x003e, 0x60e3, 0x0000, 0x001e, 0x2001, 0xb600, 0x2014, - 0xa296, 0x0004, 0x1128, 0xd19c, 0x11b0, 0x6228, 0xc29d, 0x622a, - 0x2003, 0x0001, 0x2001, 0xb623, 0x2003, 0x0000, 0x6027, 0x0020, - 0x080c, 0x5b67, 0x1140, 0x0016, 0x2009, 0x07d0, 0x2011, 0x5a56, - 0x080c, 0x6a94, 0x001e, 0xd194, 0x0904, 0x279b, 0x0016, 0x6220, - 0xd2b4, 0x0904, 0x274c, 0x080c, 0x6a82, 0x080c, 0x7df3, 0x6027, - 0x0004, 0x00f6, 0x2019, 0xb8ea, 0x2304, 0xa07d, 0x0570, 0x7804, - 0xa086, 0x0032, 0x1550, 0x00d6, 0x00c6, 0x00e6, 0x2069, 0x0140, - 0x618c, 0x6288, 0x7818, 0x608e, 0x7808, 0x608a, 0x6043, 0x0002, - 0x2001, 0x0003, 0x8001, 0x1df0, 0x6043, 0x0000, 0x6803, 0x1000, - 0x6803, 0x0000, 0x618e, 0x628a, 0x080c, 0x7102, 0x080c, 0x71e5, - 0x7810, 0x2070, 0x7037, 0x0103, 0x2f60, 0x080c, 0x86a4, 0x00ee, - 0x00ce, 0x00de, 0x00fe, 0x001e, 0x0005, 0x00fe, 0x00d6, 0x2069, - 0x0140, 0x6804, 0xa084, 0x4000, 0x0120, 0x6803, 0x1000, 0x6803, - 0x0000, 0x00de, 0x00c6, 0x2061, 0xb8e1, 0x6028, 0xa09a, 0x00c8, - 0x1238, 0x8000, 0x602a, 0x00ce, 0x080c, 0x7de6, 0x0804, 0x279a, - 0x2019, 0xb8ea, 0x2304, 0xa065, 0x0120, 0x2009, 0x0027, 0x080c, - 0x86d3, 0x00ce, 0x0804, 0x279a, 0xd2bc, 0x0904, 0x279a, 0x080c, - 0x6a8f, 0x6014, 0xa084, 0x0184, 0xa085, 0x0010, 0x6016, 0x6027, - 0x0004, 0x00d6, 0x2069, 0x0140, 0x6804, 0xa084, 0x4000, 0x0120, - 0x6803, 0x1000, 0x6803, 0x0000, 0x00de, 0x00c6, 0x2061, 0xb8e1, - 0x6044, 0xa09a, 0x00c8, 0x12f0, 0x8000, 0x6046, 0x603c, 0x00ce, - 0xa005, 0x0540, 0x2009, 0x07d0, 0x080c, 0x6a87, 0xa080, 0x0007, - 0x2004, 0xa086, 0x0006, 0x1138, 0x6114, 0xa18c, 0x0184, 0xa18d, - 0x0012, 0x6116, 0x00b8, 0x6114, 0xa18c, 0x0184, 0xa18d, 0x0016, - 0x6116, 0x0080, 0x0036, 0x2019, 0x0001, 0x080c, 0x806b, 0x003e, - 0x2019, 0xb8f0, 0x2304, 0xa065, 0x0120, 0x2009, 0x004f, 0x080c, - 0x86d3, 0x00ce, 0x001e, 0xd19c, 0x0904, 0x27f4, 0x7034, 0xd0ac, - 0x1560, 0x0016, 0x0156, 0x6027, 0x0008, 0x602f, 0x0020, 0x20a9, - 0x0006, 0x1d04, 0x27a9, 0x2091, 0x6000, 0x1f04, 0x27a9, 0x602f, - 0x0000, 0x6150, 0xa185, 0x1400, 0x6052, 0x20a9, 0x0366, 0x1d04, - 0x27b7, 0x2091, 0x6000, 0x6020, 0xd09c, 0x1130, 0x015e, 0x6152, - 0x001e, 0x6027, 0x0008, 0x0480, 0x080c, 0x293c, 0x1f04, 0x27b7, - 0x015e, 0x6152, 0x001e, 0x6027, 0x0008, 0x0016, 0x6028, 0xc09c, - 0x602a, 0x2011, 0x0003, 0x080c, 0x80fc, 0x2011, 0x0002, 0x080c, - 0x8106, 0x080c, 0x7fe0, 0x0036, 0x2019, 0x0000, 0x080c, 0x806b, - 0x003e, 0x60e3, 0x0000, 0x080c, 0xb4eb, 0x080c, 0xb506, 0xa085, - 0x0001, 0x080c, 0x5b85, 0x2001, 0xb600, 0x2003, 0x0004, 0x6027, - 0x0008, 0x080c, 0x12e2, 0x001e, 0xa18c, 0xffd0, 0x6126, 0x0005, - 0x0006, 0x0016, 0x0026, 0x00e6, 0x00f6, 0x0126, 0x2091, 0x8000, - 0x2071, 0xb600, 0x71c4, 0x70c6, 0xa116, 0x0500, 0x81ff, 0x0128, - 0x2011, 0x8011, 0x080c, 0x3f13, 0x00c8, 0x2011, 0x8012, 0x080c, - 0x3f13, 0x2001, 0xb672, 0x2004, 0xd0fc, 0x1180, 0x0036, 0x00c6, - 0x080c, 0x28c7, 0x080c, 0x7fbc, 0x2061, 0x0100, 0x2019, 0x0028, - 0x2009, 0x0000, 0x080c, 0x2ca4, 0x00ce, 0x003e, 0x012e, 0x00fe, - 0x00ee, 0x002e, 0x001e, 0x000e, 0x0005, 0x00c6, 0x00f6, 0x0006, - 0x0026, 0x2061, 0x0100, 0xa190, 0x2840, 0x2205, 0x60f2, 0x2011, - 0x284d, 0x2205, 0x60ee, 0x002e, 0x000e, 0x00fe, 0x00ce, 0x0005, - 0x0840, 0x0840, 0x0840, 0x0580, 0x0420, 0x0348, 0x02c0, 0x0258, - 0x0210, 0x01a8, 0x01a8, 0x01a8, 0x01a8, 0x0140, 0x00f8, 0x00d0, - 0x00b0, 0x00a0, 0x2028, 0xa18c, 0x00ff, 0x2130, 0xa094, 0xff00, - 0x1110, 0x81ff, 0x0118, 0x080c, 0x6723, 0x0038, 0xa080, 0x2df9, - 0x200d, 0xa18c, 0xff00, 0x810f, 0xa006, 0x0005, 0xa080, 0x2df9, - 0x200d, 0xa18c, 0x00ff, 0x0005, 0x00d6, 0x2069, 0x0140, 0x2001, - 0xb615, 0x2003, 0x00ef, 0x20a9, 0x0010, 0xa006, 0x6852, 0x6856, - 0x1f04, 0x2877, 0x00de, 0x0005, 0x0006, 0x00d6, 0x0026, 0x2069, - 0x0140, 0x2001, 0xb615, 0x2102, 0x8114, 0x8214, 0x8214, 0x8214, - 0x20a9, 0x0010, 0x6853, 0x0000, 0xa006, 0x82ff, 0x1128, 0xa184, - 0x000f, 0xa080, 0xb51a, 0x2005, 0x6856, 0x8211, 0x1f04, 0x288c, - 0x002e, 0x00de, 0x000e, 0x0005, 0x00c6, 0x2061, 0xb600, 0x6030, - 0x0110, 0xc09d, 0x0008, 0xc09c, 0x6032, 0x00ce, 0x0005, 0x0156, - 0x00d6, 0x0026, 0x0016, 0x0006, 0x2069, 0x0140, 0x6980, 0xa116, - 0x0180, 0xa112, 0x1230, 0x8212, 0x8210, 0x22a8, 0x2001, 0x0402, - 0x0018, 0x22a8, 0x2001, 0x0404, 0x680e, 0x1f04, 0x28bc, 0x680f, - 0x0000, 0x000e, 0x001e, 0x002e, 0x00de, 0x015e, 0x0005, 0x2001, - 0xb653, 0x2004, 0xd0c4, 0x0150, 0xd0a4, 0x0140, 0xa006, 0x0046, - 0x2020, 0x2009, 0x002e, 0x080c, 0xb1a4, 0x004e, 0x0005, 0x00f6, - 0x0016, 0x0026, 0x2079, 0x0140, 0x78c4, 0xd0dc, 0x0548, 0xa084, - 0x0700, 0xa08e, 0x0300, 0x1520, 0x2011, 0x0000, 0x2009, 0x0002, - 0x2300, 0xa080, 0x0020, 0x2018, 0x2300, 0x080c, 0x6bb2, 0x2011, - 0x0030, 0x2200, 0x8007, 0xa085, 0x004c, 0x78c2, 0x2009, 0x0204, - 0x210c, 0x2200, 0xa100, 0x2009, 0x0138, 0x200a, 0x080c, 0x5b41, - 0x1118, 0x2009, 0xb88f, 0x200a, 0x002e, 0x001e, 0x00fe, 0x0005, - 0x78c3, 0x0000, 0x0cc8, 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, - 0x0026, 0x2001, 0x0170, 0x200c, 0x8000, 0x2014, 0xa184, 0x0003, - 0x0110, 0x0804, 0x1b20, 0x002e, 0x001e, 0x000e, 0x012e, 0x0005, - 0x0006, 0x2001, 0x0100, 0x2004, 0xa082, 0x0005, 0x000e, 0x0268, - 0x2001, 0x0170, 0x200c, 0xa18c, 0x00ff, 0xa18e, 0x004c, 0x1128, - 0x200c, 0xa18c, 0xff00, 0x810f, 0x0010, 0x2009, 0x0000, 0x2001, - 0x0204, 0x2004, 0xa108, 0x0005, 0x0006, 0x0156, 0x00f6, 0x2079, - 0x0100, 0x20a9, 0x000a, 0x7854, 0xd08c, 0x1110, 0x1f04, 0x2943, - 0x00fe, 0x015e, 0x000e, 0x0005, 0x0016, 0x00c6, 0x0006, 0x2061, - 0x0100, 0x6030, 0x0006, 0x6048, 0x0006, 0x60e4, 0x0006, 0x60e8, - 0x0006, 0x6050, 0x0006, 0x60f0, 0x0006, 0x60ec, 0x0006, 0x600c, - 0x0006, 0x6004, 0x0006, 0x6028, 0x0006, 0x60e0, 0x0006, 0x602f, - 0x0100, 0x602f, 0x0000, 0xe000, 0xe000, 0xe000, 0xe000, 0x602f, - 0x0040, 0x602f, 0x0000, 0x000e, 0x60e2, 0x000e, 0x602a, 0x000e, - 0x6006, 0x000e, 0x600e, 0x000e, 0x60ee, 0x000e, 0x60f2, 0x000e, - 0x6052, 0x000e, 0x60ea, 0x000e, 0x60e6, 0x000e, 0x604a, 0x000e, - 0x6032, 0x6036, 0x2008, 0x080c, 0x287c, 0x000e, 0x00ce, 0x001e, - 0x0005, 0x2009, 0x0171, 0x2104, 0xd0dc, 0x0140, 0x2009, 0x0170, - 0x2104, 0x200b, 0x0080, 0xe000, 0xe000, 0x200a, 0x0005, 0x2a2f, - 0x2a33, 0x2a37, 0x2a3d, 0x2a43, 0x2a49, 0x2a4f, 0x2a57, 0x2a5f, - 0x2a65, 0x2a6b, 0x2a73, 0x2a7b, 0x2a83, 0x2a8b, 0x2a95, 0x2ae2, - 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, - 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2a9f, - 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, - 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2ae2, - 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, - 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2aa1, - 0x2aa1, 0x2aa7, 0x2aa7, 0x2aae, 0x2aae, 0x2ab5, 0x2ab5, 0x2abe, - 0x2abe, 0x2ac5, 0x2ac5, 0x2ace, 0x2ace, 0x2ad7, 0x2ad7, 0x2ae2, - 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, - 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2a9f, - 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, - 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2ae2, - 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, - 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2a9f, - 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, - 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x0106, - 0x0006, 0x0804, 0x2aea, 0x0106, 0x0006, 0x0804, 0x2aea, 0x0106, - 0x0006, 0x080c, 0x254e, 0x0804, 0x2aea, 0x0106, 0x0006, 0x080c, - 0x254e, 0x0804, 0x2aea, 0x0106, 0x0006, 0x080c, 0x23bf, 0x0804, - 0x2aea, 0x0106, 0x0006, 0x080c, 0x23bf, 0x0804, 0x2aea, 0x0106, - 0x0006, 0x080c, 0x254e, 0x080c, 0x23bf, 0x0804, 0x2aea, 0x0106, - 0x0006, 0x080c, 0x254e, 0x080c, 0x23bf, 0x0804, 0x2aea, 0x0106, - 0x0006, 0x080c, 0x2427, 0x0804, 0x2aea, 0x0106, 0x0006, 0x080c, - 0x2427, 0x0804, 0x2aea, 0x0106, 0x0006, 0x080c, 0x254e, 0x080c, - 0x2427, 0x0804, 0x2aea, 0x0106, 0x0006, 0x080c, 0x254e, 0x080c, - 0x2427, 0x0804, 0x2aea, 0x0106, 0x0006, 0x080c, 0x23bf, 0x080c, - 0x2427, 0x0804, 0x2aea, 0x0106, 0x0006, 0x080c, 0x23bf, 0x080c, - 0x2427, 0x0804, 0x2aea, 0x0106, 0x0006, 0x080c, 0x254e, 0x080c, - 0x23bf, 0x080c, 0x2427, 0x0804, 0x2aea, 0x0106, 0x0006, 0x080c, - 0x254e, 0x080c, 0x23bf, 0x080c, 0x2427, 0x0804, 0x2aea, 0xe000, - 0x0cf0, 0x0106, 0x0006, 0x080c, 0x290b, 0x0804, 0x2aea, 0x0106, - 0x0006, 0x080c, 0x290b, 0x080c, 0x254e, 0x04e0, 0x0106, 0x0006, - 0x080c, 0x290b, 0x080c, 0x23bf, 0x04a8, 0x0106, 0x0006, 0x080c, - 0x290b, 0x080c, 0x254e, 0x080c, 0x23bf, 0x0460, 0x0106, 0x0006, - 0x080c, 0x290b, 0x080c, 0x2427, 0x0428, 0x0106, 0x0006, 0x080c, - 0x290b, 0x080c, 0x254e, 0x080c, 0x2427, 0x00e0, 0x0106, 0x0006, - 0x080c, 0x290b, 0x080c, 0x23bf, 0x080c, 0x2427, 0x0098, 0x0106, - 0x0006, 0x080c, 0x290b, 0x080c, 0x254e, 0x080c, 0x23bf, 0x080c, - 0x2427, 0x0040, 0x20d1, 0x0000, 0x20d1, 0x0001, 0x20d1, 0x0000, - 0x080c, 0x151a, 0x000e, 0x010e, 0x000d, 0x00c6, 0x0026, 0x0046, - 0x2021, 0x0000, 0x080c, 0x537b, 0x1904, 0x2bca, 0x72d4, 0x2001, - 0xb89e, 0x2004, 0xa005, 0x1110, 0xd29c, 0x0148, 0xd284, 0x1138, - 0xd2bc, 0x1904, 0x2bca, 0x080c, 0x2bce, 0x0804, 0x2bca, 0xd2cc, - 0x1904, 0x2bca, 0x080c, 0x5b41, 0x1120, 0x709f, 0xffff, 0x0804, - 0x2bca, 0xd294, 0x0120, 0x709f, 0xffff, 0x0804, 0x2bca, 0x2001, - 0xb615, 0x203c, 0x7288, 0xd284, 0x0904, 0x2b6c, 0xd28c, 0x1904, - 0x2b6c, 0x0036, 0x739c, 0xa38e, 0xffff, 0x1110, 0x2019, 0x0001, - 0x8314, 0xa2e0, 0xbdc0, 0x2c04, 0xa38c, 0x0001, 0x0120, 0xa084, - 0xff00, 0x8007, 0x0010, 0xa084, 0x00ff, 0xa70e, 0x0560, 0xa08e, - 0x0000, 0x0548, 0xa08e, 0x00ff, 0x1150, 0x7230, 0xd284, 0x1538, - 0x7288, 0xc28d, 0x728a, 0x709f, 0xffff, 0x003e, 0x0428, 0x2009, - 0x0000, 0x080c, 0x2852, 0x080c, 0x4fbf, 0x11b8, 0x6004, 0xa084, - 0x00ff, 0xa086, 0x0006, 0x1150, 0x7030, 0xd08c, 0x0118, 0x6000, - 0xd0bc, 0x0120, 0x080c, 0x2be1, 0x0140, 0x0028, 0x080c, 0x2d12, - 0x080c, 0x2c0f, 0x0110, 0x8318, 0x0818, 0x739e, 0x0010, 0x709f, - 0xffff, 0x003e, 0x0804, 0x2bca, 0xa780, 0x2df9, 0x203d, 0xa7bc, - 0xff00, 0x873f, 0x2041, 0x007e, 0x709c, 0xa096, 0xffff, 0x1120, - 0x2009, 0x0000, 0x28a8, 0x0050, 0xa812, 0x0220, 0x2008, 0xa802, - 0x20a8, 0x0020, 0x709f, 0xffff, 0x0804, 0x2bca, 0x2700, 0x0156, - 0x0016, 0xa106, 0x05a0, 0xc484, 0x080c, 0x501b, 0x0120, 0x080c, - 0x4fbf, 0x15a8, 0x0008, 0xc485, 0x6004, 0xa084, 0x00ff, 0xa086, - 0x0006, 0x1130, 0x7030, 0xd08c, 0x01e8, 0x6000, 0xd0bc, 0x11d0, - 0x7288, 0xd28c, 0x0188, 0x6004, 0xa084, 0x00ff, 0xa082, 0x0006, - 0x02b0, 0xd484, 0x1118, 0x080c, 0x4fde, 0x0028, 0x080c, 0x2d9f, - 0x0170, 0x080c, 0x2dcc, 0x0058, 0x080c, 0x2d12, 0x080c, 0x2c0f, - 0x0170, 0x0028, 0x080c, 0x2d9f, 0x0110, 0x0419, 0x0140, 0x001e, - 0x8108, 0x015e, 0x1f04, 0x2b86, 0x709f, 0xffff, 0x0018, 0x001e, - 0x015e, 0x719e, 0x004e, 0x002e, 0x00ce, 0x0005, 0x00c6, 0x0016, - 0x709f, 0x0001, 0x2009, 0x007e, 0x080c, 0x4fbf, 0x1138, 0x080c, - 0x2d12, 0x04a9, 0x0118, 0x70d4, 0xc0bd, 0x70d6, 0x001e, 0x00ce, - 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68, 0x2001, 0xb657, - 0x2004, 0xa084, 0x00ff, 0x6842, 0x080c, 0x9f92, 0x01d8, 0x2d00, - 0x601a, 0x080c, 0xa0e3, 0x601f, 0x0001, 0x2001, 0x0000, 0x080c, - 0x4f5d, 0x2001, 0x0000, 0x080c, 0x4f6f, 0x0126, 0x2091, 0x8000, - 0x7098, 0x8000, 0x709a, 0x012e, 0x2009, 0x0004, 0x080c, 0x86d3, - 0xa085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x0016, - 0x0076, 0x00d6, 0x00c6, 0x2c68, 0x2001, 0xb657, 0x2004, 0xa084, - 0x00ff, 0x6842, 0x080c, 0x9f92, 0x0550, 0x2d00, 0x601a, 0x6800, - 0xc0c4, 0x6802, 0x68a0, 0xa086, 0x007e, 0x0140, 0x6804, 0xa084, - 0x00ff, 0xa086, 0x0006, 0x1110, 0x080c, 0x2cd1, 0x080c, 0xa0e3, - 0x601f, 0x0001, 0x2001, 0x0000, 0x080c, 0x4f5d, 0x2001, 0x0002, - 0x080c, 0x4f6f, 0x0126, 0x2091, 0x8000, 0x7098, 0x8000, 0x709a, - 0x012e, 0x2009, 0x0002, 0x080c, 0x86d3, 0xa085, 0x0001, 0x00ce, - 0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, 0x0026, 0x2009, 0x0080, - 0x080c, 0x4fbf, 0x1120, 0x0031, 0x0110, 0x70db, 0xffff, 0x002e, - 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68, 0x080c, - 0x864e, 0x01e8, 0x2d00, 0x601a, 0x080c, 0xa0e3, 0x601f, 0x0001, - 0x2001, 0x0000, 0x080c, 0x4f5d, 0x2001, 0x0002, 0x080c, 0x4f6f, - 0x0126, 0x2091, 0x8000, 0x080c, 0x2cd1, 0x70dc, 0x8000, 0x70de, - 0x012e, 0x2009, 0x0002, 0x080c, 0x86d3, 0xa085, 0x0001, 0x00ce, - 0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0126, 0x2091, - 0x8000, 0x2009, 0x007f, 0x080c, 0x4fbf, 0x1190, 0x2c68, 0x080c, - 0x864e, 0x0170, 0x2d00, 0x601a, 0x6312, 0x601f, 0x0001, 0x620a, - 0x080c, 0xa0e3, 0x2009, 0x0022, 0x080c, 0x86d3, 0xa085, 0x0001, - 0x012e, 0x00de, 0x00ce, 0x0005, 0x00e6, 0x00c6, 0x0066, 0x0036, - 0x0026, 0x080c, 0x6e73, 0x080c, 0x6e16, 0x080c, 0x90fb, 0x2130, - 0x81ff, 0x0128, 0x20a9, 0x007e, 0x2009, 0x0000, 0x0020, 0x20a9, - 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, 0x501b, 0x1120, 0x080c, - 0x521c, 0x080c, 0x4c7e, 0x001e, 0x8108, 0x1f04, 0x2cbb, 0x86ff, - 0x1110, 0x080c, 0x11f5, 0x002e, 0x003e, 0x006e, 0x00ce, 0x00ee, - 0x0005, 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x6218, 0x2270, - 0x72a0, 0x0026, 0x2019, 0x0029, 0x080c, 0x6e67, 0x0076, 0x2039, - 0x0000, 0x080c, 0x6d74, 0x2c08, 0x080c, 0xaf3e, 0x007e, 0x001e, - 0x2e60, 0x080c, 0x521c, 0x6210, 0x6314, 0x080c, 0x4c7e, 0x6212, - 0x6316, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee, 0x0005, 0x00e6, - 0x0006, 0x6018, 0xa080, 0x0028, 0x2004, 0xa086, 0x0080, 0x0150, - 0x2071, 0xb600, 0x7098, 0xa005, 0x0110, 0x8001, 0x709a, 0x000e, - 0x00ee, 0x0005, 0x2071, 0xb600, 0x70dc, 0xa005, 0x0dc0, 0x8001, - 0x70de, 0x0ca8, 0x6000, 0xc08c, 0x6002, 0x0005, 0x00f6, 0x00e6, - 0x00c6, 0x0036, 0x0026, 0x0016, 0x0156, 0x2178, 0x81ff, 0x1118, - 0x20a9, 0x0001, 0x0098, 0x2001, 0xb653, 0x2004, 0xd0c4, 0x0150, - 0xd0a4, 0x0140, 0xa006, 0x0046, 0x2020, 0x2009, 0x002d, 0x080c, - 0xb1a4, 0x004e, 0x20a9, 0x00ff, 0x2011, 0x0000, 0x0026, 0xa28e, - 0x007e, 0x0904, 0x2d7e, 0xa28e, 0x007f, 0x0904, 0x2d7e, 0xa28e, - 0x0080, 0x05e0, 0xa288, 0xb735, 0x210c, 0x81ff, 0x05b8, 0x8fff, - 0x1148, 0x2001, 0xb8be, 0x0006, 0x2003, 0x0001, 0x04d9, 0x000e, - 0x2003, 0x0000, 0x00c6, 0x2160, 0x2001, 0x0001, 0x080c, 0x5385, - 0x00ce, 0x2019, 0x0029, 0x080c, 0x6e67, 0x0076, 0x2039, 0x0000, - 0x080c, 0x6d74, 0x00c6, 0x0026, 0x2160, 0x6204, 0xa294, 0x00ff, - 0xa286, 0x0006, 0x1118, 0x6007, 0x0404, 0x0028, 0x2001, 0x0004, - 0x8007, 0xa215, 0x6206, 0x002e, 0x00ce, 0x0016, 0x2c08, 0x080c, - 0xaf3e, 0x001e, 0x007e, 0x2160, 0x080c, 0x521c, 0x002e, 0x8210, - 0x1f04, 0x2d36, 0x015e, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee, - 0x00fe, 0x0005, 0x0046, 0x0026, 0x0016, 0x2001, 0xb653, 0x2004, - 0xd0c4, 0x0148, 0xd0a4, 0x0138, 0xa006, 0x2220, 0x8427, 0x2009, - 0x0029, 0x080c, 0xb1a4, 0x001e, 0x002e, 0x004e, 0x0005, 0x0016, - 0x0026, 0x0036, 0x00c6, 0x7288, 0x82ff, 0x01f8, 0x2011, 0xb653, - 0x2214, 0xd2ac, 0x11d0, 0x2100, 0x080c, 0x2866, 0x81ff, 0x01b8, - 0x2019, 0x0001, 0x8314, 0xa2e0, 0xbdc0, 0x2c04, 0xd384, 0x0120, - 0xa084, 0xff00, 0x8007, 0x0010, 0xa084, 0x00ff, 0xa116, 0x0138, - 0xa096, 0x00ff, 0x0110, 0x8318, 0x0c68, 0xa085, 0x0001, 0x00ce, - 0x003e, 0x002e, 0x001e, 0x0005, 0x0016, 0x00c6, 0x0126, 0x2091, - 0x8000, 0x0016, 0x0026, 0x0036, 0x2110, 0x0026, 0x2019, 0x0029, - 0x080c, 0x8320, 0x002e, 0x080c, 0xb449, 0x003e, 0x002e, 0x001e, - 0xa180, 0xb735, 0x2004, 0xa065, 0x0158, 0x0016, 0x00c6, 0x2061, - 0xb9f5, 0x001e, 0x611a, 0x080c, 0x2cd1, 0x001e, 0x080c, 0x4fde, - 0x012e, 0x00ce, 0x001e, 0x0005, 0x2001, 0xb635, 0x2004, 0xd0cc, - 0x0005, 0x7eef, 0x7de8, 0x7ce4, 0x80e2, 0x7be1, 0x80e0, 0x80dc, - 0x80da, 0x7ad9, 0x80d6, 0x80d5, 0x80d4, 0x80d3, 0x80d2, 0x80d1, - 0x79ce, 0x78cd, 0x80cc, 0x80cb, 0x80ca, 0x80c9, 0x80c7, 0x80c6, - 0x77c5, 0x76c3, 0x80bc, 0x80ba, 0x75b9, 0x80b6, 0x74b5, 0x73b4, - 0x72b3, 0x80b2, 0x80b1, 0x80ae, 0x71ad, 0x80ac, 0x70ab, 0x6faa, - 0x6ea9, 0x80a7, 0x6da6, 0x6ca5, 0x6ba3, 0x6a9f, 0x699e, 0x689d, - 0x809b, 0x8098, 0x6797, 0x6690, 0x658f, 0x6488, 0x6384, 0x6282, - 0x8081, 0x8080, 0x617c, 0x607a, 0x8079, 0x5f76, 0x8075, 0x8074, - 0x8073, 0x8072, 0x8071, 0x806e, 0x5e6d, 0x806c, 0x5d6b, 0x5c6a, - 0x5b69, 0x8067, 0x5a66, 0x5965, 0x5863, 0x575c, 0x565a, 0x5559, - 0x8056, 0x8055, 0x5454, 0x5353, 0x5252, 0x5151, 0x504e, 0x4f4d, - 0x804c, 0x804b, 0x4e4a, 0x4d49, 0x8047, 0x4c46, 0x8045, 0x8043, - 0x803c, 0x803a, 0x8039, 0x8036, 0x4b35, 0x8034, 0x4a33, 0x4932, - 0x4831, 0x802e, 0x472d, 0x462c, 0x452b, 0x442a, 0x4329, 0x4227, - 0x8026, 0x8025, 0x4123, 0x401f, 0x3f1e, 0x3e1d, 0x3d1b, 0x3c18, - 0x8017, 0x8010, 0x3b0f, 0x3a08, 0x8004, 0x3902, 0x8001, 0x8000, - 0x8000, 0x3800, 0x3700, 0x3600, 0x8000, 0x3500, 0x8000, 0x8000, - 0x8000, 0x3400, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, - 0x3300, 0x3200, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, - 0x3100, 0x3000, 0x8000, 0x8000, 0x2f00, 0x8000, 0x2e00, 0x2d00, - 0x2c00, 0x8000, 0x8000, 0x8000, 0x2b00, 0x8000, 0x2a00, 0x2900, - 0x2800, 0x8000, 0x2700, 0x2600, 0x2500, 0x2400, 0x2300, 0x2200, - 0x8000, 0x8000, 0x2100, 0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00, - 0x8000, 0x8000, 0x1b00, 0x1a00, 0x8000, 0x1900, 0x8000, 0x8000, - 0x8000, 0x8000, 0x8000, 0x8000, 0x1800, 0x8000, 0x1700, 0x1600, - 0x1500, 0x8000, 0x1400, 0x1300, 0x1200, 0x1100, 0x1000, 0x0f00, - 0x8000, 0x8000, 0x0e00, 0x0d00, 0x0c00, 0x0b00, 0x0a00, 0x0900, - 0x8000, 0x8000, 0x0800, 0x0700, 0x8000, 0x0600, 0x8000, 0x8000, - 0x8000, 0x0500, 0x0400, 0x0300, 0x8000, 0x0200, 0x8000, 0x8000, - 0x8000, 0x0100, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, - 0x0000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, - 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, - 0x8000, 0x2071, 0xb682, 0x7003, 0x0002, 0xa006, 0x7012, 0x7016, - 0x703a, 0x703e, 0x7033, 0xb692, 0x7037, 0xb692, 0x7007, 0x0001, - 0x2061, 0xb6d2, 0x6003, 0x0002, 0x0005, 0x1004, 0x2f1f, 0x0e04, - 0x2f1f, 0x2071, 0xb682, 0x2b78, 0x7818, 0xd084, 0x1140, 0x2a60, - 0x7820, 0xa08e, 0x0069, 0x1904, 0x3004, 0x0804, 0x2f9d, 0x0005, - 0x2071, 0xb682, 0x7004, 0x0002, 0x2f28, 0x2f29, 0x2f32, 0x2f43, - 0x0005, 0x1004, 0x2f31, 0x0e04, 0x2f31, 0x2b78, 0x7818, 0xd084, - 0x01e8, 0x0005, 0x2b78, 0x2061, 0xb6d2, 0x6008, 0xa08e, 0x0100, - 0x0128, 0xa086, 0x0200, 0x0904, 0x2ffe, 0x0005, 0x7014, 0x2068, - 0x2a60, 0x7018, 0x0807, 0x7010, 0x2068, 0x6834, 0xa086, 0x0103, - 0x0108, 0x0005, 0x2a60, 0x2b78, 0x7018, 0x0807, 0x2a60, 0x7820, - 0xa08a, 0x0040, 0x1210, 0x61c4, 0x0042, 0x2100, 0xa08a, 0x003f, - 0x1a04, 0x2ffb, 0x61c4, 0x0804, 0x2f9d, 0x2fdf, 0x300a, 0x3012, - 0x3016, 0x301e, 0x3024, 0x3028, 0x3034, 0x3037, 0x3041, 0x3044, - 0x2ffb, 0x2ffb, 0x2ffb, 0x3047, 0x2ffb, 0x3056, 0x306d, 0x3084, - 0x30fe, 0x3103, 0x312c, 0x317d, 0x318e, 0x31ad, 0x31e5, 0x31ef, - 0x31fc, 0x320f, 0x3230, 0x3239, 0x326f, 0x3275, 0x2ffb, 0x329e, - 0x2ffb, 0x2ffb, 0x2ffb, 0x2ffb, 0x2ffb, 0x32a5, 0x32af, 0x2ffb, - 0x2ffb, 0x2ffb, 0x2ffb, 0x2ffb, 0x2ffb, 0x2ffb, 0x2ffb, 0x32b7, - 0x2ffb, 0x2ffb, 0x2ffb, 0x2ffb, 0x2ffb, 0x32c9, 0x32d3, 0x2ffb, - 0x2ffb, 0x2ffb, 0x2ffb, 0x2ffb, 0x2ffb, 0x0002, 0x32fd, 0x3351, - 0x33ac, 0x33c6, 0x2ffb, 0x33f7, 0x382a, 0x427a, 0x2ffb, 0x2ffb, - 0x2ffb, 0x2ffb, 0x2ffb, 0x2ffb, 0x2ffb, 0x2ffb, 0x3041, 0x3044, - 0x382c, 0x2ffb, 0x3839, 0x4313, 0x436e, 0x43d2, 0x2ffb, 0x4435, - 0x445f, 0x447e, 0x44b0, 0x2ffb, 0x2ffb, 0x2ffb, 0x383d, 0x39e2, - 0x39fc, 0x3a26, 0x3a87, 0x3ae7, 0x3af2, 0x3b2a, 0x3b39, 0x3b48, - 0x3b4b, 0x3b6e, 0x3bba, 0x3c34, 0x3c41, 0x3d42, 0x3e6a, 0x3e93, - 0x3f91, 0x3fb3, 0x3fbf, 0x3ff8, 0x40bc, 0x2ffb, 0x2ffb, 0x2ffb, - 0x2ffb, 0x4124, 0x413f, 0x41b1, 0x4263, 0x713c, 0x0000, 0x2021, - 0x4000, 0x080c, 0x3ef0, 0x0126, 0x2091, 0x8000, 0x0e04, 0x2feb, - 0x7818, 0xd084, 0x0110, 0x012e, 0x0cb0, 0x7c22, 0x7926, 0x7a2a, - 0x7b2e, 0x781b, 0x0001, 0x2091, 0x4080, 0x7007, 0x0001, 0x2091, - 0x5000, 0x012e, 0x0005, 0x2021, 0x4001, 0x0c18, 0x2021, 0x4002, - 0x0c00, 0x2021, 0x4003, 0x08e8, 0x2021, 0x4005, 0x08d0, 0x2021, - 0x4006, 0x08b8, 0xa02e, 0x2520, 0x7b28, 0x7a2c, 0x7824, 0x7930, - 0x0804, 0x3efd, 0x7823, 0x0004, 0x7824, 0x0807, 0xa02e, 0x2520, - 0x7b28, 0x7a2c, 0x7824, 0x7930, 0x0804, 0x3f00, 0x7924, 0x7828, - 0x2114, 0x200a, 0x0804, 0x2fdf, 0x7924, 0x2114, 0x0804, 0x2fdf, - 0x2099, 0x0009, 0x20a1, 0x0009, 0x20a9, 0x0007, 0x53a3, 0x7924, - 0x7a28, 0x7b2c, 0x0804, 0x2fdf, 0x7824, 0x2060, 0x0090, 0x2009, - 0x0002, 0x2011, 0x0002, 0x2019, 0x0008, 0x783b, 0x0017, 0x0804, - 0x2fdf, 0x7d38, 0x7c3c, 0x0840, 0x7d38, 0x7c3c, 0x0888, 0x2061, - 0x1000, 0xe10c, 0xa006, 0x2c15, 0xa200, 0x8c60, 0x8109, 0x1dd8, - 0x2010, 0xa005, 0x0904, 0x2fdf, 0x0804, 0x3001, 0x2069, 0xb652, - 0x7824, 0x7930, 0xa11a, 0x1a04, 0x3007, 0x8019, 0x0904, 0x3007, - 0x684a, 0x6942, 0x782c, 0x6852, 0x7828, 0x6856, 0xa006, 0x685a, - 0x685e, 0x080c, 0x5e17, 0x0804, 0x2fdf, 0x2069, 0xb652, 0x7824, - 0x7934, 0xa11a, 0x1a04, 0x3007, 0x8019, 0x0904, 0x3007, 0x684e, - 0x6946, 0x782c, 0x6862, 0x7828, 0x6866, 0xa006, 0x686a, 0x686e, - 0x080c, 0x5447, 0x0804, 0x2fdf, 0xa02e, 0x2520, 0x81ff, 0x1904, - 0x3004, 0x7924, 0x7b28, 0x7a2c, 0x20a9, 0x0005, 0x20a1, 0xb689, - 0x41a1, 0x080c, 0x3ebc, 0x0904, 0x3004, 0x2009, 0x0020, 0x080c, - 0x3efd, 0x701b, 0x309c, 0x0005, 0x6834, 0x2008, 0xa084, 0x00ff, - 0xa096, 0x0011, 0x0138, 0xa096, 0x0019, 0x0120, 0xa096, 0x0015, - 0x1904, 0x3004, 0x810f, 0xa18c, 0x00ff, 0x0904, 0x3004, 0x710e, - 0x700c, 0x8001, 0x0528, 0x700e, 0x080c, 0x3ebc, 0x0904, 0x3004, - 0x2009, 0x0020, 0x2061, 0xb6d2, 0x6224, 0x6328, 0x642c, 0x6530, - 0xa290, 0x0040, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, - 0x080c, 0x3efd, 0x701b, 0x30cd, 0x0005, 0x6834, 0xa084, 0x00ff, - 0xa096, 0x0002, 0x0120, 0xa096, 0x000a, 0x1904, 0x3004, 0x08c0, - 0x7010, 0x2068, 0x6838, 0xc0fd, 0x683a, 0x080c, 0x4ebb, 0x1128, - 0x7007, 0x0003, 0x701b, 0x30e7, 0x0005, 0x080c, 0x554d, 0x0126, - 0x2091, 0x8000, 0x20a9, 0x0005, 0x2099, 0xb689, 0x530a, 0x2100, - 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0xad80, - 0x000d, 0x2009, 0x0020, 0x012e, 0x0804, 0x3f00, 0x61ac, 0x7824, - 0x60ae, 0x0804, 0x2fdf, 0x2091, 0x8000, 0x7823, 0x4000, 0x7827, - 0x4953, 0x782b, 0x5020, 0x782f, 0x2020, 0x2009, 0x017f, 0x2104, - 0x7832, 0x3f00, 0x7836, 0x2061, 0x0100, 0x6200, 0x2061, 0x0200, - 0x603c, 0x8007, 0xa205, 0x783a, 0x2009, 0x04fd, 0x2104, 0x783e, - 0x781b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2071, 0x0010, - 0x20c1, 0x00f0, 0x0804, 0x0427, 0x81ff, 0x1904, 0x3004, 0x7924, - 0x810f, 0xa18c, 0x00ff, 0x080c, 0x501b, 0x1904, 0x3007, 0x7e38, - 0xa684, 0x3fff, 0xa082, 0x4000, 0x0210, 0x0804, 0x3007, 0x7c28, - 0x7d2c, 0x080c, 0x51e3, 0xd28c, 0x1118, 0x080c, 0x518c, 0x0010, - 0x080c, 0x51bc, 0x1518, 0x2061, 0xbe00, 0x0126, 0x2091, 0x8000, - 0x6000, 0xa086, 0x0000, 0x0148, 0x6010, 0xa06d, 0x0130, 0x683c, - 0xa406, 0x1118, 0x6840, 0xa506, 0x0150, 0x012e, 0xace0, 0x0018, - 0x2001, 0xb617, 0x2004, 0xac02, 0x1a04, 0x3004, 0x0c30, 0x080c, - 0x99e6, 0x012e, 0x0904, 0x3004, 0x0804, 0x2fdf, 0xa00e, 0x2001, - 0x0005, 0x080c, 0x554d, 0x0126, 0x2091, 0x8000, 0x080c, 0x9f8e, - 0x080c, 0x547a, 0x012e, 0x0804, 0x2fdf, 0x81ff, 0x1904, 0x3004, - 0x080c, 0x3ed1, 0x0904, 0x3007, 0x080c, 0x50e1, 0x0904, 0x3004, - 0x080c, 0x51ef, 0x0904, 0x3004, 0x0804, 0x2fdf, 0x81ff, 0x1904, - 0x3004, 0x080c, 0x3ee1, 0x0904, 0x3007, 0x080c, 0x525b, 0x0904, - 0x3004, 0x2019, 0x0005, 0x7924, 0x080c, 0x520a, 0x0904, 0x3004, - 0x7828, 0xa08a, 0x1000, 0x1a04, 0x3007, 0x8003, 0x800b, 0x810b, - 0xa108, 0x080c, 0x6a1a, 0x0804, 0x2fdf, 0x0126, 0x2091, 0x8000, - 0x81ff, 0x0118, 0x2009, 0x0001, 0x0450, 0x2029, 0x00ff, 0x6450, - 0x2400, 0xa506, 0x01f8, 0x2508, 0x080c, 0x501b, 0x11d8, 0x080c, - 0x525b, 0x1128, 0x2009, 0x0002, 0x62b4, 0x2518, 0x00c0, 0x2019, - 0x0004, 0xa00e, 0x080c, 0x520a, 0x1118, 0x2009, 0x0006, 0x0078, - 0x7824, 0xa08a, 0x1000, 0x1270, 0x8003, 0x800b, 0x810b, 0xa108, - 0x080c, 0x6a1a, 0x8529, 0x1ae0, 0x012e, 0x0804, 0x2fdf, 0x012e, - 0x0804, 0x3004, 0x012e, 0x0804, 0x3007, 0x080c, 0x3ed1, 0x0904, - 0x3007, 0x080c, 0x5147, 0x080c, 0x51e3, 0x0804, 0x2fdf, 0x81ff, - 0x1904, 0x3004, 0x080c, 0x3ed1, 0x0904, 0x3007, 0x080c, 0x5138, - 0x080c, 0x51e3, 0x0804, 0x2fdf, 0x81ff, 0x1904, 0x3004, 0x080c, - 0x3ed1, 0x0904, 0x3007, 0x080c, 0x51be, 0x0904, 0x3004, 0x080c, - 0x4eff, 0x080c, 0x5185, 0x080c, 0x51e3, 0x0804, 0x2fdf, 0x080c, - 0x3ed1, 0x0904, 0x3007, 0x080c, 0x50e1, 0x0904, 0x3004, 0x62a0, - 0x2019, 0x0005, 0x00c6, 0x080c, 0x521c, 0x2061, 0x0000, 0x080c, - 0x6e67, 0x0076, 0x2039, 0x0000, 0x080c, 0x6d74, 0x2009, 0x0000, - 0x080c, 0xaf3e, 0x007e, 0x00ce, 0x080c, 0x51e3, 0x0804, 0x2fdf, - 0x080c, 0x3ed1, 0x0904, 0x3007, 0x080c, 0x51e3, 0x2208, 0x0804, - 0x2fdf, 0x0156, 0x00d6, 0x00e6, 0x2069, 0xb714, 0x6810, 0x6914, - 0xa10a, 0x1210, 0x2009, 0x0000, 0x6816, 0x2011, 0x0000, 0x2019, - 0x0000, 0x20a9, 0x007e, 0x2069, 0xb735, 0x2d04, 0xa075, 0x0130, - 0x704c, 0x0071, 0xa210, 0x7080, 0x0059, 0xa318, 0x8d68, 0x1f04, - 0x324d, 0x2300, 0xa218, 0x00ee, 0x00de, 0x015e, 0x0804, 0x2fdf, - 0x00f6, 0x0016, 0xa07d, 0x0140, 0x2001, 0x0000, 0x8000, 0x2f0c, - 0x81ff, 0x0110, 0x2178, 0x0cd0, 0x001e, 0x00fe, 0x0005, 0x2069, - 0xb714, 0x6910, 0x62b0, 0x0804, 0x2fdf, 0x81ff, 0x1904, 0x3004, - 0x6150, 0xa190, 0x2df9, 0x2215, 0xa294, 0x00ff, 0x6370, 0x83ff, - 0x0108, 0x6274, 0x67d4, 0xd79c, 0x0118, 0x2031, 0x0001, 0x0090, - 0xd7ac, 0x0118, 0x2031, 0x0003, 0x0068, 0xd7a4, 0x0118, 0x2031, - 0x0002, 0x0040, 0x080c, 0x5b41, 0x1118, 0x2031, 0x0004, 0x0010, - 0x2031, 0x0000, 0x7e3a, 0x7f3e, 0x0804, 0x2fdf, 0x6140, 0x6244, - 0x2019, 0xb8b6, 0x231c, 0x0804, 0x2fdf, 0x0126, 0x2091, 0x8000, - 0x6134, 0xa006, 0x2010, 0x6338, 0x012e, 0x0804, 0x2fdf, 0x080c, - 0x3ee1, 0x0904, 0x3007, 0x6244, 0x6338, 0x0804, 0x2fdf, 0x6140, - 0x6244, 0x7824, 0x6042, 0x7b28, 0x6346, 0x2069, 0xb652, 0x831f, - 0xa305, 0x6816, 0x782c, 0x2069, 0xb8b6, 0x2d1c, 0x206a, 0x0804, - 0x2fdf, 0x0126, 0x2091, 0x8000, 0x7824, 0x6036, 0x782c, 0x603a, - 0x012e, 0x0804, 0x2fdf, 0x7838, 0xa005, 0x01a8, 0x7828, 0xa025, - 0x0904, 0x3007, 0x782c, 0xa02d, 0x0904, 0x3007, 0xa00e, 0x080c, - 0x501b, 0x1120, 0x6244, 0x6338, 0x6446, 0x653a, 0xa186, 0x00ff, - 0x0190, 0x8108, 0x0ca0, 0x080c, 0x3ee1, 0x0904, 0x3007, 0x7828, - 0xa00d, 0x0904, 0x3007, 0x782c, 0xa005, 0x0904, 0x3007, 0x6244, - 0x6146, 0x6338, 0x603a, 0x0804, 0x2fdf, 0x2001, 0xb600, 0x2004, - 0xa086, 0x0003, 0x1904, 0x3004, 0x00c6, 0x2061, 0x0100, 0x7924, - 0x810f, 0xa18c, 0x00ff, 0xa196, 0x00ff, 0x1130, 0x2001, 0xb615, - 0x2004, 0xa085, 0xff00, 0x0078, 0xa182, 0x007f, 0x16a0, 0xa188, - 0x2df9, 0x210d, 0xa18c, 0x00ff, 0x2001, 0xb615, 0x2004, 0xa116, - 0x0550, 0x810f, 0xa105, 0x0126, 0x2091, 0x8000, 0x0006, 0x080c, - 0x864e, 0x000e, 0x01e0, 0x601a, 0x600b, 0xbc09, 0x601f, 0x0001, - 0x080c, 0x3ebc, 0x01d8, 0x6837, 0x0000, 0x7007, 0x0003, 0x6833, - 0x0000, 0x6838, 0xc0fd, 0x683a, 0x701b, 0x33a5, 0x2d00, 0x6012, - 0x2009, 0x0032, 0x080c, 0x86d3, 0x012e, 0x00ce, 0x0005, 0x012e, - 0x00ce, 0x0804, 0x3004, 0x00ce, 0x0804, 0x3007, 0x080c, 0x86a4, - 0x0cb0, 0x2001, 0xb600, 0x2004, 0xa086, 0x0003, 0x1904, 0x3004, - 0x00c6, 0x2061, 0x0100, 0x7924, 0x810f, 0xa18c, 0x00ff, 0xa196, - 0x00ff, 0x1130, 0x2001, 0xb615, 0x2004, 0xa085, 0xff00, 0x0078, - 0xa182, 0x007f, 0x16a0, 0xa188, 0x2df9, 0x210d, 0xa18c, 0x00ff, - 0x2001, 0xb615, 0x2004, 0xa116, 0x0550, 0x810f, 0xa105, 0x0126, - 0x2091, 0x8000, 0x0006, 0x080c, 0x864e, 0x000e, 0x01e0, 0x601a, - 0x600b, 0xbc05, 0x601f, 0x0001, 0x080c, 0x3ebc, 0x01d8, 0x6837, - 0x0000, 0x7007, 0x0003, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, - 0x701b, 0x33a5, 0x2d00, 0x6012, 0x2009, 0x0032, 0x080c, 0x86d3, - 0x012e, 0x00ce, 0x0005, 0x012e, 0x00ce, 0x0804, 0x3004, 0x00ce, - 0x0804, 0x3007, 0x080c, 0x86a4, 0x0cb0, 0x6830, 0xa086, 0x0100, - 0x0904, 0x3004, 0x0804, 0x2fdf, 0x2061, 0xb975, 0x0126, 0x2091, - 0x8000, 0x6000, 0xd084, 0x0178, 0x6104, 0x6208, 0x2a60, 0x6068, - 0x783a, 0x60b4, 0x783e, 0x60b0, 0x2019, 0x0072, 0x201a, 0x6348, - 0x012e, 0x0804, 0x2fdf, 0xa00e, 0x2110, 0x0c80, 0x81ff, 0x1904, - 0x3004, 0x080c, 0x5b41, 0x0904, 0x3004, 0x0126, 0x2091, 0x8000, - 0x6248, 0x6068, 0xa202, 0x0248, 0xa085, 0x0001, 0x080c, 0x289c, - 0x080c, 0x4673, 0x012e, 0x0804, 0x2fdf, 0x012e, 0x0804, 0x3007, - 0x0006, 0x0016, 0x00c6, 0x00e6, 0x2001, 0xb8c0, 0x2070, 0x2061, - 0xb652, 0x6008, 0x2072, 0x2009, 0x0000, 0x2011, 0x1000, 0x080c, - 0x6bb2, 0x7206, 0x00ee, 0x00ce, 0x001e, 0x000e, 0x0005, 0x0126, - 0x2091, 0x8000, 0x7824, 0xa084, 0x0007, 0x0002, 0x3409, 0x3412, - 0x3419, 0x3406, 0x3406, 0x3406, 0x3406, 0x3406, 0x012e, 0x0804, - 0x3007, 0x2009, 0x0114, 0x2104, 0xa085, 0x0800, 0x200a, 0x080c, - 0x3584, 0x0070, 0x2009, 0x010b, 0x200b, 0x0010, 0x080c, 0x3584, - 0x0038, 0x81ff, 0x0128, 0x012e, 0x2021, 0x400b, 0x0804, 0x2fe1, - 0x0086, 0x0096, 0x00a6, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, - 0x080c, 0x33e0, 0x2009, 0x0101, 0x210c, 0x0016, 0x2001, 0x0138, - 0x200c, 0x2003, 0x0001, 0x0016, 0x2001, 0x007a, 0x2034, 0x2001, - 0x007b, 0x202c, 0xa006, 0x2048, 0x2050, 0x2058, 0x080c, 0x37cf, - 0x080c, 0x3733, 0xa03e, 0x2720, 0x00f6, 0x00e6, 0x00c6, 0x2d60, - 0x2071, 0xb94b, 0x2079, 0x0020, 0x00d6, 0x2069, 0x0000, 0x6824, - 0xd0b4, 0x0140, 0x2001, 0x007d, 0x2004, 0x783e, 0x2001, 0x007c, - 0x2004, 0x783a, 0x00de, 0x2011, 0x0001, 0x080c, 0x36df, 0x080c, - 0x36df, 0x00ce, 0x00ee, 0x00fe, 0x080c, 0x362a, 0x080c, 0x3707, - 0x080c, 0x3684, 0x080c, 0x35e9, 0x080c, 0x361a, 0x00f6, 0x2079, - 0x0100, 0x7824, 0xd094, 0x0530, 0x7814, 0xa084, 0x0184, 0xa085, - 0x0010, 0x7816, 0x2079, 0x0140, 0x080c, 0x3562, 0x1110, 0x00fe, - 0x0430, 0x7804, 0xd0dc, 0x0dc0, 0x2079, 0x0100, 0x7827, 0x0086, - 0x7814, 0xa084, 0x0184, 0xa085, 0x0032, 0x7816, 0x080c, 0x3562, - 0x1110, 0x00fe, 0x00a0, 0x7824, 0xd0bc, 0x0dc0, 0x7827, 0x0080, - 0xa026, 0x7c16, 0x7824, 0xd0ac, 0x0130, 0x8b58, 0x080c, 0x356c, - 0x00fe, 0x0804, 0x352c, 0x00fe, 0x080c, 0x3562, 0x1150, 0x8948, - 0x2001, 0x007a, 0x2602, 0x2001, 0x007b, 0x2502, 0x080c, 0x356c, - 0x0088, 0x87ff, 0x0140, 0x2001, 0x0201, 0x2004, 0xa005, 0x1904, - 0x3466, 0x8739, 0x0038, 0x2001, 0xb924, 0x2004, 0xa086, 0x0000, - 0x1904, 0x3466, 0x2001, 0x0033, 0x2003, 0x00f6, 0x8631, 0x1208, - 0x8529, 0x2500, 0xa605, 0x0904, 0x352c, 0x7824, 0xd0bc, 0x0128, - 0x2900, 0xaa05, 0xab05, 0x1904, 0x352c, 0x6033, 0x000d, 0x2001, - 0x0030, 0x2003, 0x0004, 0x7824, 0xd0ac, 0x1148, 0x2001, 0xb924, - 0x2003, 0x0003, 0x2001, 0x0030, 0x2003, 0x0009, 0x0040, 0x6027, - 0x0001, 0x2001, 0x0075, 0x2004, 0xa005, 0x0108, 0x6026, 0x2c00, - 0x601a, 0x20e1, 0x9040, 0x2d00, 0x681a, 0x6833, 0x000d, 0x7824, - 0xd0a4, 0x1180, 0x6827, 0x0000, 0x00c6, 0x20a9, 0x0004, 0x2061, - 0x0020, 0x6003, 0x0008, 0x2001, 0x0203, 0x2004, 0x1f04, 0x3501, - 0x00ce, 0x0040, 0x6827, 0x0001, 0x2001, 0x0074, 0x2004, 0xa005, - 0x0108, 0x6826, 0x00f6, 0x00c6, 0x2079, 0x0100, 0x2061, 0x0020, - 0x7827, 0x0002, 0x2001, 0x0072, 0x2004, 0xa084, 0xfff8, 0x601a, - 0x0006, 0x2001, 0x0073, 0x2004, 0x601e, 0x78c6, 0x000e, 0x78ca, - 0x00ce, 0x00fe, 0x0804, 0x3444, 0x2061, 0x0100, 0x6027, 0x0002, - 0x001e, 0x61e2, 0x001e, 0x6106, 0x7824, 0xa084, 0x0003, 0xa086, - 0x0002, 0x0188, 0x20e1, 0x9028, 0x6050, 0xa084, 0xf7ef, 0x6052, - 0x602f, 0x0000, 0x602c, 0xc0ac, 0x602e, 0x604b, 0xf7f7, 0x6043, - 0x0090, 0x6043, 0x0010, 0x2908, 0x2a10, 0x2b18, 0x2b00, 0xaa05, - 0xa905, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e, - 0x008e, 0x1118, 0x012e, 0x0804, 0x2fdf, 0x012e, 0x2021, 0x400c, - 0x0804, 0x2fe1, 0xa085, 0x0001, 0x1d04, 0x356b, 0x2091, 0x6000, - 0x8420, 0xa486, 0x0064, 0x0005, 0x2001, 0x0105, 0x2003, 0x0010, - 0x2001, 0x0030, 0x2003, 0x0004, 0x2001, 0x0020, 0x2003, 0x0004, - 0x2001, 0xb924, 0x2003, 0x0000, 0x2001, 0xb94b, 0x2003, 0x0000, - 0x20e1, 0xf000, 0xa026, 0x0005, 0x00f6, 0x2079, 0x0100, 0x2001, - 0xb615, 0x200c, 0x7932, 0x7936, 0x080c, 0x287c, 0x7850, 0xa084, - 0x0980, 0xa085, 0x0030, 0x7852, 0x2019, 0x01f4, 0x8319, 0x1df0, - 0xa084, 0x0980, 0x7852, 0x782c, 0xc0ad, 0x782e, 0x20a9, 0x0046, - 0x1d04, 0x35a0, 0x2091, 0x6000, 0x1f04, 0x35a0, 0x7850, 0xa085, - 0x0400, 0x7852, 0x2001, 0x0009, 0x2004, 0xa084, 0x0003, 0xa086, - 0x0001, 0x1118, 0x782c, 0xc0ac, 0x782e, 0x784b, 0xf7f7, 0x7843, - 0x0090, 0x7843, 0x0010, 0x20a9, 0x000e, 0xe000, 0x1f04, 0x35bd, - 0x7850, 0xa085, 0x1400, 0x7852, 0x2019, 0x61a8, 0x7854, 0xe000, - 0xe000, 0xd08c, 0x1110, 0x8319, 0x1dc8, 0x7827, 0x0048, 0x7850, - 0xa085, 0x0400, 0x7852, 0x7843, 0x0040, 0x2019, 0x01f4, 0xe000, - 0xe000, 0x8319, 0x1de0, 0x2001, 0x0140, 0x2003, 0x0100, 0x7827, - 0x0020, 0x7843, 0x0000, 0x2003, 0x0000, 0x7827, 0x0048, 0x00fe, - 0x0005, 0x7824, 0xd0ac, 0x11c8, 0x00f6, 0x00e6, 0x2071, 0xb924, - 0x2079, 0x0030, 0x2001, 0x0201, 0x2004, 0xa005, 0x0160, 0x7000, - 0xa086, 0x0000, 0x1140, 0x0051, 0xd0bc, 0x0108, 0x8738, 0x7003, - 0x0003, 0x7803, 0x0019, 0x00ee, 0x00fe, 0x0005, 0x780c, 0xa08c, - 0x0070, 0x0178, 0x2009, 0x007a, 0x260a, 0x2009, 0x007b, 0x250a, - 0xd0b4, 0x0108, 0x8a50, 0xd0ac, 0x0108, 0x8948, 0xd0a4, 0x0108, - 0x8b58, 0x0005, 0x00f6, 0x2079, 0x0200, 0x781c, 0xd084, 0x0140, - 0x20e1, 0x0007, 0x20e1, 0x2000, 0x2001, 0x020a, 0x2004, 0x0ca8, - 0x00fe, 0x0005, 0x00e6, 0x2071, 0x0100, 0x2001, 0xb8c1, 0x2004, - 0x70e2, 0x2009, 0xb615, 0x210c, 0x716e, 0x7063, 0x0100, 0x7166, - 0x719e, 0x706b, 0x0000, 0x7073, 0x0809, 0x7077, 0x0008, 0x7078, - 0xa080, 0x0100, 0x707a, 0x7080, 0x8000, 0x7082, 0x7087, 0xaaaa, - 0xa006, 0x708a, 0x708e, 0x707e, 0x70d6, 0x70ab, 0x0036, 0x70af, - 0x95d5, 0x7027, 0x0080, 0x7014, 0xa084, 0x0184, 0xa085, 0x0032, - 0x7016, 0x080c, 0x3707, 0x080c, 0x3562, 0x1110, 0x8421, 0x0028, - 0x7024, 0xd0bc, 0x0db0, 0x7027, 0x0080, 0x00f6, 0x00e6, 0x2071, - 0xb924, 0x2079, 0x0030, 0x00d6, 0x2069, 0x0000, 0x6824, 0xd0b4, - 0x0120, 0x683c, 0x783e, 0x6838, 0x783a, 0x00de, 0x2011, 0x0011, - 0x080c, 0x36df, 0x2011, 0x0001, 0x080c, 0x36df, 0x00ee, 0x00fe, - 0x7017, 0x0000, 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x2071, 0xb924, - 0x2079, 0x0030, 0x7904, 0xd1fc, 0x0904, 0x36dc, 0x7803, 0x0002, - 0xa026, 0xd19c, 0x1904, 0x36d8, 0x7000, 0x0002, 0x36dc, 0x369a, - 0x36be, 0x36d8, 0xd1bc, 0x1150, 0xd1dc, 0x1150, 0x8001, 0x7002, - 0x2011, 0x0001, 0x04e1, 0x05c0, 0x04d1, 0x04b0, 0x780f, 0x0000, - 0x7820, 0x7924, 0x7803, 0x0004, 0x7822, 0x7926, 0x2001, 0x0201, - 0x200c, 0x81ff, 0x0de8, 0x080c, 0x3606, 0x2009, 0x0001, 0x7808, - 0xd0ec, 0x0110, 0x2009, 0x0011, 0x7902, 0x00f0, 0x8001, 0x7002, - 0xa184, 0x0880, 0x1138, 0x7804, 0xd0fc, 0x1940, 0x2011, 0x0001, - 0x00b1, 0x0090, 0x6030, 0xa092, 0x0004, 0xa086, 0x0009, 0x1120, - 0x6000, 0x601a, 0x2011, 0x0025, 0x6232, 0xd1dc, 0x1988, 0x0870, - 0x7803, 0x0004, 0x7003, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x6024, - 0xa005, 0x0520, 0x8001, 0x6026, 0x6018, 0x6130, 0xa140, 0x2804, - 0x7832, 0x8840, 0x2804, 0x7836, 0x8840, 0x2804, 0x7822, 0x8840, - 0x2804, 0x7826, 0x8840, 0x7a02, 0x7000, 0x8000, 0x7002, 0x6018, - 0xa802, 0xa08a, 0x0029, 0x1138, 0x6018, 0xa080, 0x0001, 0x2004, - 0x601a, 0x2001, 0x000d, 0x6032, 0xa085, 0x0001, 0x0005, 0x00f6, - 0x00e6, 0x00c6, 0x2071, 0xb94b, 0x2079, 0x0020, 0x7904, 0xd1fc, - 0x01f0, 0x7803, 0x0002, 0x2d60, 0xa026, 0x7000, 0x0002, 0x372f, - 0x371a, 0x3726, 0x8001, 0x7002, 0xd19c, 0x1188, 0x2011, 0x0001, - 0x080c, 0x36df, 0x0160, 0x080c, 0x36df, 0x0048, 0x8001, 0x7002, - 0x7804, 0xd0fc, 0x1d30, 0x2011, 0x0001, 0x080c, 0x36df, 0x00ce, - 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x2061, 0x0200, - 0x2001, 0xb8c1, 0x2004, 0x601a, 0x2061, 0x0100, 0x2001, 0xb8c0, - 0x2004, 0x60ce, 0x6004, 0xc0ac, 0xa085, 0x0200, 0x6006, 0x2001, - 0x0074, 0x2004, 0xa005, 0x01f8, 0x2038, 0x2001, 0x0076, 0x2024, - 0x2001, 0x0077, 0x201c, 0x080c, 0x3ebc, 0x6833, 0x000d, 0x6f26, - 0x2d00, 0x681a, 0xa78a, 0x0007, 0x0220, 0x2138, 0x2009, 0x0007, - 0x0010, 0x2708, 0xa03e, 0x6818, 0xa080, 0x000d, 0x04b1, 0x1d90, - 0x2d00, 0x681a, 0x0088, 0x080c, 0x3ebc, 0x6833, 0x000d, 0x2070, - 0x6827, 0x0001, 0x2d00, 0x681a, 0x2001, 0x0076, 0x2004, 0x2072, - 0x2001, 0x0077, 0x2004, 0x7006, 0x2061, 0x0020, 0x2079, 0x0100, - 0x2001, 0xb8c0, 0x2004, 0x6012, 0x20e1, 0x9040, 0x2001, 0x0072, - 0x2004, 0xa084, 0xfff8, 0x700a, 0x601a, 0x0006, 0x2001, 0x0073, - 0x2004, 0x700e, 0x601e, 0x78c6, 0x000e, 0x78ca, 0xa006, 0x603a, - 0x603e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00e6, 0x2071, 0x0010, - 0x20a0, 0x2099, 0x0014, 0x7003, 0x0026, 0x7432, 0x7336, 0xa006, - 0x703a, 0x703e, 0x810b, 0x810b, 0x21a8, 0x810b, 0x7122, 0x7003, - 0x0041, 0x7004, 0xd0fc, 0x0de8, 0x7003, 0x0002, 0x7003, 0x0040, - 0x53a5, 0x7430, 0x7334, 0x87ff, 0x0180, 0x00c6, 0x00d6, 0x2d60, - 0x00c6, 0x080c, 0x3ebc, 0x00ce, 0x6018, 0x2070, 0x2d00, 0x7006, - 0x601a, 0x00de, 0x00ce, 0xa085, 0x0001, 0x00ee, 0x0005, 0x00e6, - 0x2001, 0x0075, 0x2004, 0xa005, 0x0508, 0x2038, 0x2001, 0x0078, - 0x2024, 0x2001, 0x0079, 0x201c, 0x080c, 0x3ebc, 0x2d60, 0x6833, - 0x000d, 0x6f26, 0x2d00, 0x681a, 0xa78a, 0x0007, 0x0220, 0x2138, - 0x2009, 0x0007, 0x0010, 0x2708, 0xa03e, 0x6818, 0xa080, 0x000d, - 0x080c, 0x379d, 0x1d88, 0x2d00, 0x681a, 0x00e0, 0x080c, 0x3ebc, - 0x2d60, 0x6033, 0x000d, 0x2070, 0x6027, 0x0001, 0x2c00, 0x601a, - 0x2001, 0x0078, 0x2004, 0x2072, 0x2001, 0x0079, 0x2004, 0x7006, - 0x2001, 0x0072, 0x2004, 0xa084, 0xfff8, 0x700a, 0x2001, 0x0073, - 0x2004, 0x700e, 0x2001, 0x0030, 0x2003, 0x0004, 0x7824, 0xd0ac, - 0x1178, 0x2001, 0x0101, 0x200c, 0xc1ed, 0x2102, 0x6027, 0x0000, - 0x2001, 0xb924, 0x2003, 0x0003, 0x2001, 0x0030, 0x2003, 0x0009, - 0x00ee, 0x0005, 0x0804, 0x2fdf, 0x0126, 0x2091, 0x8000, 0x20a9, - 0x0012, 0x2001, 0xb640, 0x20a0, 0xa006, 0x40a4, 0x012e, 0x0804, - 0x2fdf, 0x7d38, 0x7c3c, 0x0804, 0x3086, 0x080c, 0x3ebc, 0x0904, - 0x3004, 0x080c, 0x5b41, 0x0110, 0x080c, 0x4c52, 0x2009, 0x001c, - 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3efd, 0x701b, 0x3851, - 0x0005, 0xade8, 0x000d, 0x6800, 0xa005, 0x0904, 0x3007, 0x6804, - 0xd0ac, 0x0118, 0xd0a4, 0x0904, 0x3007, 0xd094, 0x00c6, 0x2061, - 0x0100, 0x6104, 0x0138, 0x6200, 0xa292, 0x0005, 0x0218, 0xa18c, - 0xffdf, 0x0010, 0xa18d, 0x0020, 0x6106, 0x00ce, 0xd08c, 0x00c6, - 0x2061, 0x0100, 0x6104, 0x0118, 0xa18d, 0x0010, 0x0010, 0xa18c, - 0xffef, 0x6106, 0x00ce, 0x2009, 0x0100, 0x210c, 0xa18a, 0x0002, - 0x0268, 0xd084, 0x0158, 0x6a28, 0xa28a, 0x007f, 0x1a04, 0x3007, - 0xa288, 0x2df9, 0x210d, 0xa18c, 0x00ff, 0x615a, 0xd0dc, 0x0130, - 0x6828, 0xa08a, 0x007f, 0x1a04, 0x3007, 0x6052, 0x6808, 0xa08a, - 0x0100, 0x0a04, 0x3007, 0xa08a, 0x0841, 0x1a04, 0x3007, 0xa084, - 0x0007, 0x1904, 0x3007, 0x680c, 0xa005, 0x0904, 0x3007, 0x6810, - 0xa005, 0x0904, 0x3007, 0x6848, 0x6940, 0xa10a, 0x1a04, 0x3007, - 0x8001, 0x0904, 0x3007, 0x684c, 0x6944, 0xa10a, 0x1a04, 0x3007, - 0x8001, 0x0904, 0x3007, 0x6804, 0xd0fc, 0x0560, 0x080c, 0x3ebc, - 0x0904, 0x3004, 0x2009, 0x0014, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, - 0xa290, 0x0038, 0xa399, 0x0000, 0x080c, 0x3efd, 0x701b, 0x38d1, - 0x0005, 0xade8, 0x000d, 0x20a9, 0x0014, 0x2d98, 0x2069, 0xb66e, - 0x2da0, 0x53a3, 0x7010, 0xa0e8, 0x000d, 0x2001, 0xb672, 0x200c, - 0xd1e4, 0x0140, 0x00c6, 0x2061, 0x0100, 0x6004, 0xa085, 0x0b00, - 0x6006, 0x00ce, 0x2009, 0xb8b1, 0x200b, 0x0000, 0x2001, 0xb674, - 0x2004, 0xd0ac, 0x0158, 0x7824, 0x200a, 0x2009, 0x017f, 0x200a, - 0x3200, 0xa084, 0x003f, 0xa085, 0x3020, 0x2090, 0x20a9, 0x001c, - 0x2d98, 0x2069, 0xb652, 0x2da0, 0x53a3, 0x6814, 0xa08c, 0x00ff, - 0x6142, 0x8007, 0xa084, 0x00ff, 0x6046, 0x080c, 0x5e17, 0x080c, - 0x53de, 0x080c, 0x5447, 0x6000, 0xa086, 0x0000, 0x1904, 0x39cc, - 0x6808, 0x602a, 0x080c, 0x24a5, 0x0006, 0x2001, 0x0100, 0x2004, - 0xa082, 0x0005, 0x000e, 0x0268, 0x2009, 0x0170, 0x200b, 0x0080, - 0xe000, 0xe000, 0x200b, 0x0000, 0x0036, 0x6b08, 0x080c, 0x28d7, - 0x003e, 0x6818, 0x691c, 0x6a20, 0x6b24, 0x8007, 0x810f, 0x8217, - 0x831f, 0x6016, 0x611a, 0x621e, 0x6322, 0x6c04, 0xd4f4, 0x0148, - 0x6830, 0x6934, 0x6a38, 0x6b3c, 0x8007, 0x810f, 0x8217, 0x831f, - 0x0010, 0xa084, 0xf0ff, 0x6006, 0x610a, 0x620e, 0x6312, 0x8007, - 0x810f, 0x8217, 0x831f, 0x20a9, 0x0004, 0x20a1, 0xb8c7, 0x40a1, - 0x080c, 0x6ada, 0x6904, 0xd1fc, 0x0520, 0x00c6, 0x2009, 0x0000, - 0x20a9, 0x0001, 0x6b70, 0xd384, 0x01c8, 0x0020, 0x839d, 0x12b0, - 0x3508, 0x8109, 0x080c, 0x63ce, 0x6878, 0x6016, 0x6874, 0x2008, - 0xa084, 0xff00, 0x8007, 0x600a, 0xa184, 0x00ff, 0x6006, 0x8108, - 0x1118, 0x6003, 0x0003, 0x0010, 0x6003, 0x0001, 0x1f04, 0x3966, - 0x00ce, 0x2069, 0xb652, 0x2001, 0xb89e, 0x6a80, 0xa294, 0x0030, - 0xa28e, 0x0000, 0x0170, 0xa28e, 0x0010, 0x0118, 0xa28e, 0x0020, - 0x0140, 0x2003, 0xaaaa, 0x080c, 0x2920, 0x2001, 0xb88f, 0x2102, - 0x0008, 0x2102, 0x00c6, 0x2061, 0x0100, 0x602f, 0x0040, 0x602f, - 0x0000, 0x00ce, 0x080c, 0x5b41, 0x0128, 0x080c, 0x4116, 0x0110, - 0x080c, 0x289c, 0x60c8, 0xa005, 0x01d0, 0x6003, 0x0001, 0x2009, - 0x39b2, 0x00e0, 0x080c, 0x5b41, 0x1178, 0x2011, 0x5a14, 0x080c, - 0x6a0e, 0x2011, 0x5a07, 0x080c, 0x6ace, 0x2001, 0xb89f, 0x2003, - 0x0000, 0x080c, 0x5a79, 0x0040, 0x080c, 0x4b7b, 0x0028, 0x6003, - 0x0004, 0x2009, 0x39cc, 0x0010, 0x0804, 0x2fdf, 0x2001, 0x0100, - 0x2004, 0xa082, 0x0005, 0x0258, 0x2001, 0x0170, 0x2004, 0xa084, - 0x00ff, 0xa086, 0x004c, 0x1118, 0x2091, 0x309d, 0x0817, 0x2091, - 0x301d, 0x0817, 0x6000, 0xa086, 0x0000, 0x0904, 0x3004, 0x2069, - 0xb652, 0x7830, 0x6842, 0x7834, 0x6846, 0x6804, 0xd0fc, 0x0118, - 0x2009, 0x0030, 0x0010, 0x2009, 0x001c, 0x2d00, 0x7a2c, 0x7b28, - 0x7c3c, 0x7d38, 0x0804, 0x3f00, 0xa006, 0x080c, 0x289c, 0x81ff, - 0x1904, 0x3004, 0x080c, 0x5b41, 0x1178, 0x2001, 0xb89f, 0x2003, - 0x0001, 0x2001, 0xb600, 0x2003, 0x0001, 0xa085, 0x0001, 0x080c, - 0x5b85, 0x080c, 0x5a79, 0x0080, 0x0016, 0x2009, 0xffff, 0x8109, - 0x0130, 0x2001, 0xb8e2, 0x2004, 0xa086, 0x0000, 0x1dc0, 0x001e, - 0x080c, 0x4c52, 0x080c, 0x4b7b, 0x0804, 0x2fdf, 0x81ff, 0x1904, - 0x3004, 0x080c, 0x5b41, 0x1110, 0x0804, 0x3004, 0x6188, 0x81ff, - 0x0198, 0x703f, 0x0000, 0x2001, 0xbdc0, 0x2009, 0x0040, 0x7a2c, - 0x7b28, 0x7c3c, 0x7d38, 0x0126, 0x2091, 0x8000, 0x080c, 0x3f00, - 0x701b, 0x2fdd, 0x012e, 0x0005, 0x703f, 0x0001, 0x00d6, 0x2069, - 0xbdc0, 0x20a9, 0x0040, 0x20a1, 0xbdc0, 0x2019, 0xffff, 0x43a4, - 0x6550, 0xa588, 0x2df9, 0x210d, 0xa18c, 0x00ff, 0x216a, 0xa00e, - 0x2011, 0x0002, 0x2100, 0xa506, 0x01a8, 0x080c, 0x501b, 0x1190, - 0x6014, 0x821c, 0x0238, 0xa398, 0xbdc0, 0xa085, 0xff00, 0x8007, - 0x201a, 0x0038, 0xa398, 0xbdc0, 0x2324, 0xa4a4, 0xff00, 0xa405, - 0x201a, 0x8210, 0x8108, 0xa182, 0x0080, 0x1208, 0x0c18, 0x8201, - 0x8007, 0x2d0c, 0xa105, 0x206a, 0x00de, 0x20a9, 0x0040, 0x20a1, - 0xbdc0, 0x2099, 0xbdc0, 0x080c, 0x4bf1, 0x0804, 0x3a33, 0x080c, - 0x3ee1, 0x0904, 0x3007, 0x00c6, 0x080c, 0x3ebc, 0x00ce, 0x1120, - 0x2009, 0x0002, 0x0804, 0x3004, 0x2001, 0xb653, 0x2004, 0xd0b4, - 0x0550, 0x7824, 0xa084, 0xff00, 0xa08e, 0x7e00, 0x0520, 0xa08e, - 0x7f00, 0x0508, 0xa08e, 0x8000, 0x01f0, 0x6000, 0xd08c, 0x11d8, - 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x11a8, 0x6837, 0x0000, - 0x6838, 0xc0fd, 0x683a, 0x080c, 0x9e96, 0x1120, 0x2009, 0x0003, - 0x0804, 0x3004, 0x7007, 0x0003, 0x701b, 0x3abf, 0x0005, 0x080c, - 0x3ee1, 0x0904, 0x3007, 0x20a9, 0x002b, 0x2c98, 0xade8, 0x0002, - 0x2da0, 0x53a3, 0x20a9, 0x0004, 0xac80, 0x0006, 0x2098, 0xad80, - 0x0006, 0x20a0, 0x080c, 0x4bf1, 0x20a9, 0x0004, 0xac80, 0x000a, - 0x2098, 0xad80, 0x000a, 0x20a0, 0x080c, 0x4bf1, 0x2d00, 0x2009, - 0x002b, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3f00, 0x81ff, - 0x1904, 0x3004, 0x080c, 0x3ed1, 0x0904, 0x3007, 0x080c, 0x51f8, - 0x0804, 0x2fdf, 0x81ff, 0x1904, 0x3004, 0x7828, 0xa08a, 0x1000, - 0x1a04, 0x3007, 0x080c, 0x3ee1, 0x0904, 0x3007, 0x080c, 0x525b, - 0x0904, 0x3004, 0x2019, 0x0004, 0xa00e, 0x080c, 0x520a, 0x7924, - 0x810f, 0x7a28, 0x0011, 0x0804, 0x2fdf, 0xa186, 0x00ff, 0x0110, - 0x0071, 0x0060, 0x2029, 0x007e, 0x2061, 0xb600, 0x6450, 0x2400, - 0xa506, 0x0110, 0x2508, 0x0019, 0x8529, 0x1ec8, 0x0005, 0x080c, - 0x501b, 0x1138, 0x2200, 0x8003, 0x800b, 0x810b, 0xa108, 0x080c, - 0x6a1a, 0x0005, 0x81ff, 0x1904, 0x3004, 0x080c, 0x3ed1, 0x0904, - 0x3007, 0x080c, 0x50e1, 0x0904, 0x3004, 0x080c, 0x5201, 0x0804, - 0x2fdf, 0x81ff, 0x1904, 0x3004, 0x080c, 0x3ed1, 0x0904, 0x3007, - 0x080c, 0x50e1, 0x0904, 0x3004, 0x080c, 0x51ef, 0x0804, 0x2fdf, - 0x6100, 0x0804, 0x2fdf, 0x080c, 0x3ee1, 0x0904, 0x3007, 0x2001, - 0xb600, 0x2004, 0xa086, 0x0003, 0x1904, 0x3004, 0x00d6, 0xace8, - 0x000a, 0x7924, 0xd184, 0x0110, 0xace8, 0x0006, 0x680c, 0x8007, - 0x783e, 0x6808, 0x8007, 0x783a, 0x6b04, 0x831f, 0x6a00, 0x8217, - 0x00de, 0x6100, 0xa18c, 0x0200, 0x0804, 0x2fdf, 0x7824, 0xa09c, - 0x0003, 0xd0b4, 0x1160, 0xa39a, 0x0003, 0x1a04, 0x3004, 0x6250, - 0xa294, 0x00ff, 0xa084, 0xff00, 0x8007, 0xa206, 0x1150, 0x2001, - 0xb640, 0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, - 0x3f00, 0x81ff, 0x1904, 0x3004, 0x080c, 0x3ee1, 0x0904, 0x3007, - 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1904, 0x3004, 0x00c6, - 0x080c, 0x3ebc, 0x00ce, 0x0904, 0x3004, 0x6837, 0x0000, 0x6838, - 0xc0fd, 0x683a, 0x080c, 0x9e42, 0x0904, 0x3004, 0x7007, 0x0003, - 0x701b, 0x3bab, 0x0005, 0x6830, 0xa086, 0x0100, 0x0904, 0x3004, - 0xad80, 0x000e, 0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, - 0x0804, 0x3f00, 0xa006, 0x080c, 0x289c, 0x7824, 0xa084, 0x00ff, - 0xa086, 0x00ff, 0x0118, 0x81ff, 0x1904, 0x3004, 0x080c, 0x5b41, - 0x0110, 0x080c, 0x4c52, 0x7828, 0xa08a, 0x1000, 0x1a04, 0x3007, - 0x7924, 0xa18c, 0xff00, 0x810f, 0xa186, 0x00ff, 0x0138, 0xa182, - 0x007f, 0x1a04, 0x3007, 0x2100, 0x080c, 0x2866, 0x0026, 0x00c6, - 0x0126, 0x2091, 0x8000, 0x2061, 0xb8f4, 0x601b, 0x0000, 0x601f, - 0x0000, 0x080c, 0x5b41, 0x1178, 0x2001, 0xb89f, 0x2003, 0x0001, - 0x2001, 0xb600, 0x2003, 0x0001, 0xa085, 0x0001, 0x080c, 0x5b85, - 0x080c, 0x5a79, 0x0440, 0x2011, 0x0003, 0x080c, 0x80fc, 0x2011, - 0x0002, 0x080c, 0x8106, 0x080c, 0x7fe0, 0x0036, 0x2019, 0x0000, - 0x080c, 0x806b, 0x003e, 0x2061, 0x0100, 0x2001, 0xb615, 0x2004, - 0xa084, 0x00ff, 0x810f, 0xa105, 0x604a, 0x6043, 0x0090, 0x6043, - 0x0010, 0x2009, 0xb8bf, 0x200b, 0x0000, 0x2009, 0x002d, 0x2011, - 0x4bb4, 0x080c, 0x6a94, 0x7924, 0xa18c, 0xff00, 0x810f, 0x080c, - 0x5b41, 0x1110, 0x2009, 0x00ff, 0x7a28, 0x080c, 0x3b0d, 0x012e, - 0x00ce, 0x002e, 0x0804, 0x2fdf, 0x7924, 0xa18c, 0xff00, 0x810f, - 0x00c6, 0x080c, 0x4fbf, 0x2c08, 0x00ce, 0x1904, 0x3007, 0x0804, - 0x2fdf, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x3004, 0x60d4, - 0xd0ac, 0x1130, 0xd09c, 0x1120, 0x2009, 0x0005, 0x0804, 0x3004, - 0x080c, 0x3ebc, 0x1120, 0x2009, 0x0002, 0x0804, 0x3004, 0x7924, - 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3efd, 0x701b, 0x3c61, - 0x0005, 0x2009, 0x0080, 0x080c, 0x501b, 0x1130, 0x6004, 0xa084, - 0x00ff, 0xa086, 0x0006, 0x0120, 0x2021, 0x400a, 0x0804, 0x2fe1, - 0x00d6, 0xade8, 0x000d, 0x6900, 0x6a08, 0x6b0c, 0x6c10, 0x6d14, - 0x6e18, 0x6820, 0xa0be, 0x0100, 0x0904, 0x3cd8, 0xa0be, 0x0112, - 0x0904, 0x3cd8, 0xa0be, 0x0113, 0x0904, 0x3cd8, 0xa0be, 0x0114, - 0x0904, 0x3cd8, 0xa0be, 0x0117, 0x0904, 0x3cd8, 0xa0be, 0x011a, - 0x0904, 0x3cd8, 0xa0be, 0x011c, 0x0904, 0x3cd8, 0xa0be, 0x0121, - 0x05b0, 0xa0be, 0x0131, 0x0598, 0xa0be, 0x0171, 0x05c8, 0xa0be, - 0x0173, 0x05b0, 0xa0be, 0x01a1, 0x1120, 0x6830, 0x8007, 0x6832, - 0x04a8, 0xa0be, 0x0212, 0x0540, 0xa0be, 0x0213, 0x0528, 0xa0be, - 0x0214, 0x01b0, 0xa0be, 0x0217, 0x0168, 0xa0be, 0x021a, 0x1120, - 0x6838, 0x8007, 0x683a, 0x00e0, 0xa0be, 0x0300, 0x01c8, 0x00de, - 0x0804, 0x3007, 0xad80, 0x0010, 0x20a9, 0x0007, 0x080c, 0x3d1e, - 0xad80, 0x000e, 0x20a9, 0x0001, 0x080c, 0x3d1e, 0x0048, 0xad80, - 0x000c, 0x080c, 0x3d2c, 0x0050, 0xad80, 0x000e, 0x080c, 0x3d2c, - 0xad80, 0x000c, 0x20a9, 0x0001, 0x080c, 0x3d1e, 0x00c6, 0x080c, - 0x3ebc, 0x0568, 0x6838, 0xc0fd, 0x683a, 0x6837, 0x0119, 0x6853, - 0x0000, 0x684f, 0x0020, 0x685b, 0x0001, 0x810b, 0x697e, 0x6883, - 0x0000, 0x6a86, 0x6b8a, 0x6c8e, 0x6d92, 0x6996, 0x689b, 0x0000, - 0x00ce, 0x00de, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x6823, - 0x0000, 0x6804, 0x2068, 0x080c, 0x9e5e, 0x1120, 0x2009, 0x0003, - 0x0804, 0x3004, 0x7007, 0x0003, 0x701b, 0x3d15, 0x0005, 0x00ce, - 0x00de, 0x2009, 0x0002, 0x0804, 0x3004, 0x6820, 0xa086, 0x8001, - 0x1904, 0x2fdf, 0x2009, 0x0004, 0x0804, 0x3004, 0x0016, 0x2008, - 0x2044, 0x8000, 0x204c, 0x8000, 0x290a, 0x8108, 0x280a, 0x8108, - 0x1f04, 0x3d20, 0x001e, 0x0005, 0x0016, 0x00a6, 0x00b6, 0x2008, - 0x2044, 0x8000, 0x204c, 0x8000, 0x2054, 0x8000, 0x205c, 0x2b0a, - 0x8108, 0x2a0a, 0x8108, 0x290a, 0x8108, 0x280a, 0x00be, 0x00ae, - 0x001e, 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x3004, - 0x60d4, 0xd0ac, 0x1130, 0xd09c, 0x1120, 0x2009, 0x0005, 0x0804, - 0x3004, 0x7924, 0x2140, 0xa18c, 0xff00, 0x810f, 0x60d4, 0xd0ac, - 0x1120, 0xa182, 0x0080, 0x0a04, 0x3007, 0xa182, 0x00ff, 0x1a04, - 0x3007, 0x7a2c, 0x7b28, 0x6070, 0xa306, 0x1140, 0x6074, 0xa24e, - 0x0904, 0x3007, 0xa9cc, 0xff00, 0x0904, 0x3007, 0x0126, 0x2091, - 0x8000, 0x00c6, 0x080c, 0x3e0c, 0x2c68, 0x00ce, 0x0538, 0xa0c6, - 0x4000, 0x1178, 0x00c6, 0x0006, 0x2d60, 0xa00e, 0x080c, 0x52bc, - 0x1108, 0xc185, 0x6000, 0xd0bc, 0x0108, 0xc18d, 0x000e, 0x00ce, - 0x0088, 0xa0c6, 0x4007, 0x1110, 0x2408, 0x0060, 0xa0c6, 0x4008, - 0x1118, 0x2708, 0x2610, 0x0030, 0xa0c6, 0x4009, 0x1108, 0x0010, - 0x2001, 0x4006, 0x2020, 0x012e, 0x0804, 0x2fe1, 0x2d00, 0x7022, - 0x0016, 0x00b6, 0x00c6, 0x00e6, 0x2c70, 0x080c, 0x864e, 0x05c0, - 0x2d00, 0x601a, 0x080c, 0xa0e3, 0x2e58, 0x00ee, 0x00e6, 0x00c6, - 0x080c, 0x3ebc, 0x00ce, 0x2b70, 0x1158, 0x080c, 0x86a4, 0x00ee, - 0x00ce, 0x00be, 0x001e, 0x012e, 0x2009, 0x0002, 0x0804, 0x3004, - 0x6837, 0x0000, 0x683b, 0x0000, 0x2d00, 0x6012, 0x6833, 0x0000, - 0x6838, 0xc0fd, 0xd88c, 0x0108, 0xc0f5, 0x683a, 0x080c, 0x2cd1, - 0x601f, 0x0001, 0x2001, 0x0000, 0x080c, 0x4f5d, 0x2001, 0x0002, - 0x080c, 0x4f6f, 0x2009, 0x0002, 0x080c, 0x86d3, 0xa085, 0x0001, - 0x00ee, 0x00ce, 0x00be, 0x001e, 0x012e, 0x1120, 0x2009, 0x0003, - 0x0804, 0x3004, 0x7007, 0x0003, 0x701b, 0x3def, 0x0005, 0x6830, - 0xa086, 0x0100, 0x7020, 0x2060, 0x1138, 0x2009, 0x0004, 0x6204, - 0xa294, 0x00ff, 0x0804, 0x3004, 0x2009, 0x0000, 0x6838, 0xd0f4, - 0x1904, 0x2fdf, 0x080c, 0x52bc, 0x1108, 0xc185, 0x6000, 0xd0bc, - 0x0108, 0xc18d, 0x0804, 0x2fdf, 0x00e6, 0x00d6, 0xa02e, 0x2001, - 0xb635, 0x2004, 0xd0ac, 0x0130, 0xa026, 0x20a9, 0x00ff, 0x2071, - 0xb735, 0x0030, 0x2021, 0x0080, 0x20a9, 0x007f, 0x2071, 0xb7b5, - 0x2e04, 0xa005, 0x1130, 0x2100, 0xa406, 0x1570, 0x2428, 0xc5fd, - 0x0458, 0x2068, 0x6f10, 0x2700, 0xa306, 0x11b0, 0x6e14, 0x2600, - 0xa206, 0x1190, 0x2400, 0xa106, 0x1160, 0x2d60, 0xd884, 0x0568, - 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1538, 0x2001, 0x4000, - 0x0428, 0x2001, 0x4007, 0x0410, 0x2400, 0xa106, 0x1168, 0x6e14, - 0x87ff, 0x1138, 0x86ff, 0x09d0, 0x2001, 0xb635, 0x2004, 0xd0ac, - 0x19a8, 0x2001, 0x4008, 0x0090, 0x8420, 0x8e70, 0x1f04, 0x3e20, - 0x85ff, 0x1130, 0x2001, 0x4009, 0x0048, 0x2001, 0x0001, 0x0030, - 0x080c, 0x4fbf, 0x1dd0, 0x6312, 0x6216, 0xa006, 0xa005, 0x00de, - 0x00ee, 0x0005, 0x81ff, 0x1904, 0x3004, 0x080c, 0x3ebc, 0x0904, - 0x3004, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x7824, 0xa005, - 0x0904, 0x3007, 0xa096, 0x00ff, 0x0120, 0xa092, 0x0004, 0x1a04, - 0x3007, 0x2010, 0x2d18, 0x080c, 0x2c84, 0x0904, 0x3004, 0x7007, - 0x0003, 0x701b, 0x3e8c, 0x0005, 0x6830, 0xa086, 0x0100, 0x0904, - 0x3004, 0x0804, 0x2fdf, 0x7924, 0xa18c, 0xff00, 0x810f, 0x60d4, - 0xd0ac, 0x1120, 0xa182, 0x0080, 0x0a04, 0x3007, 0xa182, 0x00ff, - 0x1a04, 0x3007, 0x0126, 0x2091, 0x8000, 0x080c, 0x9d46, 0x1188, - 0xa190, 0xb735, 0x2204, 0xa065, 0x0160, 0x080c, 0x4c7e, 0x2001, - 0xb635, 0x2004, 0xd0ac, 0x0110, 0x6017, 0x0000, 0x012e, 0x0804, - 0x2fdf, 0x012e, 0x0804, 0x3004, 0x080c, 0x15fd, 0x0188, 0xa006, - 0x6802, 0x7010, 0xa005, 0x1120, 0x2d00, 0x7012, 0x7016, 0x0030, - 0x7014, 0x6802, 0x2060, 0x2d00, 0x6006, 0x7016, 0xad80, 0x000d, - 0x0005, 0x7924, 0x810f, 0xa18c, 0x00ff, 0x080c, 0x501b, 0x1130, - 0x7e28, 0xa684, 0x3fff, 0xa082, 0x4000, 0x0208, 0xa066, 0x8cff, - 0x0005, 0x7e24, 0x860f, 0xa18c, 0x00ff, 0x080c, 0x501b, 0x1128, - 0xa6b4, 0x00ff, 0xa682, 0x4000, 0x0208, 0xa066, 0x8cff, 0x0005, - 0x0016, 0x7110, 0x81ff, 0x0128, 0x2168, 0x6904, 0x080c, 0x1614, - 0x0cc8, 0x7112, 0x7116, 0x001e, 0x0005, 0x2031, 0x0001, 0x0010, - 0x2031, 0x0000, 0x2061, 0xb6d2, 0x6606, 0x6112, 0x600e, 0x6226, - 0x632a, 0x642e, 0x6532, 0x2c10, 0x080c, 0x1648, 0x7007, 0x0002, - 0x701b, 0x2fdf, 0x0005, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2079, - 0x0000, 0x2001, 0xb690, 0x2004, 0xa005, 0x1168, 0x0e04, 0x3f2b, - 0x7818, 0xd084, 0x1140, 0x7a22, 0x7b26, 0x7c2a, 0x781b, 0x0001, - 0x2091, 0x4080, 0x0408, 0x0016, 0x00c6, 0x00e6, 0x2071, 0xb682, - 0x7138, 0xa182, 0x0010, 0x0218, 0x7030, 0x2060, 0x0078, 0x7030, - 0xa0e0, 0x0004, 0xac82, 0xb6d2, 0x0210, 0x2061, 0xb692, 0x2c00, - 0x7032, 0x81ff, 0x1108, 0x7036, 0x8108, 0x713a, 0x2262, 0x6306, - 0x640a, 0x00ee, 0x00ce, 0x001e, 0x012e, 0x00fe, 0x0005, 0x00e6, - 0x2071, 0xb682, 0x7038, 0xa005, 0x0570, 0x0126, 0x2091, 0x8000, - 0x0e04, 0x3f82, 0x00f6, 0x2079, 0x0000, 0x7818, 0xd084, 0x1508, - 0x00c6, 0x7034, 0x2060, 0x2c04, 0x7822, 0x6004, 0x7826, 0x6008, - 0x782a, 0x781b, 0x0001, 0x2091, 0x4080, 0x7038, 0x8001, 0x703a, - 0xa005, 0x1130, 0x7033, 0xb692, 0x7037, 0xb692, 0x00ce, 0x0048, - 0xac80, 0x0004, 0xa0fa, 0xb6d2, 0x0210, 0x2001, 0xb692, 0x7036, - 0x00ce, 0x00fe, 0x012e, 0x00ee, 0x0005, 0x0026, 0x2001, 0xb653, - 0x2004, 0xd0c4, 0x0120, 0x2011, 0x8014, 0x080c, 0x3f13, 0x002e, - 0x0005, 0x81ff, 0x1904, 0x3004, 0x0126, 0x2091, 0x8000, 0x6030, - 0xc08d, 0xc085, 0xc0ac, 0x6032, 0x080c, 0x5b41, 0x1178, 0x2001, - 0xb89f, 0x2003, 0x0001, 0x2001, 0xb600, 0x2003, 0x0001, 0xa085, - 0x0001, 0x080c, 0x5b85, 0x080c, 0x5a79, 0x0010, 0x080c, 0x4b7b, - 0x012e, 0x0804, 0x2fdf, 0x7824, 0x2008, 0xa18c, 0xfffd, 0x1128, - 0x61e0, 0xa10d, 0x61e2, 0x0804, 0x2fdf, 0x0804, 0x3007, 0x81ff, - 0x1904, 0x3004, 0x6000, 0xa086, 0x0003, 0x1904, 0x3004, 0x2001, - 0xb653, 0x2004, 0xd0ac, 0x1904, 0x3004, 0x080c, 0x3ee1, 0x0904, - 0x3007, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1120, 0x7828, - 0xa005, 0x0904, 0x2fdf, 0x00c6, 0x080c, 0x3ebc, 0x00ce, 0x0904, - 0x3004, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, - 0x080c, 0x9f27, 0x0904, 0x3004, 0x7007, 0x0003, 0x701b, 0x3ff1, - 0x0005, 0x6830, 0xa086, 0x0100, 0x0904, 0x3004, 0x0804, 0x2fdf, - 0x2001, 0xb600, 0x2004, 0xa086, 0x0003, 0x1904, 0x3004, 0x7f24, - 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3ebc, 0x0904, 0x3004, - 0x2009, 0x0000, 0x2031, 0x0000, 0x7023, 0x0000, 0x702f, 0x0000, - 0xad80, 0x0005, 0x7026, 0x20a0, 0x080c, 0x501b, 0x1904, 0x406b, - 0x6004, 0xa0c4, 0x00ff, 0xa8c6, 0x0006, 0x0130, 0xa0c4, 0xff00, - 0xa8c6, 0x0600, 0x1904, 0x406b, 0x2001, 0xb653, 0x2004, 0xd0ac, - 0x1128, 0x080c, 0x52bc, 0x1110, 0xd79c, 0x05e8, 0xd794, 0x1110, - 0xd784, 0x0158, 0xac80, 0x0006, 0x2098, 0x3400, 0x20a9, 0x0004, - 0x53a3, 0x080c, 0x3d2c, 0xd794, 0x0148, 0xac80, 0x000a, 0x2098, - 0x3400, 0x20a9, 0x0004, 0x53a3, 0x080c, 0x3d2c, 0x21a2, 0xd794, - 0x01d8, 0xac80, 0x0000, 0x2098, 0x94a0, 0x20a9, 0x0002, 0x53a3, - 0xac80, 0x0003, 0x20a6, 0x94a0, 0xac80, 0x0004, 0x2098, 0x3400, - 0x20a9, 0x0002, 0x53a3, 0x080c, 0x3d1e, 0xac80, 0x0026, 0x2098, - 0x20a9, 0x0002, 0x53a3, 0x0008, 0x94a0, 0xd794, 0x0110, 0xa6b0, - 0x000b, 0xa6b0, 0x0005, 0x8108, 0x2001, 0xb635, 0x2004, 0xd0ac, - 0x0118, 0xa186, 0x0100, 0x0040, 0xd78c, 0x0120, 0xa186, 0x0100, - 0x0170, 0x0018, 0xa186, 0x007e, 0x0150, 0xd794, 0x0118, 0xa686, - 0x0020, 0x0010, 0xa686, 0x0028, 0x0150, 0x0804, 0x4014, 0x86ff, - 0x1120, 0x7120, 0x810b, 0x0804, 0x2fdf, 0x702f, 0x0001, 0x711e, - 0x7020, 0xa600, 0x7022, 0x772a, 0x2061, 0xb6d2, 0x6007, 0x0000, - 0x6612, 0x7024, 0x600e, 0x6226, 0x632a, 0x642e, 0x6532, 0x2c10, - 0x080c, 0x1648, 0x7007, 0x0002, 0x701b, 0x40a7, 0x0005, 0x702c, - 0xa005, 0x1170, 0x711c, 0x7024, 0x20a0, 0x7728, 0x2031, 0x0000, - 0x2061, 0xb6d2, 0x6224, 0x6328, 0x642c, 0x6530, 0x0804, 0x4014, - 0x7120, 0x810b, 0x0804, 0x2fdf, 0x2029, 0x007e, 0x7924, 0x7a28, - 0x7b2c, 0x7c38, 0xa184, 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0a04, - 0x3007, 0xa502, 0x0a04, 0x3007, 0xa184, 0x00ff, 0xa0e2, 0x0020, - 0x0a04, 0x3007, 0xa502, 0x0a04, 0x3007, 0xa284, 0xff00, 0x8007, - 0xa0e2, 0x0020, 0x0a04, 0x3007, 0xa502, 0x0a04, 0x3007, 0xa284, - 0x00ff, 0xa0e2, 0x0020, 0x0a04, 0x3007, 0xa502, 0x0a04, 0x3007, - 0xa384, 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0a04, 0x3007, 0xa502, - 0x0a04, 0x3007, 0xa384, 0x00ff, 0xa0e2, 0x0020, 0x0a04, 0x3007, - 0xa502, 0x0a04, 0x3007, 0xa484, 0xff00, 0x8007, 0xa0e2, 0x0020, - 0x0a04, 0x3007, 0xa502, 0x0a04, 0x3007, 0xa484, 0x00ff, 0xa0e2, - 0x0020, 0x0a04, 0x3007, 0xa502, 0x0a04, 0x3007, 0x2061, 0xb8b9, - 0x6102, 0x6206, 0x630a, 0x640e, 0x0804, 0x2fdf, 0x0006, 0x2001, - 0xb653, 0x2004, 0xd0cc, 0x000e, 0x0005, 0x0006, 0x2001, 0xb672, - 0x2004, 0xd0bc, 0x000e, 0x0005, 0x6168, 0x7a24, 0x6300, 0x82ff, - 0x1118, 0x7926, 0x0804, 0x2fdf, 0x83ff, 0x1904, 0x3007, 0x2001, - 0xfff0, 0xa200, 0x1a04, 0x3007, 0x2019, 0xffff, 0x606c, 0xa302, - 0xa200, 0x0a04, 0x3007, 0x7926, 0x626a, 0x0804, 0x2fdf, 0x2001, - 0xb600, 0x2004, 0xa086, 0x0003, 0x1904, 0x3004, 0x7c28, 0x7d24, - 0x7e38, 0x7f2c, 0x080c, 0x3ebc, 0x0904, 0x3004, 0x2009, 0x0000, - 0x2019, 0x0000, 0x7023, 0x0000, 0x702f, 0x0000, 0xad80, 0x0003, - 0x7026, 0x20a0, 0xa1e0, 0xb735, 0x2c64, 0x8cff, 0x01b8, 0x6004, - 0xa084, 0x00ff, 0xa086, 0x0006, 0x0130, 0x6004, 0xa084, 0xff00, - 0xa086, 0x0600, 0x1158, 0x6014, 0x20a2, 0x94a0, 0x6010, 0x8007, - 0xa105, 0x8007, 0x20a2, 0x94a0, 0xa398, 0x0002, 0x8108, 0xa182, - 0x00ff, 0x0120, 0xa386, 0x002a, 0x0148, 0x08e0, 0x83ff, 0x1120, - 0x7120, 0x810c, 0x0804, 0x2fdf, 0x702f, 0x0001, 0x711e, 0x7020, - 0xa300, 0x7022, 0x2061, 0xb6d2, 0x6007, 0x0000, 0x6312, 0x7024, - 0x600e, 0x6426, 0x652a, 0x662e, 0x6732, 0x2c10, 0x080c, 0x1648, - 0x7007, 0x0002, 0x701b, 0x419d, 0x0005, 0x702c, 0xa005, 0x1168, - 0x711c, 0x7024, 0x20a0, 0x2019, 0x0000, 0x2061, 0xb6d2, 0x6424, - 0x6528, 0x662c, 0x6730, 0x0804, 0x415a, 0x7120, 0x810c, 0x0804, - 0x2fdf, 0x81ff, 0x1904, 0x3004, 0x60d4, 0xd0ac, 0x1118, 0xd09c, - 0x0904, 0x3004, 0x080c, 0x3ebc, 0x0904, 0x3004, 0x7924, 0x7a2c, - 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3efd, 0x701b, 0x41c8, 0x0005, - 0x00d6, 0xade8, 0x000d, 0x6828, 0xa0be, 0x7000, 0x0148, 0xa0be, - 0x7100, 0x0130, 0xa0be, 0x7200, 0x0118, 0x00de, 0x0804, 0x3007, - 0x6820, 0x6924, 0x080c, 0x2852, 0x1510, 0x080c, 0x4fbf, 0x11f8, - 0x7122, 0x6612, 0x6516, 0x6e18, 0x00c6, 0x080c, 0x3ebc, 0x01b8, - 0x080c, 0x3ebc, 0x01a0, 0x00ce, 0x00de, 0x6837, 0x0000, 0x6838, - 0xc0fd, 0x683a, 0x6823, 0x0000, 0x6804, 0x2068, 0x080c, 0x9e7a, - 0x0904, 0x3004, 0x7007, 0x0003, 0x701b, 0x4202, 0x0005, 0x00de, - 0x0804, 0x3004, 0x7120, 0x080c, 0x2dcc, 0x6820, 0xa086, 0x8001, - 0x0904, 0x3004, 0x2d00, 0x701e, 0x6804, 0xa080, 0x0002, 0x0006, - 0x20a9, 0x002a, 0x2098, 0x20a0, 0x080c, 0x4bf1, 0x000e, 0xade8, - 0x000d, 0x6a08, 0x6b0c, 0x6c10, 0x6d14, 0x2061, 0xb6d2, 0x6007, - 0x0000, 0x6e00, 0x6f28, 0xa7c6, 0x7000, 0x1108, 0x0018, 0xa7c6, - 0x7100, 0x1140, 0xa6c2, 0x0004, 0x0a04, 0x3007, 0x2009, 0x0004, - 0x0804, 0x3f00, 0xa7c6, 0x7200, 0x1904, 0x3007, 0xa6c2, 0x0054, - 0x0a04, 0x3007, 0x600e, 0x6013, 0x002a, 0x6226, 0x632a, 0x642e, - 0x6532, 0x2c10, 0x080c, 0x1648, 0x7007, 0x0002, 0x701b, 0x4249, - 0x0005, 0x701c, 0x2068, 0x6804, 0xa080, 0x0001, 0x2004, 0xa080, - 0x0002, 0x0006, 0x20a9, 0x002a, 0x2098, 0x20a0, 0x080c, 0x4bf1, - 0x000e, 0x2009, 0x002a, 0x2061, 0xb6d2, 0x6224, 0x6328, 0x642c, - 0x6530, 0x0804, 0x3f00, 0x81ff, 0x1904, 0x3004, 0x792c, 0x2001, - 0xb8a0, 0x2102, 0x080c, 0x3ed1, 0x0904, 0x3007, 0x080c, 0x50e1, - 0x0904, 0x3004, 0x0126, 0x2091, 0x8000, 0x080c, 0x5213, 0x012e, - 0x0804, 0x2fdf, 0x7824, 0xd08c, 0x1118, 0xd084, 0x0904, 0x3a87, - 0x080c, 0x3ee1, 0x0904, 0x3007, 0x00c6, 0x080c, 0x3ebc, 0x00ce, - 0x1120, 0x2009, 0x0002, 0x0804, 0x3004, 0x6004, 0xa084, 0x00ff, - 0xa086, 0x0006, 0x0128, 0xa08e, 0x0004, 0x0110, 0xa08e, 0x0005, - 0x15b8, 0x7824, 0xd08c, 0x0120, 0x6000, 0xc08c, 0x6002, 0x0030, - 0x2001, 0xb653, 0x2004, 0xd0b4, 0x0904, 0x3ac3, 0x7824, 0xa084, - 0xff00, 0xa08e, 0x7e00, 0x0904, 0x3ac3, 0xa08e, 0x7f00, 0x0904, - 0x3ac3, 0xa08e, 0x8000, 0x0904, 0x3ac3, 0x6000, 0xd08c, 0x1904, - 0x3ac3, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x080c, 0x9e96, - 0x1120, 0x2009, 0x0003, 0x0804, 0x3004, 0x7007, 0x0003, 0x701b, - 0x42ca, 0x0005, 0x080c, 0x3ee1, 0x0904, 0x3007, 0x0804, 0x3ac3, - 0x2009, 0xb631, 0x210c, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, - 0x3004, 0x2001, 0xb600, 0x2004, 0xa086, 0x0003, 0x0120, 0x2009, - 0x0007, 0x0804, 0x3004, 0x2001, 0xb653, 0x2004, 0xd0ac, 0x0120, - 0x2009, 0x0008, 0x0804, 0x3004, 0x609c, 0xd0a4, 0x1118, 0xd0ac, - 0x1904, 0x3ac3, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, - 0x683a, 0x080c, 0x9f27, 0x1120, 0x2009, 0x0003, 0x0804, 0x3004, - 0x7007, 0x0003, 0x701b, 0x4305, 0x0005, 0x6830, 0xa086, 0x0100, - 0x1120, 0x2009, 0x0004, 0x0804, 0x3004, 0x080c, 0x3ee1, 0x0904, - 0x3007, 0x0804, 0x4299, 0x81ff, 0x2009, 0x0001, 0x1904, 0x3004, - 0x6000, 0xa086, 0x0003, 0x2009, 0x0007, 0x1904, 0x3004, 0x2001, - 0xb653, 0x2004, 0xd0ac, 0x2009, 0x0008, 0x1904, 0x3004, 0x080c, - 0x3ee1, 0x0904, 0x3007, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, - 0x2009, 0x0009, 0x1904, 0x3004, 0x00c6, 0x080c, 0x3ebc, 0x00ce, - 0x2009, 0x0002, 0x0904, 0x3004, 0x6837, 0x0000, 0x6833, 0x0000, - 0x6838, 0xc0fd, 0x683a, 0x7928, 0xa194, 0xff00, 0xa18c, 0x00ff, - 0xa006, 0x82ff, 0x1128, 0xc0ed, 0x6952, 0x792c, 0x6956, 0x0048, - 0xa28e, 0x0100, 0x1904, 0x3007, 0xc0e5, 0x6853, 0x0000, 0x6857, - 0x0000, 0x683e, 0x080c, 0xa0e4, 0x2009, 0x0003, 0x0904, 0x3004, - 0x7007, 0x0003, 0x701b, 0x4365, 0x0005, 0x6830, 0xa086, 0x0100, - 0x2009, 0x0004, 0x0904, 0x3004, 0x0804, 0x2fdf, 0x81ff, 0x2009, - 0x0001, 0x1904, 0x3004, 0x6000, 0xa086, 0x0003, 0x2009, 0x0007, - 0x1904, 0x3004, 0x080c, 0x3ee1, 0x0904, 0x3007, 0x6004, 0xa084, - 0x00ff, 0xa086, 0x0006, 0x2009, 0x0009, 0x1904, 0x3004, 0x00c6, - 0x080c, 0x3ebc, 0x00ce, 0x2009, 0x0002, 0x0904, 0x3004, 0xad80, - 0x000f, 0x2009, 0x0008, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, - 0x3efd, 0x701b, 0x439c, 0x0005, 0x00d6, 0xade8, 0x000f, 0x6800, - 0xa086, 0x0500, 0x1140, 0x6804, 0xa005, 0x1128, 0x6808, 0xa084, - 0xff00, 0x1108, 0x0018, 0x00de, 0x1904, 0x3007, 0x00de, 0x6837, - 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x00c6, 0x080c, - 0x3ee1, 0x1118, 0x00ce, 0x0804, 0x3007, 0x080c, 0xa133, 0x2009, - 0x0003, 0x00ce, 0x0904, 0x3004, 0x7007, 0x0003, 0x701b, 0x43c9, - 0x0005, 0x6830, 0xa086, 0x0100, 0x2009, 0x0004, 0x0904, 0x3004, - 0x0804, 0x2fdf, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x3004, - 0x6000, 0xa086, 0x0003, 0x0120, 0x2009, 0x0007, 0x0804, 0x3004, - 0x7e24, 0x860f, 0xa18c, 0x00ff, 0xa6b4, 0x00ff, 0x080c, 0x501b, - 0x1904, 0x3007, 0xa186, 0x007f, 0x0150, 0x6004, 0xa084, 0x00ff, - 0xa086, 0x0006, 0x0120, 0x2009, 0x0009, 0x0804, 0x3004, 0x00c6, - 0x080c, 0x3ebc, 0x00ce, 0x1120, 0x2009, 0x0002, 0x0804, 0x3004, - 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x2001, 0x0100, 0x8007, - 0x680a, 0x080c, 0x9eb1, 0x1120, 0x2009, 0x0003, 0x0804, 0x3004, - 0x7007, 0x0003, 0x701b, 0x4415, 0x0005, 0x6808, 0x8007, 0xa086, - 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x3004, 0x68b0, 0x6836, - 0x6810, 0x8007, 0xa084, 0x00ff, 0x800c, 0x6814, 0x8007, 0xa084, - 0x00ff, 0x8004, 0xa080, 0x0002, 0xa108, 0xad80, 0x0004, 0x7a2c, - 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3f00, 0x080c, 0x3ebc, 0x1120, - 0x2009, 0x0002, 0x0804, 0x3004, 0x7924, 0xa194, 0xff00, 0xa18c, - 0x00ff, 0x8217, 0x82ff, 0x0110, 0x0804, 0x3007, 0x2009, 0x001a, - 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3efd, 0x701b, 0x4451, - 0x0005, 0x2001, 0xb62a, 0x2003, 0x0001, 0xad80, 0x000d, 0x2098, - 0x20a9, 0x001a, 0x20a1, 0xb8c7, 0x53a3, 0x0804, 0x2fdf, 0x080c, - 0x3ebc, 0x1120, 0x2009, 0x0002, 0x0804, 0x3004, 0x7924, 0xa194, - 0xff00, 0xa18c, 0x00ff, 0x8217, 0x82ff, 0x0110, 0x0804, 0x3007, - 0x2099, 0xb8c7, 0x20a0, 0x20a9, 0x001a, 0x53a3, 0x2009, 0x001a, - 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3f00, 0x7824, 0xa08a, - 0x1000, 0x1a04, 0x3007, 0x0126, 0x2091, 0x8000, 0x8003, 0x800b, - 0x810b, 0xa108, 0x00c6, 0x2061, 0xb8f4, 0x6142, 0x00ce, 0x012e, - 0x0804, 0x2fdf, 0x00c6, 0x080c, 0x5b41, 0x1188, 0x2001, 0xb89f, - 0x2003, 0x0001, 0x2001, 0xb600, 0x2003, 0x0001, 0xa085, 0x0001, - 0x080c, 0x5b85, 0x080c, 0x5a79, 0x080c, 0x151a, 0x0038, 0x2061, - 0xb600, 0x6030, 0xc09d, 0x6032, 0x080c, 0x4b7b, 0x00ce, 0x0005, - 0x0126, 0x2091, 0x8000, 0x00c6, 0x2061, 0xb8f4, 0x7924, 0x6152, - 0x614e, 0x6057, 0x0000, 0x604b, 0x0009, 0x7838, 0x606a, 0x783c, - 0x6066, 0x7828, 0x6062, 0x782c, 0x605e, 0x2061, 0xb8a1, 0x2001, - 0xb909, 0x600e, 0x6013, 0x0001, 0x6017, 0x0002, 0x6007, 0x0000, - 0x6037, 0x0000, 0x00ce, 0x012e, 0x0804, 0x2fdf, 0x0126, 0x00c6, - 0x00e6, 0x2061, 0x0100, 0x2071, 0xb600, 0x6044, 0xd0a4, 0x11b0, - 0xd084, 0x0118, 0x080c, 0x464d, 0x0068, 0xd08c, 0x0118, 0x080c, - 0x456e, 0x0040, 0xd094, 0x0118, 0x080c, 0x453f, 0x0018, 0xd09c, - 0x0108, 0x0061, 0x00ee, 0x00ce, 0x012e, 0x0005, 0x0016, 0x6128, - 0xd19c, 0x1110, 0xc19d, 0x612a, 0x001e, 0x0ca0, 0x624c, 0xa286, - 0xf0f0, 0x1150, 0x6048, 0xa086, 0xf0f0, 0x0130, 0x624a, 0x6043, - 0x0090, 0x6043, 0x0010, 0x0490, 0xa294, 0xff00, 0xa296, 0xf700, - 0x0178, 0x7134, 0xd1a4, 0x1160, 0x6240, 0xa295, 0x0100, 0x6242, - 0xa294, 0x0010, 0x0128, 0x2009, 0x00f7, 0x080c, 0x4c11, 0x00f0, - 0x6040, 0xa084, 0x0010, 0xa085, 0x0140, 0x6042, 0x6043, 0x0000, - 0x707b, 0x0000, 0x7097, 0x0001, 0x70bb, 0x0000, 0x70d7, 0x0000, - 0x2009, 0xbdc0, 0x200b, 0x0000, 0x708b, 0x0000, 0x707f, 0x000a, - 0x2009, 0x000a, 0x2011, 0x4b1c, 0x080c, 0x6a94, 0x0005, 0x0156, - 0x2001, 0xb674, 0x2004, 0xd08c, 0x0110, 0x7053, 0xffff, 0x707c, - 0xa005, 0x1510, 0x2011, 0x4b1c, 0x080c, 0x6a0e, 0x6040, 0xa094, - 0x0010, 0xa285, 0x0020, 0x6042, 0x20a9, 0x00c8, 0x6044, 0xd08c, - 0x1168, 0x1f04, 0x4556, 0x6242, 0x708f, 0x0000, 0x6040, 0xa094, - 0x0010, 0xa285, 0x0080, 0x6042, 0x6242, 0x0030, 0x6242, 0x708f, - 0x0000, 0x7083, 0x0000, 0x0000, 0x015e, 0x0005, 0x7080, 0xa08a, - 0x0003, 0x1210, 0x0023, 0x0010, 0x080c, 0x151a, 0x0005, 0x457a, - 0x45ca, 0x464c, 0x00f6, 0x7083, 0x0001, 0x20e1, 0xa000, 0xe000, - 0x20e1, 0x8700, 0x080c, 0x24a5, 0x20e1, 0x9080, 0x20e1, 0x4000, - 0x2079, 0xbc00, 0x207b, 0x2200, 0x7807, 0x00ef, 0x780b, 0x0000, - 0x780f, 0x00ef, 0x7813, 0x0138, 0x7817, 0x0000, 0x781b, 0x0000, - 0x781f, 0x0000, 0x7823, 0xffff, 0x7827, 0xffff, 0x782b, 0x0000, - 0x782f, 0x0000, 0x2079, 0xbc0c, 0x207b, 0x1101, 0x7807, 0x0000, - 0x2099, 0xb605, 0x20a1, 0xbc0e, 0x20a9, 0x0004, 0x53a3, 0x2079, - 0xbc12, 0x207b, 0x0000, 0x7807, 0x0000, 0x2099, 0xbc00, 0x20a1, - 0x020b, 0x20a9, 0x0014, 0x53a6, 0x60c3, 0x000c, 0x600f, 0x0000, - 0x080c, 0x4b55, 0x00fe, 0x7087, 0x0000, 0x6043, 0x0008, 0x6043, - 0x0000, 0x0005, 0x00d6, 0x7084, 0x7087, 0x0000, 0xa025, 0x0904, - 0x4634, 0x6020, 0xd0b4, 0x1904, 0x4632, 0x7194, 0x81ff, 0x0904, - 0x4622, 0xa486, 0x000c, 0x1904, 0x462d, 0xa480, 0x0018, 0x8004, - 0x20a8, 0x2011, 0xbc80, 0x2019, 0xbc00, 0x220c, 0x2304, 0xa106, - 0x11b8, 0x8210, 0x8318, 0x1f04, 0x45e5, 0x6043, 0x0004, 0x608b, - 0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0006, 0x7083, 0x0002, 0x708f, - 0x0002, 0x2009, 0x07d0, 0x2011, 0x4b23, 0x080c, 0x6a94, 0x0490, - 0x2069, 0xbc80, 0x6930, 0xa18e, 0x1101, 0x1538, 0x6834, 0xa005, - 0x1520, 0x6900, 0xa18c, 0x00ff, 0x1118, 0x6804, 0xa005, 0x0190, - 0x2011, 0xbc8e, 0x2019, 0xb605, 0x20a9, 0x0004, 0x220c, 0x2304, - 0xa102, 0x0230, 0x1190, 0x8210, 0x8318, 0x1f04, 0x4616, 0x0068, - 0x7097, 0x0000, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xbc80, - 0x20a1, 0x020b, 0x20a9, 0x0014, 0x53a6, 0x6043, 0x0008, 0x6043, - 0x0000, 0x0010, 0x00de, 0x0005, 0x6040, 0xa085, 0x0100, 0x6042, - 0x6020, 0xd0b4, 0x1db8, 0x60c3, 0x000c, 0x2011, 0xb8eb, 0x2013, - 0x0000, 0x7087, 0x0000, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, - 0x9575, 0x080c, 0x7dea, 0x0c30, 0x0005, 0x708c, 0xa08a, 0x001d, - 0x1210, 0x0023, 0x0010, 0x080c, 0x151a, 0x0005, 0x4680, 0x468f, - 0x46b7, 0x46d0, 0x46f4, 0x471c, 0x4740, 0x4771, 0x4795, 0x47bd, - 0x47f4, 0x481c, 0x4838, 0x484e, 0x486e, 0x4881, 0x4889, 0x48b9, - 0x48dd, 0x4905, 0x4929, 0x495a, 0x4997, 0x49c6, 0x49e2, 0x4a21, - 0x4a41, 0x4a5a, 0x4a5b, 0x00c6, 0x2061, 0xb600, 0x6003, 0x0007, - 0x2061, 0x0100, 0x6004, 0xa084, 0xfff9, 0x6006, 0x00ce, 0x0005, - 0x608b, 0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0002, 0x708f, 0x0001, - 0x2009, 0x07d0, 0x2011, 0x4b23, 0x080c, 0x6a94, 0x0005, 0x00f6, - 0x7084, 0xa086, 0x0014, 0x1508, 0x6043, 0x0000, 0x6020, 0xd0b4, - 0x11e0, 0x2079, 0xbc80, 0x7a30, 0xa296, 0x1102, 0x11a0, 0x7834, - 0xa005, 0x1188, 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, - 0x70bb, 0x0001, 0x2011, 0x4b23, 0x080c, 0x6a0e, 0x708f, 0x0010, - 0x080c, 0x4889, 0x0010, 0x080c, 0x4b7b, 0x00fe, 0x0005, 0x708f, - 0x0003, 0x6043, 0x0004, 0x2011, 0x4b23, 0x080c, 0x6a0e, 0x080c, - 0x4bf9, 0x20a3, 0x1102, 0x20a3, 0x0000, 0x20a9, 0x000a, 0x20a3, - 0x0000, 0x1f04, 0x46c7, 0x60c3, 0x0014, 0x080c, 0x4b55, 0x0005, - 0x00f6, 0x7084, 0xa005, 0x01f0, 0x2011, 0x4b23, 0x080c, 0x6a0e, - 0xa086, 0x0014, 0x11a8, 0x2079, 0xbc80, 0x7a30, 0xa296, 0x1102, - 0x1178, 0x7834, 0xa005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70b8, - 0xa005, 0x1110, 0x70bb, 0x0001, 0x708f, 0x0004, 0x0029, 0x0010, - 0x080c, 0x4b7b, 0x00fe, 0x0005, 0x708f, 0x0005, 0x080c, 0x4bf9, - 0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430, 0x2011, 0xbc8e, 0x080c, - 0x4c4a, 0x1160, 0x7078, 0xa005, 0x1148, 0x7150, 0xa186, 0xffff, - 0x0128, 0x080c, 0x4ae7, 0x0110, 0x080c, 0x4c28, 0x20a9, 0x0008, - 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, - 0x0014, 0x080c, 0x4b55, 0x0005, 0x00f6, 0x7084, 0xa005, 0x01f0, - 0x2011, 0x4b23, 0x080c, 0x6a0e, 0xa086, 0x0014, 0x11a8, 0x2079, - 0xbc80, 0x7a30, 0xa296, 0x1103, 0x1178, 0x7834, 0xa005, 0x1160, - 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, - 0x708f, 0x0006, 0x0029, 0x0010, 0x080c, 0x4b7b, 0x00fe, 0x0005, - 0x708f, 0x0007, 0x080c, 0x4bf9, 0x20a3, 0x1104, 0x20a3, 0x0000, - 0x3430, 0x2011, 0xbc8e, 0x080c, 0x4c4a, 0x11a8, 0x7078, 0xa005, - 0x1190, 0x7158, 0xa186, 0xffff, 0x0170, 0xa180, 0x2df9, 0x200d, - 0xa18c, 0xff00, 0x810f, 0x080c, 0x4ae7, 0x0128, 0x080c, 0x411d, - 0x0110, 0x080c, 0x289c, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x4b55, - 0x0005, 0x00f6, 0x7084, 0xa005, 0x01f0, 0x2011, 0x4b23, 0x080c, - 0x6a0e, 0xa086, 0x0014, 0x11a8, 0x2079, 0xbc80, 0x7a30, 0xa296, - 0x1104, 0x1178, 0x7834, 0xa005, 0x1160, 0x7a38, 0xd2fc, 0x0128, - 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, 0x708f, 0x0008, 0x0029, - 0x0010, 0x080c, 0x4b7b, 0x00fe, 0x0005, 0x708f, 0x0009, 0x080c, - 0x4bf9, 0x20a3, 0x1105, 0x20a3, 0x0100, 0x3430, 0x080c, 0x4c4a, - 0x1150, 0x7078, 0xa005, 0x1138, 0x080c, 0x4a5c, 0x1170, 0xa085, - 0x0001, 0x080c, 0x289c, 0x20a9, 0x0008, 0x2099, 0xbc8e, 0x26a0, - 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, - 0x4b55, 0x0010, 0x080c, 0x4673, 0x0005, 0x00f6, 0x7084, 0xa005, - 0x0588, 0x2011, 0x4b23, 0x080c, 0x6a0e, 0xa086, 0x0014, 0x1540, - 0x2079, 0xbc80, 0x7a30, 0xa296, 0x1105, 0x1510, 0x7834, 0x2011, - 0x0100, 0xa21e, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, - 0x1110, 0x70bb, 0x0001, 0x708f, 0x000a, 0x00b1, 0x0098, 0xa005, - 0x1178, 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, - 0x0001, 0x708b, 0x0000, 0x708f, 0x000e, 0x080c, 0x486e, 0x0010, - 0x080c, 0x4b7b, 0x00fe, 0x0005, 0x708f, 0x000b, 0x2011, 0xbc0e, - 0x22a0, 0x20a9, 0x0040, 0x2019, 0xffff, 0x43a4, 0x20a9, 0x0002, - 0x2009, 0x0000, 0x41a4, 0x080c, 0x4bf9, 0x20a3, 0x1106, 0x20a3, - 0x0000, 0x080c, 0x4c4a, 0x0118, 0x2013, 0x0000, 0x0020, 0x7054, - 0xa085, 0x0100, 0x2012, 0x2298, 0x20a9, 0x0042, 0x53a6, 0x60c3, - 0x0084, 0x080c, 0x4b55, 0x0005, 0x00f6, 0x7084, 0xa005, 0x01b0, - 0x2011, 0x4b23, 0x080c, 0x6a0e, 0xa086, 0x0084, 0x1168, 0x2079, - 0xbc80, 0x7a30, 0xa296, 0x1106, 0x1138, 0x7834, 0xa005, 0x1120, - 0x708f, 0x000c, 0x0029, 0x0010, 0x080c, 0x4b7b, 0x00fe, 0x0005, - 0x708f, 0x000d, 0x080c, 0x4bf9, 0x20a3, 0x1107, 0x20a3, 0x0000, - 0x2099, 0xbc8e, 0x20a9, 0x0040, 0x53a6, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x60c3, 0x0084, 0x080c, 0x4b55, 0x0005, 0x00f6, 0x7084, - 0xa005, 0x01d0, 0x2011, 0x4b23, 0x080c, 0x6a0e, 0xa086, 0x0084, - 0x1188, 0x2079, 0xbc80, 0x7a30, 0xa296, 0x1107, 0x1158, 0x7834, - 0xa005, 0x1140, 0x708b, 0x0001, 0x080c, 0x4beb, 0x708f, 0x000e, - 0x0029, 0x0010, 0x080c, 0x4b7b, 0x00fe, 0x0005, 0x708f, 0x000f, - 0x7087, 0x0000, 0x608b, 0xbc85, 0x608f, 0xb5b5, 0x6043, 0x0005, - 0x6043, 0x0004, 0x2009, 0x07d0, 0x2011, 0x4b23, 0x080c, 0x6a02, - 0x0005, 0x7084, 0xa005, 0x0120, 0x2011, 0x4b23, 0x080c, 0x6a0e, - 0x0005, 0x708f, 0x0011, 0x080c, 0x4c4a, 0x11a0, 0x7170, 0x81ff, - 0x0188, 0x2009, 0x0000, 0x7074, 0xa084, 0x00ff, 0x080c, 0x2852, - 0xa186, 0x007e, 0x0138, 0xa186, 0x0080, 0x0120, 0x2011, 0xbc8e, - 0x080c, 0x4ae7, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xbc80, - 0x20a1, 0x020b, 0x7484, 0xa480, 0x0018, 0xa080, 0x0007, 0xa084, - 0x03f8, 0x8004, 0x20a8, 0x53a6, 0x60c3, 0x0014, 0x080c, 0x4b55, - 0x0005, 0x00f6, 0x7084, 0xa005, 0x01f0, 0x2011, 0x4b23, 0x080c, - 0x6a0e, 0xa086, 0x0014, 0x11a8, 0x2079, 0xbc80, 0x7a30, 0xa296, - 0x1103, 0x1178, 0x7834, 0xa005, 0x1160, 0x7a38, 0xd2fc, 0x0128, - 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, 0x708f, 0x0012, 0x0029, - 0x0010, 0x080c, 0x4b7b, 0x00fe, 0x0005, 0x708f, 0x0013, 0x080c, - 0x4c05, 0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430, 0x2011, 0xbc8e, - 0x080c, 0x4c4a, 0x1160, 0x7078, 0xa005, 0x1148, 0x7150, 0xa186, - 0xffff, 0x0128, 0x080c, 0x4ae7, 0x0110, 0x080c, 0x4c28, 0x20a9, - 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x60c3, 0x0014, 0x080c, 0x4b55, 0x0005, 0x00f6, 0x7084, 0xa005, - 0x01f0, 0x2011, 0x4b23, 0x080c, 0x6a0e, 0xa086, 0x0014, 0x11a8, - 0x2079, 0xbc80, 0x7a30, 0xa296, 0x1104, 0x1178, 0x7834, 0xa005, - 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, - 0x0001, 0x708f, 0x0014, 0x0029, 0x0010, 0x080c, 0x4b7b, 0x00fe, - 0x0005, 0x708f, 0x0015, 0x080c, 0x4c05, 0x20a3, 0x1104, 0x20a3, - 0x0000, 0x3430, 0x2011, 0xbc8e, 0x080c, 0x4c4a, 0x11a8, 0x7078, - 0xa005, 0x1190, 0x7158, 0xa186, 0xffff, 0x0170, 0xa180, 0x2df9, - 0x200d, 0xa18c, 0xff00, 0x810f, 0x080c, 0x4ae7, 0x0128, 0x080c, - 0x411d, 0x0110, 0x080c, 0x289c, 0x20a9, 0x0008, 0x2298, 0x26a0, - 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, - 0x4b55, 0x0005, 0x00f6, 0x7084, 0xa005, 0x05b8, 0x2011, 0x4b23, - 0x080c, 0x6a0e, 0xa086, 0x0014, 0x1570, 0x2079, 0xbc80, 0x7a30, - 0xa296, 0x1105, 0x1540, 0x7834, 0x2011, 0x0100, 0xa21e, 0x1148, - 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, - 0x0060, 0xa005, 0x11c0, 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, - 0x1110, 0x70bb, 0x0001, 0x708b, 0x0000, 0x7a38, 0xd2f4, 0x0138, - 0x2001, 0xb674, 0x2004, 0xd0a4, 0x1110, 0x70d7, 0x0008, 0x708f, - 0x0016, 0x0029, 0x0010, 0x080c, 0x4b7b, 0x00fe, 0x0005, 0x20e1, - 0x9080, 0x20e1, 0x4000, 0x2099, 0xbc80, 0x20a1, 0x020b, 0x20a9, - 0x000e, 0x53a6, 0x3430, 0x2011, 0xbc8e, 0x708f, 0x0017, 0x080c, - 0x4c4a, 0x1150, 0x7078, 0xa005, 0x1138, 0x080c, 0x4a5c, 0x1170, - 0xa085, 0x0001, 0x080c, 0x289c, 0x20a9, 0x0008, 0x2099, 0xbc8e, - 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, - 0x080c, 0x4b55, 0x0010, 0x080c, 0x4673, 0x0005, 0x00f6, 0x7084, - 0xa005, 0x01b0, 0x2011, 0x4b23, 0x080c, 0x6a0e, 0xa086, 0x0084, - 0x1168, 0x2079, 0xbc80, 0x7a30, 0xa296, 0x1106, 0x1138, 0x7834, - 0xa005, 0x1120, 0x708f, 0x0018, 0x0029, 0x0010, 0x080c, 0x4b7b, - 0x00fe, 0x0005, 0x708f, 0x0019, 0x080c, 0x4c05, 0x20a3, 0x1106, - 0x20a3, 0x0000, 0x3430, 0x2099, 0xbc8e, 0x2039, 0xbc0e, 0x27a0, - 0x20a9, 0x0040, 0x53a3, 0x080c, 0x4c4a, 0x11e8, 0x2728, 0x2514, - 0x8207, 0xa084, 0x00ff, 0x8000, 0x2018, 0xa294, 0x00ff, 0x8007, - 0xa205, 0x202a, 0x7054, 0x2310, 0x8214, 0xa2a0, 0xbc0e, 0x2414, - 0xa38c, 0x0001, 0x0118, 0xa294, 0xff00, 0x0018, 0xa294, 0x00ff, - 0x8007, 0xa215, 0x2222, 0x2798, 0x26a0, 0x20a9, 0x0040, 0x53a6, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0084, 0x080c, 0x4b55, - 0x0005, 0x00f6, 0x7084, 0xa005, 0x01d0, 0x2011, 0x4b23, 0x080c, - 0x6a0e, 0xa086, 0x0084, 0x1188, 0x2079, 0xbc80, 0x7a30, 0xa296, - 0x1107, 0x1158, 0x7834, 0xa005, 0x1140, 0x708b, 0x0001, 0x080c, - 0x4beb, 0x708f, 0x001a, 0x0029, 0x0010, 0x080c, 0x4b7b, 0x00fe, - 0x0005, 0x708f, 0x001b, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, - 0xbc80, 0x20a1, 0x020b, 0x7484, 0xa480, 0x0018, 0xa080, 0x0007, - 0xa084, 0x03f8, 0x8004, 0x20a8, 0x53a6, 0x60c3, 0x0084, 0x080c, - 0x4b55, 0x0005, 0x0005, 0x0005, 0x0086, 0x0096, 0x2029, 0xb653, - 0x252c, 0x20a9, 0x0008, 0x2041, 0xbc0e, 0x28a0, 0x2099, 0xbc8e, - 0x53a3, 0x20a9, 0x0008, 0x2011, 0x0007, 0xd5d4, 0x0110, 0x2011, - 0x0000, 0x2800, 0xa200, 0x200c, 0xa1a6, 0xffff, 0x1148, 0xd5d4, - 0x0110, 0x8210, 0x0008, 0x8211, 0x1f04, 0x4a71, 0x0804, 0x4adf, - 0x82ff, 0x1160, 0xd5d4, 0x0120, 0xa1a6, 0x3fff, 0x0d90, 0x0020, - 0xa1a6, 0x3fff, 0x0904, 0x4adf, 0xa18d, 0xc000, 0x20a9, 0x0010, - 0x2019, 0x0001, 0xd5d4, 0x0110, 0x2019, 0x0010, 0x2120, 0xd5d4, - 0x0110, 0x8423, 0x0008, 0x8424, 0x1240, 0xd5d4, 0x0110, 0x8319, - 0x0008, 0x8318, 0x1f04, 0x4a97, 0x04d0, 0x23a8, 0x2021, 0x0001, - 0x8426, 0x8425, 0x1f04, 0x4aa9, 0x2328, 0x8529, 0xa2be, 0x0007, - 0x0158, 0x0006, 0x2039, 0x0007, 0x2200, 0xa73a, 0x000e, 0x27a8, - 0xa5a8, 0x0010, 0x1f04, 0x4ab8, 0x7552, 0xa5c8, 0x2df9, 0x292d, - 0xa5ac, 0x00ff, 0x7576, 0x6532, 0x6536, 0x0016, 0x2508, 0x080c, - 0x287c, 0x001e, 0x60e7, 0x0000, 0x65ea, 0x2018, 0x2304, 0xa405, - 0x201a, 0x707b, 0x0001, 0x26a0, 0x2898, 0x20a9, 0x0008, 0x53a6, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0xa085, 0x0001, 0x0028, 0xa006, - 0x0018, 0xa006, 0x080c, 0x151a, 0x009e, 0x008e, 0x0005, 0x2118, - 0x2021, 0x0000, 0x2001, 0x0007, 0xa39a, 0x0010, 0x0218, 0x8420, - 0x8001, 0x0cd0, 0x2118, 0x84ff, 0x0120, 0xa39a, 0x0010, 0x8421, - 0x1de0, 0x2021, 0x0001, 0x83ff, 0x0118, 0x8423, 0x8319, 0x1de8, - 0xa238, 0x2704, 0xa42c, 0x11b8, 0xa405, 0x203a, 0x7152, 0xa1a0, - 0x2df9, 0x242d, 0xa5ac, 0x00ff, 0x7576, 0x6532, 0x6536, 0x0016, - 0x2508, 0x080c, 0x287c, 0x001e, 0x60e7, 0x0000, 0x65ea, 0x707b, - 0x0001, 0xa084, 0x0000, 0x0005, 0x00e6, 0x2071, 0xb600, 0x707f, - 0x0000, 0x00ee, 0x0005, 0x00e6, 0x00f6, 0x2079, 0x0100, 0x2071, - 0x0140, 0x080c, 0x4c61, 0x080c, 0x7df3, 0x7004, 0xa084, 0x4000, - 0x0120, 0x7003, 0x1000, 0x7003, 0x0000, 0x0126, 0x2091, 0x8000, - 0x2071, 0xb623, 0x2073, 0x0000, 0x7840, 0x0026, 0x0016, 0x2009, - 0x00f7, 0x080c, 0x4c11, 0x001e, 0xa094, 0x0010, 0xa285, 0x0080, - 0x7842, 0x7a42, 0x2009, 0x1388, 0x2011, 0x5a14, 0x080c, 0x6a94, - 0x002e, 0x012e, 0x00fe, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, - 0x2011, 0xb8eb, 0x2013, 0x0000, 0x7087, 0x0000, 0x012e, 0x20e1, - 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, 0x7dea, 0x6144, - 0xd184, 0x0120, 0x718c, 0xa18d, 0x2000, 0x0018, 0x7180, 0xa18d, - 0x1000, 0x2011, 0xb8bf, 0x2112, 0x2009, 0x07d0, 0x2011, 0x4b23, - 0x080c, 0x6a94, 0x0005, 0x0016, 0x0026, 0x00c6, 0x0126, 0x2091, - 0x8000, 0x2011, 0x0003, 0x080c, 0x80fc, 0x2011, 0x0002, 0x080c, - 0x8106, 0x080c, 0x7fe0, 0x0036, 0x2019, 0x0000, 0x080c, 0x806b, - 0x003e, 0x2009, 0x00f7, 0x080c, 0x4c11, 0x2061, 0xb8f4, 0x601b, - 0x0000, 0x601f, 0x0000, 0x2061, 0xb600, 0x6003, 0x0001, 0x2061, - 0x0100, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0xb8bf, 0x200b, - 0x0000, 0x2009, 0x002d, 0x2011, 0x4bb4, 0x080c, 0x6a02, 0x012e, - 0x00ce, 0x002e, 0x001e, 0x0005, 0x00e6, 0x0006, 0x0126, 0x2091, - 0x8000, 0x080c, 0x4c61, 0x2071, 0x0100, 0x080c, 0x7df3, 0x2071, - 0x0140, 0x7004, 0xa084, 0x4000, 0x0120, 0x7003, 0x1000, 0x7003, - 0x0000, 0x080c, 0x5b49, 0x01a8, 0x080c, 0x5b67, 0x1190, 0x2001, - 0xb89e, 0x2003, 0xaaaa, 0x0016, 0x080c, 0x2920, 0x2001, 0xb88f, - 0x2102, 0x001e, 0x2001, 0xb89f, 0x2003, 0x0000, 0x080c, 0x5a79, - 0x0030, 0x2001, 0x0001, 0x080c, 0x27f8, 0x080c, 0x4b7b, 0x012e, - 0x000e, 0x00ee, 0x0005, 0x20a9, 0x0040, 0x20a1, 0xbdc0, 0x2099, - 0xbc8e, 0x3304, 0x8007, 0x20a2, 0x9398, 0x94a0, 0x1f04, 0x4bf1, - 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xbc00, 0x20a1, - 0x020b, 0x20a9, 0x000c, 0x53a6, 0x0005, 0x20e1, 0x9080, 0x20e1, - 0x4000, 0x2099, 0xbc80, 0x20a1, 0x020b, 0x20a9, 0x000c, 0x53a6, - 0x0005, 0x00c6, 0x0006, 0x2061, 0x0100, 0x810f, 0x2001, 0xb631, - 0x2004, 0xa005, 0x1138, 0x2001, 0xb615, 0x2004, 0xa084, 0x00ff, - 0xa105, 0x0010, 0xa185, 0x00f7, 0x604a, 0x000e, 0x00ce, 0x0005, - 0x0016, 0x0046, 0x2001, 0xb653, 0x2004, 0xd0a4, 0x0158, 0xa006, - 0x2020, 0x2009, 0x002a, 0x080c, 0xb1a4, 0x2001, 0xb60c, 0x200c, - 0xc195, 0x2102, 0x2019, 0x002a, 0x2009, 0x0000, 0x080c, 0x2ca4, - 0x004e, 0x001e, 0x0005, 0x080c, 0x4b7b, 0x708f, 0x0000, 0x7087, - 0x0000, 0x0005, 0x0006, 0x2001, 0xb60c, 0x2004, 0xd09c, 0x0100, - 0x000e, 0x0005, 0x0006, 0x0016, 0x0126, 0x2091, 0x8000, 0x2001, - 0x0101, 0x200c, 0xa18d, 0x0006, 0x2102, 0x012e, 0x001e, 0x000e, - 0x0005, 0x2001, 0xb60d, 0x2004, 0xd0bc, 0x0158, 0x0026, 0x0036, - 0x2011, 0x8017, 0x2001, 0xb8bf, 0x201c, 0x080c, 0x3f13, 0x003e, - 0x002e, 0x0005, 0x0156, 0x20a9, 0x00ff, 0x2009, 0xb735, 0xa006, - 0x200a, 0x8108, 0x1f04, 0x4c78, 0x015e, 0x0005, 0x00d6, 0x0036, - 0x0156, 0x0136, 0x0146, 0x2069, 0xb652, 0xa006, 0x6002, 0x6007, - 0x0707, 0x600a, 0x600e, 0x6012, 0xa198, 0x2df9, 0x231d, 0xa39c, - 0x00ff, 0x6316, 0x20a9, 0x0004, 0xac98, 0x0006, 0x23a0, 0x40a4, - 0x20a9, 0x0004, 0xac98, 0x000a, 0x23a0, 0x40a4, 0x603e, 0x6042, - 0x604e, 0x6052, 0x6056, 0x605a, 0x605e, 0x6062, 0x6066, 0x606a, - 0x606e, 0x6072, 0x6076, 0x607a, 0x607e, 0x6082, 0x6086, 0x608a, - 0x608e, 0x6092, 0x6096, 0x609a, 0x609e, 0x60ae, 0x61a2, 0x00d6, - 0x60a4, 0xa06d, 0x0110, 0x080c, 0x1614, 0x60a7, 0x0000, 0x60a8, - 0xa06d, 0x0110, 0x080c, 0x1614, 0x60ab, 0x0000, 0x00de, 0xa006, - 0x604a, 0x6810, 0x603a, 0x680c, 0x6046, 0x6814, 0xa084, 0x00ff, - 0x6042, 0x014e, 0x013e, 0x015e, 0x003e, 0x00de, 0x0005, 0x0126, - 0x2091, 0x8000, 0x6944, 0x6e48, 0xa684, 0x3fff, 0xa082, 0x4000, - 0x1a04, 0x4d8c, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, 0x1a04, - 0x4d91, 0x2001, 0xb60c, 0x2004, 0xa084, 0x0003, 0x01c0, 0x2001, - 0xb60c, 0x2004, 0xd084, 0x1904, 0x4d74, 0xa188, 0xb735, 0x2104, - 0xa065, 0x0904, 0x4d74, 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, - 0x1904, 0x4d74, 0x6000, 0xd0c4, 0x0904, 0x4d74, 0x0068, 0xa188, - 0xb735, 0x2104, 0xa065, 0x0904, 0x4d59, 0x6004, 0xa084, 0x00ff, - 0xa08e, 0x0006, 0x1904, 0x4d5e, 0x60a4, 0xa00d, 0x0118, 0x080c, - 0x5246, 0x05d0, 0x60a8, 0xa00d, 0x0188, 0x080c, 0x5291, 0x1170, - 0x694c, 0xd1fc, 0x1118, 0x080c, 0x4f50, 0x0448, 0x080c, 0x4eff, - 0x694c, 0xd1ec, 0x1520, 0x080c, 0x5138, 0x0408, 0x694c, 0xa184, - 0xa000, 0x0178, 0xd1ec, 0x0140, 0xd1fc, 0x0118, 0x080c, 0x5147, - 0x0028, 0x080c, 0x5147, 0x0028, 0xd1fc, 0x0118, 0x080c, 0x4eff, - 0x0070, 0x6050, 0xa00d, 0x0130, 0x2d00, 0x200a, 0x6803, 0x0000, - 0x6052, 0x0028, 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x080c, - 0x6d1c, 0xa006, 0x012e, 0x0005, 0x2001, 0x0005, 0x2009, 0x0000, - 0x04e0, 0x2001, 0x0028, 0x2009, 0x0000, 0x04b8, 0xa082, 0x0006, - 0x1298, 0x2001, 0xb635, 0x2004, 0xd0ac, 0x1158, 0x60a0, 0xd0bc, - 0x1140, 0x6100, 0xd1fc, 0x0128, 0x2001, 0x0029, 0x2009, 0x1000, - 0x0420, 0x2001, 0x0028, 0x00a8, 0x2009, 0xb60c, 0x210c, 0xd18c, - 0x0118, 0x2001, 0x0004, 0x0068, 0xd184, 0x0118, 0x2001, 0x0004, - 0x0040, 0x2001, 0x0029, 0x6100, 0xd1fc, 0x0118, 0x2009, 0x1000, - 0x0060, 0x2009, 0x0000, 0x0048, 0x2001, 0x0029, 0x2009, 0x0000, - 0x0020, 0x2001, 0x0029, 0x2009, 0x0000, 0xa005, 0x012e, 0x0005, - 0x00e6, 0x0126, 0x2091, 0x8000, 0x6844, 0x8007, 0xa084, 0x00ff, - 0x2008, 0xa182, 0x00ff, 0x1a04, 0x4deb, 0xa188, 0xb735, 0x2104, - 0xa065, 0x01c0, 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, 0x11a8, - 0x2c70, 0x080c, 0x864e, 0x05e8, 0x2e00, 0x601a, 0x2d00, 0x6012, - 0x600b, 0xffff, 0x601f, 0x000a, 0x2009, 0x0003, 0x080c, 0x86d3, - 0xa006, 0x0460, 0x2001, 0x0028, 0x0440, 0xa082, 0x0006, 0x1298, - 0x2001, 0xb635, 0x2004, 0xd0ac, 0x1158, 0x60a0, 0xd0bc, 0x1140, - 0x6100, 0xd1fc, 0x09e8, 0x2001, 0x0029, 0x2009, 0x1000, 0x00a8, - 0x2001, 0x0028, 0x0090, 0x2009, 0xb60c, 0x210c, 0xd18c, 0x0118, - 0x2001, 0x0004, 0x0050, 0xd184, 0x0118, 0x2001, 0x0004, 0x0028, - 0x2001, 0x0029, 0x0010, 0x2001, 0x0029, 0xa005, 0x012e, 0x00ee, - 0x0005, 0x2001, 0x002c, 0x0cc8, 0x00f6, 0x00e6, 0x0126, 0x2091, - 0x8000, 0x2011, 0x0000, 0x2079, 0xb600, 0x6944, 0xa18c, 0xff00, - 0x810f, 0xa182, 0x00ff, 0x1a04, 0x4eb6, 0x080c, 0x501b, 0x11a0, - 0x6004, 0xa084, 0x00ff, 0xa082, 0x0006, 0x1270, 0x6864, 0xa0c6, - 0x006f, 0x0150, 0x2001, 0xb635, 0x2004, 0xd0ac, 0x1904, 0x4e9f, - 0x60a0, 0xd0bc, 0x1904, 0x4e9f, 0x6864, 0xa0c6, 0x006f, 0x0118, - 0x2008, 0x0804, 0x4e68, 0x6968, 0x2140, 0xa18c, 0xff00, 0x810f, - 0x78d4, 0xd0ac, 0x1118, 0xa182, 0x0080, 0x06d0, 0xa182, 0x00ff, - 0x16b8, 0x6a70, 0x6b6c, 0x7870, 0xa306, 0x1160, 0x7874, 0xa24e, - 0x1118, 0x2208, 0x2310, 0x0460, 0xa9cc, 0xff00, 0x1118, 0x2208, - 0x2310, 0x0430, 0x080c, 0x3e0c, 0x2c70, 0x0550, 0x2009, 0x0000, - 0x2011, 0x0000, 0xa0c6, 0x4000, 0x1160, 0x0006, 0x2e60, 0x080c, - 0x52bc, 0x1108, 0xc185, 0x7000, 0xd0bc, 0x0108, 0xc18d, 0x000e, - 0x0088, 0xa0c6, 0x4007, 0x1110, 0x2408, 0x0060, 0xa0c6, 0x4008, - 0x1118, 0x2708, 0x2610, 0x0030, 0xa0c6, 0x4009, 0x1108, 0x0010, - 0x2001, 0x4006, 0x6866, 0x696a, 0x6a6e, 0x2001, 0x0030, 0x0450, - 0x080c, 0x864e, 0x1138, 0x2001, 0x4005, 0x2009, 0x0003, 0x2011, - 0x0000, 0x0c80, 0x2e00, 0x601a, 0x080c, 0xa0e3, 0x2d00, 0x6012, - 0x601f, 0x0001, 0x6838, 0xd88c, 0x0108, 0xc0f5, 0x683a, 0x0126, - 0x2091, 0x8000, 0x080c, 0x2cd1, 0x012e, 0x2001, 0x0000, 0x080c, - 0x4f5d, 0x2001, 0x0002, 0x080c, 0x4f6f, 0x2009, 0x0002, 0x080c, - 0x86d3, 0xa006, 0xa005, 0x012e, 0x00ee, 0x00fe, 0x0005, 0x2001, - 0x0028, 0x2009, 0x0000, 0x0cb0, 0x2009, 0xb60c, 0x210c, 0xd18c, - 0x0118, 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, 0x2001, 0x0004, - 0x0010, 0x2001, 0x0029, 0x2009, 0x0000, 0x0c20, 0x2001, 0x0029, - 0x2009, 0x0000, 0x08f8, 0x6944, 0x6e48, 0xa684, 0x3fff, 0xa082, - 0x4000, 0x16b8, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, 0x12e0, - 0xa188, 0xb735, 0x2104, 0xa065, 0x01b8, 0x6004, 0xa084, 0x00ff, - 0xa08e, 0x0006, 0x11b0, 0x684c, 0xd0ec, 0x0120, 0x080c, 0x5147, - 0x0431, 0x0030, 0x0421, 0x684c, 0xd0fc, 0x0110, 0x080c, 0x5138, - 0x080c, 0x5185, 0xa006, 0x00c8, 0x2001, 0x0028, 0x2009, 0x0000, - 0x00a0, 0xa082, 0x0006, 0x1240, 0x6100, 0xd1fc, 0x0d20, 0x2001, - 0x0029, 0x2009, 0x1000, 0x0048, 0x2001, 0x0029, 0x2009, 0x0000, - 0x0020, 0x2001, 0x0029, 0x2009, 0x0000, 0xa005, 0x0005, 0x0126, - 0x2091, 0x8000, 0x6050, 0xa00d, 0x0138, 0x2d00, 0x200a, 0x6803, - 0x0000, 0x6052, 0x012e, 0x0005, 0x2d00, 0x6052, 0x604e, 0x6803, - 0x0000, 0x0cc0, 0x0126, 0x2091, 0x8000, 0x604c, 0xa005, 0x0170, - 0x00e6, 0x2071, 0xb8e1, 0x7004, 0xa086, 0x0002, 0x0168, 0x00ee, - 0x604c, 0x6802, 0x2d00, 0x604e, 0x012e, 0x0005, 0x2d00, 0x6052, - 0x604e, 0x6803, 0x0000, 0x0cc0, 0x701c, 0xac06, 0x1d80, 0x604c, - 0x2070, 0x7000, 0x6802, 0x2d00, 0x7002, 0x00ee, 0x012e, 0x0005, - 0x0126, 0x2091, 0x8000, 0x604c, 0xa06d, 0x0130, 0x6800, 0xa005, - 0x1108, 0x6052, 0x604e, 0xad05, 0x012e, 0x0005, 0x604c, 0xa06d, - 0x0130, 0x6800, 0xa005, 0x1108, 0x6052, 0x604e, 0xad05, 0x0005, - 0x6803, 0x0000, 0x6084, 0xa00d, 0x0120, 0x2d00, 0x200a, 0x6086, - 0x0005, 0x2d00, 0x6086, 0x6082, 0x0cd8, 0x0126, 0x00c6, 0x0026, - 0x2091, 0x8000, 0x6218, 0x2260, 0x6200, 0xa005, 0x0110, 0xc285, - 0x0008, 0xc284, 0x6202, 0x002e, 0x00ce, 0x012e, 0x0005, 0x0126, - 0x00c6, 0x2091, 0x8000, 0x6218, 0x2260, 0x6204, 0x0006, 0xa086, - 0x0006, 0x1180, 0x609c, 0xd0ac, 0x0168, 0x2001, 0xb653, 0x2004, - 0xd0a4, 0x0140, 0xa284, 0xff00, 0x8007, 0xa086, 0x0007, 0x1110, - 0x2011, 0x0600, 0x000e, 0xa294, 0xff00, 0xa215, 0x6206, 0x0006, - 0xa086, 0x0006, 0x1128, 0x6290, 0x82ff, 0x1110, 0x080c, 0x151a, - 0x000e, 0x00ce, 0x012e, 0x0005, 0x0126, 0x00c6, 0x2091, 0x8000, - 0x6218, 0x2260, 0x6204, 0x0006, 0xa086, 0x0006, 0x1178, 0x609c, - 0xd0a4, 0x0160, 0x2001, 0xb653, 0x2004, 0xd0ac, 0x1138, 0xa284, - 0x00ff, 0xa086, 0x0007, 0x1110, 0x2011, 0x0006, 0x000e, 0xa294, - 0x00ff, 0x8007, 0xa215, 0x6206, 0x00ce, 0x012e, 0x0005, 0x0026, - 0xa182, 0x00ff, 0x0218, 0xa085, 0x0001, 0x00b0, 0xa190, 0xb735, - 0x2204, 0xa065, 0x1180, 0x0016, 0x00d6, 0x080c, 0x15e4, 0x2d60, - 0x00de, 0x001e, 0x0d80, 0x2c00, 0x2012, 0x60a7, 0x0000, 0x60ab, - 0x0000, 0x080c, 0x4c7e, 0xa006, 0x002e, 0x0005, 0x0126, 0x2091, - 0x8000, 0x0026, 0xa182, 0x00ff, 0x0218, 0xa085, 0x0001, 0x0480, - 0x00d6, 0xa190, 0xb735, 0x2204, 0xa06d, 0x0540, 0x2013, 0x0000, - 0x00d6, 0x00c6, 0x2d60, 0x60a4, 0xa06d, 0x0110, 0x080c, 0x1614, - 0x60a8, 0xa06d, 0x0110, 0x080c, 0x1614, 0x00ce, 0x00de, 0x00d6, - 0x00c6, 0x68ac, 0x2060, 0x8cff, 0x0168, 0x600c, 0x0006, 0x6010, - 0x2068, 0x080c, 0x9d16, 0x0110, 0x080c, 0x1624, 0x080c, 0x86a4, - 0x00ce, 0x0c88, 0x00ce, 0x00de, 0x080c, 0x1614, 0x00de, 0xa006, - 0x002e, 0x012e, 0x0005, 0x0016, 0xa182, 0x00ff, 0x0218, 0xa085, - 0x0001, 0x0030, 0xa188, 0xb735, 0x2104, 0xa065, 0x0dc0, 0xa006, - 0x001e, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x600b, 0x0000, - 0x600f, 0x0000, 0x6000, 0xc08c, 0x6002, 0x080c, 0x5b41, 0x1558, - 0x60a0, 0xa086, 0x007e, 0x2069, 0xbc90, 0x0130, 0x2001, 0xb635, - 0x2004, 0xd0ac, 0x1500, 0x0098, 0x2d04, 0xd0e4, 0x01e0, 0x00d6, - 0x2069, 0xbc8e, 0x00c6, 0x2061, 0xb8b2, 0x6810, 0x2062, 0x6814, - 0x6006, 0x6818, 0x600a, 0x681c, 0x600e, 0x00ce, 0x00de, 0x8d69, - 0x2d04, 0x2069, 0x0140, 0xa005, 0x1110, 0x2001, 0x0001, 0x6886, - 0x2069, 0xb600, 0x68a6, 0x2069, 0xbc8e, 0x6808, 0x605e, 0x6810, - 0x6062, 0x6138, 0xa10a, 0x0208, 0x603a, 0x6814, 0x6066, 0x2099, - 0xbc96, 0xac88, 0x000a, 0x21a0, 0x20a9, 0x0004, 0x53a3, 0x2099, - 0xbc9a, 0xac88, 0x0006, 0x21a0, 0x20a9, 0x0004, 0x53a3, 0x2069, - 0xbcae, 0x6808, 0x606a, 0x690c, 0x616e, 0x6810, 0x6072, 0x6818, - 0x6076, 0x60a0, 0xa086, 0x007e, 0x1120, 0x2069, 0xbc8e, 0x690c, - 0x616e, 0xa182, 0x0211, 0x1218, 0x2009, 0x0008, 0x0400, 0xa182, - 0x0259, 0x1218, 0x2009, 0x0007, 0x00d0, 0xa182, 0x02c1, 0x1218, - 0x2009, 0x0006, 0x00a0, 0xa182, 0x0349, 0x1218, 0x2009, 0x0005, - 0x0070, 0xa182, 0x0421, 0x1218, 0x2009, 0x0004, 0x0040, 0xa182, - 0x0581, 0x1218, 0x2009, 0x0003, 0x0010, 0x2009, 0x0002, 0x6192, - 0x014e, 0x013e, 0x015e, 0x00de, 0x0005, 0x0016, 0x0026, 0x00e6, - 0x2071, 0xbc8d, 0x2e04, 0x6896, 0x2071, 0xbc8e, 0x7004, 0x689a, - 0x701c, 0x689e, 0x6a00, 0x2009, 0xb672, 0x210c, 0xd0bc, 0x0120, - 0xd1ec, 0x0110, 0xc2ad, 0x0008, 0xc2ac, 0xd0c4, 0x0120, 0xd1e4, - 0x0110, 0xc2bd, 0x0008, 0xc2bc, 0x6a02, 0x00ee, 0x002e, 0x001e, - 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x60a4, 0xa06d, 0x01c0, - 0x6900, 0x81ff, 0x1540, 0x6a04, 0xa282, 0x0010, 0x1648, 0xad88, - 0x0004, 0x20a9, 0x0010, 0x2104, 0xa086, 0xffff, 0x0128, 0x8108, - 0x1f04, 0x50f3, 0x080c, 0x151a, 0x260a, 0x8210, 0x6a06, 0x0098, - 0x080c, 0x15fd, 0x01a8, 0x2d00, 0x60a6, 0x6803, 0x0000, 0xad88, - 0x0004, 0x20a9, 0x0010, 0x200b, 0xffff, 0x8108, 0x1f04, 0x510b, - 0x6807, 0x0001, 0x6e12, 0xa085, 0x0001, 0x012e, 0x00de, 0x0005, - 0xa006, 0x0cd8, 0x0126, 0x2091, 0x8000, 0x00d6, 0x60a4, 0xa00d, - 0x01a0, 0x2168, 0x6800, 0xa005, 0x1160, 0x080c, 0x5246, 0x1168, - 0x200b, 0xffff, 0x6804, 0xa08a, 0x0002, 0x0218, 0x8001, 0x6806, - 0x0020, 0x080c, 0x1614, 0x60a7, 0x0000, 0x00de, 0x012e, 0x0005, - 0x0126, 0x2091, 0x8000, 0x080c, 0x52a4, 0x0010, 0x080c, 0x4eff, - 0x080c, 0x51be, 0x1dd8, 0x080c, 0x5185, 0x012e, 0x0005, 0x00d6, - 0x0126, 0x2091, 0x8000, 0x60a8, 0xa06d, 0x01c0, 0x6950, 0x81ff, - 0x1540, 0x6a54, 0xa282, 0x0010, 0x1670, 0xad88, 0x0018, 0x20a9, - 0x0010, 0x2104, 0xa086, 0xffff, 0x0128, 0x8108, 0x1f04, 0x5159, - 0x080c, 0x151a, 0x260a, 0x8210, 0x6a56, 0x0098, 0x080c, 0x15fd, - 0x01d0, 0x2d00, 0x60aa, 0x6853, 0x0000, 0xad88, 0x0018, 0x20a9, - 0x0010, 0x200b, 0xffff, 0x8108, 0x1f04, 0x5171, 0x6857, 0x0001, - 0x6e62, 0x0010, 0x080c, 0x4f50, 0x0089, 0x1de0, 0xa085, 0x0001, - 0x012e, 0x00de, 0x0005, 0xa006, 0x0cd8, 0x0126, 0x2091, 0x8000, - 0x080c, 0x6d1c, 0x012e, 0x0005, 0xa01e, 0x0010, 0x2019, 0x0001, - 0xa00e, 0x0126, 0x2091, 0x8000, 0x604c, 0x2068, 0x6000, 0xd0dc, - 0x1170, 0x8dff, 0x01f8, 0x83ff, 0x0120, 0x6848, 0xa606, 0x0158, - 0x0030, 0x683c, 0xa406, 0x1118, 0x6840, 0xa506, 0x0120, 0x2d08, - 0x6800, 0x2068, 0x0c70, 0x080c, 0x81a5, 0x6a00, 0x604c, 0xad06, - 0x1110, 0x624e, 0x0018, 0xa180, 0x0000, 0x2202, 0x82ff, 0x1110, - 0x6152, 0x8dff, 0x012e, 0x0005, 0xa01e, 0x0010, 0x2019, 0x0001, - 0xa00e, 0x6080, 0x2068, 0x8dff, 0x01e8, 0x83ff, 0x0120, 0x6848, - 0xa606, 0x0158, 0x0030, 0x683c, 0xa406, 0x1118, 0x6840, 0xa506, - 0x0120, 0x2d08, 0x6800, 0x2068, 0x0c70, 0x6a00, 0x6080, 0xad06, - 0x1110, 0x6282, 0x0018, 0xa180, 0x0000, 0x2202, 0x82ff, 0x1110, - 0x6186, 0x8dff, 0x0005, 0xa016, 0x080c, 0x5240, 0x1110, 0x2011, - 0x0001, 0x080c, 0x528b, 0x1110, 0xa295, 0x0002, 0x0005, 0x080c, - 0x52bc, 0x0118, 0x080c, 0x9dcb, 0x0010, 0xa085, 0x0001, 0x0005, - 0x080c, 0x52bc, 0x0118, 0x080c, 0x9d5b, 0x0010, 0xa085, 0x0001, - 0x0005, 0x080c, 0x52bc, 0x0118, 0x080c, 0x9dae, 0x0010, 0xa085, - 0x0001, 0x0005, 0x080c, 0x52bc, 0x0118, 0x080c, 0x9d77, 0x0010, - 0xa085, 0x0001, 0x0005, 0x080c, 0x52bc, 0x0118, 0x080c, 0x9de7, - 0x0010, 0xa085, 0x0001, 0x0005, 0x0126, 0x0006, 0x00d6, 0x2091, - 0x8000, 0x6080, 0xa06d, 0x01a0, 0x6800, 0x0006, 0x6837, 0x0103, - 0x6b4a, 0x6847, 0x0000, 0x080c, 0x9f88, 0x0006, 0x6000, 0xd0fc, - 0x0110, 0x080c, 0xb445, 0x000e, 0x080c, 0x547a, 0x000e, 0x0c50, - 0x6083, 0x0000, 0x6087, 0x0000, 0x00de, 0x000e, 0x012e, 0x0005, - 0x60a4, 0xa00d, 0x1118, 0xa085, 0x0001, 0x0005, 0x00e6, 0x2170, - 0x7000, 0xa005, 0x1168, 0x20a9, 0x0010, 0xae88, 0x0004, 0x2104, - 0xa606, 0x0130, 0x8108, 0x1f04, 0x524f, 0xa085, 0x0001, 0x0008, - 0xa006, 0x00ee, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x60a4, - 0xa06d, 0x1128, 0x080c, 0x15fd, 0x01a0, 0x2d00, 0x60a6, 0x6803, - 0x0001, 0x6807, 0x0000, 0xad88, 0x0004, 0x20a9, 0x0010, 0x200b, - 0xffff, 0x8108, 0x1f04, 0x526f, 0xa085, 0x0001, 0x012e, 0x00de, - 0x0005, 0xa006, 0x0cd8, 0x00d6, 0x0126, 0x2091, 0x8000, 0x60a4, - 0xa06d, 0x0130, 0x60a7, 0x0000, 0x080c, 0x1614, 0xa085, 0x0001, - 0x012e, 0x00de, 0x0005, 0x60a8, 0xa00d, 0x1118, 0xa085, 0x0001, - 0x0005, 0x00e6, 0x2170, 0x7050, 0xa005, 0x1160, 0x20a9, 0x0010, - 0xae88, 0x0018, 0x2104, 0xa606, 0x0128, 0x8108, 0x1f04, 0x529a, - 0xa085, 0x0001, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x0c19, - 0x1188, 0x200b, 0xffff, 0x00d6, 0x60a8, 0x2068, 0x6854, 0xa08a, - 0x0002, 0x0218, 0x8001, 0x6856, 0x0020, 0x080c, 0x1614, 0x60ab, - 0x0000, 0x00de, 0x012e, 0x0005, 0x609c, 0xd0a4, 0x0005, 0x00f6, - 0x080c, 0x5b41, 0x01b0, 0x71b8, 0x81ff, 0x1198, 0x71d4, 0xd19c, - 0x0180, 0x2001, 0x007e, 0xa080, 0xb735, 0x2004, 0xa07d, 0x0148, - 0x7804, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1118, 0x7800, 0xc0ed, - 0x7802, 0x2079, 0xb652, 0x7804, 0xd0a4, 0x01e8, 0x0156, 0x00c6, - 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, 0x501b, 0x1168, - 0x6004, 0xa084, 0xff00, 0x8007, 0xa096, 0x0004, 0x0118, 0xa086, - 0x0006, 0x1118, 0x6000, 0xc0ed, 0x6002, 0x001e, 0x8108, 0x1f04, - 0x52e4, 0x00ce, 0x015e, 0x080c, 0x537b, 0x0120, 0x2001, 0xb8b5, - 0x200c, 0x0038, 0x2079, 0xb652, 0x7804, 0xd0a4, 0x0130, 0x2009, - 0x07d0, 0x2011, 0x530f, 0x080c, 0x6a94, 0x00fe, 0x0005, 0x2011, - 0x530f, 0x080c, 0x6a0e, 0x080c, 0x537b, 0x01f0, 0x2001, 0xb7b3, - 0x2004, 0xa080, 0x0000, 0x200c, 0xc1ec, 0x2102, 0x2001, 0xb653, - 0x2004, 0xd0a4, 0x0130, 0x2009, 0x07d0, 0x2011, 0x530f, 0x080c, - 0x6a94, 0x00e6, 0x2071, 0xb600, 0x7073, 0x0000, 0x7077, 0x0000, - 0x080c, 0x2aed, 0x00ee, 0x04b0, 0x0156, 0x00c6, 0x20a9, 0x007f, - 0x2009, 0x0000, 0x0016, 0x080c, 0x501b, 0x1530, 0x6000, 0xd0ec, - 0x0518, 0x0046, 0x62a0, 0xa294, 0x00ff, 0x8227, 0xa006, 0x2009, - 0x0029, 0x080c, 0xb1a4, 0x6000, 0xc0e5, 0xc0ec, 0x6002, 0x6004, - 0xa084, 0x00ff, 0xa085, 0x0700, 0x6006, 0x2019, 0x0029, 0x080c, - 0x6e67, 0x0076, 0x2039, 0x0000, 0x080c, 0x6d74, 0x2009, 0x0000, - 0x080c, 0xaf3e, 0x007e, 0x004e, 0x001e, 0x8108, 0x1f04, 0x533a, - 0x00ce, 0x015e, 0x0005, 0x00c6, 0x6018, 0x2060, 0x6000, 0xc0ec, - 0x6002, 0x00ce, 0x0005, 0x7818, 0x2004, 0xd0ac, 0x0005, 0x7818, - 0x2004, 0xd0bc, 0x0005, 0x00f6, 0x2001, 0xb7b3, 0x2004, 0xa07d, - 0x0110, 0x7800, 0xd0ec, 0x00fe, 0x0005, 0x0126, 0x0026, 0x2091, - 0x8000, 0x0006, 0x62a0, 0xa290, 0xb735, 0x2204, 0xac06, 0x190c, - 0x151a, 0x000e, 0x6200, 0xa005, 0x0110, 0xc2fd, 0x0008, 0xc2fc, - 0x6202, 0x002e, 0x012e, 0x0005, 0x2011, 0xb635, 0x2204, 0xd0cc, - 0x0138, 0x2001, 0xb8b3, 0x200c, 0x2011, 0x53a9, 0x080c, 0x6a94, - 0x0005, 0x2011, 0x53a9, 0x080c, 0x6a0e, 0x2011, 0xb635, 0x2204, - 0xc0cc, 0x2012, 0x0005, 0x2071, 0xb714, 0x7003, 0x0001, 0x7007, - 0x0000, 0x7013, 0x0000, 0x7017, 0x0000, 0x701b, 0x0000, 0x701f, - 0x0000, 0x700b, 0x0000, 0x704b, 0x0001, 0x704f, 0x0000, 0x705b, - 0x0020, 0x705f, 0x0040, 0x707f, 0x0000, 0x2071, 0xb87d, 0x7003, - 0xb714, 0x7007, 0x0000, 0x700b, 0x0000, 0x700f, 0xb85d, 0x7013, - 0x0020, 0x7017, 0x0040, 0x7037, 0x0000, 0x0005, 0x0016, 0x00e6, - 0x2071, 0xb835, 0xa00e, 0x7186, 0x718a, 0x7097, 0x0001, 0x2001, - 0xb653, 0x2004, 0xd0fc, 0x1150, 0x2001, 0xb653, 0x2004, 0xa00e, - 0xd09c, 0x0108, 0x8108, 0x7102, 0x0804, 0x5444, 0x2001, 0xb672, - 0x200c, 0xa184, 0x000f, 0x2009, 0xb673, 0x210c, 0x0002, 0x53ec, - 0x541f, 0x5426, 0x5430, 0x5435, 0x53ec, 0x53ec, 0x53ec, 0x540f, - 0x53ec, 0x53ec, 0x53ec, 0x53ec, 0x53ec, 0x53ec, 0x53ec, 0x7003, - 0x0004, 0x0136, 0x0146, 0x0156, 0x2099, 0xb676, 0x20a1, 0xb886, - 0x20a9, 0x0004, 0x53a3, 0x015e, 0x014e, 0x013e, 0x0428, 0x708f, - 0x0005, 0x7007, 0x0122, 0x2001, 0x0002, 0x0030, 0x708f, 0x0002, - 0x7007, 0x0121, 0x2001, 0x0003, 0x7002, 0x7097, 0x0001, 0x0088, - 0x7007, 0x0122, 0x2001, 0x0002, 0x0020, 0x7007, 0x0121, 0x2001, - 0x0003, 0x7002, 0xa006, 0x7096, 0x708e, 0xa184, 0xff00, 0x8007, - 0x709a, 0xa184, 0x00ff, 0x7092, 0x00ee, 0x001e, 0x0005, 0x00e6, - 0x2071, 0xb714, 0x684c, 0xa005, 0x1130, 0x7028, 0xc085, 0x702a, - 0xa085, 0x0001, 0x0428, 0x6a60, 0x7236, 0x6b64, 0x733a, 0x6868, - 0x703e, 0x7076, 0x686c, 0x7042, 0x707a, 0x684c, 0x702e, 0x6844, - 0x7032, 0x2009, 0x000d, 0x200a, 0x700b, 0x0000, 0x8007, 0x8006, - 0x8006, 0xa08c, 0x003f, 0xa084, 0xffc0, 0xa210, 0x2100, 0xa319, - 0x726e, 0x7372, 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0xa006, - 0x00ee, 0x0005, 0x0156, 0x00e6, 0x0026, 0x6838, 0xd0fc, 0x1904, - 0x54d3, 0x6804, 0xa00d, 0x0188, 0x00d6, 0x2071, 0xb600, 0xa016, - 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, - 0x702e, 0x70b4, 0xa200, 0x70b6, 0x00de, 0x2071, 0xb714, 0x701c, - 0xa005, 0x1904, 0x54e3, 0x20a9, 0x0032, 0x0f04, 0x54e1, 0x0e04, - 0x549d, 0x2071, 0xb835, 0x7200, 0x82ff, 0x05d8, 0x6934, 0xa186, - 0x0103, 0x1904, 0x54f1, 0x6948, 0x6844, 0xa105, 0x1540, 0x2009, - 0x8020, 0x2200, 0x0002, 0x54e1, 0x54b8, 0x5509, 0x5515, 0x54e1, - 0x2071, 0x0000, 0x20a9, 0x0032, 0x0f04, 0x54e1, 0x7018, 0xd084, - 0x1dd8, 0x7122, 0x683c, 0x7026, 0x6840, 0x702a, 0x701b, 0x0001, - 0x2091, 0x4080, 0x2071, 0xb600, 0x702c, 0x206a, 0x2d00, 0x702e, - 0x70b4, 0x8000, 0x70b6, 0x002e, 0x00ee, 0x015e, 0x0005, 0x6844, - 0xa086, 0x0100, 0x1130, 0x6868, 0xa005, 0x1118, 0x2009, 0x8020, - 0x0880, 0x2071, 0xb714, 0x2d08, 0x206b, 0x0000, 0x7010, 0x8000, - 0x7012, 0x7018, 0xa06d, 0x711a, 0x0110, 0x6902, 0x0008, 0x711e, - 0x0c10, 0xa18c, 0x00ff, 0xa186, 0x0017, 0x0130, 0xa186, 0x001e, - 0x0118, 0xa18e, 0x001f, 0x1d28, 0x684c, 0xd0cc, 0x0d10, 0x6850, - 0xa084, 0x00ff, 0xa086, 0x0001, 0x19e0, 0x2009, 0x8021, 0x0804, - 0x54b1, 0x7084, 0x8008, 0xa092, 0x001e, 0x1a98, 0x7186, 0xae90, - 0x0003, 0xa210, 0x683c, 0x2012, 0x0078, 0x7084, 0x8008, 0xa092, - 0x000f, 0x1a38, 0x7186, 0xae90, 0x0003, 0x8003, 0xa210, 0x683c, - 0x2012, 0x8210, 0x6840, 0x2012, 0x7088, 0xa10a, 0x0a04, 0x54ca, - 0x718c, 0x7084, 0xa10a, 0x0a04, 0x54ca, 0x2071, 0x0000, 0x7018, - 0xd084, 0x1904, 0x54ca, 0x2071, 0xb835, 0x7000, 0xa086, 0x0002, - 0x1150, 0x080c, 0x5794, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, - 0x4080, 0x0804, 0x54ca, 0x080c, 0x57be, 0x2071, 0x0000, 0x701b, - 0x0001, 0x2091, 0x4080, 0x0804, 0x54ca, 0x0006, 0x684c, 0x0006, - 0x6837, 0x0103, 0x20a9, 0x001c, 0xad80, 0x0011, 0x20a0, 0x2001, - 0x0000, 0x40a4, 0x000e, 0xa084, 0x00ff, 0x684e, 0x000e, 0x684a, - 0x6952, 0x0005, 0x2071, 0xb714, 0x7004, 0x0002, 0x5570, 0x5581, - 0x577f, 0x5780, 0x578d, 0x5793, 0x5571, 0x5770, 0x5706, 0x575c, - 0x0005, 0x0126, 0x2091, 0x8000, 0x0e04, 0x5580, 0x2009, 0x000d, - 0x7030, 0x200a, 0x2091, 0x4080, 0x7007, 0x0001, 0x700b, 0x0000, - 0x012e, 0x2069, 0xb8f4, 0x683c, 0xa005, 0x03f8, 0x11f0, 0x0126, - 0x2091, 0x8000, 0x2069, 0x0000, 0x6934, 0x2001, 0xb720, 0x2004, - 0xa10a, 0x0170, 0x0e04, 0x55a4, 0x2069, 0x0000, 0x6818, 0xd084, - 0x1158, 0x2009, 0x8040, 0x6922, 0x681b, 0x0001, 0x2091, 0x4080, - 0x2069, 0xb8f4, 0x683f, 0xffff, 0x012e, 0x2069, 0xb600, 0x6848, - 0x6968, 0xa102, 0x2069, 0xb835, 0x688a, 0x6984, 0x701c, 0xa06d, - 0x0120, 0x81ff, 0x0904, 0x55fa, 0x00a0, 0x81ff, 0x0904, 0x56c0, - 0x2071, 0xb835, 0x7184, 0x7088, 0xa10a, 0x1258, 0x7190, 0x2071, - 0xb8f4, 0x7038, 0xa005, 0x0128, 0x1b04, 0x56c0, 0x713a, 0x0804, - 0x56c0, 0x2071, 0xb835, 0x718c, 0x0126, 0x2091, 0x8000, 0x7084, - 0xa10a, 0x0a04, 0x56db, 0x0e04, 0x567c, 0x2071, 0x0000, 0x7018, - 0xd084, 0x1904, 0x567c, 0x2001, 0xffff, 0x2071, 0xb8f4, 0x703a, - 0x2071, 0xb835, 0x7000, 0xa086, 0x0002, 0x1150, 0x080c, 0x5794, - 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0804, 0x567c, - 0x080c, 0x57be, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, - 0x0804, 0x567c, 0x2071, 0xb835, 0x7000, 0xa005, 0x0904, 0x56a2, - 0x6934, 0xa186, 0x0103, 0x1904, 0x567f, 0x684c, 0xd0bc, 0x1904, - 0x56a2, 0x6948, 0x6844, 0xa105, 0x1904, 0x5697, 0x2009, 0x8020, - 0x2071, 0xb835, 0x7000, 0x0002, 0x56a2, 0x5662, 0x563a, 0x564c, - 0x5619, 0x0136, 0x0146, 0x0156, 0x2099, 0xb676, 0x20a1, 0xb886, - 0x20a9, 0x0004, 0x53a3, 0x015e, 0x014e, 0x013e, 0x2071, 0xb87d, - 0xad80, 0x000f, 0x700e, 0x7013, 0x0002, 0x7007, 0x0002, 0x700b, - 0x0000, 0x2e10, 0x080c, 0x1648, 0x2071, 0xb714, 0x7007, 0x0009, - 0x0804, 0x56c0, 0x7084, 0x8008, 0xa092, 0x001e, 0x1a04, 0x56c0, - 0xae90, 0x0003, 0xa210, 0x683c, 0x2012, 0x7186, 0x2071, 0xb714, - 0x080c, 0x5815, 0x0804, 0x56c0, 0x7084, 0x8008, 0xa092, 0x000f, - 0x1a04, 0x56c0, 0xae90, 0x0003, 0x8003, 0xa210, 0x683c, 0x2012, - 0x8210, 0x6840, 0x2012, 0x7186, 0x2071, 0xb714, 0x080c, 0x5815, - 0x0804, 0x56c0, 0x0126, 0x2091, 0x8000, 0x0e04, 0x567c, 0x2071, - 0x0000, 0x7018, 0xd084, 0x1180, 0x7122, 0x683c, 0x7026, 0x6840, - 0x702a, 0x701b, 0x0001, 0x2091, 0x4080, 0x012e, 0x2071, 0xb714, - 0x080c, 0x5815, 0x0804, 0x56c0, 0x012e, 0x0804, 0x56c0, 0xa18c, - 0x00ff, 0xa186, 0x0017, 0x0130, 0xa186, 0x001e, 0x0118, 0xa18e, - 0x001f, 0x11c0, 0x684c, 0xd0cc, 0x01a8, 0x6850, 0xa084, 0x00ff, - 0xa086, 0x0001, 0x1178, 0x2009, 0x8021, 0x0804, 0x5610, 0x6844, - 0xa086, 0x0100, 0x1138, 0x6868, 0xa005, 0x1120, 0x2009, 0x8020, - 0x0804, 0x5610, 0x2071, 0xb714, 0x080c, 0x5827, 0x01c8, 0x2071, - 0xb714, 0x700f, 0x0001, 0x6934, 0xa184, 0x00ff, 0xa086, 0x0003, - 0x1130, 0x810f, 0xa18c, 0x00ff, 0x8101, 0x0108, 0x710e, 0x7007, - 0x0003, 0x080c, 0x5840, 0x7050, 0xa086, 0x0100, 0x0904, 0x5780, - 0x0126, 0x2091, 0x8000, 0x2071, 0xb714, 0x7008, 0xa086, 0x0001, - 0x1180, 0x0e04, 0x56d9, 0x2009, 0x000d, 0x7030, 0x200a, 0x2091, - 0x4080, 0x700b, 0x0000, 0x7004, 0xa086, 0x0006, 0x1110, 0x7007, - 0x0001, 0x012e, 0x0005, 0x2071, 0xb714, 0x080c, 0x5827, 0x0518, - 0x2071, 0xb835, 0x7084, 0x700a, 0x20a9, 0x0020, 0x2099, 0xb836, - 0x20a1, 0xb85d, 0x53a3, 0x7087, 0x0000, 0x2071, 0xb714, 0x2069, - 0xb87d, 0x706c, 0x6826, 0x7070, 0x682a, 0x7074, 0x682e, 0x7078, - 0x6832, 0x2d10, 0x080c, 0x1648, 0x7007, 0x0008, 0x2001, 0xffff, - 0x2071, 0xb8f4, 0x703a, 0x012e, 0x0804, 0x56c0, 0x2069, 0xb87d, - 0x6808, 0xa08e, 0x0000, 0x0904, 0x575b, 0xa08e, 0x0200, 0x0904, - 0x5759, 0xa08e, 0x0100, 0x1904, 0x575b, 0x0126, 0x2091, 0x8000, - 0x0e04, 0x5757, 0x2069, 0x0000, 0x6818, 0xd084, 0x15c0, 0x702c, - 0x7130, 0x8108, 0xa102, 0x0230, 0xa00e, 0x7034, 0x706e, 0x7038, - 0x7072, 0x0048, 0x706c, 0xa080, 0x0040, 0x706e, 0x1220, 0x7070, - 0xa081, 0x0000, 0x7072, 0x7132, 0x6936, 0x700b, 0x0000, 0x2001, - 0xb85a, 0x2004, 0xa005, 0x1190, 0x6934, 0x2069, 0xb835, 0x689c, - 0x699e, 0x2069, 0xb8f4, 0xa102, 0x1118, 0x683c, 0xa005, 0x1368, - 0x2001, 0xb85b, 0x200c, 0x810d, 0x693e, 0x0038, 0x2009, 0x8040, - 0x6922, 0x681b, 0x0001, 0x2091, 0x4080, 0x7007, 0x0001, 0x012e, - 0x0010, 0x7007, 0x0005, 0x0005, 0x2001, 0xb87f, 0x2004, 0xa08e, - 0x0100, 0x1128, 0x7007, 0x0001, 0x080c, 0x5815, 0x0005, 0xa08e, - 0x0000, 0x0de0, 0xa08e, 0x0200, 0x1dc8, 0x7007, 0x0005, 0x0005, - 0x701c, 0xa06d, 0x0158, 0x080c, 0x5827, 0x0140, 0x7007, 0x0003, - 0x080c, 0x5840, 0x7050, 0xa086, 0x0100, 0x0110, 0x0005, 0x0005, - 0x7050, 0xa09e, 0x0100, 0x1118, 0x7007, 0x0004, 0x0030, 0xa086, - 0x0200, 0x1110, 0x7007, 0x0005, 0x0005, 0x080c, 0x57e3, 0x7006, - 0x080c, 0x5815, 0x0005, 0x0005, 0x00e6, 0x0156, 0x2071, 0xb835, - 0x7184, 0x81ff, 0x0500, 0xa006, 0x7086, 0xae80, 0x0003, 0x2071, - 0x0000, 0x21a8, 0x2014, 0x7226, 0x8000, 0x0f04, 0x57b8, 0x2014, - 0x722a, 0x8000, 0x0f04, 0x57b8, 0x2014, 0x722e, 0x8000, 0x0f04, - 0x57b8, 0x2014, 0x723a, 0x8000, 0x0f04, 0x57b8, 0x2014, 0x723e, - 0xa180, 0x8030, 0x7022, 0x015e, 0x00ee, 0x0005, 0x00e6, 0x0156, - 0x2071, 0xb835, 0x7184, 0x81ff, 0x01d8, 0xa006, 0x7086, 0xae80, - 0x0003, 0x2071, 0x0000, 0x21a8, 0x2014, 0x7226, 0x8000, 0x2014, - 0x722a, 0x8000, 0x0f04, 0x57da, 0x2014, 0x723a, 0x8000, 0x2014, - 0x723e, 0x0018, 0x2001, 0x8020, 0x0010, 0x2001, 0x8042, 0x7022, - 0x015e, 0x00ee, 0x0005, 0x702c, 0x7130, 0x8108, 0xa102, 0x0230, - 0xa00e, 0x7034, 0x706e, 0x7038, 0x7072, 0x0048, 0x706c, 0xa080, - 0x0040, 0x706e, 0x1220, 0x7070, 0xa081, 0x0000, 0x7072, 0x7132, - 0x700c, 0x8001, 0x700e, 0x1180, 0x0126, 0x2091, 0x8000, 0x0e04, - 0x580f, 0x2001, 0x000d, 0x2102, 0x2091, 0x4080, 0x2001, 0x0001, - 0x700b, 0x0000, 0x012e, 0x0005, 0x2001, 0x0007, 0x0005, 0x2001, - 0x0006, 0x700b, 0x0001, 0x012e, 0x0005, 0x701c, 0xa06d, 0x0170, - 0x0126, 0x2091, 0x8000, 0x7010, 0x8001, 0x7012, 0x2d04, 0x701e, - 0xa005, 0x1108, 0x701a, 0x012e, 0x080c, 0x1614, 0x0005, 0x2019, - 0x000d, 0x2304, 0x230c, 0xa10e, 0x0130, 0x2304, 0x230c, 0xa10e, - 0x0110, 0xa006, 0x0060, 0x732c, 0x8319, 0x7130, 0xa102, 0x1118, - 0x2300, 0xa005, 0x0020, 0x0210, 0xa302, 0x0008, 0x8002, 0x0005, - 0x2d00, 0x7026, 0xa080, 0x000d, 0x7056, 0x7053, 0x0000, 0x0126, - 0x2091, 0x8000, 0x2009, 0xb913, 0x2104, 0xc08d, 0x200a, 0x012e, - 0x080c, 0x1664, 0x0005, 0x708c, 0xa08a, 0x0029, 0x1220, 0xa082, - 0x001d, 0x0033, 0x0010, 0x080c, 0x151a, 0x6027, 0x1e00, 0x0005, - 0x594e, 0x58c9, 0x58e1, 0x591e, 0x593f, 0x5979, 0x598b, 0x58e1, - 0x5965, 0x586d, 0x589b, 0x586c, 0x0005, 0x00d6, 0x2069, 0x0200, - 0x6804, 0xa005, 0x1180, 0x6808, 0xa005, 0x1518, 0x708f, 0x0028, - 0x2069, 0xb8c6, 0x2d04, 0x7002, 0x080c, 0x5c43, 0x6028, 0xa085, - 0x0600, 0x602a, 0x00b0, 0x708f, 0x0028, 0x2069, 0xb8c6, 0x2d04, - 0x7002, 0x6028, 0xa085, 0x0600, 0x602a, 0x00e6, 0x0036, 0x0046, - 0x0056, 0x2071, 0xb924, 0x080c, 0x1e1a, 0x005e, 0x004e, 0x003e, - 0x00ee, 0x00de, 0x0005, 0x00d6, 0x2069, 0x0200, 0x6804, 0xa005, - 0x1180, 0x6808, 0xa005, 0x1518, 0x708f, 0x0028, 0x2069, 0xb8c6, - 0x2d04, 0x7002, 0x080c, 0x5cd0, 0x6028, 0xa085, 0x0600, 0x602a, - 0x00b0, 0x708f, 0x0028, 0x2069, 0xb8c6, 0x2d04, 0x7002, 0x6028, - 0xa085, 0x0600, 0x602a, 0x00e6, 0x0036, 0x0046, 0x0056, 0x2071, - 0xb924, 0x080c, 0x1e1a, 0x005e, 0x004e, 0x003e, 0x00ee, 0x00de, - 0x0005, 0x6803, 0x0090, 0x6124, 0xd1e4, 0x1190, 0x080c, 0x59f6, - 0xd1d4, 0x1160, 0xd1dc, 0x1138, 0xd1cc, 0x0150, 0x708f, 0x0020, - 0x080c, 0x59f6, 0x0028, 0x708f, 0x001d, 0x0010, 0x708f, 0x001f, - 0x0005, 0x6803, 0x0088, 0x6124, 0xd1cc, 0x1590, 0xd1dc, 0x1568, - 0xd1e4, 0x1540, 0xa184, 0x1e00, 0x1580, 0x60e3, 0x0001, 0x600c, - 0xc0b4, 0x600e, 0x080c, 0x5b71, 0x080c, 0x24e5, 0x0156, 0x6803, - 0x0100, 0x20a9, 0x0014, 0x6804, 0xd0dc, 0x1118, 0x1f04, 0x58fb, - 0x0048, 0x20a9, 0x0014, 0x6803, 0x0080, 0x6804, 0xd0d4, 0x1130, - 0x1f04, 0x5905, 0x080c, 0x5b92, 0x015e, 0x0078, 0x015e, 0x708f, - 0x0028, 0x0058, 0x708f, 0x001e, 0x0040, 0x708f, 0x001d, 0x0028, - 0x708f, 0x0020, 0x0010, 0x708f, 0x001f, 0x0005, 0x60e3, 0x0001, - 0x600c, 0xc0b4, 0x600e, 0x080c, 0x5b71, 0x080c, 0x24e5, 0x6803, - 0x0080, 0x6124, 0xd1d4, 0x1180, 0xd1dc, 0x1158, 0xd1e4, 0x1130, - 0xa184, 0x1e00, 0x1158, 0x708f, 0x0028, 0x0040, 0x708f, 0x001e, - 0x0028, 0x708f, 0x001d, 0x0010, 0x708f, 0x001f, 0x0005, 0x6803, - 0x00a0, 0x6124, 0xd1dc, 0x1138, 0xd1e4, 0x0138, 0x080c, 0x1e63, - 0x708f, 0x001e, 0x0010, 0x708f, 0x001d, 0x0005, 0x080c, 0x5a68, - 0x6124, 0xd1dc, 0x1188, 0x080c, 0x59f6, 0x0016, 0x080c, 0x1e63, - 0x001e, 0xd1d4, 0x1128, 0xd1e4, 0x0138, 0x708f, 0x001e, 0x0020, - 0x708f, 0x001f, 0x080c, 0x59f6, 0x0005, 0x6803, 0x00a0, 0x6124, - 0xd1d4, 0x1160, 0xd1cc, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, - 0x708f, 0x001e, 0x0028, 0x708f, 0x001d, 0x0010, 0x708f, 0x0021, - 0x0005, 0x080c, 0x5a68, 0x6124, 0xd1d4, 0x1150, 0xd1dc, 0x1128, - 0xd1e4, 0x0140, 0x708f, 0x001e, 0x0028, 0x708f, 0x001d, 0x0010, - 0x708f, 0x001f, 0x0005, 0x6803, 0x0090, 0x6124, 0xd1d4, 0x1178, - 0xd1cc, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0158, 0x708f, 0x001e, - 0x0040, 0x708f, 0x001d, 0x0028, 0x708f, 0x0020, 0x0010, 0x708f, - 0x001f, 0x0005, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x0126, 0x2061, - 0x0100, 0x2069, 0x0140, 0x2071, 0xb600, 0x2091, 0x8000, 0x080c, - 0x5b41, 0x11e8, 0x2001, 0xb60c, 0x200c, 0xd1b4, 0x01c0, 0xc1b4, - 0x2102, 0x6027, 0x0200, 0xe000, 0xe000, 0x6024, 0xd0cc, 0x0158, - 0x6803, 0x00a0, 0x2001, 0xb89f, 0x2003, 0x0001, 0x2001, 0xb600, - 0x2003, 0x0001, 0x0428, 0x6028, 0xc0cd, 0x602a, 0x0408, 0x080c, - 0x5b5d, 0x0150, 0x080c, 0x5b53, 0x1138, 0x2001, 0x0001, 0x080c, - 0x27f8, 0x080c, 0x5b18, 0x00a0, 0x080c, 0x5a65, 0x0178, 0x2001, - 0x0001, 0x080c, 0x27f8, 0x708c, 0xa086, 0x001e, 0x0120, 0x708c, - 0xa086, 0x0022, 0x1118, 0x708f, 0x0025, 0x0010, 0x708f, 0x0021, - 0x012e, 0x00ee, 0x00de, 0x00ce, 0x001e, 0x0005, 0x0026, 0x2011, - 0x5a07, 0x080c, 0x6ace, 0x002e, 0x0016, 0x0026, 0x2009, 0x0064, - 0x2011, 0x5a07, 0x080c, 0x6ac5, 0x002e, 0x001e, 0x0005, 0x00e6, - 0x00f6, 0x0016, 0x080c, 0x7df3, 0x2071, 0xb600, 0x080c, 0x59a2, - 0x001e, 0x00fe, 0x00ee, 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6, - 0x00d6, 0x00e6, 0x00f6, 0x0126, 0x080c, 0x7df3, 0x2061, 0x0100, - 0x2069, 0x0140, 0x2071, 0xb600, 0x2091, 0x8000, 0x6028, 0xc09c, - 0x602a, 0x2011, 0x0003, 0x080c, 0x80fc, 0x2011, 0x0002, 0x080c, - 0x8106, 0x080c, 0x7fe0, 0x080c, 0x6a82, 0x0036, 0x2019, 0x0000, - 0x080c, 0x806b, 0x003e, 0x60e3, 0x0000, 0x080c, 0xb4eb, 0x080c, - 0xb506, 0x2001, 0xb600, 0x2003, 0x0004, 0x6027, 0x0008, 0x080c, - 0x12e2, 0x2001, 0x0001, 0x080c, 0x27f8, 0x012e, 0x00fe, 0x00ee, - 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x0005, 0x2001, 0xb600, - 0x2004, 0xa086, 0x0004, 0x0140, 0x2001, 0xb89e, 0x2003, 0xaaaa, - 0x2001, 0xb89f, 0x2003, 0x0000, 0x0005, 0x6020, 0xd09c, 0x0005, - 0x6800, 0xa086, 0x00c0, 0x0160, 0x6803, 0x00c0, 0x0156, 0x20a9, - 0x002d, 0x1d04, 0x5a71, 0x2091, 0x6000, 0x1f04, 0x5a71, 0x015e, - 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, - 0x2071, 0xb600, 0x2001, 0xb89f, 0x200c, 0xa186, 0x0000, 0x0158, - 0xa186, 0x0001, 0x0158, 0xa186, 0x0002, 0x0158, 0xa186, 0x0003, - 0x0158, 0x0804, 0x5b06, 0x708f, 0x0022, 0x0040, 0x708f, 0x0021, - 0x0028, 0x708f, 0x0023, 0x0020, 0x708f, 0x0024, 0x6043, 0x0000, - 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, 0x28a7, - 0x0026, 0x2011, 0x0003, 0x080c, 0x80fc, 0x2011, 0x0002, 0x080c, - 0x8106, 0x080c, 0x7fe0, 0x0036, 0x2019, 0x0000, 0x080c, 0x806b, - 0x003e, 0x002e, 0x7000, 0xa08e, 0x0004, 0x0118, 0x602b, 0x0028, - 0x0010, 0x602b, 0x0020, 0x0156, 0x0126, 0x2091, 0x8000, 0x20a9, - 0x0005, 0x6024, 0xd0ac, 0x0120, 0x012e, 0x015e, 0x0804, 0x5b14, - 0x6800, 0xa084, 0x00a0, 0xc0bd, 0x6802, 0x6904, 0xd1d4, 0x1130, - 0x6803, 0x0100, 0x1f04, 0x5ac9, 0x080c, 0x5b92, 0x012e, 0x015e, - 0x080c, 0x5b53, 0x01a8, 0x6044, 0xa005, 0x0168, 0x6050, 0x0006, - 0xa085, 0x0020, 0x6052, 0x080c, 0x5b92, 0xa006, 0x8001, 0x1df0, - 0x000e, 0x6052, 0x0028, 0x6804, 0xd0d4, 0x1110, 0x080c, 0x5b92, - 0x0016, 0x0026, 0x2009, 0x00c8, 0x2011, 0x5a14, 0x080c, 0x6a94, - 0x002e, 0x001e, 0x2001, 0xb89f, 0x2003, 0x0004, 0x080c, 0x5853, - 0x080c, 0x5b53, 0x0148, 0x6804, 0xd0d4, 0x1130, 0xd0dc, 0x1100, - 0x2001, 0xb89f, 0x2003, 0x0000, 0x00ee, 0x00de, 0x00ce, 0x0005, - 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, - 0xb600, 0x2001, 0xb89e, 0x2003, 0x0000, 0x2001, 0xb88f, 0x2003, - 0x0000, 0x708f, 0x0000, 0x60e3, 0x0000, 0x6887, 0x0000, 0x2001, - 0x0000, 0x080c, 0x28a7, 0x6803, 0x0000, 0x6043, 0x0090, 0x6043, - 0x0010, 0x6027, 0xffff, 0x602b, 0x182f, 0x00ee, 0x00de, 0x00ce, - 0x0005, 0x0006, 0x2001, 0xb89e, 0x2004, 0xa086, 0xaaaa, 0x000e, - 0x0005, 0x0006, 0x2001, 0xb672, 0x2004, 0xa084, 0x0030, 0xa086, - 0x0000, 0x000e, 0x0005, 0x0006, 0x2001, 0xb672, 0x2004, 0xa084, - 0x0030, 0xa086, 0x0030, 0x000e, 0x0005, 0x0006, 0x2001, 0xb672, - 0x2004, 0xa084, 0x0030, 0xa086, 0x0010, 0x000e, 0x0005, 0x0006, - 0x2001, 0xb672, 0x2004, 0xa084, 0x0030, 0xa086, 0x0020, 0x000e, - 0x0005, 0x2001, 0xb60c, 0x2004, 0xd0a4, 0x0170, 0x080c, 0x28c7, - 0x0036, 0x0016, 0x2009, 0x0000, 0x2019, 0x0028, 0x080c, 0x2ca4, - 0x001e, 0x003e, 0xa006, 0x0009, 0x0005, 0x00e6, 0x2071, 0xb60c, - 0x2e04, 0x0118, 0xa085, 0x0010, 0x0010, 0xa084, 0xffef, 0x2072, - 0x00ee, 0x0005, 0x6050, 0x0006, 0x60f0, 0x0006, 0x60ec, 0x0006, - 0x600c, 0x0006, 0x6004, 0x0006, 0x6028, 0x0006, 0x602f, 0x0100, - 0x602f, 0x0000, 0x602f, 0x0040, 0x602f, 0x0000, 0x000e, 0x602a, - 0x000e, 0x6006, 0x000e, 0x600e, 0x000e, 0x60ee, 0x000e, 0x60f2, - 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, 0x28a7, - 0x6800, 0xa084, 0x00a0, 0xc0bd, 0x6802, 0x6803, 0x00a0, 0x000e, - 0x6052, 0x6050, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, - 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0xb600, - 0x6020, 0xa084, 0x0080, 0x0138, 0x2001, 0xb60c, 0x200c, 0xc1bd, - 0x2102, 0x0804, 0x5c3b, 0x2001, 0xb60c, 0x200c, 0xc1bc, 0x2102, - 0x6028, 0xa084, 0xe1ff, 0x602a, 0x6027, 0x0200, 0x6803, 0x0090, - 0x20a9, 0x0384, 0x6024, 0xd0cc, 0x1508, 0x1d04, 0x5bea, 0x2091, - 0x6000, 0x1f04, 0x5bea, 0x2011, 0x0003, 0x080c, 0x80fc, 0x2011, - 0x0002, 0x080c, 0x8106, 0x080c, 0x7fe0, 0x2019, 0x0000, 0x080c, - 0x806b, 0x6803, 0x00a0, 0x2001, 0xb89f, 0x2003, 0x0001, 0x2001, - 0xb600, 0x2003, 0x0001, 0xa085, 0x0001, 0x0468, 0x86ff, 0x1120, - 0x080c, 0x1e63, 0x080c, 0x24e5, 0x60e3, 0x0000, 0x2001, 0xb88f, - 0x2004, 0x080c, 0x28a7, 0x60e2, 0x6803, 0x0080, 0x20a9, 0x0384, - 0x6027, 0x1e00, 0x2009, 0x1e00, 0xe000, 0x6024, 0xa10c, 0x0138, - 0x1d04, 0x5c20, 0x2091, 0x6000, 0x1f04, 0x5c20, 0x0820, 0x6028, - 0xa085, 0x1e00, 0x602a, 0x70a4, 0xa005, 0x1118, 0x6887, 0x0001, - 0x0008, 0x6886, 0xa006, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, - 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, - 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2071, 0xb600, 0x2069, 0x0140, - 0x6020, 0xa084, 0x00c0, 0x0120, 0x6884, 0xa005, 0x1904, 0x5c97, - 0x6803, 0x0088, 0x60e3, 0x0000, 0x6887, 0x0000, 0x2001, 0x0000, - 0x080c, 0x28a7, 0x2069, 0x0200, 0x6804, 0xa005, 0x1118, 0x6808, - 0xa005, 0x01c0, 0x6028, 0xa084, 0xfbff, 0x602a, 0x6027, 0x0400, - 0x2069, 0xb8c6, 0x7000, 0x206a, 0x708f, 0x0026, 0x7003, 0x0001, - 0x20a9, 0x0002, 0x1d04, 0x5c7a, 0x2091, 0x6000, 0x1f04, 0x5c7a, - 0x0804, 0x5cc8, 0x2069, 0x0140, 0x20a9, 0x0384, 0x6027, 0x1e00, - 0x2009, 0x1e00, 0xe000, 0x6024, 0xa10c, 0x0520, 0xa084, 0x1a00, - 0x1508, 0x1d04, 0x5c86, 0x2091, 0x6000, 0x1f04, 0x5c86, 0x2011, - 0x0003, 0x080c, 0x80fc, 0x2011, 0x0002, 0x080c, 0x8106, 0x080c, - 0x7fe0, 0x2019, 0x0000, 0x080c, 0x806b, 0x6803, 0x00a0, 0x2001, - 0xb89f, 0x2003, 0x0001, 0x2001, 0xb600, 0x2003, 0x0001, 0xa085, - 0x0001, 0x00b0, 0x080c, 0x24e5, 0x6803, 0x0080, 0x2069, 0x0140, - 0x60e3, 0x0000, 0x70a4, 0xa005, 0x1118, 0x6887, 0x0001, 0x0008, - 0x6886, 0x2001, 0xb88f, 0x2004, 0x080c, 0x28a7, 0x60e2, 0xa006, - 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, - 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, 0x2061, - 0x0100, 0x2071, 0xb600, 0x6020, 0xa084, 0x00c0, 0x01e0, 0x2011, - 0x0003, 0x080c, 0x80fc, 0x2011, 0x0002, 0x080c, 0x8106, 0x080c, - 0x7fe0, 0x2019, 0x0000, 0x080c, 0x806b, 0x2069, 0x0140, 0x6803, - 0x00a0, 0x2001, 0xb89f, 0x2003, 0x0001, 0x2001, 0xb600, 0x2003, - 0x0001, 0x0804, 0x5d6d, 0x2001, 0xb60c, 0x200c, 0xd1b4, 0x1160, - 0xc1b5, 0x2102, 0x080c, 0x59fc, 0x2069, 0x0140, 0x080c, 0x24e5, - 0x6803, 0x0080, 0x60e3, 0x0000, 0x2069, 0x0200, 0x6804, 0xa005, - 0x1118, 0x6808, 0xa005, 0x01c0, 0x6028, 0xa084, 0xfdff, 0x602a, - 0x6027, 0x0200, 0x2069, 0xb8c6, 0x7000, 0x206a, 0x708f, 0x0027, - 0x7003, 0x0001, 0x20a9, 0x0002, 0x1d04, 0x5d24, 0x2091, 0x6000, - 0x1f04, 0x5d24, 0x0804, 0x5d6d, 0x6027, 0x1e00, 0x2009, 0x1e00, - 0xe000, 0x6024, 0xa10c, 0x01c8, 0xa084, 0x1c00, 0x11b0, 0x1d04, - 0x5d2c, 0x0006, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x080c, 0x696b, - 0x00ee, 0x00de, 0x00ce, 0x001e, 0x000e, 0x00e6, 0x2071, 0xb8f4, - 0x7018, 0x00ee, 0xa005, 0x1d00, 0x0500, 0x0026, 0x2011, 0x5a14, - 0x080c, 0x6a0e, 0x2011, 0x5a07, 0x080c, 0x6ace, 0x002e, 0x2069, - 0x0140, 0x60e3, 0x0000, 0x70a4, 0xa005, 0x1118, 0x6887, 0x0001, - 0x0008, 0x6886, 0x2001, 0xb88f, 0x2004, 0x080c, 0x28a7, 0x60e2, - 0x2001, 0xb60c, 0x200c, 0xc1b4, 0x2102, 0x00ee, 0x00de, 0x00ce, - 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, - 0x0036, 0x0046, 0x00c6, 0x00e6, 0x2061, 0x0100, 0x2071, 0xb600, - 0x7130, 0xd184, 0x1180, 0x2011, 0xb653, 0x2214, 0xd2ec, 0x0138, - 0xc18d, 0x7132, 0x2011, 0xb653, 0x2214, 0xd2ac, 0x1120, 0x7030, - 0xd08c, 0x0904, 0x5dda, 0x7130, 0xc185, 0x7132, 0x2011, 0xb653, - 0x220c, 0xd1a4, 0x0530, 0x0016, 0x2019, 0x000e, 0x080c, 0xb121, - 0x0156, 0x20a9, 0x007f, 0x2009, 0x0000, 0xa186, 0x007e, 0x01a0, - 0xa186, 0x0080, 0x0188, 0x080c, 0x501b, 0x1170, 0x8127, 0xa006, - 0x0016, 0x2009, 0x000e, 0x080c, 0xb1a4, 0x2009, 0x0001, 0x2011, - 0x0100, 0x080c, 0x6b8c, 0x001e, 0x8108, 0x1f04, 0x5da5, 0x015e, - 0x001e, 0xd1ac, 0x1148, 0x0016, 0x2009, 0x0000, 0x2019, 0x0004, - 0x080c, 0x2ca4, 0x001e, 0x0070, 0x0156, 0x20a9, 0x007f, 0x2009, - 0x0000, 0x080c, 0x501b, 0x1110, 0x080c, 0x4c7e, 0x8108, 0x1f04, - 0x5dd1, 0x015e, 0x080c, 0x1e63, 0x2011, 0x0003, 0x080c, 0x80fc, - 0x2011, 0x0002, 0x080c, 0x8106, 0x080c, 0x7fe0, 0x0036, 0x2019, - 0x0000, 0x080c, 0x806b, 0x003e, 0x60e3, 0x0000, 0x2001, 0xb600, - 0x2003, 0x0001, 0x080c, 0x5a79, 0x00ee, 0x00ce, 0x004e, 0x003e, - 0x002e, 0x001e, 0x015e, 0x0005, 0x2071, 0xb6e2, 0x7003, 0x0000, - 0x7007, 0x0000, 0x700f, 0x0000, 0x702b, 0x0001, 0x704f, 0x0000, - 0x7053, 0x0001, 0x705f, 0x0020, 0x7063, 0x0040, 0x7083, 0x0000, - 0x708b, 0x0000, 0x708f, 0x0001, 0x70bf, 0x0000, 0x0005, 0x00e6, - 0x2071, 0xb6e2, 0x6848, 0xa005, 0x1130, 0x7028, 0xc085, 0x702a, - 0xa085, 0x0001, 0x0428, 0x6a50, 0x7236, 0x6b54, 0x733a, 0x6858, - 0x703e, 0x707a, 0x685c, 0x7042, 0x707e, 0x6848, 0x702e, 0x6840, - 0x7032, 0x2009, 0x000c, 0x200a, 0x8007, 0x8006, 0x8006, 0xa08c, - 0x003f, 0xa084, 0xffc0, 0xa210, 0x2100, 0xa319, 0x7272, 0x7376, - 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0x700f, 0x0000, 0xa006, - 0x00ee, 0x0005, 0x2b78, 0x2071, 0xb6e2, 0x7004, 0x0043, 0x700c, - 0x0002, 0x5e56, 0x5e4d, 0x5e4d, 0x5e4d, 0x5e4d, 0x0005, 0x5eac, - 0x5ead, 0x5edf, 0x5ee0, 0x5eaa, 0x5f2e, 0x5f33, 0x5f64, 0x5f65, - 0x5f80, 0x5f81, 0x5f82, 0x5f83, 0x5f84, 0x5f85, 0x603b, 0x6062, - 0x700c, 0x0002, 0x5e6f, 0x5eaa, 0x5eaa, 0x5eab, 0x5eab, 0x7830, - 0x7930, 0xa106, 0x0120, 0x7830, 0x7930, 0xa106, 0x1510, 0x7030, - 0xa10a, 0x01f8, 0x1210, 0x712c, 0xa10a, 0xa18a, 0x0002, 0x12d0, - 0x080c, 0x15e4, 0x01b0, 0x2d00, 0x705a, 0x7063, 0x0040, 0x2001, - 0x0003, 0x7057, 0x0000, 0x0126, 0x0006, 0x2091, 0x8000, 0x2009, - 0xb913, 0x2104, 0xc085, 0x200a, 0x000e, 0x700e, 0x012e, 0x080c, - 0x1664, 0x0005, 0x080c, 0x15e4, 0x0de0, 0x2d00, 0x705a, 0x080c, - 0x15e4, 0x1108, 0x0c10, 0x2d00, 0x7086, 0x7063, 0x0080, 0x2001, - 0x0004, 0x08f8, 0x0005, 0x0005, 0x0005, 0x700c, 0x0002, 0x5eb4, - 0x5eb7, 0x5ec5, 0x5ede, 0x5ede, 0x080c, 0x5e68, 0x0005, 0x0126, - 0x8001, 0x700e, 0x7058, 0x0006, 0x080c, 0x63b5, 0x0120, 0x2091, - 0x8000, 0x080c, 0x5e68, 0x00de, 0x0048, 0x0126, 0x8001, 0x700e, - 0x080c, 0x63b5, 0x7058, 0x2068, 0x7084, 0x705a, 0x6803, 0x0000, - 0x6807, 0x0000, 0x6834, 0xa084, 0x00ff, 0xa08a, 0x003a, 0x1218, - 0x00db, 0x012e, 0x0005, 0x012e, 0x080c, 0x5f86, 0x0005, 0x0005, - 0x0005, 0x00e6, 0x2071, 0xb6e2, 0x700c, 0x0002, 0x5eeb, 0x5eeb, - 0x5eeb, 0x5eed, 0x5ef0, 0x00ee, 0x0005, 0x700f, 0x0001, 0x0010, - 0x700f, 0x0002, 0x00ee, 0x0005, 0x5f86, 0x5f86, 0x5fa2, 0x5f86, - 0x611f, 0x5f86, 0x5f86, 0x5f86, 0x5f86, 0x5f86, 0x5fa2, 0x6161, - 0x61a4, 0x61ed, 0x6201, 0x5f86, 0x5f86, 0x5fbe, 0x5fa2, 0x5f86, - 0x5f86, 0x6018, 0x62ad, 0x62c8, 0x5f86, 0x5fbe, 0x5f86, 0x5f86, - 0x5f86, 0x5f86, 0x600e, 0x62c8, 0x5f86, 0x5f86, 0x5f86, 0x5f86, - 0x5f86, 0x5f86, 0x5f86, 0x5f86, 0x5f86, 0x5fd2, 0x5f86, 0x5f86, - 0x5f86, 0x5f86, 0x5f86, 0x5f86, 0x5f86, 0x5f86, 0x5f86, 0x63d3, - 0x5f86, 0x5f86, 0x5f86, 0x5f86, 0x5f86, 0x5fe7, 0x7020, 0x2068, - 0x080c, 0x1614, 0x0005, 0x700c, 0x0002, 0x5f3a, 0x5f3d, 0x5f4b, - 0x5f63, 0x5f63, 0x080c, 0x5e68, 0x0005, 0x0126, 0x8001, 0x700e, - 0x7058, 0x0006, 0x080c, 0x63b5, 0x0120, 0x2091, 0x8000, 0x080c, - 0x5e68, 0x00de, 0x0048, 0x0126, 0x8001, 0x700e, 0x080c, 0x63b5, - 0x7058, 0x2068, 0x7084, 0x705a, 0x6803, 0x0000, 0x6807, 0x0000, - 0x6834, 0xa084, 0x00ff, 0xa08a, 0x001a, 0x1218, 0x003b, 0x012e, - 0x0005, 0x012e, 0x0419, 0x0005, 0x0005, 0x0005, 0x5f86, 0x5fa2, - 0x610b, 0x5f86, 0x5fa2, 0x5f86, 0x5fa2, 0x5fa2, 0x5f86, 0x5fa2, - 0x610b, 0x5fa2, 0x5fa2, 0x5fa2, 0x5fa2, 0x5fa2, 0x5f86, 0x5fa2, - 0x610b, 0x5f86, 0x5f86, 0x5fa2, 0x5f86, 0x5f86, 0x5f86, 0x5fa2, - 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x7007, 0x0001, - 0x6838, 0xa084, 0x00ff, 0xc0d5, 0x683a, 0x0126, 0x2091, 0x8000, - 0x080c, 0x547a, 0x012e, 0x0005, 0x7007, 0x0001, 0x6838, 0xa084, - 0x00ff, 0xc0e5, 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, 0x547a, - 0x012e, 0x0005, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0ed, - 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, 0x547a, 0x012e, 0x0005, - 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0dd, 0x683a, 0x0126, - 0x2091, 0x8000, 0x080c, 0x547a, 0x012e, 0x0005, 0x6834, 0x8007, - 0xa084, 0x00ff, 0x0988, 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, - 0x60cb, 0x7007, 0x0006, 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, - 0x60cb, 0x0005, 0x6834, 0x8007, 0xa084, 0x00ff, 0x0904, 0x5f94, - 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, 0x60e8, 0x7007, 0x0006, - 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x60e8, 0x0005, 0x6834, - 0x8007, 0xa084, 0x00ff, 0xa086, 0x0001, 0x1904, 0x5f94, 0x7007, - 0x0001, 0x2009, 0xb631, 0x210c, 0x81ff, 0x11a8, 0x6838, 0xa084, - 0x00ff, 0x683a, 0x6853, 0x0000, 0x080c, 0x4df4, 0x1108, 0x0005, - 0x0126, 0x2091, 0x8000, 0x6837, 0x0139, 0x684a, 0x6952, 0x080c, - 0x547a, 0x012e, 0x0ca0, 0x2001, 0x0028, 0x0c90, 0x684c, 0xa084, - 0x00c0, 0xa086, 0x00c0, 0x1120, 0x7007, 0x0001, 0x0804, 0x62e0, - 0x2d00, 0x7016, 0x701a, 0x20a9, 0x0004, 0xa080, 0x0024, 0x2098, - 0x20a1, 0xb70d, 0x53a3, 0x6858, 0x7012, 0xa082, 0x0401, 0x1a04, - 0x5fb0, 0x6a84, 0xa28a, 0x0002, 0x1a04, 0x5fb0, 0x82ff, 0x1138, - 0x6888, 0x698c, 0xa105, 0x0118, 0x2001, 0x609e, 0x0018, 0xa280, - 0x6094, 0x2005, 0x70c6, 0x7010, 0xa015, 0x0904, 0x6080, 0x080c, - 0x15e4, 0x1118, 0x7007, 0x000f, 0x0005, 0x2d00, 0x7022, 0x70c4, - 0x2060, 0x2c05, 0x6836, 0xe004, 0xad00, 0x7096, 0xe008, 0xa20a, - 0x1210, 0xa00e, 0x2200, 0x7112, 0xe20c, 0x8003, 0x800b, 0xa296, - 0x0004, 0x0108, 0xa108, 0x719a, 0x810b, 0x719e, 0xae90, 0x0022, - 0x080c, 0x1648, 0x7090, 0xa08e, 0x0100, 0x0170, 0xa086, 0x0200, - 0x0118, 0x7007, 0x0010, 0x0005, 0x7020, 0x2068, 0x080c, 0x1614, - 0x7014, 0x2068, 0x0804, 0x5fb0, 0x7020, 0x2068, 0x7018, 0x6802, - 0x6807, 0x0000, 0x2d08, 0x2068, 0x6906, 0x711a, 0x0804, 0x603b, - 0x7014, 0x2068, 0x7007, 0x0001, 0x6884, 0xa005, 0x1128, 0x6888, - 0x698c, 0xa105, 0x0108, 0x00b1, 0x6834, 0xa084, 0x00ff, 0xa086, - 0x001e, 0x0904, 0x62e0, 0x04b8, 0x6096, 0x609a, 0x0002, 0x0011, - 0x0007, 0x0004, 0x000a, 0x000f, 0x0005, 0x0006, 0x000a, 0x0011, - 0x0005, 0x0004, 0x00f6, 0x00e6, 0x00c6, 0x0076, 0x0066, 0x6f88, - 0x6e8c, 0x6804, 0x2060, 0xacf0, 0x0021, 0xacf8, 0x0027, 0x2009, - 0x0005, 0x700c, 0x7816, 0x7008, 0x7812, 0x7004, 0x7806, 0x7000, - 0x7802, 0x7e0e, 0x7f0a, 0x8109, 0x0128, 0xaef2, 0x0004, 0xaffa, - 0x0006, 0x0c78, 0x6004, 0xa065, 0x1d30, 0x006e, 0x007e, 0x00ce, - 0x00ee, 0x00fe, 0x0005, 0x2009, 0xb631, 0x210c, 0x81ff, 0x1198, - 0x6838, 0xa084, 0x00ff, 0x683a, 0x080c, 0x4cd7, 0x1108, 0x0005, - 0x080c, 0x554d, 0x0126, 0x2091, 0x8000, 0x080c, 0x9f88, 0x080c, - 0x547a, 0x012e, 0x0ca0, 0x2001, 0x0028, 0x2009, 0x0000, 0x0c80, - 0x2009, 0xb631, 0x210c, 0x81ff, 0x11b0, 0x6858, 0xa005, 0x01c0, - 0x6838, 0xa084, 0x00ff, 0x683a, 0x6853, 0x0000, 0x080c, 0x4d98, - 0x1108, 0x0005, 0x0126, 0x2091, 0x8000, 0x684a, 0x6952, 0x080c, - 0x547a, 0x012e, 0x0cb0, 0x2001, 0x0028, 0x2009, 0x0000, 0x0c90, - 0x2001, 0x0000, 0x0c78, 0x7018, 0x6802, 0x2d08, 0x2068, 0x6906, - 0x711a, 0x7010, 0x8001, 0x7012, 0x0118, 0x7007, 0x0006, 0x0030, - 0x7014, 0x2068, 0x7007, 0x0001, 0x7048, 0x080f, 0x0005, 0x7007, - 0x0001, 0x6944, 0x810f, 0xa18c, 0x00ff, 0x6848, 0xa084, 0x00ff, - 0x20a9, 0x0001, 0xa096, 0x0001, 0x01b0, 0x2009, 0x0000, 0x20a9, - 0x00ff, 0xa096, 0x0002, 0x0178, 0xa005, 0x11f0, 0x6944, 0x810f, - 0xa18c, 0x00ff, 0x080c, 0x501b, 0x11b8, 0x0066, 0x6e50, 0x080c, - 0x511a, 0x006e, 0x0088, 0x0046, 0x2011, 0xb60c, 0x2224, 0xc484, - 0x2412, 0x004e, 0x00c6, 0x080c, 0x501b, 0x1110, 0x080c, 0x527b, - 0x8108, 0x1f04, 0x614b, 0x00ce, 0x684c, 0xd084, 0x1118, 0x080c, - 0x1614, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x547a, 0x012e, - 0x0005, 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, 0x2001, 0xb653, - 0x2004, 0xd0a4, 0x0580, 0x2061, 0xb975, 0x6100, 0xd184, 0x0178, - 0x6858, 0xa084, 0x00ff, 0x1550, 0x6000, 0xd084, 0x0520, 0x6004, - 0xa005, 0x1538, 0x6003, 0x0000, 0x600b, 0x0000, 0x00c8, 0x2011, - 0x0001, 0x6860, 0xa005, 0x1110, 0x2001, 0x001e, 0x8000, 0x6016, - 0x6858, 0xa084, 0x00ff, 0x0178, 0x6006, 0x6858, 0x8007, 0xa084, - 0x00ff, 0x0148, 0x600a, 0x6858, 0x8000, 0x1108, 0xc28d, 0x6202, - 0x012e, 0x0804, 0x63a4, 0x012e, 0x0804, 0x639e, 0x012e, 0x0804, - 0x6398, 0x012e, 0x0804, 0x639b, 0x0126, 0x2091, 0x8000, 0x7007, - 0x0001, 0x2001, 0xb653, 0x2004, 0xd0a4, 0x05e0, 0x2061, 0xb975, - 0x6000, 0xd084, 0x05b8, 0x6204, 0x6308, 0xd08c, 0x1530, 0x6c48, - 0xa484, 0x0003, 0x0170, 0x6958, 0xa18c, 0x00ff, 0x8001, 0x1120, - 0x2100, 0xa210, 0x0620, 0x0028, 0x8001, 0x1508, 0x2100, 0xa212, - 0x02f0, 0xa484, 0x000c, 0x0188, 0x6958, 0x810f, 0xa18c, 0x00ff, - 0xa082, 0x0004, 0x1120, 0x2100, 0xa318, 0x0288, 0x0030, 0xa082, - 0x0004, 0x1168, 0x2100, 0xa31a, 0x0250, 0x6860, 0xa005, 0x0110, - 0x8000, 0x6016, 0x6206, 0x630a, 0x012e, 0x0804, 0x63a4, 0x012e, - 0x0804, 0x63a1, 0x012e, 0x0804, 0x639e, 0x0126, 0x2091, 0x8000, - 0x7007, 0x0001, 0x2061, 0xb975, 0x6300, 0xd38c, 0x1120, 0x6308, - 0x8318, 0x0220, 0x630a, 0x012e, 0x0804, 0x63b2, 0x012e, 0x0804, - 0x63a1, 0x0126, 0x00c6, 0x2091, 0x8000, 0x7007, 0x0001, 0x684c, - 0xd0ac, 0x0148, 0x00c6, 0x2061, 0xb975, 0x6000, 0xa084, 0xfcff, - 0x6002, 0x00ce, 0x0448, 0x6858, 0xa005, 0x05d0, 0x685c, 0xa065, - 0x0598, 0x2001, 0xb631, 0x2004, 0xa005, 0x0118, 0x080c, 0x9ed9, - 0x0068, 0x6013, 0x0400, 0x6057, 0x0000, 0x694c, 0xd1a4, 0x0110, - 0x6950, 0x6156, 0x2009, 0x0041, 0x080c, 0x86d3, 0x6958, 0xa18c, - 0xff00, 0xa186, 0x2000, 0x1140, 0x0026, 0x2009, 0x0000, 0x2011, - 0xfdff, 0x080c, 0x6b8c, 0x002e, 0x684c, 0xd0c4, 0x0148, 0x2061, - 0xb975, 0x6000, 0xd08c, 0x1120, 0x6008, 0x8000, 0x0208, 0x600a, - 0x00ce, 0x012e, 0x0804, 0x63a4, 0x00ce, 0x012e, 0x0804, 0x639e, - 0x6954, 0xa186, 0x002e, 0x0d40, 0xa186, 0x002d, 0x0d28, 0xa186, - 0x0045, 0x0528, 0xa186, 0x002a, 0x1130, 0x2001, 0xb60c, 0x200c, - 0xc194, 0x2102, 0x08c8, 0xa186, 0x0020, 0x0170, 0xa186, 0x0029, - 0x1d18, 0x6944, 0xa18c, 0xff00, 0x810f, 0x080c, 0x501b, 0x1960, - 0x6000, 0xc0e4, 0x6002, 0x0840, 0x685c, 0xa065, 0x09a8, 0x6007, - 0x0024, 0x2001, 0xb8b6, 0x2004, 0x6016, 0x0804, 0x623c, 0x685c, - 0xa065, 0x0950, 0x00e6, 0x6860, 0xa075, 0x2001, 0xb631, 0x2004, - 0xa005, 0x0150, 0x080c, 0x9ed9, 0x8eff, 0x0118, 0x2e60, 0x080c, - 0x9ed9, 0x00ee, 0x0804, 0x623c, 0x6020, 0xc0dc, 0xc0d5, 0x6022, - 0x2e60, 0x6007, 0x003a, 0x6870, 0xa005, 0x0130, 0x6007, 0x003b, - 0x6874, 0x602a, 0x6878, 0x6012, 0x6003, 0x0001, 0x080c, 0x6cff, - 0x080c, 0x71e5, 0x00ee, 0x0804, 0x623c, 0x2061, 0xb975, 0x6000, - 0xd084, 0x0190, 0xd08c, 0x1904, 0x63b2, 0x0126, 0x2091, 0x8000, - 0x6204, 0x8210, 0x0220, 0x6206, 0x012e, 0x0804, 0x63b2, 0x012e, - 0x6853, 0x0016, 0x0804, 0x63ab, 0x6853, 0x0007, 0x0804, 0x63ab, - 0x6834, 0x8007, 0xa084, 0x00ff, 0x1118, 0x080c, 0x5f94, 0x0078, - 0x2030, 0x8001, 0x1120, 0x7007, 0x0001, 0x0051, 0x0040, 0x7007, - 0x0006, 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x62e0, 0x0005, - 0x00e6, 0x0126, 0x2091, 0x8000, 0xa03e, 0x2009, 0xb631, 0x210c, - 0x81ff, 0x1904, 0x635e, 0x2009, 0xb60c, 0x210c, 0xd194, 0x1904, - 0x6388, 0x6848, 0x2070, 0xae82, 0xbe00, 0x0a04, 0x6352, 0x2001, - 0xb617, 0x2004, 0xae02, 0x1a04, 0x6352, 0x711c, 0xa186, 0x0006, - 0x1904, 0x6341, 0x7018, 0xa005, 0x0904, 0x635e, 0x2004, 0xd0e4, - 0x1904, 0x6383, 0x2061, 0xb975, 0x6100, 0xa184, 0x0301, 0xa086, - 0x0001, 0x1550, 0x7020, 0xd0dc, 0x1904, 0x638b, 0x6853, 0x0000, - 0x6803, 0x0000, 0x2d08, 0x7010, 0xa005, 0x1158, 0x7112, 0x684c, - 0xd0f4, 0x1904, 0x638e, 0x2e60, 0x080c, 0x6ae8, 0x012e, 0x00ee, - 0x0005, 0x2068, 0x6800, 0xa005, 0x1de0, 0x6902, 0x2168, 0x684c, - 0xd0f4, 0x1904, 0x638e, 0x012e, 0x00ee, 0x0005, 0x012e, 0x00ee, - 0x6853, 0x0006, 0x0804, 0x63ab, 0xd184, 0x0dc0, 0xd1c4, 0x11a8, - 0x00b8, 0x6944, 0xa18c, 0xff00, 0x810f, 0x080c, 0x501b, 0x15d8, - 0x6000, 0xd0e4, 0x15c0, 0x711c, 0xa186, 0x0007, 0x1118, 0x6853, - 0x0002, 0x0498, 0x6853, 0x0008, 0x0480, 0x6853, 0x000e, 0x0468, - 0x6853, 0x0017, 0x0450, 0x6853, 0x0035, 0x0438, 0x2001, 0xb672, - 0x2004, 0xd0fc, 0x01e8, 0x6848, 0x2070, 0xae82, 0xbe00, 0x02c0, - 0x605c, 0xae02, 0x12a8, 0x711c, 0xa186, 0x0006, 0x1188, 0x7018, - 0xa005, 0x0170, 0x2004, 0xd0bc, 0x0158, 0x2039, 0x0001, 0x7000, - 0xa086, 0x0007, 0x1904, 0x62eb, 0x7003, 0x0002, 0x0804, 0x62eb, - 0x6853, 0x0028, 0x0010, 0x6853, 0x0029, 0x012e, 0x00ee, 0x0418, - 0x6853, 0x002a, 0x0cd0, 0x6853, 0x0045, 0x0cb8, 0x2e60, 0x2019, - 0x0002, 0x6017, 0x0014, 0x080c, 0xad9c, 0x012e, 0x00ee, 0x0005, - 0x2009, 0x003e, 0x0058, 0x2009, 0x0004, 0x0040, 0x2009, 0x0006, - 0x0028, 0x2009, 0x0016, 0x0010, 0x2009, 0x0001, 0x6854, 0xa084, - 0xff00, 0xa105, 0x6856, 0x0126, 0x2091, 0x8000, 0x080c, 0x547a, - 0x012e, 0x0005, 0x080c, 0x1614, 0x0005, 0x702c, 0x7130, 0x8108, - 0xa102, 0x0230, 0xa00e, 0x7034, 0x7072, 0x7038, 0x7076, 0x0058, - 0x7070, 0xa080, 0x0040, 0x7072, 0x1230, 0x7074, 0xa081, 0x0000, - 0x7076, 0xa085, 0x0001, 0x7932, 0x7132, 0x0005, 0x00d6, 0x080c, - 0x6adf, 0x00de, 0x0005, 0x00d6, 0x00c6, 0x0036, 0x0026, 0x0016, - 0x7007, 0x0001, 0x6a44, 0xa282, 0x0004, 0x1a04, 0x641e, 0xd284, - 0x0170, 0x6a4c, 0xa290, 0xb735, 0x2204, 0xa065, 0x6004, 0x05e0, - 0x8007, 0xa084, 0x00ff, 0xa084, 0x0006, 0x1108, 0x04a8, 0x2c10, - 0x080c, 0x864e, 0x1118, 0x080c, 0x9f92, 0x05a0, 0x621a, 0x6844, - 0x0002, 0x63fd, 0x6402, 0x6405, 0x640b, 0x2019, 0x0002, 0x080c, - 0xb121, 0x0060, 0x080c, 0xb0b8, 0x0048, 0x2019, 0x0002, 0x6950, - 0x080c, 0xb0d3, 0x0018, 0x6950, 0x080c, 0xb0b8, 0x080c, 0x86a4, - 0x6857, 0x0000, 0x0126, 0x2091, 0x8000, 0x080c, 0x547a, 0x012e, - 0x001e, 0x002e, 0x003e, 0x00ce, 0x00de, 0x0005, 0x6857, 0x0006, - 0x0c88, 0x6857, 0x0002, 0x0c70, 0x6857, 0x0005, 0x0c58, 0x6857, - 0x0004, 0x0c40, 0x6857, 0x0007, 0x0c28, 0x00d6, 0x2011, 0x0004, - 0x2204, 0xa085, 0x8002, 0x2012, 0x00de, 0x0005, 0x20e1, 0x0002, - 0x3d08, 0x20e1, 0x2000, 0x3d00, 0xa084, 0x7000, 0x0118, 0xa086, - 0x1000, 0x1570, 0x20e1, 0x0000, 0x3d00, 0xa094, 0xff00, 0x8217, - 0xa084, 0xf000, 0xa086, 0x3000, 0x1160, 0xa184, 0xff00, 0x8007, - 0xa086, 0x0008, 0x11e8, 0x080c, 0x2df4, 0x11d0, 0x080c, 0x6675, - 0x0098, 0x20e1, 0x0004, 0x3d60, 0xd1bc, 0x1108, 0x3e60, 0xac84, - 0x0007, 0x1170, 0xac82, 0xbe00, 0x0258, 0x685c, 0xac02, 0x1240, - 0x2009, 0x0047, 0x080c, 0x86d3, 0x7a1c, 0xd284, 0x1938, 0x0005, - 0xa016, 0x080c, 0x1863, 0x0cc0, 0x0cd8, 0x781c, 0xd08c, 0x0500, - 0x0156, 0x0136, 0x0146, 0x20e1, 0x3000, 0x3d20, 0x3e28, 0xa584, - 0x0076, 0x1538, 0xa484, 0x7000, 0xa086, 0x1000, 0x11a8, 0x080c, - 0x64f0, 0x01f8, 0x20e1, 0x3000, 0x7828, 0x7828, 0x080c, 0x650c, - 0x014e, 0x013e, 0x015e, 0x2009, 0xb8e9, 0x2104, 0xa005, 0x1108, - 0x0005, 0x080c, 0x71e5, 0x0ce0, 0xa484, 0x7000, 0x1548, 0x080c, - 0x64f0, 0x01d8, 0x7000, 0xa084, 0xff00, 0xa086, 0x8100, 0x0d10, - 0x00a0, 0xd5a4, 0x0178, 0x0056, 0x0046, 0x080c, 0x1e8a, 0x080c, - 0x24e5, 0x2001, 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x004e, - 0x005e, 0x0048, 0x04a9, 0x6887, 0x0000, 0x080c, 0xb49b, 0x20e1, - 0x3000, 0x7828, 0x7828, 0x00b9, 0x014e, 0x013e, 0x015e, 0x0880, - 0x0439, 0x1130, 0x7000, 0xa084, 0xff00, 0xa086, 0x8100, 0x1d68, - 0x080c, 0xb49b, 0x20e1, 0x3000, 0x7828, 0x7828, 0x0056, 0x080c, - 0x68e6, 0x005e, 0x0c40, 0x2001, 0xb60e, 0x2004, 0xd08c, 0x0178, - 0x2001, 0xb600, 0x2004, 0xa086, 0x0003, 0x1148, 0x0026, 0x0036, - 0x2011, 0x8048, 0x2518, 0x080c, 0x3f13, 0x003e, 0x002e, 0x0005, - 0xa484, 0x01ff, 0x6886, 0xa005, 0x0160, 0xa080, 0x001f, 0xa084, - 0x03f8, 0x80ac, 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5, - 0x0005, 0x20a9, 0x000c, 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, - 0x53a5, 0xa085, 0x0001, 0x0ca0, 0x7000, 0xa084, 0xff00, 0xa08c, - 0xf000, 0x8007, 0xa196, 0x0000, 0x1118, 0x0804, 0x677a, 0x0005, - 0xa196, 0x2000, 0x1148, 0x6900, 0xa18e, 0x0001, 0x1118, 0x080c, - 0x44d6, 0x0ca8, 0x0039, 0x0c98, 0xa196, 0x8000, 0x1d80, 0x080c, - 0x6826, 0x0c68, 0x00c6, 0x6a84, 0x82ff, 0x0904, 0x666f, 0x7110, - 0xa18c, 0xff00, 0x810f, 0xa196, 0x0001, 0x0120, 0xa196, 0x0023, - 0x1904, 0x666f, 0xa08e, 0x0023, 0x1570, 0x080c, 0x68c1, 0x0904, - 0x666f, 0x7124, 0x610a, 0x7030, 0xa08e, 0x0200, 0x1150, 0x7034, - 0xa005, 0x1904, 0x666f, 0x2009, 0x0015, 0x080c, 0x86d3, 0x0804, - 0x666f, 0xa08e, 0x0214, 0x0118, 0xa08e, 0x0210, 0x1130, 0x2009, - 0x0015, 0x080c, 0x86d3, 0x0804, 0x666f, 0xa08e, 0x0100, 0x1904, - 0x666f, 0x7034, 0xa005, 0x1904, 0x666f, 0x2009, 0x0016, 0x080c, - 0x86d3, 0x0804, 0x666f, 0xa08e, 0x0022, 0x1904, 0x666f, 0x7030, - 0xa08e, 0x0300, 0x1580, 0x68d4, 0xd0a4, 0x0528, 0xc0b5, 0x68d6, - 0x7100, 0xa18c, 0x00ff, 0x6972, 0x7004, 0x6876, 0x00f6, 0x2079, - 0x0100, 0x79e6, 0x78ea, 0x0006, 0xa084, 0x00ff, 0x0016, 0x2008, - 0x080c, 0x287c, 0x7932, 0x7936, 0x001e, 0x000e, 0x00fe, 0x080c, - 0x2852, 0x6952, 0x703c, 0x00e6, 0x2071, 0x0140, 0x7086, 0x2071, - 0xb600, 0x70a6, 0x00ee, 0x7034, 0xa005, 0x1904, 0x666f, 0x2009, - 0x0017, 0x0804, 0x6635, 0xa08e, 0x0400, 0x1158, 0x7034, 0xa005, - 0x1904, 0x666f, 0x68d4, 0xc0a5, 0x68d6, 0x2009, 0x0030, 0x0804, - 0x6635, 0xa08e, 0x0500, 0x1140, 0x7034, 0xa005, 0x1904, 0x666f, - 0x2009, 0x0018, 0x0804, 0x6635, 0xa08e, 0x2010, 0x1120, 0x2009, - 0x0019, 0x0804, 0x6635, 0xa08e, 0x2110, 0x1120, 0x2009, 0x001a, - 0x0804, 0x6635, 0xa08e, 0x5200, 0x1140, 0x7034, 0xa005, 0x1904, - 0x666f, 0x2009, 0x001b, 0x0804, 0x6635, 0xa08e, 0x5000, 0x1140, - 0x7034, 0xa005, 0x1904, 0x666f, 0x2009, 0x001c, 0x0804, 0x6635, - 0xa08e, 0x1300, 0x1120, 0x2009, 0x0034, 0x0804, 0x6635, 0xa08e, - 0x1200, 0x1140, 0x7034, 0xa005, 0x1904, 0x666f, 0x2009, 0x0024, - 0x0804, 0x6635, 0xa08c, 0xff00, 0xa18e, 0x2400, 0x1118, 0x2009, - 0x002d, 0x04d8, 0xa08c, 0xff00, 0xa18e, 0x5300, 0x1118, 0x2009, - 0x002a, 0x0498, 0xa08e, 0x0f00, 0x1118, 0x2009, 0x0020, 0x0468, - 0xa08e, 0x5300, 0x1108, 0x00d8, 0xa08e, 0x6104, 0x11c0, 0x2011, - 0xbc8d, 0x8208, 0x2204, 0xa082, 0x0004, 0x20a8, 0x95ac, 0x95ac, - 0x2011, 0x8015, 0x211c, 0x8108, 0x0046, 0x2124, 0x080c, 0x3f13, - 0x004e, 0x8108, 0x1f04, 0x6618, 0x2009, 0x0023, 0x0070, 0xa08e, - 0x6000, 0x1118, 0x2009, 0x003f, 0x0040, 0xa08e, 0x7800, 0x1118, - 0x2009, 0x0045, 0x0010, 0x2009, 0x001d, 0x0016, 0x2011, 0xbc83, - 0x2204, 0x8211, 0x220c, 0x080c, 0x2852, 0x1598, 0x080c, 0x4fbf, - 0x1580, 0x6612, 0x6516, 0x86ff, 0x01e8, 0x001e, 0x0016, 0xa186, - 0x0017, 0x1158, 0x6870, 0xa606, 0x11a8, 0x6874, 0xa506, 0xa084, - 0xff00, 0x1180, 0x6000, 0xc0f5, 0x6002, 0xa186, 0x0046, 0x1150, - 0x6870, 0xa606, 0x1138, 0x6874, 0xa506, 0xa084, 0xff00, 0x1110, - 0x001e, 0x0068, 0x00c6, 0x080c, 0x864e, 0x0168, 0x001e, 0x611a, - 0x601f, 0x0004, 0x7120, 0x610a, 0x001e, 0x080c, 0x86d3, 0x00ce, - 0x0005, 0x001e, 0x0ce0, 0x00ce, 0x0ce0, 0x00c6, 0x0046, 0x080c, - 0x66c9, 0x1904, 0x66c6, 0xa28e, 0x0033, 0x11e8, 0x080c, 0x68c1, - 0x0904, 0x66c6, 0x7124, 0x610a, 0x7030, 0xa08e, 0x0200, 0x1140, - 0x7034, 0xa005, 0x15d8, 0x2009, 0x0015, 0x080c, 0x86d3, 0x04b0, - 0xa08e, 0x0100, 0x1598, 0x7034, 0xa005, 0x1580, 0x2009, 0x0016, - 0x080c, 0x86d3, 0x0458, 0xa28e, 0x0032, 0x1540, 0x7030, 0xa08e, - 0x1400, 0x1520, 0x2009, 0x0038, 0x0016, 0x2011, 0xbc83, 0x2204, - 0x8211, 0x220c, 0x080c, 0x2852, 0x11c0, 0x080c, 0x4fbf, 0x11a8, - 0x6612, 0x6516, 0x00c6, 0x080c, 0x864e, 0x0170, 0x001e, 0x611a, - 0x080c, 0xa0e3, 0x601f, 0x0004, 0x7120, 0x610a, 0x001e, 0x080c, - 0x86d3, 0x080c, 0x71e5, 0x0010, 0x00ce, 0x001e, 0x004e, 0x00ce, - 0x0005, 0x00f6, 0x00d6, 0x0026, 0x0016, 0x0136, 0x0146, 0x0156, - 0x3c00, 0x0006, 0x2079, 0x0030, 0x2069, 0x0200, 0x080c, 0x1f49, - 0x1590, 0x080c, 0x1dee, 0x05e0, 0x04f1, 0x1130, 0x7908, 0xa18c, - 0x1fff, 0xa182, 0x0011, 0x1688, 0x20a9, 0x000c, 0x20e1, 0x0000, - 0x2ea0, 0x2099, 0x020a, 0x53a5, 0x20e1, 0x2000, 0x2001, 0x020a, - 0x2004, 0x7a0c, 0x7808, 0xa080, 0x0007, 0xa084, 0x1ff8, 0x0419, - 0x1120, 0xa08a, 0x0140, 0x1a0c, 0x151a, 0x80ac, 0x20e1, 0x6000, - 0x2099, 0x020a, 0x53a5, 0x20e1, 0x7000, 0x6828, 0x6828, 0x7803, - 0x0004, 0xa294, 0x0070, 0x000e, 0x20e0, 0x015e, 0x014e, 0x013e, - 0x001e, 0x002e, 0x00de, 0x00fe, 0x0005, 0xa016, 0x080c, 0x1863, - 0xa085, 0x0001, 0x0c80, 0x0006, 0x2001, 0x0111, 0x2004, 0xa084, - 0x0003, 0x000e, 0x0005, 0x0046, 0x00e6, 0x00d6, 0x2028, 0x2130, - 0xa696, 0x00ff, 0x1198, 0xa596, 0xfffd, 0x1120, 0x2009, 0x007f, - 0x0804, 0x6775, 0xa596, 0xfffe, 0x1118, 0x2009, 0x007e, 0x04e8, - 0xa596, 0xfffc, 0x1118, 0x2009, 0x0080, 0x04b8, 0x2011, 0x0000, - 0x2019, 0xb635, 0x231c, 0xd3ac, 0x0138, 0x2021, 0x0000, 0x20a9, - 0x00ff, 0x2071, 0xb735, 0x0030, 0x2021, 0x0081, 0x20a9, 0x007e, - 0x2071, 0xb7b6, 0x2e1c, 0x83ff, 0x1128, 0x82ff, 0x1198, 0x2410, - 0xc2fd, 0x0080, 0x2368, 0x6f10, 0x0006, 0x2100, 0xa706, 0x000e, - 0x6b14, 0x1120, 0xa346, 0x1110, 0x2408, 0x0078, 0x87ff, 0x1110, - 0x83ff, 0x0d58, 0x8420, 0x8e70, 0x1f04, 0x6752, 0x82ff, 0x1118, - 0xa085, 0x0001, 0x0018, 0xc2fc, 0x2208, 0xa006, 0x00de, 0x00ee, - 0x004e, 0x0005, 0xa084, 0x0007, 0x000a, 0x0005, 0x6786, 0x6786, - 0x6786, 0x68d3, 0x6786, 0x6787, 0x679c, 0x6811, 0x0005, 0x7110, - 0xd1bc, 0x0188, 0x7120, 0x2160, 0xac8c, 0x0007, 0x1160, 0xac8a, - 0xbe00, 0x0248, 0x685c, 0xac02, 0x1230, 0x7124, 0x610a, 0x2009, - 0x0046, 0x080c, 0x86d3, 0x0005, 0x00c6, 0xa484, 0x01ff, 0x0904, - 0x67ef, 0x7110, 0xd1bc, 0x1904, 0x67ef, 0x2011, 0xbc83, 0x2204, - 0x8211, 0x220c, 0x080c, 0x2852, 0x1904, 0x67ef, 0x080c, 0x4fbf, - 0x15f0, 0x6612, 0x6516, 0x6000, 0xd0ec, 0x15c8, 0x6204, 0xa294, - 0xff00, 0x8217, 0xa286, 0x0006, 0x0148, 0x6204, 0xa294, 0x00ff, - 0xa286, 0x0006, 0x11a0, 0xa295, 0x0600, 0x6206, 0x00c6, 0x080c, - 0x864e, 0x001e, 0x0530, 0x611a, 0x601f, 0x0006, 0x7120, 0x610a, - 0x7130, 0x6152, 0x2009, 0x0044, 0x080c, 0x86d3, 0x00c0, 0x00c6, - 0x080c, 0x864e, 0x001e, 0x0198, 0x611a, 0x601f, 0x0004, 0x7120, - 0x610a, 0xa286, 0x0004, 0x1118, 0x6007, 0x0005, 0x0010, 0x6007, - 0x0001, 0x6003, 0x0001, 0x080c, 0x6d45, 0x080c, 0x71e5, 0x00ce, - 0x0005, 0x2001, 0xb60d, 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049, - 0x080c, 0x3f13, 0x00c6, 0x080c, 0x9f92, 0x001e, 0x0d80, 0x611a, - 0x601f, 0x0006, 0x7120, 0x610a, 0x7130, 0x6152, 0x6013, 0x0300, - 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x6cff, 0x080c, 0x71e5, - 0x08f0, 0x7110, 0xd1bc, 0x0188, 0x7020, 0x2060, 0xac84, 0x0007, - 0x1160, 0xac82, 0xbe00, 0x0248, 0x685c, 0xac02, 0x1230, 0x7124, - 0x610a, 0x2009, 0x0045, 0x080c, 0x86d3, 0x0005, 0x0006, 0x080c, - 0x2df4, 0x000e, 0x1168, 0x7110, 0xa18c, 0xff00, 0x810f, 0xa18e, - 0x0000, 0x1130, 0xa084, 0x000f, 0xa08a, 0x0006, 0x1208, 0x000b, - 0x0005, 0x683f, 0x6840, 0x683f, 0x683f, 0x68a9, 0x68b5, 0x0005, - 0x7110, 0xd1bc, 0x0120, 0x702c, 0xd084, 0x0904, 0x68a8, 0x700c, - 0x7108, 0x080c, 0x2852, 0x1904, 0x68a8, 0x080c, 0x4fbf, 0x1904, - 0x68a8, 0x6612, 0x6516, 0x6204, 0x7110, 0xd1bc, 0x01f8, 0xa28c, - 0x00ff, 0xa186, 0x0004, 0x0118, 0xa186, 0x0006, 0x15c8, 0x00c6, - 0x080c, 0x68c1, 0x00ce, 0x0904, 0x68a8, 0x00c6, 0x080c, 0x864e, - 0x001e, 0x05f0, 0x611a, 0x080c, 0xa0e3, 0x601f, 0x0002, 0x7120, - 0x610a, 0x2009, 0x0088, 0x080c, 0x86d3, 0x0490, 0xa28c, 0x00ff, - 0xa186, 0x0006, 0x0160, 0xa186, 0x0004, 0x0148, 0xa294, 0xff00, - 0x8217, 0xa286, 0x0004, 0x0118, 0xa286, 0x0006, 0x1188, 0x00c6, - 0x080c, 0x864e, 0x001e, 0x01e0, 0x611a, 0x080c, 0xa0e3, 0x601f, - 0x0005, 0x7120, 0x610a, 0x2009, 0x0088, 0x080c, 0x86d3, 0x0080, - 0x00c6, 0x080c, 0x864e, 0x001e, 0x0158, 0x611a, 0x080c, 0xa0e3, - 0x601f, 0x0004, 0x7120, 0x610a, 0x2009, 0x0001, 0x080c, 0x86d3, - 0x0005, 0x7110, 0xd1bc, 0x0140, 0x00a1, 0x0130, 0x7124, 0x610a, - 0x2009, 0x0089, 0x080c, 0x86d3, 0x0005, 0x7110, 0xd1bc, 0x0140, - 0x0041, 0x0130, 0x7124, 0x610a, 0x2009, 0x008a, 0x080c, 0x86d3, - 0x0005, 0x7020, 0x2060, 0xac84, 0x0007, 0x1158, 0xac82, 0xbe00, - 0x0240, 0x2001, 0xb617, 0x2004, 0xac02, 0x1218, 0xa085, 0x0001, - 0x0005, 0xa006, 0x0ce8, 0x7110, 0xd1bc, 0x1178, 0x7024, 0x2060, - 0xac84, 0x0007, 0x1150, 0xac82, 0xbe00, 0x0238, 0x685c, 0xac02, - 0x1220, 0x2009, 0x0051, 0x080c, 0x86d3, 0x0005, 0x2031, 0x0105, - 0x0069, 0x0005, 0x2031, 0x0206, 0x0049, 0x0005, 0x2031, 0x0207, - 0x0029, 0x0005, 0x2031, 0x0213, 0x0009, 0x0005, 0x00c6, 0x00d6, - 0x00f6, 0x7000, 0xa084, 0xf000, 0xa086, 0xc000, 0x05b0, 0x080c, - 0x864e, 0x0598, 0x0066, 0x00c6, 0x0046, 0x2011, 0xbc83, 0x2204, - 0x8211, 0x220c, 0x080c, 0x2852, 0x1580, 0x080c, 0x4fbf, 0x1568, - 0x6612, 0x6516, 0x2c00, 0x004e, 0x00ce, 0x601a, 0x080c, 0xa0e3, - 0x080c, 0x15fd, 0x01f0, 0x2d00, 0x6056, 0x6803, 0x0000, 0x6837, - 0x0000, 0x6c3a, 0xadf8, 0x000f, 0x20a9, 0x000e, 0x2fa0, 0x2e98, - 0x53a3, 0x006e, 0x6612, 0x6007, 0x003e, 0x601f, 0x0001, 0x6003, - 0x0001, 0x080c, 0x6d45, 0x080c, 0x71e5, 0x00fe, 0x00de, 0x00ce, - 0x0005, 0x080c, 0x86a4, 0x006e, 0x0cc0, 0x004e, 0x00ce, 0x0cc8, - 0x2071, 0xb8f4, 0x7003, 0x0003, 0x700f, 0x0361, 0xa006, 0x701a, - 0x7076, 0x7012, 0x7017, 0xbe00, 0x7007, 0x0000, 0x7026, 0x702b, - 0x7e0a, 0x7032, 0x7037, 0x7e6a, 0x703b, 0xffff, 0x703f, 0xffff, - 0x7042, 0x7047, 0x4492, 0x704a, 0x705b, 0x6a9d, 0x2001, 0xb8a1, - 0x2003, 0x0003, 0x2001, 0xb8a3, 0x2003, 0x0100, 0x3a00, 0xa084, - 0x0005, 0x706e, 0x0005, 0x2071, 0xb8f4, 0x1d04, 0x69fd, 0x2091, - 0x6000, 0x700c, 0x8001, 0x700e, 0x1518, 0x700f, 0x0361, 0x7007, - 0x0001, 0x0126, 0x2091, 0x8000, 0x7040, 0xa00d, 0x0128, 0x8109, - 0x7142, 0x1110, 0x7044, 0x080f, 0x00c6, 0x2061, 0xb600, 0x6034, - 0x00ce, 0xd0cc, 0x0180, 0x3a00, 0xa084, 0x0005, 0x726c, 0xa216, - 0x0150, 0x706e, 0x2011, 0x8043, 0x2018, 0x080c, 0x3f13, 0x0018, - 0x0126, 0x2091, 0x8000, 0x7024, 0xa00d, 0x0188, 0x7020, 0x8001, - 0x7022, 0x1168, 0x7023, 0x0009, 0x8109, 0x7126, 0xa186, 0x03e8, - 0x1110, 0x7028, 0x080f, 0x81ff, 0x1110, 0x7028, 0x080f, 0x7030, - 0xa00d, 0x0180, 0x702c, 0x8001, 0x702e, 0x1160, 0x702f, 0x0009, - 0x8109, 0x7132, 0x0128, 0xa184, 0x007f, 0x090c, 0x7eaf, 0x0010, - 0x7034, 0x080f, 0x7038, 0xa005, 0x0118, 0x0310, 0x8001, 0x703a, - 0x703c, 0xa005, 0x0118, 0x0310, 0x8001, 0x703e, 0x704c, 0xa00d, - 0x0168, 0x7048, 0x8001, 0x704a, 0x1148, 0x704b, 0x0009, 0x8109, - 0x714e, 0x1120, 0x7150, 0x714e, 0x7058, 0x080f, 0x7018, 0xa00d, - 0x01d8, 0x0016, 0x7074, 0xa00d, 0x0158, 0x7070, 0x8001, 0x7072, - 0x1138, 0x7073, 0x0009, 0x8109, 0x7176, 0x1110, 0x7078, 0x080f, - 0x001e, 0x7008, 0x8001, 0x700a, 0x1138, 0x700b, 0x0009, 0x8109, - 0x711a, 0x1110, 0x701c, 0x080f, 0x012e, 0x7004, 0x0002, 0x6a23, - 0x6a24, 0x6a3c, 0x00e6, 0x2071, 0xb8f4, 0x7018, 0xa005, 0x1120, - 0x711a, 0x721e, 0x700b, 0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006, - 0x2071, 0xb8f4, 0x701c, 0xa206, 0x1110, 0x701a, 0x701e, 0x000e, - 0x00ee, 0x0005, 0x00e6, 0x2071, 0xb8f4, 0x6088, 0xa102, 0x0208, - 0x618a, 0x00ee, 0x0005, 0x0005, 0x7110, 0x080c, 0x501b, 0x1158, - 0x6088, 0x8001, 0x0240, 0x608a, 0x1130, 0x0126, 0x2091, 0x8000, - 0x080c, 0x71e5, 0x012e, 0x8108, 0xa182, 0x00ff, 0x0218, 0xa00e, - 0x7007, 0x0002, 0x7112, 0x0005, 0x7014, 0x2060, 0x0126, 0x2091, - 0x8000, 0x603c, 0xa005, 0x0128, 0x8001, 0x603e, 0x1110, 0x080c, - 0x9fd1, 0x6014, 0xa005, 0x0500, 0x8001, 0x6016, 0x11e8, 0x611c, - 0xa186, 0x0003, 0x0118, 0xa186, 0x0006, 0x11a0, 0x6010, 0x2068, - 0x6854, 0xa08a, 0x199a, 0x0270, 0xa082, 0x1999, 0x6856, 0xa08a, - 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, 0x800b, 0x810b, 0xa108, - 0x6116, 0x0010, 0x080c, 0x9aa1, 0x012e, 0xac88, 0x0018, 0x7116, - 0x2001, 0xee00, 0xa102, 0x0220, 0x7017, 0xbe00, 0x7007, 0x0000, - 0x0005, 0x00e6, 0x2071, 0xb8f4, 0x7027, 0x07d0, 0x7023, 0x0009, - 0x00ee, 0x0005, 0x2001, 0xb8fd, 0x2003, 0x0000, 0x0005, 0x00e6, - 0x2071, 0xb8f4, 0x7132, 0x702f, 0x0009, 0x00ee, 0x0005, 0x2011, - 0xb900, 0x2013, 0x0000, 0x0005, 0x00e6, 0x2071, 0xb8f4, 0x711a, - 0x721e, 0x700b, 0x0009, 0x00ee, 0x0005, 0x00c6, 0x0026, 0x7054, - 0x8000, 0x7056, 0x2061, 0xb8a1, 0x6008, 0xa086, 0x0000, 0x0158, - 0x7068, 0x6032, 0x7064, 0x602e, 0x7060, 0x602a, 0x705c, 0x6026, - 0x2c10, 0x080c, 0x1648, 0x002e, 0x00ce, 0x0005, 0x0006, 0x0016, - 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x080c, 0x696b, 0x00fe, 0x00ee, - 0x00de, 0x00ce, 0x001e, 0x000e, 0x0005, 0x00e6, 0x2071, 0xb8f4, - 0x7176, 0x727a, 0x7073, 0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006, - 0x2071, 0xb8f4, 0x7078, 0xa206, 0x1110, 0x7076, 0x707a, 0x000e, - 0x00ee, 0x0005, 0x00c6, 0x2061, 0xb975, 0x00ce, 0x0005, 0xa184, - 0x000f, 0x8003, 0x8003, 0x8003, 0xa080, 0xb975, 0x2060, 0x0005, - 0x6854, 0xa08a, 0x199a, 0x0210, 0x2001, 0x1999, 0xa005, 0x1150, - 0x00c6, 0x2061, 0xb975, 0x6014, 0x00ce, 0xa005, 0x1138, 0x2001, - 0x001e, 0x0020, 0xa08e, 0xffff, 0x1108, 0xa006, 0x8003, 0x800b, - 0x810b, 0xa108, 0x6116, 0x684c, 0xa08c, 0x00c0, 0xa18e, 0x00c0, - 0x05e8, 0xd0b4, 0x1138, 0xd0bc, 0x1550, 0x2009, 0x0006, 0x080c, - 0x6b63, 0x0005, 0xd0fc, 0x0138, 0xa084, 0x0003, 0x0120, 0xa086, - 0x0003, 0x1904, 0x6b5d, 0x6020, 0xd0d4, 0x0130, 0xc0d4, 0x6022, - 0x6860, 0x602a, 0x685c, 0x602e, 0x2009, 0xb674, 0x2104, 0xd084, - 0x0138, 0x87ff, 0x1120, 0x2009, 0x0042, 0x080c, 0x86d3, 0x0005, - 0x87ff, 0x1120, 0x2009, 0x0043, 0x080c, 0x86d3, 0x0005, 0xd0fc, - 0x0130, 0xa084, 0x0003, 0x0118, 0xa086, 0x0003, 0x11f0, 0x87ff, - 0x1120, 0x2009, 0x0042, 0x080c, 0x86d3, 0x0005, 0xd0fc, 0x0160, - 0xa084, 0x0003, 0xa08e, 0x0002, 0x0148, 0x87ff, 0x1120, 0x2009, - 0x0041, 0x080c, 0x86d3, 0x0005, 0x0061, 0x0ce8, 0x87ff, 0x1dd8, - 0x2009, 0x0043, 0x080c, 0x86d3, 0x0cb0, 0x2009, 0x0004, 0x0019, - 0x0005, 0x2009, 0x0001, 0x00d6, 0x6010, 0xa0ec, 0xf000, 0x0510, - 0x2068, 0x6952, 0x6800, 0x6012, 0xa186, 0x0001, 0x1188, 0x694c, - 0xa18c, 0x8100, 0xa18e, 0x8100, 0x1158, 0x00c6, 0x2061, 0xb975, - 0x6200, 0xd28c, 0x1120, 0x6204, 0x8210, 0x0208, 0x6206, 0x00ce, - 0x080c, 0x547a, 0x6010, 0xa06d, 0x0076, 0x2039, 0x0000, 0x190c, - 0x6ae8, 0x007e, 0x00de, 0x0005, 0x0156, 0x00c6, 0x2061, 0xb975, - 0x6000, 0x81ff, 0x0110, 0xa205, 0x0008, 0xa204, 0x6002, 0x00ce, - 0x015e, 0x0005, 0x6800, 0xd08c, 0x1138, 0x6808, 0xa005, 0x0120, - 0x8001, 0x680a, 0xa085, 0x0001, 0x0005, 0x20a9, 0x0010, 0xa006, - 0x8004, 0x8086, 0x818e, 0x1208, 0xa200, 0x1f04, 0x6ba9, 0x8086, - 0x818e, 0x0005, 0x0156, 0x20a9, 0x0010, 0xa005, 0x01b8, 0xa11a, - 0x12a8, 0x8213, 0x818d, 0x0228, 0xa11a, 0x1220, 0x1f04, 0x6bb9, - 0x0028, 0xa11a, 0x2308, 0x8210, 0x1f04, 0x6bb9, 0x0006, 0x3200, - 0xa084, 0xefff, 0x2080, 0x000e, 0x015e, 0x0005, 0x0006, 0x3200, - 0xa085, 0x1000, 0x0cb8, 0x0126, 0x2091, 0x2800, 0x2079, 0xb8e1, - 0x012e, 0x00d6, 0x2069, 0xb8e1, 0x6803, 0x0005, 0x2069, 0x0004, - 0x2d04, 0xa085, 0x8001, 0x206a, 0x00de, 0x0005, 0x00c6, 0x6027, - 0x0001, 0x7804, 0xa084, 0x0007, 0x0002, 0x6bf7, 0x6c18, 0x6c6b, - 0x6bfd, 0x6c18, 0x6bf7, 0x6bf5, 0x6bf5, 0x080c, 0x151a, 0x080c, - 0x6a82, 0x080c, 0x71e5, 0x00ce, 0x0005, 0x62c0, 0x82ff, 0x1110, - 0x00ce, 0x0005, 0x2011, 0x4b23, 0x080c, 0x6a0e, 0x7828, 0xa092, - 0x00c8, 0x1228, 0x8000, 0x782a, 0x080c, 0x4b65, 0x0c88, 0x080c, - 0x4b23, 0x7807, 0x0003, 0x7827, 0x0000, 0x782b, 0x0000, 0x0c40, - 0x080c, 0x6a82, 0x3c00, 0x0006, 0x2011, 0x0209, 0x20e1, 0x4000, - 0x2214, 0x000e, 0x20e0, 0x82ff, 0x0178, 0x62c0, 0x82ff, 0x1160, - 0x782b, 0x0000, 0x7824, 0xa065, 0x090c, 0x151a, 0x2009, 0x0013, - 0x080c, 0x86d3, 0x00ce, 0x0005, 0x3900, 0xa082, 0xba2d, 0x1210, - 0x080c, 0x83b9, 0x00c6, 0x7824, 0xa065, 0x090c, 0x151a, 0x7804, - 0xa086, 0x0004, 0x0904, 0x6cab, 0x7828, 0xa092, 0x2710, 0x1230, - 0x8000, 0x782a, 0x00ce, 0x080c, 0x7de6, 0x0c20, 0x6104, 0xa186, - 0x0003, 0x1188, 0x00e6, 0x2071, 0xb600, 0x70e0, 0x00ee, 0xd08c, - 0x0150, 0x00c6, 0x00e6, 0x2061, 0x0100, 0x2071, 0xb600, 0x080c, - 0x4b7b, 0x00ee, 0x00ce, 0x080c, 0xb500, 0x2009, 0x0014, 0x080c, - 0x86d3, 0x00ce, 0x0838, 0x2001, 0xb8fd, 0x2003, 0x0000, 0x62c0, - 0x82ff, 0x1160, 0x782b, 0x0000, 0x7824, 0xa065, 0x090c, 0x151a, - 0x2009, 0x0013, 0x080c, 0x872c, 0x00ce, 0x0005, 0x00c6, 0x00d6, - 0x3900, 0xa082, 0xba2d, 0x1210, 0x080c, 0x83b9, 0x7824, 0xa005, - 0x090c, 0x151a, 0x781c, 0xa06d, 0x090c, 0x151a, 0x6800, 0xc0dc, - 0x6802, 0x7924, 0x2160, 0x080c, 0x86a4, 0x693c, 0x81ff, 0x090c, - 0x151a, 0x8109, 0x693e, 0x6854, 0xa015, 0x0110, 0x7a1e, 0x0010, - 0x7918, 0x791e, 0x7807, 0x0000, 0x7827, 0x0000, 0x00de, 0x00ce, - 0x080c, 0x71e5, 0x0888, 0x6104, 0xa186, 0x0002, 0x0128, 0xa186, - 0x0004, 0x0110, 0x0804, 0x6c44, 0x7808, 0xac06, 0x0904, 0x6c44, - 0x080c, 0x7102, 0x080c, 0x6d45, 0x00ce, 0x080c, 0x71e5, 0x0804, - 0x6c32, 0x00c6, 0x6027, 0x0002, 0x62c8, 0x60c4, 0xa205, 0x1178, - 0x793c, 0xa1e5, 0x0000, 0x0130, 0x2009, 0x0049, 0x080c, 0x86d3, - 0x00ce, 0x0005, 0x2011, 0xb900, 0x2013, 0x0000, 0x0cc8, 0x3908, - 0xa192, 0xba2d, 0x1210, 0x080c, 0x83b9, 0x793c, 0x81ff, 0x0d90, - 0x7944, 0xa192, 0x7530, 0x12b8, 0x8108, 0x7946, 0x793c, 0xa188, - 0x0007, 0x210c, 0xa18e, 0x0006, 0x1138, 0x6014, 0xa084, 0x0184, - 0xa085, 0x0012, 0x6016, 0x08e0, 0x6014, 0xa084, 0x0184, 0xa085, - 0x0016, 0x6016, 0x08a8, 0x7848, 0xc085, 0x784a, 0x0888, 0x0006, - 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, - 0x2061, 0xb8e1, 0x6020, 0x8000, 0x6022, 0x6010, 0xa005, 0x0148, - 0xa080, 0x0003, 0x2102, 0x6112, 0x012e, 0x00ce, 0x001e, 0x000e, - 0x0005, 0x6116, 0x6112, 0x0cc0, 0x00d6, 0x2069, 0xb8e1, 0x6000, - 0xd0d4, 0x0168, 0x6820, 0x8000, 0x6822, 0xa086, 0x0001, 0x1110, - 0x2c00, 0x681e, 0x6804, 0xa084, 0x0007, 0x0804, 0x71eb, 0xc0d5, - 0x6002, 0x6818, 0xa005, 0x0158, 0x6056, 0x605b, 0x0000, 0x0006, - 0x2c00, 0x681a, 0x00de, 0x685a, 0x2069, 0xb8e1, 0x0c18, 0x6056, - 0x605a, 0x2c00, 0x681a, 0x681e, 0x08e8, 0x0006, 0x0016, 0x00c6, - 0x0126, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, 0x2061, 0xb8e1, - 0x6020, 0x8000, 0x6022, 0x6008, 0xa005, 0x0148, 0xa080, 0x0003, - 0x2102, 0x610a, 0x012e, 0x00ce, 0x001e, 0x000e, 0x0005, 0x610e, - 0x610a, 0x0cc0, 0x00c6, 0x600f, 0x0000, 0x2c08, 0x2061, 0xb8e1, - 0x6034, 0xa005, 0x0130, 0xa080, 0x0003, 0x2102, 0x6136, 0x00ce, - 0x0005, 0x613a, 0x6136, 0x0cd8, 0x00f6, 0x00e6, 0x00d6, 0x00c6, - 0x0076, 0x0066, 0x0056, 0x0036, 0x0026, 0x0016, 0x0006, 0x0126, - 0xa02e, 0x2071, 0xb8e1, 0x7638, 0x2660, 0x2678, 0x2091, 0x8000, - 0x8cff, 0x0904, 0x6ded, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, - 0x1904, 0x6de8, 0x87ff, 0x0120, 0x6050, 0xa106, 0x1904, 0x6de8, - 0x703c, 0xac06, 0x1190, 0x0036, 0x2019, 0x0001, 0x080c, 0x806b, - 0x7033, 0x0000, 0x703f, 0x0000, 0x7043, 0x0000, 0x7047, 0x0000, - 0x704b, 0x0000, 0x003e, 0x2029, 0x0001, 0x7038, 0xac36, 0x1110, - 0x660c, 0x763a, 0x7034, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, - 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, 0x660c, 0x0066, 0x2c00, - 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, - 0x9d16, 0x01c8, 0x6010, 0x2068, 0x601c, 0xa086, 0x0003, 0x1580, - 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x0016, 0x0036, 0x0076, - 0x080c, 0x9f88, 0x080c, 0xb43c, 0x080c, 0x547a, 0x007e, 0x003e, - 0x001e, 0x080c, 0x9ecd, 0x080c, 0x9ed9, 0x00ce, 0x0804, 0x6d88, - 0x2c78, 0x600c, 0x2060, 0x0804, 0x6d88, 0x85ff, 0x0120, 0x0036, - 0x080c, 0x72a2, 0x003e, 0x012e, 0x000e, 0x001e, 0x002e, 0x003e, - 0x005e, 0x006e, 0x007e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, - 0x601c, 0xa086, 0x0006, 0x1158, 0x0016, 0x0036, 0x0076, 0x080c, - 0xb43c, 0x080c, 0xb155, 0x007e, 0x003e, 0x001e, 0x08a0, 0x601c, - 0xa086, 0x000a, 0x0904, 0x6dd2, 0x0804, 0x6dd0, 0x0006, 0x0066, - 0x00c6, 0x00d6, 0x00f6, 0x2031, 0x0000, 0x0126, 0x2091, 0x8000, - 0x2079, 0xb8e1, 0x7838, 0xa065, 0x0568, 0x600c, 0x0006, 0x600f, - 0x0000, 0x783c, 0xac06, 0x1180, 0x0036, 0x2019, 0x0001, 0x080c, - 0x806b, 0x7833, 0x0000, 0x783f, 0x0000, 0x7843, 0x0000, 0x7847, - 0x0000, 0x784b, 0x0000, 0x003e, 0x080c, 0x9d16, 0x0178, 0x6010, - 0x2068, 0x601c, 0xa086, 0x0003, 0x11b0, 0x6837, 0x0103, 0x6b4a, - 0x6847, 0x0000, 0x080c, 0x547a, 0x080c, 0x9ecd, 0x080c, 0x9ed9, - 0x000e, 0x0888, 0x7e3a, 0x7e36, 0x012e, 0x00fe, 0x00de, 0x00ce, - 0x006e, 0x000e, 0x0005, 0x601c, 0xa086, 0x0006, 0x1118, 0x080c, - 0xb155, 0x0c60, 0x601c, 0xa086, 0x000a, 0x0d08, 0x08f0, 0x0016, - 0x0026, 0x0086, 0x2041, 0x0000, 0x0099, 0x080c, 0x6f35, 0x008e, - 0x002e, 0x001e, 0x0005, 0x00f6, 0x0126, 0x2079, 0xb8e1, 0x2091, - 0x8000, 0x080c, 0x6fc2, 0x080c, 0x7034, 0x012e, 0x00fe, 0x0005, - 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0016, 0x0006, 0x0126, - 0x2091, 0x8000, 0x2071, 0xb8e1, 0x7614, 0x2660, 0x2678, 0x8cff, - 0x0904, 0x6f0b, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x1904, - 0x6f06, 0x88ff, 0x0120, 0x6050, 0xa106, 0x1904, 0x6f06, 0x7024, - 0xac06, 0x1538, 0x2069, 0x0100, 0x68c0, 0xa005, 0x01f0, 0x080c, - 0x6a82, 0x080c, 0x7df3, 0x68c3, 0x0000, 0x080c, 0x82d4, 0x7027, - 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, - 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, - 0x0110, 0x6827, 0x0001, 0x003e, 0x0020, 0x6003, 0x0009, 0x630a, - 0x04e8, 0x7014, 0xac36, 0x1110, 0x660c, 0x7616, 0x7010, 0xac36, - 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7012, 0x0010, 0x7013, - 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, - 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x080c, 0x9d16, 0x01b8, - 0x601c, 0xa086, 0x0003, 0x1540, 0x6837, 0x0103, 0x6b4a, 0x6847, - 0x0000, 0x0016, 0x0036, 0x0086, 0x080c, 0x9f88, 0x080c, 0xb43c, - 0x080c, 0x547a, 0x008e, 0x003e, 0x001e, 0x080c, 0x9ecd, 0x080c, - 0x9ed9, 0x080c, 0x81a5, 0x00ce, 0x0804, 0x6e8f, 0x2c78, 0x600c, - 0x2060, 0x0804, 0x6e8f, 0x012e, 0x000e, 0x001e, 0x006e, 0x00ce, - 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601c, 0xa086, 0x0006, 0x1158, - 0x0016, 0x0036, 0x0086, 0x080c, 0xb43c, 0x080c, 0xb155, 0x008e, - 0x003e, 0x001e, 0x08e0, 0x601c, 0xa086, 0x0002, 0x1128, 0x6004, - 0xa086, 0x0085, 0x0908, 0x0898, 0x601c, 0xa086, 0x0005, 0x1978, - 0x6004, 0xa086, 0x0085, 0x0d20, 0x0850, 0x00c6, 0x0006, 0x0126, - 0x2091, 0x8000, 0xa280, 0xb735, 0x2004, 0xa065, 0x0904, 0x6fbe, - 0x00f6, 0x00e6, 0x00d6, 0x0066, 0x2071, 0xb8e1, 0x6654, 0x7018, - 0xac06, 0x1108, 0x761a, 0x701c, 0xac06, 0x1130, 0x86ff, 0x1118, - 0x7018, 0x701e, 0x0008, 0x761e, 0x6058, 0xa07d, 0x0108, 0x7e56, - 0xa6ed, 0x0000, 0x0110, 0x2f00, 0x685a, 0x6057, 0x0000, 0x605b, - 0x0000, 0x6000, 0xc0d4, 0xc0dc, 0x6002, 0x080c, 0x4f46, 0x0904, - 0x6fba, 0x7624, 0x86ff, 0x05e8, 0xa680, 0x0004, 0x2004, 0xad06, - 0x15c0, 0x00d6, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0548, 0x080c, - 0x6a82, 0x080c, 0x7df3, 0x68c3, 0x0000, 0x080c, 0x82d4, 0x7027, - 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, - 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, - 0x0110, 0x6827, 0x0001, 0x003e, 0x00de, 0x00c6, 0x603c, 0xa005, - 0x0110, 0x8001, 0x603e, 0x2660, 0x080c, 0x9ed9, 0x00ce, 0x0048, - 0x00de, 0x00c6, 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce, 0x0804, - 0x6f65, 0x8dff, 0x0158, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, - 0x080c, 0x9f88, 0x080c, 0xb43c, 0x080c, 0x547a, 0x080c, 0x81a5, - 0x0804, 0x6f65, 0x006e, 0x00de, 0x00ee, 0x00fe, 0x012e, 0x000e, - 0x00ce, 0x0005, 0x0006, 0x0066, 0x00c6, 0x00d6, 0x2031, 0x0000, - 0x7814, 0xa065, 0x0904, 0x7014, 0x600c, 0x0006, 0x600f, 0x0000, - 0x7824, 0xac06, 0x1540, 0x2069, 0x0100, 0x68c0, 0xa005, 0x01f0, - 0x080c, 0x6a82, 0x080c, 0x7df3, 0x68c3, 0x0000, 0x080c, 0x82d4, - 0x7827, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, - 0x0120, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, - 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x0028, 0x6003, 0x0009, - 0x630a, 0x2c30, 0x00b0, 0x6010, 0x2068, 0x080c, 0x9d16, 0x0168, - 0x601c, 0xa086, 0x0003, 0x11b8, 0x6837, 0x0103, 0x6b4a, 0x6847, - 0x0000, 0x080c, 0x547a, 0x080c, 0x9ecd, 0x080c, 0x9ed9, 0x080c, - 0x81a5, 0x000e, 0x0804, 0x6fc9, 0x7e16, 0x7e12, 0x00de, 0x00ce, - 0x006e, 0x000e, 0x0005, 0x601c, 0xa086, 0x0006, 0x1118, 0x080c, - 0xb155, 0x0c58, 0x601c, 0xa086, 0x0002, 0x1128, 0x6004, 0xa086, - 0x0085, 0x09d0, 0x0c10, 0x601c, 0xa086, 0x0005, 0x19f0, 0x6004, - 0xa086, 0x0085, 0x0d60, 0x08c8, 0x0006, 0x0066, 0x00c6, 0x00d6, - 0x7818, 0xa065, 0x0904, 0x709a, 0x6054, 0x0006, 0x6057, 0x0000, - 0x605b, 0x0000, 0x6000, 0xc0d4, 0xc0dc, 0x6002, 0x080c, 0x4f46, - 0x0904, 0x7097, 0x7e24, 0x86ff, 0x05e8, 0xa680, 0x0004, 0x2004, - 0xad06, 0x15c0, 0x00d6, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0548, - 0x080c, 0x6a82, 0x080c, 0x7df3, 0x68c3, 0x0000, 0x080c, 0x82d4, - 0x7827, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, - 0x0120, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, - 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x00de, 0x00c6, 0x603c, - 0xa005, 0x0110, 0x8001, 0x603e, 0x2660, 0x080c, 0x9ed9, 0x00ce, - 0x0048, 0x00de, 0x00c6, 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce, - 0x0804, 0x7046, 0x8dff, 0x0138, 0x6837, 0x0103, 0x6b4a, 0x6847, - 0x0000, 0x080c, 0x547a, 0x080c, 0x81a5, 0x0804, 0x7046, 0x000e, - 0x0804, 0x7039, 0x781e, 0x781a, 0x00de, 0x00ce, 0x006e, 0x000e, - 0x0005, 0x00e6, 0x00d6, 0x0066, 0x6000, 0xd0dc, 0x01a0, 0x604c, - 0xa06d, 0x0188, 0x6848, 0xa606, 0x1170, 0x2071, 0xb8e1, 0x7024, - 0xa035, 0x0148, 0xa080, 0x0004, 0x2004, 0xad06, 0x1120, 0x6000, - 0xc0dc, 0x6002, 0x0021, 0x006e, 0x00de, 0x00ee, 0x0005, 0x00f6, - 0x2079, 0x0100, 0x78c0, 0xa005, 0x1138, 0x00c6, 0x2660, 0x6003, - 0x0009, 0x630a, 0x00ce, 0x04a0, 0x080c, 0x7df3, 0x78c3, 0x0000, - 0x080c, 0x82d4, 0x7027, 0x0000, 0x0036, 0x2079, 0x0140, 0x7b04, - 0xa384, 0x1000, 0x0120, 0x7803, 0x0100, 0x7803, 0x0000, 0x2079, - 0x0100, 0x7824, 0xd084, 0x0110, 0x7827, 0x0001, 0x080c, 0x82d4, - 0x003e, 0x080c, 0x4f46, 0x00c6, 0x603c, 0xa005, 0x0110, 0x8001, - 0x603e, 0x2660, 0x080c, 0x86a4, 0x00ce, 0x6837, 0x0103, 0x6b4a, - 0x6847, 0x0000, 0x080c, 0x9f88, 0x080c, 0x547a, 0x080c, 0x81a5, - 0x00fe, 0x0005, 0x00e6, 0x00c6, 0x2071, 0xb8e1, 0x7004, 0xa084, - 0x0007, 0x0002, 0x7114, 0x7117, 0x712d, 0x7146, 0x7183, 0x7114, - 0x7112, 0x7112, 0x080c, 0x151a, 0x00ce, 0x00ee, 0x0005, 0x7024, - 0xa065, 0x0148, 0x7020, 0x8001, 0x7022, 0x600c, 0xa015, 0x0150, - 0x7216, 0x600f, 0x0000, 0x7007, 0x0000, 0x7027, 0x0000, 0x00ce, - 0x00ee, 0x0005, 0x7216, 0x7212, 0x0cb0, 0x6018, 0x2060, 0x080c, - 0x4f46, 0x6000, 0xc0dc, 0x6002, 0x7020, 0x8001, 0x7022, 0x0120, - 0x6054, 0xa015, 0x0140, 0x721e, 0x7007, 0x0000, 0x7027, 0x0000, - 0x00ce, 0x00ee, 0x0005, 0x7218, 0x721e, 0x0cb0, 0x7024, 0xa065, - 0x05b8, 0x700c, 0xac06, 0x1160, 0x080c, 0x81a5, 0x600c, 0xa015, - 0x0120, 0x720e, 0x600f, 0x0000, 0x0448, 0x720e, 0x720a, 0x0430, - 0x7014, 0xac06, 0x1160, 0x080c, 0x81a5, 0x600c, 0xa015, 0x0120, - 0x7216, 0x600f, 0x0000, 0x00d0, 0x7216, 0x7212, 0x00b8, 0x601c, - 0xa086, 0x0003, 0x1198, 0x6018, 0x2060, 0x080c, 0x4f46, 0x6000, - 0xc0dc, 0x6002, 0x080c, 0x81a5, 0x701c, 0xa065, 0x0138, 0x6054, - 0xa015, 0x0110, 0x721e, 0x0010, 0x7218, 0x721e, 0x7027, 0x0000, - 0x00ce, 0x00ee, 0x0005, 0x7024, 0xa065, 0x0140, 0x080c, 0x81a5, - 0x600c, 0xa015, 0x0150, 0x720e, 0x600f, 0x0000, 0x080c, 0x82d4, - 0x7027, 0x0000, 0x00ce, 0x00ee, 0x0005, 0x720e, 0x720a, 0x0cb0, - 0x00d6, 0x2069, 0xb8e1, 0x6830, 0xa084, 0x0003, 0x0002, 0x71a5, - 0x71a7, 0x71cb, 0x71a3, 0x080c, 0x151a, 0x00de, 0x0005, 0x00c6, - 0x6840, 0xa086, 0x0001, 0x01b8, 0x683c, 0xa065, 0x0130, 0x600c, - 0xa015, 0x0170, 0x6a3a, 0x600f, 0x0000, 0x6833, 0x0000, 0x683f, - 0x0000, 0x2011, 0xb900, 0x2013, 0x0000, 0x00ce, 0x00de, 0x0005, - 0x683a, 0x6836, 0x0c90, 0x6843, 0x0000, 0x6838, 0xa065, 0x0d68, - 0x6003, 0x0003, 0x0c50, 0x00c6, 0x6843, 0x0000, 0x6847, 0x0000, - 0x684b, 0x0000, 0x683c, 0xa065, 0x0168, 0x600c, 0xa015, 0x0130, - 0x6a3a, 0x600f, 0x0000, 0x683f, 0x0000, 0x0020, 0x683f, 0x0000, - 0x683a, 0x6836, 0x00ce, 0x00de, 0x0005, 0x00d6, 0x2069, 0xb8e1, - 0x6804, 0xa084, 0x0007, 0x0002, 0x71f6, 0x7292, 0x7292, 0x7292, - 0x7292, 0x7294, 0x71f4, 0x71f4, 0x080c, 0x151a, 0x6820, 0xa005, - 0x1110, 0x00de, 0x0005, 0x00c6, 0x680c, 0xa065, 0x0150, 0x6807, - 0x0004, 0x6826, 0x682b, 0x0000, 0x080c, 0x72e4, 0x00ce, 0x00de, - 0x0005, 0x6814, 0xa065, 0x0150, 0x6807, 0x0001, 0x6826, 0x682b, - 0x0000, 0x080c, 0x72e4, 0x00ce, 0x00de, 0x0005, 0x00e6, 0x0036, - 0x6a1c, 0xa2f5, 0x0000, 0x0904, 0x728e, 0x704c, 0xa00d, 0x0118, - 0x7088, 0xa005, 0x01a0, 0x7054, 0xa075, 0x0120, 0xa20e, 0x0904, - 0x728e, 0x0028, 0x6818, 0xa20e, 0x0904, 0x728e, 0x2070, 0x704c, - 0xa00d, 0x0d88, 0x7088, 0xa005, 0x1d70, 0x2e00, 0x681e, 0x733c, - 0x7038, 0xa302, 0x1e40, 0x080c, 0x867b, 0x0904, 0x728e, 0x8318, - 0x733e, 0x6112, 0x2e10, 0x621a, 0xa180, 0x0014, 0x2004, 0xa084, - 0x00ff, 0x605a, 0xa180, 0x0014, 0x2003, 0x0000, 0xa180, 0x0015, - 0x2004, 0xa08a, 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, 0x801b, - 0x831b, 0xa318, 0x6316, 0x003e, 0x00f6, 0x2c78, 0x71a0, 0x2001, - 0xb635, 0x2004, 0xd0ac, 0x1110, 0xd1bc, 0x0150, 0x7100, 0xd1f4, - 0x0120, 0x7114, 0xa18c, 0x00ff, 0x0040, 0x2009, 0x0000, 0x0028, - 0xa1e0, 0x2df9, 0x2c0d, 0xa18c, 0x00ff, 0x2061, 0x0100, 0x619a, - 0x080c, 0x7914, 0x7300, 0xc3dd, 0x7302, 0x6807, 0x0002, 0x2f18, - 0x6b26, 0x682b, 0x0000, 0x781f, 0x0003, 0x7803, 0x0001, 0x7807, - 0x0040, 0x00fe, 0x00ee, 0x00ce, 0x00de, 0x0005, 0x003e, 0x00ee, - 0x00ce, 0x0cd0, 0x00de, 0x0005, 0x00c6, 0x680c, 0xa065, 0x0138, - 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, 0x080c, 0x72e4, 0x00ce, - 0x00de, 0x0005, 0x00f6, 0x00d6, 0x2069, 0xb8e1, 0x6830, 0xa086, - 0x0000, 0x11d0, 0x2001, 0xb60c, 0x200c, 0xd1bc, 0x1560, 0x6838, - 0xa07d, 0x0190, 0x6833, 0x0001, 0x683e, 0x6847, 0x0000, 0x684b, - 0x0000, 0x0126, 0x00f6, 0x2091, 0x2400, 0x002e, 0x080c, 0x203d, - 0x1130, 0x012e, 0x080c, 0x7c5d, 0x00de, 0x00fe, 0x0005, 0x012e, - 0xe000, 0x6843, 0x0000, 0x7803, 0x0002, 0x780c, 0xa015, 0x0140, - 0x6a3a, 0x780f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, 0x0c60, - 0x683a, 0x6836, 0x0cc0, 0xc1bc, 0x2102, 0x0066, 0x2031, 0x0001, - 0x080c, 0x5bc3, 0x006e, 0x0858, 0x601c, 0xa084, 0x000f, 0x000b, - 0x0005, 0x72f2, 0x72f7, 0x77b5, 0x78d1, 0x72f7, 0x77b5, 0x78d1, - 0x72f2, 0x72f7, 0x080c, 0x7102, 0x080c, 0x71e5, 0x0005, 0x0156, - 0x0136, 0x0146, 0x00c6, 0x00f6, 0x6004, 0xa08a, 0x0080, 0x1a0c, - 0x151a, 0x6118, 0x2178, 0x79a0, 0x2011, 0xb635, 0x2214, 0xd2ac, - 0x1110, 0xd1bc, 0x0150, 0x7900, 0xd1f4, 0x0120, 0x7914, 0xa18c, - 0x00ff, 0x0040, 0x2009, 0x0000, 0x0028, 0xa1f8, 0x2df9, 0x2f0d, - 0xa18c, 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, 0xa08a, 0x0040, - 0x1a04, 0x736b, 0x0033, 0x00fe, 0x00ce, 0x014e, 0x013e, 0x015e, - 0x0005, 0x741a, 0x7465, 0x7492, 0x755f, 0x758d, 0x7595, 0x75bb, - 0x75cc, 0x75dd, 0x75e5, 0x75fb, 0x75e5, 0x765c, 0x75cc, 0x767d, - 0x7685, 0x75dd, 0x7685, 0x7696, 0x7369, 0x7369, 0x7369, 0x7369, - 0x7369, 0x7369, 0x7369, 0x7369, 0x7369, 0x7369, 0x7369, 0x7efe, - 0x7f23, 0x7f46, 0x7f69, 0x7f8a, 0x75bb, 0x7369, 0x75bb, 0x75e5, - 0x7369, 0x7492, 0x755f, 0x7369, 0x83d6, 0x75e5, 0x7369, 0x83f6, - 0x75e5, 0x7369, 0x75dd, 0x7413, 0x737e, 0x7369, 0x841b, 0x8490, - 0x8567, 0x7369, 0x8578, 0x75b6, 0x8594, 0x7369, 0x7f9f, 0x85ef, - 0x7369, 0x080c, 0x151a, 0x2100, 0x0033, 0x00fe, 0x00ce, 0x014e, - 0x013e, 0x015e, 0x0005, 0x737c, 0x737c, 0x737c, 0x73b2, 0x73d0, - 0x73e6, 0x737c, 0x737c, 0x737c, 0x080c, 0x151a, 0x00d6, 0x20a1, - 0x020b, 0x080c, 0x76b3, 0x7810, 0x2068, 0x20a3, 0x2414, 0x20a3, - 0x0018, 0x20a3, 0x0800, 0x683c, 0x20a2, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x6850, 0x20a2, 0x6854, - 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0018, 0x080c, - 0x7de0, 0x00de, 0x0005, 0x00d6, 0x7818, 0x2068, 0x68a0, 0x2069, - 0xb600, 0x6ad4, 0xd2ac, 0x1110, 0xd0bc, 0x0110, 0xa085, 0x0001, - 0x00de, 0x0005, 0x00d6, 0x20a1, 0x020b, 0x080c, 0x76b3, 0x20a3, - 0x0500, 0x20a3, 0x0000, 0x7810, 0xa0e8, 0x000f, 0x6808, 0x20a2, - 0x680c, 0x20a2, 0x6810, 0x20a2, 0x6814, 0x20a2, 0x6818, 0x20a2, - 0x681c, 0x20a2, 0x60c3, 0x0010, 0x080c, 0x7de0, 0x00de, 0x0005, - 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x76b3, 0x20a3, 0x7800, - 0x20a3, 0x0000, 0x7808, 0x8007, 0x20a2, 0x20a3, 0x0000, 0x60c3, - 0x0008, 0x080c, 0x7de0, 0x014e, 0x015e, 0x0005, 0x0156, 0x0146, - 0x20a1, 0x020b, 0x080c, 0x774f, 0x20a3, 0x0200, 0x20a3, 0x0000, - 0x20a3, 0xdf10, 0x20a3, 0x0034, 0x2099, 0xb605, 0x20a9, 0x0004, - 0x53a6, 0x2099, 0xb601, 0x20a9, 0x0004, 0x53a6, 0x2099, 0xb8c7, - 0x20a9, 0x001a, 0x3304, 0x8007, 0x20a2, 0x9398, 0x1f04, 0x7402, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x004c, 0x080c, 0x7de0, - 0x014e, 0x015e, 0x0005, 0x2001, 0xb615, 0x2004, 0x609a, 0x080c, - 0x7de0, 0x0005, 0x20a1, 0x020b, 0x080c, 0x76b3, 0x20a3, 0x5200, - 0x20a3, 0x0000, 0x00d6, 0x2069, 0xb652, 0x6804, 0xd084, 0x0150, - 0x6828, 0x20a3, 0x0000, 0x0016, 0x080c, 0x2866, 0x21a2, 0x001e, - 0x00de, 0x0028, 0x00de, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a9, - 0x0004, 0x2099, 0xb605, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xb601, - 0x53a6, 0x2001, 0xb635, 0x2004, 0xd0ac, 0x1138, 0x7818, 0xa080, - 0x0028, 0x2004, 0xa082, 0x007f, 0x0238, 0x2001, 0xb61c, 0x20a6, - 0x2001, 0xb61d, 0x20a6, 0x0040, 0x20a3, 0x0000, 0x2001, 0xb615, - 0x2004, 0xa084, 0x00ff, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x60c3, 0x001c, 0x080c, 0x7de0, 0x0005, 0x20a1, 0x020b, 0x080c, - 0x76b3, 0x20a3, 0x0500, 0x20a3, 0x0000, 0x2001, 0xb635, 0x2004, - 0xd0ac, 0x1138, 0x7818, 0xa080, 0x0028, 0x2004, 0xa082, 0x007f, - 0x0238, 0x2001, 0xb61c, 0x20a6, 0x2001, 0xb61d, 0x20a6, 0x0040, - 0x20a3, 0x0000, 0x2001, 0xb615, 0x2004, 0xa084, 0x00ff, 0x20a2, - 0x20a9, 0x0004, 0x2099, 0xb605, 0x53a6, 0x60c3, 0x0010, 0x080c, - 0x7de0, 0x0005, 0x20a1, 0x020b, 0x080c, 0x76b3, 0x00c6, 0x7818, - 0x2060, 0x2001, 0x0000, 0x080c, 0x5385, 0x00ce, 0x7818, 0xa080, - 0x0028, 0x2004, 0xa086, 0x007e, 0x1130, 0x20a3, 0x0400, 0x620c, - 0xc2b4, 0x620e, 0x0010, 0x20a3, 0x0300, 0x20a3, 0x0000, 0x7818, - 0xa080, 0x0028, 0x2004, 0xa086, 0x007e, 0x1904, 0x7521, 0x2001, - 0xb635, 0x2004, 0xd0a4, 0x01c8, 0x2099, 0xb88e, 0x33a6, 0x9398, - 0x20a3, 0x0000, 0x9398, 0x3304, 0xa084, 0x2000, 0x20a2, 0x9398, - 0x33a6, 0x9398, 0x20a3, 0x0000, 0x9398, 0x2001, 0x2710, 0x20a2, - 0x9398, 0x33a6, 0x9398, 0x33a6, 0x00d0, 0x2099, 0xb88e, 0x33a6, - 0x9398, 0x33a6, 0x9398, 0x3304, 0x080c, 0x5b41, 0x1118, 0xa084, - 0x37ff, 0x0010, 0xa084, 0x3fff, 0x20a2, 0x9398, 0x33a6, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a9, - 0x0004, 0x2099, 0xb605, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xb601, - 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, 0x74fb, 0x20a9, - 0x0008, 0x20a3, 0x0000, 0x1f04, 0x7501, 0x2099, 0xb896, 0x3304, - 0xc0dd, 0x20a2, 0x2001, 0xb672, 0x2004, 0xd0e4, 0x0158, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x9398, 0x9398, 0x9398, 0x33a6, 0x20a9, - 0x0004, 0x0010, 0x20a9, 0x0007, 0x20a3, 0x0000, 0x1f04, 0x751c, - 0x0468, 0x2001, 0xb635, 0x2004, 0xd0a4, 0x0140, 0x2001, 0xb88f, - 0x2004, 0x60e3, 0x0000, 0x080c, 0x28a7, 0x60e2, 0x2099, 0xb88e, - 0x20a9, 0x0008, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xb605, 0x53a6, - 0x20a9, 0x0004, 0x2099, 0xb601, 0x53a6, 0x20a9, 0x0008, 0x20a3, - 0x0000, 0x1f04, 0x753f, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, - 0x7545, 0x2099, 0xb896, 0x20a9, 0x0008, 0x53a6, 0x20a9, 0x0008, - 0x20a3, 0x0000, 0x1f04, 0x7550, 0x20a9, 0x000a, 0x20a3, 0x0000, - 0x1f04, 0x7556, 0x60c3, 0x0074, 0x080c, 0x7de0, 0x0005, 0x20a1, - 0x020b, 0x080c, 0x76b3, 0x20a3, 0x2010, 0x20a3, 0x0014, 0x20a3, - 0x0800, 0x20a3, 0x2000, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, - 0x20a2, 0x00f6, 0x2079, 0xb652, 0x7904, 0x00fe, 0xd1ac, 0x1110, - 0xa085, 0x0020, 0xd1a4, 0x0110, 0xa085, 0x0010, 0xa085, 0x0002, - 0x00d6, 0x0804, 0x763e, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x60c3, 0x0014, 0x080c, 0x7de0, 0x0005, 0x20a1, 0x020b, 0x080c, - 0x76b3, 0x20a3, 0x5000, 0x0804, 0x74ad, 0x20a1, 0x020b, 0x080c, - 0x76b3, 0x20a3, 0x2110, 0x20a3, 0x0014, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x60c3, 0x0014, 0x080c, 0x7de0, 0x0005, 0x20a1, 0x020b, - 0x080c, 0x7747, 0x0020, 0x20a1, 0x020b, 0x080c, 0x774f, 0x20a3, - 0x0200, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, - 0x0004, 0x080c, 0x7de0, 0x0005, 0x20a1, 0x020b, 0x080c, 0x774f, - 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003, 0x20a3, 0x2a00, - 0x60c3, 0x0008, 0x080c, 0x7de0, 0x0005, 0x20a1, 0x020b, 0x080c, - 0x774f, 0x20a3, 0x0200, 0x0804, 0x74ad, 0x20a1, 0x020b, 0x080c, - 0x774f, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x7828, 0xa005, 0x0110, - 0x20a2, 0x0010, 0x20a3, 0x0003, 0x7810, 0x20a2, 0x60c3, 0x0008, - 0x080c, 0x7de0, 0x0005, 0x00d6, 0x20a1, 0x020b, 0x080c, 0x774f, - 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3, 0x0800, 0x7818, 0x2068, - 0x6894, 0xa086, 0x0014, 0x1198, 0x699c, 0xa184, 0x0030, 0x0190, - 0x6998, 0xa184, 0xc000, 0x1140, 0xd1ec, 0x0118, 0x20a3, 0x2100, - 0x0058, 0x20a3, 0x0100, 0x0040, 0x20a3, 0x0400, 0x0028, 0x20a3, - 0x0700, 0x0010, 0x700f, 0x0800, 0xa006, 0x20a2, 0x20a2, 0x20a2, - 0x20a2, 0x20a2, 0x00f6, 0x2079, 0xb652, 0x7904, 0x00fe, 0xd1ac, - 0x1110, 0xa085, 0x0020, 0xd1a4, 0x0110, 0xa085, 0x0010, 0x2009, - 0xb674, 0x210c, 0xd184, 0x1110, 0xa085, 0x0002, 0x0026, 0x2009, - 0xb672, 0x210c, 0xd1e4, 0x0130, 0xc0c5, 0xa094, 0x0030, 0xa296, - 0x0010, 0x0140, 0xd1ec, 0x0130, 0xa094, 0x0030, 0xa296, 0x0010, - 0x0108, 0xc0bd, 0x002e, 0x20a2, 0x20a2, 0x20a2, 0x60c3, 0x0014, - 0x080c, 0x7de0, 0x00de, 0x0005, 0x20a1, 0x020b, 0x080c, 0x774f, - 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3, 0x0000, 0x20a3, 0x0100, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x60c3, 0x0014, 0x080c, 0x7de0, 0x0005, 0x20a1, 0x020b, 0x080c, - 0x774f, 0x20a3, 0x0200, 0x0804, 0x7420, 0x20a1, 0x020b, 0x080c, - 0x774f, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003, 0x20a3, - 0x2a00, 0x60c3, 0x0008, 0x080c, 0x7de0, 0x0005, 0x20e1, 0x9080, - 0x20e1, 0x4000, 0x20a1, 0x020b, 0x080c, 0x774f, 0x20a3, 0x0100, - 0x20a3, 0x0000, 0x20a3, 0x000b, 0x20a3, 0x0000, 0x60c3, 0x0008, - 0x080c, 0x7de0, 0x0005, 0x0026, 0x0036, 0x0046, 0x2019, 0x3200, - 0x2021, 0x0800, 0x0038, 0x0026, 0x0036, 0x0046, 0x2019, 0x2200, - 0x2021, 0x0100, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, - 0x0028, 0x2014, 0xa286, 0x007e, 0x11a0, 0xa385, 0x00ff, 0x20a2, - 0x20a3, 0xfffe, 0x20a3, 0x0000, 0x2011, 0xb615, 0x2214, 0x2001, - 0xb89e, 0x2004, 0xa005, 0x0118, 0x2011, 0xb61d, 0x2214, 0x22a2, - 0x04d0, 0xa286, 0x007f, 0x1138, 0x00d6, 0xa385, 0x00ff, 0x20a2, - 0x20a3, 0xfffd, 0x00c8, 0x2001, 0xb635, 0x2004, 0xd0ac, 0x1110, - 0xd2bc, 0x01c8, 0xa286, 0x0080, 0x00d6, 0x1130, 0xa385, 0x00ff, - 0x20a2, 0x20a3, 0xfffc, 0x0040, 0xa2e8, 0xb735, 0x2d6c, 0x6810, - 0xa305, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xb61c, 0x2da6, 0x8d68, - 0x2da6, 0x00de, 0x0080, 0x00d6, 0xa2e8, 0xb735, 0x2d6c, 0x6810, - 0xa305, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, - 0xb615, 0x2214, 0x22a2, 0xa485, 0x0029, 0x20a2, 0x004e, 0x003e, - 0x20a3, 0x0000, 0x080c, 0x7dcf, 0x22a2, 0x20a3, 0x0000, 0x2fa2, - 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, - 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a3, 0x02ff, 0x2011, - 0xfffc, 0x22a2, 0x00d6, 0x2069, 0xb61c, 0x2da6, 0x8d68, 0x2da6, - 0x00de, 0x20a3, 0x2029, 0x20a3, 0x0000, 0x08e0, 0x20a3, 0x0100, - 0x20a3, 0x0000, 0x20a3, 0xfc02, 0x20a3, 0x0000, 0x0005, 0x0026, - 0x0036, 0x0046, 0x2019, 0x3300, 0x2021, 0x0800, 0x0038, 0x0026, - 0x0036, 0x0046, 0x2019, 0x2300, 0x2021, 0x0100, 0x20e1, 0x9080, - 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xb635, - 0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e, 0x02d8, 0x00d6, 0xa0e8, - 0xb735, 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x6810, - 0xa005, 0x1140, 0x6814, 0xa005, 0x1128, 0x20a3, 0x00ff, 0x20a3, - 0xfffe, 0x0028, 0x2069, 0xb61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, - 0x0080, 0x00d6, 0xa0e8, 0xb735, 0x2d6c, 0x6810, 0xa305, 0x20a2, - 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xb615, 0x2214, - 0x22a2, 0xa485, 0x0098, 0x20a2, 0x20a3, 0x0000, 0x004e, 0x003e, - 0x080c, 0x7dcf, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, 0x080c, 0x7dcf, - 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x7810, 0x20a2, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, 0x00c6, 0x00f6, 0x6004, - 0xa08a, 0x0085, 0x0a0c, 0x151a, 0xa08a, 0x008c, 0x1a0c, 0x151a, - 0x6118, 0x2178, 0x79a0, 0x2011, 0xb635, 0x2214, 0xd2ac, 0x1110, - 0xd1bc, 0x0150, 0x7900, 0xd1f4, 0x0120, 0x7914, 0xa18c, 0x00ff, - 0x0040, 0x2009, 0x0000, 0x0028, 0xa1f8, 0x2df9, 0x2f0d, 0xa18c, - 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, 0xa082, 0x0085, 0x001b, - 0x00fe, 0x00ce, 0x0005, 0x77ec, 0x77f6, 0x7811, 0x77ea, 0x77ea, - 0x77ea, 0x77ec, 0x080c, 0x151a, 0x0146, 0x20a1, 0x020b, 0x04a1, - 0x60c3, 0x0000, 0x080c, 0x7de0, 0x014e, 0x0005, 0x0146, 0x20a1, - 0x020b, 0x080c, 0x785d, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, - 0x20a2, 0x7810, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0xffff, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x60c3, 0x000c, 0x080c, 0x7de0, 0x014e, - 0x0005, 0x0146, 0x20a1, 0x020b, 0x080c, 0x7897, 0x20a3, 0x0003, - 0x20a3, 0x0300, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0004, - 0x080c, 0x7de0, 0x014e, 0x0005, 0x0026, 0x20e1, 0x9080, 0x20e1, - 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xb635, 0x2214, - 0xd2ac, 0x1118, 0xa092, 0x007e, 0x0288, 0x00d6, 0xa0e8, 0xb735, - 0x2d6c, 0x6810, 0xa085, 0x8100, 0x20a2, 0x6814, 0x20a2, 0x2069, - 0xb61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, - 0xb735, 0x2d6c, 0x6810, 0xa085, 0x8100, 0x20a2, 0x6814, 0x20a2, - 0x00de, 0x20a3, 0x0000, 0x2011, 0xb615, 0x2214, 0x22a2, 0x20a3, - 0x0009, 0x20a3, 0x0000, 0x0804, 0x771a, 0x0026, 0x20e1, 0x9080, - 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xb635, - 0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e, 0x0288, 0x00d6, 0xa0e8, - 0xb735, 0x2d6c, 0x6810, 0xa085, 0x8400, 0x20a2, 0x6814, 0x20a2, - 0x2069, 0xb61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, - 0xa0e8, 0xb735, 0x2d6c, 0x6810, 0xa085, 0x8400, 0x20a2, 0x6814, - 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xb615, 0x2214, 0x22a2, - 0x2001, 0x0099, 0x20a2, 0x20a3, 0x0000, 0x0804, 0x77a6, 0x0026, - 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, - 0x2011, 0xb635, 0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e, 0x0288, - 0x00d6, 0xa0e8, 0xb735, 0x2d6c, 0x6810, 0xa085, 0x8500, 0x20a2, - 0x6814, 0x20a2, 0x2069, 0xb61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, - 0x0088, 0x00d6, 0xa0e8, 0xb735, 0x2d6c, 0x6810, 0xa085, 0x8500, - 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xb615, - 0x2214, 0x22a2, 0x2001, 0x0099, 0x20a2, 0x20a3, 0x0000, 0x0804, - 0x77a6, 0x00c6, 0x00f6, 0x2c78, 0x7804, 0xa08a, 0x0040, 0x0a0c, - 0x151a, 0xa08a, 0x0053, 0x1a0c, 0x151a, 0x7918, 0x2160, 0x61a0, - 0x2011, 0xb635, 0x2214, 0xd2ac, 0x1110, 0xd1bc, 0x0150, 0x6100, - 0xd1f4, 0x0120, 0x6114, 0xa18c, 0x00ff, 0x0040, 0x2009, 0x0000, - 0x0028, 0xa1e0, 0x2df9, 0x2c0d, 0xa18c, 0x00ff, 0x2061, 0x0100, - 0x619a, 0xa082, 0x0040, 0x001b, 0x00fe, 0x00ce, 0x0005, 0x7914, - 0x7a20, 0x79bd, 0x7bd2, 0x7912, 0x7912, 0x7912, 0x7912, 0x7912, - 0x7912, 0x7912, 0x815e, 0x816e, 0x817e, 0x818e, 0x7912, 0x85a5, - 0x7912, 0x814d, 0x080c, 0x151a, 0x00d6, 0x0156, 0x0146, 0x780b, - 0xffff, 0x20a1, 0x020b, 0x080c, 0x7974, 0x7910, 0x2168, 0x6948, - 0x7952, 0x21a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x694c, 0xa184, - 0x000f, 0x1118, 0x2001, 0x0005, 0x0040, 0xd184, 0x0118, 0x2001, - 0x0004, 0x0018, 0xa084, 0x0006, 0x8004, 0x0016, 0x2008, 0x7858, - 0xa084, 0x00ff, 0x8007, 0xa105, 0x001e, 0x20a2, 0xd1ac, 0x0118, - 0x20a3, 0x0002, 0x0048, 0xd1b4, 0x0118, 0x20a3, 0x0001, 0x0020, - 0x20a3, 0x0000, 0x2230, 0x0010, 0x6a80, 0x6e7c, 0x20a9, 0x0008, - 0x0136, 0xad88, 0x0017, 0x2198, 0x20a1, 0x021b, 0x53a6, 0x013e, - 0x20a1, 0x020b, 0x22a2, 0x26a2, 0x60c3, 0x0020, 0x20e1, 0x9080, - 0x6014, 0xa084, 0x0004, 0xa085, 0x0009, 0x6016, 0x2001, 0xb8fd, - 0x2003, 0x07d0, 0x2001, 0xb8fc, 0x2003, 0x0009, 0x080c, 0x17e7, - 0x014e, 0x015e, 0x00de, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, - 0x7a18, 0xa280, 0x0023, 0x2014, 0x8210, 0xa294, 0x00ff, 0x2202, - 0x8217, 0x7818, 0xa080, 0x0028, 0x2004, 0x2019, 0xb635, 0x231c, - 0xd3ac, 0x1110, 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0xb735, 0x2d6c, - 0x6810, 0xa085, 0x0600, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xb61c, - 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, 0xb735, - 0x2d6c, 0x6810, 0xa085, 0x0600, 0x20a2, 0x6814, 0x20a2, 0x00de, - 0x20a3, 0x0000, 0x2009, 0xb615, 0x210c, 0x21a2, 0x20a3, 0x0829, - 0x20a3, 0x0000, 0x22a2, 0x20a3, 0x0000, 0x2fa2, 0x20a3, 0xffff, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x0005, 0x00d6, 0x0156, 0x0136, - 0x0146, 0x20a1, 0x020b, 0x00c1, 0x7810, 0x2068, 0x6860, 0x20a2, - 0x685c, 0x20a2, 0x6880, 0x20a2, 0x687c, 0x20a2, 0xa006, 0x20a2, - 0x20a2, 0x20a2, 0x20a2, 0x60c3, 0x000c, 0x080c, 0x7de0, 0x014e, - 0x013e, 0x015e, 0x00de, 0x0005, 0x0026, 0x20e1, 0x9080, 0x20e1, - 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xb635, 0x2214, - 0xd2ac, 0x1110, 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0xb735, 0x2d6c, - 0x6810, 0xa085, 0x0500, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xb61c, - 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, 0xb735, - 0x2d6c, 0x6810, 0xa085, 0x0500, 0x20a2, 0x6814, 0x20a2, 0x00de, - 0x20a3, 0x0000, 0x2011, 0xb615, 0x2214, 0x22a2, 0x20a3, 0x0889, - 0x20a3, 0x0000, 0x080c, 0x7dcf, 0x22a2, 0x20a3, 0x0000, 0x7a08, - 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, - 0x00d6, 0x0156, 0x0136, 0x0146, 0x7810, 0xa0ec, 0xf000, 0x0168, - 0xa06d, 0x080c, 0x5373, 0x0148, 0x684c, 0xa084, 0x2020, 0xa086, - 0x2020, 0x1118, 0x7820, 0xc0cd, 0x7822, 0x20a1, 0x020b, 0x080c, - 0x7b88, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x7810, - 0xa084, 0xf000, 0x1130, 0x7810, 0xa084, 0x0700, 0x8007, 0x0043, - 0x0010, 0xa006, 0x002b, 0x014e, 0x013e, 0x015e, 0x00de, 0x0005, - 0x7a5a, 0x7aef, 0x7aff, 0x7b31, 0x7b44, 0x7b5f, 0x7b68, 0x7a58, - 0x080c, 0x151a, 0x0016, 0x0036, 0x694c, 0xa18c, 0x0003, 0x0118, - 0xa186, 0x0003, 0x1170, 0x6b78, 0x7820, 0xd0cc, 0x0108, 0xc3e5, - 0x23a2, 0x6868, 0x20a2, 0x6864, 0x20a2, 0x003e, 0x001e, 0x0804, - 0x7b3b, 0xa186, 0x0001, 0x190c, 0x151a, 0x6b78, 0x7820, 0xd0cc, - 0x0108, 0xc3e5, 0x23a2, 0x6868, 0x20a2, 0x6864, 0x20a2, 0x22a2, - 0x6874, 0x20a2, 0x22a2, 0x687c, 0x20a2, 0x2009, 0x0018, 0xa384, - 0x0300, 0x0904, 0x7ae9, 0xd3c4, 0x0110, 0x687c, 0xa108, 0xd3cc, - 0x0110, 0x6874, 0xa108, 0x0156, 0x20a9, 0x000d, 0xad80, 0x0020, - 0x201c, 0x831f, 0x23a2, 0x8000, 0x1f04, 0x7a98, 0x015e, 0x22a2, - 0x22a2, 0x22a2, 0xa184, 0x0003, 0x0904, 0x7ae9, 0x20a1, 0x020b, - 0x20e1, 0x9080, 0x20e1, 0x4000, 0x0006, 0x7818, 0xa080, 0x0028, - 0x2004, 0x2011, 0xb635, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188, - 0x00d6, 0xa0e8, 0xb735, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, - 0x6814, 0x20a2, 0x2069, 0xb61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, - 0x0088, 0x00d6, 0xa0e8, 0xb735, 0x2d6c, 0x6810, 0xa085, 0x0700, - 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xb615, - 0x2214, 0x22a2, 0x000e, 0x7b20, 0xd3cc, 0x0118, 0x20a3, 0x0889, - 0x0010, 0x20a3, 0x0898, 0x20a2, 0x080c, 0x7dcf, 0x22a2, 0x20a3, - 0x0000, 0x61c2, 0x003e, 0x001e, 0x080c, 0x7de0, 0x0005, 0x2011, - 0x0008, 0x2001, 0xb60d, 0x2004, 0xd0f4, 0x0110, 0x2011, 0x0028, - 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0xa016, 0x04d0, 0x2011, - 0x0302, 0x0016, 0x0036, 0x7828, 0x792c, 0xa11d, 0x0108, 0xc2dd, - 0x7b20, 0xd3cc, 0x0108, 0xc2e5, 0x22a2, 0x20a2, 0x21a2, 0x003e, - 0x001e, 0xa016, 0x22a2, 0x20a3, 0x0012, 0x22a2, 0x20a3, 0x0008, - 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x7000, 0x20a3, 0x0500, - 0x22a2, 0x20a3, 0x000a, 0x22a2, 0x22a2, 0x20a3, 0x2500, 0x22a2, - 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0032, 0x080c, 0x7de0, - 0x0005, 0x2011, 0x0028, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, - 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, - 0x0018, 0x080c, 0x7de0, 0x0005, 0x2011, 0x0100, 0x7820, 0xd0cc, - 0x0108, 0xc2e5, 0x22a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2, - 0x22a2, 0x20a3, 0x0008, 0x22a2, 0x7854, 0xa084, 0x00ff, 0x20a2, - 0x22a2, 0x22a2, 0x60c3, 0x0020, 0x080c, 0x7de0, 0x0005, 0x2011, - 0x0008, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0xa016, 0x0888, - 0x0036, 0x7b10, 0xa384, 0xff00, 0x7812, 0xa384, 0x00ff, 0x8001, - 0x1138, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0x003e, 0x0808, - 0x0046, 0x2021, 0x0800, 0x0006, 0x7820, 0xd0cc, 0x000e, 0x0108, - 0xc4e5, 0x24a2, 0x004e, 0x22a2, 0x20a2, 0x003e, 0x0804, 0x7b3b, - 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, - 0x2004, 0x2011, 0xb635, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188, - 0x00d6, 0xa0e8, 0xb735, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, - 0x6814, 0x20a2, 0x2069, 0xb61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, - 0x0088, 0x00d6, 0xa0e8, 0xb735, 0x2d6c, 0x6810, 0xa085, 0x0700, - 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xb615, - 0x2214, 0x22a2, 0x7820, 0xd0cc, 0x0118, 0x20a3, 0x0889, 0x0010, - 0x20a3, 0x0898, 0x20a3, 0x0000, 0x080c, 0x7dcf, 0x22a2, 0x20a3, - 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x002e, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x0016, 0x0036, - 0x7810, 0xa084, 0x0700, 0x8007, 0x003b, 0x003e, 0x001e, 0x014e, - 0x013e, 0x015e, 0x00de, 0x0005, 0x7bec, 0x7bec, 0x7bee, 0x7bec, - 0x7bec, 0x7bec, 0x7c10, 0x7bec, 0x080c, 0x151a, 0x7910, 0xa18c, - 0xf8ff, 0xa18d, 0x0600, 0x7912, 0x20a1, 0x020b, 0x2009, 0x0003, - 0x00f9, 0x00d6, 0x2069, 0xb652, 0x6804, 0xd0bc, 0x0130, 0x682c, - 0xa084, 0x00ff, 0x8007, 0x20a2, 0x0010, 0x20a3, 0x3f00, 0x00de, - 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0001, 0x080c, 0x7de0, 0x0005, - 0x20a1, 0x020b, 0x2009, 0x0003, 0x0019, 0x20a3, 0x7f00, 0x0c80, - 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, - 0x2004, 0x2011, 0xb635, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188, - 0x00d6, 0xa0e8, 0xb735, 0x2d6c, 0x6810, 0xa085, 0x0100, 0x20a2, - 0x6814, 0x20a2, 0x2069, 0xb61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, - 0x0088, 0x00d6, 0xa0e8, 0xb735, 0x2d6c, 0x6810, 0xa085, 0x0100, - 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xb615, - 0x2214, 0x22a2, 0x20a3, 0x0888, 0xa18d, 0x0008, 0x21a2, 0x080c, - 0x7dcf, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, 0x00e6, 0x00d6, 0x00c6, - 0x0056, 0x0046, 0x0036, 0x2061, 0x0100, 0x2071, 0xb600, 0x7154, - 0x7818, 0x2068, 0x68a0, 0x2028, 0x76d4, 0xd6ac, 0x1130, 0xd0bc, - 0x1120, 0x6910, 0x6a14, 0x7454, 0x0020, 0x6910, 0x6a14, 0x7370, - 0x7474, 0x781c, 0xa0be, 0x0006, 0x0904, 0x7d1a, 0xa0be, 0x000a, - 0x15e8, 0xa185, 0x0200, 0x6062, 0x6266, 0x636a, 0x646e, 0x6073, - 0x2029, 0x6077, 0x0000, 0x688c, 0x8000, 0xa084, 0x00ff, 0x688e, - 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6082, 0x7808, 0x6086, - 0x7810, 0x2070, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6, - 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, - 0x609f, 0x0000, 0x080c, 0x8640, 0x2009, 0x07d0, 0x60c4, 0xa084, - 0xfff0, 0xa005, 0x0110, 0x2009, 0x1b58, 0x080c, 0x6a87, 0x003e, - 0x004e, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x70d4, 0xd0ac, - 0x1110, 0xd5bc, 0x0138, 0xa185, 0x0100, 0x6062, 0x6266, 0x636a, - 0x646e, 0x0038, 0xa185, 0x0100, 0x6062, 0x6266, 0x606b, 0x0000, - 0x646e, 0x6073, 0x0809, 0x6077, 0x0008, 0x688c, 0x8000, 0xa084, - 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6082, - 0x7808, 0x6086, 0x7810, 0x2070, 0x7014, 0x608a, 0x7010, 0x608e, - 0x700c, 0x60c6, 0x7008, 0x60ca, 0x792c, 0xa108, 0x792e, 0x700c, - 0x7928, 0xa109, 0x792a, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, - 0x0000, 0xa582, 0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120, 0x6a14, - 0xa294, 0x00ff, 0x0010, 0x2011, 0x0000, 0x629e, 0x080c, 0x8640, - 0x2009, 0x07d0, 0x60c4, 0xa084, 0xfff0, 0xa005, 0x0110, 0x2009, - 0x1b58, 0x080c, 0x6a87, 0x003e, 0x004e, 0x005e, 0x00ce, 0x00de, - 0x00ee, 0x0005, 0x7810, 0x2070, 0x704c, 0xa084, 0x0003, 0xa086, - 0x0002, 0x0904, 0x7d70, 0x2001, 0xb635, 0x2004, 0xd0ac, 0x1110, - 0xd5bc, 0x0138, 0xa185, 0x0100, 0x6062, 0x6266, 0x636a, 0x646e, - 0x0038, 0xa185, 0x0100, 0x6062, 0x6266, 0x606b, 0x0000, 0x646e, - 0x6073, 0x0880, 0x6077, 0x0008, 0x688c, 0x8000, 0xa084, 0x00ff, - 0x688e, 0x8007, 0x607a, 0x7834, 0x607e, 0x2f00, 0x6086, 0x7808, - 0x6082, 0x7060, 0x608a, 0x705c, 0x608e, 0x7080, 0x60c6, 0x707c, - 0x60ca, 0x707c, 0x792c, 0xa108, 0x792e, 0x7080, 0x7928, 0xa109, - 0x792a, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, 0xa582, - 0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120, 0x6a14, 0xa294, 0x00ff, - 0x0010, 0x2011, 0x0000, 0x629e, 0x080c, 0x863d, 0x0804, 0x7d08, - 0x2001, 0xb635, 0x2004, 0xd0ac, 0x1110, 0xd5bc, 0x0138, 0xa185, - 0x0700, 0x6062, 0x6266, 0x636a, 0x646e, 0x0038, 0xa185, 0x0700, - 0x6062, 0x6266, 0x606b, 0x0000, 0x646e, 0x080c, 0x5373, 0x0180, - 0x00d6, 0x7810, 0xa06d, 0x684c, 0x00de, 0xa084, 0x2020, 0xa086, - 0x2020, 0x1130, 0x7820, 0xc0cd, 0x7822, 0x6073, 0x0889, 0x0010, - 0x6073, 0x0898, 0x6077, 0x0000, 0x688c, 0x8000, 0xa084, 0x00ff, - 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6086, 0x7808, - 0x6082, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6, 0x7008, - 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, 0xa582, - 0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120, 0x6a14, 0xa294, 0x00ff, - 0x0010, 0x2011, 0x0000, 0x629e, 0x7820, 0xd0cc, 0x0120, 0x080c, - 0x8640, 0x0804, 0x7d08, 0x080c, 0x863d, 0x0804, 0x7d08, 0x7a18, - 0xa280, 0x0023, 0x2014, 0x8210, 0xa294, 0x00ff, 0x2202, 0x8217, - 0x0005, 0x00d6, 0x2069, 0xb8e1, 0x6843, 0x0001, 0x00de, 0x0005, - 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x0019, 0x080c, - 0x6a79, 0x0005, 0x0006, 0x6014, 0xa084, 0x0004, 0xa085, 0x0009, - 0x6016, 0x000e, 0x0005, 0x0016, 0x00c6, 0x0006, 0x2061, 0x0100, - 0x61a4, 0x60a7, 0x95f5, 0x6014, 0xa084, 0x0004, 0xa085, 0x0008, - 0x6016, 0x000e, 0xe000, 0xe000, 0xe000, 0xe000, 0x61a6, 0x00ce, - 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0016, 0x0026, 0x2061, 0x0100, - 0x2069, 0x0140, 0x080c, 0x5b41, 0x1198, 0x2001, 0xb8fd, 0x2004, - 0xa005, 0x15b8, 0x0066, 0x2031, 0x0001, 0x080c, 0x5bc3, 0x006e, - 0x1118, 0x080c, 0x6a79, 0x0468, 0x00c6, 0x2061, 0xb8e1, 0x00d8, - 0x6904, 0xa194, 0x4000, 0x0550, 0x0831, 0x6803, 0x1000, 0x6803, - 0x0000, 0x00c6, 0x2061, 0xb8e1, 0x6128, 0xa192, 0x00c8, 0x1258, - 0x8108, 0x612a, 0x6124, 0x00ce, 0x81ff, 0x0198, 0x080c, 0x6a79, - 0x080c, 0x7dea, 0x0070, 0x6124, 0xa1e5, 0x0000, 0x0140, 0x080c, - 0xb500, 0x080c, 0x6a82, 0x2009, 0x0014, 0x080c, 0x86d3, 0x00ce, - 0x0000, 0x002e, 0x001e, 0x00de, 0x00ce, 0x0005, 0x2001, 0xb8fd, - 0x2004, 0xa005, 0x1db0, 0x00c6, 0x2061, 0xb8e1, 0x6128, 0xa192, - 0x0003, 0x1e08, 0x8108, 0x612a, 0x00ce, 0x080c, 0x6a79, 0x080c, - 0x4b7b, 0x0c38, 0x00c6, 0x00d6, 0x00e6, 0x0016, 0x0026, 0x080c, - 0x6a8f, 0x2071, 0xb8e1, 0x713c, 0x81ff, 0x0590, 0x2061, 0x0100, - 0x2069, 0x0140, 0x080c, 0x5b41, 0x11a8, 0x0036, 0x2019, 0x0002, - 0x080c, 0x806b, 0x003e, 0x713c, 0x2160, 0x080c, 0xb500, 0x2009, - 0x004a, 0x080c, 0x86d3, 0x0066, 0x2031, 0x0001, 0x080c, 0x5bc3, - 0x006e, 0x00b0, 0x6904, 0xa194, 0x4000, 0x01c0, 0x6803, 0x1000, - 0x6803, 0x0000, 0x0036, 0x2019, 0x0001, 0x080c, 0x806b, 0x003e, - 0x713c, 0x2160, 0x080c, 0xb500, 0x2009, 0x004a, 0x080c, 0x86d3, - 0x002e, 0x001e, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x0c58, 0x0026, - 0x00e6, 0x2071, 0xb8e1, 0x7048, 0xd084, 0x01c0, 0x713c, 0x81ff, - 0x01a8, 0x2071, 0x0100, 0xa188, 0x0007, 0x2114, 0xa28e, 0x0006, - 0x1138, 0x7014, 0xa084, 0x0184, 0xa085, 0x0012, 0x7016, 0x0030, - 0x7014, 0xa084, 0x0184, 0xa085, 0x0016, 0x7016, 0x00ee, 0x002e, - 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046, 0x0006, - 0x0126, 0x2091, 0x8000, 0x6018, 0x2068, 0x6ca0, 0x2071, 0xb8e1, - 0x7018, 0x2068, 0x8dff, 0x0188, 0x68a0, 0xa406, 0x0118, 0x6854, - 0x2068, 0x0cc0, 0x6010, 0x2060, 0x643c, 0x6540, 0x6648, 0x2d60, - 0x080c, 0x518c, 0x0110, 0xa085, 0x0001, 0x012e, 0x000e, 0x004e, - 0x005e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x20a1, 0x020b, - 0x080c, 0x76b3, 0x20a3, 0x1200, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x781c, 0xa086, 0x0004, 0x1110, 0x6098, 0x0018, 0x2001, 0xb615, - 0x2004, 0x20a2, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x20a9, 0x0010, - 0xa006, 0x20a2, 0x1f04, 0x7f19, 0x20a2, 0x20a2, 0x60c3, 0x002c, - 0x080c, 0x7de0, 0x0005, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, - 0x76b3, 0x20a3, 0x0f00, 0x20a3, 0x0000, 0x7808, 0xd09c, 0x1150, - 0x20a3, 0x0000, 0x20a2, 0x60c3, 0x0008, 0x080c, 0x7de0, 0x014e, - 0x015e, 0x0005, 0x00d6, 0x7818, 0xa06d, 0x090c, 0x151a, 0x6810, - 0xa084, 0x00ff, 0x20a2, 0x6814, 0x00de, 0x0c60, 0x0156, 0x0146, - 0x20a1, 0x020b, 0x080c, 0x774f, 0x20a3, 0x0200, 0x20a3, 0x0000, - 0x20a9, 0x0006, 0x2011, 0xb640, 0x2019, 0xb641, 0x23a6, 0x22a6, - 0xa398, 0x0002, 0xa290, 0x0002, 0x1f04, 0x7f56, 0x20a3, 0x0000, - 0x20a3, 0x0000, 0x60c3, 0x001c, 0x080c, 0x7de0, 0x014e, 0x015e, - 0x0005, 0x0156, 0x0146, 0x0016, 0x0026, 0x20a1, 0x020b, 0x080c, - 0x7728, 0x080c, 0x773e, 0x7810, 0xa080, 0x0000, 0x2004, 0xa080, - 0x0015, 0x2098, 0x7808, 0xa088, 0x0002, 0x21a8, 0x53a6, 0xa080, - 0x0004, 0x8003, 0x60c2, 0x080c, 0x7de0, 0x002e, 0x001e, 0x014e, - 0x015e, 0x0005, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x76b3, - 0x20a3, 0x6200, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2, - 0x60c3, 0x0008, 0x080c, 0x7de0, 0x014e, 0x015e, 0x0005, 0x0156, - 0x0146, 0x0016, 0x0026, 0x20a1, 0x020b, 0x080c, 0x76b3, 0x7810, - 0xa080, 0x0000, 0x2004, 0xa080, 0x0017, 0x2098, 0x7808, 0xa088, - 0x0002, 0x21a8, 0x53a6, 0x8003, 0x60c2, 0x080c, 0x7de0, 0x002e, - 0x001e, 0x014e, 0x015e, 0x0005, 0x00e6, 0x00c6, 0x0006, 0x0126, - 0x2091, 0x8000, 0x2071, 0xb8e1, 0x700c, 0x2060, 0x8cff, 0x0178, - 0x080c, 0x9f14, 0x1110, 0x080c, 0x8ca5, 0x600c, 0x0006, 0x080c, - 0xa0db, 0x080c, 0x86a4, 0x080c, 0x81a5, 0x00ce, 0x0c78, 0x700f, - 0x0000, 0x700b, 0x0000, 0x012e, 0x000e, 0x00ce, 0x00ee, 0x0005, - 0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0026, 0x0016, - 0x0006, 0x2091, 0x8000, 0x2069, 0x0100, 0x2079, 0x0140, 0x2071, - 0xb8e1, 0x7024, 0x2060, 0x8cff, 0x05a0, 0x080c, 0x7df3, 0x68c3, - 0x0000, 0x080c, 0x6a82, 0x2009, 0x0013, 0x080c, 0x86d3, 0x20a9, - 0x01f4, 0x6824, 0xd094, 0x0158, 0x6827, 0x0004, 0x7804, 0xa084, - 0x4000, 0x01a0, 0x7803, 0x1000, 0x7803, 0x0000, 0x0078, 0xd084, - 0x0118, 0x6827, 0x0001, 0x0010, 0x1f04, 0x8001, 0x7804, 0xa084, - 0x1000, 0x0120, 0x7803, 0x0100, 0x7803, 0x0000, 0x6824, 0x000e, - 0x001e, 0x002e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, - 0x0005, 0x2001, 0xb600, 0x2004, 0xa096, 0x0001, 0x0590, 0xa096, - 0x0004, 0x0578, 0x080c, 0x6a82, 0x6814, 0xa084, 0x0001, 0x0110, - 0x68a7, 0x95f5, 0x6817, 0x0008, 0x68c3, 0x0000, 0x2011, 0x4b23, - 0x080c, 0x6a0e, 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0158, 0x6827, - 0x0004, 0x7804, 0xa084, 0x4000, 0x01a0, 0x7803, 0x1000, 0x7803, - 0x0000, 0x0078, 0xd084, 0x0118, 0x6827, 0x0001, 0x0010, 0x1f04, - 0x8044, 0x7804, 0xa084, 0x1000, 0x0120, 0x7803, 0x0100, 0x7803, - 0x0000, 0x000e, 0x001e, 0x002e, 0x00ce, 0x00de, 0x00ee, 0x00fe, - 0x015e, 0x012e, 0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6, - 0x00c6, 0x0026, 0x0016, 0x0006, 0x2091, 0x8000, 0x2069, 0x0100, - 0x2079, 0x0140, 0x2071, 0xb8e1, 0x703c, 0x2060, 0x8cff, 0x0904, - 0x80f2, 0xa386, 0x0002, 0x1128, 0x6814, 0xa084, 0x0002, 0x0904, - 0x80f2, 0x68af, 0x95f5, 0x6817, 0x0010, 0x2009, 0x00fa, 0x8109, - 0x1df0, 0x68c7, 0x0000, 0x68cb, 0x0008, 0x080c, 0x6a8f, 0x080c, - 0x222f, 0x0046, 0x2009, 0x017f, 0x200b, 0x00a5, 0x2021, 0x0169, - 0x2404, 0xa084, 0x000f, 0xa086, 0x0004, 0x1500, 0x68af, 0x95f5, - 0x68c7, 0x0000, 0x68cb, 0x0008, 0x00e6, 0x00f6, 0x2079, 0x0020, - 0x2071, 0xb94b, 0x6814, 0xa084, 0x0184, 0xa085, 0x0012, 0x6816, - 0x7803, 0x0008, 0x7003, 0x0000, 0x00fe, 0x00ee, 0xa386, 0x0002, - 0x1128, 0x7884, 0xa005, 0x1110, 0x7887, 0x0001, 0x2001, 0xb8b1, - 0x2004, 0x200a, 0x004e, 0xa39d, 0x0000, 0x1120, 0x2009, 0x0049, - 0x080c, 0x86d3, 0x20a9, 0x03e8, 0x6824, 0xd094, 0x0158, 0x6827, - 0x0004, 0x7804, 0xa084, 0x4000, 0x01a0, 0x7803, 0x1000, 0x7803, - 0x0000, 0x0078, 0xd08c, 0x0118, 0x6827, 0x0002, 0x0010, 0x1f04, - 0x80d4, 0x7804, 0xa084, 0x1000, 0x0120, 0x7803, 0x0100, 0x7803, - 0x0000, 0x6824, 0x000e, 0x001e, 0x002e, 0x00ce, 0x00de, 0x00ee, - 0x00fe, 0x015e, 0x012e, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, - 0x2069, 0xb8e1, 0x6a06, 0x012e, 0x00de, 0x0005, 0x00d6, 0x0126, - 0x2091, 0x8000, 0x2069, 0xb8e1, 0x6a32, 0x012e, 0x00de, 0x0005, - 0x00f6, 0x00e6, 0x00c6, 0x0066, 0x0006, 0x0126, 0x2071, 0xb8e1, - 0x7614, 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, 0x0538, 0x601c, - 0xa206, 0x1500, 0x7014, 0xac36, 0x1110, 0x660c, 0x7616, 0x7010, - 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7012, 0x0010, - 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, - 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, 0x9ed9, 0x080c, 0x81a5, - 0x00ce, 0x08d8, 0x2c78, 0x600c, 0x2060, 0x08b8, 0x012e, 0x000e, - 0x006e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x0156, 0x0146, 0x20a1, - 0x020b, 0x080c, 0x7974, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2, - 0x20a2, 0x20a2, 0x20a3, 0x1000, 0x0804, 0x819d, 0x0156, 0x0146, - 0x20a1, 0x020b, 0x080c, 0x7974, 0x7810, 0x20a2, 0xa006, 0x20a2, - 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x4000, 0x0478, 0x0156, 0x0146, - 0x20a1, 0x020b, 0x080c, 0x7974, 0x7810, 0x20a2, 0xa006, 0x20a2, - 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x2000, 0x00f8, 0x0156, 0x0146, - 0x20a1, 0x020b, 0x080c, 0x7974, 0x7810, 0x20a2, 0xa006, 0x20a2, - 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0400, 0x0078, 0x0156, 0x0146, - 0x20a1, 0x020b, 0x080c, 0x7974, 0x7810, 0x20a2, 0xa006, 0x20a2, - 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0200, 0x0089, 0x60c3, 0x0020, - 0x080c, 0x7de0, 0x014e, 0x015e, 0x0005, 0x00e6, 0x2071, 0xb8e1, - 0x7020, 0xa005, 0x0110, 0x8001, 0x7022, 0x00ee, 0x0005, 0x20a9, - 0x0008, 0x20a2, 0x1f04, 0x81b1, 0x20a2, 0x20a2, 0x0005, 0x00f6, - 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066, 0x0006, 0x0126, 0x2091, - 0x8000, 0x2071, 0xb8e1, 0x7614, 0x2660, 0x2678, 0x2039, 0x0001, - 0x87ff, 0x0904, 0x824d, 0x8cff, 0x0904, 0x824d, 0x601c, 0xa086, - 0x0006, 0x1904, 0x8248, 0x88ff, 0x0138, 0x2800, 0xac06, 0x1904, - 0x8248, 0x2039, 0x0000, 0x0050, 0x6018, 0xa206, 0x1904, 0x8248, - 0x85ff, 0x0120, 0x6050, 0xa106, 0x1904, 0x8248, 0x7024, 0xac06, - 0x1598, 0x2069, 0x0100, 0x68c0, 0xa005, 0x1160, 0x6824, 0xd084, - 0x0148, 0x6827, 0x0001, 0x080c, 0x6a82, 0x080c, 0x82d4, 0x7027, - 0x0000, 0x0410, 0x080c, 0x6a82, 0x6820, 0xd0b4, 0x0110, 0x68a7, - 0x95f5, 0x6817, 0x0008, 0x68c3, 0x0000, 0x080c, 0x82d4, 0x7027, - 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, - 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, - 0x0110, 0x6827, 0x0001, 0x003e, 0x7014, 0xac36, 0x1110, 0x660c, - 0x7616, 0x7010, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, - 0x7012, 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, - 0x0110, 0x7e0e, 0x0008, 0x2678, 0x89ff, 0x1158, 0x600f, 0x0000, - 0x6010, 0x2068, 0x080c, 0x9d16, 0x0110, 0x080c, 0xb155, 0x080c, - 0x9ed9, 0x080c, 0x81a5, 0x88ff, 0x1190, 0x00ce, 0x0804, 0x81c8, - 0x2c78, 0x600c, 0x2060, 0x0804, 0x81c8, 0xa006, 0x012e, 0x000e, - 0x006e, 0x007e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x6017, - 0x0000, 0x00ce, 0xa8c5, 0x0001, 0x0c88, 0x00f6, 0x00e6, 0x00d6, - 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, - 0xb8e1, 0x7638, 0x2660, 0x2678, 0x8cff, 0x0904, 0x82c4, 0x601c, - 0xa086, 0x0006, 0x1904, 0x82bf, 0x87ff, 0x0128, 0x2700, 0xac06, - 0x1904, 0x82bf, 0x0048, 0x6018, 0xa206, 0x1904, 0x82bf, 0x85ff, - 0x0118, 0x6050, 0xa106, 0x15d8, 0x703c, 0xac06, 0x1180, 0x0036, - 0x2019, 0x0001, 0x080c, 0x806b, 0x7033, 0x0000, 0x703f, 0x0000, - 0x7043, 0x0000, 0x7047, 0x0000, 0x704b, 0x0000, 0x003e, 0x7038, - 0xac36, 0x1110, 0x660c, 0x763a, 0x7034, 0xac36, 0x1140, 0x2c00, - 0xaf36, 0x0118, 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, 0x660c, - 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, - 0x0000, 0x6010, 0x2068, 0x080c, 0x9d16, 0x0110, 0x080c, 0xb155, - 0x080c, 0x9ed9, 0x87ff, 0x1190, 0x00ce, 0x0804, 0x826c, 0x2c78, - 0x600c, 0x2060, 0x0804, 0x826c, 0xa006, 0x012e, 0x000e, 0x002e, - 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x6017, 0x0000, - 0x00ce, 0xa7bd, 0x0001, 0x0c88, 0x00e6, 0x2071, 0xb8e1, 0x2001, - 0xb600, 0x2004, 0xa086, 0x0002, 0x1118, 0x7007, 0x0005, 0x0010, - 0x7007, 0x0000, 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0066, - 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0xb8e1, 0x2c10, - 0x7638, 0x2660, 0x2678, 0x8cff, 0x0518, 0x2200, 0xac06, 0x11e0, - 0x7038, 0xac36, 0x1110, 0x660c, 0x763a, 0x7034, 0xac36, 0x1140, - 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, - 0x660c, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, - 0x0000, 0xa085, 0x0001, 0x0020, 0x2c78, 0x600c, 0x2060, 0x08d8, - 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, 0x00ee, 0x00fe, 0x0005, - 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0006, 0x0126, 0x2091, - 0x8000, 0x2071, 0xb8e1, 0x760c, 0x2660, 0x2678, 0x8cff, 0x0904, - 0x83aa, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x1904, 0x83a5, - 0x7024, 0xac06, 0x1508, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0904, - 0x8381, 0x080c, 0x7df3, 0x68c3, 0x0000, 0x080c, 0x82d4, 0x7027, - 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, - 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, - 0x0110, 0x6827, 0x0001, 0x003e, 0x700c, 0xac36, 0x1110, 0x660c, - 0x760e, 0x7008, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, - 0x700a, 0x0010, 0x700b, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, - 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, 0x9f03, - 0x1158, 0x080c, 0x2cf7, 0x080c, 0x9f14, 0x11f0, 0x080c, 0x8ca5, - 0x00d8, 0x080c, 0x82d4, 0x08c0, 0x080c, 0x9f14, 0x1118, 0x080c, - 0x8ca5, 0x0090, 0x6010, 0x2068, 0x080c, 0x9d16, 0x0168, 0x601c, - 0xa086, 0x0003, 0x11f8, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, - 0x080c, 0x547a, 0x080c, 0x9ecd, 0x080c, 0xa0db, 0x080c, 0x9ed9, - 0x080c, 0x81a5, 0x00ce, 0x0804, 0x832e, 0x2c78, 0x600c, 0x2060, - 0x0804, 0x832e, 0x012e, 0x000e, 0x006e, 0x00ce, 0x00de, 0x00ee, - 0x00fe, 0x0005, 0x601c, 0xa086, 0x0006, 0x1d30, 0x080c, 0xb155, - 0x0c18, 0x0036, 0x0156, 0x0136, 0x0146, 0x3908, 0xa006, 0xa190, - 0x0020, 0x221c, 0xa39e, 0x2aec, 0x1118, 0x8210, 0x8000, 0x0cc8, - 0xa005, 0x0138, 0x20a9, 0x0020, 0x2198, 0xa110, 0x22a0, 0x22c8, - 0x53a3, 0x014e, 0x013e, 0x015e, 0x003e, 0x0005, 0x00d6, 0x20a1, - 0x020b, 0x080c, 0x774f, 0x20a3, 0x0200, 0x20a3, 0x0014, 0x60c3, - 0x0014, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x2099, 0xb8b9, 0x20a9, - 0x0004, 0x53a6, 0x20a3, 0x0004, 0x20a3, 0x7878, 0x20a3, 0x0000, - 0x20a3, 0x0000, 0x080c, 0x7de0, 0x00de, 0x0005, 0x20a1, 0x020b, - 0x080c, 0x774f, 0x20a3, 0x0214, 0x20a3, 0x0018, 0x20a3, 0x0800, - 0x7810, 0xa084, 0xff00, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7810, 0xa084, 0x00ff, 0x20a2, - 0x7828, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0018, - 0x080c, 0x7de0, 0x0005, 0x00d6, 0x0016, 0x2f68, 0x2009, 0x0035, - 0x080c, 0xa1c6, 0x1904, 0x8489, 0x20a1, 0x020b, 0x080c, 0x76b3, - 0x20a3, 0x1300, 0x20a3, 0x0000, 0x7828, 0x2068, 0x681c, 0xa086, - 0x0003, 0x0580, 0x7818, 0xa080, 0x0028, 0x2014, 0x2001, 0xb635, - 0x2004, 0xd0ac, 0x11d0, 0xa286, 0x007e, 0x1128, 0x20a3, 0x00ff, - 0x20a3, 0xfffe, 0x04b8, 0xa286, 0x007f, 0x1128, 0x20a3, 0x00ff, - 0x20a3, 0xfffd, 0x0478, 0xd2bc, 0x0180, 0xa286, 0x0080, 0x1128, - 0x20a3, 0x00ff, 0x20a3, 0xfffc, 0x0428, 0xa2e8, 0xb735, 0x2d6c, - 0x6810, 0x20a2, 0x6814, 0x20a2, 0x00e8, 0x20a3, 0x0000, 0x6098, - 0x20a2, 0x00c0, 0x2001, 0xb635, 0x2004, 0xd0ac, 0x1138, 0x7818, - 0xa080, 0x0028, 0x2004, 0xa082, 0x007e, 0x0240, 0x00d6, 0x2069, - 0xb61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0020, 0x20a3, 0x0000, - 0x6034, 0x20a2, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x20a3, 0x0000, - 0x20a3, 0x0000, 0x60c3, 0x000c, 0x080c, 0x7de0, 0x001e, 0x00de, - 0x0005, 0x7817, 0x0001, 0x7803, 0x0006, 0x001e, 0x00de, 0x0005, - 0x00d6, 0x0026, 0x7928, 0x2168, 0x691c, 0xa186, 0x0006, 0x01c0, - 0xa186, 0x0003, 0x0904, 0x84ff, 0xa186, 0x0005, 0x0904, 0x84e8, - 0xa186, 0x0004, 0x05b8, 0xa186, 0x0008, 0x0904, 0x84f0, 0x7807, - 0x0037, 0x7813, 0x1700, 0x080c, 0x8567, 0x002e, 0x00de, 0x0005, - 0x080c, 0x8523, 0x2009, 0x4000, 0x6800, 0x0002, 0x84c9, 0x84d4, - 0x84cb, 0x84d4, 0x84d0, 0x84c9, 0x84c9, 0x84d4, 0x84d4, 0x84d4, - 0x84d4, 0x84c9, 0x84c9, 0x84c9, 0x84c9, 0x84c9, 0x84d4, 0x84c9, - 0x84d4, 0x080c, 0x151a, 0x6820, 0xd0e4, 0x0110, 0xd0cc, 0x0110, - 0xa00e, 0x0010, 0x2009, 0x2000, 0x6828, 0x20a2, 0x682c, 0x20a2, - 0x0804, 0x8519, 0x080c, 0x8523, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x2009, 0x4000, 0x6a00, 0xa286, 0x0002, 0x1108, 0xa00e, 0x0488, - 0x04d1, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x2009, 0x4000, 0x0448, - 0x0491, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x2009, 0x4000, 0xa286, - 0x0005, 0x0118, 0xa286, 0x0002, 0x1108, 0xa00e, 0x00d0, 0x0419, - 0x6810, 0x2068, 0x697c, 0x6810, 0xa112, 0x6980, 0x6814, 0xa103, - 0x20a2, 0x22a2, 0x7928, 0xa180, 0x0000, 0x2004, 0xa08e, 0x0002, - 0x0130, 0xa08e, 0x0004, 0x0118, 0x2009, 0x4000, 0x0010, 0x2009, - 0x0000, 0x21a2, 0x20a3, 0x0000, 0x60c3, 0x0018, 0x080c, 0x7de0, - 0x002e, 0x00de, 0x0005, 0x0036, 0x0046, 0x0056, 0x0066, 0x20a1, - 0x020b, 0x080c, 0x774f, 0xa006, 0x20a3, 0x0200, 0x20a2, 0x7934, - 0x21a2, 0x7938, 0x21a2, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, - 0xb635, 0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e, 0x0268, 0x00d6, - 0x2069, 0xb61c, 0x2d2c, 0x8d68, 0x2d34, 0xa0e8, 0xb735, 0x2d6c, - 0x6b10, 0x6c14, 0x00de, 0x0030, 0x2019, 0x0000, 0x6498, 0x2029, - 0x0000, 0x6634, 0x7828, 0xa080, 0x0007, 0x2004, 0xa086, 0x0003, - 0x1128, 0x25a2, 0x26a2, 0x23a2, 0x24a2, 0x0020, 0x23a2, 0x24a2, - 0x25a2, 0x26a2, 0x006e, 0x005e, 0x004e, 0x003e, 0x0005, 0x20a1, - 0x020b, 0x080c, 0x774f, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, - 0x0009, 0x7810, 0x20a2, 0x60c3, 0x0008, 0x080c, 0x7de0, 0x0005, - 0x20a1, 0x020b, 0x080c, 0x76ab, 0x20a3, 0x1400, 0x20a3, 0x0000, - 0x7834, 0x20a2, 0x7838, 0x20a2, 0x7828, 0x20a2, 0x782c, 0x20a2, - 0x7830, 0xa084, 0x00ff, 0x8007, 0x20a2, 0x20a3, 0x0000, 0x60c3, - 0x0010, 0x080c, 0x7de0, 0x0005, 0x20a1, 0x020b, 0x080c, 0x7747, - 0x20a3, 0x0100, 0x20a3, 0x0000, 0x7828, 0x20a2, 0x7810, 0x20a2, - 0x60c3, 0x0008, 0x080c, 0x7de0, 0x0005, 0x0146, 0x20a1, 0x020b, - 0x0031, 0x60c3, 0x0000, 0x080c, 0x7de0, 0x014e, 0x0005, 0x20e1, - 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, - 0xb635, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188, 0x00d6, 0xa0e8, - 0xb735, 0x2d6c, 0x6810, 0xa085, 0x0300, 0x20a2, 0x6814, 0x20a2, - 0x2069, 0xb61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0078, 0x00d6, - 0xa0e8, 0xb735, 0x2d6c, 0x6810, 0xa085, 0x0300, 0x20a2, 0x6814, - 0x20a2, 0x00de, 0x20a3, 0x0000, 0x6234, 0x22a2, 0x20a3, 0x0819, - 0x20a3, 0x0000, 0x080c, 0x7dcf, 0x22a2, 0x20a3, 0x0000, 0x2fa2, - 0x7a08, 0x22a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x0005, 0x20a1, - 0x020b, 0x0079, 0x7910, 0x21a2, 0x20a3, 0x0000, 0x60c3, 0x0000, - 0x20e1, 0x9080, 0x60a7, 0x9575, 0x080c, 0x7dea, 0x080c, 0x6a79, - 0x0005, 0x0156, 0x0136, 0x0036, 0x00d6, 0x00e6, 0x20e1, 0x9080, - 0x20e1, 0x4000, 0x7854, 0x2068, 0xadf0, 0x000f, 0x7210, 0xa296, - 0x00c0, 0xa294, 0xfffd, 0x7212, 0x7214, 0xa294, 0x0300, 0x7216, - 0x7100, 0xa194, 0x00ff, 0x7308, 0xa384, 0x00ff, 0xa08d, 0xc200, - 0x7102, 0xa384, 0xff00, 0xa215, 0x720a, 0x7004, 0x720c, 0x700e, - 0x7206, 0x20a9, 0x000a, 0x2e98, 0x53a6, 0x60a3, 0x0035, 0x6a38, - 0xa294, 0x7000, 0xa286, 0x3000, 0x0110, 0x60a3, 0x0037, 0x00ee, - 0x00de, 0x003e, 0x013e, 0x015e, 0x0005, 0x2009, 0x0092, 0x0010, - 0x2009, 0x0096, 0x60ab, 0x0036, 0x6116, 0x0005, 0x2061, 0xbe00, - 0x2a70, 0x7068, 0x704a, 0x704f, 0xbe00, 0x0005, 0x00e6, 0x0126, - 0x2071, 0xb600, 0x2091, 0x8000, 0x7548, 0xa582, 0x0010, 0x0608, - 0x704c, 0x2060, 0x6000, 0xa086, 0x0000, 0x0148, 0xace0, 0x0018, - 0x705c, 0xac02, 0x1208, 0x0cb0, 0x2061, 0xbe00, 0x0c98, 0x6003, - 0x0008, 0x8529, 0x754a, 0xaca8, 0x0018, 0x705c, 0xa502, 0x1230, - 0x754e, 0xa085, 0x0001, 0x012e, 0x00ee, 0x0005, 0x704f, 0xbe00, - 0x0cc0, 0xa006, 0x0cc0, 0x00e6, 0x2071, 0xb600, 0x7548, 0xa582, - 0x0010, 0x0600, 0x704c, 0x2060, 0x6000, 0xa086, 0x0000, 0x0148, - 0xace0, 0x0018, 0x705c, 0xac02, 0x1208, 0x0cb0, 0x2061, 0xbe00, - 0x0c98, 0x6003, 0x0008, 0x8529, 0x754a, 0xaca8, 0x0018, 0x705c, - 0xa502, 0x1228, 0x754e, 0xa085, 0x0001, 0x00ee, 0x0005, 0x704f, - 0xbe00, 0x0cc8, 0xa006, 0x0cc8, 0xac82, 0xbe00, 0x0a0c, 0x151a, - 0x2001, 0xb617, 0x2004, 0xac02, 0x1a0c, 0x151a, 0xa006, 0x6006, - 0x600a, 0x600e, 0x6012, 0x6016, 0x601a, 0x601f, 0x0000, 0x6003, - 0x0000, 0x6052, 0x6056, 0x6022, 0x6026, 0x602a, 0x602e, 0x6032, - 0x6036, 0x603a, 0x603e, 0x2061, 0xb600, 0x6048, 0x8000, 0x604a, - 0xa086, 0x0001, 0x0108, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, - 0x71e5, 0x012e, 0x0cc0, 0x601c, 0xa084, 0x000f, 0x0002, 0x86e7, - 0x86f6, 0x8711, 0x872c, 0xa20e, 0xa229, 0xa244, 0x86e7, 0x86f6, - 0x86e7, 0x8747, 0x86e7, 0x86e7, 0x86e7, 0x86e7, 0x86e7, 0xa186, - 0x0013, 0x1128, 0x080c, 0x7102, 0x080c, 0x71e5, 0x0005, 0xa18e, - 0x0047, 0x1118, 0xa016, 0x080c, 0x1863, 0x0005, 0x0066, 0x6000, - 0xa0b2, 0x0010, 0x1a0c, 0x151a, 0x0013, 0x006e, 0x0005, 0x870f, - 0x8b27, 0x8cdf, 0x870f, 0x8d54, 0x8805, 0x870f, 0x870f, 0x8ab9, - 0x917b, 0x870f, 0x870f, 0x870f, 0x870f, 0x870f, 0x870f, 0x080c, - 0x151a, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x151a, 0x0013, - 0x006e, 0x0005, 0x872a, 0x97de, 0x872a, 0x872a, 0x872a, 0x872a, - 0x872a, 0x872a, 0x9789, 0x994a, 0x872a, 0x980b, 0x9882, 0x980b, - 0x9882, 0x872a, 0x080c, 0x151a, 0x0066, 0x6000, 0xa0b2, 0x0010, - 0x1a0c, 0x151a, 0x0013, 0x006e, 0x0005, 0x8745, 0x91bc, 0x9286, - 0x93c4, 0x954d, 0x8745, 0x8745, 0x8745, 0x9196, 0x9739, 0x973c, - 0x8745, 0x8745, 0x8745, 0x8745, 0x9766, 0x080c, 0x151a, 0x0066, - 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x151a, 0x0013, 0x006e, 0x0005, - 0x8760, 0x8760, 0x8760, 0x878e, 0x87db, 0x8760, 0x8760, 0x8760, - 0x8762, 0x8760, 0x8760, 0x8760, 0x8760, 0x8760, 0x8760, 0x8760, - 0x080c, 0x151a, 0xa186, 0x0003, 0x190c, 0x151a, 0x00d6, 0x6003, - 0x0003, 0x6106, 0x6010, 0x2068, 0x684f, 0x0040, 0x687c, 0x680a, - 0x6880, 0x680e, 0x6813, 0x0000, 0x6817, 0x0000, 0x6854, 0xa092, - 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, 0x8013, 0x8213, 0xa210, - 0x6216, 0x00de, 0x2c10, 0x080c, 0x1fc5, 0x080c, 0x6d62, 0x0126, - 0x2091, 0x8000, 0x080c, 0x72a2, 0x012e, 0x0005, 0xa182, 0x0047, - 0x0002, 0x879a, 0x879a, 0x879c, 0x87b5, 0x879a, 0x879a, 0x879a, - 0x879a, 0x87c7, 0x080c, 0x151a, 0x00d6, 0x0016, 0x080c, 0x7198, - 0x080c, 0x72a2, 0x6003, 0x0004, 0x6110, 0x2168, 0x684f, 0x0020, - 0x685c, 0x685a, 0x6874, 0x687e, 0x6878, 0x6882, 0x6897, 0x0000, - 0x689b, 0x0000, 0x001e, 0x00de, 0x0005, 0x080c, 0x7198, 0x00d6, - 0x6110, 0x2168, 0x080c, 0x9d16, 0x0120, 0x684b, 0x0006, 0x080c, - 0x547a, 0x00de, 0x080c, 0x86a4, 0x080c, 0x72a2, 0x0005, 0x080c, - 0x7198, 0x080c, 0x2cd1, 0x00d6, 0x6110, 0x2168, 0x080c, 0x9d16, - 0x0120, 0x684b, 0x0029, 0x080c, 0x547a, 0x00de, 0x080c, 0x86a4, - 0x080c, 0x72a2, 0x0005, 0xa182, 0x0047, 0x0002, 0x87e9, 0x87f8, - 0x87e7, 0x87e7, 0x87e7, 0x87e7, 0x87e7, 0x87e7, 0x87e7, 0x080c, - 0x151a, 0x00d6, 0x6010, 0x2068, 0x684c, 0xc0f4, 0x684e, 0x00de, - 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x1863, 0x0005, - 0x00d6, 0x6110, 0x2168, 0x684b, 0x0000, 0x6853, 0x0000, 0x080c, - 0x547a, 0x00de, 0x080c, 0x86a4, 0x0005, 0xa1b6, 0x0015, 0x1118, - 0x080c, 0x86a4, 0x0030, 0xa1b6, 0x0016, 0x190c, 0x151a, 0x080c, - 0x86a4, 0x0005, 0x20a9, 0x000e, 0x2e98, 0x6010, 0x20a0, 0x53a3, - 0x20a9, 0x0006, 0x3310, 0x3420, 0x9398, 0x94a0, 0x3318, 0x3428, - 0x222e, 0x2326, 0xa290, 0x0002, 0xa5a8, 0x0002, 0xa398, 0x0002, - 0xa4a0, 0x0002, 0x1f04, 0x8820, 0x00e6, 0x080c, 0x9d16, 0x0130, - 0x6010, 0x2070, 0x7007, 0x0000, 0x7037, 0x0103, 0x00ee, 0x080c, - 0x86a4, 0x0005, 0x00d6, 0x0036, 0x7330, 0xa386, 0x0200, 0x1130, - 0x6018, 0x2068, 0x6813, 0x00ff, 0x6817, 0xfffd, 0x6010, 0xa005, - 0x0130, 0x2068, 0x6807, 0x0000, 0x6837, 0x0103, 0x6b32, 0x080c, - 0x86a4, 0x003e, 0x00de, 0x0005, 0x0016, 0x20a9, 0x002a, 0xae80, - 0x000c, 0x2098, 0x6010, 0xa080, 0x0002, 0x20a0, 0x53a3, 0x20a9, - 0x002a, 0x6010, 0xa080, 0x0001, 0x2004, 0xa080, 0x0002, 0x20a0, - 0x53a3, 0x00e6, 0x6010, 0x2004, 0x2070, 0x7037, 0x0103, 0x00ee, - 0x080c, 0x86a4, 0x001e, 0x0005, 0x0016, 0x2009, 0x0000, 0x7030, - 0xa086, 0x0100, 0x0140, 0x7038, 0xa084, 0x00ff, 0x800c, 0x703c, - 0xa084, 0x00ff, 0x8004, 0xa080, 0x0004, 0xa108, 0x21a8, 0xae80, - 0x000c, 0x2098, 0x6010, 0xa080, 0x0002, 0x20a0, 0x080c, 0x4bf1, - 0x00e6, 0x080c, 0x9d16, 0x0140, 0x6010, 0x2070, 0x7007, 0x0000, - 0x7034, 0x70b2, 0x7037, 0x0103, 0x00ee, 0x080c, 0x86a4, 0x001e, - 0x0005, 0x00e6, 0x00d6, 0x603f, 0x0000, 0x2c68, 0x0016, 0x2009, - 0x0035, 0x080c, 0xa1c6, 0x001e, 0x1168, 0x0026, 0x6228, 0x2268, - 0x002e, 0x2071, 0xbc8c, 0x6b1c, 0xa386, 0x0003, 0x0130, 0xa386, - 0x0006, 0x0128, 0x080c, 0x86a4, 0x0020, 0x0031, 0x0010, 0x080c, - 0x8982, 0x00de, 0x00ee, 0x0005, 0x00f6, 0x6810, 0x2078, 0xa186, - 0x0015, 0x0904, 0x8969, 0xa18e, 0x0016, 0x1904, 0x8980, 0x700c, - 0xa08c, 0xff00, 0xa186, 0x1700, 0x0120, 0xa186, 0x0300, 0x1904, - 0x8948, 0x8fff, 0x1138, 0x6800, 0xa086, 0x000f, 0x0904, 0x892c, - 0x0804, 0x897e, 0x6808, 0xa086, 0xffff, 0x1904, 0x896b, 0x784c, - 0xa084, 0x0060, 0xa086, 0x0020, 0x1150, 0x797c, 0x7810, 0xa106, - 0x1904, 0x896b, 0x7980, 0x7814, 0xa106, 0x1904, 0x896b, 0x080c, - 0x9ecd, 0x6858, 0x7852, 0x784c, 0xc0dc, 0xc0f4, 0xc0d4, 0x784e, - 0x0026, 0xa00e, 0x6a14, 0x2001, 0x000a, 0x080c, 0x6bb2, 0x7854, - 0xa20a, 0x0208, 0x8011, 0x7a56, 0x82ff, 0x002e, 0x1138, 0x00c6, - 0x2d60, 0x080c, 0x9ac5, 0x00ce, 0x0804, 0x897e, 0x00c6, 0x00d6, - 0x2f68, 0x6838, 0xd0fc, 0x1118, 0x080c, 0x4cd7, 0x0010, 0x080c, - 0x4ebb, 0x00de, 0x00ce, 0x1904, 0x896b, 0x00c6, 0x2d60, 0x080c, - 0x86a4, 0x00ce, 0x0804, 0x897e, 0x00c6, 0x080c, 0x9f92, 0x0190, - 0x6013, 0x0000, 0x6818, 0x601a, 0x080c, 0xa0e3, 0x601f, 0x0003, - 0x6904, 0x00c6, 0x2d60, 0x080c, 0x86a4, 0x00ce, 0x080c, 0x86d3, - 0x00ce, 0x04e0, 0x2001, 0xb8b8, 0x2004, 0x683e, 0x00ce, 0x04b0, - 0x7008, 0xa086, 0x000b, 0x11a0, 0x6018, 0x200c, 0xc1bc, 0x2102, - 0x00c6, 0x2d60, 0x784b, 0x0003, 0x6007, 0x0085, 0x6003, 0x000b, - 0x601f, 0x0002, 0x080c, 0x6cff, 0x080c, 0x71e5, 0x00ce, 0x00f0, - 0x700c, 0xa086, 0x2a00, 0x1138, 0x2001, 0xb8b8, 0x2004, 0x683e, - 0x00a8, 0x0481, 0x00a8, 0x8fff, 0x090c, 0x151a, 0x00c6, 0x00d6, - 0x2d60, 0x2f68, 0x6837, 0x0103, 0x684b, 0x0003, 0x080c, 0x99b9, - 0x080c, 0x9ecd, 0x080c, 0x9ed9, 0x00de, 0x00ce, 0x080c, 0x86a4, - 0x00fe, 0x0005, 0xa186, 0x0015, 0x1128, 0x2001, 0xb8b8, 0x2004, - 0x683e, 0x0068, 0xa18e, 0x0016, 0x1160, 0x00c6, 0x2d00, 0x2060, - 0x080c, 0xb3f6, 0x080c, 0x6b61, 0x080c, 0x86a4, 0x00ce, 0x080c, - 0x86a4, 0x0005, 0x0026, 0x0036, 0x0046, 0x7228, 0x7c80, 0x7b7c, - 0xd2f4, 0x0130, 0x2001, 0xb8b8, 0x2004, 0x683e, 0x0804, 0x89fc, - 0x00c6, 0x2d60, 0x080c, 0x99d9, 0x00ce, 0x6804, 0xa086, 0x0050, - 0x1168, 0x00c6, 0x2d00, 0x2060, 0x6003, 0x0001, 0x6007, 0x0050, - 0x080c, 0x6cff, 0x080c, 0x71e5, 0x00ce, 0x04f0, 0x6800, 0xa086, - 0x000f, 0x01c8, 0x8fff, 0x090c, 0x151a, 0x6820, 0xd0dc, 0x1198, - 0x6800, 0xa086, 0x0004, 0x1198, 0x784c, 0xd0ac, 0x0180, 0x784c, - 0xc0dc, 0xc0f4, 0x784e, 0x7850, 0xc0f4, 0xc0fc, 0x7852, 0x2001, - 0x0001, 0x682e, 0x00e0, 0x2001, 0x0007, 0x682e, 0x00c0, 0x784c, - 0xd0b4, 0x1130, 0xd0ac, 0x0db8, 0x784c, 0xd0f4, 0x1da0, 0x0c38, - 0xd2ec, 0x1d88, 0x7024, 0xa306, 0x1118, 0x7020, 0xa406, 0x0d58, - 0x7020, 0x6836, 0x7024, 0x683a, 0x2001, 0x0005, 0x682e, 0x080c, - 0xa01f, 0x080c, 0x71e5, 0x0010, 0x080c, 0x86a4, 0x004e, 0x003e, - 0x002e, 0x0005, 0x00e6, 0x00d6, 0x0026, 0x6034, 0x2068, 0x6a1c, - 0xa286, 0x0007, 0x0904, 0x8a60, 0xa286, 0x0002, 0x0904, 0x8a60, - 0xa286, 0x0000, 0x0904, 0x8a60, 0x6808, 0x6338, 0xa306, 0x1904, - 0x8a60, 0x2071, 0xbc8c, 0xa186, 0x0015, 0x05e0, 0xa18e, 0x0016, - 0x1190, 0x6030, 0xa084, 0x00ff, 0xa086, 0x0001, 0x1160, 0x700c, - 0xa086, 0x2a00, 0x1140, 0x6034, 0xa080, 0x0008, 0x200c, 0xc1dd, - 0xc1f5, 0x2102, 0x0438, 0x00c6, 0x6034, 0x2060, 0x6104, 0xa186, - 0x004b, 0x01a0, 0xa186, 0x004c, 0x0188, 0xa186, 0x004d, 0x0170, - 0xa186, 0x004e, 0x0158, 0xa186, 0x0052, 0x0140, 0x6010, 0x2068, - 0x080c, 0x9d16, 0x090c, 0x151a, 0x684b, 0x0003, 0x6007, 0x0085, - 0x6003, 0x000b, 0x601f, 0x0002, 0x080c, 0x6cff, 0x080c, 0x71e5, - 0x00ce, 0x0030, 0x6034, 0x2070, 0x2001, 0xb8b8, 0x2004, 0x703e, - 0x080c, 0x86a4, 0x002e, 0x00de, 0x00ee, 0x0005, 0x00d6, 0x20a9, - 0x000e, 0x2e98, 0x6010, 0x20a0, 0x53a3, 0xa1b6, 0x0015, 0x1558, - 0x6018, 0x2068, 0x0156, 0x0036, 0x0026, 0xae90, 0x000c, 0xa290, - 0x0004, 0x20a9, 0x0004, 0xad98, 0x000a, 0x080c, 0x9166, 0x002e, - 0x003e, 0x015e, 0x11d8, 0x0156, 0x0036, 0x0026, 0xae90, 0x000c, - 0xa290, 0x0008, 0x20a9, 0x0004, 0xad98, 0x0006, 0x080c, 0x9166, - 0x002e, 0x003e, 0x015e, 0x1150, 0x7038, 0x680a, 0x703c, 0x680e, - 0x6800, 0xc08d, 0x6802, 0x00de, 0x0804, 0x882c, 0x080c, 0x2cd1, - 0x00c6, 0x080c, 0x864e, 0x2f00, 0x601a, 0x6013, 0x0000, 0x601f, - 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x2001, 0x0007, 0x080c, - 0x4f6f, 0x080c, 0x4f9c, 0x080c, 0x6d45, 0x080c, 0x71e5, 0x00ce, - 0x0c10, 0x2100, 0xa1b2, 0x0080, 0x1a0c, 0x151a, 0xa1b2, 0x0040, - 0x1a04, 0x8b1d, 0x0002, 0x8b11, 0x8b05, 0x8b11, 0x8b11, 0x8b11, - 0x8b11, 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, - 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, - 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, - 0x8b03, 0x8b03, 0x8b11, 0x8b03, 0x8b11, 0x8b11, 0x8b03, 0x8b03, - 0x8b03, 0x8b03, 0x8b03, 0x8b11, 0x8b03, 0x8b03, 0x8b03, 0x8b03, - 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b11, 0x8b11, 0x8b03, - 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, - 0x8b11, 0x8b03, 0x8b03, 0x080c, 0x151a, 0x6003, 0x0001, 0x6106, - 0x080c, 0x6d45, 0x0126, 0x2091, 0x8000, 0x080c, 0x71e5, 0x012e, - 0x0005, 0x6003, 0x0001, 0x6106, 0x080c, 0x6d45, 0x0126, 0x2091, - 0x8000, 0x080c, 0x71e5, 0x012e, 0x0005, 0x2600, 0x0002, 0x8b11, - 0x8b11, 0x8b25, 0x8b11, 0x8b11, 0x8b25, 0x080c, 0x151a, 0x6004, - 0xa0b2, 0x0080, 0x1a0c, 0x151a, 0xa1b6, 0x0013, 0x0904, 0x8bd7, - 0xa1b6, 0x0027, 0x1904, 0x8b9d, 0x080c, 0x7102, 0x6004, 0x080c, - 0x9f03, 0x0190, 0x080c, 0x9f14, 0x0904, 0x8b97, 0xa08e, 0x0021, - 0x0904, 0x8b9a, 0xa08e, 0x0022, 0x0904, 0x8b97, 0xa08e, 0x003d, - 0x0904, 0x8b9a, 0x0804, 0x8b90, 0x080c, 0x2cf7, 0x2001, 0x0007, - 0x080c, 0x4f6f, 0x6018, 0xa080, 0x0028, 0x200c, 0x080c, 0x8ca5, - 0xa186, 0x007e, 0x1148, 0x2001, 0xb635, 0x2014, 0xc285, 0x080c, - 0x5b41, 0x1108, 0xc2ad, 0x2202, 0x0016, 0x0026, 0x0036, 0x2110, - 0x0026, 0x2019, 0x0028, 0x080c, 0x8320, 0x002e, 0x080c, 0xb449, - 0x003e, 0x002e, 0x001e, 0x0016, 0x0026, 0x0036, 0x2110, 0x2019, - 0x0028, 0x080c, 0x6e67, 0x0076, 0x2039, 0x0000, 0x080c, 0x6d74, - 0x00c6, 0x6018, 0xa065, 0x0110, 0x080c, 0x521c, 0x00ce, 0x2c08, - 0x080c, 0xaf3e, 0x007e, 0x003e, 0x002e, 0x001e, 0x080c, 0x4fde, - 0x080c, 0xa0db, 0x080c, 0x86a4, 0x080c, 0x71e5, 0x0005, 0x080c, - 0x8ca5, 0x0cb0, 0x080c, 0x8cd3, 0x0c98, 0xa186, 0x0014, 0x1db0, - 0x080c, 0x7102, 0x080c, 0x2cd1, 0x080c, 0x9f03, 0x1188, 0x080c, - 0x2cf7, 0x6018, 0xa080, 0x0028, 0x200c, 0x080c, 0x8ca5, 0xa186, - 0x007e, 0x1128, 0x2001, 0xb635, 0x200c, 0xc185, 0x2102, 0x08c0, - 0x080c, 0x9f14, 0x1118, 0x080c, 0x8ca5, 0x0890, 0x6004, 0xa08e, - 0x0032, 0x1158, 0x00e6, 0x00f6, 0x2071, 0xb682, 0x2079, 0x0000, - 0x080c, 0x3004, 0x00fe, 0x00ee, 0x0818, 0x6004, 0xa08e, 0x0021, - 0x0d50, 0xa08e, 0x0022, 0x090c, 0x8ca5, 0x0804, 0x8b90, 0xa0b2, - 0x0040, 0x1a04, 0x8c9a, 0x2008, 0x0002, 0x8c1f, 0x8c20, 0x8c23, - 0x8c26, 0x8c29, 0x8c2c, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, - 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, - 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, - 0x8c1d, 0x8c1d, 0x8c1d, 0x8c2f, 0x8c3e, 0x8c1d, 0x8c40, 0x8c3e, - 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c3e, 0x8c3e, 0x8c1d, - 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c7a, - 0x8c3e, 0x8c1d, 0x8c3a, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c3b, 0x8c1d, - 0x8c1d, 0x8c1d, 0x8c3e, 0x8c71, 0x8c1d, 0x080c, 0x151a, 0x00f0, - 0x2001, 0x000b, 0x0460, 0x2001, 0x0003, 0x0448, 0x2001, 0x0005, - 0x0430, 0x2001, 0x0001, 0x0418, 0x2001, 0x0009, 0x0400, 0x080c, - 0x7102, 0x6003, 0x0005, 0x2001, 0xb8b8, 0x2004, 0x603e, 0x080c, - 0x71e5, 0x00a0, 0x0018, 0x0010, 0x080c, 0x4f6f, 0x0804, 0x8c8b, - 0x080c, 0x7102, 0x2001, 0xb8b6, 0x2004, 0x6016, 0x2001, 0xb8b8, - 0x2004, 0x603e, 0x6003, 0x0004, 0x080c, 0x71e5, 0x0005, 0x080c, - 0x4f6f, 0x080c, 0x7102, 0x6003, 0x0002, 0x2001, 0xb8b8, 0x2004, - 0x603e, 0x0036, 0x2019, 0xb65d, 0x2304, 0xa084, 0xff00, 0x1120, - 0x2001, 0xb8b6, 0x201c, 0x0040, 0x8007, 0xa09a, 0x0004, 0x0ec0, - 0x8003, 0x801b, 0x831b, 0xa318, 0x6316, 0x003e, 0x080c, 0x71e5, - 0x08e8, 0x080c, 0x7102, 0x080c, 0xa0db, 0x080c, 0x86a4, 0x080c, - 0x71e5, 0x08a0, 0x00e6, 0x00f6, 0x2071, 0xb682, 0x2079, 0x0000, - 0x080c, 0x3004, 0x00fe, 0x00ee, 0x080c, 0x7102, 0x080c, 0x86a4, - 0x080c, 0x71e5, 0x0818, 0x080c, 0x7102, 0x2001, 0xb8b8, 0x2004, - 0x603e, 0x6003, 0x0002, 0x2001, 0xb8b6, 0x2004, 0x6016, 0x080c, - 0x71e5, 0x0005, 0x2600, 0x2008, 0x0002, 0x8ca3, 0x8ca3, 0x8ca3, - 0x8c8b, 0x8c8b, 0x8ca3, 0x080c, 0x151a, 0x00e6, 0x0026, 0x0016, - 0x080c, 0x9d16, 0x0508, 0x6010, 0x2070, 0x7034, 0xa086, 0x0139, - 0x1148, 0x2001, 0x0030, 0x2009, 0x0000, 0x2011, 0x4005, 0x080c, - 0xa192, 0x0090, 0x7038, 0xd0fc, 0x0178, 0x7007, 0x0000, 0x0016, - 0x6004, 0xa08e, 0x0021, 0x0160, 0xa08e, 0x003d, 0x0148, 0x001e, - 0x7037, 0x0103, 0x7033, 0x0100, 0x001e, 0x002e, 0x00ee, 0x0005, - 0x001e, 0x0009, 0x0cc8, 0x00e6, 0xacf0, 0x0004, 0x2e74, 0x7000, - 0x2070, 0x7037, 0x0103, 0x7023, 0x8001, 0x00ee, 0x0005, 0x00d6, - 0x6618, 0x2668, 0x6804, 0xa084, 0x00ff, 0x00de, 0xa0b2, 0x000c, - 0x1a0c, 0x151a, 0x6604, 0xa6b6, 0x0043, 0x1120, 0x080c, 0xa14e, - 0x0804, 0x8d44, 0x6604, 0xa6b6, 0x0033, 0x1120, 0x080c, 0xa0fe, - 0x0804, 0x8d44, 0x6604, 0xa6b6, 0x0028, 0x1120, 0x080c, 0x9f44, - 0x0804, 0x8d44, 0x6604, 0xa6b6, 0x0029, 0x1118, 0x080c, 0x9f5b, - 0x04d8, 0x6604, 0xa6b6, 0x001f, 0x1118, 0x080c, 0x8812, 0x04a0, - 0x6604, 0xa6b6, 0x0000, 0x1118, 0x080c, 0x8a66, 0x0468, 0x6604, - 0xa6b6, 0x0022, 0x1118, 0x080c, 0x883a, 0x0430, 0x6604, 0xa6b6, - 0x0035, 0x1118, 0x080c, 0x88a1, 0x00f8, 0x6604, 0xa6b6, 0x0039, - 0x1118, 0x080c, 0x8a02, 0x00c0, 0x6604, 0xa6b6, 0x003d, 0x1118, - 0x080c, 0x8854, 0x0088, 0x6604, 0xa6b6, 0x0044, 0x1118, 0x080c, - 0x8874, 0x0050, 0xa1b6, 0x0015, 0x1110, 0x0053, 0x0028, 0xa1b6, - 0x0016, 0x1118, 0x0804, 0x8f08, 0x0005, 0x080c, 0x86ef, 0x0ce0, - 0x8d6b, 0x8d6e, 0x8d6b, 0x8db0, 0x8d6b, 0x8e95, 0x8f16, 0x8d6b, - 0x8d6b, 0x8ee4, 0x8d6b, 0x8ef8, 0xa1b6, 0x0048, 0x0140, 0x20e1, - 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x1863, 0x0005, 0x00e6, - 0xacf0, 0x0004, 0x2e74, 0x7000, 0x2070, 0x7037, 0x0103, 0x00ee, - 0x080c, 0x86a4, 0x0005, 0xe000, 0xe000, 0x0005, 0x00e6, 0x2071, - 0xb600, 0x7084, 0xa086, 0x0074, 0x1530, 0x080c, 0xaf15, 0x11b0, - 0x00d6, 0x6018, 0x2068, 0x7030, 0xd08c, 0x0128, 0x6800, 0xd0bc, - 0x0110, 0xc0c5, 0x6802, 0x00d9, 0x00de, 0x2001, 0x0006, 0x080c, - 0x4f6f, 0x080c, 0x2cf7, 0x080c, 0x86a4, 0x0078, 0x2001, 0x000a, - 0x080c, 0x4f6f, 0x080c, 0x2cf7, 0x6003, 0x0001, 0x6007, 0x0001, - 0x080c, 0x6d45, 0x0010, 0x080c, 0x8e82, 0x00ee, 0x0005, 0x6800, - 0xd084, 0x0168, 0x2001, 0x0000, 0x080c, 0x4f5d, 0x2069, 0xb652, - 0x6804, 0xd0a4, 0x0120, 0x2001, 0x0006, 0x080c, 0x4f9c, 0x0005, - 0x00d6, 0x2011, 0xb621, 0x2204, 0xa086, 0x0074, 0x1904, 0x8e7f, - 0x6018, 0x2068, 0x6aa0, 0xa286, 0x007e, 0x1120, 0x080c, 0x902e, - 0x0804, 0x8e1e, 0x080c, 0x9024, 0x6018, 0x2068, 0xa080, 0x0028, - 0x2014, 0xa286, 0x0080, 0x11c0, 0x6813, 0x00ff, 0x6817, 0xfffc, - 0x6010, 0xa005, 0x0138, 0x2068, 0x6807, 0x0000, 0x6837, 0x0103, - 0x6833, 0x0200, 0x2001, 0x0006, 0x080c, 0x4f6f, 0x080c, 0x2cf7, - 0x080c, 0x86a4, 0x0804, 0x8e80, 0x00e6, 0x2071, 0xb635, 0x2e04, - 0xd09c, 0x0188, 0x2071, 0xbc80, 0x7108, 0x720c, 0xa18c, 0x00ff, - 0x1118, 0xa284, 0xff00, 0x0138, 0x6018, 0x2070, 0x70a0, 0xd0bc, - 0x1110, 0x7112, 0x7216, 0x00ee, 0x6010, 0xa005, 0x0198, 0x2068, - 0x6838, 0xd0f4, 0x0178, 0x6834, 0xa084, 0x00ff, 0xa086, 0x0039, - 0x1958, 0x2001, 0x0000, 0x2009, 0x0000, 0x2011, 0x4000, 0x080c, - 0xa192, 0x0840, 0x2001, 0x0004, 0x080c, 0x4f6f, 0x6003, 0x0001, - 0x6007, 0x0003, 0x080c, 0x6d45, 0x0804, 0x8e80, 0x685c, 0xd0e4, - 0x01d8, 0x080c, 0xa08e, 0x080c, 0x5b41, 0x0118, 0xd0dc, 0x1904, - 0x8dda, 0x2011, 0xb635, 0x2204, 0xc0ad, 0x2012, 0x2001, 0xb88f, - 0x2004, 0x00f6, 0x2079, 0x0100, 0x78e3, 0x0000, 0x080c, 0x28a7, - 0x78e2, 0x00fe, 0x0804, 0x8dda, 0x080c, 0xa0c4, 0x2011, 0xb635, - 0x2204, 0xc0a5, 0x2012, 0x0006, 0x080c, 0xb037, 0x000e, 0x1904, - 0x8dda, 0xc0b5, 0x2012, 0x2001, 0x0006, 0x080c, 0x4f6f, 0x2001, - 0x0000, 0x080c, 0x4f5d, 0x00c6, 0x2009, 0x00ef, 0x00f6, 0x2079, - 0x0100, 0x79ea, 0x7932, 0x7936, 0x00fe, 0x080c, 0x287c, 0x00f6, - 0x2079, 0xb600, 0x7976, 0x2100, 0x2009, 0x0000, 0x080c, 0x2852, - 0x7952, 0x00fe, 0x8108, 0x080c, 0x4fbf, 0x2c00, 0x00ce, 0x1904, - 0x8dda, 0x601a, 0x2001, 0x0002, 0x080c, 0x4f6f, 0x601f, 0x0001, - 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x6d45, 0x0008, 0x0011, - 0x00de, 0x0005, 0x2001, 0x0007, 0x080c, 0x4f6f, 0x2001, 0xb600, - 0x2004, 0xa086, 0x0003, 0x1120, 0x2001, 0x0007, 0x080c, 0x4f9c, - 0x080c, 0x2cf7, 0x080c, 0x86a4, 0x0005, 0x00e6, 0x0026, 0x0016, - 0x2071, 0xb600, 0x7084, 0xa086, 0x0014, 0x15f0, 0x7000, 0xa086, - 0x0003, 0x1128, 0x6010, 0xa005, 0x1110, 0x080c, 0x3f85, 0x00d6, - 0x6018, 0x2068, 0x080c, 0x50bd, 0x080c, 0x8d9f, 0x00de, 0x080c, - 0x90dd, 0x1550, 0x00d6, 0x6018, 0x2068, 0x6890, 0x00de, 0xa005, - 0x0518, 0x2001, 0x0006, 0x080c, 0x4f6f, 0x00e6, 0x6010, 0xa075, - 0x01a8, 0x7034, 0xa084, 0x00ff, 0xa086, 0x0039, 0x1148, 0x2001, - 0x0000, 0x2009, 0x0000, 0x2011, 0x4000, 0x080c, 0xa192, 0x0030, - 0x7007, 0x0000, 0x7037, 0x0103, 0x7033, 0x0200, 0x00ee, 0x080c, - 0x2cf7, 0x080c, 0x86a4, 0x0020, 0x080c, 0x8ca5, 0x080c, 0x8e82, - 0x001e, 0x002e, 0x00ee, 0x0005, 0x2011, 0xb621, 0x2204, 0xa086, - 0x0014, 0x1158, 0x2001, 0x0002, 0x080c, 0x4f6f, 0x6003, 0x0001, - 0x6007, 0x0001, 0x080c, 0x6d45, 0x0010, 0x080c, 0x8e82, 0x0005, - 0x2011, 0xb621, 0x2204, 0xa086, 0x0004, 0x1138, 0x2001, 0x0007, - 0x080c, 0x4f6f, 0x080c, 0x86a4, 0x0010, 0x080c, 0x8e82, 0x0005, - 0x000b, 0x0005, 0x8d6b, 0x8f21, 0x8d6b, 0x8f55, 0x8d6b, 0x8fe0, - 0x8f16, 0x8d6b, 0x8d6b, 0x8ff3, 0x8d6b, 0x9003, 0x6604, 0xa686, - 0x0003, 0x0904, 0x8e95, 0xa6b6, 0x001e, 0x1110, 0x080c, 0x86a4, - 0x0005, 0x00d6, 0x00c6, 0x080c, 0x9013, 0x1178, 0x2001, 0x0000, - 0x080c, 0x4f5d, 0x2001, 0x0002, 0x080c, 0x4f6f, 0x6003, 0x0001, - 0x6007, 0x0002, 0x080c, 0x6d45, 0x00e8, 0x2009, 0xbc8e, 0x2104, - 0xa086, 0x0009, 0x1160, 0x6018, 0x2068, 0x6840, 0xa084, 0x00ff, - 0xa005, 0x0170, 0x8001, 0x6842, 0x6017, 0x000a, 0x0058, 0x2009, - 0xbc8f, 0x2104, 0xa084, 0xff00, 0xa086, 0x1900, 0x1108, 0x08d0, - 0x080c, 0x8e82, 0x00ce, 0x00de, 0x0005, 0x0026, 0x2011, 0x0000, - 0x080c, 0x9021, 0x00d6, 0x2069, 0xb89e, 0x2d04, 0xa005, 0x0168, - 0x6018, 0x2068, 0x68a0, 0xa086, 0x007e, 0x1138, 0x2069, 0xb61d, - 0x2d04, 0x8000, 0x206a, 0x00de, 0x0010, 0x00de, 0x0078, 0x2001, - 0x0000, 0x080c, 0x4f5d, 0x2001, 0x0002, 0x080c, 0x4f6f, 0x6003, - 0x0001, 0x6007, 0x0002, 0x080c, 0x6d45, 0x0480, 0x00d6, 0x6010, - 0x2068, 0x080c, 0x9d16, 0x00de, 0x0108, 0x6a34, 0x080c, 0x8ca5, - 0x2009, 0xbc8e, 0x2134, 0xa6b4, 0x00ff, 0xa686, 0x0005, 0x0500, - 0xa686, 0x000b, 0x01c8, 0x2009, 0xbc8f, 0x2104, 0xa084, 0xff00, - 0x1118, 0xa686, 0x0009, 0x01a0, 0xa086, 0x1900, 0x1168, 0xa686, - 0x0009, 0x0170, 0x2001, 0x0004, 0x080c, 0x4f6f, 0x2001, 0x0028, - 0x6016, 0x6007, 0x004b, 0x0010, 0x080c, 0x8e82, 0x002e, 0x0005, - 0x00d6, 0xa286, 0x0139, 0x0160, 0x6010, 0x2068, 0x080c, 0x9d16, - 0x0148, 0x6834, 0xa086, 0x0139, 0x0118, 0x6838, 0xd0fc, 0x0110, - 0x00de, 0x0c50, 0x6018, 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, - 0x0140, 0x8001, 0x6842, 0x6017, 0x000a, 0x6007, 0x0016, 0x00de, - 0x08e8, 0x68a0, 0xa086, 0x007e, 0x1138, 0x00e6, 0x2071, 0xb600, - 0x080c, 0x4c28, 0x00ee, 0x0010, 0x080c, 0x2cd1, 0x00de, 0x0860, - 0x080c, 0x9021, 0x1158, 0x2001, 0x0004, 0x080c, 0x4f6f, 0x6003, - 0x0001, 0x6007, 0x0003, 0x080c, 0x6d45, 0x0020, 0x080c, 0x8ca5, - 0x080c, 0x8e82, 0x0005, 0x0469, 0x1158, 0x2001, 0x0008, 0x080c, - 0x4f6f, 0x6003, 0x0001, 0x6007, 0x0005, 0x080c, 0x6d45, 0x0010, - 0x080c, 0x8e82, 0x0005, 0x00e9, 0x1158, 0x2001, 0x000a, 0x080c, - 0x4f6f, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x6d45, 0x0010, - 0x080c, 0x8e82, 0x0005, 0x2009, 0xbc8e, 0x2104, 0xa086, 0x0003, - 0x1138, 0x2009, 0xbc8f, 0x2104, 0xa084, 0xff00, 0xa086, 0x2a00, - 0x0005, 0xa085, 0x0001, 0x0005, 0x00c6, 0x0016, 0xac88, 0x0006, - 0x2164, 0x080c, 0x502a, 0x001e, 0x00ce, 0x0005, 0x00f6, 0x00e6, - 0x00d6, 0x0036, 0x0016, 0x6018, 0x2068, 0x2071, 0xb635, 0x2e04, - 0xa085, 0x0003, 0x2072, 0x080c, 0x90b2, 0x0560, 0x2009, 0xb635, - 0x2104, 0xc0cd, 0x200a, 0x2001, 0xb653, 0x2004, 0xd0a4, 0x0158, - 0xa006, 0x2020, 0x2009, 0x002a, 0x080c, 0xb1a4, 0x2001, 0xb60c, - 0x200c, 0xc195, 0x2102, 0x2019, 0x002a, 0x2009, 0x0001, 0x080c, - 0x2ca4, 0x2071, 0xb600, 0x080c, 0x2aed, 0x00c6, 0x0156, 0x20a9, - 0x0081, 0x2009, 0x007f, 0x080c, 0x2dcc, 0x8108, 0x1f04, 0x9063, - 0x015e, 0x00ce, 0x080c, 0x9024, 0x6813, 0x00ff, 0x6817, 0xfffe, - 0x2071, 0xbc80, 0x2079, 0x0100, 0x2e04, 0xa084, 0x00ff, 0x2069, - 0xb61c, 0x206a, 0x78e6, 0x0006, 0x8e70, 0x2e04, 0x2069, 0xb61d, - 0x206a, 0x78ea, 0x7832, 0x7836, 0x2010, 0xa084, 0xff00, 0x001e, - 0xa105, 0x2009, 0xb628, 0x200a, 0x2200, 0xa084, 0x00ff, 0x2008, - 0x080c, 0x287c, 0x080c, 0x5b41, 0x0170, 0x2069, 0xbc8e, 0x2071, - 0xb8b2, 0x6810, 0x2072, 0x6814, 0x7006, 0x6818, 0x700a, 0x681c, - 0x700e, 0x080c, 0xa08e, 0x0040, 0x2001, 0x0006, 0x080c, 0x4f6f, - 0x080c, 0x2cf7, 0x080c, 0x86a4, 0x001e, 0x003e, 0x00de, 0x00ee, - 0x00fe, 0x0005, 0x0026, 0x0036, 0x00e6, 0x0156, 0x2019, 0xb628, - 0x231c, 0x83ff, 0x01e8, 0x2071, 0xbc80, 0x2e14, 0xa294, 0x00ff, - 0x7004, 0xa084, 0xff00, 0xa205, 0xa306, 0x1190, 0x2011, 0xbc96, - 0xad98, 0x000a, 0x20a9, 0x0004, 0x080c, 0x9166, 0x1148, 0x2011, - 0xbc9a, 0xad98, 0x0006, 0x20a9, 0x0004, 0x080c, 0x9166, 0x1100, - 0x015e, 0x00ee, 0x003e, 0x002e, 0x0005, 0x00e6, 0x2071, 0xbc8c, - 0x7004, 0xa086, 0x0014, 0x11a8, 0x7008, 0xa086, 0x0800, 0x1188, - 0x700c, 0xd0ec, 0x0160, 0xa084, 0x0f00, 0xa086, 0x0100, 0x1138, - 0x7024, 0xd0a4, 0x1110, 0xd0ac, 0x0110, 0xa006, 0x0010, 0xa085, - 0x0001, 0x00ee, 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0056, - 0x0046, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2029, 0xb8ea, - 0x252c, 0x2021, 0xb8f0, 0x2424, 0x2061, 0xbe00, 0x2071, 0xb600, - 0x7248, 0x7068, 0xa202, 0x16f0, 0x080c, 0xb1cc, 0x05a0, 0x671c, - 0xa786, 0x0001, 0x0580, 0xa786, 0x0007, 0x0568, 0x2500, 0xac06, - 0x0550, 0x2400, 0xac06, 0x0538, 0x00c6, 0x6000, 0xa086, 0x0004, - 0x1110, 0x080c, 0x1952, 0xa786, 0x0008, 0x1148, 0x080c, 0x9f14, - 0x1130, 0x00ce, 0x080c, 0x8ca5, 0x080c, 0x9ed9, 0x00a0, 0x6010, - 0x2068, 0x080c, 0x9d16, 0x0160, 0xa786, 0x0003, 0x11e8, 0x6837, - 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x547a, 0x080c, 0x9ecd, - 0x080c, 0x9ed9, 0x00ce, 0xace0, 0x0018, 0x705c, 0xac02, 0x1210, - 0x0804, 0x9110, 0x012e, 0x000e, 0x002e, 0x004e, 0x005e, 0x007e, - 0x00ce, 0x00de, 0x00ee, 0x0005, 0xa786, 0x0006, 0x1118, 0x080c, - 0xb155, 0x0c30, 0xa786, 0x000a, 0x09e0, 0x08c8, 0x220c, 0x2304, - 0xa106, 0x1130, 0x8210, 0x8318, 0x1f04, 0x9166, 0xa006, 0x0005, - 0x2304, 0xa102, 0x0218, 0x2001, 0x0001, 0x0010, 0x2001, 0x0000, - 0xa18d, 0x0001, 0x0005, 0x6004, 0xa08a, 0x0080, 0x1a0c, 0x151a, - 0x080c, 0x9f03, 0x0120, 0x080c, 0x9f14, 0x0168, 0x0028, 0x080c, - 0x2cf7, 0x080c, 0x9f14, 0x0138, 0x080c, 0x7102, 0x080c, 0x86a4, - 0x080c, 0x71e5, 0x0005, 0x080c, 0x8ca5, 0x0cb0, 0xa182, 0x0040, - 0x0002, 0x91ac, 0x91ac, 0x91ac, 0x91ac, 0x91ac, 0x91ac, 0x91ac, - 0x91ac, 0x91ac, 0x91ac, 0x91ac, 0x91ae, 0x91ae, 0x91ae, 0x91ae, - 0x91ac, 0x91ac, 0x91ac, 0x91ae, 0x080c, 0x151a, 0x600b, 0xffff, - 0x6003, 0x0001, 0x6106, 0x080c, 0x6cff, 0x0126, 0x2091, 0x8000, - 0x080c, 0x71e5, 0x012e, 0x0005, 0xa186, 0x0013, 0x1128, 0x6004, - 0xa082, 0x0040, 0x0804, 0x9248, 0xa186, 0x0027, 0x11e8, 0x080c, - 0x7102, 0x080c, 0x2cd1, 0x00d6, 0x6110, 0x2168, 0x080c, 0x9d16, - 0x0168, 0x6837, 0x0103, 0x684b, 0x0029, 0x6847, 0x0000, 0x694c, - 0xc1c5, 0x694e, 0x080c, 0x547a, 0x080c, 0x9ecd, 0x00de, 0x080c, - 0x86a4, 0x080c, 0x71e5, 0x0005, 0xa186, 0x0014, 0x1120, 0x6004, - 0xa082, 0x0040, 0x0428, 0xa186, 0x0046, 0x0138, 0xa186, 0x0045, - 0x0120, 0xa186, 0x0047, 0x190c, 0x151a, 0x2001, 0x0109, 0x2004, - 0xd084, 0x0198, 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, - 0x080c, 0x6be6, 0x002e, 0x001e, 0x000e, 0x012e, 0xe000, 0x6000, - 0xa086, 0x0002, 0x1110, 0x0804, 0x9286, 0x080c, 0x86ef, 0x0005, - 0x0002, 0x9226, 0x9224, 0x9224, 0x9224, 0x9224, 0x9224, 0x9224, - 0x9224, 0x9224, 0x9224, 0x9224, 0x9241, 0x9241, 0x9241, 0x9241, - 0x9224, 0x9241, 0x9224, 0x9241, 0x080c, 0x151a, 0x080c, 0x7102, - 0x00d6, 0x6110, 0x2168, 0x080c, 0x9d16, 0x0168, 0x6837, 0x0103, - 0x684b, 0x0006, 0x6847, 0x0000, 0x6850, 0xc0ec, 0x6852, 0x080c, - 0x547a, 0x080c, 0x9ecd, 0x00de, 0x080c, 0x86a4, 0x080c, 0x71e5, - 0x0005, 0x080c, 0x7102, 0x080c, 0x86a4, 0x080c, 0x71e5, 0x0005, - 0x0002, 0x925e, 0x925c, 0x925c, 0x925c, 0x925c, 0x925c, 0x925c, - 0x925c, 0x925c, 0x925c, 0x925c, 0x9270, 0x9270, 0x9270, 0x9270, - 0x925c, 0x927f, 0x925c, 0x9270, 0x080c, 0x151a, 0x080c, 0x7102, - 0x2001, 0xb8b8, 0x2004, 0x603e, 0x6003, 0x0002, 0x080c, 0x71e5, - 0x6010, 0xa088, 0x0013, 0x2104, 0xa085, 0x0400, 0x200a, 0x0005, - 0x080c, 0x7102, 0x2001, 0xb8b6, 0x2004, 0x6016, 0x2001, 0xb8b8, - 0x2004, 0x603e, 0x6003, 0x000f, 0x080c, 0x71e5, 0x0005, 0x080c, - 0x7102, 0x080c, 0x86a4, 0x080c, 0x71e5, 0x0005, 0xa182, 0x0040, - 0x0002, 0x929c, 0x929c, 0x929c, 0x929c, 0x929c, 0x929e, 0x9386, - 0x93b5, 0x929c, 0x929c, 0x929c, 0x929c, 0x929c, 0x929c, 0x929c, - 0x929c, 0x929c, 0x929c, 0x929c, 0x080c, 0x151a, 0x00e6, 0x00d6, - 0x603f, 0x0000, 0x2071, 0xbc80, 0x7124, 0x610a, 0x2071, 0xbc8c, - 0x6110, 0x2168, 0x7614, 0xa6b4, 0x0fff, 0x86ff, 0x0904, 0x934c, - 0xa68c, 0x0c00, 0x0518, 0x00f6, 0x2c78, 0x080c, 0x5377, 0x00fe, - 0x01c8, 0x684c, 0xd0ac, 0x01b0, 0x6020, 0xd0dc, 0x1198, 0x6850, - 0xd0bc, 0x1180, 0x7318, 0x6814, 0xa306, 0x1904, 0x935f, 0x731c, - 0x6810, 0xa31e, 0x0138, 0xd6d4, 0x0904, 0x935f, 0x6b14, 0xa305, - 0x1904, 0x935f, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, - 0xa186, 0x0002, 0x0518, 0xa186, 0x0028, 0x1128, 0x080c, 0x9ef2, - 0x684b, 0x001c, 0x00e8, 0xd6dc, 0x01a0, 0x684b, 0x0015, 0x684c, - 0xd0ac, 0x0170, 0x6914, 0x6a10, 0x2100, 0xa205, 0x0148, 0x7018, - 0xa106, 0x1118, 0x701c, 0xa206, 0x0118, 0x6962, 0x6a5e, 0xc6dc, - 0x0038, 0xd6d4, 0x0118, 0x684b, 0x0007, 0x0010, 0x684b, 0x0000, - 0x6837, 0x0103, 0x6e46, 0xa01e, 0xd6c4, 0x01f0, 0xa686, 0x0100, - 0x1140, 0x2001, 0xbc99, 0x2004, 0xa005, 0x1118, 0xc6c4, 0x0804, - 0x92ad, 0x7328, 0x732c, 0x6b56, 0x83ff, 0x0170, 0xa38a, 0x0009, - 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, 0xbc98, 0xad90, - 0x0019, 0x080c, 0x99c9, 0x003e, 0xd6cc, 0x0904, 0x9375, 0x7124, - 0x695a, 0x81ff, 0x0904, 0x9375, 0xa192, 0x0021, 0x1260, 0x2071, - 0xbc98, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x080c, 0x99c9, - 0x080c, 0xa1f3, 0x04d0, 0x6838, 0xd0fc, 0x0120, 0x2009, 0x0020, - 0x695a, 0x0c68, 0x00f6, 0x2d78, 0x080c, 0x996e, 0x00fe, 0x080c, - 0xa1f3, 0x080c, 0x99b9, 0x0458, 0x00f6, 0x2c78, 0x080c, 0x5377, - 0x00fe, 0x0190, 0x684c, 0xd0ac, 0x0178, 0x6020, 0xd0dc, 0x1160, - 0x6850, 0xd0bc, 0x1148, 0x6810, 0x6914, 0xa105, 0x0128, 0x080c, - 0x9ff1, 0x00de, 0x00ee, 0x0408, 0x684b, 0x0000, 0x6837, 0x0103, - 0x6e46, 0x080c, 0x9523, 0x1148, 0x684c, 0xd0ac, 0x0130, 0x6810, - 0x6914, 0xa115, 0x0110, 0x080c, 0x953f, 0x080c, 0x547a, 0x6218, - 0x2268, 0x6a3c, 0x82ff, 0x0110, 0x8211, 0x6a3e, 0x080c, 0x9fbf, - 0x00de, 0x00ee, 0x1110, 0x080c, 0x86a4, 0x0005, 0x00f6, 0x6003, - 0x0003, 0x2079, 0xbc8c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x6010, - 0x2078, 0x784c, 0xd0ac, 0x0138, 0x6003, 0x0002, 0x00fe, 0x0005, - 0x2130, 0x2228, 0x0058, 0x2400, 0x797c, 0xa10a, 0x2300, 0x7a80, - 0xa213, 0x2600, 0xa102, 0x2500, 0xa203, 0x0e90, 0x7c12, 0x7b16, - 0x7e0a, 0x7d0e, 0x00fe, 0x603f, 0x0000, 0x2c10, 0x080c, 0x1fc5, - 0x080c, 0x6d62, 0x080c, 0x72a2, 0x0005, 0x2001, 0xb8b8, 0x2004, - 0x603e, 0x6003, 0x0004, 0x6110, 0x20e1, 0x0005, 0x3d18, 0x3e20, - 0x2c10, 0x080c, 0x1863, 0x0005, 0xa182, 0x0040, 0x0002, 0x93da, - 0x93da, 0x93da, 0x93da, 0x93da, 0x93dc, 0x946f, 0x93da, 0x93da, - 0x9485, 0x94eb, 0x93da, 0x93da, 0x93da, 0x93da, 0x9509, 0x93da, - 0x93da, 0x93da, 0x080c, 0x151a, 0x0076, 0x00f6, 0x00e6, 0x00d6, - 0x2071, 0xbc8c, 0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, 0x7e46, - 0x7f4c, 0xc7e5, 0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x82ff, 0x0110, - 0x8211, 0x6a3e, 0x86ff, 0x0904, 0x946a, 0xa694, 0xff00, 0xa284, - 0x0c00, 0x0120, 0x7018, 0x7862, 0x701c, 0x785e, 0xa284, 0x0300, - 0x0904, 0x946a, 0x080c, 0x15fd, 0x090c, 0x151a, 0x2d00, 0x784a, - 0x7f4c, 0xc7cd, 0x7f4e, 0x6837, 0x0103, 0x7838, 0x683a, 0x783c, - 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x0c00, 0x0120, 0x7318, - 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0180, - 0xa186, 0x0028, 0x1118, 0x684b, 0x001c, 0x0060, 0xd6dc, 0x0118, - 0x684b, 0x0015, 0x0038, 0xd6d4, 0x0118, 0x684b, 0x0007, 0x0010, - 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854, 0x6856, 0xa01e, - 0xd6c4, 0x0198, 0x7328, 0x732c, 0x6b56, 0x83ff, 0x0170, 0xa38a, - 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, 0xbc98, - 0xad90, 0x0019, 0x080c, 0x99c9, 0x003e, 0xd6cc, 0x01d8, 0x7124, - 0x695a, 0x81ff, 0x01b8, 0xa192, 0x0021, 0x1250, 0x2071, 0xbc98, - 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x080c, 0x99c9, 0x0050, - 0x7838, 0xd0fc, 0x0120, 0x2009, 0x0020, 0x695a, 0x0c78, 0x2d78, - 0x080c, 0x996e, 0x00de, 0x00ee, 0x00fe, 0x007e, 0x0005, 0x00f6, - 0x6003, 0x0003, 0x2079, 0xbc8c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08, - 0x6010, 0x2078, 0x7c12, 0x7b16, 0x7e0a, 0x7d0e, 0x00fe, 0x2c10, - 0x080c, 0x1fc5, 0x080c, 0x7dd9, 0x0005, 0x00d6, 0x00f6, 0x2c78, - 0x080c, 0x5377, 0x00fe, 0x0120, 0x2001, 0xb8b8, 0x2004, 0x603e, - 0x6003, 0x0002, 0x080c, 0x7198, 0x080c, 0x72a2, 0x6110, 0x2168, - 0x694c, 0xd1e4, 0x0904, 0x94e9, 0xd1cc, 0x0540, 0x6948, 0x6838, - 0xd0fc, 0x01e8, 0x0016, 0x684c, 0x0006, 0x6850, 0x0006, 0xad90, - 0x000d, 0xa198, 0x000d, 0x2009, 0x0020, 0x0156, 0x21a8, 0x2304, - 0x2012, 0x8318, 0x8210, 0x1f04, 0x94af, 0x015e, 0x000e, 0x6852, - 0x000e, 0x684e, 0x001e, 0x2168, 0x080c, 0x1624, 0x0428, 0x0016, - 0x080c, 0x1624, 0x00de, 0x080c, 0x99b9, 0x00f0, 0x6837, 0x0103, - 0x6944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x0180, 0xa086, 0x0028, - 0x1118, 0x684b, 0x001c, 0x0070, 0xd1dc, 0x0118, 0x684b, 0x0015, - 0x0048, 0xd1d4, 0x0118, 0x684b, 0x0007, 0x0020, 0x684b, 0x0000, - 0x080c, 0x9523, 0x080c, 0x547a, 0x080c, 0x9fbf, 0x1110, 0x080c, - 0x86a4, 0x00de, 0x0005, 0x2019, 0x0001, 0x080c, 0x806b, 0x6003, - 0x0002, 0x00d6, 0x6010, 0x2068, 0x080c, 0x9d16, 0x0140, 0x6808, - 0x612c, 0xa10a, 0x612e, 0x680c, 0x6128, 0xa10b, 0x612a, 0x00de, - 0x2001, 0xb8b8, 0x2004, 0x603e, 0x080c, 0x7198, 0x080c, 0x72a2, - 0x0005, 0x080c, 0x7198, 0x080c, 0x2cd1, 0x00d6, 0x6110, 0x2168, - 0x080c, 0x9d16, 0x0150, 0x6837, 0x0103, 0x684b, 0x0029, 0x6847, - 0x0000, 0x080c, 0x547a, 0x080c, 0x9ecd, 0x00de, 0x080c, 0x86a4, - 0x080c, 0x72a2, 0x0005, 0x684c, 0xd0b4, 0x01c0, 0x602c, 0x697c, - 0xa112, 0x6028, 0x6980, 0xa10b, 0x2100, 0xa205, 0x0168, 0x684b, - 0x0015, 0xd1fc, 0x0138, 0x684b, 0x0007, 0x8212, 0x8210, 0x810a, - 0xa189, 0x0000, 0x6962, 0x6a5e, 0xa085, 0x0001, 0x0005, 0x684b, - 0x0015, 0xd1fc, 0x0138, 0x684b, 0x0007, 0x8002, 0x8000, 0x810a, - 0xa189, 0x0000, 0x6962, 0x685e, 0x0005, 0xa182, 0x0040, 0x0002, - 0x9563, 0x9563, 0x9563, 0x9563, 0x9563, 0x9565, 0x9563, 0x9620, - 0x962c, 0x9563, 0x9563, 0x9563, 0x9563, 0x9563, 0x9563, 0x9563, - 0x9563, 0x9563, 0x9563, 0x080c, 0x151a, 0x0076, 0x00f6, 0x00e6, - 0x00d6, 0x2071, 0xbc8c, 0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, - 0x00f6, 0x2c78, 0x080c, 0x5377, 0x00fe, 0x0150, 0xa684, 0x00ff, - 0x1138, 0x6020, 0xd0f4, 0x0120, 0x080c, 0x9ff1, 0x0804, 0x961b, - 0x7e46, 0x7f4c, 0xc7e5, 0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x82ff, - 0x0110, 0x8211, 0x6a3e, 0x86ff, 0x0904, 0x9611, 0xa694, 0xff00, - 0xa284, 0x0c00, 0x0120, 0x7018, 0x7862, 0x701c, 0x785e, 0xa284, - 0x0300, 0x0904, 0x960f, 0xa686, 0x0100, 0x1140, 0x2001, 0xbc99, - 0x2004, 0xa005, 0x1118, 0xc6c4, 0x7e46, 0x0c28, 0x080c, 0x15fd, - 0x090c, 0x151a, 0x2d00, 0x784a, 0x7f4c, 0xa7bd, 0x0200, 0x7f4e, - 0x6837, 0x0103, 0x7838, 0x683a, 0x783c, 0x683e, 0x7840, 0x6842, - 0x6e46, 0xa68c, 0x0c00, 0x0120, 0x7318, 0x6b62, 0x731c, 0x6b5e, - 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0180, 0xa186, 0x0028, 0x1118, - 0x684b, 0x001c, 0x0060, 0xd6dc, 0x0118, 0x684b, 0x0015, 0x0038, - 0xd6d4, 0x0118, 0x684b, 0x0007, 0x0010, 0x684b, 0x0000, 0x6f4e, - 0x7850, 0x6852, 0x7854, 0x6856, 0xa01e, 0xd6c4, 0x0198, 0x7328, - 0x732c, 0x6b56, 0x83ff, 0x0170, 0xa38a, 0x0009, 0x0210, 0x2019, - 0x0008, 0x0036, 0x2308, 0x2019, 0xbc98, 0xad90, 0x0019, 0x080c, - 0x99c9, 0x003e, 0xd6cc, 0x01d8, 0x7124, 0x695a, 0x81ff, 0x01b8, - 0xa192, 0x0021, 0x1250, 0x2071, 0xbc98, 0x831c, 0x2300, 0xae18, - 0xad90, 0x001d, 0x080c, 0x99c9, 0x0050, 0x7838, 0xd0fc, 0x0120, - 0x2009, 0x0020, 0x695a, 0x0c78, 0x2d78, 0x080c, 0x996e, 0xd6dc, - 0x1110, 0xa006, 0x0030, 0x2001, 0x0001, 0x2071, 0xbc8c, 0x7218, - 0x731c, 0x080c, 0x18b6, 0x00de, 0x00ee, 0x00fe, 0x007e, 0x0005, - 0x2001, 0xb8b8, 0x2004, 0x603e, 0x20e1, 0x0005, 0x3d18, 0x3e20, - 0x2c10, 0x080c, 0x1863, 0x0005, 0x2001, 0xb8b8, 0x2004, 0x603e, - 0x00d6, 0x6003, 0x0002, 0x6110, 0x2168, 0x694c, 0xd1e4, 0x0904, - 0x9737, 0x603f, 0x0000, 0x00f6, 0x2c78, 0x080c, 0x5377, 0x00fe, - 0x0560, 0x6814, 0x6910, 0xa115, 0x0540, 0x6a60, 0xa206, 0x1118, - 0x685c, 0xa106, 0x0510, 0x684c, 0xc0e4, 0x684e, 0x6847, 0x0000, - 0x6863, 0x0000, 0x685f, 0x0000, 0x6020, 0xd0f4, 0x1158, 0x697c, - 0x6810, 0xa102, 0x603a, 0x6980, 0x6814, 0xa103, 0x6036, 0x6020, - 0xc0f5, 0x6022, 0x00d6, 0x6018, 0x2068, 0x683c, 0x8000, 0x683e, - 0x00de, 0x080c, 0x9ff1, 0x0804, 0x9737, 0x694c, 0xd1cc, 0x0904, - 0x9707, 0x6948, 0x6838, 0xd0fc, 0x0904, 0x96ca, 0x0016, 0x684c, - 0x0006, 0x6850, 0x0006, 0x00f6, 0x2178, 0x7944, 0xa184, 0x00ff, - 0xa0b6, 0x0002, 0x01e0, 0xa086, 0x0028, 0x1128, 0x684b, 0x001c, - 0x784b, 0x001c, 0x00e8, 0xd1dc, 0x0158, 0x684b, 0x0015, 0x784b, - 0x0015, 0x080c, 0xa17b, 0x0118, 0x7944, 0xc1dc, 0x7946, 0x0080, - 0xd1d4, 0x0128, 0x684b, 0x0007, 0x784b, 0x0007, 0x0048, 0x684c, - 0xd0ac, 0x0130, 0x6810, 0x6914, 0xa115, 0x0110, 0x080c, 0x953f, - 0x6848, 0x784a, 0x6860, 0x7862, 0x685c, 0x785e, 0xad90, 0x000d, - 0xaf98, 0x000d, 0x2009, 0x0020, 0x0156, 0x21a8, 0x2304, 0x2012, - 0x8318, 0x8210, 0x1f04, 0x96b6, 0x015e, 0x00fe, 0x000e, 0x6852, - 0x000e, 0x684e, 0x080c, 0xa1f3, 0x001e, 0x2168, 0x080c, 0x1624, - 0x0804, 0x9732, 0x0016, 0x00f6, 0x2178, 0x7944, 0xa184, 0x00ff, - 0xa0b6, 0x0002, 0x01e0, 0xa086, 0x0028, 0x1128, 0x684b, 0x001c, - 0x784b, 0x001c, 0x00e8, 0xd1dc, 0x0158, 0x684b, 0x0015, 0x784b, - 0x0015, 0x080c, 0xa17b, 0x0118, 0x7944, 0xc1dc, 0x7946, 0x0080, - 0xd1d4, 0x0128, 0x684b, 0x0007, 0x784b, 0x0007, 0x0048, 0x684c, - 0xd0ac, 0x0130, 0x6810, 0x6914, 0xa115, 0x0110, 0x080c, 0x953f, - 0x6860, 0x7862, 0x685c, 0x785e, 0x684c, 0x784e, 0x00fe, 0x080c, - 0x1624, 0x00de, 0x080c, 0xa1f3, 0x080c, 0x99b9, 0x0458, 0x6837, - 0x0103, 0x6944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x01b0, 0xa086, - 0x0028, 0x1118, 0x684b, 0x001c, 0x00d8, 0xd1dc, 0x0148, 0x684b, - 0x0015, 0x080c, 0xa17b, 0x0118, 0x6944, 0xc1dc, 0x6946, 0x0080, - 0xd1d4, 0x0118, 0x684b, 0x0007, 0x0058, 0x684b, 0x0000, 0x684c, - 0xd0ac, 0x0130, 0x6810, 0x6914, 0xa115, 0x0110, 0x080c, 0x953f, - 0x080c, 0x547a, 0x080c, 0x9fbf, 0x1110, 0x080c, 0x86a4, 0x00de, - 0x0005, 0x080c, 0x7102, 0x0010, 0x080c, 0x7198, 0x080c, 0x9d16, - 0x01c0, 0x00d6, 0x6110, 0x2168, 0x6837, 0x0103, 0x2009, 0xb60c, - 0x210c, 0xd18c, 0x11c0, 0xd184, 0x1198, 0x6108, 0x694a, 0xa18e, - 0x0029, 0x1110, 0x080c, 0xb43c, 0x6847, 0x0000, 0x080c, 0x547a, - 0x00de, 0x080c, 0x86a4, 0x080c, 0x71e5, 0x080c, 0x72a2, 0x0005, - 0x684b, 0x0004, 0x0c88, 0x684b, 0x0004, 0x0c70, 0xa182, 0x0040, - 0x0002, 0x977c, 0x977c, 0x977c, 0x977c, 0x977c, 0x977e, 0x977c, - 0x9781, 0x977c, 0x977c, 0x977c, 0x977c, 0x977c, 0x977c, 0x977c, - 0x977c, 0x977c, 0x977c, 0x977c, 0x080c, 0x151a, 0x080c, 0x86a4, - 0x0005, 0x0006, 0x0026, 0xa016, 0x080c, 0x1863, 0x002e, 0x000e, - 0x0005, 0xa182, 0x0085, 0x0002, 0x9795, 0x9793, 0x9793, 0x97a1, - 0x9793, 0x9793, 0x9793, 0x080c, 0x151a, 0x6003, 0x0001, 0x6106, - 0x080c, 0x6cff, 0x0126, 0x2091, 0x8000, 0x080c, 0x71e5, 0x012e, - 0x0005, 0x0026, 0x0056, 0x00d6, 0x00e6, 0x2071, 0xbc80, 0x7224, - 0x6212, 0x7220, 0x080c, 0x9d06, 0x01a0, 0x2268, 0x6800, 0xa086, - 0x0000, 0x0178, 0x6018, 0x6d18, 0xa52e, 0x1158, 0x00c6, 0x2d60, - 0x080c, 0x99d9, 0x00ce, 0x0128, 0x6803, 0x0002, 0x6007, 0x0086, - 0x0010, 0x6007, 0x0087, 0x6003, 0x0001, 0x080c, 0x6cff, 0x080c, - 0x71e5, 0x00f6, 0x2278, 0x080c, 0x5377, 0x00fe, 0x0150, 0x6820, - 0xd0ec, 0x0138, 0x00c6, 0x2260, 0x603f, 0x0000, 0x080c, 0x9ff1, - 0x00ce, 0x00ee, 0x00de, 0x005e, 0x002e, 0x0005, 0xa186, 0x0013, - 0x1160, 0x6004, 0xa08a, 0x0085, 0x0a0c, 0x151a, 0xa08a, 0x008c, - 0x1a0c, 0x151a, 0xa082, 0x0085, 0x0072, 0xa186, 0x0027, 0x0120, - 0xa186, 0x0014, 0x190c, 0x151a, 0x080c, 0x7102, 0x080c, 0x9ed9, - 0x080c, 0x71e5, 0x0005, 0x9802, 0x9804, 0x9804, 0x9802, 0x9802, - 0x9802, 0x9802, 0x080c, 0x151a, 0x080c, 0x7102, 0x080c, 0x9ed9, - 0x080c, 0x71e5, 0x0005, 0xa186, 0x0013, 0x1128, 0x6004, 0xa082, - 0x0085, 0x2008, 0x04a8, 0xa186, 0x0027, 0x11e8, 0x080c, 0x7102, - 0x080c, 0x2cd1, 0x00d6, 0x6010, 0x2068, 0x080c, 0x9d16, 0x0150, - 0x6837, 0x0103, 0x6847, 0x0000, 0x684b, 0x0029, 0x080c, 0x547a, - 0x080c, 0x9ecd, 0x00de, 0x080c, 0x86a4, 0x080c, 0x71e5, 0x0005, - 0x080c, 0x86ef, 0x0ce0, 0xa186, 0x0014, 0x1dd0, 0x080c, 0x7102, - 0x00d6, 0x6010, 0x2068, 0x080c, 0x9d16, 0x0d60, 0x6837, 0x0103, - 0x6847, 0x0000, 0x684b, 0x0006, 0x6850, 0xc0ec, 0x6852, 0x08f0, - 0x0002, 0x9852, 0x9850, 0x9850, 0x9850, 0x9850, 0x9850, 0x986a, - 0x080c, 0x151a, 0x080c, 0x7102, 0x6030, 0xa08c, 0xff00, 0x810f, - 0xa186, 0x0039, 0x0118, 0xa186, 0x0035, 0x1118, 0x2001, 0xb8b6, - 0x0010, 0x2001, 0xb8b7, 0x2004, 0x6016, 0x6003, 0x000c, 0x080c, - 0x71e5, 0x0005, 0x080c, 0x7102, 0x6030, 0xa08c, 0xff00, 0x810f, - 0xa186, 0x0039, 0x0118, 0xa186, 0x0035, 0x1118, 0x2001, 0xb8b6, - 0x0010, 0x2001, 0xb8b7, 0x2004, 0x6016, 0x6003, 0x000e, 0x080c, - 0x71e5, 0x0005, 0xa182, 0x008c, 0x1220, 0xa182, 0x0085, 0x0208, - 0x001a, 0x080c, 0x86ef, 0x0005, 0x9893, 0x9893, 0x9893, 0x9893, - 0x9895, 0x98ee, 0x9893, 0x080c, 0x151a, 0x00d6, 0x00f6, 0x2c78, - 0x080c, 0x5377, 0x00fe, 0x0168, 0x6030, 0xa08c, 0xff00, 0x810f, - 0xa186, 0x0039, 0x0118, 0xa186, 0x0035, 0x1118, 0x00de, 0x0804, - 0x9901, 0x080c, 0x9d16, 0x1118, 0x080c, 0x9ecd, 0x00f0, 0x6010, - 0x2068, 0x684c, 0xd0e4, 0x1110, 0x080c, 0x9ecd, 0x6837, 0x0103, - 0x6850, 0xd0b4, 0x0128, 0x684b, 0x0006, 0xc0ec, 0x6852, 0x0048, - 0xd0bc, 0x0118, 0x684b, 0x0002, 0x0020, 0x684b, 0x0005, 0x080c, - 0x9f8e, 0x6847, 0x0000, 0x080c, 0x547a, 0x2c68, 0x080c, 0x864e, - 0x01c0, 0x6003, 0x0001, 0x6007, 0x001e, 0x600b, 0xffff, 0x2009, - 0xbc8e, 0x210c, 0x6136, 0x2009, 0xbc8f, 0x210c, 0x613a, 0x6918, - 0x611a, 0x080c, 0xa0e3, 0x6950, 0x6152, 0x601f, 0x0001, 0x080c, - 0x6cff, 0x2d60, 0x080c, 0x86a4, 0x00de, 0x0005, 0x00f6, 0x2c78, - 0x080c, 0x5377, 0x00fe, 0x0598, 0x6030, 0xa08c, 0xff00, 0x810f, - 0xa186, 0x0035, 0x0130, 0xa186, 0x001e, 0x0118, 0xa186, 0x0039, - 0x1530, 0x00d6, 0x2c68, 0x080c, 0xa1c6, 0x1904, 0x9946, 0x080c, - 0x864e, 0x01d8, 0x6106, 0x6003, 0x0001, 0x601f, 0x0001, 0x6918, - 0x611a, 0x6928, 0x612a, 0x692c, 0x612e, 0x6930, 0xa18c, 0x00ff, - 0x6132, 0x6934, 0x6136, 0x6938, 0x613a, 0x6950, 0x6152, 0x080c, - 0xa0e3, 0x080c, 0x6cff, 0x080c, 0x71e5, 0x2d60, 0x00f8, 0x00d6, - 0x6010, 0x2068, 0x080c, 0x9d16, 0x01c8, 0x6837, 0x0103, 0x6850, - 0xd0b4, 0x0128, 0xc0ec, 0x6852, 0x684b, 0x0006, 0x0048, 0xd0bc, - 0x0118, 0x684b, 0x0002, 0x0020, 0x684b, 0x0005, 0x080c, 0x9f8e, - 0x6847, 0x0000, 0x080c, 0x547a, 0x080c, 0x9ecd, 0x00de, 0x080c, - 0x86a4, 0x0005, 0x0016, 0x00d6, 0x6010, 0x2068, 0x080c, 0x9d16, - 0x0140, 0x6837, 0x0103, 0x684b, 0x0028, 0x6847, 0x0000, 0x080c, - 0x547a, 0x00de, 0x001e, 0xa186, 0x0013, 0x0148, 0xa186, 0x0014, - 0x0130, 0xa186, 0x0027, 0x0118, 0x080c, 0x86ef, 0x0030, 0x080c, - 0x7102, 0x080c, 0x9ed9, 0x080c, 0x71e5, 0x0005, 0x0056, 0x0066, - 0x00d6, 0x00f6, 0x2029, 0x0001, 0xa182, 0x0101, 0x1208, 0x0010, - 0x2009, 0x0100, 0x2130, 0x2069, 0xbc98, 0x831c, 0x2300, 0xad18, - 0x2009, 0x0020, 0xaf90, 0x001d, 0x080c, 0x99c9, 0xa6b2, 0x0020, - 0x7804, 0xa06d, 0x0110, 0x080c, 0x1624, 0x080c, 0x15fd, 0x0500, - 0x8528, 0x6837, 0x0110, 0x683b, 0x0000, 0x2d20, 0x7c06, 0xa68a, - 0x003d, 0x1228, 0x2608, 0xad90, 0x000f, 0x0459, 0x0088, 0xa6b2, - 0x003c, 0x2009, 0x003c, 0x2d78, 0xad90, 0x000f, 0x0411, 0x0c28, - 0x00fe, 0x852f, 0xa5ad, 0x0003, 0x7d36, 0xa5ac, 0x0000, 0x0028, - 0x00fe, 0x852f, 0xa5ad, 0x0003, 0x7d36, 0x00de, 0x006e, 0x005e, - 0x0005, 0x00f6, 0x8dff, 0x0158, 0x6804, 0xa07d, 0x0130, 0x6807, - 0x0000, 0x080c, 0x547a, 0x2f68, 0x0cb8, 0x080c, 0x547a, 0x00fe, - 0x0005, 0x0156, 0xa184, 0x0001, 0x0108, 0x8108, 0x810c, 0x21a8, - 0x2304, 0x8007, 0x2012, 0x8318, 0x8210, 0x1f04, 0x99d0, 0x015e, - 0x0005, 0x0066, 0x0126, 0x2091, 0x8000, 0x2031, 0x0001, 0x601c, - 0xa084, 0x000f, 0x0083, 0x012e, 0x006e, 0x0005, 0x0126, 0x2091, - 0x8000, 0x0066, 0x2031, 0x0000, 0x601c, 0xa084, 0x000f, 0x001b, - 0x006e, 0x012e, 0x0005, 0x9a10, 0x9a10, 0x9a0b, 0x9a32, 0x99fe, - 0x9a0b, 0x9a32, 0x9a0b, 0x9a0b, 0x99fe, 0x9a0b, 0x080c, 0x151a, - 0x0036, 0x2019, 0x0010, 0x080c, 0xad9c, 0x601f, 0x0006, 0x6003, - 0x0007, 0x003e, 0x0005, 0xa006, 0x0005, 0xa085, 0x0001, 0x0005, - 0x00d6, 0x86ff, 0x11d8, 0x6010, 0x2068, 0x080c, 0x9d16, 0x01c0, - 0x6834, 0xa086, 0x0139, 0x1128, 0x684b, 0x0005, 0x6853, 0x0000, - 0x0028, 0xa00e, 0x2001, 0x0005, 0x080c, 0x554d, 0x080c, 0x9f8e, - 0x080c, 0x547a, 0x080c, 0x86a4, 0xa085, 0x0001, 0x00de, 0x0005, - 0xa006, 0x0ce0, 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x151a, 0x000b, - 0x0005, 0x9a49, 0x9a6a, 0x9a4b, 0x9a89, 0x9a67, 0x9a49, 0x9a0b, - 0x9a10, 0x9a10, 0x9a0b, 0x9a0b, 0x9a0b, 0x9a0b, 0x9a0b, 0x9a0b, - 0x9a0b, 0x080c, 0x151a, 0x86ff, 0x11b8, 0x601c, 0xa086, 0x0006, - 0x0198, 0x00d6, 0x6010, 0x2068, 0x080c, 0x9d16, 0x0110, 0x080c, - 0x9f8e, 0x00de, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, - 0x080c, 0x6cff, 0x080c, 0x71e5, 0xa085, 0x0001, 0x0005, 0x080c, - 0x1952, 0x0c08, 0x00e6, 0x2071, 0xb8e1, 0x7024, 0xac06, 0x1110, - 0x080c, 0x7fe0, 0x601c, 0xa084, 0x000f, 0xa086, 0x0006, 0x1150, - 0x0086, 0x0096, 0x2049, 0x0001, 0x2c40, 0x080c, 0x81b7, 0x009e, - 0x008e, 0x0010, 0x080c, 0x7ed1, 0x00ee, 0x1928, 0x080c, 0x9a0b, - 0x0005, 0x0036, 0x00e6, 0x2071, 0xb8e1, 0x703c, 0xac06, 0x1140, - 0x2019, 0x0000, 0x080c, 0x806b, 0x00ee, 0x003e, 0x0804, 0x9a4b, - 0x080c, 0x82e4, 0x00ee, 0x003e, 0x1904, 0x9a4b, 0x080c, 0x9a0b, - 0x0005, 0x00c6, 0x601c, 0xa084, 0x000f, 0x0013, 0x00ce, 0x0005, - 0x9aba, 0x9b27, 0x9c75, 0x9ac5, 0x9ed9, 0x9aba, 0xad8e, 0xa20a, - 0x9b27, 0x9ab3, 0x9ce0, 0x080c, 0x151a, 0x080c, 0x9f14, 0x1110, - 0x080c, 0x8ca5, 0x0005, 0x080c, 0x7102, 0x080c, 0x71e5, 0x080c, - 0x86a4, 0x0005, 0x6017, 0x0001, 0x0005, 0x080c, 0x9d16, 0x0120, - 0x6010, 0xa080, 0x0019, 0x2c02, 0x6000, 0xa08a, 0x0010, 0x1a0c, - 0x151a, 0x000b, 0x0005, 0x9ae3, 0x9ae5, 0x9b05, 0x9b17, 0x9b24, - 0x9ae3, 0x9aba, 0x9aba, 0x9aba, 0x9b17, 0x9b17, 0x9ae3, 0x9ae3, - 0x9ae3, 0x9ae3, 0x9b21, 0x080c, 0x151a, 0x00e6, 0x6010, 0x2070, - 0x7050, 0xc0b5, 0x7052, 0x2071, 0xb8e1, 0x7024, 0xac06, 0x0190, - 0x080c, 0x7ed1, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, - 0x2001, 0xb8b7, 0x2004, 0x6016, 0x080c, 0x6cff, 0x080c, 0x71e5, - 0x00ee, 0x0005, 0x6017, 0x0001, 0x0cd8, 0x00d6, 0x6010, 0x2068, - 0x6850, 0xc0b5, 0x6852, 0x00de, 0x6007, 0x0085, 0x6003, 0x000b, - 0x601f, 0x0002, 0x080c, 0x6cff, 0x080c, 0x71e5, 0x0005, 0x00d6, - 0x6017, 0x0001, 0x6010, 0x2068, 0x6850, 0xc0b5, 0x6852, 0x00de, - 0x0005, 0x080c, 0x86a4, 0x0005, 0x080c, 0x1952, 0x08f0, 0x6000, - 0xa08a, 0x0010, 0x1a0c, 0x151a, 0x000b, 0x0005, 0x9b3e, 0x9ac2, - 0x9b40, 0x9b3e, 0x9b40, 0x9b40, 0x9abb, 0x9b3e, 0x9ab5, 0x9ab5, - 0x9b3e, 0x9b3e, 0x9b3e, 0x9b3e, 0x9b3e, 0x9b3e, 0x080c, 0x151a, - 0x00d6, 0x6018, 0x2068, 0x6804, 0xa084, 0x00ff, 0x00de, 0xa08a, - 0x000c, 0x1a0c, 0x151a, 0x000b, 0x0005, 0x9b59, 0x9c1b, 0x9b5b, - 0x9b99, 0x9b5b, 0x9b99, 0x9b5b, 0x9b69, 0x9b59, 0x9b99, 0x9b59, - 0x9b85, 0x080c, 0x151a, 0x6004, 0xa08e, 0x0016, 0x05a8, 0xa08e, - 0x0004, 0x0590, 0xa08e, 0x0002, 0x0578, 0xa08e, 0x004b, 0x0904, - 0x9c17, 0x6004, 0x080c, 0x9f14, 0x0904, 0x9c34, 0xa08e, 0x0021, - 0x0904, 0x9c38, 0xa08e, 0x0022, 0x0904, 0x9c34, 0xa08e, 0x003d, - 0x0904, 0x9c38, 0xa08e, 0x0039, 0x0904, 0x9c3c, 0xa08e, 0x0035, - 0x0904, 0x9c3c, 0xa08e, 0x001e, 0x0188, 0xa08e, 0x0001, 0x1150, - 0x00d6, 0x6018, 0x2068, 0x6804, 0xa084, 0x00ff, 0x00de, 0xa086, - 0x0006, 0x0110, 0x080c, 0x2cd1, 0x080c, 0x8ca5, 0x080c, 0x9ed9, - 0x0005, 0x00c6, 0x00d6, 0x6104, 0xa186, 0x0016, 0x0904, 0x9c08, - 0xa186, 0x0002, 0x15d8, 0x2001, 0xb635, 0x2004, 0xd08c, 0x1198, - 0x080c, 0x5b41, 0x1180, 0x2001, 0xb89f, 0x2003, 0x0001, 0x2001, - 0xb600, 0x2003, 0x0001, 0xa085, 0x0001, 0x080c, 0x5b85, 0x080c, - 0x5a79, 0x0804, 0x9c5e, 0x6018, 0x2068, 0x2001, 0xb635, 0x2004, - 0xd0ac, 0x1904, 0x9c5e, 0x68a0, 0xd0bc, 0x1904, 0x9c5e, 0x6840, - 0xa084, 0x00ff, 0xa005, 0x0190, 0x8001, 0x6842, 0x6013, 0x0000, - 0x601f, 0x0007, 0x6017, 0x0398, 0x603f, 0x0000, 0x080c, 0x864e, - 0x0128, 0x2d00, 0x601a, 0x601f, 0x0001, 0x0450, 0x00de, 0x00ce, - 0x6004, 0xa08e, 0x0002, 0x11a8, 0x6018, 0xa080, 0x0028, 0x2004, - 0xa086, 0x007e, 0x1170, 0x2009, 0xb635, 0x2104, 0xc085, 0x200a, - 0x00e6, 0x2071, 0xb600, 0x080c, 0x4c28, 0x00ee, 0x080c, 0x8ca5, - 0x0020, 0x080c, 0x8ca5, 0x080c, 0x2cd1, 0x00e6, 0x0126, 0x2091, - 0x8000, 0x080c, 0x2cf7, 0x012e, 0x00ee, 0x080c, 0x9ed9, 0x0005, - 0x2001, 0x0002, 0x080c, 0x4f6f, 0x6003, 0x0001, 0x6007, 0x0002, - 0x080c, 0x6d45, 0x080c, 0x71e5, 0x00de, 0x00ce, 0x0c80, 0x080c, - 0x2cf7, 0x0804, 0x9b94, 0x00c6, 0x00d6, 0x6104, 0xa186, 0x0016, - 0x0d38, 0x6018, 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0904, - 0x9bde, 0x8001, 0x6842, 0x6003, 0x0001, 0x080c, 0x6d45, 0x080c, - 0x71e5, 0x00de, 0x00ce, 0x0898, 0x080c, 0x8ca5, 0x0804, 0x9b96, - 0x080c, 0x8cd3, 0x0804, 0x9b96, 0x00d6, 0x2c68, 0x6104, 0x080c, - 0xa1c6, 0x00de, 0x0118, 0x080c, 0x86a4, 0x00b8, 0x6004, 0x8007, - 0x6130, 0xa18c, 0x00ff, 0xa105, 0x6032, 0x6007, 0x0085, 0x6003, - 0x000b, 0x601f, 0x0002, 0x6038, 0x600a, 0x2001, 0xb8b7, 0x2004, - 0x6016, 0x080c, 0x6cff, 0x080c, 0x71e5, 0x0005, 0x00de, 0x00ce, - 0x080c, 0x8ca5, 0x080c, 0x2cd1, 0x00e6, 0x0126, 0x2091, 0x8000, - 0x080c, 0x2cf7, 0x6013, 0x0000, 0x601f, 0x0007, 0x6017, 0x0398, - 0x603f, 0x0000, 0x012e, 0x00ee, 0x0005, 0x6000, 0xa08a, 0x0010, - 0x1a0c, 0x151a, 0x000b, 0x0005, 0x9c8c, 0x9c8c, 0x9c8c, 0x9c8c, - 0x9c8c, 0x9c8c, 0x9c8c, 0x9c8c, 0x9c8c, 0x9aba, 0x9c8c, 0x9ac2, - 0x9c8e, 0x9ac2, 0x9c9b, 0x9c8c, 0x080c, 0x151a, 0x6004, 0xa086, - 0x008b, 0x0148, 0x6007, 0x008b, 0x6003, 0x000d, 0x080c, 0x6cff, - 0x080c, 0x71e5, 0x0005, 0x080c, 0x9ecd, 0x080c, 0x9d16, 0x0580, - 0x080c, 0x2cd1, 0x00d6, 0x080c, 0x9d16, 0x0168, 0x6010, 0x2068, - 0x6837, 0x0103, 0x684b, 0x0006, 0x6847, 0x0000, 0x6850, 0xc0ed, - 0x6852, 0x080c, 0x547a, 0x2c68, 0x080c, 0x864e, 0x0150, 0x6818, - 0x601a, 0x080c, 0xa0e3, 0x00c6, 0x2d60, 0x080c, 0x9ed9, 0x00ce, - 0x0008, 0x2d60, 0x00de, 0x6013, 0x0000, 0x601f, 0x0001, 0x6007, - 0x0001, 0x6003, 0x0001, 0x080c, 0x6d45, 0x080c, 0x71e5, 0x0078, - 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0118, 0xa186, - 0x0035, 0x1118, 0x080c, 0x2cd1, 0x08b0, 0x080c, 0x9ed9, 0x0005, - 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x151a, 0x000b, 0x0005, 0x9cf7, - 0x9cf7, 0x9cf7, 0x9cf9, 0x9cf9, 0x9cf7, 0x9cf7, 0x9cf7, 0x9cf7, - 0x9cf7, 0x9cf7, 0x9cf7, 0x9cf7, 0x9cf7, 0x9cf7, 0x9cf7, 0x080c, - 0x151a, 0x080c, 0x82e4, 0x190c, 0x151a, 0x6110, 0x2168, 0x684b, - 0x0006, 0x080c, 0x547a, 0x080c, 0x86a4, 0x0005, 0xa284, 0x0007, - 0x1158, 0xa282, 0xbe00, 0x0240, 0x2001, 0xb617, 0x2004, 0xa202, - 0x1218, 0xa085, 0x0001, 0x0005, 0xa006, 0x0ce8, 0x0026, 0x6210, - 0xa294, 0xf000, 0x002e, 0x0005, 0x00e6, 0x00c6, 0x0036, 0x0006, - 0x0126, 0x2091, 0x8000, 0x2061, 0xbe00, 0x2071, 0xb600, 0x7348, - 0x7068, 0xa302, 0x12a8, 0x601c, 0xa206, 0x1160, 0x080c, 0xa06e, - 0x0148, 0x080c, 0x9f14, 0x1110, 0x080c, 0x8ca5, 0x00c6, 0x080c, - 0x86a4, 0x00ce, 0xace0, 0x0018, 0x705c, 0xac02, 0x1208, 0x0c38, - 0x012e, 0x000e, 0x003e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x00c6, - 0x0016, 0xa188, 0xb735, 0x210c, 0x81ff, 0x0128, 0x2061, 0xb9f5, - 0x611a, 0x080c, 0x2cd1, 0xa006, 0x0010, 0xa085, 0x0001, 0x001e, - 0x00ce, 0x00ee, 0x0005, 0x00c6, 0x0056, 0x0126, 0x2091, 0x8000, - 0x00c6, 0x080c, 0x864e, 0x005e, 0x0180, 0x6612, 0x651a, 0x080c, - 0xa0e3, 0x601f, 0x0003, 0x2009, 0x004b, 0x080c, 0x86d3, 0xa085, - 0x0001, 0x012e, 0x005e, 0x00ce, 0x0005, 0xa006, 0x0cd0, 0x00c6, - 0x0056, 0x0126, 0x2091, 0x8000, 0x62a0, 0x00c6, 0x080c, 0x9f92, - 0x005e, 0x0550, 0x6013, 0x0000, 0x651a, 0x080c, 0xa0e3, 0x601f, - 0x0003, 0x0016, 0x00c6, 0x2560, 0x080c, 0x521c, 0x00ce, 0x080c, - 0x6e67, 0x0076, 0x2039, 0x0000, 0x080c, 0x6d74, 0x2c08, 0x080c, - 0xaf3e, 0x007e, 0x001e, 0xd184, 0x0128, 0x080c, 0x86a4, 0xa085, - 0x0001, 0x0030, 0x2009, 0x004c, 0x080c, 0x86d3, 0xa085, 0x0001, - 0x012e, 0x005e, 0x00ce, 0x0005, 0xa006, 0x0cd0, 0x00f6, 0x00c6, - 0x0046, 0x00c6, 0x080c, 0x864e, 0x2c78, 0x00ce, 0x0180, 0x7e12, - 0x2c00, 0x781a, 0x781f, 0x0003, 0x2021, 0x0005, 0x080c, 0x9e0c, - 0x2f60, 0x2009, 0x004d, 0x080c, 0x86d3, 0xa085, 0x0001, 0x004e, - 0x00ce, 0x00fe, 0x0005, 0x00f6, 0x00c6, 0x0046, 0x00c6, 0x080c, - 0x864e, 0x2c78, 0x00ce, 0x0178, 0x7e12, 0x2c00, 0x781a, 0x781f, - 0x0003, 0x2021, 0x0005, 0x0481, 0x2f60, 0x2009, 0x004e, 0x080c, - 0x86d3, 0xa085, 0x0001, 0x004e, 0x00ce, 0x00fe, 0x0005, 0x00f6, - 0x00c6, 0x0046, 0x00c6, 0x080c, 0x864e, 0x2c78, 0x00ce, 0x01c0, - 0x7e12, 0x2c00, 0x781a, 0x781f, 0x0003, 0x2021, 0x0004, 0x00a1, - 0x2001, 0xb8a0, 0x2004, 0xd0fc, 0x0120, 0x2f60, 0x080c, 0x86a4, - 0x0028, 0x2f60, 0x2009, 0x0052, 0x080c, 0x86d3, 0xa085, 0x0001, - 0x004e, 0x00ce, 0x00fe, 0x0005, 0x0096, 0x0076, 0x0126, 0x2091, - 0x8000, 0x080c, 0x51be, 0x0118, 0x2001, 0x9e11, 0x0028, 0x080c, - 0x518e, 0x0158, 0x2001, 0x9e17, 0x0006, 0xa00e, 0x2400, 0x080c, - 0x554d, 0x080c, 0x547a, 0x000e, 0x0807, 0x2418, 0x080c, 0x70a1, - 0x62a0, 0x0086, 0x2041, 0x0001, 0x2039, 0x0001, 0x2608, 0x080c, - 0x6e80, 0x008e, 0x080c, 0x6d74, 0x2f08, 0x2648, 0x080c, 0xaf3e, - 0x613c, 0x81ff, 0x090c, 0x6f35, 0x080c, 0x71e5, 0x012e, 0x007e, - 0x009e, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, - 0x864e, 0x001e, 0x0188, 0x660a, 0x611a, 0x080c, 0xa0e3, 0x601f, - 0x0001, 0x2d00, 0x6012, 0x2009, 0x001f, 0x080c, 0x86d3, 0xa085, - 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00c6, 0x0126, - 0x2091, 0x8000, 0x00c6, 0x080c, 0x864e, 0x001e, 0x0188, 0x660a, - 0x611a, 0x080c, 0xa0e3, 0x601f, 0x0008, 0x2d00, 0x6012, 0x2009, - 0x0021, 0x080c, 0x86d3, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, - 0xa006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, - 0x864e, 0x001e, 0x0188, 0x660a, 0x611a, 0x080c, 0xa0e3, 0x601f, - 0x0001, 0x2d00, 0x6012, 0x2009, 0x003d, 0x080c, 0x86d3, 0xa085, - 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00c6, 0x0126, - 0x2091, 0x8000, 0x00c6, 0x080c, 0x9f92, 0x001e, 0x0180, 0x611a, - 0x080c, 0xa0e3, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x0000, - 0x080c, 0x86d3, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, - 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x864e, - 0x001e, 0x0188, 0x660a, 0x611a, 0x080c, 0xa0e3, 0x601f, 0x0001, - 0x2d00, 0x6012, 0x2009, 0x0044, 0x080c, 0x86d3, 0xa085, 0x0001, - 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x0026, 0x00d6, 0x6218, - 0x2268, 0x6a3c, 0x82ff, 0x0110, 0x8211, 0x6a3e, 0x00de, 0x002e, - 0x0005, 0x0006, 0x6000, 0xa086, 0x0000, 0x0190, 0x6013, 0x0000, - 0x601f, 0x0007, 0x2001, 0xb8b6, 0x2004, 0x0006, 0xa082, 0x0051, - 0x000e, 0x0208, 0x8004, 0x6016, 0x080c, 0xb3f6, 0x603f, 0x0000, - 0x000e, 0x0005, 0x0066, 0x00c6, 0x00d6, 0x2031, 0xb653, 0x2634, - 0xd6e4, 0x0128, 0x6618, 0x2660, 0x6e48, 0x080c, 0x5147, 0x00de, - 0x00ce, 0x006e, 0x0005, 0x0006, 0x0016, 0x6004, 0xa08e, 0x0002, - 0x0140, 0xa08e, 0x0003, 0x0128, 0xa08e, 0x0004, 0x0110, 0xa085, - 0x0001, 0x001e, 0x000e, 0x0005, 0x0006, 0x00d6, 0x6010, 0xa06d, - 0x0148, 0x6834, 0xa086, 0x0139, 0x0138, 0x6838, 0xd0fc, 0x0110, - 0xa006, 0x0010, 0xa085, 0x0001, 0x00de, 0x000e, 0x0005, 0x00c6, - 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x864e, 0x001e, 0x0190, - 0x611a, 0x080c, 0xa0e3, 0x601f, 0x0001, 0x2d00, 0x6012, 0x080c, - 0x2cd1, 0x2009, 0x0028, 0x080c, 0x86d3, 0xa085, 0x0001, 0x012e, - 0x00ce, 0x0005, 0xa006, 0x0cd8, 0xa186, 0x0015, 0x1178, 0x2011, - 0xb621, 0x2204, 0xa086, 0x0074, 0x1148, 0x080c, 0x9024, 0x6003, - 0x0001, 0x6007, 0x0029, 0x080c, 0x6d45, 0x0020, 0x080c, 0x8ca5, - 0x080c, 0x86a4, 0x0005, 0xa186, 0x0016, 0x1128, 0x2001, 0x0004, - 0x080c, 0x4f6f, 0x00e8, 0xa186, 0x0015, 0x11e8, 0x2011, 0xb621, - 0x2204, 0xa086, 0x0014, 0x11b8, 0x00d6, 0x6018, 0x2068, 0x080c, - 0x50bd, 0x00de, 0x080c, 0x90dd, 0x1170, 0x00d6, 0x6018, 0x2068, - 0x6890, 0x00de, 0xa005, 0x0138, 0x2001, 0x0006, 0x080c, 0x4f6f, - 0x080c, 0x882c, 0x0020, 0x080c, 0x8ca5, 0x080c, 0x86a4, 0x0005, - 0x6848, 0xa086, 0x0005, 0x1108, 0x0009, 0x0005, 0x6850, 0xc0ad, - 0x6852, 0x0005, 0x00e6, 0x0126, 0x2071, 0xb600, 0x2091, 0x8000, - 0x7548, 0xa582, 0x0001, 0x0608, 0x704c, 0x2060, 0x6000, 0xa086, - 0x0000, 0x0148, 0xace0, 0x0018, 0x705c, 0xac02, 0x1208, 0x0cb0, - 0x2061, 0xbe00, 0x0c98, 0x6003, 0x0008, 0x8529, 0x754a, 0xaca8, - 0x0018, 0x705c, 0xa502, 0x1230, 0x754e, 0xa085, 0x0001, 0x012e, - 0x00ee, 0x0005, 0x704f, 0xbe00, 0x0cc0, 0xa006, 0x0cc0, 0x00e6, - 0x2071, 0xbc8c, 0x7014, 0xd0e4, 0x0150, 0x6013, 0x0000, 0x6003, - 0x0001, 0x6007, 0x0050, 0x080c, 0x6cff, 0x080c, 0x71e5, 0x00ee, - 0x0005, 0x00c6, 0x00f6, 0x2c78, 0x080c, 0x5377, 0x00fe, 0x0120, - 0x601c, 0xa084, 0x000f, 0x0013, 0x00ce, 0x0005, 0x9aba, 0x9fe9, - 0x9fec, 0x9fef, 0xb1e3, 0xb1fe, 0xb201, 0x9aba, 0x9aba, 0x080c, - 0x151a, 0xe000, 0xe000, 0x0005, 0xe000, 0xe000, 0x0005, 0x0009, - 0x0005, 0x00f6, 0x2c78, 0x080c, 0x5377, 0x0538, 0x080c, 0x864e, - 0x1128, 0x2001, 0xb8b8, 0x2004, 0x783e, 0x00f8, 0x7818, 0x601a, - 0x080c, 0xa0e3, 0x781c, 0xa086, 0x0003, 0x0128, 0x7808, 0x6036, - 0x2f00, 0x603a, 0x0020, 0x7808, 0x603a, 0x2f00, 0x6036, 0x602a, - 0x601f, 0x0001, 0x6007, 0x0035, 0x6003, 0x0001, 0x7950, 0x6152, - 0x080c, 0x6cff, 0x080c, 0x71e5, 0x2f60, 0x00fe, 0x0005, 0x0016, - 0x00f6, 0x682c, 0x6032, 0xa08e, 0x0001, 0x0138, 0xa086, 0x0005, - 0x0140, 0xa006, 0x602a, 0x602e, 0x00a0, 0x6820, 0xc0f4, 0xc0d5, - 0x6822, 0x6810, 0x2078, 0x787c, 0x6938, 0xa102, 0x7880, 0x6934, - 0xa103, 0x1e78, 0x6834, 0x602a, 0x6838, 0xa084, 0xfffc, 0x683a, - 0x602e, 0x2d00, 0x6036, 0x6808, 0x603a, 0x6918, 0x611a, 0x6950, - 0x6152, 0x601f, 0x0001, 0x6007, 0x0039, 0x6003, 0x0001, 0x080c, - 0x6cff, 0x6803, 0x0002, 0x00fe, 0x001e, 0x0005, 0x00f6, 0x2c78, - 0x080c, 0x5377, 0x1118, 0xa085, 0x0001, 0x0070, 0x6020, 0xd0f4, - 0x1150, 0xc0f5, 0x6022, 0x6010, 0x2078, 0x7828, 0x603a, 0x782c, - 0x6036, 0x080c, 0x1952, 0xa006, 0x00fe, 0x0005, 0x0006, 0x0016, - 0x6004, 0xa08e, 0x0034, 0x01b8, 0xa08e, 0x0035, 0x01a0, 0xa08e, - 0x0036, 0x0188, 0xa08e, 0x0037, 0x0170, 0xa08e, 0x0038, 0x0158, - 0xa08e, 0x0039, 0x0140, 0xa08e, 0x003a, 0x0128, 0xa08e, 0x003b, - 0x0110, 0xa085, 0x0001, 0x001e, 0x000e, 0x0005, 0x0006, 0x0016, - 0x0026, 0x0036, 0x00e6, 0x2001, 0xb8b2, 0x200c, 0x8000, 0x2014, - 0x2001, 0x0032, 0x080c, 0x6bb2, 0x2001, 0xb8b6, 0x82ff, 0x1110, - 0x2011, 0x0014, 0x2202, 0x2001, 0xb8b4, 0x200c, 0x8000, 0x2014, - 0x2071, 0xb88e, 0x711a, 0x721e, 0x2001, 0x0064, 0x080c, 0x6bb2, - 0x2001, 0xb8b7, 0x82ff, 0x1110, 0x2011, 0x0014, 0x2202, 0x2009, - 0xb8b8, 0xa280, 0x000a, 0x200a, 0x080c, 0x539c, 0x00ee, 0x003e, - 0x002e, 0x001e, 0x000e, 0x0005, 0x0006, 0x00e6, 0x2001, 0xb8b6, - 0x2003, 0x0028, 0x2001, 0xb8b7, 0x2003, 0x0014, 0x2071, 0xb88e, - 0x701b, 0x0000, 0x701f, 0x07d0, 0x2001, 0xb8b8, 0x2003, 0x001e, - 0x00ee, 0x000e, 0x0005, 0x00d6, 0x6054, 0xa06d, 0x0110, 0x080c, - 0x1614, 0x00de, 0x0005, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, - 0x00c6, 0x080c, 0x864e, 0x001e, 0x0178, 0x611a, 0x0ca1, 0x601f, - 0x0001, 0x2d00, 0x6012, 0x2009, 0x0033, 0x080c, 0x86d3, 0xa085, - 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00d6, 0x00e6, - 0x00f6, 0x2071, 0xb600, 0xa186, 0x0015, 0x1500, 0x7084, 0xa086, - 0x0018, 0x11e0, 0x6010, 0x2068, 0x6a3c, 0xd2e4, 0x1160, 0x2c78, - 0x080c, 0x73a3, 0x01d8, 0x7070, 0x6a50, 0xa206, 0x1160, 0x7074, - 0x6a54, 0xa206, 0x1140, 0x6218, 0xa290, 0x0028, 0x2214, 0x2009, - 0x0000, 0x080c, 0x2d16, 0x080c, 0x882c, 0x0020, 0x080c, 0x8ca5, - 0x080c, 0x86a4, 0x00fe, 0x00ee, 0x00de, 0x0005, 0x7054, 0x6a54, - 0xa206, 0x0d48, 0x0c80, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, - 0x080c, 0x864e, 0x001e, 0x0180, 0x611a, 0x080c, 0xa0e3, 0x601f, - 0x0001, 0x2d00, 0x6012, 0x2009, 0x0043, 0x080c, 0x86d3, 0xa085, - 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00d6, 0x00e6, - 0x00f6, 0x2071, 0xb600, 0xa186, 0x0015, 0x11c0, 0x7084, 0xa086, - 0x0004, 0x11a0, 0x6010, 0xa0e8, 0x000f, 0x2c78, 0x080c, 0x73a3, - 0x01a8, 0x7070, 0x6a08, 0xa206, 0x1130, 0x7074, 0x6a0c, 0xa206, - 0x1110, 0x080c, 0x2cd1, 0x080c, 0x882c, 0x0020, 0x080c, 0x8ca5, - 0x080c, 0x86a4, 0x00fe, 0x00ee, 0x00de, 0x0005, 0x7054, 0x6a0c, - 0xa206, 0x0d78, 0x0c80, 0x0016, 0x0026, 0x684c, 0xd0ac, 0x0178, - 0x6914, 0x6a10, 0x2100, 0xa205, 0x0150, 0x6860, 0xa106, 0x1118, - 0x685c, 0xa206, 0x0120, 0x6962, 0x6a5e, 0xa085, 0x0001, 0x002e, - 0x001e, 0x0005, 0x00d6, 0x0036, 0x6310, 0x2368, 0x684a, 0x6952, - 0xa29e, 0x4000, 0x11a0, 0x00c6, 0x6318, 0x2360, 0x2009, 0x0000, - 0x6838, 0xd0f4, 0x1140, 0x080c, 0x52bc, 0x1108, 0xc185, 0x6000, - 0xd0bc, 0x0108, 0xc18d, 0x6a66, 0x696a, 0x00ce, 0x0080, 0x6a66, - 0x3918, 0xa398, 0x0006, 0x231c, 0x686b, 0x0004, 0x6b72, 0x00c6, - 0x6318, 0x2360, 0x6004, 0xa084, 0x00ff, 0x686e, 0x00ce, 0x080c, - 0x547a, 0x6013, 0x0000, 0x003e, 0x00de, 0x0005, 0x00c6, 0x0026, - 0x0016, 0xa186, 0x0035, 0x0110, 0x6a34, 0x0008, 0x6a28, 0x080c, - 0x9d06, 0x01f0, 0x2260, 0x611c, 0xa186, 0x0003, 0x0118, 0xa186, - 0x0006, 0x1190, 0x6834, 0xa206, 0x0140, 0x6838, 0xa206, 0x1160, - 0x6108, 0x6834, 0xa106, 0x1140, 0x0020, 0x6008, 0x6938, 0xa106, - 0x1118, 0x6018, 0x6918, 0xa106, 0x001e, 0x002e, 0x00ce, 0x0005, - 0xa085, 0x0001, 0x0cc8, 0x6944, 0xd1cc, 0x0198, 0xa18c, 0x00ff, - 0xa18e, 0x0002, 0x1170, 0xad88, 0x001e, 0x210c, 0xa18c, 0x0f00, - 0x810f, 0xa18e, 0x0001, 0x1128, 0x6810, 0x6914, 0xa115, 0x190c, - 0x953f, 0x0005, 0x080c, 0x86a4, 0x0804, 0x71e5, 0x0066, 0x6000, - 0xa0b2, 0x0010, 0x1a0c, 0x151a, 0x0013, 0x006e, 0x0005, 0xa227, - 0xa702, 0xa828, 0xa227, 0xa227, 0xa227, 0xa227, 0xa227, 0xa25f, - 0xa8ac, 0xa227, 0xa227, 0xa227, 0xa227, 0xa227, 0xa227, 0x080c, - 0x151a, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x151a, 0x0013, - 0x006e, 0x0005, 0xa242, 0xad33, 0xa242, 0xa242, 0xa242, 0xa242, - 0xa242, 0xa242, 0xacf5, 0xad7b, 0xa242, 0xb328, 0xb358, 0xb328, - 0xb358, 0xa242, 0x080c, 0x151a, 0x0066, 0x6000, 0xa0b2, 0x0010, - 0x1a0c, 0x151a, 0x0013, 0x006e, 0x0005, 0xa25d, 0xa9fc, 0xaac9, - 0xaaf6, 0xab7a, 0xa25d, 0xac67, 0xac12, 0xa8b8, 0xaccb, 0xace0, - 0xa25d, 0xa25d, 0xa25d, 0xa25d, 0xa25d, 0x080c, 0x151a, 0xa1b2, - 0x0080, 0x1a0c, 0x151a, 0x2100, 0xa1b2, 0x0040, 0x1a04, 0xa676, - 0x0002, 0xa2a9, 0xa474, 0xa2a9, 0xa2a9, 0xa2a9, 0xa47b, 0xa2a9, - 0xa2a9, 0xa2a9, 0xa2a9, 0xa2a9, 0xa2a9, 0xa2a9, 0xa2a9, 0xa2a9, - 0xa2a9, 0xa2a9, 0xa2a9, 0xa2a9, 0xa2a9, 0xa2a9, 0xa2a9, 0xa2a9, - 0xa2ab, 0xa309, 0xa318, 0xa366, 0xa384, 0xa402, 0xa461, 0xa2a9, - 0xa2a9, 0xa47e, 0xa2a9, 0xa2a9, 0xa491, 0xa49c, 0xa2a9, 0xa2a9, - 0xa2a9, 0xa2a9, 0xa2a9, 0xa527, 0xa2a9, 0xa2a9, 0xa53a, 0xa2a9, - 0xa2a9, 0xa4f2, 0xa2a9, 0xa2a9, 0xa2a9, 0xa552, 0xa2a9, 0xa2a9, - 0xa2a9, 0xa5cc, 0xa2a9, 0xa2a9, 0xa2a9, 0xa2a9, 0xa2a9, 0xa2a9, - 0xa63d, 0x080c, 0x151a, 0x080c, 0x537b, 0x1150, 0x2001, 0xb635, - 0x2004, 0xd0cc, 0x1128, 0xa084, 0x0009, 0xa086, 0x0008, 0x1140, - 0x6007, 0x0009, 0x602b, 0x0009, 0x6013, 0x0000, 0x0804, 0xa46f, - 0x080c, 0x536b, 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x6218, - 0x2270, 0x72a0, 0x0026, 0x2019, 0x0029, 0x080c, 0x6e67, 0x0076, - 0x2039, 0x0000, 0x080c, 0x6d74, 0x2c08, 0x080c, 0xaf3e, 0x007e, - 0x001e, 0x2e60, 0x080c, 0x521c, 0x001e, 0x002e, 0x003e, 0x00ce, - 0x00ee, 0x6618, 0x00c6, 0x2660, 0x080c, 0x502a, 0x00ce, 0xa6b0, - 0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x0278, 0x080c, - 0xae82, 0x1904, 0xa360, 0x080c, 0xae22, 0x1120, 0x6007, 0x0008, - 0x0804, 0xa46f, 0x6007, 0x0009, 0x0804, 0xa46f, 0x080c, 0xb037, - 0x0128, 0x080c, 0xae82, 0x0d78, 0x0804, 0xa360, 0x6013, 0x1900, - 0x0c88, 0x080c, 0x2df4, 0x1904, 0xa673, 0x6106, 0x080c, 0xaddc, - 0x6007, 0x0006, 0x0804, 0xa46f, 0x6007, 0x0007, 0x0804, 0xa46f, - 0x080c, 0xb38c, 0x1904, 0xa673, 0x080c, 0x2df4, 0x1904, 0xa673, - 0x00d6, 0x6618, 0x2668, 0x6e04, 0xa684, 0x00ff, 0xa082, 0x0006, - 0x1220, 0x2001, 0x0001, 0x080c, 0x4f5d, 0xa6b4, 0xff00, 0x8637, - 0xa686, 0x0006, 0x0188, 0xa686, 0x0004, 0x0170, 0x6e04, 0xa6b4, - 0x00ff, 0xa686, 0x0006, 0x0140, 0xa686, 0x0004, 0x0128, 0xa686, - 0x0005, 0x0110, 0x00de, 0x00e0, 0x080c, 0xaee0, 0x11a0, 0xa686, - 0x0006, 0x1150, 0x0026, 0x6218, 0xa290, 0x0028, 0x2214, 0x2009, - 0x0000, 0x080c, 0x2d16, 0x002e, 0x080c, 0x50bd, 0x6007, 0x000a, - 0x00de, 0x0804, 0xa46f, 0x6007, 0x000b, 0x00de, 0x0804, 0xa46f, - 0x080c, 0x2cd1, 0x6007, 0x0001, 0x0804, 0xa46f, 0x080c, 0xb38c, - 0x1904, 0xa673, 0x080c, 0x2df4, 0x1904, 0xa673, 0x6618, 0x00d6, - 0x2668, 0x6e04, 0x00de, 0xa686, 0x0707, 0x0d50, 0x0026, 0x6218, - 0xa290, 0x0028, 0x2214, 0x2009, 0x0000, 0x080c, 0x2d16, 0x002e, - 0x6007, 0x000c, 0x0804, 0xa46f, 0x080c, 0x537b, 0x1140, 0x2001, - 0xb635, 0x2004, 0xa084, 0x0009, 0xa086, 0x0008, 0x1110, 0x0804, - 0xa2b8, 0x080c, 0x536b, 0x6618, 0xa6b0, 0x0001, 0x2634, 0xa684, - 0x00ff, 0xa082, 0x0006, 0x06e8, 0x1138, 0x0026, 0x2001, 0x0006, - 0x080c, 0x4f9c, 0x002e, 0x0050, 0xa6b4, 0xff00, 0x8637, 0xa686, - 0x0004, 0x0120, 0xa686, 0x0006, 0x1904, 0xa360, 0x080c, 0xaeed, - 0x1120, 0x6007, 0x000e, 0x0804, 0xa46f, 0x0046, 0x6418, 0xa4a0, - 0x0028, 0x2424, 0xa4a4, 0x00ff, 0x8427, 0x0046, 0x080c, 0x2cd1, - 0x004e, 0x0016, 0xa006, 0x2009, 0xb653, 0x210c, 0xd1a4, 0x0158, - 0x2009, 0x0029, 0x080c, 0xb1a4, 0x6018, 0x00d6, 0x2068, 0x6800, - 0xc0e5, 0x6802, 0x00de, 0x001e, 0x004e, 0x6007, 0x0001, 0x0804, - 0xa46f, 0x2001, 0x0001, 0x080c, 0x4f5d, 0x0156, 0x0016, 0x0026, - 0x0036, 0x20a9, 0x0004, 0x2019, 0xb605, 0x2011, 0xbc90, 0x080c, - 0x9166, 0x003e, 0x002e, 0x001e, 0x015e, 0xa005, 0x0168, 0xa6b4, - 0xff00, 0x8637, 0xa682, 0x0004, 0x0a04, 0xa360, 0xa682, 0x0007, - 0x0a04, 0xa3ae, 0x0804, 0xa360, 0x6013, 0x1900, 0x6007, 0x0009, - 0x0804, 0xa46f, 0x080c, 0x537b, 0x1140, 0x2001, 0xb635, 0x2004, - 0xa084, 0x0009, 0xa086, 0x0008, 0x1110, 0x0804, 0xa2b8, 0x080c, - 0x536b, 0x6618, 0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, - 0x0006, 0x06b8, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0004, 0x0120, - 0xa686, 0x0006, 0x1904, 0xa360, 0x080c, 0xaf15, 0x1138, 0x080c, - 0xae22, 0x1120, 0x6007, 0x0010, 0x0804, 0xa46f, 0x0046, 0x6418, - 0xa4a0, 0x0028, 0x2424, 0xa4a4, 0x00ff, 0x8427, 0x0046, 0x080c, - 0x2cd1, 0x004e, 0x0016, 0xa006, 0x2009, 0xb653, 0x210c, 0xd1a4, - 0x0158, 0x2009, 0x0029, 0x080c, 0xb1a4, 0x6018, 0x00d6, 0x2068, - 0x6800, 0xc0e5, 0x6802, 0x00de, 0x001e, 0x004e, 0x6007, 0x0001, - 0x00f0, 0x080c, 0xb037, 0x0140, 0xa6b4, 0xff00, 0x8637, 0xa686, - 0x0006, 0x0950, 0x0804, 0xa360, 0x6013, 0x1900, 0x6007, 0x0009, - 0x0070, 0x080c, 0x2df4, 0x1904, 0xa673, 0x080c, 0xb38c, 0x1904, - 0xa673, 0x080c, 0xa69b, 0x1904, 0xa360, 0x6007, 0x0012, 0x6003, - 0x0001, 0x080c, 0x6d45, 0x0005, 0x6007, 0x0001, 0x6003, 0x0001, - 0x080c, 0x6d45, 0x0cc0, 0x6007, 0x0005, 0x0cc0, 0x080c, 0xb38c, - 0x1904, 0xa673, 0x080c, 0x2df4, 0x1904, 0xa673, 0x080c, 0xa69b, - 0x1904, 0xa360, 0x6007, 0x0020, 0x6003, 0x0001, 0x080c, 0x6d45, - 0x0005, 0x080c, 0x2df4, 0x1904, 0xa673, 0x6007, 0x0023, 0x6003, - 0x0001, 0x080c, 0x6d45, 0x0005, 0x080c, 0xb38c, 0x1904, 0xa673, - 0x080c, 0x2df4, 0x1904, 0xa673, 0x080c, 0xa69b, 0x1904, 0xa360, - 0x0016, 0x0026, 0x2011, 0xbc91, 0x2214, 0xa286, 0xffff, 0x0190, - 0x2c08, 0x080c, 0x9d06, 0x01e0, 0x2260, 0x2011, 0xbc90, 0x2214, - 0x6008, 0xa206, 0x11a8, 0x6018, 0xa190, 0x0006, 0x2214, 0xa206, - 0x01e8, 0x0070, 0x2011, 0xbc90, 0x2214, 0x2c08, 0xa006, 0x080c, - 0xb176, 0x11a0, 0x2011, 0xbc91, 0x2214, 0xa286, 0xffff, 0x01c0, - 0x2160, 0x6007, 0x0026, 0x6013, 0x1700, 0x2011, 0xbc89, 0x2214, - 0xa296, 0xffff, 0x1180, 0x6007, 0x0025, 0x0068, 0x601c, 0xa086, - 0x0007, 0x1d70, 0x6004, 0xa086, 0x0024, 0x1110, 0x080c, 0x86a4, - 0x2160, 0x6007, 0x0025, 0x6003, 0x0001, 0x080c, 0x6d45, 0x002e, - 0x001e, 0x0005, 0x2001, 0x0001, 0x080c, 0x4f5d, 0x0156, 0x0016, - 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, 0xb605, 0x2011, 0xbc96, - 0x080c, 0x9166, 0x003e, 0x002e, 0x001e, 0x015e, 0x0120, 0x6007, - 0x0031, 0x0804, 0xa46f, 0x080c, 0x8e82, 0x080c, 0x5b41, 0x11b0, - 0x0006, 0x0026, 0x0036, 0x080c, 0x5b5d, 0x1158, 0x2001, 0xb89f, - 0x2003, 0x0001, 0x2001, 0xb600, 0x2003, 0x0001, 0x080c, 0x5a79, - 0x0010, 0x080c, 0x5b18, 0x003e, 0x002e, 0x000e, 0x0005, 0x080c, - 0x2df4, 0x1904, 0xa673, 0x080c, 0xa69b, 0x1904, 0xa360, 0x6106, - 0x080c, 0xa6b7, 0x6007, 0x002b, 0x0804, 0xa46f, 0x6007, 0x002c, - 0x0804, 0xa46f, 0x080c, 0xb38c, 0x1904, 0xa673, 0x080c, 0x2df4, - 0x1904, 0xa673, 0x080c, 0xa69b, 0x1904, 0xa360, 0x6106, 0x080c, - 0xa6bb, 0x1120, 0x6007, 0x002e, 0x0804, 0xa46f, 0x6007, 0x002f, - 0x0804, 0xa46f, 0x080c, 0x2df4, 0x1904, 0xa673, 0x00e6, 0x00d6, - 0x00c6, 0x6018, 0xa080, 0x0001, 0x200c, 0xa184, 0x00ff, 0xa086, - 0x0006, 0x0158, 0xa184, 0xff00, 0x8007, 0xa086, 0x0006, 0x0128, - 0x00ce, 0x00de, 0x00ee, 0x0804, 0xa474, 0x2001, 0xb672, 0x2004, - 0xd0e4, 0x0904, 0xa5c9, 0x2071, 0xbc8c, 0x7010, 0x6036, 0x7014, - 0x603a, 0x7108, 0x720c, 0x2001, 0xb653, 0x2004, 0xd0a4, 0x0140, - 0x6018, 0x2068, 0x6810, 0xa106, 0x1118, 0x6814, 0xa206, 0x01f8, - 0x2001, 0xb653, 0x2004, 0xd0ac, 0x1590, 0x2069, 0xb600, 0x6874, - 0xa206, 0x1568, 0x6870, 0xa106, 0x1550, 0x7210, 0x080c, 0x9d06, - 0x0558, 0x080c, 0xb210, 0x0540, 0x622a, 0x6007, 0x0036, 0x6003, - 0x0001, 0x080c, 0x6cff, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x7214, - 0xa286, 0xffff, 0x0150, 0x080c, 0x9d06, 0x01b0, 0xa280, 0x0002, - 0x2004, 0x7110, 0xa106, 0x1180, 0x0c08, 0x7210, 0x2c08, 0xa085, - 0x0001, 0x080c, 0xb176, 0x2c10, 0x2160, 0x0130, 0x08b8, 0x6007, - 0x0037, 0x6013, 0x1500, 0x08d8, 0x6007, 0x0037, 0x6013, 0x1700, - 0x08b0, 0x6007, 0x0012, 0x0898, 0x080c, 0x2df4, 0x1904, 0xa673, - 0x6018, 0xa080, 0x0001, 0x2004, 0xa084, 0xff00, 0x8007, 0xa086, - 0x0006, 0x1904, 0xa474, 0x00e6, 0x00d6, 0x00c6, 0x2001, 0xb672, - 0x2004, 0xd0e4, 0x0904, 0xa635, 0x2069, 0xb600, 0x2071, 0xbc8c, - 0x7008, 0x6036, 0x720c, 0x623a, 0xa286, 0xffff, 0x1150, 0x7208, - 0x00c6, 0x2c08, 0xa085, 0x0001, 0x080c, 0xb176, 0x2c10, 0x00ce, - 0x0588, 0x080c, 0x9d06, 0x0570, 0x00c6, 0x0026, 0x2260, 0x080c, - 0x99d9, 0x002e, 0x00ce, 0x7118, 0xa18c, 0xff00, 0x810f, 0xa186, - 0x0001, 0x0158, 0xa186, 0x0005, 0x0118, 0xa186, 0x0007, 0x1178, - 0xa280, 0x0004, 0x2004, 0xa005, 0x0150, 0x0056, 0x7510, 0x7614, - 0x080c, 0xb227, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x6007, - 0x003b, 0x602b, 0x0009, 0x6013, 0x2a00, 0x6003, 0x0001, 0x080c, - 0x6cff, 0x0c88, 0x6007, 0x003b, 0x602b, 0x0009, 0x6013, 0x1700, - 0x6003, 0x0001, 0x080c, 0x6cff, 0x0c30, 0x6007, 0x003b, 0x602b, - 0x000b, 0x6013, 0x0000, 0x0804, 0xa59f, 0x00e6, 0x0026, 0x080c, - 0x537b, 0x0558, 0x080c, 0x536b, 0x080c, 0xb407, 0x1520, 0x2071, - 0xb600, 0x70d4, 0xc085, 0x70d6, 0x00f6, 0x2079, 0x0100, 0x72a0, - 0xa284, 0x00ff, 0x7072, 0x78e6, 0xa284, 0xff00, 0x7274, 0xa205, - 0x7076, 0x78ea, 0x00fe, 0x70df, 0x0000, 0x2001, 0xb653, 0x2004, - 0xd0a4, 0x0120, 0x2011, 0xb8fa, 0x2013, 0x07d0, 0xd0ac, 0x1128, - 0x080c, 0x2aed, 0x0010, 0x080c, 0xb433, 0x002e, 0x00ee, 0x080c, - 0x86a4, 0x0804, 0xa473, 0x080c, 0x86a4, 0x0005, 0x2600, 0x0002, - 0xa681, 0xa681, 0xa681, 0xa681, 0xa681, 0xa683, 0xa681, 0xa681, - 0xa681, 0x080c, 0x151a, 0x080c, 0xb38c, 0x1d68, 0x080c, 0x2df4, - 0x1d50, 0x0089, 0x1138, 0x6007, 0x0045, 0x6003, 0x0001, 0x080c, - 0x6d45, 0x0005, 0x080c, 0x2cd1, 0x6007, 0x0001, 0x6003, 0x0001, - 0x080c, 0x6d45, 0x0005, 0x00d6, 0x0066, 0x6618, 0x2668, 0x6e04, - 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0170, 0xa686, 0x0004, - 0x0158, 0x6e04, 0xa6b4, 0x00ff, 0xa686, 0x0006, 0x0128, 0xa686, - 0x0004, 0x0110, 0xa085, 0x0001, 0x006e, 0x00de, 0x0005, 0x00d6, - 0x0449, 0x00de, 0x0005, 0x00d6, 0x0491, 0x11f0, 0x680c, 0xa08c, - 0xff00, 0x6820, 0xa084, 0x00ff, 0xa115, 0x6212, 0x6824, 0x602a, - 0xd1e4, 0x0118, 0x2009, 0x0001, 0x0060, 0xd1ec, 0x0168, 0x6920, - 0xa18c, 0x00ff, 0x6824, 0x080c, 0x2852, 0x1130, 0x2110, 0x2009, - 0x0000, 0x080c, 0x2d16, 0x0018, 0xa085, 0x0001, 0x0008, 0xa006, - 0x00de, 0x0005, 0x2069, 0xbc8d, 0x6800, 0xa082, 0x0010, 0x1228, - 0x6013, 0x0000, 0xa085, 0x0001, 0x0008, 0xa006, 0x0005, 0x6013, - 0x0000, 0x2069, 0xbc8c, 0x6808, 0xa084, 0xff00, 0xa086, 0x0800, - 0x1140, 0x6800, 0xa084, 0x00ff, 0xa08e, 0x0014, 0x0110, 0xa08e, - 0x0010, 0x0005, 0x6004, 0xa0b2, 0x0080, 0x1a0c, 0x151a, 0xa1b6, - 0x0013, 0x1130, 0x2008, 0xa1b2, 0x0040, 0x1a04, 0xa802, 0x0092, - 0xa1b6, 0x0027, 0x0120, 0xa1b6, 0x0014, 0x190c, 0x151a, 0x2001, - 0x0007, 0x080c, 0x4f9c, 0x080c, 0x7102, 0x080c, 0x9ed9, 0x080c, - 0x71e5, 0x0005, 0xa762, 0xa764, 0xa762, 0xa762, 0xa762, 0xa764, - 0xa776, 0xa7fb, 0xa7c6, 0xa7fb, 0xa7d7, 0xa7fb, 0xa776, 0xa7fb, - 0xa7f3, 0xa7fb, 0xa7f3, 0xa7fb, 0xa7fb, 0xa762, 0xa762, 0xa762, - 0xa762, 0xa762, 0xa762, 0xa762, 0xa762, 0xa762, 0xa762, 0xa762, - 0xa764, 0xa762, 0xa7fb, 0xa762, 0xa762, 0xa7fb, 0xa762, 0xa7f8, - 0xa7fb, 0xa762, 0xa762, 0xa762, 0xa762, 0xa7fb, 0xa7fb, 0xa762, - 0xa7fb, 0xa7fb, 0xa762, 0xa770, 0xa762, 0xa762, 0xa762, 0xa762, - 0xa7f7, 0xa7fb, 0xa762, 0xa762, 0xa7fb, 0xa7fb, 0xa762, 0xa762, - 0xa762, 0xa762, 0x080c, 0x151a, 0x080c, 0x7102, 0x2001, 0xb8b6, - 0x2004, 0x6016, 0x6003, 0x0002, 0x080c, 0x71e5, 0x0804, 0xa801, - 0x2001, 0x0000, 0x080c, 0x4f5d, 0x0804, 0xa7fb, 0x00f6, 0x2079, - 0xb652, 0x7804, 0x00fe, 0xd0ac, 0x1904, 0xa7fb, 0x2001, 0x0000, - 0x080c, 0x4f5d, 0x6018, 0xa080, 0x0004, 0x2004, 0xa086, 0x00ff, - 0x1140, 0x00f6, 0x2079, 0xb600, 0x7898, 0x8000, 0x789a, 0x00fe, - 0x00e0, 0x00c6, 0x6018, 0x2060, 0x6000, 0xd0f4, 0x1140, 0x6010, - 0xa005, 0x0128, 0x00ce, 0x080c, 0x3f85, 0x0804, 0xa7fb, 0x00ce, - 0x2001, 0xb600, 0x2004, 0xa086, 0x0002, 0x1138, 0x00f6, 0x2079, - 0xb600, 0x7898, 0x8000, 0x789a, 0x00fe, 0x2001, 0x0002, 0x080c, - 0x4f6f, 0x080c, 0x7102, 0x601f, 0x0001, 0x6003, 0x0001, 0x6007, - 0x0002, 0x080c, 0x6d45, 0x080c, 0x71e5, 0x00c6, 0x6118, 0x2160, - 0x2009, 0x0001, 0x080c, 0x6a1a, 0x00ce, 0x04d8, 0x6618, 0x00d6, - 0x2668, 0x6e04, 0x00de, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, - 0x0550, 0xa686, 0x0004, 0x0538, 0x2001, 0x0004, 0x0410, 0x2001, - 0xb600, 0x2004, 0xa086, 0x0003, 0x1110, 0x080c, 0x3f85, 0x2001, - 0x0006, 0x04a1, 0x6618, 0x00d6, 0x2668, 0x6e04, 0x00de, 0xa6b4, - 0xff00, 0x8637, 0xa686, 0x0006, 0x0170, 0x2001, 0x0006, 0x0048, - 0x2001, 0x0004, 0x0030, 0x2001, 0x0006, 0x0401, 0x0020, 0x0018, - 0x0010, 0x080c, 0x4f9c, 0x080c, 0x7102, 0x080c, 0x86a4, 0x080c, - 0x71e5, 0x0005, 0x2600, 0x0002, 0xa80d, 0xa80d, 0xa80d, 0xa80d, - 0xa80d, 0xa80f, 0xa80d, 0xa80d, 0xa80d, 0x080c, 0x151a, 0x080c, - 0x7102, 0x080c, 0x86a4, 0x080c, 0x71e5, 0x0005, 0x0016, 0x00d6, - 0x6118, 0x2168, 0x6900, 0xd184, 0x0140, 0x080c, 0x4f6f, 0x2001, - 0x0000, 0x080c, 0x4f5d, 0x080c, 0x2cf7, 0x00de, 0x001e, 0x0005, - 0x00d6, 0x6618, 0x2668, 0x6804, 0xa084, 0xff00, 0x8007, 0x00de, - 0xa0b2, 0x000c, 0x1a0c, 0x151a, 0xa1b6, 0x0015, 0x1110, 0x003b, - 0x0028, 0xa1b6, 0x0016, 0x190c, 0x151a, 0x006b, 0x0005, 0x8d6b, - 0x8d6b, 0x8d6b, 0x8d6b, 0x8d6b, 0x8d6b, 0xa898, 0xa857, 0x8d6b, - 0x8d6b, 0x8d6b, 0x8d6b, 0x8d6b, 0x8d6b, 0x8d6b, 0x8d6b, 0x8d6b, - 0x8d6b, 0xa898, 0xa89f, 0x8d6b, 0x8d6b, 0x8d6b, 0x8d6b, 0x00f6, - 0x2079, 0xb652, 0x7804, 0xd0ac, 0x11e0, 0x6018, 0xa07d, 0x01c8, - 0x7800, 0xd0f4, 0x1118, 0x7810, 0xa005, 0x1198, 0x2001, 0x0000, - 0x080c, 0x4f5d, 0x2001, 0x0002, 0x080c, 0x4f6f, 0x601f, 0x0001, - 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x6d45, 0x080c, 0x71e5, - 0x00e8, 0x2011, 0xbc83, 0x2204, 0x8211, 0x220c, 0x080c, 0x2852, - 0x11a8, 0x00c6, 0x080c, 0x501b, 0x0120, 0x00ce, 0x080c, 0x86a4, - 0x0068, 0x6010, 0x0006, 0x6014, 0x0006, 0x080c, 0x4c7e, 0x000e, - 0x6016, 0x000e, 0x6012, 0x00ce, 0x080c, 0x86a4, 0x00fe, 0x0005, - 0x6604, 0xa6b6, 0x001e, 0x1110, 0x080c, 0x86a4, 0x0005, 0x080c, - 0x9021, 0x1138, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x6d45, - 0x0010, 0x080c, 0x86a4, 0x0005, 0x6004, 0xa08a, 0x0080, 0x1a0c, - 0x151a, 0x080c, 0x7102, 0x080c, 0x9ed9, 0x080c, 0x71e5, 0x0005, - 0xa182, 0x0040, 0x0002, 0xa8ce, 0xa8ce, 0xa8ce, 0xa8ce, 0xa8d0, - 0xa8ce, 0xa8ce, 0xa8ce, 0xa8ce, 0xa8ce, 0xa8ce, 0xa8ce, 0xa8ce, - 0xa8ce, 0xa8ce, 0xa8ce, 0xa8ce, 0xa8ce, 0xa8ce, 0x080c, 0x151a, - 0x00d6, 0x00e6, 0x00f6, 0x0156, 0x0046, 0x0026, 0x6218, 0xa280, - 0x002b, 0x2004, 0xa005, 0x0120, 0x2021, 0x0000, 0x080c, 0xb3d8, - 0x6106, 0x2071, 0xbc80, 0x7444, 0xa4a4, 0xff00, 0x0904, 0xa934, - 0xa486, 0x2000, 0x1130, 0x2009, 0x0001, 0x2011, 0x0200, 0x080c, - 0x6b8c, 0x080c, 0x15fd, 0x090c, 0x151a, 0x6003, 0x0007, 0x2d00, - 0x6837, 0x010d, 0x6803, 0x0000, 0x683b, 0x0000, 0x6c5a, 0x2c00, - 0x685e, 0x6008, 0x68b2, 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130, - 0x694a, 0x0016, 0xa084, 0xff00, 0x6846, 0x684f, 0x0000, 0x6853, - 0x0000, 0x6857, 0x0036, 0x080c, 0x547a, 0x001e, 0xa486, 0x2000, - 0x1130, 0x2019, 0x0017, 0x080c, 0xb121, 0x0804, 0xa991, 0xa486, - 0x0400, 0x1130, 0x2019, 0x0002, 0x080c, 0xb0d3, 0x0804, 0xa991, - 0xa486, 0x0200, 0x1110, 0x080c, 0xb0b8, 0xa486, 0x1000, 0x1110, - 0x080c, 0xb106, 0x0804, 0xa991, 0x2069, 0xb975, 0x6a00, 0xd284, - 0x0904, 0xa9f8, 0xa284, 0x0300, 0x1904, 0xa9f1, 0x6804, 0xa005, - 0x0904, 0xa9d9, 0x2d78, 0x6003, 0x0007, 0x080c, 0x15e4, 0x0904, - 0xa998, 0x7800, 0xd08c, 0x1118, 0x7804, 0x8001, 0x7806, 0x6013, - 0x0000, 0x6803, 0x0000, 0x6837, 0x0116, 0x683b, 0x0000, 0x6008, - 0x68b2, 0x2c00, 0x684a, 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130, - 0x6986, 0x6846, 0x7928, 0x698a, 0x792c, 0x698e, 0x7930, 0x6992, - 0x7934, 0x6996, 0x6853, 0x003d, 0x7244, 0xa294, 0x0003, 0xa286, - 0x0002, 0x1118, 0x684f, 0x0040, 0x0040, 0xa286, 0x0001, 0x1118, - 0x684f, 0x0080, 0x0010, 0x684f, 0x0000, 0x20a9, 0x000a, 0x2001, - 0xbc90, 0xad90, 0x0015, 0x200c, 0x810f, 0x2112, 0x8000, 0x8210, - 0x1f04, 0xa983, 0x200c, 0x6982, 0x8000, 0x200c, 0x697e, 0x080c, - 0x547a, 0x002e, 0x004e, 0x015e, 0x00fe, 0x00ee, 0x00de, 0x0005, - 0x2001, 0xb60e, 0x2004, 0xd084, 0x0120, 0x080c, 0x15fd, 0x1904, - 0xa949, 0x6013, 0x0100, 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, - 0x6cff, 0x080c, 0x71e5, 0x0c28, 0x2069, 0xbc92, 0x2d04, 0xa084, - 0xff00, 0xa086, 0x1200, 0x11a8, 0x2069, 0xbc80, 0x686c, 0xa084, - 0x00ff, 0x0016, 0x6110, 0xa18c, 0x0700, 0xa10d, 0x6112, 0x001e, - 0x6003, 0x0001, 0x6007, 0x0043, 0x080c, 0x6cff, 0x080c, 0x71e5, - 0x0840, 0x6868, 0x602a, 0x686c, 0x602e, 0x6013, 0x0200, 0x6003, - 0x0001, 0x6007, 0x0041, 0x080c, 0x6cff, 0x080c, 0x71e5, 0x0804, - 0xa991, 0x2001, 0xb60d, 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049, - 0x080c, 0x3f13, 0x6013, 0x0300, 0x0010, 0x6013, 0x0100, 0x6003, - 0x0001, 0x6007, 0x0041, 0x080c, 0x6cff, 0x080c, 0x71e5, 0x0804, - 0xa991, 0x6013, 0x0500, 0x0c98, 0x6013, 0x0600, 0x0804, 0xa9ac, - 0x6013, 0x0200, 0x0804, 0xa9ac, 0xa186, 0x0013, 0x1170, 0x6004, - 0xa08a, 0x0040, 0x0a0c, 0x151a, 0xa08a, 0x0053, 0x1a0c, 0x151a, - 0xa082, 0x0040, 0x2008, 0x0804, 0xaa86, 0xa186, 0x0051, 0x0138, - 0xa186, 0x0047, 0x11d8, 0x6004, 0xa086, 0x0041, 0x0518, 0x2001, - 0x0109, 0x2004, 0xd084, 0x01f0, 0x0126, 0x2091, 0x2800, 0x0006, - 0x0016, 0x0026, 0x080c, 0x6be6, 0x002e, 0x001e, 0x000e, 0x012e, - 0x6000, 0xa086, 0x0002, 0x1170, 0x0804, 0xaac9, 0xa186, 0x0027, - 0x0120, 0xa186, 0x0014, 0x190c, 0x151a, 0x6004, 0xa082, 0x0040, - 0x2008, 0x001a, 0x080c, 0x86ef, 0x0005, 0xaa50, 0xaa52, 0xaa52, - 0xaa76, 0xaa50, 0xaa50, 0xaa50, 0xaa50, 0xaa50, 0xaa50, 0xaa50, - 0xaa50, 0xaa50, 0xaa50, 0xaa50, 0xaa50, 0xaa50, 0xaa50, 0xaa50, - 0x080c, 0x151a, 0x080c, 0x7102, 0x080c, 0x71e5, 0x0036, 0x00d6, - 0x6010, 0xa06d, 0x01c0, 0xad84, 0xf000, 0x01a8, 0x6003, 0x0002, - 0x6018, 0x2004, 0xd0bc, 0x1178, 0x2019, 0x0004, 0x080c, 0xb155, - 0x6013, 0x0000, 0x6014, 0xa005, 0x1120, 0x2001, 0xb8b7, 0x2004, - 0x6016, 0x6003, 0x0007, 0x00de, 0x003e, 0x0005, 0x00d6, 0x080c, - 0x7102, 0x080c, 0x71e5, 0x080c, 0x9d16, 0x0120, 0x6010, 0x2068, - 0x080c, 0x1614, 0x080c, 0x9ed9, 0x00de, 0x0005, 0x0002, 0xaa9a, - 0xaab7, 0xaaa3, 0xaac3, 0xaa9a, 0xaa9a, 0xaa9a, 0xaa9a, 0xaa9a, - 0xaa9a, 0xaa9a, 0xaa9a, 0xaa9a, 0xaa9a, 0xaa9a, 0xaa9a, 0xaa9a, - 0xaa9a, 0xaa9a, 0x080c, 0x151a, 0x6010, 0xa088, 0x0013, 0x2104, - 0xa085, 0x0400, 0x200a, 0x080c, 0x7102, 0x6010, 0xa080, 0x0013, - 0x2004, 0xd0b4, 0x0138, 0x6003, 0x0007, 0x2009, 0x0043, 0x080c, - 0x86d3, 0x0010, 0x6003, 0x0002, 0x080c, 0x71e5, 0x0005, 0x080c, - 0x7102, 0x080c, 0xb393, 0x1120, 0x080c, 0x6b61, 0x080c, 0x86a4, - 0x080c, 0x71e5, 0x0005, 0x080c, 0x7102, 0x2009, 0x0041, 0x0804, - 0xac12, 0xa182, 0x0040, 0x0002, 0xaadf, 0xaae1, 0xaadf, 0xaadf, - 0xaadf, 0xaadf, 0xaadf, 0xaae2, 0xaadf, 0xaadf, 0xaadf, 0xaadf, - 0xaadf, 0xaadf, 0xaadf, 0xaadf, 0xaadf, 0xaaed, 0xaadf, 0x080c, - 0x151a, 0x0005, 0x6003, 0x0004, 0x6110, 0x20e1, 0x0005, 0x3d18, - 0x3e20, 0x2c10, 0x080c, 0x1863, 0x0005, 0x00d6, 0x080c, 0x6b61, - 0x00de, 0x080c, 0xb3f6, 0x080c, 0x86a4, 0x0005, 0xa182, 0x0040, - 0x0002, 0xab0c, 0xab0c, 0xab0c, 0xab0c, 0xab0c, 0xab0c, 0xab0c, - 0xab0e, 0xab0c, 0xab11, 0xab4a, 0xab0c, 0xab0c, 0xab0c, 0xab0c, - 0xab4a, 0xab0c, 0xab0c, 0xab0c, 0x080c, 0x151a, 0x080c, 0x86ef, - 0x0005, 0x2001, 0xb672, 0x2004, 0xd0e4, 0x0158, 0x2001, 0x0100, - 0x2004, 0xa082, 0x0005, 0x0228, 0x2001, 0x011f, 0x2004, 0x6036, - 0x0010, 0x6037, 0x0000, 0x080c, 0x7198, 0x080c, 0x72a2, 0x6010, - 0x00d6, 0x2068, 0x684c, 0xd0fc, 0x0150, 0xa08c, 0x0003, 0xa18e, - 0x0002, 0x0168, 0x2009, 0x0041, 0x00de, 0x0804, 0xac12, 0x6003, - 0x0007, 0x6017, 0x0000, 0x080c, 0x6b61, 0x00de, 0x0005, 0x080c, - 0xb393, 0x0110, 0x00de, 0x0005, 0x080c, 0x6b61, 0x080c, 0x86a4, - 0x00de, 0x0ca0, 0x0036, 0x080c, 0x7198, 0x080c, 0x72a2, 0x6010, - 0x00d6, 0x2068, 0x6018, 0x2004, 0xd0bc, 0x0188, 0x684c, 0xa084, - 0x0003, 0xa086, 0x0002, 0x0140, 0x687c, 0x632c, 0xa31a, 0x632e, - 0x6880, 0x6328, 0xa31b, 0x632a, 0x6003, 0x0002, 0x0080, 0x2019, - 0x0004, 0x080c, 0xb155, 0x6014, 0xa005, 0x1128, 0x2001, 0xb8b7, - 0x2004, 0x8003, 0x6016, 0x6013, 0x0000, 0x6003, 0x0007, 0x00de, - 0x003e, 0x0005, 0xa186, 0x0013, 0x1150, 0x6004, 0xa086, 0x0042, - 0x190c, 0x151a, 0x080c, 0x7102, 0x080c, 0x71e5, 0x0005, 0xa186, - 0x0027, 0x0118, 0xa186, 0x0014, 0x1180, 0x6004, 0xa086, 0x0042, - 0x190c, 0x151a, 0x2001, 0x0007, 0x080c, 0x4f9c, 0x080c, 0x7102, - 0x080c, 0x9ed9, 0x080c, 0x71e5, 0x0005, 0xa182, 0x0040, 0x0002, - 0xabb3, 0xabb3, 0xabb3, 0xabb3, 0xabb3, 0xabb3, 0xabb3, 0xabb5, - 0xabc1, 0xabb3, 0xabb3, 0xabb3, 0xabb3, 0xabb3, 0xabb3, 0xabb3, - 0xabb3, 0xabb3, 0xabb3, 0x080c, 0x151a, 0x0036, 0x0046, 0x20e1, - 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x1863, 0x004e, 0x003e, - 0x0005, 0x6010, 0x00d6, 0x2068, 0x6810, 0x6a14, 0x0006, 0x0046, - 0x0056, 0x6c7c, 0xa422, 0x6d80, 0x2200, 0xa52b, 0x602c, 0xa420, - 0x642e, 0x6028, 0xa529, 0x652a, 0x005e, 0x004e, 0x000e, 0xa20d, - 0x1178, 0x684c, 0xd0fc, 0x0120, 0x2009, 0x0041, 0x00de, 0x0490, - 0x6003, 0x0007, 0x6017, 0x0000, 0x080c, 0x6b61, 0x00de, 0x0005, - 0x0006, 0x00f6, 0x2c78, 0x080c, 0x5377, 0x00fe, 0x000e, 0x0120, - 0x6003, 0x0002, 0x00de, 0x0005, 0x2009, 0xb60d, 0x210c, 0xd19c, - 0x0118, 0x6003, 0x0007, 0x0010, 0x6003, 0x0006, 0x0021, 0x080c, - 0x6b63, 0x00de, 0x0005, 0xd2fc, 0x0140, 0x8002, 0x8000, 0x8212, - 0xa291, 0x0000, 0x2009, 0x0009, 0x0010, 0x2009, 0x0015, 0x6a6a, - 0x6866, 0x0005, 0xa182, 0x0040, 0x0208, 0x0062, 0xa186, 0x0013, - 0x0120, 0xa186, 0x0014, 0x190c, 0x151a, 0x6020, 0xd0dc, 0x090c, - 0x151a, 0x0005, 0xac35, 0xac3c, 0xac48, 0xac54, 0xac35, 0xac35, - 0xac35, 0xac63, 0xac35, 0xac37, 0xac37, 0xac35, 0xac35, 0xac35, - 0xac35, 0xac37, 0xac35, 0xac37, 0xac35, 0x080c, 0x151a, 0x6020, - 0xd0dc, 0x090c, 0x151a, 0x0005, 0x6003, 0x0001, 0x6106, 0x080c, - 0x6cff, 0x0126, 0x2091, 0x8000, 0x080c, 0x71e5, 0x012e, 0x0005, - 0x6003, 0x0001, 0x6106, 0x080c, 0x6cff, 0x0126, 0x2091, 0x8000, - 0x080c, 0x71e5, 0x012e, 0x0005, 0x6003, 0x0003, 0x6106, 0x2c10, - 0x080c, 0x1fc5, 0x0126, 0x2091, 0x8000, 0x080c, 0x6d62, 0x080c, - 0x72a2, 0x012e, 0x0005, 0xa016, 0x080c, 0x1863, 0x0005, 0x0126, - 0x2091, 0x8000, 0x0036, 0x00d6, 0xa182, 0x0040, 0x0023, 0x00de, - 0x003e, 0x012e, 0x0005, 0xac83, 0xac85, 0xac97, 0xacb2, 0xac83, - 0xac83, 0xac83, 0xacc7, 0xac83, 0xac83, 0xac83, 0xac83, 0xac83, - 0xac83, 0xac83, 0xac83, 0x080c, 0x151a, 0x6010, 0x2068, 0x684c, - 0xd0fc, 0x01f8, 0xa09c, 0x0003, 0xa39e, 0x0003, 0x01d0, 0x6003, - 0x0001, 0x6106, 0x080c, 0x6cff, 0x080c, 0x71e5, 0x0498, 0x6010, - 0x2068, 0x684c, 0xd0fc, 0x0168, 0xa09c, 0x0003, 0xa39e, 0x0003, - 0x0140, 0x6003, 0x0001, 0x6106, 0x080c, 0x6cff, 0x080c, 0x71e5, - 0x0408, 0x6013, 0x0000, 0x6017, 0x0000, 0x2019, 0x0004, 0x080c, - 0xb155, 0x00c0, 0x6010, 0x2068, 0x684c, 0xd0fc, 0x0d90, 0xa09c, - 0x0003, 0xa39e, 0x0003, 0x0d68, 0x6003, 0x0003, 0x6106, 0x2c10, - 0x080c, 0x1fc5, 0x080c, 0x6d62, 0x080c, 0x72a2, 0x0018, 0xa016, - 0x080c, 0x1863, 0x0005, 0x080c, 0x7102, 0x6110, 0x81ff, 0x0158, - 0x00d6, 0x2168, 0x080c, 0xb43c, 0x0036, 0x2019, 0x0029, 0x080c, - 0xb155, 0x003e, 0x00de, 0x080c, 0x9ed9, 0x080c, 0x71e5, 0x0005, - 0x080c, 0x7198, 0x6110, 0x81ff, 0x0158, 0x00d6, 0x2168, 0x080c, - 0xb43c, 0x0036, 0x2019, 0x0029, 0x080c, 0xb155, 0x003e, 0x00de, - 0x080c, 0x9ed9, 0x080c, 0x72a2, 0x0005, 0xa182, 0x0085, 0x0002, - 0xad01, 0xacff, 0xacff, 0xad0d, 0xacff, 0xacff, 0xacff, 0x080c, - 0x151a, 0x6003, 0x000b, 0x6106, 0x080c, 0x6cff, 0x0126, 0x2091, - 0x8000, 0x080c, 0x71e5, 0x012e, 0x0005, 0x0026, 0x00e6, 0x080c, - 0xb38c, 0x0118, 0x080c, 0x86a4, 0x00d8, 0x2071, 0xbc80, 0x7224, - 0x6212, 0x7220, 0x080c, 0xb003, 0x0118, 0x6007, 0x0086, 0x0040, - 0x6007, 0x0087, 0x7224, 0xa296, 0xffff, 0x1110, 0x6007, 0x0086, - 0x6003, 0x0001, 0x080c, 0x6cff, 0x080c, 0x71e5, 0x080c, 0x72a2, - 0x00ee, 0x002e, 0x0005, 0xa186, 0x0013, 0x1160, 0x6004, 0xa08a, - 0x0085, 0x0a0c, 0x151a, 0xa08a, 0x008c, 0x1a0c, 0x151a, 0xa082, - 0x0085, 0x00a2, 0xa186, 0x0027, 0x0130, 0xa186, 0x0014, 0x0118, - 0x080c, 0x86ef, 0x0050, 0x2001, 0x0007, 0x080c, 0x4f9c, 0x080c, - 0x7102, 0x080c, 0x9ed9, 0x080c, 0x71e5, 0x0005, 0xad5d, 0xad5f, - 0xad5f, 0xad5d, 0xad5d, 0xad5d, 0xad5d, 0x080c, 0x151a, 0x080c, - 0x7102, 0x080c, 0x9ed9, 0x080c, 0x71e5, 0x0005, 0xa182, 0x0085, - 0x0a0c, 0x151a, 0xa182, 0x008c, 0x1a0c, 0x151a, 0xa182, 0x0085, - 0x0002, 0xad78, 0xad78, 0xad78, 0xad7a, 0xad78, 0xad78, 0xad78, - 0x080c, 0x151a, 0x0005, 0xa186, 0x0013, 0x0148, 0xa186, 0x0014, - 0x0130, 0xa186, 0x0027, 0x0118, 0x080c, 0x86ef, 0x0030, 0x080c, - 0x7102, 0x080c, 0x9ed9, 0x080c, 0x71e5, 0x0005, 0x0036, 0x080c, - 0xb3f6, 0x603f, 0x0000, 0x2019, 0x000b, 0x0031, 0x601f, 0x0006, - 0x6003, 0x0007, 0x003e, 0x0005, 0x0126, 0x0036, 0x2091, 0x8000, - 0x0086, 0x2c40, 0x0096, 0x2049, 0x0000, 0x080c, 0x81b7, 0x009e, - 0x008e, 0x1578, 0x0076, 0x2c38, 0x080c, 0x825d, 0x007e, 0x1548, - 0x6000, 0xa086, 0x0000, 0x0528, 0x601c, 0xa086, 0x0007, 0x0508, - 0x00d6, 0x6000, 0xa086, 0x0004, 0x1150, 0x080c, 0xb3f6, 0x601f, - 0x0007, 0x2001, 0xb8b6, 0x2004, 0x6016, 0x080c, 0x1952, 0x6010, - 0x2068, 0x080c, 0x9d16, 0x0110, 0x080c, 0xb155, 0x00de, 0x6013, - 0x0000, 0x080c, 0xb3f6, 0x601f, 0x0007, 0x2001, 0xb8b6, 0x2004, - 0x6016, 0x003e, 0x012e, 0x0005, 0x00f6, 0x00c6, 0x0036, 0x0156, - 0x2079, 0xbc80, 0x7938, 0x783c, 0x080c, 0x2852, 0x15b0, 0x0016, - 0x00c6, 0x080c, 0x501b, 0x1578, 0x001e, 0x002e, 0x0026, 0x0016, - 0x2019, 0x0029, 0x080c, 0x8320, 0x080c, 0x6e67, 0x0076, 0x2039, - 0x0000, 0x080c, 0x6d74, 0x007e, 0x001e, 0x0076, 0x2039, 0x0000, - 0x080c, 0xaf3e, 0x007e, 0x080c, 0x521c, 0x0026, 0x6204, 0xa294, - 0xff00, 0x8217, 0xa286, 0x0006, 0x0118, 0xa286, 0x0004, 0x1118, - 0x62a0, 0x080c, 0x2d8a, 0x002e, 0x001e, 0x080c, 0x4c7e, 0x6612, - 0x6516, 0xa006, 0x0010, 0x00ce, 0x001e, 0x015e, 0x003e, 0x00ce, - 0x00fe, 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x0016, 0x2009, 0xb621, - 0x2104, 0xa086, 0x0074, 0x1904, 0xae77, 0x2069, 0xbc8e, 0x690c, - 0xa182, 0x0100, 0x06c0, 0x6908, 0xa184, 0x8000, 0x05e8, 0x2001, - 0xb89e, 0x2004, 0xa005, 0x1160, 0x6018, 0x2070, 0x7010, 0xa084, - 0x00ff, 0x0118, 0x7000, 0xd0f4, 0x0118, 0xa184, 0x0800, 0x0560, - 0x6910, 0xa18a, 0x0001, 0x0610, 0x6914, 0x2069, 0xbcae, 0x6904, - 0x81ff, 0x1198, 0x690c, 0xa182, 0x0100, 0x02a8, 0x6908, 0x81ff, - 0x1178, 0x6910, 0xa18a, 0x0001, 0x0288, 0x6918, 0xa18a, 0x0001, - 0x0298, 0x00d0, 0x6013, 0x0100, 0x00a0, 0x6013, 0x0300, 0x0088, - 0x6013, 0x0500, 0x0070, 0x6013, 0x0700, 0x0058, 0x6013, 0x0900, - 0x0040, 0x6013, 0x0b00, 0x0028, 0x6013, 0x0f00, 0x0010, 0x6013, - 0x2d00, 0xa085, 0x0001, 0x0008, 0xa006, 0x001e, 0x00ee, 0x00de, - 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x0026, 0x0036, 0x0156, 0x6218, - 0x2268, 0x6b04, 0xa394, 0x00ff, 0xa286, 0x0006, 0x0190, 0xa286, - 0x0004, 0x0178, 0xa394, 0xff00, 0x8217, 0xa286, 0x0006, 0x0148, - 0xa286, 0x0004, 0x0130, 0x00c6, 0x2d60, 0x080c, 0x502a, 0x00ce, - 0x04c0, 0x2011, 0xbc96, 0xad98, 0x000a, 0x20a9, 0x0004, 0x080c, - 0x9166, 0x1580, 0x2011, 0xbc9a, 0xad98, 0x0006, 0x20a9, 0x0004, - 0x080c, 0x9166, 0x1538, 0x0046, 0x0016, 0x6aa0, 0xa294, 0x00ff, - 0x8227, 0xa006, 0x2009, 0xb653, 0x210c, 0xd1a4, 0x0138, 0x2009, - 0x0029, 0x080c, 0xb1a4, 0x6800, 0xc0e5, 0x6802, 0x2019, 0x0029, - 0x080c, 0x6e67, 0x0076, 0x2039, 0x0000, 0x080c, 0x6d74, 0x2c08, - 0x080c, 0xaf3e, 0x007e, 0x2001, 0x0007, 0x080c, 0x4f9c, 0x001e, - 0x004e, 0xa006, 0x015e, 0x003e, 0x002e, 0x00de, 0x00ce, 0x0005, - 0x00d6, 0x2069, 0xbc8e, 0x6800, 0xa086, 0x0800, 0x0118, 0x6013, - 0x0000, 0x0008, 0xa006, 0x00de, 0x0005, 0x00c6, 0x00f6, 0x0016, - 0x0026, 0x0036, 0x0156, 0x2079, 0xbc8c, 0x7930, 0x7834, 0x080c, - 0x2852, 0x11a0, 0x080c, 0x501b, 0x1188, 0x2011, 0xbc90, 0xac98, - 0x000a, 0x20a9, 0x0004, 0x080c, 0x9166, 0x1140, 0x2011, 0xbc94, - 0xac98, 0x0006, 0x20a9, 0x0004, 0x080c, 0x9166, 0x015e, 0x003e, - 0x002e, 0x001e, 0x00fe, 0x00ce, 0x0005, 0x00c6, 0x0006, 0x0016, - 0x0026, 0x0036, 0x0156, 0x2011, 0xbc83, 0x2204, 0x8211, 0x220c, - 0x080c, 0x2852, 0x11a0, 0x080c, 0x501b, 0x1188, 0x2011, 0xbc96, - 0xac98, 0x000a, 0x20a9, 0x0004, 0x080c, 0x9166, 0x1140, 0x2011, - 0xbc9a, 0xac98, 0x0006, 0x20a9, 0x0004, 0x080c, 0x9166, 0x015e, - 0x003e, 0x002e, 0x001e, 0x000e, 0x00ce, 0x0005, 0x00e6, 0x00c6, - 0x0086, 0x0076, 0x0066, 0x0056, 0x0046, 0x0026, 0x0126, 0x2091, - 0x8000, 0x2740, 0x2029, 0xb8ea, 0x252c, 0x2021, 0xb8f0, 0x2424, - 0x2061, 0xbe00, 0x2071, 0xb600, 0x7648, 0x7068, 0x81ff, 0x0150, - 0x0006, 0xa186, 0xb9f5, 0x000e, 0x0128, 0x8001, 0xa602, 0x1a04, - 0xafbf, 0x0018, 0xa606, 0x0904, 0xafbf, 0x2100, 0xac06, 0x0904, - 0xafb6, 0x080c, 0xb1cc, 0x0904, 0xafb6, 0x671c, 0xa786, 0x0001, - 0x0904, 0xafda, 0xa786, 0x0004, 0x0904, 0xafda, 0xa786, 0x0007, - 0x05e8, 0x2500, 0xac06, 0x05d0, 0x2400, 0xac06, 0x05b8, 0x080c, - 0xb1dc, 0x15a0, 0x88ff, 0x0118, 0x6050, 0xa906, 0x1578, 0x00d6, - 0x6000, 0xa086, 0x0004, 0x1120, 0x0016, 0x080c, 0x1952, 0x001e, - 0xa786, 0x0008, 0x1148, 0x080c, 0x9f14, 0x1130, 0x080c, 0x8ca5, - 0x00de, 0x080c, 0x9ed9, 0x00d0, 0x6010, 0x2068, 0x080c, 0x9d16, - 0x0190, 0xa786, 0x0003, 0x1528, 0x6837, 0x0103, 0x6b4a, 0x6847, - 0x0000, 0x080c, 0xb43c, 0x0016, 0x080c, 0x9f88, 0x080c, 0x547a, - 0x001e, 0x080c, 0x9ecd, 0x00de, 0x080c, 0x9ed9, 0xace0, 0x0018, - 0x2001, 0xb617, 0x2004, 0xac02, 0x1210, 0x0804, 0xaf52, 0x012e, - 0x002e, 0x004e, 0x005e, 0x006e, 0x007e, 0x008e, 0x00ce, 0x00ee, - 0x0005, 0xa786, 0x0006, 0x1150, 0xa386, 0x0005, 0x0128, 0x080c, - 0xb43c, 0x080c, 0xb155, 0x08f8, 0x00de, 0x0c00, 0xa786, 0x000a, - 0x0968, 0x0850, 0x080c, 0xb1dc, 0x19c8, 0x81ff, 0x09b8, 0xa180, - 0x0001, 0x2004, 0xa086, 0x0018, 0x0130, 0xa180, 0x0001, 0x2004, - 0xa086, 0x002d, 0x1958, 0x6000, 0xa086, 0x0002, 0x1938, 0x080c, - 0x9f03, 0x0130, 0x080c, 0x9f14, 0x1908, 0x080c, 0x8ca5, 0x0038, - 0x080c, 0x2cf7, 0x080c, 0x9f14, 0x1110, 0x080c, 0x8ca5, 0x080c, - 0x9ed9, 0x0804, 0xafb6, 0x00c6, 0x00e6, 0x0016, 0x2c08, 0x2170, - 0xa006, 0x080c, 0xb176, 0x001e, 0x0120, 0x601c, 0xa084, 0x000f, - 0x001b, 0x00ee, 0x00ce, 0x0005, 0xb01c, 0xb01c, 0xb01c, 0xb01c, - 0xb01c, 0xb01c, 0xb01e, 0xb01c, 0xa006, 0x0005, 0x0046, 0x0016, - 0x7018, 0xa080, 0x0028, 0x2024, 0xa4a4, 0x00ff, 0x8427, 0x2c00, - 0x2009, 0x0020, 0x080c, 0xb1a4, 0x001e, 0x004e, 0x0036, 0x2019, - 0x0002, 0x080c, 0xad9c, 0x003e, 0xa085, 0x0001, 0x0005, 0x2001, - 0x0001, 0x080c, 0x4f5d, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, - 0x0004, 0x2019, 0xb605, 0x2011, 0xbc96, 0x080c, 0x9166, 0x003e, - 0x002e, 0x001e, 0x015e, 0xa005, 0x0005, 0x00f6, 0x00e6, 0x00c6, - 0x0086, 0x0076, 0x0066, 0x0026, 0x0126, 0x2091, 0x8000, 0x2740, - 0x2061, 0xbe00, 0x2079, 0x0001, 0x8fff, 0x0904, 0xb0ab, 0x2071, - 0xb600, 0x7648, 0x7068, 0x8001, 0xa602, 0x1a04, 0xb0ab, 0x88ff, - 0x0128, 0x2800, 0xac06, 0x15b0, 0x2079, 0x0000, 0x080c, 0xb1cc, - 0x0588, 0x2400, 0xac06, 0x0570, 0x671c, 0xa786, 0x0006, 0x1550, - 0xa786, 0x0007, 0x0538, 0x88ff, 0x1140, 0x6018, 0xa206, 0x1510, - 0x85ff, 0x0118, 0x6050, 0xa106, 0x11e8, 0x00d6, 0x6000, 0xa086, - 0x0004, 0x1150, 0x080c, 0xb3f6, 0x601f, 0x0007, 0x2001, 0xb8b6, - 0x2004, 0x6016, 0x080c, 0x1952, 0x6010, 0x2068, 0x080c, 0x9d16, - 0x0120, 0x0046, 0x080c, 0xb155, 0x004e, 0x00de, 0x080c, 0x9ed9, - 0x88ff, 0x1198, 0xace0, 0x0018, 0x2001, 0xb617, 0x2004, 0xac02, - 0x1210, 0x0804, 0xb05c, 0xa006, 0x012e, 0x002e, 0x006e, 0x007e, - 0x008e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0xa8c5, 0x0001, 0x0ca0, - 0x0076, 0x0056, 0x0086, 0x2041, 0x0000, 0x2029, 0x0001, 0x2c20, - 0x2019, 0x0002, 0x6218, 0x0096, 0x2049, 0x0000, 0x080c, 0x81b7, - 0x009e, 0x008e, 0x2039, 0x0000, 0x080c, 0x825d, 0x080c, 0xb04d, - 0x005e, 0x007e, 0x0005, 0x0026, 0x0046, 0x0056, 0x0076, 0x00c6, - 0x0156, 0x2c20, 0x2128, 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, - 0x0036, 0x080c, 0x501b, 0x11b0, 0x2c10, 0x0056, 0x0086, 0x2041, - 0x0000, 0x2508, 0x2029, 0x0001, 0x0096, 0x2049, 0x0000, 0x080c, - 0x81b7, 0x009e, 0x008e, 0x2039, 0x0000, 0x080c, 0x825d, 0x080c, - 0xb04d, 0x005e, 0x003e, 0x001e, 0x8108, 0x1f04, 0xb0df, 0x015e, - 0x00ce, 0x007e, 0x005e, 0x004e, 0x002e, 0x0005, 0x0076, 0x0056, - 0x6218, 0x0086, 0x2041, 0x0000, 0x2029, 0x0001, 0x2019, 0x0048, - 0x0096, 0x2049, 0x0000, 0x080c, 0x81b7, 0x009e, 0x008e, 0x2039, - 0x0000, 0x080c, 0x825d, 0x2c20, 0x080c, 0xb04d, 0x005e, 0x007e, - 0x0005, 0x0026, 0x0046, 0x0056, 0x0076, 0x00c6, 0x0156, 0x2c20, - 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x0036, 0x080c, 0x501b, - 0x11c0, 0x2c10, 0x0086, 0x2041, 0x0000, 0x2828, 0x0046, 0x2021, - 0x0001, 0x080c, 0xb3d8, 0x004e, 0x0096, 0x2049, 0x0000, 0x080c, - 0x81b7, 0x009e, 0x008e, 0x2039, 0x0000, 0x080c, 0x825d, 0x080c, - 0xb04d, 0x003e, 0x001e, 0x8108, 0x1f04, 0xb12c, 0x015e, 0x00ce, - 0x007e, 0x005e, 0x004e, 0x002e, 0x0005, 0x0016, 0x00f6, 0x3800, - 0xd08c, 0x0130, 0xad82, 0x1000, 0x02b0, 0xad82, 0xb600, 0x0230, - 0xad82, 0xee00, 0x0280, 0xad82, 0xffff, 0x1268, 0x6800, 0xa07d, - 0x0138, 0x6803, 0x0000, 0x6b52, 0x080c, 0x547a, 0x2f68, 0x0cb0, - 0x6b52, 0x080c, 0x547a, 0x00fe, 0x001e, 0x0005, 0x00e6, 0x0046, - 0x0036, 0x2061, 0xbe00, 0xa005, 0x1138, 0x2071, 0xb600, 0x7448, - 0x7068, 0x8001, 0xa402, 0x12d8, 0x2100, 0xac06, 0x0168, 0x6000, - 0xa086, 0x0000, 0x0148, 0x6008, 0xa206, 0x1130, 0x6018, 0xa1a0, - 0x0006, 0x2424, 0xa406, 0x0140, 0xace0, 0x0018, 0x2001, 0xb617, - 0x2004, 0xac02, 0x1220, 0x0c40, 0xa085, 0x0001, 0x0008, 0xa006, - 0x003e, 0x004e, 0x00ee, 0x0005, 0x00d6, 0x0006, 0x080c, 0x15fd, - 0x000e, 0x090c, 0x151a, 0x6837, 0x010d, 0x685e, 0x0026, 0x2010, - 0x080c, 0x9d06, 0x2001, 0x0000, 0x0120, 0x2200, 0xa080, 0x0014, - 0x2004, 0x002e, 0x684a, 0x6956, 0x6c46, 0x684f, 0x0000, 0x2001, - 0xb8be, 0x2004, 0x6852, 0xa006, 0x68b2, 0x6802, 0x683a, 0x685a, - 0x080c, 0x547a, 0x00de, 0x0005, 0x6700, 0xa786, 0x0000, 0x0158, - 0xa786, 0x0001, 0x0140, 0xa786, 0x000a, 0x0128, 0xa786, 0x0009, - 0x0110, 0xa085, 0x0001, 0x0005, 0x00e6, 0x6018, 0x2070, 0x70a0, - 0xa206, 0x00ee, 0x0005, 0x0016, 0x6004, 0xa08e, 0x001e, 0x11a0, - 0x8007, 0x6130, 0xa18c, 0x00ff, 0xa105, 0x6032, 0x6007, 0x0085, - 0x6003, 0x000b, 0x601f, 0x0005, 0x2001, 0xb8b7, 0x2004, 0x6016, - 0x080c, 0x6cff, 0x080c, 0x71e5, 0x001e, 0x0005, 0xe000, 0xe000, - 0x0005, 0x6020, 0xd0e4, 0x0158, 0xd0cc, 0x0118, 0x080c, 0x9ff1, - 0x0030, 0x080c, 0xb3f6, 0x080c, 0x6b61, 0x080c, 0x86a4, 0x0005, - 0xa280, 0x0007, 0x2004, 0xa084, 0x000f, 0x0002, 0xb21f, 0xb21f, - 0xb21f, 0xb224, 0xb21f, 0xb221, 0xb221, 0xb21f, 0xb221, 0xa006, - 0x0005, 0x00c6, 0x2260, 0x00ce, 0xa085, 0x0001, 0x0005, 0xa280, - 0x0007, 0x2004, 0xa084, 0x000f, 0x0002, 0xb236, 0xb236, 0xb236, - 0xb236, 0xb236, 0xb236, 0xb241, 0xb236, 0xb236, 0x6007, 0x003b, - 0x602b, 0x0009, 0x6013, 0x2a00, 0x6003, 0x0001, 0x080c, 0x6cff, - 0x0005, 0x00c6, 0x2260, 0x080c, 0xb3f6, 0x603f, 0x0000, 0x6020, - 0xc0f4, 0xc0cc, 0x6022, 0x6037, 0x0000, 0x00ce, 0x00d6, 0x2268, - 0xa186, 0x0007, 0x1904, 0xb29c, 0x6810, 0xa005, 0x0138, 0xa080, - 0x0013, 0x2004, 0xd0fc, 0x1110, 0x00de, 0x08c0, 0x6007, 0x003a, - 0x6003, 0x0001, 0x080c, 0x6cff, 0x080c, 0x71e5, 0x00c6, 0x2d60, - 0x6100, 0xa186, 0x0002, 0x1904, 0xb325, 0x6010, 0xa005, 0x1138, - 0x6000, 0xa086, 0x0007, 0x190c, 0x151a, 0x0804, 0xb325, 0xa08c, - 0xf000, 0x1130, 0x0028, 0x2068, 0x6800, 0xa005, 0x1de0, 0x2d00, - 0xa080, 0x0013, 0x2004, 0xa084, 0x0003, 0xa086, 0x0002, 0x1180, - 0x6010, 0x2068, 0x684c, 0xc0dc, 0xc0f4, 0x684e, 0x6850, 0xc0f4, - 0xc0fc, 0x6852, 0x2009, 0x0043, 0x080c, 0xac12, 0x0804, 0xb325, - 0x2009, 0x0041, 0x0804, 0xb31f, 0xa186, 0x0005, 0x15f0, 0x6810, - 0xa080, 0x0013, 0x2004, 0xd0bc, 0x1118, 0x00de, 0x0804, 0xb236, - 0xd0b4, 0x0128, 0xd0fc, 0x090c, 0x151a, 0x0804, 0xb254, 0x6007, - 0x003a, 0x6003, 0x0001, 0x080c, 0x6cff, 0x080c, 0x71e5, 0x00c6, - 0x2d60, 0x6100, 0xa186, 0x0002, 0x0120, 0xa186, 0x0004, 0x1904, - 0xb325, 0x2071, 0xb924, 0x7000, 0xa086, 0x0003, 0x1128, 0x7004, - 0xac06, 0x1110, 0x7003, 0x0000, 0x6810, 0xa080, 0x0013, 0x200c, - 0xc1f4, 0xc1dc, 0x2102, 0x8000, 0x200c, 0xc1f4, 0xc1fc, 0xc1bc, - 0x2102, 0x2009, 0x0042, 0x0804, 0xb31f, 0x0036, 0x00d6, 0x00d6, - 0x080c, 0x15fd, 0x003e, 0x090c, 0x151a, 0x6837, 0x010d, 0x6803, - 0x0000, 0x683b, 0x0000, 0x685b, 0x0000, 0x6b5e, 0x6857, 0x0045, - 0x2c00, 0x6862, 0x6034, 0x6872, 0x2360, 0x6020, 0xc0dd, 0x6022, - 0x6018, 0xa080, 0x0028, 0x2004, 0xa084, 0x00ff, 0x8007, 0x6350, - 0x6b4a, 0x6846, 0x684f, 0x0000, 0x6853, 0x0000, 0x6d6a, 0x6e66, - 0x686f, 0x0001, 0x080c, 0x547a, 0x2019, 0x0045, 0x6008, 0x2068, - 0x080c, 0xad9c, 0x2d00, 0x600a, 0x601f, 0x0006, 0x6003, 0x0007, - 0x6017, 0x0000, 0x603f, 0x0000, 0x00de, 0x003e, 0x0038, 0x603f, - 0x0000, 0x6003, 0x0007, 0x080c, 0xac12, 0x00ce, 0x00de, 0x0005, - 0xa186, 0x0013, 0x1128, 0x6004, 0xa082, 0x0085, 0x2008, 0x00c2, - 0xa186, 0x0027, 0x1178, 0x080c, 0x7102, 0x0036, 0x00d6, 0x6010, - 0x2068, 0x2019, 0x0004, 0x080c, 0xb155, 0x00de, 0x003e, 0x080c, - 0x71e5, 0x0005, 0xa186, 0x0014, 0x0d70, 0x080c, 0x86ef, 0x0005, - 0xb351, 0xb34f, 0xb34f, 0xb34f, 0xb34f, 0xb34f, 0xb351, 0x080c, - 0x151a, 0x080c, 0x7102, 0x6003, 0x000c, 0x080c, 0x71e5, 0x0005, - 0xa182, 0x008c, 0x1220, 0xa182, 0x0085, 0x0208, 0x001a, 0x080c, - 0x86ef, 0x0005, 0xb369, 0xb369, 0xb369, 0xb369, 0xb36b, 0xb389, - 0xb369, 0x080c, 0x151a, 0x00d6, 0x2c68, 0x080c, 0x864e, 0x01a0, - 0x6003, 0x0001, 0x6007, 0x001e, 0x2009, 0xbc8e, 0x210c, 0x6136, - 0x2009, 0xbc8f, 0x210c, 0x613a, 0x600b, 0xffff, 0x6918, 0x611a, - 0x601f, 0x0004, 0x080c, 0x6cff, 0x2d60, 0x080c, 0x86a4, 0x00de, - 0x0005, 0x080c, 0x86a4, 0x0005, 0x00e6, 0x6018, 0x2070, 0x7000, - 0xd0ec, 0x00ee, 0x0005, 0x6010, 0xa08c, 0xf000, 0x0904, 0xb3d7, - 0xa080, 0x0013, 0x200c, 0xd1ec, 0x05d0, 0x2001, 0xb672, 0x2004, - 0xd0ec, 0x05a8, 0x6003, 0x0002, 0x6020, 0xc0e5, 0x6022, 0xd1ac, - 0x0180, 0x00f6, 0x2c78, 0x080c, 0x5373, 0x00fe, 0x0150, 0x2001, - 0xb8b8, 0x2004, 0x603e, 0x2009, 0xb672, 0x210c, 0xd1f4, 0x11e8, - 0x0080, 0x2009, 0xb672, 0x210c, 0xd1f4, 0x0128, 0x6020, 0xc0e4, - 0x6022, 0xa006, 0x00a0, 0x2001, 0xb8b8, 0x200c, 0x8103, 0xa100, - 0x603e, 0x6018, 0xa088, 0x002b, 0x2104, 0xa005, 0x0118, 0xa088, - 0x0003, 0x0cd0, 0x2c0a, 0x600f, 0x0000, 0xa085, 0x0001, 0x0005, - 0x0016, 0x00c6, 0x00e6, 0x6150, 0xa2f0, 0x002b, 0x2e04, 0x2060, - 0x8cff, 0x0180, 0x84ff, 0x1118, 0x6050, 0xa106, 0x1138, 0x600c, - 0x2072, 0x080c, 0x6b61, 0x080c, 0x86a4, 0x0010, 0xacf0, 0x0003, - 0x2e64, 0x0c70, 0x00ee, 0x00ce, 0x001e, 0x0005, 0x00d6, 0x6018, - 0xa0e8, 0x002b, 0x2d04, 0xa005, 0x0140, 0xac06, 0x0120, 0x2d04, - 0xa0e8, 0x0003, 0x0cb8, 0x600c, 0x206a, 0x00de, 0x0005, 0x0026, - 0x0036, 0x0156, 0x2011, 0xb628, 0x2204, 0xa084, 0x00ff, 0x2019, - 0xbc8e, 0x2334, 0xa636, 0x11d8, 0x8318, 0x2334, 0x2204, 0xa084, - 0xff00, 0xa636, 0x11a0, 0x2011, 0xbc90, 0x6018, 0xa098, 0x000a, - 0x20a9, 0x0004, 0x080c, 0x9166, 0x1150, 0x2011, 0xbc94, 0x6018, - 0xa098, 0x0006, 0x20a9, 0x0004, 0x080c, 0x9166, 0x1100, 0x015e, - 0x003e, 0x002e, 0x0005, 0x00e6, 0x2071, 0xb600, 0x080c, 0x4c28, - 0x080c, 0x2aed, 0x00ee, 0x0005, 0x00e6, 0x6018, 0x2070, 0x7000, - 0xd0fc, 0x0108, 0x0011, 0x00ee, 0x0005, 0x6850, 0xc0e5, 0x6852, - 0x0005, 0x00e6, 0x00c6, 0x0076, 0x0066, 0x0056, 0x0046, 0x0026, - 0x0016, 0x0126, 0x2091, 0x8000, 0x2029, 0xb8ea, 0x252c, 0x2021, - 0xb8f0, 0x2424, 0x2061, 0xbe00, 0x2071, 0xb600, 0x7648, 0x7068, - 0xa606, 0x0578, 0x671c, 0xa786, 0x0001, 0x0118, 0xa786, 0x0008, - 0x1500, 0x2500, 0xac06, 0x01e8, 0x2400, 0xac06, 0x01d0, 0x080c, - 0xb1cc, 0x01b8, 0x080c, 0xb1dc, 0x11a0, 0x6000, 0xa086, 0x0004, - 0x1120, 0x0016, 0x080c, 0x1952, 0x001e, 0x080c, 0x9f03, 0x1110, - 0x080c, 0x2cf7, 0x080c, 0x9f14, 0x1110, 0x080c, 0x8ca5, 0x080c, - 0x9ed9, 0xace0, 0x0018, 0x2001, 0xb617, 0x2004, 0xac02, 0x1208, - 0x0858, 0x012e, 0x001e, 0x002e, 0x004e, 0x005e, 0x006e, 0x007e, - 0x00ce, 0x00ee, 0x0005, 0x0126, 0x0006, 0x00e6, 0x0016, 0x2091, - 0x8000, 0x2071, 0xb640, 0xd5a4, 0x0118, 0x7034, 0x8000, 0x7036, - 0xd5b4, 0x0118, 0x7030, 0x8000, 0x7032, 0xd5ac, 0x0178, 0x2500, - 0xa084, 0x0007, 0xa08e, 0x0003, 0x0148, 0xa08e, 0x0004, 0x0130, - 0xa08e, 0x0005, 0x0118, 0x2071, 0xb64a, 0x04c9, 0x001e, 0x00ee, - 0x000e, 0x012e, 0x0005, 0x0126, 0x0006, 0x00e6, 0x0016, 0x2091, - 0x8000, 0x2071, 0xb640, 0xd5a4, 0x0118, 0x7034, 0x8000, 0x7036, - 0xd5b4, 0x0118, 0x7030, 0x8000, 0x7032, 0xd5ac, 0x0178, 0x2500, - 0xa084, 0x0007, 0xa08e, 0x0003, 0x0148, 0xa08e, 0x0004, 0x0130, - 0xa08e, 0x0005, 0x0118, 0x2071, 0xb64a, 0x0089, 0x001e, 0x00ee, - 0x000e, 0x012e, 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, - 0x2071, 0xb642, 0x0021, 0x00ee, 0x000e, 0x012e, 0x0005, 0x2e04, - 0x8000, 0x2072, 0x1220, 0x8e70, 0x2e04, 0x8000, 0x2072, 0x0005, - 0x00e6, 0x2071, 0xb640, 0x0c99, 0x00ee, 0x0005, 0x00e6, 0x2071, - 0xb644, 0x0c69, 0x00ee, 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, - 0x8000, 0x2071, 0xb640, 0x7044, 0x8000, 0x7046, 0x00ee, 0x000e, - 0x012e, 0x0005, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, - 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, - 0x4000, 0x8000, 0xdb06 -}; -#ifdef UNIQUE_FW_NAME -unsigned short fw2200tp_length01 = 0xa52b; -#else -unsigned short risc_code_length01 = 0xa52b; -#endif - diff --git a/drivers/scsi/qla2xxx/ql2300.c b/drivers/scsi/qla2xxx/ql2300.c deleted file mode 100644 index e7a93ddda79..00000000000 --- a/drivers/scsi/qla2xxx/ql2300.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * QLogic Fibre Channel HBA Driver - * Copyright (C) 2003 Christoph Hellwig. - * Copyright (c) 2003-2005 QLogic Corporation - * - * See LICENSE.qla2xxx for copyright and licensing details. - */ -#include -#include -#include - -#include "qla_def.h" - -static char qla_driver_name[] = "qla2300"; - -extern unsigned char fw2300ipx_version[]; -extern unsigned char fw2300ipx_version_str[]; -extern unsigned short fw2300ipx_addr01; -extern unsigned short fw2300ipx_code01[]; -extern unsigned short fw2300ipx_length01; - -static struct qla_fw_info qla_fw_tbl[] = { - { - .addressing = FW_INFO_ADDR_NORMAL, - .fwcode = &fw2300ipx_code01[0], - .fwlen = &fw2300ipx_length01, - .fwstart = &fw2300ipx_addr01, - }, - { FW_INFO_ADDR_NOMORE, }, -}; - -static struct qla_board_info qla_board_tbl[] = { - { - .drv_name = qla_driver_name, - .isp_name = "ISP2300", - .fw_info = qla_fw_tbl, - }, - { - .drv_name = qla_driver_name, - .isp_name = "ISP2312", - .fw_info = qla_fw_tbl, - }, - { - .drv_name = qla_driver_name, - .isp_name = "ISP6312", - .fw_info = qla_fw_tbl, - }, -}; - -static struct pci_device_id qla2300_pci_tbl[] = { - { - .vendor = PCI_VENDOR_ID_QLOGIC, - .device = PCI_DEVICE_ID_QLOGIC_ISP2300, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = (unsigned long)&qla_board_tbl[0], - }, - { - .vendor = PCI_VENDOR_ID_QLOGIC, - .device = PCI_DEVICE_ID_QLOGIC_ISP2312, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = (unsigned long)&qla_board_tbl[1], - }, - { - .vendor = PCI_VENDOR_ID_QLOGIC, - .device = PCI_DEVICE_ID_QLOGIC_ISP6312, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = (unsigned long)&qla_board_tbl[2], - }, - {0, 0}, -}; -MODULE_DEVICE_TABLE(pci, qla2300_pci_tbl); - -static int __devinit -qla2300_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) -{ - return qla2x00_probe_one(pdev, - (struct qla_board_info *)id->driver_data); -} - -static void __devexit -qla2300_remove_one(struct pci_dev *pdev) -{ - qla2x00_remove_one(pdev); -} - -static struct pci_driver qla2300_pci_driver = { - .name = "qla2300", - .id_table = qla2300_pci_tbl, - .probe = qla2300_probe_one, - .remove = __devexit_p(qla2300_remove_one), -}; - -static int __init -qla2300_init(void) -{ - return pci_module_init(&qla2300_pci_driver); -} - -static void __exit -qla2300_exit(void) -{ - pci_unregister_driver(&qla2300_pci_driver); -} - -module_init(qla2300_init); -module_exit(qla2300_exit); - -MODULE_AUTHOR("QLogic Corporation"); -MODULE_DESCRIPTION("QLogic ISP23xx FC-SCSI Host Bus Adapter driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(QLA2XXX_VERSION); diff --git a/drivers/scsi/qla2xxx/ql2300_fw.c b/drivers/scsi/qla2xxx/ql2300_fw.c deleted file mode 100644 index b8ce7fe5d8d..00000000000 --- a/drivers/scsi/qla2xxx/ql2300_fw.c +++ /dev/null @@ -1,7746 +0,0 @@ -/* - * QLogic Fibre Channel HBA Driver - * Copyright (c) 2003-2005 QLogic Corporation - * - * See LICENSE.qla2xxx for copyright and licensing details. - */ - -/* - * Firmware Version 3.03.20 (15:39 Feb 01, 2006) - */ - -#ifdef UNIQUE_FW_NAME -unsigned short fw2300ipx_version = 3*1024+3; -#else -unsigned short risc_code_version = 3*1024+3; -#endif - -#ifdef UNIQUE_FW_NAME -unsigned char fw2300ipx_version_str[] = {3, 3,20}; -#else -unsigned char firmware_version[] = {3, 3,20}; -#endif - -#ifdef UNIQUE_FW_NAME -#define fw2300ipx_VERSION_STRING "3.03.20" -#else -#define FW_VERSION_STRING "3.03.20" -#endif - -#ifdef UNIQUE_FW_NAME -unsigned short fw2300ipx_addr01 = 0x0800 ; -#else -unsigned short risc_code_addr01 = 0x0800 ; -#endif - -#ifdef UNIQUE_FW_NAME -unsigned short fw2300ipx_code01[] = { -#else -unsigned short risc_code01[] = { -#endif - 0x0470, 0x0000, 0x0000, 0xf091, 0x0000, 0x0003, 0x0003, 0x0014, - 0x0137, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2032, 0x3030, - 0x3120, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241, - 0x5449, 0x4f4e, 0x2049, 0x5350, 0x3233, 0x3030, 0x2046, 0x6972, - 0x6d77, 0x6172, 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030, - 0x332e, 0x3033, 0x2e32, 0x3020, 0x2020, 0x2020, 0x2400, 0x20a9, - 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2200, 0x20a9, 0x000f, - 0x2001, 0x0000, 0x400f, 0x2091, 0x2400, 0x20a9, 0x000f, 0x2001, - 0x0000, 0x400f, 0x2091, 0x2600, 0x20a9, 0x000f, 0x2001, 0x0000, - 0x400f, 0x2091, 0x2800, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, - 0x2091, 0x2a00, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, - 0x2c00, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2e00, - 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2000, 0x2001, - 0x0000, 0x20c1, 0x0004, 0x20c9, 0x1bff, 0x2059, 0x0000, 0x2b78, - 0x7883, 0x0004, 0x2089, 0x2d93, 0x2051, 0x1800, 0x2a70, 0x20e1, - 0x0001, 0x20e9, 0x0001, 0x2009, 0x0000, 0x080c, 0x0e52, 0x2029, - 0x4d00, 0x2031, 0xffff, 0x2039, 0x4cd0, 0x2021, 0x0200, 0x20e9, - 0x0001, 0x20a1, 0x0000, 0x20a9, 0x0800, 0x900e, 0x4104, 0x20e9, - 0x0001, 0x20a1, 0x1000, 0x900e, 0x2001, 0x0cc0, 0x9084, 0x0fff, - 0x20a8, 0x4104, 0x2001, 0x0000, 0x9086, 0x0000, 0x0120, 0x21a8, - 0x4104, 0x8001, 0x1de0, 0x756e, 0x7672, 0x776a, 0x7476, 0x747a, - 0x00e6, 0x2071, 0x1ad1, 0x2472, 0x00ee, 0x20a1, 0x1cd0, 0x7170, - 0x810d, 0x810d, 0x810d, 0x810d, 0x918c, 0x000f, 0x2001, 0x0001, - 0x9112, 0x900e, 0x21a8, 0x4104, 0x8211, 0x1de0, 0x7170, 0x3400, - 0x8001, 0x9102, 0x0120, 0x0218, 0x20a8, 0x900e, 0x4104, 0x2009, - 0x1800, 0x810d, 0x810d, 0x810d, 0x810d, 0x810d, 0x918c, 0x001f, - 0x2001, 0x0001, 0x9112, 0x20e9, 0x0001, 0x20a1, 0x0800, 0x900e, - 0x20a9, 0x0800, 0x4104, 0x8211, 0x1dd8, 0x080c, 0x0f26, 0x080c, - 0x613c, 0x080c, 0xb269, 0x080c, 0x10dd, 0x080c, 0x12fc, 0x080c, - 0x1bd7, 0x080c, 0x0d57, 0x080c, 0x1062, 0x080c, 0x34b6, 0x080c, - 0x7946, 0x080c, 0x6b7c, 0x080c, 0x8a69, 0x080c, 0x874a, 0x080c, - 0x24b7, 0x080c, 0x93a5, 0x080c, 0x8066, 0x080c, 0x22e8, 0x080c, - 0x241c, 0x080c, 0x24ac, 0x2091, 0x3009, 0x7883, 0x0000, 0x1004, - 0x091f, 0x7880, 0x9086, 0x0002, 0x1190, 0x7883, 0x4000, 0x7837, - 0x4000, 0x7833, 0x0010, 0x0e04, 0x0913, 0x2091, 0x5000, 0x2091, - 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11aa, 0x2071, - 0x1800, 0x7003, 0x0000, 0x2071, 0x1800, 0x7000, 0x908e, 0x0003, - 0x1178, 0x080c, 0x4d09, 0x080c, 0x34dd, 0x080c, 0x79b7, 0x080c, - 0x7122, 0x080c, 0x8b50, 0x080c, 0x8776, 0x080c, 0x2cdd, 0x0c58, - 0x000b, 0x0c78, 0x0944, 0x0945, 0x0ae0, 0x0942, 0x0ba0, 0x0d56, - 0x0d56, 0x0d56, 0x080c, 0x0dc5, 0x0005, 0x0126, 0x00f6, 0x2091, - 0x8000, 0x7000, 0x9086, 0x0001, 0x1904, 0x0ab3, 0x080c, 0x0e94, - 0x080c, 0x7637, 0x0150, 0x080c, 0x765a, 0x15a0, 0x2079, 0x0100, - 0x7828, 0x9085, 0x1800, 0x782a, 0x0468, 0x080c, 0x7563, 0x7000, - 0x9086, 0x0001, 0x1904, 0x0ab3, 0x7098, 0x9086, 0x0029, 0x1904, - 0x0ab3, 0x080c, 0x8733, 0x080c, 0x8725, 0x2001, 0x0161, 0x2003, - 0x0001, 0x2079, 0x0100, 0x7827, 0xffff, 0x7a28, 0x9295, 0x5e2f, - 0x7a2a, 0x2011, 0x74b2, 0x080c, 0x883d, 0x2011, 0x74a5, 0x080c, - 0x8917, 0x2011, 0x5f97, 0x080c, 0x883d, 0x2011, 0x8030, 0x901e, - 0x7396, 0x04d0, 0x080c, 0x583f, 0x2079, 0x0100, 0x7844, 0x9005, - 0x1904, 0x0ab3, 0x2011, 0x5f97, 0x080c, 0x883d, 0x2011, 0x74b2, - 0x080c, 0x883d, 0x2011, 0x74a5, 0x080c, 0x8917, 0x2001, 0x0265, - 0x2001, 0x0205, 0x2003, 0x0000, 0x7840, 0x9084, 0xfffb, 0x7842, - 0x2001, 0x19a7, 0x2004, 0x9005, 0x1140, 0x00c6, 0x2061, 0x0100, - 0x080c, 0x60e4, 0x00ce, 0x0804, 0x0ab3, 0x780f, 0x006b, 0x7a28, - 0x080c, 0x763f, 0x0118, 0x9295, 0x5e2f, 0x0010, 0x9295, 0x402f, - 0x7a2a, 0x2011, 0x8010, 0x73d8, 0x2001, 0x19a8, 0x2003, 0x0001, - 0x080c, 0x2b82, 0x080c, 0x4c44, 0x7248, 0xc284, 0x724a, 0x2001, - 0x180c, 0x200c, 0xc1ac, 0xc1cc, 0x2102, 0x080c, 0xa9b0, 0x2011, - 0x0004, 0x080c, 0xd0e8, 0x080c, 0x6947, 0x080c, 0x7637, 0x1120, - 0x080c, 0x2bc6, 0x02e0, 0x0400, 0x080c, 0x60eb, 0x0140, 0x7097, - 0x0001, 0x70d3, 0x0000, 0x080c, 0x5a11, 0x0804, 0x0ab3, 0x080c, - 0x57d5, 0xd094, 0x0188, 0x2011, 0x180c, 0x2204, 0xc0cd, 0x2012, - 0x080c, 0x57d9, 0xd0d4, 0x1118, 0x080c, 0x2bc6, 0x1270, 0x2011, - 0x180c, 0x2204, 0xc0bc, 0x00a8, 0x080c, 0x57d9, 0xd0d4, 0x1db8, - 0x2011, 0x180c, 0x2204, 0xc0bd, 0x0060, 0x2011, 0x180c, 0x2204, - 0xc0bd, 0x2012, 0x080c, 0x6a9b, 0x1128, 0xd0a4, 0x0118, 0x2204, - 0xc0fd, 0x2012, 0x080c, 0x6a61, 0x0120, 0x7a0c, 0xc2b4, 0x7a0e, - 0x00a8, 0x707f, 0x0000, 0x080c, 0x7637, 0x1130, 0x70b0, 0x9005, - 0x1168, 0x080c, 0xd52b, 0x0050, 0x080c, 0xd52b, 0x70dc, 0xd09c, - 0x1128, 0x70b0, 0x9005, 0x0110, 0x080c, 0x60c1, 0x70e7, 0x0000, - 0x70e3, 0x0000, 0x70a7, 0x0000, 0x080c, 0x2bce, 0x0228, 0x2011, - 0x0101, 0x2204, 0xc0c4, 0x2012, 0x72dc, 0x080c, 0x7637, 0x1178, - 0x9016, 0x0016, 0x080c, 0x298b, 0x2019, 0x196d, 0x211a, 0x001e, - 0x705f, 0xffff, 0x7063, 0x00ef, 0x7083, 0x0000, 0x0020, 0x2019, - 0x196d, 0x201b, 0x0000, 0x2079, 0x1847, 0x7804, 0xd0ac, 0x0108, - 0xc295, 0x72de, 0x080c, 0x7637, 0x0118, 0x9296, 0x0004, 0x0548, - 0x2011, 0x0001, 0x080c, 0xd0e8, 0x70ab, 0x0000, 0x70af, 0xffff, - 0x7003, 0x0002, 0x2079, 0x0100, 0x7827, 0x0003, 0x7828, 0x9085, - 0x0003, 0x782a, 0x00fe, 0x080c, 0x3000, 0x2011, 0x0005, 0x080c, - 0xaabf, 0x080c, 0x9ab1, 0x080c, 0x7637, 0x0148, 0x00c6, 0x2061, - 0x0100, 0x0016, 0x080c, 0x298b, 0x61e2, 0x001e, 0x00ce, 0x012e, - 0x0420, 0x70ab, 0x0000, 0x70af, 0xffff, 0x7003, 0x0002, 0x00f6, - 0x2079, 0x0100, 0x7827, 0x0003, 0x7828, 0x9085, 0x0003, 0x782a, - 0x00fe, 0x2011, 0x0005, 0x080c, 0xaabf, 0x080c, 0x9ab1, 0x080c, - 0x7637, 0x0148, 0x00c6, 0x2061, 0x0100, 0x0016, 0x080c, 0x298b, - 0x61e2, 0x001e, 0x00ce, 0x00fe, 0x012e, 0x0005, 0x00c6, 0x00b6, - 0x080c, 0x7637, 0x1118, 0x20a9, 0x0800, 0x0010, 0x20a9, 0x0782, - 0x080c, 0x7637, 0x1110, 0x900e, 0x0010, 0x2009, 0x007e, 0x86ff, - 0x0138, 0x9180, 0x1000, 0x2004, 0x905d, 0x0110, 0xb800, 0xd0bc, - 0x090c, 0x334c, 0x8108, 0x1f04, 0x0ac7, 0x707f, 0x0000, 0x7080, - 0x9084, 0x00ff, 0x7082, 0x70b3, 0x0000, 0x00be, 0x00ce, 0x0005, - 0x00b6, 0x0126, 0x2091, 0x8000, 0x7000, 0x9086, 0x0002, 0x1904, - 0x0b9d, 0x70ac, 0x9086, 0xffff, 0x0130, 0x080c, 0x3000, 0x080c, - 0x9ab1, 0x0804, 0x0b9d, 0x70dc, 0xd0ac, 0x1110, 0xd09c, 0x0558, - 0xd084, 0x0548, 0x0006, 0x2001, 0x0103, 0x2003, 0x002b, 0x000e, - 0xd08c, 0x0508, 0x080c, 0x33af, 0x11d0, 0x70e0, 0x9086, 0xffff, - 0x01b0, 0x080c, 0x31bc, 0x080c, 0x9ab1, 0x70dc, 0xd094, 0x1904, - 0x0b9d, 0x2011, 0x0001, 0x080c, 0xd7e3, 0x0110, 0x2011, 0x0003, - 0x901e, 0x080c, 0x31f6, 0x080c, 0x9ab1, 0x0804, 0x0b9d, 0x70e4, - 0x9005, 0x1904, 0x0b9d, 0x70a8, 0x9005, 0x1904, 0x0b9d, 0x70dc, - 0xd0a4, 0x0118, 0xd0b4, 0x0904, 0x0b9d, 0x080c, 0x6a61, 0x1904, - 0x0b9d, 0x080c, 0x6ab4, 0x1904, 0x0b9d, 0x080c, 0x6a9b, 0x01c0, - 0x0156, 0x00c6, 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, 0x6724, - 0x1118, 0xb800, 0xd0ec, 0x1138, 0x001e, 0x8108, 0x1f04, 0x0b3d, - 0x00ce, 0x015e, 0x0028, 0x001e, 0x00ce, 0x015e, 0x0804, 0x0b9d, - 0x0006, 0x2001, 0x0103, 0x2003, 0x002b, 0x000e, 0x2011, 0x19b4, - 0x080c, 0x0f96, 0x2011, 0x19ce, 0x080c, 0x0f96, 0x7030, 0xc08c, - 0x7032, 0x7003, 0x0003, 0x70af, 0xffff, 0x080c, 0x0e76, 0x9006, - 0x080c, 0x281c, 0x080c, 0x33af, 0x0118, 0x080c, 0x4de1, 0x0050, - 0x0036, 0x0046, 0x2019, 0xffff, 0x2021, 0x0006, 0x080c, 0x4dfb, - 0x004e, 0x003e, 0x00f6, 0x2079, 0x0100, 0x080c, 0x765a, 0x0150, - 0x080c, 0x7637, 0x7828, 0x0118, 0x9084, 0xe1ff, 0x0010, 0x9084, - 0xffdf, 0x782a, 0x00fe, 0x2001, 0x19e9, 0x2004, 0x9086, 0x0005, - 0x1120, 0x2011, 0x0000, 0x080c, 0xaabf, 0x2011, 0x0000, 0x080c, - 0xaac9, 0x080c, 0x9ab1, 0x080c, 0x9bd3, 0x012e, 0x00be, 0x0005, - 0x0016, 0x0046, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2079, 0x0100, - 0x7904, 0x918c, 0xfffd, 0x7906, 0x2009, 0x00f7, 0x080c, 0x60aa, - 0x7940, 0x918c, 0x0010, 0x7942, 0x7924, 0xd1b4, 0x0110, 0x7827, - 0x0040, 0xd19c, 0x0110, 0x7827, 0x0008, 0x0006, 0x0036, 0x0156, - 0x7954, 0xd1ac, 0x1904, 0x0c2d, 0x2001, 0x19a8, 0x2004, 0x9005, - 0x1518, 0x080c, 0x2c49, 0x1148, 0x2001, 0x0001, 0x080c, 0x2bb1, - 0x2001, 0x0001, 0x080c, 0x2b94, 0x00b8, 0x080c, 0x2c51, 0x1138, - 0x9006, 0x080c, 0x2bb1, 0x9006, 0x080c, 0x2b94, 0x0068, 0x080c, - 0x2c59, 0x1d50, 0x2001, 0x1998, 0x2004, 0xd0fc, 0x0108, 0x0020, - 0x080c, 0x29bf, 0x0804, 0x0d0d, 0x080c, 0x7648, 0x0148, 0x080c, - 0x765a, 0x1118, 0x080c, 0x7941, 0x0050, 0x080c, 0x763f, 0x0dd0, - 0x080c, 0x793c, 0x080c, 0x7932, 0x080c, 0x7563, 0x0058, 0x080c, - 0x7637, 0x0140, 0x2009, 0x00f8, 0x080c, 0x60aa, 0x7843, 0x0090, - 0x7843, 0x0010, 0x20a9, 0x09c4, 0x7820, 0xd09c, 0x1138, 0x080c, - 0x7637, 0x0138, 0x7824, 0xd0ac, 0x1904, 0x0d12, 0x1f04, 0x0c0c, - 0x0070, 0x7824, 0x080c, 0x7651, 0x0118, 0xd0ac, 0x1904, 0x0d12, - 0x9084, 0x1800, 0x0d98, 0x7003, 0x0001, 0x0804, 0x0d12, 0x2001, - 0x0001, 0x080c, 0x281c, 0x0804, 0x0d25, 0x2001, 0x19a8, 0x2004, - 0x9005, 0x1518, 0x080c, 0x2c49, 0x1148, 0x2001, 0x0001, 0x080c, - 0x2bb1, 0x2001, 0x0001, 0x080c, 0x2b94, 0x00b8, 0x080c, 0x2c51, - 0x1138, 0x9006, 0x080c, 0x2bb1, 0x9006, 0x080c, 0x2b94, 0x0068, - 0x080c, 0x2c59, 0x1d50, 0x2001, 0x1998, 0x2004, 0xd0fc, 0x0108, - 0x0020, 0x080c, 0x29bf, 0x0804, 0x0d0d, 0x7850, 0x9085, 0x0040, - 0x7852, 0x7938, 0x7850, 0x9084, 0xfbcf, 0x7852, 0x080c, 0x2c61, - 0x9085, 0x2000, 0x7852, 0x793a, 0x20a9, 0x0046, 0x1d04, 0x0c66, - 0x080c, 0x88f7, 0x1f04, 0x0c66, 0x7850, 0x9085, 0x0400, 0x9084, - 0xdfbf, 0x7852, 0x793a, 0x080c, 0x7648, 0x0148, 0x080c, 0x765a, - 0x1118, 0x080c, 0x7941, 0x0050, 0x080c, 0x763f, 0x0dd0, 0x080c, - 0x793c, 0x080c, 0x7932, 0x080c, 0x7563, 0x0020, 0x2009, 0x00f8, - 0x080c, 0x60aa, 0x20a9, 0x0028, 0xa001, 0x1f04, 0x0c8c, 0x7850, - 0x9085, 0x1400, 0x7852, 0x080c, 0x7637, 0x0120, 0x7843, 0x0090, - 0x7843, 0x0010, 0x2021, 0xe678, 0x2019, 0xea60, 0x0d0c, 0x88f7, - 0x7820, 0xd09c, 0x1588, 0x080c, 0x7637, 0x0904, 0x0cf2, 0x7824, - 0xd0ac, 0x1904, 0x0d12, 0x080c, 0x765a, 0x1530, 0x0046, 0x2021, - 0x0320, 0x8421, 0x1df0, 0x004e, 0x7827, 0x1800, 0x080c, 0x2c61, - 0x7824, 0x9084, 0x1800, 0x1168, 0x9484, 0x0fff, 0x1140, 0x2001, - 0x1810, 0x2004, 0x9084, 0x9000, 0x0110, 0x080c, 0x0d33, 0x8421, - 0x1158, 0x1d04, 0x0ccd, 0x080c, 0x88f7, 0x080c, 0x793c, 0x080c, - 0x7932, 0x7003, 0x0001, 0x04f0, 0x8319, 0x1940, 0x1d04, 0x0cda, - 0x080c, 0x88f7, 0x2009, 0x199b, 0x2104, 0x9005, 0x0118, 0x8001, - 0x200a, 0x1178, 0x200b, 0x000a, 0x7827, 0x0048, 0x20a9, 0x0002, - 0x080c, 0x2c42, 0x7924, 0x080c, 0x2c61, 0xd19c, 0x0110, 0x080c, - 0x2b82, 0x00d8, 0x080c, 0x7648, 0x1140, 0x94a2, 0x03e8, 0x1128, - 0x080c, 0x760f, 0x7003, 0x0001, 0x00a8, 0x7827, 0x1800, 0x080c, - 0x2c61, 0x7824, 0x080c, 0x7651, 0x0110, 0xd0ac, 0x1158, 0x9084, - 0x1800, 0x0950, 0x7003, 0x0001, 0x0028, 0x2001, 0x0001, 0x080c, - 0x281c, 0x0078, 0x2009, 0x180c, 0x210c, 0xd19c, 0x1120, 0x7904, - 0x918d, 0x0002, 0x7906, 0x7827, 0x0048, 0x7828, 0x9085, 0x0028, - 0x782a, 0x7850, 0x9085, 0x0400, 0x7852, 0x2001, 0x19a8, 0x2003, - 0x0000, 0x9006, 0x78f2, 0x015e, 0x003e, 0x000e, 0x012e, 0x00fe, - 0x004e, 0x001e, 0x0005, 0x0006, 0x0016, 0x0036, 0x0046, 0x00b6, - 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x0156, 0x0069, 0x0d0c, 0x88f7, - 0x015e, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x004e, 0x003e, - 0x001e, 0x000e, 0x0005, 0x00e6, 0x2071, 0x189e, 0x7004, 0x9086, - 0x0001, 0x1110, 0x080c, 0x34dd, 0x00ee, 0x0005, 0x0005, 0x2a70, - 0x2061, 0x19ac, 0x2063, 0x0003, 0x6007, 0x0003, 0x600b, 0x0014, - 0x600f, 0x0137, 0x2001, 0x197c, 0x900e, 0x2102, 0x7196, 0x2001, - 0x0100, 0x2004, 0x9082, 0x0002, 0x0218, 0x705f, 0xffff, 0x0008, - 0x715e, 0x7067, 0xffff, 0x717e, 0x7182, 0x080c, 0xd52b, 0x70eb, - 0x00c0, 0x2061, 0x196c, 0x6003, 0x0909, 0x6106, 0x600b, 0x8800, - 0x600f, 0x0200, 0x6013, 0x00ff, 0x6017, 0x001f, 0x611a, 0x601f, - 0x07d0, 0x2061, 0x1974, 0x6003, 0x8000, 0x6106, 0x610a, 0x600f, - 0x0200, 0x6013, 0x00ff, 0x6116, 0x601b, 0x0001, 0x611e, 0x2061, - 0x1989, 0x6003, 0x514c, 0x6007, 0x4f47, 0x600b, 0x4943, 0x600f, - 0x2020, 0x2001, 0x182c, 0x2102, 0x0005, 0x9016, 0x080c, 0x6724, - 0x1178, 0xb804, 0x90c4, 0x00ff, 0x98c6, 0x0006, 0x0128, 0x90c4, - 0xff00, 0x98c6, 0x0600, 0x1120, 0x9186, 0x0080, 0x0108, 0x8210, - 0x8108, 0x9186, 0x0800, 0x1d50, 0x2208, 0x0005, 0x2091, 0x8000, - 0x2079, 0x0000, 0x000e, 0x00f6, 0x0010, 0x2091, 0x8000, 0x0e04, - 0x0dc7, 0x0006, 0x0016, 0x2001, 0x8002, 0x0006, 0x2079, 0x0000, - 0x000e, 0x7882, 0x7836, 0x001e, 0x798e, 0x000e, 0x788a, 0x000e, - 0x7886, 0x3900, 0x789a, 0x00d6, 0x2069, 0x0300, 0x6818, 0x78ae, - 0x681c, 0x78b2, 0x2001, 0x1a09, 0x2004, 0x78b6, 0x2001, 0x1a86, - 0x2004, 0x78ba, 0x6808, 0x78be, 0x00de, 0x7833, 0x0012, 0x2091, - 0x5000, 0x0156, 0x00d6, 0x0036, 0x0026, 0x2079, 0x0300, 0x2069, - 0x1aa9, 0x7a08, 0x226a, 0x2069, 0x1aaa, 0x7a18, 0x226a, 0x8d68, - 0x7a1c, 0x226a, 0x782c, 0x2019, 0x1ab7, 0x201a, 0x2019, 0x1aba, - 0x9016, 0x7808, 0xd09c, 0x0168, 0x7820, 0x201a, 0x8210, 0x8318, - 0x9386, 0x1acf, 0x0108, 0x0ca8, 0x7808, 0xd09c, 0x0110, 0x2011, - 0xdead, 0x2019, 0x1ab8, 0x782c, 0x201a, 0x8318, 0x221a, 0x7803, - 0x0000, 0x2069, 0x1a89, 0x901e, 0x20a9, 0x0020, 0x7b26, 0x7a28, - 0x226a, 0x8d68, 0x8318, 0x1f04, 0x0e26, 0x002e, 0x003e, 0x00de, - 0x015e, 0x2079, 0x1800, 0x7803, 0x0005, 0x2091, 0x4080, 0x2001, - 0x0089, 0x2004, 0xd084, 0x0180, 0x2001, 0x1a1c, 0x2004, 0x9005, - 0x0128, 0x2001, 0x008b, 0x2004, 0xd0fc, 0x0dd8, 0x2001, 0x008a, - 0x2003, 0x0002, 0x2003, 0x1001, 0x080c, 0x57e4, 0x1108, 0x0099, - 0x0cd8, 0x0005, 0x918c, 0x03ff, 0x2001, 0x0003, 0x2004, 0x9084, - 0x0600, 0x1118, 0x918d, 0x2800, 0x0010, 0x918d, 0x2000, 0x2001, - 0x017f, 0x2102, 0x0005, 0x0026, 0x0126, 0x2011, 0x0080, 0x080c, - 0x0eee, 0x20a9, 0x0900, 0x080c, 0x0f0f, 0x2011, 0x0040, 0x080c, - 0x0eee, 0x20a9, 0x0900, 0x080c, 0x0f0f, 0x0c78, 0x0026, 0x080c, - 0x0efb, 0x1118, 0x2011, 0x0040, 0x0098, 0x2011, 0x010e, 0x2214, - 0x9294, 0x0007, 0x9296, 0x0007, 0x0118, 0x2011, 0xa880, 0x0010, - 0x2011, 0x6840, 0xd0e4, 0x70ef, 0x0000, 0x1120, 0x70ef, 0x0fa0, - 0x080c, 0x0f00, 0x002e, 0x0005, 0x0026, 0x080c, 0x0efb, 0x0128, - 0xd0a4, 0x1138, 0x2011, 0xcdd5, 0x0010, 0x2011, 0x0080, 0x080c, - 0x0f00, 0x002e, 0x0005, 0x0026, 0x70ef, 0x0000, 0x080c, 0x0efb, - 0x1148, 0x080c, 0x2c59, 0x1118, 0x2011, 0x8484, 0x0058, 0x2011, - 0x8282, 0x0040, 0x080c, 0x2c59, 0x1118, 0x2011, 0xcdc5, 0x0010, - 0x2011, 0xcac2, 0x080c, 0x0f00, 0x002e, 0x0005, 0x00e6, 0x0006, - 0x2071, 0x1800, 0xd0b4, 0x70e8, 0x1110, 0xc0e4, 0x0048, 0x0006, - 0x3b00, 0x9084, 0xff3f, 0x20d8, 0x000e, 0x70ef, 0x0000, 0xc0e5, - 0x0079, 0x000e, 0x00ee, 0x0005, 0x00e6, 0x2071, 0x1800, 0xd0e4, - 0x70e8, 0x1110, 0xc0dc, 0x0008, 0xc0dd, 0x0011, 0x00ee, 0x0005, - 0x70ea, 0x7000, 0x9084, 0x0007, 0x000b, 0x0005, 0x0ebd, 0x0e94, - 0x0e94, 0x0e76, 0x0ea3, 0x0e94, 0x0e94, 0x0ea3, 0x0016, 0x3b08, - 0x3a00, 0x9104, 0x918d, 0x00c0, 0x21d8, 0x9084, 0xff3f, 0x9205, - 0x20d0, 0x001e, 0x0005, 0x2001, 0x183a, 0x2004, 0xd0dc, 0x0005, - 0x9e86, 0x1800, 0x190c, 0x0dc5, 0x70e8, 0xd0e4, 0x0108, 0xc2e5, - 0x72ea, 0xd0e4, 0x1118, 0x9294, 0x00c0, 0x0c01, 0x0005, 0x1d04, - 0x0f0f, 0x2091, 0x6000, 0x1f04, 0x0f0f, 0x0005, 0x890e, 0x810e, - 0x810f, 0x9194, 0x003f, 0x918c, 0xffc0, 0x0005, 0x0006, 0x2200, - 0x914d, 0x894f, 0x894d, 0x894d, 0x000e, 0x0005, 0x01d6, 0x0146, - 0x0036, 0x0096, 0x2061, 0x188d, 0x600b, 0x0000, 0x600f, 0x0000, - 0x6003, 0x0000, 0x6007, 0x0000, 0x2009, 0xffc0, 0x2105, 0x0006, - 0x2001, 0xaaaa, 0x200f, 0x2019, 0x5555, 0x9016, 0x2049, 0x0bff, - 0xab02, 0xa001, 0xa001, 0xa800, 0x9306, 0x1138, 0x2105, 0x9306, - 0x0120, 0x8210, 0x99c8, 0x0400, 0x0c98, 0x000e, 0x200f, 0x2001, - 0x189d, 0x928a, 0x000e, 0x1638, 0x928a, 0x0006, 0x2011, 0x0006, - 0x1210, 0x2011, 0x0000, 0x2202, 0x9006, 0x2008, 0x82ff, 0x01b0, - 0x8200, 0x600a, 0x600f, 0xffff, 0x6003, 0x0002, 0x6007, 0x0000, - 0x0026, 0x2019, 0x0010, 0x9280, 0x0001, 0x20e8, 0x21a0, 0x21a8, - 0x4104, 0x8319, 0x1de0, 0x8211, 0x1da0, 0x002e, 0x009e, 0x003e, - 0x014e, 0x01de, 0x0005, 0x2011, 0x000e, 0x08e8, 0x0016, 0x0026, - 0x0096, 0x3348, 0x080c, 0x0f16, 0x2100, 0x9300, 0x2098, 0x22e0, - 0x009e, 0x002e, 0x001e, 0x0036, 0x3518, 0x20a9, 0x0001, 0x4002, - 0x8007, 0x4004, 0x8319, 0x1dd8, 0x003e, 0x0005, 0x20e9, 0x0001, - 0x71b8, 0x81ff, 0x11c0, 0x9006, 0x2009, 0x0200, 0x20a9, 0x0002, - 0x9298, 0x0018, 0x23a0, 0x4001, 0x2009, 0x0700, 0x20a9, 0x0002, - 0x9298, 0x0008, 0x23a0, 0x4001, 0x707c, 0x8007, 0x7180, 0x810f, - 0x20a9, 0x0002, 0x4001, 0x9298, 0x000c, 0x23a0, 0x900e, 0x080c, - 0x0da5, 0x2001, 0x0000, 0x810f, 0x20a9, 0x0002, 0x4001, 0x0005, - 0x89ff, 0x0140, 0xa804, 0xa807, 0x0000, 0x0006, 0x080c, 0x1040, - 0x009e, 0x0cb0, 0x0005, 0x00e6, 0x2071, 0x1800, 0x080c, 0x10b9, - 0x090c, 0x0dc5, 0x00ee, 0x0005, 0x0086, 0x00e6, 0x0006, 0x0026, - 0x0036, 0x0126, 0x2091, 0x8000, 0x00c9, 0x2071, 0x1800, 0x73c0, - 0x702c, 0x9016, 0x9045, 0x0158, 0x8210, 0x9906, 0x090c, 0x0dc5, - 0x2300, 0x9202, 0x0120, 0x1a0c, 0x0dc5, 0xa000, 0x0c98, 0x012e, - 0x003e, 0x002e, 0x000e, 0x00ee, 0x008e, 0x0005, 0x0086, 0x00e6, - 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x1910, 0x7010, 0x9005, - 0x0140, 0x7018, 0x9045, 0x0128, 0x9906, 0x090c, 0x0dc5, 0xa000, - 0x0cc8, 0x012e, 0x000e, 0x00ee, 0x008e, 0x0005, 0x00e6, 0x2071, - 0x1800, 0x0126, 0x2091, 0x8000, 0x70c0, 0x8001, 0x0270, 0x70c2, - 0x702c, 0x2048, 0x9085, 0x0001, 0xa800, 0x702e, 0xa803, 0x0000, - 0xa807, 0x0000, 0x012e, 0x00ee, 0x0005, 0x904e, 0x0cd8, 0x00e6, - 0x0126, 0x2091, 0x8000, 0x2071, 0x1800, 0x70c0, 0x90ca, 0x0020, - 0x0268, 0x8001, 0x70c2, 0x702c, 0x2048, 0xa800, 0x702e, 0xa803, - 0x0000, 0xa807, 0x0000, 0x012e, 0x00ee, 0x0005, 0x904e, 0x0cd8, - 0x00e6, 0x0126, 0x2091, 0x8000, 0x0016, 0x890e, 0x810e, 0x810f, - 0x9184, 0x003f, 0xa862, 0x9184, 0xffc0, 0xa85e, 0x001e, 0x0020, - 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0x1800, 0x702c, 0xa802, - 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, 0x8725, 0x012e, - 0x00ee, 0x0005, 0x2071, 0x1800, 0x9026, 0x2009, 0x0000, 0x2049, - 0x0400, 0x2900, 0x702e, 0x8940, 0x2800, 0xa802, 0xa95e, 0xa863, - 0x0001, 0x8420, 0x9886, 0x0440, 0x0120, 0x2848, 0x9188, 0x0040, - 0x0c90, 0x2071, 0x188d, 0x7000, 0x9005, 0x11a0, 0x2001, 0x0534, - 0xa802, 0x2048, 0x2009, 0x4d00, 0x8940, 0x2800, 0xa802, 0xa95e, - 0xa863, 0x0001, 0x8420, 0x9886, 0x0800, 0x0120, 0x2848, 0x9188, - 0x0040, 0x0c90, 0x2071, 0x188d, 0x7104, 0x7200, 0x82ff, 0x01d0, - 0x7308, 0x8318, 0x831f, 0x831b, 0x831b, 0x7312, 0x8319, 0x2001, - 0x0800, 0xa802, 0x2048, 0x8900, 0xa802, 0x2040, 0xa95e, 0xaa62, - 0x8420, 0x2300, 0x9906, 0x0130, 0x2848, 0x9188, 0x0040, 0x9291, - 0x0000, 0x0c88, 0xa803, 0x0000, 0x2071, 0x1800, 0x74be, 0x74c2, - 0x0005, 0x00e6, 0x0016, 0x9984, 0xfc00, 0x01e8, 0x908c, 0xf800, - 0x1168, 0x9982, 0x0400, 0x02b8, 0x9982, 0x0440, 0x0278, 0x9982, - 0x0534, 0x0288, 0x9982, 0x0800, 0x1270, 0x0040, 0x9982, 0x0800, - 0x0250, 0x2071, 0x188d, 0x7010, 0x9902, 0x1228, 0x9085, 0x0001, - 0x001e, 0x00ee, 0x0005, 0x9006, 0x0cd8, 0x00e6, 0x2071, 0x1a1b, - 0x7007, 0x0000, 0x9006, 0x701e, 0x7022, 0x7002, 0x2071, 0x0000, - 0x7010, 0x9085, 0x8044, 0x7012, 0x2071, 0x0080, 0x9006, 0x20a9, - 0x0040, 0x7022, 0x1f04, 0x10f1, 0x702b, 0x0020, 0x00ee, 0x0005, - 0x0126, 0x2091, 0x8000, 0x00e6, 0xa06f, 0x0000, 0x2071, 0x1a1b, - 0x701c, 0x9088, 0x1a25, 0x280a, 0x8000, 0x9084, 0x003f, 0x701e, - 0x7120, 0x9106, 0x090c, 0x0dc5, 0x7004, 0x9005, 0x1128, 0x00f6, - 0x2079, 0x0080, 0x00a9, 0x00fe, 0x00ee, 0x012e, 0x0005, 0x0126, - 0x2091, 0x8000, 0x00e6, 0x2071, 0x1a1b, 0x7004, 0x9005, 0x1128, - 0x00f6, 0x2079, 0x0080, 0x0021, 0x00fe, 0x00ee, 0x012e, 0x0005, - 0x7004, 0x9086, 0x0000, 0x1110, 0x7007, 0x0006, 0x7000, 0x0002, - 0x113a, 0x12bd, 0x1138, 0x1138, 0x12b1, 0x12b1, 0x12b1, 0x12b1, - 0x080c, 0x0dc5, 0x701c, 0x7120, 0x9106, 0x1148, 0x792c, 0x9184, - 0x0001, 0x1120, 0xd1fc, 0x1110, 0x7007, 0x0000, 0x0005, 0x0096, - 0x9180, 0x1a25, 0x2004, 0x700a, 0x2048, 0x8108, 0x918c, 0x003f, - 0x7122, 0x782b, 0x0026, 0xa88c, 0x7802, 0xa890, 0x7806, 0xa894, - 0x780a, 0xa898, 0x780e, 0xa878, 0x700e, 0xa870, 0x7016, 0xa874, - 0x701a, 0xa868, 0x009e, 0xd084, 0x0120, 0x7007, 0x0001, 0x0029, - 0x0005, 0x7007, 0x0002, 0x00b1, 0x0005, 0x0016, 0x0026, 0x710c, - 0x2011, 0x0040, 0x9182, 0x0040, 0x1210, 0x2110, 0x9006, 0x700e, - 0x7212, 0x8203, 0x7812, 0x782b, 0x0020, 0x782b, 0x0041, 0x002e, - 0x001e, 0x0005, 0x0016, 0x0026, 0x0136, 0x0146, 0x0156, 0x7014, - 0x20e0, 0x7018, 0x2098, 0x20e9, 0x0000, 0x20a1, 0x0088, 0x782b, - 0x0026, 0x710c, 0x2011, 0x0040, 0x9182, 0x0040, 0x1210, 0x2110, - 0x9006, 0x700e, 0x22a8, 0x4006, 0x8203, 0x7812, 0x782b, 0x0020, - 0x3300, 0x701a, 0x782b, 0x0001, 0x015e, 0x014e, 0x013e, 0x002e, - 0x001e, 0x0005, 0x2009, 0x1a1b, 0x2104, 0xc095, 0x200a, 0x080c, - 0x1117, 0x0005, 0x0016, 0x00e6, 0x2071, 0x1a1b, 0x00f6, 0x2079, - 0x0080, 0x792c, 0xd1bc, 0x190c, 0x0dbe, 0x782b, 0x0002, 0xd1fc, - 0x0120, 0x918c, 0x0700, 0x7004, 0x0023, 0x00fe, 0x00ee, 0x001e, - 0x0005, 0x1128, 0x11d0, 0x1204, 0x12dc, 0x0dc5, 0x12f7, 0x0dc5, - 0x918c, 0x0700, 0x1550, 0x0136, 0x0146, 0x0156, 0x7014, 0x20e8, - 0x7018, 0x20a0, 0x20e1, 0x0000, 0x2099, 0x0088, 0x782b, 0x0040, - 0x7010, 0x20a8, 0x4005, 0x3400, 0x701a, 0x015e, 0x014e, 0x013e, - 0x700c, 0x9005, 0x0578, 0x7800, 0x7802, 0x7804, 0x7806, 0x080c, - 0x116d, 0x0005, 0x7008, 0x0096, 0x2048, 0xa86f, 0x0100, 0x009e, - 0x7007, 0x0000, 0x080c, 0x1128, 0x0005, 0x7008, 0x0096, 0x2048, - 0xa86f, 0x0200, 0x009e, 0x0ca0, 0x918c, 0x0700, 0x1150, 0x700c, - 0x9005, 0x0180, 0x7800, 0x7802, 0x7804, 0x7806, 0x080c, 0x1182, - 0x0005, 0x7008, 0x0096, 0x2048, 0xa86f, 0x0200, 0x009e, 0x7007, - 0x0000, 0x0080, 0x0096, 0x7008, 0x2048, 0x7800, 0xa88e, 0x7804, - 0xa892, 0x7808, 0xa896, 0x780c, 0xa89a, 0xa86f, 0x0100, 0x009e, - 0x7007, 0x0000, 0x0096, 0x00d6, 0x7008, 0x2048, 0x2001, 0x18b9, - 0x2004, 0x9906, 0x1128, 0xa89c, 0x080f, 0x00de, 0x009e, 0x00a0, - 0x00de, 0x009e, 0x0096, 0x00d6, 0x7008, 0x2048, 0x0081, 0x0150, - 0xa89c, 0x0086, 0x2940, 0x080f, 0x008e, 0x00de, 0x009e, 0x080c, - 0x1117, 0x0005, 0x00de, 0x009e, 0x080c, 0x1117, 0x0005, 0xa8a8, - 0xd08c, 0x0005, 0x0096, 0xa0a0, 0x904d, 0x090c, 0x0dc5, 0xa06c, - 0x908e, 0x0100, 0x0130, 0xa87b, 0x0030, 0xa883, 0x0000, 0xa897, - 0x4002, 0x080c, 0x6e92, 0xa09f, 0x0000, 0xa0a3, 0x0000, 0x2848, - 0x080c, 0x1040, 0x009e, 0x0005, 0x00a6, 0xa0a0, 0x904d, 0x090c, - 0x0dc5, 0xa06c, 0x908e, 0x0100, 0x0128, 0xa87b, 0x0001, 0xa883, - 0x0000, 0x00c0, 0xa80c, 0x2050, 0xb004, 0x9005, 0x0198, 0xa80e, - 0x2050, 0x8006, 0x8006, 0x8007, 0x908c, 0x003f, 0x9084, 0xffc0, - 0x9080, 0x0002, 0xa076, 0xa172, 0xb000, 0xa07a, 0x2810, 0x080c, - 0x10f8, 0x00e8, 0xa97c, 0xa894, 0x0016, 0x0006, 0x080c, 0x6e92, - 0x000e, 0x001e, 0xd1fc, 0x1138, 0xd1f4, 0x0128, 0x00c6, 0x2060, - 0x080c, 0xb2d3, 0x00ce, 0x7008, 0x2048, 0xa89f, 0x0000, 0xa8a3, - 0x0000, 0x080c, 0x1040, 0x7007, 0x0000, 0x080c, 0x1117, 0x00ae, - 0x0005, 0x0126, 0x2091, 0x8000, 0x782b, 0x1001, 0x7007, 0x0005, - 0x7000, 0xc094, 0x7002, 0x012e, 0x0005, 0x0096, 0x2001, 0x192f, - 0x204c, 0xa87c, 0x7812, 0xa88c, 0x7802, 0xa890, 0x7806, 0xa894, - 0x780a, 0xa898, 0x780e, 0x782b, 0x0020, 0x0126, 0x2091, 0x8000, - 0x782b, 0x0041, 0x7007, 0x0003, 0x7000, 0xc084, 0x7002, 0x2900, - 0x700a, 0x012e, 0x009e, 0x0005, 0x20e1, 0x0000, 0x2099, 0x0088, - 0x782b, 0x0040, 0x0096, 0x2001, 0x192f, 0x204c, 0xaa7c, 0x009e, - 0x080c, 0x8d91, 0x2009, 0x188c, 0x2104, 0x9084, 0xfffc, 0x200a, - 0x080c, 0x8bf3, 0x7007, 0x0000, 0x080c, 0x1128, 0x0005, 0x7007, - 0x0000, 0x080c, 0x1128, 0x0005, 0x0126, 0x2091, 0x2200, 0x2079, - 0x0300, 0x2071, 0x1a65, 0x7003, 0x0000, 0x78bf, 0x00f6, 0x781b, - 0x4800, 0x00c1, 0x7803, 0x0003, 0x780f, 0x0000, 0x20a9, 0x03ea, - 0x2061, 0xf0ae, 0x2c0d, 0x7912, 0xe104, 0x9ce0, 0x0002, 0x7916, - 0x1f04, 0x1312, 0x7807, 0x0007, 0x7803, 0x0000, 0x7803, 0x0001, - 0x012e, 0x0005, 0x00c6, 0x7803, 0x0000, 0x7808, 0xd09c, 0x0120, - 0x7820, 0x080c, 0x1376, 0x0cc8, 0x2001, 0x1a66, 0x2003, 0x0000, - 0x78ab, 0x0004, 0x78ac, 0xd0ac, 0x1de8, 0x78ab, 0x0002, 0x7807, - 0x0007, 0x7827, 0x0030, 0x782b, 0x0400, 0x7827, 0x0031, 0x782b, - 0x1a89, 0x781f, 0xff00, 0x781b, 0xb700, 0x2001, 0x0200, 0x2004, - 0xd0dc, 0x0110, 0x781f, 0x0303, 0x2061, 0x1a89, 0x602f, 0x1cd0, - 0x2001, 0x181a, 0x2004, 0x9082, 0x1cd0, 0x6032, 0x603b, 0x20c7, - 0x2001, 0x33b6, 0xd0fc, 0x190c, 0x0dc5, 0x2001, 0x1810, 0x2004, - 0xd0c4, 0x1128, 0x2001, 0x0003, 0x2004, 0xd0d4, 0x1118, 0x783f, - 0x33b6, 0x0020, 0x9084, 0xc000, 0x783f, 0xb3b6, 0x604f, 0x193d, - 0x2001, 0x1928, 0x2004, 0x6042, 0x00ce, 0x0005, 0x9086, 0x000d, - 0x11d0, 0x7808, 0xd09c, 0x01b8, 0x7820, 0x0026, 0x2010, 0x080c, - 0xd0c6, 0x0180, 0x2260, 0x6000, 0x9086, 0x0004, 0x1158, 0x0016, - 0x6120, 0x9186, 0x0009, 0x0108, 0x0020, 0x2009, 0x004c, 0x080c, - 0xb352, 0x001e, 0x002e, 0x0005, 0x0126, 0x2091, 0x2200, 0x7908, - 0x9184, 0x0070, 0x190c, 0x0dbe, 0xd19c, 0x0158, 0x7820, 0x908c, - 0xf000, 0x15e8, 0x908a, 0x0024, 0x1a0c, 0x0dc5, 0x0023, 0x012e, - 0x0005, 0x012e, 0x0005, 0x13cf, 0x13cf, 0x13e6, 0x13eb, 0x13ef, - 0x13f4, 0x141c, 0x1420, 0x142e, 0x1432, 0x13cf, 0x14ff, 0x1503, - 0x1575, 0x157c, 0x13cf, 0x157d, 0x157e, 0x1589, 0x1590, 0x13cf, - 0x13cf, 0x13cf, 0x13cf, 0x13cf, 0x13cf, 0x13cf, 0x13f6, 0x13cf, - 0x13cf, 0x13cf, 0x13cf, 0x13cf, 0x13cf, 0x13d3, 0x13d1, 0x080c, - 0x0dc5, 0x080c, 0x0dbe, 0x080c, 0x159b, 0x2009, 0x1a7e, 0x2104, - 0x8000, 0x200a, 0x080c, 0x813a, 0x080c, 0x1ad9, 0x0005, 0x2009, - 0x0048, 0x2060, 0x080c, 0xb352, 0x012e, 0x0005, 0x7004, 0xc085, - 0xc0b5, 0x7006, 0x0005, 0x7004, 0xc085, 0x7006, 0x0005, 0x080c, - 0x159b, 0x080c, 0x16fb, 0x0005, 0x080c, 0x0dc5, 0x080c, 0x159b, - 0x2060, 0x6014, 0x0096, 0x2048, 0xa83b, 0xffff, 0x009e, 0x2009, - 0x0048, 0x080c, 0xb352, 0x2001, 0x015d, 0x2003, 0x0000, 0x2009, - 0x03e8, 0x8109, 0x0160, 0x2001, 0x0201, 0x2004, 0x9005, 0x0dc8, - 0x2001, 0x0218, 0x2004, 0xd0ec, 0x1110, 0x080c, 0x15a0, 0x2001, - 0x0307, 0x2003, 0x8000, 0x0005, 0x7004, 0xc095, 0x7006, 0x0005, - 0x080c, 0x159b, 0x2060, 0x6014, 0x0096, 0x2048, 0xa83b, 0xffff, - 0x009e, 0x2009, 0x0048, 0x080c, 0xb352, 0x0005, 0x080c, 0x159b, - 0x080c, 0x0dc5, 0x080c, 0x159b, 0x080c, 0x14ea, 0x7827, 0x0018, - 0x79ac, 0xd1dc, 0x0904, 0x149b, 0x7827, 0x0015, 0x7828, 0x782b, - 0x0000, 0x9065, 0x0140, 0x2001, 0x020d, 0x2003, 0x0050, 0x2003, - 0x0020, 0x0804, 0x14a1, 0x7004, 0x9005, 0x01c8, 0x1188, 0x78ab, - 0x0004, 0x7827, 0x0018, 0x782b, 0x0000, 0xd1bc, 0x090c, 0x0dc5, - 0x2001, 0x020d, 0x2003, 0x0050, 0x2003, 0x0020, 0x0804, 0x14cf, - 0x78ab, 0x0004, 0x7803, 0x0001, 0x080c, 0x1503, 0x0005, 0x7827, - 0x0018, 0xa001, 0x7828, 0x7827, 0x0011, 0xa001, 0x7928, 0x9106, - 0x0110, 0x79ac, 0x08e0, 0x00e6, 0x2071, 0x0200, 0x702c, 0xd0c4, - 0x0140, 0x00ee, 0x080c, 0x1ad9, 0x080c, 0x1322, 0x7803, 0x0001, - 0x0005, 0x7037, 0x0001, 0xa001, 0x7150, 0x00ee, 0x918c, 0xff00, - 0x9186, 0x0500, 0x0110, 0x79ac, 0x0810, 0x7004, 0xc09d, 0x7006, - 0x78ab, 0x0004, 0x7803, 0x0001, 0x080c, 0x1503, 0x2001, 0x020d, - 0x2003, 0x0020, 0x0005, 0x7828, 0x782b, 0x0000, 0x9065, 0x090c, - 0x0dc5, 0x6014, 0x2048, 0x78ab, 0x0004, 0x918c, 0x0700, 0x01a8, - 0x080c, 0x813a, 0x080c, 0x1ad9, 0x080c, 0xd0d8, 0x0158, 0xa9ac, - 0xa936, 0xa9b0, 0xa93a, 0xa83f, 0xffff, 0xa843, 0xffff, 0xa880, - 0xc0bd, 0xa882, 0x080c, 0xccf3, 0x0005, 0x6020, 0x9086, 0x0009, - 0x1128, 0x2009, 0x004c, 0x080c, 0xb352, 0x0048, 0x6010, 0x00b6, - 0x2058, 0xb800, 0x00be, 0xd0bc, 0x6024, 0x190c, 0xd4c4, 0x2029, - 0x00c8, 0x8529, 0x0128, 0x2001, 0x0201, 0x2004, 0x9005, 0x0dc8, - 0x7dbc, 0x080c, 0xf057, 0xd5a4, 0x1118, 0x080c, 0x15a0, 0x0005, - 0x080c, 0x813a, 0x080c, 0x1ad9, 0x0005, 0x781f, 0x0300, 0x7803, - 0x0001, 0x0005, 0x0016, 0x0066, 0x0076, 0x00f6, 0x2079, 0x0300, - 0x7908, 0x918c, 0x0007, 0x9186, 0x0003, 0x0120, 0x2001, 0x0016, - 0x080c, 0x1611, 0x00fe, 0x007e, 0x006e, 0x001e, 0x0005, 0x7004, - 0xc09d, 0x7006, 0x0005, 0x7104, 0x9184, 0x0004, 0x190c, 0x0dc5, - 0xd184, 0x11b1, 0xd19c, 0x0180, 0xc19c, 0x7106, 0x0016, 0x080c, - 0x16de, 0x001e, 0x0148, 0x2001, 0x020d, 0x2003, 0x0050, 0x2003, - 0x0020, 0x080c, 0x15a0, 0x0005, 0x81ff, 0x190c, 0x0dc5, 0x0005, - 0x2100, 0xc184, 0xc1b4, 0x7106, 0xd0b4, 0x0016, 0x00e6, 0x1904, - 0x156a, 0x2071, 0x0200, 0x080c, 0x16cb, 0x05e0, 0x080c, 0x16de, - 0x05b0, 0x6014, 0x9005, 0x05b0, 0x0096, 0x2048, 0xa864, 0x009e, - 0x9084, 0x00ff, 0x908e, 0x0029, 0x0160, 0x908e, 0x0048, 0x1550, - 0x601c, 0xd084, 0x11e0, 0x00f6, 0x2c78, 0x080c, 0x1768, 0x00fe, - 0x00b0, 0x00f6, 0x2c78, 0x080c, 0x18fd, 0x00fe, 0x2009, 0x01f4, - 0x8109, 0x0168, 0x2001, 0x0201, 0x2004, 0x9005, 0x0dc8, 0x2001, - 0x0218, 0x2004, 0xd0ec, 0x1118, 0x080c, 0x15a0, 0x0040, 0x2001, - 0x020d, 0x2003, 0x0020, 0x080c, 0x1322, 0x7803, 0x0001, 0x00ee, - 0x001e, 0x0005, 0x080c, 0x16de, 0x0dd0, 0x2001, 0x020d, 0x2003, - 0x0050, 0x2003, 0x0020, 0x0461, 0x0c90, 0x0429, 0x2060, 0x2009, - 0x0053, 0x080c, 0xb352, 0x0005, 0x0005, 0x0005, 0x00e1, 0x2008, - 0x00d1, 0x0006, 0x7004, 0xc09d, 0x7006, 0x000e, 0x080c, 0x90de, - 0x0005, 0x0089, 0x9005, 0x0118, 0x080c, 0x8ce2, 0x0cd0, 0x0005, - 0x2001, 0x0036, 0x2009, 0x1820, 0x210c, 0x2011, 0x181f, 0x2214, - 0x080c, 0x1611, 0x0005, 0x7808, 0xd09c, 0x0de8, 0x7820, 0x0005, - 0x080c, 0x14ea, 0x00d6, 0x2069, 0x0200, 0x2009, 0x01f4, 0x8109, - 0x0510, 0x6804, 0x9005, 0x0dd8, 0x2001, 0x015d, 0x2003, 0x0000, - 0x79bc, 0xd1a4, 0x1528, 0x79b8, 0x918c, 0x0fff, 0x0180, 0x9182, - 0x0841, 0x1268, 0x9188, 0x0007, 0x918c, 0x0ff8, 0x810c, 0x810c, - 0x810c, 0x080c, 0x1603, 0x6827, 0x0001, 0x8109, 0x1dd0, 0x04d9, - 0x6827, 0x0002, 0x04c1, 0x6804, 0x9005, 0x1130, 0x682c, 0xd0e4, - 0x1500, 0x6804, 0x9005, 0x0de8, 0x79b8, 0xd1ec, 0x1130, 0x08c0, - 0x080c, 0x813a, 0x080c, 0x1ad9, 0x0090, 0x7827, 0x0015, 0x782b, - 0x0000, 0x7827, 0x0018, 0x782b, 0x0000, 0x2001, 0x020d, 0x2003, - 0x0020, 0x2001, 0x0307, 0x2003, 0x0300, 0x7803, 0x0001, 0x00de, - 0x0005, 0x682c, 0x9084, 0x5400, 0x9086, 0x5400, 0x0d30, 0x7827, - 0x0015, 0x782b, 0x0000, 0x7803, 0x0001, 0x6800, 0x9085, 0x1800, - 0x6802, 0x00de, 0x0005, 0x6824, 0x9084, 0x0003, 0x1de0, 0x0005, - 0x2001, 0x0030, 0x2c08, 0x621c, 0x0021, 0x7830, 0x9086, 0x0041, - 0x0005, 0x00f6, 0x2079, 0x0300, 0x0006, 0x7808, 0xd09c, 0x0140, - 0x0016, 0x0026, 0x00c6, 0x080c, 0x1394, 0x00ce, 0x002e, 0x001e, - 0x000e, 0x0006, 0x7832, 0x7936, 0x7a3a, 0x781b, 0x8080, 0x0059, - 0x1118, 0x000e, 0x00fe, 0x0005, 0x000e, 0x792c, 0x3900, 0x8000, - 0x2004, 0x080c, 0x0dc5, 0x2009, 0x180c, 0x2104, 0xc0f4, 0x200a, - 0x2009, 0xff00, 0x8109, 0x0904, 0x168f, 0x7a18, 0x9284, 0x0030, - 0x0904, 0x168a, 0x9284, 0x0048, 0x9086, 0x0008, 0x1904, 0x168a, - 0x2001, 0x0109, 0x2004, 0xd08c, 0x01f0, 0x0006, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x0126, 0x2091, 0x2800, 0x00f6, 0x0026, - 0x0016, 0x2009, 0x1a81, 0x2104, 0x8000, 0x0208, 0x200a, 0x080c, - 0x94b1, 0x001e, 0x002e, 0x00fe, 0x012e, 0x015e, 0x014e, 0x013e, - 0x01de, 0x01ce, 0x000e, 0x2001, 0x009b, 0x2004, 0xd0fc, 0x01d0, - 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x00f6, - 0x0016, 0x2009, 0x1a82, 0x2104, 0x8000, 0x0208, 0x200a, 0x080c, - 0x1eeb, 0x001e, 0x00fe, 0x015e, 0x014e, 0x013e, 0x01de, 0x01ce, - 0x012e, 0x000e, 0x7818, 0xd0bc, 0x1904, 0x163a, 0x0005, 0x2001, - 0x180c, 0x2004, 0xd0f4, 0x1528, 0x7a18, 0x9284, 0x0030, 0x0508, - 0x9284, 0x0048, 0x9086, 0x0008, 0x11e0, 0x2001, 0x19f7, 0x2004, - 0x9005, 0x01b8, 0x2001, 0x1a69, 0x2004, 0x9086, 0x0000, 0x0188, - 0x2009, 0x1a80, 0x2104, 0x8000, 0x0208, 0x200a, 0x080c, 0xa767, - 0x2009, 0x180c, 0x2104, 0xc0f5, 0x200a, 0x2009, 0xff00, 0x0804, - 0x163a, 0x9085, 0x0001, 0x0005, 0x7832, 0x7936, 0x7a3a, 0x781b, - 0x8080, 0x080c, 0x1633, 0x1108, 0x0005, 0x792c, 0x3900, 0x8000, - 0x2004, 0x080c, 0x0dc5, 0x7037, 0x0001, 0x7150, 0x7037, 0x0002, - 0x7050, 0x2060, 0xd1bc, 0x1110, 0x7054, 0x2060, 0x918c, 0xff00, - 0x9186, 0x0500, 0x0110, 0x9085, 0x0001, 0x0005, 0x0006, 0x0046, - 0x00e6, 0x2071, 0x0200, 0x7037, 0x0002, 0x7058, 0x9084, 0xff00, - 0x8007, 0x9086, 0x00bc, 0x1158, 0x2021, 0x1a7f, 0x2404, 0x8000, - 0x0208, 0x2022, 0x080c, 0x813a, 0x080c, 0x1ad9, 0x9006, 0x00ee, - 0x004e, 0x000e, 0x0005, 0x0c11, 0x1108, 0x0005, 0x00e6, 0x0016, - 0x2071, 0x0200, 0x0841, 0x6124, 0xd1dc, 0x01f8, 0x701c, 0xd08c, - 0x0904, 0x175d, 0x7017, 0x0000, 0x2001, 0x0264, 0x2004, 0xd0bc, - 0x0904, 0x175d, 0x2001, 0x0268, 0x00c6, 0x2064, 0x6104, 0x6038, - 0x00ce, 0x918e, 0x0039, 0x1904, 0x175d, 0x9c06, 0x15f0, 0x0126, - 0x2091, 0x2600, 0x080c, 0x8081, 0x012e, 0x7358, 0x745c, 0x6014, - 0x905d, 0x0598, 0x2b48, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, - 0xd0bc, 0x190c, 0xd49f, 0xab42, 0xac3e, 0x2001, 0x1869, 0x2004, - 0xd0b4, 0x1170, 0x601c, 0xd0e4, 0x1158, 0x6010, 0x00b6, 0x2058, - 0xb800, 0x00be, 0xd0bc, 0x1120, 0xa83b, 0x7fff, 0xa837, 0xffff, - 0x080c, 0x20e7, 0x1190, 0x080c, 0x195a, 0x2a00, 0xa816, 0x0130, - 0x2800, 0xa80e, 0x2c05, 0xa80a, 0x2c00, 0xa812, 0x7037, 0x0020, - 0x781f, 0x0300, 0x001e, 0x00ee, 0x0005, 0x7037, 0x0050, 0x7037, - 0x0020, 0x001e, 0x00ee, 0x080c, 0x15a0, 0x0005, 0x080c, 0x0dc5, - 0x2001, 0x180d, 0x2004, 0xd08c, 0x190c, 0x6b5e, 0x2ff0, 0x0126, - 0x2091, 0x2200, 0x0016, 0x00c6, 0x3e60, 0x6014, 0x2048, 0x2940, - 0x903e, 0x2730, 0xa864, 0x2068, 0xa81a, 0x9d84, 0x000f, 0x9088, - 0x20c7, 0x2165, 0x0002, 0x179a, 0x1808, 0x179a, 0x179a, 0x179e, - 0x17e9, 0x179a, 0x17be, 0x1793, 0x17ff, 0x179a, 0x179a, 0x17a3, - 0x18f5, 0x17d2, 0x17c8, 0xa964, 0x918c, 0x00ff, 0x918e, 0x0048, - 0x0904, 0x17ff, 0x9085, 0x0001, 0x0804, 0x18eb, 0xa87c, 0xd0ac, - 0x0dc8, 0x0804, 0x180f, 0xa87c, 0xd0ac, 0x0da0, 0x0804, 0x187a, - 0xa898, 0x901d, 0x1108, 0xab9c, 0x9016, 0xaab2, 0xaa3e, 0xaa42, - 0x3e00, 0x9080, 0x0008, 0x2004, 0x9080, 0x933d, 0x2005, 0x9005, - 0x090c, 0x0dc5, 0x2004, 0xa8ae, 0x0804, 0x18d3, 0xa87c, 0xd0bc, - 0x09c8, 0xa890, 0xa842, 0xa88c, 0xa83e, 0xa888, 0x0804, 0x180f, - 0xa87c, 0xd0bc, 0x0978, 0xa890, 0xa842, 0xa88c, 0xa83e, 0xa888, - 0x0804, 0x187a, 0xa87c, 0xd0bc, 0x0928, 0xa890, 0xa842, 0xa88c, - 0xa83e, 0xa804, 0x9045, 0x090c, 0x0dc5, 0xa164, 0xa91a, 0x91ec, - 0x000f, 0x9d80, 0x20c7, 0x2065, 0xa888, 0xd19c, 0x1904, 0x187a, - 0x0430, 0xa87c, 0xd0ac, 0x0904, 0x179a, 0xa804, 0x9045, 0x090c, - 0x0dc5, 0xa164, 0xa91a, 0x91ec, 0x000f, 0x9d80, 0x20c7, 0x2065, - 0x9006, 0xa842, 0xa83e, 0xd19c, 0x1904, 0x187a, 0x0080, 0xa87c, - 0xd0ac, 0x0904, 0x179a, 0x9006, 0xa842, 0xa83e, 0x0804, 0x187a, - 0xa87c, 0xd0ac, 0x0904, 0x179a, 0x9006, 0xa842, 0xa83e, 0x2c05, - 0x908a, 0x0036, 0x1a0c, 0x0dc5, 0x9082, 0x001b, 0x0002, 0x1832, - 0x1832, 0x1834, 0x1832, 0x1832, 0x1832, 0x183e, 0x1832, 0x1832, - 0x1832, 0x1848, 0x1832, 0x1832, 0x1832, 0x1852, 0x1832, 0x1832, - 0x1832, 0x185c, 0x1832, 0x1832, 0x1832, 0x1866, 0x1832, 0x1832, - 0x1832, 0x1870, 0x080c, 0x0dc5, 0xa574, 0xa478, 0x9d86, 0x0024, - 0x0904, 0x17a8, 0xa37c, 0xa280, 0x0804, 0x18d3, 0xa584, 0xa488, - 0x9d86, 0x0024, 0x0904, 0x17a8, 0xa38c, 0xa290, 0x0804, 0x18d3, - 0xa594, 0xa498, 0x9d86, 0x0024, 0x0904, 0x17a8, 0xa39c, 0xa2a0, - 0x0804, 0x18d3, 0xa5a4, 0xa4a8, 0x9d86, 0x0024, 0x0904, 0x17a8, - 0xa3ac, 0xa2b0, 0x0804, 0x18d3, 0xa5b4, 0xa4b8, 0x9d86, 0x0024, - 0x0904, 0x17a8, 0xa3bc, 0xa2c0, 0x0804, 0x18d3, 0xa5c4, 0xa4c8, - 0x9d86, 0x0024, 0x0904, 0x17a8, 0xa3cc, 0xa2d0, 0x0804, 0x18d3, - 0xa5d4, 0xa4d8, 0x9d86, 0x0024, 0x0904, 0x17a8, 0xa3dc, 0xa2e0, - 0x0804, 0x18d3, 0x2c05, 0x908a, 0x0034, 0x1a0c, 0x0dc5, 0x9082, - 0x001b, 0x0002, 0x189d, 0x189b, 0x189b, 0x189b, 0x189b, 0x189b, - 0x18a8, 0x189b, 0x189b, 0x189b, 0x189b, 0x189b, 0x18b3, 0x189b, - 0x189b, 0x189b, 0x189b, 0x189b, 0x18be, 0x189b, 0x189b, 0x189b, - 0x189b, 0x189b, 0x18c9, 0x080c, 0x0dc5, 0xa56c, 0xa470, 0xa774, - 0xa678, 0x9d86, 0x002c, 0x0904, 0x17a8, 0xa37c, 0xa280, 0x0458, - 0xa584, 0xa488, 0xa78c, 0xa690, 0x9d86, 0x002c, 0x0904, 0x17a8, - 0xa394, 0xa298, 0x0400, 0xa59c, 0xa4a0, 0xa7a4, 0xa6a8, 0x9d86, - 0x002c, 0x0904, 0x17a8, 0xa3ac, 0xa2b0, 0x00a8, 0xa5b4, 0xa4b8, - 0xa7bc, 0xa6c0, 0x9d86, 0x002c, 0x0904, 0x17a8, 0xa3c4, 0xa2c8, - 0x0050, 0xa5cc, 0xa4d0, 0xa7d4, 0xa6d8, 0x9d86, 0x002c, 0x0904, - 0x17a8, 0xa3dc, 0xa2e0, 0xab2e, 0xaa32, 0xad1e, 0xac22, 0xaf26, - 0xae2a, 0xa988, 0x8c60, 0x2c1d, 0xa8ac, 0xaab0, 0xa836, 0xaa3a, - 0x8109, 0xa916, 0x1160, 0x3e60, 0x601c, 0xc085, 0x601e, 0xa87c, - 0xc0dd, 0xa87e, 0x9006, 0x00ce, 0x001e, 0x012e, 0x0005, 0x2800, - 0xa80e, 0xab0a, 0x2c00, 0xa812, 0x0c70, 0x0804, 0x179a, 0x2001, - 0x180d, 0x2004, 0xd08c, 0x190c, 0x6b5e, 0x2ff0, 0x0126, 0x2091, - 0x2200, 0x0016, 0x00c6, 0x3e60, 0x6014, 0x2048, 0x2940, 0xa80e, - 0x2061, 0x20c2, 0xa813, 0x20c2, 0x2c05, 0xa80a, 0xa964, 0xa91a, - 0xa87c, 0xd0ac, 0x090c, 0x0dc5, 0x9006, 0xa842, 0xa83e, 0x2c05, - 0x908a, 0x0034, 0x1a0c, 0x0dc5, 0xadcc, 0xacd0, 0xafd4, 0xaed8, - 0xabdc, 0xaae0, 0xab2e, 0xaa32, 0xad1e, 0xac22, 0xaf26, 0xae2a, - 0xa8ac, 0xaab0, 0xa836, 0xaa3a, 0xa988, 0xa864, 0x9084, 0x00ff, - 0x9086, 0x0008, 0x1120, 0x8109, 0xa916, 0x0128, 0x0080, 0x918a, - 0x0002, 0xa916, 0x1160, 0x3e60, 0x601c, 0xc085, 0x601e, 0xa87c, - 0xc0dd, 0xa87e, 0x9006, 0x00ce, 0x001e, 0x012e, 0x0005, 0xa804, - 0x9045, 0x090c, 0x0dc5, 0xa80e, 0xa064, 0xa81a, 0x9084, 0x000f, - 0x9080, 0x20c7, 0x2015, 0x82ff, 0x090c, 0x0dc5, 0xaa12, 0x2205, - 0xa80a, 0x0c08, 0x903e, 0x2730, 0xa880, 0xd0fc, 0x1190, 0x2d00, - 0x0002, 0x1a4f, 0x19b1, 0x19b1, 0x1a4f, 0x1a4f, 0x1a49, 0x1a4f, - 0x19b1, 0x1a00, 0x1a00, 0x1a00, 0x1a4f, 0x1a4f, 0x1a4f, 0x1a46, - 0x1a00, 0xc0fc, 0xa882, 0xab2c, 0xaa30, 0xad1c, 0xac20, 0xdd9c, - 0x0904, 0x1a51, 0x2c05, 0x908a, 0x0034, 0x1a0c, 0x0dc5, 0x9082, - 0x001b, 0x0002, 0x199d, 0x199b, 0x199b, 0x199b, 0x199b, 0x199b, - 0x19a1, 0x199b, 0x199b, 0x199b, 0x199b, 0x199b, 0x19a5, 0x199b, - 0x199b, 0x199b, 0x199b, 0x199b, 0x19a9, 0x199b, 0x199b, 0x199b, - 0x199b, 0x199b, 0x19ad, 0x080c, 0x0dc5, 0xa774, 0xa678, 0x0804, - 0x1a51, 0xa78c, 0xa690, 0x0804, 0x1a51, 0xa7a4, 0xa6a8, 0x0804, - 0x1a51, 0xa7bc, 0xa6c0, 0x0804, 0x1a51, 0xa7d4, 0xa6d8, 0x0804, - 0x1a51, 0x2c05, 0x908a, 0x0036, 0x1a0c, 0x0dc5, 0x9082, 0x001b, - 0x0002, 0x19d4, 0x19d4, 0x19d6, 0x19d4, 0x19d4, 0x19d4, 0x19dc, - 0x19d4, 0x19d4, 0x19d4, 0x19e2, 0x19d4, 0x19d4, 0x19d4, 0x19e8, - 0x19d4, 0x19d4, 0x19d4, 0x19ee, 0x19d4, 0x19d4, 0x19d4, 0x19f4, - 0x19d4, 0x19d4, 0x19d4, 0x19fa, 0x080c, 0x0dc5, 0xa574, 0xa478, - 0xa37c, 0xa280, 0x0804, 0x1a51, 0xa584, 0xa488, 0xa38c, 0xa290, - 0x0804, 0x1a51, 0xa594, 0xa498, 0xa39c, 0xa2a0, 0x0804, 0x1a51, - 0xa5a4, 0xa4a8, 0xa3ac, 0xa2b0, 0x0804, 0x1a51, 0xa5b4, 0xa4b8, - 0xa3bc, 0xa2c0, 0x0804, 0x1a51, 0xa5c4, 0xa4c8, 0xa3cc, 0xa2d0, - 0x0804, 0x1a51, 0xa5d4, 0xa4d8, 0xa3dc, 0xa2e0, 0x0804, 0x1a51, - 0x2c05, 0x908a, 0x0034, 0x1a0c, 0x0dc5, 0x9082, 0x001b, 0x0002, - 0x1a23, 0x1a21, 0x1a21, 0x1a21, 0x1a21, 0x1a21, 0x1a2a, 0x1a21, - 0x1a21, 0x1a21, 0x1a21, 0x1a21, 0x1a31, 0x1a21, 0x1a21, 0x1a21, - 0x1a21, 0x1a21, 0x1a38, 0x1a21, 0x1a21, 0x1a21, 0x1a21, 0x1a21, - 0x1a3f, 0x080c, 0x0dc5, 0xa56c, 0xa470, 0xa774, 0xa678, 0xa37c, - 0xa280, 0x0438, 0xa584, 0xa488, 0xa78c, 0xa690, 0xa394, 0xa298, - 0x0400, 0xa59c, 0xa4a0, 0xa7a4, 0xa6a8, 0xa3ac, 0xa2b0, 0x00c8, - 0xa5b4, 0xa4b8, 0xa7bc, 0xa6c0, 0xa3c4, 0xa2c8, 0x0090, 0xa5cc, - 0xa4d0, 0xa7d4, 0xa6d8, 0xa3dc, 0xa2e0, 0x0058, 0x9d86, 0x000e, - 0x1130, 0x080c, 0x207f, 0x1904, 0x195a, 0x900e, 0x0050, 0x080c, - 0x0dc5, 0xab2e, 0xaa32, 0xad1e, 0xac22, 0xaf26, 0xae2a, 0x080c, - 0x207f, 0x0005, 0x6014, 0x2048, 0x6118, 0x81ff, 0x0148, 0x810c, - 0x810c, 0x810c, 0x81ff, 0x1118, 0xa887, 0x0001, 0x0008, 0xa986, - 0x601b, 0x0002, 0xa874, 0x9084, 0x00ff, 0x9084, 0x0008, 0x0150, - 0x00e9, 0x6000, 0x9086, 0x0004, 0x1120, 0x2009, 0x0048, 0x080c, - 0xb352, 0x0005, 0xa974, 0xd1dc, 0x1108, 0x0005, 0xa934, 0xa88c, - 0x9106, 0x1158, 0xa938, 0xa890, 0x9106, 0x1138, 0x601c, 0xc084, - 0x601e, 0x2009, 0x0048, 0x0804, 0xb352, 0x0005, 0x0126, 0x00c6, - 0x2091, 0x2200, 0x00ce, 0x7908, 0x918c, 0x0007, 0x9186, 0x0000, - 0x05b0, 0x9186, 0x0003, 0x0598, 0x6020, 0x6023, 0x0000, 0x0006, - 0x2031, 0x0008, 0x00c6, 0x781f, 0x0808, 0x7808, 0xd09c, 0x0120, - 0x080c, 0x1394, 0x8631, 0x1db8, 0x00ce, 0x781f, 0x0800, 0x2031, - 0x0168, 0x00c6, 0x7808, 0xd09c, 0x190c, 0x1394, 0x00ce, 0x2001, - 0x0038, 0x080c, 0x1b69, 0x7930, 0x9186, 0x0040, 0x0160, 0x9186, - 0x0042, 0x190c, 0x0dc5, 0x2001, 0x001e, 0x8001, 0x1df0, 0x8631, - 0x1d40, 0x080c, 0x1b78, 0x000e, 0x6022, 0x012e, 0x0005, 0x080c, - 0x1b65, 0x7827, 0x0015, 0x7828, 0x9c06, 0x1db8, 0x782b, 0x0000, - 0x0ca0, 0x00f6, 0x2079, 0x0300, 0x7803, 0x0000, 0x78ab, 0x0004, - 0x2001, 0xf000, 0x8001, 0x090c, 0x0dc5, 0x7aac, 0xd2ac, 0x1dd0, - 0x00fe, 0x080c, 0x7637, 0x1188, 0x2001, 0x0138, 0x2003, 0x0000, - 0x2001, 0x0160, 0x2003, 0x0000, 0x2011, 0x012c, 0xa001, 0xa001, - 0x8211, 0x1de0, 0x0059, 0x0804, 0x76e4, 0x0479, 0x0039, 0x2001, - 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x0005, 0x00e6, 0x2071, - 0x0200, 0x080c, 0x2c6d, 0x2009, 0x003c, 0x080c, 0x2409, 0x2001, - 0x015d, 0x2003, 0x0000, 0x7000, 0x9084, 0x003c, 0x1de0, 0x080c, - 0x8725, 0x70a0, 0x70a2, 0x7098, 0x709a, 0x709c, 0x709e, 0x2001, - 0x020d, 0x2003, 0x0020, 0x00f6, 0x2079, 0x0300, 0x080c, 0x1322, - 0x7803, 0x0001, 0x00fe, 0x00ee, 0x0005, 0x2001, 0x0138, 0x2014, - 0x2003, 0x0000, 0x2001, 0x0160, 0x202c, 0x2003, 0x0000, 0x080c, - 0x7637, 0x1108, 0x0005, 0x2021, 0x0260, 0x2001, 0x0141, 0x201c, - 0xd3dc, 0x1168, 0x2001, 0x0109, 0x201c, 0x939c, 0x0048, 0x1160, - 0x2001, 0x0111, 0x201c, 0x83ff, 0x1110, 0x8421, 0x1d70, 0x2001, - 0x015d, 0x2003, 0x0000, 0x0005, 0x0046, 0x2021, 0x0019, 0x2003, - 0x0048, 0xa001, 0xa001, 0x201c, 0x939c, 0x0048, 0x0120, 0x8421, - 0x1db0, 0x004e, 0x0c60, 0x004e, 0x0c40, 0x601c, 0xc084, 0x601e, - 0x0005, 0x2c08, 0x621c, 0x080c, 0x1611, 0x7930, 0x0005, 0x2c08, - 0x621c, 0x080c, 0x16bc, 0x7930, 0x0005, 0x8001, 0x1df0, 0x0005, - 0x2031, 0x0064, 0x781c, 0x9084, 0x0007, 0x0170, 0x2001, 0x0038, - 0x0c41, 0x9186, 0x0040, 0x0904, 0x1bd6, 0x2001, 0x001e, 0x0c69, - 0x8631, 0x1d80, 0x080c, 0x0dc5, 0x781f, 0x0202, 0x2001, 0x015d, - 0x2003, 0x0000, 0x2001, 0x0dac, 0x0c01, 0x781c, 0xd084, 0x0110, - 0x0861, 0x04e0, 0x2001, 0x0030, 0x0891, 0x9186, 0x0040, 0x0568, - 0x781c, 0xd084, 0x1da8, 0x781f, 0x0101, 0x2001, 0x0014, 0x0869, - 0x2001, 0x0037, 0x0821, 0x9186, 0x0040, 0x0140, 0x2001, 0x0030, - 0x080c, 0x1b6f, 0x9186, 0x0040, 0x190c, 0x0dc5, 0x00d6, 0x2069, - 0x0200, 0x692c, 0xd1f4, 0x1170, 0xd1c4, 0x0160, 0xd19c, 0x0130, - 0x6800, 0x9085, 0x1800, 0x6802, 0x00de, 0x0080, 0x6908, 0x9184, - 0x0007, 0x1db0, 0x00de, 0x781f, 0x0100, 0x791c, 0x9184, 0x0007, - 0x090c, 0x0dc5, 0xa001, 0xa001, 0x781f, 0x0200, 0x0005, 0x0126, - 0x2091, 0x2400, 0x2071, 0x1a69, 0x2079, 0x0090, 0x012e, 0x0005, - 0x9280, 0x0005, 0x2004, 0x2048, 0xa97c, 0xd1dc, 0x1904, 0x1c78, - 0xa964, 0x9184, 0x0007, 0x0002, 0x1bf4, 0x1c63, 0x1c0b, 0x1c0d, - 0x1c0b, 0x1c4b, 0x1c2b, 0x1c1a, 0x918c, 0x00ff, 0x9186, 0x0008, - 0x1170, 0xa87c, 0xd0b4, 0x0904, 0x1ea5, 0x9006, 0xa842, 0xa83e, - 0xa988, 0x2900, 0xa85a, 0xa813, 0x20c2, 0x0804, 0x1c74, 0x9186, - 0x0048, 0x0904, 0x1c63, 0x080c, 0x0dc5, 0x9184, 0x00ff, 0x9086, - 0x0013, 0x0904, 0x1c63, 0x9184, 0x00ff, 0x9086, 0x001b, 0x0904, - 0x1c63, 0x0c88, 0xa87c, 0xd0b4, 0x0904, 0x1ea5, 0xa890, 0xa842, - 0xa83a, 0xa88c, 0xa83e, 0xa836, 0xa8ac, 0xa846, 0xa8b0, 0xa84a, - 0xa988, 0x0804, 0x1c6b, 0xa864, 0x9084, 0x00ff, 0x9086, 0x001e, - 0x19d0, 0xa87c, 0xd0b4, 0x0904, 0x1ea5, 0xa890, 0xa842, 0xa83a, - 0xa88c, 0xa83e, 0xa836, 0xa8ac, 0xa846, 0xa8b0, 0xa84a, 0xa804, - 0xa85a, 0x2040, 0xa064, 0x9084, 0x000f, 0x9080, 0x20c7, 0x2005, - 0xa812, 0xa988, 0x0448, 0x918c, 0x00ff, 0x9186, 0x0015, 0x1540, - 0xa87c, 0xd0b4, 0x0904, 0x1ea5, 0xa804, 0xa85a, 0x2040, 0xa064, - 0x9084, 0x000f, 0x9080, 0x20c7, 0x2005, 0xa812, 0xa988, 0x9006, - 0xa842, 0xa83e, 0x0088, 0xa87c, 0xd0b4, 0x0904, 0x1ea5, 0xa988, - 0x9006, 0xa842, 0xa83e, 0x2900, 0xa85a, 0xa864, 0x9084, 0x000f, - 0x9080, 0x20c7, 0x2005, 0xa812, 0xa916, 0xa87c, 0xc0dd, 0xa87e, - 0x0005, 0x00f6, 0x2079, 0x0090, 0x782c, 0xd0fc, 0x190c, 0x1eeb, - 0x00e6, 0x2071, 0x1a69, 0x7000, 0x9005, 0x1904, 0x1cdf, 0x7206, - 0x9280, 0x0005, 0x204c, 0x9280, 0x0004, 0x2004, 0x782b, 0x0004, - 0x00f6, 0x2079, 0x0200, 0x7803, 0x0040, 0x00fe, 0x00b6, 0x2058, - 0xb86c, 0x7836, 0xb890, 0x00be, 0x00f6, 0x2079, 0x0200, 0x7803, - 0x0040, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0x781a, - 0x78d7, 0x0000, 0x00fe, 0xa814, 0x2050, 0xa858, 0x2040, 0xa810, - 0x2060, 0xa064, 0x90ec, 0x000f, 0xa944, 0x791a, 0x7116, 0xa848, - 0x781e, 0x701a, 0x9006, 0x700e, 0x7012, 0x7004, 0xa940, 0xa838, - 0x9106, 0x1500, 0xa93c, 0xa834, 0x9106, 0x11e0, 0x0006, 0x0016, - 0xa938, 0xa834, 0x9105, 0x0118, 0x001e, 0x000e, 0x0098, 0x001e, - 0x000e, 0x8aff, 0x01c8, 0x0126, 0x2091, 0x8000, 0x2009, 0x0306, - 0x200b, 0x0808, 0x00d9, 0x0108, 0x00c9, 0x012e, 0x9006, 0x00ee, - 0x00fe, 0x0005, 0x0036, 0x0046, 0xab38, 0xac34, 0x080c, 0x20e7, - 0x004e, 0x003e, 0x0d30, 0x0c98, 0x9085, 0x0001, 0x0c80, 0x2009, - 0x0306, 0x200b, 0x4800, 0x7027, 0x0000, 0x0005, 0x0076, 0x0066, - 0x0056, 0x0046, 0x0036, 0x0026, 0x8aff, 0x0904, 0x1e9e, 0x700c, - 0x7214, 0x923a, 0x7010, 0x7218, 0x9203, 0x0a04, 0x1e9d, 0x9705, - 0x0904, 0x1e9d, 0x903e, 0x2730, 0xa880, 0xd0fc, 0x1190, 0x2d00, - 0x0002, 0x1e22, 0x1d61, 0x1d61, 0x1e22, 0x1e22, 0x1dff, 0x1e22, - 0x1d61, 0x1e06, 0x1db0, 0x1db0, 0x1e22, 0x1e22, 0x1e22, 0x1df9, - 0x1db0, 0xc0fc, 0xa882, 0xab2c, 0xaa30, 0xad1c, 0xac20, 0xdd9c, - 0x0904, 0x1e2f, 0x2c05, 0x908a, 0x0034, 0x1a0c, 0x0dc5, 0x9082, - 0x001b, 0x0002, 0x1d4d, 0x1d4b, 0x1d4b, 0x1d4b, 0x1d4b, 0x1d4b, - 0x1d51, 0x1d4b, 0x1d4b, 0x1d4b, 0x1d4b, 0x1d4b, 0x1d55, 0x1d4b, - 0x1d4b, 0x1d4b, 0x1d4b, 0x1d4b, 0x1d59, 0x1d4b, 0x1d4b, 0x1d4b, - 0x1d4b, 0x1d4b, 0x1d5d, 0x080c, 0x0dc5, 0xa774, 0xa678, 0x0804, - 0x1e2f, 0xa78c, 0xa690, 0x0804, 0x1e2f, 0xa7a4, 0xa6a8, 0x0804, - 0x1e2f, 0xa7bc, 0xa6c0, 0x0804, 0x1e2f, 0xa7d4, 0xa6d8, 0x0804, - 0x1e2f, 0x2c05, 0x908a, 0x0036, 0x1a0c, 0x0dc5, 0x9082, 0x001b, - 0x0002, 0x1d84, 0x1d84, 0x1d86, 0x1d84, 0x1d84, 0x1d84, 0x1d8c, - 0x1d84, 0x1d84, 0x1d84, 0x1d92, 0x1d84, 0x1d84, 0x1d84, 0x1d98, - 0x1d84, 0x1d84, 0x1d84, 0x1d9e, 0x1d84, 0x1d84, 0x1d84, 0x1da4, - 0x1d84, 0x1d84, 0x1d84, 0x1daa, 0x080c, 0x0dc5, 0xa574, 0xa478, - 0xa37c, 0xa280, 0x0804, 0x1e2f, 0xa584, 0xa488, 0xa38c, 0xa290, - 0x0804, 0x1e2f, 0xa594, 0xa498, 0xa39c, 0xa2a0, 0x0804, 0x1e2f, - 0xa5a4, 0xa4a8, 0xa3ac, 0xa2b0, 0x0804, 0x1e2f, 0xa5b4, 0xa4b8, - 0xa3bc, 0xa2c0, 0x0804, 0x1e2f, 0xa5c4, 0xa4c8, 0xa3cc, 0xa2d0, - 0x0804, 0x1e2f, 0xa5d4, 0xa4d8, 0xa3dc, 0xa2e0, 0x0804, 0x1e2f, - 0x2c05, 0x908a, 0x0034, 0x1a0c, 0x0dc5, 0x9082, 0x001b, 0x0002, - 0x1dd3, 0x1dd1, 0x1dd1, 0x1dd1, 0x1dd1, 0x1dd1, 0x1ddb, 0x1dd1, - 0x1dd1, 0x1dd1, 0x1dd1, 0x1dd1, 0x1de3, 0x1dd1, 0x1dd1, 0x1dd1, - 0x1dd1, 0x1dd1, 0x1deb, 0x1dd1, 0x1dd1, 0x1dd1, 0x1dd1, 0x1dd1, - 0x1df2, 0x080c, 0x0dc5, 0xa56c, 0xa470, 0xa774, 0xa678, 0xa37c, - 0xa280, 0x0804, 0x1e2f, 0xa584, 0xa488, 0xa78c, 0xa690, 0xa394, - 0xa298, 0x0804, 0x1e2f, 0xa59c, 0xa4a0, 0xa7a4, 0xa6a8, 0xa3ac, - 0xa2b0, 0x0804, 0x1e2f, 0xa5b4, 0xa4b8, 0xa7bc, 0xa6c0, 0xa3c4, - 0xa2c8, 0x04e8, 0xa5cc, 0xa4d0, 0xa7d4, 0xa6d8, 0xa3dc, 0xa2e0, - 0x04b0, 0xa864, 0x9084, 0x00ff, 0x9086, 0x001e, 0x1518, 0x080c, - 0x207f, 0x1904, 0x1cfc, 0x900e, 0x0804, 0x1e9e, 0xab64, 0x939c, - 0x00ff, 0x9386, 0x0048, 0x1180, 0x00c6, 0x7004, 0x2060, 0x6004, - 0x9086, 0x0043, 0x00ce, 0x0904, 0x1db0, 0xab9c, 0x9016, 0xad8c, - 0xac90, 0xaf94, 0xae98, 0x0098, 0x9386, 0x0008, 0x0904, 0x1db0, - 0x080c, 0x0dc5, 0xa964, 0x918c, 0x00ff, 0x9186, 0x0013, 0x0904, - 0x1d61, 0x9186, 0x001b, 0x0904, 0x1db0, 0x080c, 0x0dc5, 0x2009, - 0x030f, 0x2104, 0xd0fc, 0x0538, 0x0066, 0x2009, 0x0306, 0x2134, - 0x200b, 0x4000, 0x2104, 0x9084, 0x0030, 0x15b8, 0x2031, 0x1000, - 0x2600, 0x9302, 0x928b, 0x0000, 0xa82e, 0xa932, 0x0278, 0x9105, - 0x0168, 0x2011, 0x0000, 0x2618, 0x2600, 0x9500, 0xa81e, 0x9481, - 0x0000, 0xa822, 0xa880, 0xc0fd, 0xa882, 0x0020, 0xa82f, 0x0000, - 0xa833, 0x0000, 0x006e, 0x7b12, 0x7a16, 0x7d02, 0x7c06, 0x7f0a, - 0x7e0e, 0x782b, 0x0001, 0x7000, 0x8000, 0x7002, 0xa83c, 0x9300, - 0xa83e, 0xa840, 0x9201, 0xa842, 0x700c, 0x9300, 0x700e, 0x7010, - 0x9201, 0x7012, 0x080c, 0x207f, 0x0448, 0xd6b4, 0x0110, 0x200b, - 0x4040, 0x2031, 0x0080, 0x9584, 0x007f, 0x0108, 0x9632, 0x7124, - 0x7000, 0x9086, 0x0000, 0x1198, 0xc185, 0x7126, 0x2009, 0x0306, - 0x2104, 0xd0b4, 0x1904, 0x1e40, 0x200b, 0x4040, 0x2009, 0x1a83, - 0x2104, 0x8000, 0x0a04, 0x1e40, 0x200a, 0x0804, 0x1e40, 0xc18d, - 0x7126, 0xd184, 0x1d58, 0x0804, 0x1e40, 0x9006, 0x002e, 0x003e, - 0x004e, 0x005e, 0x006e, 0x007e, 0x0005, 0x080c, 0x0dc5, 0x0026, - 0x2001, 0x0105, 0x2003, 0x0010, 0x782b, 0x0004, 0x7003, 0x0000, - 0x7004, 0x2060, 0x6014, 0x2048, 0x080c, 0xd0d8, 0x0118, 0xa880, - 0xc0bd, 0xa882, 0x782c, 0xd0ac, 0x1de8, 0x080c, 0x1cef, 0x6020, - 0x9086, 0x0006, 0x1180, 0x2061, 0x0100, 0x62c8, 0x2001, 0x00fa, - 0x8001, 0x1df0, 0x60c8, 0x9206, 0x1dc0, 0x60c4, 0xa89a, 0x60c8, - 0xa896, 0x7004, 0x2060, 0x00c6, 0x080c, 0xccf3, 0x00ce, 0x2001, - 0x19f7, 0x2004, 0x9c06, 0x1160, 0x2009, 0x0040, 0x080c, 0x2409, - 0x080c, 0xac2b, 0x2011, 0x0000, 0x080c, 0xaac9, 0x080c, 0x9bd3, - 0x002e, 0x0804, 0x202f, 0x0126, 0x2091, 0x2400, 0xa858, 0x2040, - 0x792c, 0x782b, 0x0002, 0x9184, 0x0700, 0x1904, 0x1ea7, 0x7000, - 0x0002, 0x202f, 0x1efd, 0x1f7d, 0x202d, 0x8001, 0x7002, 0x7027, - 0x0000, 0xd19c, 0x1158, 0x8aff, 0x0904, 0x1f4a, 0x080c, 0x1cf6, - 0x0904, 0x202f, 0x080c, 0x1cf6, 0x0804, 0x202f, 0x782b, 0x0004, - 0xd194, 0x0148, 0xa880, 0xc0fc, 0xa882, 0x8aff, 0x1518, 0xa87c, - 0xc0f5, 0xa87e, 0x00f8, 0x0026, 0x0036, 0xab3c, 0xaa40, 0x0016, - 0x7910, 0xa82c, 0x9100, 0xa82e, 0x7914, 0xa830, 0x9101, 0xa832, - 0x001e, 0x7810, 0x931a, 0x7814, 0x9213, 0x7800, 0xa81e, 0x7804, - 0xa822, 0xab3e, 0xaa42, 0x003e, 0x002e, 0x080c, 0x209a, 0xa880, - 0xc0fd, 0xa882, 0x2a00, 0xa816, 0x2800, 0xa85a, 0x2c00, 0xa812, - 0x7003, 0x0000, 0x2009, 0x0306, 0x200b, 0x4800, 0x7027, 0x0000, - 0x0804, 0x202f, 0x00f6, 0x0026, 0x781c, 0x0006, 0x7818, 0x0006, - 0x2079, 0x0100, 0x7a14, 0x9284, 0x1984, 0x9085, 0x0012, 0x7816, - 0x0036, 0x2019, 0x1000, 0x8319, 0x090c, 0x0dc5, 0x7820, 0xd0bc, - 0x1dd0, 0x003e, 0x79c8, 0x000e, 0x9102, 0x001e, 0x0006, 0x0016, - 0x79c4, 0x000e, 0x9103, 0x78c6, 0x000e, 0x78ca, 0x9284, 0x1984, - 0x9085, 0x0012, 0x7816, 0x002e, 0x00fe, 0x782b, 0x0008, 0x7003, - 0x0000, 0x080c, 0x1cef, 0x0804, 0x202f, 0x8001, 0x7002, 0x7024, - 0x8004, 0x7026, 0xd194, 0x0170, 0x782c, 0xd0fc, 0x1904, 0x1ef0, - 0xd19c, 0x1904, 0x202b, 0x8aff, 0x0904, 0x202f, 0x080c, 0x1cf6, - 0x0804, 0x202f, 0x0026, 0x0036, 0xab3c, 0xaa40, 0x080c, 0x209a, - 0xdd9c, 0x1904, 0x1fea, 0x2c05, 0x908a, 0x0036, 0x1a0c, 0x0dc5, - 0x9082, 0x001b, 0x0002, 0x1fbe, 0x1fbe, 0x1fc0, 0x1fbe, 0x1fbe, - 0x1fbe, 0x1fc6, 0x1fbe, 0x1fbe, 0x1fbe, 0x1fcc, 0x1fbe, 0x1fbe, - 0x1fbe, 0x1fd2, 0x1fbe, 0x1fbe, 0x1fbe, 0x1fd8, 0x1fbe, 0x1fbe, - 0x1fbe, 0x1fde, 0x1fbe, 0x1fbe, 0x1fbe, 0x1fe4, 0x080c, 0x0dc5, - 0xa07c, 0x931a, 0xa080, 0x9213, 0x0804, 0x1f1f, 0xa08c, 0x931a, - 0xa090, 0x9213, 0x0804, 0x1f1f, 0xa09c, 0x931a, 0xa0a0, 0x9213, - 0x0804, 0x1f1f, 0xa0ac, 0x931a, 0xa0b0, 0x9213, 0x0804, 0x1f1f, - 0xa0bc, 0x931a, 0xa0c0, 0x9213, 0x0804, 0x1f1f, 0xa0cc, 0x931a, - 0xa0d0, 0x9213, 0x0804, 0x1f1f, 0xa0dc, 0x931a, 0xa0e0, 0x9213, - 0x0804, 0x1f1f, 0x2c05, 0x908a, 0x0034, 0x1a0c, 0x0dc5, 0x9082, - 0x001b, 0x0002, 0x200d, 0x200b, 0x200b, 0x200b, 0x200b, 0x200b, - 0x2013, 0x200b, 0x200b, 0x200b, 0x200b, 0x200b, 0x2019, 0x200b, - 0x200b, 0x200b, 0x200b, 0x200b, 0x201f, 0x200b, 0x200b, 0x200b, - 0x200b, 0x200b, 0x2025, 0x080c, 0x0dc5, 0xa07c, 0x931a, 0xa080, - 0x9213, 0x0804, 0x1f1f, 0xa094, 0x931a, 0xa098, 0x9213, 0x0804, - 0x1f1f, 0xa0ac, 0x931a, 0xa0b0, 0x9213, 0x0804, 0x1f1f, 0xa0c4, - 0x931a, 0xa0c8, 0x9213, 0x0804, 0x1f1f, 0xa0dc, 0x931a, 0xa0e0, - 0x9213, 0x0804, 0x1f1f, 0x0804, 0x1f1b, 0x080c, 0x0dc5, 0x012e, - 0x0005, 0x00f6, 0x00e6, 0x2071, 0x1a69, 0x7000, 0x9086, 0x0000, - 0x0904, 0x207a, 0x2079, 0x0090, 0x2009, 0x0207, 0x210c, 0xd194, - 0x01b8, 0x2009, 0x020c, 0x210c, 0x9184, 0x0003, 0x0188, 0x080c, - 0xf0a0, 0x2001, 0x0133, 0x2004, 0x9005, 0x090c, 0x0dc5, 0x0016, - 0x2009, 0x0040, 0x080c, 0x2409, 0x001e, 0x2001, 0x020c, 0x2102, - 0x2009, 0x0206, 0x2104, 0x2009, 0x0203, 0x210c, 0x9106, 0x1120, - 0x2009, 0x0040, 0x080c, 0x2409, 0x782c, 0xd0fc, 0x09a8, 0x080c, - 0x1eeb, 0x7000, 0x9086, 0x0000, 0x1978, 0x782b, 0x0004, 0x782c, - 0xd0ac, 0x1de8, 0x2009, 0x0040, 0x080c, 0x2409, 0x782b, 0x0002, - 0x7003, 0x0000, 0x080c, 0x1cef, 0x00ee, 0x00fe, 0x0005, 0xa880, - 0xd0fc, 0x11a8, 0x8c60, 0x2c05, 0x9005, 0x0110, 0x8a51, 0x0005, - 0xa004, 0x9005, 0x0168, 0xa85a, 0x2040, 0xa064, 0x9084, 0x000f, - 0x9080, 0x20c7, 0x2065, 0x8cff, 0x090c, 0x0dc5, 0x8a51, 0x0005, - 0x2050, 0x0005, 0xa880, 0xd0fc, 0x11b8, 0x8a50, 0x8c61, 0x2c05, - 0x9005, 0x1190, 0x2800, 0x9906, 0x0120, 0xa000, 0x9005, 0x1108, - 0x2900, 0x2040, 0xa85a, 0xa064, 0x9084, 0x000f, 0x9080, 0x20d7, - 0x2065, 0x8cff, 0x090c, 0x0dc5, 0x0005, 0x0000, 0x001d, 0x0021, - 0x0025, 0x0029, 0x002d, 0x0031, 0x0035, 0x0000, 0x001b, 0x0021, - 0x0027, 0x002d, 0x0033, 0x0000, 0x0000, 0x0023, 0x0000, 0x0000, - 0x20ba, 0x20b6, 0x20ba, 0x20ba, 0x20c4, 0x0000, 0x20ba, 0x20c1, - 0x20c1, 0x20be, 0x20c1, 0x20c1, 0x0000, 0x20c4, 0x20c1, 0x0000, - 0x20bc, 0x20bc, 0x0000, 0x20bc, 0x20c4, 0x0000, 0x20bc, 0x20c2, - 0x20c2, 0x20c2, 0x0000, 0x20c2, 0x0000, 0x20c4, 0x20c2, 0x00c6, - 0x00d6, 0x0086, 0xab42, 0xac3e, 0xa888, 0x9055, 0x0904, 0x22c6, - 0x2940, 0xa064, 0x90ec, 0x000f, 0x9084, 0x00ff, 0x9086, 0x0008, - 0x1118, 0x2061, 0x20c2, 0x00d0, 0x9de0, 0x20c7, 0x9d86, 0x0007, - 0x0130, 0x9d86, 0x000e, 0x0118, 0x9d86, 0x000f, 0x1120, 0xa08c, - 0x9422, 0xa090, 0x931b, 0x2c05, 0x9065, 0x1140, 0x0310, 0x0804, - 0x22c6, 0xa004, 0x9045, 0x0904, 0x22c6, 0x08d8, 0x2c05, 0x9005, - 0x0904, 0x21ae, 0xdd9c, 0x1904, 0x216a, 0x908a, 0x0036, 0x1a0c, - 0x0dc5, 0x9082, 0x001b, 0x0002, 0x213f, 0x213f, 0x2141, 0x213f, - 0x213f, 0x213f, 0x2147, 0x213f, 0x213f, 0x213f, 0x214d, 0x213f, - 0x213f, 0x213f, 0x2153, 0x213f, 0x213f, 0x213f, 0x2159, 0x213f, - 0x213f, 0x213f, 0x215f, 0x213f, 0x213f, 0x213f, 0x2165, 0x080c, - 0x0dc5, 0xa07c, 0x9422, 0xa080, 0x931b, 0x0804, 0x21a4, 0xa08c, - 0x9422, 0xa090, 0x931b, 0x0804, 0x21a4, 0xa09c, 0x9422, 0xa0a0, - 0x931b, 0x0804, 0x21a4, 0xa0ac, 0x9422, 0xa0b0, 0x931b, 0x0804, - 0x21a4, 0xa0bc, 0x9422, 0xa0c0, 0x931b, 0x0804, 0x21a4, 0xa0cc, - 0x9422, 0xa0d0, 0x931b, 0x0804, 0x21a4, 0xa0dc, 0x9422, 0xa0e0, - 0x931b, 0x04d0, 0x908a, 0x0034, 0x1a0c, 0x0dc5, 0x9082, 0x001b, - 0x0002, 0x218c, 0x218a, 0x218a, 0x218a, 0x218a, 0x218a, 0x2191, - 0x218a, 0x218a, 0x218a, 0x218a, 0x218a, 0x2196, 0x218a, 0x218a, - 0x218a, 0x218a, 0x218a, 0x219b, 0x218a, 0x218a, 0x218a, 0x218a, - 0x218a, 0x21a0, 0x080c, 0x0dc5, 0xa07c, 0x9422, 0xa080, 0x931b, - 0x0098, 0xa094, 0x9422, 0xa098, 0x931b, 0x0070, 0xa0ac, 0x9422, - 0xa0b0, 0x931b, 0x0048, 0xa0c4, 0x9422, 0xa0c8, 0x931b, 0x0020, - 0xa0dc, 0x9422, 0xa0e0, 0x931b, 0x0630, 0x2300, 0x9405, 0x0160, - 0x8a51, 0x0904, 0x22c6, 0x8c60, 0x0804, 0x2116, 0xa004, 0x9045, - 0x0904, 0x22c6, 0x0804, 0x20f1, 0x8a51, 0x0904, 0x22c6, 0x8c60, - 0x2c05, 0x9005, 0x1158, 0xa004, 0x9045, 0x0904, 0x22c6, 0xa064, - 0x90ec, 0x000f, 0x9de0, 0x20c7, 0x2c05, 0x2060, 0xa880, 0xc0fc, - 0xa882, 0x0804, 0x22bb, 0x2c05, 0x8422, 0x8420, 0x831a, 0x9399, - 0x0000, 0xac2e, 0xab32, 0xdd9c, 0x1904, 0x2258, 0x9082, 0x001b, - 0x0002, 0x21f4, 0x21f4, 0x21f6, 0x21f4, 0x21f4, 0x21f4, 0x2204, - 0x21f4, 0x21f4, 0x21f4, 0x2212, 0x21f4, 0x21f4, 0x21f4, 0x2220, - 0x21f4, 0x21f4, 0x21f4, 0x222e, 0x21f4, 0x21f4, 0x21f4, 0x223c, - 0x21f4, 0x21f4, 0x21f4, 0x224a, 0x080c, 0x0dc5, 0xa17c, 0x2400, - 0x9122, 0xa180, 0x2300, 0x911b, 0x0a0c, 0x0dc5, 0xa074, 0x9420, - 0xa078, 0x9319, 0x0804, 0x22b6, 0xa18c, 0x2400, 0x9122, 0xa190, - 0x2300, 0x911b, 0x0a0c, 0x0dc5, 0xa084, 0x9420, 0xa088, 0x9319, - 0x0804, 0x22b6, 0xa19c, 0x2400, 0x9122, 0xa1a0, 0x2300, 0x911b, - 0x0a0c, 0x0dc5, 0xa094, 0x9420, 0xa098, 0x9319, 0x0804, 0x22b6, - 0xa1ac, 0x2400, 0x9122, 0xa1b0, 0x2300, 0x911b, 0x0a0c, 0x0dc5, - 0xa0a4, 0x9420, 0xa0a8, 0x9319, 0x0804, 0x22b6, 0xa1bc, 0x2400, - 0x9122, 0xa1c0, 0x2300, 0x911b, 0x0a0c, 0x0dc5, 0xa0b4, 0x9420, - 0xa0b8, 0x9319, 0x0804, 0x22b6, 0xa1cc, 0x2400, 0x9122, 0xa1d0, - 0x2300, 0x911b, 0x0a0c, 0x0dc5, 0xa0c4, 0x9420, 0xa0c8, 0x9319, - 0x0804, 0x22b6, 0xa1dc, 0x2400, 0x9122, 0xa1e0, 0x2300, 0x911b, - 0x0a0c, 0x0dc5, 0xa0d4, 0x9420, 0xa0d8, 0x9319, 0x0804, 0x22b6, - 0x9082, 0x001b, 0x0002, 0x2276, 0x2274, 0x2274, 0x2274, 0x2274, - 0x2274, 0x2283, 0x2274, 0x2274, 0x2274, 0x2274, 0x2274, 0x2290, - 0x2274, 0x2274, 0x2274, 0x2274, 0x2274, 0x229d, 0x2274, 0x2274, - 0x2274, 0x2274, 0x2274, 0x22aa, 0x080c, 0x0dc5, 0xa17c, 0x2400, - 0x9122, 0xa180, 0x2300, 0x911b, 0x0a0c, 0x0dc5, 0xa06c, 0x9420, - 0xa070, 0x9319, 0x0498, 0xa194, 0x2400, 0x9122, 0xa198, 0x2300, - 0x911b, 0x0a0c, 0x0dc5, 0xa084, 0x9420, 0xa088, 0x9319, 0x0430, - 0xa1ac, 0x2400, 0x9122, 0xa1b0, 0x2300, 0x911b, 0x0a0c, 0x0dc5, - 0xa09c, 0x9420, 0xa0a0, 0x9319, 0x00c8, 0xa1c4, 0x2400, 0x9122, - 0xa1c8, 0x2300, 0x911b, 0x0a0c, 0x0dc5, 0xa0b4, 0x9420, 0xa0b8, - 0x9319, 0x0060, 0xa1dc, 0x2400, 0x9122, 0xa1e0, 0x2300, 0x911b, - 0x0a0c, 0x0dc5, 0xa0cc, 0x9420, 0xa0d0, 0x9319, 0xac1e, 0xab22, - 0xa880, 0xc0fd, 0xa882, 0x2800, 0xa85a, 0x2c00, 0xa812, 0x2a00, - 0xa816, 0x000e, 0x000e, 0x000e, 0x9006, 0x0028, 0x008e, 0x00de, - 0x00ce, 0x9085, 0x0001, 0x0005, 0x2001, 0x0005, 0x2004, 0xd0bc, - 0x190c, 0x0dbe, 0x9084, 0x0007, 0x0002, 0x22e7, 0x1eeb, 0x22e7, - 0x22dd, 0x22e0, 0x22e3, 0x22e0, 0x22e3, 0x080c, 0x1eeb, 0x0005, - 0x080c, 0x11b2, 0x0005, 0x080c, 0x1eeb, 0x080c, 0x11b2, 0x0005, - 0x0126, 0x2091, 0x2600, 0x2079, 0x0200, 0x2071, 0x0260, 0x2069, - 0x1800, 0x7817, 0x0000, 0x789b, 0x0814, 0x78a3, 0x0406, 0x789f, - 0x0410, 0x2009, 0x013b, 0x200b, 0x0400, 0x781b, 0x0002, 0x783b, - 0x001f, 0x7837, 0x0020, 0x7803, 0x1600, 0x012e, 0x0005, 0x2091, - 0x2600, 0x781c, 0xd0a4, 0x190c, 0x2406, 0x7900, 0xd1dc, 0x1118, - 0x9084, 0x0006, 0x001a, 0x9084, 0x000e, 0x0002, 0x232e, 0x2326, - 0x8081, 0x2326, 0x2328, 0x2328, 0x2328, 0x2328, 0x8067, 0x2326, - 0x232a, 0x2326, 0x2328, 0x2326, 0x2328, 0x2326, 0x080c, 0x0dc5, - 0x0031, 0x0020, 0x080c, 0x8067, 0x080c, 0x8081, 0x0005, 0x0006, - 0x0016, 0x0026, 0x080c, 0xf0a0, 0x7930, 0x9184, 0x0003, 0x01c0, - 0x2001, 0x19f7, 0x2004, 0x9005, 0x0170, 0x2001, 0x0133, 0x2004, - 0x9005, 0x090c, 0x0dc5, 0x00c6, 0x2001, 0x19f7, 0x2064, 0x080c, - 0xccf3, 0x00ce, 0x00f8, 0x2009, 0x0040, 0x080c, 0x2409, 0x00d0, - 0x9184, 0x0014, 0x01a0, 0x6a00, 0x9286, 0x0003, 0x0160, 0x080c, - 0x7637, 0x1138, 0x080c, 0x7932, 0x080c, 0x612e, 0x080c, 0x7563, - 0x0010, 0x080c, 0x5fed, 0x080c, 0x8130, 0x0041, 0x0018, 0x9184, - 0x9540, 0x1dc8, 0x002e, 0x001e, 0x000e, 0x0005, 0x00e6, 0x0036, - 0x0046, 0x0056, 0x2071, 0x1a65, 0x080c, 0x1ad9, 0x005e, 0x004e, - 0x003e, 0x00ee, 0x0005, 0x0126, 0x2091, 0x2e00, 0x2071, 0x1800, - 0x7128, 0x2001, 0x196f, 0x2102, 0x2001, 0x1977, 0x2102, 0x2001, - 0x013b, 0x2102, 0x2079, 0x0200, 0x2001, 0x0201, 0x789e, 0x78a3, - 0x0200, 0x9198, 0x0007, 0x831c, 0x831c, 0x831c, 0x9398, 0x0005, - 0x2320, 0x9182, 0x0204, 0x1230, 0x2011, 0x0008, 0x8423, 0x8423, - 0x8423, 0x0488, 0x9182, 0x024c, 0x1240, 0x2011, 0x0007, 0x8403, - 0x8003, 0x9400, 0x9400, 0x9420, 0x0430, 0x9182, 0x02bc, 0x1238, - 0x2011, 0x0006, 0x8403, 0x8003, 0x9400, 0x9420, 0x00e0, 0x9182, - 0x034c, 0x1230, 0x2011, 0x0005, 0x8403, 0x8003, 0x9420, 0x0098, - 0x9182, 0x042c, 0x1228, 0x2011, 0x0004, 0x8423, 0x8423, 0x0058, - 0x9182, 0x059c, 0x1228, 0x2011, 0x0003, 0x8403, 0x9420, 0x0018, - 0x2011, 0x0002, 0x8423, 0x9482, 0x0228, 0x8002, 0x8020, 0x8301, - 0x9402, 0x0110, 0x0208, 0x8321, 0x8217, 0x8203, 0x9405, 0x789a, - 0x012e, 0x0005, 0x0006, 0x00d6, 0x2069, 0x0200, 0x6814, 0x9084, - 0xffc0, 0x910d, 0x6916, 0x00de, 0x000e, 0x0005, 0x00d6, 0x2069, - 0x0200, 0x9005, 0x6810, 0x0110, 0xc0a5, 0x0008, 0xc0a4, 0x6812, - 0x00de, 0x0005, 0x0006, 0x00d6, 0x2069, 0x0200, 0x6810, 0x9084, - 0xfff8, 0x910d, 0x6912, 0x00de, 0x000e, 0x0005, 0x7938, 0x080c, - 0x0dbe, 0x00f6, 0x2079, 0x0200, 0x7902, 0xa001, 0xa001, 0xa001, - 0xa001, 0xa001, 0xa001, 0x7902, 0xa001, 0xa001, 0xa001, 0xa001, - 0xa001, 0xa001, 0x00fe, 0x0005, 0x0126, 0x2091, 0x2800, 0x2061, - 0x0100, 0x2071, 0x1800, 0x2009, 0x0000, 0x080c, 0x2c67, 0x080c, - 0x2b82, 0x6054, 0x8004, 0x8004, 0x8004, 0x8004, 0x9084, 0x000c, - 0x6150, 0x918c, 0xfff3, 0x9105, 0x6052, 0x6050, 0x9084, 0xb17f, - 0x9085, 0x2000, 0x6052, 0x2009, 0x199d, 0x2011, 0x199e, 0x6358, - 0x939c, 0x38f0, 0x2320, 0x080c, 0x2bc6, 0x1238, 0x939d, 0x4003, - 0x94a5, 0x8603, 0x230a, 0x2412, 0x0030, 0x939d, 0x0203, 0x94a5, - 0x8603, 0x230a, 0x2412, 0x9006, 0x080c, 0x2bb1, 0x9006, 0x080c, - 0x2b94, 0x20a9, 0x0012, 0x1d04, 0x245b, 0x2091, 0x6000, 0x1f04, - 0x245b, 0x602f, 0x0100, 0x602f, 0x0000, 0x6050, 0x9085, 0x0400, - 0x9084, 0xdfff, 0x6052, 0x6024, 0x6026, 0x080c, 0x28ac, 0x2009, - 0x00ef, 0x6132, 0x6136, 0x080c, 0x28bc, 0x60e7, 0x0000, 0x61ea, - 0x2001, 0x180d, 0x2004, 0xd08c, 0x2001, 0x0002, 0x1110, 0x2001, - 0x0008, 0x60e2, 0x604b, 0xf7f7, 0x6043, 0x0000, 0x602f, 0x0080, - 0x602f, 0x0000, 0x6007, 0x349f, 0x60bb, 0x0000, 0x20a9, 0x0018, - 0x60bf, 0x0000, 0x1f04, 0x2490, 0x60bb, 0x0000, 0x60bf, 0x0108, - 0x60bf, 0x0012, 0x60bf, 0x0405, 0x60bf, 0x0014, 0x60bf, 0x0320, - 0x60bf, 0x0018, 0x601b, 0x00f0, 0x601f, 0x001e, 0x600f, 0x006b, - 0x602b, 0x402f, 0x012e, 0x0005, 0x00f6, 0x2079, 0x0140, 0x78c3, - 0x0080, 0x78c3, 0x0083, 0x78c3, 0x0000, 0x00fe, 0x0005, 0x2001, - 0x1835, 0x2003, 0x0000, 0x2001, 0x1834, 0x2003, 0x0001, 0x0005, - 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x6124, 0x0066, - 0x2031, 0x1837, 0x2634, 0x96b4, 0x0028, 0x006e, 0x1138, 0x6020, - 0xd1bc, 0x0120, 0xd0bc, 0x1168, 0xd0b4, 0x1198, 0x9184, 0x5e2c, - 0x1118, 0x9184, 0x0007, 0x00aa, 0x9195, 0x0004, 0x9284, 0x0007, - 0x0082, 0x0016, 0x2001, 0x188b, 0x200c, 0xd184, 0x001e, 0x0d70, - 0x0c98, 0x0016, 0x2001, 0x188b, 0x200c, 0xd194, 0x001e, 0x0d30, - 0x0c58, 0x2513, 0x24f9, 0x24fc, 0x24ff, 0x2504, 0x2506, 0x250a, - 0x250e, 0x080c, 0x93e2, 0x00b8, 0x080c, 0x94b1, 0x00a0, 0x080c, - 0x94b1, 0x080c, 0x93e2, 0x0078, 0x0099, 0x0068, 0x080c, 0x93e2, - 0x0079, 0x0048, 0x080c, 0x94b1, 0x0059, 0x0028, 0x080c, 0x94b1, - 0x080c, 0x93e2, 0x0029, 0x002e, 0x001e, 0x000e, 0x012e, 0x0005, - 0x00a6, 0x6124, 0x6028, 0xd09c, 0x0118, 0xd19c, 0x1904, 0x2784, - 0xd1f4, 0x190c, 0x0dbe, 0x080c, 0x7637, 0x0904, 0x256e, 0x080c, - 0xd7e3, 0x1120, 0x7000, 0x9086, 0x0003, 0x0570, 0x6024, 0x9084, - 0x1800, 0x0550, 0x080c, 0x765a, 0x0118, 0x080c, 0x7648, 0x1520, - 0x6027, 0x0020, 0x6043, 0x0000, 0x080c, 0xd7e3, 0x0168, 0x080c, - 0x765a, 0x1150, 0x2001, 0x19a8, 0x2003, 0x0001, 0x6027, 0x1800, - 0x080c, 0x74b2, 0x0804, 0x2787, 0x70a4, 0x9005, 0x1150, 0x70a7, - 0x0001, 0x00d6, 0x2069, 0x0140, 0x080c, 0x768b, 0x00de, 0x1904, - 0x2787, 0x080c, 0x793c, 0x0428, 0x080c, 0x765a, 0x1590, 0x6024, - 0x9084, 0x1800, 0x1108, 0x0468, 0x080c, 0x793c, 0x080c, 0x7932, - 0x080c, 0x612e, 0x080c, 0x7563, 0x0804, 0x2784, 0xd1ac, 0x1508, - 0x6024, 0xd0dc, 0x1170, 0xd0e4, 0x1178, 0xd0d4, 0x1190, 0xd0cc, - 0x0130, 0x7098, 0x9086, 0x0029, 0x1110, 0x080c, 0x7818, 0x0804, - 0x2784, 0x080c, 0x7937, 0x0048, 0x2001, 0x197d, 0x2003, 0x0002, - 0x0020, 0x080c, 0x7774, 0x0804, 0x2784, 0x080c, 0x78ba, 0x0804, - 0x2784, 0x6220, 0xd1bc, 0x0138, 0xd2bc, 0x1904, 0x27e1, 0xd2b4, - 0x1904, 0x27f4, 0x0000, 0xd1ac, 0x0904, 0x2699, 0x0036, 0x6328, - 0xc3bc, 0x632a, 0x003e, 0x080c, 0x7637, 0x11c0, 0x6027, 0x0020, - 0x0006, 0x0026, 0x0036, 0x080c, 0x7651, 0x1158, 0x080c, 0x7932, - 0x080c, 0x612e, 0x080c, 0x7563, 0x003e, 0x002e, 0x000e, 0x00ae, - 0x0005, 0x003e, 0x002e, 0x000e, 0x080c, 0x760f, 0x0016, 0x0046, - 0x00c6, 0x644c, 0x9486, 0xf0f0, 0x1138, 0x2061, 0x0100, 0x644a, - 0x6043, 0x0090, 0x6043, 0x0010, 0x74da, 0x948c, 0xff00, 0x7038, - 0xd084, 0x0190, 0x080c, 0xd7e3, 0x1118, 0x9186, 0xf800, 0x1160, - 0x7048, 0xd084, 0x1148, 0xc085, 0x704a, 0x0036, 0x2418, 0x2011, - 0x8016, 0x080c, 0x4c44, 0x003e, 0x080c, 0xd7dc, 0x1904, 0x2676, - 0x9196, 0xff00, 0x05a8, 0x7060, 0x9084, 0x00ff, 0x810f, 0x81ff, - 0x0110, 0x9116, 0x0568, 0x7130, 0xd184, 0x1550, 0x080c, 0x33aa, - 0x0128, 0xc18d, 0x7132, 0x080c, 0x6a9b, 0x1510, 0x6240, 0x9294, - 0x0010, 0x0130, 0x6248, 0x9294, 0xff00, 0x9296, 0xff00, 0x01c0, - 0x7030, 0xd08c, 0x0904, 0x2676, 0x7038, 0xd08c, 0x1140, 0x2001, - 0x180c, 0x200c, 0xd1ac, 0x1904, 0x2676, 0xc1ad, 0x2102, 0x0036, - 0x73d8, 0x2011, 0x8013, 0x080c, 0x4c44, 0x003e, 0x0804, 0x2676, - 0x7038, 0xd08c, 0x1140, 0x2001, 0x180c, 0x200c, 0xd1ac, 0x1904, - 0x2676, 0xc1ad, 0x2102, 0x0036, 0x73d8, 0x2011, 0x8013, 0x080c, - 0x4c44, 0x003e, 0x7130, 0xc185, 0x7132, 0x2011, 0x1848, 0x220c, - 0xd1a4, 0x01f0, 0x0016, 0x2009, 0x0001, 0x2011, 0x0100, 0x080c, - 0x8a50, 0x2019, 0x000e, 0x00c6, 0x2061, 0x0000, 0x080c, 0xeba1, - 0x00ce, 0x9484, 0x00ff, 0x9080, 0x33b6, 0x200d, 0x918c, 0xff00, - 0x810f, 0x2120, 0x9006, 0x2009, 0x000e, 0x080c, 0xec31, 0x001e, - 0x0016, 0x2009, 0x0002, 0x2019, 0x0004, 0x080c, 0x321b, 0x001e, - 0x00a8, 0x0156, 0x00b6, 0x20a9, 0x007f, 0x900e, 0x080c, 0x6724, - 0x1140, 0x7030, 0xd084, 0x1118, 0xb800, 0xd0bc, 0x1110, 0x080c, - 0x6148, 0x8108, 0x1f04, 0x2666, 0x00be, 0x015e, 0x00ce, 0x004e, - 0x080c, 0xb244, 0x60e3, 0x0000, 0x001e, 0x2001, 0x1800, 0x2014, - 0x9296, 0x0004, 0x1170, 0xd19c, 0x11a0, 0x2011, 0x180c, 0x2214, - 0xd29c, 0x1120, 0x6204, 0x9295, 0x0002, 0x6206, 0x6228, 0xc29d, - 0x622a, 0x2003, 0x0001, 0x2001, 0x1826, 0x2003, 0x0000, 0x6027, - 0x0020, 0xd194, 0x0904, 0x2784, 0x0016, 0x6220, 0xd2b4, 0x0904, - 0x2721, 0x080c, 0x88c3, 0x080c, 0xa6e9, 0x6027, 0x0004, 0x00f6, - 0x2019, 0x19f1, 0x2304, 0x907d, 0x0904, 0x26f0, 0x7804, 0x9086, - 0x0032, 0x15f0, 0x00d6, 0x00c6, 0x00e6, 0x0096, 0x2069, 0x0140, - 0x782c, 0x685e, 0x7808, 0x685a, 0x6043, 0x0002, 0x2001, 0x0003, - 0x8001, 0x1df0, 0x6043, 0x0000, 0x2001, 0x003c, 0x8001, 0x1df0, - 0x080c, 0x2d49, 0x2001, 0x001e, 0x8001, 0x0240, 0x20a9, 0x0009, - 0x080c, 0x2c42, 0x6904, 0xd1dc, 0x1140, 0x0cb0, 0x2001, 0x0100, - 0x080c, 0x2d39, 0x9006, 0x080c, 0x2d39, 0x080c, 0x99a5, 0x080c, - 0x9ab1, 0x7814, 0x2048, 0xa867, 0x0103, 0x2f60, 0x080c, 0xb2d3, - 0x009e, 0x00ee, 0x00ce, 0x00de, 0x00fe, 0x001e, 0x00ae, 0x0005, - 0x00fe, 0x00d6, 0x2069, 0x0140, 0x6804, 0x9084, 0x4000, 0x0110, - 0x080c, 0x2d49, 0x00de, 0x00c6, 0x2061, 0x19e8, 0x6028, 0x080c, - 0xd7e3, 0x0120, 0x909a, 0x0003, 0x1258, 0x0018, 0x909a, 0x00c8, - 0x1238, 0x8000, 0x602a, 0x00ce, 0x080c, 0xa6c5, 0x0804, 0x2783, - 0x2061, 0x0100, 0x62c0, 0x080c, 0xb0ca, 0x2019, 0x19f1, 0x2304, - 0x9065, 0x0120, 0x2009, 0x0027, 0x080c, 0xb352, 0x00ce, 0x0804, - 0x2783, 0xd2bc, 0x0904, 0x276a, 0x080c, 0x88d0, 0x6014, 0x9084, - 0x1984, 0x9085, 0x0010, 0x6016, 0x6027, 0x0004, 0x00d6, 0x2069, - 0x0140, 0x6804, 0x9084, 0x4000, 0x0110, 0x080c, 0x2d49, 0x00de, - 0x00c6, 0x2061, 0x19e8, 0x6044, 0x080c, 0xd7e3, 0x0120, 0x909a, - 0x0003, 0x1658, 0x0018, 0x909a, 0x00c8, 0x1638, 0x8000, 0x6046, - 0x603c, 0x00ce, 0x9005, 0x05b8, 0x2009, 0x07d0, 0x080c, 0x88c8, - 0x9080, 0x0008, 0x2004, 0x9086, 0x0006, 0x1138, 0x6114, 0x918c, - 0x1984, 0x918d, 0x0012, 0x6116, 0x0430, 0x9080, 0x0008, 0x2004, - 0x9086, 0x0009, 0x0d98, 0x6114, 0x918c, 0x1984, 0x918d, 0x0016, - 0x6116, 0x00c8, 0x6027, 0x0004, 0x00b0, 0x0036, 0x2019, 0x0001, - 0x080c, 0xaa49, 0x003e, 0x2019, 0x19f7, 0x2304, 0x9065, 0x0150, - 0x2009, 0x004f, 0x6020, 0x9086, 0x0009, 0x1110, 0x2009, 0x004f, - 0x080c, 0xb352, 0x00ce, 0x001e, 0xd19c, 0x0904, 0x27dc, 0x7038, - 0xd0ac, 0x1538, 0x0016, 0x0156, 0x6027, 0x0008, 0x080c, 0x2d73, - 0x20a9, 0x0028, 0xa001, 0x1f04, 0x2792, 0x6150, 0x9185, 0x1400, - 0x6052, 0x20a9, 0x0366, 0x1d04, 0x279b, 0x080c, 0x88f7, 0x6020, - 0xd09c, 0x1130, 0x015e, 0x6152, 0x001e, 0x6027, 0x0008, 0x04a0, - 0x080c, 0x2c29, 0x1f04, 0x279b, 0x015e, 0x6152, 0x001e, 0x6027, - 0x0008, 0x0016, 0x6028, 0xc09c, 0x602a, 0x080c, 0xb244, 0x60e3, - 0x0000, 0x080c, 0xf07f, 0x080c, 0xf09a, 0x080c, 0x57d9, 0xd0fc, - 0x1138, 0x080c, 0xd7dc, 0x1120, 0x9085, 0x0001, 0x080c, 0x767b, - 0x9006, 0x080c, 0x2d39, 0x2009, 0x0002, 0x080c, 0x2c67, 0x00e6, - 0x2071, 0x1800, 0x7003, 0x0004, 0x080c, 0x0ea3, 0x00ee, 0x6027, - 0x0008, 0x080c, 0x0ba0, 0x001e, 0x918c, 0xffd0, 0x6126, 0x00ae, - 0x0005, 0x0016, 0x2001, 0x188b, 0x200c, 0xd184, 0x001e, 0x0904, - 0x259b, 0x0016, 0x2009, 0x27ed, 0x00d0, 0x2001, 0x188b, 0x200c, - 0xc184, 0x2102, 0x001e, 0x0c40, 0x0016, 0x2001, 0x188b, 0x200c, - 0xd194, 0x001e, 0x0904, 0x259b, 0x0016, 0x2009, 0x2800, 0x0038, - 0x2001, 0x188b, 0x200c, 0xc194, 0x2102, 0x001e, 0x08a8, 0x6028, - 0xc0bc, 0x602a, 0x2001, 0x0156, 0x2003, 0xbc91, 0x8000, 0x2003, - 0xffff, 0x6043, 0x0001, 0x080c, 0x2c61, 0x6027, 0x0080, 0x6017, - 0x0000, 0x6043, 0x0000, 0x0817, 0x0006, 0x0016, 0x0026, 0x0036, - 0x00e6, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2071, 0x1800, 0x71d0, - 0x70d2, 0x9116, 0x0904, 0x286b, 0x81ff, 0x01a0, 0x2009, 0x0000, - 0x080c, 0x2c67, 0x2011, 0x8011, 0x2019, 0x010e, 0x231c, 0x939e, - 0x0007, 0x1118, 0x2019, 0x0001, 0x0010, 0x2019, 0x0000, 0x080c, - 0x4c44, 0x0448, 0x2001, 0x19a9, 0x200c, 0x81ff, 0x1140, 0x2001, - 0x0109, 0x2004, 0xd0b4, 0x0118, 0x2019, 0x0003, 0x0008, 0x2118, - 0x2011, 0x8012, 0x080c, 0x4c44, 0x080c, 0x0ea3, 0x080c, 0x57d9, - 0xd0fc, 0x1188, 0x080c, 0xd7dc, 0x1170, 0x00c6, 0x080c, 0x2907, - 0x080c, 0xa9b0, 0x2061, 0x0100, 0x2019, 0x0028, 0x2009, 0x0002, - 0x080c, 0x321b, 0x00ce, 0x012e, 0x00fe, 0x00ee, 0x003e, 0x002e, - 0x001e, 0x000e, 0x0005, 0x2028, 0x918c, 0x00ff, 0x2130, 0x9094, - 0xff00, 0x11f0, 0x2011, 0x1837, 0x2214, 0xd2ac, 0x11c8, 0x81ff, - 0x01e8, 0x2011, 0x181f, 0x2204, 0x9106, 0x1190, 0x2011, 0x1820, - 0x2214, 0x9294, 0xff00, 0x9584, 0xff00, 0x9206, 0x1148, 0x2011, - 0x1820, 0x2214, 0x9294, 0x00ff, 0x9584, 0x00ff, 0x9206, 0x1120, - 0x2500, 0x080c, 0x83a5, 0x0048, 0x9584, 0x00ff, 0x9080, 0x33b6, - 0x200d, 0x918c, 0xff00, 0x810f, 0x9006, 0x0005, 0x9080, 0x33b6, - 0x200d, 0x918c, 0x00ff, 0x0005, 0x00d6, 0x2069, 0x0140, 0x2001, - 0x1818, 0x2003, 0x00ef, 0x20a9, 0x0010, 0x9006, 0x6852, 0x6856, - 0x1f04, 0x28b7, 0x00de, 0x0005, 0x0006, 0x00d6, 0x0026, 0x2069, - 0x0140, 0x2001, 0x1818, 0x2102, 0x8114, 0x8214, 0x8214, 0x8214, - 0x20a9, 0x0010, 0x6853, 0x0000, 0x9006, 0x82ff, 0x1128, 0x9184, - 0x000f, 0x9080, 0xf880, 0x2005, 0x6856, 0x8211, 0x1f04, 0x28cc, - 0x002e, 0x00de, 0x000e, 0x0005, 0x00c6, 0x2061, 0x1800, 0x6030, - 0x0110, 0xc09d, 0x0008, 0xc09c, 0x6032, 0x00ce, 0x0005, 0x0156, - 0x00d6, 0x0026, 0x0016, 0x0006, 0x2069, 0x0140, 0x6980, 0x9116, - 0x0180, 0x9112, 0x1230, 0x8212, 0x8210, 0x22a8, 0x2001, 0x0402, - 0x0018, 0x22a8, 0x2001, 0x0404, 0x680e, 0x1f04, 0x28fc, 0x680f, - 0x0000, 0x000e, 0x001e, 0x002e, 0x00de, 0x015e, 0x0005, 0x080c, - 0x57d5, 0xd0c4, 0x0150, 0xd0a4, 0x0140, 0x9006, 0x0046, 0x2020, - 0x2009, 0x002e, 0x080c, 0xec31, 0x004e, 0x0005, 0x00f6, 0x0016, - 0x0026, 0x2079, 0x0140, 0x78c4, 0xd0dc, 0x0904, 0x2973, 0x080c, - 0x2bc6, 0x0660, 0x9084, 0x0700, 0x908e, 0x0600, 0x1120, 0x2011, - 0x4000, 0x900e, 0x0458, 0x908e, 0x0500, 0x1120, 0x2011, 0x8000, - 0x900e, 0x0420, 0x908e, 0x0400, 0x1120, 0x9016, 0x2009, 0x0001, - 0x00e8, 0x908e, 0x0300, 0x1120, 0x9016, 0x2009, 0x0002, 0x00b0, - 0x908e, 0x0200, 0x1120, 0x9016, 0x2009, 0x0004, 0x0078, 0x908e, - 0x0100, 0x1548, 0x9016, 0x2009, 0x0008, 0x0040, 0x9084, 0x0700, - 0x908e, 0x0300, 0x1500, 0x2011, 0x0030, 0x0058, 0x2300, 0x9080, - 0x0020, 0x2018, 0x080c, 0x9375, 0x928c, 0xff00, 0x0110, 0x2011, - 0x00ff, 0x2200, 0x8007, 0x9085, 0x004c, 0x78c2, 0x2009, 0x0138, - 0x220a, 0x080c, 0x7637, 0x1118, 0x2009, 0x196d, 0x220a, 0x002e, - 0x001e, 0x00fe, 0x0005, 0x78c3, 0x0000, 0x0cc8, 0x0126, 0x2091, - 0x2800, 0x0006, 0x0016, 0x0026, 0x2001, 0x0170, 0x200c, 0x8000, - 0x2014, 0x9184, 0x0003, 0x0110, 0x080c, 0x0dbe, 0x002e, 0x001e, - 0x000e, 0x012e, 0x0005, 0x2001, 0x180d, 0x2004, 0xd08c, 0x0118, - 0x2009, 0x0002, 0x0005, 0x2001, 0x0171, 0x2004, 0xd0dc, 0x0168, - 0x2001, 0x0170, 0x200c, 0x918c, 0x00ff, 0x918e, 0x004c, 0x1128, - 0x200c, 0x918c, 0xff00, 0x810f, 0x0005, 0x900e, 0x2001, 0x0227, - 0x2004, 0x8007, 0x9084, 0x00ff, 0x8004, 0x9108, 0x2001, 0x0226, - 0x2004, 0x8007, 0x9084, 0x00ff, 0x8004, 0x9108, 0x0005, 0x0018, - 0x000c, 0x0018, 0x0020, 0x1000, 0x0800, 0x1000, 0x1800, 0x0156, - 0x0006, 0x0016, 0x0026, 0x00e6, 0x2001, 0x1990, 0x2004, 0x908a, - 0x0007, 0x1a0c, 0x0dc5, 0x0033, 0x00ee, 0x002e, 0x001e, 0x000e, - 0x015e, 0x0005, 0x29d9, 0x29f7, 0x2a1b, 0x2a1d, 0x2a46, 0x2a48, - 0x2a4a, 0x2001, 0x0001, 0x080c, 0x281c, 0x080c, 0x2c24, 0x2001, - 0x1992, 0x2003, 0x0000, 0x7828, 0x9084, 0xe1d7, 0x782a, 0x9006, - 0x20a9, 0x0009, 0x080c, 0x2be2, 0x2001, 0x1990, 0x2003, 0x0006, - 0x2009, 0x001e, 0x2011, 0x2a4b, 0x080c, 0x88d5, 0x0005, 0x2009, - 0x1995, 0x200b, 0x0000, 0x2001, 0x199a, 0x2003, 0x0036, 0x2001, - 0x1999, 0x2003, 0x002a, 0x2001, 0x1992, 0x2003, 0x0001, 0x9006, - 0x080c, 0x2b94, 0x2001, 0xffff, 0x20a9, 0x0009, 0x080c, 0x2be2, - 0x2001, 0x1990, 0x2003, 0x0006, 0x2009, 0x001e, 0x2011, 0x2a4b, - 0x080c, 0x88d5, 0x0005, 0x080c, 0x0dc5, 0x2001, 0x199a, 0x2003, - 0x0036, 0x2001, 0x1992, 0x2003, 0x0003, 0x7a38, 0x9294, 0x0005, - 0x9296, 0x0004, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, - 0x2b94, 0x2001, 0x1996, 0x2003, 0x0000, 0x2001, 0xffff, 0x20a9, - 0x0009, 0x080c, 0x2be2, 0x2001, 0x1990, 0x2003, 0x0006, 0x2009, - 0x001e, 0x2011, 0x2a4b, 0x080c, 0x88d5, 0x0005, 0x080c, 0x0dc5, - 0x080c, 0x0dc5, 0x0005, 0x0006, 0x0016, 0x0026, 0x00e6, 0x00f6, - 0x0156, 0x0126, 0x2091, 0x8000, 0x2079, 0x0100, 0x2001, 0x1992, - 0x2004, 0x908a, 0x0007, 0x1a0c, 0x0dc5, 0x0043, 0x012e, 0x015e, - 0x00fe, 0x00ee, 0x002e, 0x001e, 0x000e, 0x0005, 0x2a6d, 0x2a89, - 0x2ac5, 0x2af1, 0x2b11, 0x2b1d, 0x2b1f, 0x080c, 0x2bd6, 0x1190, - 0x2009, 0x1998, 0x2104, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0004, - 0x0110, 0xc08d, 0x0008, 0xc085, 0x200a, 0x2001, 0x1990, 0x2003, - 0x0001, 0x0030, 0x080c, 0x2b43, 0x2001, 0xffff, 0x080c, 0x29e8, - 0x0005, 0x080c, 0x2b21, 0x05c0, 0x2009, 0x1999, 0x2104, 0x8001, - 0x200a, 0x080c, 0x2bd6, 0x1158, 0x7a38, 0x9294, 0x0005, 0x9296, - 0x0005, 0x0518, 0x2009, 0x1998, 0x2104, 0xc085, 0x200a, 0x2009, - 0x1995, 0x2104, 0x8000, 0x200a, 0x9086, 0x0005, 0x0118, 0x080c, - 0x2b29, 0x00c0, 0x200b, 0x0000, 0x7a38, 0x9294, 0x0006, 0x9296, - 0x0004, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x2bb1, - 0x2001, 0x1992, 0x2003, 0x0002, 0x0028, 0x2001, 0x1990, 0x2003, - 0x0003, 0x0010, 0x080c, 0x2a0a, 0x0005, 0x080c, 0x2b21, 0x0540, - 0x2009, 0x1999, 0x2104, 0x8001, 0x200a, 0x080c, 0x2bd6, 0x1148, - 0x2001, 0x1990, 0x2003, 0x0003, 0x2001, 0x1991, 0x2003, 0x0000, - 0x00b8, 0x2009, 0x1999, 0x2104, 0x9005, 0x1118, 0x080c, 0x2b66, - 0x0010, 0x080c, 0x2b36, 0x080c, 0x2b29, 0x2009, 0x1995, 0x200b, - 0x0000, 0x2001, 0x1992, 0x2003, 0x0001, 0x080c, 0x2a0a, 0x0000, - 0x0005, 0x0479, 0x01e8, 0x080c, 0x2bd6, 0x1198, 0x2009, 0x1996, - 0x2104, 0x8000, 0x200a, 0x9086, 0x0007, 0x0108, 0x0078, 0x2001, - 0x199b, 0x2003, 0x000a, 0x2009, 0x1998, 0x2104, 0xc0fd, 0x200a, - 0x0038, 0x00f9, 0x2001, 0x1992, 0x2003, 0x0004, 0x080c, 0x2a35, - 0x0005, 0x0079, 0x0148, 0x080c, 0x2bd6, 0x1118, 0x080c, 0x2a21, - 0x0018, 0x0079, 0x080c, 0x2a35, 0x0005, 0x080c, 0x0dc5, 0x080c, - 0x0dc5, 0x2009, 0x199a, 0x2104, 0x8001, 0x200a, 0x090c, 0x2b82, - 0x0005, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0005, 0x0110, 0x9006, - 0x0010, 0x2001, 0x0001, 0x080c, 0x2bb1, 0x0005, 0x7a38, 0x9294, - 0x0006, 0x9296, 0x0006, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, - 0x080c, 0x2b94, 0x0005, 0x2009, 0x1995, 0x2104, 0x8000, 0x200a, - 0x9086, 0x0005, 0x0108, 0x0068, 0x200b, 0x0000, 0x7a38, 0x9294, - 0x0006, 0x9296, 0x0006, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, - 0x04d9, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0005, 0x0110, 0x9006, - 0x0010, 0x2001, 0x0001, 0x080c, 0x2bb1, 0x0005, 0x0086, 0x2001, - 0x1998, 0x2004, 0x9084, 0x7fff, 0x090c, 0x0dc5, 0x2009, 0x1997, - 0x2144, 0x8846, 0x280a, 0x9844, 0x0dd8, 0xd08c, 0x1120, 0xd084, - 0x1120, 0x080c, 0x0dc5, 0x9006, 0x0010, 0x2001, 0x0001, 0x00a1, - 0x008e, 0x0005, 0x0006, 0x0156, 0x2001, 0x1990, 0x20a9, 0x0009, - 0x2003, 0x0000, 0x8000, 0x1f04, 0x2b88, 0x2001, 0x1997, 0x2003, - 0x8000, 0x015e, 0x000e, 0x0005, 0x00f6, 0x2079, 0x0100, 0x9085, - 0x0000, 0x0158, 0x7838, 0x9084, 0xfff9, 0x9085, 0x0004, 0x783a, - 0x2009, 0x199d, 0x210c, 0x795a, 0x0050, 0x7838, 0x9084, 0xfffb, - 0x9085, 0x0006, 0x783a, 0x2009, 0x199e, 0x210c, 0x795a, 0x00fe, - 0x0005, 0x00f6, 0x2079, 0x0100, 0x9085, 0x0000, 0x0138, 0x7838, - 0x9084, 0xfffa, 0x9085, 0x0004, 0x783a, 0x0030, 0x7838, 0x9084, - 0xfffb, 0x9085, 0x0005, 0x783a, 0x00fe, 0x0005, 0x0006, 0x2001, - 0x0100, 0x2004, 0x9082, 0x0007, 0x000e, 0x0005, 0x0006, 0x2001, - 0x0100, 0x2004, 0x9082, 0x0009, 0x000e, 0x0005, 0x0156, 0x20a9, - 0x0064, 0x7820, 0x080c, 0x2c61, 0xd09c, 0x1110, 0x1f04, 0x2bd9, - 0x015e, 0x0005, 0x0126, 0x0016, 0x0006, 0x2091, 0x8000, 0x7850, - 0x9085, 0x0040, 0x7852, 0x7850, 0x9084, 0xfbcf, 0x7852, 0x080c, - 0x2c61, 0x9085, 0x2000, 0x7852, 0x000e, 0x2008, 0x9186, 0x0000, - 0x1118, 0x783b, 0x0007, 0x0090, 0x9186, 0x0001, 0x1118, 0x783b, - 0x0006, 0x0060, 0x9186, 0x0002, 0x1118, 0x783b, 0x0005, 0x0030, - 0x9186, 0x0003, 0x1118, 0x783b, 0x0004, 0x0000, 0x0006, 0x1d04, - 0x2c0f, 0x080c, 0x88f7, 0x1f04, 0x2c0f, 0x7850, 0x9085, 0x0400, - 0x9084, 0xdfbf, 0x7852, 0x080c, 0x2c61, 0x9085, 0x1000, 0x7852, - 0x000e, 0x001e, 0x012e, 0x0005, 0x7850, 0x9084, 0xffcf, 0x7852, - 0x0005, 0x0006, 0x0156, 0x00f6, 0x2079, 0x0100, 0x20a9, 0x000a, - 0x7854, 0xd0ac, 0x1130, 0x7820, 0xd0e4, 0x1140, 0x1f04, 0x2c33, - 0x0028, 0x7854, 0xd08c, 0x1110, 0x1f04, 0x2c39, 0x00fe, 0x015e, - 0x000e, 0x0005, 0x1d04, 0x2c42, 0x080c, 0x88f7, 0x1f04, 0x2c42, - 0x0005, 0x0006, 0x2001, 0x199c, 0x2004, 0x9086, 0x0000, 0x000e, - 0x0005, 0x0006, 0x2001, 0x199c, 0x2004, 0x9086, 0x0001, 0x000e, - 0x0005, 0x0006, 0x2001, 0x199c, 0x2004, 0x9086, 0x0002, 0x000e, - 0x0005, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0x0005, 0x0006, - 0x2001, 0x19a9, 0x2102, 0x000e, 0x0005, 0x2009, 0x0171, 0x2104, - 0xd0dc, 0x0140, 0x2009, 0x0170, 0x2104, 0x200b, 0x0080, 0xa001, - 0xa001, 0x200a, 0x0005, 0x0036, 0x0046, 0x2001, 0x0141, 0x200c, - 0x918c, 0xff00, 0x9186, 0x2100, 0x0140, 0x9186, 0x2000, 0x0170, - 0x9186, 0x0100, 0x1904, 0x2cda, 0x0048, 0x0016, 0x2009, 0x1a87, - 0x2104, 0x8000, 0x0208, 0x200a, 0x001e, 0x04f0, 0x2009, 0x00a2, - 0x080c, 0x0e52, 0x2019, 0x0160, 0x2324, 0x2011, 0x0003, 0x2009, - 0x0169, 0x2104, 0x9084, 0x0007, 0x210c, 0x918c, 0x0007, 0x910e, - 0x1db0, 0x9086, 0x0003, 0x1548, 0x2304, 0x0066, 0x0076, 0x2031, - 0x0002, 0x233c, 0x973e, 0x0148, 0x8631, 0x1dd8, 0x2031, 0x1a88, - 0x263c, 0x8738, 0x0208, 0x2732, 0x2304, 0x007e, 0x006e, 0x9402, - 0x02a0, 0x19d0, 0x8211, 0x19d8, 0x84ff, 0x0170, 0x2001, 0x0141, - 0x200c, 0x918c, 0xff00, 0x9186, 0x0100, 0x0130, 0x2009, 0x180c, - 0x2104, 0xc0dd, 0x200a, 0x0008, 0x0421, 0x2001, 0x1981, 0x200c, - 0x080c, 0x0e52, 0x004e, 0x003e, 0x0005, 0x2001, 0x180c, 0x2004, - 0xd0dc, 0x01b0, 0x2001, 0x0160, 0x2004, 0x9005, 0x0140, 0x2001, - 0x0141, 0x2004, 0x9084, 0xff00, 0x9086, 0x0100, 0x1148, 0x0126, - 0x2091, 0x8000, 0x0016, 0x0026, 0x0021, 0x002e, 0x001e, 0x012e, - 0x0005, 0x00c6, 0x2061, 0x0100, 0x6014, 0x0006, 0x2001, 0x0161, - 0x2003, 0x0000, 0x6017, 0x0018, 0xa001, 0xa001, 0x602f, 0x0008, - 0x6104, 0x918e, 0x0010, 0x6106, 0x918e, 0x0010, 0x6106, 0x6017, - 0x0040, 0x04b9, 0x001e, 0x9184, 0x0003, 0x01e0, 0x0036, 0x0016, - 0x2019, 0x0141, 0x6124, 0x918c, 0x0028, 0x1120, 0x2304, 0x9084, - 0x2800, 0x0dc0, 0x001e, 0x919c, 0xffe4, 0x9184, 0x0001, 0x0118, - 0x9385, 0x0009, 0x6016, 0x9184, 0x0002, 0x0118, 0x9385, 0x0012, - 0x6016, 0x003e, 0x2001, 0x180c, 0x200c, 0xc1dc, 0x2102, 0x00ce, - 0x0005, 0x0016, 0x0026, 0x080c, 0x7651, 0x0108, 0xc0bc, 0x2009, - 0x0140, 0x2114, 0x9294, 0x0001, 0x9215, 0x220a, 0x002e, 0x001e, - 0x0005, 0x0016, 0x0026, 0x2009, 0x0140, 0x2114, 0x9294, 0x0001, - 0x9285, 0x1000, 0x200a, 0x220a, 0x002e, 0x001e, 0x0005, 0x0016, - 0x0026, 0x2009, 0x0140, 0x2114, 0x9294, 0x0001, 0x9215, 0x220a, - 0x002e, 0x001e, 0x0005, 0x0006, 0x0016, 0x2009, 0x0140, 0x2104, - 0x1128, 0x080c, 0x7651, 0x0110, 0xc0bc, 0x0008, 0xc0bd, 0x200a, - 0x001e, 0x000e, 0x0005, 0x0006, 0x0156, 0x6050, 0x9085, 0x0040, - 0x6052, 0x6050, 0x9084, 0xfbcf, 0x6052, 0x080c, 0x2c61, 0x9085, - 0x2000, 0x6052, 0x20a9, 0x0012, 0x1d04, 0x2d84, 0x080c, 0x88f7, - 0x1f04, 0x2d84, 0x6050, 0x9085, 0x0400, 0x9084, 0xdfbf, 0x6052, - 0x015e, 0x000e, 0x0005, 0x2fff, 0x2fff, 0x2e23, 0x2e23, 0x2e2f, - 0x2e2f, 0x2e3b, 0x2e3b, 0x2e49, 0x2e49, 0x2e55, 0x2e55, 0x2e63, - 0x2e63, 0x2e71, 0x2e71, 0x2e83, 0x2e83, 0x2e8f, 0x2e8f, 0x2e9d, - 0x2e9d, 0x2ebb, 0x2ebb, 0x2edb, 0x2edb, 0x2eab, 0x2eab, 0x2ecb, - 0x2ecb, 0x2ee9, 0x2ee9, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, - 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, - 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, - 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, - 0x2e81, 0x2e81, 0x2e81, 0x2efb, 0x2efb, 0x2f07, 0x2f07, 0x2f15, - 0x2f15, 0x2f23, 0x2f23, 0x2f33, 0x2f33, 0x2f41, 0x2f41, 0x2f51, - 0x2f51, 0x2f61, 0x2f61, 0x2f73, 0x2f73, 0x2f81, 0x2f81, 0x2f91, - 0x2f91, 0x2fb3, 0x2fb3, 0x2fd5, 0x2fd5, 0x2fa1, 0x2fa1, 0x2fc4, - 0x2fc4, 0x2fe4, 0x2fe4, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, - 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, - 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, - 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, - 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, - 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, - 0x2e81, 0x2e81, 0x2e81, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x24c0, 0x0804, 0x2ff7, 0x0106, - 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, - 0x22cc, 0x0804, 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x22cc, 0x080c, 0x24c0, 0x0804, - 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x2307, 0x0804, 0x2ff7, 0x0106, 0x0006, 0x0126, - 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x24c0, 0x080c, - 0x2307, 0x0804, 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x22cc, 0x080c, 0x2307, 0x0804, - 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x22cc, 0x080c, 0x24c0, 0x080c, 0x2307, 0x0804, - 0x2ff7, 0xa001, 0x0cf0, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x1394, 0x0804, 0x2ff7, 0x0106, - 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, - 0x24c0, 0x080c, 0x1394, 0x0804, 0x2ff7, 0x0106, 0x0006, 0x0126, - 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x22cc, 0x080c, - 0x1394, 0x0804, 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x24c0, 0x080c, 0x1394, 0x080c, - 0x2307, 0x0804, 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x22cc, 0x080c, 0x24c0, 0x080c, - 0x1394, 0x0804, 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x22cc, 0x080c, 0x1394, 0x080c, - 0x2307, 0x0804, 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x1394, 0x080c, 0x2307, 0x0804, - 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x22cc, 0x080c, 0x24c0, 0x080c, 0x1394, 0x080c, - 0x2307, 0x0804, 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x2976, 0x0804, 0x2ff7, 0x0106, - 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, - 0x2976, 0x080c, 0x24c0, 0x0804, 0x2ff7, 0x0106, 0x0006, 0x0126, - 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2976, 0x080c, - 0x22cc, 0x0804, 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x2976, 0x080c, 0x22cc, 0x080c, - 0x24c0, 0x0804, 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x2976, 0x080c, 0x2307, 0x0804, - 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x2976, 0x080c, 0x24c0, 0x080c, 0x2307, 0x0804, - 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x2976, 0x080c, 0x22cc, 0x080c, 0x2307, 0x0804, - 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x2976, 0x080c, 0x22cc, 0x080c, 0x24c0, 0x080c, - 0x2307, 0x0804, 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x2976, 0x080c, 0x1394, 0x0804, - 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x2976, 0x080c, 0x24c0, 0x080c, 0x1394, 0x0804, - 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x2976, 0x080c, 0x22cc, 0x080c, 0x1394, 0x0804, - 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x2976, 0x080c, 0x24c0, 0x080c, 0x1394, 0x080c, - 0x2307, 0x0804, 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x2976, 0x080c, 0x22cc, 0x080c, - 0x24c0, 0x080c, 0x1394, 0x0498, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2976, 0x080c, 0x22cc, - 0x080c, 0x1394, 0x080c, 0x2307, 0x0410, 0x0106, 0x0006, 0x0126, - 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2976, 0x080c, - 0x1394, 0x080c, 0x2307, 0x0098, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2976, 0x080c, 0x22cc, - 0x080c, 0x24c0, 0x080c, 0x1394, 0x080c, 0x2307, 0x0000, 0x015e, - 0x014e, 0x013e, 0x01de, 0x01ce, 0x012e, 0x000e, 0x010e, 0x000d, - 0x00b6, 0x00c6, 0x0026, 0x0046, 0x9026, 0x080c, 0x6a61, 0x1904, - 0x3137, 0x72dc, 0x2001, 0x197c, 0x2004, 0x9005, 0x1110, 0xd29c, - 0x0148, 0xd284, 0x1138, 0xd2bc, 0x1904, 0x3137, 0x080c, 0x313c, - 0x0804, 0x3137, 0xd2cc, 0x1904, 0x3137, 0x080c, 0x7637, 0x1120, - 0x70af, 0xffff, 0x0804, 0x3137, 0xd294, 0x0120, 0x70af, 0xffff, - 0x0804, 0x3137, 0x080c, 0x33a5, 0x0160, 0x080c, 0xd7e3, 0x0128, - 0x2001, 0x1818, 0x203c, 0x0804, 0x30b0, 0x70af, 0xffff, 0x0804, - 0x3137, 0x2001, 0x1818, 0x203c, 0x7294, 0xd284, 0x0904, 0x30b0, - 0xd28c, 0x1904, 0x30b0, 0x0036, 0x73ac, 0x938e, 0xffff, 0x1110, - 0x2019, 0x0001, 0x8314, 0x92e0, 0x1c80, 0x2c04, 0x938c, 0x0001, - 0x0120, 0x9084, 0xff00, 0x8007, 0x0010, 0x9084, 0x00ff, 0x970e, - 0x0904, 0x30a6, 0x908e, 0x0000, 0x0904, 0x30a6, 0x908e, 0x00ff, - 0x1160, 0x7230, 0xd284, 0x1904, 0x30ab, 0x7294, 0xc28d, 0x7296, - 0x70af, 0xffff, 0x003e, 0x0804, 0x30b0, 0x2009, 0x180d, 0x210c, - 0xd18c, 0x0150, 0x0026, 0x2011, 0x0010, 0x080c, 0x6ac7, 0x002e, - 0x0118, 0x70af, 0xffff, 0x0488, 0x900e, 0x080c, 0x2873, 0x080c, - 0x66b9, 0x1538, 0x9006, 0xb8bb, 0x0520, 0xb8ac, 0x9005, 0x0148, - 0x00c6, 0x2060, 0x080c, 0x8cf7, 0x00ce, 0x090c, 0x9096, 0xb8af, - 0x0000, 0x080c, 0x6aa3, 0x1168, 0x7030, 0xd08c, 0x0130, 0xb800, - 0xd0bc, 0x0138, 0x080c, 0x6944, 0x0120, 0x080c, 0x3155, 0x0148, - 0x0028, 0x080c, 0x3295, 0x080c, 0x3181, 0x0118, 0x8318, 0x0804, - 0x304a, 0x73ae, 0x0010, 0x70af, 0xffff, 0x003e, 0x0804, 0x3137, - 0x9780, 0x33b6, 0x203d, 0x97bc, 0xff00, 0x873f, 0x2041, 0x007e, - 0x70ac, 0x9096, 0xffff, 0x1118, 0x900e, 0x28a8, 0x0050, 0x9812, - 0x0220, 0x2008, 0x9802, 0x20a8, 0x0020, 0x70af, 0xffff, 0x0804, - 0x3137, 0x2700, 0x0156, 0x0016, 0x9106, 0x0904, 0x312c, 0x2001, - 0x180d, 0x2004, 0xd08c, 0x0158, 0x0026, 0x2011, 0x0010, 0x080c, - 0x6ac7, 0x002e, 0x0120, 0x2009, 0xffff, 0x0804, 0x3134, 0xc484, - 0x080c, 0x6724, 0x0168, 0x080c, 0xd7e3, 0x1904, 0x312c, 0x080c, - 0x33a5, 0x1904, 0x312c, 0x080c, 0x66b9, 0x1904, 0x3134, 0x0008, - 0xc485, 0xb8bb, 0x0520, 0xb8ac, 0x9005, 0x0148, 0x00c6, 0x2060, - 0x080c, 0x8cf7, 0x00ce, 0x090c, 0x9096, 0xb8af, 0x0000, 0x080c, - 0x6aa3, 0x1130, 0x7030, 0xd08c, 0x01f8, 0xb800, 0xd0bc, 0x11e0, - 0x7294, 0xd28c, 0x0180, 0x080c, 0x6aa3, 0x9082, 0x0006, 0x02e0, - 0xd484, 0x1118, 0x080c, 0x66de, 0x0028, 0x080c, 0x3321, 0x01a0, - 0x080c, 0x334c, 0x0088, 0x080c, 0x3295, 0x080c, 0xd7e3, 0x1160, - 0x080c, 0x3181, 0x0188, 0x0040, 0x080c, 0xd7e3, 0x1118, 0x080c, - 0x3321, 0x0110, 0x0451, 0x0140, 0x001e, 0x8108, 0x015e, 0x1f04, - 0x30c9, 0x70af, 0xffff, 0x0018, 0x001e, 0x015e, 0x71ae, 0x004e, - 0x002e, 0x00ce, 0x00be, 0x0005, 0x00c6, 0x0016, 0x70af, 0x0001, - 0x2009, 0x007e, 0x080c, 0x66b9, 0x1168, 0xb813, 0x00ff, 0xb817, - 0xfffe, 0x080c, 0x3295, 0x04a9, 0x0128, 0x70dc, 0xc0bd, 0x70de, - 0x080c, 0xd52b, 0x001e, 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, - 0x00c6, 0x2001, 0x184c, 0x2004, 0x9084, 0x00ff, 0xb842, 0x080c, - 0xb325, 0x01d0, 0x2b00, 0x6012, 0x080c, 0xd554, 0x6023, 0x0001, - 0x9006, 0x080c, 0x6656, 0x2001, 0x0000, 0x080c, 0x666a, 0x0126, - 0x2091, 0x8000, 0x70a8, 0x8000, 0x70aa, 0x012e, 0x2009, 0x0004, - 0x080c, 0xb352, 0x9085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, - 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2001, 0x184c, 0x2004, - 0x9084, 0x00ff, 0xb842, 0x080c, 0xb325, 0x0548, 0x2b00, 0x6012, - 0xb800, 0xc0c4, 0xb802, 0xb8a0, 0x9086, 0x007e, 0x0140, 0xb804, - 0x9084, 0x00ff, 0x9086, 0x0006, 0x1110, 0x080c, 0x3250, 0x080c, - 0xd554, 0x6023, 0x0001, 0x9006, 0x080c, 0x6656, 0x2001, 0x0002, - 0x080c, 0x666a, 0x0126, 0x2091, 0x8000, 0x70a8, 0x8000, 0x70aa, - 0x012e, 0x2009, 0x0002, 0x080c, 0xb352, 0x9085, 0x0001, 0x00ce, - 0x00de, 0x007e, 0x001e, 0x0005, 0x00b6, 0x00c6, 0x0026, 0x2009, - 0x0080, 0x080c, 0x66b9, 0x1140, 0xb813, 0x00ff, 0xb817, 0xfffc, - 0x0039, 0x0110, 0x70e3, 0xffff, 0x002e, 0x00ce, 0x00be, 0x0005, - 0x0016, 0x0076, 0x00d6, 0x00c6, 0x080c, 0xb27d, 0x01d0, 0x2b00, - 0x6012, 0x080c, 0xd554, 0x6023, 0x0001, 0x9006, 0x080c, 0x6656, - 0x2001, 0x0002, 0x080c, 0x666a, 0x0126, 0x2091, 0x8000, 0x70e4, - 0x8000, 0x70e6, 0x012e, 0x2009, 0x0002, 0x080c, 0xb352, 0x9085, - 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, 0x00d6, - 0x0126, 0x2091, 0x8000, 0x2009, 0x007f, 0x080c, 0x66b9, 0x11b8, - 0xb813, 0x00ff, 0xb817, 0xfffd, 0xb8cf, 0x0004, 0x080c, 0xb27d, - 0x0170, 0x2b00, 0x6012, 0x6316, 0x6023, 0x0001, 0x620a, 0x080c, - 0xd554, 0x2009, 0x0022, 0x080c, 0xb352, 0x9085, 0x0001, 0x012e, - 0x00de, 0x00ce, 0x0005, 0x00e6, 0x00c6, 0x0066, 0x0036, 0x0026, - 0x00b6, 0x21f0, 0x080c, 0x96af, 0x080c, 0x962f, 0x080c, 0xb111, - 0x080c, 0xc2d3, 0x3e08, 0x2130, 0x81ff, 0x0120, 0x20a9, 0x007e, - 0x900e, 0x0018, 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, 0x6724, - 0x1140, 0x9686, 0x0002, 0x1118, 0xb800, 0xd0bc, 0x1110, 0x080c, - 0x6148, 0x001e, 0x8108, 0x1f04, 0x3235, 0x9686, 0x0001, 0x190c, - 0x3379, 0x00be, 0x002e, 0x003e, 0x006e, 0x00ce, 0x00ee, 0x0005, - 0x00e6, 0x00c6, 0x0046, 0x0036, 0x0026, 0x0016, 0x00b6, 0x6210, - 0x2258, 0xbaa0, 0x0026, 0x2019, 0x0029, 0x080c, 0x96a4, 0x0076, - 0x2039, 0x0000, 0x080c, 0x9577, 0x2c08, 0x080c, 0xe91c, 0x007e, - 0x001e, 0xba10, 0xbb14, 0xbcc0, 0x080c, 0x6148, 0xba12, 0xbb16, - 0xbcc2, 0x00be, 0x001e, 0x002e, 0x003e, 0x004e, 0x00ce, 0x00ee, - 0x0005, 0x00e6, 0x0006, 0x00b6, 0x6010, 0x2058, 0xb8a0, 0x00be, - 0x9086, 0x0080, 0x0150, 0x2071, 0x1800, 0x70a8, 0x9005, 0x0110, - 0x8001, 0x70aa, 0x000e, 0x00ee, 0x0005, 0x2071, 0x1800, 0x70e4, - 0x9005, 0x0dc0, 0x8001, 0x70e6, 0x0ca8, 0xb800, 0xc08c, 0xb802, - 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x00b6, 0x0046, 0x0036, 0x0026, - 0x0016, 0x0156, 0x2178, 0x81ff, 0x1118, 0x20a9, 0x0001, 0x0078, - 0x080c, 0x57d5, 0xd0c4, 0x0140, 0xd0a4, 0x0130, 0x9006, 0x2020, - 0x2009, 0x002d, 0x080c, 0xec31, 0x20a9, 0x0800, 0x9016, 0x0026, - 0x928e, 0x007e, 0x0904, 0x3300, 0x928e, 0x007f, 0x0904, 0x3300, - 0x928e, 0x0080, 0x05e8, 0x9288, 0x1000, 0x210c, 0x81ff, 0x05c0, - 0x8fff, 0x1148, 0x2001, 0x198e, 0x0006, 0x2003, 0x0001, 0x04f1, - 0x000e, 0x2003, 0x0000, 0x00b6, 0x00c6, 0x2158, 0x2001, 0x0001, - 0x080c, 0x6a6d, 0x00ce, 0x00be, 0x2019, 0x0029, 0x080c, 0x96a4, - 0x0076, 0x2039, 0x0000, 0x080c, 0x9577, 0x00b6, 0x00c6, 0x0026, - 0x2158, 0xba04, 0x9294, 0x00ff, 0x9286, 0x0006, 0x1118, 0xb807, - 0x0404, 0x0028, 0x2001, 0x0004, 0x8007, 0x9215, 0xba06, 0x002e, - 0x00ce, 0x00be, 0x0016, 0x2c08, 0x080c, 0xe91c, 0x001e, 0x007e, - 0x002e, 0x8210, 0x1f04, 0x32b7, 0x015e, 0x001e, 0x002e, 0x003e, - 0x004e, 0x00be, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x0046, 0x0026, - 0x0016, 0x080c, 0x57d5, 0xd0c4, 0x0140, 0xd0a4, 0x0130, 0x9006, - 0x2220, 0x2009, 0x0029, 0x080c, 0xec31, 0x001e, 0x002e, 0x004e, - 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6, 0x7294, 0x82ff, 0x01e8, - 0x080c, 0x6a9b, 0x11d0, 0x2100, 0x080c, 0x28a6, 0x81ff, 0x01b8, - 0x2019, 0x0001, 0x8314, 0x92e0, 0x1c80, 0x2c04, 0xd384, 0x0120, - 0x9084, 0xff00, 0x8007, 0x0010, 0x9084, 0x00ff, 0x9116, 0x0138, - 0x9096, 0x00ff, 0x0110, 0x8318, 0x0c68, 0x9085, 0x0001, 0x00ce, - 0x003e, 0x002e, 0x001e, 0x0005, 0x0016, 0x00c6, 0x0126, 0x2091, - 0x8000, 0x0036, 0x2019, 0x0029, 0x00a9, 0x003e, 0x9180, 0x1000, - 0x2004, 0x9065, 0x0158, 0x0016, 0x00c6, 0x2061, 0x1ab7, 0x001e, - 0x6112, 0x080c, 0x3250, 0x001e, 0x080c, 0x66de, 0x012e, 0x00ce, - 0x001e, 0x0005, 0x0016, 0x0026, 0x2110, 0x080c, 0xac6c, 0x080c, - 0xef94, 0x002e, 0x001e, 0x0005, 0x2001, 0x1837, 0x2004, 0xd0cc, - 0x0005, 0x00c6, 0x00b6, 0x080c, 0x7637, 0x1118, 0x20a9, 0x0800, - 0x0010, 0x20a9, 0x0782, 0x080c, 0x7637, 0x1110, 0x900e, 0x0010, - 0x2009, 0x007e, 0x9180, 0x1000, 0x2004, 0x905d, 0x0130, 0x86ff, - 0x0110, 0xb800, 0xd0bc, 0x090c, 0x66de, 0x8108, 0x1f04, 0x338a, - 0x2061, 0x1800, 0x607f, 0x0000, 0x6080, 0x9084, 0x00ff, 0x6082, - 0x60b3, 0x0000, 0x00be, 0x00ce, 0x0005, 0x2001, 0x1869, 0x2004, - 0xd0bc, 0x0005, 0x2011, 0x1848, 0x2214, 0xd2ec, 0x0005, 0x0026, - 0x2011, 0x1867, 0x2214, 0xd2dc, 0x002e, 0x0005, 0x7eef, 0x7de8, - 0x7ce4, 0x80e2, 0x7be1, 0x80e0, 0x80dc, 0x80da, 0x7ad9, 0x80d6, - 0x80d5, 0x80d4, 0x80d3, 0x80d2, 0x80d1, 0x79ce, 0x78cd, 0x80cc, - 0x80cb, 0x80ca, 0x80c9, 0x80c7, 0x80c6, 0x77c5, 0x76c3, 0x80bc, - 0x80ba, 0x75b9, 0x80b6, 0x74b5, 0x73b4, 0x72b3, 0x80b2, 0x80b1, - 0x80ae, 0x71ad, 0x80ac, 0x70ab, 0x6faa, 0x6ea9, 0x80a7, 0x6da6, - 0x6ca5, 0x6ba3, 0x6a9f, 0x699e, 0x689d, 0x809b, 0x8098, 0x6797, - 0x6690, 0x658f, 0x6488, 0x6384, 0x6282, 0x8081, 0x8080, 0x617c, - 0x607a, 0x8079, 0x5f76, 0x8075, 0x8074, 0x8073, 0x8072, 0x8071, - 0x806e, 0x5e6d, 0x806c, 0x5d6b, 0x5c6a, 0x5b69, 0x8067, 0x5a66, - 0x5965, 0x5863, 0x575c, 0x565a, 0x5559, 0x8056, 0x8055, 0x5454, - 0x5353, 0x5252, 0x5151, 0x504e, 0x4f4d, 0x804c, 0x804b, 0x4e4a, - 0x4d49, 0x8047, 0x4c46, 0x8045, 0x8043, 0x803c, 0x803a, 0x8039, - 0x8036, 0x4b35, 0x8034, 0x4a33, 0x4932, 0x4831, 0x802e, 0x472d, - 0x462c, 0x452b, 0x442a, 0x4329, 0x4227, 0x8026, 0x8025, 0x4123, - 0x401f, 0x3f1e, 0x3e1d, 0x3d1b, 0x3c18, 0x8017, 0x8010, 0x3b0f, - 0x3a08, 0x8004, 0x3902, 0x8001, 0x8000, 0x8000, 0x3800, 0x3700, - 0x3600, 0x8000, 0x3500, 0x8000, 0x8000, 0x8000, 0x3400, 0x8000, - 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3300, 0x3200, 0x8000, - 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3100, 0x3000, 0x8000, - 0x8000, 0x2f00, 0x8000, 0x2e00, 0x2d00, 0x2c00, 0x8000, 0x8000, - 0x8000, 0x2b00, 0x8000, 0x2a00, 0x2900, 0x2800, 0x8000, 0x2700, - 0x2600, 0x2500, 0x2400, 0x2300, 0x2200, 0x8000, 0x8000, 0x2100, - 0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00, 0x8000, 0x8000, 0x1b00, - 0x1a00, 0x8000, 0x1900, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, - 0x8000, 0x1800, 0x8000, 0x1700, 0x1600, 0x1500, 0x8000, 0x1400, - 0x1300, 0x1200, 0x1100, 0x1000, 0x0f00, 0x8000, 0x8000, 0x0e00, - 0x0d00, 0x0c00, 0x0b00, 0x0a00, 0x0900, 0x8000, 0x8000, 0x0800, - 0x0700, 0x8000, 0x0600, 0x8000, 0x8000, 0x8000, 0x0500, 0x0400, - 0x0300, 0x8000, 0x0200, 0x8000, 0x8000, 0x8000, 0x0100, 0x8000, - 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x0000, 0x8000, 0x8000, - 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, - 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x2071, 0x189e, - 0x7003, 0x0002, 0x9006, 0x7016, 0x701a, 0x704a, 0x704e, 0x700e, - 0x7042, 0x7046, 0x703b, 0x18ba, 0x703f, 0x18ba, 0x7007, 0x0001, - 0x080c, 0x1027, 0x090c, 0x0dc5, 0x2900, 0x706a, 0xa867, 0x0002, - 0xa8ab, 0xdcb0, 0x080c, 0x1027, 0x090c, 0x0dc5, 0x2900, 0x706e, - 0xa867, 0x0002, 0xa8ab, 0xdcb0, 0x0005, 0x2071, 0x189e, 0x7004, - 0x0002, 0x34e5, 0x34e6, 0x34f9, 0x350d, 0x0005, 0x1004, 0x34f6, - 0x0e04, 0x34f6, 0x2079, 0x0000, 0x0126, 0x2091, 0x8000, 0x700c, - 0x9005, 0x1128, 0x700f, 0x0001, 0x012e, 0x0468, 0x0005, 0x012e, - 0x0ce8, 0x2079, 0x0000, 0x2061, 0x18b8, 0x2c4c, 0xa86c, 0x908e, - 0x0100, 0x0128, 0x9086, 0x0200, 0x0904, 0x35e1, 0x0005, 0x7018, - 0x2048, 0x2061, 0x1800, 0x701c, 0x0807, 0x7014, 0x2048, 0xa864, - 0x9094, 0x00ff, 0x9296, 0x0029, 0x1120, 0xaa78, 0xd2fc, 0x0128, - 0x0005, 0x9086, 0x0103, 0x0108, 0x0005, 0x2079, 0x0000, 0x2061, - 0x1800, 0x701c, 0x0807, 0x2061, 0x1800, 0x7880, 0x908a, 0x0040, - 0x1210, 0x61d0, 0x0042, 0x2100, 0x908a, 0x003f, 0x1a04, 0x35de, - 0x61d0, 0x0804, 0x3573, 0x35b5, 0x35ed, 0x35de, 0x35f9, 0x3603, - 0x3609, 0x360d, 0x361d, 0x3621, 0x3637, 0x363d, 0x3643, 0x364e, - 0x3659, 0x3668, 0x3677, 0x3685, 0x369c, 0x36b7, 0x35de, 0x3762, - 0x37a0, 0x3846, 0x3857, 0x387a, 0x35de, 0x35de, 0x35de, 0x38b2, - 0x38ce, 0x38d7, 0x3906, 0x390c, 0x35de, 0x3952, 0x35de, 0x35de, - 0x35de, 0x35de, 0x35de, 0x395d, 0x3966, 0x396e, 0x3970, 0x35de, - 0x35de, 0x35de, 0x35de, 0x35de, 0x35de, 0x399c, 0x35de, 0x35de, - 0x35de, 0x35de, 0x35de, 0x39b9, 0x3a40, 0x35de, 0x35de, 0x35de, - 0x35de, 0x35de, 0x35de, 0x0002, 0x3a6a, 0x3a6d, 0x3acc, 0x3ae5, - 0x3b15, 0x3db7, 0x35de, 0x5398, 0x35de, 0x35de, 0x35de, 0x35de, - 0x35de, 0x35de, 0x35de, 0x35de, 0x3637, 0x363d, 0x42ec, 0x57f9, - 0x430a, 0x5427, 0x5479, 0x5584, 0x35de, 0x55e6, 0x5622, 0x5653, - 0x575b, 0x5680, 0x56db, 0x35de, 0x430e, 0x44e1, 0x44f7, 0x451c, - 0x4581, 0x45f5, 0x4615, 0x468c, 0x46e8, 0x4744, 0x4747, 0x476c, - 0x4823, 0x4889, 0x4891, 0x49c6, 0x4b6e, 0x4ba2, 0x4e06, 0x35de, - 0x4e24, 0x4eeb, 0x4fd4, 0x502e, 0x35de, 0x50c1, 0x35de, 0x50d7, - 0x50f2, 0x4891, 0x5338, 0x714c, 0x0000, 0x2021, 0x4000, 0x080c, - 0x4c20, 0x0126, 0x2091, 0x8000, 0x0e04, 0x35bf, 0x0010, 0x012e, - 0x0cc0, 0x7c36, 0x9486, 0x4000, 0x0118, 0x7833, 0x0011, 0x0010, - 0x7833, 0x0010, 0x7c82, 0x7986, 0x7a8a, 0x7b8e, 0x2091, 0x4080, - 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11aa, 0x7007, 0x0001, - 0x2091, 0x5000, 0x700f, 0x0000, 0x012e, 0x0005, 0x2021, 0x4001, - 0x08b0, 0x2021, 0x4002, 0x0898, 0x2021, 0x4003, 0x0880, 0x2021, - 0x4005, 0x0868, 0x2021, 0x4006, 0x0850, 0x2039, 0x0001, 0x902e, - 0x2520, 0x7b88, 0x7a8c, 0x7884, 0x7990, 0x81ff, 0x0d98, 0x0804, - 0x4c2d, 0x2039, 0x0001, 0x902e, 0x2520, 0x7b88, 0x7a8c, 0x7884, - 0x7990, 0x0804, 0x4c30, 0x7984, 0x7888, 0x2114, 0x200a, 0x0804, - 0x35b5, 0x7984, 0x2114, 0x0804, 0x35b5, 0x20e1, 0x0000, 0x2099, - 0x0021, 0x20e9, 0x0000, 0x20a1, 0x0021, 0x20a9, 0x001f, 0x4003, - 0x7984, 0x7a88, 0x7b8c, 0x0804, 0x35b5, 0x7884, 0x2060, 0x0804, - 0x366a, 0x2009, 0x0003, 0x2011, 0x0003, 0x2019, 0x0014, 0x789b, - 0x0137, 0x7893, 0xffff, 0x2001, 0x188f, 0x2004, 0x9005, 0x0118, - 0x7896, 0x0804, 0x35b5, 0x7897, 0x0001, 0x0804, 0x35b5, 0x2039, - 0x0001, 0x7d98, 0x7c9c, 0x0804, 0x35f1, 0x2039, 0x0001, 0x7d98, - 0x7c9c, 0x0804, 0x35fd, 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804, - 0x35ea, 0x2138, 0x7d98, 0x7c9c, 0x0804, 0x35f1, 0x79a0, 0x9182, - 0x0040, 0x0210, 0x0804, 0x35ea, 0x2138, 0x7d98, 0x7c9c, 0x0804, - 0x35fd, 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804, 0x35ea, 0x21e8, - 0x7984, 0x7888, 0x20a9, 0x0001, 0x21a0, 0x4004, 0x0804, 0x35b5, - 0x2061, 0x0800, 0xe10c, 0x9006, 0x2c15, 0x9200, 0x8c60, 0x8109, - 0x1dd8, 0x2010, 0x9005, 0x0904, 0x35b5, 0x0804, 0x35e4, 0x79a0, - 0x9182, 0x0040, 0x0210, 0x0804, 0x35ea, 0x21e0, 0x20a9, 0x0001, - 0x7984, 0x2198, 0x4012, 0x0804, 0x35b5, 0x2069, 0x1847, 0x7884, - 0x7990, 0x911a, 0x1a04, 0x35ea, 0x8019, 0x0904, 0x35ea, 0x684a, - 0x6942, 0x788c, 0x6852, 0x7888, 0x6856, 0x9006, 0x685a, 0x685e, - 0x080c, 0x7963, 0x0804, 0x35b5, 0x2069, 0x1847, 0x7884, 0x7994, - 0x911a, 0x1a04, 0x35ea, 0x8019, 0x0904, 0x35ea, 0x684e, 0x6946, - 0x788c, 0x6862, 0x7888, 0x6866, 0x9006, 0x686a, 0x686e, 0x0126, - 0x2091, 0x8000, 0x080c, 0x6bf8, 0x012e, 0x0804, 0x35b5, 0x902e, - 0x2520, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x35e7, 0x7984, - 0x7b88, 0x7a8c, 0x20a9, 0x0005, 0x20e9, 0x0001, 0x20a1, 0x18a6, - 0x4101, 0x080c, 0x4be4, 0x1120, 0x2009, 0x0002, 0x0804, 0x35e7, - 0x2009, 0x0020, 0xa85c, 0x9080, 0x0019, 0xaf60, 0x080c, 0x4c2d, - 0x701f, 0x36db, 0x0005, 0xa864, 0x2008, 0x9084, 0x00ff, 0x9096, - 0x0011, 0x0168, 0x9096, 0x0019, 0x0150, 0x9096, 0x0015, 0x0138, - 0x9096, 0x0048, 0x0120, 0x9096, 0x0029, 0x1904, 0x35e7, 0x810f, - 0x918c, 0x00ff, 0x0904, 0x35e7, 0x7112, 0x7010, 0x8001, 0x0560, - 0x7012, 0x080c, 0x4be4, 0x1120, 0x2009, 0x0002, 0x0804, 0x35e7, - 0x2009, 0x0020, 0x7068, 0x2040, 0xa28c, 0xa390, 0xa494, 0xa598, - 0x9290, 0x0040, 0x9399, 0x0000, 0x94a1, 0x0000, 0x95a9, 0x0000, - 0xa85c, 0x9080, 0x0019, 0xaf60, 0x080c, 0x4c2d, 0x701f, 0x3719, - 0x0005, 0xa864, 0x9084, 0x00ff, 0x9096, 0x0002, 0x0120, 0x9096, - 0x000a, 0x1904, 0x35e7, 0x0888, 0x0126, 0x2091, 0x8000, 0x7014, - 0x2048, 0xa868, 0xc0fd, 0xa86a, 0xa864, 0x9084, 0x00ff, 0x9096, - 0x0029, 0x1148, 0xc2fd, 0xaa7a, 0x080c, 0x629f, 0x0138, 0xa87a, - 0xa982, 0x012e, 0x0060, 0x080c, 0x65cf, 0x1130, 0x7007, 0x0003, - 0x701f, 0x3747, 0x012e, 0x0005, 0x080c, 0x710b, 0x012e, 0x0126, - 0x2091, 0x8000, 0x20a9, 0x0005, 0x20e1, 0x0001, 0x2099, 0x18a6, - 0x400a, 0x2100, 0x9210, 0x9399, 0x0000, 0x94a1, 0x0000, 0x95a9, - 0x0000, 0xa85c, 0x9080, 0x0019, 0x2009, 0x0020, 0x012e, 0xaf60, - 0x0804, 0x4c30, 0x2091, 0x8000, 0x7837, 0x4000, 0x7833, 0x0010, - 0x7883, 0x4000, 0x7887, 0x4953, 0x788b, 0x5020, 0x788f, 0x2020, - 0x2009, 0x017f, 0x2104, 0x7892, 0x3f00, 0x7896, 0x2061, 0x0100, - 0x6200, 0x2061, 0x0200, 0x603c, 0x8007, 0x9205, 0x789a, 0x2009, - 0x04fd, 0x2104, 0x789e, 0x2091, 0x5000, 0x2091, 0x4080, 0x2001, - 0x0089, 0x2004, 0xd084, 0x0180, 0x2001, 0x1a1c, 0x2004, 0x9005, - 0x0128, 0x2001, 0x008b, 0x2004, 0xd0fc, 0x0dd8, 0x2001, 0x008a, - 0x2003, 0x0002, 0x2003, 0x1001, 0x2071, 0x0080, 0x0804, 0x0427, - 0x81ff, 0x1904, 0x35e7, 0x7984, 0x080c, 0x6724, 0x1904, 0x35ea, - 0x7e98, 0x9684, 0x3fff, 0x9082, 0x4000, 0x1a04, 0x35ea, 0x7c88, - 0x7d8c, 0x080c, 0x6887, 0x080c, 0x6856, 0x0000, 0x1518, 0x2061, - 0x1cd0, 0x0126, 0x2091, 0x8000, 0x6000, 0x9086, 0x0000, 0x0148, - 0x6014, 0x904d, 0x0130, 0xa86c, 0x9406, 0x1118, 0xa870, 0x9506, - 0x0150, 0x012e, 0x9ce0, 0x0018, 0x2001, 0x181a, 0x2004, 0x9c02, - 0x1a04, 0x35e7, 0x0c30, 0x080c, 0xccf3, 0x012e, 0x0904, 0x35e7, - 0x0804, 0x35b5, 0x900e, 0x2001, 0x0005, 0x080c, 0x710b, 0x0126, - 0x2091, 0x8000, 0x080c, 0xd3d4, 0x080c, 0x6e9f, 0x012e, 0x0804, - 0x35b5, 0x00a6, 0x2950, 0xb198, 0x080c, 0x6724, 0x1904, 0x3833, - 0xb6a4, 0x9684, 0x3fff, 0x9082, 0x4000, 0x16e8, 0xb49c, 0xb5a0, - 0x080c, 0x6887, 0x080c, 0x6856, 0x1520, 0x2061, 0x1cd0, 0x0126, - 0x2091, 0x8000, 0x6000, 0x9086, 0x0000, 0x0148, 0x6014, 0x904d, - 0x0130, 0xa86c, 0x9406, 0x1118, 0xa870, 0x9506, 0x0158, 0x012e, - 0x9ce0, 0x0018, 0x2001, 0x181a, 0x2004, 0x9c02, 0x2009, 0x000d, - 0x12b0, 0x0c28, 0x080c, 0xccf3, 0x012e, 0x2009, 0x0003, 0x0178, - 0x00e0, 0x900e, 0x2001, 0x0005, 0x080c, 0x710b, 0x0126, 0x2091, - 0x8000, 0x080c, 0xd3d4, 0x080c, 0x6e92, 0x012e, 0x0070, 0xb097, - 0x4005, 0xb19a, 0x0010, 0xb097, 0x4006, 0x900e, 0x9085, 0x0001, - 0x2001, 0x0030, 0x2a48, 0x00ae, 0x0005, 0xb097, 0x4000, 0x9006, - 0x918d, 0x0001, 0x2008, 0x2a48, 0x00ae, 0x0005, 0x81ff, 0x1904, - 0x35e7, 0x080c, 0x4bfb, 0x0904, 0x35ea, 0x080c, 0x67eb, 0x0904, - 0x35e7, 0x080c, 0x688d, 0x0904, 0x35e7, 0x0804, 0x460c, 0x81ff, - 0x1904, 0x35e7, 0x080c, 0x4c17, 0x0904, 0x35ea, 0x080c, 0x691b, - 0x0904, 0x35e7, 0x2019, 0x0005, 0x79a8, 0x080c, 0x68a8, 0x0904, - 0x35e7, 0x7888, 0x908a, 0x1000, 0x1a04, 0x35ea, 0x8003, 0x800b, - 0x810b, 0x9108, 0x080c, 0x884b, 0x79a8, 0xd184, 0x1904, 0x35b5, - 0x0804, 0x460c, 0x0126, 0x2091, 0x8000, 0x81ff, 0x0118, 0x2009, - 0x0001, 0x0450, 0x2029, 0x07ff, 0x645c, 0x2400, 0x9506, 0x01f8, - 0x2508, 0x080c, 0x6724, 0x11d8, 0x080c, 0x691b, 0x1128, 0x2009, - 0x0002, 0x62c0, 0x2518, 0x00c0, 0x2019, 0x0004, 0x900e, 0x080c, - 0x68a8, 0x1118, 0x2009, 0x0006, 0x0078, 0x7884, 0x908a, 0x1000, - 0x1270, 0x8003, 0x800b, 0x810b, 0x9108, 0x080c, 0x884b, 0x8529, - 0x1ae0, 0x012e, 0x0804, 0x35b5, 0x012e, 0x0804, 0x35e7, 0x012e, - 0x0804, 0x35ea, 0x080c, 0x4bfb, 0x0904, 0x35ea, 0x080c, 0x67eb, - 0x0904, 0x35e7, 0xbaa0, 0x2019, 0x0005, 0x00c6, 0x9066, 0x080c, - 0x96a4, 0x0076, 0x903e, 0x080c, 0x9577, 0x900e, 0x080c, 0xe91c, - 0x007e, 0x00ce, 0x080c, 0x6887, 0x0804, 0x35b5, 0x080c, 0x4bfb, - 0x0904, 0x35ea, 0x080c, 0x6887, 0x2208, 0x0804, 0x35b5, 0x0156, - 0x00d6, 0x00e6, 0x2069, 0x1910, 0x6810, 0x6914, 0x910a, 0x1208, - 0x900e, 0x6816, 0x9016, 0x901e, 0x20a9, 0x007e, 0x2069, 0x1000, - 0x2d04, 0x905d, 0x0118, 0xb84c, 0x0059, 0x9210, 0x8d68, 0x1f04, - 0x38e8, 0x2300, 0x9218, 0x00ee, 0x00de, 0x015e, 0x0804, 0x35b5, - 0x00f6, 0x0016, 0x907d, 0x0138, 0x9006, 0x8000, 0x2f0c, 0x81ff, - 0x0110, 0x2178, 0x0cd0, 0x001e, 0x00fe, 0x0005, 0x2069, 0x1910, - 0x6910, 0x62bc, 0x0804, 0x35b5, 0x81ff, 0x0120, 0x2009, 0x0001, - 0x0804, 0x35e7, 0x0126, 0x2091, 0x8000, 0x080c, 0x57e9, 0x0128, - 0x2009, 0x0007, 0x012e, 0x0804, 0x35e7, 0x012e, 0x615c, 0x9190, - 0x33b6, 0x2215, 0x9294, 0x00ff, 0x637c, 0x83ff, 0x0108, 0x6280, - 0x67dc, 0x97c4, 0x000a, 0x98c6, 0x000a, 0x1118, 0x2031, 0x0001, - 0x00e8, 0x97c4, 0x0022, 0x98c6, 0x0022, 0x1118, 0x2031, 0x0003, - 0x00a8, 0x97c4, 0x0012, 0x98c6, 0x0012, 0x1118, 0x2031, 0x0002, - 0x0068, 0x080c, 0x7637, 0x1118, 0x2031, 0x0004, 0x0038, 0xd79c, - 0x0120, 0x2009, 0x0005, 0x0804, 0x35e7, 0x9036, 0x7e9a, 0x7f9e, - 0x0804, 0x35b5, 0x614c, 0x6250, 0x2019, 0x1986, 0x231c, 0x2001, - 0x1987, 0x2004, 0x789a, 0x0804, 0x35b5, 0x0126, 0x2091, 0x8000, - 0x6138, 0x623c, 0x6340, 0x012e, 0x0804, 0x35b5, 0x080c, 0x4c17, - 0x0904, 0x35ea, 0xba44, 0xbb38, 0x0804, 0x35b5, 0x080c, 0x0dc5, - 0x080c, 0x4c17, 0x2110, 0x0904, 0x35ea, 0xb804, 0x908c, 0x00ff, - 0x918e, 0x0006, 0x0140, 0x9084, 0xff00, 0x9086, 0x0600, 0x2009, - 0x0009, 0x1904, 0x35e7, 0x0126, 0x2091, 0x8000, 0x2019, 0x0005, - 0x00c6, 0x9066, 0x080c, 0xac6c, 0x080c, 0x96a4, 0x0076, 0x903e, - 0x080c, 0x9577, 0x900e, 0x080c, 0xe91c, 0x007e, 0x00ce, 0xb807, - 0x0407, 0x012e, 0x0804, 0x35b5, 0x614c, 0x6250, 0x7884, 0x604e, - 0x7b88, 0x6352, 0x2069, 0x1847, 0x831f, 0x9305, 0x6816, 0x788c, - 0x2069, 0x1986, 0x2d1c, 0x206a, 0x7e98, 0x9682, 0x0014, 0x1210, - 0x2031, 0x07d0, 0x2069, 0x1987, 0x2d04, 0x266a, 0x789a, 0x0804, - 0x35b5, 0x0126, 0x2091, 0x8000, 0x6138, 0x7884, 0x603a, 0x910e, - 0xd1b4, 0x190c, 0x0ebe, 0xd094, 0x0148, 0x00e6, 0x2071, 0x19fb, - 0x79b4, 0x9192, 0x07d0, 0x1208, 0x713e, 0x00ee, 0xd0c4, 0x01a8, - 0x00d6, 0x78a8, 0x2009, 0x199d, 0x200a, 0x78ac, 0x2011, 0x199e, - 0x2012, 0x2069, 0x0100, 0x6838, 0x9086, 0x0007, 0x1118, 0x2214, - 0x6a5a, 0x0010, 0x210c, 0x695a, 0x00de, 0x7888, 0xd0ec, 0x0178, - 0x6034, 0xc08d, 0x6036, 0x2001, 0x0050, 0x6076, 0x607a, 0x6056, - 0x606b, 0x2450, 0x00c6, 0x2061, 0x1ad1, 0x2062, 0x00ce, 0x2011, - 0x0114, 0x220c, 0x7888, 0xd08c, 0x0118, 0x918d, 0x0080, 0x0010, - 0x918c, 0xff7f, 0x2112, 0x603c, 0x7988, 0x613e, 0x6140, 0x910d, - 0x788c, 0x6042, 0x7a88, 0x9294, 0x1000, 0x9205, 0x910e, 0xd1e4, - 0x190c, 0x0ed4, 0x9084, 0x0020, 0x0130, 0x78b4, 0x6046, 0x9084, - 0x0001, 0x090c, 0x42ec, 0x6040, 0xd0cc, 0x0120, 0x78b0, 0x2011, - 0x0114, 0x2012, 0x012e, 0x0804, 0x35b5, 0x00f6, 0x2079, 0x1800, - 0x7a38, 0xa898, 0x9084, 0xfebf, 0x9215, 0xa89c, 0x9084, 0xfebf, - 0x8002, 0x9214, 0x7838, 0x9084, 0x0140, 0x9215, 0x7a3a, 0xa897, - 0x4000, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x00fe, 0x0005, - 0x7898, 0x9005, 0x01a8, 0x7888, 0x9025, 0x0904, 0x35ea, 0x788c, - 0x902d, 0x0904, 0x35ea, 0x900e, 0x080c, 0x6724, 0x1120, 0xba44, - 0xbb38, 0xbc46, 0xbd3a, 0x9186, 0x07ff, 0x0190, 0x8108, 0x0ca0, - 0x080c, 0x4c17, 0x0904, 0x35ea, 0x7888, 0x900d, 0x0904, 0x35ea, - 0x788c, 0x9005, 0x0904, 0x35ea, 0xba44, 0xb946, 0xbb38, 0xb83a, - 0x0804, 0x35b5, 0x2011, 0xbc09, 0x0010, 0x2011, 0xbc05, 0x080c, - 0x57e9, 0x1904, 0x35e7, 0x00c6, 0x2061, 0x0100, 0x7984, 0x9186, - 0x00ff, 0x1130, 0x2001, 0x1818, 0x2004, 0x9085, 0xff00, 0x0088, - 0x9182, 0x007f, 0x16e0, 0x9188, 0x33b6, 0x210d, 0x918c, 0x00ff, - 0x2001, 0x1818, 0x2004, 0x0026, 0x9116, 0x002e, 0x0580, 0x810f, - 0x9105, 0x0126, 0x2091, 0x8000, 0x0006, 0x080c, 0xb27d, 0x000e, - 0x0510, 0x602e, 0x620a, 0x7984, 0x00b6, 0x080c, 0x66bf, 0x2b08, - 0x00be, 0x1500, 0x6112, 0x6023, 0x0001, 0x080c, 0x4be4, 0x01d0, - 0x9006, 0xa866, 0x7007, 0x0003, 0xa832, 0xa868, 0xc0fd, 0xa86a, - 0x701f, 0x3ac5, 0x2900, 0x6016, 0x2009, 0x0032, 0x080c, 0xb352, - 0x012e, 0x00ce, 0x0005, 0x012e, 0x00ce, 0x0804, 0x35e7, 0x00ce, - 0x0804, 0x35ea, 0x080c, 0xb2d3, 0x0cb0, 0xa830, 0x9086, 0x0100, - 0x0904, 0x35e7, 0x0804, 0x35b5, 0x2061, 0x1a74, 0x0126, 0x2091, - 0x8000, 0x6000, 0xd084, 0x0170, 0x6104, 0x6208, 0x2061, 0x1800, - 0x6354, 0x6074, 0x789a, 0x60c0, 0x789e, 0x60bc, 0x78aa, 0x012e, - 0x0804, 0x35b5, 0x900e, 0x2110, 0x0c88, 0x81ff, 0x1904, 0x35e7, - 0x080c, 0x7637, 0x0904, 0x35e7, 0x0126, 0x2091, 0x8000, 0x6254, - 0x6074, 0x9202, 0x0248, 0x9085, 0x0001, 0x080c, 0x28dc, 0x080c, - 0x5a11, 0x012e, 0x0804, 0x35b5, 0x012e, 0x0804, 0x35ea, 0x0006, - 0x0016, 0x00c6, 0x00e6, 0x2001, 0x19aa, 0x2070, 0x2061, 0x1847, - 0x6008, 0x2072, 0x900e, 0x2011, 0x1400, 0x080c, 0x9375, 0x7206, - 0x00ee, 0x00ce, 0x001e, 0x000e, 0x0005, 0x0126, 0x2091, 0x8000, - 0x81ff, 0x0128, 0x012e, 0x2021, 0x400b, 0x0804, 0x35b7, 0x7884, - 0xd0fc, 0x0158, 0x2001, 0x002a, 0x2004, 0x9005, 0x0180, 0x9082, - 0x00e1, 0x0298, 0x012e, 0x0804, 0x35ea, 0x2001, 0x002a, 0x2004, - 0x9005, 0x0128, 0x2069, 0x1847, 0x6908, 0x9102, 0x1230, 0x012e, - 0x0804, 0x35ea, 0x012e, 0x0804, 0x35e7, 0x080c, 0xb23d, 0x0dd0, - 0x7884, 0xd0fc, 0x0904, 0x3b94, 0x00c6, 0x080c, 0x4be4, 0x00ce, - 0x0d88, 0xa867, 0x0000, 0x7884, 0xa80a, 0x7898, 0xa80e, 0x789c, - 0xa812, 0x2001, 0x002e, 0x2004, 0xa81a, 0x2001, 0x002f, 0x2004, - 0xa81e, 0x2001, 0x0030, 0x2004, 0xa822, 0x2001, 0x0031, 0x2004, - 0xa826, 0x2001, 0x0034, 0x2004, 0xa82a, 0x2001, 0x0035, 0x2004, - 0xa82e, 0x2001, 0x002a, 0x2004, 0x9080, 0x0003, 0x9084, 0x00fc, - 0x8004, 0xa816, 0x080c, 0x3d1a, 0x0928, 0x7014, 0x2048, 0xad2c, - 0xac28, 0xab1c, 0xaa18, 0xa930, 0xa808, 0xd0b4, 0x1120, 0x2029, - 0x0000, 0x2021, 0x0000, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, - 0x9084, 0xffc0, 0x9080, 0x001b, 0x080c, 0x4c2d, 0x701f, 0x3c57, - 0x7023, 0x0001, 0x012e, 0x0005, 0x0046, 0x0086, 0x0096, 0x00a6, - 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x080c, 0x3aff, 0x2001, - 0x19a0, 0x2003, 0x0000, 0x2021, 0x000a, 0x2061, 0x0100, 0x6104, - 0x0016, 0x60bb, 0x0000, 0x60bf, 0x32e1, 0x60bf, 0x0012, 0x080c, - 0x3d89, 0x080c, 0x3d48, 0x00f6, 0x00e6, 0x0086, 0x2940, 0x2071, - 0x1a69, 0x2079, 0x0090, 0x00d6, 0x2069, 0x0000, 0x6884, 0xd0b4, - 0x0140, 0x2001, 0x0035, 0x2004, 0x780e, 0x2001, 0x0034, 0x2004, - 0x780a, 0x00de, 0x2011, 0x0001, 0x080c, 0x4130, 0x008e, 0x00ee, - 0x00fe, 0x080c, 0x4052, 0x080c, 0x3f57, 0x05b8, 0x2001, 0x020b, - 0x2004, 0x9084, 0x0140, 0x1db8, 0x080c, 0x41a4, 0x00f6, 0x2079, - 0x0300, 0x78bc, 0x00fe, 0x908c, 0x0070, 0x1560, 0x2071, 0x0200, - 0x7037, 0x0000, 0x7050, 0x9084, 0xff00, 0x9086, 0x3200, 0x1510, - 0x7037, 0x0001, 0x7050, 0x9084, 0xff00, 0x9086, 0xe100, 0x11d0, - 0x7037, 0x0000, 0x7054, 0x7037, 0x0000, 0x715c, 0x9106, 0x1190, - 0x2001, 0x1820, 0x2004, 0x9106, 0x1168, 0x00c6, 0x2061, 0x0100, - 0x6024, 0x9084, 0x1e00, 0x00ce, 0x0138, 0x080c, 0x3f61, 0x080c, - 0x3d43, 0x0058, 0x080c, 0x3d43, 0x080c, 0x40c8, 0x080c, 0x4048, - 0x2001, 0x020b, 0x2004, 0xd0e4, 0x0dd8, 0x2001, 0x032a, 0x2003, - 0x0004, 0x2061, 0x0100, 0x6027, 0x0002, 0x001e, 0x6106, 0x2011, - 0x020d, 0x2013, 0x0020, 0x60bb, 0x0000, 0x60bf, 0x0108, 0x60bf, - 0x0012, 0x2001, 0x0004, 0x200c, 0x918c, 0xfffd, 0x2102, 0x080c, - 0x12fc, 0x2009, 0x0028, 0x080c, 0x2409, 0x2001, 0x0227, 0x200c, - 0x2102, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e, - 0x008e, 0x004e, 0x2001, 0x19a0, 0x2004, 0x9005, 0x1118, 0x012e, - 0x0804, 0x35b5, 0x012e, 0x2021, 0x400c, 0x0804, 0x35b7, 0x0016, - 0x0026, 0x0036, 0x0046, 0x0056, 0x0076, 0x0086, 0x0096, 0x00d6, - 0x0156, 0x7014, 0x2048, 0x7020, 0x20a8, 0x8000, 0x7022, 0xa804, - 0x9005, 0x0904, 0x3cb3, 0x2048, 0x1f04, 0x3c67, 0x7068, 0x2040, - 0xa28c, 0xa390, 0xa494, 0xa598, 0xa930, 0xa808, 0xd0b4, 0x1120, - 0x2029, 0x0000, 0x2021, 0x0000, 0x0096, 0x7014, 0x2048, 0xa864, - 0x009e, 0x9086, 0x0103, 0x0170, 0x8906, 0x8006, 0x8007, 0x90bc, - 0x003f, 0x9084, 0xffc0, 0x9080, 0x001b, 0x080c, 0x4c2d, 0x701f, - 0x3c57, 0x00b0, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, - 0xffc0, 0x9080, 0x001b, 0x21a8, 0x27e0, 0x2098, 0x27e8, 0x20a0, - 0x0006, 0x080c, 0x0f8b, 0x000e, 0x080c, 0x4c30, 0x701f, 0x3c57, - 0x015e, 0x00de, 0x009e, 0x008e, 0x007e, 0x005e, 0x004e, 0x003e, - 0x002e, 0x001e, 0x0005, 0x7014, 0x2048, 0xa864, 0x9086, 0x0103, - 0x1118, 0x701f, 0x3d18, 0x0450, 0x7014, 0x2048, 0xa868, 0xc0fd, - 0xa86a, 0x2009, 0x007f, 0x080c, 0x66b9, 0x0110, 0x9006, 0x0030, - 0xb813, 0x00ff, 0xb817, 0xfffd, 0x080c, 0xd5a7, 0x015e, 0x00de, - 0x009e, 0x008e, 0x007e, 0x005e, 0x004e, 0x003e, 0x002e, 0x001e, - 0x0904, 0x35e7, 0x0016, 0x0026, 0x0036, 0x0046, 0x0056, 0x0076, - 0x0086, 0x0096, 0x00d6, 0x0156, 0x701f, 0x3cea, 0x7007, 0x0003, - 0x0804, 0x3ca8, 0xa830, 0x9086, 0x0100, 0x2021, 0x400c, 0x0904, - 0x35b7, 0x0076, 0xad10, 0xac0c, 0xab24, 0xaa20, 0xa930, 0xa808, - 0xd0b4, 0x1120, 0x2029, 0x0000, 0x2021, 0x0000, 0x8906, 0x8006, - 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x001b, 0x21a8, - 0x27e0, 0x2098, 0x27e8, 0x20a0, 0x0006, 0x080c, 0x0f8b, 0x000e, - 0x080c, 0x4c30, 0x007e, 0x701f, 0x3c57, 0x7023, 0x0001, 0x0005, - 0x0804, 0x35b5, 0x0156, 0x00c6, 0xa814, 0x908a, 0x001e, 0x0218, - 0xa833, 0x001e, 0x0010, 0xa832, 0x0078, 0x81ff, 0x0168, 0x0016, - 0x080c, 0x4be4, 0x001e, 0x0130, 0xa800, 0x2040, 0xa008, 0xa80a, - 0x2100, 0x0c58, 0x9006, 0x0010, 0x9085, 0x0001, 0x00ce, 0x015e, - 0x0005, 0x0006, 0x00f6, 0x2079, 0x0000, 0x7880, 0x9086, 0x0044, - 0x00fe, 0x000e, 0x0005, 0x2001, 0x19a0, 0x2003, 0x0001, 0x0005, - 0x00f6, 0x00e6, 0x00c6, 0x2061, 0x0200, 0x2001, 0x19ab, 0x2004, - 0x601a, 0x2061, 0x0100, 0x2001, 0x19aa, 0x2004, 0x60ce, 0x6104, - 0xc1ac, 0x6106, 0x080c, 0x4be4, 0xa813, 0x0019, 0xa817, 0x0001, - 0x2900, 0xa85a, 0x2001, 0x002e, 0x2004, 0xa866, 0x2001, 0x002f, - 0x2004, 0xa86a, 0x2061, 0x0090, 0x2079, 0x0100, 0x2001, 0x19aa, - 0x2004, 0x6036, 0x2009, 0x0040, 0x080c, 0x2409, 0x2001, 0x002a, - 0x2004, 0x9084, 0xfff8, 0xa86e, 0x601a, 0xa873, 0x0000, 0x601f, - 0x0000, 0x78ca, 0x9006, 0x600a, 0x600e, 0x00ce, 0x00ee, 0x00fe, - 0x0005, 0x00e6, 0x080c, 0x4be4, 0x2940, 0xa013, 0x0019, 0xa017, - 0x0001, 0x2800, 0xa05a, 0x2001, 0x0030, 0x2004, 0xa866, 0x2001, - 0x0031, 0x2004, 0xa86a, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, - 0xa86e, 0xa873, 0x0000, 0x2001, 0x032a, 0x2003, 0x0004, 0x2001, - 0x0300, 0x2003, 0x0000, 0x2001, 0x020d, 0x2003, 0x0000, 0x2001, - 0x0004, 0x200c, 0x918d, 0x0002, 0x2102, 0x00ee, 0x0005, 0x0126, - 0x2091, 0x8000, 0x81ff, 0x0148, 0x080c, 0x2c59, 0x1130, 0x9006, - 0x080c, 0x2bb1, 0x9006, 0x080c, 0x2b94, 0x2001, 0x199f, 0x2003, - 0x0000, 0x7884, 0x9084, 0x0007, 0x0002, 0x3dd8, 0x3de1, 0x3dea, - 0x3dd5, 0x3dd5, 0x3dd5, 0x3dd5, 0x3dd5, 0x012e, 0x0804, 0x35ea, - 0x2009, 0x0114, 0x2104, 0x9085, 0x0800, 0x200a, 0x080c, 0x3fab, - 0x00c0, 0x2009, 0x0114, 0x2104, 0x9085, 0x4000, 0x200a, 0x080c, - 0x3fab, 0x0078, 0x080c, 0x7637, 0x1128, 0x012e, 0x2009, 0x0016, - 0x0804, 0x35e7, 0x81ff, 0x0128, 0x012e, 0x2021, 0x400b, 0x0804, - 0x35b7, 0x2001, 0x0141, 0x2004, 0xd0dc, 0x0db0, 0x0086, 0x0096, - 0x00a6, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x080c, 0x3aff, - 0x2009, 0x0101, 0x210c, 0x0016, 0x7ec8, 0x7dcc, 0x9006, 0x2068, - 0x2060, 0x2058, 0x080c, 0x427f, 0x080c, 0x41cf, 0x903e, 0x2720, - 0x00f6, 0x00e6, 0x0086, 0x2940, 0x2071, 0x1a69, 0x2079, 0x0090, - 0x00d6, 0x2069, 0x0000, 0x6884, 0xd0b4, 0x0120, 0x68d4, 0x780e, - 0x68d0, 0x780a, 0x00de, 0x2011, 0x0001, 0x080c, 0x4130, 0x080c, - 0x2c61, 0x080c, 0x2c61, 0x080c, 0x2c61, 0x080c, 0x2c61, 0x080c, - 0x4130, 0x008e, 0x00ee, 0x00fe, 0x080c, 0x4052, 0x2009, 0x9c40, - 0x8109, 0x11b0, 0x080c, 0x3f61, 0x2001, 0x0004, 0x200c, 0x918c, - 0xfffd, 0x2102, 0x001e, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, - 0x00ae, 0x009e, 0x008e, 0x2009, 0x0017, 0x080c, 0x35e7, 0x0cf8, - 0x2001, 0x020b, 0x2004, 0x9084, 0x0140, 0x1d10, 0x00f6, 0x2079, - 0x0000, 0x7884, 0x00fe, 0xd0bc, 0x0178, 0x2001, 0x0201, 0x200c, - 0x81ff, 0x0150, 0x080c, 0x4030, 0x2d00, 0x9c05, 0x9b05, 0x0120, - 0x080c, 0x3f61, 0x0804, 0x3f0e, 0x080c, 0x41a4, 0x080c, 0x40c8, - 0x080c, 0x4013, 0x080c, 0x4048, 0x00f6, 0x2079, 0x0100, 0x7824, - 0xd0ac, 0x0130, 0x8b58, 0x080c, 0x3f61, 0x00fe, 0x0804, 0x3f0e, - 0x00fe, 0x080c, 0x3f57, 0x1150, 0x8d68, 0x2001, 0x0032, 0x2602, - 0x2001, 0x0033, 0x2502, 0x080c, 0x3f61, 0x0080, 0x87ff, 0x0138, - 0x2001, 0x0201, 0x2004, 0x9005, 0x1908, 0x8739, 0x0038, 0x2001, - 0x1a65, 0x2004, 0x9086, 0x0000, 0x1904, 0x3e5e, 0x2001, 0x032f, - 0x2003, 0x00f6, 0x8631, 0x1208, 0x8529, 0x2500, 0x9605, 0x0904, - 0x3f0e, 0x7884, 0xd0bc, 0x0128, 0x2d00, 0x9c05, 0x9b05, 0x1904, - 0x3f0e, 0xa013, 0x0019, 0x2001, 0x032a, 0x2003, 0x0004, 0x7884, - 0xd0ac, 0x1148, 0x2001, 0x1a65, 0x2003, 0x0003, 0x2001, 0x032a, - 0x2003, 0x0009, 0x0030, 0xa017, 0x0001, 0x78b4, 0x9005, 0x0108, - 0xa016, 0x2800, 0xa05a, 0x2009, 0x0040, 0x080c, 0x2409, 0x2900, - 0xa85a, 0xa813, 0x0019, 0x7884, 0xd0a4, 0x1180, 0xa817, 0x0000, - 0x00c6, 0x20a9, 0x0004, 0x2061, 0x0090, 0x602b, 0x0008, 0x2001, - 0x0203, 0x2004, 0x1f04, 0x3ee5, 0x00ce, 0x0030, 0xa817, 0x0001, - 0x78b0, 0x9005, 0x0108, 0xa816, 0x00f6, 0x00c6, 0x2079, 0x0100, - 0x2061, 0x0090, 0x7827, 0x0002, 0x2001, 0x002a, 0x2004, 0x9084, - 0xfff8, 0x601a, 0x0006, 0x2001, 0x002b, 0x2004, 0x601e, 0x78c6, - 0x000e, 0x78ca, 0x00ce, 0x00fe, 0x0804, 0x3e18, 0x001e, 0x00c6, - 0x2001, 0x032a, 0x2003, 0x0004, 0x2061, 0x0100, 0x6027, 0x0002, - 0x6106, 0x2011, 0x020d, 0x2013, 0x0020, 0x2001, 0x0004, 0x200c, - 0x918c, 0xfffd, 0x2102, 0x080c, 0x12fc, 0x7884, 0x9084, 0x0003, - 0x9086, 0x0002, 0x01a0, 0x2009, 0x0028, 0x080c, 0x2409, 0x2001, - 0x0227, 0x200c, 0x2102, 0x6050, 0x9084, 0xb7ef, 0x6052, 0x602f, - 0x0000, 0x604b, 0xf7f7, 0x6043, 0x0090, 0x6043, 0x0010, 0x00ce, - 0x2d08, 0x2c10, 0x2b18, 0x2b00, 0x9c05, 0x9d05, 0x00fe, 0x00ee, - 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e, 0x008e, 0x1118, 0x012e, - 0x0804, 0x35b5, 0x012e, 0x2021, 0x400c, 0x0804, 0x35b7, 0x9085, - 0x0001, 0x1d04, 0x3f60, 0x2091, 0x6000, 0x8420, 0x9486, 0x0064, - 0x0005, 0x2001, 0x0105, 0x2003, 0x0010, 0x2001, 0x032a, 0x2003, - 0x0004, 0x2001, 0x1a65, 0x2003, 0x0000, 0x0071, 0x2009, 0x0048, - 0x080c, 0x2409, 0x2001, 0x0227, 0x2024, 0x2402, 0x2001, 0x0109, - 0x2003, 0x4000, 0x9026, 0x0005, 0x00f6, 0x00e6, 0x2071, 0x1a69, - 0x7000, 0x9086, 0x0000, 0x0520, 0x2079, 0x0090, 0x2009, 0x0206, - 0x2104, 0x2009, 0x0203, 0x210c, 0x9106, 0x1120, 0x2009, 0x0040, - 0x080c, 0x2409, 0x782c, 0xd0fc, 0x0d88, 0x080c, 0x41a4, 0x7000, - 0x9086, 0x0000, 0x1d58, 0x782b, 0x0004, 0x782c, 0xd0ac, 0x1de8, - 0x2009, 0x0040, 0x080c, 0x2409, 0x782b, 0x0002, 0x7003, 0x0000, - 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0100, 0x2001, 0x1818, - 0x200c, 0x7932, 0x7936, 0x080c, 0x28bc, 0x7850, 0x9084, 0xfbff, - 0x9085, 0x0030, 0x7852, 0x2019, 0x01f4, 0x8319, 0x1df0, 0x9084, - 0xffcf, 0x9085, 0x2000, 0x7852, 0x20a9, 0x0046, 0x1d04, 0x3fc6, - 0x2091, 0x6000, 0x1f04, 0x3fc6, 0x7850, 0x9085, 0x0400, 0x9084, - 0xdfff, 0x7852, 0x2001, 0x0021, 0x2004, 0x9084, 0x0003, 0x9086, - 0x0001, 0x1120, 0x7850, 0x9084, 0xdfff, 0x7852, 0x784b, 0xf7f7, - 0x7843, 0x0090, 0x7843, 0x0010, 0x20a9, 0x0028, 0xa001, 0x1f04, - 0x3fe6, 0x7850, 0x9085, 0x1400, 0x7852, 0x2019, 0x61a8, 0x7854, - 0xa001, 0xa001, 0xd08c, 0x1110, 0x8319, 0x1dc8, 0x7827, 0x0048, - 0x7850, 0x9085, 0x0400, 0x7852, 0x7843, 0x0040, 0x2019, 0x01f4, - 0xa001, 0xa001, 0x8319, 0x1de0, 0x2001, 0x0100, 0x080c, 0x2d39, - 0x7827, 0x0020, 0x7843, 0x0000, 0x9006, 0x080c, 0x2d39, 0x7827, - 0x0048, 0x00fe, 0x0005, 0x7884, 0xd0ac, 0x11c8, 0x00f6, 0x00e6, - 0x2071, 0x1a65, 0x2079, 0x0320, 0x2001, 0x0201, 0x2004, 0x9005, - 0x0160, 0x7000, 0x9086, 0x0000, 0x1140, 0x0051, 0xd0bc, 0x0108, - 0x8738, 0x7003, 0x0003, 0x782b, 0x0019, 0x00ee, 0x00fe, 0x0005, - 0x00f6, 0x2079, 0x0300, 0x78bc, 0x00fe, 0x908c, 0x0070, 0x0178, - 0x2009, 0x0032, 0x260a, 0x2009, 0x0033, 0x250a, 0xd0b4, 0x0108, - 0x8c60, 0xd0ac, 0x0108, 0x8d68, 0xd0a4, 0x0108, 0x8b58, 0x0005, - 0x00f6, 0x2079, 0x0200, 0x781c, 0xd084, 0x0110, 0x7837, 0x0050, - 0x00fe, 0x0005, 0x00e6, 0x2071, 0x0100, 0x2001, 0x19ab, 0x2004, - 0x70e2, 0x080c, 0x3d39, 0x1188, 0x2001, 0x1820, 0x2004, 0x2009, - 0x181f, 0x210c, 0x918c, 0x00ff, 0x706e, 0x716a, 0x7066, 0x918d, - 0x3200, 0x7162, 0x7073, 0xe109, 0x0080, 0x702c, 0x9085, 0x0002, - 0x702e, 0x2009, 0x1818, 0x210c, 0x716e, 0x7063, 0x0100, 0x7166, - 0x719e, 0x706b, 0x0000, 0x7073, 0x0809, 0x7077, 0x0008, 0x7078, - 0x9080, 0x0100, 0x707a, 0x7080, 0x8000, 0x7082, 0x7087, 0xaaaa, - 0x9006, 0x708a, 0x708e, 0x707e, 0x70d6, 0x70ab, 0x0036, 0x70af, - 0x95d5, 0x7014, 0x9084, 0x1984, 0x9085, 0x0092, 0x7016, 0x080c, - 0x41a4, 0x00f6, 0x2071, 0x1a65, 0x2079, 0x0320, 0x00d6, 0x2069, - 0x0000, 0x6884, 0xd0b4, 0x0120, 0x689c, 0x780e, 0x6898, 0x780a, - 0x00de, 0x080c, 0x3d39, 0x0140, 0x2001, 0x199f, 0x200c, 0x2003, - 0x0001, 0x918e, 0x0001, 0x0120, 0x2009, 0x03e8, 0x8109, 0x1df0, - 0x792c, 0xd1fc, 0x0110, 0x782b, 0x0004, 0x2011, 0x0011, 0x080c, - 0x4130, 0x2011, 0x0001, 0x080c, 0x4130, 0x00fe, 0x00ee, 0x0005, - 0x00f6, 0x00e6, 0x2071, 0x1a65, 0x2079, 0x0320, 0x792c, 0xd1fc, - 0x0904, 0x412d, 0x782b, 0x0002, 0x9026, 0xd19c, 0x1904, 0x4129, - 0x7000, 0x0002, 0x412d, 0x40de, 0x410e, 0x4129, 0xd1bc, 0x1170, - 0xd1dc, 0x1190, 0x8001, 0x7002, 0x2011, 0x0001, 0x080c, 0x4130, - 0x0904, 0x412d, 0x080c, 0x4130, 0x0804, 0x412d, 0x00f6, 0x2079, - 0x0300, 0x78bf, 0x0000, 0x00fe, 0x7810, 0x7914, 0x782b, 0x0004, - 0x7812, 0x7916, 0x2001, 0x0201, 0x200c, 0x81ff, 0x0de8, 0x080c, - 0x4030, 0x2009, 0x0001, 0x00f6, 0x2079, 0x0300, 0x78b8, 0x00fe, - 0xd0ec, 0x0110, 0x2009, 0x0011, 0x792a, 0x00f8, 0x8001, 0x7002, - 0x9184, 0x0880, 0x1140, 0x782c, 0xd0fc, 0x1904, 0x40d2, 0x2011, - 0x0001, 0x00b1, 0x0090, 0xa010, 0x9092, 0x0004, 0x9086, 0x0015, - 0x1120, 0xa000, 0xa05a, 0x2011, 0x0031, 0xa212, 0xd1dc, 0x1960, - 0x0828, 0x782b, 0x0004, 0x7003, 0x0000, 0x00ee, 0x00fe, 0x0005, - 0xa014, 0x9005, 0x0550, 0x8001, 0x0036, 0x0096, 0xa016, 0xa058, - 0x2048, 0xa010, 0x2009, 0x0031, 0x911a, 0x831c, 0x831c, 0x938a, - 0x0007, 0x1a0c, 0x0dc5, 0x9398, 0x415e, 0x231d, 0x083f, 0x9080, - 0x0004, 0x7a2a, 0x7100, 0x8108, 0x7102, 0x009e, 0x003e, 0x908a, - 0x0035, 0x1140, 0x0096, 0xa058, 0x2048, 0xa804, 0xa05a, 0x2001, - 0x0019, 0x009e, 0xa012, 0x9085, 0x0001, 0x0005, 0x419b, 0x4192, - 0x4189, 0x4180, 0x4177, 0x416e, 0x4165, 0xa964, 0x7902, 0xa968, - 0x7906, 0xa96c, 0x7912, 0xa970, 0x7916, 0x0005, 0xa974, 0x7902, - 0xa978, 0x7906, 0xa97c, 0x7912, 0xa980, 0x7916, 0x0005, 0xa984, - 0x7902, 0xa988, 0x7906, 0xa98c, 0x7912, 0xa990, 0x7916, 0x0005, - 0xa994, 0x7902, 0xa998, 0x7906, 0xa99c, 0x7912, 0xa9a0, 0x7916, - 0x0005, 0xa9a4, 0x7902, 0xa9a8, 0x7906, 0xa9ac, 0x7912, 0xa9b0, - 0x7916, 0x0005, 0xa9b4, 0x7902, 0xa9b8, 0x7906, 0xa9bc, 0x7912, - 0xa9c0, 0x7916, 0x0005, 0xa9c4, 0x7902, 0xa9c8, 0x7906, 0xa9cc, - 0x7912, 0xa9d0, 0x7916, 0x0005, 0x00f6, 0x00e6, 0x0086, 0x2071, - 0x1a69, 0x2079, 0x0090, 0x792c, 0xd1fc, 0x01e8, 0x782b, 0x0002, - 0x2940, 0x9026, 0x7000, 0x0002, 0x41cb, 0x41b7, 0x41c2, 0x8001, - 0x7002, 0xd19c, 0x1180, 0x2011, 0x0001, 0x080c, 0x4130, 0x190c, - 0x4130, 0x0048, 0x8001, 0x7002, 0x782c, 0xd0fc, 0x1d38, 0x2011, - 0x0001, 0x080c, 0x4130, 0x008e, 0x00ee, 0x00fe, 0x0005, 0x00f6, - 0x00e6, 0x00c6, 0x0086, 0x2061, 0x0200, 0x2001, 0x19ab, 0x2004, - 0x601a, 0x2061, 0x0100, 0x2001, 0x19aa, 0x2004, 0x60ce, 0x6104, - 0xc1ac, 0x6106, 0x2001, 0x002c, 0x2004, 0x9005, 0x0520, 0x2038, - 0x2001, 0x002e, 0x2024, 0x2001, 0x002f, 0x201c, 0x080c, 0x4be4, - 0xa813, 0x0019, 0xaf16, 0x2900, 0xa85a, 0x978a, 0x0007, 0x0220, - 0x2138, 0x2009, 0x0007, 0x0010, 0x2708, 0x903e, 0x0096, 0xa858, - 0x2048, 0xa85c, 0x9080, 0x0019, 0x009e, 0x080c, 0x4247, 0x1d68, - 0x2900, 0xa85a, 0x00d0, 0x080c, 0x4be4, 0xa813, 0x0019, 0xa817, - 0x0001, 0x2900, 0xa85a, 0x2001, 0x002e, 0x2004, 0xa866, 0x2001, - 0x002f, 0x2004, 0xa86a, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, - 0xa86e, 0x2001, 0x002b, 0x2004, 0xa872, 0x2061, 0x0090, 0x2079, - 0x0100, 0x2001, 0x19aa, 0x2004, 0x6036, 0x2009, 0x0040, 0x080c, - 0x2409, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, 0x601a, 0x0006, - 0x2001, 0x002b, 0x2004, 0x601e, 0x78c6, 0x000e, 0x78ca, 0x9006, - 0x600a, 0x600e, 0x008e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00e6, - 0x2071, 0x0080, 0xaa60, 0x22e8, 0x20a0, 0x20e1, 0x0000, 0x2099, - 0x0088, 0x702b, 0x0026, 0x7402, 0x7306, 0x9006, 0x700a, 0x700e, - 0x810b, 0x810b, 0x21a8, 0x810b, 0x7112, 0x702b, 0x0041, 0x702c, - 0xd0fc, 0x0de8, 0x702b, 0x0002, 0x702b, 0x0040, 0x4005, 0x7400, - 0x7304, 0x87ff, 0x0190, 0x0086, 0x0096, 0x2940, 0x0086, 0x080c, - 0x4be4, 0x008e, 0xa058, 0x00a6, 0x2050, 0x2900, 0xb006, 0xa05a, - 0x00ae, 0x009e, 0x008e, 0x9085, 0x0001, 0x00ee, 0x0005, 0x00e6, - 0x2001, 0x002d, 0x2004, 0x9005, 0x0528, 0x2038, 0x2001, 0x0030, - 0x2024, 0x2001, 0x0031, 0x201c, 0x080c, 0x4be4, 0x2940, 0xa813, - 0x0019, 0xaf16, 0x2900, 0xa85a, 0x978a, 0x0007, 0x0220, 0x2138, - 0x2009, 0x0007, 0x0010, 0x2708, 0x903e, 0x0096, 0xa858, 0x2048, - 0xa85c, 0x9080, 0x0019, 0x009e, 0x080c, 0x4247, 0x1d68, 0x2900, - 0xa85a, 0x00d8, 0x080c, 0x4be4, 0x2940, 0xa013, 0x0019, 0xa017, - 0x0001, 0x2800, 0xa05a, 0x2001, 0x0030, 0x2004, 0xa066, 0x2001, - 0x0031, 0x2004, 0xa06a, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, - 0xa06e, 0x2001, 0x002b, 0x2004, 0xa072, 0x2001, 0x032a, 0x2003, - 0x0004, 0x7884, 0xd0ac, 0x1180, 0x2001, 0x0101, 0x200c, 0x918d, - 0x0200, 0x2102, 0xa017, 0x0000, 0x2001, 0x1a65, 0x2003, 0x0003, - 0x2001, 0x032a, 0x2003, 0x0009, 0x2001, 0x0300, 0x2003, 0x0000, - 0x2001, 0x020d, 0x2003, 0x0000, 0x2001, 0x0004, 0x200c, 0x918d, - 0x0002, 0x2102, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x20a9, - 0x0007, 0x20a1, 0x1840, 0x20e9, 0x0001, 0x9006, 0x4004, 0x20a9, - 0x0014, 0x20a1, 0xffec, 0x20e9, 0x0000, 0x9006, 0x4004, 0x2009, - 0x013c, 0x200a, 0x012e, 0x7880, 0x9086, 0x0052, 0x0108, 0x0005, - 0x0804, 0x35b5, 0x7d98, 0x7c9c, 0x0804, 0x36b9, 0x080c, 0x7637, - 0x190c, 0x60f3, 0x6040, 0x9084, 0x0020, 0x09b1, 0x2069, 0x1847, - 0x2d00, 0x2009, 0x0030, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, - 0x0001, 0x080c, 0x4c2d, 0x701f, 0x4326, 0x0005, 0x080c, 0x57e4, - 0x1130, 0x3b00, 0x3a08, 0xc194, 0xc095, 0x20d8, 0x21d0, 0x2069, - 0x1847, 0x6800, 0x9005, 0x0904, 0x35ea, 0x2001, 0x180d, 0x2004, - 0xd08c, 0x6804, 0x0118, 0xc0a4, 0xc0ac, 0x6806, 0xd0ac, 0x0118, - 0xd0a4, 0x0904, 0x35ea, 0xd094, 0x00c6, 0x2061, 0x0100, 0x6104, - 0x0138, 0x6200, 0x9292, 0x0005, 0x0218, 0x918c, 0xffdf, 0x0010, - 0x918d, 0x0020, 0x6106, 0x00ce, 0xd08c, 0x00c6, 0x2061, 0x0100, - 0x6104, 0x0118, 0x918d, 0x0010, 0x0010, 0x918c, 0xffef, 0x6106, - 0x00ce, 0xd084, 0x0158, 0x6a28, 0x928a, 0x007f, 0x1a04, 0x35ea, - 0x9288, 0x33b6, 0x210d, 0x918c, 0x00ff, 0x6166, 0xd0dc, 0x0130, - 0x6828, 0x908a, 0x007f, 0x1a04, 0x35ea, 0x605e, 0x6888, 0x9084, - 0x0030, 0x8004, 0x8004, 0x8004, 0x8004, 0x0006, 0x2009, 0x19b2, - 0x9080, 0x29b7, 0x2005, 0x200a, 0x000e, 0x2009, 0x19b3, 0x9080, - 0x29bb, 0x2005, 0x200a, 0x6808, 0x908a, 0x0100, 0x0a04, 0x35ea, - 0x908a, 0x0841, 0x1a04, 0x35ea, 0x9084, 0x0007, 0x1904, 0x35ea, - 0x680c, 0x9005, 0x0904, 0x35ea, 0x6810, 0x9005, 0x0904, 0x35ea, - 0x6848, 0x6940, 0x910a, 0x1a04, 0x35ea, 0x8001, 0x0904, 0x35ea, - 0x684c, 0x6944, 0x910a, 0x1a04, 0x35ea, 0x8001, 0x0904, 0x35ea, - 0x2009, 0x1981, 0x200b, 0x0000, 0x2001, 0x1869, 0x2004, 0xd0c4, - 0x0140, 0x7884, 0x200a, 0x2008, 0x080c, 0x0e52, 0x3b00, 0xc085, - 0x20d8, 0x6814, 0x908c, 0x00ff, 0x614e, 0x8007, 0x9084, 0x00ff, - 0x6052, 0x080c, 0x7963, 0x080c, 0x6b8e, 0x080c, 0x6bf8, 0x6808, - 0x602a, 0x080c, 0x237b, 0x2009, 0x0170, 0x200b, 0x0080, 0xa001, - 0xa001, 0x200b, 0x0000, 0x0036, 0x6b08, 0x080c, 0x2916, 0x003e, - 0x6000, 0x9086, 0x0000, 0x1904, 0x44cf, 0x6818, 0x691c, 0x6a20, - 0x6b24, 0x8007, 0x810f, 0x8217, 0x831f, 0x6016, 0x611a, 0x621e, - 0x6322, 0x6c04, 0xd4f4, 0x0148, 0x6830, 0x6934, 0x6a38, 0x6b3c, - 0x8007, 0x810f, 0x8217, 0x831f, 0x0010, 0x9084, 0xf0ff, 0x6006, - 0x610a, 0x620e, 0x6312, 0x8007, 0x810f, 0x8217, 0x831f, 0x20a9, - 0x0004, 0x20a1, 0x19b4, 0x20e9, 0x0001, 0x4001, 0x20a9, 0x0004, - 0x20a1, 0x19ce, 0x20e9, 0x0001, 0x4001, 0x080c, 0x8962, 0x00c6, - 0x900e, 0x20a9, 0x0001, 0x6b70, 0xd384, 0x0510, 0x0068, 0x2009, - 0x0100, 0x210c, 0x918e, 0x0008, 0x1110, 0x839d, 0x0010, 0x83f5, - 0x3e18, 0x12b0, 0x3508, 0x8109, 0x080c, 0x7f6f, 0x6878, 0x6016, - 0x6874, 0x2008, 0x9084, 0xff00, 0x8007, 0x600a, 0x9184, 0x00ff, - 0x6006, 0x8108, 0x1118, 0x6003, 0x0003, 0x0010, 0x6003, 0x0001, - 0x1f04, 0x441f, 0x00ce, 0x00c6, 0x2061, 0x199c, 0x2001, 0x180d, - 0x2004, 0xd08c, 0x11a8, 0x6a88, 0x9284, 0xc000, 0x2010, 0x9286, - 0x0000, 0x1158, 0x2063, 0x0000, 0x2001, 0x0001, 0x080c, 0x2bb1, - 0x2001, 0x0001, 0x080c, 0x2b94, 0x0088, 0x9286, 0x4000, 0x1148, - 0x2063, 0x0001, 0x9006, 0x080c, 0x2bb1, 0x9006, 0x080c, 0x2b94, - 0x0028, 0x9286, 0x8000, 0x1d30, 0x2063, 0x0002, 0x00ce, 0x00e6, - 0x2c70, 0x080c, 0x0ea3, 0x00ee, 0x6888, 0xd0ec, 0x0130, 0x2011, - 0x0114, 0x2204, 0x9085, 0x0100, 0x2012, 0x6a80, 0x9284, 0x0030, - 0x9086, 0x0030, 0x1128, 0x9294, 0xffcf, 0x9295, 0x0020, 0x6a82, - 0x2001, 0x197c, 0x6a80, 0x9294, 0x0030, 0x928e, 0x0000, 0x0170, - 0x928e, 0x0010, 0x0118, 0x928e, 0x0020, 0x0140, 0x2003, 0xaaaa, - 0x080c, 0x298b, 0x2001, 0x196d, 0x2102, 0x0008, 0x2102, 0x00c6, - 0x2061, 0x0100, 0x602f, 0x0040, 0x602f, 0x0000, 0x00ce, 0x080c, - 0x7637, 0x0128, 0x080c, 0x50cb, 0x0110, 0x080c, 0x28dc, 0x60d4, - 0x9005, 0x01c0, 0x6003, 0x0001, 0x2009, 0x44b7, 0x00e0, 0x080c, - 0x7637, 0x1168, 0x2011, 0x74b2, 0x080c, 0x883d, 0x2011, 0x74a5, - 0x080c, 0x8917, 0x080c, 0x7937, 0x080c, 0x7563, 0x0040, 0x080c, - 0x5fed, 0x0028, 0x6003, 0x0004, 0x2009, 0x44cf, 0x0020, 0x080c, - 0x6a05, 0x0804, 0x35b5, 0x2001, 0x0170, 0x2004, 0x9084, 0x00ff, - 0x9086, 0x004c, 0x1118, 0x2091, 0x30bd, 0x0817, 0x2091, 0x303d, - 0x0817, 0x6000, 0x9086, 0x0000, 0x0904, 0x35e7, 0x2069, 0x1847, - 0x7890, 0x6842, 0x7894, 0x6846, 0x2d00, 0x2009, 0x0030, 0x7a8c, - 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0001, 0x0804, 0x4c30, 0x9006, - 0x080c, 0x28dc, 0x81ff, 0x1904, 0x35e7, 0x080c, 0x7637, 0x11b0, - 0x080c, 0x7932, 0x080c, 0x612e, 0x080c, 0x33aa, 0x0118, 0x6130, - 0xc18d, 0x6132, 0x080c, 0xd7e3, 0x0130, 0x080c, 0x765a, 0x1118, - 0x080c, 0x760f, 0x0038, 0x080c, 0x7563, 0x0020, 0x080c, 0x60f3, - 0x080c, 0x5fed, 0x0804, 0x35b5, 0x81ff, 0x1904, 0x35e7, 0x080c, - 0x7637, 0x1110, 0x0804, 0x35e7, 0x0126, 0x2091, 0x8000, 0x6194, - 0x81ff, 0x0190, 0x704f, 0x0000, 0x2001, 0x1c80, 0x2009, 0x0040, - 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0001, 0x080c, 0x4c30, - 0x701f, 0x35b3, 0x012e, 0x0005, 0x704f, 0x0001, 0x00d6, 0x2069, - 0x1c80, 0x20a9, 0x0040, 0x20e9, 0x0001, 0x20a1, 0x1c80, 0x2019, - 0xffff, 0x4304, 0x655c, 0x9588, 0x33b6, 0x210d, 0x918c, 0x00ff, - 0x216a, 0x900e, 0x2011, 0x0002, 0x2100, 0x9506, 0x01a8, 0x080c, - 0x6724, 0x1190, 0xb814, 0x821c, 0x0238, 0x9398, 0x1c80, 0x9085, - 0xff00, 0x8007, 0x201a, 0x0038, 0x9398, 0x1c80, 0x2324, 0x94a4, - 0xff00, 0x9405, 0x201a, 0x8210, 0x8108, 0x9182, 0x0080, 0x1208, - 0x0c18, 0x8201, 0x8007, 0x2d0c, 0x9105, 0x206a, 0x00de, 0x20a9, - 0x0040, 0x20a1, 0x1c80, 0x2099, 0x1c80, 0x080c, 0x607e, 0x0804, - 0x452c, 0x080c, 0x4c17, 0x0904, 0x35ea, 0x080c, 0x4be4, 0x1120, - 0x2009, 0x0002, 0x0804, 0x35e7, 0x080c, 0x57d5, 0xd0b4, 0x0558, - 0x7884, 0x908e, 0x007e, 0x0538, 0x908e, 0x007f, 0x0520, 0x908e, - 0x0080, 0x0508, 0x080c, 0x33a5, 0x1148, 0xb800, 0xd08c, 0x11d8, - 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, 0x11a8, 0xa867, 0x0000, - 0xa868, 0xc0fd, 0xa86a, 0x080c, 0xd2a3, 0x1120, 0x2009, 0x0003, - 0x0804, 0x35e7, 0x7007, 0x0003, 0x701f, 0x45b7, 0x0005, 0x080c, - 0x4c17, 0x0904, 0x35ea, 0x20a9, 0x002b, 0xb8c4, 0x20e0, 0xb8c8, - 0x2098, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0002, 0x20a0, 0x4003, - 0x20a9, 0x0008, 0x9080, 0x0006, 0x20a0, 0xb8c4, 0x20e0, 0xb8c8, - 0x9080, 0x0006, 0x2098, 0x080c, 0x0f8b, 0x0070, 0x20a9, 0x0004, - 0xa85c, 0x9080, 0x000a, 0x20a0, 0xb8c4, 0x20e0, 0xb8c8, 0x9080, - 0x000a, 0x2098, 0x080c, 0x0f8b, 0x8906, 0x8006, 0x8007, 0x90bc, - 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, 0x2009, 0x002b, 0x7a8c, - 0x7b88, 0x7c9c, 0x7d98, 0x0804, 0x4c30, 0x81ff, 0x1904, 0x35e7, - 0x080c, 0x4bfb, 0x0904, 0x35ea, 0x080c, 0x6896, 0x0904, 0x35e7, - 0x0058, 0xa878, 0x9005, 0x0120, 0x2009, 0x0004, 0x0804, 0x35e7, - 0xa974, 0xaa94, 0x0804, 0x35b5, 0x080c, 0x57dd, 0x0904, 0x35b5, - 0x701f, 0x4601, 0x7007, 0x0003, 0x0005, 0x81ff, 0x1904, 0x35e7, - 0x7888, 0x908a, 0x1000, 0x1a04, 0x35ea, 0x080c, 0x4c17, 0x0904, - 0x35ea, 0x080c, 0x6aa3, 0x0120, 0x080c, 0x6aab, 0x1904, 0x35ea, - 0x080c, 0x691b, 0x0904, 0x35e7, 0x2019, 0x0004, 0x900e, 0x080c, - 0x68a8, 0x0904, 0x35e7, 0x7984, 0x7a88, 0x04c9, 0x08a8, 0xa89c, - 0x908a, 0x1000, 0x12f8, 0x080c, 0x4c15, 0x01e0, 0x080c, 0x6aa3, - 0x0118, 0x080c, 0x6aab, 0x11b0, 0x080c, 0x691b, 0x2009, 0x0002, - 0x0168, 0x2009, 0x0002, 0x2019, 0x0004, 0x080c, 0x68a8, 0x2009, - 0x0003, 0x0120, 0xa998, 0xaa9c, 0x00d1, 0x0060, 0xa897, 0x4005, - 0xa99a, 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, - 0x0030, 0x0005, 0xa897, 0x4000, 0x080c, 0x57dd, 0x0110, 0x9006, - 0x0018, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x0005, 0x9186, - 0x00ff, 0x0110, 0x0071, 0x0060, 0x2029, 0x007e, 0x2061, 0x1800, - 0x645c, 0x2400, 0x9506, 0x0110, 0x2508, 0x0019, 0x8529, 0x1ec8, - 0x0005, 0x080c, 0x6724, 0x1138, 0x2200, 0x8003, 0x800b, 0x810b, - 0x9108, 0x080c, 0x884b, 0x0005, 0x81ff, 0x1904, 0x35e7, 0x798c, - 0x2001, 0x1980, 0x918c, 0x8000, 0x2102, 0x080c, 0x4bfb, 0x0904, - 0x35ea, 0x080c, 0x6aa3, 0x0120, 0x080c, 0x6aab, 0x1904, 0x35ea, - 0x080c, 0x67eb, 0x0904, 0x35e7, 0x080c, 0x689f, 0x0904, 0x35e7, - 0x2001, 0x1980, 0x2004, 0xd0fc, 0x1904, 0x35b5, 0x0804, 0x460c, - 0xa9a0, 0x2001, 0x1980, 0x918c, 0x8000, 0xc18d, 0x2102, 0x080c, - 0x4c08, 0x01a0, 0x080c, 0x6aa3, 0x0118, 0x080c, 0x6aab, 0x1170, - 0x080c, 0x67eb, 0x2009, 0x0002, 0x0128, 0x080c, 0x689f, 0x1170, - 0x2009, 0x0003, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, - 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, 0x4000, - 0x2001, 0x1980, 0x2004, 0xd0fc, 0x1128, 0x080c, 0x57dd, 0x0110, - 0x9006, 0x0018, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x0005, - 0x81ff, 0x1904, 0x35e7, 0x798c, 0x2001, 0x197f, 0x918c, 0x8000, - 0x2102, 0x080c, 0x4bfb, 0x0904, 0x35ea, 0x080c, 0x6aa3, 0x0120, - 0x080c, 0x6aab, 0x1904, 0x35ea, 0x080c, 0x67eb, 0x0904, 0x35e7, - 0x080c, 0x688d, 0x0904, 0x35e7, 0x2001, 0x197f, 0x2004, 0xd0fc, - 0x1904, 0x35b5, 0x0804, 0x460c, 0xa9a0, 0x2001, 0x197f, 0x918c, - 0x8000, 0xc18d, 0x2102, 0x080c, 0x4c08, 0x01a0, 0x080c, 0x6aa3, - 0x0118, 0x080c, 0x6aab, 0x1170, 0x080c, 0x67eb, 0x2009, 0x0002, - 0x0128, 0x080c, 0x688d, 0x1170, 0x2009, 0x0003, 0xa897, 0x4005, - 0xa99a, 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, - 0x0030, 0x0005, 0xa897, 0x4000, 0x2001, 0x197f, 0x2004, 0xd0fc, - 0x1128, 0x080c, 0x57dd, 0x0110, 0x9006, 0x0018, 0x900e, 0x9085, - 0x0001, 0x2001, 0x0000, 0x0005, 0x6100, 0x0804, 0x35b5, 0x080c, - 0x4c17, 0x0904, 0x35ea, 0x080c, 0x57e9, 0x1904, 0x35e7, 0x79a8, - 0xd184, 0x1158, 0xb834, 0x8007, 0x789e, 0xb830, 0x8007, 0x789a, - 0xbb2c, 0x831f, 0xba28, 0x8217, 0x0050, 0xb824, 0x8007, 0x789e, - 0xb820, 0x8007, 0x789a, 0xbb1c, 0x831f, 0xba18, 0x8217, 0xb900, - 0x918c, 0x0202, 0x0804, 0x35b5, 0x78a8, 0x909c, 0x0003, 0xd0ac, - 0x1158, 0xd0b4, 0x1148, 0x939a, 0x0003, 0x1a04, 0x35e7, 0x625c, - 0x7884, 0x9206, 0x1904, 0x47c7, 0x080c, 0x894c, 0x2001, 0xffec, - 0x2009, 0x000c, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0000, - 0x0006, 0x78a8, 0x9084, 0x0080, 0x1528, 0x0006, 0x0036, 0x2001, - 0x1a83, 0x201c, 0x7b9a, 0x2003, 0x0000, 0x2001, 0x1a84, 0x201c, - 0x7b9e, 0x2003, 0x0000, 0x2001, 0x1a85, 0x201c, 0x7bae, 0x2003, - 0x0000, 0x2001, 0x1a7f, 0x201c, 0x7baa, 0x2003, 0x0000, 0x2001, - 0x1a86, 0x201c, 0x7bb2, 0x2003, 0x0000, 0x003e, 0x000e, 0x000e, - 0x0804, 0x4c30, 0x000e, 0x2031, 0x0000, 0x2061, 0x18b8, 0x2c44, - 0xa66a, 0xa17a, 0xa772, 0xa076, 0xa28e, 0xa392, 0xa496, 0xa59a, - 0x080c, 0x10f8, 0x7007, 0x0002, 0x701f, 0x47e7, 0x0005, 0x81ff, - 0x1904, 0x35e7, 0x080c, 0x4c17, 0x0904, 0x35ea, 0x080c, 0x6aa3, - 0x1904, 0x35e7, 0x00c6, 0x080c, 0x4be4, 0x00ce, 0x0904, 0x35e7, - 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x7ea8, 0x080c, 0xd249, - 0x0904, 0x35e7, 0x7007, 0x0003, 0x701f, 0x480d, 0x0005, 0x080c, - 0x42ec, 0x0006, 0x0036, 0x2001, 0x1a83, 0x201c, 0x7b9a, 0x2003, - 0x0000, 0x2001, 0x1a84, 0x201c, 0x7b9e, 0x2003, 0x0000, 0x2001, - 0x1a85, 0x201c, 0x7bae, 0x2003, 0x0000, 0x2001, 0x1a7f, 0x201c, - 0x7baa, 0x2003, 0x0000, 0x2001, 0x1a86, 0x201c, 0x7bb2, 0x2003, - 0x0000, 0x003e, 0x000e, 0x0804, 0x35b5, 0xa830, 0x9086, 0x0100, - 0x0904, 0x35e7, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, - 0xffc0, 0x9080, 0x001b, 0x2009, 0x000c, 0x7a8c, 0x7b88, 0x7c9c, - 0x7d98, 0x0804, 0x4c30, 0x9006, 0x080c, 0x28dc, 0x78a8, 0x9084, - 0x00ff, 0x9086, 0x00ff, 0x0118, 0x81ff, 0x1904, 0x35e7, 0x080c, - 0x7637, 0x0110, 0x080c, 0x60f3, 0x7888, 0x908a, 0x1000, 0x1a04, - 0x35ea, 0x7984, 0x9186, 0x00ff, 0x0138, 0x9182, 0x007f, 0x1a04, - 0x35ea, 0x2100, 0x080c, 0x28a6, 0x0026, 0x00c6, 0x0126, 0x2091, - 0x8000, 0x2061, 0x19fb, 0x601b, 0x0000, 0x601f, 0x0000, 0x607b, - 0x0000, 0x607f, 0x0000, 0x080c, 0x7637, 0x1158, 0x080c, 0x7932, - 0x080c, 0x612e, 0x9085, 0x0001, 0x080c, 0x767b, 0x080c, 0x7563, - 0x00d0, 0x080c, 0xb244, 0x2061, 0x0100, 0x2001, 0x1818, 0x2004, - 0x9084, 0x00ff, 0x810f, 0x9105, 0x604a, 0x6043, 0x0090, 0x6043, - 0x0010, 0x2009, 0x1999, 0x200b, 0x0000, 0x2009, 0x002d, 0x2011, - 0x6019, 0x080c, 0x88d5, 0x7984, 0x080c, 0x7637, 0x1110, 0x2009, - 0x00ff, 0x7a88, 0x080c, 0x466f, 0x012e, 0x00ce, 0x002e, 0x0804, - 0x35b5, 0x7984, 0x080c, 0x66b9, 0x2b08, 0x1904, 0x35ea, 0x0804, - 0x35b5, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x35e7, 0x60dc, - 0xd0ac, 0x1130, 0xd09c, 0x1120, 0x2009, 0x0005, 0x0804, 0x35e7, - 0x080c, 0x4be4, 0x1120, 0x2009, 0x0002, 0x0804, 0x35e7, 0x7984, - 0x81ff, 0x0904, 0x35ea, 0x9192, 0x0021, 0x1a04, 0x35ea, 0x7a8c, - 0x7b88, 0x7c9c, 0x7d98, 0xa85c, 0x9080, 0x0019, 0x702a, 0xaf60, - 0x7736, 0x080c, 0x4c2d, 0x701f, 0x48c4, 0x7880, 0x9086, 0x006e, - 0x0110, 0x701f, 0x527d, 0x0005, 0x2009, 0x0080, 0x080c, 0x6724, - 0x1118, 0x080c, 0x6aa3, 0x0120, 0x2021, 0x400a, 0x0804, 0x35b7, - 0x00d6, 0x0096, 0xa964, 0xaa6c, 0xab70, 0xac74, 0xad78, 0xae7c, - 0xa884, 0x90be, 0x0100, 0x0904, 0x495d, 0x90be, 0x0112, 0x0904, - 0x495d, 0x90be, 0x0113, 0x0904, 0x495d, 0x90be, 0x0114, 0x0904, - 0x495d, 0x90be, 0x0117, 0x0904, 0x495d, 0x90be, 0x011a, 0x0904, - 0x495d, 0x90be, 0x011c, 0x0904, 0x495d, 0x90be, 0x0121, 0x0904, - 0x4944, 0x90be, 0x0131, 0x0904, 0x4944, 0x90be, 0x0171, 0x0904, - 0x495d, 0x90be, 0x0173, 0x0904, 0x495d, 0x90be, 0x01a1, 0x1128, - 0xa894, 0x8007, 0xa896, 0x0804, 0x4968, 0x90be, 0x0212, 0x0904, - 0x4951, 0x90be, 0x0213, 0x05e8, 0x90be, 0x0214, 0x0500, 0x90be, - 0x0217, 0x0188, 0x90be, 0x021a, 0x1120, 0xa89c, 0x8007, 0xa89e, - 0x04e0, 0x90be, 0x021f, 0x05c8, 0x90be, 0x0300, 0x05b0, 0x009e, - 0x00de, 0x0804, 0x35ea, 0x7028, 0x9080, 0x0010, 0x2098, 0x20a0, - 0x7034, 0x20e0, 0x20e8, 0x20a9, 0x0007, 0x080c, 0x49a6, 0x7028, - 0x9080, 0x000e, 0x2098, 0x20a0, 0x7034, 0x20e0, 0x20e8, 0x20a9, - 0x0001, 0x080c, 0x49a6, 0x00c8, 0x7028, 0x9080, 0x000c, 0x2098, - 0x20a0, 0x7034, 0x20e0, 0x20e8, 0x20a9, 0x0001, 0x080c, 0x49b3, - 0x00b8, 0x7028, 0x9080, 0x000e, 0x2098, 0x20a0, 0x7034, 0x20e0, - 0x20e8, 0x20a9, 0x0001, 0x080c, 0x49b3, 0x7028, 0x9080, 0x000c, - 0x2098, 0x20a0, 0x7034, 0x20e0, 0x20e8, 0x20a9, 0x0001, 0x04f1, - 0x00c6, 0x080c, 0x4be4, 0x0550, 0xa868, 0xc0fd, 0xa86a, 0xa867, - 0x0119, 0x9006, 0xa882, 0xa87f, 0x0020, 0xa88b, 0x0001, 0x810b, - 0xa9ae, 0xa8b2, 0xaab6, 0xabba, 0xacbe, 0xadc2, 0xa9c6, 0xa8ca, - 0x00ce, 0x009e, 0x00de, 0xa866, 0xa822, 0xa868, 0xc0fd, 0xa86a, - 0xa804, 0x2048, 0x080c, 0xd264, 0x1120, 0x2009, 0x0003, 0x0804, - 0x35e7, 0x7007, 0x0003, 0x701f, 0x499d, 0x0005, 0x00ce, 0x009e, - 0x00de, 0x2009, 0x0002, 0x0804, 0x35e7, 0xa820, 0x9086, 0x8001, - 0x1904, 0x35b5, 0x2009, 0x0004, 0x0804, 0x35e7, 0x0016, 0x0026, - 0x3510, 0x20a9, 0x0002, 0x4002, 0x4104, 0x4004, 0x8211, 0x1dc8, - 0x002e, 0x001e, 0x0005, 0x0016, 0x0026, 0x0036, 0x0046, 0x3520, - 0x20a9, 0x0004, 0x4002, 0x4304, 0x4204, 0x4104, 0x4004, 0x8421, - 0x1db8, 0x004e, 0x003e, 0x002e, 0x001e, 0x0005, 0x81ff, 0x0120, - 0x2009, 0x0001, 0x0804, 0x35e7, 0x60dc, 0xd0ac, 0x1188, 0x2009, - 0x180d, 0x210c, 0xd18c, 0x0130, 0xd09c, 0x0120, 0x2009, 0x0016, - 0x0804, 0x35e7, 0xd09c, 0x1120, 0x2009, 0x0005, 0x0804, 0x35e7, - 0x7984, 0x78a8, 0x2040, 0x080c, 0xb23d, 0x1120, 0x9182, 0x007f, - 0x0a04, 0x35ea, 0x9186, 0x00ff, 0x0904, 0x35ea, 0x9182, 0x0800, - 0x1a04, 0x35ea, 0x7a8c, 0x7b88, 0x607c, 0x9306, 0x1158, 0x6080, - 0x924e, 0x0904, 0x35ea, 0x080c, 0xb23d, 0x1120, 0x99cc, 0xff00, - 0x0904, 0x35ea, 0x0126, 0x2091, 0x8000, 0x2001, 0x180d, 0x2004, - 0xd08c, 0x0198, 0x9386, 0x00ff, 0x0180, 0x0026, 0x2011, 0x8008, - 0x080c, 0x6ac7, 0x002e, 0x0148, 0x918d, 0x8000, 0x080c, 0x6b11, - 0x1120, 0x2001, 0x4009, 0x0804, 0x4a64, 0x080c, 0x4af7, 0x0904, - 0x4a6a, 0x0086, 0x90c6, 0x4000, 0x008e, 0x1538, 0x00c6, 0x0006, - 0x0036, 0xb818, 0xbb1c, 0x9305, 0xbb20, 0x9305, 0xbb24, 0x9305, - 0xbb28, 0x9305, 0xbb2c, 0x9305, 0xbb30, 0x9305, 0xbb34, 0x9305, - 0x003e, 0x0570, 0xd88c, 0x1128, 0x080c, 0x6aa3, 0x0110, 0xc89d, - 0x0438, 0x900e, 0x080c, 0x6944, 0x1108, 0xc185, 0xb800, 0xd0bc, - 0x0108, 0xc18d, 0x000e, 0x00ce, 0x00b8, 0x90c6, 0x4007, 0x1110, - 0x2408, 0x0090, 0x90c6, 0x4008, 0x1118, 0x2708, 0x2610, 0x0060, - 0x90c6, 0x4009, 0x1108, 0x0040, 0x90c6, 0x4006, 0x1108, 0x0020, - 0x2001, 0x4005, 0x2009, 0x000a, 0x2020, 0x012e, 0x0804, 0x35b7, - 0x000e, 0x00ce, 0x2b00, 0x7026, 0x0016, 0x00b6, 0x00c6, 0x00e6, - 0x2c70, 0x080c, 0xb325, 0x0904, 0x4abf, 0x2b00, 0x6012, 0x080c, - 0xd554, 0x2e58, 0x00ee, 0x00e6, 0x00c6, 0x080c, 0x4be4, 0x00ce, - 0x2b70, 0x1158, 0x080c, 0xb2d3, 0x00ee, 0x00ce, 0x00be, 0x001e, - 0x012e, 0x2009, 0x0002, 0x0804, 0x35e7, 0x900e, 0xa966, 0xa96a, - 0x2900, 0x6016, 0xa932, 0xa868, 0xc0fd, 0xd88c, 0x0108, 0xc0f5, - 0xa86a, 0xd89c, 0x1110, 0x080c, 0x3250, 0x6023, 0x0001, 0x9006, - 0x080c, 0x6656, 0xd89c, 0x0138, 0x2001, 0x0004, 0x080c, 0x666a, - 0x2009, 0x0003, 0x0030, 0x2001, 0x0002, 0x080c, 0x666a, 0x2009, - 0x0002, 0x080c, 0xb352, 0x78a8, 0xd094, 0x0138, 0x00ee, 0x7024, - 0x00e6, 0x2058, 0xb8cc, 0xc08d, 0xb8ce, 0x9085, 0x0001, 0x00ee, - 0x00ce, 0x00be, 0x001e, 0x012e, 0x1120, 0x2009, 0x0003, 0x0804, - 0x35e7, 0x7007, 0x0003, 0x701f, 0x4ace, 0x0005, 0xa830, 0x2009, - 0x180d, 0x210c, 0xd18c, 0x0140, 0x2008, 0x918e, 0xdead, 0x1120, - 0x2021, 0x4009, 0x0804, 0x35b7, 0x9086, 0x0100, 0x7024, 0x2058, - 0x1138, 0x2009, 0x0004, 0xba04, 0x9294, 0x00ff, 0x0804, 0x5729, - 0x900e, 0xa868, 0xd0f4, 0x1904, 0x35b5, 0x080c, 0x6944, 0x1108, - 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x0804, 0x35b5, 0x00e6, - 0x00d6, 0x0096, 0x83ff, 0x0904, 0x4b46, 0x902e, 0x080c, 0xb23d, - 0x0130, 0x9026, 0x20a9, 0x0800, 0x2071, 0x1000, 0x0030, 0x2021, - 0x007f, 0x20a9, 0x0781, 0x2071, 0x107f, 0x2e04, 0x9005, 0x11b8, - 0x2100, 0x9406, 0x1904, 0x4b57, 0x2428, 0x94ce, 0x007f, 0x1120, - 0x92ce, 0xfffd, 0x1558, 0x0030, 0x94ce, 0x0080, 0x1130, 0x92ce, - 0xfffc, 0x1520, 0x93ce, 0x00ff, 0x1508, 0xc5fd, 0x0480, 0x2058, - 0xbf10, 0x2700, 0x9306, 0x11e8, 0xbe14, 0x2600, 0x9206, 0x11c8, - 0x2400, 0x9106, 0x1180, 0xd884, 0x0598, 0xd894, 0x1588, 0x080c, - 0x6a43, 0x1570, 0x2001, 0x4000, 0x0460, 0x080c, 0x6aa3, 0x1540, - 0x2001, 0x4000, 0x0430, 0x2001, 0x4007, 0x0418, 0x2001, 0x4006, - 0x0400, 0x2400, 0x9106, 0x1158, 0xbe14, 0x87ff, 0x1128, 0x86ff, - 0x0918, 0x080c, 0xb23d, 0x1900, 0x2001, 0x4008, 0x0090, 0x8420, - 0x8e70, 0x1f04, 0x4b0d, 0x85ff, 0x1130, 0x2001, 0x4009, 0x0048, - 0x2001, 0x0001, 0x0030, 0x080c, 0x66b9, 0x1dd0, 0xbb12, 0xba16, - 0x9006, 0x9005, 0x009e, 0x00de, 0x00ee, 0x0005, 0x81ff, 0x0120, - 0x2009, 0x0001, 0x0804, 0x35e7, 0x080c, 0x4be4, 0x1120, 0x2009, - 0x0002, 0x0804, 0x35e7, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, - 0x7884, 0x9005, 0x0904, 0x35ea, 0x9096, 0x00ff, 0x0120, 0x9092, - 0x0004, 0x1a04, 0x35ea, 0x2010, 0x2918, 0x080c, 0x31f6, 0x1120, - 0x2009, 0x0003, 0x0804, 0x35e7, 0x7007, 0x0003, 0x701f, 0x4b99, - 0x0005, 0xa830, 0x9086, 0x0100, 0x1904, 0x35b5, 0x2009, 0x0004, - 0x0804, 0x35e7, 0x7984, 0x080c, 0xb23d, 0x1120, 0x9182, 0x007f, - 0x0a04, 0x35ea, 0x9186, 0x00ff, 0x0904, 0x35ea, 0x9182, 0x0800, - 0x1a04, 0x35ea, 0x2001, 0x9400, 0x080c, 0x5784, 0x1904, 0x35e7, - 0x0804, 0x35b5, 0xa998, 0x080c, 0xb23d, 0x1118, 0x9182, 0x007f, - 0x0280, 0x9186, 0x00ff, 0x0168, 0x9182, 0x0800, 0x1250, 0x2001, - 0x9400, 0x080c, 0x5784, 0x11a8, 0x0060, 0xa897, 0x4005, 0xa99a, - 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, - 0x0005, 0xa897, 0x4000, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, - 0x0005, 0x2009, 0x000a, 0x0c48, 0x080c, 0x100e, 0x0198, 0x9006, - 0xa802, 0x7014, 0x9005, 0x1120, 0x2900, 0x7016, 0x701a, 0x0040, - 0x7018, 0xa802, 0x0086, 0x2040, 0x2900, 0xa006, 0x701a, 0x008e, - 0x9085, 0x0001, 0x0005, 0x7984, 0x080c, 0x6724, 0x1130, 0x7e88, - 0x9684, 0x3fff, 0x9082, 0x4000, 0x0208, 0x905e, 0x8bff, 0x0005, - 0xa998, 0x080c, 0x6724, 0x1130, 0xae9c, 0x9684, 0x3fff, 0x9082, - 0x4000, 0x0208, 0x905e, 0x8bff, 0x0005, 0xae98, 0x0008, 0x7e84, - 0x2608, 0x080c, 0x6724, 0x1108, 0x0008, 0x905e, 0x8bff, 0x0005, - 0x0016, 0x7114, 0x81ff, 0x0128, 0x2148, 0xa904, 0x080c, 0x1040, - 0x0cc8, 0x7116, 0x711a, 0x001e, 0x0005, 0x2031, 0x0001, 0x0010, - 0x2031, 0x0000, 0x2061, 0x18b8, 0x2c44, 0xa66a, 0xa17a, 0xa772, - 0xa076, 0xa28e, 0xa392, 0xa496, 0xa59a, 0x080c, 0x10f8, 0x7007, - 0x0002, 0x701f, 0x35b5, 0x0005, 0x00f6, 0x0126, 0x2091, 0x8000, - 0x2079, 0x0000, 0x2001, 0x18b0, 0x2004, 0x9005, 0x1190, 0x0e04, - 0x4c61, 0x7a36, 0x7833, 0x0012, 0x7a82, 0x7b86, 0x7c8a, 0x2091, - 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11aa, 0x0804, - 0x4cc7, 0x0016, 0x0086, 0x0096, 0x00c6, 0x00e6, 0x2071, 0x189e, - 0x7044, 0x9005, 0x1540, 0x7148, 0x9182, 0x0010, 0x0288, 0x7038, - 0x2060, 0x080c, 0x100e, 0x0904, 0x4cbf, 0xa84b, 0x0000, 0x2900, - 0x7046, 0x2001, 0x0002, 0x9080, 0x20c7, 0x2005, 0xa846, 0x0098, - 0x7038, 0x90e0, 0x0004, 0x2001, 0x18ba, 0x9c82, 0x18fa, 0x0210, - 0x2061, 0x18ba, 0x2c00, 0x703a, 0x7148, 0x81ff, 0x1108, 0x703e, - 0x8108, 0x714a, 0x0460, 0x7148, 0x8108, 0x714a, 0x7044, 0x2040, - 0xa144, 0x2105, 0x0016, 0x908a, 0x0036, 0x1a0c, 0x0dc5, 0x2060, - 0x001e, 0x8108, 0x2105, 0x9005, 0xa146, 0x1520, 0x080c, 0x100e, - 0x1130, 0x8109, 0xa946, 0x7148, 0x8109, 0x714a, 0x00d8, 0x9006, - 0xa806, 0xa84a, 0xa046, 0x2800, 0xa802, 0x2900, 0xa006, 0x7046, - 0x2001, 0x0002, 0x9080, 0x20c7, 0x2005, 0xa846, 0x0058, 0x2262, - 0x6306, 0x640a, 0x00ee, 0x00ce, 0x009e, 0x008e, 0x001e, 0x012e, - 0x00fe, 0x0005, 0x2c00, 0x9082, 0x001b, 0x0002, 0x4ce9, 0x4ce9, - 0x4ceb, 0x4ce9, 0x4ce9, 0x4ce9, 0x4cef, 0x4ce9, 0x4ce9, 0x4ce9, - 0x4cf3, 0x4ce9, 0x4ce9, 0x4ce9, 0x4cf7, 0x4ce9, 0x4ce9, 0x4ce9, - 0x4cfb, 0x4ce9, 0x4ce9, 0x4ce9, 0x4cff, 0x4ce9, 0x4ce9, 0x4ce9, - 0x4d04, 0x080c, 0x0dc5, 0xa276, 0xa37a, 0xa47e, 0x0898, 0xa286, - 0xa38a, 0xa48e, 0x0878, 0xa296, 0xa39a, 0xa49e, 0x0858, 0xa2a6, - 0xa3aa, 0xa4ae, 0x0838, 0xa2b6, 0xa3ba, 0xa4be, 0x0818, 0xa2c6, - 0xa3ca, 0xa4ce, 0x0804, 0x4cc2, 0xa2d6, 0xa3da, 0xa4de, 0x0804, - 0x4cc2, 0x00e6, 0x2071, 0x189e, 0x7048, 0x9005, 0x0904, 0x4d9b, - 0x0126, 0x2091, 0x8000, 0x0e04, 0x4d9a, 0x00f6, 0x2079, 0x0000, - 0x00c6, 0x0096, 0x0086, 0x0076, 0x9006, 0x2038, 0x7040, 0x2048, - 0x9005, 0x0500, 0xa948, 0x2105, 0x0016, 0x908a, 0x0036, 0x1a0c, - 0x0dc5, 0x2060, 0x001e, 0x8108, 0x2105, 0x9005, 0xa94a, 0x1904, - 0x4d9d, 0xa804, 0x9005, 0x090c, 0x0dc5, 0x7042, 0x2938, 0x2040, - 0xa003, 0x0000, 0x2001, 0x0002, 0x9080, 0x20c7, 0x2005, 0xa04a, - 0x0804, 0x4d9d, 0x703c, 0x2060, 0x2c14, 0x6304, 0x6408, 0x650c, - 0x2200, 0x7836, 0x7833, 0x0012, 0x7882, 0x2300, 0x7886, 0x2400, - 0x788a, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, - 0x11aa, 0x87ff, 0x0118, 0x2748, 0x080c, 0x1040, 0x7048, 0x8001, - 0x704a, 0x9005, 0x1170, 0x7040, 0x2048, 0x9005, 0x0128, 0x080c, - 0x1040, 0x9006, 0x7042, 0x7046, 0x703b, 0x18ba, 0x703f, 0x18ba, - 0x0420, 0x7040, 0x9005, 0x1508, 0x7238, 0x2c00, 0x9206, 0x0148, - 0x9c80, 0x0004, 0x90fa, 0x18fa, 0x0210, 0x2001, 0x18ba, 0x703e, - 0x00a0, 0x9006, 0x703e, 0x703a, 0x7044, 0x9005, 0x090c, 0x0dc5, - 0x2048, 0xa800, 0x9005, 0x1de0, 0x2900, 0x7042, 0x2001, 0x0002, - 0x9080, 0x20c7, 0x2005, 0xa84a, 0x0000, 0x007e, 0x008e, 0x009e, - 0x00ce, 0x00fe, 0x012e, 0x00ee, 0x0005, 0x2c00, 0x9082, 0x001b, - 0x0002, 0x4dbc, 0x4dbc, 0x4dbe, 0x4dbc, 0x4dbc, 0x4dbc, 0x4dc3, - 0x4dbc, 0x4dbc, 0x4dbc, 0x4dc8, 0x4dbc, 0x4dbc, 0x4dbc, 0x4dcd, - 0x4dbc, 0x4dbc, 0x4dbc, 0x4dd2, 0x4dbc, 0x4dbc, 0x4dbc, 0x4dd7, - 0x4dbc, 0x4dbc, 0x4dbc, 0x4ddc, 0x080c, 0x0dc5, 0xaa74, 0xab78, - 0xac7c, 0x0804, 0x4d48, 0xaa84, 0xab88, 0xac8c, 0x0804, 0x4d48, - 0xaa94, 0xab98, 0xac9c, 0x0804, 0x4d48, 0xaaa4, 0xaba8, 0xacac, - 0x0804, 0x4d48, 0xaab4, 0xabb8, 0xacbc, 0x0804, 0x4d48, 0xaac4, - 0xabc8, 0xaccc, 0x0804, 0x4d48, 0xaad4, 0xabd8, 0xacdc, 0x0804, - 0x4d48, 0x0016, 0x0026, 0x0036, 0x00b6, 0x00c6, 0x2009, 0x007e, - 0x080c, 0x6724, 0x2019, 0x0001, 0xb85c, 0xd0ac, 0x0110, 0x2019, - 0x0000, 0x2011, 0x801b, 0x080c, 0x4c44, 0x00ce, 0x00be, 0x003e, - 0x002e, 0x001e, 0x0005, 0x0026, 0x080c, 0x57d5, 0xd0c4, 0x0120, - 0x2011, 0x8014, 0x080c, 0x4c44, 0x002e, 0x0005, 0x81ff, 0x1904, - 0x35e7, 0x0126, 0x2091, 0x8000, 0x6030, 0xc08d, 0xc085, 0xc0ac, - 0x6032, 0x080c, 0x7637, 0x1158, 0x080c, 0x7932, 0x080c, 0x612e, - 0x9085, 0x0001, 0x080c, 0x767b, 0x080c, 0x7563, 0x0010, 0x080c, - 0x5fed, 0x012e, 0x0804, 0x35b5, 0x81ff, 0x0120, 0x2009, 0x0001, - 0x0804, 0x35e7, 0x080c, 0x57e9, 0x0120, 0x2009, 0x0007, 0x0804, - 0x35e7, 0x080c, 0x6a9b, 0x0120, 0x2009, 0x0008, 0x0804, 0x35e7, - 0x2001, 0x180d, 0x2004, 0xd08c, 0x0178, 0x0026, 0x2011, 0x0010, - 0x080c, 0x6ac7, 0x002e, 0x0140, 0x7984, 0x080c, 0x6b11, 0x1120, - 0x2009, 0x4009, 0x0804, 0x35e7, 0x7984, 0x080c, 0x66b9, 0x1904, - 0x35ea, 0x080c, 0x4c17, 0x0904, 0x35ea, 0x2b00, 0x7026, 0x080c, - 0x6aa3, 0x7888, 0x1170, 0x9084, 0x0005, 0x1158, 0x900e, 0x080c, - 0x6944, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x0804, - 0x35b5, 0x080c, 0x4be4, 0x0904, 0x35e7, 0x9006, 0xa866, 0xa832, - 0xa868, 0xc0fd, 0xa86a, 0x080c, 0xd302, 0x0904, 0x35e7, 0x7888, - 0xd094, 0x0118, 0xb8cc, 0xc08d, 0xb8ce, 0x7007, 0x0003, 0x701f, - 0x4ecb, 0x0005, 0x2061, 0x1800, 0x080c, 0x57e9, 0x2009, 0x0007, - 0x1560, 0x080c, 0x6a9b, 0x0118, 0x2009, 0x0008, 0x0430, 0xa998, - 0x080c, 0x66b9, 0x1530, 0x080c, 0x4c15, 0x0518, 0x080c, 0x6aa3, - 0xa89c, 0x1168, 0x9084, 0x0005, 0x1150, 0x900e, 0x080c, 0x6944, - 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x00d0, 0xa868, - 0xc0fc, 0xa86a, 0x080c, 0xd302, 0x11e0, 0xa89c, 0xd094, 0x0118, - 0xb8cc, 0xc08d, 0xb8ce, 0x2009, 0x0003, 0xa897, 0x4005, 0xa99a, - 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, - 0x0005, 0xa897, 0x4000, 0xa99a, 0x9006, 0x918d, 0x0001, 0x2008, - 0x0005, 0x9006, 0x0005, 0xa830, 0x2009, 0x180d, 0x210c, 0xd18c, - 0x0140, 0x2008, 0x918e, 0xdead, 0x1120, 0x2021, 0x4009, 0x0804, - 0x35b7, 0x9086, 0x0100, 0x7024, 0x2058, 0x1110, 0x0804, 0x5729, - 0x900e, 0x080c, 0x6944, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, - 0xc18d, 0x0804, 0x35b5, 0x080c, 0x57e9, 0x0120, 0x2009, 0x0007, - 0x0804, 0x35e7, 0x7f84, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x080c, - 0x4be4, 0x1120, 0x2009, 0x0002, 0x0804, 0x35e7, 0x900e, 0x2130, - 0x7126, 0x7132, 0xa860, 0x20e8, 0x7036, 0xa85c, 0x9080, 0x0005, - 0x702a, 0x20a0, 0x080c, 0x6724, 0x1904, 0x4f81, 0x080c, 0x6aa3, - 0x0138, 0x080c, 0x6aab, 0x0120, 0x080c, 0x6a43, 0x1904, 0x4f81, - 0xd794, 0x1110, 0xd784, 0x01a8, 0xb8c4, 0x20e0, 0xb8c8, 0x9080, - 0x0006, 0x2098, 0x3400, 0xd794, 0x0198, 0x20a9, 0x0008, 0x4003, - 0x2098, 0x20a0, 0x3d00, 0x20e0, 0x20a9, 0x0002, 0x080c, 0x49b3, - 0x0080, 0xb8c4, 0x20e0, 0xb8c8, 0x9080, 0x000a, 0x2098, 0x3400, - 0x20a9, 0x0004, 0x4003, 0x2098, 0x20a0, 0x3d00, 0x20e0, 0x080c, - 0x49b3, 0x9186, 0x007e, 0x0170, 0x9186, 0x0080, 0x0158, 0x080c, - 0x6aa3, 0x90c2, 0x0006, 0x1210, 0xc1fd, 0x0020, 0x080c, 0x6944, - 0x1108, 0xc1fd, 0x4104, 0xc1fc, 0xd794, 0x0528, 0xb8c4, 0x20e0, - 0xb8c8, 0x2060, 0x9c80, 0x0000, 0x2098, 0x20a9, 0x0002, 0x4003, - 0x9c80, 0x0003, 0x2098, 0x20a9, 0x0001, 0x4005, 0x9c80, 0x0004, - 0x2098, 0x3400, 0x20a9, 0x0002, 0x4003, 0x2098, 0x20a0, 0x3d00, - 0x20e0, 0x080c, 0x49a6, 0x9c80, 0x0026, 0x2098, 0xb8c4, 0x20e0, - 0x20a9, 0x0002, 0x4003, 0xd794, 0x0110, 0x96b0, 0x000b, 0x96b0, - 0x0005, 0x8108, 0x080c, 0xb23d, 0x0118, 0x9186, 0x0800, 0x0040, - 0xd78c, 0x0120, 0x9186, 0x0800, 0x0170, 0x0018, 0x9186, 0x007e, - 0x0150, 0xd794, 0x0118, 0x9686, 0x0020, 0x0010, 0x9686, 0x0028, - 0x0150, 0x0804, 0x4f0a, 0x86ff, 0x1120, 0x7124, 0x810b, 0x0804, - 0x35b5, 0x7033, 0x0001, 0x7122, 0x7024, 0x9600, 0x7026, 0x772e, - 0x2061, 0x18b8, 0x2c44, 0xa06b, 0x0000, 0xa67a, 0x7034, 0xa072, - 0x7028, 0xa076, 0xa28e, 0xa392, 0xa496, 0xa59a, 0x080c, 0x10f8, - 0x7007, 0x0002, 0x701f, 0x4fbd, 0x0005, 0x7030, 0x9005, 0x1180, - 0x7120, 0x7028, 0x20a0, 0x772c, 0x9036, 0x7034, 0x20e8, 0x2061, - 0x18b8, 0x2c44, 0xa28c, 0xa390, 0xa494, 0xa598, 0x0804, 0x4f0a, - 0x7124, 0x810b, 0x0804, 0x35b5, 0x2029, 0x007e, 0x7984, 0x7a88, - 0x7b8c, 0x7c98, 0x9184, 0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04, - 0x35ea, 0x9502, 0x0a04, 0x35ea, 0x9184, 0x00ff, 0x90e2, 0x0020, - 0x0a04, 0x35ea, 0x9502, 0x0a04, 0x35ea, 0x9284, 0xff00, 0x8007, - 0x90e2, 0x0020, 0x0a04, 0x35ea, 0x9502, 0x0a04, 0x35ea, 0x9284, - 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x35ea, 0x9502, 0x0a04, 0x35ea, - 0x9384, 0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04, 0x35ea, 0x9502, - 0x0a04, 0x35ea, 0x9384, 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x35ea, - 0x9502, 0x0a04, 0x35ea, 0x9484, 0xff00, 0x8007, 0x90e2, 0x0020, - 0x0a04, 0x35ea, 0x9502, 0x0a04, 0x35ea, 0x9484, 0x00ff, 0x90e2, - 0x0020, 0x0a04, 0x35ea, 0x9502, 0x0a04, 0x35ea, 0x2061, 0x1989, - 0x6102, 0x6206, 0x630a, 0x640e, 0x0804, 0x35b5, 0x080c, 0x4be4, - 0x0904, 0x35e7, 0x2009, 0x0016, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, - 0xa85c, 0x9080, 0x0019, 0xaf60, 0x080c, 0x4c2d, 0x701f, 0x5041, - 0x0005, 0x20a9, 0x0016, 0x896e, 0x8d6e, 0x8d6f, 0x9d84, 0xffc0, - 0x9080, 0x0019, 0x2098, 0x9d84, 0x003f, 0x20e0, 0x2069, 0x1877, - 0x20e9, 0x0001, 0x2da0, 0x4003, 0x6800, 0x9005, 0x0904, 0x50a8, - 0x6804, 0x2008, 0x918c, 0xfff8, 0x1904, 0x50a8, 0x680c, 0x9005, - 0x0904, 0x50a8, 0x9082, 0xff01, 0x1a04, 0x50a8, 0x6810, 0x9082, - 0x005c, 0x06f0, 0x6824, 0x2008, 0x9082, 0x0008, 0x06c8, 0x9182, - 0x0400, 0x16b0, 0x0056, 0x2029, 0x0000, 0x080c, 0x8e80, 0x005e, - 0x6944, 0x6820, 0x9102, 0x0660, 0x6820, 0x9082, 0x0019, 0x1640, - 0x6828, 0x6944, 0x810c, 0x9102, 0x0618, 0x6840, 0x9082, 0x000f, - 0x12f8, 0x080c, 0x1027, 0x2900, 0x0590, 0x684e, 0x00e6, 0x2071, - 0x1931, 0x00b6, 0x2059, 0x0000, 0x080c, 0x8d3c, 0x00be, 0x00ee, - 0x01e8, 0x080c, 0x8a84, 0x080c, 0x8ad3, 0x1160, 0x6857, 0x0000, - 0x00c6, 0x6b10, 0x2061, 0x1a65, 0x630a, 0x00ce, 0x0804, 0x35b5, - 0x0804, 0x35ea, 0x080c, 0x8acc, 0x00e6, 0x2071, 0x1931, 0x080c, - 0x8f00, 0x080c, 0x8f0f, 0x080c, 0x8d21, 0x00ee, 0x2001, 0x188a, - 0x204c, 0x080c, 0x1040, 0x2001, 0x188a, 0x2003, 0x0000, 0x0804, - 0x35e7, 0x0126, 0x2091, 0x8000, 0x080c, 0x92bf, 0x080c, 0x8acc, - 0x012e, 0x0804, 0x35b5, 0x0006, 0x080c, 0x57d5, 0xd0cc, 0x000e, - 0x0005, 0x0006, 0x080c, 0x57d9, 0xd0bc, 0x000e, 0x0005, 0x6174, - 0x7a84, 0x6300, 0x82ff, 0x1118, 0x7986, 0x0804, 0x35b5, 0x83ff, - 0x1904, 0x35ea, 0x2001, 0xfff0, 0x9200, 0x1a04, 0x35ea, 0x2019, - 0xffff, 0x6078, 0x9302, 0x9200, 0x0a04, 0x35ea, 0x7986, 0x6276, - 0x0804, 0x35b5, 0x080c, 0x57e9, 0x1904, 0x35e7, 0x7c88, 0x7d84, - 0x7e98, 0x7f8c, 0x080c, 0x4be4, 0x0904, 0x35e7, 0x900e, 0x901e, - 0x7326, 0x7332, 0xa860, 0x20e8, 0x7036, 0xa85c, 0x9080, 0x0003, - 0x702a, 0x20a0, 0x91d8, 0x1000, 0x2b5c, 0x8bff, 0x0178, 0x080c, - 0x6aa3, 0x0118, 0x080c, 0x6aab, 0x1148, 0x20a9, 0x0001, 0xb814, - 0x4004, 0xb810, 0x4004, 0x4104, 0x9398, 0x0003, 0x8108, 0x9182, - 0x0800, 0x0120, 0x9386, 0x003c, 0x0170, 0x0c20, 0x83ff, 0x1148, - 0x7224, 0x900e, 0x2001, 0x0003, 0x080c, 0x9375, 0x2208, 0x0804, - 0x35b5, 0x7033, 0x0001, 0x7122, 0x7024, 0x9300, 0x7026, 0x2061, - 0x18b8, 0x2c44, 0xa06b, 0x0000, 0xa37a, 0x7028, 0xa076, 0x7034, - 0xa072, 0xa48e, 0xa592, 0xa696, 0xa79a, 0x080c, 0x10f8, 0x7007, - 0x0002, 0x701f, 0x514c, 0x0005, 0x7030, 0x9005, 0x1178, 0x7120, - 0x7028, 0x20a0, 0x901e, 0x7034, 0x20e8, 0x2061, 0x18b8, 0x2c44, - 0xa48c, 0xa590, 0xa694, 0xa798, 0x0804, 0x510a, 0x7224, 0x900e, - 0x2001, 0x0003, 0x080c, 0x9375, 0x2208, 0x0804, 0x35b5, 0x00f6, - 0x00e6, 0x080c, 0x57e9, 0x2009, 0x0007, 0x1904, 0x51df, 0x2071, - 0x189e, 0x745c, 0x84ff, 0x2009, 0x000e, 0x1904, 0x51df, 0xac9c, - 0xad98, 0xaea4, 0xafa0, 0x0096, 0x080c, 0x1027, 0x2009, 0x0002, - 0x0904, 0x51df, 0x2900, 0x705e, 0x900e, 0x901e, 0x7356, 0x7362, - 0xa860, 0x7066, 0xa85c, 0x9080, 0x0003, 0x705a, 0x20a0, 0x91d8, - 0x1000, 0x2b5c, 0x8bff, 0x0178, 0x080c, 0x6aa3, 0x0118, 0x080c, - 0x6aab, 0x1148, 0xb814, 0x20a9, 0x0001, 0x4004, 0xb810, 0x4004, - 0x4104, 0x9398, 0x0003, 0x8108, 0x9182, 0x0800, 0x0120, 0x9386, - 0x003c, 0x01e8, 0x0c20, 0x83ff, 0x11c0, 0x7254, 0x900e, 0x2001, - 0x0003, 0x080c, 0x9375, 0x2208, 0x009e, 0xa897, 0x4000, 0xa99a, - 0x715c, 0x81ff, 0x090c, 0x0dc5, 0x2148, 0x080c, 0x1040, 0x9006, - 0x705e, 0x918d, 0x0001, 0x2008, 0x0418, 0x7063, 0x0001, 0x7152, - 0x7054, 0x9300, 0x7056, 0x2061, 0x18b9, 0x2c44, 0xa37a, 0x7058, - 0xa076, 0x7064, 0xa072, 0xa48e, 0xa592, 0xa696, 0xa79a, 0xa09f, - 0x51eb, 0x000e, 0xa0a2, 0x080c, 0x10f8, 0x9006, 0x0048, 0x009e, - 0xa897, 0x4005, 0xa99a, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, - 0x00ee, 0x00fe, 0x0005, 0x00f6, 0xa0a0, 0x904d, 0x090c, 0x0dc5, - 0x00e6, 0x2071, 0x189e, 0xa06c, 0x908e, 0x0100, 0x0138, 0xa87b, - 0x0030, 0xa883, 0x0000, 0xa897, 0x4002, 0x00d8, 0x7060, 0x9005, - 0x1158, 0x7150, 0x7058, 0x20a0, 0x901e, 0x7064, 0x20e8, 0xa48c, - 0xa590, 0xa694, 0xa798, 0x0428, 0xa87b, 0x0000, 0xa883, 0x0000, - 0xa897, 0x4000, 0x7254, 0x900e, 0x2001, 0x0003, 0x080c, 0x9375, - 0xaa9a, 0x715c, 0x81ff, 0x090c, 0x0dc5, 0x2148, 0x080c, 0x1040, - 0x705f, 0x0000, 0xa0a0, 0x2048, 0x0126, 0x2091, 0x8000, 0x080c, - 0x6e9f, 0x012e, 0xa09f, 0x0000, 0xa0a3, 0x0000, 0x00ee, 0x00fe, - 0x0005, 0x91d8, 0x1000, 0x2b5c, 0x8bff, 0x0178, 0x080c, 0x6aa3, - 0x0118, 0x080c, 0x6aab, 0x1148, 0xb814, 0x20a9, 0x0001, 0x4004, - 0xb810, 0x4004, 0x4104, 0x9398, 0x0003, 0x8108, 0x9182, 0x0800, - 0x0120, 0x9386, 0x003c, 0x0518, 0x0c20, 0x83ff, 0x11f0, 0x7154, - 0x810c, 0xa99a, 0xa897, 0x4000, 0x715c, 0x81ff, 0x090c, 0x0dc5, - 0x2148, 0x080c, 0x1040, 0x9006, 0x705e, 0x918d, 0x0001, 0x2008, - 0xa0a0, 0x2048, 0x0126, 0x2091, 0x8000, 0x080c, 0x6e9f, 0x012e, - 0xa09f, 0x0000, 0xa0a3, 0x0000, 0x0070, 0x7063, 0x0001, 0x7152, - 0x7054, 0x9300, 0x7056, 0xa37a, 0xa48e, 0xa592, 0xa696, 0xa79a, - 0x080c, 0x10f8, 0x9006, 0x00ee, 0x0005, 0x0096, 0xa88c, 0x90be, - 0x7000, 0x0148, 0x90be, 0x7100, 0x0130, 0x90be, 0x7200, 0x0118, - 0x009e, 0x0804, 0x35ea, 0xa884, 0xa988, 0x080c, 0x2873, 0x1518, - 0x080c, 0x66b9, 0x1500, 0x7126, 0xbe12, 0xbd16, 0xae7c, 0x080c, - 0x4be4, 0x01c8, 0x080c, 0x4be4, 0x01b0, 0x009e, 0xa867, 0x0000, - 0xa868, 0xc0fd, 0xa86a, 0xa823, 0x0000, 0xa804, 0x2048, 0x080c, - 0xd284, 0x1120, 0x2009, 0x0003, 0x0804, 0x35e7, 0x7007, 0x0003, - 0x701f, 0x52b8, 0x0005, 0x009e, 0x2009, 0x0002, 0x0804, 0x35e7, - 0x7124, 0x080c, 0x334c, 0xa820, 0x9086, 0x8001, 0x1120, 0x2009, - 0x0004, 0x0804, 0x35e7, 0x2900, 0x7022, 0xa804, 0x0096, 0x2048, - 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x009e, - 0x9080, 0x0002, 0x0076, 0x0006, 0x2098, 0x20a0, 0x27e0, 0x27e8, - 0x20a9, 0x002a, 0x080c, 0x0f8b, 0xaa6c, 0xab70, 0xac74, 0xad78, - 0x2061, 0x18b8, 0x2c44, 0xa06b, 0x0000, 0xae64, 0xaf8c, 0x97c6, - 0x7000, 0x0118, 0x97c6, 0x7100, 0x1148, 0x96c2, 0x0004, 0x0600, - 0x2009, 0x0004, 0x000e, 0x007e, 0x0804, 0x4c30, 0x97c6, 0x7200, - 0x11b8, 0x96c2, 0x0054, 0x02a0, 0x000e, 0x007e, 0x2061, 0x18b8, - 0x2c44, 0xa076, 0xa772, 0xa07b, 0x002a, 0xa28e, 0xa392, 0xa496, - 0xa59a, 0x080c, 0x10f8, 0x7007, 0x0002, 0x701f, 0x5314, 0x0005, - 0x000e, 0x007e, 0x0804, 0x35ea, 0x7020, 0x2048, 0xa804, 0x2048, - 0xa804, 0x2048, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, - 0xffc0, 0x9080, 0x0002, 0x2098, 0x20a0, 0x27e0, 0x27e8, 0x20a9, - 0x002a, 0x080c, 0x0f8b, 0x2100, 0x2238, 0x2061, 0x18b8, 0x2c44, - 0xa28c, 0xa390, 0xa494, 0xa598, 0x2009, 0x002a, 0x0804, 0x4c30, - 0x81ff, 0x1904, 0x35e7, 0x798c, 0x2001, 0x197e, 0x918c, 0x8000, - 0x2102, 0x080c, 0x4bfb, 0x0904, 0x35ea, 0x080c, 0x6aa3, 0x0120, - 0x080c, 0x6aab, 0x1904, 0x35ea, 0x080c, 0x67eb, 0x0904, 0x35e7, - 0x0126, 0x2091, 0x8000, 0x080c, 0x68b1, 0x012e, 0x0904, 0x35e7, - 0x2001, 0x197e, 0x2004, 0xd0fc, 0x1904, 0x35b5, 0x0804, 0x460c, - 0xa9a0, 0x2001, 0x197e, 0x918c, 0x8000, 0xc18d, 0x2102, 0x080c, - 0x4c08, 0x01a0, 0x080c, 0x6aa3, 0x0118, 0x080c, 0x6aab, 0x1170, - 0x080c, 0x67eb, 0x2009, 0x0002, 0x0128, 0x080c, 0x68b1, 0x1170, - 0x2009, 0x0003, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, - 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, 0x4000, - 0x2001, 0x197e, 0x2004, 0xd0fc, 0x1128, 0x080c, 0x57dd, 0x0110, - 0x9006, 0x0018, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x0005, - 0x78a8, 0xd08c, 0x1118, 0xd084, 0x0904, 0x4581, 0x080c, 0x4c17, - 0x0904, 0x35ea, 0x080c, 0x4be4, 0x1120, 0x2009, 0x0002, 0x0804, - 0x35e7, 0x080c, 0x6aa3, 0x0130, 0x908e, 0x0004, 0x0118, 0x908e, - 0x0005, 0x15a0, 0x78a8, 0xd08c, 0x0120, 0xb800, 0xc08c, 0xb802, - 0x0028, 0x080c, 0x57d5, 0xd0b4, 0x0904, 0x45bb, 0x7884, 0x908e, - 0x007e, 0x0904, 0x45bb, 0x908e, 0x007f, 0x0904, 0x45bb, 0x908e, - 0x0080, 0x0904, 0x45bb, 0xb800, 0xd08c, 0x1904, 0x45bb, 0xa867, - 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x080c, 0xd2a3, 0x1120, 0x2009, - 0x0003, 0x0804, 0x35e7, 0x7007, 0x0003, 0x701f, 0x53e0, 0x0005, - 0x080c, 0x4c17, 0x0904, 0x35ea, 0x0804, 0x45bb, 0x080c, 0x33a5, - 0x0108, 0x0005, 0x2009, 0x1834, 0x210c, 0x81ff, 0x0120, 0x2009, - 0x0001, 0x0804, 0x35e7, 0x080c, 0x57e9, 0x0120, 0x2009, 0x0007, - 0x0804, 0x35e7, 0x080c, 0x6a9b, 0x0120, 0x2009, 0x0008, 0x0804, - 0x35e7, 0xb89c, 0xd0a4, 0x1118, 0xd0ac, 0x1904, 0x45bb, 0x9006, - 0xa866, 0xa832, 0xa868, 0xc0fd, 0xa86a, 0x080c, 0xd302, 0x1120, - 0x2009, 0x0003, 0x0804, 0x35e7, 0x7007, 0x0003, 0x701f, 0x5419, - 0x0005, 0xa830, 0x9086, 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, - 0x5729, 0x080c, 0x4c17, 0x0904, 0x35ea, 0x0804, 0x53b2, 0x81ff, - 0x2009, 0x0001, 0x1904, 0x35e7, 0x080c, 0x57e9, 0x2009, 0x0007, - 0x1904, 0x35e7, 0x080c, 0x6a9b, 0x0120, 0x2009, 0x0008, 0x0804, - 0x35e7, 0x080c, 0x4c17, 0x0904, 0x35ea, 0x080c, 0x6aa3, 0x2009, - 0x0009, 0x1904, 0x35e7, 0x080c, 0x4be4, 0x2009, 0x0002, 0x0904, - 0x35e7, 0x9006, 0xa866, 0xa832, 0xa868, 0xc0fd, 0xa86a, 0x7988, - 0xa95a, 0x9194, 0xfd00, 0x918c, 0x00ff, 0x9006, 0x82ff, 0x1128, - 0xc0ed, 0xa952, 0x798c, 0xa956, 0x0038, 0x928e, 0x0100, 0x1904, - 0x35ea, 0xc0e5, 0xa952, 0xa956, 0xa83e, 0x080c, 0xd555, 0x2009, - 0x0003, 0x0904, 0x35e7, 0x7007, 0x0003, 0x701f, 0x5470, 0x0005, - 0xa830, 0x9086, 0x0100, 0x2009, 0x0004, 0x0904, 0x35e7, 0x0804, - 0x35b5, 0x7aa8, 0x9284, 0xc000, 0x0148, 0xd2ec, 0x01a0, 0x080c, - 0x57e9, 0x1188, 0x2009, 0x0014, 0x0804, 0x35e7, 0xd2dc, 0x1578, - 0x81ff, 0x2009, 0x0001, 0x1904, 0x35e7, 0x080c, 0x57e9, 0x2009, - 0x0007, 0x1904, 0x35e7, 0xd2f4, 0x0138, 0x9284, 0x5000, 0xc0d5, - 0x080c, 0x57af, 0x0804, 0x35b5, 0xd2fc, 0x0160, 0x080c, 0x4c17, - 0x0904, 0x35ea, 0x7984, 0x9284, 0x9000, 0xc0d5, 0x080c, 0x5784, - 0x0804, 0x35b5, 0x080c, 0x4c17, 0x0904, 0x35ea, 0xb804, 0x9084, - 0x00ff, 0x9086, 0x0006, 0x2009, 0x0009, 0x1904, 0x555f, 0x080c, - 0x4be4, 0x2009, 0x0002, 0x0904, 0x555f, 0xa85c, 0x9080, 0x001b, - 0xaf60, 0x2009, 0x0008, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x080c, - 0x4c2d, 0x701f, 0x54cc, 0x0005, 0xa86c, 0x9086, 0x0500, 0x1138, - 0xa870, 0x9005, 0x1120, 0xa874, 0x9084, 0xff00, 0x0110, 0x1904, - 0x35ea, 0xa866, 0xa832, 0xa868, 0xc0fd, 0xa86a, 0x080c, 0x4c17, - 0x1110, 0x0804, 0x35ea, 0x2009, 0x0043, 0x080c, 0xd5c1, 0x2009, - 0x0003, 0x0904, 0x555f, 0x7007, 0x0003, 0x701f, 0x54f0, 0x0005, - 0xa830, 0x9086, 0x0100, 0x2009, 0x0004, 0x0904, 0x555f, 0x7984, - 0x7aa8, 0x9284, 0x1000, 0xc0d5, 0x080c, 0x5784, 0x0804, 0x35b5, - 0x00c6, 0xaab0, 0x9284, 0xc000, 0x0148, 0xd2ec, 0x0170, 0x080c, - 0x57e9, 0x1158, 0x2009, 0x0014, 0x0804, 0x554e, 0x2061, 0x1800, - 0x080c, 0x57e9, 0x2009, 0x0007, 0x15c8, 0xd2f4, 0x0130, 0x9284, - 0x5000, 0xc0d5, 0x080c, 0x57af, 0x0058, 0xd2fc, 0x0180, 0x080c, - 0x4c15, 0x0590, 0xa998, 0x9284, 0x9000, 0xc0d5, 0x080c, 0x5784, - 0xa87b, 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, 0x0438, 0x080c, - 0x4c15, 0x0510, 0x080c, 0x6aa3, 0x2009, 0x0009, 0x11b8, 0xa8c4, - 0x9086, 0x0500, 0x11c8, 0xa8c8, 0x9005, 0x11b0, 0xa8cc, 0x9084, - 0xff00, 0x1190, 0x080c, 0x4c15, 0x1108, 0x0070, 0x2009, 0x004b, - 0x080c, 0xd5c1, 0x2009, 0x0003, 0x0108, 0x0078, 0x0431, 0x19c0, - 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, - 0x0001, 0x2001, 0x0030, 0x00ce, 0x0005, 0x9006, 0x0ce0, 0x7aa8, - 0xd2dc, 0x0904, 0x35e7, 0x0016, 0x7984, 0x9284, 0x1000, 0xc0fd, - 0x080c, 0x5784, 0x001e, 0x1904, 0x35e7, 0x0804, 0x35b5, 0x00f6, - 0x2d78, 0xaab0, 0x0021, 0x00fe, 0x0005, 0xaab0, 0xc2d5, 0xd2dc, - 0x0150, 0x0016, 0xa998, 0x9284, 0x1400, 0xc0fd, 0x080c, 0x5784, - 0x001e, 0x9085, 0x0001, 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001, - 0x0804, 0x35e7, 0x080c, 0x57e9, 0x0120, 0x2009, 0x0007, 0x0804, - 0x35e7, 0x7984, 0x7ea8, 0x96b4, 0x00ff, 0x080c, 0x6724, 0x1904, - 0x35ea, 0x9186, 0x007f, 0x0138, 0x080c, 0x6aa3, 0x0120, 0x2009, - 0x0009, 0x0804, 0x35e7, 0x080c, 0x4be4, 0x1120, 0x2009, 0x0002, - 0x0804, 0x35e7, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x2001, - 0x0100, 0x8007, 0xa80a, 0x080c, 0xd2bd, 0x1120, 0x2009, 0x0003, - 0x0804, 0x35e7, 0x7007, 0x0003, 0x701f, 0x55bf, 0x0005, 0xa808, - 0x8007, 0x9086, 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x35e7, - 0xa8e0, 0xa866, 0xa810, 0x8007, 0x9084, 0x00ff, 0x800c, 0xa814, - 0x8007, 0x9084, 0x00ff, 0x8004, 0x9080, 0x0002, 0x9108, 0x8906, - 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0004, - 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x0804, 0x4c30, 0x080c, 0x4be4, - 0x1120, 0x2009, 0x0002, 0x0804, 0x35e7, 0x7984, 0x9194, 0xff00, - 0x918c, 0x00ff, 0x8217, 0x82ff, 0x1118, 0x7023, 0x19b4, 0x0040, - 0x92c6, 0x0001, 0x1118, 0x7023, 0x19ce, 0x0010, 0x0804, 0x35ea, - 0x2009, 0x001a, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0xa85c, 0x9080, - 0x0019, 0xaf60, 0x080c, 0x4c2d, 0x701f, 0x560f, 0x0005, 0x2001, - 0x182e, 0x2003, 0x0001, 0xa85c, 0x9080, 0x0019, 0x2098, 0xa860, - 0x20e0, 0x20a9, 0x001a, 0x7020, 0x20a0, 0x20e9, 0x0001, 0x4003, - 0x0804, 0x35b5, 0x080c, 0x4be4, 0x1120, 0x2009, 0x0002, 0x0804, - 0x35e7, 0x7984, 0x9194, 0xff00, 0x918c, 0x00ff, 0x8217, 0x82ff, - 0x1118, 0x2099, 0x19b4, 0x0040, 0x92c6, 0x0001, 0x1118, 0x2099, - 0x19ce, 0x0010, 0x0804, 0x35ea, 0xa85c, 0x9080, 0x0019, 0x20a0, - 0xa860, 0x20e8, 0x20a9, 0x001a, 0x20e1, 0x0001, 0x4003, 0x2009, - 0x001a, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0xa85c, 0x9080, 0x0019, - 0xaf60, 0x0804, 0x4c30, 0x7884, 0x908a, 0x1000, 0x1a04, 0x35ea, - 0x0126, 0x2091, 0x8000, 0x8003, 0x800b, 0x810b, 0x9108, 0x00c6, - 0x2061, 0x19fb, 0x614a, 0x00ce, 0x012e, 0x0804, 0x35b5, 0x00c6, - 0x080c, 0x7637, 0x1160, 0x080c, 0x7932, 0x080c, 0x612e, 0x9085, - 0x0001, 0x080c, 0x767b, 0x080c, 0x7563, 0x080c, 0x0dc5, 0x2061, - 0x1800, 0x6030, 0xc09d, 0x6032, 0x080c, 0x5fed, 0x00ce, 0x0005, - 0x00c6, 0x2001, 0x1800, 0x2004, 0x908e, 0x0000, 0x0904, 0x35e7, - 0x7884, 0x9005, 0x0188, 0x7888, 0x2061, 0x199c, 0x2c0c, 0x2062, - 0x080c, 0x2c49, 0x01a0, 0x080c, 0x2c51, 0x0188, 0x080c, 0x2c59, - 0x0170, 0x2162, 0x0804, 0x35ea, 0x2061, 0x0100, 0x6038, 0x9086, - 0x0007, 0x1118, 0x2009, 0x0001, 0x0010, 0x2009, 0x0000, 0x7884, - 0x9086, 0x0002, 0x1568, 0x2061, 0x0100, 0x6028, 0xc09c, 0x602a, - 0x0026, 0x2011, 0x0003, 0x080c, 0xaabf, 0x2011, 0x0002, 0x080c, - 0xaac9, 0x002e, 0x080c, 0xa9d3, 0x0036, 0x901e, 0x080c, 0xaa49, - 0x003e, 0x60e3, 0x0000, 0x080c, 0xf07f, 0x080c, 0xf09a, 0x9085, - 0x0001, 0x080c, 0x767b, 0x9006, 0x080c, 0x2d39, 0x2001, 0x1800, - 0x2003, 0x0004, 0x2001, 0x19a8, 0x2003, 0x0000, 0x6027, 0x0008, - 0x00ce, 0x0804, 0x35b5, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, - 0x35e7, 0x080c, 0x57e9, 0x0120, 0x2009, 0x0007, 0x0804, 0x35e7, - 0x7984, 0x7ea8, 0x96b4, 0x00ff, 0x080c, 0x6724, 0x1904, 0x35ea, - 0x9186, 0x007f, 0x0138, 0x080c, 0x6aa3, 0x0120, 0x2009, 0x0009, - 0x0804, 0x35e7, 0x080c, 0x4be4, 0x1120, 0x2009, 0x0002, 0x0804, - 0x35e7, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x080c, 0xd2c0, - 0x1120, 0x2009, 0x0003, 0x0804, 0x35e7, 0x7007, 0x0003, 0x701f, - 0x5712, 0x0005, 0xa830, 0x9086, 0x0100, 0x1120, 0x2009, 0x0004, - 0x0804, 0x35e7, 0xa8e0, 0xa866, 0xa834, 0x8007, 0x800c, 0xa85c, - 0x9080, 0x000c, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0xaf60, 0x0804, - 0x4c30, 0xa898, 0x9086, 0x000d, 0x1904, 0x35e7, 0x2021, 0x4005, - 0x0126, 0x2091, 0x8000, 0x0e04, 0x5736, 0x0010, 0x012e, 0x0cc0, - 0x7c36, 0x9486, 0x4000, 0x0118, 0x7833, 0x0011, 0x0010, 0x7833, - 0x0010, 0x7883, 0x4005, 0xa998, 0x7986, 0xa9a4, 0x799a, 0xa9a8, - 0x799e, 0x080c, 0x4c20, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, - 0xd084, 0x190c, 0x11aa, 0x7007, 0x0001, 0x2091, 0x5000, 0x700f, - 0x0000, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x00c6, 0x2061, - 0x19fb, 0x7984, 0x615a, 0x6156, 0x605f, 0x0000, 0x6053, 0x0009, - 0x7898, 0x6072, 0x789c, 0x606e, 0x7888, 0x606a, 0x788c, 0x6066, - 0x2001, 0x1a0b, 0x2044, 0x2001, 0x1a12, 0xa076, 0xa060, 0xa072, - 0xa07b, 0x0001, 0xa07f, 0x0002, 0xa06b, 0x0000, 0xa09f, 0x0000, - 0x00ce, 0x012e, 0x0804, 0x35b5, 0x0126, 0x2091, 0x8000, 0x00b6, - 0x00c6, 0x90e4, 0xc000, 0x0168, 0x0006, 0xd0d4, 0x0130, 0x0036, - 0x2019, 0x0029, 0x080c, 0x336a, 0x003e, 0x080c, 0xd125, 0x000e, - 0x1198, 0xd0e4, 0x0160, 0x9180, 0x1000, 0x2004, 0x905d, 0x0160, - 0x080c, 0x6148, 0x080c, 0xb23d, 0x0110, 0xb817, 0x0000, 0x9006, - 0x00ce, 0x00be, 0x012e, 0x0005, 0x9085, 0x0001, 0x0cc8, 0x0126, - 0x2091, 0x8000, 0x0156, 0x2010, 0x900e, 0x20a9, 0x0800, 0x0016, - 0x9180, 0x1000, 0x2004, 0x9005, 0x0188, 0x9186, 0x007e, 0x0170, - 0x9186, 0x007f, 0x0158, 0x9186, 0x0080, 0x0140, 0x9186, 0x00ff, - 0x0128, 0x0026, 0x2200, 0x080c, 0x5784, 0x002e, 0x001e, 0x8108, - 0x1f04, 0x57b7, 0x015e, 0x012e, 0x0005, 0x2001, 0x1848, 0x2004, - 0x0005, 0x2001, 0x1867, 0x2004, 0x0005, 0x0006, 0x2001, 0x1810, - 0x2004, 0xd0d4, 0x000e, 0x0005, 0x2001, 0x180e, 0x2004, 0xd0b4, - 0x0005, 0x2001, 0x1800, 0x2004, 0x9086, 0x0003, 0x0005, 0x0016, - 0x00e6, 0x2071, 0x189e, 0x7108, 0x910d, 0x710a, 0x00ee, 0x001e, - 0x0005, 0x79a4, 0x81ff, 0x0904, 0x35ea, 0x9182, 0x0081, 0x1a04, - 0x35ea, 0x810c, 0x0016, 0x080c, 0x4be4, 0x0170, 0x080c, 0x0f16, - 0x2100, 0x2238, 0x7d84, 0x7c88, 0x7b8c, 0x7a90, 0x001e, 0x080c, - 0x4c2d, 0x701f, 0x5819, 0x0005, 0x001e, 0x2009, 0x0002, 0x0804, - 0x35e7, 0x2079, 0x0000, 0x7d94, 0x7c98, 0x7ba8, 0x7aac, 0x79a4, - 0x810c, 0x2061, 0x18b8, 0x2c44, 0xa770, 0xa074, 0x2071, 0x189e, - 0x080c, 0x4c30, 0x701f, 0x582d, 0x0005, 0x2061, 0x18b8, 0x2c44, - 0x0016, 0x0026, 0xa270, 0xa174, 0x080c, 0x0f1e, 0x002e, 0x001e, - 0x080c, 0x0fcb, 0x9006, 0xa802, 0xa806, 0x0804, 0x35b5, 0x0126, - 0x0156, 0x0136, 0x0146, 0x01c6, 0x01d6, 0x00c6, 0x00d6, 0x00e6, - 0x00f6, 0x2061, 0x0100, 0x2069, 0x0200, 0x2071, 0x1800, 0x6044, - 0xd0a4, 0x11e8, 0xd084, 0x0118, 0x080c, 0x59ed, 0x0068, 0xd08c, - 0x0118, 0x080c, 0x58f6, 0x0040, 0xd094, 0x0118, 0x080c, 0x58c6, - 0x0018, 0xd09c, 0x0108, 0x0099, 0x00fe, 0x00ee, 0x00de, 0x00ce, - 0x01de, 0x01ce, 0x014e, 0x013e, 0x015e, 0x012e, 0x0005, 0x0016, - 0x6128, 0xd19c, 0x1110, 0xc19d, 0x612a, 0x001e, 0x0c68, 0x7030, - 0xd09c, 0x1120, 0x6004, 0x9085, 0x0002, 0x6006, 0x7098, 0x9005, - 0x0120, 0x709b, 0x0000, 0x7093, 0x0000, 0x624c, 0x9286, 0xf0f0, - 0x1150, 0x6048, 0x9086, 0xf0f0, 0x0130, 0x624a, 0x6043, 0x0090, - 0x6043, 0x0010, 0x0490, 0x9294, 0xff00, 0x9296, 0xf700, 0x0178, - 0x7138, 0xd1a4, 0x1160, 0x6240, 0x9295, 0x0100, 0x6242, 0x9294, - 0x0010, 0x0128, 0x2009, 0x00f7, 0x080c, 0x60aa, 0x00f0, 0x6040, - 0x9084, 0x0010, 0x9085, 0x0140, 0x6042, 0x6043, 0x0000, 0x7087, - 0x0000, 0x70a3, 0x0001, 0x70c7, 0x0000, 0x70df, 0x0000, 0x2009, - 0x1c80, 0x200b, 0x0000, 0x7097, 0x0000, 0x708b, 0x000f, 0x2009, - 0x000f, 0x2011, 0x5f90, 0x080c, 0x88d5, 0x0005, 0x2001, 0x1869, - 0x2004, 0xd08c, 0x0110, 0x705f, 0xffff, 0x7088, 0x9005, 0x1528, - 0x2011, 0x5f90, 0x080c, 0x883d, 0x6040, 0x9094, 0x0010, 0x9285, - 0x0020, 0x6042, 0x20a9, 0x00c8, 0x6044, 0xd08c, 0x1168, 0x1f04, - 0x58dc, 0x6242, 0x709b, 0x0000, 0x6040, 0x9094, 0x0010, 0x9285, - 0x0080, 0x6042, 0x6242, 0x0048, 0x6242, 0x709b, 0x0000, 0x708f, - 0x0000, 0x9006, 0x080c, 0x6133, 0x0000, 0x0005, 0x708c, 0x908a, - 0x0003, 0x1a0c, 0x0dc5, 0x000b, 0x0005, 0x5900, 0x5951, 0x59ec, - 0x00f6, 0x0016, 0x6900, 0x918c, 0x0800, 0x708f, 0x0001, 0x2001, - 0x015d, 0x2003, 0x0000, 0x6803, 0x00fc, 0x20a9, 0x0004, 0x6800, - 0x9084, 0x00fc, 0x0120, 0x1f04, 0x590f, 0x080c, 0x0dc5, 0x68a0, - 0x68a2, 0x689c, 0x689e, 0x6898, 0x689a, 0xa001, 0x918d, 0x1600, - 0x6902, 0x001e, 0x6837, 0x0020, 0x080c, 0x610f, 0x2079, 0x1c00, - 0x7833, 0x1101, 0x7837, 0x0000, 0x20e1, 0x0001, 0x2099, 0x1805, - 0x20e9, 0x0001, 0x20a1, 0x1c0e, 0x20a9, 0x0004, 0x4003, 0x080c, - 0xaf8e, 0x20e1, 0x0001, 0x2099, 0x1c00, 0x20e9, 0x0000, 0x20a1, - 0x0240, 0x20a9, 0x0014, 0x4003, 0x60c3, 0x000c, 0x600f, 0x0000, - 0x080c, 0x5fc1, 0x00fe, 0x9006, 0x7092, 0x6043, 0x0008, 0x6042, - 0x0005, 0x00f6, 0x7090, 0x7093, 0x0000, 0x9025, 0x0904, 0x59c9, - 0x6020, 0xd0b4, 0x1904, 0x59c7, 0x71a0, 0x81ff, 0x0904, 0x59b5, - 0x9486, 0x000c, 0x1904, 0x59c2, 0x9480, 0x0018, 0x8004, 0x20a8, - 0x080c, 0x6108, 0x2011, 0x0260, 0x2019, 0x1c00, 0x220c, 0x2304, - 0x9106, 0x11e8, 0x8210, 0x8318, 0x1f04, 0x596e, 0x6043, 0x0004, - 0x2061, 0x0140, 0x605b, 0xbc94, 0x605f, 0xf0f0, 0x2061, 0x0100, - 0x6043, 0x0006, 0x708f, 0x0002, 0x709b, 0x0002, 0x2009, 0x07d0, - 0x2011, 0x5f97, 0x080c, 0x88d5, 0x080c, 0x610f, 0x04c0, 0x080c, - 0x6108, 0x2079, 0x0260, 0x7930, 0x918e, 0x1101, 0x1558, 0x7834, - 0x9005, 0x1540, 0x7900, 0x918c, 0x00ff, 0x1118, 0x7804, 0x9005, - 0x0190, 0x080c, 0x6108, 0x2011, 0x026e, 0x2019, 0x1805, 0x20a9, - 0x0004, 0x220c, 0x2304, 0x9102, 0x0230, 0x11a0, 0x8210, 0x8318, - 0x1f04, 0x59a9, 0x0078, 0x70a3, 0x0000, 0x080c, 0x6108, 0x20e1, - 0x0000, 0x2099, 0x0260, 0x20e9, 0x0001, 0x20a1, 0x1c00, 0x20a9, - 0x0014, 0x4003, 0x6043, 0x0008, 0x6043, 0x0000, 0x0010, 0x00fe, - 0x0005, 0x6040, 0x9085, 0x0100, 0x6042, 0x6020, 0xd0b4, 0x1db8, - 0x080c, 0xaf8e, 0x20e1, 0x0001, 0x2099, 0x1c00, 0x20e9, 0x0000, - 0x20a1, 0x0240, 0x20a9, 0x0014, 0x4003, 0x60c3, 0x000c, 0x2011, - 0x19f2, 0x2013, 0x0000, 0x7093, 0x0000, 0x60a3, 0x0056, 0x60a7, - 0x9575, 0x080c, 0xa6e0, 0x08d8, 0x0005, 0x7098, 0x908a, 0x001d, - 0x1a0c, 0x0dc5, 0x000b, 0x0005, 0x5a1e, 0x5a31, 0x5a5a, 0x5a7a, - 0x5aa0, 0x5acf, 0x5af5, 0x5b2d, 0x5b53, 0x5b81, 0x5bbc, 0x5bf4, - 0x5c12, 0x5c3d, 0x5c5f, 0x5c7a, 0x5c84, 0x5cb8, 0x5cde, 0x5d0d, - 0x5d33, 0x5d6b, 0x5daf, 0x5dec, 0x5e0d, 0x5e66, 0x5e88, 0x5eb6, - 0x5eb6, 0x00c6, 0x2061, 0x1800, 0x6003, 0x0007, 0x2061, 0x0100, - 0x6004, 0x9084, 0xfff9, 0x6006, 0x00ce, 0x0005, 0x2061, 0x0140, - 0x605b, 0xbc94, 0x605f, 0xf0f0, 0x2061, 0x0100, 0x6043, 0x0002, - 0x709b, 0x0001, 0x2009, 0x07d0, 0x2011, 0x5f97, 0x080c, 0x88d5, - 0x0005, 0x00f6, 0x7090, 0x9086, 0x0014, 0x1510, 0x6042, 0x6020, - 0xd0b4, 0x11f0, 0x080c, 0x6108, 0x2079, 0x0260, 0x7a30, 0x9296, - 0x1102, 0x11a0, 0x7834, 0x9005, 0x1188, 0x7a38, 0xd2fc, 0x0128, - 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, 0x2011, 0x5f97, 0x080c, - 0x883d, 0x709b, 0x0010, 0x080c, 0x5c84, 0x0010, 0x7093, 0x0000, - 0x00fe, 0x0005, 0x00f6, 0x709b, 0x0003, 0x6043, 0x0004, 0x2011, - 0x5f97, 0x080c, 0x883d, 0x080c, 0x608c, 0x2079, 0x0240, 0x7833, - 0x1102, 0x7837, 0x0000, 0x20a9, 0x0008, 0x9f88, 0x000e, 0x200b, - 0x0000, 0x8108, 0x1f04, 0x5a6f, 0x60c3, 0x0014, 0x080c, 0x5fc1, - 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, 0x0500, 0x2011, 0x5f97, - 0x080c, 0x883d, 0x9086, 0x0014, 0x11b8, 0x080c, 0x6108, 0x2079, - 0x0260, 0x7a30, 0x9296, 0x1102, 0x1178, 0x7834, 0x9005, 0x1160, - 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, - 0x709b, 0x0004, 0x0029, 0x0010, 0x080c, 0x60e4, 0x00fe, 0x0005, - 0x00f6, 0x709b, 0x0005, 0x080c, 0x608c, 0x2079, 0x0240, 0x7833, - 0x1103, 0x7837, 0x0000, 0x080c, 0x6108, 0x080c, 0x60eb, 0x1170, - 0x7084, 0x9005, 0x1158, 0x715c, 0x9186, 0xffff, 0x0138, 0x2011, - 0x0008, 0x080c, 0x5f44, 0x0168, 0x080c, 0x60c1, 0x20a9, 0x0008, - 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, - 0x4003, 0x60c3, 0x0014, 0x080c, 0x5fc1, 0x00fe, 0x0005, 0x00f6, - 0x7090, 0x9005, 0x0500, 0x2011, 0x5f97, 0x080c, 0x883d, 0x9086, - 0x0014, 0x11b8, 0x080c, 0x6108, 0x2079, 0x0260, 0x7a30, 0x9296, - 0x1103, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, - 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, 0x709b, 0x0006, 0x0029, - 0x0010, 0x080c, 0x60e4, 0x00fe, 0x0005, 0x00f6, 0x709b, 0x0007, - 0x080c, 0x608c, 0x2079, 0x0240, 0x7833, 0x1104, 0x7837, 0x0000, - 0x080c, 0x6108, 0x080c, 0x60eb, 0x11b8, 0x7084, 0x9005, 0x11a0, - 0x7164, 0x9186, 0xffff, 0x0180, 0x9180, 0x33b6, 0x200d, 0x918c, - 0xff00, 0x810f, 0x2011, 0x0008, 0x080c, 0x5f44, 0x0180, 0x080c, - 0x50d1, 0x0110, 0x080c, 0x28dc, 0x20a9, 0x0008, 0x20e1, 0x0000, - 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, - 0x0014, 0x080c, 0x5fc1, 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, - 0x0500, 0x2011, 0x5f97, 0x080c, 0x883d, 0x9086, 0x0014, 0x11b8, - 0x080c, 0x6108, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1104, 0x1178, - 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, - 0x1110, 0x70c7, 0x0001, 0x709b, 0x0008, 0x0029, 0x0010, 0x080c, - 0x60e4, 0x00fe, 0x0005, 0x00f6, 0x709b, 0x0009, 0x080c, 0x608c, - 0x2079, 0x0240, 0x7833, 0x1105, 0x7837, 0x0100, 0x080c, 0x60eb, - 0x1150, 0x7084, 0x9005, 0x1138, 0x080c, 0x5eb7, 0x1188, 0x9085, - 0x0001, 0x080c, 0x28dc, 0x20a9, 0x0008, 0x080c, 0x6108, 0x20e1, - 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, - 0x60c3, 0x0014, 0x080c, 0x5fc1, 0x0010, 0x080c, 0x5a11, 0x00fe, - 0x0005, 0x00f6, 0x7090, 0x9005, 0x05a8, 0x2011, 0x5f97, 0x080c, - 0x883d, 0x9086, 0x0014, 0x1560, 0x080c, 0x6108, 0x2079, 0x0260, - 0x7a30, 0x9296, 0x1105, 0x1520, 0x7834, 0x9084, 0x0100, 0x2011, - 0x0100, 0x921e, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, - 0x1110, 0x70c7, 0x0001, 0x709b, 0x000a, 0x00b1, 0x0098, 0x9005, - 0x1178, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, - 0x0001, 0x7097, 0x0000, 0x709b, 0x000e, 0x080c, 0x5c5f, 0x0010, - 0x080c, 0x60e4, 0x00fe, 0x0005, 0x00f6, 0x709b, 0x000b, 0x2011, - 0x1c0e, 0x20e9, 0x0001, 0x22a0, 0x20a9, 0x0040, 0x2019, 0xffff, - 0x4304, 0x080c, 0x608c, 0x2079, 0x0240, 0x7833, 0x1106, 0x7837, - 0x0000, 0x080c, 0x60eb, 0x0118, 0x2013, 0x0000, 0x0020, 0x7060, - 0x9085, 0x0100, 0x2012, 0x20a9, 0x0040, 0x2009, 0x024e, 0x2011, - 0x1c0e, 0x220e, 0x8210, 0x8108, 0x9186, 0x0260, 0x1128, 0x6810, - 0x8000, 0x6812, 0x2009, 0x0240, 0x1f04, 0x5be1, 0x60c3, 0x0084, - 0x080c, 0x5fc1, 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, 0x01c0, - 0x2011, 0x5f97, 0x080c, 0x883d, 0x9086, 0x0084, 0x1178, 0x080c, - 0x6108, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1106, 0x1138, 0x7834, - 0x9005, 0x1120, 0x709b, 0x000c, 0x0029, 0x0010, 0x080c, 0x60e4, - 0x00fe, 0x0005, 0x00f6, 0x709b, 0x000d, 0x080c, 0x608c, 0x2079, - 0x0240, 0x7833, 0x1107, 0x7837, 0x0000, 0x080c, 0x6108, 0x20a9, - 0x0040, 0x2011, 0x026e, 0x2009, 0x024e, 0x220e, 0x8210, 0x8108, - 0x9186, 0x0260, 0x1150, 0x6810, 0x8000, 0x6812, 0x2009, 0x0240, - 0x6814, 0x8000, 0x6816, 0x2011, 0x0260, 0x1f04, 0x5c25, 0x60c3, - 0x0084, 0x080c, 0x5fc1, 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, - 0x01e0, 0x2011, 0x5f97, 0x080c, 0x883d, 0x9086, 0x0084, 0x1198, - 0x080c, 0x6108, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1107, 0x1158, - 0x7834, 0x9005, 0x1140, 0x7097, 0x0001, 0x080c, 0x605e, 0x709b, - 0x000e, 0x0029, 0x0010, 0x080c, 0x60e4, 0x00fe, 0x0005, 0x918d, - 0x0001, 0x080c, 0x6133, 0x709b, 0x000f, 0x7093, 0x0000, 0x2061, - 0x0140, 0x605b, 0xbc85, 0x605f, 0xb5b5, 0x2061, 0x0100, 0x6043, - 0x0005, 0x6043, 0x0004, 0x2009, 0x07d0, 0x2011, 0x5f97, 0x080c, - 0x8831, 0x0005, 0x7090, 0x9005, 0x0130, 0x2011, 0x5f97, 0x080c, - 0x883d, 0x709b, 0x0000, 0x0005, 0x709b, 0x0011, 0x080c, 0xaf8e, - 0x080c, 0x6108, 0x20e1, 0x0000, 0x2099, 0x0260, 0x20e9, 0x0000, - 0x20a1, 0x0240, 0x7490, 0x9480, 0x0018, 0x9080, 0x0007, 0x9084, - 0x03f8, 0x8004, 0x20a8, 0x4003, 0x080c, 0x60eb, 0x11a0, 0x717c, - 0x81ff, 0x0188, 0x900e, 0x7080, 0x9084, 0x00ff, 0x0160, 0x080c, - 0x2873, 0x9186, 0x007e, 0x0138, 0x9186, 0x0080, 0x0120, 0x2011, - 0x0008, 0x080c, 0x5f44, 0x60c3, 0x0014, 0x080c, 0x5fc1, 0x0005, - 0x00f6, 0x7090, 0x9005, 0x0500, 0x2011, 0x5f97, 0x080c, 0x883d, - 0x9086, 0x0014, 0x11b8, 0x080c, 0x6108, 0x2079, 0x0260, 0x7a30, - 0x9296, 0x1103, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, - 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, 0x709b, 0x0012, - 0x0029, 0x0010, 0x7093, 0x0000, 0x00fe, 0x0005, 0x00f6, 0x709b, - 0x0013, 0x080c, 0x609a, 0x2079, 0x0240, 0x7833, 0x1103, 0x7837, - 0x0000, 0x080c, 0x6108, 0x080c, 0x60eb, 0x1170, 0x7084, 0x9005, - 0x1158, 0x715c, 0x9186, 0xffff, 0x0138, 0x2011, 0x0008, 0x080c, - 0x5f44, 0x0168, 0x080c, 0x60c1, 0x20a9, 0x0008, 0x20e1, 0x0000, - 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, - 0x0014, 0x080c, 0x5fc1, 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, - 0x0500, 0x2011, 0x5f97, 0x080c, 0x883d, 0x9086, 0x0014, 0x11b8, - 0x080c, 0x6108, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1104, 0x1178, - 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, - 0x1110, 0x70c7, 0x0001, 0x709b, 0x0014, 0x0029, 0x0010, 0x7093, - 0x0000, 0x00fe, 0x0005, 0x00f6, 0x709b, 0x0015, 0x080c, 0x609a, - 0x2079, 0x0240, 0x7833, 0x1104, 0x7837, 0x0000, 0x080c, 0x6108, - 0x080c, 0x60eb, 0x11b8, 0x7084, 0x9005, 0x11a0, 0x7164, 0x9186, - 0xffff, 0x0180, 0x9180, 0x33b6, 0x200d, 0x918c, 0xff00, 0x810f, - 0x2011, 0x0008, 0x080c, 0x5f44, 0x0180, 0x080c, 0x50d1, 0x0110, - 0x080c, 0x28dc, 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, - 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, - 0x5fc1, 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, 0x05f0, 0x2011, - 0x5f97, 0x080c, 0x883d, 0x9086, 0x0014, 0x15a8, 0x080c, 0x6108, - 0x2079, 0x0260, 0x7a30, 0x9296, 0x1105, 0x1568, 0x7834, 0x9084, - 0x0100, 0x2011, 0x0100, 0x921e, 0x1168, 0x9085, 0x0001, 0x080c, - 0x6133, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, - 0x0001, 0x0080, 0x9005, 0x11b8, 0x7a38, 0xd2fc, 0x0128, 0x70c4, - 0x9005, 0x1110, 0x70c7, 0x0001, 0x9085, 0x0001, 0x080c, 0x6133, - 0x7097, 0x0000, 0x7a38, 0xd2f4, 0x0110, 0x70df, 0x0008, 0x709b, - 0x0016, 0x0029, 0x0010, 0x7093, 0x0000, 0x00fe, 0x0005, 0x080c, - 0xaf8e, 0x080c, 0x6108, 0x20e1, 0x0000, 0x2099, 0x0260, 0x20e9, - 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000e, 0x4003, 0x2011, 0x026d, - 0x2204, 0x9084, 0x0100, 0x2011, 0x024d, 0x2012, 0x2011, 0x026e, - 0x709b, 0x0017, 0x080c, 0x60eb, 0x1150, 0x7084, 0x9005, 0x1138, - 0x080c, 0x5eb7, 0x1188, 0x9085, 0x0001, 0x080c, 0x28dc, 0x20a9, - 0x0008, 0x080c, 0x6108, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, - 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x5fc1, - 0x0010, 0x080c, 0x5a11, 0x0005, 0x00f6, 0x7090, 0x9005, 0x01d8, - 0x2011, 0x5f97, 0x080c, 0x883d, 0x9086, 0x0084, 0x1190, 0x080c, - 0x6108, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1106, 0x1150, 0x7834, - 0x9005, 0x1138, 0x9006, 0x080c, 0x6133, 0x709b, 0x0018, 0x0029, - 0x0010, 0x7093, 0x0000, 0x00fe, 0x0005, 0x00f6, 0x709b, 0x0019, - 0x080c, 0x609a, 0x2079, 0x0240, 0x7833, 0x1106, 0x7837, 0x0000, - 0x080c, 0x6108, 0x2009, 0x026e, 0x2039, 0x1c0e, 0x20a9, 0x0040, - 0x213e, 0x8738, 0x8108, 0x9186, 0x0280, 0x1128, 0x6814, 0x8000, - 0x6816, 0x2009, 0x0260, 0x1f04, 0x5e20, 0x2039, 0x1c0e, 0x080c, - 0x60eb, 0x11e8, 0x2728, 0x2514, 0x8207, 0x9084, 0x00ff, 0x8000, - 0x2018, 0x9294, 0x00ff, 0x8007, 0x9205, 0x202a, 0x7060, 0x2310, - 0x8214, 0x92a0, 0x1c0e, 0x2414, 0x938c, 0x0001, 0x0118, 0x9294, - 0xff00, 0x0018, 0x9294, 0x00ff, 0x8007, 0x9215, 0x2222, 0x20a9, - 0x0040, 0x2009, 0x024e, 0x270e, 0x8738, 0x8108, 0x9186, 0x0260, - 0x1128, 0x6810, 0x8000, 0x6812, 0x2009, 0x0240, 0x1f04, 0x5e53, - 0x60c3, 0x0084, 0x080c, 0x5fc1, 0x00fe, 0x0005, 0x00f6, 0x7090, - 0x9005, 0x01e0, 0x2011, 0x5f97, 0x080c, 0x883d, 0x9086, 0x0084, - 0x1198, 0x080c, 0x6108, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1107, - 0x1158, 0x7834, 0x9005, 0x1140, 0x7097, 0x0001, 0x080c, 0x605e, - 0x709b, 0x001a, 0x0029, 0x0010, 0x7093, 0x0000, 0x00fe, 0x0005, - 0x9085, 0x0001, 0x080c, 0x6133, 0x709b, 0x001b, 0x080c, 0xaf8e, - 0x080c, 0x6108, 0x2011, 0x0260, 0x2009, 0x0240, 0x7490, 0x9480, - 0x0018, 0x9080, 0x0007, 0x9084, 0x03f8, 0x8004, 0x20a8, 0x220e, - 0x8210, 0x8108, 0x9186, 0x0260, 0x1150, 0x6810, 0x8000, 0x6812, - 0x2009, 0x0240, 0x6814, 0x8000, 0x6816, 0x2011, 0x0260, 0x1f04, - 0x5e9f, 0x60c3, 0x0084, 0x080c, 0x5fc1, 0x0005, 0x0005, 0x0086, - 0x0096, 0x2029, 0x1848, 0x252c, 0x20a9, 0x0008, 0x2041, 0x1c0e, - 0x20e9, 0x0001, 0x28a0, 0x080c, 0x6108, 0x20e1, 0x0000, 0x2099, - 0x026e, 0x4003, 0x20a9, 0x0008, 0x2011, 0x0007, 0xd5d4, 0x0108, - 0x9016, 0x2800, 0x9200, 0x200c, 0x91a6, 0xffff, 0x1148, 0xd5d4, - 0x0110, 0x8210, 0x0008, 0x8211, 0x1f04, 0x5ed1, 0x0804, 0x5f40, - 0x82ff, 0x1160, 0xd5d4, 0x0120, 0x91a6, 0x3fff, 0x0d90, 0x0020, - 0x91a6, 0x3fff, 0x0904, 0x5f40, 0x918d, 0xc000, 0x20a9, 0x0010, - 0x2019, 0x0001, 0xd5d4, 0x0110, 0x2019, 0x0010, 0x2120, 0xd5d4, - 0x0110, 0x8423, 0x0008, 0x8424, 0x1240, 0xd5d4, 0x0110, 0x8319, - 0x0008, 0x8318, 0x1f04, 0x5ef7, 0x04d8, 0x23a8, 0x2021, 0x0001, - 0x8426, 0x8425, 0x1f04, 0x5f09, 0x2328, 0x8529, 0x92be, 0x0007, - 0x0158, 0x0006, 0x2039, 0x0007, 0x2200, 0x973a, 0x000e, 0x27a8, - 0x95a8, 0x0010, 0x1f04, 0x5f18, 0x755e, 0x95c8, 0x33b6, 0x292d, - 0x95ac, 0x00ff, 0x7582, 0x6532, 0x6536, 0x0016, 0x2508, 0x080c, - 0x28bc, 0x001e, 0x60e7, 0x0000, 0x65ea, 0x2018, 0x2304, 0x9405, - 0x201a, 0x7087, 0x0001, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x20e1, - 0x0001, 0x2898, 0x20a9, 0x0008, 0x4003, 0x9085, 0x0001, 0x0008, - 0x9006, 0x009e, 0x008e, 0x0005, 0x0156, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x22a8, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, - 0x2011, 0x024e, 0x22a0, 0x4003, 0x014e, 0x013e, 0x01de, 0x01ce, - 0x015e, 0x2118, 0x9026, 0x2001, 0x0007, 0x939a, 0x0010, 0x0218, - 0x8420, 0x8001, 0x0cd0, 0x2118, 0x84ff, 0x0120, 0x939a, 0x0010, - 0x8421, 0x1de0, 0x2021, 0x0001, 0x83ff, 0x0118, 0x8423, 0x8319, - 0x1de8, 0x9238, 0x2029, 0x026e, 0x9528, 0x2504, 0x942c, 0x11b8, - 0x9405, 0x203a, 0x715e, 0x91a0, 0x33b6, 0x242d, 0x95ac, 0x00ff, - 0x7582, 0x6532, 0x6536, 0x0016, 0x2508, 0x080c, 0x28bc, 0x001e, - 0x60e7, 0x0000, 0x65ea, 0x7087, 0x0001, 0x9084, 0x0000, 0x0005, - 0x00e6, 0x2071, 0x1800, 0x708b, 0x0000, 0x00ee, 0x0005, 0x00e6, - 0x00f6, 0x2079, 0x0100, 0x2071, 0x0140, 0x080c, 0x604d, 0x080c, - 0xa6e9, 0x7004, 0x9084, 0x4000, 0x0110, 0x080c, 0x2d49, 0x0126, - 0x2091, 0x8000, 0x2071, 0x1826, 0x2073, 0x0000, 0x7840, 0x0026, - 0x0016, 0x2009, 0x00f7, 0x080c, 0x60aa, 0x001e, 0x9094, 0x0010, - 0x9285, 0x0080, 0x7842, 0x7a42, 0x002e, 0x012e, 0x00fe, 0x00ee, - 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x2bce, 0x0228, 0x2011, - 0x0101, 0x2204, 0xc0c5, 0x2012, 0x2011, 0x19f2, 0x2013, 0x0000, - 0x7093, 0x0000, 0x012e, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, - 0xa6e0, 0x6144, 0xd184, 0x0120, 0x7198, 0x918d, 0x2000, 0x0018, - 0x718c, 0x918d, 0x1000, 0x2011, 0x1999, 0x2112, 0x2009, 0x07d0, - 0x2011, 0x5f97, 0x080c, 0x88d5, 0x0005, 0x0016, 0x0026, 0x00c6, - 0x0126, 0x2091, 0x8000, 0x080c, 0xb244, 0x2009, 0x00f7, 0x080c, - 0x60aa, 0x2061, 0x19fb, 0x900e, 0x611a, 0x611e, 0x617a, 0x617e, - 0x2061, 0x1800, 0x6003, 0x0001, 0x2061, 0x0100, 0x6043, 0x0090, - 0x6043, 0x0010, 0x2009, 0x1999, 0x200b, 0x0000, 0x2009, 0x002d, - 0x2011, 0x6019, 0x080c, 0x8831, 0x012e, 0x00ce, 0x002e, 0x001e, - 0x0005, 0x00e6, 0x0006, 0x0126, 0x2091, 0x8000, 0x0471, 0x2071, - 0x0100, 0x080c, 0xa6e9, 0x2071, 0x0140, 0x7004, 0x9084, 0x4000, - 0x0110, 0x080c, 0x2d49, 0x080c, 0x763f, 0x0188, 0x080c, 0x765a, - 0x1170, 0x080c, 0x793c, 0x0016, 0x080c, 0x298b, 0x2001, 0x196d, - 0x2102, 0x001e, 0x080c, 0x7937, 0x080c, 0x7563, 0x0050, 0x2009, - 0x0001, 0x080c, 0x2c67, 0x2001, 0x0001, 0x080c, 0x281c, 0x080c, - 0x5fed, 0x012e, 0x000e, 0x00ee, 0x0005, 0x2001, 0x180e, 0x2004, - 0xd0bc, 0x0158, 0x0026, 0x0036, 0x2011, 0x8017, 0x2001, 0x1999, - 0x201c, 0x080c, 0x4c44, 0x003e, 0x002e, 0x0005, 0x20a9, 0x0012, - 0x20e9, 0x0001, 0x20a1, 0x1c80, 0x080c, 0x6108, 0x20e9, 0x0000, - 0x2099, 0x026e, 0x0099, 0x20a9, 0x0020, 0x080c, 0x6102, 0x2099, - 0x0260, 0x20a1, 0x1c92, 0x0051, 0x20a9, 0x000e, 0x080c, 0x6105, - 0x2099, 0x0260, 0x20a1, 0x1cb2, 0x0009, 0x0005, 0x0016, 0x0026, - 0x3410, 0x3308, 0x2104, 0x8007, 0x2012, 0x8108, 0x8210, 0x1f04, - 0x6082, 0x002e, 0x001e, 0x0005, 0x080c, 0xaf8e, 0x20e1, 0x0001, - 0x2099, 0x1c00, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000c, - 0x4003, 0x0005, 0x080c, 0xaf8e, 0x080c, 0x6108, 0x20e1, 0x0000, - 0x2099, 0x0260, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000c, - 0x4003, 0x0005, 0x00c6, 0x0006, 0x2061, 0x0100, 0x810f, 0x2001, - 0x1834, 0x2004, 0x9005, 0x1138, 0x2001, 0x1818, 0x2004, 0x9084, - 0x00ff, 0x9105, 0x0010, 0x9185, 0x00f7, 0x604a, 0x000e, 0x00ce, - 0x0005, 0x0016, 0x0046, 0x080c, 0x6a9f, 0x0158, 0x9006, 0x2020, - 0x2009, 0x002a, 0x080c, 0xec31, 0x2001, 0x180c, 0x200c, 0xc195, - 0x2102, 0x2019, 0x002a, 0x900e, 0x080c, 0x321b, 0x080c, 0xd7e3, - 0x0140, 0x0036, 0x2019, 0xffff, 0x2021, 0x0007, 0x080c, 0x4dfb, - 0x003e, 0x004e, 0x001e, 0x0005, 0x080c, 0x5fed, 0x709b, 0x0000, - 0x7093, 0x0000, 0x0005, 0x0006, 0x2001, 0x180c, 0x2004, 0xd09c, - 0x0100, 0x000e, 0x0005, 0x0006, 0x0016, 0x0126, 0x2091, 0x8000, - 0x2001, 0x0101, 0x200c, 0x918d, 0x0006, 0x2102, 0x012e, 0x001e, - 0x000e, 0x0005, 0x2009, 0x0001, 0x0020, 0x2009, 0x0002, 0x0008, - 0x900e, 0x6814, 0x9084, 0xffc0, 0x910d, 0x6916, 0x0005, 0x00f6, - 0x0156, 0x0146, 0x01d6, 0x9006, 0x20a9, 0x0080, 0x20e9, 0x0001, - 0x20a1, 0x1c00, 0x4004, 0x2079, 0x1c00, 0x7803, 0x2200, 0x7807, - 0x00ef, 0x780f, 0x00ef, 0x7813, 0x0138, 0x7823, 0xffff, 0x7827, - 0xffff, 0x01de, 0x014e, 0x015e, 0x00fe, 0x0005, 0x2001, 0x1800, - 0x2003, 0x0001, 0x0005, 0x2001, 0x19a7, 0x0118, 0x2003, 0x0001, - 0x0010, 0x2003, 0x0000, 0x0005, 0x0156, 0x20a9, 0x0800, 0x2009, - 0x1000, 0x9006, 0x200a, 0x8108, 0x1f04, 0x6142, 0x015e, 0x0005, - 0x00d6, 0x0036, 0x0156, 0x0136, 0x0146, 0x2069, 0x1847, 0x9006, - 0xb802, 0xb8ce, 0xb807, 0x0707, 0xb80a, 0xb80e, 0xb812, 0x9198, - 0x33b6, 0x231d, 0x939c, 0x00ff, 0xbb16, 0x0016, 0x0026, 0xb8c2, - 0x080c, 0xb23d, 0x1120, 0x9192, 0x007e, 0x1208, 0xbbc2, 0x20a9, - 0x0004, 0xb8c4, 0x20e8, 0xb9c8, 0x9198, 0x0006, 0x9006, 0x23a0, - 0x4004, 0x20a9, 0x0004, 0x9198, 0x000a, 0x23a0, 0x4004, 0x002e, - 0x001e, 0xb83e, 0xb842, 0xb84e, 0xb852, 0xb856, 0xb85a, 0xb85e, - 0xb862, 0xb866, 0xb86a, 0xb86f, 0x0100, 0xb872, 0xb876, 0xb87a, - 0xb88a, 0xb88e, 0xb893, 0x0008, 0xb896, 0xb89a, 0xb89e, 0xb8be, - 0xb9a2, 0x0096, 0xb8a4, 0x904d, 0x0110, 0x080c, 0x1040, 0xb8a7, - 0x0000, 0x009e, 0x9006, 0xb84a, 0x6810, 0xb83a, 0x680c, 0xb846, - 0xb8bb, 0x0520, 0xb8ac, 0x9005, 0x0198, 0x00c6, 0x2060, 0x9c82, - 0x1cd0, 0x0a0c, 0x0dc5, 0x2001, 0x181a, 0x2004, 0x9c02, 0x1a0c, - 0x0dc5, 0x080c, 0x8cf7, 0x00ce, 0x090c, 0x9096, 0xb8af, 0x0000, - 0x6814, 0x9084, 0x00ff, 0xb842, 0x014e, 0x013e, 0x015e, 0x003e, - 0x00de, 0x0005, 0x0126, 0x2091, 0x8000, 0xa974, 0xae78, 0x9684, - 0x3fff, 0x9082, 0x4000, 0x1a04, 0x6230, 0x9182, 0x0800, 0x1a04, - 0x6234, 0x2001, 0x180c, 0x2004, 0x9084, 0x0003, 0x1904, 0x623a, - 0x9188, 0x1000, 0x2104, 0x905d, 0x0518, 0xb804, 0x9084, 0x00ff, - 0x908e, 0x0006, 0x1508, 0xb8a4, 0x900d, 0x1904, 0x624c, 0xb850, - 0x900d, 0x1148, 0xa802, 0x2900, 0xb852, 0xb84e, 0x080c, 0x951c, - 0x9006, 0x012e, 0x0005, 0x00a6, 0x2150, 0x2900, 0xb002, 0xa803, - 0x0000, 0x00ae, 0xb852, 0x0c90, 0x2001, 0x0005, 0x900e, 0x04b8, - 0x2001, 0x0028, 0x900e, 0x0498, 0x9082, 0x0006, 0x1290, 0x080c, - 0xb23d, 0x1160, 0xb8a0, 0x9084, 0xff80, 0x1140, 0xb900, 0xd1fc, - 0x0990, 0x2001, 0x0029, 0x2009, 0x1000, 0x0408, 0x2001, 0x0028, - 0x00a8, 0x2009, 0x180c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, - 0x0068, 0xd184, 0x0118, 0x2001, 0x0004, 0x0040, 0x2001, 0x0029, - 0xb900, 0xd1fc, 0x0118, 0x2009, 0x1000, 0x0048, 0x900e, 0x0038, - 0x2001, 0x0029, 0x900e, 0x0018, 0x2001, 0x0029, 0x900e, 0x9005, - 0x012e, 0x0005, 0x2001, 0x180c, 0x2004, 0xd084, 0x19d0, 0x9188, - 0x1000, 0x2104, 0x905d, 0x09a8, 0x080c, 0x6aa3, 0x1990, 0xb800, - 0xd0bc, 0x0978, 0x0804, 0x61e3, 0x080c, 0x68c0, 0x0904, 0x61fc, - 0x0804, 0x61e7, 0x00b6, 0x00e6, 0x0126, 0x2091, 0x8000, 0xa874, - 0x908e, 0x00ff, 0x1120, 0x2001, 0x196b, 0x205c, 0x0060, 0xa974, - 0x9182, 0x0800, 0x1690, 0x9188, 0x1000, 0x2104, 0x905d, 0x01d0, - 0x080c, 0x6a43, 0x11d0, 0x080c, 0xb27d, 0x0570, 0x2b00, 0x6012, - 0x2900, 0x6016, 0x6023, 0x0009, 0x600b, 0x0000, 0xa874, 0x908e, - 0x00ff, 0x1110, 0x600b, 0x8000, 0x2009, 0x0043, 0x080c, 0xb352, - 0x9006, 0x00b0, 0x2001, 0x0028, 0x0090, 0x2009, 0x180c, 0x210c, - 0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, 0x2001, - 0x0004, 0x0010, 0x2001, 0x0029, 0x0010, 0x2001, 0x0029, 0x9005, - 0x012e, 0x00ee, 0x00be, 0x0005, 0x2001, 0x002c, 0x0cc0, 0x00b6, - 0x00e6, 0x0126, 0x2091, 0x8000, 0xa974, 0x9182, 0x0800, 0x1a04, - 0x631d, 0x9188, 0x1000, 0x2104, 0x905d, 0x0904, 0x62f5, 0xb8a0, - 0x9086, 0x007f, 0x0190, 0xa87c, 0xd0fc, 0x1178, 0x080c, 0x6aab, - 0x0160, 0xa994, 0x81ff, 0x0130, 0x908e, 0x0004, 0x0130, 0x908e, - 0x0005, 0x0118, 0x080c, 0x6aa3, 0x1598, 0xa87c, 0xd0fc, 0x01e0, - 0xa894, 0x9005, 0x01c8, 0x2060, 0x0026, 0x2010, 0x080c, 0xd0c6, - 0x002e, 0x1120, 0x2001, 0x0008, 0x0804, 0x631f, 0x6020, 0x9086, - 0x000a, 0x0120, 0x2001, 0x0008, 0x0804, 0x631f, 0x601a, 0x6003, - 0x0008, 0x2900, 0x6016, 0x0058, 0x080c, 0xb27d, 0x05e8, 0x2b00, - 0x6012, 0x2900, 0x6016, 0x600b, 0xffff, 0x6023, 0x000a, 0x2009, - 0x0003, 0x080c, 0xb352, 0x9006, 0x0458, 0x2001, 0x0028, 0x0438, - 0x9082, 0x0006, 0x1290, 0x080c, 0xb23d, 0x1160, 0xb8a0, 0x9084, - 0xff80, 0x1140, 0xb900, 0xd1fc, 0x0900, 0x2001, 0x0029, 0x2009, - 0x1000, 0x00a8, 0x2001, 0x0028, 0x0090, 0x2009, 0x180c, 0x210c, - 0xd18c, 0x0118, 0x2001, 0x0004, 0x0050, 0xd184, 0x0118, 0x2001, - 0x0004, 0x0028, 0x2001, 0x0029, 0x0010, 0x2001, 0x0029, 0x9005, - 0x012e, 0x00ee, 0x00be, 0x0005, 0x2001, 0x002c, 0x0cc0, 0x00f6, - 0x00b6, 0x0126, 0x2091, 0x8000, 0xa8e0, 0x9005, 0x1550, 0xa8dc, - 0x9082, 0x0101, 0x1630, 0xa8c8, 0x9005, 0x1518, 0xa8c4, 0x9082, - 0x0101, 0x12f8, 0xa974, 0x2079, 0x1800, 0x9182, 0x0800, 0x12e8, - 0x7830, 0x9084, 0x0003, 0x1130, 0xaa98, 0xab94, 0xa878, 0x9084, - 0x0007, 0x00ea, 0x7930, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, - 0xd184, 0x0118, 0x2001, 0x0004, 0x0010, 0x2001, 0x0029, 0x900e, - 0x0038, 0x2001, 0x002c, 0x900e, 0x0018, 0x2001, 0x0029, 0x900e, - 0x9006, 0x0008, 0x9005, 0x012e, 0x00be, 0x00fe, 0x0005, 0x63b4, - 0x636f, 0x6386, 0x63b4, 0x63b4, 0x63b4, 0x63b4, 0x63b4, 0x2100, - 0x9082, 0x007e, 0x1278, 0x080c, 0x66b9, 0x0148, 0x9046, 0xb810, - 0x9306, 0x1904, 0x63bc, 0xb814, 0x9206, 0x15f0, 0x0028, 0xbb12, - 0xba16, 0x0010, 0x080c, 0x4af7, 0x0150, 0x04b0, 0x080c, 0x6724, - 0x1598, 0xb810, 0x9306, 0x1580, 0xb814, 0x9206, 0x1568, 0x080c, - 0xb27d, 0x0530, 0x2b00, 0x6012, 0x080c, 0xd554, 0x2900, 0x6016, - 0x600b, 0xffff, 0x6023, 0x000a, 0xa878, 0x9086, 0x0001, 0x1170, - 0x080c, 0x3250, 0x9006, 0x080c, 0x6656, 0x2001, 0x0002, 0x080c, - 0x666a, 0x2001, 0x0200, 0xb86e, 0xb893, 0x0002, 0x2009, 0x0003, - 0x080c, 0xb352, 0x9006, 0x0068, 0x2001, 0x0001, 0x900e, 0x0038, - 0x2001, 0x002c, 0x900e, 0x0018, 0x2001, 0x0028, 0x900e, 0x9005, - 0x0000, 0x012e, 0x00be, 0x00fe, 0x0005, 0x00b6, 0x00f6, 0x00e6, - 0x0126, 0x2091, 0x8000, 0xa894, 0x90c6, 0x0015, 0x0904, 0x65a7, - 0x90c6, 0x0056, 0x0904, 0x65ab, 0x90c6, 0x0066, 0x0904, 0x65af, - 0x90c6, 0x0067, 0x0904, 0x65b3, 0x90c6, 0x0068, 0x0904, 0x65b7, - 0x90c6, 0x0071, 0x0904, 0x65bb, 0x90c6, 0x0074, 0x0904, 0x65bf, - 0x90c6, 0x007c, 0x0904, 0x65c3, 0x90c6, 0x007e, 0x0904, 0x65c7, - 0x90c6, 0x0037, 0x0904, 0x65cb, 0x9016, 0x2079, 0x1800, 0xa974, - 0x9186, 0x00ff, 0x0904, 0x65a2, 0x9182, 0x0800, 0x1a04, 0x65a2, - 0x080c, 0x6724, 0x1198, 0xb804, 0x9084, 0x00ff, 0x9082, 0x0006, - 0x1268, 0xa894, 0x90c6, 0x006f, 0x0148, 0x080c, 0xb23d, 0x1904, - 0x658b, 0xb8a0, 0x9084, 0xff80, 0x1904, 0x658b, 0xa894, 0x90c6, - 0x006f, 0x0158, 0x90c6, 0x005e, 0x0904, 0x64eb, 0x90c6, 0x0064, - 0x0904, 0x6514, 0x2008, 0x0804, 0x64ad, 0xa998, 0xa8b0, 0x2040, - 0x080c, 0xb23d, 0x1120, 0x9182, 0x007f, 0x0a04, 0x64ad, 0x9186, - 0x00ff, 0x0904, 0x64ad, 0x9182, 0x0800, 0x1a04, 0x64ad, 0xaaa0, - 0xab9c, 0x787c, 0x9306, 0x11a8, 0x7880, 0x0096, 0x924e, 0x1128, - 0x2208, 0x2310, 0x009e, 0x0804, 0x64ad, 0x080c, 0xb23d, 0x1140, - 0x99cc, 0xff00, 0x009e, 0x1128, 0x2208, 0x2310, 0x0804, 0x64ad, - 0x009e, 0x080c, 0x4af7, 0x0904, 0x64b7, 0x900e, 0x9016, 0x90c6, - 0x4000, 0x15e0, 0x0006, 0x080c, 0x6944, 0x1108, 0xc185, 0xb800, - 0xd0bc, 0x0108, 0xc18d, 0x20a9, 0x0004, 0xa860, 0x20e8, 0xa85c, - 0x9080, 0x0031, 0x20a0, 0xb8c4, 0x20e0, 0xb8c8, 0x9080, 0x0006, - 0x2098, 0x080c, 0x0f8b, 0x20a9, 0x0004, 0xa860, 0x20e8, 0xa85c, - 0x9080, 0x0035, 0x20a0, 0xb8c4, 0x20e0, 0xb8c8, 0x9080, 0x000a, - 0x2098, 0x080c, 0x0f8b, 0xa8c4, 0xabc8, 0x9305, 0xabcc, 0x9305, - 0xabd0, 0x9305, 0xabd4, 0x9305, 0xabd8, 0x9305, 0xabdc, 0x9305, - 0xabe0, 0x9305, 0x9005, 0x0510, 0x000e, 0x00c8, 0x90c6, 0x4007, - 0x1110, 0x2408, 0x00a0, 0x90c6, 0x4008, 0x1118, 0x2708, 0x2610, - 0x0070, 0x90c6, 0x4009, 0x1108, 0x0050, 0x90c6, 0x4006, 0x0138, - 0x2001, 0x4005, 0x2009, 0x000a, 0x0010, 0x2001, 0x4006, 0xa896, - 0xa99a, 0xaa9e, 0x2001, 0x0030, 0x900e, 0x0478, 0x000e, 0x080c, - 0xb27d, 0x1130, 0x2001, 0x4005, 0x2009, 0x0003, 0x9016, 0x0c78, - 0x2b00, 0x6012, 0x080c, 0xd554, 0x2900, 0x6016, 0x6023, 0x0001, - 0xa868, 0xd88c, 0x0108, 0xc0f5, 0xa86a, 0x0126, 0x2091, 0x8000, - 0x080c, 0x3250, 0x012e, 0x9006, 0x080c, 0x6656, 0x2001, 0x0002, - 0x080c, 0x666a, 0x2009, 0x0002, 0x080c, 0xb352, 0xa8b0, 0xd094, - 0x0118, 0xb8cc, 0xc08d, 0xb8ce, 0x9006, 0x9005, 0x012e, 0x00ee, - 0x00fe, 0x00be, 0x0005, 0x080c, 0x57e9, 0x0118, 0x2009, 0x0007, - 0x00f8, 0xa998, 0xaeb0, 0x080c, 0x6724, 0x1904, 0x64a8, 0x9186, - 0x007f, 0x0130, 0x080c, 0x6aa3, 0x0118, 0x2009, 0x0009, 0x0080, - 0x0096, 0x080c, 0x100e, 0x1120, 0x009e, 0x2009, 0x0002, 0x0040, - 0x2900, 0x009e, 0xa806, 0x080c, 0xd2c0, 0x19b0, 0x2009, 0x0003, - 0x2001, 0x4005, 0x0804, 0x64af, 0xa998, 0xaeb0, 0x080c, 0x6724, - 0x1904, 0x64a8, 0x0096, 0x080c, 0x100e, 0x1128, 0x009e, 0x2009, - 0x0002, 0x0804, 0x6568, 0x2900, 0x009e, 0xa806, 0x0096, 0x2048, - 0x20a9, 0x002b, 0xb8c4, 0x20e0, 0xb8c8, 0x2098, 0xa860, 0x20e8, - 0xa85c, 0x9080, 0x0002, 0x20a0, 0x4003, 0x20a9, 0x0008, 0x9080, - 0x0006, 0x20a0, 0xbbc8, 0x9398, 0x0006, 0x2398, 0x080c, 0x0f8b, - 0x009e, 0xa87b, 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, 0xd684, - 0x1168, 0x080c, 0x57d5, 0xd0b4, 0x1118, 0xa89b, 0x000b, 0x00e0, - 0xb800, 0xd08c, 0x0118, 0xa89b, 0x000c, 0x00b0, 0x080c, 0x6aa3, - 0x0118, 0xa89b, 0x0009, 0x0080, 0x080c, 0x57e9, 0x0118, 0xa89b, - 0x0007, 0x0050, 0x080c, 0xd2a3, 0x1904, 0x64e4, 0x2009, 0x0003, - 0x2001, 0x4005, 0x0804, 0x64af, 0xa87b, 0x0030, 0xa897, 0x4005, - 0xa804, 0x8006, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, - 0x9080, 0x0002, 0x2009, 0x002b, 0xaaa0, 0xab9c, 0xaca8, 0xada4, - 0x2031, 0x0000, 0x2041, 0x1252, 0x080c, 0xb7f1, 0x1904, 0x64e4, - 0x2009, 0x0002, 0x08e8, 0x2001, 0x0028, 0x900e, 0x0804, 0x64e5, - 0x2009, 0x180c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, - 0xd184, 0x0118, 0x2001, 0x0004, 0x0010, 0x2001, 0x0029, 0x900e, - 0x0804, 0x64e5, 0x2001, 0x0029, 0x900e, 0x0804, 0x64e5, 0x080c, - 0x37e9, 0x0804, 0x64e6, 0x080c, 0x5500, 0x0804, 0x64e6, 0x080c, - 0x4637, 0x0804, 0x64e6, 0x080c, 0x46b0, 0x0804, 0x64e6, 0x080c, - 0x470c, 0x0804, 0x64e6, 0x080c, 0x4bba, 0x0804, 0x64e6, 0x080c, - 0x4e82, 0x0804, 0x64e6, 0x080c, 0x5167, 0x0804, 0x64e6, 0x080c, - 0x5360, 0x0804, 0x64e6, 0x080c, 0x3a25, 0x0804, 0x64e6, 0x00b6, - 0xa974, 0xae78, 0x9684, 0x3fff, 0x9082, 0x4000, 0x1618, 0x9182, - 0x0800, 0x1268, 0x9188, 0x1000, 0x2104, 0x905d, 0x0140, 0x080c, - 0x6aa3, 0x1148, 0x00e9, 0x080c, 0x684f, 0x9006, 0x00b0, 0x2001, - 0x0028, 0x900e, 0x0090, 0x9082, 0x0006, 0x1240, 0xb900, 0xd1fc, - 0x0d88, 0x2001, 0x0029, 0x2009, 0x1000, 0x0038, 0x2001, 0x0029, - 0x900e, 0x0018, 0x2001, 0x0029, 0x900e, 0x9005, 0x00be, 0x0005, - 0x0126, 0x2091, 0x8000, 0xb850, 0x900d, 0x0150, 0x2900, 0x0096, - 0x2148, 0xa802, 0x009e, 0xa803, 0x0000, 0xb852, 0x012e, 0x0005, - 0x2900, 0xb852, 0xb84e, 0xa803, 0x0000, 0x0cc0, 0x0126, 0x2091, - 0x8000, 0xb84c, 0x9005, 0x0170, 0x00e6, 0x2071, 0x19e8, 0x7004, - 0x9086, 0x0002, 0x0168, 0x00ee, 0xb84c, 0xa802, 0x2900, 0xb84e, - 0x012e, 0x0005, 0x2900, 0xb852, 0xb84e, 0xa803, 0x0000, 0x0cc0, - 0x701c, 0x9b06, 0x1d80, 0xb84c, 0x00a6, 0x2050, 0xb000, 0xa802, - 0x2900, 0xb002, 0x00ae, 0x00ee, 0x012e, 0x0005, 0x0126, 0x2091, - 0x8000, 0xb84c, 0x904d, 0x0130, 0xa800, 0x9005, 0x1108, 0xb852, - 0xb84e, 0x9905, 0x012e, 0x0005, 0xb84c, 0x904d, 0x0130, 0xa800, - 0x9005, 0x1108, 0xb852, 0xb84e, 0x9905, 0x0005, 0x00b6, 0x0126, - 0x00c6, 0x0026, 0x2091, 0x8000, 0x6210, 0x2258, 0xba00, 0x9005, - 0x0110, 0xc285, 0x0008, 0xc284, 0xba02, 0x002e, 0x00ce, 0x012e, - 0x00be, 0x0005, 0x00b6, 0x0126, 0x00c6, 0x2091, 0x8000, 0x6210, - 0x2258, 0xba04, 0x0006, 0x9086, 0x0006, 0x1170, 0xb89c, 0xd0ac, - 0x0158, 0x080c, 0x6a9f, 0x0140, 0x9284, 0xff00, 0x8007, 0x9086, - 0x0007, 0x1110, 0x2011, 0x0600, 0x000e, 0x9294, 0xff00, 0x9215, - 0xba06, 0x0006, 0x9086, 0x0006, 0x1120, 0xba90, 0x82ff, 0x090c, - 0x0dc5, 0x000e, 0x00ce, 0x012e, 0x00be, 0x0005, 0x00b6, 0x0126, - 0x00c6, 0x2091, 0x8000, 0x6210, 0x2258, 0xba04, 0x0006, 0x9086, - 0x0006, 0x1168, 0xb89c, 0xd0a4, 0x0150, 0x080c, 0x6a9b, 0x1138, - 0x9284, 0x00ff, 0x9086, 0x0007, 0x1110, 0x2011, 0x0006, 0x000e, - 0x9294, 0x00ff, 0x8007, 0x9215, 0xba06, 0x00ce, 0x012e, 0x00be, - 0x0005, 0x9182, 0x0800, 0x0218, 0x9085, 0x0001, 0x0005, 0x00d6, - 0x0026, 0x9190, 0x1000, 0x2204, 0x905d, 0x1188, 0x0096, 0x080c, - 0x100e, 0x2958, 0x009e, 0x0168, 0x2b00, 0x2012, 0xb85c, 0xb8ca, - 0xb860, 0xb8c6, 0x9006, 0xb8a6, 0xb8ae, 0x080c, 0x6148, 0x9006, - 0x0010, 0x9085, 0x0001, 0x002e, 0x00de, 0x0005, 0x00b6, 0x0096, - 0x0126, 0x2091, 0x8000, 0x0026, 0x9182, 0x0800, 0x0218, 0x9085, - 0x0001, 0x04a8, 0x00d6, 0x9190, 0x1000, 0x2204, 0x905d, 0x0568, - 0x2013, 0x0000, 0xb8a4, 0x904d, 0x0110, 0x080c, 0x1040, 0x00d6, - 0x00c6, 0xb8bc, 0x2060, 0x8cff, 0x0168, 0x600c, 0x0006, 0x6014, - 0x2048, 0x080c, 0xd0d8, 0x0110, 0x080c, 0x0fc0, 0x080c, 0xb2d3, - 0x00ce, 0x0c88, 0x00ce, 0x00de, 0x00c6, 0xb8ac, 0x9065, 0x0128, - 0x621c, 0xd2c4, 0x0110, 0x080c, 0x9096, 0x00ce, 0x2b48, 0xb8c8, - 0xb85e, 0xb8c4, 0xb862, 0x080c, 0x1050, 0x00de, 0x9006, 0x002e, - 0x012e, 0x009e, 0x00be, 0x0005, 0x0016, 0x9182, 0x0800, 0x0218, - 0x9085, 0x0001, 0x0030, 0x9188, 0x1000, 0x2104, 0x905d, 0x0dc0, - 0x9006, 0x001e, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x9006, - 0xb80a, 0xb80e, 0xb800, 0xc08c, 0xb802, 0x080c, 0x7637, 0x1510, - 0xb8a0, 0x9086, 0x007e, 0x0120, 0x080c, 0xb23d, 0x11d8, 0x0078, - 0x7040, 0xd0e4, 0x01b8, 0x00c6, 0x2061, 0x1982, 0x7048, 0x2062, - 0x704c, 0x6006, 0x7050, 0x600a, 0x7054, 0x600e, 0x00ce, 0x703c, - 0x2069, 0x0140, 0x9005, 0x1110, 0x2001, 0x0001, 0x6886, 0x2069, - 0x1800, 0x68b6, 0x7040, 0xb85e, 0x7048, 0xb862, 0x704c, 0xb866, - 0x20e1, 0x0000, 0x2099, 0x0276, 0xb8c4, 0x20e8, 0xb8c8, 0x9088, - 0x000a, 0x21a0, 0x20a9, 0x0004, 0x4003, 0x2099, 0x027a, 0x9088, - 0x0006, 0x21a0, 0x20a9, 0x0004, 0x4003, 0x2069, 0x0200, 0x6817, - 0x0001, 0x7040, 0xb86a, 0x7144, 0xb96e, 0x7048, 0xb872, 0x7050, - 0xb876, 0x2069, 0x0200, 0x6817, 0x0000, 0xb8a0, 0x9086, 0x007e, - 0x1110, 0x7144, 0xb96e, 0x9182, 0x0211, 0x1218, 0x2009, 0x0008, - 0x0400, 0x9182, 0x0259, 0x1218, 0x2009, 0x0007, 0x00d0, 0x9182, - 0x02c1, 0x1218, 0x2009, 0x0006, 0x00a0, 0x9182, 0x0349, 0x1218, - 0x2009, 0x0005, 0x0070, 0x9182, 0x0421, 0x1218, 0x2009, 0x0004, - 0x0040, 0x9182, 0x0581, 0x1218, 0x2009, 0x0003, 0x0010, 0x2009, - 0x0002, 0xb992, 0x014e, 0x013e, 0x015e, 0x00de, 0x0005, 0x0016, - 0x0026, 0x00e6, 0x2071, 0x0260, 0x7034, 0xb896, 0x703c, 0xb89a, - 0x7054, 0xb89e, 0x0036, 0xbbcc, 0xc384, 0xba00, 0x2009, 0x1867, - 0x210c, 0xd0bc, 0x0120, 0xd1ec, 0x0110, 0xc2ad, 0x0008, 0xc2ac, - 0xd0c4, 0x0148, 0xd1e4, 0x0138, 0xc2bd, 0xd0cc, 0x0128, 0xd38c, - 0x1108, 0xc385, 0x0008, 0xc2bc, 0xba02, 0xbbce, 0x003e, 0x00ee, - 0x002e, 0x001e, 0x0005, 0x0096, 0x0126, 0x2091, 0x8000, 0xb8a4, - 0x904d, 0x0578, 0xa900, 0x81ff, 0x15c0, 0xaa04, 0x9282, 0x0010, - 0x16c8, 0x0136, 0x0146, 0x01c6, 0x01d6, 0x8906, 0x8006, 0x8007, - 0x908c, 0x003f, 0x21e0, 0x9084, 0xffc0, 0x9080, 0x0004, 0x2098, - 0x2009, 0x0010, 0x20a9, 0x0001, 0x4002, 0x9086, 0xffff, 0x0120, - 0x8109, 0x1dd0, 0x080c, 0x0dc5, 0x3c00, 0x20e8, 0x3300, 0x8001, - 0x20a0, 0x4604, 0x8210, 0xaa06, 0x01de, 0x01ce, 0x014e, 0x013e, - 0x0060, 0x080c, 0x100e, 0x0170, 0x2900, 0xb8a6, 0xa803, 0x0000, - 0x080c, 0x68e0, 0xa807, 0x0001, 0xae12, 0x9085, 0x0001, 0x012e, - 0x009e, 0x0005, 0x9006, 0x0cd8, 0x0126, 0x2091, 0x8000, 0x0096, - 0xb8a4, 0x904d, 0x0188, 0xa800, 0x9005, 0x1150, 0x080c, 0x68ef, - 0x1158, 0xa804, 0x908a, 0x0002, 0x0218, 0x8001, 0xa806, 0x0020, - 0x080c, 0x1040, 0xb8a7, 0x0000, 0x009e, 0x012e, 0x0005, 0x0126, - 0x2091, 0x8000, 0x080c, 0x951c, 0x012e, 0x0005, 0x901e, 0x0010, - 0x2019, 0x0001, 0x900e, 0x0126, 0x2091, 0x8000, 0xb84c, 0x2048, - 0xb800, 0xd0dc, 0x1170, 0x89ff, 0x0500, 0x83ff, 0x0120, 0xa878, - 0x9606, 0x0158, 0x0030, 0xa86c, 0x9406, 0x1118, 0xa870, 0x9506, - 0x0120, 0x2908, 0xa800, 0x2048, 0x0c70, 0x080c, 0xaaf1, 0xaa00, - 0xb84c, 0x9906, 0x1110, 0xba4e, 0x0020, 0x00a6, 0x2150, 0xb202, - 0x00ae, 0x82ff, 0x1110, 0xb952, 0x89ff, 0x012e, 0x0005, 0x9016, - 0x0489, 0x1110, 0x2011, 0x0001, 0x0005, 0x080c, 0x6944, 0x0128, - 0x080c, 0xd195, 0x0010, 0x9085, 0x0001, 0x0005, 0x080c, 0x6944, - 0x0128, 0x080c, 0xd13a, 0x0010, 0x9085, 0x0001, 0x0005, 0x080c, - 0x6944, 0x0128, 0x080c, 0xd192, 0x0010, 0x9085, 0x0001, 0x0005, - 0x080c, 0x6944, 0x0128, 0x080c, 0xd159, 0x0010, 0x9085, 0x0001, - 0x0005, 0x080c, 0x6944, 0x0128, 0x080c, 0xd1d8, 0x0010, 0x9085, - 0x0001, 0x0005, 0xb8a4, 0x900d, 0x1118, 0x9085, 0x0001, 0x0005, - 0x0136, 0x01c6, 0xa800, 0x9005, 0x11b8, 0x890e, 0x810e, 0x810f, - 0x9184, 0x003f, 0x20e0, 0x9184, 0xffc0, 0x9080, 0x0004, 0x2098, - 0x20a9, 0x0001, 0x2009, 0x0010, 0x4002, 0x9606, 0x0128, 0x8109, - 0x1dd8, 0x9085, 0x0001, 0x0008, 0x9006, 0x01ce, 0x013e, 0x0005, - 0x0146, 0x01d6, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0004, 0x20a0, - 0x20a9, 0x0010, 0x2009, 0xffff, 0x4104, 0x01de, 0x014e, 0x0136, - 0x01c6, 0xa800, 0x9005, 0x11b8, 0x890e, 0x810e, 0x810f, 0x9184, - 0x003f, 0x20e0, 0x9184, 0xffc0, 0x9080, 0x0004, 0x2098, 0x20a9, - 0x0001, 0x2009, 0x0010, 0x4002, 0x9606, 0x0128, 0x8109, 0x1dd8, - 0x9085, 0x0001, 0x0068, 0x0146, 0x01d6, 0x3300, 0x8001, 0x20a0, - 0x3c00, 0x20e8, 0x2001, 0xffff, 0x4004, 0x01de, 0x014e, 0x9006, - 0x01ce, 0x013e, 0x0005, 0x0096, 0x0126, 0x2091, 0x8000, 0xb8a4, - 0x904d, 0x1128, 0x080c, 0x100e, 0x0168, 0x2900, 0xb8a6, 0x080c, - 0x68e0, 0xa803, 0x0001, 0xa807, 0x0000, 0x9085, 0x0001, 0x012e, - 0x009e, 0x0005, 0x9006, 0x0cd8, 0x0096, 0x0126, 0x2091, 0x8000, - 0xb8a4, 0x904d, 0x0130, 0xb8a7, 0x0000, 0x080c, 0x1040, 0x9085, - 0x0001, 0x012e, 0x009e, 0x0005, 0xb89c, 0xd0a4, 0x0005, 0x00b6, - 0x00f6, 0x080c, 0x7637, 0x01b0, 0x71c4, 0x81ff, 0x1198, 0x71dc, - 0xd19c, 0x0180, 0x2001, 0x007e, 0x9080, 0x1000, 0x2004, 0x905d, - 0x0148, 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, 0x1118, 0xb800, - 0xc0ed, 0xb802, 0x2079, 0x1847, 0x7804, 0xd0a4, 0x01d0, 0x0156, - 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, 0x6724, 0x1168, 0xb804, - 0x9084, 0xff00, 0x8007, 0x9096, 0x0004, 0x0118, 0x9086, 0x0006, - 0x1118, 0xb800, 0xc0ed, 0xb802, 0x001e, 0x8108, 0x1f04, 0x696b, - 0x015e, 0x080c, 0x6a61, 0x0120, 0x2001, 0x1985, 0x200c, 0x0098, - 0x2079, 0x1847, 0x7804, 0xd0a4, 0x0190, 0x2009, 0x07d0, 0x2001, - 0x182c, 0x2004, 0x9005, 0x0138, 0x2001, 0x1867, 0x2004, 0xd0e4, - 0x0110, 0x2009, 0x5dc0, 0x2011, 0x69a2, 0x080c, 0x88d5, 0x00fe, - 0x00be, 0x0005, 0x00b6, 0x2011, 0x69a2, 0x080c, 0x883d, 0x080c, - 0x6a61, 0x01d8, 0x2001, 0x107e, 0x2004, 0x2058, 0xb900, 0xc1ec, - 0xb902, 0x080c, 0x6a9f, 0x0130, 0x2009, 0x07d0, 0x2011, 0x69a2, - 0x080c, 0x88d5, 0x00e6, 0x2071, 0x1800, 0x9006, 0x707e, 0x7060, - 0x7082, 0x080c, 0x3000, 0x00ee, 0x04b0, 0x0156, 0x00c6, 0x20a9, - 0x007f, 0x900e, 0x0016, 0x080c, 0x6724, 0x1538, 0xb800, 0xd0ec, - 0x0520, 0x0046, 0xbaa0, 0x2220, 0x9006, 0x2009, 0x0029, 0x080c, - 0xec31, 0xb800, 0xc0e5, 0xc0ec, 0xb802, 0x080c, 0x6a9b, 0x2001, - 0x0707, 0x1128, 0xb804, 0x9084, 0x00ff, 0x9085, 0x0700, 0xb806, - 0x2019, 0x0029, 0x080c, 0x96a4, 0x0076, 0x903e, 0x080c, 0x9577, - 0x900e, 0x080c, 0xe91c, 0x007e, 0x004e, 0x001e, 0x8108, 0x1f04, - 0x69ca, 0x00ce, 0x015e, 0x00be, 0x0005, 0x00b6, 0x6010, 0x2058, - 0xb800, 0xc0ec, 0xb802, 0x00be, 0x0005, 0x00b6, 0x00c6, 0x0096, - 0x080c, 0x1027, 0x090c, 0x0dc5, 0x2958, 0x009e, 0x2001, 0x196b, - 0x2b02, 0x8b07, 0x8006, 0x8006, 0x908c, 0x003f, 0xb9c6, 0x908c, - 0xffc0, 0xb9ca, 0xb8af, 0x0000, 0x2009, 0x00ff, 0x080c, 0x6148, - 0xb807, 0x0006, 0xb813, 0x00ff, 0xb817, 0xffff, 0xb86f, 0x0200, - 0xb86c, 0xb893, 0x0002, 0xb8bb, 0x0520, 0xb8a3, 0x00ff, 0xb8af, - 0x0000, 0x00ce, 0x00be, 0x0005, 0x7810, 0x00b6, 0x2058, 0xb800, - 0x00be, 0xd0ac, 0x0005, 0x6010, 0x00b6, 0x905d, 0x0108, 0xb800, - 0x00be, 0xd0bc, 0x0005, 0x0006, 0x0016, 0x0026, 0xb804, 0x908c, - 0x00ff, 0x9196, 0x0006, 0x0188, 0x9196, 0x0004, 0x0170, 0x9196, - 0x0005, 0x0158, 0x908c, 0xff00, 0x810f, 0x9196, 0x0006, 0x0128, - 0x9196, 0x0004, 0x0110, 0x9196, 0x0005, 0x002e, 0x001e, 0x000e, - 0x0005, 0x00b6, 0x00f6, 0x2001, 0x107e, 0x2004, 0x905d, 0x0110, - 0xb800, 0xd0ec, 0x00fe, 0x00be, 0x0005, 0x0126, 0x0026, 0x2091, - 0x8000, 0x0006, 0xbaa0, 0x9290, 0x1000, 0x2204, 0x9b06, 0x190c, - 0x0dc5, 0x000e, 0xba00, 0x9005, 0x0110, 0xc2fd, 0x0008, 0xc2fc, - 0xba02, 0x002e, 0x012e, 0x0005, 0x2011, 0x1837, 0x2204, 0xd0cc, - 0x0138, 0x2001, 0x1983, 0x200c, 0x2011, 0x6a91, 0x080c, 0x88d5, - 0x0005, 0x2011, 0x6a91, 0x080c, 0x883d, 0x2011, 0x1837, 0x2204, - 0xc0cc, 0x2012, 0x0005, 0x080c, 0x57d5, 0xd0ac, 0x0005, 0x080c, - 0x57d5, 0xd0a4, 0x0005, 0x0016, 0xb904, 0x9184, 0x00ff, 0x908e, - 0x0006, 0x001e, 0x0005, 0x0016, 0xb904, 0x9184, 0xff00, 0x8007, - 0x908e, 0x0006, 0x001e, 0x0005, 0x00b6, 0x00f6, 0x080c, 0xd7e3, - 0x0158, 0x70dc, 0x9084, 0x0028, 0x0138, 0x2001, 0x107f, 0x2004, - 0x905d, 0x0110, 0xb8cc, 0xd094, 0x00fe, 0x00be, 0x0005, 0x0006, - 0x0016, 0x0036, 0x0046, 0x0076, 0x00b6, 0x2001, 0x1818, 0x203c, - 0x9780, 0x33b6, 0x203d, 0x97bc, 0xff00, 0x873f, 0x9006, 0x2018, - 0x2008, 0x9284, 0x8000, 0x0110, 0x2019, 0x0001, 0x9294, 0x7fff, - 0x2100, 0x9706, 0x0190, 0x91a0, 0x1000, 0x2404, 0x905d, 0x0168, - 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, 0x1138, 0x83ff, 0x0118, - 0xb89c, 0xd0a4, 0x0110, 0x8211, 0x0158, 0x8108, 0x83ff, 0x0120, - 0x9182, 0x0800, 0x0e28, 0x0068, 0x9182, 0x007e, 0x0e08, 0x0048, - 0x00be, 0x007e, 0x004e, 0x003e, 0x001e, 0x9085, 0x0001, 0x000e, - 0x0005, 0x00be, 0x007e, 0x004e, 0x003e, 0x001e, 0x9006, 0x000e, - 0x0005, 0x0046, 0x0056, 0x0076, 0x00b6, 0x2100, 0x9084, 0x7fff, - 0x9080, 0x1000, 0x2004, 0x905d, 0x0130, 0xb804, 0x9084, 0x00ff, - 0x9086, 0x0006, 0x0550, 0x9184, 0x8000, 0x0580, 0x2001, 0x1818, - 0x203c, 0x9780, 0x33b6, 0x203d, 0x97bc, 0xff00, 0x873f, 0x9006, - 0x2020, 0x2400, 0x9706, 0x01a0, 0x94a8, 0x1000, 0x2504, 0x905d, - 0x0178, 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, 0x1148, 0xb89c, - 0xd0a4, 0x0130, 0xb814, 0x9206, 0x1118, 0xb810, 0x9306, 0x0128, - 0x8420, 0x9482, 0x0800, 0x0e28, 0x0048, 0x918c, 0x7fff, 0x00be, - 0x007e, 0x005e, 0x004e, 0x9085, 0x0001, 0x0005, 0x918c, 0x7fff, - 0x00be, 0x007e, 0x005e, 0x004e, 0x9006, 0x0005, 0x0006, 0x2001, - 0x00a0, 0x8001, 0xa001, 0xa001, 0xa001, 0x1dd8, 0x000e, 0x0005, - 0x0006, 0x2001, 0x00f8, 0x8001, 0xa001, 0xa001, 0xa001, 0x1dd8, - 0x000e, 0x0005, 0x0006, 0x2001, 0x00e8, 0x8001, 0xa001, 0xa001, - 0xa001, 0x1dd8, 0x000e, 0x0005, 0x2071, 0x1910, 0x7003, 0x0001, - 0x7007, 0x0000, 0x9006, 0x7012, 0x7016, 0x701a, 0x701e, 0x700a, - 0x7046, 0x2001, 0x1922, 0x2003, 0x0000, 0x0005, 0x0016, 0x00e6, - 0x2071, 0x1948, 0x900e, 0x710a, 0x080c, 0x57d5, 0xd0fc, 0x1140, - 0x080c, 0x57d5, 0x900e, 0xd09c, 0x0108, 0x8108, 0x7102, 0x0470, - 0x2001, 0x1867, 0x200c, 0x9184, 0x0007, 0x0006, 0x2001, 0x180d, - 0x2004, 0xd08c, 0x000e, 0x0108, 0x9006, 0x0002, 0x6b98, 0x6b98, - 0x6b98, 0x6b98, 0x6b98, 0x6bb6, 0x6bcb, 0x6bd9, 0x7003, 0x0003, - 0x2009, 0x1868, 0x210c, 0x9184, 0xff00, 0x908e, 0xff00, 0x0140, - 0x8007, 0x9005, 0x1110, 0x2001, 0x0002, 0x8003, 0x7006, 0x0030, - 0x7007, 0x0001, 0x0018, 0x7003, 0x0005, 0x0c50, 0x2071, 0x1910, - 0x704f, 0x0000, 0x2071, 0x1800, 0x70f3, 0x0001, 0x00ee, 0x001e, - 0x0005, 0x7003, 0x0000, 0x2071, 0x1910, 0x2009, 0x1868, 0x210c, - 0x9184, 0x7f00, 0x8007, 0x908c, 0x000f, 0x0160, 0x714e, 0x8004, - 0x8004, 0x8004, 0x8004, 0x2071, 0x1800, 0x908c, 0x0007, 0x0128, - 0x70f2, 0x0c20, 0x704f, 0x000f, 0x0c90, 0x70f3, 0x0005, 0x08f0, - 0x00e6, 0x2071, 0x0050, 0x684c, 0x9005, 0x1150, 0x00e6, 0x2071, - 0x1910, 0x7028, 0xc085, 0x702a, 0x00ee, 0x9085, 0x0001, 0x0488, - 0x6844, 0x9005, 0x0158, 0x080c, 0x79a4, 0x6a60, 0x9200, 0x7002, - 0x6864, 0x9101, 0x7006, 0x9006, 0x7012, 0x7016, 0x6860, 0x7002, - 0x6864, 0x7006, 0x6868, 0x700a, 0x686c, 0x700e, 0x6844, 0x9005, - 0x1110, 0x7012, 0x7016, 0x684c, 0x701a, 0x701c, 0x9085, 0x0040, - 0x701e, 0x7037, 0x0019, 0x702b, 0x0001, 0x00e6, 0x2071, 0x1910, - 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0x700b, 0x0000, 0x00ee, - 0x9006, 0x00ee, 0x0005, 0x00e6, 0x0026, 0x2071, 0x1948, 0x7000, - 0x9015, 0x0904, 0x6ea5, 0x9286, 0x0003, 0x0904, 0x6d3e, 0x9286, - 0x0005, 0x0904, 0x6d3e, 0x2071, 0x1877, 0xa87c, 0x9005, 0x0904, - 0x6c99, 0x7140, 0xa868, 0x9102, 0x0a04, 0x6ea5, 0xa878, 0xd084, - 0x15d8, 0xa853, 0x0019, 0x2001, 0x8023, 0xa84e, 0x2071, 0x1910, - 0x701c, 0x9005, 0x1904, 0x7073, 0x0e04, 0x70e1, 0x2071, 0x0000, - 0xa850, 0x7032, 0xa84c, 0x7082, 0xa870, 0x7086, 0xa86c, 0x708a, - 0xa880, 0x708e, 0x7036, 0x0146, 0x01d6, 0x0136, 0x01c6, 0x0156, - 0x20e9, 0x0000, 0x20a1, 0x002a, 0xa868, 0x20a8, 0xa860, 0x20e0, - 0xa85c, 0x9080, 0x0021, 0x2098, 0x4003, 0x015e, 0x01ce, 0x013e, - 0x01de, 0x014e, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, - 0x190c, 0x11aa, 0x0804, 0x6d21, 0xa853, 0x001b, 0x2001, 0x8027, - 0x0820, 0x7004, 0xd08c, 0x1904, 0x6ea5, 0xa853, 0x001a, 0x2001, - 0x8024, 0x0804, 0x6c5d, 0x00e6, 0x0026, 0x2071, 0x1948, 0x7000, - 0x9015, 0x0904, 0x6ea5, 0x9286, 0x0003, 0x0904, 0x6d3e, 0x9286, - 0x0005, 0x0904, 0x6d3e, 0xa84f, 0x8022, 0xa853, 0x0018, 0x0804, - 0x6d06, 0xa868, 0xd0fc, 0x1508, 0x00e6, 0x0026, 0x2001, 0x1948, - 0x2004, 0x9015, 0x0904, 0x6ea5, 0xa978, 0xa874, 0x9105, 0x1904, - 0x6ea5, 0x9286, 0x0003, 0x0904, 0x6d3e, 0x9286, 0x0005, 0x0904, - 0x6d3e, 0xa87c, 0xd0bc, 0x1904, 0x6ea5, 0x2200, 0x0002, 0x6ea5, - 0x6d02, 0x6d3e, 0x6d3e, 0x6ea5, 0x6d3e, 0x0005, 0xa868, 0xd0fc, - 0x1500, 0x00e6, 0x0026, 0x2009, 0x1948, 0x210c, 0x81ff, 0x0904, - 0x6ea5, 0xa880, 0x9084, 0x00ff, 0x9086, 0x0001, 0x1904, 0x6ea5, - 0x9186, 0x0003, 0x0904, 0x6d3e, 0x9186, 0x0005, 0x0904, 0x6d3e, - 0xa87c, 0xd0cc, 0x0904, 0x6ea5, 0xa84f, 0x8021, 0xa853, 0x0017, - 0x0028, 0x0005, 0xa84f, 0x8020, 0xa853, 0x0016, 0x2071, 0x1910, - 0x701c, 0x9005, 0x1904, 0x7073, 0x0e04, 0x70e1, 0x2071, 0x0000, - 0xa84c, 0x7082, 0xa850, 0x7032, 0xa86c, 0x7086, 0x7036, 0xa870, - 0x708a, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, - 0x11aa, 0x2071, 0x1800, 0x2011, 0x0001, 0xa804, 0x900d, 0x702c, - 0x1158, 0xa802, 0x2900, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, - 0x8725, 0x002e, 0x00ee, 0x0005, 0x0096, 0x2148, 0xa904, 0xa802, - 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x009e, 0x0c58, 0xa84f, 0x0000, - 0x00f6, 0x2079, 0x0050, 0x2071, 0x1910, 0xa803, 0x0000, 0x7010, - 0x9005, 0x1904, 0x6e29, 0x782c, 0x908c, 0x0780, 0x190c, 0x722f, - 0x8004, 0x8004, 0x8004, 0x9084, 0x0003, 0x0002, 0x6d5c, 0x6e29, - 0x6d80, 0x6dc6, 0x080c, 0x0dc5, 0x2071, 0x1800, 0x2900, 0x7822, - 0xa804, 0x900d, 0x1168, 0x2071, 0x19fb, 0x7044, 0x9005, 0x1320, - 0x2001, 0x1949, 0x2004, 0x7046, 0x00fe, 0x002e, 0x00ee, 0x0005, - 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, - 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8725, 0x0c18, - 0x2071, 0x1800, 0x2900, 0x7822, 0xa804, 0x900d, 0x1578, 0x7824, - 0x00e6, 0x2071, 0x0040, 0x712c, 0xd19c, 0x1148, 0x2009, 0x1830, - 0x210c, 0x918a, 0x0020, 0x0218, 0x7022, 0x00ee, 0x0058, 0x00ee, - 0x2048, 0x702c, 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, - 0x080c, 0x8725, 0x782c, 0x9094, 0x0780, 0x190c, 0x722f, 0xd0a4, - 0x19f0, 0x2071, 0x19fb, 0x7044, 0x9005, 0x1320, 0x2001, 0x1949, - 0x2004, 0x7046, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x9016, 0x702c, - 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, - 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8725, 0x0808, 0x0096, 0x00e6, - 0x7824, 0x2048, 0x2071, 0x1800, 0x702c, 0xa802, 0x2900, 0x702e, - 0x70c0, 0x8000, 0x70c2, 0x080c, 0x8725, 0x782c, 0x9094, 0x0780, - 0x190c, 0x722f, 0xd0a4, 0x1d60, 0x00ee, 0x782c, 0x9094, 0x0780, - 0x190c, 0x722f, 0xd09c, 0x1198, 0x009e, 0x2900, 0x7822, 0xa804, - 0x900d, 0x1550, 0x2071, 0x19fb, 0x7044, 0x9005, 0x1320, 0x2001, - 0x1949, 0x2004, 0x7046, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x009e, - 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, - 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1168, 0x2071, - 0x19fb, 0x7044, 0x9005, 0x1320, 0x2001, 0x1949, 0x2004, 0x7046, - 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2071, 0x1800, 0x9016, 0x702c, - 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, - 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8725, 0x00fe, 0x002e, 0x00ee, - 0x0005, 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, - 0x0110, 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1904, - 0x6e7d, 0x782c, 0x9094, 0x0780, 0x190c, 0x722f, 0xd09c, 0x1198, - 0x701c, 0x904d, 0x0180, 0x7010, 0x8001, 0x7012, 0x1108, 0x701a, - 0xa800, 0x701e, 0x2900, 0x7822, 0x782c, 0x9094, 0x0780, 0x190c, - 0x722f, 0xd09c, 0x0d68, 0x782c, 0x9094, 0x0780, 0x190c, 0x722f, - 0xd0a4, 0x01b0, 0x00e6, 0x7824, 0x2048, 0x2071, 0x1800, 0x702c, - 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, 0x8725, - 0x782c, 0x9094, 0x0780, 0x190c, 0x722f, 0xd0a4, 0x1d60, 0x00ee, - 0x2071, 0x19fb, 0x7044, 0x9005, 0x1320, 0x2001, 0x1949, 0x2004, - 0x7046, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x00e6, 0x2071, 0x1800, - 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, - 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8725, 0x00ee, - 0x0804, 0x6e39, 0xa868, 0xd0fc, 0x1904, 0x6ef3, 0x0096, 0xa804, - 0xa807, 0x0000, 0x904d, 0x190c, 0x0fc0, 0x009e, 0x0020, 0xa868, - 0xd0fc, 0x1904, 0x6ef3, 0x00e6, 0x0026, 0xa84f, 0x0000, 0x00f6, - 0x2079, 0x0050, 0x2071, 0x1800, 0x70ec, 0x8001, 0x0558, 0x1a04, - 0x6ef0, 0x2071, 0x1910, 0xa803, 0x0000, 0xa864, 0x9084, 0x00ff, - 0x908e, 0x0016, 0x01a8, 0x7010, 0x9005, 0x1904, 0x6fef, 0x782c, - 0x908c, 0x0780, 0x190c, 0x722f, 0x8004, 0x8004, 0x8004, 0x9084, - 0x0003, 0x0002, 0x6ef4, 0x6fef, 0x6f0f, 0x6f80, 0x080c, 0x0dc5, - 0x2009, 0x1948, 0x2104, 0x0002, 0x6ebb, 0x6ebb, 0x6ebb, 0x6d47, - 0x6ebb, 0x6d47, 0x70ef, 0x0fa0, 0x71e8, 0x8107, 0x9106, 0x9094, - 0x00c0, 0x9184, 0xff3f, 0x9205, 0x70ea, 0x3b08, 0x3a00, 0x9104, - 0x918d, 0x00c0, 0x21d8, 0x9084, 0xff3f, 0x9205, 0x20d0, 0x0808, - 0x70ee, 0x0804, 0x6eb1, 0x0005, 0x2071, 0x1800, 0x2900, 0x7822, - 0xa804, 0x900d, 0x1120, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x9016, - 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, - 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8725, 0x0c60, 0x2071, - 0x1800, 0x2900, 0x7822, 0xa804, 0x900d, 0x1904, 0x6f6f, 0x7830, - 0x8007, 0x908c, 0x001f, 0x70f0, 0x9102, 0x1220, 0x00fe, 0x002e, - 0x00ee, 0x0005, 0x7824, 0x00e6, 0x2071, 0x0040, 0x712c, 0xd19c, - 0x1148, 0x2009, 0x1830, 0x210c, 0x918a, 0x0020, 0x0218, 0x7022, - 0x00ee, 0x0058, 0x00ee, 0x2048, 0x702c, 0xa802, 0x2900, 0x702e, - 0x70c0, 0x8000, 0x70c2, 0x080c, 0x8725, 0x782c, 0x9094, 0x0780, - 0x190c, 0x722f, 0xd0a4, 0x19f0, 0x0e04, 0x6f66, 0x7838, 0x7938, - 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, - 0x00de, 0x2001, 0x1921, 0x200c, 0xc184, 0x2102, 0x2091, 0x4080, - 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11aa, 0x2001, 0x1922, - 0x2003, 0x0000, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2001, 0x1921, - 0x200c, 0xc185, 0x2102, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x9016, - 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, - 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8725, 0x0804, 0x6f22, - 0x0096, 0x00e6, 0x7824, 0x2048, 0x2071, 0x1800, 0x702c, 0xa802, - 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, 0x8725, 0x782c, - 0x9094, 0x0780, 0x190c, 0x722f, 0xd0a4, 0x1d60, 0x00ee, 0x0e04, - 0x6fc2, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, - 0x6836, 0x6833, 0x0013, 0x00de, 0x7044, 0xc084, 0x7046, 0x2091, - 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11aa, 0x704b, - 0x0000, 0x782c, 0x9094, 0x0780, 0x190c, 0x722f, 0xd09c, 0x1170, - 0x009e, 0x2900, 0x7822, 0xa804, 0x900d, 0x11e0, 0x00fe, 0x002e, - 0x00ee, 0x0005, 0x7044, 0xc085, 0x7046, 0x0c58, 0x009e, 0x2908, - 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, 0xa902, - 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1120, 0x00fe, 0x002e, - 0x00ee, 0x0005, 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, - 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, - 0x70c2, 0x080c, 0x8725, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2908, - 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, 0xa902, - 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1904, 0x705e, 0x782c, - 0x9094, 0x0780, 0x190c, 0x722f, 0xd09c, 0x11b0, 0x701c, 0x904d, - 0x0198, 0xa84c, 0x9005, 0x1180, 0x7010, 0x8001, 0x7012, 0x1108, - 0x701a, 0xa800, 0x701e, 0x2900, 0x7822, 0x782c, 0x9094, 0x0780, - 0x190c, 0x722f, 0xd09c, 0x0d50, 0x782c, 0x9094, 0x0780, 0x190c, - 0x722f, 0xd0a4, 0x05b8, 0x00e6, 0x7824, 0x2048, 0x2071, 0x1800, - 0x702c, 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, - 0x8725, 0x782c, 0x9094, 0x0780, 0x190c, 0x722f, 0xd0a4, 0x1d60, - 0x00ee, 0x0e04, 0x7057, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, - 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x7044, 0xc084, - 0x7046, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, - 0x11aa, 0x704b, 0x0000, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x7044, - 0xc085, 0x7046, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x00e6, 0x2071, - 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, - 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8725, - 0x00ee, 0x0804, 0x6fff, 0x2071, 0x1910, 0xa803, 0x0000, 0x2908, - 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, 0xa902, - 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1128, 0x1e04, 0x709e, - 0x002e, 0x00ee, 0x0005, 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, - 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, - 0x9200, 0x70c2, 0x080c, 0x8725, 0x0e04, 0x7088, 0x2071, 0x1910, - 0x701c, 0x2048, 0xa84c, 0x900d, 0x0d18, 0x2071, 0x0000, 0x7182, - 0xa850, 0x7032, 0xa86c, 0x7086, 0x7036, 0xa870, 0x708a, 0xa850, - 0x9082, 0x0019, 0x1278, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, - 0xd084, 0x190c, 0x11aa, 0x2071, 0x1910, 0x080c, 0x721b, 0x002e, - 0x00ee, 0x0005, 0xa850, 0x9082, 0x001c, 0x1e68, 0xa880, 0x708e, - 0x7036, 0x0146, 0x01d6, 0x0136, 0x01c6, 0x0156, 0x20e9, 0x0000, - 0x20a1, 0x002a, 0xa868, 0x20a8, 0xa860, 0x20e0, 0xa85c, 0x9080, - 0x0021, 0x2098, 0x4003, 0x015e, 0x01ce, 0x013e, 0x01de, 0x014e, - 0x0890, 0x2071, 0x1910, 0xa803, 0x0000, 0x2908, 0x7010, 0x8000, - 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, 0xa902, 0x0008, 0x711e, - 0x2148, 0xa804, 0x900d, 0x1118, 0x002e, 0x00ee, 0x0005, 0x2071, - 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, - 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8725, - 0x002e, 0x00ee, 0x0005, 0x0006, 0xa87c, 0x0006, 0xa867, 0x0103, - 0x20a9, 0x001c, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x001d, 0x20a0, - 0x9006, 0x4004, 0x000e, 0x9084, 0x00ff, 0xa87e, 0x000e, 0xa87a, - 0xa982, 0x0005, 0x2071, 0x1910, 0x7004, 0x0002, 0x712e, 0x712f, - 0x721a, 0x712f, 0x712c, 0x721a, 0x080c, 0x0dc5, 0x0005, 0x2001, - 0x1948, 0x2004, 0x0002, 0x7139, 0x7139, 0x71b3, 0x71b4, 0x7139, - 0x71b4, 0x0126, 0x2091, 0x8000, 0x1e0c, 0x723a, 0x701c, 0x904d, - 0x0508, 0xa84c, 0x9005, 0x0904, 0x7184, 0x0e04, 0x7162, 0xa94c, - 0x2071, 0x0000, 0x7182, 0xa850, 0x7032, 0xa86c, 0x7086, 0x7036, - 0xa870, 0x708a, 0xa850, 0x9082, 0x0019, 0x1278, 0x2091, 0x4080, - 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11aa, 0x2071, 0x1910, - 0x080c, 0x721b, 0x012e, 0x0804, 0x71b2, 0xa850, 0x9082, 0x001c, - 0x1e68, 0xa880, 0x708e, 0x7036, 0x0146, 0x01d6, 0x0136, 0x01c6, - 0x0156, 0x20e9, 0x0000, 0x20a1, 0x002a, 0xa868, 0x20a8, 0xa860, - 0x20e0, 0xa85c, 0x9080, 0x0021, 0x2098, 0x4003, 0x015e, 0x01ce, - 0x013e, 0x01de, 0x014e, 0x0890, 0x2001, 0x005b, 0x2004, 0x9094, - 0x0780, 0x190c, 0x722f, 0xd09c, 0x2071, 0x1910, 0x1510, 0x2071, - 0x1910, 0x700f, 0x0001, 0xa964, 0x9184, 0x00ff, 0x9086, 0x0003, - 0x1130, 0x810f, 0x918c, 0x00ff, 0x8101, 0x0108, 0x710e, 0x2900, - 0x00d6, 0x2069, 0x0050, 0x6822, 0x00de, 0x2071, 0x1910, 0x701c, - 0x2048, 0x7010, 0x8001, 0x7012, 0xa800, 0x701e, 0x9005, 0x1108, - 0x701a, 0x012e, 0x0005, 0x0005, 0x00d6, 0x2008, 0x2069, 0x19fb, - 0x6844, 0x9005, 0x0760, 0x0158, 0x9186, 0x0003, 0x0540, 0x2001, - 0x1815, 0x2004, 0x2009, 0x1ad1, 0x210c, 0x9102, 0x1500, 0x0126, - 0x2091, 0x8000, 0x2069, 0x0050, 0x693c, 0x6838, 0x9106, 0x0190, - 0x0e04, 0x71e6, 0x2069, 0x0000, 0x6837, 0x8040, 0x6833, 0x0012, - 0x6883, 0x8040, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, - 0x190c, 0x11aa, 0x2069, 0x19fb, 0x6847, 0xffff, 0x012e, 0x00de, - 0x0126, 0x2091, 0x8000, 0x1e0c, 0x72a5, 0x701c, 0x904d, 0x0540, - 0x2001, 0x005b, 0x2004, 0x9094, 0x0780, 0x15c9, 0xd09c, 0x1500, - 0x2071, 0x1910, 0x700f, 0x0001, 0xa964, 0x9184, 0x00ff, 0x9086, - 0x0003, 0x1130, 0x810f, 0x918c, 0x00ff, 0x8101, 0x0108, 0x710e, - 0x2900, 0x00d6, 0x2069, 0x0050, 0x6822, 0x00de, 0x701c, 0x2048, - 0x7010, 0x8001, 0x7012, 0xa800, 0x701e, 0x9005, 0x1108, 0x701a, - 0x012e, 0x0005, 0x0005, 0x0126, 0x2091, 0x8000, 0x701c, 0x904d, - 0x0160, 0x7010, 0x8001, 0x7012, 0xa800, 0x701e, 0x9005, 0x1108, - 0x701a, 0x012e, 0x080c, 0x1040, 0x0005, 0x012e, 0x0005, 0x2091, - 0x8000, 0x0e04, 0x7231, 0x0006, 0x0016, 0x2001, 0x8004, 0x0006, - 0x0804, 0x0dce, 0x0096, 0x00f6, 0x2079, 0x0050, 0x7044, 0xd084, - 0x01d0, 0xc084, 0x7046, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, - 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x2091, 0x4080, - 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11aa, 0x704b, 0x0000, - 0x00fe, 0x009e, 0x0005, 0x782c, 0x9094, 0x0780, 0x1981, 0xd0a4, - 0x0db8, 0x7148, 0x704c, 0x8108, 0x714a, 0x9102, 0x0e88, 0x00e6, - 0x2071, 0x1800, 0x7824, 0x00e6, 0x2071, 0x0040, 0x712c, 0xd19c, - 0x1148, 0x2009, 0x1830, 0x210c, 0x918a, 0x0020, 0x0218, 0x7022, - 0x00ee, 0x0058, 0x00ee, 0x2048, 0x702c, 0xa802, 0x2900, 0x702e, - 0x70c0, 0x8000, 0x70c2, 0x080c, 0x8725, 0x782c, 0x9094, 0x0780, - 0x190c, 0x722f, 0xd0a4, 0x19f0, 0x7838, 0x7938, 0x910e, 0x1de0, - 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x2091, - 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11aa, 0x00ee, - 0x704b, 0x0000, 0x00fe, 0x009e, 0x0005, 0x00f6, 0x2079, 0x0050, - 0x7044, 0xd084, 0x01b8, 0xc084, 0x7046, 0x7838, 0x7938, 0x910e, - 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, - 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11aa, - 0x00fe, 0x0005, 0x782c, 0x9094, 0x0780, 0x190c, 0x722f, 0xd0a4, - 0x0db8, 0x00e6, 0x2071, 0x1800, 0x7824, 0x2048, 0x702c, 0xa802, - 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, 0x8725, 0x782c, - 0x9094, 0x0780, 0x190c, 0x722f, 0xd0a4, 0x1d70, 0x00d6, 0x2069, - 0x0050, 0x693c, 0x2069, 0x1948, 0x6808, 0x690a, 0x2069, 0x19fb, - 0x9102, 0x1118, 0x6844, 0x9005, 0x1320, 0x2001, 0x1949, 0x200c, - 0x6946, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x7098, 0x908a, 0x002a, - 0x1a0c, 0x0dc5, 0x9082, 0x001d, 0x001b, 0x6027, 0x1e00, 0x0005, - 0x73e6, 0x7353, 0x736f, 0x7399, 0x73d5, 0x7415, 0x7427, 0x736f, - 0x73fd, 0x730e, 0x733c, 0x73bf, 0x730d, 0x0005, 0x00d6, 0x2069, - 0x0200, 0x6804, 0x9005, 0x1180, 0x6808, 0x9005, 0x1518, 0x709b, - 0x0029, 0x2069, 0x198f, 0x2d04, 0x7002, 0x080c, 0x7774, 0x6028, - 0x9085, 0x0600, 0x602a, 0x00b0, 0x709b, 0x0029, 0x2069, 0x198f, - 0x2d04, 0x7002, 0x6028, 0x9085, 0x0600, 0x602a, 0x00e6, 0x0036, - 0x0046, 0x0056, 0x2071, 0x1a65, 0x080c, 0x1ad9, 0x005e, 0x004e, - 0x003e, 0x00ee, 0x00de, 0x0005, 0x00d6, 0x2069, 0x0200, 0x6804, - 0x9005, 0x1178, 0x6808, 0x9005, 0x1160, 0x709b, 0x0029, 0x2069, - 0x198f, 0x2d04, 0x7002, 0x080c, 0x7818, 0x6028, 0x9085, 0x0600, - 0x602a, 0x00de, 0x0005, 0x0006, 0x2001, 0x0090, 0x080c, 0x2d39, - 0x000e, 0x6124, 0xd1e4, 0x1190, 0x080c, 0x7494, 0xd1d4, 0x1160, - 0xd1dc, 0x1138, 0xd1cc, 0x0150, 0x709b, 0x0020, 0x080c, 0x7494, - 0x0028, 0x709b, 0x001d, 0x0010, 0x709b, 0x001f, 0x0005, 0x2001, - 0x0088, 0x080c, 0x2d39, 0x6124, 0xd1cc, 0x11e8, 0xd1dc, 0x11c0, - 0xd1e4, 0x1198, 0x9184, 0x1e00, 0x11d8, 0x080c, 0x1b06, 0x60e3, - 0x0001, 0x600c, 0xc0b4, 0x600e, 0x080c, 0x7663, 0x2001, 0x0080, - 0x080c, 0x2d39, 0x709b, 0x0029, 0x0058, 0x709b, 0x001e, 0x0040, - 0x709b, 0x001d, 0x0028, 0x709b, 0x0020, 0x0010, 0x709b, 0x001f, - 0x0005, 0x080c, 0x1b06, 0x60e3, 0x0001, 0x600c, 0xc0b4, 0x600e, - 0x080c, 0x7663, 0x2001, 0x0080, 0x080c, 0x2d39, 0x6124, 0xd1d4, - 0x1198, 0xd1dc, 0x1170, 0xd1e4, 0x1148, 0x9184, 0x1e00, 0x1118, - 0x709b, 0x0029, 0x0058, 0x709b, 0x0028, 0x0040, 0x709b, 0x001e, - 0x0028, 0x709b, 0x001d, 0x0010, 0x709b, 0x001f, 0x0005, 0x6124, - 0xd1d4, 0x1180, 0xd1dc, 0x1158, 0xd1e4, 0x1130, 0x9184, 0x1e00, - 0x1158, 0x709b, 0x0029, 0x0040, 0x709b, 0x001e, 0x0028, 0x709b, - 0x001d, 0x0010, 0x709b, 0x001f, 0x0005, 0x2001, 0x00a0, 0x080c, - 0x2d39, 0x6124, 0xd1dc, 0x1138, 0xd1e4, 0x0138, 0x080c, 0x1b06, - 0x709b, 0x001e, 0x0010, 0x709b, 0x001d, 0x0005, 0x080c, 0x7517, - 0x6124, 0xd1dc, 0x1188, 0x080c, 0x7494, 0x0016, 0x080c, 0x1b06, - 0x001e, 0xd1d4, 0x1128, 0xd1e4, 0x0138, 0x709b, 0x001e, 0x0020, - 0x709b, 0x001f, 0x080c, 0x7494, 0x0005, 0x0006, 0x2001, 0x00a0, - 0x080c, 0x2d39, 0x000e, 0x6124, 0xd1d4, 0x1160, 0xd1cc, 0x1150, - 0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x709b, 0x001e, 0x0028, 0x709b, - 0x001d, 0x0010, 0x709b, 0x0021, 0x0005, 0x080c, 0x7517, 0x6124, - 0xd1d4, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x709b, 0x001e, - 0x0028, 0x709b, 0x001d, 0x0010, 0x709b, 0x001f, 0x0005, 0x0006, - 0x2001, 0x0090, 0x080c, 0x2d39, 0x000e, 0x6124, 0xd1d4, 0x1178, - 0xd1cc, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0158, 0x709b, 0x001e, - 0x0040, 0x709b, 0x001d, 0x0028, 0x709b, 0x0020, 0x0010, 0x709b, - 0x001f, 0x0005, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x0126, 0x2061, - 0x0100, 0x2069, 0x0140, 0x2071, 0x1800, 0x2091, 0x8000, 0x080c, - 0x7637, 0x11d8, 0x2001, 0x180c, 0x200c, 0xd1b4, 0x01b0, 0xc1b4, - 0x2102, 0x6027, 0x0200, 0x080c, 0x2c61, 0x6024, 0xd0cc, 0x0148, - 0x2001, 0x00a0, 0x080c, 0x2d39, 0x080c, 0x7932, 0x080c, 0x612e, - 0x0428, 0x6028, 0xc0cd, 0x602a, 0x0408, 0x080c, 0x7651, 0x0150, - 0x080c, 0x7648, 0x1138, 0x2001, 0x0001, 0x080c, 0x281c, 0x080c, - 0x760f, 0x00a0, 0x080c, 0x7514, 0x0178, 0x2001, 0x0001, 0x080c, - 0x281c, 0x7098, 0x9086, 0x001e, 0x0120, 0x7098, 0x9086, 0x0022, - 0x1118, 0x709b, 0x0025, 0x0010, 0x709b, 0x0021, 0x012e, 0x00ee, - 0x00de, 0x00ce, 0x001e, 0x0005, 0x0026, 0x2011, 0x74a5, 0x080c, - 0x8917, 0x002e, 0x0016, 0x0026, 0x2009, 0x0064, 0x2011, 0x74a5, - 0x080c, 0x890e, 0x002e, 0x001e, 0x0005, 0x00e6, 0x00f6, 0x0016, - 0x080c, 0xa6e9, 0x2071, 0x1800, 0x080c, 0x7442, 0x001e, 0x00fe, - 0x00ee, 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, - 0x00f6, 0x0126, 0x2071, 0x1800, 0x080c, 0xa6e9, 0x2061, 0x0100, - 0x2069, 0x0140, 0x2091, 0x8000, 0x6028, 0xc09c, 0x602a, 0x2011, - 0x0003, 0x080c, 0xaabf, 0x2011, 0x0002, 0x080c, 0xaac9, 0x080c, - 0xa9d3, 0x080c, 0x88c3, 0x0036, 0x901e, 0x080c, 0xaa49, 0x003e, - 0x60e3, 0x0000, 0x080c, 0xf07f, 0x080c, 0xf09a, 0x2009, 0x0004, - 0x080c, 0x2c67, 0x080c, 0x2b82, 0x2001, 0x1800, 0x2003, 0x0004, - 0x6027, 0x0008, 0x2011, 0x74a5, 0x080c, 0x8917, 0x080c, 0x7651, - 0x0118, 0x9006, 0x080c, 0x2d39, 0x080c, 0x0ba0, 0x2001, 0x0001, - 0x080c, 0x281c, 0x012e, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x003e, - 0x002e, 0x001e, 0x0005, 0x0026, 0x00e6, 0x2011, 0x74b2, 0x2071, - 0x19fb, 0x701c, 0x9206, 0x1118, 0x7018, 0x9005, 0x0110, 0x9085, - 0x0001, 0x00ee, 0x002e, 0x0005, 0x6020, 0xd09c, 0x0005, 0x6800, - 0x9084, 0xfffe, 0x9086, 0x00c0, 0x01b8, 0x2001, 0x00c0, 0x080c, - 0x2d39, 0x0156, 0x20a9, 0x002d, 0x1d04, 0x7524, 0x2091, 0x6000, - 0x1f04, 0x7524, 0x015e, 0x00d6, 0x2069, 0x1800, 0x689c, 0x8001, - 0x0220, 0x0118, 0x689e, 0x00de, 0x0005, 0x689f, 0x0014, 0x68e8, - 0xd0dc, 0x0dc8, 0x6800, 0x9086, 0x0001, 0x1da8, 0x080c, 0x8923, - 0x0c90, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, - 0x2071, 0x1800, 0x080c, 0x7941, 0x2001, 0x196d, 0x2003, 0x0000, - 0x9006, 0x709a, 0x60e2, 0x6886, 0x080c, 0x28e7, 0x9006, 0x080c, - 0x2d39, 0x080c, 0x5fed, 0x6027, 0xffff, 0x602b, 0x182f, 0x00ee, - 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, - 0x2069, 0x0140, 0x2071, 0x1800, 0x2001, 0x197d, 0x200c, 0x9186, - 0x0000, 0x0158, 0x9186, 0x0001, 0x0158, 0x9186, 0x0002, 0x0158, - 0x9186, 0x0003, 0x0158, 0x0804, 0x75ff, 0x709b, 0x0022, 0x0040, - 0x709b, 0x0021, 0x0028, 0x709b, 0x0023, 0x0010, 0x709b, 0x0024, - 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, 0x28e7, - 0x0026, 0x080c, 0xb244, 0x002e, 0x7000, 0x908e, 0x0004, 0x0118, - 0x602b, 0x0028, 0x0010, 0x602b, 0x0020, 0x0156, 0x0126, 0x2091, - 0x8000, 0x20a9, 0x0005, 0x6024, 0xd0ac, 0x0150, 0x012e, 0x015e, - 0x080c, 0xd7e3, 0x0118, 0x9006, 0x080c, 0x2d63, 0x0804, 0x760b, - 0x6800, 0x9084, 0x00a1, 0xc0bd, 0x6802, 0x080c, 0x2c61, 0x6904, - 0xd1d4, 0x1140, 0x2001, 0x0100, 0x080c, 0x2d39, 0x1f04, 0x75a3, - 0x080c, 0x768b, 0x012e, 0x015e, 0x080c, 0x7648, 0x01d8, 0x6044, - 0x9005, 0x0198, 0x2011, 0x0114, 0x2204, 0x9085, 0x0100, 0x2012, - 0x6050, 0x0006, 0x9085, 0x0020, 0x6052, 0x080c, 0x768b, 0x9006, - 0x8001, 0x1df0, 0x000e, 0x6052, 0x0028, 0x6804, 0xd0d4, 0x1110, - 0x080c, 0x768b, 0x080c, 0xd7e3, 0x0118, 0x9006, 0x080c, 0x2d63, - 0x0016, 0x0026, 0x7000, 0x908e, 0x0004, 0x0130, 0x2009, 0x00c8, - 0x2011, 0x74b2, 0x080c, 0x88d5, 0x002e, 0x001e, 0x080c, 0x871c, - 0x7034, 0xc085, 0x7036, 0x2001, 0x197d, 0x2003, 0x0004, 0x080c, - 0x72f5, 0x080c, 0x7648, 0x0138, 0x6804, 0xd0d4, 0x1120, 0xd0dc, - 0x1100, 0x080c, 0x7937, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x00c6, - 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1800, - 0x080c, 0x8733, 0x080c, 0x8725, 0x080c, 0x7941, 0x2001, 0x196d, - 0x2003, 0x0000, 0x9006, 0x709a, 0x60e2, 0x6886, 0x080c, 0x28e7, - 0x9006, 0x080c, 0x2d39, 0x6043, 0x0090, 0x6043, 0x0010, 0x6027, - 0xffff, 0x602b, 0x182f, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x0006, - 0x2001, 0x197c, 0x2004, 0x9086, 0xaaaa, 0x000e, 0x0005, 0x0006, - 0x080c, 0x57d9, 0x9084, 0x0030, 0x9086, 0x0000, 0x000e, 0x0005, - 0x0006, 0x080c, 0x57d9, 0x9084, 0x0030, 0x9086, 0x0030, 0x000e, - 0x0005, 0x0006, 0x080c, 0x57d9, 0x9084, 0x0030, 0x9086, 0x0010, - 0x000e, 0x0005, 0x0006, 0x080c, 0x57d9, 0x9084, 0x0030, 0x9086, - 0x0020, 0x000e, 0x0005, 0x0036, 0x0016, 0x2001, 0x180c, 0x2004, - 0x908c, 0x0013, 0x0168, 0x0020, 0x080c, 0x2907, 0x900e, 0x0010, - 0x2009, 0x0002, 0x2019, 0x0028, 0x080c, 0x321b, 0x9006, 0x0019, - 0x001e, 0x003e, 0x0005, 0x00e6, 0x2071, 0x180c, 0x2e04, 0x0130, - 0x080c, 0xd7dc, 0x1128, 0x9085, 0x0010, 0x0010, 0x9084, 0xffef, - 0x2072, 0x00ee, 0x0005, 0x6050, 0x0006, 0x60ec, 0x0006, 0x600c, - 0x0006, 0x6004, 0x0006, 0x6028, 0x0006, 0x0016, 0x6138, 0x6050, - 0x9084, 0xfbff, 0x9085, 0x2000, 0x6052, 0x613a, 0x20a9, 0x0012, - 0x1d04, 0x76a0, 0x2091, 0x6000, 0x1f04, 0x76a0, 0x602f, 0x0100, - 0x602f, 0x0000, 0x6050, 0x9085, 0x0400, 0x9084, 0xdfff, 0x6052, - 0x613a, 0x001e, 0x602f, 0x0040, 0x602f, 0x0000, 0x000e, 0x602a, - 0x000e, 0x6006, 0x000e, 0x600e, 0x000e, 0x60ee, 0x60e3, 0x0000, - 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, 0x28e7, 0x2001, 0x00a0, - 0x0006, 0x080c, 0xd7e3, 0x000e, 0x0130, 0x080c, 0x2d57, 0x9006, - 0x080c, 0x2d63, 0x0010, 0x080c, 0x2d39, 0x000e, 0x6052, 0x6050, - 0x0006, 0xc0e5, 0x6052, 0x00f6, 0x2079, 0x0100, 0x080c, 0x2bd6, - 0x00fe, 0x000e, 0x6052, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, - 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, - 0x1800, 0x6020, 0x9084, 0x0080, 0x0138, 0x2001, 0x180c, 0x200c, - 0xc1c5, 0x2102, 0x0804, 0x7766, 0x2001, 0x180c, 0x200c, 0xc1c4, - 0x2102, 0x6028, 0x9084, 0xe1ff, 0x602a, 0x6027, 0x0200, 0x2001, - 0x0090, 0x080c, 0x2d39, 0x20a9, 0x0366, 0x6024, 0xd0cc, 0x1518, - 0x1d04, 0x770d, 0x2091, 0x6000, 0x1f04, 0x770d, 0x2011, 0x0003, - 0x080c, 0xaabf, 0x2011, 0x0002, 0x080c, 0xaac9, 0x080c, 0xa9d3, - 0x901e, 0x080c, 0xaa49, 0x2001, 0x00a0, 0x080c, 0x2d39, 0x080c, - 0x7932, 0x080c, 0x612e, 0x080c, 0xd7e3, 0x0110, 0x080c, 0x0d33, - 0x9085, 0x0001, 0x04c8, 0x080c, 0x1b06, 0x60e3, 0x0000, 0x2001, - 0x180d, 0x2004, 0xd08c, 0x2001, 0x0002, 0x1118, 0x2001, 0x196d, - 0x2004, 0x080c, 0x28e7, 0x60e2, 0x2001, 0x0080, 0x080c, 0x2d39, - 0x20a9, 0x0366, 0x6027, 0x1e00, 0x2009, 0x1e00, 0x080c, 0x2c61, - 0x6024, 0x910c, 0x0140, 0x1d04, 0x774a, 0x2091, 0x6000, 0x1f04, - 0x774a, 0x0804, 0x7716, 0x6028, 0x9085, 0x1e00, 0x602a, 0x70b4, - 0x9005, 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, 0x080c, 0xd7e3, - 0x0110, 0x080c, 0x0d33, 0x9006, 0x00ee, 0x00de, 0x00ce, 0x003e, - 0x002e, 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, - 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2071, 0x1800, 0x7000, - 0x9086, 0x0003, 0x1168, 0x2001, 0x020b, 0x2004, 0x9084, 0x5540, - 0x9086, 0x5540, 0x1128, 0x2069, 0x1a7c, 0x2d04, 0x8000, 0x206a, - 0x2069, 0x0140, 0x6020, 0x9084, 0x00c0, 0x0120, 0x6884, 0x9005, - 0x1904, 0x77d9, 0x2001, 0x0088, 0x080c, 0x2d39, 0x9006, 0x60e2, - 0x6886, 0x080c, 0x28e7, 0x2069, 0x0200, 0x6804, 0x9005, 0x1118, - 0x6808, 0x9005, 0x01c0, 0x6028, 0x9084, 0xfbff, 0x602a, 0x6027, - 0x0400, 0x2069, 0x198f, 0x7000, 0x206a, 0x709b, 0x0026, 0x7003, - 0x0001, 0x20a9, 0x0002, 0x1d04, 0x77bb, 0x2091, 0x6000, 0x1f04, - 0x77bb, 0x0804, 0x7810, 0x2069, 0x0140, 0x20a9, 0x0384, 0x6027, - 0x1e00, 0x2009, 0x1e00, 0x080c, 0x2c61, 0x6024, 0x910c, 0x0508, - 0x9084, 0x1a00, 0x11f0, 0x1d04, 0x77c7, 0x2091, 0x6000, 0x1f04, - 0x77c7, 0x2011, 0x0003, 0x080c, 0xaabf, 0x2011, 0x0002, 0x080c, - 0xaac9, 0x080c, 0xa9d3, 0x901e, 0x080c, 0xaa49, 0x2001, 0x00a0, - 0x080c, 0x2d39, 0x080c, 0x7932, 0x080c, 0x612e, 0x9085, 0x0001, - 0x00f8, 0x080c, 0x1b06, 0x2001, 0x0080, 0x080c, 0x2d39, 0x2069, - 0x0140, 0x60e3, 0x0000, 0x70b4, 0x9005, 0x1118, 0x6887, 0x0001, - 0x0008, 0x6886, 0x2001, 0x180d, 0x2004, 0xd08c, 0x2001, 0x0002, - 0x1118, 0x2001, 0x196d, 0x2004, 0x080c, 0x28e7, 0x60e2, 0x9006, - 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, - 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, 0x2061, - 0x0100, 0x2071, 0x1800, 0x6020, 0x9084, 0x00c0, 0x01c8, 0x2011, - 0x0003, 0x080c, 0xaabf, 0x2011, 0x0002, 0x080c, 0xaac9, 0x080c, - 0xa9d3, 0x901e, 0x080c, 0xaa49, 0x2069, 0x0140, 0x2001, 0x00a0, - 0x080c, 0x2d39, 0x080c, 0x7932, 0x080c, 0x612e, 0x0804, 0x78b2, - 0x2001, 0x180c, 0x200c, 0xd1b4, 0x1160, 0xc1b5, 0x2102, 0x080c, - 0x749a, 0x2069, 0x0140, 0x2001, 0x0080, 0x080c, 0x2d39, 0x60e3, - 0x0000, 0x2069, 0x0200, 0x6804, 0x9005, 0x1118, 0x6808, 0x9005, - 0x0180, 0x6028, 0x9084, 0xfdff, 0x602a, 0x6027, 0x0200, 0x2069, - 0x198f, 0x7000, 0x206a, 0x709b, 0x0027, 0x7003, 0x0001, 0x0804, - 0x78b2, 0x6027, 0x1e00, 0x2009, 0x1e00, 0x080c, 0x2c61, 0x6024, - 0x910c, 0x01c8, 0x9084, 0x1c00, 0x11b0, 0x1d04, 0x7869, 0x0006, - 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x080c, 0x8776, 0x00ee, 0x00de, - 0x00ce, 0x001e, 0x000e, 0x00e6, 0x2071, 0x19fb, 0x7078, 0x00ee, - 0x9005, 0x19f8, 0x0438, 0x0026, 0x2011, 0x74b2, 0x080c, 0x883d, - 0x2011, 0x74a5, 0x080c, 0x8917, 0x002e, 0x2069, 0x0140, 0x60e3, - 0x0000, 0x70b4, 0x9005, 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, - 0x2001, 0x180d, 0x2004, 0xd08c, 0x2001, 0x0002, 0x1118, 0x2001, - 0x196d, 0x2004, 0x080c, 0x28e7, 0x60e2, 0x2001, 0x180c, 0x200c, - 0xc1b4, 0x2102, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, - 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x0046, 0x00c6, - 0x00e6, 0x2061, 0x0100, 0x2071, 0x1800, 0x080c, 0xd7dc, 0x1904, - 0x7920, 0x7130, 0xd184, 0x1170, 0x080c, 0x33aa, 0x0138, 0xc18d, - 0x7132, 0x2011, 0x1848, 0x2214, 0xd2ac, 0x1120, 0x7030, 0xd08c, - 0x0904, 0x7920, 0x2011, 0x1848, 0x220c, 0xd1a4, 0x0538, 0x0016, - 0x2019, 0x000e, 0x080c, 0xeba1, 0x0156, 0x00b6, 0x20a9, 0x007f, - 0x900e, 0x9186, 0x007e, 0x01a0, 0x9186, 0x0080, 0x0188, 0x080c, - 0x6724, 0x1170, 0x2120, 0x9006, 0x0016, 0x2009, 0x000e, 0x080c, - 0xec31, 0x2009, 0x0001, 0x2011, 0x0100, 0x080c, 0x8a50, 0x001e, - 0x8108, 0x1f04, 0x78e9, 0x00be, 0x015e, 0x001e, 0xd1ac, 0x1148, - 0x0016, 0x2009, 0x0002, 0x2019, 0x0004, 0x080c, 0x321b, 0x001e, - 0x0078, 0x0156, 0x00b6, 0x20a9, 0x007f, 0x900e, 0x080c, 0x6724, - 0x1110, 0x080c, 0x6148, 0x8108, 0x1f04, 0x7916, 0x00be, 0x015e, - 0x080c, 0x1b06, 0x080c, 0xb244, 0x60e3, 0x0000, 0x080c, 0x612e, - 0x080c, 0x7563, 0x00ee, 0x00ce, 0x004e, 0x003e, 0x002e, 0x001e, - 0x015e, 0x0005, 0x2001, 0x197d, 0x2003, 0x0001, 0x0005, 0x2001, - 0x197d, 0x2003, 0x0000, 0x0005, 0x2001, 0x197c, 0x2003, 0xaaaa, - 0x0005, 0x2001, 0x197c, 0x2003, 0x0000, 0x0005, 0x2071, 0x18fa, - 0x7003, 0x0000, 0x7007, 0x0000, 0x080c, 0x1027, 0x090c, 0x0dc5, - 0xa8ab, 0xdcb0, 0x2900, 0x704e, 0x080c, 0x1027, 0x090c, 0x0dc5, - 0xa8ab, 0xdcb0, 0x2900, 0x7052, 0xa867, 0x0000, 0xa86b, 0x0001, - 0xa89f, 0x0000, 0x0005, 0x00e6, 0x2071, 0x0040, 0x6848, 0x9005, - 0x1118, 0x9085, 0x0001, 0x04b0, 0x6840, 0x9005, 0x0150, 0x04a1, - 0x6a50, 0x9200, 0x7002, 0x6854, 0x9101, 0x7006, 0x9006, 0x7012, - 0x7016, 0x6850, 0x7002, 0x6854, 0x7006, 0x6858, 0x700a, 0x685c, - 0x700e, 0x6840, 0x9005, 0x1110, 0x7012, 0x7016, 0x6848, 0x701a, - 0x701c, 0x9085, 0x0040, 0x701e, 0x2001, 0x0019, 0x7036, 0x702b, - 0x0001, 0x2001, 0x0004, 0x200c, 0x918c, 0xfff7, 0x918d, 0x8000, - 0x2102, 0x00d6, 0x2069, 0x18fa, 0x6807, 0x0001, 0x00de, 0x080c, - 0x7f74, 0x9006, 0x00ee, 0x0005, 0x900e, 0x0156, 0x20a9, 0x0006, - 0x8003, 0x2011, 0x0100, 0x2214, 0x9296, 0x0008, 0x1110, 0x818d, - 0x0010, 0x81f5, 0x3e08, 0x1f04, 0x79a8, 0x015e, 0x0005, 0x2079, - 0x0040, 0x2071, 0x18fa, 0x7004, 0x0002, 0x79c7, 0x79c8, 0x7a00, - 0x7a5b, 0x7bbb, 0x79c5, 0x79c5, 0x7be5, 0x080c, 0x0dc5, 0x0005, - 0x2079, 0x0040, 0x782c, 0x908c, 0x0780, 0x190c, 0x8056, 0xd0a4, - 0x01f8, 0x7824, 0x2048, 0x9006, 0xa802, 0xa806, 0xa864, 0x9084, - 0x00ff, 0x908a, 0x0040, 0x0610, 0x00c0, 0x2001, 0x1800, 0x200c, - 0x9186, 0x0003, 0x1168, 0x7004, 0x0002, 0x79f0, 0x79ca, 0x79f0, - 0x79ee, 0x79f0, 0x79f0, 0x79f0, 0x79f0, 0x79f0, 0x080c, 0x7a5b, - 0x782c, 0xd09c, 0x090c, 0x7f74, 0x0005, 0x9082, 0x005a, 0x1218, - 0x2100, 0x003b, 0x0c10, 0x080c, 0x7a91, 0x0c90, 0x00e3, 0x08e8, - 0x0005, 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7a91, - 0x7a91, 0x7ab3, 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7a91, - 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7a91, - 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7a9d, 0x7a91, 0x7cdb, - 0x7a91, 0x7a91, 0x7a91, 0x7ab3, 0x7a91, 0x7a9d, 0x7d1c, 0x7d5d, - 0x7da4, 0x7db8, 0x7a91, 0x7a91, 0x7ab3, 0x7a9d, 0x7ac7, 0x7a91, - 0x7b8f, 0x7e63, 0x7e7e, 0x7a91, 0x7ab3, 0x7a91, 0x7ac7, 0x7a91, - 0x7a91, 0x7b85, 0x7e7e, 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7a91, - 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7adb, 0x7a91, 0x7a91, 0x7a91, - 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7ffa, 0x7a91, - 0x7fa4, 0x7a91, 0x7fa4, 0x7a91, 0x7af0, 0x7a91, 0x7a91, 0x7a91, - 0x7a91, 0x7a91, 0x7a91, 0x2079, 0x0040, 0x7004, 0x9086, 0x0003, - 0x1198, 0x782c, 0x080c, 0x7f9d, 0xd0a4, 0x0170, 0x7824, 0x2048, - 0x9006, 0xa802, 0xa806, 0xa864, 0x9084, 0x00ff, 0x908a, 0x001a, - 0x1210, 0x002b, 0x0c50, 0x00e9, 0x080c, 0x7f74, 0x0005, 0x7a91, - 0x7a9d, 0x7cc7, 0x7a91, 0x7a9d, 0x7a91, 0x7a9d, 0x7a9d, 0x7a91, - 0x7a9d, 0x7cc7, 0x7a9d, 0x7a9d, 0x7a9d, 0x7a9d, 0x7a9d, 0x7a91, - 0x7a9d, 0x7cc7, 0x7a91, 0x7a91, 0x7a9d, 0x7a91, 0x7a91, 0x7a91, - 0x7a9d, 0x00e6, 0x2071, 0x18fa, 0x2009, 0x0400, 0x0071, 0x00ee, - 0x0005, 0x2009, 0x1000, 0x0049, 0x0005, 0x2009, 0x2000, 0x0029, - 0x0005, 0x2009, 0x0800, 0x0009, 0x0005, 0x7007, 0x0001, 0xa868, - 0x9084, 0x00ff, 0x9105, 0xa86a, 0x0126, 0x2091, 0x8000, 0x080c, - 0x6e9f, 0x012e, 0x0005, 0xa864, 0x8007, 0x9084, 0x00ff, 0x0d08, - 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, 0x7c64, 0x7007, 0x0003, - 0x7012, 0x2900, 0x7016, 0x701a, 0x704b, 0x7c64, 0x0005, 0xa864, - 0x8007, 0x9084, 0x00ff, 0x0968, 0x8001, 0x1120, 0x7007, 0x0001, - 0x0804, 0x7c7f, 0x7007, 0x0003, 0x7012, 0x2900, 0x7016, 0x701a, - 0x704b, 0x7c7f, 0x0005, 0xa864, 0x8007, 0x9084, 0x00ff, 0x0904, - 0x7a99, 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, 0x7c9b, 0x7007, - 0x0003, 0x7012, 0x2900, 0x7016, 0x701a, 0x704b, 0x7c9b, 0x0005, - 0xa864, 0x8007, 0x9084, 0x00ff, 0x9086, 0x0001, 0x1904, 0x7a99, - 0x7007, 0x0001, 0x2009, 0x1834, 0x210c, 0x81ff, 0x1904, 0x7b5c, - 0x2001, 0x180d, 0x2004, 0xd08c, 0x0904, 0x7b47, 0xa99c, 0x9186, - 0x00ff, 0x05e8, 0xa994, 0x9186, 0x006f, 0x0188, 0x9186, 0x0074, - 0x15b0, 0x0026, 0x2011, 0x0010, 0x080c, 0x6ac7, 0x002e, 0x0578, - 0x0016, 0xa998, 0x080c, 0x6b11, 0x001e, 0x1548, 0x0400, 0x080c, - 0x7637, 0x0140, 0xa897, 0x4005, 0xa89b, 0x0016, 0x2001, 0x0030, - 0x900e, 0x0438, 0x0026, 0x2011, 0x8008, 0x080c, 0x6ac7, 0x002e, - 0x01b0, 0x0016, 0x0026, 0x0036, 0xa998, 0xaaa0, 0xab9c, 0x918d, - 0x8000, 0x080c, 0x6b11, 0x003e, 0x002e, 0x001e, 0x1140, 0xa897, - 0x4005, 0xa89b, 0x4009, 0x2001, 0x0030, 0x900e, 0x0050, 0xa868, - 0x9084, 0x00ff, 0xa86a, 0xa883, 0x0000, 0x080c, 0x63c5, 0x1108, - 0x0005, 0x0126, 0x2091, 0x8000, 0xa867, 0x0139, 0xa87a, 0xa982, - 0x080c, 0x6e9f, 0x012e, 0x0ca0, 0xa994, 0x9186, 0x0071, 0x0904, - 0x7b00, 0x9186, 0x0064, 0x0904, 0x7b00, 0x9186, 0x007c, 0x0904, - 0x7b00, 0x9186, 0x0028, 0x0904, 0x7b00, 0x9186, 0x0038, 0x0904, - 0x7b00, 0x9186, 0x0078, 0x0904, 0x7b00, 0x9186, 0x005f, 0x0904, - 0x7b00, 0x9186, 0x0056, 0x0904, 0x7b00, 0xa897, 0x4005, 0xa89b, - 0x0001, 0x2001, 0x0030, 0x900e, 0x0860, 0xa87c, 0x9084, 0x00c0, - 0x9086, 0x00c0, 0x1120, 0x7007, 0x0001, 0x0804, 0x7e95, 0x2900, - 0x7016, 0x701a, 0x20a9, 0x0004, 0xa860, 0x20e0, 0xa85c, 0x9080, - 0x0030, 0x2098, 0x7050, 0x2040, 0xa060, 0x20e8, 0xa05c, 0x9080, - 0x0023, 0x20a0, 0x4003, 0xa888, 0x7012, 0x9082, 0x0401, 0x1a04, - 0x7aa1, 0xaab4, 0x928a, 0x0002, 0x1a04, 0x7aa1, 0x82ff, 0x1138, - 0xa8b8, 0xa9bc, 0x9105, 0x0118, 0x2001, 0x7c22, 0x0018, 0x9280, - 0x7c18, 0x2005, 0x7056, 0x7010, 0x9015, 0x0904, 0x7c03, 0x080c, - 0x1027, 0x1118, 0x7007, 0x0004, 0x0005, 0x2900, 0x7022, 0x7054, - 0x2060, 0xe000, 0xa866, 0x7050, 0x2040, 0xa95c, 0xe004, 0x9100, - 0xa076, 0xa860, 0xa072, 0xe008, 0x920a, 0x1210, 0x900e, 0x2200, - 0x7112, 0xe20c, 0x8003, 0x800b, 0x9296, 0x0004, 0x0108, 0x9108, - 0xa17a, 0x810b, 0xa17e, 0x080c, 0x10f8, 0xa06c, 0x908e, 0x0100, - 0x0170, 0x9086, 0x0200, 0x0118, 0x7007, 0x0007, 0x0005, 0x7020, - 0x2048, 0x080c, 0x1040, 0x7014, 0x2048, 0x0804, 0x7aa1, 0x7020, - 0x2048, 0x7018, 0xa802, 0xa807, 0x0000, 0x2908, 0x2048, 0xa906, - 0x711a, 0x0804, 0x7bbb, 0x7014, 0x2048, 0x7007, 0x0001, 0xa8b4, - 0x9005, 0x1128, 0xa8b8, 0xa9bc, 0x9105, 0x0108, 0x00b9, 0xa864, - 0x9084, 0x00ff, 0x9086, 0x001e, 0x0904, 0x7e95, 0x0804, 0x7c64, - 0x7c1a, 0x7c1e, 0x0002, 0x001d, 0x0007, 0x0004, 0x000a, 0x001b, - 0x0005, 0x0006, 0x000a, 0x001d, 0x0005, 0x0004, 0x0076, 0x0066, - 0xafb8, 0xaebc, 0xa804, 0x2050, 0xb0c0, 0xb0e2, 0xb0bc, 0xb0de, - 0xb0b8, 0xb0d2, 0xb0b4, 0xb0ce, 0xb6da, 0xb7d6, 0xb0b0, 0xb0ca, - 0xb0ac, 0xb0c6, 0xb0a8, 0xb0ba, 0xb0a4, 0xb0b6, 0xb6c2, 0xb7be, - 0xb0a0, 0xb0b2, 0xb09c, 0xb0ae, 0xb098, 0xb0a2, 0xb094, 0xb09e, - 0xb6aa, 0xb7a6, 0xb090, 0xb09a, 0xb08c, 0xb096, 0xb088, 0xb08a, - 0xb084, 0xb086, 0xb692, 0xb78e, 0xb080, 0xb082, 0xb07c, 0xb07e, - 0xb078, 0xb072, 0xb074, 0xb06e, 0xb67a, 0xb776, 0xb004, 0x9055, - 0x1958, 0x006e, 0x007e, 0x0005, 0x2009, 0x1834, 0x210c, 0x81ff, - 0x1178, 0x080c, 0x61c2, 0x1108, 0x0005, 0x080c, 0x710b, 0x0126, - 0x2091, 0x8000, 0x080c, 0xd3ce, 0x080c, 0x6e9f, 0x012e, 0x0ca0, - 0x080c, 0xd7dc, 0x1d70, 0x2001, 0x0028, 0x900e, 0x0c70, 0x2009, - 0x1834, 0x210c, 0x81ff, 0x1188, 0xa888, 0x9005, 0x0188, 0xa883, - 0x0000, 0x080c, 0x6252, 0x1108, 0x0005, 0xa87a, 0x0126, 0x2091, - 0x8000, 0x080c, 0x6e9f, 0x012e, 0x0cb8, 0x2001, 0x0028, 0x0ca8, - 0x2001, 0x0000, 0x0c90, 0x0419, 0x11d8, 0xa888, 0x9005, 0x01e0, - 0xa883, 0x0000, 0xa87c, 0xd0f4, 0x0120, 0x080c, 0x6327, 0x1138, - 0x0005, 0x9006, 0xa87a, 0x080c, 0x629f, 0x1108, 0x0005, 0x0126, - 0x2091, 0x8000, 0xa87a, 0xa982, 0x080c, 0x6e9f, 0x012e, 0x0cb0, - 0x2001, 0x0028, 0x900e, 0x0c98, 0x2001, 0x0000, 0x0c80, 0x00c6, - 0x2061, 0x1800, 0x60d0, 0x9005, 0x0100, 0x00ce, 0x0005, 0x7018, - 0xa802, 0x2908, 0x2048, 0xa906, 0x711a, 0x7010, 0x8001, 0x7012, - 0x0118, 0x7007, 0x0003, 0x0030, 0x7014, 0x2048, 0x7007, 0x0001, - 0x7048, 0x080f, 0x0005, 0x00b6, 0x7007, 0x0001, 0xa974, 0xa878, - 0x9084, 0x00ff, 0x9096, 0x0004, 0x0540, 0x20a9, 0x0001, 0x9096, - 0x0001, 0x0190, 0x900e, 0x20a9, 0x0800, 0x9096, 0x0002, 0x0160, - 0x9005, 0x11d8, 0xa974, 0x080c, 0x6724, 0x11b8, 0x0066, 0xae80, - 0x080c, 0x6834, 0x006e, 0x0088, 0x0046, 0x2011, 0x180c, 0x2224, - 0xc484, 0x2412, 0x004e, 0x00c6, 0x080c, 0x6724, 0x1110, 0x080c, - 0x6934, 0x8108, 0x1f04, 0x7d04, 0x00ce, 0xa87c, 0xd084, 0x1120, - 0x080c, 0x1040, 0x00be, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, - 0x6e9f, 0x012e, 0x00be, 0x0005, 0x0126, 0x2091, 0x8000, 0x7007, - 0x0001, 0x080c, 0x6a9f, 0x0580, 0x2061, 0x1a74, 0x6100, 0xd184, - 0x0178, 0xa888, 0x9084, 0x00ff, 0x1550, 0x6000, 0xd084, 0x0520, - 0x6004, 0x9005, 0x1538, 0x6003, 0x0000, 0x600b, 0x0000, 0x00c8, - 0x2011, 0x0001, 0xa890, 0x9005, 0x1110, 0x2001, 0x001e, 0x8000, - 0x6016, 0xa888, 0x9084, 0x00ff, 0x0178, 0x6006, 0xa888, 0x8007, - 0x9084, 0x00ff, 0x0148, 0x600a, 0xa888, 0x8000, 0x1108, 0xc28d, - 0x6202, 0x012e, 0x0804, 0x7f5e, 0x012e, 0x0804, 0x7f58, 0x012e, - 0x0804, 0x7f52, 0x012e, 0x0804, 0x7f55, 0x0126, 0x2091, 0x8000, - 0x7007, 0x0001, 0x080c, 0x6a9f, 0x05e0, 0x2061, 0x1a74, 0x6000, - 0xd084, 0x05b8, 0x6204, 0x6308, 0xd08c, 0x1530, 0xac78, 0x9484, - 0x0003, 0x0170, 0xa988, 0x918c, 0x00ff, 0x8001, 0x1120, 0x2100, - 0x9210, 0x0620, 0x0028, 0x8001, 0x1508, 0x2100, 0x9212, 0x02f0, - 0x9484, 0x000c, 0x0188, 0xa988, 0x810f, 0x918c, 0x00ff, 0x9082, - 0x0004, 0x1120, 0x2100, 0x9318, 0x0288, 0x0030, 0x9082, 0x0004, - 0x1168, 0x2100, 0x931a, 0x0250, 0xa890, 0x9005, 0x0110, 0x8000, - 0x6016, 0x6206, 0x630a, 0x012e, 0x0804, 0x7f5e, 0x012e, 0x0804, - 0x7f5b, 0x012e, 0x0804, 0x7f58, 0x0126, 0x2091, 0x8000, 0x7007, - 0x0001, 0x2061, 0x1a74, 0x6300, 0xd38c, 0x1120, 0x6308, 0x8318, - 0x0220, 0x630a, 0x012e, 0x0804, 0x7f6c, 0x012e, 0x0804, 0x7f5b, - 0x00b6, 0x0126, 0x00c6, 0x2091, 0x8000, 0x7007, 0x0001, 0xa87c, - 0xd0ac, 0x0148, 0x00c6, 0x2061, 0x1a74, 0x6000, 0x9084, 0xfcff, - 0x6002, 0x00ce, 0x0440, 0xa888, 0x9005, 0x05d8, 0xa88c, 0x9065, - 0x0598, 0x2001, 0x1834, 0x2004, 0x9005, 0x0118, 0x080c, 0xb306, - 0x0068, 0x6017, 0xf400, 0x605b, 0x0000, 0xa97c, 0xd1a4, 0x0110, - 0xa980, 0x615a, 0x2009, 0x0041, 0x080c, 0xb352, 0xa988, 0x918c, - 0xff00, 0x9186, 0x2000, 0x1138, 0x0026, 0x900e, 0x2011, 0xfdff, - 0x080c, 0x8a50, 0x002e, 0xa87c, 0xd0c4, 0x0148, 0x2061, 0x1a74, - 0x6000, 0xd08c, 0x1120, 0x6008, 0x8000, 0x0208, 0x600a, 0x00ce, - 0x012e, 0x00be, 0x0804, 0x7f5e, 0x00ce, 0x012e, 0x00be, 0x0804, - 0x7f58, 0xa984, 0x9186, 0x002e, 0x0d30, 0x9186, 0x002d, 0x0d18, - 0x9186, 0x0045, 0x0510, 0x9186, 0x002a, 0x1130, 0x2001, 0x180c, - 0x200c, 0xc194, 0x2102, 0x08b8, 0x9186, 0x0020, 0x0158, 0x9186, - 0x0029, 0x1d10, 0xa974, 0x080c, 0x6724, 0x1968, 0xb800, 0xc0e4, - 0xb802, 0x0848, 0xa88c, 0x9065, 0x09b8, 0x6007, 0x0024, 0x2001, - 0x1986, 0x2004, 0x601a, 0x0804, 0x7df3, 0xa88c, 0x9065, 0x0960, - 0x00e6, 0xa890, 0x9075, 0x2001, 0x1834, 0x2004, 0x9005, 0x0150, - 0x080c, 0xb306, 0x8eff, 0x0118, 0x2e60, 0x080c, 0xb306, 0x00ee, - 0x0804, 0x7df3, 0x6024, 0xc0dc, 0xc0d5, 0x6026, 0x2e60, 0x6007, - 0x003a, 0xa8a0, 0x9005, 0x0130, 0x6007, 0x003b, 0xa8a4, 0x602e, - 0xa8a8, 0x6016, 0x6003, 0x0001, 0x080c, 0x94ff, 0x080c, 0x9ab1, - 0x00ee, 0x0804, 0x7df3, 0x2061, 0x1a74, 0x6000, 0xd084, 0x0190, - 0xd08c, 0x1904, 0x7f6c, 0x0126, 0x2091, 0x8000, 0x6204, 0x8210, - 0x0220, 0x6206, 0x012e, 0x0804, 0x7f6c, 0x012e, 0xa883, 0x0016, - 0x0804, 0x7f65, 0xa883, 0x0007, 0x0804, 0x7f65, 0xa864, 0x8007, - 0x9084, 0x00ff, 0x0130, 0x8001, 0x1138, 0x7007, 0x0001, 0x0069, - 0x0005, 0x080c, 0x7a99, 0x0040, 0x7007, 0x0003, 0x7012, 0x2900, - 0x7016, 0x701a, 0x704b, 0x7e95, 0x0005, 0x00b6, 0x00e6, 0x0126, - 0x2091, 0x8000, 0x903e, 0x2061, 0x1800, 0x61d0, 0x81ff, 0x1904, - 0x7f17, 0x6130, 0xd194, 0x1904, 0x7f41, 0xa878, 0x2070, 0x9e82, - 0x1cd0, 0x0a04, 0x7f0b, 0x6068, 0x9e02, 0x1a04, 0x7f0b, 0x7120, - 0x9186, 0x0006, 0x1904, 0x7efd, 0x7010, 0x905d, 0x0904, 0x7f17, - 0xb800, 0xd0e4, 0x1904, 0x7f3b, 0x2061, 0x1a74, 0x6100, 0x9184, - 0x0301, 0x9086, 0x0001, 0x15a0, 0x7024, 0xd0dc, 0x1904, 0x7f44, - 0xa883, 0x0000, 0xa803, 0x0000, 0x2908, 0x7014, 0x9005, 0x1198, - 0x7116, 0xa87c, 0xd0f4, 0x1904, 0x7f47, 0x080c, 0x57d5, 0xd09c, - 0x1118, 0xa87c, 0xc0cc, 0xa87e, 0x2e60, 0x080c, 0x8970, 0x012e, - 0x00ee, 0x00be, 0x0005, 0x2048, 0xa800, 0x9005, 0x1de0, 0xa902, - 0x2148, 0xa87c, 0xd0f4, 0x1904, 0x7f47, 0x012e, 0x00ee, 0x00be, - 0x0005, 0x012e, 0x00ee, 0xa883, 0x0006, 0x00be, 0x0804, 0x7f65, - 0xd184, 0x0db8, 0xd1c4, 0x1190, 0x00a0, 0xa974, 0x080c, 0x6724, - 0x15d0, 0xb800, 0xd0e4, 0x15b8, 0x7120, 0x9186, 0x0007, 0x1118, - 0xa883, 0x0002, 0x0490, 0xa883, 0x0008, 0x0478, 0xa883, 0x000e, - 0x0460, 0xa883, 0x0017, 0x0448, 0xa883, 0x0035, 0x0430, 0x080c, - 0x57d9, 0xd0fc, 0x01e8, 0xa878, 0x2070, 0x9e82, 0x1cd0, 0x02c0, - 0x6068, 0x9e02, 0x12a8, 0x7120, 0x9186, 0x0006, 0x1188, 0x7010, - 0x905d, 0x0170, 0xb800, 0xd0bc, 0x0158, 0x2039, 0x0001, 0x7000, - 0x9086, 0x0007, 0x1904, 0x7ea1, 0x7003, 0x0002, 0x0804, 0x7ea1, - 0xa883, 0x0028, 0x0010, 0xa883, 0x0029, 0x012e, 0x00ee, 0x00be, - 0x0420, 0xa883, 0x002a, 0x0cc8, 0xa883, 0x0045, 0x0cb0, 0x2e60, - 0x2019, 0x0002, 0x601b, 0x0014, 0x080c, 0xe754, 0x012e, 0x00ee, - 0x00be, 0x0005, 0x2009, 0x003e, 0x0058, 0x2009, 0x0004, 0x0040, - 0x2009, 0x0006, 0x0028, 0x2009, 0x0016, 0x0010, 0x2009, 0x0001, - 0xa884, 0x9084, 0xff00, 0x9105, 0xa886, 0x0126, 0x2091, 0x8000, - 0x080c, 0x6e9f, 0x012e, 0x0005, 0x080c, 0x1040, 0x0005, 0x00d6, - 0x080c, 0x8967, 0x00de, 0x0005, 0x00d6, 0x00e6, 0x0126, 0x2091, - 0x8000, 0x2071, 0x0040, 0x702c, 0xd084, 0x01d8, 0x908c, 0x0780, - 0x190c, 0x8056, 0xd09c, 0x11a8, 0x2071, 0x1800, 0x70c0, 0x90ea, - 0x0020, 0x0278, 0x8001, 0x70c2, 0x702c, 0x2048, 0xa800, 0x702e, - 0x9006, 0xa802, 0xa806, 0x2071, 0x0040, 0x2900, 0x7022, 0x702c, - 0x0c28, 0x012e, 0x00ee, 0x00de, 0x0005, 0x0006, 0x9084, 0x0780, - 0x190c, 0x8056, 0x000e, 0x0005, 0xa898, 0x9084, 0x0003, 0x05a8, - 0x080c, 0xb27d, 0x05d8, 0x2900, 0x6016, 0xa864, 0x9084, 0x00ff, - 0x9086, 0x0035, 0x1138, 0x6008, 0xc0fd, 0x600a, 0x2001, 0x196b, - 0x2004, 0x0098, 0xa8a0, 0x9084, 0x00ff, 0xa99c, 0x918c, 0xff00, - 0x9105, 0xa99c, 0x918c, 0x00ff, 0x080c, 0x2873, 0x1540, 0x00b6, - 0x080c, 0x6724, 0x2b00, 0x00be, 0x1510, 0x6012, 0x6023, 0x0001, - 0x2009, 0x0040, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0035, 0x0110, - 0x2009, 0x0041, 0x080c, 0xb352, 0x0005, 0xa87b, 0x0101, 0x0126, - 0x2091, 0x8000, 0x080c, 0x6e9f, 0x012e, 0x0005, 0xa87b, 0x002c, - 0x0126, 0x2091, 0x8000, 0x080c, 0x6e9f, 0x012e, 0x0005, 0xa87b, - 0x0028, 0x0126, 0x2091, 0x8000, 0x080c, 0x6e9f, 0x012e, 0x080c, - 0xb2d3, 0x0005, 0x00d6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x00b6, - 0x7007, 0x0001, 0xaa74, 0x9282, 0x0004, 0x1a04, 0x8047, 0xa97c, - 0x9188, 0x1000, 0x2104, 0x905d, 0xb804, 0xd284, 0x0140, 0x05e8, - 0x8007, 0x9084, 0x00ff, 0x9084, 0x0006, 0x1108, 0x04b0, 0x2b10, - 0x080c, 0xb27d, 0x1118, 0x080c, 0xb325, 0x05a8, 0x6212, 0xa874, - 0x0002, 0x8025, 0x802a, 0x802d, 0x8033, 0x2019, 0x0002, 0x080c, - 0xeba1, 0x0060, 0x080c, 0xeb38, 0x0048, 0x2019, 0x0002, 0xa980, - 0x080c, 0xeb53, 0x0018, 0xa980, 0x080c, 0xeb38, 0x080c, 0xb2d3, - 0xa887, 0x0000, 0x0126, 0x2091, 0x8000, 0x080c, 0x6e9f, 0x012e, - 0x00be, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00de, 0x0005, 0xa887, - 0x0006, 0x0c80, 0xa887, 0x0002, 0x0c68, 0xa887, 0x0005, 0x0c50, - 0xa887, 0x0004, 0x0c38, 0xa887, 0x0007, 0x0c20, 0x2091, 0x8000, - 0x0e04, 0x8058, 0x0006, 0x0016, 0x2001, 0x8003, 0x0006, 0x0804, - 0x0dce, 0x2001, 0x1834, 0x2004, 0x9005, 0x0005, 0x0005, 0x00f6, - 0x2079, 0x0300, 0x2001, 0x0200, 0x200c, 0xc1e5, 0xc1dc, 0x2102, - 0x2009, 0x0218, 0x210c, 0xd1ec, 0x1120, 0x080c, 0x15a0, 0x00fe, - 0x0005, 0x2001, 0x020d, 0x2003, 0x0020, 0x781f, 0x0300, 0x00fe, - 0x0005, 0x781c, 0xd08c, 0x0904, 0x80d8, 0x68c0, 0x90aa, 0x0005, - 0x0a04, 0x871c, 0x7d44, 0x7c40, 0x9584, 0x00f6, 0x1510, 0x9484, - 0x7000, 0x0140, 0x908a, 0x2000, 0x1260, 0x9584, 0x0700, 0x8007, - 0x0804, 0x80df, 0x7000, 0x9084, 0xff00, 0x9086, 0x8100, 0x0da8, - 0x00b0, 0x9484, 0x0fff, 0x1130, 0x7000, 0x9084, 0xff00, 0x9086, - 0x8100, 0x11c0, 0x080c, 0xf057, 0x080c, 0x8601, 0x7817, 0x0140, - 0x00a8, 0x9584, 0x0076, 0x1118, 0x080c, 0x865f, 0x19c0, 0xd5a4, - 0x0148, 0x0046, 0x0056, 0x080c, 0x813a, 0x080c, 0x236e, 0x005e, - 0x004e, 0x0020, 0x080c, 0xf057, 0x7817, 0x0140, 0x080c, 0x7637, - 0x0168, 0x2001, 0x0111, 0x2004, 0xd08c, 0x0140, 0x6893, 0x0000, - 0x2001, 0x0110, 0x2003, 0x0008, 0x2003, 0x0000, 0x080c, 0x811b, - 0x2001, 0x19f1, 0x2004, 0x9005, 0x090c, 0x9ab1, 0x0005, 0x0002, - 0x80f1, 0x8409, 0x80e8, 0x80e8, 0x80e8, 0x80e8, 0x80e8, 0x80e8, - 0x7817, 0x0140, 0x2001, 0x19f1, 0x2004, 0x9005, 0x090c, 0x9ab1, - 0x0005, 0x7000, 0x908c, 0xff00, 0x9194, 0xf000, 0x810f, 0x9484, - 0x0fff, 0x6892, 0x9286, 0x2000, 0x1150, 0x6800, 0x9086, 0x0001, - 0x1118, 0x080c, 0x583f, 0x0070, 0x080c, 0x815a, 0x0058, 0x9286, - 0x3000, 0x1118, 0x080c, 0x8341, 0x0028, 0x9286, 0x8000, 0x1110, - 0x080c, 0x8528, 0x7817, 0x0140, 0x2001, 0x19f1, 0x2004, 0x9005, - 0x090c, 0x9ab1, 0x0005, 0x2001, 0x1810, 0x2004, 0xd08c, 0x0178, - 0x2001, 0x1800, 0x2004, 0x9086, 0x0003, 0x1148, 0x0026, 0x0036, - 0x2011, 0x8048, 0x2518, 0x080c, 0x4c44, 0x003e, 0x002e, 0x0005, - 0x0036, 0x0046, 0x0056, 0x00f6, 0x2079, 0x0200, 0x2019, 0xfffe, - 0x7c30, 0x0050, 0x0036, 0x0046, 0x0056, 0x00f6, 0x2079, 0x0200, - 0x7d44, 0x7c40, 0x2019, 0xffff, 0x2001, 0x1810, 0x2004, 0xd08c, - 0x0160, 0x2001, 0x1800, 0x2004, 0x9086, 0x0003, 0x1130, 0x0026, - 0x2011, 0x8048, 0x080c, 0x4c44, 0x002e, 0x00fe, 0x005e, 0x004e, - 0x003e, 0x0005, 0x00b6, 0x00c6, 0x7010, 0x9084, 0xff00, 0x8007, - 0x9096, 0x0001, 0x0120, 0x9096, 0x0023, 0x1904, 0x8312, 0x9186, - 0x0023, 0x15c0, 0x080c, 0x85c6, 0x0904, 0x8312, 0x6120, 0x9186, - 0x0001, 0x0150, 0x9186, 0x0004, 0x0138, 0x9186, 0x0008, 0x0120, - 0x9186, 0x000a, 0x1904, 0x8312, 0x7124, 0x610a, 0x7030, 0x908e, - 0x0200, 0x1130, 0x2009, 0x0015, 0x080c, 0xb352, 0x0804, 0x8312, - 0x908e, 0x0214, 0x0118, 0x908e, 0x0210, 0x1130, 0x2009, 0x0015, - 0x080c, 0xb352, 0x0804, 0x8312, 0x908e, 0x0100, 0x1904, 0x8312, - 0x7034, 0x9005, 0x1904, 0x8312, 0x2009, 0x0016, 0x080c, 0xb352, - 0x0804, 0x8312, 0x9186, 0x0022, 0x1904, 0x8312, 0x7030, 0x908e, - 0x0300, 0x1580, 0x68dc, 0xd0a4, 0x0528, 0xc0b5, 0x68de, 0x7100, - 0x918c, 0x00ff, 0x697e, 0x7004, 0x6882, 0x00f6, 0x2079, 0x0100, - 0x79e6, 0x78ea, 0x0006, 0x9084, 0x00ff, 0x0016, 0x2008, 0x080c, - 0x28bc, 0x7932, 0x7936, 0x001e, 0x000e, 0x00fe, 0x080c, 0x2873, - 0x695e, 0x703c, 0x00e6, 0x2071, 0x0140, 0x7086, 0x2071, 0x1800, - 0x70b6, 0x00ee, 0x7034, 0x9005, 0x1904, 0x8312, 0x2009, 0x0017, - 0x0804, 0x82c2, 0x908e, 0x0400, 0x1190, 0x7034, 0x9005, 0x1904, - 0x8312, 0x080c, 0x7637, 0x0120, 0x2009, 0x001d, 0x0804, 0x82c2, - 0x68dc, 0xc0a5, 0x68de, 0x2009, 0x0030, 0x0804, 0x82c2, 0x908e, - 0x0500, 0x1140, 0x7034, 0x9005, 0x1904, 0x8312, 0x2009, 0x0018, - 0x0804, 0x82c2, 0x908e, 0x2010, 0x1120, 0x2009, 0x0019, 0x0804, - 0x82c2, 0x908e, 0x2110, 0x1120, 0x2009, 0x001a, 0x0804, 0x82c2, - 0x908e, 0x5200, 0x1140, 0x7034, 0x9005, 0x1904, 0x8312, 0x2009, - 0x001b, 0x0804, 0x82c2, 0x908e, 0x5000, 0x1140, 0x7034, 0x9005, - 0x1904, 0x8312, 0x2009, 0x001c, 0x0804, 0x82c2, 0x908e, 0x1300, - 0x1120, 0x2009, 0x0034, 0x0804, 0x82c2, 0x908e, 0x1200, 0x1140, - 0x7034, 0x9005, 0x1904, 0x8312, 0x2009, 0x0024, 0x0804, 0x82c2, - 0x908c, 0xff00, 0x918e, 0x2400, 0x1170, 0x2009, 0x002d, 0x2001, - 0x1810, 0x2004, 0xd09c, 0x0904, 0x82c2, 0x080c, 0xdf1a, 0x1904, - 0x8312, 0x0804, 0x82c0, 0x908c, 0xff00, 0x918e, 0x5300, 0x1120, - 0x2009, 0x002a, 0x0804, 0x82c2, 0x908e, 0x0f00, 0x1120, 0x2009, - 0x0020, 0x0804, 0x82c2, 0x908e, 0x6104, 0x1530, 0x2029, 0x0205, - 0x2011, 0x026d, 0x8208, 0x2204, 0x9082, 0x0004, 0x8004, 0x8004, - 0x20a8, 0x2011, 0x8015, 0x211c, 0x8108, 0x0046, 0x2124, 0x080c, - 0x4c44, 0x004e, 0x8108, 0x0f04, 0x8276, 0x9186, 0x0280, 0x1d88, - 0x2504, 0x8000, 0x202a, 0x2009, 0x0260, 0x0c58, 0x202b, 0x0000, - 0x2009, 0x0023, 0x0804, 0x82c2, 0x908e, 0x6000, 0x1120, 0x2009, - 0x003f, 0x0804, 0x82c2, 0x908e, 0x5400, 0x1138, 0x080c, 0x86cc, - 0x1904, 0x8312, 0x2009, 0x0046, 0x04a8, 0x908e, 0x5500, 0x1148, - 0x080c, 0x86f4, 0x1118, 0x2009, 0x0041, 0x0460, 0x2009, 0x0042, - 0x0448, 0x908e, 0x7800, 0x1118, 0x2009, 0x0045, 0x0418, 0x908e, - 0x1000, 0x1118, 0x2009, 0x004e, 0x00e8, 0x908e, 0x6300, 0x1118, - 0x2009, 0x004a, 0x00b8, 0x908c, 0xff00, 0x918e, 0x5600, 0x1118, - 0x2009, 0x004f, 0x0078, 0x908c, 0xff00, 0x918e, 0x5700, 0x1118, - 0x2009, 0x0050, 0x0038, 0x2009, 0x001d, 0x6838, 0xd0d4, 0x0110, - 0x2009, 0x004c, 0x0016, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, - 0x080c, 0x2873, 0x1904, 0x8315, 0x080c, 0x66b9, 0x1904, 0x8315, - 0xbe12, 0xbd16, 0x001e, 0x0016, 0x080c, 0x7637, 0x01c0, 0x68dc, - 0xd08c, 0x1148, 0x7000, 0x9084, 0x00ff, 0x1188, 0x7004, 0x9084, - 0xff00, 0x1168, 0x0040, 0x687c, 0x9606, 0x1148, 0x6880, 0x9506, - 0x9084, 0xff00, 0x1120, 0x9584, 0x00ff, 0xb8c2, 0x0080, 0xb8c0, - 0x9005, 0x1168, 0x9186, 0x0046, 0x1150, 0x687c, 0x9606, 0x1138, - 0x6880, 0x9506, 0x9084, 0xff00, 0x1110, 0x001e, 0x0098, 0x080c, - 0xb27d, 0x01a8, 0x2b08, 0x6112, 0x6023, 0x0004, 0x7120, 0x610a, - 0x001e, 0x9186, 0x004c, 0x1110, 0x6023, 0x000a, 0x0016, 0x001e, - 0x080c, 0xb352, 0x00ce, 0x00be, 0x0005, 0x001e, 0x0cd8, 0x2001, - 0x180e, 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049, 0x080c, 0x4c44, - 0x080c, 0xb325, 0x0d90, 0x2b08, 0x6112, 0x6023, 0x0004, 0x7120, - 0x610a, 0x001e, 0x0016, 0x9186, 0x0017, 0x0118, 0x9186, 0x0030, - 0x1128, 0x6007, 0x0009, 0x6017, 0x2900, 0x0020, 0x6007, 0x0051, - 0x6017, 0x0000, 0x602f, 0x0009, 0x6003, 0x0001, 0x080c, 0x9547, - 0x08a0, 0x080c, 0x873b, 0x1158, 0x080c, 0x3374, 0x1140, 0x7010, - 0x9084, 0xff00, 0x8007, 0x908e, 0x0008, 0x1108, 0x0009, 0x0005, - 0x00b6, 0x00c6, 0x0046, 0x7000, 0x908c, 0xff00, 0x810f, 0x9186, - 0x0033, 0x11e8, 0x080c, 0x85c6, 0x0904, 0x83a1, 0x7124, 0x610a, - 0x7030, 0x908e, 0x0200, 0x1140, 0x7034, 0x9005, 0x15d0, 0x2009, - 0x0015, 0x080c, 0xb352, 0x04a8, 0x908e, 0x0100, 0x1590, 0x7034, - 0x9005, 0x1578, 0x2009, 0x0016, 0x080c, 0xb352, 0x0450, 0x9186, - 0x0032, 0x1538, 0x7030, 0x908e, 0x1400, 0x1518, 0x2009, 0x0038, - 0x0016, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x2873, - 0x11b8, 0x080c, 0x66b9, 0x11a0, 0xbe12, 0xbd16, 0x080c, 0xb27d, - 0x0178, 0x2b08, 0x6112, 0x080c, 0xd554, 0x6023, 0x0004, 0x7120, - 0x610a, 0x001e, 0x080c, 0xb352, 0x080c, 0x9ab1, 0x0010, 0x00ce, - 0x001e, 0x004e, 0x00ce, 0x00be, 0x0005, 0x00b6, 0x0046, 0x00e6, - 0x00d6, 0x2028, 0x2130, 0x9696, 0x00ff, 0x11b8, 0x9592, 0xfffc, - 0x02a0, 0x9596, 0xfffd, 0x1120, 0x2009, 0x007f, 0x0804, 0x8403, - 0x9596, 0xfffe, 0x1120, 0x2009, 0x007e, 0x0804, 0x8403, 0x9596, - 0xfffc, 0x1118, 0x2009, 0x0080, 0x04f0, 0x2011, 0x0000, 0x2019, - 0x1837, 0x231c, 0xd3ac, 0x0130, 0x9026, 0x20a9, 0x0800, 0x2071, - 0x1000, 0x0030, 0x2021, 0x0081, 0x20a9, 0x077f, 0x2071, 0x1081, - 0x2e1c, 0x93dd, 0x0000, 0x1140, 0x82ff, 0x11d0, 0x9496, 0x00ff, - 0x01b8, 0x2410, 0xc2fd, 0x00a0, 0xbf10, 0x2600, 0x9706, 0xb814, - 0x1120, 0x9546, 0x1110, 0x2408, 0x00b0, 0x9745, 0x1148, 0x94c6, - 0x007e, 0x0130, 0x94c6, 0x007f, 0x0118, 0x94c6, 0x0080, 0x1d20, - 0x8420, 0x8e70, 0x1f04, 0x83d8, 0x82ff, 0x1118, 0x9085, 0x0001, - 0x0018, 0xc2fc, 0x2208, 0x9006, 0x00de, 0x00ee, 0x004e, 0x00be, - 0x0005, 0x2001, 0x1837, 0x200c, 0x9184, 0x0080, 0x0110, 0xd18c, - 0x0138, 0x7000, 0x908c, 0xff00, 0x810f, 0x9184, 0x000f, 0x004a, - 0x7817, 0x0140, 0x2001, 0x19f1, 0x2004, 0x9005, 0x090c, 0x9ab1, - 0x0005, 0x8431, 0x8431, 0x8431, 0x85d8, 0x8431, 0x843a, 0x8465, - 0x84f3, 0x8431, 0x8431, 0x8431, 0x8431, 0x8431, 0x8431, 0x8431, - 0x8431, 0x7817, 0x0140, 0x2001, 0x19f1, 0x2004, 0x9005, 0x090c, - 0x9ab1, 0x0005, 0x00b6, 0x7110, 0xd1bc, 0x01e8, 0x7120, 0x2160, - 0x9c8c, 0x0007, 0x11c0, 0x9c8a, 0x1cd0, 0x02a8, 0x6868, 0x9c02, - 0x1290, 0x7008, 0x9084, 0x00ff, 0x6110, 0x2158, 0xb910, 0x9106, - 0x1150, 0x700c, 0xb914, 0x9106, 0x1130, 0x7124, 0x610a, 0x2009, - 0x0046, 0x080c, 0xb352, 0x7817, 0x0140, 0x2001, 0x19f1, 0x2004, - 0x9005, 0x090c, 0x9ab1, 0x00be, 0x0005, 0x00b6, 0x00c6, 0x9484, - 0x0fff, 0x0904, 0x84c9, 0x7110, 0xd1bc, 0x1904, 0x84c9, 0x7108, - 0x700c, 0x2028, 0x918c, 0x00ff, 0x2130, 0x9094, 0xff00, 0x15b0, - 0x81ff, 0x15a0, 0x9080, 0x33b6, 0x200d, 0x918c, 0xff00, 0x810f, - 0x2001, 0x0080, 0x9106, 0x0904, 0x84c9, 0x080c, 0x66b9, 0x1904, - 0x84c9, 0xbe12, 0xbd16, 0xb800, 0xd0ec, 0x15d8, 0xba04, 0x9294, - 0xff00, 0x9286, 0x0600, 0x11a0, 0x080c, 0xb27d, 0x05e8, 0x2b08, - 0x7028, 0x6046, 0x702c, 0x604a, 0x6112, 0x6023, 0x0006, 0x7120, - 0x610a, 0x7130, 0x6156, 0x2009, 0x0044, 0x080c, 0xe192, 0x0408, - 0x080c, 0x6aa3, 0x1138, 0xb807, 0x0606, 0x0c30, 0x190c, 0x83a5, - 0x11c0, 0x0898, 0x080c, 0xb27d, 0x2b08, 0x0198, 0x6112, 0x6023, - 0x0004, 0x7120, 0x610a, 0x9286, 0x0400, 0x1118, 0x6007, 0x0005, - 0x0010, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x9547, 0x080c, - 0x9ab1, 0x7817, 0x0140, 0x2001, 0x19f1, 0x2004, 0x9005, 0x090c, - 0x9ab1, 0x00ce, 0x00be, 0x0005, 0x2001, 0x180e, 0x2004, 0xd0ec, - 0x0120, 0x2011, 0x8049, 0x080c, 0x4c44, 0x080c, 0xb325, 0x0d48, - 0x2b08, 0x6112, 0x6023, 0x0006, 0x7120, 0x610a, 0x7130, 0x6156, - 0x6017, 0xf300, 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x94ff, - 0x080c, 0x9ab1, 0x08b0, 0x00b6, 0x7110, 0xd1bc, 0x01e8, 0x7020, - 0x2060, 0x9c84, 0x0007, 0x11c0, 0x9c82, 0x1cd0, 0x02a8, 0x6868, - 0x9c02, 0x1290, 0x7008, 0x9084, 0x00ff, 0x6110, 0x2158, 0xb910, - 0x9106, 0x1150, 0x700c, 0xb914, 0x9106, 0x1130, 0x7124, 0x610a, - 0x2009, 0x0045, 0x080c, 0xb352, 0x7817, 0x0140, 0x2001, 0x19f1, - 0x2004, 0x9005, 0x090c, 0x9ab1, 0x00be, 0x0005, 0x6120, 0x9186, - 0x0002, 0x0128, 0x9186, 0x0005, 0x0110, 0x9085, 0x0001, 0x0005, - 0x080c, 0x873b, 0x1180, 0x080c, 0x3374, 0x1168, 0x7010, 0x9084, - 0xff00, 0x8007, 0x9086, 0x0000, 0x1130, 0x9184, 0x000f, 0x908a, - 0x0006, 0x1208, 0x000b, 0x0005, 0x8542, 0x8543, 0x8542, 0x8542, - 0x85a8, 0x85b7, 0x0005, 0x00b6, 0x700c, 0x7108, 0x080c, 0x2873, - 0x1904, 0x85a6, 0x080c, 0x66b9, 0x1904, 0x85a6, 0xbe12, 0xbd16, - 0x7110, 0xd1bc, 0x0540, 0x702c, 0xd084, 0x1120, 0xb800, 0xd0bc, - 0x1904, 0x85a6, 0x080c, 0x6aa3, 0x0148, 0x9086, 0x0004, 0x0130, - 0x080c, 0x6aab, 0x0118, 0x9086, 0x0004, 0x1588, 0x00c6, 0x080c, - 0x85c6, 0x00ce, 0x05d8, 0x080c, 0xb27d, 0x2b08, 0x05b8, 0x6112, - 0x080c, 0xd554, 0x6023, 0x0002, 0x7120, 0x610a, 0x2009, 0x0088, - 0x080c, 0xb352, 0x0458, 0x080c, 0x6aa3, 0x0148, 0x9086, 0x0004, - 0x0130, 0x080c, 0x6aab, 0x0118, 0x9086, 0x0004, 0x1180, 0x080c, - 0xb27d, 0x2b08, 0x01d8, 0x6112, 0x080c, 0xd554, 0x6023, 0x0005, - 0x7120, 0x610a, 0x2009, 0x0088, 0x080c, 0xb352, 0x0078, 0x080c, - 0xb27d, 0x2b08, 0x0158, 0x6112, 0x080c, 0xd554, 0x6023, 0x0004, - 0x7120, 0x610a, 0x2009, 0x0001, 0x080c, 0xb352, 0x00be, 0x0005, - 0x7110, 0xd1bc, 0x0158, 0x00d1, 0x0148, 0x080c, 0x851e, 0x1130, - 0x7124, 0x610a, 0x2009, 0x0089, 0x080c, 0xb352, 0x0005, 0x7110, - 0xd1bc, 0x0158, 0x0059, 0x0148, 0x080c, 0x851e, 0x1130, 0x7124, - 0x610a, 0x2009, 0x008a, 0x080c, 0xb352, 0x0005, 0x7020, 0x2060, - 0x9c84, 0x0007, 0x1158, 0x9c82, 0x1cd0, 0x0240, 0x2001, 0x181a, - 0x2004, 0x9c02, 0x1218, 0x9085, 0x0001, 0x0005, 0x9006, 0x0ce8, - 0x00b6, 0x7110, 0xd1bc, 0x11d8, 0x7024, 0x2060, 0x9c84, 0x0007, - 0x11b0, 0x9c82, 0x1cd0, 0x0298, 0x6868, 0x9c02, 0x1280, 0x7008, - 0x9084, 0x00ff, 0x6110, 0x2158, 0xb910, 0x9106, 0x1140, 0x700c, - 0xb914, 0x9106, 0x1120, 0x2009, 0x0051, 0x080c, 0xb352, 0x7817, - 0x0140, 0x2001, 0x19f1, 0x2004, 0x9005, 0x090c, 0x9ab1, 0x00be, - 0x0005, 0x2031, 0x0105, 0x0069, 0x0005, 0x2031, 0x0206, 0x0049, - 0x0005, 0x2031, 0x0207, 0x0029, 0x0005, 0x2031, 0x0213, 0x0009, - 0x0005, 0x00c6, 0x0096, 0x00f6, 0x7000, 0x9084, 0xf000, 0x9086, - 0xc000, 0x05d0, 0x080c, 0xb27d, 0x05b8, 0x0066, 0x00c6, 0x0046, - 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x2873, 0x15a0, - 0x080c, 0x66b9, 0x1588, 0xbe12, 0xbd16, 0x2b00, 0x004e, 0x00ce, - 0x6012, 0x080c, 0xd554, 0x080c, 0x100e, 0x0510, 0x2900, 0x605a, - 0x9006, 0xa802, 0xa866, 0xac6a, 0xa85c, 0x90f8, 0x001b, 0x20a9, - 0x000e, 0xa860, 0x20e8, 0x20e1, 0x0000, 0x2fa0, 0x2e98, 0x4003, - 0x006e, 0x6616, 0x6007, 0x003e, 0x6023, 0x0001, 0x6003, 0x0001, - 0x080c, 0x9547, 0x080c, 0x9ab1, 0x00fe, 0x009e, 0x00ce, 0x0005, - 0x080c, 0xb2d3, 0x006e, 0x0cc0, 0x004e, 0x00ce, 0x0cc8, 0x00c6, - 0x7000, 0x908c, 0xff00, 0x9184, 0xf000, 0x810f, 0x9086, 0x2000, - 0x1904, 0x86b6, 0x9186, 0x0022, 0x15f0, 0x2001, 0x0111, 0x2004, - 0x9005, 0x1904, 0x86b8, 0x7030, 0x908e, 0x0400, 0x0904, 0x86b8, - 0x908e, 0x6000, 0x05e8, 0x908e, 0x5400, 0x05d0, 0x908e, 0x0300, - 0x11d8, 0x2009, 0x1837, 0x210c, 0xd18c, 0x1590, 0xd1a4, 0x1580, - 0x080c, 0x6a61, 0x0588, 0x68b0, 0x9084, 0x00ff, 0x7100, 0x918c, - 0x00ff, 0x9106, 0x1518, 0x6880, 0x69b0, 0x918c, 0xff00, 0x9105, - 0x7104, 0x9106, 0x11d8, 0x00e0, 0x2009, 0x0103, 0x210c, 0xd1b4, - 0x11a8, 0x908e, 0x5200, 0x09e8, 0x908e, 0x0500, 0x09d0, 0x908e, - 0x5000, 0x09b8, 0x0058, 0x9186, 0x0023, 0x1140, 0x080c, 0x85c6, - 0x0128, 0x6004, 0x9086, 0x0002, 0x0118, 0x0000, 0x9006, 0x0010, - 0x9085, 0x0001, 0x00ce, 0x0005, 0x7030, 0x908e, 0x0300, 0x0118, - 0x908e, 0x5200, 0x1d98, 0x2001, 0x1837, 0x2004, 0x9084, 0x0009, - 0x9086, 0x0008, 0x0d68, 0x0c50, 0x0156, 0x0046, 0x0016, 0x0036, - 0x7038, 0x2020, 0x8427, 0x94a4, 0x0007, 0xd484, 0x0148, 0x20a9, - 0x0004, 0x2019, 0x1805, 0x2011, 0x027a, 0x080c, 0xc365, 0x1178, - 0xd48c, 0x0148, 0x20a9, 0x0004, 0x2019, 0x1801, 0x2011, 0x027e, - 0x080c, 0xc365, 0x1120, 0xd494, 0x0110, 0x9085, 0x0001, 0x003e, - 0x001e, 0x004e, 0x015e, 0x0005, 0x0156, 0x0046, 0x0016, 0x0036, - 0x7038, 0x2020, 0x8427, 0x94a4, 0x0007, 0xd484, 0x0148, 0x20a9, - 0x0004, 0x2019, 0x1805, 0x2011, 0x0272, 0x080c, 0xc365, 0x1178, - 0xd48c, 0x0148, 0x20a9, 0x0004, 0x2019, 0x1801, 0x2011, 0x0276, - 0x080c, 0xc365, 0x1120, 0xd494, 0x0110, 0x9085, 0x0001, 0x003e, - 0x001e, 0x004e, 0x015e, 0x0005, 0x00f6, 0x2079, 0x0200, 0x7800, - 0xc0e5, 0xc0cc, 0x7802, 0x00fe, 0x0005, 0x00f6, 0x2079, 0x1800, - 0x7834, 0xd084, 0x1130, 0x2079, 0x0200, 0x7800, 0x9085, 0x1200, - 0x7802, 0x00fe, 0x0005, 0x00e6, 0x2071, 0x1800, 0x7034, 0xc084, - 0x7036, 0x00ee, 0x0005, 0x0016, 0x2001, 0x1837, 0x200c, 0x9184, - 0x0080, 0x0118, 0xd18c, 0x0118, 0x9006, 0x001e, 0x0005, 0x9085, - 0x0001, 0x0cd8, 0x2071, 0x19fb, 0x7003, 0x0003, 0x700f, 0x0361, - 0x9006, 0x701a, 0x707a, 0x7012, 0x7017, 0x1cd0, 0x7007, 0x0000, - 0x7026, 0x702b, 0xa6ff, 0x7032, 0x703a, 0x703f, 0x0064, 0x7037, - 0xa767, 0x7047, 0xffff, 0x704a, 0x704f, 0x5667, 0x7052, 0x7063, - 0x88de, 0x080c, 0x1027, 0x090c, 0x0dc5, 0x2900, 0x7042, 0xa867, - 0x0003, 0xa86f, 0x0100, 0xa8ab, 0xdcb0, 0x0005, 0x2071, 0x19fb, - 0x1d04, 0x882c, 0x2091, 0x6000, 0x700c, 0x8001, 0x700e, 0x1540, - 0x2001, 0x013c, 0x2004, 0x9005, 0x190c, 0x894c, 0x2001, 0x1869, - 0x2004, 0xd0c4, 0x0158, 0x3a00, 0xd08c, 0x1140, 0x20d1, 0x0000, - 0x20d1, 0x0001, 0x20d1, 0x0000, 0x080c, 0x0dc5, 0x700f, 0x0361, - 0x7007, 0x0001, 0x0126, 0x2091, 0x8000, 0x080c, 0x8923, 0x7048, - 0x900d, 0x0148, 0x8109, 0x714a, 0x1130, 0x704c, 0x080f, 0x0018, - 0x0126, 0x2091, 0x8000, 0x7024, 0x900d, 0x0188, 0x7020, 0x8001, - 0x7022, 0x1168, 0x7023, 0x0009, 0x8109, 0x7126, 0x9186, 0x03e8, - 0x1110, 0x7028, 0x080f, 0x81ff, 0x1110, 0x7028, 0x080f, 0x7030, - 0x900d, 0x05a8, 0x702c, 0x8001, 0x702e, 0x1588, 0x0016, 0x2009, - 0x0306, 0x210c, 0x9184, 0x0030, 0x01e8, 0x9184, 0x0048, 0x9086, - 0x0008, 0x11c0, 0x7038, 0x9005, 0x01a8, 0x8001, 0x703a, 0x1190, - 0x080c, 0x7637, 0x0178, 0x00e6, 0x2071, 0x19e8, 0x080c, 0xa7f5, - 0x00ee, 0x1140, 0x2009, 0x1a86, 0x2104, 0x8000, 0x0208, 0x200a, - 0x001e, 0x0068, 0x001e, 0x702f, 0x0009, 0x8109, 0x7132, 0x0128, - 0x9184, 0x007f, 0x090c, 0xa8ab, 0x0010, 0x7034, 0x080f, 0x7044, - 0x9005, 0x0118, 0x0310, 0x8001, 0x7046, 0x7054, 0x900d, 0x0168, - 0x7050, 0x8001, 0x7052, 0x1148, 0x7053, 0x0009, 0x8109, 0x7156, - 0x1120, 0x7158, 0x7156, 0x7060, 0x080f, 0x7018, 0x900d, 0x01d8, - 0x0016, 0x7078, 0x900d, 0x0158, 0x7074, 0x8001, 0x7076, 0x1138, - 0x7077, 0x0009, 0x8109, 0x717a, 0x1110, 0x707c, 0x080f, 0x001e, - 0x7008, 0x8001, 0x700a, 0x1138, 0x700b, 0x0009, 0x8109, 0x711a, - 0x1110, 0x701c, 0x080f, 0x012e, 0x7004, 0x0002, 0x8854, 0x8855, - 0x8871, 0x00e6, 0x2071, 0x19fb, 0x7018, 0x9005, 0x1120, 0x711a, - 0x721e, 0x700b, 0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x2071, - 0x19fb, 0x701c, 0x9206, 0x1120, 0x701a, 0x701e, 0x707a, 0x707e, - 0x000e, 0x00ee, 0x0005, 0x00e6, 0x2071, 0x19fb, 0xb888, 0x9102, - 0x0208, 0xb98a, 0x00ee, 0x0005, 0x0005, 0x00b6, 0x7110, 0x080c, - 0x6724, 0x1168, 0xb888, 0x8001, 0x0250, 0xb88a, 0x1140, 0x0126, - 0x2091, 0x8000, 0x0016, 0x080c, 0x9ab1, 0x001e, 0x012e, 0x8108, - 0x9182, 0x0800, 0x0218, 0x900e, 0x7007, 0x0002, 0x7112, 0x00be, - 0x0005, 0x7014, 0x2060, 0x0126, 0x2091, 0x8000, 0x6040, 0x9005, - 0x0128, 0x8001, 0x6042, 0x1110, 0x080c, 0xd3e5, 0x6018, 0x9005, - 0x0558, 0x8001, 0x601a, 0x1540, 0x6120, 0x9186, 0x0003, 0x0148, - 0x9186, 0x0006, 0x0130, 0x9186, 0x0009, 0x11e0, 0x611c, 0xd1c4, - 0x1100, 0x080c, 0xd0d8, 0x01b0, 0x6014, 0x2048, 0xa884, 0x908a, - 0x199a, 0x0280, 0x9082, 0x1999, 0xa886, 0x908a, 0x199a, 0x0210, - 0x2001, 0x1999, 0x8003, 0x800b, 0x810b, 0x9108, 0x611a, 0xa87c, - 0xd0e4, 0x0110, 0x080c, 0xcdbc, 0x012e, 0x9c88, 0x0018, 0x7116, - 0x2001, 0x181a, 0x2004, 0x9102, 0x0220, 0x7017, 0x1cd0, 0x7007, - 0x0000, 0x0005, 0x00e6, 0x2071, 0x19fb, 0x7027, 0x07d0, 0x7023, - 0x0009, 0x00ee, 0x0005, 0x2001, 0x1a04, 0x2003, 0x0000, 0x0005, - 0x00e6, 0x2071, 0x19fb, 0x7132, 0x702f, 0x0009, 0x00ee, 0x0005, - 0x2011, 0x1a07, 0x2013, 0x0000, 0x0005, 0x00e6, 0x2071, 0x19fb, - 0x711a, 0x721e, 0x700b, 0x0009, 0x00ee, 0x0005, 0x0086, 0x0026, - 0x705c, 0x8000, 0x705e, 0x2001, 0x1a0b, 0x2044, 0xa06c, 0x9086, - 0x0000, 0x0150, 0x7070, 0xa09a, 0x706c, 0xa096, 0x7068, 0xa092, - 0x7064, 0xa08e, 0x080c, 0x10f8, 0x002e, 0x008e, 0x0005, 0x0006, - 0x0016, 0x0096, 0x00a6, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, - 0x0156, 0x080c, 0x8776, 0x015e, 0x00fe, 0x00ee, 0x00de, 0x00ce, - 0x00be, 0x00ae, 0x009e, 0x001e, 0x000e, 0x0005, 0x00e6, 0x2071, - 0x19fb, 0x717a, 0x727e, 0x7077, 0x0009, 0x00ee, 0x0005, 0x00e6, - 0x0006, 0x2071, 0x19fb, 0x707c, 0x9206, 0x1110, 0x707a, 0x707e, - 0x000e, 0x00ee, 0x0005, 0x2069, 0x1800, 0x69e8, 0xd1e4, 0x1518, - 0x0026, 0xd1ec, 0x0140, 0x6a54, 0x6874, 0x9202, 0x0288, 0x8117, - 0x9294, 0x00c0, 0x0088, 0x9184, 0x0007, 0x01a0, 0x8109, 0x9184, - 0x0007, 0x0110, 0x69ea, 0x0070, 0x8107, 0x9084, 0x0007, 0x910d, - 0x8107, 0x9106, 0x9094, 0x00c0, 0x9184, 0xff3f, 0x9205, 0x68ea, - 0x080c, 0x0eee, 0x002e, 0x0005, 0x0016, 0x00c6, 0x2009, 0xfff4, - 0x210d, 0x2061, 0x0100, 0x60f0, 0x9100, 0x60f3, 0x0000, 0x2009, - 0xfff4, 0x200f, 0x1220, 0x8108, 0x2105, 0x8000, 0x200f, 0x00ce, - 0x001e, 0x0005, 0x00c6, 0x2061, 0x1a74, 0x00ce, 0x0005, 0x9184, - 0x000f, 0x8003, 0x8003, 0x8003, 0x9080, 0x1a74, 0x2060, 0x0005, - 0xa884, 0x908a, 0x199a, 0x1638, 0x9005, 0x1150, 0x00c6, 0x2061, - 0x1a74, 0x6014, 0x00ce, 0x9005, 0x1130, 0x2001, 0x001e, 0x0018, - 0x908e, 0xffff, 0x01b0, 0x8003, 0x800b, 0x810b, 0x9108, 0x611a, - 0xa87c, 0x908c, 0x00c0, 0x918e, 0x00c0, 0x0904, 0x89fa, 0xd0b4, - 0x1168, 0xd0bc, 0x1904, 0x89d3, 0x2009, 0x0006, 0x080c, 0x8a27, - 0x0005, 0x900e, 0x0c60, 0x2001, 0x1999, 0x08b0, 0xd0fc, 0x0160, - 0x908c, 0x0003, 0x0120, 0x918e, 0x0003, 0x1904, 0x8a21, 0x908c, - 0x2020, 0x918e, 0x2020, 0x01a8, 0x6024, 0xd0d4, 0x11e8, 0x2009, - 0x1869, 0x2104, 0xd084, 0x1138, 0x87ff, 0x1120, 0x2009, 0x0043, - 0x0804, 0xb352, 0x0005, 0x87ff, 0x1de8, 0x2009, 0x0042, 0x0804, - 0xb352, 0x6110, 0x00b6, 0x2158, 0xb900, 0x00be, 0xd1ac, 0x0d20, - 0x6024, 0xc0cd, 0x6026, 0x0c00, 0xc0d4, 0x6026, 0xa890, 0x602e, - 0xa88c, 0x6032, 0x08e0, 0xd0fc, 0x0160, 0x908c, 0x0003, 0x0120, - 0x918e, 0x0003, 0x1904, 0x8a21, 0x908c, 0x2020, 0x918e, 0x2020, - 0x0170, 0x0076, 0x00f6, 0x2c78, 0x080c, 0x1768, 0x00fe, 0x007e, - 0x87ff, 0x1120, 0x2009, 0x0042, 0x080c, 0xb352, 0x0005, 0x6110, - 0x00b6, 0x2158, 0xb900, 0x00be, 0xd1ac, 0x0d58, 0x6124, 0xc1cd, - 0x6126, 0x0c38, 0xd0fc, 0x0188, 0x908c, 0x2020, 0x918e, 0x2020, - 0x01a8, 0x9084, 0x0003, 0x908e, 0x0002, 0x0148, 0x87ff, 0x1120, - 0x2009, 0x0041, 0x080c, 0xb352, 0x0005, 0x00b9, 0x0ce8, 0x87ff, - 0x1dd8, 0x2009, 0x0043, 0x080c, 0xb352, 0x0cb0, 0x6110, 0x00b6, - 0x2158, 0xb900, 0x00be, 0xd1ac, 0x0d20, 0x6124, 0xc1cd, 0x6126, - 0x0c00, 0x2009, 0x0004, 0x0019, 0x0005, 0x2009, 0x0001, 0x0096, - 0x080c, 0xd0d8, 0x0518, 0x6014, 0x2048, 0xa982, 0xa800, 0x6016, - 0x9186, 0x0001, 0x1188, 0xa97c, 0x918c, 0x8100, 0x918e, 0x8100, - 0x1158, 0x00c6, 0x2061, 0x1a74, 0x6200, 0xd28c, 0x1120, 0x6204, - 0x8210, 0x0208, 0x6206, 0x00ce, 0x080c, 0x6cde, 0x6014, 0x904d, - 0x0076, 0x2039, 0x0000, 0x190c, 0x8970, 0x007e, 0x009e, 0x0005, - 0x0156, 0x00c6, 0x2061, 0x1a74, 0x6000, 0x81ff, 0x0110, 0x9205, - 0x0008, 0x9204, 0x6002, 0x00ce, 0x015e, 0x0005, 0x6800, 0xd08c, - 0x1138, 0x6808, 0x9005, 0x0120, 0x8001, 0x680a, 0x9085, 0x0001, - 0x0005, 0x2071, 0x1924, 0x7003, 0x0006, 0x7007, 0x0000, 0x700f, - 0x0000, 0x7013, 0x0001, 0x080c, 0x1027, 0x090c, 0x0dc5, 0xa867, - 0x0006, 0xa86b, 0x0001, 0xa8ab, 0xdcb0, 0xa89f, 0x0000, 0x2900, - 0x702e, 0x7033, 0x0000, 0x0005, 0x0126, 0x2091, 0x8000, 0x0096, - 0x00e6, 0x2071, 0x1924, 0x702c, 0x2048, 0x6a2c, 0x721e, 0x6b30, - 0x7322, 0x6834, 0x7026, 0xa896, 0x6838, 0x702a, 0xa89a, 0x6824, - 0x7016, 0x683c, 0x701a, 0x2009, 0x0028, 0x200a, 0x9005, 0x0148, - 0x900e, 0x9188, 0x000c, 0x8001, 0x1de0, 0x2100, 0x9210, 0x1208, - 0x8318, 0xaa8e, 0xab92, 0x7010, 0xd084, 0x0168, 0xc084, 0x7007, - 0x0001, 0x700f, 0x0000, 0x0006, 0x2009, 0x1ad1, 0x2104, 0x9082, - 0x0007, 0x200a, 0x000e, 0xc095, 0x7012, 0x2008, 0x2001, 0x003b, - 0x080c, 0x1611, 0x9006, 0x2071, 0x193d, 0x7002, 0x7006, 0x702a, - 0x00ee, 0x009e, 0x012e, 0x0005, 0x2009, 0x1ad1, 0x2104, 0x9080, - 0x0007, 0x200a, 0x0005, 0x00e6, 0x0126, 0x0156, 0x2091, 0x8000, - 0x2071, 0x1800, 0x7154, 0x2001, 0x0008, 0x910a, 0x0638, 0x2001, - 0x187d, 0x20ac, 0x9006, 0x9080, 0x0008, 0x1f04, 0x8ae3, 0x71c0, - 0x9102, 0x02e0, 0x2071, 0x1877, 0x20a9, 0x0007, 0x00c6, 0x080c, - 0xb27d, 0x6023, 0x0009, 0x6003, 0x0004, 0x601f, 0x0101, 0x0089, - 0x0126, 0x2091, 0x8000, 0x080c, 0x8c61, 0x012e, 0x1f04, 0x8aef, - 0x9006, 0x00ce, 0x015e, 0x012e, 0x00ee, 0x0005, 0x9085, 0x0001, - 0x0cc8, 0x00e6, 0x00b6, 0x0096, 0x0086, 0x0056, 0x0046, 0x0026, - 0x7118, 0x720c, 0x7620, 0x7004, 0xd084, 0x1128, 0x2021, 0x0024, - 0x2029, 0x0002, 0x0020, 0x2021, 0x002c, 0x2029, 0x000a, 0x080c, - 0x100e, 0x090c, 0x0dc5, 0x2900, 0x6016, 0x2058, 0xac66, 0x9006, - 0xa802, 0xa806, 0xa86a, 0xa87a, 0xa8aa, 0xa887, 0x0005, 0xa87f, - 0x0020, 0x7008, 0xa89a, 0x7010, 0xa89e, 0xae8a, 0xa8af, 0xffff, - 0xa8b3, 0x0000, 0x8109, 0x0160, 0x080c, 0x100e, 0x090c, 0x0dc5, - 0xad66, 0x2b00, 0xa802, 0x2900, 0xb806, 0x2058, 0x8109, 0x1da0, - 0x002e, 0x004e, 0x005e, 0x008e, 0x009e, 0x00be, 0x00ee, 0x0005, - 0x2079, 0x0000, 0x2071, 0x1924, 0x7004, 0x004b, 0x700c, 0x0002, - 0x8b5b, 0x8b54, 0x8b54, 0x0005, 0x8b65, 0x8bbb, 0x8bbb, 0x8bbb, - 0x8bbc, 0x8bcd, 0x8bcd, 0x700c, 0x0cba, 0x0126, 0x2091, 0x8000, - 0x78a0, 0x79a0, 0x9106, 0x1904, 0x8bad, 0x7814, 0xd0bc, 0x1904, - 0x8bb6, 0x012e, 0x7018, 0x910a, 0x1128, 0x7030, 0x9005, 0x1904, - 0x8bff, 0x0005, 0x1210, 0x7114, 0x910a, 0x9192, 0x000a, 0x0210, - 0x2009, 0x000a, 0x2001, 0x1888, 0x2014, 0x2001, 0x1936, 0x2004, - 0x9100, 0x9202, 0x0e50, 0x080c, 0x8d5c, 0x2200, 0x9102, 0x0208, - 0x2208, 0x0096, 0x702c, 0x2048, 0xa873, 0x0001, 0xa976, 0x080c, - 0x8e65, 0x2100, 0xa87e, 0xa86f, 0x0000, 0x009e, 0x0126, 0x2091, - 0x8000, 0x2009, 0x1a1b, 0x2104, 0xc085, 0x200a, 0x700f, 0x0002, - 0x012e, 0x080c, 0x1117, 0x1de8, 0x0005, 0x78a0, 0x79a0, 0x9106, - 0x0904, 0x8b6d, 0x080c, 0x8d34, 0x012e, 0x0005, 0x7810, 0xc0c5, - 0x7812, 0x0804, 0x8b6d, 0x0005, 0x700c, 0x0002, 0x8bc1, 0x8bc4, - 0x8bc3, 0x080c, 0x8b63, 0x0005, 0x8001, 0x700e, 0x0096, 0x702c, - 0x2048, 0xa974, 0x009e, 0x0011, 0x0ca0, 0x0005, 0x0096, 0x702c, - 0x2048, 0x7018, 0x9100, 0x7214, 0x921a, 0x1130, 0x701c, 0xa88e, - 0x7020, 0xa892, 0x9006, 0x0068, 0x0006, 0x080c, 0x8e65, 0x2100, - 0xaa8c, 0x9210, 0xaa8e, 0x1220, 0xa890, 0x9081, 0x0000, 0xa892, - 0x000e, 0x009e, 0x0126, 0x2091, 0x8000, 0x78a2, 0x701a, 0x080c, - 0x8d34, 0x012e, 0x0005, 0x00e6, 0x2071, 0x1924, 0x700c, 0x0002, - 0x8bfd, 0x8bfd, 0x8bfb, 0x700f, 0x0001, 0x00ee, 0x0005, 0x0126, - 0x2091, 0x8000, 0x7030, 0x9005, 0x0508, 0x2078, 0x7814, 0x2048, - 0xae88, 0x00b6, 0x2059, 0x0000, 0x080c, 0x8c6a, 0x00be, 0x01b0, - 0x00e6, 0x2071, 0x193d, 0x080c, 0x8cb1, 0x00ee, 0x0178, 0x0096, - 0x080c, 0x1027, 0x2900, 0x009e, 0x0148, 0xa8aa, 0x04b9, 0x0041, - 0x2001, 0x1947, 0x2003, 0x0000, 0x012e, 0x08c8, 0x012e, 0x0005, - 0x00d6, 0x00c6, 0x0086, 0x00a6, 0x2940, 0x2650, 0x2600, 0x9005, - 0x0180, 0xa864, 0x9084, 0x000f, 0x2068, 0x9d88, 0x20c7, 0x2165, - 0x0056, 0x2029, 0x0000, 0x080c, 0x8dea, 0x080c, 0x207f, 0x1dd8, - 0x005e, 0x00ae, 0x2001, 0x187f, 0x2004, 0xa88a, 0x080c, 0x1768, - 0x781f, 0x0101, 0x7813, 0x0000, 0x0126, 0x2091, 0x8000, 0x080c, - 0x8cc0, 0x012e, 0x008e, 0x00ce, 0x00de, 0x0005, 0x7030, 0x9005, - 0x0138, 0x2078, 0x780c, 0x7032, 0x2001, 0x1947, 0x2003, 0x0001, - 0x0005, 0x00e6, 0x2071, 0x1924, 0x7030, 0x600e, 0x2c00, 0x7032, - 0x00ee, 0x0005, 0x00d6, 0x00c6, 0x0026, 0x9b80, 0x8f33, 0x2005, - 0x906d, 0x090c, 0x0dc5, 0x9b80, 0x8f2b, 0x2005, 0x9065, 0x090c, - 0x0dc5, 0x6114, 0x2600, 0x9102, 0x0248, 0x6828, 0x9102, 0x02f0, - 0x9085, 0x0001, 0x002e, 0x00ce, 0x00de, 0x0005, 0x6804, 0xd094, - 0x0148, 0x6854, 0xd084, 0x1178, 0xc085, 0x6856, 0x2011, 0x8026, - 0x080c, 0x4c44, 0x684c, 0x0096, 0x904d, 0x090c, 0x0dc5, 0xa804, - 0x8000, 0xa806, 0x009e, 0x9006, 0x2030, 0x0c20, 0x6854, 0xd08c, - 0x1d08, 0xc08d, 0x6856, 0x2011, 0x8025, 0x080c, 0x4c44, 0x684c, - 0x0096, 0x904d, 0x090c, 0x0dc5, 0xa800, 0x8000, 0xa802, 0x009e, - 0x0888, 0x7000, 0x2019, 0x0008, 0x8319, 0x7104, 0x9102, 0x1118, - 0x2300, 0x9005, 0x0020, 0x0210, 0x9302, 0x0008, 0x8002, 0x0005, - 0x00d6, 0x7814, 0x9005, 0x090c, 0x0dc5, 0x781c, 0x9084, 0x0101, - 0x9086, 0x0101, 0x190c, 0x0dc5, 0x7827, 0x0000, 0x2069, 0x193d, - 0x6804, 0x9080, 0x193f, 0x2f08, 0x2102, 0x6904, 0x8108, 0x9182, - 0x0008, 0x0208, 0x900e, 0x6906, 0x9180, 0x193f, 0x2003, 0x0000, - 0x00de, 0x0005, 0x0096, 0x00c6, 0x2060, 0x6014, 0x2048, 0xa8a8, - 0x0096, 0x2048, 0x9005, 0x190c, 0x1040, 0x009e, 0xa8ab, 0x0000, - 0x080c, 0x0fc0, 0x080c, 0xb2d3, 0x00ce, 0x009e, 0x0005, 0x6020, - 0x9086, 0x0009, 0x1128, 0x601c, 0xd0c4, 0x0110, 0x9006, 0x0005, - 0x9085, 0x0001, 0x0005, 0x6000, 0x9086, 0x0000, 0x0178, 0x6010, - 0x9005, 0x0150, 0x00b6, 0x2058, 0x080c, 0x9067, 0x00be, 0x6013, - 0x0000, 0x601b, 0x0000, 0x0010, 0x2c00, 0x0861, 0x0005, 0x2009, - 0x1928, 0x210c, 0xd194, 0x0005, 0x2009, 0x1928, 0x210c, 0xd1c4, - 0x0005, 0x0126, 0x2091, 0x8000, 0x00e6, 0x2071, 0x1924, 0x7110, - 0xc194, 0xc185, 0x7007, 0x0000, 0x7112, 0x2001, 0x003b, 0x080c, - 0x1611, 0x00ee, 0x012e, 0x0005, 0x7814, 0xd0bc, 0x1108, 0x0005, - 0x7810, 0xc0c5, 0x7812, 0x0cc0, 0x0096, 0x00d6, 0x9006, 0x7006, - 0x700e, 0x701a, 0x701e, 0x7022, 0x7016, 0x702a, 0x7026, 0x702f, - 0x0000, 0x080c, 0x8eb3, 0x0170, 0x080c, 0x8ee8, 0x0158, 0x2900, - 0x7002, 0x700a, 0x701a, 0x7013, 0x0001, 0x701f, 0x000a, 0x00de, - 0x009e, 0x0005, 0x900e, 0x0cd8, 0x00e6, 0x0096, 0x0086, 0x00d6, - 0x00c6, 0x2071, 0x1931, 0x721c, 0x2100, 0x9202, 0x1618, 0x080c, - 0x8ee8, 0x090c, 0x0dc5, 0x7018, 0x9005, 0x1160, 0x2900, 0x7002, - 0x700a, 0x701a, 0x9006, 0x7006, 0x700e, 0xa806, 0xa802, 0x7012, - 0x701e, 0x0038, 0x2040, 0xa806, 0x2900, 0xa002, 0x701a, 0xa803, - 0x0000, 0x7010, 0x8000, 0x7012, 0x701c, 0x9080, 0x000a, 0x701e, - 0x721c, 0x08d0, 0x721c, 0x00ce, 0x00de, 0x008e, 0x009e, 0x00ee, - 0x0005, 0x0096, 0x0156, 0x0136, 0x0146, 0x00e6, 0x0126, 0x2091, - 0x8000, 0x2071, 0x1931, 0x7300, 0x831f, 0x831e, 0x831e, 0x9384, - 0x003f, 0x20e8, 0x939c, 0xffc0, 0x9398, 0x0003, 0x7104, 0x080c, - 0x8e65, 0x810c, 0x2100, 0x9318, 0x8003, 0x2228, 0x2021, 0x0078, - 0x9402, 0x9532, 0x0208, 0x2028, 0x2500, 0x8004, 0x20a8, 0x23a0, - 0xa001, 0xa001, 0x4005, 0x2508, 0x080c, 0x8e6e, 0x2130, 0x7014, - 0x9600, 0x7016, 0x2600, 0x711c, 0x9102, 0x701e, 0x7004, 0x9600, - 0x2008, 0x9082, 0x000a, 0x1190, 0x7000, 0x2048, 0xa800, 0x9005, - 0x1148, 0x2009, 0x0001, 0x0026, 0x080c, 0x8d5c, 0x002e, 0x7000, - 0x2048, 0xa800, 0x7002, 0x7007, 0x0000, 0x0008, 0x7106, 0x2500, - 0x9212, 0x1904, 0x8d9b, 0x012e, 0x00ee, 0x014e, 0x013e, 0x015e, - 0x009e, 0x0005, 0x0016, 0x0026, 0x00e6, 0x0126, 0x2091, 0x8000, - 0x9580, 0x8f2b, 0x2005, 0x9075, 0x090c, 0x0dc5, 0x080c, 0x8e40, - 0x012e, 0x9580, 0x8f27, 0x2005, 0x9075, 0x090c, 0x0dc5, 0x0156, - 0x0136, 0x01c6, 0x0146, 0x01d6, 0x831f, 0x831e, 0x831e, 0x9384, - 0x003f, 0x20e0, 0x9384, 0xffc0, 0x9100, 0x2098, 0xa860, 0x20e8, - 0xa95c, 0x2c05, 0x9100, 0x20a0, 0x20a9, 0x0002, 0x4003, 0x2e0c, - 0x2d00, 0x0002, 0x8e2a, 0x8e2a, 0x8e2c, 0x8e2a, 0x8e2c, 0x8e2a, - 0x8e2a, 0x8e2a, 0x8e2a, 0x8e2a, 0x8e32, 0x8e2a, 0x8e32, 0x8e2a, - 0x8e2a, 0x8e2a, 0x080c, 0x0dc5, 0x4104, 0x20a9, 0x0002, 0x4002, - 0x4003, 0x0028, 0x20a9, 0x0002, 0x4003, 0x4104, 0x4003, 0x01de, - 0x014e, 0x01ce, 0x013e, 0x015e, 0x00ee, 0x002e, 0x001e, 0x0005, - 0x0096, 0x7014, 0x8001, 0x7016, 0x710c, 0x2110, 0x00f1, 0x810c, - 0x9188, 0x0003, 0x7308, 0x8210, 0x9282, 0x000a, 0x1198, 0x7008, - 0x2048, 0xa800, 0x9005, 0x0158, 0x0006, 0x080c, 0x8ef7, 0x009e, - 0xa807, 0x0000, 0x2900, 0x700a, 0x7010, 0x8001, 0x7012, 0x700f, - 0x0000, 0x0008, 0x720e, 0x009e, 0x0005, 0x0006, 0x810b, 0x810b, - 0x2100, 0x810b, 0x9100, 0x2008, 0x000e, 0x0005, 0x0006, 0x0026, - 0x2100, 0x9005, 0x0158, 0x9092, 0x000c, 0x0240, 0x900e, 0x8108, - 0x9082, 0x000c, 0x1de0, 0x002e, 0x000e, 0x0005, 0x900e, 0x0cd8, - 0x2d00, 0x90b8, 0x0008, 0x2031, 0x8eb1, 0x901e, 0x6808, 0x9005, - 0x0108, 0x8318, 0x690c, 0x910a, 0x0248, 0x0140, 0x8318, 0x6810, - 0x9112, 0x0220, 0x0118, 0x8318, 0x2208, 0x0cd0, 0x233a, 0x6804, - 0xd084, 0x2300, 0x2021, 0x0001, 0x1150, 0x9082, 0x0003, 0x0967, - 0x0a67, 0x8420, 0x9082, 0x0007, 0x0967, 0x0a67, 0x0cd0, 0x9082, - 0x0002, 0x0967, 0x0a67, 0x8420, 0x9082, 0x0005, 0x0967, 0x0a67, - 0x0cd0, 0x6c1a, 0x0005, 0x0096, 0x0046, 0x0126, 0x2091, 0x8000, - 0x2b00, 0x9080, 0x8f2f, 0x2005, 0x9005, 0x090c, 0x0dc5, 0x2004, - 0x90a0, 0x000a, 0x080c, 0x1027, 0x01d0, 0x2900, 0x7026, 0xa803, - 0x0000, 0xa807, 0x0000, 0x080c, 0x1027, 0x0188, 0x7024, 0xa802, - 0xa807, 0x0000, 0x2900, 0x7026, 0x94a2, 0x000a, 0x0110, 0x0208, - 0x0c90, 0x9085, 0x0001, 0x012e, 0x004e, 0x009e, 0x0005, 0x7024, - 0x9005, 0x0dc8, 0x2048, 0xac00, 0x080c, 0x1040, 0x2400, 0x0cc0, - 0x0126, 0x2091, 0x8000, 0x7024, 0x2048, 0x9005, 0x0130, 0xa800, - 0x7026, 0xa803, 0x0000, 0xa807, 0x0000, 0x012e, 0x0005, 0x0126, - 0x2091, 0x8000, 0x7024, 0xa802, 0x2900, 0x7026, 0x012e, 0x0005, - 0x0096, 0x9e80, 0x0009, 0x2004, 0x9005, 0x0138, 0x2048, 0xa800, - 0x0006, 0x080c, 0x1040, 0x000e, 0x0cb8, 0x009e, 0x0005, 0x0096, - 0x7008, 0x9005, 0x0138, 0x2048, 0xa800, 0x0006, 0x080c, 0x1040, - 0x000e, 0x0cb8, 0x9006, 0x7002, 0x700a, 0x7006, 0x700e, 0x701a, - 0x701e, 0x7022, 0x702a, 0x7026, 0x702e, 0x009e, 0x0005, 0x1a67, - 0x0000, 0x0000, 0x0000, 0x1931, 0x0000, 0x0000, 0x0000, 0x1888, - 0x0000, 0x0000, 0x0000, 0x1877, 0x0000, 0x0000, 0x0000, 0x00e6, - 0x00c6, 0x00b6, 0x00a6, 0xa8a8, 0x2040, 0x2071, 0x1877, 0x080c, - 0x9053, 0xa067, 0x0023, 0x6010, 0x905d, 0x0904, 0x9028, 0xb814, - 0xa06e, 0xb910, 0xa172, 0xb9a0, 0xa176, 0x2001, 0x0003, 0xa07e, - 0xa834, 0xa082, 0xa07b, 0x0000, 0xa898, 0x9005, 0x0118, 0xa078, - 0xc085, 0xa07a, 0x2858, 0x2031, 0x0018, 0xa068, 0x908a, 0x0019, - 0x1a0c, 0x0dc5, 0x2020, 0x2050, 0x2940, 0xa864, 0x90bc, 0x00ff, - 0x908c, 0x000f, 0x91e0, 0x20c7, 0x2c65, 0x9786, 0x0024, 0x2c05, - 0x1590, 0x908a, 0x0036, 0x1a0c, 0x0dc5, 0x9082, 0x001b, 0x0002, - 0x8f93, 0x8f93, 0x8f95, 0x8f93, 0x8f93, 0x8f93, 0x8f97, 0x8f93, - 0x8f93, 0x8f93, 0x8f99, 0x8f93, 0x8f93, 0x8f93, 0x8f9b, 0x8f93, - 0x8f93, 0x8f93, 0x8f9d, 0x8f93, 0x8f93, 0x8f93, 0x8f9f, 0x8f93, - 0x8f93, 0x8f93, 0x8fa1, 0x080c, 0x0dc5, 0xa180, 0x04b8, 0xa190, - 0x04a8, 0xa1a0, 0x0498, 0xa1b0, 0x0488, 0xa1c0, 0x0478, 0xa1d0, - 0x0468, 0xa1e0, 0x0458, 0x908a, 0x0034, 0x1a0c, 0x0dc5, 0x9082, - 0x001b, 0x0002, 0x8fc5, 0x8fc3, 0x8fc3, 0x8fc3, 0x8fc3, 0x8fc3, - 0x8fc7, 0x8fc3, 0x8fc3, 0x8fc3, 0x8fc3, 0x8fc3, 0x8fc9, 0x8fc3, - 0x8fc3, 0x8fc3, 0x8fc3, 0x8fc3, 0x8fcb, 0x8fc3, 0x8fc3, 0x8fc3, - 0x8fc3, 0x8fc3, 0x8fcd, 0x080c, 0x0dc5, 0xa180, 0x0038, 0xa198, - 0x0028, 0xa1b0, 0x0018, 0xa1c8, 0x0008, 0xa1e0, 0x2600, 0x0002, - 0x8fe9, 0x8feb, 0x8fed, 0x8fef, 0x8ff1, 0x8ff3, 0x8ff5, 0x8ff7, - 0x8ff9, 0x8ffb, 0x8ffd, 0x8fff, 0x9001, 0x9003, 0x9005, 0x9007, - 0x9009, 0x900b, 0x900d, 0x900f, 0x9011, 0x9013, 0x9015, 0x9017, - 0x9019, 0x080c, 0x0dc5, 0xb9e2, 0x0468, 0xb9de, 0x0458, 0xb9da, - 0x0448, 0xb9d6, 0x0438, 0xb9d2, 0x0428, 0xb9ce, 0x0418, 0xb9ca, - 0x0408, 0xb9c6, 0x00f8, 0xb9c2, 0x00e8, 0xb9be, 0x00d8, 0xb9ba, - 0x00c8, 0xb9b6, 0x00b8, 0xb9b2, 0x00a8, 0xb9ae, 0x0098, 0xb9aa, - 0x0088, 0xb9a6, 0x0078, 0xb9a2, 0x0068, 0xb99e, 0x0058, 0xb99a, - 0x0048, 0xb996, 0x0038, 0xb992, 0x0028, 0xb98e, 0x0018, 0xb98a, - 0x0008, 0xb986, 0x8631, 0x8421, 0x0130, 0x080c, 0x207f, 0x090c, - 0x0dc5, 0x0804, 0x8f6d, 0x00ae, 0x00be, 0x00ce, 0x00ee, 0x0005, - 0xa86c, 0xa06e, 0xa870, 0xa072, 0xa077, 0x00ff, 0x9006, 0x0804, - 0x8f4f, 0x0006, 0x0016, 0x00b6, 0x6010, 0x2058, 0xb810, 0x9005, - 0x01b0, 0x2001, 0x1925, 0x2004, 0x9005, 0x0188, 0x2001, 0x1800, - 0x2004, 0x9086, 0x0003, 0x1158, 0x0036, 0x0046, 0xbba0, 0x2021, - 0x0004, 0x2011, 0x8014, 0x080c, 0x4c44, 0x004e, 0x003e, 0x00be, - 0x001e, 0x000e, 0x0005, 0x9016, 0x710c, 0xa834, 0x910a, 0xa936, - 0x7008, 0x9005, 0x0120, 0x8210, 0x910a, 0x0230, 0x0128, 0x7010, - 0x8210, 0x910a, 0x0208, 0x1de0, 0xaa8a, 0xa26a, 0x0005, 0x00f6, - 0x00d6, 0x0036, 0x2079, 0x0300, 0x781b, 0x0200, 0x7818, 0xd094, - 0x1dd8, 0x781b, 0x0202, 0xa001, 0xa001, 0x7818, 0xd094, 0x1da0, - 0xb8ac, 0x906d, 0x0198, 0x2079, 0x0000, 0x9c1e, 0x1118, 0x680c, - 0xb8ae, 0x0050, 0x9c06, 0x0130, 0x2d78, 0x680c, 0x906d, 0x1dd0, - 0x080c, 0x0dc5, 0x6b0c, 0x7b0e, 0x600f, 0x0000, 0x2079, 0x0300, - 0x781b, 0x0200, 0x003e, 0x00de, 0x00fe, 0x0005, 0x00e6, 0x00d6, - 0x0096, 0x00c6, 0x0036, 0x0126, 0x2091, 0x8000, 0x0156, 0x20a9, - 0x01ff, 0x2071, 0x0300, 0x701b, 0x0200, 0x7018, 0xd094, 0x0110, - 0x1f04, 0x90a3, 0x701b, 0x0202, 0xa001, 0xa001, 0x7018, 0xd094, - 0x1d90, 0xb8ac, 0x9065, 0x01f0, 0x600c, 0xb8ae, 0x6024, 0xc08d, - 0x6026, 0x6003, 0x0004, 0x601b, 0x0000, 0x6013, 0x0000, 0x601f, - 0x0101, 0x6014, 0x904d, 0x090c, 0x0dc5, 0xa88b, 0x0000, 0xa8a8, - 0xa8ab, 0x0000, 0x904d, 0x090c, 0x0dc5, 0x080c, 0x1040, 0x080c, - 0x8c61, 0x08f8, 0x2071, 0x0300, 0x701b, 0x0200, 0x015e, 0x012e, - 0x003e, 0x00ce, 0x009e, 0x00de, 0x00ee, 0x0005, 0x00c6, 0x00b6, - 0x0016, 0x0006, 0x0156, 0x080c, 0x2873, 0x015e, 0x11b0, 0x080c, - 0x66b9, 0x190c, 0x0dc5, 0x000e, 0x001e, 0xb912, 0xb816, 0x080c, - 0xb27d, 0x0140, 0x2b00, 0x6012, 0x6023, 0x0001, 0x2009, 0x0001, - 0x080c, 0xb352, 0x00be, 0x00ce, 0x0005, 0x000e, 0x001e, 0x0cd0, - 0x0066, 0x6000, 0x90b2, 0x0010, 0x1a0c, 0x0dc5, 0x0013, 0x006e, - 0x0005, 0x9119, 0x9119, 0x9119, 0x911b, 0x916c, 0x9119, 0x9119, - 0x9119, 0x91e6, 0x9119, 0x9223, 0x9119, 0x9119, 0x9119, 0x9119, - 0x9119, 0x080c, 0x0dc5, 0x9182, 0x0040, 0x0002, 0x912e, 0x912e, - 0x912e, 0x912e, 0x912e, 0x912e, 0x912e, 0x912e, 0x912e, 0x9130, - 0x9145, 0x912e, 0x912e, 0x912e, 0x912e, 0x9158, 0x080c, 0x0dc5, - 0x0096, 0x080c, 0x9a61, 0x080c, 0x9bd3, 0x6114, 0x2148, 0xa87b, - 0x0000, 0x6010, 0x00b6, 0x2058, 0xb8bb, 0x0500, 0x00be, 0x080c, - 0x6ca3, 0x080c, 0xb2d3, 0x009e, 0x0005, 0x080c, 0x9a61, 0x00d6, - 0x6114, 0x080c, 0xd0d8, 0x0130, 0x0096, 0x6114, 0x2148, 0x080c, - 0x6e9f, 0x009e, 0x00de, 0x080c, 0xb2d3, 0x080c, 0x9bd3, 0x0005, - 0x080c, 0x9a61, 0x080c, 0x3250, 0x6114, 0x0096, 0x2148, 0x080c, - 0xd0d8, 0x0120, 0xa87b, 0x0029, 0x080c, 0x6e9f, 0x009e, 0x080c, - 0xb2d3, 0x080c, 0x9bd3, 0x0005, 0x601b, 0x0000, 0x9182, 0x0040, - 0x0096, 0x0002, 0x9187, 0x9187, 0x9187, 0x9187, 0x9187, 0x9187, - 0x9187, 0x9187, 0x9189, 0x9187, 0x9187, 0x9187, 0x91e2, 0x9187, - 0x9187, 0x9187, 0x9187, 0x9187, 0x9187, 0x9190, 0x9187, 0x080c, - 0x0dc5, 0x6114, 0x2148, 0xa938, 0x918e, 0xffff, 0x0904, 0x91e2, - 0x6024, 0xd08c, 0x15d8, 0x080c, 0x8d17, 0x05e0, 0x00e6, 0x6114, - 0x2148, 0x080c, 0x8f37, 0x0096, 0xa8a8, 0x2048, 0x080c, 0x6c3b, - 0x009e, 0xa8ab, 0x0000, 0x6010, 0x9005, 0x0128, 0x00b6, 0x2058, - 0x080c, 0x9067, 0x00be, 0xae88, 0x00b6, 0x2059, 0x0000, 0x080c, - 0x8c6a, 0x00be, 0x01e0, 0x2071, 0x193d, 0x080c, 0x8cb1, 0x01b8, - 0x9086, 0x0001, 0x1128, 0x2001, 0x1947, 0x2004, 0x9005, 0x1178, - 0x0096, 0x080c, 0x100e, 0x2900, 0x009e, 0x0148, 0xa8aa, 0x00f6, - 0x2c78, 0x080c, 0x8c28, 0x00fe, 0x00ee, 0x009e, 0x0005, 0x080c, - 0x8c61, 0x0cd0, 0x080c, 0x8d1c, 0x1160, 0x6010, 0x9005, 0x0130, - 0x2058, 0xb8ac, 0x9005, 0x190c, 0x0dc5, 0x6012, 0x2c00, 0x080c, - 0x8ce2, 0x0005, 0x080c, 0x9290, 0x009e, 0x0005, 0x9182, 0x0040, - 0x0096, 0x0002, 0x91fa, 0x91fa, 0x91fa, 0x91fc, 0x91fa, 0x91fa, - 0x91fa, 0x9221, 0x91fa, 0x91fa, 0x91fa, 0x91fa, 0x91fa, 0x91fa, - 0x91fa, 0x91fa, 0x080c, 0x0dc5, 0x6003, 0x0003, 0x6106, 0x6014, - 0x2048, 0xa8ac, 0xa846, 0xa8b0, 0xa84a, 0xa837, 0x0000, 0xa83b, - 0x0000, 0xa884, 0x9092, 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, - 0x8013, 0x8213, 0x9210, 0x621a, 0x2c10, 0x080c, 0x1be0, 0x080c, - 0x9564, 0x0126, 0x2091, 0x8000, 0x080c, 0x9bd3, 0x012e, 0x009e, - 0x0005, 0x080c, 0x0dc5, 0x080c, 0x9a61, 0x080c, 0x9bd3, 0x6114, - 0x2148, 0xa87b, 0x0000, 0x6010, 0x00b6, 0x2058, 0xb8bb, 0x0500, - 0x00be, 0x080c, 0x6e9f, 0x080c, 0xb2d3, 0x009e, 0x0005, 0x6000, - 0x908a, 0x0010, 0x1a0c, 0x0dc5, 0x0096, 0x0013, 0x009e, 0x0005, - 0x9250, 0x9250, 0x9250, 0x9252, 0x9263, 0x9250, 0x9250, 0x9250, - 0x9250, 0x9250, 0x9250, 0x9250, 0x9250, 0x9250, 0x9250, 0x9250, - 0x080c, 0x0dc5, 0x080c, 0xac2b, 0x6114, 0x2148, 0xa87b, 0x0006, - 0x6010, 0x00b6, 0x2058, 0xb8bb, 0x0500, 0x00be, 0x080c, 0x6e9f, - 0x080c, 0xb2d3, 0x0005, 0x0461, 0x0005, 0x6000, 0x908a, 0x0010, - 0x1a0c, 0x0dc5, 0x0096, 0x0013, 0x009e, 0x0005, 0x927e, 0x927e, - 0x927e, 0x9280, 0x9290, 0x927e, 0x927e, 0x927e, 0x927e, 0x927e, - 0x927e, 0x927e, 0x927e, 0x927e, 0x927e, 0x927e, 0x080c, 0x0dc5, - 0x0036, 0x00e6, 0x2071, 0x19e8, 0x703c, 0x9c06, 0x1120, 0x2019, - 0x0000, 0x080c, 0xaa49, 0x080c, 0xac2b, 0x00ee, 0x003e, 0x0005, - 0x6024, 0xd08c, 0x11f0, 0x00f6, 0x00e6, 0x601b, 0x0000, 0x6014, - 0x2048, 0x6010, 0x9005, 0x0128, 0x00b6, 0x2058, 0x080c, 0x9067, - 0x00be, 0x2071, 0x193d, 0x080c, 0x8cb1, 0x0160, 0x2001, 0x187f, - 0x2004, 0xa88a, 0x2031, 0x0000, 0x2c78, 0x080c, 0x8c28, 0x00ee, - 0x00fe, 0x0005, 0x0096, 0xa88b, 0x0000, 0xa8a8, 0x2048, 0x080c, - 0x1040, 0x009e, 0xa8ab, 0x0000, 0x080c, 0x8c61, 0x0c80, 0x2001, - 0x1925, 0x200c, 0x918e, 0x0000, 0x190c, 0x8d17, 0x05c8, 0x00e6, - 0x2071, 0x1924, 0x7110, 0xc1c5, 0x7112, 0x080c, 0x8d21, 0x00f6, - 0x00c6, 0x2071, 0x1000, 0x00b6, 0x2e04, 0x905d, 0x0138, 0xb8ac, - 0x9065, 0x0120, 0x080c, 0x8cf7, 0x090c, 0x9096, 0x8e70, 0x9e86, - 0x1800, 0x1d90, 0x00be, 0x00d6, 0x0096, 0x0046, 0x2061, 0x1cd0, - 0x2001, 0x181a, 0x2024, 0x6020, 0x9086, 0x0000, 0x1191, 0x9ce0, - 0x0018, 0x2400, 0x9c06, 0x1db8, 0x004e, 0x009e, 0x00de, 0x00d1, - 0x00ce, 0x00fe, 0x2071, 0x1924, 0x7110, 0xc1c4, 0x7112, 0x00ee, - 0x0005, 0x6020, 0x9086, 0x0009, 0x1160, 0x6100, 0x9186, 0x0004, - 0x1138, 0x6110, 0x81ff, 0x190c, 0x0dc5, 0x2c00, 0x080c, 0x8ce2, - 0x9006, 0x0005, 0x2071, 0x193f, 0x2073, 0x0000, 0x8e70, 0x9e86, - 0x1947, 0x1dd0, 0x2071, 0x193d, 0x7006, 0x7002, 0x2001, 0x1930, - 0x2064, 0x8cff, 0x0130, 0x6120, 0x918e, 0x0000, 0x190c, 0x0dc5, - 0x2102, 0x2001, 0x188a, 0x200c, 0x81ff, 0x0148, 0x0096, 0x2148, - 0x080c, 0x1040, 0x009e, 0x2001, 0x188a, 0x2003, 0x0000, 0x2071, - 0x1931, 0x080c, 0x8f00, 0x0804, 0x8f0f, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x187a, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0126, 0x2091, 0x8000, - 0x0036, 0x0046, 0x20a9, 0x0010, 0x9006, 0x8004, 0x2019, 0x0100, - 0x231c, 0x93a6, 0x0008, 0x1118, 0x8086, 0x818e, 0x0020, 0x80f6, - 0x3e00, 0x81f6, 0x3e08, 0x1208, 0x9200, 0x1f04, 0x9356, 0x93a6, - 0x0008, 0x1118, 0x8086, 0x818e, 0x0020, 0x80f6, 0x3e00, 0x81f6, - 0x3e08, 0x004e, 0x003e, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, - 0x0076, 0x0156, 0x20a9, 0x0010, 0x9005, 0x0510, 0x911a, 0x1600, - 0x8213, 0x2039, 0x0100, 0x273c, 0x97be, 0x0008, 0x1110, 0x818d, - 0x0010, 0x81f5, 0x3e08, 0x0228, 0x911a, 0x1220, 0x1f04, 0x9380, - 0x0028, 0x911a, 0x2308, 0x8210, 0x1f04, 0x9380, 0x0006, 0x3200, - 0x9084, 0xefff, 0x2080, 0x000e, 0x015e, 0x007e, 0x012e, 0x0005, - 0x0006, 0x3200, 0x9085, 0x1000, 0x0ca8, 0x0126, 0x2091, 0x2800, - 0x2079, 0x19e8, 0x012e, 0x00d6, 0x2069, 0x19e8, 0x6803, 0x0005, - 0x0156, 0x0146, 0x01d6, 0x20e9, 0x0000, 0x2069, 0x0200, 0x080c, - 0xaf8e, 0x0401, 0x080c, 0xaf79, 0x00e9, 0x080c, 0xaf7c, 0x00d1, - 0x080c, 0xaf7f, 0x00b9, 0x080c, 0xaf82, 0x00a1, 0x080c, 0xaf85, - 0x0089, 0x080c, 0xaf88, 0x0071, 0x080c, 0xaf8b, 0x0059, 0x01de, - 0x014e, 0x015e, 0x2069, 0x0004, 0x2d04, 0x9085, 0x8001, 0x206a, - 0x00de, 0x0005, 0x20a9, 0x0020, 0x20a1, 0x0240, 0x2001, 0x0000, - 0x4004, 0x0005, 0x00c6, 0x6027, 0x0001, 0x7804, 0x9084, 0x0007, - 0x0002, 0x93f3, 0x9417, 0x9458, 0x93f9, 0x9417, 0x93f3, 0x93f1, - 0x93f1, 0x080c, 0x0dc5, 0x080c, 0x88c3, 0x080c, 0x9ab1, 0x00ce, - 0x0005, 0x62c0, 0x82ff, 0x1110, 0x00ce, 0x0005, 0x2011, 0x5f97, - 0x080c, 0x883d, 0x7828, 0x9092, 0x00c8, 0x1228, 0x8000, 0x782a, - 0x080c, 0x5fd7, 0x0c88, 0x62c0, 0x080c, 0xb0ca, 0x080c, 0x5f97, - 0x7807, 0x0003, 0x7827, 0x0000, 0x782b, 0x0000, 0x0c28, 0x080c, - 0x88c3, 0x6220, 0xd2a4, 0x0170, 0xd2cc, 0x0160, 0x782b, 0x0000, - 0x7824, 0x9065, 0x090c, 0x0dc5, 0x2009, 0x0013, 0x080c, 0xb352, - 0x00ce, 0x0005, 0x00c6, 0x7824, 0x9065, 0x090c, 0x0dc5, 0x7828, - 0x9092, 0xc350, 0x12c0, 0x8000, 0x782a, 0x00ce, 0x080c, 0x2bce, - 0x0278, 0x00c6, 0x7924, 0x2160, 0x6010, 0x906d, 0x090c, 0x0dc5, - 0x7807, 0x0000, 0x7827, 0x0000, 0x00ce, 0x080c, 0x9ab1, 0x0c00, - 0x080c, 0xa6c5, 0x08e8, 0x2011, 0x0130, 0x2214, 0x080c, 0xb0ca, - 0x080c, 0xf094, 0x2009, 0x0014, 0x080c, 0xb352, 0x00ce, 0x0880, - 0x2001, 0x1a04, 0x2003, 0x0000, 0x62c0, 0x82ff, 0x1160, 0x782b, - 0x0000, 0x7824, 0x9065, 0x090c, 0x0dc5, 0x2009, 0x0013, 0x080c, - 0xb3a4, 0x00ce, 0x0005, 0x00b6, 0x00c6, 0x00d6, 0x7824, 0x9005, - 0x090c, 0x0dc5, 0x7828, 0x9092, 0xc350, 0x1648, 0x8000, 0x782a, - 0x00de, 0x00ce, 0x00be, 0x080c, 0x2bce, 0x02f0, 0x00b6, 0x00c6, - 0x00d6, 0x781c, 0x905d, 0x090c, 0x0dc5, 0xb800, 0xc0dc, 0xb802, - 0x7924, 0x2160, 0x080c, 0xb2d3, 0xb93c, 0x81ff, 0x090c, 0x0dc5, - 0x8109, 0xb93e, 0x7807, 0x0000, 0x7827, 0x0000, 0x00de, 0x00ce, - 0x00be, 0x080c, 0x9ab1, 0x0868, 0x080c, 0xa6c5, 0x0850, 0x2011, - 0x0130, 0x2214, 0x080c, 0xb0ca, 0x080c, 0xf094, 0x7824, 0x9065, - 0x2009, 0x0014, 0x080c, 0xb352, 0x00de, 0x00ce, 0x00be, 0x0804, - 0x9469, 0x00c6, 0x2001, 0x009b, 0x2004, 0xd0fc, 0x190c, 0x1eeb, - 0x6024, 0x6027, 0x0002, 0xd0f4, 0x15b8, 0x62c8, 0x60c4, 0x9205, - 0x1170, 0x783c, 0x9065, 0x0130, 0x2009, 0x0049, 0x080c, 0xb352, - 0x00ce, 0x0005, 0x2011, 0x1a07, 0x2013, 0x0000, 0x0cc8, 0x793c, - 0x81ff, 0x0dc0, 0x7944, 0x9192, 0x7530, 0x1628, 0x8108, 0x7946, - 0x793c, 0x9188, 0x0008, 0x210c, 0x918e, 0x0006, 0x1138, 0x6014, - 0x9084, 0x1984, 0x9085, 0x0012, 0x6016, 0x0c10, 0x793c, 0x9188, - 0x0008, 0x210c, 0x918e, 0x0009, 0x0d90, 0x6014, 0x9084, 0x1984, - 0x9085, 0x0016, 0x6016, 0x08a0, 0x793c, 0x2160, 0x2009, 0x004a, - 0x080c, 0xb352, 0x0868, 0x7848, 0xc085, 0x784a, 0x0848, 0x0006, - 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, - 0x2061, 0x19e8, 0x6020, 0x8000, 0x6022, 0x6010, 0x9005, 0x0148, - 0x9080, 0x0003, 0x2102, 0x6112, 0x012e, 0x00ce, 0x001e, 0x000e, - 0x0005, 0x6116, 0x6112, 0x0cc0, 0x00d6, 0x2069, 0x19e8, 0xb800, - 0xd0d4, 0x0168, 0x6820, 0x8000, 0x6822, 0x9086, 0x0001, 0x1110, - 0x2b00, 0x681e, 0x00de, 0x0804, 0x9ab1, 0x00de, 0x0005, 0xc0d5, - 0xb802, 0x6818, 0x9005, 0x0168, 0xb856, 0xb85b, 0x0000, 0x0086, - 0x0006, 0x2b00, 0x681a, 0x008e, 0xa05a, 0x008e, 0x2069, 0x19e8, - 0x0c08, 0xb856, 0xb85a, 0x2b00, 0x681a, 0x681e, 0x08d8, 0x0006, - 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, - 0x2061, 0x19e8, 0x6020, 0x8000, 0x6022, 0x6008, 0x9005, 0x0148, - 0x9080, 0x0003, 0x2102, 0x610a, 0x012e, 0x00ce, 0x001e, 0x000e, - 0x0005, 0x610e, 0x610a, 0x0cc0, 0x00c6, 0x600f, 0x0000, 0x2c08, - 0x2061, 0x19e8, 0x6034, 0x9005, 0x0130, 0x9080, 0x0003, 0x2102, - 0x6136, 0x00ce, 0x0005, 0x613a, 0x6136, 0x00ce, 0x0005, 0x00f6, - 0x00e6, 0x00d6, 0x00c6, 0x00b6, 0x0096, 0x0076, 0x0066, 0x0056, - 0x0036, 0x0026, 0x0016, 0x0006, 0x0126, 0x902e, 0x2071, 0x19e8, - 0x7638, 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, 0x0904, 0x95f3, - 0x6010, 0x2058, 0xb8a0, 0x9206, 0x1904, 0x95ee, 0x87ff, 0x0120, - 0x6054, 0x9106, 0x1904, 0x95ee, 0x703c, 0x9c06, 0x1178, 0x0036, - 0x2019, 0x0001, 0x080c, 0xaa49, 0x7033, 0x0000, 0x9006, 0x703e, - 0x7042, 0x7046, 0x704a, 0x003e, 0x2029, 0x0001, 0x7038, 0x9c36, - 0x1110, 0x660c, 0x763a, 0x7034, 0x9c36, 0x1140, 0x2c00, 0x9f36, - 0x0118, 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, 0x660c, 0x0066, - 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, - 0x080c, 0xd0d8, 0x01f0, 0x6014, 0x2048, 0x6020, 0x9086, 0x0003, - 0x15b8, 0x6004, 0x9086, 0x0040, 0x090c, 0xac1b, 0xa867, 0x0103, - 0xab7a, 0xa877, 0x0000, 0x0016, 0x0036, 0x0076, 0x080c, 0xd3ce, - 0x080c, 0xef85, 0x080c, 0x6e9f, 0x007e, 0x003e, 0x001e, 0x080c, - 0xd2c3, 0x080c, 0xb306, 0x00ce, 0x0804, 0x958d, 0x2c78, 0x600c, - 0x2060, 0x0804, 0x958d, 0x85ff, 0x0120, 0x0036, 0x080c, 0x9bd3, - 0x003e, 0x012e, 0x000e, 0x001e, 0x002e, 0x003e, 0x005e, 0x006e, - 0x007e, 0x009e, 0x00be, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, - 0x6020, 0x9086, 0x0006, 0x1158, 0x0016, 0x0036, 0x0076, 0x080c, - 0xef85, 0x080c, 0xebd4, 0x007e, 0x003e, 0x001e, 0x0890, 0x6020, - 0x9086, 0x0009, 0x1168, 0xa87b, 0x0006, 0x0016, 0x0036, 0x0076, - 0x080c, 0x6e9f, 0x080c, 0xb2d3, 0x007e, 0x003e, 0x001e, 0x0818, - 0x6020, 0x9086, 0x000a, 0x0904, 0x95d8, 0x0804, 0x95d1, 0x0006, - 0x0066, 0x0096, 0x00c6, 0x00d6, 0x00f6, 0x9036, 0x0126, 0x2091, - 0x8000, 0x2079, 0x19e8, 0x7838, 0x9065, 0x0904, 0x9684, 0x600c, - 0x0006, 0x600f, 0x0000, 0x783c, 0x9c06, 0x1168, 0x0036, 0x2019, - 0x0001, 0x080c, 0xaa49, 0x7833, 0x0000, 0x901e, 0x7b3e, 0x7b42, - 0x7b46, 0x7b4a, 0x003e, 0x080c, 0xd0d8, 0x0548, 0x6014, 0x2048, - 0x6020, 0x9086, 0x0003, 0x1590, 0x3e08, 0x918e, 0x0002, 0x1188, - 0x6010, 0x9005, 0x0170, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, - 0x0140, 0x6040, 0x9005, 0x11a8, 0x2001, 0x1988, 0x2004, 0x6042, - 0x0080, 0x6004, 0x9086, 0x0040, 0x090c, 0xac1b, 0xa867, 0x0103, - 0xab7a, 0xa877, 0x0000, 0x080c, 0x6e92, 0x080c, 0xd2c3, 0x080c, - 0xb306, 0x000e, 0x0804, 0x963c, 0x7e3a, 0x7e36, 0x012e, 0x00fe, - 0x00de, 0x00ce, 0x009e, 0x006e, 0x000e, 0x0005, 0x6020, 0x9086, - 0x0006, 0x1118, 0x080c, 0xebd4, 0x0c50, 0x6020, 0x9086, 0x0009, - 0x1130, 0xab7a, 0x080c, 0x6e9f, 0x080c, 0xb2d3, 0x0c10, 0x6020, - 0x9086, 0x000a, 0x09a8, 0x0868, 0x0016, 0x0026, 0x0086, 0x9046, - 0x0099, 0x080c, 0x978f, 0x008e, 0x002e, 0x001e, 0x0005, 0x00f6, - 0x0126, 0x2079, 0x19e8, 0x2091, 0x8000, 0x080c, 0x9826, 0x080c, - 0x98b6, 0x012e, 0x00fe, 0x0005, 0x00b6, 0x0096, 0x00f6, 0x00e6, - 0x00d6, 0x00c6, 0x0066, 0x0016, 0x0006, 0x0126, 0x2091, 0x8000, - 0x2071, 0x19e8, 0x7614, 0x2660, 0x2678, 0x8cff, 0x0904, 0x9754, - 0x6010, 0x2058, 0xb8a0, 0x9206, 0x1904, 0x974f, 0x88ff, 0x0120, - 0x6054, 0x9106, 0x1904, 0x974f, 0x7024, 0x9c06, 0x1568, 0x2069, - 0x0100, 0x6820, 0xd0a4, 0x0110, 0xd0cc, 0x1508, 0x080c, 0x88c3, - 0x080c, 0xa6e9, 0x68c3, 0x0000, 0x080c, 0xac1b, 0x7027, 0x0000, - 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, - 0x0100, 0x080c, 0x2d39, 0x9006, 0x080c, 0x2d39, 0x2069, 0x0100, - 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x0028, 0x6003, - 0x0009, 0x630a, 0x0804, 0x974f, 0x7014, 0x9c36, 0x1110, 0x660c, - 0x7616, 0x7010, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, - 0x7012, 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, - 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x6014, 0x2048, - 0x080c, 0xd0d8, 0x01e8, 0x6020, 0x9086, 0x0003, 0x1580, 0x080c, - 0xd2e0, 0x1118, 0x080c, 0xbcb6, 0x0098, 0xa867, 0x0103, 0xab7a, - 0xa877, 0x0000, 0x0016, 0x0036, 0x0086, 0x080c, 0xd3ce, 0x080c, - 0xef85, 0x080c, 0x6e9f, 0x008e, 0x003e, 0x001e, 0x080c, 0xd2c3, - 0x080c, 0xb306, 0x080c, 0xaaf1, 0x00ce, 0x0804, 0x96cd, 0x2c78, - 0x600c, 0x2060, 0x0804, 0x96cd, 0x012e, 0x000e, 0x001e, 0x006e, - 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x009e, 0x00be, 0x0005, 0x6020, - 0x9086, 0x0006, 0x1158, 0x0016, 0x0036, 0x0086, 0x080c, 0xef85, - 0x080c, 0xebd4, 0x008e, 0x003e, 0x001e, 0x08d0, 0x080c, 0xbcb6, - 0x6020, 0x9086, 0x0002, 0x1160, 0x6004, 0x0006, 0x9086, 0x0085, - 0x000e, 0x0904, 0x9735, 0x9086, 0x008b, 0x0904, 0x9735, 0x0840, - 0x6020, 0x9086, 0x0005, 0x1920, 0x6004, 0x0006, 0x9086, 0x0085, - 0x000e, 0x09c8, 0x9086, 0x008b, 0x09b0, 0x0804, 0x9748, 0x00b6, - 0x00a6, 0x0096, 0x00c6, 0x0006, 0x0126, 0x2091, 0x8000, 0x9280, - 0x1000, 0x2004, 0x905d, 0x0904, 0x981f, 0x00f6, 0x00e6, 0x00d6, - 0x0066, 0x2071, 0x19e8, 0xbe54, 0x7018, 0x9b06, 0x1108, 0x761a, - 0x701c, 0x9b06, 0x1130, 0x86ff, 0x1118, 0x7018, 0x701e, 0x0008, - 0x761e, 0xb858, 0x904d, 0x0108, 0xae56, 0x96d5, 0x0000, 0x0110, - 0x2900, 0xb05a, 0xb857, 0x0000, 0xb85b, 0x0000, 0xb800, 0xc0d4, - 0xc0dc, 0xb802, 0x080c, 0x664c, 0x0904, 0x981b, 0x7624, 0x86ff, - 0x0904, 0x980a, 0x9680, 0x0005, 0x2004, 0x9906, 0x15d8, 0x00d6, - 0x2069, 0x0100, 0x68c0, 0x9005, 0x0560, 0x080c, 0x88c3, 0x080c, - 0xa6e9, 0x68c3, 0x0000, 0x080c, 0xac1b, 0x7027, 0x0000, 0x0036, - 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, - 0x080c, 0x2d39, 0x9006, 0x080c, 0x2d39, 0x2069, 0x0100, 0x6824, - 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x00de, 0x00c6, 0xb83c, - 0x9005, 0x0110, 0x8001, 0xb83e, 0x2660, 0x080c, 0xb306, 0x00ce, - 0x0048, 0x00de, 0x00c6, 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce, - 0x0804, 0x97c2, 0x89ff, 0x0158, 0xa867, 0x0103, 0xab7a, 0xa877, - 0x0000, 0x080c, 0xd3ce, 0x080c, 0xef85, 0x080c, 0x6e9f, 0x080c, - 0xaaf1, 0x0804, 0x97c2, 0x006e, 0x00de, 0x00ee, 0x00fe, 0x012e, - 0x000e, 0x00ce, 0x009e, 0x00ae, 0x00be, 0x0005, 0x0096, 0x0006, - 0x0066, 0x00c6, 0x00d6, 0x9036, 0x7814, 0x9065, 0x0904, 0x9889, - 0x600c, 0x0006, 0x600f, 0x0000, 0x7824, 0x9c06, 0x1580, 0x2069, - 0x0100, 0x6820, 0xd0a4, 0x0110, 0xd0cc, 0x1508, 0x080c, 0x88c3, - 0x080c, 0xa6e9, 0x68c3, 0x0000, 0x080c, 0xac1b, 0x7827, 0x0000, - 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, - 0x0100, 0x080c, 0x2d39, 0x9006, 0x080c, 0x2d39, 0x2069, 0x0100, - 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x0040, 0x080c, - 0x6a3b, 0x1520, 0x6003, 0x0009, 0x630a, 0x2c30, 0x00f8, 0x6014, - 0x2048, 0x080c, 0xd0d6, 0x01b0, 0x6020, 0x9086, 0x0003, 0x1508, - 0x080c, 0xd2e0, 0x1118, 0x080c, 0xbcb6, 0x0060, 0x080c, 0x6a3b, - 0x1168, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0x6e9f, - 0x080c, 0xd2c3, 0x080c, 0xb306, 0x080c, 0xaaf1, 0x000e, 0x0804, - 0x982d, 0x7e16, 0x7e12, 0x00de, 0x00ce, 0x006e, 0x000e, 0x009e, - 0x0005, 0x6020, 0x9086, 0x0006, 0x1118, 0x080c, 0xebd4, 0x0c50, - 0x080c, 0xbcb6, 0x6020, 0x9086, 0x0002, 0x1150, 0x6004, 0x0006, - 0x9086, 0x0085, 0x000e, 0x0990, 0x9086, 0x008b, 0x0978, 0x08d0, - 0x6020, 0x9086, 0x0005, 0x19b0, 0x6004, 0x0006, 0x9086, 0x0085, - 0x000e, 0x0d18, 0x9086, 0x008b, 0x0d00, 0x0860, 0x0006, 0x0066, - 0x0096, 0x00b6, 0x00c6, 0x00d6, 0x7818, 0x905d, 0x0904, 0x9936, - 0xb854, 0x0006, 0x9006, 0xb856, 0xb85a, 0xb800, 0xc0d4, 0xc0dc, - 0xb802, 0x080c, 0x664c, 0x0904, 0x9933, 0x7e24, 0x86ff, 0x0904, - 0x9926, 0x9680, 0x0005, 0x2004, 0x9906, 0x1904, 0x9926, 0x00d6, - 0x2069, 0x0100, 0x68c0, 0x9005, 0x0904, 0x991d, 0x080c, 0x88c3, - 0x080c, 0xa6e9, 0x68c3, 0x0000, 0x080c, 0xac1b, 0x7827, 0x0000, - 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, - 0x0100, 0x080c, 0x2d39, 0x9006, 0x080c, 0x2d39, 0x2069, 0x0100, - 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x00de, 0x00c6, - 0x3e08, 0x918e, 0x0002, 0x1168, 0xb800, 0xd0bc, 0x0150, 0x9680, - 0x0010, 0x200c, 0x81ff, 0x1518, 0x2009, 0x1988, 0x210c, 0x2102, - 0x00f0, 0xb83c, 0x9005, 0x0110, 0x8001, 0xb83e, 0x2660, 0x600f, - 0x0000, 0x080c, 0xb306, 0x00ce, 0x0048, 0x00de, 0x00c6, 0x2660, - 0x6003, 0x0009, 0x630a, 0x00ce, 0x0804, 0x98c9, 0x89ff, 0x0138, - 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0x6e9f, 0x080c, - 0xaaf1, 0x0804, 0x98c9, 0x000e, 0x0804, 0x98bd, 0x781e, 0x781a, - 0x00de, 0x00ce, 0x00be, 0x009e, 0x006e, 0x000e, 0x0005, 0x00e6, - 0x00d6, 0x0096, 0x0066, 0xb800, 0xd0dc, 0x01a0, 0xb84c, 0x904d, - 0x0188, 0xa878, 0x9606, 0x1170, 0x2071, 0x19e8, 0x7024, 0x9035, - 0x0148, 0x9080, 0x0005, 0x2004, 0x9906, 0x1120, 0xb800, 0xc0dc, - 0xb802, 0x0029, 0x006e, 0x009e, 0x00de, 0x00ee, 0x0005, 0x00f6, - 0x2079, 0x0100, 0x78c0, 0x9005, 0x1138, 0x00c6, 0x2660, 0x6003, - 0x0009, 0x630a, 0x00ce, 0x04b8, 0x080c, 0xa6e9, 0x78c3, 0x0000, - 0x080c, 0xac1b, 0x7027, 0x0000, 0x0036, 0x2079, 0x0140, 0x7b04, - 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2d39, 0x9006, - 0x080c, 0x2d39, 0x2079, 0x0100, 0x7824, 0xd084, 0x0110, 0x7827, - 0x0001, 0x080c, 0xac1b, 0x003e, 0x080c, 0x664c, 0x00c6, 0xb83c, - 0x9005, 0x0110, 0x8001, 0xb83e, 0x2660, 0x080c, 0xb2d3, 0x00ce, - 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0xd3ce, 0x080c, - 0x6e9f, 0x080c, 0xaaf1, 0x00fe, 0x0005, 0x00b6, 0x00e6, 0x00c6, - 0x2011, 0x0101, 0x2204, 0xc0c4, 0x2012, 0x2001, 0x180c, 0x2014, - 0xc2e4, 0x2202, 0x2071, 0x19e8, 0x7004, 0x9084, 0x0007, 0x0002, - 0x99c2, 0x99c6, 0x99e4, 0x9a0d, 0x9a4b, 0x99c2, 0x99dd, 0x99c0, - 0x080c, 0x0dc5, 0x00ce, 0x00ee, 0x00be, 0x0005, 0x7024, 0x9065, - 0x0148, 0x7020, 0x8001, 0x7022, 0x600c, 0x9015, 0x0158, 0x7216, - 0x600f, 0x0000, 0x7007, 0x0000, 0x7027, 0x0000, 0x00ce, 0x00ee, - 0x00be, 0x0005, 0x7216, 0x7212, 0x0ca8, 0x7007, 0x0000, 0x7027, - 0x0000, 0x7020, 0x9005, 0x0070, 0x6010, 0x2058, 0x080c, 0x664c, - 0xb800, 0xc0dc, 0xb802, 0x7007, 0x0000, 0x7027, 0x0000, 0x7020, - 0x8001, 0x7022, 0x1148, 0x2001, 0x180c, 0x2014, 0xd2ec, 0x1180, - 0x00ce, 0x00ee, 0x00be, 0x0005, 0xb854, 0x9015, 0x0120, 0x721e, - 0x080c, 0x9ab1, 0x0ca8, 0x7218, 0x721e, 0x080c, 0x9ab1, 0x0c80, - 0xc2ec, 0x2202, 0x080c, 0x9bd3, 0x0c58, 0x7024, 0x9065, 0x05b8, - 0x700c, 0x9c06, 0x1160, 0x080c, 0xaaf1, 0x600c, 0x9015, 0x0120, - 0x720e, 0x600f, 0x0000, 0x0448, 0x720e, 0x720a, 0x0430, 0x7014, - 0x9c06, 0x1160, 0x080c, 0xaaf1, 0x600c, 0x9015, 0x0120, 0x7216, - 0x600f, 0x0000, 0x00d0, 0x7216, 0x7212, 0x00b8, 0x6020, 0x9086, - 0x0003, 0x1198, 0x6010, 0x2058, 0x080c, 0x664c, 0xb800, 0xc0dc, - 0xb802, 0x080c, 0xaaf1, 0x701c, 0x9065, 0x0138, 0xb854, 0x9015, - 0x0110, 0x721e, 0x0010, 0x7218, 0x721e, 0x7027, 0x0000, 0x00ce, - 0x00ee, 0x00be, 0x0005, 0x7024, 0x9065, 0x0140, 0x080c, 0xaaf1, - 0x600c, 0x9015, 0x0158, 0x720e, 0x600f, 0x0000, 0x080c, 0xac1b, - 0x7027, 0x0000, 0x00ce, 0x00ee, 0x00be, 0x0005, 0x720e, 0x720a, - 0x0ca8, 0x00d6, 0x2069, 0x19e8, 0x6830, 0x9084, 0x0003, 0x0002, - 0x9a6e, 0x9a70, 0x9a94, 0x9a6c, 0x080c, 0x0dc5, 0x00de, 0x0005, - 0x00c6, 0x6840, 0x9086, 0x0001, 0x01b8, 0x683c, 0x9065, 0x0130, - 0x600c, 0x9015, 0x0170, 0x6a3a, 0x600f, 0x0000, 0x6833, 0x0000, - 0x683f, 0x0000, 0x2011, 0x1a07, 0x2013, 0x0000, 0x00ce, 0x00de, - 0x0005, 0x683a, 0x6836, 0x0c90, 0x6843, 0x0000, 0x6838, 0x9065, - 0x0d68, 0x6003, 0x0003, 0x0c50, 0x00c6, 0x9006, 0x6842, 0x6846, - 0x684a, 0x683c, 0x9065, 0x0160, 0x600c, 0x9015, 0x0130, 0x6a3a, - 0x600f, 0x0000, 0x683f, 0x0000, 0x0018, 0x683e, 0x683a, 0x6836, - 0x00ce, 0x00de, 0x0005, 0x2001, 0x180c, 0x200c, 0xc1e5, 0x2102, - 0x0005, 0x2001, 0x180c, 0x200c, 0xd1ec, 0x0120, 0xc1ec, 0x2102, - 0x080c, 0x9bd3, 0x2001, 0x19f4, 0x2004, 0x9086, 0x0001, 0x0d58, - 0x00d6, 0x2069, 0x19e8, 0x6804, 0x9084, 0x0007, 0x0006, 0x9005, - 0x11c8, 0x2001, 0x1837, 0x2004, 0x9084, 0x0028, 0x1198, 0x2001, - 0x197c, 0x2004, 0x9086, 0xaaaa, 0x0168, 0x2001, 0x188b, 0x2004, - 0xd08c, 0x1118, 0xd084, 0x1118, 0x0028, 0x080c, 0x9bd3, 0x000e, - 0x00de, 0x0005, 0x000e, 0x0002, 0x9aee, 0x9ba7, 0x9ba7, 0x9ba7, - 0x9ba7, 0x9ba9, 0x9ba7, 0x9aec, 0x080c, 0x0dc5, 0x6820, 0x9005, - 0x1110, 0x00de, 0x0005, 0x00c6, 0x680c, 0x9065, 0x01f0, 0x6104, - 0x918e, 0x0040, 0x1180, 0x2009, 0x1837, 0x210c, 0x918c, 0x0028, - 0x1150, 0x080c, 0x7637, 0x0138, 0x0006, 0x2009, 0x188b, 0x2104, - 0xc095, 0x200a, 0x000e, 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, - 0x080c, 0x9c7c, 0x00ce, 0x00de, 0x0005, 0x6814, 0x9065, 0x0150, - 0x6807, 0x0001, 0x6826, 0x682b, 0x0000, 0x080c, 0x9c7c, 0x00ce, - 0x00de, 0x0005, 0x00b6, 0x00e6, 0x6a1c, 0x92dd, 0x0000, 0x0904, - 0x9b91, 0xb84c, 0x900d, 0x0118, 0xb888, 0x9005, 0x01a0, 0xb854, - 0x905d, 0x0120, 0x920e, 0x0904, 0x9b91, 0x0028, 0x6818, 0x920e, - 0x0904, 0x9b91, 0x2058, 0xb84c, 0x900d, 0x0d88, 0xb888, 0x9005, - 0x1d70, 0x2b00, 0x681e, 0xbb3c, 0xb838, 0x9302, 0x1e40, 0x080c, - 0xb2aa, 0x0904, 0x9b91, 0x8318, 0xbb3e, 0x6116, 0x2b10, 0x6212, - 0x0096, 0x2148, 0xa880, 0x9084, 0x00ff, 0x605e, 0xa883, 0x0000, - 0xa884, 0x009e, 0x908a, 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, - 0x801b, 0x831b, 0x9318, 0x631a, 0x6114, 0x0096, 0x2148, 0xa964, - 0x009e, 0x918c, 0x00ff, 0x918e, 0x0048, 0x0538, 0x00f6, 0x2c78, - 0x2061, 0x0100, 0xbac0, 0x629a, 0x2069, 0x0200, 0x2071, 0x0240, - 0x080c, 0xa219, 0x2069, 0x19e8, 0xbb00, 0xc3dd, 0xbb02, 0x6807, - 0x0002, 0x2f18, 0x6b26, 0x682b, 0x0000, 0x7823, 0x0003, 0x7803, - 0x0001, 0x7807, 0x0040, 0x00fe, 0x00ee, 0x00be, 0x00ce, 0x00de, - 0x0005, 0x00ee, 0x00be, 0x00ce, 0x0cd0, 0x6807, 0x0006, 0x2c18, - 0x6b26, 0x6820, 0x8001, 0x6822, 0x682b, 0x0000, 0x080c, 0x664c, - 0x080c, 0xb0ea, 0x00ee, 0x00be, 0x00ce, 0x00de, 0x0005, 0x00de, - 0x0005, 0x00c6, 0x680c, 0x9065, 0x01d8, 0x6104, 0x918e, 0x0040, - 0x1180, 0x2009, 0x1837, 0x210c, 0x918c, 0x0028, 0x1150, 0x080c, - 0x7637, 0x0138, 0x0006, 0x2009, 0x188b, 0x2104, 0xc095, 0x200a, - 0x000e, 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, 0x080c, 0x9c7c, - 0x00ce, 0x00de, 0x0005, 0x2001, 0x180c, 0x2014, 0xc2ed, 0x2202, - 0x00de, 0x00fe, 0x0005, 0x00f6, 0x00d6, 0x2069, 0x19e8, 0x6830, - 0x9086, 0x0000, 0x1570, 0x2001, 0x180c, 0x2014, 0xd2e4, 0x0130, - 0xc2e4, 0x2202, 0x080c, 0x9ac0, 0x2069, 0x19e8, 0x2001, 0x180c, - 0x200c, 0xd1c4, 0x1508, 0x6838, 0x907d, 0x01d8, 0x6a04, 0x9296, - 0x0000, 0x1904, 0x9c70, 0x7920, 0x918e, 0x0009, 0x0568, 0x6833, - 0x0001, 0x683e, 0x6847, 0x0000, 0x684b, 0x0000, 0x0126, 0x00f6, - 0x2091, 0x2400, 0x002e, 0x080c, 0x1c79, 0x1158, 0x012e, 0x080c, - 0xa546, 0x00de, 0x00fe, 0x0005, 0xc1c4, 0x2102, 0x080c, 0x76e4, - 0x08d0, 0x012e, 0x6843, 0x0000, 0x7803, 0x0002, 0x780c, 0x9015, - 0x0140, 0x6a3a, 0x780f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, - 0x0c40, 0x683a, 0x6836, 0x0cc0, 0x7908, 0xd1fc, 0x1198, 0x6833, - 0x0001, 0x683e, 0x6847, 0x0000, 0x684b, 0x0000, 0x0126, 0x00f6, - 0x2091, 0x2400, 0x002e, 0x080c, 0x1c79, 0x19d8, 0x012e, 0x080c, - 0xa4c7, 0x0878, 0x2001, 0x1837, 0x2004, 0x9084, 0x0028, 0x1188, - 0x2001, 0x197c, 0x2004, 0x9086, 0xaaaa, 0x0158, 0x2001, 0x19e9, - 0x2004, 0x9005, 0x11f0, 0x2001, 0x188b, 0x200c, 0xc185, 0xc18c, - 0x2102, 0x2f00, 0x6833, 0x0001, 0x683e, 0x6847, 0x0000, 0x684b, - 0x0000, 0x0126, 0x00f6, 0x2091, 0x2400, 0x002e, 0x080c, 0x1c79, - 0x1904, 0x9c11, 0x012e, 0x6a3c, 0x2278, 0x080c, 0xa451, 0x0804, - 0x9c09, 0x2011, 0x188b, 0x2204, 0xc08d, 0x2012, 0x0804, 0x9c09, - 0x6a04, 0x9296, 0x0006, 0x1904, 0x9bcb, 0x6a30, 0x9296, 0x0000, - 0x0904, 0x9bf3, 0x0804, 0x9bcb, 0x6020, 0x9084, 0x000f, 0x000b, - 0x0005, 0x9c90, 0x9c95, 0xa149, 0xa1e2, 0x9c95, 0xa149, 0xa1e2, - 0x9c90, 0x9c95, 0x9c90, 0x9c90, 0x9c90, 0x9c90, 0x9c90, 0x9c90, - 0x080c, 0x99a5, 0x080c, 0x9ab1, 0x0005, 0x00b6, 0x0156, 0x0136, - 0x0146, 0x01c6, 0x01d6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2069, - 0x0200, 0x2071, 0x0240, 0x6004, 0x908a, 0x0053, 0x1a0c, 0x0dc5, - 0x6110, 0x2158, 0xb9c0, 0x2c78, 0x2061, 0x0100, 0x619a, 0x908a, - 0x0040, 0x1a04, 0x9d01, 0x005b, 0x00fe, 0x00ee, 0x00de, 0x00ce, - 0x01de, 0x01ce, 0x014e, 0x013e, 0x015e, 0x00be, 0x0005, 0x9eaa, - 0x9ee5, 0x9f0e, 0x9fd8, 0x9ffa, 0xa000, 0xa00d, 0xa015, 0xa021, - 0xa027, 0xa038, 0xa027, 0xa090, 0xa015, 0xa09c, 0xa0a2, 0xa021, - 0xa0a2, 0xa0ae, 0x9cff, 0x9cff, 0x9cff, 0x9cff, 0x9cff, 0x9cff, - 0x9cff, 0x9cff, 0x9cff, 0x9cff, 0x9cff, 0xa900, 0xa923, 0xa934, - 0xa954, 0xa986, 0xa00d, 0x9cff, 0xa00d, 0xa027, 0x9cff, 0x9f0e, - 0x9fd8, 0x9cff, 0xad12, 0xa027, 0x9cff, 0xad2e, 0xa027, 0x9cff, - 0xa021, 0x9ea4, 0x9d22, 0x9cff, 0xad4a, 0xadb7, 0xae92, 0x9cff, - 0xae9f, 0xa00a, 0xaeca, 0x9cff, 0xa990, 0xaef7, 0x9cff, 0x080c, - 0x0dc5, 0x2100, 0x005b, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x01de, - 0x01ce, 0x014e, 0x013e, 0x015e, 0x00be, 0x0005, 0xaf92, 0xb044, - 0x9d20, 0x9d5a, 0x9e06, 0x9e11, 0x9d20, 0xa00d, 0x9d20, 0x9e6b, - 0x9e77, 0x9d75, 0x9d20, 0x9d90, 0x9dc4, 0xb1b1, 0xb1f6, 0xa027, - 0x080c, 0x0dc5, 0x00d6, 0x0096, 0x080c, 0xa0c1, 0x0026, 0x0036, - 0x7814, 0x2048, 0xa958, 0xd1cc, 0x1138, 0x2009, 0x2414, 0x2011, - 0x0018, 0x2019, 0x0018, 0x0030, 0x2009, 0x2410, 0x2011, 0x0014, - 0x2019, 0x0014, 0x7102, 0x7206, 0x700b, 0x0800, 0xa83c, 0x700e, - 0xa850, 0x7022, 0xa854, 0x7026, 0x63c2, 0x080c, 0xa6bd, 0x003e, - 0x002e, 0x009e, 0x00de, 0x0005, 0x7810, 0x00b6, 0x2058, 0xb8a0, - 0x00be, 0x080c, 0xb23d, 0x1118, 0x9084, 0xff80, 0x0110, 0x9085, - 0x0001, 0x0005, 0x00d6, 0x0096, 0x080c, 0xa0c1, 0x7003, 0x0500, - 0x7814, 0x2048, 0xa874, 0x700a, 0xa878, 0x700e, 0xa87c, 0x7012, - 0xa880, 0x7016, 0xa884, 0x701a, 0xa888, 0x701e, 0x60c3, 0x0010, - 0x080c, 0xa6bd, 0x009e, 0x00de, 0x0005, 0x00d6, 0x0096, 0x080c, - 0xa0c1, 0x7003, 0x0500, 0x7814, 0x2048, 0xa8cc, 0x700a, 0xa8d0, - 0x700e, 0xa8d4, 0x7012, 0xa8d8, 0x7016, 0xa8dc, 0x701a, 0xa8e0, - 0x701e, 0x60c3, 0x0010, 0x080c, 0xa6bd, 0x009e, 0x00de, 0x0005, - 0x00d6, 0x0096, 0x0126, 0x2091, 0x8000, 0x080c, 0xa0c1, 0x20e9, - 0x0000, 0x2001, 0x19a4, 0x2003, 0x0000, 0x7814, 0x2048, 0xa814, - 0x8003, 0x60c2, 0xa830, 0x20a8, 0xa860, 0x20e0, 0xa85c, 0x9080, - 0x001b, 0x2098, 0x2001, 0x19a4, 0x0016, 0x200c, 0x2001, 0x0001, - 0x080c, 0x23ee, 0x080c, 0xde7c, 0x9006, 0x080c, 0x23ee, 0x001e, - 0xa804, 0x9005, 0x0110, 0x2048, 0x0c28, 0x04d9, 0x080c, 0xa6bd, - 0x012e, 0x009e, 0x00de, 0x0005, 0x00d6, 0x0096, 0x0126, 0x2091, - 0x8000, 0x080c, 0xa10c, 0x20e9, 0x0000, 0x2001, 0x19a4, 0x2003, - 0x0000, 0x7814, 0x2048, 0xa86f, 0x0200, 0xa873, 0x0000, 0xa814, - 0x8003, 0x60c2, 0xa830, 0x20a8, 0xa860, 0x20e0, 0xa85c, 0x9080, - 0x001b, 0x2098, 0x2001, 0x19a4, 0x0016, 0x200c, 0x080c, 0xde7c, - 0x001e, 0xa804, 0x9005, 0x0110, 0x2048, 0x0c60, 0x0051, 0x7814, - 0x2048, 0x080c, 0x0fc0, 0x080c, 0xa6bd, 0x012e, 0x009e, 0x00de, - 0x0005, 0x60c0, 0x8004, 0x9084, 0x0003, 0x9005, 0x0130, 0x9082, - 0x0004, 0x20a3, 0x0000, 0x8000, 0x1de0, 0x0005, 0x080c, 0xa0c1, - 0x7003, 0x7800, 0x7808, 0x8007, 0x700a, 0x60c3, 0x0008, 0x0804, - 0xa6bd, 0x00d6, 0x00e6, 0x080c, 0xa10c, 0x7814, 0x9084, 0xff00, - 0x2073, 0x0200, 0x8e70, 0x8e70, 0x9096, 0xdf00, 0x0138, 0x9096, - 0xe000, 0x0120, 0x2073, 0x0010, 0x8e70, 0x0030, 0x9095, 0x0010, - 0x2272, 0x8e70, 0x2073, 0x0034, 0x8e70, 0x2069, 0x1805, 0x20a9, - 0x0004, 0x2d76, 0x8d68, 0x8e70, 0x1f04, 0x9e31, 0x2069, 0x1801, - 0x20a9, 0x0004, 0x2d76, 0x8d68, 0x8e70, 0x1f04, 0x9e3a, 0x9096, - 0xdf00, 0x0130, 0x9096, 0xe000, 0x0118, 0x60c3, 0x0018, 0x00f0, - 0x2069, 0x19b4, 0x9086, 0xdf00, 0x0110, 0x2069, 0x19ce, 0x20a9, - 0x001a, 0x9e86, 0x0260, 0x1148, 0x00c6, 0x2061, 0x0200, 0x6010, - 0x8000, 0x6012, 0x00ce, 0x2071, 0x0240, 0x2d04, 0x8007, 0x2072, - 0x8d68, 0x8e70, 0x1f04, 0x9e51, 0x60c3, 0x004c, 0x080c, 0xa6bd, - 0x00ee, 0x00de, 0x0005, 0x080c, 0xa0c1, 0x7003, 0x6300, 0x7007, - 0x0028, 0x7808, 0x700e, 0x60c3, 0x0008, 0x0804, 0xa6bd, 0x00d6, - 0x0026, 0x0016, 0x080c, 0xa10c, 0x7003, 0x0200, 0x7814, 0x700e, - 0x00e6, 0x9ef0, 0x0004, 0x2009, 0x0001, 0x2011, 0x000c, 0x2069, - 0x1924, 0x6810, 0xd084, 0x1148, 0x2073, 0x0500, 0x8e70, 0x2073, - 0x0000, 0x8e70, 0x8108, 0x9290, 0x0004, 0x2073, 0x0800, 0x8e70, - 0x2073, 0x0000, 0x00ee, 0x7206, 0x710a, 0x62c2, 0x080c, 0xa6bd, - 0x001e, 0x002e, 0x00de, 0x0005, 0x2001, 0x1818, 0x2004, 0x609a, - 0x0804, 0xa6bd, 0x080c, 0xa0c1, 0x7003, 0x5200, 0x2069, 0x1847, - 0x6804, 0xd084, 0x0130, 0x6828, 0x0016, 0x080c, 0x28a6, 0x710e, - 0x001e, 0x20a9, 0x0004, 0x20e1, 0x0001, 0x2099, 0x1805, 0x20e9, - 0x0000, 0x20a1, 0x0250, 0x4003, 0x20a9, 0x0004, 0x2099, 0x1801, - 0x20a1, 0x0254, 0x4003, 0x080c, 0xb23d, 0x1120, 0xb8a0, 0x9082, - 0x007f, 0x0248, 0x2001, 0x181f, 0x2004, 0x7032, 0x2001, 0x1820, - 0x2004, 0x7036, 0x0030, 0x2001, 0x1818, 0x2004, 0x9084, 0x00ff, - 0x7036, 0x60c3, 0x001c, 0x0804, 0xa6bd, 0x080c, 0xa0c1, 0x7003, - 0x0500, 0x080c, 0xb23d, 0x1120, 0xb8a0, 0x9082, 0x007f, 0x0248, - 0x2001, 0x181f, 0x2004, 0x700a, 0x2001, 0x1820, 0x2004, 0x700e, - 0x0030, 0x2001, 0x1818, 0x2004, 0x9084, 0x00ff, 0x700e, 0x20a9, - 0x0004, 0x20e1, 0x0001, 0x2099, 0x1805, 0x20e9, 0x0000, 0x20a1, - 0x0250, 0x4003, 0x60c3, 0x0010, 0x0804, 0xa6bd, 0x080c, 0xa0c1, - 0x9006, 0x080c, 0x6a6d, 0xb8a0, 0x9086, 0x007e, 0x1170, 0x2011, - 0x0240, 0x2013, 0x22ff, 0x2011, 0x0241, 0x2013, 0xfffe, 0x7003, - 0x0400, 0x620c, 0xc2b4, 0x620e, 0x0058, 0x7814, 0x0096, 0x904d, - 0x0120, 0x9006, 0xa89a, 0xa8a6, 0xa8aa, 0x009e, 0x7003, 0x0300, - 0xb8a0, 0x9086, 0x007e, 0x1904, 0x9f98, 0x00d6, 0x2069, 0x196c, - 0x2001, 0x1837, 0x2004, 0xd0a4, 0x0188, 0x6800, 0x700a, 0x6808, - 0x9084, 0x2000, 0x7012, 0x080c, 0xb254, 0x680c, 0x7016, 0x701f, - 0x2710, 0x6818, 0x7022, 0x681c, 0x7026, 0x0428, 0x6800, 0x700a, - 0x6804, 0x700e, 0x2009, 0x180d, 0x210c, 0xd18c, 0x0110, 0x2001, - 0x0002, 0x00f6, 0x2079, 0x0100, 0x080c, 0x7637, 0x1128, 0x78e3, - 0x0000, 0x080c, 0x28e7, 0x78e2, 0x00fe, 0x6808, 0x080c, 0x7637, - 0x1118, 0x9084, 0x37ff, 0x0010, 0x9084, 0x3fff, 0x7012, 0x080c, - 0xb254, 0x680c, 0x7016, 0x00de, 0x20a9, 0x0004, 0x20e1, 0x0001, - 0x2099, 0x1805, 0x20e9, 0x0000, 0x20a1, 0x0256, 0x4003, 0x20a9, - 0x0004, 0x2099, 0x1801, 0x20a1, 0x025a, 0x4003, 0x00d6, 0x080c, - 0xaf79, 0x2069, 0x1974, 0x2071, 0x024e, 0x6800, 0xc0dd, 0x7002, - 0x080c, 0x57d9, 0xd0e4, 0x0110, 0x680c, 0x700e, 0x00de, 0x04e0, - 0x2001, 0x1837, 0x2004, 0xd0a4, 0x01a8, 0x0016, 0x2001, 0x180d, - 0x2004, 0xd08c, 0x2009, 0x0002, 0x1118, 0x2001, 0x196d, 0x200c, - 0x60e0, 0x9106, 0x0130, 0x2100, 0x60e3, 0x0000, 0x080c, 0x28e7, - 0x61e2, 0x001e, 0x20e1, 0x0001, 0x2099, 0x196c, 0x20e9, 0x0000, - 0x20a1, 0x024e, 0x20a9, 0x0008, 0x4003, 0x20a9, 0x0004, 0x2099, - 0x1805, 0x20a1, 0x0256, 0x4003, 0x20a9, 0x0004, 0x2099, 0x1801, - 0x20a1, 0x025a, 0x4003, 0x080c, 0xaf79, 0x20a1, 0x024e, 0x20a9, - 0x0008, 0x2099, 0x1974, 0x4003, 0x60c3, 0x0074, 0x0804, 0xa6bd, - 0x080c, 0xa0c1, 0x7003, 0x2010, 0x7007, 0x0014, 0x700b, 0x0800, - 0x700f, 0x2000, 0x9006, 0x00f6, 0x2079, 0x1847, 0x7904, 0x00fe, - 0xd1ac, 0x1110, 0x9085, 0x0020, 0xd1a4, 0x0110, 0x9085, 0x0010, - 0x9085, 0x0002, 0x00d6, 0x0804, 0xa071, 0x7026, 0x60c3, 0x0014, - 0x0804, 0xa6bd, 0x080c, 0xa0c1, 0x7003, 0x5000, 0x0804, 0x9f30, - 0x080c, 0xa0c1, 0x7003, 0x2110, 0x7007, 0x0014, 0x60c3, 0x0014, - 0x0804, 0xa6bd, 0x080c, 0xa103, 0x0010, 0x080c, 0xa10c, 0x7003, - 0x0200, 0x60c3, 0x0004, 0x0804, 0xa6bd, 0x080c, 0xa10c, 0x7003, - 0x0100, 0x700b, 0x0003, 0x700f, 0x2a00, 0x60c3, 0x0008, 0x0804, - 0xa6bd, 0x080c, 0xa10c, 0x7003, 0x0200, 0x0804, 0x9f30, 0x080c, - 0xa10c, 0x7003, 0x0100, 0x782c, 0x9005, 0x0110, 0x700a, 0x0010, - 0x700b, 0x0003, 0x7814, 0x700e, 0x60c3, 0x0008, 0x0804, 0xa6bd, - 0x00d6, 0x080c, 0xa10c, 0x7003, 0x0210, 0x7007, 0x0014, 0x700b, - 0x0800, 0xb894, 0x9086, 0x0014, 0x1198, 0xb99c, 0x9184, 0x0030, - 0x0190, 0xb998, 0x9184, 0xc000, 0x1140, 0xd1ec, 0x0118, 0x700f, - 0x2100, 0x0058, 0x700f, 0x0100, 0x0040, 0x700f, 0x0400, 0x0028, - 0x700f, 0x0700, 0x0010, 0x700f, 0x0800, 0x00f6, 0x2079, 0x1847, - 0x7904, 0x00fe, 0xd1ac, 0x1110, 0x9085, 0x0020, 0xd1a4, 0x0110, - 0x9085, 0x0010, 0x2009, 0x1869, 0x210c, 0xd184, 0x1110, 0x9085, - 0x0002, 0x0026, 0x2009, 0x1867, 0x210c, 0xd1e4, 0x0150, 0xc0c5, - 0xbacc, 0xd28c, 0x1108, 0xc0cd, 0x9094, 0x0030, 0x9296, 0x0010, - 0x0140, 0xd1ec, 0x0130, 0x9094, 0x0030, 0x9296, 0x0010, 0x0108, - 0xc0bd, 0x002e, 0x7026, 0x60c3, 0x0014, 0x00de, 0x0804, 0xa6bd, - 0x080c, 0xa10c, 0x7003, 0x0210, 0x7007, 0x0014, 0x700f, 0x0100, - 0x60c3, 0x0014, 0x0804, 0xa6bd, 0x080c, 0xa10c, 0x7003, 0x0200, - 0x0804, 0x9eae, 0x080c, 0xa10c, 0x7003, 0x0100, 0x700b, 0x0003, - 0x700f, 0x2a00, 0x60c3, 0x0008, 0x0804, 0xa6bd, 0x080c, 0xa10c, - 0x7003, 0x0100, 0x700b, 0x000b, 0x60c3, 0x0008, 0x0804, 0xa6bd, - 0x0026, 0x00d6, 0x0036, 0x0046, 0x2019, 0x3200, 0x2021, 0x0800, - 0x0040, 0x0026, 0x00d6, 0x0036, 0x0046, 0x2019, 0x2200, 0x2021, - 0x0100, 0x080c, 0xaf8e, 0xb810, 0x9305, 0x7002, 0xb814, 0x7006, - 0x2069, 0x1800, 0x687c, 0x700a, 0x6880, 0x700e, 0x9485, 0x0029, - 0x7012, 0x004e, 0x003e, 0x00de, 0x080c, 0xa6ab, 0x721a, 0x9f95, - 0x0000, 0x7222, 0x7027, 0xffff, 0x2071, 0x024c, 0x002e, 0x0005, - 0x0026, 0x080c, 0xaf8e, 0x7003, 0x02ff, 0x7007, 0xfffc, 0x00d6, - 0x2069, 0x1800, 0x687c, 0x700a, 0x6880, 0x700e, 0x00de, 0x7013, - 0x2029, 0x0c10, 0x7003, 0x0100, 0x7007, 0x0000, 0x700b, 0xfc02, - 0x700f, 0x0000, 0x0005, 0x0026, 0x00d6, 0x0036, 0x0046, 0x2019, - 0x3300, 0x2021, 0x0800, 0x0040, 0x0026, 0x00d6, 0x0036, 0x0046, - 0x2019, 0x2300, 0x2021, 0x0100, 0x080c, 0xaf8e, 0xb810, 0x9305, - 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, 0xb810, 0x9005, 0x1140, - 0xb814, 0x9005, 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffe, 0x0020, - 0x687c, 0x700a, 0x6880, 0x700e, 0x0000, 0x9485, 0x0098, 0x7012, - 0x004e, 0x003e, 0x00de, 0x080c, 0xa6ab, 0x721a, 0x7a08, 0x7222, - 0x2f10, 0x7226, 0x2071, 0x024c, 0x002e, 0x0005, 0x080c, 0xa6ab, - 0x721a, 0x7a08, 0x7222, 0x7814, 0x7026, 0x2071, 0x024c, 0x002e, - 0x0005, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2069, 0x0200, - 0x2071, 0x0240, 0x6004, 0x908a, 0x0085, 0x0a0c, 0x0dc5, 0x908a, - 0x0092, 0x1a0c, 0x0dc5, 0x6110, 0x2158, 0xb9c0, 0x2c78, 0x2061, - 0x0100, 0x619a, 0x9082, 0x0085, 0x0033, 0x00fe, 0x00ee, 0x00de, - 0x00ce, 0x00be, 0x0005, 0xa17a, 0xa189, 0xa194, 0xa178, 0xa178, - 0xa178, 0xa17a, 0xa178, 0xa178, 0xa178, 0xa178, 0xa178, 0xa178, - 0x080c, 0x0dc5, 0x0411, 0x60c3, 0x0000, 0x0026, 0x080c, 0x2bce, - 0x0228, 0x2011, 0x0101, 0x2204, 0xc0c5, 0x2012, 0x002e, 0x0804, - 0xa6bd, 0x0431, 0x7808, 0x700a, 0x7814, 0x700e, 0x7017, 0xffff, - 0x60c3, 0x000c, 0x0804, 0xa6bd, 0x04a1, 0x7003, 0x0003, 0x7007, - 0x0300, 0x60c3, 0x0004, 0x0804, 0xa6bd, 0x0026, 0x080c, 0xaf8e, - 0xb810, 0x9085, 0x8100, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, - 0x687c, 0x700a, 0x6880, 0x700e, 0x7013, 0x0009, 0x0804, 0xa0dc, - 0x0026, 0x080c, 0xaf8e, 0xb810, 0x9085, 0x8400, 0x7002, 0xb814, - 0x7006, 0x2069, 0x1800, 0x687c, 0x700a, 0x6880, 0x700e, 0x2001, - 0x0099, 0x7a20, 0x9296, 0x0005, 0x0108, 0xc0bc, 0x7012, 0x0804, - 0xa13e, 0x0026, 0x080c, 0xaf8e, 0xb810, 0x9085, 0x8500, 0x7002, - 0xb814, 0x7006, 0x2069, 0x1800, 0x687c, 0x700a, 0x6880, 0x700e, - 0x2001, 0x0099, 0x7a20, 0x9296, 0x0005, 0x0108, 0xc0bc, 0x7012, - 0x0804, 0xa13e, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2c78, - 0x2069, 0x0200, 0x2071, 0x0240, 0x7804, 0x908a, 0x0040, 0x0a0c, - 0x0dc5, 0x908a, 0x0054, 0x1a0c, 0x0dc5, 0x7910, 0x2158, 0xb9c0, - 0x2061, 0x0100, 0x619a, 0x9082, 0x0040, 0x0033, 0x00fe, 0x00ee, - 0x00de, 0x00ce, 0x00be, 0x0005, 0xa219, 0xa2e0, 0xa2b3, 0xa402, - 0xa217, 0xa217, 0xa217, 0xa217, 0xa217, 0xa217, 0xa217, 0xaad8, - 0xaadd, 0xaae2, 0xaae7, 0xa217, 0xaed6, 0xa217, 0xaad3, 0x080c, - 0x0dc5, 0x0096, 0x780b, 0xffff, 0x080c, 0xa284, 0x7914, 0x2148, - 0xa978, 0x7956, 0xae64, 0x96b4, 0x00ff, 0x9686, 0x0008, 0x1148, - 0xa8b4, 0x7032, 0xa8b8, 0x7036, 0xa8bc, 0x703a, 0xa8c0, 0x703e, - 0x0008, 0x7132, 0xa97c, 0x9184, 0x000f, 0x1118, 0x2001, 0x0005, - 0x0040, 0xd184, 0x0118, 0x2001, 0x0004, 0x0018, 0x9084, 0x0006, - 0x8004, 0x2010, 0x785c, 0x9084, 0x00ff, 0x8007, 0x9205, 0x7042, - 0xd1ac, 0x0158, 0x7047, 0x0002, 0x9686, 0x0008, 0x1118, 0x080c, - 0x18f7, 0x0010, 0x080c, 0x1768, 0x0050, 0xd1b4, 0x0118, 0x7047, - 0x0001, 0x0028, 0x7047, 0x0000, 0x9016, 0x2230, 0x0010, 0xaab0, - 0xaeac, 0x726a, 0x766e, 0x20a9, 0x0008, 0x20e9, 0x0000, 0xa860, - 0x20e0, 0xa85c, 0x9080, 0x0023, 0x2098, 0x20a1, 0x0252, 0x2069, - 0x0200, 0x6813, 0x0018, 0x4003, 0x6813, 0x0008, 0x60c3, 0x0020, - 0x6017, 0x0009, 0x2001, 0x1a04, 0x2003, 0x07d0, 0x2001, 0x1a03, - 0x2003, 0x0009, 0x009e, 0x0005, 0x6813, 0x0008, 0xba8c, 0x8210, - 0xb8cc, 0xd084, 0x0180, 0x2001, 0x1ad0, 0x200c, 0x8108, 0x2102, - 0x2001, 0x1acf, 0x201c, 0x1218, 0x8318, 0x2302, 0x0ea0, 0x794a, - 0x712e, 0x7b46, 0x732a, 0x9294, 0x00ff, 0xba8e, 0x8217, 0x721a, - 0xba10, 0x9295, 0x0600, 0x7202, 0xba14, 0x7206, 0x2069, 0x1800, - 0x6a7c, 0x720a, 0x6a80, 0x720e, 0x7013, 0x0829, 0x2f10, 0x7222, - 0x7027, 0xffff, 0x0005, 0x00d6, 0x0096, 0x0081, 0x7814, 0x2048, - 0xa890, 0x7002, 0xa88c, 0x7006, 0xa8b0, 0x700a, 0xa8ac, 0x700e, - 0x60c3, 0x000c, 0x009e, 0x00de, 0x0804, 0xa6bd, 0x6813, 0x0008, - 0xb810, 0x9085, 0x0500, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, - 0x687c, 0x700a, 0x6880, 0x700e, 0x7013, 0x0889, 0x080c, 0xa6ab, - 0x721a, 0x7a08, 0x7222, 0x2f10, 0x7226, 0x2071, 0x024c, 0x0005, - 0x00d6, 0x0096, 0x080c, 0xa3e0, 0x7814, 0x2048, 0x080c, 0xd0d6, - 0x1130, 0x7814, 0x9084, 0x0700, 0x8007, 0x0033, 0x0010, 0x9006, - 0x001b, 0x009e, 0x00de, 0x0005, 0xa2fe, 0xa367, 0xa377, 0xa39d, - 0xa3a9, 0xa3ba, 0xa3c2, 0xa2fc, 0x080c, 0x0dc5, 0x0016, 0x0036, - 0xa97c, 0x918c, 0x0003, 0x0118, 0x9186, 0x0003, 0x1198, 0xaba8, - 0x7824, 0xd0cc, 0x1168, 0x7316, 0xa898, 0x701a, 0xa894, 0x701e, - 0x003e, 0x001e, 0x2001, 0x19b2, 0x2004, 0x60c2, 0x0804, 0xa6bd, - 0xc3e5, 0x0c88, 0x9186, 0x0001, 0x190c, 0x0dc5, 0xaba8, 0x7824, - 0xd0cc, 0x1904, 0xa364, 0x7316, 0xa898, 0x701a, 0xa894, 0x701e, - 0xa8a4, 0x7026, 0xa8ac, 0x702e, 0x2009, 0x0018, 0x9384, 0x0300, - 0x0570, 0xd3c4, 0x0110, 0xa8ac, 0x9108, 0xd3cc, 0x0110, 0xa8a4, - 0x9108, 0x6810, 0x9085, 0x0010, 0x6812, 0x2011, 0x0258, 0x20e9, - 0x0000, 0x22a0, 0x0156, 0x20a9, 0x0008, 0xa860, 0x20e0, 0xa85c, - 0x9080, 0x002c, 0x2098, 0x4003, 0x6810, 0x8000, 0x6812, 0x2011, - 0x0240, 0x22a0, 0x20a9, 0x0005, 0x4003, 0x6810, 0xc0a4, 0x6812, - 0x015e, 0x9184, 0x0003, 0x0118, 0x2019, 0x0245, 0x201a, 0x61c2, - 0x003e, 0x001e, 0x0804, 0xa6bd, 0xc3e5, 0x0804, 0xa323, 0x2011, - 0x0008, 0x2001, 0x180f, 0x2004, 0xd0a4, 0x0110, 0x2011, 0x0028, - 0x7824, 0xd0cc, 0x1110, 0x7216, 0x0470, 0x0ce8, 0xc2e5, 0x2011, - 0x0302, 0x0016, 0x782c, 0x701a, 0x7930, 0x711e, 0x9105, 0x0108, - 0xc2dd, 0x001e, 0x7824, 0xd0cc, 0x0108, 0xc2e5, 0x7216, 0x7027, - 0x0012, 0x702f, 0x0008, 0x7043, 0x7000, 0x7047, 0x0500, 0x704f, - 0x000a, 0x2069, 0x0200, 0x6813, 0x0009, 0x2071, 0x0240, 0x700b, - 0x2500, 0x60c3, 0x0032, 0x0804, 0xa6bd, 0x2011, 0x0028, 0x7824, - 0xd0cc, 0x1128, 0x7216, 0x60c3, 0x0018, 0x0804, 0xa6bd, 0x0cd0, - 0xc2e5, 0x2011, 0x0100, 0x7824, 0xd0cc, 0x0108, 0xc2e5, 0x7216, - 0x702f, 0x0008, 0x7858, 0x9084, 0x00ff, 0x7036, 0x60c3, 0x0020, - 0x0804, 0xa6bd, 0x2011, 0x0008, 0x7824, 0xd0cc, 0x0108, 0xc2e5, - 0x7216, 0x0c08, 0x0036, 0x7b14, 0x9384, 0xff00, 0x7816, 0x9384, - 0x00ff, 0x8001, 0x1138, 0x7824, 0xd0cc, 0x0108, 0xc2e5, 0x7216, - 0x003e, 0x0888, 0x0046, 0x2021, 0x0800, 0x0006, 0x7824, 0xd0cc, - 0x000e, 0x0108, 0xc4e5, 0x7416, 0x004e, 0x701e, 0x003e, 0x0818, - 0x00d6, 0x6813, 0x0008, 0xb810, 0x9085, 0x0700, 0x7002, 0xb814, - 0x7006, 0x2069, 0x1800, 0x687c, 0x700a, 0x6880, 0x700e, 0x7824, - 0xd0cc, 0x1168, 0x7013, 0x0898, 0x080c, 0xa6ab, 0x721a, 0x7a08, - 0x7222, 0x2f10, 0x7226, 0x2071, 0x024c, 0x00de, 0x0005, 0x7013, - 0x0889, 0x0c90, 0x0016, 0x7814, 0x9084, 0x0700, 0x8007, 0x0013, - 0x001e, 0x0005, 0xa412, 0xa412, 0xa414, 0xa412, 0xa412, 0xa412, - 0xa42e, 0xa412, 0x080c, 0x0dc5, 0x7914, 0x918c, 0x08ff, 0x918d, - 0xf600, 0x7916, 0x2009, 0x0003, 0x00b9, 0x2069, 0x1847, 0x6804, - 0xd0bc, 0x0130, 0x682c, 0x9084, 0x00ff, 0x8007, 0x7032, 0x0010, - 0x7033, 0x3f00, 0x60c3, 0x0001, 0x0804, 0xa6bd, 0x2009, 0x0003, - 0x0019, 0x7033, 0x7f00, 0x0cb0, 0x0016, 0x080c, 0xaf8e, 0x001e, - 0xb810, 0x9085, 0x0100, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, - 0x6a7c, 0x720a, 0x6a80, 0x720e, 0x7013, 0x0888, 0x918d, 0x0008, - 0x7116, 0x080c, 0xa6ab, 0x721a, 0x7a08, 0x7222, 0x2f10, 0x7226, - 0x0005, 0x00b6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046, - 0x0036, 0x2061, 0x0100, 0x2071, 0x1800, 0x7160, 0x7810, 0x2058, - 0x76dc, 0x96b4, 0x0028, 0x0110, 0x737c, 0x7480, 0x2500, 0x76dc, - 0x96b4, 0x0028, 0x0140, 0x2001, 0x04ff, 0x6062, 0x6067, 0xffff, - 0x636a, 0x646e, 0x0050, 0x2001, 0x00ff, 0x9085, 0x0400, 0x6062, - 0x6067, 0xffff, 0x606b, 0x0000, 0x616e, 0xb8b8, 0x6073, 0x0530, - 0x6077, 0x0008, 0xb88c, 0x8000, 0x9084, 0x00ff, 0xb88e, 0x8007, - 0x9085, 0x0020, 0x607a, 0x607f, 0x0000, 0x2b00, 0x6082, 0x6087, - 0xffff, 0x7814, 0x0096, 0x2048, 0xa838, 0x608a, 0xa834, 0x608e, - 0xa848, 0x60c6, 0xa844, 0x60ca, 0x009e, 0xb86c, 0x60ce, 0x60ab, - 0x0036, 0x60af, 0x95d5, 0x60d7, 0x0000, 0x2001, 0x1837, 0x2004, - 0x9084, 0x0028, 0x0128, 0x609f, 0x0000, 0x2001, 0x0092, 0x0048, - 0x6028, 0xc0bd, 0x602a, 0x609f, 0x00ff, 0x6027, 0xffff, 0x2001, - 0x00b2, 0x6016, 0x2009, 0x07d0, 0x080c, 0x88c8, 0x003e, 0x004e, - 0x005e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00be, 0x0005, 0x00b6, - 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046, 0x0036, 0x2061, - 0x0100, 0x2071, 0x1800, 0x7160, 0x7810, 0x2058, 0xb8a0, 0x2028, - 0x76dc, 0xd6ac, 0x1168, 0x9582, 0x007e, 0x1250, 0x2500, 0x9094, - 0xff80, 0x1130, 0x9080, 0x33b6, 0x2015, 0x9294, 0x00ff, 0x0020, - 0xb910, 0xba14, 0x737c, 0x7480, 0x70dc, 0xd0ac, 0x1130, 0x9582, - 0x007e, 0x1218, 0x9584, 0xff80, 0x0138, 0x9185, 0x0400, 0x6062, - 0x6266, 0x636a, 0x646e, 0x0030, 0x6063, 0x0400, 0x6266, 0x606b, - 0x0000, 0x616e, 0xb8b8, 0x6072, 0x6077, 0x0000, 0xb864, 0xd0a4, - 0x0110, 0x6077, 0x0008, 0xb88c, 0x8000, 0x9084, 0x00ff, 0xb88e, - 0x8007, 0x9085, 0x0020, 0x607a, 0x607f, 0x0000, 0x2b00, 0x6082, - 0x6087, 0xffff, 0x7814, 0x0096, 0x2048, 0xa838, 0x608a, 0xa834, - 0x608e, 0xa848, 0x60c6, 0xa844, 0x60ca, 0x009e, 0xb86c, 0x60ce, - 0x60ab, 0x0036, 0x60af, 0x95d5, 0x60d7, 0x0000, 0xbac0, 0x629e, - 0x00f6, 0x2079, 0x0140, 0x7803, 0x0000, 0x00fe, 0x2009, 0x0092, - 0x6116, 0x2009, 0x07d0, 0x080c, 0x88c8, 0x003e, 0x004e, 0x005e, - 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00be, 0x0005, 0x00b6, 0x0096, - 0x00e6, 0x00d6, 0x00c6, 0x0056, 0x0046, 0x0036, 0x2061, 0x0100, - 0x2071, 0x1800, 0x7810, 0x2058, 0xb8a0, 0x2028, 0xb910, 0xba14, - 0x737c, 0x7480, 0x7820, 0x90be, 0x0006, 0x0904, 0xa61a, 0x90be, - 0x000a, 0x1904, 0xa5d6, 0xb8c0, 0x609e, 0x7814, 0x2048, 0xa87c, - 0xd0fc, 0x0558, 0xaf90, 0x9784, 0xff00, 0x9105, 0x6062, 0x873f, - 0x9784, 0xff00, 0x0006, 0x7814, 0x2048, 0xa878, 0xc0fc, 0x9005, - 0x000e, 0x1160, 0xaf94, 0x87ff, 0x0198, 0x2039, 0x0098, 0x9705, - 0x6072, 0x7808, 0x6082, 0x2f00, 0x6086, 0x0038, 0x9185, 0x2200, - 0x6062, 0x6073, 0x0129, 0x6077, 0x0000, 0xb8c0, 0x609e, 0x0050, - 0x2039, 0x0029, 0x9705, 0x6072, 0x0cc0, 0x9185, 0x0200, 0x6062, - 0x6073, 0x2029, 0xa87c, 0xd0fc, 0x0118, 0xaf94, 0x87ff, 0x1120, - 0x2f00, 0x6082, 0x7808, 0x6086, 0x6266, 0x636a, 0x646e, 0x6077, - 0x0000, 0xb88c, 0x8000, 0x9084, 0x00ff, 0xb88e, 0x8007, 0x607a, - 0x607f, 0x0000, 0xa838, 0x608a, 0xa834, 0x608e, 0xa848, 0x60c6, - 0xa844, 0x60ca, 0xb86c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, - 0x080c, 0xaf73, 0x2009, 0x07d0, 0x60c4, 0x9084, 0xfff0, 0x9005, - 0x0110, 0x2009, 0x1b58, 0x080c, 0x88c8, 0x003e, 0x004e, 0x005e, - 0x00ce, 0x00de, 0x00ee, 0x009e, 0x00be, 0x0005, 0x7804, 0x9086, - 0x0040, 0x0904, 0xa656, 0x9185, 0x0100, 0x6062, 0x6266, 0x636a, - 0x646e, 0x6073, 0x0809, 0x6077, 0x0008, 0x60af, 0x95d5, 0x60d7, - 0x0000, 0xb88c, 0x8000, 0x9084, 0x00ff, 0xb88e, 0x8007, 0x607a, - 0x607f, 0x0000, 0x2f00, 0x6082, 0x7808, 0x6086, 0x7814, 0x2048, - 0xa838, 0x608a, 0xa834, 0x608e, 0xa848, 0x60c6, 0xa844, 0x60ca, - 0xb86c, 0x60ce, 0xbac0, 0x629e, 0x080c, 0xaf73, 0x2009, 0x07d0, - 0x60c4, 0x9084, 0xfff0, 0x9005, 0x0110, 0x2009, 0x1b58, 0x080c, - 0x88c8, 0x003e, 0x004e, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x009e, - 0x00be, 0x0005, 0x7814, 0x2048, 0xa87c, 0x9084, 0x0003, 0x9086, - 0x0002, 0x0904, 0xa672, 0x9185, 0x0100, 0x6062, 0x6266, 0x636a, - 0x646e, 0x6073, 0x0880, 0x6077, 0x0008, 0xb88c, 0x8000, 0x9084, - 0x00ff, 0xb88e, 0x8007, 0x607a, 0x7838, 0x607e, 0x2f00, 0x6086, - 0x7808, 0x6082, 0xa890, 0x608a, 0xa88c, 0x608e, 0xa8b0, 0x60c6, - 0xa8ac, 0x60ca, 0xa8ac, 0x7930, 0x9108, 0x7932, 0xa8b0, 0x792c, - 0x9109, 0x792e, 0xb86c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, - 0xbac0, 0x629e, 0x080c, 0xaf50, 0x0804, 0xa606, 0xb8cc, 0xd084, - 0x0148, 0xb88c, 0x7814, 0x2048, 0xb88c, 0x784a, 0xa836, 0x2900, - 0xa83a, 0xb046, 0x9185, 0x0600, 0x6062, 0x6266, 0x636a, 0x646e, - 0x6073, 0x0829, 0x6077, 0x0000, 0x60af, 0x9575, 0x60d7, 0x0000, - 0x0804, 0xa5e9, 0x9185, 0x0700, 0x6062, 0x6266, 0x636a, 0x646e, - 0x7824, 0xd0cc, 0x7826, 0x0118, 0x6073, 0x0889, 0x0010, 0x6073, - 0x0898, 0x6077, 0x0000, 0xb88c, 0x8000, 0x9084, 0x00ff, 0xb88e, - 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6086, 0x7808, 0x6082, - 0xa838, 0x608a, 0xa834, 0x608e, 0xa848, 0x60c6, 0xa844, 0x60ca, - 0xb86c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, 0xbac0, 0x629e, - 0x7824, 0xd0cc, 0x0120, 0x080c, 0xaf73, 0x0804, 0xa606, 0x080c, - 0xaf50, 0x0804, 0xa606, 0x7a10, 0x00b6, 0x2258, 0xba8c, 0x8210, - 0x9294, 0x00ff, 0xba8e, 0x00be, 0x8217, 0x0005, 0x00d6, 0x2069, - 0x19e8, 0x6843, 0x0001, 0x00de, 0x0005, 0x60a3, 0x0056, 0x60a7, - 0x9575, 0x00f1, 0x080c, 0x88ba, 0x0005, 0x0016, 0x2001, 0x180c, - 0x200c, 0x9184, 0x0600, 0x9086, 0x0600, 0x0128, 0x0089, 0x080c, - 0x88ba, 0x001e, 0x0005, 0xc1e5, 0x2001, 0x180c, 0x2102, 0x2001, - 0x19e9, 0x2003, 0x0000, 0x2001, 0x19f1, 0x2003, 0x0000, 0x0c88, - 0x0006, 0x6014, 0x9084, 0x1804, 0x9085, 0x0009, 0x6016, 0x000e, - 0x0005, 0x0016, 0x00c6, 0x0006, 0x2061, 0x0100, 0x61a4, 0x60a7, - 0x95f5, 0x6014, 0x9084, 0x1804, 0x9085, 0x0008, 0x6016, 0x000e, - 0xa001, 0xa001, 0xa001, 0x61a6, 0x00ce, 0x001e, 0x0005, 0x00c6, - 0x00d6, 0x0016, 0x0026, 0x2061, 0x0100, 0x2069, 0x0140, 0x080c, - 0x7637, 0x11c0, 0x2001, 0x1a04, 0x2004, 0x9005, 0x15d0, 0x080c, - 0x76e4, 0x1160, 0x2061, 0x0100, 0x6020, 0xd0b4, 0x1120, 0x6024, - 0xd084, 0x090c, 0x0dc5, 0x080c, 0x88ba, 0x0458, 0x00c6, 0x2061, - 0x19e8, 0x00c8, 0x6904, 0x9194, 0x4000, 0x0540, 0x0811, 0x080c, - 0x2d49, 0x00c6, 0x2061, 0x19e8, 0x6128, 0x9192, 0x0008, 0x1258, - 0x8108, 0x612a, 0x6124, 0x00ce, 0x81ff, 0x0198, 0x080c, 0x88ba, - 0x080c, 0xa6e0, 0x0070, 0x6124, 0x91e5, 0x0000, 0x0140, 0x080c, - 0xf094, 0x080c, 0x88c3, 0x2009, 0x0014, 0x080c, 0xb352, 0x00ce, - 0x0000, 0x002e, 0x001e, 0x00de, 0x00ce, 0x0005, 0x2001, 0x1a04, - 0x2004, 0x9005, 0x1db0, 0x00c6, 0x2061, 0x19e8, 0x6128, 0x9192, - 0x0003, 0x1e08, 0x8108, 0x612a, 0x00ce, 0x080c, 0x88ba, 0x080c, - 0x5fed, 0x2009, 0x1846, 0x2114, 0x8210, 0x220a, 0x0c10, 0x0096, - 0x00c6, 0x00d6, 0x00e6, 0x0016, 0x0026, 0x080c, 0x88d0, 0x2071, - 0x19e8, 0x713c, 0x81ff, 0x0904, 0xa7e9, 0x2061, 0x0100, 0x2069, - 0x0140, 0x080c, 0x7637, 0x11e0, 0x0036, 0x2019, 0x0002, 0x080c, - 0xaa49, 0x003e, 0x713c, 0x2160, 0x080c, 0xf094, 0x2009, 0x004a, - 0x6220, 0x9296, 0x0009, 0x1130, 0x6114, 0x2148, 0xa87b, 0x0006, - 0x2009, 0x004a, 0x080c, 0xb352, 0x080c, 0x76e4, 0x0804, 0xa7e9, - 0x080c, 0xa7f5, 0x0904, 0xa7e9, 0x6904, 0xd1f4, 0x0904, 0xa7f0, - 0x080c, 0x2d49, 0x00c6, 0x703c, 0x9065, 0x090c, 0x0dc5, 0x6020, - 0x00ce, 0x9086, 0x0006, 0x1528, 0x61c8, 0x60c4, 0x9105, 0x1508, - 0x2009, 0x180c, 0x2104, 0xd0d4, 0x01e0, 0x6214, 0x9294, 0x1800, - 0x1128, 0x6224, 0x9294, 0x0002, 0x1560, 0x0030, 0xc0d4, 0x200a, - 0xd0cc, 0x0110, 0x080c, 0x2c7b, 0x6014, 0x9084, 0xe7fd, 0x9085, - 0x0010, 0x6016, 0x703c, 0x2060, 0x2009, 0x0049, 0x080c, 0xb352, - 0x00c0, 0x0036, 0x2019, 0x0001, 0x080c, 0xaa49, 0x003e, 0x713c, - 0x2160, 0x080c, 0xf094, 0x2009, 0x004a, 0x6220, 0x9296, 0x0009, - 0x1130, 0x6114, 0x2148, 0xa87b, 0x0006, 0x2009, 0x004a, 0x080c, - 0xb352, 0x002e, 0x001e, 0x00ee, 0x00de, 0x00ce, 0x009e, 0x0005, - 0xd1ec, 0x1904, 0xa7a0, 0x0804, 0xa7a2, 0x00d6, 0x00c6, 0x0096, - 0x703c, 0x9065, 0x090c, 0x0dc5, 0x2001, 0x0306, 0x200c, 0x9184, - 0x0030, 0x0904, 0xa8a8, 0x9184, 0x0048, 0x9086, 0x0008, 0x1904, - 0xa8a8, 0x2009, 0x0206, 0x2104, 0x2009, 0x0203, 0x210c, 0x9106, - 0x1904, 0xa8a8, 0x2009, 0x022a, 0x2104, 0x2009, 0x022f, 0x210c, - 0x9116, 0x9084, 0x03ff, 0x918c, 0x03ff, 0x9294, 0x0400, 0x0110, - 0x9102, 0x0030, 0x2010, 0x2100, 0x9202, 0x2009, 0x0228, 0x9102, - 0x9082, 0x0005, 0x0250, 0x2008, 0x2001, 0x013b, 0x2004, 0x8004, - 0x8004, 0x8004, 0x9102, 0x1a04, 0xa8a8, 0x2009, 0x1a84, 0x2104, - 0x8000, 0x0208, 0x200a, 0x2069, 0x0100, 0x6914, 0x918c, 0x1984, - 0x918d, 0x0010, 0x6916, 0x69c8, 0x2011, 0x0020, 0x68c8, 0x9106, - 0x15c0, 0x8211, 0x1dd8, 0x2001, 0x0306, 0x2003, 0x4800, 0x2001, - 0x009a, 0x2003, 0x0004, 0x2001, 0x1a69, 0x2003, 0x0000, 0x2001, - 0x1a72, 0x2003, 0x0000, 0x6a88, 0x698c, 0x2200, 0x9105, 0x1170, - 0x0096, 0x6014, 0x2048, 0xa87c, 0xc0dc, 0xa87e, 0xa880, 0xc0fc, - 0xa882, 0x009e, 0x2c10, 0x080c, 0x1be0, 0x0040, 0x6014, 0x2048, - 0xaa3a, 0xa936, 0x6ac4, 0x69c8, 0xa946, 0xaa4a, 0x0126, 0x00c6, - 0x2091, 0x2400, 0x002e, 0x080c, 0x1c79, 0x190c, 0x0dc5, 0x012e, - 0x0090, 0x2009, 0x1a85, 0x2104, 0x8000, 0x0208, 0x200a, 0x69c8, - 0x2011, 0x0020, 0x8211, 0x1df0, 0x68c8, 0x9106, 0x1dc0, 0x69c4, - 0x68c8, 0x9105, 0x0160, 0x6824, 0xd08c, 0x0110, 0x6827, 0x0002, - 0x7048, 0xc085, 0x704a, 0x0079, 0x7048, 0xc084, 0x704a, 0x2009, - 0x07d0, 0x080c, 0x88c8, 0x9006, 0x009e, 0x00ce, 0x00de, 0x0005, - 0x9085, 0x0001, 0x0cc8, 0x0026, 0x00e6, 0x2071, 0x19e8, 0x7048, - 0xd084, 0x01d8, 0x713c, 0x81ff, 0x01c0, 0x2071, 0x0100, 0x9188, - 0x0008, 0x2114, 0x928e, 0x0006, 0x1138, 0x7014, 0x9084, 0x1984, - 0x9085, 0x0012, 0x7016, 0x0048, 0x928e, 0x0009, 0x0db0, 0x7014, - 0x9084, 0x1984, 0x9085, 0x0016, 0x7016, 0x00ee, 0x002e, 0x0005, - 0x00b6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046, 0x0006, - 0x0126, 0x2091, 0x8000, 0x6010, 0x2058, 0xbca0, 0x2071, 0x19e8, - 0x7018, 0x2058, 0x8bff, 0x0190, 0xb8a0, 0x9406, 0x0118, 0xb854, - 0x2058, 0x0cc0, 0x6014, 0x0096, 0x2048, 0xac6c, 0xad70, 0xae78, - 0x009e, 0x080c, 0x6856, 0x0110, 0x9085, 0x0001, 0x012e, 0x000e, - 0x004e, 0x005e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00be, 0x0005, - 0x080c, 0xa0c1, 0x7003, 0x1200, 0x7838, 0x7012, 0x783c, 0x7016, - 0x00c6, 0x7820, 0x9086, 0x0004, 0x1148, 0x7810, 0x9005, 0x0130, - 0x00b6, 0x2058, 0xb810, 0xb914, 0x00be, 0x0020, 0x2061, 0x1800, - 0x607c, 0x6180, 0x9084, 0x00ff, 0x700a, 0x710e, 0x00ce, 0x60c3, - 0x002c, 0x0804, 0xa6bd, 0x080c, 0xa0c1, 0x7003, 0x0f00, 0x7808, - 0xd09c, 0x0128, 0xb810, 0x9084, 0x00ff, 0x700a, 0xb814, 0x700e, - 0x60c3, 0x0008, 0x0804, 0xa6bd, 0x0156, 0x080c, 0xa10c, 0x7003, - 0x0200, 0x080c, 0x894c, 0x20a9, 0x0006, 0x2011, 0xffec, 0x2019, - 0xffed, 0x9ef0, 0x0002, 0x2305, 0x2072, 0x8e70, 0x2205, 0x2072, - 0x8e70, 0x9398, 0x0002, 0x9290, 0x0002, 0x1f04, 0xa943, 0x60c3, - 0x001c, 0x015e, 0x0804, 0xa6bd, 0x0016, 0x0026, 0x080c, 0xa0e8, - 0x080c, 0xa0fa, 0x9e80, 0x0004, 0x20e9, 0x0000, 0x20a0, 0x7814, - 0x0096, 0x2048, 0xa800, 0x2048, 0xa860, 0x20e0, 0xa85c, 0x9080, - 0x0021, 0x2098, 0x009e, 0x7808, 0x9088, 0x0002, 0x21a8, 0x9192, - 0x0010, 0x1250, 0x4003, 0x9080, 0x0004, 0x8003, 0x60c2, 0x080c, - 0xa6bd, 0x002e, 0x001e, 0x0005, 0x20a9, 0x0010, 0x4003, 0x080c, - 0xaf79, 0x20a1, 0x0240, 0x22a8, 0x4003, 0x0c68, 0x080c, 0xa0c1, - 0x7003, 0x6200, 0x7808, 0x700e, 0x60c3, 0x0008, 0x0804, 0xa6bd, - 0x0016, 0x0026, 0x080c, 0xa0c1, 0x20e9, 0x0000, 0x20a1, 0x024c, - 0x7814, 0x0096, 0x2048, 0xa800, 0x2048, 0xa860, 0x20e0, 0xa85c, - 0x9080, 0x0023, 0x2098, 0x009e, 0x7808, 0x9088, 0x0002, 0x21a8, - 0x4003, 0x8003, 0x60c2, 0x080c, 0xa6bd, 0x002e, 0x001e, 0x0005, - 0x00e6, 0x00c6, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x19e8, - 0x700c, 0x2060, 0x8cff, 0x0178, 0x080c, 0xd2e0, 0x1110, 0x080c, - 0xbcb6, 0x600c, 0x0006, 0x080c, 0xd54c, 0x080c, 0xb2d3, 0x080c, - 0xaaf1, 0x00ce, 0x0c78, 0x2c00, 0x700e, 0x700a, 0x012e, 0x000e, - 0x00ce, 0x00ee, 0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6, - 0x00c6, 0x0066, 0x0026, 0x0016, 0x0006, 0x2091, 0x8000, 0x2001, - 0x180c, 0x200c, 0x918c, 0xe7ff, 0x2102, 0x2069, 0x0100, 0x2079, - 0x0140, 0x2071, 0x19e8, 0x7024, 0x2060, 0x8cff, 0x01f8, 0x080c, - 0xa6e9, 0x6ac0, 0x68c3, 0x0000, 0x080c, 0x88c3, 0x00c6, 0x2061, - 0x0100, 0x080c, 0xb0ca, 0x00ce, 0x20a9, 0x01f4, 0x0461, 0x2009, - 0x0013, 0x080c, 0xb352, 0x000e, 0x001e, 0x002e, 0x006e, 0x00ce, - 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x2001, 0x1800, - 0x2004, 0x9096, 0x0001, 0x0d78, 0x9096, 0x0004, 0x0d60, 0x080c, - 0x88c3, 0x6814, 0x9084, 0x0001, 0x0110, 0x68a7, 0x95f5, 0x6817, - 0x0008, 0x68c3, 0x0000, 0x2011, 0x5f97, 0x080c, 0x883d, 0x20a9, - 0x01f4, 0x0009, 0x08c0, 0x6824, 0xd094, 0x0140, 0x6827, 0x0004, - 0x7804, 0x9084, 0x4000, 0x190c, 0x2d49, 0x0090, 0xd084, 0x0118, - 0x6827, 0x4001, 0x0010, 0x1f04, 0xaa2b, 0x7804, 0x9084, 0x1000, - 0x0138, 0x2001, 0x0100, 0x080c, 0x2d39, 0x9006, 0x080c, 0x2d39, - 0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, - 0x0026, 0x0016, 0x0006, 0x2091, 0x8000, 0x2001, 0x180c, 0x200c, - 0x918c, 0xdbff, 0x2102, 0x2069, 0x0100, 0x2079, 0x0140, 0x2071, - 0x19e8, 0x703c, 0x2060, 0x8cff, 0x0904, 0xaab4, 0x9386, 0x0002, - 0x1128, 0x6814, 0x9084, 0x0002, 0x0904, 0xaab4, 0x68af, 0x95f5, - 0x6817, 0x0010, 0x2009, 0x00fa, 0x8109, 0x1df0, 0x69c6, 0x68cb, - 0x0008, 0x080c, 0x88d0, 0x080c, 0x2031, 0x2001, 0x0032, 0x6920, - 0xd1bc, 0x0130, 0x8001, 0x1dd8, 0x692c, 0x918d, 0x0008, 0x692e, - 0x20a9, 0x03e8, 0x6824, 0xd094, 0x0140, 0x6827, 0x0004, 0x7804, - 0x9084, 0x4000, 0x190c, 0x2d49, 0x0090, 0xd08c, 0x0118, 0x6827, - 0x0002, 0x0010, 0x1f04, 0xaa8a, 0x7804, 0x9084, 0x1000, 0x0138, - 0x2001, 0x0100, 0x080c, 0x2d39, 0x9006, 0x080c, 0x2d39, 0x6827, - 0x4000, 0x6824, 0x83ff, 0x1140, 0x2009, 0x0049, 0x6020, 0x9086, - 0x0009, 0x0110, 0x080c, 0xb352, 0x000e, 0x001e, 0x002e, 0x006e, - 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x00d6, - 0x0126, 0x2091, 0x8000, 0x2069, 0x19e8, 0x6a06, 0x012e, 0x00de, - 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x2069, 0x19e8, 0x6a32, - 0x012e, 0x00de, 0x0005, 0x080c, 0xa284, 0x7047, 0x1000, 0x0098, - 0x080c, 0xa284, 0x7047, 0x4000, 0x0070, 0x080c, 0xa284, 0x7047, - 0x2000, 0x0048, 0x080c, 0xa284, 0x7047, 0x0400, 0x0020, 0x080c, - 0xa284, 0x7047, 0x0200, 0x7854, 0x7032, 0x60c3, 0x0020, 0x0804, - 0xa6bd, 0x00e6, 0x2071, 0x19e8, 0x7020, 0x9005, 0x0110, 0x8001, - 0x7022, 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0076, - 0x0066, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x19e8, 0x7614, - 0x2660, 0x2678, 0x2039, 0x0001, 0x87ff, 0x0904, 0xab96, 0x8cff, - 0x0904, 0xab96, 0x6020, 0x9086, 0x0006, 0x1904, 0xab91, 0x88ff, - 0x0138, 0x2800, 0x9c06, 0x1904, 0xab91, 0x2039, 0x0000, 0x0050, - 0x6010, 0x9b06, 0x1904, 0xab91, 0x85ff, 0x0120, 0x6054, 0x9106, - 0x1904, 0xab91, 0x7024, 0x9c06, 0x15b0, 0x2069, 0x0100, 0x68c0, - 0x9005, 0x1160, 0x6824, 0xd084, 0x0148, 0x6827, 0x0001, 0x080c, - 0x88c3, 0x080c, 0xac1b, 0x7027, 0x0000, 0x0428, 0x080c, 0x88c3, - 0x6820, 0xd0b4, 0x0110, 0x68a7, 0x95f5, 0x6817, 0x0008, 0x68c3, - 0x0000, 0x080c, 0xac1b, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, - 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2d39, - 0x9006, 0x080c, 0x2d39, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, - 0x6827, 0x0001, 0x003e, 0x7014, 0x9c36, 0x1110, 0x660c, 0x7616, - 0x7010, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x7012, - 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, - 0x7e0e, 0x0008, 0x2678, 0x89ff, 0x1168, 0x600f, 0x0000, 0x6014, - 0x0096, 0x2048, 0x080c, 0xd0d6, 0x0110, 0x080c, 0xebd4, 0x009e, - 0x080c, 0xb306, 0x080c, 0xaaf1, 0x88ff, 0x1190, 0x00ce, 0x0804, - 0xab0c, 0x2c78, 0x600c, 0x2060, 0x0804, 0xab0c, 0x9006, 0x012e, - 0x000e, 0x006e, 0x007e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, - 0x601b, 0x0000, 0x00ce, 0x98c5, 0x0001, 0x0c88, 0x00f6, 0x00e6, - 0x00d6, 0x0096, 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, 0x2091, - 0x8000, 0x2071, 0x19e8, 0x7638, 0x2660, 0x2678, 0x8cff, 0x0904, - 0xac0a, 0x6020, 0x9086, 0x0006, 0x1904, 0xac05, 0x87ff, 0x0128, - 0x2700, 0x9c06, 0x1904, 0xac05, 0x0040, 0x6010, 0x9b06, 0x15e8, - 0x85ff, 0x0118, 0x6054, 0x9106, 0x15c0, 0x703c, 0x9c06, 0x1168, - 0x0036, 0x2019, 0x0001, 0x080c, 0xaa49, 0x7033, 0x0000, 0x9006, - 0x703e, 0x7042, 0x7046, 0x704a, 0x003e, 0x7038, 0x9c36, 0x1110, - 0x660c, 0x763a, 0x7034, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, - 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, 0x660c, 0x0066, 0x2c00, - 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x6014, - 0x2048, 0x080c, 0xd0d6, 0x0110, 0x080c, 0xebd4, 0x080c, 0xb306, - 0x87ff, 0x1198, 0x00ce, 0x0804, 0xabb6, 0x2c78, 0x600c, 0x2060, - 0x0804, 0xabb6, 0x9006, 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, - 0x009e, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601b, 0x0000, 0x00ce, - 0x97bd, 0x0001, 0x0c80, 0x00e6, 0x2071, 0x19e8, 0x2001, 0x1800, - 0x2004, 0x9086, 0x0002, 0x1118, 0x7007, 0x0005, 0x0010, 0x7007, - 0x0000, 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0066, 0x0026, - 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x19e8, 0x2c10, 0x7638, - 0x2660, 0x2678, 0x8cff, 0x0540, 0x2200, 0x9c06, 0x1508, 0x7038, - 0x9c36, 0x1110, 0x660c, 0x763a, 0x7034, 0x9c36, 0x1140, 0x2c00, - 0x9f36, 0x0118, 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, 0x660c, - 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, - 0x6004, 0x9086, 0x0040, 0x090c, 0x99a5, 0x9085, 0x0001, 0x0020, - 0x2c78, 0x600c, 0x2060, 0x08b0, 0x012e, 0x000e, 0x002e, 0x006e, - 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x0096, 0x00f6, 0x00e6, 0x00d6, - 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, - 0x19e8, 0x760c, 0x2660, 0x2678, 0x8cff, 0x0904, 0xad01, 0x6010, - 0x00b6, 0x2058, 0xb8a0, 0x00be, 0x9206, 0x1904, 0xacfc, 0x7024, - 0x9c06, 0x1520, 0x2069, 0x0100, 0x68c0, 0x9005, 0x0904, 0xacd3, - 0x080c, 0xa6e9, 0x68c3, 0x0000, 0x080c, 0xac1b, 0x7027, 0x0000, - 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, - 0x0100, 0x080c, 0x2d39, 0x9006, 0x080c, 0x2d39, 0x2069, 0x0100, - 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x700c, 0x9c36, - 0x1110, 0x660c, 0x760e, 0x7008, 0x9c36, 0x1140, 0x2c00, 0x9f36, - 0x0118, 0x2f00, 0x700a, 0x0010, 0x700b, 0x0000, 0x660c, 0x0066, - 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, - 0x080c, 0xd2cf, 0x1180, 0x080c, 0x3279, 0x080c, 0xd2e0, 0x1518, - 0x080c, 0xbcb6, 0x0400, 0x080c, 0xac1b, 0x6824, 0xd084, 0x09b0, - 0x6827, 0x0001, 0x0898, 0x080c, 0xd2e0, 0x1118, 0x080c, 0xbcb6, - 0x0090, 0x6014, 0x2048, 0x080c, 0xd0d6, 0x0168, 0x6020, 0x9086, - 0x0003, 0x1508, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, - 0x6e92, 0x080c, 0xd2c3, 0x080c, 0xd54c, 0x080c, 0xb306, 0x080c, - 0xaaf1, 0x00ce, 0x0804, 0xac7c, 0x2c78, 0x600c, 0x2060, 0x0804, - 0xac7c, 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, 0x00de, 0x00ee, - 0x00fe, 0x009e, 0x0005, 0x6020, 0x9086, 0x0006, 0x1d20, 0x080c, - 0xebd4, 0x0c08, 0x00d6, 0x080c, 0xa10c, 0x7003, 0x0200, 0x7007, - 0x0014, 0x60c3, 0x0014, 0x20e1, 0x0001, 0x2099, 0x1989, 0x20e9, - 0x0000, 0x20a1, 0x0250, 0x20a9, 0x0004, 0x4003, 0x7023, 0x0004, - 0x7027, 0x7878, 0x080c, 0xa6bd, 0x00de, 0x0005, 0x080c, 0xa10c, - 0x700b, 0x0800, 0x7814, 0x9084, 0xff00, 0x700e, 0x7814, 0x9084, - 0x00ff, 0x7022, 0x782c, 0x7026, 0x7858, 0x9084, 0x00ff, 0x9085, - 0x0200, 0x7002, 0x7858, 0x9084, 0xff00, 0x8007, 0x7006, 0x60c2, - 0x0804, 0xa6bd, 0x00b6, 0x00d6, 0x0016, 0x00d6, 0x2f68, 0x2009, - 0x0035, 0x080c, 0xd759, 0x00de, 0x1904, 0xadaf, 0x080c, 0xa0c1, - 0x7003, 0x1300, 0x782c, 0x080c, 0xaeb5, 0x2068, 0x6820, 0x9086, - 0x0003, 0x0560, 0x7810, 0x2058, 0xbaa0, 0x080c, 0xb23d, 0x11d8, - 0x9286, 0x007e, 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffe, 0x0498, - 0x9286, 0x007f, 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffd, 0x0458, - 0x9284, 0xff80, 0x0180, 0x9286, 0x0080, 0x1128, 0x700b, 0x00ff, - 0x700f, 0xfffc, 0x0400, 0x92d8, 0x1000, 0x2b5c, 0xb810, 0x700a, - 0xb814, 0x700e, 0x00c0, 0x6098, 0x700e, 0x00a8, 0x080c, 0xb23d, - 0x1130, 0x7810, 0x2058, 0xb8a0, 0x9082, 0x007e, 0x0250, 0x00d6, - 0x2069, 0x181f, 0x2d04, 0x700a, 0x8d68, 0x2d04, 0x700e, 0x00de, - 0x0010, 0x6034, 0x700e, 0x7838, 0x7012, 0x783c, 0x7016, 0x60c3, - 0x000c, 0x001e, 0x00de, 0x080c, 0xa6bd, 0x00be, 0x0005, 0x781b, - 0x0001, 0x7803, 0x0006, 0x001e, 0x00de, 0x00be, 0x0005, 0x792c, - 0x9180, 0x0008, 0x200c, 0x9186, 0x0006, 0x01c0, 0x9186, 0x0003, - 0x0904, 0xae2a, 0x9186, 0x0005, 0x0904, 0xae12, 0x9186, 0x0004, - 0x05d8, 0x9186, 0x0008, 0x0904, 0xae1b, 0x7807, 0x0037, 0x782f, - 0x0003, 0x7817, 0x1700, 0x080c, 0xae92, 0x0005, 0x080c, 0xae53, - 0x00d6, 0x0026, 0x792c, 0x2168, 0x2009, 0x4000, 0x6800, 0x0002, - 0xadf3, 0xadfe, 0xadf5, 0xadfe, 0xadfa, 0xadf3, 0xadf3, 0xadfe, - 0xadfe, 0xadfe, 0xadfe, 0xadf3, 0xadf3, 0xadf3, 0xadf3, 0xadf3, - 0xadfe, 0xadf3, 0xadfe, 0x080c, 0x0dc5, 0x6824, 0xd0e4, 0x0110, - 0xd0cc, 0x0110, 0x900e, 0x0010, 0x2009, 0x2000, 0x682c, 0x7022, - 0x6830, 0x7026, 0x0804, 0xae4c, 0x080c, 0xae53, 0x00d6, 0x0026, - 0x792c, 0x2168, 0x2009, 0x4000, 0x6a00, 0x9286, 0x0002, 0x1108, - 0x900e, 0x04d0, 0x080c, 0xae53, 0x00d6, 0x0026, 0x792c, 0x2168, - 0x2009, 0x4000, 0x0488, 0x04b9, 0x00d6, 0x0026, 0x792c, 0x2168, - 0x2009, 0x4000, 0x9286, 0x0005, 0x0118, 0x9286, 0x0002, 0x1108, - 0x900e, 0x0410, 0x0441, 0x00d6, 0x0026, 0x792c, 0x2168, 0x6814, - 0x6924, 0xc185, 0x6926, 0x0096, 0x2048, 0xa9ac, 0xa834, 0x9112, - 0xa9b0, 0xa838, 0x009e, 0x9103, 0x7022, 0x7226, 0x792c, 0x9180, - 0x0000, 0x2004, 0x908e, 0x0002, 0x0130, 0x908e, 0x0004, 0x0118, - 0x2009, 0x4000, 0x0008, 0x900e, 0x712a, 0x60c3, 0x0018, 0x002e, - 0x00de, 0x0804, 0xa6bd, 0x00b6, 0x0036, 0x0046, 0x0056, 0x0066, - 0x080c, 0xa10c, 0x9006, 0x7003, 0x0200, 0x7938, 0x710a, 0x793c, - 0x710e, 0x7810, 0x2058, 0xb8a0, 0x080c, 0xb23d, 0x1118, 0x9092, - 0x007e, 0x0268, 0x00d6, 0x2069, 0x181f, 0x2d2c, 0x8d68, 0x2d34, - 0x90d8, 0x1000, 0x2b5c, 0xbb10, 0xbc14, 0x00de, 0x0028, 0x901e, - 0x6498, 0x2029, 0x0000, 0x6634, 0x782c, 0x9080, 0x0008, 0x2004, - 0x9086, 0x0003, 0x1128, 0x7512, 0x7616, 0x731a, 0x741e, 0x0020, - 0x7312, 0x7416, 0x751a, 0x761e, 0x006e, 0x005e, 0x004e, 0x003e, - 0x00be, 0x0005, 0x080c, 0xa10c, 0x7003, 0x0100, 0x782c, 0x700a, - 0x7814, 0x700e, 0x700e, 0x60c3, 0x0008, 0x0804, 0xa6bd, 0x080c, - 0xa0b8, 0x7003, 0x1400, 0x7838, 0x700a, 0x0079, 0x783c, 0x700e, - 0x782c, 0x7012, 0x7830, 0x7016, 0x7834, 0x9084, 0x00ff, 0x8007, - 0x701a, 0x60c3, 0x0010, 0x0804, 0xa6bd, 0x00e6, 0x2071, 0x0240, - 0x0006, 0x00f6, 0x2078, 0x7810, 0x00b6, 0x2058, 0xb8cc, 0xd084, - 0x0120, 0x7844, 0x702a, 0x7848, 0x702e, 0x00be, 0x00fe, 0x000e, - 0x00ee, 0x0005, 0x080c, 0xa103, 0x7003, 0x0100, 0x782c, 0x700a, - 0x7814, 0x700e, 0x60c3, 0x0008, 0x0804, 0xa6bd, 0x0021, 0x60c3, - 0x0000, 0x0804, 0xa6bd, 0x00d6, 0x080c, 0xaf8e, 0xb810, 0x9085, - 0x0300, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, 0x687c, 0x700a, - 0x6880, 0x700e, 0x7013, 0x0819, 0x080c, 0xa6ab, 0x721a, 0x2f10, - 0x7222, 0x7a08, 0x7226, 0x2071, 0x024c, 0x00de, 0x0005, 0x00a9, - 0x7914, 0x712a, 0x60c3, 0x0000, 0x60a7, 0x9575, 0x0026, 0x080c, - 0x2bce, 0x0228, 0x2011, 0x0101, 0x2204, 0xc0c5, 0x2012, 0x002e, - 0x080c, 0xa6e0, 0x080c, 0x88ba, 0x0005, 0x0036, 0x0096, 0x00d6, - 0x00e6, 0x7858, 0x2048, 0xaa7c, 0x9296, 0x00c0, 0x9294, 0x00fd, - 0xaa7e, 0xaa80, 0x9294, 0x0300, 0xaa82, 0xa96c, 0x9194, 0x00ff, - 0xab74, 0x9384, 0x00ff, 0x908d, 0xc200, 0xa96e, 0x9384, 0xff00, - 0x9215, 0xaa76, 0xa870, 0xaa78, 0xa87a, 0xaa72, 0x00d6, 0x2069, - 0x0200, 0x080c, 0xaf8e, 0x00de, 0x20e9, 0x0000, 0x20a1, 0x0240, - 0x20a9, 0x000a, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x001b, 0x2098, - 0x4003, 0x60a3, 0x0035, 0xaa68, 0x9294, 0x7000, 0x9286, 0x3000, - 0x0110, 0x60a3, 0x0037, 0x00ee, 0x00de, 0x009e, 0x003e, 0x0005, - 0x900e, 0x7814, 0x0096, 0x2048, 0xa87c, 0xd0fc, 0x01c0, 0x9084, - 0x0003, 0x11a8, 0x2001, 0x180c, 0x2004, 0xd0bc, 0x0180, 0x7824, - 0xd0cc, 0x1168, 0xd0c4, 0x1158, 0xa8a8, 0x9005, 0x1140, 0x2001, - 0x180c, 0x200c, 0xc1d5, 0x2102, 0x2009, 0x19b3, 0x210c, 0x009e, - 0x918d, 0x0092, 0x0010, 0x2009, 0x0096, 0x60ab, 0x0036, 0x6116, - 0x0005, 0x2009, 0x0009, 0x00a0, 0x2009, 0x000a, 0x0088, 0x2009, - 0x000b, 0x0070, 0x2009, 0x000c, 0x0058, 0x2009, 0x000d, 0x0040, - 0x2009, 0x000e, 0x0028, 0x2009, 0x000f, 0x0010, 0x2009, 0x0008, - 0x6912, 0x0005, 0x080c, 0xa0c1, 0x0016, 0x0026, 0x0096, 0x00d6, - 0x7814, 0x2048, 0x7013, 0x0138, 0x2001, 0x1837, 0x2004, 0x9084, - 0x0028, 0x1138, 0x2001, 0x197c, 0x2004, 0x9086, 0xaaaa, 0x1904, - 0xb033, 0x7003, 0x5400, 0x00c6, 0x2061, 0x1800, 0x607c, 0x9084, - 0x00ff, 0xa998, 0x810f, 0x918c, 0xff00, 0x9105, 0x700a, 0x6080, - 0x700e, 0xa998, 0x918c, 0xff00, 0x7112, 0x20a9, 0x0004, 0x2009, - 0x1805, 0x2e10, 0x9290, 0x0006, 0x2104, 0x2012, 0x8108, 0x8210, - 0x1f04, 0xafc4, 0x20a9, 0x0004, 0x2009, 0x1801, 0x2104, 0x2012, - 0x8108, 0x8210, 0x1f04, 0xafce, 0xa860, 0x20e0, 0xa85c, 0x9080, - 0x0029, 0x2098, 0x2009, 0x0006, 0x20a9, 0x0001, 0x4002, 0x8007, - 0x2012, 0x8210, 0x8109, 0x1dc0, 0x00d6, 0x2069, 0x0200, 0x080c, - 0xaf79, 0x00de, 0x2071, 0x0240, 0x2011, 0x0240, 0x2009, 0x0002, - 0x20a9, 0x0001, 0x4002, 0x8007, 0x2012, 0x8210, 0x8109, 0x1dc0, - 0x2009, 0x0008, 0x20a9, 0x0001, 0x4002, 0x8007, 0x2012, 0x8210, - 0x8109, 0x1dc0, 0xa85c, 0x9080, 0x0031, 0x2098, 0x2009, 0x0008, - 0x20a9, 0x0001, 0x4002, 0x8007, 0x2012, 0x8210, 0x8109, 0x1dc0, - 0x00ce, 0x60c3, 0x004c, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x2001, - 0x1837, 0x2004, 0x9084, 0x0028, 0x1168, 0x080c, 0x7637, 0x0150, - 0x6028, 0xc0bd, 0x602a, 0x6014, 0x9084, 0x1804, 0x9085, 0x0029, - 0x6016, 0x0010, 0x080c, 0xa6bd, 0x080c, 0x88ba, 0x00de, 0x009e, - 0x002e, 0x001e, 0x0005, 0x00e6, 0x2071, 0x0240, 0x2001, 0x2200, - 0x9085, 0x00ff, 0x7002, 0x7007, 0xffff, 0x2071, 0x0100, 0x709b, - 0x00ff, 0x00ee, 0x0804, 0xafa9, 0x080c, 0xa0c1, 0x0016, 0x0026, - 0x0096, 0x00d6, 0x7814, 0x2048, 0x7013, 0x0138, 0x7003, 0x5500, - 0x00c6, 0xa89c, 0x9084, 0x00ff, 0xa998, 0x810f, 0x918c, 0xff00, - 0x9105, 0x700a, 0xa99c, 0x918c, 0xff00, 0xa8a0, 0x9084, 0x00ff, - 0x9105, 0x700e, 0xa998, 0x918c, 0xff00, 0x2061, 0x1800, 0x607c, - 0x9084, 0x00ff, 0x910d, 0x7112, 0x6180, 0x7116, 0x2009, 0x0008, - 0xa860, 0x20e0, 0xa85c, 0x9080, 0x0029, 0x2098, 0x2e10, 0x9290, - 0x0006, 0x20a9, 0x0001, 0x4002, 0x8007, 0x2012, 0x8210, 0x8109, - 0x1dc0, 0x20a9, 0x0004, 0x2009, 0x1805, 0x2104, 0x2012, 0x8108, - 0x8210, 0x1f04, 0xb085, 0x20a9, 0x0002, 0x2009, 0x1801, 0x2104, - 0x2012, 0x8108, 0x8210, 0x1f04, 0xb08f, 0x00d6, 0x0016, 0x2069, - 0x0200, 0x080c, 0xaf79, 0x001e, 0x00de, 0x2071, 0x0240, 0x20a9, - 0x0002, 0x2009, 0x1803, 0x2011, 0x0240, 0x2104, 0x2012, 0x8108, - 0x8210, 0x1f04, 0xb0a5, 0x2009, 0x0008, 0x4002, 0x8007, 0x2012, - 0x8210, 0x8109, 0x1dd0, 0x9006, 0x20a9, 0x0008, 0x2012, 0x8210, - 0x1f04, 0xb0b6, 0x00ce, 0x60c3, 0x004c, 0x60a3, 0x0056, 0x60a7, - 0x9575, 0x080c, 0xa6bd, 0x080c, 0x88ba, 0x00de, 0x009e, 0x002e, - 0x001e, 0x0005, 0x00d6, 0x9290, 0x0018, 0x8214, 0x20e9, 0x0000, - 0x2069, 0x0200, 0x6813, 0x0000, 0x22a8, 0x9284, 0x00e0, 0x0128, - 0x20a9, 0x0020, 0x9292, 0x0020, 0x0008, 0x9016, 0x20a1, 0x0240, - 0x9006, 0x4004, 0x82ff, 0x0120, 0x6810, 0x8000, 0x6812, 0x0c60, - 0x00de, 0x0005, 0x00d6, 0x0096, 0x6014, 0x2048, 0xa878, 0x6056, - 0x9006, 0xa836, 0xa83a, 0xa99c, 0xa946, 0xa84a, 0x6023, 0x0003, - 0x6007, 0x0040, 0x6003, 0x0003, 0x600b, 0xffff, 0xa817, 0x0001, - 0xa842, 0xa83e, 0x2900, 0xa85a, 0xa813, 0x20c5, 0x080c, 0x9564, - 0x0126, 0x2091, 0x8000, 0x080c, 0x9bd3, 0x012e, 0x009e, 0x00de, - 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x00a6, 0x0096, 0x0066, - 0x0126, 0x2091, 0x8000, 0x2071, 0x19e8, 0x760c, 0x2660, 0x2678, - 0x8cff, 0x0904, 0xb19d, 0x7024, 0x9c06, 0x1520, 0x2069, 0x0100, - 0x68c0, 0x9005, 0x0904, 0xb16f, 0x080c, 0xa6e9, 0x68c3, 0x0000, - 0x080c, 0xac1b, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, - 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2d39, 0x9006, - 0x080c, 0x2d39, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, - 0x0001, 0x003e, 0x700c, 0x9c36, 0x1110, 0x660c, 0x760e, 0x7008, - 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x700a, 0x0010, - 0x700b, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, - 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, 0xd2cf, 0x1180, 0x080c, - 0x3279, 0x080c, 0xd2e0, 0x1518, 0x080c, 0xbcb6, 0x0400, 0x080c, - 0xac1b, 0x6824, 0xd084, 0x09b0, 0x6827, 0x0001, 0x0898, 0x080c, - 0xd2e0, 0x1118, 0x080c, 0xbcb6, 0x0090, 0x6014, 0x2048, 0x080c, - 0xd0d6, 0x0168, 0x6020, 0x9086, 0x0003, 0x1520, 0xa867, 0x0103, - 0xab7a, 0xa877, 0x0000, 0x080c, 0x6e9f, 0x080c, 0xd2c3, 0x080c, - 0xd54c, 0x080c, 0xb306, 0x080c, 0xaaf1, 0x00ce, 0x0804, 0xb120, - 0x2c78, 0x600c, 0x2060, 0x0804, 0xb120, 0x700f, 0x0000, 0x700b, - 0x0000, 0x012e, 0x006e, 0x009e, 0x00ae, 0x00ce, 0x00de, 0x00ee, - 0x00fe, 0x0005, 0x6020, 0x9086, 0x0006, 0x1d08, 0x080c, 0xebd4, - 0x08f0, 0x00d6, 0x0156, 0x080c, 0xa10c, 0x7a14, 0x82ff, 0x0138, - 0x7003, 0x0100, 0x700b, 0x0003, 0x60c3, 0x0008, 0x0490, 0x7003, - 0x0200, 0x7007, 0x0000, 0x2069, 0x1800, 0x901e, 0x6800, 0x9086, - 0x0004, 0x1110, 0xc38d, 0x0060, 0x080c, 0x7637, 0x1110, 0xc3ad, - 0x0008, 0xc3a5, 0x6adc, 0xd29c, 0x1110, 0xd2ac, 0x0108, 0xc39d, - 0x730e, 0x080c, 0x894c, 0x20a9, 0x0006, 0x2011, 0xffec, 0x2019, - 0xffed, 0x2071, 0x0250, 0x2305, 0x2072, 0x8e70, 0x2205, 0x2072, - 0x8e70, 0x9398, 0x0002, 0x9290, 0x0002, 0x1f04, 0xb1e3, 0x60c3, - 0x0020, 0x080c, 0xa6bd, 0x015e, 0x00de, 0x0005, 0x0156, 0x080c, - 0xa10c, 0x7a14, 0x82ff, 0x0168, 0x9286, 0xffff, 0x0118, 0x9282, - 0x000e, 0x1238, 0x7003, 0x0100, 0x700b, 0x0003, 0x60c3, 0x0008, - 0x0488, 0x7003, 0x0200, 0x7007, 0x001c, 0x700f, 0x0001, 0x2011, - 0x19be, 0x2204, 0x8007, 0x701a, 0x8210, 0x2204, 0x8007, 0x701e, - 0x0421, 0x1120, 0xb8a0, 0x9082, 0x007f, 0x0248, 0x2001, 0x181f, - 0x2004, 0x7022, 0x2001, 0x1820, 0x2004, 0x7026, 0x0030, 0x2001, - 0x1818, 0x2004, 0x9084, 0x00ff, 0x7026, 0x20a9, 0x0004, 0x20e1, - 0x0001, 0x2099, 0x1805, 0x20e9, 0x0000, 0x20a1, 0x0256, 0x4003, - 0x60c3, 0x001c, 0x015e, 0x0804, 0xa6bd, 0x0006, 0x2001, 0x1837, - 0x2004, 0xd0ac, 0x000e, 0x0005, 0x2011, 0x0003, 0x080c, 0xaabf, - 0x2011, 0x0002, 0x080c, 0xaac9, 0x080c, 0xa9d3, 0x0036, 0x901e, - 0x080c, 0xaa49, 0x003e, 0x0005, 0x080c, 0x33af, 0x0188, 0x0016, - 0x00b6, 0x00c6, 0x7010, 0x9085, 0x0020, 0x7012, 0x2009, 0x007e, - 0x080c, 0x6724, 0xb85c, 0xc0ac, 0xb85e, 0x00ce, 0x00be, 0x001e, - 0x0005, 0x2071, 0x188d, 0x7000, 0x9005, 0x0140, 0x2001, 0x0976, - 0x2071, 0x1800, 0x7076, 0x707a, 0x706b, 0xffe0, 0x2071, 0x1800, - 0x7074, 0x7056, 0x705b, 0x1cd0, 0x0005, 0x00e6, 0x0126, 0x2071, - 0x1800, 0x2091, 0x8000, 0x7554, 0x9582, 0x0010, 0x0608, 0x7058, - 0x2060, 0x6000, 0x9086, 0x0000, 0x0148, 0x9ce0, 0x0018, 0x7068, - 0x9c02, 0x1208, 0x0cb0, 0x2061, 0x1cd0, 0x0c98, 0x6003, 0x0008, - 0x8529, 0x7556, 0x9ca8, 0x0018, 0x7068, 0x9502, 0x1230, 0x755a, - 0x9085, 0x0001, 0x012e, 0x00ee, 0x0005, 0x705b, 0x1cd0, 0x0cc0, - 0x9006, 0x0cc0, 0x00e6, 0x2071, 0x1800, 0x7554, 0x9582, 0x0010, - 0x0600, 0x7058, 0x2060, 0x6000, 0x9086, 0x0000, 0x0148, 0x9ce0, - 0x0018, 0x7068, 0x9c02, 0x1208, 0x0cb0, 0x2061, 0x1cd0, 0x0c98, - 0x6003, 0x0008, 0x8529, 0x7556, 0x9ca8, 0x0018, 0x7068, 0x9502, - 0x1228, 0x755a, 0x9085, 0x0001, 0x00ee, 0x0005, 0x705b, 0x1cd0, - 0x0cc8, 0x9006, 0x0cc8, 0x9c82, 0x1cd0, 0x0a0c, 0x0dc5, 0x2001, - 0x181a, 0x2004, 0x9c02, 0x1a0c, 0x0dc5, 0x9006, 0x6006, 0x600a, - 0x600e, 0x6016, 0x601a, 0x6012, 0x6023, 0x0000, 0x6003, 0x0000, - 0x601e, 0x6056, 0x605a, 0x6026, 0x602a, 0x602e, 0x6032, 0x6036, - 0x603a, 0x603e, 0x6042, 0x602a, 0x2061, 0x1800, 0x6054, 0x8000, - 0x6056, 0x9086, 0x0001, 0x0108, 0x0005, 0x0126, 0x2091, 0x8000, - 0x0016, 0x080c, 0x9ab1, 0x001e, 0x012e, 0x0cb0, 0x0006, 0x6000, - 0x9086, 0x0000, 0x01c0, 0x601c, 0xd084, 0x190c, 0x1a8e, 0x6017, - 0x0000, 0x6023, 0x0007, 0x2001, 0x1986, 0x2004, 0x0006, 0x9082, - 0x0051, 0x000e, 0x0208, 0x8004, 0x601a, 0x080c, 0xee87, 0x6043, - 0x0000, 0x6013, 0x0000, 0x000e, 0x0005, 0x00e6, 0x0126, 0x2071, - 0x1800, 0x2091, 0x8000, 0x7554, 0x9582, 0x0001, 0x0608, 0x7058, - 0x2060, 0x6000, 0x9086, 0x0000, 0x0148, 0x9ce0, 0x0018, 0x7068, - 0x9c02, 0x1208, 0x0cb0, 0x2061, 0x1cd0, 0x0c98, 0x6003, 0x0008, - 0x8529, 0x7556, 0x9ca8, 0x0018, 0x7068, 0x9502, 0x1230, 0x755a, - 0x9085, 0x0001, 0x012e, 0x00ee, 0x0005, 0x705b, 0x1cd0, 0x0cc0, - 0x9006, 0x0cc0, 0x6020, 0x9084, 0x000f, 0x0002, 0xb365, 0xb36e, - 0xb389, 0xb3a4, 0xd82b, 0xd848, 0xd863, 0xb365, 0xb36e, 0x9100, - 0xb3bd, 0xb365, 0xb365, 0xb365, 0xb365, 0x9186, 0x0013, 0x1128, - 0x080c, 0x99a5, 0x080c, 0x9ab1, 0x0005, 0x0005, 0x0066, 0x6000, - 0x90b2, 0x0010, 0x1a0c, 0x0dc5, 0x0013, 0x006e, 0x0005, 0xb387, - 0xbb05, 0xbcfd, 0xb387, 0xbd93, 0xb6a0, 0xb387, 0xb387, 0xba87, - 0xc3b1, 0xb387, 0xb387, 0xb387, 0xb387, 0xb387, 0xb387, 0x080c, - 0x0dc5, 0x0066, 0x6000, 0x90b2, 0x0010, 0x1a0c, 0x0dc5, 0x0013, - 0x006e, 0x0005, 0xb3a2, 0xca7e, 0xb3a2, 0xb3a2, 0xb3a2, 0xb3a2, - 0xb3a2, 0xb3a2, 0xca15, 0xcc00, 0xb3a2, 0xcabf, 0xcb3e, 0xcabf, - 0xcb3e, 0xb3a2, 0x080c, 0x0dc5, 0x6000, 0x9082, 0x0010, 0x1a0c, - 0x0dc5, 0x6000, 0x0002, 0xb3bb, 0xc3f8, 0xc4c0, 0xc5f3, 0xc7a2, - 0xb3bb, 0xb3bb, 0xb3bb, 0xc3cc, 0xc9a1, 0xc9a4, 0xb3bb, 0xb3bb, - 0xb3bb, 0xb3bb, 0xc9d3, 0x080c, 0x0dc5, 0x0066, 0x6000, 0x90b2, - 0x0010, 0x1a0c, 0x0dc5, 0x0013, 0x006e, 0x0005, 0xb3d6, 0xb3d6, - 0xb419, 0xb4b8, 0xb54d, 0xb3d6, 0xb3d6, 0xb3d6, 0xb3d8, 0xb3d6, - 0xb3d6, 0xb3d6, 0xb3d6, 0xb3d6, 0xb3d6, 0xb3d6, 0x080c, 0x0dc5, - 0x9186, 0x004c, 0x0588, 0x9186, 0x0003, 0x190c, 0x0dc5, 0x0096, - 0x601c, 0xc0ed, 0x601e, 0x6003, 0x0003, 0x6106, 0x6014, 0x2048, - 0xa87c, 0x9084, 0xa000, 0xc0b5, 0xa87e, 0xa8ac, 0xa846, 0xa8b0, - 0xa84a, 0x9006, 0xa836, 0xa83a, 0xa884, 0x9092, 0x199a, 0x0210, - 0x2001, 0x1999, 0x8003, 0x8013, 0x8213, 0x9210, 0x621a, 0x009e, - 0x2c10, 0x080c, 0x1be0, 0x080c, 0x9564, 0x0126, 0x2091, 0x8000, - 0x080c, 0x9bd3, 0x012e, 0x0005, 0x6010, 0x00b6, 0x2058, 0xbca0, - 0x00be, 0x2c00, 0x080c, 0xb56f, 0x080c, 0xd7fb, 0x6003, 0x0007, - 0x0005, 0x00d6, 0x0096, 0x00f6, 0x2079, 0x1800, 0x7a90, 0x6014, - 0x2048, 0xa87c, 0xd0ec, 0x1110, 0x9290, 0x0018, 0xac78, 0xc4fc, - 0x0046, 0xa8e0, 0x9005, 0x1140, 0xa8dc, 0x921a, 0x0140, 0x0220, - 0xa87b, 0x0007, 0x2010, 0x0028, 0xa87b, 0x0015, 0x0010, 0xa87b, - 0x0000, 0x8214, 0xa883, 0x0000, 0xaa02, 0x0006, 0x0016, 0x0026, - 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2400, 0x9005, 0x1108, 0x009a, - 0x2100, 0x9086, 0x0015, 0x1118, 0x2001, 0x0001, 0x0038, 0x2100, - 0x9086, 0x0016, 0x0118, 0x2001, 0x0001, 0x002a, 0x94a4, 0x0007, - 0x8423, 0x9405, 0x0002, 0xb480, 0xb480, 0xb47b, 0xb47e, 0xb480, - 0xb478, 0xb46b, 0xb46b, 0xb46b, 0xb46b, 0xb46b, 0xb46b, 0xb46b, - 0xb46b, 0xb46b, 0xb46b, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x002e, - 0x001e, 0x000e, 0x004e, 0x00fe, 0x009e, 0x00de, 0x080c, 0x0dc5, - 0x080c, 0xbfab, 0x0028, 0x080c, 0xc0e9, 0x0010, 0x080c, 0xc1df, - 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x002e, 0x001e, 0x2c00, 0xa896, - 0x000e, 0x080c, 0xb62d, 0x0530, 0xa804, 0xa80e, 0x00a6, 0x2050, - 0xb100, 0x00ae, 0x8006, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, - 0xffc0, 0x9080, 0x0002, 0xaacc, 0xabd0, 0xacd4, 0xadd8, 0x2031, - 0x0000, 0x2041, 0x126c, 0x080c, 0xb7f1, 0x0160, 0x000e, 0x9005, - 0x0120, 0x00fe, 0x009e, 0x00de, 0x0005, 0x00fe, 0x009e, 0x00de, - 0x0804, 0xb2d3, 0x2001, 0x002c, 0x900e, 0x080c, 0xb693, 0x0c70, - 0x91b6, 0x0015, 0x0170, 0x91b6, 0x0016, 0x0158, 0x91b2, 0x0047, - 0x0a0c, 0x0dc5, 0x91b2, 0x0050, 0x1a0c, 0x0dc5, 0x9182, 0x0047, - 0x00ca, 0x2001, 0x0109, 0x2004, 0xd08c, 0x0198, 0x0126, 0x2091, - 0x2800, 0x0006, 0x0016, 0x0026, 0x080c, 0x94b1, 0x002e, 0x001e, - 0x000e, 0x012e, 0xa001, 0x6000, 0x9086, 0x0002, 0x1110, 0x0804, - 0xb419, 0x0005, 0xb4eb, 0xb4eb, 0xb4ed, 0xb523, 0xb4eb, 0xb4eb, - 0xb4eb, 0xb4eb, 0xb536, 0x080c, 0x0dc5, 0x00d6, 0x0016, 0x0096, - 0x080c, 0x9a61, 0x080c, 0x9bd3, 0x6003, 0x0004, 0x6114, 0x2148, - 0xa87c, 0xd0fc, 0x01c0, 0xa878, 0xc0fc, 0x9005, 0x1158, 0xa894, - 0x9005, 0x0140, 0x2001, 0x0000, 0x900e, 0x080c, 0xb693, 0x080c, - 0xb2d3, 0x00a8, 0x6003, 0x0002, 0xa8a4, 0xa9a8, 0x9105, 0x1178, - 0xa8ae, 0xa8b2, 0x0c78, 0xa87f, 0x0020, 0xa88c, 0xa88a, 0xa8a4, - 0xa8ae, 0xa8a8, 0xa8b2, 0xa8c7, 0x0000, 0xa8cb, 0x0000, 0x009e, - 0x001e, 0x00de, 0x0005, 0x080c, 0x9a61, 0x00d6, 0x0096, 0x6114, - 0x2148, 0x080c, 0xd0d8, 0x0120, 0xa87b, 0x0006, 0x080c, 0x6e9f, - 0x009e, 0x00de, 0x080c, 0xb2d3, 0x0804, 0x9bd3, 0x080c, 0x9a61, - 0x080c, 0x3250, 0x080c, 0xd7f8, 0x00d6, 0x0096, 0x6114, 0x2148, - 0x080c, 0xd0d8, 0x0120, 0xa87b, 0x0029, 0x080c, 0x6e9f, 0x009e, - 0x00de, 0x080c, 0xb2d3, 0x0804, 0x9bd3, 0x9182, 0x0047, 0x0002, - 0xb55d, 0xb55f, 0xb55d, 0xb55d, 0xb55d, 0xb55d, 0xb55d, 0xb55d, - 0xb55d, 0xb55d, 0xb55d, 0xb55d, 0xb55f, 0x080c, 0x0dc5, 0x00d6, - 0x0096, 0x601f, 0x0000, 0x6114, 0x2148, 0xa87b, 0x0000, 0xa883, - 0x0000, 0x080c, 0x6e9f, 0x009e, 0x00de, 0x0804, 0xb2d3, 0x0026, - 0x0036, 0x0056, 0x0066, 0x0096, 0x00a6, 0x00f6, 0x0006, 0x080c, - 0x100e, 0x000e, 0x090c, 0x0dc5, 0xa960, 0x21e8, 0xa95c, 0x9188, - 0x0019, 0x21a0, 0x900e, 0x20a9, 0x0020, 0x4104, 0xa87a, 0x2079, - 0x1800, 0x7990, 0x9188, 0x0018, 0x918c, 0x0fff, 0xa972, 0xac76, - 0x2950, 0x00a6, 0x2001, 0x0205, 0x2003, 0x0000, 0x901e, 0x2029, - 0x0001, 0x9182, 0x0035, 0x1228, 0x2011, 0x001f, 0x080c, 0xcc85, - 0x04c0, 0x2130, 0x2009, 0x0034, 0x2011, 0x001f, 0x080c, 0xcc85, - 0x96b2, 0x0034, 0xb004, 0x904d, 0x0110, 0x080c, 0x0fc0, 0x080c, - 0x100e, 0x01d0, 0x8528, 0xa867, 0x0110, 0xa86b, 0x0000, 0x2920, - 0xb406, 0x968a, 0x003d, 0x1230, 0x2608, 0x2011, 0x001b, 0x080c, - 0xcc85, 0x00b8, 0x96b2, 0x003c, 0x2009, 0x003c, 0x2950, 0x2011, - 0x001b, 0x080c, 0xcc85, 0x0c18, 0x2001, 0x0205, 0x2003, 0x0000, - 0x00ae, 0x852f, 0x95ad, 0x0050, 0xb566, 0xb070, 0xc0fd, 0xb072, - 0x0048, 0x2001, 0x0205, 0x2003, 0x0000, 0x00ae, 0x852f, 0x95ad, - 0x0050, 0xb566, 0x2a48, 0xa804, 0xa807, 0x0000, 0x0006, 0x080c, - 0x6e9f, 0x000e, 0x2048, 0x9005, 0x1db0, 0x00fe, 0x00ae, 0x009e, - 0x006e, 0x005e, 0x003e, 0x002e, 0x0005, 0x00d6, 0x00f6, 0x0096, - 0x0006, 0x080c, 0x100e, 0x000e, 0x090c, 0x0dc5, 0xa960, 0x21e8, - 0xa95c, 0x9188, 0x0019, 0x21a0, 0x900e, 0x20a9, 0x0020, 0x4104, - 0xaa66, 0xa87a, 0x2079, 0x1800, 0x7990, 0x810c, 0x9188, 0x000c, - 0x9182, 0x001a, 0x0210, 0x2009, 0x001a, 0x21a8, 0x810b, 0xa972, - 0xac76, 0x2e98, 0xa85c, 0x9080, 0x001f, 0x20a0, 0x2001, 0x0205, - 0x200c, 0x918d, 0x0080, 0x2102, 0x4003, 0x2003, 0x0000, 0x080c, - 0x6e9f, 0x009e, 0x00fe, 0x00de, 0x0005, 0x0016, 0x00d6, 0x00f6, - 0x0096, 0x0016, 0x2001, 0x0205, 0x200c, 0x918d, 0x0080, 0x2102, - 0x001e, 0x2079, 0x0200, 0x2e98, 0xa87c, 0xd0ec, 0x0118, 0x9e80, - 0x000c, 0x2098, 0x2021, 0x003e, 0x901e, 0x9282, 0x0020, 0x0218, - 0x2011, 0x0020, 0x2018, 0x9486, 0x003e, 0x1170, 0x0096, 0x080c, - 0x100e, 0x2900, 0x009e, 0x05c0, 0xa806, 0x2048, 0xa860, 0x20e8, - 0xa85c, 0x9080, 0x0002, 0x20a0, 0x3300, 0x908e, 0x0260, 0x0140, - 0x2009, 0x0280, 0x9102, 0x920a, 0x0218, 0x2010, 0x2100, 0x9318, - 0x2200, 0x9402, 0x1228, 0x2400, 0x9202, 0x2410, 0x9318, 0x9006, - 0x2020, 0x22a8, 0xa800, 0x9200, 0xa802, 0x20e1, 0x0000, 0x4003, - 0x83ff, 0x0180, 0x3300, 0x9086, 0x0280, 0x1130, 0x7814, 0x8000, - 0x9085, 0x0080, 0x7816, 0x2e98, 0x2310, 0x84ff, 0x0904, 0xb642, - 0x0804, 0xb644, 0x9085, 0x0001, 0x7817, 0x0000, 0x009e, 0x00fe, - 0x00de, 0x001e, 0x0005, 0x00d6, 0x0036, 0x0096, 0x6314, 0x2348, - 0xa87a, 0xa982, 0x080c, 0x6e92, 0x009e, 0x003e, 0x00de, 0x0005, - 0x91b6, 0x0015, 0x1118, 0x080c, 0xb2d3, 0x0030, 0x91b6, 0x0016, - 0x190c, 0x0dc5, 0x080c, 0xb2d3, 0x0005, 0x20a9, 0x000e, 0x20e1, - 0x0000, 0x2e98, 0x6014, 0x0096, 0x2048, 0xa860, 0x20e8, 0xa85c, - 0x20a0, 0x009e, 0x4003, 0x9196, 0x0016, 0x01f0, 0x0136, 0x9080, - 0x001b, 0x20a0, 0x2011, 0x0006, 0x20a9, 0x0001, 0x3418, 0x8318, - 0x23a0, 0x4003, 0x3318, 0x8318, 0x2398, 0x8211, 0x1db8, 0x2011, - 0x0006, 0x013e, 0x20a0, 0x3318, 0x8318, 0x2398, 0x4003, 0x3418, - 0x8318, 0x23a0, 0x8211, 0x1db8, 0x0096, 0x080c, 0xd0d8, 0x0130, - 0x6014, 0x2048, 0xa807, 0x0000, 0xa867, 0x0103, 0x009e, 0x0804, - 0xb2d3, 0x0096, 0x00d6, 0x0036, 0x7330, 0x9386, 0x0200, 0x11a8, - 0x6010, 0x00b6, 0x2058, 0xb8cf, 0x0000, 0x00be, 0x6014, 0x9005, - 0x0130, 0x2048, 0xa807, 0x0000, 0xa867, 0x0103, 0xab32, 0x080c, - 0xb2d3, 0x003e, 0x00de, 0x009e, 0x0005, 0x0011, 0x1d48, 0x0cc8, - 0x0006, 0x0016, 0x080c, 0xd7e3, 0x0188, 0x6014, 0x9005, 0x1170, - 0x600b, 0x0003, 0x601b, 0x0000, 0x6043, 0x0000, 0x2009, 0x0022, - 0x080c, 0xbadd, 0x9006, 0x001e, 0x000e, 0x0005, 0x9085, 0x0001, - 0x0cd0, 0x0096, 0x0016, 0x20a9, 0x0014, 0x9e80, 0x000c, 0x20e1, - 0x0000, 0x2098, 0x6014, 0x2048, 0xa860, 0x20e8, 0xa85c, 0x9080, - 0x0002, 0x20a0, 0x4003, 0x2001, 0x0205, 0x2003, 0x0001, 0x2099, - 0x0260, 0x20a9, 0x0016, 0x4003, 0x20a9, 0x000a, 0xa804, 0x2048, - 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0002, 0x20a0, 0x4003, 0x2001, - 0x0205, 0x2003, 0x0002, 0x2099, 0x0260, 0x20a9, 0x0020, 0x4003, - 0x2003, 0x0000, 0x6014, 0x2048, 0xa800, 0x2048, 0xa867, 0x0103, - 0x080c, 0xb2d3, 0x001e, 0x009e, 0x0005, 0x0096, 0x0016, 0x900e, - 0x7030, 0x9086, 0x0100, 0x0140, 0x7038, 0x9084, 0x00ff, 0x800c, - 0x703c, 0x9084, 0x00ff, 0x8004, 0x9080, 0x0004, 0x9108, 0x810b, - 0x2011, 0x0002, 0x2019, 0x000c, 0x6014, 0x2048, 0x080c, 0xcc85, - 0x080c, 0xd0d8, 0x0140, 0x6014, 0x2048, 0xa807, 0x0000, 0xa864, - 0xa8e2, 0xa867, 0x0103, 0x080c, 0xb2d3, 0x001e, 0x009e, 0x0005, - 0x0016, 0x2009, 0x0000, 0x7030, 0x9086, 0x0200, 0x0110, 0x2009, - 0x0001, 0x0096, 0x6014, 0x904d, 0x090c, 0x0dc5, 0xa97a, 0x080c, - 0x6e9f, 0x009e, 0x080c, 0xb2d3, 0x001e, 0x0005, 0x0016, 0x0096, - 0x7030, 0x9086, 0x0100, 0x1118, 0x2009, 0x0004, 0x0010, 0x7034, - 0x800c, 0x810b, 0x2011, 0x000c, 0x2019, 0x000c, 0x6014, 0x2048, - 0xa804, 0x0096, 0x9005, 0x0108, 0x2048, 0x080c, 0xcc85, 0x009e, - 0x080c, 0xd0d8, 0x0148, 0xa804, 0x9005, 0x1158, 0xa807, 0x0000, - 0xa864, 0xa8e2, 0xa867, 0x0103, 0x080c, 0xb2d3, 0x009e, 0x001e, - 0x0005, 0x0086, 0x2040, 0xa030, 0x8007, 0x9086, 0x0100, 0x1118, - 0x080c, 0xbcb6, 0x00e0, 0xa034, 0x8007, 0x800c, 0x8806, 0x8006, - 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x000c, 0xa87b, - 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, 0xaaa0, 0xab9c, 0xaca8, - 0xada4, 0x2031, 0x0000, 0x2041, 0x1252, 0x0019, 0x0d08, 0x008e, - 0x0898, 0x0096, 0x0006, 0x080c, 0x100e, 0x000e, 0x01b0, 0xa8ab, - 0x0dcb, 0xa876, 0x000e, 0xa8a2, 0x0006, 0xae6a, 0x2800, 0xa89e, - 0xa97a, 0xaf72, 0xaa8e, 0xab92, 0xac96, 0xad9a, 0x0086, 0x2940, - 0x080c, 0x10f8, 0x008e, 0x9085, 0x0001, 0x009e, 0x0005, 0x00e6, - 0x00d6, 0x0026, 0x7008, 0x9084, 0x00ff, 0x6210, 0x00b6, 0x2258, - 0xba10, 0x00be, 0x9206, 0x1520, 0x700c, 0x6210, 0x00b6, 0x2258, - 0xba14, 0x00be, 0x9206, 0x11e0, 0x6043, 0x0000, 0x2c68, 0x0016, - 0x2009, 0x0035, 0x080c, 0xd759, 0x001e, 0x1158, 0x622c, 0x2268, - 0x2071, 0x026c, 0x6b20, 0x9386, 0x0003, 0x0130, 0x9386, 0x0006, - 0x0128, 0x080c, 0xb2d3, 0x0020, 0x0039, 0x0010, 0x080c, 0xb910, - 0x002e, 0x00de, 0x00ee, 0x0005, 0x0096, 0x6814, 0x2048, 0x9186, - 0x0015, 0x0904, 0xb8f8, 0x918e, 0x0016, 0x1904, 0xb90e, 0x700c, - 0x908c, 0xff00, 0x9186, 0x1700, 0x0120, 0x9186, 0x0300, 0x1904, - 0xb8d2, 0x89ff, 0x1138, 0x6800, 0x9086, 0x000f, 0x0904, 0xb8b5, - 0x0804, 0xb90c, 0x6808, 0x9086, 0xffff, 0x1904, 0xb8fa, 0xa87c, - 0x9084, 0x0060, 0x9086, 0x0020, 0x1128, 0xa83c, 0xa940, 0x9105, - 0x1904, 0xb8fa, 0x6824, 0xd084, 0x1904, 0xb8fa, 0xd0b4, 0x0158, - 0x0016, 0x2001, 0x1986, 0x200c, 0x6018, 0x9102, 0x9082, 0x0005, - 0x001e, 0x1a04, 0xb8fa, 0x080c, 0xd2c3, 0x685c, 0xa882, 0xa87c, - 0xc0dc, 0xc0f4, 0xc0d4, 0xa87e, 0x0026, 0x900e, 0x6a18, 0x2001, - 0x000a, 0x080c, 0x9375, 0xa884, 0x920a, 0x0208, 0x8011, 0xaa86, - 0x82ff, 0x002e, 0x1138, 0x00c6, 0x2d60, 0x080c, 0xcde3, 0x00ce, - 0x0804, 0xb90c, 0x00c6, 0xa868, 0xd0fc, 0x1118, 0x080c, 0x61c2, - 0x0010, 0x080c, 0x65cf, 0x00ce, 0x1904, 0xb8fa, 0x00c6, 0x2d60, - 0x080c, 0xb2d3, 0x00ce, 0x0804, 0xb90c, 0x00c6, 0x080c, 0xb325, - 0x0198, 0x6017, 0x0000, 0x6810, 0x6012, 0x080c, 0xd554, 0x6023, - 0x0003, 0x6904, 0x00c6, 0x2d60, 0x080c, 0xb2d3, 0x00ce, 0x080c, - 0xb352, 0x00ce, 0x0804, 0xb90c, 0x2001, 0x1988, 0x2004, 0x6842, - 0x00ce, 0x04d0, 0x7008, 0x9086, 0x000b, 0x11c8, 0x6010, 0x00b6, - 0x2058, 0xb900, 0xc1bc, 0xb902, 0x00be, 0x00c6, 0x2d60, 0xa87b, - 0x0003, 0x080c, 0xd79d, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, - 0x0002, 0x080c, 0x94ff, 0x080c, 0x9ab1, 0x00ce, 0x00e8, 0x700c, - 0x9086, 0x2a00, 0x1138, 0x2001, 0x1988, 0x2004, 0x6842, 0x00a0, - 0x0479, 0x00a0, 0x89ff, 0x090c, 0x0dc5, 0x00c6, 0x00d6, 0x2d60, - 0xa867, 0x0103, 0xa87b, 0x0003, 0x080c, 0x6cb9, 0x080c, 0xd2c3, - 0x080c, 0xb306, 0x00de, 0x00ce, 0x080c, 0xb2d3, 0x009e, 0x0005, - 0x9186, 0x0015, 0x1128, 0x2001, 0x1988, 0x2004, 0x6842, 0x0068, - 0x918e, 0x0016, 0x1160, 0x00c6, 0x2d00, 0x2060, 0x080c, 0xee87, - 0x080c, 0x8a25, 0x080c, 0xb2d3, 0x00ce, 0x080c, 0xb2d3, 0x0005, - 0x0026, 0x0036, 0x0046, 0x7228, 0xacb0, 0xabac, 0xd2f4, 0x0130, - 0x2001, 0x1988, 0x2004, 0x6842, 0x0804, 0xb98a, 0x00c6, 0x2d60, - 0x080c, 0xcce6, 0x00ce, 0x6804, 0x9086, 0x0050, 0x1168, 0x00c6, - 0x2d00, 0x2060, 0x6003, 0x0001, 0x6007, 0x0050, 0x080c, 0x94ff, - 0x080c, 0x9ab1, 0x00ce, 0x04f0, 0x6800, 0x9086, 0x000f, 0x01a8, - 0x89ff, 0x090c, 0x0dc5, 0x6800, 0x9086, 0x0004, 0x1190, 0xa87c, - 0xd0ac, 0x0178, 0xa843, 0x0fff, 0xa83f, 0x0fff, 0xa880, 0xc0fc, - 0xa882, 0x2001, 0x0001, 0x6832, 0x0400, 0x2001, 0x0007, 0x6832, - 0x00e0, 0xa87c, 0xd0b4, 0x1150, 0xd0ac, 0x0db8, 0x6824, 0xd0f4, - 0x1d48, 0xa838, 0xa934, 0x9105, 0x0d80, 0x0c20, 0xd2ec, 0x1d68, - 0x7024, 0x9306, 0x1118, 0x7020, 0x9406, 0x0d38, 0x7020, 0x683e, - 0x7024, 0x683a, 0x2001, 0x0005, 0x6832, 0x080c, 0xd44b, 0x080c, - 0x9ab1, 0x0010, 0x080c, 0xb2d3, 0x004e, 0x003e, 0x002e, 0x0005, - 0x00e6, 0x00d6, 0x0026, 0x7008, 0x9084, 0x00ff, 0x6210, 0x00b6, - 0x2258, 0xba10, 0x00be, 0x9206, 0x1904, 0xb9f5, 0x700c, 0x6210, - 0x00b6, 0x2258, 0xba14, 0x00be, 0x9206, 0x1904, 0xb9f5, 0x6038, - 0x2068, 0x6824, 0xc0dc, 0x6826, 0x6a20, 0x9286, 0x0007, 0x0904, - 0xb9f5, 0x9286, 0x0002, 0x0904, 0xb9f5, 0x9286, 0x0000, 0x05e8, - 0x6808, 0x633c, 0x9306, 0x15c8, 0x2071, 0x026c, 0x9186, 0x0015, - 0x0570, 0x918e, 0x0016, 0x1100, 0x00c6, 0x6038, 0x2060, 0x6104, - 0x9186, 0x004b, 0x01c0, 0x9186, 0x004c, 0x01a8, 0x9186, 0x004d, - 0x0190, 0x9186, 0x004e, 0x0178, 0x9186, 0x0052, 0x0160, 0x6014, - 0x0096, 0x2048, 0x080c, 0xd0d8, 0x090c, 0x0dc5, 0xa87b, 0x0003, - 0x009e, 0x080c, 0xd79d, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, - 0x0002, 0x080c, 0x94ff, 0x080c, 0x9ab1, 0x00ce, 0x0030, 0x6038, - 0x2070, 0x2001, 0x1988, 0x2004, 0x7042, 0x080c, 0xb2d3, 0x002e, - 0x00de, 0x00ee, 0x0005, 0x00b6, 0x0096, 0x00f6, 0x6014, 0x2048, - 0x6010, 0x2058, 0x91b6, 0x0015, 0x0130, 0xba08, 0xbb0c, 0xbc00, - 0xc48c, 0xbc02, 0x0470, 0x0096, 0x0156, 0x0036, 0x0026, 0x2b48, - 0x9e90, 0x0010, 0x2019, 0x000a, 0x20a9, 0x0004, 0x080c, 0xc379, - 0x002e, 0x003e, 0x015e, 0x009e, 0x1904, 0xba66, 0x0096, 0x0156, - 0x0036, 0x0026, 0x2b48, 0x9e90, 0x0014, 0x2019, 0x0006, 0x20a9, - 0x0004, 0x080c, 0xc379, 0x002e, 0x003e, 0x015e, 0x009e, 0x15b0, - 0x7238, 0xba0a, 0x733c, 0xbb0e, 0x83ff, 0x0118, 0xbc00, 0xc48d, - 0xbc02, 0xa804, 0x9005, 0x1128, 0x00fe, 0x009e, 0x00be, 0x0804, - 0xb6dc, 0x0096, 0x2048, 0xaa12, 0xab16, 0xac0a, 0x009e, 0x8006, - 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, - 0x2009, 0x002b, 0xaaa0, 0xab9c, 0xaca8, 0xada4, 0x2031, 0x0000, - 0x2041, 0x1252, 0x080c, 0xb7f1, 0x0130, 0x00fe, 0x009e, 0x080c, - 0xb2d3, 0x00be, 0x0005, 0x080c, 0xbcb6, 0x0cb8, 0x2b78, 0x00f6, - 0x080c, 0x3250, 0x080c, 0xd7f8, 0x00fe, 0x00c6, 0x080c, 0xb27d, - 0x2f00, 0x6012, 0x6017, 0x0000, 0x6023, 0x0001, 0x6007, 0x0001, - 0x6003, 0x0001, 0x2001, 0x0007, 0x080c, 0x666a, 0x080c, 0x6696, - 0x080c, 0x9547, 0x080c, 0x9ab1, 0x00ce, 0x0804, 0xba39, 0x2100, - 0x91b2, 0x0053, 0x1a0c, 0x0dc5, 0x91b2, 0x0040, 0x1a04, 0xbaef, - 0x0002, 0xbadd, 0xbadd, 0xbad3, 0xbadd, 0xbadd, 0xbadd, 0xbad1, - 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, - 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, - 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, - 0xbadd, 0xbad1, 0xbadd, 0xbadd, 0xbad1, 0xbad1, 0xbad1, 0xbad1, - 0xbad1, 0xbad3, 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, - 0xbad1, 0xbad1, 0xbad1, 0xbadd, 0xbadd, 0xbad1, 0xbad1, 0xbad1, - 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbadd, 0xbad1, - 0xbad1, 0x080c, 0x0dc5, 0x0066, 0x00b6, 0x6610, 0x2658, 0xb8cc, - 0xc08c, 0xb8ce, 0x00be, 0x006e, 0x0000, 0x6003, 0x0001, 0x6106, - 0x9186, 0x0032, 0x0118, 0x080c, 0x9547, 0x0010, 0x080c, 0x94ff, - 0x0126, 0x2091, 0x8000, 0x080c, 0x9ab1, 0x012e, 0x0005, 0x2600, - 0x0002, 0xbadd, 0xbadd, 0xbb03, 0xbadd, 0xbadd, 0xbb03, 0xbb03, - 0xbb03, 0xbb03, 0xbadd, 0xbb03, 0xbadd, 0xbb03, 0xbadd, 0xbb03, - 0xbb03, 0xbb03, 0xbb03, 0x080c, 0x0dc5, 0x6004, 0x90b2, 0x0053, - 0x1a0c, 0x0dc5, 0x91b6, 0x0013, 0x0904, 0xbbd8, 0x91b6, 0x0027, - 0x1904, 0xbb82, 0x080c, 0x99a5, 0x6004, 0x080c, 0xd2cf, 0x01b0, - 0x080c, 0xd2e0, 0x01a8, 0x908e, 0x0021, 0x0904, 0xbb7f, 0x908e, - 0x0022, 0x1130, 0x080c, 0xb708, 0x0904, 0xbb7b, 0x0804, 0xbb7c, - 0x908e, 0x003d, 0x0904, 0xbb7f, 0x0804, 0xbb75, 0x080c, 0x3279, - 0x2001, 0x0007, 0x080c, 0x666a, 0x6010, 0x00b6, 0x2058, 0xb9a0, - 0x00be, 0x080c, 0xbcb6, 0x9186, 0x007e, 0x1148, 0x2001, 0x1837, - 0x2014, 0xc285, 0x080c, 0x7637, 0x1108, 0xc2ad, 0x2202, 0x0036, - 0x0026, 0x2019, 0x0028, 0x2110, 0x080c, 0xef94, 0x002e, 0x003e, - 0x0016, 0x0026, 0x0036, 0x2110, 0x2019, 0x0028, 0x080c, 0x96a4, - 0x0076, 0x903e, 0x080c, 0x9577, 0x6010, 0x00b6, 0x905d, 0x0100, - 0x00be, 0x2c08, 0x080c, 0xe91c, 0x007e, 0x003e, 0x002e, 0x001e, - 0x080c, 0xd7f8, 0x0016, 0x080c, 0xd54c, 0x080c, 0xb2d3, 0x001e, - 0x080c, 0x334c, 0x080c, 0x9ab1, 0x0030, 0x080c, 0xd54c, 0x080c, - 0xb2d3, 0x080c, 0x9ab1, 0x0005, 0x080c, 0xbcb6, 0x0cb0, 0x080c, - 0xbcf2, 0x0c98, 0x9186, 0x0015, 0x0118, 0x9186, 0x0016, 0x1148, - 0x080c, 0xd809, 0x0d80, 0x6000, 0x9086, 0x0002, 0x0904, 0xbcfd, - 0x0c50, 0x9186, 0x0014, 0x1d38, 0x080c, 0x99a5, 0x6004, 0x908e, - 0x0022, 0x1118, 0x080c, 0xb708, 0x09f0, 0x080c, 0x3250, 0x080c, - 0xd7f8, 0x080c, 0xd2cf, 0x1198, 0x080c, 0x3279, 0x6010, 0x00b6, - 0x2058, 0xb9a0, 0x00be, 0x080c, 0xbcb6, 0x9186, 0x007e, 0x1128, - 0x2001, 0x1837, 0x200c, 0xc185, 0x2102, 0x0804, 0xbb75, 0x080c, - 0xd2e0, 0x1120, 0x080c, 0xbcb6, 0x0804, 0xbb75, 0x6004, 0x908e, - 0x0032, 0x1160, 0x00e6, 0x00f6, 0x2071, 0x189e, 0x2079, 0x0000, - 0x080c, 0x35e7, 0x00fe, 0x00ee, 0x0804, 0xbb75, 0x6004, 0x908e, - 0x0021, 0x0d40, 0x908e, 0x0022, 0x090c, 0xbcb6, 0x0804, 0xbb75, - 0x90b2, 0x0040, 0x1a04, 0xbc92, 0x2008, 0x0002, 0xbc20, 0xbc21, - 0xbc24, 0xbc27, 0xbc2a, 0xbc37, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, - 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, - 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, - 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc3a, 0xbc47, 0xbc1e, 0xbc49, - 0xbc47, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc47, 0xbc47, - 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, - 0xbc79, 0xbc47, 0xbc1e, 0xbc43, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc44, - 0xbc1e, 0xbc1e, 0xbc1e, 0xbc47, 0xbc70, 0xbc1e, 0x080c, 0x0dc5, - 0x0430, 0x2001, 0x000b, 0x0470, 0x2001, 0x0003, 0x0458, 0x2001, - 0x0005, 0x0440, 0x6010, 0x00b6, 0x2058, 0xb804, 0x00be, 0x9084, - 0x00ff, 0x9086, 0x0000, 0x1500, 0x2001, 0x0001, 0x00d8, 0x2001, - 0x0009, 0x00c0, 0x080c, 0x99a5, 0x6003, 0x0005, 0x080c, 0xd7fb, - 0x080c, 0x9ab1, 0x0070, 0x0018, 0x0010, 0x080c, 0x666a, 0x0804, - 0xbc8a, 0x080c, 0x99a5, 0x080c, 0xd7fb, 0x6003, 0x0004, 0x080c, - 0x9ab1, 0x0005, 0x080c, 0x666a, 0x080c, 0x99a5, 0x6003, 0x0002, - 0x0036, 0x2019, 0x1852, 0x2304, 0x9084, 0xff00, 0x1120, 0x2001, - 0x1986, 0x201c, 0x0040, 0x8007, 0x909a, 0x0004, 0x0ec0, 0x8003, - 0x801b, 0x831b, 0x9318, 0x631a, 0x003e, 0x080c, 0x9ab1, 0x0c08, - 0x080c, 0x99a5, 0x080c, 0xd54c, 0x080c, 0xb2d3, 0x080c, 0x9ab1, - 0x08c0, 0x00e6, 0x00f6, 0x2071, 0x189e, 0x2079, 0x0000, 0x080c, - 0x35e7, 0x00fe, 0x00ee, 0x080c, 0x99a5, 0x080c, 0xb2d3, 0x080c, - 0x9ab1, 0x0838, 0x080c, 0x99a5, 0x6003, 0x0002, 0x080c, 0xd7fb, - 0x0804, 0x9ab1, 0x2600, 0x2008, 0x0002, 0xbca9, 0xbc8a, 0xbca7, - 0xbc8a, 0xbc8a, 0xbca7, 0xbca7, 0xbca7, 0xbca7, 0xbc8a, 0xbca7, - 0xbc8a, 0xbca7, 0xbc8a, 0xbca7, 0xbca7, 0xbca7, 0xbca7, 0x080c, - 0x0dc5, 0x080c, 0x99a5, 0x0096, 0x6014, 0x2048, 0x080c, 0x6e9f, - 0x009e, 0x080c, 0xb2d3, 0x080c, 0x9ab1, 0x0005, 0x00e6, 0x0096, - 0x0026, 0x0016, 0x080c, 0xd0d8, 0x0568, 0x6014, 0x2048, 0xa864, - 0x9086, 0x0139, 0x11a8, 0xa894, 0x9086, 0x0056, 0x1148, 0x080c, - 0x556f, 0x0130, 0x2001, 0x0000, 0x900e, 0x2011, 0x4000, 0x0028, - 0x2001, 0x0030, 0x900e, 0x2011, 0x4005, 0x080c, 0xd6bd, 0x0090, - 0xa868, 0xd0fc, 0x0178, 0xa807, 0x0000, 0x0016, 0x6004, 0x908e, - 0x0021, 0x0168, 0x908e, 0x003d, 0x0150, 0x001e, 0xa867, 0x0103, - 0xa833, 0x0100, 0x001e, 0x002e, 0x009e, 0x00ee, 0x0005, 0x001e, - 0x0009, 0x0cc0, 0x0096, 0x6014, 0x2048, 0xa800, 0x2048, 0xa867, - 0x0103, 0xa823, 0x8001, 0x009e, 0x0005, 0x00b6, 0x6610, 0x2658, - 0xb804, 0x9084, 0x00ff, 0x90b2, 0x000c, 0x1a0c, 0x0dc5, 0x6604, - 0x96b6, 0x004d, 0x1120, 0x080c, 0xd5dc, 0x0804, 0xbd82, 0x6604, - 0x96b6, 0x0043, 0x1120, 0x080c, 0xd625, 0x0804, 0xbd82, 0x6604, - 0x96b6, 0x004b, 0x1120, 0x080c, 0xd651, 0x0804, 0xbd82, 0x6604, - 0x96b6, 0x0033, 0x1120, 0x080c, 0xd56e, 0x0804, 0xbd82, 0x6604, - 0x96b6, 0x0028, 0x1120, 0x080c, 0xd31e, 0x0804, 0xbd82, 0x6604, - 0x96b6, 0x0029, 0x1120, 0x080c, 0xd35f, 0x0804, 0xbd82, 0x6604, - 0x96b6, 0x001f, 0x1120, 0x080c, 0xb6ad, 0x0804, 0xbd82, 0x6604, - 0x96b6, 0x0000, 0x1118, 0x080c, 0xb9fb, 0x04e0, 0x6604, 0x96b6, - 0x0022, 0x1118, 0x080c, 0xb6e9, 0x04a8, 0x6604, 0x96b6, 0x0035, - 0x1118, 0x080c, 0xb80f, 0x0470, 0x6604, 0x96b6, 0x0039, 0x1118, - 0x080c, 0xb990, 0x0438, 0x6604, 0x96b6, 0x003d, 0x1118, 0x080c, - 0xb721, 0x0400, 0x6604, 0x96b6, 0x0044, 0x1118, 0x080c, 0xb75d, - 0x00c8, 0x6604, 0x96b6, 0x0049, 0x1118, 0x080c, 0xb79e, 0x0090, - 0x6604, 0x96b6, 0x0041, 0x1118, 0x080c, 0xb788, 0x0058, 0x91b6, - 0x0015, 0x1110, 0x0063, 0x0030, 0x91b6, 0x0016, 0x1128, 0x00be, - 0x0804, 0xc08e, 0x00be, 0x0005, 0x080c, 0xb36d, 0x0cd8, 0xbd9f, - 0xbdad, 0xbd9f, 0xbdf4, 0xbd9f, 0xbfab, 0xc09b, 0xbd9f, 0xbd9f, - 0xc064, 0xbd9f, 0xc07a, 0x0096, 0x601f, 0x0000, 0x6014, 0x2048, - 0xa800, 0x2048, 0xa867, 0x0103, 0x009e, 0x0804, 0xb2d3, 0xa001, - 0xa001, 0x0005, 0x6604, 0x96b6, 0x0004, 0x1130, 0x2001, 0x0001, - 0x080c, 0x6656, 0x0804, 0xb2d3, 0x0005, 0x00e6, 0x2071, 0x1800, - 0x7090, 0x9086, 0x0074, 0x1540, 0x080c, 0xe8ed, 0x11b0, 0x6010, - 0x00b6, 0x2058, 0x7030, 0xd08c, 0x0128, 0xb800, 0xd0bc, 0x0110, - 0xc0c5, 0xb802, 0x00f9, 0x00be, 0x2001, 0x0006, 0x080c, 0x666a, - 0x080c, 0x3279, 0x080c, 0xb2d3, 0x0098, 0x2001, 0x000a, 0x080c, - 0x666a, 0x080c, 0x3279, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, - 0x9547, 0x080c, 0x9ab1, 0x0020, 0x2001, 0x0001, 0x080c, 0xbf7b, - 0x00ee, 0x0005, 0x00d6, 0xb800, 0xd084, 0x0160, 0x9006, 0x080c, - 0x6656, 0x2069, 0x1847, 0x6804, 0xd0a4, 0x0120, 0x2001, 0x0006, - 0x080c, 0x6696, 0x00de, 0x0005, 0x00b6, 0x0096, 0x00d6, 0x2011, - 0x1824, 0x2204, 0x9086, 0x0074, 0x1904, 0xbf50, 0x6010, 0x2058, - 0xbaa0, 0x9286, 0x007e, 0x1120, 0x080c, 0xc1ea, 0x0804, 0xbebd, - 0x2001, 0x180d, 0x2004, 0xd08c, 0x0904, 0xbe5f, 0x00d6, 0x080c, - 0x7637, 0x01a0, 0x0026, 0x2011, 0x0010, 0x080c, 0x6ac7, 0x002e, - 0x0904, 0xbe5e, 0x080c, 0x57e9, 0x1598, 0x6014, 0x2048, 0xa807, - 0x0000, 0xa867, 0x0103, 0xa833, 0xdead, 0x0450, 0x6010, 0x00b6, - 0x2058, 0xb910, 0x00be, 0x9186, 0x00ff, 0x0580, 0x0026, 0x2011, - 0x8008, 0x080c, 0x6ac7, 0x002e, 0x0548, 0x6014, 0x9005, 0x090c, - 0x0dc5, 0x2048, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1140, - 0x2001, 0x0030, 0x900e, 0x2011, 0x4009, 0x080c, 0xd6bd, 0x0040, - 0x6014, 0x2048, 0xa807, 0x0000, 0xa867, 0x0103, 0xa833, 0xdead, - 0x6010, 0x2058, 0xb9a0, 0x0016, 0x080c, 0x3279, 0x080c, 0xb2d3, - 0x001e, 0x080c, 0x334c, 0x00de, 0x0804, 0xbf55, 0x00de, 0x080c, - 0xc1df, 0x6010, 0x2058, 0xbaa0, 0x9286, 0x0080, 0x1510, 0x6014, - 0x9005, 0x01a8, 0x2048, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, - 0x1140, 0x2001, 0x0000, 0x900e, 0x2011, 0x4000, 0x080c, 0xd6bd, - 0x0030, 0xa807, 0x0000, 0xa867, 0x0103, 0xa833, 0x0200, 0x2001, - 0x0006, 0x080c, 0x666a, 0x080c, 0x3279, 0x080c, 0xb2d3, 0x0804, - 0xbf55, 0x080c, 0xbf63, 0x6014, 0x9005, 0x0190, 0x2048, 0xa868, - 0xd0f4, 0x01e8, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1d08, - 0x2001, 0x0000, 0x900e, 0x2011, 0x4000, 0x080c, 0xd6bd, 0x08f8, - 0x080c, 0xbf59, 0x0160, 0x9006, 0x080c, 0x6656, 0x2001, 0x0004, - 0x080c, 0x6696, 0x2001, 0x0007, 0x080c, 0x666a, 0x08a0, 0x2001, - 0x0004, 0x080c, 0x666a, 0x6003, 0x0001, 0x6007, 0x0003, 0x080c, - 0x9547, 0x080c, 0x9ab1, 0x0804, 0xbf55, 0xb85c, 0xd0e4, 0x0178, - 0x080c, 0xd4ee, 0x080c, 0x7637, 0x0118, 0xd0dc, 0x1904, 0xbe7f, - 0x2011, 0x1837, 0x2204, 0xc0ad, 0x2012, 0x0804, 0xbe7f, 0x080c, - 0xd52b, 0x2011, 0x1837, 0x2204, 0xc0a5, 0x2012, 0x0006, 0x080c, - 0xeab9, 0x000e, 0x1904, 0xbe7f, 0xc0b5, 0x2012, 0x2001, 0x0006, - 0x080c, 0x666a, 0x9006, 0x080c, 0x6656, 0x00c6, 0x2001, 0x180f, - 0x2004, 0xd09c, 0x0520, 0x00f6, 0x2079, 0x0100, 0x00e6, 0x2071, - 0x1800, 0x700c, 0x9084, 0x00ff, 0x78e6, 0x707e, 0x7010, 0x78ea, - 0x7082, 0x908c, 0x00ff, 0x00ee, 0x780c, 0xc0b5, 0x780e, 0x00fe, - 0x080c, 0x28bc, 0x00f6, 0x2100, 0x900e, 0x080c, 0x2873, 0x795e, - 0x00fe, 0x9186, 0x0081, 0x01f0, 0x2009, 0x0081, 0x00e0, 0x2009, - 0x00ef, 0x00f6, 0x2079, 0x0100, 0x79ea, 0x78e7, 0x0000, 0x7932, - 0x7936, 0x780c, 0xc0b5, 0x780e, 0x00fe, 0x080c, 0x28bc, 0x00f6, - 0x2079, 0x1800, 0x7982, 0x2100, 0x900e, 0x797e, 0x080c, 0x2873, - 0x795e, 0x00fe, 0x8108, 0x080c, 0x66b9, 0x2b00, 0x00ce, 0x1904, - 0xbe7f, 0x6012, 0x2009, 0x180f, 0x210c, 0xd19c, 0x0150, 0x2009, - 0x027c, 0x210c, 0x918c, 0x00ff, 0xb912, 0x2009, 0x027d, 0x210c, - 0xb916, 0x2001, 0x0002, 0x080c, 0x666a, 0x6023, 0x0001, 0x6003, - 0x0001, 0x6007, 0x0002, 0x080c, 0x9547, 0x080c, 0x9ab1, 0x0028, - 0x080c, 0xbcb6, 0x2001, 0x0001, 0x0431, 0x00de, 0x009e, 0x00be, - 0x0005, 0x2001, 0x1810, 0x2004, 0xd0a4, 0x0120, 0x2001, 0x1848, - 0x2004, 0xd0ac, 0x0005, 0x00e6, 0x080c, 0xefed, 0x0190, 0x2071, - 0x0260, 0x7108, 0x720c, 0x918c, 0x00ff, 0x1118, 0x9284, 0xff00, - 0x0140, 0x6010, 0x2058, 0xb8a0, 0x9084, 0xff80, 0x1110, 0xb912, - 0xba16, 0x00ee, 0x0005, 0x2030, 0x9005, 0x0158, 0x2001, 0x0007, - 0x080c, 0x666a, 0x080c, 0x57e9, 0x1120, 0x2001, 0x0007, 0x080c, - 0x6696, 0x2600, 0x9005, 0x11b0, 0x6014, 0x0096, 0x2048, 0xa868, - 0x009e, 0xd0fc, 0x1178, 0x0036, 0x0046, 0x6010, 0x00b6, 0x2058, - 0xbba0, 0x00be, 0x2021, 0x0004, 0x2011, 0x8014, 0x080c, 0x4c44, - 0x004e, 0x003e, 0x080c, 0x3279, 0x6020, 0x9086, 0x000a, 0x1108, - 0x0005, 0x0804, 0xb2d3, 0x00b6, 0x00e6, 0x0026, 0x0016, 0x2071, - 0x1800, 0x7090, 0x9086, 0x0014, 0x1904, 0xc05a, 0x2001, 0x180d, - 0x2004, 0xd08c, 0x0904, 0xc00d, 0x00d6, 0x080c, 0x7637, 0x01a0, - 0x0026, 0x2011, 0x0010, 0x080c, 0x6ac7, 0x002e, 0x0904, 0xc00c, - 0x080c, 0x57e9, 0x1598, 0x6014, 0x2048, 0xa807, 0x0000, 0xa867, - 0x0103, 0xa833, 0xdead, 0x0450, 0x6010, 0x00b6, 0x2058, 0xb910, - 0x00be, 0x9186, 0x00ff, 0x0580, 0x0026, 0x2011, 0x8008, 0x080c, - 0x6ac7, 0x002e, 0x0548, 0x6014, 0x9005, 0x090c, 0x0dc5, 0x2048, - 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1140, 0x2001, 0x0030, - 0x900e, 0x2011, 0x4009, 0x080c, 0xd6bd, 0x0040, 0x6014, 0x2048, - 0xa807, 0x0000, 0xa867, 0x0103, 0xa833, 0xdead, 0x6010, 0x2058, - 0xb9a0, 0x0016, 0x080c, 0x3279, 0x080c, 0xb2d3, 0x001e, 0x080c, - 0x334c, 0x00de, 0x0804, 0xc05f, 0x00de, 0x080c, 0x57e9, 0x1170, - 0x6014, 0x9005, 0x1158, 0x0036, 0x0046, 0x6010, 0x2058, 0xbba0, - 0x2021, 0x0006, 0x080c, 0x4dfb, 0x004e, 0x003e, 0x00d6, 0x6010, - 0x2058, 0x080c, 0x67bf, 0x080c, 0xbde2, 0x00de, 0x080c, 0xc2b5, - 0x1588, 0x6010, 0x2058, 0xb890, 0x9005, 0x0560, 0x2001, 0x0006, - 0x080c, 0x666a, 0x0096, 0x6014, 0x904d, 0x01d0, 0xa864, 0x9084, - 0x00ff, 0x9086, 0x0039, 0x1140, 0x2001, 0x0000, 0x900e, 0x2011, - 0x4000, 0x080c, 0xd6bd, 0x0060, 0xa864, 0x9084, 0x00ff, 0x9086, - 0x0029, 0x0130, 0xa807, 0x0000, 0xa867, 0x0103, 0xa833, 0x0200, - 0x009e, 0x080c, 0x3279, 0x6020, 0x9086, 0x000a, 0x0140, 0x080c, - 0xb2d3, 0x0028, 0x080c, 0xbcb6, 0x9006, 0x080c, 0xbf7b, 0x001e, - 0x002e, 0x00ee, 0x00be, 0x0005, 0x2011, 0x1824, 0x2204, 0x9086, - 0x0014, 0x1160, 0x2001, 0x0002, 0x080c, 0x666a, 0x6003, 0x0001, - 0x6007, 0x0001, 0x080c, 0x9547, 0x0804, 0x9ab1, 0x2001, 0x0001, - 0x0804, 0xbf7b, 0x2030, 0x2011, 0x1824, 0x2204, 0x9086, 0x0004, - 0x1148, 0x96b6, 0x000b, 0x1120, 0x2001, 0x0007, 0x080c, 0x666a, - 0x0804, 0xb2d3, 0x2001, 0x0001, 0x0804, 0xbf7b, 0x0002, 0xbd9f, - 0xc0a6, 0xbd9f, 0xc0e9, 0xbd9f, 0xc196, 0xc09b, 0xbda2, 0xbd9f, - 0xc1aa, 0xbd9f, 0xc1bc, 0x6604, 0x9686, 0x0003, 0x0904, 0xbfab, - 0x96b6, 0x001e, 0x1110, 0x080c, 0xb2d3, 0x0005, 0x00b6, 0x00d6, - 0x00c6, 0x080c, 0xc1ce, 0x11a0, 0x9006, 0x080c, 0x6656, 0x080c, - 0x3250, 0x080c, 0xd7f8, 0x2001, 0x0002, 0x080c, 0x666a, 0x6003, - 0x0001, 0x6007, 0x0002, 0x080c, 0x9547, 0x080c, 0x9ab1, 0x0428, - 0x2009, 0x026e, 0x2104, 0x9086, 0x0009, 0x1160, 0x6010, 0x2058, - 0xb840, 0x9084, 0x00ff, 0x9005, 0x0180, 0x8001, 0xb842, 0x601b, - 0x000a, 0x0098, 0x2009, 0x026f, 0x2104, 0x9084, 0xff00, 0x908e, - 0x1900, 0x0158, 0x908e, 0x1e00, 0x0990, 0x080c, 0x3250, 0x080c, - 0xd7f8, 0x2001, 0x0001, 0x080c, 0xbf7b, 0x00ce, 0x00de, 0x00be, - 0x0005, 0x0096, 0x00b6, 0x0026, 0x9016, 0x080c, 0xc1dc, 0x00d6, - 0x2069, 0x197c, 0x2d04, 0x9005, 0x0168, 0x6010, 0x2058, 0xb8a0, - 0x9086, 0x007e, 0x1138, 0x2069, 0x1820, 0x2d04, 0x8000, 0x206a, - 0x00de, 0x0010, 0x00de, 0x0088, 0x9006, 0x080c, 0x6656, 0x2001, - 0x0002, 0x080c, 0x666a, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, - 0x9547, 0x080c, 0x9ab1, 0x0804, 0xc166, 0x080c, 0xd0d8, 0x01b0, - 0x6014, 0x2048, 0xa864, 0x2010, 0x9086, 0x0139, 0x1138, 0x6007, - 0x0016, 0x2001, 0x0002, 0x080c, 0xd71a, 0x00b0, 0x6014, 0x2048, - 0xa864, 0xd0fc, 0x0118, 0x2001, 0x0001, 0x0ca8, 0x2001, 0x180e, - 0x2004, 0xd0dc, 0x0148, 0x6010, 0x2058, 0xb840, 0x9084, 0x00ff, - 0x9005, 0x1110, 0x9006, 0x0c38, 0x080c, 0xbcb6, 0x2009, 0x026e, - 0x2134, 0x96b4, 0x00ff, 0x9686, 0x0005, 0x0520, 0x9686, 0x000b, - 0x01c8, 0x2009, 0x026f, 0x2104, 0x9084, 0xff00, 0x1118, 0x9686, - 0x0009, 0x01c0, 0x9086, 0x1900, 0x1168, 0x9686, 0x0009, 0x0190, - 0x2001, 0x0004, 0x080c, 0x666a, 0x2001, 0x0028, 0x601a, 0x6007, - 0x0052, 0x0020, 0x2001, 0x0001, 0x080c, 0xbf7b, 0x002e, 0x00be, - 0x009e, 0x0005, 0x9286, 0x0139, 0x0160, 0x6014, 0x2048, 0x080c, - 0xd0d8, 0x0140, 0xa864, 0x9086, 0x0139, 0x0118, 0xa868, 0xd0fc, - 0x0108, 0x0c40, 0x6010, 0x2058, 0xb840, 0x9084, 0x00ff, 0x9005, - 0x0138, 0x8001, 0xb842, 0x601b, 0x000a, 0x6007, 0x0016, 0x08f0, - 0xb8a0, 0x9086, 0x007e, 0x1138, 0x00e6, 0x2071, 0x1800, 0x080c, - 0x60c1, 0x00ee, 0x0010, 0x080c, 0x3250, 0x0860, 0x2001, 0x0004, - 0x080c, 0x666a, 0x080c, 0xc1dc, 0x1140, 0x6003, 0x0001, 0x6007, - 0x0003, 0x080c, 0x9547, 0x0804, 0x9ab1, 0x080c, 0xbcb6, 0x9006, - 0x0804, 0xbf7b, 0x0489, 0x1160, 0x2001, 0x0008, 0x080c, 0x666a, - 0x6003, 0x0001, 0x6007, 0x0005, 0x080c, 0x9547, 0x0804, 0x9ab1, - 0x2001, 0x0001, 0x0804, 0xbf7b, 0x00f9, 0x1160, 0x2001, 0x000a, - 0x080c, 0x666a, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x9547, - 0x0804, 0x9ab1, 0x2001, 0x0001, 0x0804, 0xbf7b, 0x2009, 0x026e, - 0x2104, 0x9086, 0x0003, 0x1138, 0x2009, 0x026f, 0x2104, 0x9084, - 0xff00, 0x9086, 0x2a00, 0x0005, 0x9085, 0x0001, 0x0005, 0x00b6, - 0x00c6, 0x0016, 0x6110, 0x2158, 0x080c, 0x6733, 0x001e, 0x00ce, - 0x00be, 0x0005, 0x00b6, 0x00f6, 0x00e6, 0x00d6, 0x0036, 0x0016, - 0x6010, 0x2058, 0x2009, 0x1837, 0x2104, 0x9085, 0x0003, 0x200a, - 0x080c, 0xc287, 0x0560, 0x2009, 0x1837, 0x2104, 0xc0cd, 0x200a, - 0x080c, 0x6a9f, 0x0158, 0x9006, 0x2020, 0x2009, 0x002a, 0x080c, - 0xec31, 0x2001, 0x180c, 0x200c, 0xc195, 0x2102, 0x2019, 0x002a, - 0x2009, 0x0001, 0x080c, 0x321b, 0x00e6, 0x2071, 0x1800, 0x080c, - 0x3000, 0x00ee, 0x00c6, 0x0156, 0x20a9, 0x0781, 0x2009, 0x007f, - 0x080c, 0x334c, 0x8108, 0x1f04, 0xc220, 0x015e, 0x00ce, 0x080c, - 0xc1df, 0x2071, 0x0260, 0x2079, 0x0200, 0x7817, 0x0001, 0x2001, - 0x1837, 0x200c, 0xc1c5, 0x7018, 0xd0fc, 0x0110, 0xd0dc, 0x0118, - 0x7038, 0xd0dc, 0x1108, 0xc1c4, 0x7817, 0x0000, 0x2001, 0x1837, - 0x2102, 0x9184, 0x0050, 0x9086, 0x0050, 0x05d0, 0x2079, 0x0100, - 0x2e04, 0x9084, 0x00ff, 0x2069, 0x181f, 0x206a, 0x78e6, 0x0006, - 0x8e70, 0x2e04, 0x2069, 0x1820, 0x206a, 0x78ea, 0x7832, 0x7836, - 0x2010, 0x9084, 0xff00, 0x001e, 0x9105, 0x2009, 0x182c, 0x200a, - 0x2200, 0x9084, 0x00ff, 0x2008, 0x080c, 0x28bc, 0x080c, 0x7637, - 0x0170, 0x2071, 0x0260, 0x2069, 0x1982, 0x7048, 0x206a, 0x704c, - 0x6806, 0x7050, 0x680a, 0x7054, 0x680e, 0x080c, 0xd4ee, 0x0040, - 0x2001, 0x0006, 0x080c, 0x666a, 0x080c, 0x3279, 0x080c, 0xb2d3, - 0x001e, 0x003e, 0x00de, 0x00ee, 0x00fe, 0x00be, 0x0005, 0x0096, - 0x0026, 0x0036, 0x00e6, 0x0156, 0x2019, 0x182c, 0x231c, 0x83ff, - 0x01f0, 0x2071, 0x0260, 0x7200, 0x9294, 0x00ff, 0x7004, 0x9084, - 0xff00, 0x9205, 0x9306, 0x1198, 0x2011, 0x0276, 0x20a9, 0x0004, - 0x2b48, 0x2019, 0x000a, 0x080c, 0xc379, 0x1148, 0x2011, 0x027a, - 0x20a9, 0x0004, 0x2019, 0x0006, 0x080c, 0xc379, 0x1100, 0x015e, - 0x00ee, 0x003e, 0x002e, 0x009e, 0x0005, 0x00e6, 0x2071, 0x0260, - 0x7034, 0x9086, 0x0014, 0x11a8, 0x7038, 0x9086, 0x0800, 0x1188, - 0x703c, 0xd0ec, 0x0160, 0x9084, 0x0f00, 0x9086, 0x0100, 0x1138, - 0x7054, 0xd0a4, 0x1110, 0xd0ac, 0x0110, 0x9006, 0x0010, 0x9085, - 0x0001, 0x00ee, 0x0005, 0x00e6, 0x0096, 0x00c6, 0x0076, 0x0056, - 0x0046, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2029, 0x19f1, - 0x252c, 0x2021, 0x19f7, 0x2424, 0x2061, 0x1cd0, 0x2071, 0x1800, - 0x7254, 0x7074, 0x9202, 0x1a04, 0xc345, 0x080c, 0x8cf7, 0x0904, - 0xc33e, 0x080c, 0xec62, 0x0904, 0xc33e, 0x6720, 0x9786, 0x0007, - 0x0904, 0xc33e, 0x2500, 0x9c06, 0x0904, 0xc33e, 0x2400, 0x9c06, - 0x05e8, 0x3e08, 0x9186, 0x0002, 0x1148, 0x6010, 0x9005, 0x0130, - 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x1580, 0x00c6, 0x6000, - 0x9086, 0x0004, 0x1110, 0x080c, 0x1a8e, 0x9786, 0x000a, 0x0148, - 0x080c, 0xd2e0, 0x1130, 0x00ce, 0x080c, 0xbcb6, 0x080c, 0xb306, - 0x00e8, 0x6014, 0x2048, 0x080c, 0xd0d8, 0x01a8, 0x9786, 0x0003, - 0x1530, 0xa867, 0x0103, 0xa87c, 0xd0cc, 0x0130, 0x0096, 0xa878, - 0x2048, 0x080c, 0x0fc0, 0x009e, 0xab7a, 0xa877, 0x0000, 0x080c, - 0x6e92, 0x080c, 0xd2c3, 0x080c, 0xb306, 0x00ce, 0x9ce0, 0x0018, - 0x7068, 0x9c02, 0x1210, 0x0804, 0xc2e8, 0x012e, 0x000e, 0x002e, - 0x004e, 0x005e, 0x007e, 0x00ce, 0x009e, 0x00ee, 0x0005, 0x9786, - 0x0006, 0x1118, 0x080c, 0xebd4, 0x0c30, 0x9786, 0x0009, 0x1148, - 0x6000, 0x9086, 0x0004, 0x0d08, 0x2009, 0x004c, 0x080c, 0xb352, - 0x08e0, 0x9786, 0x000a, 0x0980, 0x0820, 0x220c, 0x2304, 0x9106, - 0x1130, 0x8210, 0x8318, 0x1f04, 0xc365, 0x9006, 0x0005, 0x2304, - 0x9102, 0x0218, 0x2001, 0x0001, 0x0008, 0x9006, 0x918d, 0x0001, - 0x0005, 0x0136, 0x01c6, 0x0016, 0x8906, 0x8006, 0x8007, 0x908c, - 0x003f, 0x21e0, 0x9084, 0xffc0, 0x9300, 0x2098, 0x3518, 0x20a9, - 0x0001, 0x220c, 0x4002, 0x910e, 0x1140, 0x8210, 0x8319, 0x1dc8, - 0x9006, 0x001e, 0x01ce, 0x013e, 0x0005, 0x220c, 0x9102, 0x0218, - 0x2001, 0x0001, 0x0010, 0x2001, 0x0000, 0x918d, 0x0001, 0x001e, - 0x01ce, 0x013e, 0x0005, 0x220c, 0x810f, 0x2304, 0x9106, 0x1130, - 0x8210, 0x8318, 0x1f04, 0xc3a3, 0x9006, 0x0005, 0x918d, 0x0001, - 0x0005, 0x6004, 0x908a, 0x0053, 0x1a0c, 0x0dc5, 0x080c, 0xd2cf, - 0x0120, 0x080c, 0xd2e0, 0x0168, 0x0028, 0x080c, 0x3279, 0x080c, - 0xd2e0, 0x0138, 0x080c, 0x99a5, 0x080c, 0xb2d3, 0x080c, 0x9ab1, - 0x0005, 0x080c, 0xbcb6, 0x0cb0, 0x9182, 0x0054, 0x1220, 0x9182, - 0x0040, 0x0208, 0x000a, 0x0005, 0xc3e8, 0xc3e8, 0xc3e8, 0xc3e8, - 0xc3e8, 0xc3e8, 0xc3e8, 0xc3e8, 0xc3e8, 0xc3e8, 0xc3e8, 0xc3ea, - 0xc3ea, 0xc3ea, 0xc3ea, 0xc3e8, 0xc3e8, 0xc3e8, 0xc3ea, 0xc3e8, - 0x080c, 0x0dc5, 0x600b, 0xffff, 0x6003, 0x0001, 0x6106, 0x080c, - 0x94ff, 0x0126, 0x2091, 0x8000, 0x080c, 0x9ab1, 0x012e, 0x0005, - 0x9186, 0x0013, 0x1128, 0x6004, 0x9082, 0x0040, 0x0804, 0xc482, - 0x9186, 0x0027, 0x1520, 0x080c, 0x99a5, 0x080c, 0x3250, 0x080c, - 0xd7f8, 0x0096, 0x6114, 0x2148, 0x080c, 0xd0d8, 0x0198, 0x080c, - 0xd2e0, 0x1118, 0x080c, 0xbcb6, 0x0068, 0xa867, 0x0103, 0xa87b, - 0x0029, 0xa877, 0x0000, 0xa97c, 0xc1c5, 0xa97e, 0x080c, 0x6e9f, - 0x080c, 0xd2c3, 0x009e, 0x080c, 0xb2d3, 0x0804, 0x9ab1, 0x9186, - 0x0014, 0x1120, 0x6004, 0x9082, 0x0040, 0x00b8, 0x9186, 0x0046, - 0x0150, 0x9186, 0x0045, 0x0138, 0x9186, 0x0053, 0x0120, 0x9186, - 0x0048, 0x190c, 0x0dc5, 0x080c, 0xd809, 0x0130, 0x6000, 0x9086, - 0x0002, 0x1110, 0x0804, 0xc4c0, 0x0005, 0x0002, 0xc45c, 0xc45a, - 0xc45a, 0xc45a, 0xc45a, 0xc45a, 0xc45a, 0xc45a, 0xc45a, 0xc45a, - 0xc45a, 0xc477, 0xc477, 0xc477, 0xc477, 0xc45a, 0xc477, 0xc45a, - 0xc477, 0xc45a, 0x080c, 0x0dc5, 0x080c, 0x99a5, 0x0096, 0x6114, - 0x2148, 0x080c, 0xd0d8, 0x0168, 0xa867, 0x0103, 0xa87b, 0x0006, - 0xa877, 0x0000, 0xa880, 0xc0ec, 0xa882, 0x080c, 0x6e9f, 0x080c, - 0xd2c3, 0x009e, 0x080c, 0xb2d3, 0x080c, 0x9ab1, 0x0005, 0x080c, - 0x99a5, 0x080c, 0xd2e0, 0x090c, 0xbcb6, 0x080c, 0xb2d3, 0x080c, - 0x9ab1, 0x0005, 0x0002, 0xc499, 0xc497, 0xc497, 0xc497, 0xc497, - 0xc497, 0xc497, 0xc497, 0xc497, 0xc497, 0xc497, 0xc4b0, 0xc4b0, - 0xc4b0, 0xc4b0, 0xc497, 0xc4ba, 0xc497, 0xc4b0, 0xc497, 0x080c, - 0x0dc5, 0x0096, 0x080c, 0x99a5, 0x6014, 0x2048, 0x2001, 0x1988, - 0x2004, 0x6042, 0xa97c, 0xd1ac, 0x0140, 0x6003, 0x0004, 0xa87c, - 0x9085, 0x0400, 0xa87e, 0x009e, 0x0005, 0x6003, 0x0002, 0x0cb8, - 0x080c, 0x99a5, 0x080c, 0xd7fb, 0x080c, 0xd800, 0x6003, 0x000f, - 0x0804, 0x9ab1, 0x080c, 0x99a5, 0x080c, 0xb2d3, 0x0804, 0x9ab1, - 0x9182, 0x0054, 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, - 0xc4dc, 0xc4dc, 0xc4dc, 0xc4dc, 0xc4dc, 0xc4de, 0xc5be, 0xc4dc, - 0xc5f2, 0xc4dc, 0xc4dc, 0xc4dc, 0xc4dc, 0xc4dc, 0xc4dc, 0xc4dc, - 0xc4dc, 0xc4dc, 0xc4dc, 0xc5f2, 0x080c, 0x0dc5, 0x00b6, 0x0096, - 0x6114, 0x2148, 0x7644, 0x96b4, 0x0fff, 0x86ff, 0x1528, 0x6010, - 0x2058, 0xb800, 0xd0bc, 0x1904, 0xc5ad, 0xa87b, 0x0000, 0xa867, - 0x0103, 0xae76, 0xa87c, 0xd0ac, 0x0128, 0xa834, 0xa938, 0x9115, - 0x190c, 0xc78b, 0x080c, 0x6cb9, 0x6210, 0x2258, 0xba3c, 0x82ff, - 0x0110, 0x8211, 0xba3e, 0x7044, 0xd0e4, 0x1904, 0xc58e, 0x080c, - 0xb2d3, 0x009e, 0x00be, 0x0005, 0x968c, 0x0c00, 0x0150, 0x6010, - 0x2058, 0xb800, 0xd0bc, 0x1904, 0xc592, 0x7348, 0xab92, 0x734c, - 0xab8e, 0x968c, 0x00ff, 0x9186, 0x0002, 0x0508, 0x9186, 0x0028, - 0x1118, 0xa87b, 0x001c, 0x00e8, 0xd6dc, 0x01a0, 0xa87b, 0x0015, - 0xa87c, 0xd0ac, 0x0170, 0xa938, 0xaa34, 0x2100, 0x9205, 0x0148, - 0x7048, 0x9106, 0x1118, 0x704c, 0x9206, 0x0118, 0xa992, 0xaa8e, - 0xc6dc, 0x0038, 0xd6d4, 0x0118, 0xa87b, 0x0007, 0x0010, 0xa87b, - 0x0000, 0xa867, 0x0103, 0xae76, 0x901e, 0xd6c4, 0x01d8, 0x9686, - 0x0100, 0x1130, 0x7064, 0x9005, 0x1118, 0xc6c4, 0x0804, 0xc4e5, - 0x735c, 0xab86, 0x83ff, 0x0170, 0x938a, 0x0009, 0x0210, 0x2019, - 0x0008, 0x0036, 0x2308, 0x2019, 0x0018, 0x2011, 0x0025, 0x080c, - 0xcc85, 0x003e, 0xd6cc, 0x0904, 0xc4fa, 0x7154, 0xa98a, 0x81ff, - 0x0904, 0xc4fa, 0x9192, 0x0021, 0x1278, 0x8304, 0x9098, 0x0018, - 0x2011, 0x0029, 0x080c, 0xcc85, 0x2011, 0x0205, 0x2013, 0x0000, - 0x080c, 0xd786, 0x0804, 0xc4fa, 0xa868, 0xd0fc, 0x0120, 0x2009, - 0x0020, 0xa98a, 0x0c50, 0x00a6, 0x2950, 0x080c, 0xcc24, 0x00ae, - 0x080c, 0xd786, 0x080c, 0xcc75, 0x0804, 0xc4fc, 0x080c, 0xd3d8, - 0x0804, 0xc509, 0xa87c, 0xd0ac, 0x0904, 0xc515, 0xa880, 0xd0bc, - 0x1904, 0xc515, 0x9684, 0x0400, 0x0130, 0xa838, 0xab34, 0x9305, - 0x0904, 0xc515, 0x00b8, 0x7348, 0xa838, 0x9306, 0x1198, 0x734c, - 0xa834, 0x931e, 0x0904, 0xc515, 0x0068, 0xa87c, 0xd0ac, 0x0904, - 0xc4ed, 0xa838, 0xa934, 0x9105, 0x0904, 0xc4ed, 0xa880, 0xd0bc, - 0x1904, 0xc4ed, 0x080c, 0xd412, 0x0804, 0xc509, 0x0096, 0x00f6, - 0x6003, 0x0003, 0x6007, 0x0043, 0x2079, 0x026c, 0x7c04, 0x7b00, - 0x7e0c, 0x7d08, 0x6014, 0x2048, 0xa87c, 0xd0ac, 0x0140, 0x6003, - 0x0002, 0x00fe, 0x009e, 0x0005, 0x2130, 0x2228, 0x0058, 0x2400, - 0xa9ac, 0x910a, 0x2300, 0xaab0, 0x9213, 0x2600, 0x9102, 0x2500, - 0x9203, 0x0e90, 0xac36, 0xab3a, 0xae46, 0xad4a, 0x00fe, 0x6043, - 0x0000, 0x2c10, 0x080c, 0x1be0, 0x080c, 0x9564, 0x080c, 0x9bd3, - 0x009e, 0x0005, 0x0005, 0x9182, 0x0054, 0x1220, 0x9182, 0x0040, - 0x0208, 0x000a, 0x0005, 0xc60f, 0xc60f, 0xc60f, 0xc60f, 0xc60f, - 0xc611, 0xc6a7, 0xc60f, 0xc60f, 0xc6be, 0xc74e, 0xc60f, 0xc60f, - 0xc60f, 0xc60f, 0xc763, 0xc60f, 0xc60f, 0xc60f, 0xc60f, 0x080c, - 0x0dc5, 0x0076, 0x00a6, 0x00e6, 0x0096, 0x2071, 0x0260, 0x6114, - 0x2150, 0x7644, 0xb676, 0x96b4, 0x0fff, 0xb77c, 0xc7e5, 0xb77e, - 0x6210, 0x00b6, 0x2258, 0xba3c, 0x82ff, 0x0110, 0x8211, 0xba3e, - 0x00be, 0x86ff, 0x0904, 0xc6a2, 0x9694, 0xff00, 0x9284, 0x0c00, - 0x0120, 0x7048, 0xb092, 0x704c, 0xb08e, 0x9284, 0x0300, 0x0904, - 0xc6a2, 0x080c, 0x100e, 0x090c, 0x0dc5, 0x2900, 0xb07a, 0xb77c, - 0xc7cd, 0xb77e, 0xa867, 0x0103, 0xb068, 0xa86a, 0xb06c, 0xa86e, - 0xb070, 0xa872, 0xae76, 0x968c, 0x0c00, 0x0120, 0x7348, 0xab92, - 0x734c, 0xab8e, 0x968c, 0x00ff, 0x9186, 0x0002, 0x0180, 0x9186, - 0x0028, 0x1118, 0xa87b, 0x001c, 0x0060, 0xd6dc, 0x0118, 0xa87b, - 0x0015, 0x0038, 0xd6d4, 0x0118, 0xa87b, 0x0007, 0x0010, 0xa87b, - 0x0000, 0xaf7e, 0xb080, 0xa882, 0xb084, 0xa886, 0x901e, 0xd6c4, - 0x0190, 0x735c, 0xab86, 0x83ff, 0x0170, 0x938a, 0x0009, 0x0210, - 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, 0x0018, 0x2011, 0x0025, - 0x080c, 0xcc85, 0x003e, 0xd6cc, 0x01e8, 0x7154, 0xa98a, 0x81ff, - 0x01c8, 0x9192, 0x0021, 0x1260, 0x8304, 0x9098, 0x0018, 0x2011, - 0x0029, 0x080c, 0xcc85, 0x2011, 0x0205, 0x2013, 0x0000, 0x0050, - 0xb068, 0xd0fc, 0x0120, 0x2009, 0x0020, 0xa98a, 0x0c68, 0x2950, - 0x080c, 0xcc24, 0x009e, 0x00ee, 0x00ae, 0x007e, 0x0005, 0x00f6, - 0x00a6, 0x6003, 0x0003, 0x2079, 0x026c, 0x7c04, 0x7b00, 0x7e0c, - 0x7d08, 0x6014, 0x2050, 0xb436, 0xb33a, 0xb646, 0xb54a, 0x00ae, - 0x00fe, 0x2c10, 0x080c, 0x1be0, 0x0804, 0xa6b6, 0x6003, 0x0002, - 0x6004, 0x9086, 0x0040, 0x11c8, 0x0096, 0x6014, 0x2048, 0xa87c, - 0xd0ac, 0x0160, 0x601c, 0xd084, 0x1130, 0x00f6, 0x2c00, 0x2078, - 0x080c, 0x1768, 0x00fe, 0x6003, 0x0004, 0x0010, 0x6003, 0x0002, - 0x009e, 0x080c, 0x99a5, 0x080c, 0x9ab1, 0x0096, 0x2001, 0x1988, - 0x2004, 0x6042, 0x080c, 0x9a61, 0x080c, 0x9bd3, 0x6114, 0x2148, - 0xa97c, 0xd1e4, 0x0904, 0xc749, 0xd1cc, 0x05c8, 0xa978, 0xa868, - 0xd0fc, 0x0540, 0x0016, 0xa87c, 0x0006, 0xa880, 0x0006, 0xa860, - 0x20e8, 0xa85c, 0x9080, 0x0019, 0x20a0, 0x810e, 0x810e, 0x810f, - 0x9184, 0x003f, 0x20e0, 0x9184, 0xffc0, 0x9080, 0x0019, 0x2098, - 0x0156, 0x20a9, 0x0020, 0x4003, 0x015e, 0x000e, 0xa882, 0x000e, - 0xc0cc, 0xa87e, 0x001e, 0xa874, 0x0006, 0x2148, 0x080c, 0x0fc0, - 0x001e, 0x0458, 0x0016, 0x080c, 0x0fc0, 0x009e, 0xa87c, 0xc0cc, - 0xa87e, 0xa974, 0x0016, 0x080c, 0xcc75, 0x001e, 0x00f0, 0xa867, - 0x0103, 0xa974, 0x9184, 0x00ff, 0x90b6, 0x0002, 0x0180, 0x9086, - 0x0028, 0x1118, 0xa87b, 0x001c, 0x0060, 0xd1dc, 0x0118, 0xa87b, - 0x0015, 0x0038, 0xd1d4, 0x0118, 0xa87b, 0x0007, 0x0010, 0xa87b, - 0x0000, 0x0016, 0x080c, 0x6cb9, 0x001e, 0xd1e4, 0x1120, 0x080c, - 0xb2d3, 0x009e, 0x0005, 0x080c, 0xd3d8, 0x0cd8, 0x6004, 0x9086, - 0x0040, 0x1120, 0x080c, 0x99a5, 0x080c, 0x9ab1, 0x2019, 0x0001, - 0x080c, 0xaa49, 0x6003, 0x0002, 0x080c, 0xd800, 0x080c, 0x9a61, - 0x080c, 0x9bd3, 0x0005, 0x6004, 0x9086, 0x0040, 0x1120, 0x080c, - 0x99a5, 0x080c, 0x9ab1, 0x2019, 0x0001, 0x080c, 0xaa49, 0x080c, - 0x9a61, 0x080c, 0x3250, 0x080c, 0xd7f8, 0x0096, 0x6114, 0x2148, - 0x080c, 0xd0d8, 0x0150, 0xa867, 0x0103, 0xa87b, 0x0029, 0xa877, - 0x0000, 0x080c, 0x6e9f, 0x080c, 0xd2c3, 0x009e, 0x080c, 0xb2d3, - 0x080c, 0x9bd3, 0x0005, 0xa87b, 0x0015, 0xd1fc, 0x0180, 0xa87b, - 0x0007, 0x8002, 0x8000, 0x810a, 0x9189, 0x0000, 0x0006, 0x0016, - 0x2009, 0x1a7d, 0x2104, 0x8000, 0x200a, 0x001e, 0x000e, 0xa992, - 0xa88e, 0x0005, 0x9182, 0x0054, 0x1220, 0x9182, 0x0040, 0x0208, - 0x000a, 0x0005, 0xc7be, 0xc7be, 0xc7be, 0xc7be, 0xc7be, 0xc7c0, - 0xc7be, 0xc7be, 0xc866, 0xc7be, 0xc7be, 0xc7be, 0xc7be, 0xc7be, - 0xc7be, 0xc7be, 0xc7be, 0xc7be, 0xc7be, 0xc998, 0x080c, 0x0dc5, - 0x0076, 0x00a6, 0x00e6, 0x0096, 0x2071, 0x0260, 0x6114, 0x2150, - 0x7644, 0xb676, 0x96b4, 0x0fff, 0xb77c, 0xc7e5, 0xb77e, 0x6210, - 0x00b6, 0x2258, 0xba3c, 0x82ff, 0x0110, 0x8211, 0xba3e, 0x00be, - 0x86ff, 0x0904, 0xc85f, 0x9694, 0xff00, 0x9284, 0x0c00, 0x0120, - 0x7048, 0xb092, 0x704c, 0xb08e, 0x9284, 0x0300, 0x0904, 0xc85f, - 0x9686, 0x0100, 0x1130, 0x7064, 0x9005, 0x1118, 0xc6c4, 0xb676, - 0x0c38, 0x080c, 0x100e, 0x090c, 0x0dc5, 0x2900, 0xb07a, 0xb77c, - 0x97bd, 0x0200, 0xb77e, 0xa867, 0x0103, 0xb068, 0xa86a, 0xb06c, - 0xa86e, 0xb070, 0xa872, 0x7044, 0x9084, 0xf000, 0x9635, 0xae76, - 0x968c, 0x0c00, 0x0120, 0x7348, 0xab92, 0x734c, 0xab8e, 0x968c, - 0x00ff, 0x9186, 0x0002, 0x0180, 0x9186, 0x0028, 0x1118, 0xa87b, - 0x001c, 0x0060, 0xd6dc, 0x0118, 0xa87b, 0x0015, 0x0038, 0xd6d4, - 0x0118, 0xa87b, 0x0007, 0x0010, 0xa87b, 0x0000, 0xaf7e, 0xb080, - 0xa882, 0xb084, 0xa886, 0x901e, 0xd6c4, 0x0190, 0x735c, 0xab86, - 0x83ff, 0x0170, 0x938a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, - 0x2308, 0x2019, 0x0018, 0x2011, 0x0025, 0x080c, 0xcc85, 0x003e, - 0xd6cc, 0x01e8, 0x7154, 0xa98a, 0x81ff, 0x01c8, 0x9192, 0x0021, - 0x1260, 0x8304, 0x9098, 0x0018, 0x2011, 0x0029, 0x080c, 0xcc85, - 0x2011, 0x0205, 0x2013, 0x0000, 0x0050, 0xb068, 0xd0fc, 0x0120, - 0x2009, 0x0020, 0xa98a, 0x0c68, 0x2950, 0x080c, 0xcc24, 0x080c, - 0x1a5a, 0x009e, 0x00ee, 0x00ae, 0x007e, 0x0005, 0x2001, 0x1988, - 0x2004, 0x6042, 0x0096, 0x6114, 0x2148, 0xa83c, 0xa940, 0x9105, - 0x1118, 0xa87c, 0xc0dc, 0xa87e, 0x6003, 0x0002, 0xa97c, 0xd1e4, - 0x0904, 0xc993, 0x6043, 0x0000, 0x6010, 0x00b6, 0x2058, 0xb800, - 0x00be, 0xd0bc, 0x1500, 0xd1cc, 0x0904, 0xc962, 0xa978, 0xa868, - 0xd0fc, 0x0904, 0xc923, 0x0016, 0xa87c, 0x0006, 0xa880, 0x0006, - 0x00a6, 0x2150, 0xb174, 0x9184, 0x00ff, 0x90b6, 0x0002, 0x0904, - 0xc8f0, 0x9086, 0x0028, 0x1904, 0xc8dc, 0xa87b, 0x001c, 0xb07b, - 0x001c, 0x0804, 0xc8f8, 0x6024, 0xd0f4, 0x11d0, 0xa838, 0xaa34, - 0x9205, 0x09c8, 0xa838, 0xaa90, 0x9206, 0x1120, 0xa88c, 0xaa34, - 0x9206, 0x0988, 0x6024, 0xd0d4, 0x1148, 0xa9ac, 0xa834, 0x9102, - 0x603a, 0xa9b0, 0xa838, 0x9103, 0x603e, 0x6024, 0xc0f5, 0x6026, - 0x6010, 0x00b6, 0x2058, 0xb83c, 0x8000, 0xb83e, 0x00be, 0x9006, - 0xa876, 0xa892, 0xa88e, 0xa87c, 0xc0e4, 0xa87e, 0xd0cc, 0x0140, - 0xc0cc, 0xa87e, 0x0096, 0xa878, 0x2048, 0x080c, 0x0fc0, 0x009e, - 0x080c, 0xd412, 0x0804, 0xc993, 0xd1dc, 0x0158, 0xa87b, 0x0015, - 0xb07b, 0x0015, 0x080c, 0xd6a6, 0x0118, 0xb174, 0xc1dc, 0xb176, - 0x0078, 0xd1d4, 0x0128, 0xa87b, 0x0007, 0xb07b, 0x0007, 0x0040, - 0xa87c, 0xd0ac, 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, 0xc78b, - 0xa87c, 0xb07e, 0xa890, 0xb092, 0xa88c, 0xb08e, 0xa860, 0x20e8, - 0xa85c, 0x9080, 0x0019, 0x20a0, 0x20a9, 0x0020, 0x8a06, 0x8006, - 0x8007, 0x9094, 0x003f, 0x22e0, 0x9084, 0xffc0, 0x9080, 0x0019, - 0x2098, 0x4003, 0x00ae, 0x000e, 0xa882, 0x000e, 0xc0cc, 0xa87e, - 0x080c, 0xd786, 0x001e, 0xa874, 0x0006, 0x2148, 0x080c, 0x0fc0, - 0x001e, 0x0804, 0xc98f, 0x0016, 0x00a6, 0x2150, 0xb174, 0x9184, - 0x00ff, 0x90b6, 0x0002, 0x01e0, 0x9086, 0x0028, 0x1128, 0xa87b, - 0x001c, 0xb07b, 0x001c, 0x00e0, 0xd1dc, 0x0158, 0xa87b, 0x0015, - 0xb07b, 0x0015, 0x080c, 0xd6a6, 0x0118, 0xb174, 0xc1dc, 0xb176, - 0x0078, 0xd1d4, 0x0128, 0xa87b, 0x0007, 0xb07b, 0x0007, 0x0040, - 0xa87c, 0xd0ac, 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, 0xc78b, - 0xa890, 0xb092, 0xa88c, 0xb08e, 0xa87c, 0xb07e, 0x00ae, 0x080c, - 0x0fc0, 0x009e, 0x080c, 0xd786, 0xa974, 0x0016, 0x080c, 0xcc75, - 0x001e, 0x0468, 0xa867, 0x0103, 0xa974, 0x9184, 0x00ff, 0x90b6, - 0x0002, 0x01b0, 0x9086, 0x0028, 0x1118, 0xa87b, 0x001c, 0x00d0, - 0xd1dc, 0x0148, 0xa87b, 0x0015, 0x080c, 0xd6a6, 0x0118, 0xa974, - 0xc1dc, 0xa976, 0x0078, 0xd1d4, 0x0118, 0xa87b, 0x0007, 0x0050, - 0xa87b, 0x0000, 0xa87c, 0xd0ac, 0x0128, 0xa834, 0xa938, 0x9115, - 0x190c, 0xc78b, 0xa974, 0x0016, 0x080c, 0x6cb9, 0x001e, 0xd1e4, - 0x1120, 0x080c, 0xb2d3, 0x009e, 0x0005, 0x080c, 0xd3d8, 0x0cd8, - 0x6114, 0x0096, 0x2148, 0xa97c, 0xd1e4, 0x190c, 0x1a7a, 0x009e, - 0x0005, 0x080c, 0x99a5, 0x0010, 0x080c, 0x9a61, 0x080c, 0xd0d8, - 0x01f0, 0x0096, 0x6114, 0x2148, 0x080c, 0xd2e0, 0x1118, 0x080c, - 0xbcb6, 0x00a0, 0xa867, 0x0103, 0x2009, 0x180c, 0x210c, 0xd18c, - 0x11b8, 0xd184, 0x1190, 0x6108, 0xa97a, 0x918e, 0x0029, 0x1110, - 0x080c, 0xef85, 0xa877, 0x0000, 0x080c, 0x6e9f, 0x009e, 0x080c, - 0xb2d3, 0x080c, 0x9ab1, 0x0804, 0x9bd3, 0xa87b, 0x0004, 0x0c90, - 0xa87b, 0x0004, 0x0c78, 0x9182, 0x0054, 0x1220, 0x9182, 0x0040, - 0x0208, 0x000a, 0x0005, 0xc9ef, 0xc9ef, 0xc9ef, 0xc9ef, 0xc9ef, - 0xc9f1, 0xc9ef, 0xc9ef, 0xc9ef, 0xc9ef, 0xc9ef, 0xc9ef, 0xc9ef, - 0xc9ef, 0xc9ef, 0xc9ef, 0xc9ef, 0xc9ef, 0xc9ef, 0xc9ef, 0x080c, - 0x0dc5, 0x080c, 0x57dd, 0x01f8, 0x6014, 0x7144, 0x918c, 0x0fff, - 0x9016, 0xd1c4, 0x0118, 0x7264, 0x9294, 0x00ff, 0x0096, 0x904d, - 0x0188, 0xa87b, 0x0000, 0xa864, 0x9086, 0x0139, 0x0128, 0xa867, - 0x0103, 0xa976, 0xaa96, 0x0030, 0xa897, 0x4000, 0xa99a, 0xaa9e, - 0x080c, 0x6e9f, 0x009e, 0x0804, 0xb2d3, 0x9182, 0x0085, 0x0002, - 0xca27, 0xca25, 0xca25, 0xca33, 0xca25, 0xca25, 0xca25, 0xca25, - 0xca25, 0xca25, 0xca25, 0xca25, 0xca25, 0x080c, 0x0dc5, 0x6003, - 0x0001, 0x6106, 0x080c, 0x94ff, 0x0126, 0x2091, 0x8000, 0x080c, - 0x9ab1, 0x012e, 0x0005, 0x0026, 0x0056, 0x00d6, 0x00e6, 0x2071, - 0x0260, 0x7224, 0x6216, 0x7220, 0x080c, 0xd0c6, 0x01f8, 0x2268, - 0x6800, 0x9086, 0x0000, 0x01d0, 0x6010, 0x6d10, 0x952e, 0x11b0, - 0x00c6, 0x2d60, 0x00d6, 0x080c, 0xcce6, 0x00de, 0x00ce, 0x0158, - 0x702c, 0xd084, 0x1118, 0x080c, 0xccb0, 0x0010, 0x6803, 0x0002, - 0x6007, 0x0086, 0x0028, 0x080c, 0xccd2, 0x0d90, 0x6007, 0x0087, - 0x6003, 0x0001, 0x080c, 0x94ff, 0x080c, 0x9ab1, 0x7220, 0x080c, - 0xd0c6, 0x0178, 0x6810, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, - 0x0140, 0x6824, 0xd0ec, 0x0128, 0x00c6, 0x2d60, 0x080c, 0xd412, - 0x00ce, 0x00ee, 0x00de, 0x005e, 0x002e, 0x0005, 0x9186, 0x0013, - 0x1160, 0x6004, 0x908a, 0x0085, 0x0a0c, 0x0dc5, 0x908a, 0x0092, - 0x1a0c, 0x0dc5, 0x9082, 0x0085, 0x00e2, 0x9186, 0x0027, 0x0120, - 0x9186, 0x0014, 0x190c, 0x0dc5, 0x080c, 0x99a5, 0x0096, 0x6014, - 0x2048, 0x080c, 0xd0d8, 0x0140, 0xa867, 0x0103, 0xa877, 0x0000, - 0xa87b, 0x0029, 0x080c, 0x6e9f, 0x009e, 0x080c, 0xb306, 0x0804, - 0x9ab1, 0xcab6, 0xcab8, 0xcab8, 0xcab6, 0xcab6, 0xcab6, 0xcab6, - 0xcab6, 0xcab6, 0xcab6, 0xcab6, 0xcab6, 0xcab6, 0x080c, 0x0dc5, - 0x080c, 0x99a5, 0x080c, 0xb306, 0x080c, 0x9ab1, 0x0005, 0x9186, - 0x0013, 0x1128, 0x6004, 0x9082, 0x0085, 0x2008, 0x04b8, 0x9186, - 0x0027, 0x11f8, 0x080c, 0x99a5, 0x080c, 0x3250, 0x080c, 0xd7f8, - 0x0096, 0x6014, 0x2048, 0x080c, 0xd0d8, 0x0150, 0xa867, 0x0103, - 0xa877, 0x0000, 0xa87b, 0x0029, 0x080c, 0x6e9f, 0x080c, 0xd2c3, - 0x009e, 0x080c, 0xb2d3, 0x080c, 0x9ab1, 0x0005, 0x080c, 0xb36d, - 0x0ce0, 0x9186, 0x0014, 0x1dd0, 0x080c, 0x99a5, 0x0096, 0x6014, - 0x2048, 0x080c, 0xd0d8, 0x0d60, 0xa867, 0x0103, 0xa877, 0x0000, - 0xa87b, 0x0006, 0xa880, 0xc0ec, 0xa882, 0x08f0, 0x0002, 0xcb0e, - 0xcb0c, 0xcb0c, 0xcb0c, 0xcb0c, 0xcb0c, 0xcb26, 0xcb0c, 0xcb0c, - 0xcb0c, 0xcb0c, 0xcb0c, 0xcb0c, 0x080c, 0x0dc5, 0x080c, 0x99a5, - 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, - 0x0035, 0x1118, 0x2001, 0x1986, 0x0010, 0x2001, 0x1987, 0x2004, - 0x601a, 0x6003, 0x000c, 0x080c, 0x9ab1, 0x0005, 0x080c, 0x99a5, - 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, - 0x0035, 0x1118, 0x2001, 0x1986, 0x0010, 0x2001, 0x1987, 0x2004, - 0x601a, 0x6003, 0x000e, 0x080c, 0x9ab1, 0x0005, 0x9182, 0x0092, - 0x1220, 0x9182, 0x0085, 0x0208, 0x0012, 0x0804, 0xb36d, 0xcb54, - 0xcb54, 0xcb54, 0xcb54, 0xcb56, 0xcba3, 0xcb54, 0xcb54, 0xcb54, - 0xcb54, 0xcb54, 0xcb54, 0xcb54, 0x080c, 0x0dc5, 0x0096, 0x6010, - 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0168, 0x6034, 0x908c, - 0xff00, 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, - 0x009e, 0x0804, 0xcbb7, 0x080c, 0xd0d8, 0x1118, 0x080c, 0xd2c3, - 0x0068, 0x6014, 0x2048, 0xa87c, 0xd0e4, 0x1110, 0x080c, 0xd2c3, - 0xa867, 0x0103, 0x080c, 0xd7c3, 0x080c, 0x6e9f, 0x00d6, 0x2c68, - 0x080c, 0xb27d, 0x01d0, 0x6003, 0x0001, 0x6007, 0x001e, 0x600b, - 0xffff, 0x2009, 0x026e, 0x210c, 0x613a, 0x2009, 0x026f, 0x210c, - 0x613e, 0x6910, 0x6112, 0x080c, 0xd554, 0x6954, 0x6156, 0x6023, - 0x0001, 0x080c, 0x94ff, 0x080c, 0x9ab1, 0x2d60, 0x00de, 0x080c, - 0xb2d3, 0x009e, 0x0005, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, - 0xd0bc, 0x05a0, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0035, - 0x0130, 0x9186, 0x001e, 0x0118, 0x9186, 0x0039, 0x1538, 0x00d6, - 0x2c68, 0x080c, 0xd759, 0x11f0, 0x080c, 0xb27d, 0x01d8, 0x6106, - 0x6003, 0x0001, 0x6023, 0x0001, 0x6910, 0x6112, 0x692c, 0x612e, - 0x6930, 0x6132, 0x6934, 0x918c, 0x00ff, 0x6136, 0x6938, 0x613a, - 0x693c, 0x613e, 0x6954, 0x6156, 0x080c, 0xd554, 0x080c, 0x94ff, - 0x080c, 0x9ab1, 0x2d60, 0x00de, 0x0804, 0xb2d3, 0x0096, 0x6014, - 0x2048, 0x080c, 0xd0d8, 0x01c8, 0xa867, 0x0103, 0xa880, 0xd0b4, - 0x0128, 0xc0ec, 0xa882, 0xa87b, 0x0006, 0x0048, 0xd0bc, 0x0118, - 0xa87b, 0x0002, 0x0020, 0xa87b, 0x0005, 0x080c, 0xd3d4, 0xa877, - 0x0000, 0x080c, 0x6e9f, 0x080c, 0xd2c3, 0x009e, 0x0804, 0xb2d3, - 0x0016, 0x0096, 0x6014, 0x2048, 0x080c, 0xd0d8, 0x0140, 0xa867, - 0x0103, 0xa87b, 0x0028, 0xa877, 0x0000, 0x080c, 0x6e9f, 0x009e, - 0x001e, 0x9186, 0x0013, 0x0148, 0x9186, 0x0014, 0x0130, 0x9186, - 0x0027, 0x0118, 0x080c, 0xb36d, 0x0030, 0x080c, 0x99a5, 0x080c, - 0xb306, 0x080c, 0x9ab1, 0x0005, 0x0056, 0x0066, 0x0096, 0x00a6, - 0x2029, 0x0001, 0x9182, 0x0101, 0x1208, 0x0010, 0x2009, 0x0100, - 0x2130, 0x8304, 0x9098, 0x0018, 0x2009, 0x0020, 0x2011, 0x0029, - 0x080c, 0xcc85, 0x96b2, 0x0020, 0xb004, 0x904d, 0x0110, 0x080c, - 0x0fc0, 0x080c, 0x100e, 0x0520, 0x8528, 0xa867, 0x0110, 0xa86b, - 0x0000, 0x2920, 0xb406, 0x968a, 0x003d, 0x1228, 0x2608, 0x2011, - 0x001b, 0x0499, 0x00a8, 0x96b2, 0x003c, 0x2009, 0x003c, 0x2950, - 0x2011, 0x001b, 0x0451, 0x0c28, 0x2001, 0x0205, 0x2003, 0x0000, - 0x00ae, 0x852f, 0x95ad, 0x0003, 0xb566, 0x95ac, 0x0000, 0x0048, - 0x2001, 0x0205, 0x2003, 0x0000, 0x00ae, 0x852f, 0x95ad, 0x0003, - 0xb566, 0x009e, 0x006e, 0x005e, 0x0005, 0x00a6, 0x89ff, 0x0158, - 0xa804, 0x9055, 0x0130, 0xa807, 0x0000, 0x080c, 0x6e9f, 0x2a48, - 0x0cb8, 0x080c, 0x6e9f, 0x00ae, 0x0005, 0x00f6, 0x2079, 0x0200, - 0x7814, 0x9085, 0x0080, 0x7816, 0xd184, 0x0108, 0x8108, 0x810c, - 0x20a9, 0x0001, 0xa860, 0x20e8, 0xa85c, 0x9200, 0x20a0, 0x20e1, - 0x0000, 0x2300, 0x9e00, 0x2098, 0x4003, 0x8318, 0x9386, 0x0020, - 0x1148, 0x2018, 0x2300, 0x9e00, 0x2098, 0x7814, 0x8000, 0x9085, - 0x0080, 0x7816, 0x8109, 0x1d80, 0x7817, 0x0000, 0x00fe, 0x0005, - 0x6920, 0x9186, 0x0003, 0x0118, 0x9186, 0x0002, 0x11d0, 0x00c6, - 0x00d6, 0x00e6, 0x2d60, 0x0096, 0x6014, 0x2048, 0x080c, 0xd0d8, - 0x0150, 0x2001, 0x0006, 0xa980, 0xc1d5, 0x080c, 0x710b, 0x080c, - 0x6e92, 0x080c, 0xd2c3, 0x009e, 0x080c, 0xb306, 0x00ee, 0x00de, - 0x00ce, 0x0005, 0x00c6, 0x702c, 0xd084, 0x1170, 0x6008, 0x2060, - 0x6020, 0x9086, 0x0002, 0x1140, 0x6104, 0x9186, 0x0085, 0x0118, - 0x9186, 0x008b, 0x1108, 0x9006, 0x00ce, 0x0005, 0x0066, 0x0126, - 0x2091, 0x8000, 0x2031, 0x0001, 0x6020, 0x9084, 0x000f, 0x0083, - 0x012e, 0x006e, 0x0005, 0x0126, 0x2091, 0x8000, 0x0066, 0x2031, - 0x0000, 0x6020, 0x9084, 0x000f, 0x001b, 0x006e, 0x012e, 0x0005, - 0xcd1d, 0xcd1d, 0xcd18, 0xcd3f, 0xcd0f, 0xcd18, 0xcd3f, 0xcd18, - 0xcd18, 0x9265, 0xcd18, 0xcd18, 0xcd18, 0xcd0f, 0xcd0f, 0x080c, - 0x0dc5, 0x0036, 0x2019, 0x0010, 0x080c, 0xe746, 0x003e, 0x0005, - 0x9006, 0x0005, 0x9085, 0x0001, 0x0005, 0x0096, 0x86ff, 0x11d8, - 0x6014, 0x2048, 0x080c, 0xd0d8, 0x01c0, 0xa864, 0x9086, 0x0139, - 0x1128, 0xa87b, 0x0005, 0xa883, 0x0000, 0x0028, 0x900e, 0x2001, - 0x0005, 0x080c, 0x710b, 0x080c, 0xd3d4, 0x080c, 0x6e92, 0x080c, - 0xb306, 0x9085, 0x0001, 0x009e, 0x0005, 0x9006, 0x0ce0, 0x6000, - 0x908a, 0x0010, 0x1a0c, 0x0dc5, 0x0002, 0xcd55, 0xcd85, 0xcd57, - 0xcda6, 0xcd80, 0xcd55, 0xcd18, 0xcd1d, 0xcd1d, 0xcd18, 0xcd18, - 0xcd18, 0xcd18, 0xcd18, 0xcd18, 0xcd18, 0x080c, 0x0dc5, 0x86ff, - 0x1520, 0x6020, 0x9086, 0x0006, 0x0500, 0x0096, 0x6014, 0x2048, - 0x080c, 0xd0d8, 0x0168, 0xa87c, 0xd0cc, 0x0140, 0x0096, 0xc0cc, - 0xa87e, 0xa878, 0x2048, 0x080c, 0x0fc0, 0x009e, 0x080c, 0xd3d4, - 0x009e, 0x080c, 0xd79d, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, - 0x0002, 0x080c, 0x94ff, 0x080c, 0x9ab1, 0x9085, 0x0001, 0x0005, - 0x0066, 0x080c, 0x1a8e, 0x006e, 0x0890, 0x00e6, 0x2071, 0x19e8, - 0x7024, 0x9c06, 0x1120, 0x080c, 0xa9d3, 0x00ee, 0x0840, 0x6020, - 0x9084, 0x000f, 0x9086, 0x0006, 0x1150, 0x0086, 0x0096, 0x2049, - 0x0001, 0x2c40, 0x080c, 0xaafb, 0x009e, 0x008e, 0x0010, 0x080c, - 0xa8d0, 0x00ee, 0x1904, 0xcd57, 0x0804, 0xcd18, 0x0036, 0x00e6, - 0x2071, 0x19e8, 0x703c, 0x9c06, 0x1138, 0x901e, 0x080c, 0xaa49, - 0x00ee, 0x003e, 0x0804, 0xcd57, 0x080c, 0xac2b, 0x00ee, 0x003e, - 0x1904, 0xcd57, 0x0804, 0xcd18, 0x00c6, 0x6020, 0x9084, 0x000f, - 0x0013, 0x00ce, 0x0005, 0xcdd9, 0xcea3, 0xd011, 0xcde3, 0xb306, - 0xcdd9, 0xe73c, 0xd805, 0xcea3, 0x9237, 0xd09d, 0xcdd2, 0xcdd2, - 0xcdd2, 0xcdd2, 0x080c, 0x0dc5, 0x080c, 0xd2e0, 0x1110, 0x080c, - 0xbcb6, 0x0005, 0x080c, 0x99a5, 0x080c, 0x9ab1, 0x0804, 0xb2d3, - 0x601b, 0x0001, 0x0005, 0x080c, 0xd0d8, 0x0130, 0x6014, 0x0096, - 0x2048, 0x2c00, 0xa896, 0x009e, 0x6000, 0x908a, 0x0010, 0x1a0c, - 0x0dc5, 0x0002, 0xce02, 0xce04, 0xce28, 0xce3c, 0xce62, 0xce02, - 0xcdd9, 0xcdd9, 0xcdd9, 0xce3c, 0xce3c, 0xce02, 0xce02, 0xce02, - 0xce02, 0xce46, 0x080c, 0x0dc5, 0x00e6, 0x6014, 0x0096, 0x2048, - 0xa880, 0xc0b5, 0xa882, 0x009e, 0x2071, 0x19e8, 0x7024, 0x9c06, - 0x01a0, 0x080c, 0xa8d0, 0x080c, 0xd79d, 0x6007, 0x0085, 0x6003, - 0x000b, 0x6023, 0x0002, 0x2001, 0x1987, 0x2004, 0x601a, 0x080c, - 0x94ff, 0x080c, 0x9ab1, 0x00ee, 0x0005, 0x601b, 0x0001, 0x0cd8, - 0x0096, 0x6014, 0x2048, 0xa880, 0xc0b5, 0xa882, 0x009e, 0x080c, - 0xd79d, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x080c, - 0x94ff, 0x080c, 0x9ab1, 0x0005, 0x0096, 0x601b, 0x0001, 0x6014, - 0x2048, 0xa880, 0xc0b5, 0xa882, 0x009e, 0x0005, 0x080c, 0x57dd, - 0x01b8, 0x6014, 0x0096, 0x904d, 0x0190, 0xa864, 0xa867, 0x0103, - 0xa87b, 0x0006, 0x9086, 0x0139, 0x1150, 0xa867, 0x0139, 0xa87b, - 0x0030, 0xa897, 0x4005, 0xa89b, 0x0004, 0x080c, 0x6e9f, 0x009e, - 0x0804, 0xb2d3, 0x6014, 0x0096, 0x904d, 0x05c0, 0xa97c, 0xd1e4, - 0x05a8, 0x2001, 0x180f, 0x2004, 0xd0c4, 0x0110, 0x009e, 0x0005, - 0xa884, 0x009e, 0x8003, 0x800b, 0x810b, 0x9108, 0x611a, 0x2001, - 0x0030, 0x2c08, 0x080c, 0x1611, 0x2001, 0x030c, 0x2004, 0x9086, - 0x0041, 0x1198, 0x6014, 0x0096, 0x904d, 0x090c, 0x0dc5, 0xa880, - 0xd0f4, 0x1130, 0xc0f5, 0xa882, 0x009e, 0x601b, 0x0002, 0x0068, - 0x009e, 0x00c6, 0x080c, 0x236e, 0x00ce, 0x6000, 0x9086, 0x0004, - 0x1120, 0x2009, 0x0048, 0x080c, 0xb352, 0x0005, 0x009e, 0x080c, - 0x1a8e, 0x0804, 0xce28, 0x6000, 0x908a, 0x0010, 0x1a0c, 0x0dc5, - 0x000b, 0x0005, 0xceba, 0xcde0, 0xcebc, 0xceba, 0xcebc, 0xcebc, - 0xcdda, 0xceba, 0xcdd4, 0xcdd4, 0xceba, 0xceba, 0xceba, 0xceba, - 0xceba, 0xceba, 0x080c, 0x0dc5, 0x6010, 0x00b6, 0x2058, 0xb804, - 0x9084, 0x00ff, 0x00be, 0x908a, 0x000c, 0x1a0c, 0x0dc5, 0x00b6, - 0x0013, 0x00be, 0x0005, 0xced7, 0xcfa8, 0xced9, 0xcf19, 0xced9, - 0xcf19, 0xced9, 0xcee7, 0xced7, 0xcf19, 0xced7, 0xcf08, 0x080c, - 0x0dc5, 0x6004, 0x908e, 0x0016, 0x05c0, 0x908e, 0x0004, 0x05a8, - 0x908e, 0x0002, 0x0590, 0x908e, 0x0052, 0x0904, 0xcfa4, 0x6004, - 0x080c, 0xd2e0, 0x0904, 0xcfc1, 0x908e, 0x0004, 0x1110, 0x080c, - 0x3279, 0x908e, 0x0021, 0x0904, 0xcfc5, 0x908e, 0x0022, 0x0904, - 0xd00c, 0x908e, 0x003d, 0x0904, 0xcfc5, 0x908e, 0x0039, 0x0904, - 0xcfc9, 0x908e, 0x0035, 0x0904, 0xcfc9, 0x908e, 0x001e, 0x0178, - 0x908e, 0x0001, 0x1140, 0x6010, 0x2058, 0xb804, 0x9084, 0x00ff, - 0x9086, 0x0006, 0x0110, 0x080c, 0x3250, 0x080c, 0xbcb6, 0x0804, - 0xb306, 0x00c6, 0x00d6, 0x6104, 0x9186, 0x0016, 0x0904, 0xcf95, - 0x9186, 0x0002, 0x1904, 0xcf6a, 0x2001, 0x1837, 0x2004, 0xd08c, - 0x11c8, 0x080c, 0x7637, 0x11b0, 0x080c, 0xd7e3, 0x0138, 0x080c, - 0x765a, 0x1120, 0x080c, 0x7541, 0x0804, 0xcff5, 0x2001, 0x197d, - 0x2003, 0x0001, 0x2001, 0x1800, 0x2003, 0x0001, 0x080c, 0x7563, - 0x0804, 0xcff5, 0x6010, 0x2058, 0xb8a0, 0x9086, 0x0080, 0x0130, - 0x2001, 0x1837, 0x2004, 0xd0ac, 0x1904, 0xcff5, 0xb8a0, 0x9082, - 0x0081, 0x1a04, 0xcff5, 0xb840, 0x9084, 0x00ff, 0x9005, 0x0190, - 0x8001, 0xb842, 0x6017, 0x0000, 0x6023, 0x0007, 0x601b, 0x0398, - 0x6043, 0x0000, 0x080c, 0xb27d, 0x0128, 0x2b00, 0x6012, 0x6023, - 0x0001, 0x0458, 0x00de, 0x00ce, 0x6004, 0x908e, 0x0002, 0x11a0, - 0x6010, 0x2058, 0xb8a0, 0x9086, 0x007e, 0x1170, 0x2009, 0x1837, - 0x2104, 0xc085, 0x200a, 0x00e6, 0x2071, 0x1800, 0x080c, 0x60c1, - 0x00ee, 0x080c, 0xbcb6, 0x0030, 0x080c, 0xbcb6, 0x080c, 0x3250, - 0x080c, 0xd7f8, 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x3279, - 0x012e, 0x00ee, 0x080c, 0xb306, 0x0005, 0x2001, 0x0002, 0x080c, - 0x666a, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x9547, 0x080c, - 0x9ab1, 0x00de, 0x00ce, 0x0c80, 0x080c, 0x3279, 0x0804, 0xcf15, - 0x00c6, 0x00d6, 0x6104, 0x9186, 0x0016, 0x0d38, 0x6010, 0x2058, - 0xb840, 0x9084, 0x00ff, 0x9005, 0x0904, 0xcf6a, 0x8001, 0xb842, - 0x6003, 0x0001, 0x080c, 0x9547, 0x080c, 0x9ab1, 0x00de, 0x00ce, - 0x0898, 0x080c, 0xbcb6, 0x0804, 0xcf17, 0x080c, 0xbcf2, 0x0804, - 0xcf17, 0x00d6, 0x2c68, 0x6104, 0x080c, 0xd759, 0x00de, 0x0118, - 0x080c, 0xb2d3, 0x0408, 0x6004, 0x8007, 0x6134, 0x918c, 0x00ff, - 0x9105, 0x6036, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, - 0x603c, 0x600a, 0x2001, 0x1987, 0x2004, 0x601a, 0x602c, 0x2c08, - 0x2060, 0x6024, 0xd0b4, 0x0108, 0xc085, 0xc0b5, 0x6026, 0x2160, - 0x080c, 0x94ff, 0x080c, 0x9ab1, 0x0005, 0x00de, 0x00ce, 0x080c, - 0xbcb6, 0x080c, 0x3250, 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, - 0x3279, 0x6017, 0x0000, 0x6023, 0x0007, 0x601b, 0x0398, 0x6043, - 0x0000, 0x012e, 0x00ee, 0x0005, 0x080c, 0xb708, 0x1904, 0xcfc1, - 0x0005, 0x6000, 0x908a, 0x0010, 0x1a0c, 0x0dc5, 0x0096, 0x00d6, - 0x001b, 0x00de, 0x009e, 0x0005, 0xd02c, 0xd02c, 0xd02c, 0xd02c, - 0xd02c, 0xd02c, 0xd02c, 0xd02c, 0xd02c, 0xcdd9, 0xd02c, 0xcde0, - 0xd02e, 0xcde0, 0xd048, 0xd02c, 0x080c, 0x0dc5, 0x6004, 0x9086, - 0x008b, 0x01b0, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0035, - 0x1130, 0x602c, 0x9080, 0x0009, 0x200c, 0xc185, 0x2102, 0x6007, - 0x008b, 0x6003, 0x000d, 0x080c, 0x94ff, 0x080c, 0x9ab1, 0x0005, - 0x080c, 0xd7d7, 0x0118, 0x080c, 0xd7ea, 0x0010, 0x080c, 0xd7f8, - 0x080c, 0xd2c3, 0x080c, 0xd0d8, 0x0570, 0x080c, 0x3250, 0x080c, - 0xd0d8, 0x0168, 0x6014, 0x2048, 0xa867, 0x0103, 0xa87b, 0x0006, - 0xa877, 0x0000, 0xa880, 0xc0ed, 0xa882, 0x080c, 0x6e9f, 0x2c68, - 0x080c, 0xb27d, 0x0150, 0x6810, 0x6012, 0x080c, 0xd554, 0x00c6, - 0x2d60, 0x080c, 0xb306, 0x00ce, 0x0008, 0x2d60, 0x6017, 0x0000, - 0x6023, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x9547, - 0x080c, 0x9ab1, 0x00c8, 0x080c, 0xd7d7, 0x0138, 0x6034, 0x9086, - 0x4000, 0x1118, 0x080c, 0x3250, 0x08d0, 0x6034, 0x908c, 0xff00, - 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, 0x080c, - 0x3250, 0x0868, 0x080c, 0xb306, 0x0005, 0x6000, 0x908a, 0x0010, - 0x1a0c, 0x0dc5, 0x0002, 0xd0b3, 0xd0b3, 0xd0b7, 0xd0b5, 0xd0c1, - 0xd0b3, 0xd0b3, 0xb306, 0xd0b3, 0xd0b3, 0xd0b3, 0xd0b3, 0xd0b3, - 0xd0b3, 0xd0b3, 0xd0b3, 0x080c, 0x0dc5, 0x080c, 0xac2b, 0x6114, - 0x0096, 0x2148, 0xa87b, 0x0006, 0x080c, 0x6e9f, 0x009e, 0x0804, - 0xb2d3, 0x601c, 0xd084, 0x190c, 0x1a8e, 0x0c88, 0x9284, 0x0007, - 0x1158, 0x9282, 0x1cd0, 0x0240, 0x2001, 0x181a, 0x2004, 0x9202, - 0x1218, 0x9085, 0x0001, 0x0005, 0x9006, 0x0ce8, 0x0096, 0x0028, - 0x0096, 0x0006, 0x6014, 0x2048, 0x000e, 0x0006, 0x9984, 0xf000, - 0x9086, 0xf000, 0x0110, 0x080c, 0x10b9, 0x000e, 0x009e, 0x0005, - 0x00e6, 0x00c6, 0x0036, 0x0006, 0x0126, 0x2091, 0x8000, 0x2061, - 0x1cd0, 0x2071, 0x1800, 0x7354, 0x7074, 0x9302, 0x1640, 0x6020, - 0x9206, 0x11f8, 0x080c, 0xd7e3, 0x0180, 0x9286, 0x0001, 0x1168, - 0x6004, 0x9086, 0x0004, 0x1148, 0x080c, 0x3250, 0x080c, 0xd7f8, - 0x00c6, 0x080c, 0xb306, 0x00ce, 0x0060, 0x080c, 0xd4ce, 0x0148, - 0x080c, 0xd2e0, 0x1110, 0x080c, 0xbcb6, 0x00c6, 0x080c, 0xb2d3, - 0x00ce, 0x9ce0, 0x0018, 0x7068, 0x9c02, 0x1208, 0x08a0, 0x012e, - 0x000e, 0x003e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x00c6, 0x0016, - 0x9188, 0x1000, 0x210c, 0x81ff, 0x0128, 0x2061, 0x1ab7, 0x6112, - 0x080c, 0x3250, 0x9006, 0x0010, 0x9085, 0x0001, 0x001e, 0x00ce, - 0x00ee, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0xb27d, - 0x01b0, 0x6656, 0x2b00, 0x6012, 0x080c, 0x57dd, 0x0118, 0x080c, - 0xd207, 0x0168, 0x080c, 0xd554, 0x6023, 0x0003, 0x2009, 0x004b, - 0x080c, 0xb352, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, - 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0xbaa0, 0x080c, 0xb325, - 0x0560, 0x6057, 0x0000, 0x2b00, 0x6012, 0x080c, 0xd554, 0x6023, - 0x0003, 0x0016, 0x080c, 0x96a4, 0x0076, 0x903e, 0x080c, 0x9577, - 0x2c08, 0x080c, 0xe91c, 0x007e, 0x001e, 0xd184, 0x0128, 0x080c, - 0xb2d3, 0x9085, 0x0001, 0x0070, 0x080c, 0x57dd, 0x0128, 0xd18c, - 0x1170, 0x080c, 0xd207, 0x0148, 0x2009, 0x004c, 0x080c, 0xb352, - 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x2900, - 0x6016, 0x0c90, 0x2009, 0x004d, 0x0010, 0x2009, 0x004e, 0x00f6, - 0x00c6, 0x0046, 0x0016, 0x080c, 0xb27d, 0x2c78, 0x05a0, 0x7e56, - 0x2b00, 0x7812, 0x7823, 0x0003, 0x0016, 0x2021, 0x0005, 0x080c, - 0xd219, 0x001e, 0x9186, 0x004d, 0x0118, 0x9186, 0x004e, 0x0148, - 0x2001, 0x1980, 0x200c, 0xd1fc, 0x0168, 0x2f60, 0x080c, 0xb2d3, - 0x00d0, 0x2001, 0x197f, 0x200c, 0xd1fc, 0x0120, 0x2f60, 0x080c, - 0xb2d3, 0x0088, 0x2f60, 0x080c, 0x57dd, 0x0138, 0xd18c, 0x1118, - 0x04f1, 0x0148, 0x0010, 0x2900, 0x7816, 0x001e, 0x0016, 0x080c, - 0xb352, 0x9085, 0x0001, 0x001e, 0x004e, 0x00ce, 0x00fe, 0x0005, - 0x00f6, 0x00c6, 0x0046, 0x080c, 0xb27d, 0x2c78, 0x0508, 0x7e56, - 0x2b00, 0x7812, 0x7823, 0x0003, 0x0096, 0x2021, 0x0004, 0x0489, - 0x009e, 0x2001, 0x197e, 0x200c, 0xd1fc, 0x0120, 0x2f60, 0x080c, - 0xb2d3, 0x0060, 0x2f60, 0x080c, 0x57dd, 0x0120, 0xd18c, 0x1160, - 0x0071, 0x0130, 0x2009, 0x0052, 0x080c, 0xb352, 0x9085, 0x0001, - 0x004e, 0x00ce, 0x00fe, 0x0005, 0x2900, 0x7816, 0x0c98, 0x00c6, - 0x080c, 0x4be4, 0x00ce, 0x1120, 0x080c, 0xb2d3, 0x9006, 0x0005, - 0xa867, 0x0000, 0xa86b, 0x8000, 0x2900, 0x6016, 0x9085, 0x0001, - 0x0005, 0x0096, 0x0076, 0x0126, 0x2091, 0x8000, 0x080c, 0x6858, - 0x0158, 0x2001, 0xd21e, 0x0006, 0x900e, 0x2400, 0x080c, 0x710b, - 0x080c, 0x6e9f, 0x000e, 0x0807, 0x2418, 0x080c, 0x993f, 0xbaa0, - 0x0086, 0x2041, 0x0001, 0x2039, 0x0001, 0x2608, 0x080c, 0x96bc, - 0x008e, 0x080c, 0x9577, 0x2f08, 0x2648, 0x080c, 0xe91c, 0xb93c, - 0x81ff, 0x090c, 0x978f, 0x080c, 0x9ab1, 0x012e, 0x007e, 0x009e, - 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0xb27d, 0x0190, - 0x660a, 0x2b08, 0x6112, 0x080c, 0xd554, 0x6023, 0x0001, 0x2900, - 0x6016, 0x2009, 0x001f, 0x080c, 0xb352, 0x9085, 0x0001, 0x012e, - 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, - 0x080c, 0xb325, 0x01b8, 0x660a, 0x2b08, 0x6112, 0x080c, 0xd554, - 0x6023, 0x0008, 0x2900, 0x6016, 0x00f6, 0x2c78, 0x080c, 0x1768, - 0x00fe, 0x2009, 0x0021, 0x080c, 0xb352, 0x9085, 0x0001, 0x012e, - 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x2009, 0x003d, 0x00c6, 0x0126, - 0x0016, 0x2091, 0x8000, 0x080c, 0xb27d, 0x0198, 0x660a, 0x2b08, - 0x6112, 0x080c, 0xd554, 0x6023, 0x0001, 0x2900, 0x6016, 0x001e, - 0x0016, 0x080c, 0xb352, 0x9085, 0x0001, 0x001e, 0x012e, 0x00ce, - 0x0005, 0x9006, 0x0cd0, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, - 0xb325, 0x0188, 0x2b08, 0x6112, 0x080c, 0xd554, 0x6023, 0x0001, - 0x2900, 0x6016, 0x2009, 0x0000, 0x080c, 0xb352, 0x9085, 0x0001, - 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x2009, 0x0044, 0x0830, - 0x2009, 0x0049, 0x0818, 0x0026, 0x00b6, 0x6210, 0x2258, 0xba3c, - 0x82ff, 0x0110, 0x8211, 0xba3e, 0x00be, 0x002e, 0x0005, 0x0006, - 0x0016, 0x6004, 0x908e, 0x0002, 0x0140, 0x908e, 0x0003, 0x0128, - 0x908e, 0x0004, 0x0110, 0x9085, 0x0001, 0x001e, 0x000e, 0x0005, - 0x0006, 0x0086, 0x0096, 0x6020, 0x9086, 0x0004, 0x01a8, 0x6014, - 0x904d, 0x080c, 0xd0d8, 0x0180, 0xa864, 0x9086, 0x0139, 0x0170, - 0x6020, 0x90c6, 0x0003, 0x0140, 0x90c6, 0x0002, 0x0128, 0xa868, - 0xd0fc, 0x0110, 0x9006, 0x0010, 0x9085, 0x0001, 0x009e, 0x008e, - 0x000e, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0xb325, - 0x0198, 0x2b08, 0x6112, 0x080c, 0xd554, 0x6023, 0x0001, 0x2900, - 0x6016, 0x080c, 0x3250, 0x2009, 0x0028, 0x080c, 0xb352, 0x9085, - 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x9186, 0x0015, - 0x11a8, 0x2011, 0x1824, 0x2204, 0x9086, 0x0074, 0x1178, 0x00b6, - 0x080c, 0xbf63, 0x00be, 0x080c, 0xc1df, 0x6003, 0x0001, 0x6007, - 0x0029, 0x080c, 0x9547, 0x080c, 0x9ab1, 0x0078, 0x6014, 0x0096, - 0x2048, 0xa868, 0x009e, 0xd0fc, 0x0148, 0x2001, 0x0001, 0x080c, - 0xd71a, 0x080c, 0xbcb6, 0x080c, 0xb2d3, 0x0005, 0x0096, 0x6014, - 0x904d, 0x090c, 0x0dc5, 0xa87b, 0x0030, 0xa883, 0x0000, 0xa897, - 0x4005, 0xa89b, 0x0004, 0xa867, 0x0139, 0x0126, 0x2091, 0x8000, - 0x080c, 0x6e9f, 0x012e, 0x009e, 0x080c, 0xb2d3, 0x0c30, 0x0096, - 0x9186, 0x0016, 0x1128, 0x2001, 0x0004, 0x080c, 0x666a, 0x00e8, - 0x9186, 0x0015, 0x1510, 0x2011, 0x1824, 0x2204, 0x9086, 0x0014, - 0x11e0, 0x6010, 0x00b6, 0x2058, 0x080c, 0x67bf, 0x00be, 0x080c, - 0xc2b5, 0x1198, 0x6010, 0x00b6, 0x2058, 0xb890, 0x00be, 0x9005, - 0x0160, 0x2001, 0x0006, 0x080c, 0x666a, 0x6014, 0x2048, 0xa868, - 0xd0fc, 0x0170, 0x080c, 0xb6dc, 0x0048, 0x6014, 0x2048, 0xa868, - 0xd0fc, 0x0528, 0x080c, 0xbcb6, 0x080c, 0xb2d3, 0x009e, 0x0005, - 0x6014, 0x6310, 0x2358, 0x904d, 0x090c, 0x0dc5, 0xa87b, 0x0000, - 0xa883, 0x0000, 0xa897, 0x4000, 0x900e, 0x080c, 0x6944, 0x1108, - 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0xa99a, 0x0126, 0x2091, - 0x8000, 0x080c, 0x6e9f, 0x012e, 0x080c, 0xb2d3, 0x08f8, 0x6014, - 0x904d, 0x090c, 0x0dc5, 0xa87b, 0x0030, 0xa883, 0x0000, 0xa897, - 0x4005, 0xa89b, 0x0004, 0xa867, 0x0139, 0x0126, 0x2091, 0x8000, - 0x080c, 0x6e9f, 0x012e, 0x080c, 0xb2d3, 0x0840, 0xa878, 0x9086, - 0x0005, 0x1108, 0x0009, 0x0005, 0xa880, 0xc0ad, 0xa882, 0x0005, - 0x6043, 0x0000, 0x6017, 0x0000, 0x6003, 0x0001, 0x6007, 0x0050, - 0x080c, 0x94ff, 0x080c, 0x9ab1, 0x0005, 0x00c6, 0x6010, 0x00b6, - 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0120, 0x6020, 0x9084, 0x000f, - 0x0013, 0x00ce, 0x0005, 0xcdd9, 0xd404, 0xd404, 0xd407, 0xec80, - 0xec9b, 0xec9e, 0xcdd9, 0xcdd9, 0xcdd9, 0xcdd9, 0xcdd9, 0xcdd9, - 0xcdd9, 0xcdd9, 0x080c, 0x0dc5, 0xa001, 0xa001, 0x0005, 0x0096, - 0x6014, 0x904d, 0x0118, 0xa87c, 0xd0e4, 0x1110, 0x009e, 0x0010, - 0x009e, 0x0005, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, - 0x0550, 0x2001, 0x1834, 0x2004, 0x9005, 0x1540, 0x00f6, 0x2c78, - 0x080c, 0xb27d, 0x0508, 0x7810, 0x6012, 0x080c, 0xd554, 0x7820, - 0x9086, 0x0003, 0x0128, 0x7808, 0x603a, 0x2f00, 0x603e, 0x0020, - 0x7808, 0x603e, 0x2f00, 0x603a, 0x602e, 0x6023, 0x0001, 0x6007, - 0x0035, 0x6003, 0x0001, 0x7954, 0x6156, 0x080c, 0x94ff, 0x080c, - 0x9ab1, 0x2f60, 0x00fe, 0x0005, 0x2f60, 0x00fe, 0x2001, 0x1988, - 0x2004, 0x6042, 0x0005, 0x0016, 0x0096, 0x6814, 0x2048, 0xa87c, - 0xd0e4, 0x0180, 0xc0e4, 0xa87e, 0xa877, 0x0000, 0xa893, 0x0000, - 0xa88f, 0x0000, 0xd0cc, 0x0130, 0xc0cc, 0xa87e, 0xa878, 0x2048, - 0x080c, 0x0fc0, 0x6830, 0x6036, 0x908e, 0x0001, 0x0148, 0x6803, - 0x0002, 0x9086, 0x0005, 0x0170, 0x9006, 0x602e, 0x6032, 0x00d0, - 0x681c, 0xc085, 0x681e, 0x6803, 0x0004, 0x6824, 0xc0f4, 0x9085, - 0x0c00, 0x6826, 0x6814, 0x2048, 0xa8ac, 0x6938, 0x9102, 0xa8b0, - 0x693c, 0x9103, 0x1e48, 0x683c, 0x602e, 0x6838, 0x9084, 0xfffc, - 0x683a, 0x6032, 0x2d00, 0x603a, 0x6808, 0x603e, 0x6910, 0x6112, - 0x6954, 0x6156, 0x6023, 0x0001, 0x6007, 0x0039, 0x6003, 0x0001, - 0x080c, 0x94ff, 0x080c, 0x9ab1, 0x009e, 0x001e, 0x0005, 0x6024, - 0xd0d4, 0x0510, 0xd0f4, 0x11f8, 0x6038, 0x940a, 0x603c, 0x9303, - 0x0230, 0x9105, 0x0120, 0x6024, 0xc0d4, 0xc0f5, 0x0098, 0x643a, - 0x633e, 0xac3e, 0xab42, 0x0046, 0x0036, 0x2400, 0xacac, 0x9402, - 0xa836, 0x2300, 0xabb0, 0x9303, 0xa83a, 0x003e, 0x004e, 0x6024, - 0xc0d4, 0x0000, 0x6026, 0x0005, 0xd0f4, 0x1138, 0xa83c, 0x603a, - 0xa840, 0x603e, 0x6024, 0xc0f5, 0x6026, 0x0005, 0x0006, 0x0016, - 0x6004, 0x908e, 0x0034, 0x01b8, 0x908e, 0x0035, 0x01a0, 0x908e, - 0x0036, 0x0188, 0x908e, 0x0037, 0x0170, 0x908e, 0x0038, 0x0158, - 0x908e, 0x0039, 0x0140, 0x908e, 0x003a, 0x0128, 0x908e, 0x003b, - 0x0110, 0x9085, 0x0001, 0x001e, 0x000e, 0x0005, 0x0006, 0x0016, - 0x0026, 0x0036, 0x00e6, 0x2001, 0x1982, 0x200c, 0x8000, 0x2014, - 0x2001, 0x0032, 0x080c, 0x9375, 0x2001, 0x1986, 0x82ff, 0x1110, - 0x2011, 0x0014, 0x2202, 0x2001, 0x1984, 0x200c, 0x8000, 0x2014, - 0x2071, 0x196c, 0x711a, 0x721e, 0x2001, 0x0064, 0x080c, 0x9375, - 0x2001, 0x1987, 0x82ff, 0x1110, 0x2011, 0x0014, 0x2202, 0x2001, - 0x1988, 0x9288, 0x000a, 0x2102, 0x2001, 0x1a98, 0x2102, 0x2001, - 0x0032, 0x080c, 0x1611, 0x080c, 0x6a84, 0x00ee, 0x003e, 0x002e, - 0x001e, 0x000e, 0x0005, 0x0006, 0x0016, 0x00e6, 0x2001, 0x1986, - 0x2003, 0x0028, 0x2001, 0x1987, 0x2003, 0x0014, 0x2071, 0x196c, - 0x701b, 0x0000, 0x701f, 0x07d0, 0x2001, 0x1988, 0x2009, 0x001e, - 0x2102, 0x2001, 0x1a98, 0x2102, 0x2001, 0x0032, 0x080c, 0x1611, - 0x00ee, 0x001e, 0x000e, 0x0005, 0x0096, 0x6058, 0x904d, 0x0110, - 0x080c, 0x1040, 0x009e, 0x0005, 0x0005, 0x00c6, 0x0126, 0x2091, - 0x8000, 0x080c, 0xb27d, 0x0180, 0x2b08, 0x6112, 0x0ca9, 0x6023, - 0x0001, 0x2900, 0x6016, 0x2009, 0x0033, 0x080c, 0xb352, 0x9085, - 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x0096, 0x00e6, - 0x00f6, 0x2071, 0x1800, 0x9186, 0x0015, 0x1520, 0x7090, 0x9086, - 0x0018, 0x0120, 0x7090, 0x9086, 0x0014, 0x11e0, 0x6014, 0x2048, - 0xaa3c, 0xd2e4, 0x1160, 0x2c78, 0x080c, 0x9d4c, 0x01d8, 0x707c, - 0xaa50, 0x9206, 0x1160, 0x7080, 0xaa54, 0x9206, 0x1140, 0x6210, - 0x00b6, 0x2258, 0xbaa0, 0x00be, 0x900e, 0x080c, 0x3299, 0x080c, - 0xb6dc, 0x0020, 0x080c, 0xbcb6, 0x080c, 0xb2d3, 0x00fe, 0x00ee, - 0x009e, 0x0005, 0x7060, 0xaa54, 0x9206, 0x0d48, 0x0c80, 0x00c6, - 0x0126, 0x2091, 0x8000, 0x080c, 0xb27d, 0x0188, 0x2b08, 0x6112, - 0x080c, 0xd554, 0x6023, 0x0001, 0x2900, 0x6016, 0x2009, 0x004d, - 0x080c, 0xb352, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, - 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x0016, 0x080c, 0xb27d, - 0x0180, 0x2b08, 0x6112, 0x080c, 0xd554, 0x6023, 0x0001, 0x2900, - 0x6016, 0x001e, 0x080c, 0xb352, 0x9085, 0x0001, 0x012e, 0x00ce, - 0x0005, 0x001e, 0x9006, 0x0cd0, 0x0016, 0x0026, 0x0036, 0x0046, - 0x0056, 0x0066, 0x0096, 0x00e6, 0x00f6, 0x2071, 0x1800, 0x9186, - 0x0015, 0x1568, 0x7190, 0x6014, 0x2048, 0xa814, 0x8003, 0x9106, - 0x1530, 0x20e1, 0x0000, 0x2001, 0x19a1, 0x2003, 0x0000, 0x6014, - 0x2048, 0xa830, 0x20a8, 0x8906, 0x8006, 0x8007, 0x9094, 0x003f, - 0x22e8, 0x9084, 0xffc0, 0x9080, 0x001b, 0x20a0, 0x2001, 0x19a1, - 0x0016, 0x200c, 0x080c, 0xde2e, 0x001e, 0xa804, 0x9005, 0x0110, - 0x2048, 0x0c38, 0x6014, 0x2048, 0xa867, 0x0103, 0x0010, 0x080c, - 0xbcb6, 0x080c, 0xb2d3, 0x00fe, 0x00ee, 0x009e, 0x006e, 0x005e, - 0x004e, 0x003e, 0x002e, 0x001e, 0x0005, 0x0096, 0x00e6, 0x00f6, - 0x2071, 0x1800, 0x9186, 0x0015, 0x11b8, 0x7090, 0x9086, 0x0004, - 0x1198, 0x6014, 0x2048, 0x2c78, 0x080c, 0x9d4c, 0x01a8, 0x707c, - 0xaa74, 0x9206, 0x1130, 0x7080, 0xaa78, 0x9206, 0x1110, 0x080c, - 0x3250, 0x080c, 0xb6dc, 0x0020, 0x080c, 0xbcb6, 0x080c, 0xb2d3, - 0x00fe, 0x00ee, 0x009e, 0x0005, 0x7060, 0xaa78, 0x9206, 0x0d78, - 0x0c80, 0x0096, 0x00e6, 0x00f6, 0x2071, 0x1800, 0x9186, 0x0015, - 0x1550, 0x7090, 0x9086, 0x0004, 0x1530, 0x6014, 0x2048, 0x2c78, - 0x080c, 0x9d4c, 0x05f0, 0x707c, 0xaacc, 0x9206, 0x1180, 0x7080, - 0xaad0, 0x9206, 0x1160, 0x080c, 0x3250, 0x0016, 0xa998, 0xaab0, - 0x9284, 0x1000, 0xc0fd, 0x080c, 0x5784, 0x001e, 0x0010, 0x080c, - 0x556f, 0x080c, 0xd0d8, 0x0508, 0xa87b, 0x0000, 0xa883, 0x0000, - 0xa897, 0x4000, 0x0080, 0x080c, 0xd0d8, 0x01b8, 0x6014, 0x2048, - 0x080c, 0x556f, 0x1d70, 0xa87b, 0x0030, 0xa883, 0x0000, 0xa897, - 0x4005, 0xa89b, 0x0004, 0x0126, 0x2091, 0x8000, 0xa867, 0x0139, - 0x080c, 0x6e9f, 0x012e, 0x080c, 0xb2d3, 0x00fe, 0x00ee, 0x009e, - 0x0005, 0x7060, 0xaad0, 0x9206, 0x0930, 0x0888, 0x0016, 0x0026, - 0xa87c, 0xd0ac, 0x0178, 0xa938, 0xaa34, 0x2100, 0x9205, 0x0150, - 0xa890, 0x9106, 0x1118, 0xa88c, 0x9206, 0x0120, 0xa992, 0xaa8e, - 0x9085, 0x0001, 0x002e, 0x001e, 0x0005, 0x00b6, 0x00d6, 0x0036, - 0x080c, 0xd0d8, 0x0904, 0xd716, 0x0096, 0x6314, 0x2348, 0xa87a, - 0xa982, 0x929e, 0x4000, 0x1580, 0x6310, 0x00c6, 0x2358, 0x2009, - 0x0000, 0xa868, 0xd0f4, 0x1140, 0x080c, 0x6944, 0x1108, 0xc185, - 0xb800, 0xd0bc, 0x0108, 0xc18d, 0xaa96, 0xa99a, 0x20a9, 0x0004, - 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0031, 0x20a0, 0xb8c4, 0x20e0, - 0xb8c8, 0x9080, 0x0006, 0x2098, 0x080c, 0x0f8b, 0x20a9, 0x0004, - 0xa85c, 0x9080, 0x0035, 0x20a0, 0xb8c8, 0x9080, 0x000a, 0x2098, - 0x080c, 0x0f8b, 0x00ce, 0x0090, 0xaa96, 0x3918, 0x9398, 0x0007, - 0x231c, 0x6004, 0x9086, 0x0016, 0x0110, 0xa89b, 0x0004, 0xaba2, - 0x6310, 0x2358, 0xb804, 0x9084, 0x00ff, 0xa89e, 0xa868, 0xc0f4, - 0xa86a, 0x080c, 0x6e92, 0x6017, 0x0000, 0x009e, 0x003e, 0x00de, - 0x00be, 0x0005, 0x0026, 0x0036, 0x0046, 0x00b6, 0x0096, 0x00f6, - 0x6214, 0x2248, 0x6210, 0x2258, 0x2079, 0x0260, 0x9096, 0x0000, - 0x11a0, 0xb814, 0x9084, 0x00ff, 0x900e, 0x080c, 0x2873, 0x2118, - 0x831f, 0x939c, 0xff00, 0x7838, 0x9084, 0x00ff, 0x931d, 0x7c3c, - 0x2011, 0x8018, 0x080c, 0x4c44, 0x00a8, 0x9096, 0x0001, 0x1148, - 0x89ff, 0x0180, 0xa89b, 0x000d, 0x7838, 0xa8a6, 0x783c, 0xa8aa, - 0x0048, 0x9096, 0x0002, 0x1130, 0xa89b, 0x000d, 0x7838, 0xa8a6, - 0x783c, 0xa8aa, 0x00fe, 0x009e, 0x00be, 0x004e, 0x003e, 0x002e, - 0x0005, 0x00c6, 0x0026, 0x0016, 0x9186, 0x0035, 0x0110, 0x6a38, - 0x0008, 0x6a2c, 0x080c, 0xd0c6, 0x01f0, 0x2260, 0x6120, 0x9186, - 0x0003, 0x0118, 0x9186, 0x0006, 0x1190, 0x6838, 0x9206, 0x0140, - 0x683c, 0x9206, 0x1160, 0x6108, 0x6838, 0x9106, 0x1140, 0x0020, - 0x6008, 0x693c, 0x9106, 0x1118, 0x6010, 0x6910, 0x9106, 0x001e, - 0x002e, 0x00ce, 0x0005, 0x9085, 0x0001, 0x0cc8, 0xa974, 0xd1cc, - 0x0198, 0x918c, 0x00ff, 0x918e, 0x0002, 0x1170, 0xa9a8, 0x918c, - 0x000f, 0x918e, 0x0001, 0x1140, 0xa87c, 0xd0ac, 0x0128, 0xa834, - 0xa938, 0x9115, 0x190c, 0xc78b, 0x0005, 0x0036, 0x2019, 0x0001, - 0x0010, 0x0036, 0x901e, 0x0499, 0x01e0, 0x080c, 0xd0d8, 0x01c8, - 0x080c, 0xd2c3, 0x6037, 0x4000, 0x6014, 0x6017, 0x0000, 0x0096, - 0x2048, 0xa87c, 0x080c, 0xd2e0, 0x1118, 0x080c, 0xbcb6, 0x0040, - 0xa867, 0x0103, 0xa877, 0x0000, 0x83ff, 0x1129, 0x080c, 0x6e9f, - 0x009e, 0x003e, 0x0005, 0xa880, 0xd0b4, 0x0128, 0xa87b, 0x0006, - 0xc0ec, 0xa882, 0x0048, 0xd0bc, 0x0118, 0xa87b, 0x0002, 0x0020, - 0xa87b, 0x0005, 0x080c, 0xd3d4, 0xa877, 0x0000, 0x0005, 0x2001, - 0x1810, 0x2004, 0xd0ec, 0x0005, 0x0006, 0x2001, 0x1810, 0x2004, - 0xd0f4, 0x000e, 0x0005, 0x0006, 0x2001, 0x1810, 0x2004, 0xd0e4, - 0x000e, 0x0005, 0x0036, 0x0046, 0x6010, 0x00b6, 0x2058, 0xbba0, - 0x00be, 0x2021, 0x0007, 0x080c, 0x4dfb, 0x004e, 0x003e, 0x0005, - 0x0c51, 0x1d81, 0x0005, 0x2001, 0x1986, 0x2004, 0x601a, 0x0005, - 0x2001, 0x1988, 0x2004, 0x6042, 0x0005, 0x080c, 0xb2d3, 0x0804, - 0x9ab1, 0x2001, 0x0109, 0x2004, 0xd084, 0x01e0, 0x0126, 0x2091, - 0x2800, 0x0006, 0x0016, 0x0026, 0x0036, 0x00f6, 0x00e6, 0x00c6, - 0x2079, 0x19e8, 0x2071, 0x1800, 0x2061, 0x0100, 0x080c, 0x93e2, - 0x00ce, 0x00ee, 0x00fe, 0x003e, 0x002e, 0x001e, 0x000e, 0x012e, - 0x9085, 0x0001, 0x0005, 0x00b6, 0x0066, 0x6000, 0x90b2, 0x0010, - 0x1a0c, 0x0dc5, 0x001b, 0x006e, 0x00be, 0x0005, 0xd846, 0xdf8d, - 0xe102, 0xd846, 0xd846, 0xd846, 0xd846, 0xd846, 0xd87d, 0xe186, - 0xd846, 0xd846, 0xd846, 0xd846, 0xd846, 0xd846, 0x080c, 0x0dc5, - 0x0066, 0x6000, 0x90b2, 0x0010, 0x1a0c, 0x0dc5, 0x0013, 0x006e, - 0x0005, 0xd861, 0xe6d5, 0xd861, 0xd861, 0xd861, 0xd861, 0xd861, - 0xd861, 0xe682, 0xe729, 0xd861, 0xedb4, 0xedea, 0xedb4, 0xedea, - 0xd861, 0x080c, 0x0dc5, 0x6000, 0x9082, 0x0010, 0x1a0c, 0x0dc5, - 0x6000, 0x000a, 0x0005, 0xd87b, 0xe364, 0xe433, 0xe456, 0xe516, - 0xd87b, 0xe5f5, 0xe59e, 0xe192, 0xe658, 0xe66d, 0xd87b, 0xd87b, - 0xd87b, 0xd87b, 0xd87b, 0x080c, 0x0dc5, 0x91b2, 0x0053, 0x1a0c, - 0x0dc5, 0x2100, 0x91b2, 0x0040, 0x1a04, 0xdcfd, 0x0002, 0xd8c7, - 0xdacb, 0xd8c7, 0xd8c7, 0xd8c7, 0xdad4, 0xd8c7, 0xd8c7, 0xd8c7, - 0xd8c7, 0xd8c7, 0xd8c7, 0xd8c7, 0xd8c7, 0xd8c7, 0xd8c7, 0xd8c7, - 0xd8c7, 0xd8c7, 0xd8c7, 0xd8c7, 0xd8c7, 0xd8c7, 0xd8c9, 0xd92c, - 0xd93b, 0xd99f, 0xd9ca, 0xda43, 0xdab6, 0xd8c7, 0xd8c7, 0xdad7, - 0xd8c7, 0xd8c7, 0xdaec, 0xdaf9, 0xd8c7, 0xd8c7, 0xd8c7, 0xd8c7, - 0xd8c7, 0xdb9f, 0xd8c7, 0xd8c7, 0xdbb3, 0xd8c7, 0xd8c7, 0xdb6e, - 0xd8c7, 0xd8c7, 0xd8c7, 0xdbcb, 0xd8c7, 0xd8c7, 0xd8c7, 0xdc48, - 0xd8c7, 0xd8c7, 0xd8c7, 0xd8c7, 0xd8c7, 0xd8c7, 0xdcc5, 0x080c, - 0x0dc5, 0x080c, 0x6a61, 0x1150, 0x2001, 0x1837, 0x2004, 0xd0cc, - 0x1128, 0x9084, 0x0009, 0x9086, 0x0008, 0x1140, 0x6007, 0x0009, - 0x602f, 0x0009, 0x6017, 0x0000, 0x0804, 0xdac4, 0x080c, 0x69fd, - 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x6210, 0x2258, 0xbaa0, - 0x0026, 0x2019, 0x0029, 0x080c, 0x96a4, 0x0076, 0x903e, 0x080c, - 0x9577, 0x2c08, 0x080c, 0xe91c, 0x007e, 0x001e, 0x001e, 0x002e, - 0x003e, 0x00ce, 0x00ee, 0x6610, 0x2658, 0x080c, 0x6733, 0xbe04, - 0x9684, 0x00ff, 0x9082, 0x0006, 0x1268, 0x0016, 0x0026, 0x6210, - 0x00b6, 0x2258, 0xbaa0, 0x00be, 0x2c08, 0x080c, 0xf015, 0x002e, - 0x001e, 0x1178, 0x080c, 0xe84e, 0x1904, 0xd997, 0x080c, 0xe7ea, - 0x1120, 0x6007, 0x0008, 0x0804, 0xdac4, 0x6007, 0x0009, 0x0804, - 0xdac4, 0x080c, 0xeab9, 0x0128, 0x080c, 0xe84e, 0x0d78, 0x0804, - 0xd997, 0x6017, 0x1900, 0x0c88, 0x080c, 0x3374, 0x1904, 0xdcfa, - 0x6106, 0x080c, 0xe78e, 0x6007, 0x0006, 0x0804, 0xdac4, 0x6007, - 0x0007, 0x0804, 0xdac4, 0x080c, 0xee26, 0x1904, 0xdcfa, 0x080c, - 0x3374, 0x1904, 0xdcfa, 0x00d6, 0x6610, 0x2658, 0xbe04, 0x9684, - 0x00ff, 0x9082, 0x0006, 0x1220, 0x2001, 0x0001, 0x080c, 0x6656, - 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x0188, 0x9686, 0x0004, - 0x0170, 0xbe04, 0x96b4, 0x00ff, 0x9686, 0x0006, 0x0140, 0x9686, - 0x0004, 0x0128, 0x9686, 0x0005, 0x0110, 0x00de, 0x0480, 0x00e6, - 0x2071, 0x0260, 0x7034, 0x9084, 0x0003, 0x1140, 0x7034, 0x9082, - 0x0014, 0x0220, 0x7030, 0x9084, 0x0003, 0x0130, 0x00ee, 0x6017, - 0x0000, 0x602f, 0x0007, 0x00b0, 0x00ee, 0x080c, 0xe8b2, 0x1190, - 0x9686, 0x0006, 0x1140, 0x0026, 0x6210, 0x2258, 0xbaa0, 0x900e, - 0x080c, 0x3299, 0x002e, 0x080c, 0x67bf, 0x6007, 0x000a, 0x00de, - 0x0804, 0xdac4, 0x6007, 0x000b, 0x00de, 0x0804, 0xdac4, 0x080c, - 0x3250, 0x080c, 0xd7f8, 0x6007, 0x0001, 0x0804, 0xdac4, 0x080c, - 0xee26, 0x1904, 0xdcfa, 0x080c, 0x3374, 0x1904, 0xdcfa, 0x2071, - 0x0260, 0x7034, 0x90b4, 0x0003, 0x1948, 0x90b2, 0x0014, 0x0a30, - 0x7030, 0x9084, 0x0003, 0x1910, 0x6610, 0x2658, 0xbe04, 0x9686, - 0x0707, 0x09e8, 0x0026, 0x6210, 0x2258, 0xbaa0, 0x900e, 0x080c, - 0x3299, 0x002e, 0x6007, 0x000c, 0x2001, 0x0001, 0x080c, 0xeff4, - 0x0804, 0xdac4, 0x080c, 0x6a61, 0x1140, 0x2001, 0x1837, 0x2004, - 0x9084, 0x0009, 0x9086, 0x0008, 0x1110, 0x0804, 0xd8d6, 0x080c, - 0x69fd, 0x6610, 0x2658, 0xbe04, 0x9684, 0x00ff, 0x9082, 0x0006, - 0x06c8, 0x1138, 0x0026, 0x2001, 0x0006, 0x080c, 0x6696, 0x002e, - 0x0050, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0004, 0x0120, 0x9686, - 0x0006, 0x1904, 0xd997, 0x080c, 0xe8bf, 0x1120, 0x6007, 0x000e, - 0x0804, 0xdac4, 0x0046, 0x6410, 0x2458, 0xbca0, 0x0046, 0x080c, - 0x3250, 0x080c, 0xd7f8, 0x004e, 0x0016, 0x9006, 0x2009, 0x1848, - 0x210c, 0xd1a4, 0x0148, 0x2009, 0x0029, 0x080c, 0xec31, 0x6010, - 0x2058, 0xb800, 0xc0e5, 0xb802, 0x001e, 0x004e, 0x6007, 0x0001, - 0x0804, 0xdac4, 0x2001, 0x0001, 0x080c, 0x6656, 0x0156, 0x0016, - 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, 0x1805, 0x2011, 0x0270, - 0x080c, 0xc365, 0x003e, 0x002e, 0x001e, 0x015e, 0x9005, 0x0168, - 0x96b4, 0xff00, 0x8637, 0x9682, 0x0004, 0x0a04, 0xd997, 0x9682, - 0x0007, 0x0a04, 0xd9f3, 0x0804, 0xd997, 0x6017, 0x1900, 0x6007, - 0x0009, 0x0804, 0xdac4, 0x080c, 0x6a61, 0x1140, 0x2001, 0x1837, - 0x2004, 0x9084, 0x0009, 0x9086, 0x0008, 0x1110, 0x0804, 0xd8d6, - 0x080c, 0x69fd, 0x6610, 0x2658, 0xbe04, 0x9684, 0x00ff, 0x0006, - 0x0016, 0x908e, 0x0001, 0x0118, 0x908e, 0x0000, 0x1118, 0x001e, - 0x000e, 0x0080, 0x001e, 0x000e, 0x9082, 0x0006, 0x06a0, 0x0150, - 0x96b4, 0xff00, 0x8637, 0x9686, 0x0004, 0x0120, 0x9686, 0x0006, - 0x1904, 0xd997, 0x080c, 0xe8ed, 0x1138, 0x080c, 0xe7ea, 0x1120, - 0x6007, 0x0010, 0x0804, 0xdac4, 0x0046, 0x6410, 0x2458, 0xbca0, - 0x0046, 0x080c, 0x3250, 0x080c, 0xd7f8, 0x004e, 0x0016, 0x9006, - 0x2009, 0x1848, 0x210c, 0xd1a4, 0x0148, 0x2009, 0x0029, 0x080c, - 0xec31, 0x6010, 0x2058, 0xb800, 0xc0e5, 0xb802, 0x001e, 0x004e, - 0x6007, 0x0001, 0x0448, 0x080c, 0xeab9, 0x0198, 0x0016, 0x968c, - 0x00ff, 0x9186, 0x0002, 0x0160, 0x9186, 0x0003, 0x0148, 0x001e, - 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x0920, 0x0804, 0xd997, - 0x001e, 0x6017, 0x1900, 0x6007, 0x0009, 0x0070, 0x080c, 0x3374, - 0x1904, 0xdcfa, 0x080c, 0xee26, 0x1904, 0xdcfa, 0x080c, 0xdecb, - 0x1904, 0xd997, 0x6007, 0x0012, 0x6003, 0x0001, 0x080c, 0x9547, - 0x080c, 0x9ab1, 0x0005, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, - 0x9547, 0x080c, 0x9ab1, 0x0cb0, 0x6007, 0x0005, 0x0c68, 0x080c, - 0xee26, 0x1904, 0xdcfa, 0x080c, 0x3374, 0x1904, 0xdcfa, 0x080c, - 0xdecb, 0x1904, 0xd997, 0x6007, 0x0020, 0x6003, 0x0001, 0x080c, - 0x9547, 0x080c, 0x9ab1, 0x0005, 0x080c, 0x3374, 0x1904, 0xdcfa, - 0x6007, 0x0023, 0x6003, 0x0001, 0x080c, 0x9547, 0x080c, 0x9ab1, - 0x0005, 0x080c, 0xee26, 0x1904, 0xdcfa, 0x080c, 0x3374, 0x1904, - 0xdcfa, 0x080c, 0xdecb, 0x1904, 0xd997, 0x0016, 0x0026, 0x00e6, - 0x2071, 0x0260, 0x2c08, 0x2011, 0x1820, 0x2214, 0x703c, 0x9206, - 0x11e0, 0x2011, 0x181f, 0x2214, 0x7038, 0x9084, 0x00ff, 0x9206, - 0x11a0, 0x7240, 0x080c, 0xd0c6, 0x0570, 0x2260, 0x6008, 0x9086, - 0xffff, 0x0120, 0x7244, 0x6008, 0x9206, 0x1528, 0x6020, 0x9086, - 0x0007, 0x1508, 0x080c, 0xb2d3, 0x04a0, 0x7244, 0x9286, 0xffff, - 0x0180, 0x2c08, 0x080c, 0xd0c6, 0x01b0, 0x2260, 0x7240, 0x6008, - 0x9206, 0x1188, 0x6010, 0x9190, 0x0004, 0x2214, 0x9206, 0x01b8, - 0x0050, 0x7240, 0x2c08, 0x9006, 0x080c, 0xebfb, 0x1180, 0x7244, - 0x9286, 0xffff, 0x01b0, 0x2160, 0x6007, 0x0026, 0x6017, 0x1700, - 0x7214, 0x9296, 0xffff, 0x1180, 0x6007, 0x0025, 0x0068, 0x6020, - 0x9086, 0x0007, 0x1d80, 0x6004, 0x9086, 0x0024, 0x1110, 0x080c, - 0xb2d3, 0x2160, 0x6007, 0x0025, 0x6003, 0x0001, 0x080c, 0x9547, - 0x080c, 0x9ab1, 0x00ee, 0x002e, 0x001e, 0x0005, 0x2001, 0x0001, - 0x080c, 0x6656, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, - 0x2019, 0x1805, 0x2011, 0x0276, 0x080c, 0xc365, 0x003e, 0x002e, - 0x001e, 0x015e, 0x0120, 0x6007, 0x0031, 0x0804, 0xdac4, 0x080c, - 0xbf7b, 0x080c, 0x7637, 0x1190, 0x0006, 0x0026, 0x0036, 0x080c, - 0x7651, 0x1138, 0x080c, 0x7932, 0x080c, 0x612e, 0x080c, 0x7563, - 0x0010, 0x080c, 0x760f, 0x003e, 0x002e, 0x000e, 0x0005, 0x080c, - 0x3374, 0x1904, 0xdcfa, 0x080c, 0xdecb, 0x1904, 0xd997, 0x6106, - 0x080c, 0xdee7, 0x1120, 0x6007, 0x002b, 0x0804, 0xdac4, 0x6007, - 0x002c, 0x0804, 0xdac4, 0x080c, 0xee26, 0x1904, 0xdcfa, 0x080c, - 0x3374, 0x1904, 0xdcfa, 0x080c, 0xdecb, 0x1904, 0xd997, 0x6106, - 0x080c, 0xdeec, 0x1120, 0x6007, 0x002e, 0x0804, 0xdac4, 0x6007, - 0x002f, 0x0804, 0xdac4, 0x080c, 0x3374, 0x1904, 0xdcfa, 0x00e6, - 0x00d6, 0x00c6, 0x6010, 0x2058, 0xb904, 0x9184, 0x00ff, 0x9086, - 0x0006, 0x0158, 0x9184, 0xff00, 0x8007, 0x9086, 0x0006, 0x0128, - 0x00ce, 0x00de, 0x00ee, 0x0804, 0xdacb, 0x080c, 0x57d9, 0xd0e4, - 0x0904, 0xdc45, 0x2071, 0x026c, 0x7010, 0x603a, 0x7014, 0x603e, - 0x7108, 0x720c, 0x080c, 0x6a9f, 0x0140, 0x6010, 0x2058, 0xb810, - 0x9106, 0x1118, 0xb814, 0x9206, 0x0510, 0x080c, 0x6a9b, 0x15b8, - 0x2069, 0x1800, 0x6880, 0x9206, 0x1590, 0x687c, 0x9106, 0x1578, - 0x7210, 0x080c, 0xd0c6, 0x0590, 0x080c, 0xddb8, 0x0578, 0x080c, - 0xecad, 0x0560, 0x622e, 0x6007, 0x0036, 0x6003, 0x0001, 0x080c, - 0x94ff, 0x080c, 0x9ab1, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x7214, - 0x9286, 0xffff, 0x0150, 0x080c, 0xd0c6, 0x01c0, 0x9280, 0x0002, - 0x2004, 0x7110, 0x9106, 0x1190, 0x08e0, 0x7210, 0x2c08, 0x9085, - 0x0001, 0x080c, 0xebfb, 0x2c10, 0x2160, 0x0140, 0x0890, 0x6007, - 0x0037, 0x602f, 0x0009, 0x6017, 0x1500, 0x08b8, 0x6007, 0x0037, - 0x602f, 0x0003, 0x6017, 0x1700, 0x0880, 0x6007, 0x0012, 0x0868, - 0x080c, 0x3374, 0x1904, 0xdcfa, 0x6010, 0x2058, 0xb804, 0x9084, - 0xff00, 0x8007, 0x9086, 0x0006, 0x1904, 0xdacb, 0x00e6, 0x00d6, - 0x00c6, 0x080c, 0x57d9, 0xd0e4, 0x0904, 0xdcbd, 0x2069, 0x1800, - 0x2071, 0x026c, 0x7008, 0x603a, 0x720c, 0x623e, 0x9286, 0xffff, - 0x1150, 0x7208, 0x00c6, 0x2c08, 0x9085, 0x0001, 0x080c, 0xebfb, - 0x2c10, 0x00ce, 0x05e8, 0x080c, 0xd0c6, 0x05d0, 0x7108, 0x9280, - 0x0002, 0x2004, 0x9106, 0x15a0, 0x00c6, 0x0026, 0x2260, 0x080c, - 0xcce6, 0x002e, 0x00ce, 0x7118, 0x918c, 0xff00, 0x810f, 0x9186, - 0x0001, 0x0178, 0x9186, 0x0005, 0x0118, 0x9186, 0x0007, 0x1198, - 0x9280, 0x0005, 0x2004, 0x9005, 0x0170, 0x080c, 0xddb8, 0x0904, - 0xdc3e, 0x0056, 0x7510, 0x7614, 0x080c, 0xecc6, 0x005e, 0x00ce, - 0x00de, 0x00ee, 0x0005, 0x6007, 0x003b, 0x602f, 0x0009, 0x6017, - 0x2a00, 0x6003, 0x0001, 0x080c, 0x94ff, 0x080c, 0x9ab1, 0x0c78, - 0x6007, 0x003b, 0x602f, 0x0003, 0x6017, 0x0300, 0x6003, 0x0001, - 0x080c, 0x94ff, 0x080c, 0x9ab1, 0x0c10, 0x6007, 0x003b, 0x602f, - 0x000b, 0x6017, 0x0000, 0x0804, 0xdc15, 0x00e6, 0x0026, 0x080c, - 0x6a61, 0x0550, 0x080c, 0x69fd, 0x080c, 0xee97, 0x1518, 0x2071, - 0x1800, 0x70dc, 0x9085, 0x0003, 0x70de, 0x00f6, 0x2079, 0x0100, - 0x72b0, 0x9284, 0x00ff, 0x707e, 0x78e6, 0x9284, 0xff00, 0x7280, - 0x9205, 0x7082, 0x78ea, 0x00fe, 0x70e7, 0x0000, 0x080c, 0x6a9f, - 0x0120, 0x2011, 0x1a01, 0x2013, 0x07d0, 0xd0ac, 0x1128, 0x080c, - 0x3000, 0x0010, 0x080c, 0xeecb, 0x002e, 0x00ee, 0x080c, 0xb2d3, - 0x0804, 0xdaca, 0x080c, 0xb2d3, 0x0005, 0x2600, 0x0002, 0xdd11, - 0xdd3f, 0xdd50, 0xdd11, 0xdd11, 0xdd13, 0xdd61, 0xdd11, 0xdd11, - 0xdd11, 0xdd2d, 0xdd11, 0xdd11, 0xdd11, 0xdd6c, 0xdd82, 0xddb3, - 0xdd11, 0x080c, 0x0dc5, 0x080c, 0xee26, 0x1d20, 0x080c, 0x3374, - 0x1d08, 0x7038, 0x6016, 0x6007, 0x0045, 0x6003, 0x0001, 0x080c, - 0x9547, 0x0005, 0x080c, 0x3250, 0x080c, 0xd7f8, 0x6007, 0x0001, - 0x6003, 0x0001, 0x080c, 0x9547, 0x0005, 0x080c, 0xee26, 0x1950, - 0x080c, 0x3374, 0x1938, 0x080c, 0xdecb, 0x1d60, 0x703c, 0x6016, - 0x6007, 0x004a, 0x6003, 0x0001, 0x080c, 0x9547, 0x0005, 0x080c, - 0x3374, 0x1904, 0xdcfa, 0x2009, 0x0041, 0x080c, 0xeed4, 0x6007, - 0x0047, 0x6003, 0x0001, 0x080c, 0x9547, 0x080c, 0x9ab1, 0x0005, - 0x080c, 0x3374, 0x1904, 0xdcfa, 0x2009, 0x0042, 0x080c, 0xeed4, - 0x6007, 0x0047, 0x6003, 0x0001, 0x080c, 0x9547, 0x080c, 0x9ab1, - 0x0005, 0x080c, 0x3374, 0x1904, 0xdcfa, 0x2009, 0x0046, 0x080c, - 0xeed4, 0x080c, 0xb2d3, 0x0005, 0x2001, 0x1824, 0x2004, 0x9082, - 0x00e1, 0x1268, 0x080c, 0xddd5, 0x0904, 0xdcfa, 0x6007, 0x004e, - 0x6003, 0x0001, 0x080c, 0x9547, 0x080c, 0x9ab1, 0x0005, 0x6007, - 0x0012, 0x0cb0, 0x6007, 0x004f, 0x6017, 0x0000, 0x7134, 0x918c, - 0x00ff, 0x81ff, 0x0508, 0x9186, 0x0001, 0x1160, 0x7140, 0x2001, - 0x19be, 0x2004, 0x9106, 0x11b0, 0x7144, 0x2001, 0x19bf, 0x2004, - 0x9106, 0x0190, 0x9186, 0x0002, 0x1168, 0x2011, 0x0276, 0x20a9, - 0x0004, 0x6010, 0x0096, 0x2048, 0x2019, 0x000a, 0x080c, 0xc379, - 0x009e, 0x0110, 0x6017, 0x0001, 0x6003, 0x0001, 0x080c, 0x9547, - 0x080c, 0x9ab1, 0x0005, 0x6007, 0x0050, 0x703c, 0x6016, 0x0ca0, - 0x0016, 0x00e6, 0x2071, 0x0260, 0x00b6, 0x00c6, 0x2260, 0x6010, - 0x2058, 0xb8cc, 0xd084, 0x0150, 0x7128, 0x6044, 0x9106, 0x1120, - 0x712c, 0x6048, 0x9106, 0x0110, 0x9006, 0x0010, 0x9085, 0x0001, - 0x00ce, 0x00be, 0x00ee, 0x001e, 0x0005, 0x0016, 0x0096, 0x0086, - 0x00e6, 0x01c6, 0x01d6, 0x0126, 0x2091, 0x8000, 0x2071, 0x1800, - 0x20e1, 0x0000, 0x2001, 0x19a1, 0x2003, 0x0000, 0x080c, 0x1027, - 0x05a0, 0x2900, 0x6016, 0x7090, 0x8004, 0xa816, 0x908a, 0x001e, - 0x02d0, 0xa833, 0x001e, 0x20a9, 0x001e, 0xa860, 0x20e8, 0xa85c, - 0x9080, 0x001b, 0x20a0, 0x2001, 0x19a1, 0x0016, 0x200c, 0x0471, - 0x001e, 0x81ff, 0x01b8, 0x2940, 0x080c, 0x1027, 0x01b0, 0x2900, - 0xa006, 0x2100, 0x0c18, 0xa832, 0x20a8, 0xa860, 0x20e8, 0xa85c, - 0x9080, 0x001b, 0x20a0, 0x2001, 0x19a1, 0x0016, 0x200c, 0x00b1, - 0x001e, 0x0000, 0x9085, 0x0001, 0x0048, 0x2071, 0x1800, 0x7093, - 0x0000, 0x6014, 0x2048, 0x080c, 0x0fc0, 0x9006, 0x012e, 0x01de, - 0x01ce, 0x00ee, 0x008e, 0x009e, 0x001e, 0x0005, 0x0006, 0x0016, - 0x0026, 0x0036, 0x00c6, 0x918c, 0xffff, 0x11b0, 0x080c, 0x23e2, - 0x2099, 0x026c, 0x2001, 0x0014, 0x3518, 0x9312, 0x0108, 0x1218, - 0x23a8, 0x4003, 0x0400, 0x20a8, 0x4003, 0x22a8, 0x8108, 0x080c, - 0x23e2, 0x2099, 0x0260, 0x0ca8, 0x080c, 0x23e2, 0x2061, 0x19a1, - 0x6004, 0x2098, 0x6008, 0x3518, 0x9312, 0x0108, 0x1218, 0x23a8, - 0x4003, 0x0048, 0x20a8, 0x4003, 0x22a8, 0x8108, 0x080c, 0x23e2, - 0x2099, 0x0260, 0x0ca8, 0x2061, 0x19a1, 0x2019, 0x0280, 0x3300, - 0x931e, 0x0110, 0x6006, 0x0020, 0x2001, 0x0260, 0x6006, 0x8108, - 0x2162, 0x9292, 0x0021, 0x9296, 0xffff, 0x620a, 0x00ce, 0x003e, - 0x002e, 0x001e, 0x000e, 0x0005, 0x0006, 0x0016, 0x0026, 0x0036, - 0x00c6, 0x81ff, 0x11b8, 0x080c, 0x23fa, 0x20a1, 0x024c, 0x2001, - 0x0014, 0x3518, 0x9312, 0x1218, 0x23a8, 0x4003, 0x0418, 0x20a8, - 0x4003, 0x82ff, 0x01f8, 0x22a8, 0x8108, 0x080c, 0x23fa, 0x20a1, - 0x0240, 0x0c98, 0x080c, 0x23fa, 0x2061, 0x19a4, 0x6004, 0x20a0, - 0x6008, 0x3518, 0x9312, 0x1218, 0x23a8, 0x4003, 0x0058, 0x20a8, - 0x4003, 0x82ff, 0x0138, 0x22a8, 0x8108, 0x080c, 0x23fa, 0x20a1, - 0x0240, 0x0c98, 0x2061, 0x19a4, 0x2019, 0x0260, 0x3400, 0x931e, - 0x0110, 0x6006, 0x0020, 0x2001, 0x0240, 0x6006, 0x8108, 0x2162, - 0x9292, 0x0021, 0x9296, 0xffff, 0x620a, 0x00ce, 0x003e, 0x002e, - 0x001e, 0x000e, 0x0005, 0x00b6, 0x0066, 0x6610, 0x2658, 0xbe04, - 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x0170, 0x9686, 0x0004, - 0x0158, 0xbe04, 0x96b4, 0x00ff, 0x9686, 0x0006, 0x0128, 0x9686, - 0x0004, 0x0110, 0x9085, 0x0001, 0x006e, 0x00be, 0x0005, 0x00d6, - 0x080c, 0xdf63, 0x00de, 0x0005, 0x00d6, 0x080c, 0xdf70, 0x1520, - 0x680c, 0x908c, 0xff00, 0x6820, 0x9084, 0x00ff, 0x9115, 0x6216, - 0x6824, 0x602e, 0xd1e4, 0x0130, 0x9006, 0x080c, 0xeff4, 0x2009, - 0x0001, 0x0078, 0xd1ec, 0x0180, 0x6920, 0x918c, 0x00ff, 0x6824, - 0x080c, 0x2873, 0x1148, 0x2001, 0x0001, 0x080c, 0xeff4, 0x2110, - 0x900e, 0x080c, 0x3299, 0x0018, 0x9085, 0x0001, 0x0008, 0x9006, - 0x00de, 0x0005, 0x00b6, 0x00c6, 0x080c, 0xb325, 0x05a8, 0x0016, - 0x0026, 0x00c6, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, - 0x2873, 0x1578, 0x080c, 0x66b9, 0x1560, 0xbe12, 0xbd16, 0x00ce, - 0x002e, 0x001e, 0x2b00, 0x6012, 0x080c, 0xee26, 0x11d8, 0x080c, - 0x3374, 0x11c0, 0x080c, 0xdecb, 0x0510, 0x2001, 0x0007, 0x080c, - 0x666a, 0x2001, 0x0007, 0x080c, 0x6696, 0x6017, 0x0000, 0x6023, - 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x9547, 0x080c, - 0x9ab1, 0x0010, 0x080c, 0xb2d3, 0x9085, 0x0001, 0x00ce, 0x00be, - 0x0005, 0x080c, 0xb2d3, 0x00ce, 0x002e, 0x001e, 0x0ca8, 0x080c, - 0xb2d3, 0x9006, 0x0c98, 0x2069, 0x026d, 0x6800, 0x9082, 0x0010, - 0x1228, 0x6017, 0x0000, 0x9085, 0x0001, 0x0008, 0x9006, 0x0005, - 0x6017, 0x0000, 0x2069, 0x026c, 0x6808, 0x9084, 0xff00, 0x9086, - 0x0800, 0x1190, 0x6904, 0x9186, 0x0018, 0x0118, 0x9186, 0x0014, - 0x1158, 0x810f, 0x6800, 0x9084, 0x00ff, 0x910d, 0x615a, 0x908e, - 0x0014, 0x0110, 0x908e, 0x0010, 0x0005, 0x6004, 0x90b2, 0x0053, - 0x1a0c, 0x0dc5, 0x91b6, 0x0013, 0x1130, 0x2008, 0x91b2, 0x0040, - 0x1a04, 0xe0d2, 0x040a, 0x91b6, 0x0027, 0x0198, 0x9186, 0x0015, - 0x0118, 0x9186, 0x0016, 0x1148, 0x080c, 0xd809, 0x0128, 0x6000, - 0x9086, 0x0002, 0x0904, 0xbcfd, 0x0005, 0x91b6, 0x0014, 0x190c, - 0x0dc5, 0x2001, 0x0007, 0x080c, 0x6696, 0x080c, 0x99a5, 0x080c, - 0xb306, 0x080c, 0x9ab1, 0x0005, 0xdffc, 0xdffe, 0xdffc, 0xdffc, - 0xdffc, 0xdffe, 0xe00d, 0xe0cb, 0xe051, 0xe0cb, 0xe079, 0xe0cb, - 0xe00d, 0xe0cb, 0xe0c3, 0xe0cb, 0xe0c3, 0xe0cb, 0xe0cb, 0xdffc, - 0xdffc, 0xdffc, 0xdffc, 0xdffc, 0xdffc, 0xdffc, 0xdffc, 0xdffc, - 0xdffc, 0xdffc, 0xdffe, 0xdffc, 0xe0cb, 0xdffc, 0xdffc, 0xe0cb, - 0xdffc, 0xe0c8, 0xe0cb, 0xdffc, 0xdffc, 0xdffc, 0xdffc, 0xe0cb, - 0xe0cb, 0xdffc, 0xe0cb, 0xe0cb, 0xdffc, 0xe008, 0xdffc, 0xdffc, - 0xdffc, 0xdffc, 0xe0c7, 0xe0cb, 0xdffc, 0xdffc, 0xe0cb, 0xe0cb, - 0xdffc, 0xdffc, 0xdffc, 0xdffc, 0x080c, 0x0dc5, 0x080c, 0x99a5, - 0x080c, 0xd7fb, 0x6003, 0x0002, 0x080c, 0x9ab1, 0x0804, 0xe0d1, - 0x9006, 0x080c, 0x6656, 0x0804, 0xe0cb, 0x080c, 0x6a9b, 0x1904, - 0xe0cb, 0x9006, 0x080c, 0x6656, 0x6010, 0x2058, 0xb810, 0x9086, - 0x00ff, 0x1140, 0x00f6, 0x2079, 0x1800, 0x78a8, 0x8000, 0x78aa, - 0x00fe, 0x00b8, 0x6010, 0x2058, 0xb8c0, 0x9005, 0x0904, 0xe0cb, - 0x080c, 0x33a5, 0x1904, 0xe0cb, 0x2001, 0x1800, 0x2004, 0x9086, - 0x0002, 0x1138, 0x00f6, 0x2079, 0x1800, 0x78a8, 0x8000, 0x78aa, - 0x00fe, 0x2001, 0x0002, 0x080c, 0x666a, 0x080c, 0x99a5, 0x6023, - 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x9547, 0x080c, - 0x9ab1, 0x6110, 0x2158, 0x2009, 0x0001, 0x080c, 0x884b, 0x0804, - 0xe0d1, 0x6610, 0x2658, 0xbe04, 0x96b4, 0xff00, 0x8637, 0x9686, - 0x0006, 0x0148, 0x9686, 0x0004, 0x0130, 0x080c, 0x9031, 0x2001, - 0x0004, 0x080c, 0x6696, 0x080c, 0xf043, 0x0904, 0xe0cb, 0x080c, - 0x99a5, 0x2001, 0x0004, 0x080c, 0x666a, 0x6023, 0x0001, 0x6003, - 0x0001, 0x6007, 0x0003, 0x080c, 0x9547, 0x080c, 0x9ab1, 0x0804, - 0xe0d1, 0x2001, 0x1800, 0x2004, 0x9086, 0x0003, 0x1158, 0x0036, - 0x0046, 0x6010, 0x2058, 0xbba0, 0x2021, 0x0006, 0x080c, 0x4dfb, - 0x004e, 0x003e, 0x2001, 0x0006, 0x080c, 0xe0ef, 0x6610, 0x2658, - 0xbe04, 0x0066, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x006e, - 0x0180, 0x2001, 0x0006, 0x080c, 0x6696, 0x9284, 0x00ff, 0x908e, - 0x0007, 0x0118, 0x908e, 0x0004, 0x1120, 0x2001, 0x0006, 0x080c, - 0x666a, 0x080c, 0x6a9b, 0x11f8, 0x2001, 0x1837, 0x2004, 0xd0a4, - 0x01d0, 0xbe04, 0x96b4, 0x00ff, 0x9686, 0x0006, 0x01a0, 0x00f6, - 0x2079, 0x1800, 0x78a8, 0x8000, 0x78aa, 0x00fe, 0x0804, 0xe039, - 0x2001, 0x0004, 0x0030, 0x2001, 0x0006, 0x0449, 0x0020, 0x0018, - 0x0010, 0x080c, 0x6696, 0x080c, 0x99a5, 0x080c, 0xb2d3, 0x080c, - 0x9ab1, 0x0005, 0x2600, 0x0002, 0xe0e6, 0xe0e6, 0xe0e6, 0xe0e6, - 0xe0e6, 0xe0e8, 0xe0e6, 0xe0e8, 0xe0e6, 0xe0e6, 0xe0e8, 0xe0e6, - 0xe0e6, 0xe0e6, 0xe0e8, 0xe0e8, 0xe0e8, 0xe0e8, 0x080c, 0x0dc5, - 0x080c, 0x99a5, 0x080c, 0xb2d3, 0x080c, 0x9ab1, 0x0005, 0x0016, - 0x00b6, 0x00d6, 0x6110, 0x2158, 0xb900, 0xd184, 0x0138, 0x080c, - 0x666a, 0x9006, 0x080c, 0x6656, 0x080c, 0x3279, 0x00de, 0x00be, - 0x001e, 0x0005, 0x6610, 0x2658, 0xb804, 0x9084, 0xff00, 0x8007, - 0x90b2, 0x000c, 0x1a0c, 0x0dc5, 0x91b6, 0x0015, 0x1110, 0x003b, - 0x0028, 0x91b6, 0x0016, 0x190c, 0x0dc5, 0x006b, 0x0005, 0xbd9f, - 0xbd9f, 0xbd9f, 0xbd9f, 0xe184, 0xbd9f, 0xe16e, 0xe12f, 0xbd9f, - 0xbd9f, 0xbd9f, 0xbd9f, 0xbd9f, 0xbd9f, 0xbd9f, 0xbd9f, 0xe184, - 0xbd9f, 0xe16e, 0xe175, 0xbd9f, 0xbd9f, 0xbd9f, 0xbd9f, 0x00f6, - 0x080c, 0x6a9b, 0x11d8, 0x080c, 0xd7e3, 0x11c0, 0x6010, 0x905d, - 0x01a8, 0xb8c0, 0x9005, 0x0190, 0x9006, 0x080c, 0x6656, 0x2001, - 0x0002, 0x080c, 0x666a, 0x6023, 0x0001, 0x6003, 0x0001, 0x6007, - 0x0002, 0x080c, 0x9547, 0x080c, 0x9ab1, 0x00f0, 0x2011, 0x0263, - 0x2204, 0x8211, 0x220c, 0x080c, 0x2873, 0x11b0, 0x080c, 0x6724, - 0x0118, 0x080c, 0xb2d3, 0x0080, 0xb810, 0x0006, 0xb814, 0x0006, - 0xb8c0, 0x0006, 0x080c, 0x6148, 0x000e, 0xb8c2, 0x000e, 0xb816, - 0x000e, 0xb812, 0x080c, 0xb2d3, 0x00fe, 0x0005, 0x6604, 0x96b6, - 0x001e, 0x1110, 0x080c, 0xb2d3, 0x0005, 0x080c, 0xc1dc, 0x1148, - 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x9547, 0x080c, 0x9ab1, - 0x0010, 0x080c, 0xb2d3, 0x0005, 0x0804, 0xb2d3, 0x6004, 0x908a, - 0x0053, 0x1a0c, 0x0dc5, 0x080c, 0x99a5, 0x080c, 0xb306, 0x080c, - 0x9ab1, 0x0005, 0x9182, 0x0040, 0x0002, 0xe1a9, 0xe1a9, 0xe1a9, - 0xe1a9, 0xe1ab, 0xe1a9, 0xe1a9, 0xe1a9, 0xe1a9, 0xe1a9, 0xe1a9, - 0xe1a9, 0xe1a9, 0xe1a9, 0xe1a9, 0xe1a9, 0xe1a9, 0xe1a9, 0xe1a9, - 0xe1a9, 0x080c, 0x0dc5, 0x0096, 0x00b6, 0x00d6, 0x00e6, 0x00f6, - 0x0046, 0x0026, 0x6210, 0x2258, 0xb8bc, 0x9005, 0x11a8, 0x6106, - 0x2071, 0x0260, 0x7444, 0x94a4, 0xff00, 0x0904, 0xe211, 0x080c, - 0xefe8, 0x1170, 0x9486, 0x2000, 0x1158, 0x2009, 0x0001, 0x2011, - 0x0200, 0x080c, 0x8a50, 0x0020, 0x9026, 0x080c, 0xee6b, 0x0c38, - 0x080c, 0x100e, 0x090c, 0x0dc5, 0x6003, 0x0007, 0xa867, 0x010d, - 0x9006, 0xa802, 0xa86a, 0xac8a, 0x2c00, 0xa88e, 0x6008, 0xa8e2, - 0x6010, 0x2058, 0xb8a0, 0x7130, 0xa97a, 0x0016, 0xa876, 0xa87f, - 0x0000, 0xa883, 0x0000, 0xa887, 0x0036, 0x080c, 0x6e9f, 0x001e, - 0x080c, 0xefe8, 0x1904, 0xe271, 0x9486, 0x2000, 0x1130, 0x2019, - 0x0017, 0x080c, 0xeba1, 0x0804, 0xe271, 0x9486, 0x0200, 0x1120, - 0x080c, 0xeb38, 0x0804, 0xe271, 0x9486, 0x0400, 0x0120, 0x9486, - 0x1000, 0x1904, 0xe271, 0x2019, 0x0002, 0x080c, 0xeb53, 0x0804, - 0xe271, 0x2069, 0x1a74, 0x6a00, 0xd284, 0x0904, 0xe2db, 0x9284, - 0x0300, 0x1904, 0xe2d4, 0x6804, 0x9005, 0x0904, 0xe2bc, 0x2d78, - 0x6003, 0x0007, 0x080c, 0x1027, 0x0904, 0xe27d, 0x7800, 0xd08c, - 0x1118, 0x7804, 0x8001, 0x7806, 0x6017, 0x0000, 0x2001, 0x180f, - 0x2004, 0xd084, 0x1904, 0xe2df, 0x9006, 0xa802, 0xa867, 0x0116, - 0xa86a, 0x6008, 0xa8e2, 0x2c00, 0xa87a, 0x6010, 0x2058, 0xb8a0, - 0x7130, 0xa9b6, 0xa876, 0xb928, 0xa9ba, 0xb92c, 0xa9be, 0xb930, - 0xa9c2, 0xb934, 0xa9c6, 0xa883, 0x003d, 0x7044, 0x9084, 0x0003, - 0x9080, 0xe279, 0x2005, 0xa87e, 0x20a9, 0x000a, 0x2001, 0x0270, - 0xaa5c, 0x9290, 0x0021, 0x2009, 0x0205, 0x200b, 0x0080, 0x20e1, - 0x0000, 0xab60, 0x23e8, 0x2098, 0x22a0, 0x4003, 0x200b, 0x0000, - 0x2001, 0x027a, 0x200c, 0xa9b2, 0x8000, 0x200c, 0xa9ae, 0x080c, - 0x6e9f, 0x002e, 0x004e, 0x00fe, 0x00ee, 0x00de, 0x00be, 0x009e, - 0x0005, 0x0000, 0x0080, 0x0040, 0x0000, 0x2001, 0x1810, 0x2004, - 0xd084, 0x0120, 0x080c, 0x100e, 0x1904, 0xe226, 0x6017, 0xf100, - 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x94ff, 0x080c, 0x9ab1, - 0x0c00, 0x2069, 0x0260, 0x6848, 0x9084, 0xff00, 0x9086, 0x1200, - 0x1198, 0x686c, 0x9084, 0x00ff, 0x0016, 0x6114, 0x918c, 0xf700, - 0x910d, 0x6116, 0x001e, 0x6003, 0x0001, 0x6007, 0x0043, 0x080c, - 0x94ff, 0x080c, 0x9ab1, 0x0828, 0x6868, 0x602e, 0x686c, 0x6032, - 0x6017, 0xf200, 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x94ff, - 0x080c, 0x9ab1, 0x0804, 0xe271, 0x2001, 0x180e, 0x2004, 0xd0ec, - 0x0120, 0x2011, 0x8049, 0x080c, 0x4c44, 0x6017, 0xf300, 0x0010, - 0x6017, 0xf100, 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x94ff, - 0x080c, 0x9ab1, 0x0804, 0xe271, 0x6017, 0xf500, 0x0c98, 0x6017, - 0xf600, 0x0804, 0xe291, 0x6017, 0xf200, 0x0804, 0xe291, 0xa867, - 0x0146, 0xa86b, 0x0000, 0x6008, 0xa886, 0x2c00, 0xa87a, 0x7044, - 0x9084, 0x0003, 0x9080, 0xe279, 0x2005, 0xa87e, 0x2928, 0x6010, - 0x2058, 0xb8a0, 0xa876, 0xb828, 0xa88a, 0xb82c, 0xa88e, 0xb830, - 0xa892, 0xb834, 0xa896, 0xa883, 0x003d, 0x2009, 0x0205, 0x2104, - 0x9085, 0x0080, 0x200a, 0x20e1, 0x0000, 0x2011, 0x0210, 0x2214, - 0x9294, 0x0fff, 0xaaa2, 0x9282, 0x0111, 0x1a0c, 0x0dc5, 0x8210, - 0x821c, 0x2001, 0x026c, 0x2098, 0xa860, 0x20e8, 0xa85c, 0x9080, - 0x0029, 0x20a0, 0x2011, 0xe35b, 0x2041, 0x0001, 0x223d, 0x9784, - 0x00ff, 0x9322, 0x1208, 0x2300, 0x20a8, 0x4003, 0x931a, 0x0530, - 0x8210, 0xd7fc, 0x1130, 0x8d68, 0x2d0a, 0x2001, 0x0260, 0x2098, - 0x0c68, 0x2950, 0x080c, 0x1027, 0x0170, 0x2900, 0xb002, 0xa867, - 0x0147, 0xa86b, 0x0000, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x001b, - 0x20a0, 0x8840, 0x08d8, 0x2548, 0xa800, 0x902d, 0x0118, 0x080c, - 0x1040, 0x0cc8, 0x080c, 0x1040, 0x0804, 0xe27d, 0x2548, 0x8847, - 0x9885, 0x0046, 0xa866, 0x2009, 0x0205, 0x200b, 0x0000, 0x080c, - 0xebd4, 0x0804, 0xe271, 0x8010, 0x0004, 0x801a, 0x0006, 0x8018, - 0x0008, 0x8016, 0x000a, 0x8014, 0x9186, 0x0013, 0x1160, 0x6004, - 0x908a, 0x0054, 0x1a0c, 0x0dc5, 0x9082, 0x0040, 0x0a0c, 0x0dc5, - 0x2008, 0x0804, 0xe3ea, 0x9186, 0x0051, 0x0108, 0x0048, 0x080c, - 0xd809, 0x0500, 0x6000, 0x9086, 0x0002, 0x11e0, 0x0804, 0xe433, - 0x9186, 0x0027, 0x0190, 0x9186, 0x0048, 0x0128, 0x9186, 0x0014, - 0x0160, 0x190c, 0x0dc5, 0x080c, 0xd809, 0x0160, 0x6000, 0x9086, - 0x0004, 0x190c, 0x0dc5, 0x0804, 0xe516, 0x6004, 0x9082, 0x0040, - 0x2008, 0x001a, 0x080c, 0xb36d, 0x0005, 0xe3b1, 0xe3b3, 0xe3b3, - 0xe3da, 0xe3b1, 0xe3b1, 0xe3b1, 0xe3b1, 0xe3b1, 0xe3b1, 0xe3b1, - 0xe3b1, 0xe3b1, 0xe3b1, 0xe3b1, 0xe3b1, 0xe3b1, 0xe3b1, 0xe3b1, - 0xe3b1, 0x080c, 0x0dc5, 0x080c, 0x99a5, 0x080c, 0x9ab1, 0x0036, - 0x0096, 0x6014, 0x904d, 0x01d8, 0x080c, 0xd0d8, 0x01c0, 0x6003, - 0x0002, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x1178, - 0x2019, 0x0004, 0x080c, 0xebd4, 0x6017, 0x0000, 0x6018, 0x9005, - 0x1120, 0x2001, 0x1987, 0x2004, 0x601a, 0x6003, 0x0007, 0x009e, - 0x003e, 0x0005, 0x0096, 0x080c, 0x99a5, 0x080c, 0x9ab1, 0x080c, - 0xd0d8, 0x0120, 0x6014, 0x2048, 0x080c, 0x1040, 0x080c, 0xb306, - 0x009e, 0x0005, 0x0002, 0xe3ff, 0xe416, 0xe401, 0xe42d, 0xe3ff, - 0xe3ff, 0xe3ff, 0xe3ff, 0xe3ff, 0xe3ff, 0xe3ff, 0xe3ff, 0xe3ff, - 0xe3ff, 0xe3ff, 0xe3ff, 0xe3ff, 0xe3ff, 0xe3ff, 0xe3ff, 0x080c, - 0x0dc5, 0x0096, 0x080c, 0x99a5, 0x6014, 0x2048, 0xa87c, 0xd0b4, - 0x0138, 0x6003, 0x0007, 0x2009, 0x0043, 0x080c, 0xb352, 0x0010, - 0x6003, 0x0004, 0x080c, 0x9ab1, 0x009e, 0x0005, 0x080c, 0x99a5, - 0x080c, 0xd0d8, 0x0138, 0x6114, 0x0096, 0x2148, 0xa97c, 0x009e, - 0xd1ec, 0x1138, 0x080c, 0x8a25, 0x080c, 0xb2d3, 0x080c, 0x9ab1, - 0x0005, 0x080c, 0xee2f, 0x0db0, 0x0cc8, 0x080c, 0x99a5, 0x2009, - 0x0041, 0x0804, 0xe59e, 0x9182, 0x0040, 0x0002, 0xe44a, 0xe44c, - 0xe44a, 0xe44a, 0xe44a, 0xe44a, 0xe44a, 0xe44a, 0xe44a, 0xe44a, - 0xe44a, 0xe44a, 0xe44a, 0xe44a, 0xe44a, 0xe44a, 0xe44a, 0xe44d, - 0xe44a, 0xe44a, 0x080c, 0x0dc5, 0x0005, 0x00d6, 0x080c, 0x8a25, - 0x00de, 0x080c, 0xee87, 0x080c, 0xb2d3, 0x0005, 0x9182, 0x0040, - 0x0002, 0xe46d, 0xe46d, 0xe46d, 0xe46d, 0xe46d, 0xe46d, 0xe46d, - 0xe46d, 0xe46d, 0xe46f, 0xe4de, 0xe46d, 0xe46d, 0xe46d, 0xe46d, - 0xe4de, 0xe46d, 0xe46d, 0xe46d, 0xe46d, 0x080c, 0x0dc5, 0x2001, - 0x0105, 0x2004, 0x9084, 0x1800, 0x01c8, 0x2001, 0x0132, 0x200c, - 0x2001, 0x0131, 0x2004, 0x9105, 0x1904, 0xe4de, 0x2009, 0x180c, - 0x2104, 0xd0d4, 0x0904, 0xe4de, 0xc0d4, 0x200a, 0x2009, 0x0105, - 0x2104, 0x9084, 0xe7fd, 0x9085, 0x0010, 0x200a, 0x2001, 0x1867, - 0x2004, 0xd0e4, 0x1528, 0x603b, 0x0000, 0x080c, 0x9a61, 0x6014, - 0x0096, 0x2048, 0xa87c, 0xd0fc, 0x0188, 0x908c, 0x0003, 0x918e, - 0x0002, 0x0508, 0x2001, 0x180c, 0x2004, 0xd0d4, 0x11e0, 0x080c, - 0x9bd3, 0x2009, 0x0041, 0x009e, 0x0804, 0xe59e, 0x080c, 0x9bd3, - 0x6003, 0x0007, 0x601b, 0x0000, 0x080c, 0x8a25, 0x009e, 0x0005, - 0x2001, 0x0100, 0x2004, 0x9082, 0x0005, 0x0aa8, 0x2001, 0x011f, - 0x2004, 0x603a, 0x0890, 0x2001, 0x180c, 0x200c, 0xc1d4, 0x2102, - 0xd1cc, 0x0110, 0x080c, 0x2c7b, 0x080c, 0x9bd3, 0x6014, 0x2048, - 0xa97c, 0xd1ec, 0x1130, 0x080c, 0x8a25, 0x080c, 0xb2d3, 0x009e, - 0x0005, 0x080c, 0xee2f, 0x0db8, 0x009e, 0x0005, 0x2001, 0x180c, - 0x200c, 0xc1d4, 0x2102, 0x0036, 0x080c, 0x9a61, 0x080c, 0x9bd3, - 0x6014, 0x0096, 0x2048, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, - 0xd0bc, 0x0188, 0xa87c, 0x9084, 0x0003, 0x9086, 0x0002, 0x0140, - 0xa8ac, 0x6330, 0x931a, 0x6332, 0xa8b0, 0x632c, 0x931b, 0x632e, - 0x6003, 0x0002, 0x0080, 0x2019, 0x0004, 0x080c, 0xebd4, 0x6018, - 0x9005, 0x1128, 0x2001, 0x1987, 0x2004, 0x8003, 0x601a, 0x6017, - 0x0000, 0x6003, 0x0007, 0x009e, 0x003e, 0x0005, 0x9182, 0x0040, - 0x0002, 0xe52d, 0xe52d, 0xe52d, 0xe52d, 0xe52d, 0xe52d, 0xe52d, - 0xe52d, 0xe52f, 0xe52d, 0xe52d, 0xe52d, 0xe52d, 0xe52d, 0xe52d, - 0xe52d, 0xe52d, 0xe52d, 0xe52d, 0xe57a, 0x080c, 0x0dc5, 0x6014, - 0x0096, 0x2048, 0xa834, 0xaa38, 0x6110, 0x00b6, 0x2158, 0xb900, - 0x00be, 0xd1bc, 0x1190, 0x920d, 0x1518, 0xa87c, 0xd0fc, 0x0128, - 0x2009, 0x0041, 0x009e, 0x0804, 0xe59e, 0x6003, 0x0007, 0x601b, - 0x0000, 0x080c, 0x8a25, 0x009e, 0x0005, 0x6124, 0xd1f4, 0x1d58, - 0x0006, 0x0046, 0xacac, 0x9422, 0xa9b0, 0x2200, 0x910b, 0x6030, - 0x9420, 0x6432, 0x602c, 0x9109, 0x612e, 0x004e, 0x000e, 0x08d8, - 0x6110, 0x00b6, 0x2158, 0xb900, 0x00be, 0xd1bc, 0x1178, 0x2009, - 0x180e, 0x210c, 0xd19c, 0x0118, 0x6003, 0x0007, 0x0010, 0x6003, - 0x0006, 0x00e9, 0x080c, 0x8a27, 0x009e, 0x0005, 0x6003, 0x0002, - 0x009e, 0x0005, 0x6024, 0xd0f4, 0x0128, 0x080c, 0x1608, 0x1904, - 0xe52f, 0x0005, 0x6014, 0x0096, 0x2048, 0xa834, 0xa938, 0x009e, - 0x9105, 0x1120, 0x080c, 0x1608, 0x1904, 0xe52f, 0x0005, 0xd2fc, - 0x0140, 0x8002, 0x8000, 0x8212, 0x9291, 0x0000, 0x2009, 0x0009, - 0x0010, 0x2009, 0x0015, 0xaa9a, 0xa896, 0x0005, 0x9182, 0x0040, - 0x0208, 0x0062, 0x9186, 0x0013, 0x0120, 0x9186, 0x0014, 0x190c, - 0x0dc5, 0x6024, 0xd0dc, 0x090c, 0x0dc5, 0x0005, 0xe5c2, 0xe5ce, - 0xe5da, 0xe5e6, 0xe5c2, 0xe5c2, 0xe5c2, 0xe5c2, 0xe5c9, 0xe5c4, - 0xe5c4, 0xe5c2, 0xe5c2, 0xe5c2, 0xe5c2, 0xe5c4, 0xe5c2, 0xe5c4, - 0xe5c2, 0xe5c9, 0x080c, 0x0dc5, 0x6024, 0xd0dc, 0x090c, 0x0dc5, - 0x0005, 0x6014, 0x9005, 0x190c, 0x0dc5, 0x0005, 0x6003, 0x0001, - 0x6106, 0x080c, 0x94ff, 0x0126, 0x2091, 0x8000, 0x080c, 0x9ab1, - 0x012e, 0x0005, 0x6003, 0x0001, 0x6106, 0x080c, 0x94ff, 0x0126, - 0x2091, 0x8000, 0x080c, 0x9ab1, 0x012e, 0x0005, 0x6003, 0x0003, - 0x6106, 0x2c10, 0x080c, 0x1be0, 0x0126, 0x2091, 0x8000, 0x080c, - 0x9564, 0x080c, 0x9bd3, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, - 0x0036, 0x0096, 0x9182, 0x0040, 0x0023, 0x009e, 0x003e, 0x012e, - 0x0005, 0xe615, 0xe617, 0xe629, 0xe643, 0xe615, 0xe615, 0xe615, - 0xe615, 0xe615, 0xe615, 0xe615, 0xe615, 0xe615, 0xe615, 0xe615, - 0xe615, 0xe615, 0xe615, 0xe615, 0xe615, 0x080c, 0x0dc5, 0x6014, - 0x2048, 0xa87c, 0xd0fc, 0x01f8, 0x909c, 0x0003, 0x939e, 0x0003, - 0x01d0, 0x6003, 0x0001, 0x6106, 0x080c, 0x94ff, 0x080c, 0x9ab1, - 0x0470, 0x6014, 0x2048, 0xa87c, 0xd0fc, 0x0168, 0x909c, 0x0003, - 0x939e, 0x0003, 0x0140, 0x6003, 0x0001, 0x6106, 0x080c, 0x94ff, - 0x080c, 0x9ab1, 0x00e0, 0x901e, 0x6316, 0x631a, 0x2019, 0x0004, - 0x080c, 0xebd4, 0x00a0, 0x6014, 0x2048, 0xa87c, 0xd0fc, 0x0d98, - 0x909c, 0x0003, 0x939e, 0x0003, 0x0d70, 0x6003, 0x0003, 0x6106, - 0x2c10, 0x080c, 0x1be0, 0x080c, 0x9564, 0x080c, 0x9bd3, 0x0005, - 0x080c, 0x99a5, 0x6114, 0x81ff, 0x0158, 0x0096, 0x2148, 0x080c, - 0xef85, 0x0036, 0x2019, 0x0029, 0x080c, 0xebd4, 0x003e, 0x009e, - 0x080c, 0xb306, 0x080c, 0x9ab1, 0x0005, 0x080c, 0x9a61, 0x6114, - 0x81ff, 0x0158, 0x0096, 0x2148, 0x080c, 0xef85, 0x0036, 0x2019, - 0x0029, 0x080c, 0xebd4, 0x003e, 0x009e, 0x080c, 0xb306, 0x080c, - 0x9bd3, 0x0005, 0x9182, 0x0085, 0x0002, 0xe694, 0xe692, 0xe692, - 0xe6a0, 0xe692, 0xe692, 0xe692, 0xe692, 0xe692, 0xe692, 0xe692, - 0xe692, 0xe692, 0x080c, 0x0dc5, 0x6003, 0x000b, 0x6106, 0x080c, - 0x94ff, 0x0126, 0x2091, 0x8000, 0x080c, 0x9ab1, 0x012e, 0x0005, - 0x0026, 0x00e6, 0x080c, 0xee26, 0x0118, 0x080c, 0xb2d3, 0x0450, - 0x2071, 0x0260, 0x7224, 0x6216, 0x2001, 0x180e, 0x2004, 0xd0e4, - 0x0150, 0x6010, 0x00b6, 0x2058, 0xbca0, 0x00be, 0x2c00, 0x2011, - 0x014e, 0x080c, 0xb5f5, 0x7220, 0x080c, 0xea29, 0x0118, 0x6007, - 0x0086, 0x0040, 0x6007, 0x0087, 0x7224, 0x9296, 0xffff, 0x1110, - 0x6007, 0x0086, 0x6003, 0x0001, 0x080c, 0x94ff, 0x080c, 0x9ab1, - 0x080c, 0x9bd3, 0x00ee, 0x002e, 0x0005, 0x9186, 0x0013, 0x1160, - 0x6004, 0x908a, 0x0085, 0x0a0c, 0x0dc5, 0x908a, 0x0092, 0x1a0c, - 0x0dc5, 0x9082, 0x0085, 0x00a2, 0x9186, 0x0027, 0x0130, 0x9186, - 0x0014, 0x0118, 0x080c, 0xb36d, 0x0050, 0x2001, 0x0007, 0x080c, - 0x6696, 0x080c, 0x99a5, 0x080c, 0xb306, 0x080c, 0x9ab1, 0x0005, - 0xe705, 0xe707, 0xe707, 0xe705, 0xe705, 0xe705, 0xe705, 0xe705, - 0xe705, 0xe705, 0xe705, 0xe705, 0xe705, 0x080c, 0x0dc5, 0x080c, - 0x99a5, 0x080c, 0xb306, 0x080c, 0x9ab1, 0x0005, 0x9182, 0x0085, - 0x0a0c, 0x0dc5, 0x9182, 0x0092, 0x1a0c, 0x0dc5, 0x9182, 0x0085, - 0x0002, 0xe726, 0xe726, 0xe726, 0xe728, 0xe726, 0xe726, 0xe726, - 0xe726, 0xe726, 0xe726, 0xe726, 0xe726, 0xe726, 0x080c, 0x0dc5, - 0x0005, 0x9186, 0x0013, 0x0148, 0x9186, 0x0014, 0x0130, 0x9186, - 0x0027, 0x0118, 0x080c, 0xb36d, 0x0030, 0x080c, 0x99a5, 0x080c, - 0xb306, 0x080c, 0x9ab1, 0x0005, 0x0036, 0x080c, 0xee87, 0x6043, - 0x0000, 0x2019, 0x000b, 0x0011, 0x003e, 0x0005, 0x6010, 0x0006, - 0x0059, 0x000e, 0x6012, 0x6023, 0x0006, 0x6003, 0x0007, 0x601b, - 0x0000, 0x6043, 0x0000, 0x0005, 0x0126, 0x0036, 0x2091, 0x8000, - 0x0086, 0x2c40, 0x0096, 0x904e, 0x080c, 0xaafb, 0x009e, 0x008e, - 0x1550, 0x0076, 0x2c38, 0x080c, 0xaba6, 0x007e, 0x1520, 0x6000, - 0x9086, 0x0000, 0x0500, 0x6020, 0x9086, 0x0007, 0x01e0, 0x0096, - 0x601c, 0xd084, 0x0140, 0x080c, 0xee87, 0x080c, 0xd7fb, 0x080c, - 0x1a8e, 0x6023, 0x0007, 0x6014, 0x2048, 0x080c, 0xd0d8, 0x0110, - 0x080c, 0xebd4, 0x009e, 0x6017, 0x0000, 0x080c, 0xee87, 0x6023, - 0x0007, 0x080c, 0xd7fb, 0x003e, 0x012e, 0x0005, 0x00f6, 0x00c6, - 0x00b6, 0x0036, 0x0156, 0x2079, 0x0260, 0x7938, 0x783c, 0x080c, - 0x2873, 0x1904, 0xe7e4, 0x0016, 0x00c6, 0x080c, 0x6724, 0x1904, - 0xe7e2, 0x001e, 0x00c6, 0x080c, 0xd7e3, 0x1130, 0xb8c0, 0x9005, - 0x0118, 0x080c, 0x33a5, 0x0148, 0x2b10, 0x2160, 0x6010, 0x0006, - 0x6212, 0x080c, 0xd7ea, 0x000e, 0x6012, 0x00ce, 0x002e, 0x0026, - 0x0016, 0x2019, 0x0029, 0x080c, 0xac6c, 0x080c, 0x96a4, 0x0076, - 0x903e, 0x080c, 0x9577, 0x007e, 0x001e, 0x0076, 0x903e, 0x080c, - 0xe91c, 0x007e, 0x0026, 0xba04, 0x9294, 0xff00, 0x8217, 0x9286, - 0x0006, 0x0118, 0x9286, 0x0004, 0x1118, 0xbaa0, 0x080c, 0x330e, - 0x002e, 0xbcc0, 0x001e, 0x080c, 0x6148, 0xbe12, 0xbd16, 0xbcc2, - 0x9006, 0x0010, 0x00ce, 0x001e, 0x015e, 0x003e, 0x00be, 0x00ce, - 0x00fe, 0x0005, 0x00c6, 0x00d6, 0x00b6, 0x0016, 0x2009, 0x1824, - 0x2104, 0x9086, 0x0074, 0x1904, 0xe843, 0x2069, 0x0260, 0x6944, - 0x9182, 0x0100, 0x06e0, 0x6940, 0x9184, 0x8000, 0x0904, 0xe840, - 0x2001, 0x197c, 0x2004, 0x9005, 0x1140, 0x6010, 0x2058, 0xb8c0, - 0x9005, 0x0118, 0x9184, 0x0800, 0x0598, 0x6948, 0x918a, 0x0001, - 0x0648, 0x080c, 0xefed, 0x0118, 0x6978, 0xd1fc, 0x11b8, 0x2009, - 0x0205, 0x200b, 0x0001, 0x693c, 0x81ff, 0x1198, 0x6944, 0x9182, - 0x0100, 0x02a8, 0x6940, 0x81ff, 0x1178, 0x6948, 0x918a, 0x0001, - 0x0288, 0x6950, 0x918a, 0x0001, 0x0298, 0x00d0, 0x6017, 0x0100, - 0x00a0, 0x6017, 0x0300, 0x0088, 0x6017, 0x0500, 0x0070, 0x6017, - 0x0700, 0x0058, 0x6017, 0x0900, 0x0040, 0x6017, 0x0b00, 0x0028, - 0x6017, 0x0f00, 0x0010, 0x6017, 0x2d00, 0x9085, 0x0001, 0x0008, - 0x9006, 0x001e, 0x00be, 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00b6, - 0x0026, 0x0036, 0x0156, 0x6210, 0x2258, 0xbb04, 0x9394, 0x00ff, - 0x9286, 0x0006, 0x0180, 0x9286, 0x0004, 0x0168, 0x9394, 0xff00, - 0x8217, 0x9286, 0x0006, 0x0138, 0x9286, 0x0004, 0x0120, 0x080c, - 0x6733, 0x0804, 0xe8ab, 0x2011, 0x0276, 0x20a9, 0x0004, 0x0096, - 0x2b48, 0x2019, 0x000a, 0x080c, 0xc379, 0x009e, 0x15a8, 0x2011, - 0x027a, 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, 0x0006, 0x080c, - 0xc379, 0x009e, 0x1548, 0x0046, 0x0016, 0xbaa0, 0x2220, 0x9006, - 0x2009, 0x1848, 0x210c, 0xd1a4, 0x0138, 0x2009, 0x0029, 0x080c, - 0xec31, 0xb800, 0xc0e5, 0xb802, 0x2019, 0x0029, 0x080c, 0x96a4, - 0x0076, 0x2039, 0x0000, 0x080c, 0x9577, 0x2c08, 0x080c, 0xe91c, - 0x007e, 0x2001, 0x0007, 0x080c, 0x6696, 0x2001, 0x0007, 0x080c, - 0x666a, 0x001e, 0x004e, 0x9006, 0x015e, 0x003e, 0x002e, 0x00be, - 0x00ce, 0x0005, 0x00d6, 0x2069, 0x026e, 0x6800, 0x9086, 0x0800, - 0x0118, 0x6017, 0x0000, 0x0008, 0x9006, 0x00de, 0x0005, 0x00b6, - 0x00f6, 0x0016, 0x0026, 0x0036, 0x0156, 0x2079, 0x026c, 0x7930, - 0x7834, 0x080c, 0x2873, 0x11d0, 0x080c, 0x6724, 0x11b8, 0x2011, - 0x0270, 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, 0x000a, 0x080c, - 0xc379, 0x009e, 0x1158, 0x2011, 0x0274, 0x20a9, 0x0004, 0x0096, - 0x2b48, 0x2019, 0x0006, 0x080c, 0xc379, 0x009e, 0x015e, 0x003e, - 0x002e, 0x001e, 0x00fe, 0x00be, 0x0005, 0x00b6, 0x0006, 0x0016, - 0x0026, 0x0036, 0x0156, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, - 0x080c, 0x2873, 0x11d0, 0x080c, 0x6724, 0x11b8, 0x2011, 0x0276, - 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, 0x000a, 0x080c, 0xc379, - 0x009e, 0x1158, 0x2011, 0x027a, 0x20a9, 0x0004, 0x0096, 0x2b48, - 0x2019, 0x0006, 0x080c, 0xc379, 0x009e, 0x015e, 0x003e, 0x002e, - 0x001e, 0x000e, 0x00be, 0x0005, 0x00e6, 0x00c6, 0x0086, 0x0076, - 0x0066, 0x0056, 0x0046, 0x0026, 0x0126, 0x2091, 0x8000, 0x2740, - 0x2029, 0x19f1, 0x252c, 0x2021, 0x19f7, 0x2424, 0x2061, 0x1cd0, - 0x2071, 0x1800, 0x7654, 0x7074, 0x81ff, 0x0150, 0x0006, 0x9186, - 0x1ab7, 0x000e, 0x0128, 0x8001, 0x9602, 0x1a04, 0xe9ba, 0x0018, - 0x9606, 0x0904, 0xe9ba, 0x080c, 0x8cf7, 0x0904, 0xe9b1, 0x2100, - 0x9c06, 0x0904, 0xe9b1, 0x6720, 0x9786, 0x0007, 0x0904, 0xe9b1, - 0x080c, 0xec72, 0x1904, 0xe9b1, 0x080c, 0xf00b, 0x0904, 0xe9b1, - 0x080c, 0xec62, 0x0904, 0xe9b1, 0x6720, 0x9786, 0x0001, 0x1148, - 0x080c, 0x33a5, 0x0904, 0xe9f9, 0x6004, 0x9086, 0x0000, 0x1904, - 0xe9f9, 0x9786, 0x0004, 0x0904, 0xe9f9, 0x2500, 0x9c06, 0x0904, - 0xe9b1, 0x2400, 0x9c06, 0x05e8, 0x88ff, 0x0118, 0x6054, 0x9906, - 0x15c0, 0x0096, 0x6000, 0x9086, 0x0004, 0x1120, 0x0016, 0x080c, - 0x1a8e, 0x001e, 0x9786, 0x000a, 0x0148, 0x080c, 0xd2e0, 0x1130, - 0x080c, 0xbcb6, 0x009e, 0x080c, 0xb306, 0x0418, 0x6014, 0x2048, - 0x080c, 0xd0d8, 0x01d8, 0x9786, 0x0003, 0x1570, 0xa867, 0x0103, - 0xa87c, 0xd0cc, 0x0130, 0x0096, 0xa878, 0x2048, 0x080c, 0x0fc0, - 0x009e, 0xab7a, 0xa877, 0x0000, 0x080c, 0xef85, 0x0016, 0x080c, - 0xd3ce, 0x080c, 0x6e92, 0x001e, 0x080c, 0xd2c3, 0x009e, 0x080c, - 0xb306, 0x9ce0, 0x0018, 0x2001, 0x181a, 0x2004, 0x9c02, 0x1210, - 0x0804, 0xe930, 0x012e, 0x002e, 0x004e, 0x005e, 0x006e, 0x007e, - 0x008e, 0x00ce, 0x00ee, 0x0005, 0x9786, 0x0006, 0x1150, 0x9386, - 0x0005, 0x0128, 0x080c, 0xef85, 0x080c, 0xebd4, 0x08f8, 0x009e, - 0x0c00, 0x9786, 0x0009, 0x11f8, 0x6000, 0x9086, 0x0004, 0x01c0, - 0x6000, 0x9086, 0x0003, 0x11a0, 0x080c, 0x9a61, 0x0096, 0x6114, - 0x2148, 0x080c, 0xd0d8, 0x0118, 0x6010, 0x080c, 0x6e9f, 0x009e, - 0x00c6, 0x080c, 0xb2d3, 0x00ce, 0x0036, 0x080c, 0x9bd3, 0x003e, - 0x009e, 0x0804, 0xe9b1, 0x9786, 0x000a, 0x0904, 0xe9a1, 0x0804, - 0xe996, 0x81ff, 0x0904, 0xe9b1, 0x9180, 0x0001, 0x2004, 0x9086, - 0x0018, 0x0138, 0x9180, 0x0001, 0x2004, 0x9086, 0x002d, 0x1904, - 0xe9b1, 0x6000, 0x9086, 0x0002, 0x1904, 0xe9b1, 0x080c, 0xd2cf, - 0x0138, 0x080c, 0xd2e0, 0x1904, 0xe9b1, 0x080c, 0xbcb6, 0x0038, - 0x080c, 0x3279, 0x080c, 0xd2e0, 0x1110, 0x080c, 0xbcb6, 0x080c, - 0xb306, 0x0804, 0xe9b1, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, - 0x0005, 0x00c6, 0x00e6, 0x0016, 0x2c08, 0x2170, 0x9006, 0x080c, - 0xebfb, 0x001e, 0x0120, 0x6020, 0x9084, 0x000f, 0x001b, 0x00ee, - 0x00ce, 0x0005, 0xea48, 0xea48, 0xea48, 0xea48, 0xea48, 0xea48, - 0xea4a, 0xea48, 0xea48, 0xea48, 0xea73, 0xb306, 0xb306, 0xea48, - 0x9006, 0x0005, 0x0036, 0x0046, 0x0016, 0x7010, 0x00b6, 0x2058, - 0xbca0, 0x00be, 0x2c00, 0x2009, 0x0020, 0x080c, 0xec31, 0x001e, - 0x004e, 0x2019, 0x0002, 0x080c, 0xe754, 0x003e, 0x9085, 0x0001, - 0x0005, 0x0096, 0x080c, 0xd0d8, 0x0140, 0x6014, 0x904d, 0x080c, - 0xccf3, 0x687b, 0x0005, 0x080c, 0x6e9f, 0x009e, 0x080c, 0xb306, - 0x9085, 0x0001, 0x0005, 0x0019, 0x9085, 0x0001, 0x0005, 0x6000, - 0x908a, 0x0010, 0x1a0c, 0x0dc5, 0x000b, 0x0005, 0xea8e, 0xea8e, - 0xeaa5, 0xea95, 0xeab4, 0xea8e, 0xea8e, 0xea90, 0xea8e, 0xea8e, - 0xea8e, 0xea8e, 0xea8e, 0xea8e, 0xea8e, 0xea8e, 0x080c, 0x0dc5, - 0x080c, 0xb306, 0x9085, 0x0001, 0x0005, 0x0036, 0x00e6, 0x2071, - 0x19e8, 0x703c, 0x9c06, 0x1128, 0x2019, 0x0001, 0x080c, 0xaa49, - 0x0010, 0x080c, 0xac2b, 0x00ee, 0x003e, 0x0096, 0x00d6, 0x6014, - 0x2048, 0xa87b, 0x0005, 0x080c, 0x6e9f, 0x080c, 0xb306, 0x00de, - 0x009e, 0x9085, 0x0001, 0x0005, 0x601c, 0xd084, 0x190c, 0x1a8e, - 0x0c60, 0x2001, 0x0001, 0x080c, 0x6656, 0x0156, 0x0016, 0x0026, - 0x0036, 0x20a9, 0x0004, 0x2019, 0x1805, 0x2011, 0x0276, 0x080c, - 0xc365, 0x003e, 0x002e, 0x001e, 0x015e, 0x9005, 0x0005, 0x00f6, - 0x00e6, 0x00c6, 0x0086, 0x0076, 0x0066, 0x00b6, 0x0126, 0x2091, - 0x8000, 0x2740, 0x2061, 0x1cd0, 0x2079, 0x0001, 0x8fff, 0x0904, - 0xeb2b, 0x2071, 0x1800, 0x7654, 0x7074, 0x8001, 0x9602, 0x1a04, - 0xeb2b, 0x88ff, 0x0120, 0x2800, 0x9c06, 0x15a0, 0x2078, 0x080c, - 0xec62, 0x0580, 0x2400, 0x9c06, 0x0568, 0x6720, 0x9786, 0x0006, - 0x1548, 0x9786, 0x0007, 0x0530, 0x88ff, 0x1150, 0xd58c, 0x1118, - 0x6010, 0x9b06, 0x11f8, 0xd584, 0x0118, 0x6054, 0x9106, 0x11d0, - 0x0096, 0x601c, 0xd084, 0x0140, 0x080c, 0xee87, 0x080c, 0xd7fb, - 0x080c, 0x1a8e, 0x6023, 0x0007, 0x6014, 0x2048, 0x080c, 0xd0d8, - 0x0120, 0x0046, 0x080c, 0xebd4, 0x004e, 0x009e, 0x080c, 0xb306, - 0x88ff, 0x1198, 0x9ce0, 0x0018, 0x2001, 0x181a, 0x2004, 0x9c02, - 0x1210, 0x0804, 0xeade, 0x9006, 0x012e, 0x00be, 0x006e, 0x007e, - 0x008e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x98c5, 0x0001, 0x0ca0, - 0x00b6, 0x0076, 0x0056, 0x0086, 0x9046, 0x2029, 0x0001, 0x2c20, - 0x2019, 0x0002, 0x6210, 0x2258, 0x0096, 0x904e, 0x080c, 0xaafb, - 0x009e, 0x008e, 0x903e, 0x080c, 0xaba6, 0x080c, 0xeacf, 0x005e, - 0x007e, 0x00be, 0x0005, 0x00b6, 0x0046, 0x0056, 0x0076, 0x00c6, - 0x0156, 0x2c20, 0x2128, 0x20a9, 0x007f, 0x900e, 0x0016, 0x0036, - 0x080c, 0x6724, 0x1180, 0x0056, 0x0086, 0x9046, 0x2508, 0x2029, - 0x0001, 0x0096, 0x904e, 0x080c, 0xaafb, 0x009e, 0x008e, 0x903e, - 0x080c, 0xaba6, 0x005e, 0x003e, 0x001e, 0x8108, 0x1f04, 0xeb5e, - 0x0036, 0x2508, 0x2029, 0x0003, 0x080c, 0xeacf, 0x003e, 0x015e, - 0x00ce, 0x007e, 0x005e, 0x004e, 0x00be, 0x0005, 0x00b6, 0x0076, - 0x0056, 0x6210, 0x2258, 0x0086, 0x9046, 0x2029, 0x0001, 0x2019, - 0x0048, 0x0096, 0x904e, 0x080c, 0xaafb, 0x009e, 0x008e, 0x903e, - 0x080c, 0xaba6, 0x2c20, 0x080c, 0xeacf, 0x005e, 0x007e, 0x00be, - 0x0005, 0x00b6, 0x0046, 0x0056, 0x0076, 0x00c6, 0x0156, 0x2c20, - 0x20a9, 0x0800, 0x900e, 0x0016, 0x0036, 0x080c, 0x6724, 0x1190, - 0x0086, 0x9046, 0x2828, 0x0046, 0x2021, 0x0001, 0x080c, 0xee6b, - 0x004e, 0x0096, 0x904e, 0x080c, 0xaafb, 0x009e, 0x008e, 0x903e, - 0x080c, 0xaba6, 0x003e, 0x001e, 0x8108, 0x1f04, 0xebab, 0x0036, - 0x2029, 0x0002, 0x080c, 0xeacf, 0x003e, 0x015e, 0x00ce, 0x007e, - 0x005e, 0x004e, 0x00be, 0x0005, 0x0016, 0x00f6, 0x080c, 0xd0d6, - 0x0198, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0046, 0x0180, 0xa800, - 0x907d, 0x0138, 0xa803, 0x0000, 0xab82, 0x080c, 0x6e9f, 0x2f48, - 0x0cb0, 0xab82, 0x080c, 0x6e9f, 0x00fe, 0x001e, 0x0005, 0xa800, - 0x907d, 0x0130, 0xa803, 0x0000, 0x080c, 0x6e9f, 0x2f48, 0x0cb8, - 0x080c, 0x6e9f, 0x0c88, 0x00e6, 0x0046, 0x0036, 0x2061, 0x1cd0, - 0x9005, 0x1138, 0x2071, 0x1800, 0x7454, 0x7074, 0x8001, 0x9402, - 0x12f8, 0x2100, 0x9c06, 0x0188, 0x6000, 0x9086, 0x0000, 0x0168, - 0x6008, 0x9206, 0x1150, 0x6320, 0x9386, 0x0009, 0x01b0, 0x6010, - 0x91a0, 0x0004, 0x2424, 0x9406, 0x0140, 0x9ce0, 0x0018, 0x2001, - 0x181a, 0x2004, 0x9c02, 0x1220, 0x0c20, 0x9085, 0x0001, 0x0008, - 0x9006, 0x003e, 0x004e, 0x00ee, 0x0005, 0x631c, 0xd3c4, 0x1d68, - 0x0c30, 0x0096, 0x0006, 0x080c, 0x100e, 0x000e, 0x090c, 0x0dc5, - 0xaae2, 0xa867, 0x010d, 0xa88e, 0x0026, 0x2010, 0x080c, 0xd0c6, - 0x2001, 0x0000, 0x0120, 0x2200, 0x9080, 0x0015, 0x2004, 0x002e, - 0xa87a, 0x9186, 0x0020, 0x0110, 0xa8e3, 0xffff, 0xa986, 0xac76, - 0xa87f, 0x0000, 0x2001, 0x198e, 0x2004, 0xa882, 0x9006, 0xa802, - 0xa86a, 0xa88a, 0x0126, 0x2091, 0x8000, 0x080c, 0x6e9f, 0x012e, - 0x009e, 0x0005, 0x6700, 0x9786, 0x0000, 0x0158, 0x9786, 0x0001, - 0x0140, 0x9786, 0x000a, 0x0128, 0x9786, 0x0009, 0x0110, 0x9085, - 0x0001, 0x0005, 0x00e6, 0x6010, 0x9075, 0x0138, 0x00b6, 0x2058, - 0xb8a0, 0x00be, 0x9206, 0x00ee, 0x0005, 0x9085, 0x0001, 0x0cd8, - 0x0016, 0x6004, 0x908e, 0x001e, 0x11a0, 0x8007, 0x6134, 0x918c, - 0x00ff, 0x9105, 0x6036, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, - 0x0005, 0x2001, 0x1987, 0x2004, 0x601a, 0x080c, 0x94ff, 0x080c, - 0x9ab1, 0x001e, 0x0005, 0xa001, 0xa001, 0x0005, 0x6024, 0xd0e4, - 0x0158, 0xd0cc, 0x0118, 0x080c, 0xd412, 0x0030, 0x080c, 0xee87, - 0x080c, 0x8a25, 0x080c, 0xb2d3, 0x0005, 0x9280, 0x0008, 0x2004, - 0x9084, 0x000f, 0x0002, 0xecc1, 0xecc1, 0xecc1, 0xecc3, 0xecc1, - 0xecc3, 0xecc3, 0xecc1, 0xecc3, 0xecc1, 0xecc1, 0xecc1, 0xecc1, - 0xecc1, 0x9006, 0x0005, 0x9085, 0x0001, 0x0005, 0x9280, 0x0008, - 0x2004, 0x9084, 0x000f, 0x0002, 0xecda, 0xecda, 0xecda, 0xecda, - 0xecda, 0xecda, 0xece7, 0xecda, 0xecda, 0xecda, 0xecda, 0xecda, - 0xecda, 0xecda, 0x6007, 0x003b, 0x602f, 0x0009, 0x6017, 0x2a00, - 0x6003, 0x0001, 0x080c, 0x94ff, 0x080c, 0x9ab1, 0x0005, 0x0096, - 0x00c6, 0x2260, 0x080c, 0xee87, 0x6043, 0x0000, 0x6024, 0xc0f4, - 0xc0e4, 0x6026, 0x603b, 0x0000, 0x00ce, 0x00d6, 0x2268, 0x9186, - 0x0007, 0x1904, 0xed40, 0x6814, 0x9005, 0x0138, 0x2048, 0xa87c, - 0xd0fc, 0x1118, 0x00de, 0x009e, 0x08a8, 0x6007, 0x003a, 0x6003, - 0x0001, 0x080c, 0x94ff, 0x080c, 0x9ab1, 0x00c6, 0x2d60, 0x6100, - 0x9186, 0x0002, 0x1904, 0xedb0, 0x6014, 0x9005, 0x1138, 0x6000, - 0x9086, 0x0007, 0x190c, 0x0dc5, 0x0804, 0xedb0, 0x2048, 0x080c, - 0xd0d8, 0x1130, 0x0028, 0x2048, 0xa800, 0x9005, 0x1de0, 0x2900, - 0x2048, 0xa87c, 0x9084, 0x0003, 0x9086, 0x0002, 0x1168, 0xa87c, - 0xc0dc, 0xc0f4, 0xa87e, 0xa880, 0xc0fc, 0xa882, 0x2009, 0x0043, - 0x080c, 0xe59e, 0x0804, 0xedb0, 0x2009, 0x0041, 0x0804, 0xedaa, - 0x9186, 0x0005, 0x15a0, 0x6814, 0x2048, 0xa87c, 0xd0bc, 0x1120, - 0x00de, 0x009e, 0x0804, 0xecda, 0xd0b4, 0x0128, 0xd0fc, 0x090c, - 0x0dc5, 0x0804, 0xecfb, 0x6007, 0x003a, 0x6003, 0x0001, 0x080c, - 0x94ff, 0x080c, 0x9ab1, 0x00c6, 0x2d60, 0x6100, 0x9186, 0x0002, - 0x0120, 0x9186, 0x0004, 0x1904, 0xedb0, 0x6814, 0x2048, 0xa97c, - 0xc1f4, 0xc1dc, 0xa97e, 0xa980, 0xc1fc, 0xc1bc, 0xa982, 0x00f6, - 0x2c78, 0x080c, 0x1768, 0x00fe, 0x2009, 0x0042, 0x0498, 0x0036, - 0x080c, 0x100e, 0x090c, 0x0dc5, 0xa867, 0x010d, 0x9006, 0xa802, - 0xa86a, 0xa88a, 0x2d18, 0xab8e, 0xa887, 0x0045, 0x2c00, 0xa892, - 0x6038, 0xa8a2, 0x2360, 0x6024, 0xc0dd, 0x6026, 0x6010, 0x00b6, - 0x2058, 0xb8a0, 0x00be, 0x2004, 0x6354, 0xab7a, 0xa876, 0x9006, - 0xa87e, 0xa882, 0xad9a, 0xae96, 0xa89f, 0x0001, 0x080c, 0x6e9f, - 0x2019, 0x0045, 0x6008, 0x2068, 0x080c, 0xe746, 0x2d00, 0x600a, - 0x003e, 0x0038, 0x6043, 0x0000, 0x6003, 0x0007, 0x080c, 0xe59e, - 0x00ce, 0x00de, 0x009e, 0x0005, 0x9186, 0x0013, 0x1128, 0x6004, - 0x9082, 0x0085, 0x2008, 0x00c2, 0x9186, 0x0027, 0x1178, 0x080c, - 0x99a5, 0x0036, 0x0096, 0x6014, 0x2048, 0x2019, 0x0004, 0x080c, - 0xebd4, 0x009e, 0x003e, 0x080c, 0x9ab1, 0x0005, 0x9186, 0x0014, - 0x0d70, 0x080c, 0xb36d, 0x0005, 0xede3, 0xede1, 0xede1, 0xede1, - 0xede1, 0xede1, 0xede3, 0xede1, 0xede1, 0xede1, 0xede1, 0xede1, - 0xede1, 0x080c, 0x0dc5, 0x080c, 0x99a5, 0x6003, 0x000c, 0x080c, - 0x9ab1, 0x0005, 0x9182, 0x0092, 0x1220, 0x9182, 0x0085, 0x0208, - 0x001a, 0x080c, 0xb36d, 0x0005, 0xee01, 0xee01, 0xee01, 0xee01, - 0xee03, 0xee23, 0xee01, 0xee01, 0xee01, 0xee01, 0xee01, 0xee01, - 0xee01, 0x080c, 0x0dc5, 0x00d6, 0x2c68, 0x080c, 0xb27d, 0x01b0, - 0x6003, 0x0001, 0x6007, 0x001e, 0x2009, 0x026e, 0x210c, 0x613a, - 0x2009, 0x026f, 0x210c, 0x613e, 0x600b, 0xffff, 0x6910, 0x6112, - 0x6023, 0x0004, 0x080c, 0x94ff, 0x080c, 0x9ab1, 0x2d60, 0x080c, - 0xb2d3, 0x00de, 0x0005, 0x080c, 0xb2d3, 0x0005, 0x00e6, 0x6010, - 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0ec, 0x00ee, 0x0005, 0x2009, - 0x1867, 0x210c, 0xd1ec, 0x05b0, 0x6003, 0x0002, 0x6024, 0xc0e5, - 0x6026, 0xd0cc, 0x0150, 0x2001, 0x1988, 0x2004, 0x6042, 0x2009, - 0x1867, 0x210c, 0xd1f4, 0x1520, 0x00a0, 0x2009, 0x1867, 0x210c, - 0xd1f4, 0x0128, 0x6024, 0xc0e4, 0x6026, 0x9006, 0x00d8, 0x2001, - 0x1988, 0x200c, 0x2001, 0x1986, 0x2004, 0x9100, 0x9080, 0x000a, - 0x6042, 0x6010, 0x00b6, 0x2058, 0xb8bc, 0x00be, 0x0008, 0x2104, - 0x9005, 0x0118, 0x9088, 0x0003, 0x0cd0, 0x2c0a, 0x600f, 0x0000, - 0x9085, 0x0001, 0x0005, 0x0016, 0x00c6, 0x00e6, 0x6154, 0xb8bc, - 0x2060, 0x8cff, 0x0180, 0x84ff, 0x1118, 0x6054, 0x9106, 0x1138, - 0x600c, 0x2072, 0x080c, 0x8a25, 0x080c, 0xb2d3, 0x0010, 0x9cf0, - 0x0003, 0x2e64, 0x0c70, 0x00ee, 0x00ce, 0x001e, 0x0005, 0x00d6, - 0x00b6, 0x6010, 0x2058, 0xb8bc, 0x906d, 0x0130, 0x9c06, 0x0110, - 0x680c, 0x0cd0, 0x600c, 0x680e, 0x00be, 0x00de, 0x0005, 0x0026, - 0x0036, 0x0156, 0x2011, 0x182c, 0x2204, 0x9084, 0x00ff, 0x2019, - 0x026e, 0x2334, 0x96b4, 0x00ff, 0x9636, 0x1508, 0x8318, 0x2334, - 0x2204, 0x9084, 0xff00, 0x9636, 0x11d0, 0x2011, 0x0270, 0x20a9, - 0x0004, 0x6010, 0x0096, 0x2048, 0x2019, 0x000a, 0x080c, 0xc379, - 0x009e, 0x1168, 0x2011, 0x0274, 0x20a9, 0x0004, 0x6010, 0x0096, - 0x2048, 0x2019, 0x0006, 0x080c, 0xc379, 0x009e, 0x1100, 0x015e, - 0x003e, 0x002e, 0x0005, 0x00e6, 0x2071, 0x1800, 0x080c, 0x60c1, - 0x080c, 0x3000, 0x00ee, 0x0005, 0x0096, 0x0026, 0x080c, 0x100e, - 0x090c, 0x0dc5, 0xa85c, 0x9080, 0x001a, 0x20a0, 0x20a9, 0x000c, - 0xa860, 0x20e8, 0x9006, 0x4004, 0x9186, 0x0046, 0x1118, 0xa867, - 0x0136, 0x0038, 0xa867, 0x0138, 0x9186, 0x0041, 0x0110, 0xa87b, - 0x0001, 0x7038, 0x9084, 0xff00, 0x7240, 0x9294, 0xff00, 0x8007, - 0x9215, 0xaa9a, 0x9186, 0x0046, 0x1168, 0x7038, 0x9084, 0x00ff, - 0x723c, 0x9294, 0xff00, 0x9215, 0xaa9e, 0x723c, 0x9294, 0x00ff, - 0xaaa2, 0x0060, 0x7040, 0x9084, 0x00ff, 0x7244, 0x9294, 0xff00, - 0x9215, 0xaa9e, 0x7244, 0x9294, 0x00ff, 0xaaa2, 0x9186, 0x0046, - 0x1118, 0x9e90, 0x0012, 0x0010, 0x9e90, 0x001a, 0x2204, 0x8007, - 0xa8a6, 0x8210, 0x2204, 0x8007, 0xa8aa, 0x8210, 0x2204, 0x8007, - 0xa8ae, 0x8210, 0x2204, 0x8007, 0xa8b2, 0x8210, 0x9186, 0x0046, - 0x11b8, 0x9e90, 0x0016, 0x2204, 0x8007, 0xa8b6, 0x8210, 0x2204, - 0x8007, 0xa8ba, 0x8210, 0x2204, 0x8007, 0xa8be, 0x8210, 0x2204, - 0x8007, 0xa8c2, 0x8210, 0x2011, 0x0205, 0x2013, 0x0001, 0x00b0, - 0x9e90, 0x001e, 0x2204, 0x8007, 0xa8b6, 0x8210, 0x2204, 0x8007, - 0xa8ba, 0x2011, 0x0205, 0x2013, 0x0001, 0x2011, 0x0260, 0x2204, - 0x8007, 0xa8be, 0x8210, 0x2204, 0x8007, 0xa8c2, 0x9186, 0x0046, - 0x1118, 0x2011, 0x0262, 0x0010, 0x2011, 0x026a, 0x0146, 0x01d6, - 0x0036, 0x20a9, 0x0001, 0x2019, 0x0008, 0xa860, 0x20e8, 0xa85c, - 0x9080, 0x0031, 0x20a0, 0x2204, 0x8007, 0x4004, 0x8210, 0x8319, - 0x1dd0, 0x003e, 0x01ce, 0x013e, 0x2011, 0x0205, 0x2013, 0x0000, - 0x002e, 0x080c, 0x6e9f, 0x009e, 0x0005, 0x00e6, 0x6010, 0x00b6, - 0x2058, 0xb800, 0x00be, 0xd0fc, 0x0108, 0x0011, 0x00ee, 0x0005, - 0xa880, 0xc0e5, 0xa882, 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0076, - 0x0066, 0x0056, 0x0046, 0x0026, 0x0016, 0x0126, 0x2091, 0x8000, - 0x2029, 0x19f1, 0x252c, 0x2021, 0x19f7, 0x2424, 0x2061, 0x1cd0, - 0x2071, 0x1800, 0x7654, 0x7074, 0x9606, 0x0578, 0x6720, 0x9786, - 0x0001, 0x0118, 0x9786, 0x0008, 0x1500, 0x2500, 0x9c06, 0x01e8, - 0x2400, 0x9c06, 0x01d0, 0x080c, 0xec62, 0x01b8, 0x080c, 0xec72, - 0x11a0, 0x6000, 0x9086, 0x0004, 0x1120, 0x0016, 0x080c, 0x1a8e, - 0x001e, 0x080c, 0xd2cf, 0x1110, 0x080c, 0x3279, 0x080c, 0xd2e0, - 0x1110, 0x080c, 0xbcb6, 0x080c, 0xb306, 0x9ce0, 0x0018, 0x2001, - 0x181a, 0x2004, 0x9c02, 0x1208, 0x0858, 0x012e, 0x001e, 0x002e, - 0x004e, 0x005e, 0x006e, 0x007e, 0x00ce, 0x00de, 0x00ee, 0x0005, - 0x2001, 0x1810, 0x2004, 0xd0dc, 0x0005, 0x0006, 0x2001, 0x1837, - 0x2004, 0xd09c, 0x000e, 0x0005, 0x0006, 0x0036, 0x0046, 0x080c, - 0xd7e3, 0x0168, 0x2019, 0xffff, 0x9005, 0x0128, 0x6010, 0x00b6, - 0x2058, 0xbba0, 0x00be, 0x2021, 0x0004, 0x080c, 0x4dfb, 0x004e, - 0x003e, 0x000e, 0x0005, 0x6004, 0x9086, 0x0001, 0x1128, 0x080c, - 0xac6c, 0x080c, 0xb306, 0x9006, 0x0005, 0x00e6, 0x00c6, 0x00b6, - 0x0046, 0x2061, 0x1cd0, 0x2071, 0x1800, 0x7454, 0x7074, 0x8001, - 0x9402, 0x12d8, 0x2100, 0x9c06, 0x0168, 0x6000, 0x9086, 0x0000, - 0x0148, 0x6010, 0x2058, 0xb8a0, 0x9206, 0x1120, 0x6004, 0x9086, - 0x0002, 0x0140, 0x9ce0, 0x0018, 0x2001, 0x181a, 0x2004, 0x9c02, - 0x1220, 0x0c40, 0x9085, 0x0001, 0x0008, 0x9006, 0x004e, 0x00be, - 0x00ce, 0x00ee, 0x0005, 0x2001, 0x1810, 0x2004, 0xd0a4, 0x0160, - 0x2001, 0x1837, 0x2004, 0xd0a4, 0x0138, 0x2001, 0x1848, 0x2004, - 0xd0a4, 0x1118, 0x9085, 0x0001, 0x0005, 0x9006, 0x0ce8, 0x0126, - 0x0006, 0x00e6, 0x0016, 0x2091, 0x8000, 0x2071, 0x1840, 0xd5a4, - 0x0118, 0x7004, 0x8000, 0x7006, 0xd5b4, 0x0118, 0x7000, 0x8000, - 0x7002, 0xd5ac, 0x0178, 0x2500, 0x9084, 0x0007, 0x908e, 0x0003, - 0x0148, 0x908e, 0x0004, 0x0130, 0x908e, 0x0005, 0x0118, 0x2071, - 0xfff6, 0x0089, 0x001e, 0x00ee, 0x000e, 0x012e, 0x0005, 0x0126, - 0x0006, 0x00e6, 0x2091, 0x8000, 0x2071, 0xffee, 0x0021, 0x00ee, - 0x000e, 0x012e, 0x0005, 0x2e05, 0x8000, 0x2077, 0x1220, 0x8e70, - 0x2e05, 0x8000, 0x2077, 0x0005, 0x00e6, 0x2071, 0xffec, 0x0c99, - 0x00ee, 0x0005, 0x00e6, 0x2071, 0xfff0, 0x0c69, 0x00ee, 0x0005, - 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, 0x2071, 0x1840, 0x7014, - 0x8000, 0x7016, 0x00ee, 0x000e, 0x012e, 0x0005, 0x0003, 0x000b, - 0x07d2, 0x0000, 0xc000, 0x0001, 0x8064, 0x0008, 0x0010, 0x0000, - 0x8066, 0x0000, 0x0101, 0x0008, 0x4407, 0x0003, 0x8060, 0x0000, - 0x0400, 0x0000, 0x580d, 0x000b, 0x79c0, 0x0003, 0x5106, 0x0003, - 0x4c0a, 0x0003, 0xbac0, 0x0009, 0x008a, 0x0000, 0x0c0a, 0x000b, - 0x15fe, 0x0008, 0x340a, 0x0003, 0xc4c0, 0x0009, 0x7000, 0x0000, - 0xffa0, 0x0001, 0x2000, 0x0000, 0x1680, 0x000b, 0x808c, 0x0008, - 0x0001, 0x0000, 0x0000, 0x0007, 0x4028, 0x0000, 0x4047, 0x000a, - 0x808c, 0x0008, 0x0002, 0x0000, 0x0822, 0x0003, 0x4022, 0x0000, - 0x0028, 0x000b, 0x4122, 0x0008, 0x94c0, 0x0009, 0xff00, 0x0008, - 0xffe0, 0x0009, 0x0500, 0x0008, 0x0aab, 0x0003, 0x4447, 0x0002, - 0x0ea8, 0x000b, 0x0bfe, 0x0008, 0x11a0, 0x0001, 0x1286, 0x0003, - 0x0ca0, 0x0001, 0x1286, 0x0003, 0x9180, 0x0001, 0x0004, 0x0000, - 0x8060, 0x0000, 0x0400, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, - 0x0009, 0x0008, 0x4436, 0x000b, 0x808c, 0x0008, 0x0000, 0x0008, - 0x0060, 0x0008, 0x8062, 0x0008, 0x0004, 0x0000, 0x8066, 0x0000, - 0x0411, 0x0000, 0x443e, 0x0003, 0x03fe, 0x0000, 0x43e0, 0x0001, - 0x0e83, 0x000b, 0xc2c0, 0x0009, 0x00ff, 0x0008, 0x02e0, 0x0001, - 0x0e83, 0x000b, 0x9180, 0x0001, 0x0005, 0x0008, 0x8060, 0x0000, - 0x0400, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0019, 0x0000, - 0x444d, 0x000b, 0x0240, 0x0002, 0x0a80, 0x0003, 0x00fe, 0x0000, - 0x3283, 0x000b, 0x0248, 0x000a, 0x085c, 0x0003, 0x9180, 0x0001, - 0x0006, 0x0008, 0x7f62, 0x0008, 0x8002, 0x0008, 0x0003, 0x0008, - 0x8066, 0x0000, 0x020a, 0x0000, 0x445b, 0x0003, 0x112a, 0x0000, - 0x002e, 0x0008, 0x022c, 0x0008, 0x3a44, 0x0002, 0x0c0a, 0x000b, - 0x808c, 0x0008, 0x0002, 0x0000, 0x1760, 0x0008, 0x8062, 0x0008, - 0x000f, 0x0008, 0x8066, 0x0000, 0x0011, 0x0008, 0x4468, 0x0003, - 0x01fe, 0x0008, 0x42e0, 0x0009, 0x0e74, 0x0003, 0x00fe, 0x0000, - 0x43e0, 0x0001, 0x0e74, 0x0003, 0x1734, 0x0000, 0x1530, 0x0000, - 0x1632, 0x0008, 0x0d2a, 0x0008, 0x9880, 0x0001, 0x0010, 0x0000, - 0x8060, 0x0000, 0x0400, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, - 0x1e0a, 0x0008, 0x447a, 0x0003, 0x808a, 0x0008, 0x0003, 0x0008, - 0x1a60, 0x0000, 0x8062, 0x0008, 0x0002, 0x0000, 0x5880, 0x000b, - 0x8066, 0x0000, 0x3679, 0x0000, 0x4483, 0x0003, 0x5884, 0x0003, - 0x3efe, 0x0008, 0x7f4f, 0x0002, 0x088a, 0x000b, 0x0d00, 0x0000, - 0x0092, 0x000c, 0x8054, 0x0008, 0x0011, 0x0008, 0x8074, 0x0000, - 0x1010, 0x0008, 0x1efe, 0x0000, 0x300a, 0x000b, 0x00e0, 0x000c, - 0x000a, 0x000b, 0x00fe, 0x0000, 0x349a, 0x0003, 0x1a60, 0x0000, - 0x8062, 0x0008, 0x0007, 0x0000, 0x8066, 0x0000, 0x0231, 0x0008, - 0x4499, 0x000b, 0x03fe, 0x0000, 0x04d0, 0x0001, 0x0cd4, 0x000b, - 0x82c0, 0x0001, 0x1f00, 0x0000, 0xffa0, 0x0001, 0x0400, 0x0000, - 0x08b2, 0x0003, 0x14dc, 0x0003, 0x01fe, 0x0008, 0x0580, 0x0009, - 0x7f06, 0x0000, 0x8690, 0x0009, 0x0000, 0x0008, 0x7f0c, 0x0000, - 0x02fe, 0x0008, 0xffc0, 0x0001, 0x00ff, 0x0008, 0x0680, 0x0009, - 0x10b2, 0x0003, 0x7f08, 0x0008, 0x84c0, 0x0001, 0xff00, 0x0008, - 0x08d4, 0x0003, 0xb9c0, 0x0009, 0x0030, 0x0008, 0x0cc3, 0x000b, - 0x8060, 0x0000, 0x0400, 0x0000, 0x80fe, 0x0008, 0x1a0a, 0x0009, - 0x7f62, 0x0008, 0x8066, 0x0000, 0x0409, 0x0000, 0x44bc, 0x0003, - 0x80fe, 0x0008, 0x1a09, 0x0009, 0x7f62, 0x0008, 0x8066, 0x0000, - 0x040a, 0x0000, 0x44c2, 0x0003, 0x00fe, 0x0000, 0x34ca, 0x0003, - 0x8072, 0x0000, 0x1010, 0x0008, 0x3944, 0x0002, 0x08c5, 0x0003, - 0x00ce, 0x0003, 0x8072, 0x0000, 0x2020, 0x0008, 0x3945, 0x000a, - 0x08ca, 0x0003, 0x3946, 0x000a, 0x0cdb, 0x000b, 0x0000, 0x0007, - 0x3943, 0x000a, 0x08db, 0x0003, 0x00ce, 0x0003, 0x00fe, 0x0000, - 0x34d9, 0x000b, 0x8072, 0x0000, 0x1000, 0x0000, 0x00db, 0x000b, - 0x8072, 0x0000, 0x2000, 0x0000, 0x4000, 0x000f, 0x86c0, 0x0009, - 0xfc00, 0x0008, 0x08d4, 0x0003, 0x00b2, 0x000b, 0x1c60, 0x0000, - 0x1b62, 0x0000, 0x8066, 0x0000, 0x0231, 0x0008, 0x44e4, 0x000b, - 0x58e5, 0x000b, 0x0140, 0x0008, 0x0242, 0x0000, 0x1f43, 0x0002, - 0x0cf3, 0x000b, 0x0d44, 0x0000, 0x0d46, 0x0008, 0x0348, 0x0008, - 0x044a, 0x0008, 0x030a, 0x0008, 0x040c, 0x0000, 0x0d06, 0x0000, - 0x0d08, 0x0008, 0x00f7, 0x0003, 0x0344, 0x0008, 0x0446, 0x0008, - 0x0548, 0x0008, 0x064a, 0x0000, 0x1948, 0x000a, 0x08fa, 0x0003, - 0x0d4a, 0x0008, 0x58fa, 0x0003, 0x3efe, 0x0008, 0x7f4f, 0x0002, - 0x0901, 0x0003, 0x8000, 0x0000, 0x0001, 0x0000, 0x0092, 0x000c, - 0x8054, 0x0008, 0x0001, 0x0000, 0x8074, 0x0000, 0x2020, 0x0008, - 0x4000, 0x000f, 0x3a40, 0x000a, 0x0c0d, 0x0003, 0x2b24, 0x0008, - 0x2b24, 0x0008, 0x590a, 0x000b, 0x8054, 0x0008, 0x0002, 0x0000, - 0x1242, 0x0002, 0x0958, 0x0003, 0x3a45, 0x000a, 0x0947, 0x000b, - 0x8072, 0x0000, 0x1000, 0x0000, 0x3945, 0x000a, 0x0917, 0x000b, - 0x8072, 0x0000, 0x3010, 0x0000, 0x1e10, 0x000a, 0x7f3c, 0x0000, - 0x0942, 0x000b, 0x1d00, 0x0002, 0x7f3a, 0x0000, 0x0d60, 0x0000, - 0x7f62, 0x0008, 0x8066, 0x0000, 0x0009, 0x0008, 0x4520, 0x000b, - 0x00fe, 0x0000, 0x353f, 0x000b, 0x1c60, 0x0000, 0x8062, 0x0008, - 0x0001, 0x0000, 0x8066, 0x0000, 0x0009, 0x0008, 0x4528, 0x0003, - 0x00fe, 0x0000, 0x325b, 0x000b, 0x0038, 0x0000, 0x0060, 0x0008, - 0x8062, 0x0008, 0x0019, 0x0000, 0x8066, 0x0000, 0x0009, 0x0008, - 0x4531, 0x000b, 0x80c0, 0x0009, 0x00ff, 0x0008, 0x7f3e, 0x0008, - 0x0d60, 0x0000, 0x0efe, 0x0008, 0x1f80, 0x0001, 0x7f62, 0x0008, - 0x8066, 0x0000, 0x0009, 0x0008, 0x453b, 0x000b, 0x003a, 0x0008, - 0x1dfe, 0x0000, 0x011c, 0x000b, 0x0036, 0x0008, 0x00e0, 0x000c, - 0x0158, 0x000b, 0x8074, 0x0000, 0x2000, 0x0000, 0x8072, 0x0000, - 0x2000, 0x0000, 0x0158, 0x000b, 0x3a44, 0x0002, 0x0a89, 0x0003, - 0x8074, 0x0000, 0x1000, 0x0000, 0x8072, 0x0000, 0x1000, 0x0000, - 0x2d0e, 0x0000, 0x2d0e, 0x0000, 0x3658, 0x0003, 0x26fe, 0x0008, - 0x26fe, 0x0008, 0x2700, 0x0008, 0x2700, 0x0008, 0x00d0, 0x0009, - 0x0d6a, 0x0003, 0x8074, 0x0000, 0x4040, 0x0008, 0x5958, 0x0003, - 0x5106, 0x0003, 0x3a46, 0x000a, 0x0d6a, 0x0003, 0x3a47, 0x0002, - 0x0965, 0x000b, 0x8054, 0x0008, 0x0004, 0x0000, 0x8074, 0x0000, - 0x8000, 0x0000, 0x8072, 0x0000, 0x3000, 0x0008, 0x01b4, 0x0003, - 0x92c0, 0x0009, 0x0fc8, 0x0000, 0x080a, 0x0003, 0x1246, 0x000a, - 0x0e52, 0x000b, 0x1a60, 0x0000, 0x8062, 0x0008, 0x0002, 0x0000, - 0x8066, 0x0000, 0x362a, 0x0000, 0x456f, 0x0003, 0x2000, 0x0000, - 0x2000, 0x0000, 0x2102, 0x0000, 0x2102, 0x0000, 0x2204, 0x0000, - 0x2204, 0x0000, 0x2306, 0x0000, 0x2306, 0x0000, 0x2408, 0x0000, - 0x2408, 0x0000, 0x250a, 0x0000, 0x250a, 0x0000, 0x260c, 0x0000, - 0x260c, 0x0000, 0x270e, 0x0000, 0x270e, 0x0000, 0x2810, 0x0000, - 0x2810, 0x0000, 0x2912, 0x0000, 0x2912, 0x0000, 0x1a60, 0x0000, - 0x8062, 0x0008, 0x0007, 0x0000, 0x8066, 0x0000, 0x0052, 0x0000, - 0x4589, 0x000b, 0x92c0, 0x0009, 0x0780, 0x0008, 0x0e6e, 0x000b, - 0x124b, 0x0002, 0x0992, 0x0003, 0x2e4d, 0x0002, 0x2e4d, 0x0002, - 0x0a58, 0x0003, 0x3a46, 0x000a, 0x0da2, 0x000b, 0x5994, 0x0003, - 0x8054, 0x0008, 0x0004, 0x0000, 0x1243, 0x000a, 0x09b0, 0x0003, - 0x8010, 0x0008, 0x000d, 0x0000, 0x0233, 0x000c, 0x1948, 0x000a, - 0x099f, 0x000b, 0x0228, 0x000c, 0x1810, 0x0000, 0x0233, 0x000c, - 0x01b0, 0x000b, 0x1948, 0x000a, 0x09a6, 0x000b, 0x1243, 0x000a, - 0x0a5b, 0x0003, 0x194d, 0x000a, 0x09aa, 0x000b, 0x1243, 0x000a, - 0x0a62, 0x0003, 0x59aa, 0x000b, 0x8054, 0x0008, 0x0004, 0x0000, - 0x0228, 0x000c, 0x1810, 0x0000, 0x0233, 0x000c, 0x8074, 0x0000, - 0xf000, 0x0008, 0x8072, 0x0000, 0x3000, 0x0008, 0x0d30, 0x0000, - 0x3a42, 0x0002, 0x0dba, 0x000b, 0x15fe, 0x0008, 0x3461, 0x000b, - 0x000a, 0x000b, 0x8074, 0x0000, 0x0501, 0x0000, 0x8010, 0x0008, - 0x000c, 0x0008, 0x0233, 0x000c, 0x000a, 0x000b, 0xbbe0, 0x0009, - 0x0030, 0x0008, 0x0dd0, 0x000b, 0x18fe, 0x0000, 0x3ce0, 0x0009, - 0x09cd, 0x0003, 0x15fe, 0x0008, 0x3ce0, 0x0009, 0x09cd, 0x0003, - 0x0223, 0x0004, 0x8076, 0x0008, 0x0040, 0x0000, 0x0220, 0x000b, - 0x8076, 0x0008, 0x0041, 0x0008, 0x0220, 0x000b, 0xbbe0, 0x0009, - 0x0032, 0x0000, 0x0dd5, 0x000b, 0x3c1e, 0x0008, 0x0220, 0x000b, - 0xbbe0, 0x0009, 0x003b, 0x0000, 0x0dda, 0x000b, 0x3c20, 0x0000, - 0x0220, 0x000b, 0xbbe0, 0x0009, 0x0035, 0x0008, 0x0de0, 0x000b, - 0x8072, 0x0000, 0x8000, 0x0000, 0x039e, 0x0003, 0xbbe0, 0x0009, - 0x0036, 0x0008, 0x0abd, 0x000b, 0xbbe0, 0x0009, 0x0037, 0x0000, - 0x0e01, 0x000b, 0x18fe, 0x0000, 0x3ce0, 0x0009, 0x0dcd, 0x000b, - 0x8076, 0x0008, 0x0040, 0x0000, 0x1a60, 0x0000, 0x8062, 0x0008, - 0x000d, 0x0000, 0x2604, 0x0008, 0x2604, 0x0008, 0x2706, 0x0008, - 0x2706, 0x0008, 0x2808, 0x0000, 0x2808, 0x0000, 0x290a, 0x0000, - 0x290a, 0x0000, 0x8066, 0x0000, 0x0422, 0x0000, 0x45f8, 0x000b, - 0x0228, 0x000c, 0x8054, 0x0008, 0x0004, 0x0000, 0x8074, 0x0000, - 0xf000, 0x0008, 0x8072, 0x0000, 0xb000, 0x0000, 0x01b4, 0x0003, - 0xbbe0, 0x0009, 0x0038, 0x0000, 0x0e13, 0x000b, 0x18fe, 0x0000, - 0x3ce0, 0x0009, 0x0a10, 0x0003, 0x15fe, 0x0008, 0x3ce0, 0x0009, - 0x0dc9, 0x0003, 0x0223, 0x0004, 0x8076, 0x0008, 0x0040, 0x0000, - 0x8072, 0x0000, 0x8000, 0x0000, 0x0280, 0x000b, 0x8076, 0x0008, - 0x0042, 0x0008, 0x0220, 0x000b, 0xbbe0, 0x0009, 0x0016, 0x0000, - 0x0e20, 0x000b, 0x8074, 0x0000, 0x0808, 0x0008, 0x3a44, 0x0002, - 0x0c0c, 0x000b, 0x8074, 0x0000, 0x0800, 0x0000, 0x8072, 0x0000, - 0x8000, 0x0000, 0x8000, 0x000f, 0x000a, 0x000b, 0x8072, 0x0000, - 0x8000, 0x0000, 0x000a, 0x000b, 0x3d30, 0x000a, 0x7f00, 0x0000, - 0xbc80, 0x0001, 0x0007, 0x0000, 0x022c, 0x000b, 0x1930, 0x000a, - 0x7f00, 0x0000, 0x9880, 0x0001, 0x0007, 0x0000, 0x8060, 0x0000, - 0x0400, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x000a, 0x0008, - 0x4631, 0x000b, 0x4000, 0x000f, 0x2236, 0x000b, 0x0870, 0x0008, - 0x4000, 0x000f, 0x7e33, 0x000b, 0xbbe0, 0x0009, 0x0030, 0x0008, - 0x0e33, 0x0003, 0x18fe, 0x0000, 0x3ce0, 0x0009, 0x0a44, 0x000b, - 0x15fe, 0x0008, 0x3ce0, 0x0009, 0x0a44, 0x000b, 0x0223, 0x0004, - 0x8076, 0x0008, 0x0040, 0x0000, 0x0246, 0x000b, 0x8076, 0x0008, - 0x0041, 0x0008, 0x8072, 0x0000, 0x8000, 0x0000, 0x0233, 0x0003, - 0xbac0, 0x0009, 0x0090, 0x0008, 0x0a4f, 0x0003, 0x8074, 0x0000, - 0x0706, 0x0000, 0x0251, 0x000b, 0x8074, 0x0000, 0x0703, 0x0000, - 0x4000, 0x000f, 0x8010, 0x0008, 0x0023, 0x0000, 0x028e, 0x0003, - 0x8010, 0x0008, 0x0008, 0x0000, 0x028e, 0x0003, 0x8010, 0x0008, - 0x0022, 0x0008, 0x028e, 0x0003, 0x0228, 0x000c, 0x8010, 0x0008, - 0x0007, 0x0000, 0x0233, 0x000c, 0x1810, 0x0000, 0x0233, 0x000c, - 0x029a, 0x0003, 0x0228, 0x000c, 0x8010, 0x0008, 0x001b, 0x0008, - 0x0233, 0x000c, 0x1810, 0x0000, 0x0233, 0x000c, 0x8074, 0x0000, - 0xf080, 0x0000, 0x8072, 0x0000, 0x3000, 0x0008, 0x0d30, 0x0000, - 0x000a, 0x000b, 0x8010, 0x0008, 0x0009, 0x0008, 0x028e, 0x0003, - 0x8010, 0x0008, 0x0005, 0x0008, 0x028e, 0x0003, 0x1648, 0x000a, - 0x0c6f, 0x000b, 0x808c, 0x0008, 0x0001, 0x0000, 0x8010, 0x0008, - 0x0004, 0x0000, 0x4143, 0x000a, 0x086f, 0x0003, 0x3a44, 0x0002, - 0x0c0a, 0x000b, 0x0d2a, 0x0008, 0x028e, 0x0003, 0x8010, 0x0008, - 0x0003, 0x0008, 0x0292, 0x000b, 0x8010, 0x0008, 0x000b, 0x0000, - 0x0292, 0x000b, 0x8010, 0x0008, 0x0002, 0x0000, 0x0292, 0x000b, - 0x3a47, 0x0002, 0x0d58, 0x000b, 0x8010, 0x0008, 0x0006, 0x0008, - 0x0292, 0x000b, 0x8074, 0x0000, 0xf000, 0x0008, 0x8072, 0x0000, - 0x3000, 0x0008, 0x0233, 0x000c, 0x0249, 0x0004, 0x3a40, 0x000a, - 0x080a, 0x0003, 0x8010, 0x0008, 0x000c, 0x0008, 0x0233, 0x000c, - 0x000a, 0x000b, 0x8074, 0x0000, 0xf080, 0x0000, 0x8072, 0x0000, - 0x3000, 0x0008, 0x0d30, 0x0000, 0x2e4d, 0x0002, 0x2e4d, 0x0002, - 0x0aa5, 0x000b, 0x8054, 0x0008, 0x0019, 0x0000, 0x000a, 0x000b, - 0x8054, 0x0008, 0x0009, 0x0008, 0x000a, 0x000b, 0x3a44, 0x0002, - 0x0c0a, 0x000b, 0x0283, 0x000b, 0x808c, 0x0008, 0x0000, 0x0008, - 0x4447, 0x0002, 0x0ad1, 0x000b, 0xc0c0, 0x0001, 0x00ff, 0x0008, - 0xffe0, 0x0009, 0x00ff, 0x0008, 0x0ea8, 0x000b, 0xc1e0, 0x0001, - 0xffff, 0x0008, 0x0ea8, 0x000b, 0x8010, 0x0008, 0x0013, 0x0000, - 0x0233, 0x000c, 0x8074, 0x0000, 0x0202, 0x0008, 0x000a, 0x000b, - 0x3a40, 0x000a, 0x0ece, 0x000b, 0x8074, 0x0000, 0x0200, 0x0000, - 0x3d00, 0x0000, 0x3cfe, 0x0000, 0x8072, 0x0000, 0x8000, 0x0000, - 0x43e0, 0x0001, 0x0ecc, 0x0003, 0x42fe, 0x0000, 0xffc0, 0x0001, - 0x00ff, 0x0008, 0x00e0, 0x0009, 0x0aa8, 0x0003, 0x0d08, 0x0008, - 0x0321, 0x000b, 0x8072, 0x0000, 0x8000, 0x0000, 0x000a, 0x000b, - 0x03a7, 0x000c, 0x808c, 0x0008, 0x0001, 0x0000, 0x04fe, 0x0008, - 0x338a, 0x0003, 0x0460, 0x0000, 0x8062, 0x0008, 0x0001, 0x0000, - 0x8066, 0x0000, 0x0009, 0x0008, 0x46db, 0x0003, 0x0004, 0x0000, - 0x80c0, 0x0009, 0x00ff, 0x0008, 0x7f00, 0x0000, 0x80e0, 0x0001, - 0x0004, 0x0000, 0x0af5, 0x000b, 0x80e0, 0x0001, 0x0005, 0x0008, - 0x0af5, 0x000b, 0x80e0, 0x0001, 0x0006, 0x0008, 0x0af5, 0x000b, - 0x82c0, 0x0001, 0xff00, 0x0008, 0x7f04, 0x0008, 0x82e0, 0x0009, - 0x0600, 0x0008, 0x0af5, 0x000b, 0x82e0, 0x0009, 0x0500, 0x0008, - 0x0af5, 0x000b, 0x82e0, 0x0009, 0x0400, 0x0000, 0x0f8a, 0x0003, - 0xc4c0, 0x0009, 0x7000, 0x0000, 0xffe0, 0x0009, 0x1000, 0x0000, - 0x0b21, 0x0003, 0x0398, 0x000c, 0x3941, 0x0002, 0x0b00, 0x0003, - 0x8072, 0x0000, 0x0400, 0x0000, 0x000a, 0x000b, 0x0460, 0x0000, - 0x80fe, 0x0008, 0x002b, 0x0008, 0x7f62, 0x0008, 0x8066, 0x0000, - 0x2209, 0x0008, 0x4706, 0x000b, 0x11fe, 0x0000, 0x331c, 0x0003, - 0x9180, 0x0001, 0x0002, 0x0000, 0x8060, 0x0000, 0x0400, 0x0000, - 0x7f62, 0x0008, 0x8066, 0x0000, 0x0609, 0x0008, 0x4710, 0x0003, - 0x42fe, 0x0000, 0xffc0, 0x0001, 0xff00, 0x0008, 0x03e0, 0x0009, - 0x0f19, 0x0003, 0x8072, 0x0000, 0x0400, 0x0000, 0x0046, 0x0003, - 0x9180, 0x0001, 0x0003, 0x0008, 0x0303, 0x000b, 0x8072, 0x0000, - 0x0400, 0x0000, 0x8010, 0x0008, 0x0010, 0x0000, 0x037b, 0x000b, - 0x0398, 0x000c, 0x3941, 0x0002, 0x0b27, 0x0003, 0x8072, 0x0000, - 0x0400, 0x0000, 0x000a, 0x000b, 0x1042, 0x000a, 0x0b2c, 0x000b, - 0x0360, 0x0004, 0x11fe, 0x0000, 0x3731, 0x000b, 0x8072, 0x0000, - 0x0400, 0x0000, 0x8010, 0x0008, 0x000e, 0x0000, 0x037b, 0x000b, - 0x8060, 0x0000, 0x0400, 0x0000, 0x04fe, 0x0008, 0x3746, 0x000b, - 0x808c, 0x0008, 0x0000, 0x0008, 0x9180, 0x0001, 0x0005, 0x0008, - 0x7f62, 0x0008, 0x8066, 0x0000, 0x0009, 0x0008, 0x473c, 0x000b, - 0x0060, 0x0008, 0x8062, 0x0008, 0x001b, 0x0008, 0x4304, 0x0008, - 0x4206, 0x0008, 0x8066, 0x0000, 0x0412, 0x0000, 0x4744, 0x000b, - 0x035d, 0x0003, 0x808c, 0x0008, 0x0001, 0x0000, 0x0460, 0x0000, - 0x8062, 0x0008, 0x002b, 0x0008, 0x8066, 0x0000, 0x0609, 0x0008, - 0x474d, 0x000b, 0x8066, 0x0000, 0x220a, 0x0008, 0x4750, 0x000b, - 0x42fe, 0x0000, 0xffc0, 0x0001, 0xff00, 0x0008, 0x7f04, 0x0008, - 0x8060, 0x0000, 0x0400, 0x0000, 0x9180, 0x0001, 0x0002, 0x0000, - 0x7f62, 0x0008, 0x8066, 0x0000, 0x041a, 0x0008, 0x475c, 0x000b, - 0x8072, 0x0000, 0x0400, 0x0000, 0x0046, 0x0003, 0x8060, 0x0000, - 0x0400, 0x0000, 0x1362, 0x0008, 0x8066, 0x0000, 0x0411, 0x0000, - 0x4765, 0x000b, 0x02fe, 0x0008, 0x03e0, 0x0009, 0x0f6b, 0x0003, - 0x0d22, 0x0000, 0x4000, 0x000f, 0x8280, 0x0009, 0x0002, 0x0000, - 0x1380, 0x0001, 0x7f62, 0x0008, 0x8066, 0x0000, 0x2209, 0x0008, - 0x4771, 0x000b, 0x0200, 0x000a, 0xffc0, 0x0001, 0x0007, 0x0000, - 0x7f06, 0x0000, 0x1362, 0x0008, 0x8066, 0x0000, 0x060a, 0x0008, - 0x4779, 0x0003, 0x4000, 0x000f, 0x3a44, 0x0002, 0x0c0a, 0x000b, - 0x2f44, 0x000a, 0x2f44, 0x000a, 0x0e83, 0x000b, 0x808a, 0x0008, - 0x0003, 0x0008, 0x8074, 0x0000, 0xf080, 0x0000, 0x8072, 0x0000, - 0x3000, 0x0008, 0x5b86, 0x000b, 0x8054, 0x0008, 0x0019, 0x0000, - 0x000a, 0x000b, 0x3a44, 0x0002, 0x0c0a, 0x000b, 0x808c, 0x0008, - 0x0000, 0x0008, 0x8010, 0x0008, 0x0011, 0x0008, 0x0233, 0x000c, - 0x42fe, 0x0000, 0xffc0, 0x0001, 0x00ff, 0x0008, 0x7f10, 0x0008, - 0x0233, 0x000c, 0x4310, 0x0008, 0x0292, 0x000b, 0x3941, 0x0002, - 0x0b9b, 0x000b, 0x4000, 0x000f, 0x8072, 0x0000, 0x0404, 0x0008, - 0x4000, 0x000f, 0x8010, 0x0008, 0x0012, 0x0008, 0x0233, 0x000c, - 0x0360, 0x0004, 0x1110, 0x0000, 0x0233, 0x000c, 0x11fe, 0x0000, - 0x37a1, 0x000b, 0x000a, 0x000b, 0xc2c0, 0x0009, 0x00ff, 0x0008, - 0x7f00, 0x0000, 0xc3c0, 0x0001, 0xff00, 0x0008, 0x00d0, 0x0009, - 0x0bcc, 0x0003, 0x0d0a, 0x0000, 0x8580, 0x0001, 0x1000, 0x0000, - 0x7f62, 0x0008, 0x8060, 0x0000, 0x0400, 0x0000, 0x8066, 0x0000, - 0x0809, 0x0000, 0x47b6, 0x0003, 0x04fe, 0x0008, 0x33c5, 0x000b, - 0x0460, 0x0000, 0x8062, 0x0008, 0x0004, 0x0000, 0x8066, 0x0000, - 0x0211, 0x0000, 0x47be, 0x000b, 0x01fe, 0x0008, 0x00e0, 0x0009, - 0x0fc5, 0x000b, 0x02fe, 0x0008, 0x43e0, 0x0001, 0x0bcb, 0x000b, - 0x0500, 0x0002, 0x7f0a, 0x0000, 0xffe0, 0x0009, 0x0800, 0x0000, - 0x0faf, 0x000b, 0x0d08, 0x0008, 0x4000, 0x000f, 0x43fe, 0x0008, - 0x3e80, 0x0001, 0xffc0, 0x0001, 0x7fff, 0x0000, 0x0d60, 0x0000, - 0x7f62, 0x0008, 0x8066, 0x0000, 0x0809, 0x0000, 0x47d4, 0x000b, - 0x8060, 0x0000, 0x0400, 0x0000, 0x84c0, 0x0001, 0xff00, 0x0008, - 0x7f60, 0x000a, 0x7f60, 0x000a, 0x7f60, 0x000a, 0x7f60, 0x000a, - 0x7f60, 0x000a, 0x7f60, 0x000a, 0x7f60, 0x000a, 0x7f60, 0x000a, - 0xff80, 0x0009, 0x1000, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, - 0x0809, 0x0000, 0x47e6, 0x0003, 0x4000, 0x000f, 0x8d5b, 0xeac4, - 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, - 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, - 0x12b0 -}; -#ifdef UNIQUE_FW_NAME -unsigned short fw2300ipx_length01 = 0xf091; -#else -unsigned short risc_code_length01 = 0xf091; -#endif - diff --git a/drivers/scsi/qla2xxx/ql2322.c b/drivers/scsi/qla2xxx/ql2322.c deleted file mode 100644 index 3c8cafc12ee..00000000000 --- a/drivers/scsi/qla2xxx/ql2322.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * QLogic Fibre Channel HBA Driver - * Copyright (c) 2003-2005 QLogic Corporation - * - * See LICENSE.qla2xxx for copyright and licensing details. - */ -#include -#include -#include - -#include "qla_def.h" - -static char qla_driver_name[] = "qla2322"; - -extern unsigned char fw2322ipx_version[]; -extern unsigned char fw2322ipx_version_str[]; -extern unsigned short fw2322ipx_addr01; -extern unsigned short fw2322ipx_code01[]; -extern unsigned short fw2322ipx_length01; -extern unsigned long rseqipx_code_addr01; -extern unsigned short rseqipx_code01[]; -extern unsigned short rseqipx_code_length01; -extern unsigned long xseqipx_code_addr01; -extern unsigned short xseqipx_code01[]; -extern unsigned short xseqipx_code_length01; - -static struct qla_fw_info qla_fw_tbl[] = { - { - .addressing = FW_INFO_ADDR_NORMAL, - .fwcode = &fw2322ipx_code01[0], - .fwlen = &fw2322ipx_length01, - .fwstart = &fw2322ipx_addr01, - }, - { - .addressing = FW_INFO_ADDR_EXTENDED, - .fwcode = &rseqipx_code01[0], - .fwlen = &rseqipx_code_length01, - .lfwstart = &rseqipx_code_addr01, - }, - { - .addressing = FW_INFO_ADDR_EXTENDED, - .fwcode = &xseqipx_code01[0], - .fwlen = &xseqipx_code_length01, - .lfwstart = &xseqipx_code_addr01, - }, - { FW_INFO_ADDR_NOMORE, }, -}; - -static struct qla_board_info qla_board_tbl[] = { - { - .drv_name = qla_driver_name, - .isp_name = "ISP2322", - .fw_info = qla_fw_tbl, - }, - { - .drv_name = qla_driver_name, - .isp_name = "ISP6322", - .fw_info = qla_fw_tbl, - }, -}; - -static struct pci_device_id qla2322_pci_tbl[] = { - { - .vendor = PCI_VENDOR_ID_QLOGIC, - .device = PCI_DEVICE_ID_QLOGIC_ISP2322, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = (unsigned long)&qla_board_tbl[0], - }, - { - .vendor = PCI_VENDOR_ID_QLOGIC, - .device = PCI_DEVICE_ID_QLOGIC_ISP6322, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = (unsigned long)&qla_board_tbl[1], - }, - {0, 0}, -}; -MODULE_DEVICE_TABLE(pci, qla2322_pci_tbl); - -static int __devinit -qla2322_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) -{ - return qla2x00_probe_one(pdev, - (struct qla_board_info *)id->driver_data); -} - -static void __devexit -qla2322_remove_one(struct pci_dev *pdev) -{ - qla2x00_remove_one(pdev); -} - -static struct pci_driver qla2322_pci_driver = { - .name = "qla2322", - .id_table = qla2322_pci_tbl, - .probe = qla2322_probe_one, - .remove = __devexit_p(qla2322_remove_one), -}; - -static int __init -qla2322_init(void) -{ - return pci_module_init(&qla2322_pci_driver); -} - -static void __exit -qla2322_exit(void) -{ - pci_unregister_driver(&qla2322_pci_driver); -} - -module_init(qla2322_init); -module_exit(qla2322_exit); - -MODULE_AUTHOR("QLogic Corporation"); -MODULE_DESCRIPTION("QLogic ISP2322 FC-SCSI Host Bus Adapter driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(QLA2XXX_VERSION); diff --git a/drivers/scsi/qla2xxx/ql2322_fw.c b/drivers/scsi/qla2xxx/ql2322_fw.c deleted file mode 100644 index 53599a8e2a9..00000000000 --- a/drivers/scsi/qla2xxx/ql2322_fw.c +++ /dev/null @@ -1,8376 +0,0 @@ -/* - * QLogic Fibre Channel HBA Driver - * Copyright (c) 2003-2005 QLogic Corporation - * - * See LICENSE.qla2xxx for copyright and licensing details. - */ - -/* - * Firmware Version 3.03.20 (15:42 Feb 01, 2006) - */ - -#ifdef UNIQUE_FW_NAME -unsigned short fw2322ipx_version = 3*1024+3; -#else -unsigned short risc_code_version = 3*1024+3; -#endif - -#ifdef UNIQUE_FW_NAME -unsigned char fw2322ipx_version_str[] = {3, 3,20}; -#else -unsigned char firmware_version[] = {3, 3,20}; -#endif - -#ifdef UNIQUE_FW_NAME -#define fw2322ipx_VERSION_STRING "3.03.20" -#else -#define FW_VERSION_STRING "3.03.20" -#endif - -#ifdef UNIQUE_FW_NAME -unsigned short fw2322ipx_addr01 = 0x0800 ; -#else -unsigned short risc_code_addr01 = 0x0800 ; -#endif - -#ifdef UNIQUE_FW_NAME -unsigned short fw2322ipx_code01[] = { -#else -unsigned short risc_code01[] = { -#endif - 0x0470, 0x0000, 0x0000, 0xe719, 0x0000, 0x0003, 0x0003, 0x0014, - 0x0137, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2032, 0x3030, - 0x3120, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241, - 0x5449, 0x4f4e, 0x2049, 0x5350, 0x3233, 0x3030, 0x2046, 0x6972, - 0x6d77, 0x6172, 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030, - 0x332e, 0x3033, 0x2e32, 0x3020, 0x2020, 0x2020, 0x2400, 0x20a9, - 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2200, 0x20a9, 0x000f, - 0x2001, 0x0000, 0x400f, 0x2091, 0x2400, 0x20a9, 0x000f, 0x2001, - 0x0000, 0x400f, 0x2091, 0x2600, 0x20a9, 0x000f, 0x2001, 0x0000, - 0x400f, 0x2091, 0x2800, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, - 0x2091, 0x2a00, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, - 0x2c00, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2e00, - 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2000, 0x2001, - 0x0000, 0x20c1, 0x0004, 0x20c9, 0x1cff, 0x2059, 0x0000, 0x2b78, - 0x7883, 0x0004, 0x2089, 0x2bc2, 0x2051, 0x1800, 0x2a70, 0x20e1, - 0x0001, 0x20e9, 0x0001, 0x2009, 0x0000, 0x080c, 0x0e74, 0x00f6, - 0x7888, 0x9005, 0x11f8, 0x2061, 0xc000, 0x080c, 0x20c6, 0x1170, - 0x2079, 0x0300, 0x080c, 0x20dc, 0x2061, 0xe000, 0x080c, 0x20c6, - 0x1128, 0x2079, 0x0380, 0x080c, 0x20dc, 0x0060, 0x00fe, 0x7883, - 0x4010, 0x7837, 0x4010, 0x7833, 0x0011, 0x2091, 0x5000, 0x2091, - 0x4080, 0x0cf8, 0x00fe, 0x2029, 0x5600, 0x2031, 0xffff, 0x2039, - 0x55dc, 0x2021, 0x0200, 0x20e9, 0x0001, 0x20a1, 0x0000, 0x20a9, - 0x0800, 0x900e, 0x4104, 0x20e9, 0x0001, 0x20a1, 0x1000, 0x900e, - 0x2001, 0x0dc1, 0x9084, 0x0fff, 0x20a8, 0x4104, 0x2001, 0x0000, - 0x9086, 0x0000, 0x0120, 0x21a8, 0x4104, 0x8001, 0x1de0, 0x756e, - 0x7672, 0x776a, 0x7476, 0x747a, 0x00e6, 0x2071, 0x1b73, 0x2472, - 0x00ee, 0x20a1, 0x1ddc, 0x7170, 0x810d, 0x810d, 0x810d, 0x810d, - 0x918c, 0x000f, 0x2001, 0x0001, 0x9112, 0x900e, 0x21a8, 0x4104, - 0x8211, 0x1de0, 0x7170, 0x3400, 0x8001, 0x9102, 0x0120, 0x0218, - 0x20a8, 0x900e, 0x4104, 0x2009, 0x1800, 0x810d, 0x810d, 0x810d, - 0x810d, 0x810d, 0x918c, 0x001f, 0x2001, 0x0001, 0x9112, 0x20e9, - 0x0001, 0x20a1, 0x0800, 0x900e, 0x20a9, 0x0800, 0x4104, 0x8211, - 0x1dd8, 0x080c, 0x0f71, 0x080c, 0x61ab, 0x080c, 0xb102, 0x080c, - 0x1128, 0x080c, 0x1352, 0x080c, 0x1c1c, 0x080c, 0x9582, 0x080c, - 0x0d17, 0x080c, 0x10ad, 0x080c, 0x358e, 0x080c, 0x7aca, 0x080c, - 0x6cea, 0x080c, 0x8c5d, 0x080c, 0x88be, 0x080c, 0x22bf, 0x080c, - 0x81f5, 0x080c, 0x20f5, 0x080c, 0x2233, 0x080c, 0x22b4, 0x2091, - 0x3009, 0x7883, 0x0000, 0x1004, 0x0943, 0x7880, 0x9086, 0x0002, - 0x1190, 0x7883, 0x4000, 0x7837, 0x4000, 0x7833, 0x0010, 0x0e04, - 0x0937, 0x2091, 0x5000, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, - 0xd084, 0x190c, 0x1200, 0x2071, 0x1800, 0x7003, 0x0000, 0x780c, - 0x9084, 0x0030, 0x9086, 0x0020, 0x1168, 0x7034, 0xc08d, 0x7036, - 0x2001, 0x0050, 0x7076, 0x707a, 0x7056, 0x606b, 0x269c, 0x2071, - 0x1b73, 0x2072, 0x2071, 0x1800, 0x7000, 0x908e, 0x0003, 0x1168, - 0x080c, 0x4d66, 0x080c, 0x35b5, 0x080c, 0x7b32, 0x080c, 0x7275, - 0x080c, 0x8d44, 0x080c, 0x88e7, 0x0c68, 0x000b, 0x0c88, 0x0979, - 0x097a, 0x0b15, 0x0977, 0x0bcf, 0x0d16, 0x0d16, 0x0d16, 0x080c, - 0x0d85, 0x0005, 0x0126, 0x00f6, 0x2091, 0x8000, 0x7000, 0x9086, - 0x0001, 0x1904, 0x0ae8, 0x080c, 0x0ec4, 0x080c, 0x779e, 0x0150, - 0x080c, 0x77c1, 0x15b0, 0x2079, 0x0100, 0x7828, 0x9085, 0x1800, - 0x782a, 0x0478, 0x080c, 0x76cd, 0x7000, 0x9086, 0x0001, 0x1904, - 0x0ae8, 0x7098, 0x9086, 0x0029, 0x1904, 0x0ae8, 0x080c, 0x88a7, - 0x080c, 0x8899, 0x2001, 0x0161, 0x2003, 0x0001, 0x2079, 0x0100, - 0x2011, 0xffff, 0x080c, 0x2ad3, 0x7a28, 0x9295, 0x5e2c, 0x7a2a, - 0x2011, 0x7612, 0x080c, 0x8993, 0x2011, 0x7605, 0x080c, 0x8a9f, - 0x2011, 0x6002, 0x080c, 0x8993, 0x2011, 0x8030, 0x901e, 0x7396, - 0x04d0, 0x080c, 0x58aa, 0x2079, 0x0100, 0x7844, 0x9005, 0x1904, - 0x0ae8, 0x2011, 0x6002, 0x080c, 0x8993, 0x2011, 0x7612, 0x080c, - 0x8993, 0x2011, 0x7605, 0x080c, 0x8a9f, 0x2001, 0x0265, 0x2001, - 0x0205, 0x2003, 0x0000, 0x7840, 0x9084, 0xfffb, 0x7842, 0x2001, - 0x19a7, 0x2004, 0x9005, 0x1140, 0x00c6, 0x2061, 0x0100, 0x080c, - 0x6153, 0x00ce, 0x0804, 0x0ae8, 0x780f, 0x006b, 0x7a28, 0x080c, - 0x77a6, 0x0118, 0x9295, 0x5e2c, 0x0010, 0x9295, 0x402c, 0x7a2a, - 0x2011, 0x8010, 0x73d8, 0x2001, 0x19a8, 0x2003, 0x0001, 0x080c, - 0x299b, 0x080c, 0x4ca1, 0x7248, 0xc284, 0x724a, 0x2001, 0x180c, - 0x200c, 0xc1ac, 0xc1cc, 0x2102, 0x2001, 0x0390, 0x2003, 0x0400, - 0x080c, 0xacfc, 0x080c, 0xa4f1, 0x2011, 0x0004, 0x080c, 0xcf2b, - 0x080c, 0xad18, 0x080c, 0x6ab1, 0x080c, 0x779e, 0x1120, 0x080c, - 0x29fc, 0x0600, 0x0420, 0x080c, 0x615a, 0x0140, 0x7097, 0x0001, - 0x70d3, 0x0000, 0x080c, 0x5a7c, 0x0804, 0x0ae8, 0x2001, 0x0390, - 0x2003, 0x0404, 0x080c, 0x5840, 0xd094, 0x0188, 0x2011, 0x180c, - 0x2204, 0xc0cd, 0x2012, 0x080c, 0x5844, 0xd0d4, 0x1118, 0x080c, - 0x29fc, 0x1270, 0x2011, 0x180c, 0x2204, 0xc0bc, 0x00a8, 0x080c, - 0x5844, 0xd0d4, 0x1db8, 0x2011, 0x180c, 0x2204, 0xc0bd, 0x0060, - 0x2011, 0x180c, 0x2204, 0xc0bd, 0x2012, 0x080c, 0x6c09, 0x1128, - 0xd0a4, 0x0118, 0x2204, 0xc0fd, 0x2012, 0x080c, 0x6bcf, 0x0120, - 0x7a0c, 0xc2b4, 0x7a0e, 0x00a8, 0x707f, 0x0000, 0x080c, 0x779e, - 0x1130, 0x70b0, 0x9005, 0x1168, 0x080c, 0xd389, 0x0050, 0x080c, - 0xd389, 0x70dc, 0xd09c, 0x1128, 0x70b0, 0x9005, 0x0110, 0x080c, - 0x6130, 0x70e7, 0x0000, 0x70e3, 0x0000, 0x70a7, 0x0000, 0x080c, - 0x2a04, 0x0228, 0x2011, 0x0101, 0x2204, 0xc0c4, 0x2012, 0x72dc, - 0x080c, 0x779e, 0x1178, 0x9016, 0x0016, 0x080c, 0x27a4, 0x2019, - 0x196d, 0x211a, 0x001e, 0x705f, 0xffff, 0x7063, 0x00ef, 0x7083, - 0x0000, 0x0020, 0x2019, 0x196d, 0x201b, 0x0000, 0x2079, 0x1847, - 0x7804, 0xd0ac, 0x0108, 0xc295, 0x72de, 0x080c, 0x779e, 0x0118, - 0x9296, 0x0004, 0x0518, 0x2011, 0x0001, 0x080c, 0xcf2b, 0x70ab, - 0x0000, 0x70af, 0xffff, 0x7003, 0x0002, 0x00fe, 0x080c, 0x30bf, - 0x080c, 0xacfc, 0x2011, 0x0005, 0x080c, 0xa62b, 0x080c, 0xad18, - 0x080c, 0x779e, 0x0148, 0x00c6, 0x2061, 0x0100, 0x0016, 0x080c, - 0x27a4, 0x61e2, 0x001e, 0x00ce, 0x012e, 0x00e0, 0x70ab, 0x0000, - 0x70af, 0xffff, 0x7003, 0x0002, 0x080c, 0xacfc, 0x2011, 0x0005, - 0x080c, 0xa62b, 0x080c, 0xad18, 0x080c, 0x779e, 0x0148, 0x00c6, - 0x2061, 0x0100, 0x0016, 0x080c, 0x27a4, 0x61e2, 0x001e, 0x00ce, - 0x00fe, 0x012e, 0x0005, 0x00c6, 0x00b6, 0x080c, 0x779e, 0x1118, - 0x20a9, 0x0800, 0x0010, 0x20a9, 0x0782, 0x080c, 0x779e, 0x1110, - 0x900e, 0x0010, 0x2009, 0x007e, 0x86ff, 0x0138, 0x9180, 0x1000, - 0x2004, 0x905d, 0x0110, 0xb800, 0xd0bc, 0x090c, 0x341e, 0x8108, - 0x1f04, 0x0afc, 0x707f, 0x0000, 0x7080, 0x9084, 0x00ff, 0x7082, - 0x70b3, 0x0000, 0x00be, 0x00ce, 0x0005, 0x00b6, 0x0126, 0x2091, - 0x8000, 0x7000, 0x9086, 0x0002, 0x1904, 0x0bcc, 0x70ac, 0x9086, - 0xffff, 0x0120, 0x080c, 0x30bf, 0x0804, 0x0bcc, 0x70dc, 0xd0ac, - 0x1110, 0xd09c, 0x0538, 0xd084, 0x0528, 0x0006, 0x2001, 0x0103, - 0x2003, 0x002b, 0x000e, 0xd08c, 0x01e8, 0x080c, 0x3487, 0x11b0, - 0x70e0, 0x9086, 0xffff, 0x0190, 0x080c, 0x327b, 0x70dc, 0xd094, - 0x1904, 0x0bcc, 0x2011, 0x0001, 0x080c, 0xd645, 0x0110, 0x2011, - 0x0003, 0x901e, 0x080c, 0x32b5, 0x0804, 0x0bcc, 0x70e4, 0x9005, - 0x1904, 0x0bcc, 0x70a8, 0x9005, 0x1904, 0x0bcc, 0x70dc, 0xd0a4, - 0x0118, 0xd0b4, 0x0904, 0x0bcc, 0x080c, 0x6bcf, 0x1904, 0x0bcc, - 0x080c, 0x6c22, 0x1904, 0x0bcc, 0x080c, 0x6c09, 0x01c0, 0x0156, - 0x00c6, 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, 0x67b4, 0x1118, - 0xb800, 0xd0ec, 0x1138, 0x001e, 0x8108, 0x1f04, 0x0b6c, 0x00ce, - 0x015e, 0x0028, 0x001e, 0x00ce, 0x015e, 0x0804, 0x0bcc, 0x0006, - 0x2001, 0x0103, 0x2003, 0x002b, 0x000e, 0x2011, 0x19b4, 0x080c, - 0x0fe1, 0x2011, 0x19ce, 0x080c, 0x0fe1, 0x7030, 0xc08c, 0x7032, - 0x7003, 0x0003, 0x70af, 0xffff, 0x080c, 0x0e98, 0x9006, 0x080c, - 0x2631, 0x080c, 0x3487, 0x0118, 0x080c, 0x4e3e, 0x0050, 0x0036, - 0x0046, 0x2019, 0xffff, 0x2021, 0x0006, 0x080c, 0x4e58, 0x004e, - 0x003e, 0x00f6, 0x2079, 0x0100, 0x080c, 0x77c1, 0x0150, 0x080c, - 0x779e, 0x7828, 0x0118, 0x9084, 0xe1ff, 0x0010, 0x9084, 0xffdf, - 0x782a, 0x00fe, 0x080c, 0xacfc, 0x2001, 0x19e9, 0x2004, 0x9086, - 0x0005, 0x1120, 0x2011, 0x0000, 0x080c, 0xa62b, 0x2011, 0x0000, - 0x080c, 0xa635, 0x080c, 0xad18, 0x012e, 0x00be, 0x0005, 0x0016, - 0x0026, 0x0046, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2079, 0x0100, - 0x7904, 0x918c, 0xfffd, 0x7906, 0x2009, 0x00f7, 0x080c, 0x6119, - 0x7940, 0x918c, 0x0010, 0x7942, 0x7924, 0xd1b4, 0x0120, 0x2011, - 0x0040, 0x080c, 0x2ad3, 0xd19c, 0x0120, 0x2011, 0x0008, 0x080c, - 0x2ad3, 0x0006, 0x0036, 0x0156, 0x0000, 0x2001, 0x19a8, 0x2004, - 0x9005, 0x1518, 0x080c, 0x2a67, 0x1148, 0x2001, 0x0001, 0x080c, - 0x29ca, 0x2001, 0x0001, 0x080c, 0x29ad, 0x00b8, 0x080c, 0x2a6f, - 0x1138, 0x9006, 0x080c, 0x29ca, 0x9006, 0x080c, 0x29ad, 0x0068, - 0x080c, 0x2a77, 0x1d50, 0x2001, 0x1998, 0x2004, 0xd0fc, 0x0108, - 0x0020, 0x080c, 0x27d8, 0x0804, 0x0cc9, 0x20a9, 0x003a, 0x1d04, - 0x0c1f, 0x080c, 0x8a7f, 0x1f04, 0x0c1f, 0x080c, 0x77af, 0x0148, - 0x080c, 0x77c1, 0x1118, 0x080c, 0x7ac5, 0x0050, 0x080c, 0x77a6, - 0x0dd0, 0x080c, 0x7ac0, 0x080c, 0x7ab6, 0x080c, 0x76cd, 0x0020, - 0x2009, 0x00f8, 0x080c, 0x6119, 0x7850, 0xc0e5, 0x7852, 0x080c, - 0x779e, 0x0120, 0x7843, 0x0090, 0x7843, 0x0010, 0x2021, 0xe678, - 0x2019, 0xea60, 0x0d0c, 0x8a7f, 0x7820, 0xd09c, 0x15a0, 0x080c, - 0x779e, 0x0904, 0x0cab, 0x7824, 0xd0ac, 0x1904, 0x0cce, 0x080c, - 0x77c1, 0x1548, 0x0046, 0x2021, 0x0320, 0x8421, 0x1df0, 0x004e, - 0x2011, 0x1800, 0x080c, 0x2ad3, 0x080c, 0x2a7f, 0x7824, 0x9084, - 0x1800, 0x1168, 0x9484, 0x0fff, 0x1140, 0x2001, 0x1810, 0x2004, - 0x9084, 0x9000, 0x0110, 0x080c, 0x0cf1, 0x8421, 0x1160, 0x1d04, - 0x0c7b, 0x080c, 0x8a7f, 0x080c, 0x7ac0, 0x080c, 0x7ab6, 0x7003, - 0x0001, 0x0804, 0x0cce, 0x8319, 0x1928, 0x2001, 0x1810, 0x2004, - 0x9084, 0x9000, 0x0110, 0x080c, 0x0cf1, 0x1d04, 0x0c91, 0x080c, - 0x8a7f, 0x2009, 0x199b, 0x2104, 0x9005, 0x0118, 0x8001, 0x200a, - 0x1188, 0x200b, 0x000a, 0x2011, 0x0048, 0x080c, 0x2ad3, 0x20a9, - 0x0002, 0x080c, 0x2a60, 0x7924, 0x080c, 0x2a7f, 0xd19c, 0x0110, - 0x080c, 0x299b, 0x00f0, 0x080c, 0x77af, 0x1140, 0x94a2, 0x03e8, - 0x1128, 0x080c, 0x7772, 0x7003, 0x0001, 0x00c0, 0x2011, 0x1800, - 0x080c, 0x2ad3, 0x080c, 0x2a7f, 0x7824, 0x080c, 0x77b8, 0x0110, - 0xd0ac, 0x1160, 0x9084, 0x1800, 0x0904, 0x0c83, 0x7003, 0x0001, - 0x0028, 0x2001, 0x0001, 0x080c, 0x2631, 0x00a0, 0x7850, 0xc0e4, - 0x7852, 0x2009, 0x180c, 0x210c, 0xd19c, 0x1120, 0x7904, 0x918d, - 0x0002, 0x7906, 0x2011, 0x0048, 0x080c, 0x2ad3, 0x7828, 0x9085, - 0x0028, 0x782a, 0x2001, 0x19a8, 0x2003, 0x0000, 0x9006, 0x78f2, - 0x015e, 0x003e, 0x000e, 0x012e, 0x00fe, 0x004e, 0x002e, 0x001e, - 0x0005, 0x0006, 0x0016, 0x0026, 0x0036, 0x0046, 0x00b6, 0x00c6, - 0x00d6, 0x00e6, 0x00f6, 0x0156, 0x0071, 0x0d0c, 0x8a7f, 0x015e, - 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x004e, 0x003e, 0x002e, - 0x001e, 0x000e, 0x0005, 0x00e6, 0x2071, 0x189e, 0x7004, 0x9086, - 0x0001, 0x1110, 0x080c, 0x35b5, 0x00ee, 0x0005, 0x0005, 0x2a70, - 0x2061, 0x19ac, 0x2063, 0x0003, 0x6007, 0x0003, 0x600b, 0x0014, - 0x600f, 0x0137, 0x2001, 0x197c, 0x900e, 0x2102, 0x7196, 0x2001, - 0x0100, 0x2004, 0x9082, 0x0002, 0x0218, 0x705f, 0xffff, 0x0008, - 0x715e, 0x7067, 0xffff, 0x717e, 0x7182, 0x080c, 0xd389, 0x70ef, - 0x00c0, 0x2061, 0x196c, 0x6003, 0x0909, 0x6106, 0x600b, 0x8800, - 0x600f, 0x0200, 0x6013, 0x00ff, 0x6017, 0x001f, 0x611a, 0x601f, - 0x07d0, 0x2061, 0x1974, 0x6003, 0x8000, 0x6106, 0x610a, 0x600f, - 0x0200, 0x6013, 0x00ff, 0x6116, 0x601b, 0x0001, 0x611e, 0x2061, - 0x1989, 0x6003, 0x514c, 0x6007, 0x4f47, 0x600b, 0x4943, 0x600f, - 0x2020, 0x2001, 0x182c, 0x2102, 0x0005, 0x9016, 0x080c, 0x67b4, - 0x1178, 0xb804, 0x90c4, 0x00ff, 0x98c6, 0x0006, 0x0128, 0x90c4, - 0xff00, 0x98c6, 0x0600, 0x1120, 0x9186, 0x0080, 0x0108, 0x8210, - 0x8108, 0x9186, 0x0800, 0x1d50, 0x2208, 0x0005, 0x2091, 0x8000, - 0x2079, 0x0000, 0x000e, 0x00f6, 0x0010, 0x2091, 0x8000, 0x0e04, - 0x0d87, 0x0006, 0x0016, 0x2001, 0x8002, 0x0006, 0x2079, 0x0000, - 0x000e, 0x7882, 0x7836, 0x001e, 0x798e, 0x000e, 0x788a, 0x000e, - 0x7886, 0x3900, 0x789a, 0x00d6, 0x2069, 0x0300, 0x6818, 0x78ae, - 0x681c, 0x78b2, 0x6808, 0x78be, 0x00de, 0x7833, 0x0012, 0x2091, - 0x5000, 0x0156, 0x00d6, 0x0036, 0x0026, 0x2079, 0x0300, 0x2069, - 0x1b2b, 0x7a08, 0x226a, 0x2069, 0x1b2c, 0x7a18, 0x226a, 0x8d68, - 0x7a1c, 0x226a, 0x782c, 0x2019, 0x1b39, 0x201a, 0x2019, 0x1b3c, - 0x9016, 0x7808, 0xd09c, 0x0168, 0x7820, 0x201a, 0x8210, 0x8318, - 0x9386, 0x1b55, 0x0108, 0x0ca8, 0x7808, 0xd09c, 0x0110, 0x2011, - 0xdead, 0x2019, 0x1b3a, 0x782c, 0x201a, 0x8318, 0x221a, 0x7803, - 0x0000, 0x2069, 0x1a81, 0x901e, 0x20a9, 0x0020, 0x7b26, 0x7a28, - 0x226a, 0x8d68, 0x8318, 0x1f04, 0x0dde, 0x2069, 0x1aa1, 0x2019, - 0x0050, 0x20a9, 0x0020, 0x7b26, 0x7a28, 0x226a, 0x8d68, 0x8318, - 0x1f04, 0x0deb, 0x0491, 0x002e, 0x003e, 0x00de, 0x015e, 0x2079, - 0x1800, 0x7803, 0x0005, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, - 0xd084, 0x0180, 0x2001, 0x1a25, 0x2004, 0x9005, 0x0128, 0x2001, - 0x008b, 0x2004, 0xd0fc, 0x0dd8, 0x2001, 0x008a, 0x2003, 0x0002, - 0x2003, 0x1001, 0x080c, 0x584f, 0x1170, 0x080c, 0x0f32, 0x0110, - 0x080c, 0x0e85, 0x080c, 0x584f, 0x1130, 0x2071, 0x1800, 0x2011, - 0x8000, 0x080c, 0x0f46, 0x0c70, 0x0005, 0x2001, 0x0382, 0x2004, - 0x9084, 0x0007, 0x9086, 0x0001, 0x1120, 0x2001, 0x0015, 0x080c, - 0xaced, 0x2079, 0x0380, 0x2069, 0x1b0b, 0x7818, 0x6802, 0x781c, - 0x6806, 0x7840, 0x680a, 0x7844, 0x680e, 0x782c, 0x6812, 0x2019, - 0x1b16, 0x9016, 0x7808, 0xd09c, 0x0150, 0x7820, 0x201a, 0x8210, - 0x8318, 0x8210, 0x9282, 0x0011, 0x0ea8, 0x2011, 0xdead, 0x6a2a, - 0x7830, 0x681a, 0x7834, 0x681e, 0x7838, 0x6822, 0x783c, 0x6826, - 0x7803, 0x0000, 0x2069, 0x1acb, 0x901e, 0x20a9, 0x0020, 0x7b26, - 0x7828, 0x206a, 0x8d68, 0x8318, 0x1f04, 0x0e5f, 0x2069, 0x1aeb, - 0x2019, 0x00b0, 0x20a9, 0x0020, 0x7b26, 0x7828, 0x206a, 0x8d68, - 0x8318, 0x1f04, 0x0e6c, 0x0005, 0x918c, 0x03ff, 0x2001, 0x0003, - 0x2004, 0x9084, 0x0600, 0x1118, 0x918d, 0x6c00, 0x0010, 0x918d, - 0x6400, 0x2001, 0x017f, 0x2102, 0x0005, 0x0026, 0x0126, 0x2011, - 0x0080, 0x080c, 0x0f24, 0x20a9, 0x0900, 0x080c, 0x0f5a, 0x2011, - 0x0040, 0x080c, 0x0f24, 0x20a9, 0x0900, 0x080c, 0x0f5a, 0x0c78, - 0x0026, 0x080c, 0x0f32, 0x1188, 0x2011, 0x010e, 0x2214, 0x9294, - 0x0007, 0x9296, 0x0007, 0x0118, 0x2011, 0x0947, 0x0010, 0x2011, - 0x1b47, 0x080c, 0x0f46, 0x002e, 0x0005, 0x2011, 0x010e, 0x2214, - 0x9294, 0x0007, 0x9296, 0x0007, 0x0118, 0x2011, 0xa880, 0x0010, - 0x2011, 0x6840, 0xd0e4, 0x70f3, 0x0000, 0x1120, 0x70f3, 0x0fa0, - 0x080c, 0x0f37, 0x002e, 0x0005, 0x0026, 0x080c, 0x0f32, 0x0148, - 0xd0a4, 0x1138, 0x2011, 0xcdd5, 0x0010, 0x2011, 0x0080, 0x080c, - 0x0f37, 0x002e, 0x0005, 0x0026, 0x70f3, 0x0000, 0x080c, 0x0f32, - 0x1130, 0x2011, 0x8040, 0x080c, 0x0f46, 0x002e, 0x0005, 0x080c, - 0x2a77, 0x1118, 0x2011, 0xcdc5, 0x0010, 0x2011, 0xcac2, 0x080c, - 0x0f37, 0x002e, 0x0005, 0x00e6, 0x0016, 0x0006, 0x2071, 0x1800, - 0xd0b4, 0x70ec, 0x71e8, 0x1118, 0xc0e4, 0xc1f4, 0x0050, 0x0006, - 0x3b00, 0x9084, 0xff3e, 0x20d8, 0x000e, 0x70f3, 0x0000, 0xc0e5, - 0xc1f5, 0x0099, 0x000e, 0x001e, 0x00ee, 0x0005, 0x00e6, 0x2071, - 0x1800, 0xd0e4, 0x70ec, 0x1110, 0xc0dc, 0x0008, 0xc0dd, 0x0016, - 0x71e8, 0x0019, 0x001e, 0x00ee, 0x0005, 0x70ee, 0x71ea, 0x7000, - 0x9084, 0x0007, 0x000b, 0x0005, 0x0eea, 0x0ec4, 0x0ec4, 0x0e98, - 0x0ed3, 0x0ec4, 0x0ec4, 0x0ed3, 0xc284, 0x0016, 0x3b08, 0x3a00, - 0x9104, 0x918d, 0x00c1, 0x21d8, 0x9084, 0xff3e, 0x9205, 0x20d0, - 0x001e, 0x0005, 0x2001, 0x183b, 0x2004, 0xd0dc, 0x0005, 0x9e86, - 0x1800, 0x190c, 0x0d85, 0x70ec, 0xd0e4, 0x0108, 0xc2e5, 0x72ee, - 0xd0e4, 0x1118, 0x9294, 0x00c1, 0x08f9, 0x0005, 0x9e86, 0x1800, - 0x190c, 0x0d85, 0x70e8, 0xd0f4, 0x0108, 0xc2f5, 0x72ea, 0xd0f4, - 0x1140, 0x9284, 0x8000, 0x8005, 0xc284, 0x9215, 0x9294, 0x00c1, - 0x0861, 0x0005, 0x1d04, 0x0f5a, 0x2091, 0x6000, 0x1f04, 0x0f5a, - 0x0005, 0x890e, 0x810e, 0x810f, 0x9194, 0x003f, 0x918c, 0xffc0, - 0x0005, 0x0006, 0x2200, 0x914d, 0x894f, 0x894d, 0x894d, 0x000e, - 0x0005, 0x01d6, 0x0146, 0x0036, 0x0096, 0x2061, 0x188d, 0x600b, - 0x0000, 0x600f, 0x0000, 0x6003, 0x0000, 0x6007, 0x0000, 0x2009, - 0xffc0, 0x2105, 0x0006, 0x2001, 0xaaaa, 0x200f, 0x2019, 0x5555, - 0x9016, 0x2049, 0x0bff, 0xab02, 0xa001, 0xa001, 0xa800, 0x9306, - 0x1138, 0x2105, 0x9306, 0x0120, 0x8210, 0x99c8, 0x0400, 0x0c98, - 0x000e, 0x200f, 0x2001, 0x189d, 0x928a, 0x000e, 0x1638, 0x928a, - 0x0006, 0x2011, 0x0006, 0x1210, 0x2011, 0x0000, 0x2202, 0x9006, - 0x2008, 0x82ff, 0x01b0, 0x8200, 0x600a, 0x600f, 0xffff, 0x6003, - 0x0002, 0x6007, 0x0000, 0x0026, 0x2019, 0x0010, 0x9280, 0x0001, - 0x20e8, 0x21a0, 0x21a8, 0x4104, 0x8319, 0x1de0, 0x8211, 0x1da0, - 0x002e, 0x009e, 0x003e, 0x014e, 0x01de, 0x0005, 0x2011, 0x000e, - 0x08e8, 0x0016, 0x0026, 0x0096, 0x3348, 0x080c, 0x0f61, 0x2100, - 0x9300, 0x2098, 0x22e0, 0x009e, 0x002e, 0x001e, 0x0036, 0x3518, - 0x20a9, 0x0001, 0x4002, 0x8007, 0x4004, 0x8319, 0x1dd8, 0x003e, - 0x0005, 0x20e9, 0x0001, 0x71b8, 0x81ff, 0x11c0, 0x9006, 0x2009, - 0x0200, 0x20a9, 0x0002, 0x9298, 0x0018, 0x23a0, 0x4001, 0x2009, - 0x0700, 0x20a9, 0x0002, 0x9298, 0x0008, 0x23a0, 0x4001, 0x707c, - 0x8007, 0x7180, 0x810f, 0x20a9, 0x0002, 0x4001, 0x9298, 0x000c, - 0x23a0, 0x900e, 0x080c, 0x0d65, 0x2001, 0x0000, 0x810f, 0x20a9, - 0x0002, 0x4001, 0x0005, 0x89ff, 0x0140, 0xa804, 0xa807, 0x0000, - 0x0006, 0x080c, 0x108b, 0x009e, 0x0cb0, 0x0005, 0x00e6, 0x2071, - 0x1800, 0x080c, 0x1104, 0x090c, 0x0d85, 0x00ee, 0x0005, 0x0086, - 0x00e6, 0x0006, 0x0026, 0x0036, 0x0126, 0x2091, 0x8000, 0x00c9, - 0x2071, 0x1800, 0x73c0, 0x702c, 0x9016, 0x9045, 0x0158, 0x8210, - 0x9906, 0x090c, 0x0d85, 0x2300, 0x9202, 0x0120, 0x1a0c, 0x0d85, - 0xa000, 0x0c98, 0x012e, 0x003e, 0x002e, 0x000e, 0x00ee, 0x008e, - 0x0005, 0x0086, 0x00e6, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, - 0x1910, 0x7010, 0x9005, 0x0140, 0x7018, 0x9045, 0x0128, 0x9906, - 0x090c, 0x0d85, 0xa000, 0x0cc8, 0x012e, 0x000e, 0x00ee, 0x008e, - 0x0005, 0x00e6, 0x2071, 0x1800, 0x0126, 0x2091, 0x8000, 0x70c0, - 0x8001, 0x0270, 0x70c2, 0x702c, 0x2048, 0x9085, 0x0001, 0xa800, - 0x702e, 0xa803, 0x0000, 0xa807, 0x0000, 0x012e, 0x00ee, 0x0005, - 0x904e, 0x0cd8, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0x1800, - 0x70c0, 0x90ca, 0x0020, 0x0268, 0x8001, 0x70c2, 0x702c, 0x2048, - 0xa800, 0x702e, 0xa803, 0x0000, 0xa807, 0x0000, 0x012e, 0x00ee, - 0x0005, 0x904e, 0x0cd8, 0x00e6, 0x0126, 0x2091, 0x8000, 0x0016, - 0x890e, 0x810e, 0x810f, 0x9184, 0x003f, 0xa862, 0x9184, 0xffc0, - 0xa85e, 0x001e, 0x0020, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, - 0x1800, 0x702c, 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, - 0x080c, 0x8899, 0x012e, 0x00ee, 0x0005, 0x2071, 0x1800, 0x9026, - 0x2009, 0x0000, 0x2049, 0x0400, 0x2900, 0x702e, 0x8940, 0x2800, - 0xa802, 0xa95e, 0xa863, 0x0001, 0x8420, 0x9886, 0x0440, 0x0120, - 0x2848, 0x9188, 0x0040, 0x0c90, 0x2071, 0x188d, 0x7000, 0x9005, - 0x11a0, 0x2001, 0x0558, 0xa802, 0x2048, 0x2009, 0x5600, 0x8940, - 0x2800, 0xa802, 0xa95e, 0xa863, 0x0001, 0x8420, 0x9886, 0x0800, - 0x0120, 0x2848, 0x9188, 0x0040, 0x0c90, 0x2071, 0x188d, 0x7104, - 0x7200, 0x82ff, 0x01d0, 0x7308, 0x8318, 0x831f, 0x831b, 0x831b, - 0x7312, 0x8319, 0x2001, 0x0800, 0xa802, 0x2048, 0x8900, 0xa802, - 0x2040, 0xa95e, 0xaa62, 0x8420, 0x2300, 0x9906, 0x0130, 0x2848, - 0x9188, 0x0040, 0x9291, 0x0000, 0x0c88, 0xa803, 0x0000, 0x2071, - 0x1800, 0x74be, 0x74c2, 0x0005, 0x00e6, 0x0016, 0x9984, 0xfc00, - 0x01e8, 0x908c, 0xf800, 0x1168, 0x9982, 0x0400, 0x02b8, 0x9982, - 0x0440, 0x0278, 0x9982, 0x0558, 0x0288, 0x9982, 0x0800, 0x1270, - 0x0040, 0x9982, 0x0800, 0x0250, 0x2071, 0x188d, 0x7010, 0x9902, - 0x1228, 0x9085, 0x0001, 0x001e, 0x00ee, 0x0005, 0x9006, 0x0cd8, - 0x00e6, 0x2071, 0x1a24, 0x7007, 0x0000, 0x9006, 0x701e, 0x7022, - 0x7002, 0x2071, 0x0000, 0x7010, 0x9085, 0x8044, 0x7012, 0x2071, - 0x0080, 0x9006, 0x702b, 0x0060, 0x20a9, 0x0040, 0x7022, 0x1f04, - 0x113e, 0x702b, 0x0060, 0x702b, 0x0020, 0x20a9, 0x0040, 0x7022, - 0x1f04, 0x1147, 0x702b, 0x0020, 0x00ee, 0x0005, 0x0126, 0x2091, - 0x8000, 0x00e6, 0xa06f, 0x0000, 0x2071, 0x1a24, 0x701c, 0x9088, - 0x1a2e, 0x280a, 0x8000, 0x9084, 0x003f, 0x701e, 0x7120, 0x9106, - 0x090c, 0x0d85, 0x7004, 0x9005, 0x1128, 0x00f6, 0x2079, 0x0080, - 0x00a9, 0x00fe, 0x00ee, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, - 0x00e6, 0x2071, 0x1a24, 0x7004, 0x9005, 0x1128, 0x00f6, 0x2079, - 0x0080, 0x0021, 0x00fe, 0x00ee, 0x012e, 0x0005, 0x7004, 0x9086, - 0x0000, 0x1110, 0x7007, 0x0006, 0x7000, 0x0002, 0x1190, 0x1313, - 0x118e, 0x118e, 0x1307, 0x1307, 0x1307, 0x1307, 0x080c, 0x0d85, - 0x701c, 0x7120, 0x9106, 0x1148, 0x792c, 0x9184, 0x0001, 0x1120, - 0xd1fc, 0x1110, 0x7007, 0x0000, 0x0005, 0x0096, 0x9180, 0x1a2e, - 0x2004, 0x700a, 0x2048, 0x8108, 0x918c, 0x003f, 0x7122, 0x782b, - 0x0026, 0xa88c, 0x7802, 0xa890, 0x7806, 0xa894, 0x780a, 0xa898, - 0x780e, 0xa878, 0x700e, 0xa870, 0x7016, 0xa874, 0x701a, 0xa868, - 0x009e, 0xd084, 0x0120, 0x7007, 0x0001, 0x0029, 0x0005, 0x7007, - 0x0002, 0x00b1, 0x0005, 0x0016, 0x0026, 0x710c, 0x2011, 0x0040, - 0x9182, 0x0040, 0x1210, 0x2110, 0x9006, 0x700e, 0x7212, 0x8203, - 0x7812, 0x782b, 0x0020, 0x782b, 0x0041, 0x002e, 0x001e, 0x0005, - 0x0016, 0x0026, 0x0136, 0x0146, 0x0156, 0x7014, 0x20e0, 0x7018, - 0x2098, 0x20e9, 0x0000, 0x20a1, 0x0088, 0x782b, 0x0026, 0x710c, - 0x2011, 0x0040, 0x9182, 0x0040, 0x1210, 0x2110, 0x9006, 0x700e, - 0x22a8, 0x4006, 0x8203, 0x7812, 0x782b, 0x0020, 0x3300, 0x701a, - 0x782b, 0x0001, 0x015e, 0x014e, 0x013e, 0x002e, 0x001e, 0x0005, - 0x2009, 0x1a24, 0x2104, 0xc095, 0x200a, 0x080c, 0x116d, 0x0005, - 0x0016, 0x00e6, 0x2071, 0x1a24, 0x00f6, 0x2079, 0x0080, 0x792c, - 0xd1bc, 0x190c, 0x0d7e, 0x782b, 0x0002, 0xd1fc, 0x0120, 0x918c, - 0x0700, 0x7004, 0x0023, 0x00fe, 0x00ee, 0x001e, 0x0005, 0x117e, - 0x1226, 0x125a, 0x1332, 0x0d85, 0x134d, 0x0d85, 0x918c, 0x0700, - 0x1550, 0x0136, 0x0146, 0x0156, 0x7014, 0x20e8, 0x7018, 0x20a0, - 0x20e1, 0x0000, 0x2099, 0x0088, 0x782b, 0x0040, 0x7010, 0x20a8, - 0x4005, 0x3400, 0x701a, 0x015e, 0x014e, 0x013e, 0x700c, 0x9005, - 0x0578, 0x7800, 0x7802, 0x7804, 0x7806, 0x080c, 0x11c3, 0x0005, - 0x7008, 0x0096, 0x2048, 0xa86f, 0x0100, 0x009e, 0x7007, 0x0000, - 0x080c, 0x117e, 0x0005, 0x7008, 0x0096, 0x2048, 0xa86f, 0x0200, - 0x009e, 0x0ca0, 0x918c, 0x0700, 0x1150, 0x700c, 0x9005, 0x0180, - 0x7800, 0x7802, 0x7804, 0x7806, 0x080c, 0x11d8, 0x0005, 0x7008, - 0x0096, 0x2048, 0xa86f, 0x0200, 0x009e, 0x7007, 0x0000, 0x0080, - 0x0096, 0x7008, 0x2048, 0x7800, 0xa88e, 0x7804, 0xa892, 0x7808, - 0xa896, 0x780c, 0xa89a, 0xa86f, 0x0100, 0x009e, 0x7007, 0x0000, - 0x0096, 0x00d6, 0x7008, 0x2048, 0x2001, 0x18b9, 0x2004, 0x9906, - 0x1128, 0xa89c, 0x080f, 0x00de, 0x009e, 0x00a0, 0x00de, 0x009e, - 0x0096, 0x00d6, 0x7008, 0x2048, 0x0081, 0x0150, 0xa89c, 0x0086, - 0x2940, 0x080f, 0x008e, 0x00de, 0x009e, 0x080c, 0x116d, 0x0005, - 0x00de, 0x009e, 0x080c, 0x116d, 0x0005, 0xa8a8, 0xd08c, 0x0005, - 0x0096, 0xa0a0, 0x904d, 0x090c, 0x0d85, 0xa06c, 0x908e, 0x0100, - 0x0130, 0xa87b, 0x0030, 0xa883, 0x0000, 0xa897, 0x4002, 0x080c, - 0x7006, 0xa09f, 0x0000, 0xa0a3, 0x0000, 0x2848, 0x080c, 0x108b, - 0x009e, 0x0005, 0x00a6, 0xa0a0, 0x904d, 0x090c, 0x0d85, 0xa06c, - 0x908e, 0x0100, 0x0128, 0xa87b, 0x0001, 0xa883, 0x0000, 0x00c0, - 0xa80c, 0x2050, 0xb004, 0x9005, 0x0198, 0xa80e, 0x2050, 0x8006, - 0x8006, 0x8007, 0x908c, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, - 0xa076, 0xa172, 0xb000, 0xa07a, 0x2810, 0x080c, 0x114e, 0x00e8, - 0xa97c, 0xa894, 0x0016, 0x0006, 0x080c, 0x7006, 0x000e, 0x001e, - 0xd1fc, 0x1138, 0xd1f4, 0x0128, 0x00c6, 0x2060, 0x080c, 0xb16c, - 0x00ce, 0x7008, 0x2048, 0xa89f, 0x0000, 0xa8a3, 0x0000, 0x080c, - 0x108b, 0x7007, 0x0000, 0x080c, 0x116d, 0x00ae, 0x0005, 0x0126, - 0x2091, 0x8000, 0x782b, 0x1001, 0x7007, 0x0005, 0x7000, 0xc094, - 0x7002, 0x012e, 0x0005, 0x0096, 0x2001, 0x192f, 0x204c, 0xa87c, - 0x7812, 0xa88c, 0x7802, 0xa890, 0x7806, 0xa894, 0x780a, 0xa898, - 0x780e, 0x782b, 0x0020, 0x0126, 0x2091, 0x8000, 0x782b, 0x0041, - 0x7007, 0x0003, 0x7000, 0xc084, 0x7002, 0x2900, 0x700a, 0x012e, - 0x009e, 0x0005, 0x20e1, 0x0000, 0x2099, 0x0088, 0x782b, 0x0040, - 0x0096, 0x2001, 0x192f, 0x204c, 0xaa7c, 0x009e, 0x080c, 0x8f88, - 0x2009, 0x188c, 0x2104, 0x9084, 0xfffc, 0x200a, 0x080c, 0x8de7, - 0x7007, 0x0000, 0x080c, 0x117e, 0x0005, 0x7007, 0x0000, 0x080c, - 0x117e, 0x0005, 0x0126, 0x2091, 0x2200, 0x2079, 0x0300, 0x2071, - 0x1a6e, 0x7003, 0x0000, 0x78bf, 0x00f6, 0x0041, 0x7807, 0x0007, - 0x7803, 0x0000, 0x7803, 0x0001, 0x012e, 0x0005, 0x00c6, 0x7803, - 0x0000, 0x2001, 0x0165, 0x2003, 0x4198, 0x7808, 0xd09c, 0x0120, - 0x7820, 0x080c, 0x13b6, 0x0cc8, 0x2001, 0x1a6f, 0x2003, 0x0000, - 0x78ab, 0x0004, 0x78ac, 0xd0ac, 0x1de8, 0x78ab, 0x0002, 0x7807, - 0x0007, 0x7827, 0x0030, 0x782b, 0x0400, 0x7827, 0x0031, 0x782b, - 0x1a81, 0x78e3, 0xff00, 0x781f, 0xff00, 0x781b, 0xff00, 0x2001, - 0x1a70, 0x2003, 0x0000, 0x2001, 0x0200, 0x2004, 0xd0dc, 0x0110, - 0x781f, 0x0303, 0x2061, 0x1a81, 0x602f, 0x1ddc, 0x2001, 0x181a, - 0x2004, 0x9082, 0x1ddc, 0x6032, 0x603b, 0x1ec1, 0x602b, 0x1ac1, - 0x6007, 0x1aa1, 0x2061, 0x1aa1, 0x606f, 0x193d, 0x2001, 0x1928, - 0x2004, 0x607a, 0x783f, 0x348e, 0x00ce, 0x0005, 0x9086, 0x000d, - 0x11d0, 0x7808, 0xd09c, 0x01b8, 0x7820, 0x0026, 0x2010, 0x080c, - 0xcf09, 0x0180, 0x2260, 0x6000, 0x9086, 0x0004, 0x1158, 0x0016, - 0x6120, 0x9186, 0x0009, 0x0108, 0x0020, 0x2009, 0x004c, 0x080c, - 0xb20a, 0x001e, 0x002e, 0x0005, 0x0126, 0x2091, 0x2200, 0x7908, - 0x9184, 0x0070, 0x190c, 0x0d7e, 0xd19c, 0x05a0, 0x7820, 0x908c, - 0xf000, 0x0540, 0x2060, 0x6020, 0x9086, 0x0003, 0x1550, 0x6000, - 0x9086, 0x0004, 0x1530, 0x6114, 0x2148, 0xa876, 0xa87a, 0xa867, - 0x0103, 0x080c, 0x6e27, 0x00b6, 0x6010, 0x2058, 0xba3c, 0x8211, - 0x0208, 0xba3e, 0xb8d0, 0x9005, 0x190c, 0x68df, 0x00be, 0x6044, - 0xd0fc, 0x190c, 0xad25, 0x080c, 0xb195, 0x7808, 0xd09c, 0x19b0, - 0x012e, 0x0005, 0x908a, 0x0024, 0x1a0c, 0x0d85, 0x002b, 0x012e, - 0x0005, 0x04b0, 0x012e, 0x0005, 0x1438, 0x145e, 0x148e, 0x1493, - 0x1497, 0x149c, 0x14c4, 0x14c8, 0x14d6, 0x14da, 0x1438, 0x15a7, - 0x15ab, 0x161d, 0x1624, 0x1438, 0x1625, 0x1626, 0x1631, 0x1638, - 0x1438, 0x1438, 0x1438, 0x1438, 0x1438, 0x1438, 0x1438, 0x149e, - 0x1438, 0x1466, 0x148b, 0x1452, 0x1438, 0x1472, 0x143c, 0x143a, - 0x080c, 0x0d85, 0x080c, 0x0d7e, 0x080c, 0x1643, 0x2009, 0x1a7d, - 0x2104, 0x8000, 0x200a, 0x080c, 0x82b8, 0x080c, 0x1b1e, 0x0005, - 0x6044, 0xd0fc, 0x190c, 0xad25, 0x2009, 0x0055, 0x080c, 0xb20a, - 0x012e, 0x0005, 0x080c, 0x1643, 0x2060, 0x6044, 0xd0fc, 0x190c, - 0xad25, 0x2009, 0x0055, 0x080c, 0xb20a, 0x0005, 0x2009, 0x0048, - 0x080c, 0x1643, 0x2060, 0x080c, 0xb20a, 0x0005, 0x2009, 0x0054, - 0x080c, 0x1643, 0x2060, 0x6044, 0xd0fc, 0x190c, 0xad25, 0x080c, - 0xb20a, 0x0005, 0x080c, 0x1643, 0x2060, 0x0056, 0x0066, 0x080c, - 0x1643, 0x2028, 0x080c, 0x1643, 0x2030, 0x0036, 0x0046, 0x2021, - 0x0000, 0x2418, 0x2009, 0x0056, 0x080c, 0xb20a, 0x004e, 0x003e, - 0x006e, 0x005e, 0x0005, 0x080c, 0x1643, 0x0005, 0x7004, 0xc085, - 0xc0b5, 0x7006, 0x0005, 0x7004, 0xc085, 0x7006, 0x0005, 0x080c, - 0x1643, 0x080c, 0x1740, 0x0005, 0x080c, 0x0d85, 0x080c, 0x1643, - 0x2060, 0x6014, 0x0096, 0x2048, 0xa83b, 0xffff, 0x009e, 0x2009, - 0x0048, 0x080c, 0xb20a, 0x2001, 0x015d, 0x2003, 0x0000, 0x2009, - 0x03e8, 0x8109, 0x0160, 0x2001, 0x0201, 0x2004, 0x9005, 0x0dc8, - 0x2001, 0x0218, 0x2004, 0xd0ec, 0x1110, 0x080c, 0x1648, 0x2001, - 0x0307, 0x2003, 0x8000, 0x0005, 0x7004, 0xc095, 0x7006, 0x0005, - 0x080c, 0x1643, 0x2060, 0x6014, 0x0096, 0x2048, 0xa83b, 0xffff, - 0x009e, 0x2009, 0x0048, 0x080c, 0xb20a, 0x0005, 0x080c, 0x1643, - 0x080c, 0x0d85, 0x080c, 0x1643, 0x080c, 0x1592, 0x7827, 0x0018, - 0x79ac, 0xd1dc, 0x0904, 0x1543, 0x7827, 0x0015, 0x7828, 0x782b, - 0x0000, 0x9065, 0x0140, 0x2001, 0x020d, 0x2003, 0x0050, 0x2003, - 0x0020, 0x0804, 0x1549, 0x7004, 0x9005, 0x01c8, 0x1188, 0x78ab, - 0x0004, 0x7827, 0x0018, 0x782b, 0x0000, 0xd1bc, 0x090c, 0x0d85, - 0x2001, 0x020d, 0x2003, 0x0050, 0x2003, 0x0020, 0x0804, 0x1577, - 0x78ab, 0x0004, 0x7803, 0x0001, 0x080c, 0x15ab, 0x0005, 0x7827, - 0x0018, 0xa001, 0x7828, 0x7827, 0x0011, 0xa001, 0x7928, 0x9106, - 0x0110, 0x79ac, 0x08e0, 0x00e6, 0x2071, 0x0200, 0x702c, 0xd0c4, - 0x0140, 0x00ee, 0x080c, 0x1b1e, 0x080c, 0x1366, 0x7803, 0x0001, - 0x0005, 0x7037, 0x0001, 0xa001, 0x7150, 0x00ee, 0x918c, 0xff00, - 0x9186, 0x0500, 0x0110, 0x79ac, 0x0810, 0x7004, 0xc09d, 0x7006, - 0x78ab, 0x0004, 0x7803, 0x0001, 0x080c, 0x15ab, 0x2001, 0x020d, - 0x2003, 0x0020, 0x0005, 0x7828, 0x782b, 0x0000, 0x9065, 0x090c, - 0x0d85, 0x6014, 0x2048, 0x78ab, 0x0004, 0x918c, 0x0700, 0x01a8, - 0x080c, 0x82b8, 0x080c, 0x1b1e, 0x080c, 0xcf1b, 0x0158, 0xa9ac, - 0xa936, 0xa9b0, 0xa93a, 0xa83f, 0xffff, 0xa843, 0xffff, 0xa880, - 0xc0bd, 0xa882, 0x080c, 0xcae9, 0x0005, 0x6020, 0x9086, 0x0009, - 0x1128, 0x2009, 0x004c, 0x080c, 0xb20a, 0x0048, 0x6010, 0x00b6, - 0x2058, 0xb800, 0x00be, 0xd0bc, 0x6024, 0x190c, 0xd31e, 0x2029, - 0x00c8, 0x8529, 0x0128, 0x2001, 0x0201, 0x2004, 0x9005, 0x0dc8, - 0x7dbc, 0x080c, 0xeeb1, 0xd5a4, 0x1118, 0x080c, 0x1648, 0x0005, - 0x080c, 0x82b8, 0x080c, 0x1b1e, 0x0005, 0x781f, 0x0300, 0x7803, - 0x0001, 0x0005, 0x0016, 0x0066, 0x0076, 0x00f6, 0x2079, 0x0300, - 0x7908, 0x918c, 0x0007, 0x9186, 0x0003, 0x0120, 0x2001, 0x0016, - 0x080c, 0x16b9, 0x00fe, 0x007e, 0x006e, 0x001e, 0x0005, 0x7004, - 0xc09d, 0x7006, 0x0005, 0x7104, 0x9184, 0x0004, 0x190c, 0x0d85, - 0xd184, 0x11b1, 0xd19c, 0x0180, 0xc19c, 0x7106, 0x0016, 0x080c, - 0x1723, 0x001e, 0x0148, 0x2001, 0x020d, 0x2003, 0x0050, 0x2003, - 0x0020, 0x080c, 0x1648, 0x0005, 0x81ff, 0x190c, 0x0d85, 0x0005, - 0x2100, 0xc184, 0xc1b4, 0x7106, 0xd0b4, 0x0016, 0x00e6, 0x1904, - 0x1612, 0x2071, 0x0200, 0x080c, 0x1710, 0x05e0, 0x080c, 0x1723, - 0x05b0, 0x6014, 0x9005, 0x05b0, 0x0096, 0x2048, 0xa864, 0x009e, - 0x9084, 0x00ff, 0x908e, 0x0029, 0x0160, 0x908e, 0x0048, 0x1550, - 0x601c, 0xd084, 0x11e0, 0x00f6, 0x2c78, 0x080c, 0x17ad, 0x00fe, - 0x00b0, 0x00f6, 0x2c78, 0x080c, 0x1942, 0x00fe, 0x2009, 0x01f4, - 0x8109, 0x0168, 0x2001, 0x0201, 0x2004, 0x9005, 0x0dc8, 0x2001, - 0x0218, 0x2004, 0xd0ec, 0x1118, 0x080c, 0x1648, 0x0040, 0x2001, - 0x020d, 0x2003, 0x0020, 0x080c, 0x1366, 0x7803, 0x0001, 0x00ee, - 0x001e, 0x0005, 0x080c, 0x1723, 0x0dd0, 0x2001, 0x020d, 0x2003, - 0x0050, 0x2003, 0x0020, 0x0461, 0x0c90, 0x0429, 0x2060, 0x2009, - 0x0053, 0x080c, 0xb20a, 0x0005, 0x0005, 0x0005, 0x00e1, 0x2008, - 0x00d1, 0x0006, 0x7004, 0xc09d, 0x7006, 0x000e, 0x080c, 0x92d5, - 0x0005, 0x0089, 0x9005, 0x0118, 0x080c, 0x8ed9, 0x0cd0, 0x0005, - 0x2001, 0x0036, 0x2009, 0x1820, 0x210c, 0x2011, 0x181f, 0x2214, - 0x080c, 0x16b9, 0x0005, 0x7808, 0xd09c, 0x0de8, 0x7820, 0x0005, - 0x080c, 0x1592, 0x00d6, 0x2069, 0x0200, 0x2009, 0x01f4, 0x8109, - 0x0510, 0x6804, 0x9005, 0x0dd8, 0x2001, 0x015d, 0x2003, 0x0000, - 0x79bc, 0xd1a4, 0x1528, 0x79b8, 0x918c, 0x0fff, 0x0180, 0x9182, - 0x0841, 0x1268, 0x9188, 0x0007, 0x918c, 0x0ff8, 0x810c, 0x810c, - 0x810c, 0x080c, 0x16ab, 0x6827, 0x0001, 0x8109, 0x1dd0, 0x04d9, - 0x6827, 0x0002, 0x04c1, 0x6804, 0x9005, 0x1130, 0x682c, 0xd0e4, - 0x1500, 0x6804, 0x9005, 0x0de8, 0x79b8, 0xd1ec, 0x1130, 0x08c0, - 0x080c, 0x82b8, 0x080c, 0x1b1e, 0x0090, 0x7827, 0x0015, 0x782b, - 0x0000, 0x7827, 0x0018, 0x782b, 0x0000, 0x2001, 0x020d, 0x2003, - 0x0020, 0x2001, 0x0307, 0x2003, 0x0300, 0x7803, 0x0001, 0x00de, - 0x0005, 0x682c, 0x9084, 0x5400, 0x9086, 0x5400, 0x0d30, 0x7827, - 0x0015, 0x782b, 0x0000, 0x7803, 0x0001, 0x6800, 0x9085, 0x1800, - 0x6802, 0x00de, 0x0005, 0x6824, 0x9084, 0x0003, 0x1de0, 0x0005, - 0x2001, 0x0030, 0x2c08, 0x621c, 0x0021, 0x7830, 0x9086, 0x0041, - 0x0005, 0x00f6, 0x00e6, 0x2079, 0x0300, 0x0006, 0x2071, 0x1a6e, - 0x7008, 0x9005, 0x1110, 0x78e3, 0x0c0c, 0x8000, 0x700a, 0x0026, - 0x2011, 0x0006, 0x7808, 0xd09c, 0x0150, 0x0016, 0x0026, 0x00c6, - 0x080c, 0x13d4, 0x00ce, 0x002e, 0x001e, 0x8211, 0x1d98, 0x002e, - 0x000e, 0x0006, 0x7832, 0x7936, 0x7a3a, 0x781b, 0x8080, 0x00b9, - 0x1178, 0x2071, 0x1a6e, 0x7008, 0x9005, 0x0130, 0x8001, 0x0a0c, - 0x0d85, 0x700a, 0x78e3, 0x0c00, 0x000e, 0x00ee, 0x00fe, 0x0005, - 0x000e, 0x792c, 0x3900, 0x8000, 0x2004, 0x080c, 0x0d85, 0x2009, - 0xff00, 0x8109, 0x0120, 0x7818, 0xd0bc, 0x1dd8, 0x0005, 0x9085, - 0x0001, 0x0005, 0x7832, 0x7936, 0x7a3a, 0x781b, 0x8080, 0x0c79, - 0x1108, 0x0005, 0x792c, 0x3900, 0x8000, 0x2004, 0x080c, 0x0d85, - 0x7037, 0x0001, 0x7150, 0x7037, 0x0002, 0x7050, 0x2060, 0xd1bc, - 0x1110, 0x7054, 0x2060, 0x918c, 0xff00, 0x9186, 0x0500, 0x0110, - 0x9085, 0x0001, 0x0005, 0x0006, 0x0046, 0x00e6, 0x2071, 0x0200, - 0x7037, 0x0002, 0x7058, 0x9084, 0xff00, 0x8007, 0x9086, 0x00bc, - 0x1158, 0x2021, 0x1a7e, 0x2404, 0x8000, 0x0208, 0x2022, 0x080c, - 0x82b8, 0x080c, 0x1b1e, 0x9006, 0x00ee, 0x004e, 0x000e, 0x0005, - 0x0c11, 0x1108, 0x0005, 0x00e6, 0x0016, 0x2071, 0x0200, 0x0841, - 0x6124, 0xd1dc, 0x01f8, 0x701c, 0xd08c, 0x0904, 0x17a2, 0x7017, - 0x0000, 0x2001, 0x0264, 0x2004, 0xd0bc, 0x0904, 0x17a2, 0x2001, - 0x0268, 0x00c6, 0x2064, 0x6104, 0x6038, 0x00ce, 0x918e, 0x0039, - 0x1904, 0x17a2, 0x9c06, 0x15f0, 0x0126, 0x2091, 0x2600, 0x080c, - 0x8210, 0x012e, 0x7358, 0x745c, 0x6014, 0x905d, 0x0598, 0x2b48, - 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x190c, 0xd2f9, - 0xab42, 0xac3e, 0x2001, 0x1869, 0x2004, 0xd0b4, 0x1170, 0x601c, - 0xd0e4, 0x1158, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, - 0x1120, 0xa83b, 0x7fff, 0xa837, 0xffff, 0x080c, 0x1ee1, 0x1190, - 0x080c, 0x199f, 0x2a00, 0xa816, 0x0130, 0x2800, 0xa80e, 0x2c05, - 0xa80a, 0x2c00, 0xa812, 0x7037, 0x0020, 0x781f, 0x0300, 0x001e, - 0x00ee, 0x0005, 0x7037, 0x0050, 0x7037, 0x0020, 0x001e, 0x00ee, - 0x080c, 0x1648, 0x0005, 0x080c, 0x0d85, 0x2001, 0x180d, 0x2004, - 0xd08c, 0x190c, 0x6ccc, 0x2cf0, 0x0126, 0x2091, 0x2200, 0x0016, - 0x00c6, 0x3e60, 0x6014, 0x2048, 0x2940, 0x903e, 0x2730, 0xa864, - 0x2068, 0xa81a, 0x9d84, 0x000f, 0x9088, 0x1ec1, 0x2165, 0x0002, - 0x17df, 0x184d, 0x17df, 0x17df, 0x17e3, 0x182e, 0x17df, 0x1803, - 0x17d8, 0x1844, 0x17df, 0x17df, 0x17e8, 0x193a, 0x1817, 0x180d, - 0xa964, 0x918c, 0x00ff, 0x918e, 0x0048, 0x0904, 0x1844, 0x9085, - 0x0001, 0x0804, 0x1930, 0xa87c, 0xd0ac, 0x0dc8, 0x0804, 0x1854, - 0xa87c, 0xd0ac, 0x0da0, 0x0804, 0x18bf, 0xa898, 0x901d, 0x1108, - 0xab9c, 0x9016, 0xaab2, 0xaa3e, 0xaa42, 0x3e00, 0x9080, 0x0008, - 0x2004, 0x9080, 0x9536, 0x2005, 0x9005, 0x090c, 0x0d85, 0x2004, - 0xa8ae, 0x0804, 0x1918, 0xa87c, 0xd0bc, 0x09c8, 0xa890, 0xa842, - 0xa88c, 0xa83e, 0xa888, 0x0804, 0x1854, 0xa87c, 0xd0bc, 0x0978, - 0xa890, 0xa842, 0xa88c, 0xa83e, 0xa888, 0x0804, 0x18bf, 0xa87c, - 0xd0bc, 0x0928, 0xa890, 0xa842, 0xa88c, 0xa83e, 0xa804, 0x9045, - 0x090c, 0x0d85, 0xa164, 0xa91a, 0x91ec, 0x000f, 0x9d80, 0x1ec1, - 0x2065, 0xa888, 0xd19c, 0x1904, 0x18bf, 0x0430, 0xa87c, 0xd0ac, - 0x0904, 0x17df, 0xa804, 0x9045, 0x090c, 0x0d85, 0xa164, 0xa91a, - 0x91ec, 0x000f, 0x9d80, 0x1ec1, 0x2065, 0x9006, 0xa842, 0xa83e, - 0xd19c, 0x1904, 0x18bf, 0x0080, 0xa87c, 0xd0ac, 0x0904, 0x17df, - 0x9006, 0xa842, 0xa83e, 0x0804, 0x18bf, 0xa87c, 0xd0ac, 0x0904, - 0x17df, 0x9006, 0xa842, 0xa83e, 0x2c05, 0x908a, 0x0036, 0x1a0c, - 0x0d85, 0x9082, 0x001b, 0x0002, 0x1877, 0x1877, 0x1879, 0x1877, - 0x1877, 0x1877, 0x1883, 0x1877, 0x1877, 0x1877, 0x188d, 0x1877, - 0x1877, 0x1877, 0x1897, 0x1877, 0x1877, 0x1877, 0x18a1, 0x1877, - 0x1877, 0x1877, 0x18ab, 0x1877, 0x1877, 0x1877, 0x18b5, 0x080c, - 0x0d85, 0xa574, 0xa478, 0x9d86, 0x0024, 0x0904, 0x17ed, 0xa37c, - 0xa280, 0x0804, 0x1918, 0xa584, 0xa488, 0x9d86, 0x0024, 0x0904, - 0x17ed, 0xa38c, 0xa290, 0x0804, 0x1918, 0xa594, 0xa498, 0x9d86, - 0x0024, 0x0904, 0x17ed, 0xa39c, 0xa2a0, 0x0804, 0x1918, 0xa5a4, - 0xa4a8, 0x9d86, 0x0024, 0x0904, 0x17ed, 0xa3ac, 0xa2b0, 0x0804, - 0x1918, 0xa5b4, 0xa4b8, 0x9d86, 0x0024, 0x0904, 0x17ed, 0xa3bc, - 0xa2c0, 0x0804, 0x1918, 0xa5c4, 0xa4c8, 0x9d86, 0x0024, 0x0904, - 0x17ed, 0xa3cc, 0xa2d0, 0x0804, 0x1918, 0xa5d4, 0xa4d8, 0x9d86, - 0x0024, 0x0904, 0x17ed, 0xa3dc, 0xa2e0, 0x0804, 0x1918, 0x2c05, - 0x908a, 0x0034, 0x1a0c, 0x0d85, 0x9082, 0x001b, 0x0002, 0x18e2, - 0x18e0, 0x18e0, 0x18e0, 0x18e0, 0x18e0, 0x18ed, 0x18e0, 0x18e0, - 0x18e0, 0x18e0, 0x18e0, 0x18f8, 0x18e0, 0x18e0, 0x18e0, 0x18e0, - 0x18e0, 0x1903, 0x18e0, 0x18e0, 0x18e0, 0x18e0, 0x18e0, 0x190e, - 0x080c, 0x0d85, 0xa56c, 0xa470, 0xa774, 0xa678, 0x9d86, 0x002c, - 0x0904, 0x17ed, 0xa37c, 0xa280, 0x0458, 0xa584, 0xa488, 0xa78c, - 0xa690, 0x9d86, 0x002c, 0x0904, 0x17ed, 0xa394, 0xa298, 0x0400, - 0xa59c, 0xa4a0, 0xa7a4, 0xa6a8, 0x9d86, 0x002c, 0x0904, 0x17ed, - 0xa3ac, 0xa2b0, 0x00a8, 0xa5b4, 0xa4b8, 0xa7bc, 0xa6c0, 0x9d86, - 0x002c, 0x0904, 0x17ed, 0xa3c4, 0xa2c8, 0x0050, 0xa5cc, 0xa4d0, - 0xa7d4, 0xa6d8, 0x9d86, 0x002c, 0x0904, 0x17ed, 0xa3dc, 0xa2e0, - 0xab2e, 0xaa32, 0xad1e, 0xac22, 0xaf26, 0xae2a, 0xa988, 0x8c60, - 0x2c1d, 0xa8ac, 0xaab0, 0xa836, 0xaa3a, 0x8109, 0xa916, 0x1160, - 0x3e60, 0x601c, 0xc085, 0x601e, 0xa87c, 0xc0dd, 0xa87e, 0x9006, - 0x00ce, 0x001e, 0x012e, 0x0005, 0x2800, 0xa80e, 0xab0a, 0x2c00, - 0xa812, 0x0c70, 0x0804, 0x17df, 0x2001, 0x180d, 0x2004, 0xd08c, - 0x190c, 0x6ccc, 0x2ff0, 0x0126, 0x2091, 0x2200, 0x0016, 0x00c6, - 0x3e60, 0x6014, 0x2048, 0x2940, 0xa80e, 0x2061, 0x1ebc, 0xa813, - 0x1ebc, 0x2c05, 0xa80a, 0xa964, 0xa91a, 0xa87c, 0xd0ac, 0x090c, - 0x0d85, 0x9006, 0xa842, 0xa83e, 0x2c05, 0x908a, 0x0034, 0x1a0c, - 0x0d85, 0xadcc, 0xacd0, 0xafd4, 0xaed8, 0xabdc, 0xaae0, 0xab2e, - 0xaa32, 0xad1e, 0xac22, 0xaf26, 0xae2a, 0xa8ac, 0xaab0, 0xa836, - 0xaa3a, 0xa988, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0008, 0x1120, - 0x8109, 0xa916, 0x0128, 0x0080, 0x918a, 0x0002, 0xa916, 0x1160, - 0x3e60, 0x601c, 0xc085, 0x601e, 0xa87c, 0xc0dd, 0xa87e, 0x9006, - 0x00ce, 0x001e, 0x012e, 0x0005, 0xa804, 0x9045, 0x090c, 0x0d85, - 0xa80e, 0xa064, 0xa81a, 0x9084, 0x000f, 0x9080, 0x1ec1, 0x2015, - 0x82ff, 0x090c, 0x0d85, 0xaa12, 0x2205, 0xa80a, 0x0c08, 0x903e, - 0x2730, 0xa880, 0xd0fc, 0x1190, 0x2d00, 0x0002, 0x1a94, 0x19f6, - 0x19f6, 0x1a94, 0x1a94, 0x1a8e, 0x1a94, 0x19f6, 0x1a45, 0x1a45, - 0x1a45, 0x1a94, 0x1a94, 0x1a94, 0x1a8b, 0x1a45, 0xc0fc, 0xa882, - 0xab2c, 0xaa30, 0xad1c, 0xac20, 0xdd9c, 0x0904, 0x1a96, 0x2c05, - 0x908a, 0x0034, 0x1a0c, 0x0d85, 0x9082, 0x001b, 0x0002, 0x19e2, - 0x19e0, 0x19e0, 0x19e0, 0x19e0, 0x19e0, 0x19e6, 0x19e0, 0x19e0, - 0x19e0, 0x19e0, 0x19e0, 0x19ea, 0x19e0, 0x19e0, 0x19e0, 0x19e0, - 0x19e0, 0x19ee, 0x19e0, 0x19e0, 0x19e0, 0x19e0, 0x19e0, 0x19f2, - 0x080c, 0x0d85, 0xa774, 0xa678, 0x0804, 0x1a96, 0xa78c, 0xa690, - 0x0804, 0x1a96, 0xa7a4, 0xa6a8, 0x0804, 0x1a96, 0xa7bc, 0xa6c0, - 0x0804, 0x1a96, 0xa7d4, 0xa6d8, 0x0804, 0x1a96, 0x2c05, 0x908a, - 0x0036, 0x1a0c, 0x0d85, 0x9082, 0x001b, 0x0002, 0x1a19, 0x1a19, - 0x1a1b, 0x1a19, 0x1a19, 0x1a19, 0x1a21, 0x1a19, 0x1a19, 0x1a19, - 0x1a27, 0x1a19, 0x1a19, 0x1a19, 0x1a2d, 0x1a19, 0x1a19, 0x1a19, - 0x1a33, 0x1a19, 0x1a19, 0x1a19, 0x1a39, 0x1a19, 0x1a19, 0x1a19, - 0x1a3f, 0x080c, 0x0d85, 0xa574, 0xa478, 0xa37c, 0xa280, 0x0804, - 0x1a96, 0xa584, 0xa488, 0xa38c, 0xa290, 0x0804, 0x1a96, 0xa594, - 0xa498, 0xa39c, 0xa2a0, 0x0804, 0x1a96, 0xa5a4, 0xa4a8, 0xa3ac, - 0xa2b0, 0x0804, 0x1a96, 0xa5b4, 0xa4b8, 0xa3bc, 0xa2c0, 0x0804, - 0x1a96, 0xa5c4, 0xa4c8, 0xa3cc, 0xa2d0, 0x0804, 0x1a96, 0xa5d4, - 0xa4d8, 0xa3dc, 0xa2e0, 0x0804, 0x1a96, 0x2c05, 0x908a, 0x0034, - 0x1a0c, 0x0d85, 0x9082, 0x001b, 0x0002, 0x1a68, 0x1a66, 0x1a66, - 0x1a66, 0x1a66, 0x1a66, 0x1a6f, 0x1a66, 0x1a66, 0x1a66, 0x1a66, - 0x1a66, 0x1a76, 0x1a66, 0x1a66, 0x1a66, 0x1a66, 0x1a66, 0x1a7d, - 0x1a66, 0x1a66, 0x1a66, 0x1a66, 0x1a66, 0x1a84, 0x080c, 0x0d85, - 0xa56c, 0xa470, 0xa774, 0xa678, 0xa37c, 0xa280, 0x0438, 0xa584, - 0xa488, 0xa78c, 0xa690, 0xa394, 0xa298, 0x0400, 0xa59c, 0xa4a0, - 0xa7a4, 0xa6a8, 0xa3ac, 0xa2b0, 0x00c8, 0xa5b4, 0xa4b8, 0xa7bc, - 0xa6c0, 0xa3c4, 0xa2c8, 0x0090, 0xa5cc, 0xa4d0, 0xa7d4, 0xa6d8, - 0xa3dc, 0xa2e0, 0x0058, 0x9d86, 0x000e, 0x1130, 0x080c, 0x1e97, - 0x1904, 0x199f, 0x900e, 0x0050, 0x080c, 0x0d85, 0xab2e, 0xaa32, - 0xad1e, 0xac22, 0xaf26, 0xae2a, 0x080c, 0x1e97, 0x0005, 0x6014, - 0x2048, 0x6118, 0x81ff, 0x0148, 0x810c, 0x810c, 0x810c, 0x81ff, - 0x1118, 0xa887, 0x0001, 0x0008, 0xa986, 0x601b, 0x0002, 0xa874, - 0x9084, 0x00ff, 0x9084, 0x0008, 0x0150, 0x00e9, 0x6000, 0x9086, - 0x0004, 0x1120, 0x2009, 0x0048, 0x080c, 0xb20a, 0x0005, 0xa974, - 0xd1dc, 0x1108, 0x0005, 0xa934, 0xa88c, 0x9106, 0x1158, 0xa938, - 0xa890, 0x9106, 0x1138, 0x601c, 0xc084, 0x601e, 0x2009, 0x0048, - 0x0804, 0xb20a, 0x0005, 0x0126, 0x00c6, 0x2091, 0x2200, 0x00ce, - 0x7908, 0x918c, 0x0007, 0x9186, 0x0000, 0x05b0, 0x9186, 0x0003, - 0x0598, 0x6020, 0x6023, 0x0000, 0x0006, 0x2031, 0x0008, 0x00c6, - 0x781f, 0x0808, 0x7808, 0xd09c, 0x0120, 0x080c, 0x13d4, 0x8631, - 0x1db8, 0x00ce, 0x781f, 0x0800, 0x2031, 0x0168, 0x00c6, 0x7808, - 0xd09c, 0x190c, 0x13d4, 0x00ce, 0x2001, 0x0038, 0x080c, 0x1bae, - 0x7930, 0x9186, 0x0040, 0x0160, 0x9186, 0x0042, 0x190c, 0x0d85, - 0x2001, 0x001e, 0x8001, 0x1df0, 0x8631, 0x1d40, 0x080c, 0x1bbd, - 0x000e, 0x6022, 0x012e, 0x0005, 0x080c, 0x1baa, 0x7827, 0x0015, - 0x7828, 0x9c06, 0x1db8, 0x782b, 0x0000, 0x0ca0, 0x00f6, 0x2079, - 0x0300, 0x7803, 0x0000, 0x78ab, 0x0004, 0x2001, 0xf000, 0x8001, - 0x090c, 0x0d85, 0x7aac, 0xd2ac, 0x1dd0, 0x00fe, 0x080c, 0x779e, - 0x1188, 0x2001, 0x0138, 0x2003, 0x0000, 0x2001, 0x0160, 0x2003, - 0x0000, 0x2011, 0x012c, 0xa001, 0xa001, 0x8211, 0x1de0, 0x0059, - 0x0804, 0x7840, 0x0479, 0x0039, 0x2001, 0x0160, 0x2502, 0x2001, - 0x0138, 0x2202, 0x0005, 0x00e6, 0x2071, 0x0200, 0x080c, 0x2a8b, - 0x2009, 0x003c, 0x080c, 0x2220, 0x2001, 0x015d, 0x2003, 0x0000, - 0x7000, 0x9084, 0x003c, 0x1de0, 0x080c, 0x8899, 0x70a0, 0x70a2, - 0x7098, 0x709a, 0x709c, 0x709e, 0x2001, 0x020d, 0x2003, 0x0020, - 0x00f6, 0x2079, 0x0300, 0x080c, 0x1366, 0x7803, 0x0001, 0x00fe, - 0x00ee, 0x0005, 0x2001, 0x0138, 0x2014, 0x2003, 0x0000, 0x2001, - 0x0160, 0x202c, 0x2003, 0x0000, 0x080c, 0x779e, 0x1108, 0x0005, - 0x2021, 0x0260, 0x2001, 0x0141, 0x201c, 0xd3dc, 0x1168, 0x2001, - 0x0109, 0x201c, 0x939c, 0x0048, 0x1160, 0x2001, 0x0111, 0x201c, - 0x83ff, 0x1110, 0x8421, 0x1d70, 0x2001, 0x015d, 0x2003, 0x0000, - 0x0005, 0x0046, 0x2021, 0x0019, 0x2003, 0x0048, 0xa001, 0xa001, - 0x201c, 0x939c, 0x0048, 0x0120, 0x8421, 0x1db0, 0x004e, 0x0c60, - 0x004e, 0x0c40, 0x601c, 0xc084, 0x601e, 0x0005, 0x2c08, 0x621c, - 0x080c, 0x16b9, 0x7930, 0x0005, 0x2c08, 0x621c, 0x080c, 0x1702, - 0x7930, 0x0005, 0x8001, 0x1df0, 0x0005, 0x2031, 0x0064, 0x781c, - 0x9084, 0x0007, 0x0170, 0x2001, 0x0038, 0x0c41, 0x9186, 0x0040, - 0x0904, 0x1c1b, 0x2001, 0x001e, 0x0c69, 0x8631, 0x1d80, 0x080c, - 0x0d85, 0x781f, 0x0202, 0x2001, 0x015d, 0x2003, 0x0000, 0x2001, - 0x0dac, 0x0c01, 0x781c, 0xd084, 0x0110, 0x0861, 0x04e0, 0x2001, - 0x0030, 0x0891, 0x9186, 0x0040, 0x0568, 0x781c, 0xd084, 0x1da8, - 0x781f, 0x0101, 0x2001, 0x0014, 0x0869, 0x2001, 0x0037, 0x0821, - 0x9186, 0x0040, 0x0140, 0x2001, 0x0030, 0x080c, 0x1bb4, 0x9186, - 0x0040, 0x190c, 0x0d85, 0x00d6, 0x2069, 0x0200, 0x692c, 0xd1f4, - 0x1170, 0xd1c4, 0x0160, 0xd19c, 0x0130, 0x6800, 0x9085, 0x1800, - 0x6802, 0x00de, 0x0080, 0x6908, 0x9184, 0x0007, 0x1db0, 0x00de, - 0x781f, 0x0100, 0x791c, 0x9184, 0x0007, 0x090c, 0x0d85, 0xa001, - 0xa001, 0x781f, 0x0200, 0x0005, 0x0126, 0x2091, 0x2400, 0x2079, - 0x0380, 0x2001, 0x19e8, 0x2070, 0x012e, 0x0005, 0x2cf0, 0x0126, - 0x2091, 0x2400, 0x3e60, 0x6014, 0x2048, 0xa964, 0xa91a, 0x918c, - 0x00ff, 0x9184, 0x000f, 0x0002, 0x1c50, 0x1c50, 0x1c50, 0x1c52, - 0x1c50, 0x1c50, 0x1c50, 0x1c50, 0x1c44, 0x1c5a, 0x1c50, 0x1c56, - 0x1c50, 0x1c50, 0x1c50, 0x1c50, 0x9086, 0x0008, 0x1148, 0xa87c, - 0xd0b4, 0x0904, 0x1dca, 0x2011, 0x1ebc, 0x2205, 0xab88, 0x00a8, - 0x080c, 0x0d85, 0x9186, 0x0013, 0x0128, 0x0cd0, 0x9186, 0x001b, - 0x0108, 0x0cb0, 0xa87c, 0xd0b4, 0x0904, 0x1dca, 0x9184, 0x000f, - 0x9080, 0x1ec1, 0x2015, 0x2205, 0xab88, 0x2908, 0xa80a, 0xa90e, - 0xaa12, 0xab16, 0x9006, 0xa842, 0xa83e, 0x012e, 0x0005, 0x2cf0, - 0x0126, 0x2091, 0x2400, 0x3e60, 0x6014, 0x2048, 0xa88c, 0xa990, - 0xaaac, 0xabb0, 0xaa36, 0xab3a, 0xa83e, 0xa942, 0xa846, 0xa94a, - 0xa964, 0x918c, 0x00ff, 0x9186, 0x001e, 0x0198, 0x2940, 0xa064, - 0xa81a, 0x90ec, 0x000f, 0x9d80, 0x1ec1, 0x2065, 0x2c05, 0x2808, - 0x2c10, 0xab88, 0xa80a, 0xa90e, 0xaa12, 0xab16, 0x012e, 0x3e60, - 0x0005, 0xa804, 0x2040, 0x0c58, 0x2cf0, 0x0126, 0x2091, 0x2400, - 0x3e60, 0x6014, 0x2048, 0xa97c, 0x2950, 0xd1dc, 0x1904, 0x1d94, - 0xc1dd, 0xa97e, 0x9006, 0xa842, 0xa83e, 0xa988, 0x8109, 0xa916, - 0xa964, 0xa91a, 0x9184, 0x000f, 0x9088, 0x1ec1, 0x2145, 0x0002, - 0x1cc8, 0x1cd6, 0x1cc8, 0x1cc8, 0x1cc8, 0x1cca, 0x1cc8, 0x1cc8, - 0x1d2b, 0x1d2b, 0x1cc8, 0x1cc8, 0x1cc8, 0x1d29, 0x1cc8, 0x1cc8, - 0x080c, 0x0d85, 0xa804, 0x2050, 0xb164, 0xa91a, 0x9184, 0x000f, - 0x9080, 0x1ec1, 0x2045, 0xd19c, 0x1904, 0x1d2b, 0x9036, 0x2638, - 0x2805, 0x908a, 0x0036, 0x1a0c, 0x0d85, 0x9082, 0x001b, 0x0002, - 0x1cfb, 0x1cfb, 0x1cfd, 0x1cfb, 0x1cfb, 0x1cfb, 0x1d03, 0x1cfb, - 0x1cfb, 0x1cfb, 0x1d09, 0x1cfb, 0x1cfb, 0x1cfb, 0x1d0f, 0x1cfb, - 0x1cfb, 0x1cfb, 0x1d15, 0x1cfb, 0x1cfb, 0x1cfb, 0x1d1b, 0x1cfb, - 0x1cfb, 0x1cfb, 0x1d21, 0x080c, 0x0d85, 0xb574, 0xb478, 0xb37c, - 0xb280, 0x0804, 0x1d70, 0xb584, 0xb488, 0xb38c, 0xb290, 0x0804, - 0x1d70, 0xb594, 0xb498, 0xb39c, 0xb2a0, 0x0804, 0x1d70, 0xb5a4, - 0xb4a8, 0xb3ac, 0xb2b0, 0x0804, 0x1d70, 0xb5b4, 0xb4b8, 0xb3bc, - 0xb2c0, 0x0804, 0x1d70, 0xb5c4, 0xb4c8, 0xb3cc, 0xb2d0, 0x0804, - 0x1d70, 0xb5d4, 0xb4d8, 0xb3dc, 0xb2e0, 0x0804, 0x1d70, 0x0804, - 0x1d70, 0x080c, 0x0d85, 0x2805, 0x908a, 0x0034, 0x1a0c, 0x0d85, - 0x9082, 0x001b, 0x0002, 0x1d4e, 0x1d4c, 0x1d4c, 0x1d4c, 0x1d4c, - 0x1d4c, 0x1d55, 0x1d4c, 0x1d4c, 0x1d4c, 0x1d4c, 0x1d4c, 0x1d5c, - 0x1d4c, 0x1d4c, 0x1d4c, 0x1d4c, 0x1d4c, 0x1d63, 0x1d4c, 0x1d4c, - 0x1d4c, 0x1d4c, 0x1d4c, 0x1d6a, 0x080c, 0x0d85, 0xb56c, 0xb470, - 0xb774, 0xb678, 0xb37c, 0xb280, 0x00d8, 0xb584, 0xb488, 0xb78c, - 0xb690, 0xb394, 0xb298, 0x00a0, 0xb59c, 0xb4a0, 0xb7a4, 0xb6a8, - 0xb3ac, 0xb2b0, 0x0068, 0xb5b4, 0xb4b8, 0xb7bc, 0xb6c0, 0xb3c4, - 0xb2c8, 0x0030, 0xb5cc, 0xb4d0, 0xb7d4, 0xb6d8, 0xb3dc, 0xb2e0, - 0xab2e, 0xaa32, 0xad1e, 0xac22, 0xaf26, 0xae2a, 0xa988, 0x8109, - 0xa916, 0x1118, 0x9006, 0x012e, 0x0005, 0x8840, 0x2805, 0x9005, - 0x1168, 0xb004, 0x9005, 0x090c, 0x0d85, 0x2050, 0xb164, 0xa91a, - 0x9184, 0x000f, 0x9080, 0x1ec1, 0x2045, 0x2805, 0x2810, 0x2a08, - 0xa80a, 0xa90e, 0xaa12, 0x0c30, 0x3e60, 0x6344, 0xd3fc, 0x190c, - 0x0d85, 0xa93c, 0xaa40, 0xa844, 0x9106, 0x1118, 0xa848, 0x9206, - 0x0508, 0x2958, 0xab48, 0xac44, 0x2940, 0x080c, 0x1ee1, 0x1998, - 0x2850, 0x2c40, 0xab14, 0xa880, 0xd0fc, 0x1140, 0xa810, 0x2005, - 0xa80a, 0x2a00, 0xa80e, 0x2009, 0x8015, 0x0070, 0x00c6, 0x3e60, - 0x6044, 0xc0a4, 0x9085, 0x8005, 0x6046, 0x00ce, 0x8319, 0xab16, - 0x1904, 0x1d7d, 0x2009, 0x8005, 0x3e60, 0x6044, 0x9105, 0x6046, - 0x0804, 0x1d7a, 0x080c, 0x0d85, 0x00f6, 0x00e6, 0x0096, 0x00c6, - 0x0026, 0x704c, 0x9c06, 0x190c, 0x0d85, 0x2079, 0x0090, 0x2001, - 0x0105, 0x2003, 0x0010, 0x782b, 0x0004, 0x7057, 0x0000, 0x6014, - 0x2048, 0x080c, 0xcf1b, 0x0118, 0xa880, 0xc0bd, 0xa882, 0x6020, - 0x9086, 0x0006, 0x1170, 0x2061, 0x0100, 0x62c8, 0x2001, 0x00fa, - 0x8001, 0x1df0, 0x60c8, 0x9206, 0x1dc0, 0x60c4, 0xa89a, 0x60c8, - 0xa896, 0x704c, 0x2060, 0x00c6, 0x080c, 0xcae9, 0x080c, 0xacfc, - 0x00ce, 0x704c, 0x9c06, 0x1150, 0x2009, 0x0040, 0x080c, 0x2220, - 0x080c, 0xa7a1, 0x2011, 0x0000, 0x080c, 0xa635, 0x002e, 0x00ce, - 0x009e, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0090, 0x781c, - 0x0006, 0x7818, 0x0006, 0x2079, 0x0100, 0x7a14, 0x9284, 0x1984, - 0x9085, 0x0012, 0x7816, 0x2019, 0x1000, 0x8319, 0x090c, 0x0d85, - 0x7820, 0xd0bc, 0x1dd0, 0x79c8, 0x000e, 0x9102, 0x001e, 0x0006, - 0x0016, 0x79c4, 0x000e, 0x9103, 0x78c6, 0x000e, 0x78ca, 0x9284, - 0x1984, 0x9085, 0x0012, 0x7816, 0x2079, 0x0090, 0x782b, 0x0008, - 0x7057, 0x0000, 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x2071, 0x19e8, - 0x7054, 0x9086, 0x0000, 0x0904, 0x1e92, 0x2079, 0x0090, 0x2009, - 0x0207, 0x210c, 0xd194, 0x01b8, 0x2009, 0x020c, 0x210c, 0x9184, - 0x0003, 0x0188, 0x080c, 0xeefa, 0x2001, 0x0133, 0x2004, 0x9005, - 0x090c, 0x0d85, 0x0016, 0x2009, 0x0040, 0x080c, 0x2220, 0x001e, - 0x2001, 0x020c, 0x2102, 0x2009, 0x0206, 0x2104, 0x2009, 0x0203, - 0x210c, 0x9106, 0x1120, 0x2009, 0x0040, 0x080c, 0x2220, 0x782c, - 0xd0fc, 0x09a8, 0x080c, 0xad18, 0x782c, 0xd0fc, 0x1de8, 0x080c, - 0xacfc, 0x7054, 0x9086, 0x0000, 0x1950, 0x782b, 0x0004, 0x782c, - 0xd0ac, 0x1de8, 0x2009, 0x0040, 0x080c, 0x2220, 0x782b, 0x0002, - 0x7057, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x080c, 0x0d85, 0x8c60, - 0x2c05, 0x9005, 0x0110, 0x8a51, 0x0005, 0xa004, 0x9005, 0x0168, - 0xa85a, 0x2040, 0xa064, 0x9084, 0x000f, 0x9080, 0x1ec1, 0x2065, - 0x8cff, 0x090c, 0x0d85, 0x8a51, 0x0005, 0x2050, 0x0005, 0x0000, - 0x001d, 0x0021, 0x0025, 0x0029, 0x002d, 0x0031, 0x0035, 0x0000, - 0x001b, 0x0021, 0x0027, 0x002d, 0x0033, 0x0000, 0x0000, 0x0023, - 0x0000, 0x0000, 0x1eb4, 0x1eb0, 0x1eb4, 0x1eb4, 0x1ebe, 0x0000, - 0x1eb4, 0x1ebb, 0x1ebb, 0x1eb8, 0x1ebb, 0x1ebb, 0x0000, 0x1ebe, - 0x1ebb, 0x0000, 0x1eb6, 0x1eb6, 0x0000, 0x1eb6, 0x1ebe, 0x0000, - 0x1eb6, 0x1ebc, 0x1ebc, 0x1ebc, 0x0000, 0x1ebc, 0x0000, 0x1ebe, - 0x1ebc, 0x00c6, 0x00d6, 0x0086, 0xab42, 0xac3e, 0xa888, 0x9055, - 0x0904, 0x20c0, 0x2940, 0xa064, 0x90ec, 0x000f, 0x9084, 0x00ff, - 0x9086, 0x0008, 0x1118, 0x2061, 0x1ebc, 0x00d0, 0x9de0, 0x1ec1, - 0x9d86, 0x0007, 0x0130, 0x9d86, 0x000e, 0x0118, 0x9d86, 0x000f, - 0x1120, 0xa08c, 0x9422, 0xa090, 0x931b, 0x2c05, 0x9065, 0x1140, - 0x0310, 0x0804, 0x20c0, 0xa004, 0x9045, 0x0904, 0x20c0, 0x08d8, - 0x2c05, 0x9005, 0x0904, 0x1fa8, 0xdd9c, 0x1904, 0x1f64, 0x908a, - 0x0036, 0x1a0c, 0x0d85, 0x9082, 0x001b, 0x0002, 0x1f39, 0x1f39, - 0x1f3b, 0x1f39, 0x1f39, 0x1f39, 0x1f41, 0x1f39, 0x1f39, 0x1f39, - 0x1f47, 0x1f39, 0x1f39, 0x1f39, 0x1f4d, 0x1f39, 0x1f39, 0x1f39, - 0x1f53, 0x1f39, 0x1f39, 0x1f39, 0x1f59, 0x1f39, 0x1f39, 0x1f39, - 0x1f5f, 0x080c, 0x0d85, 0xa07c, 0x9422, 0xa080, 0x931b, 0x0804, - 0x1f9e, 0xa08c, 0x9422, 0xa090, 0x931b, 0x0804, 0x1f9e, 0xa09c, - 0x9422, 0xa0a0, 0x931b, 0x0804, 0x1f9e, 0xa0ac, 0x9422, 0xa0b0, - 0x931b, 0x0804, 0x1f9e, 0xa0bc, 0x9422, 0xa0c0, 0x931b, 0x0804, - 0x1f9e, 0xa0cc, 0x9422, 0xa0d0, 0x931b, 0x0804, 0x1f9e, 0xa0dc, - 0x9422, 0xa0e0, 0x931b, 0x04d0, 0x908a, 0x0034, 0x1a0c, 0x0d85, - 0x9082, 0x001b, 0x0002, 0x1f86, 0x1f84, 0x1f84, 0x1f84, 0x1f84, - 0x1f84, 0x1f8b, 0x1f84, 0x1f84, 0x1f84, 0x1f84, 0x1f84, 0x1f90, - 0x1f84, 0x1f84, 0x1f84, 0x1f84, 0x1f84, 0x1f95, 0x1f84, 0x1f84, - 0x1f84, 0x1f84, 0x1f84, 0x1f9a, 0x080c, 0x0d85, 0xa07c, 0x9422, - 0xa080, 0x931b, 0x0098, 0xa094, 0x9422, 0xa098, 0x931b, 0x0070, - 0xa0ac, 0x9422, 0xa0b0, 0x931b, 0x0048, 0xa0c4, 0x9422, 0xa0c8, - 0x931b, 0x0020, 0xa0dc, 0x9422, 0xa0e0, 0x931b, 0x0630, 0x2300, - 0x9405, 0x0160, 0x8a51, 0x0904, 0x20c0, 0x8c60, 0x0804, 0x1f10, - 0xa004, 0x9045, 0x0904, 0x20c0, 0x0804, 0x1eeb, 0x8a51, 0x0904, - 0x20c0, 0x8c60, 0x2c05, 0x9005, 0x1158, 0xa004, 0x9045, 0x0904, - 0x20c0, 0xa064, 0x90ec, 0x000f, 0x9de0, 0x1ec1, 0x2c05, 0x2060, - 0xa880, 0xc0fc, 0xa882, 0x0804, 0x20b5, 0x2c05, 0x8422, 0x8420, - 0x831a, 0x9399, 0x0000, 0xac2e, 0xab32, 0xdd9c, 0x1904, 0x2052, - 0x9082, 0x001b, 0x0002, 0x1fee, 0x1fee, 0x1ff0, 0x1fee, 0x1fee, - 0x1fee, 0x1ffe, 0x1fee, 0x1fee, 0x1fee, 0x200c, 0x1fee, 0x1fee, - 0x1fee, 0x201a, 0x1fee, 0x1fee, 0x1fee, 0x2028, 0x1fee, 0x1fee, - 0x1fee, 0x2036, 0x1fee, 0x1fee, 0x1fee, 0x2044, 0x080c, 0x0d85, - 0xa17c, 0x2400, 0x9122, 0xa180, 0x2300, 0x911b, 0x0a0c, 0x0d85, - 0xa074, 0x9420, 0xa078, 0x9319, 0x0804, 0x20b0, 0xa18c, 0x2400, - 0x9122, 0xa190, 0x2300, 0x911b, 0x0a0c, 0x0d85, 0xa084, 0x9420, - 0xa088, 0x9319, 0x0804, 0x20b0, 0xa19c, 0x2400, 0x9122, 0xa1a0, - 0x2300, 0x911b, 0x0a0c, 0x0d85, 0xa094, 0x9420, 0xa098, 0x9319, - 0x0804, 0x20b0, 0xa1ac, 0x2400, 0x9122, 0xa1b0, 0x2300, 0x911b, - 0x0a0c, 0x0d85, 0xa0a4, 0x9420, 0xa0a8, 0x9319, 0x0804, 0x20b0, - 0xa1bc, 0x2400, 0x9122, 0xa1c0, 0x2300, 0x911b, 0x0a0c, 0x0d85, - 0xa0b4, 0x9420, 0xa0b8, 0x9319, 0x0804, 0x20b0, 0xa1cc, 0x2400, - 0x9122, 0xa1d0, 0x2300, 0x911b, 0x0a0c, 0x0d85, 0xa0c4, 0x9420, - 0xa0c8, 0x9319, 0x0804, 0x20b0, 0xa1dc, 0x2400, 0x9122, 0xa1e0, - 0x2300, 0x911b, 0x0a0c, 0x0d85, 0xa0d4, 0x9420, 0xa0d8, 0x9319, - 0x0804, 0x20b0, 0x9082, 0x001b, 0x0002, 0x2070, 0x206e, 0x206e, - 0x206e, 0x206e, 0x206e, 0x207d, 0x206e, 0x206e, 0x206e, 0x206e, - 0x206e, 0x208a, 0x206e, 0x206e, 0x206e, 0x206e, 0x206e, 0x2097, - 0x206e, 0x206e, 0x206e, 0x206e, 0x206e, 0x20a4, 0x080c, 0x0d85, - 0xa17c, 0x2400, 0x9122, 0xa180, 0x2300, 0x911b, 0x0a0c, 0x0d85, - 0xa06c, 0x9420, 0xa070, 0x9319, 0x0498, 0xa194, 0x2400, 0x9122, - 0xa198, 0x2300, 0x911b, 0x0a0c, 0x0d85, 0xa084, 0x9420, 0xa088, - 0x9319, 0x0430, 0xa1ac, 0x2400, 0x9122, 0xa1b0, 0x2300, 0x911b, - 0x0a0c, 0x0d85, 0xa09c, 0x9420, 0xa0a0, 0x9319, 0x00c8, 0xa1c4, - 0x2400, 0x9122, 0xa1c8, 0x2300, 0x911b, 0x0a0c, 0x0d85, 0xa0b4, - 0x9420, 0xa0b8, 0x9319, 0x0060, 0xa1dc, 0x2400, 0x9122, 0xa1e0, - 0x2300, 0x911b, 0x0a0c, 0x0d85, 0xa0cc, 0x9420, 0xa0d0, 0x9319, - 0xac1e, 0xab22, 0xa880, 0xc0fd, 0xa882, 0x2800, 0xa85a, 0x2c00, - 0xa812, 0x2a00, 0xa816, 0x000e, 0x000e, 0x000e, 0x9006, 0x0028, - 0x008e, 0x00de, 0x00ce, 0x9085, 0x0001, 0x0005, 0x00c6, 0x610c, - 0x0016, 0x9026, 0x2410, 0x6004, 0x9420, 0x9291, 0x0000, 0x2c04, - 0x9210, 0x9ce0, 0x0002, 0x918a, 0x0002, 0x1da8, 0x9284, 0x000f, - 0x9405, 0x001e, 0x00ce, 0x0005, 0x7803, 0x0003, 0x780f, 0x0000, - 0x6004, 0x7812, 0x2c04, 0x7816, 0x9ce0, 0x0002, 0x918a, 0x0002, - 0x1db8, 0x0005, 0x2001, 0x0005, 0x2004, 0xd0bc, 0x190c, 0x0d7e, - 0xd094, 0x0110, 0x080c, 0x1208, 0x0005, 0x0126, 0x2091, 0x2600, - 0x2079, 0x0200, 0x2071, 0x0260, 0x2069, 0x1800, 0x7817, 0x0000, - 0x789b, 0x0814, 0x78a3, 0x0406, 0x789f, 0x0410, 0x2009, 0x013b, - 0x200b, 0x0400, 0x781b, 0x0002, 0x783b, 0x001f, 0x7837, 0x0020, - 0x7803, 0x1600, 0x012e, 0x0005, 0x2091, 0x2600, 0x781c, 0xd0a4, - 0x190c, 0x221d, 0x7900, 0xd1dc, 0x1118, 0x9084, 0x0006, 0x001a, - 0x9084, 0x000e, 0x0002, 0x213b, 0x2133, 0x8210, 0x2133, 0x2135, - 0x2135, 0x2135, 0x2135, 0x81f6, 0x2133, 0x2137, 0x2133, 0x2135, - 0x2133, 0x2135, 0x2133, 0x080c, 0x0d85, 0x0031, 0x0020, 0x080c, - 0x81f6, 0x080c, 0x8210, 0x0005, 0x0006, 0x0016, 0x0026, 0x080c, - 0xeefa, 0x7930, 0x9184, 0x0003, 0x0510, 0x080c, 0xacfc, 0x2001, - 0x19fb, 0x2004, 0x9005, 0x01a0, 0x2001, 0x0133, 0x2004, 0x9005, - 0x090c, 0x0d85, 0x00c6, 0x2001, 0x19fb, 0x2064, 0x080c, 0xad18, - 0x080c, 0xcae9, 0x2009, 0x0040, 0x080c, 0x2220, 0x00ce, 0x0408, - 0x2009, 0x0040, 0x080c, 0x2220, 0x080c, 0xad18, 0x00d0, 0x9184, - 0x0014, 0x01a0, 0x6a00, 0x9286, 0x0003, 0x0160, 0x080c, 0x779e, - 0x1138, 0x080c, 0x7ab6, 0x080c, 0x619d, 0x080c, 0x76cd, 0x0010, - 0x080c, 0x6058, 0x080c, 0x82ae, 0x0041, 0x0018, 0x9184, 0x9540, - 0x1dc8, 0x002e, 0x001e, 0x000e, 0x0005, 0x00e6, 0x0036, 0x0046, - 0x0056, 0x2071, 0x1a6e, 0x080c, 0x1b1e, 0x005e, 0x004e, 0x003e, - 0x00ee, 0x0005, 0x0126, 0x2091, 0x2e00, 0x2071, 0x1800, 0x7128, - 0x2001, 0x196f, 0x2102, 0x2001, 0x1977, 0x2102, 0x2001, 0x013b, - 0x2102, 0x2079, 0x0200, 0x2001, 0x0201, 0x789e, 0x78a3, 0x0200, - 0x9198, 0x0007, 0x831c, 0x831c, 0x831c, 0x9398, 0x0005, 0x2320, - 0x9182, 0x0204, 0x1230, 0x2011, 0x0008, 0x8423, 0x8423, 0x8423, - 0x0488, 0x9182, 0x024c, 0x1240, 0x2011, 0x0007, 0x8403, 0x8003, - 0x9400, 0x9400, 0x9420, 0x0430, 0x9182, 0x02bc, 0x1238, 0x2011, - 0x0006, 0x8403, 0x8003, 0x9400, 0x9420, 0x00e0, 0x9182, 0x034c, - 0x1230, 0x2011, 0x0005, 0x8403, 0x8003, 0x9420, 0x0098, 0x9182, - 0x042c, 0x1228, 0x2011, 0x0004, 0x8423, 0x8423, 0x0058, 0x9182, - 0x059c, 0x1228, 0x2011, 0x0003, 0x8403, 0x9420, 0x0018, 0x2011, - 0x0002, 0x8423, 0x9482, 0x0228, 0x8002, 0x8020, 0x8301, 0x9402, - 0x0110, 0x0208, 0x8321, 0x8217, 0x8203, 0x9405, 0x789a, 0x012e, - 0x0005, 0x0006, 0x00d6, 0x2069, 0x0200, 0x6814, 0x9084, 0xffc0, - 0x910d, 0x6916, 0x00de, 0x000e, 0x0005, 0x00d6, 0x2069, 0x0200, - 0x9005, 0x6810, 0x0110, 0xc0a5, 0x0008, 0xc0a4, 0x6812, 0x00de, - 0x0005, 0x0006, 0x00d6, 0x2069, 0x0200, 0x6810, 0x9084, 0xfff8, - 0x910d, 0x6912, 0x00de, 0x000e, 0x0005, 0x7938, 0x080c, 0x0d7e, - 0x00f6, 0x2079, 0x0200, 0x7902, 0xa001, 0xa001, 0xa001, 0xa001, - 0xa001, 0xa001, 0x7902, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, - 0xa001, 0x00fe, 0x0005, 0x0126, 0x2091, 0x2800, 0x2061, 0x0100, - 0x2071, 0x1800, 0x2009, 0x0000, 0x080c, 0x2a85, 0x080c, 0x299b, - 0x2001, 0x199d, 0x2003, 0x0700, 0x2001, 0x199e, 0x2003, 0x0700, - 0x080c, 0x2af6, 0x9006, 0x080c, 0x29ca, 0x9006, 0x080c, 0x29ad, - 0x20a9, 0x0012, 0x1d04, 0x2252, 0x2091, 0x6000, 0x1f04, 0x2252, - 0x602f, 0x0100, 0x602f, 0x0000, 0x6050, 0x9085, 0x0400, 0x9084, - 0xdfff, 0x6052, 0x6224, 0x080c, 0x2ad3, 0x080c, 0x26c5, 0x2009, - 0x00ef, 0x6132, 0x6136, 0x080c, 0x26d5, 0x60e7, 0x0000, 0x61ea, - 0x2001, 0x180d, 0x2004, 0xd08c, 0x2001, 0x0002, 0x1110, 0x2001, - 0x0008, 0x60e2, 0x604b, 0xf7f7, 0x6043, 0x0000, 0x602f, 0x0080, - 0x602f, 0x0000, 0x6007, 0x349f, 0x00c6, 0x2061, 0x0140, 0x608b, - 0x000b, 0x608f, 0x10b8, 0x6093, 0x0000, 0x6097, 0x0198, 0x00ce, - 0x6004, 0x9085, 0x8000, 0x6006, 0x60bb, 0x0000, 0x20a9, 0x0018, - 0x60bf, 0x0000, 0x1f04, 0x2298, 0x60bb, 0x0000, 0x60bf, 0x0108, - 0x60bf, 0x0012, 0x60bf, 0x0405, 0x60bf, 0x0014, 0x60bf, 0x0320, - 0x60bf, 0x0018, 0x601b, 0x00f0, 0x601f, 0x001e, 0x600f, 0x006b, - 0x602b, 0x402c, 0x012e, 0x0005, 0x00f6, 0x2079, 0x0140, 0x78c3, - 0x0080, 0x78c3, 0x0083, 0x78c3, 0x0000, 0x00fe, 0x0005, 0x2001, - 0x1835, 0x2003, 0x0000, 0x2001, 0x1834, 0x2003, 0x0001, 0x0005, - 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x6124, 0x6028, - 0x910c, 0x0066, 0x2031, 0x1837, 0x2634, 0x96b4, 0x0028, 0x006e, - 0x1138, 0x6020, 0xd1bc, 0x0120, 0xd0bc, 0x1168, 0xd0b4, 0x1198, - 0x9184, 0x5e2c, 0x1118, 0x9184, 0x0007, 0x00aa, 0x9195, 0x0004, - 0x9284, 0x0007, 0x0082, 0x0016, 0x2001, 0x0387, 0x200c, 0xd1a4, - 0x001e, 0x0d70, 0x0c98, 0x0016, 0x2001, 0x0387, 0x200c, 0xd1b4, - 0x001e, 0x0d30, 0x0c58, 0x2306, 0x2303, 0x2303, 0x2303, 0x2305, - 0x2303, 0x2303, 0x2303, 0x080c, 0x0d85, 0x0029, 0x002e, 0x001e, - 0x000e, 0x012e, 0x0005, 0x00a6, 0x6124, 0x6028, 0xd09c, 0x0118, - 0xd19c, 0x1904, 0x258b, 0xd1f4, 0x190c, 0x0d7e, 0x080c, 0x779e, - 0x0904, 0x2363, 0x080c, 0xd645, 0x1120, 0x7000, 0x9086, 0x0003, - 0x0580, 0x6024, 0x9084, 0x1800, 0x0560, 0x080c, 0x77c1, 0x0118, - 0x080c, 0x77af, 0x1530, 0x2011, 0x0020, 0x080c, 0x2ad3, 0x6043, - 0x0000, 0x080c, 0xd645, 0x0168, 0x080c, 0x77c1, 0x1150, 0x2001, - 0x19a8, 0x2003, 0x0001, 0x6027, 0x1800, 0x080c, 0x7612, 0x0804, - 0x258e, 0x70a4, 0x9005, 0x1150, 0x70a7, 0x0001, 0x00d6, 0x2069, - 0x0140, 0x080c, 0x77f2, 0x00de, 0x1904, 0x258e, 0x080c, 0x7ac0, - 0x0428, 0x080c, 0x77c1, 0x1590, 0x6024, 0x9084, 0x1800, 0x1108, - 0x0468, 0x080c, 0x7ac0, 0x080c, 0x7ab6, 0x080c, 0x619d, 0x080c, - 0x76cd, 0x0804, 0x258b, 0xd1ac, 0x1508, 0x6024, 0xd0dc, 0x1170, - 0xd0e4, 0x1178, 0xd0d4, 0x1190, 0xd0cc, 0x0130, 0x7098, 0x9086, - 0x0029, 0x1110, 0x080c, 0x7990, 0x0804, 0x258b, 0x080c, 0x7abb, - 0x0048, 0x2001, 0x197d, 0x2003, 0x0002, 0x0020, 0x080c, 0x78e4, - 0x0804, 0x258b, 0x080c, 0x7a3a, 0x0804, 0x258b, 0x6220, 0xd1bc, - 0x0138, 0xd2bc, 0x1904, 0x25f6, 0xd2b4, 0x1904, 0x2608, 0x0000, - 0xd1ac, 0x0904, 0x2498, 0x0036, 0x6328, 0xc3bc, 0x632a, 0x003e, - 0x080c, 0x779e, 0x11d0, 0x2011, 0x0020, 0x080c, 0x2ad3, 0x0006, - 0x0026, 0x0036, 0x080c, 0x77b8, 0x1158, 0x080c, 0x7ab6, 0x080c, - 0x619d, 0x080c, 0x76cd, 0x003e, 0x002e, 0x000e, 0x00ae, 0x0005, - 0x003e, 0x002e, 0x000e, 0x080c, 0x7772, 0x0016, 0x0046, 0x00c6, - 0x644c, 0x9486, 0xf0f0, 0x1138, 0x2061, 0x0100, 0x644a, 0x6043, - 0x0090, 0x6043, 0x0010, 0x74da, 0x948c, 0xff00, 0x7038, 0xd084, - 0x0190, 0x080c, 0xd645, 0x1118, 0x9186, 0xf800, 0x1160, 0x7048, - 0xd084, 0x1148, 0xc085, 0x704a, 0x0036, 0x2418, 0x2011, 0x8016, - 0x080c, 0x4ca1, 0x003e, 0x080c, 0xd63e, 0x1904, 0x246d, 0x9196, - 0xff00, 0x05a8, 0x7060, 0x9084, 0x00ff, 0x810f, 0x81ff, 0x0110, - 0x9116, 0x0568, 0x7130, 0xd184, 0x1550, 0x080c, 0x3482, 0x0128, - 0xc18d, 0x7132, 0x080c, 0x6c09, 0x1510, 0x6240, 0x9294, 0x0010, - 0x0130, 0x6248, 0x9294, 0xff00, 0x9296, 0xff00, 0x01c0, 0x7030, - 0xd08c, 0x0904, 0x246d, 0x7038, 0xd08c, 0x1140, 0x2001, 0x180c, - 0x200c, 0xd1ac, 0x1904, 0x246d, 0xc1ad, 0x2102, 0x0036, 0x73d8, - 0x2011, 0x8013, 0x080c, 0x4ca1, 0x003e, 0x0804, 0x246d, 0x7038, - 0xd08c, 0x1140, 0x2001, 0x180c, 0x200c, 0xd1ac, 0x1904, 0x246d, - 0xc1ad, 0x2102, 0x0036, 0x73d8, 0x2011, 0x8013, 0x080c, 0x4ca1, - 0x003e, 0x7130, 0xc185, 0x7132, 0x2011, 0x1848, 0x220c, 0xd1a4, - 0x01f0, 0x0016, 0x2009, 0x0001, 0x2011, 0x0100, 0x080c, 0x8c44, - 0x2019, 0x000e, 0x00c6, 0x2061, 0x0000, 0x080c, 0xe9f9, 0x00ce, - 0x9484, 0x00ff, 0x9080, 0x348e, 0x200d, 0x918c, 0xff00, 0x810f, - 0x2120, 0x9006, 0x2009, 0x000e, 0x080c, 0xea8d, 0x001e, 0x0016, - 0x2009, 0x0002, 0x2019, 0x0004, 0x080c, 0x32da, 0x001e, 0x00a8, - 0x0156, 0x00b6, 0x20a9, 0x007f, 0x900e, 0x080c, 0x67b4, 0x1140, - 0x7030, 0xd084, 0x1118, 0xb800, 0xd0bc, 0x1110, 0x080c, 0x61b7, - 0x8108, 0x1f04, 0x245d, 0x00be, 0x015e, 0x00ce, 0x004e, 0x080c, - 0xacfc, 0x080c, 0xafd2, 0x080c, 0xb09b, 0x080c, 0xad18, 0x60e3, - 0x0000, 0x001e, 0x2001, 0x1800, 0x2014, 0x9296, 0x0004, 0x1170, - 0xd19c, 0x11b0, 0x2011, 0x180c, 0x2214, 0xd29c, 0x1120, 0x6204, - 0x9295, 0x0002, 0x6206, 0x6228, 0xc29d, 0x622a, 0x2003, 0x0001, - 0x2001, 0x1826, 0x2003, 0x0000, 0x2011, 0x0020, 0x080c, 0x2ad3, - 0xd194, 0x0904, 0x258b, 0x0016, 0x080c, 0xacfc, 0x6220, 0xd2b4, - 0x0904, 0x2526, 0x080c, 0x8a4b, 0x080c, 0xa2a0, 0x2011, 0x0004, - 0x080c, 0x2ad3, 0x00f6, 0x2019, 0x19f4, 0x2304, 0x907d, 0x0904, - 0x24f3, 0x7804, 0x9086, 0x0032, 0x15f0, 0x00d6, 0x00c6, 0x00e6, - 0x0096, 0x2069, 0x0140, 0x782c, 0x685e, 0x7808, 0x685a, 0x6043, - 0x0002, 0x2001, 0x0003, 0x8001, 0x1df0, 0x6043, 0x0000, 0x2001, - 0x003c, 0x8001, 0x1df0, 0x080c, 0x2aa9, 0x2001, 0x001e, 0x8001, - 0x0240, 0x20a9, 0x0009, 0x080c, 0x2a60, 0x6904, 0xd1dc, 0x1140, - 0x0cb0, 0x2001, 0x0100, 0x080c, 0x2a99, 0x9006, 0x080c, 0x2a99, - 0x080c, 0x99ed, 0x080c, 0xad18, 0x7814, 0x2048, 0xa867, 0x0103, - 0x2f60, 0x080c, 0xb16c, 0x009e, 0x00ee, 0x00ce, 0x00de, 0x00fe, - 0x001e, 0x00ae, 0x0005, 0x00fe, 0x00d6, 0x2069, 0x0140, 0x6804, - 0x9084, 0x4000, 0x0110, 0x080c, 0x2aa9, 0x00de, 0x00c6, 0x2061, - 0x19e8, 0x6034, 0x080c, 0xd645, 0x0120, 0x909a, 0x0003, 0x1258, - 0x0018, 0x909a, 0x00c8, 0x1238, 0x8000, 0x6036, 0x00ce, 0x080c, - 0xa278, 0x0804, 0x2588, 0x2061, 0x0100, 0x62c0, 0x080c, 0xac2d, - 0x2019, 0x19f4, 0x2304, 0x9065, 0x0130, 0x6003, 0x0001, 0x2009, - 0x0027, 0x080c, 0xb20a, 0x00ce, 0x0804, 0x2588, 0xd2bc, 0x0904, - 0x256b, 0x080c, 0x8a58, 0x2011, 0x0004, 0x080c, 0x2ad3, 0x00d6, - 0x2069, 0x0140, 0x6804, 0x9084, 0x4000, 0x0110, 0x080c, 0x2aa9, - 0x00de, 0x00c6, 0x2061, 0x19e8, 0x6050, 0x080c, 0xd645, 0x0120, - 0x909a, 0x0003, 0x1668, 0x0018, 0x909a, 0x00c8, 0x1648, 0x8000, - 0x6052, 0x604c, 0x00ce, 0x9005, 0x05d8, 0x2009, 0x07d0, 0x080c, - 0x8a50, 0x9080, 0x0008, 0x2004, 0x9086, 0x0006, 0x1138, 0x2009, - 0x1984, 0x2011, 0x0012, 0x080c, 0x2ae2, 0x0450, 0x9080, 0x0008, - 0x2004, 0x9086, 0x0009, 0x0d98, 0x2009, 0x1984, 0x2011, 0x0016, - 0x080c, 0x2ae2, 0x00e8, 0x2011, 0x0004, 0x080c, 0x2ad3, 0x00c0, - 0x0036, 0x2019, 0x0001, 0x080c, 0xa596, 0x003e, 0x2019, 0x19fb, - 0x2304, 0x9065, 0x0160, 0x2009, 0x004f, 0x6020, 0x9086, 0x0009, - 0x1110, 0x2009, 0x004f, 0x6003, 0x0003, 0x080c, 0xb20a, 0x00ce, - 0x080c, 0xad18, 0x001e, 0xd19c, 0x0904, 0x25ef, 0x7038, 0xd0ac, - 0x1558, 0x0016, 0x0156, 0x2011, 0x0008, 0x080c, 0x2ad3, 0x080c, - 0x2af6, 0x080c, 0x2b29, 0x6050, 0xc0e5, 0x6052, 0x20a9, 0x0367, - 0x0f04, 0x25ba, 0x1d04, 0x25a2, 0x080c, 0x8a7f, 0x6020, 0xd09c, - 0x1db8, 0x00f6, 0x2079, 0x0100, 0x080c, 0x2a0c, 0x00fe, 0x1d80, - 0x6050, 0xc0e4, 0x6052, 0x2011, 0x0008, 0x080c, 0x2ad3, 0x015e, - 0x001e, 0x04a8, 0x015e, 0x001e, 0x0016, 0x6028, 0xc09c, 0x602a, - 0x080c, 0xacfc, 0x080c, 0xafd2, 0x080c, 0xb09b, 0x080c, 0xad18, - 0x60e3, 0x0000, 0x080c, 0xeed9, 0x080c, 0xeef4, 0x080c, 0x5844, - 0xd0fc, 0x1138, 0x080c, 0xd63e, 0x1120, 0x9085, 0x0001, 0x080c, - 0x77e2, 0x9006, 0x080c, 0x2a99, 0x2009, 0x0002, 0x080c, 0x2a85, - 0x00e6, 0x2071, 0x1800, 0x7003, 0x0004, 0x080c, 0x0ed3, 0x00ee, - 0x2011, 0x0008, 0x080c, 0x2ad3, 0x080c, 0x0bcf, 0x001e, 0x918c, - 0xffd0, 0x2110, 0x080c, 0x2ad3, 0x00ae, 0x0005, 0x0016, 0x2001, - 0x0387, 0x200c, 0xd1a4, 0x001e, 0x0904, 0x2390, 0x0016, 0x2009, - 0x2602, 0x00c0, 0x2001, 0x0387, 0x2003, 0x1000, 0x001e, 0x0c38, - 0x0016, 0x2001, 0x0387, 0x200c, 0xd1b4, 0x001e, 0x0904, 0x2390, - 0x0016, 0x2009, 0x2614, 0x0030, 0x2001, 0x0387, 0x2003, 0x4000, - 0x001e, 0x08a8, 0x6028, 0xc0bc, 0x602a, 0x2001, 0x0156, 0x2003, - 0xbc91, 0x8000, 0x2003, 0xffff, 0x6043, 0x0001, 0x080c, 0x2a7f, - 0x2011, 0x0080, 0x080c, 0x2ad3, 0x6017, 0x0000, 0x6043, 0x0000, - 0x0817, 0x0006, 0x0016, 0x0026, 0x0036, 0x00e6, 0x00f6, 0x0126, - 0x2091, 0x8000, 0x2071, 0x1800, 0x71d0, 0x70d2, 0x9116, 0x0904, - 0x2684, 0x81ff, 0x01a0, 0x2009, 0x0000, 0x080c, 0x2a85, 0x2011, - 0x8011, 0x2019, 0x010e, 0x231c, 0x939e, 0x0007, 0x1118, 0x2019, - 0x0001, 0x0010, 0x2019, 0x0000, 0x080c, 0x4ca1, 0x0468, 0x2001, - 0x19a9, 0x200c, 0x81ff, 0x1140, 0x2001, 0x0109, 0x2004, 0xd0b4, - 0x0118, 0x2019, 0x0003, 0x0008, 0x2118, 0x2011, 0x8012, 0x080c, - 0x4ca1, 0x080c, 0x0ed3, 0x080c, 0x5844, 0xd0fc, 0x11a8, 0x080c, - 0xd63e, 0x1190, 0x00c6, 0x080c, 0x2720, 0x080c, 0xacfc, 0x080c, - 0xa4f1, 0x080c, 0xad18, 0x2061, 0x0100, 0x2019, 0x0028, 0x2009, - 0x0002, 0x080c, 0x32da, 0x00ce, 0x012e, 0x00fe, 0x00ee, 0x003e, - 0x002e, 0x001e, 0x000e, 0x0005, 0x2028, 0x918c, 0x00ff, 0x2130, - 0x9094, 0xff00, 0x11f0, 0x2011, 0x1837, 0x2214, 0xd2ac, 0x11c8, - 0x81ff, 0x01e8, 0x2011, 0x181f, 0x2204, 0x9106, 0x1190, 0x2011, - 0x1820, 0x2214, 0x9294, 0xff00, 0x9584, 0xff00, 0x9206, 0x1148, - 0x2011, 0x1820, 0x2214, 0x9294, 0x00ff, 0x9584, 0x00ff, 0x9206, - 0x1120, 0x2500, 0x080c, 0x8521, 0x0048, 0x9584, 0x00ff, 0x9080, - 0x348e, 0x200d, 0x918c, 0xff00, 0x810f, 0x9006, 0x0005, 0x9080, - 0x348e, 0x200d, 0x918c, 0x00ff, 0x0005, 0x00d6, 0x2069, 0x0140, - 0x2001, 0x1818, 0x2003, 0x00ef, 0x20a9, 0x0010, 0x9006, 0x6852, - 0x6856, 0x1f04, 0x26d0, 0x00de, 0x0005, 0x0006, 0x00d6, 0x0026, - 0x2069, 0x0140, 0x2001, 0x1818, 0x2102, 0x8114, 0x8214, 0x8214, - 0x8214, 0x20a9, 0x0010, 0x6853, 0x0000, 0x9006, 0x82ff, 0x1128, - 0x9184, 0x000f, 0x9080, 0xef08, 0x2005, 0x6856, 0x8211, 0x1f04, - 0x26e5, 0x002e, 0x00de, 0x000e, 0x0005, 0x00c6, 0x2061, 0x1800, - 0x6030, 0x0110, 0xc09d, 0x0008, 0xc09c, 0x6032, 0x00ce, 0x0005, - 0x0156, 0x00d6, 0x0026, 0x0016, 0x0006, 0x2069, 0x0140, 0x6980, - 0x9116, 0x0180, 0x9112, 0x1230, 0x8212, 0x8210, 0x22a8, 0x2001, - 0x0402, 0x0018, 0x22a8, 0x2001, 0x0404, 0x680e, 0x1f04, 0x2715, - 0x680f, 0x0000, 0x000e, 0x001e, 0x002e, 0x00de, 0x015e, 0x0005, - 0x080c, 0x5840, 0xd0c4, 0x0150, 0xd0a4, 0x0140, 0x9006, 0x0046, - 0x2020, 0x2009, 0x002e, 0x080c, 0xea8d, 0x004e, 0x0005, 0x00f6, - 0x0016, 0x0026, 0x2079, 0x0140, 0x78c4, 0xd0dc, 0x0904, 0x278c, - 0x080c, 0x29fc, 0x0660, 0x9084, 0x0700, 0x908e, 0x0600, 0x1120, - 0x2011, 0x4000, 0x900e, 0x0458, 0x908e, 0x0500, 0x1120, 0x2011, - 0x8000, 0x900e, 0x0420, 0x908e, 0x0400, 0x1120, 0x9016, 0x2009, - 0x0001, 0x00e8, 0x908e, 0x0300, 0x1120, 0x9016, 0x2009, 0x0002, - 0x00b0, 0x908e, 0x0200, 0x1120, 0x9016, 0x2009, 0x0004, 0x0078, - 0x908e, 0x0100, 0x1548, 0x9016, 0x2009, 0x0008, 0x0040, 0x9084, - 0x0700, 0x908e, 0x0300, 0x1500, 0x2011, 0x0030, 0x0058, 0x2300, - 0x9080, 0x0020, 0x2018, 0x080c, 0x955b, 0x928c, 0xff00, 0x0110, - 0x2011, 0x00ff, 0x2200, 0x8007, 0x9085, 0x004c, 0x78c2, 0x2009, - 0x0138, 0x220a, 0x080c, 0x779e, 0x1118, 0x2009, 0x196d, 0x220a, - 0x002e, 0x001e, 0x00fe, 0x0005, 0x78c3, 0x0000, 0x0cc8, 0x0126, - 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x2001, 0x0170, 0x200c, - 0x8000, 0x2014, 0x9184, 0x0003, 0x0110, 0x080c, 0x0d7e, 0x002e, - 0x001e, 0x000e, 0x012e, 0x0005, 0x2001, 0x180d, 0x2004, 0xd08c, - 0x0118, 0x2009, 0x0002, 0x0005, 0x2001, 0x0171, 0x2004, 0xd0dc, - 0x0168, 0x2001, 0x0170, 0x200c, 0x918c, 0x00ff, 0x918e, 0x004c, - 0x1128, 0x200c, 0x918c, 0xff00, 0x810f, 0x0005, 0x900e, 0x2001, - 0x0227, 0x2004, 0x8007, 0x9084, 0x00ff, 0x8004, 0x9108, 0x2001, - 0x0226, 0x2004, 0x8007, 0x9084, 0x00ff, 0x8004, 0x9108, 0x0005, - 0x0018, 0x000c, 0x0018, 0x0020, 0x1000, 0x0800, 0x1000, 0x1800, - 0x0156, 0x0006, 0x0016, 0x0026, 0x00e6, 0x2001, 0x1990, 0x2004, - 0x908a, 0x0007, 0x1a0c, 0x0d85, 0x0033, 0x00ee, 0x002e, 0x001e, - 0x000e, 0x015e, 0x0005, 0x27f2, 0x2810, 0x2834, 0x2836, 0x285f, - 0x2861, 0x2863, 0x2001, 0x0001, 0x080c, 0x2631, 0x080c, 0x2a4a, - 0x2001, 0x1992, 0x2003, 0x0000, 0x7828, 0x9084, 0xe1d7, 0x782a, - 0x9006, 0x20a9, 0x0009, 0x080c, 0x2a18, 0x2001, 0x1990, 0x2003, - 0x0006, 0x2009, 0x001e, 0x2011, 0x2864, 0x080c, 0x8a5d, 0x0005, - 0x2009, 0x1995, 0x200b, 0x0000, 0x2001, 0x199a, 0x2003, 0x0036, - 0x2001, 0x1999, 0x2003, 0x002a, 0x2001, 0x1992, 0x2003, 0x0001, - 0x9006, 0x080c, 0x29ad, 0x2001, 0xffff, 0x20a9, 0x0009, 0x080c, - 0x2a18, 0x2001, 0x1990, 0x2003, 0x0006, 0x2009, 0x001e, 0x2011, - 0x2864, 0x080c, 0x8a5d, 0x0005, 0x080c, 0x0d85, 0x2001, 0x199a, - 0x2003, 0x0036, 0x2001, 0x1992, 0x2003, 0x0003, 0x7a38, 0x9294, - 0x0005, 0x9296, 0x0004, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, - 0x080c, 0x29ad, 0x2001, 0x1996, 0x2003, 0x0000, 0x2001, 0xffff, - 0x20a9, 0x0009, 0x080c, 0x2a18, 0x2001, 0x1990, 0x2003, 0x0006, - 0x2009, 0x001e, 0x2011, 0x2864, 0x080c, 0x8a5d, 0x0005, 0x080c, - 0x0d85, 0x080c, 0x0d85, 0x0005, 0x0006, 0x0016, 0x0026, 0x00e6, - 0x00f6, 0x0156, 0x0126, 0x2091, 0x8000, 0x2079, 0x0100, 0x2001, - 0x1992, 0x2004, 0x908a, 0x0007, 0x1a0c, 0x0d85, 0x0043, 0x012e, - 0x015e, 0x00fe, 0x00ee, 0x002e, 0x001e, 0x000e, 0x0005, 0x2886, - 0x28a2, 0x28de, 0x290a, 0x292a, 0x2936, 0x2938, 0x080c, 0x2a0c, - 0x1190, 0x2009, 0x1998, 0x2104, 0x7a38, 0x9294, 0x0005, 0x9296, - 0x0004, 0x0110, 0xc08d, 0x0008, 0xc085, 0x200a, 0x2001, 0x1990, - 0x2003, 0x0001, 0x0030, 0x080c, 0x295c, 0x2001, 0xffff, 0x080c, - 0x2801, 0x0005, 0x080c, 0x293a, 0x05c0, 0x2009, 0x1999, 0x2104, - 0x8001, 0x200a, 0x080c, 0x2a0c, 0x1158, 0x7a38, 0x9294, 0x0005, - 0x9296, 0x0005, 0x0518, 0x2009, 0x1998, 0x2104, 0xc085, 0x200a, - 0x2009, 0x1995, 0x2104, 0x8000, 0x200a, 0x9086, 0x0005, 0x0118, - 0x080c, 0x2942, 0x00c0, 0x200b, 0x0000, 0x7a38, 0x9294, 0x0006, - 0x9296, 0x0004, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, - 0x29ca, 0x2001, 0x1992, 0x2003, 0x0002, 0x0028, 0x2001, 0x1990, - 0x2003, 0x0003, 0x0010, 0x080c, 0x2823, 0x0005, 0x080c, 0x293a, - 0x0540, 0x2009, 0x1999, 0x2104, 0x8001, 0x200a, 0x080c, 0x2a0c, - 0x1148, 0x2001, 0x1990, 0x2003, 0x0003, 0x2001, 0x1991, 0x2003, - 0x0000, 0x00b8, 0x2009, 0x1999, 0x2104, 0x9005, 0x1118, 0x080c, - 0x297f, 0x0010, 0x080c, 0x294f, 0x080c, 0x2942, 0x2009, 0x1995, - 0x200b, 0x0000, 0x2001, 0x1992, 0x2003, 0x0001, 0x080c, 0x2823, - 0x0000, 0x0005, 0x0479, 0x01e8, 0x080c, 0x2a0c, 0x1198, 0x2009, - 0x1996, 0x2104, 0x8000, 0x200a, 0x9086, 0x0007, 0x0108, 0x0078, - 0x2001, 0x199b, 0x2003, 0x000a, 0x2009, 0x1998, 0x2104, 0xc0fd, - 0x200a, 0x0038, 0x00f9, 0x2001, 0x1992, 0x2003, 0x0004, 0x080c, - 0x284e, 0x0005, 0x0079, 0x0148, 0x080c, 0x2a0c, 0x1118, 0x080c, - 0x283a, 0x0018, 0x0079, 0x080c, 0x284e, 0x0005, 0x080c, 0x0d85, - 0x080c, 0x0d85, 0x2009, 0x199a, 0x2104, 0x8001, 0x200a, 0x090c, - 0x299b, 0x0005, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0005, 0x0110, - 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x29ca, 0x0005, 0x7a38, - 0x9294, 0x0006, 0x9296, 0x0006, 0x0110, 0x9006, 0x0010, 0x2001, - 0x0001, 0x080c, 0x29ad, 0x0005, 0x2009, 0x1995, 0x2104, 0x8000, - 0x200a, 0x9086, 0x0005, 0x0108, 0x0068, 0x200b, 0x0000, 0x7a38, - 0x9294, 0x0006, 0x9296, 0x0006, 0x0110, 0x9006, 0x0010, 0x2001, - 0x0001, 0x04d9, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0005, 0x0110, - 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x29ca, 0x0005, 0x0086, - 0x2001, 0x1998, 0x2004, 0x9084, 0x7fff, 0x090c, 0x0d85, 0x2009, - 0x1997, 0x2144, 0x8846, 0x280a, 0x9844, 0x0dd8, 0xd08c, 0x1120, - 0xd084, 0x1120, 0x080c, 0x0d85, 0x9006, 0x0010, 0x2001, 0x0001, - 0x00a1, 0x008e, 0x0005, 0x0006, 0x0156, 0x2001, 0x1990, 0x20a9, - 0x0009, 0x2003, 0x0000, 0x8000, 0x1f04, 0x29a1, 0x2001, 0x1997, - 0x2003, 0x8000, 0x015e, 0x000e, 0x0005, 0x00f6, 0x2079, 0x0100, - 0x9085, 0x0000, 0x0158, 0x7838, 0x9084, 0xfff9, 0x9085, 0x0004, - 0x783a, 0x2009, 0x199d, 0x210c, 0x795a, 0x0050, 0x7838, 0x9084, - 0xfffb, 0x9085, 0x0006, 0x783a, 0x2009, 0x199e, 0x210c, 0x795a, - 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0100, 0x9085, 0x0000, 0x0158, - 0x7838, 0x9084, 0xfffa, 0x9085, 0x0004, 0x783a, 0x7850, 0x9084, - 0xfff0, 0x7852, 0x00f8, 0x7838, 0x9084, 0xfffb, 0x9085, 0x0005, - 0x783a, 0x7850, 0x9084, 0xfff0, 0x0016, 0x2009, 0x017f, 0x210c, - 0x918e, 0x0005, 0x0140, 0x2009, 0x0003, 0x210c, 0x918c, 0x0600, - 0x918e, 0x0400, 0x0118, 0x9085, 0x000a, 0x0010, 0x9085, 0x0000, - 0x001e, 0x7852, 0x00fe, 0x0005, 0x0006, 0x2001, 0x0100, 0x2004, - 0x9082, 0x0007, 0x000e, 0x0005, 0x0006, 0x2001, 0x0100, 0x2004, - 0x9082, 0x0009, 0x000e, 0x0005, 0x0156, 0x20a9, 0x0064, 0x7820, - 0x080c, 0x2a7f, 0xd09c, 0x1110, 0x1f04, 0x2a0f, 0x015e, 0x0005, - 0x0126, 0x0016, 0x0006, 0x2091, 0x8000, 0x000e, 0x2008, 0x9186, - 0x0000, 0x1118, 0x783b, 0x0007, 0x0090, 0x9186, 0x0001, 0x1118, - 0x783b, 0x0006, 0x0060, 0x9186, 0x0002, 0x1118, 0x783b, 0x0005, - 0x0030, 0x9186, 0x0003, 0x1118, 0x783b, 0x0004, 0x0000, 0x0006, - 0x1d04, 0x2a38, 0x080c, 0x8a7f, 0x1f04, 0x2a38, 0x080c, 0x2af6, - 0x080c, 0x2b29, 0x7850, 0x9085, 0x1000, 0x7852, 0x000e, 0x001e, - 0x012e, 0x0005, 0x080c, 0x2b29, 0x0005, 0x0006, 0x0156, 0x00f6, - 0x2079, 0x0100, 0x20a9, 0x000a, 0x7854, 0xd0ac, 0x1100, 0x7854, - 0xd08c, 0x1110, 0x1f04, 0x2a57, 0x00fe, 0x015e, 0x000e, 0x0005, - 0x1d04, 0x2a60, 0x080c, 0x8a7f, 0x1f04, 0x2a60, 0x0005, 0x0006, - 0x2001, 0x199c, 0x2004, 0x9086, 0x0000, 0x000e, 0x0005, 0x0006, - 0x2001, 0x199c, 0x2004, 0x9086, 0x0001, 0x000e, 0x0005, 0x0006, - 0x2001, 0x199c, 0x2004, 0x9086, 0x0002, 0x000e, 0x0005, 0xa001, - 0xa001, 0xa001, 0xa001, 0xa001, 0x0005, 0x0006, 0x2001, 0x19a9, - 0x2102, 0x000e, 0x0005, 0x2009, 0x0171, 0x2104, 0xd0dc, 0x0140, - 0x2009, 0x0170, 0x2104, 0x200b, 0x0080, 0xa001, 0xa001, 0x200a, - 0x0005, 0x0016, 0x0026, 0x080c, 0x77b8, 0x0108, 0xc0bc, 0x2009, - 0x0140, 0x2114, 0x9294, 0x0001, 0x9215, 0x220a, 0x002e, 0x001e, - 0x0005, 0x0016, 0x0026, 0x2009, 0x0140, 0x2114, 0x9294, 0x0001, - 0x9285, 0x1000, 0x200a, 0x220a, 0x002e, 0x001e, 0x0005, 0x0016, - 0x0026, 0x2009, 0x0140, 0x2114, 0x9294, 0x0001, 0x9215, 0x220a, - 0x002e, 0x001e, 0x0005, 0x0006, 0x0016, 0x2009, 0x0140, 0x2104, - 0x1128, 0x080c, 0x77b8, 0x0110, 0xc0bc, 0x0008, 0xc0bd, 0x200a, - 0x001e, 0x000e, 0x0005, 0x00f6, 0x2079, 0x0380, 0x7843, 0x0101, - 0x7844, 0xd084, 0x1de8, 0x2001, 0x0109, 0x2202, 0x7843, 0x0100, - 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0380, 0x7843, 0x0202, 0x7844, - 0xd08c, 0x1de8, 0x2079, 0x0100, 0x7814, 0x9104, 0x9205, 0x7a16, - 0x2079, 0x0380, 0x7843, 0x0200, 0x00fe, 0x0005, 0x0016, 0x0026, - 0x0036, 0x00c6, 0x2061, 0x0100, 0x6050, 0x9084, 0xfbff, 0x9085, - 0x0040, 0x6052, 0x20a9, 0x0002, 0x080c, 0x2a60, 0x6050, 0x9085, - 0x0400, 0x9084, 0xff9f, 0x6052, 0x20a9, 0x0005, 0x080c, 0x2a60, - 0x6054, 0xd0bc, 0x090c, 0x0d85, 0x20a9, 0x0005, 0x080c, 0x2a60, - 0x6054, 0xd0ac, 0x090c, 0x0d85, 0x2009, 0x19b0, 0x9084, 0x7e00, - 0x8007, 0x8004, 0x8004, 0x200a, 0x00ce, 0x003e, 0x002e, 0x001e, - 0x0005, 0x0006, 0x00c6, 0x2061, 0x0100, 0x6050, 0xc0cd, 0x6052, - 0x00ce, 0x000e, 0x0005, 0x0016, 0x00c6, 0x00d6, 0x0006, 0x2061, - 0x0100, 0x2069, 0x0140, 0x6030, 0x0006, 0x6048, 0x0006, 0x60e4, - 0x0006, 0x60e8, 0x0006, 0x6050, 0x0006, 0x60ec, 0x0006, 0x600c, - 0x0006, 0x6004, 0x0006, 0xc0fc, 0x6006, 0x2009, 0x0800, 0x2001, - 0x0338, 0x2003, 0x0301, 0x8109, 0x090c, 0x0d85, 0x2001, 0x0338, - 0x2004, 0xd084, 0x1dc0, 0x6028, 0x0006, 0x60e0, 0x0006, 0x6888, - 0x0006, 0x688c, 0x0006, 0x6890, 0x0006, 0x080c, 0x779e, 0x1110, - 0x6884, 0x0006, 0x602f, 0x0100, 0x602f, 0x0000, 0xa001, 0xa001, - 0xa001, 0xa001, 0x602f, 0x0040, 0x602f, 0x0000, 0x080c, 0x779e, - 0x1120, 0x6803, 0x0080, 0x000e, 0x6886, 0x6897, 0x4198, 0x000e, - 0x6892, 0x000e, 0x688e, 0x000e, 0x688a, 0x000e, 0x60e2, 0x000e, - 0x602a, 0x000e, 0x6006, 0x000e, 0x600e, 0x000e, 0x60ee, 0x000e, - 0x6052, 0x000e, 0x60ea, 0x000e, 0x60e6, 0x000e, 0x604a, 0x000e, - 0x6032, 0x6036, 0x2008, 0x080c, 0x26d5, 0x000e, 0x00de, 0x00ce, - 0x001e, 0x0005, 0x0006, 0x0156, 0x6050, 0x9085, 0x0040, 0x6052, - 0x6050, 0x9084, 0xfbcf, 0x6052, 0x080c, 0x2a7f, 0x9085, 0x2000, - 0x6052, 0x20a9, 0x0012, 0x1d04, 0x2bb3, 0x080c, 0x8a7f, 0x1f04, - 0x2bb3, 0x6050, 0x9085, 0x0400, 0x9084, 0xdfbf, 0x6052, 0x015e, - 0x000e, 0x0005, 0x30be, 0x30be, 0x2cc2, 0x2cc2, 0x2cce, 0x2cce, - 0x2cda, 0x2cda, 0x2ce8, 0x2ce8, 0x2cf4, 0x2cf4, 0x2d02, 0x2d02, - 0x2d10, 0x2d10, 0x2d22, 0x2d22, 0x2d2e, 0x2d2e, 0x2d3c, 0x2d3c, - 0x2d5a, 0x2d5a, 0x2d7a, 0x2d7a, 0x2d4a, 0x2d4a, 0x2d6a, 0x2d6a, - 0x2d88, 0x2d88, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, - 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, - 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, - 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, - 0x2d20, 0x2d20, 0x2d9a, 0x2d9a, 0x2da6, 0x2da6, 0x2db4, 0x2db4, - 0x2dc2, 0x2dc2, 0x2dd2, 0x2dd2, 0x2de0, 0x2de0, 0x2df0, 0x2df0, - 0x2e00, 0x2e00, 0x2e12, 0x2e12, 0x2e20, 0x2e20, 0x2e30, 0x2e30, - 0x2e52, 0x2e52, 0x2e76, 0x2e76, 0x2e40, 0x2e40, 0x2e64, 0x2e64, - 0x2e86, 0x2e86, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, - 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, - 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, - 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, - 0x2d20, 0x2d20, 0x2e9a, 0x2e9a, 0x2ea6, 0x2ea6, 0x2eb4, 0x2eb4, - 0x2ec2, 0x2ec2, 0x2ed2, 0x2ed2, 0x2ee0, 0x2ee0, 0x2ef0, 0x2ef0, - 0x2f00, 0x2f00, 0x2f12, 0x2f12, 0x2f20, 0x2f20, 0x2f30, 0x2f30, - 0x2f40, 0x2f40, 0x2f52, 0x2f52, 0x2f62, 0x2f62, 0x2f74, 0x2f74, - 0x2f86, 0x2f86, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, - 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, - 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, - 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, - 0x2d20, 0x2d20, 0x2f9a, 0x2f9a, 0x2fa8, 0x2fa8, 0x2fb8, 0x2fb8, - 0x2fc8, 0x2fc8, 0x2fda, 0x2fda, 0x2fea, 0x2fea, 0x2ffc, 0x2ffc, - 0x300e, 0x300e, 0x3022, 0x3022, 0x3032, 0x3032, 0x3044, 0x3044, - 0x3056, 0x3056, 0x306a, 0x306a, 0x307b, 0x307b, 0x308e, 0x308e, - 0x30a1, 0x30a1, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, - 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, - 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, - 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, - 0x2d20, 0x2d20, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x22c8, 0x0804, 0x30b6, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x20ea, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x20ea, 0x080c, 0x22c8, 0x0804, 0x30b6, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x2114, 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x22c8, 0x080c, 0x2114, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x20ea, 0x080c, 0x2114, 0x0804, 0x30b6, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x20ea, 0x080c, 0x22c8, 0x080c, 0x2114, 0x0804, 0x30b6, - 0xa001, 0x0cf0, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x13d4, 0x0804, 0x30b6, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x22c8, - 0x080c, 0x13d4, 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x20ea, 0x080c, 0x13d4, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x22c8, 0x080c, 0x13d4, 0x080c, 0x2114, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x20ea, 0x080c, 0x22c8, 0x080c, 0x13d4, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x20ea, 0x080c, 0x13d4, 0x080c, 0x2114, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x13d4, 0x080c, 0x2114, 0x0804, 0x30b6, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x20ea, 0x080c, 0x22c8, 0x080c, 0x13d4, 0x080c, 0x2114, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x278f, 0x0804, 0x30b6, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x278f, - 0x080c, 0x22c8, 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0x20ea, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0x20ea, 0x080c, 0x22c8, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0x2114, 0x0804, 0x30b6, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x278f, 0x080c, 0x22c8, 0x080c, 0x2114, 0x0804, 0x30b6, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x278f, 0x080c, 0x20ea, 0x080c, 0x2114, 0x0804, 0x30b6, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x278f, 0x080c, 0x20ea, 0x080c, 0x22c8, 0x080c, 0x2114, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0x13d4, 0x0804, 0x30b6, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x278f, 0x080c, 0x22c8, 0x080c, 0x13d4, 0x0804, 0x30b6, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x278f, 0x080c, 0x20ea, 0x080c, 0x13d4, 0x0804, 0x30b6, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x278f, 0x080c, 0x22c8, 0x080c, 0x13d4, 0x080c, 0x2114, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0x20ea, 0x080c, 0x22c8, - 0x080c, 0x13d4, 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0x20ea, - 0x080c, 0x13d4, 0x080c, 0x2114, 0x0804, 0x30b6, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x278f, - 0x080c, 0x13d4, 0x080c, 0x2114, 0x0804, 0x30b6, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x278f, - 0x080c, 0x20ea, 0x080c, 0x22c8, 0x080c, 0x13d4, 0x080c, 0x2114, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0xad62, 0x0804, 0x30b6, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0xad62, - 0x080c, 0x22c8, 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x20ea, 0x080c, 0xad62, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x20ea, 0x080c, 0xad62, 0x080c, 0x22c8, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0xad62, 0x080c, 0x2114, 0x0804, 0x30b6, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0xad62, 0x080c, 0x22c8, 0x080c, 0x2114, 0x0804, 0x30b6, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x20ea, 0x080c, 0xad62, 0x080c, 0x2114, 0x0804, 0x30b6, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x20ea, 0x080c, 0xad62, 0x080c, 0x22c8, 0x080c, 0x2114, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0xad62, 0x080c, 0x13d4, 0x0804, 0x30b6, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0xad62, 0x080c, 0x22c8, 0x080c, 0x13d4, 0x0804, 0x30b6, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x20ea, 0x080c, 0xad62, 0x080c, 0x13d4, 0x0804, 0x30b6, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x20ea, 0x080c, 0xad62, 0x080c, 0x22c8, 0x080c, 0x13d4, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0xad62, 0x080c, 0x13d4, 0x080c, 0x2114, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0xad62, 0x080c, 0x22c8, 0x080c, 0x13d4, - 0x080c, 0x2114, 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x20ea, 0x080c, 0xad62, - 0x080c, 0x13d4, 0x080c, 0x2114, 0x0804, 0x30b6, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x20ea, - 0x080c, 0xad62, 0x080c, 0x22c8, 0x080c, 0x13d4, 0x080c, 0x2114, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0xad62, 0x0804, 0x30b6, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x278f, 0x080c, 0xad62, 0x080c, 0x22c8, 0x0804, 0x30b6, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x278f, 0x080c, 0x20ea, 0x080c, 0xad62, 0x0804, 0x30b6, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x278f, 0x080c, 0x20ea, 0x080c, 0xad62, 0x080c, 0x22c8, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0xad62, 0x080c, 0x2114, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0xad62, 0x080c, 0x22c8, - 0x080c, 0x2114, 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0x20ea, - 0x080c, 0xad62, 0x080c, 0x2114, 0x0804, 0x30b6, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x278f, - 0x080c, 0x20ea, 0x080c, 0xad62, 0x080c, 0x22c8, 0x080c, 0x2114, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0xad62, 0x080c, 0x13d4, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0xad62, 0x080c, 0x22c8, - 0x080c, 0x13d4, 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0x20ea, - 0x080c, 0xad62, 0x080c, 0x13d4, 0x0804, 0x30b6, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x278f, - 0x080c, 0x20ea, 0x080c, 0xad62, 0x080c, 0x22c8, 0x080c, 0x13d4, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0xad62, 0x080c, 0x13d4, - 0x080c, 0x2114, 0x04d8, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0xad62, 0x080c, - 0x22c8, 0x080c, 0x13d4, 0x080c, 0x2114, 0x0440, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x278f, - 0x080c, 0x20ea, 0x080c, 0x13d4, 0x080c, 0xad62, 0x080c, 0x2114, - 0x00a8, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x278f, 0x080c, 0x20ea, 0x080c, 0xad62, 0x080c, - 0x22c8, 0x080c, 0x13d4, 0x080c, 0x2114, 0x0000, 0x015e, 0x014e, - 0x013e, 0x01de, 0x01ce, 0x012e, 0x000e, 0x010e, 0x000d, 0x00b6, - 0x00c6, 0x0026, 0x0046, 0x9026, 0x080c, 0x6bcf, 0x1904, 0x31f6, - 0x72dc, 0x2001, 0x197c, 0x2004, 0x9005, 0x1110, 0xd29c, 0x0148, - 0xd284, 0x1138, 0xd2bc, 0x1904, 0x31f6, 0x080c, 0x31fb, 0x0804, - 0x31f6, 0xd2cc, 0x1904, 0x31f6, 0x080c, 0x779e, 0x1120, 0x70af, - 0xffff, 0x0804, 0x31f6, 0xd294, 0x0120, 0x70af, 0xffff, 0x0804, - 0x31f6, 0x080c, 0x347d, 0x0160, 0x080c, 0xd645, 0x0128, 0x2001, - 0x1818, 0x203c, 0x0804, 0x316f, 0x70af, 0xffff, 0x0804, 0x31f6, - 0x2001, 0x1818, 0x203c, 0x7294, 0xd284, 0x0904, 0x316f, 0xd28c, - 0x1904, 0x316f, 0x0036, 0x73ac, 0x938e, 0xffff, 0x1110, 0x2019, - 0x0001, 0x8314, 0x92e0, 0x1d80, 0x2c04, 0x938c, 0x0001, 0x0120, - 0x9084, 0xff00, 0x8007, 0x0010, 0x9084, 0x00ff, 0x970e, 0x0904, - 0x3165, 0x908e, 0x0000, 0x0904, 0x3165, 0x908e, 0x00ff, 0x1160, - 0x7230, 0xd284, 0x1904, 0x316a, 0x7294, 0xc28d, 0x7296, 0x70af, - 0xffff, 0x003e, 0x0804, 0x316f, 0x2009, 0x180d, 0x210c, 0xd18c, - 0x0150, 0x0026, 0x2011, 0x0010, 0x080c, 0x6c35, 0x002e, 0x0118, - 0x70af, 0xffff, 0x0488, 0x900e, 0x080c, 0x268c, 0x080c, 0x6749, - 0x1538, 0x9006, 0xb8bb, 0x0520, 0xb8ac, 0x9005, 0x0148, 0x00c6, - 0x2060, 0x080c, 0x8eee, 0x00ce, 0x090c, 0x928d, 0xb8af, 0x0000, - 0x080c, 0x6c11, 0x1168, 0x7030, 0xd08c, 0x0130, 0xb800, 0xd0bc, - 0x0138, 0x080c, 0x6aae, 0x0120, 0x080c, 0x3214, 0x0148, 0x0028, - 0x080c, 0x3360, 0x080c, 0x3240, 0x0118, 0x8318, 0x0804, 0x3109, - 0x73ae, 0x0010, 0x70af, 0xffff, 0x003e, 0x0804, 0x31f6, 0x9780, - 0x348e, 0x203d, 0x97bc, 0xff00, 0x873f, 0x2041, 0x007e, 0x70ac, - 0x9096, 0xffff, 0x1118, 0x900e, 0x28a8, 0x0050, 0x9812, 0x0220, - 0x2008, 0x9802, 0x20a8, 0x0020, 0x70af, 0xffff, 0x0804, 0x31f6, - 0x2700, 0x0156, 0x0016, 0x9106, 0x0904, 0x31eb, 0x2001, 0x180d, - 0x2004, 0xd08c, 0x0158, 0x0026, 0x2011, 0x0010, 0x080c, 0x6c35, - 0x002e, 0x0120, 0x2009, 0xffff, 0x0804, 0x31f3, 0xc484, 0x080c, - 0x67b4, 0x0168, 0x080c, 0xd645, 0x1904, 0x31eb, 0x080c, 0x347d, - 0x1904, 0x31eb, 0x080c, 0x6749, 0x1904, 0x31f3, 0x0008, 0xc485, - 0xb8bb, 0x0520, 0xb8ac, 0x9005, 0x0148, 0x00c6, 0x2060, 0x080c, - 0x8eee, 0x00ce, 0x090c, 0x928d, 0xb8af, 0x0000, 0x080c, 0x6c11, - 0x1130, 0x7030, 0xd08c, 0x01f8, 0xb800, 0xd0bc, 0x11e0, 0x7294, - 0xd28c, 0x0180, 0x080c, 0x6c11, 0x9082, 0x0006, 0x02e0, 0xd484, - 0x1118, 0x080c, 0x676e, 0x0028, 0x080c, 0x33f3, 0x01a0, 0x080c, - 0x341e, 0x0088, 0x080c, 0x3360, 0x080c, 0xd645, 0x1160, 0x080c, - 0x3240, 0x0188, 0x0040, 0x080c, 0xd645, 0x1118, 0x080c, 0x33f3, - 0x0110, 0x0451, 0x0140, 0x001e, 0x8108, 0x015e, 0x1f04, 0x3188, - 0x70af, 0xffff, 0x0018, 0x001e, 0x015e, 0x71ae, 0x004e, 0x002e, - 0x00ce, 0x00be, 0x0005, 0x00c6, 0x0016, 0x70af, 0x0001, 0x2009, - 0x007e, 0x080c, 0x6749, 0x1168, 0xb813, 0x00ff, 0xb817, 0xfffe, - 0x080c, 0x3360, 0x04a9, 0x0128, 0x70dc, 0xc0bd, 0x70de, 0x080c, - 0xd389, 0x001e, 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, - 0x2001, 0x184c, 0x2004, 0x9084, 0x00ff, 0xb842, 0x080c, 0xb1dd, - 0x01d0, 0x2b00, 0x6012, 0x080c, 0xd3b6, 0x6023, 0x0001, 0x9006, - 0x080c, 0x66e6, 0x2001, 0x0000, 0x080c, 0x66fa, 0x0126, 0x2091, - 0x8000, 0x70a8, 0x8000, 0x70aa, 0x012e, 0x2009, 0x0004, 0x080c, - 0xb20a, 0x9085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, - 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2001, 0x184c, 0x2004, 0x9084, - 0x00ff, 0xb842, 0x080c, 0xb1dd, 0x0548, 0x2b00, 0x6012, 0xb800, - 0xc0c4, 0xb802, 0xb8a0, 0x9086, 0x007e, 0x0140, 0xb804, 0x9084, - 0x00ff, 0x9086, 0x0006, 0x1110, 0x080c, 0x3315, 0x080c, 0xd3b6, - 0x6023, 0x0001, 0x9006, 0x080c, 0x66e6, 0x2001, 0x0002, 0x080c, - 0x66fa, 0x0126, 0x2091, 0x8000, 0x70a8, 0x8000, 0x70aa, 0x012e, - 0x2009, 0x0002, 0x080c, 0xb20a, 0x9085, 0x0001, 0x00ce, 0x00de, - 0x007e, 0x001e, 0x0005, 0x00b6, 0x00c6, 0x0026, 0x2009, 0x0080, - 0x080c, 0x6749, 0x1140, 0xb813, 0x00ff, 0xb817, 0xfffc, 0x0039, - 0x0110, 0x70e3, 0xffff, 0x002e, 0x00ce, 0x00be, 0x0005, 0x0016, - 0x0076, 0x00d6, 0x00c6, 0x080c, 0xb116, 0x01d0, 0x2b00, 0x6012, - 0x080c, 0xd3b6, 0x6023, 0x0001, 0x9006, 0x080c, 0x66e6, 0x2001, - 0x0002, 0x080c, 0x66fa, 0x0126, 0x2091, 0x8000, 0x70e4, 0x8000, - 0x70e6, 0x012e, 0x2009, 0x0002, 0x080c, 0xb20a, 0x9085, 0x0001, - 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0126, - 0x2091, 0x8000, 0x2009, 0x007f, 0x080c, 0x6749, 0x11b8, 0xb813, - 0x00ff, 0xb817, 0xfffd, 0xb8d7, 0x0004, 0x080c, 0xb116, 0x0170, - 0x2b00, 0x6012, 0x6316, 0x6023, 0x0001, 0x620a, 0x080c, 0xd3b6, - 0x2009, 0x0022, 0x080c, 0xb20a, 0x9085, 0x0001, 0x012e, 0x00de, - 0x00ce, 0x0005, 0x00e6, 0x00c6, 0x0066, 0x0036, 0x0026, 0x00b6, - 0x21f0, 0x080c, 0xacfc, 0x0106, 0x080c, 0x97bb, 0x080c, 0x9727, - 0x080c, 0xac4d, 0x080c, 0xc179, 0x010e, 0x090c, 0xad18, 0x3e08, - 0x2130, 0x81ff, 0x0120, 0x20a9, 0x007e, 0x900e, 0x0018, 0x20a9, - 0x007f, 0x900e, 0x0016, 0x080c, 0x67b4, 0x1140, 0x9686, 0x0002, - 0x1118, 0xb800, 0xd0bc, 0x1110, 0x080c, 0x61b7, 0x001e, 0x8108, - 0x1f04, 0x32fa, 0x9686, 0x0001, 0x190c, 0x3451, 0x00be, 0x002e, - 0x003e, 0x006e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x00c6, 0x0046, - 0x0036, 0x0026, 0x0016, 0x00b6, 0x080c, 0xacfc, 0x0106, 0x6210, - 0x2258, 0xbaa0, 0x0026, 0x2019, 0x0029, 0x080c, 0x97b0, 0x0076, - 0x2039, 0x0000, 0x080c, 0x966d, 0x2c08, 0x080c, 0xe75d, 0x007e, - 0x001e, 0x010e, 0x090c, 0xad18, 0xba10, 0xbb14, 0xbc84, 0x080c, - 0x61b7, 0xba12, 0xbb16, 0xbc86, 0x00be, 0x001e, 0x002e, 0x003e, - 0x004e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x00b6, 0x6010, - 0x2058, 0xb8a0, 0x00be, 0x9086, 0x0080, 0x0150, 0x2071, 0x1800, - 0x70a8, 0x9005, 0x0110, 0x8001, 0x70aa, 0x000e, 0x00ee, 0x0005, - 0x2071, 0x1800, 0x70e4, 0x9005, 0x0dc0, 0x8001, 0x70e6, 0x0ca8, - 0xb800, 0xc08c, 0xb802, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x00b6, - 0x0046, 0x0036, 0x0026, 0x0016, 0x0156, 0x2178, 0x080c, 0xacfc, - 0x0106, 0x81ff, 0x1118, 0x20a9, 0x0001, 0x0078, 0x080c, 0x5840, - 0xd0c4, 0x0140, 0xd0a4, 0x0130, 0x9006, 0x2020, 0x2009, 0x002d, - 0x080c, 0xea8d, 0x20a9, 0x0800, 0x9016, 0x0026, 0x928e, 0x007e, - 0x0904, 0x33cf, 0x928e, 0x007f, 0x0904, 0x33cf, 0x928e, 0x0080, - 0x05f0, 0x9288, 0x1000, 0x210c, 0x81ff, 0x05c8, 0x8fff, 0x1150, - 0x2001, 0x198e, 0x0006, 0x2003, 0x0001, 0x080c, 0x33e0, 0x000e, - 0x2003, 0x0000, 0x00b6, 0x00c6, 0x2158, 0x2001, 0x0001, 0x080c, - 0x6bdb, 0x00ce, 0x00be, 0x2019, 0x0029, 0x080c, 0x97b0, 0x0076, - 0x2039, 0x0000, 0x080c, 0x966d, 0x00b6, 0x00c6, 0x0026, 0x2158, - 0xba04, 0x9294, 0x00ff, 0x9286, 0x0006, 0x1118, 0xb807, 0x0404, - 0x0028, 0x2001, 0x0004, 0x8007, 0x9215, 0xba06, 0x002e, 0x00ce, - 0x00be, 0x0016, 0x2c08, 0x080c, 0xe75d, 0x001e, 0x007e, 0x002e, - 0x8210, 0x1f04, 0x3385, 0x010e, 0x090c, 0xad18, 0x015e, 0x001e, - 0x002e, 0x003e, 0x004e, 0x00be, 0x00ce, 0x00ee, 0x00fe, 0x0005, - 0x0046, 0x0026, 0x0016, 0x080c, 0x5840, 0xd0c4, 0x0140, 0xd0a4, - 0x0130, 0x9006, 0x2220, 0x2009, 0x0029, 0x080c, 0xea8d, 0x001e, - 0x002e, 0x004e, 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6, 0x7294, - 0x82ff, 0x01e8, 0x080c, 0x6c09, 0x11d0, 0x2100, 0x080c, 0x26bf, - 0x81ff, 0x01b8, 0x2019, 0x0001, 0x8314, 0x92e0, 0x1d80, 0x2c04, - 0xd384, 0x0120, 0x9084, 0xff00, 0x8007, 0x0010, 0x9084, 0x00ff, - 0x9116, 0x0138, 0x9096, 0x00ff, 0x0110, 0x8318, 0x0c68, 0x9085, - 0x0001, 0x00ce, 0x003e, 0x002e, 0x001e, 0x0005, 0x0016, 0x00c6, - 0x0126, 0x2091, 0x8000, 0x080c, 0xacfc, 0x0106, 0x0036, 0x2019, - 0x0029, 0x00c1, 0x003e, 0x010e, 0x090c, 0xad18, 0x9180, 0x1000, - 0x2004, 0x9065, 0x0158, 0x0016, 0x00c6, 0x2061, 0x1b39, 0x001e, - 0x6112, 0x080c, 0x3315, 0x001e, 0x080c, 0x676e, 0x012e, 0x00ce, - 0x001e, 0x0005, 0x0016, 0x0026, 0x2110, 0x080c, 0xa7e2, 0x080c, - 0xedee, 0x002e, 0x001e, 0x0005, 0x2001, 0x1837, 0x2004, 0xd0cc, - 0x0005, 0x00c6, 0x00b6, 0x080c, 0x779e, 0x1118, 0x20a9, 0x0800, - 0x0010, 0x20a9, 0x0782, 0x080c, 0x779e, 0x1110, 0x900e, 0x0010, - 0x2009, 0x007e, 0x9180, 0x1000, 0x2004, 0x905d, 0x0130, 0x86ff, - 0x0110, 0xb800, 0xd0bc, 0x090c, 0x676e, 0x8108, 0x1f04, 0x3462, - 0x2061, 0x1800, 0x607f, 0x0000, 0x6080, 0x9084, 0x00ff, 0x6082, - 0x60b3, 0x0000, 0x00be, 0x00ce, 0x0005, 0x2001, 0x1869, 0x2004, - 0xd0bc, 0x0005, 0x2011, 0x1848, 0x2214, 0xd2ec, 0x0005, 0x0026, - 0x2011, 0x1867, 0x2214, 0xd2dc, 0x002e, 0x0005, 0x7eef, 0x7de8, - 0x7ce4, 0x80e2, 0x7be1, 0x80e0, 0x80dc, 0x80da, 0x7ad9, 0x80d6, - 0x80d5, 0x80d4, 0x80d3, 0x80d2, 0x80d1, 0x79ce, 0x78cd, 0x80cc, - 0x80cb, 0x80ca, 0x80c9, 0x80c7, 0x80c6, 0x77c5, 0x76c3, 0x80bc, - 0x80ba, 0x75b9, 0x80b6, 0x74b5, 0x73b4, 0x72b3, 0x80b2, 0x80b1, - 0x80ae, 0x71ad, 0x80ac, 0x70ab, 0x6faa, 0x6ea9, 0x80a7, 0x6da6, - 0x6ca5, 0x6ba3, 0x6a9f, 0x699e, 0x689d, 0x809b, 0x8098, 0x6797, - 0x6690, 0x658f, 0x6488, 0x6384, 0x6282, 0x8081, 0x8080, 0x617c, - 0x607a, 0x8079, 0x5f76, 0x8075, 0x8074, 0x8073, 0x8072, 0x8071, - 0x806e, 0x5e6d, 0x806c, 0x5d6b, 0x5c6a, 0x5b69, 0x8067, 0x5a66, - 0x5965, 0x5863, 0x575c, 0x565a, 0x5559, 0x8056, 0x8055, 0x5454, - 0x5353, 0x5252, 0x5151, 0x504e, 0x4f4d, 0x804c, 0x804b, 0x4e4a, - 0x4d49, 0x8047, 0x4c46, 0x8045, 0x8043, 0x803c, 0x803a, 0x8039, - 0x8036, 0x4b35, 0x8034, 0x4a33, 0x4932, 0x4831, 0x802e, 0x472d, - 0x462c, 0x452b, 0x442a, 0x4329, 0x4227, 0x8026, 0x8025, 0x4123, - 0x401f, 0x3f1e, 0x3e1d, 0x3d1b, 0x3c18, 0x8017, 0x8010, 0x3b0f, - 0x3a08, 0x8004, 0x3902, 0x8001, 0x8000, 0x8000, 0x3800, 0x3700, - 0x3600, 0x8000, 0x3500, 0x8000, 0x8000, 0x8000, 0x3400, 0x8000, - 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3300, 0x3200, 0x8000, - 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3100, 0x3000, 0x8000, - 0x8000, 0x2f00, 0x8000, 0x2e00, 0x2d00, 0x2c00, 0x8000, 0x8000, - 0x8000, 0x2b00, 0x8000, 0x2a00, 0x2900, 0x2800, 0x8000, 0x2700, - 0x2600, 0x2500, 0x2400, 0x2300, 0x2200, 0x8000, 0x8000, 0x2100, - 0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00, 0x8000, 0x8000, 0x1b00, - 0x1a00, 0x8000, 0x1900, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, - 0x8000, 0x1800, 0x8000, 0x1700, 0x1600, 0x1500, 0x8000, 0x1400, - 0x1300, 0x1200, 0x1100, 0x1000, 0x0f00, 0x8000, 0x8000, 0x0e00, - 0x0d00, 0x0c00, 0x0b00, 0x0a00, 0x0900, 0x8000, 0x8000, 0x0800, - 0x0700, 0x8000, 0x0600, 0x8000, 0x8000, 0x8000, 0x0500, 0x0400, - 0x0300, 0x8000, 0x0200, 0x8000, 0x8000, 0x8000, 0x0100, 0x8000, - 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x0000, 0x8000, 0x8000, - 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, - 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x2071, 0x189e, - 0x7003, 0x0002, 0x9006, 0x7016, 0x701a, 0x704a, 0x704e, 0x700e, - 0x7042, 0x7046, 0x703b, 0x18ba, 0x703f, 0x18ba, 0x7007, 0x0001, - 0x080c, 0x1072, 0x090c, 0x0d85, 0x2900, 0x706a, 0xa867, 0x0002, - 0xa8ab, 0xdcb0, 0x080c, 0x1072, 0x090c, 0x0d85, 0x2900, 0x706e, - 0xa867, 0x0002, 0xa8ab, 0xdcb0, 0x0005, 0x2071, 0x189e, 0x7004, - 0x0002, 0x35bd, 0x35be, 0x35d1, 0x35e5, 0x0005, 0x1004, 0x35ce, - 0x0e04, 0x35ce, 0x2079, 0x0000, 0x0126, 0x2091, 0x8000, 0x700c, - 0x9005, 0x1128, 0x700f, 0x0001, 0x012e, 0x0468, 0x0005, 0x012e, - 0x0ce8, 0x2079, 0x0000, 0x2061, 0x18b8, 0x2c4c, 0xa86c, 0x908e, - 0x0100, 0x0128, 0x9086, 0x0200, 0x0904, 0x36b9, 0x0005, 0x7018, - 0x2048, 0x2061, 0x1800, 0x701c, 0x0807, 0x7014, 0x2048, 0xa864, - 0x9094, 0x00ff, 0x9296, 0x0029, 0x1120, 0xaa78, 0xd2fc, 0x0128, - 0x0005, 0x9086, 0x0103, 0x0108, 0x0005, 0x2079, 0x0000, 0x2061, - 0x1800, 0x701c, 0x0807, 0x2061, 0x1800, 0x7880, 0x908a, 0x0040, - 0x1210, 0x61d0, 0x0042, 0x2100, 0x908a, 0x003f, 0x1a04, 0x36b6, - 0x61d0, 0x0804, 0x364b, 0x368d, 0x36c5, 0x36b6, 0x36d1, 0x36db, - 0x36e1, 0x36e5, 0x36f5, 0x36f9, 0x370f, 0x3715, 0x371b, 0x3726, - 0x3731, 0x3740, 0x374f, 0x375d, 0x3774, 0x378f, 0x36b6, 0x383a, - 0x3878, 0x391d, 0x392e, 0x3951, 0x36b6, 0x36b6, 0x36b6, 0x3989, - 0x39a9, 0x39b2, 0x39de, 0x39e4, 0x36b6, 0x3a2a, 0x36b6, 0x36b6, - 0x36b6, 0x36b6, 0x36b6, 0x3a35, 0x3a3e, 0x3a46, 0x3a48, 0x36b6, - 0x36b6, 0x36b6, 0x36b6, 0x36b6, 0x36b6, 0x3a78, 0x36b6, 0x36b6, - 0x36b6, 0x36b6, 0x36b6, 0x3a95, 0x3b19, 0x36b6, 0x36b6, 0x36b6, - 0x36b6, 0x36b6, 0x36b6, 0x0002, 0x3b43, 0x3b46, 0x3ba5, 0x3bbe, - 0x3bee, 0x3e94, 0x36b6, 0x53f5, 0x36b6, 0x36b6, 0x36b6, 0x36b6, - 0x36b6, 0x36b6, 0x36b6, 0x36b6, 0x370f, 0x3715, 0x4397, 0x5864, - 0x43b5, 0x5484, 0x54d6, 0x55e1, 0x36b6, 0x5643, 0x567f, 0x56b0, - 0x57c0, 0x56dd, 0x5740, 0x36b6, 0x43b9, 0x457f, 0x4595, 0x45ba, - 0x461f, 0x4693, 0x46b3, 0x472a, 0x4786, 0x47e2, 0x47e5, 0x480a, - 0x487c, 0x48e6, 0x48ee, 0x4a23, 0x4bcb, 0x4bff, 0x4e63, 0x36b6, - 0x4e81, 0x4f48, 0x5031, 0x508b, 0x36b6, 0x511e, 0x36b6, 0x5134, - 0x514f, 0x48ee, 0x5395, 0x714c, 0x0000, 0x2021, 0x4000, 0x080c, - 0x4c7d, 0x0126, 0x2091, 0x8000, 0x0e04, 0x3697, 0x0010, 0x012e, - 0x0cc0, 0x7c36, 0x9486, 0x4000, 0x0118, 0x7833, 0x0011, 0x0010, - 0x7833, 0x0010, 0x7c82, 0x7986, 0x7a8a, 0x7b8e, 0x2091, 0x4080, - 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1200, 0x7007, 0x0001, - 0x2091, 0x5000, 0x700f, 0x0000, 0x012e, 0x0005, 0x2021, 0x4001, - 0x08b0, 0x2021, 0x4002, 0x0898, 0x2021, 0x4003, 0x0880, 0x2021, - 0x4005, 0x0868, 0x2021, 0x4006, 0x0850, 0x2039, 0x0001, 0x902e, - 0x2520, 0x7b88, 0x7a8c, 0x7884, 0x7990, 0x81ff, 0x0d98, 0x0804, - 0x4c8a, 0x2039, 0x0001, 0x902e, 0x2520, 0x7b88, 0x7a8c, 0x7884, - 0x7990, 0x0804, 0x4c8d, 0x7984, 0x7888, 0x2114, 0x200a, 0x0804, - 0x368d, 0x7984, 0x2114, 0x0804, 0x368d, 0x20e1, 0x0000, 0x2099, - 0x0021, 0x20e9, 0x0000, 0x20a1, 0x0021, 0x20a9, 0x001f, 0x4003, - 0x7984, 0x7a88, 0x7b8c, 0x0804, 0x368d, 0x7884, 0x2060, 0x0804, - 0x3742, 0x2009, 0x0003, 0x2011, 0x0003, 0x2019, 0x0014, 0x789b, - 0x0137, 0x7893, 0xffff, 0x2001, 0x188f, 0x2004, 0x9005, 0x0118, - 0x7896, 0x0804, 0x368d, 0x7897, 0x0001, 0x0804, 0x368d, 0x2039, - 0x0001, 0x7d98, 0x7c9c, 0x0804, 0x36c9, 0x2039, 0x0001, 0x7d98, - 0x7c9c, 0x0804, 0x36d5, 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804, - 0x36c2, 0x2138, 0x7d98, 0x7c9c, 0x0804, 0x36c9, 0x79a0, 0x9182, - 0x0040, 0x0210, 0x0804, 0x36c2, 0x2138, 0x7d98, 0x7c9c, 0x0804, - 0x36d5, 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804, 0x36c2, 0x21e8, - 0x7984, 0x7888, 0x20a9, 0x0001, 0x21a0, 0x4004, 0x0804, 0x368d, - 0x2061, 0x0800, 0xe10c, 0x9006, 0x2c15, 0x9200, 0x8c60, 0x8109, - 0x1dd8, 0x2010, 0x9005, 0x0904, 0x368d, 0x0804, 0x36bc, 0x79a0, - 0x9182, 0x0040, 0x0210, 0x0804, 0x36c2, 0x21e0, 0x20a9, 0x0001, - 0x7984, 0x2198, 0x4012, 0x0804, 0x368d, 0x2069, 0x1847, 0x7884, - 0x7990, 0x911a, 0x1a04, 0x36c2, 0x8019, 0x0904, 0x36c2, 0x684a, - 0x6942, 0x788c, 0x6852, 0x7888, 0x6856, 0x9006, 0x685a, 0x685e, - 0x080c, 0x7ae7, 0x0804, 0x368d, 0x2069, 0x1847, 0x7884, 0x7994, - 0x911a, 0x1a04, 0x36c2, 0x8019, 0x0904, 0x36c2, 0x684e, 0x6946, - 0x788c, 0x6862, 0x7888, 0x6866, 0x9006, 0x686a, 0x686e, 0x0126, - 0x2091, 0x8000, 0x080c, 0x6d66, 0x012e, 0x0804, 0x368d, 0x902e, - 0x2520, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x36bf, 0x7984, - 0x7b88, 0x7a8c, 0x20a9, 0x0005, 0x20e9, 0x0001, 0x20a1, 0x18a6, - 0x4101, 0x080c, 0x4c41, 0x1120, 0x2009, 0x0002, 0x0804, 0x36bf, - 0x2009, 0x0020, 0xa85c, 0x9080, 0x0019, 0xaf60, 0x080c, 0x4c8a, - 0x701f, 0x37b3, 0x0005, 0xa864, 0x2008, 0x9084, 0x00ff, 0x9096, - 0x0011, 0x0168, 0x9096, 0x0019, 0x0150, 0x9096, 0x0015, 0x0138, - 0x9096, 0x0048, 0x0120, 0x9096, 0x0029, 0x1904, 0x36bf, 0x810f, - 0x918c, 0x00ff, 0x0904, 0x36bf, 0x7112, 0x7010, 0x8001, 0x0560, - 0x7012, 0x080c, 0x4c41, 0x1120, 0x2009, 0x0002, 0x0804, 0x36bf, - 0x2009, 0x0020, 0x7068, 0x2040, 0xa28c, 0xa390, 0xa494, 0xa598, - 0x9290, 0x0040, 0x9399, 0x0000, 0x94a1, 0x0000, 0x95a9, 0x0000, - 0xa85c, 0x9080, 0x0019, 0xaf60, 0x080c, 0x4c8a, 0x701f, 0x37f1, - 0x0005, 0xa864, 0x9084, 0x00ff, 0x9096, 0x0002, 0x0120, 0x9096, - 0x000a, 0x1904, 0x36bf, 0x0888, 0x0126, 0x2091, 0x8000, 0x7014, - 0x2048, 0xa868, 0xc0fd, 0xa86a, 0xa864, 0x9084, 0x00ff, 0x9096, - 0x0029, 0x1148, 0xc2fd, 0xaa7a, 0x080c, 0x630a, 0x0138, 0xa87a, - 0xa982, 0x012e, 0x0060, 0x080c, 0x663a, 0x1130, 0x7007, 0x0003, - 0x701f, 0x381f, 0x012e, 0x0005, 0x080c, 0x725e, 0x012e, 0x0126, - 0x2091, 0x8000, 0x20a9, 0x0005, 0x20e1, 0x0001, 0x2099, 0x18a6, - 0x400a, 0x2100, 0x9210, 0x9399, 0x0000, 0x94a1, 0x0000, 0x95a9, - 0x0000, 0xa85c, 0x9080, 0x0019, 0x2009, 0x0020, 0x012e, 0xaf60, - 0x0804, 0x4c8d, 0x2091, 0x8000, 0x7837, 0x4000, 0x7833, 0x0010, - 0x7883, 0x4000, 0x7887, 0x4953, 0x788b, 0x5020, 0x788f, 0x2020, - 0x2009, 0x017f, 0x2104, 0x7892, 0x3f00, 0x7896, 0x2061, 0x0100, - 0x6200, 0x2061, 0x0200, 0x603c, 0x8007, 0x9205, 0x789a, 0x2009, - 0x04fd, 0x2104, 0x789e, 0x2091, 0x5000, 0x2091, 0x4080, 0x2001, - 0x0089, 0x2004, 0xd084, 0x0180, 0x2001, 0x1a25, 0x2004, 0x9005, - 0x0128, 0x2001, 0x008b, 0x2004, 0xd0fc, 0x0dd8, 0x2001, 0x008a, - 0x2003, 0x0002, 0x2003, 0x1001, 0x2071, 0x0080, 0x0804, 0x0427, - 0x81ff, 0x1904, 0x36bf, 0x7984, 0x080c, 0x67b4, 0x1904, 0x36c2, - 0x7e98, 0x9684, 0x3fff, 0x9082, 0x4000, 0x1a04, 0x36c2, 0x7c88, - 0x7d8c, 0x080c, 0x69f1, 0x080c, 0x697e, 0x1518, 0x2061, 0x1ddc, - 0x0126, 0x2091, 0x8000, 0x6000, 0x9086, 0x0000, 0x0148, 0x6014, - 0x904d, 0x0130, 0xa86c, 0x9406, 0x1118, 0xa870, 0x9506, 0x0150, - 0x012e, 0x9ce0, 0x001c, 0x2001, 0x181a, 0x2004, 0x9c02, 0x1a04, - 0x36bf, 0x0c30, 0x080c, 0xcae9, 0x012e, 0x0904, 0x36bf, 0x0804, - 0x368d, 0x900e, 0x2001, 0x0005, 0x080c, 0x725e, 0x0126, 0x2091, - 0x8000, 0x080c, 0xd226, 0x080c, 0x7012, 0x012e, 0x0804, 0x368d, - 0x00a6, 0x2950, 0xb198, 0x080c, 0x67b4, 0x1904, 0x390a, 0xb6a4, - 0x9684, 0x3fff, 0x9082, 0x4000, 0x16e8, 0xb49c, 0xb5a0, 0x080c, - 0x69f1, 0x080c, 0x697e, 0x1520, 0x2061, 0x1ddc, 0x0126, 0x2091, - 0x8000, 0x6000, 0x9086, 0x0000, 0x0148, 0x6014, 0x904d, 0x0130, - 0xa86c, 0x9406, 0x1118, 0xa870, 0x9506, 0x0158, 0x012e, 0x9ce0, - 0x001c, 0x2001, 0x181a, 0x2004, 0x9c02, 0x2009, 0x000d, 0x12b0, - 0x0c28, 0x080c, 0xcae9, 0x012e, 0x2009, 0x0003, 0x0178, 0x00e0, - 0x900e, 0x2001, 0x0005, 0x080c, 0x725e, 0x0126, 0x2091, 0x8000, - 0x080c, 0xd226, 0x080c, 0x7006, 0x012e, 0x0070, 0xb097, 0x4005, - 0xb19a, 0x0010, 0xb097, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, - 0x0030, 0x2a48, 0x00ae, 0x0005, 0xb097, 0x4000, 0x9006, 0x918d, - 0x0001, 0x2008, 0x2a48, 0x00ae, 0x0005, 0x81ff, 0x1904, 0x36bf, - 0x080c, 0x4c58, 0x0904, 0x36c2, 0x080c, 0x687b, 0x0904, 0x36bf, - 0x080c, 0x69f7, 0x0904, 0x36bf, 0x0804, 0x46aa, 0x81ff, 0x1904, - 0x36bf, 0x080c, 0x4c74, 0x0904, 0x36c2, 0x080c, 0x6a85, 0x0904, - 0x36bf, 0x2019, 0x0005, 0x79a8, 0x080c, 0x6a12, 0x0904, 0x36bf, - 0x7888, 0x908a, 0x1000, 0x1a04, 0x36c2, 0x8003, 0x800b, 0x810b, - 0x9108, 0x080c, 0x89a1, 0x79a8, 0xd184, 0x1904, 0x368d, 0x0804, - 0x46aa, 0x0126, 0x2091, 0x8000, 0x81ff, 0x0118, 0x2009, 0x0001, - 0x0450, 0x2029, 0x07ff, 0x645c, 0x2400, 0x9506, 0x01f8, 0x2508, - 0x080c, 0x67b4, 0x11d8, 0x080c, 0x6a85, 0x1128, 0x2009, 0x0002, - 0x62c0, 0x2518, 0x00c0, 0x2019, 0x0004, 0x900e, 0x080c, 0x6a12, - 0x1118, 0x2009, 0x0006, 0x0078, 0x7884, 0x908a, 0x1000, 0x1270, - 0x8003, 0x800b, 0x810b, 0x9108, 0x080c, 0x89a1, 0x8529, 0x1ae0, - 0x012e, 0x0804, 0x368d, 0x012e, 0x0804, 0x36bf, 0x012e, 0x0804, - 0x36c2, 0x080c, 0x4c58, 0x0904, 0x36c2, 0x080c, 0x687b, 0x0904, - 0x36bf, 0x080c, 0xacfc, 0xbaa0, 0x2019, 0x0005, 0x00c6, 0x9066, - 0x080c, 0x97b0, 0x0076, 0x903e, 0x080c, 0x966d, 0x900e, 0x080c, - 0xe75d, 0x007e, 0x00ce, 0x080c, 0xad18, 0x080c, 0x69f1, 0x0804, - 0x368d, 0x080c, 0x4c58, 0x0904, 0x36c2, 0x080c, 0x69f1, 0x2208, - 0x0804, 0x368d, 0x0156, 0x00d6, 0x00e6, 0x00c6, 0x2069, 0x1910, - 0x6810, 0x6914, 0x910a, 0x1208, 0x900e, 0x6816, 0x9016, 0x901e, - 0x2071, 0x19e8, 0x7028, 0x9065, 0x0118, 0x8210, 0x600c, 0x0cd8, - 0x2300, 0x9218, 0x00ce, 0x00ee, 0x00de, 0x015e, 0x0804, 0x368d, - 0x00f6, 0x0016, 0x907d, 0x0138, 0x9006, 0x8000, 0x2f0c, 0x81ff, - 0x0110, 0x2178, 0x0cd0, 0x001e, 0x00fe, 0x0005, 0x2069, 0x1910, - 0x6910, 0x62bc, 0x0804, 0x368d, 0x81ff, 0x0120, 0x2009, 0x0001, - 0x0804, 0x36bf, 0x0126, 0x2091, 0x8000, 0x080c, 0x5854, 0x0128, - 0x2009, 0x0007, 0x012e, 0x0804, 0x36bf, 0x012e, 0x615c, 0x9190, - 0x348e, 0x2215, 0x9294, 0x00ff, 0x637c, 0x83ff, 0x0108, 0x6280, - 0x67dc, 0x97c4, 0x000a, 0x98c6, 0x000a, 0x1118, 0x2031, 0x0001, - 0x00e8, 0x97c4, 0x0022, 0x98c6, 0x0022, 0x1118, 0x2031, 0x0003, - 0x00a8, 0x97c4, 0x0012, 0x98c6, 0x0012, 0x1118, 0x2031, 0x0002, - 0x0068, 0x080c, 0x779e, 0x1118, 0x2031, 0x0004, 0x0038, 0xd79c, - 0x0120, 0x2009, 0x0005, 0x0804, 0x36bf, 0x9036, 0x7e9a, 0x7f9e, - 0x0804, 0x368d, 0x614c, 0x6250, 0x2019, 0x1986, 0x231c, 0x2001, - 0x1987, 0x2004, 0x789a, 0x0804, 0x368d, 0x0126, 0x2091, 0x8000, - 0x6138, 0x623c, 0x6340, 0x012e, 0x0804, 0x368d, 0x080c, 0x4c74, - 0x0904, 0x36c2, 0xba44, 0xbb38, 0x0804, 0x368d, 0x080c, 0x0d85, - 0x080c, 0x4c74, 0x2110, 0x0904, 0x36c2, 0xb804, 0x908c, 0x00ff, - 0x918e, 0x0006, 0x0140, 0x9084, 0xff00, 0x9086, 0x0600, 0x2009, - 0x0009, 0x1904, 0x36bf, 0x0126, 0x2091, 0x8000, 0x2019, 0x0005, - 0x00c6, 0x9066, 0x080c, 0xacfc, 0x080c, 0xa7e2, 0x080c, 0x97b0, - 0x0076, 0x903e, 0x080c, 0x966d, 0x900e, 0x080c, 0xe75d, 0x007e, - 0x00ce, 0x080c, 0xad18, 0xb807, 0x0407, 0x012e, 0x0804, 0x368d, - 0x614c, 0x6250, 0x7884, 0x604e, 0x7b88, 0x6352, 0x2069, 0x1847, - 0x831f, 0x9305, 0x6816, 0x788c, 0x2069, 0x1986, 0x2d1c, 0x206a, - 0x7e98, 0x9682, 0x0014, 0x1210, 0x2031, 0x07d0, 0x2069, 0x1987, - 0x2d04, 0x266a, 0x789a, 0x0804, 0x368d, 0x0126, 0x2091, 0x8000, - 0x6138, 0x7884, 0x603a, 0x910e, 0xd1b4, 0x190c, 0x0eeb, 0xd0c4, - 0x01a8, 0x00d6, 0x78a8, 0x2009, 0x199d, 0x200a, 0x78ac, 0x2011, - 0x199e, 0x2012, 0x2069, 0x0100, 0x6838, 0x9086, 0x0007, 0x1118, - 0x2214, 0x6a5a, 0x0010, 0x210c, 0x695a, 0x00de, 0x7888, 0xd0ec, - 0x0178, 0x6034, 0xc08d, 0x6036, 0x2001, 0x0050, 0x6076, 0x607a, - 0x6056, 0x606b, 0x269c, 0x00c6, 0x2061, 0x1b73, 0x2062, 0x00ce, - 0x2011, 0x0116, 0x220c, 0x7888, 0xd08c, 0x0118, 0x918d, 0x0040, - 0x0010, 0x918c, 0xff7f, 0x2112, 0x6134, 0xd18c, 0x2001, 0x0000, - 0x0108, 0x603c, 0x7988, 0x613e, 0x6140, 0x910d, 0x788c, 0x6042, - 0x6234, 0xd28c, 0x0120, 0x7a88, 0x9294, 0x1000, 0x9205, 0x910e, - 0xd1e4, 0x190c, 0x0f06, 0x9084, 0x0020, 0x0130, 0x78b4, 0x6046, - 0x9084, 0x0001, 0x090c, 0x4397, 0x6040, 0xd0cc, 0x0120, 0x78b0, - 0x2011, 0x0114, 0x2012, 0x012e, 0x0804, 0x368d, 0x00f6, 0x2079, - 0x1800, 0x7a38, 0xa898, 0x9084, 0xfebf, 0x9215, 0xa89c, 0x9084, - 0xfebf, 0x8002, 0x9214, 0x7838, 0x9084, 0x0140, 0x9215, 0x7a3a, - 0xa897, 0x4000, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x00fe, - 0x0005, 0x7898, 0x9005, 0x01a8, 0x7888, 0x9025, 0x0904, 0x36c2, - 0x788c, 0x902d, 0x0904, 0x36c2, 0x900e, 0x080c, 0x67b4, 0x1120, - 0xba44, 0xbb38, 0xbc46, 0xbd3a, 0x9186, 0x07ff, 0x0190, 0x8108, - 0x0ca0, 0x080c, 0x4c74, 0x0904, 0x36c2, 0x7888, 0x900d, 0x0904, - 0x36c2, 0x788c, 0x9005, 0x0904, 0x36c2, 0xba44, 0xb946, 0xbb38, - 0xb83a, 0x0804, 0x368d, 0x2011, 0xbc09, 0x0010, 0x2011, 0xbc05, - 0x080c, 0x5854, 0x1904, 0x36bf, 0x00c6, 0x2061, 0x0100, 0x7984, - 0x9186, 0x00ff, 0x1130, 0x2001, 0x1818, 0x2004, 0x9085, 0xff00, - 0x0088, 0x9182, 0x007f, 0x16e0, 0x9188, 0x348e, 0x210d, 0x918c, - 0x00ff, 0x2001, 0x1818, 0x2004, 0x0026, 0x9116, 0x002e, 0x0580, - 0x810f, 0x9105, 0x0126, 0x2091, 0x8000, 0x0006, 0x080c, 0xb116, - 0x000e, 0x0510, 0x602e, 0x620a, 0x7984, 0x00b6, 0x080c, 0x674f, - 0x2b08, 0x00be, 0x1500, 0x6112, 0x6023, 0x0001, 0x080c, 0x4c41, - 0x01d0, 0x9006, 0xa866, 0x7007, 0x0003, 0xa832, 0xa868, 0xc0fd, - 0xa86a, 0x701f, 0x3b9e, 0x2900, 0x6016, 0x2009, 0x0032, 0x080c, - 0xb20a, 0x012e, 0x00ce, 0x0005, 0x012e, 0x00ce, 0x0804, 0x36bf, - 0x00ce, 0x0804, 0x36c2, 0x080c, 0xb16c, 0x0cb0, 0xa830, 0x9086, - 0x0100, 0x0904, 0x36bf, 0x0804, 0x368d, 0x2061, 0x1a73, 0x0126, - 0x2091, 0x8000, 0x6000, 0xd084, 0x0170, 0x6104, 0x6208, 0x2061, - 0x1800, 0x6354, 0x6074, 0x789a, 0x60c0, 0x789e, 0x60bc, 0x78aa, - 0x012e, 0x0804, 0x368d, 0x900e, 0x2110, 0x0c88, 0x81ff, 0x1904, - 0x36bf, 0x080c, 0x779e, 0x0904, 0x36bf, 0x0126, 0x2091, 0x8000, - 0x6254, 0x6074, 0x9202, 0x0248, 0x9085, 0x0001, 0x080c, 0x26f5, - 0x080c, 0x5a7c, 0x012e, 0x0804, 0x368d, 0x012e, 0x0804, 0x36c2, - 0x0006, 0x0016, 0x00c6, 0x00e6, 0x2001, 0x19aa, 0x2070, 0x2061, - 0x1847, 0x6008, 0x2072, 0x900e, 0x2011, 0x1400, 0x080c, 0x955b, - 0x7206, 0x00ee, 0x00ce, 0x001e, 0x000e, 0x0005, 0x0126, 0x2091, - 0x8000, 0x81ff, 0x0128, 0x012e, 0x2021, 0x400b, 0x0804, 0x368f, - 0x7884, 0xd0fc, 0x0158, 0x2001, 0x002a, 0x2004, 0x9005, 0x0180, - 0x9082, 0x00e1, 0x0298, 0x012e, 0x0804, 0x36c2, 0x2001, 0x002a, - 0x2004, 0x9005, 0x0128, 0x2069, 0x1847, 0x6908, 0x9102, 0x1230, - 0x012e, 0x0804, 0x36c2, 0x012e, 0x0804, 0x36bf, 0x080c, 0xb094, - 0x0dd0, 0x7884, 0xd0fc, 0x0904, 0x3c6d, 0x00c6, 0x080c, 0x4c41, - 0x00ce, 0x0d88, 0xa867, 0x0000, 0x7884, 0xa80a, 0x7898, 0xa80e, - 0x789c, 0xa812, 0x2001, 0x002e, 0x2004, 0xa81a, 0x2001, 0x002f, - 0x2004, 0xa81e, 0x2001, 0x0030, 0x2004, 0xa822, 0x2001, 0x0031, - 0x2004, 0xa826, 0x2001, 0x0034, 0x2004, 0xa82a, 0x2001, 0x0035, - 0x2004, 0xa82e, 0x2001, 0x002a, 0x2004, 0x9080, 0x0003, 0x9084, - 0x00fc, 0x8004, 0xa816, 0x080c, 0x3df7, 0x0928, 0x7014, 0x2048, - 0xad2c, 0xac28, 0xab1c, 0xaa18, 0xa930, 0xa808, 0xd0b4, 0x1120, - 0x2029, 0x0000, 0x2021, 0x0000, 0x8906, 0x8006, 0x8007, 0x90bc, - 0x003f, 0x9084, 0xffc0, 0x9080, 0x001b, 0x080c, 0x4c8a, 0x701f, - 0x3d34, 0x7023, 0x0001, 0x012e, 0x0005, 0x080c, 0xacfc, 0x0046, - 0x0086, 0x0096, 0x00a6, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, - 0x080c, 0x3bd8, 0x2001, 0x19a0, 0x2003, 0x0000, 0x2021, 0x000a, - 0x2061, 0x0100, 0x6104, 0x0016, 0x60bb, 0x0000, 0x60bf, 0x32e1, - 0x60bf, 0x0012, 0x080c, 0x3e66, 0x080c, 0x3e25, 0x00f6, 0x00e6, - 0x0086, 0x2940, 0x2071, 0x19e8, 0x2079, 0x0090, 0x00d6, 0x2069, - 0x0000, 0x6884, 0xd0b4, 0x0140, 0x2001, 0x0035, 0x2004, 0x780e, - 0x2001, 0x0034, 0x2004, 0x780a, 0x00de, 0x2011, 0x0001, 0x080c, - 0x41db, 0x008e, 0x00ee, 0x00fe, 0x080c, 0x40fd, 0x080c, 0x402a, - 0x05b8, 0x2001, 0x020b, 0x2004, 0x9084, 0x0140, 0x1db8, 0x080c, - 0x424f, 0x00f6, 0x2079, 0x0300, 0x78bc, 0x00fe, 0x908c, 0x0070, - 0x1560, 0x2071, 0x0200, 0x7037, 0x0000, 0x7050, 0x9084, 0xff00, - 0x9086, 0x3200, 0x1510, 0x7037, 0x0001, 0x7050, 0x9084, 0xff00, - 0x9086, 0xe100, 0x11d0, 0x7037, 0x0000, 0x7054, 0x7037, 0x0000, - 0x715c, 0x9106, 0x1190, 0x2001, 0x1820, 0x2004, 0x9106, 0x1168, - 0x00c6, 0x2061, 0x0100, 0x6024, 0x9084, 0x1e00, 0x00ce, 0x0138, - 0x080c, 0x4034, 0x080c, 0x3e20, 0x0058, 0x080c, 0x3e20, 0x080c, - 0x4173, 0x080c, 0x40f3, 0x2001, 0x020b, 0x2004, 0xd0e4, 0x0dd8, - 0x2001, 0x032a, 0x2003, 0x0004, 0x2061, 0x0100, 0x6027, 0x0002, - 0x001e, 0x6106, 0x2011, 0x020d, 0x2013, 0x0020, 0x60bb, 0x0000, - 0x60bf, 0x0108, 0x60bf, 0x0012, 0x2001, 0x0004, 0x200c, 0x918c, - 0xfffd, 0x2102, 0x080c, 0x1352, 0x2009, 0x0028, 0x080c, 0x2220, - 0x2001, 0x0227, 0x200c, 0x2102, 0x080c, 0xad18, 0x00fe, 0x00ee, - 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e, 0x008e, 0x004e, 0x2001, - 0x19a0, 0x2004, 0x9005, 0x1118, 0x012e, 0x0804, 0x368d, 0x012e, - 0x2021, 0x400c, 0x0804, 0x368f, 0x0016, 0x0026, 0x0036, 0x0046, - 0x0056, 0x0076, 0x0086, 0x0096, 0x00d6, 0x0156, 0x7014, 0x2048, - 0x7020, 0x20a8, 0x8000, 0x7022, 0xa804, 0x9005, 0x0904, 0x3d90, - 0x2048, 0x1f04, 0x3d44, 0x7068, 0x2040, 0xa28c, 0xa390, 0xa494, - 0xa598, 0xa930, 0xa808, 0xd0b4, 0x1120, 0x2029, 0x0000, 0x2021, - 0x0000, 0x0096, 0x7014, 0x2048, 0xa864, 0x009e, 0x9086, 0x0103, - 0x0170, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, - 0x9080, 0x001b, 0x080c, 0x4c8a, 0x701f, 0x3d34, 0x00b0, 0x8906, - 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x001b, - 0x21a8, 0x27e0, 0x2098, 0x27e8, 0x20a0, 0x0006, 0x080c, 0x0fd6, - 0x000e, 0x080c, 0x4c8d, 0x701f, 0x3d34, 0x015e, 0x00de, 0x009e, - 0x008e, 0x007e, 0x005e, 0x004e, 0x003e, 0x002e, 0x001e, 0x0005, - 0x7014, 0x2048, 0xa864, 0x9086, 0x0103, 0x1118, 0x701f, 0x3df5, - 0x0450, 0x7014, 0x2048, 0xa868, 0xc0fd, 0xa86a, 0x2009, 0x007f, - 0x080c, 0x6749, 0x0110, 0x9006, 0x0030, 0xb813, 0x00ff, 0xb817, - 0xfffd, 0x080c, 0xd409, 0x015e, 0x00de, 0x009e, 0x008e, 0x007e, - 0x005e, 0x004e, 0x003e, 0x002e, 0x001e, 0x0904, 0x36bf, 0x0016, - 0x0026, 0x0036, 0x0046, 0x0056, 0x0076, 0x0086, 0x0096, 0x00d6, - 0x0156, 0x701f, 0x3dc7, 0x7007, 0x0003, 0x0804, 0x3d85, 0xa830, - 0x9086, 0x0100, 0x2021, 0x400c, 0x0904, 0x368f, 0x0076, 0xad10, - 0xac0c, 0xab24, 0xaa20, 0xa930, 0xa808, 0xd0b4, 0x1120, 0x2029, - 0x0000, 0x2021, 0x0000, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, - 0x9084, 0xffc0, 0x9080, 0x001b, 0x21a8, 0x27e0, 0x2098, 0x27e8, - 0x20a0, 0x0006, 0x080c, 0x0fd6, 0x000e, 0x080c, 0x4c8d, 0x007e, - 0x701f, 0x3d34, 0x7023, 0x0001, 0x0005, 0x0804, 0x368d, 0x0156, - 0x00c6, 0xa814, 0x908a, 0x001e, 0x0218, 0xa833, 0x001e, 0x0010, - 0xa832, 0x0078, 0x81ff, 0x0168, 0x0016, 0x080c, 0x4c41, 0x001e, - 0x0130, 0xa800, 0x2040, 0xa008, 0xa80a, 0x2100, 0x0c58, 0x9006, - 0x0010, 0x9085, 0x0001, 0x00ce, 0x015e, 0x0005, 0x0006, 0x00f6, - 0x2079, 0x0000, 0x7880, 0x9086, 0x0044, 0x00fe, 0x000e, 0x0005, - 0x2001, 0x19a0, 0x2003, 0x0001, 0x0005, 0x00f6, 0x00e6, 0x00c6, - 0x2061, 0x0200, 0x2001, 0x19ab, 0x2004, 0x601a, 0x2061, 0x0100, - 0x2001, 0x19aa, 0x2004, 0x60ce, 0x6104, 0xc1ac, 0x6106, 0x080c, - 0x4c41, 0xa813, 0x0019, 0xa817, 0x0001, 0x2900, 0xa85a, 0x2001, - 0x002e, 0x2004, 0xa866, 0x2001, 0x002f, 0x2004, 0xa86a, 0x2061, - 0x0090, 0x2079, 0x0100, 0x2001, 0x19aa, 0x2004, 0x6036, 0x2009, - 0x0040, 0x080c, 0x2220, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, - 0xa86e, 0x601a, 0xa873, 0x0000, 0x601f, 0x0000, 0x78ca, 0x9006, - 0x600a, 0x600e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00e6, 0x080c, - 0x4c41, 0x2940, 0xa013, 0x0019, 0xa017, 0x0001, 0x2800, 0xa05a, - 0x2001, 0x0030, 0x2004, 0xa866, 0x2001, 0x0031, 0x2004, 0xa86a, - 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, 0xa86e, 0xa873, 0x0000, - 0x2001, 0x032a, 0x2003, 0x0004, 0x2001, 0x0300, 0x2003, 0x0000, - 0x2001, 0x020d, 0x2003, 0x0000, 0x2001, 0x0004, 0x200c, 0x918d, - 0x0002, 0x2102, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x81ff, - 0x0148, 0x080c, 0x2a77, 0x1130, 0x9006, 0x080c, 0x29ca, 0x9006, - 0x080c, 0x29ad, 0x2001, 0x199f, 0x2003, 0x0000, 0x7884, 0x9084, - 0x0007, 0x0002, 0x3eb5, 0x3eb6, 0x3eb7, 0x3eb2, 0x3eb2, 0x3eb2, - 0x3eb2, 0x3eb2, 0x012e, 0x0804, 0x36c2, 0x0ce0, 0x0cd8, 0x080c, - 0x779e, 0x1128, 0x012e, 0x2009, 0x0016, 0x0804, 0x36bf, 0x81ff, - 0x0128, 0x012e, 0x2021, 0x400b, 0x0804, 0x368f, 0x2001, 0x0141, - 0x2004, 0xd0dc, 0x0db0, 0x080c, 0xacfc, 0x0086, 0x0096, 0x00a6, - 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x080c, 0x3bd8, 0x2009, - 0x0101, 0x210c, 0x0016, 0x7ec8, 0x7dcc, 0x9006, 0x2068, 0x2060, - 0x2058, 0x080c, 0x432a, 0x080c, 0x427a, 0x903e, 0x2720, 0x00f6, - 0x00e6, 0x0086, 0x2940, 0x2071, 0x19e8, 0x2079, 0x0090, 0x00d6, - 0x2069, 0x0000, 0x6884, 0xd0b4, 0x0120, 0x68d4, 0x780e, 0x68d0, - 0x780a, 0x00de, 0x2011, 0x0001, 0x080c, 0x41db, 0x080c, 0x2a7f, - 0x080c, 0x2a7f, 0x080c, 0x2a7f, 0x080c, 0x2a7f, 0x080c, 0x41db, - 0x008e, 0x00ee, 0x00fe, 0x080c, 0x40fd, 0x2009, 0x9c40, 0x8109, - 0x11b0, 0x080c, 0x4034, 0x2001, 0x0004, 0x200c, 0x918c, 0xfffd, - 0x2102, 0x001e, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x00ae, - 0x009e, 0x008e, 0x2009, 0x0017, 0x080c, 0x36bf, 0x0cf8, 0x2001, - 0x020b, 0x2004, 0x9084, 0x0140, 0x1d10, 0x00f6, 0x2079, 0x0000, - 0x7884, 0x00fe, 0xd0bc, 0x0178, 0x2001, 0x0201, 0x200c, 0x81ff, - 0x0150, 0x080c, 0x40db, 0x2d00, 0x9c05, 0x9b05, 0x0120, 0x080c, - 0x4034, 0x0804, 0x3fdd, 0x080c, 0x424f, 0x080c, 0x4173, 0x080c, - 0x40be, 0x080c, 0x40f3, 0x00f6, 0x2079, 0x0100, 0x7824, 0xd0ac, - 0x0130, 0x8b58, 0x080c, 0x4034, 0x00fe, 0x0804, 0x3fdd, 0x00fe, - 0x080c, 0x402a, 0x1150, 0x8d68, 0x2001, 0x0032, 0x2602, 0x2001, - 0x0033, 0x2502, 0x080c, 0x4034, 0x0080, 0x87ff, 0x0138, 0x2001, - 0x0201, 0x2004, 0x9005, 0x1908, 0x8739, 0x0038, 0x2001, 0x1a6e, - 0x2004, 0x9086, 0x0000, 0x1904, 0x3f2d, 0x2001, 0x032f, 0x2003, - 0x00f6, 0x8631, 0x1208, 0x8529, 0x2500, 0x9605, 0x0904, 0x3fdd, - 0x7884, 0xd0bc, 0x0128, 0x2d00, 0x9c05, 0x9b05, 0x1904, 0x3fdd, - 0xa013, 0x0019, 0x2001, 0x032a, 0x2003, 0x0004, 0x7884, 0xd0ac, - 0x1148, 0x2001, 0x1a6e, 0x2003, 0x0003, 0x2001, 0x032a, 0x2003, - 0x0009, 0x0030, 0xa017, 0x0001, 0x78b4, 0x9005, 0x0108, 0xa016, - 0x2800, 0xa05a, 0x2009, 0x0040, 0x080c, 0x2220, 0x2900, 0xa85a, - 0xa813, 0x0019, 0x7884, 0xd0a4, 0x1180, 0xa817, 0x0000, 0x00c6, - 0x20a9, 0x0004, 0x2061, 0x0090, 0x602b, 0x0008, 0x2001, 0x0203, - 0x2004, 0x1f04, 0x3fb4, 0x00ce, 0x0030, 0xa817, 0x0001, 0x78b0, - 0x9005, 0x0108, 0xa816, 0x00f6, 0x00c6, 0x2079, 0x0100, 0x2061, - 0x0090, 0x7827, 0x0002, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, - 0x601a, 0x0006, 0x2001, 0x002b, 0x2004, 0x601e, 0x78c6, 0x000e, - 0x78ca, 0x00ce, 0x00fe, 0x0804, 0x3ee7, 0x001e, 0x00c6, 0x2001, - 0x032a, 0x2003, 0x0004, 0x2061, 0x0100, 0x6027, 0x0002, 0x6106, - 0x2011, 0x020d, 0x2013, 0x0020, 0x2001, 0x0004, 0x200c, 0x918c, - 0xfffd, 0x2102, 0x080c, 0x1352, 0x7884, 0x9084, 0x0003, 0x9086, - 0x0002, 0x01b0, 0x2009, 0x0028, 0x080c, 0x2220, 0x2001, 0x0227, - 0x200c, 0x2102, 0x6050, 0x9084, 0xb7ff, 0x080c, 0x2b29, 0x6052, - 0x602f, 0x0000, 0x604b, 0xf7f7, 0x6043, 0x0090, 0x6043, 0x0010, - 0x080c, 0xad18, 0x00ce, 0x2d08, 0x2c10, 0x2b18, 0x2b00, 0x9c05, - 0x9d05, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e, - 0x008e, 0x1118, 0x012e, 0x0804, 0x368d, 0x012e, 0x2021, 0x400c, - 0x0804, 0x368f, 0x9085, 0x0001, 0x1d04, 0x4033, 0x2091, 0x6000, - 0x8420, 0x9486, 0x0064, 0x0005, 0x2001, 0x0105, 0x2003, 0x0010, - 0x2001, 0x032a, 0x2003, 0x0004, 0x2001, 0x1a6e, 0x2003, 0x0000, - 0x0071, 0x2009, 0x0048, 0x080c, 0x2220, 0x2001, 0x0227, 0x2024, - 0x2402, 0x2001, 0x0109, 0x2003, 0x4000, 0x9026, 0x0005, 0x00f6, - 0x00e6, 0x2071, 0x19e8, 0x7054, 0x9086, 0x0000, 0x0520, 0x2079, - 0x0090, 0x2009, 0x0206, 0x2104, 0x2009, 0x0203, 0x210c, 0x9106, - 0x1120, 0x2009, 0x0040, 0x080c, 0x2220, 0x782c, 0xd0fc, 0x0d88, - 0x080c, 0x424f, 0x7054, 0x9086, 0x0000, 0x1d58, 0x782b, 0x0004, - 0x782c, 0xd0ac, 0x1de8, 0x2009, 0x0040, 0x080c, 0x2220, 0x782b, - 0x0002, 0x7057, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x2079, - 0x0100, 0x2001, 0x1818, 0x200c, 0x7932, 0x7936, 0x080c, 0x26d5, - 0x080c, 0x2af6, 0x080c, 0x2b29, 0x784b, 0xf7f7, 0x7843, 0x0090, - 0x7843, 0x0010, 0x7850, 0xc0e5, 0x7852, 0x2019, 0x61a8, 0x7820, - 0xd09c, 0x0110, 0x8319, 0x1dd8, 0x7850, 0xc0e4, 0x7852, 0x2011, - 0x0048, 0x080c, 0x2ad3, 0x7843, 0x0040, 0x2019, 0x01f4, 0xa001, - 0xa001, 0x8319, 0x1de0, 0x2001, 0x0100, 0x080c, 0x2a99, 0x2011, - 0x0020, 0x080c, 0x2ad3, 0x7843, 0x0000, 0x9006, 0x080c, 0x2a99, - 0x2011, 0x0048, 0x080c, 0x2ad3, 0x00fe, 0x0005, 0x7884, 0xd0ac, - 0x11c8, 0x00f6, 0x00e6, 0x2071, 0x1a6e, 0x2079, 0x0320, 0x2001, - 0x0201, 0x2004, 0x9005, 0x0160, 0x7000, 0x9086, 0x0000, 0x1140, - 0x0051, 0xd0bc, 0x0108, 0x8738, 0x7003, 0x0003, 0x782b, 0x0019, - 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0300, 0x78bc, 0x00fe, - 0x908c, 0x0070, 0x0178, 0x2009, 0x0032, 0x260a, 0x2009, 0x0033, - 0x250a, 0xd0b4, 0x0108, 0x8c60, 0xd0ac, 0x0108, 0x8d68, 0xd0a4, - 0x0108, 0x8b58, 0x0005, 0x00f6, 0x2079, 0x0200, 0x781c, 0xd084, - 0x0110, 0x7837, 0x0050, 0x00fe, 0x0005, 0x00e6, 0x2071, 0x0100, - 0x2001, 0x19ab, 0x2004, 0x70e2, 0x080c, 0x3e16, 0x1188, 0x2001, - 0x1820, 0x2004, 0x2009, 0x181f, 0x210c, 0x918c, 0x00ff, 0x706e, - 0x716a, 0x7066, 0x918d, 0x3200, 0x7162, 0x7073, 0xe109, 0x0080, - 0x702c, 0x9085, 0x0002, 0x702e, 0x2009, 0x1818, 0x210c, 0x716e, - 0x7063, 0x0100, 0x7166, 0x719e, 0x706b, 0x0000, 0x7073, 0x0809, - 0x7077, 0x0008, 0x7078, 0x9080, 0x0100, 0x707a, 0x7080, 0x8000, - 0x7082, 0x7087, 0xaaaa, 0x9006, 0x708a, 0x708e, 0x707e, 0x70d6, - 0x70ab, 0x0036, 0x70af, 0x95d5, 0x7014, 0x9084, 0x1984, 0x9085, - 0x0092, 0x7016, 0x080c, 0x424f, 0x00f6, 0x2071, 0x1a6e, 0x2079, - 0x0320, 0x00d6, 0x2069, 0x0000, 0x6884, 0xd0b4, 0x0120, 0x689c, - 0x780e, 0x6898, 0x780a, 0x00de, 0x080c, 0x3e16, 0x0140, 0x2001, - 0x199f, 0x200c, 0x2003, 0x0001, 0x918e, 0x0001, 0x0120, 0x2009, - 0x03e8, 0x8109, 0x1df0, 0x792c, 0xd1fc, 0x0110, 0x782b, 0x0004, - 0x2011, 0x0011, 0x080c, 0x41db, 0x2011, 0x0001, 0x080c, 0x41db, - 0x00fe, 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x2071, 0x1a6e, 0x2079, - 0x0320, 0x792c, 0xd1fc, 0x0904, 0x41d8, 0x782b, 0x0002, 0x9026, - 0xd19c, 0x1904, 0x41d4, 0x7000, 0x0002, 0x41d8, 0x4189, 0x41b9, - 0x41d4, 0xd1bc, 0x1170, 0xd1dc, 0x1190, 0x8001, 0x7002, 0x2011, - 0x0001, 0x080c, 0x41db, 0x0904, 0x41d8, 0x080c, 0x41db, 0x0804, - 0x41d8, 0x00f6, 0x2079, 0x0300, 0x78bf, 0x0000, 0x00fe, 0x7810, - 0x7914, 0x782b, 0x0004, 0x7812, 0x7916, 0x2001, 0x0201, 0x200c, - 0x81ff, 0x0de8, 0x080c, 0x40db, 0x2009, 0x0001, 0x00f6, 0x2079, - 0x0300, 0x78b8, 0x00fe, 0xd0ec, 0x0110, 0x2009, 0x0011, 0x792a, - 0x00f8, 0x8001, 0x7002, 0x9184, 0x0880, 0x1140, 0x782c, 0xd0fc, - 0x1904, 0x417d, 0x2011, 0x0001, 0x00b1, 0x0090, 0xa010, 0x9092, - 0x0004, 0x9086, 0x0015, 0x1120, 0xa000, 0xa05a, 0x2011, 0x0031, - 0xa212, 0xd1dc, 0x1960, 0x0828, 0x782b, 0x0004, 0x7003, 0x0000, - 0x00ee, 0x00fe, 0x0005, 0xa014, 0x9005, 0x0550, 0x8001, 0x0036, - 0x0096, 0xa016, 0xa058, 0x2048, 0xa010, 0x2009, 0x0031, 0x911a, - 0x831c, 0x831c, 0x938a, 0x0007, 0x1a0c, 0x0d85, 0x9398, 0x4209, - 0x231d, 0x083f, 0x9080, 0x0004, 0x7a2a, 0x7100, 0x8108, 0x7102, - 0x009e, 0x003e, 0x908a, 0x0035, 0x1140, 0x0096, 0xa058, 0x2048, - 0xa804, 0xa05a, 0x2001, 0x0019, 0x009e, 0xa012, 0x9085, 0x0001, - 0x0005, 0x4246, 0x423d, 0x4234, 0x422b, 0x4222, 0x4219, 0x4210, - 0xa964, 0x7902, 0xa968, 0x7906, 0xa96c, 0x7912, 0xa970, 0x7916, - 0x0005, 0xa974, 0x7902, 0xa978, 0x7906, 0xa97c, 0x7912, 0xa980, - 0x7916, 0x0005, 0xa984, 0x7902, 0xa988, 0x7906, 0xa98c, 0x7912, - 0xa990, 0x7916, 0x0005, 0xa994, 0x7902, 0xa998, 0x7906, 0xa99c, - 0x7912, 0xa9a0, 0x7916, 0x0005, 0xa9a4, 0x7902, 0xa9a8, 0x7906, - 0xa9ac, 0x7912, 0xa9b0, 0x7916, 0x0005, 0xa9b4, 0x7902, 0xa9b8, - 0x7906, 0xa9bc, 0x7912, 0xa9c0, 0x7916, 0x0005, 0xa9c4, 0x7902, - 0xa9c8, 0x7906, 0xa9cc, 0x7912, 0xa9d0, 0x7916, 0x0005, 0x00f6, - 0x00e6, 0x0086, 0x2071, 0x19e8, 0x2079, 0x0090, 0x792c, 0xd1fc, - 0x01e8, 0x782b, 0x0002, 0x2940, 0x9026, 0x7054, 0x0002, 0x4276, - 0x4262, 0x426d, 0x8001, 0x7056, 0xd19c, 0x1180, 0x2011, 0x0001, - 0x080c, 0x41db, 0x190c, 0x41db, 0x0048, 0x8001, 0x7056, 0x782c, - 0xd0fc, 0x1d38, 0x2011, 0x0001, 0x080c, 0x41db, 0x008e, 0x00ee, - 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0086, 0x2061, 0x0200, - 0x2001, 0x19ab, 0x2004, 0x601a, 0x2061, 0x0100, 0x2001, 0x19aa, - 0x2004, 0x60ce, 0x6104, 0xc1ac, 0x6106, 0x2001, 0x002c, 0x2004, - 0x9005, 0x0520, 0x2038, 0x2001, 0x002e, 0x2024, 0x2001, 0x002f, - 0x201c, 0x080c, 0x4c41, 0xa813, 0x0019, 0xaf16, 0x2900, 0xa85a, - 0x978a, 0x0007, 0x0220, 0x2138, 0x2009, 0x0007, 0x0010, 0x2708, - 0x903e, 0x0096, 0xa858, 0x2048, 0xa85c, 0x9080, 0x0019, 0x009e, - 0x080c, 0x42f2, 0x1d68, 0x2900, 0xa85a, 0x00d0, 0x080c, 0x4c41, - 0xa813, 0x0019, 0xa817, 0x0001, 0x2900, 0xa85a, 0x2001, 0x002e, - 0x2004, 0xa866, 0x2001, 0x002f, 0x2004, 0xa86a, 0x2001, 0x002a, - 0x2004, 0x9084, 0xfff8, 0xa86e, 0x2001, 0x002b, 0x2004, 0xa872, - 0x2061, 0x0090, 0x2079, 0x0100, 0x2001, 0x19aa, 0x2004, 0x6036, - 0x2009, 0x0040, 0x080c, 0x2220, 0x2001, 0x002a, 0x2004, 0x9084, - 0xfff8, 0x601a, 0x0006, 0x2001, 0x002b, 0x2004, 0x601e, 0x78c6, - 0x000e, 0x78ca, 0x9006, 0x600a, 0x600e, 0x008e, 0x00ce, 0x00ee, - 0x00fe, 0x0005, 0x00e6, 0x2071, 0x0080, 0xaa60, 0x22e8, 0x20a0, - 0x20e1, 0x0000, 0x2099, 0x0088, 0x702b, 0x0026, 0x7402, 0x7306, - 0x9006, 0x700a, 0x700e, 0x810b, 0x810b, 0x21a8, 0x810b, 0x7112, - 0x702b, 0x0041, 0x702c, 0xd0fc, 0x0de8, 0x702b, 0x0002, 0x702b, - 0x0040, 0x4005, 0x7400, 0x7304, 0x87ff, 0x0190, 0x0086, 0x0096, - 0x2940, 0x0086, 0x080c, 0x4c41, 0x008e, 0xa058, 0x00a6, 0x2050, - 0x2900, 0xb006, 0xa05a, 0x00ae, 0x009e, 0x008e, 0x9085, 0x0001, - 0x00ee, 0x0005, 0x00e6, 0x2001, 0x002d, 0x2004, 0x9005, 0x0528, - 0x2038, 0x2001, 0x0030, 0x2024, 0x2001, 0x0031, 0x201c, 0x080c, - 0x4c41, 0x2940, 0xa813, 0x0019, 0xaf16, 0x2900, 0xa85a, 0x978a, - 0x0007, 0x0220, 0x2138, 0x2009, 0x0007, 0x0010, 0x2708, 0x903e, - 0x0096, 0xa858, 0x2048, 0xa85c, 0x9080, 0x0019, 0x009e, 0x080c, - 0x42f2, 0x1d68, 0x2900, 0xa85a, 0x00d8, 0x080c, 0x4c41, 0x2940, - 0xa013, 0x0019, 0xa017, 0x0001, 0x2800, 0xa05a, 0x2001, 0x0030, - 0x2004, 0xa066, 0x2001, 0x0031, 0x2004, 0xa06a, 0x2001, 0x002a, - 0x2004, 0x9084, 0xfff8, 0xa06e, 0x2001, 0x002b, 0x2004, 0xa072, - 0x2001, 0x032a, 0x2003, 0x0004, 0x7884, 0xd0ac, 0x1180, 0x2001, - 0x0101, 0x200c, 0x918d, 0x0200, 0x2102, 0xa017, 0x0000, 0x2001, - 0x1a6e, 0x2003, 0x0003, 0x2001, 0x032a, 0x2003, 0x0009, 0x2001, - 0x0300, 0x2003, 0x0000, 0x2001, 0x020d, 0x2003, 0x0000, 0x2001, - 0x0004, 0x200c, 0x918d, 0x0002, 0x2102, 0x00ee, 0x0005, 0x0126, - 0x2091, 0x8000, 0x20a9, 0x0007, 0x20a1, 0x1840, 0x20e9, 0x0001, - 0x9006, 0x4004, 0x20a9, 0x0014, 0x20a1, 0xffec, 0x20e9, 0x0000, - 0x9006, 0x4004, 0x2009, 0x013c, 0x200a, 0x012e, 0x7880, 0x9086, - 0x0052, 0x0108, 0x0005, 0x0804, 0x368d, 0x7d98, 0x7c9c, 0x0804, - 0x3791, 0x080c, 0x779e, 0x190c, 0x6162, 0x6040, 0x9084, 0x0020, - 0x09b1, 0x2069, 0x1847, 0x2d00, 0x2009, 0x0030, 0x7a8c, 0x7b88, - 0x7c9c, 0x7d98, 0x2039, 0x0001, 0x080c, 0x4c8a, 0x701f, 0x43d1, - 0x0005, 0x080c, 0x584f, 0x1130, 0x3b00, 0x3a08, 0xc194, 0xc095, - 0x20d8, 0x21d0, 0x2069, 0x1847, 0x6800, 0x9005, 0x0904, 0x36c2, - 0x2001, 0x180d, 0x2004, 0xd08c, 0x6804, 0x0118, 0xc0a4, 0xc0ac, - 0x6806, 0xd0ac, 0x0118, 0xd0a4, 0x0904, 0x36c2, 0xd094, 0x00c6, - 0x2061, 0x0100, 0x6104, 0x0138, 0x6200, 0x9292, 0x0005, 0x0218, - 0x918c, 0xffdf, 0x0010, 0x918d, 0x0020, 0x6106, 0x00ce, 0xd08c, - 0x00c6, 0x2061, 0x0100, 0x6104, 0x0118, 0x918d, 0x0010, 0x0010, - 0x918c, 0xffef, 0x6106, 0x00ce, 0xd084, 0x0158, 0x6a28, 0x928a, - 0x007f, 0x1a04, 0x36c2, 0x9288, 0x348e, 0x210d, 0x918c, 0x00ff, - 0x6166, 0xd0dc, 0x0130, 0x6828, 0x908a, 0x007f, 0x1a04, 0x36c2, - 0x605e, 0x6888, 0x9084, 0x0030, 0x8004, 0x8004, 0x8004, 0x8004, - 0x0006, 0x2009, 0x19b2, 0x9080, 0x27d0, 0x2005, 0x200a, 0x2008, - 0x2001, 0x0018, 0x080c, 0xaced, 0x2009, 0x0390, 0x200b, 0x0400, - 0x000e, 0x2009, 0x19b3, 0x9080, 0x27d4, 0x2005, 0x200a, 0x6808, - 0x908a, 0x0100, 0x0a04, 0x36c2, 0x908a, 0x0841, 0x1a04, 0x36c2, - 0x9084, 0x0007, 0x1904, 0x36c2, 0x680c, 0x9005, 0x0904, 0x36c2, - 0x6810, 0x9005, 0x0904, 0x36c2, 0x6848, 0x6940, 0x910a, 0x1a04, - 0x36c2, 0x8001, 0x0904, 0x36c2, 0x684c, 0x6944, 0x910a, 0x1a04, - 0x36c2, 0x8001, 0x0904, 0x36c2, 0x6814, 0x908c, 0x00ff, 0x614e, - 0x8007, 0x9084, 0x00ff, 0x6052, 0x080c, 0x7ae7, 0x080c, 0x6cfc, - 0x080c, 0x6d66, 0x6808, 0x602a, 0x080c, 0x2192, 0x2009, 0x0170, - 0x200b, 0x0080, 0xa001, 0xa001, 0x200b, 0x0000, 0x0036, 0x6b08, - 0x080c, 0x272f, 0x003e, 0x6000, 0x9086, 0x0000, 0x1904, 0x456d, - 0x6818, 0x691c, 0x6a20, 0x6b24, 0x8007, 0x810f, 0x8217, 0x831f, - 0x6016, 0x611a, 0x621e, 0x6322, 0x6c04, 0xd4f4, 0x0148, 0x6830, - 0x6934, 0x6a38, 0x6b3c, 0x8007, 0x810f, 0x8217, 0x831f, 0x0010, - 0x9084, 0xf0ff, 0x6006, 0x610a, 0x620e, 0x6312, 0x8007, 0x810f, - 0x8217, 0x831f, 0x20a9, 0x0004, 0x20a1, 0x19b4, 0x20e9, 0x0001, - 0x4001, 0x20a9, 0x0004, 0x20a1, 0x19ce, 0x20e9, 0x0001, 0x4001, - 0x080c, 0x8b26, 0x00c6, 0x900e, 0x20a9, 0x0001, 0x6b70, 0xd384, - 0x01c8, 0x0020, 0x839d, 0x12b0, 0x3508, 0x8109, 0x080c, 0x80fe, - 0x6878, 0x6016, 0x6874, 0x2008, 0x9084, 0xff00, 0x8007, 0x600a, - 0x9184, 0x00ff, 0x6006, 0x8108, 0x1118, 0x6003, 0x0003, 0x0010, - 0x6003, 0x0001, 0x1f04, 0x44c2, 0x00ce, 0x00c6, 0x2061, 0x199c, - 0x2001, 0x180d, 0x2004, 0xd08c, 0x11a8, 0x6a88, 0x9284, 0xc000, - 0x2010, 0x9286, 0x0000, 0x1158, 0x2063, 0x0000, 0x2001, 0x0001, - 0x080c, 0x29ca, 0x2001, 0x0001, 0x080c, 0x29ad, 0x0088, 0x9286, - 0x4000, 0x1148, 0x2063, 0x0001, 0x9006, 0x080c, 0x29ca, 0x9006, - 0x080c, 0x29ad, 0x0028, 0x9286, 0x8000, 0x1d30, 0x2063, 0x0002, - 0x00ce, 0x00e6, 0x2c70, 0x080c, 0x0ed3, 0x00ee, 0x080c, 0x2af6, - 0x080c, 0x2b29, 0x6888, 0xd0ec, 0x0130, 0x2011, 0x0114, 0x2204, - 0x9085, 0x0180, 0x2012, 0x6a80, 0x9284, 0x0030, 0x9086, 0x0030, - 0x1128, 0x9294, 0xffcf, 0x9295, 0x0020, 0x6a82, 0x2001, 0x197c, - 0x6a80, 0x9294, 0x0030, 0x928e, 0x0000, 0x0170, 0x928e, 0x0010, - 0x0118, 0x928e, 0x0020, 0x0140, 0x2003, 0xaaaa, 0x080c, 0x27a4, - 0x2001, 0x196d, 0x2102, 0x0008, 0x2102, 0x00c6, 0x2061, 0x0100, - 0x602f, 0x0040, 0x602f, 0x0000, 0x00ce, 0x080c, 0x779e, 0x0128, - 0x080c, 0x5128, 0x0110, 0x080c, 0x26f5, 0x60d4, 0x9005, 0x01c0, - 0x6003, 0x0001, 0x2009, 0x4555, 0x00e0, 0x080c, 0x779e, 0x1168, - 0x2011, 0x7612, 0x080c, 0x8993, 0x2011, 0x7605, 0x080c, 0x8a9f, - 0x080c, 0x7abb, 0x080c, 0x76cd, 0x0040, 0x080c, 0x6058, 0x0028, - 0x6003, 0x0004, 0x2009, 0x456d, 0x0020, 0x080c, 0x6b73, 0x0804, - 0x368d, 0x2001, 0x0170, 0x2004, 0x9084, 0x00ff, 0x9086, 0x004c, - 0x1118, 0x2091, 0x31bd, 0x0817, 0x2091, 0x313d, 0x0817, 0x6000, - 0x9086, 0x0000, 0x0904, 0x36bf, 0x2069, 0x1847, 0x7890, 0x6842, - 0x7894, 0x6846, 0x2d00, 0x2009, 0x0030, 0x7a8c, 0x7b88, 0x7c9c, - 0x7d98, 0x2039, 0x0001, 0x0804, 0x4c8d, 0x9006, 0x080c, 0x26f5, - 0x81ff, 0x1904, 0x36bf, 0x080c, 0x779e, 0x11b0, 0x080c, 0x7ab6, - 0x080c, 0x619d, 0x080c, 0x3482, 0x0118, 0x6130, 0xc18d, 0x6132, - 0x080c, 0xd645, 0x0130, 0x080c, 0x77c1, 0x1118, 0x080c, 0x7772, - 0x0038, 0x080c, 0x76cd, 0x0020, 0x080c, 0x6162, 0x080c, 0x6058, - 0x0804, 0x368d, 0x81ff, 0x1904, 0x36bf, 0x080c, 0x779e, 0x1110, - 0x0804, 0x36bf, 0x0126, 0x2091, 0x8000, 0x6194, 0x81ff, 0x0190, - 0x704f, 0x0000, 0x2001, 0x1d80, 0x2009, 0x0040, 0x7a8c, 0x7b88, - 0x7c9c, 0x7d98, 0x2039, 0x0001, 0x080c, 0x4c8d, 0x701f, 0x368b, - 0x012e, 0x0005, 0x704f, 0x0001, 0x00d6, 0x2069, 0x1d80, 0x20a9, - 0x0040, 0x20e9, 0x0001, 0x20a1, 0x1d80, 0x2019, 0xffff, 0x4304, - 0x655c, 0x9588, 0x348e, 0x210d, 0x918c, 0x00ff, 0x216a, 0x900e, - 0x2011, 0x0002, 0x2100, 0x9506, 0x01a8, 0x080c, 0x67b4, 0x1190, - 0xb814, 0x821c, 0x0238, 0x9398, 0x1d80, 0x9085, 0xff00, 0x8007, - 0x201a, 0x0038, 0x9398, 0x1d80, 0x2324, 0x94a4, 0xff00, 0x9405, - 0x201a, 0x8210, 0x8108, 0x9182, 0x0080, 0x1208, 0x0c18, 0x8201, - 0x8007, 0x2d0c, 0x9105, 0x206a, 0x00de, 0x20a9, 0x0040, 0x20a1, - 0x1d80, 0x2099, 0x1d80, 0x080c, 0x60ed, 0x0804, 0x45ca, 0x080c, - 0x4c74, 0x0904, 0x36c2, 0x080c, 0x4c41, 0x1120, 0x2009, 0x0002, - 0x0804, 0x36bf, 0x080c, 0x5840, 0xd0b4, 0x0558, 0x7884, 0x908e, - 0x007e, 0x0538, 0x908e, 0x007f, 0x0520, 0x908e, 0x0080, 0x0508, - 0x080c, 0x347d, 0x1148, 0xb800, 0xd08c, 0x11d8, 0xb804, 0x9084, - 0x00ff, 0x9086, 0x0006, 0x11a8, 0xa867, 0x0000, 0xa868, 0xc0fd, - 0xa86a, 0x080c, 0xd0ec, 0x1120, 0x2009, 0x0003, 0x0804, 0x36bf, - 0x7007, 0x0003, 0x701f, 0x4655, 0x0005, 0x080c, 0x4c74, 0x0904, - 0x36c2, 0x20a9, 0x002b, 0xb8c4, 0x20e0, 0xb8c8, 0x2098, 0xa860, - 0x20e8, 0xa85c, 0x9080, 0x0002, 0x20a0, 0x4003, 0x20a9, 0x0008, - 0x9080, 0x0006, 0x20a0, 0xb8c4, 0x20e0, 0xb8c8, 0x9080, 0x0006, - 0x2098, 0x080c, 0x0fd6, 0x0070, 0x20a9, 0x0004, 0xa85c, 0x9080, - 0x000a, 0x20a0, 0xb8c4, 0x20e0, 0xb8c8, 0x9080, 0x000a, 0x2098, - 0x080c, 0x0fd6, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, - 0xffc0, 0x9080, 0x0002, 0x2009, 0x002b, 0x7a8c, 0x7b88, 0x7c9c, - 0x7d98, 0x0804, 0x4c8d, 0x81ff, 0x1904, 0x36bf, 0x080c, 0x4c58, - 0x0904, 0x36c2, 0x080c, 0x6a00, 0x0904, 0x36bf, 0x0058, 0xa878, - 0x9005, 0x0120, 0x2009, 0x0004, 0x0804, 0x36bf, 0xa974, 0xaa94, - 0x0804, 0x368d, 0x080c, 0x5848, 0x0904, 0x368d, 0x701f, 0x469f, - 0x7007, 0x0003, 0x0005, 0x81ff, 0x1904, 0x36bf, 0x7888, 0x908a, - 0x1000, 0x1a04, 0x36c2, 0x080c, 0x4c74, 0x0904, 0x36c2, 0x080c, - 0x6c11, 0x0120, 0x080c, 0x6c19, 0x1904, 0x36c2, 0x080c, 0x6a85, - 0x0904, 0x36bf, 0x2019, 0x0004, 0x900e, 0x080c, 0x6a12, 0x0904, - 0x36bf, 0x7984, 0x7a88, 0x04c9, 0x08a8, 0xa89c, 0x908a, 0x1000, - 0x12f8, 0x080c, 0x4c72, 0x01e0, 0x080c, 0x6c11, 0x0118, 0x080c, - 0x6c19, 0x11b0, 0x080c, 0x6a85, 0x2009, 0x0002, 0x0168, 0x2009, - 0x0002, 0x2019, 0x0004, 0x080c, 0x6a12, 0x2009, 0x0003, 0x0120, - 0xa998, 0xaa9c, 0x00d1, 0x0060, 0xa897, 0x4005, 0xa99a, 0x0010, - 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, - 0xa897, 0x4000, 0x080c, 0x5848, 0x0110, 0x9006, 0x0018, 0x900e, - 0x9085, 0x0001, 0x2001, 0x0000, 0x0005, 0x9186, 0x00ff, 0x0110, - 0x0071, 0x0060, 0x2029, 0x007e, 0x2061, 0x1800, 0x645c, 0x2400, - 0x9506, 0x0110, 0x2508, 0x0019, 0x8529, 0x1ec8, 0x0005, 0x080c, - 0x67b4, 0x1138, 0x2200, 0x8003, 0x800b, 0x810b, 0x9108, 0x080c, - 0x89a1, 0x0005, 0x81ff, 0x1904, 0x36bf, 0x798c, 0x2001, 0x1980, - 0x918c, 0x8000, 0x2102, 0x080c, 0x4c58, 0x0904, 0x36c2, 0x080c, - 0x6c11, 0x0120, 0x080c, 0x6c19, 0x1904, 0x36c2, 0x080c, 0x687b, - 0x0904, 0x36bf, 0x080c, 0x6a09, 0x0904, 0x36bf, 0x2001, 0x1980, - 0x2004, 0xd0fc, 0x1904, 0x368d, 0x0804, 0x46aa, 0xa9a0, 0x2001, - 0x1980, 0x918c, 0x8000, 0xc18d, 0x2102, 0x080c, 0x4c65, 0x01a0, - 0x080c, 0x6c11, 0x0118, 0x080c, 0x6c19, 0x1170, 0x080c, 0x687b, - 0x2009, 0x0002, 0x0128, 0x080c, 0x6a09, 0x1170, 0x2009, 0x0003, - 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, - 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, 0x4000, 0x2001, 0x1980, - 0x2004, 0xd0fc, 0x1128, 0x080c, 0x5848, 0x0110, 0x9006, 0x0018, - 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x0005, 0x81ff, 0x1904, - 0x36bf, 0x798c, 0x2001, 0x197f, 0x918c, 0x8000, 0x2102, 0x080c, - 0x4c58, 0x0904, 0x36c2, 0x080c, 0x6c11, 0x0120, 0x080c, 0x6c19, - 0x1904, 0x36c2, 0x080c, 0x687b, 0x0904, 0x36bf, 0x080c, 0x69f7, - 0x0904, 0x36bf, 0x2001, 0x197f, 0x2004, 0xd0fc, 0x1904, 0x368d, - 0x0804, 0x46aa, 0xa9a0, 0x2001, 0x197f, 0x918c, 0x8000, 0xc18d, - 0x2102, 0x080c, 0x4c65, 0x01a0, 0x080c, 0x6c11, 0x0118, 0x080c, - 0x6c19, 0x1170, 0x080c, 0x687b, 0x2009, 0x0002, 0x0128, 0x080c, - 0x69f7, 0x1170, 0x2009, 0x0003, 0xa897, 0x4005, 0xa99a, 0x0010, - 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, - 0xa897, 0x4000, 0x2001, 0x197f, 0x2004, 0xd0fc, 0x1128, 0x080c, - 0x5848, 0x0110, 0x9006, 0x0018, 0x900e, 0x9085, 0x0001, 0x2001, - 0x0000, 0x0005, 0x6100, 0x0804, 0x368d, 0x080c, 0x4c74, 0x0904, - 0x36c2, 0x080c, 0x5854, 0x1904, 0x36bf, 0x79a8, 0xd184, 0x1158, - 0xb834, 0x8007, 0x789e, 0xb830, 0x8007, 0x789a, 0xbb2c, 0x831f, - 0xba28, 0x8217, 0x0050, 0xb824, 0x8007, 0x789e, 0xb820, 0x8007, - 0x789a, 0xbb1c, 0x831f, 0xba18, 0x8217, 0xb900, 0x918c, 0x0202, - 0x0804, 0x368d, 0x78a8, 0x909c, 0x0003, 0xd0ac, 0x1150, 0xd0b4, - 0x1140, 0x939a, 0x0003, 0x1a04, 0x36bf, 0x625c, 0x7884, 0x9206, - 0x1548, 0x080c, 0x8b10, 0x2001, 0xffec, 0x2009, 0x000c, 0x7a8c, - 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0000, 0x0006, 0x78a8, 0x9084, - 0x0080, 0x1118, 0x000e, 0x0804, 0x4c8d, 0x000e, 0x2031, 0x0000, - 0x2061, 0x18b8, 0x2c44, 0xa66a, 0xa17a, 0xa772, 0xa076, 0xa28e, - 0xa392, 0xa496, 0xa59a, 0x080c, 0x114e, 0x7007, 0x0002, 0x701f, - 0x4862, 0x0005, 0x81ff, 0x1904, 0x36bf, 0x080c, 0x4c74, 0x0904, - 0x36c2, 0x080c, 0x6c11, 0x1904, 0x36bf, 0x00c6, 0x080c, 0x4c41, - 0x00ce, 0x0904, 0x36bf, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, - 0x7ea8, 0x080c, 0xd092, 0x0904, 0x36bf, 0x7007, 0x0003, 0x701f, - 0x4866, 0x0005, 0x080c, 0x4397, 0x0804, 0x368d, 0xa830, 0x9086, - 0x0100, 0x0904, 0x36bf, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, - 0x9084, 0xffc0, 0x9080, 0x001b, 0x2009, 0x000c, 0x7a8c, 0x7b88, - 0x7c9c, 0x7d98, 0x0804, 0x4c8d, 0x9006, 0x080c, 0x26f5, 0x78a8, - 0x9084, 0x00ff, 0x9086, 0x00ff, 0x0118, 0x81ff, 0x1904, 0x36bf, - 0x080c, 0x779e, 0x0110, 0x080c, 0x6162, 0x7888, 0x908a, 0x1000, - 0x1a04, 0x36c2, 0x7984, 0x9186, 0x00ff, 0x0138, 0x9182, 0x007f, - 0x1a04, 0x36c2, 0x2100, 0x080c, 0x26bf, 0x0026, 0x00c6, 0x0126, - 0x2091, 0x8000, 0x2061, 0x1a04, 0x601b, 0x0000, 0x601f, 0x0000, - 0x607b, 0x0000, 0x607f, 0x0000, 0x080c, 0x779e, 0x1158, 0x080c, - 0x7ab6, 0x080c, 0x619d, 0x9085, 0x0001, 0x080c, 0x77e2, 0x080c, - 0x76cd, 0x00f0, 0x080c, 0xacfc, 0x080c, 0xb09b, 0x080c, 0xad18, - 0x2061, 0x0100, 0x2001, 0x1818, 0x2004, 0x9084, 0x00ff, 0x810f, - 0x9105, 0x604a, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0x1999, - 0x200b, 0x0000, 0x2009, 0x002d, 0x2011, 0x6088, 0x080c, 0x8a5d, - 0x7984, 0x080c, 0x779e, 0x1110, 0x2009, 0x00ff, 0x7a88, 0x080c, - 0x470d, 0x012e, 0x00ce, 0x002e, 0x0804, 0x368d, 0x7984, 0x080c, - 0x6749, 0x2b08, 0x1904, 0x36c2, 0x0804, 0x368d, 0x81ff, 0x0120, - 0x2009, 0x0001, 0x0804, 0x36bf, 0x60dc, 0xd0ac, 0x1130, 0xd09c, - 0x1120, 0x2009, 0x0005, 0x0804, 0x36bf, 0x080c, 0x4c41, 0x1120, - 0x2009, 0x0002, 0x0804, 0x36bf, 0x7984, 0x81ff, 0x0904, 0x36c2, - 0x9192, 0x0021, 0x1a04, 0x36c2, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, - 0xa85c, 0x9080, 0x0019, 0x702a, 0xaf60, 0x7736, 0x080c, 0x4c8a, - 0x701f, 0x4921, 0x7880, 0x9086, 0x006e, 0x0110, 0x701f, 0x52da, - 0x0005, 0x2009, 0x0080, 0x080c, 0x67b4, 0x1118, 0x080c, 0x6c11, - 0x0120, 0x2021, 0x400a, 0x0804, 0x368f, 0x00d6, 0x0096, 0xa964, - 0xaa6c, 0xab70, 0xac74, 0xad78, 0xae7c, 0xa884, 0x90be, 0x0100, - 0x0904, 0x49ba, 0x90be, 0x0112, 0x0904, 0x49ba, 0x90be, 0x0113, - 0x0904, 0x49ba, 0x90be, 0x0114, 0x0904, 0x49ba, 0x90be, 0x0117, - 0x0904, 0x49ba, 0x90be, 0x011a, 0x0904, 0x49ba, 0x90be, 0x011c, - 0x0904, 0x49ba, 0x90be, 0x0121, 0x0904, 0x49a1, 0x90be, 0x0131, - 0x0904, 0x49a1, 0x90be, 0x0171, 0x0904, 0x49ba, 0x90be, 0x0173, - 0x0904, 0x49ba, 0x90be, 0x01a1, 0x1128, 0xa894, 0x8007, 0xa896, - 0x0804, 0x49c5, 0x90be, 0x0212, 0x0904, 0x49ae, 0x90be, 0x0213, - 0x05e8, 0x90be, 0x0214, 0x0500, 0x90be, 0x0217, 0x0188, 0x90be, - 0x021a, 0x1120, 0xa89c, 0x8007, 0xa89e, 0x04e0, 0x90be, 0x021f, - 0x05c8, 0x90be, 0x0300, 0x05b0, 0x009e, 0x00de, 0x0804, 0x36c2, - 0x7028, 0x9080, 0x0010, 0x2098, 0x20a0, 0x7034, 0x20e0, 0x20e8, - 0x20a9, 0x0007, 0x080c, 0x4a03, 0x7028, 0x9080, 0x000e, 0x2098, - 0x20a0, 0x7034, 0x20e0, 0x20e8, 0x20a9, 0x0001, 0x080c, 0x4a03, - 0x00c8, 0x7028, 0x9080, 0x000c, 0x2098, 0x20a0, 0x7034, 0x20e0, - 0x20e8, 0x20a9, 0x0001, 0x080c, 0x4a10, 0x00b8, 0x7028, 0x9080, - 0x000e, 0x2098, 0x20a0, 0x7034, 0x20e0, 0x20e8, 0x20a9, 0x0001, - 0x080c, 0x4a10, 0x7028, 0x9080, 0x000c, 0x2098, 0x20a0, 0x7034, - 0x20e0, 0x20e8, 0x20a9, 0x0001, 0x04f1, 0x00c6, 0x080c, 0x4c41, - 0x0550, 0xa868, 0xc0fd, 0xa86a, 0xa867, 0x0119, 0x9006, 0xa882, - 0xa87f, 0x0020, 0xa88b, 0x0001, 0x810b, 0xa9ae, 0xa8b2, 0xaab6, - 0xabba, 0xacbe, 0xadc2, 0xa9c6, 0xa8ca, 0x00ce, 0x009e, 0x00de, - 0xa866, 0xa822, 0xa868, 0xc0fd, 0xa86a, 0xa804, 0x2048, 0x080c, - 0xd0ad, 0x1120, 0x2009, 0x0003, 0x0804, 0x36bf, 0x7007, 0x0003, - 0x701f, 0x49fa, 0x0005, 0x00ce, 0x009e, 0x00de, 0x2009, 0x0002, - 0x0804, 0x36bf, 0xa820, 0x9086, 0x8001, 0x1904, 0x368d, 0x2009, - 0x0004, 0x0804, 0x36bf, 0x0016, 0x0026, 0x3510, 0x20a9, 0x0002, - 0x4002, 0x4104, 0x4004, 0x8211, 0x1dc8, 0x002e, 0x001e, 0x0005, - 0x0016, 0x0026, 0x0036, 0x0046, 0x3520, 0x20a9, 0x0004, 0x4002, - 0x4304, 0x4204, 0x4104, 0x4004, 0x8421, 0x1db8, 0x004e, 0x003e, - 0x002e, 0x001e, 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, - 0x36bf, 0x60dc, 0xd0ac, 0x1188, 0x2009, 0x180d, 0x210c, 0xd18c, - 0x0130, 0xd09c, 0x0120, 0x2009, 0x0016, 0x0804, 0x36bf, 0xd09c, - 0x1120, 0x2009, 0x0005, 0x0804, 0x36bf, 0x7984, 0x78a8, 0x2040, - 0x080c, 0xb094, 0x1120, 0x9182, 0x007f, 0x0a04, 0x36c2, 0x9186, - 0x00ff, 0x0904, 0x36c2, 0x9182, 0x0800, 0x1a04, 0x36c2, 0x7a8c, - 0x7b88, 0x607c, 0x9306, 0x1158, 0x6080, 0x924e, 0x0904, 0x36c2, - 0x080c, 0xb094, 0x1120, 0x99cc, 0xff00, 0x0904, 0x36c2, 0x0126, - 0x2091, 0x8000, 0x2001, 0x180d, 0x2004, 0xd08c, 0x0198, 0x9386, - 0x00ff, 0x0180, 0x0026, 0x2011, 0x8008, 0x080c, 0x6c35, 0x002e, - 0x0148, 0x918d, 0x8000, 0x080c, 0x6c7f, 0x1120, 0x2001, 0x4009, - 0x0804, 0x4ac1, 0x080c, 0x4b54, 0x0904, 0x4ac7, 0x0086, 0x90c6, - 0x4000, 0x008e, 0x1538, 0x00c6, 0x0006, 0x0036, 0xb818, 0xbb1c, - 0x9305, 0xbb20, 0x9305, 0xbb24, 0x9305, 0xbb28, 0x9305, 0xbb2c, - 0x9305, 0xbb30, 0x9305, 0xbb34, 0x9305, 0x003e, 0x0570, 0xd88c, - 0x1128, 0x080c, 0x6c11, 0x0110, 0xc89d, 0x0438, 0x900e, 0x080c, - 0x6aae, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x000e, - 0x00ce, 0x00b8, 0x90c6, 0x4007, 0x1110, 0x2408, 0x0090, 0x90c6, - 0x4008, 0x1118, 0x2708, 0x2610, 0x0060, 0x90c6, 0x4009, 0x1108, - 0x0040, 0x90c6, 0x4006, 0x1108, 0x0020, 0x2001, 0x4005, 0x2009, - 0x000a, 0x2020, 0x012e, 0x0804, 0x368f, 0x000e, 0x00ce, 0x2b00, - 0x7026, 0x0016, 0x00b6, 0x00c6, 0x00e6, 0x2c70, 0x080c, 0xb1dd, - 0x0904, 0x4b1c, 0x2b00, 0x6012, 0x080c, 0xd3b6, 0x2e58, 0x00ee, - 0x00e6, 0x00c6, 0x080c, 0x4c41, 0x00ce, 0x2b70, 0x1158, 0x080c, - 0xb16c, 0x00ee, 0x00ce, 0x00be, 0x001e, 0x012e, 0x2009, 0x0002, - 0x0804, 0x36bf, 0x900e, 0xa966, 0xa96a, 0x2900, 0x6016, 0xa932, - 0xa868, 0xc0fd, 0xd88c, 0x0108, 0xc0f5, 0xa86a, 0xd89c, 0x1110, - 0x080c, 0x3315, 0x6023, 0x0001, 0x9006, 0x080c, 0x66e6, 0xd89c, - 0x0138, 0x2001, 0x0004, 0x080c, 0x66fa, 0x2009, 0x0003, 0x0030, - 0x2001, 0x0002, 0x080c, 0x66fa, 0x2009, 0x0002, 0x080c, 0xb20a, - 0x78a8, 0xd094, 0x0138, 0x00ee, 0x7024, 0x00e6, 0x2058, 0xb8d4, - 0xc08d, 0xb8d6, 0x9085, 0x0001, 0x00ee, 0x00ce, 0x00be, 0x001e, - 0x012e, 0x1120, 0x2009, 0x0003, 0x0804, 0x36bf, 0x7007, 0x0003, - 0x701f, 0x4b2b, 0x0005, 0xa830, 0x2009, 0x180d, 0x210c, 0xd18c, - 0x0140, 0x2008, 0x918e, 0xdead, 0x1120, 0x2021, 0x4009, 0x0804, - 0x368f, 0x9086, 0x0100, 0x7024, 0x2058, 0x1138, 0x2009, 0x0004, - 0xba04, 0x9294, 0x00ff, 0x0804, 0x578e, 0x900e, 0xa868, 0xd0f4, - 0x1904, 0x368d, 0x080c, 0x6aae, 0x1108, 0xc185, 0xb800, 0xd0bc, - 0x0108, 0xc18d, 0x0804, 0x368d, 0x00e6, 0x00d6, 0x0096, 0x83ff, - 0x0904, 0x4ba3, 0x902e, 0x080c, 0xb094, 0x0130, 0x9026, 0x20a9, - 0x0800, 0x2071, 0x1000, 0x0030, 0x2021, 0x007f, 0x20a9, 0x0781, - 0x2071, 0x107f, 0x2e04, 0x9005, 0x11b8, 0x2100, 0x9406, 0x1904, - 0x4bb4, 0x2428, 0x94ce, 0x007f, 0x1120, 0x92ce, 0xfffd, 0x1558, - 0x0030, 0x94ce, 0x0080, 0x1130, 0x92ce, 0xfffc, 0x1520, 0x93ce, - 0x00ff, 0x1508, 0xc5fd, 0x0480, 0x2058, 0xbf10, 0x2700, 0x9306, - 0x11e8, 0xbe14, 0x2600, 0x9206, 0x11c8, 0x2400, 0x9106, 0x1180, - 0xd884, 0x0598, 0xd894, 0x1588, 0x080c, 0x6bb1, 0x1570, 0x2001, - 0x4000, 0x0460, 0x080c, 0x6c11, 0x1540, 0x2001, 0x4000, 0x0430, - 0x2001, 0x4007, 0x0418, 0x2001, 0x4006, 0x0400, 0x2400, 0x9106, - 0x1158, 0xbe14, 0x87ff, 0x1128, 0x86ff, 0x0918, 0x080c, 0xb094, - 0x1900, 0x2001, 0x4008, 0x0090, 0x8420, 0x8e70, 0x1f04, 0x4b6a, - 0x85ff, 0x1130, 0x2001, 0x4009, 0x0048, 0x2001, 0x0001, 0x0030, - 0x080c, 0x6749, 0x1dd0, 0xbb12, 0xba16, 0x9006, 0x9005, 0x009e, - 0x00de, 0x00ee, 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, - 0x36bf, 0x080c, 0x4c41, 0x1120, 0x2009, 0x0002, 0x0804, 0x36bf, - 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x7884, 0x9005, 0x0904, - 0x36c2, 0x9096, 0x00ff, 0x0120, 0x9092, 0x0004, 0x1a04, 0x36c2, - 0x2010, 0x2918, 0x080c, 0x32b5, 0x1120, 0x2009, 0x0003, 0x0804, - 0x36bf, 0x7007, 0x0003, 0x701f, 0x4bf6, 0x0005, 0xa830, 0x9086, - 0x0100, 0x1904, 0x368d, 0x2009, 0x0004, 0x0804, 0x36bf, 0x7984, - 0x080c, 0xb094, 0x1120, 0x9182, 0x007f, 0x0a04, 0x36c2, 0x9186, - 0x00ff, 0x0904, 0x36c2, 0x9182, 0x0800, 0x1a04, 0x36c2, 0x2001, - 0x9400, 0x080c, 0x57e9, 0x1904, 0x36bf, 0x0804, 0x368d, 0xa998, - 0x080c, 0xb094, 0x1118, 0x9182, 0x007f, 0x0280, 0x9186, 0x00ff, - 0x0168, 0x9182, 0x0800, 0x1250, 0x2001, 0x9400, 0x080c, 0x57e9, - 0x11a8, 0x0060, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, - 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, 0x4000, - 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x0005, 0x2009, 0x000a, - 0x0c48, 0x080c, 0x1059, 0x0198, 0x9006, 0xa802, 0x7014, 0x9005, - 0x1120, 0x2900, 0x7016, 0x701a, 0x0040, 0x7018, 0xa802, 0x0086, - 0x2040, 0x2900, 0xa006, 0x701a, 0x008e, 0x9085, 0x0001, 0x0005, - 0x7984, 0x080c, 0x67b4, 0x1130, 0x7e88, 0x9684, 0x3fff, 0x9082, - 0x4000, 0x0208, 0x905e, 0x8bff, 0x0005, 0xa998, 0x080c, 0x67b4, - 0x1130, 0xae9c, 0x9684, 0x3fff, 0x9082, 0x4000, 0x0208, 0x905e, - 0x8bff, 0x0005, 0xae98, 0x0008, 0x7e84, 0x2608, 0x080c, 0x67b4, - 0x1108, 0x0008, 0x905e, 0x8bff, 0x0005, 0x0016, 0x7114, 0x81ff, - 0x0128, 0x2148, 0xa904, 0x080c, 0x108b, 0x0cc8, 0x7116, 0x711a, - 0x001e, 0x0005, 0x2031, 0x0001, 0x0010, 0x2031, 0x0000, 0x2061, - 0x18b8, 0x2c44, 0xa66a, 0xa17a, 0xa772, 0xa076, 0xa28e, 0xa392, - 0xa496, 0xa59a, 0x080c, 0x114e, 0x7007, 0x0002, 0x701f, 0x368d, - 0x0005, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2079, 0x0000, 0x2001, - 0x18b0, 0x2004, 0x9005, 0x1190, 0x0e04, 0x4cbe, 0x7a36, 0x7833, - 0x0012, 0x7a82, 0x7b86, 0x7c8a, 0x2091, 0x4080, 0x2001, 0x0089, - 0x2004, 0xd084, 0x190c, 0x1200, 0x0804, 0x4d24, 0x0016, 0x0086, - 0x0096, 0x00c6, 0x00e6, 0x2071, 0x189e, 0x7044, 0x9005, 0x1540, - 0x7148, 0x9182, 0x0010, 0x0288, 0x7038, 0x2060, 0x080c, 0x1059, - 0x0904, 0x4d1c, 0xa84b, 0x0000, 0x2900, 0x7046, 0x2001, 0x0002, - 0x9080, 0x1ec1, 0x2005, 0xa846, 0x0098, 0x7038, 0x90e0, 0x0004, - 0x2001, 0x18ba, 0x9c82, 0x18fa, 0x0210, 0x2061, 0x18ba, 0x2c00, - 0x703a, 0x7148, 0x81ff, 0x1108, 0x703e, 0x8108, 0x714a, 0x0460, - 0x7148, 0x8108, 0x714a, 0x7044, 0x2040, 0xa144, 0x2105, 0x0016, - 0x908a, 0x0036, 0x1a0c, 0x0d85, 0x2060, 0x001e, 0x8108, 0x2105, - 0x9005, 0xa146, 0x1520, 0x080c, 0x1059, 0x1130, 0x8109, 0xa946, - 0x7148, 0x8109, 0x714a, 0x00d8, 0x9006, 0xa806, 0xa84a, 0xa046, - 0x2800, 0xa802, 0x2900, 0xa006, 0x7046, 0x2001, 0x0002, 0x9080, - 0x1ec1, 0x2005, 0xa846, 0x0058, 0x2262, 0x6306, 0x640a, 0x00ee, - 0x00ce, 0x009e, 0x008e, 0x001e, 0x012e, 0x00fe, 0x0005, 0x2c00, - 0x9082, 0x001b, 0x0002, 0x4d46, 0x4d46, 0x4d48, 0x4d46, 0x4d46, - 0x4d46, 0x4d4c, 0x4d46, 0x4d46, 0x4d46, 0x4d50, 0x4d46, 0x4d46, - 0x4d46, 0x4d54, 0x4d46, 0x4d46, 0x4d46, 0x4d58, 0x4d46, 0x4d46, - 0x4d46, 0x4d5c, 0x4d46, 0x4d46, 0x4d46, 0x4d61, 0x080c, 0x0d85, - 0xa276, 0xa37a, 0xa47e, 0x0898, 0xa286, 0xa38a, 0xa48e, 0x0878, - 0xa296, 0xa39a, 0xa49e, 0x0858, 0xa2a6, 0xa3aa, 0xa4ae, 0x0838, - 0xa2b6, 0xa3ba, 0xa4be, 0x0818, 0xa2c6, 0xa3ca, 0xa4ce, 0x0804, - 0x4d1f, 0xa2d6, 0xa3da, 0xa4de, 0x0804, 0x4d1f, 0x00e6, 0x2071, - 0x189e, 0x7048, 0x9005, 0x0904, 0x4df8, 0x0126, 0x2091, 0x8000, - 0x0e04, 0x4df7, 0x00f6, 0x2079, 0x0000, 0x00c6, 0x0096, 0x0086, - 0x0076, 0x9006, 0x2038, 0x7040, 0x2048, 0x9005, 0x0500, 0xa948, - 0x2105, 0x0016, 0x908a, 0x0036, 0x1a0c, 0x0d85, 0x2060, 0x001e, - 0x8108, 0x2105, 0x9005, 0xa94a, 0x1904, 0x4dfa, 0xa804, 0x9005, - 0x090c, 0x0d85, 0x7042, 0x2938, 0x2040, 0xa003, 0x0000, 0x2001, - 0x0002, 0x9080, 0x1ec1, 0x2005, 0xa04a, 0x0804, 0x4dfa, 0x703c, - 0x2060, 0x2c14, 0x6304, 0x6408, 0x650c, 0x2200, 0x7836, 0x7833, - 0x0012, 0x7882, 0x2300, 0x7886, 0x2400, 0x788a, 0x2091, 0x4080, - 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1200, 0x87ff, 0x0118, - 0x2748, 0x080c, 0x108b, 0x7048, 0x8001, 0x704a, 0x9005, 0x1170, - 0x7040, 0x2048, 0x9005, 0x0128, 0x080c, 0x108b, 0x9006, 0x7042, - 0x7046, 0x703b, 0x18ba, 0x703f, 0x18ba, 0x0420, 0x7040, 0x9005, - 0x1508, 0x7238, 0x2c00, 0x9206, 0x0148, 0x9c80, 0x0004, 0x90fa, - 0x18fa, 0x0210, 0x2001, 0x18ba, 0x703e, 0x00a0, 0x9006, 0x703e, - 0x703a, 0x7044, 0x9005, 0x090c, 0x0d85, 0x2048, 0xa800, 0x9005, - 0x1de0, 0x2900, 0x7042, 0x2001, 0x0002, 0x9080, 0x1ec1, 0x2005, - 0xa84a, 0x0000, 0x007e, 0x008e, 0x009e, 0x00ce, 0x00fe, 0x012e, - 0x00ee, 0x0005, 0x2c00, 0x9082, 0x001b, 0x0002, 0x4e19, 0x4e19, - 0x4e1b, 0x4e19, 0x4e19, 0x4e19, 0x4e20, 0x4e19, 0x4e19, 0x4e19, - 0x4e25, 0x4e19, 0x4e19, 0x4e19, 0x4e2a, 0x4e19, 0x4e19, 0x4e19, - 0x4e2f, 0x4e19, 0x4e19, 0x4e19, 0x4e34, 0x4e19, 0x4e19, 0x4e19, - 0x4e39, 0x080c, 0x0d85, 0xaa74, 0xab78, 0xac7c, 0x0804, 0x4da5, - 0xaa84, 0xab88, 0xac8c, 0x0804, 0x4da5, 0xaa94, 0xab98, 0xac9c, - 0x0804, 0x4da5, 0xaaa4, 0xaba8, 0xacac, 0x0804, 0x4da5, 0xaab4, - 0xabb8, 0xacbc, 0x0804, 0x4da5, 0xaac4, 0xabc8, 0xaccc, 0x0804, - 0x4da5, 0xaad4, 0xabd8, 0xacdc, 0x0804, 0x4da5, 0x0016, 0x0026, - 0x0036, 0x00b6, 0x00c6, 0x2009, 0x007e, 0x080c, 0x67b4, 0x2019, - 0x0001, 0xb85c, 0xd0ac, 0x0110, 0x2019, 0x0000, 0x2011, 0x801b, - 0x080c, 0x4ca1, 0x00ce, 0x00be, 0x003e, 0x002e, 0x001e, 0x0005, - 0x0026, 0x080c, 0x5840, 0xd0c4, 0x0120, 0x2011, 0x8014, 0x080c, - 0x4ca1, 0x002e, 0x0005, 0x81ff, 0x1904, 0x36bf, 0x0126, 0x2091, - 0x8000, 0x6030, 0xc08d, 0xc085, 0xc0ac, 0x6032, 0x080c, 0x779e, - 0x1158, 0x080c, 0x7ab6, 0x080c, 0x619d, 0x9085, 0x0001, 0x080c, - 0x77e2, 0x080c, 0x76cd, 0x0010, 0x080c, 0x6058, 0x012e, 0x0804, - 0x368d, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x36bf, 0x080c, - 0x5854, 0x0120, 0x2009, 0x0007, 0x0804, 0x36bf, 0x080c, 0x6c09, - 0x0120, 0x2009, 0x0008, 0x0804, 0x36bf, 0x2001, 0x180d, 0x2004, - 0xd08c, 0x0178, 0x0026, 0x2011, 0x0010, 0x080c, 0x6c35, 0x002e, - 0x0140, 0x7984, 0x080c, 0x6c7f, 0x1120, 0x2009, 0x4009, 0x0804, - 0x36bf, 0x7984, 0x080c, 0x6749, 0x1904, 0x36c2, 0x080c, 0x4c74, - 0x0904, 0x36c2, 0x2b00, 0x7026, 0x080c, 0x6c11, 0x7888, 0x1170, - 0x9084, 0x0005, 0x1158, 0x900e, 0x080c, 0x6aae, 0x1108, 0xc185, - 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x0804, 0x368d, 0x080c, 0x4c41, - 0x0904, 0x36bf, 0x9006, 0xa866, 0xa832, 0xa868, 0xc0fd, 0xa86a, - 0x080c, 0xd154, 0x0904, 0x36bf, 0x7888, 0xd094, 0x0118, 0xb8d4, - 0xc08d, 0xb8d6, 0x7007, 0x0003, 0x701f, 0x4f28, 0x0005, 0x2061, - 0x1800, 0x080c, 0x5854, 0x2009, 0x0007, 0x1560, 0x080c, 0x6c09, - 0x0118, 0x2009, 0x0008, 0x0430, 0xa998, 0x080c, 0x6749, 0x1530, - 0x080c, 0x4c72, 0x0518, 0x080c, 0x6c11, 0xa89c, 0x1168, 0x9084, - 0x0005, 0x1150, 0x900e, 0x080c, 0x6aae, 0x1108, 0xc185, 0xb800, - 0xd0bc, 0x0108, 0xc18d, 0x00d0, 0xa868, 0xc0fc, 0xa86a, 0x080c, - 0xd154, 0x11e0, 0xa89c, 0xd094, 0x0118, 0xb8d4, 0xc08d, 0xb8d6, - 0x2009, 0x0003, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, - 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, 0x4000, - 0xa99a, 0x9006, 0x918d, 0x0001, 0x2008, 0x0005, 0x9006, 0x0005, - 0xa830, 0x2009, 0x180d, 0x210c, 0xd18c, 0x0140, 0x2008, 0x918e, - 0xdead, 0x1120, 0x2021, 0x4009, 0x0804, 0x368f, 0x9086, 0x0100, - 0x7024, 0x2058, 0x1110, 0x0804, 0x578e, 0x900e, 0x080c, 0x6aae, - 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x0804, 0x368d, - 0x080c, 0x5854, 0x0120, 0x2009, 0x0007, 0x0804, 0x36bf, 0x7f84, - 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x080c, 0x4c41, 0x1120, 0x2009, - 0x0002, 0x0804, 0x36bf, 0x900e, 0x2130, 0x7126, 0x7132, 0xa860, - 0x20e8, 0x7036, 0xa85c, 0x9080, 0x0005, 0x702a, 0x20a0, 0x080c, - 0x67b4, 0x1904, 0x4fde, 0x080c, 0x6c11, 0x0138, 0x080c, 0x6c19, - 0x0120, 0x080c, 0x6bb1, 0x1904, 0x4fde, 0xd794, 0x1110, 0xd784, - 0x01a8, 0xb8c4, 0x20e0, 0xb8c8, 0x9080, 0x0006, 0x2098, 0x3400, - 0xd794, 0x0198, 0x20a9, 0x0008, 0x4003, 0x2098, 0x20a0, 0x3d00, - 0x20e0, 0x20a9, 0x0002, 0x080c, 0x4a10, 0x0080, 0xb8c4, 0x20e0, - 0xb8c8, 0x9080, 0x000a, 0x2098, 0x3400, 0x20a9, 0x0004, 0x4003, - 0x2098, 0x20a0, 0x3d00, 0x20e0, 0x080c, 0x4a10, 0x9186, 0x007e, - 0x0170, 0x9186, 0x0080, 0x0158, 0x080c, 0x6c11, 0x90c2, 0x0006, - 0x1210, 0xc1fd, 0x0020, 0x080c, 0x6aae, 0x1108, 0xc1fd, 0x4104, - 0xc1fc, 0xd794, 0x0528, 0xb8c4, 0x20e0, 0xb8c8, 0x2060, 0x9c80, - 0x0000, 0x2098, 0x20a9, 0x0002, 0x4003, 0x9c80, 0x0003, 0x2098, - 0x20a9, 0x0001, 0x4005, 0x9c80, 0x0004, 0x2098, 0x3400, 0x20a9, - 0x0002, 0x4003, 0x2098, 0x20a0, 0x3d00, 0x20e0, 0x080c, 0x4a03, - 0x9c80, 0x0026, 0x2098, 0xb8c4, 0x20e0, 0x20a9, 0x0002, 0x4003, - 0xd794, 0x0110, 0x96b0, 0x000b, 0x96b0, 0x0005, 0x8108, 0x080c, - 0xb094, 0x0118, 0x9186, 0x0800, 0x0040, 0xd78c, 0x0120, 0x9186, - 0x0800, 0x0170, 0x0018, 0x9186, 0x007e, 0x0150, 0xd794, 0x0118, - 0x9686, 0x0020, 0x0010, 0x9686, 0x0028, 0x0150, 0x0804, 0x4f67, - 0x86ff, 0x1120, 0x7124, 0x810b, 0x0804, 0x368d, 0x7033, 0x0001, - 0x7122, 0x7024, 0x9600, 0x7026, 0x772e, 0x2061, 0x18b8, 0x2c44, - 0xa06b, 0x0000, 0xa67a, 0x7034, 0xa072, 0x7028, 0xa076, 0xa28e, - 0xa392, 0xa496, 0xa59a, 0x080c, 0x114e, 0x7007, 0x0002, 0x701f, - 0x501a, 0x0005, 0x7030, 0x9005, 0x1180, 0x7120, 0x7028, 0x20a0, - 0x772c, 0x9036, 0x7034, 0x20e8, 0x2061, 0x18b8, 0x2c44, 0xa28c, - 0xa390, 0xa494, 0xa598, 0x0804, 0x4f67, 0x7124, 0x810b, 0x0804, - 0x368d, 0x2029, 0x007e, 0x7984, 0x7a88, 0x7b8c, 0x7c98, 0x9184, - 0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04, 0x36c2, 0x9502, 0x0a04, - 0x36c2, 0x9184, 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x36c2, 0x9502, - 0x0a04, 0x36c2, 0x9284, 0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04, - 0x36c2, 0x9502, 0x0a04, 0x36c2, 0x9284, 0x00ff, 0x90e2, 0x0020, - 0x0a04, 0x36c2, 0x9502, 0x0a04, 0x36c2, 0x9384, 0xff00, 0x8007, - 0x90e2, 0x0020, 0x0a04, 0x36c2, 0x9502, 0x0a04, 0x36c2, 0x9384, - 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x36c2, 0x9502, 0x0a04, 0x36c2, - 0x9484, 0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04, 0x36c2, 0x9502, - 0x0a04, 0x36c2, 0x9484, 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x36c2, - 0x9502, 0x0a04, 0x36c2, 0x2061, 0x1989, 0x6102, 0x6206, 0x630a, - 0x640e, 0x0804, 0x368d, 0x080c, 0x4c41, 0x0904, 0x36bf, 0x2009, - 0x0016, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0xa85c, 0x9080, 0x0019, - 0xaf60, 0x080c, 0x4c8a, 0x701f, 0x509e, 0x0005, 0x20a9, 0x0016, - 0x896e, 0x8d6e, 0x8d6f, 0x9d84, 0xffc0, 0x9080, 0x0019, 0x2098, - 0x9d84, 0x003f, 0x20e0, 0x2069, 0x1877, 0x20e9, 0x0001, 0x2da0, - 0x4003, 0x6800, 0x9005, 0x0904, 0x5105, 0x6804, 0x2008, 0x918c, - 0xfff8, 0x1904, 0x5105, 0x680c, 0x9005, 0x0904, 0x5105, 0x9082, - 0xff01, 0x1a04, 0x5105, 0x6810, 0x9082, 0x005c, 0x06f0, 0x6824, - 0x2008, 0x9082, 0x0008, 0x06c8, 0x9182, 0x0400, 0x16b0, 0x0056, - 0x2029, 0x0000, 0x080c, 0x9077, 0x005e, 0x6944, 0x6820, 0x9102, - 0x0660, 0x6820, 0x9082, 0x0019, 0x1640, 0x6828, 0x6944, 0x810c, - 0x9102, 0x0618, 0x6840, 0x9082, 0x000f, 0x12f8, 0x080c, 0x1072, - 0x2900, 0x0590, 0x684e, 0x00e6, 0x2071, 0x1931, 0x00b6, 0x2059, - 0x0000, 0x080c, 0x8f33, 0x00be, 0x00ee, 0x01e8, 0x080c, 0x8c78, - 0x080c, 0x8cc7, 0x1160, 0x6857, 0x0000, 0x00c6, 0x6b10, 0x2061, - 0x1a6e, 0x630e, 0x00ce, 0x0804, 0x368d, 0x0804, 0x36c2, 0x080c, - 0x8cc0, 0x00e6, 0x2071, 0x1931, 0x080c, 0x90f7, 0x080c, 0x9106, - 0x080c, 0x8f18, 0x00ee, 0x2001, 0x188a, 0x204c, 0x080c, 0x108b, - 0x2001, 0x188a, 0x2003, 0x0000, 0x0804, 0x36bf, 0x0126, 0x2091, - 0x8000, 0x080c, 0x94b8, 0x080c, 0x8cc0, 0x012e, 0x0804, 0x368d, - 0x0006, 0x080c, 0x5840, 0xd0cc, 0x000e, 0x0005, 0x0006, 0x080c, - 0x5844, 0xd0bc, 0x000e, 0x0005, 0x6174, 0x7a84, 0x6300, 0x82ff, - 0x1118, 0x7986, 0x0804, 0x368d, 0x83ff, 0x1904, 0x36c2, 0x2001, - 0xfff0, 0x9200, 0x1a04, 0x36c2, 0x2019, 0xffff, 0x6078, 0x9302, - 0x9200, 0x0a04, 0x36c2, 0x7986, 0x6276, 0x0804, 0x368d, 0x080c, - 0x5854, 0x1904, 0x36bf, 0x7c88, 0x7d84, 0x7e98, 0x7f8c, 0x080c, - 0x4c41, 0x0904, 0x36bf, 0x900e, 0x901e, 0x7326, 0x7332, 0xa860, - 0x20e8, 0x7036, 0xa85c, 0x9080, 0x0003, 0x702a, 0x20a0, 0x91d8, - 0x1000, 0x2b5c, 0x8bff, 0x0178, 0x080c, 0x6c11, 0x0118, 0x080c, - 0x6c19, 0x1148, 0x20a9, 0x0001, 0xb814, 0x4004, 0xb810, 0x4004, - 0x4104, 0x9398, 0x0003, 0x8108, 0x9182, 0x0800, 0x0120, 0x9386, - 0x003c, 0x0170, 0x0c20, 0x83ff, 0x1148, 0x7224, 0x900e, 0x2001, - 0x0003, 0x080c, 0x955b, 0x2208, 0x0804, 0x368d, 0x7033, 0x0001, - 0x7122, 0x7024, 0x9300, 0x7026, 0x2061, 0x18b8, 0x2c44, 0xa06b, - 0x0000, 0xa37a, 0x7028, 0xa076, 0x7034, 0xa072, 0xa48e, 0xa592, - 0xa696, 0xa79a, 0x080c, 0x114e, 0x7007, 0x0002, 0x701f, 0x51a9, - 0x0005, 0x7030, 0x9005, 0x1178, 0x7120, 0x7028, 0x20a0, 0x901e, - 0x7034, 0x20e8, 0x2061, 0x18b8, 0x2c44, 0xa48c, 0xa590, 0xa694, - 0xa798, 0x0804, 0x5167, 0x7224, 0x900e, 0x2001, 0x0003, 0x080c, - 0x955b, 0x2208, 0x0804, 0x368d, 0x00f6, 0x00e6, 0x080c, 0x5854, - 0x2009, 0x0007, 0x1904, 0x523c, 0x2071, 0x189e, 0x745c, 0x84ff, - 0x2009, 0x000e, 0x1904, 0x523c, 0xac9c, 0xad98, 0xaea4, 0xafa0, - 0x0096, 0x080c, 0x1072, 0x2009, 0x0002, 0x0904, 0x523c, 0x2900, - 0x705e, 0x900e, 0x901e, 0x7356, 0x7362, 0xa860, 0x7066, 0xa85c, - 0x9080, 0x0003, 0x705a, 0x20a0, 0x91d8, 0x1000, 0x2b5c, 0x8bff, - 0x0178, 0x080c, 0x6c11, 0x0118, 0x080c, 0x6c19, 0x1148, 0xb814, - 0x20a9, 0x0001, 0x4004, 0xb810, 0x4004, 0x4104, 0x9398, 0x0003, - 0x8108, 0x9182, 0x0800, 0x0120, 0x9386, 0x003c, 0x01e8, 0x0c20, - 0x83ff, 0x11c0, 0x7254, 0x900e, 0x2001, 0x0003, 0x080c, 0x955b, - 0x2208, 0x009e, 0xa897, 0x4000, 0xa99a, 0x715c, 0x81ff, 0x090c, - 0x0d85, 0x2148, 0x080c, 0x108b, 0x9006, 0x705e, 0x918d, 0x0001, - 0x2008, 0x0418, 0x7063, 0x0001, 0x7152, 0x7054, 0x9300, 0x7056, - 0x2061, 0x18b9, 0x2c44, 0xa37a, 0x7058, 0xa076, 0x7064, 0xa072, - 0xa48e, 0xa592, 0xa696, 0xa79a, 0xa09f, 0x5248, 0x000e, 0xa0a2, - 0x080c, 0x114e, 0x9006, 0x0048, 0x009e, 0xa897, 0x4005, 0xa99a, - 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x00ee, 0x00fe, 0x0005, - 0x00f6, 0xa0a0, 0x904d, 0x090c, 0x0d85, 0x00e6, 0x2071, 0x189e, - 0xa06c, 0x908e, 0x0100, 0x0138, 0xa87b, 0x0030, 0xa883, 0x0000, - 0xa897, 0x4002, 0x00d8, 0x7060, 0x9005, 0x1158, 0x7150, 0x7058, - 0x20a0, 0x901e, 0x7064, 0x20e8, 0xa48c, 0xa590, 0xa694, 0xa798, - 0x0428, 0xa87b, 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, 0x7254, - 0x900e, 0x2001, 0x0003, 0x080c, 0x955b, 0xaa9a, 0x715c, 0x81ff, - 0x090c, 0x0d85, 0x2148, 0x080c, 0x108b, 0x705f, 0x0000, 0xa0a0, - 0x2048, 0x0126, 0x2091, 0x8000, 0x080c, 0x7012, 0x012e, 0xa09f, - 0x0000, 0xa0a3, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x91d8, 0x1000, - 0x2b5c, 0x8bff, 0x0178, 0x080c, 0x6c11, 0x0118, 0x080c, 0x6c19, - 0x1148, 0xb814, 0x20a9, 0x0001, 0x4004, 0xb810, 0x4004, 0x4104, - 0x9398, 0x0003, 0x8108, 0x9182, 0x0800, 0x0120, 0x9386, 0x003c, - 0x0518, 0x0c20, 0x83ff, 0x11f0, 0x7154, 0x810c, 0xa99a, 0xa897, - 0x4000, 0x715c, 0x81ff, 0x090c, 0x0d85, 0x2148, 0x080c, 0x108b, - 0x9006, 0x705e, 0x918d, 0x0001, 0x2008, 0xa0a0, 0x2048, 0x0126, - 0x2091, 0x8000, 0x080c, 0x7012, 0x012e, 0xa09f, 0x0000, 0xa0a3, - 0x0000, 0x0070, 0x7063, 0x0001, 0x7152, 0x7054, 0x9300, 0x7056, - 0xa37a, 0xa48e, 0xa592, 0xa696, 0xa79a, 0x080c, 0x114e, 0x9006, - 0x00ee, 0x0005, 0x0096, 0xa88c, 0x90be, 0x7000, 0x0148, 0x90be, - 0x7100, 0x0130, 0x90be, 0x7200, 0x0118, 0x009e, 0x0804, 0x36c2, - 0xa884, 0xa988, 0x080c, 0x268c, 0x1518, 0x080c, 0x6749, 0x1500, - 0x7126, 0xbe12, 0xbd16, 0xae7c, 0x080c, 0x4c41, 0x01c8, 0x080c, - 0x4c41, 0x01b0, 0x009e, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, - 0xa823, 0x0000, 0xa804, 0x2048, 0x080c, 0xd0cd, 0x1120, 0x2009, - 0x0003, 0x0804, 0x36bf, 0x7007, 0x0003, 0x701f, 0x5315, 0x0005, - 0x009e, 0x2009, 0x0002, 0x0804, 0x36bf, 0x7124, 0x080c, 0x341e, - 0xa820, 0x9086, 0x8001, 0x1120, 0x2009, 0x0004, 0x0804, 0x36bf, - 0x2900, 0x7022, 0xa804, 0x0096, 0x2048, 0x8906, 0x8006, 0x8007, - 0x90bc, 0x003f, 0x9084, 0xffc0, 0x009e, 0x9080, 0x0002, 0x0076, - 0x0006, 0x2098, 0x20a0, 0x27e0, 0x27e8, 0x20a9, 0x002a, 0x080c, - 0x0fd6, 0xaa6c, 0xab70, 0xac74, 0xad78, 0x2061, 0x18b8, 0x2c44, - 0xa06b, 0x0000, 0xae64, 0xaf8c, 0x97c6, 0x7000, 0x0118, 0x97c6, - 0x7100, 0x1148, 0x96c2, 0x0004, 0x0600, 0x2009, 0x0004, 0x000e, - 0x007e, 0x0804, 0x4c8d, 0x97c6, 0x7200, 0x11b8, 0x96c2, 0x0054, - 0x02a0, 0x000e, 0x007e, 0x2061, 0x18b8, 0x2c44, 0xa076, 0xa772, - 0xa07b, 0x002a, 0xa28e, 0xa392, 0xa496, 0xa59a, 0x080c, 0x114e, - 0x7007, 0x0002, 0x701f, 0x5371, 0x0005, 0x000e, 0x007e, 0x0804, - 0x36c2, 0x7020, 0x2048, 0xa804, 0x2048, 0xa804, 0x2048, 0x8906, - 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, - 0x2098, 0x20a0, 0x27e0, 0x27e8, 0x20a9, 0x002a, 0x080c, 0x0fd6, - 0x2100, 0x2238, 0x2061, 0x18b8, 0x2c44, 0xa28c, 0xa390, 0xa494, - 0xa598, 0x2009, 0x002a, 0x0804, 0x4c8d, 0x81ff, 0x1904, 0x36bf, - 0x798c, 0x2001, 0x197e, 0x918c, 0x8000, 0x2102, 0x080c, 0x4c58, - 0x0904, 0x36c2, 0x080c, 0x6c11, 0x0120, 0x080c, 0x6c19, 0x1904, - 0x36c2, 0x080c, 0x687b, 0x0904, 0x36bf, 0x0126, 0x2091, 0x8000, - 0x080c, 0x6a1b, 0x012e, 0x0904, 0x36bf, 0x2001, 0x197e, 0x2004, - 0xd0fc, 0x1904, 0x368d, 0x0804, 0x46aa, 0xa9a0, 0x2001, 0x197e, - 0x918c, 0x8000, 0xc18d, 0x2102, 0x080c, 0x4c65, 0x01a0, 0x080c, - 0x6c11, 0x0118, 0x080c, 0x6c19, 0x1170, 0x080c, 0x687b, 0x2009, - 0x0002, 0x0128, 0x080c, 0x6a1b, 0x1170, 0x2009, 0x0003, 0xa897, - 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, - 0x2001, 0x0030, 0x0005, 0xa897, 0x4000, 0x2001, 0x197e, 0x2004, - 0xd0fc, 0x1128, 0x080c, 0x5848, 0x0110, 0x9006, 0x0018, 0x900e, - 0x9085, 0x0001, 0x2001, 0x0000, 0x0005, 0x78a8, 0xd08c, 0x1118, - 0xd084, 0x0904, 0x461f, 0x080c, 0x4c74, 0x0904, 0x36c2, 0x080c, - 0x4c41, 0x1120, 0x2009, 0x0002, 0x0804, 0x36bf, 0x080c, 0x6c11, - 0x0130, 0x908e, 0x0004, 0x0118, 0x908e, 0x0005, 0x15a0, 0x78a8, - 0xd08c, 0x0120, 0xb800, 0xc08c, 0xb802, 0x0028, 0x080c, 0x5840, - 0xd0b4, 0x0904, 0x4659, 0x7884, 0x908e, 0x007e, 0x0904, 0x4659, - 0x908e, 0x007f, 0x0904, 0x4659, 0x908e, 0x0080, 0x0904, 0x4659, - 0xb800, 0xd08c, 0x1904, 0x4659, 0xa867, 0x0000, 0xa868, 0xc0fd, - 0xa86a, 0x080c, 0xd0ec, 0x1120, 0x2009, 0x0003, 0x0804, 0x36bf, - 0x7007, 0x0003, 0x701f, 0x543d, 0x0005, 0x080c, 0x4c74, 0x0904, - 0x36c2, 0x0804, 0x4659, 0x080c, 0x347d, 0x0108, 0x0005, 0x2009, - 0x1834, 0x210c, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x36bf, - 0x080c, 0x5854, 0x0120, 0x2009, 0x0007, 0x0804, 0x36bf, 0x080c, - 0x6c09, 0x0120, 0x2009, 0x0008, 0x0804, 0x36bf, 0xb89c, 0xd0a4, - 0x1118, 0xd0ac, 0x1904, 0x4659, 0x9006, 0xa866, 0xa832, 0xa868, - 0xc0fd, 0xa86a, 0x080c, 0xd154, 0x1120, 0x2009, 0x0003, 0x0804, - 0x36bf, 0x7007, 0x0003, 0x701f, 0x5476, 0x0005, 0xa830, 0x9086, - 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x578e, 0x080c, 0x4c74, - 0x0904, 0x36c2, 0x0804, 0x540f, 0x81ff, 0x2009, 0x0001, 0x1904, - 0x36bf, 0x080c, 0x5854, 0x2009, 0x0007, 0x1904, 0x36bf, 0x080c, - 0x6c09, 0x0120, 0x2009, 0x0008, 0x0804, 0x36bf, 0x080c, 0x4c74, - 0x0904, 0x36c2, 0x080c, 0x6c11, 0x2009, 0x0009, 0x1904, 0x36bf, - 0x080c, 0x4c41, 0x2009, 0x0002, 0x0904, 0x36bf, 0x9006, 0xa866, - 0xa832, 0xa868, 0xc0fd, 0xa86a, 0x7988, 0xa95a, 0x9194, 0xfd00, - 0x918c, 0x00ff, 0x9006, 0x82ff, 0x1128, 0xc0ed, 0xa952, 0x798c, - 0xa956, 0x0038, 0x928e, 0x0100, 0x1904, 0x36c2, 0xc0e5, 0xa952, - 0xa956, 0xa83e, 0x080c, 0xd3b7, 0x2009, 0x0003, 0x0904, 0x36bf, - 0x7007, 0x0003, 0x701f, 0x54cd, 0x0005, 0xa830, 0x9086, 0x0100, - 0x2009, 0x0004, 0x0904, 0x36bf, 0x0804, 0x368d, 0x7aa8, 0x9284, - 0xc000, 0x0148, 0xd2ec, 0x01a0, 0x080c, 0x5854, 0x1188, 0x2009, - 0x0014, 0x0804, 0x36bf, 0xd2dc, 0x1578, 0x81ff, 0x2009, 0x0001, - 0x1904, 0x36bf, 0x080c, 0x5854, 0x2009, 0x0007, 0x1904, 0x36bf, - 0xd2f4, 0x0138, 0x9284, 0x5000, 0xc0d5, 0x080c, 0x581a, 0x0804, - 0x368d, 0xd2fc, 0x0160, 0x080c, 0x4c74, 0x0904, 0x36c2, 0x7984, - 0x9284, 0x9000, 0xc0d5, 0x080c, 0x57e9, 0x0804, 0x368d, 0x080c, - 0x4c74, 0x0904, 0x36c2, 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, - 0x2009, 0x0009, 0x1904, 0x55bc, 0x080c, 0x4c41, 0x2009, 0x0002, - 0x0904, 0x55bc, 0xa85c, 0x9080, 0x001b, 0xaf60, 0x2009, 0x0008, - 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x080c, 0x4c8a, 0x701f, 0x5529, - 0x0005, 0xa86c, 0x9086, 0x0500, 0x1138, 0xa870, 0x9005, 0x1120, - 0xa874, 0x9084, 0xff00, 0x0110, 0x1904, 0x36c2, 0xa866, 0xa832, - 0xa868, 0xc0fd, 0xa86a, 0x080c, 0x4c74, 0x1110, 0x0804, 0x36c2, - 0x2009, 0x0043, 0x080c, 0xd423, 0x2009, 0x0003, 0x0904, 0x55bc, - 0x7007, 0x0003, 0x701f, 0x554d, 0x0005, 0xa830, 0x9086, 0x0100, - 0x2009, 0x0004, 0x0904, 0x55bc, 0x7984, 0x7aa8, 0x9284, 0x1000, - 0xc0d5, 0x080c, 0x57e9, 0x0804, 0x368d, 0x00c6, 0xaab0, 0x9284, - 0xc000, 0x0148, 0xd2ec, 0x0170, 0x080c, 0x5854, 0x1158, 0x2009, - 0x0014, 0x0804, 0x55ab, 0x2061, 0x1800, 0x080c, 0x5854, 0x2009, - 0x0007, 0x15c8, 0xd2f4, 0x0130, 0x9284, 0x5000, 0xc0d5, 0x080c, - 0x581a, 0x0058, 0xd2fc, 0x0180, 0x080c, 0x4c72, 0x0590, 0xa998, - 0x9284, 0x9000, 0xc0d5, 0x080c, 0x57e9, 0xa87b, 0x0000, 0xa883, - 0x0000, 0xa897, 0x4000, 0x0438, 0x080c, 0x4c72, 0x0510, 0x080c, - 0x6c11, 0x2009, 0x0009, 0x11b8, 0xa8c4, 0x9086, 0x0500, 0x11c8, - 0xa8c8, 0x9005, 0x11b0, 0xa8cc, 0x9084, 0xff00, 0x1190, 0x080c, - 0x4c72, 0x1108, 0x0070, 0x2009, 0x004b, 0x080c, 0xd423, 0x2009, - 0x0003, 0x0108, 0x0078, 0x0431, 0x19c0, 0xa897, 0x4005, 0xa99a, - 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, - 0x00ce, 0x0005, 0x9006, 0x0ce0, 0x7aa8, 0xd2dc, 0x0904, 0x36bf, - 0x0016, 0x7984, 0x9284, 0x1000, 0xc0fd, 0x080c, 0x57e9, 0x001e, - 0x1904, 0x36bf, 0x0804, 0x368d, 0x00f6, 0x2d78, 0xaab0, 0x0021, - 0x00fe, 0x0005, 0xaab0, 0xc2d5, 0xd2dc, 0x0150, 0x0016, 0xa998, - 0x9284, 0x1400, 0xc0fd, 0x080c, 0x57e9, 0x001e, 0x9085, 0x0001, - 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x36bf, 0x080c, - 0x5854, 0x0120, 0x2009, 0x0007, 0x0804, 0x36bf, 0x7984, 0x7ea8, - 0x96b4, 0x00ff, 0x080c, 0x67b4, 0x1904, 0x36c2, 0x9186, 0x007f, - 0x0138, 0x080c, 0x6c11, 0x0120, 0x2009, 0x0009, 0x0804, 0x36bf, - 0x080c, 0x4c41, 0x1120, 0x2009, 0x0002, 0x0804, 0x36bf, 0xa867, - 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x2001, 0x0100, 0x8007, 0xa80a, - 0x080c, 0xd106, 0x1120, 0x2009, 0x0003, 0x0804, 0x36bf, 0x7007, - 0x0003, 0x701f, 0x561c, 0x0005, 0xa808, 0x8007, 0x9086, 0x0100, - 0x1120, 0x2009, 0x0004, 0x0804, 0x36bf, 0xa8e0, 0xa866, 0xa810, - 0x8007, 0x9084, 0x00ff, 0x800c, 0xa814, 0x8007, 0x9084, 0x00ff, - 0x8004, 0x9080, 0x0002, 0x9108, 0x8906, 0x8006, 0x8007, 0x90bc, - 0x003f, 0x9084, 0xffc0, 0x9080, 0x0004, 0x7a8c, 0x7b88, 0x7c9c, - 0x7d98, 0x0804, 0x4c8d, 0x080c, 0x4c41, 0x1120, 0x2009, 0x0002, - 0x0804, 0x36bf, 0x7984, 0x9194, 0xff00, 0x918c, 0x00ff, 0x8217, - 0x82ff, 0x1118, 0x7023, 0x19b4, 0x0040, 0x92c6, 0x0001, 0x1118, - 0x7023, 0x19ce, 0x0010, 0x0804, 0x36c2, 0x2009, 0x001a, 0x7a8c, - 0x7b88, 0x7c9c, 0x7d98, 0xa85c, 0x9080, 0x0019, 0xaf60, 0x080c, - 0x4c8a, 0x701f, 0x566c, 0x0005, 0x2001, 0x182e, 0x2003, 0x0001, - 0xa85c, 0x9080, 0x0019, 0x2098, 0xa860, 0x20e0, 0x20a9, 0x001a, - 0x7020, 0x20a0, 0x20e9, 0x0001, 0x4003, 0x0804, 0x368d, 0x080c, - 0x4c41, 0x1120, 0x2009, 0x0002, 0x0804, 0x36bf, 0x7984, 0x9194, - 0xff00, 0x918c, 0x00ff, 0x8217, 0x82ff, 0x1118, 0x2099, 0x19b4, - 0x0040, 0x92c6, 0x0001, 0x1118, 0x2099, 0x19ce, 0x0010, 0x0804, - 0x36c2, 0xa85c, 0x9080, 0x0019, 0x20a0, 0xa860, 0x20e8, 0x20a9, - 0x001a, 0x20e1, 0x0001, 0x4003, 0x2009, 0x001a, 0x7a8c, 0x7b88, - 0x7c9c, 0x7d98, 0xa85c, 0x9080, 0x0019, 0xaf60, 0x0804, 0x4c8d, - 0x7884, 0x908a, 0x1000, 0x1a04, 0x36c2, 0x0126, 0x2091, 0x8000, - 0x8003, 0x800b, 0x810b, 0x9108, 0x00c6, 0x2061, 0x1a04, 0x614a, - 0x00ce, 0x012e, 0x0804, 0x368d, 0x00c6, 0x080c, 0x779e, 0x1160, - 0x080c, 0x7ab6, 0x080c, 0x619d, 0x9085, 0x0001, 0x080c, 0x77e2, - 0x080c, 0x76cd, 0x080c, 0x0d85, 0x2061, 0x1800, 0x6030, 0xc09d, - 0x6032, 0x080c, 0x6058, 0x00ce, 0x0005, 0x00c6, 0x2001, 0x1800, - 0x2004, 0x908e, 0x0000, 0x0904, 0x36bf, 0x7884, 0x9005, 0x0188, - 0x7888, 0x2061, 0x199c, 0x2c0c, 0x2062, 0x080c, 0x2a67, 0x01a0, - 0x080c, 0x2a6f, 0x0188, 0x080c, 0x2a77, 0x0170, 0x2162, 0x0804, - 0x36c2, 0x2061, 0x0100, 0x6038, 0x9086, 0x0007, 0x1118, 0x2009, - 0x0001, 0x0010, 0x2009, 0x0000, 0x7884, 0x9086, 0x0002, 0x15a8, - 0x2061, 0x0100, 0x6028, 0xc09c, 0x602a, 0x080c, 0xacfc, 0x0026, - 0x2011, 0x0003, 0x080c, 0xa62b, 0x2011, 0x0002, 0x080c, 0xa635, - 0x002e, 0x080c, 0xa516, 0x0036, 0x901e, 0x080c, 0xa596, 0x003e, - 0x080c, 0xad18, 0x60e3, 0x0000, 0x080c, 0xeed9, 0x080c, 0xeef4, - 0x9085, 0x0001, 0x080c, 0x77e2, 0x9006, 0x080c, 0x2a99, 0x2001, - 0x1800, 0x2003, 0x0004, 0x2001, 0x19a8, 0x2003, 0x0000, 0x0026, - 0x2011, 0x0008, 0x080c, 0x2ad3, 0x002e, 0x00ce, 0x0804, 0x368d, - 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x36bf, 0x080c, 0x5854, - 0x0120, 0x2009, 0x0007, 0x0804, 0x36bf, 0x7984, 0x7ea8, 0x96b4, - 0x00ff, 0x080c, 0x67b4, 0x1904, 0x36c2, 0x9186, 0x007f, 0x0138, - 0x080c, 0x6c11, 0x0120, 0x2009, 0x0009, 0x0804, 0x36bf, 0x080c, - 0x4c41, 0x1120, 0x2009, 0x0002, 0x0804, 0x36bf, 0xa867, 0x0000, - 0xa868, 0xc0fd, 0xa86a, 0x080c, 0xd109, 0x1120, 0x2009, 0x0003, - 0x0804, 0x36bf, 0x7007, 0x0003, 0x701f, 0x5777, 0x0005, 0xa830, - 0x9086, 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x36bf, 0xa8e0, - 0xa866, 0xa834, 0x8007, 0x800c, 0xa85c, 0x9080, 0x000c, 0x7a8c, - 0x7b88, 0x7c9c, 0x7d98, 0xaf60, 0x0804, 0x4c8d, 0xa898, 0x9086, - 0x000d, 0x1904, 0x36bf, 0x2021, 0x4005, 0x0126, 0x2091, 0x8000, - 0x0e04, 0x579b, 0x0010, 0x012e, 0x0cc0, 0x7c36, 0x9486, 0x4000, - 0x0118, 0x7833, 0x0011, 0x0010, 0x7833, 0x0010, 0x7883, 0x4005, - 0xa998, 0x7986, 0xa9a4, 0x799a, 0xa9a8, 0x799e, 0x080c, 0x4c7d, - 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1200, - 0x7007, 0x0001, 0x2091, 0x5000, 0x700f, 0x0000, 0x012e, 0x0005, - 0x0126, 0x2091, 0x8000, 0x00c6, 0x2061, 0x1a04, 0x7984, 0x615a, - 0x6156, 0x605f, 0x0000, 0x6053, 0x0009, 0x7898, 0x6072, 0x789c, - 0x606e, 0x7888, 0x606a, 0x788c, 0x6066, 0x2001, 0x1a14, 0x2044, - 0x2001, 0x1a1b, 0xa076, 0xa060, 0xa072, 0xa07b, 0x0001, 0xa07f, - 0x0002, 0xa06b, 0x0000, 0xa09f, 0x0000, 0x00ce, 0x012e, 0x0804, - 0x368d, 0x0126, 0x2091, 0x8000, 0x00b6, 0x00c6, 0x90e4, 0xc000, - 0x0198, 0x0006, 0xd0d4, 0x0160, 0x0036, 0x2019, 0x0029, 0x080c, - 0xacfc, 0x0106, 0x080c, 0x3442, 0x010e, 0x090c, 0xad18, 0x003e, - 0x080c, 0xcf68, 0x000e, 0x1198, 0xd0e4, 0x0160, 0x9180, 0x1000, - 0x2004, 0x905d, 0x0160, 0x080c, 0x61b7, 0x080c, 0xb094, 0x0110, - 0xb817, 0x0000, 0x9006, 0x00ce, 0x00be, 0x012e, 0x0005, 0x9085, - 0x0001, 0x0cc8, 0x0126, 0x2091, 0x8000, 0x0156, 0x2010, 0x900e, - 0x20a9, 0x0800, 0x0016, 0x9180, 0x1000, 0x2004, 0x9005, 0x0188, - 0x9186, 0x007e, 0x0170, 0x9186, 0x007f, 0x0158, 0x9186, 0x0080, - 0x0140, 0x9186, 0x00ff, 0x0128, 0x0026, 0x2200, 0x080c, 0x57e9, - 0x002e, 0x001e, 0x8108, 0x1f04, 0x5822, 0x015e, 0x012e, 0x0005, - 0x2001, 0x1848, 0x2004, 0x0005, 0x2001, 0x1867, 0x2004, 0x0005, - 0x0006, 0x2001, 0x1810, 0x2004, 0xd0d4, 0x000e, 0x0005, 0x2001, - 0x180e, 0x2004, 0xd0b4, 0x0005, 0x2001, 0x1800, 0x2004, 0x9086, - 0x0003, 0x0005, 0x0016, 0x00e6, 0x2071, 0x189e, 0x7108, 0x910d, - 0x710a, 0x00ee, 0x001e, 0x0005, 0x79a4, 0x81ff, 0x0904, 0x36c2, - 0x9182, 0x0081, 0x1a04, 0x36c2, 0x810c, 0x0016, 0x080c, 0x4c41, - 0x0170, 0x080c, 0x0f61, 0x2100, 0x2238, 0x7d84, 0x7c88, 0x7b8c, - 0x7a90, 0x001e, 0x080c, 0x4c8a, 0x701f, 0x5884, 0x0005, 0x001e, - 0x2009, 0x0002, 0x0804, 0x36bf, 0x2079, 0x0000, 0x7d94, 0x7c98, - 0x7ba8, 0x7aac, 0x79a4, 0x810c, 0x2061, 0x18b8, 0x2c44, 0xa770, - 0xa074, 0x2071, 0x189e, 0x080c, 0x4c8d, 0x701f, 0x5898, 0x0005, - 0x2061, 0x18b8, 0x2c44, 0x0016, 0x0026, 0xa270, 0xa174, 0x080c, - 0x0f69, 0x002e, 0x001e, 0x080c, 0x1016, 0x9006, 0xa802, 0xa806, - 0x0804, 0x368d, 0x0126, 0x0156, 0x0136, 0x0146, 0x01c6, 0x01d6, - 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2061, 0x0100, 0x2069, 0x0200, - 0x2071, 0x1800, 0x6044, 0xd0a4, 0x11e8, 0xd084, 0x0118, 0x080c, - 0x5a58, 0x0068, 0xd08c, 0x0118, 0x080c, 0x5961, 0x0040, 0xd094, - 0x0118, 0x080c, 0x5931, 0x0018, 0xd09c, 0x0108, 0x0099, 0x00fe, - 0x00ee, 0x00de, 0x00ce, 0x01de, 0x01ce, 0x014e, 0x013e, 0x015e, - 0x012e, 0x0005, 0x0016, 0x6128, 0xd19c, 0x1110, 0xc19d, 0x612a, - 0x001e, 0x0c68, 0x7030, 0xd09c, 0x1120, 0x6004, 0x9085, 0x0002, - 0x6006, 0x7098, 0x9005, 0x0120, 0x709b, 0x0000, 0x7093, 0x0000, - 0x624c, 0x9286, 0xf0f0, 0x1150, 0x6048, 0x9086, 0xf0f0, 0x0130, - 0x624a, 0x6043, 0x0090, 0x6043, 0x0010, 0x0490, 0x9294, 0xff00, - 0x9296, 0xf700, 0x0178, 0x7138, 0xd1a4, 0x1160, 0x6240, 0x9295, - 0x0100, 0x6242, 0x9294, 0x0010, 0x0128, 0x2009, 0x00f7, 0x080c, - 0x6119, 0x00f0, 0x6040, 0x9084, 0x0010, 0x9085, 0x0140, 0x6042, - 0x6043, 0x0000, 0x7087, 0x0000, 0x70a3, 0x0001, 0x70c7, 0x0000, - 0x70df, 0x0000, 0x2009, 0x1d80, 0x200b, 0x0000, 0x7097, 0x0000, - 0x708b, 0x000f, 0x2009, 0x000f, 0x2011, 0x5ffb, 0x080c, 0x8a5d, - 0x0005, 0x2001, 0x1869, 0x2004, 0xd08c, 0x0110, 0x705f, 0xffff, - 0x7088, 0x9005, 0x1528, 0x2011, 0x5ffb, 0x080c, 0x8993, 0x6040, - 0x9094, 0x0010, 0x9285, 0x0020, 0x6042, 0x20a9, 0x00c8, 0x6044, - 0xd08c, 0x1168, 0x1f04, 0x5947, 0x6242, 0x709b, 0x0000, 0x6040, - 0x9094, 0x0010, 0x9285, 0x0080, 0x6042, 0x6242, 0x0048, 0x6242, - 0x709b, 0x0000, 0x708f, 0x0000, 0x9006, 0x080c, 0x61a2, 0x0000, - 0x0005, 0x708c, 0x908a, 0x0003, 0x1a0c, 0x0d85, 0x000b, 0x0005, - 0x596b, 0x59bc, 0x5a57, 0x00f6, 0x0016, 0x6900, 0x918c, 0x0800, - 0x708f, 0x0001, 0x2001, 0x015d, 0x2003, 0x0000, 0x6803, 0x00fc, - 0x20a9, 0x0004, 0x6800, 0x9084, 0x00fc, 0x0120, 0x1f04, 0x597a, - 0x080c, 0x0d85, 0x68a0, 0x68a2, 0x689c, 0x689e, 0x6898, 0x689a, - 0xa001, 0x918d, 0x1600, 0x6902, 0x001e, 0x6837, 0x0020, 0x080c, - 0x617e, 0x2079, 0x1d00, 0x7833, 0x1101, 0x7837, 0x0000, 0x20e1, - 0x0001, 0x2099, 0x1805, 0x20e9, 0x0001, 0x20a1, 0x1d0e, 0x20a9, - 0x0004, 0x4003, 0x080c, 0xaaf1, 0x20e1, 0x0001, 0x2099, 0x1d00, - 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x0014, 0x4003, 0x60c3, - 0x000c, 0x600f, 0x0000, 0x080c, 0x602c, 0x00fe, 0x9006, 0x7092, - 0x6043, 0x0008, 0x6042, 0x0005, 0x00f6, 0x7090, 0x7093, 0x0000, - 0x9025, 0x0904, 0x5a34, 0x6020, 0xd0b4, 0x1904, 0x5a32, 0x71a0, - 0x81ff, 0x0904, 0x5a20, 0x9486, 0x000c, 0x1904, 0x5a2d, 0x9480, - 0x0018, 0x8004, 0x20a8, 0x080c, 0x6177, 0x2011, 0x0260, 0x2019, - 0x1d00, 0x220c, 0x2304, 0x9106, 0x11e8, 0x8210, 0x8318, 0x1f04, - 0x59d9, 0x6043, 0x0004, 0x2061, 0x0140, 0x605b, 0xbc94, 0x605f, - 0xf0f0, 0x2061, 0x0100, 0x6043, 0x0006, 0x708f, 0x0002, 0x709b, - 0x0002, 0x2009, 0x07d0, 0x2011, 0x6002, 0x080c, 0x8a5d, 0x080c, - 0x617e, 0x04c0, 0x080c, 0x6177, 0x2079, 0x0260, 0x7930, 0x918e, - 0x1101, 0x1558, 0x7834, 0x9005, 0x1540, 0x7900, 0x918c, 0x00ff, - 0x1118, 0x7804, 0x9005, 0x0190, 0x080c, 0x6177, 0x2011, 0x026e, - 0x2019, 0x1805, 0x20a9, 0x0004, 0x220c, 0x2304, 0x9102, 0x0230, - 0x11a0, 0x8210, 0x8318, 0x1f04, 0x5a14, 0x0078, 0x70a3, 0x0000, - 0x080c, 0x6177, 0x20e1, 0x0000, 0x2099, 0x0260, 0x20e9, 0x0001, - 0x20a1, 0x1d00, 0x20a9, 0x0014, 0x4003, 0x6043, 0x0008, 0x6043, - 0x0000, 0x0010, 0x00fe, 0x0005, 0x6040, 0x9085, 0x0100, 0x6042, - 0x6020, 0xd0b4, 0x1db8, 0x080c, 0xaaf1, 0x20e1, 0x0001, 0x2099, - 0x1d00, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x0014, 0x4003, - 0x60c3, 0x000c, 0x2011, 0x19f5, 0x2013, 0x0000, 0x7093, 0x0000, - 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, 0xa293, 0x08d8, 0x0005, - 0x7098, 0x908a, 0x001d, 0x1a0c, 0x0d85, 0x000b, 0x0005, 0x5a89, - 0x5a9c, 0x5ac5, 0x5ae5, 0x5b0b, 0x5b3a, 0x5b60, 0x5b98, 0x5bbe, - 0x5bec, 0x5c27, 0x5c5f, 0x5c7d, 0x5ca8, 0x5cca, 0x5ce5, 0x5cef, - 0x5d23, 0x5d49, 0x5d78, 0x5d9e, 0x5dd6, 0x5e1a, 0x5e57, 0x5e78, - 0x5ed1, 0x5ef3, 0x5f21, 0x5f21, 0x00c6, 0x2061, 0x1800, 0x6003, - 0x0007, 0x2061, 0x0100, 0x6004, 0x9084, 0xfff9, 0x6006, 0x00ce, - 0x0005, 0x2061, 0x0140, 0x605b, 0xbc94, 0x605f, 0xf0f0, 0x2061, - 0x0100, 0x6043, 0x0002, 0x709b, 0x0001, 0x2009, 0x07d0, 0x2011, - 0x6002, 0x080c, 0x8a5d, 0x0005, 0x00f6, 0x7090, 0x9086, 0x0014, - 0x1510, 0x6042, 0x6020, 0xd0b4, 0x11f0, 0x080c, 0x6177, 0x2079, - 0x0260, 0x7a30, 0x9296, 0x1102, 0x11a0, 0x7834, 0x9005, 0x1188, - 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, - 0x2011, 0x6002, 0x080c, 0x8993, 0x709b, 0x0010, 0x080c, 0x5cef, - 0x0010, 0x7093, 0x0000, 0x00fe, 0x0005, 0x00f6, 0x709b, 0x0003, - 0x6043, 0x0004, 0x2011, 0x6002, 0x080c, 0x8993, 0x080c, 0x60fb, - 0x2079, 0x0240, 0x7833, 0x1102, 0x7837, 0x0000, 0x20a9, 0x0008, - 0x9f88, 0x000e, 0x200b, 0x0000, 0x8108, 0x1f04, 0x5ada, 0x60c3, - 0x0014, 0x080c, 0x602c, 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, - 0x0500, 0x2011, 0x6002, 0x080c, 0x8993, 0x9086, 0x0014, 0x11b8, - 0x080c, 0x6177, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1102, 0x1178, - 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, - 0x1110, 0x70c7, 0x0001, 0x709b, 0x0004, 0x0029, 0x0010, 0x080c, - 0x6153, 0x00fe, 0x0005, 0x00f6, 0x709b, 0x0005, 0x080c, 0x60fb, - 0x2079, 0x0240, 0x7833, 0x1103, 0x7837, 0x0000, 0x080c, 0x6177, - 0x080c, 0x615a, 0x1170, 0x7084, 0x9005, 0x1158, 0x715c, 0x9186, - 0xffff, 0x0138, 0x2011, 0x0008, 0x080c, 0x5faf, 0x0168, 0x080c, - 0x6130, 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, - 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x602c, - 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, 0x0500, 0x2011, 0x6002, - 0x080c, 0x8993, 0x9086, 0x0014, 0x11b8, 0x080c, 0x6177, 0x2079, - 0x0260, 0x7a30, 0x9296, 0x1103, 0x1178, 0x7834, 0x9005, 0x1160, - 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, - 0x709b, 0x0006, 0x0029, 0x0010, 0x080c, 0x6153, 0x00fe, 0x0005, - 0x00f6, 0x709b, 0x0007, 0x080c, 0x60fb, 0x2079, 0x0240, 0x7833, - 0x1104, 0x7837, 0x0000, 0x080c, 0x6177, 0x080c, 0x615a, 0x11b8, - 0x7084, 0x9005, 0x11a0, 0x7164, 0x9186, 0xffff, 0x0180, 0x9180, - 0x348e, 0x200d, 0x918c, 0xff00, 0x810f, 0x2011, 0x0008, 0x080c, - 0x5faf, 0x0180, 0x080c, 0x512e, 0x0110, 0x080c, 0x26f5, 0x20a9, - 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, - 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x602c, 0x00fe, 0x0005, - 0x00f6, 0x7090, 0x9005, 0x0500, 0x2011, 0x6002, 0x080c, 0x8993, - 0x9086, 0x0014, 0x11b8, 0x080c, 0x6177, 0x2079, 0x0260, 0x7a30, - 0x9296, 0x1104, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, - 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, 0x709b, 0x0008, - 0x0029, 0x0010, 0x080c, 0x6153, 0x00fe, 0x0005, 0x00f6, 0x709b, - 0x0009, 0x080c, 0x60fb, 0x2079, 0x0240, 0x7833, 0x1105, 0x7837, - 0x0100, 0x080c, 0x615a, 0x1150, 0x7084, 0x9005, 0x1138, 0x080c, - 0x5f22, 0x1188, 0x9085, 0x0001, 0x080c, 0x26f5, 0x20a9, 0x0008, - 0x080c, 0x6177, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, - 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x602c, 0x0010, - 0x080c, 0x5a7c, 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, 0x05a8, - 0x2011, 0x6002, 0x080c, 0x8993, 0x9086, 0x0014, 0x1560, 0x080c, - 0x6177, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1105, 0x1520, 0x7834, - 0x9084, 0x0100, 0x2011, 0x0100, 0x921e, 0x1160, 0x7a38, 0xd2fc, - 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, 0x709b, 0x000a, - 0x00b1, 0x0098, 0x9005, 0x1178, 0x7a38, 0xd2fc, 0x0128, 0x70c4, - 0x9005, 0x1110, 0x70c7, 0x0001, 0x7097, 0x0000, 0x709b, 0x000e, - 0x080c, 0x5cca, 0x0010, 0x080c, 0x6153, 0x00fe, 0x0005, 0x00f6, - 0x709b, 0x000b, 0x2011, 0x1d0e, 0x20e9, 0x0001, 0x22a0, 0x20a9, - 0x0040, 0x2019, 0xffff, 0x4304, 0x080c, 0x60fb, 0x2079, 0x0240, - 0x7833, 0x1106, 0x7837, 0x0000, 0x080c, 0x615a, 0x0118, 0x2013, - 0x0000, 0x0020, 0x7060, 0x9085, 0x0100, 0x2012, 0x20a9, 0x0040, - 0x2009, 0x024e, 0x2011, 0x1d0e, 0x220e, 0x8210, 0x8108, 0x9186, - 0x0260, 0x1128, 0x6810, 0x8000, 0x6812, 0x2009, 0x0240, 0x1f04, - 0x5c4c, 0x60c3, 0x0084, 0x080c, 0x602c, 0x00fe, 0x0005, 0x00f6, - 0x7090, 0x9005, 0x01c0, 0x2011, 0x6002, 0x080c, 0x8993, 0x9086, - 0x0084, 0x1178, 0x080c, 0x6177, 0x2079, 0x0260, 0x7a30, 0x9296, - 0x1106, 0x1138, 0x7834, 0x9005, 0x1120, 0x709b, 0x000c, 0x0029, - 0x0010, 0x080c, 0x6153, 0x00fe, 0x0005, 0x00f6, 0x709b, 0x000d, - 0x080c, 0x60fb, 0x2079, 0x0240, 0x7833, 0x1107, 0x7837, 0x0000, - 0x080c, 0x6177, 0x20a9, 0x0040, 0x2011, 0x026e, 0x2009, 0x024e, - 0x220e, 0x8210, 0x8108, 0x9186, 0x0260, 0x1150, 0x6810, 0x8000, - 0x6812, 0x2009, 0x0240, 0x6814, 0x8000, 0x6816, 0x2011, 0x0260, - 0x1f04, 0x5c90, 0x60c3, 0x0084, 0x080c, 0x602c, 0x00fe, 0x0005, - 0x00f6, 0x7090, 0x9005, 0x01e0, 0x2011, 0x6002, 0x080c, 0x8993, - 0x9086, 0x0084, 0x1198, 0x080c, 0x6177, 0x2079, 0x0260, 0x7a30, - 0x9296, 0x1107, 0x1158, 0x7834, 0x9005, 0x1140, 0x7097, 0x0001, - 0x080c, 0x60cd, 0x709b, 0x000e, 0x0029, 0x0010, 0x080c, 0x6153, - 0x00fe, 0x0005, 0x918d, 0x0001, 0x080c, 0x61a2, 0x709b, 0x000f, - 0x7093, 0x0000, 0x2061, 0x0140, 0x605b, 0xbc85, 0x605f, 0xb5b5, - 0x2061, 0x0100, 0x6043, 0x0005, 0x6043, 0x0004, 0x2009, 0x07d0, - 0x2011, 0x6002, 0x080c, 0x8987, 0x0005, 0x7090, 0x9005, 0x0130, - 0x2011, 0x6002, 0x080c, 0x8993, 0x709b, 0x0000, 0x0005, 0x709b, - 0x0011, 0x080c, 0xaaf1, 0x080c, 0x6177, 0x20e1, 0x0000, 0x2099, - 0x0260, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x7490, 0x9480, 0x0018, - 0x9080, 0x0007, 0x9084, 0x03f8, 0x8004, 0x20a8, 0x4003, 0x080c, - 0x615a, 0x11a0, 0x717c, 0x81ff, 0x0188, 0x900e, 0x7080, 0x9084, - 0x00ff, 0x0160, 0x080c, 0x268c, 0x9186, 0x007e, 0x0138, 0x9186, - 0x0080, 0x0120, 0x2011, 0x0008, 0x080c, 0x5faf, 0x60c3, 0x0014, - 0x080c, 0x602c, 0x0005, 0x00f6, 0x7090, 0x9005, 0x0500, 0x2011, - 0x6002, 0x080c, 0x8993, 0x9086, 0x0014, 0x11b8, 0x080c, 0x6177, - 0x2079, 0x0260, 0x7a30, 0x9296, 0x1103, 0x1178, 0x7834, 0x9005, - 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, - 0x0001, 0x709b, 0x0012, 0x0029, 0x0010, 0x7093, 0x0000, 0x00fe, - 0x0005, 0x00f6, 0x709b, 0x0013, 0x080c, 0x6109, 0x2079, 0x0240, - 0x7833, 0x1103, 0x7837, 0x0000, 0x080c, 0x6177, 0x080c, 0x615a, - 0x1170, 0x7084, 0x9005, 0x1158, 0x715c, 0x9186, 0xffff, 0x0138, - 0x2011, 0x0008, 0x080c, 0x5faf, 0x0168, 0x080c, 0x6130, 0x20a9, - 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, - 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x602c, 0x00fe, 0x0005, - 0x00f6, 0x7090, 0x9005, 0x0500, 0x2011, 0x6002, 0x080c, 0x8993, - 0x9086, 0x0014, 0x11b8, 0x080c, 0x6177, 0x2079, 0x0260, 0x7a30, - 0x9296, 0x1104, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, - 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, 0x709b, 0x0014, - 0x0029, 0x0010, 0x7093, 0x0000, 0x00fe, 0x0005, 0x00f6, 0x709b, - 0x0015, 0x080c, 0x6109, 0x2079, 0x0240, 0x7833, 0x1104, 0x7837, - 0x0000, 0x080c, 0x6177, 0x080c, 0x615a, 0x11b8, 0x7084, 0x9005, - 0x11a0, 0x7164, 0x9186, 0xffff, 0x0180, 0x9180, 0x348e, 0x200d, - 0x918c, 0xff00, 0x810f, 0x2011, 0x0008, 0x080c, 0x5faf, 0x0180, - 0x080c, 0x512e, 0x0110, 0x080c, 0x26f5, 0x20a9, 0x0008, 0x20e1, - 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, - 0x60c3, 0x0014, 0x080c, 0x602c, 0x00fe, 0x0005, 0x00f6, 0x7090, - 0x9005, 0x05f0, 0x2011, 0x6002, 0x080c, 0x8993, 0x9086, 0x0014, - 0x15a8, 0x080c, 0x6177, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1105, - 0x1568, 0x7834, 0x9084, 0x0100, 0x2011, 0x0100, 0x921e, 0x1168, - 0x9085, 0x0001, 0x080c, 0x61a2, 0x7a38, 0xd2fc, 0x0128, 0x70c4, - 0x9005, 0x1110, 0x70c7, 0x0001, 0x0080, 0x9005, 0x11b8, 0x7a38, - 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, 0x9085, - 0x0001, 0x080c, 0x61a2, 0x7097, 0x0000, 0x7a38, 0xd2f4, 0x0110, - 0x70df, 0x0008, 0x709b, 0x0016, 0x0029, 0x0010, 0x7093, 0x0000, - 0x00fe, 0x0005, 0x080c, 0xaaf1, 0x080c, 0x6177, 0x20e1, 0x0000, - 0x2099, 0x0260, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000e, - 0x4003, 0x2011, 0x026d, 0x2204, 0x9084, 0x0100, 0x2011, 0x024d, - 0x2012, 0x2011, 0x026e, 0x709b, 0x0017, 0x080c, 0x615a, 0x1150, - 0x7084, 0x9005, 0x1138, 0x080c, 0x5f22, 0x1188, 0x9085, 0x0001, - 0x080c, 0x26f5, 0x20a9, 0x0008, 0x080c, 0x6177, 0x20e1, 0x0000, - 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, - 0x0014, 0x080c, 0x602c, 0x0010, 0x080c, 0x5a7c, 0x0005, 0x00f6, - 0x7090, 0x9005, 0x01d8, 0x2011, 0x6002, 0x080c, 0x8993, 0x9086, - 0x0084, 0x1190, 0x080c, 0x6177, 0x2079, 0x0260, 0x7a30, 0x9296, - 0x1106, 0x1150, 0x7834, 0x9005, 0x1138, 0x9006, 0x080c, 0x61a2, - 0x709b, 0x0018, 0x0029, 0x0010, 0x7093, 0x0000, 0x00fe, 0x0005, - 0x00f6, 0x709b, 0x0019, 0x080c, 0x6109, 0x2079, 0x0240, 0x7833, - 0x1106, 0x7837, 0x0000, 0x080c, 0x6177, 0x2009, 0x026e, 0x2039, - 0x1d0e, 0x20a9, 0x0040, 0x213e, 0x8738, 0x8108, 0x9186, 0x0280, - 0x1128, 0x6814, 0x8000, 0x6816, 0x2009, 0x0260, 0x1f04, 0x5e8b, - 0x2039, 0x1d0e, 0x080c, 0x615a, 0x11e8, 0x2728, 0x2514, 0x8207, - 0x9084, 0x00ff, 0x8000, 0x2018, 0x9294, 0x00ff, 0x8007, 0x9205, - 0x202a, 0x7060, 0x2310, 0x8214, 0x92a0, 0x1d0e, 0x2414, 0x938c, - 0x0001, 0x0118, 0x9294, 0xff00, 0x0018, 0x9294, 0x00ff, 0x8007, - 0x9215, 0x2222, 0x20a9, 0x0040, 0x2009, 0x024e, 0x270e, 0x8738, - 0x8108, 0x9186, 0x0260, 0x1128, 0x6810, 0x8000, 0x6812, 0x2009, - 0x0240, 0x1f04, 0x5ebe, 0x60c3, 0x0084, 0x080c, 0x602c, 0x00fe, - 0x0005, 0x00f6, 0x7090, 0x9005, 0x01e0, 0x2011, 0x6002, 0x080c, - 0x8993, 0x9086, 0x0084, 0x1198, 0x080c, 0x6177, 0x2079, 0x0260, - 0x7a30, 0x9296, 0x1107, 0x1158, 0x7834, 0x9005, 0x1140, 0x7097, - 0x0001, 0x080c, 0x60cd, 0x709b, 0x001a, 0x0029, 0x0010, 0x7093, - 0x0000, 0x00fe, 0x0005, 0x9085, 0x0001, 0x080c, 0x61a2, 0x709b, - 0x001b, 0x080c, 0xaaf1, 0x080c, 0x6177, 0x2011, 0x0260, 0x2009, - 0x0240, 0x7490, 0x9480, 0x0018, 0x9080, 0x0007, 0x9084, 0x03f8, - 0x8004, 0x20a8, 0x220e, 0x8210, 0x8108, 0x9186, 0x0260, 0x1150, - 0x6810, 0x8000, 0x6812, 0x2009, 0x0240, 0x6814, 0x8000, 0x6816, - 0x2011, 0x0260, 0x1f04, 0x5f0a, 0x60c3, 0x0084, 0x080c, 0x602c, - 0x0005, 0x0005, 0x0086, 0x0096, 0x2029, 0x1848, 0x252c, 0x20a9, - 0x0008, 0x2041, 0x1d0e, 0x20e9, 0x0001, 0x28a0, 0x080c, 0x6177, - 0x20e1, 0x0000, 0x2099, 0x026e, 0x4003, 0x20a9, 0x0008, 0x2011, - 0x0007, 0xd5d4, 0x0108, 0x9016, 0x2800, 0x9200, 0x200c, 0x91a6, - 0xffff, 0x1148, 0xd5d4, 0x0110, 0x8210, 0x0008, 0x8211, 0x1f04, - 0x5f3c, 0x0804, 0x5fab, 0x82ff, 0x1160, 0xd5d4, 0x0120, 0x91a6, - 0x3fff, 0x0d90, 0x0020, 0x91a6, 0x3fff, 0x0904, 0x5fab, 0x918d, - 0xc000, 0x20a9, 0x0010, 0x2019, 0x0001, 0xd5d4, 0x0110, 0x2019, - 0x0010, 0x2120, 0xd5d4, 0x0110, 0x8423, 0x0008, 0x8424, 0x1240, - 0xd5d4, 0x0110, 0x8319, 0x0008, 0x8318, 0x1f04, 0x5f62, 0x04d8, - 0x23a8, 0x2021, 0x0001, 0x8426, 0x8425, 0x1f04, 0x5f74, 0x2328, - 0x8529, 0x92be, 0x0007, 0x0158, 0x0006, 0x2039, 0x0007, 0x2200, - 0x973a, 0x000e, 0x27a8, 0x95a8, 0x0010, 0x1f04, 0x5f83, 0x755e, - 0x95c8, 0x348e, 0x292d, 0x95ac, 0x00ff, 0x7582, 0x6532, 0x6536, - 0x0016, 0x2508, 0x080c, 0x26d5, 0x001e, 0x60e7, 0x0000, 0x65ea, - 0x2018, 0x2304, 0x9405, 0x201a, 0x7087, 0x0001, 0x20e9, 0x0000, - 0x20a1, 0x024e, 0x20e1, 0x0001, 0x2898, 0x20a9, 0x0008, 0x4003, - 0x9085, 0x0001, 0x0008, 0x9006, 0x009e, 0x008e, 0x0005, 0x0156, - 0x01c6, 0x01d6, 0x0136, 0x0146, 0x22a8, 0x20e1, 0x0000, 0x2099, - 0x026e, 0x20e9, 0x0000, 0x2011, 0x024e, 0x22a0, 0x4003, 0x014e, - 0x013e, 0x01de, 0x01ce, 0x015e, 0x2118, 0x9026, 0x2001, 0x0007, - 0x939a, 0x0010, 0x0218, 0x8420, 0x8001, 0x0cd0, 0x2118, 0x84ff, - 0x0120, 0x939a, 0x0010, 0x8421, 0x1de0, 0x2021, 0x0001, 0x83ff, - 0x0118, 0x8423, 0x8319, 0x1de8, 0x9238, 0x2029, 0x026e, 0x9528, - 0x2504, 0x942c, 0x11b8, 0x9405, 0x203a, 0x715e, 0x91a0, 0x348e, - 0x242d, 0x95ac, 0x00ff, 0x7582, 0x6532, 0x6536, 0x0016, 0x2508, - 0x080c, 0x26d5, 0x001e, 0x60e7, 0x0000, 0x65ea, 0x7087, 0x0001, - 0x9084, 0x0000, 0x0005, 0x00e6, 0x2071, 0x1800, 0x708b, 0x0000, - 0x00ee, 0x0005, 0x00e6, 0x00f6, 0x2079, 0x0100, 0x2071, 0x0140, - 0x080c, 0x60bc, 0x080c, 0xa2a0, 0x7004, 0x9084, 0x4000, 0x0110, - 0x080c, 0x2aa9, 0x0126, 0x2091, 0x8000, 0x2071, 0x1826, 0x2073, - 0x0000, 0x7840, 0x0026, 0x0016, 0x2009, 0x00f7, 0x080c, 0x6119, - 0x001e, 0x9094, 0x0010, 0x9285, 0x0080, 0x7842, 0x7a42, 0x002e, - 0x012e, 0x00fe, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, - 0x2a04, 0x0228, 0x2011, 0x0101, 0x2204, 0xc0c5, 0x2012, 0x2011, - 0x19f5, 0x2013, 0x0000, 0x7093, 0x0000, 0x012e, 0x60a3, 0x0056, - 0x60a7, 0x9575, 0x080c, 0xa293, 0x6144, 0xd184, 0x0120, 0x7198, - 0x918d, 0x2000, 0x0018, 0x718c, 0x918d, 0x1000, 0x2011, 0x1999, - 0x2112, 0x2009, 0x07d0, 0x2011, 0x6002, 0x080c, 0x8a5d, 0x0005, - 0x0016, 0x0026, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0xacfc, - 0x080c, 0xb09b, 0x080c, 0xad18, 0x2009, 0x00f7, 0x080c, 0x6119, - 0x2061, 0x1a04, 0x900e, 0x611a, 0x611e, 0x617a, 0x617e, 0x2061, - 0x1800, 0x6003, 0x0001, 0x2061, 0x0100, 0x6043, 0x0090, 0x6043, - 0x0010, 0x2009, 0x1999, 0x200b, 0x0000, 0x2009, 0x002d, 0x2011, - 0x6088, 0x080c, 0x8987, 0x012e, 0x00ce, 0x002e, 0x001e, 0x0005, - 0x00e6, 0x0006, 0x0126, 0x2091, 0x8000, 0x0471, 0x2071, 0x0100, - 0x080c, 0xa2a0, 0x2071, 0x0140, 0x7004, 0x9084, 0x4000, 0x0110, - 0x080c, 0x2aa9, 0x080c, 0x77a6, 0x0188, 0x080c, 0x77c1, 0x1170, - 0x080c, 0x7ac0, 0x0016, 0x080c, 0x27a4, 0x2001, 0x196d, 0x2102, - 0x001e, 0x080c, 0x7abb, 0x080c, 0x76cd, 0x0050, 0x2009, 0x0001, - 0x080c, 0x2a85, 0x2001, 0x0001, 0x080c, 0x2631, 0x080c, 0x6058, - 0x012e, 0x000e, 0x00ee, 0x0005, 0x2001, 0x180e, 0x2004, 0xd0bc, - 0x0158, 0x0026, 0x0036, 0x2011, 0x8017, 0x2001, 0x1999, 0x201c, - 0x080c, 0x4ca1, 0x003e, 0x002e, 0x0005, 0x20a9, 0x0012, 0x20e9, - 0x0001, 0x20a1, 0x1d80, 0x080c, 0x6177, 0x20e9, 0x0000, 0x2099, - 0x026e, 0x0099, 0x20a9, 0x0020, 0x080c, 0x6171, 0x2099, 0x0260, - 0x20a1, 0x1d92, 0x0051, 0x20a9, 0x000e, 0x080c, 0x6174, 0x2099, - 0x0260, 0x20a1, 0x1db2, 0x0009, 0x0005, 0x0016, 0x0026, 0x3410, - 0x3308, 0x2104, 0x8007, 0x2012, 0x8108, 0x8210, 0x1f04, 0x60f1, - 0x002e, 0x001e, 0x0005, 0x080c, 0xaaf1, 0x20e1, 0x0001, 0x2099, - 0x1d00, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000c, 0x4003, - 0x0005, 0x080c, 0xaaf1, 0x080c, 0x6177, 0x20e1, 0x0000, 0x2099, - 0x0260, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000c, 0x4003, - 0x0005, 0x00c6, 0x0006, 0x2061, 0x0100, 0x810f, 0x2001, 0x1834, - 0x2004, 0x9005, 0x1138, 0x2001, 0x1818, 0x2004, 0x9084, 0x00ff, - 0x9105, 0x0010, 0x9185, 0x00f7, 0x604a, 0x000e, 0x00ce, 0x0005, - 0x0016, 0x0046, 0x080c, 0x6c0d, 0x0158, 0x9006, 0x2020, 0x2009, - 0x002a, 0x080c, 0xea8d, 0x2001, 0x180c, 0x200c, 0xc195, 0x2102, - 0x2019, 0x002a, 0x900e, 0x080c, 0x32da, 0x080c, 0xd645, 0x0140, - 0x0036, 0x2019, 0xffff, 0x2021, 0x0007, 0x080c, 0x4e58, 0x003e, - 0x004e, 0x001e, 0x0005, 0x080c, 0x6058, 0x709b, 0x0000, 0x7093, - 0x0000, 0x0005, 0x0006, 0x2001, 0x180c, 0x2004, 0xd09c, 0x0100, - 0x000e, 0x0005, 0x0006, 0x0016, 0x0126, 0x2091, 0x8000, 0x2001, - 0x0101, 0x200c, 0x918d, 0x0006, 0x2102, 0x012e, 0x001e, 0x000e, - 0x0005, 0x2009, 0x0001, 0x0020, 0x2009, 0x0002, 0x0008, 0x900e, - 0x6814, 0x9084, 0xffc0, 0x910d, 0x6916, 0x0005, 0x00f6, 0x0156, - 0x0146, 0x01d6, 0x9006, 0x20a9, 0x0080, 0x20e9, 0x0001, 0x20a1, - 0x1d00, 0x4004, 0x2079, 0x1d00, 0x7803, 0x2200, 0x7807, 0x00ef, - 0x780f, 0x00ef, 0x7813, 0x0138, 0x7823, 0xffff, 0x7827, 0xffff, - 0x01de, 0x014e, 0x015e, 0x00fe, 0x0005, 0x2001, 0x1800, 0x2003, - 0x0001, 0x0005, 0x2001, 0x19a7, 0x0118, 0x2003, 0x0001, 0x0010, - 0x2003, 0x0000, 0x0005, 0x0156, 0x20a9, 0x0800, 0x2009, 0x1000, - 0x9006, 0x200a, 0x8108, 0x1f04, 0x61b1, 0x015e, 0x0005, 0x00d6, - 0x0036, 0x0156, 0x0136, 0x0146, 0x2069, 0x1847, 0x9006, 0xb802, - 0xb8d6, 0xb807, 0x0707, 0xb80a, 0xb80e, 0xb812, 0x9198, 0x348e, - 0x231d, 0x939c, 0x00ff, 0xbb16, 0x0016, 0x0026, 0xb886, 0x080c, - 0xb094, 0x1120, 0x9192, 0x007e, 0x1208, 0xbb86, 0x20a9, 0x0004, - 0xb8c4, 0x20e8, 0xb9c8, 0x9198, 0x0006, 0x9006, 0x23a0, 0x4004, - 0x20a9, 0x0004, 0x9198, 0x000a, 0x23a0, 0x4004, 0x002e, 0x001e, - 0xb83e, 0xb842, 0xb8ce, 0xb8d2, 0xb85e, 0xb862, 0xb866, 0xb86a, - 0xb86f, 0x0100, 0xb872, 0xb876, 0xb87a, 0xb88a, 0xb88e, 0xb893, - 0x0008, 0xb896, 0xb89a, 0xb89e, 0xb8be, 0xb9a2, 0x0096, 0xb8a4, - 0x904d, 0x0110, 0x080c, 0x108b, 0xb8a7, 0x0000, 0x009e, 0x9006, - 0xb84a, 0x6810, 0xb83a, 0x680c, 0xb846, 0xb8bb, 0x0520, 0xb8ac, - 0x9005, 0x0198, 0x00c6, 0x2060, 0x9c82, 0x1ddc, 0x0a0c, 0x0d85, - 0x2001, 0x181a, 0x2004, 0x9c02, 0x1a0c, 0x0d85, 0x080c, 0x8eee, - 0x00ce, 0x090c, 0x928d, 0xb8af, 0x0000, 0x6814, 0x9084, 0x00ff, - 0xb842, 0x014e, 0x013e, 0x015e, 0x003e, 0x00de, 0x0005, 0x0126, - 0x2091, 0x8000, 0xa974, 0xae78, 0x9684, 0x3fff, 0x9082, 0x4000, - 0x1a04, 0x628d, 0x9182, 0x0800, 0x1a04, 0x6291, 0x2001, 0x180c, - 0x2004, 0x9084, 0x0003, 0x1904, 0x6297, 0x9188, 0x1000, 0x2104, - 0x905d, 0x0198, 0xb804, 0x9084, 0x00ff, 0x908e, 0x0006, 0x1188, - 0xb8a4, 0x900d, 0x1904, 0x62a9, 0x080c, 0x6669, 0x9006, 0x012e, - 0x0005, 0x2001, 0x0005, 0x900e, 0x04b8, 0x2001, 0x0028, 0x900e, - 0x0498, 0x9082, 0x0006, 0x1290, 0x080c, 0xb094, 0x1160, 0xb8a0, - 0x9084, 0xff80, 0x1140, 0xb900, 0xd1fc, 0x0d10, 0x2001, 0x0029, - 0x2009, 0x1000, 0x0408, 0x2001, 0x0028, 0x00a8, 0x2009, 0x180c, - 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0068, 0xd184, 0x0118, - 0x2001, 0x0004, 0x0040, 0x2001, 0x0029, 0xb900, 0xd1fc, 0x0118, - 0x2009, 0x1000, 0x0048, 0x900e, 0x0038, 0x2001, 0x0029, 0x900e, - 0x0018, 0x2001, 0x0029, 0x900e, 0x9005, 0x012e, 0x0005, 0x2001, - 0x180c, 0x2004, 0xd084, 0x19d0, 0x9188, 0x1000, 0x2104, 0x9065, - 0x09a8, 0x080c, 0x6c11, 0x1990, 0xb800, 0xd0bc, 0x0978, 0x0804, - 0x6250, 0x080c, 0x6a2a, 0x0904, 0x6259, 0x0804, 0x6254, 0x00e6, - 0x2071, 0x19e8, 0x7004, 0x9086, 0x0002, 0x1128, 0x7030, 0x9080, - 0x0004, 0x2004, 0x9b06, 0x00ee, 0x0005, 0x00b6, 0x00e6, 0x0126, - 0x2091, 0x8000, 0xa874, 0x908e, 0x00ff, 0x1120, 0x2001, 0x196b, - 0x205c, 0x0060, 0xa974, 0x9182, 0x0800, 0x1690, 0x9188, 0x1000, - 0x2104, 0x905d, 0x01d0, 0x080c, 0x6bb1, 0x11d0, 0x080c, 0xb116, - 0x0570, 0x2b00, 0x6012, 0x2900, 0x6016, 0x6023, 0x0009, 0x602b, - 0x0000, 0xa874, 0x908e, 0x00ff, 0x1110, 0x602b, 0x8000, 0x2009, - 0x0043, 0x080c, 0xb20a, 0x9006, 0x00b0, 0x2001, 0x0028, 0x0090, - 0x2009, 0x180c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, - 0xd184, 0x0118, 0x2001, 0x0004, 0x0010, 0x2001, 0x0029, 0x0010, - 0x2001, 0x0029, 0x9005, 0x012e, 0x00ee, 0x00be, 0x0005, 0x2001, - 0x002c, 0x0cc0, 0x00b6, 0x00e6, 0x0126, 0x2091, 0x8000, 0xa974, - 0x9182, 0x0800, 0x1a04, 0x6388, 0x9188, 0x1000, 0x2104, 0x905d, - 0x0904, 0x6360, 0xb8a0, 0x9086, 0x007f, 0x0190, 0xa87c, 0xd0fc, - 0x1178, 0x080c, 0x6c19, 0x0160, 0xa994, 0x81ff, 0x0130, 0x908e, - 0x0004, 0x0130, 0x908e, 0x0005, 0x0118, 0x080c, 0x6c11, 0x1598, - 0xa87c, 0xd0fc, 0x01e0, 0xa894, 0x9005, 0x01c8, 0x2060, 0x0026, - 0x2010, 0x080c, 0xcf09, 0x002e, 0x1120, 0x2001, 0x0008, 0x0804, - 0x638a, 0x6020, 0x9086, 0x000a, 0x0120, 0x2001, 0x0008, 0x0804, - 0x638a, 0x601a, 0x6003, 0x0008, 0x2900, 0x6016, 0x0058, 0x080c, - 0xb116, 0x05e8, 0x2b00, 0x6012, 0x2900, 0x6016, 0x600b, 0xffff, - 0x6023, 0x000a, 0x2009, 0x0003, 0x080c, 0xb20a, 0x9006, 0x0458, - 0x2001, 0x0028, 0x0438, 0x9082, 0x0006, 0x1290, 0x080c, 0xb094, - 0x1160, 0xb8a0, 0x9084, 0xff80, 0x1140, 0xb900, 0xd1fc, 0x0900, - 0x2001, 0x0029, 0x2009, 0x1000, 0x00a8, 0x2001, 0x0028, 0x0090, - 0x2009, 0x180c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0050, - 0xd184, 0x0118, 0x2001, 0x0004, 0x0028, 0x2001, 0x0029, 0x0010, - 0x2001, 0x0029, 0x9005, 0x012e, 0x00ee, 0x00be, 0x0005, 0x2001, - 0x002c, 0x0cc0, 0x00f6, 0x00b6, 0x0126, 0x2091, 0x8000, 0xa8e0, - 0x9005, 0x1550, 0xa8dc, 0x9082, 0x0101, 0x1630, 0xa8c8, 0x9005, - 0x1518, 0xa8c4, 0x9082, 0x0101, 0x12f8, 0xa974, 0x2079, 0x1800, - 0x9182, 0x0800, 0x12e8, 0x7830, 0x9084, 0x0003, 0x1130, 0xaa98, - 0xab94, 0xa878, 0x9084, 0x0007, 0x00ea, 0x7930, 0xd18c, 0x0118, - 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, 0x2001, 0x0004, 0x0010, - 0x2001, 0x0029, 0x900e, 0x0038, 0x2001, 0x002c, 0x900e, 0x0018, - 0x2001, 0x0029, 0x900e, 0x9006, 0x0008, 0x9005, 0x012e, 0x00be, - 0x00fe, 0x0005, 0x641f, 0x63da, 0x63f1, 0x641f, 0x641f, 0x641f, - 0x641f, 0x641f, 0x2100, 0x9082, 0x007e, 0x1278, 0x080c, 0x6749, - 0x0148, 0x9046, 0xb810, 0x9306, 0x1904, 0x6427, 0xb814, 0x9206, - 0x15f0, 0x0028, 0xbb12, 0xba16, 0x0010, 0x080c, 0x4b54, 0x0150, - 0x04b0, 0x080c, 0x67b4, 0x1598, 0xb810, 0x9306, 0x1580, 0xb814, - 0x9206, 0x1568, 0x080c, 0xb116, 0x0530, 0x2b00, 0x6012, 0x080c, - 0xd3b6, 0x2900, 0x6016, 0x600b, 0xffff, 0x6023, 0x000a, 0xa878, - 0x9086, 0x0001, 0x1170, 0x080c, 0x3315, 0x9006, 0x080c, 0x66e6, - 0x2001, 0x0002, 0x080c, 0x66fa, 0x2001, 0x0200, 0xb86e, 0xb893, - 0x0002, 0x2009, 0x0003, 0x080c, 0xb20a, 0x9006, 0x0068, 0x2001, - 0x0001, 0x900e, 0x0038, 0x2001, 0x002c, 0x900e, 0x0018, 0x2001, - 0x0028, 0x900e, 0x9005, 0x0000, 0x012e, 0x00be, 0x00fe, 0x0005, - 0x00b6, 0x00f6, 0x00e6, 0x0126, 0x2091, 0x8000, 0xa894, 0x90c6, - 0x0015, 0x0904, 0x6612, 0x90c6, 0x0056, 0x0904, 0x6616, 0x90c6, - 0x0066, 0x0904, 0x661a, 0x90c6, 0x0067, 0x0904, 0x661e, 0x90c6, - 0x0068, 0x0904, 0x6622, 0x90c6, 0x0071, 0x0904, 0x6626, 0x90c6, - 0x0074, 0x0904, 0x662a, 0x90c6, 0x007c, 0x0904, 0x662e, 0x90c6, - 0x007e, 0x0904, 0x6632, 0x90c6, 0x0037, 0x0904, 0x6636, 0x9016, - 0x2079, 0x1800, 0xa974, 0x9186, 0x00ff, 0x0904, 0x660d, 0x9182, - 0x0800, 0x1a04, 0x660d, 0x080c, 0x67b4, 0x1198, 0xb804, 0x9084, - 0x00ff, 0x9082, 0x0006, 0x1268, 0xa894, 0x90c6, 0x006f, 0x0148, - 0x080c, 0xb094, 0x1904, 0x65f6, 0xb8a0, 0x9084, 0xff80, 0x1904, - 0x65f6, 0xa894, 0x90c6, 0x006f, 0x0158, 0x90c6, 0x005e, 0x0904, - 0x6556, 0x90c6, 0x0064, 0x0904, 0x657f, 0x2008, 0x0804, 0x6518, - 0xa998, 0xa8b0, 0x2040, 0x080c, 0xb094, 0x1120, 0x9182, 0x007f, - 0x0a04, 0x6518, 0x9186, 0x00ff, 0x0904, 0x6518, 0x9182, 0x0800, - 0x1a04, 0x6518, 0xaaa0, 0xab9c, 0x787c, 0x9306, 0x11a8, 0x7880, - 0x0096, 0x924e, 0x1128, 0x2208, 0x2310, 0x009e, 0x0804, 0x6518, - 0x080c, 0xb094, 0x1140, 0x99cc, 0xff00, 0x009e, 0x1128, 0x2208, - 0x2310, 0x0804, 0x6518, 0x009e, 0x080c, 0x4b54, 0x0904, 0x6522, - 0x900e, 0x9016, 0x90c6, 0x4000, 0x15e0, 0x0006, 0x080c, 0x6aae, - 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x20a9, 0x0004, - 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0031, 0x20a0, 0xb8c4, 0x20e0, - 0xb8c8, 0x9080, 0x0006, 0x2098, 0x080c, 0x0fd6, 0x20a9, 0x0004, - 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0035, 0x20a0, 0xb8c4, 0x20e0, - 0xb8c8, 0x9080, 0x000a, 0x2098, 0x080c, 0x0fd6, 0xa8c4, 0xabc8, - 0x9305, 0xabcc, 0x9305, 0xabd0, 0x9305, 0xabd4, 0x9305, 0xabd8, - 0x9305, 0xabdc, 0x9305, 0xabe0, 0x9305, 0x9005, 0x0510, 0x000e, - 0x00c8, 0x90c6, 0x4007, 0x1110, 0x2408, 0x00a0, 0x90c6, 0x4008, - 0x1118, 0x2708, 0x2610, 0x0070, 0x90c6, 0x4009, 0x1108, 0x0050, - 0x90c6, 0x4006, 0x0138, 0x2001, 0x4005, 0x2009, 0x000a, 0x0010, - 0x2001, 0x4006, 0xa896, 0xa99a, 0xaa9e, 0x2001, 0x0030, 0x900e, - 0x0478, 0x000e, 0x080c, 0xb116, 0x1130, 0x2001, 0x4005, 0x2009, - 0x0003, 0x9016, 0x0c78, 0x2b00, 0x6012, 0x080c, 0xd3b6, 0x2900, - 0x6016, 0x6023, 0x0001, 0xa868, 0xd88c, 0x0108, 0xc0f5, 0xa86a, - 0x0126, 0x2091, 0x8000, 0x080c, 0x3315, 0x012e, 0x9006, 0x080c, - 0x66e6, 0x2001, 0x0002, 0x080c, 0x66fa, 0x2009, 0x0002, 0x080c, - 0xb20a, 0xa8b0, 0xd094, 0x0118, 0xb8d4, 0xc08d, 0xb8d6, 0x9006, - 0x9005, 0x012e, 0x00ee, 0x00fe, 0x00be, 0x0005, 0x080c, 0x5854, - 0x0118, 0x2009, 0x0007, 0x00f8, 0xa998, 0xaeb0, 0x080c, 0x67b4, - 0x1904, 0x6513, 0x9186, 0x007f, 0x0130, 0x080c, 0x6c11, 0x0118, - 0x2009, 0x0009, 0x0080, 0x0096, 0x080c, 0x1059, 0x1120, 0x009e, - 0x2009, 0x0002, 0x0040, 0x2900, 0x009e, 0xa806, 0x080c, 0xd109, - 0x19b0, 0x2009, 0x0003, 0x2001, 0x4005, 0x0804, 0x651a, 0xa998, - 0xaeb0, 0x080c, 0x67b4, 0x1904, 0x6513, 0x0096, 0x080c, 0x1059, - 0x1128, 0x009e, 0x2009, 0x0002, 0x0804, 0x65d3, 0x2900, 0x009e, - 0xa806, 0x0096, 0x2048, 0x20a9, 0x002b, 0xb8c4, 0x20e0, 0xb8c8, - 0x2098, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0002, 0x20a0, 0x4003, - 0x20a9, 0x0008, 0x9080, 0x0006, 0x20a0, 0xbbc8, 0x9398, 0x0006, - 0x2398, 0x080c, 0x0fd6, 0x009e, 0xa87b, 0x0000, 0xa883, 0x0000, - 0xa897, 0x4000, 0xd684, 0x1168, 0x080c, 0x5840, 0xd0b4, 0x1118, - 0xa89b, 0x000b, 0x00e0, 0xb800, 0xd08c, 0x0118, 0xa89b, 0x000c, - 0x00b0, 0x080c, 0x6c11, 0x0118, 0xa89b, 0x0009, 0x0080, 0x080c, - 0x5854, 0x0118, 0xa89b, 0x0007, 0x0050, 0x080c, 0xd0ec, 0x1904, - 0x654f, 0x2009, 0x0003, 0x2001, 0x4005, 0x0804, 0x651a, 0xa87b, - 0x0030, 0xa897, 0x4005, 0xa804, 0x8006, 0x8006, 0x8007, 0x90bc, - 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, 0x2009, 0x002b, 0xaaa0, - 0xab9c, 0xaca8, 0xada4, 0x2031, 0x0000, 0x2041, 0x12a8, 0x080c, - 0xb691, 0x1904, 0x654f, 0x2009, 0x0002, 0x08e8, 0x2001, 0x0028, - 0x900e, 0x0804, 0x6550, 0x2009, 0x180c, 0x210c, 0xd18c, 0x0118, - 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, 0x2001, 0x0004, 0x0010, - 0x2001, 0x0029, 0x900e, 0x0804, 0x6550, 0x2001, 0x0029, 0x900e, - 0x0804, 0x6550, 0x080c, 0x38c0, 0x0804, 0x6551, 0x080c, 0x555d, - 0x0804, 0x6551, 0x080c, 0x46d5, 0x0804, 0x6551, 0x080c, 0x474e, - 0x0804, 0x6551, 0x080c, 0x47aa, 0x0804, 0x6551, 0x080c, 0x4c17, - 0x0804, 0x6551, 0x080c, 0x4edf, 0x0804, 0x6551, 0x080c, 0x51c4, - 0x0804, 0x6551, 0x080c, 0x53bd, 0x0804, 0x6551, 0x080c, 0x3afe, - 0x0804, 0x6551, 0x00b6, 0xa974, 0xae78, 0x9684, 0x3fff, 0x9082, - 0x4000, 0x1608, 0x9182, 0x0800, 0x1258, 0x9188, 0x1000, 0x2104, - 0x905d, 0x0130, 0x080c, 0x6c11, 0x1138, 0x00d9, 0x9006, 0x00b0, - 0x2001, 0x0028, 0x900e, 0x0090, 0x9082, 0x0006, 0x1240, 0xb900, - 0xd1fc, 0x0d98, 0x2001, 0x0029, 0x2009, 0x1000, 0x0038, 0x2001, - 0x0029, 0x900e, 0x0018, 0x2001, 0x0029, 0x900e, 0x9005, 0x00be, - 0x0005, 0xa877, 0x0000, 0xb8d0, 0x9005, 0x1904, 0x66da, 0xb888, - 0x9005, 0x1904, 0x66da, 0xb838, 0xb93c, 0x9102, 0x1a04, 0x66da, - 0x2b10, 0x080c, 0xb143, 0x0904, 0x66d6, 0x8108, 0xb93e, 0x6212, - 0x2900, 0x6016, 0x6023, 0x0003, 0x600b, 0xffff, 0x6007, 0x0040, - 0xa878, 0x605e, 0xa880, 0x6066, 0xa883, 0x0000, 0xa87c, 0xd0ac, - 0x05b8, 0xc0dd, 0xa87e, 0xa888, 0x8001, 0x1560, 0x2011, 0x180d, - 0x2214, 0xd28c, 0x190c, 0x6cd6, 0xa816, 0xa864, 0x9094, 0x00f7, - 0x9296, 0x0011, 0x11f8, 0x9084, 0x00ff, 0xc0bd, 0x601e, 0xa8ac, - 0xaab0, 0xa836, 0xaa3a, 0x2001, 0x000f, 0x8001, 0x1df0, 0x2001, - 0x8004, 0x6003, 0x0004, 0x6046, 0x00f6, 0x2079, 0x0380, 0x7818, - 0xd0bc, 0x1de8, 0x7833, 0x0010, 0x2c00, 0x7836, 0x781b, 0x8080, - 0x00fe, 0x0005, 0x080c, 0x17ad, 0x601c, 0xc0bd, 0x601e, 0x0c38, - 0x2009, 0x180d, 0x210c, 0xd18c, 0x190c, 0x6ce0, 0xd0b4, 0x190c, - 0x1c9c, 0x2001, 0x8004, 0x6003, 0x0002, 0x08e8, 0x81ff, 0x1110, - 0xb88b, 0x0001, 0x2908, 0xb8cc, 0xb9ce, 0x9005, 0x1110, 0xb9d2, - 0x0020, 0x0096, 0x2048, 0xa902, 0x009e, 0x0005, 0x00b6, 0x0126, - 0x00c6, 0x0026, 0x2091, 0x8000, 0x6210, 0x2258, 0xba00, 0x9005, - 0x0110, 0xc285, 0x0008, 0xc284, 0xba02, 0x002e, 0x00ce, 0x012e, - 0x00be, 0x0005, 0x00b6, 0x0126, 0x00c6, 0x2091, 0x8000, 0x6210, - 0x2258, 0xba04, 0x0006, 0x9086, 0x0006, 0x1170, 0xb89c, 0xd0ac, - 0x0158, 0x080c, 0x6c0d, 0x0140, 0x9284, 0xff00, 0x8007, 0x9086, - 0x0007, 0x1110, 0x2011, 0x0600, 0x000e, 0x9294, 0xff00, 0x9215, - 0xba06, 0x0006, 0x9086, 0x0006, 0x1120, 0xba90, 0x82ff, 0x090c, - 0x0d85, 0x000e, 0x00ce, 0x012e, 0x00be, 0x0005, 0x00b6, 0x0126, - 0x00c6, 0x2091, 0x8000, 0x6210, 0x2258, 0xba04, 0x0006, 0x9086, - 0x0006, 0x1168, 0xb89c, 0xd0a4, 0x0150, 0x080c, 0x6c09, 0x1138, - 0x9284, 0x00ff, 0x9086, 0x0007, 0x1110, 0x2011, 0x0006, 0x000e, - 0x9294, 0x00ff, 0x8007, 0x9215, 0xba06, 0x00ce, 0x012e, 0x00be, - 0x0005, 0x9182, 0x0800, 0x0218, 0x9085, 0x0001, 0x0005, 0x00d6, - 0x0026, 0x9190, 0x1000, 0x2204, 0x905d, 0x1188, 0x0096, 0x080c, - 0x1059, 0x2958, 0x009e, 0x0168, 0x2b00, 0x2012, 0xb85c, 0xb8ca, - 0xb860, 0xb8c6, 0x9006, 0xb8a6, 0xb8ae, 0x080c, 0x61b7, 0x9006, - 0x0010, 0x9085, 0x0001, 0x002e, 0x00de, 0x0005, 0x00b6, 0x0096, - 0x0126, 0x2091, 0x8000, 0x0026, 0x9182, 0x0800, 0x0218, 0x9085, - 0x0001, 0x04a8, 0x00d6, 0x9190, 0x1000, 0x2204, 0x905d, 0x0568, - 0x2013, 0x0000, 0xb8a4, 0x904d, 0x0110, 0x080c, 0x108b, 0x00d6, - 0x00c6, 0xb8bc, 0x2060, 0x8cff, 0x0168, 0x600c, 0x0006, 0x6014, - 0x2048, 0x080c, 0xcf1b, 0x0110, 0x080c, 0x100b, 0x080c, 0xb16c, - 0x00ce, 0x0c88, 0x00ce, 0x00de, 0x00c6, 0xb8ac, 0x9065, 0x0128, - 0x621c, 0xd2c4, 0x0110, 0x080c, 0x928d, 0x00ce, 0x2b48, 0xb8c8, - 0xb85e, 0xb8c4, 0xb862, 0x080c, 0x109b, 0x00de, 0x9006, 0x002e, - 0x012e, 0x009e, 0x00be, 0x0005, 0x0016, 0x9182, 0x0800, 0x0218, - 0x9085, 0x0001, 0x0030, 0x9188, 0x1000, 0x2104, 0x905d, 0x0dc0, - 0x9006, 0x001e, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x9006, - 0xb80a, 0xb80e, 0xb800, 0xc08c, 0xb802, 0x080c, 0x779e, 0x1510, - 0xb8a0, 0x9086, 0x007e, 0x0120, 0x080c, 0xb094, 0x11d8, 0x0078, - 0x7040, 0xd0e4, 0x01b8, 0x00c6, 0x2061, 0x1982, 0x7048, 0x2062, - 0x704c, 0x6006, 0x7050, 0x600a, 0x7054, 0x600e, 0x00ce, 0x703c, - 0x2069, 0x0140, 0x9005, 0x1110, 0x2001, 0x0001, 0x6886, 0x2069, - 0x1800, 0x68b6, 0x7040, 0xb85e, 0x7048, 0xb862, 0x704c, 0xb866, - 0x20e1, 0x0000, 0x2099, 0x0276, 0xb8c4, 0x20e8, 0xb8c8, 0x9088, - 0x000a, 0x21a0, 0x20a9, 0x0004, 0x4003, 0x2099, 0x027a, 0x9088, - 0x0006, 0x21a0, 0x20a9, 0x0004, 0x4003, 0x2069, 0x0200, 0x6817, - 0x0001, 0x7040, 0xb86a, 0x7144, 0xb96e, 0x7048, 0xb872, 0x7050, - 0xb876, 0x2069, 0x0200, 0x6817, 0x0000, 0xb8a0, 0x9086, 0x007e, - 0x1110, 0x7144, 0xb96e, 0x9182, 0x0211, 0x1218, 0x2009, 0x0008, - 0x0400, 0x9182, 0x0259, 0x1218, 0x2009, 0x0007, 0x00d0, 0x9182, - 0x02c1, 0x1218, 0x2009, 0x0006, 0x00a0, 0x9182, 0x0349, 0x1218, - 0x2009, 0x0005, 0x0070, 0x9182, 0x0421, 0x1218, 0x2009, 0x0004, - 0x0040, 0x9182, 0x0581, 0x1218, 0x2009, 0x0003, 0x0010, 0x2009, - 0x0002, 0xb992, 0x014e, 0x013e, 0x015e, 0x00de, 0x0005, 0x0016, - 0x0026, 0x00e6, 0x2071, 0x0260, 0x7034, 0xb896, 0x703c, 0xb89a, - 0x7054, 0xb89e, 0x0036, 0xbbd4, 0xc384, 0xba00, 0x2009, 0x1867, - 0x210c, 0xd0bc, 0x0120, 0xd1ec, 0x0110, 0xc2ad, 0x0008, 0xc2ac, - 0xd0c4, 0x0148, 0xd1e4, 0x0138, 0xc2bd, 0xd0cc, 0x0128, 0xd38c, - 0x1108, 0xc385, 0x0008, 0xc2bc, 0xba02, 0xbbd6, 0x003e, 0x00ee, - 0x002e, 0x001e, 0x0005, 0x0096, 0x0126, 0x2091, 0x8000, 0xb8a4, - 0x904d, 0x0578, 0xa900, 0x81ff, 0x15c0, 0xaa04, 0x9282, 0x0010, - 0x16c8, 0x0136, 0x0146, 0x01c6, 0x01d6, 0x8906, 0x8006, 0x8007, - 0x908c, 0x003f, 0x21e0, 0x9084, 0xffc0, 0x9080, 0x0004, 0x2098, - 0x2009, 0x0010, 0x20a9, 0x0001, 0x4002, 0x9086, 0xffff, 0x0120, - 0x8109, 0x1dd0, 0x080c, 0x0d85, 0x3c00, 0x20e8, 0x3300, 0x8001, - 0x20a0, 0x4604, 0x8210, 0xaa06, 0x01de, 0x01ce, 0x014e, 0x013e, - 0x0060, 0x080c, 0x1059, 0x0170, 0x2900, 0xb8a6, 0xa803, 0x0000, - 0x080c, 0x6a4a, 0xa807, 0x0001, 0xae12, 0x9085, 0x0001, 0x012e, - 0x009e, 0x0005, 0x9006, 0x0cd8, 0x0126, 0x2091, 0x8000, 0x0096, - 0xb8a4, 0x904d, 0x0188, 0xa800, 0x9005, 0x1150, 0x080c, 0x6a59, - 0x1158, 0xa804, 0x908a, 0x0002, 0x0218, 0x8001, 0xa806, 0x0020, - 0x080c, 0x108b, 0xb8a7, 0x0000, 0x009e, 0x012e, 0x0005, 0x0096, - 0x00c6, 0xb888, 0x9005, 0x1904, 0x693f, 0xb8d0, 0x904d, 0x0904, - 0x693f, 0x2001, 0x0382, 0x2004, 0x9084, 0x0007, 0x9086, 0x0001, - 0x1904, 0x693d, 0x080c, 0xb143, 0x0904, 0x693d, 0x8210, 0xba3e, - 0xa800, 0xb8d2, 0x9005, 0x1108, 0xb8ce, 0x2b00, 0x6012, 0x2900, - 0x6016, 0x6023, 0x0003, 0x600b, 0xffff, 0x6007, 0x0040, 0xa878, - 0x605e, 0xa880, 0x9084, 0x00ff, 0x6066, 0xa883, 0x0000, 0xa87c, - 0xd0ac, 0x01c8, 0xc0dd, 0xa87e, 0xa888, 0x8001, 0x1558, 0xa816, - 0xa864, 0x9094, 0x00f7, 0x9296, 0x0011, 0x1520, 0x9084, 0x00ff, - 0xc0bd, 0x601e, 0xa8ac, 0xaab0, 0xa836, 0xaa3a, 0x2001, 0x8004, - 0x6003, 0x0004, 0x0030, 0x080c, 0x1c9c, 0x2001, 0x8004, 0x6003, - 0x0002, 0x6046, 0x2001, 0x0010, 0x2c08, 0x080c, 0xaced, 0xb838, - 0xba3c, 0x9202, 0x0a04, 0x68e5, 0x0010, 0xb88b, 0x0001, 0x00ce, - 0x009e, 0x0005, 0x080c, 0x17ad, 0x601c, 0xc0bd, 0x601e, 0x08f0, - 0x00b6, 0x0096, 0x0016, 0x20a9, 0x0800, 0x900e, 0x0016, 0x080c, - 0x67b4, 0x1158, 0xb8d0, 0x904d, 0x0140, 0x3e00, 0x9086, 0x0002, - 0x1118, 0xb800, 0xd0bc, 0x1108, 0x0041, 0x001e, 0x8108, 0x1f04, - 0x694e, 0x001e, 0x00be, 0x009e, 0x0005, 0x0096, 0x0016, 0xb8d0, - 0x904d, 0x0188, 0xa800, 0xb8d2, 0x9005, 0x1108, 0xb8ce, 0x9006, - 0xa802, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0xd220, - 0x080c, 0x7012, 0x0c60, 0x001e, 0x009e, 0x0005, 0x0086, 0x9046, - 0xb8d0, 0x904d, 0x01b0, 0xa86c, 0x9406, 0x1118, 0xa870, 0x9506, - 0x0128, 0x2940, 0xa800, 0x904d, 0x0160, 0x0ca8, 0xa800, 0x88ff, - 0x1128, 0xb8d2, 0x9005, 0x1118, 0xb8ce, 0x0008, 0xa002, 0xa803, - 0x0000, 0x008e, 0x0005, 0x901e, 0x0010, 0x2019, 0x0001, 0x0126, - 0x2091, 0x8000, 0x00e6, 0x0096, 0x00c6, 0x0086, 0x0026, 0x2071, - 0x19e8, 0x9046, 0x7028, 0x9065, 0x01e8, 0x6014, 0x2068, 0x83ff, - 0x0120, 0x605c, 0x9606, 0x0158, 0x0030, 0xa86c, 0x9406, 0x1118, - 0xa870, 0x9506, 0x0120, 0x2c40, 0x600c, 0x2060, 0x0c60, 0x600c, - 0x0006, 0x0066, 0x2830, 0x080c, 0xa420, 0x006e, 0x000e, 0x83ff, - 0x0508, 0x0c08, 0x9046, 0xb8d0, 0x904d, 0x01e0, 0x83ff, 0x0120, - 0xa878, 0x9606, 0x0158, 0x0030, 0xa86c, 0x9406, 0x1118, 0xa870, - 0x9506, 0x0120, 0x2940, 0xa800, 0x2048, 0x0c70, 0xb8d0, 0xaa00, - 0x0026, 0x9906, 0x1110, 0xbad2, 0x0008, 0xa202, 0x000e, 0x83ff, - 0x0108, 0x0c10, 0x002e, 0x008e, 0x00ce, 0x009e, 0x00ee, 0x012e, - 0x0005, 0x9016, 0x0489, 0x1110, 0x2011, 0x0001, 0x0005, 0x080c, - 0x6aae, 0x0128, 0x080c, 0xcfdc, 0x0010, 0x9085, 0x0001, 0x0005, - 0x080c, 0x6aae, 0x0128, 0x080c, 0xcf7d, 0x0010, 0x9085, 0x0001, - 0x0005, 0x080c, 0x6aae, 0x0128, 0x080c, 0xcfd9, 0x0010, 0x9085, - 0x0001, 0x0005, 0x080c, 0x6aae, 0x0128, 0x080c, 0xcf9c, 0x0010, - 0x9085, 0x0001, 0x0005, 0x080c, 0x6aae, 0x0128, 0x080c, 0xd01f, - 0x0010, 0x9085, 0x0001, 0x0005, 0xb8a4, 0x900d, 0x1118, 0x9085, - 0x0001, 0x0005, 0x0136, 0x01c6, 0xa800, 0x9005, 0x11b8, 0x890e, - 0x810e, 0x810f, 0x9184, 0x003f, 0x20e0, 0x9184, 0xffc0, 0x9080, - 0x0004, 0x2098, 0x20a9, 0x0001, 0x2009, 0x0010, 0x4002, 0x9606, - 0x0128, 0x8109, 0x1dd8, 0x9085, 0x0001, 0x0008, 0x9006, 0x01ce, - 0x013e, 0x0005, 0x0146, 0x01d6, 0xa860, 0x20e8, 0xa85c, 0x9080, - 0x0004, 0x20a0, 0x20a9, 0x0010, 0x2009, 0xffff, 0x4104, 0x01de, - 0x014e, 0x0136, 0x01c6, 0xa800, 0x9005, 0x11b8, 0x890e, 0x810e, - 0x810f, 0x9184, 0x003f, 0x20e0, 0x9184, 0xffc0, 0x9080, 0x0004, - 0x2098, 0x20a9, 0x0001, 0x2009, 0x0010, 0x4002, 0x9606, 0x0128, - 0x8109, 0x1dd8, 0x9085, 0x0001, 0x0068, 0x0146, 0x01d6, 0x3300, - 0x8001, 0x20a0, 0x3c00, 0x20e8, 0x2001, 0xffff, 0x4004, 0x01de, - 0x014e, 0x9006, 0x01ce, 0x013e, 0x0005, 0x0096, 0x0126, 0x2091, - 0x8000, 0xb8a4, 0x904d, 0x1128, 0x080c, 0x1059, 0x0168, 0x2900, - 0xb8a6, 0x080c, 0x6a4a, 0xa803, 0x0001, 0xa807, 0x0000, 0x9085, - 0x0001, 0x012e, 0x009e, 0x0005, 0x9006, 0x0cd8, 0x0096, 0x0126, - 0x2091, 0x8000, 0xb8a4, 0x904d, 0x0130, 0xb8a7, 0x0000, 0x080c, - 0x108b, 0x9085, 0x0001, 0x012e, 0x009e, 0x0005, 0xb89c, 0xd0a4, - 0x0005, 0x00b6, 0x00f6, 0x080c, 0x779e, 0x01b0, 0x71c4, 0x81ff, - 0x1198, 0x71dc, 0xd19c, 0x0180, 0x2001, 0x007e, 0x9080, 0x1000, - 0x2004, 0x905d, 0x0148, 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, - 0x1118, 0xb800, 0xc0ed, 0xb802, 0x2079, 0x1847, 0x7804, 0xd0a4, - 0x01d0, 0x0156, 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, 0x67b4, - 0x1168, 0xb804, 0x9084, 0xff00, 0x8007, 0x9096, 0x0004, 0x0118, - 0x9086, 0x0006, 0x1118, 0xb800, 0xc0ed, 0xb802, 0x001e, 0x8108, - 0x1f04, 0x6ad5, 0x015e, 0x080c, 0x6bcf, 0x0120, 0x2001, 0x1985, - 0x200c, 0x0098, 0x2079, 0x1847, 0x7804, 0xd0a4, 0x0190, 0x2009, - 0x07d0, 0x2001, 0x182c, 0x2004, 0x9005, 0x0138, 0x2001, 0x1867, - 0x2004, 0xd0e4, 0x0110, 0x2009, 0x5dc0, 0x2011, 0x6b0c, 0x080c, - 0x8a5d, 0x00fe, 0x00be, 0x0005, 0x00b6, 0x2011, 0x6b0c, 0x080c, - 0x8993, 0x080c, 0x6bcf, 0x01d8, 0x2001, 0x107e, 0x2004, 0x2058, - 0xb900, 0xc1ec, 0xb902, 0x080c, 0x6c0d, 0x0130, 0x2009, 0x07d0, - 0x2011, 0x6b0c, 0x080c, 0x8a5d, 0x00e6, 0x2071, 0x1800, 0x9006, - 0x707e, 0x7060, 0x7082, 0x080c, 0x30bf, 0x00ee, 0x04d0, 0x0156, - 0x00c6, 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, 0x67b4, 0x1558, - 0xb800, 0xd0ec, 0x0540, 0x0046, 0xbaa0, 0x2220, 0x9006, 0x2009, - 0x0029, 0x080c, 0xea8d, 0xb800, 0xc0e5, 0xc0ec, 0xb802, 0x080c, - 0x6c09, 0x2001, 0x0707, 0x1128, 0xb804, 0x9084, 0x00ff, 0x9085, - 0x0700, 0xb806, 0x080c, 0xacfc, 0x2019, 0x0029, 0x080c, 0x97b0, - 0x0076, 0x903e, 0x080c, 0x966d, 0x900e, 0x080c, 0xe75d, 0x007e, - 0x004e, 0x080c, 0xad18, 0x001e, 0x8108, 0x1f04, 0x6b34, 0x00ce, - 0x015e, 0x00be, 0x0005, 0x00b6, 0x6010, 0x2058, 0xb800, 0xc0ec, - 0xb802, 0x00be, 0x0005, 0x00b6, 0x00c6, 0x0096, 0x080c, 0x1072, - 0x090c, 0x0d85, 0x2958, 0x009e, 0x2001, 0x196b, 0x2b02, 0x8b07, - 0x8006, 0x8006, 0x908c, 0x003f, 0xb9c6, 0x908c, 0xffc0, 0xb9ca, - 0xb8af, 0x0000, 0x2009, 0x00ff, 0x080c, 0x61b7, 0xb807, 0x0006, - 0xb813, 0x00ff, 0xb817, 0xffff, 0xb86f, 0x0200, 0xb86c, 0xb893, - 0x0002, 0xb8bb, 0x0520, 0xb8a3, 0x00ff, 0xb8af, 0x0000, 0x00ce, - 0x00be, 0x0005, 0x7810, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0ac, - 0x0005, 0x6010, 0x00b6, 0x905d, 0x0108, 0xb800, 0x00be, 0xd0bc, - 0x0005, 0x0006, 0x0016, 0x0026, 0xb804, 0x908c, 0x00ff, 0x9196, - 0x0006, 0x0188, 0x9196, 0x0004, 0x0170, 0x9196, 0x0005, 0x0158, - 0x908c, 0xff00, 0x810f, 0x9196, 0x0006, 0x0128, 0x9196, 0x0004, - 0x0110, 0x9196, 0x0005, 0x002e, 0x001e, 0x000e, 0x0005, 0x00b6, - 0x00f6, 0x2001, 0x107e, 0x2004, 0x905d, 0x0110, 0xb800, 0xd0ec, - 0x00fe, 0x00be, 0x0005, 0x0126, 0x0026, 0x2091, 0x8000, 0x0006, - 0xbaa0, 0x9290, 0x1000, 0x2204, 0x9b06, 0x190c, 0x0d85, 0x000e, - 0xba00, 0x9005, 0x0110, 0xc2fd, 0x0008, 0xc2fc, 0xba02, 0x002e, - 0x012e, 0x0005, 0x2011, 0x1837, 0x2204, 0xd0cc, 0x0138, 0x2001, - 0x1983, 0x200c, 0x2011, 0x6bff, 0x080c, 0x8a5d, 0x0005, 0x2011, - 0x6bff, 0x080c, 0x8993, 0x2011, 0x1837, 0x2204, 0xc0cc, 0x2012, - 0x0005, 0x080c, 0x5840, 0xd0ac, 0x0005, 0x080c, 0x5840, 0xd0a4, - 0x0005, 0x0016, 0xb904, 0x9184, 0x00ff, 0x908e, 0x0006, 0x001e, - 0x0005, 0x0016, 0xb904, 0x9184, 0xff00, 0x8007, 0x908e, 0x0006, - 0x001e, 0x0005, 0x00b6, 0x00f6, 0x080c, 0xd645, 0x0158, 0x70dc, - 0x9084, 0x0028, 0x0138, 0x2001, 0x107f, 0x2004, 0x905d, 0x0110, - 0xb8d4, 0xd094, 0x00fe, 0x00be, 0x0005, 0x0006, 0x0016, 0x0036, - 0x0046, 0x0076, 0x00b6, 0x2001, 0x1818, 0x203c, 0x9780, 0x348e, - 0x203d, 0x97bc, 0xff00, 0x873f, 0x9006, 0x2018, 0x2008, 0x9284, - 0x8000, 0x0110, 0x2019, 0x0001, 0x9294, 0x7fff, 0x2100, 0x9706, - 0x0190, 0x91a0, 0x1000, 0x2404, 0x905d, 0x0168, 0xb804, 0x9084, - 0x00ff, 0x9086, 0x0006, 0x1138, 0x83ff, 0x0118, 0xb89c, 0xd0a4, - 0x0110, 0x8211, 0x0158, 0x8108, 0x83ff, 0x0120, 0x9182, 0x0800, - 0x0e28, 0x0068, 0x9182, 0x007e, 0x0e08, 0x0048, 0x00be, 0x007e, - 0x004e, 0x003e, 0x001e, 0x9085, 0x0001, 0x000e, 0x0005, 0x00be, - 0x007e, 0x004e, 0x003e, 0x001e, 0x9006, 0x000e, 0x0005, 0x0046, - 0x0056, 0x0076, 0x00b6, 0x2100, 0x9084, 0x7fff, 0x9080, 0x1000, - 0x2004, 0x905d, 0x0130, 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, - 0x0550, 0x9184, 0x8000, 0x0580, 0x2001, 0x1818, 0x203c, 0x9780, - 0x348e, 0x203d, 0x97bc, 0xff00, 0x873f, 0x9006, 0x2020, 0x2400, - 0x9706, 0x01a0, 0x94a8, 0x1000, 0x2504, 0x905d, 0x0178, 0xb804, - 0x9084, 0x00ff, 0x9086, 0x0006, 0x1148, 0xb89c, 0xd0a4, 0x0130, - 0xb814, 0x9206, 0x1118, 0xb810, 0x9306, 0x0128, 0x8420, 0x9482, - 0x0800, 0x0e28, 0x0048, 0x918c, 0x7fff, 0x00be, 0x007e, 0x005e, - 0x004e, 0x9085, 0x0001, 0x0005, 0x918c, 0x7fff, 0x00be, 0x007e, - 0x005e, 0x004e, 0x9006, 0x0005, 0x0006, 0x2001, 0x00a0, 0x8001, - 0xa001, 0xa001, 0xa001, 0x1dd8, 0x000e, 0x0005, 0x0006, 0x2001, - 0x00f8, 0x8001, 0xa001, 0xa001, 0xa001, 0x1dd8, 0x000e, 0x0005, - 0x0006, 0x2001, 0x00e8, 0x8001, 0xa001, 0xa001, 0xa001, 0x1dd8, - 0x000e, 0x0005, 0x2071, 0x1910, 0x7003, 0x0001, 0x7007, 0x0000, - 0x9006, 0x7012, 0x7016, 0x701a, 0x701e, 0x700a, 0x7046, 0x2001, - 0x1922, 0x2003, 0x0000, 0x0005, 0x0016, 0x00e6, 0x2071, 0x1948, - 0x900e, 0x710a, 0x080c, 0x5840, 0xd0fc, 0x1140, 0x080c, 0x5840, - 0x900e, 0xd09c, 0x0108, 0x8108, 0x7102, 0x0470, 0x2001, 0x1867, - 0x200c, 0x9184, 0x0007, 0x0006, 0x2001, 0x180d, 0x2004, 0xd08c, - 0x000e, 0x0108, 0x9006, 0x0002, 0x6d06, 0x6d06, 0x6d06, 0x6d06, - 0x6d06, 0x6d24, 0x6d39, 0x6d47, 0x7003, 0x0003, 0x2009, 0x1868, - 0x210c, 0x9184, 0xff00, 0x908e, 0xff00, 0x0140, 0x8007, 0x9005, - 0x1110, 0x2001, 0x0002, 0x8003, 0x7006, 0x0030, 0x7007, 0x0001, - 0x0018, 0x7003, 0x0005, 0x0c50, 0x2071, 0x1910, 0x704f, 0x0000, - 0x2071, 0x1800, 0x70f7, 0x0001, 0x00ee, 0x001e, 0x0005, 0x7003, - 0x0000, 0x2071, 0x1910, 0x2009, 0x1868, 0x210c, 0x9184, 0x7f00, - 0x8007, 0x908c, 0x000f, 0x0160, 0x714e, 0x8004, 0x8004, 0x8004, - 0x8004, 0x2071, 0x1800, 0x908c, 0x0007, 0x0128, 0x70f6, 0x0c20, - 0x704f, 0x000f, 0x0c90, 0x70f7, 0x0005, 0x08f0, 0x00e6, 0x2071, - 0x0050, 0x684c, 0x9005, 0x1150, 0x00e6, 0x2071, 0x1910, 0x7028, - 0xc085, 0x702a, 0x00ee, 0x9085, 0x0001, 0x0488, 0x6844, 0x9005, - 0x0158, 0x080c, 0x7b28, 0x6a60, 0x9200, 0x7002, 0x6864, 0x9101, - 0x7006, 0x9006, 0x7012, 0x7016, 0x6860, 0x7002, 0x6864, 0x7006, - 0x6868, 0x700a, 0x686c, 0x700e, 0x6844, 0x9005, 0x1110, 0x7012, - 0x7016, 0x684c, 0x701a, 0x701c, 0x9085, 0x0040, 0x701e, 0x7037, - 0x0019, 0x702b, 0x0001, 0x00e6, 0x2071, 0x1910, 0x7028, 0xc084, - 0x702a, 0x7007, 0x0001, 0x700b, 0x0000, 0x00ee, 0x9006, 0x00ee, - 0x0005, 0x00e6, 0x0026, 0x2071, 0x1948, 0x7000, 0x9015, 0x0904, - 0x7017, 0x9286, 0x0003, 0x0904, 0x6eac, 0x9286, 0x0005, 0x0904, - 0x6eac, 0x2071, 0x1877, 0xa87c, 0x9005, 0x0904, 0x6e07, 0x7140, - 0xa868, 0x9102, 0x0a04, 0x7017, 0xa878, 0xd084, 0x15d8, 0xa853, - 0x0019, 0x2001, 0x8023, 0xa84e, 0x2071, 0x1910, 0x701c, 0x9005, - 0x1904, 0x71c6, 0x0e04, 0x7234, 0x2071, 0x0000, 0xa850, 0x7032, - 0xa84c, 0x7082, 0xa870, 0x7086, 0xa86c, 0x708a, 0xa880, 0x708e, - 0x7036, 0x0146, 0x01d6, 0x0136, 0x01c6, 0x0156, 0x20e9, 0x0000, - 0x20a1, 0x002a, 0xa868, 0x20a8, 0xa860, 0x20e0, 0xa85c, 0x9080, - 0x0021, 0x2098, 0x4003, 0x015e, 0x01ce, 0x013e, 0x01de, 0x014e, - 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1200, - 0x0804, 0x6e8f, 0xa853, 0x001b, 0x2001, 0x8027, 0x0820, 0x7004, - 0xd08c, 0x1904, 0x7017, 0xa853, 0x001a, 0x2001, 0x8024, 0x0804, - 0x6dcb, 0x00e6, 0x0026, 0x2071, 0x1948, 0x7000, 0x9015, 0x0904, - 0x7017, 0x9286, 0x0003, 0x0904, 0x6eac, 0x9286, 0x0005, 0x0904, - 0x6eac, 0xa84f, 0x8022, 0xa853, 0x0018, 0x0804, 0x6e74, 0xa868, - 0xd0fc, 0x1508, 0x00e6, 0x0026, 0x2001, 0x1948, 0x2004, 0x9015, - 0x0904, 0x7017, 0xa978, 0xa874, 0x9105, 0x1904, 0x7017, 0x9286, - 0x0003, 0x0904, 0x6eac, 0x9286, 0x0005, 0x0904, 0x6eac, 0xa87c, - 0xd0bc, 0x1904, 0x7017, 0x2200, 0x0002, 0x7017, 0x6e70, 0x6eac, - 0x6eac, 0x7017, 0x6eac, 0x0005, 0xa868, 0xd0fc, 0x1500, 0x00e6, - 0x0026, 0x2009, 0x1948, 0x210c, 0x81ff, 0x0904, 0x7017, 0xa880, - 0x9084, 0x00ff, 0x9086, 0x0001, 0x1904, 0x7017, 0x9186, 0x0003, - 0x0904, 0x6eac, 0x9186, 0x0005, 0x0904, 0x6eac, 0xa87c, 0xd0cc, - 0x0904, 0x7017, 0xa84f, 0x8021, 0xa853, 0x0017, 0x0028, 0x0005, - 0xa84f, 0x8020, 0xa853, 0x0016, 0x2071, 0x1910, 0x701c, 0x9005, - 0x1904, 0x71c6, 0x0e04, 0x7234, 0x2071, 0x0000, 0xa84c, 0x7082, - 0xa850, 0x7032, 0xa86c, 0x7086, 0x7036, 0xa870, 0x708a, 0x2091, - 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1200, 0x2071, - 0x1800, 0x2011, 0x0001, 0xa804, 0x900d, 0x702c, 0x1158, 0xa802, - 0x2900, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8899, 0x002e, - 0x00ee, 0x0005, 0x0096, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, - 0x81ff, 0x1dc8, 0x009e, 0x0c58, 0xa84f, 0x0000, 0x00f6, 0x2079, - 0x0050, 0x2071, 0x1910, 0xa803, 0x0000, 0x7010, 0x9005, 0x1904, - 0x6f9d, 0x782c, 0x908c, 0x0780, 0x190c, 0x7382, 0x8004, 0x8004, - 0x8004, 0x9084, 0x0003, 0x0002, 0x6eca, 0x6f9d, 0x6eee, 0x6f3a, - 0x080c, 0x0d85, 0x2071, 0x1800, 0x2900, 0x7822, 0xa804, 0x900d, - 0x1168, 0x2071, 0x1a04, 0x7044, 0x9005, 0x1320, 0x2001, 0x1949, - 0x2004, 0x7046, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x9016, 0x702c, - 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, - 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8899, 0x0c18, 0x2071, 0x1800, - 0x2900, 0x7822, 0xa804, 0x900d, 0x15a0, 0x7824, 0x00e6, 0x2071, - 0x0040, 0x712c, 0xd19c, 0x1170, 0x2009, 0x1830, 0x210c, 0x918a, - 0x0020, 0x0240, 0x7022, 0x2001, 0x1dc0, 0x200c, 0x8108, 0x2102, - 0x00ee, 0x0058, 0x00ee, 0x2048, 0x702c, 0xa802, 0x2900, 0x702e, - 0x70c0, 0x8000, 0x70c2, 0x080c, 0x8899, 0x782c, 0x9094, 0x0780, - 0x190c, 0x7382, 0xd0a4, 0x19c8, 0x2071, 0x1a04, 0x7044, 0x9005, - 0x1320, 0x2001, 0x1949, 0x2004, 0x7046, 0x00fe, 0x002e, 0x00ee, - 0x0005, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, - 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8899, - 0x0804, 0x6ef5, 0x0096, 0x00e6, 0x7824, 0x2048, 0x2071, 0x1800, - 0x702c, 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, - 0x8899, 0x782c, 0x9094, 0x0780, 0x190c, 0x7382, 0xd0a4, 0x1d60, - 0x00ee, 0x782c, 0x9094, 0x0780, 0x190c, 0x7382, 0xd09c, 0x1198, - 0x009e, 0x2900, 0x7822, 0xa804, 0x900d, 0x1550, 0x2071, 0x1a04, - 0x7044, 0x9005, 0x1320, 0x2001, 0x1949, 0x2004, 0x7046, 0x00fe, - 0x002e, 0x00ee, 0x0005, 0x009e, 0x2908, 0x7010, 0x8000, 0x7012, - 0x7018, 0x904d, 0x711a, 0x0110, 0xa902, 0x0008, 0x711e, 0x2148, - 0xa804, 0x900d, 0x1168, 0x2071, 0x1a04, 0x7044, 0x9005, 0x1320, - 0x2001, 0x1949, 0x2004, 0x7046, 0x00fe, 0x002e, 0x00ee, 0x0005, - 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, - 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, - 0x8899, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2908, 0x7010, 0x8000, - 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, 0xa902, 0x0008, 0x711e, - 0x2148, 0xa804, 0x900d, 0x1904, 0x6ff1, 0x782c, 0x9094, 0x0780, - 0x190c, 0x7382, 0xd09c, 0x1198, 0x701c, 0x904d, 0x0180, 0x7010, - 0x8001, 0x7012, 0x1108, 0x701a, 0xa800, 0x701e, 0x2900, 0x7822, - 0x782c, 0x9094, 0x0780, 0x190c, 0x7382, 0xd09c, 0x0d68, 0x782c, - 0x9094, 0x0780, 0x190c, 0x7382, 0xd0a4, 0x01b0, 0x00e6, 0x7824, - 0x2048, 0x2071, 0x1800, 0x702c, 0xa802, 0x2900, 0x702e, 0x70c0, - 0x8000, 0x70c2, 0x080c, 0x8899, 0x782c, 0x9094, 0x0780, 0x190c, - 0x7382, 0xd0a4, 0x1d60, 0x00ee, 0x2071, 0x1a04, 0x7044, 0x9005, - 0x1320, 0x2001, 0x1949, 0x2004, 0x7046, 0x00fe, 0x002e, 0x00ee, - 0x0005, 0x00e6, 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, - 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, - 0x70c2, 0x080c, 0x8899, 0x00ee, 0x0804, 0x6fad, 0xa868, 0xd0fc, - 0x15e0, 0x0096, 0xa804, 0xa807, 0x0000, 0x904d, 0x190c, 0x100b, - 0x009e, 0x0018, 0xa868, 0xd0fc, 0x1580, 0x00e6, 0x0026, 0xa84f, - 0x0000, 0x00f6, 0x2079, 0x0050, 0x2071, 0x1910, 0xa803, 0x0000, - 0xa864, 0x9084, 0x00ff, 0x908e, 0x0016, 0x01a8, 0x7010, 0x9005, - 0x1904, 0x7142, 0x782c, 0x908c, 0x0780, 0x190c, 0x7382, 0x8004, - 0x8004, 0x8004, 0x9084, 0x0003, 0x0002, 0x7046, 0x7142, 0x7061, - 0x70d3, 0x080c, 0x0d85, 0x2009, 0x1948, 0x2104, 0x0002, 0x7026, - 0x7026, 0x7026, 0x6eb5, 0x7026, 0x6eb5, 0x0005, 0x2071, 0x1800, - 0x2900, 0x7822, 0xa804, 0x900d, 0x1120, 0x00fe, 0x002e, 0x00ee, - 0x0005, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, - 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8899, - 0x0c60, 0x2071, 0x1800, 0x2900, 0x7822, 0xa804, 0x900d, 0x1904, - 0x70c2, 0x7830, 0xd0dc, 0x1120, 0x00fe, 0x002e, 0x00ee, 0x0005, - 0x7824, 0x00e6, 0x2071, 0x0040, 0x712c, 0xd19c, 0x1170, 0x2009, - 0x1830, 0x210c, 0x918a, 0x0020, 0x0240, 0x7022, 0x2001, 0x1dc0, - 0x200c, 0x8108, 0x2102, 0x00ee, 0x0058, 0x00ee, 0x2048, 0x702c, - 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, 0x8899, - 0x782c, 0x9094, 0x0780, 0x190c, 0x7382, 0xd0a4, 0x19c8, 0x0e04, - 0x70b9, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, - 0x6836, 0x6833, 0x0013, 0x00de, 0x2001, 0x1921, 0x200c, 0xc184, - 0x2102, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, - 0x1200, 0x2001, 0x1922, 0x2003, 0x0000, 0x00fe, 0x002e, 0x00ee, - 0x0005, 0x2001, 0x1921, 0x200c, 0xc185, 0x2102, 0x00fe, 0x002e, - 0x00ee, 0x0005, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, - 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, - 0x8899, 0x0804, 0x7070, 0x0096, 0x00e6, 0x7824, 0x2048, 0x2071, - 0x1800, 0x702c, 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, - 0x080c, 0x8899, 0x782c, 0x9094, 0x0780, 0x190c, 0x7382, 0xd0a4, - 0x1d60, 0x00ee, 0x0e04, 0x7115, 0x7838, 0x7938, 0x910e, 0x1de0, - 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x7044, - 0xc084, 0x7046, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, - 0x190c, 0x1200, 0x704b, 0x0000, 0x782c, 0x9094, 0x0780, 0x190c, - 0x7382, 0xd09c, 0x1170, 0x009e, 0x2900, 0x7822, 0xa804, 0x900d, - 0x11e0, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x7044, 0xc085, 0x7046, - 0x0c58, 0x009e, 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, - 0x711a, 0x0110, 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, - 0x1120, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2071, 0x1800, 0x9016, - 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, - 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8899, 0x00fe, 0x002e, - 0x00ee, 0x0005, 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, - 0x711a, 0x0110, 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, - 0x1904, 0x71b1, 0x782c, 0x9094, 0x0780, 0x190c, 0x7382, 0xd09c, - 0x11b0, 0x701c, 0x904d, 0x0198, 0xa84c, 0x9005, 0x1180, 0x7010, - 0x8001, 0x7012, 0x1108, 0x701a, 0xa800, 0x701e, 0x2900, 0x7822, - 0x782c, 0x9094, 0x0780, 0x190c, 0x7382, 0xd09c, 0x0d50, 0x782c, - 0x9094, 0x0780, 0x190c, 0x7382, 0xd0a4, 0x05b8, 0x00e6, 0x7824, - 0x2048, 0x2071, 0x1800, 0x702c, 0xa802, 0x2900, 0x702e, 0x70c0, - 0x8000, 0x70c2, 0x080c, 0x8899, 0x782c, 0x9094, 0x0780, 0x190c, - 0x7382, 0xd0a4, 0x1d60, 0x00ee, 0x0e04, 0x71aa, 0x7838, 0x7938, - 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, - 0x00de, 0x7044, 0xc084, 0x7046, 0x2091, 0x4080, 0x2001, 0x0089, - 0x2004, 0xd084, 0x190c, 0x1200, 0x704b, 0x0000, 0x00fe, 0x002e, - 0x00ee, 0x0005, 0x7044, 0xc085, 0x7046, 0x00fe, 0x002e, 0x00ee, - 0x0005, 0x00e6, 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, - 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, - 0x70c2, 0x080c, 0x8899, 0x00ee, 0x0804, 0x7152, 0x2071, 0x1910, - 0xa803, 0x0000, 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, - 0x711a, 0x0110, 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, - 0x1128, 0x1e04, 0x71f1, 0x002e, 0x00ee, 0x0005, 0x2071, 0x1800, - 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, - 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8899, 0x0e04, - 0x71db, 0x2071, 0x1910, 0x701c, 0x2048, 0xa84c, 0x900d, 0x0d18, - 0x2071, 0x0000, 0x7182, 0xa850, 0x7032, 0xa86c, 0x7086, 0x7036, - 0xa870, 0x708a, 0xa850, 0x9082, 0x0019, 0x1278, 0x2091, 0x4080, - 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1200, 0x2071, 0x1910, - 0x080c, 0x736e, 0x002e, 0x00ee, 0x0005, 0xa850, 0x9082, 0x001c, - 0x1e68, 0xa880, 0x708e, 0x7036, 0x0146, 0x01d6, 0x0136, 0x01c6, - 0x0156, 0x20e9, 0x0000, 0x20a1, 0x002a, 0xa868, 0x20a8, 0xa860, - 0x20e0, 0xa85c, 0x9080, 0x0021, 0x2098, 0x4003, 0x015e, 0x01ce, - 0x013e, 0x01de, 0x014e, 0x0890, 0x2071, 0x1910, 0xa803, 0x0000, - 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, - 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1118, 0x002e, - 0x00ee, 0x0005, 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, - 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, - 0x70c2, 0x080c, 0x8899, 0x002e, 0x00ee, 0x0005, 0x0006, 0xa87c, - 0x0006, 0xa867, 0x0103, 0x20a9, 0x001c, 0xa860, 0x20e8, 0xa85c, - 0x9080, 0x001d, 0x20a0, 0x9006, 0x4004, 0x000e, 0x9084, 0x00ff, - 0xa87e, 0x000e, 0xa87a, 0xa982, 0x0005, 0x2071, 0x1910, 0x7004, - 0x0002, 0x7281, 0x7282, 0x736d, 0x7282, 0x727f, 0x736d, 0x080c, - 0x0d85, 0x0005, 0x2001, 0x1948, 0x2004, 0x0002, 0x728c, 0x728c, - 0x7306, 0x7307, 0x728c, 0x7307, 0x0126, 0x2091, 0x8000, 0x1e0c, - 0x738d, 0x701c, 0x904d, 0x0508, 0xa84c, 0x9005, 0x0904, 0x72d7, - 0x0e04, 0x72b5, 0xa94c, 0x2071, 0x0000, 0x7182, 0xa850, 0x7032, - 0xa86c, 0x7086, 0x7036, 0xa870, 0x708a, 0xa850, 0x9082, 0x0019, - 0x1278, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, - 0x1200, 0x2071, 0x1910, 0x080c, 0x736e, 0x012e, 0x0804, 0x7305, - 0xa850, 0x9082, 0x001c, 0x1e68, 0xa880, 0x708e, 0x7036, 0x0146, - 0x01d6, 0x0136, 0x01c6, 0x0156, 0x20e9, 0x0000, 0x20a1, 0x002a, - 0xa868, 0x20a8, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x0021, 0x2098, - 0x4003, 0x015e, 0x01ce, 0x013e, 0x01de, 0x014e, 0x0890, 0x2001, - 0x005b, 0x2004, 0x9094, 0x0780, 0x190c, 0x7382, 0xd09c, 0x2071, - 0x1910, 0x1510, 0x2071, 0x1910, 0x700f, 0x0001, 0xa964, 0x9184, - 0x00ff, 0x9086, 0x0003, 0x1130, 0x810f, 0x918c, 0x00ff, 0x8101, - 0x0108, 0x710e, 0x2900, 0x00d6, 0x2069, 0x0050, 0x6822, 0x00de, - 0x2071, 0x1910, 0x701c, 0x2048, 0x7010, 0x8001, 0x7012, 0xa800, - 0x701e, 0x9005, 0x1108, 0x701a, 0x012e, 0x0005, 0x0005, 0x00d6, - 0x2008, 0x2069, 0x1a04, 0x6844, 0x9005, 0x0760, 0x0158, 0x9186, - 0x0003, 0x0540, 0x2001, 0x1815, 0x2004, 0x2009, 0x1b73, 0x210c, - 0x9102, 0x1500, 0x0126, 0x2091, 0x8000, 0x2069, 0x0050, 0x693c, - 0x6838, 0x9106, 0x0190, 0x0e04, 0x7339, 0x2069, 0x0000, 0x6837, - 0x8040, 0x6833, 0x0012, 0x6883, 0x8040, 0x2091, 0x4080, 0x2001, - 0x0089, 0x2004, 0xd084, 0x190c, 0x1200, 0x2069, 0x1a04, 0x6847, - 0xffff, 0x012e, 0x00de, 0x0126, 0x2091, 0x8000, 0x1e0c, 0x73fd, - 0x701c, 0x904d, 0x0540, 0x2001, 0x005b, 0x2004, 0x9094, 0x0780, - 0x15c9, 0xd09c, 0x1500, 0x2071, 0x1910, 0x700f, 0x0001, 0xa964, - 0x9184, 0x00ff, 0x9086, 0x0003, 0x1130, 0x810f, 0x918c, 0x00ff, - 0x8101, 0x0108, 0x710e, 0x2900, 0x00d6, 0x2069, 0x0050, 0x6822, - 0x00de, 0x701c, 0x2048, 0x7010, 0x8001, 0x7012, 0xa800, 0x701e, - 0x9005, 0x1108, 0x701a, 0x012e, 0x0005, 0x0005, 0x0126, 0x2091, - 0x8000, 0x701c, 0x904d, 0x0160, 0x7010, 0x8001, 0x7012, 0xa800, - 0x701e, 0x9005, 0x1108, 0x701a, 0x012e, 0x080c, 0x108b, 0x0005, - 0x012e, 0x0005, 0x2091, 0x8000, 0x0e04, 0x7384, 0x0006, 0x0016, - 0x2001, 0x8004, 0x0006, 0x0804, 0x0d8e, 0x0096, 0x00f6, 0x2079, - 0x0050, 0x7044, 0xd084, 0x01d0, 0xc084, 0x7046, 0x7838, 0x7938, - 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, - 0x00de, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, - 0x1200, 0x704b, 0x0000, 0x00fe, 0x009e, 0x0005, 0x782c, 0x9094, - 0x0780, 0x1981, 0xd0a4, 0x0db8, 0x7148, 0x704c, 0x8108, 0x714a, - 0x9102, 0x0e88, 0x00e6, 0x2071, 0x1800, 0x7824, 0x00e6, 0x2071, - 0x0040, 0x712c, 0xd19c, 0x1170, 0x2009, 0x1830, 0x210c, 0x918a, - 0x0020, 0x0240, 0x7022, 0x2001, 0x1dc0, 0x200c, 0x8108, 0x2102, - 0x00ee, 0x0058, 0x00ee, 0x2048, 0x702c, 0xa802, 0x2900, 0x702e, - 0x70c0, 0x8000, 0x70c2, 0x080c, 0x8899, 0x782c, 0x9094, 0x0780, - 0x190c, 0x7382, 0xd0a4, 0x19c8, 0x7838, 0x7938, 0x910e, 0x1de0, - 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x2091, - 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1200, 0x00ee, - 0x704b, 0x0000, 0x00fe, 0x009e, 0x0005, 0x00f6, 0x2079, 0x0050, - 0x7044, 0xd084, 0x01b8, 0xc084, 0x7046, 0x7838, 0x7938, 0x910e, - 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, - 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1200, - 0x00fe, 0x0005, 0x782c, 0x9094, 0x0780, 0x190c, 0x7382, 0xd0a4, - 0x0db8, 0x00e6, 0x2071, 0x1800, 0x7824, 0x2048, 0x702c, 0xa802, - 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, 0x8899, 0x782c, - 0x9094, 0x0780, 0x190c, 0x7382, 0xd0a4, 0x1d70, 0x00d6, 0x2069, - 0x0050, 0x693c, 0x2069, 0x1948, 0x6808, 0x690a, 0x2069, 0x1a04, - 0x9102, 0x1118, 0x6844, 0x9005, 0x1320, 0x2001, 0x1949, 0x200c, - 0x6946, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x7098, 0x908a, 0x002a, - 0x1a0c, 0x0d85, 0x9082, 0x001d, 0x003b, 0x0026, 0x2011, 0x1e00, - 0x080c, 0x2ad3, 0x002e, 0x0005, 0x7542, 0x74af, 0x74cb, 0x74f5, - 0x7531, 0x7571, 0x7583, 0x74cb, 0x7559, 0x746a, 0x7498, 0x751b, - 0x7469, 0x0005, 0x00d6, 0x2069, 0x0200, 0x6804, 0x9005, 0x1180, - 0x6808, 0x9005, 0x1518, 0x709b, 0x0029, 0x2069, 0x198f, 0x2d04, - 0x7002, 0x080c, 0x78e4, 0x6028, 0x9085, 0x0600, 0x602a, 0x00b0, - 0x709b, 0x0029, 0x2069, 0x198f, 0x2d04, 0x7002, 0x6028, 0x9085, - 0x0600, 0x602a, 0x00e6, 0x0036, 0x0046, 0x0056, 0x2071, 0x1a6e, - 0x080c, 0x1b1e, 0x005e, 0x004e, 0x003e, 0x00ee, 0x00de, 0x0005, - 0x00d6, 0x2069, 0x0200, 0x6804, 0x9005, 0x1178, 0x6808, 0x9005, - 0x1160, 0x709b, 0x0029, 0x2069, 0x198f, 0x2d04, 0x7002, 0x080c, - 0x7990, 0x6028, 0x9085, 0x0600, 0x602a, 0x00de, 0x0005, 0x0006, - 0x2001, 0x0090, 0x080c, 0x2a99, 0x000e, 0x6124, 0xd1e4, 0x1190, - 0x080c, 0x75f4, 0xd1d4, 0x1160, 0xd1dc, 0x1138, 0xd1cc, 0x0150, - 0x709b, 0x0020, 0x080c, 0x75f4, 0x0028, 0x709b, 0x001d, 0x0010, - 0x709b, 0x001f, 0x0005, 0x2001, 0x0088, 0x080c, 0x2a99, 0x6124, - 0xd1cc, 0x11e8, 0xd1dc, 0x11c0, 0xd1e4, 0x1198, 0x9184, 0x1e00, - 0x11d8, 0x080c, 0x1b4b, 0x60e3, 0x0001, 0x600c, 0xc0b4, 0x600e, - 0x080c, 0x77ca, 0x2001, 0x0080, 0x080c, 0x2a99, 0x709b, 0x0029, - 0x0058, 0x709b, 0x001e, 0x0040, 0x709b, 0x001d, 0x0028, 0x709b, - 0x0020, 0x0010, 0x709b, 0x001f, 0x0005, 0x080c, 0x1b4b, 0x60e3, - 0x0001, 0x600c, 0xc0b4, 0x600e, 0x080c, 0x77ca, 0x2001, 0x0080, - 0x080c, 0x2a99, 0x6124, 0xd1d4, 0x1198, 0xd1dc, 0x1170, 0xd1e4, - 0x1148, 0x9184, 0x1e00, 0x1118, 0x709b, 0x0029, 0x0058, 0x709b, - 0x0028, 0x0040, 0x709b, 0x001e, 0x0028, 0x709b, 0x001d, 0x0010, - 0x709b, 0x001f, 0x0005, 0x6124, 0xd1d4, 0x1180, 0xd1dc, 0x1158, - 0xd1e4, 0x1130, 0x9184, 0x1e00, 0x1158, 0x709b, 0x0029, 0x0040, - 0x709b, 0x001e, 0x0028, 0x709b, 0x001d, 0x0010, 0x709b, 0x001f, - 0x0005, 0x2001, 0x00a0, 0x080c, 0x2a99, 0x6124, 0xd1dc, 0x1138, - 0xd1e4, 0x0138, 0x080c, 0x1b4b, 0x709b, 0x001e, 0x0010, 0x709b, - 0x001d, 0x0005, 0x080c, 0x767d, 0x6124, 0xd1dc, 0x1188, 0x080c, - 0x75f4, 0x0016, 0x080c, 0x1b4b, 0x001e, 0xd1d4, 0x1128, 0xd1e4, - 0x0138, 0x709b, 0x001e, 0x0020, 0x709b, 0x001f, 0x080c, 0x75f4, - 0x0005, 0x0006, 0x2001, 0x00a0, 0x080c, 0x2a99, 0x000e, 0x6124, - 0xd1d4, 0x1160, 0xd1cc, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, - 0x709b, 0x001e, 0x0028, 0x709b, 0x001d, 0x0010, 0x709b, 0x0021, - 0x0005, 0x080c, 0x767d, 0x6124, 0xd1d4, 0x1150, 0xd1dc, 0x1128, - 0xd1e4, 0x0140, 0x709b, 0x001e, 0x0028, 0x709b, 0x001d, 0x0010, - 0x709b, 0x001f, 0x0005, 0x0006, 0x2001, 0x0090, 0x080c, 0x2a99, - 0x000e, 0x6124, 0xd1d4, 0x1178, 0xd1cc, 0x1150, 0xd1dc, 0x1128, - 0xd1e4, 0x0158, 0x709b, 0x001e, 0x0040, 0x709b, 0x001d, 0x0028, - 0x709b, 0x0020, 0x0010, 0x709b, 0x001f, 0x0005, 0x0016, 0x00c6, - 0x00d6, 0x00e6, 0x0126, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, - 0x1800, 0x2091, 0x8000, 0x080c, 0x779e, 0x11f8, 0x2001, 0x180c, - 0x200c, 0xd1b4, 0x01d0, 0xc1b4, 0x2102, 0x0026, 0x2011, 0x0200, - 0x080c, 0x2ad3, 0x002e, 0x080c, 0x2a7f, 0x6024, 0xd0cc, 0x0148, - 0x2001, 0x00a0, 0x080c, 0x2a99, 0x080c, 0x7ab6, 0x080c, 0x619d, - 0x0428, 0x6028, 0xc0cd, 0x602a, 0x0408, 0x080c, 0x77b8, 0x0150, - 0x080c, 0x77af, 0x1138, 0x2001, 0x0001, 0x080c, 0x2631, 0x080c, - 0x7772, 0x00a0, 0x080c, 0x767a, 0x0178, 0x2001, 0x0001, 0x080c, - 0x2631, 0x7098, 0x9086, 0x001e, 0x0120, 0x7098, 0x9086, 0x0022, - 0x1118, 0x709b, 0x0025, 0x0010, 0x709b, 0x0021, 0x012e, 0x00ee, - 0x00de, 0x00ce, 0x001e, 0x0005, 0x0026, 0x2011, 0x7605, 0x080c, - 0x8a9f, 0x002e, 0x0016, 0x0026, 0x2009, 0x0064, 0x2011, 0x7605, - 0x080c, 0x8a96, 0x002e, 0x001e, 0x0005, 0x00e6, 0x00f6, 0x0016, - 0x080c, 0xa2a0, 0x2071, 0x1800, 0x080c, 0x759e, 0x001e, 0x00fe, - 0x00ee, 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, - 0x00f6, 0x0126, 0x2071, 0x1800, 0x080c, 0xa2a0, 0x2061, 0x0100, - 0x2069, 0x0140, 0x2091, 0x8000, 0x6028, 0xc09c, 0x602a, 0x080c, - 0xacfc, 0x2011, 0x0003, 0x080c, 0xa62b, 0x2011, 0x0002, 0x080c, - 0xa635, 0x080c, 0xa516, 0x080c, 0x8a4b, 0x0036, 0x901e, 0x080c, - 0xa596, 0x003e, 0x080c, 0xad18, 0x60e3, 0x0000, 0x080c, 0xeed9, - 0x080c, 0xeef4, 0x2009, 0x0004, 0x080c, 0x2a85, 0x080c, 0x299b, - 0x2001, 0x1800, 0x2003, 0x0004, 0x2011, 0x0008, 0x080c, 0x2ad3, - 0x2011, 0x7605, 0x080c, 0x8a9f, 0x080c, 0x77b8, 0x0118, 0x9006, - 0x080c, 0x2a99, 0x080c, 0x0bcf, 0x2001, 0x0001, 0x080c, 0x2631, - 0x012e, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, - 0x0005, 0x0026, 0x00e6, 0x2011, 0x7612, 0x2071, 0x1a04, 0x701c, - 0x9206, 0x1118, 0x7018, 0x9005, 0x0110, 0x9085, 0x0001, 0x00ee, - 0x002e, 0x0005, 0x6020, 0xd09c, 0x0005, 0x6800, 0x9084, 0xfffe, - 0x9086, 0x00c0, 0x01b8, 0x2001, 0x00c0, 0x080c, 0x2a99, 0x0156, - 0x20a9, 0x002d, 0x1d04, 0x768a, 0x2091, 0x6000, 0x1f04, 0x768a, - 0x015e, 0x00d6, 0x2069, 0x1800, 0x689c, 0x8001, 0x0220, 0x0118, - 0x689e, 0x00de, 0x0005, 0x689f, 0x0014, 0x68ec, 0xd0dc, 0x0dc8, - 0x6800, 0x9086, 0x0001, 0x1da8, 0x080c, 0x8aab, 0x0c90, 0x00c6, - 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1800, - 0x080c, 0x7ac5, 0x2001, 0x196d, 0x2003, 0x0000, 0x9006, 0x709a, - 0x60e2, 0x6886, 0x080c, 0x2700, 0x9006, 0x080c, 0x2a99, 0x080c, - 0x6058, 0x0026, 0x2011, 0xffff, 0x080c, 0x2ad3, 0x002e, 0x602b, - 0x182c, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x00e6, - 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1800, 0x2001, 0x197d, - 0x200c, 0x9186, 0x0000, 0x0158, 0x9186, 0x0001, 0x0158, 0x9186, - 0x0002, 0x0158, 0x9186, 0x0003, 0x0158, 0x0804, 0x7762, 0x709b, - 0x0022, 0x0040, 0x709b, 0x0021, 0x0028, 0x709b, 0x0023, 0x0010, - 0x709b, 0x0024, 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, - 0x080c, 0x2700, 0x080c, 0xacfc, 0x0026, 0x080c, 0xafd2, 0x080c, - 0xb09b, 0x002e, 0x080c, 0xad18, 0x7000, 0x908e, 0x0004, 0x0118, - 0x602b, 0x0028, 0x0010, 0x602b, 0x0020, 0x0156, 0x0126, 0x2091, - 0x8000, 0x20a9, 0x0005, 0x6024, 0xd0ac, 0x0150, 0x012e, 0x015e, - 0x080c, 0xd645, 0x0118, 0x9006, 0x080c, 0x2ac3, 0x0804, 0x776e, - 0x6800, 0x9084, 0x00a1, 0xc0bd, 0x6802, 0x080c, 0x2a7f, 0x6904, - 0xd1d4, 0x1140, 0x2001, 0x0100, 0x080c, 0x2a99, 0x1f04, 0x7713, - 0x080c, 0x77f2, 0x012e, 0x015e, 0x080c, 0x77af, 0x0170, 0x6044, - 0x9005, 0x0130, 0x080c, 0x77f2, 0x9006, 0x8001, 0x1df0, 0x0028, - 0x6804, 0xd0d4, 0x1110, 0x080c, 0x77f2, 0x080c, 0xd645, 0x0118, - 0x9006, 0x080c, 0x2ac3, 0x0016, 0x0026, 0x7000, 0x908e, 0x0004, - 0x0130, 0x2009, 0x00c8, 0x2011, 0x7612, 0x080c, 0x8a5d, 0x002e, - 0x001e, 0x080c, 0x8890, 0x7034, 0xc085, 0x7036, 0x2001, 0x197d, - 0x2003, 0x0004, 0x080c, 0x744d, 0x080c, 0x77af, 0x0138, 0x6804, - 0xd0d4, 0x1120, 0xd0dc, 0x1100, 0x080c, 0x7abb, 0x00ee, 0x00de, - 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, - 0x0140, 0x2071, 0x1800, 0x080c, 0x88a7, 0x080c, 0x8899, 0x080c, - 0x7ac5, 0x2001, 0x196d, 0x2003, 0x0000, 0x9006, 0x709a, 0x60e2, - 0x6886, 0x080c, 0x2700, 0x9006, 0x080c, 0x2a99, 0x6043, 0x0090, - 0x6043, 0x0010, 0x0026, 0x2011, 0xffff, 0x080c, 0x2ad3, 0x002e, - 0x602b, 0x182c, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x0006, 0x2001, - 0x197c, 0x2004, 0x9086, 0xaaaa, 0x000e, 0x0005, 0x0006, 0x080c, - 0x5844, 0x9084, 0x0030, 0x9086, 0x0000, 0x000e, 0x0005, 0x0006, - 0x080c, 0x5844, 0x9084, 0x0030, 0x9086, 0x0030, 0x000e, 0x0005, - 0x0006, 0x080c, 0x5844, 0x9084, 0x0030, 0x9086, 0x0010, 0x000e, - 0x0005, 0x0006, 0x080c, 0x5844, 0x9084, 0x0030, 0x9086, 0x0020, - 0x000e, 0x0005, 0x0036, 0x0016, 0x2001, 0x180c, 0x2004, 0x908c, - 0x0013, 0x0168, 0x0020, 0x080c, 0x2720, 0x900e, 0x0010, 0x2009, - 0x0002, 0x2019, 0x0028, 0x080c, 0x32da, 0x9006, 0x0019, 0x001e, - 0x003e, 0x0005, 0x00e6, 0x2071, 0x180c, 0x2e04, 0x0130, 0x080c, - 0xd63e, 0x1128, 0x9085, 0x0010, 0x0010, 0x9084, 0xffef, 0x2072, - 0x00ee, 0x0005, 0x6050, 0x0006, 0x60ec, 0x0006, 0x600c, 0x0006, - 0x6004, 0x0006, 0x6028, 0x0006, 0x080c, 0x2af6, 0x080c, 0x2b29, - 0x602f, 0x0100, 0x602f, 0x0000, 0x602f, 0x0040, 0x602f, 0x0000, - 0x20a9, 0x0002, 0x080c, 0x2a60, 0x0026, 0x2011, 0x0040, 0x080c, - 0x2ad3, 0x002e, 0x000e, 0x602a, 0x000e, 0x6006, 0x000e, 0x600e, - 0x000e, 0x60ee, 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, - 0x080c, 0x2700, 0x2001, 0x00a0, 0x0006, 0x080c, 0xd645, 0x000e, - 0x0130, 0x080c, 0x2ab7, 0x9006, 0x080c, 0x2ac3, 0x0010, 0x080c, - 0x2a99, 0x000e, 0x6052, 0x6050, 0x0006, 0xc0e5, 0x6052, 0x00f6, - 0x2079, 0x0100, 0x080c, 0x2a0c, 0x00fe, 0x000e, 0x6052, 0x0005, - 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, 0x2061, - 0x0100, 0x2069, 0x0140, 0x2071, 0x1800, 0x080c, 0xad5a, 0x0158, - 0x2001, 0x0386, 0x2004, 0xd0b4, 0x1130, 0x2001, 0x0016, 0x080c, - 0xaced, 0x0804, 0x78d6, 0x2001, 0x180c, 0x200c, 0xc1c4, 0x2102, - 0x6028, 0x9084, 0xe1ff, 0x602a, 0x2011, 0x0200, 0x080c, 0x2ad3, - 0x2001, 0x0090, 0x080c, 0x2a99, 0x20a9, 0x0366, 0x6024, 0xd0cc, - 0x1560, 0x1d04, 0x786e, 0x2091, 0x6000, 0x1f04, 0x786e, 0x080c, - 0xacfc, 0x2011, 0x0003, 0x080c, 0xa62b, 0x2011, 0x0002, 0x080c, - 0xa635, 0x080c, 0xa516, 0x901e, 0x080c, 0xa596, 0x2001, 0x0386, - 0x2003, 0x7000, 0x080c, 0xad18, 0x2001, 0x00a0, 0x080c, 0x2a99, - 0x080c, 0x7ab6, 0x080c, 0x619d, 0x080c, 0xd645, 0x0110, 0x080c, - 0x0cf1, 0x9085, 0x0001, 0x0804, 0x78dc, 0x080c, 0x1b4b, 0x60e3, - 0x0000, 0x2001, 0x180d, 0x2004, 0xd08c, 0x2001, 0x0002, 0x1118, - 0x2001, 0x196d, 0x2004, 0x080c, 0x2700, 0x60e2, 0x2001, 0x0080, - 0x080c, 0x2a99, 0x20a9, 0x0366, 0x2011, 0x1e00, 0x080c, 0x2ad3, - 0x2009, 0x1e00, 0x080c, 0x2a7f, 0x6024, 0x910c, 0x0140, 0x1d04, - 0x78b4, 0x2091, 0x6000, 0x1f04, 0x78b4, 0x0804, 0x7877, 0x2001, - 0x0386, 0x2003, 0x7000, 0x6028, 0x9085, 0x1e00, 0x602a, 0x70b4, - 0x9005, 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, 0x080c, 0xd645, - 0x0110, 0x080c, 0x0cf1, 0x9006, 0x00ee, 0x00de, 0x00ce, 0x003e, - 0x002e, 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, - 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2071, 0x1800, 0x7000, - 0x9086, 0x0003, 0x1168, 0x2001, 0x020b, 0x2004, 0x9084, 0x5540, - 0x9086, 0x5540, 0x1128, 0x2069, 0x1a7b, 0x2d04, 0x8000, 0x206a, - 0x2069, 0x0140, 0x6020, 0x9084, 0x00c0, 0x0120, 0x6884, 0x9005, - 0x1904, 0x794d, 0x2001, 0x0088, 0x080c, 0x2a99, 0x9006, 0x60e2, - 0x6886, 0x080c, 0x2700, 0x2069, 0x0200, 0x6804, 0x9005, 0x1118, - 0x6808, 0x9005, 0x01d0, 0x6028, 0x9084, 0xfbff, 0x602a, 0x2011, - 0x0400, 0x080c, 0x2ad3, 0x2069, 0x198f, 0x7000, 0x206a, 0x709b, - 0x0026, 0x7003, 0x0001, 0x20a9, 0x0002, 0x1d04, 0x792d, 0x2091, - 0x6000, 0x1f04, 0x792d, 0x0804, 0x7988, 0x2069, 0x0140, 0x20a9, - 0x0384, 0x2011, 0x1e00, 0x080c, 0x2ad3, 0x2009, 0x1e00, 0x080c, - 0x2a7f, 0x6024, 0x910c, 0x0528, 0x9084, 0x1a00, 0x1510, 0x1d04, - 0x7939, 0x2091, 0x6000, 0x1f04, 0x7939, 0x080c, 0xacfc, 0x2011, - 0x0003, 0x080c, 0xa62b, 0x2011, 0x0002, 0x080c, 0xa635, 0x080c, - 0xa516, 0x901e, 0x080c, 0xa596, 0x080c, 0xad18, 0x2001, 0x00a0, - 0x080c, 0x2a99, 0x080c, 0x7ab6, 0x080c, 0x619d, 0x9085, 0x0001, - 0x00f8, 0x080c, 0x1b4b, 0x2001, 0x0080, 0x080c, 0x2a99, 0x2069, - 0x0140, 0x60e3, 0x0000, 0x70b4, 0x9005, 0x1118, 0x6887, 0x0001, - 0x0008, 0x6886, 0x2001, 0x180d, 0x2004, 0xd08c, 0x2001, 0x0002, - 0x1118, 0x2001, 0x196d, 0x2004, 0x080c, 0x2700, 0x60e2, 0x9006, - 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, - 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, 0x2061, - 0x0100, 0x2071, 0x1800, 0x6020, 0x9084, 0x00c0, 0x01e8, 0x080c, - 0xacfc, 0x2011, 0x0003, 0x080c, 0xa62b, 0x2011, 0x0002, 0x080c, - 0xa635, 0x080c, 0xa516, 0x901e, 0x080c, 0xa596, 0x080c, 0xad18, - 0x2069, 0x0140, 0x2001, 0x00a0, 0x080c, 0x2a99, 0x080c, 0x7ab6, - 0x080c, 0x619d, 0x0804, 0x7a32, 0x2001, 0x180c, 0x200c, 0xd1b4, - 0x1160, 0xc1b5, 0x2102, 0x080c, 0x75fa, 0x2069, 0x0140, 0x2001, - 0x0080, 0x080c, 0x2a99, 0x60e3, 0x0000, 0x2069, 0x0200, 0x6804, - 0x9005, 0x1118, 0x6808, 0x9005, 0x0190, 0x6028, 0x9084, 0xfdff, - 0x602a, 0x2011, 0x0200, 0x080c, 0x2ad3, 0x2069, 0x198f, 0x7000, - 0x206a, 0x709b, 0x0027, 0x7003, 0x0001, 0x0804, 0x7a32, 0x2011, - 0x1e00, 0x080c, 0x2ad3, 0x2009, 0x1e00, 0x080c, 0x2a7f, 0x6024, - 0x910c, 0x01c8, 0x9084, 0x1c00, 0x11b0, 0x1d04, 0x79e7, 0x0006, - 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x080c, 0x88e7, 0x00ee, 0x00de, - 0x00ce, 0x001e, 0x000e, 0x00e6, 0x2071, 0x1a04, 0x7078, 0x00ee, - 0x9005, 0x19e8, 0x0438, 0x0026, 0x2011, 0x7612, 0x080c, 0x8993, - 0x2011, 0x7605, 0x080c, 0x8a9f, 0x002e, 0x2069, 0x0140, 0x60e3, - 0x0000, 0x70b4, 0x9005, 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, - 0x2001, 0x180d, 0x2004, 0xd08c, 0x2001, 0x0002, 0x1118, 0x2001, - 0x196d, 0x2004, 0x080c, 0x2700, 0x60e2, 0x2001, 0x180c, 0x200c, - 0xc1b4, 0x2102, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, - 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x0046, 0x00c6, - 0x00e6, 0x2061, 0x0100, 0x2071, 0x1800, 0x080c, 0xd63e, 0x1904, - 0x7aa0, 0x7130, 0xd184, 0x1170, 0x080c, 0x3482, 0x0138, 0xc18d, - 0x7132, 0x2011, 0x1848, 0x2214, 0xd2ac, 0x1120, 0x7030, 0xd08c, - 0x0904, 0x7aa0, 0x2011, 0x1848, 0x220c, 0xd1a4, 0x0538, 0x0016, - 0x2019, 0x000e, 0x080c, 0xe9f9, 0x0156, 0x00b6, 0x20a9, 0x007f, - 0x900e, 0x9186, 0x007e, 0x01a0, 0x9186, 0x0080, 0x0188, 0x080c, - 0x67b4, 0x1170, 0x2120, 0x9006, 0x0016, 0x2009, 0x000e, 0x080c, - 0xea8d, 0x2009, 0x0001, 0x2011, 0x0100, 0x080c, 0x8c44, 0x001e, - 0x8108, 0x1f04, 0x7a69, 0x00be, 0x015e, 0x001e, 0xd1ac, 0x1148, - 0x0016, 0x2009, 0x0002, 0x2019, 0x0004, 0x080c, 0x32da, 0x001e, - 0x0078, 0x0156, 0x00b6, 0x20a9, 0x007f, 0x900e, 0x080c, 0x67b4, - 0x1110, 0x080c, 0x61b7, 0x8108, 0x1f04, 0x7a96, 0x00be, 0x015e, - 0x080c, 0x1b4b, 0x080c, 0xacfc, 0x080c, 0xb09b, 0x080c, 0xad18, - 0x60e3, 0x0000, 0x080c, 0x619d, 0x080c, 0x76cd, 0x00ee, 0x00ce, - 0x004e, 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, 0x2001, 0x197d, - 0x2003, 0x0001, 0x0005, 0x2001, 0x197d, 0x2003, 0x0000, 0x0005, - 0x2001, 0x197c, 0x2003, 0xaaaa, 0x0005, 0x2001, 0x197c, 0x2003, - 0x0000, 0x0005, 0x2071, 0x18fa, 0x7003, 0x0000, 0x7007, 0x0000, - 0x080c, 0x1072, 0x090c, 0x0d85, 0xa8ab, 0xdcb0, 0x2900, 0x704e, - 0x080c, 0x1072, 0x090c, 0x0d85, 0xa8ab, 0xdcb0, 0x2900, 0x7052, - 0xa867, 0x0000, 0xa86b, 0x0001, 0xa89f, 0x0000, 0x0005, 0x00e6, - 0x2071, 0x0040, 0x6848, 0x9005, 0x1118, 0x9085, 0x0001, 0x04b0, - 0x6840, 0x9005, 0x0150, 0x04a1, 0x6a50, 0x9200, 0x7002, 0x6854, - 0x9101, 0x7006, 0x9006, 0x7012, 0x7016, 0x6850, 0x7002, 0x6854, - 0x7006, 0x6858, 0x700a, 0x685c, 0x700e, 0x6840, 0x9005, 0x1110, - 0x7012, 0x7016, 0x6848, 0x701a, 0x701c, 0x9085, 0x0040, 0x701e, - 0x2001, 0x0019, 0x7036, 0x702b, 0x0001, 0x2001, 0x0004, 0x200c, - 0x918c, 0xfff7, 0x918d, 0x8000, 0x2102, 0x00d6, 0x2069, 0x18fa, - 0x6807, 0x0001, 0x00de, 0x080c, 0x8103, 0x9006, 0x00ee, 0x0005, - 0x900e, 0x0156, 0x20a9, 0x0006, 0x8003, 0x818d, 0x1f04, 0x7b2c, - 0x015e, 0x0005, 0x2079, 0x0040, 0x2071, 0x18fa, 0x7004, 0x0002, - 0x7b42, 0x7b43, 0x7b8f, 0x7bea, 0x7d4a, 0x7b40, 0x7b40, 0x7d74, - 0x080c, 0x0d85, 0x0005, 0x2079, 0x0040, 0x2001, 0x1dc0, 0x2003, - 0x0000, 0x782c, 0x908c, 0x0780, 0x190c, 0x81e5, 0xd0a4, 0x0578, - 0x2001, 0x1dc0, 0x2004, 0x9082, 0x0080, 0x1648, 0x1d04, 0x7b60, - 0x2001, 0x1a07, 0x200c, 0x8109, 0x0510, 0x2091, 0x6000, 0x2102, - 0x7824, 0x2048, 0x9006, 0xa802, 0xa806, 0xa864, 0x9084, 0x00ff, - 0x908a, 0x0040, 0x0610, 0x00c0, 0x2001, 0x1800, 0x200c, 0x9186, - 0x0003, 0x1168, 0x7004, 0x0002, 0x7b7f, 0x7b49, 0x7b7f, 0x7b7d, - 0x7b7f, 0x7b7f, 0x7b7f, 0x7b7f, 0x7b7f, 0x080c, 0x7bea, 0x782c, - 0xd09c, 0x090c, 0x8103, 0x0005, 0x9082, 0x005a, 0x1218, 0x2100, - 0x003b, 0x0c10, 0x080c, 0x7c20, 0x0c90, 0x00e3, 0x08e8, 0x0005, - 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c20, - 0x7c42, 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c20, - 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c20, - 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c2c, 0x7c20, 0x7e6a, 0x7c20, - 0x7c20, 0x7c20, 0x7c42, 0x7c20, 0x7c2c, 0x7eab, 0x7eec, 0x7f33, - 0x7f47, 0x7c20, 0x7c20, 0x7c42, 0x7c2c, 0x7c56, 0x7c20, 0x7d1e, - 0x7ff2, 0x800d, 0x7c20, 0x7c42, 0x7c20, 0x7c56, 0x7c20, 0x7c20, - 0x7d14, 0x800d, 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c20, - 0x7c20, 0x7c20, 0x7c20, 0x7c6a, 0x7c20, 0x7c20, 0x7c20, 0x7c20, - 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x8189, 0x7c20, 0x8133, - 0x7c20, 0x8133, 0x7c20, 0x7c7f, 0x7c20, 0x7c20, 0x7c20, 0x7c20, - 0x7c20, 0x7c20, 0x2079, 0x0040, 0x7004, 0x9086, 0x0003, 0x1198, - 0x782c, 0x080c, 0x812c, 0xd0a4, 0x0170, 0x7824, 0x2048, 0x9006, - 0xa802, 0xa806, 0xa864, 0x9084, 0x00ff, 0x908a, 0x001a, 0x1210, - 0x002b, 0x0c50, 0x00e9, 0x080c, 0x8103, 0x0005, 0x7c20, 0x7c2c, - 0x7e56, 0x7c20, 0x7c2c, 0x7c20, 0x7c2c, 0x7c2c, 0x7c20, 0x7c2c, - 0x7e56, 0x7c2c, 0x7c2c, 0x7c2c, 0x7c2c, 0x7c2c, 0x7c20, 0x7c2c, - 0x7e56, 0x7c20, 0x7c20, 0x7c2c, 0x7c20, 0x7c20, 0x7c20, 0x7c2c, - 0x00e6, 0x2071, 0x18fa, 0x2009, 0x0400, 0x0071, 0x00ee, 0x0005, - 0x2009, 0x1000, 0x0049, 0x0005, 0x2009, 0x2000, 0x0029, 0x0005, - 0x2009, 0x0800, 0x0009, 0x0005, 0x7007, 0x0001, 0xa868, 0x9084, - 0x00ff, 0x9105, 0xa86a, 0x0126, 0x2091, 0x8000, 0x080c, 0x7012, - 0x012e, 0x0005, 0xa864, 0x8007, 0x9084, 0x00ff, 0x0d08, 0x8001, - 0x1120, 0x7007, 0x0001, 0x0804, 0x7df3, 0x7007, 0x0003, 0x7012, - 0x2900, 0x7016, 0x701a, 0x704b, 0x7df3, 0x0005, 0xa864, 0x8007, - 0x9084, 0x00ff, 0x0968, 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, - 0x7e0e, 0x7007, 0x0003, 0x7012, 0x2900, 0x7016, 0x701a, 0x704b, - 0x7e0e, 0x0005, 0xa864, 0x8007, 0x9084, 0x00ff, 0x0904, 0x7c28, - 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, 0x7e2a, 0x7007, 0x0003, - 0x7012, 0x2900, 0x7016, 0x701a, 0x704b, 0x7e2a, 0x0005, 0xa864, - 0x8007, 0x9084, 0x00ff, 0x9086, 0x0001, 0x1904, 0x7c28, 0x7007, - 0x0001, 0x2009, 0x1834, 0x210c, 0x81ff, 0x1904, 0x7ceb, 0x2001, - 0x180d, 0x2004, 0xd08c, 0x0904, 0x7cd6, 0xa99c, 0x9186, 0x00ff, - 0x05e8, 0xa994, 0x9186, 0x006f, 0x0188, 0x9186, 0x0074, 0x15b0, - 0x0026, 0x2011, 0x0010, 0x080c, 0x6c35, 0x002e, 0x0578, 0x0016, - 0xa998, 0x080c, 0x6c7f, 0x001e, 0x1548, 0x0400, 0x080c, 0x779e, - 0x0140, 0xa897, 0x4005, 0xa89b, 0x0016, 0x2001, 0x0030, 0x900e, - 0x0438, 0x0026, 0x2011, 0x8008, 0x080c, 0x6c35, 0x002e, 0x01b0, - 0x0016, 0x0026, 0x0036, 0xa998, 0xaaa0, 0xab9c, 0x918d, 0x8000, - 0x080c, 0x6c7f, 0x003e, 0x002e, 0x001e, 0x1140, 0xa897, 0x4005, - 0xa89b, 0x4009, 0x2001, 0x0030, 0x900e, 0x0050, 0xa868, 0x9084, - 0x00ff, 0xa86a, 0xa883, 0x0000, 0x080c, 0x6430, 0x1108, 0x0005, - 0x0126, 0x2091, 0x8000, 0xa867, 0x0139, 0xa87a, 0xa982, 0x080c, - 0x7012, 0x012e, 0x0ca0, 0xa994, 0x9186, 0x0071, 0x0904, 0x7c8f, - 0x9186, 0x0064, 0x0904, 0x7c8f, 0x9186, 0x007c, 0x0904, 0x7c8f, - 0x9186, 0x0028, 0x0904, 0x7c8f, 0x9186, 0x0038, 0x0904, 0x7c8f, - 0x9186, 0x0078, 0x0904, 0x7c8f, 0x9186, 0x005f, 0x0904, 0x7c8f, - 0x9186, 0x0056, 0x0904, 0x7c8f, 0xa897, 0x4005, 0xa89b, 0x0001, - 0x2001, 0x0030, 0x900e, 0x0860, 0xa87c, 0x9084, 0x00c0, 0x9086, - 0x00c0, 0x1120, 0x7007, 0x0001, 0x0804, 0x8024, 0x2900, 0x7016, - 0x701a, 0x20a9, 0x0004, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x0030, - 0x2098, 0x7050, 0x2040, 0xa060, 0x20e8, 0xa05c, 0x9080, 0x0023, - 0x20a0, 0x4003, 0xa888, 0x7012, 0x9082, 0x0401, 0x1a04, 0x7c30, - 0xaab4, 0x928a, 0x0002, 0x1a04, 0x7c30, 0x82ff, 0x1138, 0xa8b8, - 0xa9bc, 0x9105, 0x0118, 0x2001, 0x7db1, 0x0018, 0x9280, 0x7da7, - 0x2005, 0x7056, 0x7010, 0x9015, 0x0904, 0x7d92, 0x080c, 0x1072, - 0x1118, 0x7007, 0x0004, 0x0005, 0x2900, 0x7022, 0x7054, 0x2060, - 0xe000, 0xa866, 0x7050, 0x2040, 0xa95c, 0xe004, 0x9100, 0xa076, - 0xa860, 0xa072, 0xe008, 0x920a, 0x1210, 0x900e, 0x2200, 0x7112, - 0xe20c, 0x8003, 0x800b, 0x9296, 0x0004, 0x0108, 0x9108, 0xa17a, - 0x810b, 0xa17e, 0x080c, 0x114e, 0xa06c, 0x908e, 0x0100, 0x0170, - 0x9086, 0x0200, 0x0118, 0x7007, 0x0007, 0x0005, 0x7020, 0x2048, - 0x080c, 0x108b, 0x7014, 0x2048, 0x0804, 0x7c30, 0x7020, 0x2048, - 0x7018, 0xa802, 0xa807, 0x0000, 0x2908, 0x2048, 0xa906, 0x711a, - 0x0804, 0x7d4a, 0x7014, 0x2048, 0x7007, 0x0001, 0xa8b4, 0x9005, - 0x1128, 0xa8b8, 0xa9bc, 0x9105, 0x0108, 0x00b9, 0xa864, 0x9084, - 0x00ff, 0x9086, 0x001e, 0x0904, 0x8024, 0x0804, 0x7df3, 0x7da9, - 0x7dad, 0x0002, 0x001d, 0x0007, 0x0004, 0x000a, 0x001b, 0x0005, - 0x0006, 0x000a, 0x001d, 0x0005, 0x0004, 0x0076, 0x0066, 0xafb8, - 0xaebc, 0xa804, 0x2050, 0xb0c0, 0xb0e2, 0xb0bc, 0xb0de, 0xb0b8, - 0xb0d2, 0xb0b4, 0xb0ce, 0xb6da, 0xb7d6, 0xb0b0, 0xb0ca, 0xb0ac, - 0xb0c6, 0xb0a8, 0xb0ba, 0xb0a4, 0xb0b6, 0xb6c2, 0xb7be, 0xb0a0, - 0xb0b2, 0xb09c, 0xb0ae, 0xb098, 0xb0a2, 0xb094, 0xb09e, 0xb6aa, - 0xb7a6, 0xb090, 0xb09a, 0xb08c, 0xb096, 0xb088, 0xb08a, 0xb084, - 0xb086, 0xb692, 0xb78e, 0xb080, 0xb082, 0xb07c, 0xb07e, 0xb078, - 0xb072, 0xb074, 0xb06e, 0xb67a, 0xb776, 0xb004, 0x9055, 0x1958, - 0x006e, 0x007e, 0x0005, 0x2009, 0x1834, 0x210c, 0x81ff, 0x1178, - 0x080c, 0x622f, 0x1108, 0x0005, 0x080c, 0x725e, 0x0126, 0x2091, - 0x8000, 0x080c, 0xd220, 0x080c, 0x7012, 0x012e, 0x0ca0, 0x080c, - 0xd63e, 0x1d70, 0x2001, 0x0028, 0x900e, 0x0c70, 0x2009, 0x1834, - 0x210c, 0x81ff, 0x1188, 0xa888, 0x9005, 0x0188, 0xa883, 0x0000, - 0x080c, 0x62bd, 0x1108, 0x0005, 0xa87a, 0x0126, 0x2091, 0x8000, - 0x080c, 0x7012, 0x012e, 0x0cb8, 0x2001, 0x0028, 0x0ca8, 0x2001, - 0x0000, 0x0c90, 0x0419, 0x11d8, 0xa888, 0x9005, 0x01e0, 0xa883, - 0x0000, 0xa87c, 0xd0f4, 0x0120, 0x080c, 0x6392, 0x1138, 0x0005, - 0x9006, 0xa87a, 0x080c, 0x630a, 0x1108, 0x0005, 0x0126, 0x2091, - 0x8000, 0xa87a, 0xa982, 0x080c, 0x7012, 0x012e, 0x0cb0, 0x2001, - 0x0028, 0x900e, 0x0c98, 0x2001, 0x0000, 0x0c80, 0x00c6, 0x2061, - 0x1800, 0x60d0, 0x9005, 0x0100, 0x00ce, 0x0005, 0x7018, 0xa802, - 0x2908, 0x2048, 0xa906, 0x711a, 0x7010, 0x8001, 0x7012, 0x0118, - 0x7007, 0x0003, 0x0030, 0x7014, 0x2048, 0x7007, 0x0001, 0x7048, - 0x080f, 0x0005, 0x00b6, 0x7007, 0x0001, 0xa974, 0xa878, 0x9084, - 0x00ff, 0x9096, 0x0004, 0x0540, 0x20a9, 0x0001, 0x9096, 0x0001, - 0x0190, 0x900e, 0x20a9, 0x0800, 0x9096, 0x0002, 0x0160, 0x9005, - 0x11d8, 0xa974, 0x080c, 0x67b4, 0x11b8, 0x0066, 0xae80, 0x080c, - 0x68c4, 0x006e, 0x0088, 0x0046, 0x2011, 0x180c, 0x2224, 0xc484, - 0x2412, 0x004e, 0x00c6, 0x080c, 0x67b4, 0x1110, 0x080c, 0x6a9e, - 0x8108, 0x1f04, 0x7e93, 0x00ce, 0xa87c, 0xd084, 0x1120, 0x080c, - 0x108b, 0x00be, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x7012, - 0x012e, 0x00be, 0x0005, 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, - 0x080c, 0x6c0d, 0x0580, 0x2061, 0x1a73, 0x6100, 0xd184, 0x0178, - 0xa888, 0x9084, 0x00ff, 0x1550, 0x6000, 0xd084, 0x0520, 0x6004, - 0x9005, 0x1538, 0x6003, 0x0000, 0x600b, 0x0000, 0x00c8, 0x2011, - 0x0001, 0xa890, 0x9005, 0x1110, 0x2001, 0x001e, 0x8000, 0x6016, - 0xa888, 0x9084, 0x00ff, 0x0178, 0x6006, 0xa888, 0x8007, 0x9084, - 0x00ff, 0x0148, 0x600a, 0xa888, 0x8000, 0x1108, 0xc28d, 0x6202, - 0x012e, 0x0804, 0x80ed, 0x012e, 0x0804, 0x80e7, 0x012e, 0x0804, - 0x80e1, 0x012e, 0x0804, 0x80e4, 0x0126, 0x2091, 0x8000, 0x7007, - 0x0001, 0x080c, 0x6c0d, 0x05e0, 0x2061, 0x1a73, 0x6000, 0xd084, - 0x05b8, 0x6204, 0x6308, 0xd08c, 0x1530, 0xac78, 0x9484, 0x0003, - 0x0170, 0xa988, 0x918c, 0x00ff, 0x8001, 0x1120, 0x2100, 0x9210, - 0x0620, 0x0028, 0x8001, 0x1508, 0x2100, 0x9212, 0x02f0, 0x9484, - 0x000c, 0x0188, 0xa988, 0x810f, 0x918c, 0x00ff, 0x9082, 0x0004, - 0x1120, 0x2100, 0x9318, 0x0288, 0x0030, 0x9082, 0x0004, 0x1168, - 0x2100, 0x931a, 0x0250, 0xa890, 0x9005, 0x0110, 0x8000, 0x6016, - 0x6206, 0x630a, 0x012e, 0x0804, 0x80ed, 0x012e, 0x0804, 0x80ea, - 0x012e, 0x0804, 0x80e7, 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, - 0x2061, 0x1a73, 0x6300, 0xd38c, 0x1120, 0x6308, 0x8318, 0x0220, - 0x630a, 0x012e, 0x0804, 0x80fb, 0x012e, 0x0804, 0x80ea, 0x00b6, - 0x0126, 0x00c6, 0x2091, 0x8000, 0x7007, 0x0001, 0xa87c, 0xd0ac, - 0x0148, 0x00c6, 0x2061, 0x1a73, 0x6000, 0x9084, 0xfcff, 0x6002, - 0x00ce, 0x0440, 0xa888, 0x9005, 0x05d8, 0xa88c, 0x9065, 0x0598, - 0x2001, 0x1834, 0x2004, 0x9005, 0x0118, 0x080c, 0xb1a7, 0x0068, - 0x6017, 0xf400, 0x6063, 0x0000, 0xa97c, 0xd1a4, 0x0110, 0xa980, - 0x6162, 0x2009, 0x0041, 0x080c, 0xb20a, 0xa988, 0x918c, 0xff00, - 0x9186, 0x2000, 0x1138, 0x0026, 0x900e, 0x2011, 0xfdff, 0x080c, - 0x8c44, 0x002e, 0xa87c, 0xd0c4, 0x0148, 0x2061, 0x1a73, 0x6000, - 0xd08c, 0x1120, 0x6008, 0x8000, 0x0208, 0x600a, 0x00ce, 0x012e, - 0x00be, 0x0804, 0x80ed, 0x00ce, 0x012e, 0x00be, 0x0804, 0x80e7, - 0xa984, 0x9186, 0x002e, 0x0d30, 0x9186, 0x002d, 0x0d18, 0x9186, - 0x0045, 0x0510, 0x9186, 0x002a, 0x1130, 0x2001, 0x180c, 0x200c, - 0xc194, 0x2102, 0x08b8, 0x9186, 0x0020, 0x0158, 0x9186, 0x0029, - 0x1d10, 0xa974, 0x080c, 0x67b4, 0x1968, 0xb800, 0xc0e4, 0xb802, - 0x0848, 0xa88c, 0x9065, 0x09b8, 0x6007, 0x0024, 0x2001, 0x1986, - 0x2004, 0x601a, 0x0804, 0x7f82, 0xa88c, 0x9065, 0x0960, 0x00e6, - 0xa890, 0x9075, 0x2001, 0x1834, 0x2004, 0x9005, 0x0150, 0x080c, - 0xb1a7, 0x8eff, 0x0118, 0x2e60, 0x080c, 0xb1a7, 0x00ee, 0x0804, - 0x7f82, 0x6024, 0xc0dc, 0xc0d5, 0x6026, 0x2e60, 0x6007, 0x003a, - 0xa8a0, 0x9005, 0x0130, 0x6007, 0x003b, 0xa8a4, 0x602e, 0xa8a8, - 0x6016, 0x6003, 0x0001, 0x2009, 0x8020, 0x080c, 0x9617, 0x00ee, - 0x0804, 0x7f82, 0x2061, 0x1a73, 0x6000, 0xd084, 0x0190, 0xd08c, - 0x1904, 0x80fb, 0x0126, 0x2091, 0x8000, 0x6204, 0x8210, 0x0220, - 0x6206, 0x012e, 0x0804, 0x80fb, 0x012e, 0xa883, 0x0016, 0x0804, - 0x80f4, 0xa883, 0x0007, 0x0804, 0x80f4, 0xa864, 0x8007, 0x9084, - 0x00ff, 0x0130, 0x8001, 0x1138, 0x7007, 0x0001, 0x0069, 0x0005, - 0x080c, 0x7c28, 0x0040, 0x7007, 0x0003, 0x7012, 0x2900, 0x7016, - 0x701a, 0x704b, 0x8024, 0x0005, 0x00b6, 0x00e6, 0x0126, 0x2091, - 0x8000, 0x903e, 0x2061, 0x1800, 0x61d0, 0x81ff, 0x1904, 0x80a6, - 0x6130, 0xd194, 0x1904, 0x80d0, 0xa878, 0x2070, 0x9e82, 0x1ddc, - 0x0a04, 0x809a, 0x6068, 0x9e02, 0x1a04, 0x809a, 0x7120, 0x9186, - 0x0006, 0x1904, 0x808c, 0x7010, 0x905d, 0x0904, 0x80a6, 0xb800, - 0xd0e4, 0x1904, 0x80ca, 0x2061, 0x1a73, 0x6100, 0x9184, 0x0301, - 0x9086, 0x0001, 0x15a0, 0x7024, 0xd0dc, 0x1904, 0x80d3, 0xa883, - 0x0000, 0xa803, 0x0000, 0x2908, 0x7014, 0x9005, 0x1198, 0x7116, - 0xa87c, 0xd0f4, 0x1904, 0x80d6, 0x080c, 0x5840, 0xd09c, 0x1118, - 0xa87c, 0xc0cc, 0xa87e, 0x2e60, 0x080c, 0x8b34, 0x012e, 0x00ee, - 0x00be, 0x0005, 0x2048, 0xa800, 0x9005, 0x1de0, 0xa902, 0x2148, - 0xa87c, 0xd0f4, 0x1904, 0x80d6, 0x012e, 0x00ee, 0x00be, 0x0005, - 0x012e, 0x00ee, 0xa883, 0x0006, 0x00be, 0x0804, 0x80f4, 0xd184, - 0x0db8, 0xd1c4, 0x1190, 0x00a0, 0xa974, 0x080c, 0x67b4, 0x15d0, - 0xb800, 0xd0e4, 0x15b8, 0x7120, 0x9186, 0x0007, 0x1118, 0xa883, - 0x0002, 0x0490, 0xa883, 0x0008, 0x0478, 0xa883, 0x000e, 0x0460, - 0xa883, 0x0017, 0x0448, 0xa883, 0x0035, 0x0430, 0x080c, 0x5844, - 0xd0fc, 0x01e8, 0xa878, 0x2070, 0x9e82, 0x1ddc, 0x02c0, 0x6068, - 0x9e02, 0x12a8, 0x7120, 0x9186, 0x0006, 0x1188, 0x7010, 0x905d, - 0x0170, 0xb800, 0xd0bc, 0x0158, 0x2039, 0x0001, 0x7000, 0x9086, - 0x0007, 0x1904, 0x8030, 0x7003, 0x0002, 0x0804, 0x8030, 0xa883, - 0x0028, 0x0010, 0xa883, 0x0029, 0x012e, 0x00ee, 0x00be, 0x0420, - 0xa883, 0x002a, 0x0cc8, 0xa883, 0x0045, 0x0cb0, 0x2e60, 0x2019, - 0x0002, 0x601b, 0x0014, 0x080c, 0xe586, 0x012e, 0x00ee, 0x00be, - 0x0005, 0x2009, 0x003e, 0x0058, 0x2009, 0x0004, 0x0040, 0x2009, - 0x0006, 0x0028, 0x2009, 0x0016, 0x0010, 0x2009, 0x0001, 0xa884, - 0x9084, 0xff00, 0x9105, 0xa886, 0x0126, 0x2091, 0x8000, 0x080c, - 0x7012, 0x012e, 0x0005, 0x080c, 0x108b, 0x0005, 0x00d6, 0x080c, - 0x8b2b, 0x00de, 0x0005, 0x00d6, 0x00e6, 0x0126, 0x2091, 0x8000, - 0x2071, 0x0040, 0x702c, 0xd084, 0x01d8, 0x908c, 0x0780, 0x190c, - 0x81e5, 0xd09c, 0x11a8, 0x2071, 0x1800, 0x70c0, 0x90ea, 0x0020, - 0x0278, 0x8001, 0x70c2, 0x702c, 0x2048, 0xa800, 0x702e, 0x9006, - 0xa802, 0xa806, 0x2071, 0x0040, 0x2900, 0x7022, 0x702c, 0x0c28, - 0x012e, 0x00ee, 0x00de, 0x0005, 0x0006, 0x9084, 0x0780, 0x190c, - 0x81e5, 0x000e, 0x0005, 0xa898, 0x9084, 0x0003, 0x05a8, 0x080c, - 0xb116, 0x05d8, 0x2900, 0x6016, 0xa864, 0x9084, 0x00ff, 0x9086, - 0x0035, 0x1138, 0x6028, 0xc0fd, 0x602a, 0x2001, 0x196b, 0x2004, - 0x0098, 0xa8a0, 0x9084, 0x00ff, 0xa99c, 0x918c, 0xff00, 0x9105, - 0xa99c, 0x918c, 0x00ff, 0x080c, 0x268c, 0x1540, 0x00b6, 0x080c, - 0x67b4, 0x2b00, 0x00be, 0x1510, 0x6012, 0x6023, 0x0001, 0x2009, - 0x0040, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0035, 0x0110, 0x2009, - 0x0041, 0x080c, 0xb20a, 0x0005, 0xa87b, 0x0101, 0x0126, 0x2091, - 0x8000, 0x080c, 0x7012, 0x012e, 0x0005, 0xa87b, 0x002c, 0x0126, - 0x2091, 0x8000, 0x080c, 0x7012, 0x012e, 0x0005, 0xa87b, 0x0028, - 0x0126, 0x2091, 0x8000, 0x080c, 0x7012, 0x012e, 0x080c, 0xb16c, - 0x0005, 0x00d6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x00b6, 0x7007, - 0x0001, 0xaa74, 0x9282, 0x0004, 0x1a04, 0x81d6, 0xa97c, 0x9188, - 0x1000, 0x2104, 0x905d, 0xb804, 0xd284, 0x0140, 0x05e8, 0x8007, - 0x9084, 0x00ff, 0x9084, 0x0006, 0x1108, 0x04b0, 0x2b10, 0x080c, - 0xb116, 0x1118, 0x080c, 0xb1dd, 0x05a8, 0x6212, 0xa874, 0x0002, - 0x81b4, 0x81b9, 0x81bc, 0x81c2, 0x2019, 0x0002, 0x080c, 0xe9f9, - 0x0060, 0x080c, 0xe984, 0x0048, 0x2019, 0x0002, 0xa980, 0x080c, - 0xe9a3, 0x0018, 0xa980, 0x080c, 0xe984, 0x080c, 0xb16c, 0xa887, - 0x0000, 0x0126, 0x2091, 0x8000, 0x080c, 0x7012, 0x012e, 0x00be, - 0x001e, 0x002e, 0x003e, 0x00ce, 0x00de, 0x0005, 0xa887, 0x0006, - 0x0c80, 0xa887, 0x0002, 0x0c68, 0xa887, 0x0005, 0x0c50, 0xa887, - 0x0004, 0x0c38, 0xa887, 0x0007, 0x0c20, 0x2091, 0x8000, 0x0e04, - 0x81e7, 0x0006, 0x0016, 0x2001, 0x8003, 0x0006, 0x0804, 0x0d8e, - 0x2001, 0x1834, 0x2004, 0x9005, 0x0005, 0x0005, 0x00f6, 0x2079, - 0x0300, 0x2001, 0x0200, 0x200c, 0xc1e5, 0xc1dc, 0x2102, 0x2009, - 0x0218, 0x210c, 0xd1ec, 0x1120, 0x080c, 0x1648, 0x00fe, 0x0005, - 0x2001, 0x020d, 0x2003, 0x0020, 0x781f, 0x0300, 0x00fe, 0x0005, - 0x781c, 0xd08c, 0x0904, 0x8268, 0x68c0, 0x90aa, 0x0005, 0x0a04, - 0x8890, 0x7d44, 0x7c40, 0xd59c, 0x190c, 0x0d85, 0x9584, 0x00f6, - 0x1508, 0x9484, 0x7000, 0x0138, 0x908a, 0x2000, 0x1258, 0x9584, - 0x0700, 0x8007, 0x04f0, 0x7000, 0x9084, 0xff00, 0x9086, 0x8100, - 0x0db0, 0x00b0, 0x9484, 0x0fff, 0x1130, 0x7000, 0x9084, 0xff00, - 0x9086, 0x8100, 0x11c0, 0x080c, 0xeeb1, 0x080c, 0x8777, 0x7817, - 0x0140, 0x00a8, 0x9584, 0x0076, 0x1118, 0x080c, 0x87d3, 0x19c8, - 0xd5a4, 0x0148, 0x0046, 0x0056, 0x080c, 0x82b8, 0x080c, 0x2185, - 0x005e, 0x004e, 0x0020, 0x080c, 0xeeb1, 0x7817, 0x0140, 0x080c, - 0x779e, 0x0168, 0x2001, 0x0111, 0x2004, 0xd08c, 0x0140, 0x6893, - 0x0000, 0x2001, 0x0110, 0x2003, 0x0008, 0x2003, 0x0000, 0x0489, - 0x0005, 0x0002, 0x8275, 0x8585, 0x8272, 0x8272, 0x8272, 0x8272, - 0x8272, 0x8272, 0x7817, 0x0140, 0x0005, 0x7000, 0x908c, 0xff00, - 0x9194, 0xf000, 0x810f, 0x9484, 0x0fff, 0x6892, 0x9286, 0x2000, - 0x1150, 0x6800, 0x9086, 0x0001, 0x1118, 0x080c, 0x58aa, 0x0070, - 0x080c, 0x82d8, 0x0058, 0x9286, 0x3000, 0x1118, 0x080c, 0x84bf, - 0x0028, 0x9286, 0x8000, 0x1110, 0x080c, 0x86a4, 0x7817, 0x0140, - 0x0005, 0x2001, 0x1810, 0x2004, 0xd08c, 0x0178, 0x2001, 0x1800, - 0x2004, 0x9086, 0x0003, 0x1148, 0x0026, 0x0036, 0x2011, 0x8048, - 0x2518, 0x080c, 0x4ca1, 0x003e, 0x002e, 0x0005, 0x0036, 0x0046, - 0x0056, 0x00f6, 0x2079, 0x0200, 0x2019, 0xfffe, 0x7c30, 0x0050, - 0x0036, 0x0046, 0x0056, 0x00f6, 0x2079, 0x0200, 0x7d44, 0x7c40, - 0x2019, 0xffff, 0x2001, 0x1810, 0x2004, 0xd08c, 0x0160, 0x2001, - 0x1800, 0x2004, 0x9086, 0x0003, 0x1130, 0x0026, 0x2011, 0x8048, - 0x080c, 0x4ca1, 0x002e, 0x00fe, 0x005e, 0x004e, 0x003e, 0x0005, - 0x00b6, 0x00c6, 0x7010, 0x9084, 0xff00, 0x8007, 0x9096, 0x0001, - 0x0120, 0x9096, 0x0023, 0x1904, 0x8490, 0x9186, 0x0023, 0x15c0, - 0x080c, 0x8742, 0x0904, 0x8490, 0x6120, 0x9186, 0x0001, 0x0150, - 0x9186, 0x0004, 0x0138, 0x9186, 0x0008, 0x0120, 0x9186, 0x000a, - 0x1904, 0x8490, 0x7124, 0x610a, 0x7030, 0x908e, 0x0200, 0x1130, - 0x2009, 0x0015, 0x080c, 0xb20a, 0x0804, 0x8490, 0x908e, 0x0214, - 0x0118, 0x908e, 0x0210, 0x1130, 0x2009, 0x0015, 0x080c, 0xb20a, - 0x0804, 0x8490, 0x908e, 0x0100, 0x1904, 0x8490, 0x7034, 0x9005, - 0x1904, 0x8490, 0x2009, 0x0016, 0x080c, 0xb20a, 0x0804, 0x8490, - 0x9186, 0x0022, 0x1904, 0x8490, 0x7030, 0x908e, 0x0300, 0x1580, - 0x68dc, 0xd0a4, 0x0528, 0xc0b5, 0x68de, 0x7100, 0x918c, 0x00ff, - 0x697e, 0x7004, 0x6882, 0x00f6, 0x2079, 0x0100, 0x79e6, 0x78ea, - 0x0006, 0x9084, 0x00ff, 0x0016, 0x2008, 0x080c, 0x26d5, 0x7932, - 0x7936, 0x001e, 0x000e, 0x00fe, 0x080c, 0x268c, 0x695e, 0x703c, - 0x00e6, 0x2071, 0x0140, 0x7086, 0x2071, 0x1800, 0x70b6, 0x00ee, - 0x7034, 0x9005, 0x1904, 0x8490, 0x2009, 0x0017, 0x0804, 0x8440, - 0x908e, 0x0400, 0x1190, 0x7034, 0x9005, 0x1904, 0x8490, 0x080c, - 0x779e, 0x0120, 0x2009, 0x001d, 0x0804, 0x8440, 0x68dc, 0xc0a5, - 0x68de, 0x2009, 0x0030, 0x0804, 0x8440, 0x908e, 0x0500, 0x1140, - 0x7034, 0x9005, 0x1904, 0x8490, 0x2009, 0x0018, 0x0804, 0x8440, - 0x908e, 0x2010, 0x1120, 0x2009, 0x0019, 0x0804, 0x8440, 0x908e, - 0x2110, 0x1120, 0x2009, 0x001a, 0x0804, 0x8440, 0x908e, 0x5200, - 0x1140, 0x7034, 0x9005, 0x1904, 0x8490, 0x2009, 0x001b, 0x0804, - 0x8440, 0x908e, 0x5000, 0x1140, 0x7034, 0x9005, 0x1904, 0x8490, - 0x2009, 0x001c, 0x0804, 0x8440, 0x908e, 0x1300, 0x1120, 0x2009, - 0x0034, 0x0804, 0x8440, 0x908e, 0x1200, 0x1140, 0x7034, 0x9005, - 0x1904, 0x8490, 0x2009, 0x0024, 0x0804, 0x8440, 0x908c, 0xff00, - 0x918e, 0x2400, 0x1170, 0x2009, 0x002d, 0x2001, 0x1810, 0x2004, - 0xd09c, 0x0904, 0x8440, 0x080c, 0xdd8d, 0x1904, 0x8490, 0x0804, - 0x843e, 0x908c, 0xff00, 0x918e, 0x5300, 0x1120, 0x2009, 0x002a, - 0x0804, 0x8440, 0x908e, 0x0f00, 0x1120, 0x2009, 0x0020, 0x0804, - 0x8440, 0x908e, 0x6104, 0x1530, 0x2029, 0x0205, 0x2011, 0x026d, - 0x8208, 0x2204, 0x9082, 0x0004, 0x8004, 0x8004, 0x20a8, 0x2011, - 0x8015, 0x211c, 0x8108, 0x0046, 0x2124, 0x080c, 0x4ca1, 0x004e, - 0x8108, 0x0f04, 0x83f4, 0x9186, 0x0280, 0x1d88, 0x2504, 0x8000, - 0x202a, 0x2009, 0x0260, 0x0c58, 0x202b, 0x0000, 0x2009, 0x0023, - 0x0804, 0x8440, 0x908e, 0x6000, 0x1120, 0x2009, 0x003f, 0x0804, - 0x8440, 0x908e, 0x5400, 0x1138, 0x080c, 0x8840, 0x1904, 0x8490, - 0x2009, 0x0046, 0x04a8, 0x908e, 0x5500, 0x1148, 0x080c, 0x8868, - 0x1118, 0x2009, 0x0041, 0x0460, 0x2009, 0x0042, 0x0448, 0x908e, - 0x7800, 0x1118, 0x2009, 0x0045, 0x0418, 0x908e, 0x1000, 0x1118, - 0x2009, 0x004e, 0x00e8, 0x908e, 0x6300, 0x1118, 0x2009, 0x004a, - 0x00b8, 0x908c, 0xff00, 0x918e, 0x5600, 0x1118, 0x2009, 0x004f, - 0x0078, 0x908c, 0xff00, 0x918e, 0x5700, 0x1118, 0x2009, 0x0050, - 0x0038, 0x2009, 0x001d, 0x6838, 0xd0d4, 0x0110, 0x2009, 0x004c, - 0x0016, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x268c, - 0x1904, 0x8493, 0x080c, 0x6749, 0x1904, 0x8493, 0xbe12, 0xbd16, - 0x001e, 0x0016, 0x080c, 0x779e, 0x01c0, 0x68dc, 0xd08c, 0x1148, - 0x7000, 0x9084, 0x00ff, 0x1188, 0x7004, 0x9084, 0xff00, 0x1168, - 0x0040, 0x687c, 0x9606, 0x1148, 0x6880, 0x9506, 0x9084, 0xff00, - 0x1120, 0x9584, 0x00ff, 0xb886, 0x0080, 0xb884, 0x9005, 0x1168, - 0x9186, 0x0046, 0x1150, 0x687c, 0x9606, 0x1138, 0x6880, 0x9506, - 0x9084, 0xff00, 0x1110, 0x001e, 0x0098, 0x080c, 0xb116, 0x01a8, - 0x2b08, 0x6112, 0x6023, 0x0004, 0x7120, 0x610a, 0x001e, 0x9186, - 0x004c, 0x1110, 0x6023, 0x000a, 0x0016, 0x001e, 0x080c, 0xb20a, - 0x00ce, 0x00be, 0x0005, 0x001e, 0x0cd8, 0x2001, 0x180e, 0x2004, - 0xd0ec, 0x0120, 0x2011, 0x8049, 0x080c, 0x4ca1, 0x080c, 0xb1dd, - 0x0d90, 0x2b08, 0x6112, 0x6023, 0x0004, 0x7120, 0x610a, 0x001e, - 0x0016, 0x9186, 0x0017, 0x0118, 0x9186, 0x0030, 0x1128, 0x6007, - 0x0009, 0x6017, 0x2900, 0x0020, 0x6007, 0x0051, 0x6017, 0x0000, - 0x602f, 0x0009, 0x6003, 0x0001, 0x080c, 0x961e, 0x08a0, 0x080c, - 0x88af, 0x1158, 0x080c, 0x344c, 0x1140, 0x7010, 0x9084, 0xff00, - 0x8007, 0x908e, 0x0008, 0x1108, 0x0009, 0x0005, 0x00b6, 0x00c6, - 0x0046, 0x7000, 0x908c, 0xff00, 0x810f, 0x9186, 0x0033, 0x11e8, - 0x080c, 0x8742, 0x0904, 0x851d, 0x7124, 0x610a, 0x7030, 0x908e, - 0x0200, 0x1140, 0x7034, 0x9005, 0x15c0, 0x2009, 0x0015, 0x080c, - 0xb20a, 0x0498, 0x908e, 0x0100, 0x1580, 0x7034, 0x9005, 0x1568, - 0x2009, 0x0016, 0x080c, 0xb20a, 0x0440, 0x9186, 0x0032, 0x1528, - 0x7030, 0x908e, 0x1400, 0x1508, 0x2009, 0x0038, 0x0016, 0x2011, - 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x268c, 0x11a8, 0x080c, - 0x6749, 0x1190, 0xbe12, 0xbd16, 0x080c, 0xb116, 0x0168, 0x2b08, - 0x6112, 0x080c, 0xd3b6, 0x6023, 0x0004, 0x7120, 0x610a, 0x001e, - 0x080c, 0xb20a, 0x0010, 0x00ce, 0x001e, 0x004e, 0x00ce, 0x00be, - 0x0005, 0x00b6, 0x0046, 0x00e6, 0x00d6, 0x2028, 0x2130, 0x9696, - 0x00ff, 0x11b8, 0x9592, 0xfffc, 0x02a0, 0x9596, 0xfffd, 0x1120, - 0x2009, 0x007f, 0x0804, 0x857f, 0x9596, 0xfffe, 0x1120, 0x2009, - 0x007e, 0x0804, 0x857f, 0x9596, 0xfffc, 0x1118, 0x2009, 0x0080, - 0x04f0, 0x2011, 0x0000, 0x2019, 0x1837, 0x231c, 0xd3ac, 0x0130, - 0x9026, 0x20a9, 0x0800, 0x2071, 0x1000, 0x0030, 0x2021, 0x0081, - 0x20a9, 0x077f, 0x2071, 0x1081, 0x2e1c, 0x93dd, 0x0000, 0x1140, - 0x82ff, 0x11d0, 0x9496, 0x00ff, 0x01b8, 0x2410, 0xc2fd, 0x00a0, - 0xbf10, 0x2600, 0x9706, 0xb814, 0x1120, 0x9546, 0x1110, 0x2408, - 0x00b0, 0x9745, 0x1148, 0x94c6, 0x007e, 0x0130, 0x94c6, 0x007f, - 0x0118, 0x94c6, 0x0080, 0x1d20, 0x8420, 0x8e70, 0x1f04, 0x8554, - 0x82ff, 0x1118, 0x9085, 0x0001, 0x0018, 0xc2fc, 0x2208, 0x9006, - 0x00de, 0x00ee, 0x004e, 0x00be, 0x0005, 0x2001, 0x1837, 0x200c, - 0x9184, 0x0080, 0x0110, 0xd18c, 0x0138, 0x7000, 0x908c, 0xff00, - 0x810f, 0x9184, 0x000f, 0x001a, 0x7817, 0x0140, 0x0005, 0x85a7, - 0x85a7, 0x85a7, 0x8754, 0x85a7, 0x85aa, 0x85cf, 0x8658, 0x85a7, - 0x85a7, 0x85a7, 0x85a7, 0x85a7, 0x85a7, 0x85a7, 0x85a7, 0x7817, - 0x0140, 0x0005, 0x00b6, 0x7110, 0xd1bc, 0x01e8, 0x7120, 0x2160, - 0x9c8c, 0x0003, 0x11c0, 0x9c8a, 0x1ddc, 0x02a8, 0x6868, 0x9c02, - 0x1290, 0x7008, 0x9084, 0x00ff, 0x6110, 0x2158, 0xb910, 0x9106, - 0x1150, 0x700c, 0xb914, 0x9106, 0x1130, 0x7124, 0x610a, 0x2009, - 0x0046, 0x080c, 0xb20a, 0x7817, 0x0140, 0x00be, 0x0005, 0x00b6, - 0x00c6, 0x9484, 0x0fff, 0x0904, 0x8634, 0x7110, 0xd1bc, 0x1904, - 0x8634, 0x7108, 0x700c, 0x2028, 0x918c, 0x00ff, 0x2130, 0x9094, - 0xff00, 0x15c8, 0x81ff, 0x15b8, 0x9080, 0x348e, 0x200d, 0x918c, - 0xff00, 0x810f, 0x2001, 0x0080, 0x9106, 0x0904, 0x8634, 0x9182, - 0x0801, 0x1a04, 0x8634, 0x9190, 0x1000, 0x2204, 0x905d, 0x05e0, - 0xbe12, 0xbd16, 0xb800, 0xd0ec, 0x15b8, 0xba04, 0x9294, 0xff00, - 0x9286, 0x0600, 0x1190, 0x080c, 0xb116, 0x0598, 0x2b08, 0x7028, - 0x604e, 0x702c, 0x6052, 0x6112, 0x6023, 0x0006, 0x7120, 0x610a, - 0x7130, 0x615e, 0x080c, 0xe009, 0x00f8, 0x080c, 0x6c11, 0x1138, - 0xb807, 0x0606, 0x0c40, 0x190c, 0x8521, 0x11b0, 0x0880, 0x080c, - 0xb116, 0x2b08, 0x0188, 0x6112, 0x6023, 0x0004, 0x7120, 0x610a, - 0x9286, 0x0400, 0x1118, 0x6007, 0x0005, 0x0010, 0x6007, 0x0001, - 0x6003, 0x0001, 0x080c, 0x961e, 0x7817, 0x0140, 0x00ce, 0x00be, - 0x0005, 0x2001, 0x180e, 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049, - 0x080c, 0x4ca1, 0x080c, 0xb1dd, 0x0d78, 0x2b08, 0x6112, 0x6023, - 0x0006, 0x7120, 0x610a, 0x7130, 0x615e, 0x6017, 0xf300, 0x6003, - 0x0001, 0x6007, 0x0041, 0x2009, 0xa022, 0x080c, 0x9617, 0x08e0, - 0x00b6, 0x7110, 0xd1bc, 0x05d0, 0x7020, 0x2060, 0x9c84, 0x0003, - 0x15a8, 0x9c82, 0x1ddc, 0x0690, 0x6868, 0x9c02, 0x1678, 0x9484, - 0x0fff, 0x9082, 0x000c, 0x0650, 0x7008, 0x9084, 0x00ff, 0x6110, - 0x2158, 0xb910, 0x9106, 0x1510, 0x700c, 0xb914, 0x9106, 0x11f0, - 0x7124, 0x610a, 0x601c, 0xd0fc, 0x11c8, 0x2001, 0x0271, 0x2004, - 0x9005, 0x1180, 0x9484, 0x0fff, 0x9082, 0x000c, 0x0158, 0x0066, - 0x2031, 0x0100, 0xa001, 0xa001, 0x8631, 0x1de0, 0x006e, 0x601c, - 0xd0fc, 0x1120, 0x2009, 0x0045, 0x080c, 0xb20a, 0x7817, 0x0140, - 0x00be, 0x0005, 0x6120, 0x9186, 0x0002, 0x0128, 0x9186, 0x0005, - 0x0110, 0x9085, 0x0001, 0x0005, 0x080c, 0x88af, 0x1180, 0x080c, - 0x344c, 0x1168, 0x7010, 0x9084, 0xff00, 0x8007, 0x9086, 0x0000, - 0x1130, 0x9184, 0x000f, 0x908a, 0x0006, 0x1208, 0x000b, 0x0005, - 0x86be, 0x86bf, 0x86be, 0x86be, 0x8724, 0x8733, 0x0005, 0x00b6, - 0x700c, 0x7108, 0x080c, 0x268c, 0x1904, 0x8722, 0x080c, 0x6749, - 0x1904, 0x8722, 0xbe12, 0xbd16, 0x7110, 0xd1bc, 0x0540, 0x702c, - 0xd084, 0x1120, 0xb800, 0xd0bc, 0x1904, 0x8722, 0x080c, 0x6c11, - 0x0148, 0x9086, 0x0004, 0x0130, 0x080c, 0x6c19, 0x0118, 0x9086, - 0x0004, 0x1588, 0x00c6, 0x080c, 0x8742, 0x00ce, 0x05d8, 0x080c, - 0xb116, 0x2b08, 0x05b8, 0x6112, 0x080c, 0xd3b6, 0x6023, 0x0002, - 0x7120, 0x610a, 0x2009, 0x0088, 0x080c, 0xb20a, 0x0458, 0x080c, - 0x6c11, 0x0148, 0x9086, 0x0004, 0x0130, 0x080c, 0x6c19, 0x0118, - 0x9086, 0x0004, 0x1180, 0x080c, 0xb116, 0x2b08, 0x01d8, 0x6112, - 0x080c, 0xd3b6, 0x6023, 0x0005, 0x7120, 0x610a, 0x2009, 0x0088, - 0x080c, 0xb20a, 0x0078, 0x080c, 0xb116, 0x2b08, 0x0158, 0x6112, - 0x080c, 0xd3b6, 0x6023, 0x0004, 0x7120, 0x610a, 0x2009, 0x0001, - 0x080c, 0xb20a, 0x00be, 0x0005, 0x7110, 0xd1bc, 0x0158, 0x00d1, - 0x0148, 0x080c, 0x869a, 0x1130, 0x7124, 0x610a, 0x2009, 0x0089, - 0x080c, 0xb20a, 0x0005, 0x7110, 0xd1bc, 0x0158, 0x0059, 0x0148, - 0x080c, 0x869a, 0x1130, 0x7124, 0x610a, 0x2009, 0x008a, 0x080c, - 0xb20a, 0x0005, 0x7020, 0x2060, 0x9c84, 0x0003, 0x1158, 0x9c82, - 0x1ddc, 0x0240, 0x2001, 0x181a, 0x2004, 0x9c02, 0x1218, 0x9085, - 0x0001, 0x0005, 0x9006, 0x0ce8, 0x00b6, 0x7110, 0xd1bc, 0x11d8, - 0x7024, 0x2060, 0x9c84, 0x0003, 0x11b0, 0x9c82, 0x1ddc, 0x0298, - 0x6868, 0x9c02, 0x1280, 0x7008, 0x9084, 0x00ff, 0x6110, 0x2158, - 0xb910, 0x9106, 0x1140, 0x700c, 0xb914, 0x9106, 0x1120, 0x2009, - 0x0051, 0x080c, 0xb20a, 0x7817, 0x0140, 0x00be, 0x0005, 0x2031, - 0x0105, 0x0069, 0x0005, 0x2031, 0x0206, 0x0049, 0x0005, 0x2031, - 0x0207, 0x0029, 0x0005, 0x2031, 0x0213, 0x0009, 0x0005, 0x00c6, - 0x0096, 0x00f6, 0x7000, 0x9084, 0xf000, 0x9086, 0xc000, 0x05c0, - 0x080c, 0xb116, 0x05a8, 0x0066, 0x00c6, 0x0046, 0x2011, 0x0263, - 0x2204, 0x8211, 0x220c, 0x080c, 0x268c, 0x1590, 0x080c, 0x6749, - 0x1578, 0xbe12, 0xbd16, 0x2b00, 0x004e, 0x00ce, 0x6012, 0x080c, - 0xd3b6, 0x080c, 0x1059, 0x0500, 0x2900, 0x6062, 0x9006, 0xa802, - 0xa866, 0xac6a, 0xa85c, 0x90f8, 0x001b, 0x20a9, 0x000e, 0xa860, - 0x20e8, 0x20e1, 0x0000, 0x2fa0, 0x2e98, 0x4003, 0x006e, 0x6616, - 0x6007, 0x003e, 0x6023, 0x0001, 0x6003, 0x0001, 0x080c, 0x961e, - 0x00fe, 0x009e, 0x00ce, 0x0005, 0x080c, 0xb16c, 0x006e, 0x0cc0, - 0x004e, 0x00ce, 0x0cc8, 0x00c6, 0x7000, 0x908c, 0xff00, 0x9184, - 0xf000, 0x810f, 0x9086, 0x2000, 0x1904, 0x882a, 0x9186, 0x0022, - 0x15f0, 0x2001, 0x0111, 0x2004, 0x9005, 0x1904, 0x882c, 0x7030, - 0x908e, 0x0400, 0x0904, 0x882c, 0x908e, 0x6000, 0x05e8, 0x908e, - 0x5400, 0x05d0, 0x908e, 0x0300, 0x11d8, 0x2009, 0x1837, 0x210c, - 0xd18c, 0x1590, 0xd1a4, 0x1580, 0x080c, 0x6bcf, 0x0588, 0x68b0, - 0x9084, 0x00ff, 0x7100, 0x918c, 0x00ff, 0x9106, 0x1518, 0x6880, - 0x69b0, 0x918c, 0xff00, 0x9105, 0x7104, 0x9106, 0x11d8, 0x00e0, - 0x2009, 0x0103, 0x210c, 0xd1b4, 0x11a8, 0x908e, 0x5200, 0x09e8, - 0x908e, 0x0500, 0x09d0, 0x908e, 0x5000, 0x09b8, 0x0058, 0x9186, - 0x0023, 0x1140, 0x080c, 0x8742, 0x0128, 0x6004, 0x9086, 0x0002, - 0x0118, 0x0000, 0x9006, 0x0010, 0x9085, 0x0001, 0x00ce, 0x0005, - 0x7030, 0x908e, 0x0300, 0x0118, 0x908e, 0x5200, 0x1d98, 0x2001, - 0x1837, 0x2004, 0x9084, 0x0009, 0x9086, 0x0008, 0x0d68, 0x0c50, - 0x0156, 0x0046, 0x0016, 0x0036, 0x7038, 0x2020, 0x8427, 0x94a4, - 0x0007, 0xd484, 0x0148, 0x20a9, 0x0004, 0x2019, 0x1805, 0x2011, - 0x027a, 0x080c, 0xc20e, 0x1178, 0xd48c, 0x0148, 0x20a9, 0x0004, - 0x2019, 0x1801, 0x2011, 0x027e, 0x080c, 0xc20e, 0x1120, 0xd494, - 0x0110, 0x9085, 0x0001, 0x003e, 0x001e, 0x004e, 0x015e, 0x0005, - 0x0156, 0x0046, 0x0016, 0x0036, 0x7038, 0x2020, 0x8427, 0x94a4, - 0x0007, 0xd484, 0x0148, 0x20a9, 0x0004, 0x2019, 0x1805, 0x2011, - 0x0272, 0x080c, 0xc20e, 0x1178, 0xd48c, 0x0148, 0x20a9, 0x0004, - 0x2019, 0x1801, 0x2011, 0x0276, 0x080c, 0xc20e, 0x1120, 0xd494, - 0x0110, 0x9085, 0x0001, 0x003e, 0x001e, 0x004e, 0x015e, 0x0005, - 0x00f6, 0x2079, 0x0200, 0x7800, 0xc0e5, 0xc0cc, 0x7802, 0x00fe, - 0x0005, 0x00f6, 0x2079, 0x1800, 0x7834, 0xd084, 0x1130, 0x2079, - 0x0200, 0x7800, 0x9085, 0x1200, 0x7802, 0x00fe, 0x0005, 0x00e6, - 0x2071, 0x1800, 0x7034, 0xc084, 0x7036, 0x00ee, 0x0005, 0x0016, - 0x2001, 0x1837, 0x200c, 0x9184, 0x0080, 0x0118, 0xd18c, 0x0118, - 0x9006, 0x001e, 0x0005, 0x9085, 0x0001, 0x0cd8, 0x2071, 0x1a04, - 0x7003, 0x0003, 0x700f, 0x0361, 0x9006, 0x701a, 0x707a, 0x7012, - 0x7017, 0x1ddc, 0x7007, 0x0000, 0x7026, 0x702b, 0xa2c0, 0x7032, - 0x7037, 0xa33d, 0x7047, 0xffff, 0x704a, 0x704f, 0x56c4, 0x7052, - 0x7063, 0x8a66, 0x080c, 0x1072, 0x090c, 0x0d85, 0x2900, 0x7042, - 0xa867, 0x0003, 0xa86f, 0x0100, 0xa8ab, 0xdcb0, 0x0005, 0x2071, - 0x1a04, 0x1d04, 0x8982, 0x2091, 0x6000, 0x700c, 0x8001, 0x700e, - 0x1590, 0x2001, 0x013c, 0x2004, 0x9005, 0x190c, 0x8b10, 0x2001, - 0x1869, 0x2004, 0xd0c4, 0x0158, 0x3a00, 0xd08c, 0x1140, 0x20d1, - 0x0000, 0x20d1, 0x0001, 0x20d1, 0x0000, 0x080c, 0x0d85, 0x700f, - 0x0361, 0x7007, 0x0001, 0x0126, 0x2091, 0x8000, 0x2069, 0x1800, - 0x69ec, 0xd1e4, 0x1138, 0xd1dc, 0x1118, 0x080c, 0x8ad4, 0x0010, - 0x080c, 0x8aab, 0x7048, 0x900d, 0x0148, 0x8109, 0x714a, 0x1130, - 0x704c, 0x080f, 0x0018, 0x0126, 0x2091, 0x8000, 0x7024, 0x900d, - 0x0188, 0x7020, 0x8001, 0x7022, 0x1168, 0x7023, 0x0009, 0x8109, - 0x7126, 0x9186, 0x03e8, 0x1110, 0x7028, 0x080f, 0x81ff, 0x1110, - 0x7028, 0x080f, 0x7030, 0x900d, 0x0180, 0x702c, 0x8001, 0x702e, - 0x1160, 0x702f, 0x0009, 0x8109, 0x7132, 0x0128, 0x9184, 0x007f, - 0x090c, 0xa3eb, 0x0010, 0x7034, 0x080f, 0x7044, 0x9005, 0x0118, - 0x0310, 0x8001, 0x7046, 0x7054, 0x900d, 0x0168, 0x7050, 0x8001, - 0x7052, 0x1148, 0x7053, 0x0009, 0x8109, 0x7156, 0x1120, 0x7158, - 0x7156, 0x7060, 0x080f, 0x7018, 0x900d, 0x01d8, 0x0016, 0x7078, - 0x900d, 0x0158, 0x7074, 0x8001, 0x7076, 0x1138, 0x7077, 0x0009, - 0x8109, 0x717a, 0x1110, 0x707c, 0x080f, 0x001e, 0x7008, 0x8001, - 0x700a, 0x1138, 0x700b, 0x0009, 0x8109, 0x711a, 0x1110, 0x701c, - 0x080f, 0x012e, 0x7004, 0x0002, 0x89aa, 0x89ab, 0x89d5, 0x00e6, - 0x2071, 0x1a04, 0x7018, 0x9005, 0x1120, 0x711a, 0x721e, 0x700b, - 0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x2071, 0x1a04, 0x701c, - 0x9206, 0x1120, 0x701a, 0x701e, 0x707a, 0x707e, 0x000e, 0x00ee, - 0x0005, 0x00e6, 0x2071, 0x1a04, 0xb888, 0x9102, 0x0208, 0xb98a, - 0x00ee, 0x0005, 0x0005, 0x00b6, 0x2031, 0x0010, 0x7110, 0x080c, - 0x67b4, 0x11a8, 0xb888, 0x8001, 0x0290, 0xb88a, 0x1180, 0x0126, - 0x2091, 0x8000, 0x0066, 0xb8d0, 0x9005, 0x0138, 0x0026, 0xba3c, - 0x0016, 0x080c, 0x68df, 0x001e, 0x002e, 0x006e, 0x012e, 0x8108, - 0x9182, 0x0800, 0x1220, 0x8631, 0x0128, 0x7112, 0x0c00, 0x900e, - 0x7007, 0x0002, 0x7112, 0x00be, 0x0005, 0x2031, 0x0010, 0x7014, - 0x2060, 0x0126, 0x2091, 0x8000, 0x6048, 0x9005, 0x0128, 0x8001, - 0x604a, 0x1110, 0x080c, 0xd237, 0x6018, 0x9005, 0x0904, 0x8a2d, - 0x00f6, 0x2079, 0x0300, 0x7918, 0xd1b4, 0x1904, 0x8a40, 0x781b, - 0x2020, 0xa001, 0x7918, 0xd1b4, 0x0120, 0x781b, 0x2000, 0x0804, - 0x8a40, 0x8001, 0x601a, 0x0106, 0x781b, 0x2000, 0xa001, 0x7918, - 0xd1ac, 0x1dd0, 0x010e, 0x00fe, 0x1540, 0x6120, 0x9186, 0x0003, - 0x0148, 0x9186, 0x0006, 0x0130, 0x9186, 0x0009, 0x11e0, 0x611c, - 0xd1c4, 0x1100, 0x080c, 0xcf1b, 0x01b0, 0x6014, 0x2048, 0xa884, - 0x908a, 0x199a, 0x0280, 0x9082, 0x1999, 0xa886, 0x908a, 0x199a, - 0x0210, 0x2001, 0x1999, 0x8003, 0x800b, 0x810b, 0x9108, 0x611a, - 0x080c, 0xd671, 0x0110, 0x080c, 0xcbd9, 0x012e, 0x9c88, 0x001c, - 0x7116, 0x2001, 0x181a, 0x2004, 0x9102, 0x1228, 0x8631, 0x0138, - 0x2160, 0x0804, 0x89d9, 0x7017, 0x1ddc, 0x7007, 0x0000, 0x0005, - 0x00fe, 0x0c58, 0x00e6, 0x2071, 0x1a04, 0x7027, 0x07d0, 0x7023, - 0x0009, 0x00ee, 0x0005, 0x2001, 0x1a0d, 0x2003, 0x0000, 0x0005, - 0x00e6, 0x2071, 0x1a04, 0x7132, 0x702f, 0x0009, 0x00ee, 0x0005, - 0x2011, 0x1a10, 0x2013, 0x0000, 0x0005, 0x00e6, 0x2071, 0x1a04, - 0x711a, 0x721e, 0x700b, 0x0009, 0x00ee, 0x0005, 0x0086, 0x0026, - 0x705c, 0x8000, 0x705e, 0x2001, 0x1a14, 0x2044, 0xa06c, 0x9086, - 0x0000, 0x0150, 0x7070, 0xa09a, 0x706c, 0xa096, 0x7068, 0xa092, - 0x7064, 0xa08e, 0x080c, 0x114e, 0x002e, 0x008e, 0x0005, 0x0006, - 0x0016, 0x0096, 0x00a6, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, - 0x0156, 0x080c, 0x88e7, 0x015e, 0x00fe, 0x00ee, 0x00de, 0x00ce, - 0x00be, 0x00ae, 0x009e, 0x001e, 0x000e, 0x0005, 0x00e6, 0x2071, - 0x1a04, 0x717a, 0x727e, 0x7077, 0x0009, 0x00ee, 0x0005, 0x00e6, - 0x0006, 0x2071, 0x1a04, 0x707c, 0x9206, 0x1110, 0x707a, 0x707e, - 0x000e, 0x00ee, 0x0005, 0x2069, 0x1800, 0x69ec, 0xd1e4, 0x1518, - 0x0026, 0xd1ec, 0x0140, 0x6a54, 0x6874, 0x9202, 0x0288, 0x8117, - 0x9294, 0x00c1, 0x0088, 0x9184, 0x0007, 0x01a0, 0x8109, 0x9184, - 0x0007, 0x0110, 0x69ee, 0x0070, 0x8107, 0x9084, 0x0007, 0x910d, - 0x8107, 0x9106, 0x9094, 0x00c1, 0x9184, 0xff3e, 0x9205, 0x68ee, - 0x080c, 0x0f24, 0x002e, 0x0005, 0x69e8, 0x9184, 0x003f, 0x05b8, - 0x8109, 0x9184, 0x003f, 0x01a8, 0x6a54, 0x6874, 0x9202, 0x0220, - 0xd1bc, 0x0168, 0xc1bc, 0x0018, 0xd1bc, 0x1148, 0xc1bd, 0x2110, - 0x00e6, 0x2071, 0x1800, 0x080c, 0x0f46, 0x00ee, 0x0400, 0x69ea, - 0x00f0, 0x0026, 0x8107, 0x9094, 0x0007, 0x0128, 0x8001, 0x8007, - 0x9085, 0x0007, 0x0050, 0x2010, 0x8004, 0x8004, 0x8004, 0x9084, - 0x0007, 0x9205, 0x8007, 0x9085, 0x0028, 0x9086, 0x0040, 0x2010, - 0x00e6, 0x2071, 0x1800, 0x080c, 0x0f46, 0x00ee, 0x002e, 0x0005, - 0x0016, 0x00c6, 0x2009, 0xfff4, 0x210d, 0x2061, 0x0100, 0x60f0, - 0x9100, 0x60f3, 0x0000, 0x2009, 0xfff4, 0x200f, 0x1220, 0x8108, - 0x2105, 0x8000, 0x200f, 0x00ce, 0x001e, 0x0005, 0x00c6, 0x2061, - 0x1a73, 0x00ce, 0x0005, 0x9184, 0x000f, 0x8003, 0x8003, 0x8003, - 0x9080, 0x1a73, 0x2060, 0x0005, 0xa884, 0x908a, 0x199a, 0x1638, - 0x9005, 0x1150, 0x00c6, 0x2061, 0x1a73, 0x6014, 0x00ce, 0x9005, - 0x1130, 0x2001, 0x001e, 0x0018, 0x908e, 0xffff, 0x01b0, 0x8003, - 0x800b, 0x810b, 0x9108, 0x611a, 0xa87c, 0x908c, 0x00c0, 0x918e, - 0x00c0, 0x0904, 0x8bee, 0xd0b4, 0x1168, 0xd0bc, 0x1904, 0x8bc7, - 0x2009, 0x0006, 0x080c, 0x8c1b, 0x0005, 0x900e, 0x0c60, 0x2001, - 0x1999, 0x08b0, 0xd0fc, 0x05e0, 0x908c, 0x2023, 0x1568, 0x87ff, - 0x1558, 0xa9a8, 0x81ff, 0x1540, 0x6124, 0x918c, 0x0500, 0x1520, - 0x6100, 0x918e, 0x0007, 0x1500, 0x2009, 0x1869, 0x210c, 0xd184, - 0x11d8, 0x6003, 0x0003, 0x6007, 0x0043, 0x6047, 0xb035, 0x080c, - 0x1c6f, 0xa87c, 0xc0dd, 0xa87e, 0x600f, 0x0000, 0x00f6, 0x2079, - 0x0380, 0x7818, 0xd0bc, 0x1de8, 0x7833, 0x0013, 0x2c00, 0x7836, - 0x781b, 0x8080, 0x00fe, 0x0005, 0x908c, 0x0003, 0x0120, 0x918e, - 0x0003, 0x1904, 0x8c15, 0x908c, 0x2020, 0x918e, 0x2020, 0x01a8, - 0x6024, 0xd0d4, 0x11e8, 0x2009, 0x1869, 0x2104, 0xd084, 0x1138, - 0x87ff, 0x1120, 0x2009, 0x0043, 0x0804, 0xb20a, 0x0005, 0x87ff, - 0x1de8, 0x2009, 0x0042, 0x0804, 0xb20a, 0x6110, 0x00b6, 0x2158, - 0xb900, 0x00be, 0xd1ac, 0x0d20, 0x6024, 0xc0cd, 0x6026, 0x0c00, - 0xc0d4, 0x6026, 0xa890, 0x602e, 0xa88c, 0x6032, 0x08e0, 0xd0fc, - 0x0160, 0x908c, 0x0003, 0x0120, 0x918e, 0x0003, 0x1904, 0x8c15, - 0x908c, 0x2020, 0x918e, 0x2020, 0x0170, 0x0076, 0x00f6, 0x2c78, - 0x080c, 0x17ad, 0x00fe, 0x007e, 0x87ff, 0x1120, 0x2009, 0x0042, - 0x080c, 0xb20a, 0x0005, 0x6110, 0x00b6, 0x2158, 0xb900, 0x00be, - 0xd1ac, 0x0d58, 0x6124, 0xc1cd, 0x6126, 0x0c38, 0xd0fc, 0x0188, - 0x908c, 0x2020, 0x918e, 0x2020, 0x01a8, 0x9084, 0x0003, 0x908e, - 0x0002, 0x0148, 0x87ff, 0x1120, 0x2009, 0x0041, 0x080c, 0xb20a, - 0x0005, 0x00b9, 0x0ce8, 0x87ff, 0x1dd8, 0x2009, 0x0043, 0x080c, - 0xb20a, 0x0cb0, 0x6110, 0x00b6, 0x2158, 0xb900, 0x00be, 0xd1ac, - 0x0d20, 0x6124, 0xc1cd, 0x6126, 0x0c00, 0x2009, 0x0004, 0x0019, - 0x0005, 0x2009, 0x0001, 0x0096, 0x080c, 0xcf1b, 0x0518, 0x6014, - 0x2048, 0xa982, 0xa800, 0x6016, 0x9186, 0x0001, 0x1188, 0xa97c, - 0x918c, 0x8100, 0x918e, 0x8100, 0x1158, 0x00c6, 0x2061, 0x1a73, - 0x6200, 0xd28c, 0x1120, 0x6204, 0x8210, 0x0208, 0x6206, 0x00ce, - 0x080c, 0x6e4c, 0x6014, 0x904d, 0x0076, 0x2039, 0x0000, 0x190c, - 0x8b34, 0x007e, 0x009e, 0x0005, 0x0156, 0x00c6, 0x2061, 0x1a73, - 0x6000, 0x81ff, 0x0110, 0x9205, 0x0008, 0x9204, 0x6002, 0x00ce, - 0x015e, 0x0005, 0x6800, 0xd08c, 0x1138, 0x6808, 0x9005, 0x0120, - 0x8001, 0x680a, 0x9085, 0x0001, 0x0005, 0x2071, 0x1924, 0x7003, - 0x0006, 0x7007, 0x0000, 0x700f, 0x0000, 0x7013, 0x0001, 0x080c, - 0x1072, 0x090c, 0x0d85, 0xa867, 0x0006, 0xa86b, 0x0001, 0xa8ab, - 0xdcb0, 0xa89f, 0x0000, 0x2900, 0x702e, 0x7033, 0x0000, 0x0005, - 0x0126, 0x2091, 0x8000, 0x0096, 0x00e6, 0x2071, 0x1924, 0x702c, - 0x2048, 0x6a2c, 0x721e, 0x6b30, 0x7322, 0x6834, 0x7026, 0xa896, - 0x6838, 0x702a, 0xa89a, 0x6824, 0x7016, 0x683c, 0x701a, 0x2009, - 0x0028, 0x200a, 0x9005, 0x0148, 0x900e, 0x9188, 0x000c, 0x8001, - 0x1de0, 0x2100, 0x9210, 0x1208, 0x8318, 0xaa8e, 0xab92, 0x7010, - 0xd084, 0x0168, 0xc084, 0x7007, 0x0001, 0x700f, 0x0000, 0x0006, - 0x2009, 0x1b73, 0x2104, 0x9082, 0x0007, 0x200a, 0x000e, 0xc095, - 0x7012, 0x2008, 0x2001, 0x003b, 0x080c, 0x16b9, 0x9006, 0x2071, - 0x193d, 0x7002, 0x7006, 0x702a, 0x00ee, 0x009e, 0x012e, 0x0005, - 0x2009, 0x1b73, 0x2104, 0x9080, 0x0007, 0x200a, 0x0005, 0x00e6, - 0x0126, 0x0156, 0x2091, 0x8000, 0x2071, 0x1800, 0x7154, 0x2001, - 0x0008, 0x910a, 0x0638, 0x2001, 0x187d, 0x20ac, 0x9006, 0x9080, - 0x0008, 0x1f04, 0x8cd7, 0x71c0, 0x9102, 0x02e0, 0x2071, 0x1877, - 0x20a9, 0x0007, 0x00c6, 0x080c, 0xb116, 0x6023, 0x0009, 0x6003, - 0x0004, 0x601f, 0x0101, 0x0089, 0x0126, 0x2091, 0x8000, 0x080c, - 0x8e58, 0x012e, 0x1f04, 0x8ce3, 0x9006, 0x00ce, 0x015e, 0x012e, - 0x00ee, 0x0005, 0x9085, 0x0001, 0x0cc8, 0x00e6, 0x00b6, 0x0096, - 0x0086, 0x0056, 0x0046, 0x0026, 0x7118, 0x720c, 0x7620, 0x7004, - 0xd084, 0x1128, 0x2021, 0x0024, 0x2029, 0x0002, 0x0020, 0x2021, - 0x002c, 0x2029, 0x000a, 0x080c, 0x1059, 0x090c, 0x0d85, 0x2900, - 0x6016, 0x2058, 0xac66, 0x9006, 0xa802, 0xa806, 0xa86a, 0xa87a, - 0xa8aa, 0xa887, 0x0005, 0xa87f, 0x0020, 0x7008, 0xa89a, 0x7010, - 0xa89e, 0xae8a, 0xa8af, 0xffff, 0xa8b3, 0x0000, 0x8109, 0x0160, - 0x080c, 0x1059, 0x090c, 0x0d85, 0xad66, 0x2b00, 0xa802, 0x2900, - 0xb806, 0x2058, 0x8109, 0x1da0, 0x002e, 0x004e, 0x005e, 0x008e, - 0x009e, 0x00be, 0x00ee, 0x0005, 0x2079, 0x0000, 0x2071, 0x1924, - 0x7004, 0x004b, 0x700c, 0x0002, 0x8d4f, 0x8d48, 0x8d48, 0x0005, - 0x8d59, 0x8daf, 0x8daf, 0x8daf, 0x8db0, 0x8dc1, 0x8dc1, 0x700c, - 0x0cba, 0x0126, 0x2091, 0x8000, 0x78a0, 0x79a0, 0x9106, 0x1904, - 0x8da1, 0x7814, 0xd0bc, 0x1904, 0x8daa, 0x012e, 0x7018, 0x910a, - 0x1128, 0x7030, 0x9005, 0x1904, 0x8df3, 0x0005, 0x1210, 0x7114, - 0x910a, 0x9192, 0x000a, 0x0210, 0x2009, 0x000a, 0x2001, 0x1888, - 0x2014, 0x2001, 0x1936, 0x2004, 0x9100, 0x9202, 0x0e50, 0x080c, - 0x8f53, 0x2200, 0x9102, 0x0208, 0x2208, 0x0096, 0x702c, 0x2048, - 0xa873, 0x0001, 0xa976, 0x080c, 0x905c, 0x2100, 0xa87e, 0xa86f, - 0x0000, 0x009e, 0x0126, 0x2091, 0x8000, 0x2009, 0x1a24, 0x2104, - 0xc085, 0x200a, 0x700f, 0x0002, 0x012e, 0x080c, 0x116d, 0x1de8, - 0x0005, 0x78a0, 0x79a0, 0x9106, 0x0904, 0x8d61, 0x080c, 0x8f2b, - 0x012e, 0x0005, 0x7810, 0xc0c5, 0x7812, 0x0804, 0x8d61, 0x0005, - 0x700c, 0x0002, 0x8db5, 0x8db8, 0x8db7, 0x080c, 0x8d57, 0x0005, - 0x8001, 0x700e, 0x0096, 0x702c, 0x2048, 0xa974, 0x009e, 0x0011, - 0x0ca0, 0x0005, 0x0096, 0x702c, 0x2048, 0x7018, 0x9100, 0x7214, - 0x921a, 0x1130, 0x701c, 0xa88e, 0x7020, 0xa892, 0x9006, 0x0068, - 0x0006, 0x080c, 0x905c, 0x2100, 0xaa8c, 0x9210, 0xaa8e, 0x1220, - 0xa890, 0x9081, 0x0000, 0xa892, 0x000e, 0x009e, 0x0126, 0x2091, - 0x8000, 0x78a2, 0x701a, 0x080c, 0x8f2b, 0x012e, 0x0005, 0x00e6, - 0x2071, 0x1924, 0x700c, 0x0002, 0x8df1, 0x8df1, 0x8def, 0x700f, - 0x0001, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x7030, 0x9005, - 0x0508, 0x2078, 0x7814, 0x2048, 0xae88, 0x00b6, 0x2059, 0x0000, - 0x080c, 0x8e61, 0x00be, 0x01b0, 0x00e6, 0x2071, 0x193d, 0x080c, - 0x8ea8, 0x00ee, 0x0178, 0x0096, 0x080c, 0x1072, 0x2900, 0x009e, - 0x0148, 0xa8aa, 0x04d1, 0x0041, 0x2001, 0x1947, 0x2003, 0x0000, - 0x012e, 0x08c8, 0x012e, 0x0005, 0x00d6, 0x00c6, 0x0086, 0x00a6, - 0x2940, 0x2650, 0x2600, 0x9005, 0x0180, 0xa864, 0x9084, 0x000f, - 0x2068, 0x9d88, 0x1ec1, 0x2165, 0x0056, 0x2029, 0x0000, 0x080c, - 0x8fe1, 0x080c, 0x1e97, 0x1dd8, 0x005e, 0x00ae, 0x2001, 0x187f, - 0x2004, 0xa88a, 0x00c6, 0x2f60, 0x080c, 0x17ad, 0x00ce, 0x781f, - 0x0101, 0x7813, 0x0000, 0x0126, 0x2091, 0x8000, 0x080c, 0x8eb7, - 0x012e, 0x008e, 0x00ce, 0x00de, 0x0005, 0x7030, 0x9005, 0x0138, - 0x2078, 0x780c, 0x7032, 0x2001, 0x1947, 0x2003, 0x0001, 0x0005, - 0x00e6, 0x2071, 0x1924, 0x7030, 0x600e, 0x2c00, 0x7032, 0x00ee, - 0x0005, 0x00d6, 0x00c6, 0x0026, 0x9b80, 0x912a, 0x2005, 0x906d, - 0x090c, 0x0d85, 0x9b80, 0x9122, 0x2005, 0x9065, 0x090c, 0x0d85, - 0x6114, 0x2600, 0x9102, 0x0248, 0x6828, 0x9102, 0x02f0, 0x9085, - 0x0001, 0x002e, 0x00ce, 0x00de, 0x0005, 0x6804, 0xd094, 0x0148, - 0x6854, 0xd084, 0x1178, 0xc085, 0x6856, 0x2011, 0x8026, 0x080c, - 0x4ca1, 0x684c, 0x0096, 0x904d, 0x090c, 0x0d85, 0xa804, 0x8000, - 0xa806, 0x009e, 0x9006, 0x2030, 0x0c20, 0x6854, 0xd08c, 0x1d08, - 0xc08d, 0x6856, 0x2011, 0x8025, 0x080c, 0x4ca1, 0x684c, 0x0096, - 0x904d, 0x090c, 0x0d85, 0xa800, 0x8000, 0xa802, 0x009e, 0x0888, - 0x7000, 0x2019, 0x0008, 0x8319, 0x7104, 0x9102, 0x1118, 0x2300, - 0x9005, 0x0020, 0x0210, 0x9302, 0x0008, 0x8002, 0x0005, 0x00d6, - 0x7814, 0x9005, 0x090c, 0x0d85, 0x781c, 0x9084, 0x0101, 0x9086, - 0x0101, 0x190c, 0x0d85, 0x7827, 0x0000, 0x2069, 0x193d, 0x6804, - 0x9080, 0x193f, 0x2f08, 0x2102, 0x6904, 0x8108, 0x9182, 0x0008, - 0x0208, 0x900e, 0x6906, 0x9180, 0x193f, 0x2003, 0x0000, 0x00de, - 0x0005, 0x0096, 0x00c6, 0x2060, 0x6014, 0x2048, 0xa8a8, 0x0096, - 0x2048, 0x9005, 0x190c, 0x108b, 0x009e, 0xa8ab, 0x0000, 0x080c, - 0x100b, 0x080c, 0xb16c, 0x00ce, 0x009e, 0x0005, 0x6020, 0x9086, - 0x0009, 0x1128, 0x601c, 0xd0c4, 0x0110, 0x9006, 0x0005, 0x9085, - 0x0001, 0x0005, 0x6000, 0x9086, 0x0000, 0x0178, 0x6010, 0x9005, - 0x0150, 0x00b6, 0x2058, 0x080c, 0x925e, 0x00be, 0x6013, 0x0000, - 0x601b, 0x0000, 0x0010, 0x2c00, 0x0861, 0x0005, 0x2009, 0x1928, - 0x210c, 0xd194, 0x0005, 0x2009, 0x1928, 0x210c, 0xd1c4, 0x0005, - 0x0126, 0x2091, 0x8000, 0x00e6, 0x2071, 0x1924, 0x7110, 0xc194, - 0xc185, 0x7007, 0x0000, 0x7112, 0x2001, 0x003b, 0x080c, 0x16b9, - 0x00ee, 0x012e, 0x0005, 0x7814, 0xd0bc, 0x1108, 0x0005, 0x7810, - 0xc0c5, 0x7812, 0x0cc0, 0x0096, 0x00d6, 0x9006, 0x7006, 0x700e, - 0x701a, 0x701e, 0x7022, 0x7016, 0x702a, 0x7026, 0x702f, 0x0000, - 0x080c, 0x90aa, 0x0170, 0x080c, 0x90df, 0x0158, 0x2900, 0x7002, - 0x700a, 0x701a, 0x7013, 0x0001, 0x701f, 0x000a, 0x00de, 0x009e, - 0x0005, 0x900e, 0x0cd8, 0x00e6, 0x0096, 0x0086, 0x00d6, 0x00c6, - 0x2071, 0x1931, 0x721c, 0x2100, 0x9202, 0x1618, 0x080c, 0x90df, - 0x090c, 0x0d85, 0x7018, 0x9005, 0x1160, 0x2900, 0x7002, 0x700a, - 0x701a, 0x9006, 0x7006, 0x700e, 0xa806, 0xa802, 0x7012, 0x701e, - 0x0038, 0x2040, 0xa806, 0x2900, 0xa002, 0x701a, 0xa803, 0x0000, - 0x7010, 0x8000, 0x7012, 0x701c, 0x9080, 0x000a, 0x701e, 0x721c, - 0x08d0, 0x721c, 0x00ce, 0x00de, 0x008e, 0x009e, 0x00ee, 0x0005, - 0x0096, 0x0156, 0x0136, 0x0146, 0x00e6, 0x0126, 0x2091, 0x8000, - 0x2071, 0x1931, 0x7300, 0x831f, 0x831e, 0x831e, 0x9384, 0x003f, - 0x20e8, 0x939c, 0xffc0, 0x9398, 0x0003, 0x7104, 0x080c, 0x905c, - 0x810c, 0x2100, 0x9318, 0x8003, 0x2228, 0x2021, 0x0078, 0x9402, - 0x9532, 0x0208, 0x2028, 0x2500, 0x8004, 0x20a8, 0x23a0, 0xa001, - 0xa001, 0x4005, 0x2508, 0x080c, 0x9065, 0x2130, 0x7014, 0x9600, - 0x7016, 0x2600, 0x711c, 0x9102, 0x701e, 0x7004, 0x9600, 0x2008, - 0x9082, 0x000a, 0x1190, 0x7000, 0x2048, 0xa800, 0x9005, 0x1148, - 0x2009, 0x0001, 0x0026, 0x080c, 0x8f53, 0x002e, 0x7000, 0x2048, - 0xa800, 0x7002, 0x7007, 0x0000, 0x0008, 0x7106, 0x2500, 0x9212, - 0x1904, 0x8f92, 0x012e, 0x00ee, 0x014e, 0x013e, 0x015e, 0x009e, - 0x0005, 0x0016, 0x0026, 0x00e6, 0x0126, 0x2091, 0x8000, 0x9580, - 0x9122, 0x2005, 0x9075, 0x090c, 0x0d85, 0x080c, 0x9037, 0x012e, - 0x9580, 0x911e, 0x2005, 0x9075, 0x090c, 0x0d85, 0x0156, 0x0136, - 0x01c6, 0x0146, 0x01d6, 0x831f, 0x831e, 0x831e, 0x9384, 0x003f, - 0x20e0, 0x9384, 0xffc0, 0x9100, 0x2098, 0xa860, 0x20e8, 0xa95c, - 0x2c05, 0x9100, 0x20a0, 0x20a9, 0x0002, 0x4003, 0x2e0c, 0x2d00, - 0x0002, 0x9021, 0x9021, 0x9023, 0x9021, 0x9023, 0x9021, 0x9021, - 0x9021, 0x9021, 0x9021, 0x9029, 0x9021, 0x9029, 0x9021, 0x9021, - 0x9021, 0x080c, 0x0d85, 0x4104, 0x20a9, 0x0002, 0x4002, 0x4003, - 0x0028, 0x20a9, 0x0002, 0x4003, 0x4104, 0x4003, 0x01de, 0x014e, - 0x01ce, 0x013e, 0x015e, 0x00ee, 0x002e, 0x001e, 0x0005, 0x0096, - 0x7014, 0x8001, 0x7016, 0x710c, 0x2110, 0x00f1, 0x810c, 0x9188, - 0x0003, 0x7308, 0x8210, 0x9282, 0x000a, 0x1198, 0x7008, 0x2048, - 0xa800, 0x9005, 0x0158, 0x0006, 0x080c, 0x90ee, 0x009e, 0xa807, - 0x0000, 0x2900, 0x700a, 0x7010, 0x8001, 0x7012, 0x700f, 0x0000, - 0x0008, 0x720e, 0x009e, 0x0005, 0x0006, 0x810b, 0x810b, 0x2100, - 0x810b, 0x9100, 0x2008, 0x000e, 0x0005, 0x0006, 0x0026, 0x2100, - 0x9005, 0x0158, 0x9092, 0x000c, 0x0240, 0x900e, 0x8108, 0x9082, - 0x000c, 0x1de0, 0x002e, 0x000e, 0x0005, 0x900e, 0x0cd8, 0x2d00, - 0x90b8, 0x0008, 0x2031, 0x90a8, 0x901e, 0x6808, 0x9005, 0x0108, - 0x8318, 0x690c, 0x910a, 0x0248, 0x0140, 0x8318, 0x6810, 0x9112, - 0x0220, 0x0118, 0x8318, 0x2208, 0x0cd0, 0x233a, 0x6804, 0xd084, - 0x2300, 0x2021, 0x0001, 0x1150, 0x9082, 0x0003, 0x0967, 0x0a67, - 0x8420, 0x9082, 0x0007, 0x0967, 0x0a67, 0x0cd0, 0x9082, 0x0002, - 0x0967, 0x0a67, 0x8420, 0x9082, 0x0005, 0x0967, 0x0a67, 0x0cd0, - 0x6c1a, 0x0005, 0x0096, 0x0046, 0x0126, 0x2091, 0x8000, 0x2b00, - 0x9080, 0x9126, 0x2005, 0x9005, 0x090c, 0x0d85, 0x2004, 0x90a0, - 0x000a, 0x080c, 0x1072, 0x01d0, 0x2900, 0x7026, 0xa803, 0x0000, - 0xa807, 0x0000, 0x080c, 0x1072, 0x0188, 0x7024, 0xa802, 0xa807, - 0x0000, 0x2900, 0x7026, 0x94a2, 0x000a, 0x0110, 0x0208, 0x0c90, - 0x9085, 0x0001, 0x012e, 0x004e, 0x009e, 0x0005, 0x7024, 0x9005, - 0x0dc8, 0x2048, 0xac00, 0x080c, 0x108b, 0x2400, 0x0cc0, 0x0126, - 0x2091, 0x8000, 0x7024, 0x2048, 0x9005, 0x0130, 0xa800, 0x7026, - 0xa803, 0x0000, 0xa807, 0x0000, 0x012e, 0x0005, 0x0126, 0x2091, - 0x8000, 0x7024, 0xa802, 0x2900, 0x7026, 0x012e, 0x0005, 0x0096, - 0x9e80, 0x0009, 0x2004, 0x9005, 0x0138, 0x2048, 0xa800, 0x0006, - 0x080c, 0x108b, 0x000e, 0x0cb8, 0x009e, 0x0005, 0x0096, 0x7008, - 0x9005, 0x0138, 0x2048, 0xa800, 0x0006, 0x080c, 0x108b, 0x000e, - 0x0cb8, 0x9006, 0x7002, 0x700a, 0x7006, 0x700e, 0x701a, 0x701e, - 0x7022, 0x702a, 0x7026, 0x702e, 0x009e, 0x0005, 0x1a71, 0x0000, - 0x0000, 0x0000, 0x1931, 0x0000, 0x0000, 0x0000, 0x1888, 0x0000, - 0x0000, 0x0000, 0x1877, 0x0000, 0x0000, 0x0000, 0x00e6, 0x00c6, - 0x00b6, 0x00a6, 0xa8a8, 0x2040, 0x2071, 0x1877, 0x080c, 0x924a, - 0xa067, 0x0023, 0x6010, 0x905d, 0x0904, 0x921f, 0xb814, 0xa06e, - 0xb910, 0xa172, 0xb9a0, 0xa176, 0x2001, 0x0003, 0xa07e, 0xa834, - 0xa082, 0xa07b, 0x0000, 0xa898, 0x9005, 0x0118, 0xa078, 0xc085, - 0xa07a, 0x2858, 0x2031, 0x0018, 0xa068, 0x908a, 0x0019, 0x1a0c, - 0x0d85, 0x2020, 0x2050, 0x2940, 0xa864, 0x90bc, 0x00ff, 0x908c, - 0x000f, 0x91e0, 0x1ec1, 0x2c65, 0x9786, 0x0024, 0x2c05, 0x1590, - 0x908a, 0x0036, 0x1a0c, 0x0d85, 0x9082, 0x001b, 0x0002, 0x918a, - 0x918a, 0x918c, 0x918a, 0x918a, 0x918a, 0x918e, 0x918a, 0x918a, - 0x918a, 0x9190, 0x918a, 0x918a, 0x918a, 0x9192, 0x918a, 0x918a, - 0x918a, 0x9194, 0x918a, 0x918a, 0x918a, 0x9196, 0x918a, 0x918a, - 0x918a, 0x9198, 0x080c, 0x0d85, 0xa180, 0x04b8, 0xa190, 0x04a8, - 0xa1a0, 0x0498, 0xa1b0, 0x0488, 0xa1c0, 0x0478, 0xa1d0, 0x0468, - 0xa1e0, 0x0458, 0x908a, 0x0034, 0x1a0c, 0x0d85, 0x9082, 0x001b, - 0x0002, 0x91bc, 0x91ba, 0x91ba, 0x91ba, 0x91ba, 0x91ba, 0x91be, - 0x91ba, 0x91ba, 0x91ba, 0x91ba, 0x91ba, 0x91c0, 0x91ba, 0x91ba, - 0x91ba, 0x91ba, 0x91ba, 0x91c2, 0x91ba, 0x91ba, 0x91ba, 0x91ba, - 0x91ba, 0x91c4, 0x080c, 0x0d85, 0xa180, 0x0038, 0xa198, 0x0028, - 0xa1b0, 0x0018, 0xa1c8, 0x0008, 0xa1e0, 0x2600, 0x0002, 0x91e0, - 0x91e2, 0x91e4, 0x91e6, 0x91e8, 0x91ea, 0x91ec, 0x91ee, 0x91f0, - 0x91f2, 0x91f4, 0x91f6, 0x91f8, 0x91fa, 0x91fc, 0x91fe, 0x9200, - 0x9202, 0x9204, 0x9206, 0x9208, 0x920a, 0x920c, 0x920e, 0x9210, - 0x080c, 0x0d85, 0xb9e2, 0x0468, 0xb9de, 0x0458, 0xb9da, 0x0448, - 0xb9d6, 0x0438, 0xb9d2, 0x0428, 0xb9ce, 0x0418, 0xb9ca, 0x0408, - 0xb9c6, 0x00f8, 0xb9c2, 0x00e8, 0xb9be, 0x00d8, 0xb9ba, 0x00c8, - 0xb9b6, 0x00b8, 0xb9b2, 0x00a8, 0xb9ae, 0x0098, 0xb9aa, 0x0088, - 0xb9a6, 0x0078, 0xb9a2, 0x0068, 0xb99e, 0x0058, 0xb99a, 0x0048, - 0xb996, 0x0038, 0xb992, 0x0028, 0xb98e, 0x0018, 0xb98a, 0x0008, - 0xb986, 0x8631, 0x8421, 0x0130, 0x080c, 0x1e97, 0x090c, 0x0d85, - 0x0804, 0x9164, 0x00ae, 0x00be, 0x00ce, 0x00ee, 0x0005, 0xa86c, - 0xa06e, 0xa870, 0xa072, 0xa077, 0x00ff, 0x9006, 0x0804, 0x9146, - 0x0006, 0x0016, 0x00b6, 0x6010, 0x2058, 0xb810, 0x9005, 0x01b0, - 0x2001, 0x1925, 0x2004, 0x9005, 0x0188, 0x2001, 0x1800, 0x2004, - 0x9086, 0x0003, 0x1158, 0x0036, 0x0046, 0xbba0, 0x2021, 0x0004, - 0x2011, 0x8014, 0x080c, 0x4ca1, 0x004e, 0x003e, 0x00be, 0x001e, - 0x000e, 0x0005, 0x9016, 0x710c, 0xa834, 0x910a, 0xa936, 0x7008, - 0x9005, 0x0120, 0x8210, 0x910a, 0x0230, 0x0128, 0x7010, 0x8210, - 0x910a, 0x0208, 0x1de0, 0xaa8a, 0xa26a, 0x0005, 0x00f6, 0x00d6, - 0x0036, 0x2079, 0x0300, 0x781b, 0x0200, 0x7818, 0xd094, 0x1dd8, - 0x781b, 0x0202, 0xa001, 0xa001, 0x7818, 0xd094, 0x1da0, 0xb8ac, - 0x906d, 0x0198, 0x2079, 0x0000, 0x9c1e, 0x1118, 0x680c, 0xb8ae, - 0x0050, 0x9c06, 0x0130, 0x2d78, 0x680c, 0x906d, 0x1dd0, 0x080c, - 0x0d85, 0x6b0c, 0x7b0e, 0x600f, 0x0000, 0x2079, 0x0300, 0x781b, - 0x0200, 0x003e, 0x00de, 0x00fe, 0x0005, 0x00e6, 0x00d6, 0x0096, - 0x00c6, 0x0036, 0x0126, 0x2091, 0x8000, 0x0156, 0x20a9, 0x01ff, - 0x2071, 0x0300, 0x701b, 0x0200, 0x7018, 0xd094, 0x0110, 0x1f04, - 0x929a, 0x701b, 0x0202, 0xa001, 0xa001, 0x7018, 0xd094, 0x1d90, - 0xb8ac, 0x9065, 0x01f0, 0x600c, 0xb8ae, 0x6024, 0xc08d, 0x6026, - 0x6003, 0x0004, 0x601b, 0x0000, 0x6013, 0x0000, 0x601f, 0x0101, - 0x6014, 0x904d, 0x090c, 0x0d85, 0xa88b, 0x0000, 0xa8a8, 0xa8ab, - 0x0000, 0x904d, 0x090c, 0x0d85, 0x080c, 0x108b, 0x080c, 0x8e58, - 0x08f8, 0x2071, 0x0300, 0x701b, 0x0200, 0x015e, 0x012e, 0x003e, - 0x00ce, 0x009e, 0x00de, 0x00ee, 0x0005, 0x00c6, 0x00b6, 0x0016, - 0x0006, 0x0156, 0x080c, 0x268c, 0x015e, 0x11b0, 0x080c, 0x6749, - 0x190c, 0x0d85, 0x000e, 0x001e, 0xb912, 0xb816, 0x080c, 0xb116, - 0x0140, 0x2b00, 0x6012, 0x6023, 0x0001, 0x2009, 0x0001, 0x080c, - 0xb20a, 0x00be, 0x00ce, 0x0005, 0x000e, 0x001e, 0x0cd0, 0x0066, - 0x6000, 0x90b2, 0x0010, 0x1a0c, 0x0d85, 0x0013, 0x006e, 0x0005, - 0x9310, 0x9310, 0x9310, 0x9312, 0x935b, 0x9310, 0x9310, 0x9310, - 0x93d5, 0x9310, 0x940d, 0x9310, 0x9310, 0x9310, 0x9310, 0x9310, - 0x080c, 0x0d85, 0x9182, 0x0040, 0x0002, 0x9325, 0x9325, 0x9325, - 0x9325, 0x9325, 0x9325, 0x9325, 0x9325, 0x9325, 0x9327, 0x9338, - 0x9325, 0x9325, 0x9325, 0x9325, 0x9349, 0x080c, 0x0d85, 0x0096, - 0x6114, 0x2148, 0xa87b, 0x0000, 0x6010, 0x00b6, 0x2058, 0xb8bb, - 0x0500, 0x00be, 0x080c, 0x6e11, 0x080c, 0xb16c, 0x009e, 0x0005, - 0x080c, 0x9a48, 0x00d6, 0x6114, 0x080c, 0xcf1b, 0x0130, 0x0096, - 0x6114, 0x2148, 0x080c, 0x7012, 0x009e, 0x00de, 0x080c, 0xb16c, - 0x0005, 0x080c, 0x9a48, 0x080c, 0x3315, 0x6114, 0x0096, 0x2148, - 0x080c, 0xcf1b, 0x0120, 0xa87b, 0x0029, 0x080c, 0x7012, 0x009e, - 0x080c, 0xb16c, 0x0005, 0x601b, 0x0000, 0x9182, 0x0040, 0x0096, - 0x0002, 0x9376, 0x9376, 0x9376, 0x9376, 0x9376, 0x9376, 0x9376, - 0x9376, 0x9378, 0x9376, 0x9376, 0x9376, 0x93d1, 0x9376, 0x9376, - 0x9376, 0x9376, 0x9376, 0x9376, 0x937f, 0x9376, 0x080c, 0x0d85, - 0x6114, 0x2148, 0xa938, 0x918e, 0xffff, 0x0904, 0x93d1, 0x6024, - 0xd08c, 0x15d8, 0x080c, 0x8f0e, 0x05e0, 0x00e6, 0x6114, 0x2148, - 0x080c, 0x912e, 0x0096, 0xa8a8, 0x2048, 0x080c, 0x6da9, 0x009e, - 0xa8ab, 0x0000, 0x6010, 0x9005, 0x0128, 0x00b6, 0x2058, 0x080c, - 0x925e, 0x00be, 0xae88, 0x00b6, 0x2059, 0x0000, 0x080c, 0x8e61, - 0x00be, 0x01e0, 0x2071, 0x193d, 0x080c, 0x8ea8, 0x01b8, 0x9086, - 0x0001, 0x1128, 0x2001, 0x1947, 0x2004, 0x9005, 0x1178, 0x0096, - 0x080c, 0x1059, 0x2900, 0x009e, 0x0148, 0xa8aa, 0x00f6, 0x2c78, - 0x080c, 0x8e1c, 0x00fe, 0x00ee, 0x009e, 0x0005, 0x080c, 0x8e58, - 0x0cd0, 0x080c, 0x8f13, 0x1160, 0x6010, 0x9005, 0x0130, 0x2058, - 0xb8ac, 0x9005, 0x190c, 0x0d85, 0x6012, 0x2c00, 0x080c, 0x8ed9, - 0x0005, 0x080c, 0x9489, 0x009e, 0x0005, 0x9182, 0x0040, 0x0096, - 0x0002, 0x93e9, 0x93e9, 0x93e9, 0x93eb, 0x93e9, 0x93e9, 0x93e9, - 0x940b, 0x93e9, 0x93e9, 0x93e9, 0x93e9, 0x93e9, 0x93e9, 0x93e9, - 0x93e9, 0x080c, 0x0d85, 0x6003, 0x0003, 0x6106, 0x6014, 0x2048, - 0xa8ac, 0xa836, 0xa8b0, 0xa83a, 0xa847, 0x0000, 0xa84b, 0x0000, - 0xa884, 0x9092, 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, 0x8013, - 0x8213, 0x9210, 0x621a, 0x080c, 0x1c26, 0x2009, 0x8030, 0x080c, - 0x965e, 0x009e, 0x0005, 0x080c, 0x0d85, 0x080c, 0x9a48, 0x6114, - 0x2148, 0xa87b, 0x0000, 0x6010, 0x00b6, 0x2058, 0xb8bb, 0x0500, - 0x00be, 0x080c, 0x7012, 0x080c, 0xb16c, 0x009e, 0x0005, 0x080c, - 0xacfc, 0x6144, 0xd1fc, 0x0120, 0xd1ac, 0x1110, 0x6003, 0x0003, - 0x6000, 0x908a, 0x0010, 0x1a0c, 0x0d85, 0x0096, 0x0023, 0x009e, - 0x080c, 0xad18, 0x0005, 0x9443, 0x9443, 0x9443, 0x9445, 0x9456, - 0x9443, 0x9443, 0x9443, 0x9443, 0x9443, 0x9443, 0x9443, 0x9443, - 0x9443, 0x9443, 0x9443, 0x080c, 0x0d85, 0x080c, 0xaee3, 0x6114, - 0x2148, 0xa87b, 0x0006, 0x6010, 0x00b6, 0x2058, 0xb8bb, 0x0500, - 0x00be, 0x080c, 0x7012, 0x080c, 0xb16c, 0x0005, 0x0491, 0x0005, - 0x080c, 0xacfc, 0x6000, 0x6144, 0xd1fc, 0x0130, 0xd1ac, 0x1120, - 0x6003, 0x0003, 0x2009, 0x0003, 0x908a, 0x0010, 0x1a0c, 0x0d85, - 0x0096, 0x0033, 0x009e, 0x0106, 0x080c, 0xad18, 0x010e, 0x0005, - 0x9480, 0x9480, 0x9480, 0x9482, 0x9489, 0x9480, 0x9480, 0x9480, - 0x9480, 0x9480, 0x9480, 0x9480, 0x9480, 0x9480, 0x9480, 0x9480, - 0x080c, 0x0d85, 0x0036, 0x00e6, 0x080c, 0xaee3, 0x00ee, 0x003e, - 0x0005, 0x6024, 0xd08c, 0x11f0, 0x00f6, 0x00e6, 0x601b, 0x0000, - 0x6014, 0x2048, 0x6010, 0x9005, 0x0128, 0x00b6, 0x2058, 0x080c, - 0x925e, 0x00be, 0x2071, 0x193d, 0x080c, 0x8ea8, 0x0160, 0x2001, - 0x187f, 0x2004, 0xa88a, 0x2031, 0x0000, 0x2c78, 0x080c, 0x8e1c, - 0x00ee, 0x00fe, 0x0005, 0x0096, 0xa88b, 0x0000, 0xa8a8, 0x2048, - 0x080c, 0x108b, 0x009e, 0xa8ab, 0x0000, 0x080c, 0x8e58, 0x0c80, - 0x2001, 0x1925, 0x200c, 0x918e, 0x0000, 0x190c, 0x8f0e, 0x05c8, - 0x00e6, 0x2071, 0x1924, 0x7110, 0xc1c5, 0x7112, 0x080c, 0x8f18, - 0x00f6, 0x00c6, 0x2071, 0x1000, 0x00b6, 0x2e04, 0x905d, 0x0138, - 0xb8ac, 0x9065, 0x0120, 0x080c, 0x8eee, 0x090c, 0x928d, 0x8e70, - 0x9e86, 0x1800, 0x1d90, 0x00be, 0x00d6, 0x0096, 0x0046, 0x2061, - 0x1ddc, 0x2001, 0x181a, 0x2024, 0x6020, 0x9086, 0x0000, 0x1191, - 0x9ce0, 0x001c, 0x2400, 0x9c06, 0x1db8, 0x004e, 0x009e, 0x00de, - 0x00d1, 0x00ce, 0x00fe, 0x2071, 0x1924, 0x7110, 0xc1c4, 0x7112, - 0x00ee, 0x0005, 0x6020, 0x9086, 0x0009, 0x1160, 0x6100, 0x9186, - 0x0004, 0x1138, 0x6110, 0x81ff, 0x190c, 0x0d85, 0x2c00, 0x080c, - 0x8ed9, 0x9006, 0x0005, 0x2071, 0x193f, 0x2073, 0x0000, 0x8e70, - 0x9e86, 0x1947, 0x1dd0, 0x2071, 0x193d, 0x7006, 0x7002, 0x2001, - 0x1930, 0x2064, 0x8cff, 0x0130, 0x6120, 0x918e, 0x0000, 0x190c, - 0x0d85, 0x2102, 0x2001, 0x188a, 0x200c, 0x81ff, 0x0148, 0x0096, - 0x2148, 0x080c, 0x108b, 0x009e, 0x2001, 0x188a, 0x2003, 0x0000, - 0x2071, 0x1931, 0x080c, 0x90f7, 0x0804, 0x9106, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x187a, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0126, 0x2091, - 0x8000, 0x0036, 0x0046, 0x20a9, 0x0010, 0x9006, 0x8004, 0x8086, - 0x818e, 0x1208, 0x9200, 0x1f04, 0x954f, 0x8086, 0x818e, 0x004e, - 0x003e, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x0076, 0x0156, - 0x20a9, 0x0010, 0x9005, 0x01c8, 0x911a, 0x12b8, 0x8213, 0x818d, - 0x0228, 0x911a, 0x1220, 0x1f04, 0x9566, 0x0028, 0x911a, 0x2308, - 0x8210, 0x1f04, 0x9566, 0x0006, 0x3200, 0x9084, 0xefff, 0x2080, - 0x000e, 0x015e, 0x007e, 0x012e, 0x0005, 0x0006, 0x3200, 0x9085, - 0x1000, 0x0ca8, 0x0126, 0x2091, 0x2800, 0x2079, 0x19e8, 0x012e, - 0x00d6, 0x2069, 0x19e8, 0x6803, 0x0005, 0x0156, 0x0146, 0x01d6, - 0x20e9, 0x0000, 0x2069, 0x0200, 0x080c, 0xaaf1, 0x04c9, 0x080c, - 0xaadc, 0x04b1, 0x080c, 0xaadf, 0x0499, 0x080c, 0xaae2, 0x0481, - 0x080c, 0xaae5, 0x0469, 0x080c, 0xaae8, 0x0451, 0x080c, 0xaaeb, - 0x0439, 0x080c, 0xaaee, 0x0421, 0x01de, 0x014e, 0x015e, 0x6857, - 0x0000, 0x00f6, 0x2079, 0x0380, 0x0419, 0x7807, 0x0003, 0x7803, - 0x0000, 0x7803, 0x0001, 0x2069, 0x0004, 0x2d04, 0x9084, 0xfffe, - 0x9085, 0x8000, 0x206a, 0x2069, 0x0100, 0x6828, 0x9084, 0xfffc, - 0x682a, 0x00fe, 0x2001, 0x1b5d, 0x2003, 0x0000, 0x00de, 0x0005, - 0x20a9, 0x0020, 0x20a1, 0x0240, 0x2001, 0x0000, 0x4004, 0x0005, - 0x00c6, 0x7803, 0x0000, 0x9006, 0x7827, 0x0030, 0x782b, 0x0400, - 0x7827, 0x0031, 0x782b, 0x1af6, 0x781f, 0xff00, 0x781b, 0xff00, - 0x2061, 0x1aeb, 0x602f, 0x19e8, 0x6033, 0x1800, 0x6037, 0x1a04, - 0x603b, 0x1ec1, 0x603f, 0x1ed1, 0x6042, 0x6047, 0x1ac1, 0x00ce, - 0x0005, 0x2001, 0x0382, 0x2004, 0x9084, 0x0007, 0x9086, 0x0001, - 0x01b0, 0x00c6, 0x6146, 0x600f, 0x0000, 0x2c08, 0x2061, 0x19e8, - 0x602c, 0x8000, 0x602e, 0x601c, 0x9005, 0x0130, 0x9080, 0x0003, - 0x2102, 0x611e, 0x00ce, 0x0005, 0x6122, 0x611e, 0x0cd8, 0x6146, - 0x2c08, 0x2001, 0x0012, 0x080c, 0xaced, 0x0005, 0x0016, 0x2009, - 0x8020, 0x6146, 0x2c08, 0x2001, 0x0382, 0x2004, 0x9084, 0x0007, - 0x9086, 0x0001, 0x1128, 0x2001, 0x0019, 0x080c, 0xaced, 0x0088, - 0x00c6, 0x2061, 0x19e8, 0x602c, 0x8000, 0x602e, 0x600c, 0x9005, - 0x0128, 0x9080, 0x0003, 0x2102, 0x610e, 0x0010, 0x6112, 0x610e, - 0x00ce, 0x001e, 0x0005, 0x2001, 0x0382, 0x2004, 0x9084, 0x0007, - 0x9086, 0x0001, 0x0198, 0x00c6, 0x6146, 0x600f, 0x0000, 0x2c08, - 0x2061, 0x19e8, 0x6044, 0x9005, 0x0130, 0x9080, 0x0003, 0x2102, - 0x6146, 0x00ce, 0x0005, 0x614a, 0x6146, 0x0cd8, 0x6146, 0x600f, - 0x0000, 0x2c08, 0x2001, 0x0013, 0x080c, 0xaced, 0x0005, 0x6044, - 0xd0dc, 0x0110, 0x080c, 0xa78a, 0x0005, 0x00f6, 0x00e6, 0x00d6, - 0x00c6, 0x00b6, 0x0096, 0x0076, 0x0066, 0x0056, 0x0036, 0x0026, - 0x0016, 0x0006, 0x0126, 0x902e, 0x2071, 0x19e8, 0x7648, 0x2660, - 0x2678, 0x2091, 0x8000, 0x8cff, 0x0904, 0x96f1, 0x9c86, 0x1b55, - 0x0904, 0x96ec, 0x6010, 0x2058, 0xb8a0, 0x9206, 0x1904, 0x96ec, - 0x87ff, 0x0120, 0x605c, 0x9106, 0x1904, 0x96ec, 0x704c, 0x9c06, - 0x1188, 0x0036, 0x2019, 0x0001, 0x080c, 0xa596, 0x703f, 0x0000, - 0x9006, 0x704e, 0x706a, 0x7052, 0x706e, 0x080c, 0xaff4, 0x003e, - 0x2029, 0x0001, 0x080c, 0x9667, 0x7048, 0x9c36, 0x1110, 0x660c, - 0x764a, 0x7044, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, - 0x7046, 0x0010, 0x7047, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, - 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, 0xcf1b, - 0x01f0, 0x6014, 0x2048, 0x6020, 0x9086, 0x0003, 0x1588, 0x6004, - 0x9086, 0x0040, 0x090c, 0xa78a, 0xa867, 0x0103, 0xab7a, 0xa877, - 0x0000, 0x0016, 0x0036, 0x0076, 0x080c, 0xd220, 0x080c, 0xeddf, - 0x080c, 0x7012, 0x007e, 0x003e, 0x001e, 0x080c, 0xd10c, 0x080c, - 0xb1a7, 0x00ce, 0x0804, 0x9683, 0x2c78, 0x600c, 0x2060, 0x0804, - 0x9683, 0x012e, 0x000e, 0x001e, 0x002e, 0x003e, 0x005e, 0x006e, - 0x007e, 0x009e, 0x00be, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, - 0x6020, 0x9086, 0x0006, 0x1158, 0x0016, 0x0036, 0x0076, 0x080c, - 0xeddf, 0x080c, 0xea30, 0x007e, 0x003e, 0x001e, 0x08c0, 0x6020, - 0x9086, 0x0009, 0x1168, 0xa87b, 0x0006, 0x0016, 0x0036, 0x0076, - 0x080c, 0x7012, 0x080c, 0xb16c, 0x007e, 0x003e, 0x001e, 0x0848, - 0x6020, 0x9086, 0x000a, 0x0904, 0x96d6, 0x0804, 0x96cf, 0x0006, - 0x0066, 0x0096, 0x00c6, 0x00d6, 0x00f6, 0x9036, 0x0126, 0x2091, - 0x8000, 0x2079, 0x19e8, 0x7848, 0x9065, 0x0904, 0x9790, 0x600c, - 0x0006, 0x600f, 0x0000, 0x784c, 0x9c06, 0x11b0, 0x0036, 0x2019, - 0x0001, 0x080c, 0xa596, 0x783f, 0x0000, 0x901e, 0x7b4e, 0x7b6a, - 0x7b52, 0x7b6e, 0x080c, 0xaff4, 0x003e, 0x000e, 0x9005, 0x1118, - 0x600c, 0x600f, 0x0000, 0x0006, 0x9c86, 0x1b55, 0x05b0, 0x00e6, - 0x2f70, 0x080c, 0x9667, 0x00ee, 0x080c, 0xcf1b, 0x0548, 0x6014, - 0x2048, 0x6020, 0x9086, 0x0003, 0x15a8, 0x3e08, 0x918e, 0x0002, - 0x1188, 0x6010, 0x9005, 0x0170, 0x00b6, 0x2058, 0xb800, 0x00be, - 0xd0bc, 0x0140, 0x6048, 0x9005, 0x11c0, 0x2001, 0x1988, 0x2004, - 0x604a, 0x0098, 0x6004, 0x9086, 0x0040, 0x090c, 0xa78a, 0xa867, - 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0x7006, 0x080c, 0xd10c, - 0x6044, 0xc0fc, 0x6046, 0x080c, 0xb1a7, 0x000e, 0x0804, 0x9734, - 0x7e4a, 0x7e46, 0x012e, 0x00fe, 0x00de, 0x00ce, 0x009e, 0x006e, - 0x000e, 0x0005, 0x6020, 0x9086, 0x0006, 0x1118, 0x080c, 0xea30, - 0x0c38, 0x6020, 0x9086, 0x0009, 0x1130, 0xab7a, 0x080c, 0x7012, - 0x080c, 0xb16c, 0x0c10, 0x6020, 0x9086, 0x000a, 0x0990, 0x0850, - 0x0016, 0x0026, 0x0086, 0x9046, 0x00a9, 0x080c, 0x98a3, 0x008e, - 0x002e, 0x001e, 0x0005, 0x00f6, 0x0126, 0x2079, 0x19e8, 0x2091, - 0x8000, 0x080c, 0x98ec, 0x080c, 0x9982, 0x080c, 0x6948, 0x012e, - 0x00fe, 0x0005, 0x00b6, 0x0096, 0x00f6, 0x00e6, 0x00d6, 0x00c6, - 0x0066, 0x0016, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x19e8, - 0x7620, 0x2660, 0x2678, 0x8cff, 0x0904, 0x9868, 0x6010, 0x2058, - 0xb8a0, 0x9206, 0x1904, 0x9863, 0x88ff, 0x0120, 0x605c, 0x9106, - 0x1904, 0x9863, 0x7030, 0x9c06, 0x1580, 0x2069, 0x0100, 0x6820, - 0xd0a4, 0x0110, 0xd0cc, 0x1508, 0x080c, 0x8a4b, 0x080c, 0xa2a0, - 0x68c3, 0x0000, 0x080c, 0xa78a, 0x7033, 0x0000, 0x0036, 0x2069, - 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, - 0x2a99, 0x9006, 0x080c, 0x2a99, 0x2069, 0x0100, 0x6824, 0xd084, - 0x0110, 0x6827, 0x0001, 0x003e, 0x0040, 0x7008, 0xc0ad, 0x700a, - 0x6003, 0x0009, 0x630a, 0x0804, 0x9863, 0x7020, 0x9c36, 0x1110, - 0x660c, 0x7622, 0x701c, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, - 0x2f00, 0x701e, 0x0010, 0x701f, 0x0000, 0x660c, 0x0066, 0x2c00, - 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x6044, - 0xc0fc, 0x6046, 0x6014, 0x2048, 0x080c, 0xcf1b, 0x01e8, 0x6020, - 0x9086, 0x0003, 0x1580, 0x080c, 0xd132, 0x1118, 0x080c, 0xbb5c, - 0x0098, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x0016, 0x0036, - 0x0086, 0x080c, 0xd220, 0x080c, 0xeddf, 0x080c, 0x7012, 0x008e, - 0x003e, 0x001e, 0x080c, 0xd10c, 0x080c, 0xb1a7, 0x080c, 0xa65d, - 0x00ce, 0x0804, 0x97db, 0x2c78, 0x600c, 0x2060, 0x0804, 0x97db, - 0x012e, 0x000e, 0x001e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, - 0x009e, 0x00be, 0x0005, 0x6020, 0x9086, 0x0006, 0x1158, 0x0016, - 0x0036, 0x0086, 0x080c, 0xeddf, 0x080c, 0xea30, 0x008e, 0x003e, - 0x001e, 0x08d0, 0x080c, 0xbb5c, 0x6020, 0x9086, 0x0002, 0x1160, - 0x6004, 0x0006, 0x9086, 0x0085, 0x000e, 0x0904, 0x9849, 0x9086, - 0x008b, 0x0904, 0x9849, 0x0840, 0x6020, 0x9086, 0x0005, 0x1920, - 0x6004, 0x0006, 0x9086, 0x0085, 0x000e, 0x09c8, 0x9086, 0x008b, - 0x09b0, 0x0804, 0x985c, 0x0006, 0x00f6, 0x00e6, 0x0096, 0x00b6, - 0x00c6, 0x0066, 0x0016, 0x0126, 0x2091, 0x8000, 0x9280, 0x1000, - 0x2004, 0x905d, 0x2079, 0x19e8, 0x9036, 0x7828, 0x2060, 0x8cff, - 0x0538, 0x6010, 0x9b06, 0x1500, 0x6043, 0xffff, 0x080c, 0xaf2e, - 0x01d8, 0x610c, 0x0016, 0x080c, 0xa420, 0x6014, 0x2048, 0xa867, - 0x0103, 0xab7a, 0xa877, 0x0000, 0x0016, 0x0036, 0x0086, 0x080c, - 0xd220, 0x080c, 0xeddf, 0x080c, 0x7012, 0x008e, 0x003e, 0x001e, - 0x080c, 0xb1a7, 0x00ce, 0x08d8, 0x2c30, 0x600c, 0x2060, 0x08b8, - 0x080c, 0x6965, 0x012e, 0x001e, 0x006e, 0x00ce, 0x00be, 0x009e, - 0x00ee, 0x00fe, 0x000e, 0x0005, 0x0096, 0x0006, 0x0066, 0x00c6, - 0x00d6, 0x9036, 0x7820, 0x9065, 0x0904, 0x9955, 0x600c, 0x0006, - 0x6044, 0xc0fc, 0x6046, 0x600f, 0x0000, 0x7830, 0x9c06, 0x1598, - 0x2069, 0x0100, 0x6820, 0xd0a4, 0x0110, 0xd0cc, 0x1508, 0x080c, - 0x8a4b, 0x080c, 0xa2a0, 0x68c3, 0x0000, 0x080c, 0xa78a, 0x7833, - 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, - 0x2001, 0x0100, 0x080c, 0x2a99, 0x9006, 0x080c, 0x2a99, 0x2069, - 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x0058, - 0x080c, 0x6ba9, 0x1538, 0x6003, 0x0009, 0x630a, 0x7808, 0xc0ad, - 0x780a, 0x2c30, 0x00f8, 0x6014, 0x2048, 0x080c, 0xcf19, 0x01b0, - 0x6020, 0x9086, 0x0003, 0x1508, 0x080c, 0xd132, 0x1118, 0x080c, - 0xbb5c, 0x0060, 0x080c, 0x6ba9, 0x1168, 0xa867, 0x0103, 0xab7a, - 0xa877, 0x0000, 0x080c, 0x7012, 0x080c, 0xd10c, 0x080c, 0xb1a7, - 0x080c, 0xa65d, 0x000e, 0x0804, 0x98f3, 0x7e22, 0x7e1e, 0x00de, - 0x00ce, 0x006e, 0x000e, 0x009e, 0x0005, 0x6020, 0x9086, 0x0006, - 0x1118, 0x080c, 0xea30, 0x0c50, 0x080c, 0xbb5c, 0x6020, 0x9086, - 0x0002, 0x1150, 0x6004, 0x0006, 0x9086, 0x0085, 0x000e, 0x0990, - 0x9086, 0x008b, 0x0978, 0x08d0, 0x6020, 0x9086, 0x0005, 0x19b0, - 0x6004, 0x0006, 0x9086, 0x0085, 0x000e, 0x0d18, 0x9086, 0x008b, - 0x0d00, 0x0860, 0x0006, 0x0096, 0x00b6, 0x00c6, 0x0066, 0x9036, - 0x7828, 0x9065, 0x0510, 0x6010, 0x2058, 0x600c, 0x0006, 0x3e08, - 0x918e, 0x0002, 0x1118, 0xb800, 0xd0bc, 0x11a8, 0x6043, 0xffff, - 0x080c, 0xaf2e, 0x0180, 0x610c, 0x080c, 0xa420, 0x6014, 0x2048, - 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0x7012, 0x080c, - 0xb1a7, 0x000e, 0x08f0, 0x2c30, 0x0ce0, 0x006e, 0x00ce, 0x00be, - 0x009e, 0x000e, 0x0005, 0x00e6, 0x00d6, 0x0096, 0x0066, 0x080c, - 0x62af, 0x11b0, 0x2071, 0x19e8, 0x7030, 0x9080, 0x0005, 0x2004, - 0x904d, 0x0170, 0xa878, 0x9606, 0x1158, 0x2071, 0x19e8, 0x7030, - 0x9035, 0x0130, 0x9080, 0x0005, 0x2004, 0x9906, 0x1108, 0x0029, - 0x006e, 0x009e, 0x00de, 0x00ee, 0x0005, 0x00c6, 0x2660, 0x6043, - 0xffff, 0x080c, 0xaf2e, 0x0178, 0x080c, 0xa420, 0x6014, 0x2048, - 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0xd220, 0x080c, - 0x7012, 0x080c, 0xb1a7, 0x00ce, 0x0005, 0x00b6, 0x00e6, 0x00c6, - 0x080c, 0xacfc, 0x0106, 0x2071, 0x0101, 0x2e04, 0xc0c4, 0x2072, - 0x6044, 0xd0fc, 0x1138, 0x010e, 0x090c, 0xad18, 0x00ce, 0x00ee, - 0x00be, 0x0005, 0x2071, 0x19e8, 0x7030, 0x9005, 0x0da0, 0x9c06, - 0x190c, 0x0d85, 0x7036, 0x080c, 0x8a4b, 0x7004, 0x9084, 0x0007, - 0x0002, 0x9a1b, 0x9a1d, 0x9a24, 0x9a2e, 0x9a3c, 0x9a1b, 0x9a29, - 0x9a19, 0x080c, 0x0d85, 0x0428, 0x0005, 0x080c, 0xaf19, 0x7007, - 0x0000, 0x7033, 0x0000, 0x00e8, 0x0066, 0x9036, 0x080c, 0xa420, - 0x006e, 0x7007, 0x0000, 0x7033, 0x0000, 0x0098, 0x080c, 0xaf04, - 0x0140, 0x080c, 0xaf19, 0x0128, 0x0066, 0x9036, 0x080c, 0xa420, - 0x006e, 0x7033, 0x0000, 0x0028, 0x080c, 0xaf04, 0x080c, 0xa78a, - 0x0000, 0x010e, 0x090c, 0xad18, 0x00ce, 0x00ee, 0x00be, 0x0005, - 0x00d6, 0x00c6, 0x080c, 0xacfc, 0x0106, 0x6044, 0xd0fc, 0x1130, - 0x010e, 0x090c, 0xad18, 0x00ce, 0x00de, 0x0005, 0x2069, 0x19e8, - 0x684c, 0x9005, 0x0da8, 0x9c06, 0x190c, 0x0d85, 0x6852, 0x00e6, - 0x2d70, 0x080c, 0x9667, 0x00ee, 0x080c, 0x8a58, 0x0016, 0x2009, - 0x0040, 0x080c, 0x2220, 0x001e, 0x683c, 0x9084, 0x0003, 0x0002, - 0x9a76, 0x9a77, 0x9a96, 0x9a74, 0x080c, 0x0d85, 0x0490, 0x6868, - 0x9086, 0x0001, 0x0198, 0x600c, 0x9015, 0x0168, 0x6a4a, 0x600f, - 0x0000, 0x6044, 0x9084, 0x7f7f, 0x6046, 0x9006, 0x6842, 0x684e, - 0x683f, 0x0000, 0x00f0, 0x684a, 0x6846, 0x0c98, 0x686b, 0x0000, - 0x6848, 0x9065, 0x0d70, 0x6003, 0x0002, 0x0c58, 0x6044, 0x9084, - 0x7f7f, 0x6046, 0x9006, 0x6842, 0x684e, 0x686a, 0x6852, 0x686e, - 0x600c, 0x9015, 0x0120, 0x6a4a, 0x600f, 0x0000, 0x0010, 0x684a, - 0x6846, 0x080c, 0xaff4, 0x684f, 0x0000, 0x010e, 0x090c, 0xad18, - 0x00ce, 0x00de, 0x0005, 0x0005, 0x6020, 0x9084, 0x000f, 0x000b, - 0x0005, 0x9ac9, 0x9acc, 0x9f80, 0xa019, 0x9acc, 0x9f80, 0xa019, - 0x9ac9, 0x9acc, 0x9ac9, 0x9ac9, 0x9ac9, 0x9ac9, 0x9ac9, 0x9ac9, - 0x9ac9, 0x080c, 0x99ed, 0x0005, 0x00b6, 0x0156, 0x0136, 0x0146, - 0x01c6, 0x01d6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2069, 0x0200, - 0x2071, 0x0240, 0x6004, 0x908a, 0x0053, 0x1a0c, 0x0d85, 0x6110, - 0x2158, 0xb984, 0x2c78, 0x2061, 0x0100, 0x619a, 0x908a, 0x0040, - 0x1a04, 0x9b38, 0x005b, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x01de, - 0x01ce, 0x014e, 0x013e, 0x015e, 0x00be, 0x0005, 0x9ce1, 0x9d1c, - 0x9d45, 0x9e0f, 0x9e31, 0x9e37, 0x9e44, 0x9e4c, 0x9e58, 0x9e5e, - 0x9e6f, 0x9e5e, 0x9ec7, 0x9e4c, 0x9ed3, 0x9ed9, 0x9e58, 0x9ed9, - 0x9ee5, 0x9b36, 0x9b36, 0x9b36, 0x9b36, 0x9b36, 0x9b36, 0x9b36, - 0x9b36, 0x9b36, 0x9b36, 0x9b36, 0xa441, 0xa464, 0xa475, 0xa495, - 0xa4c7, 0x9e44, 0x9b36, 0x9e44, 0x9e5e, 0x9b36, 0x9d45, 0x9e0f, - 0x9b36, 0xa888, 0x9e5e, 0x9b36, 0xa8a4, 0x9e5e, 0x9b36, 0x9e58, - 0x9cdb, 0x9b59, 0x9b36, 0xa8c0, 0xa92d, 0xaa11, 0x9b36, 0xaa1e, - 0x9e41, 0xaa49, 0x9b36, 0xa4d1, 0xaa55, 0x9b36, 0x080c, 0x0d85, - 0x2100, 0x005b, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x01de, 0x01ce, - 0x014e, 0x013e, 0x015e, 0x00be, 0x0005, 0xaaf5, 0xaba7, 0x9b57, - 0x9b91, 0x9c3d, 0x9c48, 0x9b57, 0x9e44, 0x9b57, 0x9ca2, 0x9cae, - 0x9bac, 0x9b57, 0x9bc7, 0x9bfb, 0xb008, 0xb04d, 0x9e5e, 0x080c, - 0x0d85, 0x00d6, 0x0096, 0x080c, 0x9ef8, 0x0026, 0x0036, 0x7814, - 0x2048, 0xa958, 0xd1cc, 0x1138, 0x2009, 0x2414, 0x2011, 0x0018, - 0x2019, 0x0018, 0x0030, 0x2009, 0x2410, 0x2011, 0x0014, 0x2019, - 0x0014, 0x7102, 0x7206, 0x700b, 0x0800, 0xa83c, 0x700e, 0xa850, - 0x7022, 0xa854, 0x7026, 0x63c2, 0x080c, 0xa270, 0x003e, 0x002e, - 0x009e, 0x00de, 0x0005, 0x7810, 0x00b6, 0x2058, 0xb8a0, 0x00be, - 0x080c, 0xb094, 0x1118, 0x9084, 0xff80, 0x0110, 0x9085, 0x0001, - 0x0005, 0x00d6, 0x0096, 0x080c, 0x9ef8, 0x7003, 0x0500, 0x7814, - 0x2048, 0xa874, 0x700a, 0xa878, 0x700e, 0xa87c, 0x7012, 0xa880, - 0x7016, 0xa884, 0x701a, 0xa888, 0x701e, 0x60c3, 0x0010, 0x080c, - 0xa270, 0x009e, 0x00de, 0x0005, 0x00d6, 0x0096, 0x080c, 0x9ef8, - 0x7003, 0x0500, 0x7814, 0x2048, 0xa8cc, 0x700a, 0xa8d0, 0x700e, - 0xa8d4, 0x7012, 0xa8d8, 0x7016, 0xa8dc, 0x701a, 0xa8e0, 0x701e, - 0x60c3, 0x0010, 0x080c, 0xa270, 0x009e, 0x00de, 0x0005, 0x00d6, - 0x0096, 0x0126, 0x2091, 0x8000, 0x080c, 0x9ef8, 0x20e9, 0x0000, - 0x2001, 0x19a4, 0x2003, 0x0000, 0x7814, 0x2048, 0xa814, 0x8003, - 0x60c2, 0xa830, 0x20a8, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x001b, - 0x2098, 0x2001, 0x19a4, 0x0016, 0x200c, 0x2001, 0x0001, 0x080c, - 0x2205, 0x080c, 0xdcef, 0x9006, 0x080c, 0x2205, 0x001e, 0xa804, - 0x9005, 0x0110, 0x2048, 0x0c28, 0x04d9, 0x080c, 0xa270, 0x012e, - 0x009e, 0x00de, 0x0005, 0x00d6, 0x0096, 0x0126, 0x2091, 0x8000, - 0x080c, 0x9f43, 0x20e9, 0x0000, 0x2001, 0x19a4, 0x2003, 0x0000, - 0x7814, 0x2048, 0xa86f, 0x0200, 0xa873, 0x0000, 0xa814, 0x8003, - 0x60c2, 0xa830, 0x20a8, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x001b, - 0x2098, 0x2001, 0x19a4, 0x0016, 0x200c, 0x080c, 0xdcef, 0x001e, - 0xa804, 0x9005, 0x0110, 0x2048, 0x0c60, 0x0051, 0x7814, 0x2048, - 0x080c, 0x100b, 0x080c, 0xa270, 0x012e, 0x009e, 0x00de, 0x0005, - 0x60c0, 0x8004, 0x9084, 0x0003, 0x9005, 0x0130, 0x9082, 0x0004, - 0x20a3, 0x0000, 0x8000, 0x1de0, 0x0005, 0x080c, 0x9ef8, 0x7003, - 0x7800, 0x7808, 0x8007, 0x700a, 0x60c3, 0x0008, 0x0804, 0xa270, - 0x00d6, 0x00e6, 0x080c, 0x9f43, 0x7814, 0x9084, 0xff00, 0x2073, - 0x0200, 0x8e70, 0x8e70, 0x9096, 0xdf00, 0x0138, 0x9096, 0xe000, - 0x0120, 0x2073, 0x0010, 0x8e70, 0x0030, 0x9095, 0x0010, 0x2272, - 0x8e70, 0x2073, 0x0034, 0x8e70, 0x2069, 0x1805, 0x20a9, 0x0004, - 0x2d76, 0x8d68, 0x8e70, 0x1f04, 0x9c68, 0x2069, 0x1801, 0x20a9, - 0x0004, 0x2d76, 0x8d68, 0x8e70, 0x1f04, 0x9c71, 0x9096, 0xdf00, - 0x0130, 0x9096, 0xe000, 0x0118, 0x60c3, 0x0018, 0x00f0, 0x2069, - 0x19b4, 0x9086, 0xdf00, 0x0110, 0x2069, 0x19ce, 0x20a9, 0x001a, - 0x9e86, 0x0260, 0x1148, 0x00c6, 0x2061, 0x0200, 0x6010, 0x8000, - 0x6012, 0x00ce, 0x2071, 0x0240, 0x2d04, 0x8007, 0x2072, 0x8d68, - 0x8e70, 0x1f04, 0x9c88, 0x60c3, 0x004c, 0x080c, 0xa270, 0x00ee, - 0x00de, 0x0005, 0x080c, 0x9ef8, 0x7003, 0x6300, 0x7007, 0x0028, - 0x7808, 0x700e, 0x60c3, 0x0008, 0x0804, 0xa270, 0x00d6, 0x0026, - 0x0016, 0x080c, 0x9f43, 0x7003, 0x0200, 0x7814, 0x700e, 0x00e6, - 0x9ef0, 0x0004, 0x2009, 0x0001, 0x2011, 0x000c, 0x2069, 0x1924, - 0x6810, 0xd084, 0x1148, 0x2073, 0x0500, 0x8e70, 0x2073, 0x0000, - 0x8e70, 0x8108, 0x9290, 0x0004, 0x2073, 0x0800, 0x8e70, 0x2073, - 0x0000, 0x00ee, 0x7206, 0x710a, 0x62c2, 0x080c, 0xa270, 0x001e, - 0x002e, 0x00de, 0x0005, 0x2001, 0x1818, 0x2004, 0x609a, 0x0804, - 0xa270, 0x080c, 0x9ef8, 0x7003, 0x5200, 0x2069, 0x1847, 0x6804, - 0xd084, 0x0130, 0x6828, 0x0016, 0x080c, 0x26bf, 0x710e, 0x001e, - 0x20a9, 0x0004, 0x20e1, 0x0001, 0x2099, 0x1805, 0x20e9, 0x0000, - 0x20a1, 0x0250, 0x4003, 0x20a9, 0x0004, 0x2099, 0x1801, 0x20a1, - 0x0254, 0x4003, 0x080c, 0xb094, 0x1120, 0xb8a0, 0x9082, 0x007f, - 0x0248, 0x2001, 0x181f, 0x2004, 0x7032, 0x2001, 0x1820, 0x2004, - 0x7036, 0x0030, 0x2001, 0x1818, 0x2004, 0x9084, 0x00ff, 0x7036, - 0x60c3, 0x001c, 0x0804, 0xa270, 0x080c, 0x9ef8, 0x7003, 0x0500, - 0x080c, 0xb094, 0x1120, 0xb8a0, 0x9082, 0x007f, 0x0248, 0x2001, - 0x181f, 0x2004, 0x700a, 0x2001, 0x1820, 0x2004, 0x700e, 0x0030, - 0x2001, 0x1818, 0x2004, 0x9084, 0x00ff, 0x700e, 0x20a9, 0x0004, - 0x20e1, 0x0001, 0x2099, 0x1805, 0x20e9, 0x0000, 0x20a1, 0x0250, - 0x4003, 0x60c3, 0x0010, 0x0804, 0xa270, 0x080c, 0x9ef8, 0x9006, - 0x080c, 0x6bdb, 0xb8a0, 0x9086, 0x007e, 0x1170, 0x2011, 0x0240, - 0x2013, 0x22ff, 0x2011, 0x0241, 0x2013, 0xfffe, 0x7003, 0x0400, - 0x620c, 0xc2b4, 0x620e, 0x0058, 0x7814, 0x0096, 0x904d, 0x0120, - 0x9006, 0xa89a, 0xa8a6, 0xa8aa, 0x009e, 0x7003, 0x0300, 0xb8a0, - 0x9086, 0x007e, 0x1904, 0x9dcf, 0x00d6, 0x2069, 0x196c, 0x2001, - 0x1837, 0x2004, 0xd0a4, 0x0188, 0x6800, 0x700a, 0x6808, 0x9084, - 0x2000, 0x7012, 0x080c, 0xb0ab, 0x680c, 0x7016, 0x701f, 0x2710, - 0x6818, 0x7022, 0x681c, 0x7026, 0x0428, 0x6800, 0x700a, 0x6804, - 0x700e, 0x2009, 0x180d, 0x210c, 0xd18c, 0x0110, 0x2001, 0x0002, - 0x00f6, 0x2079, 0x0100, 0x080c, 0x779e, 0x1128, 0x78e3, 0x0000, - 0x080c, 0x2700, 0x78e2, 0x00fe, 0x6808, 0x080c, 0x779e, 0x1118, - 0x9084, 0x37ff, 0x0010, 0x9084, 0x3fff, 0x7012, 0x080c, 0xb0ab, - 0x680c, 0x7016, 0x00de, 0x20a9, 0x0004, 0x20e1, 0x0001, 0x2099, - 0x1805, 0x20e9, 0x0000, 0x20a1, 0x0256, 0x4003, 0x20a9, 0x0004, - 0x2099, 0x1801, 0x20a1, 0x025a, 0x4003, 0x00d6, 0x080c, 0xaadc, - 0x2069, 0x1974, 0x2071, 0x024e, 0x6800, 0xc0dd, 0x7002, 0x080c, - 0x5844, 0xd0e4, 0x0110, 0x680c, 0x700e, 0x00de, 0x04e0, 0x2001, - 0x1837, 0x2004, 0xd0a4, 0x01a8, 0x0016, 0x2001, 0x180d, 0x2004, - 0xd08c, 0x2009, 0x0002, 0x1118, 0x2001, 0x196d, 0x200c, 0x60e0, - 0x9106, 0x0130, 0x2100, 0x60e3, 0x0000, 0x080c, 0x2700, 0x61e2, - 0x001e, 0x20e1, 0x0001, 0x2099, 0x196c, 0x20e9, 0x0000, 0x20a1, - 0x024e, 0x20a9, 0x0008, 0x4003, 0x20a9, 0x0004, 0x2099, 0x1805, - 0x20a1, 0x0256, 0x4003, 0x20a9, 0x0004, 0x2099, 0x1801, 0x20a1, - 0x025a, 0x4003, 0x080c, 0xaadc, 0x20a1, 0x024e, 0x20a9, 0x0008, - 0x2099, 0x1974, 0x4003, 0x60c3, 0x0074, 0x0804, 0xa270, 0x080c, - 0x9ef8, 0x7003, 0x2010, 0x7007, 0x0014, 0x700b, 0x0800, 0x700f, - 0x2000, 0x9006, 0x00f6, 0x2079, 0x1847, 0x7904, 0x00fe, 0xd1ac, - 0x1110, 0x9085, 0x0020, 0xd1a4, 0x0110, 0x9085, 0x0010, 0x9085, - 0x0002, 0x00d6, 0x0804, 0x9ea8, 0x7026, 0x60c3, 0x0014, 0x0804, - 0xa270, 0x080c, 0x9ef8, 0x7003, 0x5000, 0x0804, 0x9d67, 0x080c, - 0x9ef8, 0x7003, 0x2110, 0x7007, 0x0014, 0x60c3, 0x0014, 0x0804, - 0xa270, 0x080c, 0x9f3a, 0x0010, 0x080c, 0x9f43, 0x7003, 0x0200, - 0x60c3, 0x0004, 0x0804, 0xa270, 0x080c, 0x9f43, 0x7003, 0x0100, - 0x700b, 0x0003, 0x700f, 0x2a00, 0x60c3, 0x0008, 0x0804, 0xa270, - 0x080c, 0x9f43, 0x7003, 0x0200, 0x0804, 0x9d67, 0x080c, 0x9f43, - 0x7003, 0x0100, 0x782c, 0x9005, 0x0110, 0x700a, 0x0010, 0x700b, - 0x0003, 0x7814, 0x700e, 0x60c3, 0x0008, 0x0804, 0xa270, 0x00d6, - 0x080c, 0x9f43, 0x7003, 0x0210, 0x7007, 0x0014, 0x700b, 0x0800, - 0xb894, 0x9086, 0x0014, 0x1198, 0xb99c, 0x9184, 0x0030, 0x0190, - 0xb998, 0x9184, 0xc000, 0x1140, 0xd1ec, 0x0118, 0x700f, 0x2100, - 0x0058, 0x700f, 0x0100, 0x0040, 0x700f, 0x0400, 0x0028, 0x700f, - 0x0700, 0x0010, 0x700f, 0x0800, 0x00f6, 0x2079, 0x1847, 0x7904, - 0x00fe, 0xd1ac, 0x1110, 0x9085, 0x0020, 0xd1a4, 0x0110, 0x9085, - 0x0010, 0x2009, 0x1869, 0x210c, 0xd184, 0x1110, 0x9085, 0x0002, - 0x0026, 0x2009, 0x1867, 0x210c, 0xd1e4, 0x0150, 0xc0c5, 0xbad4, - 0xd28c, 0x1108, 0xc0cd, 0x9094, 0x0030, 0x9296, 0x0010, 0x0140, - 0xd1ec, 0x0130, 0x9094, 0x0030, 0x9296, 0x0010, 0x0108, 0xc0bd, - 0x002e, 0x7026, 0x60c3, 0x0014, 0x00de, 0x0804, 0xa270, 0x080c, - 0x9f43, 0x7003, 0x0210, 0x7007, 0x0014, 0x700f, 0x0100, 0x60c3, - 0x0014, 0x0804, 0xa270, 0x080c, 0x9f43, 0x7003, 0x0200, 0x0804, - 0x9ce5, 0x080c, 0x9f43, 0x7003, 0x0100, 0x700b, 0x0003, 0x700f, - 0x2a00, 0x60c3, 0x0008, 0x0804, 0xa270, 0x080c, 0x9f43, 0x7003, - 0x0100, 0x700b, 0x000b, 0x60c3, 0x0008, 0x0804, 0xa270, 0x0026, - 0x00d6, 0x0036, 0x0046, 0x2019, 0x3200, 0x2021, 0x0800, 0x0040, - 0x0026, 0x00d6, 0x0036, 0x0046, 0x2019, 0x2200, 0x2021, 0x0100, - 0x080c, 0xaaf1, 0xb810, 0x9305, 0x7002, 0xb814, 0x7006, 0x2069, - 0x1800, 0x687c, 0x700a, 0x6880, 0x700e, 0x9485, 0x0029, 0x7012, - 0x004e, 0x003e, 0x00de, 0x080c, 0xa264, 0x721a, 0x9f95, 0x0000, - 0x7222, 0x7027, 0xffff, 0x2071, 0x024c, 0x002e, 0x0005, 0x0026, - 0x080c, 0xaaf1, 0x7003, 0x02ff, 0x7007, 0xfffc, 0x00d6, 0x2069, - 0x1800, 0x687c, 0x700a, 0x6880, 0x700e, 0x00de, 0x7013, 0x2029, - 0x0c10, 0x7003, 0x0100, 0x7007, 0x0000, 0x700b, 0xfc02, 0x700f, - 0x0000, 0x0005, 0x0026, 0x00d6, 0x0036, 0x0046, 0x2019, 0x3300, - 0x2021, 0x0800, 0x0040, 0x0026, 0x00d6, 0x0036, 0x0046, 0x2019, - 0x2300, 0x2021, 0x0100, 0x080c, 0xaaf1, 0xb810, 0x9305, 0x7002, - 0xb814, 0x7006, 0x2069, 0x1800, 0xb810, 0x9005, 0x1140, 0xb814, - 0x9005, 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffe, 0x0020, 0x687c, - 0x700a, 0x6880, 0x700e, 0x0000, 0x9485, 0x0098, 0x7012, 0x004e, - 0x003e, 0x00de, 0x080c, 0xa264, 0x721a, 0x7a08, 0x7222, 0x2f10, - 0x7226, 0x2071, 0x024c, 0x002e, 0x0005, 0x080c, 0xa264, 0x721a, - 0x7a08, 0x7222, 0x7814, 0x7026, 0x2071, 0x024c, 0x002e, 0x0005, - 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2069, 0x0200, 0x2071, - 0x0240, 0x6004, 0x908a, 0x0085, 0x0a0c, 0x0d85, 0x908a, 0x0092, - 0x1a0c, 0x0d85, 0x6110, 0x2158, 0xb984, 0x2c78, 0x2061, 0x0100, - 0x619a, 0x9082, 0x0085, 0x0033, 0x00fe, 0x00ee, 0x00de, 0x00ce, - 0x00be, 0x0005, 0x9fb1, 0x9fc0, 0x9fcb, 0x9faf, 0x9faf, 0x9faf, - 0x9fb1, 0x9faf, 0x9faf, 0x9faf, 0x9faf, 0x9faf, 0x9faf, 0x080c, - 0x0d85, 0x0411, 0x60c3, 0x0000, 0x0026, 0x080c, 0x2a04, 0x0228, - 0x2011, 0x0101, 0x2204, 0xc0c5, 0x2012, 0x002e, 0x0804, 0xa270, - 0x0431, 0x7808, 0x700a, 0x7814, 0x700e, 0x7017, 0xffff, 0x60c3, - 0x000c, 0x0804, 0xa270, 0x04a1, 0x7003, 0x0003, 0x7007, 0x0300, - 0x60c3, 0x0004, 0x0804, 0xa270, 0x0026, 0x080c, 0xaaf1, 0xb810, - 0x9085, 0x8100, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, 0x687c, - 0x700a, 0x6880, 0x700e, 0x7013, 0x0009, 0x0804, 0x9f13, 0x0026, - 0x080c, 0xaaf1, 0xb810, 0x9085, 0x8400, 0x7002, 0xb814, 0x7006, - 0x2069, 0x1800, 0x687c, 0x700a, 0x6880, 0x700e, 0x2001, 0x0099, - 0x7a20, 0x9296, 0x0005, 0x0108, 0xc0bc, 0x7012, 0x0804, 0x9f75, - 0x0026, 0x080c, 0xaaf1, 0xb810, 0x9085, 0x8500, 0x7002, 0xb814, - 0x7006, 0x2069, 0x1800, 0x687c, 0x700a, 0x6880, 0x700e, 0x2001, - 0x0099, 0x7a20, 0x9296, 0x0005, 0x0108, 0xc0bc, 0x7012, 0x0804, - 0x9f75, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2c78, 0x2069, - 0x0200, 0x2071, 0x0240, 0x7804, 0x908a, 0x0040, 0x0a0c, 0x0d85, - 0x908a, 0x0057, 0x1a0c, 0x0d85, 0x7910, 0x2158, 0xb984, 0x2061, - 0x0100, 0x619a, 0x9082, 0x0040, 0x0033, 0x00fe, 0x00ee, 0x00de, - 0x00ce, 0x00be, 0x0005, 0xa04e, 0xa04e, 0xa04e, 0xa07f, 0xa04e, - 0xa04e, 0xa04e, 0xa04e, 0xa04e, 0xa04e, 0xa04e, 0xa644, 0xa649, - 0xa64e, 0xa653, 0xa04e, 0xa04e, 0xa04e, 0xa63f, 0x080c, 0x0d85, - 0x6813, 0x0008, 0xba8c, 0x8210, 0xb8d4, 0xd084, 0x0180, 0x2001, - 0x1b72, 0x200c, 0x8108, 0x2102, 0x2001, 0x1b71, 0x201c, 0x1218, - 0x8318, 0x2302, 0x0ea0, 0x7952, 0x712e, 0x7b4e, 0x732a, 0x9294, - 0x00ff, 0xba8e, 0x8217, 0x721a, 0xba10, 0x9295, 0x0600, 0x7202, - 0xba14, 0x7206, 0x2069, 0x1800, 0x6a7c, 0x720a, 0x6a80, 0x720e, - 0x7013, 0x0829, 0x2f10, 0x7222, 0x7027, 0xffff, 0x0005, 0x0016, - 0x7814, 0x9084, 0x0700, 0x8007, 0x0013, 0x001e, 0x0005, 0xa08f, - 0xa08f, 0xa091, 0xa08f, 0xa08f, 0xa08f, 0xa0ab, 0xa08f, 0x080c, - 0x0d85, 0x7914, 0x918c, 0x08ff, 0x918d, 0xf600, 0x7916, 0x2009, - 0x0003, 0x00b9, 0x2069, 0x1847, 0x6804, 0xd0bc, 0x0130, 0x682c, - 0x9084, 0x00ff, 0x8007, 0x7032, 0x0010, 0x7033, 0x3f00, 0x60c3, - 0x0001, 0x0804, 0xa270, 0x2009, 0x0003, 0x0019, 0x7033, 0x7f00, - 0x0cb0, 0x0016, 0x080c, 0xaaf1, 0x001e, 0xb810, 0x9085, 0x0100, - 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, 0x6a7c, 0x720a, 0x6a80, - 0x720e, 0x7013, 0x0888, 0x918d, 0x0008, 0x7116, 0x080c, 0xa264, - 0x721a, 0x7a08, 0x7222, 0x2f10, 0x7226, 0x0005, 0x00b6, 0x00e6, - 0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046, 0x0036, 0x2061, 0x0100, - 0x2071, 0x1800, 0x7160, 0x7810, 0x2058, 0x76dc, 0x96b4, 0x0028, - 0x0110, 0x737c, 0x7480, 0x2500, 0x76dc, 0x96b4, 0x0028, 0x0140, - 0x2001, 0x04ff, 0x6062, 0x6067, 0xffff, 0x636a, 0x646e, 0x0050, - 0x2001, 0x00ff, 0x9085, 0x0400, 0x6062, 0x6067, 0xffff, 0x606b, - 0x0000, 0x616e, 0xb8b8, 0x6073, 0x0530, 0x6077, 0x0008, 0xb88c, - 0x8000, 0x9084, 0x00ff, 0xb88e, 0x8007, 0x9085, 0x0020, 0x607a, - 0x607f, 0x0000, 0x2b00, 0x6082, 0x6087, 0xffff, 0x7814, 0x0096, - 0x2048, 0xa848, 0x608a, 0xa844, 0x608e, 0xa838, 0x60c6, 0xa834, - 0x60ca, 0x009e, 0xb86c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5, - 0x60d7, 0x0000, 0x2001, 0x1837, 0x2004, 0x9084, 0x0028, 0x0128, - 0x609f, 0x0000, 0x2001, 0x0092, 0x0058, 0x6028, 0xc0bd, 0x602a, - 0x609f, 0x00ff, 0x2011, 0xffff, 0x080c, 0x2ad3, 0x2001, 0x00b2, - 0x2010, 0x900e, 0x080c, 0x2ae2, 0x2009, 0x07d0, 0x080c, 0x8a50, - 0x003e, 0x004e, 0x005e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00be, - 0x0005, 0x00b6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046, - 0x0036, 0x2061, 0x0100, 0x2071, 0x1800, 0x7160, 0x7810, 0x2058, - 0xb8a0, 0x2028, 0x76dc, 0xd6ac, 0x1168, 0x9582, 0x007e, 0x1250, - 0x2500, 0x9094, 0xff80, 0x1130, 0x9080, 0x348e, 0x2015, 0x9294, - 0x00ff, 0x0020, 0xb910, 0xba14, 0x737c, 0x7480, 0x70dc, 0xd0ac, - 0x1130, 0x9582, 0x007e, 0x1218, 0x9584, 0xff80, 0x0138, 0x9185, - 0x0400, 0x6062, 0x6266, 0x636a, 0x646e, 0x0030, 0x6063, 0x0400, - 0x6266, 0x606b, 0x0000, 0x616e, 0xb8b8, 0x6072, 0x6077, 0x0000, - 0xb864, 0xd0a4, 0x0110, 0x6077, 0x0008, 0xb88c, 0x8000, 0x9084, - 0x00ff, 0xb88e, 0x8007, 0x9085, 0x0020, 0x607a, 0x607f, 0x0000, - 0x2b00, 0x6082, 0x6087, 0xffff, 0x7814, 0x0096, 0x2048, 0xa848, - 0x608a, 0xa844, 0x608e, 0xa838, 0x60c6, 0xa834, 0x60ca, 0x009e, - 0xb86c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5, 0x60d7, 0x0000, - 0xba84, 0x629e, 0x00f6, 0x2079, 0x0140, 0x7803, 0x0000, 0x00fe, - 0x900e, 0x2011, 0x0092, 0x080c, 0x2ae2, 0x2009, 0x07d0, 0x080c, - 0x8a50, 0x003e, 0x004e, 0x005e, 0x006e, 0x00ce, 0x00de, 0x00ee, - 0x00be, 0x0005, 0x00b6, 0x0096, 0x00e6, 0x00d6, 0x00c6, 0x0056, - 0x0046, 0x0036, 0x2061, 0x0100, 0x2071, 0x1800, 0x7810, 0x2058, - 0xb8a0, 0x2028, 0xb910, 0xba14, 0x737c, 0x7480, 0x7820, 0x0002, - 0xa1ef, 0xa1ef, 0xa1ef, 0xa1ef, 0xa1ef, 0xa1ef, 0xa1ef, 0xa1ef, - 0xa1ef, 0xa1ef, 0xa1f1, 0xa1ef, 0xa1ef, 0xa1ef, 0xa1ef, 0x080c, - 0x0d85, 0xb884, 0x609e, 0x7814, 0x2048, 0xa87c, 0xd0fc, 0x0558, - 0xaf90, 0x9784, 0xff00, 0x9105, 0x6062, 0x873f, 0x9784, 0xff00, - 0x0006, 0x7814, 0x2048, 0xa878, 0xc0fc, 0x9005, 0x000e, 0x1160, - 0xaf94, 0x87ff, 0x0198, 0x2039, 0x0098, 0x9705, 0x6072, 0x7808, - 0x6082, 0x2f00, 0x6086, 0x0038, 0x9185, 0x2200, 0x6062, 0x6073, - 0x0129, 0x6077, 0x0000, 0xb884, 0x609e, 0x0050, 0x2039, 0x0029, - 0x9705, 0x6072, 0x0cc0, 0x9185, 0x0200, 0x6062, 0x6073, 0x2029, - 0xa87c, 0xd0fc, 0x0118, 0xaf94, 0x87ff, 0x1120, 0x2f00, 0x6082, - 0x7808, 0x6086, 0x6266, 0x636a, 0x646e, 0x6077, 0x0000, 0xb88c, - 0x8000, 0x9084, 0x00ff, 0xb88e, 0x8007, 0x607a, 0x607f, 0x0000, - 0xa848, 0x608a, 0xa844, 0x608e, 0xa838, 0x60c6, 0xa834, 0x60ca, - 0xb86c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, 0x080c, 0xaad1, - 0x2009, 0x07d0, 0x60c4, 0x9084, 0xfff0, 0x9005, 0x0110, 0x2009, - 0x1b58, 0x080c, 0x8a50, 0x003e, 0x004e, 0x005e, 0x00ce, 0x00de, - 0x00ee, 0x009e, 0x00be, 0x0005, 0x7a40, 0x9294, 0x00ff, 0x8217, - 0x0005, 0x00d6, 0x2069, 0x19e8, 0x686b, 0x0001, 0x00de, 0x0005, - 0x60a3, 0x0056, 0x60a7, 0x9575, 0x00f1, 0x080c, 0x8a42, 0x0005, - 0x0016, 0x2001, 0x180c, 0x200c, 0x9184, 0x0600, 0x9086, 0x0600, - 0x0128, 0x0089, 0x080c, 0x8a42, 0x001e, 0x0005, 0xc1e5, 0x2001, - 0x180c, 0x2102, 0x2001, 0x19e9, 0x2003, 0x0000, 0x2001, 0x19f4, - 0x2003, 0x0000, 0x0c88, 0x0006, 0x0016, 0x0026, 0x2009, 0x1804, - 0x2011, 0x0009, 0x080c, 0x2ae2, 0x002e, 0x001e, 0x000e, 0x0005, - 0x0016, 0x00c6, 0x0006, 0x080c, 0xacfc, 0x0106, 0x2061, 0x0100, - 0x61a4, 0x60a7, 0x95f5, 0x0016, 0x0026, 0x2009, 0x1804, 0x2011, - 0x0008, 0x080c, 0x2ae2, 0x002e, 0x001e, 0x010e, 0x090c, 0xad18, - 0x000e, 0xa001, 0xa001, 0xa001, 0x61a6, 0x00ce, 0x001e, 0x0005, - 0x00c6, 0x00d6, 0x0016, 0x0026, 0x2061, 0x0100, 0x2069, 0x0140, - 0x080c, 0x779e, 0x1510, 0x2001, 0x1a0d, 0x2004, 0x9005, 0x1904, - 0xa31f, 0x080c, 0x7840, 0x11a8, 0x2069, 0x0380, 0x6843, 0x0101, - 0x6844, 0xd084, 0x1de8, 0x2061, 0x0100, 0x6020, 0xd0b4, 0x1120, - 0x6024, 0xd084, 0x090c, 0x0d85, 0x6843, 0x0100, 0x080c, 0x8a42, - 0x04b0, 0x00c6, 0x2061, 0x19e8, 0x00f0, 0x6904, 0x9194, 0x4000, - 0x0598, 0x080c, 0xa2a0, 0x080c, 0x2aa9, 0x00c6, 0x2061, 0x19e8, - 0x6134, 0x9192, 0x0008, 0x1278, 0x8108, 0x6136, 0x080c, 0xacfc, - 0x6130, 0x080c, 0xad18, 0x00ce, 0x81ff, 0x01c8, 0x080c, 0x8a42, - 0x080c, 0xa293, 0x00a0, 0x080c, 0xacfc, 0x6130, 0x91e5, 0x0000, - 0x0150, 0x080c, 0xeeee, 0x080c, 0x8a4b, 0x6003, 0x0001, 0x2009, - 0x0014, 0x080c, 0xb20a, 0x080c, 0xad18, 0x00ce, 0x0000, 0x002e, - 0x001e, 0x00de, 0x00ce, 0x0005, 0x2001, 0x1a0d, 0x2004, 0x9005, - 0x1db0, 0x00c6, 0x2061, 0x19e8, 0x6134, 0x9192, 0x0003, 0x1ad8, - 0x8108, 0x6136, 0x00ce, 0x080c, 0x8a42, 0x080c, 0x6058, 0x2009, - 0x1846, 0x2114, 0x8210, 0x220a, 0x0c10, 0x0096, 0x00c6, 0x00d6, - 0x00e6, 0x0016, 0x0026, 0x080c, 0x8a58, 0x080c, 0xacfc, 0x2001, - 0x0387, 0x2003, 0x0202, 0x2071, 0x19e8, 0x714c, 0x81ff, 0x0904, - 0xa3d9, 0x2061, 0x0100, 0x2069, 0x0140, 0x080c, 0x779e, 0x1518, - 0x0036, 0x2019, 0x0002, 0x080c, 0xa596, 0x003e, 0x080c, 0xeeee, - 0x704c, 0x9065, 0x0180, 0x2009, 0x004a, 0x6220, 0x9296, 0x0009, - 0x1130, 0x6114, 0x2148, 0xa87b, 0x0006, 0x2009, 0x004a, 0x6003, - 0x0003, 0x080c, 0xb20a, 0x2001, 0x0386, 0x2003, 0x5040, 0x080c, - 0x7840, 0x0804, 0xa3d9, 0x6904, 0xd1f4, 0x0904, 0xa3e6, 0x080c, - 0x2aa9, 0x00c6, 0x704c, 0x9065, 0x090c, 0x0d85, 0x6020, 0x00ce, - 0x9086, 0x0006, 0x1520, 0x61c8, 0x60c4, 0x9105, 0x1500, 0x714c, - 0x9188, 0x0011, 0x2104, 0xd0e4, 0x01d0, 0x6214, 0x9294, 0x1800, - 0x1128, 0x6224, 0x9294, 0x0002, 0x15e0, 0x0010, 0xc0e4, 0x200a, - 0x6014, 0x9084, 0xe7fd, 0x9085, 0x0010, 0x6016, 0x704c, 0x2060, - 0x080c, 0x9a48, 0x2009, 0x0049, 0x080c, 0xb20a, 0x0450, 0x080c, - 0xeeee, 0x704c, 0x9065, 0x9086, 0x1b55, 0x1158, 0x080c, 0xafd2, - 0x1500, 0x2061, 0x1b55, 0x6064, 0x8000, 0x6066, 0x080c, 0x6058, - 0x00c0, 0x0036, 0x2019, 0x0001, 0x080c, 0xa596, 0x003e, 0x714c, - 0x2160, 0x2009, 0x004a, 0x6220, 0x9296, 0x0009, 0x1130, 0x6114, - 0x2148, 0xa87b, 0x0006, 0x2009, 0x004a, 0x6003, 0x0003, 0x080c, - 0xb20a, 0x2001, 0x0387, 0x2003, 0x0200, 0x080c, 0xad18, 0x002e, - 0x001e, 0x00ee, 0x00de, 0x00ce, 0x009e, 0x0005, 0xd1ec, 0x1904, - 0xa37f, 0x0804, 0xa381, 0x0026, 0x00e6, 0x2071, 0x19e8, 0x706c, - 0xd084, 0x01e8, 0xc084, 0x706e, 0x714c, 0x81ff, 0x01c0, 0x2071, - 0x0100, 0x9188, 0x0008, 0x2114, 0x928e, 0x0006, 0x1138, 0x2009, - 0x1984, 0x2011, 0x0012, 0x080c, 0x2ae2, 0x0048, 0x928e, 0x0009, - 0x0db0, 0x2009, 0x1984, 0x2011, 0x0016, 0x080c, 0x2ae2, 0x00ee, - 0x002e, 0x0005, 0x9036, 0x2001, 0x19f2, 0x2004, 0x9005, 0x0128, - 0x9c06, 0x0128, 0x2c30, 0x600c, 0x0cc8, 0x9085, 0x0001, 0x0005, - 0x00f6, 0x2079, 0x19e8, 0x610c, 0x9006, 0x600e, 0x6044, 0xc0fc, - 0x6046, 0x86ff, 0x1140, 0x7824, 0x9c06, 0x1118, 0x7826, 0x782a, - 0x0050, 0x792a, 0x0040, 0x00c6, 0x2660, 0x610e, 0x00ce, 0x7824, - 0x9c06, 0x1108, 0x7e26, 0x080c, 0xa65d, 0x080c, 0xd10c, 0x00fe, - 0x0005, 0x080c, 0x9ef8, 0x7003, 0x1200, 0x7838, 0x7012, 0x783c, - 0x7016, 0x00c6, 0x7820, 0x9086, 0x0004, 0x1148, 0x7810, 0x9005, - 0x0130, 0x00b6, 0x2058, 0xb810, 0xb914, 0x00be, 0x0020, 0x2061, - 0x1800, 0x607c, 0x6180, 0x9084, 0x00ff, 0x700a, 0x710e, 0x00ce, - 0x60c3, 0x002c, 0x0804, 0xa270, 0x080c, 0x9ef8, 0x7003, 0x0f00, - 0x7808, 0xd09c, 0x0128, 0xb810, 0x9084, 0x00ff, 0x700a, 0xb814, - 0x700e, 0x60c3, 0x0008, 0x0804, 0xa270, 0x0156, 0x080c, 0x9f43, - 0x7003, 0x0200, 0x080c, 0x8b10, 0x20a9, 0x0006, 0x2011, 0xffec, - 0x2019, 0xffed, 0x9ef0, 0x0002, 0x2305, 0x2072, 0x8e70, 0x2205, - 0x2072, 0x8e70, 0x9398, 0x0002, 0x9290, 0x0002, 0x1f04, 0xa484, - 0x60c3, 0x001c, 0x015e, 0x0804, 0xa270, 0x0016, 0x0026, 0x080c, - 0x9f1f, 0x080c, 0x9f31, 0x9e80, 0x0004, 0x20e9, 0x0000, 0x20a0, - 0x7814, 0x0096, 0x2048, 0xa800, 0x2048, 0xa860, 0x20e0, 0xa85c, - 0x9080, 0x0021, 0x2098, 0x009e, 0x7808, 0x9088, 0x0002, 0x21a8, - 0x9192, 0x0010, 0x1250, 0x4003, 0x9080, 0x0004, 0x8003, 0x60c2, - 0x080c, 0xa270, 0x002e, 0x001e, 0x0005, 0x20a9, 0x0010, 0x4003, - 0x080c, 0xaadc, 0x20a1, 0x0240, 0x22a8, 0x4003, 0x0c68, 0x080c, - 0x9ef8, 0x7003, 0x6200, 0x7808, 0x700e, 0x60c3, 0x0008, 0x0804, - 0xa270, 0x0016, 0x0026, 0x080c, 0x9ef8, 0x20e9, 0x0000, 0x20a1, - 0x024c, 0x7814, 0x0096, 0x2048, 0xa800, 0x2048, 0xa860, 0x20e0, - 0xa85c, 0x9080, 0x0023, 0x2098, 0x009e, 0x7808, 0x9088, 0x0002, - 0x21a8, 0x4003, 0x8003, 0x60c2, 0x080c, 0xa270, 0x002e, 0x001e, - 0x0005, 0x00e6, 0x00c6, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, - 0x19e8, 0x7010, 0x2060, 0x8cff, 0x0188, 0x080c, 0xd132, 0x1110, - 0x080c, 0xbb5c, 0x600c, 0x0006, 0x080c, 0xd3ae, 0x600f, 0x0000, - 0x080c, 0xb16c, 0x080c, 0xa65d, 0x00ce, 0x0c68, 0x2c00, 0x7012, - 0x700e, 0x012e, 0x000e, 0x00ce, 0x00ee, 0x0005, 0x0126, 0x0156, - 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0026, 0x0016, 0x0006, - 0x2091, 0x8000, 0x2001, 0x180c, 0x200c, 0x918c, 0xe7ff, 0x2102, - 0x2069, 0x0100, 0x2079, 0x0140, 0x2071, 0x19e8, 0x7030, 0x2060, - 0x8cff, 0x0548, 0x080c, 0xa2a0, 0x6ac0, 0x68c3, 0x0000, 0x080c, - 0x8a4b, 0x00c6, 0x2061, 0x0100, 0x080c, 0xac2d, 0x00ce, 0x20a9, - 0x01f4, 0x04b1, 0x080c, 0x99ed, 0x6044, 0xd0ac, 0x1128, 0x2001, - 0x1988, 0x2004, 0x604a, 0x0020, 0x2009, 0x0013, 0x080c, 0xb20a, - 0x000e, 0x001e, 0x002e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, - 0x015e, 0x012e, 0x0005, 0x2001, 0x1800, 0x2004, 0x9096, 0x0001, - 0x0d78, 0x9096, 0x0004, 0x0d60, 0x080c, 0x8a4b, 0x6814, 0x9084, - 0x0001, 0x0110, 0x68a7, 0x95f5, 0x6817, 0x0008, 0x68c3, 0x0000, - 0x2011, 0x6002, 0x080c, 0x8993, 0x20a9, 0x01f4, 0x0009, 0x08c0, - 0x6824, 0xd094, 0x0140, 0x6827, 0x0004, 0x7804, 0x9084, 0x4000, - 0x190c, 0x2aa9, 0x0090, 0xd084, 0x0118, 0x6827, 0x4001, 0x0010, - 0x1f04, 0xa578, 0x7804, 0x9084, 0x1000, 0x0138, 0x2001, 0x0100, - 0x080c, 0x2a99, 0x9006, 0x080c, 0x2a99, 0x0005, 0x0126, 0x0156, - 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0026, 0x0016, 0x0006, - 0x2091, 0x8000, 0x2001, 0x180c, 0x200c, 0x918c, 0xdbff, 0x2102, - 0x2069, 0x0100, 0x2079, 0x0140, 0x2071, 0x0380, 0x701c, 0x0006, - 0x701f, 0x0202, 0x2071, 0x19e8, 0x704c, 0x2060, 0x8cff, 0x0904, - 0xa619, 0x080c, 0xaf84, 0x0904, 0xa619, 0x9386, 0x0002, 0x1128, - 0x6814, 0x9084, 0x0002, 0x0904, 0xa619, 0x68af, 0x95f5, 0x6817, - 0x0010, 0x2009, 0x00fa, 0x8109, 0x1df0, 0x69c6, 0x68cb, 0x0008, - 0x080c, 0x8a58, 0x080c, 0x1e44, 0x2001, 0x0032, 0x6920, 0xd1bc, - 0x0130, 0x8001, 0x1dd8, 0x692c, 0x918d, 0x0008, 0x692e, 0x0016, - 0x2009, 0x0040, 0x080c, 0x2220, 0x001e, 0x20a9, 0x03e8, 0x6824, - 0xd094, 0x0140, 0x6827, 0x0004, 0x7804, 0x9084, 0x4000, 0x190c, - 0x2aa9, 0x0090, 0xd08c, 0x0118, 0x6827, 0x0002, 0x0010, 0x1f04, - 0xa5e7, 0x7804, 0x9084, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, - 0x2a99, 0x9006, 0x080c, 0x2a99, 0x6827, 0x4000, 0x6824, 0x83ff, - 0x1180, 0x2009, 0x0049, 0x6020, 0x9086, 0x0009, 0x0150, 0x080c, - 0x9a48, 0x6044, 0xd0ac, 0x1118, 0x6003, 0x0002, 0x0010, 0x080c, - 0xb20a, 0x000e, 0x2071, 0x0380, 0xd08c, 0x1110, 0x701f, 0x0200, - 0x000e, 0x001e, 0x002e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, - 0x015e, 0x012e, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x2069, - 0x19e8, 0x6a06, 0x012e, 0x00de, 0x0005, 0x00d6, 0x0126, 0x2091, - 0x8000, 0x2069, 0x19e8, 0x6a3e, 0x012e, 0x00de, 0x0005, 0x080c, - 0xa050, 0x7047, 0x1000, 0x0098, 0x080c, 0xa050, 0x7047, 0x4000, - 0x0070, 0x080c, 0xa050, 0x7047, 0x2000, 0x0048, 0x080c, 0xa050, - 0x7047, 0x0400, 0x0020, 0x080c, 0xa050, 0x7047, 0x0200, 0x785c, - 0x7032, 0x60c3, 0x0020, 0x0804, 0xa270, 0x00e6, 0x2071, 0x19e8, - 0x702c, 0x9005, 0x0110, 0x8001, 0x702e, 0x00ee, 0x0005, 0x00f6, - 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066, 0x0006, 0x0126, 0x2091, - 0x8000, 0x2071, 0x19e8, 0x7620, 0x2660, 0x2678, 0x2039, 0x0001, - 0x87ff, 0x0904, 0xa702, 0x8cff, 0x0904, 0xa702, 0x6020, 0x9086, - 0x0006, 0x1904, 0xa6fd, 0x88ff, 0x0138, 0x2800, 0x9c06, 0x1904, - 0xa6fd, 0x2039, 0x0000, 0x0050, 0x6010, 0x9b06, 0x1904, 0xa6fd, - 0x85ff, 0x0120, 0x605c, 0x9106, 0x1904, 0xa6fd, 0x7030, 0x9c06, - 0x15b0, 0x2069, 0x0100, 0x68c0, 0x9005, 0x1160, 0x6824, 0xd084, - 0x0148, 0x6827, 0x0001, 0x080c, 0x8a4b, 0x080c, 0xa78a, 0x7033, - 0x0000, 0x0428, 0x080c, 0x8a4b, 0x6820, 0xd0b4, 0x0110, 0x68a7, - 0x95f5, 0x6817, 0x0008, 0x68c3, 0x0000, 0x080c, 0xa78a, 0x7033, - 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, - 0x2001, 0x0100, 0x080c, 0x2a99, 0x9006, 0x080c, 0x2a99, 0x2069, - 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x7020, - 0x9c36, 0x1110, 0x660c, 0x7622, 0x701c, 0x9c36, 0x1140, 0x2c00, - 0x9f36, 0x0118, 0x2f00, 0x701e, 0x0010, 0x701f, 0x0000, 0x660c, - 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x89ff, - 0x1168, 0x600f, 0x0000, 0x6014, 0x0096, 0x2048, 0x080c, 0xcf19, - 0x0110, 0x080c, 0xea30, 0x009e, 0x080c, 0xb1a7, 0x080c, 0xa65d, - 0x88ff, 0x1190, 0x00ce, 0x0804, 0xa678, 0x2c78, 0x600c, 0x2060, - 0x0804, 0xa678, 0x9006, 0x012e, 0x000e, 0x006e, 0x007e, 0x00ce, - 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601b, 0x0000, 0x00ce, 0x98c5, - 0x0001, 0x0c88, 0x00f6, 0x00e6, 0x00d6, 0x0096, 0x00c6, 0x0066, - 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x19e8, 0x7648, - 0x2660, 0x2678, 0x8cff, 0x0904, 0xa779, 0x6020, 0x9086, 0x0006, - 0x1904, 0xa774, 0x87ff, 0x0128, 0x2700, 0x9c06, 0x1904, 0xa774, - 0x0048, 0x6010, 0x9b06, 0x1904, 0xa774, 0x85ff, 0x0118, 0x605c, - 0x9106, 0x15d0, 0x704c, 0x9c06, 0x1178, 0x0036, 0x2019, 0x0001, - 0x080c, 0xa596, 0x703f, 0x0000, 0x9006, 0x704e, 0x706a, 0x7052, - 0x706e, 0x080c, 0xaff4, 0x003e, 0x7048, 0x9c36, 0x1110, 0x660c, - 0x764a, 0x7044, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, - 0x7046, 0x0010, 0x7047, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, - 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x6014, 0x2048, - 0x080c, 0xcf19, 0x0110, 0x080c, 0xea30, 0x080c, 0xb1a7, 0x87ff, - 0x1198, 0x00ce, 0x0804, 0xa722, 0x2c78, 0x600c, 0x2060, 0x0804, - 0xa722, 0x9006, 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, 0x009e, - 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601b, 0x0000, 0x00ce, 0x97bd, - 0x0001, 0x0c80, 0x00e6, 0x2071, 0x19e8, 0x9006, 0x7032, 0x700a, - 0x7004, 0x9086, 0x0003, 0x0158, 0x2001, 0x1800, 0x2004, 0x9086, - 0x0002, 0x1118, 0x7007, 0x0005, 0x0010, 0x7007, 0x0000, 0x00ee, - 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, - 0x2091, 0x8000, 0x2071, 0x19e8, 0x2c10, 0x7648, 0x2660, 0x2678, - 0x8cff, 0x0540, 0x2200, 0x9c06, 0x1508, 0x7048, 0x9c36, 0x1110, - 0x660c, 0x764a, 0x7044, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, - 0x2f00, 0x7046, 0x0010, 0x7047, 0x0000, 0x660c, 0x2c00, 0x9f06, - 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x6004, 0x9086, - 0x0040, 0x090c, 0x99ed, 0x9085, 0x0001, 0x0020, 0x2c78, 0x600c, - 0x2060, 0x08b0, 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, 0x00ee, - 0x00fe, 0x0005, 0x0096, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, - 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x19e8, 0x7610, - 0x2660, 0x2678, 0x8cff, 0x0904, 0xa877, 0x6010, 0x00b6, 0x2058, - 0xb8a0, 0x00be, 0x9206, 0x1904, 0xa872, 0x7030, 0x9c06, 0x1520, - 0x2069, 0x0100, 0x68c0, 0x9005, 0x0904, 0xa849, 0x080c, 0xa2a0, - 0x68c3, 0x0000, 0x080c, 0xa78a, 0x7033, 0x0000, 0x0036, 0x2069, - 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, - 0x2a99, 0x9006, 0x080c, 0x2a99, 0x2069, 0x0100, 0x6824, 0xd084, - 0x0110, 0x6827, 0x0001, 0x003e, 0x7010, 0x9c36, 0x1110, 0x660c, - 0x7612, 0x700c, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, - 0x700e, 0x0010, 0x700f, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, - 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, 0xd121, - 0x1180, 0x080c, 0x3344, 0x080c, 0xd132, 0x1518, 0x080c, 0xbb5c, - 0x0400, 0x080c, 0xa78a, 0x6824, 0xd084, 0x09b0, 0x6827, 0x0001, - 0x0898, 0x080c, 0xd132, 0x1118, 0x080c, 0xbb5c, 0x0090, 0x6014, - 0x2048, 0x080c, 0xcf19, 0x0168, 0x6020, 0x9086, 0x0003, 0x1508, - 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0x7006, 0x080c, - 0xd10c, 0x080c, 0xd3ae, 0x080c, 0xb1a7, 0x080c, 0xa65d, 0x00ce, - 0x0804, 0xa7f2, 0x2c78, 0x600c, 0x2060, 0x0804, 0xa7f2, 0x012e, - 0x000e, 0x002e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x009e, - 0x0005, 0x6020, 0x9086, 0x0006, 0x1d20, 0x080c, 0xea30, 0x0c08, - 0x00d6, 0x080c, 0x9f43, 0x7003, 0x0200, 0x7007, 0x0014, 0x60c3, - 0x0014, 0x20e1, 0x0001, 0x2099, 0x1989, 0x20e9, 0x0000, 0x20a1, - 0x0250, 0x20a9, 0x0004, 0x4003, 0x7023, 0x0004, 0x7027, 0x7878, - 0x080c, 0xa270, 0x00de, 0x0005, 0x080c, 0x9f43, 0x700b, 0x0800, - 0x7814, 0x9084, 0xff00, 0x700e, 0x7814, 0x9084, 0x00ff, 0x7022, - 0x782c, 0x7026, 0x7860, 0x9084, 0x00ff, 0x9085, 0x0200, 0x7002, - 0x7860, 0x9084, 0xff00, 0x8007, 0x7006, 0x60c2, 0x0804, 0xa270, - 0x00b6, 0x00d6, 0x0016, 0x00d6, 0x2f68, 0x2009, 0x0035, 0x080c, - 0xd5bb, 0x00de, 0x1904, 0xa925, 0x080c, 0x9ef8, 0x7003, 0x1300, - 0x782c, 0x080c, 0xaa34, 0x2068, 0x6820, 0x9086, 0x0003, 0x0560, - 0x7810, 0x2058, 0xbaa0, 0x080c, 0xb094, 0x11d8, 0x9286, 0x007e, - 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffe, 0x0498, 0x9286, 0x007f, - 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffd, 0x0458, 0x9284, 0xff80, - 0x0180, 0x9286, 0x0080, 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffc, - 0x0400, 0x92d8, 0x1000, 0x2b5c, 0xb810, 0x700a, 0xb814, 0x700e, - 0x00c0, 0xb884, 0x700e, 0x00a8, 0x080c, 0xb094, 0x1130, 0x7810, - 0x2058, 0xb8a0, 0x9082, 0x007e, 0x0250, 0x00d6, 0x2069, 0x181f, - 0x2d04, 0x700a, 0x8d68, 0x2d04, 0x700e, 0x00de, 0x0010, 0x6034, - 0x700e, 0x7838, 0x7012, 0x783c, 0x7016, 0x60c3, 0x000c, 0x001e, - 0x00de, 0x080c, 0xa270, 0x00be, 0x0005, 0x781b, 0x0001, 0x7803, - 0x0006, 0x001e, 0x00de, 0x00be, 0x0005, 0x792c, 0x9180, 0x0008, - 0x200c, 0x9186, 0x0006, 0x01c0, 0x9186, 0x0003, 0x0904, 0xa9a4, - 0x9186, 0x0005, 0x0904, 0xa98c, 0x9186, 0x0004, 0x05f0, 0x9186, - 0x0008, 0x0904, 0xa995, 0x7807, 0x0037, 0x782f, 0x0003, 0x7817, - 0x1700, 0x080c, 0xaa11, 0x0005, 0x080c, 0xa9d2, 0x00d6, 0x0026, - 0x792c, 0x2168, 0x2009, 0x4000, 0x6800, 0x6a44, 0xd2fc, 0x11f8, - 0x0002, 0xa96c, 0xa977, 0xa96e, 0xa977, 0xa973, 0xa96c, 0xa96c, - 0xa977, 0xa977, 0xa977, 0xa977, 0xa96c, 0xa96c, 0xa96c, 0xa96c, - 0xa96c, 0xa977, 0xa96c, 0xa977, 0x080c, 0x0d85, 0x6824, 0xd0e4, - 0x0110, 0xd0cc, 0x0110, 0x900e, 0x0010, 0x2009, 0x2000, 0x682c, - 0x7022, 0x6830, 0x7026, 0x0804, 0xa9cb, 0x080c, 0xa9d2, 0x00d6, - 0x0026, 0x792c, 0x2168, 0x2009, 0x4000, 0x6a00, 0x9286, 0x0002, - 0x1108, 0x900e, 0x0804, 0xa9cb, 0x080c, 0xa9d2, 0x00d6, 0x0026, - 0x792c, 0x2168, 0x2009, 0x4000, 0x04b0, 0x04e1, 0x00d6, 0x0026, - 0x792c, 0x2168, 0x2009, 0x4000, 0x9286, 0x0005, 0x0118, 0x9286, - 0x0002, 0x1108, 0x900e, 0x0438, 0x0469, 0x00d6, 0x0026, 0x792c, - 0x2168, 0x6814, 0x6924, 0xc185, 0x6926, 0x0096, 0x2048, 0xa9ac, - 0xa834, 0x9112, 0xa9b0, 0xa838, 0x009e, 0x9103, 0x7022, 0x7226, - 0x792c, 0x9180, 0x0011, 0x2004, 0xd0fc, 0x1148, 0x9180, 0x0000, - 0x2004, 0x908e, 0x0002, 0x0130, 0x908e, 0x0004, 0x0118, 0x2009, - 0x4000, 0x0008, 0x900e, 0x712a, 0x60c3, 0x0018, 0x002e, 0x00de, - 0x0804, 0xa270, 0x00b6, 0x0036, 0x0046, 0x0056, 0x0066, 0x080c, - 0x9f43, 0x9006, 0x7003, 0x0200, 0x7938, 0x710a, 0x793c, 0x710e, - 0x7810, 0x2058, 0xb8a0, 0x080c, 0xb094, 0x1118, 0x9092, 0x007e, - 0x0268, 0x00d6, 0x2069, 0x181f, 0x2d2c, 0x8d68, 0x2d34, 0x90d8, - 0x1000, 0x2b5c, 0xbb10, 0xbc14, 0x00de, 0x0028, 0x901e, 0xbc84, - 0x2029, 0x0000, 0x6634, 0x782c, 0x9080, 0x0008, 0x2004, 0x9086, - 0x0003, 0x1128, 0x7512, 0x7616, 0x731a, 0x741e, 0x0020, 0x7312, - 0x7416, 0x751a, 0x761e, 0x006e, 0x005e, 0x004e, 0x003e, 0x00be, - 0x0005, 0x080c, 0x9f43, 0x7003, 0x0100, 0x782c, 0x700a, 0x7814, - 0x700e, 0x700e, 0x60c3, 0x0008, 0x0804, 0xa270, 0x080c, 0x9eef, - 0x7003, 0x1400, 0x7838, 0x700a, 0x0079, 0x783c, 0x700e, 0x782c, - 0x7012, 0x7830, 0x7016, 0x7834, 0x9084, 0x00ff, 0x8007, 0x701a, - 0x60c3, 0x0010, 0x0804, 0xa270, 0x00e6, 0x2071, 0x0240, 0x0006, - 0x00f6, 0x2078, 0x7810, 0x00b6, 0x2058, 0xb8d4, 0xd084, 0x0120, - 0x784c, 0x702a, 0x7850, 0x702e, 0x00be, 0x00fe, 0x000e, 0x00ee, - 0x0005, 0x080c, 0x9f3a, 0x7003, 0x0100, 0x782c, 0x700a, 0x7814, - 0x700e, 0x60c3, 0x0008, 0x0804, 0xa270, 0x00a9, 0x7914, 0x712a, - 0x60c3, 0x0000, 0x60a7, 0x9575, 0x0026, 0x080c, 0x2a04, 0x0228, - 0x2011, 0x0101, 0x2204, 0xc0c5, 0x2012, 0x002e, 0x080c, 0xa293, - 0x080c, 0x8a42, 0x0005, 0x0036, 0x0096, 0x00d6, 0x00e6, 0x7860, - 0x2048, 0xaa7c, 0x9296, 0x00c0, 0x9294, 0x00fd, 0xaa7e, 0xaa80, - 0x9294, 0x0300, 0xaa82, 0xa96c, 0x9194, 0x00ff, 0xab74, 0x9384, - 0x00ff, 0x908d, 0xc200, 0xa96e, 0x9384, 0xff00, 0x9215, 0xaa76, - 0xa870, 0xaa78, 0xa87a, 0xaa72, 0x00d6, 0x2069, 0x0200, 0x080c, - 0xaaf1, 0x00de, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000a, - 0xa860, 0x20e0, 0xa85c, 0x9080, 0x001b, 0x2098, 0x4003, 0x60a3, - 0x0035, 0xaa68, 0x9294, 0x7000, 0x9286, 0x3000, 0x0110, 0x60a3, - 0x0037, 0x00ee, 0x00de, 0x009e, 0x003e, 0x0005, 0x900e, 0x7814, - 0x0096, 0x2048, 0xa87c, 0xd0fc, 0x01c0, 0x9084, 0x0003, 0x11a8, - 0x2001, 0x180c, 0x2004, 0xd0bc, 0x0180, 0x7824, 0xd0cc, 0x1168, - 0xd0c4, 0x1158, 0xa8a8, 0x9005, 0x1140, 0x2001, 0x180c, 0x200c, - 0xc1d5, 0x2102, 0x2009, 0x19b3, 0x210c, 0x009e, 0x918d, 0x0092, - 0x0010, 0x2009, 0x0096, 0x60ab, 0x0036, 0x0026, 0x2110, 0x900e, - 0x080c, 0x2ae2, 0x002e, 0x0005, 0x2009, 0x0009, 0x00a0, 0x2009, - 0x000a, 0x0088, 0x2009, 0x000b, 0x0070, 0x2009, 0x000c, 0x0058, - 0x2009, 0x000d, 0x0040, 0x2009, 0x000e, 0x0028, 0x2009, 0x000f, - 0x0010, 0x2009, 0x0008, 0x6912, 0x0005, 0x080c, 0x9ef8, 0x0016, - 0x0026, 0x0096, 0x00d6, 0x7814, 0x2048, 0x7013, 0x0138, 0x2001, - 0x1837, 0x2004, 0x9084, 0x0028, 0x1138, 0x2001, 0x197c, 0x2004, - 0x9086, 0xaaaa, 0x1904, 0xab96, 0x7003, 0x5400, 0x00c6, 0x2061, - 0x1800, 0x607c, 0x9084, 0x00ff, 0xa998, 0x810f, 0x918c, 0xff00, - 0x9105, 0x700a, 0x6080, 0x700e, 0xa998, 0x918c, 0xff00, 0x7112, - 0x20a9, 0x0004, 0x2009, 0x1805, 0x2e10, 0x9290, 0x0006, 0x2104, - 0x2012, 0x8108, 0x8210, 0x1f04, 0xab27, 0x20a9, 0x0004, 0x2009, - 0x1801, 0x2104, 0x2012, 0x8108, 0x8210, 0x1f04, 0xab31, 0xa860, - 0x20e0, 0xa85c, 0x9080, 0x0029, 0x2098, 0x2009, 0x0006, 0x20a9, - 0x0001, 0x4002, 0x8007, 0x2012, 0x8210, 0x8109, 0x1dc0, 0x00d6, - 0x2069, 0x0200, 0x080c, 0xaadc, 0x00de, 0x2071, 0x0240, 0x2011, - 0x0240, 0x2009, 0x0002, 0x20a9, 0x0001, 0x4002, 0x8007, 0x2012, - 0x8210, 0x8109, 0x1dc0, 0x2009, 0x0008, 0x20a9, 0x0001, 0x4002, - 0x8007, 0x2012, 0x8210, 0x8109, 0x1dc0, 0xa85c, 0x9080, 0x0031, - 0x2098, 0x2009, 0x0008, 0x20a9, 0x0001, 0x4002, 0x8007, 0x2012, - 0x8210, 0x8109, 0x1dc0, 0x00ce, 0x60c3, 0x004c, 0x60a3, 0x0056, - 0x60a7, 0x9575, 0x2001, 0x1837, 0x2004, 0x9084, 0x0028, 0x1168, - 0x080c, 0x779e, 0x0150, 0x6028, 0xc0bd, 0x602a, 0x2009, 0x1804, - 0x2011, 0x0029, 0x080c, 0x2ae2, 0x0010, 0x080c, 0xa270, 0x080c, - 0x8a42, 0x00de, 0x009e, 0x002e, 0x001e, 0x0005, 0x00e6, 0x2071, - 0x0240, 0x2001, 0x2200, 0x9085, 0x00ff, 0x7002, 0x7007, 0xffff, - 0x2071, 0x0100, 0x709b, 0x00ff, 0x00ee, 0x0804, 0xab0c, 0x080c, - 0x9ef8, 0x0016, 0x0026, 0x0096, 0x00d6, 0x7814, 0x2048, 0x7013, - 0x0138, 0x7003, 0x5500, 0x00c6, 0xa89c, 0x9084, 0x00ff, 0xa998, - 0x810f, 0x918c, 0xff00, 0x9105, 0x700a, 0xa99c, 0x918c, 0xff00, - 0xa8a0, 0x9084, 0x00ff, 0x9105, 0x700e, 0xa998, 0x918c, 0xff00, - 0x2061, 0x1800, 0x607c, 0x9084, 0x00ff, 0x910d, 0x7112, 0x6180, - 0x7116, 0x2009, 0x0008, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x0029, - 0x2098, 0x2e10, 0x9290, 0x0006, 0x20a9, 0x0001, 0x4002, 0x8007, - 0x2012, 0x8210, 0x8109, 0x1dc0, 0x20a9, 0x0004, 0x2009, 0x1805, - 0x2104, 0x2012, 0x8108, 0x8210, 0x1f04, 0xabe8, 0x20a9, 0x0002, - 0x2009, 0x1801, 0x2104, 0x2012, 0x8108, 0x8210, 0x1f04, 0xabf2, - 0x00d6, 0x0016, 0x2069, 0x0200, 0x080c, 0xaadc, 0x001e, 0x00de, - 0x2071, 0x0240, 0x20a9, 0x0002, 0x2009, 0x1803, 0x2011, 0x0240, - 0x2104, 0x2012, 0x8108, 0x8210, 0x1f04, 0xac08, 0x2009, 0x0008, - 0x4002, 0x8007, 0x2012, 0x8210, 0x8109, 0x1dd0, 0x9006, 0x20a9, - 0x0008, 0x2012, 0x8210, 0x1f04, 0xac19, 0x00ce, 0x60c3, 0x004c, - 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, 0xa270, 0x080c, 0x8a42, - 0x00de, 0x009e, 0x002e, 0x001e, 0x0005, 0x00d6, 0x9290, 0x0018, - 0x8214, 0x20e9, 0x0000, 0x2069, 0x0200, 0x6813, 0x0000, 0x22a8, - 0x9284, 0x00e0, 0x0128, 0x20a9, 0x0020, 0x9292, 0x0020, 0x0008, - 0x9016, 0x20a1, 0x0240, 0x9006, 0x4004, 0x82ff, 0x0120, 0x6810, - 0x8000, 0x6812, 0x0c60, 0x00de, 0x0005, 0x00f6, 0x00e6, 0x00d6, - 0x00c6, 0x00a6, 0x0096, 0x0066, 0x0126, 0x2091, 0x8000, 0x2071, - 0x19e8, 0x7610, 0x2660, 0x2678, 0x8cff, 0x0904, 0xacd9, 0x7030, - 0x9c06, 0x1520, 0x2069, 0x0100, 0x68c0, 0x9005, 0x0904, 0xacab, - 0x080c, 0xa2a0, 0x68c3, 0x0000, 0x080c, 0xa78a, 0x7033, 0x0000, - 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, - 0x0100, 0x080c, 0x2a99, 0x9006, 0x080c, 0x2a99, 0x2069, 0x0100, - 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x7010, 0x9c36, - 0x1110, 0x660c, 0x7612, 0x700c, 0x9c36, 0x1140, 0x2c00, 0x9f36, - 0x0118, 0x2f00, 0x700e, 0x0010, 0x700f, 0x0000, 0x660c, 0x0066, - 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, - 0x080c, 0xd121, 0x1180, 0x080c, 0x3344, 0x080c, 0xd132, 0x1518, - 0x080c, 0xbb5c, 0x0400, 0x080c, 0xa78a, 0x6824, 0xd084, 0x09b0, - 0x6827, 0x0001, 0x0898, 0x080c, 0xd132, 0x1118, 0x080c, 0xbb5c, - 0x0090, 0x6014, 0x2048, 0x080c, 0xcf19, 0x0168, 0x6020, 0x9086, - 0x0003, 0x1520, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, - 0x7012, 0x080c, 0xd10c, 0x080c, 0xd3ae, 0x080c, 0xb1a7, 0x080c, - 0xa65d, 0x00ce, 0x0804, 0xac5c, 0x2c78, 0x600c, 0x2060, 0x0804, - 0xac5c, 0x7013, 0x0000, 0x700f, 0x0000, 0x012e, 0x006e, 0x009e, - 0x00ae, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x6020, 0x9086, - 0x0006, 0x1d08, 0x080c, 0xea30, 0x08f0, 0x00f6, 0x0036, 0x2079, - 0x0380, 0x7b18, 0xd3bc, 0x1de8, 0x7832, 0x7936, 0x7a3a, 0x781b, - 0x8080, 0x003e, 0x00fe, 0x0005, 0x0016, 0x2001, 0x0382, 0x2004, - 0x9084, 0x0007, 0x9086, 0x0001, 0x1188, 0x2001, 0x0015, 0x0c29, - 0x2009, 0x1000, 0x2001, 0x0382, 0x2004, 0x9084, 0x0007, 0x9086, - 0x0003, 0x0120, 0x8109, 0x1db0, 0x080c, 0x0d85, 0x001e, 0x0005, - 0x2001, 0x0382, 0x2004, 0x9084, 0x0007, 0x9086, 0x0003, 0x1120, - 0x2001, 0x0380, 0x2003, 0x0001, 0x0005, 0x0156, 0x0016, 0x0026, - 0x00e6, 0x900e, 0x2071, 0x19e8, 0x0469, 0x0106, 0x0190, 0x7004, - 0x9086, 0x0003, 0x0148, 0x20a9, 0x1000, 0x6044, 0xd0fc, 0x01d8, - 0x1f04, 0xad35, 0x080c, 0x0d85, 0x080c, 0xacfc, 0x6044, 0xd0fc, - 0x0190, 0x7030, 0x9c06, 0x1148, 0x080c, 0x99ed, 0x6044, 0xd0dc, - 0x0150, 0xc0dc, 0x6046, 0x700a, 0x7042, 0x704c, 0x9c06, 0x190c, - 0x0d85, 0x080c, 0x9a48, 0x010e, 0x1919, 0x00ee, 0x002e, 0x001e, - 0x015e, 0x0005, 0x2001, 0x0382, 0x2004, 0x9084, 0x0007, 0x9086, - 0x0003, 0x0005, 0x0126, 0x2091, 0x2400, 0x7808, 0xd0a4, 0x190c, - 0x0d7e, 0xd09c, 0x0128, 0x7820, 0x908c, 0xf000, 0x11b8, 0x0012, - 0x012e, 0x0005, 0xad82, 0xadc0, 0xadef, 0xae37, 0xae47, 0xae58, - 0xae67, 0xae75, 0xaea2, 0xaea6, 0xad82, 0xad82, 0xaea9, 0xaec5, - 0xad82, 0xad82, 0x080c, 0x0d85, 0x012e, 0x0005, 0x2060, 0x6044, - 0xd0bc, 0x0140, 0xc0bc, 0x6046, 0x6000, 0x908a, 0x0010, 0x1a0c, - 0x0d85, 0x0012, 0x012e, 0x0005, 0xada7, 0xada9, 0xada7, 0xadaf, - 0xada7, 0xada7, 0xada7, 0xada7, 0xada7, 0xada9, 0xada7, 0xada9, - 0xada7, 0xada9, 0xada7, 0xada7, 0xada7, 0xada9, 0xada7, 0x080c, - 0x0d85, 0x2009, 0x0013, 0x080c, 0xb20a, 0x012e, 0x0005, 0x6014, - 0x2048, 0xa87c, 0xd0dc, 0x0130, 0x080c, 0x8c19, 0x080c, 0xb16c, - 0x012e, 0x0005, 0x2009, 0x0049, 0x080c, 0xb20a, 0x012e, 0x0005, - 0x080c, 0xacfc, 0x2001, 0x1a0d, 0x2003, 0x0000, 0x7030, 0x9065, - 0x1130, 0x7004, 0x9086, 0x0003, 0x01e0, 0x080c, 0x0d85, 0x7034, - 0x9092, 0xc350, 0x1258, 0x8000, 0x7036, 0x7004, 0x9086, 0x0003, - 0x0110, 0x7007, 0x0000, 0x781f, 0x0808, 0x0058, 0x080c, 0xb0c0, - 0x0140, 0x080c, 0xeeee, 0x6003, 0x0001, 0x2009, 0x0014, 0x080c, - 0xb20a, 0x781f, 0x0100, 0x080c, 0xad18, 0x012e, 0x0005, 0x080c, - 0xacfc, 0x714c, 0x81ff, 0x1128, 0x2011, 0x1a10, 0x2013, 0x0000, - 0x04c0, 0x2061, 0x0100, 0x7150, 0x9192, 0x7530, 0x1678, 0x8108, - 0x7152, 0x714c, 0x9186, 0x1b55, 0x0120, 0x2001, 0x0391, 0x2003, - 0x0400, 0x9188, 0x0008, 0x210c, 0x918e, 0x0006, 0x1160, 0x6014, - 0x9084, 0x1984, 0x9085, 0x0012, 0x714c, 0x918e, 0x1b55, 0x1108, - 0xc0fd, 0x6016, 0x00b0, 0x714c, 0x9188, 0x0008, 0x210c, 0x918e, - 0x0009, 0x0d68, 0x6014, 0x9084, 0x1984, 0x9085, 0x0016, 0x714c, - 0x918e, 0x1b55, 0x1108, 0xc0fd, 0x6016, 0x0018, 0x706c, 0xc085, - 0x706e, 0x781f, 0x0200, 0x080c, 0xad18, 0x012e, 0x0005, 0x080c, - 0xacfc, 0x714c, 0x2160, 0x6003, 0x0003, 0x2009, 0x004a, 0x080c, - 0xb20a, 0x781f, 0x0200, 0x080c, 0xad18, 0x012e, 0x0005, 0x7808, - 0xd09c, 0x0de8, 0x7820, 0x2060, 0x6003, 0x0003, 0x080c, 0xacfc, - 0x080c, 0x1dcc, 0x781f, 0x0400, 0x080c, 0xad18, 0x012e, 0x0005, - 0x7808, 0xd09c, 0x0de8, 0x7820, 0x2060, 0x080c, 0xacfc, 0x080c, - 0x1e14, 0x781f, 0x0400, 0x080c, 0xad18, 0x012e, 0x0005, 0x7030, - 0x9065, 0x0148, 0x6044, 0xc0bc, 0x6046, 0x7104, 0x9186, 0x0003, - 0x0110, 0x080c, 0x9ab4, 0x012e, 0x0005, 0x00f6, 0x703c, 0x9086, - 0x0002, 0x0528, 0x704c, 0x907d, 0x0510, 0x7844, 0xc0bc, 0x7846, - 0x7820, 0x9086, 0x0009, 0x0118, 0x080c, 0xa1ca, 0x00c0, 0x7828, - 0xd0fc, 0x1118, 0x080c, 0xa149, 0x0090, 0x2001, 0x1837, 0x2004, - 0x9084, 0x0028, 0x1130, 0x2001, 0x197c, 0x2004, 0x9086, 0xaaaa, - 0x1120, 0x2001, 0x0387, 0x2003, 0x1000, 0x080c, 0xa0ce, 0x00fe, - 0x012e, 0x0005, 0x080c, 0x7840, 0x012e, 0x0005, 0x080c, 0x0d85, - 0x0005, 0x2009, 0x1b66, 0x2104, 0xd0bc, 0x01a8, 0xc0bc, 0x200a, - 0x2009, 0x010b, 0x2104, 0x9085, 0x0002, 0x200a, 0x2009, 0x0101, - 0x2104, 0xc0ac, 0x200a, 0x2009, 0x0105, 0x2104, 0x9084, 0x1984, - 0x9085, 0x8092, 0x200a, 0x012e, 0x0005, 0x080c, 0x8a58, 0x2009, - 0x010b, 0x2104, 0xd08c, 0x01a8, 0xc08c, 0x200a, 0x2001, 0x1848, - 0x2004, 0xd094, 0x1130, 0x2009, 0x0101, 0x2104, 0x9085, 0x0020, - 0x200a, 0x2009, 0x1b66, 0x200b, 0x0000, 0x2001, 0x001b, 0x080c, - 0xaced, 0x012e, 0x0005, 0x00e6, 0x2071, 0x19e8, 0x6044, 0xc0bc, - 0x6046, 0xd0fc, 0x01b8, 0x704c, 0x9c06, 0x1190, 0x2019, 0x0001, - 0x080c, 0xa596, 0x704f, 0x0000, 0x2001, 0x0109, 0x2004, 0xd08c, - 0x1138, 0x2001, 0x0108, 0x2004, 0xd0bc, 0x1110, 0x703f, 0x0000, - 0x080c, 0xa7a1, 0x00ee, 0x0005, 0x0026, 0x7010, 0x9c06, 0x1178, - 0x080c, 0xa65d, 0x6044, 0xc0fc, 0x6046, 0x600c, 0x9015, 0x0120, - 0x7212, 0x600f, 0x0000, 0x0010, 0x7212, 0x720e, 0x9006, 0x002e, - 0x0005, 0x0026, 0x7020, 0x9c06, 0x1178, 0x080c, 0xa65d, 0x6044, - 0xc0fc, 0x6046, 0x600c, 0x9015, 0x0120, 0x7222, 0x600f, 0x0000, - 0x0010, 0x7222, 0x721e, 0x9006, 0x002e, 0x0005, 0x00d6, 0x0036, - 0x7830, 0x9c06, 0x1558, 0x2069, 0x0100, 0x68c0, 0x9005, 0x01f8, - 0x080c, 0x8a4b, 0x080c, 0xa2a0, 0x68c3, 0x0000, 0x080c, 0xa78a, - 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, - 0x080c, 0x2a99, 0x9006, 0x080c, 0x2a99, 0x2069, 0x0100, 0x6824, - 0xd084, 0x0110, 0x6827, 0x0001, 0x9085, 0x0001, 0x0038, 0x7808, - 0xc0ad, 0x780a, 0x6003, 0x0009, 0x630a, 0x9006, 0x003e, 0x00de, - 0x0005, 0x0016, 0x0026, 0x0036, 0x6100, 0x2019, 0x0100, 0x2001, - 0x0382, 0x2004, 0xd09c, 0x0190, 0x00c6, 0x0126, 0x2091, 0x2800, - 0x0016, 0x0036, 0x080c, 0xad62, 0x003e, 0x001e, 0x012e, 0x00ce, - 0x6200, 0x2200, 0x9106, 0x0d58, 0x2200, 0x0010, 0x8319, 0x1d38, - 0x003e, 0x002e, 0x001e, 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x080c, - 0xacfc, 0x0106, 0x2071, 0x19e8, 0x2069, 0x0100, 0x704c, 0x2060, - 0x9086, 0x1b55, 0x15b8, 0x6814, 0xd08c, 0x0188, 0x6817, 0x0010, - 0x2009, 0x0019, 0x8109, 0x1df0, 0x2001, 0x0032, 0x6920, 0xd1bc, - 0x0130, 0x8001, 0x1dd8, 0x692c, 0x918d, 0x0008, 0x692e, 0x6824, - 0xd08c, 0x0110, 0x6827, 0x0002, 0x68d0, 0x9005, 0x0118, 0x9082, - 0x0005, 0x0238, 0x6060, 0x8000, 0x6062, 0x2001, 0x0391, 0x2003, - 0x0400, 0x080c, 0x9a48, 0x682c, 0x9084, 0xfffd, 0x682e, 0x2001, - 0x1848, 0x2004, 0xd094, 0x1120, 0x6804, 0x9085, 0x0020, 0x6806, - 0x2069, 0x0000, 0x010e, 0x090c, 0xad18, 0x8dff, 0x00ce, 0x00de, - 0x00ee, 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x080c, 0xacfc, 0x0106, - 0x2071, 0x19e8, 0x2069, 0x0100, 0x080c, 0xaf84, 0x68d0, 0x9005, - 0x0158, 0x9082, 0x0005, 0x1240, 0x080c, 0x2b33, 0x2001, 0x0391, - 0x2003, 0x0400, 0x2069, 0x0000, 0x010e, 0x090c, 0xad18, 0x8dff, - 0x00ce, 0x00de, 0x00ee, 0x0005, 0x0016, 0x2001, 0x0134, 0x2004, - 0x9005, 0x0140, 0x9082, 0x0005, 0x1228, 0x2001, 0x0391, 0x2003, - 0x0404, 0x0020, 0x2001, 0x0391, 0x2003, 0x0400, 0x001e, 0x0005, - 0x00d6, 0x0156, 0x080c, 0x9f43, 0x7a14, 0x82ff, 0x0138, 0x7003, - 0x0100, 0x700b, 0x0003, 0x60c3, 0x0008, 0x0490, 0x7003, 0x0200, - 0x7007, 0x0000, 0x2069, 0x1800, 0x901e, 0x6800, 0x9086, 0x0004, - 0x1110, 0xc38d, 0x0060, 0x080c, 0x779e, 0x1110, 0xc3ad, 0x0008, - 0xc3a5, 0x6adc, 0xd29c, 0x1110, 0xd2ac, 0x0108, 0xc39d, 0x730e, - 0x080c, 0x8b10, 0x20a9, 0x0006, 0x2011, 0xffec, 0x2019, 0xffed, - 0x2071, 0x0250, 0x2305, 0x2072, 0x8e70, 0x2205, 0x2072, 0x8e70, - 0x9398, 0x0002, 0x9290, 0x0002, 0x1f04, 0xb03a, 0x60c3, 0x0020, - 0x080c, 0xa270, 0x015e, 0x00de, 0x0005, 0x0156, 0x080c, 0x9f43, - 0x7a14, 0x82ff, 0x0168, 0x9286, 0xffff, 0x0118, 0x9282, 0x000e, - 0x1238, 0x7003, 0x0100, 0x700b, 0x0003, 0x60c3, 0x0008, 0x0488, - 0x7003, 0x0200, 0x7007, 0x001c, 0x700f, 0x0001, 0x2011, 0x19be, - 0x2204, 0x8007, 0x701a, 0x8210, 0x2204, 0x8007, 0x701e, 0x0421, - 0x1120, 0xb8a0, 0x9082, 0x007f, 0x0248, 0x2001, 0x181f, 0x2004, - 0x7022, 0x2001, 0x1820, 0x2004, 0x7026, 0x0030, 0x2001, 0x1818, - 0x2004, 0x9084, 0x00ff, 0x7026, 0x20a9, 0x0004, 0x20e1, 0x0001, - 0x2099, 0x1805, 0x20e9, 0x0000, 0x20a1, 0x0256, 0x4003, 0x60c3, - 0x001c, 0x015e, 0x0804, 0xa270, 0x0006, 0x2001, 0x1837, 0x2004, - 0xd0ac, 0x000e, 0x0005, 0x2011, 0x0003, 0x080c, 0xa62b, 0x2011, - 0x0002, 0x080c, 0xa635, 0x080c, 0xa516, 0x0036, 0x901e, 0x080c, - 0xa596, 0x003e, 0x0005, 0x080c, 0x3487, 0x0188, 0x0016, 0x00b6, - 0x00c6, 0x7010, 0x9085, 0x0020, 0x7012, 0x2009, 0x007e, 0x080c, - 0x67b4, 0xb85c, 0xc0ac, 0xb85e, 0x00ce, 0x00be, 0x001e, 0x0005, - 0x00d6, 0x00f6, 0x7104, 0x9186, 0x0004, 0x1130, 0x7410, 0x9e90, - 0x0004, 0x9e98, 0x0003, 0x0088, 0x9186, 0x0001, 0x1130, 0x7420, - 0x9e90, 0x0008, 0x9e98, 0x0007, 0x0040, 0x9186, 0x0002, 0x1538, - 0x7428, 0x9e90, 0x000a, 0x9e98, 0x0009, 0x6110, 0x2468, 0x680c, - 0x907d, 0x01e8, 0x7810, 0x9106, 0x1128, 0x2f68, 0x780c, 0x907d, - 0x1dc8, 0x00a8, 0x780c, 0x680e, 0x7c0e, 0x2f12, 0x2304, 0x9f06, - 0x1108, 0x2d1a, 0x9006, 0x7032, 0x7036, 0x7004, 0x9086, 0x0003, - 0x0110, 0x7007, 0x0000, 0x9006, 0x00fe, 0x00de, 0x0005, 0x9085, - 0x0001, 0x0cd0, 0x2071, 0x188d, 0x7000, 0x9005, 0x0140, 0x2001, - 0x0812, 0x2071, 0x1800, 0x7076, 0x707a, 0x706b, 0xffd4, 0x2071, - 0x1800, 0x7074, 0x7056, 0x705b, 0x1ddc, 0x0005, 0x00e6, 0x0126, - 0x2071, 0x1800, 0x2091, 0x8000, 0x7554, 0x9582, 0x0010, 0x0608, - 0x7058, 0x2060, 0x6000, 0x9086, 0x0000, 0x0148, 0x9ce0, 0x001c, - 0x7068, 0x9c02, 0x1208, 0x0cb0, 0x2061, 0x1ddc, 0x0c98, 0x6003, - 0x0008, 0x8529, 0x7556, 0x9ca8, 0x001c, 0x7068, 0x9502, 0x1230, - 0x755a, 0x9085, 0x0001, 0x012e, 0x00ee, 0x0005, 0x705b, 0x1ddc, - 0x0cc0, 0x9006, 0x0cc0, 0x00e6, 0x2071, 0x1800, 0x7554, 0x9582, - 0x0010, 0x0600, 0x7058, 0x2060, 0x6000, 0x9086, 0x0000, 0x0148, - 0x9ce0, 0x001c, 0x7068, 0x9c02, 0x1208, 0x0cb0, 0x2061, 0x1ddc, - 0x0c98, 0x6003, 0x0008, 0x8529, 0x7556, 0x9ca8, 0x001c, 0x7068, - 0x9502, 0x1228, 0x755a, 0x9085, 0x0001, 0x00ee, 0x0005, 0x705b, - 0x1ddc, 0x0cc8, 0x9006, 0x0cc8, 0x9c82, 0x1ddc, 0x0a0c, 0x0d85, - 0x2001, 0x181a, 0x2004, 0x9c02, 0x1a0c, 0x0d85, 0x9006, 0x6006, - 0x600a, 0x600e, 0x6016, 0x601a, 0x6012, 0x6023, 0x0000, 0x6003, - 0x0000, 0x601e, 0x605e, 0x6062, 0x6026, 0x602a, 0x602e, 0x6032, - 0x6036, 0x603a, 0x603e, 0x604a, 0x602a, 0x6046, 0x6042, 0x2061, - 0x1800, 0x6054, 0x8000, 0x6056, 0x0005, 0x9006, 0x600e, 0x6016, - 0x601a, 0x6012, 0x6022, 0x6002, 0x601e, 0x605e, 0x6062, 0x604a, - 0x6046, 0x2061, 0x1800, 0x6054, 0x8000, 0x6056, 0x0005, 0x0006, - 0x6000, 0x9086, 0x0000, 0x01d8, 0x601c, 0xd084, 0x190c, 0x1ad3, - 0x6023, 0x0007, 0x2001, 0x1986, 0x2004, 0x0006, 0x9082, 0x0051, - 0x000e, 0x0208, 0x8004, 0x601a, 0x080c, 0xece1, 0x604b, 0x0000, - 0x6044, 0xd0fc, 0x1131, 0x9006, 0x6046, 0x6016, 0x6012, 0x000e, - 0x0005, 0x080c, 0xacfc, 0x0106, 0x2001, 0x19fb, 0x2004, 0x9c06, - 0x1130, 0x0036, 0x2019, 0x0001, 0x080c, 0xa596, 0x003e, 0x080c, - 0xa7a1, 0x010e, 0x090c, 0xad18, 0x0005, 0x00e6, 0x0126, 0x2071, - 0x1800, 0x2091, 0x8000, 0x7554, 0x9582, 0x0001, 0x0608, 0x7058, - 0x2060, 0x6000, 0x9086, 0x0000, 0x0148, 0x9ce0, 0x001c, 0x7068, - 0x9c02, 0x1208, 0x0cb0, 0x2061, 0x1ddc, 0x0c98, 0x6003, 0x0008, - 0x8529, 0x7556, 0x9ca8, 0x001c, 0x7068, 0x9502, 0x1230, 0x755a, - 0x9085, 0x0001, 0x012e, 0x00ee, 0x0005, 0x705b, 0x1ddc, 0x0cc0, - 0x9006, 0x0cc0, 0x6020, 0x9084, 0x000f, 0x0002, 0xb21e, 0xb228, - 0xb243, 0xb25e, 0xd69a, 0xd6b7, 0xd6d2, 0xb21e, 0xb228, 0x92f7, - 0xb277, 0xb21e, 0xb21e, 0xb21e, 0xb21e, 0xb21e, 0x9186, 0x0013, - 0x1130, 0x6044, 0xd0fc, 0x0110, 0x080c, 0x99ed, 0x0005, 0x0005, - 0x0066, 0x6000, 0x90b2, 0x0010, 0x1a0c, 0x0d85, 0x0013, 0x006e, - 0x0005, 0xb241, 0xb9bc, 0xbba3, 0xb241, 0xbc39, 0xb540, 0xb241, - 0xb241, 0xb93e, 0xc25a, 0xb241, 0xb241, 0xb241, 0xb241, 0xb241, - 0xb241, 0x080c, 0x0d85, 0x0066, 0x6000, 0x90b2, 0x0010, 0x1a0c, - 0x0d85, 0x0013, 0x006e, 0x0005, 0xb25c, 0xc875, 0xb25c, 0xb25c, - 0xb25c, 0xb25c, 0xb25c, 0xb25c, 0xc80c, 0xc9f8, 0xb25c, 0xc8b2, - 0xc936, 0xc8b2, 0xc936, 0xb25c, 0x080c, 0x0d85, 0x6000, 0x9082, - 0x0010, 0x1a0c, 0x0d85, 0x6000, 0x0002, 0xb275, 0xc2a4, 0xc33e, - 0xc4c1, 0xc530, 0xb275, 0xb275, 0xb275, 0xc273, 0xc78d, 0xc790, - 0xb275, 0xb275, 0xb275, 0xb275, 0xc7c0, 0x080c, 0x0d85, 0x0066, - 0x6000, 0x90b2, 0x0010, 0x1a0c, 0x0d85, 0x0013, 0x006e, 0x0005, - 0xb290, 0xb290, 0xb2ce, 0xb36d, 0xb3ed, 0xb290, 0xb290, 0xb290, - 0xb292, 0xb290, 0xb290, 0xb290, 0xb290, 0xb290, 0xb290, 0xb290, - 0x080c, 0x0d85, 0x9186, 0x004c, 0x0560, 0x9186, 0x0003, 0x190c, - 0x0d85, 0x0096, 0x601c, 0xc0ed, 0x601e, 0x6003, 0x0003, 0x6106, - 0x6014, 0x2048, 0xa87c, 0x9084, 0xa000, 0xc0b5, 0xa87e, 0xa8ac, - 0xa836, 0xa8b0, 0xa83a, 0x9006, 0xa846, 0xa84a, 0xa884, 0x9092, - 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, 0x8013, 0x8213, 0x9210, - 0x621a, 0x009e, 0x080c, 0x1c26, 0x2009, 0x8030, 0x080c, 0x965e, - 0x0005, 0x6010, 0x00b6, 0x2058, 0xbca0, 0x00be, 0x2c00, 0x080c, - 0xb40f, 0x080c, 0xd65d, 0x6003, 0x0007, 0x0005, 0x00d6, 0x0096, - 0x00f6, 0x2079, 0x1800, 0x7a90, 0x6014, 0x2048, 0xa87c, 0xd0ec, - 0x1110, 0x9290, 0x0018, 0xac78, 0xc4fc, 0x0046, 0xa8e0, 0x9005, - 0x1140, 0xa8dc, 0x921a, 0x0140, 0x0220, 0xa87b, 0x0007, 0x2010, - 0x0028, 0xa87b, 0x0015, 0x0010, 0xa87b, 0x0000, 0x8214, 0xa883, - 0x0000, 0xaa02, 0x0006, 0x0016, 0x0026, 0x00c6, 0x00d6, 0x00e6, - 0x00f6, 0x2400, 0x9005, 0x1108, 0x009a, 0x2100, 0x9086, 0x0015, - 0x1118, 0x2001, 0x0001, 0x0038, 0x2100, 0x9086, 0x0016, 0x0118, - 0x2001, 0x0001, 0x002a, 0x94a4, 0x0007, 0x8423, 0x9405, 0x0002, - 0xb335, 0xb335, 0xb330, 0xb333, 0xb335, 0xb32d, 0xb320, 0xb320, - 0xb320, 0xb320, 0xb320, 0xb320, 0xb320, 0xb320, 0xb320, 0xb320, - 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x002e, 0x001e, 0x000e, 0x004e, - 0x00fe, 0x009e, 0x00de, 0x080c, 0x0d85, 0x080c, 0xbe51, 0x0028, - 0x080c, 0xbf8f, 0x0010, 0x080c, 0xc085, 0x00fe, 0x00ee, 0x00de, - 0x00ce, 0x002e, 0x001e, 0x2c00, 0xa896, 0x000e, 0x080c, 0xb4cd, - 0x0530, 0xa804, 0xa80e, 0x00a6, 0x2050, 0xb100, 0x00ae, 0x8006, - 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, - 0xaacc, 0xabd0, 0xacd4, 0xadd8, 0x2031, 0x0000, 0x2041, 0x12c2, - 0x080c, 0xb691, 0x0160, 0x000e, 0x9005, 0x0120, 0x00fe, 0x009e, - 0x00de, 0x0005, 0x00fe, 0x009e, 0x00de, 0x0804, 0xb16c, 0x2001, - 0x002c, 0x900e, 0x080c, 0xb533, 0x0c70, 0x91b6, 0x0015, 0x0170, - 0x91b6, 0x0016, 0x0158, 0x91b2, 0x0047, 0x0a0c, 0x0d85, 0x91b2, - 0x0050, 0x1a0c, 0x0d85, 0x9182, 0x0047, 0x0042, 0x080c, 0xaf61, - 0x0120, 0x9086, 0x0002, 0x0904, 0xb2ce, 0x0005, 0xb38f, 0xb38f, - 0xb391, 0xb3c3, 0xb38f, 0xb38f, 0xb38f, 0xb38f, 0xb3d6, 0x080c, - 0x0d85, 0x00d6, 0x0016, 0x0096, 0x6003, 0x0004, 0x6114, 0x2148, - 0xa87c, 0xd0fc, 0x01c0, 0xa878, 0xc0fc, 0x9005, 0x1158, 0xa894, - 0x9005, 0x0140, 0x2001, 0x0000, 0x900e, 0x080c, 0xb533, 0x080c, - 0xb16c, 0x00a8, 0x6003, 0x0002, 0xa8a4, 0xa9a8, 0x9105, 0x1178, - 0xa8ae, 0xa8b2, 0x0c78, 0xa87f, 0x0020, 0xa88c, 0xa88a, 0xa8a4, - 0xa8ae, 0xa8a8, 0xa8b2, 0xa8c7, 0x0000, 0xa8cb, 0x0000, 0x009e, - 0x001e, 0x00de, 0x0005, 0x080c, 0x9a48, 0x00d6, 0x0096, 0x6114, - 0x2148, 0x080c, 0xcf1b, 0x0120, 0xa87b, 0x0006, 0x080c, 0x7012, - 0x009e, 0x00de, 0x080c, 0xb16c, 0x0804, 0x9ab3, 0x080c, 0x9a48, - 0x080c, 0x3315, 0x080c, 0xd65a, 0x00d6, 0x0096, 0x6114, 0x2148, - 0x080c, 0xcf1b, 0x0120, 0xa87b, 0x0029, 0x080c, 0x7012, 0x009e, - 0x00de, 0x080c, 0xb16c, 0x0804, 0x9ab3, 0x9182, 0x0047, 0x0002, - 0xb3fd, 0xb3ff, 0xb3fd, 0xb3fd, 0xb3fd, 0xb3fd, 0xb3fd, 0xb3fd, - 0xb3fd, 0xb3fd, 0xb3fd, 0xb3fd, 0xb3ff, 0x080c, 0x0d85, 0x00d6, - 0x0096, 0x601f, 0x0000, 0x6114, 0x2148, 0xa87b, 0x0000, 0xa883, - 0x0000, 0x080c, 0x7012, 0x009e, 0x00de, 0x0804, 0xb16c, 0x0026, - 0x0036, 0x0056, 0x0066, 0x0096, 0x00a6, 0x00f6, 0x0006, 0x080c, - 0x1059, 0x000e, 0x090c, 0x0d85, 0xa960, 0x21e8, 0xa95c, 0x9188, - 0x0019, 0x21a0, 0x900e, 0x20a9, 0x0020, 0x4104, 0xa87a, 0x2079, - 0x1800, 0x7990, 0x9188, 0x0018, 0x918c, 0x0fff, 0xa972, 0xac76, - 0x2950, 0x00a6, 0x2001, 0x0205, 0x2003, 0x0000, 0x901e, 0x2029, - 0x0001, 0x9182, 0x0035, 0x1228, 0x2011, 0x001f, 0x080c, 0xca7b, - 0x04c0, 0x2130, 0x2009, 0x0034, 0x2011, 0x001f, 0x080c, 0xca7b, - 0x96b2, 0x0034, 0xb004, 0x904d, 0x0110, 0x080c, 0x100b, 0x080c, - 0x1059, 0x01d0, 0x8528, 0xa867, 0x0110, 0xa86b, 0x0000, 0x2920, - 0xb406, 0x968a, 0x003d, 0x1230, 0x2608, 0x2011, 0x001b, 0x080c, - 0xca7b, 0x00b8, 0x96b2, 0x003c, 0x2009, 0x003c, 0x2950, 0x2011, - 0x001b, 0x080c, 0xca7b, 0x0c18, 0x2001, 0x0205, 0x2003, 0x0000, - 0x00ae, 0x852f, 0x95ad, 0x0050, 0xb566, 0xb070, 0xc0fd, 0xb072, - 0x0048, 0x2001, 0x0205, 0x2003, 0x0000, 0x00ae, 0x852f, 0x95ad, - 0x0050, 0xb566, 0x2a48, 0xa804, 0xa807, 0x0000, 0x0006, 0x080c, - 0x7012, 0x000e, 0x2048, 0x9005, 0x1db0, 0x00fe, 0x00ae, 0x009e, - 0x006e, 0x005e, 0x003e, 0x002e, 0x0005, 0x00d6, 0x00f6, 0x0096, - 0x0006, 0x080c, 0x1059, 0x000e, 0x090c, 0x0d85, 0xa960, 0x21e8, - 0xa95c, 0x9188, 0x0019, 0x21a0, 0x900e, 0x20a9, 0x0020, 0x4104, - 0xaa66, 0xa87a, 0x2079, 0x1800, 0x7990, 0x810c, 0x9188, 0x000c, - 0x9182, 0x001a, 0x0210, 0x2009, 0x001a, 0x21a8, 0x810b, 0xa972, - 0xac76, 0x2e98, 0xa85c, 0x9080, 0x001f, 0x20a0, 0x2001, 0x0205, - 0x200c, 0x918d, 0x0080, 0x2102, 0x4003, 0x2003, 0x0000, 0x080c, - 0x7012, 0x009e, 0x00fe, 0x00de, 0x0005, 0x0016, 0x00d6, 0x00f6, - 0x0096, 0x0016, 0x2001, 0x0205, 0x200c, 0x918d, 0x0080, 0x2102, - 0x001e, 0x2079, 0x0200, 0x2e98, 0xa87c, 0xd0ec, 0x0118, 0x9e80, - 0x000c, 0x2098, 0x2021, 0x003e, 0x901e, 0x9282, 0x0020, 0x0218, - 0x2011, 0x0020, 0x2018, 0x9486, 0x003e, 0x1170, 0x0096, 0x080c, - 0x1059, 0x2900, 0x009e, 0x05c0, 0xa806, 0x2048, 0xa860, 0x20e8, - 0xa85c, 0x9080, 0x0002, 0x20a0, 0x3300, 0x908e, 0x0260, 0x0140, - 0x2009, 0x0280, 0x9102, 0x920a, 0x0218, 0x2010, 0x2100, 0x9318, - 0x2200, 0x9402, 0x1228, 0x2400, 0x9202, 0x2410, 0x9318, 0x9006, - 0x2020, 0x22a8, 0xa800, 0x9200, 0xa802, 0x20e1, 0x0000, 0x4003, - 0x83ff, 0x0180, 0x3300, 0x9086, 0x0280, 0x1130, 0x7814, 0x8000, - 0x9085, 0x0080, 0x7816, 0x2e98, 0x2310, 0x84ff, 0x0904, 0xb4e2, - 0x0804, 0xb4e4, 0x9085, 0x0001, 0x7817, 0x0000, 0x009e, 0x00fe, - 0x00de, 0x001e, 0x0005, 0x00d6, 0x0036, 0x0096, 0x6314, 0x2348, - 0xa87a, 0xa982, 0x080c, 0x7006, 0x009e, 0x003e, 0x00de, 0x0005, - 0x91b6, 0x0015, 0x1118, 0x080c, 0xb16c, 0x0030, 0x91b6, 0x0016, - 0x190c, 0x0d85, 0x080c, 0xb16c, 0x0005, 0x20a9, 0x000e, 0x20e1, - 0x0000, 0x2e98, 0x6014, 0x0096, 0x2048, 0xa860, 0x20e8, 0xa85c, - 0x20a0, 0x009e, 0x4003, 0x9196, 0x0016, 0x01f0, 0x0136, 0x9080, - 0x001b, 0x20a0, 0x2011, 0x0006, 0x20a9, 0x0001, 0x3418, 0x8318, - 0x23a0, 0x4003, 0x3318, 0x8318, 0x2398, 0x8211, 0x1db8, 0x2011, - 0x0006, 0x013e, 0x20a0, 0x3318, 0x8318, 0x2398, 0x4003, 0x3418, - 0x8318, 0x23a0, 0x8211, 0x1db8, 0x0096, 0x080c, 0xcf1b, 0x0130, - 0x6014, 0x2048, 0xa807, 0x0000, 0xa867, 0x0103, 0x009e, 0x0804, - 0xb16c, 0x0096, 0x00d6, 0x0036, 0x7330, 0x9386, 0x0200, 0x11a8, - 0x6010, 0x00b6, 0x2058, 0xb8d7, 0x0000, 0x00be, 0x6014, 0x9005, - 0x0130, 0x2048, 0xa807, 0x0000, 0xa867, 0x0103, 0xab32, 0x080c, - 0xb16c, 0x003e, 0x00de, 0x009e, 0x0005, 0x0011, 0x1d48, 0x0cc8, - 0x0006, 0x0016, 0x080c, 0xd645, 0x0188, 0x6014, 0x9005, 0x1170, - 0x600b, 0x0003, 0x601b, 0x0000, 0x604b, 0x0000, 0x2009, 0x0022, - 0x080c, 0xb994, 0x9006, 0x001e, 0x000e, 0x0005, 0x9085, 0x0001, - 0x0cd0, 0x0096, 0x0016, 0x20a9, 0x0014, 0x9e80, 0x000c, 0x20e1, - 0x0000, 0x2098, 0x6014, 0x2048, 0xa860, 0x20e8, 0xa85c, 0x9080, - 0x0002, 0x20a0, 0x4003, 0x2001, 0x0205, 0x2003, 0x0001, 0x2099, - 0x0260, 0x20a9, 0x0016, 0x4003, 0x20a9, 0x000a, 0xa804, 0x2048, - 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0002, 0x20a0, 0x4003, 0x2001, - 0x0205, 0x2003, 0x0002, 0x2099, 0x0260, 0x20a9, 0x0020, 0x4003, - 0x2003, 0x0000, 0x6014, 0x2048, 0xa800, 0x2048, 0xa867, 0x0103, - 0x080c, 0xb16c, 0x001e, 0x009e, 0x0005, 0x0096, 0x0016, 0x900e, - 0x7030, 0x9086, 0x0100, 0x0140, 0x7038, 0x9084, 0x00ff, 0x800c, - 0x703c, 0x9084, 0x00ff, 0x8004, 0x9080, 0x0004, 0x9108, 0x810b, - 0x2011, 0x0002, 0x2019, 0x000c, 0x6014, 0x2048, 0x080c, 0xca7b, - 0x080c, 0xcf1b, 0x0140, 0x6014, 0x2048, 0xa807, 0x0000, 0xa864, - 0xa8e2, 0xa867, 0x0103, 0x080c, 0xb16c, 0x001e, 0x009e, 0x0005, - 0x0016, 0x2009, 0x0000, 0x7030, 0x9086, 0x0200, 0x0110, 0x2009, - 0x0001, 0x0096, 0x6014, 0x904d, 0x090c, 0x0d85, 0xa97a, 0x080c, - 0x7012, 0x009e, 0x080c, 0xb16c, 0x001e, 0x0005, 0x0016, 0x0096, - 0x7030, 0x9086, 0x0100, 0x1118, 0x2009, 0x0004, 0x0010, 0x7034, - 0x800c, 0x810b, 0x2011, 0x000c, 0x2019, 0x000c, 0x6014, 0x2048, - 0xa804, 0x0096, 0x9005, 0x0108, 0x2048, 0x080c, 0xca7b, 0x009e, - 0x080c, 0xcf1b, 0x0148, 0xa804, 0x9005, 0x1158, 0xa807, 0x0000, - 0xa864, 0xa8e2, 0xa867, 0x0103, 0x080c, 0xb16c, 0x009e, 0x001e, - 0x0005, 0x0086, 0x2040, 0xa030, 0x8007, 0x9086, 0x0100, 0x1118, - 0x080c, 0xbb5c, 0x00e0, 0xa034, 0x8007, 0x800c, 0x8806, 0x8006, - 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x000c, 0xa87b, - 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, 0xaaa0, 0xab9c, 0xaca8, - 0xada4, 0x2031, 0x0000, 0x2041, 0x12a8, 0x0019, 0x0d08, 0x008e, - 0x0898, 0x0096, 0x0006, 0x080c, 0x1059, 0x000e, 0x01b0, 0xa8ab, - 0x0dcb, 0xa876, 0x000e, 0xa8a2, 0x0006, 0xae6a, 0x2800, 0xa89e, - 0xa97a, 0xaf72, 0xaa8e, 0xab92, 0xac96, 0xad9a, 0x0086, 0x2940, - 0x080c, 0x114e, 0x008e, 0x9085, 0x0001, 0x009e, 0x0005, 0x00e6, - 0x00d6, 0x0026, 0x7008, 0x9084, 0x00ff, 0x6210, 0x00b6, 0x2258, - 0xba10, 0x00be, 0x9206, 0x1520, 0x700c, 0x6210, 0x00b6, 0x2258, - 0xba14, 0x00be, 0x9206, 0x11e0, 0x604b, 0x0000, 0x2c68, 0x0016, - 0x2009, 0x0035, 0x080c, 0xd5bb, 0x001e, 0x1158, 0x622c, 0x2268, - 0x2071, 0x026c, 0x6b20, 0x9386, 0x0003, 0x0130, 0x9386, 0x0006, - 0x0128, 0x080c, 0xb16c, 0x0020, 0x0039, 0x0010, 0x080c, 0xb7c7, - 0x002e, 0x00de, 0x00ee, 0x0005, 0x0096, 0x6814, 0x2048, 0x9186, - 0x0015, 0x0904, 0xb7a6, 0x918e, 0x0016, 0x1904, 0xb7c5, 0x700c, - 0x908c, 0xff00, 0x9186, 0x1700, 0x0120, 0x9186, 0x0300, 0x1904, - 0xb780, 0x89ff, 0x1138, 0x6800, 0x9086, 0x000f, 0x0904, 0xb762, - 0x0804, 0xb7c3, 0x6808, 0x9086, 0xffff, 0x1904, 0xb7a8, 0xa87c, - 0x9084, 0x0060, 0x9086, 0x0020, 0x1150, 0xa8ac, 0xa934, 0x9106, - 0x1904, 0xb7a8, 0xa8b0, 0xa938, 0x9106, 0x1904, 0xb7a8, 0x6824, - 0xd084, 0x1904, 0xb7a8, 0xd0b4, 0x0158, 0x0016, 0x2001, 0x1986, - 0x200c, 0x6018, 0x9102, 0x9082, 0x0005, 0x001e, 0x1a04, 0xb7a8, - 0x080c, 0xd10c, 0x6810, 0x0096, 0x2048, 0xa9a0, 0x009e, 0x685c, - 0xa87a, 0xa976, 0x6864, 0xa882, 0xa87c, 0xc0dc, 0xc0f4, 0xc0d4, - 0xa87e, 0x0026, 0x900e, 0x6a18, 0x2001, 0x000a, 0x080c, 0x955b, - 0xa884, 0x920a, 0x0208, 0x8011, 0xaa86, 0x82ff, 0x002e, 0x1138, - 0x00c6, 0x2d60, 0x080c, 0xcc01, 0x00ce, 0x0804, 0xb7c3, 0x00c6, - 0xa868, 0xd0fc, 0x1118, 0x080c, 0x622f, 0x0010, 0x080c, 0x663a, - 0x00ce, 0x1904, 0xb7a8, 0x00c6, 0x2d60, 0x080c, 0xb16c, 0x00ce, - 0x0804, 0xb7c3, 0x00c6, 0x080c, 0xb1dd, 0x0198, 0x6017, 0x0000, - 0x6810, 0x6012, 0x080c, 0xd3b6, 0x6023, 0x0003, 0x6904, 0x00c6, - 0x2d60, 0x080c, 0xb16c, 0x00ce, 0x080c, 0xb20a, 0x00ce, 0x0804, - 0xb7c3, 0x2001, 0x1988, 0x2004, 0x684a, 0x00ce, 0x0804, 0xb7c3, - 0x7008, 0x9086, 0x000b, 0x11c8, 0x6010, 0x00b6, 0x2058, 0xb900, - 0xc1bc, 0xb902, 0x00be, 0x00c6, 0x2d60, 0xa87b, 0x0003, 0x080c, - 0xd5ff, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x2009, - 0x8020, 0x080c, 0x9617, 0x00ce, 0x0430, 0x700c, 0x9086, 0x2a00, - 0x1138, 0x2001, 0x1988, 0x2004, 0x684a, 0x00e8, 0x04c1, 0x00e8, - 0x89ff, 0x090c, 0x0d85, 0x00c6, 0x00d6, 0x2d60, 0xa867, 0x0103, - 0xa87b, 0x0003, 0x080c, 0x6e27, 0x080c, 0xd10c, 0x080c, 0xb1a7, - 0x0026, 0x6010, 0x00b6, 0x2058, 0xba3c, 0x080c, 0x68df, 0x00be, - 0x002e, 0x00de, 0x00ce, 0x080c, 0xb16c, 0x009e, 0x0005, 0x9186, - 0x0015, 0x1128, 0x2001, 0x1988, 0x2004, 0x684a, 0x0068, 0x918e, - 0x0016, 0x1160, 0x00c6, 0x2d00, 0x2060, 0x080c, 0xece1, 0x080c, - 0x8c19, 0x080c, 0xb16c, 0x00ce, 0x080c, 0xb16c, 0x0005, 0x0026, - 0x0036, 0x0046, 0x7228, 0xacb0, 0xabac, 0xd2f4, 0x0130, 0x2001, - 0x1988, 0x2004, 0x684a, 0x0804, 0xb841, 0x00c6, 0x2d60, 0x080c, - 0xcadc, 0x00ce, 0x6804, 0x9086, 0x0050, 0x1168, 0x00c6, 0x2d00, - 0x2060, 0x6003, 0x0001, 0x6007, 0x0050, 0x2009, 0x8023, 0x080c, - 0x9617, 0x00ce, 0x04f0, 0x6800, 0x9086, 0x000f, 0x01a8, 0x89ff, - 0x090c, 0x0d85, 0x6800, 0x9086, 0x0004, 0x1190, 0xa87c, 0xd0ac, - 0x0178, 0xa843, 0x0fff, 0xa83f, 0x0fff, 0xa880, 0xc0fc, 0xa882, - 0x2001, 0x0001, 0x6832, 0x0400, 0x2001, 0x0007, 0x6832, 0x00e0, - 0xa87c, 0xd0b4, 0x1150, 0xd0ac, 0x0db8, 0x6824, 0xd0f4, 0x1d48, - 0xa838, 0xa934, 0x9105, 0x0d80, 0x0c20, 0xd2ec, 0x1d68, 0x7024, - 0x9306, 0x1118, 0x7020, 0x9406, 0x0d38, 0x7020, 0x683e, 0x7024, - 0x683a, 0x2001, 0x0005, 0x6832, 0x080c, 0xd2a0, 0x080c, 0x9ab3, - 0x0010, 0x080c, 0xb16c, 0x004e, 0x003e, 0x002e, 0x0005, 0x00e6, - 0x00d6, 0x0026, 0x7008, 0x9084, 0x00ff, 0x6210, 0x00b6, 0x2258, - 0xba10, 0x00be, 0x9206, 0x1904, 0xb8ac, 0x700c, 0x6210, 0x00b6, - 0x2258, 0xba14, 0x00be, 0x9206, 0x1904, 0xb8ac, 0x6038, 0x2068, - 0x6824, 0xc0dc, 0x6826, 0x6a20, 0x9286, 0x0007, 0x0904, 0xb8ac, - 0x9286, 0x0002, 0x0904, 0xb8ac, 0x9286, 0x0000, 0x05e8, 0x6808, - 0x633c, 0x9306, 0x15c8, 0x2071, 0x026c, 0x9186, 0x0015, 0x0570, - 0x918e, 0x0016, 0x1100, 0x00c6, 0x6038, 0x2060, 0x6104, 0x9186, - 0x004b, 0x01c0, 0x9186, 0x004c, 0x01a8, 0x9186, 0x004d, 0x0190, - 0x9186, 0x004e, 0x0178, 0x9186, 0x0052, 0x0160, 0x6014, 0x0096, - 0x2048, 0x080c, 0xcf1b, 0x090c, 0x0d85, 0xa87b, 0x0003, 0x009e, - 0x080c, 0xd5ff, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, - 0x2009, 0x8020, 0x080c, 0x9617, 0x00ce, 0x0030, 0x6038, 0x2070, - 0x2001, 0x1988, 0x2004, 0x704a, 0x080c, 0xb16c, 0x002e, 0x00de, - 0x00ee, 0x0005, 0x00b6, 0x0096, 0x00f6, 0x6014, 0x2048, 0x6010, - 0x2058, 0x91b6, 0x0015, 0x0130, 0xba08, 0xbb0c, 0xbc00, 0xc48c, - 0xbc02, 0x0470, 0x0096, 0x0156, 0x0036, 0x0026, 0x2b48, 0x9e90, - 0x0010, 0x2019, 0x000a, 0x20a9, 0x0004, 0x080c, 0xc222, 0x002e, - 0x003e, 0x015e, 0x009e, 0x1904, 0xb91d, 0x0096, 0x0156, 0x0036, - 0x0026, 0x2b48, 0x9e90, 0x0014, 0x2019, 0x0006, 0x20a9, 0x0004, - 0x080c, 0xc222, 0x002e, 0x003e, 0x015e, 0x009e, 0x15b0, 0x7238, - 0xba0a, 0x733c, 0xbb0e, 0x83ff, 0x0118, 0xbc00, 0xc48d, 0xbc02, - 0xa804, 0x9005, 0x1128, 0x00fe, 0x009e, 0x00be, 0x0804, 0xb57c, - 0x0096, 0x2048, 0xaa12, 0xab16, 0xac0a, 0x009e, 0x8006, 0x8006, - 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, 0x2009, - 0x002b, 0xaaa0, 0xab9c, 0xaca8, 0xada4, 0x2031, 0x0000, 0x2041, - 0x12a8, 0x080c, 0xb691, 0x0130, 0x00fe, 0x009e, 0x080c, 0xb16c, - 0x00be, 0x0005, 0x080c, 0xbb5c, 0x0cb8, 0x2b78, 0x00f6, 0x080c, - 0x3315, 0x080c, 0xd65a, 0x00fe, 0x00c6, 0x080c, 0xb116, 0x2f00, - 0x6012, 0x6017, 0x0000, 0x6023, 0x0001, 0x6007, 0x0001, 0x6003, - 0x0001, 0x2001, 0x0007, 0x080c, 0x66fa, 0x080c, 0x6726, 0x080c, - 0x961e, 0x080c, 0x9ab3, 0x00ce, 0x0804, 0xb8f0, 0x2100, 0x91b2, - 0x0053, 0x1a0c, 0x0d85, 0x91b2, 0x0040, 0x1a04, 0xb9a6, 0x0002, - 0xb994, 0xb994, 0xb98a, 0xb994, 0xb994, 0xb994, 0xb988, 0xb988, - 0xb988, 0xb988, 0xb988, 0xb988, 0xb988, 0xb988, 0xb988, 0xb988, - 0xb988, 0xb988, 0xb988, 0xb988, 0xb988, 0xb988, 0xb988, 0xb988, - 0xb988, 0xb988, 0xb988, 0xb988, 0xb988, 0xb988, 0xb988, 0xb994, - 0xb988, 0xb994, 0xb994, 0xb988, 0xb988, 0xb988, 0xb988, 0xb988, - 0xb98a, 0xb988, 0xb988, 0xb988, 0xb988, 0xb988, 0xb988, 0xb988, - 0xb988, 0xb988, 0xb994, 0xb994, 0xb988, 0xb988, 0xb988, 0xb988, - 0xb988, 0xb988, 0xb988, 0xb988, 0xb988, 0xb994, 0xb988, 0xb988, - 0x080c, 0x0d85, 0x0066, 0x00b6, 0x6610, 0x2658, 0xb8d4, 0xc08c, - 0xb8d6, 0x00be, 0x006e, 0x0000, 0x6003, 0x0001, 0x6106, 0x9186, - 0x0032, 0x0118, 0x080c, 0x961e, 0x0010, 0x080c, 0x9617, 0x0126, - 0x2091, 0x8000, 0x080c, 0x9ab3, 0x012e, 0x0005, 0x2600, 0x0002, - 0xb994, 0xb994, 0xb9ba, 0xb994, 0xb994, 0xb9ba, 0xb9ba, 0xb9ba, - 0xb9ba, 0xb994, 0xb9ba, 0xb994, 0xb9ba, 0xb994, 0xb9ba, 0xb9ba, - 0xb9ba, 0xb9ba, 0x080c, 0x0d85, 0x6004, 0x90b2, 0x0053, 0x1a0c, - 0x0d85, 0x91b6, 0x0013, 0x0904, 0xba91, 0x91b6, 0x0027, 0x1904, - 0xba3d, 0x080c, 0x99ed, 0x6004, 0x080c, 0xd121, 0x01b0, 0x080c, - 0xd132, 0x01a8, 0x908e, 0x0021, 0x0904, 0xba3a, 0x908e, 0x0022, - 0x1130, 0x080c, 0xb5a8, 0x0904, 0xba36, 0x0804, 0xba37, 0x908e, - 0x003d, 0x0904, 0xba3a, 0x0804, 0xba30, 0x080c, 0x3344, 0x2001, - 0x0007, 0x080c, 0x66fa, 0x6010, 0x00b6, 0x2058, 0xb9a0, 0x00be, - 0x080c, 0xbb5c, 0x9186, 0x007e, 0x1148, 0x2001, 0x1837, 0x2014, - 0xc285, 0x080c, 0x779e, 0x1108, 0xc2ad, 0x2202, 0x080c, 0xacfc, - 0x0036, 0x0026, 0x2019, 0x0028, 0x2110, 0x080c, 0xedee, 0x002e, - 0x003e, 0x0016, 0x0026, 0x0036, 0x2110, 0x2019, 0x0028, 0x080c, - 0x97b0, 0x0076, 0x903e, 0x080c, 0x966d, 0x6010, 0x00b6, 0x905d, - 0x0100, 0x00be, 0x2c08, 0x080c, 0xe75d, 0x007e, 0x003e, 0x002e, - 0x001e, 0x080c, 0xad18, 0x080c, 0xd65a, 0x0016, 0x080c, 0xd3ae, - 0x080c, 0xb16c, 0x001e, 0x080c, 0x341e, 0x080c, 0x9ab3, 0x0030, - 0x080c, 0xd3ae, 0x080c, 0xb16c, 0x080c, 0x9ab3, 0x0005, 0x080c, - 0xbb5c, 0x0cb0, 0x080c, 0xbb98, 0x0c98, 0x9186, 0x0015, 0x0118, - 0x9186, 0x0016, 0x1140, 0x080c, 0xaf61, 0x0d80, 0x9086, 0x0002, - 0x0904, 0xbba3, 0x0c58, 0x9186, 0x0014, 0x1d40, 0x080c, 0x99ed, - 0x6004, 0x908e, 0x0022, 0x1118, 0x080c, 0xb5a8, 0x09f8, 0x080c, - 0x3315, 0x080c, 0xd65a, 0x080c, 0xd121, 0x1190, 0x080c, 0x3344, - 0x6010, 0x00b6, 0x2058, 0xb9a0, 0x00be, 0x080c, 0xbb5c, 0x9186, - 0x007e, 0x1128, 0x2001, 0x1837, 0x200c, 0xc185, 0x2102, 0x0800, - 0x080c, 0xd132, 0x1120, 0x080c, 0xbb5c, 0x0804, 0xba30, 0x6004, - 0x908e, 0x0032, 0x1160, 0x00e6, 0x00f6, 0x2071, 0x189e, 0x2079, - 0x0000, 0x080c, 0x36bf, 0x00fe, 0x00ee, 0x0804, 0xba30, 0x6004, - 0x908e, 0x0021, 0x0d40, 0x908e, 0x0022, 0x090c, 0xbb5c, 0x0804, - 0xba30, 0x90b2, 0x0040, 0x1a04, 0xbb3c, 0x2008, 0x0002, 0xbad9, - 0xbada, 0xbadd, 0xbae0, 0xbae3, 0xbaf0, 0xbad7, 0xbad7, 0xbad7, - 0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbad7, - 0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbad7, - 0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbaf3, 0xbafe, 0xbad7, - 0xbaff, 0xbafe, 0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbafe, - 0xbafe, 0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbad7, - 0xbad7, 0xbb27, 0xbafe, 0xbad7, 0xbafa, 0xbad7, 0xbad7, 0xbad7, - 0xbafb, 0xbad7, 0xbad7, 0xbad7, 0xbafe, 0xbb22, 0xbad7, 0x080c, - 0x0d85, 0x0420, 0x2001, 0x000b, 0x0448, 0x2001, 0x0003, 0x0430, - 0x2001, 0x0005, 0x0418, 0x6010, 0x00b6, 0x2058, 0xb804, 0x00be, - 0x9084, 0x00ff, 0x9086, 0x0000, 0x11d8, 0x2001, 0x0001, 0x00b0, - 0x2001, 0x0009, 0x0098, 0x6003, 0x0005, 0x080c, 0xd65d, 0x080c, - 0x9ab3, 0x0058, 0x0018, 0x0010, 0x080c, 0x66fa, 0x04b8, 0x080c, - 0xd65d, 0x6003, 0x0004, 0x080c, 0x9ab3, 0x0005, 0x080c, 0x66fa, - 0x6003, 0x0002, 0x0036, 0x2019, 0x1852, 0x2304, 0x9084, 0xff00, - 0x1120, 0x2001, 0x1986, 0x201c, 0x0040, 0x8007, 0x909a, 0x0004, - 0x0ec0, 0x8003, 0x801b, 0x831b, 0x9318, 0x631a, 0x003e, 0x080c, - 0x9ab3, 0x0c18, 0x080c, 0xd3ae, 0x080c, 0xb16c, 0x08f0, 0x00e6, - 0x00f6, 0x2071, 0x189e, 0x2079, 0x0000, 0x080c, 0x36bf, 0x00fe, - 0x00ee, 0x080c, 0x99ed, 0x080c, 0xb16c, 0x0878, 0x6003, 0x0002, - 0x080c, 0xd65d, 0x0804, 0x9ab3, 0x2600, 0x2008, 0x0002, 0xbb53, - 0xbb36, 0xbb51, 0xbb36, 0xbb36, 0xbb51, 0xbb51, 0xbb51, 0xbb51, - 0xbb36, 0xbb51, 0xbb36, 0xbb51, 0xbb36, 0xbb51, 0xbb51, 0xbb51, - 0xbb51, 0x080c, 0x0d85, 0x0096, 0x6014, 0x2048, 0x080c, 0x7012, - 0x009e, 0x080c, 0xb16c, 0x0005, 0x00e6, 0x0096, 0x0026, 0x0016, - 0x080c, 0xcf1b, 0x0568, 0x6014, 0x2048, 0xa864, 0x9086, 0x0139, - 0x11a8, 0xa894, 0x9086, 0x0056, 0x1148, 0x080c, 0x55cc, 0x0130, - 0x2001, 0x0000, 0x900e, 0x2011, 0x4000, 0x0028, 0x2001, 0x0030, - 0x900e, 0x2011, 0x4005, 0x080c, 0xd51f, 0x0090, 0xa868, 0xd0fc, - 0x0178, 0xa807, 0x0000, 0x0016, 0x6004, 0x908e, 0x0021, 0x0168, - 0x908e, 0x003d, 0x0150, 0x001e, 0xa867, 0x0103, 0xa833, 0x0100, - 0x001e, 0x002e, 0x009e, 0x00ee, 0x0005, 0x001e, 0x0009, 0x0cc0, - 0x0096, 0x6014, 0x2048, 0xa800, 0x2048, 0xa867, 0x0103, 0xa823, - 0x8001, 0x009e, 0x0005, 0x00b6, 0x6610, 0x2658, 0xb804, 0x9084, - 0x00ff, 0x90b2, 0x000c, 0x1a0c, 0x0d85, 0x6604, 0x96b6, 0x004d, - 0x1120, 0x080c, 0xd43e, 0x0804, 0xbc28, 0x6604, 0x96b6, 0x0043, - 0x1120, 0x080c, 0xd487, 0x0804, 0xbc28, 0x6604, 0x96b6, 0x004b, - 0x1120, 0x080c, 0xd4b3, 0x0804, 0xbc28, 0x6604, 0x96b6, 0x0033, - 0x1120, 0x080c, 0xd3d0, 0x0804, 0xbc28, 0x6604, 0x96b6, 0x0028, - 0x1120, 0x080c, 0xd170, 0x0804, 0xbc28, 0x6604, 0x96b6, 0x0029, - 0x1120, 0x080c, 0xd1b1, 0x0804, 0xbc28, 0x6604, 0x96b6, 0x001f, - 0x1120, 0x080c, 0xb54d, 0x0804, 0xbc28, 0x6604, 0x96b6, 0x0000, - 0x1118, 0x080c, 0xb8b2, 0x04e0, 0x6604, 0x96b6, 0x0022, 0x1118, - 0x080c, 0xb589, 0x04a8, 0x6604, 0x96b6, 0x0035, 0x1118, 0x080c, - 0xb6af, 0x0470, 0x6604, 0x96b6, 0x0039, 0x1118, 0x080c, 0xb847, - 0x0438, 0x6604, 0x96b6, 0x003d, 0x1118, 0x080c, 0xb5c1, 0x0400, - 0x6604, 0x96b6, 0x0044, 0x1118, 0x080c, 0xb5fd, 0x00c8, 0x6604, - 0x96b6, 0x0049, 0x1118, 0x080c, 0xb63e, 0x0090, 0x6604, 0x96b6, - 0x0041, 0x1118, 0x080c, 0xb628, 0x0058, 0x91b6, 0x0015, 0x1110, - 0x0063, 0x0030, 0x91b6, 0x0016, 0x1128, 0x00be, 0x0804, 0xbf34, - 0x00be, 0x0005, 0x080c, 0xb227, 0x0cd8, 0xbc45, 0xbc53, 0xbc45, - 0xbc9a, 0xbc45, 0xbe51, 0xbf41, 0xbc45, 0xbc45, 0xbf0a, 0xbc45, - 0xbf20, 0x0096, 0x601f, 0x0000, 0x6014, 0x2048, 0xa800, 0x2048, - 0xa867, 0x0103, 0x009e, 0x0804, 0xb16c, 0xa001, 0xa001, 0x0005, - 0x6604, 0x96b6, 0x0004, 0x1130, 0x2001, 0x0001, 0x080c, 0x66e6, - 0x0804, 0xb16c, 0x0005, 0x00e6, 0x2071, 0x1800, 0x7090, 0x9086, - 0x0074, 0x1540, 0x080c, 0xe72e, 0x11b0, 0x6010, 0x00b6, 0x2058, - 0x7030, 0xd08c, 0x0128, 0xb800, 0xd0bc, 0x0110, 0xc0c5, 0xb802, - 0x00f9, 0x00be, 0x2001, 0x0006, 0x080c, 0x66fa, 0x080c, 0x3344, - 0x080c, 0xb16c, 0x0098, 0x2001, 0x000a, 0x080c, 0x66fa, 0x080c, - 0x3344, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x961e, 0x080c, - 0x9ab3, 0x0020, 0x2001, 0x0001, 0x080c, 0xbe21, 0x00ee, 0x0005, - 0x00d6, 0xb800, 0xd084, 0x0160, 0x9006, 0x080c, 0x66e6, 0x2069, - 0x1847, 0x6804, 0xd0a4, 0x0120, 0x2001, 0x0006, 0x080c, 0x6726, - 0x00de, 0x0005, 0x00b6, 0x0096, 0x00d6, 0x2011, 0x1824, 0x2204, - 0x9086, 0x0074, 0x1904, 0xbdf6, 0x6010, 0x2058, 0xbaa0, 0x9286, - 0x007e, 0x1120, 0x080c, 0xc090, 0x0804, 0xbd63, 0x2001, 0x180d, - 0x2004, 0xd08c, 0x0904, 0xbd05, 0x00d6, 0x080c, 0x779e, 0x01a0, - 0x0026, 0x2011, 0x0010, 0x080c, 0x6c35, 0x002e, 0x0904, 0xbd04, - 0x080c, 0x5854, 0x1598, 0x6014, 0x2048, 0xa807, 0x0000, 0xa867, - 0x0103, 0xa833, 0xdead, 0x0450, 0x6010, 0x00b6, 0x2058, 0xb910, - 0x00be, 0x9186, 0x00ff, 0x0580, 0x0026, 0x2011, 0x8008, 0x080c, - 0x6c35, 0x002e, 0x0548, 0x6014, 0x9005, 0x090c, 0x0d85, 0x2048, - 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1140, 0x2001, 0x0030, - 0x900e, 0x2011, 0x4009, 0x080c, 0xd51f, 0x0040, 0x6014, 0x2048, - 0xa807, 0x0000, 0xa867, 0x0103, 0xa833, 0xdead, 0x6010, 0x2058, - 0xb9a0, 0x0016, 0x080c, 0x3344, 0x080c, 0xb16c, 0x001e, 0x080c, - 0x341e, 0x00de, 0x0804, 0xbdfb, 0x00de, 0x080c, 0xc085, 0x6010, - 0x2058, 0xbaa0, 0x9286, 0x0080, 0x1510, 0x6014, 0x9005, 0x01a8, - 0x2048, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1140, 0x2001, - 0x0000, 0x900e, 0x2011, 0x4000, 0x080c, 0xd51f, 0x0030, 0xa807, - 0x0000, 0xa867, 0x0103, 0xa833, 0x0200, 0x2001, 0x0006, 0x080c, - 0x66fa, 0x080c, 0x3344, 0x080c, 0xb16c, 0x0804, 0xbdfb, 0x080c, - 0xbe09, 0x6014, 0x9005, 0x0190, 0x2048, 0xa868, 0xd0f4, 0x01e8, - 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1d08, 0x2001, 0x0000, - 0x900e, 0x2011, 0x4000, 0x080c, 0xd51f, 0x08f8, 0x080c, 0xbdff, - 0x0160, 0x9006, 0x080c, 0x66e6, 0x2001, 0x0004, 0x080c, 0x6726, - 0x2001, 0x0007, 0x080c, 0x66fa, 0x08a0, 0x2001, 0x0004, 0x080c, - 0x66fa, 0x6003, 0x0001, 0x6007, 0x0003, 0x080c, 0x961e, 0x080c, - 0x9ab3, 0x0804, 0xbdfb, 0xb85c, 0xd0e4, 0x0178, 0x080c, 0xd348, - 0x080c, 0x779e, 0x0118, 0xd0dc, 0x1904, 0xbd25, 0x2011, 0x1837, - 0x2204, 0xc0ad, 0x2012, 0x0804, 0xbd25, 0x080c, 0xd389, 0x2011, - 0x1837, 0x2204, 0xc0a5, 0x2012, 0x0006, 0x080c, 0xe905, 0x000e, - 0x1904, 0xbd25, 0xc0b5, 0x2012, 0x2001, 0x0006, 0x080c, 0x66fa, - 0x9006, 0x080c, 0x66e6, 0x00c6, 0x2001, 0x180f, 0x2004, 0xd09c, - 0x0520, 0x00f6, 0x2079, 0x0100, 0x00e6, 0x2071, 0x1800, 0x700c, - 0x9084, 0x00ff, 0x78e6, 0x707e, 0x7010, 0x78ea, 0x7082, 0x908c, - 0x00ff, 0x00ee, 0x780c, 0xc0b5, 0x780e, 0x00fe, 0x080c, 0x26d5, - 0x00f6, 0x2100, 0x900e, 0x080c, 0x268c, 0x795e, 0x00fe, 0x9186, - 0x0081, 0x01f0, 0x2009, 0x0081, 0x00e0, 0x2009, 0x00ef, 0x00f6, - 0x2079, 0x0100, 0x79ea, 0x78e7, 0x0000, 0x7932, 0x7936, 0x780c, - 0xc0b5, 0x780e, 0x00fe, 0x080c, 0x26d5, 0x00f6, 0x2079, 0x1800, - 0x7982, 0x2100, 0x900e, 0x797e, 0x080c, 0x268c, 0x795e, 0x00fe, - 0x8108, 0x080c, 0x6749, 0x2b00, 0x00ce, 0x1904, 0xbd25, 0x6012, - 0x2009, 0x180f, 0x210c, 0xd19c, 0x0150, 0x2009, 0x027c, 0x210c, - 0x918c, 0x00ff, 0xb912, 0x2009, 0x027d, 0x210c, 0xb916, 0x2001, - 0x0002, 0x080c, 0x66fa, 0x6023, 0x0001, 0x6003, 0x0001, 0x6007, - 0x0002, 0x080c, 0x961e, 0x080c, 0x9ab3, 0x0028, 0x080c, 0xbb5c, - 0x2001, 0x0001, 0x0431, 0x00de, 0x009e, 0x00be, 0x0005, 0x2001, - 0x1810, 0x2004, 0xd0a4, 0x0120, 0x2001, 0x1848, 0x2004, 0xd0ac, - 0x0005, 0x00e6, 0x080c, 0xee47, 0x0190, 0x2071, 0x0260, 0x7108, - 0x720c, 0x918c, 0x00ff, 0x1118, 0x9284, 0xff00, 0x0140, 0x6010, - 0x2058, 0xb8a0, 0x9084, 0xff80, 0x1110, 0xb912, 0xba16, 0x00ee, - 0x0005, 0x2030, 0x9005, 0x0158, 0x2001, 0x0007, 0x080c, 0x66fa, - 0x080c, 0x5854, 0x1120, 0x2001, 0x0007, 0x080c, 0x6726, 0x2600, - 0x9005, 0x11b0, 0x6014, 0x0096, 0x2048, 0xa868, 0x009e, 0xd0fc, - 0x1178, 0x0036, 0x0046, 0x6010, 0x00b6, 0x2058, 0xbba0, 0x00be, - 0x2021, 0x0004, 0x2011, 0x8014, 0x080c, 0x4ca1, 0x004e, 0x003e, - 0x080c, 0x3344, 0x6020, 0x9086, 0x000a, 0x1108, 0x0005, 0x0804, - 0xb16c, 0x00b6, 0x00e6, 0x0026, 0x0016, 0x2071, 0x1800, 0x7090, - 0x9086, 0x0014, 0x1904, 0xbf00, 0x2001, 0x180d, 0x2004, 0xd08c, - 0x0904, 0xbeb3, 0x00d6, 0x080c, 0x779e, 0x01a0, 0x0026, 0x2011, - 0x0010, 0x080c, 0x6c35, 0x002e, 0x0904, 0xbeb2, 0x080c, 0x5854, - 0x1598, 0x6014, 0x2048, 0xa807, 0x0000, 0xa867, 0x0103, 0xa833, - 0xdead, 0x0450, 0x6010, 0x00b6, 0x2058, 0xb910, 0x00be, 0x9186, - 0x00ff, 0x0580, 0x0026, 0x2011, 0x8008, 0x080c, 0x6c35, 0x002e, - 0x0548, 0x6014, 0x9005, 0x090c, 0x0d85, 0x2048, 0xa864, 0x9084, - 0x00ff, 0x9086, 0x0039, 0x1140, 0x2001, 0x0030, 0x900e, 0x2011, - 0x4009, 0x080c, 0xd51f, 0x0040, 0x6014, 0x2048, 0xa807, 0x0000, - 0xa867, 0x0103, 0xa833, 0xdead, 0x6010, 0x2058, 0xb9a0, 0x0016, - 0x080c, 0x3344, 0x080c, 0xb16c, 0x001e, 0x080c, 0x341e, 0x00de, - 0x0804, 0xbf05, 0x00de, 0x080c, 0x5854, 0x1170, 0x6014, 0x9005, - 0x1158, 0x0036, 0x0046, 0x6010, 0x2058, 0xbba0, 0x2021, 0x0006, - 0x080c, 0x4e58, 0x004e, 0x003e, 0x00d6, 0x6010, 0x2058, 0x080c, - 0x684f, 0x080c, 0xbc88, 0x00de, 0x080c, 0xc15b, 0x1588, 0x6010, - 0x2058, 0xb890, 0x9005, 0x0560, 0x2001, 0x0006, 0x080c, 0x66fa, - 0x0096, 0x6014, 0x904d, 0x01d0, 0xa864, 0x9084, 0x00ff, 0x9086, - 0x0039, 0x1140, 0x2001, 0x0000, 0x900e, 0x2011, 0x4000, 0x080c, - 0xd51f, 0x0060, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0029, 0x0130, - 0xa807, 0x0000, 0xa867, 0x0103, 0xa833, 0x0200, 0x009e, 0x080c, - 0x3344, 0x6020, 0x9086, 0x000a, 0x0140, 0x080c, 0xb16c, 0x0028, - 0x080c, 0xbb5c, 0x9006, 0x080c, 0xbe21, 0x001e, 0x002e, 0x00ee, - 0x00be, 0x0005, 0x2011, 0x1824, 0x2204, 0x9086, 0x0014, 0x1160, - 0x2001, 0x0002, 0x080c, 0x66fa, 0x6003, 0x0001, 0x6007, 0x0001, - 0x080c, 0x961e, 0x0804, 0x9ab3, 0x2001, 0x0001, 0x0804, 0xbe21, - 0x2030, 0x2011, 0x1824, 0x2204, 0x9086, 0x0004, 0x1148, 0x96b6, - 0x000b, 0x1120, 0x2001, 0x0007, 0x080c, 0x66fa, 0x0804, 0xb16c, - 0x2001, 0x0001, 0x0804, 0xbe21, 0x0002, 0xbc45, 0xbf4c, 0xbc45, - 0xbf8f, 0xbc45, 0xc03c, 0xbf41, 0xbc48, 0xbc45, 0xc050, 0xbc45, - 0xc062, 0x6604, 0x9686, 0x0003, 0x0904, 0xbe51, 0x96b6, 0x001e, - 0x1110, 0x080c, 0xb16c, 0x0005, 0x00b6, 0x00d6, 0x00c6, 0x080c, - 0xc074, 0x11a0, 0x9006, 0x080c, 0x66e6, 0x080c, 0x3315, 0x080c, - 0xd65a, 0x2001, 0x0002, 0x080c, 0x66fa, 0x6003, 0x0001, 0x6007, - 0x0002, 0x080c, 0x961e, 0x080c, 0x9ab3, 0x0428, 0x2009, 0x026e, - 0x2104, 0x9086, 0x0009, 0x1160, 0x6010, 0x2058, 0xb840, 0x9084, - 0x00ff, 0x9005, 0x0180, 0x8001, 0xb842, 0x601b, 0x000a, 0x0098, - 0x2009, 0x026f, 0x2104, 0x9084, 0xff00, 0x908e, 0x1900, 0x0158, - 0x908e, 0x1e00, 0x0990, 0x080c, 0x3315, 0x080c, 0xd65a, 0x2001, - 0x0001, 0x080c, 0xbe21, 0x00ce, 0x00de, 0x00be, 0x0005, 0x0096, - 0x00b6, 0x0026, 0x9016, 0x080c, 0xc082, 0x00d6, 0x2069, 0x197c, - 0x2d04, 0x9005, 0x0168, 0x6010, 0x2058, 0xb8a0, 0x9086, 0x007e, - 0x1138, 0x2069, 0x1820, 0x2d04, 0x8000, 0x206a, 0x00de, 0x0010, - 0x00de, 0x0088, 0x9006, 0x080c, 0x66e6, 0x2001, 0x0002, 0x080c, - 0x66fa, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x961e, 0x080c, - 0x9ab3, 0x0804, 0xc00c, 0x080c, 0xcf1b, 0x01b0, 0x6014, 0x2048, - 0xa864, 0x2010, 0x9086, 0x0139, 0x1138, 0x6007, 0x0016, 0x2001, - 0x0002, 0x080c, 0xd57c, 0x00b0, 0x6014, 0x2048, 0xa864, 0xd0fc, - 0x0118, 0x2001, 0x0001, 0x0ca8, 0x2001, 0x180e, 0x2004, 0xd0dc, - 0x0148, 0x6010, 0x2058, 0xb840, 0x9084, 0x00ff, 0x9005, 0x1110, - 0x9006, 0x0c38, 0x080c, 0xbb5c, 0x2009, 0x026e, 0x2134, 0x96b4, - 0x00ff, 0x9686, 0x0005, 0x0520, 0x9686, 0x000b, 0x01c8, 0x2009, - 0x026f, 0x2104, 0x9084, 0xff00, 0x1118, 0x9686, 0x0009, 0x01c0, - 0x9086, 0x1900, 0x1168, 0x9686, 0x0009, 0x0190, 0x2001, 0x0004, - 0x080c, 0x66fa, 0x2001, 0x0028, 0x601a, 0x6007, 0x0052, 0x0020, - 0x2001, 0x0001, 0x080c, 0xbe21, 0x002e, 0x00be, 0x009e, 0x0005, - 0x9286, 0x0139, 0x0160, 0x6014, 0x2048, 0x080c, 0xcf1b, 0x0140, - 0xa864, 0x9086, 0x0139, 0x0118, 0xa868, 0xd0fc, 0x0108, 0x0c40, - 0x6010, 0x2058, 0xb840, 0x9084, 0x00ff, 0x9005, 0x0138, 0x8001, - 0xb842, 0x601b, 0x000a, 0x6007, 0x0016, 0x08f0, 0xb8a0, 0x9086, - 0x007e, 0x1138, 0x00e6, 0x2071, 0x1800, 0x080c, 0x6130, 0x00ee, - 0x0010, 0x080c, 0x3315, 0x0860, 0x2001, 0x0004, 0x080c, 0x66fa, - 0x080c, 0xc082, 0x1140, 0x6003, 0x0001, 0x6007, 0x0003, 0x080c, - 0x961e, 0x0804, 0x9ab3, 0x080c, 0xbb5c, 0x9006, 0x0804, 0xbe21, - 0x0489, 0x1160, 0x2001, 0x0008, 0x080c, 0x66fa, 0x6003, 0x0001, - 0x6007, 0x0005, 0x080c, 0x961e, 0x0804, 0x9ab3, 0x2001, 0x0001, - 0x0804, 0xbe21, 0x00f9, 0x1160, 0x2001, 0x000a, 0x080c, 0x66fa, - 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x961e, 0x0804, 0x9ab3, - 0x2001, 0x0001, 0x0804, 0xbe21, 0x2009, 0x026e, 0x2104, 0x9086, - 0x0003, 0x1138, 0x2009, 0x026f, 0x2104, 0x9084, 0xff00, 0x9086, - 0x2a00, 0x0005, 0x9085, 0x0001, 0x0005, 0x00b6, 0x00c6, 0x0016, - 0x6110, 0x2158, 0x080c, 0x67c3, 0x001e, 0x00ce, 0x00be, 0x0005, - 0x00b6, 0x00f6, 0x00e6, 0x00d6, 0x0036, 0x0016, 0x6010, 0x2058, - 0x2009, 0x1837, 0x2104, 0x9085, 0x0003, 0x200a, 0x080c, 0xc12d, - 0x0560, 0x2009, 0x1837, 0x2104, 0xc0cd, 0x200a, 0x080c, 0x6c0d, - 0x0158, 0x9006, 0x2020, 0x2009, 0x002a, 0x080c, 0xea8d, 0x2001, - 0x180c, 0x200c, 0xc195, 0x2102, 0x2019, 0x002a, 0x2009, 0x0001, - 0x080c, 0x32da, 0x00e6, 0x2071, 0x1800, 0x080c, 0x30bf, 0x00ee, - 0x00c6, 0x0156, 0x20a9, 0x0781, 0x2009, 0x007f, 0x080c, 0x341e, - 0x8108, 0x1f04, 0xc0c6, 0x015e, 0x00ce, 0x080c, 0xc085, 0x2071, - 0x0260, 0x2079, 0x0200, 0x7817, 0x0001, 0x2001, 0x1837, 0x200c, - 0xc1c5, 0x7018, 0xd0fc, 0x0110, 0xd0dc, 0x0118, 0x7038, 0xd0dc, - 0x1108, 0xc1c4, 0x7817, 0x0000, 0x2001, 0x1837, 0x2102, 0x9184, - 0x0050, 0x9086, 0x0050, 0x05d0, 0x2079, 0x0100, 0x2e04, 0x9084, - 0x00ff, 0x2069, 0x181f, 0x206a, 0x78e6, 0x0006, 0x8e70, 0x2e04, - 0x2069, 0x1820, 0x206a, 0x78ea, 0x7832, 0x7836, 0x2010, 0x9084, - 0xff00, 0x001e, 0x9105, 0x2009, 0x182c, 0x200a, 0x2200, 0x9084, - 0x00ff, 0x2008, 0x080c, 0x26d5, 0x080c, 0x779e, 0x0170, 0x2071, - 0x0260, 0x2069, 0x1982, 0x7048, 0x206a, 0x704c, 0x6806, 0x7050, - 0x680a, 0x7054, 0x680e, 0x080c, 0xd348, 0x0040, 0x2001, 0x0006, - 0x080c, 0x66fa, 0x080c, 0x3344, 0x080c, 0xb16c, 0x001e, 0x003e, - 0x00de, 0x00ee, 0x00fe, 0x00be, 0x0005, 0x0096, 0x0026, 0x0036, - 0x00e6, 0x0156, 0x2019, 0x182c, 0x231c, 0x83ff, 0x01f0, 0x2071, - 0x0260, 0x7200, 0x9294, 0x00ff, 0x7004, 0x9084, 0xff00, 0x9205, - 0x9306, 0x1198, 0x2011, 0x0276, 0x20a9, 0x0004, 0x2b48, 0x2019, - 0x000a, 0x080c, 0xc222, 0x1148, 0x2011, 0x027a, 0x20a9, 0x0004, - 0x2019, 0x0006, 0x080c, 0xc222, 0x1100, 0x015e, 0x00ee, 0x003e, - 0x002e, 0x009e, 0x0005, 0x00e6, 0x2071, 0x0260, 0x7034, 0x9086, - 0x0014, 0x11a8, 0x7038, 0x9086, 0x0800, 0x1188, 0x703c, 0xd0ec, - 0x0160, 0x9084, 0x0f00, 0x9086, 0x0100, 0x1138, 0x7054, 0xd0a4, - 0x1110, 0xd0ac, 0x0110, 0x9006, 0x0010, 0x9085, 0x0001, 0x00ee, - 0x0005, 0x00e6, 0x0096, 0x00c6, 0x0076, 0x0056, 0x0046, 0x0026, - 0x0006, 0x0126, 0x2091, 0x8000, 0x2029, 0x19f4, 0x252c, 0x2021, - 0x19fb, 0x2424, 0x2061, 0x1ddc, 0x2071, 0x1800, 0x7254, 0x7074, - 0x9202, 0x1a04, 0xc1ee, 0x080c, 0x8eee, 0x0904, 0xc1e7, 0x080c, - 0xeabe, 0x0904, 0xc1e7, 0x6720, 0x9786, 0x0007, 0x0904, 0xc1e7, - 0x2500, 0x9c06, 0x0904, 0xc1e7, 0x2400, 0x9c06, 0x0904, 0xc1e7, - 0x3e08, 0x9186, 0x0002, 0x1148, 0x6010, 0x9005, 0x0130, 0x00b6, - 0x2058, 0xb800, 0x00be, 0xd0bc, 0x1590, 0x00c6, 0x6043, 0xffff, - 0x6000, 0x9086, 0x0004, 0x1110, 0x080c, 0x1ad3, 0x9786, 0x000a, - 0x0148, 0x080c, 0xd132, 0x1130, 0x00ce, 0x080c, 0xbb5c, 0x080c, - 0xb1a7, 0x00e8, 0x6014, 0x2048, 0x080c, 0xcf1b, 0x01a8, 0x9786, - 0x0003, 0x1530, 0xa867, 0x0103, 0xa87c, 0xd0cc, 0x0130, 0x0096, - 0xa878, 0x2048, 0x080c, 0x100b, 0x009e, 0xab7a, 0xa877, 0x0000, - 0x080c, 0x7006, 0x080c, 0xd10c, 0x080c, 0xb1a7, 0x00ce, 0x9ce0, - 0x001c, 0x7068, 0x9c02, 0x1210, 0x0804, 0xc18e, 0x012e, 0x000e, - 0x002e, 0x004e, 0x005e, 0x007e, 0x00ce, 0x009e, 0x00ee, 0x0005, - 0x9786, 0x0006, 0x1118, 0x080c, 0xea30, 0x0c30, 0x9786, 0x0009, - 0x1148, 0x6000, 0x9086, 0x0004, 0x0d08, 0x2009, 0x004c, 0x080c, - 0xb20a, 0x08e0, 0x9786, 0x000a, 0x0980, 0x0820, 0x220c, 0x2304, - 0x9106, 0x1130, 0x8210, 0x8318, 0x1f04, 0xc20e, 0x9006, 0x0005, - 0x2304, 0x9102, 0x0218, 0x2001, 0x0001, 0x0008, 0x9006, 0x918d, - 0x0001, 0x0005, 0x0136, 0x01c6, 0x0016, 0x8906, 0x8006, 0x8007, - 0x908c, 0x003f, 0x21e0, 0x9084, 0xffc0, 0x9300, 0x2098, 0x3518, - 0x20a9, 0x0001, 0x220c, 0x4002, 0x910e, 0x1140, 0x8210, 0x8319, - 0x1dc8, 0x9006, 0x001e, 0x01ce, 0x013e, 0x0005, 0x220c, 0x9102, - 0x0218, 0x2001, 0x0001, 0x0010, 0x2001, 0x0000, 0x918d, 0x0001, - 0x001e, 0x01ce, 0x013e, 0x0005, 0x220c, 0x810f, 0x2304, 0x9106, - 0x1130, 0x8210, 0x8318, 0x1f04, 0xc24c, 0x9006, 0x0005, 0x918d, - 0x0001, 0x0005, 0x6004, 0x908a, 0x0053, 0x1a0c, 0x0d85, 0x080c, - 0xd121, 0x0120, 0x080c, 0xd132, 0x0158, 0x0028, 0x080c, 0x3344, - 0x080c, 0xd132, 0x0128, 0x080c, 0x99ed, 0x080c, 0xb16c, 0x0005, - 0x080c, 0xbb5c, 0x0cc0, 0x9182, 0x0057, 0x1220, 0x9182, 0x0040, - 0x0208, 0x000a, 0x0005, 0xc292, 0xc292, 0xc292, 0xc292, 0xc292, - 0xc292, 0xc292, 0xc292, 0xc292, 0xc292, 0xc292, 0xc294, 0xc294, - 0xc294, 0xc294, 0xc292, 0xc292, 0xc292, 0xc294, 0xc292, 0xc292, - 0xc292, 0xc292, 0x080c, 0x0d85, 0x600b, 0xffff, 0x6003, 0x000f, - 0x6106, 0x0126, 0x2091, 0x8000, 0x080c, 0xd65d, 0x2009, 0x8000, - 0x080c, 0x9617, 0x012e, 0x0005, 0x9186, 0x0013, 0x1128, 0x6004, - 0x9082, 0x0040, 0x0804, 0xc31c, 0x9186, 0x0027, 0x1520, 0x080c, - 0x99ed, 0x080c, 0x3315, 0x080c, 0xd65a, 0x0096, 0x6114, 0x2148, - 0x080c, 0xcf1b, 0x0198, 0x080c, 0xd132, 0x1118, 0x080c, 0xbb5c, - 0x0068, 0xa867, 0x0103, 0xa87b, 0x0029, 0xa877, 0x0000, 0xa97c, - 0xc1c5, 0xa97e, 0x080c, 0x7012, 0x080c, 0xd10c, 0x009e, 0x080c, - 0xb16c, 0x0804, 0x9ab3, 0x9186, 0x0014, 0x1120, 0x6004, 0x9082, - 0x0040, 0x0030, 0x9186, 0x0053, 0x0110, 0x080c, 0x0d85, 0x0005, - 0x0002, 0xc2fa, 0xc2f8, 0xc2f8, 0xc2f8, 0xc2f8, 0xc2f8, 0xc2f8, - 0xc2f8, 0xc2f8, 0xc2f8, 0xc2f8, 0xc313, 0xc313, 0xc313, 0xc313, - 0xc2f8, 0xc313, 0xc2f8, 0xc313, 0xc2f8, 0xc2f8, 0xc2f8, 0xc2f8, - 0x080c, 0x0d85, 0x080c, 0x99ed, 0x0096, 0x6114, 0x2148, 0x080c, - 0xcf1b, 0x0168, 0xa867, 0x0103, 0xa87b, 0x0006, 0xa877, 0x0000, - 0xa880, 0xc0ec, 0xa882, 0x080c, 0x7012, 0x080c, 0xd10c, 0x009e, - 0x080c, 0xb16c, 0x0005, 0x080c, 0x99ed, 0x080c, 0xd132, 0x090c, - 0xbb5c, 0x080c, 0xb16c, 0x0005, 0x0002, 0xc336, 0xc334, 0xc334, - 0xc334, 0xc334, 0xc334, 0xc334, 0xc334, 0xc334, 0xc334, 0xc334, - 0xc338, 0xc338, 0xc338, 0xc338, 0xc334, 0xc33a, 0xc334, 0xc338, - 0xc334, 0xc334, 0xc334, 0xc334, 0x080c, 0x0d85, 0x080c, 0x0d85, - 0x080c, 0x0d85, 0x080c, 0xb16c, 0x0804, 0x9ab3, 0x9182, 0x0057, - 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, 0xc35d, 0xc35d, - 0xc35d, 0xc35d, 0xc35d, 0xc396, 0xc488, 0xc35d, 0xc494, 0xc35d, - 0xc35d, 0xc35d, 0xc35d, 0xc35d, 0xc35d, 0xc35d, 0xc35d, 0xc35d, - 0xc35d, 0xc494, 0xc35f, 0xc35d, 0xc492, 0x080c, 0x0d85, 0x00b6, - 0x0096, 0x6114, 0x2148, 0x6010, 0x2058, 0xb800, 0xd0bc, 0x1508, - 0xa87b, 0x0000, 0xa867, 0x0103, 0xa877, 0x0000, 0xa87c, 0xd0ac, - 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, 0xc519, 0x080c, 0x6e27, - 0x6210, 0x2258, 0xba3c, 0x82ff, 0x0110, 0x8211, 0xba3e, 0xb8d0, - 0x9005, 0x0110, 0x080c, 0x68df, 0x080c, 0xb16c, 0x009e, 0x00be, - 0x0005, 0xa87c, 0xd0ac, 0x09e0, 0xa838, 0xa934, 0x9105, 0x09c0, - 0xa880, 0xd0bc, 0x19a8, 0x080c, 0xd267, 0x0c80, 0x00b6, 0x0096, - 0x6114, 0x2148, 0x601c, 0xd0fc, 0x1110, 0x7644, 0x0008, 0x9036, - 0x96b4, 0x0fff, 0x86ff, 0x1590, 0x6010, 0x2058, 0xb800, 0xd0bc, - 0x1904, 0xc477, 0xa87b, 0x0000, 0xa867, 0x0103, 0xae76, 0xa87c, - 0xd0ac, 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, 0xc519, 0x080c, - 0x6e27, 0x6210, 0x2258, 0xba3c, 0x82ff, 0x0110, 0x8211, 0xba3e, - 0xb8d0, 0x9005, 0x0110, 0x080c, 0x68df, 0x601c, 0xd0fc, 0x1148, - 0x7044, 0xd0e4, 0x1904, 0xc458, 0x080c, 0xb16c, 0x009e, 0x00be, - 0x0005, 0x2009, 0x0211, 0x210c, 0x080c, 0x0d85, 0x968c, 0x0c00, - 0x0150, 0x6010, 0x2058, 0xb800, 0xd0bc, 0x1904, 0xc45c, 0x7348, - 0xab92, 0x734c, 0xab8e, 0x968c, 0x00ff, 0x9186, 0x0002, 0x0508, - 0x9186, 0x0028, 0x1118, 0xa87b, 0x001c, 0x00e8, 0xd6dc, 0x01a0, - 0xa87b, 0x0015, 0xa87c, 0xd0ac, 0x0170, 0xa938, 0xaa34, 0x2100, - 0x9205, 0x0148, 0x7048, 0x9106, 0x1118, 0x704c, 0x9206, 0x0118, - 0xa992, 0xaa8e, 0xc6dc, 0x0038, 0xd6d4, 0x0118, 0xa87b, 0x0007, - 0x0010, 0xa87b, 0x0000, 0xa867, 0x0103, 0xae76, 0x901e, 0xd6c4, - 0x01d8, 0x9686, 0x0100, 0x1130, 0x7064, 0x9005, 0x1118, 0xc6c4, - 0x0804, 0xc3a2, 0x735c, 0xab86, 0x83ff, 0x0170, 0x938a, 0x0009, - 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, 0x0018, 0x2011, - 0x0025, 0x080c, 0xca7b, 0x003e, 0xd6cc, 0x0904, 0xc3b7, 0x7154, - 0xa98a, 0x81ff, 0x0904, 0xc3b7, 0x9192, 0x0021, 0x1278, 0x8304, - 0x9098, 0x0018, 0x2011, 0x0029, 0x080c, 0xca7b, 0x2011, 0x0205, - 0x2013, 0x0000, 0x080c, 0xd5e8, 0x0804, 0xc3b7, 0xa868, 0xd0fc, - 0x0120, 0x2009, 0x0020, 0xa98a, 0x0c50, 0x00a6, 0x2950, 0x080c, - 0xca1a, 0x00ae, 0x080c, 0xd5e8, 0x080c, 0xca6b, 0x0804, 0xc3b9, - 0x080c, 0xd22a, 0x0804, 0xc3ce, 0xa87c, 0xd0ac, 0x0904, 0xc3df, - 0xa880, 0xd0bc, 0x1904, 0xc3df, 0x9684, 0x0400, 0x0130, 0xa838, - 0xab34, 0x9305, 0x0904, 0xc3df, 0x00b8, 0x7348, 0xa838, 0x9306, - 0x1198, 0x734c, 0xa834, 0x931e, 0x0904, 0xc3df, 0x0068, 0xa87c, - 0xd0ac, 0x0904, 0xc3aa, 0xa838, 0xa934, 0x9105, 0x0904, 0xc3aa, - 0xa880, 0xd0bc, 0x1904, 0xc3aa, 0x080c, 0xd267, 0x0804, 0xc3ce, - 0x00f6, 0x2079, 0x026c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x00fe, - 0x0021, 0x0005, 0x0011, 0x0005, 0x0005, 0x0096, 0x6003, 0x0002, - 0x6007, 0x0043, 0x6014, 0x2048, 0xa87c, 0xd0ac, 0x0128, 0x009e, - 0x0005, 0x2130, 0x2228, 0x0058, 0x2400, 0xa9ac, 0x910a, 0x2300, - 0xaab0, 0x9213, 0x2600, 0x9102, 0x2500, 0x9203, 0x0e90, 0xac46, - 0xab4a, 0xae36, 0xad3a, 0x6044, 0xd0fc, 0x190c, 0xad25, 0x604b, - 0x0000, 0x080c, 0x1c9c, 0x1118, 0x6144, 0x080c, 0x9643, 0x009e, - 0x0005, 0x9182, 0x0057, 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, - 0x0005, 0xc4e0, 0xc4e0, 0xc4e0, 0xc4e0, 0xc4e0, 0xc4e0, 0xc4e0, - 0xc4e0, 0xc4e0, 0xc4e0, 0xc4e2, 0xc4e0, 0xc4e0, 0xc4e0, 0xc4e0, - 0xc4f3, 0xc4e0, 0xc4e0, 0xc4e0, 0xc4e0, 0xc517, 0xc4e0, 0xc4e0, - 0x080c, 0x0d85, 0x6004, 0x9086, 0x0040, 0x1110, 0x080c, 0x99ed, - 0x2019, 0x0001, 0x080c, 0xa596, 0x6003, 0x0002, 0x080c, 0xd662, - 0x080c, 0x9a48, 0x0005, 0x6004, 0x9086, 0x0040, 0x1110, 0x080c, - 0x99ed, 0x2019, 0x0001, 0x080c, 0xa596, 0x080c, 0x9a48, 0x080c, - 0x3315, 0x080c, 0xd65a, 0x0096, 0x6114, 0x2148, 0x080c, 0xcf1b, - 0x0150, 0xa867, 0x0103, 0xa87b, 0x0029, 0xa877, 0x0000, 0x080c, - 0x7012, 0x080c, 0xd10c, 0x009e, 0x080c, 0xb16c, 0x0005, 0x080c, - 0x0d85, 0xa87b, 0x0015, 0xd1fc, 0x0180, 0xa87b, 0x0007, 0x8002, - 0x8000, 0x810a, 0x9189, 0x0000, 0x0006, 0x0016, 0x2009, 0x1a7c, - 0x2104, 0x8000, 0x200a, 0x001e, 0x000e, 0xa992, 0xa88e, 0x0005, - 0x9182, 0x0057, 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, - 0xc54f, 0xc54f, 0xc54f, 0xc54f, 0xc54f, 0xc551, 0xc54f, 0xc54f, - 0xc60e, 0xc54f, 0xc54f, 0xc54f, 0xc54f, 0xc54f, 0xc54f, 0xc54f, - 0xc54f, 0xc54f, 0xc54f, 0xc74e, 0xc54f, 0xc758, 0xc54f, 0x080c, - 0x0d85, 0x601c, 0xd0bc, 0x0178, 0xd084, 0x0168, 0xd0f4, 0x0120, - 0xc084, 0x601e, 0x0804, 0xc33e, 0x6114, 0x0096, 0x2148, 0xa87c, - 0xc0e5, 0xa87e, 0x009e, 0x0076, 0x00a6, 0x00e6, 0x0096, 0x2071, - 0x0260, 0x6114, 0x2150, 0x601c, 0xd0fc, 0x1110, 0x7644, 0x0008, - 0x9036, 0xb676, 0x96b4, 0x0fff, 0xb77c, 0xc7e5, 0xb77e, 0x6210, - 0x00b6, 0x2258, 0xba3c, 0x82ff, 0x0110, 0x8211, 0xba3e, 0x00be, - 0x86ff, 0x0904, 0xc607, 0x9694, 0xff00, 0x9284, 0x0c00, 0x0120, - 0x7048, 0xb092, 0x704c, 0xb08e, 0x9284, 0x0300, 0x0904, 0xc607, - 0x9686, 0x0100, 0x1130, 0x7064, 0x9005, 0x1118, 0xc6c4, 0xb676, - 0x0c38, 0x080c, 0x1059, 0x090c, 0x0d85, 0x2900, 0xb07a, 0xb77c, - 0x97bd, 0x0200, 0xb77e, 0xa867, 0x0103, 0xb068, 0xa86a, 0xb06c, - 0xa86e, 0xb070, 0xa872, 0x7044, 0x9084, 0xf000, 0x9635, 0xae76, - 0x968c, 0x0c00, 0x0120, 0x7348, 0xab92, 0x734c, 0xab8e, 0x968c, - 0x00ff, 0x9186, 0x0002, 0x0180, 0x9186, 0x0028, 0x1118, 0xa87b, - 0x001c, 0x0060, 0xd6dc, 0x0118, 0xa87b, 0x0015, 0x0038, 0xd6d4, - 0x0118, 0xa87b, 0x0007, 0x0010, 0xa87b, 0x0000, 0xaf7e, 0xb080, - 0xa882, 0xb084, 0xa886, 0x901e, 0xd6c4, 0x0190, 0x735c, 0xab86, - 0x83ff, 0x0170, 0x938a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, - 0x2308, 0x2019, 0x0018, 0x2011, 0x0025, 0x080c, 0xca7b, 0x003e, - 0xd6cc, 0x01e8, 0x7154, 0xa98a, 0x81ff, 0x01c8, 0x9192, 0x0021, - 0x1260, 0x8304, 0x9098, 0x0018, 0x2011, 0x0029, 0x080c, 0xca7b, - 0x2011, 0x0205, 0x2013, 0x0000, 0x0050, 0xb068, 0xd0fc, 0x0120, - 0x2009, 0x0020, 0xa98a, 0x0c68, 0x2950, 0x080c, 0xca1a, 0x080c, - 0x1a9f, 0x009e, 0x00ee, 0x00ae, 0x007e, 0x0005, 0x2001, 0x1988, - 0x2004, 0x604a, 0x0096, 0x6114, 0x2148, 0xa83c, 0xa940, 0x9105, - 0x1118, 0xa87c, 0xc0dc, 0xa87e, 0x6003, 0x0002, 0x080c, 0xd66b, - 0x0904, 0xc749, 0x604b, 0x0000, 0x6010, 0x00b6, 0x2058, 0xb800, - 0x00be, 0xd0bc, 0x1500, 0xd1cc, 0x0904, 0xc70d, 0xa978, 0xa868, - 0xd0fc, 0x0904, 0xc6ce, 0x0016, 0xa87c, 0x0006, 0xa880, 0x0006, - 0x00a6, 0x2150, 0xb174, 0x9184, 0x00ff, 0x90b6, 0x0002, 0x0904, - 0xc69b, 0x9086, 0x0028, 0x1904, 0xc687, 0xa87b, 0x001c, 0xb07b, - 0x001c, 0x0804, 0xc6a3, 0x6024, 0xd0f4, 0x11d0, 0xa838, 0xaa34, - 0x9205, 0x09c8, 0xa838, 0xaa90, 0x9206, 0x1120, 0xa88c, 0xaa34, - 0x9206, 0x0988, 0x6024, 0xd0d4, 0x1148, 0xa9ac, 0xa834, 0x9102, - 0x603a, 0xa9b0, 0xa838, 0x9103, 0x603e, 0x6024, 0xc0f5, 0x6026, - 0x6010, 0x00b6, 0x2058, 0xb83c, 0x8000, 0xb83e, 0x00be, 0x601c, - 0xc0fc, 0x601e, 0x9006, 0xa876, 0xa892, 0xa88e, 0xa87c, 0xc0e4, - 0xa87e, 0xd0cc, 0x0140, 0xc0cc, 0xa87e, 0x0096, 0xa878, 0x2048, - 0x080c, 0x100b, 0x009e, 0x080c, 0xd267, 0x0804, 0xc749, 0xd1dc, - 0x0158, 0xa87b, 0x0015, 0xb07b, 0x0015, 0x080c, 0xd508, 0x0118, - 0xb174, 0xc1dc, 0xb176, 0x0078, 0xd1d4, 0x0128, 0xa87b, 0x0007, - 0xb07b, 0x0007, 0x0040, 0xa87c, 0xd0ac, 0x0128, 0xa834, 0xa938, - 0x9115, 0x190c, 0xc519, 0xa87c, 0xb07e, 0xa890, 0xb092, 0xa88c, - 0xb08e, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0019, 0x20a0, 0x20a9, - 0x0020, 0x8a06, 0x8006, 0x8007, 0x9094, 0x003f, 0x22e0, 0x9084, - 0xffc0, 0x9080, 0x0019, 0x2098, 0x4003, 0x00ae, 0x000e, 0xa882, - 0x000e, 0xc0cc, 0xa87e, 0x080c, 0xd5e8, 0x001e, 0xa874, 0x0006, - 0x2148, 0x080c, 0x100b, 0x001e, 0x0804, 0xc73a, 0x0016, 0x00a6, - 0x2150, 0xb174, 0x9184, 0x00ff, 0x90b6, 0x0002, 0x01e0, 0x9086, - 0x0028, 0x1128, 0xa87b, 0x001c, 0xb07b, 0x001c, 0x00e0, 0xd1dc, - 0x0158, 0xa87b, 0x0015, 0xb07b, 0x0015, 0x080c, 0xd508, 0x0118, - 0xb174, 0xc1dc, 0xb176, 0x0078, 0xd1d4, 0x0128, 0xa87b, 0x0007, - 0xb07b, 0x0007, 0x0040, 0xa87c, 0xd0ac, 0x0128, 0xa834, 0xa938, - 0x9115, 0x190c, 0xc519, 0xa890, 0xb092, 0xa88c, 0xb08e, 0xa87c, - 0xb07e, 0x00ae, 0x080c, 0x100b, 0x009e, 0x080c, 0xd5e8, 0xa974, - 0x0016, 0x080c, 0xca6b, 0x001e, 0x0468, 0xa867, 0x0103, 0xa974, - 0x9184, 0x00ff, 0x90b6, 0x0002, 0x01b0, 0x9086, 0x0028, 0x1118, - 0xa87b, 0x001c, 0x00d0, 0xd1dc, 0x0148, 0xa87b, 0x0015, 0x080c, - 0xd508, 0x0118, 0xa974, 0xc1dc, 0xa976, 0x0078, 0xd1d4, 0x0118, - 0xa87b, 0x0007, 0x0050, 0xa87b, 0x0000, 0xa87c, 0xd0ac, 0x0128, - 0xa834, 0xa938, 0x9115, 0x190c, 0xc519, 0xa974, 0x0016, 0x080c, - 0x6e27, 0x001e, 0x6010, 0x00b6, 0x2058, 0xba3c, 0xb8d0, 0x0016, - 0x9005, 0x190c, 0x68df, 0x001e, 0x00be, 0xd1e4, 0x1120, 0x080c, - 0xb16c, 0x009e, 0x0005, 0x080c, 0xd22a, 0x0cd8, 0x6114, 0x0096, - 0x2148, 0xa97c, 0x080c, 0xd66b, 0x190c, 0x1abf, 0x009e, 0x0005, - 0x0096, 0x6114, 0x2148, 0xa83c, 0xa940, 0x9105, 0x01e8, 0xa877, - 0x0000, 0xa87b, 0x0000, 0xa867, 0x0103, 0x00b6, 0x6010, 0x2058, - 0xa834, 0xa938, 0x9115, 0x11a0, 0x080c, 0x6e27, 0xba3c, 0x8211, - 0x0208, 0xba3e, 0xb8d0, 0x9005, 0x0110, 0x080c, 0x68df, 0x080c, - 0xb16c, 0x00be, 0x009e, 0x0005, 0xa87c, 0xc0dc, 0xa87e, 0x08f8, - 0xb800, 0xd0bc, 0x1120, 0xa834, 0x080c, 0xc519, 0x0c28, 0xa880, - 0xd0bc, 0x1dc8, 0x080c, 0xd267, 0x0c60, 0x080c, 0x99ed, 0x0010, - 0x080c, 0x9a48, 0x601c, 0xd084, 0x0110, 0x080c, 0x1ad3, 0x080c, - 0xcf1b, 0x01f0, 0x0096, 0x6114, 0x2148, 0x080c, 0xd132, 0x1118, - 0x080c, 0xbb5c, 0x00a0, 0xa867, 0x0103, 0x2009, 0x180c, 0x210c, - 0xd18c, 0x1198, 0xd184, 0x1170, 0x6108, 0xa97a, 0x918e, 0x0029, - 0x1110, 0x080c, 0xeddf, 0xa877, 0x0000, 0x080c, 0x7012, 0x009e, - 0x0804, 0xb1a7, 0xa87b, 0x0004, 0x0cb0, 0xa87b, 0x0004, 0x0c98, - 0x9182, 0x0057, 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, - 0xc7df, 0xc7df, 0xc7df, 0xc7df, 0xc7df, 0xc7e1, 0xc7df, 0xc7df, - 0xc7df, 0xc7df, 0xc7df, 0xc7df, 0xc7df, 0xc7df, 0xc7df, 0xc7df, - 0xc7df, 0xc7df, 0xc7df, 0xc7df, 0xc805, 0xc7df, 0xc7df, 0x080c, - 0x0d85, 0x080c, 0x5848, 0x01f8, 0x6014, 0x7144, 0x918c, 0x0fff, - 0x9016, 0xd1c4, 0x0118, 0x7264, 0x9294, 0x00ff, 0x0096, 0x904d, - 0x0188, 0xa87b, 0x0000, 0xa864, 0x9086, 0x0139, 0x0128, 0xa867, - 0x0103, 0xa976, 0xaa96, 0x0030, 0xa897, 0x4000, 0xa99a, 0xaa9e, - 0x080c, 0x7012, 0x009e, 0x0804, 0xb16c, 0x080c, 0x5848, 0x0dd8, - 0x6014, 0x900e, 0x9016, 0x0c10, 0x9182, 0x0085, 0x0002, 0xc81e, - 0xc81c, 0xc81c, 0xc82a, 0xc81c, 0xc81c, 0xc81c, 0xc81c, 0xc81c, - 0xc81c, 0xc81c, 0xc81c, 0xc81c, 0x080c, 0x0d85, 0x6003, 0x0001, - 0x6106, 0x0126, 0x2091, 0x8000, 0x2009, 0x8020, 0x080c, 0x9617, - 0x012e, 0x0005, 0x0026, 0x0056, 0x00d6, 0x00e6, 0x2071, 0x0260, - 0x7224, 0x6216, 0x7220, 0x080c, 0xcf09, 0x01f8, 0x2268, 0x6800, - 0x9086, 0x0000, 0x01d0, 0x6010, 0x6d10, 0x952e, 0x11b0, 0x00c6, - 0x2d60, 0x00d6, 0x080c, 0xcadc, 0x00de, 0x00ce, 0x0158, 0x702c, - 0xd084, 0x1118, 0x080c, 0xcaa6, 0x0010, 0x6803, 0x0002, 0x6007, - 0x0086, 0x0028, 0x080c, 0xcac8, 0x0d90, 0x6007, 0x0087, 0x6003, - 0x0001, 0x2009, 0x8020, 0x080c, 0x9617, 0x7220, 0x080c, 0xcf09, - 0x0178, 0x6810, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0140, - 0x6824, 0xd0ec, 0x0128, 0x00c6, 0x2d60, 0x080c, 0xd267, 0x00ce, - 0x00ee, 0x00de, 0x005e, 0x002e, 0x0005, 0x9186, 0x0013, 0x1160, - 0x6004, 0x908a, 0x0085, 0x0a0c, 0x0d85, 0x908a, 0x0092, 0x1a0c, - 0x0d85, 0x9082, 0x0085, 0x00e2, 0x9186, 0x0027, 0x0120, 0x9186, - 0x0014, 0x190c, 0x0d85, 0x080c, 0x99ed, 0x0096, 0x6014, 0x2048, - 0x080c, 0xcf1b, 0x0140, 0xa867, 0x0103, 0xa877, 0x0000, 0xa87b, - 0x0029, 0x080c, 0x7012, 0x009e, 0x080c, 0xb1a7, 0x0804, 0x9ab3, - 0xc8ad, 0xc8af, 0xc8af, 0xc8ad, 0xc8ad, 0xc8ad, 0xc8ad, 0xc8ad, - 0xc8ad, 0xc8ad, 0xc8ad, 0xc8ad, 0xc8ad, 0x080c, 0x0d85, 0x080c, - 0xb1a7, 0x0005, 0x9186, 0x0013, 0x1130, 0x6004, 0x9082, 0x0085, - 0x2008, 0x0804, 0xc8fe, 0x9186, 0x0027, 0x1558, 0x080c, 0x99ed, - 0x080c, 0x3315, 0x080c, 0xd65a, 0x0096, 0x6014, 0x2048, 0x080c, - 0xcf1b, 0x0150, 0xa867, 0x0103, 0xa877, 0x0000, 0xa87b, 0x0029, - 0x080c, 0x7012, 0x080c, 0xd10c, 0x009e, 0x080c, 0xb16c, 0x0005, - 0x9186, 0x0089, 0x0118, 0x9186, 0x008a, 0x1140, 0x080c, 0xaf61, - 0x0128, 0x9086, 0x000c, 0x0904, 0xc936, 0x0000, 0x080c, 0xb227, - 0x0c70, 0x9186, 0x0014, 0x1d60, 0x080c, 0x99ed, 0x0096, 0x6014, - 0x2048, 0x080c, 0xcf1b, 0x0d00, 0xa867, 0x0103, 0xa877, 0x0000, - 0xa87b, 0x0006, 0xa880, 0xc0ec, 0xa882, 0x0890, 0x0002, 0xc90e, - 0xc90c, 0xc90c, 0xc90c, 0xc90c, 0xc90c, 0xc922, 0xc90c, 0xc90c, - 0xc90c, 0xc90c, 0xc90c, 0xc90c, 0x080c, 0x0d85, 0x6034, 0x908c, - 0xff00, 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, - 0x2001, 0x1986, 0x0010, 0x2001, 0x1987, 0x2004, 0x601a, 0x6003, - 0x000c, 0x0005, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0039, - 0x0118, 0x9186, 0x0035, 0x1118, 0x2001, 0x1986, 0x0010, 0x2001, - 0x1987, 0x2004, 0x601a, 0x6003, 0x000e, 0x0005, 0x9182, 0x0092, - 0x1220, 0x9182, 0x0085, 0x0208, 0x0012, 0x0804, 0xb227, 0xc94c, - 0xc94c, 0xc94c, 0xc94c, 0xc94e, 0xc99b, 0xc94c, 0xc94c, 0xc94c, - 0xc94c, 0xc94c, 0xc94c, 0xc94c, 0x080c, 0x0d85, 0x0096, 0x6010, - 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0168, 0x6034, 0x908c, - 0xff00, 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, - 0x009e, 0x0804, 0xc9af, 0x080c, 0xcf1b, 0x1118, 0x080c, 0xd10c, - 0x0068, 0x6014, 0x2048, 0x080c, 0xd671, 0x1110, 0x080c, 0xd10c, - 0xa867, 0x0103, 0x080c, 0xd625, 0x080c, 0x7012, 0x00d6, 0x2c68, - 0x080c, 0xb116, 0x01d0, 0x6003, 0x0001, 0x6007, 0x001e, 0x600b, - 0xffff, 0x2009, 0x026e, 0x210c, 0x613a, 0x2009, 0x026f, 0x210c, - 0x613e, 0x6910, 0x6112, 0x080c, 0xd3b6, 0x695c, 0x615e, 0x6023, - 0x0001, 0x2009, 0x8020, 0x080c, 0x9617, 0x2d60, 0x00de, 0x080c, - 0xb16c, 0x009e, 0x0005, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, - 0xd0bc, 0x05a0, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0035, - 0x0130, 0x9186, 0x001e, 0x0118, 0x9186, 0x0039, 0x1538, 0x00d6, - 0x2c68, 0x080c, 0xd5bb, 0x11f0, 0x080c, 0xb116, 0x01d8, 0x6106, - 0x6003, 0x0001, 0x6023, 0x0001, 0x6910, 0x6112, 0x692c, 0x612e, - 0x6930, 0x6132, 0x6934, 0x918c, 0x00ff, 0x6136, 0x6938, 0x613a, - 0x693c, 0x613e, 0x695c, 0x615e, 0x080c, 0xd3b6, 0x2009, 0x8020, - 0x080c, 0x9617, 0x2d60, 0x00de, 0x0804, 0xb16c, 0x0096, 0x6014, - 0x2048, 0x080c, 0xcf1b, 0x01c8, 0xa867, 0x0103, 0xa880, 0xd0b4, - 0x0128, 0xc0ec, 0xa882, 0xa87b, 0x0006, 0x0048, 0xd0bc, 0x0118, - 0xa87b, 0x0002, 0x0020, 0xa87b, 0x0005, 0x080c, 0xd226, 0xa877, - 0x0000, 0x080c, 0x7012, 0x080c, 0xd10c, 0x009e, 0x0804, 0xb16c, - 0x0016, 0x0096, 0x6014, 0x2048, 0x080c, 0xcf1b, 0x0140, 0xa867, - 0x0103, 0xa87b, 0x0028, 0xa877, 0x0000, 0x080c, 0x7012, 0x009e, - 0x001e, 0x9186, 0x0013, 0x0158, 0x9186, 0x0014, 0x0130, 0x9186, - 0x0027, 0x0118, 0x080c, 0xb227, 0x0020, 0x080c, 0x99ed, 0x080c, - 0xb1a7, 0x0005, 0x0056, 0x0066, 0x0096, 0x00a6, 0x2029, 0x0001, - 0x9182, 0x0101, 0x1208, 0x0010, 0x2009, 0x0100, 0x2130, 0x8304, - 0x9098, 0x0018, 0x2009, 0x0020, 0x2011, 0x0029, 0x080c, 0xca7b, - 0x96b2, 0x0020, 0xb004, 0x904d, 0x0110, 0x080c, 0x100b, 0x080c, - 0x1059, 0x0520, 0x8528, 0xa867, 0x0110, 0xa86b, 0x0000, 0x2920, - 0xb406, 0x968a, 0x003d, 0x1228, 0x2608, 0x2011, 0x001b, 0x0499, - 0x00a8, 0x96b2, 0x003c, 0x2009, 0x003c, 0x2950, 0x2011, 0x001b, - 0x0451, 0x0c28, 0x2001, 0x0205, 0x2003, 0x0000, 0x00ae, 0x852f, - 0x95ad, 0x0003, 0xb566, 0x95ac, 0x0000, 0x0048, 0x2001, 0x0205, - 0x2003, 0x0000, 0x00ae, 0x852f, 0x95ad, 0x0003, 0xb566, 0x009e, - 0x006e, 0x005e, 0x0005, 0x00a6, 0x89ff, 0x0158, 0xa804, 0x9055, - 0x0130, 0xa807, 0x0000, 0x080c, 0x7012, 0x2a48, 0x0cb8, 0x080c, - 0x7012, 0x00ae, 0x0005, 0x00f6, 0x2079, 0x0200, 0x7814, 0x9085, - 0x0080, 0x7816, 0xd184, 0x0108, 0x8108, 0x810c, 0x20a9, 0x0001, - 0xa860, 0x20e8, 0xa85c, 0x9200, 0x20a0, 0x20e1, 0x0000, 0x2300, - 0x9e00, 0x2098, 0x4003, 0x8318, 0x9386, 0x0020, 0x1148, 0x2018, - 0x2300, 0x9e00, 0x2098, 0x7814, 0x8000, 0x9085, 0x0080, 0x7816, - 0x8109, 0x1d80, 0x7817, 0x0000, 0x00fe, 0x0005, 0x6920, 0x9186, - 0x0003, 0x0118, 0x9186, 0x0002, 0x11d0, 0x00c6, 0x00d6, 0x00e6, - 0x2d60, 0x0096, 0x6014, 0x2048, 0x080c, 0xcf1b, 0x0150, 0x2001, - 0x0006, 0xa980, 0xc1d5, 0x080c, 0x725e, 0x080c, 0x7006, 0x080c, - 0xd10c, 0x009e, 0x080c, 0xb1a7, 0x00ee, 0x00de, 0x00ce, 0x0005, - 0x00c6, 0x702c, 0xd084, 0x1170, 0x6008, 0x2060, 0x6020, 0x9086, - 0x0002, 0x1140, 0x6104, 0x9186, 0x0085, 0x0118, 0x9186, 0x008b, - 0x1108, 0x9006, 0x00ce, 0x0005, 0x0066, 0x0126, 0x2091, 0x8000, - 0x2031, 0x0001, 0x6020, 0x9084, 0x000f, 0x0083, 0x012e, 0x006e, - 0x0005, 0x0126, 0x2091, 0x8000, 0x0066, 0x2031, 0x0000, 0x6020, - 0x9084, 0x000f, 0x001b, 0x006e, 0x012e, 0x0005, 0xcb2a, 0xcb2a, - 0xcb25, 0xcb4e, 0xcb06, 0xcb25, 0xcb08, 0xcb25, 0xcb25, 0x9458, - 0xcb25, 0xcb25, 0xcb25, 0xcb06, 0xcb06, 0xcb06, 0x080c, 0x0d85, - 0x6010, 0x9080, 0x0000, 0x2004, 0xd0bc, 0x190c, 0xcb4e, 0x0036, - 0x6014, 0x0096, 0x2048, 0xa880, 0x009e, 0xd0cc, 0x0118, 0x2019, - 0x000c, 0x0038, 0xd094, 0x0118, 0x2019, 0x000d, 0x0010, 0x2019, - 0x0010, 0x080c, 0xe578, 0x003e, 0x0005, 0x9006, 0x0005, 0x9085, - 0x0001, 0x0005, 0x0096, 0x86ff, 0x11e8, 0x6014, 0x2048, 0x080c, - 0xcf1b, 0x01d0, 0x6043, 0xffff, 0xa864, 0x9086, 0x0139, 0x1128, - 0xa87b, 0x0005, 0xa883, 0x0000, 0x0028, 0x900e, 0x2001, 0x0005, - 0x080c, 0x725e, 0x080c, 0xd226, 0x080c, 0x7006, 0x080c, 0xb1a7, - 0x9085, 0x0001, 0x009e, 0x0005, 0x9006, 0x0ce0, 0x080c, 0xacfc, - 0x080c, 0xd67f, 0x908a, 0x0010, 0x1a0c, 0x0d85, 0x002b, 0x0106, - 0x080c, 0xad18, 0x010e, 0x0005, 0xcb6c, 0xcb9c, 0xcb6e, 0xcbc3, - 0xcb97, 0xcb6c, 0xcb25, 0xcb2a, 0xcb2a, 0xcb25, 0xcb25, 0xcb25, - 0xcb25, 0xcb25, 0xcb25, 0xcb25, 0x080c, 0x0d85, 0x86ff, 0x1520, - 0x6020, 0x9086, 0x0006, 0x0500, 0x0096, 0x6014, 0x2048, 0x080c, - 0xcf1b, 0x0168, 0xa87c, 0xd0cc, 0x0140, 0x0096, 0xc0cc, 0xa87e, - 0xa878, 0x2048, 0x080c, 0x100b, 0x009e, 0x080c, 0xd226, 0x009e, - 0x080c, 0xd5ff, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, - 0x2009, 0x8020, 0x080c, 0x95f9, 0x9085, 0x0001, 0x0005, 0x0066, - 0x080c, 0x1ad3, 0x006e, 0x0890, 0x00e6, 0x2071, 0x19e8, 0x7030, - 0x9c06, 0x1120, 0x080c, 0xa516, 0x00ee, 0x0840, 0x6020, 0x9084, - 0x000f, 0x9086, 0x0006, 0x1150, 0x0086, 0x0096, 0x2049, 0x0001, - 0x2c40, 0x080c, 0xa667, 0x009e, 0x008e, 0x0040, 0x0066, 0x080c, - 0xa412, 0x190c, 0x0d85, 0x080c, 0xa420, 0x006e, 0x00ee, 0x1904, - 0xcb6e, 0x0804, 0xcb25, 0x0036, 0x00e6, 0x2071, 0x19e8, 0x704c, - 0x9c06, 0x1138, 0x901e, 0x080c, 0xa596, 0x00ee, 0x003e, 0x0804, - 0xcb6e, 0x080c, 0xa7a1, 0x00ee, 0x003e, 0x1904, 0xcb6e, 0x0804, - 0xcb25, 0x00c6, 0x0066, 0x6020, 0x9084, 0x000f, 0x001b, 0x006e, - 0x00ce, 0x0005, 0xcbf9, 0xcce2, 0xce50, 0xcc01, 0xb1a7, 0xcbf9, - 0xe56e, 0xd667, 0xcce2, 0x941f, 0xcedc, 0xcbf2, 0xcbf2, 0xcbf2, - 0xcbf2, 0xcbf2, 0x080c, 0x0d85, 0x080c, 0xd132, 0x1110, 0x080c, - 0xbb5c, 0x0005, 0x080c, 0x99ed, 0x0804, 0xb16c, 0x601b, 0x0001, - 0x0005, 0x080c, 0xcf1b, 0x0130, 0x6014, 0x0096, 0x2048, 0x2c00, - 0xa896, 0x009e, 0x080c, 0xacfc, 0x080c, 0xd67f, 0x908a, 0x0010, - 0x1a0c, 0x0d85, 0x0013, 0x0804, 0xad18, 0xcc25, 0xcc27, 0xcc51, - 0xcc65, 0xcc92, 0xcc25, 0xcbf9, 0xcbf9, 0xcbf9, 0xcc6c, 0xcc6c, - 0xcc25, 0xcc25, 0xcc25, 0xcc25, 0xcc76, 0x080c, 0x0d85, 0x00e6, - 0x6014, 0x0096, 0x2048, 0xa880, 0xc0b5, 0xa882, 0x009e, 0x2071, - 0x19e8, 0x7030, 0x9c06, 0x01d0, 0x0066, 0x080c, 0xa412, 0x190c, - 0x0d85, 0x080c, 0xa420, 0x006e, 0x080c, 0xd5ff, 0x6007, 0x0085, - 0x6003, 0x000b, 0x6023, 0x0002, 0x2001, 0x1987, 0x2004, 0x601a, - 0x2009, 0x8020, 0x080c, 0x95f9, 0x00ee, 0x0005, 0x601b, 0x0001, - 0x0cd8, 0x0096, 0x6014, 0x2048, 0xa880, 0xc0b5, 0xa882, 0x009e, - 0x080c, 0xd5ff, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, - 0x2009, 0x8020, 0x080c, 0x95f9, 0x0005, 0x080c, 0xacfc, 0x080c, - 0xaee3, 0x080c, 0xad18, 0x0c28, 0x0096, 0x601b, 0x0001, 0x6014, - 0x2048, 0xa880, 0xc0b5, 0xa882, 0x009e, 0x0005, 0x080c, 0x5848, - 0x01b8, 0x6014, 0x0096, 0x904d, 0x0190, 0xa864, 0xa867, 0x0103, - 0xa87b, 0x0006, 0x9086, 0x0139, 0x1150, 0xa867, 0x0139, 0xa87b, - 0x0030, 0xa897, 0x4005, 0xa89b, 0x0004, 0x080c, 0x7012, 0x009e, - 0x0804, 0xb16c, 0x6014, 0x0096, 0x904d, 0x0904, 0xccdd, 0xa97c, - 0xd1e4, 0x1160, 0x611c, 0xd1fc, 0x0904, 0xccdd, 0x6110, 0x00b6, - 0x2158, 0xb93c, 0x8109, 0x0208, 0xb93e, 0x00be, 0x080c, 0xad18, - 0x2001, 0x180f, 0x2004, 0xd0c4, 0x0110, 0x009e, 0x0005, 0xa884, - 0x009e, 0x8003, 0x800b, 0x810b, 0x9108, 0x611a, 0x2001, 0x0030, - 0x2c08, 0x080c, 0x16b9, 0x2001, 0x030c, 0x2004, 0x9086, 0x0041, - 0x1198, 0x6014, 0x0096, 0x904d, 0x090c, 0x0d85, 0xa880, 0xd0f4, - 0x1130, 0xc0f5, 0xa882, 0x009e, 0x601b, 0x0002, 0x0068, 0x009e, - 0x00c6, 0x080c, 0x2185, 0x00ce, 0x6000, 0x9086, 0x0004, 0x1120, - 0x2009, 0x0048, 0x080c, 0xb20a, 0x0005, 0x009e, 0x080c, 0x1ad3, - 0x0804, 0xcc51, 0x6000, 0x908a, 0x0010, 0x1a0c, 0x0d85, 0x000b, - 0x0005, 0xccf9, 0xcbfe, 0xccfb, 0xccf9, 0xccfb, 0xccfb, 0xcbfa, - 0xccf9, 0xcbf4, 0xcbf4, 0xccf9, 0xccf9, 0xccf9, 0xccf9, 0xccf9, - 0xccf9, 0x080c, 0x0d85, 0x6010, 0x00b6, 0x2058, 0xb804, 0x9084, - 0x00ff, 0x00be, 0x908a, 0x000c, 0x1a0c, 0x0d85, 0x00b6, 0x0013, - 0x00be, 0x0005, 0xcd16, 0xcde7, 0xcd18, 0xcd58, 0xcd18, 0xcd58, - 0xcd18, 0xcd26, 0xcd16, 0xcd58, 0xcd16, 0xcd47, 0x080c, 0x0d85, - 0x6004, 0x908e, 0x0016, 0x05c0, 0x908e, 0x0004, 0x05a8, 0x908e, - 0x0002, 0x0590, 0x908e, 0x0052, 0x0904, 0xcde3, 0x6004, 0x080c, - 0xd132, 0x0904, 0xce00, 0x908e, 0x0004, 0x1110, 0x080c, 0x3344, - 0x908e, 0x0021, 0x0904, 0xce04, 0x908e, 0x0022, 0x0904, 0xce4b, - 0x908e, 0x003d, 0x0904, 0xce04, 0x908e, 0x0039, 0x0904, 0xce08, - 0x908e, 0x0035, 0x0904, 0xce08, 0x908e, 0x001e, 0x0178, 0x908e, - 0x0001, 0x1140, 0x6010, 0x2058, 0xb804, 0x9084, 0x00ff, 0x9086, - 0x0006, 0x0110, 0x080c, 0x3315, 0x080c, 0xbb5c, 0x0804, 0xb1a7, - 0x00c6, 0x00d6, 0x6104, 0x9186, 0x0016, 0x0904, 0xcdd4, 0x9186, - 0x0002, 0x1904, 0xcda9, 0x2001, 0x1837, 0x2004, 0xd08c, 0x11c8, - 0x080c, 0x779e, 0x11b0, 0x080c, 0xd645, 0x0138, 0x080c, 0x77c1, - 0x1120, 0x080c, 0x76a7, 0x0804, 0xce34, 0x2001, 0x197d, 0x2003, - 0x0001, 0x2001, 0x1800, 0x2003, 0x0001, 0x080c, 0x76cd, 0x0804, - 0xce34, 0x6010, 0x2058, 0xb8a0, 0x9086, 0x0080, 0x0130, 0x2001, - 0x1837, 0x2004, 0xd0ac, 0x1904, 0xce34, 0xb8a0, 0x9082, 0x0081, - 0x1a04, 0xce34, 0xb840, 0x9084, 0x00ff, 0x9005, 0x0190, 0x8001, - 0xb842, 0x6017, 0x0000, 0x6023, 0x0007, 0x601b, 0x0398, 0x604b, - 0x0000, 0x080c, 0xb116, 0x0128, 0x2b00, 0x6012, 0x6023, 0x0001, - 0x0458, 0x00de, 0x00ce, 0x6004, 0x908e, 0x0002, 0x11a0, 0x6010, - 0x2058, 0xb8a0, 0x9086, 0x007e, 0x1170, 0x2009, 0x1837, 0x2104, - 0xc085, 0x200a, 0x00e6, 0x2071, 0x1800, 0x080c, 0x6130, 0x00ee, - 0x080c, 0xbb5c, 0x0030, 0x080c, 0xbb5c, 0x080c, 0x3315, 0x080c, - 0xd65a, 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x3344, 0x012e, - 0x00ee, 0x080c, 0xb1a7, 0x0005, 0x2001, 0x0002, 0x080c, 0x66fa, - 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x961e, 0x080c, 0x9ab3, - 0x00de, 0x00ce, 0x0c80, 0x080c, 0x3344, 0x0804, 0xcd54, 0x00c6, - 0x00d6, 0x6104, 0x9186, 0x0016, 0x0d38, 0x6010, 0x2058, 0xb840, - 0x9084, 0x00ff, 0x9005, 0x0904, 0xcda9, 0x8001, 0xb842, 0x6003, - 0x0001, 0x080c, 0x961e, 0x080c, 0x9ab3, 0x00de, 0x00ce, 0x0898, - 0x080c, 0xbb5c, 0x0804, 0xcd56, 0x080c, 0xbb98, 0x0804, 0xcd56, - 0x00d6, 0x2c68, 0x6104, 0x080c, 0xd5bb, 0x00de, 0x0118, 0x080c, - 0xb16c, 0x0408, 0x6004, 0x8007, 0x6134, 0x918c, 0x00ff, 0x9105, - 0x6036, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x603c, - 0x600a, 0x2001, 0x1987, 0x2004, 0x601a, 0x602c, 0x2c08, 0x2060, - 0x6024, 0xd0b4, 0x0108, 0xc085, 0xc0b5, 0x6026, 0x2160, 0x2009, - 0x8020, 0x080c, 0x9617, 0x0005, 0x00de, 0x00ce, 0x080c, 0xbb5c, - 0x080c, 0x3315, 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x3344, - 0x6017, 0x0000, 0x6023, 0x0007, 0x601b, 0x0398, 0x604b, 0x0000, - 0x012e, 0x00ee, 0x0005, 0x080c, 0xb5a8, 0x1904, 0xce00, 0x0005, - 0x6000, 0x908a, 0x0010, 0x1a0c, 0x0d85, 0x0096, 0x00d6, 0x001b, - 0x00de, 0x009e, 0x0005, 0xce6b, 0xce6b, 0xce6b, 0xce6b, 0xce6b, - 0xce6b, 0xce6b, 0xce6b, 0xce6b, 0xcbf9, 0xce6b, 0xcbfe, 0xce6d, - 0xcbfe, 0xce87, 0xce6b, 0x080c, 0x0d85, 0x6004, 0x9086, 0x008b, - 0x01b0, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0035, 0x1130, - 0x602c, 0x9080, 0x0009, 0x200c, 0xc185, 0x2102, 0x6007, 0x008b, - 0x6003, 0x000d, 0x2009, 0x8020, 0x080c, 0x9617, 0x0005, 0x080c, - 0xd639, 0x0118, 0x080c, 0xd64c, 0x0010, 0x080c, 0xd65a, 0x080c, - 0xd10c, 0x080c, 0xcf1b, 0x0570, 0x080c, 0x3315, 0x080c, 0xcf1b, - 0x0168, 0x6014, 0x2048, 0xa867, 0x0103, 0xa87b, 0x0006, 0xa877, - 0x0000, 0xa880, 0xc0ed, 0xa882, 0x080c, 0x7012, 0x2c68, 0x080c, - 0xb116, 0x0150, 0x6810, 0x6012, 0x080c, 0xd3b6, 0x00c6, 0x2d60, - 0x080c, 0xb1a7, 0x00ce, 0x0008, 0x2d60, 0x6017, 0x0000, 0x6023, - 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x961e, 0x080c, - 0x9ab3, 0x00c8, 0x080c, 0xd639, 0x0138, 0x6034, 0x9086, 0x4000, - 0x1118, 0x080c, 0x3315, 0x08d0, 0x6034, 0x908c, 0xff00, 0x810f, - 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, 0x080c, 0x3315, - 0x0868, 0x080c, 0xb1a7, 0x0005, 0x6000, 0x908a, 0x0010, 0x1a0c, - 0x0d85, 0x0002, 0xcef2, 0xcef2, 0xcefa, 0xcef4, 0xcf04, 0xcef2, - 0xcef2, 0xb1a7, 0xcef2, 0xcef2, 0xcef2, 0xcef2, 0xcef2, 0xcef2, - 0xcef2, 0xcef2, 0x080c, 0x0d85, 0x080c, 0xacfc, 0x080c, 0xaee3, - 0x080c, 0xad18, 0x6114, 0x0096, 0x2148, 0xa87b, 0x0006, 0x080c, - 0x7012, 0x009e, 0x0804, 0xb16c, 0x601c, 0xd084, 0x190c, 0x1ad3, - 0x0c88, 0x9284, 0x0003, 0x1158, 0x9282, 0x1ddc, 0x0240, 0x2001, - 0x181a, 0x2004, 0x9202, 0x1218, 0x9085, 0x0001, 0x0005, 0x9006, - 0x0ce8, 0x0096, 0x0028, 0x0096, 0x0006, 0x6014, 0x2048, 0x000e, - 0x0006, 0x9984, 0xf000, 0x9086, 0xf000, 0x0110, 0x080c, 0x1104, - 0x000e, 0x009e, 0x0005, 0x00e6, 0x00c6, 0x0036, 0x0006, 0x0126, - 0x2091, 0x8000, 0x2061, 0x1ddc, 0x2071, 0x1800, 0x7354, 0x7074, - 0x9302, 0x1640, 0x6020, 0x9206, 0x11f8, 0x080c, 0xd645, 0x0180, - 0x9286, 0x0001, 0x1168, 0x6004, 0x9086, 0x0004, 0x1148, 0x080c, - 0x3315, 0x080c, 0xd65a, 0x00c6, 0x080c, 0xb1a7, 0x00ce, 0x0060, - 0x080c, 0xd328, 0x0148, 0x080c, 0xd132, 0x1110, 0x080c, 0xbb5c, - 0x00c6, 0x080c, 0xb16c, 0x00ce, 0x9ce0, 0x001c, 0x7068, 0x9c02, - 0x1208, 0x08a0, 0x012e, 0x000e, 0x003e, 0x00ce, 0x00ee, 0x0005, - 0x00e6, 0x00c6, 0x0016, 0x9188, 0x1000, 0x210c, 0x81ff, 0x0128, - 0x2061, 0x1b39, 0x6112, 0x080c, 0x3315, 0x9006, 0x0010, 0x9085, - 0x0001, 0x001e, 0x00ce, 0x00ee, 0x0005, 0x00c6, 0x0126, 0x2091, - 0x8000, 0x080c, 0xb116, 0x01b0, 0x665e, 0x2b00, 0x6012, 0x080c, - 0x5848, 0x0118, 0x080c, 0xd04e, 0x0168, 0x080c, 0xd3b6, 0x6023, - 0x0003, 0x2009, 0x004b, 0x080c, 0xb20a, 0x9085, 0x0001, 0x012e, - 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, - 0xbaa0, 0x080c, 0xb1dd, 0x0580, 0x605f, 0x0000, 0x2b00, 0x6012, - 0x080c, 0xd3b6, 0x6023, 0x0003, 0x0016, 0x080c, 0xacfc, 0x080c, - 0x97b0, 0x0076, 0x903e, 0x080c, 0x966d, 0x2c08, 0x080c, 0xe75d, - 0x007e, 0x080c, 0xad18, 0x001e, 0xd184, 0x0128, 0x080c, 0xb16c, - 0x9085, 0x0001, 0x0070, 0x080c, 0x5848, 0x0128, 0xd18c, 0x1170, - 0x080c, 0xd04e, 0x0148, 0x2009, 0x004c, 0x080c, 0xb20a, 0x9085, - 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x2900, 0x6016, - 0x0c90, 0x2009, 0x004d, 0x0010, 0x2009, 0x004e, 0x00f6, 0x00c6, - 0x0046, 0x0016, 0x080c, 0xb116, 0x2c78, 0x05a0, 0x7e5e, 0x2b00, - 0x7812, 0x7823, 0x0003, 0x0016, 0x2021, 0x0005, 0x080c, 0xd060, - 0x001e, 0x9186, 0x004d, 0x0118, 0x9186, 0x004e, 0x0148, 0x2001, - 0x1980, 0x200c, 0xd1fc, 0x0168, 0x2f60, 0x080c, 0xb16c, 0x00d0, - 0x2001, 0x197f, 0x200c, 0xd1fc, 0x0120, 0x2f60, 0x080c, 0xb16c, - 0x0088, 0x2f60, 0x080c, 0x5848, 0x0138, 0xd18c, 0x1118, 0x04f1, - 0x0148, 0x0010, 0x2900, 0x7816, 0x001e, 0x0016, 0x080c, 0xb20a, - 0x9085, 0x0001, 0x001e, 0x004e, 0x00ce, 0x00fe, 0x0005, 0x00f6, - 0x00c6, 0x0046, 0x080c, 0xb116, 0x2c78, 0x0508, 0x7e5e, 0x2b00, - 0x7812, 0x7823, 0x0003, 0x0096, 0x2021, 0x0004, 0x0489, 0x009e, - 0x2001, 0x197e, 0x200c, 0xd1fc, 0x0120, 0x2f60, 0x080c, 0xb16c, - 0x0060, 0x2f60, 0x080c, 0x5848, 0x0120, 0xd18c, 0x1160, 0x0071, - 0x0130, 0x2009, 0x0052, 0x080c, 0xb20a, 0x9085, 0x0001, 0x004e, - 0x00ce, 0x00fe, 0x0005, 0x2900, 0x7816, 0x0c98, 0x00c6, 0x080c, - 0x4c41, 0x00ce, 0x1120, 0x080c, 0xb16c, 0x9006, 0x0005, 0xa867, - 0x0000, 0xa86b, 0x8000, 0x2900, 0x6016, 0x9085, 0x0001, 0x0005, - 0x0096, 0x0076, 0x0126, 0x2091, 0x8000, 0x080c, 0xacfc, 0x080c, - 0x699d, 0x0158, 0x2001, 0xd067, 0x0006, 0x900e, 0x2400, 0x080c, - 0x725e, 0x080c, 0x7012, 0x000e, 0x0807, 0x2418, 0x080c, 0x99b3, - 0xbaa0, 0x0086, 0x2041, 0x0001, 0x2039, 0x0001, 0x2608, 0x080c, - 0x97ca, 0x008e, 0x080c, 0x966d, 0x2f08, 0x2648, 0x080c, 0xe75d, - 0xb93c, 0x81ff, 0x090c, 0x98a3, 0x080c, 0xad18, 0x012e, 0x007e, - 0x009e, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0xb116, - 0x0190, 0x660a, 0x2b08, 0x6112, 0x080c, 0xd3b6, 0x6023, 0x0001, - 0x2900, 0x6016, 0x2009, 0x001f, 0x080c, 0xb20a, 0x9085, 0x0001, - 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x00c6, 0x0126, 0x2091, - 0x8000, 0x080c, 0xb1dd, 0x01b8, 0x660a, 0x2b08, 0x6112, 0x080c, - 0xd3b6, 0x6023, 0x0008, 0x2900, 0x6016, 0x00f6, 0x2c78, 0x080c, - 0x17ad, 0x00fe, 0x2009, 0x0021, 0x080c, 0xb20a, 0x9085, 0x0001, - 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x2009, 0x003d, 0x00c6, - 0x0126, 0x0016, 0x2091, 0x8000, 0x080c, 0xb116, 0x0198, 0x660a, - 0x2b08, 0x6112, 0x080c, 0xd3b6, 0x6023, 0x0001, 0x2900, 0x6016, - 0x001e, 0x0016, 0x080c, 0xb20a, 0x9085, 0x0001, 0x001e, 0x012e, - 0x00ce, 0x0005, 0x9006, 0x0cd0, 0x00c6, 0x0126, 0x2091, 0x8000, - 0x080c, 0xb1dd, 0x0188, 0x2b08, 0x6112, 0x080c, 0xd3b6, 0x6023, - 0x0001, 0x2900, 0x6016, 0x2009, 0x0000, 0x080c, 0xb20a, 0x9085, - 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x2009, 0x0044, - 0x0830, 0x2009, 0x0049, 0x0818, 0x0026, 0x00b6, 0x6210, 0x2258, - 0xba3c, 0x82ff, 0x0118, 0x8211, 0xba3e, 0x1140, 0xb8d0, 0x9005, - 0x0128, 0xb888, 0x9005, 0x1110, 0xb88b, 0x0001, 0x00be, 0x002e, - 0x0005, 0x0006, 0x0016, 0x6004, 0x908e, 0x0002, 0x0140, 0x908e, - 0x0003, 0x0128, 0x908e, 0x0004, 0x0110, 0x9085, 0x0001, 0x001e, - 0x000e, 0x0005, 0x0006, 0x0086, 0x0096, 0x6020, 0x9086, 0x0004, - 0x01a8, 0x6014, 0x904d, 0x080c, 0xcf1b, 0x0180, 0xa864, 0x9086, - 0x0139, 0x0170, 0x6020, 0x90c6, 0x0003, 0x0140, 0x90c6, 0x0002, - 0x0128, 0xa868, 0xd0fc, 0x0110, 0x9006, 0x0010, 0x9085, 0x0001, - 0x009e, 0x008e, 0x000e, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, - 0x080c, 0xb1dd, 0x0198, 0x2b08, 0x6112, 0x080c, 0xd3b6, 0x6023, - 0x0001, 0x2900, 0x6016, 0x080c, 0x3315, 0x2009, 0x0028, 0x080c, - 0xb20a, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, - 0x9186, 0x0015, 0x11a8, 0x2011, 0x1824, 0x2204, 0x9086, 0x0074, - 0x1178, 0x00b6, 0x080c, 0xbe09, 0x00be, 0x080c, 0xc085, 0x6003, - 0x0001, 0x6007, 0x0029, 0x080c, 0x961e, 0x080c, 0x9ab3, 0x0078, - 0x6014, 0x0096, 0x2048, 0xa868, 0x009e, 0xd0fc, 0x0148, 0x2001, - 0x0001, 0x080c, 0xd57c, 0x080c, 0xbb5c, 0x080c, 0xb16c, 0x0005, - 0x0096, 0x6014, 0x904d, 0x090c, 0x0d85, 0xa87b, 0x0030, 0xa883, - 0x0000, 0xa897, 0x4005, 0xa89b, 0x0004, 0xa867, 0x0139, 0x0126, - 0x2091, 0x8000, 0x080c, 0x7012, 0x012e, 0x009e, 0x080c, 0xb16c, - 0x0c30, 0x0096, 0x9186, 0x0016, 0x1128, 0x2001, 0x0004, 0x080c, - 0x66fa, 0x00e8, 0x9186, 0x0015, 0x1510, 0x2011, 0x1824, 0x2204, - 0x9086, 0x0014, 0x11e0, 0x6010, 0x00b6, 0x2058, 0x080c, 0x684f, - 0x00be, 0x080c, 0xc15b, 0x1198, 0x6010, 0x00b6, 0x2058, 0xb890, - 0x00be, 0x9005, 0x0160, 0x2001, 0x0006, 0x080c, 0x66fa, 0x6014, - 0x2048, 0xa868, 0xd0fc, 0x0170, 0x080c, 0xb57c, 0x0048, 0x6014, - 0x2048, 0xa868, 0xd0fc, 0x0528, 0x080c, 0xbb5c, 0x080c, 0xb16c, - 0x009e, 0x0005, 0x6014, 0x6310, 0x2358, 0x904d, 0x090c, 0x0d85, - 0xa87b, 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, 0x900e, 0x080c, - 0x6aae, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0xa99a, - 0x0126, 0x2091, 0x8000, 0x080c, 0x7012, 0x012e, 0x080c, 0xb16c, - 0x08f8, 0x6014, 0x904d, 0x090c, 0x0d85, 0xa87b, 0x0030, 0xa883, - 0x0000, 0xa897, 0x4005, 0xa89b, 0x0004, 0xa867, 0x0139, 0x0126, - 0x2091, 0x8000, 0x080c, 0x7012, 0x012e, 0x080c, 0xb16c, 0x0840, - 0xa878, 0x9086, 0x0005, 0x1108, 0x0009, 0x0005, 0xa880, 0xc0ad, - 0xa882, 0x0005, 0x604b, 0x0000, 0x6017, 0x0000, 0x6003, 0x0001, - 0x6007, 0x0050, 0x2009, 0x8023, 0x080c, 0x9617, 0x0005, 0x00c6, - 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0130, 0x0066, - 0x6020, 0x9084, 0x000f, 0x001b, 0x006e, 0x00ce, 0x0005, 0xcbf9, - 0xd259, 0xd259, 0xd25c, 0xeadc, 0xeaf7, 0xeafa, 0xcbf9, 0xcbf9, - 0xcbf9, 0xcbf9, 0xcbf9, 0xcbf9, 0xcbf9, 0xcbf9, 0xcbf9, 0x080c, - 0x0d85, 0xa001, 0xa001, 0x0005, 0x0096, 0x6014, 0x904d, 0x0118, - 0xa87c, 0xd0e4, 0x1110, 0x009e, 0x0010, 0x009e, 0x0005, 0x6010, - 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0550, 0x2001, 0x1834, - 0x2004, 0x9005, 0x1540, 0x00f6, 0x2c78, 0x080c, 0xb116, 0x0508, - 0x7810, 0x6012, 0x080c, 0xd3b6, 0x7820, 0x9086, 0x0003, 0x0128, - 0x7808, 0x603a, 0x2f00, 0x603e, 0x0020, 0x7808, 0x603e, 0x2f00, - 0x603a, 0x602e, 0x6023, 0x0001, 0x6007, 0x0035, 0x6003, 0x0001, - 0x795c, 0x615e, 0x2009, 0x8020, 0x080c, 0x9617, 0x2f60, 0x00fe, - 0x0005, 0x2f60, 0x00fe, 0x2001, 0x1988, 0x2004, 0x604a, 0x0005, - 0x0016, 0x0096, 0x6814, 0x2048, 0x681c, 0xd0fc, 0xc0fc, 0x681e, - 0xa87c, 0x1108, 0xd0e4, 0x0180, 0xc0e4, 0xa87e, 0xa877, 0x0000, - 0xa893, 0x0000, 0xa88f, 0x0000, 0xd0cc, 0x0130, 0xc0cc, 0xa87e, - 0xa878, 0x2048, 0x080c, 0x100b, 0x6830, 0x6036, 0x908e, 0x0001, - 0x0148, 0x6803, 0x0002, 0x9086, 0x0005, 0x0170, 0x9006, 0x602e, - 0x6032, 0x00d0, 0x681c, 0xc085, 0x681e, 0x6803, 0x0004, 0x6824, - 0xc0f4, 0x9085, 0x0c00, 0x6826, 0x6814, 0x2048, 0xa8ac, 0x6938, - 0x9102, 0xa8b0, 0x693c, 0x9103, 0x1e48, 0x683c, 0x602e, 0x6838, - 0x9084, 0xfffc, 0x683a, 0x6032, 0x2d00, 0x603a, 0x6808, 0x603e, - 0x6910, 0x6112, 0x695c, 0x615e, 0x6023, 0x0001, 0x6007, 0x0039, - 0x6003, 0x0001, 0x2009, 0x8020, 0x080c, 0x9617, 0x009e, 0x001e, - 0x0005, 0x6024, 0xd0d4, 0x0510, 0xd0f4, 0x11f8, 0x6038, 0x940a, - 0x603c, 0x9303, 0x0230, 0x9105, 0x0120, 0x6024, 0xc0d4, 0xc0f5, - 0x0098, 0x643a, 0x633e, 0xac3e, 0xab42, 0x0046, 0x0036, 0x2400, - 0xacac, 0x9402, 0xa836, 0x2300, 0xabb0, 0x9303, 0xa83a, 0x003e, - 0x004e, 0x6024, 0xc0d4, 0x0000, 0x6026, 0x0005, 0xd0f4, 0x1138, - 0xa83c, 0x603a, 0xa840, 0x603e, 0x6024, 0xc0f5, 0x6026, 0x0005, - 0x0006, 0x0016, 0x6004, 0x908e, 0x0034, 0x01b8, 0x908e, 0x0035, - 0x01a0, 0x908e, 0x0036, 0x0188, 0x908e, 0x0037, 0x0170, 0x908e, - 0x0038, 0x0158, 0x908e, 0x0039, 0x0140, 0x908e, 0x003a, 0x0128, - 0x908e, 0x003b, 0x0110, 0x9085, 0x0001, 0x001e, 0x000e, 0x0005, - 0x0006, 0x0016, 0x0026, 0x0036, 0x00e6, 0x2001, 0x1982, 0x200c, - 0x8000, 0x2014, 0x2001, 0x0032, 0x080c, 0x955b, 0x2001, 0x1986, - 0x82ff, 0x1110, 0x2011, 0x0014, 0x2202, 0x2001, 0x1984, 0x200c, - 0x8000, 0x2014, 0x2071, 0x196c, 0x711a, 0x721e, 0x2001, 0x0064, - 0x080c, 0x955b, 0x2001, 0x1987, 0x82ff, 0x1110, 0x2011, 0x0014, - 0x2202, 0x2001, 0x1988, 0x9288, 0x000a, 0x2102, 0x2001, 0x0017, - 0x080c, 0xaced, 0x2001, 0x1a90, 0x2102, 0x2001, 0x0032, 0x080c, - 0x16b9, 0x080c, 0x6bf2, 0x00ee, 0x003e, 0x002e, 0x001e, 0x000e, - 0x0005, 0x0006, 0x0016, 0x00e6, 0x2001, 0x1986, 0x2003, 0x0028, - 0x2001, 0x1987, 0x2003, 0x0014, 0x2071, 0x196c, 0x701b, 0x0000, - 0x701f, 0x07d0, 0x2001, 0x1988, 0x2009, 0x001e, 0x2102, 0x2001, - 0x0017, 0x080c, 0xaced, 0x2001, 0x1a90, 0x2102, 0x2001, 0x0032, - 0x080c, 0x16b9, 0x00ee, 0x001e, 0x000e, 0x0005, 0x0096, 0x6060, - 0x904d, 0x0110, 0x080c, 0x108b, 0x009e, 0x0005, 0x0005, 0x00c6, - 0x0126, 0x2091, 0x8000, 0x080c, 0xb116, 0x0180, 0x2b08, 0x6112, - 0x0ca9, 0x6023, 0x0001, 0x2900, 0x6016, 0x2009, 0x0033, 0x080c, - 0xb20a, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, - 0x0096, 0x00e6, 0x00f6, 0x2071, 0x1800, 0x9186, 0x0015, 0x1520, - 0x7090, 0x9086, 0x0018, 0x0120, 0x7090, 0x9086, 0x0014, 0x11e0, - 0x6014, 0x2048, 0xaa3c, 0xd2e4, 0x1160, 0x2c78, 0x080c, 0x9b83, - 0x01d8, 0x707c, 0xaa50, 0x9206, 0x1160, 0x7080, 0xaa54, 0x9206, - 0x1140, 0x6210, 0x00b6, 0x2258, 0xbaa0, 0x00be, 0x900e, 0x080c, - 0x3364, 0x080c, 0xb57c, 0x0020, 0x080c, 0xbb5c, 0x080c, 0xb16c, - 0x00fe, 0x00ee, 0x009e, 0x0005, 0x7060, 0xaa54, 0x9206, 0x0d48, - 0x0c80, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0xb116, 0x0188, - 0x2b08, 0x6112, 0x080c, 0xd3b6, 0x6023, 0x0001, 0x2900, 0x6016, - 0x2009, 0x004d, 0x080c, 0xb20a, 0x9085, 0x0001, 0x012e, 0x00ce, - 0x0005, 0x9006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x0016, - 0x080c, 0xb116, 0x0180, 0x2b08, 0x6112, 0x080c, 0xd3b6, 0x6023, - 0x0001, 0x2900, 0x6016, 0x001e, 0x080c, 0xb20a, 0x9085, 0x0001, - 0x012e, 0x00ce, 0x0005, 0x001e, 0x9006, 0x0cd0, 0x0016, 0x0026, - 0x0036, 0x0046, 0x0056, 0x0066, 0x0096, 0x00e6, 0x00f6, 0x2071, - 0x1800, 0x9186, 0x0015, 0x1568, 0x7190, 0x6014, 0x2048, 0xa814, - 0x8003, 0x9106, 0x1530, 0x20e1, 0x0000, 0x2001, 0x19a1, 0x2003, - 0x0000, 0x6014, 0x2048, 0xa830, 0x20a8, 0x8906, 0x8006, 0x8007, - 0x9094, 0x003f, 0x22e8, 0x9084, 0xffc0, 0x9080, 0x001b, 0x20a0, - 0x2001, 0x19a1, 0x0016, 0x200c, 0x080c, 0xdca1, 0x001e, 0xa804, - 0x9005, 0x0110, 0x2048, 0x0c38, 0x6014, 0x2048, 0xa867, 0x0103, - 0x0010, 0x080c, 0xbb5c, 0x080c, 0xb16c, 0x00fe, 0x00ee, 0x009e, - 0x006e, 0x005e, 0x004e, 0x003e, 0x002e, 0x001e, 0x0005, 0x0096, - 0x00e6, 0x00f6, 0x2071, 0x1800, 0x9186, 0x0015, 0x11b8, 0x7090, - 0x9086, 0x0004, 0x1198, 0x6014, 0x2048, 0x2c78, 0x080c, 0x9b83, - 0x01a8, 0x707c, 0xaa74, 0x9206, 0x1130, 0x7080, 0xaa78, 0x9206, - 0x1110, 0x080c, 0x3315, 0x080c, 0xb57c, 0x0020, 0x080c, 0xbb5c, - 0x080c, 0xb16c, 0x00fe, 0x00ee, 0x009e, 0x0005, 0x7060, 0xaa78, - 0x9206, 0x0d78, 0x0c80, 0x0096, 0x00e6, 0x00f6, 0x2071, 0x1800, - 0x9186, 0x0015, 0x1550, 0x7090, 0x9086, 0x0004, 0x1530, 0x6014, - 0x2048, 0x2c78, 0x080c, 0x9b83, 0x05f0, 0x707c, 0xaacc, 0x9206, - 0x1180, 0x7080, 0xaad0, 0x9206, 0x1160, 0x080c, 0x3315, 0x0016, - 0xa998, 0xaab0, 0x9284, 0x1000, 0xc0fd, 0x080c, 0x57e9, 0x001e, - 0x0010, 0x080c, 0x55cc, 0x080c, 0xcf1b, 0x0508, 0xa87b, 0x0000, - 0xa883, 0x0000, 0xa897, 0x4000, 0x0080, 0x080c, 0xcf1b, 0x01b8, - 0x6014, 0x2048, 0x080c, 0x55cc, 0x1d70, 0xa87b, 0x0030, 0xa883, - 0x0000, 0xa897, 0x4005, 0xa89b, 0x0004, 0x0126, 0x2091, 0x8000, - 0xa867, 0x0139, 0x080c, 0x7012, 0x012e, 0x080c, 0xb16c, 0x00fe, - 0x00ee, 0x009e, 0x0005, 0x7060, 0xaad0, 0x9206, 0x0930, 0x0888, - 0x0016, 0x0026, 0xa87c, 0xd0ac, 0x0178, 0xa938, 0xaa34, 0x2100, - 0x9205, 0x0150, 0xa890, 0x9106, 0x1118, 0xa88c, 0x9206, 0x0120, - 0xa992, 0xaa8e, 0x9085, 0x0001, 0x002e, 0x001e, 0x0005, 0x00b6, - 0x00d6, 0x0036, 0x080c, 0xcf1b, 0x0904, 0xd578, 0x0096, 0x6314, - 0x2348, 0xa87a, 0xa982, 0x929e, 0x4000, 0x1580, 0x6310, 0x00c6, - 0x2358, 0x2009, 0x0000, 0xa868, 0xd0f4, 0x1140, 0x080c, 0x6aae, - 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0xaa96, 0xa99a, - 0x20a9, 0x0004, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0031, 0x20a0, - 0xb8c4, 0x20e0, 0xb8c8, 0x9080, 0x0006, 0x2098, 0x080c, 0x0fd6, - 0x20a9, 0x0004, 0xa85c, 0x9080, 0x0035, 0x20a0, 0xb8c8, 0x9080, - 0x000a, 0x2098, 0x080c, 0x0fd6, 0x00ce, 0x0090, 0xaa96, 0x3918, - 0x9398, 0x0007, 0x231c, 0x6004, 0x9086, 0x0016, 0x0110, 0xa89b, - 0x0004, 0xaba2, 0x6310, 0x2358, 0xb804, 0x9084, 0x00ff, 0xa89e, - 0xa868, 0xc0f4, 0xa86a, 0x080c, 0x7006, 0x6017, 0x0000, 0x009e, - 0x003e, 0x00de, 0x00be, 0x0005, 0x0026, 0x0036, 0x0046, 0x00b6, - 0x0096, 0x00f6, 0x6214, 0x2248, 0x6210, 0x2258, 0x2079, 0x0260, - 0x9096, 0x0000, 0x11a0, 0xb814, 0x9084, 0x00ff, 0x900e, 0x080c, - 0x268c, 0x2118, 0x831f, 0x939c, 0xff00, 0x7838, 0x9084, 0x00ff, - 0x931d, 0x7c3c, 0x2011, 0x8018, 0x080c, 0x4ca1, 0x00a8, 0x9096, - 0x0001, 0x1148, 0x89ff, 0x0180, 0xa89b, 0x000d, 0x7838, 0xa8a6, - 0x783c, 0xa8aa, 0x0048, 0x9096, 0x0002, 0x1130, 0xa89b, 0x000d, - 0x7838, 0xa8a6, 0x783c, 0xa8aa, 0x00fe, 0x009e, 0x00be, 0x004e, - 0x003e, 0x002e, 0x0005, 0x00c6, 0x0026, 0x0016, 0x9186, 0x0035, - 0x0110, 0x6a38, 0x0008, 0x6a2c, 0x080c, 0xcf09, 0x01f0, 0x2260, - 0x6120, 0x9186, 0x0003, 0x0118, 0x9186, 0x0006, 0x1190, 0x6838, - 0x9206, 0x0140, 0x683c, 0x9206, 0x1160, 0x6108, 0x6838, 0x9106, - 0x1140, 0x0020, 0x6008, 0x693c, 0x9106, 0x1118, 0x6010, 0x6910, - 0x9106, 0x001e, 0x002e, 0x00ce, 0x0005, 0x9085, 0x0001, 0x0cc8, - 0xa974, 0xd1cc, 0x0198, 0x918c, 0x00ff, 0x918e, 0x0002, 0x1170, - 0xa9a8, 0x918c, 0x000f, 0x918e, 0x0001, 0x1140, 0xa87c, 0xd0ac, - 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, 0xc519, 0x0005, 0x0036, - 0x2019, 0x0001, 0x0010, 0x0036, 0x901e, 0x0499, 0x01e0, 0x080c, - 0xcf1b, 0x01c8, 0x080c, 0xd10c, 0x6037, 0x4000, 0x6014, 0x6017, - 0x0000, 0x0096, 0x2048, 0xa87c, 0x080c, 0xd132, 0x1118, 0x080c, - 0xbb5c, 0x0040, 0xa867, 0x0103, 0xa877, 0x0000, 0x83ff, 0x1129, - 0x080c, 0x7012, 0x009e, 0x003e, 0x0005, 0xa880, 0xd0b4, 0x0128, - 0xa87b, 0x0006, 0xc0ec, 0xa882, 0x0048, 0xd0bc, 0x0118, 0xa87b, - 0x0002, 0x0020, 0xa87b, 0x0005, 0x080c, 0xd226, 0xa877, 0x0000, - 0x0005, 0x2001, 0x1810, 0x2004, 0xd0ec, 0x0005, 0x0006, 0x2001, - 0x1810, 0x2004, 0xd0f4, 0x000e, 0x0005, 0x0006, 0x2001, 0x1810, - 0x2004, 0xd0e4, 0x000e, 0x0005, 0x0036, 0x0046, 0x6010, 0x00b6, - 0x2058, 0xbba0, 0x00be, 0x2021, 0x0007, 0x080c, 0x4e58, 0x004e, - 0x003e, 0x0005, 0x0c51, 0x1d81, 0x0005, 0x2001, 0x1986, 0x2004, - 0x601a, 0x0005, 0x2001, 0x1988, 0x2004, 0x604a, 0x0005, 0x080c, - 0xb16c, 0x0804, 0x9ab3, 0x611c, 0xd1fc, 0xa97c, 0x1108, 0xd1e4, - 0x0005, 0x601c, 0xd0fc, 0xa87c, 0x1108, 0xd0e4, 0x0005, 0x601c, - 0xd0fc, 0xc0fc, 0x601e, 0xa87c, 0x1108, 0xd0e4, 0x0005, 0x6044, - 0xd0fc, 0x1138, 0xd0bc, 0x01a0, 0xc0bc, 0x6046, 0x2001, 0x0002, - 0x0080, 0xd0ac, 0x1168, 0xd0dc, 0x1128, 0x908c, 0x000f, 0x9186, - 0x0005, 0x1118, 0x2001, 0x0003, 0x0020, 0x2001, 0x0001, 0x0008, - 0x6000, 0x0005, 0x00b6, 0x0066, 0x6000, 0x90b2, 0x0010, 0x1a0c, - 0x0d85, 0x001b, 0x006e, 0x00be, 0x0005, 0xd6b5, 0xddfe, 0xdf62, - 0xd6b5, 0xd6b5, 0xd6b5, 0xd6b5, 0xd6b5, 0xd6ec, 0xdfe6, 0xd6b5, - 0xd6b5, 0xd6b5, 0xd6b5, 0xd6b5, 0xd6b5, 0x080c, 0x0d85, 0x0066, - 0x6000, 0x90b2, 0x0010, 0x1a0c, 0x0d85, 0x0013, 0x006e, 0x0005, - 0xd6d0, 0xe50b, 0xd6d0, 0xd6d0, 0xd6d0, 0xd6d0, 0xd6d0, 0xd6d0, - 0xe4ba, 0xe55d, 0xd6d0, 0xec10, 0xec44, 0xec10, 0xec44, 0xd6d0, - 0x080c, 0x0d85, 0x6000, 0x9082, 0x0010, 0x1a0c, 0x0d85, 0x6000, - 0x000a, 0x0005, 0xd6ea, 0xe1c3, 0xe28e, 0xe2b1, 0xe32d, 0xd6ea, - 0xe42a, 0xe3b5, 0xdff0, 0xe492, 0xe4a7, 0xd6ea, 0xd6ea, 0xd6ea, - 0xd6ea, 0xd6ea, 0x080c, 0x0d85, 0x91b2, 0x0053, 0x1a0c, 0x0d85, - 0x2100, 0x91b2, 0x0040, 0x1a04, 0xdb70, 0x0002, 0xd736, 0xd93e, - 0xd736, 0xd736, 0xd736, 0xd947, 0xd736, 0xd736, 0xd736, 0xd736, - 0xd736, 0xd736, 0xd736, 0xd736, 0xd736, 0xd736, 0xd736, 0xd736, - 0xd736, 0xd736, 0xd736, 0xd736, 0xd736, 0xd738, 0xd79f, 0xd7ae, - 0xd812, 0xd83d, 0xd8b6, 0xd929, 0xd736, 0xd736, 0xd94a, 0xd736, - 0xd736, 0xd95f, 0xd96c, 0xd736, 0xd736, 0xd736, 0xd736, 0xd736, - 0xda12, 0xd736, 0xd736, 0xda26, 0xd736, 0xd736, 0xd9e1, 0xd736, - 0xd736, 0xd736, 0xda3e, 0xd736, 0xd736, 0xd736, 0xdabb, 0xd736, - 0xd736, 0xd736, 0xd736, 0xd736, 0xd736, 0xdb38, 0x080c, 0x0d85, - 0x080c, 0x6bcf, 0x1150, 0x2001, 0x1837, 0x2004, 0xd0cc, 0x1128, - 0x9084, 0x0009, 0x9086, 0x0008, 0x1140, 0x6007, 0x0009, 0x602f, - 0x0009, 0x6017, 0x0000, 0x0804, 0xd937, 0x080c, 0x6b6b, 0x00e6, - 0x00c6, 0x0036, 0x0026, 0x0016, 0x6210, 0x2258, 0xbaa0, 0x0026, - 0x2019, 0x0029, 0x080c, 0xacfc, 0x080c, 0x97b0, 0x0076, 0x903e, - 0x080c, 0x966d, 0x2c08, 0x080c, 0xe75d, 0x007e, 0x001e, 0x080c, - 0xad18, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee, 0x6610, 0x2658, - 0x080c, 0x67c3, 0xbe04, 0x9684, 0x00ff, 0x9082, 0x0006, 0x1268, - 0x0016, 0x0026, 0x6210, 0x00b6, 0x2258, 0xbaa0, 0x00be, 0x2c08, - 0x080c, 0xee6f, 0x002e, 0x001e, 0x1178, 0x080c, 0xe68b, 0x1904, - 0xd80a, 0x080c, 0xe627, 0x1120, 0x6007, 0x0008, 0x0804, 0xd937, - 0x6007, 0x0009, 0x0804, 0xd937, 0x080c, 0xe905, 0x0128, 0x080c, - 0xe68b, 0x0d78, 0x0804, 0xd80a, 0x6017, 0x1900, 0x0c88, 0x080c, - 0x344c, 0x1904, 0xdb6d, 0x6106, 0x080c, 0xe5c7, 0x6007, 0x0006, - 0x0804, 0xd937, 0x6007, 0x0007, 0x0804, 0xd937, 0x080c, 0xec80, - 0x1904, 0xdb6d, 0x080c, 0x344c, 0x1904, 0xdb6d, 0x00d6, 0x6610, - 0x2658, 0xbe04, 0x9684, 0x00ff, 0x9082, 0x0006, 0x1220, 0x2001, - 0x0001, 0x080c, 0x66e6, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, - 0x0188, 0x9686, 0x0004, 0x0170, 0xbe04, 0x96b4, 0x00ff, 0x9686, - 0x0006, 0x0140, 0x9686, 0x0004, 0x0128, 0x9686, 0x0005, 0x0110, - 0x00de, 0x0480, 0x00e6, 0x2071, 0x0260, 0x7034, 0x9084, 0x0003, - 0x1140, 0x7034, 0x9082, 0x0014, 0x0220, 0x7030, 0x9084, 0x0003, - 0x0130, 0x00ee, 0x6017, 0x0000, 0x602f, 0x0007, 0x00b0, 0x00ee, - 0x080c, 0xe6f3, 0x1190, 0x9686, 0x0006, 0x1140, 0x0026, 0x6210, - 0x2258, 0xbaa0, 0x900e, 0x080c, 0x3364, 0x002e, 0x080c, 0x684f, - 0x6007, 0x000a, 0x00de, 0x0804, 0xd937, 0x6007, 0x000b, 0x00de, - 0x0804, 0xd937, 0x080c, 0x3315, 0x080c, 0xd65a, 0x6007, 0x0001, - 0x0804, 0xd937, 0x080c, 0xec80, 0x1904, 0xdb6d, 0x080c, 0x344c, - 0x1904, 0xdb6d, 0x2071, 0x0260, 0x7034, 0x90b4, 0x0003, 0x1948, - 0x90b2, 0x0014, 0x0a30, 0x7030, 0x9084, 0x0003, 0x1910, 0x6610, - 0x2658, 0xbe04, 0x9686, 0x0707, 0x09e8, 0x0026, 0x6210, 0x2258, - 0xbaa0, 0x900e, 0x080c, 0x3364, 0x002e, 0x6007, 0x000c, 0x2001, - 0x0001, 0x080c, 0xee4e, 0x0804, 0xd937, 0x080c, 0x6bcf, 0x1140, - 0x2001, 0x1837, 0x2004, 0x9084, 0x0009, 0x9086, 0x0008, 0x1110, - 0x0804, 0xd745, 0x080c, 0x6b6b, 0x6610, 0x2658, 0xbe04, 0x9684, - 0x00ff, 0x9082, 0x0006, 0x06c8, 0x1138, 0x0026, 0x2001, 0x0006, - 0x080c, 0x6726, 0x002e, 0x0050, 0x96b4, 0xff00, 0x8637, 0x9686, - 0x0004, 0x0120, 0x9686, 0x0006, 0x1904, 0xd80a, 0x080c, 0xe700, - 0x1120, 0x6007, 0x000e, 0x0804, 0xd937, 0x0046, 0x6410, 0x2458, - 0xbca0, 0x0046, 0x080c, 0x3315, 0x080c, 0xd65a, 0x004e, 0x0016, - 0x9006, 0x2009, 0x1848, 0x210c, 0xd1a4, 0x0148, 0x2009, 0x0029, - 0x080c, 0xea8d, 0x6010, 0x2058, 0xb800, 0xc0e5, 0xb802, 0x001e, - 0x004e, 0x6007, 0x0001, 0x0804, 0xd937, 0x2001, 0x0001, 0x080c, - 0x66e6, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, - 0x1805, 0x2011, 0x0270, 0x080c, 0xc20e, 0x003e, 0x002e, 0x001e, - 0x015e, 0x9005, 0x0168, 0x96b4, 0xff00, 0x8637, 0x9682, 0x0004, - 0x0a04, 0xd80a, 0x9682, 0x0007, 0x0a04, 0xd866, 0x0804, 0xd80a, - 0x6017, 0x1900, 0x6007, 0x0009, 0x0804, 0xd937, 0x080c, 0x6bcf, - 0x1140, 0x2001, 0x1837, 0x2004, 0x9084, 0x0009, 0x9086, 0x0008, - 0x1110, 0x0804, 0xd745, 0x080c, 0x6b6b, 0x6610, 0x2658, 0xbe04, - 0x9684, 0x00ff, 0x0006, 0x0016, 0x908e, 0x0001, 0x0118, 0x908e, - 0x0000, 0x1118, 0x001e, 0x000e, 0x0080, 0x001e, 0x000e, 0x9082, - 0x0006, 0x06a0, 0x0150, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0004, - 0x0120, 0x9686, 0x0006, 0x1904, 0xd80a, 0x080c, 0xe72e, 0x1138, - 0x080c, 0xe627, 0x1120, 0x6007, 0x0010, 0x0804, 0xd937, 0x0046, - 0x6410, 0x2458, 0xbca0, 0x0046, 0x080c, 0x3315, 0x080c, 0xd65a, - 0x004e, 0x0016, 0x9006, 0x2009, 0x1848, 0x210c, 0xd1a4, 0x0148, - 0x2009, 0x0029, 0x080c, 0xea8d, 0x6010, 0x2058, 0xb800, 0xc0e5, - 0xb802, 0x001e, 0x004e, 0x6007, 0x0001, 0x0448, 0x080c, 0xe905, - 0x0198, 0x0016, 0x968c, 0x00ff, 0x9186, 0x0002, 0x0160, 0x9186, - 0x0003, 0x0148, 0x001e, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, - 0x0920, 0x0804, 0xd80a, 0x001e, 0x6017, 0x1900, 0x6007, 0x0009, - 0x0070, 0x080c, 0x344c, 0x1904, 0xdb6d, 0x080c, 0xec80, 0x1904, - 0xdb6d, 0x080c, 0xdd3e, 0x1904, 0xd80a, 0x6007, 0x0012, 0x6003, - 0x0001, 0x080c, 0x961e, 0x080c, 0x9ab3, 0x0005, 0x6007, 0x0001, - 0x6003, 0x0001, 0x080c, 0x961e, 0x080c, 0x9ab3, 0x0cb0, 0x6007, - 0x0005, 0x0c68, 0x080c, 0xec80, 0x1904, 0xdb6d, 0x080c, 0x344c, - 0x1904, 0xdb6d, 0x080c, 0xdd3e, 0x1904, 0xd80a, 0x6007, 0x0020, - 0x6003, 0x0001, 0x080c, 0x961e, 0x080c, 0x9ab3, 0x0005, 0x080c, - 0x344c, 0x1904, 0xdb6d, 0x6007, 0x0023, 0x6003, 0x0001, 0x080c, - 0x961e, 0x080c, 0x9ab3, 0x0005, 0x080c, 0xec80, 0x1904, 0xdb6d, - 0x080c, 0x344c, 0x1904, 0xdb6d, 0x080c, 0xdd3e, 0x1904, 0xd80a, - 0x0016, 0x0026, 0x00e6, 0x2071, 0x0260, 0x2c08, 0x2011, 0x1820, - 0x2214, 0x703c, 0x9206, 0x11e0, 0x2011, 0x181f, 0x2214, 0x7038, - 0x9084, 0x00ff, 0x9206, 0x11a0, 0x7240, 0x080c, 0xcf09, 0x0570, - 0x2260, 0x6008, 0x9086, 0xffff, 0x0120, 0x7244, 0x6008, 0x9206, - 0x1528, 0x6020, 0x9086, 0x0007, 0x1508, 0x080c, 0xb16c, 0x04a0, - 0x7244, 0x9286, 0xffff, 0x0180, 0x2c08, 0x080c, 0xcf09, 0x01b0, - 0x2260, 0x7240, 0x6008, 0x9206, 0x1188, 0x6010, 0x9190, 0x0004, - 0x2214, 0x9206, 0x01b8, 0x0050, 0x7240, 0x2c08, 0x9006, 0x080c, - 0xea57, 0x1180, 0x7244, 0x9286, 0xffff, 0x01b0, 0x2160, 0x6007, - 0x0026, 0x6017, 0x1700, 0x7214, 0x9296, 0xffff, 0x1180, 0x6007, - 0x0025, 0x0068, 0x6020, 0x9086, 0x0007, 0x1d80, 0x6004, 0x9086, - 0x0024, 0x1110, 0x080c, 0xb16c, 0x2160, 0x6007, 0x0025, 0x6003, - 0x0001, 0x080c, 0x961e, 0x080c, 0x9ab3, 0x00ee, 0x002e, 0x001e, - 0x0005, 0x2001, 0x0001, 0x080c, 0x66e6, 0x0156, 0x0016, 0x0026, - 0x0036, 0x20a9, 0x0004, 0x2019, 0x1805, 0x2011, 0x0276, 0x080c, - 0xc20e, 0x003e, 0x002e, 0x001e, 0x015e, 0x0120, 0x6007, 0x0031, - 0x0804, 0xd937, 0x080c, 0xbe21, 0x080c, 0x779e, 0x1190, 0x0006, - 0x0026, 0x0036, 0x080c, 0x77b8, 0x1138, 0x080c, 0x7ab6, 0x080c, - 0x619d, 0x080c, 0x76cd, 0x0010, 0x080c, 0x7772, 0x003e, 0x002e, - 0x000e, 0x0005, 0x080c, 0x344c, 0x1904, 0xdb6d, 0x080c, 0xdd3e, - 0x1904, 0xd80a, 0x6106, 0x080c, 0xdd5a, 0x1120, 0x6007, 0x002b, - 0x0804, 0xd937, 0x6007, 0x002c, 0x0804, 0xd937, 0x080c, 0xec80, - 0x1904, 0xdb6d, 0x080c, 0x344c, 0x1904, 0xdb6d, 0x080c, 0xdd3e, - 0x1904, 0xd80a, 0x6106, 0x080c, 0xdd5f, 0x1120, 0x6007, 0x002e, - 0x0804, 0xd937, 0x6007, 0x002f, 0x0804, 0xd937, 0x080c, 0x344c, - 0x1904, 0xdb6d, 0x00e6, 0x00d6, 0x00c6, 0x6010, 0x2058, 0xb904, - 0x9184, 0x00ff, 0x9086, 0x0006, 0x0158, 0x9184, 0xff00, 0x8007, - 0x9086, 0x0006, 0x0128, 0x00ce, 0x00de, 0x00ee, 0x0804, 0xd93e, - 0x080c, 0x5844, 0xd0e4, 0x0904, 0xdab8, 0x2071, 0x026c, 0x7010, - 0x603a, 0x7014, 0x603e, 0x7108, 0x720c, 0x080c, 0x6c0d, 0x0140, - 0x6010, 0x2058, 0xb810, 0x9106, 0x1118, 0xb814, 0x9206, 0x0510, - 0x080c, 0x6c09, 0x15b8, 0x2069, 0x1800, 0x6880, 0x9206, 0x1590, - 0x687c, 0x9106, 0x1578, 0x7210, 0x080c, 0xcf09, 0x0590, 0x080c, - 0xdc2b, 0x0578, 0x080c, 0xeb09, 0x0560, 0x622e, 0x6007, 0x0036, - 0x6003, 0x0001, 0x2009, 0x8020, 0x080c, 0x9617, 0x00ce, 0x00de, - 0x00ee, 0x0005, 0x7214, 0x9286, 0xffff, 0x0150, 0x080c, 0xcf09, - 0x01c0, 0x9280, 0x0002, 0x2004, 0x7110, 0x9106, 0x1190, 0x08e0, - 0x7210, 0x2c08, 0x9085, 0x0001, 0x080c, 0xea57, 0x2c10, 0x2160, - 0x0140, 0x0890, 0x6007, 0x0037, 0x602f, 0x0009, 0x6017, 0x1500, - 0x08b8, 0x6007, 0x0037, 0x602f, 0x0003, 0x6017, 0x1700, 0x0880, - 0x6007, 0x0012, 0x0868, 0x080c, 0x344c, 0x1904, 0xdb6d, 0x6010, - 0x2058, 0xb804, 0x9084, 0xff00, 0x8007, 0x9086, 0x0006, 0x1904, - 0xd93e, 0x00e6, 0x00d6, 0x00c6, 0x080c, 0x5844, 0xd0e4, 0x0904, - 0xdb30, 0x2069, 0x1800, 0x2071, 0x026c, 0x7008, 0x603a, 0x720c, - 0x623e, 0x9286, 0xffff, 0x1150, 0x7208, 0x00c6, 0x2c08, 0x9085, - 0x0001, 0x080c, 0xea57, 0x2c10, 0x00ce, 0x05e8, 0x080c, 0xcf09, - 0x05d0, 0x7108, 0x9280, 0x0002, 0x2004, 0x9106, 0x15a0, 0x00c6, - 0x0026, 0x2260, 0x080c, 0xcadc, 0x002e, 0x00ce, 0x7118, 0x918c, - 0xff00, 0x810f, 0x9186, 0x0001, 0x0178, 0x9186, 0x0005, 0x0118, - 0x9186, 0x0007, 0x1198, 0x9280, 0x0005, 0x2004, 0x9005, 0x0170, - 0x080c, 0xdc2b, 0x0904, 0xdab1, 0x0056, 0x7510, 0x7614, 0x080c, - 0xeb22, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x6007, 0x003b, - 0x602f, 0x0009, 0x6017, 0x2a00, 0x6003, 0x0001, 0x2009, 0x8020, - 0x080c, 0x9617, 0x0c78, 0x6007, 0x003b, 0x602f, 0x0003, 0x6017, - 0x0300, 0x6003, 0x0001, 0x2009, 0x8020, 0x080c, 0x9617, 0x0c10, - 0x6007, 0x003b, 0x602f, 0x000b, 0x6017, 0x0000, 0x0804, 0xda88, - 0x00e6, 0x0026, 0x080c, 0x6bcf, 0x0550, 0x080c, 0x6b6b, 0x080c, - 0xecf1, 0x1518, 0x2071, 0x1800, 0x70dc, 0x9085, 0x0003, 0x70de, - 0x00f6, 0x2079, 0x0100, 0x72b0, 0x9284, 0x00ff, 0x707e, 0x78e6, - 0x9284, 0xff00, 0x7280, 0x9205, 0x7082, 0x78ea, 0x00fe, 0x70e7, - 0x0000, 0x080c, 0x6c0d, 0x0120, 0x2011, 0x1a0a, 0x2013, 0x07d0, - 0xd0ac, 0x1128, 0x080c, 0x30bf, 0x0010, 0x080c, 0xed25, 0x002e, - 0x00ee, 0x080c, 0xb16c, 0x0804, 0xd93d, 0x080c, 0xb16c, 0x0005, - 0x2600, 0x0002, 0xdb84, 0xdbb2, 0xdbc3, 0xdb84, 0xdb84, 0xdb86, - 0xdbd4, 0xdb84, 0xdb84, 0xdb84, 0xdba0, 0xdb84, 0xdb84, 0xdb84, - 0xdbdf, 0xdbf5, 0xdc26, 0xdb84, 0x080c, 0x0d85, 0x080c, 0xec80, - 0x1d20, 0x080c, 0x344c, 0x1d08, 0x7038, 0x6016, 0x6007, 0x0045, - 0x6003, 0x0001, 0x080c, 0x961e, 0x0005, 0x080c, 0x3315, 0x080c, - 0xd65a, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x961e, 0x0005, - 0x080c, 0xec80, 0x1950, 0x080c, 0x344c, 0x1938, 0x080c, 0xdd3e, - 0x1d60, 0x703c, 0x6016, 0x6007, 0x004a, 0x6003, 0x0001, 0x080c, - 0x961e, 0x0005, 0x080c, 0x344c, 0x1904, 0xdb6d, 0x2009, 0x0041, - 0x080c, 0xed2e, 0x6007, 0x0047, 0x6003, 0x0001, 0x080c, 0x961e, - 0x080c, 0x9ab3, 0x0005, 0x080c, 0x344c, 0x1904, 0xdb6d, 0x2009, - 0x0042, 0x080c, 0xed2e, 0x6007, 0x0047, 0x6003, 0x0001, 0x080c, - 0x961e, 0x080c, 0x9ab3, 0x0005, 0x080c, 0x344c, 0x1904, 0xdb6d, - 0x2009, 0x0046, 0x080c, 0xed2e, 0x080c, 0xb16c, 0x0005, 0x2001, - 0x1824, 0x2004, 0x9082, 0x00e1, 0x1268, 0x080c, 0xdc48, 0x0904, - 0xdb6d, 0x6007, 0x004e, 0x6003, 0x0001, 0x080c, 0x961e, 0x080c, - 0x9ab3, 0x0005, 0x6007, 0x0012, 0x0cb0, 0x6007, 0x004f, 0x6017, - 0x0000, 0x7134, 0x918c, 0x00ff, 0x81ff, 0x0508, 0x9186, 0x0001, - 0x1160, 0x7140, 0x2001, 0x19be, 0x2004, 0x9106, 0x11b0, 0x7144, - 0x2001, 0x19bf, 0x2004, 0x9106, 0x0190, 0x9186, 0x0002, 0x1168, - 0x2011, 0x0276, 0x20a9, 0x0004, 0x6010, 0x0096, 0x2048, 0x2019, - 0x000a, 0x080c, 0xc222, 0x009e, 0x0110, 0x6017, 0x0001, 0x6003, - 0x0001, 0x080c, 0x961e, 0x080c, 0x9ab3, 0x0005, 0x6007, 0x0050, - 0x703c, 0x6016, 0x0ca0, 0x0016, 0x00e6, 0x2071, 0x0260, 0x00b6, - 0x00c6, 0x2260, 0x6010, 0x2058, 0xb8d4, 0xd084, 0x0150, 0x7128, - 0x604c, 0x9106, 0x1120, 0x712c, 0x6050, 0x9106, 0x0110, 0x9006, - 0x0010, 0x9085, 0x0001, 0x00ce, 0x00be, 0x00ee, 0x001e, 0x0005, - 0x0016, 0x0096, 0x0086, 0x00e6, 0x01c6, 0x01d6, 0x0126, 0x2091, - 0x8000, 0x2071, 0x1800, 0x20e1, 0x0000, 0x2001, 0x19a1, 0x2003, - 0x0000, 0x080c, 0x1072, 0x05a0, 0x2900, 0x6016, 0x7090, 0x8004, - 0xa816, 0x908a, 0x001e, 0x02d0, 0xa833, 0x001e, 0x20a9, 0x001e, - 0xa860, 0x20e8, 0xa85c, 0x9080, 0x001b, 0x20a0, 0x2001, 0x19a1, - 0x0016, 0x200c, 0x0471, 0x001e, 0x81ff, 0x01b8, 0x2940, 0x080c, - 0x1072, 0x01b0, 0x2900, 0xa006, 0x2100, 0x0c18, 0xa832, 0x20a8, - 0xa860, 0x20e8, 0xa85c, 0x9080, 0x001b, 0x20a0, 0x2001, 0x19a1, - 0x0016, 0x200c, 0x00b1, 0x001e, 0x0000, 0x9085, 0x0001, 0x0048, - 0x2071, 0x1800, 0x7093, 0x0000, 0x6014, 0x2048, 0x080c, 0x100b, - 0x9006, 0x012e, 0x01de, 0x01ce, 0x00ee, 0x008e, 0x009e, 0x001e, - 0x0005, 0x0006, 0x0016, 0x0026, 0x0036, 0x00c6, 0x918c, 0xffff, - 0x11b0, 0x080c, 0x21f9, 0x2099, 0x026c, 0x2001, 0x0014, 0x3518, - 0x9312, 0x0108, 0x1218, 0x23a8, 0x4003, 0x0400, 0x20a8, 0x4003, - 0x22a8, 0x8108, 0x080c, 0x21f9, 0x2099, 0x0260, 0x0ca8, 0x080c, - 0x21f9, 0x2061, 0x19a1, 0x6004, 0x2098, 0x6008, 0x3518, 0x9312, - 0x0108, 0x1218, 0x23a8, 0x4003, 0x0048, 0x20a8, 0x4003, 0x22a8, - 0x8108, 0x080c, 0x21f9, 0x2099, 0x0260, 0x0ca8, 0x2061, 0x19a1, - 0x2019, 0x0280, 0x3300, 0x931e, 0x0110, 0x6006, 0x0020, 0x2001, - 0x0260, 0x6006, 0x8108, 0x2162, 0x9292, 0x0021, 0x9296, 0xffff, - 0x620a, 0x00ce, 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, 0x0006, - 0x0016, 0x0026, 0x0036, 0x00c6, 0x81ff, 0x11b8, 0x080c, 0x2211, - 0x20a1, 0x024c, 0x2001, 0x0014, 0x3518, 0x9312, 0x1218, 0x23a8, - 0x4003, 0x0418, 0x20a8, 0x4003, 0x82ff, 0x01f8, 0x22a8, 0x8108, - 0x080c, 0x2211, 0x20a1, 0x0240, 0x0c98, 0x080c, 0x2211, 0x2061, - 0x19a4, 0x6004, 0x20a0, 0x6008, 0x3518, 0x9312, 0x1218, 0x23a8, - 0x4003, 0x0058, 0x20a8, 0x4003, 0x82ff, 0x0138, 0x22a8, 0x8108, - 0x080c, 0x2211, 0x20a1, 0x0240, 0x0c98, 0x2061, 0x19a4, 0x2019, - 0x0260, 0x3400, 0x931e, 0x0110, 0x6006, 0x0020, 0x2001, 0x0240, - 0x6006, 0x8108, 0x2162, 0x9292, 0x0021, 0x9296, 0xffff, 0x620a, - 0x00ce, 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, 0x00b6, 0x0066, - 0x6610, 0x2658, 0xbe04, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, - 0x0170, 0x9686, 0x0004, 0x0158, 0xbe04, 0x96b4, 0x00ff, 0x9686, - 0x0006, 0x0128, 0x9686, 0x0004, 0x0110, 0x9085, 0x0001, 0x006e, - 0x00be, 0x0005, 0x00d6, 0x080c, 0xddd4, 0x00de, 0x0005, 0x00d6, - 0x080c, 0xdde1, 0x1520, 0x680c, 0x908c, 0xff00, 0x6820, 0x9084, - 0x00ff, 0x9115, 0x6216, 0x6824, 0x602e, 0xd1e4, 0x0130, 0x9006, - 0x080c, 0xee4e, 0x2009, 0x0001, 0x0078, 0xd1ec, 0x0180, 0x6920, - 0x918c, 0x00ff, 0x6824, 0x080c, 0x268c, 0x1148, 0x2001, 0x0001, - 0x080c, 0xee4e, 0x2110, 0x900e, 0x080c, 0x3364, 0x0018, 0x9085, - 0x0001, 0x0008, 0x9006, 0x00de, 0x0005, 0x00b6, 0x00c6, 0x080c, - 0xb1dd, 0x0598, 0x0016, 0x0026, 0x00c6, 0x2011, 0x0263, 0x2204, - 0x8211, 0x220c, 0x080c, 0x268c, 0x1568, 0x080c, 0x6749, 0x1550, - 0xbe12, 0xbd16, 0x00ce, 0x002e, 0x001e, 0x2b00, 0x6012, 0x080c, - 0xec80, 0x11c8, 0x080c, 0x344c, 0x11b0, 0x080c, 0xdd3e, 0x0500, - 0x2001, 0x0007, 0x080c, 0x66fa, 0x2001, 0x0007, 0x080c, 0x6726, - 0x6017, 0x0000, 0x6023, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, - 0x080c, 0x961e, 0x0010, 0x080c, 0xb16c, 0x9085, 0x0001, 0x00ce, - 0x00be, 0x0005, 0x080c, 0xb16c, 0x00ce, 0x002e, 0x001e, 0x0ca8, - 0x080c, 0xb16c, 0x9006, 0x0c98, 0x2069, 0x026d, 0x6800, 0x9082, - 0x0010, 0x1228, 0x6017, 0x0000, 0x9085, 0x0001, 0x0008, 0x9006, - 0x0005, 0x6017, 0x0000, 0x2069, 0x026c, 0x6808, 0x9084, 0xff00, - 0x9086, 0x0800, 0x1190, 0x6904, 0x9186, 0x0018, 0x0118, 0x9186, - 0x0014, 0x1158, 0x810f, 0x6800, 0x9084, 0x00ff, 0x910d, 0x6162, - 0x908e, 0x0014, 0x0110, 0x908e, 0x0010, 0x0005, 0x6004, 0x90b2, - 0x0053, 0x1a0c, 0x0d85, 0x91b6, 0x0013, 0x1130, 0x2008, 0x91b2, - 0x0040, 0x1a04, 0xdf36, 0x0402, 0x91b6, 0x0027, 0x0190, 0x9186, - 0x0015, 0x0118, 0x9186, 0x0016, 0x1140, 0x080c, 0xaf61, 0x0120, - 0x9086, 0x0002, 0x0904, 0xbba3, 0x0005, 0x91b6, 0x0014, 0x190c, - 0x0d85, 0x2001, 0x0007, 0x080c, 0x6726, 0x080c, 0x99ed, 0x080c, - 0xb1a7, 0x080c, 0x9ab3, 0x0005, 0xde6c, 0xde6e, 0xde6c, 0xde6c, - 0xde6c, 0xde6e, 0xde7b, 0xdf33, 0xdebd, 0xdf33, 0xdee1, 0xdf33, - 0xde7b, 0xdf33, 0xdf2b, 0xdf33, 0xdf2b, 0xdf33, 0xdf33, 0xde6c, - 0xde6c, 0xde6c, 0xde6c, 0xde6c, 0xde6c, 0xde6c, 0xde6c, 0xde6c, - 0xde6c, 0xde6c, 0xde6e, 0xde6c, 0xdf33, 0xde6c, 0xde6c, 0xdf33, - 0xde6c, 0xdf30, 0xdf33, 0xde6c, 0xde6c, 0xde6c, 0xde6c, 0xdf33, - 0xdf33, 0xde6c, 0xdf33, 0xdf33, 0xde6c, 0xde76, 0xde6c, 0xde6c, - 0xde6c, 0xde6c, 0xdf2f, 0xdf33, 0xde6c, 0xde6c, 0xdf33, 0xdf33, - 0xde6c, 0xde6c, 0xde6c, 0xde6c, 0x080c, 0x0d85, 0x080c, 0xd65d, - 0x6003, 0x0002, 0x080c, 0x9ab3, 0x0804, 0xdf35, 0x9006, 0x080c, - 0x66e6, 0x0804, 0xdf33, 0x080c, 0x6c09, 0x1904, 0xdf33, 0x9006, - 0x080c, 0x66e6, 0x6010, 0x2058, 0xb810, 0x9086, 0x00ff, 0x1140, - 0x00f6, 0x2079, 0x1800, 0x78a8, 0x8000, 0x78aa, 0x00fe, 0x00b8, - 0x6010, 0x2058, 0xb884, 0x9005, 0x0904, 0xdf33, 0x080c, 0x347d, - 0x1904, 0xdf33, 0x2001, 0x1800, 0x2004, 0x9086, 0x0002, 0x1138, - 0x00f6, 0x2079, 0x1800, 0x78a8, 0x8000, 0x78aa, 0x00fe, 0x2001, - 0x0002, 0x080c, 0x66fa, 0x6023, 0x0001, 0x6003, 0x0001, 0x6007, - 0x0002, 0x080c, 0x961e, 0x080c, 0x9ab3, 0x6110, 0x2158, 0x2009, - 0x0001, 0x080c, 0x89a1, 0x0804, 0xdf35, 0x6610, 0x2658, 0xbe04, - 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x0148, 0x9686, 0x0004, - 0x0130, 0x080c, 0x9228, 0x2001, 0x0004, 0x080c, 0x6726, 0x080c, - 0xee9d, 0x0904, 0xdf33, 0x2001, 0x0004, 0x080c, 0x66fa, 0x6023, - 0x0001, 0x6003, 0x0001, 0x6007, 0x0003, 0x080c, 0x961e, 0x0804, - 0xdf35, 0x2001, 0x1800, 0x2004, 0x9086, 0x0003, 0x1158, 0x0036, - 0x0046, 0x6010, 0x2058, 0xbba0, 0x2021, 0x0006, 0x080c, 0x4e58, - 0x004e, 0x003e, 0x2001, 0x0006, 0x080c, 0xdf4f, 0x6610, 0x2658, - 0xbe04, 0x0066, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x006e, - 0x0180, 0x2001, 0x0006, 0x080c, 0x6726, 0x9284, 0x00ff, 0x908e, - 0x0007, 0x0118, 0x908e, 0x0004, 0x1120, 0x2001, 0x0006, 0x080c, - 0x66fa, 0x080c, 0x6c09, 0x11f8, 0x2001, 0x1837, 0x2004, 0xd0a4, - 0x01d0, 0xbe04, 0x96b4, 0x00ff, 0x9686, 0x0006, 0x01a0, 0x00f6, - 0x2079, 0x1800, 0x78a8, 0x8000, 0x78aa, 0x00fe, 0x0804, 0xdea7, - 0x2001, 0x0004, 0x0030, 0x2001, 0x0006, 0x0409, 0x0020, 0x0018, - 0x0010, 0x080c, 0x6726, 0x080c, 0xb16c, 0x0005, 0x2600, 0x0002, - 0xdf4a, 0xdf4a, 0xdf4a, 0xdf4a, 0xdf4a, 0xdf4c, 0xdf4a, 0xdf4c, - 0xdf4a, 0xdf4a, 0xdf4c, 0xdf4a, 0xdf4a, 0xdf4a, 0xdf4c, 0xdf4c, - 0xdf4c, 0xdf4c, 0x080c, 0x0d85, 0x080c, 0xb16c, 0x0005, 0x0016, - 0x00b6, 0x00d6, 0x6110, 0x2158, 0xb900, 0xd184, 0x0138, 0x080c, - 0x66fa, 0x9006, 0x080c, 0x66e6, 0x080c, 0x3344, 0x00de, 0x00be, - 0x001e, 0x0005, 0x6610, 0x2658, 0xb804, 0x9084, 0xff00, 0x8007, - 0x90b2, 0x000c, 0x1a0c, 0x0d85, 0x91b6, 0x0015, 0x1110, 0x003b, - 0x0028, 0x91b6, 0x0016, 0x190c, 0x0d85, 0x006b, 0x0005, 0xbc45, - 0xbc45, 0xbc45, 0xbc45, 0xdfe4, 0xbc45, 0xdfce, 0xdf8f, 0xbc45, - 0xbc45, 0xbc45, 0xbc45, 0xbc45, 0xbc45, 0xbc45, 0xbc45, 0xdfe4, - 0xbc45, 0xdfce, 0xdfd5, 0xbc45, 0xbc45, 0xbc45, 0xbc45, 0x00f6, - 0x080c, 0x6c09, 0x11d8, 0x080c, 0xd645, 0x11c0, 0x6010, 0x905d, - 0x01a8, 0xb884, 0x9005, 0x0190, 0x9006, 0x080c, 0x66e6, 0x2001, - 0x0002, 0x080c, 0x66fa, 0x6023, 0x0001, 0x6003, 0x0001, 0x6007, - 0x0002, 0x080c, 0x961e, 0x080c, 0x9ab3, 0x00f0, 0x2011, 0x0263, - 0x2204, 0x8211, 0x220c, 0x080c, 0x268c, 0x11b0, 0x080c, 0x67b4, - 0x0118, 0x080c, 0xb16c, 0x0080, 0xb810, 0x0006, 0xb814, 0x0006, - 0xb884, 0x0006, 0x080c, 0x61b7, 0x000e, 0xb886, 0x000e, 0xb816, - 0x000e, 0xb812, 0x080c, 0xb16c, 0x00fe, 0x0005, 0x6604, 0x96b6, - 0x001e, 0x1110, 0x080c, 0xb16c, 0x0005, 0x080c, 0xc082, 0x1148, - 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x961e, 0x080c, 0x9ab3, - 0x0010, 0x080c, 0xb16c, 0x0005, 0x0804, 0xb16c, 0x6004, 0x908a, - 0x0053, 0x1a0c, 0x0d85, 0x080c, 0x99ed, 0x080c, 0xb1a7, 0x0005, - 0x9182, 0x0040, 0x0002, 0xe007, 0xe007, 0xe007, 0xe007, 0xe009, - 0xe007, 0xe007, 0xe007, 0xe007, 0xe007, 0xe007, 0xe007, 0xe007, - 0xe007, 0xe007, 0xe007, 0xe007, 0xe007, 0xe007, 0xe007, 0x080c, - 0x0d85, 0x0096, 0x00b6, 0x00d6, 0x00e6, 0x00f6, 0x0046, 0x0026, - 0x6210, 0x2258, 0xb8bc, 0x9005, 0x11b0, 0x6007, 0x0044, 0x2071, - 0x0260, 0x7444, 0x94a4, 0xff00, 0x0904, 0xe070, 0x080c, 0xee42, - 0x1170, 0x9486, 0x2000, 0x1158, 0x2009, 0x0001, 0x2011, 0x0200, - 0x080c, 0x8c44, 0x0020, 0x9026, 0x080c, 0xecc5, 0x0c30, 0x080c, - 0x1059, 0x090c, 0x0d85, 0x6003, 0x0007, 0xa867, 0x010d, 0x9006, - 0xa802, 0xa86a, 0xac8a, 0x2c00, 0xa88e, 0x6008, 0xa8e2, 0x6010, - 0x2058, 0xb8a0, 0x7130, 0xa97a, 0x0016, 0xa876, 0xa87f, 0x0000, - 0xa883, 0x0000, 0xa887, 0x0036, 0x080c, 0x7012, 0x001e, 0x080c, - 0xee42, 0x1904, 0xe0d0, 0x9486, 0x2000, 0x1130, 0x2019, 0x0017, - 0x080c, 0xe9f9, 0x0804, 0xe0d0, 0x9486, 0x0200, 0x1120, 0x080c, - 0xe984, 0x0804, 0xe0d0, 0x9486, 0x0400, 0x0120, 0x9486, 0x1000, - 0x1904, 0xe0d0, 0x2019, 0x0002, 0x080c, 0xe9a3, 0x0804, 0xe0d0, - 0x2069, 0x1a73, 0x6a00, 0xd284, 0x0904, 0xe13a, 0x9284, 0x0300, - 0x1904, 0xe133, 0x6804, 0x9005, 0x0904, 0xe11b, 0x2d78, 0x6003, - 0x0007, 0x080c, 0x1072, 0x0904, 0xe0dc, 0x7800, 0xd08c, 0x1118, - 0x7804, 0x8001, 0x7806, 0x6017, 0x0000, 0x2001, 0x180f, 0x2004, - 0xd084, 0x1904, 0xe13e, 0x9006, 0xa802, 0xa867, 0x0116, 0xa86a, - 0x6008, 0xa8e2, 0x2c00, 0xa87a, 0x6010, 0x2058, 0xb8a0, 0x7130, - 0xa9b6, 0xa876, 0xb928, 0xa9ba, 0xb92c, 0xa9be, 0xb930, 0xa9c2, - 0xb934, 0xa9c6, 0xa883, 0x003d, 0x7044, 0x9084, 0x0003, 0x9080, - 0xe0d8, 0x2005, 0xa87e, 0x20a9, 0x000a, 0x2001, 0x0270, 0xaa5c, - 0x9290, 0x0021, 0x2009, 0x0205, 0x200b, 0x0080, 0x20e1, 0x0000, - 0xab60, 0x23e8, 0x2098, 0x22a0, 0x4003, 0x200b, 0x0000, 0x2001, - 0x027a, 0x200c, 0xa9b2, 0x8000, 0x200c, 0xa9ae, 0x080c, 0x7015, - 0x002e, 0x004e, 0x00fe, 0x00ee, 0x00de, 0x00be, 0x009e, 0x0005, - 0x0000, 0x0080, 0x0040, 0x0000, 0x2001, 0x1810, 0x2004, 0xd084, - 0x0120, 0x080c, 0x1059, 0x1904, 0xe085, 0x6017, 0xf100, 0x6003, - 0x0001, 0x6007, 0x0041, 0x2009, 0xa022, 0x080c, 0x9617, 0x0c00, - 0x2069, 0x0260, 0x6848, 0x9084, 0xff00, 0x9086, 0x1200, 0x1198, - 0x686c, 0x9084, 0x00ff, 0x0016, 0x6114, 0x918c, 0xf700, 0x910d, - 0x6116, 0x001e, 0x6003, 0x0001, 0x6007, 0x0043, 0x2009, 0xa025, - 0x080c, 0x9617, 0x0828, 0x6868, 0x602e, 0x686c, 0x6032, 0x6017, - 0xf200, 0x6003, 0x0001, 0x6007, 0x0041, 0x2009, 0xa022, 0x080c, - 0x9617, 0x0804, 0xe0d0, 0x2001, 0x180e, 0x2004, 0xd0ec, 0x0120, - 0x2011, 0x8049, 0x080c, 0x4ca1, 0x6017, 0xf300, 0x0010, 0x6017, - 0xf100, 0x6003, 0x0001, 0x6007, 0x0041, 0x2009, 0xa022, 0x080c, - 0x9617, 0x0804, 0xe0d0, 0x6017, 0xf500, 0x0c98, 0x6017, 0xf600, - 0x0804, 0xe0f0, 0x6017, 0xf200, 0x0804, 0xe0f0, 0xa867, 0x0146, - 0xa86b, 0x0000, 0x6008, 0xa886, 0x2c00, 0xa87a, 0x7044, 0x9084, - 0x0003, 0x9080, 0xe0d8, 0x2005, 0xa87e, 0x2928, 0x6010, 0x2058, - 0xb8a0, 0xa876, 0xb828, 0xa88a, 0xb82c, 0xa88e, 0xb830, 0xa892, - 0xb834, 0xa896, 0xa883, 0x003d, 0x2009, 0x0205, 0x2104, 0x9085, - 0x0080, 0x200a, 0x20e1, 0x0000, 0x2011, 0x0210, 0x2214, 0x9294, - 0x0fff, 0xaaa2, 0x9282, 0x0111, 0x1a0c, 0x0d85, 0x8210, 0x821c, - 0x2001, 0x026c, 0x2098, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0029, - 0x20a0, 0x2011, 0xe1ba, 0x2041, 0x0001, 0x223d, 0x9784, 0x00ff, - 0x9322, 0x1208, 0x2300, 0x20a8, 0x4003, 0x931a, 0x0530, 0x8210, - 0xd7fc, 0x1130, 0x8d68, 0x2d0a, 0x2001, 0x0260, 0x2098, 0x0c68, - 0x2950, 0x080c, 0x1072, 0x0170, 0x2900, 0xb002, 0xa867, 0x0147, - 0xa86b, 0x0000, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x001b, 0x20a0, - 0x8840, 0x08d8, 0x2548, 0xa800, 0x902d, 0x0118, 0x080c, 0x108b, - 0x0cc8, 0x080c, 0x108b, 0x0804, 0xe0dc, 0x2548, 0x8847, 0x9885, - 0x0046, 0xa866, 0x2009, 0x0205, 0x200b, 0x0000, 0x080c, 0xea30, - 0x0804, 0xe0d0, 0x8010, 0x0004, 0x801a, 0x0006, 0x8018, 0x0008, - 0x8016, 0x000a, 0x8014, 0x9186, 0x0013, 0x1160, 0x6004, 0x908a, - 0x0057, 0x1a0c, 0x0d85, 0x9082, 0x0040, 0x0a0c, 0x0d85, 0x2008, - 0x0804, 0xe246, 0x9186, 0x0051, 0x0108, 0x0040, 0x080c, 0xaf61, - 0x01e8, 0x9086, 0x0002, 0x0904, 0xe28e, 0x00c0, 0x9186, 0x0027, - 0x0180, 0x9186, 0x0048, 0x0128, 0x9186, 0x0014, 0x0150, 0x190c, - 0x0d85, 0x080c, 0xaf61, 0x0150, 0x9086, 0x0004, 0x0904, 0xe32d, - 0x0028, 0x6004, 0x9082, 0x0040, 0x2008, 0x001a, 0x080c, 0xb227, - 0x0005, 0xe20d, 0xe20f, 0xe20f, 0xe236, 0xe20d, 0xe20d, 0xe20d, - 0xe20d, 0xe20d, 0xe20d, 0xe20d, 0xe20d, 0xe20d, 0xe20d, 0xe20d, - 0xe20d, 0xe20d, 0xe20d, 0xe20d, 0xe20d, 0x080c, 0x0d85, 0x080c, - 0x99ed, 0x080c, 0x9ab3, 0x0036, 0x0096, 0x6014, 0x904d, 0x01d8, - 0x080c, 0xcf1b, 0x01c0, 0x6003, 0x0002, 0x6010, 0x00b6, 0x2058, - 0xb800, 0x00be, 0xd0bc, 0x1178, 0x2019, 0x0004, 0x080c, 0xea30, - 0x6017, 0x0000, 0x6018, 0x9005, 0x1120, 0x2001, 0x1987, 0x2004, - 0x601a, 0x6003, 0x0007, 0x009e, 0x003e, 0x0005, 0x0096, 0x080c, - 0x99ed, 0x080c, 0x9ab3, 0x080c, 0xcf1b, 0x0120, 0x6014, 0x2048, - 0x080c, 0x108b, 0x080c, 0xb1a7, 0x009e, 0x0005, 0x0002, 0xe25b, - 0xe270, 0xe25d, 0xe285, 0xe25b, 0xe25b, 0xe25b, 0xe25b, 0xe25b, - 0xe25b, 0xe25b, 0xe25b, 0xe25b, 0xe25b, 0xe25b, 0xe25b, 0xe25b, - 0xe25b, 0xe25b, 0xe25b, 0x080c, 0x0d85, 0x0096, 0x6014, 0x2048, - 0xa87c, 0xd0b4, 0x0138, 0x6003, 0x0007, 0x2009, 0x0043, 0x080c, - 0xb20a, 0x0010, 0x6003, 0x0004, 0x080c, 0x9ab3, 0x009e, 0x0005, - 0x080c, 0xcf1b, 0x0138, 0x6114, 0x0096, 0x2148, 0xa97c, 0x009e, - 0xd1ec, 0x1138, 0x080c, 0x8c19, 0x080c, 0xb16c, 0x080c, 0x9ab3, - 0x0005, 0x080c, 0xec89, 0x0db0, 0x0cc8, 0x6003, 0x0001, 0x6007, - 0x0041, 0x2009, 0xa022, 0x080c, 0x9617, 0x0005, 0x9182, 0x0040, - 0x0002, 0xe2a5, 0xe2a7, 0xe2a5, 0xe2a5, 0xe2a5, 0xe2a5, 0xe2a5, - 0xe2a5, 0xe2a5, 0xe2a5, 0xe2a5, 0xe2a5, 0xe2a5, 0xe2a5, 0xe2a5, - 0xe2a5, 0xe2a5, 0xe2a8, 0xe2a5, 0xe2a5, 0x080c, 0x0d85, 0x0005, - 0x00d6, 0x080c, 0x8c19, 0x00de, 0x080c, 0xece1, 0x080c, 0xb16c, - 0x0005, 0x9182, 0x0040, 0x0002, 0xe2c8, 0xe2c8, 0xe2c8, 0xe2c8, - 0xe2c8, 0xe2c8, 0xe2c8, 0xe2c8, 0xe2c8, 0xe2ca, 0xe2f5, 0xe2c8, - 0xe2c8, 0xe2c8, 0xe2c8, 0xe2f5, 0xe2c8, 0xe2c8, 0xe2c8, 0xe2c8, - 0x080c, 0x0d85, 0x6014, 0x0096, 0x2048, 0xa87c, 0xd0fc, 0x0168, - 0x908c, 0x0003, 0x918e, 0x0002, 0x0180, 0x6144, 0xd1e4, 0x1168, - 0x2009, 0x0041, 0x009e, 0x0804, 0xe3b5, 0x6003, 0x0007, 0x601b, - 0x0000, 0x080c, 0x8c19, 0x009e, 0x0005, 0x6014, 0x2048, 0xa97c, - 0xd1ec, 0x1130, 0x080c, 0x8c19, 0x080c, 0xb16c, 0x009e, 0x0005, - 0x080c, 0xec89, 0x0db8, 0x009e, 0x0005, 0x2001, 0x180c, 0x200c, - 0xc1d4, 0x2102, 0x0036, 0x080c, 0x9a48, 0x080c, 0x9ab3, 0x6014, - 0x0096, 0x2048, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, - 0x0188, 0xa87c, 0x9084, 0x0003, 0x9086, 0x0002, 0x0140, 0xa8ac, - 0x6330, 0x931a, 0x6332, 0xa8b0, 0x632c, 0x931b, 0x632e, 0x6003, - 0x0002, 0x0080, 0x2019, 0x0004, 0x080c, 0xea30, 0x6018, 0x9005, - 0x1128, 0x2001, 0x1987, 0x2004, 0x8003, 0x601a, 0x6017, 0x0000, - 0x6003, 0x0007, 0x009e, 0x003e, 0x0005, 0x9182, 0x0040, 0x0002, - 0xe344, 0xe344, 0xe344, 0xe344, 0xe344, 0xe344, 0xe344, 0xe344, - 0xe346, 0xe344, 0xe344, 0xe344, 0xe344, 0xe344, 0xe344, 0xe344, - 0xe344, 0xe344, 0xe344, 0xe391, 0x080c, 0x0d85, 0x6014, 0x0096, - 0x2048, 0xa834, 0xaa38, 0x6110, 0x00b6, 0x2158, 0xb900, 0x00be, - 0xd1bc, 0x1190, 0x920d, 0x1518, 0xa87c, 0xd0fc, 0x0128, 0x2009, - 0x0041, 0x009e, 0x0804, 0xe3b5, 0x6003, 0x0007, 0x601b, 0x0000, - 0x080c, 0x8c19, 0x009e, 0x0005, 0x6124, 0xd1f4, 0x1d58, 0x0006, - 0x0046, 0xacac, 0x9422, 0xa9b0, 0x2200, 0x910b, 0x6030, 0x9420, - 0x6432, 0x602c, 0x9109, 0x612e, 0x004e, 0x000e, 0x08d8, 0x6110, - 0x00b6, 0x2158, 0xb900, 0x00be, 0xd1bc, 0x1178, 0x2009, 0x180e, - 0x210c, 0xd19c, 0x0118, 0x6003, 0x0007, 0x0010, 0x6003, 0x0006, - 0x00e9, 0x080c, 0x8c1b, 0x009e, 0x0005, 0x6003, 0x0002, 0x009e, - 0x0005, 0x6024, 0xd0f4, 0x0128, 0x080c, 0x16b0, 0x1904, 0xe346, - 0x0005, 0x6014, 0x0096, 0x2048, 0xa834, 0xa938, 0x009e, 0x9105, - 0x1120, 0x080c, 0x16b0, 0x1904, 0xe346, 0x0005, 0xd2fc, 0x0140, - 0x8002, 0x8000, 0x8212, 0x9291, 0x0000, 0x2009, 0x0009, 0x0010, - 0x2009, 0x0015, 0xaa9a, 0xa896, 0x0005, 0x9182, 0x0040, 0x0208, - 0x0062, 0x9186, 0x0013, 0x0120, 0x9186, 0x0014, 0x190c, 0x0d85, - 0x6024, 0xd0dc, 0x090c, 0x0d85, 0x0005, 0xe3d9, 0xe3e5, 0xe3f1, - 0xe3fd, 0xe3d9, 0xe3d9, 0xe3d9, 0xe3d9, 0xe3e0, 0xe3db, 0xe3db, - 0xe3d9, 0xe3d9, 0xe3d9, 0xe3d9, 0xe3db, 0xe3d9, 0xe3db, 0xe3d9, - 0xe3e0, 0x080c, 0x0d85, 0x6024, 0xd0dc, 0x090c, 0x0d85, 0x0005, - 0x6014, 0x9005, 0x190c, 0x0d85, 0x0005, 0x6003, 0x0001, 0x6106, - 0x0126, 0x2091, 0x8000, 0x2009, 0xa022, 0x080c, 0x95f9, 0x012e, - 0x0005, 0x6003, 0x0004, 0x6106, 0x0126, 0x2091, 0x8000, 0x2009, - 0xa001, 0x080c, 0x9617, 0x012e, 0x0005, 0x6003, 0x0003, 0x6106, - 0x6047, 0x0000, 0x080c, 0x1c6f, 0x0126, 0x2091, 0x8000, 0x6014, - 0x0096, 0x2048, 0xa87c, 0xd0fc, 0x0188, 0x9084, 0x0003, 0x9086, - 0x0002, 0x01a0, 0x6024, 0xd0cc, 0x1148, 0xd0c4, 0x1138, 0xa8a8, - 0x9005, 0x1120, 0x6144, 0x918d, 0xb035, 0x0018, 0x6144, 0x918d, - 0xa035, 0x009e, 0x080c, 0x965e, 0x012e, 0x0005, 0x6144, 0x918d, - 0xa032, 0x0cb8, 0x0126, 0x2091, 0x8000, 0x0036, 0x0096, 0x9182, - 0x0040, 0x0023, 0x009e, 0x003e, 0x012e, 0x0005, 0xe44a, 0xe44c, - 0xe461, 0xe47b, 0xe44a, 0xe44a, 0xe44a, 0xe44a, 0xe44a, 0xe44a, - 0xe44a, 0xe44a, 0xe44a, 0xe44a, 0xe44a, 0xe44a, 0xe44a, 0xe44a, - 0xe44a, 0xe44a, 0x080c, 0x0d85, 0x6014, 0x2048, 0xa87c, 0xd0fc, - 0x0510, 0x909c, 0x0003, 0x939e, 0x0003, 0x01e8, 0x6003, 0x0001, - 0x6106, 0x0126, 0x2091, 0x8000, 0x2009, 0xa022, 0x080c, 0x9617, - 0x0480, 0x6014, 0x2048, 0xa87c, 0xd0fc, 0x0168, 0x909c, 0x0003, - 0x939e, 0x0003, 0x0140, 0x6003, 0x0001, 0x6106, 0x2009, 0xa001, - 0x080c, 0x9617, 0x00f0, 0x901e, 0x6316, 0x631a, 0x2019, 0x0004, - 0x080c, 0xea30, 0x00b0, 0x6014, 0x2048, 0xa87c, 0xd0fc, 0x0d98, - 0x909c, 0x0003, 0x939e, 0x0003, 0x0d70, 0x6003, 0x0003, 0x6106, - 0x6047, 0x0000, 0x080c, 0x1c6f, 0x6144, 0x918d, 0xa035, 0x080c, - 0x965e, 0x0005, 0x080c, 0x99ed, 0x6114, 0x81ff, 0x0158, 0x0096, - 0x2148, 0x080c, 0xeddf, 0x0036, 0x2019, 0x0029, 0x080c, 0xea30, - 0x003e, 0x009e, 0x080c, 0xb1a7, 0x080c, 0x9ab3, 0x0005, 0x080c, - 0x9a48, 0x6114, 0x81ff, 0x0158, 0x0096, 0x2148, 0x080c, 0xeddf, - 0x0036, 0x2019, 0x0029, 0x080c, 0xea30, 0x003e, 0x009e, 0x080c, - 0xb1a7, 0x0005, 0x9182, 0x0085, 0x0002, 0xe4cc, 0xe4ca, 0xe4ca, - 0xe4d8, 0xe4ca, 0xe4ca, 0xe4ca, 0xe4ca, 0xe4ca, 0xe4ca, 0xe4ca, - 0xe4ca, 0xe4ca, 0x080c, 0x0d85, 0x6003, 0x000b, 0x6106, 0x0126, - 0x2091, 0x8000, 0x2009, 0x8020, 0x080c, 0x9617, 0x012e, 0x0005, - 0x0026, 0x00e6, 0x080c, 0xec80, 0x0118, 0x080c, 0xb16c, 0x0440, - 0x2071, 0x0260, 0x7224, 0x6216, 0x2001, 0x180e, 0x2004, 0xd0e4, - 0x0150, 0x6010, 0x00b6, 0x2058, 0xbca0, 0x00be, 0x2c00, 0x2011, - 0x014e, 0x080c, 0xb495, 0x7220, 0x080c, 0xe875, 0x0118, 0x6007, - 0x0086, 0x0040, 0x6007, 0x0087, 0x7224, 0x9296, 0xffff, 0x1110, - 0x6007, 0x0086, 0x6003, 0x0001, 0x2009, 0x8020, 0x080c, 0x9617, - 0x00ee, 0x002e, 0x0005, 0x9186, 0x0013, 0x1160, 0x6004, 0x908a, - 0x0085, 0x0a0c, 0x0d85, 0x908a, 0x0092, 0x1a0c, 0x0d85, 0x9082, - 0x0085, 0x00a2, 0x9186, 0x0027, 0x0130, 0x9186, 0x0014, 0x0118, - 0x080c, 0xb227, 0x0050, 0x2001, 0x0007, 0x080c, 0x6726, 0x080c, - 0x99ed, 0x080c, 0xb1a7, 0x080c, 0x9ab3, 0x0005, 0xe53b, 0xe53d, - 0xe53d, 0xe53b, 0xe53b, 0xe53b, 0xe53b, 0xe53b, 0xe53b, 0xe53b, - 0xe53b, 0xe53b, 0xe53b, 0x080c, 0x0d85, 0x080c, 0xb1a7, 0x080c, - 0x9ab3, 0x0005, 0x9182, 0x0085, 0x0a0c, 0x0d85, 0x9182, 0x0092, - 0x1a0c, 0x0d85, 0x9182, 0x0085, 0x0002, 0xe55a, 0xe55a, 0xe55a, - 0xe55c, 0xe55a, 0xe55a, 0xe55a, 0xe55a, 0xe55a, 0xe55a, 0xe55a, - 0xe55a, 0xe55a, 0x080c, 0x0d85, 0x0005, 0x9186, 0x0013, 0x0148, - 0x9186, 0x0014, 0x0130, 0x9186, 0x0027, 0x0118, 0x080c, 0xb227, - 0x0020, 0x080c, 0x99ed, 0x080c, 0xb1a7, 0x0005, 0x0036, 0x080c, - 0xece1, 0x604b, 0x0000, 0x2019, 0x000b, 0x0011, 0x003e, 0x0005, - 0x6010, 0x0006, 0x0059, 0x000e, 0x6012, 0x6023, 0x0006, 0x6003, - 0x0007, 0x601b, 0x0000, 0x604b, 0x0000, 0x0005, 0x0126, 0x0036, - 0x2091, 0x8000, 0x080c, 0xacfc, 0x0106, 0x0086, 0x2c40, 0x0096, - 0x904e, 0x080c, 0xa667, 0x009e, 0x008e, 0x1558, 0x0076, 0x2c38, - 0x080c, 0xa712, 0x007e, 0x1528, 0x6000, 0x9086, 0x0000, 0x0508, - 0x6020, 0x9086, 0x0007, 0x01e8, 0x0096, 0x601c, 0xd084, 0x0140, - 0x080c, 0xece1, 0x080c, 0xd65d, 0x080c, 0x1ad3, 0x6023, 0x0007, - 0x6014, 0x2048, 0x080c, 0xcf1b, 0x0110, 0x080c, 0xea30, 0x009e, - 0x9006, 0x6046, 0x6016, 0x080c, 0xece1, 0x6023, 0x0007, 0x080c, - 0xd65d, 0x010e, 0x090c, 0xad18, 0x003e, 0x012e, 0x0005, 0x00f6, - 0x00c6, 0x00b6, 0x0036, 0x0156, 0x2079, 0x0260, 0x7938, 0x783c, - 0x080c, 0x268c, 0x1904, 0xe621, 0x0016, 0x00c6, 0x080c, 0x67b4, - 0x1904, 0xe61f, 0x001e, 0x00c6, 0x080c, 0xd645, 0x1130, 0xb884, - 0x9005, 0x0118, 0x080c, 0x347d, 0x0148, 0x2b10, 0x2160, 0x6010, - 0x0006, 0x6212, 0x080c, 0xd64c, 0x000e, 0x6012, 0x00ce, 0x002e, - 0x0026, 0x0016, 0x080c, 0xacfc, 0x2019, 0x0029, 0x080c, 0xa7e2, - 0x080c, 0x97b0, 0x0076, 0x903e, 0x080c, 0x966d, 0x007e, 0x001e, - 0x0076, 0x903e, 0x080c, 0xe75d, 0x007e, 0x080c, 0xad18, 0x0026, - 0xba04, 0x9294, 0xff00, 0x8217, 0x9286, 0x0006, 0x0118, 0x9286, - 0x0004, 0x1118, 0xbaa0, 0x080c, 0x33e0, 0x002e, 0xbc84, 0x001e, - 0x080c, 0x61b7, 0xbe12, 0xbd16, 0xbc86, 0x9006, 0x0010, 0x00ce, - 0x001e, 0x015e, 0x003e, 0x00be, 0x00ce, 0x00fe, 0x0005, 0x00c6, - 0x00d6, 0x00b6, 0x0016, 0x2009, 0x1824, 0x2104, 0x9086, 0x0074, - 0x1904, 0xe680, 0x2069, 0x0260, 0x6944, 0x9182, 0x0100, 0x06e0, - 0x6940, 0x9184, 0x8000, 0x0904, 0xe67d, 0x2001, 0x197c, 0x2004, - 0x9005, 0x1140, 0x6010, 0x2058, 0xb884, 0x9005, 0x0118, 0x9184, - 0x0800, 0x0598, 0x6948, 0x918a, 0x0001, 0x0648, 0x080c, 0xee47, - 0x0118, 0x6978, 0xd1fc, 0x11b8, 0x2009, 0x0205, 0x200b, 0x0001, - 0x693c, 0x81ff, 0x1198, 0x6944, 0x9182, 0x0100, 0x02a8, 0x6940, - 0x81ff, 0x1178, 0x6948, 0x918a, 0x0001, 0x0288, 0x6950, 0x918a, - 0x0001, 0x0298, 0x00d0, 0x6017, 0x0100, 0x00a0, 0x6017, 0x0300, - 0x0088, 0x6017, 0x0500, 0x0070, 0x6017, 0x0700, 0x0058, 0x6017, - 0x0900, 0x0040, 0x6017, 0x0b00, 0x0028, 0x6017, 0x0f00, 0x0010, - 0x6017, 0x2d00, 0x9085, 0x0001, 0x0008, 0x9006, 0x001e, 0x00be, - 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00b6, 0x0026, 0x0036, 0x0156, - 0x6210, 0x2258, 0xbb04, 0x9394, 0x00ff, 0x9286, 0x0006, 0x0180, - 0x9286, 0x0004, 0x0168, 0x9394, 0xff00, 0x8217, 0x9286, 0x0006, - 0x0138, 0x9286, 0x0004, 0x0120, 0x080c, 0x67c3, 0x0804, 0xe6ec, - 0x2011, 0x0276, 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, 0x000a, - 0x080c, 0xc222, 0x009e, 0x15c8, 0x2011, 0x027a, 0x20a9, 0x0004, - 0x0096, 0x2b48, 0x2019, 0x0006, 0x080c, 0xc222, 0x009e, 0x1568, - 0x0046, 0x0016, 0xbaa0, 0x2220, 0x9006, 0x2009, 0x1848, 0x210c, - 0xd1a4, 0x0138, 0x2009, 0x0029, 0x080c, 0xea8d, 0xb800, 0xc0e5, - 0xb802, 0x080c, 0xacfc, 0x2019, 0x0029, 0x080c, 0x97b0, 0x0076, - 0x2039, 0x0000, 0x080c, 0x966d, 0x2c08, 0x080c, 0xe75d, 0x007e, - 0x080c, 0xad18, 0x2001, 0x0007, 0x080c, 0x6726, 0x2001, 0x0007, - 0x080c, 0x66fa, 0x001e, 0x004e, 0x9006, 0x015e, 0x003e, 0x002e, - 0x00be, 0x00ce, 0x0005, 0x00d6, 0x2069, 0x026e, 0x6800, 0x9086, - 0x0800, 0x0118, 0x6017, 0x0000, 0x0008, 0x9006, 0x00de, 0x0005, - 0x00b6, 0x00f6, 0x0016, 0x0026, 0x0036, 0x0156, 0x2079, 0x026c, - 0x7930, 0x7834, 0x080c, 0x268c, 0x11d0, 0x080c, 0x67b4, 0x11b8, - 0x2011, 0x0270, 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, 0x000a, - 0x080c, 0xc222, 0x009e, 0x1158, 0x2011, 0x0274, 0x20a9, 0x0004, - 0x0096, 0x2b48, 0x2019, 0x0006, 0x080c, 0xc222, 0x009e, 0x015e, - 0x003e, 0x002e, 0x001e, 0x00fe, 0x00be, 0x0005, 0x00b6, 0x0006, - 0x0016, 0x0026, 0x0036, 0x0156, 0x2011, 0x0263, 0x2204, 0x8211, - 0x220c, 0x080c, 0x268c, 0x11d0, 0x080c, 0x67b4, 0x11b8, 0x2011, - 0x0276, 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, 0x000a, 0x080c, - 0xc222, 0x009e, 0x1158, 0x2011, 0x027a, 0x20a9, 0x0004, 0x0096, - 0x2b48, 0x2019, 0x0006, 0x080c, 0xc222, 0x009e, 0x015e, 0x003e, - 0x002e, 0x001e, 0x000e, 0x00be, 0x0005, 0x00e6, 0x00c6, 0x0086, - 0x0076, 0x0066, 0x0056, 0x0046, 0x0026, 0x0126, 0x2091, 0x8000, - 0x080c, 0xad5a, 0x0106, 0x190c, 0xacfc, 0x2740, 0x2029, 0x19f4, - 0x252c, 0x2021, 0x19fb, 0x2424, 0x2061, 0x1ddc, 0x2071, 0x1800, - 0x7654, 0x7074, 0x81ff, 0x0150, 0x0006, 0x9186, 0x1b39, 0x000e, - 0x0128, 0x8001, 0x9602, 0x1a04, 0xe803, 0x0018, 0x9606, 0x0904, - 0xe803, 0x080c, 0x8eee, 0x0904, 0xe7fa, 0x2100, 0x9c06, 0x0904, - 0xe7fa, 0x6720, 0x9786, 0x0007, 0x0904, 0xe7fa, 0x080c, 0xeace, - 0x1904, 0xe7fa, 0x080c, 0xee65, 0x0904, 0xe7fa, 0x080c, 0xeabe, - 0x0904, 0xe7fa, 0x6720, 0x9786, 0x0001, 0x1148, 0x080c, 0x347d, - 0x0904, 0xe845, 0x6004, 0x9086, 0x0000, 0x1904, 0xe845, 0x9786, - 0x0004, 0x0904, 0xe845, 0x2500, 0x9c06, 0x0904, 0xe7fa, 0x2400, - 0x9c06, 0x0904, 0xe7fa, 0x88ff, 0x0118, 0x605c, 0x9906, 0x15d0, - 0x0096, 0x6043, 0xffff, 0x6000, 0x9086, 0x0004, 0x1120, 0x0016, - 0x080c, 0x1ad3, 0x001e, 0x9786, 0x000a, 0x0148, 0x080c, 0xd132, - 0x1130, 0x080c, 0xbb5c, 0x009e, 0x080c, 0xb1a7, 0x0418, 0x6014, - 0x2048, 0x080c, 0xcf1b, 0x01d8, 0x9786, 0x0003, 0x1588, 0xa867, - 0x0103, 0xa87c, 0xd0cc, 0x0130, 0x0096, 0xa878, 0x2048, 0x080c, - 0x100b, 0x009e, 0xab7a, 0xa877, 0x0000, 0x080c, 0xeddf, 0x0016, - 0x080c, 0xd220, 0x080c, 0x7006, 0x001e, 0x080c, 0xd10c, 0x009e, - 0x080c, 0xb1a7, 0x9ce0, 0x001c, 0x2001, 0x181a, 0x2004, 0x9c02, - 0x1210, 0x0804, 0xe776, 0x010e, 0x190c, 0xad18, 0x012e, 0x002e, - 0x004e, 0x005e, 0x006e, 0x007e, 0x008e, 0x00ce, 0x00ee, 0x0005, - 0x9786, 0x0006, 0x1150, 0x9386, 0x0005, 0x0128, 0x080c, 0xeddf, - 0x080c, 0xea30, 0x08e0, 0x009e, 0x08e8, 0x9786, 0x0009, 0x11f8, - 0x6000, 0x9086, 0x0004, 0x01c0, 0x6000, 0x9086, 0x0003, 0x11a0, - 0x080c, 0x9a48, 0x0096, 0x6114, 0x2148, 0x080c, 0xcf1b, 0x0118, - 0x6010, 0x080c, 0x7012, 0x009e, 0x00c6, 0x080c, 0xb16c, 0x00ce, - 0x0036, 0x080c, 0x9ab3, 0x003e, 0x009e, 0x0804, 0xe7fa, 0x9786, - 0x000a, 0x0904, 0xe7ea, 0x0804, 0xe7df, 0x81ff, 0x0904, 0xe7fa, - 0x9180, 0x0001, 0x2004, 0x9086, 0x0018, 0x0138, 0x9180, 0x0001, - 0x2004, 0x9086, 0x002d, 0x1904, 0xe7fa, 0x6000, 0x9086, 0x0002, - 0x1904, 0xe7fa, 0x080c, 0xd121, 0x0138, 0x080c, 0xd132, 0x1904, - 0xe7fa, 0x080c, 0xbb5c, 0x0038, 0x080c, 0x3344, 0x080c, 0xd132, - 0x1110, 0x080c, 0xbb5c, 0x080c, 0xb1a7, 0x0804, 0xe7fa, 0xa864, - 0x9084, 0x00ff, 0x9086, 0x0039, 0x0005, 0x00c6, 0x00e6, 0x0016, - 0x2c08, 0x2170, 0x9006, 0x080c, 0xea57, 0x001e, 0x0120, 0x6020, - 0x9084, 0x000f, 0x001b, 0x00ee, 0x00ce, 0x0005, 0xe894, 0xe894, - 0xe894, 0xe894, 0xe894, 0xe894, 0xe896, 0xe894, 0xe894, 0xe894, - 0xe8bf, 0xb1a7, 0xb1a7, 0xe894, 0x9006, 0x0005, 0x0036, 0x0046, - 0x0016, 0x7010, 0x00b6, 0x2058, 0xbca0, 0x00be, 0x2c00, 0x2009, - 0x0020, 0x080c, 0xea8d, 0x001e, 0x004e, 0x2019, 0x0002, 0x080c, - 0xe586, 0x003e, 0x9085, 0x0001, 0x0005, 0x0096, 0x080c, 0xcf1b, - 0x0140, 0x6014, 0x904d, 0x080c, 0xcae9, 0x687b, 0x0005, 0x080c, - 0x7012, 0x009e, 0x080c, 0xb1a7, 0x9085, 0x0001, 0x0005, 0x0019, - 0x9085, 0x0001, 0x0005, 0x6000, 0x908a, 0x0010, 0x1a0c, 0x0d85, - 0x000b, 0x0005, 0xe8da, 0xe8da, 0xe8f1, 0xe8e1, 0xe900, 0xe8da, - 0xe8da, 0xe8dc, 0xe8da, 0xe8da, 0xe8da, 0xe8da, 0xe8da, 0xe8da, - 0xe8da, 0xe8da, 0x080c, 0x0d85, 0x080c, 0xb1a7, 0x9085, 0x0001, - 0x0005, 0x0036, 0x00e6, 0x2071, 0x19e8, 0x704c, 0x9c06, 0x1128, - 0x2019, 0x0001, 0x080c, 0xa596, 0x0010, 0x080c, 0xa7a1, 0x00ee, - 0x003e, 0x0096, 0x00d6, 0x6014, 0x2048, 0xa87b, 0x0005, 0x080c, - 0x7012, 0x080c, 0xb1a7, 0x00de, 0x009e, 0x9085, 0x0001, 0x0005, - 0x601c, 0xd084, 0x190c, 0x1ad3, 0x0c60, 0x2001, 0x0001, 0x080c, - 0x66e6, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, - 0x1805, 0x2011, 0x0276, 0x080c, 0xc20e, 0x003e, 0x002e, 0x001e, - 0x015e, 0x9005, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0086, 0x0076, - 0x0066, 0x00b6, 0x0126, 0x2091, 0x8000, 0x2740, 0x2061, 0x1ddc, - 0x2079, 0x0001, 0x8fff, 0x0904, 0xe977, 0x2071, 0x1800, 0x7654, - 0x7074, 0x8001, 0x9602, 0x1a04, 0xe977, 0x88ff, 0x0120, 0x2800, - 0x9c06, 0x15a0, 0x2078, 0x080c, 0xeabe, 0x0580, 0x2400, 0x9c06, - 0x0568, 0x6720, 0x9786, 0x0006, 0x1548, 0x9786, 0x0007, 0x0530, - 0x88ff, 0x1150, 0xd58c, 0x1118, 0x6010, 0x9b06, 0x11f8, 0xd584, - 0x0118, 0x605c, 0x9106, 0x11d0, 0x0096, 0x601c, 0xd084, 0x0140, - 0x080c, 0xece1, 0x080c, 0xd65d, 0x080c, 0x1ad3, 0x6023, 0x0007, - 0x6014, 0x2048, 0x080c, 0xcf1b, 0x0120, 0x0046, 0x080c, 0xea30, - 0x004e, 0x009e, 0x080c, 0xb1a7, 0x88ff, 0x1198, 0x9ce0, 0x001c, - 0x2001, 0x181a, 0x2004, 0x9c02, 0x1210, 0x0804, 0xe92a, 0x9006, - 0x012e, 0x00be, 0x006e, 0x007e, 0x008e, 0x00ce, 0x00ee, 0x00fe, - 0x0005, 0x98c5, 0x0001, 0x0ca0, 0x080c, 0xacfc, 0x00b6, 0x0076, - 0x0056, 0x0086, 0x9046, 0x2029, 0x0001, 0x2c20, 0x2019, 0x0002, - 0x6210, 0x2258, 0x0096, 0x904e, 0x080c, 0xa667, 0x009e, 0x008e, - 0x903e, 0x080c, 0xa712, 0x080c, 0xe91b, 0x005e, 0x007e, 0x00be, - 0x080c, 0xad18, 0x0005, 0x080c, 0xacfc, 0x00b6, 0x0046, 0x0056, - 0x0076, 0x00c6, 0x0156, 0x2c20, 0x2128, 0x20a9, 0x007f, 0x900e, - 0x0016, 0x0036, 0x080c, 0x67b4, 0x1180, 0x0056, 0x0086, 0x9046, - 0x2508, 0x2029, 0x0001, 0x0096, 0x904e, 0x080c, 0xa667, 0x009e, - 0x008e, 0x903e, 0x080c, 0xa712, 0x005e, 0x003e, 0x001e, 0x8108, - 0x1f04, 0xe9b0, 0x0036, 0x2508, 0x2029, 0x0003, 0x080c, 0xe91b, - 0x003e, 0x015e, 0x00ce, 0x007e, 0x005e, 0x004e, 0x00be, 0x080c, - 0xad18, 0x0005, 0x080c, 0xacfc, 0x00b6, 0x0076, 0x0056, 0x6210, - 0x2258, 0x0086, 0x9046, 0x2029, 0x0001, 0x2019, 0x0048, 0x0096, - 0x904e, 0x080c, 0xa667, 0x009e, 0x008e, 0x903e, 0x080c, 0xa712, - 0x2c20, 0x080c, 0xe91b, 0x005e, 0x007e, 0x00be, 0x080c, 0xad18, - 0x0005, 0x080c, 0xacfc, 0x00b6, 0x0046, 0x0056, 0x0076, 0x00c6, - 0x0156, 0x2c20, 0x20a9, 0x0800, 0x900e, 0x0016, 0x0036, 0x080c, - 0x67b4, 0x1190, 0x0086, 0x9046, 0x2828, 0x0046, 0x2021, 0x0001, - 0x080c, 0xecc5, 0x004e, 0x0096, 0x904e, 0x080c, 0xa667, 0x009e, - 0x008e, 0x903e, 0x080c, 0xa712, 0x003e, 0x001e, 0x8108, 0x1f04, - 0xea05, 0x0036, 0x2029, 0x0002, 0x080c, 0xe91b, 0x003e, 0x015e, - 0x00ce, 0x007e, 0x005e, 0x004e, 0x00be, 0x080c, 0xad18, 0x0005, - 0x0016, 0x00f6, 0x080c, 0xcf19, 0x0198, 0xa864, 0x9084, 0x00ff, - 0x9086, 0x0046, 0x0180, 0xa800, 0x907d, 0x0138, 0xa803, 0x0000, - 0xab82, 0x080c, 0x7012, 0x2f48, 0x0cb0, 0xab82, 0x080c, 0x7012, - 0x00fe, 0x001e, 0x0005, 0xa800, 0x907d, 0x0130, 0xa803, 0x0000, - 0x080c, 0x7012, 0x2f48, 0x0cb8, 0x080c, 0x7012, 0x0c88, 0x00e6, - 0x0046, 0x0036, 0x2061, 0x1ddc, 0x9005, 0x1138, 0x2071, 0x1800, - 0x7454, 0x7074, 0x8001, 0x9402, 0x12f8, 0x2100, 0x9c06, 0x0188, - 0x6000, 0x9086, 0x0000, 0x0168, 0x6008, 0x9206, 0x1150, 0x6320, - 0x9386, 0x0009, 0x01b0, 0x6010, 0x91a0, 0x0004, 0x2424, 0x9406, - 0x0140, 0x9ce0, 0x001c, 0x2001, 0x181a, 0x2004, 0x9c02, 0x1220, - 0x0c20, 0x9085, 0x0001, 0x0008, 0x9006, 0x003e, 0x004e, 0x00ee, - 0x0005, 0x631c, 0xd3c4, 0x1d68, 0x0c30, 0x0096, 0x0006, 0x080c, - 0x1059, 0x000e, 0x090c, 0x0d85, 0xaae2, 0xa867, 0x010d, 0xa88e, - 0x0026, 0x2010, 0x080c, 0xcf09, 0x2001, 0x0000, 0x0120, 0x2200, - 0x9080, 0x0017, 0x2004, 0x002e, 0xa87a, 0x9186, 0x0020, 0x0110, - 0xa8e3, 0xffff, 0xa986, 0xac76, 0xa87f, 0x0000, 0x2001, 0x198e, - 0x2004, 0xa882, 0x9006, 0xa802, 0xa86a, 0xa88a, 0x0126, 0x2091, - 0x8000, 0x080c, 0x7012, 0x012e, 0x009e, 0x0005, 0x6700, 0x9786, - 0x0000, 0x0158, 0x9786, 0x0001, 0x0140, 0x9786, 0x000a, 0x0128, - 0x9786, 0x0009, 0x0110, 0x9085, 0x0001, 0x0005, 0x00e6, 0x6010, - 0x9075, 0x0138, 0x00b6, 0x2058, 0xb8a0, 0x00be, 0x9206, 0x00ee, - 0x0005, 0x9085, 0x0001, 0x0cd8, 0x0016, 0x6004, 0x908e, 0x001e, - 0x11a0, 0x8007, 0x6134, 0x918c, 0x00ff, 0x9105, 0x6036, 0x6007, - 0x0085, 0x6003, 0x000b, 0x6023, 0x0005, 0x2001, 0x1987, 0x2004, - 0x601a, 0x2009, 0x8020, 0x080c, 0x9617, 0x001e, 0x0005, 0xa001, - 0xa001, 0x0005, 0x6024, 0xd0e4, 0x0158, 0xd0cc, 0x0118, 0x080c, - 0xd267, 0x0030, 0x080c, 0xece1, 0x080c, 0x8c19, 0x080c, 0xb16c, - 0x0005, 0x9280, 0x0008, 0x2004, 0x9084, 0x000f, 0x0002, 0xeb1d, - 0xeb1d, 0xeb1d, 0xeb1f, 0xeb1d, 0xeb1f, 0xeb1f, 0xeb1d, 0xeb1f, - 0xeb1d, 0xeb1d, 0xeb1d, 0xeb1d, 0xeb1d, 0x9006, 0x0005, 0x9085, - 0x0001, 0x0005, 0x9280, 0x0008, 0x2004, 0x9084, 0x000f, 0x0002, - 0xeb36, 0xeb36, 0xeb36, 0xeb36, 0xeb36, 0xeb36, 0xeb43, 0xeb36, - 0xeb36, 0xeb36, 0xeb36, 0xeb36, 0xeb36, 0xeb36, 0x6007, 0x003b, - 0x602f, 0x0009, 0x6017, 0x2a00, 0x6003, 0x0001, 0x2009, 0x8020, - 0x080c, 0x9617, 0x0005, 0x0096, 0x00c6, 0x2260, 0x080c, 0xece1, - 0x604b, 0x0000, 0x6024, 0xc0f4, 0xc0e4, 0x6026, 0x603b, 0x0000, - 0x00ce, 0x00d6, 0x2268, 0x9186, 0x0007, 0x1904, 0xeb9c, 0x6814, - 0x9005, 0x0138, 0x2048, 0xa87c, 0xd0fc, 0x1118, 0x00de, 0x009e, - 0x08a8, 0x6007, 0x003a, 0x6003, 0x0001, 0x2009, 0x8020, 0x080c, - 0x9617, 0x00c6, 0x2d60, 0x6100, 0x9186, 0x0002, 0x1904, 0xec0c, - 0x6014, 0x9005, 0x1138, 0x6000, 0x9086, 0x0007, 0x190c, 0x0d85, - 0x0804, 0xec0c, 0x2048, 0x080c, 0xcf1b, 0x1130, 0x0028, 0x2048, - 0xa800, 0x9005, 0x1de0, 0x2900, 0x2048, 0xa87c, 0x9084, 0x0003, - 0x9086, 0x0002, 0x1168, 0xa87c, 0xc0dc, 0xc0f4, 0xa87e, 0xa880, - 0xc0fc, 0xa882, 0x2009, 0x0043, 0x080c, 0xe3b5, 0x0804, 0xec0c, - 0x2009, 0x0041, 0x0804, 0xec06, 0x9186, 0x0005, 0x15a0, 0x6814, - 0x2048, 0xa87c, 0xd0bc, 0x1120, 0x00de, 0x009e, 0x0804, 0xeb36, - 0xd0b4, 0x0128, 0xd0fc, 0x090c, 0x0d85, 0x0804, 0xeb57, 0x6007, - 0x003a, 0x6003, 0x0001, 0x2009, 0x8020, 0x080c, 0x9617, 0x00c6, - 0x2d60, 0x6100, 0x9186, 0x0002, 0x0120, 0x9186, 0x0004, 0x1904, - 0xec0c, 0x6814, 0x2048, 0xa97c, 0xc1f4, 0xc1dc, 0xa97e, 0xa980, - 0xc1fc, 0xc1bc, 0xa982, 0x00f6, 0x2c78, 0x080c, 0x17ad, 0x00fe, - 0x2009, 0x0042, 0x0498, 0x0036, 0x080c, 0x1059, 0x090c, 0x0d85, - 0xa867, 0x010d, 0x9006, 0xa802, 0xa86a, 0xa88a, 0x2d18, 0xab8e, - 0xa887, 0x0045, 0x2c00, 0xa892, 0x6038, 0xa8a2, 0x2360, 0x6024, - 0xc0dd, 0x6026, 0x6010, 0x00b6, 0x2058, 0xb8a0, 0x00be, 0x2004, - 0x635c, 0xab7a, 0xa876, 0x9006, 0xa87e, 0xa882, 0xad9a, 0xae96, - 0xa89f, 0x0001, 0x080c, 0x7012, 0x2019, 0x0045, 0x6008, 0x2068, - 0x080c, 0xe578, 0x2d00, 0x600a, 0x003e, 0x0038, 0x604b, 0x0000, - 0x6003, 0x0007, 0x080c, 0xe3b5, 0x00ce, 0x00de, 0x009e, 0x0005, - 0x9186, 0x0013, 0x1128, 0x6004, 0x9082, 0x0085, 0x2008, 0x00c2, - 0x9186, 0x0027, 0x1178, 0x080c, 0x99ed, 0x0036, 0x0096, 0x6014, - 0x2048, 0x2019, 0x0004, 0x080c, 0xea30, 0x009e, 0x003e, 0x080c, - 0x9ab3, 0x0005, 0x9186, 0x0014, 0x0d70, 0x080c, 0xb227, 0x0005, - 0xec3f, 0xec3d, 0xec3d, 0xec3d, 0xec3d, 0xec3d, 0xec3f, 0xec3d, - 0xec3d, 0xec3d, 0xec3d, 0xec3d, 0xec3d, 0x080c, 0x0d85, 0x6003, - 0x000c, 0x080c, 0x9ab3, 0x0005, 0x9182, 0x0092, 0x1220, 0x9182, - 0x0085, 0x0208, 0x001a, 0x080c, 0xb227, 0x0005, 0xec5b, 0xec5b, - 0xec5b, 0xec5b, 0xec5d, 0xec7d, 0xec5b, 0xec5b, 0xec5b, 0xec5b, - 0xec5b, 0xec5b, 0xec5b, 0x080c, 0x0d85, 0x00d6, 0x2c68, 0x080c, - 0xb116, 0x01b0, 0x6003, 0x0001, 0x6007, 0x001e, 0x2009, 0x026e, - 0x210c, 0x613a, 0x2009, 0x026f, 0x210c, 0x613e, 0x600b, 0xffff, - 0x6910, 0x6112, 0x6023, 0x0004, 0x2009, 0x8020, 0x080c, 0x9617, - 0x2d60, 0x080c, 0xb16c, 0x00de, 0x0005, 0x080c, 0xb16c, 0x0005, - 0x00e6, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0ec, 0x00ee, - 0x0005, 0x2009, 0x1867, 0x210c, 0xd1ec, 0x05b0, 0x6003, 0x0002, - 0x6024, 0xc0e5, 0x6026, 0xd0cc, 0x0150, 0x2001, 0x1988, 0x2004, - 0x604a, 0x2009, 0x1867, 0x210c, 0xd1f4, 0x1520, 0x00a0, 0x2009, - 0x1867, 0x210c, 0xd1f4, 0x0128, 0x6024, 0xc0e4, 0x6026, 0x9006, - 0x00d8, 0x2001, 0x1988, 0x200c, 0x2001, 0x1986, 0x2004, 0x9100, - 0x9080, 0x000a, 0x604a, 0x6010, 0x00b6, 0x2058, 0xb8bc, 0x00be, - 0x0008, 0x2104, 0x9005, 0x0118, 0x9088, 0x0003, 0x0cd0, 0x2c0a, - 0x600f, 0x0000, 0x9085, 0x0001, 0x0005, 0x0016, 0x00c6, 0x00e6, - 0x615c, 0xb8bc, 0x2060, 0x8cff, 0x0180, 0x84ff, 0x1118, 0x605c, - 0x9106, 0x1138, 0x600c, 0x2072, 0x080c, 0x8c19, 0x080c, 0xb16c, - 0x0010, 0x9cf0, 0x0003, 0x2e64, 0x0c70, 0x00ee, 0x00ce, 0x001e, - 0x0005, 0x00d6, 0x00b6, 0x6010, 0x2058, 0xb8bc, 0x906d, 0x0130, - 0x9c06, 0x0110, 0x680c, 0x0cd0, 0x600c, 0x680e, 0x00be, 0x00de, - 0x0005, 0x0026, 0x0036, 0x0156, 0x2011, 0x182c, 0x2204, 0x9084, - 0x00ff, 0x2019, 0x026e, 0x2334, 0x96b4, 0x00ff, 0x9636, 0x1508, - 0x8318, 0x2334, 0x2204, 0x9084, 0xff00, 0x9636, 0x11d0, 0x2011, - 0x0270, 0x20a9, 0x0004, 0x6010, 0x0096, 0x2048, 0x2019, 0x000a, - 0x080c, 0xc222, 0x009e, 0x1168, 0x2011, 0x0274, 0x20a9, 0x0004, - 0x6010, 0x0096, 0x2048, 0x2019, 0x0006, 0x080c, 0xc222, 0x009e, - 0x1100, 0x015e, 0x003e, 0x002e, 0x0005, 0x00e6, 0x2071, 0x1800, - 0x080c, 0x6130, 0x080c, 0x30bf, 0x00ee, 0x0005, 0x0096, 0x0026, - 0x080c, 0x1059, 0x090c, 0x0d85, 0xa85c, 0x9080, 0x001a, 0x20a0, - 0x20a9, 0x000c, 0xa860, 0x20e8, 0x9006, 0x4004, 0x9186, 0x0046, - 0x1118, 0xa867, 0x0136, 0x0038, 0xa867, 0x0138, 0x9186, 0x0041, - 0x0110, 0xa87b, 0x0001, 0x7038, 0x9084, 0xff00, 0x7240, 0x9294, - 0xff00, 0x8007, 0x9215, 0xaa9a, 0x9186, 0x0046, 0x1168, 0x7038, - 0x9084, 0x00ff, 0x723c, 0x9294, 0xff00, 0x9215, 0xaa9e, 0x723c, - 0x9294, 0x00ff, 0xaaa2, 0x0060, 0x7040, 0x9084, 0x00ff, 0x7244, - 0x9294, 0xff00, 0x9215, 0xaa9e, 0x7244, 0x9294, 0x00ff, 0xaaa2, - 0x9186, 0x0046, 0x1118, 0x9e90, 0x0012, 0x0010, 0x9e90, 0x001a, - 0x2204, 0x8007, 0xa8a6, 0x8210, 0x2204, 0x8007, 0xa8aa, 0x8210, - 0x2204, 0x8007, 0xa8ae, 0x8210, 0x2204, 0x8007, 0xa8b2, 0x8210, - 0x9186, 0x0046, 0x11b8, 0x9e90, 0x0016, 0x2204, 0x8007, 0xa8b6, - 0x8210, 0x2204, 0x8007, 0xa8ba, 0x8210, 0x2204, 0x8007, 0xa8be, - 0x8210, 0x2204, 0x8007, 0xa8c2, 0x8210, 0x2011, 0x0205, 0x2013, - 0x0001, 0x00b0, 0x9e90, 0x001e, 0x2204, 0x8007, 0xa8b6, 0x8210, - 0x2204, 0x8007, 0xa8ba, 0x2011, 0x0205, 0x2013, 0x0001, 0x2011, - 0x0260, 0x2204, 0x8007, 0xa8be, 0x8210, 0x2204, 0x8007, 0xa8c2, - 0x9186, 0x0046, 0x1118, 0x2011, 0x0262, 0x0010, 0x2011, 0x026a, - 0x0146, 0x01d6, 0x0036, 0x20a9, 0x0001, 0x2019, 0x0008, 0xa860, - 0x20e8, 0xa85c, 0x9080, 0x0031, 0x20a0, 0x2204, 0x8007, 0x4004, - 0x8210, 0x8319, 0x1dd0, 0x003e, 0x01ce, 0x013e, 0x2011, 0x0205, - 0x2013, 0x0000, 0x002e, 0x080c, 0x7012, 0x009e, 0x0005, 0x00e6, - 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0fc, 0x0108, 0x0011, - 0x00ee, 0x0005, 0xa880, 0xc0e5, 0xa882, 0x0005, 0x00e6, 0x00d6, - 0x00c6, 0x0076, 0x0066, 0x0056, 0x0046, 0x0026, 0x0016, 0x0126, - 0x2091, 0x8000, 0x2029, 0x19f4, 0x252c, 0x2021, 0x19fb, 0x2424, - 0x2061, 0x1ddc, 0x2071, 0x1800, 0x7654, 0x7074, 0x9606, 0x0578, - 0x6720, 0x9786, 0x0001, 0x0118, 0x9786, 0x0008, 0x1500, 0x2500, - 0x9c06, 0x01e8, 0x2400, 0x9c06, 0x01d0, 0x080c, 0xeabe, 0x01b8, - 0x080c, 0xeace, 0x11a0, 0x6000, 0x9086, 0x0004, 0x1120, 0x0016, - 0x080c, 0x1ad3, 0x001e, 0x080c, 0xd121, 0x1110, 0x080c, 0x3344, - 0x080c, 0xd132, 0x1110, 0x080c, 0xbb5c, 0x080c, 0xb1a7, 0x9ce0, - 0x001c, 0x2001, 0x181a, 0x2004, 0x9c02, 0x1208, 0x0858, 0x012e, - 0x001e, 0x002e, 0x004e, 0x005e, 0x006e, 0x007e, 0x00ce, 0x00de, - 0x00ee, 0x0005, 0x2001, 0x1810, 0x2004, 0xd0dc, 0x0005, 0x0006, - 0x2001, 0x1837, 0x2004, 0xd09c, 0x000e, 0x0005, 0x0006, 0x0036, - 0x0046, 0x080c, 0xd645, 0x0168, 0x2019, 0xffff, 0x9005, 0x0128, - 0x6010, 0x00b6, 0x2058, 0xbba0, 0x00be, 0x2021, 0x0004, 0x080c, - 0x4e58, 0x004e, 0x003e, 0x000e, 0x0005, 0x6004, 0x9086, 0x0001, - 0x1128, 0x080c, 0xa7e2, 0x080c, 0xb1a7, 0x9006, 0x0005, 0x00e6, - 0x00c6, 0x00b6, 0x0046, 0x2061, 0x1ddc, 0x2071, 0x1800, 0x7454, - 0x7074, 0x8001, 0x9402, 0x12d8, 0x2100, 0x9c06, 0x0168, 0x6000, - 0x9086, 0x0000, 0x0148, 0x6010, 0x2058, 0xb8a0, 0x9206, 0x1120, - 0x6004, 0x9086, 0x0002, 0x0140, 0x9ce0, 0x001c, 0x2001, 0x181a, - 0x2004, 0x9c02, 0x1220, 0x0c40, 0x9085, 0x0001, 0x0008, 0x9006, - 0x004e, 0x00be, 0x00ce, 0x00ee, 0x0005, 0x2001, 0x1810, 0x2004, - 0xd0a4, 0x0160, 0x2001, 0x1837, 0x2004, 0xd0a4, 0x0138, 0x2001, - 0x1848, 0x2004, 0xd0a4, 0x1118, 0x9085, 0x0001, 0x0005, 0x9006, - 0x0ce8, 0x0126, 0x0006, 0x00e6, 0x0016, 0x2091, 0x8000, 0x2071, - 0x1840, 0xd5a4, 0x0118, 0x7004, 0x8000, 0x7006, 0xd5b4, 0x0118, - 0x7000, 0x8000, 0x7002, 0xd5ac, 0x0178, 0x2500, 0x9084, 0x0007, - 0x908e, 0x0003, 0x0148, 0x908e, 0x0004, 0x0130, 0x908e, 0x0005, - 0x0118, 0x2071, 0xfff6, 0x0089, 0x001e, 0x00ee, 0x000e, 0x012e, - 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, 0x2071, 0xffee, - 0x0021, 0x00ee, 0x000e, 0x012e, 0x0005, 0x2e05, 0x8000, 0x2077, - 0x1220, 0x8e70, 0x2e05, 0x8000, 0x2077, 0x0005, 0x00e6, 0x2071, - 0xffec, 0x0c99, 0x00ee, 0x0005, 0x00e6, 0x2071, 0xfff0, 0x0c69, - 0x00ee, 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, 0x2071, - 0x1840, 0x7014, 0x8000, 0x7016, 0x00ee, 0x000e, 0x012e, 0x0005, - 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, - 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, - 0xaa6e -}; -#ifdef UNIQUE_FW_NAME -unsigned short fw2322ipx_length01 = 0xe719; -#else -unsigned short risc_code_length01 = 0xe719; -#endif - -/* - * - */ - -unsigned long rseqipx_code_addr01 = 0x0001c000 ; -unsigned short rseqipx_code01[] = { -0x000b, 0x0003, 0x0000, 0x0a4e, 0x0001, 0xc000, 0x0008, 0x8064, - 0x0000, 0x0010, 0x0000, 0x8066, 0x0008, 0x0101, 0x0003, 0xc007, - 0x0008, 0x80e0, 0x0008, 0xff00, 0x0000, 0x80e2, 0x0008, 0xff00, - 0x0008, 0x0162, 0x0000, 0x8066, 0x0008, 0xa101, 0x000b, 0xc00f, - 0x0008, 0x0d02, 0x0000, 0x8060, 0x0000, 0x0400, 0x000b, 0x60c6, - 0x0008, 0x80e0, 0x0000, 0x0100, 0x000b, 0x5819, 0x0003, 0x7b08, - 0x0003, 0x5241, 0x000b, 0xc813, 0x0009, 0xbac0, 0x0000, 0x008a, - 0x0003, 0x8813, 0x000a, 0x7042, 0x0003, 0x8813, 0x0000, 0x15fc, - 0x000b, 0xb013, 0x0009, 0xc4c0, 0x0000, 0x7000, 0x0001, 0xffa0, - 0x0000, 0x2000, 0x0003, 0x93cd, 0x0008, 0x808c, 0x0000, 0x0001, - 0x0007, 0x0000, 0x0007, 0x0000, 0x0000, 0x40d4, 0x000a, 0x4047, - 0x0008, 0x808c, 0x0000, 0x0002, 0x0007, 0x0000, 0x000b, 0x0832, - 0x0000, 0x4022, 0x0003, 0x0038, 0x0008, 0x4122, 0x0009, 0xeac0, - 0x0008, 0xff00, 0x0009, 0xffe0, 0x0008, 0x0500, 0x000b, 0x0bf4, - 0x0002, 0x4447, 0x0003, 0x8bf1, 0x0008, 0x0bfe, 0x0001, 0x11a0, - 0x000b, 0x13d3, 0x0001, 0x0ca0, 0x000b, 0x13d3, 0x0001, 0x9180, - 0x0000, 0x0004, 0x0000, 0x8060, 0x0000, 0x0400, 0x0008, 0x7f62, - 0x0000, 0x8066, 0x0008, 0x0009, 0x0003, 0xc046, 0x0008, 0x808c, - 0x0008, 0x0000, 0x0008, 0x0060, 0x0008, 0x8062, 0x0000, 0x0004, - 0x0000, 0x8066, 0x0000, 0x0411, 0x000b, 0xc04e, 0x0000, 0x03fe, - 0x0001, 0x43e0, 0x0003, 0x8bd0, 0x0009, 0xc2c0, 0x0008, 0x00ff, - 0x0001, 0x02e0, 0x0003, 0x8bd0, 0x0001, 0x9180, 0x0008, 0x0005, - 0x0000, 0x8060, 0x0000, 0x0400, 0x0008, 0x7f62, 0x0000, 0x8066, - 0x0000, 0x0019, 0x0003, 0xc05d, 0x0002, 0x0240, 0x000b, 0x0bcd, - 0x0008, 0x00fc, 0x0003, 0x33d0, 0x000a, 0x0244, 0x0003, 0x086f, - 0x0004, 0x021a, 0x0001, 0x9180, 0x0000, 0x0007, 0x0008, 0x7f62, - 0x0000, 0x8060, 0x0000, 0x0400, 0x0002, 0x0234, 0x0008, 0x7f04, - 0x0000, 0x8066, 0x0000, 0x040a, 0x0003, 0xc06e, 0x000a, 0x0248, - 0x000b, 0x0879, 0x0001, 0x9180, 0x0008, 0x0006, 0x0008, 0x7f62, - 0x0008, 0x8002, 0x0008, 0x0003, 0x0000, 0x8066, 0x0000, 0x020a, - 0x000b, 0xc078, 0x0000, 0x112a, 0x0008, 0x002e, 0x0008, 0x022c, - 0x0002, 0x3a44, 0x0003, 0x8813, 0x0008, 0x808c, 0x0000, 0x0002, - 0x0008, 0x1760, 0x0008, 0x8062, 0x0008, 0x000f, 0x0000, 0x8066, - 0x0008, 0x0011, 0x0003, 0xc085, 0x0008, 0x01fe, 0x0009, 0x42e0, - 0x000b, 0x8bc0, 0x0000, 0x00fe, 0x0001, 0x43e0, 0x000b, 0x8bc0, - 0x0000, 0x1734, 0x0000, 0x1530, 0x0008, 0x1632, 0x0008, 0x0d2a, - 0x0001, 0x9880, 0x0008, 0x0012, 0x0000, 0x8060, 0x0000, 0x0400, - 0x0008, 0x7f62, 0x0000, 0x8066, 0x0008, 0x1e0a, 0x0003, 0xc097, - 0x0008, 0x808a, 0x0008, 0x0003, 0x0000, 0x1a60, 0x0008, 0x8062, - 0x0000, 0x0002, 0x000b, 0x589d, 0x0000, 0x8066, 0x0000, 0x3679, - 0x000b, 0xc0a0, 0x000b, 0x58a1, 0x0008, 0x8054, 0x0008, 0x0011, - 0x0000, 0x8074, 0x0008, 0x1010, 0x0008, 0x1efc, 0x0003, 0x3013, - 0x0004, 0x00aa, 0x0003, 0x0013, 0x0000, 0x1c60, 0x0000, 0x1b62, - 0x0000, 0x8066, 0x0008, 0x0231, 0x0003, 0xc0ae, 0x0003, 0x58af, - 0x0008, 0x0140, 0x0000, 0x0242, 0x0002, 0x1f43, 0x0003, 0x88b9, - 0x0000, 0x0d44, 0x0008, 0x0d46, 0x0008, 0x0348, 0x0008, 0x044a, - 0x000b, 0x00bd, 0x0008, 0x0344, 0x0008, 0x0446, 0x0008, 0x0548, - 0x0000, 0x064a, 0x000a, 0x1948, 0x0003, 0x08c0, 0x0008, 0x0d4a, - 0x0003, 0x58c0, 0x0008, 0x8054, 0x0000, 0x0001, 0x0000, 0x8074, - 0x0008, 0x2020, 0x000f, 0x4000, 0x0002, 0x7043, 0x0003, 0x8816, - 0x0002, 0x7040, 0x000b, 0x8949, 0x0000, 0x4820, 0x0008, 0x0bfe, - 0x0009, 0x10a0, 0x0003, 0x1140, 0x0001, 0x0ca0, 0x0003, 0x1140, - 0x0000, 0x8060, 0x0000, 0x0400, 0x0009, 0x9080, 0x0000, 0x0008, - 0x0008, 0x7f62, 0x0000, 0x8066, 0x0008, 0x0009, 0x000b, 0xc0d7, - 0x0001, 0x80e0, 0x0008, 0x0003, 0x000b, 0x8940, 0x0000, 0x8060, - 0x0000, 0x0400, 0x0009, 0x9080, 0x0000, 0x0004, 0x0008, 0x7f62, - 0x0000, 0x8066, 0x0008, 0x0009, 0x000b, 0xc0e2, 0x0008, 0x0060, - 0x0008, 0x8062, 0x0000, 0x0004, 0x0000, 0x8066, 0x0000, 0x0411, - 0x000b, 0xc0e8, 0x0008, 0x4afe, 0x0009, 0x03e0, 0x000b, 0x8940, - 0x0009, 0xcbc0, 0x0008, 0x00ff, 0x0001, 0x02e0, 0x000b, 0x8940, - 0x0000, 0x49b4, 0x0002, 0x4b4e, 0x000b, 0x8951, 0x0008, 0x808a, - 0x0000, 0x0004, 0x0000, 0x18fe, 0x0001, 0x10e0, 0x000b, 0x88fa, - 0x0002, 0x192f, 0x0008, 0x7f32, 0x0008, 0x15fe, 0x0001, 0x10e0, - 0x000b, 0x88ff, 0x0002, 0x162f, 0x0008, 0x7f2c, 0x0000, 0x8060, - 0x0000, 0x0400, 0x0009, 0x9080, 0x0000, 0x0007, 0x0008, 0x7f62, - 0x0000, 0x8066, 0x0008, 0x0009, 0x0003, 0xc106, 0x000a, 0x004f, - 0x000b, 0x8937, 0x000a, 0x0040, 0x000b, 0x0921, 0x0002, 0x004e, - 0x000b, 0x0921, 0x0002, 0x0030, 0x0002, 0x7f2f, 0x0000, 0x7f00, - 0x0000, 0x8066, 0x0008, 0x000a, 0x0003, 0xc112, 0x0008, 0x1010, - 0x0004, 0x0201, 0x0003, 0xb11a, 0x0004, 0x0387, 0x000c, 0x01eb, - 0x0003, 0x7816, 0x0003, 0x0013, 0x0000, 0x0806, 0x0008, 0x8010, - 0x0000, 0x001f, 0x0004, 0x0387, 0x0000, 0x0310, 0x0004, 0x0387, - 0x0003, 0x0118, 0x000a, 0x002f, 0x0000, 0x7f00, 0x0000, 0x8066, - 0x0008, 0x000a, 0x000b, 0xc125, 0x0004, 0x01c4, 0x000a, 0x0040, - 0x000b, 0x093a, 0x0004, 0x0231, 0x0000, 0x8000, 0x0000, 0x0002, - 0x0000, 0x8060, 0x0000, 0x0400, 0x0009, 0x9080, 0x0008, 0x0006, - 0x0008, 0x7f62, 0x0000, 0x8066, 0x0008, 0x000a, 0x0003, 0xc133, - 0x0000, 0x8072, 0x0000, 0x4000, 0x0003, 0x0118, 0x0008, 0x8010, - 0x0008, 0x001e, 0x0003, 0x013c, 0x0008, 0x8010, 0x0008, 0x001d, - 0x0004, 0x0387, 0x0008, 0x1010, 0x0004, 0x0387, 0x0003, 0x0016, - 0x0002, 0x4b4e, 0x0003, 0x0946, 0x0008, 0x808a, 0x0000, 0x0004, - 0x000b, 0x6146, 0x000f, 0x8000, 0x0008, 0x808a, 0x0000, 0x0004, - 0x0003, 0x0016, 0x0008, 0x808a, 0x0000, 0x0004, 0x0007, 0x0000, - 0x0007, 0x0000, 0x0008, 0x80e0, 0x0008, 0x0202, 0x000b, 0x6149, - 0x000b, 0x0014, 0x0000, 0x8060, 0x0000, 0x0400, 0x0009, 0x9080, - 0x0008, 0x0011, 0x0008, 0x7f62, 0x0000, 0x8066, 0x0008, 0x0009, - 0x000b, 0xc158, 0x000a, 0x004f, 0x000b, 0x89b5, 0x0000, 0x8060, - 0x0000, 0x0400, 0x0009, 0x9080, 0x0008, 0x0005, 0x0008, 0x7f62, - 0x0000, 0x8066, 0x0008, 0x0009, 0x000b, 0xc162, 0x0008, 0x0060, - 0x0008, 0x8062, 0x0000, 0x001f, 0x0000, 0x8066, 0x0000, 0x0209, - 0x000b, 0xc168, 0x000a, 0x014b, 0x0003, 0x09b5, 0x0008, 0x8062, - 0x0008, 0x000f, 0x0000, 0x8066, 0x0000, 0x0211, 0x0003, 0xc16f, - 0x0008, 0x01fe, 0x0001, 0x02d0, 0x000b, 0x89b5, 0x0004, 0x01cd, - 0x0003, 0x09b5, 0x0008, 0x03a0, 0x0008, 0x8004, 0x0000, 0x0002, - 0x0000, 0x8006, 0x0000, 0x0043, 0x0008, 0x4908, 0x0008, 0x808a, - 0x0000, 0x0004, 0x0000, 0x8060, 0x0000, 0x0400, 0x0009, 0x9080, - 0x0008, 0x0000, 0x0008, 0x7f62, 0x0000, 0x8066, 0x0008, 0x041a, - 0x0003, 0xc184, 0x0003, 0xe185, 0x0008, 0x4908, 0x0008, 0x480a, - 0x0008, 0x808a, 0x0000, 0x0004, 0x0008, 0x0060, 0x0008, 0x8062, - 0x0008, 0x002b, 0x0000, 0x8066, 0x0000, 0x0411, 0x000b, 0xc18f, - 0x0008, 0x04fe, 0x0009, 0x02a0, 0x0003, 0x9196, 0x0002, 0x0500, - 0x000b, 0x09b2, 0x000b, 0x0197, 0x0000, 0x05fe, 0x0001, 0x03a0, - 0x000b, 0x11b2, 0x0000, 0x0d0c, 0x0008, 0x0d0e, 0x0008, 0x0d10, - 0x0000, 0x0d12, 0x0008, 0x0060, 0x0008, 0x8062, 0x0000, 0x000d, - 0x0000, 0x8066, 0x0008, 0x0832, 0x000b, 0xc1a2, 0x0000, 0x800a, - 0x0000, 0x8005, 0x0000, 0x8060, 0x0000, 0x0400, 0x0009, 0x9080, - 0x0008, 0x0011, 0x0008, 0x7f62, 0x0000, 0x8066, 0x0008, 0x0a12, - 0x0003, 0xc1ac, 0x0008, 0x5006, 0x0008, 0x100e, 0x000c, 0x01d8, - 0x0003, 0x7816, 0x0003, 0x0013, 0x0008, 0x0208, 0x0008, 0x030a, - 0x0003, 0x0199, 0x0004, 0x01c4, 0x0008, 0x808a, 0x0000, 0x0004, - 0x0008, 0x8010, 0x0008, 0x0021, 0x0004, 0x0387, 0x0008, 0x1010, - 0x0004, 0x0387, 0x0000, 0x4810, 0x0004, 0x0387, 0x0008, 0x4910, - 0x0004, 0x0387, 0x0008, 0x808a, 0x0000, 0x0004, 0x0003, 0x0016, - 0x0000, 0x8060, 0x0000, 0x0400, 0x0009, 0x9080, 0x0000, 0x0002, - 0x0008, 0x7f62, 0x0000, 0x8066, 0x0008, 0xb40a, 0x000b, 0xc1cb, - 0x000f, 0x4000, 0x0000, 0x8060, 0x0000, 0x0400, 0x0000, 0x0a62, - 0x0000, 0x8066, 0x0000, 0x0411, 0x0003, 0xc1d2, 0x0002, 0x0210, - 0x0001, 0xffc0, 0x0000, 0x0007, 0x0009, 0x03e0, 0x000f, 0x4000, - 0x0000, 0x8060, 0x0000, 0x0400, 0x0001, 0x8380, 0x0000, 0x0002, - 0x0009, 0x0a80, 0x0008, 0x7f62, 0x0000, 0x8066, 0x0000, 0x0e0a, - 0x000b, 0xc1e0, 0x0002, 0x0300, 0x0001, 0xffc0, 0x0000, 0x0007, - 0x0000, 0x7f06, 0x0002, 0x0a00, 0x0008, 0x7f62, 0x0000, 0x8066, - 0x0008, 0x060a, 0x000b, 0xc1e9, 0x000f, 0x4000, 0x0000, 0x0da0, - 0x0008, 0x0da2, 0x0008, 0x0da4, 0x0009, 0x8880, 0x0000, 0x0001, - 0x0008, 0x7f62, 0x0000, 0x8060, 0x0000, 0x0400, 0x0000, 0x8066, - 0x0008, 0xa012, 0x0000, 0x0da6, 0x0008, 0x0da8, 0x0000, 0x0daa, - 0x0000, 0x0dac, 0x0003, 0xc1f9, 0x0009, 0x8880, 0x0008, 0x0009, - 0x0008, 0x7f62, 0x0000, 0x8066, 0x0008, 0xa03a, 0x0003, 0xc1ff, - 0x000f, 0x4000, 0x0009, 0x8880, 0x0008, 0x0005, 0x0000, 0x8060, - 0x0000, 0x0400, 0x0008, 0x7f62, 0x0000, 0x8066, 0x0008, 0x0009, - 0x000b, 0xc208, 0x0008, 0x0060, 0x0008, 0x8062, 0x0000, 0x000d, - 0x0000, 0x8066, 0x0008, 0x0021, 0x000b, 0xc20e, 0x0000, 0x00fe, - 0x0001, 0x01d0, 0x0003, 0x8a17, 0x0008, 0x02fe, 0x0009, 0x03d0, - 0x000b, 0x0a17, 0x0000, 0x0d06, 0x000f, 0x4000, 0x0000, 0x8006, - 0x0000, 0x0001, 0x000f, 0x4000, 0x0008, 0x0060, 0x0008, 0x8062, - 0x0008, 0x002b, 0x0000, 0x8066, 0x0008, 0xa041, 0x000b, 0xc21f, - 0x0002, 0x0243, 0x000b, 0x8a26, 0x0000, 0x54ac, 0x0000, 0x55ae, - 0x0008, 0x0da8, 0x0000, 0x0daa, 0x0000, 0x50b0, 0x0000, 0x51b2, - 0x0000, 0x0db4, 0x0008, 0x0db6, 0x0008, 0x0060, 0x0008, 0x8062, - 0x0000, 0x0007, 0x0000, 0x8066, 0x0008, 0xa452, 0x000b, 0xc22f, - 0x000f, 0x4000, 0x000a, 0x3945, 0x000b, 0x8a3b, 0x0000, 0x8072, - 0x0008, 0x4040, 0x0007, 0x0000, 0x000a, 0x3945, 0x0003, 0x8a39, - 0x000f, 0x4000, 0x0000, 0x8072, 0x0000, 0x4000, 0x0007, 0x0000, - 0x0007, 0x0000, 0x0007, 0x0000, 0x000a, 0x3945, 0x000b, 0x0a33, - 0x000b, 0x023b, 0x000a, 0x3a40, 0x0003, 0x8819, 0x0001, 0xabd0, - 0x0008, 0x0000, 0x0000, 0x7f24, 0x0003, 0x5a46, 0x0008, 0x8054, - 0x0000, 0x0002, 0x0002, 0x1242, 0x0003, 0x0a8c, 0x000a, 0x3a45, - 0x000b, 0x0a7b, 0x000a, 0x1e10, 0x0000, 0x7f3c, 0x000b, 0x0a78, - 0x0002, 0x1d00, 0x0000, 0x7f3a, 0x0000, 0x0d60, 0x0008, 0x7f62, - 0x0000, 0x8066, 0x0008, 0x0009, 0x0003, 0xc256, 0x0008, 0x00fc, - 0x0003, 0xb275, 0x0000, 0x1c60, 0x0008, 0x8062, 0x0000, 0x0001, - 0x0000, 0x8066, 0x0008, 0x0009, 0x000b, 0xc25e, 0x0008, 0x00fc, - 0x000b, 0x33a9, 0x0000, 0x0038, 0x0008, 0x0060, 0x0008, 0x8062, - 0x0000, 0x0019, 0x0000, 0x8066, 0x0008, 0x0009, 0x000b, 0xc267, - 0x0009, 0x80c0, 0x0008, 0x00ff, 0x0008, 0x7f3e, 0x0000, 0x0d60, - 0x0008, 0x0efe, 0x0001, 0x1f80, 0x0008, 0x7f62, 0x0000, 0x8066, - 0x0008, 0x0009, 0x0003, 0xc271, 0x0008, 0x003a, 0x0000, 0x1dfe, - 0x000b, 0x0252, 0x0008, 0x0036, 0x0004, 0x00aa, 0x000b, 0x028c, - 0x0000, 0x8074, 0x0000, 0x2000, 0x000b, 0x028c, 0x0002, 0x3a44, - 0x000b, 0x0bd6, 0x0000, 0x8074, 0x0000, 0x1000, 0x0001, 0xadd0, - 0x0008, 0x0000, 0x0008, 0x7f0e, 0x0003, 0xb3a6, 0x0001, 0xa7d0, - 0x0008, 0x0000, 0x0000, 0x7f00, 0x0009, 0xa6d0, 0x0008, 0x0000, - 0x0009, 0x00d0, 0x0003, 0x8a9c, 0x0000, 0x8074, 0x0008, 0x4040, - 0x0003, 0x5a8c, 0x0003, 0x5241, 0x000a, 0x3a46, 0x0003, 0x8a9c, - 0x0002, 0x3a47, 0x0003, 0x0a97, 0x0008, 0x8054, 0x0000, 0x0004, - 0x0000, 0x8074, 0x0000, 0x8000, 0x0003, 0x02fc, 0x0009, 0x92c0, - 0x0000, 0x0fc8, 0x000b, 0x0813, 0x000a, 0x1246, 0x000b, 0x8ba0, - 0x0000, 0x1a60, 0x0008, 0x8062, 0x0000, 0x0002, 0x0000, 0x8066, - 0x0000, 0x367a, 0x000b, 0xc2a1, 0x0009, 0x92c0, 0x0008, 0x0780, - 0x0003, 0x8bba, 0x0002, 0x124b, 0x000b, 0x0aaa, 0x0002, 0x2e4d, - 0x0002, 0x2e4d, 0x0003, 0x0ba6, 0x000a, 0x3a46, 0x000b, 0x8aba, - 0x000b, 0x5aac, 0x0008, 0x8054, 0x0000, 0x0004, 0x000a, 0x1243, - 0x000b, 0x0afa, 0x0008, 0x8010, 0x0000, 0x000d, 0x0004, 0x0387, - 0x000a, 0x1948, 0x000b, 0x0ab7, 0x000c, 0x037c, 0x0000, 0x1810, - 0x0004, 0x0387, 0x0003, 0x02fa, 0x000a, 0x1948, 0x000b, 0x0abe, - 0x000a, 0x1243, 0x0003, 0x0ba9, 0x000a, 0x194d, 0x0003, 0x0ac2, - 0x000a, 0x1243, 0x000b, 0x0bb0, 0x0003, 0x5ac2, 0x0008, 0x8054, - 0x0000, 0x0004, 0x000a, 0x192e, 0x0008, 0x7f32, 0x000a, 0x1947, - 0x0003, 0x0af4, 0x0002, 0x194f, 0x000b, 0x0ad2, 0x000c, 0x037c, - 0x0000, 0x1810, 0x0004, 0x0201, 0x000b, 0xb2ed, 0x0004, 0x0387, - 0x000c, 0x01eb, 0x0003, 0x02fa, 0x0000, 0x1a60, 0x0008, 0x8062, - 0x0000, 0x001f, 0x0000, 0x8066, 0x0008, 0x0009, 0x0003, 0xc2d7, - 0x000a, 0x004c, 0x000b, 0x8af4, 0x0000, 0x8060, 0x0000, 0x0400, - 0x0001, 0x9880, 0x0000, 0x0007, 0x0008, 0x7f62, 0x0000, 0x8066, - 0x0000, 0x320a, 0x0003, 0xc2e1, 0x0000, 0x8060, 0x0000, 0x0400, - 0x0001, 0x9880, 0x0008, 0x0012, 0x0008, 0x7f62, 0x0000, 0x8066, - 0x0008, 0x1e0a, 0x000b, 0xc2e9, 0x0000, 0x1826, 0x0000, 0x1928, - 0x0003, 0x02fa, 0x0000, 0x0806, 0x0008, 0x8010, 0x0000, 0x001f, - 0x0004, 0x0387, 0x0000, 0x0310, 0x0004, 0x0387, 0x0003, 0x02fa, - 0x000c, 0x037c, 0x0008, 0x8010, 0x0000, 0x0001, 0x0004, 0x0387, - 0x0000, 0x1810, 0x0004, 0x0387, 0x0000, 0x8074, 0x0008, 0xf000, - 0x0000, 0x0d30, 0x0002, 0x3a42, 0x0003, 0x8b02, 0x0000, 0x15fc, - 0x0003, 0xb07e, 0x0003, 0x0013, 0x0000, 0x8074, 0x0000, 0x0501, - 0x0008, 0x8010, 0x0008, 0x000c, 0x0004, 0x0387, 0x0003, 0x0013, - 0x0009, 0xbbe0, 0x0008, 0x0030, 0x000b, 0x8b1e, 0x0000, 0x18fe, - 0x0009, 0x3ce0, 0x0003, 0x0b1b, 0x0008, 0x15fe, 0x0009, 0x3ce0, - 0x0003, 0x0b1b, 0x0008, 0x13fe, 0x0009, 0x3ce0, 0x000b, 0x8b17, - 0x000c, 0x0375, 0x0008, 0x0d26, 0x000b, 0x0318, 0x0004, 0x0377, - 0x0008, 0x8076, 0x0000, 0x0040, 0x000b, 0x0372, 0x0008, 0x8076, - 0x0008, 0x0041, 0x000b, 0x0372, 0x0009, 0xbbe0, 0x0000, 0x0032, - 0x0003, 0x8b23, 0x0008, 0x3c1e, 0x000b, 0x0372, 0x0009, 0xbbe0, - 0x0000, 0x003b, 0x000b, 0x8b28, 0x0000, 0x3cdc, 0x000b, 0x0372, - 0x0009, 0xbbe0, 0x0008, 0x0035, 0x000b, 0x8b2e, 0x0000, 0x8072, - 0x0000, 0x8000, 0x000b, 0x04e5, 0x0009, 0xbbe0, 0x0008, 0x0036, - 0x000b, 0x0c06, 0x0009, 0xbbe0, 0x0000, 0x0037, 0x000b, 0x8b53, - 0x0000, 0x18fe, 0x0009, 0x3ce0, 0x000b, 0x8b1b, 0x0008, 0x8076, - 0x0000, 0x0040, 0x0000, 0x1a60, 0x0008, 0x8062, 0x0000, 0x000d, - 0x0009, 0xa6d0, 0x0008, 0x0000, 0x0008, 0x7f04, 0x0001, 0xa7d0, - 0x0008, 0x0000, 0x0000, 0x7f06, 0x0001, 0xa8d0, 0x0008, 0x0000, - 0x0008, 0x7f08, 0x0009, 0xa9d0, 0x0008, 0x0000, 0x0000, 0x7f0a, - 0x0000, 0x8066, 0x0000, 0x0422, 0x0003, 0xc34a, 0x000c, 0x037c, - 0x0008, 0x8054, 0x0000, 0x0004, 0x0000, 0x8074, 0x0008, 0xf000, - 0x0000, 0x8072, 0x0000, 0x8000, 0x0003, 0x02fc, 0x0009, 0xbbe0, - 0x0000, 0x0038, 0x000b, 0x8b65, 0x0000, 0x18fe, 0x0009, 0x3ce0, - 0x000b, 0x0b62, 0x0008, 0x15fe, 0x0009, 0x3ce0, 0x000b, 0x8b11, - 0x0004, 0x0377, 0x0008, 0x8076, 0x0000, 0x0040, 0x0000, 0x8072, - 0x0000, 0x8000, 0x0003, 0x03cd, 0x0008, 0x8076, 0x0008, 0x0042, - 0x000b, 0x0372, 0x0009, 0xbbe0, 0x0000, 0x0016, 0x000b, 0x8b72, - 0x0000, 0x8074, 0x0008, 0x0808, 0x0002, 0x3a44, 0x000b, 0x8818, - 0x0000, 0x8074, 0x0000, 0x0800, 0x0000, 0x8072, 0x0000, 0x8000, - 0x000f, 0x8000, 0x0003, 0x0013, 0x0000, 0x8072, 0x0000, 0x8000, - 0x0003, 0x0013, 0x0002, 0x1430, 0x000b, 0x0378, 0x000a, 0x3d30, - 0x0000, 0x7f00, 0x0001, 0xbc80, 0x0000, 0x0007, 0x0003, 0x0380, - 0x000a, 0x1930, 0x0000, 0x7f00, 0x0001, 0x9880, 0x0000, 0x0007, - 0x0000, 0x8060, 0x0000, 0x0400, 0x0008, 0x7f62, 0x0000, 0x8066, - 0x0008, 0x000a, 0x0003, 0xc385, 0x000f, 0x4000, 0x000b, 0x238a, - 0x0008, 0x0870, 0x000f, 0x4000, 0x0002, 0x7040, 0x0003, 0x0b87, - 0x000b, 0xe394, 0x0008, 0x808a, 0x0000, 0x0004, 0x0007, 0x0000, - 0x0007, 0x0000, 0x0008, 0x80e0, 0x0008, 0x0202, 0x000b, 0x638d, - 0x0008, 0x80e0, 0x0000, 0x0100, 0x000b, 0x0387, 0x0009, 0xbac0, - 0x0008, 0x0090, 0x000b, 0x0b9d, 0x0000, 0x8074, 0x0000, 0x0706, - 0x000b, 0x039f, 0x0000, 0x8074, 0x0000, 0x0703, 0x000f, 0x4000, - 0x0008, 0x8010, 0x0000, 0x0023, 0x000b, 0x03db, 0x0008, 0x8010, - 0x0000, 0x0008, 0x000b, 0x03db, 0x0008, 0x8010, 0x0008, 0x0022, - 0x000b, 0x03db, 0x000c, 0x037c, 0x0008, 0x8010, 0x0000, 0x0007, - 0x0004, 0x0387, 0x0000, 0x1810, 0x0004, 0x0387, 0x0003, 0x03e5, - 0x000c, 0x037c, 0x0008, 0x8010, 0x0008, 0x001b, 0x0004, 0x0387, - 0x0000, 0x1810, 0x0004, 0x0387, 0x0000, 0x8074, 0x0000, 0xf080, - 0x0000, 0x0d30, 0x0003, 0x0013, 0x0008, 0x8010, 0x0008, 0x0009, - 0x000b, 0x03db, 0x0008, 0x8010, 0x0008, 0x0005, 0x000b, 0x03db, - 0x000a, 0x1648, 0x0003, 0x888c, 0x0008, 0x808c, 0x0000, 0x0001, - 0x0007, 0x0000, 0x0008, 0x8010, 0x0000, 0x0004, 0x000a, 0x4143, - 0x000b, 0x088c, 0x0002, 0x3a44, 0x0003, 0x8813, 0x0008, 0x0d2a, - 0x000b, 0x03db, 0x0008, 0x8010, 0x0008, 0x0003, 0x000b, 0x03dd, - 0x0008, 0x8010, 0x0000, 0x000b, 0x000b, 0x03dd, 0x0008, 0x8010, - 0x0000, 0x0002, 0x000b, 0x03dd, 0x0002, 0x3a47, 0x000b, 0x8a8c, - 0x0008, 0x8010, 0x0008, 0x0006, 0x000b, 0x03dd, 0x0000, 0x8074, - 0x0008, 0xf000, 0x0004, 0x0387, 0x000c, 0x0397, 0x000a, 0x3a40, - 0x000b, 0x0813, 0x0008, 0x8010, 0x0008, 0x000c, 0x0004, 0x0387, - 0x0003, 0x0013, 0x0000, 0x8074, 0x0000, 0xf080, 0x0000, 0x0d30, - 0x0002, 0x2e4d, 0x0002, 0x2e4d, 0x0003, 0x0bee, 0x0008, 0x8054, - 0x0000, 0x0019, 0x0003, 0x0013, 0x0008, 0x8054, 0x0008, 0x0009, - 0x0003, 0x0013, 0x0002, 0x3a44, 0x0003, 0x8813, 0x0003, 0x03d0, - 0x0008, 0x808c, 0x0008, 0x0000, 0x0002, 0x4447, 0x0003, 0x0c1a, - 0x0001, 0xc0c0, 0x0008, 0x00ff, 0x0009, 0xffe0, 0x0008, 0x00ff, - 0x0003, 0x8bf1, 0x0001, 0xc1e0, 0x0008, 0xffff, 0x0003, 0x8bf1, - 0x0008, 0x8010, 0x0000, 0x0013, 0x0004, 0x0387, 0x0000, 0x8074, - 0x0008, 0x0202, 0x0003, 0x0013, 0x000a, 0x3a40, 0x0003, 0x8c17, - 0x0000, 0x8074, 0x0000, 0x0200, 0x0000, 0x3d00, 0x0000, 0x3cfe, - 0x0000, 0x8072, 0x0000, 0x8000, 0x0001, 0x43e0, 0x000b, 0x8c15, - 0x0000, 0x42fe, 0x0001, 0xffc0, 0x0008, 0x00ff, 0x0009, 0x00e0, - 0x000b, 0x0bf1, 0x0008, 0x0d08, 0x0003, 0x046a, 0x0000, 0x8072, - 0x0000, 0x8000, 0x0003, 0x0013, 0x000c, 0x04ee, 0x0008, 0x808c, - 0x0000, 0x0001, 0x0000, 0x04fc, 0x0003, 0x34d1, 0x0000, 0x0460, - 0x0008, 0x8062, 0x0000, 0x0001, 0x0000, 0x8066, 0x0008, 0x0009, - 0x0003, 0xc424, 0x0000, 0x0004, 0x0009, 0x80c0, 0x0008, 0x00ff, - 0x0000, 0x7f00, 0x0001, 0x80e0, 0x0000, 0x0004, 0x0003, 0x0c3e, - 0x0001, 0x80e0, 0x0008, 0x0005, 0x0003, 0x0c3e, 0x0001, 0x80e0, - 0x0008, 0x0006, 0x0003, 0x0c3e, 0x0001, 0x82c0, 0x0008, 0xff00, - 0x0008, 0x7f04, 0x0009, 0x82e0, 0x0008, 0x0600, 0x0003, 0x0c3e, - 0x0009, 0x82e0, 0x0008, 0x0500, 0x0003, 0x0c3e, 0x0009, 0x82e0, - 0x0000, 0x0400, 0x0003, 0x8cd1, 0x0009, 0xc4c0, 0x0000, 0x7000, - 0x0009, 0xffe0, 0x0000, 0x1000, 0x000b, 0x0c6a, 0x0004, 0x04df, - 0x0002, 0x3941, 0x0003, 0x0c49, 0x0000, 0x8072, 0x0000, 0x0400, - 0x0003, 0x0013, 0x0000, 0x0460, 0x0008, 0x80fe, 0x0008, 0x002b, - 0x0008, 0x7f62, 0x0000, 0x8066, 0x0008, 0x2209, 0x000b, 0xc44f, - 0x0008, 0x11fc, 0x0003, 0x3465, 0x0001, 0x9180, 0x0000, 0x0002, - 0x0000, 0x8060, 0x0000, 0x0400, 0x0008, 0x7f62, 0x0000, 0x8066, - 0x0008, 0x0609, 0x0003, 0xc459, 0x0000, 0x42fe, 0x0001, 0xffc0, - 0x0008, 0xff00, 0x0009, 0x03e0, 0x000b, 0x8c62, 0x0000, 0x8072, - 0x0000, 0x0400, 0x000b, 0x0056, 0x0001, 0x9180, 0x0008, 0x0003, - 0x000b, 0x044c, 0x0000, 0x8072, 0x0000, 0x0400, 0x0008, 0x8010, - 0x0000, 0x0010, 0x000b, 0x04c4, 0x0004, 0x04df, 0x0002, 0x3941, - 0x0003, 0x0c70, 0x0000, 0x8072, 0x0000, 0x0400, 0x0003, 0x0013, - 0x000a, 0x6e42, 0x0003, 0x0c75, 0x000c, 0x04a9, 0x0008, 0x11fc, - 0x0003, 0xb47a, 0x0000, 0x8072, 0x0000, 0x0400, 0x0008, 0x8010, - 0x0000, 0x000e, 0x000b, 0x04c4, 0x0000, 0x8060, 0x0000, 0x0400, - 0x0000, 0x04fc, 0x0003, 0xb48f, 0x0008, 0x808c, 0x0008, 0x0000, - 0x0001, 0x9180, 0x0008, 0x0005, 0x0008, 0x7f62, 0x0000, 0x8066, - 0x0008, 0x0009, 0x000b, 0xc485, 0x0008, 0x0060, 0x0008, 0x8062, - 0x0008, 0x001b, 0x0008, 0x4304, 0x0008, 0x4206, 0x0000, 0x8066, - 0x0000, 0x0412, 0x0003, 0xc48d, 0x0003, 0x04a6, 0x0008, 0x808c, - 0x0000, 0x0001, 0x0000, 0x0460, 0x0008, 0x8062, 0x0008, 0x002b, - 0x0000, 0x8066, 0x0008, 0x0609, 0x0003, 0xc496, 0x0000, 0x8066, - 0x0008, 0x220a, 0x0003, 0xc499, 0x0000, 0x42fe, 0x0001, 0xffc0, - 0x0008, 0xff00, 0x0008, 0x7f04, 0x0000, 0x8060, 0x0000, 0x0400, - 0x0001, 0x9180, 0x0000, 0x0002, 0x0008, 0x7f62, 0x0000, 0x8066, - 0x0008, 0x041a, 0x0003, 0xc4a5, 0x0000, 0x8072, 0x0000, 0x0400, - 0x000b, 0x0056, 0x0000, 0x8060, 0x0000, 0x0400, 0x0008, 0x6b62, - 0x0000, 0x8066, 0x0000, 0x0411, 0x000b, 0xc4ae, 0x0008, 0x02fe, - 0x0009, 0x03e0, 0x0003, 0x8cb4, 0x0000, 0x0d22, 0x000f, 0x4000, - 0x0009, 0x8280, 0x0000, 0x0002, 0x0001, 0x6b80, 0x0008, 0x7f62, - 0x0000, 0x8066, 0x0008, 0x2209, 0x000b, 0xc4ba, 0x000a, 0x0200, - 0x0001, 0xffc0, 0x0000, 0x0007, 0x0000, 0x7f06, 0x0008, 0x6b62, - 0x0000, 0x8066, 0x0008, 0x060a, 0x000b, 0xc4c2, 0x000f, 0x4000, - 0x0002, 0x3a44, 0x0003, 0x8813, 0x000a, 0x2f44, 0x000a, 0x2f44, - 0x0003, 0x8bd0, 0x0008, 0x808a, 0x0008, 0x0003, 0x0000, 0x8074, - 0x0000, 0xf080, 0x0003, 0x5ccd, 0x0008, 0x8054, 0x0000, 0x0019, - 0x0003, 0x0013, 0x0002, 0x3a44, 0x0003, 0x8813, 0x0008, 0x808c, - 0x0008, 0x0000, 0x0008, 0x8010, 0x0008, 0x0011, 0x0004, 0x0387, - 0x0000, 0x42fe, 0x0001, 0xffc0, 0x0008, 0x00ff, 0x0008, 0x7f10, - 0x0004, 0x0387, 0x0008, 0x4310, 0x000b, 0x03dd, 0x0002, 0x3941, - 0x000b, 0x0ce2, 0x000f, 0x4000, 0x0000, 0x8072, 0x0008, 0x0404, - 0x000f, 0x4000, 0x0008, 0x8010, 0x0008, 0x0012, 0x0004, 0x0387, - 0x000c, 0x04a9, 0x0000, 0x1110, 0x0004, 0x0387, 0x0008, 0x11fc, - 0x000b, 0xb4e8, 0x0003, 0x0013, 0x0009, 0xc2c0, 0x0008, 0x00ff, - 0x0000, 0x7f00, 0x0001, 0xc3c0, 0x0008, 0xff00, 0x0009, 0x00d0, - 0x000b, 0x0d13, 0x0000, 0x0d0a, 0x0001, 0x8580, 0x0000, 0x1000, - 0x0008, 0x7f62, 0x0000, 0x8060, 0x0000, 0x0400, 0x0000, 0x8066, - 0x0000, 0x0809, 0x000b, 0xc4fd, 0x0000, 0x04fc, 0x000b, 0x350c, - 0x0000, 0x0460, 0x0008, 0x8062, 0x0000, 0x0004, 0x0000, 0x8066, - 0x0000, 0x0211, 0x000b, 0xc505, 0x0008, 0x01fe, 0x0009, 0x00e0, - 0x000b, 0x8d0c, 0x0008, 0x02fe, 0x0001, 0x43e0, 0x0003, 0x0d12, - 0x0002, 0x0500, 0x0000, 0x7f0a, 0x0009, 0xffe0, 0x0000, 0x0800, - 0x0003, 0x8cf6, 0x0008, 0x0d08, 0x000f, 0x4000, 0x0008, 0x43fe, - 0x0001, 0x3e80, 0x0000, 0x0d60, 0x0008, 0x7f62, 0x0000, 0x8066, - 0x0000, 0x0809, 0x0003, 0xc519, 0x0000, 0x8060, 0x0000, 0x0400, - 0x0001, 0x84c0, 0x0008, 0xff00, 0x0002, 0x7f70, 0x0009, 0xff80, - 0x0000, 0x1000, 0x0008, 0x7f62, 0x0000, 0x8066, 0x0000, 0x0809, - 0x000b, 0xc524, 0x000f, 0x4000, 0xe4a8, 0xa3b9 -}; -unsigned short rseqipx_code_length01 = 0x0a4e; -/* - * - */ - -unsigned long xseqipx_code_addr01 = 0x0001e000 ; -unsigned short xseqipx_code01[] = { -0x0013, 0x0003, 0x0000, 0x1252, 0x0001, 0xe000, 0x0005, 0x0032, - 0x0000, 0x0010, 0x0015, 0x0033, 0x0010, 0xbb39, 0x000b, 0x8007, - 0x0004, 0x0113, 0x0004, 0x0125, 0x0010, 0xc000, 0x0000, 0xc001, - 0x0000, 0xc0b0, 0x0010, 0xc0b1, 0x0010, 0xc0b2, 0x0000, 0xc0b3, - 0x0010, 0xc0b4, 0x0000, 0xc0b5, 0x0000, 0xc0b6, 0x0010, 0xc0b7, - 0x0010, 0xc0b8, 0x0000, 0xc0b9, 0x0000, 0xc0ba, 0x0000, 0xc0c2, - 0x0010, 0xc0c3, 0x0000, 0xc0c4, 0x0010, 0xc0c5, 0x0010, 0xc0c6, - 0x0000, 0xc0c7, 0x0000, 0xc0c8, 0x0010, 0xc0c9, 0x0010, 0xc0ca, - 0x0000, 0xc0cb, 0x0010, 0xc0cc, 0x0000, 0xc0cd, 0x0000, 0xc0ce, - 0x0010, 0xc0cf, 0x0015, 0x0039, 0x0010, 0xff00, 0x0015, 0x003a, - 0x0010, 0xff00, 0x0005, 0x00d0, 0x0010, 0xff00, 0x0015, 0x00d1, - 0x0010, 0xff00, 0x0012, 0x3a40, 0x000b, 0x1031, 0x0002, 0x7940, - 0x001b, 0x1137, 0x0002, 0x3a42, 0x001b, 0x1035, 0x0003, 0xb035, - 0x0003, 0xa1e2, 0x0002, 0x3a41, 0x001b, 0x1039, 0x0012, 0x7941, - 0x001b, 0x1317, 0x0013, 0xe054, 0x0001, 0x0fe8, 0x0000, 0x0001, - 0x0013, 0x1054, 0x0000, 0x0cfe, 0x0013, 0x6047, 0x0002, 0x3a44, - 0x001b, 0x1047, 0x0011, 0x02e8, 0x0010, 0x0000, 0x0013, 0x13cd, - 0x0011, 0x02e8, 0x0010, 0x0005, 0x0013, 0x145f, 0x0012, 0x3a46, - 0x000b, 0x1054, 0x0011, 0x02e8, 0x0010, 0x0000, 0x0013, 0x104f, - 0x0011, 0x02e8, 0x0010, 0x0005, 0x000b, 0x1054, 0x0000, 0x12fe, - 0x0003, 0x6054, 0x0001, 0x0fe8, 0x0010, 0x0000, 0x0003, 0x1695, - 0x0015, 0x0030, 0x0000, 0x0400, 0x0010, 0xc131, 0x0015, 0x0033, - 0x0010, 0xb211, 0x001b, 0x8059, 0x0010, 0xb2ff, 0x0001, 0xb3e0, - 0x001c, 0x10d5, 0x000b, 0xf02d, 0x0011, 0x3be8, 0x0000, 0x0010, - 0x001b, 0x1071, 0x0000, 0x0afe, 0x000b, 0x6065, 0x0000, 0x3c0b, - 0x0003, 0x006d, 0x0015, 0x0030, 0x0000, 0x0400, 0x0001, 0x0a88, - 0x0010, 0x0003, 0x0000, 0xff31, 0x0015, 0x0033, 0x0010, 0x3c0a, - 0x001b, 0x806c, 0x0010, 0x3c0a, 0x0002, 0x0c00, 0x0010, 0xff0c, - 0x0013, 0x00d2, 0x0011, 0x3be8, 0x0010, 0x0012, 0x001b, 0x1084, - 0x0010, 0x08fe, 0x000b, 0x6078, 0x0010, 0x3c09, 0x0003, 0x0080, - 0x0015, 0x0030, 0x0000, 0x0400, 0x0011, 0x0888, 0x0010, 0x0003, - 0x0000, 0xff31, 0x0015, 0x0033, 0x0010, 0x3c0a, 0x000b, 0x807f, - 0x0000, 0x3c08, 0x0002, 0x0c00, 0x0010, 0xff0c, 0x0013, 0x00d2, - 0x0011, 0x3be8, 0x0000, 0x0013, 0x000b, 0x108a, 0x0000, 0x3cb0, - 0x0014, 0x00e5, 0x0013, 0x00d2, 0x0011, 0x3be8, 0x0000, 0x0019, - 0x000b, 0x109d, 0x0010, 0x04fe, 0x001b, 0x6091, 0x0010, 0x3c05, - 0x0013, 0x0099, 0x0015, 0x0030, 0x0000, 0x0400, 0x0011, 0x0488, - 0x0010, 0x0003, 0x0000, 0xff31, 0x0015, 0x0033, 0x0010, 0x3c0a, - 0x000b, 0x8098, 0x0000, 0x3c04, 0x0002, 0x0c00, 0x0010, 0xff0c, - 0x0013, 0x00d2, 0x0011, 0x3be8, 0x0010, 0x001b, 0x001b, 0x10a6, - 0x0010, 0xc014, 0x0000, 0xc013, 0x0000, 0xc010, 0x0015, 0x000f, - 0x0010, 0x0000, 0x0013, 0x00d2, 0x0011, 0x3be8, 0x0000, 0x0015, - 0x001b, 0x10b2, 0x0004, 0x011c, 0x0014, 0x012e, 0x0015, 0x0039, - 0x0000, 0x8000, 0x0017, 0x8000, 0x0004, 0x0113, 0x0004, 0x0125, - 0x0014, 0x00fe, 0x0013, 0x002d, 0x0011, 0x3be8, 0x0000, 0x0016, - 0x000b, 0x10c4, 0x0001, 0x0fe8, 0x0010, 0x0000, 0x0003, 0x10be, - 0x0001, 0x0fe8, 0x0000, 0x0002, 0x0003, 0x10be, 0x0015, 0x0039, - 0x0010, 0x1010, 0x0013, 0x00d2, 0x0015, 0x0039, 0x0000, 0x5040, - 0x0015, 0x00b8, 0x0000, 0x0008, 0x0014, 0x0925, 0x0013, 0x00d2, - 0x0011, 0x3be8, 0x0010, 0x0017, 0x001b, 0x10c9, 0x0010, 0x3cc3, - 0x0013, 0x00d2, 0x0011, 0x3be8, 0x0010, 0x0018, 0x000b, 0x10ce, - 0x0000, 0x3cc2, 0x0013, 0x00d2, 0x0005, 0x00ce, 0x0000, 0x0001, - 0x0000, 0x3bcf, 0x0014, 0x08e7, 0x0015, 0x0039, 0x0000, 0x8000, - 0x0013, 0x002d, 0x0001, 0xb288, 0x0000, 0x0002, 0x0001, 0xc180, - 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb009, 0x001b, 0x80db, - 0x0002, 0xb200, 0x0011, 0xffc8, 0x0000, 0x0007, 0x0010, 0xffb2, - 0x0010, 0xc131, 0x0015, 0x0033, 0x0010, 0xb20a, 0x0001, 0xb0d0, - 0x001b, 0x80e4, 0x0015, 0x0030, 0x0000, 0x0400, 0x0011, 0xb088, - 0x0000, 0x0010, 0x0000, 0xff31, 0x0015, 0x0033, 0x0010, 0xb109, - 0x000b, 0x80ec, 0x0001, 0xb1e8, 0x0010, 0xffff, 0x0013, 0x10fd, - 0x0000, 0x11fe, 0x001b, 0x60f4, 0x0000, 0xb012, 0x0013, 0x00fc, - 0x0015, 0x0030, 0x0000, 0x0400, 0x0001, 0x1188, 0x0010, 0x0003, - 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb00a, 0x000b, 0x80fb, - 0x0000, 0xb011, 0x0017, 0x4000, 0x0015, 0x0030, 0x0000, 0x0400, - 0x0011, 0xbc88, 0x0000, 0x001f, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0000, 0xc411, 0x000b, 0x8105, 0x0011, 0xbc88, 0x0010, 0x0018, - 0x0000, 0xff31, 0x0015, 0x0033, 0x0010, 0xc609, 0x001b, 0x810b, - 0x0011, 0xbc88, 0x0000, 0x0037, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0000, 0xc709, 0x000b, 0x8111, 0x0017, 0x4000, 0x0015, 0x0030, - 0x0000, 0x0400, 0x0001, 0xbb88, 0x0000, 0x0001, 0x0000, 0xff31, - 0x0015, 0x0033, 0x0000, 0x0269, 0x001b, 0x811a, 0x0017, 0x4000, - 0x0015, 0x0030, 0x0000, 0x0400, 0x0001, 0xbb88, 0x0000, 0x0001, - 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0x026a, 0x001b, 0x8123, - 0x0017, 0x4000, 0x0015, 0x0030, 0x0000, 0x0400, 0x0001, 0xbb88, - 0x0010, 0x000f, 0x0000, 0xff31, 0x0015, 0x0033, 0x0010, 0x0f59, - 0x001b, 0x812c, 0x0017, 0x4000, 0x0015, 0x0030, 0x0000, 0x0400, - 0x0001, 0xbb88, 0x0010, 0x000f, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0010, 0x0f5a, 0x000b, 0x8135, 0x0017, 0x4000, 0x0000, 0xd0ff, - 0x0012, 0xff40, 0x000b, 0x1031, 0x0015, 0x00d1, 0x0010, 0x0101, - 0x0003, 0x913c, 0x0005, 0x0079, 0x0000, 0x0001, 0x0003, 0x913f, - 0x0015, 0x00d1, 0x0000, 0x0100, 0x0011, 0x02e8, 0x0000, 0x0002, - 0x0003, 0x1167, 0x0011, 0x02e8, 0x0000, 0x0001, 0x0003, 0x117f, - 0x0011, 0x02e8, 0x0000, 0x0004, 0x0003, 0x119d, 0x0011, 0x02e8, - 0x0010, 0x0003, 0x0003, 0x11ce, 0x0005, 0x0002, 0x0010, 0x0000, - 0x0000, 0xc00e, 0x0000, 0xc00d, 0x0010, 0xc003, 0x0015, 0x0030, - 0x0000, 0x0400, 0x0001, 0xbd88, 0x0010, 0x0009, 0x0000, 0xff31, - 0x0015, 0x0033, 0x0010, 0xc00a, 0x000b, 0x815a, 0x0000, 0xff31, - 0x0015, 0x0033, 0x0010, 0xc00a, 0x001b, 0x815e, 0x0012, 0x3a45, - 0x0013, 0x1166, 0x0015, 0x003a, 0x0000, 0x2000, 0x0015, 0x003a, - 0x0010, 0x1010, 0x0004, 0x0911, 0x0003, 0x004f, 0x0012, 0x7849, - 0x0003, 0x11dc, 0x0010, 0x0dfe, 0x0003, 0x6150, 0x0012, 0x0c10, - 0x0010, 0xff0c, 0x0015, 0x0030, 0x0000, 0x0400, 0x0011, 0x0d88, - 0x0010, 0x0003, 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb309, - 0x000b, 0x8174, 0x0010, 0xb3fe, 0x0013, 0x617c, 0x0010, 0xb30b, - 0x0015, 0x0033, 0x0010, 0xc00a, 0x001b, 0x817a, 0x0003, 0x01d1, - 0x0000, 0xc00b, 0x0010, 0xc00a, 0x0003, 0x01d1, 0x0000, 0x78b0, - 0x0012, 0xb044, 0x0003, 0x11dc, 0x0002, 0xb049, 0x0003, 0x11dc, - 0x0010, 0x71ff, 0x0012, 0xff38, 0x0010, 0xff71, 0x0010, 0x0dfe, - 0x0003, 0x614e, 0x0012, 0x0c10, 0x0010, 0xff0c, 0x0015, 0x0030, - 0x0000, 0x0400, 0x0011, 0x0d88, 0x0010, 0x0003, 0x0000, 0xff31, - 0x0015, 0x0033, 0x0000, 0xb309, 0x001b, 0x8192, 0x0010, 0xb3fe, - 0x0003, 0x619a, 0x0000, 0xb309, 0x0015, 0x0033, 0x0010, 0xc00a, - 0x001b, 0x8198, 0x0003, 0x01d1, 0x0010, 0xc009, 0x0000, 0xc008, - 0x0003, 0x01d1, 0x0000, 0x78b0, 0x0012, 0xb044, 0x0003, 0x11dc, - 0x0002, 0xb049, 0x0003, 0x11dc, 0x0010, 0x71ff, 0x0012, 0xff38, - 0x0010, 0xff71, 0x0010, 0x0dfe, 0x0003, 0x614e, 0x0012, 0x0c10, - 0x0010, 0xff0c, 0x0015, 0x0030, 0x0000, 0x0400, 0x0011, 0x0d88, - 0x0010, 0x0003, 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb309, - 0x001b, 0x81b0, 0x0010, 0xb3fe, 0x0003, 0x61b8, 0x0000, 0xb305, - 0x0015, 0x0033, 0x0010, 0xc00a, 0x001b, 0x81b6, 0x0013, 0x01ba, - 0x0010, 0xc005, 0x0000, 0xc004, 0x0002, 0x033f, 0x0002, 0xff27, - 0x0000, 0x0db8, 0x0014, 0x03c2, 0x0000, 0x0db8, 0x0014, 0x0925, - 0x0015, 0x0030, 0x0000, 0x0400, 0x0011, 0xbc88, 0x0010, 0x0000, - 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb309, 0x001b, 0x81c7, - 0x0011, 0xb3e8, 0x0000, 0x0002, 0x000b, 0x114e, 0x0005, 0x0002, - 0x0010, 0x0005, 0x0003, 0x0150, 0x0012, 0x7849, 0x0003, 0x11dc, - 0x0003, 0x0150, 0x0000, 0x0db8, 0x0012, 0x0345, 0x000b, 0x11d7, - 0x0002, 0x033f, 0x0014, 0x03c2, 0x0003, 0x014e, 0x0002, 0x033f, - 0x0002, 0xff27, 0x0014, 0x03c2, 0x0014, 0x0925, 0x0003, 0x014e, - 0x0015, 0x00b8, 0x0000, 0x0001, 0x0015, 0x003a, 0x0010, 0x0101, - 0x0014, 0x0925, 0x0003, 0x015f, 0x0001, 0x2bd8, 0x0010, 0x0000, - 0x0000, 0xffba, 0x0003, 0xb1e5, 0x0005, 0x002a, 0x0000, 0x0002, - 0x0001, 0xbac8, 0x0000, 0x0700, 0x000b, 0x12d2, 0x0011, 0x15e8, - 0x0000, 0x0002, 0x0013, 0x1248, 0x0011, 0x15e8, 0x0000, 0x0001, - 0x0003, 0x11f4, 0x0005, 0x0015, 0x0010, 0x0000, 0x0003, 0x022b, - 0x0005, 0x0015, 0x0010, 0x0000, 0x0002, 0xba43, 0x0003, 0x122c, - 0x0003, 0xb1f8, 0x0005, 0x002a, 0x0000, 0x0004, 0x0012, 0xba42, - 0x0003, 0x1232, 0x0012, 0x104b, 0x000b, 0x122b, 0x0000, 0x1a30, - 0x0005, 0x0031, 0x0000, 0x0002, 0x0015, 0x0033, 0x0000, 0x1b2a, - 0x001b, 0x8204, 0x0011, 0x20d8, 0x0010, 0x0000, 0x0000, 0xffb0, - 0x0001, 0x21d8, 0x0010, 0x0000, 0x0010, 0xffb1, 0x0001, 0x22d8, - 0x0010, 0x0000, 0x0010, 0xffb2, 0x0011, 0x23d8, 0x0010, 0x0000, - 0x0000, 0xffb3, 0x0001, 0x24d8, 0x0010, 0x0000, 0x0010, 0xffb4, - 0x0011, 0x25d8, 0x0010, 0x0000, 0x0000, 0xffb5, 0x0001, 0x28d8, - 0x0010, 0x0000, 0x0010, 0xffb8, 0x0011, 0x29d8, 0x0010, 0x0000, - 0x0000, 0xffb9, 0x0000, 0x1a30, 0x0005, 0x0031, 0x0000, 0x0007, - 0x0015, 0x0033, 0x0010, 0xb032, 0x000b, 0x8222, 0x0000, 0x1a30, - 0x0005, 0x0031, 0x0010, 0x000f, 0x0015, 0x0033, 0x0010, 0xb812, - 0x000b, 0x8228, 0x0005, 0x0015, 0x0010, 0x0000, 0x0013, 0x0035, - 0x0000, 0x1efe, 0x0013, 0x6240, 0x0014, 0x0277, 0x0000, 0x1efe, - 0x000c, 0x6277, 0x0003, 0x022b, 0x0000, 0x1a30, 0x0005, 0x0031, - 0x0000, 0x0020, 0x0015, 0x0033, 0x0000, 0xb009, 0x001b, 0x8237, - 0x0002, 0xb02f, 0x0000, 0xffb0, 0x0005, 0x0031, 0x0000, 0x0020, - 0x0015, 0x0033, 0x0000, 0xb00a, 0x001b, 0x823e, 0x0003, 0x01ff, - 0x0015, 0x00b8, 0x0010, 0x0005, 0x0014, 0x0925, 0x0000, 0x13b8, - 0x0015, 0x003a, 0x0010, 0x0404, 0x0014, 0x0925, 0x0003, 0x022b, - 0x0005, 0x0015, 0x0000, 0x0001, 0x0012, 0xba42, 0x0013, 0x1256, - 0x0003, 0xb24c, 0x0001, 0x2bd8, 0x0010, 0x0000, 0x0012, 0xff4f, - 0x000b, 0x11e2, 0x0002, 0xba43, 0x001b, 0x1232, 0x0000, 0x1efe, - 0x000c, 0x6277, 0x0003, 0x022b, 0x0001, 0x28d8, 0x0010, 0x0000, - 0x0010, 0xffb8, 0x0011, 0x29d8, 0x0010, 0x0000, 0x0000, 0xffb9, - 0x0014, 0x02e8, 0x0002, 0x3a42, 0x000b, 0x122b, 0x0000, 0x1c30, - 0x0015, 0x00ff, 0x0000, 0x0002, 0x0002, 0x1f43, 0x001b, 0x1267, - 0x0001, 0xff88, 0x0000, 0x0002, 0x0003, 0x0269, 0x0001, 0xff88, - 0x0000, 0x0004, 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb011, - 0x000b, 0x826c, 0x0000, 0xb0ff, 0x0011, 0x16a0, 0x0000, 0xff16, - 0x001b, 0x2273, 0x0002, 0xb100, 0x0003, 0x0274, 0x0010, 0xb1ff, - 0x0001, 0x17a0, 0x0010, 0xff17, 0x0013, 0x0232, 0x0000, 0x16ff, - 0x0001, 0x18a0, 0x0010, 0xff00, 0x000b, 0x227e, 0x0002, 0x1700, - 0x0013, 0x12d1, 0x0013, 0x027f, 0x0010, 0x17ff, 0x0011, 0x19a0, - 0x0013, 0x22d1, 0x0011, 0x00d0, 0x0013, 0x12d1, 0x0000, 0x1c30, - 0x0000, 0x1b31, 0x0015, 0x0033, 0x0000, 0xb131, 0x000b, 0x8287, - 0x0013, 0xb288, 0x0000, 0xb120, 0x0010, 0xb221, 0x0002, 0x1f43, - 0x001b, 0x1294, 0x0010, 0xc022, 0x0000, 0xc023, 0x0000, 0xb324, - 0x0000, 0xb425, 0x0010, 0xb3b5, 0x0000, 0xb4b6, 0x0013, 0x0298, - 0x0000, 0xb322, 0x0000, 0xb423, 0x0000, 0xb524, 0x0010, 0xb625, - 0x0003, 0xb298, 0x0005, 0x002a, 0x0000, 0x0001, 0x0012, 0x1500, - 0x0000, 0xff15, 0x0000, 0x16ff, 0x0001, 0xb580, 0x0000, 0xff16, - 0x000b, 0x22a3, 0x0002, 0x1700, 0x0013, 0x02a4, 0x0010, 0x17ff, - 0x0001, 0xb680, 0x0010, 0xff17, 0x0012, 0x1e10, 0x0010, 0xff1e, - 0x0003, 0x62d1, 0x0002, 0x1d00, 0x0010, 0xff1d, 0x0010, 0xc030, - 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb009, 0x000b, 0x82af, - 0x0010, 0xb0fe, 0x000b, 0x62d0, 0x0000, 0x1c30, 0x0005, 0x0031, - 0x0000, 0x0001, 0x0015, 0x0033, 0x0000, 0xb009, 0x000b, 0x82b7, - 0x0010, 0xb0fe, 0x001b, 0x62bd, 0x0005, 0x00ce, 0x0010, 0x0005, - 0x0003, 0x08e7, 0x0010, 0xb01c, 0x0000, 0x1c30, 0x0005, 0x0031, - 0x0000, 0x0019, 0x0015, 0x0033, 0x0000, 0xb009, 0x000b, 0x82c3, - 0x0001, 0xb0c8, 0x0010, 0x00ff, 0x0000, 0xff1f, 0x0010, 0xc030, - 0x0011, 0xbe80, 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb009, - 0x000b, 0x82cc, 0x0000, 0xb01d, 0x0010, 0x1dff, 0x0013, 0x02ab, - 0x0000, 0xb01b, 0x0017, 0x4000, 0x0002, 0x3a41, 0x0003, 0x12da, - 0x0013, 0xb2d4, 0x0005, 0x002a, 0x0000, 0x0004, 0x0005, 0x0015, - 0x0010, 0x0000, 0x0003, 0x022b, 0x0000, 0x1a30, 0x0005, 0x0031, - 0x0000, 0x0002, 0x0015, 0x0033, 0x0000, 0x1b2a, 0x001b, 0x82df, - 0x0015, 0x00b8, 0x0000, 0x0004, 0x0014, 0x0925, 0x0000, 0x13b8, - 0x0015, 0x003a, 0x0010, 0x0404, 0x0014, 0x0925, 0x0013, 0x0039, - 0x0002, 0x1e00, 0x0010, 0xff1e, 0x0012, 0x1d10, 0x0010, 0xff1d, - 0x0010, 0xc030, 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb009, - 0x000b, 0x82f0, 0x0010, 0xb0fe, 0x001b, 0x6315, 0x0000, 0x1cff, - 0x0001, 0x1ae0, 0x0013, 0x12ff, 0x0000, 0x1c30, 0x0005, 0x0031, - 0x0010, 0x0000, 0x0015, 0x0033, 0x0000, 0xb009, 0x001b, 0x82fb, - 0x0010, 0xb0fe, 0x001b, 0x62ff, 0x0000, 0x1aff, 0x0000, 0xff1c, - 0x0000, 0x1c30, 0x0005, 0x0031, 0x0000, 0x0019, 0x0015, 0x0033, - 0x0000, 0xb009, 0x001b, 0x8305, 0x0001, 0xb0c8, 0x0010, 0x000f, - 0x0000, 0xff1f, 0x0001, 0xbf80, 0x0010, 0xff1d, 0x0010, 0xc030, - 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb009, 0x001b, 0x830f, - 0x0010, 0xb0fe, 0x001b, 0x6315, 0x0005, 0x00ce, 0x0010, 0x0006, - 0x0003, 0x08e7, 0x0000, 0xb01b, 0x0017, 0x4000, 0x0010, 0x79b0, - 0x0000, 0xd0ff, 0x0012, 0xff40, 0x001b, 0x1039, 0x0015, 0x00d1, - 0x0010, 0x0101, 0x0013, 0x931d, 0x0005, 0x0079, 0x0000, 0x0002, - 0x0003, 0x9320, 0x0015, 0x00d1, 0x0000, 0x0100, 0x0010, 0x13fe, - 0x0013, 0x6371, 0x0012, 0xb04e, 0x001b, 0x139a, 0x0000, 0x78b0, - 0x0002, 0xb045, 0x0003, 0x13a0, 0x0012, 0x784a, 0x0003, 0x13a0, - 0x0000, 0x75ff, 0x0011, 0xffc8, 0x0010, 0x1800, 0x001b, 0x13a0, - 0x0001, 0x0fe8, 0x0000, 0x0001, 0x001b, 0x133c, 0x0015, 0x0030, - 0x0000, 0x0400, 0x0011, 0x1388, 0x0000, 0x000e, 0x0000, 0xff31, - 0x0015, 0x0033, 0x0000, 0x8f0a, 0x001b, 0x833a, 0x0013, 0x03a6, - 0x0001, 0x0fe8, 0x0000, 0x0002, 0x001b, 0x1347, 0x0015, 0x0030, - 0x0000, 0x0400, 0x0005, 0x0031, 0x0000, 0x001a, 0x0015, 0x0033, - 0x0010, 0xc00a, 0x000b, 0x8345, 0x0013, 0x03a6, 0x0001, 0x0fe8, - 0x0010, 0x0000, 0x0003, 0x134e, 0x0005, 0x00ce, 0x0000, 0x0007, - 0x0010, 0x0fcf, 0x0003, 0x08e1, 0x0002, 0xd142, 0x0013, 0x1367, - 0x0015, 0x00d1, 0x0000, 0x0400, 0x0011, 0x13e8, 0x0001, 0x1b55, - 0x000b, 0x1367, 0x0005, 0x0031, 0x0011, 0x1b6d, 0x0015, 0x0033, - 0x0010, 0xb409, 0x001b, 0x8359, 0x0002, 0xb400, 0x0010, 0xffb4, - 0x0005, 0x0031, 0x0011, 0x1b6d, 0x0015, 0x0033, 0x0010, 0xb40a, - 0x001b, 0x8360, 0x0012, 0xd042, 0x0003, 0x1371, 0x0015, 0x00b8, - 0x0000, 0x000d, 0x0014, 0x0925, 0x0003, 0x0054, 0x0000, 0x13b8, - 0x0002, 0x1045, 0x0003, 0x136f, 0x0012, 0x103f, 0x0002, 0xff27, - 0x0014, 0x03c2, 0x0014, 0x0925, 0x0013, 0x0371, 0x0012, 0x103f, - 0x0014, 0x03c2, 0x0015, 0x000f, 0x0010, 0x0000, 0x0002, 0x3944, - 0x0013, 0x137a, 0x0015, 0x0039, 0x0000, 0x5040, 0x0015, 0x00b8, - 0x0000, 0x0008, 0x0014, 0x0925, 0x0015, 0x0030, 0x0000, 0x0400, - 0x0001, 0xbd88, 0x0010, 0x000c, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0010, 0xc00a, 0x001b, 0x8381, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0010, 0xc00a, 0x000b, 0x8385, 0x0010, 0xc014, 0x0000, 0xc013, - 0x0000, 0xc010, 0x0000, 0xa4ff, 0x0003, 0x6392, 0x0011, 0xffa8, - 0x0010, 0x0005, 0x000b, 0x2392, 0x0015, 0x00d1, 0x0010, 0x0404, - 0x0015, 0x003a, 0x0000, 0x8000, 0x0002, 0x3a47, 0x0003, 0x1399, - 0x0015, 0x003a, 0x0000, 0x8000, 0x0015, 0x003a, 0x0010, 0x4040, - 0x0004, 0x08ec, 0x0013, 0x0039, 0x0015, 0x00b8, 0x0010, 0x0003, - 0x0015, 0x003a, 0x0010, 0x0202, 0x0014, 0x0925, 0x0003, 0x0389, - 0x0015, 0x00b8, 0x0000, 0x0002, 0x0015, 0x003a, 0x0010, 0x0202, - 0x0014, 0x0925, 0x0003, 0x0389, 0x0015, 0x0030, 0x0000, 0x0400, - 0x0011, 0x1388, 0x0010, 0x0003, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0000, 0xb009, 0x000b, 0x83ad, 0x0011, 0x1388, 0x0010, 0x0003, - 0x0000, 0xff31, 0x0015, 0x0033, 0x0010, 0xc00a, 0x000b, 0x83b3, - 0x0010, 0xb0fe, 0x0013, 0x63b8, 0x0000, 0xb012, 0x0003, 0x03ba, - 0x0010, 0xc012, 0x0010, 0xc011, 0x0012, 0x104b, 0x0003, 0x134e, - 0x0002, 0x103b, 0x0010, 0xff03, 0x0005, 0x0002, 0x0010, 0x0000, - 0x0000, 0xc00d, 0x0013, 0x034e, 0x0000, 0xffb0, 0x0010, 0xc3b1, - 0x0015, 0x0030, 0x0000, 0x0400, 0x0001, 0xb888, 0x0010, 0x0011, - 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb012, 0x000b, 0x83cb, - 0x0017, 0x4000, 0x0002, 0xd142, 0x001b, 0x1485, 0x0012, 0x3a43, - 0x0003, 0x13de, 0x0015, 0x003a, 0x0000, 0x0800, 0x0010, 0x0db0, - 0x0013, 0x63de, 0x0000, 0x0bff, 0x0001, 0xb0e0, 0x0003, 0x1407, - 0x0010, 0x09ff, 0x0001, 0xb0e0, 0x0003, 0x13eb, 0x0010, 0x05ff, - 0x0001, 0xb0e0, 0x0003, 0x13e2, 0x0000, 0xc00e, 0x0000, 0x05fe, - 0x0013, 0x63e8, 0x0000, 0x050d, 0x0005, 0x0002, 0x0000, 0x0004, - 0x0014, 0x046c, 0x0002, 0x3a47, 0x001b, 0x146b, 0x0013, 0x0402, - 0x0000, 0x09fe, 0x0013, 0x6404, 0x0000, 0x090d, 0x0005, 0x0002, - 0x0000, 0x0001, 0x0014, 0x049a, 0x0015, 0x0030, 0x0000, 0x0400, - 0x0011, 0x0d88, 0x0000, 0x0004, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0000, 0xba09, 0x001b, 0x83f5, 0x0011, 0x03c8, 0x0010, 0x000f, - 0x0000, 0xffb6, 0x0011, 0xb6e8, 0x0000, 0x0001, 0x0003, 0x153f, - 0x0011, 0xb6e8, 0x0000, 0x0002, 0x0013, 0x1561, 0x0011, 0xb6e8, - 0x0010, 0x0003, 0x0003, 0x1653, 0x0004, 0x08ec, 0x0013, 0x046b, - 0x0010, 0x0bfe, 0x0013, 0x646b, 0x0010, 0x0b0d, 0x0005, 0x0002, - 0x0000, 0x0002, 0x0014, 0x049a, 0x0015, 0x0030, 0x0000, 0x0400, - 0x0011, 0x0d88, 0x0000, 0x0004, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0000, 0xba09, 0x000b, 0x8411, 0x0000, 0xb930, 0x0005, 0x0031, - 0x0010, 0x0021, 0x0015, 0x0033, 0x0000, 0xb009, 0x000b, 0x8417, - 0x0001, 0xb0a8, 0x0000, 0x199a, 0x0013, 0x241d, 0x0005, 0x00b0, - 0x0000, 0x1999, 0x0012, 0xb050, 0x0000, 0xffb0, 0x0002, 0xff50, - 0x0002, 0xff50, 0x0001, 0xb080, 0x0000, 0xffb0, 0x0015, 0x0030, - 0x0000, 0x0400, 0x0011, 0x0d88, 0x0010, 0x0006, 0x0000, 0xff31, - 0x0015, 0x0033, 0x0000, 0xb00a, 0x001b, 0x842a, 0x0000, 0xb930, - 0x0005, 0x0031, 0x0000, 0x0019, 0x0015, 0x0033, 0x0000, 0xb009, - 0x000b, 0x8430, 0x0001, 0xb0c8, 0x0010, 0x00ff, 0x0001, 0xffe8, - 0x0010, 0x0048, 0x000b, 0x14a9, 0x0005, 0x0002, 0x0010, 0x0006, - 0x0012, 0x0c10, 0x0010, 0xff0c, 0x0015, 0x0030, 0x0000, 0x0400, - 0x0011, 0x0d88, 0x0010, 0x0003, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0010, 0xb109, 0x000b, 0x8441, 0x0000, 0xb10b, 0x000b, 0x6445, - 0x0010, 0xb10a, 0x0015, 0x0033, 0x0010, 0xc00a, 0x000b, 0x8447, - 0x0002, 0x032b, 0x0010, 0xff03, 0x0011, 0x0d88, 0x0010, 0x0011, - 0x0000, 0xff31, 0x0015, 0x0033, 0x0010, 0x030a, 0x001b, 0x844f, - 0x0000, 0x11fe, 0x000b, 0x6454, 0x0000, 0x0d12, 0x0013, 0x045d, - 0x0015, 0x0030, 0x0000, 0x0400, 0x0001, 0x1188, 0x0010, 0x0003, - 0x0000, 0xff31, 0x0010, 0x0db0, 0x0015, 0x0033, 0x0000, 0xb00a, - 0x000b, 0x845c, 0x0000, 0x0d11, 0x0013, 0x046b, 0x0002, 0xd142, - 0x0003, 0x1462, 0x0013, 0x0485, 0x0000, 0x05fe, 0x0013, 0x646b, - 0x0005, 0x0002, 0x0000, 0x0004, 0x0000, 0x050d, 0x0014, 0x046c, - 0x0002, 0x3a47, 0x001b, 0x146b, 0x0004, 0x08ec, 0x0013, 0x0047, - 0x0001, 0xc7c8, 0x0010, 0x0028, 0x000b, 0x1484, 0x0015, 0x0030, - 0x0000, 0x0400, 0x0011, 0x0d88, 0x0010, 0x000a, 0x0000, 0xff31, - 0x0015, 0x0033, 0x0000, 0xb009, 0x001b, 0x8476, 0x0002, 0xb04f, - 0x0013, 0x1484, 0x0001, 0x0fe8, 0x0010, 0x0000, 0x0013, 0x1482, - 0x0001, 0x0fe8, 0x0000, 0x0002, 0x0013, 0x1482, 0x0015, 0x003a, - 0x0010, 0x8080, 0x0003, 0x0484, 0x0015, 0x003a, 0x0010, 0x4040, - 0x0017, 0x4000, 0x0000, 0x12fe, 0x001b, 0x604f, 0x0015, 0x0012, - 0x0001, 0x1b55, 0x0015, 0x0011, 0x0001, 0x1b55, 0x0001, 0x1288, - 0x0010, 0x0003, 0x0000, 0xff31, 0x0015, 0x0033, 0x0010, 0xc00a, - 0x000b, 0x8490, 0x0005, 0x00b0, 0x0000, 0x8000, 0x0001, 0x1288, - 0x0010, 0x0011, 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb00a, - 0x001b, 0x8498, 0x0003, 0x004f, 0x0015, 0x0030, 0x0000, 0x0400, - 0x0011, 0x0d88, 0x0010, 0x0011, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0010, 0x0309, 0x001b, 0x84a1, 0x0011, 0x0d88, 0x0010, 0x0005, - 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb909, 0x001b, 0x84a7, - 0x0017, 0x4000, 0x0005, 0x00b6, 0x0010, 0x0600, 0x0014, 0x0683, - 0x0004, 0x051b, 0x0000, 0xb05a, 0x0000, 0xb15b, 0x0005, 0x0054, - 0x0010, 0x0829, 0x0010, 0x0d58, 0x0015, 0x0059, 0x0010, 0xffff, - 0x0000, 0xb930, 0x0005, 0x0031, 0x0010, 0x001e, 0x0015, 0x0033, - 0x0000, 0xb009, 0x001b, 0x84b9, 0x0000, 0xb05c, 0x0005, 0x0031, - 0x0000, 0x001f, 0x0015, 0x0033, 0x0000, 0xb009, 0x001b, 0x84bf, - 0x0001, 0xb0c8, 0x0010, 0x000f, 0x000b, 0x14c6, 0x0015, 0x00ff, - 0x0010, 0x0005, 0x0013, 0x04ce, 0x0002, 0xb040, 0x0003, 0x14cb, - 0x0015, 0x00ff, 0x0000, 0x0004, 0x0013, 0x04ce, 0x0001, 0xb0c8, - 0x0010, 0x0006, 0x0002, 0xff60, 0x0010, 0xffb2, 0x0015, 0x0030, - 0x0000, 0x0400, 0x0011, 0x0d88, 0x0000, 0x0019, 0x0000, 0xff31, - 0x0015, 0x0033, 0x0010, 0xb109, 0x001b, 0x84d6, 0x0012, 0xb170, - 0x0011, 0xffc8, 0x0010, 0xff00, 0x0011, 0xb2d0, 0x0010, 0xff60, - 0x0002, 0xb045, 0x0013, 0x14e1, 0x0015, 0x00b2, 0x0000, 0x0002, - 0x0003, 0x04eb, 0x0002, 0xb046, 0x0003, 0x14e6, 0x0015, 0x00b2, - 0x0000, 0x0001, 0x0003, 0x04eb, 0x0015, 0x00b2, 0x0010, 0x0000, - 0x0000, 0xc0b0, 0x0010, 0xc0b1, 0x0013, 0x04f1, 0x0000, 0xb930, - 0x0005, 0x0031, 0x0010, 0x002b, 0x0015, 0x0033, 0x0000, 0xb011, - 0x000b, 0x84f0, 0x0010, 0xb16a, 0x0010, 0xb06b, 0x0000, 0xb261, - 0x0015, 0x0044, 0x0010, 0x0018, 0x0000, 0xb930, 0x0005, 0x0031, - 0x0000, 0x0023, 0x0015, 0x0033, 0x0000, 0x6241, 0x001b, 0x84fb, - 0x0003, 0x94fc, 0x0015, 0x00a0, 0x0000, 0x0020, 0x0012, 0xd041, - 0x000b, 0x14ff, 0x0015, 0x00d1, 0x0010, 0x0202, 0x0013, 0x9503, - 0x0000, 0x75ff, 0x0011, 0xffc8, 0x0000, 0x1804, 0x0001, 0xffd8, - 0x0010, 0x0009, 0x0013, 0x9509, 0x0000, 0xff75, 0x0003, 0x950b, - 0x0015, 0x00d1, 0x0000, 0x0200, 0x0015, 0x0030, 0x0000, 0x0400, - 0x0001, 0xbd88, 0x0000, 0x0008, 0x0000, 0xff31, 0x0015, 0x00b1, - 0x0010, 0x07d0, 0x0005, 0x00b0, 0x0010, 0x0009, 0x0015, 0x0033, - 0x0000, 0xb012, 0x000b, 0x8519, 0x0013, 0x046b, 0x0000, 0xba30, - 0x0005, 0x0031, 0x0010, 0x0035, 0x0015, 0x0033, 0x0000, 0xb009, - 0x000b, 0x8520, 0x0002, 0xb040, 0x0003, 0x153c, 0x0015, 0x0030, - 0x0000, 0x0400, 0x0005, 0x0031, 0x0001, 0x1b71, 0x0015, 0x0033, - 0x0000, 0xb011, 0x000b, 0x8529, 0x0002, 0xb100, 0x0010, 0xffb1, - 0x001b, 0x2530, 0x0012, 0xb000, 0x0000, 0xffb0, 0x0013, 0x252a, - 0x0015, 0x0033, 0x0000, 0xb012, 0x000b, 0x8532, 0x0015, 0x0030, - 0x0000, 0x0400, 0x0011, 0x0d88, 0x0000, 0x0013, 0x0000, 0xff31, - 0x0015, 0x0033, 0x0000, 0xb012, 0x001b, 0x853a, 0x0003, 0x053e, - 0x0010, 0xc0b1, 0x0000, 0xc0b0, 0x0017, 0x4000, 0x0005, 0x00b6, - 0x0010, 0x0500, 0x0014, 0x0683, 0x0005, 0x0054, 0x0010, 0x0889, - 0x0015, 0x0030, 0x0000, 0x0400, 0x0011, 0x0d88, 0x0000, 0x0002, - 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb009, 0x001b, 0x854b, - 0x0010, 0xb058, 0x0000, 0x0d59, 0x0000, 0xb930, 0x0005, 0x0031, - 0x0000, 0x0023, 0x0015, 0x0033, 0x0000, 0xb011, 0x001b, 0x8553, - 0x0010, 0xb15c, 0x0010, 0xb05d, 0x0005, 0x0031, 0x0010, 0x002b, - 0x0015, 0x0033, 0x0000, 0xb011, 0x001b, 0x855a, 0x0000, 0xb15e, - 0x0000, 0xb05f, 0x0003, 0x955d, 0x0015, 0x00a0, 0x0010, 0x000c, - 0x0003, 0x0668, 0x0005, 0x00b6, 0x0000, 0x0700, 0x0014, 0x0683, - 0x0015, 0x0030, 0x0000, 0x0400, 0x0011, 0x0d88, 0x0010, 0x0009, - 0x0000, 0xff31, 0x0015, 0x0033, 0x0010, 0xb709, 0x000b, 0x856b, - 0x0012, 0xb749, 0x0003, 0x1571, 0x0005, 0x0054, 0x0010, 0x0889, - 0x0003, 0x0573, 0x0005, 0x0054, 0x0010, 0x0898, 0x0015, 0x0030, - 0x0000, 0x0400, 0x0011, 0x0d88, 0x0000, 0x0002, 0x0000, 0xff31, - 0x0015, 0x0033, 0x0000, 0xb009, 0x000b, 0x857a, 0x0010, 0xb058, - 0x0000, 0x0d59, 0x0001, 0xb9c8, 0x0010, 0xf000, 0x0001, 0xffe8, - 0x0010, 0xf000, 0x001b, 0x15a3, 0x0015, 0x0030, 0x0000, 0x0400, - 0x0011, 0x0d88, 0x0010, 0x0005, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0000, 0xb009, 0x000b, 0x8589, 0x0001, 0xb0c8, 0x0000, 0xf700, - 0x0000, 0xffb0, 0x0011, 0xb0e8, 0x0000, 0xf100, 0x0013, 0x15ea, - 0x0011, 0xb0e8, 0x0000, 0xf200, 0x0013, 0x15ef, 0x0011, 0xb0e8, - 0x0010, 0xf300, 0x0003, 0x1614, 0x0011, 0xb0e8, 0x0000, 0xf400, - 0x0013, 0x1619, 0x0011, 0xb0e8, 0x0010, 0xf500, 0x0013, 0x15ea, - 0x0011, 0xb0e8, 0x0010, 0xf600, 0x0003, 0x162b, 0x0005, 0x00ce, - 0x0010, 0x0009, 0x0000, 0xb0cf, 0x0003, 0x08e1, 0x0000, 0xb930, - 0x0005, 0x0031, 0x0000, 0x0025, 0x0015, 0x0033, 0x0000, 0xb039, - 0x000b, 0x85a8, 0x0012, 0xb749, 0x0013, 0x15ad, 0x0002, 0xb52c, - 0x0000, 0xffb5, 0x0000, 0xb162, 0x0000, 0xb063, 0x0005, 0x0031, - 0x0000, 0x001f, 0x0015, 0x0033, 0x0000, 0xb309, 0x000b, 0x85b3, - 0x0001, 0xb3c8, 0x0010, 0x0003, 0x0003, 0x15bb, 0x0010, 0xffb2, - 0x0001, 0xffe8, 0x0010, 0x0003, 0x001b, 0x15bd, 0x0000, 0xc2b7, - 0x0013, 0x0647, 0x0001, 0xb2e8, 0x0000, 0x0001, 0x0013, 0x15c4, - 0x0005, 0x00ce, 0x0010, 0x000a, 0x0010, 0xb2cf, 0x0003, 0x08e1, - 0x0010, 0xb465, 0x0010, 0xb667, 0x0015, 0x00b7, 0x0010, 0x0018, - 0x0001, 0xb5c8, 0x0010, 0x0300, 0x0013, 0x15e9, 0x0012, 0xb548, - 0x0013, 0x15d0, 0x0000, 0xb6ff, 0x0011, 0xb780, 0x0010, 0xffb7, - 0x0002, 0xb549, 0x0013, 0x15d5, 0x0010, 0xb4ff, 0x0011, 0xb780, - 0x0010, 0xffb7, 0x0015, 0x0044, 0x0010, 0x0018, 0x0005, 0x0031, - 0x0000, 0x002c, 0x0015, 0x0033, 0x0000, 0x6841, 0x001b, 0x85db, - 0x0015, 0x0044, 0x0000, 0x0019, 0x0005, 0x0031, 0x0000, 0x0034, - 0x0015, 0x0033, 0x0000, 0x5029, 0x001b, 0x85e2, 0x0015, 0x0044, - 0x0000, 0x0008, 0x0011, 0xb7c8, 0x0010, 0x0003, 0x0013, 0x15e9, - 0x0010, 0xff55, 0x0013, 0x0647, 0x0005, 0x00b5, 0x0000, 0x0008, - 0x0015, 0x00b7, 0x0010, 0x0018, 0x0013, 0x0647, 0x0015, 0x0030, - 0x0000, 0x0400, 0x0011, 0x0d88, 0x0000, 0x000b, 0x0000, 0xff31, - 0x0015, 0x0033, 0x0000, 0xb011, 0x001b, 0x85f6, 0x0010, 0xb1ff, - 0x0001, 0xb0d0, 0x0003, 0x15ff, 0x0005, 0x00b5, 0x0010, 0x0b02, - 0x0010, 0xb062, 0x0010, 0xb163, 0x0003, 0x0601, 0x0005, 0x00b5, - 0x0000, 0x0302, 0x0015, 0x0065, 0x0010, 0x0012, 0x0005, 0x0067, - 0x0000, 0x0008, 0x0015, 0x006c, 0x0000, 0x7000, 0x0005, 0x006d, - 0x0010, 0x0500, 0x0015, 0x006f, 0x0010, 0x000a, 0x0015, 0x0044, - 0x0000, 0x0001, 0x0005, 0x0052, 0x0000, 0x2500, 0x0015, 0x0044, - 0x0000, 0x0008, 0x0015, 0x00b7, 0x0000, 0x0032, 0x0013, 0x0647, - 0x0005, 0x00b5, 0x0010, 0x0028, 0x0015, 0x00b7, 0x0010, 0x0018, - 0x0013, 0x0647, 0x0005, 0x00b5, 0x0000, 0x0100, 0x0005, 0x0067, - 0x0000, 0x0008, 0x0015, 0x0030, 0x0000, 0x0400, 0x0011, 0x0d88, - 0x0010, 0x0018, 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb009, - 0x001b, 0x8624, 0x0001, 0xb0c8, 0x0010, 0x00ff, 0x0010, 0xff69, - 0x0015, 0x00b7, 0x0000, 0x0020, 0x0013, 0x0647, 0x0015, 0x0030, - 0x0000, 0x0400, 0x0011, 0x0d88, 0x0010, 0x0005, 0x0000, 0xff31, - 0x0015, 0x0033, 0x0000, 0xb609, 0x000b, 0x8632, 0x0001, 0xb6c8, - 0x0010, 0xff00, 0x0000, 0xffb0, 0x0015, 0x0033, 0x0000, 0xb00a, - 0x000b, 0x8638, 0x0001, 0xb6c8, 0x0010, 0x00ff, 0x0012, 0xff10, - 0x001b, 0x1641, 0x0000, 0xffb5, 0x0015, 0x00b7, 0x0010, 0x0018, - 0x0013, 0x0647, 0x0010, 0xff63, 0x0005, 0x00b5, 0x0000, 0x0800, - 0x0015, 0x00b7, 0x0010, 0x0018, 0x0013, 0x0647, 0x0015, 0x0030, - 0x0000, 0x0400, 0x0011, 0x0d88, 0x0010, 0x0009, 0x0000, 0xff31, - 0x0015, 0x0033, 0x0000, 0xb009, 0x001b, 0x864e, 0x0010, 0xb561, - 0x0013, 0x9650, 0x0010, 0xb7a0, 0x0003, 0x0668, 0x0005, 0x00b6, - 0x0010, 0x0300, 0x0014, 0x0683, 0x0005, 0x0054, 0x0010, 0x0819, - 0x0010, 0x0d58, 0x0015, 0x0030, 0x0000, 0x0400, 0x0011, 0x0d88, - 0x0000, 0x0002, 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb009, - 0x001b, 0x8660, 0x0000, 0xb059, 0x0003, 0x9662, 0x0010, 0xc0a0, - 0x0010, 0x71ff, 0x0002, 0xff28, 0x0010, 0xff71, 0x0003, 0x0668, - 0x0012, 0xd041, 0x000b, 0x1668, 0x0015, 0x00d1, 0x0010, 0x0202, - 0x0000, 0x75ff, 0x0011, 0xffc8, 0x0000, 0x1804, 0x0001, 0xffd8, - 0x0010, 0x0009, 0x0013, 0x9671, 0x0000, 0xff75, 0x0003, 0x9673, - 0x0015, 0x00d1, 0x0000, 0x0200, 0x0015, 0x0030, 0x0000, 0x0400, - 0x0001, 0xbd88, 0x0000, 0x0008, 0x0000, 0xff31, 0x0005, 0x00b0, - 0x0010, 0x0009, 0x0015, 0x00b1, 0x0010, 0x07d0, 0x0015, 0x0033, - 0x0000, 0xb012, 0x001b, 0x8681, 0x0013, 0x046b, 0x0015, 0x0044, - 0x0000, 0x0008, 0x0005, 0x0098, 0x0010, 0x0056, 0x0015, 0x0099, - 0x0000, 0x9575, 0x0004, 0x08a8, 0x0000, 0xb096, 0x0012, 0xb270, - 0x0010, 0xff56, 0x0014, 0x08ca, 0x0010, 0xb052, 0x0010, 0xb153, - 0x0000, 0xb6ff, 0x0011, 0xb2d0, 0x0010, 0xff50, 0x0010, 0xb351, - 0x0017, 0x4000, 0x0001, 0x12e8, 0x0001, 0x1b55, 0x0003, 0x1845, - 0x0015, 0x00d1, 0x0000, 0x0400, 0x0015, 0x0030, 0x0000, 0x0400, - 0x0001, 0x1288, 0x0010, 0x0011, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0000, 0x1009, 0x000b, 0x86a1, 0x0015, 0x000f, 0x0000, 0x0001, - 0x0010, 0xc014, 0x0000, 0x1213, 0x0015, 0x0030, 0x0000, 0x0400, - 0x0011, 0x1388, 0x0000, 0x0004, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0000, 0xba09, 0x000b, 0x86ad, 0x0015, 0x0030, 0x0000, 0x0400, - 0x0011, 0x1388, 0x0010, 0x0005, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0000, 0x1a09, 0x000b, 0x86b5, 0x0012, 0x104b, 0x001b, 0x16be, - 0x0000, 0x1a30, 0x0005, 0x0031, 0x0000, 0x000b, 0x0015, 0x0033, - 0x0000, 0x1621, 0x001b, 0x86bd, 0x0010, 0x15fe, 0x000b, 0x66dd, - 0x0004, 0x0704, 0x0002, 0x3a42, 0x000b, 0x1703, 0x0001, 0x10c8, - 0x0010, 0x000f, 0x000b, 0x1766, 0x0015, 0x0030, 0x0000, 0x0400, - 0x0011, 0x1388, 0x0000, 0x0008, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0000, 0xb009, 0x000b, 0x86cd, 0x0011, 0xb0e8, 0x0010, 0x0009, - 0x0003, 0x16d4, 0x0011, 0xb0e8, 0x0000, 0x0001, 0x001b, 0x1702, - 0x0011, 0x1388, 0x0010, 0x000a, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0000, 0xb009, 0x000b, 0x86d9, 0x0002, 0xb04f, 0x001b, 0x16f9, - 0x0013, 0x0702, 0x0015, 0x0030, 0x0000, 0x0400, 0x0011, 0x1388, - 0x0010, 0x0003, 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb009, - 0x001b, 0x86e4, 0x0015, 0x0033, 0x0010, 0xc00a, 0x001b, 0x86e7, - 0x0010, 0xb0fe, 0x0003, 0x66ec, 0x0000, 0xb012, 0x0013, 0x06ee, - 0x0010, 0xc012, 0x0010, 0xc011, 0x0015, 0x000f, 0x0010, 0x0000, - 0x0002, 0x3944, 0x0013, 0x16f7, 0x0015, 0x0039, 0x0000, 0x5040, - 0x0015, 0x00b8, 0x0000, 0x0008, 0x0014, 0x0925, 0x0000, 0xc013, - 0x0003, 0x0703, 0x0010, 0x02fe, 0x0003, 0x66fe, 0x0015, 0x003a, - 0x0010, 0x2020, 0x0003, 0x0703, 0x0015, 0x003a, 0x0000, 0x2000, - 0x0015, 0x003a, 0x0010, 0x1010, 0x0004, 0x0911, 0x0003, 0x0054, - 0x0003, 0xb704, 0x0005, 0x002a, 0x0000, 0x0004, 0x0000, 0xba30, - 0x0005, 0x0031, 0x0010, 0x001b, 0x0015, 0x0033, 0x0000, 0xb009, - 0x000b, 0x870c, 0x0000, 0xc02c, 0x0000, 0xb02d, 0x0012, 0x104b, - 0x0013, 0x1727, 0x0000, 0x1a30, 0x0005, 0x0031, 0x0000, 0x0023, - 0x0015, 0x0033, 0x0000, 0xb129, 0x001b, 0x8716, 0x0000, 0xb120, - 0x0010, 0xb221, 0x0000, 0xb322, 0x0000, 0xb423, 0x0000, 0xb524, - 0x0000, 0xc025, 0x0010, 0xb526, 0x0010, 0xc027, 0x0010, 0xb516, - 0x0010, 0xc017, 0x0000, 0xb518, 0x0000, 0xc019, 0x0010, 0xc028, - 0x0000, 0xc029, 0x0010, 0xc01e, 0x0013, 0x075d, 0x0012, 0x1044, - 0x0003, 0x1757, 0x0002, 0x1034, 0x0000, 0xff10, 0x0000, 0x1a30, - 0x0005, 0x0031, 0x0000, 0x0002, 0x0015, 0x0033, 0x0000, 0x1b29, - 0x000b, 0x8730, 0x0000, 0x1c30, 0x0000, 0x1b31, 0x0015, 0x0033, - 0x0000, 0xb131, 0x000b, 0x8735, 0x0002, 0x1f43, 0x000b, 0x173c, - 0x0010, 0xb3b5, 0x0000, 0xb4b6, 0x0000, 0xc0b3, 0x0010, 0xc0b4, - 0x0000, 0xb120, 0x0010, 0xb221, 0x0000, 0xb322, 0x0000, 0xb423, - 0x0000, 0xb524, 0x0010, 0xb625, 0x0010, 0xb516, 0x0000, 0xb617, - 0x0000, 0x1826, 0x0000, 0x1927, 0x0000, 0x1a30, 0x0005, 0x0031, - 0x0010, 0x000f, 0x0015, 0x0033, 0x0000, 0xb011, 0x000b, 0x874b, - 0x0000, 0xb028, 0x0000, 0xb129, 0x0012, 0x1e10, 0x0010, 0xff1e, - 0x0013, 0x675d, 0x0002, 0x1d00, 0x0010, 0xff1d, 0x0004, 0x02ab, - 0x0002, 0x3a42, 0x0003, 0x175d, 0x0003, 0x0765, 0x0000, 0x1a30, - 0x0005, 0x0031, 0x0000, 0x0002, 0x0015, 0x0033, 0x0000, 0x1b79, - 0x000b, 0x875c, 0x0003, 0xb75d, 0x0005, 0x002a, 0x0000, 0x0001, - 0x0005, 0x0015, 0x0000, 0x0001, 0x0000, 0x1efe, 0x0003, 0x6765, - 0x0003, 0x0277, 0x0017, 0x4000, 0x0000, 0xba30, 0x0005, 0x0031, - 0x0010, 0x001b, 0x0015, 0x0033, 0x0010, 0xb051, 0x001b, 0x876b, - 0x0000, 0xb0a3, 0x0010, 0xb697, 0x0010, 0xb946, 0x0015, 0x00a5, - 0x0000, 0x0010, 0x0015, 0x0030, 0x0000, 0x0400, 0x0011, 0x1388, - 0x0000, 0x0002, 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb509, - 0x000b, 0x8778, 0x0014, 0x08ca, 0x0004, 0x08b9, 0x0012, 0xb470, - 0x0010, 0xffb4, 0x0010, 0xb48e, 0x0010, 0xb08a, 0x0010, 0xb18b, - 0x0012, 0x104d, 0x0003, 0x1783, 0x0013, 0x07b0, 0x0012, 0x104b, - 0x0013, 0x1796, 0x0005, 0x008c, 0x0010, 0x0829, 0x0010, 0xc08d, - 0x0001, 0xb2d8, 0x0010, 0x0600, 0x0010, 0xff88, 0x0010, 0xb389, - 0x0000, 0x1390, 0x0010, 0xb591, 0x0000, 0xc08f, 0x0010, 0x1ab9, - 0x0004, 0x051b, 0x0013, 0x9791, 0x0010, 0xb092, 0x0010, 0xb193, - 0x0013, 0x9794, 0x0013, 0x07ab, 0x0005, 0x008c, 0x0000, 0x0809, - 0x0015, 0x008d, 0x0000, 0x0008, 0x0001, 0xb2d8, 0x0000, 0x0100, - 0x0010, 0xff88, 0x0010, 0xb389, 0x0000, 0x1390, 0x0010, 0xb591, - 0x0000, 0xc08f, 0x0000, 0x1a30, 0x0005, 0x0031, 0x0010, 0x000f, - 0x0015, 0x0033, 0x0000, 0xb011, 0x000b, 0x87a6, 0x0013, 0x97a7, - 0x0000, 0xb192, 0x0000, 0xb093, 0x0003, 0x97aa, 0x0010, 0x19a1, - 0x0000, 0x18a2, 0x0015, 0x00b1, 0x0010, 0x0096, 0x0003, 0x0821, - 0x0000, 0xb590, 0x0010, 0x1391, 0x0001, 0x10c8, 0x0010, 0x000f, - 0x0001, 0xffe8, 0x0010, 0x0005, 0x0013, 0x17d7, 0x0001, 0xb2d8, - 0x0000, 0x0700, 0x0010, 0xff88, 0x0010, 0xb389, 0x0015, 0x0030, - 0x0000, 0x0400, 0x0011, 0x1388, 0x0010, 0x0009, 0x0000, 0xff31, - 0x0015, 0x0033, 0x0000, 0xb009, 0x001b, 0x87c2, 0x0002, 0xb049, - 0x0013, 0x17ca, 0x0005, 0x008c, 0x0010, 0x0889, 0x0015, 0x00b1, - 0x0010, 0x0096, 0x0013, 0x07ce, 0x0005, 0x008c, 0x0010, 0x0898, - 0x0015, 0x00b1, 0x0000, 0x0092, 0x0010, 0xc08d, 0x0000, 0xc08f, - 0x0013, 0x97d0, 0x0000, 0xc092, 0x0010, 0xc093, 0x0013, 0x97d3, - 0x0010, 0x19a1, 0x0000, 0x18a2, 0x0003, 0x0821, 0x0001, 0xb2d8, - 0x0000, 0x0100, 0x0010, 0xff88, 0x0010, 0xb389, 0x0005, 0x008c, - 0x0010, 0x0880, 0x0015, 0x008d, 0x0000, 0x0008, 0x0015, 0x0030, - 0x0000, 0x0400, 0x0011, 0x1388, 0x0000, 0x000e, 0x0000, 0xff31, - 0x0015, 0x0033, 0x0000, 0xb009, 0x001b, 0x87e6, 0x0010, 0xb08f, - 0x0000, 0xb590, 0x0010, 0x1391, 0x0000, 0x1a30, 0x0005, 0x0031, - 0x0000, 0x000d, 0x0015, 0x0033, 0x0000, 0xb021, 0x001b, 0x87ef, - 0x0003, 0x97f0, 0x0010, 0xb392, 0x0010, 0xb293, 0x0003, 0x97f3, - 0x0000, 0xb1a1, 0x0010, 0xb0a2, 0x0015, 0x0030, 0x0000, 0x0400, - 0x0011, 0x1388, 0x0000, 0x000b, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0010, 0xb211, 0x001b, 0x87fd, 0x0000, 0xb3ff, 0x0001, 0xb080, - 0x0000, 0xffb3, 0x001b, 0x2804, 0x0002, 0xb200, 0x0003, 0x0805, - 0x0010, 0xb2ff, 0x0011, 0xb180, 0x0010, 0xffb2, 0x0011, 0x1388, - 0x0000, 0x000b, 0x0000, 0xff31, 0x0015, 0x0033, 0x0010, 0xb212, - 0x000b, 0x880c, 0x0015, 0x00b1, 0x0000, 0x0092, 0x0002, 0x104c, - 0x0003, 0x181f, 0x0011, 0xc2e8, 0x0010, 0x000c, 0x000b, 0x1817, - 0x0015, 0x00ff, 0x0000, 0x0800, 0x0013, 0x081f, 0x0011, 0xc2e8, - 0x0000, 0x0020, 0x000b, 0x181d, 0x0015, 0x00ff, 0x0010, 0x1800, - 0x0013, 0x081f, 0x0015, 0x00ff, 0x0000, 0x1000, 0x0011, 0xb1d0, - 0x0010, 0xffb1, 0x0015, 0x009a, 0x0010, 0x0036, 0x0005, 0x009b, - 0x0000, 0x95d5, 0x0012, 0xd041, 0x001b, 0x1825, 0x0015, 0x00d1, - 0x0010, 0x0202, 0x0013, 0x9829, 0x0012, 0x104e, 0x0013, 0x182e, - 0x0012, 0xb12f, 0x0010, 0xffb1, 0x0000, 0xb175, 0x0013, 0x982f, - 0x0015, 0x00d1, 0x0000, 0x0200, 0x0001, 0x19c8, 0x0010, 0xfff0, - 0x001b, 0x1838, 0x0015, 0x00b1, 0x0010, 0x07d0, 0x0003, 0x083a, - 0x0015, 0x00b1, 0x0000, 0x1b58, 0x0005, 0x00b0, 0x0010, 0x0009, - 0x0015, 0x0030, 0x0000, 0x0400, 0x0001, 0xbd88, 0x0000, 0x000b, - 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb012, 0x001b, 0x8843, - 0x0003, 0x0703, 0x0015, 0x0030, 0x0000, 0x0400, 0x0000, 0xa4ff, - 0x0003, 0x6893, 0x0011, 0xffa8, 0x0010, 0x0005, 0x000b, 0x2893, - 0x0005, 0x0031, 0x0001, 0x1b6c, 0x0015, 0x0033, 0x0010, 0xb211, - 0x000b, 0x8850, 0x0002, 0xb200, 0x0010, 0xffb2, 0x0005, 0x0031, - 0x0001, 0x1b6c, 0x0015, 0x0033, 0x0010, 0xb20a, 0x001b, 0x8857, - 0x0015, 0x000f, 0x0000, 0x0001, 0x0000, 0x1213, 0x0005, 0x0010, - 0x0000, 0x8000, 0x0015, 0x00a3, 0x0000, 0x0200, 0x0000, 0xc697, - 0x0005, 0x0046, 0x0000, 0x0002, 0x0015, 0x00a5, 0x0000, 0x0010, - 0x0011, 0xc4d8, 0x0000, 0x3200, 0x0010, 0xff88, 0x0000, 0xc589, - 0x0010, 0xc48a, 0x0010, 0xc58b, 0x0010, 0xc08e, 0x0005, 0x008c, - 0x0010, 0xe109, 0x0010, 0xc08d, 0x0015, 0x0090, 0x0001, 0x1b55, - 0x0005, 0x0091, 0x0010, 0xffff, 0x0000, 0xb292, 0x0000, 0xb393, - 0x0015, 0x009a, 0x0010, 0x0056, 0x0005, 0x009b, 0x0010, 0x95f5, - 0x0012, 0xd042, 0x0003, 0x1886, 0x0005, 0x00b0, 0x0010, 0x8080, - 0x0011, 0x1388, 0x0010, 0x0011, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0000, 0xb00a, 0x000b, 0x8881, 0x0015, 0x00b8, 0x0010, 0x000c, - 0x0014, 0x0925, 0x0003, 0x0888, 0x0005, 0x0075, 0x0010, 0x8092, - 0x0015, 0x00b1, 0x0010, 0x07d0, 0x0005, 0x00b0, 0x0010, 0x0009, - 0x0001, 0xbd88, 0x0000, 0x000b, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0000, 0xb012, 0x001b, 0x8891, 0x0003, 0x0703, 0x0015, 0x00d1, - 0x0000, 0x0400, 0x0001, 0x1288, 0x0010, 0x0003, 0x0000, 0xff31, - 0x0015, 0x0033, 0x0000, 0xb009, 0x000b, 0x889a, 0x0001, 0x1288, - 0x0010, 0x0003, 0x0000, 0xff31, 0x0015, 0x0033, 0x0010, 0xc00a, - 0x000b, 0x88a0, 0x0010, 0xb0fe, 0x0003, 0x68a5, 0x0000, 0xb012, - 0x0003, 0x0703, 0x0010, 0xc012, 0x0010, 0xc011, 0x0003, 0x0703, - 0x0000, 0xba30, 0x0005, 0x0031, 0x0010, 0x0021, 0x0015, 0x0033, - 0x0010, 0xb019, 0x001b, 0x88ad, 0x0002, 0xb200, 0x0011, 0xffc8, - 0x0010, 0x00ff, 0x0010, 0xffb2, 0x0010, 0xb2b7, 0x0005, 0x0031, - 0x0000, 0x0023, 0x0015, 0x0033, 0x0010, 0xb20a, 0x000b, 0x88b7, - 0x0017, 0x4000, 0x0000, 0xba30, 0x0005, 0x0031, 0x0000, 0x0023, - 0x0015, 0x0033, 0x0010, 0xb409, 0x000b, 0x88be, 0x0002, 0xb400, - 0x0011, 0xffc8, 0x0010, 0x00ff, 0x0010, 0xffb4, 0x0010, 0xb4b7, - 0x0005, 0x0031, 0x0000, 0x0023, 0x0015, 0x0033, 0x0010, 0xb40a, - 0x001b, 0x88c8, 0x0017, 0x4000, 0x0000, 0xba30, 0x0001, 0xc7c8, - 0x0000, 0x0020, 0x001b, 0x18d6, 0x0005, 0x0031, 0x0010, 0x0028, - 0x0015, 0x0033, 0x0010, 0xb209, 0x000b, 0x88d2, 0x0011, 0xb2c8, - 0x0000, 0xff80, 0x0003, 0x18d9, 0x0010, 0xc4b0, 0x0010, 0xc5b1, - 0x0003, 0x08db, 0x0010, 0xc6b1, 0x0000, 0xc0b0, 0x0005, 0x0031, - 0x0000, 0x0004, 0x0015, 0x0033, 0x0010, 0xb211, 0x001b, 0x88df, - 0x0017, 0x4000, 0x0015, 0x00b8, 0x0010, 0x0009, 0x0015, 0x003a, - 0x0010, 0x0707, 0x0014, 0x0925, 0x0013, 0x002d, 0x0015, 0x00b8, - 0x0010, 0x0009, 0x0015, 0x003a, 0x0010, 0x0707, 0x0003, 0x0925, - 0x0004, 0x011c, 0x0015, 0x0030, 0x0000, 0x0400, 0x0011, 0x0d88, - 0x0000, 0x0004, 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xba09, - 0x001b, 0x88f4, 0x0004, 0x08a8, 0x0015, 0x0030, 0x0000, 0x0400, - 0x0011, 0x0d88, 0x0000, 0x0010, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0010, 0xb20a, 0x001b, 0x88fd, 0x0015, 0x0030, 0x0000, 0x0400, - 0x0011, 0x0d88, 0x0010, 0x0011, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0010, 0x0309, 0x001b, 0x8905, 0x0002, 0x0327, 0x0010, 0xffb2, - 0x0011, 0x0d88, 0x0010, 0x0011, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0010, 0xb20a, 0x000b, 0x890d, 0x0015, 0x00b8, 0x0010, 0x0006, - 0x0003, 0x0925, 0x0014, 0x012e, 0x0004, 0x08a8, 0x0015, 0x0030, - 0x0000, 0x0400, 0x0011, 0x1388, 0x0000, 0x0010, 0x0000, 0xff31, - 0x0015, 0x0033, 0x0010, 0xb20a, 0x000b, 0x891a, 0x0012, 0x1027, - 0x0010, 0xffb2, 0x0011, 0x1388, 0x0010, 0x0011, 0x0000, 0xff31, - 0x0015, 0x0033, 0x0010, 0xb20a, 0x001b, 0x8922, 0x0015, 0x00b8, - 0x0000, 0x0007, 0x0013, 0x4925, 0x0000, 0xb838, 0x0017, 0x4000, - 0x9a8c, 0xaf3d -}; -unsigned short xseqipx_code_length01 = 0x1252; diff --git a/drivers/scsi/qla2xxx/ql2400.c b/drivers/scsi/qla2xxx/ql2400.c deleted file mode 100644 index 77914fcfa2b..00000000000 --- a/drivers/scsi/qla2xxx/ql2400.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - * QLogic Fibre Channel HBA Driver - * Copyright (c) 2003-2005 QLogic Corporation - * - * See LICENSE.qla2xxx for copyright and licensing details. - */ -#include -#include -#include - -#include "qla_def.h" - -static char qla_driver_name[] = "qla2400"; - -extern uint32_t fw2400_version_str[]; -extern uint32_t fw2400_addr01; -extern uint32_t fw2400_code01[]; -extern uint32_t fw2400_length01; -extern uint32_t fw2400_addr02; -extern uint32_t fw2400_code02[]; -extern uint32_t fw2400_length02; - -static struct qla_fw_info qla_fw_tbl[] = { - { - .addressing = FW_INFO_ADDR_EXTENDED, - .fwcode = (unsigned short *)&fw2400_code01[0], - .fwlen = (unsigned short *)&fw2400_length01, - .lfwstart = (unsigned long *)&fw2400_addr01, - }, - { - .addressing = FW_INFO_ADDR_EXTENDED, - .fwcode = (unsigned short *)&fw2400_code02[0], - .fwlen = (unsigned short *)&fw2400_length02, - .lfwstart = (unsigned long *)&fw2400_addr02, - }, - { FW_INFO_ADDR_NOMORE, }, -}; - -static struct qla_board_info qla_board_tbl[] = { - { - .drv_name = qla_driver_name, - .isp_name = "ISP2422", - .fw_info = qla_fw_tbl, - .fw_fname = "ql2400_fw.bin", - }, - { - .drv_name = qla_driver_name, - .isp_name = "ISP2432", - .fw_info = qla_fw_tbl, - .fw_fname = "ql2400_fw.bin", - }, - { - .drv_name = qla_driver_name, - .isp_name = "ISP5422", - .fw_info = qla_fw_tbl, - .fw_fname = "ql2400_fw.bin", - }, - { - .drv_name = qla_driver_name, - .isp_name = "ISP5432", - .fw_info = qla_fw_tbl, - .fw_fname = "ql2400_fw.bin", - }, -}; - -static struct pci_device_id qla24xx_pci_tbl[] = { - { - .vendor = PCI_VENDOR_ID_QLOGIC, - .device = PCI_DEVICE_ID_QLOGIC_ISP2422, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = (unsigned long)&qla_board_tbl[0], - }, - { - .vendor = PCI_VENDOR_ID_QLOGIC, - .device = PCI_DEVICE_ID_QLOGIC_ISP2432, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = (unsigned long)&qla_board_tbl[1], - }, - { - .vendor = PCI_VENDOR_ID_QLOGIC, - .device = PCI_DEVICE_ID_QLOGIC_ISP5422, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = (unsigned long)&qla_board_tbl[2], - }, - { - .vendor = PCI_VENDOR_ID_QLOGIC, - .device = PCI_DEVICE_ID_QLOGIC_ISP5432, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = (unsigned long)&qla_board_tbl[3], - }, - - {0, 0}, -}; -MODULE_DEVICE_TABLE(pci, qla24xx_pci_tbl); - -static int __devinit -qla24xx_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) -{ - return qla2x00_probe_one(pdev, - (struct qla_board_info *)id->driver_data); -} - -static void __devexit -qla24xx_remove_one(struct pci_dev *pdev) -{ - qla2x00_remove_one(pdev); -} - -static struct pci_driver qla24xx_pci_driver = { - .name = "qla2400", - .id_table = qla24xx_pci_tbl, - .probe = qla24xx_probe_one, - .remove = __devexit_p(qla24xx_remove_one), -}; - -static int __init -qla24xx_init(void) -{ - return pci_module_init(&qla24xx_pci_driver); -} - -static void __exit -qla24xx_exit(void) -{ - pci_unregister_driver(&qla24xx_pci_driver); -} - -module_init(qla24xx_init); -module_exit(qla24xx_exit); - -MODULE_AUTHOR("QLogic Corporation"); -MODULE_DESCRIPTION("QLogic ISP24xx FC-SCSI Host Bus Adapter driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(QLA2XXX_VERSION); diff --git a/drivers/scsi/qla2xxx/ql2400_fw.c b/drivers/scsi/qla2xxx/ql2400_fw.c deleted file mode 100644 index 282b2d33ebf..00000000000 --- a/drivers/scsi/qla2xxx/ql2400_fw.c +++ /dev/null @@ -1,12346 +0,0 @@ -/* - * QLogic Fibre Channel HBA Driver - * Copyright (c) 2003-2005 QLogic Corporation - * - * See LICENSE.qla2xxx for copyright and licensing details. - */ -#include - -/* - * Firmware Version 4.00.18 (14:53 Jan 30, 2006) - */ - -#ifdef UNIQUE_FW_NAME -uint32_t fw2400_version = 4*1024+0; -#else -uint32_t risc_code_version = 4*1024+0; -#endif - -#ifdef UNIQUE_FW_NAME -uint32_t fw2400_version_str[] = {4, 0,18}; -#else -uint32_t firmware_version[] = {4, 0,18}; -#endif - -#ifdef UNIQUE_FW_NAME -#define fw2400_VERSION_STRING "4.00.18" -#else -#define FW_VERSION_STRING "4.00.18" -#endif - -#ifdef UNIQUE_FW_NAME -uint32_t fw2400_addr01 = 0x00100000 ; -#else -uint32_t risc_code_addr01 = 0x00100000 ; -#endif - -#ifdef UNIQUE_FW_NAME -uint32_t fw2400_code01[] = { -#else -uint32_t risc_code01[] = { -#endif - 0x0401f17c, 0x0010d000, 0x00100000, 0x0000a971, - 0x00000004, 0x00000000, 0x00000012, 0x00000002, - 0x00000003, 0x00000000, 0x20434f50, 0x59524947, - 0x48542032, 0x30303520, 0x514c4f47, 0x49432043, - 0x4f52504f, 0x52415449, 0x4f4e2020, 0x20495350, - 0x32347878, 0x20466972, 0x6d776172, 0x65202020, - 0x56657273, 0x696f6e20, 0x342e302e, 0x31382020, - 0x20202024, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x42001800, 0x0010014f, 0x42002000, 0x0010b6fd, - 0x500c0800, 0x800c1800, 0x500c1000, 0x800c1800, - 0x54042000, 0x80102000, 0x80040800, 0x80081040, - 0x040207fc, 0x500c0800, 0x800409c0, 0x040207f6, - 0x44002000, 0x80102000, 0x40100000, 0x44040000, - 0x80000000, 0x44080000, 0x80000000, 0x440c0000, - 0x80000000, 0x44100000, 0x80000000, 0x44140000, - 0x80000000, 0x44180000, 0x80000000, 0x441c0000, - 0x80000000, 0x44200000, 0x80000000, 0x44240000, - 0x80000000, 0x44280000, 0x80000000, 0x442c0000, - 0x80000000, 0x44300000, 0x80000000, 0x44340000, - 0x80000000, 0x44380000, 0x80000000, 0x443c0000, - 0x80000000, 0x44400000, 0x80000000, 0x44440000, - 0x80000000, 0x44480000, 0x80000000, 0x444c0000, - 0x80000000, 0x44500000, 0x80000000, 0x44540000, - 0x80000000, 0x44580000, 0x80000000, 0x445c0000, - 0x80000000, 0x44600000, 0x80000000, 0x44640000, - 0x80000000, 0x44680000, 0x80000000, 0x446c0000, - 0x80000000, 0x44700000, 0x80000000, 0x44740000, - 0x80000000, 0x44780000, 0x80000000, 0x447c0000, - 0x80000000, 0x44800000, 0x80000000, 0x44840000, - 0x80000000, 0x44880000, 0x80000000, 0x448c0000, - 0x80000000, 0x44900000, 0x80000000, 0x44940000, - 0x80000000, 0x44980000, 0x80000000, 0x449c0000, - 0x80000000, 0x44a00000, 0x80000000, 0x44a40000, - 0x80000000, 0x44a80000, 0x80000000, 0x44ac0000, - 0x80000000, 0x44b00000, 0x80000000, 0x44b40000, - 0x80000000, 0x44b80000, 0x80000000, 0x44bc0000, - 0x80000000, 0x44c00000, 0x80000000, 0x44c40000, - 0x80000000, 0x44c80000, 0x80000000, 0x44cc0000, - 0x80000000, 0x44d00000, 0x80000000, 0x44d80000, - 0x80000000, 0x44d40000, 0x80000000, 0x44dc0000, - 0x80000000, 0x44e00000, 0x80000000, 0x44e40000, - 0x80000000, 0x44e80000, 0x80000000, 0x44ec0000, - 0x80000000, 0x44f00000, 0x80000000, 0x44f40000, - 0x80000000, 0x44f80000, 0x80000000, 0x44fc0000, - 0x80000000, 0x45000000, 0x80000000, 0x45040000, - 0x80000000, 0x45080000, 0x80000000, 0x450c0000, - 0x80000000, 0x45100000, 0x80000000, 0x45140000, - 0x80000000, 0x45180000, 0x80000000, 0x451c0000, - 0x80000000, 0x45200000, 0x80000000, 0x45240000, - 0x80000000, 0x45280000, 0x80000000, 0x452c0000, - 0x80000000, 0x45300000, 0x80000000, 0x45340000, - 0x80000000, 0x45380000, 0x80000000, 0x453c0000, - 0x80000000, 0x45400000, 0x80000000, 0x45440000, - 0x80000000, 0x45480000, 0x80000000, 0x454c0000, - 0x80000000, 0x45500000, 0x80000000, 0x45540000, - 0x80000000, 0x45580000, 0x80000000, 0x455c0000, - 0x80000000, 0x45600000, 0x80000000, 0x45640000, - 0x80000000, 0x45680000, 0x80000000, 0x456c0000, - 0x80000000, 0x45700000, 0x80000000, 0x45740000, - 0x80000000, 0x45780000, 0x80000000, 0x457c0000, - 0x80000000, 0x45800000, 0x80000000, 0x45840000, - 0x80000000, 0x45880000, 0x80000000, 0x458c0000, - 0x80000000, 0x45900000, 0x80000000, 0x45940000, - 0x80000000, 0x45980000, 0x80000000, 0x459c0000, - 0x80000000, 0x45a00000, 0x80000000, 0x45a40000, - 0x80000000, 0x45a80000, 0x80000000, 0x45ac0000, - 0x80000000, 0x45b00000, 0x80000000, 0x45b40000, - 0x80000000, 0x45b80000, 0x80000000, 0x45bc0000, - 0x80000000, 0x45c00000, 0x80000000, 0x45c40000, - 0x80000000, 0x45c80000, 0x80000000, 0x45cc0000, - 0x80000000, 0x45d00000, 0x80000000, 0x45d40000, - 0x80000000, 0x45d80000, 0x80000000, 0x45dc0000, - 0x80000000, 0x45e00000, 0x80000000, 0x45e40000, - 0x80000000, 0x45e80000, 0x80000000, 0x45ec0000, - 0x80000000, 0x45f00000, 0x80000000, 0x45f40000, - 0x80000000, 0x45f80000, 0x80000000, 0x45fc0000, - 0x4a03c020, 0x00004000, 0x4a03c011, 0x40000010, - 0x04006000, 0x4203e000, 0x40000000, 0x59e00017, - 0x8c000508, 0x04000003, 0x4a03c017, 0x00000000, - 0x4203e000, 0x30000001, 0x0401f000, 0x0000bf00, - 0x00000080, 0x0000bfe0, 0x00000020, 0x0000ff00, - 0x00000080, 0x0000ffd0, 0x00000030, 0x00007100, - 0x00000010, 0x00007200, 0x00000008, 0x00007209, - 0x00000007, 0x00007300, 0x00000008, 0x00007309, - 0x00000007, 0x00007400, 0x00000008, 0x00007409, - 0x00000007, 0x00007600, 0x000000b0, 0x00007700, - 0x00000040, 0x00003000, 0x00000070, 0x00004000, - 0x000000c0, 0x00006000, 0x00000050, 0x00006100, - 0x00000010, 0x00006130, 0x00000010, 0x00006150, - 0x00000010, 0x00006170, 0x00000010, 0x00006190, - 0x00000010, 0x000061b0, 0x00000010, 0x00000000, - 0x42000000, 0x00000100, 0x4202f000, 0x00000000, - 0x42000800, 0x00021f00, 0x45780800, 0x80040800, - 0x80000040, 0x040207fd, 0x4203f000, 0x00021fff, - 0x40000000, 0x4203e000, 0x90000100, 0x40000000, - 0x0201f800, 0x00100743, 0x42000000, 0x00001000, - 0x50000000, 0x82000480, 0x24320002, 0x04020015, - 0x42000800, 0x00000064, 0x80040840, 0x04000007, - 0x4a030000, 0x00000001, 0x40000000, 0x59800000, - 0x8c000500, 0x040007f9, 0x04000008, 0x42000800, - 0x00007a17, 0x50040000, 0x8c00050e, 0x04020003, - 0x8400054e, 0x44000800, 0x4a030000, 0x00000000, - 0x4a03c020, 0x00000004, 0x4203e000, 0x6000000f, - 0x59e00023, 0x8c000500, 0x04020039, 0x42000000, - 0x00100001, 0x50000800, 0x82040c00, 0x00000004, - 0x58042003, 0x42001000, 0xffffffff, 0x0201f800, - 0x0010073a, 0x0402004e, 0x58042003, 0x42001000, - 0xffffffff, 0x0201f800, 0x0010073a, 0x04020048, - 0x58042003, 0x42001000, 0x00ffffff, 0x0201f800, - 0x0010073a, 0x04020042, 0x58042003, 0x42001000, - 0x00ffffff, 0x0201f800, 0x0010073a, 0x0402003c, - 0x42000000, 0x00100001, 0x5000a000, 0x8250a400, - 0x00000004, 0x4200a800, 0x00020000, 0x5850b003, - 0x0201f800, 0x0010a93e, 0x8250a400, 0x00000005, - 0x4a0370e8, 0x00000003, 0x4200a800, 0x0000c000, - 0x5850b003, 0x0201f800, 0x0010a93e, 0x4a0378e8, - 0x00000003, 0x4200a800, 0x00008000, 0x5850b003, - 0x0201f800, 0x0010a93e, 0x0401f02b, 0x42000800, - 0x00020000, 0x58042003, 0x42001000, 0xffffffff, - 0x0201f800, 0x0010073a, 0x04020019, 0x4a0370e8, - 0x00000003, 0x42000800, 0x0000c000, 0x58042003, - 0x82102500, 0x00ffffff, 0x42001000, 0x00ffffff, - 0x0201f800, 0x0010073a, 0x0402000d, 0x4a0378e8, - 0x00000003, 0x42000800, 0x00008000, 0x58042003, - 0x82102500, 0x00ffffff, 0x42001000, 0x00ffffff, - 0x0201f800, 0x0010073a, 0x0400000b, 0x4a03c020, - 0x00004010, 0x4a03c011, 0x40100011, 0x04006000, - 0x4203e000, 0x40000000, 0x4203e000, 0x30000001, - 0x0401f000, 0x0201f800, 0x001007d7, 0x42001000, - 0x0010a971, 0x40080000, 0x80140480, 0x82001d00, - 0xffffff00, 0x04020003, 0x40001800, 0x0401f003, - 0x42001800, 0x000000ff, 0x480bc840, 0x480fc842, - 0x04011000, 0x400c0000, 0x80081400, 0x40140000, - 0x80080580, 0x040207f0, 0x4817500d, 0x45782800, - 0x59c40000, 0x82000500, 0xffff0000, 0x80000120, - 0x82000580, 0x00002422, 0x04020005, 0x59a8006f, - 0x84000540, 0x4803506f, 0x0401f00a, 0x59e00003, - 0x82000500, 0x00030000, 0x82000580, 0x00010000, - 0x04020004, 0x59a8006f, 0x84000542, 0x4803506f, - 0x42000800, 0x00000040, 0x59a8006f, 0x8c000502, - 0x0402000e, 0x42000800, 0x00001000, 0x82141480, - 0x0017ffff, 0x04021009, 0x80040902, 0x82141480, - 0x0013ffff, 0x04021005, 0x80040902, 0x82141480, - 0x0011ffff, 0x04001bc8, 0x4807500e, 0x42001000, - 0x00000024, 0x0201f800, 0x001063cf, 0x82040c00, - 0x0010cfc0, 0x4807500b, 0x4a03c810, 0x00100000, - 0x4a03c811, 0x0010a971, 0x4a03c829, 0x00000004, - 0x59e40001, 0x82000540, 0x0003001d, 0x4803c801, - 0x4a03c014, 0x001c001c, 0x42001000, 0x0000001c, - 0x0201f800, 0x00100728, 0x4202c000, 0x0010cfc0, - 0x59aab00b, 0x59aaa00b, 0x59aaa80b, 0x59aac80e, - 0x49675069, 0x59a8000b, 0x4803500c, 0x0201f800, - 0x001006a3, 0x0201f800, 0x0010768a, 0x0201f800, - 0x00100804, 0x0201f800, 0x0010084d, 0x0201f800, - 0x00101a60, 0x0201f800, 0x001013a4, 0x0201f800, - 0x001009b6, 0x0201f800, 0x001013a4, 0x0201f800, - 0x00100f9a, 0x0201f800, 0x0010640f, 0x0401fb54, - 0x0201f800, 0x00101fb5, 0x0201f800, 0x0010508b, - 0x0201f800, 0x00104b36, 0x0201f800, 0x00105ecd, - 0x0201f800, 0x00105c61, 0x0201f800, 0x0010143d, - 0x0201f800, 0x001012bf, 0x4203e000, 0xf0000001, - 0x4a035070, 0x00000014, 0x4a035071, 0x0000000b, - 0x4a035072, 0x00000001, 0x4a035073, 0x00000000, - 0x42000000, 0x00001000, 0x50000000, 0x82000480, - 0x24220001, 0x0400004a, 0x59e00002, 0x8c00051e, - 0x42000000, 0x7ffe00fe, 0x04000003, 0x42000000, - 0x7ffe01fe, 0x50000800, 0x48075058, 0x80040920, - 0x82040580, 0x0000013e, 0x0402000b, 0x59a8006f, - 0x84000548, 0x4803506f, 0x4a035070, 0x00000055, - 0x4a035071, 0x00000051, 0x4a035073, 0x0000000f, - 0x0401f033, 0x82040580, 0x0000013f, 0x0402000b, - 0x59a8006f, 0x8400054a, 0x4803506f, 0x4a035070, - 0x00000055, 0x4a035071, 0x00000051, 0x4a035073, - 0x0000000f, 0x0401f026, 0x59e00003, 0x82000500, - 0x00030000, 0x82000580, 0x00000000, 0x04020020, - 0x82040580, 0x00000147, 0x04000010, 0x82040580, - 0x00000145, 0x0402001a, 0x59a8006f, 0x84000546, - 0x4803506f, 0x4a035070, 0x00000033, 0x4a035071, - 0x00000030, 0x4a035072, 0x00000020, 0x4a035073, - 0x00000001, 0x0401f00c, 0x59a8006f, 0x84000544, - 0x4803506f, 0x4a035070, 0x00000033, 0x4a035071, - 0x00000030, 0x4a035072, 0x00000020, 0x4a035073, - 0x00000001, 0x4a0378e4, 0x000c0000, 0x59a8006f, - 0x8c000502, 0x04000004, 0x82000500, 0x00000030, - 0x04000b25, 0x4a03c018, 0x0000000f, 0x4203e000, - 0x20000511, 0x4203e000, 0x50010000, 0x4a03c020, - 0x00000000, 0x04027013, 0x59e00020, 0x82000580, - 0x00000002, 0x0402000f, 0x4a03c020, 0x00004000, - 0x4a03c011, 0x40000010, 0x04006000, 0x4203e000, - 0x40000000, 0x59e00017, 0x8c000508, 0x04000003, - 0x4a03c017, 0x00000000, 0x4203e000, 0x30000001, - 0x4202d800, 0x00000000, 0x4203e000, 0xb0600000, - 0x59a80873, 0x4007f800, 0x0201f000, 0x00020004, - 0x4df00000, 0x4203e000, 0x50000000, 0x416c0000, - 0x82000c80, 0x00000008, 0x04021afb, 0x0c01f804, - 0x5c03e000, 0x0201f000, 0x00020008, 0x00100328, - 0x0010033b, 0x00100411, 0x00100327, 0x0010048c, - 0x00100327, 0x00100327, 0x001005d0, 0x0401faee, - 0x42000800, 0x0010b2a0, 0x5804001d, 0x4803c857, - 0x8c000500, 0x0400000d, 0x84000500, 0x4800081d, - 0x4202d800, 0x00000004, 0x0401fbe8, 0x49f3c857, - 0x5c000800, 0x5c000000, 0x82000540, 0x00003e00, - 0x4c000000, 0x4c040000, 0x1c01f000, 0x0401fbd2, - 0x0201f800, 0x00104e0d, 0x04000010, 0x0201f800, - 0x00104e23, 0x04020035, 0x59940023, 0x82000580, - 0x0010401b, 0x04020004, 0x59940022, 0x800001c0, - 0x0402002e, 0x59c40006, 0x82000540, 0x000000c0, - 0x48038806, 0x0401f029, 0x0201f800, 0x00104d76, - 0x836c0580, 0x00000001, 0x040200be, 0x59a80017, - 0x82000580, 0x00000009, 0x040200ba, 0x497b5010, - 0x4a038893, 0x00000001, 0x42001000, 0x000000f0, - 0x0201f800, 0x001019aa, 0x0201f800, 0x00104e1b, - 0x59c41006, 0x04020006, 0x82081540, 0x000000f1, - 0x82081500, 0xbbffffff, 0x0401f003, 0x82081540, - 0x440000f1, 0x480b8806, 0x0201f800, 0x00105de2, - 0x0201f800, 0x001069b8, 0x42000000, 0x0010b638, - 0x0201f800, 0x0010a86e, 0x42001000, 0x00008030, - 0x497b5013, 0x0401f037, 0x0201f800, 0x00103951, - 0x59c400a4, 0x82000500, 0x0000000f, 0x82000480, - 0x00000007, 0x04021093, 0x0201f800, 0x00105de2, - 0x59c400a3, 0x82000500, 0xffefffff, 0x480388a3, - 0x59a8004b, 0x800001c0, 0x04020004, 0x0201f800, - 0x00103f53, 0x0401f087, 0x59a80015, 0x84000546, - 0x48035015, 0x0201f800, 0x00104e13, 0x59c41006, - 0x04020006, 0x82081540, 0x44000001, 0x82081500, - 0xffffff0f, 0x0401f003, 0x82081540, 0x440000f1, - 0x480b8806, 0x497b9005, 0x4a038802, 0x0000ffff, - 0x4a0378e4, 0x00003000, 0x4a0378e4, 0x000c0000, - 0x42000000, 0x0010b60a, 0x0201f800, 0x0010a86e, - 0x59a81010, 0x42000800, 0x00000003, 0x0201f800, - 0x001069af, 0x42001000, 0x00008010, 0x59a8180a, - 0x0201f800, 0x00103857, 0x0201f800, 0x00101886, - 0x59a80805, 0x82040d00, 0xffffffdf, 0x48075005, - 0x0201f800, 0x0010468b, 0x0201f800, 0x00104e0d, - 0x0400000a, 0x0201f800, 0x00103f58, 0x04000007, - 0x4a035013, 0x00000001, 0x497b5021, 0x0201f800, - 0x00103a9f, 0x0401f04f, 0x0201f800, 0x0010473b, - 0x04000005, 0x59c41002, 0x8408150c, 0x480b8802, - 0x0401f012, 0x0201f800, 0x00104e0d, 0x04020006, - 0x59a8001d, 0x80000540, 0x02000800, 0x001090d5, - 0x0401f00a, 0x0201f800, 0x001090d5, 0x59a80026, - 0x8c000506, 0x04020005, 0x59a8001d, 0x80000540, - 0x02020800, 0x00104075, 0x497b5028, 0x497b5027, - 0x497b5018, 0x0201f800, 0x00104e0d, 0x59a81026, - 0x0402000a, 0x0201f800, 0x00101694, 0x80001580, - 0x59a8002a, 0x82000500, 0xffff0000, 0x80040d40, - 0x4807502a, 0x0401f005, 0x59a8002a, 0x82000500, - 0xffff0000, 0x4803502a, 0x599c0017, 0x8c00050a, - 0x04000002, 0x84081544, 0x480b5026, 0x0201f800, - 0x00104e0d, 0x04000004, 0x0201f800, 0x00101694, - 0x48078880, 0x42001000, 0x00000005, 0x0201f800, - 0x00106e07, 0x497b5028, 0x497b501b, 0x4a03501c, - 0x0000ffff, 0x4a0378e4, 0x000000c0, 0x4202d800, - 0x00000002, 0x0201f800, 0x00104e0d, 0x04000007, - 0x59a80026, 0x82000500, 0x0000000c, 0x82000580, - 0x00000004, 0x04000003, 0x0201f800, 0x00101bf0, - 0x1c01f000, 0x59a8001c, 0x82000580, 0x0000ffff, - 0x04000004, 0x0201f800, 0x00101bf0, 0x0401f074, - 0x59a80026, 0x8c00050a, 0x04020003, 0x8c000506, - 0x0400001c, 0x8c000500, 0x0400001a, 0x4a038802, - 0x0000ffbf, 0x8c000502, 0x04000016, 0x599c0018, - 0x8c000516, 0x04020010, 0x59a80027, 0x82000580, - 0x0000ffff, 0x0400000c, 0x0201f800, 0x00101d45, - 0x59a80026, 0x8c000504, 0x0402005d, 0x42001000, - 0x00000003, 0x417a5800, 0x0201f800, 0x00101d6a, - 0x0401f057, 0x59a80028, 0x80000540, 0x04020054, - 0x59a80026, 0x8c000508, 0x04020005, 0x59a8001b, - 0x80000540, 0x0402004e, 0x0401f003, 0x8c000516, - 0x0400004b, 0x0201f800, 0x0010473b, 0x04020048, - 0x599c0018, 0x8c000516, 0x04020004, 0x0201f800, - 0x00104abe, 0x04020042, 0x599c0017, 0x8c00050a, - 0x0400000d, 0x4200b000, 0x000007f0, 0x417a8800, - 0x0201f800, 0x00020267, 0x04020004, 0x59340200, - 0x8c00051a, 0x04020036, 0x81468800, 0x8058b040, - 0x040207f8, 0x4a038802, 0x0000ffff, 0x42001800, - 0x0010b2e7, 0x0401fb98, 0x42001800, 0x0010b2f4, - 0x0401fb95, 0x59a80005, 0x84000502, 0x48035005, - 0x4a0378e4, 0x00000080, 0x4202d800, 0x00000003, - 0x4a03501c, 0x0000ffff, 0x0401fa8b, 0x80000580, - 0x0201f800, 0x001015fa, 0x599c0018, 0x8c000516, - 0x04000004, 0x0201f800, 0x00103929, 0x0401f009, - 0x42001800, 0x0000ffff, 0x42002000, 0x00000006, - 0x42003000, 0x00000000, 0x0201f800, 0x001038c7, - 0x0201f800, 0x00104e23, 0x0400000b, 0x59c40006, - 0x0201f800, 0x00104e0d, 0x04000004, 0x82000500, - 0xffffff0f, 0x0401f003, 0x82000500, 0xfbffffff, - 0x48038806, 0x0201f800, 0x00106c8a, 0x1c01f000, - 0x4c040000, 0x4c080000, 0x4c100000, 0x59a8003e, - 0x82000c80, 0x00000004, 0x04021983, 0x0c01f805, - 0x5c002000, 0x5c001000, 0x5c000800, 0x1c01f000, - 0x0010049c, 0x00100527, 0x00100553, 0x001005b4, - 0x42000000, 0x00000001, 0x0201f800, 0x001015fa, - 0x0201f800, 0x00105de2, 0x59c408a3, 0x82040d00, - 0xfffffff7, 0x480788a3, 0x0201f800, 0x00104e13, - 0x0400000e, 0x0201f800, 0x00104e23, 0x0400000b, - 0x0201f800, 0x00104e1b, 0x04020967, 0x59c400a3, - 0x84000532, 0x84000570, 0x480388a3, 0x4a038808, - 0x00000008, 0x0401f013, 0x59c400a3, 0x84000530, - 0x82000500, 0xbf7fffff, 0x480388a3, 0x42000800, - 0x000000f8, 0x0201f800, 0x00104030, 0x59c400a3, - 0x82000540, 0x00018000, 0x8400051c, 0x480388a3, - 0x82000500, 0xfffeffff, 0x480388a3, 0x497b8808, - 0x59c40006, 0x82000500, 0xfbffff0e, 0x48038806, - 0x497b2822, 0x497b2823, 0x42000800, 0x000001f4, - 0x42001000, 0x001005ce, 0x0201f800, 0x00105cbc, - 0x59c40805, 0x42001000, 0x00000001, 0x0201f800, - 0x001019aa, 0x0201f800, 0x001016ac, 0x0402000a, - 0x42000000, 0x00000001, 0x0201f800, 0x001018fa, - 0x42000000, 0x00000001, 0x0201f800, 0x00101892, - 0x0401f022, 0x0201f800, 0x001016b3, 0x04020008, - 0x41780000, 0x0201f800, 0x001018fa, 0x41780000, - 0x0201f800, 0x00101892, 0x0401f018, 0x0201f800, - 0x001016ba, 0x0402000a, 0x42000000, 0x00000002, - 0x0201f800, 0x001018fa, 0x42000000, 0x00000002, - 0x0201f800, 0x00101892, 0x0401f00c, 0x0201f800, - 0x001016c1, 0x04020918, 0x59a80049, 0x800001c0, - 0x04000006, 0x0201f800, 0x001016c7, 0x4a03503e, - 0x00000001, 0x0401f021, 0x0201f800, 0x00101994, - 0x4a03503e, 0x00000001, 0x0201f800, 0x00104e13, - 0x0400000c, 0x0201f800, 0x00104e23, 0x04000009, - 0x0201f800, 0x00104e1b, 0x04020903, 0x4a035033, - 0x00000001, 0x0201f800, 0x00104d76, 0x0401f00f, - 0x59c400a4, 0x82000500, 0x0000000f, 0x82000580, - 0x00000008, 0x04000003, 0x4a038805, 0x04000000, - 0x59c400a3, 0x82000540, 0x0001c000, 0x480388a3, - 0x84000520, 0x480388a3, 0x1c01f000, 0x0401f8a3, - 0x04020004, 0x4a03503e, 0x00000003, 0x0401f027, - 0x0201f800, 0x001016c1, 0x04020011, 0x59a80049, - 0x800001c0, 0x0400000e, 0x0201f800, 0x001016c7, - 0x59a80048, 0x8c00051e, 0x0400001c, 0x0201f800, - 0x00104e1b, 0x04020009, 0x4a035033, 0x00000001, - 0x0201f800, 0x00104d76, 0x0401f004, 0x0201f800, - 0x00101941, 0x04020011, 0x0201f800, 0x00101886, - 0x4a03503e, 0x00000002, 0x497b5049, 0x59c400a3, - 0x84000520, 0x480388a3, 0x497b2822, 0x497b2823, - 0x42000800, 0x0000002d, 0x42001000, 0x001005ce, - 0x0201f800, 0x00105cbc, 0x1c01f000, 0x0401f877, - 0x04020004, 0x4a03503e, 0x00000003, 0x0401f05b, - 0x4a038805, 0x000000f0, 0x0201f800, 0x00101941, - 0x04020050, 0x0201f800, 0x00104e1b, 0x04000044, - 0x59c400a4, 0x82000500, 0x0000000f, 0x82000580, - 0x00000008, 0x04000020, 0x59c40005, 0x8c000534, - 0x0402001d, 0x59940022, 0x82000580, 0x00000001, - 0x04020046, 0x0201f800, 0x00104e23, 0x04020043, - 0x4a038805, 0x000000f0, 0x0201f800, 0x00104e67, - 0x4a035032, 0x0000aaaa, 0x4a035033, 0x00000000, - 0x59c408a3, 0x82040d40, 0x00000008, 0x480788a3, - 0x4202d800, 0x00000001, 0x4a03503e, 0x00000000, - 0x4a038805, 0x00000001, 0x497b2822, 0x497b2823, - 0x0401f01f, 0x0201f800, 0x00104e23, 0x04020007, - 0x59a80032, 0x82000580, 0x0000aaaa, 0x04020003, - 0x4a035010, 0x00ffffff, 0x497b5032, 0x59c40006, - 0x82000540, 0x04000001, 0x48038806, 0x59a80805, - 0x8c040d06, 0x04020005, 0x59c408a3, 0x82040d40, - 0x00000008, 0x480788a3, 0x4202d800, 0x00000001, - 0x4a03503e, 0x00000000, 0x4a038805, 0x00000001, - 0x497b2822, 0x497b2823, 0x0401f010, 0x59c40005, - 0x82000500, 0x000000c0, 0x0400000c, 0x59c40006, - 0x82000540, 0x000000f1, 0x48038806, 0x0401f7ef, - 0x0201f800, 0x001016c1, 0x04020004, 0x59a80049, - 0x800001c0, 0x040207a4, 0x497b8885, 0x1c01f000, - 0x4803c856, 0x42000000, 0x00000001, 0x0201f800, - 0x001015fa, 0x4a03503e, 0x00000000, 0x0201f800, - 0x001016c1, 0x0402000b, 0x59a80052, 0x800001c0, - 0x04000004, 0x80000040, 0x48035052, 0x04020005, - 0x4a035052, 0x0000000a, 0x4a035049, 0x00000001, - 0x497b8885, 0x0401f0f6, 0x59940022, 0x59940823, - 0x80040540, 0x1c01f000, 0x497b2823, 0x1c01f000, - 0x4c080000, 0x42001000, 0x000000f0, 0x0201f800, - 0x001019aa, 0x5c001000, 0x1c01f000, 0x4a03505c, - 0x00000004, 0x4a03505d, 0x00000000, 0x4a03505e, - 0x00000012, 0x4a03505f, 0x00000002, 0x4a035010, - 0x00ffffff, 0x0201f800, 0x001090d5, 0x4a03502a, - 0x20200000, 0x4a03502b, 0x88000200, 0x4a03502c, - 0x00ff001f, 0x4a03502d, 0x000007d0, 0x4a03502e, - 0x80000000, 0x4a03502f, 0x00000200, 0x4a035030, - 0x00ff0000, 0x4a035031, 0x00010000, 0x4a03503a, - 0x514c4f47, 0x4a03503b, 0x49432020, 0x1c01f000, - 0x4d440000, 0x417a8800, 0x41780800, 0x0201f800, - 0x00020267, 0x04020005, 0x0201f800, 0x00104836, - 0x04020002, 0x80040800, 0x81468800, 0x83440580, - 0x000007f0, 0x040207f6, 0x5c028800, 0x1c01f000, - 0x4803c857, 0x5c000000, 0x4c000000, 0x4803c857, - 0x0401f809, 0x485fc857, 0x4203e000, 0x50000000, - 0x5c000000, 0x4d780000, 0x4200b800, 0x00008002, - 0x0401f006, 0x485fc857, 0x4203e000, 0x50000000, - 0x4200b800, 0x00008002, 0x04006000, 0x4c000000, - 0x4c040000, 0x59bc00ea, 0x82000500, 0x00000007, - 0x82000580, 0x00000001, 0x04020005, 0x42000800, - 0x00000000, 0x0201f800, 0x001069a3, 0x5c000800, - 0x4807c025, 0x80040920, 0x4807c026, 0x5c000000, - 0x4803c023, 0x80000120, 0x4803c024, 0x5c000000, - 0x4803c857, 0x4803c021, 0x80000120, 0x4803c022, - 0x41f80000, 0x4803c027, 0x80000120, 0x4803c028, - 0x42000000, 0x00001000, 0x50000000, 0x82000480, - 0x24320001, 0x4803c857, 0x04001053, 0x42000800, - 0x00000064, 0x80040840, 0x04000007, 0x4a030000, - 0x00000001, 0x40000000, 0x59800000, 0x8c000500, - 0x040007f9, 0x04000046, 0x42000800, 0x0010bfa2, - 0x46000800, 0xfaceface, 0x80040800, 0x4c080000, - 0x4c0c0000, 0x42001000, 0x00007a00, 0x58080013, - 0x44000800, 0x80040800, 0x58080019, 0x44000800, - 0x80040800, 0x5808001a, 0x44000800, 0x80040800, - 0x5808001b, 0x44000800, 0x80040800, 0x5808001c, - 0x44000800, 0x80040800, 0x5808001f, 0x44000800, - 0x80040800, 0x42001000, 0x00007a40, 0x42001800, - 0x0000000b, 0x50080000, 0x44000800, 0x80081000, - 0x80040800, 0x800c1840, 0x040207fb, 0x42001800, - 0x00000003, 0x42001000, 0x00007b00, 0x480c1003, - 0x58080005, 0x44000800, 0x80040800, 0x800c1840, - 0x040217fb, 0x42001000, 0x00007c00, 0x58080002, - 0x44000800, 0x80040800, 0x58080003, 0x44000800, - 0x80040800, 0x58080020, 0x44000800, 0x80040800, - 0x58080021, 0x44000800, 0x80040800, 0x58080022, - 0x44000800, 0x80040800, 0x58080023, 0x44000800, - 0x80040800, 0x5c001800, 0x5c001000, 0x4a030000, - 0x00000000, 0x485fc020, 0x905cb9c0, 0x825cbd40, - 0x00000012, 0x485fc011, 0x4203e000, 0x40000000, - 0x4202d800, 0x00000005, 0x59e00017, 0x8c000508, - 0x04000003, 0x4a03c017, 0x00000002, 0x4203e000, - 0x30000001, 0x0401f81f, 0x0401f7ff, 0x4a03c850, - 0x0010bfbe, 0x4a03c851, 0x0010cfbd, 0x4a03c853, - 0x00000800, 0x4a03c855, 0x0001eb5a, 0x59e40001, - 0x82000540, 0x00003f00, 0x4803c801, 0x4a03b104, - 0x70000002, 0x4a03a804, 0x70000002, 0x4a03b004, - 0x70000002, 0x42000000, 0x0010b6eb, 0x49780001, - 0x49780002, 0x1c01f000, 0x5c036000, 0x4db00000, - 0x49b3c857, 0x4803c857, 0x1c01f000, 0x1c01f000, - 0x59a8006b, 0x8c000530, 0x040207fe, 0x4c080000, - 0x42001000, 0x00000004, 0x0401f862, 0x5c001000, - 0x4201d000, 0x00028b0a, 0x0201f800, 0x00105dd2, - 0x4c080000, 0x42001000, 0x00000008, 0x0401f859, - 0x5c001000, 0x4201d000, 0x00028b0a, 0x0201f800, - 0x00105dd2, 0x4c080000, 0x42001000, 0x00000010, - 0x0401f850, 0x5c001000, 0x4201d000, 0x00028b0a, - 0x0201f800, 0x00105dd2, 0x0401f7e2, 0x8c00050c, - 0x59a8086b, 0x04020003, 0x84040d30, 0x0401f006, - 0x84040d70, 0x4807506b, 0x42001000, 0x00000000, - 0x0401f040, 0x4807506b, 0x836c0500, 0x00000007, - 0x0c01f001, 0x00100727, 0x0010070d, 0x0010070d, - 0x001006f5, 0x0010071a, 0x0010070d, 0x0010070d, - 0x0010071a, 0x59a8006f, 0x8c000502, 0x04020013, - 0x59c40801, 0x82040d00, 0x00018000, 0x82040580, - 0x00010000, 0x0400000a, 0x82040580, 0x00008000, - 0x04000004, 0x42001000, 0x42004000, 0x0401f006, - 0x42001000, 0x22002000, 0x0401f003, 0x42001000, - 0x12001000, 0x0401f025, 0x42001000, 0x00001004, - 0x0401f022, 0x59a8006f, 0x8c000502, 0x04020008, - 0x59a8006b, 0x8c000534, 0x04020004, 0x42001000, - 0x74057005, 0x0401f819, 0x1c01f000, 0x42001000, - 0x00002008, 0x0401f7fc, 0x59a8006b, 0x8c000534, - 0x0402000a, 0x59a8006f, 0x8c000502, 0x04000004, - 0x42001000, 0x24052005, 0x0401f00c, 0x42001000, - 0x74057005, 0x0401f009, 0x1c01f000, 0x1c01f000, - 0x82081500, 0x0000001c, 0x82081540, 0x001c0000, - 0x480bc013, 0x1c01f000, 0x59a8006b, 0x8c000530, - 0x04000002, 0x84081570, 0x480b506b, 0x8c000530, - 0x04020005, 0x82081500, 0x00007000, 0x80081114, - 0x0401fff0, 0x1c01f000, 0x41780000, 0x50041800, - 0x800c0400, 0x80040800, 0x80102040, 0x040207fc, - 0x80080500, 0x80000540, 0x1c01f000, 0x4202f000, - 0x00000000, 0x41780000, 0x41780800, 0x41781000, - 0x41781800, 0x41782000, 0x41782800, 0x41783000, - 0x41783800, 0x41784000, 0x41784800, 0x41785000, - 0x41785800, 0x41786000, 0x41786800, 0x41787000, - 0x41787800, 0x41788000, 0x41788800, 0x41789000, - 0x41789800, 0x4178a000, 0x4178a800, 0x4178b000, - 0x4178b800, 0x4178c000, 0x4178c800, 0x4178d000, - 0x4178d800, 0x4178e000, 0x4178e800, 0x4178f000, - 0x4178f800, 0x41790000, 0x41790800, 0x41791000, - 0x41791800, 0x41792000, 0x41792800, 0x41793000, - 0x41793800, 0x41794000, 0x41794800, 0x41795000, - 0x41795800, 0x41796000, 0x41796800, 0x41797000, - 0x41797800, 0x41798000, 0x41798800, 0x42019000, - 0x0010b333, 0x42019800, 0x0010b30a, 0x4179a000, - 0x4179a800, 0x4179b000, 0x4179b800, 0x4179c800, - 0x4179c000, 0x4179d000, 0x4179d800, 0x4179e000, - 0x4179e800, 0x4179f000, 0x4179f800, 0x417a0000, - 0x417a0800, 0x417a1000, 0x417a1800, 0x417a2000, - 0x42022800, 0x00006100, 0x417a3000, 0x417a3800, - 0x417a4000, 0x417a4800, 0x417a5000, 0x417a5800, - 0x417a6000, 0x417a6800, 0x417a7000, 0x417a7800, - 0x417a8000, 0x417a8800, 0x417a9000, 0x417a9800, - 0x417ae800, 0x417af800, 0x42030000, 0x00007c00, - 0x42031000, 0x0010b604, 0x42031800, 0x0000bf1d, - 0x42032000, 0x0000bf32, 0x42032800, 0x0010b5cc, - 0x42033000, 0x0010b274, 0x42034000, 0x0010b2a0, - 0x42033800, 0x0010b2bf, 0x42034800, 0x0010b342, - 0x42035000, 0x0010b200, 0x42035800, 0x0010aa00, - 0x42030800, 0x0010b301, 0x417b6000, 0x42036800, - 0x00006f00, 0x4203c800, 0x00003000, 0x42037000, - 0x0000ff00, 0x42037800, 0x0000bf00, 0x42038000, - 0x00007700, 0x42038800, 0x00004000, 0x42039000, - 0x00006000, 0x42039800, 0x0010bcda, 0x4203a000, - 0x00007600, 0x4203a800, 0x00007400, 0x4203b000, - 0x00007200, 0x4203b800, 0x00007100, 0x4203c000, - 0x00007000, 0x4203d000, 0x00000000, 0x4203e800, - 0x000200f9, 0x417bd800, 0x1c01f000, 0x42000800, - 0x00100000, 0x50040000, 0x4c000000, 0x42000000, - 0x0000aaaa, 0x44000800, 0x42001800, 0x00005555, - 0x41782000, 0x82102400, 0x00010000, 0x40100000, - 0x80042c00, 0x440c2800, 0x42003000, 0x0000000a, - 0x80183040, 0x040207ff, 0x50140000, 0x800c0580, - 0x04020004, 0x50040000, 0x800c0580, 0x040207f2, - 0x5c000000, 0x44000800, 0x80142840, 0x4817c861, - 0x1c01f000, 0x59a8081f, 0x800409c0, 0x04020009, - 0x49781c0c, 0x4a001a0c, 0x00000200, 0x4a001804, - 0x07000000, 0x59a80010, 0x9c0001c0, 0x48001805, - 0x0401fdf8, 0x9c0409c0, 0x48041806, 0x1c01f000, - 0x59a8080c, 0x4006d000, 0x4202b800, 0x00000001, - 0x59a8180d, 0x480fc857, 0x82041400, 0x00000014, - 0x82082400, 0x00000014, 0x40100000, 0x800c0480, - 0x04001006, 0x44080800, 0x40080800, 0x40101000, - 0x815eb800, 0x0401f7f7, 0x45780800, 0x495f5020, - 0x1c01f000, 0x835c0480, 0x00000020, 0x04001009, - 0x496bc857, 0x815eb840, 0x416a5800, 0x592ed000, - 0x497a5800, 0x497a5801, 0x812e59c0, 0x1c01f000, - 0x42000000, 0x0010b652, 0x0201f800, 0x0010a86e, - 0x417a5800, 0x0401f7f9, 0x815eb840, 0x04001008, - 0x416a5800, 0x492fc857, 0x592ed000, 0x497a5800, - 0x497a5801, 0x812e59c0, 0x1c01f000, 0x42000000, - 0x0010b652, 0x0201f800, 0x0010a86e, 0x417ab800, - 0x417a5800, 0x0401f7f8, 0x492fc857, 0x496a5800, - 0x412ed000, 0x815eb800, 0x59c80000, 0x82000540, - 0x00001200, 0x48039000, 0x1c01f000, 0x492fc857, - 0x812e59c0, 0x04000007, 0x592c0001, 0x497a5801, - 0x4c000000, 0x0401fff1, 0x5c025800, 0x0401f7f9, - 0x1c01f000, 0x4807c856, 0x42007000, 0x0010b5f6, - 0x4a007001, 0x00000000, 0x59e00003, 0x82000540, - 0x00008080, 0x4803c003, 0x4a03b805, 0x90000001, - 0x59dc0006, 0x4a03b805, 0x70000000, 0x59dc0006, - 0x4a03b805, 0x30000000, 0x59dc0006, 0x4a03b805, - 0x80000000, 0x4200b000, 0x00000020, 0x497bb807, - 0x8058b040, 0x040207fe, 0x4a03b805, 0x30000000, - 0x59dc0006, 0x4a03b805, 0x60000001, 0x59dc0006, - 0x4a03b805, 0x70000001, 0x59dc0006, 0x4a03b805, - 0x30000002, 0x4200b000, 0x00000020, 0x497bb807, - 0x8058b040, 0x040207fe, 0x4a03b805, 0x30000000, - 0x59dc0006, 0x4a03b805, 0x60000001, 0x0401ff9e, - 0x04000d99, 0x42001000, 0x0010b5f4, 0x452c1000, - 0x4a025801, 0x00000001, 0x4a025802, 0x00000100, - 0x4a025809, 0x00106eac, 0x497a580a, 0x497a580b, - 0x497a580c, 0x0401ff90, 0x04000d8b, 0x42001000, - 0x0010b5f5, 0x452c1000, 0x4a025801, 0x00000000, - 0x4a025802, 0x00000100, 0x4a025809, 0x0010120c, - 0x497a5803, 0x497a5807, 0x497a5808, 0x497a580a, - 0x59a8006f, 0x8c000500, 0x04000006, 0x4a03b805, - 0xe0000001, 0x59dc0006, 0x8c000522, 0x040007fc, - 0x1c01f000, 0x4df00000, 0x4203e000, 0x50000000, - 0x4c380000, 0x40087000, 0x4a007002, 0x00000000, - 0x42007000, 0x0010b5f6, 0x82080400, 0x00000000, - 0x45780000, 0x58380005, 0x48087005, 0x80000540, - 0x04000006, 0x480bc857, 0x82000400, 0x00000000, - 0x44080000, 0x0401f003, 0x480bc857, 0x48087006, - 0x58380001, 0x80000540, 0x0400080c, 0x5c007000, - 0x5c03e000, 0x1c01f000, 0x4c380000, 0x42007000, - 0x0010b5f6, 0x58380001, 0x80000540, 0x04000803, - 0x5c007000, 0x1c01f000, 0x42007000, 0x0010b5f6, - 0x58380001, 0x82000580, 0x00000000, 0x04020012, - 0x58380000, 0x0c01f001, 0x001008d7, 0x001008d6, - 0x001008d6, 0x001008d6, 0x001008d6, 0x001008d6, - 0x001008d6, 0x001008d6, 0x0401fd3f, 0x58380808, - 0x800409c0, 0x04020027, 0x58380006, 0x80000540, - 0x04020002, 0x1c01f000, 0x4803c857, 0x48007002, - 0x40006800, 0x58340000, 0x80000540, 0x04020002, - 0x48007005, 0x48007006, 0x4a03b805, 0x20000000, - 0x59dc0006, 0x4a03b805, 0x30000000, 0x58340007, - 0x4803b800, 0x4803c857, 0x58340008, 0x4803b801, - 0x4803c857, 0x58340004, 0x48007003, 0x58340003, - 0x48007004, 0x4803b803, 0x4803c857, 0x58340001, - 0x8c000500, 0x04000004, 0x4a007001, 0x00000001, - 0x0401f028, 0x4a007001, 0x00000002, 0x0401f03e, - 0x0201f800, 0x001091b3, 0x0201f800, 0x0010a4b8, - 0x04000017, 0x4a03b805, 0x20000000, 0x59dc0006, - 0x4a03b805, 0x30000000, 0x4807b800, 0x480bb801, - 0x4a007003, 0x00000010, 0x480c7009, 0x42001000, - 0x001008be, 0x0201f800, 0x00105cd3, 0x58380008, - 0x82000400, 0x00000004, 0x48007004, 0x4803b803, - 0x4a007001, 0x00000007, 0x0401f023, 0x0201f800, - 0x001091cb, 0x42000800, 0x00000001, 0x42001000, - 0x001008be, 0x0201f800, 0x00105caf, 0x0401f7b7, - 0x4c040000, 0x4c080000, 0x58380803, 0x42001000, - 0x00003fff, 0x82040480, 0x00003fff, 0x04021003, - 0x40041000, 0x80000580, 0x48007003, 0x4803c857, - 0x800800c4, 0x4803b802, 0x4a03b805, 0x30000002, - 0x59dc0006, 0x4a03b805, 0x70000001, 0x59dc0006, - 0x4a03b805, 0x10000000, 0x5c001000, 0x5c000800, - 0x1c01f000, 0x483bc857, 0x4c040000, 0x4c080000, - 0x58380803, 0x42001000, 0x00003fff, 0x82040480, - 0x00003fff, 0x04021003, 0x40041000, 0x80000580, - 0x48007003, 0x800800c4, 0x4803b802, 0x4803c857, - 0x4a03b805, 0x10000002, 0x5c001000, 0x5c000800, - 0x1c01f000, 0x4c040000, 0x4c380000, 0x42007000, - 0x0010b5f6, 0x59dc0806, 0x4807c857, 0x4a03b805, - 0x20000000, 0x8c040d3e, 0x04000007, 0x8c040d08, - 0x04020cb9, 0x58380001, 0x82000500, 0x00000007, - 0x0c01f804, 0x5c007000, 0x5c000800, 0x1c01f000, - 0x001008c6, 0x0010096c, 0x0010097c, 0x00100615, - 0x00100615, 0x00100615, 0x00100615, 0x0010123a, - 0x4807c856, 0x82040d00, 0x43000f80, 0x04020009, - 0x58380003, 0x80000540, 0x0400001c, 0x59dc0000, - 0x4803b800, 0x59dc0001, 0x4803b801, 0x0401f7ad, - 0x58380802, 0x4a000802, 0x00000200, 0x0401f01d, - 0x4807c856, 0x82040d00, 0x43000f80, 0x04020009, - 0x58380003, 0x80000540, 0x0400000c, 0x59dc0000, - 0x4803b800, 0x59dc0001, 0x4803b801, 0x0401f7b6, - 0x58380002, 0x82000400, 0x00000002, 0x46000000, - 0x00000200, 0x0401f00b, 0x4c340000, 0x58386802, - 0x59dc0000, 0x4803c857, 0x48006807, 0x59dc0001, - 0x48006808, 0x4a006802, 0x00000100, 0x5c006800, - 0x4a007001, 0x00000000, 0x4c300000, 0x58386002, - 0x4833c857, 0x0401f80c, 0x04000009, 0x58300009, - 0x82000c80, 0x0010a971, 0x04021c73, 0x82000c80, - 0x00020000, 0x04001c70, 0x0801f800, 0x5c006000, - 0x0401f71e, 0x803061c0, 0x04000009, 0x59a8000c, - 0x80300480, 0x04001007, 0x59a8000d, 0x80300480, - 0x04021004, 0x82000540, 0x00000001, 0x1c01f000, - 0x80000580, 0x1c01f000, 0x4803c856, 0x4dc00000, - 0x42007000, 0x0010b601, 0x4a007400, 0x00000000, - 0x49787001, 0x42038000, 0x00007720, 0x4a038006, - 0x60000001, 0x4a038009, 0xf4f60000, 0x42038000, - 0x00007700, 0x4a038006, 0x60000001, 0x4a038009, - 0xf4f60000, 0x4a03c822, 0x00000010, 0x4a0370e8, - 0x00000000, 0x0401f809, 0x4a0370e9, 0x00003a0f, - 0x4a0370e8, 0x00000000, 0x4a0370e8, 0x00000001, - 0x5c038000, 0x1c01f000, 0x4c5c0000, 0x4178b800, - 0x0401f80a, 0x5c00b800, 0x1c01f000, 0x4803c856, - 0x4c5c0000, 0x825cbd40, 0x00000001, 0x0401f803, - 0x5c00b800, 0x1c01f000, 0x4803c856, 0x4dc00000, - 0x4c500000, 0x4c580000, 0x4c540000, 0x4a0370e8, - 0x00000000, 0x805cb9c0, 0x04000009, 0x4a038807, - 0x00000004, 0x59b800ea, 0x8c000510, 0x04000004, - 0x59b800e0, 0x0401f87b, 0x0401f7fb, 0x42038000, - 0x00007720, 0x0201f800, 0x00100f0f, 0x59c00007, - 0x4a038006, 0x20000000, 0x59c00007, 0x4a038006, - 0x8000000a, 0x59c00007, 0x4a038006, 0x8000000b, - 0x59c00007, 0x4a038006, 0x40000001, 0x83c00580, - 0x00007700, 0x04000004, 0x42038000, 0x00007700, - 0x0401f7ed, 0x42038000, 0x00007720, 0x42000800, - 0x00000800, 0x59c00007, 0x8c00051e, 0x04000006, - 0x4a038006, 0x90000001, 0x80040840, 0x040207fa, - 0x0401fc01, 0x83c00580, 0x00007700, 0x04000004, - 0x42038000, 0x00007700, 0x0401f7f1, 0x805cb9c0, - 0x0402001d, 0x4200b000, 0x00000020, 0x83b8ac00, - 0x00000020, 0x0201f800, 0x0010a947, 0x4a0370fb, - 0x00000001, 0x4a037020, 0x0010110d, 0x59a80039, - 0x82000500, 0x0000ffff, 0x48037021, 0x4a037035, - 0x0010bbda, 0x4a037030, 0x0010b210, 0x4a037031, - 0x0010aa00, 0x4a037032, 0x0010b315, 0x4a037036, - 0x0010b320, 0x59840002, 0x48037034, 0x4a037038, - 0x00101104, 0x4a0370fb, 0x00000001, 0x4178a000, - 0x4200b000, 0x00000020, 0x83b8ac00, 0x00000000, - 0x0201f800, 0x0010a947, 0x4200b000, 0x00000040, - 0x83b8ac00, 0x00000040, 0x0201f800, 0x0010a947, - 0x805cb9c0, 0x04020004, 0x4a0370e4, 0xaaaaaaaa, - 0x0401f003, 0x4a0370e4, 0xa2aaaa82, 0x4a0370e5, - 0xaaaaaaaa, 0x4a0370e6, 0xaaaaaaaa, 0x4a0370fb, - 0x00000000, 0x4a0370e6, 0xaaaaaaaa, 0x42038000, - 0x00007720, 0x4a038006, 0x90000000, 0x59c00007, - 0x8c00051e, 0x02020800, 0x00100615, 0x42038000, - 0x00007700, 0x4a038006, 0x90000000, 0x59c00007, - 0x8c00051e, 0x02020800, 0x00100615, 0x5c00a800, - 0x5c00b000, 0x5c00a000, 0x5c038000, 0x1c01f000, - 0x4d300000, 0x4d380000, 0x40026000, 0x82000500, - 0x7f000000, 0x82000580, 0x00000003, 0x0402000f, - 0x83326500, 0x00ffffff, 0x59300203, 0x82000580, - 0x00000004, 0x04020009, 0x59300c06, 0x82040580, - 0x00000009, 0x04020005, 0x42027000, 0x00000047, - 0x0201f800, 0x000208d8, 0x5c027000, 0x5c026000, - 0x1c01f000, 0x4d300000, 0x4d2c0000, 0x4d340000, - 0x4d400000, 0x4cfc0000, 0x4d380000, 0x4d3c0000, - 0x4d440000, 0x4d4c0000, 0x4d480000, 0x4c5c0000, - 0x4c600000, 0x4c640000, 0x4d040000, 0x4cc80000, - 0x4ccc0000, 0x4cf40000, 0x4cf80000, 0x4cfc0000, - 0x0201f800, 0x00020016, 0x5c01f800, 0x5c01f000, - 0x5c01e800, 0x5c019800, 0x5c019000, 0x5c020800, - 0x5c00c800, 0x5c00c000, 0x5c00b800, 0x5c029000, - 0x5c029800, 0x5c028800, 0x5c027800, 0x5c027000, - 0x5c01f800, 0x5c028000, 0x5c026800, 0x5c025800, - 0x5c026000, 0x1c01f000, 0x493bc857, 0x0201f000, - 0x00020045, 0x83300500, 0x1f000000, 0x04000008, - 0x81326580, 0x80000130, 0x82000c80, 0x00000014, - 0x02021800, 0x00100615, 0x0c01f013, 0x83300500, - 0x000000ff, 0x82000c80, 0x00000007, 0x02021800, - 0x00100615, 0x0c01f025, 0x1c01f000, 0x82000d00, - 0xc0000038, 0x02020800, 0x0010060d, 0x0201f800, - 0x00100615, 0x00000000, 0x00000048, 0x00000054, - 0x00000053, 0x00100ae4, 0x00100b08, 0x00100b03, - 0x00100b28, 0x00100aef, 0x00100afb, 0x00100ae4, - 0x00100b23, 0x00100b64, 0x00100ae4, 0x00100ae4, - 0x00100ae4, 0x00100ae4, 0x00100b67, 0x00100b6d, - 0x00100b7e, 0x00100b8f, 0x00100ae4, 0x00100b98, - 0x00100ba4, 0x00100ae4, 0x00100ae4, 0x00100ae4, - 0x0201f800, 0x00100615, 0x00100aed, 0x00100c3f, - 0x00100b35, 0x00100b59, 0x00100aed, 0x00100aed, - 0x00100aed, 0x0201f800, 0x00100615, 0x4803c856, - 0x59300004, 0x8c00053e, 0x04020005, 0x42027000, - 0x00000055, 0x0201f000, 0x000208d8, 0x0201f800, - 0x00106cb4, 0x040007fa, 0x1c01f000, 0x4803c856, - 0x0401f8aa, 0x40002800, 0x41782000, 0x42027000, - 0x00000056, 0x0201f000, 0x000208d8, 0x4803c856, - 0x42027000, 0x00000057, 0x0201f000, 0x000208d8, - 0x4803c856, 0x59300007, 0x8c00051a, 0x04020010, - 0x59325808, 0x812e59c0, 0x04000014, 0x592c0408, - 0x8c00051c, 0x04020003, 0x4a026011, 0xffffffff, - 0x59300004, 0x8c00053e, 0x04020009, 0x42027000, - 0x00000048, 0x0201f000, 0x000208d8, 0x59325808, - 0x4a025a06, 0x00000007, 0x0401f7f4, 0x0201f800, - 0x00106cb4, 0x040007f6, 0x1c01f000, 0x4803c856, - 0x83300500, 0x00ffffff, 0x0201f000, 0x0010620f, - 0x1c01f000, 0x4c040000, 0x59b808ea, 0x82040d00, - 0x00000007, 0x82040580, 0x00000003, 0x04000004, - 0x42000000, 0x60000000, 0x0401f8ac, 0x5c000800, - 0x1c01f000, 0x0401f8fa, 0x0400001b, 0x59325808, - 0x812e59c0, 0x04000018, 0x592c0204, 0x82000500, - 0x000000ff, 0x82000d80, 0x00000029, 0x04020012, - 0x59300203, 0x82000580, 0x00000003, 0x0400000b, - 0x59300807, 0x84040d26, 0x48066007, 0x0201f800, - 0x00020087, 0x4a03900d, 0x00000040, 0x4a0370e5, - 0x00000008, 0x1c01f000, 0x0201f800, 0x00106cb4, - 0x040007f4, 0x59880053, 0x80000000, 0x48031053, - 0x4a03900d, 0x00000040, 0x42000000, 0xc0000000, - 0x0401f05a, 0x42007800, 0x0010bbe1, 0x42002000, - 0x00003000, 0x42003000, 0x00000105, 0x0201f800, - 0x00105b3d, 0x4a0370e4, 0x02000000, 0x1c01f000, - 0x4933c857, 0x0201f000, 0x000208b4, 0x41300800, - 0x800409c0, 0x02020800, 0x00100615, 0x0201f800, - 0x0010060d, 0x4933c857, 0x813261c0, 0x02000800, - 0x00100615, 0x0401f835, 0x40002800, 0x0201f800, - 0x0010a7c3, 0x0401f8ae, 0x04000007, 0x59326809, - 0x59340200, 0x8c00050e, 0x59300414, 0x02020800, - 0x00109094, 0x1c01f000, 0x4933c857, 0x813261c0, - 0x02000800, 0x00100615, 0x0401f8a1, 0x0400000b, - 0x59325808, 0x0201f800, 0x00108df4, 0x04000007, - 0x592c0208, 0x8400054e, 0x48025a08, 0x417a7800, - 0x0201f800, 0x00108997, 0x1c01f000, 0x485fc857, - 0x5c000000, 0x4d780000, 0x4203e000, 0x50000000, - 0x4200b800, 0x00008005, 0x0201f000, 0x0010061a, - 0x4933c857, 0x83300480, 0x00000020, 0x02021800, - 0x00100615, 0x83300c00, 0x0010b6cb, 0x50040000, - 0x80000000, 0x04001002, 0x44000800, 0x1c01f000, - 0x4933c857, 0x0401f7f4, 0x4807c856, 0x59b800ea, - 0x8c000510, 0x040007fd, 0x59b800e0, 0x4803c857, - 0x1c01f000, 0x4803c856, 0x42000000, 0x10000000, - 0x41300800, 0x0401f02d, 0x82000500, 0xf0000000, - 0x82040d00, 0x0fffffff, 0x80040d40, 0x4807c857, - 0x59b800ea, 0x8c000516, 0x04020003, 0x480770e1, - 0x1c01f000, 0x8c000510, 0x040007fa, 0x4c040000, - 0x0401f809, 0x5c000800, 0x82100480, 0x00000008, - 0x040017f4, 0x4c040000, 0x0401febf, 0x5c000800, - 0x0401f7f0, 0x59b800e2, 0x59b820e2, 0x80100580, - 0x040207fd, 0x80102114, 0x0401f006, 0x59b800e2, - 0x59b820e2, 0x80100580, 0x040207fd, 0x0401f001, - 0x40101800, 0x800c190a, 0x82100500, 0x0000001f, - 0x820c1d00, 0x0000001f, 0x800c2480, 0x82102500, - 0x0000001f, 0x1c01f000, 0x82000500, 0xf0000000, - 0x82040d00, 0x0fffffff, 0x80040d40, 0x4807c857, - 0x42001000, 0x0010b602, 0x50080000, 0x80000540, - 0x04020005, 0x4a0370e5, 0x00000003, 0x4a0370e4, - 0x00000300, 0x80000000, 0x44001000, 0x42001000, - 0x00000400, 0x59b800ea, 0x8c000510, 0x0400000c, - 0x0401ffd5, 0x82100480, 0x00000008, 0x04001007, - 0x4c040000, 0x4c080000, 0x0401fe8b, 0x5c001000, - 0x5c000800, 0x0401f020, 0x59b800ea, 0x8c000516, - 0x0402001d, 0x4a0370e4, 0x00300000, 0x480770e1, - 0x42001000, 0x0000ff00, 0x80081040, 0x04000012, - 0x59b808e4, 0x8c040d28, 0x040207fc, 0x42001000, - 0x0010b602, 0x50080000, 0x80000040, 0x04020005, - 0x4a0370e5, 0x00000002, 0x4a0370e4, 0x00000200, - 0x02001800, 0x00100615, 0x44001000, 0x8c040d2c, - 0x1c01f000, 0x41f80000, 0x50000000, 0x0201f800, - 0x00100615, 0x80081040, 0x040207d3, 0x41f80000, - 0x50000000, 0x0201f800, 0x00100615, 0x4d380000, - 0x59300c06, 0x82040580, 0x00000009, 0x04020006, - 0x42027000, 0x00000047, 0x0201f800, 0x000208d8, - 0x80000580, 0x5c027000, 0x1c01f000, 0x4c500000, - 0x4a03900d, 0x00000001, 0x59c8a020, 0x4a03900d, - 0x00000002, 0x59c80820, 0x8c50a52e, 0x04000002, - 0x900409c0, 0x82040d00, 0x0000ffff, 0x0201f800, - 0x00105b0f, 0x5c00a000, 0x1c01f000, 0x0401fff0, - 0x04000045, 0x4933c857, 0x59300406, 0x82000580, - 0x00000000, 0x04000040, 0x59c82021, 0x4a03900d, - 0x00000001, 0x59c82821, 0x82142d00, 0x0000ffff, - 0x59325808, 0x812e59c0, 0x04000037, 0x59326809, - 0x0201f800, 0x00104728, 0x02020800, 0x0010907c, - 0x599c0019, 0x8c00050c, 0x04020018, 0x0201f800, - 0x00104728, 0x04020015, 0x59300811, 0x4807c857, - 0x592c0408, 0x8c00051c, 0x0402000e, 0x8400055c, - 0x48025c08, 0x592c0a04, 0x82040d00, 0x000000ff, - 0x82040580, 0x00000048, 0x04000004, 0x82040580, - 0x00000018, 0x04020003, 0x59300811, 0x48065803, - 0x4a026011, 0x7fffffff, 0x48166013, 0x0201f800, - 0x0010112d, 0x04020014, 0x0401fa07, 0x40280000, - 0x4802600d, 0x04000005, 0x4832600b, 0x50200000, - 0x4802600a, 0x4822600c, 0x59300414, 0x8c00051c, - 0x04020004, 0x599c0019, 0x8c00050c, 0x0402086e, - 0x4a03900d, 0x00000040, 0x4a0370e5, 0x00000008, - 0x1c01f000, 0x59880053, 0x80000000, 0x48031053, - 0x4a03900d, 0x00000040, 0x42000000, 0xc0000000, - 0x0401f726, 0x4cf80000, 0x58f40000, 0x8001f540, - 0x0401f820, 0x41781800, 0x0401f8e7, 0x04020014, - 0x44140800, 0x0401f82a, 0x04000011, 0x40043800, - 0x42001800, 0x00000001, 0x40142000, 0x0401f8de, - 0x0402000b, 0x801c3800, 0x501c0000, 0x44000800, - 0x0401f810, 0x801c0580, 0x04000004, 0x44103800, - 0x801c3840, 0x44143800, 0x0401f819, 0x5c01f000, - 0x1c01f000, 0x80f9f1c0, 0x04020003, 0x58f41202, - 0x0401f003, 0x42001000, 0x00000007, 0x1c01f000, - 0x80f9f1c0, 0x04020006, 0x58f40401, 0x82000480, - 0x00000002, 0x80f40400, 0x0401f005, 0x58f80401, - 0x82000480, 0x00000002, 0x80f80400, 0x50002800, - 0x80000000, 0x50002000, 0x1c01f000, 0x80f9f1c0, - 0x04020008, 0x58f40401, 0x82000480, 0x00000002, - 0x02001800, 0x00100615, 0x4801ec01, 0x0401f00b, - 0x58f80401, 0x82000480, 0x00000002, 0x02001800, - 0x00100615, 0x4801f401, 0x82000580, 0x00000002, - 0x04020002, 0x0401f809, 0x58f40202, 0x80000040, - 0x4801ea02, 0x02000800, 0x00100615, 0x82000580, - 0x00000001, 0x1c01f000, 0x4d2c0000, 0x40fa5800, - 0x0201f800, 0x0010083a, 0x4979e800, 0x4179f000, - 0x5c025800, 0x1c01f000, 0x80f5e9c0, 0x04000009, - 0x80f9f1c0, 0x04020ff5, 0x4d2c0000, 0x40f65800, - 0x0201f800, 0x0010083a, 0x4179e800, 0x5c025800, - 0x1c01f000, 0x4cf40000, 0x0201f800, 0x00104728, - 0x04020036, 0x59300807, 0x82040500, 0x00003100, - 0x04020032, 0x8c040d22, 0x04000032, 0x5930001f, - 0x8001ed40, 0x02000800, 0x00100615, 0x82000580, - 0xffffffff, 0x04000029, 0x58f40201, 0x82000580, - 0x0000dcb3, 0x02020800, 0x00100615, 0x58f40a02, - 0x82040500, 0x0000fffe, 0x04000003, 0x0401ff86, - 0x58f40a02, 0x82040480, 0x0000000f, 0x04021059, - 0x80040800, 0x4805ea02, 0x82040580, 0x00000008, - 0x0400005d, 0x82040480, 0x00000008, 0x0400100a, - 0x58f40000, 0x8001ed40, 0x02000800, 0x00100615, - 0x58f40201, 0x82000580, 0x0000ddb9, 0x02020800, - 0x00100615, 0x58f40401, 0x82000c00, 0x00000002, - 0x4805ec01, 0x80f40400, 0x59300812, 0x44040000, - 0x80000000, 0x45780000, 0x5c01e800, 0x1c01f000, - 0x42001000, 0x00000400, 0x59b800e4, 0x8c000524, - 0x04020023, 0x4a0370e4, 0x00030000, 0x40000000, - 0x59b800e4, 0x8c000524, 0x0402001b, 0x59300807, - 0x84040d62, 0x48066007, 0x4a0370e4, 0x00020000, - 0x4d2c0000, 0x0201f800, 0x00100819, 0x04000025, - 0x492e601f, 0x4a025a01, 0x0000dcb3, 0x59300008, - 0x80001d40, 0x02000800, 0x00100615, 0x580c080f, - 0x48065803, 0x59301811, 0x40040000, 0x800c0580, - 0x0402000d, 0x497a5a02, 0x4a025c01, 0x00000004, - 0x0401f011, 0x4a0370e4, 0x00020000, 0x40000000, - 0x40000000, 0x80081040, 0x02000800, 0x00100615, - 0x0401f7d6, 0x4a025a02, 0x00000001, 0x4a025c01, - 0x00000006, 0x497a5804, 0x400c0000, 0x80040480, - 0x48025805, 0x412de800, 0x5c025800, 0x0401f7a9, - 0x5c025800, 0x4a02601f, 0xffffffff, 0x0401f7c3, - 0x4d2c0000, 0x58f65800, 0x0201f800, 0x0010083a, - 0x40f65800, 0x0201f800, 0x0010083a, 0x5c025800, - 0x0401f7f5, 0x4d2c0000, 0x0201f800, 0x00100819, - 0x040007f8, 0x4a025a01, 0x0000ddb9, 0x4a025c01, - 0x00000002, 0x492de800, 0x412de800, 0x5c025800, - 0x0401f7a5, 0x0401ff30, 0x82f40400, 0x00000004, - 0x800c0400, 0x40000800, 0x50040000, 0x80100580, - 0x04000016, 0x82040c00, 0x00000002, 0x80081040, - 0x040207fa, 0x80f9f1c0, 0x04000011, 0x58f41202, - 0x82081480, 0x00000007, 0x82f80400, 0x00000002, - 0x800c0400, 0x40000800, 0x50040000, 0x80100580, - 0x04000006, 0x82040c00, 0x00000002, 0x80081040, - 0x040207fa, 0x0401f002, 0x1c01f000, 0x82000540, - 0x00000001, 0x0401f7fd, 0x4cf40000, 0x4cf80000, - 0x4001e800, 0x592c0a06, 0x800409c0, 0x04020021, - 0x82f40580, 0xffffffff, 0x0400001b, 0x58f40201, - 0x82000580, 0x0000dcb3, 0x02020800, 0x00100615, - 0x58f40000, 0x8001f540, 0x04000006, 0x58f80201, - 0x82000580, 0x0000ddb9, 0x02020800, 0x00100615, - 0x41783800, 0x58f44003, 0x0401f83d, 0x04020009, - 0x0401ff2e, 0x497a601f, 0x59300807, 0x84040d22, - 0x48066007, 0x5c01f000, 0x5c01e800, 0x1c01f000, - 0x0401ff26, 0x4a025a06, 0x00000011, 0x0401f7f6, - 0x82f40580, 0xffffffff, 0x04020f20, 0x0401f7f2, - 0x4cf40000, 0x4cf80000, 0x4001e800, 0x82040580, - 0x00000001, 0x04020020, 0x82f40580, 0xffffffff, - 0x0400001a, 0x58f40201, 0x82000580, 0x0000dcb3, - 0x02020800, 0x00100615, 0x58f40000, 0x8001f540, - 0x04000006, 0x58f80201, 0x82000580, 0x0000ddb9, - 0x02020800, 0x00100615, 0x41783800, 0x58f44003, - 0x0401f813, 0x04020008, 0x0401ff04, 0x42000800, - 0x00000001, 0x497a601f, 0x5c01f000, 0x5c01e800, - 0x1c01f000, 0x0401fefd, 0x42000800, 0x00000011, - 0x0401f7f9, 0x4c040000, 0x82f40580, 0xffffffff, - 0x04020ef6, 0x5c000800, 0x0401f7f3, 0x4803c856, - 0x401c2000, 0x41781800, 0x4c200000, 0x0401ff86, - 0x5c004000, 0x0402002c, 0x40202000, 0x42001800, - 0x00000001, 0x0401ff80, 0x04020027, 0x0401feae, - 0x40082800, 0x82f40400, 0x00000004, 0x40003000, - 0x50182000, 0x40100000, 0x801c0580, 0x04000005, - 0x42001800, 0x00000001, 0x0401ff73, 0x0402001a, - 0x82183400, 0x00000002, 0x80142840, 0x040207f5, - 0x80f9f1c0, 0x04000013, 0x58f42a02, 0x82142c80, - 0x00000007, 0x82f80400, 0x00000003, 0x40003000, - 0x50182000, 0x40100000, 0x801c0580, 0x04000005, - 0x42001800, 0x00000001, 0x0401ff5f, 0x04020006, - 0x82183400, 0x00000002, 0x80142840, 0x040207f5, - 0x1c01f000, 0x82000540, 0x00000001, 0x0401f7fd, - 0x0201f800, 0x00100615, 0x58380207, 0x8c000502, - 0x040007fc, 0x50200000, 0x80387c00, 0x583c2800, - 0x583c2001, 0x58380404, 0x80001540, 0x04020002, - 0x58381407, 0x58c83401, 0x58380c08, 0x59303807, - 0x497a6012, 0x497a6013, 0x0201f000, 0x000200bf, - 0x592c0408, 0x8c000502, 0x040007ea, 0x592c0409, - 0x80000540, 0x040007e7, 0x82000c80, 0x00000002, - 0x04001011, 0x58380001, 0x80007540, 0x02000800, - 0x00100615, 0x58380204, 0x82000500, 0x0000000f, - 0x82000400, 0x0010110d, 0x50004000, 0x40040000, - 0x800409c0, 0x04000005, 0x82040c80, 0x00000005, - 0x040217f1, 0x80204400, 0x50200000, 0x80387c00, - 0x583c2800, 0x583c2001, 0x583c1002, 0x592c0a07, - 0x592c4c08, 0x592c300d, 0x59303807, 0x497a6012, - 0x497a6013, 0x4816600e, 0x4812600f, 0x480a6010, - 0x481a6011, 0x80040840, 0x4806600d, 0x02000000, - 0x000200c7, 0x80204000, 0x50201800, 0x800c19c0, - 0x0402000c, 0x58380001, 0x80007540, 0x02000800, - 0x00100615, 0x58380204, 0x82000500, 0x0000000f, - 0x82000400, 0x0010110d, 0x50004000, 0x50201800, - 0x483a600b, 0x480e600a, 0x4822600c, 0x0201f000, - 0x000200c7, 0x4803c856, 0x592c0208, 0x8c00051e, - 0x04020017, 0x50200000, 0x80306c00, 0x40240000, - 0x0c01f001, 0x00100e91, 0x00100e91, 0x00100e9a, - 0x00100e91, 0x00100e91, 0x00100e91, 0x00100e91, - 0x00100e91, 0x00100e9a, 0x00100e91, 0x00100e9a, - 0x00100e91, 0x00100e91, 0x00100e9a, 0x00100e91, - 0x00100e91, 0x0201f800, 0x00100615, 0x8400051e, - 0x48025a08, 0x50200000, 0x80306c00, 0x58343801, - 0x481e600f, 0x0401f007, 0x58341802, 0x58342800, - 0x58343801, 0x480e6010, 0x4816600e, 0x481e600f, - 0x0401f24b, 0x4933c857, 0x5931f808, 0x59300a06, - 0x800409c0, 0x04000005, 0x80040906, 0x04020002, - 0x80040800, 0x4805fc06, 0x4a026206, 0x00000002, - 0x592c0409, 0x82000500, 0x00000008, 0x0400000b, - 0x0401f834, 0x59300203, 0x82000580, 0x00000004, - 0x04020005, 0x42027000, 0x00000048, 0x0201f800, - 0x000208d8, 0x1c01f000, 0x4cfc0000, 0x58fc0204, - 0x82000500, 0x000000ff, 0x82000580, 0x00000048, - 0x0402000c, 0x58fc000b, 0x800001c0, 0x04000009, - 0x58fc0407, 0x800001c0, 0x04000006, 0x58fc080b, - 0x8c040d16, 0x04000017, 0x58fc0007, 0x0401f00a, - 0x58fc0408, 0x8c000512, 0x04020014, 0x58fc0c09, - 0x8c040d16, 0x04020003, 0x5c01f800, 0x1c01f000, - 0x58fc000a, 0x59300811, 0x80040580, 0x04020009, - 0x59300007, 0x84000500, 0x48026007, 0x42027000, - 0x00000048, 0x5c01f800, 0x0201f000, 0x000208d8, - 0x5c01f800, 0x1c01f000, 0x58fdf809, 0x0401f7ec, - 0x5c000000, 0x4c000000, 0x4803c857, 0x4933c857, - 0x59b808ea, 0x82040d00, 0x00000007, 0x82040580, - 0x00000000, 0x0400001e, 0x82040580, 0x00000003, - 0x0400001b, 0x59300406, 0x4c000000, 0x4a026406, - 0x00000000, 0x42003000, 0x00000041, 0x42000000, - 0x50000000, 0x41300800, 0x4c180000, 0x0401fce3, - 0x5c003000, 0x0400000b, 0x42000000, 0x0000001e, - 0x80000040, 0x040207ff, 0x80183040, 0x040207f4, - 0x42000000, 0x40000000, 0x41300800, 0x0401fcd7, - 0x5c000000, 0x48026406, 0x1c01f000, 0x59300007, - 0x84000500, 0x48026007, 0x0401f7fc, 0x59c00007, - 0x4a038006, 0x30000000, 0x40000000, 0x59c00007, - 0x8c00050a, 0x040207fe, 0x1c01f000, 0x5c000000, - 0x4c000000, 0x4803c857, 0x4dc00000, 0x4a0370e8, - 0x00000000, 0x42038000, 0x00007720, 0x0401fff0, - 0x42038000, 0x00007700, 0x0401ffed, 0x0201f800, - 0x00104e0d, 0x04020013, 0x4a038891, 0x0000ffff, - 0x497b8880, 0x497b8892, 0x42001000, 0x00000190, - 0x40000000, 0x40000000, 0x80081040, 0x040207fd, - 0x42000000, 0x0010b6a5, 0x0201f800, 0x0010a86e, - 0x0401f80e, 0x5c038000, 0x0201f000, 0x00104f29, - 0x0401f82d, 0x42000000, 0x0010b6a6, 0x0201f800, - 0x0010a86e, 0x0401f805, 0x48178892, 0x480b8880, - 0x5c038000, 0x1c01f000, 0x496fc857, 0x836c0580, - 0x00000003, 0x0402000b, 0x4c080000, 0x4c0c0000, - 0x42001000, 0x00008048, 0x42001800, 0x0000ffff, - 0x0201f800, 0x00103857, 0x5c001800, 0x5c001000, - 0x42000800, 0x0000003c, 0x0201f800, 0x00101395, - 0x59a8006c, 0x80000540, 0x04000006, 0x59a8106d, - 0x800811c0, 0x04000003, 0x0201f800, 0x00101b0a, - 0x4a038891, 0x0000ffff, 0x4a03900d, 0x00000040, - 0x0201f800, 0x001009db, 0x4a0370e8, 0x00000001, - 0x1c01f000, 0x5c000000, 0x4c000000, 0x4803c857, - 0x59c41080, 0x497b8880, 0x59c42892, 0x497b8892, - 0x0201f800, 0x00104e0d, 0x04020002, 0x1c01f000, - 0x42002000, 0x00000260, 0x59c418a4, 0x820c1d00, - 0x0000000f, 0x820c0580, 0x00000000, 0x04000010, - 0x59c41805, 0x820c1d00, 0x00000001, 0x0402000e, - 0x59c418a4, 0x820c1d00, 0x0000000f, 0x820c0480, - 0x00000007, 0x04001004, 0x820c0480, 0x0000000c, - 0x04001003, 0x80102040, 0x040207ec, 0x497b8891, - 0x1c01f000, 0x4c100000, 0x42002000, 0x00000019, - 0x46000000, 0x00000001, 0x0201f800, 0x001019a4, - 0x50001800, 0x820c1d00, 0x00000001, 0x04000005, - 0x80102040, 0x040207f7, 0x5c002000, 0x0401f7f0, - 0x5c002000, 0x0401f7ec, 0x4803c856, 0x1c01f000, - 0x4d2c0000, 0x59325808, 0x592c0a04, 0x4807c857, - 0x82040d00, 0x000000ff, 0x82040500, 0x0000000f, - 0x0c01f001, 0x00100fb5, 0x00100fb5, 0x00100fb5, - 0x00100fcd, 0x00100fb5, 0x00100fb5, 0x00100fb5, - 0x00100fb5, 0x00100fb5, 0x00100fcd, 0x00100fb5, - 0x00100fb7, 0x00100fb5, 0x00100fb5, 0x00100fb5, - 0x00100fb5, 0x0201f800, 0x00100615, 0x82040580, - 0x0000003b, 0x02020800, 0x00100615, 0x592c020a, - 0x8c000500, 0x0400005f, 0x592c1a07, 0x82040500, - 0x0000000f, 0x82000400, 0x0010110d, 0x50001000, - 0x50080000, 0x59302013, 0x4802600a, 0x492e600b, - 0x480a600c, 0x480e600d, 0x48126012, 0x5c025800, - 0x1c01f000, 0x82040500, 0x0000000f, 0x82000400, - 0x0010110d, 0x50001000, 0x50080000, 0x592c1a07, - 0x4802600a, 0x492e600b, 0x480a600c, 0x480e600d, - 0x497a6012, 0x0401f7f2, 0x8c040d00, 0x04020041, - 0x82040d00, 0x00000080, 0x0400003e, 0x0201f000, - 0x000200d0, 0x59300013, 0x59301012, 0x80080580, - 0x0402000c, 0x42007800, 0x80000005, 0x592c1208, - 0x82080500, 0xffff7fff, 0x48025a08, 0x8c08151e, - 0x0402002d, 0x823c7d40, 0x00000020, 0x0401f02a, - 0x480bc857, 0x42000000, 0x0010b64f, 0x0201f800, - 0x0010a86e, 0x59300414, 0x4803c857, 0x8c000514, - 0x04020007, 0x599c1819, 0x8c0c1d12, 0x04020004, - 0x820c1d40, 0x00000001, 0x0401f01d, 0x59302013, - 0x0401f92d, 0x0402001a, 0x42007800, 0x80000005, - 0x5930500d, 0x592c0208, 0x4803c857, 0x8c00051e, - 0x04020005, 0x823c7d40, 0x00000020, 0x5930400c, - 0x0401f004, 0x8400051e, 0x48025a08, 0x0401f8dc, - 0x50201800, 0x480e600a, 0x4832600b, 0x4822600c, - 0x482a600d, 0x480fc857, 0x4833c857, 0x4823c857, - 0x482bc857, 0x80000580, 0x483e6004, 0x1c01f000, - 0x0201f800, 0x00100615, 0x4933c857, 0x4d2c0000, - 0x59900004, 0x81300580, 0x02020800, 0x00100615, - 0x0201f800, 0x00108df4, 0x02000800, 0x00100615, - 0x59325808, 0x4d3c0000, 0x4d400000, 0x59300004, - 0x4803c857, 0x4c000000, 0x0201f800, 0x00106b13, - 0x0201f800, 0x001068c1, 0x5c000000, 0x8c000516, - 0x04000010, 0x592c000f, 0x4803c857, 0x48025807, - 0x41780800, 0x42028000, 0x00000002, 0x0201f800, - 0x00104bee, 0x4a025c06, 0x0000ffff, 0x0201f800, - 0x00020381, 0x0201f800, 0x00107698, 0x0401f015, - 0x4a026203, 0x00000002, 0x592c0208, 0x8400054e, - 0x48025a08, 0x59300406, 0x82000580, 0x00000006, - 0x04020009, 0x811800ca, 0x81c80c00, 0x58040939, - 0x592c000d, 0x80040480, 0x592c080f, 0x80040480, - 0x4802580b, 0x417a7800, 0x0201f800, 0x00108997, - 0x5c028000, 0x5c027800, 0x5c025800, 0x1c01f000, - 0x4933c857, 0x4d2c0000, 0x59900004, 0x81300580, - 0x02020800, 0x00100615, 0x0201f800, 0x00108df4, - 0x02000800, 0x00100615, 0x59325808, 0x592c0208, - 0x84000540, 0x48025a08, 0x0401f7bf, 0x491bc857, - 0x49d3c857, 0x4dd00000, 0x41780800, 0x8007a0ca, - 0x83d3a400, 0x00007600, 0x4a03a005, 0x80000002, - 0x42000000, 0x00001000, 0x50000000, 0x82000480, - 0x24220001, 0x04020029, 0x59d01006, 0x82080500, - 0x00006000, 0x82000580, 0x00006000, 0x04000031, - 0x82080500, 0x40008000, 0x040007f8, 0x800409c0, - 0x0402002c, 0x811a31c0, 0x0400002a, 0x42000000, - 0x00001002, 0x50001000, 0x46000000, 0x00000512, - 0x42001800, 0x0000000a, 0x59e00000, 0x8c00051a, - 0x040207fc, 0x800c1840, 0x040207fc, 0x42000000, - 0x00001002, 0x46000000, 0x00000514, 0x42001800, - 0x0000000a, 0x59e00000, 0x8c00053a, 0x040207fc, - 0x800c1840, 0x040207fc, 0x42000000, 0x00001002, - 0x44080000, 0x0401f00f, 0x02004800, 0x000207c8, - 0x59d01006, 0x82080500, 0x00006000, 0x82000580, - 0x00006000, 0x04000007, 0x8c08151e, 0x040007f7, - 0x59d01006, 0x82080500, 0x00006000, 0x040207f3, - 0x83d3a400, 0x00000020, 0x80040800, 0x82040480, - 0x00000005, 0x040017bd, 0x5c03a000, 0x1c01f000, - 0x491bc857, 0x49d3c857, 0x4dd00000, 0x41780800, - 0x8007a0ca, 0x83d3a400, 0x00007600, 0x4a03a005, - 0x80000001, 0x59d00006, 0x83d3a400, 0x00000020, - 0x80040800, 0x82040480, 0x00000005, 0x040017f8, - 0x5c03a000, 0x1c01f000, 0x59d00006, 0x8c00053e, - 0x0400001e, 0x59902804, 0x4817c857, 0x801429c0, - 0x04000013, 0x5990000a, 0x5990080b, 0x5990100c, - 0x5990180d, 0x4800280a, 0x4804280b, 0x4808280c, - 0x480c280d, 0x59d00000, 0x59d00801, 0x59d01002, - 0x59d01803, 0x59d02004, 0x4800280e, 0x4804280f, - 0x48082810, 0x480c2811, 0x48102812, 0x59900006, - 0x82000500, 0xffff0000, 0x48032006, 0x4a03a005, - 0x30000000, 0x59d00006, 0x1c01f000, 0x4803c856, - 0x80204000, 0x50200000, 0x80000540, 0x04000003, - 0x80285040, 0x1c01f000, 0x58300001, 0x80000540, - 0x0400000e, 0x4802600b, 0x40006000, 0x58300204, - 0x82000500, 0x0000000f, 0x82000400, 0x0010110d, - 0x50004000, 0x802041c0, 0x02000800, 0x00100615, - 0x80285040, 0x1c01f000, 0x40005000, 0x1c01f000, - 0x00000005, 0x00000008, 0x0000000b, 0x0000000e, - 0x00000011, 0x00000000, 0x00000000, 0x0000000b, - 0x00000000, 0x00000000, 0x00000000, 0x00101108, - 0x00101107, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00101108, 0x00101107, 0x00101104, - 0x00101108, 0x00101107, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00101108, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00101108, 0x00101108, 0x00101108, - 0x00000000, 0x00101108, 0x00000000, 0x00000000, - 0x00000000, 0x4813c857, 0x492fc857, 0x4933c857, - 0x48126012, 0x592c5207, 0x802851c0, 0x0400004a, - 0x412c6000, 0x0401f84b, 0x04000009, 0x82240580, - 0x00000002, 0x04020003, 0x5830000d, 0x80102480, - 0x50200000, 0x80004540, 0x0400003f, 0x50200000, - 0x80000540, 0x0400000b, 0x80301400, 0x58080002, - 0x80102480, 0x0400101e, 0x801021c0, 0x04000009, - 0x80285040, 0x04000034, 0x80204000, 0x0401f7f4, - 0x58300001, 0x80006540, 0x0400002f, 0x0401f7e6, - 0x80285040, 0x0400002c, 0x80204000, 0x50200000, - 0x80000540, 0x0402000a, 0x58300001, 0x80006540, - 0x04000025, 0x58300204, 0x82004d00, 0x0000000f, - 0x82244400, 0x0010110d, 0x50204000, 0x592c0208, - 0x8400051e, 0x48025a08, 0x0401f013, 0x80102080, - 0x80102000, 0x48126010, 0x4813c857, 0x58080802, - 0x40100000, 0x80042480, 0x02001800, 0x00100615, - 0x58080000, 0x58081801, 0x80102400, 0x4812600e, - 0x480e600f, 0x4813c857, 0x592c0208, 0x8400055e, - 0x48025a08, 0x4833c857, 0x4823c857, 0x482bc857, - 0x4832600b, 0x4822600c, 0x482a600d, 0x80000580, - 0x0401f003, 0x82000540, 0x00000001, 0x1c01f000, - 0x58300204, 0x82004d00, 0x0000000f, 0x82244400, - 0x0010110d, 0x82000500, 0x000000ff, 0x82000580, - 0x00000029, 0x0402001b, 0x50204000, 0x592c0409, - 0x80000540, 0x02000800, 0x00100615, 0x82000c80, - 0x00000002, 0x04001011, 0x58300001, 0x80006540, - 0x02000800, 0x00100615, 0x58300204, 0x82000500, - 0x0000000f, 0x82000400, 0x0010110d, 0x50004000, - 0x40040000, 0x800409c0, 0x04000006, 0x82040c80, - 0x00000005, 0x040217f1, 0x80204400, 0x80000580, - 0x1c01f000, 0x59e00004, 0x8c00050e, 0x02020000, - 0x00100951, 0x1c01f000, 0x4c5c0000, 0x59e4b800, - 0x485fc857, 0x825c0500, 0x0000001f, 0x04000004, - 0x59e40862, 0x0201f800, 0x00100615, 0x825c0500, - 0x000000e0, 0x02000800, 0x00100615, 0x8c5cbd0e, - 0x04020807, 0x8c5cbd0c, 0x04020809, 0x8c5cbd0a, - 0x04020878, 0x5c00b800, 0x1c01f000, 0x4803c856, - 0x4a03c800, 0x00000080, 0x1c01f000, 0x4d2c0000, - 0x42007800, 0x0010b6eb, 0x583c0001, 0x583c0802, - 0x80040540, 0x0400003f, 0x42000800, 0x0010b5f5, - 0x50065800, 0x592c0002, 0x82000580, 0x00000000, - 0x0400000e, 0x59e40850, 0x59e41853, 0x400c0000, - 0x80040400, 0x59e40852, 0x4807c857, 0x80041480, - 0x04021008, 0x40001000, 0x480bc857, 0x4a007800, - 0x00000001, 0x0401f006, 0x4803c857, 0x0401f029, - 0x59e41050, 0x480bc857, 0x49787800, 0x480bc857, - 0x480fc857, 0x592c0003, 0x80000540, 0x04000006, - 0x80080580, 0x04020004, 0x592c0003, 0x4803c857, - 0x480bc857, 0x480a5803, 0x592c0007, 0x800001c0, - 0x04000007, 0x592c1007, 0x480bc857, 0x583c0003, - 0x4803c857, 0x80080480, 0x04001003, 0x583c1001, - 0x480bc857, 0x583c0802, 0x480bc857, 0x4807c857, - 0x4a025801, 0x00000000, 0x4a025809, 0x0010120c, - 0x480a5807, 0x48065808, 0x59e40053, 0x48025804, - 0x412c1000, 0x492fc857, 0x0201f800, 0x001008a1, - 0x5c025800, 0x4a03c800, 0x00000040, 0x1c01f000, - 0x42007800, 0x0010b5f5, 0x503c7800, 0x4a007802, - 0x00000100, 0x42007800, 0x0010b6eb, 0x583c0000, - 0x4803c857, 0x82000d80, 0x00000001, 0x04000004, - 0x80000000, 0x48007800, 0x0401f019, 0x49787800, - 0x583c1806, 0x583c0005, 0x800c1800, 0x480c7806, - 0x800c0580, 0x04020002, 0x49787806, 0x583c0807, - 0x800409c0, 0x0400000e, 0x583c0008, 0x80000000, - 0x48007808, 0x80040580, 0x04020009, 0x49787808, - 0x583c2006, 0x42001800, 0x00000001, 0x42001000, - 0x00008028, 0x0201f800, 0x00103857, 0x1c01f000, - 0x4a03c800, 0x00000020, 0x0201f800, 0x0010a867, - 0x59e40000, 0x1c01f000, 0x4d2c0000, 0x4a007001, - 0x00000000, 0x82040d00, 0x43000f80, 0x02020800, - 0x00100615, 0x58380009, 0x4803c00f, 0x0201f800, - 0x001091cb, 0x583a5808, 0x592c0000, 0x48007008, - 0x800001c0, 0x04020002, 0x49787007, 0x0201f800, - 0x0010083a, 0x5c025800, 0x0201f000, 0x001008c6, - 0x4803c856, 0x4c3c0000, 0x4d2c0000, 0x4d300000, - 0x5830000a, 0x80025d40, 0x02000800, 0x00100615, - 0x592e6008, 0x4c300000, 0x0201f800, 0x001091e3, - 0x5c006000, 0x02000800, 0x00100615, 0x58300002, - 0x82000580, 0x00000100, 0x04020010, 0x5930780b, - 0x583c0001, 0x80000540, 0x0400000e, 0x4802600b, - 0x40007800, 0x82000400, 0x00000002, 0x48006003, - 0x583c0000, 0x48006004, 0x40301000, 0x0201f800, - 0x001008a1, 0x0401f00c, 0x4a025a06, 0x00000002, - 0x4c300000, 0x0201f800, 0x00020381, 0x5c006000, - 0x40325800, 0x0201f800, 0x0010083a, 0x0201f800, - 0x000208b4, 0x5c026000, 0x5c025800, 0x5c007800, - 0x1c01f000, 0x4803c856, 0x4d2c0000, 0x4d300000, - 0x42007000, 0x0010b5f6, 0x58380801, 0x82040580, - 0x00000002, 0x04020011, 0x58386002, 0x5830000a, - 0x812c0580, 0x0402000d, 0x59e00004, 0x8c00050e, - 0x040007fe, 0x59dc0006, 0x4803c857, 0x4a03b805, - 0x20000000, 0x8c00053e, 0x040007f8, 0x4a007001, - 0x00000000, 0x0401f019, 0x58386006, 0x40305000, - 0x803061c0, 0x02000800, 0x00100615, 0x5830000a, - 0x812c0580, 0x04000004, 0x40305000, 0x58306000, - 0x0401f7f8, 0x40280000, 0x80300580, 0x58300000, - 0x04000006, 0x48005000, 0x800001c0, 0x04020007, - 0x48287005, 0x0401f005, 0x800001c0, 0x04020002, - 0x48007005, 0x48007006, 0x40325800, 0x0201f800, - 0x0010083a, 0x42007000, 0x0010b5f6, 0x58380001, - 0x82000580, 0x00000000, 0x02000800, 0x001008c6, - 0x5c026000, 0x5c025800, 0x1c01f000, 0x4803c856, - 0x42000800, 0x0000003c, 0x48079000, 0x59c80000, - 0x80040500, 0x040207fe, 0x497b9005, 0x4a039035, - 0x00880200, 0x59a8000e, 0x800000e0, 0x4803900e, - 0x4a039011, 0x00000024, 0x4a03900f, 0x0010cfc0, - 0x4a039010, 0x0010cfc0, 0x4a039015, 0x0000007f, - 0x4a03900d, 0x00000040, 0x4a039000, 0x00001600, - 0x1c01f000, 0x59c80007, 0x8c000508, 0x040208b7, - 0x59c80800, 0x8c040d16, 0x04020004, 0x82000500, - 0x00000006, 0x0c01f005, 0x4807c857, 0x82000500, - 0x0000000e, 0x0c01f001, 0x001012f8, 0x001012f6, - 0x0010567d, 0x001012f6, 0x001012fa, 0x001012f6, - 0x001012fa, 0x001012fa, 0x001012f6, 0x001012f6, - 0x001012f6, 0x001012f6, 0x001012fa, 0x001012f6, - 0x001012fa, 0x001012f6, 0x0201f800, 0x00100615, - 0x4803c857, 0x1c01f000, 0x59c8080c, 0x4807c857, - 0x82040500, 0x00006000, 0x04000004, 0x0201f800, - 0x0010a82a, 0x0401f006, 0x82040500, 0x007f0000, - 0x04000006, 0x0201f800, 0x0010a7fc, 0x0201f800, - 0x00106c07, 0x0401f02b, 0x82040500, 0x00000014, - 0x04000014, 0x0201f800, 0x0010a859, 0x836c0580, - 0x00000003, 0x0400000d, 0x0201f800, 0x00104e0d, - 0x04000004, 0x0201f800, 0x00103f37, 0x0401f007, - 0x4a035033, 0x00000001, 0x4202d800, 0x00000001, - 0x0201f800, 0x00104d76, 0x0401f817, 0x0401f015, - 0x82040500, 0x00001c00, 0x04000005, 0x0201f800, - 0x0010a838, 0x0401f810, 0x0401f00e, 0x82040500, - 0x00000140, 0x04000005, 0x0201f800, 0x0010a84b, - 0x0401f809, 0x0401f007, 0x82040500, 0x00008000, - 0x04000004, 0x0201f800, 0x0010a823, 0x0401f802, - 0x1c01f000, 0x4c0c0000, 0x4c100000, 0x4c140000, - 0x0201f800, 0x00100f17, 0x5c002800, 0x5c002000, - 0x5c001800, 0x1c01f000, 0x4803c856, 0x59a80804, - 0x59a8002b, 0x82000500, 0xfffff000, 0x80040540, - 0x4803502b, 0x59a8002f, 0x82000500, 0xfffff000, - 0x80040540, 0x4803502f, 0x48078882, 0x82041c00, - 0x0000000f, 0x800c1908, 0x820c1c00, 0x00000004, - 0x400c2000, 0x901029c0, 0x82040480, 0x000001e4, - 0x04021005, 0x42001000, 0x00000008, 0x801020c6, - 0x0401f031, 0x82040480, 0x00000230, 0x04021009, - 0x42001000, 0x00000007, 0x801000c2, 0x800000c2, - 0x80100400, 0x80100400, 0x80102400, 0x0401f026, - 0x82040480, 0x00000298, 0x04021008, 0x42001000, - 0x00000006, 0x801000c2, 0x800000c2, 0x80100400, - 0x80102400, 0x0401f01c, 0x82040480, 0x00000328, - 0x04021007, 0x42001000, 0x00000005, 0x801000c2, - 0x800000c2, 0x80102400, 0x0401f013, 0x82040480, - 0x00000404, 0x04021005, 0x42001000, 0x00000004, - 0x801020c4, 0x0401f00c, 0x82040480, 0x0000056c, - 0x04021006, 0x42001000, 0x00000003, 0x801000c2, - 0x80102400, 0x0401f004, 0x42001000, 0x00000002, - 0x801020c2, 0x82100480, 0x00000110, 0x80000080, - 0x80002000, 0x800800d0, 0x80140540, 0x80100540, - 0x48039035, 0x1c01f000, 0x59c80815, 0x0201f800, - 0x0010060d, 0x82040d00, 0x0000007c, 0x48079000, - 0x59c80000, 0x80040500, 0x040207fe, 0x8c040d04, - 0x04000003, 0x59c80035, 0x48039035, 0x59c80000, - 0x82000540, 0x00001200, 0x48039000, 0x1c01f000, - 0x4803c856, 0x497b88a9, 0x4a038807, 0x00000001, - 0x497b8807, 0x59c40005, 0x48038805, 0x0201f800, - 0x00101886, 0x4201d000, 0x000001f4, 0x0201f800, - 0x00105dd2, 0x497b880e, 0x4200b000, 0x000001f4, - 0x42000000, 0x00000001, 0x42000800, 0x00000014, - 0x0201f800, 0x001019b1, 0x42000800, 0x00000014, - 0x0201f800, 0x001019ac, 0x8c040d00, 0x04000005, - 0x8058b040, 0x040207f3, 0x0201f800, 0x00100615, - 0x4200b000, 0x00000032, 0x42000000, 0x00000001, - 0x42000800, 0x000000b4, 0x0201f800, 0x001019b1, - 0x42000800, 0x000000b4, 0x0201f800, 0x001019ac, - 0x8c040d00, 0x04000005, 0x8058b040, 0x040207f3, - 0x0201f800, 0x00100615, 0x59c40005, 0x48038805, - 0x42000000, 0x00000089, 0x800008d0, 0x48075054, - 0x48075055, 0x48075056, 0x42000800, 0x000000e0, - 0x0201f800, 0x001019b1, 0x42000800, 0x000000f4, - 0x0201f800, 0x001019ac, 0x82040500, 0xffffffd1, - 0x82000540, 0x00000002, 0x42000800, 0x000000f4, - 0x0201f800, 0x001019b1, 0x42000800, 0x000000a0, - 0x0201f800, 0x001019ac, 0x82040540, 0x00000001, - 0x42000800, 0x000000a0, 0x0201f800, 0x001019b1, - 0x42000800, 0x00000000, 0x0201f800, 0x001019ac, - 0x82040540, 0x00000001, 0x42000800, 0x00000000, - 0x0201f800, 0x001019b1, 0x4201d000, 0x0001d4c0, - 0x0201f800, 0x00105dd2, 0x0401fa45, 0x4a0388a7, - 0x0000f7f7, 0x4a0388a3, 0x8000403c, 0x4a0388ae, - 0x000061a8, 0x4a038801, 0x00032063, 0x4a038810, - 0x00410108, 0x4a038811, 0x00520608, 0x4a038812, - 0x00450320, 0x4a038813, 0x00440405, 0x4a03881c, - 0x004132e1, 0x4a038850, 0x80000108, 0x4a038860, - 0x00000008, 0x4a038870, 0x00000008, 0x4a038851, - 0x80000508, 0x4a038861, 0x00800000, 0x4a038871, - 0x00800000, 0x4a038852, 0x80000708, 0x4a038862, - 0x00800000, 0x4a038872, 0x00800000, 0x4a038853, - 0x80000608, 0x497b8863, 0x4a038873, 0x00800000, - 0x4a038882, 0x00000840, 0x4a0388a5, 0x0000001e, - 0x4a0388a6, 0x0000001e, 0x4a0388b0, 0x00007530, - 0x4a038802, 0x0000ffff, 0x4a038806, 0xc0e00800, - 0x1c01f000, 0x497b5022, 0x4a035021, 0x00000001, - 0x42000800, 0x00000040, 0x0201f800, 0x001019ac, - 0x82040500, 0xffffffaf, 0x82000540, 0x00000000, - 0x42000800, 0x00000040, 0x0201f800, 0x001019b1, - 0x42000800, 0x000000f4, 0x0201f800, 0x001019ac, - 0x4c040000, 0x40040000, 0x84000548, 0x42000800, - 0x000000f4, 0x0201f800, 0x001019b1, 0x42000800, - 0x00000000, 0x0201f800, 0x001019ac, 0x82040500, - 0xffffffc1, 0x82000540, 0x00000038, 0x42000800, - 0x00000000, 0x0201f800, 0x001019b1, 0x5c000000, - 0x42000800, 0x000000f4, 0x0201f000, 0x001019b1, - 0x59c40805, 0x59c40006, 0x80040d00, 0x02000800, - 0x00100615, 0x82040500, 0x00e00800, 0x04020004, - 0x8c040d3e, 0x040208df, 0x0401f007, 0x82040500, - 0x00800800, 0x02020800, 0x0010060d, 0x0201f800, - 0x00100615, 0x4c5c0000, 0x4c600000, 0x59c4b805, - 0x59c40006, 0x8c000500, 0x04000003, 0x8c5cbd00, - 0x04020095, 0x485fc857, 0x0201f800, 0x00104e0d, - 0x0400001e, 0x59c40005, 0x82000500, 0x000000c0, - 0x0400004b, 0x0201f800, 0x00104e23, 0x04020048, - 0x59c40006, 0x82000500, 0x000000f0, 0x04020004, - 0x4a038805, 0x000000c0, 0x0401f041, 0x59a80015, - 0x84000506, 0x48035015, 0x42006000, 0xff203fff, - 0x42006800, 0x40000000, 0x0201f800, 0x001040ad, - 0x42000800, 0x00000010, 0x42001000, 0x00104020, - 0x0201f800, 0x00105dc7, 0x8c5cbd34, 0x04020030, - 0x4a035032, 0x0000aaaa, 0x59c40005, 0x8c00050c, - 0x04020012, 0x8c00050e, 0x0402001c, 0x8c00050a, - 0x0402001d, 0x8c000508, 0x0400000b, 0x59a80017, - 0x82000580, 0x00000009, 0x04020007, 0x42000000, - 0x0010b642, 0x0201f800, 0x0010a86e, 0x0201f800, - 0x00104fe9, 0x0401f05a, 0x0201f800, 0x00104e23, - 0x04020007, 0x42000800, 0x0000000f, 0x42001000, - 0x00103f37, 0x0201f800, 0x00105da7, 0x4a035033, - 0x00000000, 0x0401f00b, 0x4a035033, 0x00000002, - 0x0401f008, 0x42000000, 0x0010b644, 0x0201f800, - 0x0010a86e, 0x0201f800, 0x00104f93, 0x0401f044, - 0x0201f800, 0x00105049, 0x0401f041, 0x8c5cbd34, - 0x0400003d, 0x59c40005, 0x8c00053a, 0x04020005, - 0x42000000, 0x0010b616, 0x0201f800, 0x0010a86e, - 0x4a038805, 0x02000000, 0x0201f800, 0x00104e0d, - 0x04020010, 0x4a038805, 0x04000000, 0x0201f800, - 0x00104e1b, 0x04020008, 0x4a035033, 0x00000001, - 0x4202d800, 0x00000001, 0x0201f800, 0x00104d76, - 0x0401f061, 0x41780000, 0x0201f800, 0x00104de5, - 0x0201f800, 0x00101a59, 0x4000c000, 0x0201f800, - 0x001019d0, 0x836c1580, 0x00000004, 0x0402000d, - 0x8c5cbd00, 0x04020018, 0x59a81005, 0x8c081506, - 0x04020005, 0x59c410a3, 0x82081540, 0x00000008, - 0x480b88a3, 0x59c41006, 0x84081540, 0x480b8806, - 0x4a038805, 0x04000000, 0x4202d800, 0x00000001, - 0x497b5014, 0x59a80005, 0x8c000518, 0x04020004, - 0x0401f95c, 0x0201f800, 0x00103f5c, 0x0201f800, - 0x00103951, 0x8c5cbd3c, 0x04020858, 0x8c5cbd00, - 0x04000036, 0x42000000, 0x0010b6c9, 0x0201f800, - 0x0010a86e, 0x4a038805, 0x00000001, 0x4200b000, - 0x00000352, 0x4201d000, 0x00000064, 0x4c580000, - 0x0201f800, 0x00105dd2, 0x0201f800, 0x00101941, - 0x5c00b000, 0x04000004, 0x8058b040, 0x040207f6, - 0x0401f004, 0x4a038805, 0x00000001, 0x0401f01f, - 0x59c40006, 0x84000500, 0x48038806, 0x0201f800, - 0x00106c32, 0x497b8880, 0x0201f800, 0x0010a7e7, - 0x59c4000d, 0x8c000500, 0x02020800, 0x0010a7f5, - 0x59c400a3, 0x82000500, 0xfcf8ffff, 0x480388a3, - 0x4a03504c, 0x00000002, 0x4202d800, 0x00000004, - 0x4a038805, 0x00000001, 0x0201f800, 0x0010071a, - 0x0401fb42, 0x497b5052, 0x4a035049, 0x00000001, - 0x0201f800, 0x0010048c, 0x825cbd00, 0xbbfffffe, - 0x485f8805, 0x5c00c000, 0x5c00b800, 0x1c01f000, - 0x59c41004, 0x480bc857, 0x8c081500, 0x04000006, - 0x4803c856, 0x497b2807, 0x0201f800, 0x00106cf9, - 0x0401f00a, 0x82080500, 0x000001f0, 0x04000007, - 0x4803c856, 0x417a3000, 0x0201f800, 0x00105d9b, - 0x0201f800, 0x00106d1b, 0x4a038805, 0x80000000, - 0x1c01f000, 0x59c408a3, 0x4807c857, 0x84040d40, - 0x480788a3, 0x1c01f000, 0x4d900000, 0x4dd00000, - 0x4da40000, 0x4d140000, 0x4a038805, 0x40000000, - 0x42000000, 0x0010b6c5, 0x0201f800, 0x0010a86e, - 0x0201f800, 0x0010698c, 0x59c41004, 0x8c081500, - 0x04000054, 0x598e600d, 0x497b2807, 0x813261c0, - 0x04000032, 0x59300403, 0x82000580, 0x00000032, - 0x0402002e, 0x5930001c, 0x48038833, 0x4a038807, - 0x00018000, 0x4201d000, 0x00000002, 0x0201f800, - 0x00105dd2, 0x497b8807, 0x4201d000, 0x00000002, - 0x0201f800, 0x00105dd2, 0x0201f800, 0x00106b71, - 0x4201d000, 0x00007530, 0x0201f800, 0x00105dd2, - 0x59c408a4, 0x82040d00, 0x0000000f, 0x82040d80, - 0x00000000, 0x04000005, 0x42000000, 0x00200000, - 0x0201f800, 0x001019b6, 0x0201f800, 0x001068f6, - 0x59300008, 0x80000540, 0x02000800, 0x00100615, - 0x40025800, 0x4a025a04, 0x00000103, 0x5931d821, - 0x58ef400b, 0x58ec0009, 0x0801f800, 0x0201f800, - 0x000208b4, 0x0401f047, 0x598c000f, 0x82001c80, - 0x000000c8, 0x0402100f, 0x80000000, 0x4803180f, - 0x59c400a4, 0x82000500, 0x0000000f, 0x82000580, - 0x00000002, 0x04020004, 0x42000000, 0x00200000, - 0x0401fbfa, 0x0201f800, 0x00105d86, 0x0401f035, - 0x4933c857, 0x0201f800, 0x00106b71, 0x813261c0, - 0x04000030, 0x4a026203, 0x00000001, 0x42027000, - 0x00000027, 0x0201f800, 0x000208d8, 0x0401f029, - 0x8c081508, 0x04000027, 0x417a3000, 0x0201f800, - 0x00106e2f, 0x42032000, 0x0000bf32, 0x0201f800, - 0x00105d9b, 0x59926004, 0x813261c0, 0x04000012, - 0x42001800, 0x000000c8, 0x0201f800, 0x00106dfb, - 0x0402000d, 0x59c400a4, 0x82000500, 0x0000000f, - 0x82000580, 0x00000002, 0x04020004, 0x42000000, - 0x00200000, 0x0401fbd1, 0x0201f800, 0x00105d8b, - 0x0401f00c, 0x4933c857, 0x0201f800, 0x00106b13, - 0x813261c0, 0x04000007, 0x42027000, 0x0000004f, - 0x4a026203, 0x00000003, 0x0201f800, 0x000208d8, - 0x5c022800, 0x5c034800, 0x5c03a000, 0x5c032000, - 0x0201f000, 0x00106982, 0x4803c857, 0x59a80821, - 0x48035021, 0x80041580, 0x04000045, 0x800409c0, - 0x04000023, 0x497b504c, 0x42000000, 0x0010b60b, - 0x0201f800, 0x0010a86e, 0x0201f800, 0x0010a920, - 0x42001000, 0x00008011, 0x59c40001, 0x82000500, - 0x00018000, 0x82001d80, 0x00000000, 0x04000009, - 0x82001d80, 0x00008000, 0x04000009, 0x82001d80, - 0x00010000, 0x04000009, 0x0201f800, 0x00100615, - 0x42001800, 0x00000000, 0x0401f006, 0x42001800, - 0x00000001, 0x0401f003, 0x42001800, 0x00000003, - 0x0201f800, 0x00103857, 0x0401f021, 0x59a8084c, - 0x800409c0, 0x04020007, 0x59c4000d, 0x8c000520, - 0x04000004, 0x42001800, 0x00000003, 0x0401f002, - 0x40041800, 0x0201f800, 0x0010a904, 0x42001000, - 0x00008012, 0x0201f800, 0x00103857, 0x0201f800, - 0x0010071a, 0x0201f800, 0x0010a95a, 0x0402000c, - 0x0401f853, 0x4d400000, 0x4d3c0000, 0x42028000, - 0x00000028, 0x42027800, 0x00000008, 0x0201f800, - 0x00101d90, 0x5c027800, 0x5c028000, 0x1c01f000, - 0x4803c857, 0x82000400, 0x00101eb5, 0x50000800, - 0x82040d00, 0x000000ff, 0x1c01f000, 0x4803c856, - 0x4c580000, 0x4200b000, 0x00000010, 0x497b88ac, - 0x497b88ad, 0x8058b040, 0x040207fe, 0x5c00b000, - 0x1c01f000, 0x4807c857, 0x48075010, 0x80041108, - 0x4200b000, 0x00000010, 0x497b88ac, 0x80000580, - 0x800811c0, 0x04020006, 0x82040500, 0x0000000f, - 0x82000400, 0x0010a95f, 0x50000000, 0x480388ad, - 0x80081040, 0x8058b040, 0x040207f5, 0x1c01f000, - 0x59a80005, 0x04000003, 0x84000546, 0x0401f002, - 0x84000506, 0x48035005, 0x4803c857, 0x1c01f000, - 0x4803c857, 0x4c080000, 0x4c040000, 0x4c000000, - 0x59c40892, 0x4807c857, 0x80041580, 0x04000010, - 0x80041480, 0x04021007, 0x80081080, 0x80081000, - 0x4008b000, 0x42000000, 0x00000201, 0x0401f004, - 0x4008b000, 0x42000000, 0x00000210, 0x48038886, - 0x8058b040, 0x040207fe, 0x497b8886, 0x5c000000, - 0x5c000800, 0x5c001000, 0x1c01f000, 0x4803c856, - 0x0201f800, 0x0010393e, 0x04000005, 0x42028000, - 0x0000002e, 0x0201f000, 0x0010a25b, 0x1c01f000, - 0x59a8086f, 0x82040500, 0x00000010, 0x04000004, - 0x42000800, 0x00000002, 0x0401f010, 0x82040500, - 0x00000020, 0x42000800, 0x00000002, 0x0402000b, - 0x59c80835, 0x82040d00, 0x00001f00, 0x80040910, - 0x80040800, 0x59a8006c, 0x80000540, 0x04000003, - 0x42000800, 0x0000025a, 0x4807c857, 0x1c01f000, - 0x4c000000, 0x59a80053, 0x4803c857, 0x82000580, - 0x00000000, 0x5c000000, 0x1c01f000, 0x4c000000, - 0x59a80053, 0x4803c857, 0x82000580, 0x00000001, - 0x5c000000, 0x1c01f000, 0x4c000000, 0x59a80053, - 0x4803c857, 0x82000580, 0x00000003, 0x5c000000, - 0x1c01f000, 0x4c000000, 0x59a80053, 0x82000580, - 0x00000002, 0x5c000000, 0x1c01f000, 0x4c000000, - 0x4c040000, 0x4c080000, 0x4c380000, 0x59a80040, - 0x82000c80, 0x00000007, 0x02021800, 0x00100615, - 0x0c01f806, 0x5c007000, 0x5c001000, 0x5c000800, - 0x5c000000, 0x1c01f000, 0x001016dd, 0x001016f0, - 0x00101704, 0x00101706, 0x0010172d, 0x0010172f, - 0x00101731, 0x4803c856, 0x4a035042, 0x00000000, - 0x42000000, 0x00000002, 0x0401fa18, 0x42000000, - 0x00000002, 0x0401f9ad, 0x0401faae, 0x4803c856, - 0x4a035040, 0x00000006, 0x42000800, 0x0000001e, - 0x42001000, 0x00101732, 0x0201f000, 0x00105da7, - 0x497b5045, 0x4a035050, 0x00000036, 0x4a03504f, - 0x0000002a, 0x4803c856, 0x4a035042, 0x00000001, - 0x42000000, 0x00000002, 0x0401f998, 0x4803c856, - 0x4a035040, 0x00000006, 0x42000800, 0x0000001e, - 0x42001000, 0x00101732, 0x0201f000, 0x00105da7, - 0x0201f800, 0x00100615, 0x4a035050, 0x00000036, - 0x4803c856, 0x4a035042, 0x00000003, 0x42000800, - 0x00000000, 0x0401fa9f, 0x82040d00, 0x00000090, - 0x82040580, 0x00000090, 0x04000009, 0x82040580, - 0x00000010, 0x04000009, 0x82040580, 0x00000000, - 0x04000008, 0x0201f800, 0x00100615, 0x42000000, - 0x00000001, 0x0401f005, 0x41780000, 0x0401f003, - 0x42000000, 0x00000002, 0x0401f970, 0x497b5046, - 0x4803c856, 0x4a035040, 0x00000006, 0x42000800, - 0x0000001e, 0x42001000, 0x00101732, 0x0201f000, - 0x00105da7, 0x0201f800, 0x00100615, 0x0201f800, - 0x00100615, 0x1c01f000, 0x4c000000, 0x4c040000, - 0x4c080000, 0x4c380000, 0x59a80042, 0x82000c80, - 0x00000007, 0x02021800, 0x00100615, 0x0c01f806, - 0x5c007000, 0x5c001000, 0x5c000800, 0x5c000000, - 0x1c01f000, 0x00101748, 0x00101767, 0x001017bb, - 0x001017d2, 0x001017e9, 0x001017f2, 0x001017f4, - 0x0401f9f9, 0x0402001b, 0x59a81048, 0x42000800, - 0x00000000, 0x0401fa5f, 0x82040d00, 0x00000090, - 0x82040580, 0x00000090, 0x04000009, 0x82040580, - 0x00000010, 0x04000008, 0x82040580, 0x00000000, - 0x04000007, 0x0201f800, 0x00100615, 0x84081540, - 0x0401f004, 0x84081542, 0x0401f002, 0x84081544, - 0x480b5048, 0x4a035040, 0x00000001, 0x0401f003, - 0x0401f8cb, 0x0401ff82, 0x1c01f000, 0x0401f88f, - 0x04000052, 0x0401f9d8, 0x0402002a, 0x42000800, - 0x00000000, 0x0401fa3f, 0x82040d00, 0x00000090, - 0x82040580, 0x00000000, 0x04000044, 0x82040580, - 0x00000010, 0x04000006, 0x82040580, 0x00000090, - 0x04000009, 0x0201f800, 0x00100615, 0x59c40801, - 0x82040d00, 0x00018000, 0x82040580, 0x00000000, - 0x04000036, 0x42000800, 0x00000000, 0x0401fa29, - 0x82040d00, 0x00000090, 0x82040580, 0x00000010, - 0x04000006, 0x82040580, 0x00000090, 0x04000006, - 0x02020800, 0x00100615, 0x59a80048, 0x84000542, - 0x0401f003, 0x59a80048, 0x84000540, 0x48035048, - 0x59a80045, 0x80000000, 0x48035045, 0x82000580, - 0x00000005, 0x04000003, 0x0401f861, 0x0401f01e, - 0x497b5045, 0x59c40801, 0x82040d00, 0x00018000, - 0x82040580, 0x00000000, 0x04000009, 0x82040580, - 0x00008000, 0x04000009, 0x82040580, 0x00010000, - 0x04000008, 0x0201f800, 0x00100615, 0x42000000, - 0x00000001, 0x0401f005, 0x41780000, 0x0401f003, - 0x42000000, 0x00000002, 0x0401f948, 0x4a035042, - 0x00000002, 0x0401f004, 0x4a035040, 0x00000003, - 0x0401f002, 0x0401ff42, 0x1c01f000, 0x0401f83b, - 0x04000015, 0x59a8004f, 0x80000040, 0x4803504f, - 0x0401f981, 0x04020005, 0x4a035040, 0x00000003, - 0x497b5041, 0x0401f00c, 0x59a8004f, 0x80000540, - 0x04020003, 0x0401f89e, 0x0401f002, 0x0401f84b, - 0x0401f82f, 0x497b5045, 0x4a035042, 0x00000001, - 0x0401ff2b, 0x1c01f000, 0x0401f824, 0x04000015, - 0x0401f96d, 0x0402000f, 0x59a80046, 0x80000000, - 0x48035046, 0x82000580, 0x00000007, 0x0402000c, - 0x4a035052, 0x0000000a, 0x497b5049, 0x59a80048, - 0x8400055e, 0x48035048, 0x4803c857, 0x0401f005, - 0x0401f817, 0x4a035042, 0x00000004, 0x0401ff3d, - 0x1c01f000, 0x0401f80d, 0x04000007, 0x0401f956, - 0x04020003, 0x0401ff1b, 0x0401f003, 0x0401f80c, - 0x0401ff34, 0x1c01f000, 0x0201f800, 0x00100615, - 0x0201f800, 0x00100615, 0x59a80050, 0x80000040, - 0x48035050, 0x0400088d, 0x1c01f000, 0x4c040000, - 0x42000800, 0x00000000, 0x0401f9ae, 0x82040d00, - 0x00000090, 0x82040580, 0x00000090, 0x04000009, - 0x82040580, 0x00000010, 0x04000009, 0x82040580, - 0x00000000, 0x04000009, 0x0201f800, 0x00100615, - 0x42000000, 0x00000002, 0x0401f005, 0x42000000, - 0x00000001, 0x0401f002, 0x41780000, 0x0401f8e7, - 0x5c000800, 0x1c01f000, 0x4c040000, 0x59c40801, - 0x82040d00, 0x00018000, 0x82040580, 0x00000000, - 0x04000009, 0x82040580, 0x00008000, 0x04000009, - 0x82040580, 0x00010000, 0x04000009, 0x0201f800, - 0x00100615, 0x42000000, 0x00000002, 0x0401f005, - 0x42000000, 0x00000001, 0x0401f002, 0x41780000, - 0x0401f866, 0x5c000800, 0x1c01f000, 0x4c040000, - 0x59a80045, 0x80000000, 0x48035045, 0x82000580, - 0x00000005, 0x04020018, 0x497b5045, 0x59c40801, - 0x82040d00, 0x00018000, 0x82040580, 0x00000000, - 0x04000009, 0x82040580, 0x00008000, 0x04000009, - 0x82040580, 0x00010000, 0x04000009, 0x0201f800, - 0x00100615, 0x42000000, 0x00000002, 0x0401f005, - 0x42000000, 0x00000001, 0x0401f002, 0x41780000, - 0x0401f846, 0x42000800, 0x00000000, 0x0401f95d, - 0x82040d00, 0x00000090, 0x82040580, 0x00000090, - 0x04000009, 0x82040580, 0x00000010, 0x04000009, - 0x82040580, 0x00000000, 0x04000009, 0x0201f800, - 0x00100615, 0x42000000, 0x00000002, 0x0401f005, - 0x42000000, 0x00000001, 0x0401f002, 0x41780000, - 0x0401f896, 0x5c000800, 0x1c01f000, 0x4c200000, - 0x59a80048, 0x82000500, 0x00007fff, 0x02000800, - 0x00100615, 0x59a84047, 0x80204102, 0x02001800, - 0x00100615, 0x48235047, 0x80204500, 0x040007fa, - 0x8c000504, 0x04020007, 0x8c000502, 0x04020008, - 0x8c000500, 0x04020008, 0x0201f800, 0x00100615, - 0x42000000, 0x00000002, 0x0401f005, 0x41780000, - 0x0401f003, 0x42000000, 0x00000001, 0x0401f80f, - 0x5c004000, 0x1c01f000, 0x04011000, 0x4a03c840, - 0x0010b240, 0x4a03c842, 0x00000009, 0x40000000, - 0x040117ff, 0x4a035047, 0x00000004, 0x4a03503e, - 0x00000000, 0x1c01f000, 0x59a80858, 0x82040d80, - 0x01391077, 0x04020008, 0x59e00813, 0x8c040d00, - 0x04000005, 0x82000d80, 0x00000002, 0x04020002, - 0x41780000, 0x800001c0, 0x04000040, 0x82000d80, - 0x00000001, 0x0402001d, 0x42000800, 0x000000a0, - 0x0401f908, 0x82040540, 0x00000004, 0x42000800, - 0x000000a0, 0x0401f908, 0x42000800, 0x000000c0, - 0x0401f900, 0x82040540, 0x00000020, 0x42000800, - 0x000000c0, 0x0401f900, 0x59c40001, 0x82000500, - 0xfffe7fff, 0x82000540, 0x00000000, 0x48038801, - 0x59a80054, 0x80000110, 0x42000800, 0x000000e0, - 0x0401f8f5, 0x0401f03c, 0x82000d80, 0x00000002, - 0x02020800, 0x00100615, 0x42000800, 0x000000a0, - 0x0401f8e8, 0x82040500, 0xfffffffb, 0x42000800, - 0x000000a0, 0x0401f8e8, 0x42000800, 0x000000c0, - 0x0401f8e0, 0x82040500, 0xffffffdf, 0x42000800, - 0x000000c0, 0x0401f8e0, 0x59c40001, 0x82000500, - 0xfffe7fff, 0x82000540, 0x00010000, 0x48038801, - 0x59a80056, 0x80000110, 0x42000800, 0x000000e0, - 0x0401f8d5, 0x0401f01c, 0x42000800, 0x000000a0, - 0x0401f8cc, 0x82040540, 0x00000004, 0x42000800, - 0x000000a0, 0x0401f8cc, 0x42000800, 0x000000c0, - 0x0401f8c4, 0x82040500, 0xffffffdf, 0x42000800, - 0x000000c0, 0x0401f8c4, 0x59c40001, 0x82000500, - 0xfffe7fff, 0x82000540, 0x00008000, 0x48038801, - 0x59a80055, 0x80000110, 0x42000800, 0x000000e0, - 0x0401f8b9, 0x1c01f000, 0x4803c857, 0x59a80858, - 0x82040d80, 0x01391077, 0x04020008, 0x59e00813, - 0x8c040d00, 0x04000005, 0x82000d80, 0x00000002, - 0x04020002, 0x41780000, 0x4c000000, 0x0401f942, - 0x5c000000, 0x800001c0, 0x04000026, 0x82000d80, - 0x00000001, 0x04020010, 0x59a8006c, 0x80000540, - 0x04000004, 0x42001000, 0x00000000, 0x0401f9f7, - 0x42000800, 0x00000000, 0x0401f896, 0x82040540, - 0x00000090, 0x42000800, 0x00000000, 0x0401f896, - 0x0401f024, 0x82000d80, 0x00000002, 0x02020800, - 0x00100615, 0x59a8006c, 0x80000540, 0x04000004, - 0x42001000, 0x00010000, 0x0401f9e4, 0x42000800, - 0x00000000, 0x0401f883, 0x82040500, 0xffffff6f, - 0x42000800, 0x00000000, 0x0401f883, 0x0401f011, - 0x59a8006c, 0x80000540, 0x04000004, 0x42001000, - 0x00008000, 0x0401f9d5, 0x42000800, 0x00000000, - 0x0401f874, 0x82040500, 0xffffff6f, 0x82000540, - 0x00000010, 0x42000800, 0x00000000, 0x0401f872, - 0x0401f111, 0x4c580000, 0x4200b000, 0x00000014, - 0x8058b040, 0x04000042, 0x59c4000d, 0x8c000520, - 0x040207fc, 0x0401f85b, 0x59c4000d, 0x8c000520, - 0x040207f8, 0x59c40808, 0x84040d50, 0x48078808, - 0x4200b000, 0x000000c8, 0x8058b040, 0x040207ff, - 0x4200b000, 0x00000014, 0x8058b040, 0x04000030, - 0x59c4000d, 0x8c000520, 0x0402002d, 0x42000800, - 0x00001000, 0x50040800, 0x82040c80, 0x24220001, - 0x04020003, 0x8c000504, 0x040007f4, 0x0401f841, - 0x59c4000d, 0x8c000520, 0x04020021, 0x42000800, - 0x00001000, 0x50040800, 0x82040c80, 0x24220001, - 0x04020003, 0x8c000504, 0x040007e8, 0x4200b000, - 0x0000000a, 0x8058b040, 0x04000003, 0x0401f831, - 0x0401f7fd, 0x4200b000, 0x00000064, 0x59c4000d, - 0x8c00051e, 0x0400000e, 0x8058b040, 0x040207fc, - 0x42000000, 0x00001000, 0x50000000, 0x82000480, - 0x24220001, 0x04020004, 0x59c40808, 0x84040d10, - 0x48078808, 0x80000580, 0x0401f00c, 0x42000000, - 0x00001000, 0x50000000, 0x82000480, 0x24220001, - 0x04020004, 0x59c40808, 0x84040d10, 0x48078808, - 0x82000540, 0x00000001, 0x5c00b000, 0x1c01f000, - 0x42000800, 0x000000a0, 0x0401f816, 0x82040500, - 0xfffffffe, 0x42000800, 0x000000a0, 0x0401f816, - 0x42000800, 0x00000000, 0x0401f80e, 0x82040500, - 0xfffffffe, 0x42000800, 0x00000000, 0x0401f00e, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x1c01f000, 0x480b8805, 0x1c01f000, - 0x4807880e, 0x59c4080f, 0x82040d00, 0x000000ff, - 0x1c01f000, 0x900001c0, 0x80040d40, 0x84040d40, - 0x4807880e, 0x1c01f000, 0x82000d80, 0x00200000, - 0x04000009, 0x82000d80, 0x02000000, 0x04000006, - 0x82000d80, 0x01000000, 0x04000006, 0x59c408a3, - 0x0401f006, 0x59c408a3, 0x84040d30, 0x0401f003, - 0x59c408a3, 0x84040d32, 0x80040540, 0x480388a3, - 0x480788a3, 0x1c01f000, 0x59c400a3, 0x84000556, - 0x480388a3, 0x84000516, 0x480388a3, 0x1c01f000, - 0x485fc857, 0x4863c857, 0x4c640000, 0x4d3c0000, - 0x4d400000, 0x0201f800, 0x00106c32, 0x4863500a, - 0x0201f800, 0x0010a95a, 0x0402006a, 0x82600d00, - 0x0000ff00, 0x800409c0, 0x0400000c, 0x4200c800, - 0x00000001, 0x59a80010, 0x82000500, 0x000000ff, - 0x80041110, 0x80081580, 0x04000021, 0x82041580, - 0x0000ff00, 0x0400000a, 0x59c410a3, 0x82081500, - 0x00008000, 0x04000009, 0x59c410a7, 0x82081500, - 0x0000ff00, 0x82081580, 0x0000ff00, 0x4200c800, - 0x00000000, 0x04000012, 0x59a80005, 0x8c000502, - 0x04020008, 0x8c000500, 0x0402000d, 0x599c1017, - 0x8c08151a, 0x0400003c, 0x84000542, 0x48035005, - 0x4200c800, 0x00000002, 0x42028000, 0x00000004, - 0x42027800, 0x00000008, 0x0401f007, 0x59a80805, - 0x84040d40, 0x48075005, 0x42028000, 0x00000004, - 0x417a7800, 0x59a80006, 0x8c000502, 0x04020006, - 0x59a80805, 0x8c040d0a, 0x04020032, 0x84040d4a, - 0x48075005, 0x42000000, 0x0010b610, 0x0201f800, - 0x0010a86e, 0x59a8180a, 0x42001000, 0x00008013, - 0x0201f800, 0x00103857, 0x0201f800, 0x0010393e, - 0x04000015, 0x4d400000, 0x82600500, 0x000000ff, - 0x42028800, 0x0000ffff, 0x40643000, 0x42028000, - 0x0000000e, 0x0201f800, 0x0010a258, 0x42000800, - 0x00000001, 0x42001000, 0x00000100, 0x0201f800, - 0x00105ec4, 0x5c028000, 0x599c0817, 0x8c040d0a, - 0x04020010, 0x493fc857, 0x4943c857, 0x0401fb59, - 0x0401f00c, 0x0201f800, 0x0010393e, 0x04000009, - 0x42028000, 0x0000000f, 0x42028800, 0x0000ffff, - 0x42003000, 0x00000000, 0x0201f800, 0x0010a25b, - 0x497b8880, 0x5c028000, 0x5c027800, 0x5c00c800, - 0x1c01f000, 0x42000800, 0x00000000, 0x0401ff61, - 0x82040540, 0x00000002, 0x42000800, 0x00000000, - 0x0401f761, 0x42000800, 0x00000000, 0x0401ff59, - 0x82040500, 0xfffffffd, 0x42000800, 0x00000000, - 0x0401f759, 0x59c408a8, 0x0401ff4a, 0x0401ff49, - 0x59c400a8, 0x80040d80, 0x040207fb, 0x1c01f000, - 0x4803c856, 0x4a038807, 0x00000001, 0x497b8807, - 0x59c40005, 0x48038805, 0x497b506c, 0x497b506d, - 0x41785800, 0x42006000, 0x00000001, 0x42006800, - 0x00000003, 0x0401f824, 0x0401f82f, 0x40400000, - 0x4803c857, 0x82408580, 0x00000000, 0x0402001d, - 0x41785800, 0x42006000, 0x0000001e, 0x42006800, - 0x00000014, 0x0401f818, 0x0401f823, 0x40400000, - 0x4803c857, 0x82408580, 0x00000800, 0x04020011, - 0x42005800, 0x00000001, 0x42006000, 0x0000001e, - 0x42006800, 0x00000014, 0x0401f80b, 0x0401f816, - 0x40400000, 0x4803c857, 0x82408580, 0x0000ffff, - 0x04020004, 0x4a03506c, 0x00000001, 0x4803c856, - 0x1c01f000, 0x41785000, 0x0401f812, 0x0401f838, - 0x40347000, 0x40340800, 0x0401f03d, 0x42005000, - 0x00000001, 0x0401f80b, 0x0401f831, 0x40340800, - 0x0401f037, 0x42005000, 0x00000002, 0x0401f805, - 0x0401f81d, 0x0401f835, 0x40048000, 0x1c01f000, - 0x0401f808, 0x0401f814, 0x40280800, 0x0401f826, - 0x402c0800, 0x0401f827, 0x40300800, 0x0401f025, - 0x42000800, 0x0000ffff, 0x42001000, 0x00000001, - 0x0401f829, 0x42001000, 0x00000010, 0x0401f826, - 0x42000800, 0x0000ffff, 0x42001000, 0x00000010, - 0x0401f021, 0x41780800, 0x42001000, 0x00000002, - 0x0401f01d, 0x0401f92e, 0x4a03d000, 0x00050004, - 0x0401f92b, 0x4a03d000, 0x00050005, 0x0401f928, - 0x4a03d000, 0x00050004, 0x42000800, 0x00000001, - 0x42001000, 0x00000001, 0x0401f00f, 0x42000800, - 0x00000002, 0x42001000, 0x00000002, 0x0401f00a, - 0x42001000, 0x00000005, 0x0401f007, 0x42001000, - 0x00000010, 0x0401f004, 0x42001000, 0x00000010, - 0x0401f01b, 0x0401f912, 0x82082c00, 0x0010a95f, - 0x50142800, 0x82081500, 0xffffffff, 0x04000013, - 0x0401f90b, 0x80081040, 0x80142902, 0x40040000, - 0x80140500, 0x04000007, 0x4a03d000, 0x00070006, - 0x0401f903, 0x4a03d000, 0x00070007, 0x0401f006, - 0x4a03d000, 0x00070004, 0x0401f8fd, 0x4a03d000, - 0x00070005, 0x0401f7ec, 0x1c01f000, 0x41780800, - 0x82082c00, 0x0010a95f, 0x50142800, 0x82081500, - 0xffffffff, 0x04000010, 0x0401f8f1, 0x4a03d000, - 0x00050001, 0x0401f8ee, 0x59e81800, 0x80081040, - 0x80142902, 0x8c0c1d06, 0x04000004, 0x40140000, - 0x80040d40, 0x0401f8e6, 0x4a03d000, 0x00070000, - 0x0401f7ef, 0x1c01f000, 0x480bc857, 0x480b506d, - 0x59c40001, 0x82000500, 0xffffefff, 0x48038801, - 0x41781800, 0x0401f8c4, 0x41785800, 0x42006000, - 0x0000001e, 0x42006800, 0x00000004, 0x0401ff7a, - 0x42006800, 0x0000003c, 0x0401ff7d, 0x41785800, - 0x42006000, 0x0000001e, 0x42006800, 0x00000004, - 0x0401ff71, 0x41786800, 0x0401ff75, 0x41785800, - 0x42006000, 0x0000001e, 0x41786800, 0x0401ff6a, - 0x42006800, 0x00000002, 0x0401ff6d, 0x42006800, - 0x00000001, 0x0401ff64, 0x42006800, 0x000000f5, - 0x0401ff67, 0x41785800, 0x42006000, 0x0000001e, - 0x42006800, 0x00000004, 0x0401ff5b, 0x42006800, - 0x00000020, 0x0401ff5e, 0x59a8106d, 0x0401f865, - 0x42001800, 0x000200f5, 0x0401f897, 0x59a8106d, - 0x0401f879, 0x41785800, 0x42006000, 0x0000001e, - 0x42006800, 0x00000004, 0x0401ff4b, 0x41786800, - 0x0401ff4f, 0x59c40001, 0x82000540, 0x00001000, - 0x48038801, 0x41785800, 0x42006000, 0x0000001e, - 0x42006800, 0x00000015, 0x0401ff3f, 0x0401ff4a, - 0x40400000, 0x82000540, 0x00000002, 0x4c000000, - 0x41785800, 0x42006000, 0x0000001e, 0x42006800, - 0x00000015, 0x0401ff34, 0x5c000000, 0x40006800, - 0x0401ff37, 0x41785800, 0x42006000, 0x0000001e, - 0x42006800, 0x00000015, 0x0401ff2b, 0x0401ff36, - 0x40400000, 0x82000500, 0x0000fffd, 0x4c000000, - 0x41785800, 0x42006000, 0x0000001e, 0x42006800, - 0x00000015, 0x0401ff20, 0x5c000000, 0x40006800, - 0x0401ff23, 0x41785800, 0x42006000, 0x0000001e, - 0x42006800, 0x00000014, 0x0401ff17, 0x0401ff22, - 0x40400000, 0x82000540, 0x00000040, 0x4c000000, - 0x41785800, 0x42006000, 0x0000001e, 0x42006800, - 0x00000014, 0x0401ff0c, 0x5c000000, 0x40006800, - 0x0401ff0f, 0x41785800, 0x42006000, 0x0000001e, - 0x42006800, 0x00000014, 0x0401ff03, 0x0401ff0e, - 0x40400000, 0x82000500, 0x0000ffbf, 0x4c000000, - 0x41785800, 0x42006000, 0x0000001e, 0x42006800, - 0x00000014, 0x0401fef8, 0x5c000000, 0x40006800, - 0x0401fefb, 0x4a038886, 0x00002020, 0x0401f04c, - 0x480bc857, 0x82080580, 0x00010000, 0x04020007, - 0x82040d40, 0x00010000, 0x42001800, 0x00000001, - 0x0401f82d, 0x0401f00f, 0x82080580, 0x00008000, - 0x04000007, 0x82040d40, 0x00000000, 0x42001800, - 0x00900001, 0x0401f824, 0x0401f006, 0x82040d40, - 0x00008000, 0x42001800, 0x00100001, 0x0401f81e, - 0x1c01f000, 0x480bc857, 0x82080580, 0x00010000, - 0x04020008, 0x42001800, 0x000000a1, 0x0401f816, - 0x42001800, 0x000000c1, 0x0401f813, 0x0401f011, - 0x82080580, 0x00008000, 0x04000008, 0x42001800, - 0x000400a1, 0x0401f80c, 0x42001800, 0x002000c1, - 0x0401f809, 0x0401f007, 0x42001800, 0x000400a1, - 0x0401f805, 0x42001800, 0x000000c1, 0x0401f802, - 0x1c01f000, 0x480fc857, 0x41785800, 0x42006000, - 0x0000001e, 0x41786800, 0x0401feb7, 0x400c6800, - 0x80346960, 0x0401feba, 0x42006800, 0x00000001, - 0x0401feb1, 0x400c6800, 0x0401feb5, 0x42006800, - 0x00000003, 0x0401feac, 0x0401feb7, 0x40400000, - 0x8c000504, 0x040207fc, 0x1c01f000, 0x42000000, - 0x00000064, 0x80000040, 0x040207ff, 0x1c01f000, - 0x4c5c0000, 0x4c600000, 0x4178b800, 0x0201f800, - 0x0010473b, 0x040200fd, 0x59a8c026, 0x0201f800, - 0x00104e0d, 0x04000003, 0x8c60c506, 0x0400000e, - 0x8c60c500, 0x04020004, 0x8c60c50e, 0x040008f6, - 0x0401f0f2, 0x0401faaf, 0x040200f0, 0x0201f800, - 0x00104e0d, 0x04020004, 0x4a03501c, 0x0000ffff, - 0x0401f0ea, 0x8c60c504, 0x04000004, 0x4a03501c, - 0x0000ffff, 0x0401f0e5, 0x59a8c010, 0x8260c500, - 0x000000ff, 0x59a81013, 0x8c081500, 0x0400005d, - 0x8c081502, 0x0402005b, 0x59a8b81c, 0x825c0d80, - 0x0000ffff, 0x04020003, 0x4200b800, 0x00000001, - 0x805c1104, 0x82086400, 0x0010bc20, 0x50300800, - 0x825c0500, 0x00000003, 0x0c01f001, 0x00101c2c, - 0x00101c27, 0x00101c2b, 0x00101c29, 0x80040910, - 0x0401f004, 0x80040930, 0x0401f002, 0x80040920, - 0x82040500, 0x000000ff, 0x82000d80, 0x000000ff, - 0x0400000f, 0x4c000000, 0x82000400, 0x00101eb5, - 0x50000800, 0x80040910, 0x82040580, 0x00000080, - 0x5c000000, 0x04000030, 0x80600d80, 0x0400002e, - 0x80000540, 0x0400002c, 0x0401f00b, 0x59a81005, - 0x82081500, 0x00000003, 0x0402002b, 0x59a81013, - 0x84081542, 0x480b5013, 0x4a03501c, 0x0000ffff, - 0x0401f028, 0x4c000000, 0x59a8006f, 0x8c000502, - 0x42001000, 0x00000010, 0x02020800, 0x00104ada, - 0x5c000000, 0x0402001c, 0x417a8800, 0x0201f800, - 0x001059b9, 0x04020016, 0x0201f800, 0x0010443b, - 0x04000006, 0x0201f800, 0x00104acf, 0x0401f8b1, - 0x0400000f, 0x0401f00c, 0x599c0019, 0x8c00050e, - 0x04020009, 0x0201f800, 0x001043fc, 0x04020008, - 0x0201f800, 0x00104acf, 0x0401f9dd, 0x0401f8be, - 0x04000003, 0x805cb800, 0x0401f7b2, 0x485f501c, - 0x0401f086, 0x4a03501c, 0x0000ffff, 0x0401f083, - 0x42003000, 0x0000007e, 0x59a8001c, 0x82001580, - 0x0000ffff, 0x04020005, 0x80000d80, 0x4018b000, - 0x4803c856, 0x0401f009, 0x8018b480, 0x04001004, - 0x40000800, 0x4803c856, 0x0401f004, 0x4a03501c, - 0x0000ffff, 0x0401f071, 0x4c040000, 0x4c580000, - 0x82040400, 0x00101eb5, 0x50000000, 0x82000500, - 0x000000ff, 0x80604580, 0x0400005c, 0x0201f800, - 0x001059ba, 0x04020061, 0x59a8006f, 0x8c000502, - 0x42001000, 0x00000010, 0x02020800, 0x00104ada, - 0x5c00b000, 0x5c000800, 0x040207d7, 0x4c040000, - 0x4c580000, 0x845cbd00, 0x0201f800, 0x00020267, - 0x04000008, 0x599c0019, 0x8c00050e, 0x04020047, - 0x0201f800, 0x00104401, 0x0402004c, 0x0401f002, - 0x845cbd40, 0x0201f800, 0x00104acf, 0x0201f800, - 0x00104836, 0x04020007, 0x59a80005, 0x8c000502, - 0x04000033, 0x59340200, 0x8c00050e, 0x04020030, - 0x59a81013, 0x8c081502, 0x04000025, 0x0201f800, - 0x00104858, 0x04000031, 0x8c5cbd00, 0x04020004, - 0x0201f800, 0x00104455, 0x0401f02c, 0x0401f9c8, - 0x0400002a, 0x42026000, 0x0010bbe8, 0x49366009, - 0x497a6008, 0x417a7800, 0x0401f920, 0x42000000, - 0x0010b663, 0x0201f800, 0x0010a86e, 0x0201f800, - 0x0010393e, 0x0400001d, 0x41782800, 0x42003000, - 0x00000008, 0x4d400000, 0x4d440000, 0x59368c03, - 0x42028000, 0x00000029, 0x0201f800, 0x0010a258, - 0x5c028800, 0x5c028000, 0x0401f010, 0x4937c857, - 0x599c0019, 0x8c00050e, 0x0402000c, 0x0401f968, - 0x0401f849, 0x04000011, 0x0401f008, 0x59a80013, - 0x8c000500, 0x04000003, 0x0401f9a1, 0x04000003, - 0x0401f828, 0x04000009, 0x5c00b000, 0x5c000800, - 0x80040800, 0x8058b040, 0x04020798, 0x4a03501c, - 0x0000ffff, 0x0401f005, 0x4937c857, 0x5c00b000, - 0x5c000800, 0x4807501c, 0x5c00c000, 0x5c00b800, - 0x1c01f000, 0x4803c856, 0x4a03501c, 0x00000001, - 0x42028800, 0x000007fe, 0x42003000, 0x00fffffe, - 0x0201f800, 0x001043fc, 0x0402000c, 0x0401f944, - 0x0401f825, 0x04000009, 0x59a80026, 0x8400054e, - 0x48035026, 0x0201f800, 0x001090d5, 0x82000540, - 0x00000001, 0x1c01f000, 0x80000580, 0x0401f7fe, - 0x4937c857, 0x0201f800, 0x001076c9, 0x04000015, - 0x49366009, 0x4a026406, 0x00000001, 0x417a7800, - 0x0201f800, 0x001043bd, 0x59a8001b, 0x80000000, - 0x4803501b, 0x42027000, 0x00000004, 0x599c0019, - 0x8c00050e, 0x04000003, 0x42027000, 0x00000000, - 0x0201f800, 0x000208d8, 0x82000540, 0x00000001, - 0x1c01f000, 0x4937c857, 0x0201f800, 0x001076c9, - 0x0400001c, 0x49366009, 0x59340403, 0x82000580, - 0x000007fe, 0x04000005, 0x4d3c0000, 0x417a7800, - 0x0401f8b2, 0x5c027800, 0x4a026406, 0x00000001, - 0x417a7800, 0x0201f800, 0x001043bd, 0x42000800, - 0x00000003, 0x0201f800, 0x001043c7, 0x59a8001b, - 0x80000000, 0x4803501b, 0x42027000, 0x00000002, - 0x0201f800, 0x000208d8, 0x82000540, 0x00000001, - 0x1c01f000, 0x4803c856, 0x42028800, 0x000007fc, - 0x42003000, 0x00fffffc, 0x0201f800, 0x001043fc, - 0x04020005, 0x0401f805, 0x04000003, 0x4a035027, - 0x0000ffff, 0x1c01f000, 0x4937c857, 0x0201f800, - 0x001076c9, 0x04000014, 0x49366009, 0x4a026406, - 0x00000001, 0x417a7800, 0x0201f800, 0x001043bd, - 0x42000800, 0x00000003, 0x0201f800, 0x001043c7, - 0x59a80028, 0x80000000, 0x48035028, 0x42027000, - 0x00000002, 0x0201f800, 0x000208d8, 0x82000540, - 0x00000001, 0x1c01f000, 0x480bc857, 0x492fc857, - 0x4c5c0000, 0x4008b800, 0x42028800, 0x000007fd, - 0x42003000, 0x00fffffd, 0x0201f800, 0x001043fc, - 0x0402001a, 0x0201f800, 0x00020892, 0x04000017, - 0x49366009, 0x5934000a, 0x84000544, 0x4802680a, - 0x812e59c0, 0x04000005, 0x592c0404, 0x8c00051e, - 0x04000002, 0x48ee6021, 0x492e6008, 0x4a026406, - 0x00000001, 0x485e601c, 0x42027000, 0x00000022, - 0x0201f800, 0x000208d8, 0x82000540, 0x00000001, - 0x5c00b800, 0x1c01f000, 0x80000580, 0x0401f7fd, - 0x5c000000, 0x4c000000, 0x4803c857, 0x4943c857, - 0x493fc857, 0x4d340000, 0x4d440000, 0x4c580000, - 0x4d2c0000, 0x4c5c0000, 0x0201f800, 0x0010698c, - 0x4df00000, 0x0201f800, 0x0010673a, 0x0201f800, - 0x001067ee, 0x0201f800, 0x0010647f, 0x0201f800, - 0x0010822b, 0x5c03e000, 0x02000800, 0x00106982, - 0x4200b000, 0x000007f0, 0x417a8800, 0x0201f800, - 0x00020267, 0x0402001a, 0x8d3e7d06, 0x04000004, - 0x59340200, 0x8c00050e, 0x04020015, 0x8d3e7d18, - 0x04000010, 0x5934b80f, 0x805cb9c0, 0x04000009, - 0x49425a06, 0x592cb800, 0x0201f800, 0x00020381, - 0x805cb9c0, 0x040207fb, 0x497a680f, 0x497a6810, - 0x4937c857, 0x4a026c00, 0x00000707, 0x0401f004, - 0x4937c857, 0x0201f800, 0x001040e4, 0x81468800, - 0x8058b040, 0x040207e2, 0x8d3e7d02, 0x04000011, - 0x497b501d, 0x42028800, 0x000007f0, 0x4200b000, - 0x00000010, 0x0201f800, 0x00020267, 0x04020006, - 0x4937c857, 0x4a026c00, 0x00000707, 0x0201f800, - 0x001040e4, 0x81468800, 0x8058b040, 0x040207f6, - 0x5c00b800, 0x5c025800, 0x5c00b000, 0x5c028800, - 0x5c026800, 0x1c01f000, 0x5c000000, 0x4c000000, - 0x4803c857, 0x4933c857, 0x493fc857, 0x4d340000, - 0x4d400000, 0x4d440000, 0x4d2c0000, 0x4c5c0000, - 0x0201f800, 0x0010698c, 0x4df00000, 0x59326809, - 0x813669c0, 0x04000021, 0x59368c03, 0x42028000, - 0x00000029, 0x0201f800, 0x0010679b, 0x0201f800, - 0x001067f6, 0x0201f800, 0x00106543, 0x0201f800, - 0x0010a0da, 0x4937c857, 0x8d3e7d18, 0x04000011, - 0x5934b80f, 0x805cb9c0, 0x0400000a, 0x405e5800, - 0x49425a06, 0x592cb800, 0x0201f800, 0x00020381, - 0x805cb9c0, 0x040207fa, 0x497a680f, 0x497a6810, - 0x4937c857, 0x4a026c00, 0x00000707, 0x0401f003, - 0x0201f800, 0x001040e4, 0x5c03e000, 0x02000800, - 0x00106982, 0x5c00b800, 0x5c025800, 0x5c028800, - 0x5c028000, 0x5c026800, 0x1c01f000, 0x4933c857, - 0x59a80026, 0x8c000508, 0x04020012, 0x59305009, - 0x482bc857, 0x836c0580, 0x00000002, 0x0402000d, - 0x0401f813, 0x0402000b, 0x58280403, 0x82000580, - 0x000007fc, 0x04000008, 0x59a8001b, 0x80000040, - 0x4803c857, 0x02001800, 0x00100615, 0x4803501b, - 0x1c01f000, 0x59a80028, 0x80000040, 0x4803c857, - 0x040017fc, 0x48035028, 0x1c01f000, 0x59300008, - 0x800001c0, 0x04020009, 0x59300403, 0x82000580, - 0x00000001, 0x04020004, 0x82000540, 0x00000001, - 0x0401f002, 0x80000580, 0x1c01f000, 0x4937c857, - 0x59340200, 0x84000502, 0x48026a00, 0x1c01f000, - 0x4933c857, 0x493fc857, 0x4947c857, 0x4d400000, - 0x4d340000, 0x4d440000, 0x4c580000, 0x0201f800, - 0x0010698c, 0x4df00000, 0x8060c1c0, 0x04020004, - 0x4200b000, 0x00000001, 0x0401f004, 0x4200b000, - 0x000007f0, 0x417a8800, 0x41440000, 0x81ac0400, - 0x50000000, 0x80026d40, 0x0400001a, 0x4d3c0000, - 0x42027800, 0x00000001, 0x0201f800, 0x00104745, - 0x5c027800, 0x42028000, 0x00000029, 0x0201f800, - 0x0010679b, 0x0201f800, 0x001067f6, 0x0201f800, - 0x00106543, 0x0201f800, 0x00104836, 0x04020005, - 0x4937c857, 0x4a026c00, 0x00000404, 0x0401f003, - 0x0201f800, 0x00104863, 0x0201f800, 0x0010a0da, - 0x81468800, 0x8058b040, 0x040207e0, 0x5c03e000, - 0x02000800, 0x00106982, 0x5c00b000, 0x5c028800, - 0x5c026800, 0x5c028000, 0x1c01f000, 0x4937c857, - 0x4947c857, 0x4c5c0000, 0x4c600000, 0x4c640000, - 0x59a80013, 0x8c000500, 0x0400001f, 0x599c0017, - 0x8c00050a, 0x0402001c, 0x5934ba02, 0x825cbd00, - 0x000000ff, 0x485fc857, 0x4178c000, 0x4178c800, - 0x82600400, 0x0010bc20, 0x50002000, 0x8060c1c0, - 0x04000008, 0x82100500, 0x000000ff, 0x82002d80, - 0x000000ff, 0x0400000c, 0x805c0580, 0x0400000d, - 0x80102110, 0x8064c800, 0x82640580, 0x00000004, - 0x040207f5, 0x8060c000, 0x82600580, 0x00000020, - 0x040207eb, 0x4813c857, 0x82000540, 0x00000001, - 0x5c00c800, 0x5c00c000, 0x5c00b800, 0x1c01f000, - 0x59a80026, 0x8c000512, 0x02020800, 0x001006ba, - 0x1c01f000, 0x00007eef, 0x00007de8, 0x00007ce4, - 0x000080e2, 0x00007be1, 0x000080e0, 0x000080dc, - 0x000080da, 0x00007ad9, 0x000080d6, 0x000080d5, - 0x000080d4, 0x000080d3, 0x000080d2, 0x000080d1, - 0x000079ce, 0x000078cd, 0x000080cc, 0x000080cb, - 0x000080ca, 0x000080c9, 0x000080c7, 0x000080c6, - 0x000077c5, 0x000076c3, 0x000080bc, 0x000080ba, - 0x000075b9, 0x000080b6, 0x000074b5, 0x000073b4, - 0x000072b3, 0x000080b2, 0x000080b1, 0x000080ae, - 0x000071ad, 0x000080ac, 0x000070ab, 0x00006faa, - 0x00006ea9, 0x000080a7, 0x00006da6, 0x00006ca5, - 0x00006ba3, 0x00006a9f, 0x0000699e, 0x0000689d, - 0x0000809b, 0x00008098, 0x00006797, 0x00006690, - 0x0000658f, 0x00006488, 0x00006384, 0x00006282, - 0x00008081, 0x00008080, 0x0000617c, 0x0000607a, - 0x00008079, 0x00005f76, 0x00008075, 0x00008074, - 0x00008073, 0x00008072, 0x00008071, 0x0000806e, - 0x00005e6d, 0x0000806c, 0x00005d6b, 0x00005c6a, - 0x00005b69, 0x00008067, 0x00005a66, 0x00005965, - 0x00005863, 0x0000575c, 0x0000565a, 0x00005559, - 0x00008056, 0x00008055, 0x00005454, 0x00005353, - 0x00005252, 0x00005151, 0x0000504e, 0x00004f4d, - 0x0000804c, 0x0000804b, 0x00004e4a, 0x00004d49, - 0x00008047, 0x00004c46, 0x00008045, 0x00008043, - 0x0000803c, 0x0000803a, 0x00008039, 0x00008036, - 0x00004b35, 0x00008034, 0x00004a33, 0x00004932, - 0x00004831, 0x0000802e, 0x0000472d, 0x0000462c, - 0x0000452b, 0x0000442a, 0x00004329, 0x00004227, - 0x00008026, 0x00008025, 0x00004123, 0x0000401f, - 0x00003f1e, 0x00003e1d, 0x00003d1b, 0x00003c18, - 0x00008017, 0x00008010, 0x00003b0f, 0x00003a08, - 0x00008004, 0x00003902, 0x00008001, 0x00008000, - 0x00008000, 0x00003800, 0x00003700, 0x00003600, - 0x00008000, 0x00003500, 0x00008000, 0x00008000, - 0x00008000, 0x00003400, 0x00008000, 0x00008000, - 0x00008000, 0x00008000, 0x00008000, 0x00008000, - 0x00003300, 0x00003200, 0x00008000, 0x00008000, - 0x00008000, 0x00008000, 0x00008000, 0x00008000, - 0x00003100, 0x00003000, 0x00008000, 0x00008000, - 0x00002f00, 0x00008000, 0x00002e00, 0x00002d00, - 0x00002c00, 0x00008000, 0x00008000, 0x00008000, - 0x00002b00, 0x00008000, 0x00002a00, 0x00002900, - 0x00002800, 0x00008000, 0x00002700, 0x00002600, - 0x00002500, 0x00002400, 0x00002300, 0x00002200, - 0x00008000, 0x00008000, 0x00002100, 0x00002000, - 0x00001f00, 0x00001e00, 0x00001d00, 0x00001c00, - 0x00008000, 0x00008000, 0x00001b00, 0x00001a00, - 0x00008000, 0x00001900, 0x00008000, 0x00008000, - 0x00008000, 0x00008000, 0x00008000, 0x00008000, - 0x00001800, 0x00008000, 0x00001700, 0x00001600, - 0x00001500, 0x00008000, 0x00001400, 0x00001300, - 0x00001200, 0x00001100, 0x00001000, 0x00000f00, - 0x00008000, 0x00008000, 0x00000e00, 0x00000d00, - 0x00000c00, 0x00000b00, 0x00000a00, 0x00000900, - 0x00008000, 0x00008000, 0x00000800, 0x00000700, - 0x00008000, 0x00000600, 0x00008000, 0x00008000, - 0x00008000, 0x00000500, 0x00000400, 0x00000300, - 0x00008000, 0x00000200, 0x00008000, 0x00008000, - 0x00008000, 0x00000100, 0x00008000, 0x00008000, - 0x00008000, 0x00008000, 0x00008000, 0x00008000, - 0x00000000, 0x00008000, 0x00008000, 0x00008000, - 0x00008000, 0x00008000, 0x00008000, 0x00008000, - 0x00008000, 0x00008000, 0x00008000, 0x00008000, - 0x00008000, 0x00008000, 0x00008000, 0x00008000, - 0x00008000, 0x0201f800, 0x00100819, 0x02000800, - 0x00100615, 0x492f4016, 0x1c01f000, 0x83a0ac00, - 0x00000006, 0x83a00580, 0x0010b2a0, 0x0400000c, - 0x492fc857, 0x812e59c0, 0x02000800, 0x00100615, - 0x832ca400, 0x00000006, 0x4200b000, 0x0000000d, - 0x0201f800, 0x0010a93e, 0x0401f00f, 0x4200b000, - 0x00000010, 0x83e0a400, 0x00000020, 0x50500000, - 0x8050a000, 0x50500800, 0x900409c0, 0x80040540, - 0x4400a800, 0x8050a000, 0x8054a800, 0x8058b040, - 0x040207f7, 0x1c01f000, 0x59a00206, 0x82000c80, - 0x0000007f, 0x040210c9, 0x59a80821, 0x0c01f001, - 0x00102066, 0x001020a6, 0x001020a6, 0x001020f0, - 0x00102112, 0x001020a6, 0x00102066, 0x00102134, - 0x00102145, 0x001020a6, 0x001020a6, 0x00102152, - 0x0010216a, 0x00102182, 0x001020a6, 0x001021b1, - 0x001021e3, 0x001020a6, 0x0010220c, 0x001020a6, - 0x00102269, 0x001020a6, 0x001020a6, 0x001020a6, - 0x001020a6, 0x00102280, 0x001022b9, 0x001020a6, - 0x001020a6, 0x001020a6, 0x001020a6, 0x001020a6, - 0x001022ee, 0x001020a6, 0x00102340, 0x001020a6, - 0x001020a6, 0x001020a6, 0x001020a6, 0x00102345, - 0x001023be, 0x001020a6, 0x001023c5, 0x001020a6, - 0x001020a6, 0x001020a6, 0x001020a6, 0x001020a6, - 0x001023c7, 0x00102445, 0x00102585, 0x001020a6, - 0x001020a6, 0x001020a6, 0x001020a6, 0x001020a6, - 0x00102594, 0x001020a6, 0x001020a6, 0x001020a6, - 0x001020a6, 0x001020a6, 0x001020a6, 0x001020a6, - 0x001025b1, 0x00102604, 0x00102660, 0x00102674, - 0x00102696, 0x001028d1, 0x00102c60, 0x001020a6, - 0x001020a6, 0x001020a6, 0x001020a6, 0x001020a6, - 0x001020a6, 0x001020a6, 0x001020a6, 0x001020a6, - 0x001020a6, 0x001020a6, 0x001020a6, 0x00102d9f, - 0x00102e13, 0x001020a6, 0x001020a6, 0x00102e81, - 0x001020a6, 0x00102f1f, 0x00102fd1, 0x001020a6, - 0x001020a6, 0x00103008, 0x00103064, 0x001020a6, - 0x001030bc, 0x00103220, 0x001020a6, 0x00103234, - 0x001032bf, 0x001020a6, 0x001020a6, 0x001020a6, - 0x001020a6, 0x0010332f, 0x00103333, 0x00103352, - 0x001020a6, 0x001033f4, 0x001020a6, 0x001020a6, - 0x00103421, 0x001020a6, 0x0010344f, 0x001020a6, - 0x001020a6, 0x001034b6, 0x001035c3, 0x00103620, - 0x001020a6, 0x00103686, 0x001020a6, 0x001020a6, - 0x001036db, 0x0010373e, 0x001020a6, 0x48efc857, - 0x4031d800, 0x58ef400b, 0x58ec0002, 0x82000580, - 0x00000200, 0x04000045, 0x48efc857, 0x4a034206, - 0x00004000, 0x0201f800, 0x0010382f, 0x83a00580, - 0x0010b2a0, 0x0400000d, 0x58ee580a, 0x4d2c0000, - 0x0401f856, 0x41a25800, 0x0201f800, 0x0010083a, - 0x40ee5800, 0x0201f800, 0x0010083a, 0x5c025800, - 0x0201f000, 0x00020381, 0x04026007, 0x59a0001d, - 0x84000542, 0x4803401d, 0x4a01d809, 0x0010207a, - 0x1c01f000, 0x59a00206, 0x82000d80, 0x00004000, - 0x04000006, 0x900001c0, 0x82000540, 0x00000011, - 0x4803c011, 0x0401f005, 0x900001c0, 0x82000540, - 0x00000010, 0x4803c011, 0x0401f844, 0x59e00017, - 0x8c000508, 0x0402000c, 0x4203e000, 0x30000001, - 0x4203e000, 0x40000000, 0x40ee5800, 0x0201f800, - 0x0010083a, 0x59a0001d, 0x84000504, 0x4803401d, - 0x1c01f000, 0x4a03c017, 0x00000000, 0x59a00206, - 0x82000d80, 0x00004000, 0x040007f0, 0x4a03c017, - 0x00000001, 0x0401f7ed, 0x4803c856, 0x4a034206, - 0x00004001, 0x0401f7c0, 0x4803c856, 0x4a034206, - 0x00004002, 0x0401f7bc, 0x4803c856, 0x4a034206, - 0x00004003, 0x0401f7b8, 0x4803c856, 0x4a034206, - 0x00004005, 0x0401f7b4, 0x4803c856, 0x4a034206, - 0x00004006, 0x0401f7b0, 0x4803c856, 0x4a034206, - 0x0000400b, 0x0401f7ac, 0x4803c856, 0x4a034206, - 0x0000400c, 0x0401f7a8, 0x4803c856, 0x4a034206, - 0x0000400c, 0x0401f7a4, 0x58eca80a, 0x8054a9c0, - 0x02000800, 0x00100615, 0x83a0a400, 0x00000006, - 0x8254ac00, 0x00000006, 0x4200b000, 0x0000000d, - 0x0201f000, 0x0010a93e, 0x59a00206, 0x4803c857, - 0x59a00406, 0x4803c857, 0x59a00207, 0x4803c857, - 0x59a00407, 0x4803c857, 0x59a00208, 0x4803c857, - 0x59a00408, 0x4803c857, 0x59a00209, 0x4803c857, - 0x83e0ac00, 0x00000020, 0x83a0a400, 0x00000006, - 0x4200b000, 0x00000010, 0x50500000, 0x4400a800, - 0x8054a800, 0x900001c0, 0x4400a800, 0x8054a800, - 0x8050a000, 0x8058b040, 0x040207f8, 0x1c01f000, - 0x59a00406, 0x800000c2, 0x59a00a07, 0x900409c0, - 0x80040540, 0x84000540, 0x59a00c07, 0x8c040d00, - 0x04000018, 0x59a8086f, 0x8c040d00, 0x040207bb, - 0x42000800, 0x00000064, 0x80040840, 0x04000007, - 0x4a030000, 0x00000001, 0x40000000, 0x59801000, - 0x8c081500, 0x040007f9, 0x04000005, 0x48030004, - 0x4a030000, 0x00000000, 0x0401f75c, 0x4a030000, - 0x00000000, 0x4a034406, 0x00000004, 0x040007a3, - 0x4803880e, 0x0401f755, 0x59a00406, 0x800000c2, - 0x59a00c07, 0x8c040d00, 0x0400001a, 0x59a8086f, - 0x8c040d00, 0x0402079d, 0x42000800, 0x00000064, - 0x80040840, 0x04000007, 0x4a030000, 0x00000001, - 0x40000000, 0x59801000, 0x8c081500, 0x040007f9, - 0x04000007, 0x48030004, 0x59800805, 0x48074406, - 0x4a030000, 0x00000000, 0x0401f73c, 0x4a030000, - 0x00000000, 0x4a034406, 0x00000004, 0x04000783, - 0x4803880e, 0x59c4080f, 0x48074406, 0x0401f733, - 0x59a01c06, 0x59a00207, 0x900c19c0, 0x800c1d40, - 0x580c0803, 0x80000580, 0x500c1000, 0x80080400, - 0x800c1800, 0x80040840, 0x040207fc, 0x48034406, - 0x900001c0, 0x48034207, 0x800001c0, 0x04000723, - 0x0401f76a, 0x4a034406, 0x00000004, 0x4a034207, - 0x00000000, 0x4a034407, 0x00000012, 0x59a8000d, - 0x48034208, 0x900001c0, 0x48034408, 0x4a034209, - 0x00000002, 0x0401f715, 0x59a00407, 0x59a01207, - 0x900811c0, 0x80081540, 0x59a00409, 0x59a01a09, - 0x900c19c0, 0x800c1d40, 0x59a00a08, 0x59a00408, - 0x900409c0, 0x80040d40, 0x59a0020a, 0x82002480, - 0x00000010, 0x04001755, 0x59a02406, 0x900001c0, - 0x80100540, 0x59a8280d, 0x80142480, 0x0400174f, - 0x0201f000, 0x0010383e, 0x59a00407, 0x59a01207, - 0x900811c0, 0x80081540, 0x59a00409, 0x59a01a09, - 0x900c19c0, 0x800c1d40, 0x59a00a08, 0x59a00408, - 0x900409c0, 0x80040d40, 0x59a0020a, 0x82002480, - 0x00000010, 0x0400173d, 0x59a02406, 0x900001c0, - 0x80100540, 0x59a8280d, 0x80142480, 0x04001737, - 0x0201f000, 0x00103841, 0x59a02407, 0x59a00207, - 0x901021c0, 0x80102540, 0x59a01a0a, 0x59a00406, - 0x900c19c0, 0x800c1d40, 0x41781000, 0x42000000, - 0x00001000, 0x50000000, 0x82000480, 0x24320001, - 0x04001016, 0x820c0580, 0x00007c00, 0x04000013, - 0x820c0480, 0x00007a00, 0x04001010, 0x820c0480, - 0x00007cff, 0x0402100d, 0x42000800, 0x00000064, - 0x80040840, 0x04000007, 0x4a030000, 0x00000001, - 0x40000000, 0x59800000, 0x8c000500, 0x040007f9, - 0x04000008, 0x80081000, 0x44101800, 0x800811c0, - 0x040006be, 0x4a030000, 0x00000000, 0x0401f6bb, - 0x4a030000, 0x00000000, 0x4a034406, 0x00000004, - 0x0401f702, 0x59a01a0a, 0x59a00406, 0x900c19c0, - 0x800c1d40, 0x41781000, 0x42000000, 0x00001000, - 0x50000000, 0x82000480, 0x24320001, 0x04001016, - 0x820c0580, 0x00007c00, 0x04000013, 0x820c0480, - 0x00007a00, 0x04001010, 0x820c0480, 0x00007cff, - 0x0402100d, 0x42000800, 0x00000064, 0x80040840, - 0x04000007, 0x4a030000, 0x00000001, 0x40000000, - 0x59800000, 0x8c000500, 0x040007f9, 0x0400000f, - 0x80081000, 0x500c0000, 0x82000d00, 0x0000ffff, - 0x48074207, 0x82000d00, 0xffff0000, 0x900409c0, - 0x48074407, 0x800811c0, 0x0400068c, 0x4a030000, - 0x00000000, 0x0401f689, 0x4a030000, 0x00000000, - 0x4a034406, 0x00000004, 0x0401f6d0, 0x59a00406, - 0x8c000500, 0x04000020, 0x59a01207, 0x59a01c07, - 0x59a02208, 0x480b5054, 0x480f5055, 0x48135056, - 0x59c40801, 0x82040d00, 0x00018000, 0x82040580, - 0x00000000, 0x04000009, 0x82040580, 0x00008000, - 0x04000008, 0x82040580, 0x00010000, 0x04000007, - 0x0201f800, 0x00100615, 0x40080000, 0x0401f004, - 0x400c0000, 0x0401f002, 0x40100000, 0x80000110, - 0x42000800, 0x000000e0, 0x0201f800, 0x001019b1, - 0x0401f007, 0x59a81054, 0x59a81855, 0x59a82056, - 0x480b4207, 0x480f4407, 0x48134208, 0x0401f65b, - 0x4d2c0000, 0x4d340000, 0x4d300000, 0x4d440000, - 0x59a28c06, 0x0201f800, 0x00020267, 0x04000006, - 0x5c028800, 0x5c026000, 0x5c026800, 0x5c025800, - 0x0401f69e, 0x59a04407, 0x59a00207, 0x900001c0, - 0x80204540, 0x0401f81e, 0x04000009, 0x4a034208, - 0x00000001, 0x4a034406, 0x0000ffff, 0x4a034207, - 0x0000ffff, 0x497b4407, 0x0401f00b, 0x0401f822, - 0x0400000e, 0x4a034208, 0x00000002, 0x59300402, - 0x48034406, 0x59300202, 0x48034207, 0x59300206, - 0x48034407, 0x5c028800, 0x5c026000, 0x5c026800, - 0x5c025800, 0x0401f631, 0x5c028800, 0x5c026000, - 0x5c026800, 0x5c025800, 0x0401f678, 0x4937c856, - 0x4823c856, 0x4d2c0000, 0x5934000f, 0x80025d40, - 0x04000007, 0x592c0005, 0x80200580, 0x592c0000, - 0x040207fb, 0x82000540, 0x00000001, 0x5c025800, - 0x1c01f000, 0x4823c857, 0x4d2c0000, 0x4d300000, - 0x42026000, 0x0010cfc0, 0x59300406, 0x82000d80, - 0x00000003, 0x04000004, 0x82000d80, 0x00000006, - 0x04020007, 0x59325808, 0x812e59c0, 0x04000004, - 0x592c0005, 0x80200580, 0x0400000a, 0x83326400, - 0x00000024, 0x41580000, 0x81300480, 0x040017ef, - 0x80000580, 0x5c026000, 0x5c025800, 0x1c01f000, - 0x82000540, 0x00000001, 0x5c026000, 0x5c025800, - 0x1c01f000, 0x83a00580, 0x0010b2a0, 0x0402063b, - 0x59a8006f, 0x8c000500, 0x04020003, 0x4a030000, - 0x00000000, 0x4a034206, 0x00004000, 0x4a03c011, - 0x40000010, 0x0401fe5d, 0x59e00017, 0x8c000508, - 0x04000003, 0x4a03c017, 0x00000000, 0x4203e000, - 0x30000001, 0x4203e000, 0x40000000, 0x0401f000, - 0x59a00c06, 0x800409c0, 0x04000007, 0x836c0580, - 0x00000000, 0x04000004, 0x4a034406, 0x0000001a, - 0x0401f62a, 0x42007000, 0x0010b33f, 0x58381c01, - 0x58382202, 0x8c040d00, 0x0400000b, 0x59a01207, - 0x82080500, 0x0000f003, 0x04020624, 0x82080480, - 0x00000841, 0x04021621, 0x82080480, 0x00000100, - 0x0400161e, 0x8c040d06, 0x04000003, 0x4a0378e4, - 0x000c0000, 0x8c040d04, 0x0400000c, 0x42000000, - 0x00001000, 0x50000000, 0x82000480, 0x24220001, - 0x04020003, 0x84040d04, 0x0401f004, 0x59e00002, - 0x84000548, 0x4803c002, 0x8c040d02, 0x04000005, - 0x42002800, 0x00007600, 0x4a002805, 0xd0000000, - 0x40040000, 0x800c0540, 0x48007401, 0x8c040d00, - 0x04000002, 0x48087202, 0x480f4406, 0x48134207, - 0x0401f5ae, 0x4d440000, 0x4d340000, 0x59a28c06, - 0x0201f800, 0x00020267, 0x04020009, 0x0201f800, - 0x00104842, 0x04000009, 0x4a034406, 0x00000009, - 0x5c026800, 0x5c028800, 0x0401f5ec, 0x5c026800, - 0x5c028800, 0x0401f5ed, 0x59a01207, 0x59a01c07, - 0x5934400a, 0x82203d00, 0x0000e000, 0x801c391a, - 0x8c081500, 0x04000019, 0x820c0d00, 0x00000007, - 0x82040580, 0x00000000, 0x04000007, 0x82040580, - 0x00000001, 0x04000004, 0x82040580, 0x00000003, - 0x040207eb, 0x82204500, 0xffff1fff, 0x800400da, - 0x80200540, 0x4802680a, 0x4c1c0000, 0x0201f800, - 0x0010698c, 0x0201f800, 0x00104afd, 0x0201f800, - 0x00106982, 0x5c003800, 0x481f4407, 0x5c026800, - 0x5c028800, 0x0401f579, 0x800409c0, 0x04000004, - 0x4a034406, 0x00000001, 0x0401f5c0, 0x836c0580, - 0x00000003, 0x04020010, 0x59a80010, 0x497b4406, - 0x0201f800, 0x00104e0d, 0x0400000f, 0x82000d00, - 0x00ffff00, 0x0402000c, 0x82000c00, 0x00101eb5, - 0x50040800, 0x80040910, 0x82041580, 0x00000080, - 0x04020004, 0x4a034406, 0x00000007, 0x0401f5ab, - 0x48074406, 0x82000d00, 0x0000ffff, 0x48074207, - 0x80000120, 0x48034407, 0x59a80026, 0x82001500, - 0x00000100, 0x480b4409, 0x8c000502, 0x0400001f, - 0x8c000506, 0x04000009, 0x82000d00, 0x0000000a, - 0x82040d80, 0x0000000a, 0x04020004, 0x4a034209, - 0x00000001, 0x0401f022, 0x8c00050a, 0x04000009, - 0x82000d00, 0x00000022, 0x82040d80, 0x00000022, - 0x04020004, 0x4a034209, 0x00000003, 0x0401f018, - 0x8c000508, 0x04000009, 0x82000d00, 0x00000012, - 0x82040d80, 0x00000012, 0x04020004, 0x4a034209, - 0x00000002, 0x0401f00e, 0x0201f800, 0x00104e0d, - 0x04020004, 0x4a034209, 0x00000004, 0x0401f52f, - 0x8c000506, 0x04000004, 0x4a034406, 0x00000005, - 0x0401f576, 0x4a034209, 0x00000000, 0x0401f527, - 0x59a80037, 0x48034407, 0x59a80038, 0x48034209, - 0x0401f522, 0x42007800, 0x0010b6eb, 0x59a00406, - 0x4803c857, 0x82000c80, 0x00000007, 0x0402156b, - 0x0c01f001, 0x00102354, 0x00102355, 0x00102363, - 0x00102376, 0x00102397, 0x00102354, 0x00102354, - 0x0401f562, 0x836c0580, 0x00000000, 0x0400055b, - 0x59a00a07, 0x59a00407, 0x900001c0, 0x80040d40, - 0x4807c857, 0x59a00a08, 0x59a00408, 0x900001c0, - 0x80040d40, 0x4807c857, 0x0401f056, 0x836c0580, - 0x00000000, 0x0400054d, 0x59a00407, 0x59a01207, - 0x900001c0, 0x80081540, 0x59a00408, 0x59a01a08, - 0x900001c0, 0x800c1d40, 0x42000000, 0x0010bfbe, - 0x480fc857, 0x480bc857, 0x42000800, 0x00001000, - 0x0201f000, 0x00103841, 0x59a00a07, 0x59a00407, - 0x900001c0, 0x80041d40, 0x820c0c80, 0x0010a971, - 0x0402153a, 0x820c0c80, 0x00100000, 0x04001537, - 0x480fc857, 0x823c7c00, 0x00000009, 0x503c0800, - 0x800409c0, 0x04000006, 0x823c0580, 0x0000000d, - 0x0400052e, 0x803c7800, 0x0401f7f9, 0x59e41001, - 0x82080d00, 0xfffeffcf, 0x4807c801, 0x440c7800, - 0x46001800, 0x0201f800, 0x800c1800, 0x46001800, - 0x00100608, 0x480bc801, 0x0401f022, 0x59a01a07, - 0x59a00407, 0x900001c0, 0x800c1d40, 0x480c7801, - 0x59a02208, 0x59a00408, 0x900001c0, 0x80102540, - 0x48107802, 0x59a00209, 0x80000040, 0x04001513, - 0x48007806, 0x80000000, 0x48007805, 0x42000800, - 0x00004000, 0x40001000, 0x0201f800, 0x001063cf, - 0x80000540, 0x04000003, 0x49787801, 0x0401f507, - 0x40040000, 0x800c1c00, 0x04001504, 0x480c7803, - 0x48107804, 0x49787808, 0x59a00409, 0x48007807, - 0x59e40001, 0x4803c857, 0x82000540, 0x00040000, - 0x4803c801, 0x0401f4a9, 0x59a80006, 0x48034406, - 0x59a80007, 0x48034207, 0x59a80008, 0x48034407, - 0x0401f4a2, 0x0201f800, 0x00100615, 0x4803c856, - 0x4a03c013, 0x03800300, 0x4a03c014, 0x03800380, - 0x59a00c06, 0x82040580, 0x000000a0, 0x04000004, - 0x82040580, 0x000000a2, 0x04020028, 0x59a0140a, - 0x82080480, 0x00000100, 0x04021024, 0x59a0020b, - 0x8c000500, 0x0402002b, 0x59a00a0a, 0x800409c0, - 0x0400001e, 0x82040480, 0x00000041, 0x0402101b, - 0x82040c00, 0x00000003, 0x82040d00, 0x000000fc, - 0x80040904, 0x59a00407, 0x59a01207, 0x900811c0, - 0x80081540, 0x59a00409, 0x59a01a09, 0x900c19c0, - 0x800c1d40, 0x0201f800, 0x0010381a, 0x04020006, - 0x4a034406, 0x00000002, 0x4a03c014, 0x03800000, - 0x0401f4be, 0x0201f800, 0x0010383e, 0x4a01d809, - 0x001023fd, 0x1c01f000, 0x4a03c014, 0x03800000, - 0x0401f4ba, 0x4031d800, 0x58ef400b, 0x58ee580d, - 0x58ec0002, 0x82000580, 0x00000200, 0x040004a7, - 0x59a00c06, 0x59a0140a, 0x59a0020b, 0x8c000500, - 0x04020031, 0x832e5c00, 0x00000004, 0x41783800, - 0x59a04a0a, 0x401c0000, 0x812c0400, 0x50004000, - 0x82201d00, 0x000000ff, 0x4c040000, 0x0401f8af, - 0x5c000800, 0x0400002d, 0x80244840, 0x04000028, - 0x80081000, 0x82201d00, 0x0000ff00, 0x800c1910, - 0x4c040000, 0x0401f8a5, 0x5c000800, 0x04000023, - 0x80244840, 0x0400001e, 0x80081000, 0x82201d00, - 0x00ff0000, 0x800c1920, 0x4c040000, 0x0401f89b, - 0x5c000800, 0x04000019, 0x80244840, 0x04000014, - 0x80081000, 0x82201d00, 0xff000000, 0x800c1930, - 0x4c040000, 0x0401f891, 0x5c000800, 0x0400000f, - 0x80244840, 0x0400000a, 0x80081000, 0x801c3800, - 0x0401f7d5, 0x59a0020a, 0x82000500, 0x000000ff, - 0x40001800, 0x0401f885, 0x04000004, 0x4a03c014, - 0x03800000, 0x0401f425, 0x4a03c014, 0x03800000, - 0x0401f46e, 0x4803c856, 0x4a03c013, 0x03800300, - 0x4a03c014, 0x03800380, 0x59a00c06, 0x82040580, - 0x000000a0, 0x04000004, 0x82040580, 0x000000a2, - 0x0402006e, 0x59a0140a, 0x82080480, 0x00000100, - 0x0402106a, 0x59a0020b, 0x8c000500, 0x0402005c, - 0x59a01a0a, 0x800c19c0, 0x04000064, 0x820c0480, - 0x00000041, 0x04021061, 0x0201f800, 0x0010381a, - 0x04020006, 0x4a034406, 0x00000002, 0x4a03c014, - 0x03800000, 0x0401f44d, 0x832e5c00, 0x00000004, - 0x41783800, 0x59a04a0a, 0x401c0000, 0x812c0400, - 0x40004000, 0x4c040000, 0x4c080000, 0x0401f877, - 0x5c001000, 0x5c000800, 0x04000048, 0x44144000, - 0x80244840, 0x0400002b, 0x80081000, 0x4c040000, - 0x4c080000, 0x0401f86d, 0x5c001000, 0x5c000800, - 0x0400003e, 0x50200000, 0x801428d0, 0x80140540, - 0x44004000, 0x80244840, 0x0400001e, 0x80081000, - 0x4c040000, 0x4c080000, 0x0401f860, 0x5c001000, - 0x5c000800, 0x04000031, 0x50200000, 0x801428e0, - 0x80140540, 0x44004000, 0x80244840, 0x04000011, - 0x80081000, 0x4c040000, 0x4c080000, 0x0401f853, - 0x5c001000, 0x5c000800, 0x04000024, 0x50200000, - 0x801428f0, 0x80140540, 0x44004000, 0x80244840, - 0x04000004, 0x80081000, 0x801c3800, 0x0401f7cb, - 0x59a00a0a, 0x82040c00, 0x00000003, 0x82040d00, - 0x000000fc, 0x80040904, 0x59a00407, 0x59a01207, - 0x900811c0, 0x80081540, 0x59a00409, 0x59a01a09, - 0x900c19c0, 0x800c1d40, 0x4a03c014, 0x03800000, - 0x412c0000, 0x0201f000, 0x00103841, 0x0401f833, - 0x04000006, 0x48174406, 0x4a03c014, 0x03800000, - 0x0201f000, 0x00102066, 0x4a03c014, 0x03800000, - 0x0201f000, 0x001020b2, 0x4a03c014, 0x03800000, - 0x0201f000, 0x001020b6, 0x0401f836, 0x04000010, - 0x0401f862, 0x0402000f, 0x40080800, 0x0401f85f, - 0x0402000c, 0x400c0800, 0x0401f85c, 0x04020009, - 0x0401f84b, 0x42000000, 0x00030d40, 0x80000040, - 0x040207ff, 0x82000540, 0x00000001, 0x1c01f000, - 0x0401f843, 0x80000580, 0x0401f7fd, 0x0401f821, - 0x0400000a, 0x82040d40, 0x00000001, 0x0401f84b, - 0x04020007, 0x0401f87e, 0x0401f898, 0x0401f838, - 0x82000540, 0x00000001, 0x1c01f000, 0x0401f834, - 0x80000580, 0x0401f7fd, 0x40041800, 0x0401f811, - 0x0400000c, 0x0401f83d, 0x0402000b, 0x40080800, - 0x0401f83a, 0x04020008, 0x400c0800, 0x0401ffe8, - 0x04000004, 0x0401f826, 0x82000540, 0x00000001, - 0x1c01f000, 0x0401f822, 0x80000580, 0x0401f7fd, - 0x4c040000, 0x42000800, 0x00000064, 0x4a03c013, - 0x03800300, 0x80040840, 0x04000016, 0x59e00013, - 0x82000500, 0x00000300, 0x82000580, 0x00000300, - 0x040207f7, 0x42000000, 0x00000064, 0x80000040, - 0x040207ff, 0x4a03c013, 0x01000000, 0x42000000, - 0x00000064, 0x80000040, 0x040207ff, 0x4a03c013, - 0x02000000, 0x82000540, 0x00000001, 0x0401f002, - 0x80000580, 0x5c000800, 0x1c01f000, 0x4a03c013, - 0x01000000, 0x42000000, 0x00000064, 0x80000040, - 0x040207ff, 0x4a03c013, 0x02000200, 0x42000000, - 0x00000064, 0x80000040, 0x040207ff, 0x4a03c013, - 0x01000100, 0x1c01f000, 0x42002000, 0x00000008, - 0x82040500, 0x00000080, 0x800000c2, 0x82000540, - 0x01000000, 0x4803c013, 0x42000000, 0x00000064, - 0x80000040, 0x040207ff, 0x4a03c013, 0x02000200, - 0x42000000, 0x00000064, 0x80000040, 0x040207ff, - 0x4a03c013, 0x02000000, 0x800408c2, 0x80102040, - 0x040207ec, 0x4a03c013, 0x01000100, 0x42000000, - 0x00000064, 0x80000040, 0x040207ff, 0x4a03c013, - 0x02000200, 0x42000000, 0x00000064, 0x80000040, - 0x040207ff, 0x59e00013, 0x82000500, 0x00000100, - 0x4a03c013, 0x02000000, 0x4c040000, 0x42000800, - 0x00000064, 0x59e00013, 0x82000500, 0x00000100, - 0x80040840, 0x04000003, 0x80000540, 0x040207fa, - 0x80000540, 0x5c000800, 0x1c01f000, 0x4a03c013, - 0x01000100, 0x42001000, 0x00000008, 0x80000d80, - 0x42000000, 0x00000064, 0x80000040, 0x040207ff, - 0x4a03c013, 0x02000200, 0x42000000, 0x00000064, - 0x80000040, 0x040207ff, 0x59e00013, 0x82000500, - 0x00000100, 0x80000110, 0x800408c2, 0x80040d40, - 0x4a03c013, 0x02000000, 0x80081040, 0x040207ed, - 0x40042800, 0x1c01f000, 0x4a03c013, 0x01000100, - 0x42000000, 0x00000064, 0x80000040, 0x040207ff, - 0x4a03c013, 0x02000200, 0x42000000, 0x00000064, - 0x80000040, 0x040207ff, 0x4a03c013, 0x02000000, - 0x1c01f000, 0x59a00407, 0x59a80837, 0x48035037, - 0x48074407, 0x59a00a09, 0x82040480, 0x00000014, - 0x04021003, 0x42000800, 0x000007d0, 0x59a80038, - 0x48075038, 0x48034209, 0x0201f000, 0x00102066, - 0x836c0580, 0x00000000, 0x0400000e, 0x59a80006, - 0x59a00c06, 0x80041580, 0x82081500, 0x00000040, - 0x02000000, 0x00102066, 0x80080580, 0x48035006, - 0x0201f800, 0x001006df, 0x0201f000, 0x00102066, - 0x59a00406, 0x59a80806, 0x48035006, 0x80040d80, - 0x8c040d0c, 0x02020800, 0x001006df, 0x59a00207, - 0x48035007, 0x59a00407, 0x48035008, 0x0201f000, - 0x00102066, 0x800409c0, 0x04000005, 0x4a034406, - 0x00000001, 0x0201f000, 0x001020b2, 0x0201f800, - 0x00104e0d, 0x04020005, 0x4a034406, 0x00000016, - 0x0201f000, 0x001020b2, 0x836c0580, 0x00000003, - 0x04000005, 0x4a034406, 0x00000007, 0x0201f000, - 0x001020b2, 0x59a00c06, 0x82040500, 0xffffff00, - 0x02020000, 0x001020b6, 0x82041580, 0x000000ff, - 0x04020007, 0x59a80010, 0x82000500, 0x000000ff, - 0x82001540, 0x0000ff00, 0x0401f011, 0x82040400, - 0x00101eb5, 0x50000000, 0x80000110, 0x82000580, - 0x00000080, 0x02000000, 0x001020b6, 0x59a80010, - 0x82000500, 0x000000ff, 0x80041580, 0x02000000, - 0x001020b6, 0x840409c0, 0x80041540, 0x0201f800, - 0x00020892, 0x04020005, 0x4a034406, 0x00000003, - 0x0201f000, 0x001020b2, 0x48ee6021, 0x480a621c, - 0x4a02641c, 0x0000bc09, 0x4a026406, 0x00000001, - 0x0201f800, 0x0010381a, 0x04020007, 0x0201f800, - 0x000208b4, 0x4a034406, 0x00000002, 0x0201f000, - 0x001020b2, 0x497a5a04, 0x497a5805, 0x4a025c04, - 0x00008000, 0x4a01d809, 0x00102657, 0x492e6008, - 0x42027000, 0x00000032, 0x0201f000, 0x000208d8, - 0x800409c0, 0x04000005, 0x4a034406, 0x00000001, - 0x0201f000, 0x001020b2, 0x0201f800, 0x00104e0d, - 0x04020005, 0x4a034406, 0x00000016, 0x0201f000, - 0x001020b2, 0x836c0580, 0x00000003, 0x04000005, - 0x4a034406, 0x00000007, 0x0201f000, 0x001020b2, - 0x59a00c06, 0x82040500, 0xffffff00, 0x02020000, - 0x001020b6, 0x82041580, 0x000000ff, 0x04020007, - 0x59a80010, 0x82000500, 0x000000ff, 0x82001540, - 0x0000ff00, 0x0401f011, 0x82040400, 0x00101eb5, - 0x50000000, 0x80000110, 0x82000580, 0x00000080, - 0x02000000, 0x001020b6, 0x59a80010, 0x82000500, - 0x000000ff, 0x80041580, 0x02000000, 0x001020b6, - 0x840409c0, 0x80041540, 0x0201f800, 0x00020892, - 0x04020005, 0x4a034406, 0x00000003, 0x0201f000, - 0x001020b2, 0x48ee6021, 0x480a621c, 0x4a02641c, - 0x0000bc05, 0x4a026406, 0x00000001, 0x0201f800, - 0x0010381a, 0x04020007, 0x0201f800, 0x000208b4, - 0x4a034406, 0x00000002, 0x0201f000, 0x001020b2, - 0x497a5a04, 0x497a5805, 0x4a025c04, 0x00008000, - 0x4a01d809, 0x00102657, 0x492e6008, 0x42027000, - 0x00000032, 0x0201f000, 0x000208d8, 0x592c0005, - 0x82000580, 0x01000000, 0x02020000, 0x00102066, - 0x4a034406, 0x00000004, 0x0201f000, 0x001020b2, - 0x497b4406, 0x497b4207, 0x0201f800, 0x0010393e, - 0x04000008, 0x59a80066, 0x59a8086a, 0x80040480, - 0x59a80867, 0x48074406, 0x80041480, 0x480b4207, - 0x49674407, 0x59a8000e, 0x48034209, 0x495f4409, - 0x59a80020, 0x4803420b, 0x0201f000, 0x00102066, - 0x800409c0, 0x04000005, 0x4a034406, 0x00000001, - 0x0201f000, 0x001020b2, 0x59a00406, 0x8c000500, - 0x0402000f, 0x59a80069, 0x81640480, 0x04001008, - 0x59a8000b, 0x81500580, 0x04000009, 0x59a8006a, - 0x59a81066, 0x80080580, 0x04000005, 0x4a034406, - 0x00000018, 0x0201f000, 0x001020b2, 0x59a80005, - 0x84000558, 0x48035005, 0x82000540, 0x00000001, - 0x0201f800, 0x00101668, 0x0201f800, 0x00103a9f, - 0x0201f000, 0x00102066, 0x4803c856, 0x800409c0, - 0x02020000, 0x001020ba, 0x59a00406, 0x8c00051e, - 0x04000008, 0x4803c856, 0x59a0020b, 0x82000480, - 0x00000800, 0x04001015, 0x0201f000, 0x001020b6, - 0x4803c856, 0x59a0020b, 0x599c0a01, 0x80040480, - 0x04021003, 0x0201f000, 0x001020b6, 0x59a8000e, - 0x81640580, 0x04000009, 0x4a034406, 0x00000018, - 0x0201f000, 0x001020b2, 0x4a034406, 0x00000005, - 0x0201f000, 0x001020b2, 0x59a80026, 0x8c00050a, - 0x040007fa, 0x59a00406, 0x8c00051e, 0x04000036, - 0x0201f800, 0x00020892, 0x040007f4, 0x0201f800, - 0x0010381a, 0x040007f1, 0x497a5a04, 0x59a00406, - 0x4802620a, 0x59a00209, 0x4802640a, 0x59a00409, - 0x4802620b, 0x59a0020d, 0x4802620c, 0x59a0040d, - 0x4802640c, 0x59a0020e, 0x4802620d, 0x59a0040e, - 0x4802640d, 0x59a00210, 0x4802620e, 0x59a00410, - 0x4802640e, 0x59a0020b, 0x82000500, 0x0000fffc, - 0x80000104, 0x4802640b, 0x0401f9d9, 0x040007d7, - 0x48ee6021, 0x58ee580d, 0x5930020e, 0x59301c0e, - 0x900c19c0, 0x800c1d40, 0x5930020c, 0x5930140c, - 0x900811c0, 0x80081540, 0x592c0a05, 0x832c0400, - 0x00000006, 0x0201f800, 0x0010383e, 0x4a01d809, - 0x00102846, 0x4a034000, 0x00000001, 0x49334001, - 0x1c01f000, 0x0201f800, 0x0010698c, 0x0201f800, - 0x00100b29, 0x0401f86d, 0x497b5057, 0x4201d000, - 0x00002710, 0x0201f800, 0x00105e06, 0x59c40880, - 0x4c040000, 0x59c408a3, 0x4c040000, 0x497b4002, - 0x0401f876, 0x0401f893, 0x4a03a005, 0x10000000, - 0x0401f8b4, 0x0401f901, 0x04000048, 0x59c80001, - 0x800001c0, 0x040007fc, 0x59c80018, 0x82000500, - 0xf0000000, 0x59c00808, 0x82040d00, 0x0fffffff, - 0x80040540, 0x48038008, 0x0201f800, 0x00100f0f, - 0x59c00006, 0x4a038006, 0x10000000, 0x59c00009, - 0x82000d00, 0x00e00000, 0x04020024, 0x4a03900d, - 0x00000000, 0x59c80020, 0x82000500, 0xff000000, - 0x82000580, 0x32000000, 0x0402001c, 0x4a03900d, - 0x00000001, 0x59c80020, 0x82000500, 0xff000000, - 0x82000580, 0xe1000000, 0x04020014, 0x4a03900d, - 0x00000000, 0x59c80020, 0x82000500, 0x00ffffff, - 0x4a03900d, 0x00000000, 0x59c80821, 0x82040d00, - 0x00ffffff, 0x80040580, 0x04020008, 0x59a80010, - 0x80040580, 0x04020005, 0x59c40005, 0x82000500, - 0x000000f0, 0x04000006, 0x4803c856, 0x0401f8d7, - 0x4a035057, 0x00000001, 0x0401f002, 0x0401f8e1, - 0x42000000, 0x00000064, 0x80000040, 0x02000800, - 0x00100615, 0x59c00807, 0x82040d00, 0x0000000c, - 0x040007fa, 0x0401f003, 0x4a035057, 0x00000001, - 0x0401f8da, 0x0201f800, 0x00106c8a, 0x0401f818, - 0x4201d000, 0x000186a0, 0x0201f800, 0x00105e06, - 0x5c000800, 0x480788a3, 0x5c000800, 0x48078880, - 0x59a80057, 0x800001c0, 0x02000000, 0x00102066, - 0x0201f000, 0x001020be, 0x599c0201, 0x48035059, - 0x41780800, 0x42001000, 0x00003b10, 0x0201f800, - 0x001063ee, 0x480b505a, 0x1c01f000, 0x0201f800, - 0x00106982, 0x59b800ea, 0x82000500, 0x00000007, - 0x82000580, 0x00000003, 0x04020003, 0x4a0370e8, - 0x00000001, 0x1c01f000, 0x42038000, 0x00007700, - 0x4a038006, 0x30000000, 0x59c00007, 0x8c00050a, - 0x040207fe, 0x59c00006, 0x59a00209, 0x59a00c09, - 0x900409c0, 0x80040d40, 0x48078001, 0x59a0020e, - 0x59a00c0e, 0x900409c0, 0x80040d40, 0x48078000, - 0x59a0020b, 0x82000500, 0x0000fffc, 0x48038002, - 0x48038003, 0x48038005, 0x497b9009, 0x59e00003, - 0x82000540, 0x00008060, 0x4803c003, 0x1c01f000, - 0x41780800, 0x8007a0ca, 0x83d3a400, 0x00007600, - 0x42000800, 0x00000040, 0x0201f800, 0x00101395, - 0x4a03a00a, 0x00000001, 0x4a03a005, 0x20000000, - 0x59d00006, 0x4a03a005, 0x30000000, 0x59d00006, - 0x8c00050a, 0x040207fe, 0x59d00005, 0x59a00210, - 0x59a00c10, 0x900409c0, 0x80040d40, 0x4807a001, - 0x59a0020d, 0x59a00c0d, 0x900409c0, 0x80040d40, - 0x4807a000, 0x59a0020b, 0x82000500, 0x0000fffc, - 0x4803a003, 0x4803a002, 0x4803a008, 0x1c01f000, - 0x59a00002, 0x4803c857, 0x800001c0, 0x0402004a, - 0x59a8005a, 0x48038880, 0x59c400a3, 0x82000540, - 0x00002008, 0x8400053a, 0x480388a3, 0x59c40008, - 0x8400054e, 0x82000500, 0xffffffe1, 0x48038808, - 0x59c80040, 0x84000534, 0x48039040, 0x0401f902, - 0x04020013, 0x59a80010, 0x800000d0, 0x82000540, - 0x00000011, 0x48039120, 0x59a80010, 0x82000500, - 0x00ffffff, 0x82000540, 0x32000000, 0x48039121, - 0x4a039123, 0xe1290008, 0x59a80010, 0x82000500, - 0x00ffffff, 0x48039122, 0x0401f016, 0x59a80010, - 0x82000500, 0x000000ff, 0x900009c0, 0x840001c0, - 0x80040540, 0x82000540, 0x00000000, 0x48039120, - 0x59a80010, 0x82000500, 0x000000ff, 0x82000540, - 0x01000000, 0x48039121, 0x4a039123, 0x08210008, - 0x59a80010, 0x82000500, 0x000000ff, 0x48039122, - 0x497b9124, 0x59a80c5b, 0x80040800, 0x4807545b, - 0x900409c0, 0x82040540, 0x0000aaaa, 0x48039125, - 0x497b9126, 0x497b9127, 0x0401f8cf, 0x04020004, - 0x4a039100, 0x0000e980, 0x0401f003, 0x4a039100, - 0x0000e9a0, 0x1c01f000, 0x82000540, 0x00000001, - 0x0402500d, 0x4203e000, 0x80000000, 0x40e81000, - 0x41780800, 0x42000000, 0x00000064, 0x0201f800, - 0x001063ee, 0x59940024, 0x80080400, 0x48032824, - 0x80000580, 0x1c01f000, 0x4d900000, 0x4dd00000, - 0x4da40000, 0x4d140000, 0x417a3000, 0x0201f800, - 0x00106e2f, 0x0201f800, 0x00106b13, 0x5c022800, - 0x5c034800, 0x5c03a000, 0x5c032000, 0x1c01f000, - 0x59c80007, 0x8c000500, 0x04000003, 0x4a03900d, - 0x00000030, 0x1c01f000, 0x4a038805, 0x00020000, - 0x42000800, 0x0000003c, 0x0201f800, 0x00101395, - 0x4a038891, 0x0000ffff, 0x59c80035, 0x48039035, - 0x4a03900d, 0x00000040, 0x42038000, 0x00007700, - 0x0201f800, 0x00100f0f, 0x42038000, 0x00007720, - 0x0201f800, 0x00100f0f, 0x4a03a005, 0x20000000, - 0x4a03a005, 0x30000000, 0x59d00806, 0x8c040d0a, - 0x040207fe, 0x1c01f000, 0x4d300000, 0x4031d800, - 0x58ef400b, 0x58ee580d, 0x58ec0002, 0x82000580, - 0x00000200, 0x5c026000, 0x02000000, 0x001020aa, - 0x4d300000, 0x59a26001, 0x59a00000, 0x4000b000, - 0x80000000, 0x48034000, 0x592c0001, 0x80000540, - 0x0400001e, 0x40025800, 0x8058b040, 0x040207fb, - 0x58ec1007, 0x58ec1808, 0x592c0a05, 0x4d2c0000, - 0x58ec000d, 0x40025800, 0x592c0204, 0x5c025800, - 0x82000580, 0x00000103, 0x04000008, 0x832c0400, - 0x00000006, 0x0201f800, 0x0010383e, 0x4a01d809, - 0x00102846, 0x0401f007, 0x832c0400, 0x00000006, - 0x0201f800, 0x00103841, 0x4a01d809, 0x00102846, - 0x5c026000, 0x1c01f000, 0x58ec000d, 0x40025800, - 0x592c0204, 0x82000580, 0x00000103, 0x04020006, - 0x0201f800, 0x000208b4, 0x5c026000, 0x0201f000, - 0x00102066, 0x58ec000d, 0x40025800, 0x592c0404, - 0x8400055e, 0x48025c04, 0x42028800, 0x000007fd, - 0x42003000, 0x00fffffd, 0x0201f800, 0x001043fc, - 0x04000003, 0x80000580, 0x0401f004, 0x59a26001, - 0x0201f800, 0x00109146, 0x5c026000, 0x02000000, - 0x001020b2, 0x4d300000, 0x4a01d809, 0x00102899, - 0x0401f7dc, 0x592c0005, 0x82000580, 0x01000000, - 0x02000000, 0x001020be, 0x4d300000, 0x59a26001, - 0x5930020b, 0x59301c0a, 0x900001c0, 0x800c1d40, - 0x5930040d, 0x5930120d, 0x900001c0, 0x80081540, - 0x592c0a05, 0x832c0400, 0x00000006, 0x0201f800, - 0x00103841, 0x4a01d809, 0x00102846, 0x4a034000, - 0x00000001, 0x5c026000, 0x1c01f000, 0x4933c857, - 0x4c300000, 0x5930040b, 0x82000c80, 0x0000000e, - 0x04001004, 0x4a025a05, 0x0000000e, 0x0401f003, - 0x48025a05, 0x0401f00c, 0x800409c0, 0x0400000a, - 0x4c040000, 0x0201f800, 0x0010381a, 0x5c000800, - 0x04000003, 0x40040000, 0x0401f7f0, 0x80000580, - 0x0401f003, 0x82000540, 0x00000001, 0x5c006000, - 0x1c01f000, 0x59a00206, 0x82000580, 0x00000044, - 0x1c01f000, 0x4807c857, 0x800409c0, 0x0400000c, - 0x0201f800, 0x001016c1, 0x04020009, 0x42000000, - 0x00000002, 0x0201f800, 0x001018fa, 0x42000000, - 0x00000002, 0x0201f800, 0x00101892, 0x59a00406, - 0x82000500, 0x00000007, 0x0c01f001, 0x001028ed, - 0x00102902, 0x00102918, 0x001028eb, 0x001028eb, - 0x001028eb, 0x001028eb, 0x001028eb, 0x0201f000, - 0x001020b6, 0x42000800, 0x000000c0, 0x0201f800, - 0x001019ac, 0x82040540, 0x00000002, 0x42000800, - 0x000000c0, 0x0201f800, 0x001019b1, 0x42000800, - 0x00000000, 0x0201f800, 0x001019ac, 0x82040540, - 0x00000008, 0x42000800, 0x00000000, 0x0201f800, - 0x001019b1, 0x0401f00b, 0x42000800, 0x000000c0, - 0x0201f800, 0x001019ac, 0x82040540, 0x00000001, - 0x42000800, 0x000000c0, 0x0201f800, 0x001019b1, - 0x59c80040, 0x4c000000, 0x59a80010, 0x4c000000, - 0x59c400a3, 0x4c000000, 0x59c40008, 0x4c000000, - 0x0401f911, 0x04000021, 0x0201f800, 0x00100615, - 0x59a80821, 0x800409c0, 0x02020000, 0x001020ba, - 0x0201f800, 0x00104e0d, 0x04020005, 0x4a034406, - 0x00000016, 0x0201f000, 0x001020b2, 0x836c0580, - 0x00000003, 0x02020000, 0x001020ba, 0x59c408a4, - 0x82040d00, 0x0000000f, 0x82040580, 0x00000000, - 0x02020000, 0x001020ba, 0x59c80040, 0x4c000000, - 0x59a80010, 0x4c000000, 0x59c400a3, 0x4c000000, - 0x59c40008, 0x4c000000, 0x59c40080, 0x4c000000, - 0x59a0020f, 0x59a0bc0f, 0x905cb9c0, 0x805cbd40, - 0x41784800, 0x41785000, 0x41785800, 0x41789000, - 0x41789800, 0x0401fe21, 0x0201f800, 0x0010698c, - 0x0201f800, 0x00100b29, 0x4178c000, 0x497b4002, - 0x0401f95c, 0x0401f9aa, 0x59a0020c, 0x59a00c0c, - 0x80040d40, 0x04000002, 0x0401f9fb, 0x0401f9fa, - 0x0401fe68, 0x8060c1c0, 0x04020014, 0x0401fa98, - 0x0401feb2, 0x0402000e, 0x0201f800, 0x00101941, - 0x04020008, 0x4a034406, 0x00000017, 0x0201f800, - 0x001020b2, 0x4203e000, 0x50000000, 0x0401f000, - 0x42005800, 0x0000aaaa, 0x0401f058, 0x59c80001, - 0x800001c0, 0x040007ee, 0x59c80801, 0x800409c0, - 0x04000006, 0x0401fa70, 0x40240000, 0x80280540, - 0x802c0540, 0x0402004d, 0x59a00002, 0x82000580, - 0xfeedbeef, 0x04000004, 0x42008800, 0x10000000, - 0x0401f003, 0x42008800, 0x10000004, 0x0401fa19, - 0x4a034002, 0xfeedbeef, 0x0401fa71, 0x0401fa97, - 0x0401fea8, 0x59c40005, 0x8c000534, 0x04000004, - 0x42005800, 0x0000bbbb, 0x0401f038, 0x0401fe83, - 0x04020007, 0x42005800, 0x0000cccc, 0x485f420f, - 0x905cb9c0, 0x485f440f, 0x0401f030, 0x59a0040c, - 0x800001c0, 0x0400000e, 0x59a26000, 0x5930000d, - 0x800001c0, 0x040207be, 0x59a26001, 0x5930080d, - 0x800409c0, 0x040207ba, 0x804891c0, 0x040207b8, - 0x804c99c0, 0x040207b6, 0x0401f87a, 0x805cb840, - 0x04000005, 0x40240000, 0x80280540, 0x802c0540, - 0x0402001a, 0x42000000, 0x00030d40, 0x80000040, - 0x04020012, 0x59c00007, 0x82000500, 0x000501c0, - 0x0402000b, 0x0201f800, 0x00101941, 0x04020008, - 0x4a034406, 0x00000017, 0x0201f800, 0x001020b2, - 0x4203e000, 0x50000000, 0x0401f000, 0x42005800, - 0x0000dddd, 0x0401f005, 0x59c00807, 0x82040d00, - 0x0000000c, 0x040007ea, 0x0401fe5c, 0x59a0040c, - 0x800001c0, 0x04000002, 0x0401f856, 0x0401fe6b, - 0x40240000, 0x80280540, 0x802c0540, 0x04020003, - 0x805cb9c0, 0x04020781, 0x0201f800, 0x00106c8a, - 0x0401fda3, 0x4201d000, 0x000186a0, 0x0201f800, - 0x00105e06, 0x5c000800, 0x48078880, 0x5c000800, - 0x48078808, 0x5c000800, 0x480788a3, 0x5c000800, - 0x48075010, 0x5c000800, 0x48079040, 0x0201f800, - 0x001009b6, 0x59a00406, 0x82000500, 0x00000003, - 0x82000580, 0x00000002, 0x0400002c, 0x42000800, - 0x000000c0, 0x0201f800, 0x001019ac, 0x82040500, - 0xfffffffc, 0x42000800, 0x000000c0, 0x0201f800, - 0x001019b1, 0x42000800, 0x00000000, 0x0201f800, - 0x001019ac, 0x82040500, 0xfffffff7, 0x42000800, - 0x00000000, 0x0201f800, 0x001019b1, 0x42000800, - 0x00000000, 0x0201f800, 0x001019ac, 0x82040500, - 0xfffffffb, 0x42000800, 0x00000000, 0x0201f800, - 0x001019b1, 0x4a0388a7, 0x0000f7f7, 0x42006000, - 0xbeffffff, 0x42006800, 0x80018000, 0x0201f800, - 0x001040ad, 0x42006000, 0xfffeffff, 0x41786800, - 0x0201f800, 0x001040ad, 0x402c0000, 0x80280540, - 0x80240540, 0x02000000, 0x00102066, 0x48274406, - 0x482b4207, 0x482f4407, 0x0201f000, 0x001020c2, - 0x59a26000, 0x813261c0, 0x0400000e, 0x59325808, - 0x812e59c0, 0x0400000b, 0x0201f800, 0x000208b4, - 0x0201f800, 0x00100843, 0x59a26001, 0x59325808, - 0x0201f800, 0x000208b4, 0x0201f800, 0x00100843, - 0x1c01f000, 0x42000800, 0x000000ef, 0x0201f800, - 0x00101655, 0x59c400a3, 0x8400055a, 0x8400053a, - 0x480388a3, 0x0201f800, 0x001016ac, 0x0402000a, - 0x42000000, 0x00000001, 0x0201f800, 0x001018fa, - 0x42000000, 0x00000001, 0x0201f800, 0x00101892, - 0x0401f013, 0x0201f800, 0x001016b3, 0x04020008, - 0x41780000, 0x0201f800, 0x001018fa, 0x41780000, - 0x0201f800, 0x00101892, 0x0401f009, 0x42000000, - 0x00000002, 0x0201f800, 0x001018fa, 0x42000000, - 0x00000002, 0x0201f800, 0x00101892, 0x42000800, - 0x00000000, 0x0201f800, 0x001019ac, 0x82040540, - 0x00000004, 0x42000800, 0x00000000, 0x0201f800, - 0x001019b1, 0x4201d000, 0x00000014, 0x0201f800, - 0x00105dd2, 0x59c40008, 0x8400054e, 0x82000500, - 0xffffffe1, 0x48038808, 0x4a0388a7, 0x0000f7f7, - 0x42001000, 0x04000001, 0x0201f800, 0x001019aa, - 0x42006000, 0xbe20bfff, 0x42006800, 0x80018000, - 0x0201f800, 0x001040ad, 0x42006000, 0xfffeffff, - 0x41786800, 0x0201f800, 0x001040ad, 0x4200b000, - 0x00001388, 0x4201d000, 0x00000014, 0x4c580000, - 0x0201f800, 0x00105dd2, 0x0201f800, 0x00101941, - 0x5c00b000, 0x04000004, 0x8058b040, 0x040207f6, - 0x0401f025, 0x59c40005, 0x8c000534, 0x04020007, - 0x59c400a4, 0x82000500, 0x0000000f, 0x82000580, - 0x00000008, 0x0402001c, 0x42006000, 0x00020000, - 0x0201f800, 0x001040b2, 0x4201d000, 0x00000064, - 0x0201f800, 0x00105dd2, 0x42006000, 0xfeffffff, - 0x42006800, 0x02000000, 0x0201f800, 0x001040ad, - 0x42006000, 0xfdffffff, 0x41786800, 0x0201f800, - 0x001040ad, 0x4a038805, 0x04000001, 0x59c400a4, - 0x82000500, 0x0000000f, 0x82000580, 0x00000000, - 0x04000003, 0x82000540, 0x00000001, 0x1c01f000, - 0x4803c856, 0x42038000, 0x00007700, 0x0201f800, - 0x00100f0f, 0x59c00006, 0x59a0040c, 0x800001c0, - 0x0400003f, 0x59a03c0c, 0x59a00209, 0x59a01c09, - 0x900c19c0, 0x800c1d40, 0x59a0020e, 0x59a0240e, - 0x901021c0, 0x80102540, 0x59a0020b, 0x82000500, - 0x0000fffc, 0x59a0140b, 0x900811c0, 0x80081540, - 0x480b8003, 0x0201f800, 0x00020892, 0x02000800, - 0x00100615, 0x49334000, 0x0201f800, 0x0010082a, - 0x4a025a04, 0x00000018, 0x4a025805, 0x00abcdef, - 0x492e6008, 0x492e600b, 0x481e600d, 0x4a02600c, - 0x00000004, 0x832c0400, 0x00000011, 0x4802600a, - 0x42001000, 0x0000000c, 0x821c0d80, 0x00000001, - 0x04000004, 0x801c3840, 0x0401f963, 0x0401f004, - 0x41783800, 0x0401f960, 0x0401f011, 0x821c0c80, - 0x00000005, 0x04001005, 0x40043800, 0x42001000, - 0x0000003c, 0x0401f006, 0x80001580, 0x82081400, - 0x0000000c, 0x801c3840, 0x040207fd, 0x832c0400, - 0x00000005, 0x0401f950, 0x040207f1, 0x497b9009, - 0x59e00003, 0x82000540, 0x00008060, 0x4803c003, - 0x4a038009, 0x00e00000, 0x1c01f000, 0x4803c856, - 0x41780800, 0x8007a0ca, 0x83d3a400, 0x00007600, - 0x42000800, 0x00000040, 0x0201f800, 0x00101395, - 0x4a03a00a, 0x00000001, 0x4a03a005, 0x20000000, - 0x59d00006, 0x4a03a005, 0x30000000, 0x59d00006, - 0x8c00050a, 0x040207fe, 0x59d00005, 0x59a0020c, - 0x800001c0, 0x0400003f, 0x59a03a0c, 0x59a00210, - 0x59a01c10, 0x900c19c0, 0x800c1d40, 0x59a0020d, - 0x59a0240d, 0x901021c0, 0x80102540, 0x59a0120b, - 0x82081500, 0x0000fffc, 0x59a0040b, 0x900001c0, - 0x80081540, 0x480ba003, 0x0201f800, 0x00020892, - 0x02000800, 0x00100615, 0x49334001, 0x0201f800, - 0x0010082a, 0x4a025a04, 0x00000018, 0x4a025805, - 0x00abcdef, 0x492e6008, 0x492e600b, 0x481e600d, - 0x4a02600c, 0x00000004, 0x832c0400, 0x00000011, - 0x4802600a, 0x42001000, 0x0000000c, 0x821c0d80, - 0x00000001, 0x04000004, 0x801c3840, 0x0401f906, - 0x0401f004, 0x41783800, 0x0401f903, 0x0401f011, - 0x821c0c80, 0x00000005, 0x04001005, 0x40043800, - 0x42001000, 0x0000003c, 0x0401f006, 0x80001580, - 0x82081400, 0x0000000c, 0x801c3840, 0x040207fd, - 0x832c0400, 0x00000005, 0x0401f8f3, 0x040207f1, - 0x1c01f000, 0x4803c856, 0x59a0020c, 0x800001c0, - 0x04000024, 0x824c0580, 0x00000002, 0x04000040, - 0x59a26001, 0x5930380d, 0x801c39c0, 0x0400003c, - 0x801c3840, 0x481e600d, 0x5932580b, 0x5930080a, - 0x50042000, 0x58041801, 0x58041002, 0x82081500, - 0xfffffffc, 0x5930000c, 0x80000000, 0x82000d80, - 0x00000005, 0x04020009, 0x497a600c, 0x592e5801, - 0x812e59c0, 0x0400001a, 0x492e600b, 0x832c0c00, - 0x00000005, 0x0401f005, 0x4802600c, 0x5930080a, - 0x82040c00, 0x00000003, 0x4806600a, 0x0401f010, - 0x59a0120b, 0x82081500, 0x0000fffc, 0x59a0040b, - 0x900001c0, 0x80081540, 0x480ba003, 0x59a0020d, - 0x59a0240d, 0x901021c0, 0x80102540, 0x59a00210, - 0x59a01c10, 0x900c19c0, 0x800c1d40, 0x4201d000, - 0x00003a98, 0x0201f800, 0x00105e06, 0x480ba002, - 0x59a80059, 0x4803a008, 0x4813a000, 0x480fa001, - 0x4a03a005, 0x10000000, 0x02005800, 0x00100615, - 0x804c9800, 0x82000540, 0x00000001, 0x1c01f000, - 0x4847c857, 0x59a0040c, 0x800001c0, 0x04000024, - 0x82480580, 0x00000002, 0x04000042, 0x59a26000, - 0x5930380d, 0x801c39c0, 0x0400003e, 0x801c3840, - 0x481e600d, 0x5932580b, 0x5930080a, 0x50042000, - 0x58041801, 0x58041002, 0x82081500, 0xfffffffc, - 0x5930000c, 0x80000000, 0x82000d80, 0x00000005, - 0x04020009, 0x497a600c, 0x592e5801, 0x812e59c0, - 0x0400001d, 0x492e600b, 0x832c0c00, 0x00000005, - 0x0401f005, 0x4802600c, 0x5930080a, 0x82040c00, - 0x00000003, 0x4806600a, 0x0401f013, 0x82440580, - 0x10000000, 0x0402001f, 0x59a0020e, 0x59a0240e, - 0x901021c0, 0x80102540, 0x59a00209, 0x59a01c09, - 0x900c19c0, 0x800c1d40, 0x59a0020b, 0x82000500, - 0x0000fffc, 0x59a0140b, 0x900811c0, 0x80081540, - 0x480b8003, 0x48138000, 0x480f8001, 0x480b8002, - 0x59c80018, 0x82000500, 0xf0000000, 0x59c02008, - 0x82102500, 0x0fffffff, 0x80100540, 0x48038008, - 0x48478006, 0x80489000, 0x8260c540, 0x00000001, - 0x1c01f000, 0x59c00009, 0x4803c857, 0x82000d00, - 0x00e00000, 0x0400000d, 0x485f420f, 0x905cb9c0, - 0x485f440f, 0x8c00052e, 0x04000002, 0x80285000, - 0x8c00052c, 0x04000002, 0x80244800, 0x8c00052a, - 0x04000002, 0x802c5800, 0x1c01f000, 0x59a0020c, - 0x800001c0, 0x04000024, 0x59d00806, 0x4807c857, - 0x8c040d3e, 0x04000020, 0x4a03a005, 0x20000000, - 0x4a03a005, 0x30000000, 0x59d00806, 0x8c040d0a, - 0x040207fe, 0x824c0480, 0x00000003, 0x02021800, - 0x00100615, 0x404c0000, 0x0c01f001, 0x00102c02, - 0x00102c04, 0x00102c0a, 0x0201f800, 0x00100615, - 0x80000040, 0x40009800, 0x0401ff43, 0x0400000a, - 0x0401ff41, 0x0401f008, 0x80000040, 0x40009800, - 0x59d00806, 0x4807c857, 0x8c040d3e, 0x040207e3, - 0x0401ff39, 0x1c01f000, 0x59a0040c, 0x800001c0, - 0x04000024, 0x59c00807, 0x4807c857, 0x8c040d3e, - 0x04000020, 0x59c00807, 0x4a038006, 0x20000000, - 0x82480480, 0x00000003, 0x02021800, 0x00100615, - 0x40480000, 0x0c01f001, 0x00102c25, 0x00102c27, - 0x00102c2f, 0x0201f800, 0x00100615, 0x80000040, - 0x40009000, 0x42008800, 0x10000004, 0x0401ff65, - 0x0400000c, 0x0401ff63, 0x0401f00a, 0x80000040, - 0x40009000, 0x59c00807, 0x4807c857, 0x8c040d3e, - 0x040207e5, 0x42008800, 0x10000004, 0x0401ff59, - 0x1c01f000, 0x492fc857, 0x4000a800, 0x4a03b805, - 0x20000000, 0x59dc0006, 0x4a03b805, 0x30000000, - 0x4813b800, 0x480fb801, 0x480bb802, 0x4857b803, - 0x4a03b805, 0x30000002, 0x59dc0006, 0x4a03b805, - 0x70000001, 0x59dc0006, 0x4a03b805, 0x10000000, - 0x59dc0006, 0x8c00053e, 0x040007fe, 0x4a03b805, - 0x20000000, 0x59dc0006, 0x59dc2000, 0x59dc1801, - 0x801c39c0, 0x0400000a, 0x4d2c0000, 0x0201f800, - 0x0010082a, 0x5c000800, 0x02000800, 0x00100615, - 0x4a025a04, 0x0000000a, 0x492c0801, 0x1c01f000, - 0x42006000, 0x00102d9d, 0x42000800, 0x0000007c, - 0x0201f800, 0x00101395, 0x4a03902c, 0x00200000, - 0x4200b000, 0x000001f4, 0x59c8002c, 0x8c00052c, - 0x04000007, 0x8058b040, 0x040207fc, 0x42000000, - 0x00004003, 0x41781000, 0x0401f11e, 0x50301000, - 0x41784800, 0x4a03902d, 0x00008000, 0x4200b000, - 0x000001f4, 0x59c8002c, 0x8c000534, 0x04000007, - 0x8058b040, 0x040207fc, 0x42000000, 0x00004003, - 0x41781000, 0x0401f10f, 0x0401f895, 0x80244800, - 0x82240580, 0x000003b1, 0x040207fc, 0x0401f911, - 0x41784800, 0x0401f8bb, 0x80244800, 0x82240580, - 0x000003b1, 0x040207fc, 0x80306000, 0x82300580, - 0x00102d9f, 0x040207e2, 0x59a80863, 0x800409c0, - 0x04000007, 0x42000000, 0x00004004, 0x42001000, - 0x00000002, 0x59a81862, 0x0401f0f6, 0x42006000, - 0x00102d9d, 0x50301000, 0x41784800, 0x4a03902d, - 0x00000800, 0x0401f876, 0x80244800, 0x82240580, - 0x00000018, 0x040207fc, 0x0401f8f2, 0x41784800, - 0x0401f89c, 0x80244800, 0x82240580, 0x00000018, - 0x040207fc, 0x80306000, 0x82300580, 0x00102d9f, - 0x040207ed, 0x59a80863, 0x800409c0, 0x04000007, - 0x42000000, 0x00004004, 0x42001000, 0x00000010, - 0x59a81862, 0x0401f0d7, 0x42006000, 0x00102d9d, - 0x50301000, 0x41784800, 0x4a03902d, 0x00000400, - 0x0401f857, 0x80244800, 0x82240580, 0x00000088, - 0x040207fc, 0x0401f8d3, 0x41784800, 0x0401f87d, - 0x80244800, 0x82240580, 0x00000088, 0x040207fc, - 0x80306000, 0x82300580, 0x00102d9f, 0x040207ed, - 0x59a80863, 0x800409c0, 0x04000007, 0x42000000, - 0x00004004, 0x42001000, 0x00000008, 0x59a81862, - 0x0401f0b8, 0x42006000, 0x00102d9d, 0x50301000, - 0x41784800, 0x4a03902d, 0x00002000, 0x4200b000, - 0x000001f4, 0x59c8002c, 0x8c000530, 0x04000007, - 0x8058b040, 0x040207fc, 0x42000000, 0x00004003, - 0x41781000, 0x0401f0a7, 0x59c8002c, 0x82000500, - 0xffe0ffff, 0x82080d00, 0x001f0000, 0x80040540, - 0x4803902c, 0x0401f826, 0x80244800, 0x82240580, - 0x00000110, 0x040207fc, 0x0401f8a2, 0x41784800, - 0x0401f84c, 0x59c80034, 0x82080d00, 0x001f0000, - 0x82000500, 0x001f0000, 0x80040580, 0x04000006, - 0x59a80063, 0x80000000, 0x48035063, 0x40240000, - 0x48035062, 0x80244800, 0x82240580, 0x00000110, - 0x040207f0, 0x80306000, 0x82300580, 0x00102d9f, - 0x040207cf, 0x59a80863, 0x800409c0, 0x04000006, - 0x42000000, 0x00004004, 0x42001000, 0x00000020, - 0x59a81862, 0x0201f000, 0x00102066, 0x59c8002c, - 0x82000500, 0xffff0000, 0x82080d00, 0x0000ffff, - 0x80040540, 0x4803902c, 0x480b9028, 0x480b9029, - 0x59a80064, 0x82000580, 0x00000004, 0x04000003, - 0x480b902a, 0x480b902b, 0x59c8002d, 0x82000500, - 0xfffffc00, 0x80240540, 0x4803902d, 0x4200b000, - 0x000001f4, 0x59c8002c, 0x82000500, 0x18000000, - 0x04000007, 0x8058b040, 0x040207fb, 0x42000000, - 0x00004003, 0x41781000, 0x0401f05a, 0x4a03902e, - 0x00000001, 0x4200b000, 0x000001f4, 0x59c8002e, - 0x8c000500, 0x04000006, 0x8058b040, 0x040207fc, - 0x42000000, 0x00004003, 0x0401f04e, 0x1c01f000, - 0x41783800, 0x59c8002d, 0x82000500, 0xfffffc00, - 0x80240d40, 0x4807902d, 0x4200b000, 0x000001f4, - 0x59c8002c, 0x82000500, 0x18000000, 0x04000007, - 0x8058b040, 0x040207fb, 0x42000000, 0x00004003, - 0x41781000, 0x0401f03b, 0x59c81830, 0x59c80030, - 0x800c0d80, 0x040207fd, 0x80080d80, 0x04000002, - 0x801c3800, 0x59c82031, 0x59c80031, 0x80100d80, - 0x040207fd, 0x80080d80, 0x04000002, 0x801c3800, - 0x59a80064, 0x82000580, 0x00000004, 0x04000019, - 0x59c82832, 0x59c80032, 0x80140d80, 0x040207fd, - 0x80080d80, 0x04000002, 0x801c3800, 0x59c83033, - 0x59c80033, 0x80180d80, 0x040207fd, 0x80080d80, - 0x04000002, 0x801c3800, 0x59c80034, 0x59c80834, - 0x80040d80, 0x040207fd, 0x80080d80, 0x82040d00, - 0x0000ffff, 0x0400000c, 0x801c3800, 0x0401f00a, - 0x59c80034, 0x59c80834, 0x80040d80, 0x040207fd, - 0x80080d80, 0x82040d00, 0x000000ff, 0x04000002, - 0x801c3800, 0x801c39c0, 0x04000005, 0x59a80063, - 0x801c0400, 0x48035063, 0x48275062, 0x1c01f000, - 0x48034206, 0x48074406, 0x480b4207, 0x480f4407, - 0x48134208, 0x48174408, 0x0201f000, 0x00102069, - 0x42000000, 0x00600000, 0x80000040, 0x040207ff, - 0x1c01f000, 0x5a5a5a5a, 0xa5a5a5a5, 0x59a00c0a, - 0x800409c0, 0x02000000, 0x001020b6, 0x82040480, - 0x00000021, 0x02021000, 0x001020b6, 0x82040480, - 0x00000011, 0x04001003, 0x42000800, 0x00000010, - 0x59a00208, 0x59a01407, 0x900811c0, 0x80081540, - 0x59a00207, 0x59a01c06, 0x900c19c0, 0x800c1d40, - 0x0201f800, 0x0010381a, 0x04000006, 0x0201f800, - 0x0010383e, 0x4a01d809, 0x00102dc0, 0x1c01f000, - 0x4a034406, 0x00000002, 0x0201f000, 0x001020b2, - 0x4031d800, 0x58ef400b, 0x58ec0002, 0x82000580, - 0x00000200, 0x02000000, 0x001020aa, 0x59a00c0a, - 0x82040480, 0x00000011, 0x04001003, 0x42000800, - 0x00000010, 0x59a0040b, 0x59a0120b, 0x900811c0, - 0x80081540, 0x59a00209, 0x59a01c08, 0x900c19c0, - 0x800c1d40, 0x58ec0003, 0x0201f800, 0x00103841, - 0x4a01d809, 0x00102ddb, 0x1c01f000, 0x4031d800, - 0x58ef400b, 0x58ec0002, 0x82000580, 0x00000200, - 0x02000000, 0x001020aa, 0x59a00c0a, 0x82040480, - 0x00000011, 0x02001000, 0x00102066, 0x82040c80, - 0x00000010, 0x59a00208, 0x59a01407, 0x900811c0, - 0x80081540, 0x59a00207, 0x59a01c06, 0x900c19c0, - 0x800c1d40, 0x82081400, 0x00000040, 0x58ec0003, - 0x0201f800, 0x0010383e, 0x4a01d809, 0x00102df9, - 0x1c01f000, 0x4031d800, 0x58ef400b, 0x58ec0002, - 0x82000580, 0x00000200, 0x02000000, 0x001020aa, - 0x59a0040a, 0x82000c80, 0x00000010, 0x59a0040b, - 0x59a0120b, 0x900811c0, 0x80081540, 0x59a00209, - 0x59a01c08, 0x900c19c0, 0x800c1d40, 0x82081400, - 0x00000040, 0x58ec0003, 0x0201f800, 0x00103841, - 0x4a01d809, 0x0010205f, 0x1c01f000, 0x48efc857, - 0x59a00207, 0x59a01407, 0x900001c0, 0x80081540, - 0x59a00209, 0x59a01c09, 0x900001c0, 0x800c1d40, - 0x59a00406, 0x48034000, 0x480b4001, 0x480f4002, - 0x0201f800, 0x0010381a, 0x04020005, 0x4a034406, - 0x00000002, 0x0201f000, 0x001020b2, 0x42000800, - 0x00000010, 0x0201f800, 0x0010383e, 0x4a01d809, - 0x00102e2e, 0x1c01f000, 0x4031d800, 0x58ef400b, - 0x58ee580d, 0x58ec0002, 0x82000580, 0x00000200, - 0x02000000, 0x001020aa, 0x48efc857, 0x49a3c857, - 0x492fc857, 0x592c0a04, 0x80040910, 0x04020005, - 0x4a034406, 0x00000019, 0x0201f000, 0x001020b2, - 0x4805d80c, 0x0401f00a, 0x4031d800, 0x58ef400b, - 0x58ec0002, 0x82000580, 0x00000200, 0x02000000, - 0x001020aa, 0x48efc857, 0x49a3c857, 0x48efc857, - 0x49a3c857, 0x58ec000c, 0x80000040, 0x04000012, - 0x4801d80c, 0x0201f800, 0x0010381a, 0x04020005, - 0x4a034406, 0x00000002, 0x0201f000, 0x001020b2, - 0x42000800, 0x00000010, 0x58ec1007, 0x58ec1808, - 0x0201f800, 0x0010383e, 0x4a01d809, 0x00102e42, - 0x1c01f000, 0x58ee580d, 0x48efc857, 0x49a3c857, - 0x492fc857, 0x492f3006, 0x592c0404, 0x8400055e, - 0x48025c04, 0x4a01d809, 0x00102e6c, 0x1c01f000, - 0x4d2c0000, 0x58ee580d, 0x48efc857, 0x49a3c857, - 0x492fc857, 0x592c0404, 0x8400051e, 0x48025c04, - 0x59a00000, 0x59a01001, 0x59a01802, 0x80081400, - 0x820c1c40, 0x00000000, 0x832c0400, 0x00000004, - 0x42000800, 0x00000010, 0x5c025800, 0x0201f000, - 0x00103841, 0x800409c0, 0x04000005, 0x4a034406, - 0x00000001, 0x0201f000, 0x001020b2, 0x836c0580, - 0x00000003, 0x04000005, 0x4a034406, 0x00000007, - 0x0201f000, 0x001020b2, 0x59a0320b, 0x82183500, - 0x000000ff, 0x59a28c06, 0x0201f800, 0x00020267, - 0x02020000, 0x001020b6, 0x83440580, 0x000007fd, - 0x04000008, 0x0201f800, 0x00104836, 0x04000005, - 0x4a034406, 0x00000009, 0x0201f000, 0x001020b2, - 0x0201f800, 0x0010381a, 0x04020005, 0x4a034406, - 0x00000002, 0x0201f000, 0x001020b2, 0x801831c0, - 0x0400000a, 0x412c0800, 0x0201f800, 0x0010381a, - 0x04020005, 0x4a034406, 0x00000002, 0x0201f000, - 0x001020b2, 0x40065800, 0x4a025c04, 0x00008000, - 0x497a5a04, 0x0201f800, 0x00108ebd, 0x04020005, - 0x4a034406, 0x00000003, 0x0201f000, 0x001020b2, - 0x4a01d809, 0x00102ebf, 0x1c01f000, 0x592c0005, - 0x82000580, 0x01000000, 0x04020005, 0x4a034406, - 0x00000004, 0x0201f000, 0x001020b2, 0x592c0406, - 0x82002d00, 0x0000ff00, 0x82000500, 0x000000ff, - 0x80000904, 0x80040800, 0x82040480, 0x00000006, - 0x04001003, 0x42000800, 0x00000005, 0x4c500000, - 0x4c540000, 0x4c580000, 0x832ca400, 0x00000006, - 0x4050a800, 0x4004b000, 0x0201f800, 0x0010a94f, - 0x59a00407, 0x59a01207, 0x900811c0, 0x80081540, - 0x59a00409, 0x59a01a09, 0x900c19c0, 0x800c1d40, - 0x832c0400, 0x00000006, 0x4c140000, 0x0201f800, - 0x00103841, 0x5c002800, 0x801429c0, 0x04000003, - 0x4a01d809, 0x00102ef2, 0x5c00b000, 0x5c00a800, - 0x5c00a000, 0x1c01f000, 0x4031d800, 0x58ef400b, - 0x58ee580d, 0x58ec0002, 0x82000580, 0x00000200, - 0x02000000, 0x001020aa, 0x812e59c0, 0x02000800, - 0x00100615, 0x592c0006, 0x82000500, 0xff000000, - 0x80000904, 0x800409c0, 0x02000000, 0x001020aa, - 0x82040480, 0x0000000e, 0x04001003, 0x42000800, - 0x0000000d, 0x592e5801, 0x812e59c0, 0x02000800, - 0x00100615, 0x4c500000, 0x4c540000, 0x4c580000, - 0x832ca400, 0x00000005, 0x4050a800, 0x4004b000, - 0x0201f800, 0x0010a94f, 0x5c00b000, 0x5c00a800, - 0x5c00a000, 0x58ec1007, 0x58ec1808, 0x832c0400, - 0x00000005, 0x0201f000, 0x00103841, 0x0201f800, - 0x0010381a, 0x04020005, 0x4a034406, 0x00000002, - 0x0201f000, 0x001020b2, 0x59a00c06, 0x82040500, - 0x0000ff00, 0x840001c0, 0x82001480, 0x00000007, - 0x02021000, 0x001020b6, 0x0c01f001, 0x00102f36, - 0x00102f3d, 0x00102f44, 0x00102f44, 0x00102f44, - 0x00102f46, 0x00102f4b, 0x42000800, 0x0000000d, - 0x42003800, 0x00102f5f, 0x4a034000, 0x0010b2e7, - 0x0401f013, 0x42000800, 0x0000000d, 0x42003800, - 0x00102f5f, 0x4a034000, 0x0010b2f4, 0x0401f00c, - 0x0201f000, 0x001020b6, 0x42000800, 0x00000008, - 0x42003800, 0x00102f72, 0x0401f005, 0x42000800, - 0x00000004, 0x42003800, 0x00102fbc, 0x59a00207, - 0x59a01407, 0x900001c0, 0x80081540, 0x59a00209, - 0x59a01c09, 0x900001c0, 0x800c1d40, 0x832c0400, - 0x00000005, 0x4c1c0000, 0x0201f800, 0x0010383e, - 0x5c003800, 0x481dd809, 0x1c01f000, 0x4031d800, - 0x58ef400b, 0x58ee580d, 0x58ec0002, 0x82000580, - 0x00000200, 0x02000000, 0x001020aa, 0x4a03501f, - 0x00000001, 0x4200b000, 0x0000000d, 0x59a0a800, - 0x832ca400, 0x00000005, 0x0201f800, 0x0010a93e, - 0x0201f000, 0x00102066, 0x4031d800, 0x58ef400b, - 0x58ee580d, 0x58ec0002, 0x82000580, 0x00000200, - 0x02000000, 0x001020aa, 0x832ca400, 0x00000005, - 0x50500000, 0x82001500, 0x000c0016, 0x02020000, - 0x001020b6, 0x82500c00, 0x00000003, 0x50040000, - 0x82001500, 0x00000001, 0x02020000, 0x001020b6, - 0x50500000, 0x82001500, 0x00000028, 0x0400001d, - 0x82081580, 0x00000028, 0x02020000, 0x001020b6, - 0x80500800, 0x50040000, 0x82001500, 0x00000013, - 0x82081580, 0x00000013, 0x02020000, 0x001020b6, - 0x80040800, 0x50040000, 0x82001500, 0x00010000, - 0x82081580, 0x00010000, 0x02020000, 0x001020b6, - 0x836c0580, 0x00000000, 0x04000012, 0x599c0019, - 0x8c00050e, 0x0402000f, 0x0201f000, 0x001020b6, - 0x80500800, 0x50040000, 0x82001500, 0x00000013, - 0x02020000, 0x001020b6, 0x80040800, 0x50040000, - 0x82001500, 0x00010000, 0x02020000, 0x001020b6, - 0x4200b000, 0x00000008, 0x4200a800, 0x0010b2df, - 0x0201f800, 0x0010a93e, 0x0201f000, 0x00102066, - 0x4031d800, 0x58ef400b, 0x58ee580d, 0x58ec0002, - 0x82000580, 0x00000200, 0x02000000, 0x001020aa, - 0x4200b000, 0x00000004, 0x4200a800, 0x0010b6f9, - 0x832ca400, 0x00000005, 0x0201f800, 0x0010a93e, - 0x59a80005, 0x84000550, 0x48035005, 0x0201f000, - 0x00102066, 0x0201f800, 0x0010381a, 0x04020005, - 0x4a034406, 0x00000002, 0x0201f000, 0x001020b2, - 0x59a00c06, 0x82040500, 0x0000ff00, 0x840001c0, - 0x82001480, 0x00000006, 0x02021000, 0x001020b6, - 0x0c01f001, 0x00102fe7, 0x00102fec, 0x00102ff1, - 0x00102ff1, 0x00102ff1, 0x00102ff3, 0x42000800, - 0x0000000d, 0x4200a000, 0x0010b2e7, 0x0401f00c, - 0x42000800, 0x0000000d, 0x4200a000, 0x0010b2f4, - 0x0401f007, 0x0201f000, 0x001020b6, 0x42000800, - 0x00000008, 0x4200a000, 0x0010b2df, 0x4004b000, - 0x832cac00, 0x00000005, 0x0201f800, 0x0010a93e, - 0x59a00207, 0x59a01407, 0x900001c0, 0x80081540, - 0x59a00209, 0x59a01c09, 0x900001c0, 0x800c1d40, - 0x832c0400, 0x00000005, 0x0201f000, 0x00103841, - 0x836c0580, 0x00000000, 0x04020005, 0x4a034406, - 0x00000007, 0x0201f000, 0x001020b2, 0x59a01406, - 0x800811c0, 0x04020017, 0x59c40801, 0x82040d00, - 0x00018000, 0x82040580, 0x00000000, 0x04020004, - 0x4a034406, 0x00000000, 0x0401f048, 0x82040580, - 0x00008000, 0x04020004, 0x4a034406, 0x00000001, - 0x0401f042, 0x82040580, 0x00010000, 0x02020800, - 0x00100615, 0x4a034406, 0x00000003, 0x0401f03b, - 0x59a8006f, 0x8c000508, 0x04000005, 0x42000000, - 0x00000001, 0x40000800, 0x0401f003, 0x59a00207, - 0x59a80853, 0x48035053, 0x0201f800, 0x001016ac, - 0x0400000d, 0x0201f800, 0x001016b3, 0x0400000a, - 0x0201f800, 0x001016ba, 0x04000007, 0x0201f800, - 0x001016c1, 0x04000004, 0x48075053, 0x0201f000, - 0x001020b6, 0x82080580, 0x00000002, 0x0402001f, - 0x59c40006, 0x84000500, 0x48038806, 0x0201f800, - 0x00106c32, 0x497b8880, 0x0201f800, 0x0010a7e7, - 0x0201f800, 0x0010a7f5, 0x42000000, 0x0010b6c9, - 0x0201f800, 0x0010a86e, 0x82000540, 0x00000001, - 0x0201f800, 0x00104e5d, 0x4a038808, 0x00000000, - 0x4202d800, 0x00000004, 0x42001000, 0x00000001, - 0x0201f800, 0x001019aa, 0x4a035049, 0x00000001, - 0x0201f800, 0x0010071a, 0x0201f000, 0x00102066, - 0x800409c0, 0x04000005, 0x4a034406, 0x00000001, - 0x0201f000, 0x001020b2, 0x836c0580, 0x00000003, - 0x04000005, 0x4a034406, 0x00000007, 0x0201f000, - 0x001020b2, 0x59a28c06, 0x59a0320b, 0x82183500, - 0x000000ff, 0x0201f800, 0x00020267, 0x02020000, - 0x001020b6, 0x83440580, 0x000007fd, 0x04000008, - 0x0201f800, 0x00104836, 0x04000005, 0x42000800, - 0x00000009, 0x0201f000, 0x001020b2, 0x0201f800, - 0x0010381a, 0x04020005, 0x4a034406, 0x00000002, - 0x0201f000, 0x001020b2, 0x497a5a04, 0x4a025c04, - 0x00008000, 0x0201f800, 0x00108ed2, 0x04020005, - 0x4a034406, 0x00000003, 0x0201f000, 0x001020b2, - 0x4a01d809, 0x00103097, 0x1c01f000, 0x592c0005, - 0x82000d00, 0x0000ffff, 0x82000500, 0xffff0000, - 0x82000580, 0x01000000, 0x04020005, 0x4a034406, - 0x00000004, 0x0201f000, 0x001020b2, 0x80040904, - 0x4c500000, 0x4c540000, 0x4c580000, 0x832ca400, - 0x00000005, 0x4050a800, 0x4004b000, 0x0201f800, - 0x0010a94f, 0x5c00b000, 0x5c00a800, 0x5c00a000, - 0x59a00207, 0x59a01407, 0x900001c0, 0x80081540, - 0x59a00209, 0x59a01c09, 0x900001c0, 0x800c1d40, - 0x832c0400, 0x00000005, 0x0201f000, 0x00103841, - 0x496fc857, 0x836c0580, 0x00000000, 0x04000005, - 0x4a034406, 0x0000001a, 0x0201f000, 0x001020b2, - 0x0201f800, 0x00104e0d, 0x02020800, 0x00103f5c, - 0x42000800, 0x00000020, 0x59a00407, 0x59a01207, - 0x900811c0, 0x80081540, 0x59a00409, 0x59a01a09, - 0x900c19c0, 0x800c1d40, 0x419c0000, 0x49a3c857, - 0x0201f800, 0x0010383e, 0x4a01d809, 0x001030d9, - 0x1c01f000, 0x4833c857, 0x4031d800, 0x58ef400b, - 0x58ec0002, 0x82000580, 0x00000200, 0x02000000, - 0x001020aa, 0x599c0200, 0x800001c0, 0x02000000, - 0x001020b6, 0x59a8006f, 0x8c000504, 0x04020003, - 0x8c000506, 0x04000004, 0x599c0019, 0x8400050c, - 0x48033819, 0x0201f800, 0x001095a3, 0x59a8006f, - 0x8c000502, 0x04000004, 0x599c0017, 0x84000508, - 0x48033817, 0x0201f800, 0x0010393e, 0x04020004, - 0x8c00050a, 0x02020000, 0x001020b6, 0x4803c857, - 0x8c000504, 0x04020004, 0x59c408a3, 0x84040d7a, - 0x480788a3, 0x8c000502, 0x04020004, 0x59c408a3, - 0x84040d08, 0x480788a3, 0x599c0c02, 0x8c000500, - 0x04020004, 0x8c000516, 0x04000012, 0x0401f001, - 0x82041480, 0x0000007f, 0x02021000, 0x001020b6, - 0x82041400, 0x00101eb5, 0x50081000, 0x82081500, - 0x000000ff, 0x8c000500, 0x04020006, 0x480b5010, - 0x42000800, 0x00000003, 0x0201f800, 0x001069af, - 0x599c0019, 0x8c000506, 0x04000003, 0x4a03b805, - 0x90000000, 0x8c00050e, 0x0402000b, 0x59a80806, - 0x8c040d14, 0x04000008, 0x42000800, 0x0010b2df, - 0x50040800, 0x82040d00, 0x00000028, 0x02020000, - 0x001020b6, 0x82000500, 0x00000030, 0x04000003, - 0x80000108, 0x0401f003, 0x42000000, 0x00000002, - 0x48039040, 0x42000800, 0x00000002, 0x82000400, - 0x0010321c, 0x50001000, 0x0201f800, 0x001069af, - 0x599c0201, 0x82000c80, 0x00000100, 0x02001000, - 0x001020b6, 0x82000c80, 0x00000841, 0x02021000, - 0x001020b6, 0x82000500, 0x00000007, 0x02020000, - 0x001020b6, 0x599c0401, 0x80000540, 0x02000000, - 0x001020b6, 0x599c0409, 0x599c0c07, 0x80040c80, - 0x02021000, 0x001020b6, 0x80000040, 0x02000000, - 0x001020b6, 0x599c0209, 0x599c0a07, 0x80040c80, - 0x02021000, 0x001020b6, 0x80000040, 0x02000000, - 0x001020b6, 0x0201f800, 0x0010509d, 0x0201f800, - 0x00104b53, 0x599c0201, 0x48035004, 0x0201f800, - 0x0010133e, 0x599c020a, 0x800001c0, 0x04000003, - 0x4803504d, 0x0401f003, 0x4a03504d, 0x000000c8, - 0x0201f800, 0x0010393e, 0x04000004, 0x0201f800, - 0x00105e18, 0x417a5000, 0x836c0580, 0x00000000, - 0x0402009a, 0x599c0003, 0x599c0804, 0x9c0001c0, - 0x9c0409c0, 0x48035002, 0x48075003, 0x599c1017, - 0x8c08151c, 0x04000006, 0x599c0005, 0x599c0806, - 0x9c0001c0, 0x9c0409c0, 0x0401f003, 0x82000500, - 0xf0ffffff, 0x48035000, 0x48075001, 0x42001000, - 0x0010b2e7, 0x48001000, 0x48041001, 0x42001000, - 0x0010b2f4, 0x48001000, 0x48041001, 0x59a8006f, - 0x8c000508, 0x04020017, 0x8c00050a, 0x04020021, - 0x599c1019, 0x82081500, 0x0000e000, 0x82080580, - 0x00000000, 0x0402000c, 0x4a035053, 0x00000000, - 0x42000000, 0x00000001, 0x0201f800, 0x001018fa, - 0x42000000, 0x00000001, 0x0201f800, 0x00101892, - 0x0401f02b, 0x82080580, 0x00002000, 0x0402000a, - 0x4a035053, 0x00000001, 0x41780000, 0x0201f800, - 0x001018fa, 0x41780000, 0x0201f800, 0x00101892, - 0x0401f01f, 0x82080580, 0x00004000, 0x04020006, - 0x4a035053, 0x00000002, 0x4a035049, 0x00000001, - 0x0401f017, 0x82080580, 0x00006000, 0x02020000, - 0x001020b6, 0x59a80858, 0x82040d80, 0x01391077, - 0x04020005, 0x59e00813, 0x8c040d00, 0x02020000, - 0x001020b6, 0x4a035053, 0x00000003, 0x42000000, - 0x00000002, 0x0201f800, 0x001018fa, 0x42000000, - 0x00000002, 0x0201f800, 0x00101892, 0x599c0019, - 0x8c000520, 0x0400000d, 0x42000000, 0x00000004, - 0x42000800, 0x00000040, 0x0201f800, 0x001019b1, - 0x42000000, 0x00000010, 0x42000800, 0x000000c0, - 0x0201f800, 0x001019b1, 0x4a035032, 0x0000aaaa, - 0x599c1018, 0x82081500, 0x00000030, 0x59a8006c, - 0x80000540, 0x0400000c, 0x82080580, 0x00000000, - 0x02000000, 0x001020b6, 0x599c1018, 0x82081500, - 0xffffffcf, 0x82081540, 0x00000010, 0x480b3818, - 0x0401f010, 0x82080d80, 0x00000000, 0x04000007, - 0x82080d80, 0x00000010, 0x0400000a, 0x82080d80, - 0x00000020, 0x04020002, 0x48075032, 0x0201f800, - 0x001038d3, 0x04000008, 0x0201f800, 0x00101668, - 0x0201f800, 0x00101694, 0x59a8002a, 0x80040540, - 0x4803502a, 0x49f3c857, 0x42001000, 0x00104d39, - 0x0201f800, 0x00105cc9, 0x42001000, 0x00104d2c, - 0x0201f800, 0x00105dbd, 0x4a038805, 0xffffffff, - 0x4a03c014, 0x00400040, 0x4a03c013, 0x00400000, - 0x0201f800, 0x00104717, 0x59a0001d, 0x84000540, - 0x4803401d, 0x49f3c857, 0x0201f000, 0x00102066, - 0x00000018, 0x0000000c, 0x00000018, 0x00000020, - 0x836c0580, 0x00000000, 0x04020005, 0x42000800, - 0x00000007, 0x0201f000, 0x001020b2, 0x42000800, - 0x00000020, 0x59a00407, 0x59a01207, 0x900811c0, - 0x80081540, 0x59a00409, 0x59a01a09, 0x900c19c0, - 0x800c1d40, 0x419c0000, 0x0201f000, 0x00103841, - 0x800409c0, 0x04000005, 0x4a034406, 0x00000001, - 0x0201f000, 0x001020b2, 0x0201f800, 0x00104e0d, - 0x04020005, 0x4a034406, 0x00000016, 0x0201f000, - 0x001020b2, 0x59a80013, 0x8c000500, 0x04000011, - 0x4a034406, 0x00000000, 0x42000800, 0x00000020, - 0x59a00407, 0x59a01207, 0x900811c0, 0x80081540, - 0x59a00409, 0x59a01a09, 0x900c19c0, 0x800c1d40, - 0x42000000, 0x0010bc20, 0x0201f000, 0x00103841, - 0x4a034406, 0x00000001, 0x4200b000, 0x00000020, - 0x4200a800, 0x0010bc20, 0x4200a000, 0xffffffff, - 0x4450a800, 0x8054a800, 0x8058b040, 0x040207fd, - 0x4d440000, 0x4d340000, 0x42028800, 0xffffffff, - 0x42002000, 0xffffffff, 0x42003000, 0x00000001, - 0x42003800, 0x00000001, 0x42001800, 0x0010bc20, - 0x59a81010, 0x82081500, 0x000000ff, 0x40180000, - 0x0c01f001, 0x00103275, 0x00103278, 0x0010327c, - 0x00103280, 0x82102500, 0xffffff00, 0x0401f014, - 0x82102500, 0xffff00ff, 0x840811c0, 0x0401f010, - 0x82102500, 0xff00ffff, 0x900811c0, 0x0401f00c, - 0x82102500, 0x00ffffff, 0x9c0801c0, 0x80102540, - 0x44101800, 0x42003000, 0xffffffff, 0x42002000, - 0xffffffff, 0x800c1800, 0x0401f003, 0x40080000, - 0x80102540, 0x81468800, 0x83442c80, 0x0000007f, - 0x04021014, 0x4c080000, 0x4c0c0000, 0x4c180000, - 0x4c1c0000, 0x0201f800, 0x00020267, 0x5c003800, - 0x5c003000, 0x5c001800, 0x5c001000, 0x040207f2, - 0x0201f800, 0x00104842, 0x040207ef, 0x80183000, - 0x801c3800, 0x59341202, 0x40180000, 0x0c01f7ce, - 0x82100580, 0xffffffff, 0x04000002, 0x44101800, - 0x42001800, 0x0010bc20, 0x500c0000, 0x82000500, - 0xffffff00, 0x801c0540, 0x44001800, 0x5c026800, - 0x5c028800, 0x42000800, 0x00000020, 0x59a00407, - 0x59a01207, 0x900811c0, 0x80081540, 0x59a00409, - 0x59a01a09, 0x900c19c0, 0x800c1d40, 0x42000000, - 0x0010bc20, 0x0201f000, 0x00103841, 0x59a28c06, - 0x59a0020b, 0x8c000500, 0x0400000e, 0x59a01208, - 0x59a00408, 0x82000500, 0x000000ff, 0x900001c0, - 0x80081540, 0x41784000, 0x0201f800, 0x00104768, - 0x04000008, 0x48034406, 0x0201f000, 0x001020b6, - 0x0201f800, 0x00020267, 0x02020000, 0x001020b6, - 0x0201f800, 0x0010381a, 0x04020005, 0x4a034406, - 0x00000002, 0x0201f000, 0x001020b2, 0x59a0020b, - 0x8c000500, 0x04000005, 0x0201f800, 0x00104842, - 0x02020000, 0x001038dd, 0x59a0020b, 0x8c000502, - 0x04000019, 0x83440480, 0x000007f0, 0x04021016, - 0x0201f800, 0x0010484b, 0x04020013, 0x497a5a04, - 0x4a025c04, 0x00008000, 0x0201f800, 0x00108ea3, - 0x04020005, 0x4a034406, 0x00000003, 0x0201f000, - 0x001020b2, 0x4a01d809, 0x001032f8, 0x1c01f000, - 0x59a28c06, 0x0201f800, 0x00020267, 0x02020000, - 0x001020b6, 0x4c580000, 0x4c500000, 0x4c540000, - 0x4200b000, 0x0000000a, 0x4134a000, 0x832e5c00, - 0x00000002, 0x412ca800, 0x0201f800, 0x0010a93e, - 0x832cac00, 0x00000006, 0x4054a000, 0x4200b000, - 0x00000004, 0x0201f800, 0x0010a94f, 0x5c00a800, - 0x5c00a000, 0x5c00b000, 0x592c0802, 0x82040500, - 0x00ff00ff, 0x900001c0, 0x82041500, 0xff00ff00, - 0x80080540, 0x48025802, 0x592c0801, 0x82040500, - 0x00ff00ff, 0x900001c0, 0x82041500, 0xff00ff00, - 0x80080540, 0x48025801, 0x42000800, 0x0000000a, - 0x59a00407, 0x59a01207, 0x900811c0, 0x80081540, - 0x59a00409, 0x59a01a09, 0x900c19c0, 0x800c1d40, - 0x412c0000, 0x0201f000, 0x00103841, 0x496fc857, - 0x496f4406, 0x0201f000, 0x00102066, 0x59a28c06, - 0x0201f800, 0x00020267, 0x02020000, 0x001020b6, - 0x836c0580, 0x00000003, 0x04000005, 0x4a034406, - 0x00000007, 0x0201f000, 0x001020b2, 0x83340c00, - 0x00000006, 0x59a0020b, 0x8c000500, 0x04000003, - 0x83340c00, 0x00000008, 0x58040001, 0x48034409, - 0x900001c0, 0x48034209, 0x50040000, 0x48034407, - 0x900001c0, 0x48034207, 0x59340200, 0x48034406, - 0x0201f000, 0x00102066, 0x800409c0, 0x04000005, - 0x4a034406, 0x00000001, 0x0201f000, 0x001020b2, - 0x59a0220b, 0x8c102500, 0x0402002e, 0x8c102506, - 0x04020006, 0x59a03208, 0x82180480, 0x00000003, - 0x02021000, 0x001020b6, 0x59a28c06, 0x0201f800, - 0x00020267, 0x02020000, 0x001020b6, 0x0201f800, - 0x00104836, 0x04000005, 0x4a034406, 0x00000009, - 0x0201f000, 0x001020b2, 0x0201f800, 0x0010381a, - 0x04020005, 0x4a034406, 0x00000002, 0x0201f000, - 0x001020b2, 0x59a0220b, 0x8c102506, 0x04000004, - 0x59343002, 0x82183500, 0x00ffffff, 0x497a5a04, - 0x4a025c04, 0x00008000, 0x0201f800, 0x00108e65, - 0x04020005, 0x4a034406, 0x00000003, 0x0201f000, - 0x001020b2, 0x4a01d809, 0x001033de, 0x1c01f000, - 0x59a28c06, 0x0201f800, 0x00020267, 0x02020000, - 0x001020b6, 0x0201f800, 0x00104836, 0x04000005, - 0x4a034406, 0x00000009, 0x0201f000, 0x001020b2, - 0x0201f800, 0x0010381a, 0x04020005, 0x4a034406, - 0x00000002, 0x0201f000, 0x001020b2, 0x497a5a04, - 0x4a025c04, 0x00008000, 0x0201f800, 0x0010381a, - 0x04020005, 0x4a034406, 0x00000002, 0x0201f000, - 0x001020b2, 0x592e5800, 0x0201f800, 0x00108e7a, - 0x04020005, 0x4a034406, 0x00000003, 0x0201f000, - 0x001020b2, 0x4a01d809, 0x001033b0, 0x1c01f000, - 0x592c2805, 0x82140d80, 0x01000000, 0x04020005, - 0x4a034406, 0x00000004, 0x0201f000, 0x001020b2, - 0x42000800, 0x00000008, 0x59a00207, 0x59a01407, - 0x900001c0, 0x80081540, 0x59a00209, 0x59a01c09, - 0x900001c0, 0x800c1d40, 0x832c0400, 0x00000005, - 0x0201f800, 0x00103841, 0x8c142d00, 0x04000003, - 0x4a01d809, 0x001033cb, 0x1c01f000, 0x4031d800, - 0x58ef400b, 0x58ee580e, 0x58ec0002, 0x82000580, - 0x00000200, 0x02000000, 0x001020aa, 0x812e59c0, - 0x02000800, 0x00100615, 0x42000800, 0x00000008, - 0x832c0400, 0x00000005, 0x58ec1007, 0x58ec1808, - 0x0201f000, 0x00103841, 0x592c0005, 0x82000580, - 0x01000000, 0x04020005, 0x4a034406, 0x00000004, - 0x0201f000, 0x001020b2, 0x59a00207, 0x59a01407, - 0x900001c0, 0x80081540, 0x59a00209, 0x59a01c09, - 0x900001c0, 0x800c1d40, 0x42000800, 0x00000006, - 0x832c0400, 0x00000006, 0x0201f000, 0x00103841, - 0x59a00a0a, 0x800409c0, 0x02000000, 0x001020b6, - 0x82040480, 0x000000e8, 0x04001003, 0x42000800, - 0x000000e7, 0x59a00207, 0x59a01407, 0x900001c0, - 0x80081540, 0x59a00209, 0x59a01c09, 0x900001c0, - 0x800c1d40, 0x83880400, 0x00000000, 0x0201f800, - 0x00103841, 0x4a01d809, 0x0010340c, 0x1c01f000, - 0x4031d800, 0x58ef400b, 0x58ec0002, 0x82000580, - 0x00000200, 0x02000000, 0x001020aa, 0x59a0020b, - 0x8c000500, 0x04000008, 0x83880400, 0x00000000, - 0x4803c840, 0x4a03c842, 0x00000006, 0x04011000, - 0x497b8885, 0x4a034207, 0x000000e7, 0x0201f000, - 0x00102066, 0x800409c0, 0x04000005, 0x4a034406, - 0x00000001, 0x0201f000, 0x001020b2, 0x0401fbf3, - 0x04020005, 0x4a034406, 0x00000002, 0x0201f000, - 0x001020b2, 0x497a5a04, 0x4a025c04, 0x00008000, - 0x59a00406, 0x800001c0, 0x02000000, 0x001020b6, - 0x82001580, 0x000000ff, 0x04000005, 0x82001480, - 0x00000004, 0x02021000, 0x001020b6, 0x40001000, - 0x0201f800, 0x00101d6a, 0x04020005, 0x4a034406, - 0x00000003, 0x0201f000, 0x001020b2, 0x4a01d809, - 0x00103446, 0x1c01f000, 0x592c0005, 0x82000580, - 0x01000000, 0x02020000, 0x00102066, 0x4a034406, - 0x00000004, 0x0201f000, 0x001020b2, 0x59a01406, - 0x8c081508, 0x04020007, 0x800409c0, 0x04000005, - 0x4a034406, 0x00000001, 0x0201f000, 0x001020b2, - 0x59a01c07, 0x820c0480, 0x00001000, 0x02021000, - 0x001020b6, 0x497b2804, 0x497b2805, 0x497b281c, - 0x497b281d, 0x497b281f, 0x497b2820, 0x497b2822, - 0x497b2823, 0x80000580, 0x0201f800, 0x00101668, - 0x59a80805, 0x8c081500, 0x04000004, 0x82040d40, - 0x00000011, 0x0401f004, 0x8c081506, 0x04000002, - 0x84040d42, 0x84040d0a, 0x48075005, 0x4202d800, - 0x00000001, 0x82081500, 0x000000e0, 0x8008010a, - 0x0c020036, 0x0201f800, 0x00104e0d, 0x04020009, - 0x4a035033, 0x00000001, 0x0201f800, 0x00104d76, - 0x0401f01f, 0x4a035033, 0x00000000, 0x0401f7fb, - 0x497b5032, 0x0201f800, 0x00103f5c, 0x0201f800, - 0x0010698c, 0x0201f800, 0x00106c32, 0x0201f800, - 0x00106982, 0x59a00a07, 0x480788a7, 0x59c400a3, - 0x82000500, 0xfeffffff, 0x82000540, 0x80018000, - 0x40000800, 0x84040d20, 0x480388a3, 0x480788a3, - 0x497b504e, 0x42000800, 0x0000002d, 0x42001000, - 0x00103fe4, 0x0201f800, 0x00105ca2, 0x59a00407, - 0x800000c2, 0x800008c4, 0x8005d400, 0x42000000, - 0x0000ffff, 0x0201f800, 0x00104e0d, 0x04000003, - 0x59a00207, 0x80000110, 0x0201f800, 0x00103915, - 0x0201f000, 0x00102066, 0x00103479, 0x0010347c, - 0x00103484, 0x001020b6, 0x00103481, 0x001020b6, - 0x001020b6, 0x001020b6, 0x836c0580, 0x00000003, - 0x04000005, 0x4a034406, 0x00000007, 0x0201f000, - 0x001020b2, 0x59a03c06, 0x59a00407, 0x59a04a07, - 0x902449c0, 0x80244d40, 0x59a00409, 0x59a05209, - 0x902851c0, 0x80285540, 0x0401fb54, 0x04020005, - 0x4a034406, 0x00000002, 0x0201f000, 0x001020b2, - 0x417a8800, 0x41783000, 0x497b4001, 0x497b4004, - 0x832c4400, 0x00000005, 0x48234002, 0x8c1c3d04, - 0x04020078, 0x0201f800, 0x00020267, 0x0402002a, - 0x0201f800, 0x00104836, 0x04000004, 0x0201f800, - 0x00104732, 0x04020024, 0x8c1c3d00, 0x04000008, - 0x59340009, 0x44004000, 0x59340008, 0x80204000, - 0x44004000, 0x80204000, 0x0401f007, 0x59340007, - 0x44004000, 0x59340006, 0x80204000, 0x44004000, - 0x80204000, 0x83440580, 0x000007fe, 0x0400000d, - 0x83440580, 0x000007fc, 0x0400000a, 0x0201f800, - 0x00104842, 0x04000003, 0x85468d5e, 0x0401f005, - 0x0201f800, 0x00104686, 0x04020002, 0x85468d5e, - 0x45444000, 0x85468d1e, 0x80204000, 0x82183400, - 0x00000003, 0x81468800, 0x83440480, 0x000007f0, - 0x0400100e, 0x8c1c3d06, 0x04000010, 0x83440580, - 0x000007f0, 0x04020004, 0x42028800, 0x000007fe, - 0x0401f006, 0x83440580, 0x000007ff, 0x04020007, - 0x42028800, 0x000007fc, 0x82180580, 0x0000000f, - 0x0400000b, 0x0401f7c0, 0x801831c0, 0x04020006, - 0x59a00801, 0x800408c4, 0x48074406, 0x0201f000, - 0x00102066, 0x4a034004, 0x00000001, 0x49474000, - 0x59a00001, 0x80180400, 0x48034001, 0x481f4003, - 0x4a01d801, 0x00000000, 0x4819d804, 0x59a00002, - 0x4801d803, 0x4825d807, 0x4829d808, 0x4000a800, - 0x4000a000, 0x4018b000, 0x0201f800, 0x0010a93e, - 0x40ec1000, 0x0201f800, 0x001008a1, 0x4a01d809, - 0x00103536, 0x1c01f000, 0x4031d800, 0x58ef400b, - 0x58ec0002, 0x82000580, 0x00000200, 0x02000000, - 0x001020aa, 0x59a00004, 0x80000540, 0x04020008, - 0x59a28800, 0x59a04002, 0x59a03803, 0x41783000, - 0x58ec4807, 0x58ec5008, 0x0401f78f, 0x59a00801, - 0x800408c4, 0x48074406, 0x0201f000, 0x00102066, - 0x0201f800, 0x00020267, 0x0402002f, 0x0201f800, - 0x00104836, 0x04000004, 0x0201f800, 0x00104732, - 0x04020029, 0x83440580, 0x000007fe, 0x04000011, - 0x83440580, 0x000007fc, 0x0400000e, 0x0201f800, - 0x00104842, 0x04000005, 0x59340403, 0x8400055e, - 0x48026c03, 0x0401f007, 0x0201f800, 0x00104686, - 0x04020004, 0x59340403, 0x8400055e, 0x48026c03, - 0x4134a000, 0x4020a800, 0x4200b000, 0x00000006, - 0x0201f800, 0x0010a93e, 0x59340007, 0x4400a800, - 0x59340006, 0x4800a801, 0x59340009, 0x4800a802, - 0x59340008, 0x4800a803, 0x59340403, 0x8400051e, - 0x48026c03, 0x82204400, 0x0000000a, 0x82183400, - 0x0000000a, 0x81468800, 0x83440480, 0x000007f0, - 0x0400100e, 0x8c1c3d06, 0x04000010, 0x83440580, - 0x000007f0, 0x04020004, 0x42028800, 0x000007fe, - 0x0401f006, 0x83440580, 0x000007ff, 0x04020007, - 0x42028800, 0x000007fc, 0x82180580, 0x0000000a, - 0x0400000b, 0x0401f7bb, 0x801831c0, 0x04020006, - 0x59a00801, 0x800408c4, 0x48074406, 0x0201f000, - 0x00102066, 0x4a034004, 0x00000001, 0x49474000, - 0x59a00001, 0x80180400, 0x48034001, 0x481f4003, - 0x4a01d801, 0x00000000, 0x4819d804, 0x59a00002, - 0x4801d803, 0x4825d807, 0x4829d808, 0x40ec1000, - 0x0201f800, 0x001008a1, 0x4a01d809, 0x001035ad, - 0x1c01f000, 0x4031d800, 0x58ef400b, 0x58ec0002, - 0x82000580, 0x00000200, 0x02000000, 0x001020aa, - 0x59a00004, 0x80000540, 0x04020008, 0x59a28800, - 0x59a04002, 0x59a03803, 0x41783000, 0x58ec4807, - 0x58ec5008, 0x0401f78f, 0x59a00801, 0x800408c4, - 0x48074406, 0x0201f000, 0x00102066, 0x42002800, - 0x0000007e, 0x59a00c06, 0x59a01207, 0x59a01c07, - 0x59a02209, 0x82040500, 0x0000ff00, 0x840001c0, - 0x82003480, 0x00000020, 0x02001000, 0x001020b6, - 0x80140480, 0x02001000, 0x001020b6, 0x82040500, - 0x000000ff, 0x82003480, 0x00000020, 0x02001000, - 0x001020b6, 0x80140480, 0x02001000, 0x001020b6, - 0x82080500, 0x0000ff00, 0x840001c0, 0x82003480, - 0x00000020, 0x02001000, 0x001020b6, 0x80140480, - 0x02001000, 0x001020b6, 0x82080500, 0x000000ff, - 0x82003480, 0x00000020, 0x02001000, 0x001020b6, - 0x80140480, 0x02001000, 0x001020b6, 0x820c0500, - 0x0000ff00, 0x840001c0, 0x82003480, 0x00000020, - 0x02001000, 0x001020b6, 0x80140480, 0x02001000, - 0x001020b6, 0x820c0500, 0x000000ff, 0x82003480, - 0x00000020, 0x02001000, 0x001020b6, 0x80140480, - 0x02001000, 0x001020b6, 0x82100500, 0x0000ff00, - 0x840001c0, 0x82003480, 0x00000020, 0x02001000, - 0x001020b6, 0x80140480, 0x02001000, 0x001020b6, - 0x82100500, 0x000000ff, 0x82003480, 0x00000020, - 0x02001000, 0x001020b6, 0x80140480, 0x02001000, - 0x001020b6, 0x900401c0, 0x80080d40, 0x900c01c0, - 0x80101d40, 0x83a83400, 0x0000003a, 0x44043000, - 0x80183000, 0x440c3000, 0x0201f000, 0x00102066, - 0x0401f9fa, 0x04020005, 0x4a034406, 0x00000002, - 0x0201f000, 0x001020b2, 0x42000800, 0x0000000c, - 0x0401f853, 0x4a01d809, 0x0010362c, 0x1c01f000, - 0x4031d800, 0x58ee580d, 0x58ef400b, 0x58ec0002, - 0x82000580, 0x00000200, 0x02000000, 0x001020aa, - 0x832ca400, 0x00000004, 0x4200b000, 0x0000000c, - 0x40c8a800, 0x0201f800, 0x0010a93e, 0x58c80200, - 0x80000540, 0x04000034, 0x58c80400, 0x82000500, - 0xfffffffb, 0x04020030, 0x58c80401, 0x80000540, - 0x0400002d, 0x82000480, 0x0000ff01, 0x0402102a, - 0x58c80202, 0x82000480, 0x0000005c, 0x04001026, - 0x0201f800, 0x001060db, 0x58c80c08, 0x58c80204, - 0x80040480, 0x04001020, 0x58c80204, 0x82000480, - 0x00000005, 0x0402101c, 0x58c80205, 0x58c80c08, - 0x80040902, 0x80040480, 0x04001017, 0x58c80c08, - 0x0201f800, 0x0010602a, 0x0400001b, 0x0201f800, - 0x00105ef2, 0x04020012, 0x4979940b, 0x59c408a3, - 0x82040d40, 0x00000002, 0x480788a3, 0x4a038830, - 0x00000001, 0x4a038832, 0x01ffffff, 0x58c80202, - 0x48030804, 0x0201f800, 0x00105ed4, 0x0201f000, - 0x00102066, 0x0201f000, 0x001020b6, 0x0201f800, - 0x0010612d, 0x0201f800, 0x0010613a, 0x0201f800, - 0x0010601d, 0x0201f000, 0x001020b2, 0x4c000000, - 0x59a01207, 0x59a00407, 0x900811c0, 0x80081540, - 0x59a01a09, 0x59a00409, 0x900c19c0, 0x800c1d40, - 0x5c000000, 0x0401f1b9, 0x59840000, 0x82000580, - 0x00000000, 0x04000050, 0x59840002, 0x8c000504, - 0x0400004d, 0x84000546, 0x48030802, 0x0201f800, - 0x0010601d, 0x59c408a3, 0x82040d00, 0xfffffffd, - 0x480788a3, 0x4c5c0000, 0x4200b800, 0x0010aa00, - 0x505e6800, 0x813669c0, 0x04000008, 0x5936600e, - 0x813261c0, 0x04000005, 0x0201f800, 0x0010600e, - 0x02000800, 0x001061e5, 0x805cb800, 0x825c0580, - 0x0010b1f0, 0x040207f3, 0x59866003, 0x813261c0, - 0x0400000b, 0x59300406, 0x82000580, 0x00000009, - 0x02020800, 0x00100615, 0x5930b800, 0x0201f800, - 0x00105ffa, 0x405e6000, 0x0401f7f5, 0x497b0803, - 0x4200b800, 0x0010b317, 0x505e6000, 0x813261c0, - 0x04000011, 0x59300406, 0x82000580, 0x00000009, - 0x0402000d, 0x59300203, 0x82000580, 0x00000004, - 0x04020009, 0x59326809, 0x813669c0, 0x02020800, - 0x00100615, 0x0201f800, 0x00100ee4, 0x0201f800, - 0x00105ffa, 0x4578b800, 0x805cb800, 0x825c0580, - 0x0010b31f, 0x040207e9, 0x42000800, 0x0010b315, - 0x49780801, 0x49780800, 0x0201f800, 0x0010612d, - 0x0201f800, 0x0010613a, 0x5c00b800, 0x0201f800, - 0x00105eed, 0x0201f000, 0x00102066, 0x836c0580, - 0x00000003, 0x04000005, 0x4a034406, 0x00000007, - 0x0201f000, 0x001020b2, 0x59a00407, 0x59a02207, - 0x901021c0, 0x80102540, 0x59a00409, 0x59a02a09, - 0x901429c0, 0x80142d40, 0x0401f930, 0x04020005, - 0x4a034406, 0x00000002, 0x0201f000, 0x001020b2, - 0x417a8800, 0x41781800, 0x497b4001, 0x497b4003, - 0x832c3400, 0x00000004, 0x481b4002, 0x41440000, - 0x81ac0400, 0x50026800, 0x813669c0, 0x0400000b, - 0x0201f800, 0x00104836, 0x04020008, 0x59340002, - 0x48003000, 0x49443001, 0x82183400, 0x00000002, - 0x820c1c00, 0x00000002, 0x81468800, 0x83440480, - 0x00000800, 0x04000005, 0x820c0480, 0x00000010, - 0x0402100b, 0x0401f7ea, 0x800c19c0, 0x04020006, - 0x59a00801, 0x80040902, 0x48074406, 0x0201f000, - 0x00102066, 0x4a034003, 0x00000001, 0x49474000, - 0x59a00001, 0x800c0400, 0x48034001, 0x40ec1000, - 0x4a001001, 0x00000000, 0x480c1004, 0x59a00002, - 0x48001003, 0x48101007, 0x48141008, 0x0201f800, - 0x001008a1, 0x4a01d809, 0x00103728, 0x1c01f000, - 0x4031d800, 0x58ef400b, 0x58ec0002, 0x82000580, - 0x00000200, 0x02000000, 0x001020aa, 0x59a00003, - 0x80000540, 0x04020008, 0x59a28800, 0x59a03002, - 0x41781800, 0x40ec1000, 0x58082007, 0x58082808, - 0x0401f7bf, 0x59a00801, 0x80040902, 0x48074406, - 0x0201f000, 0x00102066, 0x800409c0, 0x04000005, - 0x4a034406, 0x00000001, 0x0201f000, 0x001020b2, - 0x59a80026, 0x8c00050a, 0x04020007, 0x8c000506, - 0x04020005, 0x4a034406, 0x00000016, 0x0201f000, - 0x001020b2, 0x0401f8cd, 0x04020005, 0x4a034406, - 0x00000002, 0x0201f000, 0x001020b2, 0x59a00c06, - 0x80040902, 0x59a00407, 0x59a01207, 0x900811c0, - 0x80081540, 0x59a00409, 0x59a01a09, 0x900c19c0, - 0x800c1d40, 0x832c0400, 0x00000005, 0x0401f8df, - 0x4a01d809, 0x00103763, 0x1c01f000, 0x4031d800, - 0x58ef400b, 0x58ee580d, 0x58ec0002, 0x82000580, - 0x00000200, 0x02000000, 0x001020aa, 0x592c0009, - 0x0201f800, 0x001059b9, 0x02000800, 0x001043fc, - 0x02020000, 0x001020b6, 0x49474001, 0x481a6802, - 0x592c000a, 0x82001d80, 0x70000000, 0x04020007, - 0x0401f8a2, 0x04020011, 0x4a034406, 0x00000002, - 0x0201f000, 0x001020b2, 0x82001d80, 0x72000000, - 0x02020000, 0x001020b6, 0x0401f898, 0x04020897, - 0x04020896, 0x04020005, 0x4a034406, 0x00000002, - 0x0201f000, 0x001020b2, 0x58ee580d, 0x4a025c04, - 0x00008000, 0x497a5a04, 0x592c3208, 0x80183102, - 0x592c1801, 0x4a001805, 0x01000000, 0x0201f800, - 0x00108e8e, 0x04020005, 0x4a034406, 0x00000003, - 0x0201f000, 0x001020b2, 0x4a01d809, 0x0010379d, - 0x1c01f000, 0x592c4000, 0x592c0005, 0x82000580, - 0x01000000, 0x04020005, 0x4a034406, 0x00000004, - 0x0201f000, 0x001020b2, 0x4c580000, 0x4c500000, - 0x4c540000, 0x832c3c00, 0x00000005, 0x401ca000, - 0x401ca800, 0x5820280a, 0x4200b000, 0x00000002, - 0x82143580, 0x70000000, 0x04000003, 0x4200b000, - 0x0000000f, 0x0201f800, 0x0010a94f, 0x5c00a800, - 0x5c00a000, 0x5c00b000, 0x401c0000, 0x58201006, - 0x58201807, 0x58202205, 0x80102102, 0x82143580, - 0x70000000, 0x04020008, 0x82103480, 0x00000002, - 0x02001000, 0x001020b6, 0x42000800, 0x00000002, - 0x0401f079, 0x82143580, 0x72000000, 0x02020000, - 0x001020b6, 0x82103480, 0x0000002a, 0x02001000, - 0x001020b6, 0x42000800, 0x0000000f, 0x0401f86e, - 0x4a01d809, 0x001037d7, 0x1c01f000, 0x4031d800, - 0x58ef400b, 0x58ee580e, 0x58ec0002, 0x82000580, - 0x00000200, 0x02000000, 0x001020aa, 0x592e5800, - 0x832c0c00, 0x00000005, 0x4c580000, 0x4c500000, - 0x4c540000, 0x4004a000, 0x4004a800, 0x4200b000, - 0x0000000f, 0x0201f800, 0x0010a94f, 0x5c00a800, - 0x5c00a000, 0x5c00b000, 0x40ec1000, 0x4a001001, - 0x00000000, 0x4a001004, 0x0000000f, 0x48041003, - 0x0201f800, 0x001008a1, 0x4a01d809, 0x001037f9, - 0x1c01f000, 0x4031d800, 0x58ef400b, 0x58ee580e, - 0x58ec0002, 0x82000580, 0x00000200, 0x02000000, - 0x001020aa, 0x832c0c00, 0x00000005, 0x4c580000, - 0x4c500000, 0x4c540000, 0x4004a000, 0x4004a800, - 0x4200b000, 0x0000000c, 0x0201f800, 0x0010a94f, - 0x5c00a800, 0x5c00a000, 0x5c00b000, 0x40ec1000, - 0x4a001001, 0x00000000, 0x4a001004, 0x0000000c, - 0x48041003, 0x0201f800, 0x001008a1, 0x4a01d809, - 0x0010205f, 0x1c01f000, 0x0201f800, 0x0010082a, - 0x04000010, 0x497a5800, 0x58ec000d, 0x80000540, - 0x04020004, 0x492dd80d, 0x492dd80e, 0x0401f007, - 0x58ec000e, 0x48025800, 0x82000400, 0x00000001, - 0x452c0000, 0x492dd80e, 0x832c0400, 0x00000004, - 0x492fc857, 0x4803c857, 0x1c01f000, 0x4d2c0000, - 0x58ec400d, 0x802041c0, 0x04000008, 0x4823c857, - 0x40225800, 0x592c4001, 0x497a5801, 0x0201f800, - 0x0010083a, 0x0401f7f8, 0x4979d80d, 0x4979d80e, - 0x5c025800, 0x1c01f000, 0x42003000, 0x00000001, - 0x0401f003, 0x42003000, 0x00000000, 0x4803c857, - 0x4807c857, 0x480bc857, 0x480fc857, 0x481bc857, - 0x48efc857, 0x4819d801, 0x800409c0, 0x02000800, - 0x00100615, 0x4805d804, 0x4801d803, 0x4809d807, - 0x480dd808, 0x40ec1000, 0x0201f800, 0x001008a1, - 0x4a01d809, 0x0010205f, 0x1c01f000, 0x80002d80, - 0x480bc857, 0x480fc857, 0x4813c857, 0x4817c857, - 0x4d2c0000, 0x4da00000, 0x42034000, 0x0010b2a0, - 0x59a00017, 0x800001c0, 0x04020013, 0x04006012, - 0x480bc020, 0x480fc021, 0x4813c022, 0x4817c023, - 0x900811c0, 0x82081540, 0x00000012, 0x480bc011, - 0x59e00017, 0x8c000508, 0x04020004, 0x4203e000, - 0x30000001, 0x0401f053, 0x4a03c017, 0x00000002, - 0x0401f7fb, 0x4c040000, 0x4c1c0000, 0x80000800, - 0x48074017, 0x59a0381a, 0x481fc857, 0x801c39c0, - 0x04020027, 0x82000480, 0x0000000a, 0x04021010, - 0x59a00018, 0x80000000, 0x48034018, 0x59a00219, - 0x82000400, 0x00000002, 0x82000c80, 0x00000013, - 0x48034219, 0x04001003, 0x497b4219, 0x41780000, - 0x59a03816, 0x801c3c00, 0x0401f030, 0x4803c856, - 0x0201f800, 0x0010082a, 0x04000007, 0x492f401a, - 0x492f401b, 0x412c3800, 0x497b421c, 0x497a5813, - 0x0401f026, 0x59880052, 0x80000000, 0x48031052, - 0x59a00017, 0x80000040, 0x48034017, 0x59a00219, - 0x59a03816, 0x801c3c00, 0x0401f01c, 0x59a0021c, - 0x82000400, 0x00000002, 0x82000c80, 0x00000012, - 0x04021004, 0x4803421c, 0x801c3c00, 0x0401f013, - 0x0201f800, 0x0010082a, 0x0402000b, 0x59880052, - 0x80000000, 0x48031052, 0x59a00017, 0x80000040, - 0x48034017, 0x4803c856, 0x59a0021c, 0x801c3c00, - 0x0401f006, 0x492f401a, 0x492c3813, 0x412c3800, - 0x497b421c, 0x497a5813, 0x48083c00, 0x480c3a00, - 0x48103c01, 0x48143a01, 0x5c003800, 0x5c000800, - 0x5c034000, 0x5c025800, 0x1c01f000, 0x480fc857, - 0x4813c857, 0x481bc857, 0x42000000, 0x0010b611, - 0x0201f800, 0x0010a86e, 0x801800d0, 0x40002800, - 0x42001000, 0x00008014, 0x0401f786, 0x4c000000, - 0x599c0017, 0x8c000512, 0x5c000000, 0x1c01f000, - 0x4c000000, 0x599c0018, 0x8c00050e, 0x5c000000, - 0x1c01f000, 0x59a80821, 0x800409c0, 0x04000005, - 0x4a034406, 0x00000001, 0x0201f000, 0x001020b2, - 0x836c0580, 0x00000003, 0x04000005, 0x4a034406, - 0x00000007, 0x0201f000, 0x001020b2, 0x599c0017, - 0x8c00050a, 0x04000005, 0x4a034406, 0x00000008, - 0x0201f000, 0x001020b2, 0x59340405, 0x8c000508, - 0x04020004, 0x8c00050a, 0x02020000, 0x001032e2, - 0x497a5a04, 0x497a5805, 0x4a025c04, 0x00008000, - 0x0201f800, 0x00108f2d, 0x04020005, 0x4a034406, - 0x00000003, 0x0201f000, 0x001020b2, 0x4a01d809, - 0x00103906, 0x1c01f000, 0x592c0005, 0x82000580, - 0x01000000, 0x04020005, 0x4a034406, 0x00000004, - 0x0201f000, 0x001020b2, 0x59a28c06, 0x0201f800, - 0x00020267, 0x02020000, 0x001020b6, 0x0201f000, - 0x001032e2, 0x82001580, 0x0000ffff, 0x04000009, - 0x0201f800, 0x001059b9, 0x02000800, 0x00020267, - 0x0402000c, 0x0201f800, 0x00105ce7, 0x0401f009, - 0x42028800, 0x000007ef, 0x0201f800, 0x00020267, - 0x02000800, 0x00105ce7, 0x81468840, 0x040217fb, - 0x1c01f000, 0x4803c856, 0x4c0c0000, 0x4d340000, - 0x4d440000, 0x42028800, 0x000007fe, 0x0201f800, - 0x00020267, 0x04020009, 0x5934180a, 0x820c1d00, - 0x00000001, 0x820c1d80, 0x00000001, 0x42001000, - 0x0000801b, 0x0401ff1e, 0x5c028800, 0x5c026800, - 0x5c001800, 0x1c01f000, 0x599c0017, 0x8c000508, - 0x1c01f000, 0x48efc857, 0x04011000, 0x48efc840, - 0x4a03c842, 0x00000011, 0x40000000, 0x040117ff, - 0x4a01d80f, 0xbeefbeef, 0x1c01f000, 0x497b4000, - 0x497b4001, 0x497b4002, 0x497b4003, 0x497b4004, - 0x1c01f000, 0x59c400a4, 0x4c580000, 0x4c500000, - 0x4c540000, 0x82000500, 0x0000000f, 0x82000480, - 0x00000007, 0x0400100a, 0x82006c80, 0x00000007, - 0x02021800, 0x00100615, 0x0c01f807, 0x5c00a800, - 0x5c00a000, 0x5c00b000, 0x1c01f000, 0x0401f90c, - 0x0401f7fb, 0x0010396c, 0x00103972, 0x00103997, - 0x001039b9, 0x00103a78, 0x0010396b, 0x1c01f000, - 0x59c40806, 0x8c040d00, 0x04020003, 0x84040d40, - 0x48078806, 0x1c01f000, 0x59c40005, 0x8c000534, - 0x02020000, 0x001040ce, 0x4a038805, 0xffffffff, - 0x42006000, 0x00020000, 0x0201f800, 0x001040b2, - 0x59a80015, 0x82000500, 0xfffffffa, 0x84000542, - 0x48035015, 0x497b5026, 0x42000800, 0x0010bc20, - 0x45780800, 0x497b5013, 0x42006000, 0xffefffff, - 0x42006800, 0x40000000, 0x0201f800, 0x001040ad, - 0x59c40006, 0x82000500, 0xffffff0f, 0x48038806, - 0x42000800, 0x00000010, 0x42001000, 0x0010401b, - 0x0201f800, 0x00105cbc, 0x0401f001, 0x42006000, - 0xffffffff, 0x42006800, 0x00800000, 0x0201f800, - 0x001040ad, 0x4200b000, 0x000000c8, 0x59c400a4, - 0x82000500, 0x0000000f, 0x82000580, 0x0000000a, - 0x0400000f, 0x8058b040, 0x040207f9, 0x497b5014, - 0x42006000, 0xbf7fffff, 0x42006800, 0x00018000, - 0x0201f800, 0x001040ad, 0x42006000, 0xfffeffff, - 0x41786800, 0x0201f000, 0x001040ad, 0x497b5014, - 0x4a035012, 0x00000000, 0x80000580, 0x0201f000, - 0x001040b9, 0x4a038805, 0xffffffff, 0x59a80012, - 0x82000c80, 0x00000004, 0x02021800, 0x00100615, - 0x0c01f001, 0x001039c4, 0x001039f1, 0x00103a6e, - 0x4803c856, 0x59c400a3, 0x8400051e, 0x480388a3, - 0x4a035012, 0x00000001, 0x59c40008, 0x8400054e, - 0x48038808, 0x0201f800, 0x00104093, 0x42007800, - 0x0010b34a, 0x4a007806, 0x11010000, 0x4200a000, - 0x0010b202, 0x4200a800, 0x0010b351, 0x4200b000, - 0x00000002, 0x0201f800, 0x0010a93e, 0x497b8802, - 0x42000800, 0x00000003, 0x497b504a, 0x0201f800, - 0x00103f8e, 0x4a03504a, 0x00000001, 0x497b5016, - 0x0201f800, 0x001040c0, 0x42006000, 0xffffffff, - 0x42006800, 0x00080000, 0x0201f800, 0x001040ad, - 0x42006000, 0xfff7ffff, 0x41786800, 0x0201f000, - 0x001040ad, 0x59a80016, 0x497b5016, 0x80002540, - 0x0400006a, 0x59c40004, 0x82000500, 0x00000003, - 0x04020075, 0x59a80815, 0x8c040d02, 0x0400004f, - 0x82100580, 0x0000000c, 0x04020053, 0x82100400, - 0x00000018, 0x8000b104, 0x41cc1000, 0x42001800, - 0x0010b34a, 0x50080800, 0x500c0000, 0x80040580, - 0x0402001e, 0x80081000, 0x800c1800, 0x8058b040, - 0x040207f9, 0x0201f800, 0x001040c0, 0x42006000, - 0xffffffff, 0x42006800, 0x00500000, 0x0201f800, - 0x001040ad, 0x4a035012, 0x00000002, 0x4a035014, - 0x00000002, 0x0201f800, 0x0010164b, 0x42000800, - 0x000007d0, 0x42001000, 0x00103f62, 0x0201f800, - 0x00105da7, 0x59a80015, 0x84000506, 0x48035015, - 0x0201f000, 0x00104093, 0x59cc0806, 0x82040d80, - 0x11010000, 0x04020028, 0x59cc0800, 0x82040500, - 0x00ffffff, 0x0400001a, 0x82000580, 0x000000ef, - 0x04020017, 0x59cc0801, 0x82040500, 0x00ffffff, - 0x82000580, 0x000000ef, 0x04020011, 0x83cca400, - 0x00000007, 0x4200a800, 0x0010b202, 0x4200b000, - 0x00000002, 0x50500800, 0x50540000, 0x80040480, - 0x04001007, 0x04020010, 0x8050a000, 0x8054a800, - 0x8058b040, 0x040207f8, 0x0401f00b, 0x59a80015, - 0x84000502, 0x48035015, 0x41cca000, 0x4200a800, - 0x0010b34a, 0x4200b000, 0x00000009, 0x0201f800, - 0x0010a93e, 0x0201f800, 0x001040c0, 0x42006000, - 0xffffffff, 0x42006800, 0x00080000, 0x0201f800, - 0x001040ad, 0x42006000, 0xfff7ffff, 0x41786800, - 0x0201f800, 0x001040ad, 0x42006000, 0xffffffff, - 0x42006800, 0x00004000, 0x0201f800, 0x001040ad, - 0x59c40004, 0x82000500, 0x00000003, 0x04020006, - 0x497b5016, 0x42000800, 0x00000003, 0x0201f000, - 0x00103f8e, 0x1c01f000, 0x1c01f000, 0x59a80014, - 0x82006d80, 0x0000000f, 0x04000005, 0x82000580, - 0x0000001b, 0x02020800, 0x00103f53, 0x1c01f000, - 0x59a80015, 0x84000506, 0x48035015, 0x497b504a, - 0x59a80014, 0x82000c80, 0x0000001e, 0x02021800, - 0x00100615, 0x0c01f001, 0x00103ab6, 0x00103acd, - 0x00103af6, 0x00103b11, 0x00103b34, 0x00103b65, - 0x00103b87, 0x00103bba, 0x00103bdc, 0x00103c00, - 0x00103c3c, 0x00103c63, 0x00103c79, 0x00103c8b, - 0x00103ca3, 0x00103cba, 0x00103cbf, 0x00103ce7, - 0x00103d0a, 0x00103d30, 0x00103d53, 0x00103d86, - 0x00103dc8, 0x00103df2, 0x00103e0a, 0x00103e4a, - 0x00103e63, 0x00103e76, 0x00103e77, 0x4803c856, - 0x4202d800, 0x00000007, 0x0201f800, 0x00104e0d, - 0x04000007, 0x42006000, 0xffffffd7, 0x41786800, - 0x0201f800, 0x001040ad, 0x0401f00b, 0x59c40006, - 0x82000500, 0xffffff0f, 0x48038806, 0x42001000, - 0x000000f0, 0x0201f800, 0x001019aa, 0x0201f800, - 0x00104d6c, 0x1c01f000, 0x4803c856, 0x42006000, - 0xbf7fffff, 0x42006800, 0x00400000, 0x0201f800, - 0x001040ad, 0x0201f800, 0x0010164b, 0x4a035014, - 0x00000001, 0x42001000, 0x0010401b, 0x0201f800, - 0x00105cdd, 0x0201f800, 0x00104024, 0x42000800, - 0x000007d0, 0x42001000, 0x00103f62, 0x0201f000, - 0x00105da7, 0x59a80016, 0x82000580, 0x00000014, - 0x04020023, 0x4803c857, 0x42006000, 0xffbfffff, - 0x41786800, 0x0201f800, 0x001040ad, 0x59c40004, - 0x82000500, 0x00000003, 0x04020019, 0x42001000, - 0x00103f62, 0x0201f800, 0x00105cc9, 0x59cc1006, - 0x82081580, 0x11020000, 0x04020012, 0x59cc1007, - 0x8c08153e, 0x0400000b, 0x59a80015, 0x8c000504, - 0x04020008, 0x42000000, 0x0010b63d, 0x0201f800, - 0x0010a86e, 0x59a80015, 0x84000544, 0x48035015, - 0x4a035014, 0x00000010, 0x0401f1cd, 0x1c01f000, - 0x0201f000, 0x00103f53, 0x4803c856, 0x4a035014, - 0x00000003, 0x42006000, 0xbf3fffff, 0x42006800, - 0x00100000, 0x0201f800, 0x001040ad, 0x42001000, - 0x0010401b, 0x0201f800, 0x00105cdd, 0x0201f800, - 0x00104024, 0x42001000, 0x00103f62, 0x0201f800, - 0x00105cc9, 0x42007800, 0x0010b350, 0x46007800, - 0x11020000, 0x42000800, 0x00000005, 0x0201f000, - 0x00103f8e, 0x59a80016, 0x80000540, 0x0400001e, - 0x4803c857, 0x42001000, 0x00103f62, 0x0201f800, - 0x00105cc9, 0x59a80016, 0x82000580, 0x00000014, - 0x04020016, 0x59cc1006, 0x82081580, 0x11020000, - 0x04020012, 0x59cc1007, 0x8c08153e, 0x0400000b, - 0x59a80015, 0x8c000504, 0x04020008, 0x42000000, - 0x0010b63d, 0x0201f800, 0x0010a86e, 0x59a80015, - 0x84000544, 0x48035015, 0x4a035014, 0x00000004, - 0x0401f004, 0x1c01f000, 0x0201f000, 0x00103f53, - 0x4803c856, 0x4a035014, 0x00000005, 0x83cca400, - 0x00000006, 0x4200a800, 0x0010b350, 0x4200b000, - 0x00000005, 0x0201f800, 0x0010a93e, 0x42007800, - 0x0010b350, 0x46007800, 0x11030000, 0x0201f800, - 0x00103f58, 0x04020014, 0x59a80015, 0x8c000500, - 0x04020011, 0x59a80810, 0x82040580, 0x00ffffff, - 0x0400000d, 0x82040d00, 0x000000ff, 0x82040400, - 0x00101eb5, 0x50000800, 0x80040910, 0x42001000, - 0x00000004, 0x0401fb95, 0x0400000b, 0x0201f800, - 0x0010403d, 0x4200b000, 0x00000004, 0x83cca400, - 0x00000007, 0x4200a800, 0x0010b351, 0x0201f800, - 0x0010a93e, 0x42000800, 0x00000005, 0x0201f000, - 0x00103f8e, 0x59a80016, 0x80000540, 0x0400001e, - 0x4803c857, 0x42001000, 0x00103f62, 0x0201f800, - 0x00105cc9, 0x59a80016, 0x82000580, 0x00000014, - 0x04020016, 0x59cc1006, 0x82081580, 0x11030000, - 0x04020012, 0x59cc1007, 0x8c08153e, 0x0400000b, - 0x59a80015, 0x8c000504, 0x04020008, 0x42000000, - 0x0010b63d, 0x0201f800, 0x0010a86e, 0x59a80015, - 0x84000544, 0x48035015, 0x4a035014, 0x00000006, - 0x0401f003, 0x1c01f000, 0x0401f3cd, 0x4803c856, - 0x4a035014, 0x00000007, 0x83cca400, 0x00000006, - 0x4200a800, 0x0010b350, 0x4200b000, 0x00000005, - 0x0201f800, 0x0010a93e, 0x42007800, 0x0010b350, - 0x46007800, 0x11040000, 0x0401fbc2, 0x04020020, - 0x59a80015, 0x8c000500, 0x0402001d, 0x599c0017, - 0x8c000500, 0x0400001a, 0x599c1402, 0x82080480, - 0x0000007f, 0x02021800, 0x00100615, 0x4c080000, - 0x82081400, 0x00101eb5, 0x50081000, 0x82081500, - 0x000000ff, 0x480b5010, 0x42000800, 0x00000003, - 0x0201f800, 0x001069af, 0x5c000800, 0x42001000, - 0x00000004, 0x0401fb39, 0x04000005, 0x0401fd25, - 0x04000003, 0x0201f800, 0x00101668, 0x42000800, - 0x00000005, 0x0401f3d5, 0x59a80016, 0x80000540, - 0x0400001e, 0x4803c857, 0x42001000, 0x00103f62, - 0x0201f800, 0x00105cc9, 0x59a80016, 0x82000580, - 0x00000014, 0x04020016, 0x59cc1006, 0x82081580, - 0x11040000, 0x04020012, 0x59cc1007, 0x8c08153e, - 0x0400000b, 0x59a80015, 0x8c000504, 0x04020008, - 0x42000000, 0x0010b63d, 0x0201f800, 0x0010a86e, - 0x59a80015, 0x84000544, 0x48035015, 0x4a035014, - 0x00000008, 0x0401f003, 0x1c01f000, 0x0401f378, - 0x4803c856, 0x4a035014, 0x00000009, 0x83cca400, - 0x00000006, 0x4200a800, 0x0010b350, 0x4200b000, - 0x00000005, 0x0201f800, 0x0010a93e, 0x42007800, - 0x0010b350, 0x46007800, 0x11050100, 0x0401fb6d, - 0x0402000a, 0x59a80015, 0x8c000500, 0x04020007, - 0x0401fa88, 0x04020005, 0x82000540, 0x00000001, - 0x0201f800, 0x00101668, 0x42000800, 0x00000005, - 0x0401fb96, 0x4d3c0000, 0x42027800, 0x00000001, - 0x0201f800, 0x00109640, 0x5c027800, 0x1c01f000, - 0x59a80016, 0x80000540, 0x04000038, 0x4803c857, - 0x42001000, 0x00103f62, 0x0201f800, 0x00105cc9, - 0x59a80016, 0x82000580, 0x00000014, 0x04020030, - 0x59cc1006, 0x82080500, 0x11050000, 0x82000580, - 0x11050000, 0x0402002a, 0x8c081510, 0x04000014, - 0x59cc1007, 0x8c08153e, 0x0400000b, 0x59a80015, - 0x8c000504, 0x04020008, 0x42000000, 0x0010b63d, - 0x0201f800, 0x0010a86e, 0x59a80015, 0x84000544, - 0x48035015, 0x4a035013, 0x00000001, 0x4a035014, - 0x0000000a, 0x0401f817, 0x0401f014, 0x80000540, - 0x04020013, 0x59cc1007, 0x8c08153e, 0x0400000b, - 0x59a80015, 0x8c000504, 0x04020008, 0x42000000, - 0x0010b63d, 0x0201f800, 0x0010a86e, 0x59a80015, - 0x84000544, 0x48035015, 0x497b5013, 0x4a035014, - 0x0000000e, 0x0401f06a, 0x1c01f000, 0x0401f318, - 0x4803c856, 0x4a035014, 0x0000000b, 0x42001000, - 0x0010b351, 0x4008a800, 0x4200b000, 0x00000020, - 0x4600a800, 0xffffffff, 0x8054a800, 0x8058b040, - 0x040207fc, 0x42007800, 0x0010b350, 0x46007800, - 0x11060000, 0x42001000, 0x0010b351, 0x0401fb09, - 0x04000005, 0x50080000, 0x46001000, 0x00ffffff, - 0x0401f00c, 0x50080800, 0x82040d00, 0x0000ffff, - 0x59a80010, 0x82000500, 0x000000ff, 0x82000540, - 0x00000100, 0x800000e0, 0x80040d40, 0x44041000, - 0x42000800, 0x00000021, 0x0401f32c, 0x59a80016, - 0x80000540, 0x04000012, 0x4803c857, 0x59a80016, - 0x42001000, 0x00103f62, 0x0201f800, 0x00105cc9, - 0x59a80016, 0x82000580, 0x00000084, 0x04020009, - 0x59cc1006, 0x82081580, 0x11060000, 0x04020005, - 0x4a035014, 0x0000000c, 0x0401f003, 0x1c01f000, - 0x0401f2db, 0x4803c856, 0x4a035014, 0x0000000d, - 0x83cca400, 0x00000006, 0x4200a800, 0x0010b350, - 0x4200b000, 0x00000021, 0x0201f800, 0x0010a93e, - 0x42007800, 0x0010b350, 0x46007800, 0x11070000, - 0x42000800, 0x00000021, 0x0401f304, 0x59a80016, - 0x80000540, 0x04000014, 0x4803c857, 0x59a80016, - 0x42001000, 0x00103f62, 0x0201f800, 0x00105cc9, - 0x82000580, 0x00000084, 0x0402000c, 0x59cc1006, - 0x82081580, 0x11070000, 0x04020008, 0x4a035013, - 0x00000001, 0x0401fa91, 0x4a035014, 0x0000000e, - 0x0401f003, 0x1c01f000, 0x0401f2b1, 0x4803c856, - 0x82040d40, 0x00000001, 0x0201f800, 0x001040b9, - 0x4a035014, 0x0000000f, 0x497b5016, 0x42006000, - 0xffffffff, 0x42006800, 0x00300000, 0x0401fbfe, - 0x42006000, 0xffdfffff, 0x41786800, 0x0401fbfa, - 0x42000800, 0x000007d0, 0x42001000, 0x00103f62, - 0x0201f000, 0x00105ca2, 0x4803c856, 0x59a80016, - 0x80000540, 0x04020296, 0x1c01f000, 0x4803c856, - 0x4a035014, 0x00000011, 0x83cca400, 0x00000006, - 0x4200a800, 0x0010b350, 0x4200b000, 0x00000005, - 0x0201f800, 0x0010a93e, 0x4200a800, 0x0010b350, - 0x4600a800, 0x11020000, 0x0401fa8a, 0x04020015, - 0x59a80010, 0x82000d00, 0xffff0000, 0x04000011, - 0x82000500, 0x000000ff, 0x0400000e, 0x82000c00, - 0x00101eb5, 0x50040800, 0x80040910, 0x82040580, - 0x0000007e, 0x04000007, 0x82040580, 0x00000080, - 0x04000004, 0x42001000, 0x00000004, 0x0401fa07, - 0x42000800, 0x00000005, 0x0401f2a8, 0x59a80016, - 0x80000540, 0x04000020, 0x4803c857, 0x42001000, - 0x00103f62, 0x0201f800, 0x00105cc9, 0x59a80016, - 0x82000580, 0x00000014, 0x04020016, 0x59cc1006, - 0x82081580, 0x11030000, 0x04020012, 0x59cc1007, - 0x8c08153e, 0x0400000b, 0x59a80015, 0x8c000504, - 0x04020008, 0x42000000, 0x0010b63d, 0x0201f800, - 0x0010a86e, 0x59a80015, 0x84000544, 0x48035015, - 0x4a035014, 0x00000012, 0x0401f804, 0x0401f002, - 0x0401fa4b, 0x1c01f000, 0x4803c856, 0x4a035014, - 0x00000013, 0x83cca400, 0x00000006, 0x4200a800, - 0x0010b350, 0x4200b000, 0x00000005, 0x0201f800, - 0x0010a93e, 0x4200a800, 0x0010b350, 0x4600a800, - 0x11030000, 0x0401fa3f, 0x04020013, 0x59a80015, - 0x8c000500, 0x04020010, 0x59a80810, 0x82040580, - 0x00ffffff, 0x0400000c, 0x82040d00, 0x000000ff, - 0x82040400, 0x00101eb5, 0x50000800, 0x80040910, - 0x42001000, 0x00000004, 0x0401f9c0, 0x04000002, - 0x0401fb11, 0x42000800, 0x00000005, 0x0401f25f, - 0x59a80016, 0x80000540, 0x04000020, 0x4803c857, - 0x42001000, 0x00103f62, 0x0201f800, 0x00105cc9, - 0x59a80016, 0x82000580, 0x00000014, 0x04020016, - 0x59cc1006, 0x82081580, 0x11040000, 0x04020012, - 0x59cc1007, 0x8c08153e, 0x0400000b, 0x59a80015, - 0x8c000504, 0x04020008, 0x42000000, 0x0010b63d, - 0x0201f800, 0x0010a86e, 0x59a80015, 0x84000544, - 0x48035015, 0x4a035014, 0x00000014, 0x0401f804, - 0x0401f002, 0x0401fa02, 0x1c01f000, 0x4803c856, - 0x4a035014, 0x00000015, 0x83cca400, 0x00000006, - 0x4200a800, 0x0010b350, 0x4200b000, 0x00000005, - 0x0201f800, 0x0010a93e, 0x4200a800, 0x0010b350, - 0x4600a800, 0x11040000, 0x0401f9f6, 0x04020020, - 0x59a80015, 0x8c000500, 0x0402001d, 0x599c0017, - 0x8c000500, 0x0400001a, 0x599c1402, 0x82080480, - 0x0000007f, 0x02021800, 0x00100615, 0x4c080000, - 0x82081400, 0x00101eb5, 0x50081000, 0x82081500, - 0x000000ff, 0x480b5010, 0x42000800, 0x00000003, - 0x0201f800, 0x001069af, 0x5c000800, 0x42001000, - 0x00000004, 0x0401f96d, 0x04000005, 0x0201f800, - 0x001038d8, 0x02020800, 0x00101668, 0x42000800, - 0x00000005, 0x0401f209, 0x59a80016, 0x80000540, - 0x0400003f, 0x4803c857, 0x42001000, 0x00103f62, - 0x0201f800, 0x00105cc9, 0x59a80016, 0x82000580, - 0x00000014, 0x04020035, 0x59cc1006, 0x82080500, - 0x11050000, 0x82000580, 0x11050000, 0x0402002f, - 0x8c081510, 0x04000010, 0x0401fb1f, 0x59cc1007, - 0x8c08153e, 0x0400000b, 0x59a80015, 0x8c000504, - 0x04020008, 0x42000000, 0x0010b63d, 0x0201f800, - 0x0010a86e, 0x59a80015, 0x84000544, 0x48035015, - 0x0401f013, 0x59cc1007, 0x8c08153e, 0x0400000b, - 0x59a80015, 0x8c000504, 0x04020008, 0x42000000, - 0x0010b63d, 0x0201f800, 0x0010a86e, 0x59a80015, - 0x84000544, 0x48035015, 0x82000540, 0x00000001, - 0x0401fb01, 0x497b5013, 0x0401f003, 0x4a035013, - 0x00000001, 0x59cc1007, 0x8c08153c, 0x04000003, - 0x4a035026, 0x00000008, 0x4a035014, 0x00000016, - 0x0401f804, 0x0401f002, 0x0401f98d, 0x1c01f000, - 0x4803c856, 0x83cca400, 0x00000006, 0x4200a800, - 0x0010b350, 0x4200b000, 0x00000005, 0x0201f800, - 0x0010a93e, 0x4a035014, 0x00000017, 0x59a80013, - 0x8c000500, 0x04000006, 0x42001000, 0x0010b350, - 0x46001000, 0x11050100, 0x0401f003, 0x4a035014, - 0x0000001b, 0x0401f97b, 0x0402000a, 0x59a80015, - 0x8c000500, 0x04020007, 0x0401f896, 0x04020005, - 0x82000540, 0x00000001, 0x0201f800, 0x00101668, - 0x42000800, 0x00000005, 0x0401f9a4, 0x4d3c0000, - 0x42027800, 0x00000001, 0x0201f800, 0x00109640, - 0x5c027800, 0x1c01f000, 0x59a80016, 0x80000540, - 0x04000015, 0x4803c857, 0x42001000, 0x00103f62, - 0x0201f800, 0x00105cc9, 0x59a80016, 0x82000580, - 0x00000084, 0x0402000b, 0x59cc1006, 0x82081580, - 0x11060000, 0x04020007, 0x80000580, 0x0401fab6, - 0x4a035014, 0x00000018, 0x0401f804, 0x0401f002, - 0x0401f94b, 0x1c01f000, 0x4803c856, 0x4a035014, - 0x00000019, 0x83cca400, 0x00000006, 0x4200a800, - 0x0010b350, 0x4200b000, 0x00000021, 0x0201f800, - 0x0010a93e, 0x42003800, 0x0010b351, 0x0401f941, - 0x04020018, 0x401c2800, 0x50141000, 0x80080130, - 0x80000000, 0x40001800, 0x82081500, 0x00ffffff, - 0x800000f0, 0x80080540, 0x44002800, 0x59a80810, - 0x82040d00, 0x000000ff, 0x400c1000, 0x80081104, - 0x82082400, 0x0010b351, 0x50101000, 0x820c0500, - 0x00000003, 0x0c01f806, 0x80081540, 0x44082000, - 0x42000800, 0x00000021, 0x0401f15c, 0x00103e37, - 0x00103e3c, 0x00103e41, 0x00103e46, 0x800408f0, - 0x40040000, 0x82081500, 0x00ffffff, 0x1c01f000, - 0x800408e0, 0x40040000, 0x82081500, 0xff00ffff, - 0x1c01f000, 0x800408d0, 0x40040000, 0x82081500, - 0xffff00ff, 0x1c01f000, 0x40040000, 0x82081500, - 0xffffff00, 0x1c01f000, 0x59a80016, 0x80000540, - 0x04000016, 0x4803c857, 0x42001000, 0x00103f62, - 0x0201f800, 0x00105cc9, 0x59a80016, 0x82000580, - 0x00000084, 0x0402000c, 0x59cc1006, 0x82081580, - 0x11070000, 0x04020008, 0x4a035013, 0x00000001, - 0x0401f8d2, 0x4a035014, 0x0000001a, 0x0401f804, - 0x0401f002, 0x0401f8f2, 0x1c01f000, 0x82000540, - 0x00000001, 0x0401fa54, 0x4a035014, 0x0000001b, - 0x83cca400, 0x00000006, 0x4200a800, 0x0010b350, - 0x59a82016, 0x40100000, 0x8000b104, 0x40580800, - 0x5450a800, 0x8050a000, 0x8054a800, 0x8058b040, - 0x040207fc, 0x0401f119, 0x1c01f000, 0x1c01f000, - 0x4803c856, 0x42003000, 0x00000004, 0x42004000, - 0x0010b351, 0x599c2817, 0x8c142d14, 0x0402001f, - 0x42001000, 0x00000003, 0x40200000, 0x80080400, - 0x50000800, 0x82042580, 0xffffffff, 0x04020005, - 0x80081040, 0x80183040, 0x040207f8, 0x0401f05e, - 0x800811c0, 0x04020006, 0x82042580, 0x3fffffff, - 0x04000058, 0x82040d40, 0xc0000000, 0x4200b000, - 0x00000020, 0x42001800, 0x00000001, 0x40042000, - 0x80102102, 0x04021021, 0x800c18c2, 0x8058b040, - 0x040207fc, 0x0401f04b, 0x41781000, 0x40200000, - 0x80080400, 0x50000800, 0x82042580, 0xffffffff, - 0x04020005, 0x80081000, 0x80183040, 0x040207f8, - 0x0401f040, 0x800811c0, 0x04020003, 0x82040d40, - 0xc0000000, 0x4200b000, 0x00000001, 0x42001800, - 0x80000000, 0x40042000, 0x801020c2, 0x04021007, - 0x800c1902, 0x8058b000, 0x82580480, 0x00000021, - 0x040017fa, 0x0401f02f, 0x40200000, 0x80082400, - 0x50100000, 0x800c0540, 0x44002000, 0x59a80015, - 0x84000540, 0x48035015, 0x40580000, 0x42002800, - 0x00000020, 0x80142c80, 0x40080000, 0x42003800, - 0x00000003, 0x801c0480, 0x800000ca, 0x80142d40, - 0x82144c00, 0x00101eb5, 0x50242800, 0x82142d00, - 0x000000ff, 0x48175010, 0x4c040000, 0x40140800, - 0x0201f800, 0x00101655, 0x5c000800, 0x40001800, - 0x500c0000, 0x80100540, 0x44001800, 0x59a80015, - 0x84000540, 0x48035015, 0x4200a800, 0x0010b351, - 0x4020a000, 0x4200b000, 0x00000004, 0x0201f800, - 0x0010a93e, 0x82000540, 0x00000001, 0x0401f002, - 0x80000580, 0x1c01f000, 0x4807c857, 0x480bc857, - 0x4008b000, 0x83cca400, 0x00000007, 0x4200a800, - 0x0010b351, 0x40541000, 0x0201f800, 0x0010a93e, - 0x40041800, 0x41782000, 0x42000000, 0x00000003, - 0x820c1c80, 0x00000020, 0x04001004, 0x80102000, - 0x80000040, 0x0401f7fb, 0x40041800, 0x801021c0, - 0x04000005, 0x820c1c80, 0x00000020, 0x80102040, - 0x040207fd, 0x42002000, 0x00000001, 0x800c19c0, - 0x04000004, 0x801020c2, 0x800c1840, 0x040207fe, - 0x80083c00, 0x83cc2c00, 0x00000007, 0x80142c00, - 0x50140000, 0x80102d00, 0x04020012, 0x80100540, - 0x44003800, 0x82042400, 0x00101eb5, 0x50102800, - 0x82142d00, 0x000000ff, 0x48175010, 0x4c040000, - 0x40140800, 0x0201f800, 0x00101655, 0x5c000800, - 0x59a80015, 0x84000540, 0x48035015, 0x80000580, - 0x1c01f000, 0x4807c856, 0x42001000, 0x00008017, - 0x59a8184e, 0x0201f800, 0x0010a876, 0x0201f800, - 0x00103857, 0x1c01f000, 0x4807c856, 0x4200b000, - 0x00000020, 0x83cca400, 0x00000007, 0x4200a800, - 0x0010bc20, 0x0201f000, 0x0010a94f, 0x4807c856, - 0x0201f800, 0x00106c32, 0x42000800, 0x000000f7, - 0x0401f8f4, 0x497b2804, 0x497b2805, 0x497b281c, - 0x497b281d, 0x4202d800, 0x00000001, 0x42006000, - 0xbf7fffff, 0x42006800, 0x00018000, 0x0401f966, - 0x42006000, 0xfffeffff, 0x41786800, 0x0401f962, - 0x497b504e, 0x42000800, 0x0000002d, 0x42001000, - 0x00103fe4, 0x0201f000, 0x00105ca2, 0x4807c856, - 0x0401ffe3, 0x497b5014, 0x497b5016, 0x1c01f000, - 0x4807c856, 0x59a80005, 0x8c000506, 0x1c01f000, - 0x4807c856, 0x42006000, 0xffffffff, 0x42006800, - 0x00000028, 0x0401f14c, 0x4807c856, 0x0401ffc2, - 0x0201f800, 0x0010698c, 0x4df00000, 0x0201f800, - 0x00106b71, 0x5c03e000, 0x02000800, 0x00106982, - 0x59c400a4, 0x82000500, 0x0000000f, 0x82000580, - 0x00000002, 0x0402000a, 0x42006000, 0xffffffff, - 0x42006800, 0x00200000, 0x0401f937, 0x42006000, - 0xffdfffff, 0x41786800, 0x0401f933, 0x497b5014, - 0x42000800, 0x000000f7, 0x0401f8b2, 0x59c400a3, - 0x82000500, 0xbf20bfff, 0x82000540, 0x0001c000, - 0x480388a3, 0x84000520, 0x480388a3, 0x497b504e, - 0x42000800, 0x0000002d, 0x42001000, 0x00103fe4, - 0x0201f000, 0x00105ca2, 0x497b5016, 0x59b400f5, - 0x8c000500, 0x04020004, 0x82000540, 0x00000001, - 0x480368f5, 0x800400c4, 0x82000400, 0x00002000, - 0x4803910a, 0x59b400f6, 0x82000500, 0x00000018, - 0x040207fd, 0x4a0368f0, 0x0010b349, 0x42000000, - 0x0010b350, 0x4c040000, 0x50000800, 0x82040d80, - 0x11010000, 0x04000003, 0x50000800, 0x4807c857, - 0x5c000800, 0x480368f1, 0x82040400, 0x0000dc00, - 0x480368f3, 0x59c400a4, 0x82000500, 0x0000000f, - 0x82000580, 0x00000008, 0x04020017, 0x4c5c0000, - 0x4c600000, 0x59c4b805, 0x8c5cbd3a, 0x04020005, - 0x42000000, 0x0010b616, 0x0201f800, 0x0010a86e, - 0x4a038805, 0x02000000, 0x0201f800, 0x00101a59, - 0x4000c000, 0x0201f800, 0x001019d0, 0x4202d800, - 0x00000001, 0x497b5014, 0x5c00c000, 0x5c00b800, - 0x1c01f000, 0x59c8010b, 0x8c000502, 0x040007e2, - 0x59c408a4, 0x82040d00, 0x0000000f, 0x82040d80, - 0x0000000b, 0x04020005, 0x59a80814, 0x82040d40, - 0x00002000, 0x0401f004, 0x59a80812, 0x82040d40, - 0x00001000, 0x4807504e, 0x59a8084a, 0x800409c0, - 0x04020007, 0x42000800, 0x000007d0, 0x42001000, - 0x00103f62, 0x0201f800, 0x00105da7, 0x1c01f000, - 0x4807c856, 0x0401ff40, 0x0201f800, 0x0010698c, - 0x4df00000, 0x0201f800, 0x00106b71, 0x5c03e000, - 0x02000800, 0x00106982, 0x59c400a4, 0x82000500, - 0x0000000f, 0x82000580, 0x00000002, 0x0402000a, - 0x42006000, 0xffffffff, 0x42006800, 0x00200000, - 0x0401f8b5, 0x42006000, 0xffdfffff, 0x41786800, - 0x0401f8b1, 0x0201f800, 0x00104e13, 0x04000014, - 0x0201f800, 0x00104e23, 0x04020011, 0x4a035032, - 0x0000aaaa, 0x4c040000, 0x0201f800, 0x00101694, - 0x59a8002a, 0x82000500, 0xffff0000, 0x80040540, - 0x4803502a, 0x5c000800, 0x4a035033, 0x00000000, - 0x0201f800, 0x00104d76, 0x0401f008, 0x4a03504c, - 0x00000005, 0x42000000, 0x00000001, 0x0201f800, - 0x001015fa, 0x0401ff1e, 0x1c01f000, 0x0401f809, - 0x42006000, 0xbf7f7fff, 0x41786800, 0x0401f08e, - 0x42006000, 0xbf7f7fff, 0x41786800, 0x0401f08a, - 0x0201f800, 0x00104e23, 0x04020009, 0x59c40006, - 0x82000540, 0x000000f0, 0x48038806, 0x42006000, - 0xbfffffff, 0x41786800, 0x0401f87f, 0x1c01f000, - 0x800408d0, 0x59a80015, 0x8c000506, 0x04000006, - 0x59a80010, 0x82000500, 0x000000ff, 0x80040540, - 0x0401f003, 0x82040540, 0x000000f7, 0x480388a7, - 0x1c01f000, 0x4807c856, 0x42000000, 0x0010b639, - 0x0201f800, 0x0010a86e, 0x42003000, 0x00000005, - 0x4d3c0000, 0x4c180000, 0x42003000, 0x0000000d, - 0x42027800, 0x00000002, 0x0401f038, 0x4807c856, - 0x42000000, 0x0010b66a, 0x0201f800, 0x0010a86e, - 0x42003000, 0x00000000, 0x4d3c0000, 0x4c180000, - 0x42003000, 0x0000000f, 0x42027800, 0x00000002, - 0x0401f02a, 0x4807c856, 0x42000000, 0x0010b669, - 0x0201f800, 0x0010a86e, 0x42003000, 0x00000003, - 0x4d3c0000, 0x4c180000, 0x42003000, 0x0000000e, - 0x42027800, 0x00000202, 0x0401f01c, 0x4807c856, - 0x42000000, 0x0010b668, 0x0201f800, 0x0010a86e, - 0x42003000, 0x00000004, 0x4d3c0000, 0x4c180000, - 0x42003000, 0x00000010, 0x42027800, 0x00000202, - 0x0401f00e, 0x4807c856, 0x42000000, 0x0010b63c, - 0x0201f800, 0x0010a86e, 0x42003000, 0x00000001, - 0x4d3c0000, 0x4c180000, 0x42003000, 0x0000000c, - 0x42027800, 0x00000202, 0x42001800, 0x0000ffff, - 0x42002000, 0x00000007, 0x0201f800, 0x001038c7, - 0x5c003000, 0x4d400000, 0x0201f800, 0x0010a784, - 0x42028000, 0x0000002a, 0x0201f800, 0x00101d90, - 0x5c028000, 0x5c027800, 0x1c01f000, 0x4807c856, - 0x04011000, 0x4a03c840, 0x0010b349, 0x4a03c842, - 0x00000040, 0x40000000, 0x040117ff, 0x42007800, - 0x0010b349, 0x46007800, 0x00000011, 0x803c7800, - 0x4a007800, 0x220000ef, 0x4a007801, 0x000000ef, - 0x4a007802, 0x01380000, 0x4a007803, 0x00000000, - 0x4a007804, 0xffffffff, 0x4a007805, 0x00000000, - 0x1c01f000, 0x59c400a3, 0x80300500, 0x80340540, - 0x480388a3, 0x1c01f000, 0x4833c857, 0x59c400a3, - 0x80300540, 0x480388a3, 0x80300580, 0x480388a3, - 0x1c01f000, 0x4803c856, 0x04000004, 0x4a03504b, - 0x00000001, 0x0401f002, 0x497b504b, 0x1c01f000, - 0x4803c856, 0x59c80002, 0x80000540, 0x0400000a, - 0x80000040, 0x04000008, 0x4a039005, 0x00000140, - 0x42000000, 0x00000006, 0x80000040, 0x040207ff, - 0x0401f7f4, 0x1c01f000, 0x4c5c0000, 0x4c600000, - 0x59c4b805, 0x485fc856, 0x8c5cbd3a, 0x04020005, - 0x42000000, 0x0010b616, 0x0201f800, 0x0010a86e, - 0x4a038805, 0x02000000, 0x0201f800, 0x00101a59, - 0x4000c000, 0x0201f800, 0x001019d0, 0x4a038805, - 0x04000000, 0x5c00c000, 0x5c00b800, 0x1c01f000, - 0x497a6a00, 0x4a026c00, 0x00000707, 0x497a6801, - 0x497a6808, 0x497a6809, 0x497a6806, 0x497a6807, - 0x497a6c0b, 0x497a680c, 0x0201f800, 0x0010393e, - 0x04020006, 0x5934080f, 0x59340010, 0x80040540, - 0x02020800, 0x00100615, 0x4a026a04, 0x00000100, - 0x497a6a03, 0x59340402, 0x82000500, 0x000000ff, - 0x48026c02, 0x497a6c04, 0x497a6a05, 0x497a6c05, - 0x497a6811, 0x4d2c0000, 0x5934000d, 0x49466c03, - 0x80025d40, 0x04000004, 0x0201f800, 0x00100843, - 0x497a680d, 0x5c025800, 0x599c0401, 0x48026a0b, - 0x599c0208, 0x48026c12, 0x4a02680a, 0x00006000, - 0x0201f000, 0x00104acf, 0x42000000, 0x00000005, - 0x80000d80, 0x0401f02d, 0x0201f800, 0x00104858, - 0x04020017, 0x59a80026, 0x8c00050a, 0x04020010, - 0x59340212, 0x82000500, 0x0000ff00, 0x4803c857, - 0x0400000b, 0x59340a00, 0x8c040d1e, 0x02000000, - 0x000201f8, 0x42000000, 0x00000029, 0x42000800, - 0x00001000, 0x492fc857, 0x0401f018, 0x492fc857, - 0x42000000, 0x00000028, 0x0401f012, 0x59a80805, - 0x8c040d02, 0x04020003, 0x8c040d00, 0x04000004, - 0x42000000, 0x00000004, 0x0401f00a, 0x42000000, - 0x00000029, 0x59340a00, 0x8c040d1e, 0x04000005, - 0x492fc857, 0x42000800, 0x00001000, 0x0401f003, - 0x492fc857, 0x80000d80, 0x4803c857, 0x80028540, - 0x1c01f000, 0x4803c857, 0x59a80005, 0x8c000500, - 0x040207ec, 0x0201f800, 0x00104836, 0x040207e4, - 0x59340200, 0x8c00050e, 0x040007e1, 0x0201f000, - 0x000201f8, 0x0201f800, 0x00104639, 0x040007bf, - 0x0201f000, 0x000201fc, 0x592c0206, 0x492fc857, - 0x82000d80, 0x000007ff, 0x04020006, 0x4a025c0a, - 0x00000030, 0x42026800, 0x0010b320, 0x0401f021, - 0x82000c80, 0x000007f0, 0x04021046, 0x81ac0400, - 0x50000000, 0x80026d40, 0x04000038, 0x0201f800, - 0x00104732, 0x04020038, 0x592c040a, 0x8c00050a, - 0x04020014, 0x592e6009, 0x83300480, 0x0010cfc0, - 0x0400103b, 0x41580000, 0x81300480, 0x04021038, - 0x59300c06, 0x82040580, 0x00000009, 0x04020037, - 0x4a025a06, 0x00000000, 0x497a5800, 0x59300008, - 0x80000540, 0x04020018, 0x492e6008, 0x0401f010, - 0x0201f800, 0x00020892, 0x04000019, 0x592c0206, - 0x49366009, 0x492e6008, 0x4a026406, 0x00000009, - 0x497a6015, 0x49325809, 0x82000d80, 0x000007ff, - 0x04020003, 0x4a026015, 0x00008000, 0x42027000, - 0x00000043, 0x0201f800, 0x000208d8, 0x80000580, - 0x0401f020, 0x40000800, 0x58040000, 0x80000d40, - 0x040207fd, 0x492c0800, 0x0401f01a, 0x42000000, - 0x0000002c, 0x0401f016, 0x42000000, 0x00000028, - 0x0401f013, 0x59a80805, 0x82040500, 0x00000003, - 0x04000004, 0x42000000, 0x00000004, 0x0401f00c, - 0x42000000, 0x00000029, 0x0401f009, 0x42000000, - 0x00000008, 0x0401f006, 0x82040580, 0x00000007, - 0x040207fb, 0x42000000, 0x00000005, 0x80000540, - 0x1c01f000, 0x492fc857, 0x592e8c06, 0x83440d80, - 0x000007fc, 0x04000004, 0x83440480, 0x000007f0, - 0x04021014, 0x0201f800, 0x00020267, 0x04020011, - 0x0201f800, 0x00104842, 0x04020011, 0x0201f800, - 0x00020892, 0x0400001c, 0x49366009, 0x492e6008, - 0x4a026406, 0x0000000a, 0x42027000, 0x00000040, - 0x0201f800, 0x000208d8, 0x80000580, 0x0401f011, - 0x42000000, 0x00000028, 0x0401f00d, 0x0201f800, - 0x00104858, 0x040007fb, 0x59a80805, 0x82040d00, - 0x00000003, 0x04000004, 0x42000000, 0x00000004, - 0x0401f003, 0x42000000, 0x00000029, 0x80000540, - 0x1c01f000, 0x42000000, 0x0000002c, 0x0401f7fc, - 0x492fc857, 0x592e8c06, 0x4947c857, 0x83440c80, - 0x00000800, 0x42000000, 0x0000000a, 0x0402119c, - 0x592c4207, 0x4823c857, 0x82200500, 0x0000000f, - 0x0c01f001, 0x00104205, 0x0010428d, 0x001042dd, - 0x001042e8, 0x001042f3, 0x00104201, 0x00104201, - 0x00104201, 0x00104303, 0x00104361, 0x00104386, - 0x00104201, 0x00104201, 0x00104201, 0x00104201, - 0x00104201, 0x4803c857, 0x42000000, 0x0000000c, - 0x0401f183, 0x592c1008, 0x82081500, 0x00ffffff, - 0x59a80010, 0x80084d80, 0x42000000, 0x00000010, - 0x0400017b, 0x0201f800, 0x00104768, 0x04000036, - 0x4803c857, 0x82004d80, 0x0000001d, 0x0402001a, - 0x0201f800, 0x00105439, 0x59340405, 0x4c000000, - 0x0201f800, 0x00104836, 0x5c000000, 0x04000004, - 0x8c20450a, 0x04000028, 0x80000580, 0x44002800, - 0x59340008, 0x48002802, 0x59340009, 0x48002801, - 0x59340006, 0x48002804, 0x59340007, 0x48002803, - 0x4200b000, 0x00000005, 0x0201f800, 0x00109328, - 0x0401f18c, 0x4803c857, 0x82004d80, 0x0000001a, - 0x04020003, 0x40101000, 0x0401f15c, 0x4803c857, - 0x82004d80, 0x0000001b, 0x04020003, 0x40181000, - 0x0401f156, 0x4803c857, 0x82004d80, 0x0000001c, - 0x04000157, 0x82004d80, 0x00000019, 0x42000000, - 0x0000000a, 0x04000146, 0x42000000, 0x0000000a, - 0x0402015d, 0x59a8006f, 0x8c000502, 0x0400001b, - 0x0201f800, 0x00104836, 0x04000018, 0x59340212, - 0x82000500, 0x0000ff00, 0x42001000, 0x00000010, - 0x0402000c, 0x42001000, 0x00000008, 0x59a80026, - 0x8c000506, 0x04020009, 0x59340002, 0x82000500, - 0x00ff0000, 0x82000580, 0x00ff0000, 0x04000007, - 0x0201f800, 0x00104ada, 0x42000000, 0x0000001c, - 0x40181000, 0x0402012d, 0x0201f800, 0x00020892, - 0x04000137, 0x49366009, 0x492e6008, 0x4a026406, - 0x00000001, 0x8c20450a, 0x04000004, 0x592c0404, - 0x8400055c, 0x48025c04, 0x4c200000, 0x4d3c0000, - 0x42027800, 0x00001800, 0x0201f800, 0x00101de2, - 0x5c027800, 0x5c004000, 0x8c204512, 0x0400000b, - 0x599c0018, 0x8c000518, 0x04000008, 0x592c0009, - 0x82000500, 0x00000380, 0x5934080a, 0x80040d40, - 0x84040d54, 0x4806680a, 0x417a7800, 0x0401f93a, - 0x42000800, 0x00000003, 0x0401f941, 0x42027000, - 0x00000002, 0x0201f800, 0x000208d8, 0x80000580, - 0x0401f130, 0x0201f800, 0x00020267, 0x04020112, - 0x0201f800, 0x0010483c, 0x0400000c, 0x0201f800, - 0x00104836, 0x04020112, 0x4c600000, 0x4178c000, - 0x42027800, 0x00001800, 0x417a6000, 0x0201f800, - 0x00101e48, 0x5c00c000, 0x59a8006f, 0x8c000502, - 0x0400001b, 0x0201f800, 0x00104836, 0x04000018, - 0x59340212, 0x82000500, 0x0000ff00, 0x42001000, - 0x00000010, 0x0402000c, 0x42001000, 0x00000008, - 0x59a80026, 0x8c000506, 0x04020009, 0x59340002, - 0x82000500, 0x00ff0000, 0x82000580, 0x00ff0000, - 0x04000007, 0x0201f800, 0x00104ada, 0x42000000, - 0x0000001c, 0x40181000, 0x040200d4, 0x0201f800, - 0x00020892, 0x040000de, 0x5934080a, 0x8c204512, - 0x0400000c, 0x599c0018, 0x8c000518, 0x04000009, - 0x592c0009, 0x82000500, 0x00000380, 0x82041500, - 0xfffffc7f, 0x80080d40, 0x84040d54, 0x0401f002, - 0x84040d14, 0x4806680a, 0x49366009, 0x492e6008, - 0x4a026406, 0x00000001, 0x417a7800, 0x0401f8ea, - 0x42000800, 0x00000005, 0x0401f8f1, 0x42027000, - 0x00000003, 0x0201f800, 0x000208d8, 0x80000580, - 0x0401f0e0, 0x0201f800, 0x00020267, 0x040200c2, - 0x0201f800, 0x0010484b, 0x040200c5, 0x0201f800, - 0x001092e0, 0x040000b6, 0x80000580, 0x0401f0d5, - 0x0201f800, 0x00020267, 0x040200b7, 0x0201f800, - 0x0010484b, 0x040200ba, 0x0201f800, 0x00108ea3, - 0x040000ab, 0x80000580, 0x0401f0ca, 0x0201f800, - 0x00020267, 0x040200ac, 0x83444d80, 0x000007fe, - 0x42000000, 0x0000000a, 0x0402008d, 0x0201f800, - 0x00104836, 0x040200aa, 0x0201f800, 0x001092f8, - 0x0400009b, 0x80000580, 0x0401f0ba, 0x82200500, - 0x00000070, 0x04020005, 0x8c20450e, 0x42000000, - 0x0000000c, 0x0402007e, 0x8c20450a, 0x0400000d, - 0x4d3c0000, 0x42027800, 0x00001000, 0x8c20450e, - 0x04020002, 0x853e7d56, 0x82200500, 0x000000a0, - 0x0201f800, 0x00104822, 0x5c027800, 0x0401f0a1, - 0x8c204508, 0x04020024, 0x592c1008, 0x82081500, - 0x00ffffff, 0x59a80010, 0x80084d80, 0x42000000, - 0x00000010, 0x04000066, 0x0201f800, 0x00104768, - 0x0400002b, 0x4803c857, 0x82004d80, 0x0000001a, - 0x04020003, 0x40101000, 0x0401f064, 0x4803c857, - 0x82004d80, 0x0000001b, 0x04020003, 0x40181000, - 0x0401f05e, 0x4803c857, 0x82004d80, 0x0000001c, - 0x0400005f, 0x82004d80, 0x00000019, 0x42000000, - 0x0000000a, 0x0400004e, 0x42000000, 0x0000000a, - 0x0401f065, 0x0201f800, 0x00020267, 0x04020062, - 0x4d3c0000, 0x42027800, 0x00001000, 0x8c20450e, - 0x04020002, 0x853e7d56, 0x82200500, 0x00000090, - 0x0201f800, 0x0010480a, 0x5c027800, 0x42000000, - 0x0000000a, 0x0402003a, 0x0401f06a, 0x836c0580, - 0x00000003, 0x42000800, 0x00000007, 0x04020006, - 0x0201f800, 0x0010928e, 0x04000007, 0x80000580, - 0x0401f064, 0x0201f800, 0x00104871, 0x04000059, - 0x0401f05c, 0x0201f800, 0x00104871, 0x0400003c, - 0x0401f058, 0x0201f800, 0x00020267, 0x0402003e, - 0x836c0580, 0x00000003, 0x04020048, 0x8c204508, - 0x0400000a, 0x4c600000, 0x4178c000, 0x42027800, - 0x00001800, 0x417a6000, 0x0201f800, 0x00101e48, - 0x5c00c000, 0x0401f047, 0x0201f800, 0x0010483c, - 0x0400000c, 0x0201f800, 0x00104836, 0x04020030, - 0x4c600000, 0x4178c000, 0x42027800, 0x00001800, - 0x417a6000, 0x0201f800, 0x00101e48, 0x5c00c000, - 0x480bc856, 0x0201f800, 0x001090f8, 0x04000018, - 0x80000580, 0x0401f037, 0x0401f7db, 0x480bc857, - 0x42000800, 0x00000019, 0x40001000, 0x4200b000, - 0x00000002, 0x0401f00a, 0x480bc857, 0x40000800, - 0x4200b000, 0x00000002, 0x0401f005, 0x480bc857, - 0x40000800, 0x4200b000, 0x00000001, 0x480bc857, - 0x42028000, 0x00000031, 0x0401f020, 0x480bc857, - 0x42000800, 0x00000003, 0x4200b000, 0x00000001, - 0x0401f7f7, 0x480bc857, 0x42000800, 0x0000000a, - 0x4200b000, 0x00000001, 0x0401f7f1, 0x480bc857, - 0x42000800, 0x00000009, 0x40001000, 0x4200b000, - 0x00000002, 0x0401f7ea, 0x480bc857, 0x42000800, - 0x00000007, 0x4200b000, 0x00000001, 0x0401f7e4, - 0x480bc857, 0x4200b000, 0x00000001, 0x0401f7e0, - 0x80028580, 0x4178b000, 0x82000540, 0x00000001, - 0x1c01f000, 0x4937c857, 0x59326809, 0x59341200, - 0x813e79c0, 0x04000003, 0x84081540, 0x0401f002, - 0x84081500, 0x480a6a00, 0x1c01f000, 0x59326809, - 0x5c000000, 0x4c000000, 0x4803c857, 0x4937c857, - 0x82040580, 0x00000006, 0x04020004, 0x42000000, - 0x00000606, 0x0401f021, 0x82040580, 0x00000004, - 0x04020004, 0x42000000, 0x00000404, 0x0401f01b, - 0x82040580, 0x00000007, 0x42000000, 0x00000707, - 0x04000016, 0x82040580, 0x00000003, 0x42000000, - 0x00000703, 0x04000011, 0x82040580, 0x00000005, - 0x42000000, 0x00000405, 0x0400000c, 0x82040580, - 0x00000009, 0x42000000, 0x00000409, 0x04000007, - 0x82040580, 0x0000000b, 0x42000000, 0x0000070b, - 0x02020800, 0x00100615, 0x4803c857, 0x48026c00, - 0x82040d80, 0x00000006, 0x04020005, 0x59341404, - 0x800811c0, 0x02000800, 0x00100615, 0x1c01f000, - 0x5c000000, 0x4c000000, 0x4803c857, 0x4947c857, - 0x481bc857, 0x83440480, 0x00000800, 0x04021034, - 0x83441400, 0x0010aa00, 0x50080000, 0x80026d40, - 0x04020011, 0x4c180000, 0x4d2c0000, 0x0201f800, - 0x00100819, 0x412e6800, 0x5c025800, 0x5c003000, - 0x04000027, 0x45341000, 0x497a680d, 0x497a6810, - 0x497a680f, 0x497a680e, 0x4c180000, 0x0401fccd, - 0x5c003000, 0x59340a12, 0x4c040000, 0x0201f800, - 0x00104e0d, 0x5c000800, 0x04000009, 0x82180500, - 0x00ffff00, 0x04000008, 0x59a81010, 0x82081500, - 0x00ffff00, 0x80080580, 0x04000003, 0x80000580, - 0x0401f004, 0x82180500, 0x000000ff, 0x800000d0, - 0x80040d80, 0x04000003, 0x4803c857, 0x48026a12, - 0x59340002, 0x80180580, 0x04000003, 0x481bc857, - 0x481a6802, 0x80000580, 0x1c01f000, 0x4803c856, - 0x82000540, 0x00000001, 0x0401f7fc, 0x4947c857, - 0x83440480, 0x00000800, 0x04021011, 0x83441400, - 0x0010aa00, 0x50080000, 0x80026d40, 0x0400000b, - 0x0401fbf2, 0x0402000a, 0x59a80005, 0x8c000502, - 0x04000004, 0x59340200, 0x8c00050e, 0x04000004, - 0x82000540, 0x00000001, 0x1c01f000, 0x80000580, - 0x0401f7fe, 0x5c000000, 0x4c000000, 0x4803c857, - 0x4947c857, 0x4d2c0000, 0x4d300000, 0x83440480, - 0x00000800, 0x04021024, 0x83441400, 0x0010aa00, - 0x50080000, 0x80026d40, 0x0400001b, 0x45781000, - 0x5934000d, 0x80025d40, 0x02020800, 0x00100843, - 0x59366011, 0x813261c0, 0x0400000e, 0x4c640000, - 0x5930c800, 0x59325808, 0x0201f800, 0x00108df4, - 0x02020800, 0x00100843, 0x0201f800, 0x000208b4, - 0x82666540, 0x00000000, 0x040207f6, 0x5c00c800, - 0x0201f800, 0x00104acf, 0x41365800, 0x0201f800, - 0x0010083b, 0x80000580, 0x5c026000, 0x5c025800, - 0x1c01f000, 0x82000540, 0x00000001, 0x0401f7fb, - 0x4937c857, 0x4c580000, 0x59cc0001, 0x82000500, - 0x00ffffff, 0x48026802, 0x497a6c01, 0x497a6a01, - 0x59340200, 0x84000502, 0x48026a00, 0x0201f800, - 0x00104e0d, 0x04020017, 0x59340403, 0x82000580, - 0x000007fe, 0x04000005, 0x59a80026, 0x8c00050a, - 0x04020010, 0x0401f008, 0x59cc0408, 0x8c000518, - 0x0400000c, 0x59cc0009, 0x48035035, 0x59cc000a, - 0x48035036, 0x59cc0207, 0x80000540, 0x04020003, - 0x42000000, 0x00000001, 0x48038893, 0x4803501e, - 0x59cc0a09, 0x82040d00, 0x00000010, 0x59cc0408, - 0x82000500, 0x00000020, 0x04000002, 0x84040d40, - 0x5934000a, 0x82000500, 0xffffffee, 0x80040540, - 0x4802680a, 0x83cca400, 0x0000000b, 0x8334ac00, - 0x00000006, 0x4200b000, 0x00000002, 0x0201f800, - 0x0010a93e, 0x83cca400, 0x0000000d, 0x8334ac00, - 0x00000008, 0x4200b000, 0x00000002, 0x0201f800, - 0x0010a93e, 0x59cc0a18, 0x82040480, 0x00000800, - 0x0402100c, 0x82040480, 0x00000400, 0x04001004, - 0x42000800, 0x00000400, 0x0401f006, 0x82040480, - 0x00000200, 0x04001003, 0x42000800, 0x00000200, - 0x42001000, 0x0010b33f, 0x58080202, 0x80041480, - 0x04001002, 0x40000800, 0x48066a04, 0x59340403, - 0x82000580, 0x000007fe, 0x04020003, 0x59cc0a08, - 0x48066a04, 0x0201f800, 0x00104afd, 0x5c00b000, - 0x1c01f000, 0x4937c857, 0x59a80026, 0x8c000508, - 0x04000004, 0x84000556, 0x4803c857, 0x48035026, - 0x59cc0207, 0x4803c857, 0x48026a05, 0x59cc020a, - 0x4803c857, 0x48026c05, 0x59341200, 0x599c0818, - 0x5934180a, 0x4807c857, 0x480bc857, 0x480fc857, - 0x59cc2006, 0x82102500, 0xff000000, 0x82102580, - 0x02000000, 0x04000007, 0x8c00050e, 0x04000009, - 0x8c0c1d14, 0x04000003, 0x8c0c1d0e, 0x04000005, - 0x8c040d18, 0x04000003, 0x8408154a, 0x0401f002, - 0x8408150a, 0x8c000510, 0x04000009, 0x8c0c1d14, - 0x04000003, 0x8c0c1d10, 0x04000005, 0x8c040d18, - 0x04000003, 0x8408154e, 0x0401f002, 0x8408150e, - 0x8c000512, 0x04000009, 0x8c0c1d14, 0x04000003, - 0x8c0c1d12, 0x04000005, 0x8c040d18, 0x04000003, - 0x8408155c, 0x0401f002, 0x8408151c, 0x480a6a00, - 0x1c01f000, 0x4803c856, 0x4c5c0000, 0x4d2c0000, - 0x4c580000, 0x5934000d, 0x80025d40, 0x04000029, - 0x592c0003, 0x82000480, 0x00000008, 0x0400100b, - 0x412cb800, 0x592c0001, 0x80025d40, 0x040207f9, - 0x0201f800, 0x0010082a, 0x04000037, 0x492fc857, - 0x492cb801, 0x0401f020, 0x832c0c00, 0x00000004, - 0x4200b000, 0x00000008, 0x50040000, 0x82000580, - 0xffffffff, 0x04020006, 0x80041000, 0x50080000, - 0x82000580, 0xffffffff, 0x04000007, 0x82040c00, - 0x00000002, 0x8058b040, 0x040207f4, 0x0201f800, - 0x00100615, 0x45480800, 0x454c1000, 0x592c1803, - 0x800c1800, 0x480e5803, 0x480fc857, 0x0401f014, - 0x0201f800, 0x0010082a, 0x04000017, 0x492fc857, - 0x492e680d, 0x497a5802, 0x4a025803, 0x00000001, - 0x494a5804, 0x494e5805, 0x832c0c00, 0x00000006, - 0x4200b000, 0x0000000e, 0x46000800, 0xffffffff, - 0x80040800, 0x8058b040, 0x040207fc, 0x82000540, - 0x00000001, 0x5c00b000, 0x5c025800, 0x5c00b800, - 0x1c01f000, 0x80000580, 0x0401f7fb, 0x4803c856, - 0x4d3c0000, 0x4d2c0000, 0x5934000d, 0x80025d40, - 0x0400001f, 0x592c0002, 0x80000540, 0x0402001f, - 0x412e7800, 0x0401f8c8, 0x0402001c, 0x46000800, - 0xffffffff, 0x46001000, 0xffffffff, 0x4813c857, - 0x480fc857, 0x580c0003, 0x82000c80, 0x00000002, - 0x04021014, 0x480fc857, 0x400c0000, 0x812c0580, - 0x04020004, 0x580c0001, 0x4802680d, 0x0401f003, - 0x580c0001, 0x48002001, 0x400e5800, 0x0201f800, - 0x0010083a, 0x82000540, 0x00000001, 0x5c025800, - 0x5c027800, 0x1c01f000, 0x80000580, 0x0401f7fc, - 0x80000040, 0x48001803, 0x4803c857, 0x0401f7f6, - 0x0201f800, 0x00020087, 0x59300007, 0x8400054e, - 0x48026007, 0x592c1a04, 0x820c1d00, 0x000000ff, - 0x820c0580, 0x00000048, 0x04000013, 0x0201f000, - 0x000202b0, 0x8c000500, 0x02020800, 0x000200e6, - 0x4a026203, 0x00000002, 0x592c1a04, 0x820c1d00, - 0x000000ff, 0x820c0580, 0x00000018, 0x02000000, - 0x000202b0, 0x820c0580, 0x00000048, 0x02020000, - 0x000202b0, 0x42000800, 0x80000804, 0x0201f800, - 0x00106466, 0x0201f000, 0x000202b9, 0x4a025a06, - 0x00000008, 0x0201f000, 0x00020381, 0x4a025a06, - 0x00000029, 0x0201f000, 0x00020381, 0x4a025a06, - 0x0000002a, 0x0201f000, 0x00020381, 0x4a025a06, - 0x00000028, 0x0201f000, 0x00020381, 0x4943c857, - 0x4d440000, 0x4d340000, 0x4d2c0000, 0x4c580000, - 0x4200b000, 0x000007f0, 0x417a8800, 0x0201f800, - 0x00020267, 0x04020007, 0x8d3e7d06, 0x04000004, - 0x59340200, 0x8c00050e, 0x04020002, 0x0401f813, - 0x81468800, 0x8058b040, 0x040207f5, 0x83440480, - 0x00000800, 0x04021008, 0x8d3e7d02, 0x04000006, - 0x42028800, 0x000007f0, 0x4200b000, 0x00000010, - 0x0401f7eb, 0x5c00b000, 0x5c025800, 0x5c026800, - 0x5c028800, 0x1c01f000, 0x4d2c0000, 0x41783000, - 0x5936580f, 0x812e59c0, 0x04000029, 0x592c0204, - 0x82000500, 0x000000ff, 0x82000580, 0x00000012, - 0x04000020, 0x8d3e7d00, 0x04000003, 0x0401f83c, - 0x0402001c, 0x592c2000, 0x497a5800, 0x801831c0, - 0x04020009, 0x59340010, 0x812c0580, 0x04020004, - 0x497a680f, 0x497a6810, 0x0401f008, 0x4812680f, - 0x0401f006, 0x48103000, 0x59340010, 0x812c0580, - 0x04020002, 0x481a6810, 0x4a025a04, 0x00000103, - 0x49425a06, 0x497a5c09, 0x0201f800, 0x00108f7d, - 0x0201f800, 0x00020381, 0x40125800, 0x0401f7da, - 0x412c3000, 0x592e5800, 0x0401f7d7, 0x5c025800, - 0x1c01f000, 0x4803c856, 0x41781800, 0x5934000f, - 0x80025d40, 0x04000010, 0x592c0005, 0x80200580, - 0x592c0000, 0x04000003, 0x412c1800, 0x0401f7f9, - 0x497a5800, 0x800c19c0, 0x04000008, 0x48001800, - 0x80000540, 0x04020004, 0x480e6810, 0x82000540, - 0x00000001, 0x1c01f000, 0x4802680f, 0x80000540, - 0x040207fd, 0x497a6810, 0x0401f7f9, 0x592c0008, - 0x81480580, 0x04020003, 0x592c0009, 0x814c0580, - 0x1c01f000, 0x4803c856, 0x4c580000, 0x413c1800, - 0x400c2000, 0x593c0002, 0x80000540, 0x04020018, - 0x4200b000, 0x00000008, 0x820c0c00, 0x00000004, - 0x50040000, 0x81480580, 0x04020005, 0x80041000, - 0x50080000, 0x814c0580, 0x0400000d, 0x82040c00, - 0x00000002, 0x8058b040, 0x040207f6, 0x400c2000, - 0x580c0001, 0x80001d40, 0x040207ee, 0x82000540, - 0x00000001, 0x5c00b000, 0x1c01f000, 0x80000580, - 0x0401f7fd, 0x4937c857, 0x4c580000, 0x4d2c0000, - 0x5934000d, 0x80025d40, 0x04020016, 0x0201f800, - 0x0010082a, 0x04000010, 0x492e680d, 0x4a025802, - 0x00000001, 0x497a5803, 0x832c0c00, 0x00000004, - 0x4200b000, 0x00000010, 0x46000800, 0xffffffff, - 0x80040800, 0x8058b040, 0x040207fc, 0x82000540, - 0x00000001, 0x5c025800, 0x5c00b000, 0x1c01f000, - 0x4d2c0000, 0x592e5801, 0x0201f800, 0x00100843, - 0x5c025800, 0x0401f7ea, 0x4d2c0000, 0x5936580d, - 0x812e59c0, 0x04000007, 0x4937c857, 0x497a680d, - 0x0201f800, 0x00100843, 0x82000540, 0x00000001, - 0x5c025800, 0x1c01f000, 0x59340405, 0x4937c857, - 0x4803c857, 0x8c000508, 0x1c01f000, 0x4803c856, - 0x0201f800, 0x00104e0d, 0x04000011, 0x59a80815, - 0x8c040d04, 0x0402000e, 0x59a80826, 0x8c040d06, - 0x0400000b, 0x83ac0400, 0x000007fe, 0x50000000, - 0x80026d40, 0x04000006, 0x0401f9a8, 0x04020004, - 0x59340200, 0x8400055a, 0x48026a00, 0x599c0017, - 0x8c000508, 0x04000015, 0x4200b000, 0x000007f0, - 0x417a8800, 0x0201f800, 0x00020267, 0x0402000c, - 0x0401f99a, 0x0402000a, 0x59a80010, 0x59340802, - 0x80040580, 0x82000500, 0x00ffff00, 0x04020004, - 0x59340200, 0x8400055a, 0x48026a00, 0x81468800, - 0x8058b040, 0x040207f0, 0x0401f885, 0x04000003, - 0x59a80836, 0x0401f006, 0x599c0017, 0x8c000508, - 0x04000007, 0x42000800, 0x000007d0, 0x42001000, - 0x001046c4, 0x0201f800, 0x00105da7, 0x1c01f000, - 0x4803c856, 0x4d300000, 0x4d340000, 0x4d440000, - 0x4d3c0000, 0x4c580000, 0x42001000, 0x001046c4, - 0x0201f800, 0x00105cc9, 0x59a80826, 0x8c040d06, - 0x04000015, 0x0401f86a, 0x04000013, 0x83ae6c00, - 0x000007fe, 0x51366800, 0x59340200, 0x8400051a, - 0x48026a00, 0x599c0017, 0x8c000508, 0x04000007, - 0x42000800, 0x000007d0, 0x42001000, 0x001046c4, - 0x0201f800, 0x00105da7, 0x0201f800, 0x00101bf0, - 0x0401f027, 0x4200b000, 0x000007f0, 0x80028d80, - 0x0201f800, 0x00020267, 0x0402001e, 0x59340200, - 0x8c00051a, 0x0400001b, 0x59368c03, 0x417a7800, - 0x42028000, 0x00000029, 0x41783000, 0x0201f800, - 0x0010a258, 0x59340200, 0x84000558, 0x8400051a, - 0x48026a00, 0x4937c857, 0x4a026c00, 0x00000707, - 0x42028000, 0x00000029, 0x0201f800, 0x001067f6, - 0x417a7800, 0x0201f800, 0x00106543, 0x417a6000, - 0x0201f800, 0x0010a0da, 0x0201f800, 0x00106982, - 0x81468800, 0x8058b040, 0x040207de, 0x5c00b000, - 0x5c027800, 0x5c028800, 0x5c026800, 0x5c026000, - 0x1c01f000, 0x4933c857, 0x59303809, 0x581c0200, - 0x8400051a, 0x48003a00, 0x1c01f000, 0x42026800, - 0x0010b320, 0x497a680e, 0x42028800, 0x000007ff, - 0x0201f800, 0x001040e4, 0x4937c857, 0x4a026c00, - 0x00000606, 0x4a026802, 0x00ffffff, 0x4a026a04, - 0x00000200, 0x4a026c04, 0x00000002, 0x1c01f000, - 0x59300009, 0x50000000, 0x4933c857, 0x4803c857, - 0x8c00050e, 0x1c01f000, 0x59300009, 0x50000000, - 0x8c00050a, 0x1c01f000, 0x4933c856, 0x0401f90f, - 0x04000006, 0x59340400, 0x82000d00, 0x000000ff, - 0x82041580, 0x00000005, 0x1c01f000, 0x4d340000, - 0x83ac0400, 0x000007fe, 0x50000000, 0x80026d40, - 0x04000003, 0x59340200, 0x8c00051a, 0x5c026800, - 0x1c01f000, 0x4937c857, 0x493fc857, 0x59340403, - 0x81ac0400, 0x50000000, 0x81340580, 0x02020800, - 0x00100615, 0x59341200, 0x813e79c0, 0x04000003, - 0x8408155e, 0x0401f002, 0x8408151e, 0x480a6a00, - 0x1c01f000, 0x4937c857, 0x0201f800, 0x00101eb0, - 0x04000006, 0x59a80835, 0x42001000, 0x0010475f, - 0x0201f800, 0x00105da7, 0x1c01f000, 0x4937c857, - 0x42001000, 0x0010475f, 0x0201f800, 0x00105cc9, - 0x59a81026, 0x84081512, 0x480b5026, 0x1c01f000, - 0x4c380000, 0x4c340000, 0x4c240000, 0x4c600000, - 0x4008c000, 0x83440480, 0x00000800, 0x04021045, - 0x80002d80, 0x41442000, 0x83447400, 0x0010aa00, - 0x4200b000, 0x000007f0, 0x83444c80, 0x000007f0, - 0x04001003, 0x4200b000, 0x00000010, 0x50380000, - 0x80000540, 0x0402001e, 0x41440000, 0x80100580, - 0x04020043, 0x40102800, 0x82104c80, 0x000007f0, - 0x04001015, 0x82104d80, 0x000007fc, 0x04020005, - 0x82604d80, 0x00fffffc, 0x0402002a, 0x0401f00e, - 0x82104d80, 0x000007fd, 0x04020005, 0x82604d80, - 0x00fffffd, 0x04020023, 0x0401f007, 0x82104d80, - 0x000007ff, 0x0402001f, 0x82604d80, 0x00ffffff, - 0x0402001c, 0x84142d5e, 0x0401f029, 0x40006800, - 0x58343002, 0x82183500, 0x00ffffff, 0x40180000, - 0x80600580, 0x04020019, 0x40100000, 0x81440580, - 0x0402000a, 0x40366800, 0x8c204508, 0x04000053, - 0x0401ff8a, 0x04020051, 0x4947c857, 0x42000000, - 0x0000001d, 0x0401f04e, 0x4947c857, 0x480bc857, - 0x4823c857, 0x42000000, 0x0000001a, 0x0401f048, - 0x4947c857, 0x4863c857, 0x4813c857, 0x42000000, - 0x00000019, 0x0401f042, 0x40100000, 0x81440580, - 0x04020007, 0x58343002, 0x4947c857, 0x481bc857, - 0x42000000, 0x0000001b, 0x0401f039, 0x80102000, - 0x80387000, 0x83444c80, 0x000007f0, 0x04001009, - 0x82104d80, 0x00000800, 0x0402000c, 0x42002000, - 0x000007f0, 0x42007000, 0x0010b1f0, 0x0401f007, - 0x82104d80, 0x000007f0, 0x04020004, 0x41782000, - 0x42007000, 0x0010aa00, 0x8058b040, 0x040207a4, - 0x801429c0, 0x04020007, 0x0201f800, 0x00100615, - 0x4947c857, 0x42000000, 0x0000000a, 0x0401f01c, - 0x4d2c0000, 0x4c180000, 0x40603000, 0x0401fc19, - 0x4947c857, 0x4937c857, 0x5c003000, 0x5c025800, - 0x040207f4, 0x497a6a12, 0x59a80026, 0x8c00050a, - 0x0402000d, 0x82600500, 0x00ffff00, 0x04000006, - 0x59a84810, 0x82244d00, 0x00ffff00, 0x80240580, - 0x04020005, 0x82600500, 0x000000ff, 0x800000d0, - 0x48026a12, 0x48626802, 0x80000580, 0x80000540, - 0x5c00c000, 0x5c004800, 0x5c006800, 0x5c007000, - 0x1c01f000, 0x5934000f, 0x5934140b, 0x80081040, - 0x04001002, 0x480a6c0b, 0x80000540, 0x02020800, - 0x00020275, 0x1c01f000, 0x4803c857, 0x4947c857, - 0x4c300000, 0x82006500, 0x00000030, 0x04000006, - 0x4c000000, 0x0201f800, 0x001091f3, 0x5c000000, - 0x0402000b, 0x8c00050e, 0x04000006, 0x0201f800, - 0x00020267, 0x04020006, 0x4937c857, 0x0401fc36, - 0x80000580, 0x5c006000, 0x1c01f000, 0x82000540, - 0x00000001, 0x0401f7fc, 0x4803c857, 0x4c580000, - 0x4d440000, 0x40001000, 0x80000d80, 0x4200b000, - 0x000007f0, 0x4c040000, 0x40068800, 0x4c080000, - 0x40080000, 0x0401ffdd, 0x5c001000, 0x5c000800, - 0x80040800, 0x8058b040, 0x040207f7, 0x5c028800, - 0x5c00b000, 0x1c01f000, 0x4c5c0000, 0x59340400, - 0x8200bd80, 0x00000606, 0x5c00b800, 0x1c01f000, - 0x4c5c0000, 0x59340400, 0x8200bd80, 0x00000404, - 0x5c00b800, 0x1c01f000, 0x4c5c0000, 0x59340400, - 0x8200bd80, 0x00000404, 0x04000003, 0x8200bd80, - 0x00000606, 0x5c00b800, 0x1c01f000, 0x4c5c0000, - 0x4c600000, 0x59340400, 0x8200bd00, 0x0000ff00, - 0x825cc580, 0x00000400, 0x04000003, 0x825cc580, - 0x00000600, 0x5c00c000, 0x5c00b800, 0x1c01f000, - 0x4c5c0000, 0x59340400, 0x82000500, 0x000000ff, - 0x8200bd80, 0x00000003, 0x04000003, 0x8200bd80, - 0x00000005, 0x5c00b800, 0x1c01f000, 0x5c000000, - 0x4c000000, 0x4803c857, 0x4c5c0000, 0x59340400, - 0x82000500, 0x0000ff00, 0x8400b9c0, 0x805c0580, - 0x4937c857, 0x4803c857, 0x48026c00, 0x5c00b800, - 0x1c01f000, 0x4c040000, 0x4c080000, 0x592c0207, - 0x8c00050c, 0x0400000f, 0x592e8c06, 0x82000500, - 0x00000080, 0x84000548, 0x4d3c0000, 0x42027800, - 0x00001000, 0x0401ff8d, 0x5c027800, 0x82000540, - 0x00000001, 0x5c001000, 0x5c000800, 0x1c01f000, - 0x80000580, 0x0401f7fc, 0x592c040b, 0x82000500, - 0x0000e000, 0x82000580, 0x00006000, 0x04000019, - 0x836c0580, 0x00000003, 0x04000016, 0x836c0580, - 0x00000002, 0x04020106, 0x59a80026, 0x82000d00, - 0x00000038, 0x04020005, 0x59a80832, 0x800409c0, - 0x0400000c, 0x0401f0fe, 0x82000d00, 0x00000003, - 0x82040d80, 0x00000003, 0x040200f9, 0x82000d00, - 0x00000028, 0x04020003, 0x8c00050c, 0x040000f4, - 0x592c100a, 0x82080500, 0xff000000, 0x040200d2, - 0x59a80010, 0x80080580, 0x040000cc, 0x592c0c0b, - 0x82040d00, 0x0000e000, 0x82040480, 0x00008000, - 0x040210cc, 0x592e8c06, 0x83440480, 0x00000800, - 0x04001007, 0x83440580, 0x0000ffff, 0x040200b3, - 0x800409c0, 0x040200fe, 0x0401f0b0, 0x800409c0, - 0x040200fb, 0x41784000, 0x0401feaa, 0x040200e2, - 0x59342204, 0x592c000d, 0x80100480, 0x040010bc, - 0x42027000, 0x00000053, 0x592c2409, 0x82100500, - 0xffffff00, 0x040200aa, 0x4813c857, 0x592c000c, - 0x800001c0, 0x04000083, 0x82100580, 0x00000004, - 0x040000a0, 0x82100580, 0x00000051, 0x0400009d, - 0x82100580, 0x00000003, 0x04000016, 0x82100580, - 0x00000020, 0x0400004b, 0x82100580, 0x00000024, - 0x04000042, 0x82100580, 0x00000021, 0x04000042, - 0x82100580, 0x00000050, 0x04000037, 0x82100580, - 0x00000052, 0x04000031, 0x82100580, 0x00000005, - 0x0402006b, 0x42027000, 0x00000001, 0x0401f01b, - 0x42027000, 0x00000002, 0x59a8006f, 0x8c000502, - 0x04000016, 0x0401ff45, 0x04000014, 0x59340212, - 0x82000500, 0x0000ff00, 0x42001000, 0x00000010, - 0x0402000c, 0x59a80026, 0x8c000506, 0x0402006f, - 0x42001000, 0x00000008, 0x59340002, 0x82000500, - 0x00ff0000, 0x82000580, 0x00ff0000, 0x04000003, - 0x0401f9d6, 0x04020065, 0x0201f800, 0x00020892, - 0x04000081, 0x4a026406, 0x00000010, 0x49366009, - 0x42000800, 0x00000003, 0x83380580, 0x00000002, - 0x04000003, 0x42000800, 0x0000000b, 0x0201f800, - 0x001043c7, 0x0401f044, 0x42027000, 0x00000000, - 0x0401f003, 0x42027000, 0x00000004, 0x0401ff30, - 0x04020074, 0x0401f036, 0x42027000, 0x00000033, - 0x0401f006, 0x42027000, 0x00000005, 0x0401f003, - 0x42027000, 0x00000003, 0x0401ff1c, 0x04020069, - 0x59a8006f, 0x8c000502, 0x04000016, 0x0401ff0b, - 0x04000014, 0x59340212, 0x82000500, 0x0000ff00, - 0x42001000, 0x00000010, 0x0402000c, 0x59a80026, - 0x8c000506, 0x04020035, 0x42001000, 0x00000008, - 0x59340002, 0x82000500, 0x00ff0000, 0x82000580, - 0x00ff0000, 0x04000003, 0x0401f99c, 0x0402002b, - 0x0201f800, 0x00020892, 0x04000047, 0x4a026406, - 0x00000010, 0x49366009, 0x42000800, 0x00000005, - 0x83380580, 0x00000003, 0x04000003, 0x42000800, - 0x00000009, 0x0201f800, 0x001043c7, 0x0401f00a, - 0x82102580, 0x00000011, 0x04020030, 0x0201f800, - 0x00020892, 0x04000034, 0x4a026406, 0x00000010, - 0x49366009, 0x492e6008, 0x49325808, 0x813669c0, - 0x04000007, 0x592c0c0b, 0x8c040d18, 0x04000004, - 0x59340200, 0x84000514, 0x48026a00, 0x0201f800, - 0x000208d8, 0x80000580, 0x1c01f000, 0x82000540, - 0x00000001, 0x0401f7fd, 0x42001000, 0x0000000a, - 0x0401f018, 0x42001000, 0x00000010, 0x0401f015, - 0x42001000, 0x00000016, 0x0401f012, 0x42001000, - 0x00000017, 0x0401f00f, 0x42001000, 0x00000018, - 0x0401f00c, 0x42001000, 0x0000001b, 0x0401f009, - 0x42001000, 0x0000001e, 0x0401f006, 0x42001000, - 0x00000024, 0x0401f003, 0x42001000, 0x00000020, - 0x42000800, 0x00000019, 0x42028000, 0x00000031, - 0x0401f7df, 0x42000800, 0x00000003, 0x0401f003, - 0x42000800, 0x0000000a, 0x41781000, 0x0401f7f7, - 0x42000800, 0x00000009, 0x59341400, 0x0401f7f3, - 0x42028000, 0x00000008, 0x0401f005, 0x42000800, - 0x00000007, 0x416c1000, 0x0401f7ec, 0x41780800, - 0x41781000, 0x0401f7ca, 0x42028000, 0x00000000, - 0x0401f7fb, 0x82004d80, 0x0000001d, 0x02000800, - 0x00100615, 0x82004d80, 0x0000001a, 0x04020004, - 0x40101000, 0x40000800, 0x0401f7dc, 0x82004d80, - 0x0000001b, 0x04020003, 0x40181000, 0x0401f7fa, - 0x82004d80, 0x0000001c, 0x040007f7, 0x82004d80, - 0x00000019, 0x040007b5, 0x0401f7d6, 0x592e6008, - 0x0201f800, 0x001091e3, 0x040007b3, 0x59300c06, - 0x82040580, 0x00000011, 0x040207d6, 0x83440580, - 0x0000ffff, 0x04020005, 0x59326809, 0x813669c0, - 0x0400000e, 0x0401f7cf, 0x592c100a, 0x82081500, - 0x00ffffff, 0x41784000, 0x0401fd9e, 0x040207d6, - 0x59300009, 0x800001c0, 0x04000003, 0x81340580, - 0x040207c4, 0x49366009, 0x592c0c0b, 0x82041500, - 0x0000e000, 0x82080580, 0x00006000, 0x04000011, - 0x42000800, 0x00000100, 0x813669c0, 0x04000002, - 0x59340a04, 0x592c000d, 0x80040480, 0x040017a0, - 0x59300a03, 0x82040580, 0x00000007, 0x040207b1, - 0x492e6008, 0x42027000, 0x00000054, 0x0401f774, - 0x0201f800, 0x0010a6e6, 0x040007b4, 0x0401f7a9, - 0x492fc857, 0x592e6008, 0x4933c857, 0x0201f800, - 0x001091e3, 0x04000047, 0x59301406, 0x82080580, - 0x00000005, 0x04020061, 0x592c0207, 0x8c000500, - 0x04020085, 0x59a80021, 0x800001c0, 0x0402006a, - 0x59301203, 0x82080580, 0x00000007, 0x04020057, - 0x592e8c06, 0x83440480, 0x00000800, 0x04021032, - 0x41784000, 0x592c1009, 0x82081500, 0x00ffffff, - 0x0401fd60, 0x0402005f, 0x59300009, 0x800001c0, - 0x04000003, 0x81340580, 0x04020048, 0x4d300000, - 0x592e6013, 0x4933c857, 0x83300580, 0xffffffff, - 0x0400000d, 0x0201f800, 0x001091e3, 0x5c026000, - 0x04000029, 0x591c1406, 0x82080580, 0x00000006, - 0x04000046, 0x82080580, 0x00000011, 0x04000043, - 0x0401f002, 0x5c026000, 0x59a80010, 0x592c100a, - 0x82081500, 0x00ffffff, 0x80081580, 0x04020017, - 0x592c1009, 0x82081500, 0x00ffffff, 0x80081580, - 0x0400000f, 0x49366009, 0x492e6008, 0x42027000, - 0x00000092, 0x0201f800, 0x000208d8, 0x80000580, - 0x1c01f000, 0x42001000, 0x0000000a, 0x0401f00c, - 0x42001000, 0x00000010, 0x0401f009, 0x42001000, - 0x00000014, 0x0401f006, 0x42001000, 0x00000018, - 0x0401f003, 0x42001000, 0x0000003c, 0x492fc857, - 0x480bc857, 0x42000800, 0x00000019, 0x42028000, - 0x00000031, 0x82000540, 0x00000001, 0x0401f7e9, - 0x492fc857, 0x4803c857, 0x480bc857, 0x40000800, - 0x0401f7f7, 0x492fc857, 0x42000800, 0x0000000a, - 0x41781000, 0x0401f7f2, 0x4933c857, 0x59300406, - 0x4803c857, 0x59300203, 0x4803c857, 0x59300009, - 0x4803c857, 0x42028000, 0x00000008, 0x41780800, - 0x41781000, 0x0401f7e8, 0x42000800, 0x0000001e, - 0x0401f7f0, 0x42000800, 0x00000001, 0x0401f7ed, - 0x82004d80, 0x0000001d, 0x02000800, 0x00100615, - 0x82004d80, 0x0000001a, 0x04020003, 0x40101000, - 0x0401f7dc, 0x82004d80, 0x0000001b, 0x04020003, - 0x40181000, 0x0401f7d7, 0x82004d80, 0x0000001c, - 0x040007d4, 0x82004d80, 0x00000019, 0x040007d1, - 0x0401f7d5, 0x0201f800, 0x0010a6e6, 0x040207d7, - 0x42028000, 0x00000000, 0x0401f7dd, 0x5c000000, - 0x4c000000, 0x4803c857, 0x59302009, 0x801021c0, - 0x04000035, 0x58101400, 0x4813c857, 0x480bc857, - 0x82081d00, 0x000000ff, 0x59300c03, 0x82040580, - 0x00000008, 0x04000022, 0x82040580, 0x0000000a, - 0x04000017, 0x82040580, 0x0000000c, 0x04000010, - 0x82040580, 0x00000002, 0x04000019, 0x82040580, - 0x00000001, 0x04000012, 0x82040580, 0x00000003, - 0x0400000b, 0x82040580, 0x00000005, 0x04000004, - 0x82040580, 0x00000033, 0x04020017, 0x820c0580, - 0x00000009, 0x0400000d, 0x0401f013, 0x820c0580, - 0x00000005, 0x04000009, 0x0401f00f, 0x820c0580, - 0x0000000b, 0x04000005, 0x0401f00b, 0x820c0580, - 0x00000003, 0x04020008, 0x82081d00, 0xffffff00, - 0x840c01c0, 0x800c0540, 0x4807c857, 0x4803c857, - 0x48002400, 0x1c01f000, 0x599c0017, 0x8c00050a, - 0x04000003, 0x80000580, 0x1c01f000, 0x59a80026, - 0x82000500, 0x00000028, 0x04000008, 0x42028800, - 0x000007fd, 0x0201f800, 0x00020267, 0x04020003, - 0x5934000a, 0x8c000504, 0x1c01f000, 0x4d300000, - 0x5934000e, 0x80026540, 0x04000006, 0x0201f800, - 0x0010600e, 0x02000800, 0x001061e5, 0x497a680e, - 0x5c026000, 0x1c01f000, 0x4d440000, 0x4d340000, - 0x80000580, 0x40001800, 0x40028800, 0x82080580, - 0x00000008, 0x04020003, 0x42001800, 0x00000001, - 0x0201f800, 0x00020267, 0x0402000a, 0x0401fd4f, - 0x04020008, 0x800c19c0, 0x04000004, 0x59340405, - 0x8c000508, 0x04000003, 0x80081040, 0x04000009, - 0x81468800, 0x83440480, 0x00000800, 0x040017f1, - 0x80000580, 0x5c026800, 0x5c028800, 0x1c01f000, - 0x82000540, 0x00000001, 0x5c026800, 0x5c028800, - 0x1c01f000, 0x42000800, 0x00000001, 0x0401fb0e, - 0x04020034, 0x59a80026, 0x8c000508, 0x04020031, - 0x5934100a, 0x82081500, 0x0000e000, 0x42007000, - 0x0010b33f, 0x58380401, 0x8c000504, 0x0402001c, - 0x42000800, 0x00000001, 0x82080580, 0x00006000, - 0x04000024, 0x59341a04, 0x820c0480, 0x00000800, - 0x04001004, 0x42000800, 0x00000a00, 0x0401f009, - 0x820c0480, 0x00000400, 0x04001004, 0x42000800, - 0x00000500, 0x0401f003, 0x42000800, 0x00000200, - 0x82080580, 0x00002000, 0x04000002, 0x800408c2, - 0x82040d40, 0x00000001, 0x0401f00e, 0x42000800, - 0x00000008, 0x82080580, 0x00002000, 0x04020004, - 0x42000800, 0x00000004, 0x0401f006, 0x82080580, - 0x00000000, 0x04020003, 0x42000800, 0x00000002, - 0x48066c04, 0x1c01f000, 0x4a033020, 0x00000000, - 0x4a03b104, 0x80000000, 0x497b3026, 0x497b3027, - 0x497b3028, 0x497b3029, 0x497b302b, 0x497b3021, - 0x4a03b104, 0x60000001, 0x1c01f000, 0x599c0018, - 0x4803c856, 0x497b3024, 0x497b3025, 0x82000500, - 0x0000000f, 0x48033022, 0x04000008, 0x599c0216, - 0x82000500, 0x0000ffff, 0x04020003, 0x42000000, - 0x00000002, 0x48033023, 0x1c01f000, 0x0401fff0, - 0x4a03c826, 0x00000004, 0x599c0209, 0x80000540, - 0x0400001f, 0x599c0207, 0x80000540, 0x04000007, - 0x800000cc, 0x599c080d, 0x80040400, 0x4803b100, - 0x497bb102, 0x59d80101, 0x599c000d, 0x4803b100, - 0x599c000e, 0x4803b101, 0x599c0207, 0x80000540, - 0x04020002, 0x497bb102, 0x599c0a09, 0x82040540, - 0x00400000, 0x59980822, 0x4803b103, 0x4a03b109, - 0x00000004, 0x4a03b104, 0x10000001, 0x800409c0, - 0x04020004, 0x4a033020, 0x00000001, 0x1c01f000, - 0x4a033020, 0x00000002, 0x0401f7fd, 0x592c0204, - 0x492fc857, 0x80000540, 0x04000008, 0x42034000, - 0x0010b2a0, 0x59a1d81e, 0x80edd9c0, 0x02000800, - 0x00100615, 0x0401f003, 0x5931d821, 0x58ef400b, - 0x58ec0009, 0x800001c0, 0x08020000, 0x0201f800, - 0x00100615, 0x5998002b, 0x84000540, 0x4803302b, - 0x0201f000, 0x00020403, 0x42000000, 0x0010b654, - 0x0201f800, 0x0010a86e, 0x492fc857, 0x59980026, - 0x59980828, 0x80000000, 0x48033026, 0x800409c0, - 0x492f3028, 0x04000003, 0x492c0800, 0x0401f002, - 0x492f3029, 0x592c0001, 0x80000d40, 0x02020000, - 0x000202fb, 0x1c01f000, 0x59980026, 0x59980828, - 0x80000000, 0x48033026, 0x492fc857, 0x800409c0, - 0x492f3028, 0x04000003, 0x492c0800, 0x0401f002, - 0x492f3029, 0x592c0001, 0x80000d40, 0x02020800, - 0x000202fb, 0x0402d00e, 0x59980029, 0x80025d40, - 0x0400000f, 0x59980026, 0x80000040, 0x48033026, - 0x04020002, 0x48033028, 0x592c0000, 0x48033029, - 0x492fc857, 0x492fb107, 0x0400d7f4, 0x42000000, - 0x0010b654, 0x0201f800, 0x0010a86e, 0x0402e01d, - 0x59da5908, 0x496a5800, 0x412ed000, 0x815eb800, - 0x0400e7fc, 0x59c80000, 0x82000540, 0x00001200, - 0x48039000, 0x04006019, 0x59d8010a, 0x59d8090a, - 0x80040d80, 0x040207fd, 0x900001c0, 0x82000540, - 0x00000013, 0x4803c011, 0x5998002b, 0x84000500, - 0x4803302b, 0x59e00017, 0x8c000508, 0x04000003, - 0x4a03c017, 0x00000003, 0x4203e000, 0x30000001, - 0x59d80105, 0x82000500, 0x00018780, 0x02020000, - 0x00020482, 0x1c01f000, 0x5998002b, 0x84000540, - 0x4803302b, 0x0401f7f7, 0x5c000000, 0x4c000000, - 0x4803c857, 0x492fc857, 0x4943c857, 0x4807c857, - 0x4a025a04, 0x00000103, 0x49425a06, 0x48065a08, - 0x4a025c06, 0x0000ffff, 0x813261c0, 0x04000003, - 0x59300402, 0x48025c06, 0x832c0400, 0x00000009, - 0x04011000, 0x4803c840, 0x4a03c842, 0x0000000b, - 0x04011000, 0x1c01f000, 0x42000000, 0x0010b654, - 0x0201f800, 0x0010a86e, 0x0201f000, 0x00020464, - 0x59a80017, 0x82000c80, 0x0000000a, 0x02021800, - 0x00100615, 0x0c01f809, 0x4a038805, 0x000000f0, - 0x59c400a3, 0x82000500, 0x02870000, 0x02020800, - 0x00100615, 0x1c01f000, 0x00104c99, 0x00104c25, - 0x00104c40, 0x00104c69, 0x00104c8c, 0x00104cc6, - 0x00104cd8, 0x00104c40, 0x00104caa, 0x00104c24, - 0x1c01f000, 0x4a038808, 0x00000004, 0x0401f8f9, - 0x0201f800, 0x0010507b, 0x59c40805, 0x8c040d0e, - 0x04020013, 0x8c040d0a, 0x0402000b, 0x8c040d0c, - 0x04020006, 0x8c040d08, 0x0400000d, 0x4a035017, - 0x00000003, 0x0401f00a, 0x4a035017, 0x00000000, - 0x0401f007, 0x42000000, 0x0010b642, 0x0201f800, - 0x0010a86e, 0x4a035017, 0x00000002, 0x1c01f000, - 0x4a038808, 0x00000002, 0x0401f8de, 0x59c40805, - 0x8c040d08, 0x04020021, 0x8c040d0c, 0x0402001c, - 0x8c040d0e, 0x04020017, 0x82040500, 0x000000f0, - 0x0402001c, 0x0201f800, 0x0010507b, 0x4a038808, - 0x00000080, 0x59c40002, 0x8400050c, 0x48038802, - 0x0401f9d7, 0x4d3c0000, 0x42027800, 0x00000001, - 0x0201f800, 0x00109640, 0x5c027800, 0x4a038808, - 0x00000080, 0x4a035017, 0x00000009, 0x0401f009, - 0x4a035017, 0x00000001, 0x0401f006, 0x4a035017, - 0x00000000, 0x0401f003, 0x4a035017, 0x00000003, - 0x1c01f000, 0x0401f8b7, 0x4a038808, 0x00000080, - 0x59c40805, 0x8c040d0a, 0x0402001b, 0x8c040d0c, - 0x04020016, 0x8c040d0e, 0x04020011, 0x82040500, - 0x000000f0, 0x04020016, 0x59c40002, 0x8400050c, - 0x48038802, 0x0401f9b2, 0x4d3c0000, 0x42027800, - 0x00000001, 0x0201f800, 0x00109640, 0x5c027800, - 0x4a035017, 0x00000009, 0x0401f009, 0x4a035017, - 0x00000001, 0x0401f006, 0x4a035017, 0x00000000, - 0x0401f003, 0x4a035017, 0x00000002, 0x1c01f000, - 0x4a038808, 0x00000008, 0x59c40805, 0x8c040d0c, - 0x04020006, 0x8c040d0e, 0x04000006, 0x4a035017, - 0x00000001, 0x0401f003, 0x4a035017, 0x00000000, - 0x1c01f000, 0x0401f8d3, 0x59c40805, 0x8c040d0c, - 0x0402000d, 0x4c040000, 0x0401f882, 0x5c000800, - 0x8c040d0a, 0x04020006, 0x8c040d0e, 0x04000006, - 0x4a035017, 0x00000001, 0x0401f003, 0x4a035017, - 0x00000002, 0x1c01f000, 0x4a038808, 0x00000008, - 0x42001000, 0x00104d2c, 0x0201f800, 0x00105dbd, - 0x59c40805, 0x8c040d0a, 0x0402000d, 0x8c040d08, - 0x0402000b, 0x8c040d0c, 0x04020006, 0x8c040d0e, - 0x0400000d, 0x4a035017, 0x00000001, 0x0401f00a, - 0x4a035017, 0x00000000, 0x0401f007, 0x42000000, - 0x0010b642, 0x0201f800, 0x0010a86e, 0x4a035017, - 0x00000004, 0x1c01f000, 0x0401f8a6, 0x0401f859, - 0x59c40805, 0x8c040d0a, 0x0402000b, 0x8c040d0c, - 0x04020006, 0x8c040d0e, 0x04000009, 0x4a035017, - 0x00000001, 0x0401f006, 0x4a035017, 0x00000000, - 0x0401f003, 0x4a035017, 0x00000002, 0x1c01f000, - 0x4a038808, 0x00000004, 0x0401f846, 0x59c40805, - 0x8c040d0a, 0x04020010, 0x8c040d08, 0x0402000b, - 0x8c040d0c, 0x04020006, 0x8c040d0e, 0x0400000c, - 0x4a035017, 0x00000001, 0x0401f009, 0x4a035017, - 0x00000000, 0x0401f006, 0x4a035017, 0x00000003, - 0x0401f003, 0x4a035017, 0x00000002, 0x1c01f000, - 0x0401f91d, 0x02020800, 0x00100615, 0x59a80805, - 0x8c040d0c, 0x04000015, 0x84040d0c, 0x48075005, - 0x4a038805, 0x00000010, 0x0201f800, 0x001019a4, - 0x59c40005, 0x8c000508, 0x04000008, 0x4a038808, - 0x00000008, 0x4a035033, 0x00000001, 0x4202d800, - 0x00000001, 0x0401f01a, 0x59c40006, 0x84000548, - 0x48038806, 0x0401f016, 0x59a80017, 0x82000580, - 0x00000001, 0x0400000c, 0x59a80017, 0x82000580, - 0x00000005, 0x0402000c, 0x42000000, 0x0010b642, - 0x0201f800, 0x0010a86e, 0x4a035017, 0x00000008, - 0x0401f007, 0x42000000, 0x0010b642, 0x0201f800, - 0x0010a86e, 0x4a035017, 0x00000004, 0x1c01f000, - 0x4803c856, 0x4c040000, 0x4c080000, 0x42000800, - 0x00000064, 0x42001000, 0x00104d2c, 0x0201f800, - 0x00105db2, 0x5c001000, 0x5c000800, 0x1c01f000, - 0x4803c856, 0x4c040000, 0x0201f800, 0x0010698c, - 0x4df00000, 0x0201f800, 0x00106b71, 0x5c03e000, - 0x02000800, 0x00106982, 0x0401ffba, 0x5c000800, - 0x1c01f000, 0x4803c856, 0x4c040000, 0x4c080000, - 0x0201f800, 0x0010698c, 0x4df00000, 0x0201f800, - 0x00106b71, 0x5c03e000, 0x02000800, 0x00106982, - 0x59c40006, 0x84000500, 0x48038806, 0x0201f800, - 0x00106c32, 0x497b8880, 0x0201f800, 0x0010a7e7, - 0x0201f800, 0x0010a7f5, 0x0201f800, 0x00101886, - 0x4a03504c, 0x00000004, 0x4202d800, 0x00000004, - 0x4a038805, 0x00000001, 0x42001000, 0x00104d2c, - 0x0201f800, 0x00105dbd, 0x0201f800, 0x0010071a, - 0x0401f8bf, 0x04000006, 0x42006000, 0xfeffffff, - 0x41786800, 0x0201f800, 0x001040ad, 0x0201f800, - 0x0010048c, 0x42000000, 0x00000001, 0x0201f800, - 0x001015fa, 0x5c001000, 0x5c000800, 0x1c01f000, - 0x59c40008, 0x8c000508, 0x04020007, 0x4a038808, - 0x00000010, 0x4201d000, 0x00001388, 0x0201f800, - 0x00105dd2, 0x1c01f000, 0x4c040000, 0x59a80833, - 0x82040580, 0x00000000, 0x0400000b, 0x82040580, - 0x00000001, 0x0400000b, 0x82040580, 0x00000002, - 0x0400000b, 0x82040580, 0x00000003, 0x0400000b, - 0x0401f055, 0x4a035017, 0x00000000, 0x0401f009, - 0x4a035017, 0x00000004, 0x0401f006, 0x4a035017, - 0x00000001, 0x0401f003, 0x4a035017, 0x00000007, - 0x497b8880, 0x4a038893, 0x00000001, 0x41780000, - 0x0201f800, 0x00101670, 0x0201f800, 0x00106c32, - 0x836c0d80, 0x00000004, 0x04000008, 0x59c40006, - 0x82000500, 0xffffff0f, 0x82000540, 0x04000001, - 0x48038806, 0x0401f007, 0x59c40006, 0x82000500, - 0xffffff0f, 0x82000540, 0x04000000, 0x48038806, - 0x0401f873, 0x04020005, 0x59c40806, 0x82040d00, - 0xfbffff0f, 0x48078806, 0x59c40005, 0x8c000534, - 0x04020033, 0x42006000, 0xfc18ffff, 0x42006800, - 0x01000000, 0x0201f800, 0x001040ad, 0x0201f800, - 0x001019a4, 0x59c408a4, 0x82040d00, 0x0000000f, - 0x82040d80, 0x0000000c, 0x040208a9, 0x0401f85c, - 0x04000006, 0x42006000, 0xfeffffff, 0x41786800, - 0x0201f800, 0x001040ad, 0x836c0d80, 0x00000004, - 0x0400000f, 0x0401f85a, 0x04020008, 0x59940005, - 0x82000580, 0x00103f37, 0x04020004, 0x59940004, - 0x800001c0, 0x04020006, 0x59a8084d, 0x42001000, - 0x00104d39, 0x0201f800, 0x00105da7, 0x4a035033, - 0x00000004, 0x0401fe33, 0x0401f841, 0x04020008, - 0x59c408a4, 0x82040d00, 0x0000000f, 0x82040580, - 0x0000000c, 0x02020800, 0x00100615, 0x5c000800, - 0x1c01f000, 0x4803c856, 0x4c000000, 0x0201f800, - 0x00105de2, 0x4a035010, 0x00ffffff, 0x497b5032, - 0x59a8002a, 0x82000500, 0xffff0000, 0x4803502a, - 0x497b8880, 0x497b8893, 0x41780000, 0x0201f800, - 0x00101670, 0x59c40001, 0x82000500, 0xfffffcff, - 0x48038801, 0x42006000, 0xfc18ffff, 0x41786800, - 0x0201f800, 0x001040ad, 0x4a038808, 0x00000000, - 0x5c000000, 0x800001c0, 0x02020800, 0x00103f37, - 0x4a038805, 0x040000f0, 0x59c40006, 0x82000500, - 0xffffffcf, 0x82000540, 0x440000c1, 0x48038806, - 0x1c01f000, 0x4c5c0000, 0x59a8b832, 0x825cbd80, - 0x0000aaaa, 0x5c00b800, 0x1c01f000, 0x4c5c0000, - 0x599cb818, 0x825cbd00, 0x00000030, 0x825cbd80, - 0x00000000, 0x5c00b800, 0x1c01f000, 0x4c5c0000, - 0x599cb818, 0x825cbd00, 0x00000030, 0x825cbd80, - 0x00000010, 0x5c00b800, 0x1c01f000, 0x4c5c0000, - 0x599cb818, 0x825cbd00, 0x00000030, 0x825cbd80, - 0x00000020, 0x5c00b800, 0x1c01f000, 0x59a80005, - 0x4803c857, 0x82000d00, 0x00000013, 0x04000024, - 0x599c1017, 0x4d3c0000, 0x82000500, 0x00000011, - 0x04000006, 0x417a7800, 0x0201f800, 0x0010393e, - 0x0402000a, 0x0401f012, 0x42027800, 0x00000008, - 0x0201f800, 0x0010393e, 0x0400000d, 0x42003000, - 0x00000003, 0x0401f003, 0x42003000, 0x00000004, - 0x42028000, 0x0000000e, 0x0201f800, 0x0010a25b, - 0x599c1017, 0x8c08150a, 0x04020007, 0x42028000, - 0x00000004, 0x0201f800, 0x00101d90, 0x80000580, - 0x0401f80d, 0x5c027800, 0x0401f00a, 0x0201f800, - 0x0010393e, 0x04000007, 0x42028000, 0x0000000f, - 0x42003000, 0x00000001, 0x0201f800, 0x0010a25b, - 0x1c01f000, 0x59a80005, 0x04000004, 0x82000540, - 0x00000010, 0x0401f003, 0x82000500, 0xffffffef, - 0x48035005, 0x4803c857, 0x1c01f000, 0x4803c856, - 0x4c580000, 0x42000000, 0x0010b6ca, 0x0201f800, - 0x0010a86e, 0x42000800, 0x0010bef0, 0x59c40003, - 0x44000800, 0x59c40004, 0x48000801, 0x59c4000b, - 0x48000802, 0x59c4008e, 0x48000803, 0x59c4008f, - 0x48000804, 0x59c40090, 0x48000805, 0x59c40091, - 0x48000806, 0x59c40092, 0x48000807, 0x59c40093, - 0x48000808, 0x59c40099, 0x48000809, 0x59c4009e, - 0x4800080a, 0x59c400aa, 0x4800080b, 0x59c400af, - 0x4800080c, 0x59c400b2, 0x4800080d, 0x59c400b1, - 0x4800080e, 0x82040c00, 0x0000000f, 0x41c41800, - 0x4200b000, 0x00000030, 0x580c0050, 0x44000800, - 0x80040800, 0x800c1800, 0x8058b040, 0x040207fb, - 0x41c41800, 0x4200b000, 0x00000020, 0x580c0010, - 0x44000800, 0x80040800, 0x800c1800, 0x8058b040, - 0x040207fb, 0x497b8830, 0x4200b000, 0x00000040, - 0x59c40031, 0x44000800, 0x80040800, 0x8058b040, - 0x040207fc, 0x497b88ac, 0x4200b000, 0x00000010, - 0x59c400ad, 0x44000800, 0x80040800, 0x8058b040, - 0x040207fc, 0x59c41001, 0x4c080000, 0x8408150c, - 0x480b8801, 0x4a0370e4, 0x00000300, 0x4a0370e5, - 0xb0000000, 0x42000800, 0x00000800, 0x80040840, - 0x02000800, 0x00100615, 0x59b800e5, 0x8c000538, - 0x040207fb, 0x4a0370e4, 0x00000200, 0x42006000, - 0xffffffff, 0x42006800, 0x80000000, 0x0201f800, - 0x001040ad, 0x4a038807, 0x00000001, 0x497b8807, - 0x4a038808, 0x00000010, 0x42006000, 0xfcf8ffff, - 0x42006800, 0x01000000, 0x0201f800, 0x001040ad, - 0x5c001000, 0x480b8801, 0x42000800, 0x0010bef0, - 0x50040000, 0x48038803, 0x58040001, 0x48038804, - 0x58040002, 0x4803880b, 0x58040003, 0x4803888e, - 0x58040004, 0x4803888f, 0x58040005, 0x48038890, - 0x58040006, 0x48038891, 0x58040007, 0x48038892, - 0x58040008, 0x48038893, 0x58040009, 0x48038899, - 0x5804000a, 0x4803889e, 0x5804000b, 0x480388aa, - 0x5804000c, 0x480388af, 0x5804000d, 0x480388b2, - 0x5804000e, 0x480388b1, 0x82040c00, 0x0000000f, - 0x41c41800, 0x4200b000, 0x00000030, 0x50040000, - 0x48001850, 0x80040800, 0x800c1800, 0x8058b040, - 0x040207fb, 0x41c41800, 0x4200b000, 0x00000020, - 0x50040000, 0x48001810, 0x80040800, 0x800c1800, - 0x8058b040, 0x040207fb, 0x497b8830, 0x4200b000, - 0x00000040, 0x50040000, 0x48038831, 0x80040800, - 0x8058b040, 0x040207fc, 0x497b88ac, 0x4200b000, - 0x00000010, 0x50040000, 0x480388ad, 0x80040800, - 0x8058b040, 0x040207fc, 0x497b8880, 0x41780000, - 0x0201f800, 0x00101670, 0x59c408a4, 0x82040d00, - 0x0000000f, 0x82040580, 0x0000000c, 0x02020800, - 0x00100615, 0x4a038805, 0x04000000, 0x5c00b000, - 0x1c01f000, 0x4803c856, 0x4c580000, 0x4ce80000, - 0x42000000, 0x0010b643, 0x0201f800, 0x0010a86e, - 0x59c41008, 0x4c080000, 0x82080500, 0xffffff7f, - 0x48038808, 0x59c40004, 0x82000500, 0x00003e02, - 0x04000005, 0x4201d000, 0x00000014, 0x0201f800, - 0x00105dd2, 0x59c40006, 0x82000500, 0xffffff0f, - 0x48038806, 0x4a038805, 0x00000010, 0x4a038808, - 0x00000004, 0x4200b000, 0x00000065, 0x59c40005, - 0x8c000508, 0x04020012, 0x4201d000, 0x000003e8, - 0x0201f800, 0x00105dd2, 0x8058b040, 0x040207f8, - 0x0201f800, 0x00106c32, 0x4a038808, 0x00000008, - 0x4a035033, 0x00000001, 0x4202d800, 0x00000001, - 0x82000540, 0x00000001, 0x0401f030, 0x0201f800, - 0x00100b29, 0x42000000, 0x0010b6a7, 0x0201f800, - 0x0010a86e, 0x0201f800, 0x00100f42, 0x497b8880, - 0x59a8002a, 0x82000500, 0x0000ffff, 0x4c000000, - 0x0201f800, 0x00101670, 0x5c000000, 0x48038880, - 0x4a038808, 0x00000000, 0x4200b000, 0x00000065, - 0x4a038805, 0x000000f0, 0x0201f800, 0x001019a4, - 0x42000800, 0x000000f0, 0x59c40005, 0x80040d00, - 0x04000008, 0x4201d000, 0x000003e8, 0x0201f800, - 0x00105dd2, 0x8058b040, 0x040207f2, 0x0401f7d1, - 0x59c40006, 0x82000540, 0x000000f0, 0x48038806, - 0x59a8001e, 0x80000540, 0x04020002, 0x80000000, - 0x48038893, 0x80000580, 0x5c001000, 0x4df00000, - 0x0201f800, 0x001019ca, 0x5c03e000, 0x480b8808, - 0x5c01d000, 0x5c00b000, 0x1c01f000, 0x4803c856, - 0x4c580000, 0x4ce80000, 0x59c41008, 0x82080500, - 0xffffff7f, 0x48038808, 0x4c080000, 0x59c40004, - 0x82000500, 0x00003e02, 0x04000005, 0x4201d000, - 0x00000014, 0x0201f800, 0x00105dd2, 0x0201f800, - 0x00100b29, 0x42000000, 0x0010b6a8, 0x0201f800, - 0x0010a86e, 0x0201f800, 0x00100f42, 0x4a038808, - 0x00000002, 0x80000580, 0x48038880, 0x48038893, - 0x0201f800, 0x00101670, 0x4200b000, 0x00000384, - 0x4a038805, 0x000000f0, 0x0201f800, 0x001019a4, - 0x42000800, 0x000000f0, 0x59c40005, 0x80040d00, - 0x04000015, 0x82000500, 0x000000d0, 0x04020012, - 0x4201d000, 0x00000067, 0x0201f800, 0x00105dd2, - 0x8058b040, 0x040207ef, 0x0201f800, 0x00106c32, - 0x4a038808, 0x00000008, 0x4a035033, 0x00000001, - 0x4202d800, 0x00000001, 0x82000540, 0x00000001, - 0x0401f010, 0x497b8880, 0x59a8001e, 0x80000540, - 0x04020002, 0x80000000, 0x48038893, 0x59a8002a, - 0x82000500, 0x0000ffff, 0x4c000000, 0x0201f800, - 0x00101670, 0x5c000000, 0x48038880, 0x80000580, - 0x5c001000, 0x4df00000, 0x0201f800, 0x001019ca, - 0x5c03e000, 0x480b8808, 0x5c01d000, 0x5c00b000, - 0x1c01f000, 0x4803c856, 0x59c40004, 0x82000500, - 0x00003e02, 0x0400000a, 0x0201f800, 0x00106c32, - 0x4a038808, 0x00000008, 0x4a035033, 0x00000001, - 0x4202d800, 0x00000001, 0x0401f052, 0x0201f800, - 0x00100b29, 0x42000000, 0x0010b6a9, 0x0201f800, - 0x0010a86e, 0x0201f800, 0x00100f42, 0x59c40006, - 0x84000508, 0x48038806, 0x4a038805, 0x00000010, - 0x59a80805, 0x84040d4c, 0x48075005, 0x42000800, - 0x00000064, 0x42001000, 0x00104d2c, 0x0201f800, - 0x00105da7, 0x4a038808, 0x00000000, 0x497b8880, - 0x4a038805, 0x000000f0, 0x0201f800, 0x001019a4, - 0x42000800, 0x000000f0, 0x59c40005, 0x80040d00, - 0x0400000e, 0x82000500, 0x000000e0, 0x0402000b, - 0x4201d000, 0x000003e8, 0x0201f800, 0x00105dd2, - 0x0201f800, 0x00105c81, 0x59940004, 0x80000540, - 0x040207ec, 0x0401f023, 0x4c080000, 0x42001000, - 0x00104d39, 0x0201f800, 0x00105cc9, 0x42001000, - 0x00104d2c, 0x0201f800, 0x00105dbd, 0x5c001000, - 0x497b8880, 0x59a8001e, 0x80000540, 0x04020002, - 0x80000000, 0x48038893, 0x59a8002a, 0x82000500, - 0x0000ffff, 0x4c000000, 0x0201f800, 0x00101670, - 0x5c000000, 0x48038880, 0x59a80805, 0x84040d0c, - 0x48075005, 0x59c40006, 0x84000548, 0x48038806, - 0x0201f800, 0x001019ca, 0x4a038808, 0x00000080, - 0x1c01f000, 0x4803c856, 0x4d400000, 0x4d3c0000, - 0x0201f800, 0x00106c32, 0x0201f800, 0x0010a95a, - 0x04020024, 0x599c1017, 0x59a80805, 0x8c040d00, - 0x0402000c, 0x8c08151a, 0x0400001e, 0x84040d42, - 0x48075005, 0x42028000, 0x00000004, 0x42027800, - 0x00000008, 0x8c081508, 0x04020007, 0x0401f011, - 0x42028000, 0x00000004, 0x417a7800, 0x8c081508, - 0x0400000c, 0x4d400000, 0x42028000, 0x0000000e, - 0x42028800, 0x0000ffff, 0x0201f800, 0x0010a258, - 0x5c028000, 0x599c0817, 0x8c040d0a, 0x04020005, - 0x4943c857, 0x493fc857, 0x0201f800, 0x00101d90, - 0x497b8880, 0x4202d800, 0x00000001, 0x0401fcff, - 0x5c027800, 0x5c028000, 0x1c01f000, 0x0201f800, - 0x00100b29, 0x42000000, 0x0010b6aa, 0x0201f800, - 0x0010a86e, 0x0201f800, 0x00100f42, 0x42000000, - 0x00000001, 0x0201f800, 0x00101670, 0x4a038880, - 0x00000001, 0x0201f000, 0x001019ca, 0x4202e000, - 0x00000000, 0x4a033015, 0x00000001, 0x497b301d, - 0x497b3006, 0x4a03b004, 0x60000001, 0x59d80005, - 0x4a03b004, 0x90000001, 0x4a03a804, 0x60000001, - 0x59d40005, 0x4a03a804, 0x90000001, 0x0201f000, - 0x00105667, 0x4a03c825, 0x00000004, 0x4a03c827, - 0x00000004, 0x599c0409, 0x80000d40, 0x04000020, - 0x599c0407, 0x80000540, 0x04000007, 0x800000cc, - 0x599c100b, 0x80080400, 0x4803b000, 0x497bb002, - 0x59d80001, 0x599c000b, 0x4803b000, 0x599c000c, - 0x4803b001, 0x599c0407, 0x80000540, 0x04020002, - 0x497bb002, 0x599c0c09, 0x82040540, 0x00400000, - 0x4803b003, 0x4a03b009, 0x00000004, 0x4a03b004, - 0x10000001, 0x59e00803, 0x82040d00, 0xfffffeff, - 0x82040d40, 0x00008000, 0x4807c003, 0x599c040a, - 0x80000540, 0x04000020, 0x599c0408, 0x80000540, - 0x04000007, 0x800000cc, 0x599c100f, 0x80080400, - 0x4803a800, 0x497ba802, 0x59d40001, 0x599c000f, - 0x4803a800, 0x599c0010, 0x4803a801, 0x599c0408, - 0x80000540, 0x04020002, 0x497ba802, 0x599c0c0a, - 0x82040540, 0x00400000, 0x4803a803, 0x4a03a809, - 0x00000004, 0x4a03a804, 0x10000001, 0x59e00803, - 0x82040d00, 0xfffffbff, 0x82040d40, 0x00008000, - 0x4807c003, 0x800409c0, 0x04000007, 0x4202e000, - 0x00000001, 0x0200b800, 0x00020685, 0x0200f000, - 0x0002069a, 0x1c01f000, 0x0201f800, 0x00100615, - 0x1c01f000, 0x4df00000, 0x4203e000, 0x50000000, - 0x59981005, 0x800811c0, 0x0400001e, 0x58080005, - 0x82000d00, 0x43018780, 0x02020000, 0x0010552a, - 0x8c000508, 0x04000015, 0x580a5808, 0x592c0204, - 0x497a5800, 0x497a5801, 0x82000500, 0x000000ff, - 0x82000c80, 0x0000004b, 0x0402100b, 0x0c01f80f, - 0x5c03e000, 0x83700580, 0x00000003, 0x040007e6, - 0x0200f800, 0x0002069a, 0x0200b000, 0x00020685, - 0x1c01f000, 0x0401f850, 0x5c03e000, 0x0401f7f9, - 0x0401f8ee, 0x0401f7fd, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105171, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x001051f9, 0x00105161, 0x00105161, 0x00105171, - 0x00105171, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x492fc857, 0x42000000, 0x0010b65d, - 0x0201f800, 0x0010a86e, 0x42000000, 0x00000400, - 0x0401f019, 0x492fc857, 0x42000000, 0x0010b65c, - 0x0201f800, 0x0010a86e, 0x42000000, 0x00001000, - 0x0401f011, 0x492fc857, 0x42000000, 0x0010b65b, - 0x0201f800, 0x0010a86e, 0x42000000, 0x00002000, - 0x0401f009, 0x492fc857, 0x42000000, 0x0010b65e, - 0x0201f800, 0x0010a86e, 0x42000000, 0x00000800, - 0x0401f001, 0x4803c857, 0x4202e000, 0x00000001, - 0x592c0c04, 0x82040d00, 0xffff80ff, 0x80040540, - 0x48025c04, 0x0201f000, 0x00020381, 0x592c0204, - 0x492fc857, 0x80000110, 0x040007db, 0x80000040, - 0x04000035, 0x48033002, 0x492f3003, 0x492f3004, - 0x4a033008, 0x001051c5, 0x4202e000, 0x00000003, - 0x1c01f000, 0x592c0204, 0x492fc857, 0x80000110, - 0x040007cd, 0x80000040, 0x04000043, 0x48033002, - 0x492f3003, 0x492f3004, 0x4a033008, 0x001051e1, - 0x4202e000, 0x00000003, 0x1c01f000, 0x492fc857, - 0x0201f800, 0x0010a95a, 0x02020000, 0x0002060c, - 0x492fc857, 0x592e8a06, 0x83440c80, 0x000007f0, - 0x0402100b, 0x83440400, 0x0010aa00, 0x50000000, - 0x80026d40, 0x04000006, 0x4937c857, 0x59340200, - 0x8c00050e, 0x02020000, 0x0002060c, 0x42028000, - 0x00000028, 0x41780800, 0x417a6000, 0x0201f800, - 0x00104bee, 0x0201f800, 0x00108f7d, 0x0201f000, - 0x00020381, 0x592c0a0a, 0x8c040d02, 0x04020016, - 0x59a80021, 0x492fc857, 0x80000540, 0x0402000f, - 0x592c0207, 0x80000540, 0x04000005, 0x0201f800, - 0x00104156, 0x04020004, 0x1c01f000, 0x42000000, - 0x00000000, 0x592c0a06, 0x48065c06, 0x48025a06, - 0x0201f000, 0x00020381, 0x42000000, 0x00000028, - 0x0401f7f9, 0x42000800, 0x00000009, 0x0201f000, - 0x001063a9, 0x592c0208, 0x492fc857, 0x82000c80, - 0x0000199a, 0x04021794, 0x592c0408, 0x80000540, - 0x04020791, 0x59a80821, 0x800409c0, 0x04020009, - 0x592c0207, 0x80000540, 0x0400078b, 0x497a5a06, - 0x0201f800, 0x001041b5, 0x04020004, 0x1c01f000, - 0x42000000, 0x00000028, 0x48025a06, 0x0201f000, - 0x00020381, 0x59980804, 0x59980002, 0x48065800, - 0x492c0801, 0x492f3004, 0x80000040, 0x48033002, - 0x04000002, 0x1c01f000, 0x599a5803, 0x59980008, - 0x4202e000, 0x00000001, 0x0801f000, 0x592e8a06, - 0x592c0406, 0x4803c856, 0x82000500, 0x000000ff, - 0x4200b800, 0x00000001, 0x82000d80, 0x00000001, - 0x04000015, 0x417a8800, 0x4200b800, 0x000007f0, - 0x82000d80, 0x00000002, 0x0400000f, 0x80000540, - 0x02020000, 0x00020381, 0x592e8a06, 0x0201f800, - 0x00020267, 0x02020000, 0x00020381, 0x592e9008, - 0x592e9809, 0x0201f800, 0x00104567, 0x0201f000, - 0x00020381, 0x59a80805, 0x84040d00, 0x48075005, - 0x0201f800, 0x00020267, 0x02000800, 0x0010467a, - 0x81468800, 0x805cb840, 0x040207fa, 0x0201f000, - 0x00020381, 0x592c0a08, 0x4807c857, 0x82040580, - 0x0000000e, 0x04000045, 0x82040580, 0x00000046, - 0x04000046, 0x82040580, 0x00000045, 0x04000020, - 0x82040580, 0x00000029, 0x04000010, 0x82040580, - 0x0000002a, 0x04000009, 0x82040580, 0x0000000f, - 0x04000200, 0x82040580, 0x0000002e, 0x040001fd, - 0x4807c856, 0x0401f1f6, 0x59a80805, 0x84040d04, - 0x48075005, 0x0401f1f7, 0x592e8a06, 0x0201f800, - 0x00020267, 0x040201f3, 0x59340200, 0x84000518, - 0x48026a00, 0x592e6009, 0x4933c857, 0x83300580, - 0xffffffff, 0x0402002a, 0x0401f1ea, 0x592c1407, - 0x480bc857, 0x0201f800, 0x001091d9, 0x411e6000, - 0x04020003, 0x4803c856, 0x0401f1dd, 0x592e3809, - 0x591c1414, 0x84081516, 0x84081554, 0x480a3c14, - 0x4a026403, 0x0000003a, 0x592c040b, 0x80000540, - 0x04000007, 0x4a026403, 0x0000003b, 0x592c020c, - 0x4802641a, 0x592c040c, 0x4802621a, 0x4a026203, - 0x00000001, 0x42000800, 0x80000040, 0x0201f800, - 0x00020855, 0x0401f1cb, 0x59a80068, 0x84000510, - 0x48035068, 0x0401f1c7, 0x592c1207, 0x8c081500, - 0x040201c4, 0x592e8a06, 0x592e6009, 0x0201f800, - 0x001091e3, 0x04020003, 0x4803c856, 0x0401f1b8, - 0x59300c06, 0x82040580, 0x00000004, 0x04000003, - 0x4803c856, 0x0401f1b2, 0x59300a03, 0x82040580, - 0x00000007, 0x04000003, 0x4803c856, 0x0401f1ac, - 0x59300c03, 0x82040580, 0x00000001, 0x04000025, - 0x82040580, 0x00000003, 0x0400001a, 0x82040580, - 0x00000006, 0x04000024, 0x82040580, 0x00000008, - 0x04000019, 0x82040580, 0x0000000a, 0x0400000a, - 0x82040580, 0x0000000c, 0x04000004, 0x82040580, - 0x0000002e, 0x0402001c, 0x42000800, 0x00000009, - 0x0401f017, 0x59326809, 0x0201f800, 0x0010484b, - 0x04020015, 0x42000800, 0x00000005, 0x0401f010, - 0x417a7800, 0x0201f800, 0x00101de2, 0x4a026406, - 0x00000001, 0x42000800, 0x00000003, 0x0401f008, - 0x417a7800, 0x0201f800, 0x00101de2, 0x4a026406, - 0x00000001, 0x42000800, 0x0000000b, 0x0201f800, - 0x001043c7, 0x4a026203, 0x00000001, 0x0201f800, - 0x00106470, 0x0401f17b, 0x40000800, 0x58040000, - 0x80000540, 0x040207fd, 0x492c0800, 0x1c01f000, - 0x492fc857, 0x59300c06, 0x82040580, 0x00000006, - 0x04020094, 0x0201f800, 0x00104836, 0x04020005, - 0x59340200, 0x8c00051a, 0x02000000, 0x00020667, - 0x59340200, 0x8c00050e, 0x0400008a, 0x59300203, - 0x42027800, 0x00000001, 0x82000580, 0x00000007, - 0x02020000, 0x00020667, 0x4a026203, 0x00000002, - 0x0201f000, 0x00020667, 0x42028000, 0x00000002, - 0x4a026206, 0x00000014, 0x4d2c0000, 0x0201f800, - 0x00109fc0, 0x5c025800, 0x59300c06, 0x4807c857, - 0x82040580, 0x00000007, 0x04020063, 0x492fc857, - 0x4a025a06, 0x00000001, 0x0201f000, 0x00020381, - 0x592c240a, 0x492fc857, 0x4813c857, 0x8c10251c, - 0x04020016, 0x8c10251a, 0x04000003, 0x8c10250a, - 0x04000069, 0x59340a00, 0x8c040d0e, 0x04000003, - 0x8c10251e, 0x04000064, 0x0201f800, 0x00020892, - 0x0400006b, 0x592c240a, 0x49366009, 0x49325809, - 0x4a026406, 0x00000006, 0x4a026203, 0x00000007, - 0x0201f000, 0x00020663, 0x592c0a0c, 0x5934000f, - 0x41784000, 0x80001540, 0x0400006d, 0x58080204, - 0x82000500, 0x000000ff, 0x82000580, 0x00000012, - 0x04020004, 0x5808020c, 0x80040580, 0x04000004, - 0x58080000, 0x40084000, 0x0401f7f3, 0x58080000, - 0x49781000, 0x802041c0, 0x04000006, 0x48004000, - 0x80000540, 0x04020007, 0x48226810, 0x0401f005, - 0x4802680f, 0x80000540, 0x04020002, 0x497a6810, - 0x4d2c0000, 0x400a5800, 0x4a025a06, 0x00000002, - 0x0201f800, 0x00020381, 0x5c025800, 0x0401f7bc, - 0x592c040a, 0x8c00051c, 0x04000016, 0x592c0206, - 0x82000580, 0x0000ffff, 0x04020012, 0x592e6009, - 0x83300580, 0xffffffff, 0x040007b1, 0x83300480, - 0x0010cfc0, 0x04001010, 0x59a8000b, 0x81300480, - 0x0402100d, 0x59300008, 0x800001c0, 0x04020005, - 0x59300203, 0x82000580, 0x00000007, 0x04000797, - 0x492fc857, 0x4a025a06, 0x00000029, 0x0201f000, - 0x00020381, 0x492fc857, 0x4a025a06, 0x00000008, - 0x0201f000, 0x00020381, 0x492fc857, 0x4a025a06, - 0x00000045, 0x0201f000, 0x00020381, 0x492fc857, - 0x4a025a06, 0x0000002a, 0x0201f000, 0x00020381, - 0x492fc857, 0x4a025a06, 0x00000028, 0x0201f000, - 0x00020381, 0x492fc857, 0x4a025a06, 0x00000006, - 0x0201f000, 0x00020381, 0x492fc857, 0x4a025a06, - 0x0000000e, 0x0201f000, 0x00020381, 0x59340010, - 0x492e6810, 0x492fc857, 0x80000d40, 0x04000003, - 0x492c0800, 0x1c01f000, 0x5934040b, 0x492e680f, - 0x492fc857, 0x4803c857, 0x80000540, 0x04020003, - 0x4a026a03, 0x00000001, 0x1c01f000, 0x59a8000e, - 0x81640480, 0x0402176e, 0x42026000, 0x0010cfc0, - 0x59300009, 0x81340580, 0x04020004, 0x59300202, - 0x80040580, 0x04000759, 0x83326400, 0x00000024, - 0x41580000, 0x81300480, 0x040017f6, 0x0401f760, - 0x492fc857, 0x592c0407, 0x82000c80, 0x0000199a, - 0x040215dd, 0x592c0204, 0x80000112, 0x040205ca, - 0x592e8a06, 0x0201f800, 0x00020267, 0x04020059, - 0x0201f800, 0x00104836, 0x04020059, 0x592e780a, - 0x493fc857, 0x8d3e7d3e, 0x04020007, 0x59a80021, - 0x80000540, 0x0402004f, 0x0201f800, 0x00104686, - 0x040005c9, 0x833c1d00, 0x0000001f, 0x040005c6, - 0x592c0207, 0x82000c80, 0x00001000, 0x040215c2, - 0x800000c2, 0x800008c4, 0x8005d400, 0x592e9008, - 0x592e9809, 0x5934080d, 0x800409c0, 0x0402002e, - 0x833c1d00, 0x0000001f, 0x81780040, 0x80000000, - 0x800c1902, 0x040217fe, 0x040205b3, 0x0c01f001, - 0x001053cd, 0x001053d0, 0x001053dd, 0x001053e0, - 0x001053e3, 0x0201f800, 0x00108dfb, 0x0401f01a, - 0x0201f800, 0x00104659, 0x04000027, 0x80e9d1c0, - 0x02020800, 0x00105ce7, 0x42028000, 0x00000005, - 0x417a9000, 0x417a9800, 0x0201f800, 0x00108e0b, - 0x0401f00d, 0x42027000, 0x0000004d, 0x0401f006, - 0x42027000, 0x0000004e, 0x0401f003, 0x42027000, - 0x00000052, 0x0201f800, 0x0010451d, 0x02020800, - 0x00108e3b, 0x04000010, 0x8d3e7d3e, 0x04020017, - 0x1c01f000, 0x58040002, 0x80000540, 0x04020007, - 0x4d3c0000, 0x40067800, 0x0201f800, 0x00104639, - 0x5c027800, 0x040207cb, 0x4a025a06, 0x00000030, - 0x0401f00d, 0x4a025a06, 0x0000002c, 0x0401f00a, - 0x4a025a06, 0x00000028, 0x0401f007, 0x4a025a06, - 0x00000029, 0x0401f004, 0x497a5c09, 0x4a025a06, - 0x00000000, 0x4a025a04, 0x00000103, 0x0201f000, - 0x00020381, 0x492fc857, 0x592c0204, 0x80000110, - 0x80000040, 0x04000002, 0x0401f55b, 0x592c0207, - 0x82000500, 0x000003ff, 0x48025a07, 0x8c000506, - 0x04000004, 0x82000500, 0x00000070, 0x04020004, - 0x59a80821, 0x800409c0, 0x04020018, 0x4a025a06, - 0x0000dead, 0x592c0408, 0x82000500, 0x0000f0ff, - 0x48025c08, 0x0201f800, 0x001041e4, 0x04020002, - 0x1c01f000, 0x49425a06, 0x8058b1c0, 0x04000009, - 0x0201f800, 0x00109328, 0x0401f80f, 0x44042800, - 0x82580580, 0x00000002, 0x04020002, 0x48082801, - 0x0201f000, 0x00020381, 0x42028000, 0x00000031, - 0x42000800, 0x00000001, 0x4200b000, 0x00000001, - 0x0401f7ed, 0x592c0408, 0x80000118, 0x832c2c00, - 0x00000009, 0x80142c00, 0x1c01f000, 0x492fc857, - 0x4a025a08, 0x00000006, 0x0201f000, 0x00020381, - 0x492fc857, 0x4a025a08, 0x00000001, 0x0201f000, - 0x00020381, 0x492fc857, 0x592c040a, 0x82000500, - 0x00000003, 0x04000020, 0x0201f800, 0x00020892, - 0x04000021, 0x592c0204, 0x492e6008, 0x82000500, - 0x000000ff, 0x82000580, 0x00000045, 0x0400000e, - 0x592c000b, 0x0201f800, 0x001059b9, 0x02000800, - 0x00020267, 0x04020018, 0x42027000, 0x00000041, - 0x49366009, 0x4a026406, 0x00000001, 0x0201f000, - 0x000208d8, 0x59300015, 0x8400055e, 0x48026015, - 0x42026800, 0x0010b320, 0x42027000, 0x00000040, - 0x0401f7f4, 0x4a025a06, 0x00000101, 0x0201f000, - 0x00020381, 0x4a025a06, 0x0000002c, 0x0201f000, - 0x00020381, 0x4a025a06, 0x00000028, 0x0201f800, - 0x00020381, 0x0201f000, 0x000208b4, 0x492fc857, - 0x0201f800, 0x0010601a, 0x0400000b, 0x592c0204, - 0x80000110, 0x80000040, 0x040204e7, 0x592c0c06, - 0x800409c0, 0x04000009, 0x42000000, 0x00000102, - 0x0401f003, 0x42000000, 0x00000104, 0x48025a06, - 0x0201f000, 0x00020381, 0x592c0c07, 0x800409c0, - 0x04000024, 0x82040480, 0x00000005, 0x04021021, - 0x4c040000, 0x80040800, 0x0201f800, 0x0010603f, - 0x5c001000, 0x04020018, 0x832c0400, 0x00000008, - 0x4000a000, 0x0201f800, 0x00106068, 0x04020012, - 0x592c1207, 0x82cc0580, 0x0010b30a, 0x04020009, - 0x58c80c0b, 0x84040d00, 0x84040d02, 0x8c081500, - 0x04000002, 0x84040d5e, 0x4805940b, 0x0401f001, - 0x42000000, 0x00000000, 0x48025a06, 0x0201f000, - 0x00020381, 0x42000000, 0x00000103, 0x0401f7fb, - 0x42000000, 0x00000102, 0x0401f7f8, 0x492fc857, - 0x592e7c06, 0x833c0500, 0xfffffffe, 0x04020043, - 0x592c4007, 0x42026000, 0x0010cfc0, 0x41581800, - 0x400c0000, 0x81300480, 0x04021023, 0x59300203, - 0x82000580, 0x00000000, 0x04000007, 0x59300008, - 0x80000d40, 0x04000004, 0x58040005, 0x80200580, - 0x04000004, 0x83326400, 0x00000024, 0x0401f7f1, - 0x58040204, 0x82000500, 0x000000ff, 0x82000d80, - 0x00000053, 0x04000007, 0x82000d80, 0x00000048, - 0x04000004, 0x82000580, 0x00000018, 0x04020023, - 0x4d2c0000, 0x0201f800, 0x00108997, 0x5c025800, - 0x0400001e, 0x4a025a06, 0x00000000, 0x0201f000, - 0x00020381, 0x592e8a06, 0x83440480, 0x000007f0, - 0x04021016, 0x83440400, 0x0010aa00, 0x50000000, - 0x80026d40, 0x04000011, 0x4d2c0000, 0x0201f800, - 0x00104619, 0x0400000c, 0x42028000, 0x00000005, - 0x592c0a08, 0x0201f800, 0x00104bee, 0x0201f800, - 0x00108f83, 0x0201f800, 0x00020381, 0x5c025800, - 0x0401f7e5, 0x5c025800, 0x4a025a06, 0x00000031, - 0x0201f000, 0x00020381, 0x492fc857, 0x4d2c0000, - 0x0201f800, 0x0010082a, 0x04000016, 0x492fc857, - 0x412f4000, 0x0201f800, 0x0010082a, 0x0400000e, - 0x492fc857, 0x412dd800, 0x0201f800, 0x00103941, - 0x0201f800, 0x0010394b, 0x49a1d80b, 0x5c025800, - 0x492dd80a, 0x0201f800, 0x00101fbb, 0x0201f000, - 0x00101fda, 0x41a25800, 0x0201f800, 0x0010083a, - 0x5c025800, 0x4a025a06, 0x00004005, 0x4a025c06, - 0x00000002, 0x0201f000, 0x00020381, 0x4807c857, - 0x485fc857, 0x4200b800, 0x00000001, 0x5c000800, - 0x4c5c0000, 0x0401f005, 0x4807c857, 0x485fc857, - 0x5c000800, 0x4d780000, 0x4803c857, 0x492fc857, - 0x8c00050e, 0x02020800, 0x0010060d, 0x4203e000, - 0x50000000, 0x4200b800, 0x00008003, 0x0201f000, - 0x0010061a, 0x592c0204, 0x80000110, 0x80000040, - 0x0402042d, 0x0201f800, 0x00104886, 0x04020002, - 0x1c01f000, 0x49425a06, 0x4806580d, 0x480a580e, - 0x4943c857, 0x4807c857, 0x480bc857, 0x0201f000, - 0x00020381, 0x592c0204, 0x80000110, 0x80000040, - 0x0402041d, 0x0201f800, 0x001049ec, 0x04020002, - 0x1c01f000, 0x49425a06, 0x48065811, 0x480a5812, - 0x0201f000, 0x00020381, 0x592c0204, 0x80000110, - 0x04000411, 0x80000040, 0x0402000c, 0x4202e000, - 0x00000001, 0x592c020a, 0x8c000504, 0x02000000, - 0x00020603, 0x592c0207, 0x82000c80, 0x00001001, - 0x04021415, 0x0401f009, 0x4202e000, 0x00000003, - 0x48033002, 0x492f3003, 0x492f3004, 0x4a033008, - 0x00020603, 0x1c01f000, 0x4202e000, 0x00000002, - 0x42000000, 0x0010bcd9, 0x50007000, 0x492c700b, - 0x4978700e, 0x4978700c, 0x592c0011, 0x592c0812, - 0x48007007, 0x48047008, 0x592c1013, 0x82080500, - 0xffff0000, 0x04000003, 0x0201f800, 0x00100615, - 0x4978700d, 0x82080480, 0x00000180, 0x4803c857, - 0x04001007, 0x4800700f, 0x4a007005, 0x00000180, - 0x4a007004, 0x00000060, 0x0401f005, 0x4978700f, - 0x48087005, 0x80081104, 0x48087004, 0x5838000a, - 0x48007003, 0x40381000, 0x0201f000, 0x001008a1, - 0x0201f800, 0x00100819, 0x04000003, 0x59980007, - 0x0801f000, 0x1c01f000, 0x40307000, 0x5838000b, - 0x80025d40, 0x0400001b, 0x58380002, 0x82000580, - 0x00000100, 0x0400001d, 0x4c380000, 0x592c0204, - 0x82000500, 0x000000ff, 0x82000580, 0x00000012, - 0x0400000b, 0x592c0208, 0x8400054e, 0x48025a08, - 0x4a025a06, 0x00000002, 0x4a025a04, 0x00000103, - 0x0201f800, 0x00020381, 0x0401f005, 0x4a025a06, - 0x00000010, 0x0201f800, 0x00020381, 0x5c007000, - 0x4202e000, 0x00000001, 0x4a007002, 0x00000100, - 0x49787010, 0x1c01f000, 0x58380004, 0x82000480, - 0x00000003, 0x04000087, 0x58380010, 0x8c000500, - 0x04020019, 0x4200b000, 0x00000003, 0x832cac00, - 0x00000011, 0x5838000a, 0x5838100d, 0x8008a400, - 0x4c380000, 0x0201f800, 0x0010a93e, 0x5c007000, - 0x5838000d, 0x82000400, 0x00000003, 0x4800700d, - 0x4a007010, 0x00000001, 0x58380004, 0x82000480, - 0x00000003, 0x48007004, 0x82000580, 0x00000003, - 0x0400006c, 0x5838000e, 0x80001d40, 0x04020020, - 0x4c380000, 0x0201f800, 0x00100819, 0x5c007000, - 0x04000010, 0x4a025a04, 0x0000010a, 0x42001800, - 0x00000005, 0x480c700e, 0x5838000c, 0x80000540, - 0x04020002, 0x5838000b, 0x40000800, 0x492c0801, - 0x492c700c, 0x42000800, 0x0000000f, 0x0401f011, - 0x4202e000, 0x00000008, 0x4a033007, 0x001055f9, - 0x1c01f000, 0x4202e000, 0x00000002, 0x42000000, - 0x0010bcd9, 0x50007000, 0x0401f7e7, 0x583a580c, - 0x400c0000, 0x42000800, 0x00000014, 0x80040c80, - 0x58381004, 0x5838000f, 0x41783000, 0x80000540, - 0x04020005, 0x84183540, 0x82081480, 0x00000003, - 0x0400003c, 0x40080000, 0x80040480, 0x04001002, - 0x40080800, 0x4004b000, 0x412c0000, 0x800c0400, - 0x4000a800, 0x5838000a, 0x5838100d, 0x8008a400, - 0x4c080000, 0x4c040000, 0x4c0c0000, 0x4c380000, - 0x0201f800, 0x0010a93e, 0x5c007000, 0x5c001800, - 0x5c000800, 0x40040000, 0x58381004, 0x80080480, - 0x48007004, 0x82000580, 0x00000003, 0x04000002, - 0x84183500, 0x5c000000, 0x80041400, 0x82080480, - 0x00000060, 0x04020003, 0x84183542, 0x41781000, - 0x400c0000, 0x80041c00, 0x820c0480, 0x00000014, - 0x04020003, 0x84183544, 0x40001800, 0x40080800, - 0x4804700d, 0x480c700e, 0x40180000, 0x0c01f001, - 0x00105644, 0x00105648, 0x00105646, 0x00105644, - 0x001055e0, 0x00105648, 0x00105646, 0x00105644, - 0x0201f800, 0x00100615, 0x5838100f, 0x0401f739, - 0x5838080d, 0x82040400, 0x00000002, 0x5838100a, - 0x80080400, 0x50001000, 0x800811c0, 0x0402000f, - 0x4202e000, 0x00000001, 0x583a580b, 0x4978700b, - 0x49787010, 0x592c0204, 0x82000500, 0x000000ff, - 0x82000580, 0x00000012, 0x02000000, 0x0002063b, - 0x0201f000, 0x00020603, 0x5838000a, 0x80040c00, - 0x82381c00, 0x00000007, 0x54041800, 0x80040800, - 0x800c1800, 0x54041800, 0x0401f71a, 0x0201f800, - 0x00100819, 0x02000800, 0x00100615, 0x4a02580a, - 0x0010bc78, 0x42000800, 0x0010bcd9, 0x452c0800, - 0x497a580b, 0x497a580c, 0x497a580d, 0x497a580e, - 0x497a580f, 0x4a025809, 0x0010559a, 0x497a5810, - 0x4a025802, 0x00000100, 0x4a025801, 0x00000001, - 0x1c01f000, 0x59c80007, 0x8c000502, 0x04000071, - 0x835c2c80, 0x00000005, 0x02001000, 0x00105c5c, - 0x59c82817, 0x4817506e, 0x497b9005, 0x82140500, - 0x00e00000, 0x0402004f, 0x82140500, 0x000003ff, - 0x82001c00, 0x00000006, 0x41cc2000, 0x42003000, - 0x00006080, 0x820c0480, 0x00000040, 0x04001006, - 0x42001000, 0x00000040, 0x820c1c80, 0x00000040, - 0x0401f003, 0x400c1000, 0x41781800, 0x54182000, - 0x80102000, 0x80183000, 0x80081040, 0x040207fc, - 0x800c19c0, 0x04000005, 0x59c80005, 0x80000000, - 0x48039005, 0x0401f7ea, 0x82140500, 0x01f60000, - 0x04020029, 0x82140500, 0x0000f000, 0x0400000b, - 0x82000c80, 0x00002000, 0x0402100f, 0x4a039005, - 0x00000140, 0x82140500, 0x0e000000, 0x80000132, - 0x0c01f83e, 0x1c01f000, 0x59cc0400, 0x82000500, - 0x0000ff00, 0x82000580, 0x00008100, 0x040007f4, - 0x0401f01c, 0x4817c857, 0x82140500, 0x000003ff, - 0x04020007, 0x59cc0400, 0x82000500, 0x0000ff00, - 0x82000580, 0x00008100, 0x04020012, 0x42000000, - 0x0010b6bc, 0x0201f800, 0x0010a86e, 0x0201f800, - 0x00105b32, 0x4803c856, 0x4a039005, 0x00000140, - 0x0401f020, 0x4817c857, 0x82140500, 0x00f60000, - 0x04020004, 0x0201f800, 0x00105b6e, 0x040207d2, - 0x0201f800, 0x00104e0d, 0x04000010, 0x59c400a4, - 0x4803c857, 0x82000500, 0x0000000f, 0x82000580, - 0x0000000a, 0x04020009, 0x497b5016, 0x59c400a3, - 0x82000540, 0x00080000, 0x480388a3, 0x82000500, - 0xfff7ffff, 0x480388a3, 0x4817c856, 0x0201f800, - 0x0010a79f, 0x4a039005, 0x00000140, 0x0401f842, - 0x4803c856, 0x1c01f000, 0x00105702, 0x00105a13, - 0x001056fa, 0x001056fa, 0x001056fa, 0x001056fa, - 0x001056fa, 0x001056fa, 0x4803c857, 0x42000000, - 0x0010b659, 0x0201f800, 0x0010a86e, 0x4a039005, - 0x00000140, 0x1c01f000, 0x59cc0400, 0x82000d00, - 0x0000ff00, 0x82041500, 0x0000f000, 0x840409c0, - 0x82140500, 0x000003ff, 0x800018c4, 0x8c142d14, - 0x04000005, 0x59cc0002, 0x82000500, 0x00000003, - 0x800c1c80, 0x480f5016, 0x82080580, 0x00002000, - 0x04020013, 0x836c0580, 0x00000001, 0x0402000e, - 0x59cc0006, 0x82000500, 0xff000000, 0x82000580, - 0x11000000, 0x02020800, 0x001006ba, 0x04020011, - 0x0201f800, 0x00103951, 0x0201f800, 0x00105c81, - 0x0401f00c, 0x0401f81f, 0x0401f00a, 0x82080580, - 0x00003000, 0x04020003, 0x0401fa40, 0x0401f005, - 0x82080580, 0x00008000, 0x04020002, 0x0401fb36, - 0x1c01f000, 0x4817c857, 0x42000000, 0x0010b658, - 0x0201f800, 0x0010a86e, 0x836c0580, 0x00000003, - 0x0402000b, 0x4c080000, 0x4c0c0000, 0x42001000, - 0x00008048, 0x40141800, 0x80142120, 0x0201f800, - 0x00103857, 0x5c001800, 0x5c001000, 0x1c01f000, - 0x59cc0002, 0x82000500, 0xff000000, 0x82001580, - 0x01000000, 0x04000006, 0x82001580, 0x23000000, - 0x02020800, 0x001006ba, 0x040201c9, 0x82040580, - 0x00000023, 0x04020055, 0x59cc0004, 0x4803c857, - 0x59cc0006, 0x82000500, 0xff000000, 0x59cc0801, - 0x82040d00, 0x00ffffff, 0x80040540, 0x4803c857, - 0x0401fbb2, 0x02000800, 0x001006ba, 0x040001b8, - 0x59300c06, 0x82040580, 0x00000010, 0x04000012, - 0x82040580, 0x00000011, 0x0400000f, 0x82040580, - 0x00000001, 0x0400000c, 0x82040580, 0x00000004, - 0x04000009, 0x82040580, 0x00000008, 0x04000006, - 0x82040580, 0x0000000a, 0x02020800, 0x001006ba, - 0x040201a3, 0x59300004, 0x82000500, 0x80010000, - 0x04000006, 0x0201f800, 0x00106cb4, 0x02020800, - 0x001006ba, 0x0402019a, 0x59cc0a04, 0x48066202, - 0x59a80016, 0x800001c0, 0x02000800, 0x001006ba, - 0x04000193, 0x59cc0006, 0x82000500, 0xffff0000, - 0x82000d80, 0x02000000, 0x04020005, 0x42027000, - 0x00000015, 0x0201f000, 0x000208d8, 0x82000d80, - 0x02140000, 0x040007fa, 0x82000d80, 0x02100000, - 0x040007f7, 0x82000d80, 0x02100000, 0x040007f4, - 0x82000d80, 0x01000000, 0x02020800, 0x001006ba, - 0x0402017b, 0x59cc0006, 0x82000500, 0x0000ffff, - 0x02020800, 0x001006ba, 0x04020175, 0x42027000, - 0x00000016, 0x0401f7e8, 0x82040580, 0x00000022, - 0x02020800, 0x001006ba, 0x0402016d, 0x59cc0004, - 0x4803c857, 0x59cc0006, 0x4803c857, 0x59cc0001, - 0x4803c857, 0x59a80016, 0x800001c0, 0x02000800, - 0x001006ba, 0x04000162, 0x59a80806, 0x8c040d14, - 0x04000011, 0x0401f97d, 0x0402000f, 0x0401f993, - 0x0400000d, 0x42027000, 0x0000004c, 0x59cc0001, - 0x82000500, 0x00ffffff, 0x0201f800, 0x00105c25, - 0x0400013e, 0x42028800, 0x0000ffff, 0x417a6800, - 0x0401f13a, 0x59cc0006, 0x82000500, 0xffff0000, - 0x82000d80, 0x03000000, 0x04020023, 0x59a80026, - 0x8c000508, 0x04000017, 0x8400054c, 0x48035026, - 0x59cc0800, 0x82040d00, 0x00ffffff, 0x48075010, - 0x497b8830, 0x84040d70, 0x48078832, 0x59c40802, - 0x84040d4c, 0x48078802, 0x59cc0007, 0x82000500, - 0x0000ffff, 0x48038893, 0x4803501e, 0x42000800, - 0x00000003, 0x59a81010, 0x0201f800, 0x001069af, - 0x59cc0006, 0x82000500, 0x0000ffff, 0x02020800, - 0x001006ba, 0x0402012a, 0x42027000, 0x00000017, - 0x0401f0e5, 0x82000d80, 0x04000000, 0x04020013, - 0x59cc0006, 0x82000500, 0x0000ffff, 0x02020800, - 0x001006ba, 0x0402011e, 0x0201f800, 0x00104e0d, - 0x04000004, 0x42027000, 0x0000001d, 0x0401f0d6, - 0x59a80026, 0x84000548, 0x48035026, 0x42027000, - 0x00000030, 0x0401f0d0, 0x82000d80, 0x05000000, - 0x0402000a, 0x59cc0006, 0x82000500, 0x0000ffff, - 0x02020800, 0x001006ba, 0x04020109, 0x42027000, - 0x00000018, 0x0401f0c4, 0x82000d80, 0x20100000, - 0x04020004, 0x42027000, 0x00000019, 0x0401f0be, - 0x82000d80, 0x21100000, 0x04020004, 0x42027000, - 0x0000001a, 0x0401f0b8, 0x82000d80, 0x52000000, - 0x0402000a, 0x59cc0006, 0x82000500, 0x0000ffff, - 0x02020800, 0x001006ba, 0x040200f1, 0x42027000, - 0x0000001b, 0x0401f0ac, 0x82000d80, 0x50000000, - 0x0402000a, 0x59cc0006, 0x82000500, 0x0000ffff, - 0x02020800, 0x001006ba, 0x040200e5, 0x42027000, - 0x0000001c, 0x0401f0a0, 0x82000d80, 0x13000000, - 0x04020004, 0x42027000, 0x00000034, 0x0401f09a, - 0x82000d80, 0x12000000, 0x0402000a, 0x59cc0006, - 0x82000500, 0x0000ffff, 0x02020800, 0x001006ba, - 0x040200d3, 0x42027000, 0x00000024, 0x0401f08e, - 0x82000d00, 0xff000000, 0x82040d80, 0x24000000, - 0x04020004, 0x42027000, 0x0000002d, 0x0401f086, - 0x82000d00, 0xff000000, 0x82040d80, 0x53000000, - 0x04020004, 0x42027000, 0x0000002a, 0x0401f07e, - 0x82000d80, 0x0f000000, 0x04020004, 0x42027000, - 0x00000020, 0x0401f078, 0x82000d80, 0x61040000, - 0x04020036, 0x83cc1400, 0x00000006, 0x80080800, - 0x50080000, 0x82000500, 0x0000ffff, 0x82000480, - 0x00000004, 0x4c580000, 0x8000b104, 0x8058b1c0, - 0x04000026, 0x4c100000, 0x50041800, 0x820c1500, - 0x03000000, 0x80081130, 0x42000000, 0x0010b615, - 0x82082580, 0x00000000, 0x04020004, 0x42000000, - 0x0010b612, 0x0401f00c, 0x82082580, 0x00000001, - 0x04020004, 0x42000000, 0x0010b613, 0x0401f006, - 0x82082580, 0x00000002, 0x04020003, 0x42000000, - 0x0010b614, 0x0201f800, 0x0010a86e, 0x42001000, - 0x00008015, 0x820c2500, 0x0000ffff, 0x800c1920, - 0x0201f800, 0x00103857, 0x5c002000, 0x80040800, - 0x8058b040, 0x040207da, 0x5c00b000, 0x42027000, - 0x00000023, 0x0401f040, 0x82000d80, 0x60000000, - 0x04020004, 0x42027000, 0x0000003f, 0x0401f03a, - 0x82000d80, 0x54000000, 0x04020008, 0x0401fb36, - 0x02020800, 0x001006ba, 0x04020075, 0x42027000, - 0x00000046, 0x0401f030, 0x82000d80, 0x55000000, - 0x04020009, 0x0401fb54, 0x04020004, 0x42027000, - 0x00000041, 0x0401f028, 0x42027000, 0x00000042, - 0x0401f025, 0x82000d80, 0x78000000, 0x04020004, - 0x42027000, 0x00000045, 0x0401f01f, 0x82000d80, - 0x10000000, 0x04020004, 0x42027000, 0x0000004e, - 0x0401f019, 0x82000d80, 0x63000000, 0x04020004, - 0x42027000, 0x0000004a, 0x0401f013, 0x82000d00, - 0xff000000, 0x82040d80, 0x56000000, 0x04020004, - 0x42027000, 0x0000004f, 0x0401f00b, 0x82000d00, - 0xff000000, 0x82040d80, 0x57000000, 0x04020004, - 0x42027000, 0x00000050, 0x0401f003, 0x42027000, - 0x0000001d, 0x59cc3800, 0x821c3d00, 0x00ffffff, - 0x821c0580, 0x00fffffe, 0x59cc0001, 0x04020005, - 0x40003000, 0x42028800, 0x000007fe, 0x0401f005, - 0x0401f8da, 0x02020800, 0x001006ba, 0x04020034, - 0x0201f800, 0x00104401, 0x02020800, 0x001006ba, - 0x0402002f, 0x83380580, 0x00000046, 0x04020006, - 0x59a80010, 0x80180580, 0x02000800, 0x001006ba, - 0x04000027, 0x59340200, 0x8c000514, 0x0400000f, - 0x83380580, 0x00000030, 0x0400000c, 0x83380580, - 0x0000003f, 0x04000009, 0x83380580, 0x00000034, - 0x04000006, 0x83380580, 0x00000024, 0x04000003, - 0x42027000, 0x0000004c, 0x0201f800, 0x00020892, - 0x04000018, 0x49366009, 0x4a026406, 0x00000004, - 0x59cc0c04, 0x48066202, 0x83380580, 0x0000004c, - 0x04020009, 0x4a026406, 0x00000011, 0x813669c0, - 0x04020005, 0x59cc0001, 0x82000500, 0x00ffffff, - 0x4802601e, 0x0201f000, 0x000208d8, 0x59880053, - 0x4803c857, 0x80000000, 0x48031053, 0x1c01f000, - 0x42001000, 0x00008049, 0x59cc1806, 0x800c1930, - 0x0201f800, 0x00103857, 0x0201f800, 0x001076c9, - 0x02000800, 0x001006ba, 0x040007f1, 0x49366009, - 0x4a026406, 0x00000004, 0x59cc0c04, 0x48066202, - 0x4a026403, 0x00000009, 0x4a02641a, 0x00000009, - 0x4a02621a, 0x00002900, 0x4a026203, 0x00000001, - 0x0201f000, 0x00106470, 0x59a80026, 0x4803c857, - 0x8c000508, 0x04000010, 0x59cc0006, 0x82000500, - 0xff000000, 0x82000d80, 0x03000000, 0x0400000c, - 0x82000d80, 0x20000000, 0x04000009, 0x82000d80, - 0x05000000, 0x04000006, 0x82000d80, 0x21000000, - 0x04000003, 0x80000580, 0x1c01f000, 0x82000540, - 0x00000001, 0x0401f7fd, 0x59cc2006, 0x82102500, - 0xff000000, 0x9c1021c0, 0x0401f807, 0x820c1c00, - 0x0010b2df, 0x500c1800, 0x800c0500, 0x4803c857, - 0x1c01f000, 0x40100800, 0x41781800, 0x82040480, - 0x00000020, 0x04001004, 0x800c1800, 0x40000800, - 0x0401f7fb, 0x82040500, 0x0000000f, 0x82000400, - 0x0010a95f, 0x50000000, 0x8c040d08, 0x04000002, - 0x900001c0, 0x1c01f000, 0x4803c856, 0x0401fadd, - 0x0402000a, 0x0201f800, 0x00101eb0, 0x04020007, - 0x59cc0002, 0x82000500, 0xff000000, 0x82000d80, - 0x08000000, 0x04000802, 0x1c01f000, 0x4803c856, - 0x59cc0400, 0x82000d00, 0x0000ff00, 0x840409c0, - 0x82040580, 0x00000033, 0x0402001f, 0x0401f98f, - 0x04000038, 0x59cc0a04, 0x48066202, 0x59cc0006, - 0x4803c857, 0x82000500, 0xffff0000, 0x82000d80, - 0x02000000, 0x04020009, 0x59cc0006, 0x82000500, - 0x0000ffff, 0x0402002b, 0x42027000, 0x00000015, - 0x0201f000, 0x000208d8, 0x82000d80, 0x01000000, - 0x04020024, 0x59cc0006, 0x82000500, 0x0000ffff, - 0x04020020, 0x42027000, 0x00000016, 0x0201f000, - 0x000208d8, 0x82040580, 0x00000032, 0x04020019, - 0x59cc0006, 0x82000500, 0xffff0000, 0x82000d80, - 0x14000000, 0x04020013, 0x42027000, 0x00000038, - 0x59cc0001, 0x0401f810, 0x0402000e, 0x0201f800, - 0x001043fc, 0x0402000b, 0x0201f800, 0x00020892, - 0x04000008, 0x49366009, 0x4a026406, 0x00000004, - 0x59cc0c04, 0x48066202, 0x0201f000, 0x000208d8, - 0x1c01f000, 0x4803c857, 0x4c580000, 0x4c100000, - 0x4c380000, 0x4c340000, 0x82003500, 0x00ffffff, - 0x82181500, 0x00ff0000, 0x82081580, 0x00ff0000, - 0x04020016, 0x82181480, 0x00fffffc, 0x04001013, - 0x82181580, 0x00fffffd, 0x04020004, 0x42028800, - 0x000007fd, 0x0401f040, 0x82181580, 0x00fffffe, - 0x04020004, 0x42028800, 0x000007fe, 0x0401f03a, - 0x82181580, 0x00fffffc, 0x04020004, 0x42028800, - 0x000007fc, 0x0401f034, 0x41781000, 0x42002000, - 0x00000000, 0x4200b000, 0x000007f0, 0x41ac7000, - 0x50380000, 0x80006d40, 0x04020005, 0x800811c0, - 0x0402001e, 0x8410155e, 0x0401f01c, 0x58340212, - 0x82000500, 0x0000ff00, 0x04000011, 0x59a84010, - 0x82204500, 0x00ffff00, 0x82180500, 0x00ffff00, - 0x04000002, 0x80200580, 0x58340002, 0x0402000f, - 0x82000500, 0x000000ff, 0x82184500, 0x000000ff, - 0x80204580, 0x04020009, 0x0401f006, 0x58340002, - 0x82000500, 0x00ffffff, 0x80184580, 0x04020003, - 0x40128800, 0x0401f00c, 0x80102000, 0x80387000, - 0x8058b040, 0x040207db, 0x800811c0, 0x04020005, - 0x481bc857, 0x82000540, 0x00000001, 0x0401f003, - 0x840a8d1e, 0x80000580, 0x5c006800, 0x5c007000, - 0x5c002000, 0x5c00b000, 0x1c01f000, 0x59a80026, - 0x8c00050e, 0x04000003, 0x8c000502, 0x04000006, - 0x59cc0c00, 0x80040910, 0x82040500, 0x0000000f, - 0x0c01f002, 0x1c01f000, 0x00105a2e, 0x00105a2e, - 0x00105a2e, 0x00105b1d, 0x00105a2e, 0x00105a30, - 0x00105a48, 0x00105a4b, 0x00105a2e, 0x00105a2e, - 0x00105a2e, 0x00105a2e, 0x00105a2e, 0x00105a2e, - 0x00105a2e, 0x00105a2e, 0x4803c856, 0x1c01f000, - 0x0401f8de, 0x04000014, 0x82140500, 0x000003ff, - 0x800000c4, 0x82000480, 0x00000008, 0x0400100e, - 0x59cc0001, 0x59326809, 0x59340802, 0x80040580, - 0x82000500, 0x00ffffff, 0x04020007, 0x59cc0a04, - 0x48066202, 0x42027000, 0x00000046, 0x0201f000, - 0x000208d8, 0x59cc0004, 0x4803c857, 0x1c01f000, - 0x59cc0004, 0x4803c857, 0x1c01f000, 0x0401f8c3, - 0x04000016, 0x82140500, 0x000003ff, 0x800000c4, - 0x82000480, 0x0000000c, 0x04001010, 0x59cc0001, - 0x82000500, 0x00ffffff, 0x59326809, 0x59340802, - 0x82040d00, 0x00ffffff, 0x80040580, 0x04020007, - 0x59cc0a04, 0x48066202, 0x42027000, 0x00000045, - 0x0201f000, 0x000208d8, 0x59cc0004, 0x4803c857, - 0x1c01f000, 0x59cc0004, 0x4803c857, 0x59cc0000, - 0x82000500, 0xff000000, 0x59cc1001, 0x82081500, - 0x00ffffff, 0x80080540, 0x4803c857, 0x4817c857, - 0x0401f9d8, 0x02020800, 0x001006ba, 0x04020016, - 0x0201f800, 0x00101eb0, 0x02020800, 0x001006ba, - 0x04020011, 0x59cc0002, 0x82000500, 0xff000000, - 0x82000580, 0x00000000, 0x02020800, 0x001006ba, - 0x04020009, 0x82040500, 0x0000000f, 0x82000c80, - 0x00000006, 0x02021800, 0x001006ba, 0x04021002, - 0x0c01f003, 0x4803c856, 0x1c01f000, 0x00105a91, - 0x00105a93, 0x00105a91, 0x00105a91, 0x00105aec, - 0x00105afb, 0x4803c856, 0x1c01f000, 0x59a80016, - 0x800001c0, 0x02020800, 0x001006ba, 0x040207fa, - 0x59cc0802, 0x4807c856, 0x8c040d2e, 0x0402001d, - 0x0201f800, 0x001076c9, 0x02000800, 0x00100615, - 0x59cc0001, 0x0401ff18, 0x0402000d, 0x0201f800, - 0x00020267, 0x0402000a, 0x4a026406, 0x00000005, - 0x49366009, 0x59cc0804, 0x4806601c, 0x42027000, - 0x00000088, 0x0201f000, 0x000208d8, 0x4803c857, - 0x42028800, 0x0000ffff, 0x417a6800, 0x59cc0001, - 0x82000500, 0x00ffffff, 0x4802601e, 0x0401f7ef, - 0x59cc0001, 0x4803c857, 0x0401feff, 0x02020800, - 0x001006ba, 0x040207d4, 0x0201f800, 0x001043fc, - 0x02020800, 0x001006ba, 0x040207cf, 0x59cc0005, - 0x8c000500, 0x04020006, 0x59340200, 0x8c00050e, - 0x02020800, 0x001006ba, 0x040207c7, 0x0201f800, - 0x00104842, 0x04020013, 0x0401f840, 0x02000800, - 0x001006ba, 0x040007c0, 0x0201f800, 0x00020892, - 0x02000800, 0x001006ba, 0x040007bb, 0x49366009, - 0x4a026406, 0x00000002, 0x59cc0804, 0x4806601c, - 0x42027000, 0x00000088, 0x0201f000, 0x000208d8, - 0x0201f800, 0x00020892, 0x040007af, 0x49366009, - 0x4a026406, 0x00000004, 0x59cc0c04, 0x48066202, - 0x42027000, 0x00000001, 0x0201f000, 0x000208d8, - 0x59cc0802, 0x8c040d2e, 0x0400000b, 0x0401f81f, - 0x04000009, 0x0401f961, 0x04020007, 0x59cc0a04, - 0x48066202, 0x42027000, 0x00000089, 0x0201f000, - 0x000208d8, 0x4933c857, 0x1c01f000, 0x59cc0004, - 0x4803c857, 0x59cc0802, 0x8c040d2e, 0x0400000b, - 0x0401f80e, 0x04000009, 0x0401f950, 0x04020007, - 0x59cc0a04, 0x48066202, 0x42027000, 0x0000008a, - 0x0201f000, 0x000208d8, 0x4933c857, 0x1c01f000, - 0x59cc0a04, 0x0401f002, 0x59cc0c04, 0x59a8000e, - 0x59a81067, 0x80080400, 0x80040480, 0x04021008, - 0x40040000, 0x800000c4, 0x800408ca, 0x80040c00, - 0x82066400, 0x0010cfc0, 0x1c01f000, 0x80000580, - 0x0401f7fe, 0x59cc0802, 0x8c040d2e, 0x04020010, - 0x0401ffec, 0x0400000e, 0x59cc0001, 0x82000500, - 0x00ffffff, 0x59326809, 0x59340802, 0x82040d00, - 0x00ffffff, 0x80040580, 0x04020005, 0x42027000, - 0x00000051, 0x0201f000, 0x000208d8, 0x59cc0004, - 0x4803c857, 0x1c01f000, 0x4803c856, 0x42003000, - 0x00000105, 0x0401f001, 0x4803c856, 0x4c3c0000, - 0x41cc7800, 0x40142000, 0x0401f803, 0x5c007800, - 0x1c01f000, 0x4803c856, 0x4c580000, 0x583c0400, - 0x82000500, 0x0000f000, 0x82000580, 0x0000c000, - 0x04000024, 0x0201f800, 0x00020892, 0x04000021, - 0x4c180000, 0x583c0001, 0x0401fe6f, 0x0402001f, - 0x0201f800, 0x001043fc, 0x0402001c, 0x49366009, - 0x0201f800, 0x0010082a, 0x04000018, 0x492e6017, - 0x497a5800, 0x497a5a04, 0x48125c04, 0x832cac00, - 0x00000005, 0x4200b000, 0x00000007, 0x403ca000, - 0x0201f800, 0x0010a93e, 0x5c003000, 0x481a641a, - 0x4a026403, 0x0000003e, 0x4a026406, 0x00000001, - 0x4a026203, 0x00000001, 0x0201f800, 0x00106470, - 0x5c00b000, 0x1c01f000, 0x0201f800, 0x000208b4, - 0x5c003000, 0x0401f7fb, 0x4803c856, 0x59cc0400, - 0x82000d00, 0x0000ff00, 0x82040500, 0x0000f000, - 0x840409c0, 0x82000580, 0x00002000, 0x04020049, - 0x82040580, 0x00000022, 0x0402003a, 0x59c400a4, - 0x82000500, 0x0000000f, 0x82000c80, 0x00000007, - 0x04001004, 0x82000480, 0x0000000c, 0x0400103f, - 0x59cc0006, 0x82000500, 0xffff0000, 0x82000d80, - 0x04000000, 0x04000039, 0x82000d80, 0x60000000, - 0x04000036, 0x82000d80, 0x54000000, 0x04000033, - 0x82000d80, 0x03000000, 0x04020015, 0x59a80826, - 0x8c040d02, 0x0402002d, 0x8c040d08, 0x0402002b, - 0x0201f800, 0x0010473b, 0x0400002b, 0x59a8001d, - 0x800000d0, 0x59a80810, 0x82040d00, 0x000000ff, - 0x80040540, 0x59cc0800, 0x82040d00, 0x00ffffff, - 0x80040580, 0x0402001b, 0x0401f01c, 0x59c40802, - 0x8c040d0c, 0x04020017, 0x82000d80, 0x52000000, - 0x040007ec, 0x82000d80, 0x05000000, 0x040007e9, - 0x82000d80, 0x50000000, 0x040007e6, 0x0401f00d, - 0x82040580, 0x00000023, 0x0402000a, 0x0401ff57, - 0x04000008, 0x59300c03, 0x82040580, 0x00000002, - 0x04000006, 0x82040580, 0x00000051, 0x04000003, - 0x80000580, 0x0401f003, 0x82000540, 0x00000001, - 0x1c01f000, 0x59cc0006, 0x82000500, 0xffff0000, - 0x82000d80, 0x03000000, 0x04000004, 0x82000d80, - 0x52000000, 0x040207f3, 0x59a80026, 0x82000500, - 0x00000009, 0x82000580, 0x00000008, 0x040007ef, - 0x0401f7ec, 0x4803c856, 0x4c5c0000, 0x4c580000, - 0x59a80016, 0x82000580, 0x0000004c, 0x0402001f, - 0x59ccb807, 0x9c5cb9c0, 0x825cbd00, 0x00000007, - 0x8c5cbd00, 0x0400000a, 0x4200b000, 0x00000002, - 0x83a81c00, 0x00000002, 0x83cc1400, 0x0000000d, - 0x0201f800, 0x001082ff, 0x04020010, 0x8c5cbd02, - 0x0400000a, 0x4200b000, 0x00000002, 0x83a81c00, - 0x00000000, 0x83cc1400, 0x0000000f, 0x0201f800, - 0x001082ff, 0x04020005, 0x8c5cbd04, 0x04000003, - 0x82000540, 0x00000001, 0x5c00b000, 0x5c00b800, - 0x1c01f000, 0x4803c856, 0x4c5c0000, 0x4c580000, - 0x59a80016, 0x82000580, 0x0000004c, 0x0402001f, - 0x59ccb807, 0x9c5cb9c0, 0x825cbd00, 0x00000007, - 0x8c5cbd00, 0x0400000a, 0x4200b000, 0x00000002, - 0x83a81c00, 0x00000002, 0x83cc1400, 0x00000009, - 0x0201f800, 0x001082ff, 0x04020010, 0x8c5cbd02, - 0x0400000a, 0x4200b000, 0x00000002, 0x83a81c00, - 0x00000000, 0x83cc1400, 0x0000000b, 0x0201f800, - 0x001082ff, 0x04020005, 0x8c5cbd04, 0x04000003, - 0x82000540, 0x00000001, 0x5c00b000, 0x5c00b800, - 0x1c01f000, 0x4803c857, 0x4c580000, 0x40003000, - 0x42002000, 0x000007f0, 0x4200b000, 0x00000010, - 0x83ac7400, 0x000007f0, 0x50380000, 0x80026d40, - 0x04000006, 0x59340002, 0x82000500, 0x00ffffff, - 0x80180580, 0x04000010, 0x80102000, 0x80387000, - 0x8058b040, 0x040207f5, 0x82100480, 0x00000800, - 0x42002000, 0x00000000, 0x4200b000, 0x000007f0, - 0x41ac7000, 0x040217ed, 0x82000540, 0x00000001, - 0x0401f002, 0x40128800, 0x5c00b000, 0x1c01f000, - 0x59a80026, 0x8c00050e, 0x04000004, 0x8c000502, - 0x04000003, 0x80000580, 0x1c01f000, 0x82000540, - 0x00000001, 0x0401f7fd, 0x59300c06, 0x82040580, - 0x00000002, 0x04000006, 0x82040580, 0x00000005, - 0x04000003, 0x82000540, 0x00000001, 0x1c01f000, - 0x59c80000, 0x84000558, 0x84000512, 0x48039000, - 0x1c01f000, 0x4a03281a, 0x000003e8, 0x4a032802, - 0x0010cfc0, 0x4a032800, 0x00000000, 0x4a032808, - 0x00106d9f, 0x42000000, 0x00000005, 0x83947c00, - 0x00000009, 0x49787801, 0x4a007802, 0x00106d54, - 0x823c7c00, 0x00000003, 0x80000040, 0x040207fa, - 0x4a032819, 0xffff0000, 0x4201d000, 0x00000064, - 0x0401f97c, 0x4201d000, 0x000186a0, 0x0401f18b, - 0x00000000, 0x00000003, 0x00000006, 0x00000009, - 0x0000000c, 0x4d300000, 0x4d2c0000, 0x4d340000, - 0x4d400000, 0x4cfc0000, 0x4d380000, 0x4d3c0000, - 0x4d440000, 0x4d4c0000, 0x4d480000, 0x4c5c0000, - 0x4c600000, 0x4c640000, 0x4cc80000, 0x4ccc0000, - 0x0201f800, 0x000206af, 0x5c019800, 0x5c019000, - 0x5c00c800, 0x5c00c000, 0x5c00b800, 0x5c029000, - 0x5c029800, 0x5c028800, 0x5c027800, 0x5c027000, - 0x5c01f800, 0x5c028000, 0x5c026800, 0x5c025800, - 0x5c026000, 0x1c01f000, 0x59940004, 0x80000540, - 0x0402000a, 0x59940025, 0x80040400, 0x02001800, - 0x00100615, 0x48032804, 0x480b2805, 0x4a032803, - 0x0000000a, 0x80000580, 0x1c01f000, 0x5994001f, - 0x80000540, 0x0402000a, 0x59940025, 0x80040400, - 0x02001800, 0x00100615, 0x4803281f, 0x480b2820, - 0x4a03281e, 0x00000001, 0x80000580, 0x1c01f000, - 0x59940022, 0x80000540, 0x0402000a, 0x59940025, - 0x80040400, 0x02001800, 0x00100615, 0x48032822, - 0x480b2823, 0x4a032821, 0x0000000a, 0x80000580, - 0x1c01f000, 0x4c000000, 0x59940005, 0x4803c857, - 0x480bc857, 0x80080580, 0x04020003, 0x497b2804, - 0x497b2805, 0x5c000000, 0x1c01f000, 0x4c000000, - 0x59940020, 0x4803c857, 0x480bc857, 0x80080580, - 0x04020003, 0x497b281f, 0x497b2820, 0x5c000000, - 0x1c01f000, 0x4c000000, 0x59940023, 0x4803c857, - 0x480bc857, 0x80080580, 0x04020003, 0x497b2822, - 0x497b2823, 0x5c000000, 0x1c01f000, 0x4937c857, - 0x48ebc857, 0x59340203, 0x80e80480, 0x04001002, - 0x48ea6a03, 0x1c01f000, 0x5c03e000, 0x1c01f000, - 0x4d440000, 0x42007800, 0x00000010, 0x59968801, - 0x0201f800, 0x00020267, 0x04020012, 0x59341a03, - 0x800c1840, 0x0400100f, 0x59940027, 0x800c0480, - 0x04000003, 0x48026a03, 0x0402100a, 0x5934000f, - 0x497a6a03, 0x80000540, 0x04000006, 0x4c3c0000, - 0x5934140b, 0x0201f800, 0x00020275, 0x5c007800, - 0x81468800, 0x83440480, 0x00000800, 0x04021007, - 0x803c7840, 0x040207e7, 0x49472801, 0x5c028800, - 0x5c03e000, 0x1c01f000, 0x4a032800, 0x00000002, - 0x497b2801, 0x0401f7fa, 0x42007800, 0x00000010, - 0x59966002, 0x59300205, 0x80000d40, 0x04000006, - 0x59940027, 0x80040480, 0x48026205, 0x0400102d, - 0x0400002c, 0x59300206, 0x80000d40, 0x04000014, - 0x59b800e4, 0x8c000524, 0x04020011, 0x4a0370e4, - 0x00030000, 0x40000000, 0x59b800e4, 0x8c000524, - 0x04000004, 0x4a0370e4, 0x00020000, 0x0401f008, - 0x59940027, 0x80040480, 0x48026206, 0x4a0370e4, - 0x00020000, 0x0400101c, 0x0400001b, 0x83326400, - 0x00000024, 0x49332802, 0x41540000, 0x81300480, - 0x04021005, 0x803c7840, 0x040207db, 0x5c03e000, - 0x1c01f000, 0x59940026, 0x48032827, 0x4a032802, - 0x0010cfc0, 0x497b2826, 0x80000540, 0x0400000f, - 0x4a032800, 0x00000001, 0x5c03e000, 0x1c01f000, - 0x4c3c0000, 0x0201f800, 0x00108f92, 0x5c007800, - 0x0401f7d1, 0x4c3c0000, 0x0201f800, 0x00108b11, - 0x5c007800, 0x0401f7e2, 0x4a032800, 0x00000000, - 0x5c03e000, 0x1c01f000, 0x59a8086b, 0x8c040d30, - 0x04020029, 0x8c040d32, 0x0400000f, 0x59a80069, - 0x81640480, 0x04001019, 0x59a8000b, 0x81500580, - 0x04000005, 0x59a8006a, 0x59a81066, 0x80080580, - 0x04020012, 0x900411c0, 0x82081500, 0x00007000, - 0x0401f012, 0x82040500, 0x0000001f, 0x04000016, - 0x80040840, 0x82040500, 0x0000001f, 0x04000003, - 0x4807506b, 0x0401f010, 0x900401c0, 0x82000500, - 0x0000001f, 0x80040d40, 0x900401c0, 0x80040580, - 0x82001500, 0x00007000, 0x82040500, 0xffff8fff, - 0x80080540, 0x4803506b, 0x80081114, 0x0201f800, - 0x00100728, 0x1c01f000, 0x4a032807, 0x000007d0, - 0x4a032806, 0x0000000a, 0x1c01f000, 0x42000800, - 0x000007d0, 0x83180480, 0x00000005, 0x02021800, - 0x00100615, 0x83947c00, 0x00000009, 0x83180400, - 0x00105c7c, 0x50000000, 0x803c7c00, 0x48047801, - 0x4a007800, 0x0000000a, 0x1c01f000, 0x83180480, - 0x00000005, 0x02021800, 0x00100615, 0x83947c00, - 0x00000009, 0x83180400, 0x00105c7c, 0x50000000, - 0x803c7c00, 0x49787801, 0x1c01f000, 0x4807c857, - 0x480bc857, 0x59940025, 0x80040400, 0x02001800, - 0x00100615, 0x48032804, 0x480b2805, 0x4a032803, - 0x0000000a, 0x1c01f000, 0x4807c857, 0x480bc857, - 0x59940025, 0x80040400, 0x02001800, 0x00100615, - 0x4803281c, 0x480b281d, 0x4a03281b, 0x0000000a, - 0x1c01f000, 0x4c000000, 0x5994001d, 0x4803c857, - 0x480bc857, 0x80080580, 0x04020003, 0x4803281c, - 0x4803281d, 0x5c000000, 0x1c01f000, 0x4807c857, - 0x480bc857, 0x59940025, 0x80040400, 0x02001800, - 0x00100615, 0x48032822, 0x480b2823, 0x4a032821, - 0x0000000a, 0x1c01f000, 0x80e9d1c0, 0x0400000e, - 0x0401f832, 0x04025000, 0x4203e000, 0x80000000, - 0x40e81000, 0x41780800, 0x42000000, 0x00000064, - 0x0201f800, 0x001063ee, 0x59940024, 0x80080400, - 0x48032824, 0x1c01f000, 0x42001000, 0x00104d39, - 0x0401fee5, 0x42001000, 0x00104d2c, 0x0401ffd6, - 0x42001000, 0x00103f62, 0x0401fedf, 0x42001000, - 0x00103fe4, 0x0401fedc, 0x42001000, 0x00103f37, - 0x0401fed9, 0x42001000, 0x0010401b, 0x0401f6ea, - 0x4203e000, 0x70000000, 0x4203e000, 0xb0300000, - 0x40ebf800, 0x42000000, 0x0000003c, 0x04004004, - 0x80000040, 0x040207fe, 0x0401f007, 0x4203e000, - 0x70000000, 0x42000000, 0x0010b67d, 0x0201f800, - 0x0010a86e, 0x1c01f000, 0x4203e000, 0x80000000, - 0x4203e000, 0xb0400000, 0x40ebf800, 0x42000000, - 0x0000003c, 0x04005004, 0x80000040, 0x040207fe, - 0x0401f007, 0x4203e000, 0x80000000, 0x42000000, - 0x0010b67e, 0x0201f800, 0x0010a86e, 0x1c01f000, - 0x59a8000e, 0x82000480, 0x00000100, 0x599c0a02, - 0x800409c0, 0x04020002, 0x80040800, 0x80041480, - 0x04001002, 0x40000800, 0x48075067, 0x59a8100e, - 0x40040000, 0x800acc80, 0x4967500e, 0x49675069, - 0x59aaa80b, 0x41640800, 0x42001000, 0x00000024, - 0x0201f800, 0x001063cf, 0x8206a400, 0x0010cfc0, - 0x49535065, 0x4152b000, 0x42006000, 0x0010bc64, - 0x4a006004, 0x0000012c, 0x4a006005, 0xda10da10, - 0x4a006008, 0x00000011, 0x4a006009, 0x0010bc64, - 0x4a00600a, 0x00101108, 0x599c0014, 0x48006011, - 0x599c0015, 0x48006012, 0x42006000, 0x0010bc40, - 0x4a006203, 0x00000008, 0x4a006406, 0x00000006, - 0x4a006002, 0xffff0000, 0x4a006008, 0x0010bc64, - 0x4a006014, 0x0010bc64, 0x599c0014, 0x48006015, - 0x599c0015, 0x48006016, 0x599c0413, 0x48006017, - 0x49506018, 0x49546019, 0x59a80067, 0x4800601a, - 0x4a00601b, 0x0010b265, 0x4a00601c, 0x0010b266, - 0x4a00601d, 0x0010b26a, 0x42000000, 0xb0000000, - 0x42000800, 0x0010bc40, 0x0201f800, 0x00100bb2, - 0x1c01f000, 0x82000d00, 0x000000c0, 0x04000004, - 0x82040d80, 0x000000c0, 0x04020055, 0x82000d00, - 0x00002020, 0x59300414, 0x84000512, 0x82040d80, - 0x00002020, 0x0400000b, 0x8c000514, 0x0402000f, - 0x48026414, 0x813e79c0, 0x02020000, 0x00020804, - 0x42027000, 0x00000043, 0x0201f000, 0x000208d8, - 0x59326809, 0x59340a00, 0x8c040d0a, 0x040007f3, - 0x84000552, 0x0401f7f1, 0x84000514, 0x592c080d, - 0x48066015, 0x0401f7ef, 0x59326809, 0x59340a00, - 0x8c040d0a, 0x02000000, 0x00020817, 0x59300c14, - 0x84040d52, 0x48066414, 0x0201f000, 0x00020817, - 0x0201f800, 0x00020087, 0x813e79c0, 0x02020000, - 0x00020804, 0x0201f000, 0x00020825, 0x8c00051e, - 0x02000000, 0x00020831, 0x82000d00, 0x00002020, - 0x82040d80, 0x00002020, 0x04000014, 0x82000500, - 0x000000c0, 0x82000d80, 0x00000080, 0x04000008, - 0x813e79c0, 0x02020000, 0x00020804, 0x42027000, - 0x00000041, 0x0201f000, 0x000208d8, 0x813e79c0, - 0x02020000, 0x00020804, 0x42027000, 0x00000043, - 0x0201f000, 0x000208d8, 0x59326809, 0x59340a00, - 0x8c040d0a, 0x040007ea, 0x59300c14, 0x84040d52, - 0x48066414, 0x0401f7e6, 0x492fc857, 0x42000800, - 0x00000006, 0x0201f000, 0x0002082c, 0x492fc857, - 0x42000800, 0x00000004, 0x0201f000, 0x0002082c, - 0x4807c856, 0x59a80068, 0x800409c0, 0x04000003, - 0x80080540, 0x0401f002, 0x80080500, 0x48035068, - 0x1c01f000, 0x4a030800, 0x00000000, 0x4a030802, - 0x00000001, 0x497b0803, 0x497b0804, 0x1c01f000, - 0x59840002, 0x8c000500, 0x04000004, 0x84000500, - 0x4a030800, 0x00000001, 0x84000544, 0x84000506, - 0x48030802, 0x82000d00, 0x0fffffff, 0x42000000, - 0x90000000, 0x0201f800, 0x00100bde, 0x59a80069, - 0x82000480, 0x00000007, 0x48035069, 0x80000580, - 0x42000800, 0x0010b315, 0x48000800, 0x48000801, - 0x1c01f000, 0x59a80069, 0x82000400, 0x00000007, - 0x48035069, 0x1c01f000, 0x83640480, 0x00000008, - 0x0400101b, 0x58c80a03, 0x80000580, 0x82000400, - 0x00000008, 0x80040840, 0x040207fd, 0x815c0480, - 0x04001013, 0x4200b000, 0x00000007, 0x0201f800, - 0x00020892, 0x4a026203, 0x00000004, 0x4a026406, - 0x00000009, 0x4a026203, 0x00000004, 0x4a026007, - 0x00000101, 0x0401f809, 0x0401f880, 0x8058b040, - 0x040207f3, 0x80000580, 0x1c01f000, 0x82000540, - 0x00000001, 0x0401f7fd, 0x0201f800, 0x0010082a, - 0x492e6008, 0x58c80a03, 0x4a025a04, 0x0000002c, - 0x497a5800, 0x497a5801, 0x497a5c04, 0x497a5c06, - 0x497a5805, 0x4a025a08, 0x00000005, 0x4a025a07, - 0x00000002, 0x58c80201, 0x48025c04, 0x58c80202, - 0x48025c07, 0x58c80204, 0x48025c08, 0x4a02580d, - 0x0000ffff, 0x80040840, 0x0400000c, 0x412c2000, - 0x0201f800, 0x0010082a, 0x4a025a04, 0x0000000a, - 0x497a5c04, 0x48125800, 0x492c2001, 0x412c2000, - 0x80040840, 0x040207f7, 0x1c01f000, 0x4d7c0000, - 0x4202f800, 0x00000010, 0x4df00000, 0x4203e000, - 0x50000000, 0x59847803, 0x803c79c0, 0x0400001e, - 0x4c5c0000, 0x583cb808, 0x585c3408, 0x801831c0, - 0x0400000b, 0x0401f84a, 0x04000016, 0x42001000, - 0x0010b315, 0x0401f87f, 0x04000012, 0x0201f800, - 0x00100819, 0x0400000f, 0x492cb805, 0x585c0005, - 0x80000540, 0x02000800, 0x00100615, 0x0401f830, - 0x585c5408, 0x0401f80b, 0x5c00b800, 0x5c03e000, - 0x817ef840, 0x040207e1, 0x5c02f800, 0x1c01f000, - 0x5c00b800, 0x5c03e000, 0x5c02f800, 0x1c01f000, - 0x4803c856, 0x405c6000, 0x802851c0, 0x04000018, - 0x585c0204, 0x82000d00, 0x0000000f, 0x82040c00, - 0x0010110d, 0x50044000, 0x4c600000, 0x4c640000, - 0x4d040000, 0x4020c000, 0x40320800, 0x5984c804, - 0x4c280000, 0x0401f934, 0x5c005000, 0x40604000, - 0x41046000, 0x0201f800, 0x001010eb, 0x040207f6, - 0x5c020800, 0x5c00c800, 0x5c00c000, 0x58c80204, - 0x4800bc08, 0x0201f800, 0x00020087, 0x4a026007, - 0x00000101, 0x497a6009, 0x0401f055, 0x4803c856, - 0x59840003, 0x80026540, 0x04000003, 0x59300000, - 0x48030803, 0x1c01f000, 0x4803c856, 0x59840003, - 0x48026000, 0x49330803, 0x1c01f000, 0x58cc0805, - 0x40180000, 0x80040480, 0x0400100d, 0x82cc0580, - 0x0010b30a, 0x02020800, 0x00100615, 0x58c80205, - 0x80040480, 0x0400101d, 0x82000540, 0x00000001, - 0x1c01f000, 0x80003580, 0x0401f7fe, 0x82cc0580, - 0x0010b30a, 0x02020800, 0x00100615, 0x58c80400, - 0x8c000504, 0x040007f8, 0x58c8040b, 0x8c00051e, - 0x040007f5, 0x8c000500, 0x040207f3, 0x84000540, - 0x4801940b, 0x42000000, 0x0010b637, 0x0201f800, - 0x0010a86e, 0x42001000, 0x00008026, 0x0201f800, - 0x00103857, 0x0401f7e8, 0x58c8040b, 0x8c00051e, - 0x040007e2, 0x8c000502, 0x040207e0, 0x84000542, - 0x4801940b, 0x42000000, 0x0010b636, 0x0201f800, - 0x0010a86e, 0x42001000, 0x00008025, 0x42001800, - 0x00000000, 0x0201f800, 0x00103857, 0x0401f7d3, - 0x4803c856, 0x58080000, 0x42001800, 0x00000007, - 0x58080801, 0x80040480, 0x04020004, 0x400c0000, - 0x80000540, 0x0401f005, 0x04001003, 0x800c0480, - 0x0401f002, 0x80000080, 0x1c01f000, 0x4803c856, - 0x59300008, 0x80000d40, 0x02000800, 0x00100615, - 0x58040005, 0x80000540, 0x02000800, 0x00100615, - 0x59300007, 0x82000500, 0x00000101, 0x82000580, - 0x00000101, 0x02020800, 0x00100615, 0x42001000, - 0x0010b315, 0x58080801, 0x82040400, 0x0010b317, - 0x497a6414, 0x4a026015, 0x0000ffff, 0x45300000, - 0x80040800, 0x82040480, 0x00000008, 0x04001002, - 0x80000d80, 0x48041001, 0x82040400, 0x0010b317, - 0x45780000, 0x1c01f000, 0x4933c857, 0x59300808, - 0x800409c0, 0x02000800, 0x00100615, 0x4d2c0000, - 0x58065805, 0x812e59c0, 0x02020800, 0x0010083a, - 0x49780805, 0x40065800, 0x0201f800, 0x00100843, - 0x5c025800, 0x4d300000, 0x0201f800, 0x000208b4, - 0x5c026000, 0x1c01f000, 0x59300406, 0x82000580, - 0x00000009, 0x04020006, 0x59300007, 0x8c000510, - 0x04000003, 0x80000580, 0x1c01f000, 0x82000540, - 0x00000001, 0x1c01f000, 0x59840802, 0x8c040d04, - 0x1c01f000, 0x4803c856, 0x59840802, 0x84040d04, - 0x84040d40, 0x4a030800, 0x00000000, 0x48070802, - 0x82040d00, 0x0fffffff, 0x42000000, 0x90000000, - 0x0201f000, 0x00100bde, 0x4807c857, 0x4805980a, - 0x49799801, 0x49799803, 0x49799806, 0x49799807, - 0x49799808, 0x49799805, 0x49799809, 0x0401f8c8, - 0x0400000a, 0x0401f8ea, 0x04000008, 0x48359800, - 0x48359802, 0x48359806, 0x4a019804, 0x00000001, - 0x4a019807, 0x00000005, 0x1c01f000, 0x4807c857, - 0x58cc1007, 0x40040000, 0x80080480, 0x04021020, - 0x4c040000, 0x4c080000, 0x0401f8d9, 0x5c001000, - 0x5c000800, 0x0400001c, 0x58cc0006, 0x80006540, - 0x0402000b, 0x48359800, 0x48359802, 0x48359806, - 0x49799801, 0x49799803, 0x49786801, 0x49786800, - 0x49799804, 0x49799807, 0x0401f005, 0x48306801, - 0x48346000, 0x48359806, 0x49786800, 0x58cc0004, - 0x58cc1007, 0x80000000, 0x82081400, 0x00000005, - 0x48019804, 0x48099807, 0x0401f7df, 0x80000580, - 0x1c01f000, 0x82000540, 0x00000001, 0x1c01f000, - 0x480bc857, 0x4c500000, 0x4c540000, 0x4c580000, - 0x40083000, 0x58cc0801, 0x82040480, 0x00000005, - 0x02021800, 0x00100615, 0x82040400, 0x00106150, - 0x50000000, 0x58cca800, 0x8054ac00, 0x42001800, - 0x00000005, 0x40040000, 0x800c0480, 0x80082480, - 0x04021002, 0x40080000, 0x8000b0c2, 0x8058b400, - 0x5450a800, 0x8050a000, 0x8054a800, 0x8058b040, - 0x040207fc, 0x40001000, 0x58cc2805, 0x58cc0807, - 0x58cc2001, 0x80142c00, 0x80040c80, 0x80102400, - 0x48159805, 0x48059807, 0x48119801, 0x82100580, - 0x00000005, 0x0400000c, 0x48119801, 0x40080000, - 0x80181480, 0x40083000, 0x04000003, 0x040217d6, - 0x80000580, 0x5c00b000, 0x5c00a800, 0x5c00a000, - 0x1c01f000, 0x58cc0800, 0x800409c0, 0x02000800, - 0x00100615, 0x58040800, 0x48059800, 0x41782000, - 0x0401f7ee, 0x0401f812, 0x50600000, 0x81041c00, - 0x585c0204, 0x4803c857, 0x82000580, 0x0000002c, - 0x02020800, 0x00100615, 0x58040202, 0x800000e0, - 0x80640540, 0x48001802, 0x58040000, 0x48001800, - 0x58040001, 0x48001801, 0x1c01f000, 0x4807c856, - 0x58cc0005, 0x80000040, 0x02001800, 0x00100615, - 0x48019805, 0x58cc1003, 0x82080480, 0x00000005, - 0x02021800, 0x00100615, 0x82080400, 0x00106150, - 0x50000000, 0x58cc0802, 0x80040c00, 0x80081000, - 0x82080480, 0x00000005, 0x0402000f, 0x58cc2002, - 0x58100000, 0x80006d40, 0x04000009, 0x4c340000, - 0x0401f858, 0x5c006800, 0x49786801, 0x48359802, - 0x58cc0004, 0x80000040, 0x48019804, 0x49799803, - 0x0401f002, 0x48099803, 0x1c01f000, 0x4807c856, - 0x41781800, 0x58c80201, 0x80000540, 0x04000002, - 0x800c1800, 0x58c80c01, 0x80040c80, 0x0400100a, - 0x04000009, 0x800c1800, 0x58c80202, 0x80041480, - 0x04001005, 0x04000004, 0x800c1800, 0x40080800, - 0x0401f7fb, 0x480d9204, 0x400c0000, 0x42002000, - 0x00000001, 0x80000040, 0x04000007, 0x04001006, - 0x80102000, 0x82000480, 0x00000005, 0x04000002, - 0x040217fc, 0x48119203, 0x1c01f000, 0x4807c856, - 0x4d2c0000, 0x58cc000a, 0x80000540, 0x02000800, - 0x00100615, 0x82002400, 0x00000005, 0x0201f800, - 0x00100819, 0x04000012, 0x492d9809, 0x497a5800, - 0x497a5801, 0x0201f800, 0x00100819, 0x0400000c, - 0x58cc0009, 0x48025800, 0x497a5801, 0x492d9809, - 0x82102480, 0x00000005, 0x040217f7, 0x82000540, - 0x00000001, 0x5c025800, 0x1c01f000, 0x58cc0009, - 0x80025d40, 0x040007fc, 0x592c2000, 0x0201f800, - 0x0010083a, 0x40100000, 0x0401f7fa, 0x58cc0009, - 0x48cfc857, 0x80006d40, 0x04000005, 0x50340000, - 0x48019809, 0x49786800, 0x49786801, 0x1c01f000, - 0x4813c857, 0x58cc0009, 0x48002000, 0x48119809, - 0x1c01f000, 0x4807c856, 0x4d2c0000, 0x58cc0009, - 0x80025d40, 0x04000007, 0x592c0000, 0x4c000000, - 0x0201f800, 0x0010083a, 0x5c000000, 0x0401f7f9, - 0x5c025800, 0x1c01f000, 0x4807c856, 0x4d2c0000, - 0x58cc0002, 0x80025d40, 0x04000007, 0x592c0000, - 0x4c000000, 0x0201f800, 0x0010083a, 0x5c000000, - 0x0401f7f9, 0x49799800, 0x49799802, 0x49799801, - 0x49799803, 0x49799806, 0x49799807, 0x49799808, - 0x49799809, 0x4979980a, 0x5c025800, 0x1c01f000, - 0x00000003, 0x00000006, 0x00000009, 0x0000000c, - 0x0000000f, 0x00000012, 0x4803c856, 0x0401f857, - 0x4a00c204, 0x0000003c, 0x59301009, 0x82080580, - 0x0010b320, 0x04000013, 0x58080802, 0x82040d00, - 0x00ffffff, 0x58080403, 0x4804c005, 0x4800c406, - 0x4a00c207, 0x00000003, 0x59300811, 0x585c0404, - 0x4978c206, 0x4804c407, 0x80000540, 0x0400000d, - 0x58600206, 0x84000540, 0x4800c206, 0x0401f009, - 0x585c080a, 0x82040d00, 0x00ffffff, 0x4804c005, - 0x4a00c406, 0x000007ff, 0x4978c207, 0x0401f7ef, - 0x82603c00, 0x00000008, 0x58605404, 0x40282000, - 0x405c6000, 0x585c0a04, 0x82040d00, 0x0000000f, - 0x82040c00, 0x0010110d, 0x50044000, 0x80004d80, - 0x50200000, 0x80307400, 0x58380402, 0x8c244d00, - 0x04020003, 0x48003a00, 0x0401f003, 0x48003c00, - 0x801c3800, 0x80244800, 0x80102040, 0x04000006, - 0x0201f800, 0x001010eb, 0x02000800, 0x00100615, - 0x0401f7f0, 0x1c01f000, 0x4803c856, 0x4d340000, - 0x59300009, 0x80026d40, 0x02000800, 0x00100615, - 0x59340401, 0x80000540, 0x0400000e, 0x59840000, - 0x80000540, 0x0400000b, 0x836c0580, 0x00000003, - 0x04020008, 0x59341c03, 0x42002000, 0x00000004, - 0x42003000, 0x00000004, 0x0201f800, 0x001038c7, - 0x5c026800, 0x1c01f000, 0x4803c856, 0x80001580, - 0x58c80c01, 0x59300011, 0x80040c80, 0x48066011, - 0x58c80201, 0x80000540, 0x04000005, 0x80081000, - 0x80040c80, 0x04001007, 0x04000006, 0x58c80202, - 0x80081000, 0x80040c80, 0x04001002, 0x040207fd, - 0x4808bc08, 0x4808c404, 0x1c01f000, 0x4803c856, - 0x4a0370e5, 0x00020000, 0x59b800e5, 0x8c000524, - 0x040207fc, 0x4a0370e5, 0x00030000, 0x40000000, - 0x40000000, 0x59b800e5, 0x8c000524, 0x040207f5, - 0x5934000e, 0x80006d40, 0x04000010, 0x81300580, - 0x04020004, 0x58340000, 0x4802680e, 0x0401f00a, - 0x40347800, 0x58340000, 0x80006d40, 0x02000800, - 0x00100615, 0x81300580, 0x040207fa, 0x58340000, - 0x48007800, 0x497a6000, 0x4a0370e5, 0x00020000, - 0x1c01f000, 0x4803c856, 0x4d300000, 0x4d2c0000, - 0x42000800, 0x000003ff, 0x4a0370e5, 0x00020000, - 0x59b800e5, 0x8c000524, 0x04000005, 0x80040840, - 0x040207fa, 0x0201f800, 0x00100615, 0x4a0370e5, - 0x00030000, 0x40000000, 0x40000000, 0x59b800e5, - 0x8c000524, 0x040207f1, 0x5934000e, 0x80026540, - 0x0400000e, 0x4933c857, 0x59300000, 0x4802680e, - 0x4a026203, 0x00000004, 0x497a6206, 0x497a6009, - 0x4a026007, 0x00000101, 0x59325808, 0x497a5c08, - 0x0401fd82, 0x0401f7f1, 0x4a0370e5, 0x00020000, - 0x5c025800, 0x5c026000, 0x1c01f000, 0x4803c856, - 0x4c000000, 0x0201f800, 0x001059b9, 0x04020011, - 0x0201f800, 0x001043fc, 0x02020800, 0x00100615, - 0x5c000000, 0x48026802, 0x0201f800, 0x00020892, - 0x04000009, 0x49366009, 0x4a026406, 0x00000001, - 0x42027000, 0x00000001, 0x0201f000, 0x000208d8, - 0x5c000000, 0x1c01f000, 0x59300203, 0x82000c80, - 0x0000000e, 0x02021800, 0x00100615, 0x4803c857, - 0x0c01f001, 0x0010623b, 0x0010623b, 0x0010623b, - 0x0010623d, 0x0010629d, 0x0010623b, 0x0010623b, - 0x001062ef, 0x001062f0, 0x0010623b, 0x0010623b, - 0x0010623b, 0x0010623b, 0x0010623b, 0x0201f800, - 0x00100615, 0x493bc857, 0x83380480, 0x00000050, - 0x02021800, 0x00100615, 0x83380480, 0x00000049, - 0x02001800, 0x00100615, 0x0c01f001, 0x00106250, - 0x00106272, 0x0010624e, 0x0010624e, 0x0010624e, - 0x0010624e, 0x00106281, 0x0201f800, 0x00100615, - 0x4d2c0000, 0x59325808, 0x592c0206, 0x48025c06, - 0x4a025a06, 0x00000000, 0x4c5c0000, 0x592cbc0a, - 0x592c0000, 0x48026008, 0x0201f800, 0x00020385, - 0x59300008, 0x80000540, 0x04000008, 0x4a026203, - 0x00000007, 0x42027000, 0x00000043, 0x5c00b800, - 0x5c025800, 0x0401f08a, 0x8c5cbd08, 0x04020006, - 0x4a026203, 0x00000007, 0x497a6206, 0x497a6008, - 0x0401f003, 0x0201f800, 0x000208b4, 0x5c00b800, - 0x5c025800, 0x1c01f000, 0x0201f800, 0x001068c1, - 0x4d2c0000, 0x59325808, 0x0201f800, 0x00108df4, - 0x04000006, 0x4d400000, 0x42028000, 0x00000001, - 0x0401f90e, 0x5c028000, 0x5c025800, 0x0201f000, - 0x000208b4, 0x0201f800, 0x001068c1, 0x4d3c0000, - 0x417a7800, 0x0201f800, 0x00101de2, 0x5c027800, - 0x42003000, 0x00000014, 0x0201f800, 0x0010a766, - 0x42000000, 0x0010b663, 0x0201f800, 0x0010a86e, - 0x4d2c0000, 0x59325808, 0x0201f800, 0x00108df4, - 0x04000006, 0x4d400000, 0x42028000, 0x00000029, - 0x0401f8f2, 0x5c028000, 0x5c025800, 0x0201f000, - 0x000208b4, 0x493bc857, 0x497a6206, 0x83380480, - 0x00000054, 0x02021800, 0x00100615, 0x83380480, - 0x00000047, 0x02001800, 0x00100615, 0x0c01f001, - 0x001062ee, 0x001062b7, 0x001062b5, 0x001062b5, - 0x001062b5, 0x001062b5, 0x001062b5, 0x001062b5, - 0x001062b5, 0x001062b5, 0x001062b5, 0x001062b5, - 0x001062bb, 0x0201f800, 0x00100615, 0x59300011, - 0x82000500, 0xffff0000, 0x04020034, 0x59840802, - 0x8c040d04, 0x04000025, 0x59300009, 0x80026d40, - 0x0400001f, 0x4c5c0000, 0x4c600000, 0x497a6206, - 0x5930b808, 0x585c0005, 0x8000c540, 0x02000800, - 0x00100615, 0x0401fe8d, 0x40625800, 0x0201f800, - 0x00020385, 0x4978b805, 0x0401fef5, 0x497a6009, - 0x585c3408, 0x0401fcbe, 0x0400000e, 0x42001000, - 0x0010b315, 0x0401fcf3, 0x0400000a, 0x0201f800, - 0x0010082a, 0x04000007, 0x492cb805, 0x585c5408, - 0x0401fc84, 0x5c00c000, 0x5c00b800, 0x1c01f000, - 0x0401fcaa, 0x0401f7fc, 0x8c040d06, 0x040207fc, - 0x59300009, 0x80026d40, 0x04000006, 0x5934000e, - 0x80000540, 0x02020800, 0x00100615, 0x497a6009, - 0x0401fd0e, 0x0401f7f2, 0x0401f085, 0x4803c856, - 0x4803c856, 0x83380580, 0x00000043, 0x02020800, - 0x00100615, 0x4a026203, 0x00000003, 0x493a6403, - 0x59325808, 0x592c000f, 0x48026011, 0x497a6013, - 0x592c0406, 0x800000c2, 0x800010c4, 0x80081400, - 0x480a6206, 0x0201f800, 0x00100f9c, 0x42000800, - 0x80000060, 0x0401f161, 0x42000000, 0x0010b674, - 0x0201f800, 0x0010a86e, 0x59300203, 0x82000c80, - 0x0000000e, 0x02021800, 0x00100615, 0x4803c857, - 0x82000d80, 0x00000003, 0x04000006, 0x82000d80, - 0x00000004, 0x0400005b, 0x0201f800, 0x00100615, - 0x0201f800, 0x0010698c, 0x59300004, 0x8c00053e, - 0x04020007, 0x0201f800, 0x001068a3, 0x02020800, - 0x00100615, 0x0201f000, 0x00106982, 0x0401f9d3, - 0x0201f800, 0x00106982, 0x59325808, 0x42028000, - 0x00000006, 0x0401f861, 0x0201f000, 0x000208b4, - 0x4803c856, 0x59300203, 0x82000c80, 0x0000000e, - 0x02021800, 0x00100615, 0x82000d80, 0x00000002, - 0x04000009, 0x82000d80, 0x00000003, 0x04000019, - 0x82000d80, 0x00000004, 0x04000036, 0x0201f800, - 0x00100615, 0x4933c857, 0x4d2c0000, 0x59325808, - 0x812e59c0, 0x02000800, 0x00100615, 0x592c1a08, - 0x8c0c1d0e, 0x02000800, 0x00100615, 0x4d400000, - 0x42028000, 0x00000001, 0x0401f840, 0x0201f800, - 0x00107698, 0x5c028000, 0x5c025800, 0x1c01f000, - 0x4933c857, 0x0201f800, 0x0010698c, 0x4df00000, - 0x59300004, 0x8c00053e, 0x04020006, 0x0201f800, - 0x00106cb4, 0x02020800, 0x00100615, 0x0401f010, - 0x0201f800, 0x00108a8a, 0x04020004, 0x0201f800, - 0x00106bb2, 0x0402000a, 0x0401f994, 0x02020800, - 0x00100615, 0x5c03e000, 0x02000800, 0x00106982, - 0x82000540, 0x00000001, 0x1c01f000, 0x5c03e000, - 0x02000800, 0x00106982, 0x80000580, 0x1c01f000, - 0x4933c857, 0x0201f800, 0x00100ee4, 0x4933c857, - 0x4c5c0000, 0x4d340000, 0x497a6206, 0x5930b808, - 0x59300009, 0x80026d40, 0x04020e49, 0x42001000, - 0x0010b315, 0x0401fc4b, 0x04000009, 0x58c80204, - 0x4800bc08, 0x41785000, 0x0201f800, 0x00105f60, - 0x5c026800, 0x5c00b800, 0x1c01f000, 0x4978bc08, - 0x0401fc02, 0x0401f7fb, 0x4803c856, 0x0201f800, - 0x00108df4, 0x0400000f, 0x592c0000, 0x80000d40, - 0x04000009, 0x497a5800, 0x49425a06, 0x4c040000, - 0x0201f800, 0x00020381, 0x5c000800, 0x40065800, - 0x0401f7f6, 0x49425a06, 0x0201f800, 0x00020381, - 0x1c01f000, 0x4933c857, 0x59300c06, 0x82040580, - 0x0000000e, 0x04000004, 0x82040580, 0x00000009, - 0x04020004, 0x0401ffe5, 0x497a6008, 0x80000580, - 0x1c01f000, 0x592e6009, 0x83300480, 0x0010cfc0, - 0x04001016, 0x41580000, 0x81300480, 0x04021013, - 0x40040000, 0x59300c06, 0x80040580, 0x04020012, - 0x59300a03, 0x82040580, 0x00000007, 0x02020800, - 0x00100615, 0x59300008, 0x80000540, 0x02020800, - 0x00100615, 0x0201f800, 0x000208b4, 0x42000000, - 0x00000000, 0x0401f009, 0x42000000, 0x00000008, - 0x0401f006, 0x82040580, 0x00000007, 0x040207fb, - 0x42000000, 0x00000005, 0x592c0a06, 0x48065c06, - 0x48025a06, 0x0201f000, 0x00020381, 0x4c0c0000, - 0x4c100000, 0x4c140000, 0x4c180000, 0x80001d80, - 0x80002580, 0x42003000, 0x00000020, 0x82040500, - 0x00000001, 0x04000003, 0x40080000, 0x800c1c00, - 0x400c2800, 0x800c1902, 0x80102102, 0x82140500, - 0x00000001, 0x04000003, 0x82102540, 0x80000000, - 0x80040902, 0x80183040, 0x040207f1, 0x40100800, - 0x400c0000, 0x5c003000, 0x5c002800, 0x5c002000, - 0x5c001800, 0x1c01f000, 0x4c580000, 0x4200b000, - 0x00000020, 0x80000540, 0x04000018, 0x80041c80, - 0x04021016, 0x800810c2, 0x80040982, 0x04001006, - 0x80041c80, 0x04021005, 0x8058b040, 0x040207fa, - 0x0401f006, 0x80041c80, 0x400c0800, 0x80081000, - 0x8058b040, 0x040207f4, 0x4c000000, 0x41f00000, - 0x82000500, 0xf7ffffff, 0x4003e000, 0x5c000000, - 0x5c00b000, 0x1c01f000, 0x4c000000, 0x41f00000, - 0x82000540, 0x08000000, 0x0401f7f8, 0x42007000, - 0x0010b33f, 0x4a007000, 0x00000005, 0x4a007401, - 0x00000000, 0x4a007202, 0x00000840, 0x4a0378e8, - 0x00000000, 0x4a03c821, 0x00000010, 0x4a03c823, - 0x00000004, 0x0401f81d, 0x4a0378e9, 0x00003a0d, - 0x4a0378e8, 0x00000001, 0x42000800, 0x00000005, - 0x4203a000, 0x00007600, 0x4a03a005, 0xd0000001, - 0x59d00006, 0x4a03a005, 0x90000001, 0x83d3a400, - 0x00000020, 0x80040840, 0x040207fa, 0x59e00003, - 0x82000500, 0xffffffe0, 0x82000540, 0x00008000, - 0x4803c003, 0x59c40006, 0x82000500, 0xfffcffff, - 0x48038806, 0x1c01f000, 0x4d900000, 0x4d180000, - 0x4a0378e7, 0xaaaaaaaa, 0x4a0378e6, 0xaaaaaaaa, - 0x4a0378e5, 0xaaaaaaaa, 0x4a0378e4, 0xaaaaaaaa, - 0x4a03781a, 0x0010b5d2, 0x4a03781b, 0x0010110d, - 0x4a03781c, 0x0010111d, 0x4a031800, 0x00000000, - 0x4a031801, 0x0010b342, 0x4a031802, 0x0010b349, - 0x42000800, 0x0010b5d5, 0x417a3000, 0x811b20c8, - 0x83932400, 0x0000bf32, 0x48072000, 0x4a032001, - 0x00000000, 0x83180400, 0x00106e41, 0x50000000, - 0x48032002, 0x82040c00, 0x00000003, 0x811a3000, - 0x83180480, 0x00000005, 0x040017f1, 0x5c023000, - 0x5c032000, 0x1c01f000, 0x48066004, 0x497a6000, - 0x497a6001, 0x59bc00ea, 0x8c000516, 0x040207fe, - 0x83300400, 0xa0000000, 0x480378e1, 0x1c01f000, - 0x4933c857, 0x59300804, 0x82040d00, 0x00000100, - 0x82040d40, 0x80000040, 0x48066004, 0x497a6000, - 0x59bc00ea, 0x8c000516, 0x040207fe, 0x83300400, - 0x60000000, 0x480378e1, 0x1c01f000, 0x0201f800, - 0x0010698c, 0x4df00000, 0x4d300000, 0x4d340000, - 0x4d2c0000, 0x4d180000, 0x4c5c0000, 0x4c600000, - 0x4d900000, 0x4dd00000, 0x4da40000, 0x4d140000, - 0x42003000, 0x0000bf2e, 0x581a6001, 0x813261c0, - 0x0400002c, 0x41302800, 0x4178c000, 0x59300000, - 0x4c000000, 0x59326809, 0x5930b801, 0x59300406, - 0x82000d80, 0x00000006, 0x04020003, 0x8d3e7d18, - 0x04000010, 0x8d3e7d06, 0x04000007, 0x82000580, - 0x00000003, 0x04020004, 0x59340200, 0x8c00050e, - 0x04020008, 0x0401f92d, 0x4c0c0000, 0x4c140000, - 0x0401fb59, 0x5c002800, 0x5c001800, 0x0401f005, - 0x41301800, 0x8060c1c0, 0x04020002, 0x400cc000, - 0x805cb9c0, 0x04000003, 0x405e6000, 0x0401f7e3, - 0x5c026000, 0x813261c0, 0x04000006, 0x8060c1c0, - 0x04000002, 0x40602800, 0x4178c000, 0x0401f7d8, - 0x417a3000, 0x0201f800, 0x00106e2f, 0x59926004, - 0x813261c0, 0x04000023, 0x59326809, 0x4130c000, - 0x59300001, 0x8000bd40, 0x04000016, 0x40026000, - 0x40602800, 0x5930b801, 0x59300406, 0x82000d80, - 0x00000006, 0x0400000e, 0x8d3e7d06, 0x04000007, - 0x82000580, 0x00000003, 0x04020004, 0x59340200, - 0x8c00050e, 0x04020006, 0x0401f8da, 0x4c140000, - 0x0401fb29, 0x5c002800, 0x0401f002, 0x41302800, - 0x405e6000, 0x813261c0, 0x040207eb, 0x8060c1c0, - 0x04000004, 0x40626000, 0x4178c000, 0x0401f7e7, - 0x811a3000, 0x83180480, 0x00000005, 0x040017d6, - 0x5c022800, 0x5c034800, 0x5c03a000, 0x5c032000, - 0x5c00c000, 0x5c00b800, 0x5c023000, 0x5c025800, - 0x5c026800, 0x5c026000, 0x5c03e000, 0x02000800, - 0x00106982, 0x1c01f000, 0x4933c857, 0x0201f800, - 0x0010698c, 0x4df00000, 0x4d340000, 0x4d180000, - 0x4d900000, 0x42003000, 0x0000bf2e, 0x59326809, - 0x58182001, 0x40102800, 0x801021c0, 0x04000016, - 0x41300000, 0x80100580, 0x04000011, 0x58100009, - 0x81340580, 0x0402000b, 0x40101800, 0x58102001, - 0x41300000, 0x801021c0, 0x0400000b, 0x80100d80, - 0x04000007, 0x40101800, 0x58102001, 0x0401f7fa, - 0x40102800, 0x58102000, 0x0401f7ec, 0x0401f8bb, - 0x0401f01a, 0x42032000, 0x0000bf32, 0x417a3000, - 0x59902004, 0x40102800, 0x801021c0, 0x0400000b, - 0x58100009, 0x81340580, 0x04020008, 0x41300000, - 0x80100580, 0x0400000c, 0x40102800, 0x58102001, - 0x801021c0, 0x040207fa, 0x811a3000, 0x83180480, - 0x00000005, 0x0402100d, 0x83932400, 0x00000010, - 0x0401f7ec, 0x0401f87f, 0x5c032000, 0x5c023000, - 0x5c026800, 0x5c03e000, 0x02000800, 0x00106982, - 0x80000580, 0x1c01f000, 0x5c032000, 0x5c023000, - 0x5c026800, 0x5c03e000, 0x02000800, 0x00106982, - 0x82000540, 0x00000001, 0x1c01f000, 0x0201f800, - 0x0010698c, 0x4df00000, 0x4d300000, 0x4d340000, - 0x4d180000, 0x4d2c0000, 0x4c5c0000, 0x4c600000, - 0x4d900000, 0x4dd00000, 0x4da40000, 0x4d140000, - 0x42003000, 0x0000bf2e, 0x581a6001, 0x813261c0, - 0x04000023, 0x41302800, 0x5930b800, 0x59326809, - 0x59340403, 0x81440580, 0x04000006, 0x805cb9c0, - 0x0400001b, 0x41302800, 0x405e6000, 0x0401f7f7, - 0x5930b801, 0x8d3e7d00, 0x04000003, 0x0401fb58, - 0x0402000e, 0x59300406, 0x82000580, 0x00000006, - 0x04020003, 0x8d3e7d18, 0x04000008, 0x0401f867, - 0x4c0c0000, 0x4c140000, 0x0401fa93, 0x5c002800, - 0x5c001800, 0x0401f002, 0x41301800, 0x405e6000, - 0x813261c0, 0x040207eb, 0x0401f02d, 0x417a3000, - 0x0201f800, 0x00106e2f, 0x59926004, 0x813261c0, - 0x04000005, 0x59326809, 0x59340403, 0x81440580, - 0x04000006, 0x811a3000, 0x83180480, 0x00000005, - 0x040017f4, 0x0401f01e, 0x4130c000, 0x59300001, - 0x8000bd40, 0x04000012, 0x40026000, 0x40602800, - 0x5930b801, 0x8d3e7d00, 0x04000003, 0x0401fb2c, - 0x0402000a, 0x59300406, 0x82000580, 0x00000006, - 0x04000006, 0x0401f81b, 0x4c140000, 0x0401fa6a, - 0x5c002800, 0x0401f002, 0x41302800, 0x405e6000, - 0x813261c0, 0x040207ef, 0x8060c1c0, 0x04000004, - 0x40626000, 0x4178c000, 0x0401f7eb, 0x5c022800, - 0x5c034800, 0x5c03a000, 0x5c032000, 0x5c00c000, - 0x5c00b800, 0x5c025800, 0x5c023000, 0x5c026800, - 0x5c026000, 0x5c03e000, 0x04000bd4, 0x1c01f000, - 0x0401fbb9, 0x59900004, 0x81300580, 0x04020018, - 0x4c140000, 0x0201f800, 0x00106b13, 0x0401fba9, - 0x5c002800, 0x59300001, 0x800001c0, 0x04020003, - 0x497a680c, 0x1c01f000, 0x42003000, 0x0000bf2e, - 0x497a6001, 0x58180801, 0x800409c0, 0x04020004, - 0x48003000, 0x48003001, 0x1c01f000, 0x58180800, - 0x48000800, 0x48003000, 0x1c01f000, 0x59300001, - 0x48002801, 0x800001c0, 0x04020002, 0x4816680c, - 0x497a6001, 0x1c01f000, 0x0401fb97, 0x42003000, - 0x0000bf2e, 0x58180001, 0x81300580, 0x0402001c, - 0x59300801, 0x800409c0, 0x0400000e, 0x59300000, - 0x800001c0, 0x04020005, 0x48043001, 0x48043000, - 0x497a6001, 0x1c01f000, 0x59300000, 0x48000800, - 0x48043001, 0x497a6000, 0x497a6001, 0x1c01f000, - 0x59300800, 0x800409c0, 0x04020005, 0x49783001, - 0x49783000, 0x497a680c, 0x1c01f000, 0x48043001, - 0x497a6000, 0x497a680c, 0x1c01f000, 0x58180000, - 0x81300580, 0x0402000c, 0x59300001, 0x800001c0, - 0x04020005, 0x48143000, 0x49782800, 0x497a680c, - 0x1c01f000, 0x48003000, 0x48002800, 0x497a6001, - 0x1c01f000, 0x59300000, 0x800001c0, 0x04020008, - 0x59300001, 0x48001801, 0x800001c0, 0x04020002, - 0x480e680c, 0x497a6001, 0x1c01f000, 0x59300801, - 0x800409c0, 0x04020006, 0x59300800, 0x48042800, - 0x497a6000, 0x497a680c, 0x1c01f000, 0x59300000, - 0x48000800, 0x48042800, 0x497a6000, 0x497a6001, - 0x1c01f000, 0x0401fb73, 0x4df00000, 0x0401f83a, - 0x040208c7, 0x0402094a, 0x04020005, 0x5c03e000, - 0x04000b62, 0x80000580, 0x1c01f000, 0x5c03e000, - 0x04000b5e, 0x82000540, 0x00000001, 0x1c01f000, - 0x4d2c0000, 0x4d340000, 0x4d300000, 0x41783000, - 0x598e6009, 0x813261c0, 0x04000023, 0x59300406, - 0x82000580, 0x00000006, 0x04020004, 0x8d3e7d18, - 0x0402000c, 0x0401f019, 0x82040580, 0x00000005, - 0x04020008, 0x8d3e7d18, 0x04000003, 0x8d3e7d16, - 0x04000004, 0x59300420, 0x8c000500, 0x0402000f, - 0x0401fa49, 0x59300000, 0x4c000000, 0x8d3e7d06, - 0x04000004, 0x0201f800, 0x0010909d, 0x04000005, - 0x0401f869, 0x4c180000, 0x0401f9b7, 0x5c003000, - 0x5c026000, 0x0401f7e0, 0x41303000, 0x59326000, - 0x0401f7dd, 0x5c026000, 0x5c026800, 0x5c025800, - 0x1c01f000, 0x4933c857, 0x4c5c0000, 0x813261c0, - 0x02000800, 0x00100615, 0x41300000, 0x598cb809, - 0x41783000, 0x805cb9c0, 0x04000013, 0x805c0d80, - 0x04000004, 0x405c3000, 0x5818b800, 0x0401f7fa, - 0x0401f84d, 0x598c000d, 0x81300580, 0x02000800, - 0x00106e10, 0x59300403, 0x82000580, 0x00000042, - 0x04020002, 0x497a6007, 0x80000580, 0x5c00b800, - 0x1c01f000, 0x82000540, 0x00000001, 0x5c00b800, - 0x1c01f000, 0x0401fb17, 0x4df00000, 0x4d2c0000, - 0x4d340000, 0x4d300000, 0x41783000, 0x598e6009, - 0x813261c0, 0x0400002e, 0x59300c06, 0x82040580, - 0x00000006, 0x04020004, 0x8d3e7d18, 0x0402000c, - 0x0401f024, 0x82040580, 0x00000005, 0x04020008, - 0x8d3e7d18, 0x04000003, 0x8d3e7d16, 0x04000004, - 0x59300420, 0x8c000500, 0x0402001a, 0x59326809, - 0x59340403, 0x81440580, 0x04020016, 0x8d3e7d00, - 0x04000006, 0x82040580, 0x00000003, 0x04020011, - 0x0401fa23, 0x0402000f, 0x0401f9ef, 0x59300000, - 0x4c000000, 0x8d3e7d06, 0x04000004, 0x0201f800, - 0x0010909d, 0x04000005, 0x0401f80f, 0x4c180000, - 0x0401f95d, 0x5c003000, 0x5c026000, 0x0401f7d5, - 0x41303000, 0x59326000, 0x0401f7d2, 0x5c026000, - 0x5c026800, 0x5c025800, 0x5c03e000, 0x04000ad3, - 0x1c01f000, 0x59300800, 0x497a6000, 0x0401fab6, - 0x801831c0, 0x04020009, 0x598c0008, 0x81300580, - 0x04020004, 0x48031808, 0x48031809, 0x0401f008, - 0x48071809, 0x0401f006, 0x48043000, 0x598c0008, - 0x81300580, 0x04020002, 0x481b1808, 0x0401f2b8, - 0x4d2c0000, 0x4d300000, 0x4d340000, 0x41783000, - 0x598e600b, 0x813261c0, 0x04000013, 0x8d3e7d06, - 0x04000005, 0x59326809, 0x59340200, 0x8c00050e, - 0x0402000a, 0x0401f9b8, 0x59300000, 0x4c000000, - 0x0401f853, 0x4c180000, 0x0401f92b, 0x5c003000, - 0x5c026000, 0x0401f7f0, 0x41303000, 0x59326000, - 0x0401f7ed, 0x0201f800, 0x001045c7, 0x5c026800, - 0x5c026000, 0x5c025800, 0x1c01f000, 0x4933c857, - 0x4c5c0000, 0x813261c0, 0x02000800, 0x00100615, - 0x41300000, 0x598cb80b, 0x41783000, 0x805cb9c0, - 0x0400000f, 0x805c0d80, 0x04000004, 0x405c3000, - 0x5818b800, 0x0401f7fa, 0x0401f835, 0x598c000d, - 0x81300580, 0x02000800, 0x00106e10, 0x497a6007, - 0x80000580, 0x5c00b800, 0x1c01f000, 0x82000540, - 0x00000001, 0x5c00b800, 0x1c01f000, 0x0401fa8d, - 0x4df00000, 0x4d340000, 0x4d300000, 0x4d2c0000, - 0x0201f800, 0x00020267, 0x02020800, 0x00100615, - 0x41783000, 0x598e600b, 0x813261c0, 0x04000014, - 0x59300009, 0x81340580, 0x0402000e, 0x8d3e7d00, - 0x04000003, 0x0401f9aa, 0x0402000a, 0x0401f976, - 0x59300000, 0x4c000000, 0x0401f811, 0x4c180000, - 0x0401f8e9, 0x5c003000, 0x5c026000, 0x0401f7ef, - 0x41303000, 0x59326000, 0x0401f7ec, 0x0201f800, - 0x001045ea, 0x5c025800, 0x5c026000, 0x5c026800, - 0x5c03e000, 0x04000a5d, 0x1c01f000, 0x59300800, - 0x497a6000, 0x0401fa40, 0x801831c0, 0x04020009, - 0x598c000a, 0x81300580, 0x04020004, 0x4803180a, - 0x4803180b, 0x0401f008, 0x4807180b, 0x0401f006, - 0x48043000, 0x598c000a, 0x81300580, 0x04020002, - 0x481b180a, 0x0401f242, 0x0401fa52, 0x4df00000, - 0x4d300000, 0x4c5c0000, 0x4178b800, 0x8d3e7d18, - 0x04000004, 0x8d3e7d16, 0x04020002, 0x805cb800, - 0x598e6005, 0x813261c0, 0x0400001a, 0x59300000, - 0x4c000000, 0x805cb9c0, 0x0402000b, 0x59300c06, - 0x82040580, 0x00000011, 0x04000010, 0x82040580, - 0x00000004, 0x04020004, 0x59300420, 0x8c000500, - 0x0402000a, 0x0201f800, 0x00108f05, 0x02000800, - 0x00107da6, 0x0201f800, 0x001090ec, 0x0201f800, - 0x000208b4, 0x0401fa1e, 0x5c026000, 0x0401f7e6, - 0x497b1805, 0x497b1804, 0x5c00b800, 0x5c026000, - 0x5c03e000, 0x04000a1d, 0x1c01f000, 0x4933c857, - 0x4c5c0000, 0x4c600000, 0x813261c0, 0x02000800, - 0x00100615, 0x41300000, 0x598cb805, 0x405cc000, - 0x805cb9c0, 0x04000025, 0x805c0d80, 0x04000004, - 0x405cc000, 0x5860b800, 0x0401f7fa, 0x598c000d, - 0x81300580, 0x02000800, 0x00106e10, 0x0401f9ee, - 0x598c0005, 0x805c0580, 0x04020009, 0x585c0000, - 0x48031805, 0x4978b800, 0x598c0004, 0x805c0580, - 0x0402000d, 0x497b1804, 0x0401f00b, 0x598c0004, - 0x805c0580, 0x04020005, 0x48631804, 0x4978b800, - 0x4978c000, 0x0401f004, 0x585c0000, 0x4800c000, - 0x4978b800, 0x0401f9ea, 0x80000580, 0x5c00c000, - 0x5c00b800, 0x1c01f000, 0x82000540, 0x00000001, - 0x5c00c000, 0x5c00b800, 0x1c01f000, 0x4933c857, - 0x0401f9f0, 0x4df00000, 0x4d2c0000, 0x4d340000, - 0x4d300000, 0x4c5c0000, 0x4178b800, 0x8d3e7d18, - 0x04000004, 0x8d3e7d16, 0x04020002, 0x805cb800, - 0x41783000, 0x598e6005, 0x813261c0, 0x04000029, - 0x59326809, 0x813669c0, 0x04000023, 0x59340403, - 0x81440580, 0x04020020, 0x805cb9c0, 0x0402000b, - 0x59300c06, 0x82040580, 0x00000011, 0x0400001a, - 0x82040580, 0x00000004, 0x04020004, 0x59300420, - 0x8c000500, 0x04020014, 0x0201f800, 0x00108df4, - 0x04000008, 0x0201f800, 0x00109360, 0x04020005, - 0x59300403, 0x82000580, 0x00000043, 0x0400000a, - 0x0401f8c1, 0x59300000, 0x4c000000, 0x0401f810, - 0x4c180000, 0x0401f834, 0x5c003000, 0x5c026000, - 0x0401f7da, 0x41303000, 0x59326000, 0x0401f7d7, - 0x5c00b800, 0x5c026000, 0x5c026800, 0x5c025800, - 0x5c03e000, 0x040009a9, 0x1c01f000, 0x59300800, - 0x497a6000, 0x0401f98c, 0x801831c0, 0x04020009, - 0x598c0004, 0x81300580, 0x04020004, 0x48031804, - 0x48031805, 0x0401f008, 0x48071805, 0x0401f006, - 0x48043000, 0x598c0004, 0x81300580, 0x04020002, - 0x481b1804, 0x0401f18e, 0x4943c857, 0x0401f99d, - 0x4df00000, 0x0401fe37, 0x0401fed2, 0x5c03e000, - 0x0400098e, 0x1c01f000, 0x4947c857, 0x0401f995, - 0x4df00000, 0x4d3c0000, 0x853e7d00, 0x0401fe7a, - 0x0401ff03, 0x5c027800, 0x5c03e000, 0x04000983, - 0x1c01f000, 0x5c000000, 0x4c000000, 0x4803c857, - 0x4d340000, 0x4d2c0000, 0x59326809, 0x59325808, - 0x59300406, 0x82000c80, 0x00000012, 0x02021800, - 0x00100615, 0x4933c857, 0x4943c857, 0x493fc857, - 0x4803c857, 0x0c01f804, 0x5c025800, 0x5c026800, - 0x1c01f000, 0x00106827, 0x00106829, 0x00106833, - 0x0010684d, 0x00106829, 0x0010683d, 0x00106865, - 0x00106827, 0x00106827, 0x00106878, 0x0010686f, - 0x00106827, 0x00106827, 0x00106827, 0x00106827, - 0x00106827, 0x0010687e, 0x0010687e, 0x0201f800, - 0x00100615, 0x0201f800, 0x00108ef1, 0x02000800, - 0x00101e1b, 0x0201f800, 0x001090ec, 0x0201f800, - 0x00107da6, 0x0201f000, 0x00107698, 0x812e59c0, - 0x02020800, 0x00100615, 0x5930021d, 0x82000580, - 0x00000003, 0x02000800, 0x00108ee7, 0x0201f000, - 0x00107698, 0x0201f800, 0x00108df4, 0x02000000, - 0x00107698, 0x592c1204, 0x82081500, 0x000000ff, - 0x82080580, 0x00000055, 0x02020800, 0x00100615, - 0x49425a06, 0x0201f800, 0x00020381, 0x0201f000, - 0x00107698, 0x59300004, 0x8400055c, 0x48026004, - 0x59300007, 0x8c000500, 0x02020800, 0x00100ee4, - 0x0201f800, 0x00108df4, 0x0400000d, 0x4a025a04, - 0x00000103, 0x49425a06, 0x497a5c09, 0x0201f800, - 0x00108f7d, 0x0201f800, 0x0010a4ae, 0x0201f800, - 0x00020381, 0x0201f800, 0x00108ee7, 0x0201f000, - 0x00107698, 0x59300007, 0x8c000500, 0x02020800, - 0x00100ee4, 0x0201f800, 0x00108df4, 0x02020800, - 0x0010a201, 0x0201f000, 0x00107698, 0x0201f800, - 0x00108df4, 0x04000005, 0x49425a06, 0x497a5c09, - 0x0201f800, 0x00020381, 0x0201f000, 0x00107698, - 0x0201f800, 0x00108df4, 0x02020800, 0x0010639d, - 0x0201f000, 0x00107698, 0x0201f800, 0x00108df4, - 0x04000004, 0x49425a06, 0x0201f800, 0x00020381, - 0x59325817, 0x0201f800, 0x00100843, 0x0201f000, - 0x00107698, 0x598c000d, 0x81300580, 0x04000003, - 0x497a6007, 0x1c01f000, 0x59c40004, 0x82000500, - 0x0000000c, 0x04000005, 0x4a038804, 0x0000000c, - 0x497b2807, 0x0401f00a, 0x0401fadb, 0x59300403, - 0x82000d80, 0x00000040, 0x04000004, 0x82000580, - 0x00000042, 0x04020002, 0x497a6007, 0x0201f800, - 0x00106e10, 0x80000580, 0x1c01f000, 0x59300804, - 0x8c040d20, 0x04020004, 0x82000540, 0x00000001, - 0x1c01f000, 0x4933c857, 0x4d380000, 0x59300804, - 0x84040d20, 0x48066004, 0x42027000, 0x00000049, - 0x59300203, 0x82000580, 0x00000003, 0x04000003, - 0x42027000, 0x00000013, 0x0201f800, 0x000208d8, - 0x80000580, 0x5c027000, 0x1c01f000, 0x59300017, - 0x81480580, 0x04020003, 0x59300018, 0x814c0580, - 0x1c01f000, 0x4d2c0000, 0x4d300000, 0x0401f8c9, - 0x4df00000, 0x0201f800, 0x00105d9b, 0x59900001, - 0x82000500, 0x00000003, 0x0c01f001, 0x001068f1, - 0x001068d1, 0x001068cf, 0x001068cf, 0x0201f800, - 0x00100615, 0x59926004, 0x0401f88e, 0x813261c0, - 0x0400001d, 0x59300004, 0x8c000516, 0x04000004, - 0x59325808, 0x497a5808, 0x497a5809, 0x0401f88e, - 0x59300001, 0x800001c0, 0x0400000e, 0x497a6001, - 0x42003000, 0x0000bf2e, 0x58180801, 0x800409c0, - 0x04020004, 0x48003001, 0x48003000, 0x0401f00a, - 0x58180800, 0x48000800, 0x48003000, 0x0401f006, - 0x59300809, 0x800409c0, 0x02000800, 0x00100615, - 0x4978080c, 0x5c03e000, 0x04000890, 0x5c026000, - 0x5c025800, 0x1c01f000, 0x4d300000, 0x497b2807, - 0x0401f894, 0x4df00000, 0x598c0000, 0x82000500, - 0x00000007, 0x4803c857, 0x0c01f001, 0x00106926, - 0x00106909, 0x00106912, 0x00106916, 0x00106921, - 0x00106926, 0x00106907, 0x00106907, 0x0201f800, - 0x00100615, 0x598c000d, 0x80026540, 0x04000004, - 0x0401f81e, 0x02020800, 0x00100615, 0x0201f800, - 0x00106e10, 0x0401f015, 0x0401f827, 0x0201f800, - 0x00106e10, 0x0401f011, 0x598c000d, 0x80026540, - 0x0400000e, 0x0401f838, 0x04000004, 0x0401f80f, - 0x04000002, 0x0401f81c, 0x0201f800, 0x00106e10, - 0x0401f006, 0x0401f830, 0x02020800, 0x00100615, - 0x0201f800, 0x00106e10, 0x5c03e000, 0x0400085b, - 0x5c026000, 0x1c01f000, 0x598c0009, 0x81300580, - 0x0402000c, 0x0401f84e, 0x0401f83b, 0x59300000, - 0x800001c0, 0x04000004, 0x48031809, 0x497a6000, - 0x0401f003, 0x497b1809, 0x497b1808, 0x80000580, - 0x1c01f000, 0x4d2c0000, 0x59300406, 0x82000580, - 0x00000003, 0x04020012, 0x598c000b, 0x81300580, - 0x0402000f, 0x0401f83a, 0x59325808, 0x497a5808, - 0x497a5809, 0x0401f824, 0x59300000, 0x800001c0, - 0x04000004, 0x4803180b, 0x497a6000, 0x0401f003, - 0x497b180a, 0x497b180b, 0x80000580, 0x5c025800, - 0x1c01f000, 0x598c0005, 0x81300580, 0x0402000c, - 0x0401f827, 0x0401f814, 0x59300000, 0x800001c0, - 0x04000004, 0x48031805, 0x497a6000, 0x0401f003, - 0x497b1805, 0x497b1804, 0x80000580, 0x1c01f000, - 0x4a032001, 0x00000000, 0x497b2004, 0x497b2005, - 0x59900006, 0x82000500, 0x0000ffff, 0x48032006, - 0x1c01f000, 0x4c040000, 0x59300004, 0x82000500, - 0x7ffeffff, 0x48026004, 0x59bc00e4, 0x8c000514, - 0x04000009, 0x42000800, 0x0000bf00, 0x58040012, - 0x81300580, 0x04020004, 0x49780812, 0x4a0378e4, - 0x00000800, 0x5c000800, 0x1c01f000, 0x4803c856, - 0x598c000c, 0x80000540, 0x04000003, 0x80000040, - 0x4803180c, 0x1c01f000, 0x59bc00ea, 0x82000500, - 0x00000007, 0x82000580, 0x00000003, 0x04020004, - 0x4803c856, 0x4a0378e8, 0x00000001, 0x1c01f000, - 0x59bc00ea, 0x82000500, 0x00000007, 0x82000580, - 0x00000001, 0x04020011, 0x4803c856, 0x42000800, - 0x00000000, 0x0401f80e, 0x42000800, 0x00001000, - 0x59bc00ea, 0x82000500, 0x00000007, 0x82000580, - 0x00000003, 0x04000005, 0x80040840, 0x040207f9, - 0x0201f800, 0x00100615, 0x1c01f000, 0x59bc00ea, - 0x82000500, 0x00000007, 0x82000580, 0x00000001, - 0x02020800, 0x00100615, 0x59bc00ea, 0x8c000516, - 0x040207fe, 0x480778e1, 0x1c01f000, 0x59bc00ea, - 0x8c000516, 0x040207fe, 0x480778e1, 0x59bc00ea, - 0x8c000516, 0x040207fe, 0x480b78e1, 0x1c01f000, - 0x4a0378e4, 0x00002000, 0x59a8006f, 0x82000500, - 0x0000000c, 0x04020008, 0x42007000, 0x0010b33f, - 0x58380401, 0x8c000506, 0x04020003, 0x4a0378e4, - 0x00080000, 0x1c01f000, 0x82000d00, 0x80000018, - 0x02020800, 0x0010060d, 0x0201f800, 0x00100615, - 0x001069dc, 0x00106a81, 0x00106a9b, 0x001069dc, - 0x001069de, 0x001069ff, 0x00106a1e, 0x00106a53, - 0x001069dc, 0x00106a7f, 0x001069dc, 0x001069dc, - 0x001069dc, 0x001069dc, 0x001069dc, 0x001069dc, - 0x0201f800, 0x00100615, 0x4d300000, 0x4d900000, - 0x4dd00000, 0x4da40000, 0x4d140000, 0x0201f800, - 0x00106e2f, 0x59bc00ea, 0x8c000510, 0x040007fe, - 0x59be60e0, 0x59300004, 0x8c000520, 0x04000011, - 0x82000500, 0xfffefeff, 0x48026004, 0x4a026203, - 0x00000003, 0x0401ff9b, 0x0201f800, 0x0010101e, - 0x5c022800, 0x5c034800, 0x5c03a000, 0x5c032000, - 0x5c026000, 0x4a0378e4, 0x00000008, 0x0401f787, - 0x84000510, 0x48026004, 0x0401f7f6, 0x4d300000, - 0x4d900000, 0x4dd00000, 0x4da40000, 0x4d140000, - 0x0201f800, 0x00106e2f, 0x59bc00ea, 0x8c000510, - 0x040007fe, 0x59be60e0, 0x59300004, 0x8c000520, - 0x0400000f, 0x82000500, 0xfffefeff, 0x48026004, - 0x0401ff7c, 0x0201f800, 0x0010105c, 0x5c022800, - 0x5c034800, 0x5c03a000, 0x5c032000, 0x5c026000, - 0x4a0378e4, 0x00000008, 0x0401f768, 0x84000510, - 0x48026004, 0x0401f7f6, 0x4d300000, 0x4d2c0000, - 0x4d340000, 0x4da40000, 0x4cd00000, 0x59bc00ea, - 0x8c000510, 0x040007fe, 0x59be60e0, 0x813261c0, - 0x02000800, 0x00100615, 0x59300004, 0x8c000520, - 0x0400001e, 0x82000500, 0xfffefeff, 0x48026004, - 0x59326809, 0x42034800, 0x0010b342, 0x04011000, - 0x4a03c840, 0x0010b349, 0x4a03c842, 0x00000012, - 0x04011000, 0x4a03c840, 0x0010b35b, 0x4a03c842, - 0x000000ff, 0x04011000, 0x4a03c840, 0x0010b45a, - 0x4a03c842, 0x000000ff, 0x0201f800, 0x00106e46, - 0x5c01a000, 0x5c034800, 0x5c026800, 0x5c025800, - 0x5c026000, 0x1c01f000, 0x84000510, 0x48026004, - 0x5c01a000, 0x5c034800, 0x5c026800, 0x5c025800, - 0x5c026000, 0x1c01f000, 0x1c01f000, 0x4d300000, - 0x4d2c0000, 0x4d340000, 0x4cd00000, 0x4d900000, - 0x4dd00000, 0x4da40000, 0x4d140000, 0x0401fbd4, - 0x59bc00ea, 0x8c000510, 0x040007fe, 0x59be60e0, - 0x813261c0, 0x02000800, 0x00100615, 0x59300004, - 0x8c000520, 0x0400000f, 0x82000500, 0xfffefeff, - 0x48026004, 0x0201f800, 0x001075b9, 0x5c022800, - 0x5c034800, 0x5c03a000, 0x5c032000, 0x5c01a000, - 0x5c026800, 0x5c025800, 0x5c026000, 0x1c01f000, - 0x84000510, 0x48026004, 0x5c022800, 0x5c034800, - 0x5c03a000, 0x5c032000, 0x5c01a000, 0x5c026800, - 0x5c025800, 0x5c026000, 0x1c01f000, 0x0201f800, - 0x00100615, 0x4d300000, 0x4d380000, 0x42000000, - 0x0010b6c3, 0x0201f800, 0x0010a86e, 0x0401ff05, - 0x598e600d, 0x59c40004, 0x8c000506, 0x04000004, - 0x0401f8e5, 0x4a038804, 0x00000008, 0x813261c0, - 0x04000006, 0x0401fb98, 0x42027000, 0x00000014, - 0x0201f800, 0x000208d8, 0x4a0378e4, 0x00000002, - 0x5c027000, 0x5c026000, 0x0401f6e8, 0x4d180000, - 0x4d300000, 0x4d380000, 0x4d900000, 0x4dd00000, - 0x4da40000, 0x4d140000, 0x0401feea, 0x417a3000, - 0x59c40804, 0x83180400, 0x00106df6, 0x50000000, - 0x80040500, 0x0400001b, 0x42000000, 0x0010b6c4, - 0x0201f800, 0x0010a86e, 0x0401fb81, 0x59926004, - 0x0401f863, 0x83180400, 0x00106df6, 0x50000000, - 0x48038804, 0x813261c0, 0x0400000a, 0x59300004, - 0x8c00050c, 0x04020003, 0x4a026203, 0x00000003, - 0x42027000, 0x0000004a, 0x0201f800, 0x000208d8, - 0x59c40004, 0x82000500, 0x00f80000, 0x04000005, - 0x811a3000, 0x83180480, 0x00000005, 0x040017dd, - 0x4a0378e4, 0x00000008, 0x5c022800, 0x5c034800, - 0x5c03a000, 0x5c032000, 0x5c027000, 0x5c026000, - 0x5c023000, 0x0401f6b1, 0x4d2c0000, 0x4d340000, - 0x59326809, 0x598c0800, 0x82040580, 0x00000004, - 0x04020006, 0x838c1400, 0x00000005, 0x838c1c00, - 0x00000004, 0x0401f010, 0x82040580, 0x00000001, - 0x04020006, 0x838c1400, 0x00000009, 0x838c1c00, - 0x00000008, 0x0401f008, 0x82040580, 0x00000002, - 0x04020028, 0x838c1400, 0x0000000b, 0x838c1c00, - 0x0000000a, 0x41306800, 0x58340000, 0x80007d40, - 0x04000020, 0x583c0009, 0x81340580, 0x04020006, - 0x403c6800, 0x583c0000, 0x80007d40, 0x040207fa, - 0x0401f018, 0x4933c857, 0x483fc857, 0x583c0000, - 0x48006800, 0x49307800, 0x443c1000, 0x500c0000, - 0x803c0580, 0x04020002, 0x44341800, 0x80000580, - 0x4803180d, 0x4803180f, 0x598c0000, 0x82000580, - 0x00000003, 0x04000003, 0x4a031800, 0x00000000, - 0x80000580, 0x5c026800, 0x5c025800, 0x1c01f000, - 0x82000540, 0x00000001, 0x0401f7fb, 0x491bc857, - 0x59c80840, 0x82040540, 0x00000010, 0x48039040, - 0x59c41008, 0x82080500, 0xffffff7f, 0x48038808, - 0x4c040000, 0x4c080000, 0x0401fac2, 0x04020007, - 0x0401fac6, 0x04000022, 0x48038804, 0x0201f800, - 0x001010ca, 0x0401f042, 0x4a038803, 0x00000008, - 0x59c40003, 0x82000500, 0x00000003, 0x040007fd, - 0x8c000502, 0x04020007, 0x0401fab8, 0x04000014, - 0x48038804, 0x0201f800, 0x001010ca, 0x0401f034, - 0x59c80040, 0x8400056a, 0x48039040, 0x59c80040, - 0x8c00052a, 0x040207fe, 0x59c40005, 0x82000500, - 0xc0000000, 0x04000006, 0x59c400a3, 0x84000540, - 0x480388a3, 0x4a038805, 0xc0000000, 0x0201f800, - 0x0010106b, 0x4a03a005, 0x30000000, 0x59d00006, - 0x4a03a005, 0x30000000, 0x59900006, 0x82000500, - 0xffff0000, 0x48032006, 0x59d00005, 0x8c000504, - 0x040207fe, 0x42000800, 0x00007600, 0x83180540, - 0x60000000, 0x480008a1, 0x811800dc, 0x59c80840, - 0x80040540, 0x48039040, 0x82000540, 0x00003000, - 0x48039040, 0x59c80040, 0x82000500, 0x00003000, - 0x040207fd, 0x0201f800, 0x001010b8, 0x83180400, - 0x00106df6, 0x50000000, 0x48038804, 0x80000580, - 0x4df00000, 0x0201f800, 0x00105d9b, 0x5c03e000, - 0x5c001000, 0x5c000800, 0x480b8808, 0x48079040, - 0x1c01f000, 0x4803c856, 0x59c80840, 0x82040540, - 0x00000010, 0x48039040, 0x59c41008, 0x82080500, - 0xffffff7f, 0x48038808, 0x4c040000, 0x4c080000, - 0x59c40004, 0x82000500, 0x00000003, 0x04020010, - 0x59c40004, 0x82000500, 0x0000000c, 0x04000005, - 0x4a038804, 0x0000000c, 0x8c000504, 0x0401f025, - 0x59c80040, 0x8400056e, 0x48039040, 0x59c80040, - 0x8c00052e, 0x040207fe, 0x0401f01e, 0x4a038803, - 0x00000008, 0x59c40003, 0x82000500, 0x00000003, - 0x040007fd, 0x8c000502, 0x04020006, 0x59c40004, - 0x4a038804, 0x0000000c, 0x8c000504, 0x0401f011, - 0x59c80040, 0x8400056a, 0x48039040, 0x59c80040, - 0x8c00052a, 0x040207fe, 0x59c40005, 0x82000500, - 0xc0000000, 0x04000007, 0x59c400a3, 0x84000540, - 0x480388a3, 0x4a038805, 0xc0000000, 0x80000580, - 0x497b2807, 0x5c001000, 0x5c000800, 0x480b8808, - 0x48079040, 0x1c01f000, 0x5c000000, 0x4c000000, - 0x4803c857, 0x491bc857, 0x4933c857, 0x4d900000, - 0x4dd00000, 0x4da40000, 0x4d140000, 0x0401fdd1, - 0x4df00000, 0x0401fa72, 0x59900004, 0x800001c0, - 0x04000011, 0x81300580, 0x0402000f, 0x59300004, - 0x84000520, 0x48026004, 0x0401ff4d, 0x04020009, - 0x5c03e000, 0x04000db9, 0x80000580, 0x5c022800, - 0x5c034800, 0x5c03a000, 0x5c032000, 0x1c01f000, - 0x0401fcf1, 0x42027000, 0x00000049, 0x59300004, - 0x84000520, 0x48026004, 0x8c00050c, 0x02020800, - 0x000208d8, 0x5c03e000, 0x04000da8, 0x82000540, - 0x00000001, 0x5c022800, 0x5c034800, 0x5c03a000, - 0x5c032000, 0x1c01f000, 0x4933c857, 0x0401fda9, - 0x4df00000, 0x598c000d, 0x80026540, 0x04000012, - 0x59300004, 0x84000520, 0x48026004, 0x0401ff86, - 0x04000017, 0x0401fd09, 0x42027000, 0x00000013, - 0x59300004, 0x8c00050c, 0x02020800, 0x000208d8, - 0x5c03e000, 0x04000d8d, 0x82000540, 0x00000001, - 0x1c01f000, 0x836c1580, 0x00000001, 0x040007f9, - 0x836c1580, 0x00000004, 0x040007f6, 0x42001000, - 0x00103f62, 0x0201f800, 0x00105cc9, 0x5c03e000, - 0x04000d7e, 0x80000580, 0x1c01f000, 0x4d300000, - 0x4d180000, 0x4d3c0000, 0x0401fd82, 0x4df00000, - 0x4a0378e4, 0x0000000f, 0x0401fa02, 0x417a3000, - 0x59926004, 0x813261c0, 0x04000010, 0x417a7800, - 0x0201f800, 0x00104728, 0x0400000a, 0x59300c06, - 0x82040580, 0x00000003, 0x04000004, 0x82040580, - 0x00000006, 0x04020003, 0x42027800, 0x00000002, - 0x0201f800, 0x00108997, 0x811a3000, 0x83180480, - 0x00000005, 0x040017eb, 0x42000800, 0x00000040, - 0x0201f800, 0x00101395, 0x4a0378e4, 0x0000000a, - 0x5c03e000, 0x04000d55, 0x5c027800, 0x5c023000, - 0x5c026000, 0x1c01f000, 0x4803c856, 0x4d300000, - 0x0401fd58, 0x4df00000, 0x59c80840, 0x82040540, - 0x00000010, 0x48039040, 0x59c41008, 0x82080500, - 0xffffff7f, 0x48038808, 0x4c040000, 0x4c080000, - 0x42001000, 0x00000003, 0x0401f9c5, 0x598e600d, - 0x813261c0, 0x04020f9d, 0x040009ca, 0x497b2807, - 0x0401f80a, 0x5c001000, 0x5c000800, 0x480b8808, - 0x84040d74, 0x48079040, 0x5c03e000, 0x04000d33, - 0x5c026000, 0x1c01f000, 0x4d380000, 0x4d180000, - 0x4d300000, 0x4d900000, 0x4dd00000, 0x4da40000, - 0x4d140000, 0x59c41004, 0x480bc857, 0x82080500, - 0x00003ff0, 0x04000025, 0x417a3000, 0x4c080000, - 0x0201f800, 0x00105d9b, 0x5c001000, 0x82080500, - 0x00000210, 0x04020004, 0x811a3000, 0x80081102, - 0x0401f7f7, 0x0401f9c6, 0x59926004, 0x4933c857, - 0x813261c0, 0x04020005, 0x59c400a3, 0x8c00051a, - 0x02000800, 0x00100615, 0x0401fea1, 0x04000009, - 0x0401fc4d, 0x42027000, 0x00000049, 0x59300004, - 0x8c00050c, 0x02020800, 0x000208d8, 0x0401f007, - 0x42027000, 0x0000004a, 0x4a026203, 0x00000003, - 0x0201f800, 0x000208d8, 0x5c022800, 0x5c034800, - 0x5c03a000, 0x5c032000, 0x5c026000, 0x5c023000, - 0x5c027000, 0x1c01f000, 0x4d300000, 0x4d180000, - 0x4d900000, 0x0401fcff, 0x42001000, 0x00000000, - 0x598c0000, 0x82000580, 0x00000005, 0x04000974, - 0x417a3000, 0x811b20c8, 0x83932400, 0x0000bf32, - 0x59900001, 0x82000580, 0x00000001, 0x0402000d, - 0x42000800, 0x000007d0, 0x59926004, 0x59300011, - 0x82000500, 0xfff00000, 0x80000540, 0x04000003, - 0x42000800, 0x00001b58, 0x0201f800, 0x00105d8d, - 0x811a3000, 0x83180480, 0x00000005, 0x040017ea, - 0x59c81040, 0x84081534, 0x480b9040, 0x0401fcd3, - 0x5c032000, 0x5c023000, 0x5c026000, 0x1c01f000, - 0x4933c857, 0x4d900000, 0x4dd00000, 0x4da40000, - 0x4d140000, 0x4d380000, 0x0401fcd2, 0x4df00000, - 0x59300004, 0x8c00053e, 0x04020007, 0x8c000520, - 0x04000026, 0x0201f800, 0x001068a3, 0x04000023, - 0x0401f02b, 0x598c000d, 0x81300580, 0x04000012, - 0x0201f800, 0x00108a8a, 0x04020025, 0x0401f91b, - 0x04000023, 0x48038804, 0x0401f961, 0x0201f800, - 0x001010ca, 0x0201f800, 0x001068c1, 0x42027000, - 0x00000049, 0x59300004, 0x8c00050c, 0x0402000d, - 0x0401f00e, 0x59c40004, 0x8c000504, 0x04000014, - 0x4a038804, 0x00000004, 0x0401fc18, 0x42027000, - 0x00000013, 0x59300004, 0x8c00050c, 0x04000003, - 0x0201f800, 0x000208d8, 0x5c03e000, 0x04000c9b, - 0x5c027000, 0x5c022800, 0x5c034800, 0x5c03a000, - 0x5c032000, 0x80000580, 0x1c01f000, 0x5c03e000, - 0x04000c92, 0x5c027000, 0x5c022800, 0x5c034800, - 0x5c03a000, 0x5c032000, 0x82000540, 0x00000001, - 0x1c01f000, 0x497b2807, 0x0401fc92, 0x59c400af, - 0x800001c0, 0x04020004, 0x0401fc84, 0x0201f000, - 0x00101565, 0x598c000f, 0x82001480, 0x00000002, - 0x04021007, 0x80000000, 0x4803180f, 0x80000580, - 0x0201f800, 0x00105d86, 0x0400000e, 0x0401fed7, - 0x0402000c, 0x0401fdc5, 0x0400000a, 0x0201f800, - 0x0010a7ee, 0x0401f918, 0x4d380000, 0x42027000, - 0x00000014, 0x0201f800, 0x000208d8, 0x5c027000, - 0x0401fc6a, 0x0201f000, 0x00101565, 0x4d900000, - 0x4dd00000, 0x4da40000, 0x4d140000, 0x4d300000, - 0x0201f800, 0x00105d9b, 0x0401fc6a, 0x59c400af, - 0x800001c0, 0x04000027, 0x0401f909, 0x59926004, - 0x4933c857, 0x59300004, 0x8c000516, 0x0400000b, - 0x0401fe86, 0x0402001f, 0x0201f800, 0x001068c1, - 0x0401fc52, 0x42000800, 0x80000804, 0x0201f800, - 0x00106466, 0x0401f017, 0x42001800, 0x00007530, - 0x0401f8c3, 0x04020004, 0x0201f800, 0x00105d8b, - 0x0401f010, 0x0401fe75, 0x0402000e, 0x0201f800, - 0x0010a7ee, 0x59300004, 0x8c00050c, 0x04020003, - 0x4a026203, 0x00000003, 0x4d380000, 0x42027000, - 0x0000004a, 0x0201f800, 0x000208d8, 0x5c027000, - 0x0401fc36, 0x5c026000, 0x5c022800, 0x5c034800, - 0x5c03a000, 0x5c032000, 0x0201f000, 0x00101565, - 0x4d900000, 0x4dd00000, 0x4da40000, 0x4d140000, - 0x4d300000, 0x4d2c0000, 0x0401fc32, 0x0401f8d4, - 0x59926004, 0x4933c857, 0x0401f882, 0x04000016, - 0x0201f800, 0x00105d9b, 0x813261c0, 0x04000034, - 0x59325808, 0x812e59c0, 0x02000800, 0x00100615, - 0x0201f800, 0x00104e0d, 0x0402001d, 0x592c0208, - 0x84000550, 0x48025a08, 0x0201f800, 0x00104f29, - 0x04020027, 0x592c0208, 0x84000510, 0x48025a08, - 0x0401f023, 0x0201f800, 0x00105d8b, 0x0401f020, - 0x0201f800, 0x0010a7ee, 0x0401fd99, 0x592c0208, - 0x84000550, 0x48025a08, 0x4d380000, 0x42027000, - 0x0000004a, 0x4a026203, 0x00000003, 0x0201f800, - 0x000208d8, 0x5c027000, 0x0401f011, 0x59900006, - 0x82000500, 0xffff0000, 0x040207ee, 0x59c408af, - 0x82040480, 0x000003e8, 0x040217ea, 0x59900006, - 0x82000400, 0x00010000, 0x48032006, 0x0201f800, - 0x00105d8b, 0x0201f800, 0x00103f37, 0x5c025800, - 0x5c026000, 0x5c022800, 0x5c034800, 0x5c03a000, - 0x5c032000, 0x0201f000, 0x00106982, 0x4d300000, - 0x4d2c0000, 0x0201f800, 0x0010698c, 0x598e600d, - 0x4933c857, 0x59c41004, 0x8c081500, 0x04000007, - 0x0201f800, 0x00104e0d, 0x04020007, 0x0201f800, - 0x00104f29, 0x0402002f, 0x0201f800, 0x00105d86, - 0x0401f02c, 0x598c000f, 0x80000540, 0x04020011, - 0x59c408af, 0x82040480, 0x000003e8, 0x0402100d, - 0x598c080f, 0x80040800, 0x4807180f, 0x0201f800, - 0x00105d86, 0x42000000, 0x0010b650, 0x0201f800, - 0x0010a86e, 0x0201f800, 0x00103f37, 0x0401f019, - 0x0401fdad, 0x813261c0, 0x04020003, 0x0401f849, - 0x0401f014, 0x0201f800, 0x0010a7ee, 0x59300406, - 0x82000580, 0x00000003, 0x04020007, 0x59325808, - 0x812e59c0, 0x04000004, 0x592c0208, 0x84000550, - 0x48025a08, 0x0401f854, 0x4d380000, 0x42027000, - 0x00000014, 0x0201f800, 0x000208d8, 0x5c027000, - 0x5c025800, 0x5c026000, 0x0201f000, 0x00106982, - 0x59c40804, 0x83180400, 0x00106dec, 0x50000000, - 0x80040500, 0x1c01f000, 0x59c40804, 0x83180400, - 0x00106df1, 0x50000000, 0x80040500, 0x1c01f000, - 0x00000210, 0x00000420, 0x00000840, 0x00001080, - 0x00002100, 0x00004000, 0x00008000, 0x00010000, - 0x00020000, 0x00040000, 0x00080000, 0x00100000, - 0x00200000, 0x00400000, 0x00800000, 0x59900806, - 0x80040120, 0x800c0480, 0x04021004, 0x82000540, - 0x00000001, 0x0401f005, 0x82040c00, 0x00010000, - 0x48072006, 0x80000580, 0x1c01f000, 0x480bc857, - 0x0201f800, 0x0010698c, 0x4df00000, 0x480b1800, - 0x5c03e000, 0x02000800, 0x00106982, 0x1c01f000, - 0x4803c856, 0x0201f800, 0x0010698c, 0x4df00000, - 0x497b180d, 0x497b1803, 0x497b180e, 0x497b180f, - 0x497b1810, 0x598c0000, 0x82000580, 0x00000003, - 0x04000009, 0x836c0580, 0x00000002, 0x04020004, - 0x4a031800, 0x00000005, 0x0401f003, 0x4a031800, - 0x00000000, 0x5c03e000, 0x02000800, 0x00106982, - 0x1c01f000, 0x59300004, 0x8c00050c, 0x04020003, - 0x4a026203, 0x00000001, 0x1c01f000, 0x83180480, - 0x00000005, 0x02021800, 0x00100615, 0x491bc857, - 0x811b20c8, 0x83932400, 0x0000bf32, 0x811ba0ca, - 0x83d3a400, 0x00007600, 0x83180400, 0x00106e41, - 0x50034800, 0x811a28c2, 0x83162c00, 0x00006100, - 0x1c01f000, 0x0010b559, 0x0010b570, 0x0010b587, - 0x0010b59e, 0x0010b5b5, 0x4933c857, 0x59300406, - 0x82000c80, 0x00000012, 0x04021016, 0x4803c857, - 0x04011000, 0x0c01f001, 0x00106e60, 0x00106f03, - 0x00107249, 0x001072cf, 0x00106f03, 0x00107249, - 0x001072cf, 0x00106e60, 0x00106f03, 0x00106e60, - 0x00106e60, 0x00106e60, 0x00106e60, 0x00106e60, - 0x00106e60, 0x00106e60, 0x00106e66, 0x00106e66, - 0x0201f800, 0x0010698c, 0x0201f800, 0x001068f6, - 0x0201f000, 0x00106982, 0x42001000, 0x0010b5f4, - 0x50081000, 0x4930100c, 0x58080002, 0x82000580, - 0x00000100, 0x0402003e, 0x59325808, 0x812e59c0, - 0x02000800, 0x00100615, 0x59326809, 0x813669c0, - 0x04000025, 0x592c040b, 0x82000500, 0x0000e000, - 0x04000003, 0x0401fbc9, 0x0401f002, 0x0401fbb9, - 0x592c000d, 0x82000500, 0x00000003, 0x04000007, - 0x82000580, 0x00000003, 0x80000000, 0x58d00802, - 0x80040540, 0x4801a002, 0x42001000, 0x0010b5f4, - 0x50081000, 0x4930100b, 0x492c100a, 0x82d00400, - 0x00000006, 0x48001003, 0x592c000d, 0x82000400, - 0x00000003, 0x80000104, 0x48001004, 0x592c000e, - 0x48001007, 0x592c000f, 0x48001008, 0x0201f000, - 0x001008a1, 0x42026800, 0x0010bc0c, 0x592c080a, - 0x48066802, 0x82040500, 0x00ffff00, 0x04000007, - 0x497a6a12, 0x59a81010, 0x82081500, 0x00ffff00, - 0x80080580, 0x040207d0, 0x82040d00, 0x000000ff, - 0x800408d0, 0x48066a12, 0x0401f7cb, 0x1c01f000, - 0x4d2c0000, 0x4d300000, 0x4c580000, 0x4c540000, - 0x4c500000, 0x5832580a, 0x812e59c0, 0x02000800, - 0x00100615, 0x58300002, 0x4a006002, 0x00000100, - 0x82000580, 0x00000100, 0x04020020, 0x5830000b, - 0x5832600c, 0x81300580, 0x04020012, 0x0401f82f, - 0x04020014, 0x592c080d, 0x82040c00, 0x00000003, - 0x80040904, 0x4004b000, 0x4200a000, 0x0010b349, - 0x4050a800, 0x0201f800, 0x0010a94f, 0x42001000, - 0x0000dc00, 0x0201f800, 0x0010763b, 0x0401f005, - 0x4803c857, 0x4933c857, 0x0401f81c, 0x04000f93, - 0x5c00a000, 0x5c00a800, 0x5c00b000, 0x5c026000, - 0x5c025800, 0x1c01f000, 0x5830000b, 0x5832600c, - 0x4803c857, 0x4933c857, 0x81300580, 0x040207f1, - 0x0401f80e, 0x040207f3, 0x4803c857, 0x0201f800, - 0x00106619, 0x02020800, 0x00100615, 0x4a025a06, - 0x00000002, 0x0201f800, 0x00020381, 0x0201f800, - 0x00107698, 0x0401f7e7, 0x0201f800, 0x0010698c, - 0x4df00000, 0x598c000d, 0x81300580, 0x04020009, - 0x598c0005, 0x81300580, 0x04020006, 0x5c03e000, - 0x02000800, 0x00106982, 0x80000580, 0x1c01f000, - 0x4803c857, 0x5c03e000, 0x02000800, 0x00106982, - 0x82000540, 0x00000001, 0x1c01f000, 0x59300403, - 0x82000c80, 0x00000056, 0x02021800, 0x00100615, - 0x4803c857, 0x0c01f001, 0x0010707a, 0x00107095, - 0x001070a6, 0x001071a9, 0x00107169, 0x0010716d, - 0x0010717e, 0x00107192, 0x00107187, 0x00107192, - 0x001071cd, 0x00107192, 0x0010720f, 0x00107192, - 0x0010721d, 0x00107192, 0x00107187, 0x00107192, - 0x00107221, 0x00106f60, 0x00106f60, 0x00106f60, - 0x00106f60, 0x00106f60, 0x00106f60, 0x00106f60, - 0x00106f60, 0x00106f60, 0x00106f60, 0x00106f60, - 0x001072ed, 0x0010730c, 0x00107316, 0x00106f60, - 0x0010732c, 0x0010717e, 0x00106f60, 0x0010717e, - 0x00107192, 0x00106f60, 0x001070a6, 0x001071a9, - 0x00106f60, 0x0010737c, 0x00107192, 0x00106f60, - 0x0010738c, 0x00107192, 0x00106f60, 0x00107187, - 0x0010706b, 0x00106f62, 0x00106f60, 0x001073a3, - 0x001073dc, 0x00107456, 0x00106f60, 0x00107466, - 0x0010717c, 0x00107459, 0x00106f60, 0x00107338, - 0x0010747f, 0x00106f60, 0x001074b4, 0x00107507, - 0x00106f60, 0x00106f77, 0x00106fdd, 0x00106fea, - 0x00106f60, 0x0010717e, 0x00106f60, 0x00107031, - 0x0010703c, 0x00106f60, 0x00106f60, 0x00106f8b, - 0x00106fb0, 0x00107546, 0x00107587, 0x001075ad, - 0x00106f60, 0x00106f60, 0x00106f60, 0x0010757b, - 0x0201f800, 0x00100615, 0x0401fad2, 0x59325808, - 0x592c0009, 0x4801a006, 0x592c000a, 0x4801a007, - 0x592c000b, 0x4801a008, 0x592c000c, 0x4801a009, - 0x592c000d, 0x4801a00a, 0x4979a00b, 0x592c0809, - 0x82040d00, 0x00000fff, 0x80040904, 0x42001000, - 0x0000dc00, 0x0201f000, 0x0010763b, 0x4a026202, - 0x0000ffff, 0x0401fabb, 0x4d2c0000, 0x4a01a006, - 0x05000000, 0x59325808, 0x592c0009, 0x4801a007, - 0x592c000a, 0x4801a008, 0x592c000b, 0x4801a009, - 0x42000800, 0x00000004, 0x42001000, 0x0000dc00, - 0x5c025800, 0x0201f000, 0x0010763b, 0x4c580000, - 0x4c500000, 0x4c540000, 0x4d2c0000, 0x0401faa5, - 0x59325808, 0x5930040b, 0x800000c2, 0x4200a800, - 0x0010b349, 0x592cb205, 0x832ca400, 0x00000006, - 0x0201f800, 0x0010a93e, 0x40580000, 0x8054ac00, - 0x592c0001, 0x80000540, 0x04000003, 0x40025800, - 0x0401f7f5, 0x4200a000, 0x0010b349, 0x4050a800, - 0x5930b40b, 0x0201f800, 0x0010a94f, 0x59300c0b, - 0x42001000, 0x0000dc00, 0x5c025800, 0x5c00a800, - 0x5c00b000, 0x5c00a000, 0x0201f000, 0x0010763b, - 0x4c580000, 0x4c500000, 0x4c540000, 0x4d2c0000, - 0x42034800, 0x0010b342, 0x0401fa8c, 0x59325808, - 0x592c0802, 0x4807c857, 0x40041000, 0x80040904, - 0x82081500, 0x00000003, 0x04000008, 0x80040800, - 0x82081580, 0x00000003, 0x80081000, 0x58d00002, - 0x80080540, 0x4801a002, 0x4a025805, 0x02000000, - 0x82d0ac00, 0x00000006, 0x592cb011, 0x832ca400, - 0x00000005, 0x0201f800, 0x0010a93e, 0x40580000, - 0x8054ac00, 0x592e5801, 0x41780000, 0x812e5d40, - 0x040207f6, 0x42001000, 0x0000dc00, 0x5c025800, - 0x5c00a800, 0x5c00b000, 0x5c00a000, 0x0201f000, - 0x0010763b, 0x0401fa57, 0x4a01a006, 0x78000000, - 0x5930001c, 0x840001c0, 0x4801a407, 0x4979a207, - 0x42000800, 0x00000002, 0x42001000, 0x0000dc00, - 0x0201f000, 0x0010763b, 0x4c580000, 0x4c540000, - 0x4c500000, 0x0401fa55, 0x4a01a006, 0x02000000, - 0x59a80002, 0x4801a008, 0x59a80003, 0x4801a009, - 0x59a80000, 0x4801a00a, 0x59a80001, 0x4801a00b, - 0x5930001c, 0x82000d80, 0x0000e000, 0x04000016, - 0x82000d80, 0x0000df00, 0x04000006, 0x4a01a407, - 0x00000010, 0x42000800, 0x00000006, 0x0401f027, - 0x4a03c840, 0x0010b2e7, 0x4a03c842, 0x0000000d, - 0x42001800, 0x0010b2e7, 0x0201f800, 0x001007f5, - 0x42000000, 0x0000df00, 0x4200a000, 0x0010b2e7, - 0x0401f00d, 0x4a03c840, 0x0010b2f4, 0x4a03c842, - 0x0000000d, 0x42001800, 0x0010b2f4, 0x0201f800, - 0x001007f5, 0x42000000, 0x0000e000, 0x4200a000, - 0x0010b2f4, 0x82000540, 0x00000010, 0x4801a407, - 0x4a01a207, 0x00000034, 0x4200b000, 0x0000000d, - 0x82d0ac00, 0x0000000c, 0x0201f800, 0x0010a93e, - 0x42000800, 0x00000013, 0x42001000, 0x0000dc00, - 0x5c00a000, 0x5c00a800, 0x5c00b000, 0x0201f000, - 0x0010763b, 0x0401fa03, 0x4a01a006, 0x63000028, - 0x5930001c, 0x4801a007, 0x42000800, 0x00000002, - 0x42001000, 0x0000dc00, 0x0201f000, 0x0010763b, - 0x0401fa06, 0x41780000, 0x41780800, 0x42002000, - 0x00080000, 0x0c01f81b, 0x80000000, 0x80040800, - 0x42001000, 0x0000000c, 0x59841802, 0x8c0c1d00, - 0x04020008, 0x42002000, 0x00050000, 0x0c01f811, - 0x80000000, 0x80040800, 0x82081400, 0x00000004, - 0x82080540, 0x02000000, 0x4801a006, 0x800408e0, - 0x5930001c, 0x80040540, 0x4801a007, 0x80080904, - 0x42001000, 0x0000dc00, 0x0201f000, 0x0010763b, - 0x00107061, 0x00107063, 0x00107065, 0x00107067, - 0x00107069, 0x4811a008, 0x1c01f000, 0x4811a009, - 0x1c01f000, 0x4811a00a, 0x1c01f000, 0x4811a00b, - 0x1c01f000, 0x4811a00c, 0x1c01f000, 0x4a026009, - 0x0010bc0c, 0x59a80010, 0x82000500, 0x000000ff, - 0x800000d0, 0x42026800, 0x0010bc0c, 0x48026a12, - 0x0401fa3c, 0x41780800, 0x42001000, 0x00005c00, - 0x0201f000, 0x0010763b, 0x0401f9ba, 0x4a01a006, - 0x52000000, 0x4979a007, 0x599c0017, 0x8c000500, - 0x04000005, 0x599c0402, 0x0201f800, 0x00101644, - 0x4805a007, 0x59a80002, 0x4801a008, 0x59a80003, - 0x4801a009, 0x59a80000, 0x4801a00a, 0x59a80001, - 0x4801a00b, 0x59a80010, 0x4801a00c, 0x42000800, - 0x00000007, 0x42001000, 0x0000dc00, 0x0201f000, - 0x0010763b, 0x4a026202, 0x0000ffff, 0x0401f99d, - 0x4a01a006, 0x05000000, 0x59a80010, 0x4801a007, - 0x59a80002, 0x59a80803, 0x4801a008, 0x4805a009, - 0x42000800, 0x00000004, 0x42001000, 0x0000dc00, - 0x0201f000, 0x0010763b, 0x4a026202, 0x0000ffff, - 0x0401f98c, 0x4d3c0000, 0x417a7800, 0x0201f800, - 0x00104745, 0x5c027800, 0x4a01a006, 0x03000000, - 0x59340403, 0x82000580, 0x000007fe, 0x0402006e, - 0x4a01a006, 0x04000000, 0x81a40800, 0x4a000800, - 0x22fffffe, 0x5934000a, 0x84000500, 0x4802680a, - 0x59c41002, 0x8408150c, 0x480b8802, 0x59a80026, - 0x8c000508, 0x04000010, 0x59a8002a, 0x4801a007, - 0x59a8002b, 0x82000500, 0xffff2000, 0x599c0818, - 0x8c040d16, 0x04000002, 0x8400056a, 0x4801a008, - 0x4a01a009, 0x00002710, 0x59a8002d, 0x4801a00a, - 0x0401f039, 0x59a8002a, 0x4801a007, 0x0201f800, - 0x00104e0d, 0x04020009, 0x497b8880, 0x82000500, - 0x0000ffff, 0x4c000000, 0x0201f800, 0x00101670, - 0x5c000000, 0x48038880, 0x59a8002b, 0x0201f800, - 0x00104e0d, 0x04020004, 0x82000500, 0x37ffffff, - 0x0401f003, 0x82000500, 0x3fffffff, 0x599c0818, - 0x8c040d16, 0x04000002, 0x8400056a, 0x59a80805, - 0x8c040d10, 0x04000019, 0x59300c03, 0x82041580, - 0x00000051, 0x04000015, 0x82041580, 0x00000031, - 0x04000012, 0x4c580000, 0x4c500000, 0x4c540000, - 0x4200b000, 0x00000004, 0x4200a000, 0x0010b6f9, - 0x82d0ac00, 0x0000001f, 0x4c000000, 0x0201f800, - 0x0010a93e, 0x5c000000, 0x5c00a800, 0x5c00a000, - 0x5c00b000, 0x8400057a, 0x4801a008, 0x4979a009, - 0x4979a00a, 0x59a80002, 0x59a80803, 0x4801a00b, - 0x4805a00c, 0x59a80000, 0x59a80801, 0x4801a00d, - 0x4805a00e, 0x4979a00f, 0x4979a010, 0x4979a011, - 0x4979a012, 0x4979a013, 0x4979a014, 0x4979a015, - 0x4979a016, 0x59a8002e, 0x84000576, 0x4801a017, - 0x59a8002f, 0x4801a018, 0x4979a019, 0x4979a01a, - 0x0401f043, 0x59a80026, 0x8c000508, 0x0400000d, - 0x59a8002a, 0x82000500, 0x0000ffff, 0x59c40880, - 0x80040d80, 0x04000007, 0x497b8880, 0x4c000000, - 0x0201f800, 0x00101670, 0x5c000000, 0x48038880, - 0x59a8002a, 0x4801a007, 0x4c640000, 0x4d2c0000, - 0x59a8c82b, 0x0201f800, 0x00108df4, 0x0400000d, - 0x0201f800, 0x00109360, 0x0402000a, 0x592c0207, - 0x8c00050e, 0x04000007, 0x8264cd00, 0x0000ffff, - 0x592c0009, 0x82000500, 0xffff0000, 0x8064cd40, - 0x4865a008, 0x5c025800, 0x5c00c800, 0x59a8002c, - 0x4801a009, 0x59a8002d, 0x4801a00a, 0x59a80002, - 0x59a80803, 0x4801a00b, 0x4805a00c, 0x59a80000, - 0x59a80801, 0x4801a00d, 0x4805a00e, 0x4979a00f, - 0x4979a010, 0x4979a011, 0x4979a012, 0x4979a013, - 0x4979a014, 0x4979a015, 0x4979a016, 0x59a8002e, - 0x4801a017, 0x59a8002f, 0x4801a018, 0x59a80030, - 0x4801a019, 0x59a80031, 0x4801a01a, 0x42000800, - 0x0000001d, 0x42001000, 0x0000dc00, 0x0201f000, - 0x0010763b, 0x0401f8cb, 0x4a01a006, 0x50000000, - 0x0401f7b5, 0x0401f8c7, 0x4a01a406, 0x21000010, - 0x4a01a206, 0x00000014, 0x4979a007, 0x4979a008, - 0x4979a009, 0x4979a00a, 0x42000800, 0x00000005, - 0x42001000, 0x0000dc00, 0x0201f000, 0x0010763b, - 0x0401f8bf, 0x0401f002, 0x0401f8c4, 0x4a01a006, - 0x02000000, 0x42000800, 0x00000001, 0x42001000, - 0x0000dc00, 0x0201f000, 0x0010763b, 0x0401f8bb, - 0x4a01a006, 0x02000000, 0x59300403, 0x82000580, - 0x00000031, 0x04020794, 0x81a40800, 0x4a000801, - 0x00fffffe, 0x0401f72b, 0x0401f8b0, 0x4a01a006, - 0x01000000, 0x5930041a, 0x80000540, 0x04000003, - 0x4801a407, 0x0401f003, 0x4a01a407, 0x00000003, - 0x5930021a, 0x80000540, 0x04000003, 0x4801a207, - 0x0401f003, 0x4a01a207, 0x00002a00, 0x42000800, - 0x00000002, 0x42001000, 0x0000dc00, 0x0201f000, - 0x0010763b, 0x4a026202, 0x0000ffff, 0x0401f889, - 0x4a01a406, 0x00002010, 0x4a01a206, 0x00000014, - 0x4a01a407, 0x00000800, 0x4a01a207, 0x00002000, - 0x80000580, 0x599c0817, 0x8c040d0a, 0x04020003, - 0x82000540, 0x00000020, 0x8c040d08, 0x04000003, - 0x82000540, 0x00000010, 0x82000540, 0x00000002, - 0x5934080a, 0x8c040d14, 0x04000005, 0x82040d00, - 0x00000380, 0x80040540, 0x0401f006, 0x599c0818, - 0x8c040d18, 0x04000003, 0x82000540, 0x00000380, - 0x0401f03c, 0x0401f875, 0x4a01a406, 0x00000210, - 0x4a01a206, 0x00000014, 0x4a01a407, 0x00000800, - 0x5934000a, 0x8c000516, 0x04000014, 0x59340c05, - 0x82040500, 0x00000030, 0x04000013, 0x59340a05, - 0x82040500, 0x0000c000, 0x04020009, 0x8c040d1a, - 0x04000004, 0x4a01a207, 0x00002100, 0x0401f00c, - 0x4a01a207, 0x00000100, 0x0401f009, 0x4a01a207, - 0x00000400, 0x0401f006, 0x4a01a207, 0x00000700, - 0x0401f003, 0x4a01a207, 0x00000800, 0x80000580, - 0x599c0817, 0x8c040d0a, 0x04020003, 0x82000540, - 0x00000020, 0x8c040d08, 0x04000003, 0x82000540, - 0x00000010, 0x82000540, 0x00000002, 0x59340a00, - 0x8c040d0e, 0x0400000b, 0x84000550, 0x599c1017, - 0x8c08150a, 0x04020004, 0x8c040d0a, 0x04000002, - 0x8400054e, 0x8c040d1c, 0x04000002, 0x84000552, - 0x4801a20a, 0x42000800, 0x00000005, 0x42001000, - 0x0000dc00, 0x0201f000, 0x0010763b, 0x0401f833, - 0x4a01a006, 0x02100014, 0x4a01a007, 0x01000000, - 0x4979a008, 0x4979a009, 0x4979a00a, 0x42000800, - 0x00000005, 0x42001000, 0x0000dc00, 0x0201f000, - 0x0010763b, 0x0401f825, 0x4a01a006, 0x02000000, - 0x0401f65d, 0x4933c857, 0x0401f820, 0x4a01a006, - 0x01000000, 0x4a01a407, 0x0000000b, 0x42000800, - 0x00000002, 0x42001000, 0x0000dc00, 0x0201f000, - 0x0010763b, 0x42005000, 0x32000000, 0x42006000, - 0x08290000, 0x41786800, 0x41787800, 0x0401f3e6, - 0x42005000, 0x22000000, 0x42006000, 0x01290000, - 0x41786800, 0x41787800, 0x0401f3df, 0x42005000, - 0x33000000, 0x42006000, 0x08980000, 0x41786800, - 0x41787800, 0x0401f3d8, 0x42005000, 0x23000000, - 0x42006000, 0x01980000, 0x41786800, 0x41787800, - 0x0401f3d1, 0x59300403, 0x82000c80, 0x00000085, - 0x02001800, 0x00100615, 0x82000c80, 0x00000093, - 0x02021800, 0x00100615, 0x82000480, 0x00000085, - 0x0c01f001, 0x00107263, 0x00107265, 0x00107272, - 0x00107263, 0x00107263, 0x00107263, 0x00107263, - 0x00107263, 0x00107263, 0x00107263, 0x00107263, - 0x00107263, 0x00107263, 0x0010727f, 0x0201f800, - 0x00100615, 0x4933c857, 0x0401f851, 0x5930001c, - 0x4801a004, 0x4801a007, 0x4979a408, 0x4a01a208, - 0x0000ffff, 0x42000800, 0x00000003, 0x42001000, - 0x0000dc00, 0x0401f3ca, 0x4933c857, 0x0401f850, - 0x5930001c, 0x4801a004, 0x4a01a406, 0x00000003, - 0x4a01a206, 0x00000300, 0x42000800, 0x00000001, - 0x42001000, 0x0000dc00, 0x0401f3bd, 0x4d2c0000, - 0x59325808, 0x4933c857, 0x492fc857, 0x812e59c0, - 0x02000800, 0x00100615, 0x59340a12, 0x82040d00, - 0x0000ff00, 0x592c000a, 0x82000500, 0x000000ff, - 0x900001c0, 0x80040540, 0x82000540, 0x00000011, - 0x44034800, 0x81a5a000, 0x42001000, 0x00000009, - 0x42000800, 0x00000003, 0x592c0009, 0x82000500, - 0xff000000, 0x82001d80, 0x84000000, 0x04000009, - 0x82001d80, 0x85000000, 0x02020800, 0x00100615, - 0x42001000, 0x00000007, 0x42000800, 0x00000001, - 0x832c1c00, 0x00000009, 0x500c0000, 0x4401a000, - 0x800c1800, 0x80d1a000, 0x80081040, 0x040207fb, - 0x42001000, 0x0000dc00, 0x5c025800, 0x0401f38c, - 0x42005000, 0x81000000, 0x42006000, 0x00090000, - 0x41786800, 0x41787800, 0x0401f363, 0x42005000, - 0x84000000, 0x42006000, 0x00990000, 0x59300406, - 0x82000580, 0x00000005, 0x04000002, 0x8430652e, - 0x41786800, 0x41787800, 0x0401f357, 0x42005000, - 0x85000000, 0x42006000, 0x00990000, 0x59300406, - 0x82000580, 0x00000005, 0x04000002, 0x8430652e, - 0x41786800, 0x41787800, 0x0401f34b, 0x59300403, - 0x82000c80, 0x00000053, 0x02021800, 0x00100615, - 0x82000480, 0x0000004b, 0x02001800, 0x00100615, - 0x59326809, 0x59368c03, 0x4803c857, 0x0c01f001, - 0x00107353, 0x0010735b, 0x00107363, 0x0010736b, - 0x001072e4, 0x001072e4, 0x001072e4, 0x0010734b, - 0x0201f800, 0x00100615, 0x42005000, 0x06000000, - 0x42006000, 0x08290000, 0x41786800, 0x41787800, - 0x0401f32d, 0x4933c857, 0x0401ff46, 0x4a01a006, - 0x12000000, 0x59300406, 0x82000580, 0x00000004, - 0x04020003, 0x59340002, 0x0401f002, 0x59a80010, - 0x82000500, 0x00ffffff, 0x4801a007, 0x59300419, - 0x4801a408, 0x59300219, 0x4801a208, 0x4979a009, - 0x4979a00a, 0x4979a00b, 0x4979a00c, 0x4979a00d, - 0x4979a00e, 0x4979a00f, 0x4979a010, 0x42000800, - 0x0000000b, 0x42001000, 0x0000dc00, 0x0401f330, - 0x0401ff28, 0x4a01a006, 0x0f000000, 0x5930001c, - 0x4801a007, 0x42000800, 0x00000002, 0x42001000, - 0x0000dc00, 0x0401f326, 0x0401ff2c, 0x4a01a006, - 0x02000000, 0x59c40085, 0x48031004, 0x59880000, - 0x4801a007, 0x59880001, 0x4801a008, 0x59880002, - 0x4801a009, 0x59880003, 0x4801a00a, 0x59880004, - 0x4801a00b, 0x59880005, 0x4801a00c, 0x42000800, - 0x00000007, 0x42001000, 0x0000dc00, 0x0401f310, - 0x4a026202, 0x0000ffff, 0x0401ff06, 0x4a01a006, - 0x62000000, 0x5930001c, 0x4801a007, 0x42000800, - 0x00000002, 0x42001000, 0x0000dc00, 0x0401f304, - 0x0401fefc, 0x59300808, 0x4c500000, 0x4c540000, - 0x4c580000, 0x8204a400, 0x0000000a, 0x5930b01c, - 0x82d0ac00, 0x00000006, 0x0201f800, 0x0010a93e, - 0x5930081c, 0x42001000, 0x0000dc00, 0x5c00b000, - 0x5c00a800, 0x5c00a000, 0x0401f2f1, 0x0401ff9b, - 0x59300017, 0x4801a006, 0x59300018, 0x4801a007, - 0x4a01a008, 0x00001000, 0x0401f020, 0x0401ff93, - 0x59300017, 0x4801a006, 0x59300018, 0x4801a007, - 0x4a01a008, 0x00004000, 0x0401f018, 0x0401ff8b, - 0x59300017, 0x4801a006, 0x59300018, 0x4801a007, - 0x4a01a008, 0x00002000, 0x0401f010, 0x0401ff83, - 0x59300017, 0x4801a006, 0x59300018, 0x4801a007, - 0x4a01a008, 0x00000400, 0x0401f008, 0x0401ff7b, - 0x59300017, 0x4801a006, 0x59300018, 0x4801a007, - 0x4a01a008, 0x00000200, 0x4979a009, 0x4979a00a, - 0x4979a00b, 0x4979a00c, 0x4979a00d, 0x42000800, - 0x00000008, 0x42001000, 0x0000dc00, 0x0401f2c0, - 0x0401fec6, 0x4a01a006, 0x02000014, 0x4979a407, - 0x4979a207, 0x59a8003a, 0x4801a008, 0x59a8003b, - 0x4801a009, 0x4a01a00a, 0x00047878, 0x42000800, - 0x00000005, 0x42001000, 0x0000dc00, 0x0401f2b0, - 0x0401feb6, 0x4a01a006, 0x02140018, 0x4a01a407, - 0x00000800, 0x5930001c, 0x82000d00, 0xff000000, - 0x900409c0, 0x4805a207, 0x82000500, 0x00ffffff, - 0x4801a00a, 0x4979a408, 0x4979a208, 0x4979a409, - 0x4979a209, 0x4979a00b, 0x42000800, 0x00000006, - 0x42001000, 0x0000dc00, 0x0401f299, 0x4933c857, - 0x4937c857, 0x4d380000, 0x4d1c0000, 0x42027000, - 0x00000035, 0x0201f800, 0x00109183, 0x04020022, - 0x0401fe88, 0x4a01a006, 0x13000000, 0x5932381e, - 0x591c0414, 0x8c000502, 0x02000800, 0x00100615, - 0x591c0019, 0x4801a005, 0x591c0406, 0x82000580, - 0x00000003, 0x04000007, 0x59300809, 0x58040002, - 0x82000500, 0x00ffffff, 0x4801a007, 0x0401f003, - 0x59a80010, 0x4801a007, 0x59300419, 0x4801a408, - 0x59300219, 0x4801a208, 0x42000800, 0x00000003, - 0x42001000, 0x0000dc00, 0x5c023800, 0x5c027000, - 0x0401f26f, 0x4803c856, 0x0201f800, 0x0010698c, - 0x598c000d, 0x81300580, 0x02020800, 0x00100615, - 0x0201f800, 0x001068f6, 0x0201f800, 0x000208b4, - 0x5c023800, 0x5c027000, 0x0201f000, 0x00106982, - 0x4803c856, 0x4d2c0000, 0x4d1c0000, 0x5932381e, - 0x811e39c0, 0x02000800, 0x00100615, 0x591c0c06, - 0x82040580, 0x00000006, 0x0400000d, 0x82040580, - 0x00000003, 0x04000036, 0x4a026403, 0x00000037, - 0x4a02641a, 0x00000003, 0x4a02621a, 0x00001700, - 0x5c023800, 0x5c025800, 0x0401f064, 0x0401f84b, - 0x42001000, 0x40000000, 0x591c0203, 0x591c0804, - 0x8c040d3e, 0x04020023, 0x82000c80, 0x0000000e, - 0x0c001003, 0x0201f800, 0x00100615, 0x00107410, - 0x0010741c, 0x00107412, 0x0010741c, 0x00107418, - 0x00107410, 0x00107410, 0x0010741c, 0x0010741c, - 0x00107410, 0x00107410, 0x00107410, 0x00107410, - 0x00107410, 0x0010741c, 0x00107410, 0x0010741c, - 0x0201f800, 0x00100615, 0x591c0414, 0x4803c857, - 0x8c000518, 0x04000003, 0x8c000512, 0x04000003, - 0x80001580, 0x0401f003, 0x42001000, 0x20000000, - 0x591c0015, 0x4801a00a, 0x0401f018, 0x0401f81f, - 0x591e5808, 0x812e59c0, 0x02000800, 0x00100615, - 0x592c100f, 0x591c0011, 0x80080480, 0x4801a00a, - 0x591c0203, 0x591c0804, 0x8c040d3e, 0x04020007, - 0x82000d80, 0x00000002, 0x04000007, 0x82000d80, - 0x00000004, 0x04000004, 0x42001000, 0x40000000, - 0x0401f002, 0x80001580, 0x4809a00b, 0x42000800, - 0x00000006, 0x42001000, 0x0000dc00, 0x5c023800, - 0x5c025800, 0x0401f1fe, 0x4803c856, 0x0401fe03, - 0x4a01a006, 0x02000000, 0x59300c19, 0x4805a407, - 0x59300a19, 0x4805a207, 0x59a81010, 0x59300809, - 0x58041802, 0x820c1d00, 0x00ffffff, 0x5930081e, - 0x58040406, 0x82000580, 0x00000003, 0x04020004, - 0x4809a008, 0x480da009, 0x0401f003, 0x480da008, - 0x4809a009, 0x1c01f000, 0x4803c856, 0x0401fdeb, - 0x0401f003, 0x4803c856, 0x0401fde1, 0x4a01a006, - 0x01000000, 0x5930041a, 0x4801a407, 0x5930021a, - 0x4801a207, 0x42000800, 0x00000002, 0x42001000, - 0x0000dc00, 0x0401f1d6, 0x4803c856, 0x4d1c0000, - 0x0401fdc5, 0x4a01a006, 0x14000000, 0x5932381e, - 0x591c0019, 0x4801a005, 0x59300419, 0x4801a407, - 0x59300219, 0x4801a207, 0x59300015, 0x4801a008, - 0x59300216, 0x82000500, 0x000000ff, 0x840001c0, - 0x4801a409, 0x42000800, 0x00000004, 0x42001000, - 0x0000dc00, 0x5c023800, 0x0401f1bd, 0x4803c856, - 0x0401f80b, 0x5930041a, 0x900001c0, 0x4801a005, - 0x0401f9f4, 0x41780800, 0x42001000, 0x00005c00, - 0x0401f9b3, 0x0201f000, 0x00105d86, 0x4803c856, - 0x59300817, 0x82041c00, 0x00000005, 0x46034800, - 0x00000021, 0x58040404, 0x82000500, 0x0000f000, - 0x82000580, 0x00003000, 0x04000003, 0x46034800, - 0x00000041, 0x81a5a000, 0x580c0001, 0x82000d00, - 0x00ffffff, 0x82040d40, 0xc2000000, 0x4805a000, - 0x580c0800, 0x82041500, 0x00ffffff, 0x82000500, - 0xff000000, 0x80080540, 0x4801a001, 0x580c0002, - 0x82000580, 0x00c00000, 0x82000500, 0x00fd0300, - 0x4801a002, 0x580c0003, 0x4801a003, 0x580c0404, - 0x4801a404, 0x580c0204, 0x4801a204, 0x1c01f000, - 0x4803c856, 0x59a80026, 0x82000500, 0x00000028, - 0x04020009, 0x59a80026, 0x82000500, 0x00000028, - 0x04000003, 0x497a6a12, 0x0401f003, 0x4a026a12, - 0x0000ff00, 0x42005000, 0x22000000, 0x42006000, - 0x01380000, 0x41786800, 0x41787800, 0x0401f952, - 0x59301008, 0x4a01a006, 0x54000000, 0x59a80010, - 0x82000500, 0x00ffffff, 0x58080c0a, 0x800408f0, - 0x80040540, 0x4801a007, 0x5808000a, 0x82000500, - 0xff000000, 0x4801a008, 0x59a80002, 0x4801a009, - 0x59a80003, 0x4801a00a, 0x59a80000, 0x4801a00b, - 0x59a80001, 0x4801a00c, 0x5808000c, 0x9c0001c0, - 0x4801a00d, 0x5808000d, 0x9c0001c0, 0x4801a00e, - 0x5808000e, 0x9c0001c0, 0x4801a00f, 0x5808000f, - 0x9c0001c0, 0x4801a010, 0x58080010, 0x9c0001c0, - 0x4801a011, 0x58080011, 0x9c0001c0, 0x4801a012, - 0x58080012, 0x9c0001c0, 0x4801a013, 0x58080013, - 0x9c0001c0, 0x4801a014, 0x58080010, 0x9c0001c0, - 0x4801a015, 0x58080011, 0x9c0001c0, 0x4801a016, - 0x58080012, 0x9c0001c0, 0x4801a017, 0x58080013, - 0x9c0001c0, 0x4801a018, 0x42000800, 0x00000013, - 0x42001000, 0x0000dc00, 0x0401f135, 0x4803c856, - 0x42005000, 0x22000000, 0x42006000, 0x01290000, - 0x41786800, 0x41787800, 0x0401f90b, 0x59301008, - 0x4a01a006, 0x55000000, 0x5808000b, 0x82000500, - 0x00ffffff, 0x58080c0a, 0x800408f0, 0x80040540, - 0x4801a007, 0x5808080a, 0x82040d00, 0xff000000, - 0x59a80010, 0x82000500, 0x00ffffff, 0x80040540, - 0x4801a008, 0x5808000c, 0x9c0001c0, 0x4801a009, - 0x5808000d, 0x9c0001c0, 0x4801a00a, 0x5808000e, - 0x9c0001c0, 0x4801a00b, 0x5808000f, 0x9c0001c0, - 0x4801a00c, 0x59a80002, 0x4801a00d, 0x59a80003, - 0x4801a00e, 0x59a80000, 0x4801a00f, 0x59a80001, - 0x4801a010, 0x58080010, 0x4801a011, 0x58080011, - 0x4801a012, 0x58080012, 0x4801a013, 0x58080013, - 0x4801a014, 0x4979a015, 0x4979a016, 0x4979a017, - 0x4979a018, 0x42000800, 0x00000013, 0x42001000, - 0x0000dc00, 0x0401f0f6, 0x0401fcfc, 0x5930001c, - 0x800001c0, 0x04000008, 0x4a01a006, 0x01000000, - 0x4a01a407, 0x00000003, 0x42000800, 0x00000002, - 0x0401f028, 0x4a01a006, 0x02000000, 0x41780800, - 0x836c0580, 0x00000004, 0x04020003, 0x84040d42, - 0x0401f00d, 0x0201f800, 0x00104e0d, 0x04020003, - 0x84040d4a, 0x0401f002, 0x84040d48, 0x59a80026, - 0x8c000506, 0x04020003, 0x8c00050a, 0x04000002, - 0x84040d46, 0x4805a207, 0x59c40085, 0x48031004, - 0x4c580000, 0x4c500000, 0x4c540000, 0x4200b000, - 0x00000006, 0x8388a400, 0x00000000, 0x82d0ac00, - 0x00000008, 0x0201f800, 0x0010a93e, 0x5c00a800, - 0x5c00a000, 0x5c00b000, 0x42000800, 0x00000008, - 0x42001000, 0x0000dc00, 0x0401f0c1, 0x0401fcb9, - 0x4a01a006, 0x56000000, 0x59340006, 0x4801a007, - 0x59340007, 0x4801a008, 0x42000800, 0x00000003, - 0x42001000, 0x0000dc00, 0x0401f0b5, 0x4803c856, - 0x0401fcba, 0x5930081c, 0x800409c0, 0x0400000e, - 0x82040580, 0x0000ffff, 0x04000004, 0x82040480, - 0x00000007, 0x04021008, 0x4a01a006, 0x01000000, - 0x4a01a407, 0x00000003, 0x42000800, 0x00000002, - 0x0401f012, 0x4a01a006, 0x0200001c, 0x4a01a007, - 0x00000001, 0x42001000, 0x0010b2ec, 0x50080000, - 0x9c0001c0, 0x4801a009, 0x59a80010, 0x4801a00a, - 0x59a80002, 0x59a80803, 0x4801a00b, 0x4805a00c, - 0x42000800, 0x00000007, 0x42001000, 0x0000dc00, - 0x0401f08f, 0x4d2c0000, 0x0401fc86, 0x59325808, - 0x592c0008, 0x82000500, 0x00ffffff, 0x4801a001, - 0x4a01a006, 0x51000000, 0x5c025800, 0x0201f000, - 0x001070bc, 0x4803c856, 0x59a80810, 0x82040d00, - 0x000000ff, 0x59325808, 0x59326809, 0x59a83026, - 0x8c18350a, 0x04020008, 0x8c00050e, 0x04020006, - 0x80001d80, 0x59a82010, 0x82102500, 0x000000ff, - 0x0401f001, 0x59300406, 0x4803c857, 0x82000d80, - 0x00000009, 0x04000006, 0x82000d80, 0x0000000a, - 0x0400002e, 0x0201f800, 0x00100615, 0x59300015, - 0x8c00051e, 0x04020020, 0x42005000, 0x04000000, - 0x42006000, 0x05000000, 0x592c040a, 0x82000500, - 0x00000030, 0x800000e0, 0x80306540, 0x5934000a, - 0x8c000508, 0x04000002, 0x84306546, 0x41786800, - 0x41787800, 0x0401f831, 0x59300c14, 0x80040000, - 0x48026414, 0x40040000, 0x800000d0, 0x82000540, - 0x00000020, 0x4801a403, 0x83180d40, 0x00000038, - 0x42001000, 0x0000c920, 0x0401f868, 0x0201f000, - 0x00105d8b, 0x59a80026, 0x82000500, 0x00000028, - 0x04000003, 0x497a6a12, 0x0401f7dc, 0x4a026a12, - 0x0000ff00, 0x0401f7d9, 0x42005000, 0x02000000, - 0x42006000, 0x20290000, 0x41786800, 0x41787800, - 0x0401f812, 0x83180d40, 0x00000038, 0x42001000, - 0x0000c9a0, 0x0401f851, 0x42000800, 0x000007d0, - 0x59300011, 0x82000500, 0xfff00000, 0x80000540, - 0x04000003, 0x42000800, 0x00001b58, 0x41781000, - 0x0201f000, 0x00105d8d, 0x4201a000, 0x00000000, - 0x0401f003, 0x4201a000, 0x00000011, 0x59340a12, - 0x82040d00, 0x0000ff00, 0x59a80010, 0x82000500, - 0x000000ff, 0x900001c0, 0x80040540, 0x80d00540, - 0x44034800, 0x81a5a000, 0x59340002, 0x82000500, - 0x00ffffff, 0x80280540, 0x4801a000, 0x59a80010, - 0x4801a001, 0x4831a002, 0x82340540, 0x00000000, - 0x4801a003, 0x59300402, 0x4801a404, 0x59300a02, - 0x4805a204, 0x8c30652e, 0x04000003, 0x4805a404, - 0x4801a204, 0x483da005, 0x1c01f000, 0x4807c857, - 0x4c040000, 0x0401f82a, 0x5c000800, 0x40040000, - 0x80081540, 0x800000c4, 0x82000540, 0x00002000, - 0x4803910a, 0x59b400f6, 0x82000500, 0x00000018, - 0x040207fd, 0x4a0368f0, 0x0010b342, 0x42001800, - 0x0010b343, 0x580c0000, 0x4803c857, 0x580c0002, - 0x4803c857, 0x580c0004, 0x4803c857, 0x4a0368f1, - 0x0010b349, 0x480b68f3, 0x4a0378e4, 0x00008000, - 0x0201f000, 0x00105d86, 0x4807c857, 0x480a2800, - 0x4c040000, 0x0401f80a, 0x5c000800, 0x59b400f6, - 0x8c00050a, 0x040207fe, 0x49a768f2, 0x480768f4, - 0x4a0378e4, 0x00008000, 0x1c01f000, 0x4a0378e4, - 0x0000c000, 0x59bc00e4, 0x8c000520, 0x0400000c, - 0x4a0378e4, 0x00008000, 0x42007000, 0x000003e8, - 0x59bc00e4, 0x8c000520, 0x040007f5, 0x80387040, - 0x02000800, 0x00100615, 0x0401f7fa, 0x1c01f000, - 0x82000500, 0xffff0000, 0x82000580, 0x01050000, - 0x0402000d, 0x599c0818, 0x8c040d10, 0x0400000a, - 0x59a80807, 0x8c040d0a, 0x04000007, 0x42001000, - 0x0000804f, 0x41781800, 0x41782000, 0x0201f800, - 0x00103857, 0x1c01f000, 0x41781000, 0x42026000, - 0x0010cfc0, 0x59a8180e, 0x480a6402, 0x4a026202, - 0x0000ffff, 0x80081000, 0x800c1840, 0x04000004, - 0x83326400, 0x00000024, 0x0401f7f8, 0x1c01f000, - 0x4933c857, 0x59300203, 0x82000580, 0x00000000, - 0x0400002c, 0x59300406, 0x4803c857, 0x82000d80, - 0x00000004, 0x04000011, 0x82000d80, 0x00000001, - 0x0400000e, 0x82000d80, 0x00000003, 0x04000006, - 0x82000d80, 0x00000006, 0x04020011, 0x0201f800, - 0x0010a3fa, 0x5930001c, 0x800001c0, 0x02020800, - 0x0010961a, 0x0401f00a, 0x5930081e, 0x4807c857, - 0x800409c0, 0x04000006, 0x5804001c, 0x4803c857, - 0x81300580, 0x04020002, 0x4978081c, 0x497a6008, - 0x4a026004, 0x00004000, 0x59a80037, 0x82000c80, - 0x00000051, 0x04001002, 0x80000102, 0x48026206, - 0x497a6205, 0x497a6009, 0x4a026406, 0x00000007, - 0x1c01f000, 0x8166c9c0, 0x0400001c, 0x41626000, - 0x41580000, 0x59300a03, 0x82040d80, 0x00000000, - 0x04000008, 0x83326400, 0x00000024, 0x81300c80, - 0x040017f9, 0x42026000, 0x0010cfc0, 0x0401f7f6, - 0x4933c857, 0x8166c840, 0x83300c00, 0x00000024, - 0x80040480, 0x04021006, 0x4006c000, 0x4a026203, - 0x00000008, 0x813261c0, 0x1c01f000, 0x4202c000, - 0x0010cfc0, 0x0401f7fa, 0x42000000, 0x0010b653, - 0x0201f800, 0x0010a86e, 0x4933c856, 0x417a6000, - 0x0401f7f5, 0x4933c857, 0x83380580, 0x00000013, - 0x0402000b, 0x59300004, 0x8c00053e, 0x04000007, - 0x0201f800, 0x0010698c, 0x0201f800, 0x001068f6, - 0x0201f800, 0x00106982, 0x1c01f000, 0x4933c857, - 0x59880053, 0x80000000, 0x48031053, 0x1c01f000, - 0x4933c857, 0x59300203, 0x82003480, 0x0000000e, - 0x02021800, 0x00100615, 0x4d2c0000, 0x0c01f803, - 0x5c025800, 0x1c01f000, 0x00107718, 0x00107c84, - 0x00107dd4, 0x00107718, 0x00107e3a, 0x0010787c, - 0x00107718, 0x00107718, 0x00107c1a, 0x00107718, - 0x00107718, 0x00107718, 0x00107718, 0x00107718, - 0x0201f800, 0x00100615, 0x4933c857, 0x59300203, - 0x82003480, 0x0000000e, 0x02021800, 0x00100615, - 0x0c01f001, 0x0010772f, 0x001087f0, 0x0010772f, - 0x0010772f, 0x0010772f, 0x0010772f, 0x0010772f, - 0x0010772f, 0x0010879a, 0x0010880c, 0x0010887a, - 0x0010880c, 0x0010887a, 0x0010772f, 0x0201f800, - 0x00100615, 0x0201f800, 0x00100615, 0x4933c857, - 0x4d2c0000, 0x59325808, 0x59300203, 0x82003480, - 0x0000000e, 0x02021800, 0x00100615, 0x0c01f803, - 0x5c025800, 0x1c01f000, 0x0010774c, 0x0010774c, - 0x0010774c, 0x00107768, 0x001077b4, 0x0010774c, - 0x0010774c, 0x0010774c, 0x0010774e, 0x0010774c, - 0x0010774c, 0x0010774c, 0x0010774c, 0x0010774c, - 0x0201f800, 0x00100615, 0x4933c857, 0x83380580, - 0x00000040, 0x02020800, 0x00100615, 0x4a026007, - 0x00082000, 0x4a026203, 0x00000003, 0x493a6403, - 0x4a025c08, 0x00000001, 0x592c000d, 0x48026011, - 0x497a6013, 0x592c0208, 0x800000c2, 0x800010c4, - 0x80081400, 0x480a6206, 0x0201f800, 0x00100f9c, - 0x42000800, 0x80000060, 0x0201f000, 0x00106466, - 0x4933c857, 0x83380480, 0x00000050, 0x02021800, - 0x00100615, 0x83380480, 0x00000049, 0x02001800, - 0x00100615, 0x0c01f001, 0x0010777b, 0x00107786, - 0x00107779, 0x00107779, 0x00107779, 0x00107779, - 0x00107791, 0x0201f800, 0x00100615, 0x4a026203, - 0x00000004, 0x4a025c08, 0x00000002, 0x592c0207, - 0x48025c09, 0x592c0209, 0x48025a07, 0x592c000c, - 0x4802580d, 0x1c01f000, 0x0201f800, 0x001068c1, - 0x0201f800, 0x00108df4, 0x04000005, 0x4a025a06, - 0x00000006, 0x0201f800, 0x00020381, 0x0201f000, - 0x000208b4, 0x0201f800, 0x001068c1, 0x4d3c0000, - 0x417a7800, 0x0201f800, 0x00101de2, 0x5c027800, - 0x42003000, 0x00000014, 0x41782800, 0x42002000, - 0x00000002, 0x4d400000, 0x4d440000, 0x59368c03, - 0x42028000, 0x00000029, 0x0201f800, 0x0010962a, - 0x5c028800, 0x5c028000, 0x42000000, 0x0010b663, - 0x0201f800, 0x0010a86e, 0x0201f800, 0x00108df4, - 0x02000000, 0x000208b4, 0x4a025a06, 0x00000029, - 0x0201f800, 0x00020381, 0x0201f000, 0x000208b4, - 0x4933c857, 0x83380580, 0x00000048, 0x04000005, - 0x83380580, 0x00000053, 0x02020800, 0x00100615, - 0x592c0206, 0x82000580, 0x00000007, 0x04000009, - 0x59300011, 0x80000540, 0x04000006, 0x592c080c, - 0x80040480, 0x4802580c, 0x4a025a06, 0x00000015, - 0x592c0206, 0x80000540, 0x04020003, 0x4a025a06, - 0x00000000, 0x0201f800, 0x00020381, 0x0201f000, - 0x000208b4, 0x4933c857, 0x4d2c0000, 0x4c500000, - 0x4c540000, 0x4c580000, 0x0201f800, 0x0010082a, - 0x02000800, 0x00100615, 0x497a5a06, 0x59a8006e, - 0x82000500, 0x0000f000, 0x48025c07, 0x59a80816, - 0x82040c00, 0x00000018, 0x48065a07, 0x412c7800, - 0x4d2c0000, 0x41cca000, 0x42002800, 0x00000001, - 0x42001000, 0x0000002c, 0x82040480, 0x0000002d, - 0x04021006, 0x832cac00, 0x00000009, 0x0201f800, - 0x0010894a, 0x0401f02e, 0x40043000, 0x42000800, - 0x0000002c, 0x832cac00, 0x00000009, 0x0201f800, - 0x0010894a, 0x82183480, 0x0000002c, 0x0201f800, - 0x0010082a, 0x0400001a, 0x80142800, 0x4a025804, - 0x00000110, 0x492c7801, 0x82180c80, 0x0000003d, - 0x04021007, 0x40180800, 0x832cac00, 0x00000005, - 0x0201f800, 0x0010894a, 0x0401f015, 0x82081400, - 0x0000003c, 0x82183480, 0x0000003c, 0x42000800, - 0x0000003c, 0x412c7800, 0x832cac00, 0x00000005, - 0x0201f800, 0x0010894a, 0x0401f7e5, 0x5c025800, - 0x592c0206, 0x8400055e, 0x48025a06, 0x592c0407, - 0x80080540, 0x48025c07, 0x0401f002, 0x5c025800, - 0x813669c0, 0x04000003, 0x59343403, 0x0401f003, - 0x42003000, 0x0000ffff, 0x49325808, 0x481a5c06, - 0x82100580, 0x00000054, 0x04020002, 0x491e5813, - 0x841401c0, 0x80100540, 0x48025804, 0x592c0001, - 0x497a5801, 0x4c000000, 0x0201f800, 0x00020381, - 0x5c025800, 0x812e59c0, 0x040207f9, 0x5c00b000, - 0x5c00a800, 0x5c00a000, 0x5c025800, 0x1c01f000, - 0x4803c856, 0x4c5c0000, 0x4d2c0000, 0x4c500000, - 0x4c540000, 0x4c580000, 0x412cb800, 0x592c040b, - 0x8c000516, 0x04000003, 0x41cca000, 0x0401f003, - 0x83cca400, 0x00000006, 0x4008b000, 0x41781000, - 0x82580480, 0x00000012, 0x04001004, 0x4200b000, - 0x00000012, 0x40001000, 0x4c080000, 0x4d2c0000, - 0x0201f800, 0x0010082a, 0x04000023, 0x5c001800, - 0x492c1801, 0x485a5800, 0x832cac00, 0x00000002, - 0x0201f800, 0x0010a94f, 0x585c040b, 0x8c000500, - 0x0400000e, 0x832c1400, 0x00000002, 0x8c000516, - 0x04000003, 0x82081400, 0x00000006, 0x46001000, - 0x00000001, 0x80081000, 0x46001000, 0x00000900, - 0x84000500, 0x4800bc0b, 0x5c001000, 0x800811c0, - 0x040207da, 0x82000540, 0x00000001, 0x5c00b000, - 0x5c00a800, 0x5c00a000, 0x5c025800, 0x5c00b800, - 0x1c01f000, 0x5c025800, 0x5c001000, 0x0401f7f8, - 0x4933c857, 0x83380d80, 0x00000015, 0x04020003, - 0x0201f000, 0x000208b4, 0x83380d80, 0x00000016, - 0x02020800, 0x00100615, 0x0201f000, 0x000208b4, - 0x4933c857, 0x4d2c0000, 0x4c500000, 0x4c540000, - 0x4c580000, 0x59325808, 0x83cca400, 0x00000006, - 0x59cc1806, 0x820c0580, 0x01000000, 0x04020004, - 0x4200b000, 0x00000002, 0x0401f00f, 0x4200b000, - 0x00000008, 0x832cac00, 0x00000005, 0x0201f800, - 0x0010a93e, 0x8c0c1d00, 0x0400000b, 0x4200b000, - 0x00000008, 0x592e5801, 0x812e59c0, 0x02000800, - 0x00100615, 0x832cac00, 0x00000005, 0x0201f800, - 0x0010a93e, 0x0401f816, 0x5c00b000, 0x5c00a800, - 0x5c00a000, 0x5c025800, 0x1c01f000, 0x4933c857, - 0x4c500000, 0x4c540000, 0x4c580000, 0x83cca400, - 0x00000006, 0x5930a808, 0x8254ac00, 0x00000005, - 0x4200b000, 0x00000007, 0x0201f800, 0x0010a93e, - 0x5c00b000, 0x5c00a800, 0x5c00a000, 0x4933c857, - 0x0201f800, 0x00108df4, 0x02000000, 0x000208b4, - 0x4d2c0000, 0x0201f800, 0x00109360, 0x0402000b, - 0x41780800, 0x4d400000, 0x42028000, 0x00000000, - 0x0201f800, 0x00109204, 0x5c028000, 0x5c025800, - 0x0201f000, 0x000208b4, 0x5931d821, 0x58ef400b, - 0x58ee580d, 0x4a025a04, 0x00000103, 0x58ec0009, - 0x0801f800, 0x5c025800, 0x0201f000, 0x000208b4, - 0x4933c857, 0x59cc1806, 0x820c0580, 0x02000000, - 0x04020014, 0x4a026802, 0x00fffffd, 0x5934000a, - 0x84000504, 0x4802680a, 0x59300808, 0x800409c0, - 0x02000000, 0x000208b4, 0x4a000a04, 0x00000103, - 0x480c0805, 0x5931d821, 0x58ef400b, 0x58ee580d, - 0x58ec0009, 0x0801f800, 0x0201f000, 0x000208b4, - 0x42000000, 0x0010b66b, 0x0201f800, 0x0010a86e, - 0x4c0c0000, 0x0401f804, 0x5c001800, 0x040207eb, - 0x1c01f000, 0x4933c857, 0x4d2c0000, 0x59325808, - 0x812e59c0, 0x04020009, 0x497a6206, 0x497a6205, - 0x4d380000, 0x42027000, 0x00000022, 0x0401fb77, - 0x5c027000, 0x80000580, 0x5c025800, 0x1c01f000, - 0x4933c857, 0x4d2c0000, 0x4c500000, 0x4c540000, - 0x4c580000, 0x59325808, 0x592e5801, 0x832cac00, - 0x00000005, 0x83cca400, 0x00000006, 0x59a8086e, - 0x82040d00, 0x000003ff, 0x82041480, 0x0000000f, - 0x0400101b, 0x4200b000, 0x0000000f, 0x0201f800, - 0x0010a93e, 0x592e5801, 0x832cac00, 0x00000005, - 0x82080c80, 0x0000000f, 0x0400100d, 0x4200b000, - 0x0000000f, 0x0201f800, 0x0010a93e, 0x592e5801, - 0x832cac00, 0x00000005, 0x82041480, 0x0000000f, - 0x04001007, 0x42001000, 0x0000000f, 0x4008b000, - 0x0201f800, 0x0010a93e, 0x0401f004, 0x4004b000, - 0x0201f800, 0x0010a93e, 0x5931d821, 0x58ef400b, - 0x58ee580d, 0x4a025a04, 0x00000103, 0x592e5801, - 0x58ec0009, 0x0801f800, 0x0201f800, 0x000208b4, - 0x5c00b000, 0x5c00a800, 0x5c00a000, 0x5c025800, - 0x1c01f000, 0x4933c857, 0x4d2c0000, 0x4c500000, - 0x4c540000, 0x4c580000, 0x59cc0006, 0x82000d80, - 0x01000000, 0x0400002c, 0x59cc0007, 0x9000b1c0, - 0x8258b500, 0x000000ff, 0x8058b104, 0x8258b400, - 0x00000002, 0x82580c80, 0x00000007, 0x04001003, - 0x4200b000, 0x00000006, 0x83cca400, 0x00000006, - 0x59301008, 0x800811c0, 0x02000800, 0x00100615, - 0x8208ac00, 0x00000005, 0x0201f800, 0x0010a93e, - 0x82000d00, 0xff000000, 0x800409c0, 0x04000019, - 0x8200b500, 0x000000ff, 0x8058b104, 0x82580c80, - 0x0000000e, 0x04001003, 0x4200b000, 0x0000000d, - 0x58081001, 0x800811c0, 0x02000800, 0x00100615, - 0x8208ac00, 0x00000005, 0x0201f800, 0x0010a93e, - 0x0401f008, 0x59301008, 0x800811c0, 0x02000800, - 0x00100615, 0x48001005, 0x59cc0007, 0x48001006, - 0x0401ff3b, 0x5c00b000, 0x5c00a800, 0x5c00a000, - 0x5c025800, 0x1c01f000, 0x4933c857, 0x42000800, - 0x00000000, 0x59cc0006, 0x82000580, 0x02000000, - 0x04000003, 0x42000800, 0x00000001, 0x4d2c0000, - 0x59325808, 0x812e59c0, 0x02000800, 0x00100615, - 0x48065a06, 0x0201f800, 0x00020381, 0x5c025800, - 0x0201f000, 0x000208b4, 0x4933c857, 0x4d2c0000, - 0x4c500000, 0x4c540000, 0x4c580000, 0x4200b000, - 0x00000002, 0x59cc0806, 0x82040580, 0x01000000, - 0x04000004, 0x8204b500, 0x0000ffff, 0x8058b104, - 0x83cca400, 0x00000006, 0x59300008, 0x8200ac00, - 0x00000005, 0x0201f800, 0x0010a93e, 0x0401ff0c, - 0x5c00b000, 0x5c00a800, 0x5c00a000, 0x5c025800, - 0x1c01f000, 0x4933c857, 0x4803c857, 0x4807c857, - 0x480bc857, 0x480fc857, 0x4813c857, 0x481bc857, - 0x492fc857, 0x4d2c0000, 0x4c000000, 0x0201f800, - 0x00100819, 0x5c000000, 0x0400000f, 0x48025803, - 0x5c000000, 0x4802580a, 0x4c000000, 0x481a5801, - 0x48125809, 0x48065804, 0x480a5807, 0x480e5808, - 0x412c1000, 0x0201f800, 0x001008a1, 0x82000540, - 0x00000001, 0x5c025800, 0x1c01f000, 0x4933c857, - 0x4d1c0000, 0x59cc0001, 0x82000500, 0x00ffffff, - 0x59341002, 0x82081500, 0x00ffffff, 0x80080580, - 0x0402001f, 0x497a6205, 0x4d380000, 0x42027000, - 0x00000035, 0x0201f800, 0x00109183, 0x5c027000, - 0x04020012, 0x591c001c, 0x800001c0, 0x0400000f, - 0x497a381c, 0x591c0414, 0x8c000502, 0x02000800, - 0x00100615, 0x84000502, 0x48023c14, 0x591c1406, - 0x82080580, 0x00000003, 0x04000006, 0x82080580, - 0x00000006, 0x04000005, 0x0401fc9e, 0x0401f004, - 0x0401f805, 0x0401f002, 0x0401f8c0, 0x5c023800, - 0x1c01f000, 0x4d2c0000, 0x591e5808, 0x4933c857, - 0x491fc857, 0x493bc857, 0x492fc857, 0x83380580, - 0x00000015, 0x040000b3, 0x83380580, 0x00000016, - 0x040200ae, 0x4d300000, 0x411e6000, 0x59cc0207, - 0x4803c857, 0x82000d00, 0x0000ff00, 0x82040580, - 0x00001700, 0x04000004, 0x82040580, 0x00000300, - 0x0402005b, 0x591c0203, 0x4803c857, 0x82000580, - 0x0000000d, 0x0400003f, 0x812e59c0, 0x0400009a, - 0x591c0202, 0x4803c857, 0x82000580, 0x0000ffff, - 0x0402007e, 0x592c020a, 0x4803c857, 0x82000500, - 0x00000003, 0x82000580, 0x00000002, 0x04020007, - 0x592c080f, 0x591c0011, 0x4803c857, 0x4807c857, - 0x80040580, 0x04020071, 0x591c0414, 0x4803c857, - 0x8c000500, 0x0402006d, 0x41780800, 0x591c1206, - 0x42000000, 0x0000000a, 0x0201f800, 0x001063ee, - 0x592c0406, 0x4803c857, 0x800001c0, 0x0400000c, - 0x80080c80, 0x04001004, 0x02020800, 0x00100615, - 0x80001040, 0x480a5c06, 0x800811c0, 0x04020004, - 0x0201f800, 0x00108b3c, 0x0401f06b, 0x0201f800, - 0x00108ee7, 0x591c0817, 0x591c0018, 0x48065808, - 0x48025809, 0x59300007, 0x8c000500, 0x02020800, - 0x00100ee4, 0x497a3808, 0x0201f800, 0x000201ee, - 0x0402004a, 0x411e6000, 0x0401fc3e, 0x0401f05a, - 0x0401fc6d, 0x04000013, 0x49366009, 0x4a026406, - 0x00000003, 0x492e6008, 0x591c0817, 0x591c1018, - 0x48066017, 0x480a6018, 0x4d380000, 0x591e7403, - 0x4d300000, 0x411e6000, 0x0401fc2e, 0x5c026000, - 0x0201f800, 0x000208d8, 0x5c027000, 0x0401f046, - 0x59a80039, 0x48023a05, 0x0401f043, 0x59cc0407, - 0x82000580, 0x0000000b, 0x04020025, 0x59340a00, - 0x84040d0e, 0x48066a00, 0x592c0a04, 0x82040d00, - 0x000000ff, 0x82040d80, 0x00000014, 0x04000003, - 0x4a02621d, 0x00000003, 0x59300007, 0x8c000500, - 0x02020800, 0x00100ee4, 0x4d400000, 0x42028000, - 0x00000003, 0x592c0a08, 0x0201f800, 0x00104bee, - 0x0201f800, 0x00020381, 0x5c028000, 0x497a6008, - 0x4a026403, 0x00000085, 0x4a026203, 0x00000009, - 0x4a026406, 0x00000002, 0x42000800, 0x8000404b, - 0x0201f800, 0x00020855, 0x0401f01b, 0x59cc0207, - 0x82000580, 0x00002a00, 0x04020004, 0x59a80039, - 0x48023a05, 0x0401f014, 0x812e59c0, 0x02000800, - 0x00100615, 0x4a025a04, 0x00000103, 0x591c0007, - 0x8c000500, 0x02020800, 0x00100ee4, 0x591c0402, - 0x48025c06, 0x4a025a06, 0x00000003, 0x0201f800, - 0x00020381, 0x0201f800, 0x00107698, 0x0201f800, - 0x00104801, 0x5c026000, 0x0201f800, 0x000208b4, - 0x0401f002, 0x5c026000, 0x5c025800, 0x1c01f000, - 0x0401f819, 0x0401f7fd, 0x4933c857, 0x83380580, - 0x00000015, 0x04020004, 0x59a80039, 0x48023a05, - 0x0401f00d, 0x83380580, 0x00000016, 0x0402000d, - 0x4d300000, 0x411e6000, 0x0201f800, 0x0010a3fa, - 0x0201f800, 0x00020831, 0x0201f800, 0x000208b4, - 0x5c026000, 0x497a381c, 0x0201f800, 0x000208b4, - 0x1c01f000, 0x591c0414, 0x84000540, 0x48023c14, - 0x59cc100b, 0x4933c857, 0x491fc857, 0x492fc857, - 0x4803c857, 0x480bc857, 0x8c08153c, 0x04000006, - 0x59a80039, 0x48023a05, 0x497a381c, 0x0201f000, - 0x000208b4, 0x4d300000, 0x411e6000, 0x0201f800, - 0x0010898b, 0x5c026000, 0x591c0406, 0x82000580, - 0x00000000, 0x02000000, 0x000208b4, 0x591c0403, - 0x82000580, 0x00000050, 0x0402000d, 0x4d300000, - 0x411e6000, 0x4a026203, 0x00000001, 0x42000800, - 0x80000043, 0x0201f800, 0x00020855, 0x5c026000, - 0x497a381c, 0x0201f000, 0x000208b4, 0x591c0203, - 0x82000580, 0x0000000d, 0x04000014, 0x812e59c0, - 0x02000800, 0x00100615, 0x591c0203, 0x82000580, - 0x00000004, 0x04020011, 0x592c020a, 0x8c000502, - 0x0400000e, 0x4a023812, 0x0fffffff, 0x592c0208, - 0x8400051e, 0x48025a08, 0x42000000, 0x00000001, - 0x48023a14, 0x0401f021, 0x42000000, 0x00000007, - 0x48023a14, 0x0401f01d, 0x592c020a, 0x4803c857, - 0x8c000500, 0x0402000b, 0x8c000502, 0x040007f7, - 0x591c0414, 0x8c00051c, 0x040207eb, 0x591c0011, - 0x4803c857, 0x800001c0, 0x040007f0, 0x0401f7e6, - 0x8c08153a, 0x040207ed, 0x59cc000a, 0x592c180f, - 0x4803c857, 0x480fc857, 0x800c0580, 0x040007e7, - 0x59cc000a, 0x4803c857, 0x48023816, 0x42000000, - 0x00000005, 0x48023a14, 0x0201f000, 0x0010901b, - 0x4933c857, 0x4d1c0000, 0x59cc0001, 0x59341002, - 0x80080580, 0x82000500, 0x00ffffff, 0x04020041, - 0x59301419, 0x0201f800, 0x001091d9, 0x02000800, - 0x00100615, 0x591c1406, 0x82080580, 0x00000007, - 0x04000038, 0x82080580, 0x00000002, 0x04000035, - 0x82080580, 0x00000000, 0x04000032, 0x591c0202, - 0x82000d80, 0x0000ffff, 0x04000004, 0x59301a19, - 0x800c0580, 0x0402002b, 0x83380580, 0x00000015, - 0x04000026, 0x4d300000, 0x4d2c0000, 0x411e6000, - 0x59325808, 0x0201f800, 0x00108df4, 0x02000800, - 0x00100615, 0x592c0204, 0x82000500, 0x000000ff, - 0x82000580, 0x00000014, 0x04000003, 0x4a02621d, - 0x00000003, 0x42028000, 0x00000003, 0x592c0a08, - 0x0201f800, 0x00104bee, 0x0201f800, 0x00020381, - 0x5c025800, 0x497a6008, 0x4a026403, 0x00000085, - 0x4a026203, 0x00000009, 0x4a026406, 0x00000002, - 0x42000800, 0x8000404b, 0x0201f800, 0x00020855, - 0x5c026000, 0x0401f003, 0x59a80039, 0x48023a05, - 0x497a381c, 0x0201f800, 0x000208b4, 0x5c023800, - 0x1c01f000, 0x4933c857, 0x4c580000, 0x4d2c0000, - 0x59325808, 0x83383580, 0x00000015, 0x04000010, - 0x59342200, 0x84102502, 0x48126a00, 0x0201f800, - 0x00108df4, 0x04000066, 0x0201f800, 0x00109360, - 0x04020005, 0x4200b000, 0x00000002, 0x0201f800, - 0x00109346, 0x0401fa0d, 0x0401f079, 0x83cc1400, - 0x00000008, 0x4200b000, 0x00000002, 0x83341c00, - 0x00000006, 0x0201f800, 0x001082ff, 0x04020015, - 0x83cc1400, 0x0000000a, 0x4200b000, 0x00000002, - 0x83341c00, 0x00000008, 0x0201f800, 0x001082ff, - 0x0402000c, 0x0201f800, 0x00101e1b, 0x59342200, - 0x59cc1007, 0x800811c0, 0x04000003, 0x480a6801, - 0x84102542, 0x8410251a, 0x48126a00, 0x0401f05f, - 0x4d3c0000, 0x417a7800, 0x0201f800, 0x00101de2, - 0x5c027800, 0x42000000, 0x0010b663, 0x0201f800, - 0x0010a86e, 0x59340200, 0x84000558, 0x48026a00, - 0x4d300000, 0x0201f800, 0x00020892, 0x02000800, - 0x00100615, 0x49366009, 0x497a6008, 0x4a026406, - 0x00000001, 0x4a026403, 0x00000001, 0x42003000, - 0x00000003, 0x0201f800, 0x0010a766, 0x0201f800, - 0x0010393e, 0x04000011, 0x41782800, 0x42003000, - 0x00000001, 0x4d400000, 0x42028000, 0x00000029, - 0x0201f800, 0x0010a250, 0x5c028000, 0x4a026406, - 0x00000004, 0x4a026203, 0x00000007, 0x4a026420, - 0x00000001, 0x0401f009, 0x4a026203, 0x00000001, - 0x42000800, 0x0000000b, 0x0201f800, 0x001043c7, - 0x0201f800, 0x00106470, 0x5c026000, 0x0201f800, - 0x00108df4, 0x04000022, 0x0201f800, 0x00109360, - 0x04020022, 0x0401f9b1, 0x0401f01d, 0x4d3c0000, - 0x417a7800, 0x0201f800, 0x00101de2, 0x42000000, - 0x0010b663, 0x0201f800, 0x0010a86e, 0x59340200, - 0x84000558, 0x48026a00, 0x42003000, 0x00000003, - 0x41782800, 0x42002000, 0x00000005, 0x4d400000, - 0x4d440000, 0x59368c03, 0x42028000, 0x00000029, - 0x0201f800, 0x0010962a, 0x5c028800, 0x5c028000, - 0x5c027800, 0x0201f800, 0x00101e1b, 0x0201f800, - 0x000208b4, 0x0401f002, 0x0401fca9, 0x5c025800, - 0x5c00b000, 0x1c01f000, 0x4933c857, 0x41380000, - 0x83383480, 0x00000056, 0x02021800, 0x00100615, - 0x0c01f001, 0x00107c7e, 0x00107c79, 0x00107c7e, - 0x00107c7e, 0x00107c7e, 0x00107c7e, 0x00107c77, - 0x00107c77, 0x00107c77, 0x00107c77, 0x00107c77, - 0x00107c77, 0x00107c77, 0x00107c77, 0x00107c77, - 0x00107c77, 0x00107c77, 0x00107c77, 0x00107c77, - 0x00107c77, 0x00107c77, 0x00107c77, 0x00107c77, - 0x00107c77, 0x00107c77, 0x00107c77, 0x00107c77, - 0x00107c77, 0x00107c77, 0x00107c77, 0x00107c77, - 0x00107c7e, 0x00107c77, 0x00107c7e, 0x00107c7e, - 0x00107c77, 0x00107c77, 0x00107c77, 0x00107c77, - 0x00107c77, 0x00107c7e, 0x00107c77, 0x00107c77, - 0x00107c77, 0x00107c77, 0x00107c77, 0x00107c77, - 0x00107c77, 0x00107c77, 0x00107c77, 0x00107c7e, - 0x00107c7e, 0x00107c77, 0x00107c77, 0x00107c77, - 0x00107c77, 0x00107c77, 0x00107c77, 0x00107c77, - 0x00107c77, 0x00107c77, 0x00107c7e, 0x00107c77, - 0x00107c77, 0x00107c7e, 0x00107c7e, 0x00107c77, - 0x00107c7e, 0x00107c7e, 0x00107c77, 0x00107c77, - 0x00107c77, 0x00107c77, 0x00107c7e, 0x00107c77, - 0x00107c77, 0x00107c77, 0x00107c7e, 0x00107c77, - 0x00107c77, 0x00107c77, 0x00107c7e, 0x00107c77, - 0x00107c77, 0x00107c77, 0x00107c7e, 0x0201f800, - 0x00100615, 0x4a026203, 0x00000001, 0x493a6403, - 0x0201f000, 0x00106470, 0x4933c857, 0x4a026203, - 0x00000001, 0x493a6403, 0x0201f000, 0x00106470, - 0x59300403, 0x82003480, 0x00000056, 0x02021800, - 0x00100615, 0x83383580, 0x00000013, 0x04000096, - 0x83383580, 0x00000027, 0x0402004c, 0x4933c857, - 0x0201f800, 0x001068f6, 0x0201f800, 0x00108ef1, - 0x0400000b, 0x0201f800, 0x00108f05, 0x04000041, - 0x59300403, 0x82000d80, 0x00000022, 0x04020038, - 0x0401fc61, 0x0400003a, 0x0401f03a, 0x0201f800, - 0x00101e1b, 0x42000800, 0x00000007, 0x0201f800, - 0x001043c7, 0x0401f901, 0x4d440000, 0x59368c03, - 0x83440580, 0x000007fe, 0x04020008, 0x59a81026, - 0x84081540, 0x0201f800, 0x00104e0d, 0x04020002, - 0x8408154a, 0x480b5026, 0x42028000, 0x00000029, - 0x4d3c0000, 0x417a7800, 0x0201f800, 0x00101de2, - 0x5c027800, 0x836c0580, 0x00000003, 0x0400000c, - 0x59326809, 0x59340008, 0x800001c0, 0x04020008, - 0x59368c03, 0x4933c857, 0x4937c857, 0x4947c857, - 0x0201f800, 0x00104451, 0x0401f00c, 0x42000000, - 0x0010b663, 0x0201f800, 0x0010a86e, 0x42003000, - 0x00000015, 0x41782800, 0x42002000, 0x00000003, - 0x0201f800, 0x0010962a, 0x5c028800, 0x0201f800, - 0x001090ec, 0x0201f000, 0x000208b4, 0x1c01f000, - 0x0401f8ce, 0x0401f7fa, 0x83380580, 0x00000014, - 0x0400000c, 0x4933c857, 0x0201f800, 0x00106cb4, - 0x02020000, 0x001076fb, 0x59300203, 0x82000580, - 0x00000002, 0x040000ef, 0x0201f800, 0x00100615, - 0x4933c857, 0x0201f800, 0x001068f6, 0x4d3c0000, - 0x417a7800, 0x0201f800, 0x00101de2, 0x5c027800, - 0x42003000, 0x00000016, 0x41782800, 0x4d400000, - 0x4d440000, 0x59368c03, 0x42002000, 0x00000009, - 0x42028000, 0x00000029, 0x0201f800, 0x0010962a, - 0x5c028800, 0x5c028000, 0x42000000, 0x0010b663, - 0x0201f800, 0x0010a86e, 0x0201f800, 0x00108ef1, - 0x0402000c, 0x0201f800, 0x00101e1b, 0x0401f89f, - 0x59340c03, 0x82040580, 0x000007fe, 0x040207c8, - 0x59a80826, 0x84040d40, 0x48075026, 0x0401f7c4, - 0x0201f800, 0x00108f05, 0x04020003, 0x0401f893, - 0x0401f7bf, 0x59300403, 0x82000d80, 0x00000032, - 0x04020004, 0x0201f800, 0x001020b2, 0x0401f7b8, - 0x59300403, 0x82000d80, 0x00000022, 0x04000887, - 0x0401f7b3, 0x4933c857, 0x4803c857, 0x0c01f001, - 0x00107da0, 0x00107da0, 0x00107da0, 0x00107da0, - 0x00107da0, 0x00107da0, 0x00107d7a, 0x00107d7a, - 0x00107d7a, 0x00107d7a, 0x00107d7a, 0x00107d7a, - 0x00107d7a, 0x00107d7a, 0x00107d7a, 0x00107d7a, - 0x00107d7a, 0x00107d7a, 0x00107d7a, 0x00107d7a, - 0x00107d7a, 0x00107d7a, 0x00107d7a, 0x00107d7a, - 0x00107d7a, 0x00107d7a, 0x00107d7a, 0x00107d7a, - 0x00107d7a, 0x00107d7a, 0x00107d83, 0x00107da0, - 0x00107d7a, 0x00107da0, 0x00107da0, 0x00107d7a, - 0x00107d7a, 0x00107d7a, 0x00107d7a, 0x00107d7a, - 0x00107da0, 0x00107da0, 0x00107d7a, 0x00107d7a, - 0x00107d7a, 0x00107d7a, 0x00107d7a, 0x00107d7a, - 0x00107d7a, 0x00107d7a, 0x00107d91, 0x00107da0, - 0x00107d7a, 0x00107d8a, 0x00107d7a, 0x00107d7a, - 0x00107d7a, 0x00107d8a, 0x00107d7a, 0x00107d7a, - 0x00107d7a, 0x00107da0, 0x00107d8d, 0x00107d7a, - 0x00107d7c, 0x00107da0, 0x00107d7a, 0x00107da0, - 0x00107da0, 0x00107d7a, 0x00107d7a, 0x00107d7a, - 0x00107d7a, 0x00107da0, 0x00107d7a, 0x00107d7a, - 0x00107d7a, 0x00107da0, 0x00107d7a, 0x00107d7a, - 0x00107d7a, 0x00107da0, 0x00107d7a, 0x00107d7a, - 0x00107d7a, 0x00107da0, 0x0201f800, 0x00100615, - 0x4d2c0000, 0x59325808, 0x0201f800, 0x00020381, - 0x5c025800, 0x0201f000, 0x000208b4, 0x4a026203, - 0x00000005, 0x59a80039, 0x48026205, 0x59a80037, - 0x48026206, 0x1c01f000, 0x5930081e, 0x49780a05, - 0x0401f014, 0x0201f800, 0x001090ec, 0x0201f000, - 0x000208b4, 0x0201f800, 0x001020b2, 0x0201f800, - 0x0010698c, 0x04000005, 0x0201f800, 0x001068f6, - 0x0201f000, 0x000208b4, 0x0201f800, 0x001068f6, - 0x0201f800, 0x000208b4, 0x0201f000, 0x00106982, - 0x4933c857, 0x4a026203, 0x00000002, 0x59a80037, - 0x48026206, 0x1c01f000, 0x4933c857, 0x0201f800, - 0x00108df4, 0x0400002a, 0x4d2c0000, 0x0201f800, - 0x00109360, 0x0402000a, 0x4d400000, 0x42028000, - 0x00000031, 0x42000800, 0x00000004, 0x0201f800, - 0x00109204, 0x5c028000, 0x0401f01c, 0x59300c06, - 0x82040580, 0x00000010, 0x04000004, 0x82040580, - 0x00000011, 0x0402000a, 0x4a025a06, 0x00000031, - 0x4a02580d, 0x00000004, 0x4a02580e, 0x000000ff, - 0x0201f800, 0x00020381, 0x0401f00c, 0x592c0404, - 0x8c00051e, 0x04000009, 0x4a025a04, 0x00000103, - 0x4a025805, 0x01000000, 0x5931d821, 0x58ef400b, - 0x58ec0009, 0x0801f800, 0x5c025800, 0x1c01f000, - 0x4933c857, 0x59340400, 0x82000500, 0x000000ff, - 0x82003480, 0x0000000c, 0x02021800, 0x00100615, - 0x59303403, 0x82180d80, 0x0000004d, 0x02000000, - 0x00109154, 0x82180d80, 0x00000033, 0x02000000, - 0x0010910f, 0x82180d80, 0x00000028, 0x02000000, - 0x00108f46, 0x82180d80, 0x00000029, 0x02000000, - 0x00108f5a, 0x82180d80, 0x0000001f, 0x02000000, - 0x001078af, 0x82180d80, 0x00000055, 0x02000000, - 0x00107888, 0x82180d80, 0x00000000, 0x0400058e, - 0x82180d80, 0x00000022, 0x02000000, 0x001078dc, - 0x82180d80, 0x00000035, 0x02000000, 0x001079d7, - 0x82180d80, 0x00000039, 0x04000536, 0x82180d80, - 0x0000003d, 0x02000000, 0x0010790c, 0x82180d80, - 0x00000044, 0x02000000, 0x00107949, 0x82180d80, - 0x00000049, 0x02000000, 0x0010799e, 0x82180d80, - 0x00000041, 0x02000000, 0x0010798a, 0x82180d80, - 0x00000043, 0x02000000, 0x001092a5, 0x82180d80, - 0x00000051, 0x02000000, 0x0010930b, 0x82180d80, - 0x00000004, 0x04020003, 0x42000000, 0x00000001, - 0x83380d80, 0x00000015, 0x04000006, 0x83380d80, - 0x00000016, 0x02020000, 0x001076fb, 0x0401f226, - 0x4d2c0000, 0x4d3c0000, 0x0c01f804, 0x5c027800, - 0x5c025800, 0x1c01f000, 0x00107e42, 0x00107e46, - 0x00107e42, 0x00107ebb, 0x00107e42, 0x00107fc7, - 0x00108060, 0x00107e42, 0x00107e42, 0x00108029, - 0x00107e42, 0x0010803b, 0x4933c857, 0x497a6007, - 0x59300808, 0x58040000, 0x4a000a04, 0x00000103, - 0x0201f000, 0x000208b4, 0x4933c857, 0x40000000, - 0x40000000, 0x1c01f000, 0x4933c857, 0x59a80016, - 0x82000580, 0x00000074, 0x0402005c, 0x0201f800, - 0x0010a0b1, 0x04020016, 0x0401f85c, 0x0201f800, - 0x00108df4, 0x0400000c, 0x0201f800, 0x00109360, - 0x04020009, 0x41780800, 0x4d400000, 0x42028000, - 0x00000000, 0x0201f800, 0x00109204, 0x5c028000, - 0x0401f003, 0x0201f800, 0x00101e1b, 0x0201f800, - 0x00104711, 0x0201f000, 0x000208b4, 0x0201f800, - 0x00108df4, 0x04000007, 0x0201f800, 0x00109360, - 0x04020004, 0x0401ff3d, 0x0201f000, 0x000208b4, - 0x417a7800, 0x0201f800, 0x00101de2, 0x42000000, - 0x0010b663, 0x0201f800, 0x0010a86e, 0x59340200, - 0x84000558, 0x48026a00, 0x42003000, 0x00000003, - 0x0201f800, 0x0010a766, 0x4d300000, 0x0201f800, - 0x00020892, 0x02000800, 0x00100615, 0x49366009, - 0x497a6008, 0x4a026406, 0x00000001, 0x4a026403, - 0x00000001, 0x0201f800, 0x0010393e, 0x04000011, - 0x4a026406, 0x00000004, 0x4a026203, 0x00000007, - 0x4a026420, 0x00000001, 0x42003000, 0x00000001, - 0x4d400000, 0x42028000, 0x00000029, 0x41782800, - 0x0201f800, 0x0010a250, 0x5c028000, 0x0401f009, - 0x42000800, 0x0000000b, 0x0201f800, 0x001043c7, - 0x4a026203, 0x00000001, 0x0201f800, 0x00106470, - 0x5c026000, 0x0401ff05, 0x0201f800, 0x00101e1b, - 0x0201f000, 0x000208b4, 0x0401ff00, 0x42000000, - 0x00000001, 0x0401f0de, 0x4933c857, 0x59340200, - 0x8c000500, 0x0400000d, 0x4d3c0000, 0x417a7800, - 0x0201f800, 0x001043bd, 0x5c027800, 0x0201f800, - 0x0010393e, 0x04000005, 0x42000800, 0x00000006, - 0x0201f800, 0x001043c7, 0x1c01f000, 0x4933c857, - 0x59a80816, 0x82040580, 0x00000074, 0x0400000e, - 0x4807c857, 0x82040580, 0x00000100, 0x040200b7, - 0x59cc0408, 0x4803c857, 0x8c000500, 0x040000b3, - 0x59341403, 0x82080580, 0x000007fe, 0x04000006, - 0x0401f0ae, 0x59341403, 0x82080580, 0x000007fe, - 0x0402001a, 0x59a80026, 0x8c000506, 0x04000015, - 0x59cc0000, 0x82000500, 0x000000ff, 0x59a80810, - 0x82040d00, 0x000000ff, 0x80040580, 0x0400000d, - 0x0201f800, 0x00101e1b, 0x0201f800, 0x000208b4, - 0x42000000, 0x0010b651, 0x0201f800, 0x0010a86e, - 0x4202d800, 0x00000001, 0x0201f000, 0x00103f37, - 0x0401fa9c, 0x0401f04c, 0x0201f800, 0x00104480, - 0x59341403, 0x82080580, 0x000007fc, 0x0402001f, - 0x4a026802, 0x00fffffc, 0x0201f800, 0x00108df4, - 0x04000012, 0x0201f800, 0x00109360, 0x0402000f, - 0x0401f8a9, 0x41780800, 0x4d400000, 0x42028000, - 0x00000000, 0x0201f800, 0x00109204, 0x5c028000, - 0x42000800, 0x00000004, 0x0201f800, 0x001043c7, - 0x0201f000, 0x000208b4, 0x42000800, 0x00000004, - 0x0201f800, 0x001043c7, 0x0201f800, 0x00101e1b, - 0x0201f000, 0x000208b4, 0x59a8006f, 0x8c000502, - 0x04000011, 0x0201f800, 0x00104e0d, 0x42001000, - 0x00000010, 0x04020009, 0x59340002, 0x82000500, - 0x00ff0000, 0x82000580, 0x00ff0000, 0x04000006, - 0x42001000, 0x00000008, 0x0201f800, 0x00104ada, - 0x0402005a, 0x0201f800, 0x00108df4, 0x0400005b, - 0x0201f800, 0x00109360, 0x04020005, 0x592c0404, - 0x8c00051c, 0x040207c9, 0x0401f877, 0x42000800, - 0x00000005, 0x0201f800, 0x001043c7, 0x4a026203, - 0x00000001, 0x4a026403, 0x00000003, 0x0201f000, - 0x00106470, 0x59cc0408, 0x8c000518, 0x04000010, - 0x0201f800, 0x001090ab, 0x0201f800, 0x00104e0d, - 0x04000004, 0x59cc0408, 0x8c000516, 0x040207b3, - 0x59a80026, 0x8400054a, 0x48035026, 0x59a80010, - 0x84000570, 0x48038832, 0x0401f7ac, 0x42001000, - 0x000000ef, 0x480b5010, 0x497b8830, 0x84081570, - 0x480b8832, 0x59c40802, 0x84040d4c, 0x48078802, - 0x0201f800, 0x001090d5, 0x59a80026, 0x84000548, - 0x48035026, 0x0201f800, 0x0010a1ec, 0x0402079b, - 0x59a80026, 0x8400054c, 0x48035026, 0x42000800, - 0x00000006, 0x0201f800, 0x001043c7, 0x417a7800, - 0x0201f800, 0x001043bd, 0x42000000, 0x000000e8, - 0x0201f800, 0x001059b9, 0x02000800, 0x001043fc, - 0x02020800, 0x00100615, 0x49366009, 0x59340200, - 0x8400051a, 0x48026a00, 0x42000800, 0x00000003, - 0x0201f800, 0x001043c7, 0x4a026406, 0x00000001, - 0x4a026203, 0x00000001, 0x4a026403, 0x00000002, - 0x0201f000, 0x00106470, 0x0401fe2c, 0x42000000, - 0x00000001, 0x0401f00a, 0x599c0017, 0x8c00050a, - 0x040007ab, 0x42000800, 0x00000004, 0x0201f800, - 0x001043c7, 0x0201f000, 0x000208b4, 0x4933c857, - 0x80003540, 0x04000005, 0x42000800, 0x00000007, - 0x0201f800, 0x001043c7, 0x801831c0, 0x0402000e, - 0x59302008, 0x801021c0, 0x04000004, 0x58100404, - 0x8c00051e, 0x04020008, 0x59341c03, 0x42002000, - 0x00000004, 0x42003000, 0x00000012, 0x0201f800, - 0x001038c7, 0x0201f800, 0x00101e1b, 0x0201f000, - 0x000208b4, 0x4c5c0000, 0x4d2c0000, 0x59325808, - 0x0201f800, 0x00105439, 0x5c025800, 0x59cc0008, - 0x48002805, 0x59cc0009, 0x48002806, 0x49782807, - 0x49782808, 0x49782809, 0x4978280a, 0x59cc0013, - 0x8c00053e, 0x04000009, 0x59cc0414, 0x900001c0, - 0x59ccbc15, 0x805c0540, 0x48002807, 0x59cc0416, - 0x900001c0, 0x48002808, 0x59cc0017, 0x8c00053e, - 0x04000009, 0x59cc0418, 0x900001c0, 0x59ccbc19, - 0x805c0540, 0x48002809, 0x59cc041a, 0x900001c0, - 0x4800280a, 0x5c00b800, 0x1c01f000, 0x4933c857, - 0x59a80016, 0x82000580, 0x00000014, 0x04020048, - 0x59a8006f, 0x8c000502, 0x04000015, 0x0201f800, - 0x00104e0d, 0x42001000, 0x00000010, 0x04020009, - 0x59340002, 0x82000500, 0x00ff0000, 0x82000580, - 0x00ff0000, 0x0400000a, 0x42001000, 0x00000008, - 0x0201f800, 0x00104ada, 0x04000005, 0x59a8006f, - 0x8400054c, 0x4803506f, 0x0401f031, 0x836c0580, - 0x00000003, 0x0402000b, 0x59300008, 0x80000540, - 0x04020008, 0x59341c03, 0x42002000, 0x00000006, - 0x42003000, 0x00000013, 0x0201f800, 0x001038c7, - 0x0201f800, 0x001044e1, 0x0401feb8, 0x0401fa1d, - 0x0402001f, 0x59340404, 0x80000540, 0x0400001c, - 0x42000800, 0x00000006, 0x0201f800, 0x001043c7, - 0x0201f800, 0x00108df4, 0x04000011, 0x0201f800, - 0x00109360, 0x0402000a, 0x41780800, 0x4d400000, - 0x42028000, 0x00000000, 0x0201f800, 0x00109204, - 0x5c028000, 0x0201f000, 0x000208b4, 0x4a025a04, - 0x00000103, 0x4a025805, 0x02000000, 0x0201f800, - 0x00101e1b, 0x0201f000, 0x000208b4, 0x0201f800, - 0x00104a83, 0x0201f800, 0x00108df4, 0x04000007, - 0x0201f800, 0x00109360, 0x04020004, 0x0401fd8b, - 0x0201f000, 0x000208b4, 0x0401fd88, 0x80000580, - 0x59a8006f, 0x8c00050c, 0x04000005, 0x8400050c, - 0x4803506f, 0x82000540, 0x00000001, 0x0401ff60, - 0x1c01f000, 0x4933c857, 0x59a80016, 0x82000580, - 0x00000014, 0x0402000b, 0x42000800, 0x0000000b, - 0x0201f800, 0x001043c7, 0x4a026203, 0x00000001, - 0x4a026403, 0x00000001, 0x0201f000, 0x00106470, - 0x42000000, 0x00000001, 0x0401f74d, 0x4933c857, - 0x40003000, 0x59a80016, 0x82000580, 0x00000004, - 0x0402000a, 0x82183580, 0x0000000b, 0x04020005, - 0x42000800, 0x00000007, 0x0201f800, 0x001043c7, - 0x0201f000, 0x000208b4, 0x42000000, 0x00000001, - 0x0401f73b, 0x4803c857, 0x4d2c0000, 0x4d3c0000, - 0x0c01f804, 0x5c027800, 0x5c025800, 0x1c01f000, - 0x00107e42, 0x0010806f, 0x00107e42, 0x001080c4, - 0x00107e42, 0x00108132, 0x00108060, 0x00107e42, - 0x00107e42, 0x00108152, 0x00107e42, 0x00108162, - 0x4933c857, 0x4d1c0000, 0x59301403, 0x82080580, - 0x00000003, 0x04000008, 0x82081580, 0x0000001e, - 0x04020003, 0x0201f800, 0x000208b4, 0x5c023800, - 0x1c01f000, 0x0401ff5a, 0x0401f7fd, 0x4933c857, - 0x0201f800, 0x00108df4, 0x0400000b, 0x0201f800, - 0x00109360, 0x04020008, 0x4200b000, 0x00000002, - 0x0201f800, 0x00109346, 0x0401fd2c, 0x0201f000, - 0x000208b4, 0x0401f8f5, 0x04020030, 0x417a7800, - 0x0201f800, 0x001043bd, 0x417a7800, 0x0201f800, - 0x00101de2, 0x42000000, 0x0010b663, 0x0201f800, - 0x0010a86e, 0x59340200, 0x84000558, 0x48026a00, - 0x4a026403, 0x00000002, 0x42003000, 0x00000003, - 0x0201f800, 0x0010a766, 0x0201f800, 0x0010393e, - 0x04000011, 0x4d400000, 0x41782800, 0x42003000, - 0x00000005, 0x42028000, 0x00000029, 0x0201f800, - 0x0010a250, 0x5c028000, 0x4a026203, 0x00000007, - 0x4a026406, 0x00000004, 0x4a026420, 0x00000001, - 0x1c01f000, 0x42000800, 0x00000003, 0x0201f800, - 0x001043c7, 0x4a026203, 0x00000001, 0x0201f800, - 0x00106470, 0x0401f7f7, 0x59cc0407, 0x82000580, - 0x00000009, 0x0402000a, 0x59340412, 0x82000500, - 0x000000ff, 0x0400000c, 0x80000040, 0x48026c12, - 0x4a026206, 0x0000000a, 0x0401f7ea, 0x59cc0207, - 0x82000500, 0x0000ff00, 0x82000580, 0x00001900, - 0x040007c2, 0x0401fce5, 0x80000580, 0x0401f6c4, - 0x4933c857, 0x59a80032, 0x80000540, 0x04000015, - 0x59340403, 0x82000580, 0x000007fe, 0x04020011, - 0x59a80010, 0x80000000, 0x48035010, 0x417a7800, - 0x0201f800, 0x001043bd, 0x42000800, 0x00000003, - 0x0201f800, 0x001043c7, 0x4a026203, 0x00000001, - 0x4a026403, 0x00000002, 0x0201f000, 0x00106470, - 0x0201f800, 0x00108df4, 0x04000011, 0x0201f800, - 0x00109360, 0x0402000e, 0x4c580000, 0x4200b000, - 0x00000002, 0x0201f800, 0x00109346, 0x5c00b000, - 0x0401fcbe, 0x42000800, 0x00000007, 0x0201f800, - 0x001043c7, 0x0201f000, 0x000208b4, 0x0401fcb7, - 0x59cc3407, 0x82183500, 0x000000ff, 0x82180580, - 0x00000005, 0x0400001c, 0x82180580, 0x0000000b, - 0x04000016, 0x59cc0207, 0x82000500, 0x0000ff00, - 0x04020004, 0x82180580, 0x00000009, 0x04000012, - 0x82000580, 0x00001900, 0x0402000c, 0x82180580, - 0x00000009, 0x0400000c, 0x42000800, 0x00000004, - 0x0201f800, 0x001043c7, 0x0201f800, 0x00101e1b, - 0x0201f000, 0x000208b4, 0x42000000, 0x00000001, - 0x0401f677, 0x0201f800, 0x00108df4, 0x59325808, - 0x04000008, 0x592c0204, 0x82000580, 0x00000139, - 0x040007f6, 0x592c0404, 0x8c00051e, 0x040207f3, - 0x59340403, 0x82000580, 0x000007fe, 0x04020007, - 0x59a80026, 0x84000540, 0x48035026, 0x0201f800, - 0x00104059, 0x0401f7e9, 0x417a7800, 0x0201f800, - 0x00101de2, 0x42003000, 0x00000005, 0x0201f800, - 0x0010a766, 0x42000000, 0x0010b663, 0x0201f800, - 0x0010a86e, 0x0401f7dd, 0x4933c857, 0x0401f84d, - 0x0402000b, 0x42000800, 0x00000005, 0x0201f800, - 0x001043c7, 0x4a026203, 0x00000001, 0x4a026403, - 0x00000003, 0x0201f000, 0x00106470, 0x42000800, - 0x00000004, 0x0201f800, 0x001043c7, 0x0201f800, - 0x00109360, 0x0402000a, 0x4c580000, 0x4200b000, - 0x00000002, 0x0201f800, 0x00109346, 0x5c00b000, - 0x0401fc5a, 0x0201f000, 0x000208b4, 0x0401fc57, - 0x80000580, 0x0401f636, 0x4933c857, 0x0401f82d, - 0x0402000b, 0x42000800, 0x00000009, 0x0201f800, - 0x001043c7, 0x4a026203, 0x00000001, 0x4a026403, - 0x00000005, 0x0201f000, 0x00106470, 0x42000000, - 0x00000001, 0x0401f626, 0x4933c857, 0x0401f81d, - 0x0402000b, 0x42000800, 0x0000000b, 0x0201f800, - 0x001043c7, 0x4a026203, 0x00000001, 0x4a026403, - 0x00000001, 0x0201f000, 0x00106470, 0x42000000, - 0x00000001, 0x0401f616, 0x4933c857, 0x59cc0407, - 0x82000580, 0x00000003, 0x04020009, 0x59cc0207, - 0x82000500, 0x0000ff00, 0x82000d80, 0x00002a00, - 0x04000003, 0x82000d80, 0x00001e00, 0x1c01f000, - 0x4933c857, 0x82000540, 0x00000001, 0x1c01f000, - 0x4933c857, 0x4d400000, 0x4c580000, 0x59a80026, - 0x82000540, 0x00000003, 0x48035026, 0x0401f85c, - 0x04000038, 0x4d340000, 0x4d440000, 0x59a80026, - 0x84000552, 0x48035026, 0x0201f800, 0x0010393e, - 0x0400000c, 0x42028000, 0x0000002a, 0x42028800, - 0x0000ffff, 0x42003000, 0x00000002, 0x0201f800, - 0x0010a258, 0x59a80805, 0x84040d44, 0x48075005, - 0x42028000, 0x0000002a, 0x4d3c0000, 0x42027800, - 0x00000200, 0x0201f800, 0x00101d90, 0x5c027800, - 0x42000000, 0x0010b663, 0x0201f800, 0x0010a86e, - 0x0201f800, 0x00101bf0, 0x4200b000, 0x00000010, - 0x42028800, 0x000007f0, 0x4d2c0000, 0x83440580, - 0x000007fe, 0x04000003, 0x0201f800, 0x00104451, - 0x81468800, 0x8058b040, 0x040207f9, 0x5c025800, - 0x59cc0408, 0x8c00051e, 0x04000004, 0x59a80026, - 0x84000512, 0x48035026, 0x5c028800, 0x5c026800, - 0x0201f800, 0x00104480, 0x4a026802, 0x00fffffe, - 0x59a80826, 0x84040d50, 0x59cc0013, 0x8c00053e, - 0x04000003, 0x8c000536, 0x04000004, 0x59cc0017, - 0x8c000536, 0x04020002, 0x84040d10, 0x48075026, - 0x59cc0800, 0x82040d00, 0x00ffffff, 0x48075010, - 0x80040110, 0x4803501d, 0x48038881, 0x0201f800, - 0x00104e0d, 0x04000007, 0x59cc0009, 0x48035035, - 0x59cc000a, 0x48035036, 0x0201f800, 0x001090ab, - 0x5c00b000, 0x5c028000, 0x1c01f000, 0x4933c857, - 0x4c580000, 0x59a80010, 0x82000500, 0x00ffff00, - 0x04000022, 0x59cc1000, 0x82081500, 0x00ffff00, - 0x80080580, 0x04000004, 0x42000000, 0x0010b639, - 0x0401f016, 0x83cc1400, 0x0000000b, 0x4200b000, - 0x00000002, 0x83341c00, 0x00000006, 0x0401f904, - 0x04000004, 0x42000000, 0x0010b63a, 0x0401f00b, - 0x83cc1400, 0x0000000d, 0x4200b000, 0x00000002, - 0x83341c00, 0x00000008, 0x0401f8f9, 0x04000007, - 0x42000000, 0x0010b63b, 0x0201f800, 0x0010a86e, - 0x82000540, 0x00000001, 0x5c00b000, 0x1c01f000, - 0x4933c857, 0x59cc0206, 0x82000580, 0x00000014, - 0x04020016, 0x59cc0407, 0x82000580, 0x00000800, - 0x04020012, 0x59cc0207, 0x8c00051a, 0x0400000d, - 0x82000500, 0x00000f00, 0x82000580, 0x00000100, - 0x04020008, 0x59cc020a, 0x8c000508, 0x04020003, - 0x8c00050a, 0x04000003, 0x80000580, 0x1c01f000, - 0x82000540, 0x00000001, 0x1c01f000, 0x4933c857, - 0x4943c857, 0x493fc857, 0x4c5c0000, 0x4d300000, - 0x4d340000, 0x4d2c0000, 0x4d380000, 0x4130b800, - 0x42026000, 0x0010cfc0, 0x59a8000e, 0x81640480, - 0x040210c1, 0x8d3e7d12, 0x04000004, 0x405c0000, - 0x81300580, 0x040000b7, 0x59300406, 0x82000c80, - 0x00000012, 0x04021015, 0x59326809, 0x0c01f001, - 0x001082f4, 0x0010825f, 0x00108278, 0x00108283, - 0x00108258, 0x00108271, 0x001082ac, 0x001082f4, - 0x00108256, 0x001082c0, 0x001082cf, 0x00108256, - 0x00108256, 0x00108256, 0x00108256, 0x001082f4, - 0x001082e5, 0x001082dd, 0x0201f800, 0x00100615, - 0x8d3e7d18, 0x04000003, 0x8d3e7d16, 0x04000004, - 0x59300420, 0x8c000500, 0x04020096, 0x59300403, - 0x82000580, 0x00000043, 0x04000092, 0x0201f800, - 0x00108ef1, 0x02000800, 0x00101e1b, 0x0201f800, - 0x00108f05, 0x02000800, 0x00107da6, 0x8d3e7d06, - 0x04000086, 0x0201f800, 0x0010909d, 0x04000085, - 0x0401f082, 0x8d3e7d18, 0x04000003, 0x8d3e7d16, - 0x04000004, 0x59300420, 0x8c000500, 0x0402007d, - 0x59325808, 0x0201f800, 0x00108df4, 0x04000077, - 0x49425a06, 0x497a5c09, 0x0201f800, 0x00020381, - 0x0201f800, 0x00108ee7, 0x0401f070, 0x813669c0, - 0x02000800, 0x00100615, 0x8d3e7d06, 0x04000004, - 0x59340200, 0x8c00050e, 0x0402006a, 0x59300004, - 0x8400055c, 0x48026004, 0x59300203, 0x82000580, - 0x00000004, 0x02000800, 0x00100ee4, 0x59325808, - 0x0201f800, 0x00108df4, 0x0400005c, 0x4a025a04, - 0x00000103, 0x59300402, 0x48025c06, 0x592c0408, - 0x8c000512, 0x04000006, 0x4d2c0000, 0x592e5809, - 0x0201f800, 0x00100843, 0x5c025800, 0x49425a06, - 0x497a5c09, 0x0201f800, 0x00109365, 0x0201f800, - 0x00020381, 0x0201f800, 0x00108ee7, 0x0401f047, - 0x8c000518, 0x04000047, 0x59300203, 0x82000580, - 0x00000004, 0x02000800, 0x00100ee4, 0x59325808, - 0x0201f800, 0x00108df4, 0x0400003c, 0x49425a06, - 0x497a5c09, 0x0201f800, 0x0010a4ae, 0x0201f800, - 0x00109365, 0x0201f800, 0x00020381, 0x0401f033, - 0x0201f800, 0x0010600e, 0x04000032, 0x59300203, - 0x82000580, 0x00000004, 0x04020004, 0x0201f800, - 0x00100ee4, 0x0401f02b, 0x42027000, 0x00000047, - 0x0201f800, 0x000208d8, 0x0401f026, 0x59300203, - 0x82000580, 0x00000004, 0x02000800, 0x00100ee4, - 0x59325808, 0x0201f800, 0x00108df4, 0x0400001b, - 0x49425a06, 0x497a5c09, 0x0201f800, 0x00020381, - 0x0401f016, 0x833c0500, 0x00001800, 0x04000015, - 0x8d3e7d16, 0x04020013, 0x59325817, 0x0201f800, - 0x00100843, 0x59300203, 0x82000580, 0x00000004, - 0x02000800, 0x00100ee4, 0x59325808, 0x0201f800, - 0x00108df4, 0x04000005, 0x49425a06, 0x497a5c09, - 0x0201f800, 0x00020381, 0x0201f800, 0x00107698, - 0x83326400, 0x00000024, 0x41580000, 0x81300480, - 0x0400173e, 0x5c027000, 0x5c025800, 0x5c026800, - 0x5c026000, 0x5c00b800, 0x1c01f000, 0x5c000000, - 0x4c000000, 0x4803c857, 0x480bc857, 0x480fc857, - 0x485bc857, 0x50080800, 0x500c0000, 0x80042580, - 0x04020007, 0x80081000, 0x800c1800, 0x8058b040, - 0x040207f9, 0x80000580, 0x1c01f000, 0x4803c857, - 0x4807c857, 0x480bc857, 0x480fc857, 0x80040480, - 0x04001006, 0x42000000, 0x00000001, 0x82040d40, - 0x00000001, 0x1c01f000, 0x41780000, 0x0401f7fc, - 0x83380480, 0x00000053, 0x02021800, 0x00100615, - 0x83380480, 0x0000004b, 0x02001800, 0x00100615, - 0x0c01f001, 0x0010832f, 0x0010832f, 0x0010832f, - 0x0010832f, 0x0010832d, 0x0010832d, 0x0010832d, - 0x0010832f, 0x0201f800, 0x00100615, 0x493bc857, - 0x4a026203, 0x0000000d, 0x493a6403, 0x42000800, - 0x80000000, 0x0201f000, 0x00020855, 0x83380580, - 0x00000013, 0x04020008, 0x59300403, 0x82000580, - 0x00000050, 0x02020800, 0x00100615, 0x0201f000, - 0x000208b4, 0x4933c857, 0x83380580, 0x00000027, - 0x04020030, 0x4933c857, 0x0201f800, 0x001068f6, - 0x4d3c0000, 0x417a7800, 0x0201f800, 0x00101de2, - 0x5c027800, 0x42000000, 0x0010b663, 0x0201f800, - 0x0010a86e, 0x4d2c0000, 0x59325808, 0x0201f800, - 0x00108df4, 0x492fc857, 0x0400000d, 0x4a025a04, - 0x00000103, 0x59300c02, 0x48065c06, 0x4a025a06, - 0x00000029, 0x497a5c09, 0x592c0c08, 0x84040d50, - 0x48065c08, 0x0201f800, 0x00020381, 0x5c025800, - 0x42003000, 0x00000015, 0x41782800, 0x42002000, - 0x00000003, 0x4d400000, 0x4d440000, 0x59368c03, - 0x42028000, 0x00000029, 0x0201f800, 0x0010962a, - 0x5c028800, 0x5c028000, 0x0201f000, 0x000208b4, - 0x83380580, 0x00000014, 0x0402000d, 0x59300403, - 0x82000c80, 0x00000053, 0x02021800, 0x00100615, - 0x82000480, 0x00000040, 0x02001800, 0x00100615, - 0x4933c857, 0x4803c857, 0x0c01f00e, 0x83380580, - 0x00000053, 0x0400000a, 0x83380580, 0x00000048, - 0x02020800, 0x00100615, 0x59300403, 0x82000580, - 0x00000050, 0x02020800, 0x00100615, 0x1c01f000, - 0x001083a5, 0x001083a3, 0x001083a3, 0x001083a3, - 0x001083a3, 0x001083a3, 0x001083a3, 0x001083a3, - 0x001083a3, 0x001083a3, 0x001083a3, 0x001083bc, - 0x001083bc, 0x001083bc, 0x001083bc, 0x001083a3, - 0x001083bc, 0x001083a3, 0x001083bc, 0x0201f800, - 0x00100615, 0x4933c857, 0x0201f800, 0x001068f6, - 0x0201f800, 0x00108df4, 0x02000000, 0x000208b4, - 0x4d2c0000, 0x59325808, 0x4a025a04, 0x00000103, - 0x59300402, 0x48025c06, 0x4a025a06, 0x00000006, - 0x497a5c09, 0x0201f800, 0x00020381, 0x5c025800, - 0x0201f800, 0x00108ee7, 0x0201f000, 0x000208b4, - 0x4933c857, 0x0201f800, 0x001068f6, 0x0201f000, - 0x000208b4, 0x0201f800, 0x00100615, 0x5930001c, - 0x800001c0, 0x02020800, 0x0010961a, 0x59300004, - 0x8c00053e, 0x04020029, 0x59325808, 0x592c0c08, - 0x59cc2a08, 0x82141d00, 0x00000c00, 0x04000002, - 0x59cc1809, 0x84040d58, 0x48065c08, 0x82143500, - 0x00000fff, 0x04020027, 0x59340200, 0x8c00050e, - 0x04020080, 0x0201f800, 0x00020962, 0x04020006, - 0x4a025a06, 0x00000000, 0x59300811, 0x800409c0, - 0x04020951, 0x4a025a04, 0x00000103, 0x48065807, - 0x480e580a, 0x48165c09, 0x59300c02, 0x48065c06, - 0x0201f800, 0x00020381, 0x0201f800, 0x00104801, - 0x59cc0208, 0x8c000518, 0x02020000, 0x00108f88, - 0x0201f000, 0x000208b4, 0x0201f800, 0x00106cb4, - 0x040007d6, 0x4d3c0000, 0x42027800, 0x00000002, - 0x0201f800, 0x00108997, 0x5c027800, 0x0401f7cf, - 0x4817c857, 0x480fc857, 0x82180500, 0x000000ff, - 0x0400000e, 0x592c0204, 0x82000500, 0x000000ff, - 0x82000580, 0x00000048, 0x04020008, 0x592c0407, - 0x800001c0, 0x04000005, 0x0201f800, 0x0010950b, - 0x0201f000, 0x00109553, 0x82180d00, 0x00000c00, - 0x04000004, 0x59340200, 0x8c00050e, 0x04020032, - 0x4a025a06, 0x00000000, 0x41782000, 0x8c183510, - 0x04000007, 0x59cc000c, 0x82000500, 0x000000ff, - 0x04000002, 0x4803c857, 0x59cc200b, 0x4812580c, - 0x41780000, 0x8c183512, 0x04000002, 0x59cc000a, - 0x4802580b, 0x80100c00, 0x040007b8, 0x82041480, - 0x0000001d, 0x04001006, 0x592c0404, 0x8c00051e, - 0x0400000e, 0x42000800, 0x0000001c, 0x4c500000, - 0x4c540000, 0x83cca400, 0x0000000c, 0x832cac00, - 0x0000000d, 0x0201f800, 0x00108953, 0x5c00a800, - 0x5c00a000, 0x0401f7a5, 0x59300011, 0x59301402, - 0x480a5c06, 0x48025807, 0x480e580a, 0x48165c09, - 0x0201f800, 0x001088fc, 0x0201f800, 0x00108938, - 0x0401f7a6, 0x592c020a, 0x8c000502, 0x040007cd, - 0x592c0208, 0x8c00050e, 0x040207ca, 0x59300011, - 0x800c0d80, 0x040007c7, 0x4803c857, 0x480fc857, - 0x8c183514, 0x02000000, 0x00108fc6, 0x80000540, - 0x040007c0, 0x4807c856, 0x0201f000, 0x00108fc6, - 0x592c020a, 0x8c000502, 0x04000782, 0x59300011, - 0x800001c0, 0x0400077f, 0x592c0208, 0x8c00050e, - 0x0402077c, 0x0201f000, 0x00108fc6, 0x59cc2006, - 0x59cc2807, 0x0401f037, 0x0401f036, 0x1c01f000, - 0x4933c857, 0x5930001c, 0x800001c0, 0x02020800, - 0x0010961a, 0x59325808, 0x592c0c08, 0x41782800, - 0x41781800, 0x84040d58, 0x48065c08, 0x41783000, - 0x59340200, 0x8c00050e, 0x0402001a, 0x0201f800, - 0x00020962, 0x04020007, 0x4a025a06, 0x00000000, - 0x59300811, 0x4807c857, 0x800409c0, 0x040208b2, - 0x4a025a04, 0x00000103, 0x48065807, 0x480e580a, - 0x48165c09, 0x4933c857, 0x59300c02, 0x48065c06, - 0x0201f800, 0x00109365, 0x0201f800, 0x00020381, - 0x0201f800, 0x00104801, 0x0201f000, 0x000208b4, - 0x592c020a, 0x8c000502, 0x040007e8, 0x59300011, - 0x4803c857, 0x800001c0, 0x040007e4, 0x592c0208, - 0x8c00050e, 0x040207e1, 0x0201f000, 0x00108fc6, - 0x5930001c, 0x800001c0, 0x4c100000, 0x4c140000, - 0x02020800, 0x0010961a, 0x5c002800, 0x5c002000, - 0x4a026203, 0x00000002, 0x4a026403, 0x00000043, - 0x59325808, 0x592c020a, 0x8c000502, 0x0402001c, - 0x40100000, 0x592c080f, 0x80040c80, 0x40140000, - 0x80040480, 0x04001018, 0x59300004, 0x8c00053e, - 0x0402000a, 0x48126013, 0x48166011, 0x497a6205, - 0x0201f800, 0x00100fe1, 0x0402000d, 0x59300804, - 0x0201f000, 0x00106466, 0x4c100000, 0x4c140000, - 0x0201f800, 0x00106cb4, 0x5c002800, 0x5c002000, - 0x040007f1, 0x0201f000, 0x001076fb, 0x4933c857, - 0x1c01f000, 0x4807c857, 0x40042800, 0x0401f7e7, - 0x83380480, 0x00000058, 0x04021005, 0x83380480, - 0x00000040, 0x04001002, 0x0c01f002, 0x1c01f000, - 0x001084ec, 0x001084ec, 0x001084ec, 0x001084ec, - 0x001084ec, 0x001084ec, 0x001084ec, 0x001084ec, - 0x001084ec, 0x001084ec, 0x001084ee, 0x001084ec, - 0x001084ec, 0x001084ec, 0x001084ec, 0x001084fb, - 0x001084ec, 0x001084ec, 0x001084ec, 0x001084ec, - 0x00108529, 0x001084ec, 0x001084ec, 0x001084ec, - 0x0201f800, 0x00100615, 0x4933c857, 0x0201f800, - 0x00106b13, 0x4a026203, 0x00000002, 0x59a80039, - 0x48026205, 0x59300011, 0x59300815, 0x80040c80, - 0x48066015, 0x0201f000, 0x001068c1, 0x4933c857, - 0x0201f800, 0x001068c1, 0x4d3c0000, 0x417a7800, - 0x0201f800, 0x00101de2, 0x5c027800, 0x42000000, - 0x0010b663, 0x0201f800, 0x0010a86e, 0x0201f800, - 0x00108df4, 0x04000010, 0x4d2c0000, 0x59325808, - 0x4a025a04, 0x00000103, 0x59300402, 0x48025c06, - 0x4a025a06, 0x00000029, 0x497a5c09, 0x592c0c08, - 0x84040d50, 0x48065c08, 0x0201f800, 0x00020381, - 0x5c025800, 0x42003000, 0x00000014, 0x41782800, - 0x4d400000, 0x4d440000, 0x59368c03, 0x42002000, - 0x00000002, 0x42028000, 0x00000029, 0x0201f800, - 0x0010962a, 0x5c028800, 0x5c028000, 0x0201f000, - 0x000208b4, 0x4933c857, 0x59300808, 0x49780c09, - 0x4978080a, 0x58041408, 0x84081558, 0x48080c08, - 0x1c01f000, 0x4807c857, 0x8c040d3e, 0x04020024, - 0x497a5a06, 0x5930001f, 0x80000540, 0x04000018, - 0x497a5a06, 0x4c040000, 0x4c080000, 0x4c0c0000, - 0x4c100000, 0x4c140000, 0x40002800, 0x58141003, - 0x40040000, 0x80081480, 0x48082803, 0x40140000, - 0x0201f800, 0x00100d9a, 0x5c002800, 0x5c002000, - 0x5c001800, 0x5c001000, 0x5c000800, 0x592c0206, - 0x80000540, 0x04020009, 0x0401f005, 0x592c0408, - 0x8c00051c, 0x04000002, 0x592c0803, 0x4807c857, - 0x4a025a06, 0x00000015, 0x1c01f000, 0x5930001f, - 0x80000540, 0x04000009, 0x4a025a06, 0x00000011, - 0x5930001f, 0x4c040000, 0x0201f800, 0x00100d9a, - 0x5c000800, 0x0401f7f5, 0x4807c856, 0x4a025a06, - 0x00000007, 0x1c01f000, 0x83380480, 0x00000058, - 0x04021007, 0x83380480, 0x00000040, 0x04001004, - 0x4d2c0000, 0x0c01f803, 0x5c025800, 0x1c01f000, - 0x00108588, 0x00108588, 0x00108588, 0x00108588, - 0x00108588, 0x0010858a, 0x00108588, 0x00108588, - 0x0010860d, 0x00108588, 0x00108588, 0x00108588, - 0x00108588, 0x00108588, 0x00108588, 0x00108588, - 0x00108588, 0x00108588, 0x00108588, 0x001086c5, - 0x001086ee, 0x001086cd, 0x00108588, 0x001086fa, - 0x0201f800, 0x00100615, 0x5930001c, 0x800001c0, - 0x02020800, 0x0010961a, 0x59300007, 0x8c00050e, - 0x0400007c, 0x8c000500, 0x0400006e, 0x8c00051c, - 0x04000009, 0x84000500, 0x48026007, 0x59325808, - 0x592c3c08, 0x841c3d58, 0x481e5c08, 0x0201f000, - 0x00020914, 0x59325808, 0x592c3c08, 0x841c3d58, - 0x59300007, 0x8c00051c, 0x040207f3, 0x481e5c08, - 0x42000000, 0x00000005, 0x40000000, 0x80000040, - 0x040207fe, 0x59300007, 0x8c00051c, 0x040207ea, - 0x59cc0a08, 0x592c0204, 0x82000500, 0x000000ff, - 0x82000580, 0x00000048, 0x0402000c, 0x497a580b, - 0x82040500, 0x000000ff, 0x04000008, 0x592c0407, - 0x800001c0, 0x04000005, 0x0201f800, 0x0010950b, - 0x0201f000, 0x00100ea1, 0x48065c09, 0x41782000, - 0x82040500, 0x00000c00, 0x04000002, 0x59cc2009, - 0x82043500, 0x00000fff, 0x04020027, 0x481e5c08, - 0x4a025a06, 0x00000000, 0x801831c0, 0x02000000, - 0x00100ea1, 0x41782000, 0x8c183510, 0x04000002, - 0x59cc200b, 0x4812580c, 0x41780000, 0x8c183512, - 0x04000002, 0x59cc000a, 0x4802580b, 0x80100c00, - 0x02001800, 0x00100615, 0x02000000, 0x00100ea1, - 0x82041480, 0x0000001d, 0x0402100c, 0x4c500000, - 0x4c540000, 0x83cca400, 0x0000000c, 0x832cac00, - 0x0000000d, 0x0401fb6e, 0x5c00a800, 0x5c00a000, - 0x0201f000, 0x00100ea1, 0x0401fb12, 0x0201f000, - 0x00100ea1, 0x412c7800, 0x0201f800, 0x0010082a, - 0x02000800, 0x00100615, 0x492c7809, 0x841c3d52, - 0x481c7c08, 0x4a025a04, 0x00000103, 0x4812580a, - 0x48065c09, 0x583c0404, 0x583c1005, 0x583c2208, - 0x48025c04, 0x480a5805, 0x48125a08, 0x0401f7c8, - 0x8c000524, 0x04000794, 0x59325808, 0x4c000000, - 0x592c0408, 0x8c00051c, 0x5c000000, 0x04020003, - 0x4a026011, 0xffffffff, 0x84000524, 0x0401f78a, - 0x1c01f000, 0x59a80039, 0x48026205, 0x59325808, - 0x4a026203, 0x00000002, 0x592c2408, 0x59300807, - 0x4933c857, 0x4807c857, 0x592c0204, 0x82000500, - 0x000000ff, 0x82000580, 0x00000048, 0x04020004, - 0x8c102500, 0x02020000, 0x00109553, 0x4a025a06, - 0x00000000, 0x8c040d1e, 0x04000027, 0x41780800, - 0x497a5c09, 0x592c1c09, 0x59300011, 0x59341200, - 0x497a6205, 0x8c08150e, 0x0402006e, 0x4807c857, - 0x4806580a, 0x80000d40, 0x04020f03, 0x59300402, - 0x48025c06, 0x48065807, 0x4a025a04, 0x00000103, - 0x4c040000, 0x4c0c0000, 0x4c100000, 0x0201f800, - 0x00109365, 0x5c002000, 0x5c001800, 0x5c000800, - 0x8c102512, 0x0402001a, 0x4c0c0000, 0x0201f800, - 0x00020381, 0x0201f800, 0x00104801, 0x5c001800, - 0x8c0c1d18, 0x02000000, 0x000208b4, 0x0201f000, - 0x00108f88, 0x4813c857, 0x8c102518, 0x0400004b, - 0x41780800, 0x592c1c09, 0x820c0580, 0x00001000, - 0x040007d6, 0x8c102512, 0x040007d4, 0x592c7809, - 0x583c080a, 0x583c1c09, 0x0401f7d0, 0x4807c857, - 0x592c7809, 0x59300402, 0x592c1404, 0x8c08151e, - 0x0402000d, 0x592c1206, 0x48007c06, 0x48047807, - 0x48087a06, 0x84102512, 0x48107c08, 0x4c0c0000, - 0x0201f800, 0x00100843, 0x403e5800, 0x0401fad1, - 0x0401f7d9, 0x48025c06, 0x48065807, 0x583c080c, - 0x583c000b, 0x80040c00, 0x82041480, 0x0000001d, - 0x04001006, 0x583c1001, 0x480a5801, 0x49787801, - 0x42000800, 0x0000001c, 0x82040c00, 0x00000014, - 0x4c0c0000, 0x4c500000, 0x4c540000, 0x823ca400, - 0x00000008, 0x832cac00, 0x00000008, 0x4c100000, - 0x4c3c0000, 0x0401fad2, 0x5c007800, 0x5c002000, - 0x5c00a800, 0x5c00a000, 0x84102512, 0x48125c08, - 0x403e5800, 0x0201f800, 0x00100843, 0x42034000, - 0x0010b2a0, 0x59a1d81e, 0x80edd9c0, 0x02000800, - 0x00100615, 0x48efc857, 0x58ec0009, 0x4803c857, - 0x0801f800, 0x0401f7ac, 0x4933c857, 0x1c01f000, - 0x59301414, 0x480bc857, 0x8c08151c, 0x0402000e, - 0x80000540, 0x4803c857, 0x0400078d, 0x80042c80, - 0x0402178b, 0x8c081514, 0x04020005, 0x592c080f, - 0x4807c857, 0x80040480, 0x48026016, 0x8408155c, - 0x480a6414, 0x59301007, 0x8408151e, 0x480a6007, - 0x4c100000, 0x4c3c0000, 0x4d400000, 0x592e8206, - 0x4a025a06, 0x00000001, 0x0201f800, 0x00109365, - 0x49425a06, 0x5c028000, 0x5c007800, 0x5c002000, - 0x497a5c09, 0x8c102512, 0x04000006, 0x4d2c0000, - 0x403e5800, 0x0201f800, 0x00100843, 0x5c025800, - 0x82102500, 0xffffedff, 0x48125c08, 0x0201f000, - 0x00108fc6, 0x59325808, 0x592c0408, 0x8c000518, - 0x04000004, 0x412df800, 0x0201f000, 0x00100eba, - 0x1c01f000, 0x4933c857, 0x59325808, 0x497a5c09, - 0x4a025a06, 0x00000000, 0x4a025a04, 0x00000103, - 0x59300811, 0x4807c857, 0x800409c0, 0x0402000a, - 0x48065807, 0x59300c02, 0x48065c06, 0x0201f800, - 0x00020381, 0x0201f800, 0x00104801, 0x0201f000, - 0x000208b4, 0x59340200, 0x8c00050e, 0x04020005, - 0x59300811, 0x0401fe4c, 0x48065807, 0x0401f7f2, - 0x592c0208, 0x8c00050e, 0x040207fa, 0x4933c857, - 0x0201f000, 0x00108fc6, 0x4933c857, 0x59325808, - 0x812e59c0, 0x02000800, 0x00100615, 0x592c020a, - 0x8c000502, 0x02000800, 0x00100615, 0x4a026206, - 0x00000002, 0x1c01f000, 0x5930001c, 0x800001c0, - 0x02020800, 0x0010961a, 0x59300007, 0x4933c857, - 0x4803c857, 0x8c00050e, 0x04000037, 0x8c000500, - 0x04000029, 0x8c00051c, 0x0400000a, 0x84000500, - 0x48026007, 0x59325808, 0x592c3c08, 0x481fc857, - 0x841c3d58, 0x481e5c08, 0x0201f000, 0x00020914, - 0x59325808, 0x592c3c08, 0x841c3d58, 0x59300007, - 0x8c00051c, 0x040207f2, 0x481e5c08, 0x42000000, - 0x00000005, 0x40000000, 0x80000040, 0x040207fe, - 0x59300007, 0x8c00051c, 0x040207e9, 0x592c0204, - 0x82000500, 0x000000ff, 0x82000580, 0x00000048, - 0x04020003, 0x497a580b, 0x0401f002, 0x497a5c09, - 0x481e5c08, 0x4a025a06, 0x00000000, 0x0201f000, - 0x00100ea1, 0x8c000524, 0x040007d9, 0x59325808, - 0x4c000000, 0x592c0408, 0x8c00051c, 0x5c000000, - 0x04020003, 0x4a026011, 0xffffffff, 0x84000524, - 0x0401f7cf, 0x1c01f000, 0x4933c857, 0x41780800, - 0x83380480, 0x00000058, 0x0402100b, 0x83380480, - 0x00000040, 0x04001008, 0x4d2c0000, 0x59325808, - 0x812e59c0, 0x0c020806, 0x5c025800, 0x0201f000, - 0x000208b4, 0x493bc857, 0x1c01f000, 0x00108763, - 0x00108763, 0x00108763, 0x00108763, 0x00108763, - 0x00108765, 0x00108763, 0x00108763, 0x00108763, - 0x00108763, 0x00108763, 0x00108763, 0x00108763, - 0x00108763, 0x00108763, 0x00108763, 0x00108763, - 0x00108763, 0x00108763, 0x00108763, 0x0010876a, - 0x00108763, 0x00108763, 0x00108763, 0x0201f800, - 0x00100615, 0x59cc0a08, 0x497a5807, 0x4807c857, - 0x82040d00, 0x00000fff, 0x59300402, 0x48025c06, - 0x4a025a04, 0x00000103, 0x48065c09, 0x4a025a06, - 0x00000000, 0x800409c0, 0x02000000, 0x00020381, - 0x59cc0009, 0x4802580a, 0x82042500, 0x00000100, - 0x04000002, 0x59cc200b, 0x4812580c, 0x82040500, - 0x00000200, 0x04000002, 0x59cc000a, 0x4802580b, - 0x80100c00, 0x02001800, 0x00100615, 0x02000000, - 0x00020381, 0x82041480, 0x0000001d, 0x04001006, - 0x592c0404, 0x8c00051e, 0x0400000e, 0x42000800, - 0x0000001c, 0x4c500000, 0x4c540000, 0x83cca400, - 0x0000000c, 0x832cac00, 0x0000000d, 0x0401f9c0, - 0x5c00a800, 0x5c00a000, 0x0201f000, 0x00020381, - 0x0401f964, 0x0401f19f, 0x83380480, 0x00000093, - 0x02021800, 0x00100615, 0x83380480, 0x00000085, - 0x02001800, 0x00100615, 0x0c01f001, 0x001087b2, - 0x001087b0, 0x001087b0, 0x001087b9, 0x001087b0, - 0x001087b0, 0x001087b0, 0x001087b0, 0x001087b0, - 0x001087b0, 0x001087b0, 0x001087b0, 0x001087b0, - 0x0201f800, 0x00100615, 0x4a026203, 0x00000001, - 0x493a6403, 0x42000800, 0x80000040, 0x0201f000, - 0x00020855, 0x4933c857, 0x59cc1404, 0x0201f800, - 0x001091d9, 0x0400001b, 0x591c0203, 0x82000580, - 0x00000000, 0x04000017, 0x591c0009, 0x81340580, - 0x04020014, 0x4d300000, 0x4d1c0000, 0x411e6000, - 0x0401f9c3, 0x5c023800, 0x5c026000, 0x0400000b, - 0x59cc0005, 0x8c000500, 0x04020003, 0x0401f98d, - 0x0401f003, 0x4a023a03, 0x00000002, 0x4a026403, - 0x00000086, 0x0401f005, 0x0401f9a7, 0x040007f5, - 0x4a026403, 0x00000087, 0x4a026203, 0x00000001, - 0x42000800, 0x80000040, 0x0201f800, 0x00020855, - 0x59340200, 0x8c00050e, 0x0400000d, 0x59cc1404, - 0x0201f800, 0x001091d9, 0x04000009, 0x591c0414, - 0x8c00051a, 0x04000006, 0x4d300000, 0x411e6000, - 0x0201f800, 0x00108fdb, 0x5c026000, 0x1c01f000, - 0x83380580, 0x00000013, 0x0402000b, 0x59300403, - 0x4803c857, 0x82000d80, 0x00000086, 0x04000012, - 0x82000d80, 0x00000087, 0x02020800, 0x00100615, - 0x0401f00d, 0x83380580, 0x00000027, 0x04000005, - 0x83380580, 0x00000014, 0x02020800, 0x00100615, - 0x493bc857, 0x0201f800, 0x001068f6, 0x0201f000, - 0x00107698, 0x4933c857, 0x0201f000, 0x00107698, - 0x83380580, 0x00000013, 0x04020005, 0x59300403, - 0x82000480, 0x00000085, 0x0c01f04d, 0x83380580, - 0x00000027, 0x04020041, 0x4933c857, 0x0201f800, - 0x001068f6, 0x4d3c0000, 0x417a7800, 0x0201f800, - 0x00101de2, 0x5c027800, 0x42003000, 0x00000015, - 0x41782800, 0x42002000, 0x00000003, 0x42028000, - 0x00000029, 0x4d400000, 0x4d440000, 0x59368c03, - 0x0201f800, 0x0010962a, 0x5c028800, 0x5c028000, - 0x42000000, 0x0010b663, 0x0201f800, 0x0010a86e, - 0x0201f800, 0x00108df4, 0x0400000c, 0x4d2c0000, - 0x59325808, 0x4a025a04, 0x00000103, 0x59300402, - 0x48025c06, 0x497a5c09, 0x49425a06, 0x0201f800, - 0x00020381, 0x5c025800, 0x0201f800, 0x00108ee7, - 0x0201f000, 0x000208b4, 0x83380580, 0x00000089, - 0x04000005, 0x83380580, 0x0000008a, 0x02020000, - 0x001076fb, 0x0201f800, 0x00106cb4, 0x02020000, - 0x001076fb, 0x59300a03, 0x82040580, 0x0000000a, - 0x0400002a, 0x82040580, 0x0000000c, 0x04000027, - 0x0201f800, 0x00100615, 0x83380580, 0x00000014, - 0x040207ea, 0x4933c857, 0x0201f800, 0x001068f6, - 0x42028000, 0x00000006, 0x0401f7d2, 0x0010886e, - 0x0010886c, 0x0010886c, 0x0010886c, 0x0010886c, - 0x0010886c, 0x00108874, 0x0010886c, 0x0010886c, - 0x0010886c, 0x0010886c, 0x0010886c, 0x0010886c, - 0x0201f800, 0x00100615, 0x4933c857, 0x59a80037, - 0x48026206, 0x4a026203, 0x0000000a, 0x1c01f000, - 0x4933c857, 0x59a80037, 0x48026206, 0x4a026203, - 0x0000000c, 0x1c01f000, 0x83380580, 0x00000089, - 0x04000008, 0x83380580, 0x0000008a, 0x04000032, - 0x4933c857, 0x493bc857, 0x0201f000, 0x001076fb, - 0x4933c857, 0x59325808, 0x59300a1d, 0x82040580, - 0x00000003, 0x04020004, 0x0201f800, 0x00104801, - 0x0401f00c, 0x5930021d, 0x82000580, 0x00000001, - 0x04020008, 0x59300c16, 0x82040580, 0x00000039, - 0x0400002c, 0x82040580, 0x00000035, 0x04000029, - 0x4c5c0000, 0x4130b800, 0x0201f800, 0x00020892, - 0x04000010, 0x4a026203, 0x00000001, 0x4a026403, - 0x0000001e, 0x59cc0c07, 0x48066419, 0x59cc0a07, - 0x48066219, 0x49366009, 0x4a026406, 0x00000001, - 0x42000800, 0x80000040, 0x0201f800, 0x00020855, - 0x405e6000, 0x0201f800, 0x000208b4, 0x5c00b800, - 0x1c01f000, 0x4933c857, 0x5930021d, 0x82000580, - 0x00000001, 0x04020040, 0x59300c16, 0x82040580, - 0x00000035, 0x04000007, 0x82040580, 0x0000001e, - 0x04000004, 0x82040580, 0x00000039, 0x04020036, - 0x4933c857, 0x4c500000, 0x4d1c0000, 0x4130a000, - 0x40067000, 0x0201f800, 0x00109183, 0x04020029, - 0x0201f800, 0x00020892, 0x04000026, 0x491fc857, - 0x4933c857, 0x83380580, 0x00000035, 0x04000004, - 0x83380580, 0x00000039, 0x04020002, 0x4932381c, - 0x493a6403, 0x4a026203, 0x00000001, 0x4a026406, - 0x00000001, 0x58500809, 0x4807c857, 0x48066009, - 0x58500c15, 0x4807c857, 0x48066415, 0x58500a15, - 0x4807c857, 0x48066215, 0x58500a16, 0x4807c857, - 0x48066216, 0x58500c19, 0x4807c857, 0x48066419, - 0x58500a19, 0x4807c857, 0x48066219, 0x491e601e, - 0x42000800, 0x80000040, 0x0201f800, 0x00020855, - 0x40526000, 0x5c023800, 0x5c00a000, 0x0201f000, - 0x000208b4, 0x5930021d, 0x82000580, 0x00000003, - 0x02000800, 0x00104801, 0x0201f000, 0x000208b4, - 0x4803c856, 0x4c500000, 0x4c540000, 0x412c7800, - 0x4c3c0000, 0x42002800, 0x00000001, 0x82040480, - 0x00000101, 0x04001003, 0x42000800, 0x00000100, - 0x40043000, 0x42000800, 0x0000001c, 0x83cca400, - 0x0000000c, 0x832cac00, 0x0000000d, 0x0401f844, - 0x82183480, 0x0000001c, 0x592e5801, 0x812e59c0, - 0x02020800, 0x00100843, 0x0201f800, 0x0010082a, - 0x04000017, 0x80142800, 0x4a025a04, 0x00000110, - 0x497a5c04, 0x492c7801, 0x82180c80, 0x0000003d, - 0x04021006, 0x40180800, 0x832cac00, 0x00000005, - 0x0401f82f, 0x0401f00a, 0x82183480, 0x0000003c, - 0x42000800, 0x0000003c, 0x412c7800, 0x832cac00, - 0x00000005, 0x0401f826, 0x0401f7e8, 0x5c007800, - 0x841429c0, 0x82142d40, 0x00000003, 0x48147a04, - 0x403e5800, 0x5c00a800, 0x5c00a000, 0x1c01f000, - 0x492fc857, 0x812e59c0, 0x0400000f, 0x4d2c0000, - 0x4c3c0000, 0x592c7801, 0x803c79c0, 0x04000006, - 0x497a5801, 0x0201f800, 0x00020381, 0x403e5800, - 0x0401f7f9, 0x5c007800, 0x0201f800, 0x00020381, - 0x5c025800, 0x1c01f000, 0x4803c856, 0x4c580000, - 0x82040c00, 0x00000003, 0x8004b104, 0x0201f800, - 0x0010a93e, 0x5c00b000, 0x1c01f000, 0x4803c856, - 0x4c580000, 0x82040c00, 0x00000003, 0x8004b104, - 0x0201f800, 0x0010a93e, 0x5c00b000, 0x1c01f000, - 0x591c0c06, 0x82040580, 0x00000003, 0x04000004, - 0x82040580, 0x00000002, 0x0402001a, 0x4d300000, - 0x4d2c0000, 0x411e6000, 0x59325808, 0x0201f800, - 0x00108df4, 0x0400000f, 0x4d400000, 0x42028000, - 0x00000013, 0x592c0a08, 0x84040d54, 0x0201f800, - 0x00104bee, 0x5c028000, 0x0201f800, 0x00109365, - 0x0201f800, 0x00020381, 0x0201f800, 0x00108ee7, - 0x0201f800, 0x00107698, 0x5c025800, 0x5c026000, - 0x1c01f000, 0x59cc0005, 0x8c000500, 0x0402000b, - 0x591c0406, 0x82000580, 0x00000002, 0x04020007, - 0x591c0c03, 0x82040580, 0x00000085, 0x04000003, - 0x82040580, 0x0000008b, 0x1c01f000, 0x4933c857, - 0x4d3c0000, 0x42027800, 0x00000002, 0x59300406, - 0x82000c80, 0x00000012, 0x02021800, 0x00100615, - 0x0c01f80a, 0x5c027800, 0x1c01f000, 0x4933c857, - 0x59300406, 0x82000c80, 0x00000012, 0x02021800, - 0x00100615, 0x0c01f001, 0x001089b5, 0x001089b2, - 0x001089b2, 0x001089dd, 0x001089b0, 0x001089b2, - 0x001089ce, 0x001089b2, 0x001089b0, 0x0010632c, - 0x001089b2, 0x001089b2, 0x001089b2, 0x001089b0, - 0x001089b0, 0x001089b0, 0x00108aad, 0x001089b2, - 0x0201f800, 0x00100615, 0x4803c856, 0x80000580, - 0x1c01f000, 0x4803c856, 0x8d3e7d02, 0x04020016, - 0x0201f800, 0x00108df4, 0x0400000f, 0x59325808, - 0x41780800, 0x4d400000, 0x42028000, 0x00000005, - 0x0201f800, 0x00104bee, 0x5c028000, 0x0201f800, - 0x00109365, 0x0201f800, 0x00108f83, 0x0201f800, - 0x00020381, 0x0201f800, 0x00107698, 0x82000540, - 0x00000001, 0x1c01f000, 0x4933c857, 0x0201f800, - 0x00104728, 0x0402000c, 0x4d400000, 0x42028000, - 0x00000010, 0x0201f800, 0x00109fc0, 0x4a026406, - 0x00000006, 0x4a026203, 0x00000007, 0x5c028000, - 0x1c01f000, 0x4933c857, 0x0201f800, 0x0010698c, - 0x4df00000, 0x0401f8b8, 0x82000c80, 0x0000000e, - 0x02021800, 0x00100615, 0x0c01f001, 0x001089f7, - 0x00108a64, 0x00108a0e, 0x00108a77, 0x00108a5f, - 0x001089f5, 0x001089f7, 0x001089f7, 0x001089fb, - 0x001089f7, 0x001089f7, 0x001089f7, 0x001089f7, - 0x00108a0e, 0x0201f800, 0x00100615, 0x5c03e000, - 0x02000800, 0x00106982, 0x0401f7b8, 0x5c03e000, - 0x02000800, 0x00106982, 0x59300406, 0x82000580, - 0x00000003, 0x040207b4, 0x59300203, 0x82000580, - 0x0000000d, 0x040007b0, 0x8d3e7d02, 0x040207ae, - 0x4d340000, 0x59326809, 0x0201f800, 0x00104801, - 0x5c026800, 0x0401f7a8, 0x59300004, 0x8400055c, - 0x48026004, 0x0201f800, 0x00106982, 0x59300406, - 0x82000580, 0x00000006, 0x04000043, 0x8d3e7d02, - 0x04020041, 0x497a621d, 0x59300203, 0x82000580, - 0x0000000d, 0x04000003, 0x4a02621d, 0x00000003, - 0x0401fbd4, 0x04000024, 0x4d2c0000, 0x4d400000, - 0x59325808, 0x0201f800, 0x00108f83, 0x592c0408, - 0x8c000512, 0x04000009, 0x4d2c0000, 0x84000512, - 0x48025c08, 0x592c0809, 0x40065800, 0x0201f800, - 0x00100843, 0x5c025800, 0x4d400000, 0x42028000, - 0x00000005, 0x592c0a08, 0x8c040d0e, 0x04000004, - 0x42028000, 0x00000002, 0x0401f001, 0x0201f800, - 0x00104bee, 0x5c028000, 0x0201f800, 0x00109365, - 0x0201f800, 0x00020381, 0x497a6008, 0x5c028000, - 0x5c025800, 0x8d3e7d00, 0x04000009, 0x4d340000, - 0x59326809, 0x0201f800, 0x00104801, 0x5c026800, - 0x0201f800, 0x00107698, 0x0401f00b, 0x4a026403, - 0x00000085, 0x4a026203, 0x00000009, 0x4a026406, - 0x00000002, 0x42000800, 0x8000404b, 0x0201f800, - 0x00020855, 0x5c03e000, 0x02020800, 0x0010698c, - 0x82000540, 0x00000001, 0x1c01f000, 0x0201f800, - 0x00106982, 0x0201f800, 0x00100ee4, 0x0401f7ab, - 0x598c000d, 0x81300580, 0x04020004, 0x0201f800, - 0x00106be2, 0x0402001b, 0x0201f800, 0x00106619, - 0x04020006, 0x59300c03, 0x82040580, 0x00000040, - 0x0400078b, 0x0401f79d, 0x0201f800, 0x001068a3, - 0x04000010, 0x0201f800, 0x00100615, 0x0401f813, - 0x04020004, 0x0201f800, 0x00106bb2, 0x04020009, - 0x0201f800, 0x001064f6, 0x040207f4, 0x59300c03, - 0x82040580, 0x00000040, 0x04000779, 0x0401f78b, - 0x59300203, 0x82000c80, 0x0000000e, 0x02021800, - 0x00100615, 0x0c01f75e, 0x417a3000, 0x42032000, - 0x0000bf32, 0x59900004, 0x81300580, 0x04000009, - 0x83932400, 0x00000010, 0x811a3000, 0x83180480, - 0x00000005, 0x040017f8, 0x82000540, 0x00000001, - 0x1c01f000, 0x59300004, 0x8c00053e, 0x04000010, - 0x8c00050c, 0x0402000e, 0x8c000516, 0x04020006, - 0x82000d00, 0x0000001f, 0x82040580, 0x00000005, - 0x04020004, 0x42000000, 0x00000003, 0x0401f005, - 0x42000000, 0x00000001, 0x0401f002, 0x59300203, - 0x1c01f000, 0x4933c857, 0x0201f800, 0x0010698c, - 0x4df00000, 0x59300203, 0x82000c80, 0x0000000e, - 0x02021800, 0x00100615, 0x0c01f001, 0x00108ac7, - 0x00108ae4, 0x00108acb, 0x00108ac5, 0x00108ac5, - 0x00108ac5, 0x00108ac5, 0x00108ac5, 0x00108ac5, - 0x00108ac5, 0x00108ac5, 0x00108ac5, 0x00108ac5, - 0x00108ac5, 0x0201f800, 0x00100615, 0x5c03e000, - 0x02000800, 0x00106982, 0x0401f6e8, 0x5c03e000, - 0x02000800, 0x00106982, 0x4d2c0000, 0x59325808, - 0x59300403, 0x82000580, 0x00000052, 0x02000800, - 0x00101281, 0x0401fb1f, 0x02000800, 0x00100615, - 0x4a025a06, 0x00000005, 0x0201f800, 0x00020381, - 0x0201f800, 0x00104a83, 0x0201f800, 0x00107698, - 0x5c025800, 0x82000540, 0x00000001, 0x1c01f000, - 0x598c000d, 0x81300580, 0x0402001a, 0x59300004, - 0x8c000520, 0x04000004, 0x84000520, 0x48026004, - 0x0401f01a, 0x42001000, 0x0010b5f4, 0x50081000, - 0x58080002, 0x82000580, 0x00000100, 0x0400000a, - 0x5808000c, 0x81300580, 0x02020800, 0x00100615, - 0x0201f800, 0x00106619, 0x02020800, 0x00100615, - 0x0401f7cf, 0x0201f800, 0x00106be2, 0x0402000c, - 0x59300004, 0x8c000520, 0x04000004, 0x84000520, - 0x48026004, 0x0401f7c6, 0x0201f800, 0x00106619, - 0x040007c3, 0x0201f800, 0x00100615, 0x59300203, - 0x82000c80, 0x0000000e, 0x02021800, 0x00100615, - 0x0c01f7a7, 0x59300406, 0x4933c857, 0x4803c857, - 0x82000c80, 0x00000012, 0x02021800, 0x00100615, - 0x0c01f001, 0x00108b30, 0x00108bfe, 0x00108d36, - 0x00108b3c, 0x00107698, 0x00108b30, 0x00109faf, - 0x000208b4, 0x00108bfe, 0x00106306, 0x00108d97, - 0x00108b2b, 0x00108b2b, 0x00108b2b, 0x00108b2b, - 0x00108b2b, 0x001094b7, 0x001094b7, 0x0201f800, - 0x00100615, 0x0401fbd8, 0x02000000, 0x00107da6, - 0x1c01f000, 0x0201f800, 0x0010698c, 0x0201f800, - 0x001068f6, 0x0201f800, 0x00106982, 0x0201f000, - 0x000208b4, 0x4a026206, 0x00000001, 0x1c01f000, - 0x42000000, 0x0010b671, 0x0201f800, 0x0010a86e, - 0x4d2c0000, 0x4d400000, 0x417a5800, 0x0401fab1, - 0x04000007, 0x59325808, 0x592c0208, 0x8400054c, - 0x48025a08, 0x42028000, 0x00000006, 0x0201f800, - 0x0010698c, 0x0401ff4c, 0x4803c857, 0x82000c80, - 0x0000000e, 0x02021800, 0x00100615, 0x0c01f806, - 0x0201f800, 0x00106982, 0x5c028000, 0x5c025800, - 0x1c01f000, 0x00108bfd, 0x00108b69, 0x00108b79, - 0x00108ba0, 0x00108bce, 0x00108b67, 0x00108b30, - 0x00108b30, 0x00108b30, 0x00108b67, 0x00108b67, - 0x00108b67, 0x00108b67, 0x00108b79, 0x0201f800, - 0x00100615, 0x598c000d, 0x4803c857, 0x81300580, - 0x04020004, 0x0201f800, 0x00106be2, 0x0402003f, - 0x0201f800, 0x00106619, 0x04000043, 0x4803c856, - 0x0201f800, 0x001068a3, 0x04000038, 0x0201f800, - 0x00100615, 0x497a621d, 0x812e59c0, 0x02000800, - 0x00100615, 0x592c0204, 0x4803c857, 0x82000500, - 0x000000ff, 0x82000580, 0x00000014, 0x04000003, - 0x4a02621d, 0x00000003, 0x592c0a08, 0x0201f800, - 0x00104bee, 0x0201f800, 0x00109365, 0x0201f800, - 0x00020381, 0x497a6008, 0x4a026403, 0x00000085, - 0x4a026203, 0x00000009, 0x4a026406, 0x00000002, - 0x59300804, 0x82040d00, 0x00000100, 0x82040d40, - 0x8000404b, 0x48066004, 0x0201f800, 0x00106982, - 0x42000800, 0x8000404b, 0x0201f000, 0x00020855, - 0x0401feea, 0x04020004, 0x0201f800, 0x00106bb2, - 0x0402000a, 0x0201f800, 0x001064f6, 0x040207cc, - 0x59300c03, 0x4807c857, 0x82040580, 0x00000040, - 0x04000009, 0x0401f7cc, 0x59300203, 0x4803c857, - 0x82000c80, 0x0000000e, 0x02021800, 0x00100615, - 0x0c01f7a5, 0x0201f800, 0x00106982, 0x812e59c0, - 0x04000013, 0x592c0a08, 0x0201f800, 0x00104bee, - 0x0201f800, 0x00109365, 0x0201f800, 0x00020381, - 0x59300203, 0x82000580, 0x0000000d, 0x04000008, - 0x0201f800, 0x00106982, 0x4d340000, 0x59326809, - 0x0201f800, 0x00104801, 0x5c026800, 0x0201f800, - 0x00107698, 0x0401f030, 0x812e59c0, 0x02000800, - 0x00100615, 0x0201f800, 0x001091d3, 0x04020004, - 0x0201f800, 0x00100ee4, 0x0401f7a3, 0x0201f800, - 0x00106982, 0x592c0208, 0x8400050c, 0x48025a08, - 0x592c0406, 0x800000c2, 0x800008c4, 0x80040c00, - 0x48066206, 0x42000000, 0x10000000, 0x41300800, - 0x0201f800, 0x00100bde, 0x0400000d, 0x592c0208, - 0x8c00051c, 0x04020006, 0x8400055c, 0x48025a08, - 0x4a026206, 0x00000002, 0x0401f00f, 0x4d300000, - 0x0201f800, 0x00101335, 0x5c026000, 0x59300203, - 0x82000580, 0x00000004, 0x04020007, 0x4d380000, - 0x42027000, 0x00000048, 0x0201f800, 0x000208d8, - 0x5c027000, 0x1c01f000, 0x42000000, 0x0010b66d, - 0x0201f800, 0x0010a86e, 0x59300203, 0x82000c80, - 0x0000000e, 0x02021800, 0x00100615, 0x4803c857, - 0x0c01f001, 0x00108c17, 0x00108b39, 0x00108c19, - 0x00108c17, 0x00108c19, 0x00108c19, 0x00108b31, - 0x00108c17, 0x00108b2d, 0x00108c17, 0x00108c17, - 0x00108c17, 0x00108c17, 0x00108c17, 0x0201f800, - 0x00100615, 0x4d340000, 0x4d2c0000, 0x59326809, - 0x59340400, 0x82000500, 0x000000ff, 0x82000c80, - 0x0000000c, 0x02021800, 0x00100615, 0x59303403, - 0x82180d80, 0x00000004, 0x04020004, 0x42000000, - 0x00000001, 0x0401f006, 0x82180d80, 0x00000000, - 0x04020003, 0x42000000, 0x00000001, 0x4803c857, - 0x0c01f804, 0x5c025800, 0x5c026800, 0x1c01f000, - 0x00108c40, 0x00108cdf, 0x00108c42, 0x00108c77, - 0x00108c42, 0x00108cfc, 0x00108c42, 0x00108c4c, - 0x00108c40, 0x00108cfc, 0x00108c40, 0x00108c5b, - 0x0201f800, 0x00100615, 0x59300403, 0x82000d80, - 0x00000016, 0x0400002e, 0x82000d80, 0x00000004, - 0x0400002b, 0x82000d80, 0x00000002, 0x04000028, - 0x0401fab9, 0x04000079, 0x59300403, 0x82000d80, - 0x00000022, 0x040000ae, 0x82000d80, 0x00000039, - 0x040000b3, 0x82000d80, 0x00000035, 0x040000b0, - 0x82000d80, 0x0000001e, 0x0400001b, 0x0401f999, - 0x04000007, 0x0201f800, 0x00109360, 0x04020004, - 0x0201f800, 0x00104863, 0x0401f011, 0x59300403, - 0x82000d80, 0x00000001, 0x04020004, 0x0201f800, - 0x00104836, 0x0400000a, 0x4d3c0000, 0x417a7800, - 0x0201f800, 0x00101de2, 0x5c027800, 0x42000000, - 0x0010b663, 0x0201f800, 0x0010a86e, 0x0201f800, - 0x00107da6, 0x0201f000, 0x00107698, 0x0401f97d, - 0x04000004, 0x0201f800, 0x00109360, 0x040000a9, - 0x59300c03, 0x82040580, 0x00000016, 0x04000056, - 0x82040580, 0x00000002, 0x04020034, 0x59a80026, - 0x8c000502, 0x04020013, 0x0201f800, 0x00104e0d, - 0x04020010, 0x0201f800, 0x00104e23, 0x04020006, - 0x42000000, 0x00000001, 0x0201f800, 0x00104de5, - 0x0401f094, 0x4a035033, 0x00000001, 0x4202d800, - 0x00000001, 0x0201f800, 0x00104d76, 0x0401f08d, - 0x59340403, 0x82000580, 0x000007fc, 0x04000008, - 0x59a80026, 0x8c00050a, 0x04020084, 0x59340212, - 0x82000500, 0x0000ff00, 0x04000082, 0x59340412, - 0x82000500, 0x000000ff, 0x04000010, 0x80000040, - 0x48026c12, 0x497a6008, 0x4a026406, 0x00000007, - 0x4a026206, 0x00000398, 0x497a6205, 0x0201f800, - 0x00020892, 0x04000005, 0x49366009, 0x4a026406, - 0x00000001, 0x0401f020, 0x59300403, 0x82000d80, - 0x00000002, 0x0402000d, 0x59340403, 0x82000580, - 0x000007fe, 0x04020009, 0x59a80026, 0x84000540, - 0x48035026, 0x0201f800, 0x00104067, 0x0201f800, - 0x00107da6, 0x0401f00c, 0x0201f800, 0x00107da6, - 0x4d3c0000, 0x417a7800, 0x0201f800, 0x00101de2, - 0x5c027800, 0x42000000, 0x0010b663, 0x0201f800, - 0x0010a86e, 0x0201f800, 0x00101e1b, 0x0201f000, - 0x00107698, 0x42000800, 0x00000003, 0x0201f800, - 0x001043c7, 0x4a026203, 0x00000001, 0x4a026403, - 0x00000002, 0x0201f000, 0x00106470, 0x0401f915, - 0x04020793, 0x0201f800, 0x00101e1b, 0x4d3c0000, - 0x417a7800, 0x0201f800, 0x00101de2, 0x5c027800, - 0x42000000, 0x0010b663, 0x0201f800, 0x0010a86e, - 0x42003000, 0x00000018, 0x41782800, 0x42002000, - 0x00000000, 0x4d400000, 0x4d440000, 0x59368c03, - 0x42028000, 0x00000029, 0x0201f800, 0x0010962a, - 0x5c028800, 0x5c028000, 0x0201f000, 0x00107698, - 0x0201f800, 0x00104863, 0x0401f7c8, 0x42000000, - 0x0010b66c, 0x0201f800, 0x0010a86e, 0x0201f800, - 0x001078fd, 0x040207c1, 0x1c01f000, 0x4d380000, - 0x59327403, 0x0201f800, 0x00109183, 0x5c027000, - 0x02020000, 0x000208b4, 0x836c0580, 0x00000003, - 0x04000004, 0x4a026206, 0x00000002, 0x1c01f000, - 0x59300403, 0x48026416, 0x4a02621d, 0x00000001, - 0x4a026403, 0x00000085, 0x4a026203, 0x00000009, - 0x4a026406, 0x00000002, 0x42000800, 0x8000004b, - 0x0201f000, 0x00020855, 0x0201f800, 0x00101e1b, - 0x0201f800, 0x00107da6, 0x4d3c0000, 0x417a7800, - 0x0201f800, 0x00101de2, 0x5c027800, 0x42000000, - 0x0010b663, 0x0201f800, 0x0010a86e, 0x497a6008, - 0x4a026406, 0x00000007, 0x4a026206, 0x00000398, - 0x497a6205, 0x1c01f000, 0x42000000, 0x0010b66f, - 0x0201f800, 0x0010a86e, 0x4d340000, 0x59326809, - 0x59300203, 0x82000c80, 0x0000000e, 0x02021800, - 0x00100615, 0x4803c857, 0x0c01f803, 0x5c026800, - 0x1c01f000, 0x00108d53, 0x00108b39, 0x00108d53, - 0x00108d53, 0x00108d53, 0x00108d53, 0x00108d53, - 0x00108d53, 0x00108d53, 0x00108b39, 0x00108d55, - 0x00108b39, 0x00108d5d, 0x00108d53, 0x0201f800, - 0x00100615, 0x4a026403, 0x0000008b, 0x4a026203, - 0x0000000b, 0x42000800, 0x8000404b, 0x0201f000, - 0x00020855, 0x59300a1d, 0x4d3c0000, 0x417a7800, - 0x0201f800, 0x00101de2, 0x5c027800, 0x42003000, - 0x00000011, 0x0201f800, 0x0010a766, 0x42000000, - 0x0010b663, 0x0201f800, 0x0010a86e, 0x41306800, - 0x0201f800, 0x00020892, 0x04000008, 0x49366009, - 0x4d300000, 0x40366000, 0x0201f800, 0x00107698, - 0x5c026000, 0x0401f002, 0x40366000, 0x497a6008, - 0x4a026406, 0x00000001, 0x4a026403, 0x00000001, - 0x0201f800, 0x0010393e, 0x04000011, 0x4a026406, - 0x00000004, 0x4a026203, 0x00000007, 0x4a026420, - 0x00000001, 0x42003000, 0x00000004, 0x4d400000, - 0x42028000, 0x00000029, 0x41782800, 0x0201f800, - 0x0010a250, 0x5c028000, 0x1c01f000, 0x42000800, - 0x0000000b, 0x0201f800, 0x001043c7, 0x4a026203, - 0x00000001, 0x0201f000, 0x00106470, 0x42000000, - 0x0010b675, 0x0201f800, 0x0010a86e, 0x59300203, - 0x82000c80, 0x0000000e, 0x02021800, 0x00100615, - 0x4803c857, 0x0c01f001, 0x00108dc8, 0x00108db0, - 0x00108db4, 0x00108dc9, 0x00108db2, 0x00108db0, - 0x00108db0, 0x00108db0, 0x00108db0, 0x00108db0, - 0x00108db0, 0x00108db0, 0x00108db0, 0x00108db0, - 0x0201f800, 0x00100615, 0x0201f800, 0x00100ee4, - 0x4d2c0000, 0x59325808, 0x4a025a06, 0x00000006, - 0x0201f800, 0x00020381, 0x5c025800, 0x497a6008, - 0x4a02621d, 0x0000000a, 0x4a026403, 0x00000085, - 0x4a026203, 0x00000009, 0x4a026406, 0x00000002, - 0x42000800, 0x8000404b, 0x0201f000, 0x00020855, - 0x1c01f000, 0x0201f800, 0x0010698c, 0x4df00000, - 0x0401fcbe, 0x04020004, 0x0201f800, 0x00106bb2, - 0x0402000c, 0x0201f800, 0x001064f6, 0x04020005, - 0x5c03e000, 0x0201f800, 0x00106982, 0x0401f7dd, - 0x0201f800, 0x001068a3, 0x02020800, 0x00100615, - 0x5c03e000, 0x0201f800, 0x00106982, 0x59300203, - 0x82000d80, 0x00000003, 0x02000800, 0x00100615, - 0x82000c80, 0x0000000e, 0x02021800, 0x00100615, - 0x0c01f7ba, 0x4803c856, 0x59a8000e, 0x59a80867, - 0x80040400, 0x80080480, 0x04021004, 0x82000540, - 0x00000001, 0x1c01f000, 0x80000580, 0x1c01f000, - 0x4803c856, 0x4c080000, 0x59301008, 0x82081500, - 0xfff00000, 0x5c001000, 0x1c01f000, 0x4803c856, - 0x4d300000, 0x0201f800, 0x00020892, 0x0400000a, - 0x0401f82f, 0x4d380000, 0x42027000, 0x0000004b, - 0x0201f800, 0x000208d8, 0x5c027000, 0x82000540, - 0x00000001, 0x5c026000, 0x1c01f000, 0x4803c856, - 0x4d300000, 0x0201f800, 0x001076c9, 0x0400001b, - 0x0401f81f, 0x4d300000, 0x0201f800, 0x0010698c, - 0x4d3c0000, 0x417a7800, 0x0201f800, 0x001067f6, - 0x0201f800, 0x00106543, 0x5c027800, 0x0201f800, - 0x0010a0da, 0x0201f800, 0x00106982, 0x5c026000, - 0x8d3e7d3e, 0x0402000b, 0x4d380000, 0x42027000, - 0x0000004c, 0x0201f800, 0x000208d8, 0x5c027000, - 0x82000540, 0x00000001, 0x5c026000, 0x1c01f000, - 0x0201f800, 0x000208b4, 0x0401f7fa, 0x592c0407, - 0x494a6017, 0x494e6018, 0x49366009, 0x492e6008, - 0x4a026406, 0x00000003, 0x800000c2, 0x800008c4, - 0x80040400, 0x48026206, 0x1c01f000, 0x493bc857, - 0x4d300000, 0x0201f800, 0x00020892, 0x0400000d, - 0x0401ffef, 0x4d400000, 0x42028000, 0x00000005, - 0x0401f80d, 0x5c028000, 0x8d3e7d3e, 0x04020007, - 0x0201f800, 0x000208d8, 0x82000540, 0x00000001, - 0x5c026000, 0x1c01f000, 0x0201f800, 0x000208b4, - 0x0401f7fa, 0x4803c856, 0x0201f800, 0x0010698c, - 0x4d3c0000, 0x4d440000, 0x59368c03, 0x42027800, - 0x00000001, 0x0201f800, 0x001066ff, 0x0201f800, - 0x00106675, 0x0201f800, 0x00106543, 0x0201f800, - 0x0010a0da, 0x5c028800, 0x5c027800, 0x0201f000, - 0x00106982, 0x4803c856, 0x4d300000, 0x0201f800, - 0x00020892, 0x0400000f, 0x481a601c, 0x48ee6021, - 0x49366009, 0x4a026406, 0x00000001, 0x492e6008, - 0x4d380000, 0x42027000, 0x0000001f, 0x0201f800, - 0x000208d8, 0x5c027000, 0x82000540, 0x00000001, - 0x5c026000, 0x1c01f000, 0x4803c856, 0x4d300000, - 0x0201f800, 0x00020892, 0x0400000e, 0x48ee6021, - 0x49366009, 0x4a026406, 0x00000001, 0x492e6008, - 0x4d380000, 0x42027000, 0x00000055, 0x0201f800, - 0x000208d8, 0x5c027000, 0x82000540, 0x00000001, - 0x5c026000, 0x1c01f000, 0x4803c856, 0x4d300000, - 0x0201f800, 0x00020892, 0x0400000f, 0x481a601c, - 0x48ee6021, 0x49366009, 0x4a026406, 0x00000001, - 0x492e6008, 0x4d380000, 0x42027000, 0x0000003d, - 0x0201f800, 0x000208d8, 0x5c027000, 0x82000540, - 0x00000001, 0x5c026000, 0x1c01f000, 0x4803c856, - 0x4d300000, 0x0201f800, 0x001076c9, 0x04000014, - 0x49366009, 0x492fc857, 0x4933c857, 0x592c0404, - 0x8c00051e, 0x04000003, 0x48efc857, 0x48ee6021, - 0x4a026406, 0x00000001, 0x492e6008, 0x4d380000, - 0x42027000, 0x00000000, 0x0201f800, 0x000208d8, - 0x5c027000, 0x82000540, 0x00000001, 0x5c026000, - 0x1c01f000, 0x4803c856, 0x4d300000, 0x0201f800, - 0x00020892, 0x0400000f, 0x48ee6021, 0x481a601c, - 0x49366009, 0x4a026406, 0x00000001, 0x492e6008, - 0x4d380000, 0x42027000, 0x00000044, 0x0201f800, - 0x000208d8, 0x5c027000, 0x82000540, 0x00000001, - 0x5c026000, 0x1c01f000, 0x4803c856, 0x4d300000, - 0x0201f800, 0x00020892, 0x0400000f, 0x481a601c, - 0x48ee6021, 0x49366009, 0x4a026406, 0x00000001, - 0x492e6008, 0x4d380000, 0x42027000, 0x00000049, - 0x0201f800, 0x000208d8, 0x5c027000, 0x82000540, - 0x00000001, 0x5c026000, 0x1c01f000, 0x59300009, - 0x80001540, 0x02000800, 0x00100615, 0x5808040b, - 0x4803c856, 0x80000040, 0x04001002, 0x4800140b, - 0x1c01f000, 0x4803c856, 0x59300403, 0x82000d80, - 0x00000002, 0x0400000f, 0x82000d80, 0x00000003, - 0x0400000c, 0x82000d80, 0x00000004, 0x04000009, - 0x599c0819, 0x8c040d0e, 0x04000004, 0x82000d80, - 0x00000000, 0x04000003, 0x82000540, 0x00000001, - 0x1c01f000, 0x4803c856, 0x4c000000, 0x4d2c0000, - 0x59300406, 0x82000580, 0x00000004, 0x0400001d, - 0x59300008, 0x80025d40, 0x800001c0, 0x04000019, - 0x0201f800, 0x00109360, 0x04000014, 0x59300406, - 0x82004580, 0x00000010, 0x04000010, 0x82004580, - 0x00000011, 0x0400000d, 0x82004580, 0x00000003, - 0x0400000c, 0x82004580, 0x00000002, 0x04000009, - 0x82004580, 0x0000000a, 0x04000006, 0x592c0404, - 0x8c00051e, 0x04000003, 0x80000580, 0x0401f003, - 0x82000540, 0x00000001, 0x5c025800, 0x5c000000, - 0x1c01f000, 0x4803c856, 0x4d300000, 0x0201f800, - 0x001076c9, 0x04000013, 0x49366009, 0x48ee6021, - 0x4a026406, 0x00000001, 0x492e6008, 0x4d3c0000, - 0x417a7800, 0x0201f800, 0x00101de2, 0x5c027800, - 0x4d380000, 0x42027000, 0x00000028, 0x0201f800, - 0x000208d8, 0x5c027000, 0x82000540, 0x00000001, - 0x5c026000, 0x1c01f000, 0x4803c856, 0x83380580, - 0x00000015, 0x0402000d, 0x59a80016, 0x82000580, - 0x00000074, 0x04020009, 0x0201f800, 0x00104480, - 0x4a026203, 0x00000001, 0x4a026403, 0x00000029, - 0x0201f000, 0x00106470, 0x0201f800, 0x00107da6, - 0x0201f000, 0x000208b4, 0x4803c856, 0x83380580, - 0x00000016, 0x04020007, 0x42000800, 0x00000004, - 0x0201f800, 0x001043c7, 0x0201f000, 0x001078bf, - 0x83380580, 0x00000015, 0x04020013, 0x59a80016, - 0x82000580, 0x00000014, 0x0402000f, 0x0201f800, - 0x001044e1, 0x0201f800, 0x00108210, 0x0402000a, - 0x59340404, 0x80000540, 0x04000007, 0x42000800, - 0x00000006, 0x0201f800, 0x001043c7, 0x0201f000, - 0x001078bf, 0x0201f800, 0x00107da6, 0x0201f000, - 0x000208b4, 0x4803c856, 0x592c0206, 0x82000580, - 0x00000005, 0x04000002, 0x1c01f000, 0x4803c856, - 0x592c0208, 0x8400054a, 0x48025a08, 0x1c01f000, - 0x497a6205, 0x497a6008, 0x4a026203, 0x00000001, - 0x4a026403, 0x00000050, 0x42000800, 0x80000043, - 0x0201f000, 0x00020855, 0x4933c857, 0x4d340000, - 0x59326809, 0x59340200, 0x8c00050e, 0x04000006, - 0x59300406, 0x82000c80, 0x00000012, 0x04021004, - 0x0c01f806, 0x5c026800, 0x1c01f000, 0x0201f800, - 0x00108b30, 0x0401f7fc, 0x00108b30, 0x00108fb4, - 0x00108fb8, 0x00108fbb, 0x0010a2b9, 0x0010a2d6, - 0x0010a2da, 0x00108b30, 0x00108b30, 0x00108b30, - 0x00108b30, 0x00108b30, 0x00108b30, 0x00108b30, - 0x00108b30, 0x00108b30, 0x00108b30, 0x00108b30, - 0x4803c856, 0x40000000, 0x40000000, 0x1c01f000, - 0x40000000, 0x40000000, 0x1c01f000, 0x5930001c, - 0x4803c857, 0x59300414, 0x4933c857, 0x4803c857, - 0x8c000502, 0x04000005, 0x4803c857, 0x84000540, - 0x48026414, 0x1c01f000, 0x42000000, 0xd0000000, - 0x41300800, 0x0201f800, 0x00100bde, 0x0401f810, - 0x0402000e, 0x59300c14, 0x59300403, 0x82000580, - 0x00000040, 0x04000003, 0x84040d40, 0x0401f005, - 0x59a80037, 0x82000400, 0x0000000a, 0x48026205, - 0x84040d42, 0x48066414, 0x1c01f000, 0x4933c857, - 0x4d340000, 0x59326809, 0x59340200, 0x8c00050e, - 0x02000800, 0x00100615, 0x5930001c, 0x80000540, - 0x04020034, 0x59300403, 0x4803c857, 0x82000580, - 0x00000040, 0x04000004, 0x59a80021, 0x80000540, - 0x0402002a, 0x4d1c0000, 0x41323800, 0x0201f800, - 0x00020892, 0x04000023, 0x4932381c, 0x591c0414, - 0x84000542, 0x48023c14, 0x49366009, 0x591c0406, - 0x82000580, 0x00000003, 0x04000006, 0x591c0202, - 0x48026419, 0x591c0402, 0x48026219, 0x0401f005, - 0x591c0202, 0x48026219, 0x591c0402, 0x48026419, - 0x491e601e, 0x4a026406, 0x00000001, 0x4a026403, - 0x00000035, 0x4a026203, 0x00000001, 0x42000800, - 0x80000040, 0x0201f800, 0x00020855, 0x411e6000, - 0x5c023800, 0x80000580, 0x5c026800, 0x1c01f000, - 0x411e6000, 0x5c023800, 0x59a80039, 0x48026205, - 0x82000540, 0x00000001, 0x0401f7f8, 0x4933c857, - 0x4d2c0000, 0x4932381c, 0x4a026202, 0x0000ffff, - 0x591e5808, 0x591c0007, 0x8c00051e, 0x04000005, - 0x8400051e, 0x48023807, 0x497a5c09, 0x0401f018, - 0x592c0408, 0x8c000518, 0x04000015, 0x84000518, - 0x48025c08, 0x4d400000, 0x592e8206, 0x4a025a06, - 0x00000001, 0x0401fb34, 0x49425a06, 0x5c028000, - 0x497a5c09, 0x592c0408, 0x8c000512, 0x04000008, - 0x4d2c0000, 0x84000512, 0x48025c08, 0x592e5809, - 0x0201f800, 0x00100843, 0x5c025800, 0x59a80039, - 0x48026205, 0x591c0214, 0x48026216, 0x82000d80, - 0x00000001, 0x04000008, 0x4a023a03, 0x00000002, - 0x82000580, 0x00000005, 0x04000008, 0x497a6015, - 0x0401f01e, 0x591c0007, 0x84000540, 0x48023807, - 0x4a023a03, 0x00000004, 0x591c0414, 0x4803c857, - 0x8400051c, 0x84000554, 0x48023c14, 0x592c000f, - 0x40001000, 0x591c0816, 0x80040480, 0x040217f0, - 0x591c0016, 0x82000500, 0xfffffffc, 0x48026015, - 0x48023816, 0x591c0a14, 0x4807c857, 0x82040d80, - 0x00000005, 0x04020005, 0x480bc857, 0x4803c857, - 0x4a023812, 0xffffffff, 0x591c0402, 0x48026419, - 0x591c0202, 0x48026219, 0x591e6809, 0x49366009, - 0x4a026406, 0x00000001, 0x4a026403, 0x00000039, - 0x4a026203, 0x00000001, 0x42000800, 0x80000040, - 0x0201f800, 0x00020855, 0x5c025800, 0x1c01f000, - 0x4933c857, 0x59300414, 0x8c000514, 0x04000015, - 0x8c00051c, 0x04020012, 0x59300016, 0x80100480, - 0x04001006, 0x04000005, 0x59300414, 0x84000514, - 0x8400055c, 0x0401f009, 0x48126016, 0x48126012, - 0x40100000, 0x592c180f, 0x800c0480, 0x48026011, - 0x59300414, 0x84000514, 0x48026414, 0x1c01f000, - 0x4933c857, 0x8c00051c, 0x04020006, 0x59300012, - 0x48026016, 0x59300414, 0x8400055c, 0x48026414, - 0x1c01f000, 0x59300c03, 0x4933c857, 0x4807c857, - 0x82040480, 0x00000034, 0x04001006, 0x82040480, - 0x0000003c, 0x04021003, 0x80000580, 0x1c01f000, - 0x82000540, 0x00000001, 0x0401f7fd, 0x41780800, - 0x59a81035, 0x42000000, 0x00000032, 0x0201f800, - 0x001063ee, 0x800811c0, 0x04020003, 0x42001000, - 0x00000014, 0x480b5037, 0x59a81036, 0x480b502d, - 0x41780800, 0x42000000, 0x00000064, 0x0201f800, - 0x001063ee, 0x800811c0, 0x04020003, 0x42001000, - 0x00000014, 0x480b5038, 0x82081400, 0x0000000a, - 0x480b5039, 0x42000800, 0x00000001, 0x0201f800, - 0x001069af, 0x42000000, 0x30000000, 0x40080800, - 0x0201f800, 0x00100bb2, 0x42000800, 0x00000003, - 0x59a81010, 0x0201f800, 0x001069af, 0x0201f000, - 0x00104755, 0x4a035037, 0x00000028, 0x4a035038, - 0x00000014, 0x4a03502d, 0x000007d0, 0x42001000, - 0x0000001e, 0x480b5039, 0x42000800, 0x00000001, - 0x0201f800, 0x001069af, 0x42000000, 0x30000000, - 0x40080800, 0x0201f800, 0x00100bb2, 0x42000800, - 0x00000003, 0x59a81010, 0x0201f000, 0x001069af, - 0x4933c857, 0x4d2c0000, 0x59300403, 0x82000580, - 0x0000003e, 0x04020005, 0x59325817, 0x812e59c0, - 0x02020800, 0x0010083a, 0x5c025800, 0x1c01f000, - 0x4937c857, 0x4d300000, 0x0201f800, 0x00020892, - 0x04000011, 0x49366009, 0x4a026406, 0x00000001, - 0x492e6008, 0x42000800, 0x00000009, 0x0201f800, - 0x001043c7, 0x4d380000, 0x42027000, 0x00000033, - 0x0201f800, 0x000208d8, 0x5c027000, 0x82000540, - 0x00000001, 0x5c026000, 0x1c01f000, 0x4933c857, - 0x4d2c0000, 0x4c580000, 0x4d3c0000, 0x59325808, - 0x83380580, 0x00000015, 0x04020025, 0x59a8b016, - 0x82580c80, 0x00000019, 0x04001003, 0x4200b000, - 0x00000018, 0x8058b104, 0x0401fa0a, 0x80000580, - 0x0401fa1a, 0x832cac00, 0x00000009, 0x83cca400, - 0x00000006, 0x0201f800, 0x0010a93e, 0x4c600000, - 0x4200c000, 0x00000001, 0x592c100a, 0x8c081518, - 0x04020006, 0x59a80010, 0x592c100d, 0x80080580, - 0x04020007, 0x4178c000, 0x59301009, 0x58081403, - 0x417a7800, 0x0201f800, 0x00101e48, 0x5c00c000, - 0x0201f800, 0x001078bf, 0x0401f008, 0x4200b000, - 0x00000002, 0x0401fa09, 0x0201f800, 0x00107da6, - 0x0201f800, 0x000208b4, 0x5c027800, 0x5c00b000, - 0x5c025800, 0x1c01f000, 0x4933c856, 0x49366009, - 0x4a026406, 0x00000001, 0x492e6008, 0x4d380000, - 0x42027000, 0x0000004d, 0x0201f800, 0x000208d8, - 0x5c027000, 0x82000540, 0x00000001, 0x1c01f000, - 0x4803c856, 0x4d2c0000, 0x83380580, 0x00000015, - 0x04020027, 0x59a80816, 0x59325808, 0x5930040b, - 0x800000c4, 0x80040580, 0x04020021, 0x4c500000, - 0x4c540000, 0x4c580000, 0x83cca400, 0x00000006, - 0x4050a800, 0x5930b40b, 0x0201f800, 0x0010a94f, - 0x83cca400, 0x00000006, 0x592cb205, 0x832cac00, - 0x00000006, 0x0201f800, 0x0010a93e, 0x592e5801, - 0x812e59c0, 0x040207f9, 0x5931d821, 0x58ef400b, - 0x58ee580d, 0x4a025a04, 0x00000103, 0x58ec0009, - 0x0801f800, 0x59300402, 0x5c00b000, 0x5c00a800, - 0x5c00a000, 0x5c025800, 0x1c01f000, 0x0201f800, - 0x00107da6, 0x5c025800, 0x1c01f000, 0x4933c857, - 0x83380580, 0x00000035, 0x04000005, 0x59301419, - 0x0401f851, 0x04000027, 0x0401f006, 0x4d300000, - 0x5932601e, 0x0401f856, 0x5c026000, 0x04000020, - 0x591c0c06, 0x82040580, 0x00000003, 0x04000004, - 0x82040580, 0x00000006, 0x0402001c, 0x591c0c02, - 0x59300419, 0x80040580, 0x04000009, 0x59300219, - 0x80040580, 0x04020015, 0x591c0a02, 0x59300419, - 0x80040580, 0x04020011, 0x0401f009, 0x59300a19, - 0x82040580, 0x0000ffff, 0x04000005, 0x591c0202, - 0x59300a19, 0x80040580, 0x04020008, 0x591c0009, - 0x59300809, 0x80040580, 0x1c01f000, 0x417a3800, - 0x82000540, 0x00000001, 0x1c01f000, 0x4803c856, - 0x59b800e4, 0x8c000538, 0x02020800, 0x00100615, - 0x42000800, 0x0000012c, 0x4a0370e4, 0x20000000, - 0x59b800e4, 0x80040840, 0x02000800, 0x00100615, - 0x8c00053c, 0x040207f9, 0x4a0370e4, 0x30000000, - 0x40000000, 0x40000000, 0x40000000, 0x59b800e4, - 0x8c00053c, 0x040207f1, 0x1c01f000, 0x4803c856, - 0x4a0370e4, 0x20000000, 0x40000000, 0x59b800e4, - 0x8c000538, 0x040207fb, 0x1c01f000, 0x59300807, - 0x8c040d1e, 0x592c0c08, 0x04020002, 0x8c040d18, - 0x1c01f000, 0x0401fc10, 0x04000008, 0x42000800, - 0x00000024, 0x0201f800, 0x001063cf, 0x82063c00, - 0x0010cfc0, 0x491fc857, 0x1c01f000, 0x83300480, - 0x0010cfc0, 0x0400100a, 0x59a8000b, 0x81300480, - 0x04021007, 0x59301402, 0x0401ffef, 0x04000007, - 0x411c0000, 0x81300580, 0x04000003, 0x81780500, - 0x0401f002, 0x81300540, 0x1c01f000, 0x4947c857, - 0x4d300000, 0x0201f800, 0x00020267, 0x0402000a, - 0x42026000, 0x0010bbe8, 0x49366009, 0x492e6008, - 0x0201f800, 0x00101de2, 0x80000580, 0x5c026000, - 0x1c01f000, 0x82000540, 0x00000001, 0x0401f7fc, - 0x4933c857, 0x0201f800, 0x00108df4, 0x02000800, - 0x00100615, 0x4d2c0000, 0x4d340000, 0x4d440000, - 0x4c580000, 0x59325808, 0x59326809, 0x49425a06, - 0x0201f800, 0x00105439, 0x592e8c06, 0x592c4207, - 0x82200500, 0x0000000f, 0x0c01f806, 0x5c00b000, - 0x5c028800, 0x5c026800, 0x5c025800, 0x1c01f000, - 0x0010922f, 0x00109251, 0x00109258, 0x0010925c, - 0x00109265, 0x0010922c, 0x0010922c, 0x0010922c, - 0x00109269, 0x00109275, 0x00109275, 0x0010922c, - 0x0010922c, 0x0010922c, 0x0010922c, 0x0010922c, - 0x4803c857, 0x0201f800, 0x00100615, 0x814281c0, - 0x04020012, 0x41785800, 0x592c0404, 0x8c00051c, - 0x04020002, 0x59345c05, 0x442c2800, 0x59340008, - 0x48002802, 0x59340009, 0x48002801, 0x59340006, - 0x48002804, 0x59340007, 0x48002803, 0x4200b000, - 0x0000000b, 0x0401f037, 0x592c0207, 0x8c00051e, - 0x4200b000, 0x00000002, 0x04020032, 0x8204b540, - 0x00000000, 0x0400002f, 0x44042800, 0x59326809, - 0x59340400, 0x48002801, 0x4200b000, 0x00000002, - 0x0401f028, 0x814281c0, 0x04020030, 0x59345c05, - 0x442c2800, 0x4200b000, 0x00000001, 0x0401f021, - 0x8340b540, 0x00000000, 0x0400001e, 0x0401f027, - 0x814281c0, 0x04020025, 0x59340200, 0x44002800, - 0x59340001, 0x48002801, 0x4200b000, 0x00000002, - 0x0401f014, 0x8340b540, 0x00000000, 0x0402001b, - 0x0401f010, 0x8340b540, 0x00000000, 0x0400000d, - 0x0201f800, 0x00104871, 0x04000014, 0x8c20450e, - 0x04000002, 0x497a6009, 0x4178b000, 0x497a5a06, - 0x0401f004, 0x8340b540, 0x00000000, 0x0402000b, - 0x592c0404, 0x8400051c, 0x48025c04, 0x592c0207, - 0x8400051e, 0x48025a07, 0x0401f8aa, 0x497a6008, - 0x0201f000, 0x00020381, 0x592c0207, 0x8c00051e, - 0x4200b000, 0x00000002, 0x040207f2, 0x8204b540, - 0x00000000, 0x040007ef, 0x44042800, 0x4200b000, - 0x00000001, 0x0401f7eb, 0x4937c857, 0x4d300000, - 0x0201f800, 0x00020892, 0x04000011, 0x49366009, - 0x4a026406, 0x00000001, 0x492e6008, 0x42000800, - 0x0000000b, 0x0201f800, 0x001043c7, 0x4d380000, - 0x42027000, 0x00000043, 0x0201f800, 0x000208d8, - 0x5c027000, 0x82000540, 0x00000001, 0x5c026000, - 0x1c01f000, 0x4937c857, 0x4d2c0000, 0x59325808, - 0x83380580, 0x00000015, 0x04020025, 0x59a80016, - 0x82000580, 0x00000004, 0x04020021, 0x59a80010, - 0x592c1009, 0x80080580, 0x04020010, 0x4d440000, - 0x592e8c06, 0x592c0207, 0x4803c856, 0x82000500, - 0x00000080, 0x84000548, 0x4d3c0000, 0x42027800, - 0x00001000, 0x0201f800, 0x0010480a, 0x5c027800, - 0x5c028800, 0x0401f004, 0x4803c856, 0x0201f800, - 0x00104871, 0x0201f800, 0x00108df4, 0x04000017, - 0x4d400000, 0x42028000, 0x00000000, 0x41780800, - 0x0401ff38, 0x5c028000, 0x0401f00e, 0x0201f800, - 0x00104871, 0x040207f4, 0x0201f800, 0x00108df4, - 0x0400000a, 0x4c580000, 0x4200b000, 0x00000002, - 0x0401f86e, 0x5c00b000, 0x0201f800, 0x00107da6, - 0x0201f800, 0x000208b4, 0x5c025800, 0x1c01f000, - 0x4937c857, 0x4d300000, 0x0201f800, 0x00020892, - 0x04000012, 0x49366009, 0x4a026406, 0x00000001, - 0x4d3c0000, 0x4d380000, 0x417a7800, 0x0201f800, - 0x001043bd, 0x492e6008, 0x42027000, 0x00000004, - 0x0201f800, 0x000208d8, 0x5c027000, 0x5c027800, - 0x82000540, 0x00000001, 0x5c026000, 0x1c01f000, - 0x4937c857, 0x4d300000, 0x0201f800, 0x001076c9, - 0x0400000d, 0x49366009, 0x4a026406, 0x00000001, - 0x492e6008, 0x4d380000, 0x42027000, 0x00000051, - 0x0201f800, 0x000208d8, 0x5c027000, 0x82000540, - 0x00000001, 0x5c026000, 0x1c01f000, 0x4933c857, - 0x4c580000, 0x59325808, 0x83383580, 0x00000015, - 0x04020011, 0x592c0008, 0x82000500, 0x00ffffff, - 0x0402000a, 0x0201f800, 0x00105439, 0x59cc0000, - 0x82000500, 0x00ffffff, 0x44002800, 0x4200b000, - 0x00000001, 0x0401f80b, 0x0201f800, 0x001078bf, - 0x0401f006, 0x4200b000, 0x00000002, 0x0401f823, - 0x0201f800, 0x00107da6, 0x5c00b000, 0x1c01f000, - 0x492fc857, 0x4c580000, 0x4c000000, 0x8058b1c0, - 0x0400000b, 0x82580500, 0xfffffff0, 0x02020800, - 0x00100615, 0x8058b0d0, 0x592c0408, 0x82000500, - 0xfffff0ff, 0x80580540, 0x48025c08, 0x5c000000, - 0x5c00b000, 0x1c01f000, 0x492fc857, 0x4c000000, - 0x4c040000, 0x800000d8, 0x592c0c08, 0x82040d00, - 0xffff0fff, 0x80040540, 0x48025c08, 0x5c000800, - 0x5c000000, 0x1c01f000, 0x4933c857, 0x4d2c0000, - 0x59325808, 0x592c0207, 0x8400055e, 0x48025a07, - 0x4c500000, 0x4c540000, 0x4c580000, 0x0401ffd9, - 0x0201f800, 0x00105439, 0x46002800, 0x00000018, - 0x80142800, 0x8058b040, 0x83cca400, 0x00000007, - 0x4014a800, 0x0201f800, 0x0010a93e, 0x5c00b000, - 0x5c00a800, 0x5c00a000, 0x5c025800, 0x1c01f000, - 0x59325808, 0x592c0204, 0x82000580, 0x00000152, - 0x1c01f000, 0x5930001f, 0x80000540, 0x02020800, - 0x00100d9a, 0x1c01f000, 0x4d2c0000, 0x59325808, - 0x59300203, 0x4933c857, 0x492fc857, 0x493bc857, - 0x4803c857, 0x82003480, 0x0000000e, 0x02021800, - 0x00100615, 0x0c01f803, 0x5c025800, 0x1c01f000, - 0x00109386, 0x00109391, 0x001093cf, 0x00109386, - 0x00109386, 0x00109386, 0x00109386, 0x00109386, - 0x00109388, 0x00109386, 0x00109386, 0x00109386, - 0x00109386, 0x00109386, 0x0201f800, 0x00100615, - 0x83383480, 0x00000056, 0x02021800, 0x00100615, - 0x493a6403, 0x4a026203, 0x00000001, 0x0201f000, - 0x00106470, 0x83380580, 0x00000013, 0x04020010, - 0x4937c857, 0x592c000c, 0x800001c0, 0x04000006, - 0x4a026203, 0x00000002, 0x59a80037, 0x48026206, - 0x1c01f000, 0x4a025a06, 0x00000000, 0x0201f800, - 0x00020381, 0x0201f000, 0x000208b4, 0x83380580, - 0x00000027, 0x0400001b, 0x83380580, 0x00000014, - 0x04000012, 0x83380580, 0x00000015, 0x04000005, - 0x83380580, 0x00000016, 0x02020800, 0x00100615, - 0x0201f800, 0x00106cb4, 0x02020000, 0x001076fb, - 0x59300203, 0x82000580, 0x00000002, 0x02020800, - 0x00100615, 0x0401f016, 0x4937c857, 0x0201f800, - 0x001068f6, 0x4a02580e, 0x00000011, 0x0401f006, - 0x4937c857, 0x0201f800, 0x001068f6, 0x4a02580e, - 0x00000010, 0x4a025a06, 0x00000031, 0x4a02580d, - 0x00000004, 0x0201f800, 0x00020381, 0x0201f800, - 0x00104a83, 0x0201f000, 0x00107698, 0x59341400, - 0x82081d00, 0x000000ff, 0x59300c03, 0x480bc857, - 0x4807c857, 0x82040580, 0x00000053, 0x0400002e, - 0x82040580, 0x00000002, 0x04000016, 0x82040580, - 0x00000001, 0x04000017, 0x82040580, 0x00000003, - 0x0400001c, 0x82040580, 0x00000005, 0x0400001d, - 0x82040580, 0x00000033, 0x0400001a, 0x82040580, - 0x00000000, 0x0400001b, 0x82040580, 0x00000004, - 0x02020800, 0x00100615, 0x0401f8a1, 0x0401f016, - 0x820c0580, 0x00000003, 0x0400084c, 0x0401f012, - 0x820c0580, 0x0000000b, 0x0402000f, 0x42000800, - 0x00000007, 0x0201f800, 0x001043c7, 0x0401f00a, - 0x820c0580, 0x00000005, 0x04000864, 0x0401f006, - 0x820c0580, 0x00000009, 0x04000889, 0x0401f002, - 0x0401f893, 0x4a026403, 0x00000052, 0x59a81016, - 0x592c040b, 0x8c000500, 0x04000003, 0x42001000, - 0x00000008, 0x592c040b, 0x8c000516, 0x04000003, - 0x82081400, 0x00000018, 0x592c000c, 0x497a580d, - 0x497a580e, 0x80080c80, 0x04000009, 0x04001005, - 0x4a025a06, 0x00000007, 0x40001000, 0x0401f006, - 0x4a025a06, 0x00000015, 0x0401f003, 0x4a025a06, - 0x00000000, 0x480a580c, 0x82081400, 0x00000003, - 0x80081104, 0x0201f800, 0x0010783c, 0x04000010, - 0x592c1001, 0x480a600b, 0x58080800, 0x82080400, - 0x00000002, 0x592c1011, 0x592c1812, 0x42003000, - 0x00000000, 0x42002000, 0x00101250, 0x0201f800, - 0x001079b9, 0x04000002, 0x1c01f000, 0x4a025a06, - 0x0000002c, 0x497a580c, 0x0201f800, 0x00020381, - 0x0201f000, 0x000208b4, 0x83380580, 0x00000015, - 0x0402000a, 0x59a8006f, 0x8c000502, 0x0402000b, - 0x0201f800, 0x00104480, 0x42000800, 0x00000004, - 0x0201f000, 0x001043c7, 0x42000800, 0x00000007, - 0x0201f000, 0x001043c7, 0x0201f800, 0x00104e0d, - 0x42001000, 0x00000010, 0x04020009, 0x59340002, - 0x82000500, 0x00ff0000, 0x82000580, 0x00ff0000, - 0x040007ec, 0x42001000, 0x00000008, 0x0201f800, - 0x00104ada, 0x040007e7, 0x592c040b, 0x84000540, - 0x48025c0b, 0x0401f7e9, 0x83380580, 0x00000015, - 0x0402000f, 0x59a8006f, 0x8c000502, 0x04020010, - 0x0201f800, 0x001044e1, 0x4d3c0000, 0x417a7800, - 0x0201f800, 0x001043bd, 0x5c027800, 0x42000800, - 0x00000006, 0x0201f000, 0x001043c7, 0x42000800, - 0x00000004, 0x0201f000, 0x001043c7, 0x0201f800, - 0x00104e0d, 0x42001000, 0x00000010, 0x04020009, - 0x59340002, 0x82000500, 0x00ff0000, 0x82000580, - 0x00ff0000, 0x040007e7, 0x42001000, 0x00000008, - 0x0201f800, 0x00104ada, 0x040007e2, 0x592c040b, - 0x84000540, 0x48025c0b, 0x0401f7e9, 0x42000800, - 0x00000004, 0x0201f000, 0x001043c7, 0x83380580, - 0x00000015, 0x04020005, 0x0201f800, 0x0010a0b1, - 0x02000800, 0x00104711, 0x1c01f000, 0x83380580, - 0x00000015, 0x0402001d, 0x4c580000, 0x83cc1400, - 0x00000008, 0x4200b000, 0x00000002, 0x83341c00, - 0x00000006, 0x0201f800, 0x001082ff, 0x04020012, - 0x83cc1400, 0x0000000a, 0x4200b000, 0x00000002, - 0x83341c00, 0x00000008, 0x0201f800, 0x001082ff, - 0x04020009, 0x59342200, 0x59cc1007, 0x800811c0, - 0x04000003, 0x480a6801, 0x84102542, 0x8410251a, - 0x48126a00, 0x5c00b000, 0x1c01f000, 0x42000000, - 0x0010b67a, 0x0201f800, 0x0010a86e, 0x0201f800, - 0x0010698c, 0x59300203, 0x4933c857, 0x4803c857, - 0x82000c80, 0x0000000e, 0x02021800, 0x00100615, - 0x0c01f803, 0x0201f000, 0x00106982, 0x001094d7, - 0x001094e6, 0x001094d8, 0x001094d5, 0x001094d5, - 0x001094d5, 0x001094d5, 0x001094d5, 0x001094d5, - 0x001094d5, 0x001094d5, 0x001094d5, 0x001094d5, - 0x001094d5, 0x0201f800, 0x00100615, 0x1c01f000, - 0x59300403, 0x82000580, 0x00000052, 0x02000000, - 0x00108b39, 0x0201f800, 0x00104a83, 0x59325808, - 0x4a025a06, 0x00000006, 0x0201f800, 0x00020381, - 0x0201f000, 0x00107698, 0x59301804, 0x840c0520, - 0x48026004, 0x598c000d, 0x81300580, 0x04020010, - 0x8c0c1d20, 0x04020010, 0x42001000, 0x0010b5f4, - 0x50081000, 0x58080002, 0x82000580, 0x00000100, - 0x0400000e, 0x5808000c, 0x81300580, 0x02020800, - 0x00100615, 0x4978100c, 0x0401f003, 0x8c0c1d20, - 0x040207dc, 0x0201f800, 0x00106619, 0x040007d9, - 0x0201f800, 0x00100615, 0x0201f800, 0x00106be2, - 0x040007f9, 0x59300203, 0x82000c80, 0x0000000e, - 0x02021800, 0x00100615, 0x0c01f7bd, 0x4933c857, - 0x4c500000, 0x4c540000, 0x4c580000, 0x592c0c07, - 0x4806580a, 0x59cc0809, 0x48065807, 0x59cc0a08, - 0x4806580b, 0x59a8086e, 0x82040500, 0x000003ff, - 0x800010c4, 0x8c040d14, 0x04000005, 0x59cc0002, - 0x82000500, 0x00000003, 0x80081480, 0x82080480, - 0x000000f1, 0x02021800, 0x00100615, 0x480a621a, - 0x412c0800, 0x0201f800, 0x00100819, 0x02000800, - 0x00100615, 0x492c0809, 0x58040408, 0x84000552, - 0x84000540, 0x48000c08, 0x82081400, 0x00000003, - 0x80081104, 0x83cca400, 0x00000006, 0x832cac00, - 0x00000004, 0x42000800, 0x00000010, 0x82080480, - 0x00000010, 0x04021003, 0x40080800, 0x80000580, - 0x4004b000, 0x4c000000, 0x0201f800, 0x0010a94f, - 0x5c000000, 0x800001c0, 0x0400000d, 0x412c1000, - 0x4c000000, 0x0201f800, 0x00100819, 0x02000800, - 0x00100615, 0x492c1001, 0x832cac00, 0x00000004, - 0x5c000000, 0x40001000, 0x0401f7e9, 0x5c00b000, - 0x5c00a800, 0x5c00a000, 0x1c01f000, 0x4933c857, - 0x4d2c0000, 0x4c380000, 0x59325808, 0x5930021a, - 0x48025a08, 0x59301011, 0x800811c0, 0x04020008, - 0x4a025a06, 0x00000000, 0x592c000b, 0x82000500, - 0x00000c00, 0x0400000b, 0x0401f00b, 0x8c08153e, - 0x04000006, 0x4a025a06, 0x00000007, 0x80081080, - 0x80081000, 0x0401f003, 0x4a025a06, 0x00000015, - 0x480a5807, 0x42000000, 0x0010bcd8, 0x50007000, - 0x5838000b, 0x80000540, 0x04020008, 0x4930700c, - 0x4930700b, 0x58380002, 0x82000580, 0x00000000, - 0x04020809, 0x0401f005, 0x82001400, 0x00000000, - 0x45301000, 0x4930700b, 0x5c007000, 0x5c025800, - 0x1c01f000, 0x4933c857, 0x592c0009, 0x40001000, - 0x4800700a, 0x82080400, 0x00000004, 0x48007003, - 0x592c000d, 0x592c100e, 0x48007007, 0x48087008, - 0x592c000a, 0x592c1208, 0x80080c80, 0x04001002, - 0x40001000, 0x82081400, 0x00000003, 0x80081104, - 0x82080480, 0x00000010, 0x04021003, 0x80000580, - 0x0401f003, 0x42001000, 0x00000010, 0x4800700d, - 0x48087004, 0x800810c4, 0x48087005, 0x40381000, - 0x0201f800, 0x001008a1, 0x1c01f000, 0x4d2c0000, - 0x0201f800, 0x00100819, 0x02000800, 0x00100615, - 0x42000800, 0x0010bcd8, 0x452c0800, 0x497a580b, - 0x497a580c, 0x497a580d, 0x4a025809, 0x001095b6, - 0x4a025802, 0x00000100, 0x4a025801, 0x00000000, - 0x5c025800, 0x1c01f000, 0x4833c857, 0x4d300000, - 0x4d2c0000, 0x4c5c0000, 0x4030b800, 0x585c000a, - 0x80025d40, 0x04020004, 0x585c000c, 0x4c000000, - 0x0401f044, 0x585c0002, 0x82000580, 0x00000100, - 0x04020022, 0x592c0801, 0x4c040000, 0x0201f800, - 0x0010083a, 0x5c000800, 0x800409c0, 0x0400001c, - 0x4804b80a, 0x585c100d, 0x800811c0, 0x04020005, - 0x40065800, 0x0201f800, 0x00100843, 0x0401f014, - 0x82080480, 0x00000010, 0x04021003, 0x80000580, - 0x0401f003, 0x42001000, 0x00000010, 0x4800b80d, - 0x4808b804, 0x800810c4, 0x4808b805, 0x82040400, - 0x00000004, 0x4800b803, 0x405c1000, 0x0201f800, - 0x001008a1, 0x0401f025, 0x0401f828, 0x585c000c, - 0x80026540, 0x59300000, 0x80000d40, 0x04020002, - 0x4800b80b, 0x4800b80c, 0x497a6000, 0x4c000000, - 0x4978b80a, 0x59325808, 0x4a025a04, 0x00000103, - 0x59300402, 0x48025c06, 0x592c100b, 0x4c080000, - 0x0201f800, 0x00020381, 0x0201f800, 0x00108ee7, - 0x5c001000, 0x8c081518, 0x04000004, 0x0201f800, - 0x00108f88, 0x0401f003, 0x0201f800, 0x000208b4, - 0x405c7000, 0x5c000000, 0x80026540, 0x04000003, - 0x59325808, 0x0401ff78, 0x5c00b800, 0x5c025800, - 0x5c026000, 0x1c01f000, 0x483bc857, 0x5838000a, - 0x40025800, 0x0201f800, 0x00100843, 0x5838000c, - 0x80026540, 0x59300008, 0x80025d40, 0x4a025a06, - 0x00000002, 0x1c01f000, 0x4803c857, 0x4d1c0000, - 0x497a601c, 0x41323800, 0x40026000, 0x4d3c0000, - 0x42027800, 0x00000005, 0x0401f840, 0x5c027800, - 0x411e6000, 0x59300414, 0x84000502, 0x48026414, - 0x5c023800, 0x1c01f000, 0x481bc857, 0x4933c857, - 0x4c5c0000, 0x4c600000, 0x4010b800, 0x4014c000, - 0x0201f800, 0x0010a766, 0x0201f800, 0x0010393e, - 0x04000008, 0x40602800, 0x405c3000, 0x0201f800, - 0x0010a258, 0x82000540, 0x00000001, 0x0401f002, - 0x80000580, 0x5c00c000, 0x5c00b800, 0x1c01f000, - 0x4803c856, 0x4d300000, 0x42026000, 0x0010cfc0, - 0x59a8000e, 0x81640580, 0x0400001a, 0x59300c06, - 0x82040580, 0x00000001, 0x0400000d, 0x82040580, - 0x00000004, 0x04000006, 0x82040580, 0x00000010, - 0x02000800, 0x00108aad, 0x0401f009, 0x59300203, - 0x82000d80, 0x00000007, 0x04000005, 0x4807c857, - 0x0201f800, 0x0010909d, 0x04020808, 0x83326400, - 0x00000024, 0x41580000, 0x81300480, 0x040017e5, - 0x5c026000, 0x1c01f000, 0x4933c857, 0x59300403, - 0x4803c857, 0x0201f800, 0x0010698c, 0x4df00000, - 0x59300406, 0x4803c857, 0x82000d80, 0x00000002, - 0x04000018, 0x82000d80, 0x00000001, 0x04000009, - 0x82000d80, 0x00000004, 0x04000006, 0x4933c856, - 0x5c03e000, 0x02000800, 0x00106982, 0x0401f03c, - 0x59300203, 0x82000d80, 0x00000001, 0x04000018, - 0x82000d80, 0x00000002, 0x04000026, 0x82000d80, - 0x00000005, 0x04000023, 0x0201f800, 0x00100615, - 0x59300203, 0x82000d80, 0x00000009, 0x0400000c, - 0x82000d80, 0x0000000b, 0x04000009, 0x82000d80, - 0x0000000a, 0x04000017, 0x82000d80, 0x0000000c, - 0x04000014, 0x0201f800, 0x00100615, 0x598c000d, - 0x81300580, 0x04020004, 0x0201f800, 0x00106be2, - 0x0402000c, 0x59300004, 0x4803c857, 0x8c000520, - 0x04000004, 0x84000520, 0x48026004, 0x0401f005, - 0x0201f800, 0x00106619, 0x02020800, 0x00100615, - 0x5c03e000, 0x02000800, 0x00106982, 0x59300406, - 0x82000d80, 0x00000002, 0x04000009, 0x0201f800, - 0x00104a83, 0x0201f800, 0x00108f05, 0x02000800, - 0x00107da6, 0x8d3e7d00, 0x04000003, 0x0201f000, - 0x00107698, 0x4a02621d, 0x00000001, 0x4a026403, - 0x00000085, 0x4a026203, 0x00000009, 0x4a026406, - 0x00000002, 0x42000800, 0x8000004b, 0x0201f000, - 0x00020855, 0x4933c857, 0x59368c03, 0x4c180000, - 0x59300203, 0x82003480, 0x0000000e, 0x02021800, - 0x00100615, 0x0c01f803, 0x5c003000, 0x1c01f000, - 0x001096da, 0x00109bb9, 0x00109cbd, 0x001096da, - 0x001096da, 0x001096da, 0x001096da, 0x001096da, - 0x001096fd, 0x001096da, 0x001096da, 0x001096da, - 0x001096da, 0x001096da, 0x0201f800, 0x00100615, - 0x4933c857, 0x42028800, 0x0000ffff, 0x813669c0, - 0x04000002, 0x59368c03, 0x4c180000, 0x59300203, - 0x82003480, 0x0000000e, 0x02021800, 0x00100615, - 0x0c01f803, 0x5c003000, 0x1c01f000, 0x001096f9, - 0x00109f70, 0x001096f9, 0x001096f9, 0x001096f9, - 0x001096f9, 0x001096f9, 0x0010a779, 0x00109edd, - 0x0010a34a, 0x0010a380, 0x0010a34a, 0x0010a380, - 0x001096f9, 0x0201f800, 0x00100615, 0x0201f800, - 0x00100615, 0x83383480, 0x00000051, 0x02021800, - 0x00100615, 0x41380000, 0x493bc857, 0x4d1c0000, - 0x4d400000, 0x0c01f804, 0x5c028000, 0x5c023800, - 0x1c01f000, 0x0010975a, 0x0010993d, 0x0010975a, - 0x0010975a, 0x0010975a, 0x00109948, 0x0010975a, - 0x0010975a, 0x0010975a, 0x0010975a, 0x0010975a, - 0x0010975a, 0x0010975a, 0x0010975a, 0x0010975a, - 0x0010975a, 0x0010975a, 0x0010975a, 0x0010975a, - 0x0010975a, 0x0010975a, 0x0010975a, 0x0010975a, - 0x0010977c, 0x001097ba, 0x001097d1, 0x0010982d, - 0x00109894, 0x001098d2, 0x00109902, 0x0010975a, - 0x0010975a, 0x00109950, 0x0010975a, 0x0010975a, - 0x0010995e, 0x00109967, 0x0010975a, 0x0010975a, - 0x0010975a, 0x0010975a, 0x0010975a, 0x001099e9, - 0x0010975a, 0x0010975a, 0x00109868, 0x0010975a, - 0x0010975a, 0x001099c0, 0x0010975a, 0x0010975a, - 0x0010975a, 0x001099f7, 0x0010975a, 0x0010975a, - 0x0010975a, 0x00109a40, 0x0010975a, 0x0010975a, - 0x0010975a, 0x0010975a, 0x0010975a, 0x0010975a, - 0x00109a8d, 0x0010975a, 0x00109ab9, 0x00109ac4, - 0x0010975a, 0x0010975a, 0x0010975c, 0x00109acf, - 0x0010975a, 0x0010975a, 0x0010975a, 0x0010976b, - 0x0010975a, 0x0010975a, 0x0010975a, 0x00109ad6, - 0x00109ade, 0x00109afc, 0x0201f800, 0x00100615, - 0x4933c857, 0x0201f800, 0x0010a3b0, 0x040203a8, - 0x0201f800, 0x00101eb0, 0x040203a5, 0x59cc0407, - 0x4802601c, 0x4a026403, 0x00000045, 0x4a026203, - 0x00000001, 0x0201f000, 0x00106470, 0x4933c857, - 0x0201f800, 0x0010a3b0, 0x04020399, 0x0201f800, - 0x00101eb0, 0x04020396, 0x0401fbd6, 0x0402019e, - 0x59cc0007, 0x4802601c, 0x4a026403, 0x0000004a, - 0x4a026203, 0x00000001, 0x0201f000, 0x00106470, - 0x4933c857, 0x0201f800, 0x00101eb0, 0x04020009, - 0x0201f800, 0x0010473b, 0x04020006, 0x82000500, - 0x00000009, 0x82000580, 0x00000008, 0x04020008, - 0x4a026403, 0x00000009, 0x4a02641a, 0x00000009, - 0x4a02621a, 0x00000000, 0x0401f1b6, 0x0201f800, - 0x00104858, 0x04000018, 0x0201f800, 0x0010a041, - 0x0402001f, 0x42028000, 0x00000029, 0x4d3c0000, - 0x417a7800, 0x0201f800, 0x00101de2, 0x5c027800, - 0x0201f800, 0x00104480, 0x4a026403, 0x00000008, - 0x42003000, 0x00000003, 0x0201f800, 0x0010393e, - 0x040001a0, 0x4a026203, 0x00000007, 0x41782800, - 0x0401f18b, 0x0201f800, 0x0010a1ec, 0x040207e7, - 0x4a026403, 0x00000009, 0x4a02641a, 0x0000000e, - 0x4a02621a, 0x00001900, 0x0401f192, 0x4a026403, - 0x00000009, 0x4a02641a, 0x00000003, 0x4a02621a, - 0x00000f00, 0x0401f18b, 0x4933c857, 0x0201f800, - 0x00101eb0, 0x0402034a, 0x0201f800, 0x0010473b, - 0x04020347, 0x493a6403, 0x0201f800, 0x0010a01c, - 0x04020006, 0x42003000, 0x00000005, 0x4a026403, - 0x00000006, 0x0401f7d9, 0x4a026403, 0x00000007, - 0x4a02641a, 0x00000009, 0x4a02621a, 0x00000000, - 0x0401f174, 0x4933c857, 0x0201f800, 0x0010473b, - 0x04020333, 0x0201f800, 0x0010a3b0, 0x02000800, - 0x00101eb0, 0x0402032e, 0x0201f800, 0x00104858, - 0x04020005, 0x42027800, 0x00000001, 0x0201f800, - 0x001043bd, 0x0201f800, 0x0010484b, 0x04020031, - 0x59cc0206, 0x82003500, 0x00000003, 0x04020034, - 0x82003480, 0x00000014, 0x04001031, 0x5934300a, - 0x84183516, 0x82000580, 0x00000014, 0x04020002, - 0x84183556, 0x481a680a, 0x59cc0406, 0x82000500, - 0x00000003, 0x04020026, 0x0201f800, 0x0010a08e, - 0x0402002e, 0x0201f800, 0x00104836, 0x04020007, - 0x4c600000, 0x4178c000, 0x417a7800, 0x0201f800, - 0x00101e48, 0x5c00c000, 0x836c0580, 0x00000003, - 0x04020009, 0x42003000, 0x00000006, 0x0201f800, - 0x0010a75e, 0x42000000, 0x0010b664, 0x0201f800, - 0x0010a86e, 0x0201f800, 0x001044e1, 0x4a026403, - 0x0000000a, 0x42003000, 0x00000020, 0x0401f78f, - 0x4a026403, 0x0000000b, 0x4a02641a, 0x00000009, - 0x4a02621a, 0x00001e00, 0x0401f12a, 0x42000000, - 0x0010b65f, 0x0201f800, 0x0010a86e, 0x4a026403, - 0x0000000b, 0x4a02641a, 0x00000007, 0x4a02621a, - 0x00000000, 0x0401f11f, 0x4a026403, 0x0000000b, - 0x4a02641a, 0x00000003, 0x4a02621a, 0x00000000, - 0x0401f118, 0x4933c857, 0x0201f800, 0x0010473b, - 0x040202d7, 0x0201f800, 0x0010a3b0, 0x040202d4, - 0x0201f800, 0x00101eb0, 0x040202d1, 0x59cc0206, - 0x82003500, 0x00000003, 0x04020020, 0x82003480, - 0x00000014, 0x0400101d, 0x59cc0406, 0x82000500, - 0x00000003, 0x04020019, 0x59340400, 0x82000580, - 0x00000707, 0x0400001c, 0x417a7800, 0x4c600000, - 0x4178c000, 0x0201f800, 0x00101e48, 0x5c00c000, - 0x42003000, 0x0000000a, 0x0201f800, 0x0010a75e, - 0x42000000, 0x0010b661, 0x0201f800, 0x0010a86e, - 0x4a026403, 0x0000000c, 0x41782800, 0x42003000, - 0x00000021, 0x0401f749, 0x4a026403, 0x0000000d, - 0x4a02641a, 0x00000007, 0x4a02621a, 0x00000000, - 0x0401f0e4, 0x4a026403, 0x0000000d, 0x4a02641a, - 0x00000009, 0x4a02621a, 0x00001e00, 0x0401f0dd, - 0x4933c857, 0x0201f800, 0x0010473b, 0x0402029c, - 0x0201f800, 0x0010a3b0, 0x04020299, 0x0201f800, - 0x00101eb0, 0x04020296, 0x0401fad6, 0x0402001a, - 0x493a6403, 0x4c5c0000, 0x0401fadc, 0x0402000e, - 0x4a026403, 0x0000002e, 0x4014b800, 0x0201f800, - 0x0010393e, 0x0400000e, 0x4a026203, 0x00000007, - 0x405c2800, 0x42003000, 0x00000024, 0x5c00b800, - 0x0401f0af, 0x4a026403, 0x0000000d, 0x4a02641a, - 0x00000007, 0x4a02621a, 0x00000000, 0x5c00b800, - 0x0401f0b8, 0x4a026403, 0x0000000d, 0x4a02641a, - 0x00000009, 0x4a02621a, 0x00001e00, 0x0401f0b1, - 0x4933c857, 0x0201f800, 0x0010473b, 0x040206f1, - 0x59a80026, 0x82000500, 0x00000009, 0x82000580, - 0x00000008, 0x040006eb, 0x0201f800, 0x0010484b, - 0x0402002d, 0x0201f800, 0x0010a096, 0x04020007, - 0x4a026403, 0x0000000e, 0x41782800, 0x42003000, - 0x00000052, 0x0401f6f9, 0x4933c857, 0x42003000, - 0x00000003, 0x0201f800, 0x0010a766, 0x4d3c0000, - 0x417a7800, 0x0201f800, 0x00101de2, 0x5c027800, - 0x42000000, 0x0010b663, 0x0201f800, 0x0010a86e, - 0x59340200, 0x84000558, 0x48026a00, 0x42000800, - 0x0000000b, 0x0201f800, 0x001043c7, 0x0201f800, - 0x0010393e, 0x0400007c, 0x42003000, 0x00000007, - 0x0401f061, 0x4933c857, 0x4a026403, 0x0000000f, - 0x4a02641a, 0x00000003, 0x4a02621a, 0x00001e00, - 0x0401f078, 0x59340400, 0x82000580, 0x00000703, - 0x040007f5, 0x0401f040, 0x4933c857, 0x0201f800, - 0x0010473b, 0x04020232, 0x59a80026, 0x82000500, - 0x00000009, 0x82000580, 0x00000008, 0x0400022c, - 0x0201f800, 0x00104842, 0x0402002f, 0x0201f800, - 0x0010a0b1, 0x02000800, 0x0010a041, 0x04020007, - 0x4a026403, 0x00000010, 0x41782800, 0x42003000, - 0x00000050, 0x0401f6b9, 0x4d3c0000, 0x417a7800, - 0x0201f800, 0x00101de2, 0x5c027800, 0x42003000, - 0x00000003, 0x0201f800, 0x0010a766, 0x42000000, - 0x0010b663, 0x0201f800, 0x0010a86e, 0x59340200, - 0x84000558, 0x48026a00, 0x0401f7c5, 0x4a026403, - 0x00000011, 0x4a02641a, 0x00000003, 0x4a02621a, - 0x00001e00, 0x0401f043, 0x4933c857, 0x0201f800, - 0x00101eb0, 0x02000800, 0x0010a3b0, 0x04020200, - 0x0401fa40, 0x04020008, 0x4a026403, 0x00000012, - 0x0401f038, 0x59340400, 0x82000580, 0x00000703, - 0x040007eb, 0x4d3c0000, 0x417a7800, 0x42028000, - 0x00000029, 0x0201f800, 0x00101de2, 0x5c027800, - 0x42003000, 0x00000017, 0x0201f800, 0x0010a766, - 0x42000000, 0x0010b663, 0x0201f800, 0x0010a86e, - 0x0201f800, 0x0010393e, 0x0400001b, 0x42003000, - 0x00000006, 0x42028000, 0x00000029, 0x4933c857, - 0x4a026403, 0x00000001, 0x4a026203, 0x00000007, - 0x4c180000, 0x0201f800, 0x0010a79b, 0x5c003000, - 0x41782800, 0x0201f000, 0x0010a250, 0x42028000, - 0x00000046, 0x4c140000, 0x4c180000, 0x0201f800, - 0x0010a79b, 0x5c003000, 0x5c002800, 0x0201f000, - 0x0010a250, 0x4933c857, 0x4a026403, 0x00000001, - 0x42000800, 0x0000000b, 0x0201f800, 0x001043c7, - 0x4a026203, 0x00000001, 0x0201f000, 0x00106470, - 0x4933c857, 0x42000800, 0x00000009, 0x0201f800, - 0x001043c7, 0x4a026403, 0x00000005, 0x0401f7f5, - 0x0201f800, 0x0010a3b0, 0x040201b5, 0x0201f800, - 0x00101eb0, 0x040201b2, 0x0401f9f2, 0x040207ba, - 0x4a026403, 0x00000020, 0x4a026203, 0x00000001, - 0x0201f000, 0x00106470, 0x0201f800, 0x00101eb0, - 0x040201a7, 0x4a026403, 0x00000023, 0x4a026203, - 0x00000001, 0x0201f000, 0x00106470, 0x0201f800, - 0x0010a3b0, 0x02000800, 0x00101eb0, 0x0402019c, - 0x0401f9dc, 0x040207a4, 0x40300800, 0x59a81010, - 0x59cc0007, 0x82000500, 0x00ffffff, 0x80080580, - 0x04000019, 0x59cc1408, 0x0201f800, 0x00108de9, - 0x0400002d, 0x59cc0c08, 0x4d300000, 0x0201f800, - 0x00105b0f, 0x41323800, 0x5c026000, 0x04000026, - 0x591c0202, 0x82000580, 0x0000ffff, 0x04000005, - 0x59cc1208, 0x591c0202, 0x80080580, 0x0402001e, - 0x591c0406, 0x82000580, 0x00000007, 0x0402001a, - 0x0401f02c, 0x59cc1208, 0x82080580, 0x0000ffff, - 0x0400000c, 0x0201f800, 0x001091d9, 0x04000012, - 0x59cc1408, 0x591c0202, 0x80080580, 0x0402000e, - 0x591c0009, 0x81340580, 0x04000016, 0x0401f00a, - 0x59cc1408, 0x417a7800, 0x0201f800, 0x0010a217, - 0x04020010, 0x59cc1208, 0x82080580, 0x0000ffff, - 0x04000019, 0x4a026403, 0x00000026, 0x4a02621a, - 0x00001700, 0x59cc1204, 0x82081580, 0x0000ffff, - 0x04020798, 0x4a026403, 0x00000025, 0x0401f795, - 0x591c0406, 0x82000580, 0x00000007, 0x040207f2, - 0x591c0403, 0x82000580, 0x00000024, 0x04020006, - 0x4d300000, 0x411e6000, 0x0201f800, 0x000208b4, - 0x5c026000, 0x4a026403, 0x00000025, 0x0401f785, - 0x4933c857, 0x4d3c0000, 0x42027800, 0x00000001, - 0x0201f800, 0x001043bd, 0x5c027800, 0x4c580000, - 0x4200b000, 0x00000002, 0x83a81c00, 0x00000002, - 0x83cc1400, 0x0000000b, 0x0201f800, 0x001082ff, - 0x5c00b000, 0x04000004, 0x4a026403, 0x00000031, - 0x0401f770, 0x0201f800, 0x00107698, 0x0201f800, - 0x00104e0d, 0x0402000f, 0x0201f800, 0x00104e1b, - 0x04020008, 0x4a035033, 0x00000001, 0x4202d800, - 0x00000001, 0x0201f800, 0x00104d76, 0x0401f005, - 0x42000000, 0x00000001, 0x0201f800, 0x00104de5, - 0x1c01f000, 0x0201f800, 0x00101eb0, 0x0402011c, - 0x0401f95c, 0x04020724, 0x493a6403, 0x0401f9ac, - 0x04020004, 0x4a026403, 0x0000002b, 0x0401f751, - 0x4a026403, 0x0000002c, 0x0401f74e, 0x4933c857, - 0x0201f800, 0x00101eb0, 0x0402010d, 0x0201f800, - 0x00104836, 0x04020740, 0x0201f800, 0x00104728, - 0x0400003c, 0x59cc0408, 0x48026419, 0x59cc0208, - 0x48026219, 0x59cc0807, 0x59340002, 0x82000500, - 0x00ffffff, 0x80040580, 0x04000012, 0x59a80010, - 0x80040580, 0x04020021, 0x59cc1408, 0x0201f800, - 0x001091d9, 0x04000023, 0x0201f800, 0x0010a2e8, - 0x04000020, 0x0201f800, 0x0010a745, 0x0400001d, - 0x491e601e, 0x4a026403, 0x00000036, 0x0401f0e6, - 0x59cc1208, 0x82080580, 0x0000ffff, 0x04000009, - 0x0201f800, 0x001091d9, 0x04000012, 0x591c0202, - 0x59cc0c08, 0x80040580, 0x0402000e, 0x0401f7eb, - 0x59cc1408, 0x41327800, 0x0201f800, 0x0010a217, - 0x04000008, 0x0401f7e5, 0x4803c856, 0x4a02641a, - 0x00000009, 0x4a02621a, 0x00001500, 0x0401f006, - 0x4803c856, 0x4a02641a, 0x00000003, 0x4a02621a, - 0x00001700, 0x4a026403, 0x00000037, 0x0401f0c6, - 0x4803c856, 0x4a026403, 0x00000012, 0x0401f0c2, - 0x4933c857, 0x0201f800, 0x00101eb0, 0x040200c4, - 0x0201f800, 0x00104836, 0x040206f7, 0x0201f800, - 0x00104728, 0x0400003e, 0x59cc0407, 0x48026419, - 0x59cc1207, 0x480a6219, 0x82080580, 0x0000ffff, - 0x04000005, 0x0201f800, 0x001091d9, 0x0400002c, - 0x0401f006, 0x59cc1407, 0x41327800, 0x0201f800, - 0x0010a217, 0x04000026, 0x59cc0c07, 0x591c0202, - 0x80040580, 0x04020022, 0x4d300000, 0x411e6000, - 0x0201f800, 0x0010898b, 0x5c026000, 0x59cc0c09, - 0x82040d00, 0x0000ff00, 0x840409c0, 0x0201f800, - 0x0010a745, 0x04000016, 0x82040580, 0x00000001, - 0x0400000a, 0x82040580, 0x00000005, 0x04000004, - 0x82040580, 0x00000007, 0x04020007, 0x591c0008, - 0x80000540, 0x04000004, 0x59cc2808, 0x0201f000, - 0x0010a2fc, 0x4803c856, 0x4a02641a, 0x00000009, - 0x4a02621a, 0x00002a00, 0x0401f006, 0x4803c856, - 0x4a02641a, 0x00000003, 0x4a02621a, 0x00000300, - 0x4a026403, 0x0000003b, 0x0401f07b, 0x4803c856, - 0x4a02641a, 0x0000000b, 0x4a02621a, 0x00000000, - 0x0401f7f8, 0x4c080000, 0x0201f800, 0x0010473b, - 0x04000026, 0x0201f800, 0x00104711, 0x0201f800, - 0x0010a41c, 0x0402001e, 0x59a80026, 0x82000540, - 0x00000003, 0x48035026, 0x59a8001d, 0x800000d0, - 0x59a80810, 0x82040d00, 0x000000ff, 0x80041540, - 0x480b5010, 0x42000800, 0x00000003, 0x0201f800, - 0x001069af, 0x497b5028, 0x0201f800, 0x0010393e, - 0x04000003, 0x4a032804, 0x000007d0, 0x8c00050a, - 0x0402000a, 0x0201f800, 0x000208b4, 0x0201f800, - 0x00101bf0, 0x5c001000, 0x1c01f000, 0x0201f800, - 0x0010a43e, 0x0401f7fc, 0x5c001000, 0x0201f000, - 0x000208b4, 0x0201f800, 0x00101eb0, 0x0402004c, - 0x0201f800, 0x0010a443, 0x4a026403, 0x00000047, - 0x4a026203, 0x00000001, 0x0201f000, 0x00106470, - 0x0201f800, 0x00101eb0, 0x04020041, 0x0201f800, - 0x0010a443, 0x4a026403, 0x00000047, 0x4a026203, - 0x00000001, 0x0201f000, 0x00106470, 0x0201f800, - 0x00101eb0, 0x04020036, 0x0201f800, 0x0010a443, - 0x0201f000, 0x000208b4, 0x0401f834, 0x04000030, - 0x4a026403, 0x0000004e, 0x4a026203, 0x00000001, - 0x0201f000, 0x00106470, 0x4a026403, 0x0000004f, - 0x497a601c, 0x59cc0a06, 0x82040d00, 0x000000ff, - 0x800409c0, 0x0400065f, 0x82040580, 0x00000001, - 0x04020005, 0x59cc0808, 0x59a80005, 0x80040580, - 0x04000658, 0x82040580, 0x00000002, 0x0402000a, - 0x83cc1400, 0x0000000b, 0x4200b000, 0x00000002, - 0x83341c00, 0x00000006, 0x0201f800, 0x001082ff, - 0x0400064c, 0x4a02601c, 0x00000001, 0x0401f649, - 0x4a026403, 0x00000050, 0x59cc0207, 0x4802601c, - 0x0401f644, 0x4a026203, 0x00000001, 0x42000800, - 0x80000040, 0x0201f000, 0x00020855, 0x4803c857, - 0x0201f000, 0x000208b4, 0x4d2c0000, 0x4c500000, - 0x4c580000, 0x4c540000, 0x59a80016, 0x82000c80, - 0x00000841, 0x0402102d, 0x0201f800, 0x00100819, - 0x0400002a, 0x492e6008, 0x59a80016, 0x48025802, - 0x82000400, 0x00000003, 0x80000104, 0x83cca400, - 0x00000006, 0x82000c80, 0x0000000b, 0x04001015, - 0x4a025811, 0x0000000b, 0x4200b000, 0x0000000b, - 0x832c0400, 0x00000005, 0x4000a800, 0x0201f800, - 0x0010a93e, 0x412c7000, 0x800409c0, 0x04020003, - 0x49787001, 0x0401f00e, 0x0201f800, 0x00100819, - 0x0400000e, 0x492c7001, 0x40040000, 0x0401f7ea, - 0x48025811, 0x4000b000, 0x832c0400, 0x00000005, - 0x4000a800, 0x0201f800, 0x0010a93e, 0x82000540, - 0x00000001, 0x0401f006, 0x497b5016, 0x59325808, - 0x0201f800, 0x00100843, 0x80000580, 0x5c00a800, - 0x5c00b000, 0x5c00a000, 0x5c025800, 0x1c01f000, - 0x4d340000, 0x59326809, 0x59343400, 0x4933c857, - 0x4937c857, 0x481bc857, 0x0201f800, 0x00104842, - 0x5c026800, 0x1c01f000, 0x4933c857, 0x4c600000, - 0x4c5c0000, 0x4d3c0000, 0x4d440000, 0x4d340000, - 0x0401f84f, 0x04020037, 0x59cc0207, 0x82000d00, - 0x0000ff00, 0x900411c0, 0x59cc000a, 0x82000500, - 0x00ffffff, 0x80081540, 0x480a601c, 0x8c040d18, - 0x04000011, 0x42003000, 0x00000008, 0x0201f800, - 0x0010a756, 0x42000000, 0x0010b662, 0x0201f800, - 0x0010a86e, 0x4200b800, 0x00000002, 0x4200c000, - 0x00000001, 0x417a7800, 0x0201f800, 0x00101e48, - 0x0401f01f, 0x4178b800, 0x8c040d1a, 0x04000019, - 0x59cc000a, 0x0201f800, 0x001059b9, 0x02000800, - 0x00020267, 0x04020013, 0x59300009, 0x4c000000, - 0x49366009, 0x42003000, 0x00000009, 0x0201f800, - 0x0010a75e, 0x42000000, 0x0010b662, 0x0201f800, - 0x0010a86e, 0x417a7800, 0x4178c000, 0x0201f800, - 0x00101e48, 0x5c000000, 0x48026009, 0x0401f004, - 0x82000540, 0x00000001, 0x0401f003, 0x405c2800, - 0x80000580, 0x5c026800, 0x5c028800, 0x5c027800, - 0x5c00b800, 0x5c00c000, 0x1c01f000, 0x4933c857, - 0x59cc0206, 0x82000480, 0x00000010, 0x04021006, - 0x4a02621a, 0x00000000, 0x82000540, 0x00000001, - 0x0401f002, 0x80000580, 0x1c01f000, 0x4933c857, - 0x4a02621a, 0x00000000, 0x59cc0407, 0x82000500, - 0x0000ff00, 0x82000580, 0x00000800, 0x04020009, - 0x59cc0006, 0x82000500, 0x00ff0000, 0x82000d80, - 0x00140000, 0x04000003, 0x82000d80, 0x00100000, - 0x1c01f000, 0x59300403, 0x82003480, 0x00000051, - 0x02021800, 0x00100615, 0x83383580, 0x00000013, - 0x04020003, 0x4803c857, 0x0c01f016, 0x4933c857, - 0x493bc857, 0x83383580, 0x00000027, 0x04000005, - 0x83383580, 0x00000014, 0x02020800, 0x00100615, - 0x493bc857, 0x4937c857, 0x0201f800, 0x00104711, - 0x42000800, 0x00000007, 0x0201f800, 0x001043c7, - 0x0201f800, 0x001068f6, 0x0201f000, 0x00107698, - 0x00109c29, 0x00109c32, 0x00109c29, 0x00109c29, - 0x00109c29, 0x00109c32, 0x00109c3d, 0x00109cb0, - 0x00109c82, 0x00109cb0, 0x00109c9a, 0x00109cb0, - 0x00109ca1, 0x00109cb0, 0x00109ca9, 0x00109cb0, - 0x00109ca9, 0x00109cb0, 0x00109cb0, 0x00109c29, - 0x00109c29, 0x00109c29, 0x00109c29, 0x00109c29, - 0x00109c29, 0x00109c29, 0x00109c29, 0x00109c29, - 0x00109c29, 0x00109c29, 0x00109c32, 0x00109c29, - 0x00109cb0, 0x00109c29, 0x00109c29, 0x00109cb0, - 0x00109c29, 0x00109cad, 0x00109cb0, 0x00109c29, - 0x00109c29, 0x00109c29, 0x00109c29, 0x00109cb0, - 0x00109cb0, 0x00109c29, 0x00109ca6, 0x00109cb0, - 0x00109c29, 0x00109c37, 0x00109c29, 0x00109c29, - 0x00109c29, 0x00109c29, 0x00109cac, 0x00109cb0, - 0x00109c29, 0x00109c29, 0x00109cb0, 0x00109cb0, - 0x00109c29, 0x00109c29, 0x00109c29, 0x00109c29, - 0x00109c29, 0x00109c29, 0x00109c29, 0x00109c29, - 0x00109c29, 0x00109c2b, 0x00109c29, 0x00109c2b, - 0x00109c29, 0x00109c29, 0x00109c2b, 0x00109c29, - 0x00109c29, 0x00109c29, 0x00109c2b, 0x00109c2b, - 0x00109c2b, 0x0201f800, 0x00100615, 0x4d2c0000, - 0x59325808, 0x0201f800, 0x00100843, 0x5c025800, - 0x0201f000, 0x000208b4, 0x59a80037, 0x48026206, - 0x4a026203, 0x00000002, 0x1c01f000, 0x4d3c0000, - 0x417a7800, 0x0201f800, 0x001043bd, 0x5c027800, - 0x0401f074, 0x42000800, 0x00000007, 0x0201f800, - 0x001043c7, 0x59a80026, 0x8c000508, 0x04000012, - 0x59326809, 0x4c580000, 0x4200b000, 0x00000002, - 0x83a81c00, 0x00000002, 0x83341400, 0x00000006, - 0x0201f800, 0x001082ff, 0x80000540, 0x5c00b000, - 0x04020060, 0x59340200, 0x8400051a, 0x48026a00, - 0x0401f01b, 0x599c0017, 0x8c00050a, 0x04020059, - 0x4d3c0000, 0x417a7800, 0x0201f800, 0x001043bd, - 0x5c027800, 0x42000800, 0x00000007, 0x0201f800, - 0x001043c7, 0x59340212, 0x82000500, 0x0000ff00, - 0x0400004c, 0x599c0019, 0x8c00050e, 0x04020049, - 0x416c0000, 0x82000580, 0x00000002, 0x04020004, - 0x59a8001b, 0x80000000, 0x4803501b, 0x42000800, - 0x00000003, 0x0201f800, 0x001043c7, 0x4a026406, - 0x00000001, 0x4a026203, 0x00000001, 0x4a026403, - 0x00000002, 0x0201f800, 0x00106470, 0x4ce80000, - 0x4201d000, 0x00000001, 0x0201f800, 0x00105ce7, - 0x5c01d000, 0x1c01f000, 0x0201f800, 0x00104842, - 0x0400002c, 0x0201f800, 0x00106196, 0x42000800, - 0x00000004, 0x0201f800, 0x001043c7, 0x0201f800, - 0x0010a791, 0x04020023, 0x42000800, 0x00000005, - 0x0201f800, 0x001043c7, 0x4a026406, 0x00000001, - 0x4a026203, 0x00000001, 0x4a026403, 0x00000003, - 0x0201f000, 0x00106470, 0x0201f800, 0x0010484b, - 0x04020014, 0x42000800, 0x00000006, 0x0401f813, - 0x0401f010, 0x42000800, 0x00000004, 0x0201f800, - 0x001043c7, 0x0401f79c, 0x42000800, 0x00000004, - 0x0401f006, 0x0201f800, 0x00104711, 0x0401f005, - 0x0401f004, 0x0401f003, 0x0201f800, 0x001043c7, - 0x0201f000, 0x000208b4, 0x4933c857, 0x4807c857, - 0x0201f800, 0x001043c7, 0x4d3c0000, 0x417a7800, - 0x0201f800, 0x001043bd, 0x5c027800, 0x0201f000, - 0x00104711, 0x59340400, 0x4803c857, 0x80000110, - 0x82003480, 0x0000000c, 0x02021800, 0x00100615, - 0x83383580, 0x00000015, 0x04020002, 0x0c01f006, - 0x83383580, 0x00000016, 0x02020800, 0x00100615, - 0x0c01f00d, 0x00107e42, 0x00107e42, 0x00107e42, - 0x00107e42, 0x00107e42, 0x00107e42, 0x00109d11, - 0x00109ce5, 0x00107e42, 0x00107e42, 0x00107e42, - 0x00107e42, 0x00107e42, 0x00107e42, 0x00107e42, - 0x00107e42, 0x00107e42, 0x00107e42, 0x00109d11, - 0x00109d18, 0x00107e42, 0x00107e42, 0x00107e42, - 0x00107e42, 0x4933c857, 0x599c0017, 0x8c00050a, - 0x0402001b, 0x813669c0, 0x04000019, 0x59340212, - 0x82000500, 0x0000ff00, 0x04000015, 0x599c0019, - 0x8c00050e, 0x04020012, 0x4d3c0000, 0x417a7800, - 0x0201f800, 0x001043bd, 0x5c027800, 0x42000800, - 0x00000003, 0x0201f800, 0x001043c7, 0x4a026406, - 0x00000001, 0x4a026203, 0x00000001, 0x4a026403, - 0x00000002, 0x0201f000, 0x00106470, 0x59cc0001, - 0x59340802, 0x80040580, 0x82000500, 0x00ffffff, - 0x02020000, 0x000208b4, 0x59345002, 0x0201f800, - 0x001040e4, 0x482a6802, 0x0201f000, 0x000208b4, - 0x1c01f000, 0x4933c857, 0x59303403, 0x82183580, - 0x0000001e, 0x02000000, 0x000208b4, 0x1c01f000, - 0x4933c857, 0x0201f800, 0x00108180, 0x02020000, - 0x000208b4, 0x4a026203, 0x00000001, 0x4a026403, - 0x00000001, 0x0201f000, 0x00106470, 0x493bc857, - 0x83380580, 0x00000051, 0x0402000b, 0x0201f800, - 0x00106cb4, 0x02020000, 0x001076fb, 0x59300203, - 0x82000580, 0x00000002, 0x0400006e, 0x0201f800, - 0x00100615, 0x83380580, 0x00000027, 0x04000014, - 0x83380580, 0x00000048, 0x04000006, 0x83380580, - 0x00000014, 0x0400000e, 0x02020800, 0x00100615, - 0x0201f800, 0x00106cb4, 0x02020000, 0x001076fb, - 0x59300203, 0x82000580, 0x00000004, 0x02000000, - 0x000209a5, 0x0201f800, 0x00100615, 0x4933c857, - 0x59300403, 0x82000c80, 0x00000044, 0x02021800, - 0x00100615, 0x82000480, 0x00000040, 0x02001800, - 0x00100615, 0x40027000, 0x4803c857, 0x0c01f001, - 0x00109d58, 0x00109d5a, 0x00109d5a, 0x00109d75, - 0x0201f800, 0x00100615, 0x0201f800, 0x001068f6, - 0x59325808, 0x812e59c0, 0x04000016, 0x832c0500, - 0x00ff0000, 0x04000013, 0x4a026203, 0x00000002, - 0x59326809, 0x59340200, 0x8c00050e, 0x0402000d, - 0x42028000, 0x00000004, 0x0201f800, 0x0010a201, - 0x497a6008, 0x59300206, 0x80000540, 0x04020003, - 0x59a80038, 0x48026206, 0x4a026203, 0x00000007, - 0x1c01f000, 0x0201f800, 0x001068f6, 0x0201f800, - 0x00108df4, 0x02000000, 0x00107698, 0x59325808, - 0x0201f800, 0x0010083a, 0x0201f000, 0x00107698, - 0x0201f800, 0x00100615, 0x59325808, 0x592c040a, - 0x8c000502, 0x04000007, 0x4a026203, 0x00000007, - 0x42027000, 0x00000043, 0x0201f000, 0x000208d8, - 0x4a026203, 0x00000004, 0x1c01f000, 0x0201f800, - 0x0010a3b6, 0x02000000, 0x000209a3, 0x1c01f000, - 0x4a026203, 0x00000001, 0x4a026403, 0x00000041, - 0x42027800, 0x80002042, 0x0201f000, 0x00020855, - 0x83380580, 0x00000051, 0x04000006, 0x83380580, - 0x00000041, 0x02020800, 0x00100615, 0x1c01f000, - 0x0201f800, 0x00020831, 0x0201f800, 0x0010a3fa, - 0x0201f000, 0x000208b4, 0x83380480, 0x00000052, - 0x02021800, 0x00100615, 0x83380480, 0x00000049, - 0x02001800, 0x00100615, 0x0c01f001, 0x00109dbe, - 0x00109ddf, 0x00109dbc, 0x00109dbc, 0x00109dbc, - 0x00109dbc, 0x00109ddf, 0x00109dbc, 0x00109e01, - 0x0201f800, 0x00100615, 0x59325808, 0x592c040a, - 0x8c00051e, 0x0400000d, 0x82000d00, 0x000000c0, - 0x82040d80, 0x00000080, 0x0400000d, 0x59300804, - 0x8c040d18, 0x0402000a, 0x42027000, 0x00000041, - 0x0201f000, 0x000209c4, 0x4a026203, 0x00000007, - 0x497a6206, 0x0201f000, 0x00020831, 0x59325808, - 0x592c0c0a, 0x8c040d1a, 0x04020005, 0x0201f800, - 0x00020831, 0x0201f000, 0x000208b4, 0x0201f800, - 0x0010a3b6, 0x040007fa, 0x1c01f000, 0x0201f800, - 0x001068c1, 0x59325808, 0x59326809, 0x59340200, - 0x8c00050e, 0x0400000e, 0x592c040a, 0x82000500, - 0x000000c0, 0x82000580, 0x00000080, 0x04000005, - 0x592c000f, 0x59301815, 0x800c1c80, 0x480e6015, - 0x4a026203, 0x00000002, 0x0401f00e, 0x42028000, - 0x00000004, 0x0201f800, 0x0010a201, 0x59300206, - 0x80000540, 0x04020004, 0x59a80038, 0x800000c2, - 0x48026206, 0x497a6008, 0x4a026203, 0x00000007, - 0x1c01f000, 0x4933c857, 0x0201f800, 0x00106cb4, - 0x02020800, 0x00100615, 0x59300203, 0x82000580, - 0x00000002, 0x04000793, 0x0201f800, 0x00100615, - 0x4a026203, 0x00000007, 0x497a6206, 0x0201f000, - 0x00020831, 0x4a026203, 0x00000007, 0x497a6206, - 0x0201f000, 0x0002082c, 0x59300414, 0x8c00051c, - 0x02020000, 0x000209b5, 0x59325808, 0x592c200f, - 0x40080000, 0x80102480, 0x59300015, 0x80102400, - 0x48126015, 0x0201f000, 0x000209b5, 0x8c040d0e, - 0x0402000a, 0x4a026203, 0x00000006, 0x0401f823, - 0x5930001f, 0x80000540, 0x02020800, 0x00100dc4, - 0x0201f000, 0x0002082c, 0x4a026203, 0x00000002, - 0x1c01f000, 0x42000800, 0x00000001, 0x0201f800, - 0x00100dc4, 0x82040580, 0x00000001, 0x02000000, - 0x000209bc, 0x0401f7d8, 0x59300414, 0x8c00051c, - 0x04000006, 0x0201f800, 0x00100bad, 0x02000000, - 0x000209ae, 0x1c01f000, 0x59300011, 0x80000540, - 0x04020005, 0x0201f800, 0x00100bad, 0x02000000, - 0x000209ae, 0x1c01f000, 0x492fc857, 0x480bc857, - 0x8c08153e, 0x04000006, 0x80081080, 0x80081000, - 0x42000800, 0x00000009, 0x0401f003, 0x42000800, - 0x00000015, 0x480a580b, 0x1c01f000, 0x83380580, - 0x00000013, 0x04000005, 0x83380580, 0x00000014, - 0x02020800, 0x00100615, 0x59300414, 0x8c000516, - 0x02000800, 0x00100615, 0x1c01f000, 0x0201f800, - 0x00100615, 0x59300008, 0x80000540, 0x02020800, - 0x00100615, 0x1c01f000, 0x59300414, 0x8c000516, - 0x02000800, 0x00100615, 0x1c01f000, 0x4a026203, - 0x00000004, 0x493a6403, 0x42000800, 0x80002001, - 0x0201f000, 0x00020855, 0x4a026203, 0x00000003, - 0x493a6403, 0x0201f800, 0x000200ca, 0x59325808, - 0x592c040a, 0x8c00051e, 0x04000012, 0x82000500, - 0x000000c0, 0x82000580, 0x00000080, 0x04000011, - 0x59300414, 0x8c000512, 0x0402000a, 0x8c000510, - 0x04020008, 0x592c040c, 0x80000540, 0x04020005, - 0x82080d40, 0x80003065, 0x0201f000, 0x00106466, - 0x82080d40, 0x80002065, 0x0201f000, 0x00106466, - 0x82080d40, 0x80002042, 0x0201f000, 0x00106466, - 0x4933c857, 0x493bc857, 0x83380480, 0x00000044, - 0x02021800, 0x00100615, 0x83380480, 0x00000041, - 0x02001800, 0x00100615, 0x0c01f001, 0x00109ea6, - 0x00109eb6, 0x00109ecb, 0x59325808, 0x592c040a, - 0x8c00051e, 0x0400001d, 0x82001d00, 0x000000c0, - 0x820c1d80, 0x000000c0, 0x04000018, 0x4a026203, - 0x00000001, 0x493a6403, 0x42000800, 0x80002042, - 0x0201f000, 0x00020855, 0x59325808, 0x592c040a, - 0x8c00051e, 0x0400000d, 0x82001d00, 0x000000c0, - 0x820c1d80, 0x000000c0, 0x04000008, 0x4a026203, - 0x00000001, 0x493a6403, 0x42000800, 0x80002001, - 0x0201f000, 0x00020855, 0x497a6008, 0x497a6206, - 0x42028000, 0x00000004, 0x0401f337, 0x59325808, - 0x592c040a, 0x8c00051e, 0x040007f8, 0x82001d00, - 0x000000c0, 0x820c1d80, 0x000000c0, 0x040007f3, - 0x4a026203, 0x00000003, 0x493a6403, 0x0201f800, - 0x000200ca, 0x82080d40, 0x80002065, 0x0201f000, - 0x00106466, 0x4933c857, 0x493bc857, 0x83380580, - 0x00000085, 0x04000006, 0x83380580, 0x00000088, - 0x0400000a, 0x0201f800, 0x00100615, 0x4a026203, - 0x00000009, 0x493a6403, 0x42000800, 0x8000004b, - 0x0201f000, 0x00020855, 0x4d1c0000, 0x813669c0, - 0x04000004, 0x0201f800, 0x0010a3b0, 0x04020044, - 0x59cc1404, 0x0401f846, 0x04000018, 0x591c0406, - 0x82000500, 0x0000001f, 0x82002580, 0x00000006, - 0x04000007, 0x82002580, 0x00000004, 0x0400002e, - 0x82002580, 0x00000011, 0x0402000c, 0x497a3a05, - 0x42002000, 0x00000054, 0x0201f800, 0x001077d1, - 0x4a026203, 0x00000007, 0x493a6403, 0x0201f800, - 0x0010a79b, 0x0401f02c, 0x0201f800, 0x0010393e, - 0x04000004, 0x42023800, 0xffffffff, 0x0401f7f1, - 0x813669c0, 0x04020009, 0x59cc0001, 0x0201f800, - 0x001059b9, 0x0402001e, 0x0201f800, 0x001043fc, - 0x0402001b, 0x49366009, 0x4a026403, 0x00000087, - 0x59cc1204, 0x82081580, 0x0000ffff, 0x04020003, - 0x4a026403, 0x00000086, 0x4a026203, 0x00000001, - 0x42000800, 0x80000040, 0x0201f800, 0x00020855, - 0x0401f00d, 0x591c0203, 0x82000580, 0x00000007, - 0x040207de, 0x4d300000, 0x411e6000, 0x0201f800, - 0x00107698, 0x5c026000, 0x0401f7d8, 0x0201f800, - 0x00107698, 0x5c023800, 0x1c01f000, 0x4933c857, - 0x480bc857, 0x42002800, 0x0010cfc0, 0x41300000, - 0x80140580, 0x04000017, 0x58140203, 0x82000580, - 0x00000000, 0x04000013, 0x58140202, 0x80080580, - 0x04020010, 0x58141c06, 0x820c0580, 0x00000005, - 0x0400000c, 0x820c0580, 0x00000009, 0x0400001d, - 0x59302009, 0x58140009, 0x800001c0, 0x0400000b, - 0x801021c0, 0x04000003, 0x80100580, 0x04000010, - 0x82142c00, 0x00000024, 0x41540000, 0x80140480, - 0x0402100e, 0x0401f7e2, 0x5814001e, 0x801021c0, - 0x04000005, 0x58102002, 0x82102500, 0x00ffffff, - 0x0401f7f2, 0x5810201e, 0x0401f7f0, 0x40163800, - 0x81300540, 0x0401f002, 0x80000580, 0x1c01f000, - 0x58141807, 0x8c0c1d10, 0x040207ea, 0x0401f7e1, - 0x83380580, 0x00000013, 0x0402000e, 0x59300403, - 0x4803c857, 0x82000c80, 0x00000085, 0x02001800, - 0x00100615, 0x82000c80, 0x00000093, 0x02021800, - 0x00100615, 0x82000480, 0x00000085, 0x0c01f019, - 0x83380580, 0x00000027, 0x04000005, 0x83380580, - 0x00000014, 0x02020000, 0x001076fb, 0x493bc857, - 0x0201f800, 0x001068f6, 0x59325808, 0x812e59c0, - 0x02000000, 0x00107698, 0x4a025a06, 0x00000031, - 0x4a025811, 0x00000004, 0x4a025812, 0x000000ff, - 0x0201f800, 0x00020381, 0x0201f000, 0x00107698, - 0x00109fa6, 0x00109fad, 0x00109fad, 0x00109fa6, - 0x00109fa6, 0x00109fa6, 0x00109fa6, 0x00109fa6, - 0x00109fa6, 0x00109fa6, 0x00109fa6, 0x00109fa6, - 0x00109fa6, 0x00109fa8, 0x0201f800, 0x00100615, - 0x59325808, 0x4a025a06, 0x00000000, 0x0201f800, - 0x00020381, 0x0201f000, 0x000208b4, 0x4933c857, - 0x42000000, 0x0010b672, 0x0201f800, 0x0010a86e, - 0x0201f800, 0x0010a3fa, 0x497a6205, 0x42028000, - 0x0000000b, 0x0401f807, 0x4a026406, 0x00000006, - 0x4a026203, 0x00000007, 0x497a6206, 0x1c01f000, - 0x4933c857, 0x4943c857, 0x59300406, 0x82000580, - 0x00000007, 0x04020002, 0x1c01f000, 0x0201f800, - 0x0010698c, 0x4df00000, 0x0201f800, 0x00108a99, - 0x82000c80, 0x0000000e, 0x02021800, 0x00100615, - 0x0c01f001, 0x00109ff4, 0x00109ff8, 0x00109fdf, - 0x0010a006, 0x0010a019, 0x00109fdf, 0x00109fdf, - 0x00109fdf, 0x00109fdf, 0x00109fdf, 0x00109fdf, - 0x00109fdf, 0x00109fdf, 0x00109fdf, 0x4d400000, - 0x5930001f, 0x80000540, 0x04000005, 0x41400800, - 0x0201f800, 0x00100dc4, 0x40068000, 0x4d2c0000, - 0x59325808, 0x0201f800, 0x00108df4, 0x04020a16, - 0x4c5c0000, 0x5930b809, 0x0201f800, 0x00107698, - 0x485e6009, 0x5c00b800, 0x5c025800, 0x5c028000, - 0x5c03e000, 0x02000000, 0x00106982, 0x1c01f000, - 0x598c000d, 0x81300580, 0x04020004, 0x0201f800, - 0x00106be2, 0x04020016, 0x0201f800, 0x00106619, - 0x040007df, 0x0201f800, 0x001068a3, 0x04000010, - 0x0201f800, 0x00100615, 0x0201f800, 0x00108a8a, - 0x04020004, 0x0201f800, 0x00106bb2, 0x04020008, - 0x0201f800, 0x001064f6, 0x040007d1, 0x0201f800, - 0x001068a3, 0x02020800, 0x00100615, 0x59300203, - 0x82000c80, 0x0000000e, 0x02021800, 0x00100615, - 0x0c01f7b9, 0x0201f800, 0x00100ee4, 0x0401f7c4, - 0x4933c857, 0x4d440000, 0x4d340000, 0x59cc0007, - 0x0201f800, 0x001059b9, 0x02000800, 0x00020267, - 0x0402001a, 0x59300009, 0x4c000000, 0x49366009, - 0x42003000, 0x0000000b, 0x0201f800, 0x0010a766, - 0x42000000, 0x0010b660, 0x0201f800, 0x0010a86e, - 0x4d3c0000, 0x4d400000, 0x42028000, 0x00000029, - 0x417a7800, 0x0201f800, 0x00101de2, 0x5c028000, - 0x5c027800, 0x5c000000, 0x48026009, 0x59cc0007, - 0x48026802, 0x80000580, 0x5c026800, 0x5c028800, - 0x1c01f000, 0x4933c857, 0x4c040000, 0x59a80016, - 0x82000580, 0x00000074, 0x04020040, 0x59cc0a08, - 0x82040480, 0x00000100, 0x04001033, 0x59cc0c08, - 0x82040500, 0x00008000, 0x04000035, 0x59a80032, - 0x80000540, 0x04020009, 0x59301009, 0x58080212, - 0x82000500, 0x0000ff00, 0x04000004, 0x82040500, - 0x00000800, 0x0400002a, 0x59cc0c09, 0x80040840, - 0x04001024, 0x59a80826, 0x8c040d06, 0x04000004, - 0x59cc0c0f, 0x8c040d1e, 0x04020012, 0x59cc0a17, - 0x800409c0, 0x04020012, 0x59cc0a18, 0x82040480, - 0x00000100, 0x04001014, 0x59cc0c18, 0x800409c0, - 0x0402000e, 0x59cc0c19, 0x80040840, 0x04001011, - 0x59cc0c1a, 0x80040840, 0x04001011, 0x0401f018, - 0x4a02621a, 0x00000100, 0x0401f012, 0x4a02621a, - 0x00000300, 0x0401f00f, 0x4a02621a, 0x00000500, - 0x0401f00c, 0x4a02621a, 0x00000700, 0x0401f009, - 0x4a02621a, 0x00000900, 0x0401f006, 0x4a02621a, - 0x00000f00, 0x0401f003, 0x4a02621a, 0x00002d00, - 0x82000540, 0x00000001, 0x0401f002, 0x80000580, - 0x5c000800, 0x1c01f000, 0x59cc0407, 0x4803c857, - 0x82000580, 0x00000800, 0x04000003, 0x4a02621a, - 0x00000000, 0x1c01f000, 0x4933c857, 0x4c580000, - 0x59cc000c, 0x59340802, 0x82040d00, 0x00ffffff, - 0x80040580, 0x04020012, 0x83cc1400, 0x00000008, - 0x4200b000, 0x00000002, 0x83341c00, 0x00000006, - 0x0201f800, 0x001082ff, 0x04020009, 0x83cc1400, - 0x0000000a, 0x4200b000, 0x00000002, 0x83341c00, - 0x00000008, 0x0201f800, 0x001082ff, 0x5c00b000, - 0x1c01f000, 0x4933c857, 0x4c580000, 0x83cc1400, - 0x0000000b, 0x4200b000, 0x00000002, 0x83341c00, - 0x00000006, 0x0201f800, 0x001082ff, 0x0402000c, - 0x83cc1400, 0x0000000d, 0x4200b000, 0x00000002, - 0x83341c00, 0x00000008, 0x0201f800, 0x001082ff, - 0x04000014, 0x4933c856, 0x4933c856, 0x4933c857, - 0x59340009, 0x4803c857, 0x5934000e, 0x4803c857, - 0x59340008, 0x4803c857, 0x5934000d, 0x4803c857, - 0x59340007, 0x4803c857, 0x5934000c, 0x4803c857, - 0x59340006, 0x4803c857, 0x5934000b, 0x4803c857, - 0x5c00b000, 0x1c01f000, 0x4933c857, 0x4947c857, - 0x4943c857, 0x4c600000, 0x0201f800, 0x0010698c, - 0x4df00000, 0x4d2c0000, 0x4d300000, 0x4d340000, - 0x0401f8d8, 0x4130c000, 0x42026000, 0x0010cfc0, - 0x59a8000e, 0x8060c1c0, 0x04000005, 0x82601580, - 0x0010bbe8, 0x04000002, 0x80000040, 0x81640480, - 0x040210c4, 0x40600000, 0x81300580, 0x040000bc, - 0x0401f9bc, 0x040200ba, 0x59326809, 0x59300406, - 0x82000c80, 0x00000012, 0x02021800, 0x00100615, - 0x0c01f001, 0x0010a1af, 0x0010a118, 0x0010a133, - 0x0010a13e, 0x0010a111, 0x0010a12c, 0x0010a169, - 0x0010a1af, 0x0010a10f, 0x0010a17c, 0x0010a190, - 0x0010a10f, 0x0010a10f, 0x0010a10f, 0x0010a10f, - 0x0010a1af, 0x0010a1a6, 0x0010a19e, 0x0201f800, - 0x00100615, 0x8d3e7d18, 0x04000003, 0x8d3e7d16, - 0x04000004, 0x59300420, 0x8c000500, 0x04020098, - 0x59300403, 0x82000580, 0x00000043, 0x04000094, - 0x0201f800, 0x00108ef1, 0x04000007, 0x0201f800, - 0x00108f05, 0x0402008c, 0x0201f800, 0x00107da6, - 0x0401f089, 0x0201f800, 0x00101e1b, 0x0201f800, - 0x00108f05, 0x02000800, 0x00107da6, 0x0401f082, - 0x8d3e7d18, 0x04000003, 0x8d3e7d16, 0x04000004, - 0x59300420, 0x8c000500, 0x0402007d, 0x59325808, - 0x0201f800, 0x00108df4, 0x04000077, 0x49425a06, - 0x497a5c09, 0x0201f800, 0x00020381, 0x0201f800, - 0x00108ee7, 0x0401f070, 0x8d3e7d00, 0x04000007, - 0x59300017, 0x81480580, 0x0402006d, 0x59300018, - 0x814c0580, 0x0402006a, 0x59300203, 0x82000580, - 0x00000004, 0x02000800, 0x00100ee4, 0x59325808, - 0x0201f800, 0x00108df4, 0x0400005f, 0x4a025a04, - 0x00000103, 0x59300004, 0x8400055c, 0x48026004, - 0x592c0408, 0x8c000512, 0x04000007, 0x4d2c0000, - 0x592c0009, 0x40025800, 0x0201f800, 0x00100843, - 0x5c025800, 0x49425a06, 0x497a5c09, 0x0401fb4f, - 0x0201f800, 0x00109365, 0x0201f800, 0x00108f7d, - 0x0201f800, 0x00020381, 0x0201f800, 0x00108ee7, - 0x0401f045, 0x8d3e7d18, 0x04000045, 0x59300203, - 0x82000580, 0x00000004, 0x02000800, 0x00100ee4, - 0x59325808, 0x0201f800, 0x00108df4, 0x0400003a, - 0x49425a06, 0x497a5c09, 0x0401fb38, 0x0201f800, - 0x00109365, 0x0201f800, 0x00020381, 0x0401f032, - 0x0201f800, 0x0010600e, 0x04000031, 0x59300203, - 0x82000580, 0x00000004, 0x0400002d, 0x59300203, - 0x82000580, 0x00000003, 0x04020029, 0x0201f800, - 0x001068c1, 0x59325808, 0x0201f800, 0x00108df4, - 0x04000021, 0x0201f800, 0x00020381, 0x0401f01e, - 0x59300203, 0x82000580, 0x00000004, 0x02000800, - 0x00100ee4, 0x59325808, 0x0201f800, 0x00108df4, - 0x04000015, 0x49425a06, 0x497a5c09, 0x0201f800, - 0x00020381, 0x0401f010, 0x833c0500, 0x00001800, - 0x0400000f, 0x8d3e7d16, 0x0402000d, 0x59325817, - 0x0201f800, 0x00100843, 0x59325808, 0x0201f800, - 0x00108df4, 0x04000004, 0x49425a06, 0x0201f800, - 0x00020381, 0x0201f800, 0x00107698, 0x83326400, - 0x00000024, 0x41580000, 0x81300480, 0x04001735, - 0x5c026800, 0x5c026000, 0x5c025800, 0x5c03e000, - 0x02000800, 0x00106982, 0x5c00c000, 0x1c01f000, - 0x4933c857, 0x813261c0, 0x0400002d, 0x83300d80, - 0x0010bbe8, 0x0400002a, 0x8d3e7d06, 0x04020028, - 0x59300c06, 0x82040580, 0x00000001, 0x0400000a, - 0x82040580, 0x00000002, 0x04020021, 0x5930021d, - 0x82000580, 0x00000001, 0x0402001d, 0x59300c16, - 0x0401f002, 0x59300c03, 0x82040580, 0x00000039, - 0x04000004, 0x82040580, 0x00000035, 0x04020014, - 0x4d300000, 0x4d1c0000, 0x5932601e, 0x4933c857, - 0x0201f800, 0x001091e3, 0x02000800, 0x00100615, - 0x591c001c, 0x497a381c, 0x591c0c14, 0x84040d02, - 0x48063c14, 0x5c023800, 0x5c026000, 0x81300580, - 0x02020800, 0x00100615, 0x497a601e, 0x1c01f000, - 0x5c000000, 0x4c000000, 0x4803c857, 0x4d3c0000, - 0x42027800, 0x00000001, 0x0201f800, 0x001043bd, - 0x5c027800, 0x4c580000, 0x4200b000, 0x00000002, - 0x83a81c00, 0x00000002, 0x83cc1400, 0x0000000b, - 0x0201f800, 0x001082ff, 0x5c00b000, 0x80000540, - 0x1c01f000, 0x492fc857, 0x4943c857, 0x59a8000c, - 0x812c0480, 0x04001011, 0x59a8000d, 0x812c0480, - 0x0402100e, 0x592c0000, 0x80005d40, 0x04000008, - 0x497a5800, 0x49425a06, 0x4c2c0000, 0x0201f800, - 0x00020381, 0x5c025800, 0x0401f7f7, 0x49425a06, - 0x0201f000, 0x00020381, 0x1c01f000, 0x493fc857, - 0x4933c857, 0x480bc857, 0x0201f800, 0x0010393e, - 0x0400002e, 0x41502800, 0x813e79c0, 0x04020006, - 0x59a80066, 0x80000000, 0x59a8086a, 0x80040580, - 0x04000026, 0x41300000, 0x80140580, 0x0400001a, - 0x58140203, 0x82000580, 0x00000000, 0x04000016, - 0x58140202, 0x80080580, 0x04020013, 0x58141c06, - 0x820c0580, 0x00000005, 0x0400000f, 0x820c0580, - 0x00000009, 0x04000017, 0x59300009, 0x58142009, - 0x801021c0, 0x04020006, 0x5814201e, 0x59301809, - 0x580c0002, 0x82000500, 0x00ffffff, 0x80100580, - 0x04000007, 0x82142c00, 0x00000024, 0x41540000, - 0x80140480, 0x04021005, 0x0401f7df, 0x40163800, - 0x81300540, 0x0401f002, 0x80000580, 0x1c01f000, - 0x58141807, 0x8c0c1d10, 0x040207f3, 0x0401f7e7, - 0x42002000, 0x0000ffff, 0x59301009, 0x800811c0, - 0x04000002, 0x58082403, 0x41301000, 0x0401f007, - 0x41781000, 0x41442000, 0x0401f004, 0x41781000, - 0x42002000, 0x0000ffff, 0x5c000000, 0x4c000000, - 0x4803c857, 0x480bc857, 0x4813c857, 0x492fc857, - 0x4943c857, 0x4d2c0000, 0x4c080000, 0x4c100000, - 0x4c140000, 0x4c180000, 0x0201f800, 0x0010082a, - 0x02000800, 0x00100615, 0x5c003000, 0x5c002800, - 0x5c002000, 0x5c001000, 0x4a025a04, 0x0000010d, - 0x800811c0, 0x04000017, 0x83400580, 0x00000029, - 0x04020010, 0x82180580, 0x00000002, 0x0400000a, - 0x82180580, 0x00000003, 0x04000007, 0x82180580, - 0x00000008, 0x04000004, 0x82180580, 0x00000009, - 0x04020004, 0x4a025809, 0xffffffff, 0x0401f002, - 0x480a5809, 0x58080202, 0x48025c13, 0x0401f005, - 0x4a025809, 0xffffffff, 0x4a025c13, 0x0000ffff, - 0x49425a08, 0x48125a06, 0x82100580, 0x0000ffff, - 0x04000012, 0x4c140000, 0x4c180000, 0x4d440000, - 0x4d340000, 0x40128800, 0x0201f800, 0x00020267, - 0x02020800, 0x00100615, 0x59340002, 0x82000500, - 0x00ffffff, 0x48025812, 0x5c026800, 0x5c028800, - 0x5c003000, 0x5c002800, 0x497a5800, 0x497a5c04, - 0x83400580, 0x00000046, 0x04020002, 0x48165a07, - 0x481a5c08, 0x0401fbe0, 0x5c025800, 0x1c01f000, - 0x59300809, 0x800409c0, 0x04000004, 0x58040403, - 0x81440580, 0x1c01f000, 0x82000540, 0x00000001, - 0x0401f7fd, 0x4933c857, 0x4c040000, 0x59300403, - 0x82000d80, 0x0000001e, 0x04020016, 0x800000d0, - 0x59300a16, 0x82040d00, 0x000000ff, 0x80040540, - 0x4803c857, 0x48026416, 0x4a026403, 0x00000085, - 0x4a026203, 0x00000009, 0x4a026406, 0x00000005, - 0x4a02621d, 0x00000004, 0x59a80038, 0x48026206, - 0x42000800, 0x8000004b, 0x0201f800, 0x00020855, - 0x5c000800, 0x1c01f000, 0x4933c857, 0x40000000, - 0x40000000, 0x1c01f000, 0x59300414, 0x4933c857, - 0x4803c857, 0x8c000518, 0x04000009, 0x8c000512, - 0x02020000, 0x00108fdb, 0x0401f918, 0x0201f800, - 0x00020831, 0x0201f800, 0x000208b4, 0x1c01f000, - 0x591c0406, 0x4803c857, 0x82000c80, 0x00000009, - 0x0402100b, 0x0c01f001, 0x0010a2f7, 0x0010a2f7, - 0x0010a2f7, 0x0010a2f9, 0x0010a2f7, 0x0010a2f9, - 0x0010a2f9, 0x0010a2f7, 0x0010a2f9, 0x80000580, - 0x1c01f000, 0x82000540, 0x00000001, 0x1c01f000, - 0x591c0406, 0x82000500, 0x0000001f, 0x82000580, - 0x00000006, 0x0400000e, 0x4803c857, 0x4a026403, - 0x0000003b, 0x4a02641a, 0x00000009, 0x4a02621a, - 0x00002a00, 0x4a026203, 0x00000001, 0x42000800, - 0x80000040, 0x0201f000, 0x00020855, 0x4803c856, - 0x4c040000, 0x4c140000, 0x4d300000, 0x411e6000, - 0x0401f8e6, 0x497a6205, 0x59300414, 0x4803c857, - 0x82000500, 0xffffadff, 0x48026414, 0x497a6405, - 0x5c026000, 0x0201f800, 0x0010082a, 0x02000800, - 0x00100615, 0x5c002800, 0x5c000800, 0x4a025a04, - 0x0000010d, 0x497a5800, 0x497a5c04, 0x4a025a08, - 0x00000045, 0x491e5809, 0x59300402, 0x48025c07, - 0x59300419, 0x48025c0b, 0x591c0414, 0x84000556, - 0x48023c14, 0x591c1809, 0x580c0403, 0x48025a06, - 0x4816580a, 0x48065a0b, 0x0401fb57, 0x4d400000, - 0x42028000, 0x00000045, 0x591c0202, 0x4c000000, - 0x4d300000, 0x411e6000, 0x0401fc82, 0x5c026000, - 0x5c000000, 0x48023a02, 0x5c028000, 0x4a023c06, - 0x00000006, 0x4a023a03, 0x00000007, 0x497a3a06, - 0x497a3a05, 0x1c01f000, 0x4933c857, 0x83380580, - 0x00000013, 0x0402000b, 0x59300403, 0x4803c857, - 0x82000d80, 0x00000085, 0x0400002b, 0x82000d80, - 0x0000008b, 0x04000028, 0x0201f800, 0x00100615, - 0x83380580, 0x00000027, 0x0402000c, 0x0201f800, - 0x001068f6, 0x4d2c0000, 0x4d400000, 0x59325808, - 0x42028000, 0x00000004, 0x0401fe9f, 0x5c028000, - 0x5c025800, 0x1c01f000, 0x83380580, 0x00000014, - 0x040007f3, 0x83380580, 0x00000089, 0x04000005, - 0x83380580, 0x0000008a, 0x02020000, 0x001076fb, - 0x0201f800, 0x00106cb4, 0x02020000, 0x001076fb, - 0x59300a03, 0x82040580, 0x0000000a, 0x04000009, - 0x82040580, 0x0000000c, 0x04000006, 0x0201f800, - 0x00100615, 0x4a026203, 0x0000000a, 0x1c01f000, - 0x83380480, 0x00000093, 0x0402100c, 0x83380480, - 0x00000085, 0x04001009, 0x83380580, 0x00000089, - 0x0400000a, 0x83380580, 0x0000008a, 0x04000022, - 0x0201f800, 0x00100615, 0x493bc857, 0x4933c857, - 0x0201f000, 0x001076fb, 0x4933c857, 0x4c340000, - 0x41306800, 0x0201f800, 0x00020892, 0x04000011, - 0x4a026203, 0x00000001, 0x4a026403, 0x0000001e, - 0x59cc0c07, 0x48066419, 0x59cc0a07, 0x48066219, - 0x58340809, 0x48066009, 0x4a026406, 0x00000004, - 0x42000800, 0x80000040, 0x0201f800, 0x00020855, - 0x40366000, 0x0201f800, 0x000208b4, 0x5c006800, - 0x1c01f000, 0x4933c857, 0x0201f000, 0x000208b4, - 0x59300809, 0x58040200, 0x8c00051a, 0x02020800, - 0x001006ba, 0x1c01f000, 0x0201f800, 0x0010472e, - 0x0400001e, 0x4a026203, 0x00000002, 0x59300414, - 0x84000558, 0x48026414, 0x8c000512, 0x04000004, - 0x59a80039, 0x48026205, 0x0401f007, 0x59a80839, - 0x59a80037, 0x80040400, 0x82000400, 0x0000001e, - 0x48026205, 0x59300009, 0x82000c00, 0x00000011, - 0x50040000, 0x80000540, 0x04000004, 0x82000c00, - 0x00000000, 0x0401f7fb, 0x45300800, 0x497a6000, - 0x82000540, 0x00000001, 0x1c01f000, 0x82100500, - 0xfffffeef, 0x0402001c, 0x4d2c0000, 0x4937c857, - 0x59340811, 0x83341400, 0x00000011, 0x800409c0, - 0x0400000e, 0x40040000, 0x81300580, 0x04000005, - 0x58040800, 0x82041400, 0x00000000, 0x0401f7f8, - 0x59300800, 0x497a6000, 0x44041000, 0x0201f800, - 0x00020831, 0x0401f002, 0x4933c857, 0x5c025800, - 0x492e6008, 0x0201f800, 0x00020831, 0x0201f000, - 0x000208b4, 0x492fc857, 0x4a025a06, 0x00000006, - 0x0201f000, 0x00020381, 0x4c340000, 0x59300009, - 0x800001c0, 0x04000010, 0x82006c00, 0x00000011, - 0x50340000, 0x80000540, 0x04000009, 0x81300580, - 0x04000005, 0x50340000, 0x82006c00, 0x00000000, - 0x0401f7f8, 0x59300000, 0x44006800, 0x5c006800, - 0x1c01f000, 0x59300c06, 0x82040580, 0x00000005, - 0x040007fb, 0x82040580, 0x00000011, 0x040007f8, - 0x82040580, 0x00000006, 0x040007f5, 0x82040580, - 0x00000001, 0x040007f2, 0x0201f800, 0x00100615, - 0x4933c857, 0x4c080000, 0x4c0c0000, 0x4c580000, - 0x59a8101d, 0x59cc1807, 0x820c1d00, 0x00ffffff, - 0x800c0110, 0x80083580, 0x04020014, 0x83cc1400, - 0x00000008, 0x4200b000, 0x00000002, 0x59300009, - 0x82001c00, 0x00000006, 0x0201f800, 0x001082ff, - 0x0402000a, 0x83cc1400, 0x0000000a, 0x4200b000, - 0x00000002, 0x59300009, 0x82001c00, 0x00000008, - 0x0201f800, 0x001082ff, 0x5c00b000, 0x5c001800, - 0x5c001000, 0x1c01f000, 0x4933c856, 0x0201f800, - 0x0010404b, 0x0201f000, 0x00101bf0, 0x493bc857, - 0x4d2c0000, 0x0201f800, 0x0010082a, 0x02000800, - 0x00100615, 0x832cac00, 0x00000005, 0x4c580000, - 0x4c540000, 0x4200b000, 0x00000006, 0x4578a800, - 0x8054a800, 0x8058b040, 0x040207fd, 0x83380580, - 0x00000046, 0x04020004, 0x4a025a04, 0x00000144, - 0x0401f008, 0x4a025a04, 0x00000146, 0x83380580, - 0x00000041, 0x04000003, 0x4a025a06, 0x00000001, - 0x59cc0007, 0x82000500, 0xff000000, 0x80000110, - 0x59cc1008, 0x82081500, 0xff000000, 0x80081540, - 0x480a580a, 0x83380580, 0x00000046, 0x04020006, - 0x59cc0007, 0x82000500, 0x00ffffff, 0x4802580b, - 0x0401f005, 0x59cc0008, 0x82000500, 0x00ffffff, - 0x4802580b, 0x83380580, 0x00000046, 0x04020004, - 0x83cc1400, 0x00000009, 0x0401f003, 0x83cc1400, - 0x0000000d, 0x50080000, 0x9c0001c0, 0x4802580c, - 0x80081000, 0x50080000, 0x9c0001c0, 0x4802580d, - 0x83380580, 0x00000046, 0x04020008, 0x59cc000b, - 0x9c0001c0, 0x4802580e, 0x59cc000c, 0x9c0001c0, - 0x4802580f, 0x0401f007, 0x59cc000f, 0x9c0001c0, - 0x4802580e, 0x59cc0010, 0x9c0001c0, 0x4802580f, - 0x83380580, 0x00000046, 0x04020004, 0x83cc1400, - 0x00000011, 0x0401f003, 0x83cc1400, 0x00000015, - 0x412c3000, 0x82183400, 0x00000010, 0x4200b000, - 0x00000004, 0x50080000, 0x9c0001c0, 0x44003000, - 0x80081000, 0x80183000, 0x8058b040, 0x040207fa, - 0x5c00a800, 0x5c00b000, 0x0201f800, 0x00020381, - 0x5c025800, 0x1c01f000, 0x4933c857, 0x492fc857, - 0x59300809, 0x58040200, 0x8c00051e, 0x04000004, - 0x592c0208, 0x84000558, 0x48025a08, 0x1c01f000, - 0x59e0180f, 0x599c0413, 0x800c1000, 0x80080580, - 0x04020002, 0x41781000, 0x59e00010, 0x59e00810, - 0x80040d80, 0x040207fd, 0x80080580, 0x0400000b, - 0x4c080000, 0x599c0814, 0x599c1015, 0x800c00cc, - 0x80040c00, 0x82081440, 0x00000000, 0x5c001800, - 0x82000540, 0x00000001, 0x4803c857, 0x1c01f000, - 0x59300203, 0x4933c857, 0x4937c857, 0x493bc857, - 0x4803c857, 0x82003480, 0x0000000e, 0x02021800, - 0x00100615, 0x0c01f001, 0x0010a4e8, 0x0010a63a, - 0x0010a4e8, 0x0010a4e8, 0x0010a4e8, 0x0010a4e8, - 0x0010a4e8, 0x0010a59f, 0x0010a4ea, 0x0010a4e8, - 0x0010a4e8, 0x0010a4e8, 0x0010a4e8, 0x0010a4e8, - 0x0201f800, 0x00100615, 0x83380580, 0x0000004c, - 0x02020800, 0x00100615, 0x0201f800, 0x0010473b, - 0x04020020, 0x59a80826, 0x82040500, 0x00000009, - 0x82000580, 0x00000008, 0x0400001a, 0x8c040d12, - 0x0400003d, 0x59cc0806, 0x82040d00, 0xff000000, - 0x82040580, 0x03000000, 0x0400001f, 0x82040580, - 0x50000000, 0x04000005, 0x82040580, 0x52000000, - 0x02020000, 0x000208b4, 0x813669c0, 0x04000006, - 0x4d3c0000, 0x417a7800, 0x0201f800, 0x00101de2, - 0x5c027800, 0x4a026403, 0x00000001, 0x0401f014, - 0x59cc0806, 0x82040d00, 0xff000000, 0x82040580, - 0x03000000, 0x04000008, 0x82040580, 0x50000000, - 0x04000005, 0x82040580, 0x52000000, 0x02020000, - 0x000208b4, 0x4a026403, 0x00000009, 0x4a02641a, - 0x00000009, 0x4a02621a, 0x00000000, 0x813669c0, - 0x0402000b, 0x59cc0001, 0x0201f800, 0x001059b9, - 0x02020000, 0x000208b4, 0x0201f800, 0x001043fc, - 0x02020000, 0x000208b4, 0x49366009, 0x4a026406, - 0x00000004, 0x4a026203, 0x00000001, 0x0201f000, - 0x00106470, 0x0201f800, 0x0010393e, 0x04000023, - 0x59cc0806, 0x4807c857, 0x82040d00, 0xff000000, - 0x82040580, 0x03000000, 0x04000033, 0x82040580, - 0x20000000, 0x04000041, 0x82040580, 0x21000000, - 0x04000052, 0x82040580, 0x24000000, 0x0400004f, - 0x82040580, 0x50000000, 0x0400004c, 0x82040580, - 0x52000000, 0x04000049, 0x82040580, 0x05000000, - 0x0402000d, 0x59cc0806, 0x82040d00, 0xff000000, - 0x9c0431c0, 0x42028000, 0x00000046, 0x42002800, - 0x00000001, 0x0401fcf7, 0x0401f940, 0x02000800, - 0x00100615, 0x42002000, 0x00000051, 0x0201f800, - 0x001077d1, 0x59cc0000, 0x82000500, 0x00ffffff, - 0x82000580, 0x00ffffff, 0x04000005, 0x4a026203, - 0x00000007, 0x493a6403, 0x1c01f000, 0x59325817, - 0x812e59c0, 0x02020800, 0x00100843, 0x0201f000, - 0x000208b4, 0x813669c0, 0x040007df, 0x59340400, - 0x82000500, 0x000000ff, 0x82000580, 0x00000003, - 0x040207d9, 0x0401fc73, 0x040207d7, 0x4a026403, - 0x00000009, 0x4a02641a, 0x0000000e, 0x4a02621a, - 0x00001900, 0x0401f7a2, 0x813669c0, 0x0400000c, - 0x59340c00, 0x82040500, 0x000000ff, 0x82000580, - 0x00000009, 0x04000794, 0x82040500, 0x0000ff00, - 0x82000580, 0x00000700, 0x040207c3, 0x4a026403, - 0x00000009, 0x4a02641a, 0x00000009, 0x4a02621a, - 0x00001e00, 0x0401f78e, 0x813669c0, 0x040007f8, - 0x59340c00, 0x82040500, 0x0000ff00, 0x82000580, - 0x00000700, 0x040007f2, 0x0401f7b3, 0x4d2c0000, - 0x4c580000, 0x4c500000, 0x4c540000, 0x41385000, - 0x83380580, 0x00000054, 0x02020800, 0x00100615, - 0x59325808, 0x592c0c0b, 0x82040d00, 0x0000e000, - 0x82040580, 0x00002000, 0x04020076, 0x59300817, - 0x800409c0, 0x04000014, 0x58041404, 0x41cca800, - 0x8204a400, 0x00000005, 0x82080480, 0x00000010, - 0x04021004, 0x4008b000, 0x0401fb84, 0x0401f00a, - 0x40001000, 0x4200b000, 0x0000000f, 0x0401fb7f, - 0x58040801, 0x800409c0, 0x040207f2, 0x0201f800, - 0x00100615, 0x813669c0, 0x0400005e, 0x59344c00, - 0x592c0c09, 0x4807c857, 0x4827c857, 0x82040d00, - 0x000000ff, 0x82040580, 0x00000003, 0x0400002a, - 0x82040580, 0x00000005, 0x04000032, 0x82040580, - 0x00000020, 0x04000036, 0x82040580, 0x00000052, - 0x04000042, 0x82040580, 0x00000050, 0x04000042, - 0x82040580, 0x00000021, 0x04000004, 0x82040580, - 0x00000024, 0x04020043, 0x82240500, 0x0000ff00, - 0x82000580, 0x00000007, 0x04000008, 0x42000800, - 0x00000009, 0x0201f800, 0x001043c7, 0x42005000, - 0x0000000c, 0x0401f037, 0x4a025a06, 0x00000031, - 0x4a02580d, 0x00000009, 0x59340400, 0x4802580e, - 0x0201f800, 0x00020381, 0x0201f800, 0x00107698, - 0x0401f03d, 0x0201f800, 0x001040e4, 0x0201f800, - 0x00104480, 0x42000800, 0x00000003, 0x0201f800, - 0x001043c7, 0x42005000, 0x00000008, 0x0401f021, - 0x59cc0007, 0x0201f800, 0x00105c25, 0x0402001d, - 0x0201f800, 0x001040e4, 0x0401f01a, 0x82240500, - 0x0000ff00, 0x82000580, 0x00000007, 0x040007df, - 0x82240500, 0x000000ff, 0x82000580, 0x00000009, - 0x040007da, 0x0201f800, 0x001044e1, 0x42005000, - 0x0000000a, 0x0401f00b, 0x42005000, 0x0000000e, - 0x0401f003, 0x42005000, 0x00000010, 0x82240500, - 0x0000ff00, 0x82000580, 0x00000007, 0x040007cb, - 0x482a6403, 0x4a026203, 0x00000001, 0x592c000d, - 0x48026011, 0x497a6013, 0x59a80038, 0x48026206, - 0x417a7800, 0x0201f800, 0x00106470, 0x59325817, - 0x812e59c0, 0x04000004, 0x0201f800, 0x00100843, - 0x497a6017, 0x5c00a800, 0x5c00a000, 0x5c00b000, - 0x5c025800, 0x1c01f000, 0x4d2c0000, 0x59325808, - 0x83380580, 0x00000013, 0x0402002a, 0x492fc857, - 0x59300c03, 0x82040580, 0x00000054, 0x0400001e, - 0x82040580, 0x00000010, 0x04000018, 0x82040580, - 0x0000000e, 0x04000015, 0x82040580, 0x00000008, - 0x0400000d, 0x82040580, 0x0000000c, 0x0400000a, - 0x82040580, 0x0000000a, 0x02020800, 0x00100615, - 0x42000800, 0x00000006, 0x0201f800, 0x001043c7, - 0x0401f009, 0x42000800, 0x00000004, 0x0201f800, - 0x001043c7, 0x0401f004, 0x59340200, 0x8400051a, - 0x48026a00, 0x4a025a06, 0x00000000, 0x0201f800, - 0x00020381, 0x0201f800, 0x000208b4, 0x0401f024, - 0x83380580, 0x00000027, 0x0400000f, 0x83380580, - 0x00000014, 0x02020800, 0x00100615, 0x492fc857, - 0x0201f800, 0x001068f6, 0x42028000, 0x00000031, - 0x42000800, 0x00000004, 0x42001000, 0x000000ff, - 0x0401f00a, 0x492fc857, 0x0201f800, 0x001068f6, - 0x42028000, 0x00000031, 0x42000800, 0x00000004, - 0x42001000, 0x00000010, 0x49425a06, 0x4806580d, - 0x480a580e, 0x0201f800, 0x00020381, 0x0201f800, - 0x00104a83, 0x0201f800, 0x00107698, 0x5c025800, - 0x1c01f000, 0x492fc857, 0x42007000, 0x0010b5f6, - 0x58380807, 0x800409c0, 0x04020005, 0x492c7008, - 0x492c7007, 0x0201f000, 0x001008be, 0x492c0800, - 0x492c7007, 0x1c01f000, 0x4d2c0000, 0x4c580000, - 0x4c500000, 0x4c540000, 0x4933c857, 0x4937c857, - 0x59cc0806, 0x4807c857, 0x82040d00, 0xff000000, - 0x82040580, 0x03000000, 0x0400000d, 0x82040580, - 0x05000000, 0x0400000a, 0x82040580, 0x21000000, - 0x04000030, 0x82040580, 0x24000000, 0x0400002d, - 0x82040580, 0x20000000, 0x0402002f, 0x0201f800, - 0x0010082a, 0x0400002c, 0x492fc857, 0x492e6017, - 0x59a8b016, 0x8258b400, 0x0000001b, 0x8258b500, - 0xfffffffc, 0x8058b104, 0x485a5c04, 0x412c7800, - 0x41cca000, 0x82580480, 0x00000010, 0x04021005, - 0x832cac00, 0x00000005, 0x0401fa78, 0x0401f015, - 0x40580800, 0x4200b000, 0x0000000f, 0x832cac00, - 0x00000005, 0x0401fa71, 0x8204b480, 0x0000000f, - 0x0201f800, 0x0010082a, 0x04000004, 0x492c7801, - 0x412c7800, 0x0401f7ec, 0x59325817, 0x0201f800, - 0x00100843, 0x497a6017, 0x80000580, 0x0401f006, - 0x59340200, 0x84000554, 0x48026a00, 0x82000540, - 0x00000001, 0x5c00a800, 0x5c00a000, 0x5c00b000, - 0x5c025800, 0x1c01f000, 0x4933c857, 0x492fc857, - 0x4d2c0000, 0x4c5c0000, 0x5930bc06, 0x59300a03, - 0x82040580, 0x00000007, 0x0400003c, 0x82040580, - 0x00000001, 0x02020800, 0x00100615, 0x0201f800, - 0x0010698c, 0x4df00000, 0x598c000d, 0x81300580, - 0x04020019, 0x59300004, 0x8c000520, 0x04000004, - 0x84000520, 0x48026004, 0x0401f019, 0x825c0580, - 0x00000011, 0x0402000d, 0x42001000, 0x0010b5f4, - 0x50081000, 0x58080002, 0x82000580, 0x00000100, - 0x04000006, 0x5808000c, 0x81300580, 0x02020800, - 0x00100615, 0x0401f00a, 0x0201f800, 0x00106be2, - 0x04020027, 0x59300004, 0x8c000520, 0x04000004, - 0x84000520, 0x48026004, 0x0401f003, 0x0201f800, - 0x00106619, 0x5c03e000, 0x02000800, 0x00106982, - 0x0201f800, 0x00108df4, 0x02000800, 0x00100615, - 0x59325808, 0x4a025a06, 0x00000005, 0x0201f800, - 0x00020381, 0x825c0580, 0x00000005, 0x0400001b, - 0x0201f800, 0x00104a83, 0x825c0580, 0x00000005, - 0x04000016, 0x59325817, 0x812e59c0, 0x02020800, - 0x00100843, 0x0201f800, 0x00107698, 0x80000580, - 0x5c00b800, 0x5c025800, 0x1c01f000, 0x5c03e000, - 0x02000800, 0x00106982, 0x59300c06, 0x82040580, - 0x00000011, 0x040007ae, 0x82040580, 0x00000005, - 0x040007ab, 0x0401f7f3, 0x0201f800, 0x000208b4, - 0x0401f7ef, 0x4c040000, 0x59340200, 0x4803c857, - 0x8c00051c, 0x04000009, 0x59cc0805, 0x591c0019, - 0x4803c857, 0x80040580, 0x04000004, 0x80000580, - 0x4803c856, 0x0401f003, 0x82000540, 0x00000001, - 0x5c000800, 0x1c01f000, 0x4c000000, 0x4c0c0000, - 0x4c100000, 0x42001800, 0x0000ffff, 0x42002000, - 0x00000004, 0x0401f013, 0x4c000000, 0x4c0c0000, - 0x4c100000, 0x59302009, 0x58101c03, 0x42002000, - 0x00000004, 0x0401f00b, 0x4c000000, 0x4c0c0000, - 0x4c100000, 0x59302009, 0x801021c0, 0x02000800, - 0x00100615, 0x58101c03, 0x42002000, 0x00000007, - 0x480fc857, 0x4813c857, 0x481bc857, 0x0201f800, - 0x001038c7, 0x5c002000, 0x5c001800, 0x5c000000, - 0x1c01f000, 0x83380580, 0x00000092, 0x02020800, - 0x00100615, 0x42000800, 0x80000040, 0x4a026203, - 0x00000001, 0x493a6403, 0x0201f000, 0x00020855, - 0x4d400000, 0x0201f800, 0x0010393e, 0x04000008, - 0x59a80005, 0x84000544, 0x48035005, 0x42028000, - 0x0000002a, 0x0201f800, 0x0010a25b, 0x5c028000, - 0x1c01f000, 0x59a80026, 0x8c000508, 0x04000005, - 0x599c0017, 0x8c00050a, 0x04020002, 0x1c01f000, - 0x82000540, 0x00000001, 0x1c01f000, 0x59300420, - 0x84000540, 0x48026420, 0x1c01f000, 0x4817c857, - 0x4c000000, 0x4c040000, 0x8c142d2a, 0x04000004, - 0x598800b9, 0x80000000, 0x480310b9, 0x8c142d2e, - 0x04000004, 0x598800ba, 0x80000000, 0x480310ba, - 0x8c142d2c, 0x04000013, 0x40140000, 0x82000500, - 0x00070000, 0x82000d80, 0x00030000, 0x0400000d, - 0x82000d80, 0x00040000, 0x0400000a, 0x82000d80, - 0x00050000, 0x04000007, 0x59880005, 0x80000000, - 0x48031005, 0x598800bb, 0x80000000, 0x480310bb, - 0x5c000800, 0x5c000000, 0x1c01f000, 0x4817c857, - 0x4c000000, 0x4c040000, 0x8c142d2a, 0x04000004, - 0x598800bc, 0x80000000, 0x480310bc, 0x8c142d2e, - 0x04000004, 0x598800bd, 0x80000000, 0x480310bd, - 0x8c142d2c, 0x04000013, 0x40140000, 0x82000500, - 0x00070000, 0x82000d80, 0x00030000, 0x0400000d, - 0x82000d80, 0x00040000, 0x0400000a, 0x82000d80, - 0x00050000, 0x04000007, 0x59880005, 0x80000000, - 0x48031005, 0x598800be, 0x80000000, 0x480310be, - 0x5c000800, 0x5c000000, 0x1c01f000, 0x4c000000, - 0x59880001, 0x80000000, 0x4803c857, 0x48031001, - 0x5c000000, 0x1c01f000, 0x4c000000, 0x59880000, - 0x80000000, 0x4803c857, 0x48031000, 0x5c000000, - 0x1c01f000, 0x4c000000, 0x59880002, 0x80000000, - 0x4803c857, 0x48031002, 0x5c000000, 0x1c01f000, - 0x4807c857, 0x4c000000, 0x8c040d2c, 0x04000004, - 0x598800a7, 0x80000000, 0x480310a7, 0x8c040d2a, - 0x04000004, 0x598800a8, 0x80000000, 0x480310a8, - 0x8c040d28, 0x04000004, 0x598800a9, 0x80000000, - 0x480310a9, 0x8c040d26, 0x04000004, 0x598800aa, - 0x80000000, 0x480310aa, 0x8c040d24, 0x04000004, - 0x598800ab, 0x80000000, 0x480310ab, 0x8c040d22, - 0x04000004, 0x598800ac, 0x80000000, 0x480310ac, - 0x8c040d20, 0x04000004, 0x598800ad, 0x80000000, - 0x480310ad, 0x5c000000, 0x1c01f000, 0x4807c857, - 0x4c000000, 0x598800ae, 0x80000000, 0x480310ae, - 0x5c000000, 0x1c01f000, 0x4807c857, 0x4c000000, - 0x8c040d1c, 0x04000004, 0x598800af, 0x80000000, - 0x480310af, 0x8c040d1a, 0x04000004, 0x598800b0, - 0x80000000, 0x480310b0, 0x5c000000, 0x1c01f000, - 0x4807c857, 0x4c000000, 0x8c040d18, 0x04000004, - 0x598800b1, 0x80000000, 0x480310b1, 0x8c040d16, - 0x04000004, 0x598800b2, 0x80000000, 0x480310b2, - 0x8c040d14, 0x04000004, 0x598800b3, 0x80000000, - 0x480310b3, 0x5c000000, 0x1c01f000, 0x4807c857, - 0x4c000000, 0x8c040d10, 0x04000004, 0x598800b4, - 0x80000000, 0x480310b4, 0x8c040d0c, 0x04000004, - 0x598800b5, 0x80000000, 0x480310b5, 0x5c000000, - 0x1c01f000, 0x4807c857, 0x4c000000, 0x8c040d08, - 0x04000004, 0x598800b6, 0x80000000, 0x480310b6, - 0x8c040d04, 0x04000004, 0x598800b7, 0x80000000, - 0x480310b7, 0x5c000000, 0x1c01f000, 0x4807c856, - 0x4c000000, 0x59880080, 0x80000000, 0x48031080, - 0x5c000000, 0x1c01f000, 0x4803c857, 0x4c040000, - 0x50000800, 0x80040800, 0x4807c857, 0x44040000, - 0x5c000800, 0x1c01f000, 0x480fc857, 0x4c000000, - 0x820c0580, 0x00000000, 0x04020004, 0x42000000, - 0x0010b617, 0x0401f014, 0x820c0580, 0x00001001, - 0x04020004, 0x42000000, 0x0010b618, 0x0401f00e, - 0x820c0580, 0x00001002, 0x04020004, 0x42000000, - 0x0010b619, 0x0401f008, 0x820c0c80, 0x0000201c, - 0x02021800, 0x00100615, 0x820c0500, 0x0000001f, - 0x0c01f804, 0x0401ffdd, 0x5c000000, 0x1c01f000, - 0x0010a8b0, 0x0010a8b3, 0x0010a8b6, 0x0010a8b9, - 0x0010a8bc, 0x0010a8bf, 0x0010a8c2, 0x0010a8c5, - 0x0010a8c8, 0x0010a8cb, 0x0010a8ce, 0x0010a8d1, - 0x0010a8d4, 0x0010a8d7, 0x0010a8da, 0x0010a8dd, - 0x0010a8e0, 0x0010a8e3, 0x0010a8e6, 0x0010a8e9, - 0x0010a8ec, 0x0010a8ef, 0x0010a8f2, 0x0010a8f5, - 0x0010a8f8, 0x0010a8fb, 0x0010a8fe, 0x0010a901, - 0x42000000, 0x0010b61a, 0x1c01f000, 0x42000000, - 0x0010b61b, 0x1c01f000, 0x42000000, 0x0010b61c, - 0x1c01f000, 0x42000000, 0x0010b61d, 0x1c01f000, - 0x42000000, 0x0010b61e, 0x1c01f000, 0x42000000, - 0x0010b61f, 0x1c01f000, 0x42000000, 0x0010b620, - 0x1c01f000, 0x42000000, 0x0010b621, 0x1c01f000, - 0x42000000, 0x0010b622, 0x1c01f000, 0x42000000, - 0x0010b623, 0x1c01f000, 0x42000000, 0x0010b624, - 0x1c01f000, 0x42000000, 0x0010b625, 0x1c01f000, - 0x42000000, 0x0010b626, 0x1c01f000, 0x42000000, - 0x0010b627, 0x1c01f000, 0x42000000, 0x0010b628, - 0x1c01f000, 0x42000000, 0x0010b629, 0x1c01f000, - 0x42000000, 0x0010b62a, 0x1c01f000, 0x42000000, - 0x0010b62b, 0x1c01f000, 0x42000000, 0x0010b62c, - 0x1c01f000, 0x42000000, 0x0010b62d, 0x1c01f000, - 0x42000000, 0x0010b62e, 0x1c01f000, 0x42000000, - 0x0010b62f, 0x1c01f000, 0x42000000, 0x0010b630, - 0x1c01f000, 0x42000000, 0x0010b631, 0x1c01f000, - 0x42000000, 0x0010b632, 0x1c01f000, 0x42000000, - 0x0010b633, 0x1c01f000, 0x42000000, 0x0010b634, - 0x1c01f000, 0x42000000, 0x0010b635, 0x1c01f000, - 0x480fc857, 0x4c000000, 0x820c0580, 0x00000001, - 0x04020004, 0x42000000, 0x0010b60c, 0x0401f012, - 0x820c0580, 0x00000002, 0x04020004, 0x42000000, - 0x0010b60d, 0x0401f00c, 0x820c0580, 0x00000003, - 0x04020004, 0x42000000, 0x0010b60e, 0x0401f006, - 0x820c0580, 0x00000004, 0x04020004, 0x42000000, - 0x0010b60f, 0x0401ff51, 0x5c000000, 0x1c01f000, - 0x4c000000, 0x59a80026, 0x4803c857, 0x8c000502, - 0x04000010, 0x8c000506, 0x04000004, 0x42000000, - 0x0010b63f, 0x0401f012, 0x8c00050a, 0x04000004, - 0x42000000, 0x0010b63e, 0x0401f00d, 0x8c000508, - 0x04000004, 0x42000000, 0x0010b641, 0x0401f008, - 0x0201f800, 0x00104e0d, 0x04000006, 0x8c000506, - 0x04020004, 0x42000000, 0x0010b640, 0x0401ff33, - 0x5c000000, 0x1c01f000, 0x8058b1c0, 0x02000800, - 0x00100615, 0x5450a800, 0x8050a000, 0x8054a800, - 0x8058b040, 0x040207fc, 0x1c01f000, 0x8058b1c0, - 0x02000800, 0x00100615, 0x4450a800, 0x8054a800, - 0x8058b040, 0x040207fd, 0x1c01f000, 0x8058b1c0, - 0x02000800, 0x00100615, 0x50500000, 0x9c0001c0, - 0x4400a800, 0x8050a000, 0x8054a800, 0x8058b040, - 0x040207fa, 0x1c01f000, 0x4c000000, 0x59a80008, - 0x8c00051c, 0x5c000000, 0x1c01f000, 0x00000001, - 0x00000002, 0x00000004, 0x00000008, 0x00000010, - 0x00000020, 0x00000040, 0x00000080, 0x00000100, - 0x00000200, 0x00000400, 0x00000800, 0x00001000, - 0x00002000, 0x00004000, 0x00008000, 0x00010000, - 0xd2764e14 -}; - -#ifdef UNIQUE_FW_NAME -uint32_t fw2400_length01 = 0x0000a971 ; -#else -uint32_t risc_code_length01 = 0x0000a971 ; -#endif - - -#ifdef UNIQUE_FW_NAME -uint32_t fw2400_addr02 = 0x0010d000 ; -#else -uint32_t risc_code_addr02 = 0x0010d000 ; -#endif - -#ifdef UNIQUE_FW_NAME -uint32_t fw2400_code02[] = { -#else -uint32_t risc_code02[] = { -#endif - 0x00000000, 0x00000000, 0x0010d000, 0x0000165e, - 0x00000000, 0x00000000, 0x00020000, 0x000009f7, - 0x836c0580, 0x00000003, 0x02020000, 0x00100314, - 0x42000000, 0x0010b2b7, 0x50000000, 0x800001c0, - 0x0402098a, 0x0401f94d, 0x0201f800, 0x00020524, - 0x0401fbfe, 0x0201f800, 0x0002084c, 0x0201f800, - 0x000206af, 0x0401f7ef, 0x59b800ea, 0x82000d00, - 0xf0000038, 0x02020000, 0x00100ac3, 0x8c000510, - 0x02000000, 0x00100ac2, 0x59ba60e0, 0x81300182, - 0x0402104e, 0x04002030, 0x8532653e, 0x59300406, - 0x82000580, 0x00000003, 0x04020028, 0x59300203, - 0x82000580, 0x00000004, 0x04020024, 0x59325808, - 0x59300402, 0x4a025a04, 0x00000103, 0x900001c0, - 0x48025806, 0x497a5807, 0x497a5c09, 0x5930001f, - 0x80000540, 0x02020800, 0x00100d9a, 0x59300004, - 0x8c00053e, 0x04020010, 0x0401fb47, 0x59326809, - 0x0201f800, 0x000208b4, 0x5934000f, 0x5934140b, - 0x80081040, 0x04001002, 0x480a6c0b, 0x80000540, - 0x04020a31, 0x59b800ea, 0x8c000510, 0x040207d7, - 0x1c01f000, 0x0201f800, 0x00106cb4, 0x040007ef, - 0x0201f000, 0x00100aae, 0x42027000, 0x00000055, - 0x0401f027, 0x83326500, 0x3fffffff, 0x59300406, - 0x82000580, 0x00000003, 0x04020015, 0x59325808, - 0x59326809, 0x59301402, 0x4a025a04, 0x00000103, - 0x900811c0, 0x480a5806, 0x497a5c09, 0x497a5807, - 0x0401fb21, 0x0201f800, 0x000208b4, 0x5934000f, - 0x5934140b, 0x80081040, 0x04001002, 0x480a6c0b, - 0x80000540, 0x04020a0c, 0x0401f7db, 0x42027000, - 0x00000054, 0x0401f00a, 0x83300500, 0x60000000, - 0x02000000, 0x00100ab1, 0x81326580, 0x8000013a, - 0x82000400, 0x00100ac9, 0x50027000, 0x59300c06, - 0x82040580, 0x00000002, 0x02000000, 0x00100aae, - 0x59300004, 0x8c00053e, 0x04020004, 0x0201f800, - 0x000208d8, 0x0401f7c4, 0x0201f800, 0x00106cb4, - 0x040007fb, 0x0201f000, 0x00100aae, 0x59325808, - 0x412c7000, 0x58380a04, 0x82040500, 0x0000000f, - 0x82000c00, 0x0010110d, 0x50044000, 0x0c01f001, - 0x00100e24, 0x00100e24, 0x000200a0, 0x00100e24, - 0x00100e24, 0x00100e24, 0x00100e24, 0x00100e24, - 0x000200b0, 0x00100e38, 0x00100e24, 0x00100e24, - 0x00100e26, 0x00100e24, 0x00100e24, 0x00100e24, - 0x5838040a, 0x8c000500, 0x02000800, 0x00100615, - 0x50200000, 0x80387c00, 0x583c1002, 0x583c2800, - 0x583c2001, 0x58380a07, 0x5838300f, 0x59303807, - 0x58384c08, 0x5838000d, 0x48026012, 0x0401f010, - 0x5838020a, 0x8c000502, 0x02000000, 0x00100e24, - 0x50200000, 0x80387c00, 0x583c2800, 0x583c2001, - 0x583c1002, 0x592c0a07, 0x592c4c08, 0x592c300f, - 0x59303807, 0x497a6012, 0x497a6013, 0x4816600e, - 0x4812600f, 0x480a6010, 0x481a6011, 0x80040840, - 0x4806600d, 0x02020000, 0x00100e65, 0x841c3d40, - 0x481e6007, 0x1c01f000, 0x41787800, 0x59325808, - 0x592c0c0a, 0x8c040d02, 0x02000000, 0x00100fda, - 0x592c000d, 0x592c100f, 0x592c0a04, 0x480a6011, - 0x48026012, 0x48026013, 0x412c3000, 0x82040500, - 0x0000000f, 0x82000400, 0x0010110d, 0x50003800, - 0x501c0000, 0x401c1000, 0x592c1a07, 0x4802600a, - 0x481a600b, 0x480a600c, 0x480e600d, 0x843c7d4a, - 0x403c1000, 0x1c01f000, 0x41787800, 0x497a6012, - 0x592c0a04, 0x412c3000, 0x592c1a07, 0x82040500, - 0x0000000f, 0x82000400, 0x0010110d, 0x50004000, - 0x50200000, 0x40201000, 0x4802600a, 0x481a600b, - 0x480a600c, 0x480e600d, 0x80000580, 0x483e6004, - 0x1c01f000, 0x0002014c, 0x00020139, 0x00020139, - 0x00020139, 0x00020139, 0x00020139, 0x00020139, - 0x00020139, 0x00020139, 0x00020139, 0x00020139, - 0x00020139, 0x00020139, 0x00020139, 0x00020139, - 0x00020139, 0x00020139, 0x00020139, 0x00020139, - 0x00020139, 0x00020139, 0x00020139, 0x00020139, - 0x00020139, 0x00020139, 0x00020139, 0x00020139, - 0x00020139, 0x00020139, 0x00020139, 0x00020139, - 0x00020139, 0x00020139, 0x00020139, 0x00020139, - 0x00020139, 0x00020139, 0x00020139, 0x00020139, - 0x00020139, 0x00020139, 0x00020139, 0x00020139, - 0x00020139, 0x00020139, 0x00020139, 0x00020139, - 0x00020139, 0x00020139, 0x00020139, 0x00020139, - 0x00020139, 0x00020139, 0x00020139, 0x00020139, - 0x00020139, 0x00020139, 0x00020139, 0x00020139, - 0x00020139, 0x00020139, 0x00020139, 0x00020139, - 0x00020139, 0x4c000000, 0x4df00000, 0x4203e000, - 0xb0100000, 0x41f00000, 0x81fe1500, 0x8d0a1512, - 0x02020800, 0x00101468, 0x8d0a1518, 0x02020800, - 0x00020861, 0x8d0a151a, 0x04020ed0, 0x83080500, - 0x00000d00, 0x04020804, 0x5c03e000, 0x5c000000, - 0x1801f000, 0x8d0a1516, 0x02020800, 0x001012d9, - 0x8d0a1514, 0x02020800, 0x001011a5, 0x8d0a1508, - 0x02020800, 0x001011aa, 0x8d0a1500, 0x02020000, - 0x000207c8, 0x1c01f000, 0x42000000, 0x0010b2bd, - 0x50000000, 0x8c000504, 0x04000014, 0x42000000, - 0x0010b2bd, 0x50000000, 0x8c000502, 0x04020002, - 0x1c01f000, 0x4df00000, 0x4203e000, 0x50000000, - 0x42034000, 0x0010b2a0, 0x59a0001d, 0x59a1d81e, - 0x84000502, 0x4803401d, 0x58ec0009, 0x0801f800, - 0x5c03e000, 0x1c01f000, 0x04027002, 0x04026002, - 0x1c01f000, 0x4df00000, 0x4203e000, 0x50000000, - 0x0201f800, 0x0010082a, 0x0400001a, 0x412dd800, - 0x48efc857, 0x0201f800, 0x00103941, 0x42034000, - 0x0010b2a0, 0x49a1d80b, 0x48ef401e, 0x59a0001d, - 0x84000544, 0x4803401d, 0x59e00020, 0x4803c857, - 0x59e00021, 0x4803c857, 0x59e00022, 0x4803c857, - 0x59e00023, 0x4803c857, 0x59e00024, 0x4803c857, - 0x0201f800, 0x00101fbb, 0x0201f800, 0x00101fda, - 0x5c03e000, 0x1c01f000, 0x4da00000, 0x4df00000, - 0x4203e000, 0x50000000, 0x04006051, 0x42034000, - 0x0010b2a0, 0x59a01017, 0x59a01818, 0x800c19c0, - 0x04020008, 0x59a0381b, 0x801c39c0, 0x02000800, - 0x00100615, 0x59a0041c, 0x801c3c00, 0x0401f00c, - 0x59a00419, 0x82000400, 0x00000002, 0x48034419, - 0x82000c80, 0x00000013, 0x04001003, 0x497b4419, - 0x41780000, 0x59a03816, 0x801c3c00, 0x80081040, - 0x480b4017, 0x581c0200, 0x4803c021, 0x581c0401, - 0x4803c022, 0x581c0201, 0x4803c023, 0x581c0400, - 0x4803c020, 0x900001c0, 0x82000540, 0x00000012, - 0x4803c011, 0x59e00017, 0x8c000508, 0x04000003, - 0x4a03c017, 0x00000002, 0x4203e000, 0x30000001, - 0x800c19c0, 0x04000007, 0x800c1840, 0x480f4018, - 0x0402001f, 0x497b4419, 0x497b4219, 0x0401f01c, - 0x800811c0, 0x0402000b, 0x4d2c0000, 0x59a2581b, - 0x0201f800, 0x0010083a, 0x5c025800, 0x497b401b, - 0x497b401a, 0x497b441c, 0x497b421c, 0x0401f010, - 0x59a0041c, 0x82000400, 0x00000002, 0x82000c80, - 0x00000012, 0x4803441c, 0x04001009, 0x4d2c0000, - 0x59a2581b, 0x592c3813, 0x481f401b, 0x497b441c, - 0x0201f800, 0x0010083a, 0x5c025800, 0x5c03e000, - 0x5c034000, 0x1c01f000, 0x59a80005, 0x82000500, - 0x00000003, 0x02020000, 0x00104145, 0x59340400, - 0x82000580, 0x00000606, 0x02020000, 0x00104116, - 0x5934000d, 0x80027d40, 0x02020000, 0x00104151, - 0x0401f803, 0x80000580, 0x1c01f000, 0x5934000f, - 0x59341203, 0x80080540, 0x0402005d, 0x5934020b, - 0x5934140b, 0x80080480, 0x04021059, 0x0201f800, - 0x00020892, 0x04000052, 0x592c0406, 0x49366009, - 0x492e6008, 0x4a026406, 0x00000003, 0x4a026403, - 0x00000040, 0x80081000, 0x480a6c0b, 0x800000c2, - 0x800018c4, 0x800c0400, 0x48026206, 0x592c0808, - 0x592c1809, 0x592c020a, 0x48066017, 0x480e6018, - 0x8c000502, 0x0400002a, 0x4a026203, 0x00000004, - 0x592c0207, 0x80000040, 0x0402001a, 0x59a80070, - 0x80000040, 0x040207ff, 0x592c0204, 0x82000500, - 0x000000ff, 0x82000580, 0x00000018, 0x04020011, - 0x592c180f, 0x59300007, 0x82000540, 0x00000091, - 0x480e6011, 0x48026007, 0x42000000, 0x80000004, - 0x48026004, 0x59bc00ea, 0x8c000516, 0x040207fe, - 0x83300400, 0x20000000, 0x480378e1, 0x1c01f000, - 0x0401fe4b, 0x59300007, 0x8400054e, 0x48026007, - 0x592c1a04, 0x820c1d00, 0x000000ff, 0x820c0580, - 0x00000048, 0x04000012, 0x0401f7ec, 0x8c000500, - 0x04020e9e, 0x4a026203, 0x00000002, 0x59a80071, - 0x80000040, 0x040207ff, 0x592c1a04, 0x820c1d00, - 0x000000ff, 0x820c0580, 0x00000018, 0x040007df, - 0x820c0580, 0x00000048, 0x040207dc, 0x42000800, - 0x80000804, 0x0201f000, 0x00106466, 0x800811c0, - 0x04020003, 0x4a026a03, 0x00000001, 0x59340010, - 0x492e6810, 0x80000d40, 0x04020003, 0x492e680f, - 0x1c01f000, 0x492c0800, 0x1c01f000, 0x83440c80, - 0x00000800, 0x04021009, 0x83440400, 0x0010aa00, - 0x50000000, 0x80000540, 0x04000004, 0x40026800, - 0x80000580, 0x1c01f000, 0x82000540, 0x00000001, - 0x1c01f000, 0x59340203, 0x80000540, 0x0402004b, - 0x4d300000, 0x4d2c0000, 0x5934000f, 0x80025d40, - 0x04000044, 0x0201f800, 0x00020892, 0x0400003f, - 0x592c0000, 0x4802680f, 0x80000540, 0x04020002, - 0x48026810, 0x592c2a04, 0x80081000, 0x480a6c0b, - 0x49366009, 0x492e6008, 0x82142d00, 0x000000ff, - 0x82140580, 0x00000012, 0x04000035, 0x4a026406, - 0x00000003, 0x4a026403, 0x00000040, 0x592c0406, - 0x800000c2, 0x800018c4, 0x800c0400, 0x48026206, - 0x592c0808, 0x592c1809, 0x592c020a, 0x48066017, - 0x480e6018, 0x8c000502, 0x02000000, 0x001045a1, - 0x4a026203, 0x00000004, 0x592c0207, 0x80000040, - 0x02020000, 0x00104594, 0x82140580, 0x00000018, - 0x02020000, 0x00104594, 0x592c180f, 0x59300007, - 0x82000540, 0x00000091, 0x480e6011, 0x48026007, - 0x42000000, 0x80000004, 0x48026004, 0x59bc00ea, - 0x8c000516, 0x040207fe, 0x83300400, 0x20000000, - 0x480378e1, 0x5934020b, 0x5934140b, 0x80080480, - 0x040017be, 0x0401f003, 0x4a026a03, 0x00000001, - 0x5c025800, 0x5c026000, 0x1c01f000, 0x497a5800, - 0x49325809, 0x4a026406, 0x00000006, 0x4a026203, - 0x00000007, 0x0401f802, 0x0401f7ef, 0x59a80021, - 0x800001c0, 0x02020000, 0x001045c3, 0x59a80005, - 0x8c000504, 0x02020000, 0x001045bf, 0x59340200, - 0x8c000518, 0x02020000, 0x001045bb, 0x592c0a0c, - 0x48066202, 0x4a025a06, 0x00000000, 0x8c000508, - 0x02020000, 0x001045b7, 0x4d3c0000, 0x417a7800, - 0x0201f800, 0x000207ce, 0x5c027800, 0x1c01f000, - 0x59980026, 0x497a5800, 0x80000540, 0x04020067, - 0x59d80105, 0x82000d00, 0x00018780, 0x04020197, - 0x800000f6, 0x8000013c, 0x0c01f001, 0x000202f3, - 0x0002034e, 0x00020308, 0x00020326, 0x592c0001, - 0x492fb107, 0x80000d40, 0x04020805, 0x59940019, - 0x80000540, 0x04002085, 0x1c01f000, 0x497a5801, - 0x40065800, 0x592c0001, 0x496a5800, 0x815eb800, - 0x412ed000, 0x80000d40, 0x040207f9, 0x59c80000, - 0x82000540, 0x00001200, 0x48039000, 0x1c01f000, - 0x492fb107, 0x592c0001, 0x80000d40, 0x04020ff0, - 0x59da5908, 0x835c0480, 0x00000020, 0x0400100d, - 0x0402b00b, 0x492fb007, 0x0400e7fa, 0x59d80105, - 0x82000500, 0x00018780, 0x0402016c, 0x59940019, - 0x80000540, 0x04002065, 0x1c01f000, 0x0400f009, - 0x496a5800, 0x412ed000, 0x815eb800, 0x59c80000, - 0x82000540, 0x00001200, 0x48039000, 0x0401f7ef, - 0x492fa807, 0x0401f7ed, 0x59d81108, 0x45681000, - 0x400ad000, 0x815eb800, 0x0400e7fc, 0x59c80000, - 0x82000540, 0x00001200, 0x48039000, 0x0402d009, - 0x592c0001, 0x492fb107, 0x80000d40, 0x04020fc8, - 0x59940019, 0x80000540, 0x04002048, 0x1c01f000, - 0x59d80105, 0x82000500, 0x00018780, 0x04020147, - 0x42000000, 0x0010b654, 0x0201f800, 0x0010a86e, - 0x59980026, 0x59980828, 0x80000000, 0x48033026, - 0x492f3028, 0x800409c0, 0x04000003, 0x492c0800, - 0x0401f002, 0x492f3029, 0x592c0001, 0x80000d40, - 0x04020faf, 0x0401f7e7, 0x59980026, 0x59980828, - 0x80000000, 0x48033026, 0x492f3028, 0x800409c0, - 0x04000003, 0x492c0800, 0x0401f002, 0x492f3029, - 0x592c0001, 0x80000d40, 0x04020fa1, 0x0402d00d, - 0x59980029, 0x80025d40, 0x0400000e, 0x59980026, - 0x80000040, 0x48033026, 0x04020002, 0x48033028, - 0x592c0000, 0x48033029, 0x492fb107, 0x0400d7f5, - 0x42000000, 0x0010b654, 0x0201f800, 0x0010a86e, - 0x0402e00a, 0x59da5908, 0x496a5800, 0x412ed000, - 0x815eb800, 0x0400e7fc, 0x59c80000, 0x82000540, - 0x00001200, 0x48039000, 0x59d80105, 0x82000500, - 0x00018780, 0x04020109, 0x59940019, 0x80000540, - 0x04002002, 0x1c01f000, 0x59980023, 0x48032819, - 0x1c01f000, 0x592c0404, 0x8c00051e, 0x02020000, - 0x00104b7b, 0x59980022, 0x80000540, 0x0402075d, - 0x59980026, 0x497a5800, 0x80000540, 0x02020000, - 0x00104ba6, 0x59d80105, 0x82000d00, 0x00018780, - 0x040200f2, 0x800000f6, 0x8000013c, 0x0c01f001, - 0x00020398, 0x00104ba6, 0x0002039d, 0x000203e6, - 0x592c0001, 0x492fb107, 0x80000d40, 0x04020760, - 0x1c01f000, 0x592c0001, 0x492fb107, 0x80000d40, - 0x04020f5b, 0x59da5908, 0x835c0480, 0x00000020, - 0x0400102b, 0x0402b033, 0x492fb007, 0x0400e7fa, - 0x59d80105, 0x82000500, 0x00018780, 0x040200d7, - 0x0400601f, 0x59d8010a, 0x59d8090a, 0x80040580, - 0x040207fd, 0x800408e0, 0x599c1017, 0x8c081508, - 0x04020028, 0x82040d40, 0x00000013, 0x5998002b, - 0x4807c011, 0x84000500, 0x4803302b, 0x59e00017, - 0x8c000508, 0x04020004, 0x4203e000, 0x30000001, - 0x1c01f000, 0x4a03c017, 0x00000003, 0x82040500, - 0x000000ff, 0x82000580, 0x0000001d, 0x040207f7, - 0x4a03c017, 0x0000000d, 0x0401f7f4, 0x5998082b, - 0x84040d40, 0x4807302b, 0x1c01f000, 0x496a5800, - 0x412ed000, 0x815eb800, 0x59c80000, 0x82000540, - 0x00001200, 0x48039000, 0x0400e7cb, 0x0401f7d1, - 0x0402f7f7, 0x492fa807, 0x0400e7c7, 0x0401f7cd, - 0x59e0000f, 0x59e0100f, 0x80081580, 0x040207fd, - 0x81281580, 0x040007d4, 0x40025000, 0x82040d40, - 0x0000001d, 0x0401f7d2, 0x59d80908, 0x45680800, - 0x4006d000, 0x815eb800, 0x0400e7fc, 0x59c80000, - 0x82000540, 0x00001200, 0x48039000, 0x02006000, - 0x00104b8d, 0x59d8010a, 0x59d8090a, 0x80040d80, - 0x040207fd, 0x900001c0, 0x82000540, 0x00000013, - 0x4803c011, 0x5998002b, 0x84000500, 0x4803302b, - 0x59e00017, 0x8c000508, 0x04000003, 0x4a03c017, - 0x00000003, 0x4203e000, 0x30000001, 0x59d80105, - 0x82000500, 0x00018780, 0x0402007c, 0x0202d000, - 0x00104b92, 0x592c0001, 0x492fb107, 0x80000d40, - 0x040206ef, 0x1c01f000, 0x59980020, 0x0c01f001, - 0x00020413, 0x00020414, 0x00020434, 0x1c01f000, - 0x4df00000, 0x4203e000, 0x50000000, 0x04026876, - 0x04006004, 0x599c0017, 0x8c000508, 0x040208f5, - 0x59980029, 0x80025d40, 0x0400000a, 0x0402d00b, - 0x59980026, 0x80000040, 0x48033026, 0x592c0000, - 0x492fb107, 0x48033029, 0x04020002, 0x48033028, - 0x5c03e000, 0x1c01f000, 0x59d80105, 0x82000500, - 0x00018780, 0x04020055, 0x42000000, 0x0010b654, - 0x0201f800, 0x0010a86e, 0x5c03e000, 0x1c01f000, - 0x4df00000, 0x4203e000, 0x50000000, 0x599cb817, - 0x59940019, 0x80000540, 0x04002023, 0x0400000e, - 0x59980022, 0x82000580, 0x00000005, 0x0400001e, - 0x59a80069, 0x81640580, 0x0402001b, 0x8c5cbd08, - 0x04000007, 0x59a8006a, 0x59a80866, 0x80040580, - 0x04020015, 0x8c5cbd08, 0x0402002b, 0x59d8090b, - 0x59d8010a, 0x80040580, 0x0400000d, 0x0400600e, - 0x4a03c011, 0x80400012, 0x4a03c020, 0x00008040, - 0x59e00017, 0x8c000508, 0x04000003, 0x4a03c017, - 0x00000002, 0x4203e000, 0x30000001, 0x4a032819, - 0xffff0000, 0x0400e879, 0x04006003, 0x8c5cbd08, - 0x0402088e, 0x59980029, 0x80025d40, 0x04020003, - 0x5c03e000, 0x1c01f000, 0x59d80105, 0x82000500, - 0x00018780, 0x04020019, 0x0202d000, 0x00104c06, - 0x59980826, 0x592c0000, 0x80040840, 0x48073026, - 0x492fb107, 0x48033029, 0x040207f2, 0x48033028, - 0x0401f7f0, 0x59e0000f, 0x59e0080f, 0x80040580, - 0x040207fd, 0x59e00010, 0x59e01010, 0x80081580, - 0x040207fd, 0x40065000, 0x80041580, 0x040007cc, - 0x040067e1, 0x0401f7cf, 0x4803c857, 0x485fc857, - 0x8c00050e, 0x02020800, 0x0010060d, 0x4203e000, - 0x50000000, 0x4200b800, 0x00008004, 0x0201f000, - 0x0010061a, 0x5998002b, 0x8c000500, 0x04020039, - 0x0400e006, 0x59d80105, 0x82000500, 0x00018780, - 0x040207ee, 0x1c01f000, 0x59da5908, 0x835c0c80, - 0x00000020, 0x04001003, 0x0400b028, 0x0400f02a, - 0x496a5800, 0x412ed000, 0x815eb800, 0x59c80000, - 0x82000540, 0x00001200, 0x48039000, 0x0400e7f3, - 0x59d8010a, 0x59d8090a, 0x80040580, 0x040207fd, - 0x800408e0, 0x599c1017, 0x8c081508, 0x04020021, - 0x82040d40, 0x00000013, 0x4807c011, 0x59e00017, - 0x8c000508, 0x0400000a, 0x4a03c017, 0x00000003, - 0x82040500, 0x000000ff, 0x82000580, 0x0000001d, - 0x04020003, 0x4a03c017, 0x0000000d, 0x4203e000, - 0x30000001, 0x59d80105, 0x82000500, 0x00018780, - 0x040207c2, 0x1c01f000, 0x492fb007, 0x0400e7d3, - 0x0401f7e0, 0x492fa807, 0x0400e7d0, 0x0401f7dd, - 0x84000500, 0x4803302b, 0x0400e7cc, 0x0401f7d9, - 0x59e0000f, 0x59e0100f, 0x80081580, 0x040207fd, - 0x81281580, 0x040007db, 0x40025000, 0x82040d40, - 0x0000001d, 0x0401f7d9, 0x59da5908, 0x496a5800, - 0x412ed000, 0x815eb800, 0x0400e7fc, 0x59c80000, - 0x82000540, 0x00001200, 0x48039000, 0x59d8090b, - 0x59980024, 0x48073024, 0x80040480, 0x04020004, - 0x59940019, 0x80000540, 0x04022003, 0x59980823, - 0x48072819, 0x59d80105, 0x82000500, 0x00018780, - 0x04020796, 0x1c01f000, 0x59981025, 0x59e00010, - 0x59e00810, 0x80041d80, 0x040207fd, 0x80080580, - 0x04000011, 0x48073025, 0x59e0000f, 0x59e0100f, - 0x80081d80, 0x040207fd, 0x81280580, 0x04000006, - 0x400a5000, 0x40080000, 0x80040580, 0x0402067f, - 0x1c01f000, 0x59940019, 0x80000540, 0x040227fa, - 0x1c01f000, 0x59e0000f, 0x59e0100f, 0x80081d80, - 0x040207fd, 0x81280580, 0x040007f6, 0x400a5000, - 0x59940019, 0x80000540, 0x040027ef, 0x1c01f000, - 0x59e0000f, 0x59e0100f, 0x80080d80, 0x040207fd, - 0x81280580, 0x04020002, 0x1c01f000, 0x400a5000, - 0x900811c0, 0x82081540, 0x0000001c, 0x480bc011, - 0x59e00017, 0x8c000508, 0x04000003, 0x4a03c017, - 0x0000000c, 0x4203e000, 0x30000001, 0x1c01f000, - 0x41700000, 0x0c01f001, 0x001050f0, 0x0002052f, - 0x001050f0, 0x001050f1, 0x001050ee, 0x001050ee, - 0x001050ee, 0x001050ee, 0x00105594, 0x04010037, - 0x59980006, 0x80000540, 0x0402003c, 0x0402c01c, - 0x4202f800, 0x00000010, 0x4df00000, 0x4203e000, - 0x50000000, 0x49db3005, 0x59da5808, 0x592c0204, - 0x497a5800, 0x497a5801, 0x82000500, 0x000000ff, - 0x82000c80, 0x00000079, 0x04021036, 0x0c01f839, - 0x5c03e000, 0x817ef840, 0x04000009, 0x836c0580, - 0x00000003, 0x04020006, 0x83700580, 0x00000001, - 0x04020010, 0x0401001b, 0x0400c7e8, 0x0400f94b, - 0x0400b135, 0x59d40005, 0x82000500, 0x43018780, - 0x02020000, 0x00105523, 0x59d80005, 0x82000500, - 0x43018780, 0x02020000, 0x0010552a, 0x1c01f000, - 0x83700580, 0x00000003, 0x02000800, 0x001050f1, - 0x83700580, 0x00000001, 0x040207ed, 0x04010005, - 0x0400c7d2, 0x0401f7ea, 0x4202f800, 0x00000010, - 0x4df00000, 0x4203e000, 0x50000000, 0x49d73005, - 0x59d65808, 0x0401f7ce, 0x4df00000, 0x4203e000, - 0x50000000, 0x40025800, 0x592c0204, 0x497b3005, - 0x497b3006, 0x4202f800, 0x00000010, 0x0401f7c7, - 0x0201f800, 0x00105161, 0x5c03e000, 0x0401f7d4, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105207, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105171, 0x00105161, - 0x00105161, 0x00105161, 0x00105231, 0x00105161, - 0x00105161, 0x00105161, 0x00020623, 0x00105161, - 0x00105398, 0x00105161, 0x00105161, 0x00105161, - 0x000205f5, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105199, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x001054b7, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105502, 0x00105161, 0x0010518b, - 0x00105161, 0x0010547b, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105449, 0x00105161, 0x00105449, - 0x00105556, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105409, 0x00105539, - 0x00105161, 0x00105549, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x592c0204, 0x80000110, 0x80000040, - 0x0400000b, 0x02001000, 0x00105169, 0x48033002, - 0x492f3003, 0x492f3004, 0x4a033008, 0x00020603, - 0x4202e000, 0x00000003, 0x1c01f000, 0x592c0406, - 0x82000c80, 0x0000199a, 0x02021000, 0x00105179, - 0x59a80021, 0x80000540, 0x02020000, 0x001051a7, - 0x592e8a06, 0x83440c80, 0x000007f0, 0x02021000, - 0x00105179, 0x83440400, 0x0010aa00, 0x50000000, - 0x80026d40, 0x02000000, 0x001051bb, 0x59340002, - 0x592c0810, 0x80040580, 0x82000500, 0x00ffffff, - 0x02020000, 0x00105179, 0x0201f800, 0x000201ee, - 0x02020000, 0x001051be, 0x1c01f000, 0x592c0204, - 0x80000110, 0x02000000, 0x00105169, 0x80000040, - 0x0402000b, 0x592c040a, 0x8c000504, 0x04000010, - 0x592c0207, 0x82000c80, 0x00001001, 0x02021000, - 0x00105179, 0x0201f000, 0x0010556e, 0x48033002, - 0x492f3003, 0x492f3004, 0x4a033008, 0x0002063b, - 0x4202e000, 0x00000003, 0x1c01f000, 0x592c0406, - 0x82000c80, 0x0000199a, 0x02021000, 0x00105179, - 0x592e8a06, 0x417a7800, 0x0401fc25, 0x02020000, - 0x0010533c, 0x59340002, 0x592c0808, 0x80040580, - 0x82000500, 0x00ffffff, 0x02020000, 0x00105179, - 0x497a5808, 0x592e6009, 0x83300580, 0xffffffff, - 0x02000000, 0x001052fc, 0x83300480, 0x0010cfc0, - 0x02001000, 0x00105359, 0x59a8000b, 0x81300480, - 0x02021000, 0x00105359, 0x592c240a, 0x49366009, - 0x8c10251c, 0x02020000, 0x001052ea, 0x59a80068, - 0x8c000510, 0x02020000, 0x00105372, 0x59a80821, - 0x800409c0, 0x02020000, 0x001052d0, 0x59a80805, - 0x8c040d04, 0x02020000, 0x00105363, 0x59340200, - 0x8c000518, 0x02020000, 0x00105354, 0x59300c06, - 0x82040580, 0x00000006, 0x02020000, 0x001052f4, - 0x59300414, 0x8c000516, 0x02020000, 0x0010535e, - 0x8c102508, 0x02020000, 0x0010a3d7, 0x59300808, - 0x4a025a06, 0x00000000, 0x800409c0, 0x02020000, - 0x001052cb, 0x592c0a0c, 0x48066202, 0x492e6008, - 0x0401f14a, 0x4df00000, 0x4203e000, 0x50000000, - 0x0402b00b, 0x835c0480, 0x00000020, 0x0400100d, - 0x815eb840, 0x416a5800, 0x592ed000, 0x492fb007, - 0x497a5800, 0x497a5801, 0x0400b7f7, 0x59d80005, - 0x82000500, 0x43018780, 0x02020000, 0x0010552a, - 0x5c03e000, 0x1c01f000, 0x4df00000, 0x4203e000, - 0x50000000, 0x0402f00b, 0x835c0480, 0x00000020, - 0x0400100d, 0x815eb840, 0x416a5800, 0x592ed000, - 0x492fa807, 0x497a5800, 0x497a5801, 0x0400f7f7, - 0x59d40005, 0x82000500, 0x43018780, 0x02020000, - 0x00105523, 0x5c03e000, 0x1c01f000, 0x4df00000, - 0x4203e000, 0x50000000, 0x59940024, 0x80000540, - 0x0400010f, 0x4c000000, 0x42000000, 0x00001000, - 0x50000000, 0x82000480, 0x24320001, 0x04020015, - 0x42000800, 0x00000064, 0x80040840, 0x04000007, - 0x4a030000, 0x00000001, 0x40000000, 0x59800000, - 0x8c000500, 0x040007f9, 0x04000008, 0x42000800, - 0x00007a01, 0x50040000, 0x8c000510, 0x04000003, - 0x84000510, 0x44000800, 0x4a030000, 0x00000000, - 0x59e00002, 0x8c00051e, 0x0402001b, 0x42000000, - 0x00001000, 0x50000000, 0x82000480, 0x24320002, - 0x04020015, 0x42000800, 0x00000064, 0x80040840, - 0x04000007, 0x4a030000, 0x00000001, 0x40000000, - 0x59800000, 0x8c000500, 0x040007f9, 0x04000008, - 0x42000800, 0x00007a17, 0x50040000, 0x8c00050e, - 0x04020003, 0x8400054e, 0x44000800, 0x4a030000, - 0x00000000, 0x5c000000, 0x5994781a, 0x48032825, - 0x803c0480, 0x04001004, 0x04000003, 0x4803281a, - 0x0401f022, 0x41787800, 0x803c7800, 0x82000400, - 0x000003e8, 0x040027fd, 0x4803281a, 0x59a80024, - 0x803c1400, 0x480b5024, 0x803c0040, 0x04000002, - 0x483fc857, 0x59e40852, 0x59a80025, 0x80040580, - 0x04000004, 0x480bc857, 0x59e40052, 0x48035025, - 0x59940026, 0x803c0400, 0x48032826, 0x0201f800, - 0x00105d5a, 0x59940000, 0x82000580, 0x00000000, - 0x04020006, 0x59940026, 0x48032827, 0x497b2826, - 0x4a032800, 0x00000001, 0x4c0c0000, 0x59940007, - 0x80000d40, 0x0400001d, 0x59941006, 0x59940025, - 0x80081c80, 0x04001004, 0x04000003, 0x480f2806, - 0x0401f016, 0x80040840, 0x48072807, 0x82040580, - 0x000003e8, 0x04020007, 0x4c040000, 0x4c0c0000, - 0x59940008, 0x0801f800, 0x5c001800, 0x5c000800, - 0x800409c0, 0x04020004, 0x59940008, 0x0801f800, - 0x0401f006, 0x400c0000, 0x820c1c00, 0x0000000a, - 0x040027ed, 0x480f2806, 0x5c001800, 0x4d180000, - 0x59c40008, 0x8c000534, 0x04020025, 0x417a3000, - 0x83947c00, 0x00000009, 0x583c0001, 0x80000d40, - 0x04020008, 0x823c7c00, 0x00000003, 0x811a3000, - 0x83180580, 0x00000005, 0x040207f8, 0x0401f018, - 0x583c1000, 0x59940025, 0x80080480, 0x04001005, - 0x04000004, 0x48007800, 0x80000040, 0x04021010, - 0x80040840, 0x48047801, 0x04000008, 0x82000400, - 0x0000000a, 0x48007800, 0x040027fa, 0x82040500, - 0x0000007f, 0x0401f7e8, 0x583c0002, 0x4c3c0000, - 0x0801f800, 0x5c007800, 0x0401f7e3, 0x5c023000, - 0x59940019, 0x80001540, 0x04000007, 0x04002006, - 0x59940025, 0x80080480, 0x04021002, 0x80000580, - 0x48032819, 0x5994001c, 0x80000d40, 0x04000013, - 0x5994101b, 0x59940025, 0x80080480, 0x04001005, - 0x04000004, 0x4803281b, 0x80000040, 0x0402100b, - 0x80040840, 0x4807281c, 0x04020004, 0x5994001d, - 0x0801f800, 0x0401f005, 0x82000400, 0x0000000a, - 0x4803281b, 0x040027f7, 0x59940004, 0x80000d40, - 0x04000013, 0x59941003, 0x59940025, 0x80080480, - 0x04001005, 0x04000004, 0x48032803, 0x80000040, - 0x0402100b, 0x80040840, 0x48072804, 0x04020004, - 0x59940005, 0x0801f800, 0x0401f005, 0x82000400, - 0x0000000a, 0x48032803, 0x040027f7, 0x5994001f, - 0x80000d40, 0x04000013, 0x5994101e, 0x59940025, - 0x80080480, 0x04001005, 0x04000004, 0x4803281e, - 0x80000040, 0x0402100b, 0x80040840, 0x4807281f, - 0x04020004, 0x59940020, 0x0801f800, 0x0401f005, - 0x82000400, 0x00000001, 0x4803281e, 0x040027f7, - 0x59940022, 0x80000d40, 0x04000013, 0x59941021, - 0x59940025, 0x80080480, 0x04001005, 0x04000004, - 0x48032821, 0x80000040, 0x0402100b, 0x80040840, - 0x48072822, 0x04020004, 0x59940023, 0x0801f800, - 0x0401f005, 0x82000400, 0x0000000a, 0x48032821, - 0x040027f7, 0x59940824, 0x59940025, 0x80040480, - 0x02001800, 0x00100615, 0x48032824, 0x59940000, - 0x0c01f001, 0x00105cee, 0x00105cf0, 0x00105d16, - 0x59940024, 0x80000000, 0x48032824, 0x4203e000, - 0x70000000, 0x1c01f000, 0x592c0406, 0x800000c2, - 0x800008c4, 0x80040c00, 0x592c040a, 0x48066206, - 0x82000d00, 0x00000003, 0x02000000, 0x00105e97, - 0x8c000500, 0x0402002c, 0x59a80872, 0x80040840, - 0x040207ff, 0x8c00051e, 0x02000000, 0x00105e72, - 0x82000d00, 0x000000c0, 0x02020000, 0x00105e68, - 0x82000d00, 0x00002020, 0x02020000, 0x00105e65, - 0x813e79c0, 0x02020000, 0x00105e65, 0x592c0c0c, - 0x800409c0, 0x02020000, 0x00105e65, 0x59300a03, - 0x82040d80, 0x00000007, 0x02020000, 0x00105e65, - 0x4a026203, 0x00000003, 0x4a026403, 0x00000043, - 0x0201f800, 0x000200ca, 0x82080d40, 0x80003465, - 0x48066004, 0x497a6000, 0x59bc00ea, 0x8c000516, - 0x040207fe, 0x83300400, 0xa0000000, 0x480378e1, - 0x1c01f000, 0x8c000502, 0x02020000, 0x00105eba, - 0x8c00051e, 0x0400000e, 0x82000d00, 0x000000c0, - 0x04000005, 0x82040d80, 0x000000c0, 0x02020000, - 0x00105ebf, 0x82000d00, 0x00002020, 0x82040d80, - 0x00002020, 0x02000000, 0x00105e86, 0x592c0207, - 0x80000040, 0x02020000, 0x00105e90, 0x592c180d, - 0x800c19c0, 0x02020000, 0x00105e90, 0x592c180f, - 0x59300007, 0x82000540, 0x00000011, 0x480e6011, - 0x48026007, 0x4a026203, 0x00000004, 0x4a026403, - 0x00000042, 0x42000800, 0x80002001, 0x0401f02a, - 0x5c000000, 0x4c000000, 0x4803c857, 0x4807c857, - 0x0401f003, 0x42000800, 0x00000001, 0x59325808, - 0x832c0500, 0x00ff0000, 0x0400000d, 0x592c0000, - 0x48065a06, 0x48026008, 0x592c040a, 0x8c000510, - 0x04020008, 0x0201f800, 0x00020381, 0x417a7800, - 0x59300008, 0x80025d40, 0x0402078c, 0x1c01f000, - 0x456a5800, 0x412ed000, 0x815eb800, 0x59c80000, - 0x82000540, 0x00001200, 0x48039000, 0x0401f7f4, - 0x59840000, 0x80000540, 0x04020002, 0x1c01f000, - 0x59840003, 0x80000540, 0x02020000, 0x00105f37, - 0x1c01f000, 0x59300004, 0x82000500, 0x00000100, - 0x80040d40, 0x48066004, 0x59bc00ea, 0x8c000516, - 0x040207fe, 0x83300400, 0x40000000, 0x480378e1, - 0x1c01f000, 0x59bc00ea, 0x82001500, 0xb0000018, - 0x02020000, 0x001069c6, 0x8c000510, 0x0400002a, - 0x59bc10e0, 0x82080500, 0xfffff000, 0x0402000a, - 0x80080108, 0x820a3500, 0x0000000f, 0x4803c857, - 0x1201f000, 0x001069cc, 0x84000510, 0x48026004, - 0x0401f016, 0x840a653e, 0x59300004, 0x8c000520, - 0x040007fa, 0x82000500, 0xfffefeff, 0x48026004, - 0x8c08153e, 0x04020005, 0x42027000, 0x00000013, - 0x0401f858, 0x0401f009, 0x59300004, 0x8c000514, - 0x04000003, 0x0401ffac, 0x0401f02e, 0x42027000, - 0x00000049, 0x0401f84f, 0x59bc00ea, 0x82001500, - 0xb0000018, 0x02020000, 0x001069c6, 0x8c000510, - 0x040207d8, 0x1c01f000, 0x83640480, 0x00000010, - 0x04001019, 0x41626000, 0x41580000, 0x59300a03, - 0x82040d80, 0x00000000, 0x04000008, 0x83326400, - 0x00000024, 0x81300c80, 0x040017f9, 0x42026000, - 0x0010cfc0, 0x0401f7f6, 0x4a026203, 0x00000008, - 0x8166c840, 0x8332c400, 0x00000024, 0x81600480, - 0x04021002, 0x1c01f000, 0x837ac540, 0x0010cfc0, - 0x1c01f000, 0x42000000, 0x0010b653, 0x0201f800, - 0x0010a86e, 0x4967c857, 0x80026580, 0x1c01f000, - 0x83300480, 0x0010cfc0, 0x02001800, 0x00100615, - 0x41580000, 0x81300480, 0x0402100c, 0x04011000, - 0x457a6000, 0x4a026202, 0x0000ffff, 0x83300400, - 0x00000003, 0x4803c840, 0x4a03c842, 0x00000021, - 0x8166c800, 0x1c01f000, 0x41540000, 0x81300480, - 0x02021800, 0x00100615, 0x04011000, 0x457a6000, - 0x4a026202, 0x0000ffff, 0x83300400, 0x00000003, - 0x4803c840, 0x4a03c842, 0x00000021, 0x59a80066, - 0x49335065, 0x80000000, 0x48035066, 0x1c01f000, - 0x4d340000, 0x59326809, 0x59300406, 0x82000500, - 0x0000001f, 0x0c01f803, 0x5c026800, 0x1c01f000, - 0x001076ed, 0x00107700, 0x0010771a, 0x00020900, - 0x001096c1, 0x001096dc, 0x00020975, 0x001076ed, - 0x00107700, 0x00106226, 0x00107733, 0x001076ed, - 0x001076ed, 0x001076ed, 0x001076ed, 0x001076ed, - 0x0010936a, 0x0010a4d0, 0x001076ed, 0x001076ed, - 0x001076ed, 0x001076ed, 0x001076ed, 0x001076ed, - 0x001076ed, 0x001076ed, 0x001076ed, 0x001076ed, - 0x001076ed, 0x001076ed, 0x001076ed, 0x001076ed, - 0x59300203, 0x82000c80, 0x0000000e, 0x02021800, - 0x00100615, 0x0c01f001, 0x00107731, 0x00108337, - 0x00020914, 0x001084cc, 0x00108566, 0x00107731, - 0x00107731, 0x00107731, 0x0010831c, 0x00107731, - 0x00107731, 0x00107731, 0x00107731, 0x0010873a, - 0x83380480, 0x00000058, 0x04021007, 0x83380480, - 0x00000040, 0x04001004, 0x4d2c0000, 0x0c01f803, - 0x5c025800, 0x1c01f000, 0x001083c1, 0x001083c1, - 0x001083c1, 0x001083c1, 0x001083c1, 0x001083c3, - 0x00108463, 0x001083c1, 0x001083c1, 0x001083c1, - 0x001083c1, 0x001083c1, 0x001083c1, 0x001083c1, - 0x001083c1, 0x001083c1, 0x001083c1, 0x001083c1, - 0x001083c1, 0x00108467, 0x00020936, 0x001083c1, - 0x00108466, 0x00108468, 0x59325808, 0x59300811, - 0x59301402, 0x59340200, 0x8c00050e, 0x0402001c, - 0x0401f826, 0x04000005, 0x4a025a04, 0x00000103, - 0x497a5c09, 0x0401f009, 0x4a025a04, 0x00000103, - 0x4a025a06, 0x00000000, 0x497a5c09, 0x800409c0, - 0x02020800, 0x00108531, 0x48065807, 0x480a5c06, - 0x0201f800, 0x00020381, 0x5934000f, 0x5934140b, - 0x80081040, 0x04001002, 0x480a6c0b, 0x80000540, - 0x02020800, 0x00020275, 0x0401f75e, 0x592c020a, - 0x8c000502, 0x040007e9, 0x800409c0, 0x040007e7, - 0x592c0208, 0x8c00050e, 0x040207e4, 0x4933c857, - 0x0201f000, 0x00108fc6, 0x592c020a, 0x8c000500, - 0x04000010, 0x59300015, 0x592c380f, 0x801c3c80, - 0x0400000c, 0x4a025a06, 0x00000015, 0x8c1c3d3e, - 0x04000005, 0x4a025a06, 0x00000007, 0x801c3880, - 0x801c3800, 0x481fc857, 0x821c0d40, 0x00000000, - 0x1c01f000, 0x59300203, 0x82003480, 0x0000000e, - 0x02021800, 0x00100615, 0x0c01f001, 0x001096fb, - 0x00020989, 0x00109d9c, 0x00109daa, 0x000209a5, - 0x001096fb, 0x00109e98, 0x000209c4, 0x001096fb, - 0x001096fb, 0x001096fb, 0x001096fb, 0x001096fb, - 0x001096fb, 0x83380580, 0x00000013, 0x02020000, - 0x00109d23, 0x59300403, 0x82027480, 0x00000044, - 0x02021800, 0x00100615, 0x82000480, 0x00000040, - 0x02001800, 0x00100615, 0x0c01f001, 0x00109d80, - 0x0002099b, 0x00109d82, 0x00109d94, 0x59325808, - 0x832c0500, 0x00ff0000, 0x04000005, 0x592c0c0a, - 0x8c040d1a, 0x02020000, 0x00109d8f, 0x0401fe8e, - 0x0401f710, 0x83380580, 0x00000048, 0x04000007, - 0x83380580, 0x00000053, 0x02000000, 0x00109e3a, - 0x0201f800, 0x00100615, 0x5930001f, 0x59301011, - 0x59300809, 0x58040a00, 0x8c040d0e, 0x02020000, - 0x00109e16, 0x800811c0, 0x02020000, 0x00109e23, - 0x5930001f, 0x80000540, 0x02020000, 0x00109e31, - 0x59325808, 0x592c040a, 0x8c00051e, 0x02000000, - 0x00109e0c, 0x42027000, 0x00000041, 0x0401f001, - 0x83380480, 0x00000054, 0x02021800, 0x00100615, - 0x83380480, 0x00000040, 0x02001000, 0x00109e57, - 0x0c01f001, 0x00109e63, 0x000209e1, 0x00109e6f, - 0x00109e76, 0x00109e63, 0x00109e63, 0x00109e63, - 0x00109e63, 0x00109e65, 0x00109e6a, 0x00109e6a, - 0x00109e63, 0x00109e63, 0x00109e63, 0x00109e63, - 0x00109e6a, 0x00109e63, 0x00109e6a, 0x00109e63, - 0x00109e65, 0x4a026203, 0x00000001, 0x493a6403, - 0x42000800, 0x80002042, 0x0401f66f, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xa36ec441, 0x00000000, - 0x00000000, 0x00000000, 0x00000005, 0xfffffffb, - 0x02800004, 0x00000000, 0x0000c000, 0x0000071b, - 0x073fca5a, 0x0705a5a5, 0x01928009, 0x070ff0e1, - 0x03800006, 0x04958010, 0x05308000, 0x05008000, - 0x0600902f, 0x04a004dc, 0x0202f051, 0x042e4020, - 0x018f021b, 0x033e5000, 0x03020000, 0x078d0018, - 0x0493041a, 0x0092041c, 0x038a0305, 0x078b0303, - 0x048e8010, 0x0678aae5, 0x06000001, 0x07818174, - 0x040010e6, 0x0448e0e6, 0x04818010, 0x002fb008, - 0x0448e0e6, 0x04818010, 0x060ff0e6, 0x00580401, - 0x054880ff, 0x04818010, 0x022a5001, 0x030430d4, - 0x06780043, 0x030e0000, 0x030450ff, 0x06780043, - 0x03019000, 0x048185c4, 0x027c0045, 0x03020000, - 0x06810037, 0x027c0045, 0x03040000, 0x068100c7, - 0x027c0045, 0x03080000, 0x0681061c, 0x04908037, - 0x029105c2, 0x010410a6, 0x0379ff41, 0x037fffff, - 0x072d6000, 0x07601241, 0x050f80ff, 0x032fa009, - 0x05600400, 0x050f80ff, 0x056c04ff, 0x068105da, - 0x073fa009, 0x06000001, 0x0279ff02, 0x0700ffff, - 0x070ff0d1, 0x0179feff, 0x0700ffff, 0x045c0402, - 0x048185da, 0x060ff0d0, 0x0179feff, 0x0700ffff, - 0x057dfeff, 0x0700ffff, 0x068105bc, 0x05600e41, - 0x050f80ff, 0x032fa069, 0x07480000, 0x068105ce, - 0x06780043, 0x070000f0, 0x0781005f, 0x037c00ff, - 0x06000010, 0x0781005f, 0x038005ca, 0x0379ff00, - 0x070fffff, 0x06780043, 0x07f00000, 0x075a0000, - 0x020ef001, 0x038605cc, 0x05484000, 0x02a1819e, - 0x062d6001, 0x002fb001, 0x070ff069, 0x01868072, - 0x060ff079, 0x055c0441, 0x06810010, 0x012fb000, - 0x060560fb, 0x03800078, 0x060ff079, 0x02868198, - 0x070ff069, 0x055c0441, 0x06810010, 0x060560fb, - 0x0400d0d0, 0x062d6002, 0x0648300d, 0x06810086, - 0x070ff0d1, 0x062d6001, 0x045c040b, 0x06810089, - 0x05488000, 0x04818086, 0x072e500c, 0x00208001, - 0x05a004e1, 0x02800010, 0x062d6001, 0x07f00000, - 0x07f00000, 0x070ff0d1, 0x0179feff, 0x070000ff, - 0x055c040c, 0x058180bb, 0x0007b001, 0x03079041, - 0x0307a000, 0x06600a79, 0x050f80ff, 0x053fa80a, - 0x06000010, 0x072d5003, 0x078d0096, 0x0307c003, - 0x0007d004, 0x0107e005, 0x0307f006, 0x02080007, - 0x00081008, 0x01082009, 0x0308300a, 0x0008400b, - 0x0308500c, 0x068d00a1, 0x0678007a, 0x07f00000, - 0x010880ff, 0x03386000, 0x03010000, 0x072e6300, - 0x020ef07f, 0x02860010, 0x070ff07d, 0x0450047c, - 0x050f80ff, 0x002fa819, 0x068d00ae, 0x02080001, - 0x00081002, 0x0448807a, 0x068100b5, 0x0379ff03, - 0x070000ff, 0x01082003, 0x068d00b6, 0x02386004, - 0x03010000, 0x072e6c00, 0x02800010, 0x06780043, - 0x070000f0, 0x068105d5, 0x050020ff, 0x027c0002, - 0x06000010, 0x078100c3, 0x028005d5, 0x0700c0d1, - 0x0379ff0c, 0x070000ff, 0x0380008e, 0x0204a051, - 0x06780043, 0x070000f0, 0x037c00ff, 0x06000010, - 0x0781816a, 0x072d6000, 0x019485be, 0x050fb056, - 0x044880e6, 0x04818010, 0x060ff0d0, 0x0179feff, - 0x0700ffff, 0x057dfeff, 0x0700ffff, 0x068105bc, - 0x05a00212, 0x0349c0e4, 0x0781811d, 0x070ff093, - 0x050010ff, 0x070ff093, 0x045c0401, 0x058180db, - 0x02046092, 0x04002046, 0x04600202, 0x00540401, - 0x048280e6, 0x04500425, 0x070060ff, 0x0730ffff, - 0x0700000f, 0x0742000f, 0x05810190, 0x06a005a4, - 0x0648a002, 0x048180e9, 0x00047089, 0x070ff047, - 0x045c0443, 0x077800ff, 0x07f00000, 0x0781818e, - 0x07780047, 0x0500e000, 0x048185ab, 0x070ff006, - 0x01860117, 0x0179fe47, 0x0700000f, 0x010480ff, - 0x056c7048, 0x06818102, 0x007a0d4a, 0x04003801, - 0x0220f001, 0x0180010f, 0x07608e48, 0x034a60ff, - 0x0700f0ff, 0x074b88ff, 0x037000ff, 0x07000600, - 0x05500448, 0x074d00ff, 0x045a044a, 0x0304a0ff, - 0x070ff00f, 0x01540406, 0x05820117, 0x04950120, - 0x05a001bd, 0x02868123, 0x0134bfff, 0x070fffff, - 0x0104102e, 0x050fd041, 0x00800126, 0x0595011d, - 0x05a001bd, 0x0186011d, 0x0202f00e, 0x052e4030, - 0x040fd02f, 0x070fc0ff, 0x05a00218, 0x02800010, - 0x0400e02f, 0x042e4020, 0x0202f051, 0x0004100e, - 0x0004b00e, 0x050fd041, 0x024a6c46, 0x04500423, - 0x050070ff, 0x03620024, 0x050080ff, 0x04004046, - 0x0700500f, 0x03206000, 0x05601048, 0x0700a0ff, - 0x0700900a, 0x070ff005, 0x04500446, 0x00540425, - 0x04820157, 0x05601622, 0x050f80ff, 0x063fa032, - 0x06000002, 0x03203000, 0x01204000, 0x03205000, - 0x0120b000, 0x0320c000, 0x07601441, 0x050f80ff, - 0x043fa852, 0x06000001, 0x070ff056, 0x056c02ff, - 0x050fb0ff, 0x070560ff, 0x03079041, 0x05600e41, - 0x050f80ff, 0x073fa011, 0x0600003d, 0x06780043, - 0x07f00000, 0x065a007a, 0x010880ff, 0x04a001b6, - 0x058d0150, 0x0208a04a, 0x0108b04b, 0x02386001, - 0x03010000, 0x072e6300, 0x028000a8, 0x0500d00a, - 0x05500405, 0x014a68ff, 0x070090ff, 0x0154040a, - 0x0700c0ff, 0x0600a023, 0x0500b024, 0x02206001, - 0x05601622, 0x050f80ff, 0x063fa04a, 0x06000002, - 0x05601022, 0x050f80ff, 0x043fa819, 0x06000001, - 0x0600a00d, 0x0180013c, 0x06780043, 0x070000f0, - 0x050010ff, 0x027c0001, 0x07000030, 0x078105b2, - 0x027c0001, 0x06000020, 0x078105b2, 0x038005ca, - 0x054880ff, 0x06810010, 0x070ff056, 0x050fb0ff, - 0x044880e5, 0x0581017d, 0x044880e6, 0x04818010, - 0x00800183, 0x056c02ff, 0x050fb0ff, 0x070560ff, - 0x072e5300, 0x044880e6, 0x04818010, 0x072d5003, - 0x06780043, 0x07f00000, 0x010880ff, 0x058d0187, - 0x03386005, 0x03010000, 0x033e6000, 0x0700000c, - 0x052e5200, 0x02800010, 0x0120918e, 0x018004e4, - 0x01209190, 0x018004e4, 0x00209192, 0x018004e4, - 0x03209000, 0x018004e4, 0x01209196, 0x018004e4, - 0x00209198, 0x018004e4, 0x02493075, 0x0681050b, - 0x0120919a, 0x018004e4, 0x06601e01, 0x050f80ff, - 0x063fa029, 0x06000008, 0x02015010, 0x02016051, - 0x00017051, 0x00011051, 0x05601a41, 0x050f80ff, - 0x053fa83a, 0x06000008, 0x05600e41, 0x050f80ff, - 0x01464000, 0x032fa00a, 0x07006011, 0x05007012, - 0x04008013, 0x07009014, 0x0600a015, 0x0400b016, - 0x0700c017, 0x07c00000, 0x072d5003, 0x06601479, - 0x050f80ff, 0x048d01b9, 0x063fa051, 0x0600003e, - 0x07c00000, 0x06005051, 0x0400e02c, 0x0660060e, - 0x050f80ff, 0x032fa009, 0x0379ff00, 0x070000ff, - 0x076c0000, 0x058101dd, 0x0660480e, 0x0500e0ff, - 0x034000ff, 0x01540427, 0x0582020a, 0x03400005, - 0x070ff005, 0x055c0428, 0x0481020e, 0x01680e05, - 0x056c0405, 0x068181bf, 0x040f8029, 0x053fa809, - 0x07000024, 0x06600649, 0x050f80ff, 0x032fa009, - 0x0379ff00, 0x070000ff, 0x076c0000, 0x068181bf, - 0x0400e049, 0x0340002d, 0x050f802b, 0x053fa80a, - 0x06000016, 0x0660480e, 0x0302c0ff, 0x034000ff, - 0x01540427, 0x0582020c, 0x072d6000, 0x0460040e, - 0x050f80ff, 0x0104e0d1, 0x0379ff4e, 0x0700ffff, - 0x062d6002, 0x032fa009, 0x0004d0d0, 0x074b004d, - 0x07780000, 0x07ffff00, 0x055a044d, 0x070000ff, - 0x00201008, 0x04002051, 0x06003051, 0x05304000, - 0x07000060, 0x03205009, 0x07006022, 0x0460040e, - 0x050f80ff, 0x032fa03a, 0x06603c0e, 0x050f80ff, - 0x073fa00a, 0x07000027, 0x050010d1, 0x0460320e, - 0x050f80ff, 0x012fa80a, 0x060ff00e, 0x055c042e, - 0x04810210, 0x07c00000, 0x0400e026, 0x008001cb, - 0x0202c026, 0x008001e6, 0x0500e02e, 0x008001e6, - 0x0400e051, 0x01800209, 0x0349c0e4, 0x04810215, - 0x07c00000, 0x013e4000, 0x070c0000, 0x07c00000, - 0x013e4000, 0x03080000, 0x07c00000, 0x009702f4, - 0x022a5002, 0x0790821d, 0x00910291, 0x030400a6, - 0x0678aae5, 0x06000001, 0x01a1860c, 0x06600c40, - 0x050f80ff, 0x032fa021, 0x074b0000, 0x076c0600, - 0x07818293, 0x05600403, 0x050f80ff, 0x073fa009, - 0x06000002, 0x0279ff04, 0x0700ffff, 0x010440d7, - 0x0179fe44, 0x0700ffff, 0x045c0404, 0x07818295, - 0x0349f044, 0x0681829e, 0x02495001, 0x06818297, - 0x060ff079, 0x045c0440, 0x0781823c, 0x0644f07a, - 0x002fb008, 0x060ff079, 0x045c0440, 0x07818241, - 0x0644f07a, 0x002fb008, 0x0648f001, 0x07818288, - 0x04600e40, 0x050f80ff, 0x06480001, 0x04810257, - 0x0448e001, 0x04810273, 0x02460001, 0x0644f001, - 0x012fa80a, 0x04008040, 0x05a004ee, 0x0286828c, - 0x05a004d8, 0x062da001, 0x013e4000, 0x06000080, - 0x06930013, 0x02920013, 0x02800010, 0x0644f001, - 0x012fa80a, 0x020ef002, 0x00860275, 0x04600840, - 0x050f80ff, 0x053fa809, 0x06000002, 0x05780105, - 0x00800440, 0x017c0105, 0x05000400, 0x06818275, - 0x06601e02, 0x050f80ff, 0x053fa809, 0x06000002, - 0x04602a40, 0x050f80ff, 0x070ff005, 0x053fa809, - 0x06000002, 0x055c0405, 0x06818275, 0x04008040, - 0x0045e008, 0x05a004d8, 0x00800251, 0x0644f001, - 0x012fa80a, 0x050020d8, 0x04600440, 0x050f80ff, - 0x073fa00a, 0x06000001, 0x06480001, 0x07818281, - 0x05308000, 0x03040000, 0x06009040, 0x04a004dc, - 0x00800251, 0x07a0060c, 0x054b0800, 0x056a0700, - 0x06600c40, 0x050f80ff, 0x032fa00a, 0x00800251, - 0x013e4000, 0x06000080, 0x01209288, 0x018004e4, - 0x06009008, 0x05308000, 0x05004000, 0x04a004dc, - 0x00800251, 0x02209002, 0x008002e5, 0x03209000, - 0x008002e5, 0x02209004, 0x008002e5, 0x04a002fd, - 0x062da001, 0x05308000, 0x05002000, 0x06009040, - 0x04a004dc, 0x00800252, 0x013e4000, 0x06000080, - 0x02495001, 0x078182db, 0x04600840, 0x050f80ff, - 0x053fa809, 0x06000001, 0x0721f000, 0x0349f003, - 0x058102aa, 0x0245f01f, 0x06000002, 0x018602db, - 0x07601400, 0x050f80ff, 0x012fa809, 0x06480001, - 0x058102db, 0x06602440, 0x050f80ff, 0x012fa809, - 0x020ef001, 0x038682db, 0x019b02db, 0x050020d8, - 0x062da001, 0x06303002, 0x05000430, 0x04600440, - 0x050f80ff, 0x073fa012, 0x06000001, 0x028f82bf, - 0x050040d8, 0x062da001, 0x07601e00, 0x050f80ff, - 0x073fa009, 0x06000001, 0x060ff004, 0x00540402, - 0x048202d9, 0x06005051, 0x06006051, 0x06602240, - 0x050f80ff, 0x063fa01a, 0x06000002, 0x06600a40, - 0x050f80ff, 0x073fa00a, 0x07000003, 0x060ff040, - 0x045a041f, 0x010eb0ff, 0x06930013, 0x02920013, - 0x02800010, 0x04004002, 0x018002c9, 0x04a002fd, - 0x062da001, 0x05308000, 0x07005000, 0x06009040, - 0x04a004dc, 0x050080d8, 0x05a004e1, 0x062da001, - 0x02800013, 0x050fd009, 0x050fd041, 0x013e4000, - 0x06000080, 0x05308000, 0x03013000, 0x04a004dc, - 0x010440d7, 0x0349f044, 0x048102f2, 0x062da001, - 0x008f02f2, 0x03e00000, 0x062da001, 0x02800013, - 0x0249c0e5, 0x06810013, 0x062da001, 0x07f00000, - 0x07f00000, 0x033e5000, 0x070c0000, 0x018f02f6, - 0x03800011, 0x050020d8, 0x04600440, 0x050f80ff, - 0x073fa00a, 0x06000001, 0x07c00000, 0x002fb001, - 0x03800306, 0x012fb000, 0x03075087, 0x068d0307, - 0x03386000, 0x03020000, 0x04482075, 0x06810352, - 0x0648a0e6, 0x07810347, 0x0642007f, 0x06810345, - 0x0340007e, 0x060ff038, 0x0154047e, 0x02d00334, - 0x0560027d, 0x050f80ff, 0x032fa009, 0x030ef000, - 0x02860504, 0x0107d000, 0x05600800, 0x050f80ff, - 0x032fa009, 0x03681e00, 0x04500420, 0x050f80ff, - 0x073fa009, 0x0700003f, 0x03800311, 0x070ff07d, - 0x0450047c, 0x050f80ff, 0x002fa819, 0x078d0327, - 0x02080001, 0x00081002, 0x0448807a, 0x0781032e, - 0x0379ff03, 0x070000ff, 0x01082003, 0x068d032f, - 0x02386004, 0x03010000, 0x072e6c00, 0x02800352, - 0x0380033a, 0x0380033c, 0x0280033e, 0x02800340, - 0x03800342, 0x03800344, 0x0727c005, 0x02800323, - 0x0627c008, 0x02800323, 0x0627c00b, 0x02800323, - 0x0627c00e, 0x02800323, 0x0727c011, 0x02800323, - 0x03800314, 0x052e6800, 0x02800352, 0x044880e6, - 0x06810531, 0x052e6200, 0x070ff088, 0x0179feff, - 0x070fffff, 0x04818501, 0x060ff083, 0x0086836d, - 0x033e6000, 0x07000003, 0x068d0352, 0x07286000, - 0x07f00000, 0x078d0355, 0x038c0306, 0x0648c0e6, - 0x05818372, 0x0448e0e6, 0x0781036a, 0x004920e6, - 0x07810365, 0x06a0056d, 0x05001088, 0x00700101, - 0x03100000, 0x00088001, 0x033e6000, 0x07000088, - 0x0280055e, 0x02386001, 0x07030000, 0x033e6000, - 0x06000008, 0x028003f1, 0x02799075, 0x0500040f, - 0x06810010, 0x06601479, 0x050080ff, 0x06309052, - 0x0600003e, 0x02800376, 0x06602279, 0x050080ff, - 0x05309812, 0x07000041, 0x0648007a, 0x0781037e, - 0x04488075, 0x0581837e, 0x040f8008, 0x070fa009, - 0x0049107a, 0x01a183f3, 0x00798075, 0x06000507, - 0x0481851c, 0x0448b075, 0x06810385, 0x02493075, - 0x07810509, 0x0249c0e6, 0x048183e0, 0x0648c0e6, - 0x0581839a, 0x068d0389, 0x02386001, 0x07030000, - 0x0049107a, 0x07810390, 0x020ef083, 0x0386039a, - 0x06483075, 0x068103ef, 0x0678007a, 0x07000035, - 0x03a184cf, 0x05308000, 0x07060000, 0x06009079, - 0x04a004dc, 0x028003ef, 0x0448807a, 0x0681039e, - 0x06483075, 0x058104f9, 0x0448d07a, 0x068103a2, - 0x06483075, 0x058104f9, 0x068d03a2, 0x02386001, - 0x07030000, 0x0444e07a, 0x0648307a, 0x048183c7, - 0x0448707a, 0x068103ea, 0x0648f07a, 0x078103b2, - 0x05a004cf, 0x04008079, 0x05a004ee, 0x008683c2, - 0x05a004d8, 0x028003ef, 0x0560107b, 0x050f80ff, - 0x032fa009, 0x0349c000, 0x058183c0, 0x04600e79, - 0x050f80ff, 0x073fa00a, 0x0600003d, 0x06600a79, - 0x050f80ff, 0x053fa80a, 0x06000010, 0x028003ef, - 0x0046e07a, 0x028003ea, 0x06009008, 0x05308000, - 0x05004000, 0x04a004dc, 0x028003ef, 0x0560167b, - 0x050f80ff, 0x032fa011, 0x070ff000, 0x04500401, - 0x030460ff, 0x060ff025, 0x00540446, 0x078203d1, - 0x030460ff, 0x04092046, 0x05a00218, 0x06600679, - 0x050f80ff, 0x00201007, 0x012fa80a, 0x0046047a, - 0x034630ff, 0x050020ff, 0x06003051, 0x04600e79, - 0x050f80ff, 0x073fa012, 0x06000001, 0x028003ef, - 0x033e6a00, 0x0202000e, 0x02079051, 0x07000088, - 0x078d03e4, 0x0744c000, 0x01088000, 0x03386006, - 0x03010000, 0x02800010, 0x05a004cf, 0x05308000, - 0x03020000, 0x06009079, 0x04a004dc, 0x033e6a00, - 0x0302000a, 0x02079051, 0x02800010, 0x04603e79, - 0x050f80ff, 0x032fa009, 0x070ff000, 0x0186040c, - 0x057dfeff, 0x07ffffff, 0x0581040c, 0x050f8000, - 0x012fa811, 0x0079fe02, 0x070000ff, 0x077d66ff, - 0x060000dc, 0x0781840c, 0x060ff001, 0x0286840d, - 0x064b0002, 0x06420002, 0x060ff002, 0x05500400, - 0x050f80ff, 0x05004084, 0x073fa00a, 0x06000002, - 0x07c00000, 0x04600201, 0x050f80ff, 0x073fa009, - 0x06000001, 0x0079fe02, 0x070000ff, 0x077d72ff, - 0x070000dd, 0x0781840c, 0x064b0002, 0x06420002, - 0x06000001, 0x01800406, 0x0605004c, 0x0180041e, - 0x0493041a, 0x04a004d5, 0x054bc450, 0x05810421, - 0x01d00422, 0x01800421, 0x00800432, 0x00800434, - 0x00800432, 0x008004a7, 0x0180043f, 0x00800434, - 0x01800471, 0x00800432, 0x00800432, 0x008004ab, - 0x00800432, 0x018004af, 0x008004c4, 0x01800488, - 0x00800432, 0x00800432, 0x00209432, 0x018004e4, - 0x0379ff50, 0x070fffff, 0x060ff079, 0x055c0450, - 0x048104a4, 0x002fb008, 0x060ff079, 0x055c0450, - 0x058104a3, 0x04a004c7, 0x0180049c, 0x0179fe50, - 0x070fffff, 0x070050ff, 0x060ff079, 0x055c0405, - 0x04810449, 0x002fb008, 0x060ff079, 0x055c0405, - 0x078184a0, 0x070ff087, 0x017980ff, 0x06000507, - 0x06818451, 0x02203040, 0x05002087, 0x0049d002, - 0x0481046b, 0x04930458, 0x01257000, 0x073c3fff, - 0x0700000f, 0x052e4003, 0x072e5030, 0x0304c050, - 0x02400057, 0x06740057, 0x06000002, 0x06820016, - 0x04002083, 0x07003084, 0x04004085, 0x06602279, - 0x050f80ff, 0x063fa01a, 0x06000001, 0x05a004cf, - 0x06a00576, 0x033e6a00, 0x0302000a, 0x062e5020, - 0x003e4002, 0x07000a00, 0x028003f1, 0x07420003, - 0x0781844e, 0x00798002, 0x06000507, 0x06818451, - 0x0180045c, 0x05930478, 0x01257000, 0x073c3fff, - 0x0700000f, 0x052e4003, 0x072e5030, 0x0304c050, - 0x067800e6, 0x07000041, 0x0581047d, 0x06a0057f, - 0x04818016, 0x002fb008, 0x067800e6, 0x07000041, - 0x04810483, 0x06a0057f, 0x04818016, 0x062e5020, - 0x003e4002, 0x07000a00, 0x03e00000, 0x02800010, - 0x0379ff50, 0x070fffff, 0x060ff079, 0x055c0450, - 0x0781848e, 0x0245507a, 0x002fb008, 0x060ff079, - 0x055c0450, 0x07818493, 0x0245507a, 0x002fb008, - 0x05600e50, 0x050f80ff, 0x012fa809, 0x02455001, - 0x05600e50, 0x050f80ff, 0x012fa80a, 0x0080049d, - 0x002fb008, 0x003e4002, 0x07000a00, 0x02800016, - 0x079384a3, 0x062e5020, 0x042e4002, 0x002fb008, - 0x013e4000, 0x05000e00, 0x02800016, 0x0179fe50, - 0x070fffff, 0x010210ff, 0x02800016, 0x0179fe50, - 0x070fffff, 0x050340ff, 0x0080049d, 0x0179fe50, - 0x070fffff, 0x0102e0ff, 0x0760282e, 0x050f80ff, - 0x05222000, 0x07223000, 0x05224000, 0x07225000, - 0x07226000, 0x05227000, 0x05228000, 0x07229000, - 0x0722a000, 0x0522b000, 0x063fa051, 0x07000011, - 0x0202c026, 0x0522d000, 0x052e400c, 0x02800016, - 0x030430d4, 0x062e5008, 0x00800176, 0x05600e50, - 0x050f80ff, 0x032fa009, 0x03460000, 0x018004d2, - 0x0246007a, 0x0045207a, 0x008004d0, 0x0246007a, - 0x0600007a, 0x04600e79, 0x050f80ff, 0x032fa00a, - 0x07c00000, 0x029284d5, 0x070500e1, 0x07c00000, - 0x0245f008, 0x048404d9, 0x020e0008, 0x07c00000, - 0x070ff009, 0x065a0008, 0x058404de, 0x020e0008, - 0x07c00000, 0x058404e1, 0x020e0008, 0x07c00000, - 0x05308000, 0x0500d000, 0x04a004dc, 0x04a004e9, - 0x02800010, 0x052e4300, 0x072e500c, 0x073c3fff, - 0x0700000f, 0x07c00000, 0x06602208, 0x050f80ff, - 0x032fa011, 0x076a0000, 0x068184f7, 0x066a0001, - 0x048104f7, 0x04002051, 0x07c00000, 0x00202001, - 0x07c00000, 0x0648307a, 0x01a18606, 0x05a004cc, - 0x05308000, 0x05001000, 0x06009079, 0x04a004dc, - 0x0280055e, 0x0249c0e6, 0x058104f9, 0x0280036d, - 0x0648307a, 0x07818196, 0x05a004cf, 0x02209504, - 0x018004e4, 0x02490075, 0x06810519, 0x04002089, - 0x04780102, 0x07f00000, 0x05001088, 0x06a0056d, - 0x04740101, 0x03100000, 0x060ff002, 0x045c0401, - 0x0481851a, 0x00088001, 0x033e6000, 0x070000c0, - 0x0380055a, 0x07f00000, 0x0220951a, 0x018004e4, - 0x040fd075, 0x040fd07a, 0x040fd079, 0x0648307a, - 0x06810525, 0x06780075, 0x06000007, 0x0481852c, - 0x07a00606, 0x06486075, 0x06818194, 0x02490075, - 0x0781819a, 0x04487075, 0x04818534, 0x0280053b, - 0x05308000, 0x03010000, 0x06009079, 0x04a004dc, - 0x02800010, 0x0448e0e6, 0x04818352, 0x00800192, - 0x05308000, 0x0500e000, 0x06009079, 0x04a004dc, - 0x04008089, 0x05a004e1, 0x0380055a, 0x05a004cc, - 0x05308000, 0x0700f000, 0x06009079, 0x07000088, - 0x06a00543, 0x04a004dc, 0x02800010, 0x03386000, - 0x07030000, 0x07f00000, 0x068d0546, 0x033e6a00, - 0x0202000e, 0x02079051, 0x0448b075, 0x06810551, - 0x02493075, 0x06810551, 0x05301005, 0x03010000, - 0x03800553, 0x05301006, 0x03010000, 0x05002087, - 0x06485002, 0x05818553, 0x0744c000, 0x01088000, - 0x02086001, 0x07c00000, 0x05001088, 0x06a0056d, - 0x0644c001, 0x00088001, 0x033e6a00, 0x0202000e, - 0x004920e6, 0x05818563, 0x02079051, 0x078d0563, - 0x060ff089, 0x034990ff, 0x0781056a, 0x03386005, - 0x03010000, 0x02800010, 0x03386006, 0x03010000, - 0x02800010, 0x068d056d, 0x03386000, 0x07030000, - 0x07f00000, 0x078d0571, 0x070ff087, 0x074850ff, - 0x05818572, 0x07c00000, 0x068d0576, 0x02386001, - 0x07030000, 0x07f00000, 0x068d057a, 0x070ff087, - 0x074850ff, 0x0581857b, 0x07c00000, 0x05002087, - 0x0049d002, 0x0581858e, 0x002fb008, 0x067800e6, - 0x07000041, 0x002fb008, 0x0581858e, 0x06a005a4, - 0x0448e002, 0x06810591, 0x0648a002, 0x0481859b, - 0x06486002, 0x07810595, 0x02400057, 0x056a02ff, - 0x07c00000, 0x06a005a4, 0x06788102, 0x06000004, - 0x0581858e, 0x04002089, 0x070ff0d4, 0x045c0402, - 0x077800ff, 0x07f00000, 0x0581858e, 0x00202010, - 0x038c058e, 0x07f00000, 0x06420002, 0x0581859c, - 0x06a00576, 0x033e6a00, 0x0302000a, 0x07c00000, - 0x07f00000, 0x060ff0a2, 0x050020ff, 0x060ff0a2, - 0x045c0402, 0x058185a5, 0x07c00000, 0x05a00218, - 0x03495047, 0x068105b0, 0x0320901d, 0x02800602, - 0x0220901f, 0x02800602, 0x014980e4, 0x04818010, - 0x013e4000, 0x07003000, 0x05600e35, 0x050f80ff, - 0x07a006fa, 0x01208003, 0x05a004e1, 0x038005ca, - 0x03209009, 0x02800602, 0x03209011, 0x02800602, - 0x02209007, 0x02800602, 0x03209003, 0x02800602, - 0x00498043, 0x048185bc, 0x00497043, 0x058185c0, - 0x02209001, 0x02800602, 0x0220900d, 0x02800602, - 0x0320900f, 0x02800602, 0x03493000, 0x068105d3, - 0x027c0045, 0x070a0000, 0x068105dc, 0x0220900b, - 0x02800602, 0x02209013, 0x05308000, 0x01012000, - 0x04a004dc, 0x00800183, 0x03209005, 0x02800602, - 0x072e500c, 0x00208002, 0x05a004e1, 0x02800010, - 0x02209015, 0x02800602, 0x072d6000, 0x05308000, - 0x05007000, 0x07f00000, 0x070090d1, 0x0379ff09, - 0x0700ffff, 0x04a004dc, 0x03209017, 0x02800602, - 0x033e5000, 0x06000080, 0x02209019, 0x02800602, - 0x072d6000, 0x033e5000, 0x06000080, 0x07f00000, - 0x060ff0d0, 0x0179feff, 0x0700ffff, 0x057dfeff, - 0x0700ffff, 0x04818010, 0x02400058, 0x00642058, - 0x06820010, 0x033e5000, 0x06000080, 0x04058051, - 0x0320901b, 0x02800602, 0x05308000, 0x01012000, - 0x04a004dc, 0x00800176, 0x05a00218, 0x05308000, - 0x05008000, 0x06009079, 0x04a004dc, 0x07c00000, - 0x034900e4, 0x04818616, 0x013e4000, 0x070000c0, - 0x07f00000, 0x034900e4, 0x05818614, 0x07c00000, - 0x013e4000, 0x06000080, 0x07f00000, 0x07f00000, - 0x07f00000, 0x034900e4, 0x0681060e, 0x02800616, - 0x072d6000, 0x00498043, 0x07810630, 0x060ff0d0, - 0x0179feff, 0x0700ffff, 0x057dfeff, 0x0700ffff, - 0x048185e0, 0x050f8030, 0x032fa009, 0x0379ff00, - 0x0700ffff, 0x070ff0d1, 0x0179feff, 0x0700ffff, - 0x055c0400, 0x068105e0, 0x04004051, 0x03800678, - 0x06a006da, 0x062d6001, 0x020ef004, 0x038605e2, - 0x06600004, 0x050f80ff, 0x032fa009, 0x074b0000, - 0x05002000, 0x0769ff00, 0x01640800, 0x078205e2, - 0x01640e00, 0x058285e2, 0x070ff036, 0x045c0404, - 0x0581864b, 0x072d6000, 0x050f8030, 0x032fa009, - 0x0379ff00, 0x0700ffff, 0x070ff0d1, 0x0179feff, - 0x0700ffff, 0x055c0400, 0x068105e0, 0x04482034, - 0x068105fd, 0x06483034, 0x048185fd, 0x070ff0d4, - 0x077800ff, 0x070000f0, 0x037c00ff, 0x06000010, - 0x07810678, 0x07a006d4, 0x024900e5, 0x0681065b, - 0x033e5000, 0x06000080, 0x02800010, 0x04601c04, - 0x050f80ff, 0x053fa809, 0x06000020, 0x030ef041, - 0x028605ec, 0x062d6002, 0x05602a41, 0x050f80ff, - 0x012fa809, 0x060ff0d0, 0x074b00ff, 0x045c0401, - 0x04818676, 0x062d6001, 0x07602841, 0x050f80ff, - 0x053fa809, 0x06000001, 0x070ff0d1, 0x054b80ff, - 0x074b0003, 0x055c0403, 0x04818676, 0x033e5000, - 0x06000080, 0x0180070c, 0x07600041, 0x0380065c, - 0x07a006d4, 0x024900e5, 0x0781067e, 0x033e5000, - 0x06000080, 0x02800010, 0x07a006c0, 0x030ef041, - 0x038605f0, 0x04058051, 0x072d6000, 0x05601041, - 0x050f80ff, 0x012fa809, 0x0600a0d0, 0x0500b0d1, - 0x062d6001, 0x07f00000, 0x07f00000, 0x0600c0d0, - 0x0500d0d1, 0x062d6002, 0x0279ff0d, 0x07ff0000, - 0x044d800d, 0x060ff0d0, 0x074b00ff, 0x065a000d, - 0x06601201, 0x050f80ff, 0x073fa022, 0x07000005, - 0x0079fe0d, 0x070000ff, 0x050020ff, 0x05602a41, - 0x050f80ff, 0x073fa00a, 0x06000001, 0x020ef004, - 0x038606bd, 0x04601c04, 0x050f80ff, 0x053fa809, - 0x06000001, 0x050f80ff, 0x053fa80a, 0x06000020, - 0x07602841, 0x050f80ff, 0x073fa009, 0x06000001, - 0x0279ff02, 0x070000ff, 0x0678000d, 0x0700ff00, - 0x065a0002, 0x07602841, 0x050f80ff, 0x073fa00a, - 0x06000001, 0x07600041, 0x050f80ff, 0x053fa80a, - 0x06000001, 0x07601241, 0x050f80ff, 0x073fa00a, - 0x06000002, 0x033e5000, 0x06000080, 0x0180070c, - 0x040f8032, 0x073fa011, 0x06000001, 0x060ff002, - 0x055c0403, 0x048186c8, 0x00041051, 0x07c00000, - 0x04600402, 0x04500432, 0x050f80ff, 0x053fa809, - 0x06000020, 0x00400402, 0x01680eff, 0x070030ff, - 0x040f8032, 0x053fa80a, 0x06000001, 0x07c00000, - 0x024900e5, 0x078106d7, 0x07c00000, 0x033e5000, - 0x070000c0, 0x07c00000, 0x05004036, 0x060000d0, - 0x0179fe00, 0x0700ffff, 0x057dfeff, 0x0700ffff, - 0x078106f9, 0x070000d1, 0x0379ff00, 0x0700ffff, - 0x06005051, 0x060ff031, 0x05500405, 0x050f80ff, - 0x073fa009, 0x06000002, 0x020ef004, 0x038606f3, - 0x04600404, 0x050f80ff, 0x012fa809, 0x0079fe01, - 0x0700ffff, 0x055c0400, 0x078106f9, 0x01400405, - 0x070050ff, 0x057de0ff, 0x06000007, 0x048186e5, - 0x04004051, 0x07c00000, 0x072d6000, 0x07f00000, - 0x07f00000, 0x000110d0, 0x010120d1, 0x062d6001, - 0x07f00000, 0x07f00000, 0x020130d0, 0x010140d1, - 0x062d6002, 0x010170d4, 0x07f00000, 0x020150d0, - 0x030160d1, 0x053fa83a, 0x06000008, 0x07c00000, - 0x07600c41, 0x050f80ff, 0x073fa009, 0x06000001, - 0x04780102, 0x07ffff00, 0x046a0702, 0x050f80ff, - 0x073fa00a, 0x06000001, 0x05600e41, 0x050f80ff, - 0x032fa069, 0x03800053, 0xdb4ee9e2, 0x02800004, - 0x00000000, 0x00008000, 0x00000542, 0x040f801f, - 0x012fa8c9, 0x040f801f, 0x073fa081, 0x06000010, - 0x03200005, 0x07420000, 0x050fb000, 0x040f801f, - 0x073fa011, 0x06000038, 0x040f801f, 0x053fa859, - 0x0700003a, 0x050fe000, 0x0581800a, 0x0784003c, - 0x04958019, 0x030e0011, 0x072e4200, 0x03800014, - 0x0291001f, 0x050010c0, 0x04482001, 0x058180fa, - 0x06483001, 0x0681815d, 0x02920029, 0x068b0029, - 0x008a0162, 0x050010c0, 0x06780001, 0x050007c0, - 0x06818240, 0x06780001, 0x0500f800, 0x06818280, - 0x03910030, 0x040fe029, 0x03860030, 0x076c001d, - 0x058102b1, 0x076c0a1d, 0x048102da, 0x029200ab, - 0x040fe02f, 0x0386003c, 0x06000013, 0x050fb000, - 0x066c0073, 0x068103ec, 0x014920e4, 0x0581803c, - 0x03400000, 0x076c0a00, 0x04818034, 0x0696003e, - 0x03b900ca, 0x05908014, 0x010170e1, 0x07780017, - 0x03e00000, 0x06810091, 0x050010ff, 0x0179fe17, - 0x031fffff, 0x070000ff, 0x05600800, 0x050f80ff, - 0x073fa009, 0x06000001, 0x06780002, 0x02800040, - 0x037c00ff, 0x03800000, 0x0681005d, 0x0249f002, - 0x078100aa, 0x0448e002, 0x0681005d, 0x07600c00, - 0x050f80ff, 0x073fa009, 0x06000001, 0x06780002, - 0x07ffff00, 0x037c00ff, 0x05000200, 0x058180aa, - 0x064bd401, 0x03d0005f, 0x028000a8, 0x02800067, - 0x03800071, 0x0380007b, 0x02800085, 0x0280008f, - 0x028000a8, 0x028000a8, 0x050fe027, 0x0086806b, - 0x01028000, 0x0280006e, 0x07600027, 0x050f80ff, - 0x032fa00a, 0x01027000, 0x02400029, 0x038000aa, - 0x040fe025, 0x00868075, 0x03026000, 0x03800078, - 0x06600025, 0x050f80ff, 0x032fa00a, 0x03025000, - 0x02400029, 0x038000aa, 0x050fe021, 0x0086807f, - 0x01022000, 0x03800082, 0x07600021, 0x050f80ff, - 0x032fa00a, 0x01021000, 0x02400029, 0x038000aa, - 0x040fe023, 0x00868089, 0x01024000, 0x0280008c, - 0x06600023, 0x050f80ff, 0x032fa00a, 0x03023000, - 0x02400029, 0x038000aa, 0x06a000da, 0x038000aa, - 0x01640817, 0x048280a8, 0x070ff017, 0x03d00095, - 0x0280009d, 0x0380009f, 0x028000a2, 0x038000a5, - 0x028000a8, 0x028000a8, 0x028000a8, 0x028000a8, - 0x03e00000, 0x03800014, 0x0590809f, 0x030160e1, - 0x038000aa, 0x049080a2, 0x030150e1, 0x038000aa, - 0x059080a5, 0x010140e1, 0x038000aa, 0x060fc013, - 0x07a0053a, 0x03800014, 0x014940e4, 0x00a180ae, - 0x0380003c, 0x02681e0d, 0x050fb0ff, 0x04600876, - 0x050f80ff, 0x053fa809, 0x06000001, 0x05488003, - 0x058180bd, 0x0400800d, 0x0120d000, 0x013e4000, - 0x05000200, 0x06009076, 0x04002075, 0x06a00526, - 0x07c00000, 0x072e4800, 0x07000012, 0x028000cd, - 0x0747f000, 0x05600800, 0x050f80ff, 0x012fa809, - 0x0249f001, 0x068100cd, 0x01012000, 0x052e4c00, - 0x07c00000, 0x070000eb, 0x0349f000, 0x048180c1, - 0x05600800, 0x050f80ff, 0x012fa809, 0x0448e001, - 0x068100d3, 0x07c00000, 0x0079c101, 0x07ffffff, - 0x027a4b01, 0x03800000, 0x05600800, 0x050f80ff, - 0x012fa80a, 0x07600c00, 0x050f80ff, 0x012fa821, - 0x06780001, 0x07ffff00, 0x037c00ff, 0x05000700, - 0x068100ef, 0x06601804, 0x070030ff, 0x050f80ff, - 0x012fa809, 0x05002000, 0x050f8003, 0x073fa00a, - 0x06000001, 0x040fe001, 0x038600f0, 0x04600201, - 0x050f80ff, 0x032fa00a, 0x07c00000, 0x050fe02e, - 0x018680f5, 0x0102e000, 0x0302f000, 0x038000f9, - 0x0760002e, 0x050f80ff, 0x032fa00a, 0x0102e000, - 0x07c00000, 0x022c0004, 0x056c041d, 0x0481010e, - 0x056c021d, 0x04810125, 0x056c081d, 0x04810137, - 0x076c061d, 0x04810151, 0x0521d000, 0x0202c013, - 0x0202a013, 0x02020013, 0x0460021a, 0x050f80ff, - 0x053fa80a, 0x07000009, 0x03b600be, 0x0484801f, - 0x0380003c, 0x040fe02a, 0x00860104, 0x06000013, - 0x04001013, 0x0560102b, 0x050f80ff, 0x032fa012, - 0x06420029, 0x0660002a, 0x050f80ff, 0x053fa809, - 0x06000001, 0x050fe003, 0x01860122, 0x01028003, - 0x0660002a, 0x050f80ff, 0x053fa80a, 0x07000009, - 0x00800152, 0x00028013, 0x00027013, 0x00800152, - 0x040fe02a, 0x01860103, 0x06420029, 0x0660002a, - 0x050f80ff, 0x053fa809, 0x06000001, 0x050fe003, - 0x00860134, 0x03026003, 0x0660002a, 0x050f80ff, - 0x053fa80a, 0x07000009, 0x00800152, 0x02026013, - 0x02025013, 0x00800152, 0x040fe02a, 0x01860103, - 0x06420029, 0x0660002a, 0x050f80ff, 0x053fa809, - 0x06000001, 0x050fe003, 0x00860146, 0x01022003, - 0x0660002a, 0x050f80ff, 0x053fa80a, 0x07000009, - 0x01800148, 0x00022013, 0x00021013, 0x0647f020, - 0x007a0120, 0x04000101, 0x04a002a2, 0x0400802a, - 0x06a0051f, 0x03948103, 0x0521d005, 0x00800104, - 0x0180010c, 0x0647f020, 0x06486020, 0x06818157, - 0x04a002a2, 0x01800103, 0x007a0120, 0x04000101, - 0x04a002a2, 0x0400802a, 0x06a0051f, 0x01800103, - 0x040fd02a, 0x052e4003, 0x00208010, 0x06a0051f, - 0x0180010c, 0x00018098, 0x07480018, 0x06818173, - 0x05481018, 0x07818171, 0x05482018, 0x0781816f, - 0x07483018, 0x0681816d, 0x002fb004, 0x01800174, - 0x012fb003, 0x01800174, 0x002fb002, 0x01800174, - 0x002fb001, 0x01800174, 0x012fb000, 0x0179fe78, - 0x070000ff, 0x030190ff, 0x00017086, 0x058b0178, - 0x03385000, 0x03020000, 0x07780017, 0x00430407, - 0x07818200, 0x046c0419, 0x058101b4, 0x046c0219, - 0x05810184, 0x07219000, 0x00800198, 0x07219000, - 0x07483017, 0x0481019e, 0x05482017, 0x058101a5, - 0x0448b075, 0x06818198, 0x06601476, 0x050f80ff, - 0x073fa022, 0x0600003e, 0x06000080, 0x05001081, - 0x05002082, 0x06003083, 0x05004084, 0x04601c76, - 0x050f80ff, 0x022fa02a, 0x07219000, 0x07780078, - 0x07ffff00, 0x045a0419, 0x010780ff, 0x0484801f, - 0x0380003c, 0x040fe07f, 0x008601ad, 0x04a001cd, - 0x00920198, 0x040fe07f, 0x06a681cd, 0x00800198, - 0x0560107b, 0x050f80ff, 0x032fa009, 0x0744f000, - 0x0560107b, 0x050f80ff, 0x032fa00a, 0x0180018b, - 0x052e400c, 0x040080fb, 0x046aa108, 0x06009076, - 0x04002075, 0x06a00526, 0x00800198, 0x06219001, - 0x05482017, 0x048101c1, 0x058b01b7, 0x060ff086, - 0x0349f0ff, 0x07818177, 0x07483017, 0x058101be, - 0x050fd0ff, 0x040fe07f, 0x06a681cd, 0x00800198, - 0x05004084, 0x05a00222, 0x00920198, 0x070ff07d, - 0x0450047c, 0x056004ff, 0x050f80ff, 0x032fa009, - 0x070ff000, 0x00540479, 0x030790ff, 0x018001a5, - 0x060ff079, 0x0054047a, 0x058201f9, 0x058101f9, - 0x070ff07d, 0x0450047c, 0x050f80ff, 0x002fa819, - 0x048b01d5, 0x02080001, 0x00081002, 0x01082003, - 0x048b01d9, 0x03385000, 0x03010000, 0x02400019, - 0x070ff003, 0x04500479, 0x030790ff, 0x0340007e, - 0x0642007f, 0x058101f9, 0x070ff07e, 0x050f80ff, - 0x032fa009, 0x050fe000, 0x028681f8, 0x070ff07d, - 0x056002ff, 0x050f80ff, 0x032fa009, 0x0107d000, - 0x018601fa, 0x0560087d, 0x050f80ff, 0x032fa009, - 0x03681e00, 0x0550041b, 0x050f80ff, 0x032fa009, - 0x0107e000, 0x070ff07e, 0x018001e4, 0x0307c000, - 0x07c00000, 0x052e400c, 0x040080fb, 0x046aa108, - 0x06009076, 0x04002075, 0x02800526, 0x040fd076, - 0x050fd017, 0x060ff086, 0x077800ff, 0x07000060, - 0x037c00ff, 0x07000060, 0x06818202, 0x07780078, - 0x07ffff00, 0x045a0419, 0x010780ff, 0x06601476, - 0x050f80ff, 0x073fa022, 0x0600003e, 0x052e400c, - 0x04600876, 0x050f80ff, 0x053fa809, 0x06000001, - 0x05488003, 0x0481021c, 0x0400d0fb, 0x066a810d, - 0x013e4000, 0x07000300, 0x02800029, 0x040080fb, - 0x066a8108, 0x06009076, 0x04002075, 0x06a00526, - 0x02800029, 0x0240007f, 0x0742007e, 0x050f807e, - 0x032fa009, 0x050fe000, 0x0386823c, 0x070ff07d, - 0x055c047b, 0x04810231, 0x0760007d, 0x050f80ff, - 0x032fa009, 0x050fe000, 0x02868231, 0x070ff07b, - 0x0107d0ff, 0x0560087d, 0x050f80ff, 0x032fa009, - 0x03681e00, 0x0450041c, 0x0107e0ff, 0x050f80ff, - 0x032fa009, 0x050fe000, 0x0086023e, 0x0307c000, - 0x07c00000, 0x040fd076, 0x0380053a, 0x010180c0, - 0x0548e018, 0x07818259, 0x0748f018, 0x07818255, - 0x03490018, 0x06818251, 0x01491018, 0x0781824d, - 0x073c0000, 0x06000040, 0x02200004, 0x0180025c, - 0x073c0000, 0x06000020, 0x03200003, 0x0180025c, - 0x073c0000, 0x06000010, 0x02200002, 0x0180025c, - 0x073c0000, 0x06000008, 0x02200001, 0x0180025c, - 0x073c0000, 0x06000004, 0x06000013, 0x050fb000, - 0x040fe076, 0x00860275, 0x046c0273, 0x04810285, - 0x066c0073, 0x05810266, 0x040fd076, 0x07a0053a, - 0x03800014, 0x040fd076, 0x01800269, 0x00452075, - 0x00077013, 0x0647f075, 0x06486075, 0x0781826f, - 0x04a002a8, 0x00800275, 0x007a0175, 0x04000101, - 0x04a002a8, 0x04008076, 0x0245f008, 0x06a0051f, - 0x07273000, 0x05600272, 0x050f80ff, 0x053fa80a, - 0x07000009, 0x0379ff78, 0x070000ff, 0x02076013, - 0x02075013, 0x0484801f, 0x0380003c, 0x070fc0ff, - 0x052e400c, 0x00208020, 0x06a0051f, 0x0180027e, - 0x04600276, 0x050010ff, 0x040f8001, 0x032fa009, - 0x040f8001, 0x053fa80a, 0x07000009, 0x070ff000, - 0x02868297, 0x06601276, 0x050f80ff, 0x073fa009, - 0x0700000c, 0x07601818, 0x050f80ff, 0x053fa80a, - 0x07000009, 0x00800298, 0x07a000f0, 0x0448b075, - 0x04810268, 0x06000013, 0x04001013, 0x0560107b, - 0x050f80ff, 0x032fa012, 0x0046b075, 0x03b600be, - 0x01800269, 0x06000020, 0x04001016, 0x0460082a, - 0x050f80ff, 0x032fa012, 0x07c00000, 0x06000075, - 0x040010a2, 0x044b0801, 0x060ff016, 0x065a0001, - 0x04600876, 0x050f80ff, 0x032fa012, 0x07c00000, - 0x050fe022, 0x008602bc, 0x0421d004, 0x0302a022, - 0x04a002e9, 0x04488020, 0x048102ce, 0x040fd02a, - 0x0521d000, 0x0202a013, 0x02020013, 0x040fe026, - 0x018602d4, 0x0421d001, 0x0202a026, 0x04a002e9, - 0x0202c013, 0x00683e20, 0x070060ff, 0x056c0206, - 0x0681031c, 0x056c0406, 0x06810332, 0x076c0606, - 0x078103a3, 0x04488020, 0x068182d0, 0x056c1606, - 0x078103b1, 0x06a00516, 0x018002e2, 0x040fd02a, - 0x0521d000, 0x0202a013, 0x02020013, 0x050fe028, - 0x018602e2, 0x0302a028, 0x0421d002, 0x04a002e9, - 0x018002f0, 0x050fe022, 0x018602e2, 0x0421d004, - 0x0302a022, 0x04a002e9, 0x04488020, 0x078182e4, - 0x06a00516, 0x05848030, 0x0380003c, 0x040fd02a, - 0x0521d000, 0x0202a013, 0x02020013, 0x018002e2, - 0x0460082a, 0x050f80ff, 0x022fa031, 0x03020000, - 0x0002b004, 0x01018005, 0x07c00000, 0x0400702a, - 0x07a003e4, 0x007a0101, 0x07060000, 0x07303000, - 0x07008290, 0x07600018, 0x050f80ff, 0x053fa809, - 0x07000003, 0x0448e007, 0x068182fe, 0x06006013, - 0x03800305, 0x02400010, 0x048102fe, 0x06006010, - 0x0460322a, 0x050f80ff, 0x073fa00a, 0x07000003, - 0x050f801e, 0x032fa03a, 0x063aa020, 0x06000002, - 0x013e4000, 0x07000030, 0x0298030b, 0x070ff0f6, - 0x036830ff, 0x0581830c, 0x070f001e, 0x0560102b, - 0x050f10ff, 0x063f3c08, 0x0600000d, 0x013e4000, - 0x06000020, 0x040f801a, 0x0320000a, 0x022017d0, - 0x032fa012, 0x0202c013, 0x018002e2, 0x04007013, - 0x07a003e4, 0x007a0101, 0x07050000, 0x07303000, - 0x07008890, 0x074d0005, 0x06006013, 0x050f801e, - 0x032fa03a, 0x05601a2b, 0x050f80ff, 0x022fa019, - 0x04001002, 0x04002013, 0x040f801f, 0x022fa01a, - 0x073aa00c, 0x06000002, 0x07300c03, 0x0600000d, - 0x038003d1, 0x04007013, 0x07a003e4, 0x007a0101, - 0x03070000, 0x0660282a, 0x050f80ff, 0x073fa009, - 0x06000004, 0x02499008, 0x0781033f, 0x07303000, - 0x07008890, 0x03800341, 0x07303000, 0x04008980, - 0x05007003, 0x074d0005, 0x06006013, 0x050f801e, - 0x032fa03a, 0x0760142b, 0x050f80ff, 0x032fa021, - 0x064b0002, 0x02499008, 0x0781034d, 0x0644c002, - 0x054b0400, 0x050040ff, 0x06698104, 0x04818362, - 0x06000013, 0x04001013, 0x04780102, 0x06000010, - 0x06003013, 0x04004013, 0x06005013, 0x06006013, - 0x04007013, 0x00644015, 0x0682035e, 0x04448002, - 0x02205008, 0x040f801f, 0x032fa042, 0x04008015, - 0x0280039b, 0x046c8004, 0x04818370, 0x01208018, - 0x06780002, 0x07000003, 0x04818373, 0x06003001, - 0x06000013, 0x04001013, 0x04004013, 0x06005013, - 0x040f801f, 0x022fa032, 0x0280039b, 0x040fd02a, - 0x07a0053a, 0x03800014, 0x0379ff03, 0x070000ff, - 0x04488002, 0x0681037a, 0x070ff003, 0x04500408, - 0x050080ff, 0x0379ff00, 0x070000ff, 0x06489002, - 0x07810381, 0x070ff000, 0x04500408, 0x050080ff, - 0x07005003, 0x05004000, 0x06003001, 0x06000013, - 0x04001013, 0x040f801f, 0x022fa032, 0x05601c2b, - 0x050f80ff, 0x022fa031, 0x06600c1f, 0x050f80ff, - 0x022fa032, 0x02680608, 0x0681039b, 0x016408ff, - 0x057dfeff, 0x07ffffff, 0x034000ff, 0x045a0407, - 0x070000ff, 0x0760061e, 0x050f80ff, 0x032fa00a, - 0x06600908, 0x0669f908, 0x027a0008, 0x06000020, - 0x070aa0ff, 0x014a20ff, 0x037a00ff, 0x060000dc, - 0x070000ff, 0x038003d1, 0x04007013, 0x07a003e4, - 0x007a0101, 0x07030000, 0x07303000, 0x07008190, - 0x06006013, 0x050f801e, 0x032fa03a, 0x073aa000, - 0x06000002, 0x07300c00, 0x07000005, 0x038003d1, - 0x04007013, 0x07a003e4, 0x007a0101, 0x07810000, - 0x07303000, 0x07000090, 0x06006013, 0x06600c2a, - 0x050f80ff, 0x053fa809, 0x07000003, 0x04780107, - 0x07ffff00, 0x007c0107, 0x07000500, 0x048183c4, - 0x07303000, 0x05000890, 0x074d0005, 0x0660282a, - 0x050f80ff, 0x053fa809, 0x07000003, 0x0049d007, - 0x068103cb, 0x02206001, 0x050f801e, 0x032fa03a, - 0x073aa000, 0x06000002, 0x07300c00, 0x07000005, - 0x013e4000, 0x07000030, 0x029803d3, 0x070ff0f6, - 0x036830ff, 0x058183d4, 0x070f001e, 0x040f101f, - 0x070f3000, 0x013e4000, 0x06000020, 0x040f801a, - 0x0320000a, 0x022017d0, 0x032fa012, 0x018002e2, - 0x03200000, 0x06006076, 0x028003e6, 0x03200011, - 0x0600602a, 0x04a0046b, 0x05600406, 0x050f80ff, - 0x053fa809, 0x06000002, 0x07c00000, 0x0207602f, - 0x04600876, 0x050f80ff, 0x022fa031, 0x03075000, - 0x0007b004, 0x01018005, 0x06600076, 0x050020ff, - 0x050f80ff, 0x012fa809, 0x0202f001, 0x018683fa, - 0x0002e013, 0x040f8002, 0x053fa80a, 0x07000009, - 0x06273001, 0x0448b075, 0x06818404, 0x04602076, - 0x050f80ff, 0x053fa811, 0x0700003c, 0x0179fe78, - 0x070000ff, 0x030190ff, 0x0386840c, 0x04a00420, - 0x00078019, 0x0092041f, 0x00800464, 0x040fd076, - 0x040fd019, 0x04600276, 0x050020ff, 0x050f80ff, - 0x032fa009, 0x040f8002, 0x053fa80a, 0x07000009, - 0x050fe000, 0x0286841c, 0x07601818, 0x050f80ff, - 0x053fa80a, 0x07000009, 0x0180041d, 0x07a000f0, - 0x07273000, 0x02076013, 0x0380003c, 0x048b0420, - 0x03385000, 0x07030000, 0x05600818, 0x050f80ff, - 0x032fa009, 0x054b0400, 0x0308a0ff, 0x0179fe00, - 0x070000ff, 0x010880ff, 0x0448b075, 0x0581043a, - 0x0760147b, 0x050f80ff, 0x002fa819, 0x064b0001, - 0x02080002, 0x01081003, 0x00082001, 0x02083001, - 0x02079001, 0x0207a001, 0x00084013, 0x0207f013, - 0x0180045c, 0x06485075, 0x04810452, 0x02465075, - 0x06601476, 0x050f80ff, 0x073fa021, 0x0600003e, - 0x070ff07d, 0x0450047c, 0x050f80ff, 0x002fa819, - 0x048b0445, 0x02080001, 0x00081002, 0x01082003, - 0x03079003, 0x0208307a, 0x0340007e, 0x0642007f, - 0x04810457, 0x070ff07e, 0x05a001e4, 0x02928457, - 0x01800463, 0x048b0452, 0x06601476, 0x050f80ff, - 0x073fa041, 0x0600003e, 0x06602476, 0x050f80ff, - 0x073fa009, 0x06000007, 0x0008400e, 0x058b045c, - 0x03385000, 0x03010000, 0x06219001, 0x040fe07f, - 0x01860463, 0x008001cd, 0x07c00000, 0x00683e75, - 0x05810469, 0x0448d075, 0x0481048f, 0x018004bd, - 0x06a0051a, 0x0080041f, 0x02978476, 0x07602418, - 0x050f80ff, 0x012fa809, 0x06780001, 0x070000ff, - 0x075a0000, 0x070ff014, 0x0569feff, 0x054b08ff, - 0x075a0000, 0x05600418, 0x050f80ff, 0x012fa809, - 0x040fe007, 0x0386847d, 0x01204000, 0x0180048b, - 0x00700101, 0x03010000, 0x06780001, 0x07ff0000, - 0x076c00ff, 0x06818485, 0x00700101, 0x03010000, - 0x05600418, 0x050f80ff, 0x012fa80a, 0x06780001, - 0x07ff0000, 0x050040ff, 0x0279ff01, 0x0700ffff, - 0x05002014, 0x07c00000, 0x04007076, 0x0448b075, - 0x058104a9, 0x03200011, 0x06006076, 0x06a003e6, - 0x007a0101, 0x07060000, 0x07303000, 0x07008290, - 0x07600018, 0x050f80ff, 0x053fa809, 0x07000003, - 0x0448e007, 0x068184a1, 0x06006013, 0x018004b8, - 0x02400010, 0x048104a1, 0x06006010, 0x04603276, - 0x050f80ff, 0x073fa00a, 0x07000003, 0x018004b8, - 0x04602a76, 0x050f80ff, 0x032fa009, 0x060ff07a, - 0x05500400, 0x070000ff, 0x04602a76, 0x050f80ff, - 0x032fa00a, 0x07a003e1, 0x007a0101, 0x03010000, - 0x06303008, 0x05008000, 0x0600600e, 0x050f8074, - 0x032fa03a, 0x053079a0, 0x0700000c, 0x008004fd, - 0x00683e75, 0x076c0aff, 0x048104dc, 0x04007013, - 0x03200011, 0x06006076, 0x06a003e6, 0x007a0101, - 0x03070000, 0x06602876, 0x050f80ff, 0x053fa809, - 0x06000001, 0x03499003, 0x058104d1, 0x07303000, - 0x07008890, 0x053079a0, 0x0700000c, 0x008004d5, - 0x07303000, 0x04008980, 0x04307920, 0x0700000c, - 0x074d0005, 0x06006013, 0x050f8074, 0x032fa03a, - 0x04307920, 0x0700000c, 0x008004fd, 0x04602a76, - 0x050f80ff, 0x032fa009, 0x060ff07a, 0x05500400, - 0x070000ff, 0x04602a76, 0x050f80ff, 0x032fa00a, - 0x04007076, 0x07a003e1, 0x007a0101, 0x03010000, - 0x06303008, 0x07008800, 0x074d0005, 0x06600a76, - 0x050f80ff, 0x073fa009, 0x07000003, 0x054b0406, - 0x045a0404, 0x050040ff, 0x0600600e, 0x050f8074, - 0x032fa03a, 0x0648c075, 0x048104fb, 0x06307d20, - 0x0700000c, 0x008004fd, 0x04307920, 0x0700000c, - 0x013e4000, 0x07000030, 0x019804ff, 0x070ff0f6, - 0x074850ff, 0x05818500, 0x050f2074, 0x060a0007, - 0x040070fb, 0x046a7007, 0x050f40ff, 0x013e4000, - 0x06000020, 0x0678007a, 0x07fff000, 0x04818510, - 0x0320000a, 0x022017d0, 0x02800513, 0x0320000a, - 0x06301b58, 0x06000001, 0x050f8072, 0x032fa012, - 0x0080041f, 0x01208060, 0x0600902a, 0x04002020, - 0x02800526, 0x040080fb, 0x066ae108, 0x06009076, - 0x04002075, 0x02800526, 0x03201100, 0x05848524, - 0x06420001, 0x04818520, 0x0280053d, 0x020e0008, - 0x07c00000, 0x050fd009, 0x040fd008, 0x03201100, - 0x0584852d, 0x06420001, 0x04818529, 0x0280053d, - 0x007a0102, 0x04000101, 0x05600809, 0x050f80ff, - 0x073fa00a, 0x06000001, 0x020e0008, 0x06840537, - 0x030e0009, 0x07c00000, 0x01011009, 0x052e4300, - 0x07c00000, 0x052e400f, 0x01208090, 0x0280051f, - 0x070fc0ff, 0x040f8013, 0x032fa009, 0x02800540, - 0x6321d92e, 0xffef19a2 -}; - -#ifdef UNIQUE_FW_NAME -uint32_t fw2400_length02 = 0x0000165e ; -#else -uint32_t risc_code_length02 = 0x0000165e ; -#endif - diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 4c67494e9f7..c4136bf344a 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -1938,26 +1938,6 @@ struct sns_cmd_pkt { } p; }; -struct qla_fw_info { - unsigned short addressing; /* addressing method used to load fw */ -#define FW_INFO_ADDR_NORMAL 0 -#define FW_INFO_ADDR_EXTENDED 1 -#define FW_INFO_ADDR_NOMORE 0xffff - unsigned short *fwcode; /* pointer to FW array */ - unsigned short *fwlen; /* number of words in array */ - unsigned short *fwstart; /* start address for F/W */ - unsigned long *lfwstart; /* start address (long) for F/W */ -}; - -struct qla_board_info { - char *drv_name; - - char isp_name[8]; - struct qla_fw_info *fw_info; - char *fw_fname; - struct scsi_host_template *sht; -}; - struct fw_blob { char *name; uint32_t segs[4]; @@ -2305,13 +2285,16 @@ typedef struct scsi_qla_host { mbx_cmd_t mc; /* Basic firmware related information. */ - struct qla_board_info *brd_info; uint16_t fw_major_version; uint16_t fw_minor_version; uint16_t fw_subminor_version; uint16_t fw_attributes; uint32_t fw_memory_size; uint32_t fw_transfer_size; + uint32_t fw_srisc_address; +#define RISC_START_ADDRESS_2100 0x1000 +#define RISC_START_ADDRESS_2300 0x800 +#define RISC_START_ADDRESS_2400 0x100000 uint16_t fw_options[16]; /* slots: 1,2,3,10,11 */ uint8_t fw_seriallink_options[4]; diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h index d2f5870628d..3af478663be 100644 --- a/drivers/scsi/qla2xxx/qla_fw.h +++ b/drivers/scsi/qla2xxx/qla_fw.h @@ -7,7 +7,6 @@ #ifndef __QLA_FW_H #define __QLA_FW_H -#define RISC_SADDRESS 0x100000 #define MBS_CHECKSUM_ERROR 0x4010 /* diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 02922299871..164d53ccbfd 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -9,9 +9,6 @@ #include -extern void qla2x00_remove_one(struct pci_dev *); -extern int qla2x00_probe_one(struct pci_dev *, struct qla_board_info *); - /* * Global Function Prototypes in qla_init.c source file. */ diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 7b48c655b76..748be95c51a 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -383,9 +383,7 @@ qla2x00_isp_firmware(scsi_qla_host_t *ha) qla_printk(KERN_INFO, ha, "RISC CODE NOT loaded\n"); /* Verify checksum of loaded RISC code. */ - rval = qla2x00_verify_checksum(ha, - IS_QLA24XX(ha) || IS_QLA54XX(ha) ? RISC_SADDRESS : - *ha->brd_info->fw_info[0].fwstart); + rval = qla2x00_verify_checksum(ha, ha->fw_srisc_address); } if (rval) { @@ -3545,135 +3543,6 @@ qla24xx_load_risc_flash(scsi_qla_host_t *ha, uint32_t *srisc_addr) return rval; } -#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) - -int -qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) -{ - int rval, num, i; - uint32_t cnt; - uint16_t *risc_code; - uint32_t risc_addr, risc_size; - uint16_t *req_ring; - struct qla_fw_info *fw_iter; - - rval = QLA_SUCCESS; - - /* Load firmware sequences */ - fw_iter = ha->brd_info->fw_info; - *srisc_addr = *ha->brd_info->fw_info->fwstart; - while (fw_iter->addressing != FW_INFO_ADDR_NOMORE) { - risc_code = fw_iter->fwcode; - risc_size = *fw_iter->fwlen; - if (fw_iter->addressing == FW_INFO_ADDR_NORMAL) - risc_addr = *fw_iter->fwstart; - else - risc_addr = *fw_iter->lfwstart; - - num = 0; - rval = 0; - while (risc_size > 0 && !rval) { - cnt = (uint16_t)(ha->fw_transfer_size >> 1); - if (cnt > risc_size) - cnt = risc_size; - - DEBUG7(printk("scsi(%ld): Loading risc segment@ " - "addr %p, number of bytes 0x%x, offset 0x%lx.\n", - ha->host_no, risc_code, cnt, risc_addr)); - - req_ring = (uint16_t *)ha->request_ring; - for (i = 0; i < cnt; i++) - req_ring[i] = cpu_to_le16(risc_code[i]); - - rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr, - cnt); - if (rval) { - DEBUG(printk("scsi(%ld): [ERROR] Failed to " - "load segment %d of firmware\n", - ha->host_no, num)); - qla_printk(KERN_WARNING, ha, - "[ERROR] Failed to load segment %d of " - "firmware\n", num); - - qla2x00_dump_regs(ha); - break; - } - - risc_code += cnt; - risc_addr += cnt; - risc_size -= cnt; - num++; - } - - /* Next firmware sequence */ - fw_iter++; - } - return rval; -} - -int -qla24xx_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) -{ - int rval, num, i; - uint32_t cnt; - uint32_t *risc_code; - uint32_t risc_addr, risc_size; - uint32_t *req_ring; - struct qla_fw_info *fw_iter; - - rval = QLA_SUCCESS; - - /* Load firmware sequences */ - fw_iter = ha->brd_info->fw_info; - *srisc_addr = *((uint32_t *)fw_iter->lfwstart); - while (fw_iter->addressing != FW_INFO_ADDR_NOMORE) { - risc_code = (uint32_t *)fw_iter->fwcode; - risc_size = *((uint32_t *)fw_iter->fwlen); - risc_addr = *((uint32_t *)fw_iter->lfwstart); - - num = 0; - rval = 0; - while (risc_size > 0 && !rval) { - cnt = (uint32_t)(ha->fw_transfer_size >> 2); - if (cnt > risc_size) - cnt = risc_size; - - DEBUG7(printk("scsi(%ld): Loading risc segment@ " - "addr %p, number of bytes 0x%x, offset 0x%lx.\n", - ha->host_no, risc_code, cnt, risc_addr)); - - req_ring = (uint32_t *)ha->request_ring; - for (i = 0; i < cnt; i++) - req_ring[i] = cpu_to_le32(risc_code[i]); - - rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr, - cnt); - if (rval) { - DEBUG(printk("scsi(%ld): [ERROR] Failed to " - "load segment %d of firmware\n", - ha->host_no, num)); - qla_printk(KERN_WARNING, ha, - "[ERROR] Failed to load segment %d of " - "firmware\n", num); - - qla2x00_dump_regs(ha); - break; - } - - risc_code += cnt; - risc_addr += cnt; - risc_size -= cnt; - num++; - } - - /* Next firmware sequence */ - fw_iter++; - } - return rval; -} - -#else /* !defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) */ - #define QLA_FW_URL "ftp://ftp.qlogic.com/outgoing/linux/firmware/" int @@ -3884,4 +3753,3 @@ qla24xx_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) fail_fw_integrity: return QLA_FUNCTION_FAILED; } -#endif diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 22e8714a91f..ea8239dcbbb 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -54,13 +54,6 @@ module_param(ql2xloginretrycount, int, S_IRUGO|S_IRUSR); MODULE_PARM_DESC(ql2xloginretrycount, "Specify an alternate value for the NVRAM login retry count."); -#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) -int ql2xfwloadflash; -module_param(ql2xfwloadflash, int, S_IRUGO|S_IRUSR); -MODULE_PARM_DESC(ql2xfwloadflash, - "Load ISP24xx firmware image from FLASH (onboard memory)."); -#endif - static void qla2x00_free_device(scsi_qla_host_t *); static void qla2x00_config_dma_addressing(scsi_qla_host_t *ha); @@ -1150,18 +1143,22 @@ qla2x00_set_isp_flags(scsi_qla_host_t *ha) case PCI_DEVICE_ID_QLOGIC_ISP2100: ha->device_type |= DT_ISP2100; ha->device_type &= ~DT_EXTENDED_IDS; + ha->fw_srisc_address = RISC_START_ADDRESS_2100; break; case PCI_DEVICE_ID_QLOGIC_ISP2200: ha->device_type |= DT_ISP2200; ha->device_type &= ~DT_EXTENDED_IDS; + ha->fw_srisc_address = RISC_START_ADDRESS_2100; break; case PCI_DEVICE_ID_QLOGIC_ISP2300: ha->device_type |= DT_ISP2300; ha->device_type |= DT_ZIO_SUPPORTED; + ha->fw_srisc_address = RISC_START_ADDRESS_2300; break; case PCI_DEVICE_ID_QLOGIC_ISP2312: ha->device_type |= DT_ISP2312; ha->device_type |= DT_ZIO_SUPPORTED; + ha->fw_srisc_address = RISC_START_ADDRESS_2300; break; case PCI_DEVICE_ID_QLOGIC_ISP2322: ha->device_type |= DT_ISP2322; @@ -1169,26 +1166,33 @@ qla2x00_set_isp_flags(scsi_qla_host_t *ha) if (ha->pdev->subsystem_vendor == 0x1028 && ha->pdev->subsystem_device == 0x0170) ha->device_type |= DT_OEM_001; + ha->fw_srisc_address = RISC_START_ADDRESS_2300; break; case PCI_DEVICE_ID_QLOGIC_ISP6312: ha->device_type |= DT_ISP6312; + ha->fw_srisc_address = RISC_START_ADDRESS_2300; break; case PCI_DEVICE_ID_QLOGIC_ISP6322: ha->device_type |= DT_ISP6322; + ha->fw_srisc_address = RISC_START_ADDRESS_2300; break; case PCI_DEVICE_ID_QLOGIC_ISP2422: ha->device_type |= DT_ISP2422; ha->device_type |= DT_ZIO_SUPPORTED; + ha->fw_srisc_address = RISC_START_ADDRESS_2400; break; case PCI_DEVICE_ID_QLOGIC_ISP2432: ha->device_type |= DT_ISP2432; ha->device_type |= DT_ZIO_SUPPORTED; + ha->fw_srisc_address = RISC_START_ADDRESS_2400; break; case PCI_DEVICE_ID_QLOGIC_ISP5422: ha->device_type |= DT_ISP5422; + ha->fw_srisc_address = RISC_START_ADDRESS_2400; break; case PCI_DEVICE_ID_QLOGIC_ISP5432: ha->device_type |= DT_ISP5432; + ha->fw_srisc_address = RISC_START_ADDRESS_2400; break; } } @@ -1235,7 +1239,7 @@ qla2x00_iospace_config(scsi_qla_host_t *ha) goto iospace_error_exit; } - if (pci_request_regions(ha->pdev, ha->brd_info->drv_name)) { + if (pci_request_regions(ha->pdev, "qla2xxx")) { qla_printk(KERN_WARNING, ha, "Failed to reserve PIO/MMIO regions (%s)\n", pci_name(ha->pdev)); @@ -1317,7 +1321,7 @@ qla24xx_disable_intrs(scsi_qla_host_t *ha) /* * PCI driver interface */ -int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) +static int qla2x00_probe_one(struct pci_dev *pdev) { int ret = -ENODEV; device_reg_t __iomem *reg; @@ -1351,8 +1355,7 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) ha->pdev = pdev; ha->host = host; ha->host_no = host->host_no; - ha->brd_info = brd_info; - sprintf(ha->host_str, "%s_%ld", ha->brd_info->drv_name, ha->host_no); + sprintf(ha->host_str, "qla2xxx_%ld", ha->host_no); /* Set ISP-type information. */ qla2x00_set_isp_flags(ha); @@ -1449,10 +1452,6 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) ha->isp_ops.nvram_config = qla24xx_nvram_config; ha->isp_ops.update_fw_options = qla24xx_update_fw_options; ha->isp_ops.load_risc = qla24xx_load_risc; -#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) - if (ql2xfwloadflash) - ha->isp_ops.load_risc = qla24xx_load_risc_flash; -#endif ha->isp_ops.pci_info_str = qla24xx_pci_info_str; ha->isp_ops.fw_version_str = qla24xx_fw_version_str; ha->isp_ops.intr_handler = qla24xx_intr_handler; @@ -1539,7 +1538,7 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) host->transportt = qla2xxx_transport_template; ret = request_irq(pdev->irq, ha->isp_ops.intr_handler, - SA_INTERRUPT|SA_SHIRQ, ha->brd_info->drv_name, ha); + SA_INTERRUPT|SA_SHIRQ, "qla2xxx", ha); if (ret) { qla_printk(KERN_WARNING, ha, "Failed to reserve interrupt %d already in use.\n", @@ -1637,9 +1636,8 @@ probe_disable_device: probe_out: return ret; } -EXPORT_SYMBOL_GPL(qla2x00_probe_one); -void qla2x00_remove_one(struct pci_dev *pdev) +static void qla2x00_remove_one(struct pci_dev *pdev) { scsi_qla_host_t *ha; @@ -1657,7 +1655,6 @@ void qla2x00_remove_one(struct pci_dev *pdev) pci_set_drvdata(pdev, NULL); } -EXPORT_SYMBOL_GPL(qla2x00_remove_one); static void qla2x00_free_device(scsi_qla_host_t *ha) @@ -2539,14 +2536,6 @@ qla2x00_down_timeout(struct semaphore *sema, unsigned long timeout) return -ETIMEDOUT; } -#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) - -#define qla2x00_release_firmware() do { } while (0) -#define qla2x00_pci_module_init() (0) -#define qla2x00_pci_module_exit() do { } while (0) - -#else /* !defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) */ - /* Firmware interface routines. */ #define FW_BLOBS 5 @@ -2613,10 +2602,6 @@ qla2x00_release_firmware(void) up(&qla_fw_lock); } -static struct qla_board_info qla_board_tbl = { - .drv_name = "qla2xxx", -}; - static struct pci_device_id qla2xxx_pci_tbl[] = { { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2100, PCI_ANY_ID, PCI_ANY_ID, }, @@ -2647,7 +2632,7 @@ MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl); static int __devinit qla2xxx_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) { - return qla2x00_probe_one(pdev, &qla_board_tbl); + return qla2x00_probe_one(pdev); } static void __devexit @@ -2678,8 +2663,6 @@ qla2x00_pci_module_exit(void) pci_unregister_driver(&qla2xxx_pci_driver); } -#endif - /** * qla2x00_module_init - Module initialization. **/ @@ -2699,9 +2682,6 @@ qla2x00_module_init(void) /* Derive version string. */ strcpy(qla2x00_version_str, QLA2XXX_VERSION); -#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) - strcat(qla2x00_version_str, "-fw"); -#endif #if DEBUG_QLA2100 strcat(qla2x00_version_str, "-debug"); #endif -- cgit v1.2.3 From 47f5e069e4d03dda36e3a13f3e20147efd710340 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Wed, 17 May 2006 15:09:39 -0700 Subject: [SCSI] qla2xxx: Use PCI_DEVICE() for pci_device_id definition. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_os.c | 33 +++++++++++---------------------- 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index ea8239dcbbb..2f83523e78f 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -2603,28 +2603,17 @@ qla2x00_release_firmware(void) } static struct pci_device_id qla2xxx_pci_tbl[] = { - { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2100, - PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2200, - PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2300, - PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2312, - PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2322, - PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP6312, - PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP6322, - PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2422, - PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2432, - PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5422, - PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5432, - PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2100) }, + { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2200) }, + { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2300) }, + { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2312) }, + { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2322) }, + { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP6312) }, + { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP6322) }, + { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2422) }, + { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2432) }, + { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5422) }, + { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5432) }, { 0 }, }; MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl); -- cgit v1.2.3 From cb63067a772c0149184309a1f232d62c81a93673 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Wed, 17 May 2006 15:09:45 -0700 Subject: [SCSI] qla2xxx: Consolidate "qla2xxx" string usage to a #define. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_def.h | 2 ++ drivers/scsi/qla2xxx/qla_os.c | 15 ++++++++------- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index c4136bf344a..30a93197988 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -31,6 +31,8 @@ #include #include +#define QLA2XXX_DRIVER_NAME "qla2xxx" + /* * We have MAILBOX_REGISTER_COUNT sized arrays in a few places, * but that's fine as we don't look at the last 24 ones for diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 2f83523e78f..b6adc8a9d4c 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -86,7 +86,7 @@ static int qla2x00_change_queue_type(struct scsi_device *, int); static struct scsi_host_template qla2x00_driver_template = { .module = THIS_MODULE, - .name = "qla2xxx", + .name = QLA2XXX_DRIVER_NAME, .queuecommand = qla2x00_queuecommand, .eh_abort_handler = qla2xxx_eh_abort, @@ -115,7 +115,7 @@ static struct scsi_host_template qla2x00_driver_template = { static struct scsi_host_template qla24xx_driver_template = { .module = THIS_MODULE, - .name = "qla2xxx", + .name = QLA2XXX_DRIVER_NAME, .queuecommand = qla24xx_queuecommand, .eh_abort_handler = qla2xxx_eh_abort, @@ -1239,7 +1239,7 @@ qla2x00_iospace_config(scsi_qla_host_t *ha) goto iospace_error_exit; } - if (pci_request_regions(ha->pdev, "qla2xxx")) { + if (pci_request_regions(ha->pdev, QLA2XXX_DRIVER_NAME)) { qla_printk(KERN_WARNING, ha, "Failed to reserve PIO/MMIO regions (%s)\n", pci_name(ha->pdev)); @@ -1355,7 +1355,7 @@ static int qla2x00_probe_one(struct pci_dev *pdev) ha->pdev = pdev; ha->host = host; ha->host_no = host->host_no; - sprintf(ha->host_str, "qla2xxx_%ld", ha->host_no); + sprintf(ha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, ha->host_no); /* Set ISP-type information. */ qla2x00_set_isp_flags(ha); @@ -1538,7 +1538,7 @@ static int qla2x00_probe_one(struct pci_dev *pdev) host->transportt = qla2xxx_transport_template; ret = request_irq(pdev->irq, ha->isp_ops.intr_handler, - SA_INTERRUPT|SA_SHIRQ, "qla2xxx", ha); + SA_INTERRUPT|SA_SHIRQ, QLA2XXX_DRIVER_NAME, ha); if (ret) { qla_printk(KERN_WARNING, ha, "Failed to reserve interrupt %d already in use.\n", @@ -1868,7 +1868,8 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha) continue; } - snprintf(name, sizeof(name), "qla2xxx_%ld", ha->host_no); + snprintf(name, sizeof(name), "%s_%ld", QLA2XXX_DRIVER_NAME, + ha->host_no); ha->s_dma_pool = dma_pool_create(name, &ha->pdev->dev, DMA_POOL_SIZE, 8, 0); if (ha->s_dma_pool == NULL) { @@ -2631,7 +2632,7 @@ qla2xxx_remove_one(struct pci_dev *pdev) } static struct pci_driver qla2xxx_pci_driver = { - .name = "qla2xxx", + .name = QLA2XXX_DRIVER_NAME, .driver = { .owner = THIS_MODULE, }, -- cgit v1.2.3 From d4e3e04d789ba23027c66e176b10ac7477906948 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Wed, 17 May 2006 15:09:50 -0700 Subject: [SCSI] qla2xxx: Consolidate firmware-dump handling across ISPs. Simplify and centralise buffer allocation/deallocation, as there's no point in having two memory request methods. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_attr.c | 12 +++------- drivers/scsi/qla2xxx/qla_dbg.c | 53 ++++++++++++++++------------------------- drivers/scsi/qla2xxx/qla_def.h | 6 +---- drivers/scsi/qla2xxx/qla_init.c | 27 ++++++++++++++------- drivers/scsi/qla2xxx/qla_os.c | 7 +----- 5 files changed, 43 insertions(+), 62 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index fee0c493775..e96d58ded57 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -46,22 +46,16 @@ qla2x00_sysfs_write_fw_dump(struct kobject *kobj, char *buf, loff_t off, case 0: if (ha->fw_dump_reading == 1) { qla_printk(KERN_INFO, ha, - "Firmware dump cleared on (%ld).\n", - ha->host_no); + "Firmware dump cleared on (%ld).\n", ha->host_no); vfree(ha->fw_dump_buffer); - if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) - free_pages((unsigned long)ha->fw_dump, - ha->fw_dump_order); - - ha->fw_dump_reading = 0; ha->fw_dump_buffer = NULL; - ha->fw_dump = NULL; + ha->fw_dump_reading = 0; ha->fw_dumped = 0; } break; case 1: - if ((ha->fw_dump || ha->fw_dumped) && !ha->fw_dump_reading) { + if (ha->fw_dumped && !ha->fw_dump_reading) { ha->fw_dump_reading = 1; if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index e8120fb7f88..74e54713aa7 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -28,7 +28,7 @@ qla2300_fw_dump(scsi_qla_host_t *ha, int hardware_locked) uint16_t __iomem *dmp_reg; unsigned long flags; struct qla2300_fw_dump *fw; - uint32_t dump_size, data_ram_cnt; + uint32_t data_ram_cnt; risc_address = data_ram_cnt = 0; mb0 = mb2 = 0; @@ -37,23 +37,16 @@ qla2300_fw_dump(scsi_qla_host_t *ha, int hardware_locked) if (!hardware_locked) spin_lock_irqsave(&ha->hardware_lock, flags); - if (ha->fw_dump != NULL) { + if (!ha->fw_dump) { qla_printk(KERN_WARNING, ha, - "Firmware has been previously dumped (%p) -- ignoring " - "request...\n", ha->fw_dump); + "No buffer available for dump!!!\n"); goto qla2300_fw_dump_failed; } - /* Allocate (large) dump buffer. */ - dump_size = sizeof(struct qla2300_fw_dump); - dump_size += (ha->fw_memory_size - 0x11000) * sizeof(uint16_t); - ha->fw_dump_order = get_order(dump_size); - ha->fw_dump = (struct qla2300_fw_dump *) __get_free_pages(GFP_ATOMIC, - ha->fw_dump_order); - if (ha->fw_dump == NULL) { + if (ha->fw_dumped) { qla_printk(KERN_WARNING, ha, - "Unable to allocated memory for firmware dump (%d/%d).\n", - ha->fw_dump_order, dump_size); + "Firmware has been previously dumped (%p) -- ignoring " + "request...\n", ha->fw_dump); goto qla2300_fw_dump_failed; } fw = ha->fw_dump; @@ -358,17 +351,16 @@ qla2300_fw_dump(scsi_qla_host_t *ha, int hardware_locked) } } - if (rval != QLA_SUCCESS) { qla_printk(KERN_WARNING, ha, "Failed to dump firmware (%x)!!!\n", rval); + ha->fw_dumped = 0; - free_pages((unsigned long)ha->fw_dump, ha->fw_dump_order); - ha->fw_dump = NULL; } else { qla_printk(KERN_INFO, ha, "Firmware dump saved to temp buffer (%ld/%p).\n", ha->host_no, ha->fw_dump); + ha->fw_dumped = 1; } qla2300_fw_dump_failed: @@ -587,21 +579,16 @@ qla2100_fw_dump(scsi_qla_host_t *ha, int hardware_locked) if (!hardware_locked) spin_lock_irqsave(&ha->hardware_lock, flags); - if (ha->fw_dump != NULL) { + if (!ha->fw_dump) { qla_printk(KERN_WARNING, ha, - "Firmware has been previously dumped (%p) -- ignoring " - "request...\n", ha->fw_dump); + "No buffer available for dump!!!\n"); goto qla2100_fw_dump_failed; } - /* Allocate (large) dump buffer. */ - ha->fw_dump_order = get_order(sizeof(struct qla2100_fw_dump)); - ha->fw_dump = (struct qla2100_fw_dump *) __get_free_pages(GFP_ATOMIC, - ha->fw_dump_order); - if (ha->fw_dump == NULL) { + if (ha->fw_dumped) { qla_printk(KERN_WARNING, ha, - "Unable to allocated memory for firmware dump (%d/%Zd).\n", - ha->fw_dump_order, sizeof(struct qla2100_fw_dump)); + "Firmware has been previously dumped (%p) -- ignoring " + "request...\n", ha->fw_dump); goto qla2100_fw_dump_failed; } fw = ha->fw_dump; @@ -777,13 +764,13 @@ qla2100_fw_dump(scsi_qla_host_t *ha, int hardware_locked) if (rval != QLA_SUCCESS) { qla_printk(KERN_WARNING, ha, "Failed to dump firmware (%x)!!!\n", rval); + ha->fw_dumped = 0; - free_pages((unsigned long)ha->fw_dump, ha->fw_dump_order); - ha->fw_dump = NULL; } else { qla_printk(KERN_INFO, ha, "Firmware dump saved to temp buffer (%ld/%p).\n", ha->host_no, ha->fw_dump); + ha->fw_dumped = 1; } qla2100_fw_dump_failed: @@ -988,7 +975,7 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked) if (!hardware_locked) spin_lock_irqsave(&ha->hardware_lock, flags); - if (!ha->fw_dump24) { + if (!ha->fw_dump) { qla_printk(KERN_WARNING, ha, "No buffer available for dump!!!\n"); goto qla24xx_fw_dump_failed; @@ -997,10 +984,10 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked) if (ha->fw_dumped) { qla_printk(KERN_WARNING, ha, "Firmware has been previously dumped (%p) -- ignoring " - "request...\n", ha->fw_dump24); + "request...\n", ha->fw_dump); goto qla24xx_fw_dump_failed; } - fw = (struct qla24xx_fw_dump *) ha->fw_dump24; + fw = ha->fw_dump; rval = QLA_SUCCESS; fw->host_status = RD_REG_DWORD(®->host_status); @@ -1654,7 +1641,7 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked) } else { qla_printk(KERN_INFO, ha, "Firmware dump saved to temp buffer (%ld/%p).\n", - ha->host_no, ha->fw_dump24); + ha->host_no, ha->fw_dump); ha->fw_dumped = 1; } @@ -1672,7 +1659,7 @@ qla24xx_ascii_fw_dump(scsi_qla_host_t *ha) uint32_t ext_mem_cnt; uiter = ha->fw_dump_buffer; - fw = ha->fw_dump24; + fw = ha->fw_dump; qla_uprintf(&uiter, "ISP FW Version %d.%02d.%02d Attributes %04x\n", ha->fw_major_version, ha->fw_minor_version, diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 30a93197988..d6f6579cfd2 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2304,15 +2304,11 @@ typedef struct scsi_qla_host { /* Firmware dump information. */ void *fw_dump; - int fw_dump_order; + int fw_dumped; int fw_dump_reading; char *fw_dump_buffer; int fw_dump_buffer_len; - int fw_dumped; - void *fw_dump24; - int fw_dump24_len; - uint8_t host_str[16]; uint32_t pci_attr; diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 748be95c51a..011e8795545 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -773,16 +773,26 @@ qla24xx_chip_diag(scsi_qla_host_t *ha) static void qla2x00_alloc_fw_dump(scsi_qla_host_t *ha) { + uint32_t dump_size = 0; + ha->fw_dumped = 0; - ha->fw_dump24_len = sizeof(struct qla24xx_fw_dump); - ha->fw_dump24_len += (ha->fw_memory_size - 0x100000) * sizeof(uint32_t); - ha->fw_dump24 = vmalloc(ha->fw_dump24_len); - if (ha->fw_dump24) + if (IS_QLA2100(ha) || IS_QLA2200(ha)) { + dump_size = sizeof(struct qla2100_fw_dump); + } else if (IS_QLA23XX(ha)) { + dump_size = sizeof(struct qla2300_fw_dump); + dump_size += (ha->fw_memory_size - 0x11000) * sizeof(uint16_t); + } else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { + dump_size = sizeof(struct qla24xx_fw_dump); + dump_size += (ha->fw_memory_size - 0x100000) * sizeof(uint32_t); + } + + ha->fw_dump = vmalloc(dump_size); + if (ha->fw_dump) qla_printk(KERN_INFO, ha, "Allocated (%d KB) for firmware " - "dump...\n", ha->fw_dump24_len / 1024); + "dump...\n", dump_size / 1024); else qla_printk(KERN_WARNING, ha, "Unable to allocate (%d KB) for " - "firmware dump!!!\n", ha->fw_dump24_len / 1024); + "firmware dump!!!\n", dump_size / 1024); } /** @@ -800,13 +810,12 @@ qla2x00_resize_request_q(scsi_qla_host_t *ha) dma_addr_t request_dma; request_t *request_ring; + qla2x00_alloc_fw_dump(ha); + /* Valid only on recent ISPs. */ if (IS_QLA2100(ha) || IS_QLA2200(ha)) return; - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) - qla2x00_alloc_fw_dump(ha); - /* Retrieve IOCB counts available to the firmware. */ rval = qla2x00_get_resource_cnts(ha, NULL, NULL, NULL, &fw_iocb_cnt); if (rval) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index b6adc8a9d4c..1052528c310 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -2068,15 +2068,10 @@ qla2x00_mem_free(scsi_qla_host_t *ha) } INIT_LIST_HEAD(&ha->fcports); - if (ha->fw_dump) - free_pages((unsigned long)ha->fw_dump, ha->fw_dump_order); - - vfree(ha->fw_dump24); - + vfree(ha->fw_dump); vfree(ha->fw_dump_buffer); ha->fw_dump = NULL; - ha->fw_dump24 = NULL; ha->fw_dumped = 0; ha->fw_dump_reading = 0; ha->fw_dump_buffer = NULL; -- cgit v1.2.3 From 21333b481159a78b5379b8ddb400efafd5857d55 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Wed, 17 May 2006 15:09:56 -0700 Subject: [SCSI] qla2xxx: Correct issue where driver improperly issued SNS commands in N2N topologies. Semantic changes in ISP24xx firmware behaviour inadvertently caused the driver to believe an F-port topology was present in an N_port-to-N_port configuration. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_init.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 011e8795545..aef093db597 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1778,6 +1778,9 @@ qla2x00_configure_loop(scsi_qla_host_t *ha) set_bit(RSCN_UPDATE, &flags); clear_bit(LOCAL_LOOP_UPDATE, &flags); + } else if (ha->current_topology == ISP_CFG_N) { + clear_bit(RSCN_UPDATE, &flags); + } else if (!ha->flags.online || (test_bit(ABORT_ISP_ACTIVE, &flags))) { -- cgit v1.2.3 From 818bf493525d2a0ce3ddaefb2b78db1635596666 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Wed, 17 May 2006 15:10:01 -0700 Subject: [SCSI] qla2xxx: Update version number to 8.01.05-k2. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index d537192a1ed..6b315521bd8 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -7,9 +7,9 @@ /* * Driver version */ -#define QLA2XXX_VERSION "8.01.04-k" +#define QLA2XXX_VERSION "8.01.05-k2" #define QLA_DRIVER_MAJOR_VER 8 #define QLA_DRIVER_MINOR_VER 1 -#define QLA_DRIVER_PATCH_VER 4 +#define QLA_DRIVER_PATCH_VER 5 #define QLA_DRIVER_BETA_VER 0 -- cgit v1.2.3 From 979dca3826841e5dc9170c28f20bd75ece266a9a Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 19 May 2006 11:55:58 -0700 Subject: [SCSI] imm: no need for unchecked_isa_dma Relax the lowmem bounce buffer requirement for imm so that any low memory page will do -- they don't need to be below the ISA 16 MB limit, just need to be mapped in low memory. Signed-off-by: Randy Dunlap Signed-off-by: James Bottomley --- drivers/scsi/imm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/imm.c b/drivers/scsi/imm.c index fc0f30ae0f7..cd2dffdab77 100644 --- a/drivers/scsi/imm.c +++ b/drivers/scsi/imm.c @@ -1119,6 +1119,10 @@ static int device_check(imm_struct *dev) return -ENODEV; } +/* + * imm cannot deal with highmem, so this causes all IO pages for this host + * to reside in low memory (hence mapped) + */ static int imm_adjust_queue(struct scsi_device *device) { blk_queue_bounce_limit(device->request_queue, BLK_BOUNCE_HIGH); @@ -1141,10 +1145,6 @@ static struct scsi_host_template imm_template = { .use_clustering = ENABLE_CLUSTERING, .can_queue = 1, .slave_alloc = imm_adjust_queue, - .unchecked_isa_dma = 1, /* imm cannot deal with highmem, so - * this is an easy trick to ensure - * all io pages for this host reside - * in low memory */ }; /*************************************************************************** -- cgit v1.2.3 From 4c5c81613b0eb0dba97a8f312a2f1162f39fd47b Mon Sep 17 00:00:00 2001 From: Andrew Chew Date: Thu, 20 Apr 2006 15:54:26 -0700 Subject: [PATCH] sata_nv: Add MCP61 support Added MCP61 SATA support to sata_nv. Signed-off-by: Jeff Garzik --- drivers/ide/pci/amd74xx.c | 7 +++++-- drivers/scsi/sata_nv.c | 6 ++++++ include/linux/pci_ids.h | 4 ++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c index b22ee546231..6e9dbf4d807 100644 --- a/drivers/ide/pci/amd74xx.c +++ b/drivers/ide/pci/amd74xx.c @@ -74,6 +74,7 @@ static struct amd_ide_chip { { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE, 0x50, AMD_UDMA_133 }, { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE, 0x50, AMD_UDMA_133 }, { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE, 0x50, AMD_UDMA_133 }, + { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE, 0x50, AMD_UDMA_133 }, { PCI_DEVICE_ID_AMD_CS5536_IDE, 0x40, AMD_UDMA_100 }, { 0 } }; @@ -488,7 +489,8 @@ static ide_pci_device_t amd74xx_chipsets[] __devinitdata = { /* 14 */ DECLARE_NV_DEV("NFORCE-MCP04"), /* 15 */ DECLARE_NV_DEV("NFORCE-MCP51"), /* 16 */ DECLARE_NV_DEV("NFORCE-MCP55"), - /* 17 */ DECLARE_AMD_DEV("AMD5536"), + /* 17 */ DECLARE_NV_DEV("NFORCE-MCP61"), + /* 18 */ DECLARE_AMD_DEV("AMD5536"), }; static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id) @@ -525,7 +527,8 @@ static struct pci_device_id amd74xx_pci_tbl[] = { { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14 }, { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 15 }, { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 16 }, - { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 17 }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 17 }, + { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 18 }, { 0, }, }; MODULE_DEVICE_TABLE(pci, amd74xx_pci_tbl); diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c index 70c51088d37..043ff4fd9ba 100644 --- a/drivers/scsi/sata_nv.c +++ b/drivers/scsi/sata_nv.c @@ -140,6 +140,12 @@ static const struct pci_device_id nv_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC }, { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC }, { PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE<<8, 0xffff00, GENERIC }, diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index d6fe048376a..233f60741c8 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1182,6 +1182,10 @@ #define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_1100 0x034E #define PCI_DEVICE_ID_NVIDIA_NVENET_14 0x0372 #define PCI_DEVICE_ID_NVIDIA_NVENET_15 0x0373 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA 0x03E7 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE 0x03EC +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2 0x03F6 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3 0x03F7 #define PCI_VENDOR_ID_IMS 0x10e0 #define PCI_DEVICE_ID_IMS_TT128 0x9128 -- cgit v1.2.3 From d3fb4e8dddebbf7d6c0b02842c619bfd4fa199f5 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Wed, 24 May 2006 01:43:25 -0400 Subject: [libata sata_promise] Add PATA cable detection. Original patch from Phillip Jordan Cleanups and fixes by me. --- drivers/scsi/sata_promise.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index bb000438cb6..285ab0263d9 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c @@ -364,12 +364,23 @@ static void pdc_sata_phy_reset(struct ata_port *ap) sata_phy_reset(ap); } -static void pdc_pata_phy_reset(struct ata_port *ap) +static void pdc_pata_cbl_detect(struct ata_port *ap) { - /* FIXME: add cable detect. Don't assume 40-pin cable */ - ap->cbl = ATA_CBL_PATA40; - ap->udma_mask &= ATA_UDMA_MASK_40C; + u8 tmp; + void __iomem *mmio = (void *) ap->ioaddr.cmd_addr + PDC_CTLSTAT + 0x03; + + tmp = readb(mmio); + + if (tmp & 0x01) { + ap->cbl = ATA_CBL_PATA40; + ap->udma_mask &= ATA_UDMA_MASK_40C; + } else + ap->cbl = ATA_CBL_PATA80; +} +static void pdc_pata_phy_reset(struct ata_port *ap) +{ + pdc_pata_cbl_detect(ap); pdc_reset_port(ap); ata_port_probe(ap); ata_bus_reset(ap); -- cgit v1.2.3 From 1f3461a72619fcd70a0fcb563306c91f753b4620 Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Tue, 23 May 2006 18:12:30 +0800 Subject: [PATCH] libata: minor fix for irq-pio merge Minor fix to put the ATA_FLAG_NO_ATAPI flag back. Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik --- drivers/scsi/sata_mv.c | 2 +- drivers/scsi/sata_sx4.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index bfe817fc752..eb5f8bcd03c 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -93,7 +93,7 @@ enum { MV_FLAG_IRQ_COALESCE = (1 << 29), /* IRQ coalescing capability */ MV_COMMON_FLAGS = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO | - ATA_FLAG_PIO_POLLING), + ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING), MV_6XXX_FLAGS = MV_FLAG_IRQ_COALESCE, CRQB_FLAG_READ = (1 << 0), diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c index 70a69548829..e799ef35e9d 100644 --- a/drivers/scsi/sata_sx4.c +++ b/drivers/scsi/sata_sx4.c @@ -218,7 +218,7 @@ static const struct ata_port_info pdc_port_info[] = { .sht = &pdc_sata_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST | ATA_FLAG_MMIO | - ATA_FLAG_PIO_POLLING, + ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */ -- cgit v1.2.3 From b6079ca409bf88c248992e96510dd6f610f7ed89 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 22 May 2006 16:52:06 +0100 Subject: [PATCH] libata: PIO 0 Ensure the pio_mode is always setup. Don't do any setup on the controller b just ensure the mode reporting is valid to avoid tons of special cases in PATA driver code when mode switching on the fly. Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index e891b83be10..45b6b29bc10 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1498,6 +1498,12 @@ static int ata_bus_probe(struct ata_port *ap) if (classes[i] == ATA_DEV_UNKNOWN) classes[i] = ATA_DEV_NONE; + /* after the reset the device state is PIO 0 and the controller + state is undefined. Record the mode */ + + for (i = 0; i < ATA_MAX_DEVICES; i++) + ap->device[i].pio_mode = XFER_PIO_0; + /* read IDENTIFY page and configure devices */ for (i = 0; i < ATA_MAX_DEVICES; i++) { dev = &ap->device[i]; -- cgit v1.2.3 From f79d409fae879d135d1aaca6d83451f2787aec07 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 22 May 2006 16:55:11 +0100 Subject: [PATCH] libata - fix bracketing and DMA oops The upstream tree has the ATA_DFLAG_PIO bug fixed but does not have the pass throuugh bug fix Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/scsi/libata-scsi.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 2007b4b6e1b..3ce7c198ff0 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -1921,7 +1921,7 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf, return 0; dpofua = 0; - if (ata_dev_supports_fua(args->id) && dev->flags & ATA_DFLAG_LBA48 && + if (ata_dev_supports_fua(args->id) && (dev->flags & ATA_DFLAG_LBA48) && (!(dev->flags & ATA_DFLAG_PIO) || dev->multi_count)) dpofua = 1 << 4; @@ -2408,9 +2408,14 @@ ata_scsi_pass_thru(struct ata_queued_cmd *qc, const u8 *scsicmd) { struct ata_taskfile *tf = &(qc->tf); struct scsi_cmnd *cmd = qc->scsicmd; + struct ata_device *dev = qc->dev; if ((tf->protocol = ata_scsi_map_proto(scsicmd[1])) == ATA_PROT_UNKNOWN) goto invalid_fld; + + /* We may not issue DMA commands if no DMA mode is set */ + if (tf->protocol == ATA_PROT_DMA && dev->dma_mode == 0) + goto invalid_fld; if (scsicmd[1] & 0xe0) /* PIO multi not supported yet */ -- cgit v1.2.3 From 8190bdb9291758f3b8c436ec1154c9923ddb57ea Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Wed, 24 May 2006 01:53:39 -0400 Subject: [libata] libata-scsi, sata_mv: trim trailing whitespace --- drivers/scsi/libata-scsi.c | 2 +- drivers/scsi/sata_mv.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 3ce7c198ff0..9e5cb9f748e 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -2412,7 +2412,7 @@ ata_scsi_pass_thru(struct ata_queued_cmd *qc, const u8 *scsicmd) if ((tf->protocol = ata_scsi_map_proto(scsicmd[1])) == ATA_PROT_UNKNOWN) goto invalid_fld; - + /* We may not issue DMA commands if no DMA mode is set */ if (tf->protocol == ATA_PROT_DMA && dev->dma_mode == 0) goto invalid_fld; diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index eb5f8bcd03c..691c115ac8e 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -1377,7 +1377,7 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant, /* Note that DEV_IRQ might happen spuriously during EDMA, * and should be ignored in such cases. * The cause of this is still under investigation. - */ + */ if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) { /* EDMA: check for response queue interrupt */ if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause) { -- cgit v1.2.3 From a6b2c5d4754dc539a560fdf0d3fb78a14174394a Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 22 May 2006 16:59:59 +0100 Subject: [PATCH] PATCH: libata. Add ->data_xfer method We need to pass the device in order to do per device checks such as 32bit I/O enables. With the changes to include dev->ap we now don't have to add parameters however just clean them up. Also add data_xfer methods to the existing drivers except ata_piix (which is in the other block of patches). If you reject the piix one just add a data_xfer to it... Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 63 +++++++++++++-------------------------------- drivers/scsi/sata_mv.c | 2 ++ drivers/scsi/sata_nv.c | 1 + drivers/scsi/sata_promise.c | 2 ++ drivers/scsi/sata_qstor.c | 1 + drivers/scsi/sata_sil.c | 1 + drivers/scsi/sata_sis.c | 1 + drivers/scsi/sata_svw.c | 1 + drivers/scsi/sata_sx4.c | 1 + drivers/scsi/sata_uli.c | 1 + drivers/scsi/sata_via.c | 1 + drivers/scsi/sata_vsc.c | 1 + include/linux/libata.h | 6 +++++ 13 files changed, 37 insertions(+), 45 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 45b6b29bc10..074a46e5bbd 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3527,7 +3527,7 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words) /** * ata_mmio_data_xfer - Transfer data by MMIO - * @ap: port to read/write + * @dev: device for this I/O * @buf: data buffer * @buflen: buffer length * @write_data: read/write @@ -3538,9 +3538,10 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words) * Inherited from caller. */ -static void ata_mmio_data_xfer(struct ata_port *ap, unsigned char *buf, - unsigned int buflen, int write_data) +void ata_mmio_data_xfer(struct ata_device *adev, unsigned char *buf, + unsigned int buflen, int write_data) { + struct ata_port *ap = adev->ap; unsigned int i; unsigned int words = buflen >> 1; u16 *buf16 = (u16 *) buf; @@ -3572,7 +3573,7 @@ static void ata_mmio_data_xfer(struct ata_port *ap, unsigned char *buf, /** * ata_pio_data_xfer - Transfer data by PIO - * @ap: port to read/write + * @adev: device to target * @buf: data buffer * @buflen: buffer length * @write_data: read/write @@ -3583,9 +3584,10 @@ static void ata_mmio_data_xfer(struct ata_port *ap, unsigned char *buf, * Inherited from caller. */ -static void ata_pio_data_xfer(struct ata_port *ap, unsigned char *buf, - unsigned int buflen, int write_data) +void ata_pio_data_xfer(struct ata_device *adev, unsigned char *buf, + unsigned int buflen, int write_data) { + struct ata_port *ap = adev->ap; unsigned int words = buflen >> 1; /* Transfer multiple of 2 bytes */ @@ -3609,39 +3611,6 @@ static void ata_pio_data_xfer(struct ata_port *ap, unsigned char *buf, } } -/** - * ata_data_xfer - Transfer data from/to the data register. - * @ap: port to read/write - * @buf: data buffer - * @buflen: buffer length - * @do_write: read/write - * - * Transfer data from/to the device data register. - * - * LOCKING: - * Inherited from caller. - */ - -static void ata_data_xfer(struct ata_port *ap, unsigned char *buf, - unsigned int buflen, int do_write) -{ - /* Make the crap hardware pay the costs not the good stuff */ - if (unlikely(ap->flags & ATA_FLAG_IRQ_MASK)) { - unsigned long flags; - local_irq_save(flags); - if (ap->flags & ATA_FLAG_MMIO) - ata_mmio_data_xfer(ap, buf, buflen, do_write); - else - ata_pio_data_xfer(ap, buf, buflen, do_write); - local_irq_restore(flags); - } else { - if (ap->flags & ATA_FLAG_MMIO) - ata_mmio_data_xfer(ap, buf, buflen, do_write); - else - ata_pio_data_xfer(ap, buf, buflen, do_write); - } -} - /** * ata_pio_sector - Transfer ATA_SECT_SIZE (512 bytes) of data. * @qc: Command on going @@ -3676,17 +3645,18 @@ static void ata_pio_sector(struct ata_queued_cmd *qc) if (PageHighMem(page)) { unsigned long flags; + /* FIXME: use a bounce buffer */ local_irq_save(flags); buf = kmap_atomic(page, KM_IRQ0); /* do the actual data transfer */ - ata_data_xfer(ap, buf + offset, ATA_SECT_SIZE, do_write); + ap->ops->data_xfer(qc->dev, buf + offset, ATA_SECT_SIZE, do_write); kunmap_atomic(buf, KM_IRQ0); local_irq_restore(flags); } else { buf = page_address(page); - ata_data_xfer(ap, buf + offset, ATA_SECT_SIZE, do_write); + ap->ops->data_xfer(qc->dev, buf + offset, ATA_SECT_SIZE, do_write); } qc->cursect++; @@ -3742,7 +3712,7 @@ static void atapi_send_cdb(struct ata_port *ap, struct ata_queued_cmd *qc) DPRINTK("send cdb\n"); WARN_ON(qc->dev->cdb_len < 12); - ata_data_xfer(ap, qc->cdb, qc->dev->cdb_len, 1); + ap->ops->data_xfer(qc->dev, qc->cdb, qc->dev->cdb_len, 1); ata_altstatus(ap); /* flush */ switch (qc->tf.protocol) { @@ -3802,7 +3772,7 @@ next_sg: "%u bytes trailing data\n", bytes); for (i = 0; i < words; i++) - ata_data_xfer(ap, (unsigned char*)pad_buf, 2, do_write); + ap->ops->data_xfer(qc->dev, (unsigned char*)pad_buf, 2, do_write); ap->hsm_task_state = HSM_ST_LAST; return; @@ -3828,17 +3798,18 @@ next_sg: if (PageHighMem(page)) { unsigned long flags; + /* FIXME: use bounce buffer */ local_irq_save(flags); buf = kmap_atomic(page, KM_IRQ0); /* do the actual data transfer */ - ata_data_xfer(ap, buf + offset, count, do_write); + ap->ops->data_xfer(qc->dev, buf + offset, count, do_write); kunmap_atomic(buf, KM_IRQ0); local_irq_restore(flags); } else { buf = page_address(page); - ata_data_xfer(ap, buf + offset, count, do_write); + ap->ops->data_xfer(qc->dev, buf + offset, count, do_write); } bytes -= count; @@ -5702,6 +5673,8 @@ EXPORT_SYMBOL_GPL(ata_port_start); EXPORT_SYMBOL_GPL(ata_port_stop); EXPORT_SYMBOL_GPL(ata_host_stop); EXPORT_SYMBOL_GPL(ata_interrupt); +EXPORT_SYMBOL_GPL(ata_mmio_data_xfer); +EXPORT_SYMBOL_GPL(ata_pio_data_xfer); EXPORT_SYMBOL_GPL(ata_qc_prep); EXPORT_SYMBOL_GPL(ata_noop_qc_prep); EXPORT_SYMBOL_GPL(ata_bmdma_setup); diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index 691c115ac8e..bf3529fdea9 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -406,6 +406,7 @@ static const struct ata_port_operations mv5_ops = { .qc_prep = mv_qc_prep, .qc_issue = mv_qc_issue, + .data_xfer = ata_mmio_data_xfer, .eng_timeout = mv_eng_timeout, @@ -433,6 +434,7 @@ static const struct ata_port_operations mv6_ops = { .qc_prep = mv_qc_prep, .qc_issue = mv_qc_issue, + .data_xfer = ata_mmio_data_xfer, .eng_timeout = mv_eng_timeout, diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c index 043ff4fd9ba..d93513ef741 100644 --- a/drivers/scsi/sata_nv.c +++ b/drivers/scsi/sata_nv.c @@ -234,6 +234,7 @@ static const struct ata_port_operations nv_ops = { .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, .eng_timeout = ata_eng_timeout, + .data_xfer = ata_pio_data_xfer, .irq_handler = nv_interrupt, .irq_clear = ata_bmdma_irq_clear, .scr_read = nv_scr_read, diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index 285ab0263d9..01111594d09 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c @@ -137,6 +137,7 @@ static const struct ata_port_operations pdc_sata_ops = { .qc_prep = pdc_qc_prep, .qc_issue = pdc_qc_issue_prot, .eng_timeout = pdc_eng_timeout, + .data_xfer = ata_mmio_data_xfer, .irq_handler = pdc_interrupt, .irq_clear = pdc_irq_clear, @@ -159,6 +160,7 @@ static const struct ata_port_operations pdc_pata_ops = { .qc_prep = pdc_qc_prep, .qc_issue = pdc_qc_issue_prot, + .data_xfer = ata_mmio_data_xfer, .eng_timeout = pdc_eng_timeout, .irq_handler = pdc_interrupt, .irq_clear = pdc_irq_clear, diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c index 54283e06070..68737cadd2d 100644 --- a/drivers/scsi/sata_qstor.c +++ b/drivers/scsi/sata_qstor.c @@ -156,6 +156,7 @@ static const struct ata_port_operations qs_ata_ops = { .phy_reset = qs_phy_reset, .qc_prep = qs_qc_prep, .qc_issue = qs_qc_issue, + .data_xfer = ata_mmio_data_xfer, .eng_timeout = qs_eng_timeout, .irq_handler = qs_intr, .irq_clear = qs_irq_clear, diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index aa63044eed2..3bd80773869 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -176,6 +176,7 @@ static const struct ata_port_operations sil_ops = { .bmdma_status = ata_bmdma_status, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, + .data_xfer = ata_mmio_data_xfer, .freeze = sil_freeze, .thaw = sil_thaw, .error_handler = ata_bmdma_error_handler, diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c index 3097821688d..82a07bff7e9 100644 --- a/drivers/scsi/sata_sis.c +++ b/drivers/scsi/sata_sis.c @@ -113,6 +113,7 @@ static const struct ata_port_operations sis_ops = { .bmdma_status = ata_bmdma_status, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, + .data_xfer = ata_pio_data_xfer, .eng_timeout = ata_eng_timeout, .irq_handler = ata_interrupt, .irq_clear = ata_bmdma_irq_clear, diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c index d5eb5375e26..7a4703bfa12 100644 --- a/drivers/scsi/sata_svw.c +++ b/drivers/scsi/sata_svw.c @@ -320,6 +320,7 @@ static const struct ata_port_operations k2_sata_ops = { .bmdma_status = ata_bmdma_status, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, + .data_xfer = ata_mmio_data_xfer, .eng_timeout = ata_eng_timeout, .irq_handler = ata_interrupt, .irq_clear = ata_bmdma_irq_clear, diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c index e799ef35e9d..c4db6bf14a2 100644 --- a/drivers/scsi/sata_sx4.c +++ b/drivers/scsi/sata_sx4.c @@ -204,6 +204,7 @@ static const struct ata_port_operations pdc_20621_ops = { .phy_reset = pdc_20621_phy_reset, .qc_prep = pdc20621_qc_prep, .qc_issue = pdc20621_qc_issue_prot, + .data_xfer = ata_mmio_data_xfer, .eng_timeout = pdc_eng_timeout, .irq_handler = pdc20621_interrupt, .irq_clear = pdc20621_irq_clear, diff --git a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c index 15f81bfc30f..7fae3e06e46 100644 --- a/drivers/scsi/sata_uli.c +++ b/drivers/scsi/sata_uli.c @@ -110,6 +110,7 @@ static const struct ata_port_operations uli_ops = { .bmdma_status = ata_bmdma_status, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, + .data_xfer = ata_pio_data_xfer, .eng_timeout = ata_eng_timeout, diff --git a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c index 17aefab5f42..1c9e2f36805 100644 --- a/drivers/scsi/sata_via.c +++ b/drivers/scsi/sata_via.c @@ -124,6 +124,7 @@ static const struct ata_port_operations svia_sata_ops = { .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, + .data_xfer = ata_pio_data_xfer, .eng_timeout = ata_eng_timeout, diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c index 0372be7ff1c..438e7c6a0f8 100644 --- a/drivers/scsi/sata_vsc.c +++ b/drivers/scsi/sata_vsc.c @@ -297,6 +297,7 @@ static const struct ata_port_operations vsc_sata_ops = { .bmdma_status = ata_bmdma_status, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, + .data_xfer = ata_pio_data_xfer, .eng_timeout = ata_eng_timeout, .irq_handler = vsc_sata_interrupt, .irq_clear = ata_bmdma_irq_clear, diff --git a/include/linux/libata.h b/include/linux/libata.h index c51502c047a..25a6bf18159 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -525,6 +525,8 @@ struct ata_port_operations { void (*bmdma_setup) (struct ata_queued_cmd *qc); void (*bmdma_start) (struct ata_queued_cmd *qc); + void (*data_xfer) (struct ata_device *, unsigned char *, unsigned int, int); + void (*qc_prep) (struct ata_queued_cmd *qc); unsigned int (*qc_issue) (struct ata_queued_cmd *qc); @@ -646,6 +648,10 @@ extern int ata_port_start (struct ata_port *ap); extern void ata_port_stop (struct ata_port *ap); extern void ata_host_stop (struct ata_host_set *host_set); extern irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs); +extern void ata_mmio_data_xfer(struct ata_device *adev, unsigned char *buf, + unsigned int buflen, int write_data); +extern void ata_pio_data_xfer(struct ata_device *adev, unsigned char *buf, + unsigned int buflen, int write_data); extern void ata_qc_prep(struct ata_queued_cmd *qc); extern void ata_noop_qc_prep(struct ata_queued_cmd *qc); extern unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc); -- cgit v1.2.3 From e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1 Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Mon, 22 May 2006 19:02:03 -0400 Subject: [PATCH] sata_mv: endian annotations Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/scsi/sata_mv.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index bf3529fdea9..624983c2e24 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -272,33 +272,33 @@ enum chip_type { /* Command ReQuest Block: 32B */ struct mv_crqb { - u32 sg_addr; - u32 sg_addr_hi; - u16 ctrl_flags; - u16 ata_cmd[11]; + __le32 sg_addr; + __le32 sg_addr_hi; + __le16 ctrl_flags; + __le16 ata_cmd[11]; }; struct mv_crqb_iie { - u32 addr; - u32 addr_hi; - u32 flags; - u32 len; - u32 ata_cmd[4]; + __le32 addr; + __le32 addr_hi; + __le32 flags; + __le32 len; + __le32 ata_cmd[4]; }; /* Command ResPonse Block: 8B */ struct mv_crpb { - u16 id; - u16 flags; - u32 tmstmp; + __le16 id; + __le16 flags; + __le32 tmstmp; }; /* EDMA Physical Region Descriptor (ePRD); A.K.A. SG */ struct mv_sg { - u32 addr; - u32 flags_size; - u32 addr_hi; - u32 reserved; + __le32 addr; + __le32 flags_size; + __le32 addr_hi; + __le32 reserved; }; struct mv_port_priv { @@ -1030,7 +1030,7 @@ static inline unsigned mv_inc_q_index(unsigned index) return (index + 1) & MV_MAX_Q_DEPTH_MASK; } -static inline void mv_crqb_pack_cmd(u16 *cmdw, u8 data, u8 addr, unsigned last) +static inline void mv_crqb_pack_cmd(__le16 *cmdw, u8 data, u8 addr, unsigned last) { u16 tmp = data | (addr << CRQB_CMD_ADDR_SHIFT) | CRQB_CMD_CS | (last ? CRQB_CMD_LAST : 0); @@ -1053,7 +1053,7 @@ static void mv_qc_prep(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; struct mv_port_priv *pp = ap->private_data; - u16 *cw; + __le16 *cw; struct ata_taskfile *tf; u16 flags = 0; unsigned in_index; -- cgit v1.2.3 From b58b7f98670ab6dd7774b67ff1655a787321209f Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Fri, 19 May 2006 16:42:49 +1000 Subject: [PATCH] powerpc: tidy up iseries/pci.c Remove some unused counters. No need to allocate iomm_table and iobar_table, which means that iomm_table_initialize is not longer needed. Use kzalloc where sensible. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/pci.c | 78 +++++------------------------------- 1 file changed, 11 insertions(+), 67 deletions(-) diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c index 428ffb5cf04..91a94747eda 100644 --- a/arch/powerpc/platforms/iseries/pci.c +++ b/arch/powerpc/platforms/iseries/pci.c @@ -57,15 +57,6 @@ LIST_HEAD(iSeries_Global_Device_List); static int DeviceCount; -/* Counters and control flags. */ -static long Pci_Io_Read_Count; -static long Pci_Io_Write_Count; -#if 0 -static long Pci_Cfg_Read_Count; -static long Pci_Cfg_Write_Count; -#endif -static long Pci_Error_Count; - static int Pci_Retry_Max = 3; /* Only retry 3 times */ static int Pci_Error_Flag = 1; /* Set Retry Error on. */ @@ -79,40 +70,18 @@ static struct pci_ops iSeries_pci_ops; #define IOMM_TABLE_ENTRY_SIZE 0x0000000000400000UL #define BASE_IO_MEMORY 0xE000000000000000UL -static unsigned long max_io_memory = 0xE000000000000000UL; +static unsigned long max_io_memory = BASE_IO_MEMORY; static long current_iomm_table_entry; /* * Lookup Tables. */ -static struct device_node **iomm_table; -static u8 *iobar_table; +static struct device_node *iomm_table[IOMM_TABLE_MAX_ENTRIES]; +static u8 iobar_table[IOMM_TABLE_MAX_ENTRIES]; -/* - * Static and Global variables - */ -static char *pci_io_text = "iSeries PCI I/O"; +static const char pci_io_text[] = "iSeries PCI I/O"; static DEFINE_SPINLOCK(iomm_table_lock); -/* - * iomm_table_initialize - * - * Allocates and initalizes the Address Translation Table and Bar - * Tables to get them ready for use. Must be called before any - * I/O space is handed out to the device BARs. - */ -static void iomm_table_initialize(void) -{ - spin_lock(&iomm_table_lock); - iomm_table = kmalloc(sizeof(*iomm_table) * IOMM_TABLE_MAX_ENTRIES, - GFP_KERNEL); - iobar_table = kmalloc(sizeof(*iobar_table) * IOMM_TABLE_MAX_ENTRIES, - GFP_KERNEL); - spin_unlock(&iomm_table_lock); - if ((iomm_table == NULL) || (iobar_table == NULL)) - panic("PCI: I/O tables allocation failed.\n"); -} - /* * iomm_table_allocate_entry * @@ -140,9 +109,8 @@ static void iomm_table_allocate_entry(struct pci_dev *dev, int bar_num) */ spin_lock(&iomm_table_lock); bar_res->name = pci_io_text; - bar_res->start = + bar_res->start = BASE_IO_MEMORY + IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry; - bar_res->start += BASE_IO_MEMORY; bar_res->end = bar_res->start + bar_size - 1; /* * Allocate the number of table entries needed for BAR. @@ -154,7 +122,7 @@ static void iomm_table_allocate_entry(struct pci_dev *dev, int bar_num) ++current_iomm_table_entry; } max_io_memory = BASE_IO_MEMORY + - (IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry); + IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry; spin_unlock(&iomm_table_lock); } @@ -171,13 +139,10 @@ static void iomm_table_allocate_entry(struct pci_dev *dev, int bar_num) */ static void allocate_device_bars(struct pci_dev *dev) { - struct resource *bar_res; int bar_num; - for (bar_num = 0; bar_num <= PCI_ROM_RESOURCE; ++bar_num) { - bar_res = &dev->resource[bar_num]; + for (bar_num = 0; bar_num <= PCI_ROM_RESOURCE; ++bar_num) iomm_table_allocate_entry(dev, bar_num); - } } /* @@ -205,10 +170,9 @@ static struct device_node *build_device_node(HvBusNumber Bus, struct device_node *node; struct pci_dn *pdn; - node = kmalloc(sizeof(struct device_node), GFP_KERNEL); + node = kzalloc(sizeof(struct device_node), GFP_KERNEL); if (node == NULL) return NULL; - memset(node, 0, sizeof(struct device_node)); pdn = kzalloc(sizeof(*pdn), GFP_KERNEL); if (pdn == NULL) { kfree(node); @@ -224,7 +188,7 @@ static struct device_node *build_device_node(HvBusNumber Bus, } /* - * unsigned long __init find_and_init_phbs(void) + * iSeries_pcibios_init * * Description: * This function checks for all possible system PCI host bridges that connect @@ -232,7 +196,7 @@ static struct device_node *build_device_node(HvBusNumber Bus, * ownership status. A pci_controller is built for any bus which is partially * owned or fully owned by this guest partition. */ -unsigned long __init find_and_init_phbs(void) +void iSeries_pcibios_init(void) { struct pci_controller *phb; HvBusNumber bus; @@ -263,18 +227,6 @@ unsigned long __init find_and_init_phbs(void) printk(KERN_ERR "Unexpected Return on Probe(0x%04X): 0x%04X", bus, ret); } - return 0; -} - -/* - * iSeries_pcibios_init - * - * Chance to initialize and structures or variable before PCI Bus walk. - */ -void iSeries_pcibios_init(void) -{ - iomm_table_initialize(); - find_and_init_phbs(); } /* @@ -331,8 +283,7 @@ static void scan_PHB_slots(struct pci_controller *Phb) int IdSel; const int MaxAgents = 8; - DevInfo = (struct HvCallPci_DeviceInfo*) - kmalloc(sizeof(struct HvCallPci_DeviceInfo), GFP_KERNEL); + DevInfo = kmalloc(sizeof(struct HvCallPci_DeviceInfo), GFP_KERNEL); if (DevInfo == NULL) return; @@ -622,7 +573,6 @@ static int CheckReturnCode(char *TextHdr, struct device_node *DevNode, if (ret != 0) { struct pci_dn *pdn = PCI_DN(DevNode); - ++Pci_Error_Count; (*retry)++; printk("PCI: %s: Device 0x%04X:%02X I/O Error(%2d): 0x%04X\n", TextHdr, pdn->busno, pdn->devfn, @@ -704,7 +654,6 @@ u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress) return 0xff; } do { - ++Pci_Io_Read_Count; HvCall3Ret16(HvCallPciBarLoad8, &ret, dsa, BarOffset, 0); } while (CheckReturnCode("RDB", DevNode, &retry, ret.rc) != 0); @@ -734,7 +683,6 @@ u16 iSeries_Read_Word(const volatile void __iomem *IoAddress) return 0xffff; } do { - ++Pci_Io_Read_Count; HvCall3Ret16(HvCallPciBarLoad16, &ret, dsa, BarOffset, 0); } while (CheckReturnCode("RDW", DevNode, &retry, ret.rc) != 0); @@ -765,7 +713,6 @@ u32 iSeries_Read_Long(const volatile void __iomem *IoAddress) return 0xffffffff; } do { - ++Pci_Io_Read_Count; HvCall3Ret16(HvCallPciBarLoad32, &ret, dsa, BarOffset, 0); } while (CheckReturnCode("RDL", DevNode, &retry, ret.rc) != 0); @@ -803,7 +750,6 @@ void iSeries_Write_Byte(u8 data, volatile void __iomem *IoAddress) return; } do { - ++Pci_Io_Write_Count; rc = HvCall4(HvCallPciBarStore8, dsa, BarOffset, data, 0); } while (CheckReturnCode("WWB", DevNode, &retry, rc) != 0); } @@ -831,7 +777,6 @@ void iSeries_Write_Word(u16 data, volatile void __iomem *IoAddress) return; } do { - ++Pci_Io_Write_Count; rc = HvCall4(HvCallPciBarStore16, dsa, BarOffset, swab16(data), 0); } while (CheckReturnCode("WWW", DevNode, &retry, rc) != 0); } @@ -859,7 +804,6 @@ void iSeries_Write_Long(u32 data, volatile void __iomem *IoAddress) return; } do { - ++Pci_Io_Write_Count; rc = HvCall4(HvCallPciBarStore32, dsa, BarOffset, swab32(data), 0); } while (CheckReturnCode("WWL", DevNode, &retry, rc) != 0); } -- cgit v1.2.3 From 66b3851a6947482987b4c05aa781a33696287648 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Fri, 19 May 2006 16:43:58 +1000 Subject: [PATCH] powerpc: reintroduce HvCallPci_configLoad32 This function was removed during iSeries cleanup but will prove useful in the following patches. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/call_pci.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/arch/powerpc/platforms/iseries/call_pci.h b/arch/powerpc/platforms/iseries/call_pci.h index 59d4e0ad5cf..dbdf69850ed 100644 --- a/arch/powerpc/platforms/iseries/call_pci.h +++ b/arch/powerpc/platforms/iseries/call_pci.h @@ -145,6 +145,25 @@ static inline u64 HvCallPci_configLoad16(u16 busNumber, u8 subBusNumber, return retVal.rc; } +static inline u64 HvCallPci_configLoad32(u16 busNumber, u8 subBusNumber, + u8 deviceId, u32 offset, u32 *value) +{ + struct HvCallPci_DsaAddr dsa; + struct HvCallPci_LoadReturn retVal; + + *((u64*)&dsa) = 0; + + dsa.busNumber = busNumber; + dsa.subBusNumber = subBusNumber; + dsa.deviceId = deviceId; + + HvCall3Ret16(HvCallPciConfigLoad32, &retVal, *(u64 *)&dsa, offset, 0); + + *value = retVal.value; + + return retVal.rc; +} + static inline u64 HvCallPci_configStore8(u16 busNumber, u8 subBusNumber, u8 deviceId, u32 offset, u8 value) { -- cgit v1.2.3 From 0d177df15d12926dc2ef7c814f317f02de52ce17 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Fri, 19 May 2006 16:46:28 +1000 Subject: [PATCH] powerpc: move iSeries PCI devices to the device tree Move the probing of PCI devices to setup.c and put them all into the flattened device tree. The later probing is now done by traversing the device tree. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/irq.c | 7 +- arch/powerpc/platforms/iseries/irq.h | 2 +- arch/powerpc/platforms/iseries/pci.c | 273 ++++++++++----------------------- arch/powerpc/platforms/iseries/setup.c | 204 ++++++++++++++++++++++++ 4 files changed, 286 insertions(+), 200 deletions(-) diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c index be3fbfc24e6..62bbbcf5ded 100644 --- a/arch/powerpc/platforms/iseries/irq.c +++ b/arch/powerpc/platforms/iseries/irq.c @@ -42,6 +42,7 @@ #include #include "irq.h" +#include "pci.h" #include "call_pci.h" #if defined(CONFIG_SMP) @@ -312,12 +313,12 @@ static hw_irq_controller iSeries_IRQ_handler = { * Note that sub_bus is always 0 (at the moment at least). */ int __init iSeries_allocate_IRQ(HvBusNumber bus, - HvSubBusNumber sub_bus, HvAgentId dev_id) + HvSubBusNumber sub_bus, u32 bsubbus) { int virtirq; unsigned int realirq; - u8 idsel = (dev_id >> 4); - u8 function = dev_id & 7; + u8 idsel = ISERIES_GET_DEVICE_FROM_SUBBUS(bsubbus); + u8 function = ISERIES_GET_FUNCTION_FROM_SUBBUS(bsubbus); realirq = (((((sub_bus << 8) + (bus - 1)) << 3) + (idsel - 1)) << 3) + function; diff --git a/arch/powerpc/platforms/iseries/irq.h b/arch/powerpc/platforms/iseries/irq.h index b9c801ba5a4..188aa808abd 100644 --- a/arch/powerpc/platforms/iseries/irq.h +++ b/arch/powerpc/platforms/iseries/irq.h @@ -2,7 +2,7 @@ #define _ISERIES_IRQ_H extern void iSeries_init_IRQ(void); -extern int iSeries_allocate_IRQ(HvBusNumber, HvSubBusNumber, HvAgentId); +extern int iSeries_allocate_IRQ(HvBusNumber, HvSubBusNumber, u32); extern void iSeries_activate_IRQs(void); extern int iSeries_get_irq(struct pt_regs *); diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c index 91a94747eda..9d571e74909 100644 --- a/arch/powerpc/platforms/iseries/pci.c +++ b/arch/powerpc/platforms/iseries/pci.c @@ -49,14 +49,9 @@ * Forward declares of prototypes. */ static struct device_node *find_Device_Node(int bus, int devfn); -static void scan_PHB_slots(struct pci_controller *Phb); -static void scan_EADS_bridge(HvBusNumber Bus, HvSubBusNumber SubBus, int IdSel); -static int scan_bridge_slot(HvBusNumber Bus, struct HvCallPci_BridgeInfo *Info); LIST_HEAD(iSeries_Global_Device_List); -static int DeviceCount; - static int Pci_Retry_Max = 3; /* Only retry 3 times */ static int Pci_Error_Flag = 1; /* Set Retry Error on. */ @@ -161,32 +156,6 @@ static void pci_Log_Error(char *Error_Text, int Bus, int SubBus, Error_Text, Bus, SubBus, AgentId, HvRc); } -/* - * build_device_node(u16 Bus, int SubBus, u8 DevFn) - */ -static struct device_node *build_device_node(HvBusNumber Bus, - HvSubBusNumber SubBus, int AgentId, int Function) -{ - struct device_node *node; - struct pci_dn *pdn; - - node = kzalloc(sizeof(struct device_node), GFP_KERNEL); - if (node == NULL) - return NULL; - pdn = kzalloc(sizeof(*pdn), GFP_KERNEL); - if (pdn == NULL) { - kfree(node); - return NULL; - } - node->data = pdn; - pdn->node = node; - list_add_tail(&pdn->Device_List, &iSeries_Global_Device_List); - pdn->busno = Bus; - pdn->bussubno = SubBus; - pdn->devfn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(AgentId), Function); - return node; -} - /* * iSeries_pcibios_init * @@ -199,33 +168,86 @@ static struct device_node *build_device_node(HvBusNumber Bus, void iSeries_pcibios_init(void) { struct pci_controller *phb; - HvBusNumber bus; - - /* Check all possible buses. */ - for (bus = 0; bus < 256; bus++) { - int ret = HvCallXm_testBus(bus); - if (ret == 0) { - printk("bus %d appears to exist\n", bus); - - phb = pcibios_alloc_controller(NULL); - if (phb == NULL) - return -ENOMEM; + struct device_node *node; + struct device_node *dn; + + for_each_node_by_type(node, "pci") { + HvBusNumber bus; + u32 *busp; + + busp = (u32 *)get_property(node, "bus-range", NULL); + if (busp == NULL) + continue; + bus = *busp; + printk("bus %d appears to exist\n", bus); + phb = pcibios_alloc_controller(node); + if (phb == NULL) + continue; + + phb->pci_mem_offset = phb->local_number = bus; + phb->first_busno = bus; + phb->last_busno = bus; + phb->ops = &iSeries_pci_ops; + + /* Find and connect the devices. */ + for (dn = NULL; (dn = of_get_next_child(node, dn)) != NULL;) { + struct pci_dn *pdn; + u8 irq; + int err; + u32 *agent; + u32 *reg; + u32 *lsn; + + reg = (u32 *)get_property(dn, "reg", NULL); + if (reg == NULL) { + printk(KERN_DEBUG "no reg property!\n"); + continue; + } + busp = (u32 *)get_property(dn, "linux,subbus", NULL); + if (busp == NULL) { + printk(KERN_DEBUG "no subbus property!\n"); + continue; + } + agent = (u32 *)get_property(dn, "linux,agent-id", NULL); + if (agent == NULL) { + printk(KERN_DEBUG "no agent-id\n"); + continue; + } + lsn = (u32 *)get_property(dn, + "linux,logical-slot-number", NULL); + if (lsn == NULL) { + printk(KERN_DEBUG "no logical-slot-number\n"); + continue; + } - phb->pci_mem_offset = phb->local_number = bus; - phb->first_busno = bus; - phb->last_busno = bus; - phb->ops = &iSeries_pci_ops; + irq = iSeries_allocate_IRQ(bus, 0, *busp); + err = HvCallXm_connectBusUnit(bus, *busp, *agent, irq); + if (err) { + pci_Log_Error("Connect Bus Unit", + bus, *busp, *agent, err); + continue; + } + err = HvCallPci_configStore8(bus, *busp, *agent, + PCI_INTERRUPT_LINE, irq); + if (err) { + pci_Log_Error("PciCfgStore Irq Failed!", + bus, *busp, *agent, err); + continue; + } - /* Find and connect the devices. */ - scan_PHB_slots(phb); + pdn = kzalloc(sizeof(*pdn), GFP_KERNEL); + if (pdn == NULL) + return; + dn->data = pdn; + pdn->node = dn; + pdn->busno = bus; + pdn->devfn = (reg[0] >> 8) & 0xff; + pdn->bussubno = *busp; + pdn->Irq = irq; + pdn->LogicalSlot = *lsn; + list_add_tail(&pdn->Device_List, + &iSeries_Global_Device_List); } - /* - * Check for Unexpected Return code, a clue that something - * has gone wrong. - */ - else if (ret != 0x0301) - printk(KERN_ERR "Unexpected Return on Probe(0x%04X): 0x%04X", - bus, ret); } } @@ -271,147 +293,6 @@ void pcibios_fixup_resources(struct pci_dev *pdev) { } -/* - * Loop through each node function to find usable EADs bridges. - */ -static void scan_PHB_slots(struct pci_controller *Phb) -{ - struct HvCallPci_DeviceInfo *DevInfo; - HvBusNumber bus = Phb->local_number; /* System Bus */ - const HvSubBusNumber SubBus = 0; /* EADs is always 0. */ - int HvRc = 0; - int IdSel; - const int MaxAgents = 8; - - DevInfo = kmalloc(sizeof(struct HvCallPci_DeviceInfo), GFP_KERNEL); - if (DevInfo == NULL) - return; - - /* - * Probe for EADs Bridges - */ - for (IdSel = 1; IdSel < MaxAgents; ++IdSel) { - HvRc = HvCallPci_getDeviceInfo(bus, SubBus, IdSel, - iseries_hv_addr(DevInfo), - sizeof(struct HvCallPci_DeviceInfo)); - if (HvRc == 0) { - if (DevInfo->deviceType == HvCallPci_NodeDevice) - scan_EADS_bridge(bus, SubBus, IdSel); - else - printk("PCI: Invalid System Configuration(0x%02X)" - " for bus 0x%02x id 0x%02x.\n", - DevInfo->deviceType, bus, IdSel); - } - else - pci_Log_Error("getDeviceInfo", bus, SubBus, IdSel, HvRc); - } - kfree(DevInfo); -} - -static void scan_EADS_bridge(HvBusNumber bus, HvSubBusNumber SubBus, - int IdSel) -{ - struct HvCallPci_BridgeInfo *BridgeInfo; - HvAgentId AgentId; - int Function; - int HvRc; - - BridgeInfo = (struct HvCallPci_BridgeInfo *) - kmalloc(sizeof(struct HvCallPci_BridgeInfo), GFP_KERNEL); - if (BridgeInfo == NULL) - return; - - /* Note: hvSubBus and irq is always be 0 at this level! */ - for (Function = 0; Function < 8; ++Function) { - AgentId = ISERIES_PCI_AGENTID(IdSel, Function); - HvRc = HvCallXm_connectBusUnit(bus, SubBus, AgentId, 0); - if (HvRc == 0) { - printk("found device at bus %d idsel %d func %d (AgentId %x)\n", - bus, IdSel, Function, AgentId); - /* Connect EADs: 0x18.00.12 = 0x00 */ - HvRc = HvCallPci_getBusUnitInfo(bus, SubBus, AgentId, - iseries_hv_addr(BridgeInfo), - sizeof(struct HvCallPci_BridgeInfo)); - if (HvRc == 0) { - printk("bridge info: type %x subbus %x maxAgents %x maxsubbus %x logslot %x\n", - BridgeInfo->busUnitInfo.deviceType, - BridgeInfo->subBusNumber, - BridgeInfo->maxAgents, - BridgeInfo->maxSubBusNumber, - BridgeInfo->logicalSlotNumber); - if (BridgeInfo->busUnitInfo.deviceType == - HvCallPci_BridgeDevice) { - /* Scan_Bridge_Slot...: 0x18.00.12 */ - scan_bridge_slot(bus, BridgeInfo); - } else - printk("PCI: Invalid Bridge Configuration(0x%02X)", - BridgeInfo->busUnitInfo.deviceType); - } - } else if (HvRc != 0x000B) - pci_Log_Error("EADs Connect", - bus, SubBus, AgentId, HvRc); - } - kfree(BridgeInfo); -} - -/* - * This assumes that the node slot is always on the primary bus! - */ -static int scan_bridge_slot(HvBusNumber Bus, - struct HvCallPci_BridgeInfo *BridgeInfo) -{ - struct device_node *node; - HvSubBusNumber SubBus = BridgeInfo->subBusNumber; - u16 VendorId = 0; - int HvRc = 0; - u8 Irq = 0; - int IdSel = ISERIES_GET_DEVICE_FROM_SUBBUS(SubBus); - int Function = ISERIES_GET_FUNCTION_FROM_SUBBUS(SubBus); - HvAgentId EADsIdSel = ISERIES_PCI_AGENTID(IdSel, Function); - - /* iSeries_allocate_IRQ.: 0x18.00.12(0xA3) */ - Irq = iSeries_allocate_IRQ(Bus, 0, EADsIdSel); - - /* - * Connect all functions of any device found. - */ - for (IdSel = 1; IdSel <= BridgeInfo->maxAgents; ++IdSel) { - for (Function = 0; Function < 8; ++Function) { - HvAgentId AgentId = ISERIES_PCI_AGENTID(IdSel, Function); - HvRc = HvCallXm_connectBusUnit(Bus, SubBus, - AgentId, Irq); - if (HvRc != 0) { - pci_Log_Error("Connect Bus Unit", - Bus, SubBus, AgentId, HvRc); - continue; - } - - HvRc = HvCallPci_configLoad16(Bus, SubBus, AgentId, - PCI_VENDOR_ID, &VendorId); - if (HvRc != 0) { - pci_Log_Error("Read Vendor", - Bus, SubBus, AgentId, HvRc); - continue; - } - printk("read vendor ID: %x\n", VendorId); - - /* FoundDevice: 0x18.28.10 = 0x12AE */ - HvRc = HvCallPci_configStore8(Bus, SubBus, AgentId, - PCI_INTERRUPT_LINE, Irq); - if (HvRc != 0) - pci_Log_Error("PciCfgStore Irq Failed!", - Bus, SubBus, AgentId, HvRc); - - ++DeviceCount; - node = build_device_node(Bus, SubBus, EADsIdSel, Function); - PCI_DN(node)->Irq = Irq; - PCI_DN(node)->LogicalSlot = BridgeInfo->logicalSlotNumber; - - } /* for (Function = 0; Function < 8; ++Function) */ - } /* for (IdSel = 1; IdSel <= MaxAgents; ++IdSel) */ - return HvRc; -} - /* * I/0 Memory copy MUST use mmio commands on iSeries * To do; For performance, include the hv call directly diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index fd6d0ebe8dd..d83f5ed4ec1 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -66,6 +66,8 @@ #include "main_store.h" #include "call_sm.h" #include "call_hpt.h" +#include "call_pci.h" +#include "pci.h" #ifdef DEBUG #define DBG(fmt...) udbg_printf(fmt) @@ -1000,6 +1002,207 @@ void dt_vdevices(struct iseries_flat_dt *dt) dt_end_node(dt); } +/* + * This assumes that the node slot is always on the primary bus! + */ +static void scan_bridge_slot(struct iseries_flat_dt *dt, HvBusNumber bus, + struct HvCallPci_BridgeInfo *bridge_info) +{ + HvSubBusNumber sub_bus = bridge_info->subBusNumber; + u16 vendor_id; + u16 device_id; + u32 class_id; + int err; + char buf[32]; + u32 reg[5]; + int id_sel = ISERIES_GET_DEVICE_FROM_SUBBUS(sub_bus); + int function = ISERIES_GET_FUNCTION_FROM_SUBBUS(sub_bus); + HvAgentId eads_id_sel = ISERIES_PCI_AGENTID(id_sel, function); + + /* + * Connect all functions of any device found. + */ + for (id_sel = 1; id_sel <= bridge_info->maxAgents; id_sel++) { + for (function = 0; function < 8; function++) { + u8 devfn; + + HvAgentId agent_id = ISERIES_PCI_AGENTID(id_sel, + function); + err = HvCallXm_connectBusUnit(bus, sub_bus, + agent_id, 0); + if (err) { + if (err != 0x302) + printk(KERN_DEBUG + "connectBusUnit(%x, %x, %x) " + "== %x\n", + bus, sub_bus, agent_id, err); + continue; + } + + err = HvCallPci_configLoad16(bus, sub_bus, agent_id, + PCI_VENDOR_ID, &vendor_id); + if (err) { + printk(KERN_DEBUG + "ReadVendor(%x, %x, %x) == %x\n", + bus, sub_bus, agent_id, err); + continue; + } + err = HvCallPci_configLoad16(bus, sub_bus, agent_id, + PCI_DEVICE_ID, &device_id); + if (err) { + printk(KERN_DEBUG + "ReadDevice(%x, %x, %x) == %x\n", + bus, sub_bus, agent_id, err); + continue; + } + err = HvCallPci_configLoad32(bus, sub_bus, agent_id, + PCI_CLASS_REVISION , &class_id); + if (err) { + printk(KERN_DEBUG + "ReadClass(%x, %x, %x) == %x\n", + bus, sub_bus, agent_id, err); + continue; + } + + devfn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(eads_id_sel), + function); + if (function == 0) + snprintf(buf, sizeof(buf), "pci@%x", + PCI_SLOT(devfn)); + else + snprintf(buf, sizeof(buf), "pci@%x,%d", + PCI_SLOT(devfn), function); + dt_start_node(dt, buf); + reg[0] = (bus << 18) | (devfn << 8); + reg[1] = 0; + reg[2] = 0; + reg[3] = 0; + reg[4] = 0; + dt_prop_u32_list(dt, "reg", reg, 5); + dt_prop_u32(dt, "vendor-id", vendor_id); + dt_prop_u32(dt, "device-id", device_id); + dt_prop_u32(dt, "class-code", class_id >> 8); + dt_prop_u32(dt, "revision-id", class_id & 0xff); + dt_prop_u32(dt, "linux,subbus", sub_bus); + dt_prop_u32(dt, "linux,agent-id", agent_id); + dt_prop_u32(dt, "linux,logical-slot-number", + bridge_info->logicalSlotNumber); + dt_end_node(dt); + + } + } +} + +static void scan_bridge(struct iseries_flat_dt *dt, HvBusNumber bus, + HvSubBusNumber sub_bus, int id_sel) +{ + struct HvCallPci_BridgeInfo bridge_info; + HvAgentId agent_id; + int function; + int ret; + + /* Note: hvSubBus and irq is always be 0 at this level! */ + for (function = 0; function < 8; ++function) { + agent_id = ISERIES_PCI_AGENTID(id_sel, function); + ret = HvCallXm_connectBusUnit(bus, sub_bus, agent_id, 0); + if (ret != 0) { + if (ret != 0xb) + printk(KERN_DEBUG "connectBusUnit(%x, %x, %x) " + "== %x\n", + bus, sub_bus, agent_id, ret); + continue; + } + printk("found device at bus %d idsel %d func %d (AgentId %x)\n", + bus, id_sel, function, agent_id); + ret = HvCallPci_getBusUnitInfo(bus, sub_bus, agent_id, + iseries_hv_addr(&bridge_info), + sizeof(struct HvCallPci_BridgeInfo)); + if (ret != 0) + continue; + printk("bridge info: type %x subbus %x " + "maxAgents %x maxsubbus %x logslot %x\n", + bridge_info.busUnitInfo.deviceType, + bridge_info.subBusNumber, + bridge_info.maxAgents, + bridge_info.maxSubBusNumber, + bridge_info.logicalSlotNumber); + if (bridge_info.busUnitInfo.deviceType == + HvCallPci_BridgeDevice) + scan_bridge_slot(dt, bus, &bridge_info); + else + printk("PCI: Invalid Bridge Configuration(0x%02X)", + bridge_info.busUnitInfo.deviceType); + } +} + +static void scan_phb(struct iseries_flat_dt *dt, HvBusNumber bus) +{ + struct HvCallPci_DeviceInfo dev_info; + const HvSubBusNumber sub_bus = 0; /* EADs is always 0. */ + int err; + int id_sel; + const int max_agents = 8; + + /* + * Probe for EADs Bridges + */ + for (id_sel = 1; id_sel < max_agents; ++id_sel) { + err = HvCallPci_getDeviceInfo(bus, sub_bus, id_sel, + iseries_hv_addr(&dev_info), + sizeof(struct HvCallPci_DeviceInfo)); + if (err) { + if (err != 0x302) + printk(KERN_DEBUG "getDeviceInfo(%x, %x, %x) " + "== %x\n", + bus, sub_bus, id_sel, err); + continue; + } + if (dev_info.deviceType != HvCallPci_NodeDevice) { + printk(KERN_DEBUG "PCI: Invalid System Configuration" + "(0x%02X) for bus 0x%02x id 0x%02x.\n", + dev_info.deviceType, bus, id_sel); + continue; + } + scan_bridge(dt, bus, sub_bus, id_sel); + } +} + +static void dt_pci_devices(struct iseries_flat_dt *dt) +{ + HvBusNumber bus; + char buf[32]; + u32 buses[2]; + int phb_num = 0; + + /* Check all possible buses. */ + for (bus = 0; bus < 256; bus++) { + int err = HvCallXm_testBus(bus); + + if (err) { + /* + * Check for Unexpected Return code, a clue that + * something has gone wrong. + */ + if (err != 0x0301) + printk(KERN_ERR "Unexpected Return on Probe" + "(0x%02X): 0x%04X", bus, err); + continue; + } + printk("bus %d appears to exist\n", bus); + snprintf(buf, 32, "pci@%d", phb_num); + dt_start_node(dt, buf); + dt_prop_str(dt, "device_type", "pci"); + dt_prop_str(dt, "compatible", "IBM,iSeries-Logical-PHB"); + dt_prop_u32(dt, "#address-cells", 3); + dt_prop_u32(dt, "#size-cells", 2); + buses[0] = buses[1] = bus; + dt_prop_u32_list(dt, "bus-range", buses, 2); + scan_phb(dt, bus); + dt_end_node(dt); + phb_num++; + } +} + void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size) { u64 tmp[2]; @@ -1029,6 +1232,7 @@ void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size) dt_cpus(dt); dt_vdevices(dt); + dt_pci_devices(dt); dt_end_node(dt); -- cgit v1.2.3 From 96ff6afaf1c2fdd118139095dea66c0910379780 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Fri, 19 May 2006 16:48:47 +1000 Subject: [PATCH] powerpc: remove iSeries_Global_Device_List We can now scan the list of device nodes instead. This also allows us to remove the Device_list member of struct pci_dn. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/iommu.c | 15 +++++++++------ arch/powerpc/platforms/iseries/pci.c | 14 ++++++-------- include/asm-powerpc/pci-bridge.h | 1 - 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c index 3ac22065c42..75a5a1e8abb 100644 --- a/arch/powerpc/platforms/iseries/iommu.c +++ b/arch/powerpc/platforms/iseries/iommu.c @@ -32,13 +32,11 @@ #include #include #include +#include #include #include #include -extern struct list_head iSeries_Global_Device_List; - - static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages, unsigned long uaddr, enum dma_data_direction direction) { @@ -140,10 +138,15 @@ void iommu_table_getparms_iSeries(unsigned long busno, */ static struct iommu_table *iommu_table_find(struct iommu_table * tbl) { - struct pci_dn *pdn; + struct device_node *node; + + for (node = NULL; (node = of_find_all_nodes(node)); ) { + struct pci_dn *pdn = PCI_DN(node); + struct iommu_table *it; - list_for_each_entry(pdn, &iSeries_Global_Device_List, Device_List) { - struct iommu_table *it = pdn->iommu_table; + if (pdn == NULL) + continue; + it = pdn->iommu_table; if ((it != NULL) && (it->it_type == TCE_PCI) && (it->it_offset == tbl->it_offset) && diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c index 9d571e74909..5bc08d4eef4 100644 --- a/arch/powerpc/platforms/iseries/pci.c +++ b/arch/powerpc/platforms/iseries/pci.c @@ -50,8 +50,6 @@ */ static struct device_node *find_Device_Node(int bus, int devfn); -LIST_HEAD(iSeries_Global_Device_List); - static int Pci_Retry_Max = 3; /* Only retry 3 times */ static int Pci_Error_Flag = 1; /* Set Retry Error on. */ @@ -245,8 +243,6 @@ void iSeries_pcibios_init(void) pdn->bussubno = *busp; pdn->Irq = irq; pdn->LogicalSlot = *lsn; - list_add_tail(&pdn->Device_List, - &iSeries_Global_Device_List); } } } @@ -338,11 +334,13 @@ EXPORT_SYMBOL(iSeries_memcpy_fromio); */ static struct device_node *find_Device_Node(int bus, int devfn) { - struct pci_dn *pdn; + struct device_node *node; + + for (node = NULL; (node = of_find_all_nodes(node)); ) { + struct pci_dn *pdn = PCI_DN(node); - list_for_each_entry(pdn, &iSeries_Global_Device_List, Device_List) { - if ((bus == pdn->busno) && (devfn == pdn->devfn)) - return pdn->node; + if (pdn && (bus == pdn->busno) && (devfn == pdn->devfn)) + return node; } return NULL; } diff --git a/include/asm-powerpc/pci-bridge.h b/include/asm-powerpc/pci-bridge.h index 38de92d41a1..59794b466ef 100644 --- a/include/asm-powerpc/pci-bridge.h +++ b/include/asm-powerpc/pci-bridge.h @@ -79,7 +79,6 @@ struct pci_dn { struct pci_dev *pcidev; /* back-pointer to the pci device */ struct device_node *node; /* back-pointer to the device_node */ #ifdef CONFIG_PPC_ISERIES - struct list_head Device_List; int Irq; /* Assigned IRQ */ int Flags; /* Possible flags(disable/bist)*/ u8 LogicalSlot; /* Hv Slot Index for Tces */ -- cgit v1.2.3 From b02527931672749d404b5f640b7e086afc37f4e0 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Fri, 19 May 2006 16:50:39 +1000 Subject: [PATCH] powerpc: remove Irq from pci_dn As we now store enough information in the device_node to allocate the irq number in pcibios_final_fixup. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/pci.c | 53 +++++++++++++++++++----------------- include/asm-powerpc/pci-bridge.h | 1 - 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c index 5bc08d4eef4..edaafbb817b 100644 --- a/arch/powerpc/platforms/iseries/pci.c +++ b/arch/powerpc/platforms/iseries/pci.c @@ -190,9 +190,6 @@ void iSeries_pcibios_init(void) /* Find and connect the devices. */ for (dn = NULL; (dn = of_get_next_child(node, dn)) != NULL;) { struct pci_dn *pdn; - u8 irq; - int err; - u32 *agent; u32 *reg; u32 *lsn; @@ -206,11 +203,6 @@ void iSeries_pcibios_init(void) printk(KERN_DEBUG "no subbus property!\n"); continue; } - agent = (u32 *)get_property(dn, "linux,agent-id", NULL); - if (agent == NULL) { - printk(KERN_DEBUG "no agent-id\n"); - continue; - } lsn = (u32 *)get_property(dn, "linux,logical-slot-number", NULL); if (lsn == NULL) { @@ -218,21 +210,6 @@ void iSeries_pcibios_init(void) continue; } - irq = iSeries_allocate_IRQ(bus, 0, *busp); - err = HvCallXm_connectBusUnit(bus, *busp, *agent, irq); - if (err) { - pci_Log_Error("Connect Bus Unit", - bus, *busp, *agent, err); - continue; - } - err = HvCallPci_configStore8(bus, *busp, *agent, - PCI_INTERRUPT_LINE, irq); - if (err) { - pci_Log_Error("PciCfgStore Irq Failed!", - bus, *busp, *agent, err); - continue; - } - pdn = kzalloc(sizeof(*pdn), GFP_KERNEL); if (pdn == NULL) return; @@ -241,7 +218,6 @@ void iSeries_pcibios_init(void) pdn->busno = bus; pdn->devfn = (reg[0] >> 8) & 0xff; pdn->bussubno = *busp; - pdn->Irq = irq; pdn->LogicalSlot = *lsn; } } @@ -266,6 +242,34 @@ void __init iSeries_pci_final_fixup(void) pdev->bus->number, pdev->devfn, node); if (node != NULL) { + struct pci_dn *pdn = PCI_DN(node); + u32 *agent; + + agent = (u32 *)get_property(node, "linux,agent-id", + NULL); + if ((pdn != NULL) && (agent != NULL)) { + u8 irq = iSeries_allocate_IRQ(pdn->busno, 0, + pdn->bussubno); + int err; + + err = HvCallXm_connectBusUnit(pdn->busno, pdn->bussubno, + *agent, irq); + if (err) + pci_Log_Error("Connect Bus Unit", + pdn->busno, pdn->bussubno, *agent, err); + else { + err = HvCallPci_configStore8(pdn->busno, pdn->bussubno, + *agent, + PCI_INTERRUPT_LINE, + irq); + if (err) + pci_Log_Error("PciCfgStore Irq Failed!", + pdn->busno, pdn->bussubno, *agent, err); + } + if (!err) + pdev->irq = irq; + } + ++DeviceCount; pdev->sysdata = (void *)node; PCI_DN(node)->pcidev = pdev; @@ -275,7 +279,6 @@ void __init iSeries_pci_final_fixup(void) } else printk("PCI: Device Tree not found for 0x%016lX\n", (unsigned long)pdev); - pdev->irq = PCI_DN(node)->Irq; } iSeries_activate_IRQs(); mf_display_src(0xC9000200); diff --git a/include/asm-powerpc/pci-bridge.h b/include/asm-powerpc/pci-bridge.h index 59794b466ef..09079e400d2 100644 --- a/include/asm-powerpc/pci-bridge.h +++ b/include/asm-powerpc/pci-bridge.h @@ -79,7 +79,6 @@ struct pci_dn { struct pci_dev *pcidev; /* back-pointer to the pci device */ struct device_node *node; /* back-pointer to the device_node */ #ifdef CONFIG_PPC_ISERIES - int Irq; /* Assigned IRQ */ int Flags; /* Possible flags(disable/bist)*/ u8 LogicalSlot; /* Hv Slot Index for Tces */ #endif -- cgit v1.2.3 From 403fac4f83bd8e089a192c542511fbeb2729a6c5 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Fri, 19 May 2006 16:51:57 +1000 Subject: [PATCH] powerpc: remove LogicalSlot from pci_dn As we now store enough information in the device_node. Also the Flags field was not used either, do remove that. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/iommu.c | 5 ++++- arch/powerpc/platforms/iseries/pci.c | 8 -------- include/asm-powerpc/pci-bridge.h | 4 ---- 3 files changed, 4 insertions(+), 13 deletions(-) diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c index 75a5a1e8abb..a992f6af249 100644 --- a/arch/powerpc/platforms/iseries/iommu.c +++ b/arch/powerpc/platforms/iseries/iommu.c @@ -162,10 +162,13 @@ void iommu_devnode_init_iSeries(struct device_node *dn) { struct iommu_table *tbl; struct pci_dn *pdn = PCI_DN(dn); + u32 *lsn = (u32 *)get_property(dn, "linux,logical-slot-number", NULL); + + BUG_ON(lsn == NULL); tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); - iommu_table_getparms_iSeries(pdn->busno, pdn->LogicalSlot, 0, tbl); + iommu_table_getparms_iSeries(pdn->busno, *lsn, 0, tbl); /* Look for existing tce table */ pdn->iommu_table = iommu_table_find(tbl); diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c index edaafbb817b..86a869839d3 100644 --- a/arch/powerpc/platforms/iseries/pci.c +++ b/arch/powerpc/platforms/iseries/pci.c @@ -191,7 +191,6 @@ void iSeries_pcibios_init(void) for (dn = NULL; (dn = of_get_next_child(node, dn)) != NULL;) { struct pci_dn *pdn; u32 *reg; - u32 *lsn; reg = (u32 *)get_property(dn, "reg", NULL); if (reg == NULL) { @@ -203,12 +202,6 @@ void iSeries_pcibios_init(void) printk(KERN_DEBUG "no subbus property!\n"); continue; } - lsn = (u32 *)get_property(dn, - "linux,logical-slot-number", NULL); - if (lsn == NULL) { - printk(KERN_DEBUG "no logical-slot-number\n"); - continue; - } pdn = kzalloc(sizeof(*pdn), GFP_KERNEL); if (pdn == NULL) @@ -218,7 +211,6 @@ void iSeries_pcibios_init(void) pdn->busno = bus; pdn->devfn = (reg[0] >> 8) & 0xff; pdn->bussubno = *busp; - pdn->LogicalSlot = *lsn; } } } diff --git a/include/asm-powerpc/pci-bridge.h b/include/asm-powerpc/pci-bridge.h index 09079e400d2..84a3075db52 100644 --- a/include/asm-powerpc/pci-bridge.h +++ b/include/asm-powerpc/pci-bridge.h @@ -78,10 +78,6 @@ struct pci_dn { struct iommu_table *iommu_table; /* for phb's or bridges */ struct pci_dev *pcidev; /* back-pointer to the pci device */ struct device_node *node; /* back-pointer to the device_node */ -#ifdef CONFIG_PPC_ISERIES - int Flags; /* Possible flags(disable/bist)*/ - u8 LogicalSlot; /* Hv Slot Index for Tces */ -#endif u32 config_space[16]; /* saved PCI config space */ }; -- cgit v1.2.3 From efbd386967aaa7fcf7ffbb13e4975df1cdf04cb8 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Fri, 19 May 2006 16:53:11 +1000 Subject: [PATCH] powerpc: iSeries PCI devices can now have a devpsec attribute Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/pci_64.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index e1b3b3ef191..30a4e6a1368 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -886,8 +886,8 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, return ret; } -#ifdef CONFIG_PPC_MULTIPLATFORM -static ssize_t pci_show_devspec(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t pci_show_devspec(struct device *dev, + struct device_attribute *attr, char *buf) { struct pci_dev *pdev; struct device_node *np; @@ -899,13 +899,10 @@ static ssize_t pci_show_devspec(struct device *dev, struct device_attribute *att return sprintf(buf, "%s", np->full_name); } static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL); -#endif /* CONFIG_PPC_MULTIPLATFORM */ void pcibios_add_platform_entries(struct pci_dev *pdev) { -#ifdef CONFIG_PPC_MULTIPLATFORM device_create_file(&pdev->dev, &dev_attr_devspec); -#endif /* CONFIG_PPC_MULTIPLATFORM */ } #ifdef CONFIG_PPC_MULTIPLATFORM -- cgit v1.2.3 From 095eed4f8d0be13a7934031434b6e9ceddb87ff6 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Fri, 19 May 2006 16:54:42 +1000 Subject: [PATCH] powerpc: clean up iSeries PCI probe Only scan the host bridges and then use the existing pci_devs_phb_init() routine. Also fix typo in setup of reg property. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/pci_dn.c | 6 +++++ arch/powerpc/platforms/iseries/pci.c | 42 ++++++++++++---------------------- arch/powerpc/platforms/iseries/setup.c | 2 +- 3 files changed, 21 insertions(+), 29 deletions(-) diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c index 12c4c9e9bbc..1c18953514c 100644 --- a/arch/powerpc/kernel/pci_dn.c +++ b/arch/powerpc/kernel/pci_dn.c @@ -31,6 +31,7 @@ #include #include #include +#include /* * Traverse_func that inits the PCI fields of the device node. @@ -59,6 +60,11 @@ static void * __devinit update_dn_pci_info(struct device_node *dn, void *data) pdn->busno = (regs[0] >> 16) & 0xff; pdn->devfn = (regs[0] >> 8) & 0xff; } + if (firmware_has_feature(FW_FEATURE_ISERIES)) { + u32 *busp = (u32 *)get_property(dn, "linux,subbus", NULL); + if (busp) + pdn->bussubno = *busp; + } pdn->pci_ext_config_space = (type && *type == 1); return NULL; diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c index 86a869839d3..35bcc98111f 100644 --- a/arch/powerpc/platforms/iseries/pci.c +++ b/arch/powerpc/platforms/iseries/pci.c @@ -166,13 +166,21 @@ static void pci_Log_Error(char *Error_Text, int Bus, int SubBus, void iSeries_pcibios_init(void) { struct pci_controller *phb; - struct device_node *node; - struct device_node *dn; + struct device_node *root = of_find_node_by_path("/"); + struct device_node *node = NULL; - for_each_node_by_type(node, "pci") { + if (root == NULL) { + printk(KERN_CRIT "iSeries_pcibios_init: can't find root " + "of device tree\n"); + return; + } + while ((node = of_get_next_child(root, node)) != NULL) { HvBusNumber bus; u32 *busp; + if ((node->type == NULL) || (strcmp(node->type, "pci") != 0)) + continue; + busp = (u32 *)get_property(node, "bus-range", NULL); if (busp == NULL) continue; @@ -186,33 +194,11 @@ void iSeries_pcibios_init(void) phb->first_busno = bus; phb->last_busno = bus; phb->ops = &iSeries_pci_ops; + } - /* Find and connect the devices. */ - for (dn = NULL; (dn = of_get_next_child(node, dn)) != NULL;) { - struct pci_dn *pdn; - u32 *reg; - - reg = (u32 *)get_property(dn, "reg", NULL); - if (reg == NULL) { - printk(KERN_DEBUG "no reg property!\n"); - continue; - } - busp = (u32 *)get_property(dn, "linux,subbus", NULL); - if (busp == NULL) { - printk(KERN_DEBUG "no subbus property!\n"); - continue; - } + of_node_put(root); - pdn = kzalloc(sizeof(*pdn), GFP_KERNEL); - if (pdn == NULL) - return; - dn->data = pdn; - pdn->node = dn; - pdn->busno = bus; - pdn->devfn = (reg[0] >> 8) & 0xff; - pdn->bussubno = *busp; - } - } + pci_devs_phb_init(); } /* diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index d83f5ed4ec1..0f49412b438 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -1073,7 +1073,7 @@ static void scan_bridge_slot(struct iseries_flat_dt *dt, HvBusNumber bus, snprintf(buf, sizeof(buf), "pci@%x,%d", PCI_SLOT(devfn), function); dt_start_node(dt, buf); - reg[0] = (bus << 18) | (devfn << 8); + reg[0] = (bus << 16) | (devfn << 8); reg[1] = 0; reg[2] = 0; reg[3] = 0; -- cgit v1.2.3 From 29629b2972467f6cc00427a89008c09d010074c8 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Fri, 19 May 2006 16:55:53 +1000 Subject: [PATCH] powerpc: make iSeries flat device tree stuff static Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/setup.c | 40 +++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 0f49412b438..95864146b8f 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -723,9 +723,9 @@ struct iseries_flat_dt { struct blob strings; }; -struct iseries_flat_dt iseries_dt; +static struct iseries_flat_dt iseries_dt; -void dt_init(struct iseries_flat_dt *dt) +static void dt_init(struct iseries_flat_dt *dt) { dt->header.off_mem_rsvmap = offsetof(struct iseries_flat_dt, reserve_map); @@ -748,7 +748,7 @@ void dt_init(struct iseries_flat_dt *dt) dt->reserve_map[1] = 0; } -void dt_check_blob(struct blob *b) +static void dt_check_blob(struct blob *b) { if (b->next >= (unsigned long)&b->next) { DBG("Ran out of space in flat device tree blob!\n"); @@ -756,7 +756,7 @@ void dt_check_blob(struct blob *b) } } -void dt_push_u32(struct iseries_flat_dt *dt, u32 value) +static void dt_push_u32(struct iseries_flat_dt *dt, u32 value) { *((u32*)dt->dt.next) = value; dt->dt.next += sizeof(u32); @@ -764,15 +764,17 @@ void dt_push_u32(struct iseries_flat_dt *dt, u32 value) dt_check_blob(&dt->dt); } -void dt_push_u64(struct iseries_flat_dt *dt, u64 value) +#ifdef notyet +static void dt_push_u64(struct iseries_flat_dt *dt, u64 value) { *((u64*)dt->dt.next) = value; dt->dt.next += sizeof(u64); dt_check_blob(&dt->dt); } +#endif -unsigned long dt_push_bytes(struct blob *blob, char *data, int len) +static unsigned long dt_push_bytes(struct blob *blob, char *data, int len) { unsigned long start = blob->next - (unsigned long)blob->data; @@ -784,7 +786,7 @@ unsigned long dt_push_bytes(struct blob *blob, char *data, int len) return start; } -void dt_start_node(struct iseries_flat_dt *dt, char *name) +static void dt_start_node(struct iseries_flat_dt *dt, char *name) { dt_push_u32(dt, OF_DT_BEGIN_NODE); dt_push_bytes(&dt->dt, name, strlen(name) + 1); @@ -792,7 +794,7 @@ void dt_start_node(struct iseries_flat_dt *dt, char *name) #define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE) -void dt_prop(struct iseries_flat_dt *dt, char *name, char *data, int len) +static void dt_prop(struct iseries_flat_dt *dt, char *name, char *data, int len) { unsigned long offset; @@ -811,37 +813,39 @@ void dt_prop(struct iseries_flat_dt *dt, char *name, char *data, int len) dt_push_bytes(&dt->dt, data, len); } -void dt_prop_str(struct iseries_flat_dt *dt, char *name, char *data) +static void dt_prop_str(struct iseries_flat_dt *dt, char *name, char *data) { dt_prop(dt, name, data, strlen(data) + 1); /* + 1 for NULL */ } -void dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data) +static void dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data) { dt_prop(dt, name, (char *)&data, sizeof(u32)); } -void dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data) +static void dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data) { dt_prop(dt, name, (char *)&data, sizeof(u64)); } -void dt_prop_u64_list(struct iseries_flat_dt *dt, char *name, u64 *data, int n) +static void dt_prop_u64_list(struct iseries_flat_dt *dt, char *name, u64 *data, int n) { dt_prop(dt, name, (char *)data, sizeof(u64) * n); } -void dt_prop_u32_list(struct iseries_flat_dt *dt, char *name, u32 *data, int n) +static void dt_prop_u32_list(struct iseries_flat_dt *dt, char *name, u32 *data, int n) { dt_prop(dt, name, (char *)data, sizeof(u32) * n); } -void dt_prop_empty(struct iseries_flat_dt *dt, char *name) +#ifdef notyet +static void dt_prop_empty(struct iseries_flat_dt *dt, char *name) { dt_prop(dt, name, NULL, 0); } +#endif -void dt_cpus(struct iseries_flat_dt *dt) +static void dt_cpus(struct iseries_flat_dt *dt) { unsigned char buf[32]; unsigned char *p; @@ -895,7 +899,7 @@ void dt_cpus(struct iseries_flat_dt *dt) dt_end_node(dt); } -void dt_model(struct iseries_flat_dt *dt) +static void dt_model(struct iseries_flat_dt *dt) { char buf[16] = "IBM,"; @@ -913,7 +917,7 @@ void dt_model(struct iseries_flat_dt *dt) dt_prop_str(dt, "compatible", "IBM,iSeries"); } -void dt_vdevices(struct iseries_flat_dt *dt) +static void dt_vdevices(struct iseries_flat_dt *dt) { u32 reg = 0; HvLpIndexMap vlan_map; @@ -1203,7 +1207,7 @@ static void dt_pci_devices(struct iseries_flat_dt *dt) } } -void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size) +static void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size) { u64 tmp[2]; -- cgit v1.2.3 From 9ceb19093b5e5f037c6b47df0607dd567283287d Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Fri, 19 May 2006 16:58:13 +1000 Subject: [PATCH] powerpc: give iSeries device tree nodes better names Use the PCI class code to choose a name for the PCI device nodes and to guess a device_type. Failing that, base the name on the vendor and device ids as specified in the spec. Mark just about everything __init{data}. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/setup.c | 95 +++++++++++++++++++++++----------- 1 file changed, 66 insertions(+), 29 deletions(-) diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 95864146b8f..5661bd0d427 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -725,7 +725,7 @@ struct iseries_flat_dt { static struct iseries_flat_dt iseries_dt; -static void dt_init(struct iseries_flat_dt *dt) +static void __init dt_init(struct iseries_flat_dt *dt) { dt->header.off_mem_rsvmap = offsetof(struct iseries_flat_dt, reserve_map); @@ -748,7 +748,7 @@ static void dt_init(struct iseries_flat_dt *dt) dt->reserve_map[1] = 0; } -static void dt_check_blob(struct blob *b) +static void __init dt_check_blob(struct blob *b) { if (b->next >= (unsigned long)&b->next) { DBG("Ran out of space in flat device tree blob!\n"); @@ -756,7 +756,7 @@ static void dt_check_blob(struct blob *b) } } -static void dt_push_u32(struct iseries_flat_dt *dt, u32 value) +static void __init dt_push_u32(struct iseries_flat_dt *dt, u32 value) { *((u32*)dt->dt.next) = value; dt->dt.next += sizeof(u32); @@ -765,7 +765,7 @@ static void dt_push_u32(struct iseries_flat_dt *dt, u32 value) } #ifdef notyet -static void dt_push_u64(struct iseries_flat_dt *dt, u64 value) +static void __init dt_push_u64(struct iseries_flat_dt *dt, u64 value) { *((u64*)dt->dt.next) = value; dt->dt.next += sizeof(u64); @@ -774,7 +774,7 @@ static void dt_push_u64(struct iseries_flat_dt *dt, u64 value) } #endif -static unsigned long dt_push_bytes(struct blob *blob, char *data, int len) +static unsigned long __init dt_push_bytes(struct blob *blob, char *data, int len) { unsigned long start = blob->next - (unsigned long)blob->data; @@ -786,7 +786,7 @@ static unsigned long dt_push_bytes(struct blob *blob, char *data, int len) return start; } -static void dt_start_node(struct iseries_flat_dt *dt, char *name) +static void __init dt_start_node(struct iseries_flat_dt *dt, char *name) { dt_push_u32(dt, OF_DT_BEGIN_NODE); dt_push_bytes(&dt->dt, name, strlen(name) + 1); @@ -794,7 +794,8 @@ static void dt_start_node(struct iseries_flat_dt *dt, char *name) #define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE) -static void dt_prop(struct iseries_flat_dt *dt, char *name, char *data, int len) +static void __init dt_prop(struct iseries_flat_dt *dt, char *name, + char *data, int len) { unsigned long offset; @@ -813,39 +814,42 @@ static void dt_prop(struct iseries_flat_dt *dt, char *name, char *data, int len) dt_push_bytes(&dt->dt, data, len); } -static void dt_prop_str(struct iseries_flat_dt *dt, char *name, char *data) +static void __init dt_prop_str(struct iseries_flat_dt *dt, char *name, + char *data) { dt_prop(dt, name, data, strlen(data) + 1); /* + 1 for NULL */ } -static void dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data) +static void __init dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data) { dt_prop(dt, name, (char *)&data, sizeof(u32)); } -static void dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data) +static void __init dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data) { dt_prop(dt, name, (char *)&data, sizeof(u64)); } -static void dt_prop_u64_list(struct iseries_flat_dt *dt, char *name, u64 *data, int n) +static void __init dt_prop_u64_list(struct iseries_flat_dt *dt, char *name, + u64 *data, int n) { dt_prop(dt, name, (char *)data, sizeof(u64) * n); } -static void dt_prop_u32_list(struct iseries_flat_dt *dt, char *name, u32 *data, int n) +static void __init dt_prop_u32_list(struct iseries_flat_dt *dt, char *name, + u32 *data, int n) { dt_prop(dt, name, (char *)data, sizeof(u32) * n); } #ifdef notyet -static void dt_prop_empty(struct iseries_flat_dt *dt, char *name) +static void __init dt_prop_empty(struct iseries_flat_dt *dt, char *name) { dt_prop(dt, name, NULL, 0); } #endif -static void dt_cpus(struct iseries_flat_dt *dt) +static void __init dt_cpus(struct iseries_flat_dt *dt) { unsigned char buf[32]; unsigned char *p; @@ -899,7 +903,7 @@ static void dt_cpus(struct iseries_flat_dt *dt) dt_end_node(dt); } -static void dt_model(struct iseries_flat_dt *dt) +static void __init dt_model(struct iseries_flat_dt *dt) { char buf[16] = "IBM,"; @@ -917,7 +921,7 @@ static void dt_model(struct iseries_flat_dt *dt) dt_prop_str(dt, "compatible", "IBM,iSeries"); } -static void dt_vdevices(struct iseries_flat_dt *dt) +static void __init dt_vdevices(struct iseries_flat_dt *dt) { u32 reg = 0; HvLpIndexMap vlan_map; @@ -1006,11 +1010,32 @@ static void dt_vdevices(struct iseries_flat_dt *dt) dt_end_node(dt); } +struct pci_class_name { + u16 code; + char *name; + char *type; +}; + +static struct pci_class_name __initdata pci_class_name[] = { + { PCI_CLASS_NETWORK_ETHERNET, "ethernet", "network" }, +}; + +static struct pci_class_name * __init dt_find_pci_class_name(u16 class_code) +{ + struct pci_class_name *cp; + + for (cp = pci_class_name; + cp < &pci_class_name[ARRAY_SIZE(pci_class_name)]; cp++) + if (cp->code == class_code) + return cp; + return NULL; +} + /* * This assumes that the node slot is always on the primary bus! */ -static void scan_bridge_slot(struct iseries_flat_dt *dt, HvBusNumber bus, - struct HvCallPci_BridgeInfo *bridge_info) +static void __init scan_bridge_slot(struct iseries_flat_dt *dt, + HvBusNumber bus, struct HvCallPci_BridgeInfo *bridge_info) { HvSubBusNumber sub_bus = bridge_info->subBusNumber; u16 vendor_id; @@ -1022,14 +1047,14 @@ static void scan_bridge_slot(struct iseries_flat_dt *dt, HvBusNumber bus, int id_sel = ISERIES_GET_DEVICE_FROM_SUBBUS(sub_bus); int function = ISERIES_GET_FUNCTION_FROM_SUBBUS(sub_bus); HvAgentId eads_id_sel = ISERIES_PCI_AGENTID(id_sel, function); + u8 devfn; + struct pci_class_name *cp; /* * Connect all functions of any device found. */ for (id_sel = 1; id_sel <= bridge_info->maxAgents; id_sel++) { for (function = 0; function < 8; function++) { - u8 devfn; - HvAgentId agent_id = ISERIES_PCI_AGENTID(id_sel, function); err = HvCallXm_connectBusUnit(bus, sub_bus, @@ -1070,12 +1095,20 @@ static void scan_bridge_slot(struct iseries_flat_dt *dt, HvBusNumber bus, devfn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(eads_id_sel), function); - if (function == 0) - snprintf(buf, sizeof(buf), "pci@%x", - PCI_SLOT(devfn)); + cp = dt_find_pci_class_name(class_id >> 16); + if (cp && cp->name) + strncpy(buf, cp->name, sizeof(buf) - 1); else - snprintf(buf, sizeof(buf), "pci@%x,%d", - PCI_SLOT(devfn), function); + snprintf(buf, sizeof(buf), "pci%x,%x", + vendor_id, device_id); + buf[sizeof(buf) - 1] = '\0'; + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), + "@%x", PCI_SLOT(devfn)); + buf[sizeof(buf) - 1] = '\0'; + if (function != 0) + snprintf(buf + strlen(buf), + sizeof(buf) - strlen(buf), + ",%x", function); dt_start_node(dt, buf); reg[0] = (bus << 16) | (devfn << 8); reg[1] = 0; @@ -1083,6 +1116,9 @@ static void scan_bridge_slot(struct iseries_flat_dt *dt, HvBusNumber bus, reg[3] = 0; reg[4] = 0; dt_prop_u32_list(dt, "reg", reg, 5); + if (cp && (cp->type || cp->name)) + dt_prop_str(dt, "device_type", + cp->type ? cp->type : cp->name); dt_prop_u32(dt, "vendor-id", vendor_id); dt_prop_u32(dt, "device-id", device_id); dt_prop_u32(dt, "class-code", class_id >> 8); @@ -1097,7 +1133,7 @@ static void scan_bridge_slot(struct iseries_flat_dt *dt, HvBusNumber bus, } } -static void scan_bridge(struct iseries_flat_dt *dt, HvBusNumber bus, +static void __init scan_bridge(struct iseries_flat_dt *dt, HvBusNumber bus, HvSubBusNumber sub_bus, int id_sel) { struct HvCallPci_BridgeInfo bridge_info; @@ -1139,7 +1175,7 @@ static void scan_bridge(struct iseries_flat_dt *dt, HvBusNumber bus, } } -static void scan_phb(struct iseries_flat_dt *dt, HvBusNumber bus) +static void __init scan_phb(struct iseries_flat_dt *dt, HvBusNumber bus) { struct HvCallPci_DeviceInfo dev_info; const HvSubBusNumber sub_bus = 0; /* EADs is always 0. */ @@ -1171,7 +1207,7 @@ static void scan_phb(struct iseries_flat_dt *dt, HvBusNumber bus) } } -static void dt_pci_devices(struct iseries_flat_dt *dt) +static void __init dt_pci_devices(struct iseries_flat_dt *dt) { HvBusNumber bus; char buf[32]; @@ -1207,7 +1243,8 @@ static void dt_pci_devices(struct iseries_flat_dt *dt) } } -static void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size) +static void __init build_flat_dt(struct iseries_flat_dt *dt, + unsigned long phys_mem_size) { u64 tmp[2]; -- cgit v1.2.3 From c81014f603db26e1ed818decebd3b594606e20a6 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Fri, 19 May 2006 17:00:04 +1000 Subject: [PATCH] powerpc: split device tree stuff out of iseries/setup.c Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/Makefile | 2 +- arch/powerpc/platforms/iseries/dt.c | 618 ++++++++++++++++++++++++++++++++ arch/powerpc/platforms/iseries/setup.c | 578 +---------------------------- arch/powerpc/platforms/iseries/setup.h | 2 + 4 files changed, 622 insertions(+), 578 deletions(-) create mode 100644 arch/powerpc/platforms/iseries/dt.c diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile index 7e67a20c18a..32306214a30 100644 --- a/arch/powerpc/platforms/iseries/Makefile +++ b/arch/powerpc/platforms/iseries/Makefile @@ -1,6 +1,6 @@ EXTRA_CFLAGS += -mno-minimal-toc -obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o mf.o lpevents.o \ +obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o dt.o mf.o lpevents.o \ hvcall.o proc.o htab.o iommu.o misc.o irq.o obj-$(CONFIG_PCI) += pci.o vpdinfo.o obj-$(CONFIG_SMP) += smp.o diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c new file mode 100644 index 00000000000..93d4233e73e --- /dev/null +++ b/arch/powerpc/platforms/iseries/dt.c @@ -0,0 +1,618 @@ +/* + * Copyright (c) 2005-2006 Michael Ellerman, IBM Corporation + * + * Description: + * This file contains all the routines to build a flattened device + * tree for a legacy iSeries machine. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#undef DEBUG + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* ETH_ALEN */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "processor_vpd.h" +#include "call_hpt.h" +#include "call_pci.h" +#include "pci.h" + +#ifdef DEBUG +#define DBG(fmt...) udbg_printf(fmt) +#else +#define DBG(fmt...) +#endif + +struct blob { + unsigned char data[PAGE_SIZE * 2]; + unsigned long next; +}; + +struct iseries_flat_dt { + struct boot_param_header header; + u64 reserve_map[2]; + struct blob dt; + struct blob strings; +}; + +static struct iseries_flat_dt iseries_dt; + +static void __init dt_init(struct iseries_flat_dt *dt) +{ + dt->header.off_mem_rsvmap = + offsetof(struct iseries_flat_dt, reserve_map); + dt->header.off_dt_struct = offsetof(struct iseries_flat_dt, dt); + dt->header.off_dt_strings = offsetof(struct iseries_flat_dt, strings); + dt->header.totalsize = sizeof(struct iseries_flat_dt); + dt->header.dt_strings_size = sizeof(struct blob); + + /* There is no notion of hardware cpu id on iSeries */ + dt->header.boot_cpuid_phys = smp_processor_id(); + + dt->dt.next = (unsigned long)&dt->dt.data; + dt->strings.next = (unsigned long)&dt->strings.data; + + dt->header.magic = OF_DT_HEADER; + dt->header.version = 0x10; + dt->header.last_comp_version = 0x10; + + dt->reserve_map[0] = 0; + dt->reserve_map[1] = 0; +} + +static void __init dt_check_blob(struct blob *b) +{ + if (b->next >= (unsigned long)&b->next) { + DBG("Ran out of space in flat device tree blob!\n"); + BUG(); + } +} + +static void __init dt_push_u32(struct iseries_flat_dt *dt, u32 value) +{ + *((u32*)dt->dt.next) = value; + dt->dt.next += sizeof(u32); + + dt_check_blob(&dt->dt); +} + +#ifdef notyet +static void __init dt_push_u64(struct iseries_flat_dt *dt, u64 value) +{ + *((u64*)dt->dt.next) = value; + dt->dt.next += sizeof(u64); + + dt_check_blob(&dt->dt); +} +#endif + +static unsigned long __init dt_push_bytes(struct blob *blob, char *data, int len) +{ + unsigned long start = blob->next - (unsigned long)blob->data; + + memcpy((char *)blob->next, data, len); + blob->next = _ALIGN(blob->next + len, 4); + + dt_check_blob(blob); + + return start; +} + +static void __init dt_start_node(struct iseries_flat_dt *dt, char *name) +{ + dt_push_u32(dt, OF_DT_BEGIN_NODE); + dt_push_bytes(&dt->dt, name, strlen(name) + 1); +} + +#define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE) + +static void __init dt_prop(struct iseries_flat_dt *dt, char *name, + char *data, int len) +{ + unsigned long offset; + + dt_push_u32(dt, OF_DT_PROP); + + /* Length of the data */ + dt_push_u32(dt, len); + + /* Put the property name in the string blob. */ + offset = dt_push_bytes(&dt->strings, name, strlen(name) + 1); + + /* The offset of the properties name in the string blob. */ + dt_push_u32(dt, (u32)offset); + + /* The actual data. */ + dt_push_bytes(&dt->dt, data, len); +} + +static void __init dt_prop_str(struct iseries_flat_dt *dt, char *name, + char *data) +{ + dt_prop(dt, name, data, strlen(data) + 1); /* + 1 for NULL */ +} + +static void __init dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data) +{ + dt_prop(dt, name, (char *)&data, sizeof(u32)); +} + +static void __init dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data) +{ + dt_prop(dt, name, (char *)&data, sizeof(u64)); +} + +static void __init dt_prop_u64_list(struct iseries_flat_dt *dt, char *name, + u64 *data, int n) +{ + dt_prop(dt, name, (char *)data, sizeof(u64) * n); +} + +static void __init dt_prop_u32_list(struct iseries_flat_dt *dt, char *name, + u32 *data, int n) +{ + dt_prop(dt, name, (char *)data, sizeof(u32) * n); +} + +#ifdef notyet +static void __init dt_prop_empty(struct iseries_flat_dt *dt, char *name) +{ + dt_prop(dt, name, NULL, 0); +} +#endif + +static void __init dt_cpus(struct iseries_flat_dt *dt) +{ + unsigned char buf[32]; + unsigned char *p; + unsigned int i, index; + struct IoHriProcessorVpd *d; + u32 pft_size[2]; + + /* yuck */ + snprintf(buf, 32, "PowerPC,%s", cur_cpu_spec->cpu_name); + p = strchr(buf, ' '); + if (!p) p = buf + strlen(buf); + + dt_start_node(dt, "cpus"); + dt_prop_u32(dt, "#address-cells", 1); + dt_prop_u32(dt, "#size-cells", 0); + + pft_size[0] = 0; /* NUMA CEC cookie, 0 for non NUMA */ + pft_size[1] = __ilog2(HvCallHpt_getHptPages() * HW_PAGE_SIZE); + + for (i = 0; i < NR_CPUS; i++) { + if (lppaca[i].dyn_proc_status >= 2) + continue; + + snprintf(p, 32 - (p - buf), "@%d", i); + dt_start_node(dt, buf); + + dt_prop_str(dt, "device_type", "cpu"); + + index = lppaca[i].dyn_hv_phys_proc_index; + d = &xIoHriProcessorVpd[index]; + + dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024); + dt_prop_u32(dt, "i-cache-line-size", d->xInstCacheOperandSize); + + dt_prop_u32(dt, "d-cache-size", d->xDataL1CacheSizeKB * 1024); + dt_prop_u32(dt, "d-cache-line-size", d->xDataCacheOperandSize); + + /* magic conversions to Hz copied from old code */ + dt_prop_u32(dt, "clock-frequency", + ((1UL << 34) * 1000000) / d->xProcFreq); + dt_prop_u32(dt, "timebase-frequency", + ((1UL << 32) * 1000000) / d->xTimeBaseFreq); + + dt_prop_u32(dt, "reg", i); + + dt_prop_u32_list(dt, "ibm,pft-size", pft_size, 2); + + dt_end_node(dt); + } + + dt_end_node(dt); +} + +static void __init dt_model(struct iseries_flat_dt *dt) +{ + char buf[16] = "IBM,"; + + /* "IBM," + mfgId[2:3] + systemSerial[1:5] */ + strne2a(buf + 4, xItExtVpdPanel.mfgID + 2, 2); + strne2a(buf + 6, xItExtVpdPanel.systemSerial + 1, 5); + buf[11] = '\0'; + dt_prop_str(dt, "system-id", buf); + + /* "IBM," + machineType[0:4] */ + strne2a(buf + 4, xItExtVpdPanel.machineType, 4); + buf[8] = '\0'; + dt_prop_str(dt, "model", buf); + + dt_prop_str(dt, "compatible", "IBM,iSeries"); +} + +static void __init dt_vdevices(struct iseries_flat_dt *dt) +{ + u32 reg = 0; + HvLpIndexMap vlan_map; + int i; + char buf[32]; + + dt_start_node(dt, "vdevice"); + dt_prop_str(dt, "device_type", "vdevice"); + dt_prop_str(dt, "compatible", "IBM,iSeries-vdevice"); + dt_prop_u32(dt, "#address-cells", 1); + dt_prop_u32(dt, "#size-cells", 0); + + snprintf(buf, sizeof(buf), "vty@%08x", reg); + dt_start_node(dt, buf); + dt_prop_str(dt, "device_type", "serial"); + dt_prop_u32(dt, "reg", reg); + dt_end_node(dt); + reg++; + + snprintf(buf, sizeof(buf), "v-scsi@%08x", reg); + dt_start_node(dt, buf); + dt_prop_str(dt, "device_type", "vscsi"); + dt_prop_str(dt, "compatible", "IBM,v-scsi"); + dt_prop_u32(dt, "reg", reg); + dt_end_node(dt); + reg++; + + vlan_map = HvLpConfig_getVirtualLanIndexMap(); + for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) { + unsigned char mac_addr[ETH_ALEN]; + + if ((vlan_map & (0x8000 >> i)) == 0) + continue; + snprintf(buf, 32, "l-lan@%08x", reg + i); + dt_start_node(dt, buf); + dt_prop_str(dt, "device_type", "network"); + dt_prop_str(dt, "compatible", "IBM,iSeries-l-lan"); + dt_prop_u32(dt, "reg", reg + i); + dt_prop_u32(dt, "linux,unit_address", i); + + mac_addr[0] = 0x02; + mac_addr[1] = 0x01; + mac_addr[2] = 0xff; + mac_addr[3] = i; + mac_addr[4] = 0xff; + mac_addr[5] = HvLpConfig_getLpIndex_outline(); + dt_prop(dt, "local-mac-address", (char *)mac_addr, ETH_ALEN); + dt_prop(dt, "mac-address", (char *)mac_addr, ETH_ALEN); + dt_prop_u32(dt, "max-frame-size", 9000); + dt_prop_u32(dt, "address-bits", 48); + + dt_end_node(dt); + } + reg += HVMAXARCHITECTEDVIRTUALLANS; + + for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++) { + snprintf(buf, 32, "viodasd@%08x", reg + i); + dt_start_node(dt, buf); + dt_prop_str(dt, "device_type", "block"); + dt_prop_str(dt, "compatible", "IBM,iSeries-viodasd"); + dt_prop_u32(dt, "reg", reg + i); + dt_prop_u32(dt, "linux,unit_address", i); + dt_end_node(dt); + } + reg += HVMAXARCHITECTEDVIRTUALDISKS; + for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++) { + snprintf(buf, 32, "viocd@%08x", reg + i); + dt_start_node(dt, buf); + dt_prop_str(dt, "device_type", "block"); + dt_prop_str(dt, "compatible", "IBM,iSeries-viocd"); + dt_prop_u32(dt, "reg", reg + i); + dt_prop_u32(dt, "linux,unit_address", i); + dt_end_node(dt); + } + reg += HVMAXARCHITECTEDVIRTUALCDROMS; + for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++) { + snprintf(buf, 32, "viotape@%08x", reg + i); + dt_start_node(dt, buf); + dt_prop_str(dt, "device_type", "byte"); + dt_prop_str(dt, "compatible", "IBM,iSeries-viotape"); + dt_prop_u32(dt, "reg", reg + i); + dt_prop_u32(dt, "linux,unit_address", i); + dt_end_node(dt); + } + + dt_end_node(dt); +} + +struct pci_class_name { + u16 code; + char *name; + char *type; +}; + +static struct pci_class_name __initdata pci_class_name[] = { + { PCI_CLASS_NETWORK_ETHERNET, "ethernet", "network" }, +}; + +static struct pci_class_name * __init dt_find_pci_class_name(u16 class_code) +{ + struct pci_class_name *cp; + + for (cp = pci_class_name; + cp < &pci_class_name[ARRAY_SIZE(pci_class_name)]; cp++) + if (cp->code == class_code) + return cp; + return NULL; +} + +/* + * This assumes that the node slot is always on the primary bus! + */ +static void __init scan_bridge_slot(struct iseries_flat_dt *dt, + HvBusNumber bus, struct HvCallPci_BridgeInfo *bridge_info) +{ + HvSubBusNumber sub_bus = bridge_info->subBusNumber; + u16 vendor_id; + u16 device_id; + u32 class_id; + int err; + char buf[32]; + u32 reg[5]; + int id_sel = ISERIES_GET_DEVICE_FROM_SUBBUS(sub_bus); + int function = ISERIES_GET_FUNCTION_FROM_SUBBUS(sub_bus); + HvAgentId eads_id_sel = ISERIES_PCI_AGENTID(id_sel, function); + u8 devfn; + struct pci_class_name *cp; + + /* + * Connect all functions of any device found. + */ + for (id_sel = 1; id_sel <= bridge_info->maxAgents; id_sel++) { + for (function = 0; function < 8; function++) { + HvAgentId agent_id = ISERIES_PCI_AGENTID(id_sel, + function); + err = HvCallXm_connectBusUnit(bus, sub_bus, + agent_id, 0); + if (err) { + if (err != 0x302) + printk(KERN_DEBUG + "connectBusUnit(%x, %x, %x) " + "== %x\n", + bus, sub_bus, agent_id, err); + continue; + } + + err = HvCallPci_configLoad16(bus, sub_bus, agent_id, + PCI_VENDOR_ID, &vendor_id); + if (err) { + printk(KERN_DEBUG + "ReadVendor(%x, %x, %x) == %x\n", + bus, sub_bus, agent_id, err); + continue; + } + err = HvCallPci_configLoad16(bus, sub_bus, agent_id, + PCI_DEVICE_ID, &device_id); + if (err) { + printk(KERN_DEBUG + "ReadDevice(%x, %x, %x) == %x\n", + bus, sub_bus, agent_id, err); + continue; + } + err = HvCallPci_configLoad32(bus, sub_bus, agent_id, + PCI_CLASS_REVISION , &class_id); + if (err) { + printk(KERN_DEBUG + "ReadClass(%x, %x, %x) == %x\n", + bus, sub_bus, agent_id, err); + continue; + } + + devfn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(eads_id_sel), + function); + cp = dt_find_pci_class_name(class_id >> 16); + if (cp && cp->name) + strncpy(buf, cp->name, sizeof(buf) - 1); + else + snprintf(buf, sizeof(buf), "pci%x,%x", + vendor_id, device_id); + buf[sizeof(buf) - 1] = '\0'; + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), + "@%x", PCI_SLOT(devfn)); + buf[sizeof(buf) - 1] = '\0'; + if (function != 0) + snprintf(buf + strlen(buf), + sizeof(buf) - strlen(buf), + ",%x", function); + dt_start_node(dt, buf); + reg[0] = (bus << 16) | (devfn << 8); + reg[1] = 0; + reg[2] = 0; + reg[3] = 0; + reg[4] = 0; + dt_prop_u32_list(dt, "reg", reg, 5); + if (cp && (cp->type || cp->name)) + dt_prop_str(dt, "device_type", + cp->type ? cp->type : cp->name); + dt_prop_u32(dt, "vendor-id", vendor_id); + dt_prop_u32(dt, "device-id", device_id); + dt_prop_u32(dt, "class-code", class_id >> 8); + dt_prop_u32(dt, "revision-id", class_id & 0xff); + dt_prop_u32(dt, "linux,subbus", sub_bus); + dt_prop_u32(dt, "linux,agent-id", agent_id); + dt_prop_u32(dt, "linux,logical-slot-number", + bridge_info->logicalSlotNumber); + dt_end_node(dt); + + } + } +} + +static void __init scan_bridge(struct iseries_flat_dt *dt, HvBusNumber bus, + HvSubBusNumber sub_bus, int id_sel) +{ + struct HvCallPci_BridgeInfo bridge_info; + HvAgentId agent_id; + int function; + int ret; + + /* Note: hvSubBus and irq is always be 0 at this level! */ + for (function = 0; function < 8; ++function) { + agent_id = ISERIES_PCI_AGENTID(id_sel, function); + ret = HvCallXm_connectBusUnit(bus, sub_bus, agent_id, 0); + if (ret != 0) { + if (ret != 0xb) + printk(KERN_DEBUG "connectBusUnit(%x, %x, %x) " + "== %x\n", + bus, sub_bus, agent_id, ret); + continue; + } + printk("found device at bus %d idsel %d func %d (AgentId %x)\n", + bus, id_sel, function, agent_id); + ret = HvCallPci_getBusUnitInfo(bus, sub_bus, agent_id, + iseries_hv_addr(&bridge_info), + sizeof(struct HvCallPci_BridgeInfo)); + if (ret != 0) + continue; + printk("bridge info: type %x subbus %x " + "maxAgents %x maxsubbus %x logslot %x\n", + bridge_info.busUnitInfo.deviceType, + bridge_info.subBusNumber, + bridge_info.maxAgents, + bridge_info.maxSubBusNumber, + bridge_info.logicalSlotNumber); + if (bridge_info.busUnitInfo.deviceType == + HvCallPci_BridgeDevice) + scan_bridge_slot(dt, bus, &bridge_info); + else + printk("PCI: Invalid Bridge Configuration(0x%02X)", + bridge_info.busUnitInfo.deviceType); + } +} + +static void __init scan_phb(struct iseries_flat_dt *dt, HvBusNumber bus) +{ + struct HvCallPci_DeviceInfo dev_info; + const HvSubBusNumber sub_bus = 0; /* EADs is always 0. */ + int err; + int id_sel; + const int max_agents = 8; + + /* + * Probe for EADs Bridges + */ + for (id_sel = 1; id_sel < max_agents; ++id_sel) { + err = HvCallPci_getDeviceInfo(bus, sub_bus, id_sel, + iseries_hv_addr(&dev_info), + sizeof(struct HvCallPci_DeviceInfo)); + if (err) { + if (err != 0x302) + printk(KERN_DEBUG "getDeviceInfo(%x, %x, %x) " + "== %x\n", + bus, sub_bus, id_sel, err); + continue; + } + if (dev_info.deviceType != HvCallPci_NodeDevice) { + printk(KERN_DEBUG "PCI: Invalid System Configuration" + "(0x%02X) for bus 0x%02x id 0x%02x.\n", + dev_info.deviceType, bus, id_sel); + continue; + } + scan_bridge(dt, bus, sub_bus, id_sel); + } +} + +static void __init dt_pci_devices(struct iseries_flat_dt *dt) +{ + HvBusNumber bus; + char buf[32]; + u32 buses[2]; + int phb_num = 0; + + /* Check all possible buses. */ + for (bus = 0; bus < 256; bus++) { + int err = HvCallXm_testBus(bus); + + if (err) { + /* + * Check for Unexpected Return code, a clue that + * something has gone wrong. + */ + if (err != 0x0301) + printk(KERN_ERR "Unexpected Return on Probe" + "(0x%02X): 0x%04X", bus, err); + continue; + } + printk("bus %d appears to exist\n", bus); + snprintf(buf, 32, "pci@%d", phb_num); + dt_start_node(dt, buf); + dt_prop_str(dt, "device_type", "pci"); + dt_prop_str(dt, "compatible", "IBM,iSeries-Logical-PHB"); + dt_prop_u32(dt, "#address-cells", 3); + dt_prop_u32(dt, "#size-cells", 2); + buses[0] = buses[1] = bus; + dt_prop_u32_list(dt, "bus-range", buses, 2); + scan_phb(dt, bus); + dt_end_node(dt); + phb_num++; + } +} + +void * __init build_flat_dt(unsigned long phys_mem_size) +{ + u64 tmp[2]; + + dt_init(&iseries_dt); + + dt_start_node(&iseries_dt, ""); + + dt_prop_u32(&iseries_dt, "#address-cells", 2); + dt_prop_u32(&iseries_dt, "#size-cells", 2); + dt_model(&iseries_dt); + + /* /memory */ + dt_start_node(&iseries_dt, "memory@0"); + dt_prop_str(&iseries_dt, "name", "memory"); + dt_prop_str(&iseries_dt, "device_type", "memory"); + tmp[0] = 0; + tmp[1] = phys_mem_size; + dt_prop_u64_list(&iseries_dt, "reg", tmp, 2); + dt_end_node(&iseries_dt); + + /* /chosen */ + dt_start_node(&iseries_dt, "chosen"); + dt_prop_str(&iseries_dt, "bootargs", cmd_line); + dt_end_node(&iseries_dt); + + dt_cpus(&iseries_dt); + + dt_vdevices(&iseries_dt); + dt_pci_devices(&iseries_dt); + + dt_end_node(&iseries_dt); + + dt_push_u32(&iseries_dt, OF_DT_END); + + return &iseries_dt; +} diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 5661bd0d427..617c724c459 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -28,7 +28,6 @@ #include #include #include -#include /* ETH_ALEN */ #include #include @@ -46,13 +45,11 @@ #include #include #include -#include #include #include #include #include #include -#include #include #include #include @@ -66,8 +63,6 @@ #include "main_store.h" #include "call_sm.h" #include "call_hpt.h" -#include "call_pci.h" -#include "pci.h" #ifdef DEBUG #define DBG(fmt...) udbg_printf(fmt) @@ -711,575 +706,6 @@ define_machine(iseries) { /* XXX Implement enable_pmcs for iSeries */ }; -struct blob { - unsigned char data[PAGE_SIZE * 2]; - unsigned long next; -}; - -struct iseries_flat_dt { - struct boot_param_header header; - u64 reserve_map[2]; - struct blob dt; - struct blob strings; -}; - -static struct iseries_flat_dt iseries_dt; - -static void __init dt_init(struct iseries_flat_dt *dt) -{ - dt->header.off_mem_rsvmap = - offsetof(struct iseries_flat_dt, reserve_map); - dt->header.off_dt_struct = offsetof(struct iseries_flat_dt, dt); - dt->header.off_dt_strings = offsetof(struct iseries_flat_dt, strings); - dt->header.totalsize = sizeof(struct iseries_flat_dt); - dt->header.dt_strings_size = sizeof(struct blob); - - /* There is no notion of hardware cpu id on iSeries */ - dt->header.boot_cpuid_phys = smp_processor_id(); - - dt->dt.next = (unsigned long)&dt->dt.data; - dt->strings.next = (unsigned long)&dt->strings.data; - - dt->header.magic = OF_DT_HEADER; - dt->header.version = 0x10; - dt->header.last_comp_version = 0x10; - - dt->reserve_map[0] = 0; - dt->reserve_map[1] = 0; -} - -static void __init dt_check_blob(struct blob *b) -{ - if (b->next >= (unsigned long)&b->next) { - DBG("Ran out of space in flat device tree blob!\n"); - BUG(); - } -} - -static void __init dt_push_u32(struct iseries_flat_dt *dt, u32 value) -{ - *((u32*)dt->dt.next) = value; - dt->dt.next += sizeof(u32); - - dt_check_blob(&dt->dt); -} - -#ifdef notyet -static void __init dt_push_u64(struct iseries_flat_dt *dt, u64 value) -{ - *((u64*)dt->dt.next) = value; - dt->dt.next += sizeof(u64); - - dt_check_blob(&dt->dt); -} -#endif - -static unsigned long __init dt_push_bytes(struct blob *blob, char *data, int len) -{ - unsigned long start = blob->next - (unsigned long)blob->data; - - memcpy((char *)blob->next, data, len); - blob->next = _ALIGN(blob->next + len, 4); - - dt_check_blob(blob); - - return start; -} - -static void __init dt_start_node(struct iseries_flat_dt *dt, char *name) -{ - dt_push_u32(dt, OF_DT_BEGIN_NODE); - dt_push_bytes(&dt->dt, name, strlen(name) + 1); -} - -#define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE) - -static void __init dt_prop(struct iseries_flat_dt *dt, char *name, - char *data, int len) -{ - unsigned long offset; - - dt_push_u32(dt, OF_DT_PROP); - - /* Length of the data */ - dt_push_u32(dt, len); - - /* Put the property name in the string blob. */ - offset = dt_push_bytes(&dt->strings, name, strlen(name) + 1); - - /* The offset of the properties name in the string blob. */ - dt_push_u32(dt, (u32)offset); - - /* The actual data. */ - dt_push_bytes(&dt->dt, data, len); -} - -static void __init dt_prop_str(struct iseries_flat_dt *dt, char *name, - char *data) -{ - dt_prop(dt, name, data, strlen(data) + 1); /* + 1 for NULL */ -} - -static void __init dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data) -{ - dt_prop(dt, name, (char *)&data, sizeof(u32)); -} - -static void __init dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data) -{ - dt_prop(dt, name, (char *)&data, sizeof(u64)); -} - -static void __init dt_prop_u64_list(struct iseries_flat_dt *dt, char *name, - u64 *data, int n) -{ - dt_prop(dt, name, (char *)data, sizeof(u64) * n); -} - -static void __init dt_prop_u32_list(struct iseries_flat_dt *dt, char *name, - u32 *data, int n) -{ - dt_prop(dt, name, (char *)data, sizeof(u32) * n); -} - -#ifdef notyet -static void __init dt_prop_empty(struct iseries_flat_dt *dt, char *name) -{ - dt_prop(dt, name, NULL, 0); -} -#endif - -static void __init dt_cpus(struct iseries_flat_dt *dt) -{ - unsigned char buf[32]; - unsigned char *p; - unsigned int i, index; - struct IoHriProcessorVpd *d; - u32 pft_size[2]; - - /* yuck */ - snprintf(buf, 32, "PowerPC,%s", cur_cpu_spec->cpu_name); - p = strchr(buf, ' '); - if (!p) p = buf + strlen(buf); - - dt_start_node(dt, "cpus"); - dt_prop_u32(dt, "#address-cells", 1); - dt_prop_u32(dt, "#size-cells", 0); - - pft_size[0] = 0; /* NUMA CEC cookie, 0 for non NUMA */ - pft_size[1] = __ilog2(HvCallHpt_getHptPages() * HW_PAGE_SIZE); - - for (i = 0; i < NR_CPUS; i++) { - if (lppaca[i].dyn_proc_status >= 2) - continue; - - snprintf(p, 32 - (p - buf), "@%d", i); - dt_start_node(dt, buf); - - dt_prop_str(dt, "device_type", "cpu"); - - index = lppaca[i].dyn_hv_phys_proc_index; - d = &xIoHriProcessorVpd[index]; - - dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024); - dt_prop_u32(dt, "i-cache-line-size", d->xInstCacheOperandSize); - - dt_prop_u32(dt, "d-cache-size", d->xDataL1CacheSizeKB * 1024); - dt_prop_u32(dt, "d-cache-line-size", d->xDataCacheOperandSize); - - /* magic conversions to Hz copied from old code */ - dt_prop_u32(dt, "clock-frequency", - ((1UL << 34) * 1000000) / d->xProcFreq); - dt_prop_u32(dt, "timebase-frequency", - ((1UL << 32) * 1000000) / d->xTimeBaseFreq); - - dt_prop_u32(dt, "reg", i); - - dt_prop_u32_list(dt, "ibm,pft-size", pft_size, 2); - - dt_end_node(dt); - } - - dt_end_node(dt); -} - -static void __init dt_model(struct iseries_flat_dt *dt) -{ - char buf[16] = "IBM,"; - - /* "IBM," + mfgId[2:3] + systemSerial[1:5] */ - strne2a(buf + 4, xItExtVpdPanel.mfgID + 2, 2); - strne2a(buf + 6, xItExtVpdPanel.systemSerial + 1, 5); - buf[11] = '\0'; - dt_prop_str(dt, "system-id", buf); - - /* "IBM," + machineType[0:4] */ - strne2a(buf + 4, xItExtVpdPanel.machineType, 4); - buf[8] = '\0'; - dt_prop_str(dt, "model", buf); - - dt_prop_str(dt, "compatible", "IBM,iSeries"); -} - -static void __init dt_vdevices(struct iseries_flat_dt *dt) -{ - u32 reg = 0; - HvLpIndexMap vlan_map; - int i; - char buf[32]; - - dt_start_node(dt, "vdevice"); - dt_prop_str(dt, "device_type", "vdevice"); - dt_prop_str(dt, "compatible", "IBM,iSeries-vdevice"); - dt_prop_u32(dt, "#address-cells", 1); - dt_prop_u32(dt, "#size-cells", 0); - - snprintf(buf, sizeof(buf), "vty@%08x", reg); - dt_start_node(dt, buf); - dt_prop_str(dt, "device_type", "serial"); - dt_prop_u32(dt, "reg", reg); - dt_end_node(dt); - reg++; - - snprintf(buf, sizeof(buf), "v-scsi@%08x", reg); - dt_start_node(dt, buf); - dt_prop_str(dt, "device_type", "vscsi"); - dt_prop_str(dt, "compatible", "IBM,v-scsi"); - dt_prop_u32(dt, "reg", reg); - dt_end_node(dt); - reg++; - - vlan_map = HvLpConfig_getVirtualLanIndexMap(); - for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) { - unsigned char mac_addr[ETH_ALEN]; - - if ((vlan_map & (0x8000 >> i)) == 0) - continue; - snprintf(buf, 32, "l-lan@%08x", reg + i); - dt_start_node(dt, buf); - dt_prop_str(dt, "device_type", "network"); - dt_prop_str(dt, "compatible", "IBM,iSeries-l-lan"); - dt_prop_u32(dt, "reg", reg + i); - dt_prop_u32(dt, "linux,unit_address", i); - - mac_addr[0] = 0x02; - mac_addr[1] = 0x01; - mac_addr[2] = 0xff; - mac_addr[3] = i; - mac_addr[4] = 0xff; - mac_addr[5] = HvLpConfig_getLpIndex_outline(); - dt_prop(dt, "local-mac-address", (char *)mac_addr, ETH_ALEN); - dt_prop(dt, "mac-address", (char *)mac_addr, ETH_ALEN); - dt_prop_u32(dt, "max-frame-size", 9000); - dt_prop_u32(dt, "address-bits", 48); - - dt_end_node(dt); - } - reg += HVMAXARCHITECTEDVIRTUALLANS; - - for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++) { - snprintf(buf, 32, "viodasd@%08x", reg + i); - dt_start_node(dt, buf); - dt_prop_str(dt, "device_type", "block"); - dt_prop_str(dt, "compatible", "IBM,iSeries-viodasd"); - dt_prop_u32(dt, "reg", reg + i); - dt_prop_u32(dt, "linux,unit_address", i); - dt_end_node(dt); - } - reg += HVMAXARCHITECTEDVIRTUALDISKS; - for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++) { - snprintf(buf, 32, "viocd@%08x", reg + i); - dt_start_node(dt, buf); - dt_prop_str(dt, "device_type", "block"); - dt_prop_str(dt, "compatible", "IBM,iSeries-viocd"); - dt_prop_u32(dt, "reg", reg + i); - dt_prop_u32(dt, "linux,unit_address", i); - dt_end_node(dt); - } - reg += HVMAXARCHITECTEDVIRTUALCDROMS; - for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++) { - snprintf(buf, 32, "viotape@%08x", reg + i); - dt_start_node(dt, buf); - dt_prop_str(dt, "device_type", "byte"); - dt_prop_str(dt, "compatible", "IBM,iSeries-viotape"); - dt_prop_u32(dt, "reg", reg + i); - dt_prop_u32(dt, "linux,unit_address", i); - dt_end_node(dt); - } - - dt_end_node(dt); -} - -struct pci_class_name { - u16 code; - char *name; - char *type; -}; - -static struct pci_class_name __initdata pci_class_name[] = { - { PCI_CLASS_NETWORK_ETHERNET, "ethernet", "network" }, -}; - -static struct pci_class_name * __init dt_find_pci_class_name(u16 class_code) -{ - struct pci_class_name *cp; - - for (cp = pci_class_name; - cp < &pci_class_name[ARRAY_SIZE(pci_class_name)]; cp++) - if (cp->code == class_code) - return cp; - return NULL; -} - -/* - * This assumes that the node slot is always on the primary bus! - */ -static void __init scan_bridge_slot(struct iseries_flat_dt *dt, - HvBusNumber bus, struct HvCallPci_BridgeInfo *bridge_info) -{ - HvSubBusNumber sub_bus = bridge_info->subBusNumber; - u16 vendor_id; - u16 device_id; - u32 class_id; - int err; - char buf[32]; - u32 reg[5]; - int id_sel = ISERIES_GET_DEVICE_FROM_SUBBUS(sub_bus); - int function = ISERIES_GET_FUNCTION_FROM_SUBBUS(sub_bus); - HvAgentId eads_id_sel = ISERIES_PCI_AGENTID(id_sel, function); - u8 devfn; - struct pci_class_name *cp; - - /* - * Connect all functions of any device found. - */ - for (id_sel = 1; id_sel <= bridge_info->maxAgents; id_sel++) { - for (function = 0; function < 8; function++) { - HvAgentId agent_id = ISERIES_PCI_AGENTID(id_sel, - function); - err = HvCallXm_connectBusUnit(bus, sub_bus, - agent_id, 0); - if (err) { - if (err != 0x302) - printk(KERN_DEBUG - "connectBusUnit(%x, %x, %x) " - "== %x\n", - bus, sub_bus, agent_id, err); - continue; - } - - err = HvCallPci_configLoad16(bus, sub_bus, agent_id, - PCI_VENDOR_ID, &vendor_id); - if (err) { - printk(KERN_DEBUG - "ReadVendor(%x, %x, %x) == %x\n", - bus, sub_bus, agent_id, err); - continue; - } - err = HvCallPci_configLoad16(bus, sub_bus, agent_id, - PCI_DEVICE_ID, &device_id); - if (err) { - printk(KERN_DEBUG - "ReadDevice(%x, %x, %x) == %x\n", - bus, sub_bus, agent_id, err); - continue; - } - err = HvCallPci_configLoad32(bus, sub_bus, agent_id, - PCI_CLASS_REVISION , &class_id); - if (err) { - printk(KERN_DEBUG - "ReadClass(%x, %x, %x) == %x\n", - bus, sub_bus, agent_id, err); - continue; - } - - devfn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(eads_id_sel), - function); - cp = dt_find_pci_class_name(class_id >> 16); - if (cp && cp->name) - strncpy(buf, cp->name, sizeof(buf) - 1); - else - snprintf(buf, sizeof(buf), "pci%x,%x", - vendor_id, device_id); - buf[sizeof(buf) - 1] = '\0'; - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), - "@%x", PCI_SLOT(devfn)); - buf[sizeof(buf) - 1] = '\0'; - if (function != 0) - snprintf(buf + strlen(buf), - sizeof(buf) - strlen(buf), - ",%x", function); - dt_start_node(dt, buf); - reg[0] = (bus << 16) | (devfn << 8); - reg[1] = 0; - reg[2] = 0; - reg[3] = 0; - reg[4] = 0; - dt_prop_u32_list(dt, "reg", reg, 5); - if (cp && (cp->type || cp->name)) - dt_prop_str(dt, "device_type", - cp->type ? cp->type : cp->name); - dt_prop_u32(dt, "vendor-id", vendor_id); - dt_prop_u32(dt, "device-id", device_id); - dt_prop_u32(dt, "class-code", class_id >> 8); - dt_prop_u32(dt, "revision-id", class_id & 0xff); - dt_prop_u32(dt, "linux,subbus", sub_bus); - dt_prop_u32(dt, "linux,agent-id", agent_id); - dt_prop_u32(dt, "linux,logical-slot-number", - bridge_info->logicalSlotNumber); - dt_end_node(dt); - - } - } -} - -static void __init scan_bridge(struct iseries_flat_dt *dt, HvBusNumber bus, - HvSubBusNumber sub_bus, int id_sel) -{ - struct HvCallPci_BridgeInfo bridge_info; - HvAgentId agent_id; - int function; - int ret; - - /* Note: hvSubBus and irq is always be 0 at this level! */ - for (function = 0; function < 8; ++function) { - agent_id = ISERIES_PCI_AGENTID(id_sel, function); - ret = HvCallXm_connectBusUnit(bus, sub_bus, agent_id, 0); - if (ret != 0) { - if (ret != 0xb) - printk(KERN_DEBUG "connectBusUnit(%x, %x, %x) " - "== %x\n", - bus, sub_bus, agent_id, ret); - continue; - } - printk("found device at bus %d idsel %d func %d (AgentId %x)\n", - bus, id_sel, function, agent_id); - ret = HvCallPci_getBusUnitInfo(bus, sub_bus, agent_id, - iseries_hv_addr(&bridge_info), - sizeof(struct HvCallPci_BridgeInfo)); - if (ret != 0) - continue; - printk("bridge info: type %x subbus %x " - "maxAgents %x maxsubbus %x logslot %x\n", - bridge_info.busUnitInfo.deviceType, - bridge_info.subBusNumber, - bridge_info.maxAgents, - bridge_info.maxSubBusNumber, - bridge_info.logicalSlotNumber); - if (bridge_info.busUnitInfo.deviceType == - HvCallPci_BridgeDevice) - scan_bridge_slot(dt, bus, &bridge_info); - else - printk("PCI: Invalid Bridge Configuration(0x%02X)", - bridge_info.busUnitInfo.deviceType); - } -} - -static void __init scan_phb(struct iseries_flat_dt *dt, HvBusNumber bus) -{ - struct HvCallPci_DeviceInfo dev_info; - const HvSubBusNumber sub_bus = 0; /* EADs is always 0. */ - int err; - int id_sel; - const int max_agents = 8; - - /* - * Probe for EADs Bridges - */ - for (id_sel = 1; id_sel < max_agents; ++id_sel) { - err = HvCallPci_getDeviceInfo(bus, sub_bus, id_sel, - iseries_hv_addr(&dev_info), - sizeof(struct HvCallPci_DeviceInfo)); - if (err) { - if (err != 0x302) - printk(KERN_DEBUG "getDeviceInfo(%x, %x, %x) " - "== %x\n", - bus, sub_bus, id_sel, err); - continue; - } - if (dev_info.deviceType != HvCallPci_NodeDevice) { - printk(KERN_DEBUG "PCI: Invalid System Configuration" - "(0x%02X) for bus 0x%02x id 0x%02x.\n", - dev_info.deviceType, bus, id_sel); - continue; - } - scan_bridge(dt, bus, sub_bus, id_sel); - } -} - -static void __init dt_pci_devices(struct iseries_flat_dt *dt) -{ - HvBusNumber bus; - char buf[32]; - u32 buses[2]; - int phb_num = 0; - - /* Check all possible buses. */ - for (bus = 0; bus < 256; bus++) { - int err = HvCallXm_testBus(bus); - - if (err) { - /* - * Check for Unexpected Return code, a clue that - * something has gone wrong. - */ - if (err != 0x0301) - printk(KERN_ERR "Unexpected Return on Probe" - "(0x%02X): 0x%04X", bus, err); - continue; - } - printk("bus %d appears to exist\n", bus); - snprintf(buf, 32, "pci@%d", phb_num); - dt_start_node(dt, buf); - dt_prop_str(dt, "device_type", "pci"); - dt_prop_str(dt, "compatible", "IBM,iSeries-Logical-PHB"); - dt_prop_u32(dt, "#address-cells", 3); - dt_prop_u32(dt, "#size-cells", 2); - buses[0] = buses[1] = bus; - dt_prop_u32_list(dt, "bus-range", buses, 2); - scan_phb(dt, bus); - dt_end_node(dt); - phb_num++; - } -} - -static void __init build_flat_dt(struct iseries_flat_dt *dt, - unsigned long phys_mem_size) -{ - u64 tmp[2]; - - dt_init(dt); - - dt_start_node(dt, ""); - - dt_prop_u32(dt, "#address-cells", 2); - dt_prop_u32(dt, "#size-cells", 2); - dt_model(dt); - - /* /memory */ - dt_start_node(dt, "memory@0"); - dt_prop_str(dt, "name", "memory"); - dt_prop_str(dt, "device_type", "memory"); - tmp[0] = 0; - tmp[1] = phys_mem_size; - dt_prop_u64_list(dt, "reg", tmp, 2); - dt_end_node(dt); - - /* /chosen */ - dt_start_node(dt, "chosen"); - dt_prop_str(dt, "bootargs", cmd_line); - dt_end_node(dt); - - dt_cpus(dt); - - dt_vdevices(dt); - dt_pci_devices(dt); - - dt_end_node(dt); - - dt_push_u32(dt, OF_DT_END); -} - void * __init iSeries_early_setup(void) { unsigned long phys_mem_size; @@ -1294,9 +720,7 @@ void * __init iSeries_early_setup(void) iSeries_get_cmdline(); - build_flat_dt(&iseries_dt, phys_mem_size); - - return (void *) __pa(&iseries_dt); + return (void *) __pa(build_flat_dt(phys_mem_size)); } static void hvputc(char c) diff --git a/arch/powerpc/platforms/iseries/setup.h b/arch/powerpc/platforms/iseries/setup.h index 5213044ec41..0a47ac53c95 100644 --- a/arch/powerpc/platforms/iseries/setup.h +++ b/arch/powerpc/platforms/iseries/setup.h @@ -21,4 +21,6 @@ extern unsigned long iSeries_get_boot_time(void); extern int iSeries_set_rtc_time(struct rtc_time *tm); extern void iSeries_get_rtc_time(struct rtc_time *tm); +extern void *build_flat_dt(unsigned long phys_mem_size); + #endif /* __ISERIES_SETUP_H__ */ -- cgit v1.2.3 From c4e3ea2553308ba65fea582dc9a42221ef8b49e5 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Fri, 19 May 2006 17:04:48 +1000 Subject: [PATCH] powerpc: make iSeries flattened device tree dynamic First we capture all the strings from dt.c statically by noting that gcc puts them in a special section of their own. Idea from Michael Ellerman. Then we move the flattened device tree to klimit. Still to come, making the values blob grow as needed. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/vmlinux.lds.S | 5 ++ arch/powerpc/platforms/iseries/Makefile | 5 +- arch/powerpc/platforms/iseries/dt.c | 96 +++++++++++++++++++-------------- 3 files changed, 66 insertions(+), 40 deletions(-) diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S index fe79c2584cb..8b25953dc4f 100644 --- a/arch/powerpc/kernel/vmlinux.lds.S +++ b/arch/powerpc/kernel/vmlinux.lds.S @@ -93,6 +93,11 @@ SECTIONS __ptov_table_begin = .; *(.ptov_fixup); __ptov_table_end = .; +#ifdef CONFIG_PPC_ISERIES + __dt_strings_start = .; + *(.dt_strings); + __dt_strings_end = .; +#endif } . = ALIGN(16); diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile index 32306214a30..dee4eb4d8be 100644 --- a/arch/powerpc/platforms/iseries/Makefile +++ b/arch/powerpc/platforms/iseries/Makefile @@ -1,8 +1,11 @@ EXTRA_CFLAGS += -mno-minimal-toc -obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o dt.o mf.o lpevents.o \ +obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o dt_mod.o mf.o lpevents.o \ hvcall.o proc.o htab.o iommu.o misc.o irq.o obj-$(CONFIG_PCI) += pci.o vpdinfo.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_VIOPATH) += viopath.o obj-$(CONFIG_MODULES) += ksyms.o + +$(obj)/dt_mod.o: $(obj)/dt.o + @$(OBJCOPY) --rename-section .rodata.str1.8=.dt_strings $(obj)/dt.o $(obj)/dt_mod.o diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c index 93d4233e73e..0371329f82e 100644 --- a/arch/powerpc/platforms/iseries/dt.c +++ b/arch/powerpc/platforms/iseries/dt.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -47,6 +48,9 @@ #define DBG(fmt...) #endif +extern char __dt_strings_start[]; +extern char __dt_strings_end[]; + struct blob { unsigned char data[PAGE_SIZE * 2]; unsigned long next; @@ -55,26 +59,34 @@ struct blob { struct iseries_flat_dt { struct boot_param_header header; u64 reserve_map[2]; - struct blob dt; - struct blob strings; + struct blob *dt; }; -static struct iseries_flat_dt iseries_dt; +static struct iseries_flat_dt *iseries_dt; -static void __init dt_init(struct iseries_flat_dt *dt) +static struct iseries_flat_dt * __init dt_init(void) { + struct iseries_flat_dt *dt; + unsigned long str_len; + + str_len = __dt_strings_end - __dt_strings_start; + dt = (struct iseries_flat_dt *)ALIGN(klimit, 8); dt->header.off_mem_rsvmap = offsetof(struct iseries_flat_dt, reserve_map); - dt->header.off_dt_struct = offsetof(struct iseries_flat_dt, dt); - dt->header.off_dt_strings = offsetof(struct iseries_flat_dt, strings); - dt->header.totalsize = sizeof(struct iseries_flat_dt); - dt->header.dt_strings_size = sizeof(struct blob); + dt->header.off_dt_strings = ALIGN(sizeof(*dt), 8); + dt->header.off_dt_struct = dt->header.off_dt_strings + + ALIGN(str_len, 8); + dt->dt = (struct blob *)((unsigned long)dt + dt->header.off_dt_struct); + klimit = ALIGN((unsigned long)(dt->dt) + sizeof(struct blob), 8); + dt->header.totalsize = klimit - (unsigned long)dt; + dt->header.dt_strings_size = str_len; /* There is no notion of hardware cpu id on iSeries */ dt->header.boot_cpuid_phys = smp_processor_id(); - dt->dt.next = (unsigned long)&dt->dt.data; - dt->strings.next = (unsigned long)&dt->strings.data; + dt->dt->next = (unsigned long)&dt->dt->data; + memcpy((char *)dt + dt->header.off_dt_strings, __dt_strings_start, + str_len); dt->header.magic = OF_DT_HEADER; dt->header.version = 0x10; @@ -82,6 +94,8 @@ static void __init dt_init(struct iseries_flat_dt *dt) dt->reserve_map[0] = 0; dt->reserve_map[1] = 0; + + return dt; } static void __init dt_check_blob(struct blob *b) @@ -94,19 +108,19 @@ static void __init dt_check_blob(struct blob *b) static void __init dt_push_u32(struct iseries_flat_dt *dt, u32 value) { - *((u32*)dt->dt.next) = value; - dt->dt.next += sizeof(u32); + *((u32*)dt->dt->next) = value; + dt->dt->next += sizeof(u32); - dt_check_blob(&dt->dt); + dt_check_blob(dt->dt); } #ifdef notyet static void __init dt_push_u64(struct iseries_flat_dt *dt, u64 value) { - *((u64*)dt->dt.next) = value; - dt->dt.next += sizeof(u64); + *((u64*)dt->dt->next) = value; + dt->dt->next += sizeof(u64); - dt_check_blob(&dt->dt); + dt_check_blob(dt->dt); } #endif @@ -125,7 +139,7 @@ static unsigned long __init dt_push_bytes(struct blob *blob, char *data, int len static void __init dt_start_node(struct iseries_flat_dt *dt, char *name) { dt_push_u32(dt, OF_DT_BEGIN_NODE); - dt_push_bytes(&dt->dt, name, strlen(name) + 1); + dt_push_bytes(dt->dt, name, strlen(name) + 1); } #define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE) @@ -140,14 +154,13 @@ static void __init dt_prop(struct iseries_flat_dt *dt, char *name, /* Length of the data */ dt_push_u32(dt, len); - /* Put the property name in the string blob. */ - offset = dt_push_bytes(&dt->strings, name, strlen(name) + 1); + offset = name - __dt_strings_start; /* The offset of the properties name in the string blob. */ dt_push_u32(dt, (u32)offset); /* The actual data. */ - dt_push_bytes(&dt->dt, data, len); + dt_push_bytes(dt->dt, data, len); } static void __init dt_prop_str(struct iseries_flat_dt *dt, char *name, @@ -579,40 +592,45 @@ static void __init dt_pci_devices(struct iseries_flat_dt *dt) } } +static void dt_finish(struct iseries_flat_dt *dt) +{ + dt_push_u32(dt, OF_DT_END); +} + void * __init build_flat_dt(unsigned long phys_mem_size) { u64 tmp[2]; - dt_init(&iseries_dt); + iseries_dt = dt_init(); - dt_start_node(&iseries_dt, ""); + dt_start_node(iseries_dt, ""); - dt_prop_u32(&iseries_dt, "#address-cells", 2); - dt_prop_u32(&iseries_dt, "#size-cells", 2); - dt_model(&iseries_dt); + dt_prop_u32(iseries_dt, "#address-cells", 2); + dt_prop_u32(iseries_dt, "#size-cells", 2); + dt_model(iseries_dt); /* /memory */ - dt_start_node(&iseries_dt, "memory@0"); - dt_prop_str(&iseries_dt, "name", "memory"); - dt_prop_str(&iseries_dt, "device_type", "memory"); + dt_start_node(iseries_dt, "memory@0"); + dt_prop_str(iseries_dt, "name", "memory"); + dt_prop_str(iseries_dt, "device_type", "memory"); tmp[0] = 0; tmp[1] = phys_mem_size; - dt_prop_u64_list(&iseries_dt, "reg", tmp, 2); - dt_end_node(&iseries_dt); + dt_prop_u64_list(iseries_dt, "reg", tmp, 2); + dt_end_node(iseries_dt); /* /chosen */ - dt_start_node(&iseries_dt, "chosen"); - dt_prop_str(&iseries_dt, "bootargs", cmd_line); - dt_end_node(&iseries_dt); + dt_start_node(iseries_dt, "chosen"); + dt_prop_str(iseries_dt, "bootargs", cmd_line); + dt_end_node(iseries_dt); - dt_cpus(&iseries_dt); + dt_cpus(iseries_dt); - dt_vdevices(&iseries_dt); - dt_pci_devices(&iseries_dt); + dt_vdevices(iseries_dt); + dt_pci_devices(iseries_dt); - dt_end_node(&iseries_dt); + dt_end_node(iseries_dt); - dt_push_u32(&iseries_dt, OF_DT_END); + dt_finish(iseries_dt); - return &iseries_dt; + return iseries_dt; } -- cgit v1.2.3 From 72a14eafb243b1f31118ea55a7e8c2588b5ad468 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Fri, 19 May 2006 17:04:12 +1000 Subject: [PATCH] powerpc: make iSeries flattened device tree dynamic - part 2 This actually simplies things as we just figure out how much space we used at the end and adjust klimit then. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/dt.c | 62 ++++++++++++------------------------- 1 file changed, 19 insertions(+), 43 deletions(-) diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c index 0371329f82e..2a51ec1e335 100644 --- a/arch/powerpc/platforms/iseries/dt.c +++ b/arch/powerpc/platforms/iseries/dt.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -51,15 +50,10 @@ extern char __dt_strings_start[]; extern char __dt_strings_end[]; -struct blob { - unsigned char data[PAGE_SIZE * 2]; - unsigned long next; -}; - struct iseries_flat_dt { struct boot_param_header header; u64 reserve_map[2]; - struct blob *dt; + void *data; }; static struct iseries_flat_dt *iseries_dt; @@ -76,15 +70,12 @@ static struct iseries_flat_dt * __init dt_init(void) dt->header.off_dt_strings = ALIGN(sizeof(*dt), 8); dt->header.off_dt_struct = dt->header.off_dt_strings + ALIGN(str_len, 8); - dt->dt = (struct blob *)((unsigned long)dt + dt->header.off_dt_struct); - klimit = ALIGN((unsigned long)(dt->dt) + sizeof(struct blob), 8); - dt->header.totalsize = klimit - (unsigned long)dt; + dt->data = (void *)((unsigned long)dt + dt->header.off_dt_struct); dt->header.dt_strings_size = str_len; /* There is no notion of hardware cpu id on iSeries */ dt->header.boot_cpuid_phys = smp_processor_id(); - dt->dt->next = (unsigned long)&dt->dt->data; memcpy((char *)dt + dt->header.off_dt_strings, __dt_strings_start, str_len); @@ -98,54 +89,37 @@ static struct iseries_flat_dt * __init dt_init(void) return dt; } -static void __init dt_check_blob(struct blob *b) -{ - if (b->next >= (unsigned long)&b->next) { - DBG("Ran out of space in flat device tree blob!\n"); - BUG(); - } -} - static void __init dt_push_u32(struct iseries_flat_dt *dt, u32 value) { - *((u32*)dt->dt->next) = value; - dt->dt->next += sizeof(u32); - - dt_check_blob(dt->dt); + *((u32 *)dt->data) = value; + dt->data += sizeof(u32); } #ifdef notyet static void __init dt_push_u64(struct iseries_flat_dt *dt, u64 value) { - *((u64*)dt->dt->next) = value; - dt->dt->next += sizeof(u64); - - dt_check_blob(dt->dt); + *((u64 *)dt->data) = value; + dt->data += sizeof(u64); } #endif -static unsigned long __init dt_push_bytes(struct blob *blob, char *data, int len) +static void __init dt_push_bytes(struct iseries_flat_dt *dt, char *data, + int len) { - unsigned long start = blob->next - (unsigned long)blob->data; - - memcpy((char *)blob->next, data, len); - blob->next = _ALIGN(blob->next + len, 4); - - dt_check_blob(blob); - - return start; + memcpy(dt->data, data, len); + dt->data += ALIGN(len, 4); } static void __init dt_start_node(struct iseries_flat_dt *dt, char *name) { dt_push_u32(dt, OF_DT_BEGIN_NODE); - dt_push_bytes(dt->dt, name, strlen(name) + 1); + dt_push_bytes(dt, name, strlen(name) + 1); } #define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE) static void __init dt_prop(struct iseries_flat_dt *dt, char *name, - char *data, int len) + void *data, int len) { unsigned long offset; @@ -160,7 +134,7 @@ static void __init dt_prop(struct iseries_flat_dt *dt, char *name, dt_push_u32(dt, (u32)offset); /* The actual data. */ - dt_push_bytes(dt->dt, data, len); + dt_push_bytes(dt, data, len); } static void __init dt_prop_str(struct iseries_flat_dt *dt, char *name, @@ -171,24 +145,24 @@ static void __init dt_prop_str(struct iseries_flat_dt *dt, char *name, static void __init dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data) { - dt_prop(dt, name, (char *)&data, sizeof(u32)); + dt_prop(dt, name, &data, sizeof(u32)); } static void __init dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data) { - dt_prop(dt, name, (char *)&data, sizeof(u64)); + dt_prop(dt, name, &data, sizeof(u64)); } static void __init dt_prop_u64_list(struct iseries_flat_dt *dt, char *name, u64 *data, int n) { - dt_prop(dt, name, (char *)data, sizeof(u64) * n); + dt_prop(dt, name, data, sizeof(u64) * n); } static void __init dt_prop_u32_list(struct iseries_flat_dt *dt, char *name, u32 *data, int n) { - dt_prop(dt, name, (char *)data, sizeof(u32) * n); + dt_prop(dt, name, data, sizeof(u32) * n); } #ifdef notyet @@ -595,6 +569,8 @@ static void __init dt_pci_devices(struct iseries_flat_dt *dt) static void dt_finish(struct iseries_flat_dt *dt) { dt_push_u32(dt, OF_DT_END); + dt->header.totalsize = (unsigned long)dt->data - (unsigned long)dt; + klimit = ALIGN((unsigned long)dt->data, 8); } void * __init build_flat_dt(unsigned long phys_mem_size) -- cgit v1.2.3 From 7499bf1a4cabde789e7694b33d01a1913ae1dddf Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Fri, 19 May 2006 17:06:38 +1000 Subject: [PATCH] powerpc: cleanup of iSeries flat device tree Consolidate the vio device node creation. Make some parameters const. Make a few more things __initdata. Get the device_type strings out of the device tree blob. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/dt.c | 199 ++++++++++++++++++------------------ 1 file changed, 101 insertions(+), 98 deletions(-) diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c index 2a51ec1e335..d3444aabe76 100644 --- a/arch/powerpc/platforms/iseries/dt.c +++ b/arch/powerpc/platforms/iseries/dt.c @@ -47,16 +47,34 @@ #define DBG(fmt...) #endif +/* + * These are created by the linker script at the start and end + * of the section containing all the strings from this file. + */ extern char __dt_strings_start[]; extern char __dt_strings_end[]; struct iseries_flat_dt { struct boot_param_header header; u64 reserve_map[2]; - void *data; }; -static struct iseries_flat_dt *iseries_dt; +static void * __initdata dt_data; + +/* + * Putting these strings here keeps them out of the section + * that we rename to .dt_strings using objcopy and capture + * for the strings blob of the flattened device tree. + */ +static char __initdata device_type_cpu[] = "cpu"; +static char __initdata device_type_memory[] = "memory"; +static char __initdata device_type_serial[] = "serial"; +static char __initdata device_type_network[] = "network"; +static char __initdata device_type_block[] = "block"; +static char __initdata device_type_byte[] = "byte"; +static char __initdata device_type_pci[] = "pci"; +static char __initdata device_type_vdevice[] = "vdevice"; +static char __initdata device_type_vscsi[] = "vscsi"; static struct iseries_flat_dt * __init dt_init(void) { @@ -70,7 +88,7 @@ static struct iseries_flat_dt * __init dt_init(void) dt->header.off_dt_strings = ALIGN(sizeof(*dt), 8); dt->header.off_dt_struct = dt->header.off_dt_strings + ALIGN(str_len, 8); - dt->data = (void *)((unsigned long)dt + dt->header.off_dt_struct); + dt_data = (void *)((unsigned long)dt + dt->header.off_dt_struct); dt->header.dt_strings_size = str_len; /* There is no notion of hardware cpu id on iSeries */ @@ -91,26 +109,26 @@ static struct iseries_flat_dt * __init dt_init(void) static void __init dt_push_u32(struct iseries_flat_dt *dt, u32 value) { - *((u32 *)dt->data) = value; - dt->data += sizeof(u32); + *((u32 *)dt_data) = value; + dt_data += sizeof(u32); } #ifdef notyet static void __init dt_push_u64(struct iseries_flat_dt *dt, u64 value) { - *((u64 *)dt->data) = value; - dt->data += sizeof(u64); + *((u64 *)dt_data) = value; + dt_data += sizeof(u64); } #endif -static void __init dt_push_bytes(struct iseries_flat_dt *dt, char *data, +static void __init dt_push_bytes(struct iseries_flat_dt *dt, const char *data, int len) { - memcpy(dt->data, data, len); - dt->data += ALIGN(len, 4); + memcpy(dt_data, data, len); + dt_data += ALIGN(len, 4); } -static void __init dt_start_node(struct iseries_flat_dt *dt, char *name) +static void __init dt_start_node(struct iseries_flat_dt *dt, const char *name) { dt_push_u32(dt, OF_DT_BEGIN_NODE); dt_push_bytes(dt, name, strlen(name) + 1); @@ -118,8 +136,8 @@ static void __init dt_start_node(struct iseries_flat_dt *dt, char *name) #define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE) -static void __init dt_prop(struct iseries_flat_dt *dt, char *name, - void *data, int len) +static void __init dt_prop(struct iseries_flat_dt *dt, const char *name, + const void *data, int len) { unsigned long offset; @@ -137,36 +155,40 @@ static void __init dt_prop(struct iseries_flat_dt *dt, char *name, dt_push_bytes(dt, data, len); } -static void __init dt_prop_str(struct iseries_flat_dt *dt, char *name, - char *data) +static void __init dt_prop_str(struct iseries_flat_dt *dt, const char *name, + const char *data) { dt_prop(dt, name, data, strlen(data) + 1); /* + 1 for NULL */ } -static void __init dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data) +static void __init dt_prop_u32(struct iseries_flat_dt *dt, const char *name, + u32 data) { dt_prop(dt, name, &data, sizeof(u32)); } -static void __init dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data) +#ifdef notyet +static void __init dt_prop_u64(struct iseries_flat_dt *dt, const char *name, + u64 data) { dt_prop(dt, name, &data, sizeof(u64)); } +#endif -static void __init dt_prop_u64_list(struct iseries_flat_dt *dt, char *name, - u64 *data, int n) +static void __init dt_prop_u64_list(struct iseries_flat_dt *dt, + const char *name, u64 *data, int n) { dt_prop(dt, name, data, sizeof(u64) * n); } -static void __init dt_prop_u32_list(struct iseries_flat_dt *dt, char *name, - u32 *data, int n) +static void __init dt_prop_u32_list(struct iseries_flat_dt *dt, + const char *name, u32 *data, int n) { dt_prop(dt, name, data, sizeof(u32) * n); } #ifdef notyet -static void __init dt_prop_empty(struct iseries_flat_dt *dt, char *name) +static void __init dt_prop_empty(struct iseries_flat_dt *dt, const char *name) { dt_prop(dt, name, NULL, 0); } @@ -199,7 +221,7 @@ static void __init dt_cpus(struct iseries_flat_dt *dt) snprintf(p, 32 - (p - buf), "@%d", i); dt_start_node(dt, buf); - dt_prop_str(dt, "device_type", "cpu"); + dt_prop_str(dt, "device_type", device_type_cpu); index = lppaca[i].dyn_hv_phys_proc_index; d = &xIoHriProcessorVpd[index]; @@ -244,32 +266,41 @@ static void __init dt_model(struct iseries_flat_dt *dt) dt_prop_str(dt, "compatible", "IBM,iSeries"); } +static void __init dt_do_vdevice(struct iseries_flat_dt *dt, + const char *name, u32 reg, int unit, + const char *type, const char *compat, int end) +{ + char buf[32]; + + snprintf(buf, 32, "%s@%08x", name, reg + ((unit >= 0) ? unit : 0)); + dt_start_node(dt, buf); + dt_prop_str(dt, "device_type", type); + if (compat) + dt_prop_str(dt, "compatible", compat); + dt_prop_u32(dt, "reg", reg + ((unit >= 0) ? unit : 0)); + if (unit >= 0) + dt_prop_u32(dt, "linux,unit_address", unit); + if (end) + dt_end_node(dt); +} + static void __init dt_vdevices(struct iseries_flat_dt *dt) { u32 reg = 0; HvLpIndexMap vlan_map; int i; - char buf[32]; dt_start_node(dt, "vdevice"); - dt_prop_str(dt, "device_type", "vdevice"); + dt_prop_str(dt, "device_type", device_type_vdevice); dt_prop_str(dt, "compatible", "IBM,iSeries-vdevice"); dt_prop_u32(dt, "#address-cells", 1); dt_prop_u32(dt, "#size-cells", 0); - snprintf(buf, sizeof(buf), "vty@%08x", reg); - dt_start_node(dt, buf); - dt_prop_str(dt, "device_type", "serial"); - dt_prop_u32(dt, "reg", reg); - dt_end_node(dt); + dt_do_vdevice(dt, "vty", reg, -1, device_type_serial, NULL, 1); reg++; - snprintf(buf, sizeof(buf), "v-scsi@%08x", reg); - dt_start_node(dt, buf); - dt_prop_str(dt, "device_type", "vscsi"); - dt_prop_str(dt, "compatible", "IBM,v-scsi"); - dt_prop_u32(dt, "reg", reg); - dt_end_node(dt); + dt_do_vdevice(dt, "v-scsi", reg, -1, device_type_vscsi, + "IBM,v-scsi", 1); reg++; vlan_map = HvLpConfig_getVirtualLanIndexMap(); @@ -278,13 +309,8 @@ static void __init dt_vdevices(struct iseries_flat_dt *dt) if ((vlan_map & (0x8000 >> i)) == 0) continue; - snprintf(buf, 32, "l-lan@%08x", reg + i); - dt_start_node(dt, buf); - dt_prop_str(dt, "device_type", "network"); - dt_prop_str(dt, "compatible", "IBM,iSeries-l-lan"); - dt_prop_u32(dt, "reg", reg + i); - dt_prop_u32(dt, "linux,unit_address", i); - + dt_do_vdevice(dt, "l-lan", reg, i, device_type_network, + "IBM,iSeries-l-lan", 0); mac_addr[0] = 0x02; mac_addr[1] = 0x01; mac_addr[2] = 0xff; @@ -300,47 +326,31 @@ static void __init dt_vdevices(struct iseries_flat_dt *dt) } reg += HVMAXARCHITECTEDVIRTUALLANS; - for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++) { - snprintf(buf, 32, "viodasd@%08x", reg + i); - dt_start_node(dt, buf); - dt_prop_str(dt, "device_type", "block"); - dt_prop_str(dt, "compatible", "IBM,iSeries-viodasd"); - dt_prop_u32(dt, "reg", reg + i); - dt_prop_u32(dt, "linux,unit_address", i); - dt_end_node(dt); - } + for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++) + dt_do_vdevice(dt, "viodasd", reg, i, device_type_block, + "IBM,iSeries-viodasd", 1); reg += HVMAXARCHITECTEDVIRTUALDISKS; - for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++) { - snprintf(buf, 32, "viocd@%08x", reg + i); - dt_start_node(dt, buf); - dt_prop_str(dt, "device_type", "block"); - dt_prop_str(dt, "compatible", "IBM,iSeries-viocd"); - dt_prop_u32(dt, "reg", reg + i); - dt_prop_u32(dt, "linux,unit_address", i); - dt_end_node(dt); - } + + for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++) + dt_do_vdevice(dt, "viocd", reg, i, device_type_block, + "IBM,iSeries-viocd", 1); reg += HVMAXARCHITECTEDVIRTUALCDROMS; - for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++) { - snprintf(buf, 32, "viotape@%08x", reg + i); - dt_start_node(dt, buf); - dt_prop_str(dt, "device_type", "byte"); - dt_prop_str(dt, "compatible", "IBM,iSeries-viotape"); - dt_prop_u32(dt, "reg", reg + i); - dt_prop_u32(dt, "linux,unit_address", i); - dt_end_node(dt); - } + + for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++) + dt_do_vdevice(dt, "viotape", reg, i, device_type_byte, + "IBM,iSeries-viotape", 1); dt_end_node(dt); } struct pci_class_name { u16 code; - char *name; - char *type; + const char *name; + const char *type; }; static struct pci_class_name __initdata pci_class_name[] = { - { PCI_CLASS_NETWORK_ETHERNET, "ethernet", "network" }, + { PCI_CLASS_NETWORK_ETHERNET, "ethernet", device_type_network }, }; static struct pci_class_name * __init dt_find_pci_class_name(u16 class_code) @@ -384,9 +394,7 @@ static void __init scan_bridge_slot(struct iseries_flat_dt *dt, agent_id, 0); if (err) { if (err != 0x302) - printk(KERN_DEBUG - "connectBusUnit(%x, %x, %x) " - "== %x\n", + DBG("connectBusUnit(%x, %x, %x) %x\n", bus, sub_bus, agent_id, err); continue; } @@ -394,24 +402,21 @@ static void __init scan_bridge_slot(struct iseries_flat_dt *dt, err = HvCallPci_configLoad16(bus, sub_bus, agent_id, PCI_VENDOR_ID, &vendor_id); if (err) { - printk(KERN_DEBUG - "ReadVendor(%x, %x, %x) == %x\n", + DBG("ReadVendor(%x, %x, %x) %x\n", bus, sub_bus, agent_id, err); continue; } err = HvCallPci_configLoad16(bus, sub_bus, agent_id, PCI_DEVICE_ID, &device_id); if (err) { - printk(KERN_DEBUG - "ReadDevice(%x, %x, %x) == %x\n", + DBG("ReadDevice(%x, %x, %x) %x\n", bus, sub_bus, agent_id, err); continue; } err = HvCallPci_configLoad32(bus, sub_bus, agent_id, PCI_CLASS_REVISION , &class_id); if (err) { - printk(KERN_DEBUG - "ReadClass(%x, %x, %x) == %x\n", + DBG("ReadClass(%x, %x, %x) %x\n", bus, sub_bus, agent_id, err); continue; } @@ -470,19 +475,18 @@ static void __init scan_bridge(struct iseries_flat_dt *dt, HvBusNumber bus, ret = HvCallXm_connectBusUnit(bus, sub_bus, agent_id, 0); if (ret != 0) { if (ret != 0xb) - printk(KERN_DEBUG "connectBusUnit(%x, %x, %x) " - "== %x\n", + DBG("connectBusUnit(%x, %x, %x) %x\n", bus, sub_bus, agent_id, ret); continue; } - printk("found device at bus %d idsel %d func %d (AgentId %x)\n", + DBG("found device at bus %d idsel %d func %d (AgentId %x)\n", bus, id_sel, function, agent_id); ret = HvCallPci_getBusUnitInfo(bus, sub_bus, agent_id, iseries_hv_addr(&bridge_info), sizeof(struct HvCallPci_BridgeInfo)); if (ret != 0) continue; - printk("bridge info: type %x subbus %x " + DBG("bridge info: type %x subbus %x " "maxAgents %x maxsubbus %x logslot %x\n", bridge_info.busUnitInfo.deviceType, bridge_info.subBusNumber, @@ -493,7 +497,7 @@ static void __init scan_bridge(struct iseries_flat_dt *dt, HvBusNumber bus, HvCallPci_BridgeDevice) scan_bridge_slot(dt, bus, &bridge_info); else - printk("PCI: Invalid Bridge Configuration(0x%02X)", + DBG("PCI: Invalid Bridge Configuration(0x%02X)", bridge_info.busUnitInfo.deviceType); } } @@ -515,13 +519,12 @@ static void __init scan_phb(struct iseries_flat_dt *dt, HvBusNumber bus) sizeof(struct HvCallPci_DeviceInfo)); if (err) { if (err != 0x302) - printk(KERN_DEBUG "getDeviceInfo(%x, %x, %x) " - "== %x\n", + DBG("getDeviceInfo(%x, %x, %x) %x\n", bus, sub_bus, id_sel, err); continue; } if (dev_info.deviceType != HvCallPci_NodeDevice) { - printk(KERN_DEBUG "PCI: Invalid System Configuration" + DBG("PCI: Invalid System Configuration" "(0x%02X) for bus 0x%02x id 0x%02x.\n", dev_info.deviceType, bus, id_sel); continue; @@ -547,14 +550,14 @@ static void __init dt_pci_devices(struct iseries_flat_dt *dt) * something has gone wrong. */ if (err != 0x0301) - printk(KERN_ERR "Unexpected Return on Probe" - "(0x%02X): 0x%04X", bus, err); + DBG("Unexpected Return on Probe(0x%02X) " + "0x%04X\n", bus, err); continue; } - printk("bus %d appears to exist\n", bus); + DBG("bus %d appears to exist\n", bus); snprintf(buf, 32, "pci@%d", phb_num); dt_start_node(dt, buf); - dt_prop_str(dt, "device_type", "pci"); + dt_prop_str(dt, "device_type", device_type_pci); dt_prop_str(dt, "compatible", "IBM,iSeries-Logical-PHB"); dt_prop_u32(dt, "#address-cells", 3); dt_prop_u32(dt, "#size-cells", 2); @@ -569,12 +572,13 @@ static void __init dt_pci_devices(struct iseries_flat_dt *dt) static void dt_finish(struct iseries_flat_dt *dt) { dt_push_u32(dt, OF_DT_END); - dt->header.totalsize = (unsigned long)dt->data - (unsigned long)dt; - klimit = ALIGN((unsigned long)dt->data, 8); + dt->header.totalsize = (unsigned long)dt_data - (unsigned long)dt; + klimit = ALIGN((unsigned long)dt_data, 8); } void * __init build_flat_dt(unsigned long phys_mem_size) { + struct iseries_flat_dt *iseries_dt; u64 tmp[2]; iseries_dt = dt_init(); @@ -587,8 +591,7 @@ void * __init build_flat_dt(unsigned long phys_mem_size) /* /memory */ dt_start_node(iseries_dt, "memory@0"); - dt_prop_str(iseries_dt, "name", "memory"); - dt_prop_str(iseries_dt, "device_type", "memory"); + dt_prop_str(iseries_dt, "device_type", device_type_memory); tmp[0] = 0; tmp[1] = phys_mem_size; dt_prop_u64_list(iseries_dt, "reg", tmp, 2); -- cgit v1.2.3 From 0a9cb46a73abd6c45e7c986bec984eed60c417b6 Mon Sep 17 00:00:00 2001 From: Jon Mason Date: Fri, 19 May 2006 15:35:32 -0500 Subject: [PATCH] remove powerpc bitops in favor of existing generic bitops There already exists a big endian safe bitops implementation in lib/find_next_bit.c. The code in it is 90%+ common with the powerpc specific version, so the powerpc version is redundant. This patch makes the necessary changes to use the generic bitops in powerpc, and removes the powerpc specific version. Signed-off-by: Jon Mason Signed-off-by: Paul Mackerras --- arch/powerpc/Kconfig | 4 ++ arch/powerpc/lib/Makefile | 1 - arch/powerpc/lib/bitops.c | 150 ------------------------------------------- arch/ppc/Kconfig | 4 ++ include/asm-powerpc/bitops.h | 6 +- 5 files changed, 11 insertions(+), 154 deletions(-) delete mode 100644 arch/powerpc/lib/bitops.c diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 6729c98b66f..75ba0ec49e5 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -45,6 +45,10 @@ config GENERIC_CALIBRATE_DELAY bool default y +config GENERIC_FIND_NEXT_BIT + bool + default y + config PPC bool default y diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile index 34f5c2e074c..ae354d65b82 100644 --- a/arch/powerpc/lib/Makefile +++ b/arch/powerpc/lib/Makefile @@ -7,7 +7,6 @@ obj-y := string.o strcase.o obj-$(CONFIG_PPC32) += div64.o copy_32.o checksum_32.o endif -obj-y += bitops.o obj-$(CONFIG_PPC64) += checksum_64.o copypage_64.o copyuser_64.o \ memcpy_64.o usercopy_64.o mem_64.o string.o \ strcase.o diff --git a/arch/powerpc/lib/bitops.c b/arch/powerpc/lib/bitops.c deleted file mode 100644 index f68ad71a018..00000000000 --- a/arch/powerpc/lib/bitops.c +++ /dev/null @@ -1,150 +0,0 @@ -#include -#include -#include -#include - -/** - * find_next_bit - find the next set bit in a memory region - * @addr: The address to base the search on - * @offset: The bitnumber to start searching at - * @size: The maximum size to search - */ -unsigned long find_next_bit(const unsigned long *addr, unsigned long size, - unsigned long offset) -{ - const unsigned long *p = addr + BITOP_WORD(offset); - unsigned long result = offset & ~(BITS_PER_LONG-1); - unsigned long tmp; - - if (offset >= size) - return size; - size -= result; - offset %= BITS_PER_LONG; - if (offset) { - tmp = *(p++); - tmp &= (~0UL << offset); - if (size < BITS_PER_LONG) - goto found_first; - if (tmp) - goto found_middle; - size -= BITS_PER_LONG; - result += BITS_PER_LONG; - } - while (size & ~(BITS_PER_LONG-1)) { - if ((tmp = *(p++))) - goto found_middle; - result += BITS_PER_LONG; - size -= BITS_PER_LONG; - } - if (!size) - return result; - tmp = *p; - -found_first: - tmp &= (~0UL >> (BITS_PER_LONG - size)); - if (tmp == 0UL) /* Are any bits set? */ - return result + size; /* Nope. */ -found_middle: - return result + __ffs(tmp); -} -EXPORT_SYMBOL(find_next_bit); - -/* - * This implementation of find_{first,next}_zero_bit was stolen from - * Linus' asm-alpha/bitops.h. - */ -unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, - unsigned long offset) -{ - const unsigned long *p = addr + BITOP_WORD(offset); - unsigned long result = offset & ~(BITS_PER_LONG-1); - unsigned long tmp; - - if (offset >= size) - return size; - size -= result; - offset %= BITS_PER_LONG; - if (offset) { - tmp = *(p++); - tmp |= ~0UL >> (BITS_PER_LONG - offset); - if (size < BITS_PER_LONG) - goto found_first; - if (~tmp) - goto found_middle; - size -= BITS_PER_LONG; - result += BITS_PER_LONG; - } - while (size & ~(BITS_PER_LONG-1)) { - if (~(tmp = *(p++))) - goto found_middle; - result += BITS_PER_LONG; - size -= BITS_PER_LONG; - } - if (!size) - return result; - tmp = *p; - -found_first: - tmp |= ~0UL << size; - if (tmp == ~0UL) /* Are any bits zero? */ - return result + size; /* Nope. */ -found_middle: - return result + ffz(tmp); -} -EXPORT_SYMBOL(find_next_zero_bit); - -static inline unsigned int ext2_ilog2(unsigned int x) -{ - int lz; - - asm("cntlzw %0,%1": "=r"(lz):"r"(x)); - return 31 - lz; -} - -static inline unsigned int ext2_ffz(unsigned int x) -{ - u32 rc; - if ((x = ~x) == 0) - return 32; - rc = ext2_ilog2(x & -x); - return rc; -} - -unsigned long find_next_zero_le_bit(const unsigned long *addr, - unsigned long size, unsigned long offset) -{ - const unsigned int *p = ((const unsigned int *)addr) + (offset >> 5); - unsigned int result = offset & ~31; - unsigned int tmp; - - if (offset >= size) - return size; - size -= result; - offset &= 31; - if (offset) { - tmp = cpu_to_le32p(p++); - tmp |= ~0U >> (32 - offset); /* bug or feature ? */ - if (size < 32) - goto found_first; - if (tmp != ~0) - goto found_middle; - size -= 32; - result += 32; - } - while (size >= 32) { - if ((tmp = cpu_to_le32p(p++)) != ~0) - goto found_middle; - result += 32; - size -= 32; - } - if (!size) - return result; - tmp = cpu_to_le32p(p); -found_first: - tmp |= ~0 << size; - if (tmp == ~0) /* Are any bits zero? */ - return result + size; /* Nope. */ -found_middle: - return result + ext2_ffz(tmp); -} -EXPORT_SYMBOL(find_next_zero_le_bit); diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig index e9a8f5d1dfc..b55de4f42ae 100644 --- a/arch/ppc/Kconfig +++ b/arch/ppc/Kconfig @@ -40,6 +40,10 @@ config GENERIC_NVRAM bool default y +config GENERIC_FIND_NEXT_BIT + bool + default y + config SCHED_NO_NO_OMIT_FRAME_POINTER bool default y diff --git a/include/asm-powerpc/bitops.h b/include/asm-powerpc/bitops.h index d1c2a440566..76e2f08c3c8 100644 --- a/include/asm-powerpc/bitops.h +++ b/include/asm-powerpc/bitops.h @@ -288,8 +288,8 @@ static __inline__ int test_le_bit(unsigned long nr, #define __test_and_clear_le_bit(nr, addr) \ __test_and_clear_bit((nr) ^ BITOP_LE_SWIZZLE, (addr)) -#define find_first_zero_le_bit(addr, size) find_next_zero_le_bit((addr), (size), 0) -unsigned long find_next_zero_le_bit(const unsigned long *addr, +#define find_first_zero_le_bit(addr, size) generic_find_next_zero_le_bit((addr), (size), 0) +unsigned long generic_find_next_zero_le_bit(const unsigned long *addr, unsigned long size, unsigned long offset); /* Bitmap functions for the ext2 filesystem */ @@ -309,7 +309,7 @@ unsigned long find_next_zero_le_bit(const unsigned long *addr, #define ext2_find_first_zero_bit(addr, size) \ find_first_zero_le_bit((unsigned long*)addr, size) #define ext2_find_next_zero_bit(addr, size, off) \ - find_next_zero_le_bit((unsigned long*)addr, size, off) + generic_find_next_zero_le_bit((unsigned long*)addr, size, off) /* Bitmap functions for the minix filesystem. */ -- cgit v1.2.3 From 31a34fe75906ba5f61606eaed01da313f29ca4b1 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 22 May 2006 22:58:14 +0100 Subject: [PATCH] ata_piix formatting if( spacing fix for Garzik compliant formatting Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/scsi/ata_piix.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index 28bd8cae52c..1db007f41a6 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -767,15 +767,15 @@ static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev) pci_read_config_byte(pdev, PCI_REVISION_ID, &rev); pci_read_config_word(pdev, 0x41, &cfg); /* Only on the original revision: IDE DMA can hang */ - if(rev == 0x00) + if (rev == 0x00) no_piix_dma = 1; /* On all revisions below 5 PXB bus lock must be disabled for IDE */ - else if(cfg & (1<<14) && rev < 5) + else if (cfg & (1<<14) && rev < 5) no_piix_dma = 2; } - if(no_piix_dma) + if (no_piix_dma) dev_printk(KERN_WARNING, &ata_dev->dev, "450NX errata present, disabling IDE DMA.\n"); - if(no_piix_dma == 2) + if (no_piix_dma == 2) dev_printk(KERN_WARNING, &ata_dev->dev, "A BIOS update may resolve this.\n"); return no_piix_dma; } -- cgit v1.2.3 From 957d2df1801865eb1e63864bc63b970aa9c460ba Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 23 May 2006 13:18:57 +0100 Subject: [PATCH] libata: Remove obsolete flag ATA_FLAG_IRQ_MASK was added when I did the original data transfer with IRQ masked bits for PIO. It has since been replaced by ->pio_data_xfer methods so should be removed so nobody uses it by mistake thinking it still works. Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- include/linux/libata.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/linux/libata.h b/include/linux/libata.h index 25a6bf18159..9c60b4a4e2f 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -149,7 +149,6 @@ enum { ATA_FLAG_NO_ATAPI = (1 << 6), /* No ATAPI support */ ATA_FLAG_PIO_DMA = (1 << 7), /* PIO cmds via DMA */ ATA_FLAG_PIO_LBA48 = (1 << 8), /* Host DMA engine is LBA28 only */ - ATA_FLAG_IRQ_MASK = (1 << 9), /* Mask IRQ in PIO xfers */ ATA_FLAG_PIO_POLLING = (1 << 10), /* use polling PIO if LLD * doesn't handle PIO interrupts */ ATA_FLAG_NCQ = (1 << 11), /* host supports NCQ */ -- cgit v1.2.3 From 89bad5892abca55f56d0ea713c7306d1f845ac8e Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Fri, 26 May 2006 13:49:18 +0800 Subject: [PATCH] libata: add back ->data_xfer to ata_piix.c Add back ->data_xfer and ->mode_filter to ata_piix.c. Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik --- drivers/scsi/ata_piix.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index 1db007f41a6..ad41dfd33e0 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -228,6 +228,7 @@ static const struct ata_port_operations piix_pata_ops = { .port_disable = ata_port_disable, .set_piomode = piix_set_piomode, .set_dmamode = piix_set_dmamode, + .mode_filter = ata_pci_default_filter, .tf_load = ata_tf_load, .tf_read = ata_tf_read, @@ -243,6 +244,7 @@ static const struct ata_port_operations piix_pata_ops = { .bmdma_status = ata_bmdma_status, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, + .data_xfer = ata_pio_data_xfer, .freeze = ata_bmdma_freeze, .thaw = ata_bmdma_thaw, @@ -274,6 +276,7 @@ static const struct ata_port_operations piix_sata_ops = { .bmdma_status = ata_bmdma_status, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, + .data_xfer = ata_pio_data_xfer, .freeze = ata_bmdma_freeze, .thaw = ata_bmdma_thaw, -- cgit v1.2.3 From 622b20fcb8b42aa4c3c87c0a036f2ad0927b64bc Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Wed, 24 May 2006 14:06:11 +0100 Subject: [PATCH] PCI identifiers for the pata_via update These IDs are also used by the drivers/ide/pci changes submitted by VIA. Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- include/linux/pci_ids.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 233f60741c8..e75727954a1 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1238,6 +1238,7 @@ #define PCI_DEVICE_ID_VIA_PX8X0_0 0x0259 #define PCI_DEVICE_ID_VIA_3269_0 0x0269 #define PCI_DEVICE_ID_VIA_K8T800PRO_0 0x0282 +#define PCI_DEVICE_ID_VIA_3296_0 0x0296 #define PCI_DEVICE_ID_VIA_8363_0 0x0305 #define PCI_DEVICE_ID_VIA_P4M800CE 0x0314 #define PCI_DEVICE_ID_VIA_8371_0 0x0391 @@ -1245,6 +1246,7 @@ #define PCI_DEVICE_ID_VIA_82C561 0x0561 #define PCI_DEVICE_ID_VIA_82C586_1 0x0571 #define PCI_DEVICE_ID_VIA_82C576 0x0576 +#define PCI_DEVICE_ID_VIA_SATA_EIDE 0x0581 #define PCI_DEVICE_ID_VIA_82C586_0 0x0586 #define PCI_DEVICE_ID_VIA_82C596 0x0596 #define PCI_DEVICE_ID_VIA_82C597_0 0x0597 @@ -1285,10 +1287,11 @@ #define PCI_DEVICE_ID_VIA_8783_0 0x3208 #define PCI_DEVICE_ID_VIA_8237 0x3227 #define PCI_DEVICE_ID_VIA_8251 0x3287 -#define PCI_DEVICE_ID_VIA_3296_0 0x0296 +#define PCI_DEVICE_ID_VIA_8237A 0x3337 #define PCI_DEVICE_ID_VIA_8231 0x8231 #define PCI_DEVICE_ID_VIA_8231_4 0x8235 #define PCI_DEVICE_ID_VIA_8365_1 0x8305 +#define PCI_DEVICE_ID_VIA_CX700 0x8324 #define PCI_DEVICE_ID_VIA_8371_1 0x8391 #define PCI_DEVICE_ID_VIA_82C598_1 0x8598 #define PCI_DEVICE_ID_VIA_838X_1 0xB188 -- cgit v1.2.3 From 75e995855f45a83afdae34d50c0b3ee14fb23b7a Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Wed, 24 May 2006 14:14:41 +0100 Subject: [PATCH] libata: add pio_data_xfer_noirq Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 25 +++++++++++++++++++++++++ include/linux/libata.h | 2 ++ 2 files changed, 27 insertions(+) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 074a46e5bbd..f19fe662f0c 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3611,6 +3611,30 @@ void ata_pio_data_xfer(struct ata_device *adev, unsigned char *buf, } } +/** + * ata_pio_data_xfer_noirq - Transfer data by PIO + * @adev: device to target + * @buf: data buffer + * @buflen: buffer length + * @write_data: read/write + * + * Transfer data from/to the device data register by PIO. Do the + * transfer with interrupts disabled. + * + * LOCKING: + * Inherited from caller. + */ + +void ata_pio_data_xfer_noirq(struct ata_device *adev, unsigned char *buf, + unsigned int buflen, int write_data) +{ + unsigned long flags; + local_irq_save(flags); + ata_pio_data_xfer(adev, buf, buflen, write_data); + local_irq_restore(flags); +} + + /** * ata_pio_sector - Transfer ATA_SECT_SIZE (512 bytes) of data. * @qc: Command on going @@ -5675,6 +5699,7 @@ EXPORT_SYMBOL_GPL(ata_host_stop); EXPORT_SYMBOL_GPL(ata_interrupt); EXPORT_SYMBOL_GPL(ata_mmio_data_xfer); EXPORT_SYMBOL_GPL(ata_pio_data_xfer); +EXPORT_SYMBOL_GPL(ata_pio_data_xfer_noirq); EXPORT_SYMBOL_GPL(ata_qc_prep); EXPORT_SYMBOL_GPL(ata_noop_qc_prep); EXPORT_SYMBOL_GPL(ata_bmdma_setup); diff --git a/include/linux/libata.h b/include/linux/libata.h index 9c60b4a4e2f..b0ee1c1437d 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -651,6 +651,8 @@ extern void ata_mmio_data_xfer(struct ata_device *adev, unsigned char *buf, unsigned int buflen, int write_data); extern void ata_pio_data_xfer(struct ata_device *adev, unsigned char *buf, unsigned int buflen, int write_data); +extern void ata_pio_data_xfer_noirq(struct ata_device *adev, unsigned char *buf, + unsigned int buflen, int write_data); extern void ata_qc_prep(struct ata_queued_cmd *qc); extern void ata_noop_qc_prep(struct ata_queued_cmd *qc); extern unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc); -- cgit v1.2.3 From 4a9d2d8bf989c77b54add430932fa5ed8a80dba9 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Mon, 22 May 2006 18:14:08 +0200 Subject: [SCSI] zfcp: (cleanup) shortened copyright and author information Copyright update, shortened file headers, shortened author information. Signed-off-by: Andreas Herrmann Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_aux.c | 40 ++++++++++++++++------------------ drivers/s390/scsi/zfcp_ccw.c | 14 +++--------- drivers/s390/scsi/zfcp_dbf.c | 10 +++------ drivers/s390/scsi/zfcp_def.h | 17 +++------------ drivers/s390/scsi/zfcp_erp.c | 18 ++++----------- drivers/s390/scsi/zfcp_ext.h | 16 +++----------- drivers/s390/scsi/zfcp_fsf.c | 17 +++------------ drivers/s390/scsi/zfcp_fsf.h | 17 +++------------ drivers/s390/scsi/zfcp_qdio.c | 16 +++----------- drivers/s390/scsi/zfcp_scsi.c | 16 +++----------- drivers/s390/scsi/zfcp_sysfs_adapter.c | 14 +++--------- drivers/s390/scsi/zfcp_sysfs_driver.c | 14 +++--------- drivers/s390/scsi/zfcp_sysfs_port.c | 15 +++---------- drivers/s390/scsi/zfcp_sysfs_unit.c | 15 +++---------- 14 files changed, 59 insertions(+), 180 deletions(-) diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 395cfc6a344..12bc8f2905c 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -1,18 +1,8 @@ /* + * This file is part of the zfcp device driver for + * FCP adapters for IBM System z9 and zSeries. * - * linux/drivers/s390/scsi/zfcp_aux.c - * - * FCP adapter driver for IBM eServer zSeries - * - * (C) Copyright IBM Corp. 2002, 2004 - * - * Author(s): Martin Peschke - * Raimund Schroeder - * Aron Zeh - * Wolfgang Taphorn - * Stefan Bader - * Heiko Carstens - * Andreas Herrmann + * (C) Copyright IBM Corp. 2002, 2006 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,6 +19,20 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* + * Driver authors: + * Martin Peschke (originator of the driver) + * Raimund Schroeder + * Aron Zeh + * Wolfgang Taphorn + * Stefan Bader + * Heiko Carstens (kernel 2.6 port of the driver) + * Andreas Herrmann + * Maxim Shchetynin + * Volker Sameske + * Ralph Wuerthner + */ + #include "zfcp_ext.h" /* accumulated log level (module parameter) */ @@ -75,15 +79,9 @@ static struct miscdevice zfcp_cfdc_misc = { /* declare driver module init/cleanup functions */ module_init(zfcp_module_init); -MODULE_AUTHOR("Heiko Carstens , " - "Andreas Herrman , " - "Martin Peschke , " - "Raimund Schroeder , " - "Wolfgang Taphorn , " - "Aron Zeh , " - "IBM Deutschland Entwicklung GmbH"); +MODULE_AUTHOR("IBM Deutschland Entwicklung GmbH - linux390@de.ibm.com"); MODULE_DESCRIPTION - ("FCP (SCSI over Fibre Channel) HBA driver for IBM eServer zSeries"); + ("FCP (SCSI over Fibre Channel) HBA driver for IBM System z9 and zSeries"); MODULE_LICENSE("GPL"); module_param(device, charp, 0400); diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c index 241136d0c6e..57d8e4bfb8d 100644 --- a/drivers/s390/scsi/zfcp_ccw.c +++ b/drivers/s390/scsi/zfcp_ccw.c @@ -1,16 +1,8 @@ /* - * linux/drivers/s390/scsi/zfcp_ccw.c + * This file is part of the zfcp device driver for + * FCP adapters for IBM System z9 and zSeries. * - * FCP adapter driver for IBM eServer zSeries - * - * CCW driver related routines - * - * (C) Copyright IBM Corp. 2003, 2004 - * - * Authors: - * Martin Peschke - * Heiko Carstens - * Andreas Herrmann + * (C) Copyright IBM Corp. 2002, 2006 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index a5f2ba9a8fd..c033145d0f1 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c @@ -1,12 +1,8 @@ /* + * This file is part of the zfcp device driver for + * FCP adapters for IBM System z9 and zSeries. * - * linux/drivers/s390/scsi/zfcp_dbf.c - * - * FCP adapter driver for IBM eServer zSeries - * - * Debugging facilities - * - * (C) Copyright IBM Corp. 2005 + * (C) Copyright IBM Corp. 2002, 2006 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 6eba56cd89b..362af4d9535 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -1,19 +1,8 @@ /* - * - * linux/drivers/s390/scsi/zfcp_def.h - * - * FCP adapter driver for IBM eServer zSeries - * - * (C) Copyright IBM Corp. 2002, 2004 + * This file is part of the zfcp device driver for + * FCP adapters for IBM System z9 and zSeries. * - * Author(s): Martin Peschke - * Raimund Schroeder - * Aron Zeh - * Wolfgang Taphorn - * Stefan Bader - * Heiko Carstens - * Andreas Herrmann - * Volker Sameske + * (C) Copyright IBM Corp. 2002, 2006 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 57cb628a05a..e2dac3dc3fc 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -1,18 +1,8 @@ /* - * - * linux/drivers/s390/scsi/zfcp_erp.c - * - * FCP adapter driver for IBM eServer zSeries - * - * (C) Copyright IBM Corp. 2002, 2004 - * - * Author(s): Martin Peschke - * Raimund Schroeder - * Aron Zeh - * Wolfgang Taphorn - * Stefan Bader - * Heiko Carstens - * Andreas Herrmann + * This file is part of the zfcp device driver for + * FCP adapters for IBM System z9 and zSeries. + * + * (C) Copyright IBM Corp. 2002, 2006 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index 700f5402a97..6be2bb71c73 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -1,18 +1,8 @@ /* - * - * linux/drivers/s390/scsi/zfcp_ext.h - * - * FCP adapter driver for IBM eServer zSeries - * - * (C) Copyright IBM Corp. 2002, 2004 + * This file is part of the zfcp device driver for + * FCP adapters for IBM System z9 and zSeries. * - * Author(s): Martin Peschke - * Raimund Schroeder - * Aron Zeh - * Wolfgang Taphorn - * Stefan Bader - * Heiko Carstens - * Andreas Herrmann + * (C) Copyright IBM Corp. 2002, 2006 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 662ec571d73..4a35960103d 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -1,19 +1,8 @@ /* + * This file is part of the zfcp device driver for + * FCP adapters for IBM System z9 and zSeries. * - * linux/drivers/s390/scsi/zfcp_fsf.c - * - * FCP adapter driver for IBM eServer zSeries - * - * (C) Copyright IBM Corp. 2002, 2004 - * - * Author(s): Martin Peschke - * Raimund Schroeder - * Aron Zeh - * Wolfgang Taphorn - * Stefan Bader - * Heiko Carstens - * Andreas Herrmann - * Volker Sameske + * (C) Copyright IBM Corp. 2002, 2006 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h index e734415cae6..ca16dca3050 100644 --- a/drivers/s390/scsi/zfcp_fsf.h +++ b/drivers/s390/scsi/zfcp_fsf.h @@ -1,19 +1,8 @@ /* - * - * linux/drivers/s390/scsi/zfcp_fsf.h - * - * FCP adapter driver for IBM eServer zSeries - * - * (C) Copyright IBM Corp. 2002, 2004 + * This file is part of the zfcp device driver for + * FCP adapters for IBM System z9 and zSeries. * - * Author(s): Martin Peschke - * Raimund Schroeder - * Aron Zeh - * Wolfgang Taphorn - * Stefan Bader - * Heiko Carstens - * Andreas Herrmann - * Volker Sameske + * (C) Copyright IBM Corp. 2002, 2006 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index 1c3275163c9..dfb6644d17b 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c @@ -1,18 +1,8 @@ /* - * linux/drivers/s390/scsi/zfcp_qdio.c + * This file is part of the zfcp device driver for + * FCP adapters for IBM System z9 and zSeries. * - * FCP adapter driver for IBM eServer zSeries - * - * QDIO related routines - * - * (C) Copyright IBM Corp. 2002, 2004 - * - * Authors: - * Martin Peschke - * Raimund Schroeder - * Wolfgang Taphorn - * Heiko Carstens - * Andreas Herrmann + * (C) Copyright IBM Corp. 2002, 2006 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 9e6d07d7b3c..4b4041a9da5 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -1,18 +1,8 @@ /* - * - * linux/drivers/s390/scsi/zfcp_scsi.c - * - * FCP adapter driver for IBM eServer zSeries - * - * (C) Copyright IBM Corp. 2002, 2004 + * This file is part of the zfcp device driver for + * FCP adapters for IBM System z9 and zSeries. * - * Author(s): Martin Peschke - * Raimund Schroeder - * Aron Zeh - * Wolfgang Taphorn - * Stefan Bader - * Heiko Carstens - * Andreas Herrmann + * (C) Copyright IBM Corp. 2002, 2006 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/s390/scsi/zfcp_sysfs_adapter.c b/drivers/s390/scsi/zfcp_sysfs_adapter.c index b29ac25e07f..705c6d4428f 100644 --- a/drivers/s390/scsi/zfcp_sysfs_adapter.c +++ b/drivers/s390/scsi/zfcp_sysfs_adapter.c @@ -1,16 +1,8 @@ /* - * linux/drivers/s390/scsi/zfcp_sysfs_adapter.c + * This file is part of the zfcp device driver for + * FCP adapters for IBM System z9 and zSeries. * - * FCP adapter driver for IBM eServer zSeries - * - * sysfs adapter related routines - * - * (C) Copyright IBM Corp. 2003, 2004 - * - * Authors: - * Martin Peschke - * Heiko Carstens - * Andreas Herrmann + * (C) Copyright IBM Corp. 2002, 2006 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/s390/scsi/zfcp_sysfs_driver.c b/drivers/s390/scsi/zfcp_sysfs_driver.c index 6622d55e0a4..005e62f8593 100644 --- a/drivers/s390/scsi/zfcp_sysfs_driver.c +++ b/drivers/s390/scsi/zfcp_sysfs_driver.c @@ -1,16 +1,8 @@ /* - * linux/drivers/s390/scsi/zfcp_sysfs_driver.c + * This file is part of the zfcp device driver for + * FCP adapters for IBM System z9 and zSeries. * - * FCP adapter driver for IBM eServer zSeries - * - * sysfs driver related routines - * - * (C) Copyright IBM Corp. 2003, 2004 - * - * Authors: - * Martin Peschke - * Heiko Carstens - * Andreas Herrmann + * (C) Copyright IBM Corp. 2002, 2006 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/s390/scsi/zfcp_sysfs_port.c b/drivers/s390/scsi/zfcp_sysfs_port.c index f401d42db21..1320c059143 100644 --- a/drivers/s390/scsi/zfcp_sysfs_port.c +++ b/drivers/s390/scsi/zfcp_sysfs_port.c @@ -1,17 +1,8 @@ /* - * linux/drivers/s390/scsi/zfcp_sysfs_port.c + * This file is part of the zfcp device driver for + * FCP adapters for IBM System z9 and zSeries. * - * FCP adapter driver for IBM eServer zSeries - * - * sysfs port related routines - * - * (C) Copyright IBM Corp. 2003, 2004 - * - * Authors: - * Martin Peschke - * Heiko Carstens - * Andreas Herrmann - * Volker Sameske + * (C) Copyright IBM Corp. 2002, 2006 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/s390/scsi/zfcp_sysfs_unit.c b/drivers/s390/scsi/zfcp_sysfs_unit.c index ad5dfb889be..81a48417586 100644 --- a/drivers/s390/scsi/zfcp_sysfs_unit.c +++ b/drivers/s390/scsi/zfcp_sysfs_unit.c @@ -1,17 +1,8 @@ /* - * linux/drivers/s390/scsi/zfcp_sysfs_unit.c + * This file is part of the zfcp device driver for + * FCP adapters for IBM System z9 and zSeries. * - * FCP adapter driver for IBM eServer zSeries - * - * sysfs unit related routines - * - * (C) Copyright IBM Corp. 2003, 2004 - * - * Authors: - * Martin Peschke - * Heiko Carstens - * Andreas Herrmann - * Volker Sameske + * (C) Copyright IBM Corp. 2002, 2006 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by -- cgit v1.2.3 From ca3271b40225a1049334766f6fb35b57a0162bd2 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Mon, 22 May 2006 18:15:49 +0200 Subject: [SCSI] zfcp: (cleanup) remove useless comments Removed some useless comments. Signed-off-by: Andreas Herrmann Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_erp.c | 218 ------------------------------------------ drivers/s390/scsi/zfcp_fsf.c | 20 ---- drivers/s390/scsi/zfcp_scsi.c | 46 --------- 3 files changed, 284 deletions(-) diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index e2dac3dc3fc..f57440c96e2 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -221,13 +221,6 @@ zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear_mask) return retval; } -/* - * function: - * - * purpose: - * - * returns: - */ int zfcp_erp_adapter_shutdown(struct zfcp_adapter *adapter, int clear_mask) { @@ -241,13 +234,6 @@ zfcp_erp_adapter_shutdown(struct zfcp_adapter *adapter, int clear_mask) return retval; } -/* - * function: - * - * purpose: - * - * returns: - */ int zfcp_erp_port_shutdown(struct zfcp_port *port, int clear_mask) { @@ -261,13 +247,6 @@ zfcp_erp_port_shutdown(struct zfcp_port *port, int clear_mask) return retval; } -/* - * function: - * - * purpose: - * - * returns: - */ int zfcp_erp_unit_shutdown(struct zfcp_unit *unit, int clear_mask) { @@ -802,13 +781,6 @@ zfcp_erp_unit_unblock(struct zfcp_unit *unit) atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &unit->status); } -/* - * function: - * - * purpose: - * - * returns: - */ static void zfcp_erp_action_ready(struct zfcp_erp_action *erp_action) { @@ -1346,13 +1318,6 @@ zfcp_erp_strategy_check_action(struct zfcp_erp_action *erp_action, int retval) return retval; } -/* - * function: - * - * purpose: - * - * returns: - */ static int zfcp_erp_strategy_do_action(struct zfcp_erp_action *erp_action) { @@ -1528,13 +1493,6 @@ zfcp_erp_strategy_check_target(struct zfcp_erp_action *erp_action, int result) return result; } -/* - * function: - * - * purpose: - * - * returns: - */ static int zfcp_erp_strategy_statechange(int action, u32 status, @@ -1576,13 +1534,6 @@ zfcp_erp_strategy_statechange(int action, return retval; } -/* - * function: - * - * purpose: - * - * returns: - */ static inline int zfcp_erp_strategy_statechange_detected(atomic_t * target_status, u32 erp_status) { @@ -1595,13 +1546,6 @@ zfcp_erp_strategy_statechange_detected(atomic_t * target_status, u32 erp_status) !(ZFCP_STATUS_ERP_CLOSE_ONLY & erp_status)); } -/* - * function: - * - * purpose: - * - * returns: - */ static int zfcp_erp_strategy_check_unit(struct zfcp_unit *unit, int result) { @@ -1632,13 +1576,6 @@ zfcp_erp_strategy_check_unit(struct zfcp_unit *unit, int result) return result; } -/* - * function: - * - * purpose: - * - * returns: - */ static int zfcp_erp_strategy_check_port(struct zfcp_port *port, int result) { @@ -1668,13 +1605,6 @@ zfcp_erp_strategy_check_port(struct zfcp_port *port, int result) return result; } -/* - * function: - * - * purpose: - * - * returns: - */ static int zfcp_erp_strategy_check_adapter(struct zfcp_adapter *adapter, int result) { @@ -1754,13 +1684,6 @@ zfcp_erp_strategy_followup_actions(int action, return 0; } -/* - * function: - * - * purpose: - * - * returns: - */ static int zfcp_erp_strategy_check_queues(struct zfcp_adapter *adapter) { @@ -1799,12 +1722,6 @@ zfcp_erp_wait(struct zfcp_adapter *adapter) return retval; } -/* - * function: zfcp_erp_modify_adapter_status - * - * purpose: - * - */ void zfcp_erp_modify_adapter_status(struct zfcp_adapter *adapter, u32 mask, int set_or_clear) @@ -1909,13 +1826,6 @@ zfcp_erp_port_reopen_all(struct zfcp_adapter *adapter, int clear_mask) return retval; } -/* - * function: - * - * purpose: - * - * returns: FIXME - */ static int zfcp_erp_port_reopen_all_internal(struct zfcp_adapter *adapter, int clear_mask) { @@ -2360,13 +2270,6 @@ zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action) return ret; } -/* - * function: - * - * purpose: - * - * returns: - */ static int zfcp_erp_adapter_strategy_open_fsf_statusread(struct zfcp_erp_action *erp_action) @@ -2535,13 +2438,6 @@ zfcp_erp_port_strategy(struct zfcp_erp_action *erp_action) return retval; } -/* - * function: - * - * purpose: - * - * returns: - */ static int zfcp_erp_port_strategy_open(struct zfcp_erp_action *erp_action) { @@ -2556,15 +2452,6 @@ zfcp_erp_port_strategy_open(struct zfcp_erp_action *erp_action) return retval; } -/* - * function: - * - * purpose: - * - * returns: - * - * FIXME(design): currently only prepared for fabric (nameserver!) - */ static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *erp_action) { @@ -2680,13 +2567,6 @@ zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *erp_action) return retval; } -/* - * function: - * - * purpose: - * - * returns: - */ static int zfcp_erp_port_strategy_open_nameserver(struct zfcp_erp_action *erp_action) { @@ -2803,13 +2683,6 @@ zfcp_erp_port_forced_strategy_close(struct zfcp_erp_action *erp_action) return retval; } -/* - * function: - * - * purpose: - * - * returns: - */ static int zfcp_erp_port_strategy_clearstati(struct zfcp_port *port) { @@ -3012,13 +2885,6 @@ zfcp_erp_unit_strategy(struct zfcp_erp_action *erp_action) return retval; } -/* - * function: - * - * purpose: - * - * returns: - */ static int zfcp_erp_unit_strategy_clearstati(struct zfcp_unit *unit) { @@ -3119,13 +2985,6 @@ zfcp_erp_unit_strategy_open(struct zfcp_erp_action *erp_action) return retval; } -/* - * function: - * - * purpose: - * - * returns: - */ static inline void zfcp_erp_timeout_init(struct zfcp_erp_action *erp_action) { @@ -3321,13 +3180,6 @@ zfcp_erp_action_enqueue(int action, return retval; } -/* - * function: - * - * purpose: - * - * returns: - */ static int zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action) { @@ -3422,13 +3274,6 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter, } -/* - * function: - * - * purpose: - * - * returns: FIXME - */ static int zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter) { @@ -3445,13 +3290,6 @@ zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter) return retval; } -/* - * function: - * - * purpose: - * - * returns: FIXME - */ static int zfcp_erp_action_dismiss_port(struct zfcp_port *port) { @@ -3470,13 +3308,6 @@ zfcp_erp_action_dismiss_port(struct zfcp_port *port) return retval; } -/* - * function: - * - * purpose: - * - * returns: FIXME - */ static int zfcp_erp_action_dismiss_unit(struct zfcp_unit *unit) { @@ -3491,13 +3322,6 @@ zfcp_erp_action_dismiss_unit(struct zfcp_unit *unit) return retval; } -/* - * function: - * - * purpose: moves erp_action to 'erp running list' - * - * returns: - */ static inline void zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action) { @@ -3508,13 +3332,6 @@ zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action) list_move(&erp_action->list, &erp_action->adapter->erp_running_head); } -/* - * function: - * - * purpose: moves erp_action to 'erp ready list' - * - * returns: - */ static inline void zfcp_erp_action_to_ready(struct zfcp_erp_action *erp_action) { @@ -3525,11 +3342,6 @@ zfcp_erp_action_to_ready(struct zfcp_erp_action *erp_action) list_move(&erp_action->list, &erp_action->adapter->erp_ready_head); } -/* - * function: zfcp_erp_port_boxed - * - * purpose: - */ void zfcp_erp_port_boxed(struct zfcp_port *port) { @@ -3546,11 +3358,6 @@ zfcp_erp_port_boxed(struct zfcp_port *port) zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED); } -/* - * function: zfcp_erp_unit_boxed - * - * purpose: - */ void zfcp_erp_unit_boxed(struct zfcp_unit *unit) { @@ -3564,11 +3371,6 @@ zfcp_erp_unit_boxed(struct zfcp_unit *unit) zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED); } -/* - * function: zfcp_erp_port_access_denied - * - * purpose: - */ void zfcp_erp_port_access_denied(struct zfcp_port *port) { @@ -3585,11 +3387,6 @@ zfcp_erp_port_access_denied(struct zfcp_port *port) read_unlock_irqrestore(&zfcp_data.config_lock, flags); } -/* - * function: zfcp_erp_unit_access_denied - * - * purpose: - */ void zfcp_erp_unit_access_denied(struct zfcp_unit *unit) { @@ -3603,11 +3400,6 @@ zfcp_erp_unit_access_denied(struct zfcp_unit *unit) ZFCP_SET); } -/* - * function: zfcp_erp_adapter_access_changed - * - * purpose: - */ void zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter) { @@ -3629,11 +3421,6 @@ zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter) read_unlock_irqrestore(&zfcp_data.config_lock, flags); } -/* - * function: zfcp_erp_port_access_changed - * - * purpose: - */ void zfcp_erp_port_access_changed(struct zfcp_port *port) { @@ -3662,11 +3449,6 @@ zfcp_erp_port_access_changed(struct zfcp_port *port) zfcp_get_busid_by_adapter(adapter), port->wwpn); } -/* - * function: zfcp_erp_unit_access_changed - * - * purpose: - */ void zfcp_erp_unit_access_changed(struct zfcp_unit *unit) { diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 4a35960103d..4475e412066 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -1929,14 +1929,6 @@ skip_fsfstatus: return retval; } -/* - * function: - * - * purpose: - * - * returns: address of initiated FSF request - * NULL - request could not be initiated - */ int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action) { @@ -3656,18 +3648,6 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter, return retval; } -/* - * function: zfcp_fsf_send_fcp_command_task_management - * - * purpose: - * - * returns: - * - * FIXME(design): should be watched by a timeout!!! - * FIXME(design) shouldn't this be modified to return an int - * also...don't know how though - * - */ struct zfcp_fsf_req * zfcp_fsf_send_fcp_command_task_management(struct zfcp_adapter *adapter, struct zfcp_unit *unit, diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 4b4041a9da5..118cf0fa0af 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -151,14 +151,6 @@ set_driver_byte(u32 * result, char status) set_byte(result, status, 3); } -/* - * function: zfcp_scsi_slave_alloc - * - * purpose: - * - * returns: - */ - static int zfcp_scsi_slave_alloc(struct scsi_device *sdp) { @@ -185,14 +177,6 @@ zfcp_scsi_slave_alloc(struct scsi_device *sdp) return retval; } -/* - * function: zfcp_scsi_slave_destroy - * - * purpose: - * - * returns: - */ - static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt) { @@ -364,15 +348,6 @@ zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt, return zfcp_scsi_command_async(adapter, unit, scpnt, NULL); } -/* - * function: zfcp_unit_lookup - * - * purpose: - * - * returns: - * - * context: - */ static struct zfcp_unit * zfcp_unit_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id, scsi_lun_t lun) @@ -481,13 +456,6 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) return retval; } -/* - * function: zfcp_scsi_eh_device_reset_handler - * - * purpose: - * - * returns: - */ int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt) { @@ -615,13 +583,6 @@ zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt) return SUCCESS; } -/* - * function: - * - * purpose: - * - * returns: - */ int zfcp_adapter_scsi_register(struct zfcp_adapter *adapter) { @@ -668,13 +629,6 @@ zfcp_adapter_scsi_register(struct zfcp_adapter *adapter) return retval; } -/* - * function: - * - * purpose: - * - * returns: - */ void zfcp_adapter_scsi_unregister(struct zfcp_adapter *adapter) { -- cgit v1.2.3 From ec4081c6ba4fba6a8bc12a0e93db8817ba63ce47 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Mon, 22 May 2006 18:17:30 +0200 Subject: [SCSI] zfcp: (cleanup) kmalloc/kzalloc replacement Replace kmalloc/memset by kzalloc or kcalloc. Signed-off-by: Andreas Herrmann Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_aux.c | 15 +++++---------- drivers/s390/scsi/zfcp_erp.c | 9 +++------ drivers/s390/scsi/zfcp_scsi.c | 6 ++---- 3 files changed, 10 insertions(+), 20 deletions(-) diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 12bc8f2905c..4a17ce49980 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -289,12 +289,11 @@ zfcp_cfdc_dev_ioctl(struct file *file, unsigned int command, goto out; } - sg_list = kmalloc(sizeof(struct zfcp_sg_list), GFP_KERNEL); + sg_list = kzalloc(sizeof(struct zfcp_sg_list), GFP_KERNEL); if (sg_list == NULL) { retval = -ENOMEM; goto out; } - memset(sg_list, 0, sizeof(*sg_list)); if (command != ZFCP_CFDC_IOC) { ZFCP_LOG_INFO("IOC request code 0x%x invalid\n", command); @@ -476,14 +475,13 @@ zfcp_sg_list_alloc(struct zfcp_sg_list *sg_list, size_t size) sg_list->count = size >> PAGE_SHIFT; if (size & ~PAGE_MASK) sg_list->count++; - sg_list->sg = kmalloc(sg_list->count * sizeof(struct scatterlist), + sg_list->sg = kcalloc(sg_list->count, sizeof(struct scatterlist), GFP_KERNEL); if (sg_list->sg == NULL) { sg_list->count = 0; retval = -ENOMEM; goto out; } - memset(sg_list->sg, 0, sg_list->count * sizeof(struct scatterlist)); for (i = 0, sg = sg_list->sg; i < sg_list->count; i++, sg++) { sg->length = min(size, PAGE_SIZE); @@ -756,10 +754,9 @@ zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun) if (unit) return NULL; - unit = kmalloc(sizeof (struct zfcp_unit), GFP_KERNEL); + unit = kzalloc(sizeof (struct zfcp_unit), GFP_KERNEL); if (!unit) return NULL; - memset(unit, 0, sizeof (struct zfcp_unit)); /* initialise reference count stuff */ atomic_set(&unit->refcount, 0); @@ -927,13 +924,12 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device) */ /* try to allocate new adapter data structure (zeroed) */ - adapter = kmalloc(sizeof (struct zfcp_adapter), GFP_KERNEL); + adapter = kzalloc(sizeof (struct zfcp_adapter), GFP_KERNEL); if (!adapter) { ZFCP_LOG_INFO("error: allocation of base adapter " "structure failed\n"); goto out; } - memset(adapter, 0, sizeof (struct zfcp_adapter)); ccw_device->handler = NULL; @@ -1137,10 +1133,9 @@ zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status, return NULL; } - port = kmalloc(sizeof (struct zfcp_port), GFP_KERNEL); + port = kzalloc(sizeof (struct zfcp_port), GFP_KERNEL); if (!port) return NULL; - memset(port, 0, sizeof (struct zfcp_port)); /* initialise reference count stuff */ atomic_set(&port->refcount, 0); diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index f57440c96e2..ea2e7a39889 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -275,20 +275,17 @@ zfcp_erp_adisc(struct zfcp_port *port) int retval = 0; struct timer_list *timer; - send_els = kmalloc(sizeof(struct zfcp_send_els), GFP_ATOMIC); + send_els = kzalloc(sizeof(struct zfcp_send_els), GFP_ATOMIC); if (send_els == NULL) goto nomem; - memset(send_els, 0, sizeof(*send_els)); - send_els->req = kmalloc(sizeof(struct scatterlist), GFP_ATOMIC); + send_els->req = kzalloc(sizeof(struct scatterlist), GFP_ATOMIC); if (send_els->req == NULL) goto nomem; - memset(send_els->req, 0, sizeof(*send_els->req)); - send_els->resp = kmalloc(sizeof(struct scatterlist), GFP_ATOMIC); + send_els->resp = kzalloc(sizeof(struct scatterlist), GFP_ATOMIC); if (send_els->resp == NULL) goto nomem; - memset(send_els->resp, 0, sizeof(*send_els->resp)); address = (void *) get_zeroed_page(GFP_ATOMIC); if (address == NULL) diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 118cf0fa0af..3a180d80c3c 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -761,10 +761,9 @@ zfcp_get_fc_host_stats(struct Scsi_Host *shost) if (!fc_stats) return NULL; - data = kmalloc(sizeof(*data), GFP_KERNEL); + data = kzalloc(sizeof(*data), GFP_KERNEL); if (!data) return NULL; - memset(data, 0, sizeof(*data)); ret = zfcp_fsf_exchange_port_data(NULL, adapter, data); if (ret) { @@ -792,10 +791,9 @@ zfcp_reset_fc_host_stats(struct Scsi_Host *shost) int ret; adapter = (struct zfcp_adapter *)shost->hostdata[0]; - data = kmalloc(sizeof(*data), GFP_KERNEL); + data = kzalloc(sizeof(*data), GFP_KERNEL); if (!data) return; - memset(data, 0, sizeof(*data)); ret = zfcp_fsf_exchange_port_data(NULL, adapter, data); if (ret == 0) { -- cgit v1.2.3 From 06506d00ec1a0d7d3b1dff59185af355ce29ac0a Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Mon, 22 May 2006 18:18:19 +0200 Subject: [SCSI] zfcp: (cleanup) removed superfluous macros, struct members, typedefs Removed some macros, struct members and typedefs which were unused or not necessary. Signed-off-by: Andreas Herrmann Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_aux.c | 15 ++++------- drivers/s390/scsi/zfcp_def.h | 47 +++++--------------------------- drivers/s390/scsi/zfcp_erp.c | 2 +- drivers/s390/scsi/zfcp_fsf.c | 62 ++++++++++++++----------------------------- drivers/s390/scsi/zfcp_fsf.h | 21 +++------------ drivers/s390/scsi/zfcp_qdio.c | 3 ++- drivers/s390/scsi/zfcp_scsi.c | 13 +++------ 7 files changed, 41 insertions(+), 122 deletions(-) diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 4a17ce49980..bdaad5535e2 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -740,7 +740,7 @@ struct zfcp_unit * zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun) { struct zfcp_unit *unit, *tmp_unit; - scsi_lun_t scsi_lun; + unsigned int scsi_lun; int found; /* @@ -991,12 +991,6 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device) /* intitialise SCSI ER timer */ init_timer(&adapter->scsi_er_timer); - /* set FC service class used per default */ - adapter->fc_service_class = ZFCP_FC_SERVICE_CLASS_DEFAULT; - - sprintf(adapter->name, "%s", zfcp_get_busid_by_adapter(adapter)); - ASCEBC(adapter->name, strlen(adapter->name)); - /* mark adapter unusable as long as sysfs registration is not complete */ atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status); @@ -1347,18 +1341,19 @@ static void zfcp_fsf_incoming_els_plogi(struct zfcp_adapter *adapter, struct fsf_status_read_buffer *status_buffer) { - logi *els_logi = (logi *) status_buffer->payload; + struct fsf_plogi *els_plogi; struct zfcp_port *port; unsigned long flags; + els_plogi = (struct fsf_plogi *) status_buffer->payload; read_lock_irqsave(&zfcp_data.config_lock, flags); list_for_each_entry(port, &adapter->port_list_head, list) { - if (port->wwpn == (*(wwn_t *) & els_logi->nport_wwn)) + if (port->wwpn == (*(wwn_t *) &els_plogi->serv_param.wwpn)) break; } read_unlock_irqrestore(&zfcp_data.config_lock, flags); - if (!port || (port->wwpn != (*(wwn_t *) & els_logi->nport_wwn))) { + if (!port || (port->wwpn != (*(wwn_t *) &els_plogi->serv_param.wwpn))) { ZFCP_LOG_DEBUG("ignored incoming PLOGI for nonexisting port " "with d_id 0x%08x on adapter %s\n", status_buffer->d_id, diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 362af4d9535..e93272f1882 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -39,7 +39,6 @@ #include #include #include -#include "../../fc4/fc.h" #include "zfcp_fsf.h" #include #include @@ -78,13 +77,9 @@ zfcp_address_to_sg(void *address, struct scatterlist *list) list->offset = ((unsigned long) address) & (PAGE_SIZE - 1); } -/********************* SCSI SPECIFIC DEFINES *********************************/ - -/* 32 bit for SCSI ID and LUN as long as the SCSI stack uses this type */ -typedef u32 scsi_id_t; -typedef u32 scsi_lun_t; +#define REQUEST_LIST_SIZE 128 -#define ZFCP_ERP_SCSI_LOW_MEM_TIMEOUT (100*HZ) +/********************* SCSI SPECIFIC DEFINES *********************************/ #define ZFCP_SCSI_ER_TIMEOUT (100*HZ) /********************* CIO/QDIO SPECIFIC DEFINES *****************************/ @@ -222,8 +217,9 @@ struct fcp_rsp_iu { #define RSP_CODE_TASKMAN_FAILED 5 /* see fc-fs */ -#define LS_FAN 0x60000000 -#define LS_RSCN 0x61040000 +#define LS_RSCN 0x61040000 +#define LS_LOGO 0x05000000 +#define LS_PLOGI 0x03000000 struct fcp_rscn_head { u8 command; @@ -252,13 +248,6 @@ struct fcp_rscn_element { #define ZFCP_NO_PORTS_PER_DOMAIN 0x10000 #define ZFCP_NO_PORTS_PER_FABRIC 0x1000000 -struct fcp_fan { - u32 command; - u32 fport_did; - wwn_t fport_wwpn; - wwn_t fport_wwname; -} __attribute__((packed)); - /* see fc-ph */ struct fcp_logo { u32 command; @@ -496,9 +485,6 @@ struct zfcp_rc_entry { #define ZFCP_NAME "zfcp" -/* read-only LUN sharing switch initial value */ -#define ZFCP_RO_LUN_SHARING_DEFAULTS 0 - /* independent log areas */ #define ZFCP_LOG_AREA_OTHER 0 #define ZFCP_LOG_AREA_SCSI 1 @@ -597,7 +583,6 @@ do { \ * and unit */ #define ZFCP_COMMON_FLAGS 0xfff00000 -#define ZFCP_SPECIFIC_FLAGS 0x000fffff /* common status bits */ #define ZFCP_STATUS_COMMON_REMOVE 0x80000000 @@ -622,11 +607,6 @@ do { \ #define ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED 0x00000200 #define ZFCP_STATUS_ADAPTER_XPORT_OK 0x00000800 -#define ZFCP_STATUS_ADAPTER_SCSI_UP \ - (ZFCP_STATUS_COMMON_UNBLOCKED | \ - ZFCP_STATUS_ADAPTER_REGISTERED) - - /* FC-PH/FC-GS well-known address identifiers for generic services */ #define ZFCP_DID_MANAGEMENT_SERVICE 0xFFFFFA #define ZFCP_DID_TIME_SERVICE 0xFFFFFB @@ -641,7 +621,6 @@ do { \ #define ZFCP_STATUS_PORT_NO_WWPN 0x00000008 #define ZFCP_STATUS_PORT_NO_SCSI_ID 0x00000010 #define ZFCP_STATUS_PORT_INVALID_WWPN 0x00000020 -#define ZFCP_STATUS_PORT_ACCESS_DENIED 0x00000040 /* for ports with well known addresses */ #define ZFCP_STATUS_PORT_WKA \ @@ -897,15 +876,12 @@ struct zfcp_adapter { wwn_t peer_wwpn; /* P2P peer WWPN */ u32 peer_d_id; /* P2P peer D_ID */ struct ccw_device *ccw_device; /* S/390 ccw device */ - u8 fc_service_class; u32 hydra_version; /* Hydra version */ u32 fsf_lic_version; u32 adapter_features; /* FCP channel features */ u32 connection_features; /* host connection features */ u32 hardware_version; /* of FCP channel */ struct Scsi_Host *scsi_host; /* Pointer to mid-layer */ - unsigned short scsi_host_no; /* Assigned host number */ - unsigned char name[9]; struct list_head port_list_head; /* remote port list */ struct list_head port_remove_lh; /* head of ports to be removed */ @@ -997,7 +973,7 @@ struct zfcp_unit { refcount drop to zero */ struct zfcp_port *port; /* remote port of unit */ atomic_t status; /* status of this logical unit */ - scsi_lun_t scsi_lun; /* own SCSI LUN */ + unsigned int scsi_lun; /* own SCSI LUN */ fcp_lun_t fcp_lun; /* own FCP_LUN */ u32 handle; /* handle assigned by FSF */ struct scsi_device *device; /* scsi device struct pointer */ @@ -1041,11 +1017,6 @@ struct zfcp_data { struct list_head adapter_list_head; /* head of adapter list */ struct list_head adapter_remove_lh; /* head of adapters to be removed */ - rwlock_t status_read_lock; /* for status read thread */ - struct list_head status_read_receive_head; - struct list_head status_read_send_head; - struct semaphore status_read_sema; - wait_queue_head_t status_read_thread_wqh; u32 adapters; /* # of adapters in list */ rwlock_t config_lock; /* serialises changes to adapter/port/unit @@ -1084,9 +1055,6 @@ struct zfcp_fsf_req_pool_element { /********************** ZFCP SPECIFIC DEFINES ********************************/ -#define ZFCP_FSFREQ_CLEANUP_TIMEOUT HZ/10 - -#define ZFCP_KNOWN 0x00000001 #define ZFCP_REQ_AUTO_CLEANUP 0x00000002 #define ZFCP_WAIT_FOR_SBAL 0x00000004 #define ZFCP_REQ_NO_QTCB 0x00000008 @@ -1094,9 +1062,6 @@ struct zfcp_fsf_req_pool_element { #define ZFCP_SET 0x00000100 #define ZFCP_CLEAR 0x00000200 -#define ZFCP_INTERRUPTIBLE 1 -#define ZFCP_UNINTERRUPTIBLE 0 - #ifndef atomic_test_mask #define atomic_test_mask(mask, target) \ ((atomic_read(target) & mask) == mask) diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index ea2e7a39889..ce852c0de12 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -3407,7 +3407,7 @@ zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter) return; debug_text_event(adapter->erp_dbf, 3, "a_access_recover"); - debug_event(adapter->erp_dbf, 3, &adapter->name, 8); + debug_event(adapter->erp_dbf, 3, zfcp_get_busid_by_adapter(adapter), 8); read_lock_irqsave(&zfcp_data.config_lock, flags); if (adapter->nameserver_port) diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 4475e412066..83b68e3043c 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -1416,7 +1416,8 @@ zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool, /* settings in QTCB */ fsf_req->qtcb->header.port_handle = port->handle; - fsf_req->qtcb->bottom.support.service_class = adapter->fc_service_class; + fsf_req->qtcb->bottom.support.service_class = + ZFCP_FC_SERVICE_CLASS_DEFAULT; fsf_req->qtcb->bottom.support.timeout = ct->timeout; fsf_req->data = (unsigned long) ct; @@ -1485,18 +1486,10 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req) break; case FSF_SERVICE_CLASS_NOT_SUPPORTED: - if (adapter->fc_service_class <= 3) { - ZFCP_LOG_INFO("error: adapter %s does not support fc " - "class %d.\n", - zfcp_get_busid_by_port(port), - adapter->fc_service_class); - } else { - ZFCP_LOG_INFO("bug: The fibre channel class at the " - "adapter %s is invalid. " - "(debug info %d)\n", - zfcp_get_busid_by_port(port), - adapter->fc_service_class); - } + ZFCP_LOG_INFO("error: adapter %s does not support fc " + "class %d.\n", + zfcp_get_busid_by_port(port), + ZFCP_FC_SERVICE_CLASS_DEFAULT); /* stop operation for this adapter */ debug_text_exception(adapter->erp_dbf, 0, "fsf_s_class_nsup"); zfcp_erp_adapter_shutdown(adapter, 0); @@ -1719,7 +1712,8 @@ zfcp_fsf_send_els(struct zfcp_send_els *els) /* settings in QTCB */ fsf_req->qtcb->bottom.support.d_id = d_id; - fsf_req->qtcb->bottom.support.service_class = adapter->fc_service_class; + fsf_req->qtcb->bottom.support.service_class = + ZFCP_FC_SERVICE_CLASS_DEFAULT; fsf_req->qtcb->bottom.support.timeout = ZFCP_ELS_TIMEOUT; fsf_req->data = (unsigned long) els; @@ -1789,18 +1783,10 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req) break; case FSF_SERVICE_CLASS_NOT_SUPPORTED: - if (adapter->fc_service_class <= 3) { - ZFCP_LOG_INFO("error: adapter %s does " - "not support fibrechannel class %d.\n", - zfcp_get_busid_by_adapter(adapter), - adapter->fc_service_class); - } else { - ZFCP_LOG_INFO("bug: The fibrechannel class at " - "adapter %s is invalid. " - "(debug info %d)\n", - zfcp_get_busid_by_adapter(adapter), - adapter->fc_service_class); - } + ZFCP_LOG_INFO("error: adapter %s does not support fc " + "class %d.\n", + zfcp_get_busid_by_adapter(adapter), + ZFCP_FC_SERVICE_CLASS_DEFAULT); /* stop operation for this adapter */ debug_text_exception(adapter->erp_dbf, 0, "fsf_s_class_nsup"); zfcp_erp_adapter_shutdown(adapter, 0); @@ -2974,8 +2960,8 @@ zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action) erp_action->fsf_req->qtcb->bottom.support.fcp_lun = erp_action->unit->fcp_lun; if (!(erp_action->adapter->connection_features & FSF_FEATURE_NPIV_MODE)) - erp_action->fsf_req->qtcb->bottom.support.option = - FSF_OPEN_LUN_SUPPRESS_BOXING; + erp_action->fsf_req->qtcb->bottom.support.option = + FSF_OPEN_LUN_SUPPRESS_BOXING; atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->unit->status); erp_action->fsf_req->data = (unsigned long) erp_action->unit; erp_action->fsf_req->erp_action = erp_action; @@ -3550,7 +3536,7 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter, } /* set FC service class in QTCB (3 per default) */ - fsf_req->qtcb->bottom.io.service_class = adapter->fc_service_class; + fsf_req->qtcb->bottom.io.service_class = ZFCP_FC_SERVICE_CLASS_DEFAULT; /* set FCP_LUN in FCP_CMND IU in QTCB */ fcp_cmnd_iu->fcp_lun = unit->fcp_lun; @@ -3689,7 +3675,7 @@ zfcp_fsf_send_fcp_command_task_management(struct zfcp_adapter *adapter, fsf_req->qtcb->header.lun_handle = unit->handle; fsf_req->qtcb->header.port_handle = unit->port->handle; fsf_req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND; - fsf_req->qtcb->bottom.io.service_class = adapter->fc_service_class; + fsf_req->qtcb->bottom.io.service_class = ZFCP_FC_SERVICE_CLASS_DEFAULT; fsf_req->qtcb->bottom.io.fcp_cmnd_length = sizeof (struct fcp_cmnd_iu) + sizeof (fcp_dl_t); @@ -3812,18 +3798,10 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req) break; case FSF_SERVICE_CLASS_NOT_SUPPORTED: - if (fsf_req->adapter->fc_service_class <= 3) { - ZFCP_LOG_NORMAL("error: The adapter %s does " - "not support fibrechannel class %d.\n", - zfcp_get_busid_by_unit(unit), - fsf_req->adapter->fc_service_class); - } else { - ZFCP_LOG_NORMAL("bug: The fibrechannel class at " - "adapter %s is invalid. " - "(debug info %d)\n", - zfcp_get_busid_by_unit(unit), - fsf_req->adapter->fc_service_class); - } + ZFCP_LOG_INFO("error: adapter %s does not support fc " + "class %d.\n", + zfcp_get_busid_by_unit(unit), + ZFCP_FC_SERVICE_CLASS_DEFAULT); /* stop operation for this adapter */ debug_text_exception(fsf_req->adapter->erp_dbf, 0, "fsf_s_class_nsup"); diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h index ca16dca3050..71186618947 100644 --- a/drivers/s390/scsi/zfcp_fsf.h +++ b/drivers/s390/scsi/zfcp_fsf.h @@ -22,8 +22,7 @@ #ifndef FSF_H #define FSF_H -#define FSF_QTCB_VERSION1 0x00000001 -#define FSF_QTCB_CURRENT_VERSION FSF_QTCB_VERSION1 +#define FSF_QTCB_CURRENT_VERSION 0x00000001 /* FSF commands */ #define FSF_QTCB_FCP_CMND 0x00000001 @@ -53,7 +52,7 @@ #define FSF_CFDC_OPTION_FULL_ACCESS 0x00000002 #define FSF_CFDC_OPTION_RESTRICTED_ACCESS 0x00000004 -/* FSF protocol stati */ +/* FSF protocol states */ #define FSF_PROT_GOOD 0x00000001 #define FSF_PROT_QTCB_VERSION_ERROR 0x00000010 #define FSF_PROT_SEQ_NUMB_ERROR 0x00000020 @@ -65,7 +64,7 @@ #define FSF_PROT_REEST_QUEUE 0x00000800 #define FSF_PROT_ERROR_STATE 0x01000000 -/* FSF stati */ +/* FSF states */ #define FSF_GOOD 0x00000000 #define FSF_PORT_ALREADY_OPEN 0x00000001 #define FSF_LUN_ALREADY_OPEN 0x00000002 @@ -258,20 +257,6 @@ #define FSF_UNIT_ACCESS_EXCLUSIVE 0x02000000 #define FSF_UNIT_ACCESS_OUTBOUND_TRANSFER 0x10000000 -struct fsf_queue_designator; -struct fsf_status_read_buffer; -struct fsf_port_closed_payload; -struct fsf_bit_error_payload; -union fsf_prot_status_qual; -struct fsf_qual_version_error; -struct fsf_qual_sequence_error; -struct fsf_qtcb_prefix; -struct fsf_qtcb_header; -struct fsf_qtcb_bottom_config; -struct fsf_qtcb_bottom_support; -struct fsf_qtcb_bottom_io; -union fsf_qtcb_bottom; - struct fsf_queue_designator { u8 cssid; u8 chpid; diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index dfb6644d17b..345a191926a 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c @@ -168,7 +168,8 @@ zfcp_qdio_allocate(struct zfcp_adapter *adapter) init_data->cdev = adapter->ccw_device; init_data->q_format = QDIO_SCSI_QFMT; - memcpy(init_data->adapter_name, &adapter->name, 8); + memcpy(init_data->adapter_name, zfcp_get_busid_by_adapter(adapter), 8); + ASCEBC(init_data->adapter_name, 8); init_data->qib_param_field_format = 0; init_data->qib_param_field = NULL; init_data->input_slib_elements = NULL; diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 3a180d80c3c..f198814196a 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -35,8 +35,8 @@ static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *); static int zfcp_task_management_function(struct zfcp_unit *, u8, struct scsi_cmnd *); -static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int, scsi_id_t, - scsi_lun_t); +static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int, + unsigned int, unsigned int); static struct device_attribute *zfcp_sysfs_sdev_attrs[]; @@ -349,8 +349,8 @@ zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt, } static struct zfcp_unit * -zfcp_unit_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id, - scsi_lun_t lun) +zfcp_unit_lookup(struct zfcp_adapter *adapter, int channel, unsigned int id, + unsigned int lun) { struct zfcp_port *port; struct zfcp_unit *unit, *retval = NULL; @@ -608,10 +608,6 @@ zfcp_adapter_scsi_register(struct zfcp_adapter *adapter) adapter->scsi_host->unique_id = unique_id++; /* FIXME */ adapter->scsi_host->max_cmd_len = ZFCP_MAX_SCSI_CMND_LENGTH; adapter->scsi_host->transportt = zfcp_transport_template; - /* - * Reverse mapping of the host number to avoid race condition - */ - adapter->scsi_host_no = adapter->scsi_host->host_no; /* * save a pointer to our own adapter data structure within @@ -647,7 +643,6 @@ zfcp_adapter_scsi_unregister(struct zfcp_adapter *adapter) scsi_remove_host(shost); scsi_host_put(shost); adapter->scsi_host = NULL; - adapter->scsi_host_no = 0; atomic_clear_mask(ZFCP_STATUS_ADAPTER_REGISTERED, &adapter->status); return; -- cgit v1.2.3 From b7a52fa7fff2309031a2f849bc489206afd2fa4a Mon Sep 17 00:00:00 2001 From: Ralph Wuerthner Date: Mon, 22 May 2006 18:21:28 +0200 Subject: [SCSI] zfcp: print bit error threshold data human readable Replace hex dump of bit error threshold data by log message showing bit error threshold data human readable. Signed-off-by: Ralph Wuerthner Signed-off-by: Andreas Herrmann Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_fsf.c | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 83b68e3043c..55785acf870 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -866,6 +866,7 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req) struct zfcp_adapter *adapter = fsf_req->adapter; struct fsf_status_read_buffer *status_buffer = (struct fsf_status_read_buffer *) fsf_req->data; + struct fsf_bit_error_payload *fsf_bit_error; if (fsf_req->status & ZFCP_STATUS_FSFREQ_DISMISSED) { zfcp_hba_dbf_event_fsf_unsol("dism", adapter, status_buffer); @@ -892,10 +893,37 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req) break; case FSF_STATUS_READ_BIT_ERROR_THRESHOLD: - ZFCP_LOG_NORMAL("Bit error threshold data received:\n"); - ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL, - (char *) status_buffer, - sizeof (struct fsf_status_read_buffer)); + fsf_bit_error = (struct fsf_bit_error_payload *) + status_buffer->payload; + ZFCP_LOG_NORMAL("Warning: bit error threshold data " + "received (adapter %s, " + "link failures = %i, loss of sync errors = %i, " + "loss of signal errors = %i, " + "primitive sequence errors = %i, " + "invalid transmission word errors = %i, " + "CRC errors = %i)\n", + zfcp_get_busid_by_adapter(adapter), + fsf_bit_error->link_failure_error_count, + fsf_bit_error->loss_of_sync_error_count, + fsf_bit_error->loss_of_signal_error_count, + fsf_bit_error->primitive_sequence_error_count, + fsf_bit_error->invalid_transmission_word_error_count, + fsf_bit_error->crc_error_count); + ZFCP_LOG_INFO("Additional bit error threshold data " + "(adapter %s, " + "primitive sequence event time-outs = %i, " + "elastic buffer overrun errors = %i, " + "advertised receive buffer-to-buffer credit = %i, " + "current receice buffer-to-buffer credit = %i, " + "advertised transmit buffer-to-buffer credit = %i, " + "current transmit buffer-to-buffer credit = %i)\n", + zfcp_get_busid_by_adapter(adapter), + fsf_bit_error->primitive_sequence_event_timeout_count, + fsf_bit_error->elastic_buffer_overrun_error_count, + fsf_bit_error->advertised_receive_b2b_credit, + fsf_bit_error->current_receive_b2b_credit, + fsf_bit_error->advertised_transmit_b2b_credit, + fsf_bit_error->current_transmit_b2b_credit); break; case FSF_STATUS_READ_LINK_DOWN: -- cgit v1.2.3 From 75bfc2837bbcc329193d51e8b7115184b78beae0 Mon Sep 17 00:00:00 2001 From: Ralph Wuerthner Date: Mon, 22 May 2006 18:24:33 +0200 Subject: [SCSI] zfcp: evaluate plogi payload to set maxframe_size, supported_classes of rports Signed-off-by: Ralph Wuerthner Signed-off-by: Andreas Herrmann Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_aux.c | 21 +++++++++++++++++++++ drivers/s390/scsi/zfcp_def.h | 2 ++ drivers/s390/scsi/zfcp_erp.c | 6 +++++- drivers/s390/scsi/zfcp_ext.h | 1 + drivers/s390/scsi/zfcp_fsf.c | 7 ++++--- drivers/s390/scsi/zfcp_scsi.c | 1 + 6 files changed, 34 insertions(+), 4 deletions(-) diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index bdaad5535e2..9cd789b8acd 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -1748,4 +1748,25 @@ zfcp_handle_els_rjt(u32 sq, struct zfcp_ls_rjt_par *rjt_par) return ret; } +/** + * zfcp_plogi_evaluate - evaluate PLOGI playload and copy important fields + * into zfcp_port structure + * @port: zfcp_port structure + * @plogi: plogi payload + */ +void +zfcp_plogi_evaluate(struct zfcp_port *port, struct fsf_plogi *plogi) +{ + port->maxframe_size = plogi->serv_param.common_serv_param[7] | + ((plogi->serv_param.common_serv_param[6] & 0x0F) << 8); + if (plogi->serv_param.class1_serv_param[0] & 0x80) + port->supported_classes |= FC_COS_CLASS1; + if (plogi->serv_param.class2_serv_param[0] & 0x80) + port->supported_classes |= FC_COS_CLASS2; + if (plogi->serv_param.class3_serv_param[0] & 0x80) + port->supported_classes |= FC_COS_CLASS3; + if (plogi->serv_param.class4_serv_param[0] & 0x80) + port->supported_classes |= FC_COS_CLASS4; +} + #undef ZFCP_LOG_AREA diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index e93272f1882..a67d608388a 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -959,6 +959,8 @@ struct zfcp_port { u32 handle; /* handle assigned by FSF */ struct zfcp_erp_action erp_action; /* pending error recovery */ atomic_t erp_counter; + u32 maxframe_size; + u32 supported_classes; }; /* the struct device sysfs_device must be at the beginning of this structure. diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index ce852c0de12..05c47f6ca92 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -3257,8 +3257,12 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter, "(adapter %s, wwpn=0x%016Lx)\n", zfcp_get_busid_by_port(port), port->wwpn); - else + else { scsi_flush_work(adapter->scsi_host); + port->rport->maxframe_size = port->maxframe_size; + port->rport->supported_classes = + port->supported_classes; + } } zfcp_port_put(port); break; diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index 6be2bb71c73..ab38b8ce27a 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -115,6 +115,7 @@ extern int zfcp_nameserver_enqueue(struct zfcp_adapter *); extern int zfcp_ns_gid_pn_request(struct zfcp_erp_action *); extern int zfcp_check_ct_response(struct ct_hdr *); extern int zfcp_handle_els_rjt(u32, struct zfcp_ls_rjt_par *); +extern void zfcp_plogi_evaluate(struct zfcp_port *, struct fsf_plogi *); /******************************* SCSI ****************************************/ extern int zfcp_adapter_scsi_register(struct zfcp_adapter *); diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 55785acf870..6335f922918 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -2560,8 +2560,7 @@ zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req) if (!atomic_test_mask(ZFCP_STATUS_PORT_NO_WWPN, &port->status)) { if (fsf_req->qtcb->bottom.support.els1_length < - ((((unsigned long) &plogi->serv_param.wwpn) - - ((unsigned long) plogi)) + sizeof (u64))) { + sizeof (struct fsf_plogi)) { ZFCP_LOG_INFO( "warning: insufficient length of " "PLOGI payload (%i)\n", @@ -2580,8 +2579,10 @@ zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req) atomic_clear_mask( ZFCP_STATUS_PORT_DID_DID, &port->status); - } else + } else { port->wwnn = plogi->serv_param.wwnn; + zfcp_plogi_evaluate(port, plogi); + } } } break; diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index f198814196a..30e87197f5f 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -805,6 +805,7 @@ struct fc_function_template zfcp_transport_functions = { .show_starget_port_name = 1, .show_starget_node_name = 1, .show_rport_supported_classes = 1, + .show_rport_maxframe_size = 1, .show_host_node_name = 1, .show_host_port_name = 1, .show_host_permanent_port_name = 1, -- cgit v1.2.3 From 338151e066084d92d89f44311e5521ef847a50b9 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Mon, 22 May 2006 18:25:56 +0200 Subject: [SCSI] zfcp: make use of fc_remote_port_delete when target port is unavailable If zfcp's port erp fails we now call fc_remote_port_delete. This helps to avoid offlined scsi devices if scsi commands time out due to path failures. When an adapter erp fails we call fc_remote_port_delete for all ports on that adapter. Signed-off-by: Andreas Herrmann Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_erp.c | 22 ++++++++++++++++++++-- drivers/s390/scsi/zfcp_ext.h | 2 -- drivers/s390/scsi/zfcp_scsi.c | 7 +++++++ 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 05c47f6ca92..4682c8b8bd2 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -3241,9 +3241,13 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter, break; case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: case ZFCP_ERP_ACTION_REOPEN_PORT: + if (atomic_test_mask(ZFCP_STATUS_PORT_NO_WWPN, + &port->status)) { + zfcp_port_put(port); + break; + } + if ((result == ZFCP_ERP_SUCCEEDED) - && !atomic_test_mask(ZFCP_STATUS_PORT_NO_WWPN, - &port->status) && !port->rport) { struct fc_rport_identifiers ids; ids.node_name = port->wwnn; @@ -3264,9 +3268,23 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter, port->supported_classes; } } + if ((result != ZFCP_ERP_SUCCEEDED) && port->rport) { + fc_remote_port_delete(port->rport); + port->rport = NULL; + } zfcp_port_put(port); break; case ZFCP_ERP_ACTION_REOPEN_ADAPTER: + if (result != ZFCP_ERP_SUCCEEDED) { + struct zfcp_port *port; + list_for_each_entry(port, &adapter->port_list_head, list) + if (port->rport && + !atomic_test_mask(ZFCP_STATUS_PORT_WKA, + &port->status)) { + fc_remote_port_delete(port->rport); + port->rport = NULL; + } + } zfcp_adapter_put(adapter); break; default: diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index ab38b8ce27a..d02366004cd 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -132,8 +132,6 @@ extern int zfcp_scsi_command_async(struct zfcp_adapter *,struct zfcp_unit *, struct scsi_cmnd *, struct timer_list *); extern int zfcp_scsi_command_sync(struct zfcp_unit *, struct scsi_cmnd *, struct timer_list *); -extern void zfcp_set_fc_host_attrs(struct zfcp_adapter *); -extern void zfcp_set_fc_rport_attrs(struct zfcp_port *); extern struct scsi_transport_template *zfcp_transport_template; extern struct fc_function_template zfcp_transport_functions; diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 30e87197f5f..46e14f22ec1 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -800,12 +800,18 @@ zfcp_reset_fc_host_stats(struct Scsi_Host *shost) } } +static void zfcp_set_rport_dev_loss_tmo(struct fc_rport *rport, u32 timeout) +{ + rport->dev_loss_tmo = timeout; +} + struct fc_function_template zfcp_transport_functions = { .show_starget_port_id = 1, .show_starget_port_name = 1, .show_starget_node_name = 1, .show_rport_supported_classes = 1, .show_rport_maxframe_size = 1, + .show_rport_dev_loss_tmo = 1, .show_host_node_name = 1, .show_host_port_name = 1, .show_host_permanent_port_name = 1, @@ -815,6 +821,7 @@ struct fc_function_template zfcp_transport_functions = { .show_host_serial_number = 1, .get_fc_host_stats = zfcp_get_fc_host_stats, .reset_fc_host_stats = zfcp_reset_fc_host_stats, + .set_rport_dev_loss_tmo = zfcp_set_rport_dev_loss_tmo, /* no functions registered for following dynamic attributes but directly set by LLDD */ .show_host_port_type = 1, -- cgit v1.2.3 From 93ef588735973e4c35ff3707685678cdebd694a4 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Mon, 22 May 2006 18:27:30 +0200 Subject: [SCSI] zfcp: bump up version number Bump up version number, skip "4.6.0" because this might clash with zfcp version in certain distros. Signed-off-by: Andreas Herrmann Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_def.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index a67d608388a..2df512a18e2 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -52,7 +52,7 @@ /********************* GENERAL DEFINES *********************************/ /* zfcp version number, it consists of major, minor, and patch-level number */ -#define ZFCP_VERSION "4.5.0" +#define ZFCP_VERSION "4.7.0" /** * zfcp_sg_to_address - determine kernel address from struct scatterlist -- cgit v1.2.3 From 091686d3b5569d2ec76b9e6dab7f3608b6f64497 Mon Sep 17 00:00:00 2001 From: Amit Arora Date: Fri, 19 May 2006 16:14:50 -0700 Subject: [SCSI] Return -EINVAL when "id == max_id" in scsi_scan_host_selected() The scsi_scan_host_selected() should return -EINVAL when the id is equal to the max_id. Currently it uses ">" when comparing with max_id, and hence leaves the border case when "id==max_id". The channel and lun have values valid from 0 up to, and including, max_channel or max_lun. But, the valid values for id range from 0 to max_id-1. This patch fixes the problem. Signed-off-by: Amit Arora Signed-off-by: James Bottomley --- drivers/scsi/scsi_scan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index f85d9100f55..fd97d07577a 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -1503,7 +1503,7 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel, __FUNCTION__, channel, id, lun)); if (((channel != SCAN_WILD_CARD) && (channel > shost->max_channel)) || - ((id != SCAN_WILD_CARD) && (id > shost->max_id)) || + ((id != SCAN_WILD_CARD) && (id >= shost->max_id)) || ((lun != SCAN_WILD_CARD) && (lun > shost->max_lun))) return -EINVAL; -- cgit v1.2.3 From 2b89dad0c7e3b03d45d9674ee9a7b49670df098e Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 23 May 2006 10:29:28 +0200 Subject: [SCSI] audit drivers for incorrect max_id use max_id now means the maximum number of ids on the bus, which means it is one greater than the largest possible id number. Signed-off-by: James Bottomley --- drivers/scsi/53c700.c | 2 +- drivers/scsi/53c7xx.c | 4 ++-- drivers/scsi/aic7xxx/aic79xx_core.c | 4 ++-- drivers/scsi/aic7xxx/aic7xxx_core.c | 4 ++-- drivers/scsi/atp870u.c | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c index 6a0f9506ea0..b767918b9a9 100644 --- a/drivers/scsi/53c700.c +++ b/drivers/scsi/53c700.c @@ -376,7 +376,7 @@ NCR_700_detect(struct scsi_host_template *tpnt, dma_sync_single_for_device(hostdata->dev, pScript, sizeof(SCRIPT), DMA_TO_DEVICE); hostdata->state = NCR_700_HOST_FREE; hostdata->cmd = NULL; - host->max_id = 7; + host->max_id = 8; host->max_lun = NCR_700_MAX_LUNS; BUG_ON(NCR_700_transport_template == NULL); host->transportt = NCR_700_transport_template; diff --git a/drivers/scsi/53c7xx.c b/drivers/scsi/53c7xx.c index 7894b8ea84b..cfc991271cc 100644 --- a/drivers/scsi/53c7xx.c +++ b/drivers/scsi/53c7xx.c @@ -709,7 +709,7 @@ request_synchronous (int host, int target) { printk (KERN_ALERT "target %d is host ID\n", target); return -1; } - else if (target > h->max_id) { + else if (target >= h->max_id) { printk (KERN_ALERT "target %d exceeds maximum of %d\n", target, h->max_id); return -1; @@ -3622,7 +3622,7 @@ NCR53c7xx_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)) { #ifdef LINUX_1_2 || cmd->device->id > 7 #else - || cmd->device->id > host->max_id + || cmd->device->id >= host->max_id #endif || cmd->device->id == host->this_id || hostdata->state == STATE_DISABLED) { diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c index 08771f6f685..e14244aa69d 100644 --- a/drivers/scsi/aic7xxx/aic79xx_core.c +++ b/drivers/scsi/aic7xxx/aic79xx_core.c @@ -9396,8 +9396,8 @@ ahd_find_tmode_devs(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb, } else { u_int max_id; - max_id = (ahd->features & AHD_WIDE) ? 15 : 7; - if (ccb->ccb_h.target_id > max_id) + max_id = (ahd->features & AHD_WIDE) ? 16 : 8; + if (ccb->ccb_h.target_id >= max_id) return (CAM_TID_INVALID); if (ccb->ccb_h.target_lun >= AHD_NUM_LUNS) diff --git a/drivers/scsi/aic7xxx/aic7xxx_core.c b/drivers/scsi/aic7xxx/aic7xxx_core.c index d37566978fb..50a3dd047cf 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_core.c +++ b/drivers/scsi/aic7xxx/aic7xxx_core.c @@ -6774,8 +6774,8 @@ ahc_find_tmode_devs(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb, } else { u_int max_id; - max_id = (ahc->features & AHC_WIDE) ? 15 : 7; - if (ccb->ccb_h.target_id > max_id) + max_id = (ahc->features & AHC_WIDE) ? 16 : 8; + if (ccb->ccb_h.target_id >= max_id) return (CAM_TID_INVALID); if (ccb->ccb_h.target_lun >= AHC_NUM_LUNS) diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c index a198d86667e..58d7e34807a 100644 --- a/drivers/scsi/atp870u.c +++ b/drivers/scsi/atp870u.c @@ -3047,7 +3047,7 @@ flash_ok_885: if (atp_dev.chip_ver == 4) shpnt->max_id = 16; else - shpnt->max_id = 7; + shpnt->max_id = 8; shpnt->this_id = host_id; shpnt->unique_id = base_io; shpnt->io_port = base_io; -- cgit v1.2.3 From ef2824073fba9def3cf122e89cc485f66dd71f70 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 29 May 2006 01:06:23 -0400 Subject: libata debugging: set initial dbg value This patch sets the prerequisites for the new debugging scheme that more or less resembles Donald Becker's net driver example. This one liner doesn't change any functionality beside setting the appropriate debug level for the msg_enable control in the ata_port struct, which will be later used by the ata_msg_* macros to control the amount of debug information sent to printk. Signed-off-by: Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index abcf17ebda9..11df827e166 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -5185,6 +5185,7 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host, ap->sata_spd_limit = UINT_MAX; ap->active_tag = ATA_TAG_POISON; ap->last_ctl = 0xFF; + ap->msg_enable = ATA_MSG_DRV; INIT_WORK(&ap->port_task, NULL, NULL); INIT_LIST_HEAD(&ap->eh_done_q); -- cgit v1.2.3 From 20952b699035448d2277c64efc5910a31be66ed1 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 31 May 2006 18:27:23 +0900 Subject: [PATCH] libata: set PIO-0 after successful EH reset Set ata_device->pio_mode to XFER_PIO_0 after a successful reset. This is to keep EH resets consistent with probe resets as updated by the commit b6079ca409bf88c248992e96510dd6f610f7ed89. Note that, with soon-to-follow hotplug update, EH resets will include probe resets. Signed-off-by: Tejun Heo --- drivers/scsi/libata-eh.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c index 71b45ad2c12..b88f492eab1 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/scsi/libata-eh.c @@ -1287,7 +1287,7 @@ static int ata_eh_reset(struct ata_port *ap, ata_reset_fn_t softreset, unsigned int classes[ATA_MAX_DEVICES]; int tries = ATA_EH_RESET_TRIES; ata_reset_fn_t reset; - int rc; + int i, rc; if (softreset && (!hardreset || (!sata_set_spd_needed(ap) && !(ehc->i.action & ATA_EH_HARDRESET)))) @@ -1319,6 +1319,12 @@ static int ata_eh_reset(struct ata_port *ap, ata_reset_fn_t softreset, } if (rc == 0) { + /* After the reset, the device state is PIO 0 and the + * controller state is undefined. Record the mode. + */ + for (i = 0; i < ATA_MAX_DEVICES; i++) + ap->device[i].pio_mode = XFER_PIO_0; + if (postreset) postreset(ap, classes); -- cgit v1.2.3 From 7395acb2c840fd4d0cacc91d6fb71440057141ab Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 31 May 2006 18:27:25 +0900 Subject: [PATCH] libata: shift host flag constants Nudge host flag constants to make a room after ATA_FLAG_EH_PENDING. New EH flag will be added. Signed-off-by: Tejun Heo --- include/linux/libata.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/linux/libata.h b/include/linux/libata.h index b0ee1c1437d..3f9c65f1aaf 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -149,14 +149,14 @@ enum { ATA_FLAG_NO_ATAPI = (1 << 6), /* No ATAPI support */ ATA_FLAG_PIO_DMA = (1 << 7), /* PIO cmds via DMA */ ATA_FLAG_PIO_LBA48 = (1 << 8), /* Host DMA engine is LBA28 only */ - ATA_FLAG_PIO_POLLING = (1 << 10), /* use polling PIO if LLD - * doesn't handle PIO interrupts */ - ATA_FLAG_NCQ = (1 << 11), /* host supports NCQ */ + ATA_FLAG_PIO_POLLING = (1 << 9), /* use polling PIO if LLD + * doesn't handle PIO interrupts */ + ATA_FLAG_NCQ = (1 << 10), /* host supports NCQ */ - ATA_FLAG_DEBUGMSG = (1 << 14), - ATA_FLAG_FLUSH_PORT_TASK = (1 << 15), /* flush port task */ + ATA_FLAG_DEBUGMSG = (1 << 13), + ATA_FLAG_FLUSH_PORT_TASK = (1 << 14), /* flush port task */ - ATA_FLAG_EH_PENDING = (1 << 16), /* EH pending */ + ATA_FLAG_EH_PENDING = (1 << 15), /* EH pending */ ATA_FLAG_FROZEN = (1 << 17), /* port is frozen */ ATA_FLAG_RECOVERED = (1 << 18), /* recovery action performed */ -- cgit v1.2.3 From c6cf9e99d1de5ca6a08fb639bb73031ffe50d802 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 31 May 2006 18:27:27 +0900 Subject: [PATCH] libata: implement ata_eh_wait() Implement ata_eh_wait(). On return from this function, it's guaranteed that the EH which was pending or in progress when the function was called is complete - including the tailing part of SCSI EH. This will be used by hotplug and others to synchronize with EH. Signed-off-by: Tejun Heo --- drivers/scsi/libata-core.c | 1 + drivers/scsi/libata-eh.c | 38 ++++++++++++++++++++++++++++++++++++++ drivers/scsi/libata.h | 1 + include/linux/libata.h | 2 ++ 4 files changed, 42 insertions(+) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 11df827e166..66df895c961 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -5189,6 +5189,7 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host, INIT_WORK(&ap->port_task, NULL, NULL); INIT_LIST_HEAD(&ap->eh_done_q); + init_waitqueue_head(&ap->eh_wait_q); /* set cable type */ ap->cbl = ATA_CBL_NONE; diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c index b88f492eab1..9173d8f2ce5 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/scsi/libata-eh.c @@ -237,6 +237,7 @@ void ata_scsi_error(struct Scsi_Host *host) ap->eh_context.i = ap->eh_info; memset(&ap->eh_info, 0, sizeof(ap->eh_info)); + ap->flags |= ATA_FLAG_EH_IN_PROGRESS; ap->flags &= ~ATA_FLAG_EH_PENDING; spin_unlock_irqrestore(hs_lock, flags); @@ -290,11 +291,48 @@ void ata_scsi_error(struct Scsi_Host *host) ata_port_printk(ap, KERN_INFO, "EH complete\n"); ap->flags &= ~ATA_FLAG_RECOVERED; + /* tell wait_eh that we're done */ + ap->flags &= ~ATA_FLAG_EH_IN_PROGRESS; + wake_up_all(&ap->eh_wait_q); + spin_unlock_irqrestore(hs_lock, flags); DPRINTK("EXIT\n"); } +/** + * ata_port_wait_eh - Wait for the currently pending EH to complete + * @ap: Port to wait EH for + * + * Wait until the currently pending EH is complete. + * + * LOCKING: + * Kernel thread context (may sleep). + */ +void ata_port_wait_eh(struct ata_port *ap) +{ + unsigned long flags; + DEFINE_WAIT(wait); + + retry: + spin_lock_irqsave(&ap->host_set->lock, flags); + + while (ap->flags & (ATA_FLAG_EH_PENDING | ATA_FLAG_EH_IN_PROGRESS)) { + prepare_to_wait(&ap->eh_wait_q, &wait, TASK_UNINTERRUPTIBLE); + spin_unlock_irqrestore(&ap->host_set->lock, flags); + schedule(); + spin_lock_irqsave(&ap->host_set->lock, flags); + } + + spin_unlock_irqrestore(&ap->host_set->lock, flags); + + /* make sure SCSI EH is complete */ + if (scsi_host_in_recovery(ap->host)) { + msleep(10); + goto retry; + } +} + /** * ata_qc_timeout - Handle timeout of queued command * @qc: Command that timed out diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index b76ad7d7062..d56d9e1d73d 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -103,6 +103,7 @@ extern void ata_schedule_scsi_eh(struct Scsi_Host *shost); /* libata-eh.c */ extern enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd); extern void ata_scsi_error(struct Scsi_Host *host); +extern void ata_port_wait_eh(struct ata_port *ap); extern void ata_qc_schedule_eh(struct ata_queued_cmd *qc); #endif /* __LIBATA_H__ */ diff --git a/include/linux/libata.h b/include/linux/libata.h index 3f9c65f1aaf..2eb5828839e 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -157,6 +157,7 @@ enum { ATA_FLAG_FLUSH_PORT_TASK = (1 << 14), /* flush port task */ ATA_FLAG_EH_PENDING = (1 << 15), /* EH pending */ + ATA_FLAG_EH_IN_PROGRESS = (1 << 16), /* EH in progress */ ATA_FLAG_FROZEN = (1 << 17), /* port is frozen */ ATA_FLAG_RECOVERED = (1 << 18), /* recovery action performed */ @@ -490,6 +491,7 @@ struct ata_port { u32 msg_enable; struct list_head eh_done_q; + wait_queue_head_t eh_wait_q; void *private_data; -- cgit v1.2.3 From abdda7331d469fa965167365f011d05e226008fb Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 31 May 2006 18:27:29 +0900 Subject: [PATCH] libata-hp-prep: add flags and eh_info/context fields for hotplug Add hotplug related flags and eh_info/context fields. Signed-off-by: Tejun Heo --- include/linux/libata.h | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/include/linux/libata.h b/include/linux/libata.h index 2eb5828839e..d4a668cf143 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -131,6 +131,9 @@ enum { ATA_DFLAG_PIO = (1 << 8), /* device currently in PIO mode */ + ATA_DFLAG_DETACH = (1 << 16), + ATA_DFLAG_DETACHED = (1 << 17), + ATA_DEV_UNKNOWN = 0, /* unknown device */ ATA_DEV_ATA = 1, /* ATA device */ ATA_DEV_ATA_UNSUP = 2, /* ATA device (unsupported) */ @@ -152,6 +155,9 @@ enum { ATA_FLAG_PIO_POLLING = (1 << 9), /* use polling PIO if LLD * doesn't handle PIO interrupts */ ATA_FLAG_NCQ = (1 << 10), /* host supports NCQ */ + ATA_FLAG_HRST_TO_RESUME = (1 << 11), /* hardreset to resume phy */ + ATA_FLAG_SKIP_D2H_BSY = (1 << 12), /* can't wait for the first D2H + * Register FIS clearing BSY */ ATA_FLAG_DEBUGMSG = (1 << 13), ATA_FLAG_FLUSH_PORT_TASK = (1 << 14), /* flush port task */ @@ -160,6 +166,9 @@ enum { ATA_FLAG_EH_IN_PROGRESS = (1 << 16), /* EH in progress */ ATA_FLAG_FROZEN = (1 << 17), /* port is frozen */ ATA_FLAG_RECOVERED = (1 << 18), /* recovery action performed */ + ATA_FLAG_LOADING = (1 << 19), /* boot/loading probe */ + ATA_FLAG_UNLOADING = (1 << 20), /* module is unloading */ + ATA_FLAG_SCSI_HOTPLUG = (1 << 21), /* SCSI hotplug scheduled */ ATA_FLAG_DISABLED = (1 << 22), /* port is disabled, ignore it */ ATA_FLAG_SUSPENDED = (1 << 23), /* port is suspended (power) */ @@ -241,7 +250,9 @@ enum { ATA_EH_RESET_MASK = ATA_EH_SOFTRESET | ATA_EH_HARDRESET, /* ata_eh_info->flags */ - ATA_EHI_DID_RESET = (1 << 0), /* already reset this port */ + ATA_EHI_HOTPLUGGED = (1 << 0), /* could have been hotplugged */ + + ATA_EHI_DID_RESET = (1 << 16), /* already reset this port */ /* max repeat if error condition is still set after ->error_handler */ ATA_EH_MAX_REPEAT = 5, @@ -434,6 +445,10 @@ struct ata_eh_info { unsigned int err_mask; /* port-wide err_mask */ unsigned int action; /* ATA_EH_* action mask */ unsigned int flags; /* ATA_EHI_* flags */ + + unsigned long hotplug_timestamp; + unsigned int probe_mask; + char desc[ATA_EH_DESC_LEN]; int desc_len; }; @@ -441,6 +456,8 @@ struct ata_eh_info { struct ata_eh_context { struct ata_eh_info i; int tries[ATA_MAX_DEVICES]; + unsigned int classes[ATA_MAX_DEVICES]; + unsigned int did_probe_mask; }; struct ata_port { -- cgit v1.2.3 From 3ef3b43d5633d30fa3f033f62094ec2e9c5b8376 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 31 May 2006 18:27:30 +0900 Subject: [PATCH] libata-hp-prep: implement ata_dev_init() Move initialization of struct ata_device into ata_dev_init() in preparation for hotplug. This patch calls ata_dev_init() from ata_host_init() and thus makes no functional difference. Signed-off-by: Tejun Heo --- drivers/scsi/libata-core.c | 26 +++++++++++++++++++++----- drivers/scsi/libata.h | 1 + 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 66df895c961..8fda8228159 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -5141,6 +5141,26 @@ static void ata_host_remove(struct ata_port *ap, unsigned int do_unregister) ap->ops->port_stop(ap); } +/** + * ata_dev_init - Initialize an ata_device structure + * @dev: Device structure to initialize + * + * Initialize @dev in preparation for probing. + * + * LOCKING: + * Inherited from caller. + */ +void ata_dev_init(struct ata_device *dev) +{ + struct ata_port *ap = dev->ap; + + memset((void *)dev, 0, sizeof(*dev)); + dev->devno = dev - ap->device; + dev->pio_mask = UINT_MAX; + dev->mwdma_mask = UINT_MAX; + dev->udma_mask = UINT_MAX; +} + /** * ata_host_init - Initialize an ata_port structure * @ap: Structure to initialize @@ -5155,7 +5175,6 @@ static void ata_host_remove(struct ata_port *ap, unsigned int do_unregister) * LOCKING: * Inherited from caller. */ - static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host, struct ata_host_set *host_set, const struct ata_probe_ent *ent, unsigned int port_no) @@ -5199,10 +5218,7 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host, for (i = 0; i < ATA_MAX_DEVICES; i++) { struct ata_device *dev = &ap->device[i]; dev->ap = ap; - dev->devno = i; - dev->pio_mask = UINT_MAX; - dev->mwdma_mask = UINT_MAX; - dev->udma_mask = UINT_MAX; + ata_dev_init(dev); } #ifdef ATA_IRQ_TRAP diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index d56d9e1d73d..c2b1c919b96 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -62,6 +62,7 @@ extern int ata_check_atapi_dma(struct ata_queued_cmd *qc); extern void ata_dev_select(struct ata_port *ap, unsigned int device, unsigned int wait, unsigned int can_sleep); extern void swap_buf_le16(u16 *buf, unsigned int buf_words); +extern void ata_dev_init(struct ata_device *dev); extern int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg); extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg); -- cgit v1.2.3 From 72fa4b742b327bd1b07985d79a61c61dbd9fd4e6 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 31 May 2006 18:27:32 +0900 Subject: [PATCH] libata-hp-prep: make some ata_device fields persistent Lifetimes of some fields span over device plugging/unplugging. This patch moves such persistent fields to the top of ata_device and separate them with ATA_DEVICE_CLEAR_OFFSET. Fields above the offset are initialized once during host initializatino while all other fields are cleared before hotplugging. Currently ->ap, devno and part of flags are persistent. Note that flags is partially cleared while holding host_set lock. This is to synchronize with later warm plug implementation which will record hotplug request in dev->flags. Signed-off-by: Tejun Heo --- drivers/scsi/libata-core.c | 14 ++++++++++++-- include/linux/libata.h | 11 +++++++++-- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 8fda8228159..a07ab77d32d 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -5153,9 +5153,18 @@ static void ata_host_remove(struct ata_port *ap, unsigned int do_unregister) void ata_dev_init(struct ata_device *dev) { struct ata_port *ap = dev->ap; + unsigned long flags; + + /* High bits of dev->flags are used to record warm plug + * requests which occur asynchronously. Synchronize using + * host_set lock. + */ + spin_lock_irqsave(&ap->host_set->lock, flags); + dev->flags &= ~ATA_DFLAG_INIT_MASK; + spin_unlock_irqrestore(&ap->host_set->lock, flags); - memset((void *)dev, 0, sizeof(*dev)); - dev->devno = dev - ap->device; + memset((void *)dev + ATA_DEVICE_CLEAR_OFFSET, 0, + sizeof(*dev) - ATA_DEVICE_CLEAR_OFFSET); dev->pio_mask = UINT_MAX; dev->mwdma_mask = UINT_MAX; dev->udma_mask = UINT_MAX; @@ -5218,6 +5227,7 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host, for (i = 0; i < ATA_MAX_DEVICES; i++) { struct ata_device *dev = &ap->device[i]; dev->ap = ap; + dev->devno = i; ata_dev_init(dev); } diff --git a/include/linux/libata.h b/include/linux/libata.h index d4a668cf143..aa14eda0656 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -130,6 +130,7 @@ enum { ATA_DFLAG_CFG_MASK = (1 << 8) - 1, ATA_DFLAG_PIO = (1 << 8), /* device currently in PIO mode */ + ATA_DFLAG_INIT_MASK = (1 << 16) - 1, ATA_DFLAG_DETACH = (1 << 16), ATA_DFLAG_DETACHED = (1 << 17), @@ -410,10 +411,11 @@ struct ata_ering { struct ata_device { struct ata_port *ap; - u64 n_sectors; /* size of device, if ATA */ + unsigned int devno; /* 0 or 1 */ unsigned long flags; /* ATA_DFLAG_xxx */ + /* n_sector is used as CLEAR_OFFSET, read comment above CLEAR_OFFSET */ + u64 n_sectors; /* size of device, if ATA */ unsigned int class; /* ATA_DEV_xxx */ - unsigned int devno; /* 0 or 1 */ u16 id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */ u8 pio_mode; u8 dma_mode; @@ -439,6 +441,11 @@ struct ata_device { struct ata_ering ering; }; +/* Offset into struct ata_device. Fields above it are maintained + * acress device init. Fields below are zeroed. + */ +#define ATA_DEVICE_CLEAR_OFFSET offsetof(struct ata_device, n_sectors) + struct ata_eh_info { struct ata_device *dev; /* offending device */ u32 serror; /* SError from LLDD */ -- cgit v1.2.3 From ab5b3a5b2d887ce63f8c6a7fcb9f5c07ca4b4d43 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 31 May 2006 18:27:34 +0900 Subject: [PATCH] libata-hp-prep: update ata_scsi_find_dev() and friends Separate out ata_find_dev() and __ata_scsi_find_dev() from ata_scsi_find_dev(). These will be used by later hotplug implementation. Signed-off-by: Tejun Heo --- drivers/scsi/libata-scsi.c | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 9e5cb9f748e..b45b8b34c0c 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -52,8 +52,12 @@ #define SECTOR_SIZE 512 typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc, const u8 *scsicmd); -static struct ata_device * -ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev); + +static struct ata_device * __ata_scsi_find_dev(struct ata_port *ap, + const struct scsi_device *scsidev); +static struct ata_device * ata_scsi_find_dev(struct ata_port *ap, + const struct scsi_device *scsidev); + #define RW_RECOVERY_MPAGE 0x1 #define RW_RECOVERY_MPAGE_LEN 12 @@ -2308,6 +2312,23 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd) return 0; } +static struct ata_device * ata_find_dev(struct ata_port *ap, int id) +{ + if (likely(id < ATA_MAX_DEVICES)) + return &ap->device[id]; + return NULL; +} + +static struct ata_device * __ata_scsi_find_dev(struct ata_port *ap, + const struct scsi_device *scsidev) +{ + /* skip commands not addressed to targets we simulate */ + if (unlikely(scsidev->channel || scsidev->lun)) + return NULL; + + return ata_find_dev(ap, scsidev->id); +} + /** * ata_scsi_find_dev - lookup ata_device from scsi_cmnd * @ap: ATA port to which the device is attached @@ -2324,23 +2345,12 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd) * RETURNS: * Associated ATA device, or %NULL if not found. */ - static struct ata_device * ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev) { - struct ata_device *dev; - - /* skip commands not addressed to targets we simulate */ - if (likely(scsidev->id < ATA_MAX_DEVICES)) - dev = &ap->device[scsidev->id]; - else - return NULL; - - if (unlikely((scsidev->channel != 0) || - (scsidev->lun != 0))) - return NULL; + struct ata_device *dev = __ata_scsi_find_dev(ap, scsidev); - if (unlikely(!ata_dev_enabled(dev))) + if (unlikely(!dev || !ata_dev_enabled(dev))) return NULL; if (!atapi_enabled || (ap->flags & ATA_FLAG_NO_ATAPI)) { -- cgit v1.2.3 From 315343637b988ac32d730a6a9f7bf5866838bcb0 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 31 May 2006 18:27:36 +0900 Subject: [PATCH] libata-hp-prep: use __ata_scsi_find_dev() Convert direct sdev -> dev lookup to __ata_scsi_find_dev(). Signed-off-by: Tejun Heo --- drivers/scsi/libata-scsi.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index b45b8b34c0c..05090768d9a 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -399,7 +399,7 @@ void ata_dump_status(unsigned id, struct ata_taskfile *tf) int ata_scsi_device_resume(struct scsi_device *sdev) { struct ata_port *ap = ata_shost_to_port(sdev->host); - struct ata_device *dev = &ap->device[sdev->id]; + struct ata_device *dev = __ata_scsi_find_dev(ap, sdev); return ata_device_resume(dev); } @@ -407,7 +407,7 @@ int ata_scsi_device_resume(struct scsi_device *sdev) int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t state) { struct ata_port *ap = ata_shost_to_port(sdev->host); - struct ata_device *dev = &ap->device[sdev->id]; + struct ata_device *dev = __ata_scsi_find_dev(ap, sdev); return ata_device_suspend(dev, state); } @@ -713,19 +713,15 @@ static void ata_scsi_dev_config(struct scsi_device *sdev, int ata_scsi_slave_config(struct scsi_device *sdev) { + struct ata_port *ap = ata_shost_to_port(sdev->host); + struct ata_device *dev = __ata_scsi_find_dev(ap, sdev); + ata_scsi_sdev_config(sdev); blk_queue_max_phys_segments(sdev->request_queue, LIBATA_MAX_PRD); - if (sdev->id < ATA_MAX_DEVICES) { - struct ata_port *ap; - struct ata_device *dev; - - ap = ata_shost_to_port(sdev->host); - dev = &ap->device[sdev->id]; - + if (dev) ata_scsi_dev_config(sdev, dev); - } return 0; /* scsi layer doesn't check return value, sigh */ } -- cgit v1.2.3 From 5a04bf4befa8bffa012eedc3a0903c158b9131a9 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 31 May 2006 18:27:38 +0900 Subject: [PATCH] libata-hp-prep: implement ap->hw_sata_spd_limit Add ap->hw_sata_spd_limit and initialize it once during the boot initialization (or driver load initialization). ap->sata_spd_limit is reset to ap->hw_sata_spd_limit on hotplug. This prevents spd limits introduced by earlier devices from affecting new devices. Signed-off-by: Tejun Heo --- drivers/scsi/libata-core.c | 21 ++++++++++++--------- include/linux/libata.h | 1 + 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index a07ab77d32d..b1a02fdbb0a 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2466,17 +2466,9 @@ static int sata_phy_resume(struct ata_port *ap) */ void ata_std_probeinit(struct ata_port *ap) { - u32 scontrol; - /* resume link */ sata_phy_resume(ap); - /* init sata_spd_limit to the current value */ - if (sata_scr_read(ap, SCR_CONTROL, &scontrol) == 0) { - int spd = (scontrol >> 4) & 0xf; - ap->sata_spd_limit &= (1 << spd) - 1; - } - /* wait for device */ if (ata_port_online(ap)) ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT); @@ -5155,6 +5147,9 @@ void ata_dev_init(struct ata_device *dev) struct ata_port *ap = dev->ap; unsigned long flags; + /* SATA spd limit is bound to the first device */ + ap->sata_spd_limit = ap->hw_sata_spd_limit; + /* High bits of dev->flags are used to record warm plug * requests which occur asynchronously. Synchronize using * host_set lock. @@ -5210,7 +5205,7 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host, ap->udma_mask = ent->udma_mask; ap->flags |= ent->host_flags; ap->ops = ent->port_ops; - ap->sata_spd_limit = UINT_MAX; + ap->hw_sata_spd_limit = UINT_MAX; ap->active_tag = ATA_TAG_POISON; ap->last_ctl = 0xFF; ap->msg_enable = ATA_MSG_DRV; @@ -5375,10 +5370,18 @@ int ata_device_add(const struct ata_probe_ent *ent) DPRINTK("probe begin\n"); for (i = 0; i < count; i++) { struct ata_port *ap; + u32 scontrol; int rc; ap = host_set->ports[i]; + /* init sata_spd_limit to the current value */ + if (sata_scr_read(ap, SCR_CONTROL, &scontrol) == 0) { + int spd = (scontrol >> 4) & 0xf; + ap->hw_sata_spd_limit &= (1 << spd) - 1; + } + ap->sata_spd_limit = ap->hw_sata_spd_limit; + DPRINTK("ata%u: bus probe begin\n", ap->id); rc = ata_bus_probe(ap); DPRINTK("ata%u: bus probe end\n", ap->id); diff --git a/include/linux/libata.h b/include/linux/libata.h index aa14eda0656..10dc235ad8b 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -489,6 +489,7 @@ struct ata_port { unsigned int mwdma_mask; unsigned int udma_mask; unsigned int cbl; /* cable type; ATA_CBL_xxx */ + unsigned int hw_sata_spd_limit; unsigned int sata_spd_limit; /* SATA PHY speed limit */ /* record runtime error info, protected by host_set lock */ -- cgit v1.2.3 From 3edebac41bab7e146578ad9e723ee7fff71c99c0 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 31 May 2006 18:27:40 +0900 Subject: [PATCH] libata-hp-prep: store attached SCSI device Add device persistent field dev->sdev and store the attached SCSI device. With hotplug, libata needs to know the attached SCSI device to offline and detach it, but scsi_device_lookup() cannot be used because libata will reuse SCSI ID numbers - dead but not gone devices (due to zombie opens, etc...) interfere with the lookup. dev->sdev doesn't hold reference to the SCSI device. It's cleared when the SCSI device goes away. Signed-off-by: Tejun Heo --- drivers/scsi/libata-scsi.c | 14 ++++++++++---- include/linux/libata.h | 1 + 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 05090768d9a..da9689b7082 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -2743,16 +2743,22 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd, void ata_scsi_scan_host(struct ata_port *ap) { - struct ata_device *dev; unsigned int i; if (ap->flags & ATA_FLAG_DISABLED) return; for (i = 0; i < ATA_MAX_DEVICES; i++) { - dev = &ap->device[i]; + struct ata_device *dev = &ap->device[i]; + struct scsi_device *sdev; + + if (!ata_dev_enabled(dev) || dev->sdev) + continue; - if (ata_dev_enabled(dev)) - scsi_scan_target(&ap->host->shost_gendev, 0, i, 0, 0); + sdev = __scsi_add_device(ap->host, 0, i, 0, NULL); + if (!IS_ERR(sdev)) { + dev->sdev = sdev; + scsi_device_put(sdev); + } } } diff --git a/include/linux/libata.h b/include/linux/libata.h index 10dc235ad8b..c0513c75275 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -413,6 +413,7 @@ struct ata_device { struct ata_port *ap; unsigned int devno; /* 0 or 1 */ unsigned long flags; /* ATA_DFLAG_xxx */ + struct scsi_device *sdev; /* attached SCSI device */ /* n_sector is used as CLEAR_OFFSET, read comment above CLEAR_OFFSET */ u64 n_sectors; /* size of device, if ATA */ unsigned int class; /* ATA_DEV_xxx */ -- cgit v1.2.3 From 453b07accb47c5b54aa2f156ebffac63c543027b Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 31 May 2006 18:27:42 +0900 Subject: [PATCH] libata-hp-prep: add ata_aux_wq It's best to run ATA hotplug from EH but attaching SCSI devices needs working EH. ata_aux_wq is used to give SCSI hotplug operations a separate context. Signed-off-by: Tejun Heo --- drivers/scsi/libata-core.c | 9 +++++++++ drivers/scsi/libata.h | 1 + 2 files changed, 10 insertions(+) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index b1a02fdbb0a..04921cf2fc0 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -69,6 +69,8 @@ static void ata_dev_xfermask(struct ata_device *dev); static unsigned int ata_unique_id = 1; static struct workqueue_struct *ata_wq; +struct workqueue_struct *ata_aux_wq; + int atapi_enabled = 1; module_param(atapi_enabled, int, 0444); MODULE_PARM_DESC(atapi_enabled, "Enable discovery of ATAPI devices (0=off, 1=on)"); @@ -5623,6 +5625,12 @@ static int __init ata_init(void) if (!ata_wq) return -ENOMEM; + ata_aux_wq = create_singlethread_workqueue("ata_aux"); + if (!ata_aux_wq) { + destroy_workqueue(ata_wq); + return -ENOMEM; + } + printk(KERN_DEBUG "libata version " DRV_VERSION " loaded.\n"); return 0; } @@ -5630,6 +5638,7 @@ static int __init ata_init(void) static void __exit ata_exit(void) { destroy_workqueue(ata_wq); + destroy_workqueue(ata_aux_wq); } module_init(ata_init); diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index c2b1c919b96..4458fd9fc1a 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -39,6 +39,7 @@ struct ata_scsi_args { }; /* libata-core.c */ +extern struct workqueue_struct *ata_aux_wq; extern int atapi_enabled; extern int atapi_dmadir; extern int libata_fua; -- cgit v1.2.3 From a9beec95352ff675f27d74c3cb97dc258d022497 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 31 May 2006 18:27:44 +0900 Subject: [PATCH] libata-hp-prep: make probing related functions global Hotplug will be implemented in libata-eh.c. Make ata_dev_read_id() and ata_dev_configure() global. Signed-off-by: Tejun Heo --- drivers/scsi/libata-core.c | 6 +++--- drivers/scsi/libata.h | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 04921cf2fc0..a9f79b47b4c 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1167,8 +1167,8 @@ unsigned int ata_pio_need_iordy(const struct ata_device *adev) * RETURNS: * 0 on success, -errno otherwise. */ -static int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, - int post_reset, u16 *id) +int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, + int post_reset, u16 *id) { struct ata_port *ap = dev->ap; unsigned int class = *p_class; @@ -1292,7 +1292,7 @@ static void ata_dev_config_ncq(struct ata_device *dev, * RETURNS: * 0 on success, -errno otherwise */ -static int ata_dev_configure(struct ata_device *dev, int print_info) +int ata_dev_configure(struct ata_device *dev, int print_info) { struct ata_port *ap = dev->ap; const u16 *id = dev->id; diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index 4458fd9fc1a..2d704be355c 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -50,6 +50,9 @@ extern void ata_port_flush_task(struct ata_port *ap); extern unsigned ata_exec_internal(struct ata_device *dev, struct ata_taskfile *tf, const u8 *cdb, int dma_dir, void *buf, unsigned int buflen); +extern int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, + int post_reset, u16 *id); +extern int ata_dev_configure(struct ata_device *dev, int print_info); extern int sata_down_spd_limit(struct ata_port *ap); extern int sata_set_spd_needed(struct ata_port *ap); extern int ata_down_xfermask_limit(struct ata_device *dev, int force_pio0); -- cgit v1.2.3 From d7bb4cc7575929a60b0a718daa1bce87bea9a9cc Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 31 May 2006 18:27:46 +0900 Subject: [PATCH] libata-hp-prep: implement sata_phy_debounce() With hotplug, PHY always needs to be debounced before a reset as any reset might find new devices. Extract PHY waiting code from sata_phy_resume() and extend it to include SStatus debouncing. Note that sata_phy_debounce() is superset of what used to be done inside sata_phy_resume(). Three default debounce timing parameters are defined to be used by hot/boot plug. As resume failure during probing will be properly handled as errors, timeout doesn't have to be long as before. probeinit() uses the same timeout to retain the original behavior. Signed-off-by: Tejun Heo --- drivers/scsi/libata-core.c | 107 +++++++++++++++++++++++++++++++++++++++------ include/linux/libata.h | 6 +++ 2 files changed, 99 insertions(+), 14 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index a9f79b47b4c..4823ecefb8a 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -61,6 +61,11 @@ #include "libata.h" +/* debounce timing parameters in msecs { interval, duration, timeout } */ +const unsigned long sata_deb_timing_boot[] = { 5, 100, 2000 }; +const unsigned long sata_deb_timing_eh[] = { 25, 500, 2000 }; +const unsigned long sata_deb_timing_before_fsrst[] = { 100, 2000, 5000 }; + static unsigned int ata_dev_init_params(struct ata_device *dev, u16 heads, u16 sectors); static unsigned int ata_dev_set_xfermode(struct ata_device *dev); @@ -2427,10 +2432,81 @@ err_out: DPRINTK("EXIT\n"); } -static int sata_phy_resume(struct ata_port *ap) +/** + * sata_phy_debounce - debounce SATA phy status + * @ap: ATA port to debounce SATA phy status for + * @params: timing parameters { interval, duratinon, timeout } in msec + * + * Make sure SStatus of @ap reaches stable state, determined by + * holding the same value where DET is not 1 for @duration polled + * every @interval, before @timeout. Timeout constraints the + * beginning of the stable state. Because, after hot unplugging, + * DET gets stuck at 1 on some controllers, this functions waits + * until timeout then returns 0 if DET is stable at 1. + * + * LOCKING: + * Kernel thread context (may sleep) + * + * RETURNS: + * 0 on success, -errno on failure. + */ +int sata_phy_debounce(struct ata_port *ap, const unsigned long *params) { - unsigned long timeout = jiffies + (HZ * 5); - u32 scontrol, sstatus; + unsigned long interval_msec = params[0]; + unsigned long duration = params[1] * HZ / 1000; + unsigned long timeout = jiffies + params[2] * HZ / 1000; + unsigned long last_jiffies; + u32 last, cur; + int rc; + + if ((rc = sata_scr_read(ap, SCR_STATUS, &cur))) + return rc; + cur &= 0xf; + + last = cur; + last_jiffies = jiffies; + + while (1) { + msleep(interval_msec); + if ((rc = sata_scr_read(ap, SCR_STATUS, &cur))) + return rc; + cur &= 0xf; + + /* DET stable? */ + if (cur == last) { + if (cur == 1 && time_before(jiffies, timeout)) + continue; + if (time_after(jiffies, last_jiffies + duration)) + return 0; + continue; + } + + /* unstable, start over */ + last = cur; + last_jiffies = jiffies; + + /* check timeout */ + if (time_after(jiffies, timeout)) + return -EBUSY; + } +} + +/** + * sata_phy_resume - resume SATA phy + * @ap: ATA port to resume SATA phy for + * @params: timing parameters { interval, duratinon, timeout } in msec + * + * Resume SATA phy of @ap and debounce it. + * + * LOCKING: + * Kernel thread context (may sleep) + * + * RETURNS: + * 0 on success, -errno on failure. + */ +int sata_phy_resume(struct ata_port *ap, const unsigned long *params) +{ + u32 scontrol; int rc; if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol))) @@ -2441,16 +2517,12 @@ static int sata_phy_resume(struct ata_port *ap) if ((rc = sata_scr_write(ap, SCR_CONTROL, scontrol))) return rc; - /* Wait for phy to become ready, if necessary. */ - do { - msleep(200); - if ((rc = sata_scr_read(ap, SCR_STATUS, &sstatus))) - return rc; - if ((sstatus & 0xf) != 1) - return 0; - } while (time_before(jiffies, timeout)); + /* Some PHYs react badly if SStatus is pounded immediately + * after resuming. Delay 200ms before debouncing. + */ + msleep(200); - return -EBUSY; + return sata_phy_debounce(ap, params); } /** @@ -2468,8 +2540,10 @@ static int sata_phy_resume(struct ata_port *ap) */ void ata_std_probeinit(struct ata_port *ap) { + static const unsigned long deb_timing[] = { 5, 100, 5000 }; + /* resume link */ - sata_phy_resume(ap); + sata_phy_resume(ap, deb_timing); /* wait for device */ if (ata_port_online(ap)) @@ -2585,7 +2659,7 @@ int sata_std_hardreset(struct ata_port *ap, unsigned int *class) msleep(1); /* bring phy back */ - sata_phy_resume(ap); + sata_phy_resume(ap, sata_deb_timing_eh); /* TODO: phy layer with polling, timeouts, etc. */ if (ata_port_offline(ap)) { @@ -5718,6 +5792,9 @@ u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val, * Do not depend on ABI/API stability. */ +EXPORT_SYMBOL_GPL(sata_deb_timing_boot); +EXPORT_SYMBOL_GPL(sata_deb_timing_eh); +EXPORT_SYMBOL_GPL(sata_deb_timing_before_fsrst); EXPORT_SYMBOL_GPL(ata_std_bios_param); EXPORT_SYMBOL_GPL(ata_std_ports); EXPORT_SYMBOL_GPL(ata_device_add); @@ -5757,6 +5834,8 @@ EXPORT_SYMBOL_GPL(ata_bmdma_error_handler); EXPORT_SYMBOL_GPL(ata_bmdma_post_internal_cmd); EXPORT_SYMBOL_GPL(ata_port_probe); EXPORT_SYMBOL_GPL(sata_set_spd); +EXPORT_SYMBOL_GPL(sata_phy_debounce); +EXPORT_SYMBOL_GPL(sata_phy_resume); EXPORT_SYMBOL_GPL(sata_phy_reset); EXPORT_SYMBOL_GPL(__sata_phy_reset); EXPORT_SYMBOL_GPL(ata_bus_reset); diff --git a/include/linux/libata.h b/include/linux/libata.h index c0513c75275..1c167f728fb 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -607,11 +607,17 @@ struct ata_timing { #define FIT(v,vmin,vmax) max_t(short,min_t(short,v,vmax),vmin) +extern const unsigned long sata_deb_timing_boot[]; +extern const unsigned long sata_deb_timing_eh[]; +extern const unsigned long sata_deb_timing_before_fsrst[]; + extern void ata_port_probe(struct ata_port *); extern void __sata_phy_reset(struct ata_port *ap); extern void sata_phy_reset(struct ata_port *ap); extern void ata_bus_reset(struct ata_port *ap); extern int sata_set_spd(struct ata_port *ap); +extern int sata_phy_debounce(struct ata_port *ap, const unsigned long *param); +extern int sata_phy_resume(struct ata_port *ap, const unsigned long *param); extern int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, ata_reset_fn_t softreset, ata_reset_fn_t hardreset, -- cgit v1.2.3 From f5914a461eb9703773226a0813f6ffcae10c0861 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 31 May 2006 18:27:48 +0900 Subject: [PATCH] libata-hp-prep: add prereset() method and implement ata_std_prereset() With hotplug, every reset might be a probing reset and thus something similar to probe_init() is needed. prereset() method is called before a series of resets to a port and is the counterpart of postreset(). prereset() can tell EH to use different type of reset or skip reset by modifying ehc->i.action. This patch also implements ata_std_prereset(). Most controllers should be able to use this function directly or with some wrapping. After hotplug, different controllers need different actions to resume the PHY and detect the newly attached device. Controllers can be categorized as follows. * Controllers which can wait for the first D2H FIS after hotplug. Note that if the waiting is implemented by polling TF status, there needs to be a way to set BSY on PHY status change. It can be implemented by hardware or with the help of the driver. * Controllers which can wait for the first D2H FIS after sending COMRESET. These controllers need to issue COMRESET to wait for the first FIS. Note that the received D2H FIS could be the first D2H FIS after POR (power-on-reset) or D2H FIS in response to the COMRESET. Some controllers use COMRESET as TF status synchronization point and clear TF automatically (sata_sil). * Controllers which cannot wait for the first D2H FIS reliably. Blindly issuing SRST to spinning-up device often results in command issue failure or timeout, causing extended delay. For these controllers, ata_std_prereset() explicitly waits ATA_SPINUP_WAIT (currently 8s) to give newly attached device time to spin up, then issues reset. Note that failing to getting ready in ATA_SPINUP_WAIT is not critical. libata will retry. So, the timeout needs to be long enough to spin up most devices. LLDDs can tell ata_std_prereset() which of above action is needed with ATA_FLAG_HRST_TO_RESUME and ATA_FLAG_SKIP_D2H_BSY flags. These flags are PHY-specific property and will be moved to ata_link later. While at it, this patch unifies function typedef's such that they all have named arguments. Signed-off-by: Tejun Heo --- drivers/scsi/ahci.c | 3 +- drivers/scsi/libata-bmdma.c | 11 +++--- drivers/scsi/libata-core.c | 85 +++++++++++++++++++++++++++++++++++++++++++++ drivers/scsi/libata-eh.c | 60 +++++++++++++++++++++++++++----- drivers/scsi/sata_sil24.c | 3 +- include/linux/libata.h | 24 +++++++++---- 6 files changed, 165 insertions(+), 21 deletions(-) diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 45fd71d8012..8493b021cc0 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -1026,7 +1026,8 @@ static void ahci_error_handler(struct ata_port *ap) } /* perform recovery */ - ata_do_eh(ap, ahci_softreset, ahci_hardreset, ahci_postreset); + ata_do_eh(ap, ata_std_prereset, ahci_softreset, ahci_hardreset, + ahci_postreset); } static void ahci_post_internal_cmd(struct ata_queued_cmd *qc) diff --git a/drivers/scsi/libata-bmdma.c b/drivers/scsi/libata-bmdma.c index 6d30d2c5296..4bc05371737 100644 --- a/drivers/scsi/libata-bmdma.c +++ b/drivers/scsi/libata-bmdma.c @@ -695,6 +695,7 @@ void ata_bmdma_thaw(struct ata_port *ap) /** * ata_bmdma_drive_eh - Perform EH with given methods for BMDMA controller * @ap: port to handle error for + * @prereset: prereset method (can be NULL) * @softreset: softreset method (can be NULL) * @hardreset: hardreset method (can be NULL) * @postreset: postreset method (can be NULL) @@ -710,8 +711,9 @@ void ata_bmdma_thaw(struct ata_port *ap) * LOCKING: * Kernel thread context (may sleep) */ -void ata_bmdma_drive_eh(struct ata_port *ap, ata_reset_fn_t softreset, - ata_reset_fn_t hardreset, ata_postreset_fn_t postreset) +void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset, + ata_reset_fn_t softreset, ata_reset_fn_t hardreset, + ata_postreset_fn_t postreset) { struct ata_host_set *host_set = ap->host_set; struct ata_eh_context *ehc = &ap->eh_context; @@ -759,7 +761,7 @@ void ata_bmdma_drive_eh(struct ata_port *ap, ata_reset_fn_t softreset, ata_eh_thaw_port(ap); /* PIO and DMA engines have been stopped, perform recovery */ - ata_do_eh(ap, softreset, hardreset, postreset); + ata_do_eh(ap, prereset, softreset, hardreset, postreset); } /** @@ -779,7 +781,8 @@ void ata_bmdma_error_handler(struct ata_port *ap) if (sata_scr_valid(ap)) hardreset = sata_std_hardreset; - ata_bmdma_drive_eh(ap, ata_std_softreset, hardreset, ata_std_postreset); + ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, hardreset, + ata_std_postreset); } /** diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 4823ecefb8a..2531a701d6e 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2525,6 +2525,90 @@ int sata_phy_resume(struct ata_port *ap, const unsigned long *params) return sata_phy_debounce(ap, params); } +static void ata_wait_spinup(struct ata_port *ap) +{ + struct ata_eh_context *ehc = &ap->eh_context; + unsigned long end, secs; + int rc; + + /* first, debounce phy if SATA */ + if (ap->cbl == ATA_CBL_SATA) { + rc = sata_phy_debounce(ap, sata_deb_timing_eh); + + /* if debounced successfully and offline, no need to wait */ + if ((rc == 0 || rc == -EOPNOTSUPP) && ata_port_offline(ap)) + return; + } + + /* okay, let's give the drive time to spin up */ + end = ehc->i.hotplug_timestamp + ATA_SPINUP_WAIT * HZ / 1000; + secs = ((end - jiffies) + HZ - 1) / HZ; + + if (time_after(jiffies, end)) + return; + + if (secs > 5) + ata_port_printk(ap, KERN_INFO, "waiting for device to spin up " + "(%lu secs)\n", secs); + + schedule_timeout_uninterruptible(end - jiffies); +} + +/** + * ata_std_prereset - prepare for reset + * @ap: ATA port to be reset + * + * @ap is about to be reset. Initialize it. + * + * LOCKING: + * Kernel thread context (may sleep) + * + * RETURNS: + * 0 on success, -errno otherwise. + */ +int ata_std_prereset(struct ata_port *ap) +{ + struct ata_eh_context *ehc = &ap->eh_context; + const unsigned long *timing; + int rc; + + /* hotplug? */ + if (ehc->i.flags & ATA_EHI_HOTPLUGGED) { + if (ap->flags & ATA_FLAG_HRST_TO_RESUME) + ehc->i.action |= ATA_EH_HARDRESET; + if (ap->flags & ATA_FLAG_SKIP_D2H_BSY) + ata_wait_spinup(ap); + } + + /* if we're about to do hardreset, nothing more to do */ + if (ehc->i.action & ATA_EH_HARDRESET) + return 0; + + /* if SATA, resume phy */ + if (ap->cbl == ATA_CBL_SATA) { + if (ap->flags & ATA_FLAG_LOADING) + timing = sata_deb_timing_boot; + else + timing = sata_deb_timing_eh; + + rc = sata_phy_resume(ap, timing); + if (rc && rc != -EOPNOTSUPP) { + /* phy resume failed */ + ata_port_printk(ap, KERN_WARNING, "failed to resume " + "link for reset (errno=%d)\n", rc); + return rc; + } + } + + /* Wait for !BSY if the controller can wait for the first D2H + * Reg FIS and we don't know that no device is attached. + */ + if (!(ap->flags & ATA_FLAG_SKIP_D2H_BSY) && !ata_port_offline(ap)) + ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT); + + return 0; +} + /** * ata_std_probeinit - initialize probing * @ap: port to be probed @@ -5840,6 +5924,7 @@ EXPORT_SYMBOL_GPL(sata_phy_reset); EXPORT_SYMBOL_GPL(__sata_phy_reset); EXPORT_SYMBOL_GPL(ata_bus_reset); EXPORT_SYMBOL_GPL(ata_std_probeinit); +EXPORT_SYMBOL_GPL(ata_std_prereset); EXPORT_SYMBOL_GPL(ata_std_softreset); EXPORT_SYMBOL_GPL(sata_std_hardreset); EXPORT_SYMBOL_GPL(ata_std_postreset); diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c index 9173d8f2ce5..0e66f140e53 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/scsi/libata-eh.c @@ -1318,20 +1318,58 @@ static void ata_eh_report(struct ata_port *ap) } } -static int ata_eh_reset(struct ata_port *ap, ata_reset_fn_t softreset, +static int ata_eh_reset(struct ata_port *ap, + ata_prereset_fn_t prereset, ata_reset_fn_t softreset, ata_reset_fn_t hardreset, ata_postreset_fn_t postreset) { struct ata_eh_context *ehc = &ap->eh_context; unsigned int classes[ATA_MAX_DEVICES]; int tries = ATA_EH_RESET_TRIES; + unsigned int action; ata_reset_fn_t reset; int i, rc; + /* Determine which reset to use and record in ehc->i.action. + * prereset() may examine and modify it. + */ + action = ehc->i.action; + ehc->i.action &= ~ATA_EH_RESET_MASK; if (softreset && (!hardreset || (!sata_set_spd_needed(ap) && - !(ehc->i.action & ATA_EH_HARDRESET)))) - reset = softreset; + !(action & ATA_EH_HARDRESET)))) + ehc->i.action |= ATA_EH_SOFTRESET; else + ehc->i.action |= ATA_EH_HARDRESET; + + if (prereset) { + rc = prereset(ap); + if (rc) { + ata_port_printk(ap, KERN_ERR, + "prereset failed (errno=%d)\n", rc); + return rc; + } + } + + /* prereset() might have modified ehc->i.action */ + if (ehc->i.action & ATA_EH_HARDRESET) reset = hardreset; + else if (ehc->i.action & ATA_EH_SOFTRESET) + reset = softreset; + else { + /* prereset told us not to reset, bang classes and return */ + for (i = 0; i < ATA_MAX_DEVICES; i++) + classes[i] = ATA_DEV_NONE; + return 0; + } + + /* did prereset() screw up? if so, fix up to avoid oopsing */ + if (!reset) { + ata_port_printk(ap, KERN_ERR, "BUG: prereset() requested " + "invalid reset type\n"); + if (softreset) + reset = softreset; + else + reset = hardreset; + } retry: ata_port_printk(ap, KERN_INFO, "%s resetting port\n", @@ -1424,6 +1462,7 @@ static int ata_port_nr_enabled(struct ata_port *ap) /** * ata_eh_recover - recover host port after error * @ap: host port to recover + * @prereset: prereset method (can be NULL) * @softreset: softreset method (can be NULL) * @hardreset: hardreset method (can be NULL) * @postreset: postreset method (can be NULL) @@ -1440,8 +1479,8 @@ static int ata_port_nr_enabled(struct ata_port *ap) * RETURNS: * 0 on success, -errno on failure. */ -static int ata_eh_recover(struct ata_port *ap, ata_reset_fn_t softreset, - ata_reset_fn_t hardreset, +static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, + ata_reset_fn_t softreset, ata_reset_fn_t hardreset, ata_postreset_fn_t postreset) { struct ata_eh_context *ehc = &ap->eh_context; @@ -1469,7 +1508,8 @@ static int ata_eh_recover(struct ata_port *ap, ata_reset_fn_t softreset, if (ehc->i.action & ATA_EH_RESET_MASK) { ata_eh_freeze_port(ap); - rc = ata_eh_reset(ap, softreset, hardreset, postreset); + rc = ata_eh_reset(ap, prereset, softreset, hardreset, + postreset); if (rc) { ata_port_printk(ap, KERN_ERR, "reset failed, giving up\n"); @@ -1586,6 +1626,7 @@ static void ata_eh_finish(struct ata_port *ap) /** * ata_do_eh - do standard error handling * @ap: host port to handle error for + * @prereset: prereset method (can be NULL) * @softreset: softreset method (can be NULL) * @hardreset: hardreset method (can be NULL) * @postreset: postreset method (can be NULL) @@ -1595,11 +1636,12 @@ static void ata_eh_finish(struct ata_port *ap) * LOCKING: * Kernel thread context (may sleep). */ -void ata_do_eh(struct ata_port *ap, ata_reset_fn_t softreset, - ata_reset_fn_t hardreset, ata_postreset_fn_t postreset) +void ata_do_eh(struct ata_port *ap, ata_prereset_fn_t prereset, + ata_reset_fn_t softreset, ata_reset_fn_t hardreset, + ata_postreset_fn_t postreset) { ata_eh_autopsy(ap); ata_eh_report(ap); - ata_eh_recover(ap, softreset, hardreset, postreset); + ata_eh_recover(ap, prereset, softreset, hardreset, postreset); ata_eh_finish(ap); } diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 4c76f05d9b6..26d7c54c175 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -912,7 +912,8 @@ static void sil24_error_handler(struct ata_port *ap) } /* perform recovery */ - ata_do_eh(ap, sil24_softreset, sil24_hardreset, ata_std_postreset); + ata_do_eh(ap, ata_std_prereset, sil24_softreset, sil24_hardreset, + ata_std_postreset); } static void sil24_post_internal_cmd(struct ata_queued_cmd *qc) diff --git a/include/linux/libata.h b/include/linux/libata.h index 1c167f728fb..fe5f53943c4 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -262,6 +262,15 @@ enum { ATA_PROBE_MAX_TRIES = 3, ATA_EH_RESET_TRIES = 3, ATA_EH_DEV_TRIES = 3, + + /* Drive spinup time (time from power-on to the first D2H FIS) + * in msecs - 8s currently. Failing to get ready in this time + * isn't critical. It will result in reset failure for + * controllers which can't wait for the first D2H FIS. libata + * will retry, so it just has to be long enough to spin up + * most devices. + */ + ATA_SPINUP_WAIT = 8000, }; enum hsm_task_states { @@ -294,9 +303,10 @@ struct ata_queued_cmd; /* typedefs */ typedef void (*ata_qc_cb_t) (struct ata_queued_cmd *qc); -typedef void (*ata_probeinit_fn_t)(struct ata_port *); -typedef int (*ata_reset_fn_t)(struct ata_port *, unsigned int *); -typedef void (*ata_postreset_fn_t)(struct ata_port *ap, unsigned int *); +typedef void (*ata_probeinit_fn_t)(struct ata_port *ap); +typedef int (*ata_prereset_fn_t)(struct ata_port *ap); +typedef int (*ata_reset_fn_t)(struct ata_port *ap, unsigned int *classes); +typedef void (*ata_postreset_fn_t)(struct ata_port *ap, unsigned int *classes); struct ata_ioports { unsigned long cmd_addr; @@ -623,6 +633,7 @@ extern int ata_drive_probe_reset(struct ata_port *ap, ata_reset_fn_t softreset, ata_reset_fn_t hardreset, ata_postreset_fn_t postreset, unsigned int *classes); extern void ata_std_probeinit(struct ata_port *ap); +extern int ata_std_prereset(struct ata_port *ap); extern int ata_std_softreset(struct ata_port *ap, unsigned int *classes); extern int sata_std_hardreset(struct ata_port *ap, unsigned int *class); extern void ata_std_postreset(struct ata_port *ap, unsigned int *classes); @@ -706,7 +717,7 @@ extern u8 ata_bmdma_status(struct ata_port *ap); extern void ata_bmdma_irq_clear(struct ata_port *ap); extern void ata_bmdma_freeze(struct ata_port *ap); extern void ata_bmdma_thaw(struct ata_port *ap); -extern void ata_bmdma_drive_eh(struct ata_port *ap, +extern void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset, ata_reset_fn_t softreset, ata_reset_fn_t hardreset, ata_postreset_fn_t postreset); @@ -784,8 +795,9 @@ extern void ata_eh_thaw_port(struct ata_port *ap); extern void ata_eh_qc_complete(struct ata_queued_cmd *qc); extern void ata_eh_qc_retry(struct ata_queued_cmd *qc); -extern void ata_do_eh(struct ata_port *ap, ata_reset_fn_t softreset, - ata_reset_fn_t hardreset, ata_postreset_fn_t postreset); +extern void ata_do_eh(struct ata_port *ap, ata_prereset_fn_t prereset, + ata_reset_fn_t softreset, ata_reset_fn_t hardreset, + ata_postreset_fn_t postreset); /* * printk helpers -- cgit v1.2.3 From 664faf09a05d74085c0b31e2c621d7647322325b Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 31 May 2006 18:27:50 +0900 Subject: [PATCH] libata-hp-prep: implement followup softreset handling In some cases, hardreset must be followed by SRST. * some controllers can't classify with hardreset * some controllers can't wait for !BSY after hardreset (LLDD should explicitly request followup softreset by returning -EAGAIN) * (later) PM needs SRST w/ PMP==15 to operate after hardreset To handle above cases, this patch implements follow-up softreset. After a hardreset, ata_eh_reset() checks whether any of above conditions are met and do a follow-up softreset if necessary. Signed-off-by: Tejun Heo --- drivers/scsi/libata-eh.c | 58 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 52 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c index 0e66f140e53..8ecb8424d7b 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/scsi/libata-eh.c @@ -1318,16 +1318,28 @@ static void ata_eh_report(struct ata_port *ap) } } -static int ata_eh_reset(struct ata_port *ap, +static int ata_eh_followup_srst_needed(int rc, int classify, + const unsigned int *classes) +{ + if (rc == -EAGAIN) + return 1; + if (rc != 0) + return 0; + if (classify && classes[0] == ATA_DEV_UNKNOWN) + return 1; + return 0; +} + +static int ata_eh_reset(struct ata_port *ap, int classify, ata_prereset_fn_t prereset, ata_reset_fn_t softreset, ata_reset_fn_t hardreset, ata_postreset_fn_t postreset) { struct ata_eh_context *ehc = &ap->eh_context; - unsigned int classes[ATA_MAX_DEVICES]; + unsigned int *classes = ehc->classes; int tries = ATA_EH_RESET_TRIES; unsigned int action; ata_reset_fn_t reset; - int i, rc; + int i, did_followup_srst, rc; /* Determine which reset to use and record in ehc->i.action. * prereset() may examine and modify it. @@ -1381,10 +1393,44 @@ static int ata_eh_reset(struct ata_port *ap, rc = ata_do_reset(ap, reset, classes); + did_followup_srst = 0; + if (reset == hardreset && + ata_eh_followup_srst_needed(rc, classify, classes)) { + /* okay, let's do follow-up softreset */ + did_followup_srst = 1; + reset = softreset; + + if (!reset) { + ata_port_printk(ap, KERN_ERR, + "follow-up softreset required " + "but no softreset avaliable\n"); + return -EINVAL; + } + + ata_eh_about_to_do(ap, ATA_EH_RESET_MASK); + rc = ata_do_reset(ap, reset, classes); + + if (rc == 0 && classify && + classes[0] == ATA_DEV_UNKNOWN) { + ata_port_printk(ap, KERN_ERR, + "classification failed\n"); + return -EINVAL; + } + } + if (rc && --tries) { + const char *type; + + if (reset == softreset) { + if (did_followup_srst) + type = "follow-up soft"; + else + type = "soft"; + } else + type = "hard"; + ata_port_printk(ap, KERN_WARNING, - "%sreset failed, retrying in 5 secs\n", - reset == softreset ? "soft" : "hard"); + "%sreset failed, retrying in 5 secs\n", type); ssleep(5); if (reset == hardreset) @@ -1508,7 +1554,7 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, if (ehc->i.action & ATA_EH_RESET_MASK) { ata_eh_freeze_port(ap); - rc = ata_eh_reset(ap, prereset, softreset, hardreset, + rc = ata_eh_reset(ap, 0, prereset, softreset, hardreset, postreset); if (rc) { ata_port_printk(ap, KERN_ERR, -- cgit v1.2.3 From 9a1004d0c11be41c83d06a67dfe74567a41ae582 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 31 May 2006 18:27:52 +0900 Subject: [PATCH] libata: export ata_hsm_move() ata_hsm_move() will be used by LLDDs which depend on standard PIO HSM but implement their own interrupt handlers. Signed-off-by: Tejun Heo --- drivers/scsi/libata-core.c | 6 +++--- include/linux/libata.h | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 2531a701d6e..c965eea3b3d 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -4140,9 +4140,8 @@ static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq) * RETURNS: * 1 when poll next status needed, 0 otherwise. */ - -static int ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc, - u8 status, int in_wq) +int ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc, + u8 status, int in_wq) { unsigned long flags = 0; int poll_next; @@ -5885,6 +5884,7 @@ EXPORT_SYMBOL_GPL(ata_device_add); EXPORT_SYMBOL_GPL(ata_host_set_remove); EXPORT_SYMBOL_GPL(ata_sg_init); EXPORT_SYMBOL_GPL(ata_sg_init_one); +EXPORT_SYMBOL_GPL(ata_hsm_move); EXPORT_SYMBOL_GPL(ata_qc_complete); EXPORT_SYMBOL_GPL(ata_qc_complete_multiple); EXPORT_SYMBOL_GPL(ata_qc_issue_prot); diff --git a/include/linux/libata.h b/include/linux/libata.h index fe5f53943c4..a1ceb5b67b9 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -723,6 +723,8 @@ extern void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset, ata_postreset_fn_t postreset); extern void ata_bmdma_error_handler(struct ata_port *ap); extern void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc); +extern int ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc, + u8 status, int in_wq); extern void ata_qc_complete(struct ata_queued_cmd *qc); extern int ata_qc_complete_multiple(struct ata_port *ap, u32 qc_active, void (*finish_qc)(struct ata_queued_cmd *)); -- cgit v1.2.3 From 20888d83687d5cb374cdb5b0afa746ab79666f4e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 31 May 2006 18:27:53 +0900 Subject: [PATCH] sata_sil: add new constants in preparation for new interrupt handler sata_sil is about to get a brand new interrupt handler. Add relevant constants. Signed-off-by: Tejun Heo --- drivers/scsi/sata_sil.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index 3bd80773869..f926883fd16 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -54,6 +54,7 @@ enum { */ SIL_FLAG_RERR_ON_DMA_ACT = (1 << 29), SIL_FLAG_MOD15WRITE = (1 << 30), + SIL_DFL_HOST_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO, @@ -84,6 +85,20 @@ enum { /* BMDMA/BMDMA2 */ SIL_INTR_STEERING = (1 << 1), + SIL_DMA_ENABLE = (1 << 0), /* DMA run switch */ + SIL_DMA_RDWR = (1 << 3), /* DMA Rd-Wr */ + SIL_DMA_SATA_IRQ = (1 << 4), /* OR of all SATA IRQs */ + SIL_DMA_ACTIVE = (1 << 16), /* DMA running */ + SIL_DMA_ERROR = (1 << 17), /* PCI bus error */ + SIL_DMA_COMPLETE = (1 << 18), /* cmd complete / IRQ pending */ + SIL_DMA_N_SATA_IRQ = (1 << 6), /* SATA_IRQ for the next channel */ + SIL_DMA_N_ACTIVE = (1 << 24), /* ACTIVE for the next channel */ + SIL_DMA_N_ERROR = (1 << 25), /* ERROR for the next channel */ + SIL_DMA_N_COMPLETE = (1 << 26), /* COMPLETE for the next channel */ + + /* SIEN */ + SIL_SIEN_N = (1 << 16), /* triggered by SError.N */ + /* * Others */ @@ -226,6 +241,7 @@ static const struct { unsigned long tf; /* ATA taskfile register block */ unsigned long ctl; /* ATA control/altstatus register block */ unsigned long bmdma; /* DMA register block */ + unsigned long bmdma2; /* DMA register block #2 */ unsigned long fifo_cfg; /* FIFO Valid Byte Count and Control */ unsigned long scr; /* SATA control register block */ unsigned long sien; /* SATA Interrupt Enable register */ @@ -233,10 +249,10 @@ static const struct { unsigned long sfis_cfg; /* SATA FIS reception config register */ } sil_port[] = { /* port 0 ... */ - { 0x80, 0x8A, 0x00, 0x40, 0x100, 0x148, 0xb4, 0x14c }, - { 0xC0, 0xCA, 0x08, 0x44, 0x180, 0x1c8, 0xf4, 0x1cc }, - { 0x280, 0x28A, 0x200, 0x240, 0x300, 0x348, 0x2b4, 0x34c }, - { 0x2C0, 0x2CA, 0x208, 0x244, 0x380, 0x3c8, 0x2f4, 0x3cc }, + { 0x80, 0x8A, 0x00, 0x10, 0x40, 0x100, 0x148, 0xb4, 0x14c }, + { 0xC0, 0xCA, 0x08, 0x18, 0x44, 0x180, 0x1c8, 0xf4, 0x1cc }, + { 0x280, 0x28A, 0x200, 0x210, 0x240, 0x300, 0x348, 0x2b4, 0x34c }, + { 0x2C0, 0x2CA, 0x208, 0x218, 0x244, 0x380, 0x3c8, 0x2f4, 0x3cc }, /* ... port 3 */ }; -- cgit v1.2.3 From cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0ba Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 31 May 2006 18:27:55 +0900 Subject: [PATCH] sata_sil: new interrupt handler The DMA complete bit of these controllers reflects ATA IRQ status while no DMA command is in progress. So, we can tell whether the controller is raising an interrupt or not in deterministic manner. This patch gives sata_sil its own interrupt handler which behaves much better than the original one in terms of error detection and handling. This change is also necessary for later hotplug support. Further improvements are possible, in both 2 and 4 ports versions, we can get all status with only one readl and using custom bmdma operations can further cut down register accesses. Signed-off-by: Tejun Heo --- drivers/scsi/sata_sil.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 91 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index f926883fd16..03c1d1b1a04 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -111,6 +111,8 @@ static void sil_dev_config(struct ata_port *ap, struct ata_device *dev); static u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg); static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); static void sil_post_set_mode (struct ata_port *ap); +static irqreturn_t sil_interrupt(int irq, void *dev_instance, + struct pt_regs *regs); static void sil_freeze(struct ata_port *ap); static void sil_thaw(struct ata_port *ap); @@ -196,7 +198,7 @@ static const struct ata_port_operations sil_ops = { .thaw = sil_thaw, .error_handler = ata_bmdma_error_handler, .post_internal_cmd = ata_bmdma_post_internal_cmd, - .irq_handler = ata_interrupt, + .irq_handler = sil_interrupt, .irq_clear = ata_bmdma_irq_clear, .scr_read = sil_scr_read, .scr_write = sil_scr_write, @@ -336,6 +338,94 @@ static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val) writel(val, mmio); } +static void sil_host_intr(struct ata_port *ap, u32 bmdma2) +{ + struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag); + u8 status; + + if (unlikely(!qc || qc->tf.ctl & ATA_NIEN)) + goto freeze; + + /* Check whether we are expecting interrupt in this state */ + switch (ap->hsm_task_state) { + case HSM_ST_FIRST: + /* Some pre-ATAPI-4 devices assert INTRQ + * at this state when ready to receive CDB. + */ + + /* Check the ATA_DFLAG_CDB_INTR flag is enough here. + * The flag was turned on only for atapi devices. + * No need to check is_atapi_taskfile(&qc->tf) again. + */ + if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) + goto err_hsm; + break; + case HSM_ST_LAST: + if (qc->tf.protocol == ATA_PROT_DMA || + qc->tf.protocol == ATA_PROT_ATAPI_DMA) { + /* clear DMA-Start bit */ + ap->ops->bmdma_stop(qc); + + if (bmdma2 & SIL_DMA_ERROR) { + qc->err_mask |= AC_ERR_HOST_BUS; + ap->hsm_task_state = HSM_ST_ERR; + } + } + break; + case HSM_ST: + break; + default: + goto err_hsm; + } + + /* check main status, clearing INTRQ */ + status = ata_chk_status(ap); + if (unlikely(status & ATA_BUSY)) + goto err_hsm; + + /* ack bmdma irq events */ + ata_bmdma_irq_clear(ap); + + /* kick HSM in the ass */ + ata_hsm_move(ap, qc, status, 0); + + return; + + err_hsm: + qc->err_mask |= AC_ERR_HSM; + freeze: + ata_port_freeze(ap); +} + +static irqreturn_t sil_interrupt(int irq, void *dev_instance, + struct pt_regs *regs) +{ + struct ata_host_set *host_set = dev_instance; + void __iomem *mmio_base = host_set->mmio_base; + int handled = 0; + int i; + + spin_lock(&host_set->lock); + + for (i = 0; i < host_set->n_ports; i++) { + struct ata_port *ap = host_set->ports[i]; + u32 bmdma2 = readl(mmio_base + sil_port[ap->port_no].bmdma2); + + if (unlikely(!ap || ap->flags & ATA_FLAG_DISABLED)) + continue; + + if (!(bmdma2 & SIL_DMA_COMPLETE)) + continue; + + sil_host_intr(ap, bmdma2); + handled = 1; + } + + spin_unlock(&host_set->lock); + + return IRQ_RETVAL(handled); +} + static void sil_freeze(struct ata_port *ap) { void __iomem *mmio_base = ap->host_set->mmio_base; -- cgit v1.2.3 From 135da34573f6d3bab2976a75063f7232a4311a74 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 31 May 2006 18:27:57 +0900 Subject: [PATCH] sata_sil24: rename PORT_PRB to PORT_LRAM and add PORT_LRAM_SLOT_SZ PORT_PRB is a misnomer as the area also contains other stuff. Rename it to PORT_LRAM and add PORT_LRAM_SLOT_SZ. Signed-off-by: Tejun Heo --- drivers/scsi/sata_sil24.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 26d7c54c175..a39e8d0332c 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -98,7 +98,9 @@ enum { * (8192 bytes @ +0x0000, +0x2000, +0x4000 and +0x6000 @ BAR2) */ PORT_REGS_SIZE = 0x2000, - PORT_PRB = 0x0000, /* (32 bytes PRB + 16 bytes SGEs * 6) * 31 (3968 bytes) */ + + PORT_LRAM = 0x0000, /* 31 LRAM slots and PM regs */ + PORT_LRAM_SLOT_SZ = 0x0080, /* 32 bytes PRB + 2 SGE, ACT... */ PORT_PM = 0x0f80, /* 8 bytes PM * 16 (128 bytes) */ /* 32 bit regs */ @@ -1103,7 +1105,7 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) void __iomem *port = port_base + i * PORT_REGS_SIZE; unsigned long portu = (unsigned long)port; - probe_ent->port[i].cmd_addr = portu + PORT_PRB; + probe_ent->port[i].cmd_addr = portu; probe_ent->port[i].scr_addr = portu + PORT_SCONTROL; ata_std_ports(&probe_ent->port[i]); -- cgit v1.2.3 From e8e008e7b5ed8c65675cc9b3e778b8bb909f65ab Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 31 May 2006 18:27:59 +0900 Subject: [PATCH] sata_sil24: update sil24_hardreset() Use phy debouncing instead of unconditional wait after DEV_RST and make sil24_hardreset() to request followup SRST as that's the only way to wait for !BSY. Note that the original implementation never worked - if the cached status was !BSY, ata_busy_sleep() finished immediately; otherwise, it timed out regardless of the actual device status. Signed-off-by: Tejun Heo --- drivers/scsi/sata_sil24.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index a39e8d0332c..4a830903393 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -591,7 +591,7 @@ static int sil24_hardreset(struct ata_port *ap, unsigned int *class) { void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; const char *reason; - int tout_msec; + int tout_msec, rc; u32 tmp; /* sil24 does the right thing(tm) without any protection */ @@ -605,10 +605,14 @@ static int sil24_hardreset(struct ata_port *ap, unsigned int *class) tmp = ata_wait_register(port + PORT_CTRL_STAT, PORT_CS_DEV_RST, PORT_CS_DEV_RST, 10, tout_msec); - /* SStatus oscillates between zero and valid status for short - * duration after DEV_RST, give it time to settle. + /* SStatus oscillates between zero and valid status after + * DEV_RST, debounce it. */ - msleep(100); + rc = sata_phy_debounce(ap, sata_deb_timing_before_fsrst); + if (rc) { + reason = "PHY debouncing failed"; + goto err; + } if (tmp & PORT_CS_DEV_RST) { if (ata_port_offline(ap)) @@ -617,15 +621,13 @@ static int sil24_hardreset(struct ata_port *ap, unsigned int *class) goto err; } - if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) { - reason = "device not ready"; - goto err; - } - - /* sil24 doesn't report device class code after hardreset, - * leave *class alone. + /* Sil24 doesn't store signature FIS after hardreset, so we + * can't wait for BSY to clear. Some devices take a long time + * to get ready and those devices will choke if we don't wait + * for BSY clearance here. Tell libata to perform follow-up + * softreset. */ - return 0; + return -EAGAIN; err: ata_port_printk(ap, KERN_ERR, "hardreset failed (%s)\n", reason); -- cgit v1.2.3 From 0ea035a3d1ad948096e205f08f350c03d5cea453 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 31 May 2006 18:28:01 +0900 Subject: [PATCH] libata-hp: implement ata_eh_detach_dev() Implement ata_eh_detach_dev(). This function is responsible for detaching an ATA device and offlining the associated SCSI device atomically so that the detached device is not accessed after ATA detach is complete. Signed-off-by: Tejun Heo --- drivers/scsi/libata-eh.c | 28 ++++++++++++++++++++++++++++ drivers/scsi/libata-scsi.c | 24 ++++++++++++++++++++++++ drivers/scsi/libata.h | 1 + 3 files changed, 53 insertions(+) diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c index 8ecb8424d7b..a049bffdf77 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/scsi/libata-eh.c @@ -666,6 +666,34 @@ void ata_eh_qc_retry(struct ata_queued_cmd *qc) __ata_eh_qc_complete(qc); } +/** + * ata_eh_detach_dev - detach ATA device + * @dev: ATA device to detach + * + * Detach @dev. + * + * LOCKING: + * None. + */ +static void ata_eh_detach_dev(struct ata_device *dev) +{ + struct ata_port *ap = dev->ap; + unsigned long flags; + + ata_dev_disable(dev); + + spin_lock_irqsave(&ap->host_set->lock, flags); + + dev->flags &= ~ATA_DFLAG_DETACH; + + if (ata_scsi_offline_dev(dev)) { + dev->flags |= ATA_DFLAG_DETACHED; + ap->flags |= ATA_FLAG_SCSI_HOTPLUG; + } + + spin_unlock_irqrestore(&ap->host_set->lock, flags); +} + /** * ata_eh_about_to_do - about to perform eh_action * @ap: target ATA port diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index da9689b7082..3dc6188af0e 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -2762,3 +2762,27 @@ void ata_scsi_scan_host(struct ata_port *ap) } } } + +/** + * ata_scsi_offline_dev - offline attached SCSI device + * @dev: ATA device to offline attached SCSI device for + * + * This function is called from ata_eh_hotplug() and responsible + * for taking the SCSI device attached to @dev offline. This + * function is called with host_set lock which protects dev->sdev + * against clearing. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + * + * RETURNS: + * 1 if attached SCSI device exists, 0 otherwise. + */ +int ata_scsi_offline_dev(struct ata_device *dev) +{ + if (dev->sdev) { + scsi_device_set_state(dev->sdev, SDEV_OFFLINE); + return 1; + } + return 0; +} diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index 2d704be355c..e38759fdc18 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -75,6 +75,7 @@ extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg); extern struct scsi_transport_template ata_scsi_transport_template; extern void ata_scsi_scan_host(struct ata_port *ap); +extern int ata_scsi_offline_dev(struct ata_device *dev); extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf, unsigned int buflen); -- cgit v1.2.3 From 084fe639b81c4d418a2cf714acb0475e3713cb73 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 31 May 2006 18:28:03 +0900 Subject: [PATCH] libata-hp: implement hotplug Implement ATA part of hotplug. To avoid probing broken devices over and over again, disabled devices are not automatically detached. They are detached only if probing is requested for the device or the associated port is offline. Also, to avoid infinite probing loop, Each device is probed only once per EH run. As SATA PHY status is fragile, devices are detached only after it has used up its recovery chances unless explicitly requested by LLDD or user (LLDD may request direct detach if, for example, it supports cold presence detection). Signed-off-by: Tejun Heo --- drivers/scsi/libata-eh.c | 123 +++++++++++++++++++++++++++++++++++++++-------- include/linux/libata.h | 13 +++++ 2 files changed, 115 insertions(+), 21 deletions(-) diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c index a049bffdf77..b53e2e7db49 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/scsi/libata-eh.c @@ -932,10 +932,8 @@ static void ata_eh_analyze_serror(struct ata_port *ap) err_mask |= AC_ERR_SYSTEM; action |= ATA_EH_SOFTRESET; } - if (serror & (SERR_PHYRDY_CHG | SERR_DEV_XCHG)) { - err_mask |= AC_ERR_ATA_BUS; - action |= ATA_EH_HARDRESET; - } + if (serror & (SERR_PHYRDY_CHG | SERR_DEV_XCHG)) + ata_ehi_hotplugged(&ehc->i); ehc->i.err_mask |= err_mask; ehc->i.action |= action; @@ -1487,11 +1485,12 @@ static int ata_eh_reset(struct ata_port *ap, int classify, return rc; } -static int ata_eh_revalidate(struct ata_port *ap, - struct ata_device **r_failed_dev) +static int ata_eh_revalidate_and_attach(struct ata_port *ap, + struct ata_device **r_failed_dev) { struct ata_eh_context *ehc = &ap->eh_context; struct ata_device *dev; + unsigned long flags; int i, rc = 0; DPRINTK("ENTER\n"); @@ -1513,6 +1512,23 @@ static int ata_eh_revalidate(struct ata_port *ap, break; ehc->i.action &= ~ATA_EH_REVALIDATE; + } else if (dev->class == ATA_DEV_UNKNOWN && + ehc->tries[dev->devno] && + ata_class_enabled(ehc->classes[dev->devno])) { + dev->class = ehc->classes[dev->devno]; + + rc = ata_dev_read_id(dev, &dev->class, 1, dev->id); + if (rc == 0) + rc = ata_dev_configure(dev, 1); + + if (rc) { + dev->class = ATA_DEV_UNKNOWN; + break; + } + + spin_lock_irqsave(&ap->host_set->lock, flags); + ap->flags |= ATA_FLAG_SCSI_HOTPLUG; + spin_unlock_irqrestore(&ap->host_set->lock, flags); } } @@ -1533,6 +1549,36 @@ static int ata_port_nr_enabled(struct ata_port *ap) return cnt; } +static int ata_port_nr_vacant(struct ata_port *ap) +{ + int i, cnt = 0; + + for (i = 0; i < ATA_MAX_DEVICES; i++) + if (ap->device[i].class == ATA_DEV_UNKNOWN) + cnt++; + return cnt; +} + +static int ata_eh_skip_recovery(struct ata_port *ap) +{ + struct ata_eh_context *ehc = &ap->eh_context; + int i; + + if (ap->flags & ATA_FLAG_FROZEN || ata_port_nr_enabled(ap)) + return 0; + + /* skip if class codes for all vacant slots are ATA_DEV_NONE */ + for (i = 0; i < ATA_MAX_DEVICES; i++) { + struct ata_device *dev = &ap->device[i]; + + if (dev->class == ATA_DEV_UNKNOWN && + ehc->classes[dev->devno] != ATA_DEV_NONE) + return 0; + } + + return 1; +} + /** * ata_eh_recover - recover host port after error * @ap: host port to recover @@ -1543,9 +1589,10 @@ static int ata_port_nr_enabled(struct ata_port *ap) * * This is the alpha and omega, eum and yang, heart and soul of * libata exception handling. On entry, actions required to - * recover each devices are recorded in eh_context. This - * function executes all the operations with appropriate retrials - * and fallbacks to resurrect failed devices. + * recover the port and hotplug requests are recorded in + * eh_context. This function executes all the operations with + * appropriate retrials and fallbacks to resurrect failed + * devices, detach goners and greet newcomers. * * LOCKING: * Kernel thread context (may sleep). @@ -1568,6 +1615,19 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, dev = &ap->device[i]; ehc->tries[dev->devno] = ATA_EH_DEV_TRIES; + + /* process hotplug request */ + if (dev->flags & ATA_DFLAG_DETACH) + ata_eh_detach_dev(dev); + + if (!ata_dev_enabled(dev) && + ((ehc->i.probe_mask & (1 << dev->devno)) && + !(ehc->did_probe_mask & (1 << dev->devno)))) { + ata_eh_detach_dev(dev); + ata_dev_init(dev); + ehc->did_probe_mask |= (1 << dev->devno); + ehc->i.action |= ATA_EH_SOFTRESET; + } } retry: @@ -1575,15 +1635,18 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, rc = 0; /* skip EH if possible. */ - if (!ata_port_nr_enabled(ap) && !(ap->flags & ATA_FLAG_FROZEN)) + if (ata_eh_skip_recovery(ap)) ehc->i.action = 0; + for (i = 0; i < ATA_MAX_DEVICES; i++) + ehc->classes[i] = ATA_DEV_UNKNOWN; + /* reset */ if (ehc->i.action & ATA_EH_RESET_MASK) { ata_eh_freeze_port(ap); - rc = ata_eh_reset(ap, 0, prereset, softreset, hardreset, - postreset); + rc = ata_eh_reset(ap, ata_port_nr_vacant(ap), prereset, + softreset, hardreset, postreset); if (rc) { ata_port_printk(ap, KERN_ERR, "reset failed, giving up\n"); @@ -1593,8 +1656,8 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, ata_eh_thaw_port(ap); } - /* revalidate existing devices */ - rc = ata_eh_revalidate(ap, &dev); + /* revalidate existing devices and attach new ones */ + rc = ata_eh_revalidate_and_attach(ap, &dev); if (rc) goto dev_fail; @@ -1612,6 +1675,8 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, dev_fail: switch (rc) { case -ENODEV: + /* device missing, schedule probing */ + ehc->i.probe_mask |= (1 << dev->devno); case -EINVAL: ehc->tries[dev->devno] = 0; break; @@ -1624,15 +1689,31 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, ehc->tries[dev->devno] = 0; } - /* disable device if it has used up all its chances */ - if (ata_dev_enabled(dev) && !ehc->tries[dev->devno]) + if (ata_dev_enabled(dev) && !ehc->tries[dev->devno]) { + /* disable device if it has used up all its chances */ ata_dev_disable(dev); - /* soft didn't work? be haaaaard */ - if (ehc->i.flags & ATA_EHI_DID_RESET) - ehc->i.action |= ATA_EH_HARDRESET; - else - ehc->i.action |= ATA_EH_SOFTRESET; + /* detach if offline */ + if (ata_port_offline(ap)) + ata_eh_detach_dev(dev); + + /* probe if requested */ + if ((ehc->i.probe_mask & (1 << dev->devno)) && + !(ehc->did_probe_mask & (1 << dev->devno))) { + ata_eh_detach_dev(dev); + ata_dev_init(dev); + + ehc->tries[dev->devno] = ATA_EH_DEV_TRIES; + ehc->did_probe_mask |= (1 << dev->devno); + ehc->i.action |= ATA_EH_SOFTRESET; + } + } else { + /* soft didn't work? be haaaaard */ + if (ehc->i.flags & ATA_EHI_DID_RESET) + ehc->i.action |= ATA_EH_HARDRESET; + else + ehc->i.action |= ATA_EH_SOFTRESET; + } if (ata_port_nr_enabled(ap)) { ata_port_printk(ap, KERN_WARNING, "failed to recover some " diff --git a/include/linux/libata.h b/include/linux/libata.h index a1ceb5b67b9..56971943d26 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -824,6 +824,19 @@ extern void ata_do_eh(struct ata_port *ap, ata_prereset_fn_t prereset, (ehi)->desc_len = 0; \ } while (0) +static inline void ata_ehi_hotplugged(struct ata_eh_info *ehi) +{ + if (ehi->flags & ATA_EHI_HOTPLUGGED) + return; + + ehi->flags |= ATA_EHI_HOTPLUGGED; + ehi->hotplug_timestamp = jiffies; + + ehi->err_mask |= AC_ERR_ATA_BUS; + ehi->action |= ATA_EH_SOFTRESET; + ehi->probe_mask |= (1 << ATA_MAX_DEVICES) - 1; +} + /* * qc helpers */ -- cgit v1.2.3 From 580b2102327ab8444af5bde4e70b50d268a1d558 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 31 May 2006 18:28:05 +0900 Subject: [PATCH] libata-hp: implement SCSI part of hotplug Implement SCSI part of hotplug. This must be done in a separate context as SCSI makes use of EH during probing. SCSI scan fails silently if EH is in progress. In such cases, libata pauses briefly and retries until every device is attached. Signed-off-by: Tejun Heo --- drivers/scsi/libata-core.c | 1 + drivers/scsi/libata-eh.c | 6 ++- drivers/scsi/libata-scsi.c | 116 +++++++++++++++++++++++++++++++++++++++++++++ drivers/scsi/libata.h | 1 + include/linux/libata.h | 2 +- 5 files changed, 124 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index c965eea3b3d..8df8ecc51a7 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -5370,6 +5370,7 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host, ap->msg_enable = ATA_MSG_DRV; INIT_WORK(&ap->port_task, NULL, NULL); + INIT_WORK(&ap->hotplug_task, ata_scsi_hotplug, ap); INIT_LIST_HEAD(&ap->eh_done_q); init_waitqueue_head(&ap->eh_wait_q); diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c index b53e2e7db49..733dfa53297 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/scsi/libata-eh.c @@ -287,9 +287,13 @@ void ata_scsi_error(struct Scsi_Host *host) /* clean up */ spin_lock_irqsave(hs_lock, flags); + if (ap->flags & ATA_FLAG_SCSI_HOTPLUG) + queue_work(ata_aux_wq, &ap->hotplug_task); + if (ap->flags & ATA_FLAG_RECOVERED) ata_port_printk(ap, KERN_INFO, "EH complete\n"); - ap->flags &= ~ATA_FLAG_RECOVERED; + + ap->flags &= ~(ATA_FLAG_SCSI_HOTPLUG | ATA_FLAG_RECOVERED); /* tell wait_eh that we're done */ ap->flags &= ~ATA_FLAG_EH_IN_PROGRESS; diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 3dc6188af0e..12563998d97 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -2786,3 +2786,119 @@ int ata_scsi_offline_dev(struct ata_device *dev) } return 0; } + +/** + * ata_scsi_remove_dev - remove attached SCSI device + * @dev: ATA device to remove attached SCSI device for + * + * This function is called from ata_eh_scsi_hotplug() and + * responsible for removing the SCSI device attached to @dev. + * + * LOCKING: + * Kernel thread context (may sleep). + */ +static void ata_scsi_remove_dev(struct ata_device *dev) +{ + struct ata_port *ap = dev->ap; + struct scsi_device *sdev; + unsigned long flags; + + /* Alas, we need to grab scan_mutex to ensure SCSI device + * state doesn't change underneath us and thus + * scsi_device_get() always succeeds. The mutex locking can + * be removed if there is __scsi_device_get() interface which + * increments reference counts regardless of device state. + */ + mutex_lock(&ap->host->scan_mutex); + spin_lock_irqsave(&ap->host_set->lock, flags); + + /* clearing dev->sdev is protected by host_set lock */ + sdev = dev->sdev; + dev->sdev = NULL; + + if (sdev) { + /* If user initiated unplug races with us, sdev can go + * away underneath us after the host_set lock and + * scan_mutex are released. Hold onto it. + */ + if (scsi_device_get(sdev) == 0) { + /* The following ensures the attached sdev is + * offline on return from ata_scsi_offline_dev() + * regardless it wins or loses the race + * against this function. + */ + scsi_device_set_state(sdev, SDEV_OFFLINE); + } else { + WARN_ON(1); + sdev = NULL; + } + } + + spin_unlock_irqrestore(&ap->host_set->lock, flags); + mutex_unlock(&ap->host->scan_mutex); + + if (sdev) { + ata_dev_printk(dev, KERN_INFO, "detaching (SCSI %s)\n", + sdev->sdev_gendev.bus_id); + + scsi_remove_device(sdev); + scsi_device_put(sdev); + } +} + +/** + * ata_scsi_hotplug - SCSI part of hotplug + * @data: Pointer to ATA port to perform SCSI hotplug on + * + * Perform SCSI part of hotplug. It's executed from a separate + * workqueue after EH completes. This is necessary because SCSI + * hot plugging requires working EH and hot unplugging is + * synchronized with hot plugging with a mutex. + * + * LOCKING: + * Kernel thread context (may sleep). + */ +void ata_scsi_hotplug(void *data) +{ + struct ata_port *ap = data; + int i; + + if (ap->flags & ATA_FLAG_UNLOADING) { + DPRINTK("ENTER/EXIT - unloading\n"); + return; + } + + DPRINTK("ENTER\n"); + + /* unplug detached devices */ + for (i = 0; i < ATA_MAX_DEVICES; i++) { + struct ata_device *dev = &ap->device[i]; + unsigned long flags; + + if (!(dev->flags & ATA_DFLAG_DETACHED)) + continue; + + spin_lock_irqsave(&ap->host_set->lock, flags); + dev->flags &= ~ATA_DFLAG_DETACHED; + spin_unlock_irqrestore(&ap->host_set->lock, flags); + + ata_scsi_remove_dev(dev); + } + + /* scan for new ones */ + ata_scsi_scan_host(ap); + + /* If we scanned while EH was in progress, scan would have + * failed silently. Requeue if there are enabled but + * unattached devices. + */ + for (i = 0; i < ATA_MAX_DEVICES; i++) { + struct ata_device *dev = &ap->device[i]; + if (ata_dev_enabled(dev) && !dev->sdev) { + queue_delayed_work(ata_aux_wq, &ap->hotplug_task, HZ); + break; + } + } + + DPRINTK("EXIT\n"); +} diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index e38759fdc18..0586b0cd73f 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -76,6 +76,7 @@ extern struct scsi_transport_template ata_scsi_transport_template; extern void ata_scsi_scan_host(struct ata_port *ap); extern int ata_scsi_offline_dev(struct ata_device *dev); +extern void ata_scsi_hotplug(void *data); extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf, unsigned int buflen); diff --git a/include/linux/libata.h b/include/linux/libata.h index 56971943d26..407115624d9 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -521,7 +521,7 @@ struct ata_port { struct ata_host_set *host_set; struct device *dev; - struct work_struct port_task; + struct work_struct port_task, hotplug_task; unsigned int hsm_task_state; -- cgit v1.2.3 From 83c47bcb3c533180a6dda78152334de50065358a Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 31 May 2006 18:28:07 +0900 Subject: [PATCH] libata-hp: implement warmplug Implement warmplug. User-initiated unplug can be detected by hostt->slave_destroy() and plug by transportt->user_scan(). This patch only implements the two callbacks. The next function will hook them. Signed-off-by: Tejun Heo --- drivers/scsi/libata-core.c | 1 + drivers/scsi/libata-scsi.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++ include/linux/libata.h | 1 + 3 files changed, 91 insertions(+) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 8df8ecc51a7..c61cfc74238 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -5942,6 +5942,7 @@ EXPORT_SYMBOL_GPL(ata_port_queue_task); EXPORT_SYMBOL_GPL(ata_scsi_ioctl); EXPORT_SYMBOL_GPL(ata_scsi_queuecmd); EXPORT_SYMBOL_GPL(ata_scsi_slave_config); +EXPORT_SYMBOL_GPL(ata_scsi_slave_destroy); EXPORT_SYMBOL_GPL(ata_scsi_change_queue_depth); EXPORT_SYMBOL_GPL(ata_scsi_release); EXPORT_SYMBOL_GPL(ata_host_intr); diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 12563998d97..7c1ac58c430 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -57,6 +57,8 @@ static struct ata_device * __ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev); static struct ata_device * ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev); +static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel, + unsigned int id, unsigned int lun); #define RW_RECOVERY_MPAGE 0x1 @@ -726,6 +728,40 @@ int ata_scsi_slave_config(struct scsi_device *sdev) return 0; /* scsi layer doesn't check return value, sigh */ } +/** + * ata_scsi_slave_destroy - SCSI device is about to be destroyed + * @sdev: SCSI device to be destroyed + * + * @sdev is about to be destroyed for hot/warm unplugging. If + * this unplugging was initiated by libata as indicated by NULL + * dev->sdev, this function doesn't have to do anything. + * Otherwise, SCSI layer initiated warm-unplug is in progress. + * Clear dev->sdev, schedule the device for ATA detach and invoke + * EH. + * + * LOCKING: + * Defined by SCSI layer. We don't really care. + */ +void ata_scsi_slave_destroy(struct scsi_device *sdev) +{ + struct ata_port *ap = ata_shost_to_port(sdev->host); + unsigned long flags; + struct ata_device *dev; + + if (!ap->ops->error_handler) + return; + + spin_lock_irqsave(&ap->host_set->lock, flags); + dev = __ata_scsi_find_dev(ap, sdev); + if (dev && dev->sdev) { + /* SCSI device already in CANCEL state, no need to offline it */ + dev->sdev = NULL; + dev->flags |= ATA_DFLAG_DETACH; + ata_port_schedule_eh(ap); + } + spin_unlock_irqrestore(&ap->host_set->lock, flags); +} + /** * ata_scsi_change_queue_depth - SCSI callback for queue depth config * @sdev: SCSI device to configure queue depth for @@ -2902,3 +2938,56 @@ void ata_scsi_hotplug(void *data) DPRINTK("EXIT\n"); } + +/** + * ata_scsi_user_scan - indication for user-initiated bus scan + * @shost: SCSI host to scan + * @channel: Channel to scan + * @id: ID to scan + * @lun: LUN to scan + * + * This function is called when user explicitly requests bus + * scan. Set probe pending flag and invoke EH. + * + * LOCKING: + * SCSI layer (we don't care) + * + * RETURNS: + * Zero. + */ +static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel, + unsigned int id, unsigned int lun) +{ + struct ata_port *ap = ata_shost_to_port(shost); + unsigned long flags; + int rc = 0; + + if (!ap->ops->error_handler) + return -EOPNOTSUPP; + + if ((channel != SCAN_WILD_CARD && channel != 0) || + (lun != SCAN_WILD_CARD && lun != 0)) + return -EINVAL; + + spin_lock_irqsave(&ap->host_set->lock, flags); + + if (id == SCAN_WILD_CARD) { + ap->eh_info.probe_mask |= (1 << ATA_MAX_DEVICES) - 1; + ap->eh_info.action |= ATA_EH_SOFTRESET; + } else { + struct ata_device *dev = ata_find_dev(ap, id); + + if (dev) { + ap->eh_info.probe_mask |= 1 << dev->devno; + ap->eh_info.action |= ATA_EH_SOFTRESET; + } else + rc = -EINVAL; + } + + if (rc == 0) + ata_port_schedule_eh(ap); + + spin_unlock_irqrestore(&ap->host_set->lock, flags); + + return rc; +} diff --git a/include/linux/libata.h b/include/linux/libata.h index 407115624d9..74786c33c52 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -734,6 +734,7 @@ extern int ata_std_bios_param(struct scsi_device *sdev, struct block_device *bdev, sector_t capacity, int geom[]); extern int ata_scsi_slave_config(struct scsi_device *sdev); +extern void ata_scsi_slave_destroy(struct scsi_device *sdev); extern int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth); extern struct ata_device *ata_dev_pair(struct ata_device *adev); -- cgit v1.2.3 From ccf68c3405fca11386004674377d951b9b18e756 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 31 May 2006 18:28:09 +0900 Subject: [PATCH] libata-hp: hook warmplug Hook transportt->user_scan() and hostt->slave_destroy(). Signed-off-by: Tejun Heo --- drivers/scsi/ahci.c | 1 + drivers/scsi/ata_piix.c | 1 + drivers/scsi/libata-scsi.c | 1 + drivers/scsi/pdc_adma.c | 1 + drivers/scsi/sata_mv.c | 1 + drivers/scsi/sata_nv.c | 1 + drivers/scsi/sata_promise.c | 1 + drivers/scsi/sata_qstor.c | 1 + drivers/scsi/sata_sil.c | 1 + drivers/scsi/sata_sil24.c | 1 + drivers/scsi/sata_sis.c | 1 + drivers/scsi/sata_svw.c | 1 + drivers/scsi/sata_sx4.c | 1 + drivers/scsi/sata_uli.c | 1 + drivers/scsi/sata_via.c | 1 + drivers/scsi/sata_vsc.c | 1 + 16 files changed, 16 insertions(+) diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 8493b021cc0..afb3805f9e9 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -228,6 +228,7 @@ static struct scsi_host_template ahci_sht = { .proc_name = DRV_NAME, .dma_boundary = AHCI_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index ad41dfd33e0..54c2e52373f 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -219,6 +219,7 @@ static struct scsi_host_template piix_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, .resume = ata_scsi_device_resume, .suspend = ata_scsi_device_suspend, diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 7c1ac58c430..5f90d8e3354 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -107,6 +107,7 @@ static const u8 def_control_mpage[CONTROL_MPAGE_LEN] = { struct scsi_transport_template ata_scsi_transport_template = { .eh_strategy_handler = ata_scsi_error, .eh_timed_out = ata_scsi_timed_out, + .user_scan = ata_scsi_user_scan, }; diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c index a341fa8d329..eb910e4c7d7 100644 --- a/drivers/scsi/pdc_adma.c +++ b/drivers/scsi/pdc_adma.c @@ -152,6 +152,7 @@ static struct scsi_host_template adma_ata_sht = { .proc_name = DRV_NAME, .dma_boundary = ADMA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index 624983c2e24..634bab17a6b 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -390,6 +390,7 @@ static struct scsi_host_template mv_sht = { .proc_name = DRV_NAME, .dma_boundary = MV_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c index d93513ef741..90551246aa4 100644 --- a/drivers/scsi/sata_nv.c +++ b/drivers/scsi/sata_nv.c @@ -216,6 +216,7 @@ static struct scsi_host_template nv_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index 01111594d09..b2b6ed5216e 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c @@ -121,6 +121,7 @@ static struct scsi_host_template pdc_ata_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c index 68737cadd2d..98ddc25655f 100644 --- a/drivers/scsi/sata_qstor.c +++ b/drivers/scsi/sata_qstor.c @@ -142,6 +142,7 @@ static struct scsi_host_template qs_ata_sht = { .proc_name = DRV_NAME, .dma_boundary = QS_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index 03c1d1b1a04..7d43cd3a50f 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -174,6 +174,7 @@ static struct scsi_host_template sil_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 4a830903393..d4ca6d6b402 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -370,6 +370,7 @@ static struct scsi_host_template sil24_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c index 82a07bff7e9..a07e6e52517 100644 --- a/drivers/scsi/sata_sis.c +++ b/drivers/scsi/sata_sis.c @@ -96,6 +96,7 @@ static struct scsi_host_template sis_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c index 7a4703bfa12..d9b51683648 100644 --- a/drivers/scsi/sata_svw.c +++ b/drivers/scsi/sata_svw.c @@ -299,6 +299,7 @@ static struct scsi_host_template k2_sata_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, #ifdef CONFIG_PPC_OF .proc_info = k2_sata_proc_info, #endif diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c index c4db6bf14a2..7f864410f7c 100644 --- a/drivers/scsi/sata_sx4.c +++ b/drivers/scsi/sata_sx4.c @@ -191,6 +191,7 @@ static struct scsi_host_template pdc_sata_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c index 7fae3e06e46..e69ba229adc 100644 --- a/drivers/scsi/sata_uli.c +++ b/drivers/scsi/sata_uli.c @@ -90,6 +90,7 @@ static struct scsi_host_template uli_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c index 1c9e2f36805..c6975c5580e 100644 --- a/drivers/scsi/sata_via.c +++ b/drivers/scsi/sata_via.c @@ -103,6 +103,7 @@ static struct scsi_host_template svia_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c index 438e7c6a0f8..22ca7b848cf 100644 --- a/drivers/scsi/sata_vsc.c +++ b/drivers/scsi/sata_vsc.c @@ -279,6 +279,7 @@ static struct scsi_host_template vsc_sata_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; -- cgit v1.2.3 From 3e706399b03bd237d087d731d4b1b029e546b33d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 31 May 2006 18:28:11 +0900 Subject: [PATCH] libata-hp: implement bootplug Implement bootplug - boot probing via hotplug path. While loading, ata_host_add() simply schedules probing and invokes EH. After EH completes, ata_host_add() scans and assicates them with SCSI devices. EH path is slightly modified to handle this (e.g. no autopsy during bootplug). The SCSI part is left in ata_host_add() because it's shared with legacy path and to keep probing order as before (ATA scan all ports in host_set then attach all). Signed-off-by: Tejun Heo --- drivers/scsi/libata-core.c | 49 ++++++++++++++++++++++++++++++++-------------- drivers/scsi/libata-eh.c | 27 ++++++++++++++++--------- 2 files changed, 52 insertions(+), 24 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index c61cfc74238..a42877e6b86 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -5419,7 +5419,7 @@ static struct ata_port * ata_host_add(const struct ata_probe_ent *ent, DPRINTK("ENTER\n"); - if (!ent->port_ops->probe_reset && + if (!ent->port_ops->probe_reset && !ent->port_ops->error_handler && !(ent->host_flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST))) { printk(KERN_ERR "ata%u: no reset mechanism available\n", port_no); @@ -5465,7 +5465,6 @@ err_out: * RETURNS: * Number of ports registered. Zero on error (no ports registered). */ - int ata_device_add(const struct ata_probe_ent *ent) { unsigned int count = 0, i; @@ -5542,19 +5541,6 @@ int ata_device_add(const struct ata_probe_ent *ent) } ap->sata_spd_limit = ap->hw_sata_spd_limit; - DPRINTK("ata%u: bus probe begin\n", ap->id); - rc = ata_bus_probe(ap); - DPRINTK("ata%u: bus probe end\n", ap->id); - - if (rc) { - /* FIXME: do something useful here? - * Current libata behavior will - * tear down everything when - * the module is removed - * or the h/w is unplugged. - */ - } - rc = scsi_add_host(ap->host, dev); if (rc) { ata_port_printk(ap, KERN_ERR, "scsi_add_host failed\n"); @@ -5564,6 +5550,39 @@ int ata_device_add(const struct ata_probe_ent *ent) * at the very least */ } + + if (!ap->ops->probe_reset) { + unsigned long flags; + + ata_port_probe(ap); + + /* kick EH for boot probing */ + spin_lock_irqsave(&ap->host_set->lock, flags); + + ap->eh_info.probe_mask = (1 << ATA_MAX_DEVICES) - 1; + ap->eh_info.action |= ATA_EH_SOFTRESET; + + ap->flags |= ATA_FLAG_LOADING; + ata_port_schedule_eh(ap); + + spin_unlock_irqrestore(&ap->host_set->lock, flags); + + /* wait for EH to finish */ + ata_port_wait_eh(ap); + } else { + DPRINTK("ata%u: bus probe begin\n", ap->id); + rc = ata_bus_probe(ap); + DPRINTK("ata%u: bus probe end\n", ap->id); + + if (rc) { + /* FIXME: do something useful here? + * Current libata behavior will + * tear down everything when + * the module is removed + * or the h/w is unplugged. + */ + } + } } /* probes are done, now scan each port's disk(s) */ diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c index 733dfa53297..70c132bef68 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/scsi/libata-eh.c @@ -287,11 +287,14 @@ void ata_scsi_error(struct Scsi_Host *host) /* clean up */ spin_lock_irqsave(hs_lock, flags); - if (ap->flags & ATA_FLAG_SCSI_HOTPLUG) - queue_work(ata_aux_wq, &ap->hotplug_task); - - if (ap->flags & ATA_FLAG_RECOVERED) - ata_port_printk(ap, KERN_INFO, "EH complete\n"); + if (ap->flags & ATA_FLAG_LOADING) { + ap->flags &= ~ATA_FLAG_LOADING; + } else { + if (ap->flags & ATA_FLAG_SCSI_HOTPLUG) + queue_work(ata_aux_wq, &ap->hotplug_task); + if (ap->flags & ATA_FLAG_RECOVERED) + ata_port_printk(ap, KERN_INFO, "EH complete\n"); + } ap->flags &= ~(ATA_FLAG_SCSI_HOTPLUG | ATA_FLAG_RECOVERED); @@ -1367,6 +1370,7 @@ static int ata_eh_reset(struct ata_port *ap, int classify, struct ata_eh_context *ehc = &ap->eh_context; unsigned int *classes = ehc->classes; int tries = ATA_EH_RESET_TRIES; + int verbose = !(ap->flags & ATA_FLAG_LOADING); unsigned int action; ata_reset_fn_t reset; int i, did_followup_srst, rc; @@ -1414,8 +1418,10 @@ static int ata_eh_reset(struct ata_port *ap, int classify, } retry: - ata_port_printk(ap, KERN_INFO, "%s resetting port\n", - reset == softreset ? "soft" : "hard"); + /* shut up during boot probing */ + if (verbose) + ata_port_printk(ap, KERN_INFO, "%s resetting port\n", + reset == softreset ? "soft" : "hard"); /* reset */ ata_eh_about_to_do(ap, ATA_EH_RESET_MASK); @@ -1799,8 +1805,11 @@ void ata_do_eh(struct ata_port *ap, ata_prereset_fn_t prereset, ata_reset_fn_t softreset, ata_reset_fn_t hardreset, ata_postreset_fn_t postreset) { - ata_eh_autopsy(ap); - ata_eh_report(ap); + if (!(ap->flags & ATA_FLAG_LOADING)) { + ata_eh_autopsy(ap); + ata_eh_report(ap); + } + ata_eh_recover(ap, prereset, softreset, hardreset, postreset); ata_eh_finish(ap); } -- cgit v1.2.3 From 720ba12620ee09dce269adf4ad50958adac7bb54 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 31 May 2006 18:28:13 +0900 Subject: [PATCH] libata-hp: update unload-unplug Update unload unplug - driver unloading / PCI removal. This is done by ata_port_detach() which short-circuits EH, disables all devices and freezes the port. With this patch, EH and unloading/unplugging are properly synchronized. Signed-off-by: Tejun Heo --- drivers/scsi/ahci.c | 10 +++---- drivers/scsi/libata-core.c | 67 +++++++++++++++++++++++++++++++++++++++++----- drivers/scsi/libata-eh.c | 8 ++++-- include/linux/libata.h | 1 + 4 files changed, 71 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index afb3805f9e9..60f455bf369 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -1389,21 +1389,17 @@ static void ahci_remove_one (struct pci_dev *pdev) struct device *dev = pci_dev_to_dev(pdev); struct ata_host_set *host_set = dev_get_drvdata(dev); struct ahci_host_priv *hpriv = host_set->private_data; - struct ata_port *ap; unsigned int i; int have_msi; - for (i = 0; i < host_set->n_ports; i++) { - ap = host_set->ports[i]; - - scsi_remove_host(ap->host); - } + for (i = 0; i < host_set->n_ports; i++) + ata_port_detach(host_set->ports[i]); have_msi = hpriv->flags & AHCI_FLAG_MSI; free_irq(host_set->irq, host_set); for (i = 0; i < host_set->n_ports; i++) { - ap = host_set->ports[i]; + struct ata_port *ap = host_set->ports[i]; ata_scsi_release(ap->host); scsi_host_put(ap->host); diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index a42877e6b86..01f2c59536b 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -5609,6 +5609,63 @@ err_free_ret: return 0; } +/** + * ata_port_detach - Detach ATA port in prepration of device removal + * @ap: ATA port to be detached + * + * Detach all ATA devices and the associated SCSI devices of @ap; + * then, remove the associated SCSI host. @ap is guaranteed to + * be quiescent on return from this function. + * + * LOCKING: + * Kernel thread context (may sleep). + */ +void ata_port_detach(struct ata_port *ap) +{ + unsigned long flags; + int i; + + if (!ap->ops->error_handler) + return; + + /* tell EH we're leaving & flush EH */ + spin_lock_irqsave(&ap->host_set->lock, flags); + ap->flags |= ATA_FLAG_UNLOADING; + spin_unlock_irqrestore(&ap->host_set->lock, flags); + + ata_port_wait_eh(ap); + + /* EH is now guaranteed to see UNLOADING, so no new device + * will be attached. Disable all existing devices. + */ + spin_lock_irqsave(&ap->host_set->lock, flags); + + for (i = 0; i < ATA_MAX_DEVICES; i++) + ata_dev_disable(&ap->device[i]); + + spin_unlock_irqrestore(&ap->host_set->lock, flags); + + /* Final freeze & EH. All in-flight commands are aborted. EH + * will be skipped and retrials will be terminated with bad + * target. + */ + spin_lock_irqsave(&ap->host_set->lock, flags); + ata_port_freeze(ap); /* won't be thawed */ + spin_unlock_irqrestore(&ap->host_set->lock, flags); + + ata_port_wait_eh(ap); + + /* Flush hotplug task. The sequence is similar to + * ata_port_flush_task(). + */ + flush_workqueue(ata_aux_wq); + cancel_delayed_work(&ap->hotplug_task); + flush_workqueue(ata_aux_wq); + + /* remove the associated SCSI host */ + scsi_remove_host(ap->host); +} + /** * ata_host_set_remove - PCI layer callback for device removal * @host_set: ATA host set that was removed @@ -5622,18 +5679,15 @@ err_free_ret: void ata_host_set_remove(struct ata_host_set *host_set) { - struct ata_port *ap; unsigned int i; - for (i = 0; i < host_set->n_ports; i++) { - ap = host_set->ports[i]; - scsi_remove_host(ap->host); - } + for (i = 0; i < host_set->n_ports; i++) + ata_port_detach(host_set->ports[i]); free_irq(host_set->irq, host_set); for (i = 0; i < host_set->n_ports; i++) { - ap = host_set->ports[i]; + struct ata_port *ap = host_set->ports[i]; ata_scsi_release(ap->host); @@ -5901,6 +5955,7 @@ EXPORT_SYMBOL_GPL(sata_deb_timing_before_fsrst); EXPORT_SYMBOL_GPL(ata_std_bios_param); EXPORT_SYMBOL_GPL(ata_std_ports); EXPORT_SYMBOL_GPL(ata_device_add); +EXPORT_SYMBOL_GPL(ata_port_detach); EXPORT_SYMBOL_GPL(ata_host_set_remove); EXPORT_SYMBOL_GPL(ata_sg_init); EXPORT_SYMBOL_GPL(ata_sg_init_one); diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c index 70c132bef68..30a83a57a12 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/scsi/libata-eh.c @@ -46,6 +46,7 @@ #include "libata.h" static void __ata_port_freeze(struct ata_port *ap); +static void ata_eh_finish(struct ata_port *ap); static void ata_ering_record(struct ata_ering *ering, int is_io, unsigned int err_mask) @@ -242,8 +243,11 @@ void ata_scsi_error(struct Scsi_Host *host) spin_unlock_irqrestore(hs_lock, flags); - /* invoke EH */ - ap->ops->error_handler(ap); + /* invoke EH. if unloading, just finish failed qcs */ + if (!(ap->flags & ATA_FLAG_UNLOADING)) + ap->ops->error_handler(ap); + else + ata_eh_finish(ap); /* Exception might have happend after ->error_handler * recovered the port but before this point. Repeat diff --git a/include/linux/libata.h b/include/linux/libata.h index 74786c33c52..f11ba2715be 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -649,6 +649,7 @@ extern int ata_pci_device_resume(struct pci_dev *pdev); extern int ata_pci_clear_simplex(struct pci_dev *pdev); #endif /* CONFIG_PCI */ extern int ata_device_add(const struct ata_probe_ent *ent); +extern void ata_port_detach(struct ata_port *ap); extern void ata_host_set_remove(struct ata_host_set *host_set); extern int ata_scsi_detect(struct scsi_host_template *sht); extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg); -- cgit v1.2.3 From ccc4672aff1861a9c80ed9e8ec11dc304b31d307 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 31 May 2006 18:28:14 +0900 Subject: [PATCH] ata_piix: convert ata_piix to new probing mechanism Convert ata_piix to new probing mechanism. Automatic hotplug is not supported due to hardware limitation (no PHY event interrupt), but warm plugging works. Signed-off-by: Tejun Heo --- drivers/scsi/ata_piix.c | 87 ++++++++++++++++++------------------------------- 1 file changed, 32 insertions(+), 55 deletions(-) diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index 54c2e52373f..521b718763f 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -146,11 +146,10 @@ struct piix_map_db { static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); - -static int piix_pata_probe_reset(struct ata_port *ap, unsigned int *classes); -static int piix_sata_probe_reset(struct ata_port *ap, unsigned int *classes); static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev); static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev); +static void piix_pata_error_handler(struct ata_port *ap); +static void piix_sata_error_handler(struct ata_port *ap); static unsigned int in_module_init = 1; @@ -237,8 +236,6 @@ static const struct ata_port_operations piix_pata_ops = { .exec_command = ata_exec_command, .dev_select = ata_std_dev_select, - .probe_reset = piix_pata_probe_reset, - .bmdma_setup = ata_bmdma_setup, .bmdma_start = ata_bmdma_start, .bmdma_stop = ata_bmdma_stop, @@ -249,7 +246,7 @@ static const struct ata_port_operations piix_pata_ops = { .freeze = ata_bmdma_freeze, .thaw = ata_bmdma_thaw, - .error_handler = ata_bmdma_error_handler, + .error_handler = piix_pata_error_handler, .post_internal_cmd = ata_bmdma_post_internal_cmd, .irq_handler = ata_interrupt, @@ -269,8 +266,6 @@ static const struct ata_port_operations piix_sata_ops = { .exec_command = ata_exec_command, .dev_select = ata_std_dev_select, - .probe_reset = piix_sata_probe_reset, - .bmdma_setup = ata_bmdma_setup, .bmdma_start = ata_bmdma_start, .bmdma_stop = ata_bmdma_stop, @@ -281,7 +276,7 @@ static const struct ata_port_operations piix_sata_ops = { .freeze = ata_bmdma_freeze, .thaw = ata_bmdma_thaw, - .error_handler = ata_bmdma_error_handler, + .error_handler = piix_sata_error_handler, .post_internal_cmd = ata_bmdma_post_internal_cmd, .irq_handler = ata_interrupt, @@ -466,59 +461,51 @@ cbl40: } /** - * piix_pata_probeinit - probeinit for PATA host controller + * piix_pata_prereset - prereset for PATA host controller * @ap: Target port * - * Probeinit including cable detection. - * - * LOCKING: - * None (inherited from caller). - */ -static void piix_pata_probeinit(struct ata_port *ap) -{ - piix_pata_cbl_detect(ap); - ata_std_probeinit(ap); -} - -/** - * piix_pata_probe_reset - Perform reset on PATA port and classify - * @ap: Port to reset - * @classes: Resulting classes of attached devices - * - * Reset PATA phy and classify attached devices. + * Prereset including cable detection. * * LOCKING: * None (inherited from caller). */ -static int piix_pata_probe_reset(struct ata_port *ap, unsigned int *classes) +static int piix_pata_prereset(struct ata_port *ap) { struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->hard_port_no])) { ata_port_printk(ap, KERN_INFO, "port disabled. ignoring.\n"); + ap->eh_context.i.action &= ~ATA_EH_RESET_MASK; return 0; } - return ata_drive_probe_reset(ap, piix_pata_probeinit, - ata_std_softreset, NULL, - ata_std_postreset, classes); + piix_pata_cbl_detect(ap); + + return ata_std_prereset(ap); +} + +static void piix_pata_error_handler(struct ata_port *ap) +{ + ata_bmdma_drive_eh(ap, piix_pata_prereset, ata_std_softreset, NULL, + ata_std_postreset); } /** - * piix_sata_probe - Probe PCI device for present SATA devices - * @ap: Port associated with the PCI device we wish to probe + * piix_sata_prereset - prereset for SATA host controller + * @ap: Target port * * Reads and configures SATA PCI device's PCI config register * Port Configuration and Status (PCS) to determine port and - * device availability. + * device availability. Return -ENODEV to skip reset if no + * device is present. * * LOCKING: * None (inherited from caller). * * RETURNS: - * Mask of avaliable devices on the port. + * 0 if device is present, -ENODEV otherwise. */ -static unsigned int piix_sata_probe (struct ata_port *ap) +static int piix_sata_prereset(struct ata_port *ap) { struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); const unsigned int *map = ap->host_set->private_data; @@ -560,29 +547,19 @@ static unsigned int piix_sata_probe (struct ata_port *ap) DPRINTK("ata%u: LEAVE, pcs=0x%x present_mask=0x%x\n", ap->id, pcs, present_mask); - return present_mask; -} - -/** - * piix_sata_probe_reset - Perform reset on SATA port and classify - * @ap: Port to reset - * @classes: Resulting classes of attached devices - * - * Reset SATA phy and classify attached devices. - * - * LOCKING: - * None (inherited from caller). - */ -static int piix_sata_probe_reset(struct ata_port *ap, unsigned int *classes) -{ - if (!piix_sata_probe(ap)) { + if (!present_mask) { ata_port_printk(ap, KERN_INFO, "SATA port has no device.\n"); + ap->eh_context.i.action &= ~ATA_EH_RESET_MASK; return 0; } - return ata_drive_probe_reset(ap, ata_std_probeinit, - ata_std_softreset, NULL, - ata_std_postreset, classes); + return ata_std_prereset(ap); +} + +static void piix_sata_error_handler(struct ata_port *ap) +{ + ata_bmdma_drive_eh(ap, piix_sata_prereset, ata_std_softreset, NULL, + ata_std_postreset); } /** -- cgit v1.2.3 From e573890b00426189e1e223967a2c46fb758bf06e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 31 May 2006 18:28:16 +0900 Subject: [PATCH] sata_sil: convert to new probing mechanism and add hotplug support Convert to new probing mechanism and add hotplug support by enabling SATA IRQ for SError.N, marking ehi for hotplug and scheduling EH on SATA IRQs. Sil3112/3512/3114 family of controllers use COMRESET as TF clearing point and can reliably wait for D2H FIS after COMRESET whether the FIS is the first D2H FIS after POR or in response to the COMRESET. Thus, setting ATA_FLAG_HRST_TO_RESUME is enough for device detection after hotplug. Signed-off-by: Tejun Heo --- drivers/scsi/sata_sil.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index 7d43cd3a50f..0898cbe6458 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -56,7 +56,7 @@ enum { SIL_FLAG_MOD15WRITE = (1 << 30), SIL_DFL_HOST_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_MMIO, + ATA_FLAG_MMIO | ATA_FLAG_HRST_TO_RESUME, /* * Controller IDs @@ -186,7 +186,6 @@ static const struct ata_port_operations sil_ops = { .check_status = ata_check_status, .exec_command = ata_exec_command, .dev_select = ata_std_dev_select, - .probe_reset = ata_std_probe_reset, .post_set_mode = sil_post_set_mode, .bmdma_setup = ata_bmdma_setup, .bmdma_start = ata_bmdma_start, @@ -344,6 +343,11 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2) struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag); u8 status; + if (unlikely(bmdma2 & SIL_DMA_SATA_IRQ)) { + ata_ehi_hotplugged(&ap->eh_info); + goto freeze; + } + if (unlikely(!qc || qc->tf.ctl & ATA_NIEN)) goto freeze; @@ -415,7 +419,7 @@ static irqreturn_t sil_interrupt(int irq, void *dev_instance, if (unlikely(!ap || ap->flags & ATA_FLAG_DISABLED)) continue; - if (!(bmdma2 & SIL_DMA_COMPLETE)) + if (!(bmdma2 & (SIL_DMA_COMPLETE | SIL_DMA_SATA_IRQ))) continue; sil_host_intr(ap, bmdma2); @@ -432,6 +436,9 @@ static void sil_freeze(struct ata_port *ap) void __iomem *mmio_base = ap->host_set->mmio_base; u32 tmp; + /* global IRQ mask doesn't block SATA IRQ, turn off explicitly */ + writel(0, mmio_base + sil_port[ap->port_no].sien); + /* plug IRQ */ tmp = readl(mmio_base + SIL_SYSCFG); tmp |= SIL_MASK_IDE0_INT << ap->port_no; @@ -448,6 +455,9 @@ static void sil_thaw(struct ata_port *ap) ata_chk_status(ap); ata_bmdma_irq_clear(ap); + /* turn on SATA IRQ */ + writel(SIL_SIEN_N, mmio_base + sil_port[ap->port_no].sien); + /* turn on IRQ */ tmp = readl(mmio_base + SIL_SYSCFG); tmp &= ~(SIL_MASK_IDE0_INT << ap->port_no); @@ -621,11 +631,6 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) mmio_base + sil_port[2].bmdma); } - /* mask all SATA phy-related interrupts */ - /* TODO: unmask bit 6 (SError N bit) for hotplug */ - for (i = 0; i < probe_ent->n_ports; i++) - writel(0, mmio_base + sil_port[i].sien); - pci_set_master(pdev); /* FIXME: check ata_device_add return value */ -- cgit v1.2.3 From 4296971dd36e2c2deae0826305f591480223af88 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 31 May 2006 18:28:18 +0900 Subject: [PATCH] ahci: convert to new probing mechanism and add hotplug support Convert to new probing mechanism and add hotplug support by enabling PORT_IRQ_PHYRDY, marking ehi for hotplug and scheduling EH on CONNECT/PHYRDY interrupts. Unfortunately, ahci cannot reliably wait for the first D2H FIS after hotplug. It sometimes succeeds but times out more often than not, so ATA_FLAG_SKIP_D2H_BSY is used. This patch also fixes ahci_hardreset() such that D2H Register FIS RX area is cleared before issuing COMRESET. Without this, ata_busy_sleep() after COMRESET might prematually finish if the previous TF contains DRDY && !BSY. Signed-off-by: Tejun Heo --- drivers/scsi/ahci.c | 47 +++++++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 60f455bf369..e261b37c2e4 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -136,6 +136,7 @@ enum { PORT_IRQ_FREEZE = PORT_IRQ_HBUS_ERR | PORT_IRQ_IF_ERR | PORT_IRQ_CONNECT | + PORT_IRQ_PHYRDY | PORT_IRQ_UNK_FIS, PORT_IRQ_ERROR = PORT_IRQ_FREEZE | PORT_IRQ_TF_ERR | @@ -200,7 +201,6 @@ static void ahci_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc); static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *regs); -static int ahci_probe_reset(struct ata_port *ap, unsigned int *classes); static void ahci_irq_clear(struct ata_port *ap); static int ahci_port_start(struct ata_port *ap); static void ahci_port_stop(struct ata_port *ap); @@ -241,8 +241,6 @@ static const struct ata_port_operations ahci_ops = { .tf_read = ahci_tf_read, - .probe_reset = ahci_probe_reset, - .qc_prep = ahci_qc_prep, .qc_issue = ahci_qc_issue, @@ -267,7 +265,8 @@ static const struct ata_port_info ahci_port_info[] = { { .sht = &ahci_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA, + ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | + ATA_FLAG_SKIP_D2H_BSY, .pio_mask = 0x1f, /* pio0-4 */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */ .port_ops = &ahci_ops, @@ -277,6 +276,7 @@ static const struct ata_port_info ahci_port_info[] = { .sht = &ahci_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | + ATA_FLAG_SKIP_D2H_BSY | AHCI_FLAG_RESET_NEEDS_CLO, .pio_mask = 0x1f, /* pio0-4 */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */ @@ -569,6 +569,17 @@ static int ahci_clo(struct ata_port *ap) return 0; } +static int ahci_prereset(struct ata_port *ap) +{ + if ((ap->flags & AHCI_FLAG_RESET_NEEDS_CLO) && + (ata_busy_wait(ap, ATA_BUSY, 1000) & ATA_BUSY)) { + /* ATA_BUSY hasn't cleared, so send a CLO */ + ahci_clo(ap); + } + + return ata_std_prereset(ap); +} + static int ahci_softreset(struct ata_port *ap, unsigned int *class) { struct ahci_port_priv *pp = ap->private_data; @@ -678,12 +689,22 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class) static int ahci_hardreset(struct ata_port *ap, unsigned int *class) { + struct ahci_port_priv *pp = ap->private_data; + u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; + struct ata_taskfile tf; int rc; DPRINTK("ENTER\n"); ahci_stop_engine(ap); + + /* clear D2H reception area to properly wait for D2H FIS */ + ata_tf_init(ap->device, &tf); + tf.command = 0xff; + ata_tf_to_fis(&tf, d2h_fis, 0); + rc = sata_std_hardreset(ap, class); + ahci_start_engine(ap); if (rc == 0 && ata_port_online(ap)) @@ -714,19 +735,6 @@ static void ahci_postreset(struct ata_port *ap, unsigned int *class) } } -static int ahci_probe_reset(struct ata_port *ap, unsigned int *classes) -{ - if ((ap->flags & AHCI_FLAG_RESET_NEEDS_CLO) && - (ata_busy_wait(ap, ATA_BUSY, 1000) & ATA_BUSY)) { - /* ATA_BUSY hasn't cleared, so send a CLO */ - ahci_clo(ap); - } - - return ata_drive_probe_reset(ap, ata_std_probeinit, - ahci_softreset, ahci_hardreset, - ahci_postreset, classes); -} - static u8 ahci_check_status(struct ata_port *ap) { void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr; @@ -839,8 +847,7 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat) } if (irq_stat & (PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY)) { - err_mask |= AC_ERR_ATA_BUS; - action |= ATA_EH_SOFTRESET; + ata_ehi_hotplugged(ehi); ata_ehi_push_desc(ehi, ", %s", irq_stat & PORT_IRQ_CONNECT ? "connection status changed" : "PHY RDY changed"); } @@ -1027,7 +1034,7 @@ static void ahci_error_handler(struct ata_port *ap) } /* perform recovery */ - ata_do_eh(ap, ata_std_prereset, ahci_softreset, ahci_hardreset, + ata_do_eh(ap, ahci_prereset, ahci_softreset, ahci_hardreset, ahci_postreset); } -- cgit v1.2.3 From 0542925b25676543e8384edf454668f89227e905 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 31 May 2006 18:28:20 +0900 Subject: [PATCH] sata_sil24: convert to new probing mechanism and add hotplug support Convert to new probing mechanism and add hotplug support by enabling PORT_IRQ_PHYRDY_CHG, marking ehi for hotplug and scheduling EH on PORT_IRQ_PHYRDY_CHG or PORT_IRQ_DEV_XCHG. Sil3124/32 family of controllers don't have any mechanism to wait for the first D2H FIS after hotplug, so ATA_FLAG_SKIP_D2H_BSY is used. Signed-off-by: Tejun Heo --- drivers/scsi/sata_sil24.c | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index d4ca6d6b402..97e93392f92 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -159,7 +159,8 @@ enum { PORT_IRQ_SDB_NOTIFY = (1 << 11), /* SDB notify received */ DEF_PORT_IRQ = PORT_IRQ_COMPLETE | PORT_IRQ_ERROR | - PORT_IRQ_DEV_XCHG | PORT_IRQ_UNK_FIS, + PORT_IRQ_PHYRDY_CHG | PORT_IRQ_DEV_XCHG | + PORT_IRQ_UNK_FIS, /* bits[27:16] are unmasked (raw) */ PORT_IRQ_RAW_SHIFT = 16, @@ -228,7 +229,7 @@ enum { /* host flags */ SIL24_COMMON_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | - ATA_FLAG_NCQ, + ATA_FLAG_NCQ | ATA_FLAG_SKIP_D2H_BSY, SIL24_FLAG_PCIX_IRQ_WOC = (1 << 24), /* IRQ loss errata on PCI-X */ IRQ_STAT_4PORTS = 0xf, @@ -325,7 +326,6 @@ static u8 sil24_check_status(struct ata_port *ap); static u32 sil24_scr_read(struct ata_port *ap, unsigned sc_reg); static void sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val); static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf); -static int sil24_probe_reset(struct ata_port *ap, unsigned int *classes); static void sil24_qc_prep(struct ata_queued_cmd *qc); static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc); static void sil24_irq_clear(struct ata_port *ap); @@ -385,8 +385,6 @@ static const struct ata_port_operations sil24_ops = { .tf_read = sil24_tf_read, - .probe_reset = sil24_probe_reset, - .qc_prep = sil24_qc_prep, .qc_issue = sil24_qc_issue, @@ -635,13 +633,6 @@ static int sil24_hardreset(struct ata_port *ap, unsigned int *class) return -EIO; } -static int sil24_probe_reset(struct ata_port *ap, unsigned int *classes) -{ - return ata_drive_probe_reset(ap, ata_std_probeinit, - sil24_softreset, sil24_hardreset, - ata_std_postreset, classes); -} - static inline void sil24_fill_sg(struct ata_queued_cmd *qc, struct sil24_sge *sge) { @@ -772,13 +763,11 @@ static void sil24_error_intr(struct ata_port *ap) ata_ehi_push_desc(ehi, "irq_stat 0x%08x", irq_stat); - if (irq_stat & PORT_IRQ_DEV_XCHG) { - ehi->err_mask |= AC_ERR_ATA_BUS; - /* sil24 doesn't recover very well from phy - * disconnection with a softreset. Force hardreset. - */ - ehi->action |= ATA_EH_HARDRESET; - ata_ehi_push_desc(ehi, ", device_exchanged"); + if (irq_stat & (PORT_IRQ_PHYRDY_CHG | PORT_IRQ_DEV_XCHG)) { + ata_ehi_hotplugged(ehi); + ata_ehi_push_desc(ehi, ", %s", + irq_stat & PORT_IRQ_PHYRDY_CHG ? + "PHY RDY changed" : "device exchanged"); freeze = 1; } -- cgit v1.2.3 From 52783c5dcc8d317bc8c3e2692d366e8a305abada Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 31 May 2006 18:28:22 +0900 Subject: [PATCH] libata-hp: killl ops->probe_reset Now that all drivers implementing new EH are converted to new probing mechanism, ops->probe_reset doesn't have any user. Kill it. Signed-off-by: Tejun Heo --- drivers/scsi/libata-core.c | 187 ++++----------------------------------------- include/linux/libata.h | 8 -- 2 files changed, 13 insertions(+), 182 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 01f2c59536b..30a6020c512 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1479,31 +1479,21 @@ static int ata_bus_probe(struct ata_port *ap) down_xfermask = 0; /* reset and determine device classes */ - for (i = 0; i < ATA_MAX_DEVICES; i++) - classes[i] = ATA_DEV_UNKNOWN; + ap->ops->phy_reset(ap); - if (ap->ops->probe_reset) { - rc = ap->ops->probe_reset(ap, classes); - if (rc) { - ata_port_printk(ap, KERN_ERR, - "reset failed (errno=%d)\n", rc); - return rc; - } - } else { - ap->ops->phy_reset(ap); + for (i = 0; i < ATA_MAX_DEVICES; i++) { + dev = &ap->device[i]; - for (i = 0; i < ATA_MAX_DEVICES; i++) { - if (!(ap->flags & ATA_FLAG_DISABLED)) - classes[i] = ap->device[i].class; - ap->device[i].class = ATA_DEV_UNKNOWN; - } + if (!(ap->flags & ATA_FLAG_DISABLED) && + dev->class != ATA_DEV_UNKNOWN) + classes[dev->devno] = dev->class; + else + classes[dev->devno] = ATA_DEV_NONE; - ata_port_probe(ap); + dev->class = ATA_DEV_UNKNOWN; } - for (i = 0; i < ATA_MAX_DEVICES; i++) - if (classes[i] == ATA_DEV_UNKNOWN) - classes[i] = ATA_DEV_NONE; + ata_port_probe(ap); /* after the reset the device state is PIO 0 and the controller state is undefined. Record the mode */ @@ -2609,38 +2599,12 @@ int ata_std_prereset(struct ata_port *ap) return 0; } -/** - * ata_std_probeinit - initialize probing - * @ap: port to be probed - * - * @ap is about to be probed. Initialize it. This function is - * to be used as standard callback for ata_drive_probe_reset(). - * - * NOTE!!! Do not use this function as probeinit if a low level - * driver implements only hardreset. Just pass NULL as probeinit - * in that case. Using this function is probably okay but doing - * so makes reset sequence different from the original - * ->phy_reset implementation and Jeff nervous. :-P - */ -void ata_std_probeinit(struct ata_port *ap) -{ - static const unsigned long deb_timing[] = { 5, 100, 5000 }; - - /* resume link */ - sata_phy_resume(ap, deb_timing); - - /* wait for device */ - if (ata_port_online(ap)) - ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT); -} - /** * ata_std_softreset - reset host port via ATA SRST * @ap: port to reset * @classes: resulting classes of attached devices * - * Reset host port using ATA SRST. This function is to be used - * as standard callback for ata_drive_*_reset() functions. + * Reset host port using ATA SRST. * * LOCKING: * Kernel thread context (may sleep) @@ -2695,8 +2659,6 @@ int ata_std_softreset(struct ata_port *ap, unsigned int *classes) * @class: resulting class of attached device * * SATA phy-reset host port using DET bits of SControl register. - * This function is to be used as standard callback for - * ata_drive_*_reset(). * * LOCKING: * Kernel thread context (may sleep) @@ -2775,9 +2737,6 @@ int sata_std_hardreset(struct ata_port *ap, unsigned int *class) * the device might have been reset more than once using * different reset methods before postreset is invoked. * - * This function is to be used as standard callback for - * ata_drive_*_reset(). - * * LOCKING: * Kernel thread context (may sleep) */ @@ -2824,32 +2783,6 @@ void ata_std_postreset(struct ata_port *ap, unsigned int *classes) DPRINTK("EXIT\n"); } -/** - * ata_std_probe_reset - standard probe reset method - * @ap: prot to perform probe-reset - * @classes: resulting classes of attached devices - * - * The stock off-the-shelf ->probe_reset method. - * - * LOCKING: - * Kernel thread context (may sleep) - * - * RETURNS: - * 0 on success, -errno otherwise. - */ -int ata_std_probe_reset(struct ata_port *ap, unsigned int *classes) -{ - ata_reset_fn_t hardreset; - - hardreset = NULL; - if (sata_scr_valid(ap)) - hardreset = sata_std_hardreset; - - return ata_drive_probe_reset(ap, ata_std_probeinit, - ata_std_softreset, hardreset, - ata_std_postreset, classes); -} - int ata_do_reset(struct ata_port *ap, ata_reset_fn_t reset, unsigned int *classes) { @@ -2878,97 +2811,6 @@ int ata_do_reset(struct ata_port *ap, ata_reset_fn_t reset, return 0; } -/** - * ata_drive_probe_reset - Perform probe reset with given methods - * @ap: port to reset - * @probeinit: probeinit method (can be NULL) - * @softreset: softreset method (can be NULL) - * @hardreset: hardreset method (can be NULL) - * @postreset: postreset method (can be NULL) - * @classes: resulting classes of attached devices - * - * Reset the specified port and classify attached devices using - * given methods. This function prefers softreset but tries all - * possible reset sequences to reset and classify devices. This - * function is intended to be used for constructing ->probe_reset - * callback by low level drivers. - * - * Reset methods should follow the following rules. - * - * - Return 0 on sucess, -errno on failure. - * - If classification is supported, fill classes[] with - * recognized class codes. - * - If classification is not supported, leave classes[] alone. - * - * LOCKING: - * Kernel thread context (may sleep) - * - * RETURNS: - * 0 on success, -EINVAL if no reset method is avaliable, -ENODEV - * if classification fails, and any error code from reset - * methods. - */ -int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, - ata_reset_fn_t softreset, ata_reset_fn_t hardreset, - ata_postreset_fn_t postreset, unsigned int *classes) -{ - int rc = -EINVAL; - - ata_eh_freeze_port(ap); - - if (probeinit) - probeinit(ap); - - if (softreset && !sata_set_spd_needed(ap)) { - rc = ata_do_reset(ap, softreset, classes); - if (rc == 0 && classes[0] != ATA_DEV_UNKNOWN) - goto done; - ata_port_printk(ap, KERN_INFO, "softreset failed, " - "will try hardreset in 5 secs\n"); - ssleep(5); - } - - if (!hardreset) - goto done; - - while (1) { - rc = ata_do_reset(ap, hardreset, classes); - if (rc == 0) { - if (classes[0] != ATA_DEV_UNKNOWN) - goto done; - break; - } - - if (sata_down_spd_limit(ap)) - goto done; - - ata_port_printk(ap, KERN_INFO, "hardreset failed, " - "will retry in 5 secs\n"); - ssleep(5); - } - - if (softreset) { - ata_port_printk(ap, KERN_INFO, - "hardreset succeeded without classification, " - "will retry softreset in 5 secs\n"); - ssleep(5); - - rc = ata_do_reset(ap, softreset, classes); - } - - done: - if (rc == 0) { - if (postreset) - postreset(ap, classes); - - ata_eh_thaw_port(ap); - - if (classes[0] == ATA_DEV_UNKNOWN) - rc = -ENODEV; - } - return rc; -} - /** * ata_dev_same_device - Determine whether new ID matches configured device * @dev: device to compare against @@ -5419,7 +5261,7 @@ static struct ata_port * ata_host_add(const struct ata_probe_ent *ent, DPRINTK("ENTER\n"); - if (!ent->port_ops->probe_reset && !ent->port_ops->error_handler && + if (!ent->port_ops->error_handler && !(ent->host_flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST))) { printk(KERN_ERR "ata%u: no reset mechanism available\n", port_no); @@ -5551,7 +5393,7 @@ int ata_device_add(const struct ata_probe_ent *ent) */ } - if (!ap->ops->probe_reset) { + if (ap->ops->error_handler) { unsigned long flags; ata_port_probe(ap); @@ -5998,13 +5840,10 @@ EXPORT_SYMBOL_GPL(sata_phy_resume); EXPORT_SYMBOL_GPL(sata_phy_reset); EXPORT_SYMBOL_GPL(__sata_phy_reset); EXPORT_SYMBOL_GPL(ata_bus_reset); -EXPORT_SYMBOL_GPL(ata_std_probeinit); EXPORT_SYMBOL_GPL(ata_std_prereset); EXPORT_SYMBOL_GPL(ata_std_softreset); EXPORT_SYMBOL_GPL(sata_std_hardreset); EXPORT_SYMBOL_GPL(ata_std_postreset); -EXPORT_SYMBOL_GPL(ata_std_probe_reset); -EXPORT_SYMBOL_GPL(ata_drive_probe_reset); EXPORT_SYMBOL_GPL(ata_dev_revalidate); EXPORT_SYMBOL_GPL(ata_dev_classify); EXPORT_SYMBOL_GPL(ata_dev_pair); diff --git a/include/linux/libata.h b/include/linux/libata.h index f11ba2715be..a2a33a90291 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -303,7 +303,6 @@ struct ata_queued_cmd; /* typedefs */ typedef void (*ata_qc_cb_t) (struct ata_queued_cmd *qc); -typedef void (*ata_probeinit_fn_t)(struct ata_port *ap); typedef int (*ata_prereset_fn_t)(struct ata_port *ap); typedef int (*ata_reset_fn_t)(struct ata_port *ap, unsigned int *classes); typedef void (*ata_postreset_fn_t)(struct ata_port *ap, unsigned int *classes); @@ -553,7 +552,6 @@ struct ata_port_operations { void (*phy_reset) (struct ata_port *ap); /* obsolete */ void (*set_mode) (struct ata_port *ap); - int (*probe_reset) (struct ata_port *ap, unsigned int *classes); void (*post_set_mode) (struct ata_port *ap); @@ -628,11 +626,6 @@ extern void ata_bus_reset(struct ata_port *ap); extern int sata_set_spd(struct ata_port *ap); extern int sata_phy_debounce(struct ata_port *ap, const unsigned long *param); extern int sata_phy_resume(struct ata_port *ap, const unsigned long *param); -extern int ata_drive_probe_reset(struct ata_port *ap, - ata_probeinit_fn_t probeinit, - ata_reset_fn_t softreset, ata_reset_fn_t hardreset, - ata_postreset_fn_t postreset, unsigned int *classes); -extern void ata_std_probeinit(struct ata_port *ap); extern int ata_std_prereset(struct ata_port *ap); extern int ata_std_softreset(struct ata_port *ap, unsigned int *classes); extern int sata_std_hardreset(struct ata_port *ap, unsigned int *class); @@ -688,7 +681,6 @@ extern void ata_std_dev_select (struct ata_port *ap, unsigned int device); extern u8 ata_check_status(struct ata_port *ap); extern u8 ata_altstatus(struct ata_port *ap); extern void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf); -extern int ata_std_probe_reset(struct ata_port *ap, unsigned int *classes); extern int ata_port_start (struct ata_port *ap); extern void ata_port_stop (struct ata_port *ap); extern void ata_host_stop (struct ata_host_set *host_set); -- cgit v1.2.3 From d87fa38e70853a9607dc34a02d15cf5f149f49f2 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 31 May 2006 18:28:24 +0900 Subject: [PATCH] libata-hp: move ata_do_reset() to libata-eh.c With ops->probe_init() gone, no user is left in libata-core.c. Move ata_do_reset() to libata-eh.c and make it static. Signed-off-by: Tejun Heo --- drivers/scsi/libata-core.c | 28 ---------------------------- drivers/scsi/libata-eh.c | 28 ++++++++++++++++++++++++++++ drivers/scsi/libata.h | 2 -- 3 files changed, 28 insertions(+), 30 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 30a6020c512..40d16124cc9 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2783,34 +2783,6 @@ void ata_std_postreset(struct ata_port *ap, unsigned int *classes) DPRINTK("EXIT\n"); } -int ata_do_reset(struct ata_port *ap, ata_reset_fn_t reset, - unsigned int *classes) -{ - int i, rc; - - for (i = 0; i < ATA_MAX_DEVICES; i++) - classes[i] = ATA_DEV_UNKNOWN; - - rc = reset(ap, classes); - if (rc) - return rc; - - /* If any class isn't ATA_DEV_UNKNOWN, consider classification - * is complete and convert all ATA_DEV_UNKNOWN to - * ATA_DEV_NONE. - */ - for (i = 0; i < ATA_MAX_DEVICES; i++) - if (classes[i] != ATA_DEV_UNKNOWN) - break; - - if (i < ATA_MAX_DEVICES) - for (i = 0; i < ATA_MAX_DEVICES; i++) - if (classes[i] == ATA_DEV_UNKNOWN) - classes[i] = ATA_DEV_NONE; - - return 0; -} - /** * ata_dev_same_device - Determine whether new ID matches configured device * @dev: device to compare against diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c index 30a83a57a12..d4b80b64342 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/scsi/libata-eh.c @@ -1355,6 +1355,34 @@ static void ata_eh_report(struct ata_port *ap) } } +static int ata_do_reset(struct ata_port *ap, ata_reset_fn_t reset, + unsigned int *classes) +{ + int i, rc; + + for (i = 0; i < ATA_MAX_DEVICES; i++) + classes[i] = ATA_DEV_UNKNOWN; + + rc = reset(ap, classes); + if (rc) + return rc; + + /* If any class isn't ATA_DEV_UNKNOWN, consider classification + * is complete and convert all ATA_DEV_UNKNOWN to + * ATA_DEV_NONE. + */ + for (i = 0; i < ATA_MAX_DEVICES; i++) + if (classes[i] != ATA_DEV_UNKNOWN) + break; + + if (i < ATA_MAX_DEVICES) + for (i = 0; i < ATA_MAX_DEVICES; i++) + if (classes[i] == ATA_DEV_UNKNOWN) + classes[i] = ATA_DEV_NONE; + + return 0; +} + static int ata_eh_followup_srst_needed(int rc, int classify, const unsigned int *classes) { diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index 0586b0cd73f..1dd496f1f7a 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -57,8 +57,6 @@ extern int sata_down_spd_limit(struct ata_port *ap); extern int sata_set_spd_needed(struct ata_port *ap); extern int ata_down_xfermask_limit(struct ata_device *dev, int force_pio0); extern int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev); -extern int ata_do_reset(struct ata_port *ap, ata_reset_fn_t reset, - unsigned int *classes); extern void ata_qc_free(struct ata_queued_cmd *qc); extern void ata_qc_issue(struct ata_queued_cmd *qc); extern void __ata_qc_complete(struct ata_queued_cmd *qc); -- cgit v1.2.3 From 9bf0a28c9a24e2cee5deecf89d118254374c75ba Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Thu, 27 Apr 2006 02:33:13 -0700 Subject: [SCSI] kdump: mpt fusion driver initialization failure fix MPT fusion driver initialization fails while second kernel is booting, after a system crash (if kdump kernel is configured). Oops message is pasted below. ***************************************************************************** Fusion MPT base driver 3.03.08 Copyright (c) 1999-2005 LSI Logic Corporation Fusion MPT SAS Host driver 3.03.08 ACPI: PCI Interrupt 0000:01:00.0[A] -> Link [LNKA] -> GSI 5 (level, low) -> IRQ 5 mptbase: Initiating ioc0 bringup BUG: unable to handle kernel paging request at virtual address 00002608 printing eip: c11782fd *pde = 00000000 Oops: 0000 [#1] Modules linked in: CPU: 0 EIP: 0060:[] Not tainted VLI EFLAGS: 00010046 (2.6.17-rc1-16M #2) EIP is at mptscsih_io_done+0x27/0x3a3 eax: c4fed000 ebx: c4fed000 ecx: 00002600 edx: 00000298 esi: c11782d6 edi: 00002600 ebp: 00000000 esp: c1332f74 ds: 007b es: 007b ss: 0068 Process swapper (pid: 0, threadinfo=c1332000 task=c128f9c0) Stack: <0>0000006c 00000020 00000298 00002600 c4fed000 c4fed000 c11782d6 0000260 0 00000000 c1172c49 c4fed000 c1305b40 00000005 00000000 c1172d75 c48877e0 c1029687 00000000 c1307fb8 00000000 c1305a00 00000001 00000000 c1307fb8 Call Trace: mptscsih_io_done+0x0/0x3a3 mpt_turbo_reply+0xbb/0xd3 mpt_interrupt+0x22/0x2b misrouted_irq+0x63/0xcb note_interrupt+0x43/0x98 __do_IRQ+0x68/0x8f do_IRQ+0x36/0x4e ======================= common_interrupt+0x1a/0x20 mwait_idle+0x1a/0x2a cpu_idle+0x40/0x5c start_kernel+0x17a/0x17c Code: 5e 5f 5d c3 55 89 cd 57 56 53 83 ec 14 89 54 24 0c 89 44 24 10 8b 90 cc 00 00 00 8b 4c 24 0c 81 c2 98 02 00 00 85 ed 89 54 24 08 <0f> b7 79 08 89 fe 74 04 0f b7 75 08 66 39 f7 75 0d 8b 44 24 0c ******************************************************************************* o Kdump capture kernel boot fails during initialization of MPT fusion driver. (LSI Logic / Symbios Logic SAS1064E PCI-Express Fusion-MPT SAS (rev 01)) o Problem is easily reproducible, if system crashed while some disk activity like cp operation was going on. o After a system crash, devices are not shutdown and capture kernel starts booting while skipping BIOS. Hence underlying device is left in operational state. In this case scsi contoller was left with interrupt line asserted reply FIFO was not empty. When driver starts initializing in the second kernel, it receives the interrupt the moment request_irq() is called. Interrupt handler, reads the message from reply FIFO and tries to access the associated message frame and panics, as in the new kernel's context that message frame is not valid at all. o In this scenario, probably we should delay the request_irq() call. First bring up the IOC, reset it if needed and then should register for irq. o I have tested the patch with SAS1064E and 53c1030 controllers. Signed-off-by: Vivek Goyal Signed-off-by: Andrew Morton Acked-by: "Moore, Eric Dean" Signed-off-by: James Bottomley --- drivers/message/fusion/mptbase.c | 88 +++++++++++++++++++++++----------------- 1 file changed, 50 insertions(+), 38 deletions(-) diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 266414ca281..bb7ad4d0678 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -1387,39 +1387,6 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) /* Set lookup ptr. */ list_add_tail(&ioc->list, &ioc_list); - ioc->pci_irq = -1; - if (pdev->irq) { - if (mpt_msi_enable && !pci_enable_msi(pdev)) - printk(MYIOC_s_INFO_FMT "PCI-MSI enabled\n", ioc->name); - - r = request_irq(pdev->irq, mpt_interrupt, SA_SHIRQ, ioc->name, ioc); - - if (r < 0) { -#ifndef __sparc__ - printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %d!\n", - ioc->name, pdev->irq); -#else - printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %s!\n", - ioc->name, __irq_itoa(pdev->irq)); -#endif - list_del(&ioc->list); - iounmap(mem); - kfree(ioc); - return -EBUSY; - } - - ioc->pci_irq = pdev->irq; - - pci_set_master(pdev); /* ?? */ - pci_set_drvdata(pdev, ioc); - -#ifndef __sparc__ - dprintk((KERN_INFO MYNAM ": %s installed at interrupt %d\n", ioc->name, pdev->irq)); -#else - dprintk((KERN_INFO MYNAM ": %s installed at interrupt %s\n", ioc->name, __irq_itoa(pdev->irq))); -#endif - } - /* Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets. */ mpt_detect_bound_ports(ioc, pdev); @@ -1429,11 +1396,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) printk(KERN_WARNING MYNAM ": WARNING - %s did not initialize properly! (%d)\n", ioc->name, r); - list_del(&ioc->list); - free_irq(ioc->pci_irq, ioc); - if (mpt_msi_enable) - pci_disable_msi(pdev); if (ioc->alt_ioc) ioc->alt_ioc->alt_ioc = NULL; iounmap(mem); @@ -1637,6 +1600,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) int handlers; int ret = 0; int reset_alt_ioc_active = 0; + int irq_allocated = 0; printk(KERN_INFO MYNAM ": Initiating %s %s\n", ioc->name, reason==MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery"); @@ -1720,6 +1684,48 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) } } + /* + * Device is reset now. It must have de-asserted the interrupt line + * (if it was asserted) and it should be safe to register for the + * interrupt now. + */ + if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) { + ioc->pci_irq = -1; + if (ioc->pcidev->irq) { + if (mpt_msi_enable && !pci_enable_msi(ioc->pcidev)) + printk(MYIOC_s_INFO_FMT "PCI-MSI enabled\n", + ioc->name); + rc = request_irq(ioc->pcidev->irq, mpt_interrupt, + SA_SHIRQ, ioc->name, ioc); + if (rc < 0) { +#ifndef __sparc__ + printk(MYIOC_s_ERR_FMT "Unable to allocate " + "interrupt %d!\n", ioc->name, + ioc->pcidev->irq); +#else + printk(MYIOC_s_ERR_FMT "Unable to allocate " + "interrupt %s!\n", ioc->name, + __irq_itoa(ioc->pcidev->irq)); +#endif + if (mpt_msi_enable) + pci_disable_msi(ioc->pcidev); + return -EBUSY; + } + irq_allocated = 1; + ioc->pci_irq = ioc->pcidev->irq; + pci_set_master(ioc->pcidev); /* ?? */ + pci_set_drvdata(ioc->pcidev, ioc); +#ifndef __sparc__ + dprintk((KERN_INFO MYNAM ": %s installed at interrupt " + "%d\n", ioc->name, ioc->pcidev->irq)); +#else + dprintk((KERN_INFO MYNAM ": %s installed at interrupt " + "%s\n", ioc->name, + __irq_itoa(ioc->pcidev->irq))); +#endif + } + } + /* Prime reply & request queues! * (mucho alloc's) Must be done prior to * init as upper addresses are needed for init. @@ -1819,7 +1825,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) ret = mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT); if(ret != 0) - return -1; + goto out; } /* Find IM volumes @@ -1900,6 +1906,12 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) /* FIXME? Examine results here? */ } +out: + if ((ret != 0) && irq_allocated) { + free_irq(ioc->pci_irq, ioc); + if (mpt_msi_enable) + pci_disable_msi(ioc->pcidev); + } return ret; } -- cgit v1.2.3 From 42adb53cb36d19862a02d3087e2e3d9dab39e5fa Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 1 Jun 2006 17:41:00 -0400 Subject: ACPI: Allow a WAN module enable/disable on a Thinkpad X60. The WAN (Sierra Wireless EV-DO) module is very similar to the Bluetooth module. It appears on the USB bus when enabled. It can be controlled via hot key, or directly via ACPI. This change enables direct control via ACPI. I have tested it on my Lenovo Thinkpad X60; I guess it will probably work on other Thinkpad models which come with this module installed. Signed-off-by: Jeremy Fitzhardinge Ack'd by: Borislav Deianov Signed-off-by: Len Brown --- drivers/acpi/ibm_acpi.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c index 262b1f41335..15fc12482ba 100644 --- a/drivers/acpi/ibm_acpi.c +++ b/drivers/acpi/ibm_acpi.c @@ -567,6 +567,69 @@ static int bluetooth_write(char *buf) return 0; } +static int wan_supported; + +static int wan_init(void) +{ + wan_supported = hkey_handle && + acpi_evalf(hkey_handle, NULL, "GWAN", "qv"); + + return 0; +} + +static int wan_status(void) +{ + int status; + + if (!wan_supported || + !acpi_evalf(hkey_handle, &status, "GWAN", "d")) + status = 0; + + return status; +} + +static int wan_read(char *p) +{ + int len = 0; + int status = wan_status(); + + if (!wan_supported) + len += sprintf(p + len, "status:\t\tnot supported\n"); + else if (!(status & 1)) + len += sprintf(p + len, "status:\t\tnot installed\n"); + else { + len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 1)); + len += sprintf(p + len, "commands:\tenable, disable\n"); + } + + return len; +} + +static int wan_write(char *buf) +{ + int status = wan_status(); + char *cmd; + int do_cmd = 0; + + if (!wan_supported) + return -ENODEV; + + while ((cmd = next_cmd(&buf))) { + if (strlencmp(cmd, "enable") == 0) { + status |= 2; + } else if (strlencmp(cmd, "disable") == 0) { + status &= ~2; + } else + return -EINVAL; + do_cmd = 1; + } + + if (do_cmd && !acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status)) + return -EIO; + + return 0; +} + static int video_supported; static int video_orig_autosw; @@ -1562,6 +1625,13 @@ static struct ibm_struct ibms[] = { .read = bluetooth_read, .write = bluetooth_write, }, + { + .name = "wan", + .init = wan_init, + .read = wan_read, + .write = wan_write, + .experimental = 1, + }, { .name = "video", .init = video_init, -- cgit v1.2.3 From 67a611149b2ac5f4af1e36bfffbfe3198cd3712c Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Tue, 30 May 2006 00:37:20 -0500 Subject: [SCSI] iscsi: don't switch states when just cleaning up If recovery failed or we are in recovery only overwrite the state if we are going to terminate the session or if we logged back in. STOP_CONN_SUSPEND and conn_cnt are not used. We only support a single connection session ATM, so cleanup that code while we are working around it. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/iscsi_tcp.c | 40 +++++++++++++++++------------------ drivers/scsi/libiscsi.c | 55 ++++++++++++------------------------------------ include/scsi/libiscsi.h | 1 - 3 files changed, 33 insertions(+), 63 deletions(-) diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index c66faee07ca..2abda804a92 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -1955,30 +1955,28 @@ iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session, if (err) return err; - if (conn->stop_stage != STOP_CONN_SUSPEND) { - /* bind iSCSI connection and socket */ - tcp_conn->sock = sock; + /* bind iSCSI connection and socket */ + tcp_conn->sock = sock; - /* setup Socket parameters */ - sk = sock->sk; - sk->sk_reuse = 1; - sk->sk_sndtimeo = 15 * HZ; /* FIXME: make it configurable */ - sk->sk_allocation = GFP_ATOMIC; + /* setup Socket parameters */ + sk = sock->sk; + sk->sk_reuse = 1; + sk->sk_sndtimeo = 15 * HZ; /* FIXME: make it configurable */ + sk->sk_allocation = GFP_ATOMIC; - /* FIXME: disable Nagle's algorithm */ + /* FIXME: disable Nagle's algorithm */ - /* - * Intercept TCP callbacks for sendfile like receive - * processing. - */ - conn->recv_lock = &sk->sk_callback_lock; - iscsi_conn_set_callbacks(conn); - tcp_conn->sendpage = tcp_conn->sock->ops->sendpage; - /* - * set receive state machine into initial state - */ - tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER; - } + /* + * Intercept TCP callbacks for sendfile like receive + * processing. + */ + conn->recv_lock = &sk->sk_callback_lock; + iscsi_conn_set_callbacks(conn); + tcp_conn->sendpage = tcp_conn->sock->ops->sendpage; + /* + * set receive state machine into initial state + */ + tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER; return 0; } diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index d810acae45f..96300259899 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -492,7 +492,7 @@ void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err) return; } - if (session->conn_cnt == 1 || session->leadconn == conn) + if (conn->stop_stage == 0) session->state = ISCSI_STATE_FAILED; spin_unlock_irqrestore(&session->lock, flags); set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); @@ -652,7 +652,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) */ if (session->state == ISCSI_STATE_IN_RECOVERY) { reason = FAILURE_SESSION_IN_RECOVERY; - goto fault; + goto reject; } if (session->state == ISCSI_STATE_RECOVERY_FAILED) @@ -1411,8 +1411,8 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) struct iscsi_session *session = conn->session; unsigned long flags; - mutex_lock(&conn->xmitmutex); set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); + mutex_lock(&conn->xmitmutex); if (conn->c_stage == ISCSI_CONN_INITIAL_STAGE) { if (session->tt->suspend_conn_recv) session->tt->suspend_conn_recv(conn); @@ -1498,7 +1498,6 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn) * unblock eh_abort() if it is blocked. re-try all * commands after successful recovery */ - session->conn_cnt++; conn->stop_stage = 0; conn->tmabort_state = TMABORT_INITIAL; session->age++; @@ -1508,13 +1507,7 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn) wake_up(&conn->ehwait); return 0; case STOP_CONN_TERM: - session->conn_cnt++; - conn->stop_stage = 0; - break; - case STOP_CONN_SUSPEND: conn->stop_stage = 0; - clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx); - clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); break; default: break; @@ -1589,28 +1582,24 @@ static void iscsi_start_session_recovery(struct iscsi_session *session, /* * When this is called for the in_login state, we only want to clean - * up the login task and connection. + * up the login task and connection. We do not need to block and set + * the recovery state again */ - if (conn->stop_stage != STOP_CONN_RECOVER) - session->conn_cnt--; + if (flag == STOP_CONN_TERM) + session->state = ISCSI_STATE_TERMINATE; + else if (conn->stop_stage != STOP_CONN_RECOVER) + session->state = ISCSI_STATE_IN_RECOVERY; old_stop_stage = conn->stop_stage; conn->stop_stage = flag; + conn->c_stage = ISCSI_CONN_STOPPED; + set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); spin_unlock_bh(&session->lock); if (session->tt->suspend_conn_recv) session->tt->suspend_conn_recv(conn); mutex_lock(&conn->xmitmutex); - spin_lock_bh(&session->lock); - conn->c_stage = ISCSI_CONN_STOPPED; - set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); - - if (session->conn_cnt == 0 || session->leadconn == conn) - session->state = ISCSI_STATE_IN_RECOVERY; - - spin_unlock_bh(&session->lock); - /* * for connection level recovery we should not calculate * header digest. conn->hdr_size used for optimization @@ -1620,13 +1609,11 @@ static void iscsi_start_session_recovery(struct iscsi_session *session, if (flag == STOP_CONN_RECOVER) { conn->hdrdgst_en = 0; conn->datadgst_en = 0; - /* - * if this is called from the eh and and from userspace - * then we only need to block once. - */ if (session->state == ISCSI_STATE_IN_RECOVERY && - old_stop_stage != STOP_CONN_RECOVER) + old_stop_stage != STOP_CONN_RECOVER) { + debug_scsi("blocking session\n"); iscsi_block_session(session_to_cls(session)); + } } session->tt->terminate_conn(conn); @@ -1651,20 +1638,6 @@ void iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) case STOP_CONN_TERM: iscsi_start_session_recovery(session, conn, flag); break; - case STOP_CONN_SUSPEND: - if (session->tt->suspend_conn_recv) - session->tt->suspend_conn_recv(conn); - - mutex_lock(&conn->xmitmutex); - spin_lock_bh(&session->lock); - - conn->stop_stage = flag; - conn->c_stage = ISCSI_CONN_STOPPED; - set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); - - spin_unlock_bh(&session->lock); - mutex_unlock(&conn->xmitmutex); - break; default: printk(KERN_ERR "iscsi: invalid stop flag %d\n", flag); } diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index 17b28f08b69..cbf7e58bd6f 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h @@ -211,7 +211,6 @@ struct iscsi_session { * - r2tpool */ int state; /* session state */ struct list_head item; - int conn_cnt; int age; /* counts session re-opens */ struct list_head connections; /* list of connections */ -- cgit v1.2.3 From 994442e807782d68bb1d3ae34044f95990411a22 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Tue, 30 May 2006 00:37:22 -0500 Subject: [SCSI] iscsi: fix run list corruption from davidw@netapp.com: We must grab the session lock when modifying the running lists. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/libiscsi.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 96300259899..a223413e156 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -552,8 +552,10 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) if (unlikely(__kfifo_len(conn->immqueue))) { while (__kfifo_get(conn->immqueue, (void*)&conn->mtask, sizeof(void*))) { + spin_lock_bh(&conn->session->lock); list_add_tail(&conn->mtask->running, &conn->mgmt_run_list); + spin_unlock_bh(&conn->session->lock); if (tt->xmit_mgmt_task(conn, conn->mtask)) goto again; } @@ -568,8 +570,10 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) * iscsi tcp may readd the task to the xmitqueue to send * write data */ + spin_lock_bh(&conn->session->lock); if (list_empty(&conn->ctask->running)) list_add_tail(&conn->ctask->running, &conn->run_list); + spin_unlock_bh(&conn->session->lock); if (tt->xmit_cmd_task(conn, conn->ctask)) goto again; } @@ -580,8 +584,10 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) if (unlikely(__kfifo_len(conn->mgmtqueue))) { while (__kfifo_get(conn->mgmtqueue, (void*)&conn->mtask, sizeof(void*))) { + spin_lock_bh(&conn->session->lock); list_add_tail(&conn->mtask->running, &conn->mgmt_run_list); + spin_unlock_bh(&conn->session->lock); if (tt->xmit_mgmt_task(conn, conn->mtask)) goto again; } -- cgit v1.2.3 From 040515f53c09047c76ad074dc6a280984dc84b04 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Tue, 30 May 2006 00:37:25 -0500 Subject: [SCSI] iscsi: return task found during search from davidw@netapp.com: remove task type should return a task on success. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/libiscsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index a223413e156..256b87a8597 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -985,7 +985,7 @@ iscsi_remove_##tasktype(struct kfifo *fifo, uint32_t itt) \ \ if (task->itt == itt) { \ debug_scsi("matched task\n"); \ - break; \ + return task; \ } \ \ __kfifo_put(fifo, (void*)&task, sizeof(void*)); \ -- cgit v1.2.3 From 3219e5294150aee7d389e19029f49b44fb6b5c9f Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Tue, 30 May 2006 00:37:28 -0500 Subject: [SCSI] iscsi: fix writepsace race We can race and misset the suspend bit if iscsi_write_space is called then iscsi_send returns with a failure indicating there is no space. To handle this this patch returns a error upwards allowing xmitworker to decide if we need to try and transmit again. For the no write space case xmitworker will not retry, and instead let iscsi_write_space queue it back up if needed (this relies on the work queue code to properly requeue us if needed). Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/iscsi_tcp.c | 182 ++++++++++++++++++++---------------- drivers/scsi/libiscsi.c | 31 +++--- include/scsi/scsi_transport_iscsi.h | 8 +- 3 files changed, 126 insertions(+), 95 deletions(-) diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 2abda804a92..7fa85937a99 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -1006,7 +1006,6 @@ iscsi_write_space(struct sock *sk) tcp_conn->old_write_space(sk); debug_tcp("iscsi_write_space: cid %d\n", conn->id); - clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); scsi_queue_work(conn->session->host, &conn->xmitwork); } @@ -1056,7 +1055,7 @@ iscsi_send(struct iscsi_conn *conn, struct iscsi_buf *buf, int size, int flags) { struct iscsi_tcp_conn *tcp_conn = conn->dd_data; struct socket *sk = tcp_conn->sock; - int offset = buf->sg.offset + buf->sent; + int offset = buf->sg.offset + buf->sent, res; /* * if we got use_sg=0 or are sending something we kmallocd @@ -1067,10 +1066,22 @@ iscsi_send(struct iscsi_conn *conn, struct iscsi_buf *buf, int size, int flags) * slab case. */ if (buf->use_sendmsg) - return sock_no_sendpage(sk, buf->sg.page, offset, size, flags); + res = sock_no_sendpage(sk, buf->sg.page, offset, size, flags); else - return tcp_conn->sendpage(sk, buf->sg.page, offset, size, - flags); + res = tcp_conn->sendpage(sk, buf->sg.page, offset, size, flags); + + if (res >= 0) { + conn->txdata_octets += res; + buf->sent += res; + return res; + } + + tcp_conn->sendpage_failures_cnt++; + if (res == -EAGAIN) + res = -ENOBUFS; + else + iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); + return res; } /** @@ -1085,7 +1096,6 @@ iscsi_send(struct iscsi_conn *conn, struct iscsi_buf *buf, int size, int flags) static inline int iscsi_sendhdr(struct iscsi_conn *conn, struct iscsi_buf *buf, int datalen) { - struct iscsi_tcp_conn *tcp_conn; int flags = 0; /* MSG_DONTWAIT; */ int res, size; @@ -1097,17 +1107,10 @@ iscsi_sendhdr(struct iscsi_conn *conn, struct iscsi_buf *buf, int datalen) res = iscsi_send(conn, buf, size, flags); debug_tcp("sendhdr %d bytes, sent %d res %d\n", size, buf->sent, res); if (res >= 0) { - conn->txdata_octets += res; - buf->sent += res; if (size != res) return -EAGAIN; return 0; - } else if (res == -EAGAIN) { - tcp_conn = conn->dd_data; - tcp_conn->sendpage_failures_cnt++; - set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); - } else if (res == -EPIPE) - iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); + } return res; } @@ -1126,7 +1129,6 @@ static inline int iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf, int *count, int *sent) { - struct iscsi_tcp_conn *tcp_conn; int flags = 0; /* MSG_DONTWAIT; */ int res, size; @@ -1141,19 +1143,12 @@ iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf, debug_tcp("sendpage: %d bytes, sent %d left %d sent %d res %d\n", size, buf->sent, *count, *sent, res); if (res >= 0) { - conn->txdata_octets += res; - buf->sent += res; *count -= res; *sent += res; if (size != res) return -EAGAIN; return 0; - } else if (res == -EAGAIN) { - tcp_conn = conn->dd_data; - tcp_conn->sendpage_failures_cnt++; - set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); - } else if (res == -EPIPE) - iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); + } return res; } @@ -1342,6 +1337,7 @@ static int iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) { struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data; + int rc; debug_scsi("mtask deq [cid %d state %x itt 0x%x]\n", conn->id, tcp_mtask->xmstate, mtask->itt); @@ -1355,12 +1351,13 @@ iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) conn->hdrdgst_en) iscsi_hdr_digest(conn, &tcp_mtask->headbuf, (u8*)tcp_mtask->hdrext); - if (iscsi_sendhdr(conn, &tcp_mtask->headbuf, - mtask->data_count)) { + rc = iscsi_sendhdr(conn, &tcp_mtask->headbuf, + mtask->data_count); + if (rc) { tcp_mtask->xmstate |= XMSTATE_IMM_HDR; if (mtask->data_count) tcp_mtask->xmstate &= ~XMSTATE_IMM_DATA; - return -EAGAIN; + return rc; } } @@ -1371,10 +1368,13 @@ iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) * Virtual buffer could be spreaded across multiple pages... */ do { - if (iscsi_sendpage(conn, &tcp_mtask->sendbuf, - &mtask->data_count, &tcp_mtask->sent)) { + int rc; + + rc = iscsi_sendpage(conn, &tcp_mtask->sendbuf, + &mtask->data_count, &tcp_mtask->sent); + if (rc) { tcp_mtask->xmstate |= XMSTATE_IMM_DATA; - return -EAGAIN; + return rc; } } while (mtask->data_count); } @@ -1396,16 +1396,19 @@ static inline int handle_xmstate_r_hdr(struct iscsi_conn *conn, struct iscsi_tcp_cmd_task *tcp_ctask) { + int rc; + tcp_ctask->xmstate &= ~XMSTATE_R_HDR; if (conn->hdrdgst_en) iscsi_hdr_digest(conn, &tcp_ctask->headbuf, (u8*)tcp_ctask->hdrext); - if (!iscsi_sendhdr(conn, &tcp_ctask->headbuf, 0)) { + rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, 0); + if (!rc) { BUG_ON(tcp_ctask->xmstate != XMSTATE_IDLE); return 0; /* wait for Data-In */ } tcp_ctask->xmstate |= XMSTATE_R_HDR; - return -EAGAIN; + return rc; } static inline int @@ -1413,16 +1416,16 @@ handle_xmstate_w_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; + int rc; tcp_ctask->xmstate &= ~XMSTATE_W_HDR; if (conn->hdrdgst_en) iscsi_hdr_digest(conn, &tcp_ctask->headbuf, (u8*)tcp_ctask->hdrext); - if (iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->imm_count)) { + rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->imm_count); + if (rc) tcp_ctask->xmstate |= XMSTATE_W_HDR; - return -EAGAIN; - } - return 0; + return rc; } static inline int @@ -1430,17 +1433,19 @@ handle_xmstate_data_digest(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; + int rc; tcp_ctask->xmstate &= ~XMSTATE_DATA_DIGEST; debug_tcp("resent data digest 0x%x\n", tcp_ctask->datadigest); - if (iscsi_digest_final_send(conn, ctask, &tcp_ctask->immbuf, - &tcp_ctask->datadigest, 0)) { + rc = iscsi_digest_final_send(conn, ctask, &tcp_ctask->immbuf, + &tcp_ctask->datadigest, 0); + if (rc) { tcp_ctask->xmstate |= XMSTATE_DATA_DIGEST; debug_tcp("resent data digest 0x%x fail!\n", tcp_ctask->datadigest); - return -EAGAIN; } - return 0; + + return rc; } static inline int @@ -1448,6 +1453,7 @@ handle_xmstate_imm_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; struct iscsi_tcp_conn *tcp_conn = conn->dd_data; + int rc; BUG_ON(!ctask->imm_count); tcp_ctask->xmstate &= ~XMSTATE_IMM_DATA; @@ -1458,8 +1464,9 @@ handle_xmstate_imm_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) } for (;;) { - if (iscsi_sendpage(conn, &tcp_ctask->sendbuf, &ctask->imm_count, - &tcp_ctask->sent)) { + rc = iscsi_sendpage(conn, &tcp_ctask->sendbuf, + &ctask->imm_count, &tcp_ctask->sent); + if (rc) { tcp_ctask->xmstate |= XMSTATE_IMM_DATA; if (conn->datadgst_en) { crypto_digest_final(tcp_conn->data_tx_tfm, @@ -1467,7 +1474,7 @@ handle_xmstate_imm_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) debug_tcp("tx imm sendpage fail 0x%x\n", tcp_ctask->datadigest); } - return -EAGAIN; + return rc; } if (conn->datadgst_en) crypto_digest_update(tcp_conn->data_tx_tfm, @@ -1480,11 +1487,12 @@ handle_xmstate_imm_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) } if (conn->datadgst_en && !(tcp_ctask->xmstate & XMSTATE_W_PAD)) { - if (iscsi_digest_final_send(conn, ctask, &tcp_ctask->immbuf, - &tcp_ctask->immdigest, 1)) { + rc = iscsi_digest_final_send(conn, ctask, &tcp_ctask->immbuf, + &tcp_ctask->immdigest, 1); + if (rc) { debug_tcp("sending imm digest 0x%x fail!\n", tcp_ctask->immdigest); - return -EAGAIN; + return rc; } debug_tcp("sending imm digest 0x%x\n", tcp_ctask->immdigest); } @@ -1497,6 +1505,7 @@ handle_xmstate_uns_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; struct iscsi_data_task *dtask; + int rc; tcp_ctask->xmstate |= XMSTATE_UNS_DATA; if (tcp_ctask->xmstate & XMSTATE_UNS_INIT) { @@ -1507,10 +1516,12 @@ handle_xmstate_uns_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) (u8*)dtask->hdrext); tcp_ctask->xmstate &= ~XMSTATE_UNS_INIT; } - if (iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->data_count)) { + + rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->data_count); + if (rc) { tcp_ctask->xmstate &= ~XMSTATE_UNS_DATA; tcp_ctask->xmstate |= XMSTATE_UNS_HDR; - return -EAGAIN; + return rc; } debug_scsi("uns dout [itt 0x%x dlen %d sent %d]\n", @@ -1524,6 +1535,7 @@ handle_xmstate_uns_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; struct iscsi_data_task *dtask = tcp_ctask->dtask; struct iscsi_tcp_conn *tcp_conn = conn->dd_data; + int rc; BUG_ON(!ctask->data_count); tcp_ctask->xmstate &= ~XMSTATE_UNS_DATA; @@ -1536,8 +1548,9 @@ handle_xmstate_uns_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) for (;;) { int start = tcp_ctask->sent; - if (iscsi_sendpage(conn, &tcp_ctask->sendbuf, - &ctask->data_count, &tcp_ctask->sent)) { + rc = iscsi_sendpage(conn, &tcp_ctask->sendbuf, + &ctask->data_count, &tcp_ctask->sent); + if (rc) { ctask->unsol_count -= tcp_ctask->sent - start; tcp_ctask->xmstate |= XMSTATE_UNS_DATA; /* will continue with this ctask later.. */ @@ -1547,7 +1560,7 @@ handle_xmstate_uns_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) debug_tcp("tx uns data fail 0x%x\n", dtask->digest); } - return -EAGAIN; + return rc; } BUG_ON(tcp_ctask->sent > ctask->total_length); @@ -1574,12 +1587,13 @@ handle_xmstate_uns_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) */ if (ctask->unsol_count) { if (conn->datadgst_en) { - if (iscsi_digest_final_send(conn, ctask, + rc = iscsi_digest_final_send(conn, ctask, &dtask->digestbuf, - &dtask->digest, 1)) { + &dtask->digest, 1); + if (rc) { debug_tcp("send uns digest 0x%x fail\n", dtask->digest); - return -EAGAIN; + return rc; } debug_tcp("sending uns digest 0x%x, more uns\n", dtask->digest); @@ -1589,12 +1603,13 @@ handle_xmstate_uns_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) } if (conn->datadgst_en && !(tcp_ctask->xmstate & XMSTATE_W_PAD)) { - if (iscsi_digest_final_send(conn, ctask, + rc = iscsi_digest_final_send(conn, ctask, &dtask->digestbuf, - &dtask->digest, 1)) { + &dtask->digest, 1); + if (rc) { debug_tcp("send last uns digest 0x%x fail\n", dtask->digest); - return -EAGAIN; + return rc; } debug_tcp("sending uns digest 0x%x\n",dtask->digest); } @@ -1610,7 +1625,7 @@ handle_xmstate_sol_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; struct iscsi_r2t_info *r2t = tcp_ctask->r2t; struct iscsi_data_task *dtask = &r2t->dtask; - int left; + int left, rc; tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA; tcp_ctask->dtask = dtask; @@ -1626,7 +1641,8 @@ solicit_again: if (!r2t->data_count) goto data_out_done; - if (iscsi_sendpage(conn, &r2t->sendbuf, &r2t->data_count, &r2t->sent)) { + rc = iscsi_sendpage(conn, &r2t->sendbuf, &r2t->data_count, &r2t->sent); + if (rc) { tcp_ctask->xmstate |= XMSTATE_SOL_DATA; /* will continue with this ctask later.. */ if (conn->datadgst_en) { @@ -1634,7 +1650,7 @@ solicit_again: (u8 *)&dtask->digest); debug_tcp("r2t data send fail 0x%x\n", dtask->digest); } - return -EAGAIN; + return rc; } BUG_ON(r2t->data_count < 0); @@ -1661,12 +1677,13 @@ data_out_done: left = r2t->data_length - r2t->sent; if (left) { if (conn->datadgst_en) { - if (iscsi_digest_final_send(conn, ctask, + rc = iscsi_digest_final_send(conn, ctask, &dtask->digestbuf, - &dtask->digest, 1)) { + &dtask->digest, 1); + if (rc) { debug_tcp("send r2t data digest 0x%x" "fail\n", dtask->digest); - return -EAGAIN; + return rc; } debug_tcp("r2t data send digest 0x%x\n", dtask->digest); @@ -1683,11 +1700,12 @@ data_out_done: */ BUG_ON(tcp_ctask->r2t_data_count - r2t->data_length < 0); if (conn->datadgst_en) { - if (iscsi_digest_final_send(conn, ctask, &dtask->digestbuf, - &dtask->digest, 1)) { + rc = iscsi_digest_final_send(conn, ctask, &dtask->digestbuf, + &dtask->digest, 1); + if (rc) { debug_tcp("send last r2t data digest 0x%x" "fail\n", dtask->digest); - return -EAGAIN; + return rc; } debug_tcp("r2t done dout digest 0x%x\n", dtask->digest); } @@ -1713,15 +1731,16 @@ handle_xmstate_w_pad(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; struct iscsi_tcp_conn *tcp_conn = conn->dd_data; struct iscsi_data_task *dtask = tcp_ctask->dtask; - int sent; + int sent, rc; tcp_ctask->xmstate &= ~XMSTATE_W_PAD; iscsi_buf_init_iov(&tcp_ctask->sendbuf, (char*)&tcp_ctask->pad, tcp_ctask->pad_count); - if (iscsi_sendpage(conn, &tcp_ctask->sendbuf, &tcp_ctask->pad_count, - &sent)) { + rc = iscsi_sendpage(conn, &tcp_ctask->sendbuf, &tcp_ctask->pad_count, + &sent); + if (rc) { tcp_ctask->xmstate |= XMSTATE_W_PAD; - return -EAGAIN; + return rc; } if (conn->datadgst_en) { @@ -1729,22 +1748,24 @@ handle_xmstate_w_pad(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) &tcp_ctask->sendbuf.sg, 1); /* imm data? */ if (!dtask) { - if (iscsi_digest_final_send(conn, ctask, + rc = iscsi_digest_final_send(conn, ctask, &tcp_ctask->immbuf, - &tcp_ctask->immdigest, 1)) { + &tcp_ctask->immdigest, 1); + if (rc) { debug_tcp("send padding digest 0x%x" "fail!\n", tcp_ctask->immdigest); - return -EAGAIN; + return rc; } debug_tcp("done with padding, digest 0x%x\n", tcp_ctask->datadigest); } else { - if (iscsi_digest_final_send(conn, ctask, + rc = iscsi_digest_final_send(conn, ctask, &dtask->digestbuf, - &dtask->digest, 1)) { + &dtask->digest, 1); + if (rc) { debug_tcp("send padding digest 0x%x" "fail\n", dtask->digest); - return -EAGAIN; + return rc; } debug_tcp("done with padding, digest 0x%x\n", dtask->digest); @@ -1769,10 +1790,8 @@ iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) if (ctask->mtask) return rc; - if (tcp_ctask->xmstate & XMSTATE_R_HDR) { - rc = handle_xmstate_r_hdr(conn, tcp_ctask); - return rc; - } + if (tcp_ctask->xmstate & XMSTATE_R_HDR) + return handle_xmstate_r_hdr(conn, tcp_ctask); if (tcp_ctask->xmstate & XMSTATE_W_HDR) { rc = handle_xmstate_w_hdr(conn, ctask); @@ -1824,10 +1843,11 @@ solicit_head_again: if (conn->hdrdgst_en) iscsi_hdr_digest(conn, &r2t->headbuf, (u8*)r2t->dtask.hdrext); - if (iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count)) { + rc = iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count); + if (rc) { tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA; tcp_ctask->xmstate |= XMSTATE_SOL_HDR; - return -EAGAIN; + return rc; } debug_scsi("sol dout [dsn %d itt 0x%x dlen %d sent %d]\n", diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 256b87a8597..2673a11a949 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -513,10 +513,11 @@ EXPORT_SYMBOL_GPL(iscsi_conn_failure); static int iscsi_data_xmit(struct iscsi_conn *conn) { struct iscsi_transport *tt; + int rc = 0; if (unlikely(conn->suspend_tx)) { debug_scsi("conn %d Tx suspended!\n", conn->id); - return 0; + return -ENODATA; } tt = conn->session->tt; @@ -536,13 +537,15 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) BUG_ON(conn->ctask && conn->mtask); if (conn->ctask) { - if (tt->xmit_cmd_task(conn, conn->ctask)) + rc = tt->xmit_cmd_task(conn, conn->ctask); + if (rc) goto again; /* done with this in-progress ctask */ conn->ctask = NULL; } if (conn->mtask) { - if (tt->xmit_mgmt_task(conn, conn->mtask)) + rc = tt->xmit_mgmt_task(conn, conn->mtask); + if (rc) goto again; /* done with this in-progress mtask */ conn->mtask = NULL; @@ -556,7 +559,8 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) list_add_tail(&conn->mtask->running, &conn->mgmt_run_list); spin_unlock_bh(&conn->session->lock); - if (tt->xmit_mgmt_task(conn, conn->mtask)) + rc = tt->xmit_mgmt_task(conn, conn->mtask); + if (rc) goto again; } /* done with this mtask */ @@ -574,7 +578,8 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) if (list_empty(&conn->ctask->running)) list_add_tail(&conn->ctask->running, &conn->run_list); spin_unlock_bh(&conn->session->lock); - if (tt->xmit_cmd_task(conn, conn->ctask)) + rc = tt->xmit_cmd_task(conn, conn->ctask); + if (rc) goto again; } /* done with this ctask */ @@ -588,32 +593,34 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) list_add_tail(&conn->mtask->running, &conn->mgmt_run_list); spin_unlock_bh(&conn->session->lock); - if (tt->xmit_mgmt_task(conn, conn->mtask)) + rc = tt->xmit_mgmt_task(conn, conn->mtask); + if (rc) goto again; } /* done with this mtask */ conn->mtask = NULL; } - return 0; + return -ENODATA; again: if (unlikely(conn->suspend_tx)) - return 0; + return -ENODATA; - return -EAGAIN; + return rc; } static void iscsi_xmitworker(void *data) { struct iscsi_conn *conn = data; - + int rc; /* * serialize Xmit worker on a per-connection basis. */ mutex_lock(&conn->xmitmutex); - if (iscsi_data_xmit(conn)) - scsi_queue_work(conn->session->host, &conn->xmitwork); + do { + rc = iscsi_data_xmit(conn); + } while (rc >= 0 || rc == -EAGAIN); mutex_unlock(&conn->xmitmutex); } diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index 92129b97d31..b684426a590 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -57,8 +57,12 @@ struct iscsi_mgmt_task; * Called from queuecommand with session lock held. * @init_mgmt_task: Initialize a iscsi_mgmt_task and any internal structs. * Called from iscsi_conn_send_generic with xmitmutex. - * @xmit_cmd_task: requests LLD to transfer cmd task - * @xmit_mgmt_task: requests LLD to transfer mgmt task + * @xmit_cmd_task: Requests LLD to transfer cmd task. Returns 0 or the + * the number of bytes transferred on success, and -Exyz + * value on error. + * @xmit_mgmt_task: Requests LLD to transfer mgmt task. Returns 0 or the + * the number of bytes transferred on success, and -Exyz + * value on error. * @cleanup_cmd_task: requests LLD to fail cmd task. Called with xmitmutex * and session->lock after the connection has been * suspended and terminated during recovery. If called -- cgit v1.2.3 From f70e9c5f91f1d2d9ce79dc45221540e25b4e4ac0 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Tue, 30 May 2006 01:04:51 -0500 Subject: [SCSI] iscsi: update version to 1.0-595 Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/iscsi_tcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 7fa85937a99..b4743a9ecc8 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -43,7 +43,7 @@ #include "iscsi_tcp.h" -#define ISCSI_TCP_VERSION "1.0-574" +#define ISCSI_TCP_VERSION "1.0-595" MODULE_AUTHOR("Dmitry Yusupov , " "Alex Aizman "); -- cgit v1.2.3 From e4a082c7c1f9a7b11fece6918e7ee5519b39ac46 Mon Sep 17 00:00:00 2001 From: Sumant Patro Date: Tue, 30 May 2006 12:03:37 -0700 Subject: [SCSI] megaraid_sas: switch fw_outstanding to an atomic_t This patch( originally submitted by Christoph Hellwig) removes instance_lock and changes fw_outstanding variable data type to atomic_t. Signed-off-by: Sumant Patro Signed-off-by: James Bottomley --- Documentation/scsi/ChangeLog.megaraid_sas | 13 +++++++++++++ drivers/scsi/megaraid/megaraid_sas.c | 26 ++++++++++---------------- drivers/scsi/megaraid/megaraid_sas.h | 3 +-- 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/Documentation/scsi/ChangeLog.megaraid_sas b/Documentation/scsi/ChangeLog.megaraid_sas index 2dafa63bd37..0a85a7e8120 100644 --- a/Documentation/scsi/ChangeLog.megaraid_sas +++ b/Documentation/scsi/ChangeLog.megaraid_sas @@ -1,3 +1,16 @@ + +1 Release Date : Wed Feb 03 14:31:44 PST 2006 - Sumant Patro +2 Current Version : 00.00.02.04 +3 Older Version : 00.00.02.04 + +i. Remove superflous instance_lock + + gets rid of the otherwise superflous instance_lock and avoids an unsave + unsynchronized access in the error handler. + + - Christoph Hellwig + + 1 Release Date : Wed Feb 03 14:31:44 PST 2006 - Sumant Patro 2 Current Version : 00.00.02.04 3 Older Version : 00.00.02.04 diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index 39729460b00..0c9516ff636 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c @@ -741,7 +741,6 @@ static int megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *)) { u32 frame_count; - unsigned long flags; struct megasas_cmd *cmd; struct megasas_instance *instance; @@ -776,9 +775,7 @@ megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *)) /* * Issue the command to the FW */ - spin_lock_irqsave(&instance->instance_lock, flags); - instance->fw_outstanding++; - spin_unlock_irqrestore(&instance->instance_lock, flags); + atomic_inc(&instance->fw_outstanding); instance->instancet->fire_cmd(cmd->frame_phys_addr ,cmd->frame_count-1,instance->reg_set); @@ -826,19 +823,20 @@ static int megasas_wait_for_outstanding(struct megasas_instance *instance) for (i = 0; i < wait_time; i++) { - if (!instance->fw_outstanding) + int outstanding = atomic_read(&instance->fw_outstanding); + + if (!outstanding) break; if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) { printk(KERN_NOTICE "megasas: [%2d]waiting for %d " - "commands to complete\n", i, - instance->fw_outstanding); + "commands to complete\n",i,outstanding); } msleep(1000); } - if (instance->fw_outstanding) { + if (atomic_read(&instance->fw_outstanding)) { instance->hw_crit_error = 1; return FAILED; } @@ -1050,7 +1048,6 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, { int exception = 0; struct megasas_header *hdr = &cmd->frame->hdr; - unsigned long flags; if (cmd->scmd) { cmd->scmd->SCp.ptr = (char *)0; @@ -1082,9 +1079,7 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, if (exception) { - spin_lock_irqsave(&instance->instance_lock, flags); - instance->fw_outstanding--; - spin_unlock_irqrestore(&instance->instance_lock, flags); + atomic_dec(&instance->fw_outstanding); megasas_unmap_sgbuf(instance, cmd); cmd->scmd->scsi_done(cmd->scmd); @@ -1132,9 +1127,7 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, break; } - spin_lock_irqsave(&instance->instance_lock, flags); - instance->fw_outstanding--; - spin_unlock_irqrestore(&instance->instance_lock, flags); + atomic_dec(&instance->fw_outstanding); megasas_unmap_sgbuf(instance, cmd); cmd->scmd->scsi_done(cmd->scmd); @@ -2171,11 +2164,12 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) */ INIT_LIST_HEAD(&instance->cmd_pool); + atomic_set(&instance->fw_outstanding,0); + init_waitqueue_head(&instance->int_cmd_wait_q); init_waitqueue_head(&instance->abort_cmd_wait_q); spin_lock_init(&instance->cmd_pool_lock); - spin_lock_init(&instance->instance_lock); sema_init(&instance->aen_mutex, 1); sema_init(&instance->ioctl_sem, MEGASAS_INT_CMDS); diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index 89639f0c38e..927d6ffef05 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -1077,9 +1077,8 @@ struct megasas_instance { struct pci_dev *pdev; u32 unique_id; - u32 fw_outstanding; + atomic_t fw_outstanding; u32 hw_crit_error; - spinlock_t instance_lock; struct megasas_instance_template *instancet; }; -- cgit v1.2.3 From 5d5ff44fe6775ccb922fd1f7d478b2ba9ca95068 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sat, 3 Jun 2006 13:21:13 +0200 Subject: [SCSI] fix up request buffer reference in various scsi drivers Various scsi drivers use scsi_cmnd.buffer and scsi_cmnd.bufflen in their queuecommand functions. Those fields are internal storage for the midlayer only and are used to restore the original payload after request_buffer and request_bufflen have been overwritten for EH. Using the buffer and bufflen fields means they do very broken things in error handling. Signed-off-by: Christoph Hellwig Signed-off-by: James Bottomley --- drivers/block/cciss_scsi.c | 6 +++--- drivers/scsi/3w-9xxx.c | 2 +- drivers/scsi/3w-xxxx.c | 2 +- drivers/scsi/NCR5380.c | 2 +- drivers/scsi/aacraid/aachba.c | 4 ++-- drivers/scsi/atp870u.c | 2 +- drivers/scsi/gdth.c | 2 +- drivers/scsi/in2000.c | 2 +- drivers/scsi/ips.c | 2 +- drivers/scsi/libata-scsi.c | 4 ++-- drivers/scsi/megaraid.c | 4 ++-- drivers/scsi/ncr53c8xx.c | 6 +++--- drivers/scsi/nsp32.c | 2 +- drivers/scsi/sd.c | 2 +- drivers/scsi/sr.c | 2 +- drivers/scsi/sym53c8xx_2/sym_glue.c | 6 +++--- drivers/usb/image/microtek.c | 10 +++++----- 17 files changed, 30 insertions(+), 30 deletions(-) diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index 597c007fe81..afdff32f672 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c @@ -578,7 +578,7 @@ complete_scsi_command( CommandList_struct *cp, int timeout, __u32 tag) if (cmd->use_sg) { pci_unmap_sg(ctlr->pdev, - cmd->buffer, cmd->use_sg, + cmd->request_buffer, cmd->use_sg, cmd->sc_data_direction); } else if (cmd->request_bufflen) { @@ -1210,7 +1210,7 @@ cciss_scatter_gather(struct pci_dev *pdev, struct scsi_cmnd *cmd) { unsigned int use_sg, nsegs=0, len; - struct scatterlist *scatter = (struct scatterlist *) cmd->buffer; + struct scatterlist *scatter = (struct scatterlist *) cmd->request_buffer; __u64 addr64; /* is it just one virtual address? */ @@ -1232,7 +1232,7 @@ cciss_scatter_gather(struct pci_dev *pdev, } /* else, must be a list of virtual addresses.... */ else if (cmd->use_sg <= MAXSGENTRIES) { /* not too many addrs? */ - use_sg = pci_map_sg(pdev, cmd->buffer, cmd->use_sg, + use_sg = pci_map_sg(pdev, cmd->request_buffer, cmd->use_sg, cmd->sc_data_direction); for (nsegs=0; nsegs < use_sg; nsegs++) { diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c index caeb6d246e5..b003baf8d40 100644 --- a/drivers/scsi/3w-9xxx.c +++ b/drivers/scsi/3w-9xxx.c @@ -1388,7 +1388,7 @@ static int twa_map_scsi_sg_data(TW_Device_Extension *tw_dev, int request_id) if (cmd->use_sg == 0) goto out; - use_sg = pci_map_sg(pdev, cmd->buffer, cmd->use_sg, DMA_BIDIRECTIONAL); + use_sg = pci_map_sg(pdev, cmd->request_buffer, cmd->use_sg, DMA_BIDIRECTIONAL); if (use_sg == 0) { TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1c, "Failed to map scatter gather list"); diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c index e8e41e6eb42..37a58c6dad2 100644 --- a/drivers/scsi/3w-xxxx.c +++ b/drivers/scsi/3w-xxxx.c @@ -1286,7 +1286,7 @@ static int tw_map_scsi_sg_data(struct pci_dev *pdev, struct scsi_cmnd *cmd) if (cmd->use_sg == 0) return 0; - use_sg = pci_map_sg(pdev, cmd->buffer, cmd->use_sg, DMA_BIDIRECTIONAL); + use_sg = pci_map_sg(pdev, cmd->request_buffer, cmd->use_sg, DMA_BIDIRECTIONAL); if (use_sg == 0) { printk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data(): pci_map_sg() failed.\n"); diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 9f0ddbe6dc7..fa57e0b4a5f 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -296,7 +296,7 @@ static __inline__ void initialize_SCp(Scsi_Cmnd * cmd) */ if (cmd->use_sg) { - cmd->SCp.buffer = (struct scatterlist *) cmd->buffer; + cmd->SCp.buffer = (struct scatterlist *) cmd->request_buffer; cmd->SCp.buffers_residual = cmd->use_sg - 1; cmd->SCp.ptr = page_address(cmd->SCp.buffer->page)+ cmd->SCp.buffer->offset; diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index be8dde4c0f0..e4b38f896cb 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -961,7 +961,7 @@ static void io_callback(void *context, struct fib * fibptr) if(scsicmd->use_sg) pci_unmap_sg(dev->pdev, - (struct scatterlist *)scsicmd->buffer, + (struct scatterlist *)scsicmd->request_buffer, scsicmd->use_sg, scsicmd->sc_data_direction); else if(scsicmd->request_bufflen) @@ -1919,7 +1919,7 @@ static void aac_srb_callback(void *context, struct fib * fibptr) if(scsicmd->use_sg) pci_unmap_sg(dev->pdev, - (struct scatterlist *)scsicmd->buffer, + (struct scatterlist *)scsicmd->request_buffer, scsicmd->use_sg, scsicmd->sc_data_direction); else if(scsicmd->request_bufflen) diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c index 58d7e34807a..3ee4d4d3f44 100644 --- a/drivers/scsi/atp870u.c +++ b/drivers/scsi/atp870u.c @@ -473,7 +473,7 @@ go_42: */ if (workreq->use_sg) { pci_unmap_sg(dev->pdev, - (struct scatterlist *)workreq->buffer, + (struct scatterlist *)workreq->request_buffer, workreq->use_sg, workreq->sc_data_direction); } else if (workreq->request_bufflen && diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index d5740bbdef3..9b918fd43bf 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c @@ -2542,7 +2542,7 @@ static void gdth_copy_internal_data(int hanum,Scsi_Cmnd *scp, gdth_ha_str *ha; char *address; - cpcount = count<=(ushort)scp->bufflen ? count:(ushort)scp->bufflen; + cpcount = count<=(ushort)scp->request_bufflen ? count:(ushort)scp->request_bufflen; ha = HADATA(gdth_ctr_tab[hanum]); if (scp->use_sg) { diff --git a/drivers/scsi/in2000.c b/drivers/scsi/in2000.c index 9c519876f8a..89a57a62e8c 100644 --- a/drivers/scsi/in2000.c +++ b/drivers/scsi/in2000.c @@ -370,7 +370,7 @@ static int in2000_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) */ if (cmd->use_sg) { - cmd->SCp.buffer = (struct scatterlist *) cmd->buffer; + cmd->SCp.buffer = (struct scatterlist *) cmd->request_buffer; cmd->SCp.buffers_residual = cmd->use_sg - 1; cmd->SCp.ptr = (char *) page_address(cmd->SCp.buffer->page) + cmd->SCp.buffer->offset; cmd->SCp.this_residual = cmd->SCp.buffer->length; diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index a4c0b04cfdb..350c08c6088 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c @@ -4364,7 +4364,7 @@ ips_rdcap(ips_ha_t * ha, ips_scb_t * scb) METHOD_TRACE("ips_rdcap", 1); - if (scb->scsi_cmd->bufflen < 8) + if (scb->scsi_cmd->request_bufflen < 8) return (0); cap.lba = diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index a0289ec3e28..994015726ec 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -2310,7 +2310,7 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd) #endif } - qc->nbytes = cmd->bufflen; + qc->nbytes = cmd->request_bufflen; return 0; } @@ -2500,7 +2500,7 @@ ata_scsi_pass_thru(struct ata_queued_cmd *qc, const u8 *scsicmd) * TODO: find out if we need to do more here to * cover scatter/gather case. */ - qc->nsect = cmd->bufflen / ATA_SECT_SIZE; + qc->nsect = cmd->request_bufflen / ATA_SECT_SIZE; return 0; diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index 80b68a2481b..d245717fee6 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c @@ -524,7 +524,7 @@ mega_build_cmd(adapter_t *adapter, Scsi_Cmnd *cmd, int *busy) * filter the internal and ioctl commands */ if((cmd->cmnd[0] == MEGA_INTERNAL_CMD)) { - return cmd->buffer; + return cmd->request_buffer; } @@ -4493,7 +4493,7 @@ mega_internal_command(adapter_t *adapter, megacmd_t *mc, mega_passthru *pthru) scmd->device = sdev; scmd->device->host = adapter->host; - scmd->buffer = (void *)scb; + scmd->request_buffer = (void *)scb; scmd->cmnd[0] = MEGA_INTERNAL_CMD; scb->state |= SCB_ACTIVE; diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c index 22f913127f0..6ab035590ee 100644 --- a/drivers/scsi/ncr53c8xx.c +++ b/drivers/scsi/ncr53c8xx.c @@ -529,7 +529,7 @@ static void __unmap_scsi_data(struct device *dev, struct scsi_cmnd *cmd) { switch(cmd->__data_mapped) { case 2: - dma_unmap_sg(dev, cmd->buffer, cmd->use_sg, + dma_unmap_sg(dev, cmd->request_buffer, cmd->use_sg, cmd->sc_data_direction); break; case 1: @@ -564,7 +564,7 @@ static int __map_scsi_sg_data(struct device *dev, struct scsi_cmnd *cmd) if (cmd->use_sg == 0) return 0; - use_sg = dma_map_sg(dev, cmd->buffer, cmd->use_sg, + use_sg = dma_map_sg(dev, cmd->request_buffer, cmd->use_sg, cmd->sc_data_direction); cmd->__data_mapped = 2; cmd->__data_mapping = use_sg; @@ -7697,7 +7697,7 @@ static int ncr_scatter(struct ncb *np, struct ccb *cp, struct scsi_cmnd *cmd) if (!use_sg) segment = ncr_scatter_no_sglist(np, cp, cmd); else if ((use_sg = map_scsi_sg_data(np, cmd)) > 0) { - struct scatterlist *scatter = (struct scatterlist *)cmd->buffer; + struct scatterlist *scatter = (struct scatterlist *)cmd->request_buffer; struct scr_tblmove *data; if (use_sg > MAX_SCATTER) { diff --git a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c index 30ee0ef4b45..5c55e152e71 100644 --- a/drivers/scsi/nsp32.c +++ b/drivers/scsi/nsp32.c @@ -1636,7 +1636,7 @@ static void nsp32_scsi_done(struct scsi_cmnd *SCpnt) if (SCpnt->use_sg) { pci_unmap_sg(data->Pci, - (struct scatterlist *)SCpnt->buffer, + (struct scatterlist *)SCpnt->request_buffer, SCpnt->use_sg, SCpnt->sc_data_direction); } else { pci_unmap_single(data->Pci, diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index c647d85d97d..a112e49e946 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -891,7 +891,7 @@ static struct block_device_operations sd_fops = { static void sd_rw_intr(struct scsi_cmnd * SCpnt) { int result = SCpnt->result; - int this_count = SCpnt->bufflen; + int this_count = SCpnt->request_bufflen; int good_bytes = (result == 0 ? this_count : 0); sector_t block_sectors = 1; u64 first_err_block; diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 7c80711e18e..ebf6579ed69 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -217,7 +217,7 @@ int sr_media_change(struct cdrom_device_info *cdi, int slot) static void rw_intr(struct scsi_cmnd * SCpnt) { int result = SCpnt->result; - int this_count = SCpnt->bufflen; + int this_count = SCpnt->request_bufflen; int good_bytes = (result == 0 ? this_count : 0); int block_sectors = 0; long error_sector; diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index 9c83b4d39a2..ee081320e1f 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -156,7 +156,7 @@ static void __unmap_scsi_data(struct pci_dev *pdev, struct scsi_cmnd *cmd) switch(SYM_UCMD_PTR(cmd)->data_mapped) { case 2: - pci_unmap_sg(pdev, cmd->buffer, cmd->use_sg, dma_dir); + pci_unmap_sg(pdev, cmd->request_buffer, cmd->use_sg, dma_dir); break; case 1: pci_unmap_single(pdev, SYM_UCMD_PTR(cmd)->data_mapping, @@ -186,7 +186,7 @@ static int __map_scsi_sg_data(struct pci_dev *pdev, struct scsi_cmnd *cmd) int use_sg; int dma_dir = cmd->sc_data_direction; - use_sg = pci_map_sg(pdev, cmd->buffer, cmd->use_sg, dma_dir); + use_sg = pci_map_sg(pdev, cmd->request_buffer, cmd->use_sg, dma_dir); if (use_sg > 0) { SYM_UCMD_PTR(cmd)->data_mapped = 2; SYM_UCMD_PTR(cmd)->data_mapping = use_sg; @@ -376,7 +376,7 @@ static int sym_scatter(struct sym_hcb *np, struct sym_ccb *cp, struct scsi_cmnd if (!use_sg) segment = sym_scatter_no_sglist(np, cp, cmd); else if ((use_sg = map_scsi_sg_data(np, cmd)) > 0) { - struct scatterlist *scatter = (struct scatterlist *)cmd->buffer; + struct scatterlist *scatter = (struct scatterlist *)cmd->request_buffer; struct sym_tcb *tp = &np->target[cp->target]; struct sym_tblmove *data; diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c index 2a0e18a4874..b2bafc37c41 100644 --- a/drivers/usb/image/microtek.c +++ b/drivers/usb/image/microtek.c @@ -513,7 +513,7 @@ static void mts_do_sg (struct urb* transfer, struct pt_regs *regs) mts_transfer_cleanup(transfer); } - sg = context->srb->buffer; + sg = context->srb->request_buffer; context->fragment++; mts_int_submit_urb(transfer, context->data_pipe, @@ -549,19 +549,19 @@ mts_build_transfer_context( Scsi_Cmnd *srb, struct mts_desc* desc ) desc->context.fragment = 0; if (!srb->use_sg) { - if ( !srb->bufflen ){ + if ( !srb->request_bufflen ){ desc->context.data = NULL; desc->context.data_length = 0; return; } else { - desc->context.data = srb->buffer; - desc->context.data_length = srb->bufflen; + desc->context.data = srb->request_buffer; + desc->context.data_length = srb->request_bufflen; MTS_DEBUG("length = %d or %d\n", srb->request_bufflen, srb->bufflen); } } else { MTS_DEBUG("Using scatter/gather\n"); - sg = srb->buffer; + sg = srb->request_buffer; desc->context.data = page_address(sg[0].page) + sg[0].offset; desc->context.data_length = sg[0].length; } -- cgit v1.2.3 From 3e57ecf640428c01ba1ed8c8fc538447ada1715b Mon Sep 17 00:00:00 2001 From: Olaf Weber Date: Fri, 9 Jun 2006 14:48:12 +1000 Subject: [XFS] Add parameters to xfs_bmapi() and xfs_bunmapi() to have them report the range spanned by modifications to the in-core extent map. Add XFS_BUNMAPI() and XFS_SWAP_EXTENTS() macros that call xfs_bunmapi() and xfs_swap_extents() via the ioops vector. Change all calls that may modify the in-core extent map for the data fork to go through the ioops vector. This allows a cache of extent map data to be kept in sync. SGI-PV: 947615 SGI-Modid: xfs-linux-melb:xfs-kern:209226a Signed-off-by: Olaf Weber Signed-off-by: Nathan Scott --- fs/xfs/linux-2.6/xfs_lrw.c | 4 +- fs/xfs/linux-2.6/xfs_lrw.h | 2 +- fs/xfs/quota/xfs_dquot.c | 4 +- fs/xfs/quota/xfs_qm.c | 2 +- fs/xfs/xfs_attr.c | 12 +- fs/xfs/xfs_attr_leaf.c | 2 +- fs/xfs/xfs_bmap.c | 363 +++++++++++++++++++++++++++++++++++---------- fs/xfs/xfs_bmap.h | 22 ++- fs/xfs/xfs_da_btree.c | 9 +- fs/xfs/xfs_dfrag.c | 74 +++++---- fs/xfs/xfs_dfrag.h | 3 + fs/xfs/xfs_dir2.c | 7 +- fs/xfs/xfs_dir2_leaf.c | 2 +- fs/xfs/xfs_inode.c | 11 +- fs/xfs/xfs_iocore.c | 3 + fs/xfs/xfs_iomap.c | 24 +-- fs/xfs/xfs_mount.h | 23 ++- fs/xfs/xfs_rtalloc.c | 2 +- fs/xfs/xfs_vnodeops.c | 34 ++--- 19 files changed, 437 insertions(+), 166 deletions(-) diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c index 67efe330898..67b5e1c20de 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.c +++ b/fs/xfs/linux-2.6/xfs_lrw.c @@ -458,7 +458,7 @@ xfs_zero_last_block( last_fsb = XFS_B_TO_FSBT(mp, isize); nimaps = 1; error = XFS_BMAPI(mp, NULL, io, last_fsb, 1, 0, NULL, 0, &imap, - &nimaps, NULL); + &nimaps, NULL, NULL); if (error) { return error; } @@ -556,7 +556,7 @@ xfs_zero_eof( nimaps = 1; zero_count_fsb = end_zero_fsb - start_zero_fsb + 1; error = XFS_BMAPI(mp, NULL, io, start_zero_fsb, zero_count_fsb, - 0, NULL, 0, &imap, &nimaps, NULL); + 0, NULL, 0, &imap, &nimaps, NULL, NULL); if (error) { ASSERT(ismrlocked(io->io_lock, MR_UPDATE)); ASSERT(ismrlocked(io->io_iolock, MR_UPDATE)); diff --git a/fs/xfs/linux-2.6/xfs_lrw.h b/fs/xfs/linux-2.6/xfs_lrw.h index 8f453995235..dc49050688c 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.h +++ b/fs/xfs/linux-2.6/xfs_lrw.h @@ -49,7 +49,7 @@ struct xfs_iomap; #define XFS_CTRUNC4 14 #define XFS_CTRUNC5 15 #define XFS_CTRUNC6 16 -#define XFS_BUNMAPI 17 +#define XFS_BUNMAP 17 #define XFS_INVAL_CACHED 18 #define XFS_DIORD_ENTER 19 #define XFS_DIOWR_ENTER 20 diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c index 772ac48329e..26ee5df4f83 100644 --- a/fs/xfs/quota/xfs_dquot.c +++ b/fs/xfs/quota/xfs_dquot.c @@ -444,7 +444,7 @@ xfs_qm_dqalloc( XFS_BMAPI_METADATA | XFS_BMAPI_WRITE, &firstblock, XFS_QM_DQALLOC_SPACE_RES(mp), - &map, &nmaps, &flist))) { + &map, &nmaps, &flist, NULL))) { goto error0; } ASSERT(map.br_blockcount == XFS_DQUOT_CLUSTER_SIZE_FSB); @@ -559,7 +559,7 @@ xfs_qm_dqtobp( error = xfs_bmapi(NULL, quotip, dqp->q_fileoffset, XFS_DQUOT_CLUSTER_SIZE_FSB, XFS_BMAPI_METADATA, - NULL, 0, &map, &nmaps, NULL); + NULL, 0, &map, &nmaps, NULL, NULL); xfs_iunlock(quotip, XFS_ILOCK_SHARED); if (error) diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c index 7fb5eca9bd5..492840b2a35 100644 --- a/fs/xfs/quota/xfs_qm.c +++ b/fs/xfs/quota/xfs_qm.c @@ -1603,7 +1603,7 @@ xfs_qm_dqiterate( maxlblkcnt - lblkno, XFS_BMAPI_METADATA, NULL, - 0, map, &nmaps, NULL); + 0, map, &nmaps, NULL, NULL); xfs_iunlock(qip, XFS_ILOCK_SHARED); if (error) break; diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c index b6e1e02bbb2..3ef41e75d08 100644 --- a/fs/xfs/xfs_attr.c +++ b/fs/xfs/xfs_attr.c @@ -1910,7 +1910,7 @@ xfs_attr_rmtval_get(xfs_da_args_t *args) error = xfs_bmapi(args->trans, args->dp, (xfs_fileoff_t)lblkno, args->rmtblkcnt, XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, - NULL, 0, map, &nmap, NULL); + NULL, 0, map, &nmap, NULL, NULL); if (error) return(error); ASSERT(nmap >= 1); @@ -1988,7 +1988,7 @@ xfs_attr_rmtval_set(xfs_da_args_t *args) XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA | XFS_BMAPI_WRITE, args->firstblock, args->total, &map, &nmap, - args->flist); + args->flist, NULL); if (!error) { error = xfs_bmap_finish(&args->trans, args->flist, *args->firstblock, &committed); @@ -2039,7 +2039,8 @@ xfs_attr_rmtval_set(xfs_da_args_t *args) error = xfs_bmapi(NULL, dp, (xfs_fileoff_t)lblkno, args->rmtblkcnt, XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, - args->firstblock, 0, &map, &nmap, NULL); + args->firstblock, 0, &map, &nmap, + NULL, NULL); if (error) { return(error); } @@ -2104,7 +2105,7 @@ xfs_attr_rmtval_remove(xfs_da_args_t *args) args->rmtblkcnt, XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, args->firstblock, 0, &map, &nmap, - args->flist); + args->flist, NULL); if (error) { return(error); } @@ -2142,7 +2143,8 @@ xfs_attr_rmtval_remove(xfs_da_args_t *args) XFS_BMAP_INIT(args->flist, args->firstblock); error = xfs_bunmapi(args->trans, args->dp, lblkno, blkcnt, XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, - 1, args->firstblock, args->flist, &done); + 1, args->firstblock, args->flist, + NULL, &done); if (!error) { error = xfs_bmap_finish(&args->trans, args->flist, *args->firstblock, &committed); diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c index 9462be86aa1..5c44343d4a3 100644 --- a/fs/xfs/xfs_attr_leaf.c +++ b/fs/xfs/xfs_attr_leaf.c @@ -2990,7 +2990,7 @@ xfs_attr_leaf_freextent(xfs_trans_t **trans, xfs_inode_t *dp, nmap = 1; error = xfs_bmapi(*trans, dp, (xfs_fileoff_t)tblkno, tblkcnt, XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, - NULL, 0, &map, &nmap, NULL); + NULL, 0, &map, &nmap, NULL, NULL); if (error) { return(error); } diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 26939d364bc..890ad352817 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2005 Silicon Graphics, Inc. + * Copyright (c) 2000-2006 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -101,6 +101,7 @@ xfs_bmap_add_extent( xfs_fsblock_t *first, /* pointer to firstblock variable */ xfs_bmap_free_t *flist, /* list of extents to be freed */ int *logflagsp, /* inode logging flags */ + xfs_extdelta_t *delta, /* Change made to incore extents */ int whichfork, /* data or attr fork */ int rsvd); /* OK to allocate reserved blocks */ @@ -118,6 +119,7 @@ xfs_bmap_add_extent_delay_real( xfs_fsblock_t *first, /* pointer to firstblock variable */ xfs_bmap_free_t *flist, /* list of extents to be freed */ int *logflagsp, /* inode logging flags */ + xfs_extdelta_t *delta, /* Change made to incore extents */ int rsvd); /* OK to allocate reserved blocks */ /* @@ -131,6 +133,7 @@ xfs_bmap_add_extent_hole_delay( xfs_btree_cur_t *cur, /* if null, not a btree */ xfs_bmbt_irec_t *new, /* new data to add to file extents */ int *logflagsp,/* inode logging flags */ + xfs_extdelta_t *delta, /* Change made to incore extents */ int rsvd); /* OK to allocate reserved blocks */ /* @@ -144,6 +147,7 @@ xfs_bmap_add_extent_hole_real( xfs_btree_cur_t *cur, /* if null, not a btree */ xfs_bmbt_irec_t *new, /* new data to add to file extents */ int *logflagsp, /* inode logging flags */ + xfs_extdelta_t *delta, /* Change made to incore extents */ int whichfork); /* data or attr fork */ /* @@ -156,7 +160,8 @@ xfs_bmap_add_extent_unwritten_real( xfs_extnum_t idx, /* extent number to update/insert */ xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ xfs_bmbt_irec_t *new, /* new data to add to file extents */ - int *logflagsp); /* inode logging flags */ + int *logflagsp, /* inode logging flags */ + xfs_extdelta_t *delta); /* Change made to incore extents */ /* * xfs_bmap_alloc is called by xfs_bmapi to allocate an extent for a file. @@ -203,6 +208,7 @@ xfs_bmap_del_extent( xfs_btree_cur_t *cur, /* if null, not a btree */ xfs_bmbt_irec_t *new, /* new data to add to file extents */ int *logflagsp,/* inode logging flags */ + xfs_extdelta_t *delta, /* Change made to incore extents */ int whichfork, /* data or attr fork */ int rsvd); /* OK to allocate reserved blocks */ @@ -530,6 +536,7 @@ xfs_bmap_add_extent( xfs_fsblock_t *first, /* pointer to firstblock variable */ xfs_bmap_free_t *flist, /* list of extents to be freed */ int *logflagsp, /* inode logging flags */ + xfs_extdelta_t *delta, /* Change made to incore extents */ int whichfork, /* data or attr fork */ int rsvd) /* OK to use reserved data blocks */ { @@ -567,6 +574,15 @@ xfs_bmap_add_extent( logflags = XFS_ILOG_CORE | XFS_ILOG_FEXT(whichfork); } else logflags = 0; + /* DELTA: single new extent */ + if (delta) { + if (delta->xed_startoff > new->br_startoff) + delta->xed_startoff = new->br_startoff; + if (delta->xed_blockcount < + new->br_startoff + new->br_blockcount) + delta->xed_blockcount = new->br_startoff + + new->br_blockcount; + } } /* * Any kind of new delayed allocation goes here. @@ -576,7 +592,7 @@ xfs_bmap_add_extent( ASSERT((cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL) == 0); if ((error = xfs_bmap_add_extent_hole_delay(ip, idx, cur, new, - &logflags, rsvd))) + &logflags, delta, rsvd))) goto done; } /* @@ -587,7 +603,7 @@ xfs_bmap_add_extent( ASSERT((cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL) == 0); if ((error = xfs_bmap_add_extent_hole_real(ip, idx, cur, new, - &logflags, whichfork))) + &logflags, delta, whichfork))) goto done; } else { xfs_bmbt_irec_t prev; /* old extent at offset idx */ @@ -612,17 +628,17 @@ xfs_bmap_add_extent( XFS_BTCUR_BPRV_WASDEL); if ((error = xfs_bmap_add_extent_delay_real(ip, idx, &cur, new, &da_new, first, flist, - &logflags, rsvd))) + &logflags, delta, rsvd))) goto done; } else if (new->br_state == XFS_EXT_NORM) { ASSERT(new->br_state == XFS_EXT_NORM); if ((error = xfs_bmap_add_extent_unwritten_real( - ip, idx, &cur, new, &logflags))) + ip, idx, &cur, new, &logflags, delta))) goto done; } else { ASSERT(new->br_state == XFS_EXT_UNWRITTEN); if ((error = xfs_bmap_add_extent_unwritten_real( - ip, idx, &cur, new, &logflags))) + ip, idx, &cur, new, &logflags, delta))) goto done; } ASSERT(*curp == cur || *curp == NULL); @@ -635,7 +651,7 @@ xfs_bmap_add_extent( ASSERT((cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL) == 0); if ((error = xfs_bmap_add_extent_hole_real(ip, idx, cur, - new, &logflags, whichfork))) + new, &logflags, delta, whichfork))) goto done; } } @@ -700,6 +716,7 @@ xfs_bmap_add_extent_delay_real( xfs_fsblock_t *first, /* pointer to firstblock variable */ xfs_bmap_free_t *flist, /* list of extents to be freed */ int *logflagsp, /* inode logging flags */ + xfs_extdelta_t *delta, /* Change made to incore extents */ int rsvd) /* OK to use reserved data block allocation */ { xfs_btree_cur_t *cur; /* btree cursor */ @@ -716,8 +733,8 @@ xfs_bmap_add_extent_delay_real( /* left is 0, right is 1, prev is 2 */ int rval=0; /* return value (logging flags) */ int state = 0;/* state bits, accessed thru macros */ - xfs_filblks_t temp; /* value for dnew calculations */ - xfs_filblks_t temp2; /* value for dnew calculations */ + xfs_filblks_t temp=0; /* value for dnew calculations */ + xfs_filblks_t temp2=0;/* value for dnew calculations */ int tmp_rval; /* partial logging flags */ enum { /* bit number definitions for state */ LEFT_CONTIG, RIGHT_CONTIG, @@ -839,6 +856,11 @@ xfs_bmap_add_extent_delay_real( goto done; } *dnew = 0; + /* DELTA: Three in-core extents are replaced by one. */ + temp = LEFT.br_startoff; + temp2 = LEFT.br_blockcount + + PREV.br_blockcount + + RIGHT.br_blockcount; break; case MASK3(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG): @@ -872,6 +894,10 @@ xfs_bmap_add_extent_delay_real( goto done; } *dnew = 0; + /* DELTA: Two in-core extents are replaced by one. */ + temp = LEFT.br_startoff; + temp2 = LEFT.br_blockcount + + PREV.br_blockcount; break; case MASK3(LEFT_FILLING, RIGHT_FILLING, RIGHT_CONTIG): @@ -906,6 +932,10 @@ xfs_bmap_add_extent_delay_real( goto done; } *dnew = 0; + /* DELTA: Two in-core extents are replaced by one. */ + temp = PREV.br_startoff; + temp2 = PREV.br_blockcount + + RIGHT.br_blockcount; break; case MASK2(LEFT_FILLING, RIGHT_FILLING): @@ -936,6 +966,9 @@ xfs_bmap_add_extent_delay_real( ASSERT(i == 1); } *dnew = 0; + /* DELTA: The in-core extent described by new changed type. */ + temp = new->br_startoff; + temp2 = new->br_blockcount; break; case MASK2(LEFT_FILLING, LEFT_CONTIG): @@ -978,6 +1011,10 @@ xfs_bmap_add_extent_delay_real( xfs_bmap_trace_post_update(fname, "LF|LC", ip, idx, XFS_DATA_FORK); *dnew = temp; + /* DELTA: The boundary between two in-core extents moved. */ + temp = LEFT.br_startoff; + temp2 = LEFT.br_blockcount + + PREV.br_blockcount; break; case MASK(LEFT_FILLING): @@ -1025,6 +1062,9 @@ xfs_bmap_add_extent_delay_real( xfs_bmap_trace_post_update(fname, "LF", ip, idx + 1, XFS_DATA_FORK); *dnew = temp; + /* DELTA: One in-core extent is split in two. */ + temp = PREV.br_startoff; + temp2 = PREV.br_blockcount; break; case MASK2(RIGHT_FILLING, RIGHT_CONTIG): @@ -1067,6 +1107,10 @@ xfs_bmap_add_extent_delay_real( xfs_bmap_trace_post_update(fname, "RF|RC", ip, idx, XFS_DATA_FORK); *dnew = temp; + /* DELTA: The boundary between two in-core extents moved. */ + temp = PREV.br_startoff; + temp2 = PREV.br_blockcount + + RIGHT.br_blockcount; break; case MASK(RIGHT_FILLING): @@ -1112,6 +1156,9 @@ xfs_bmap_add_extent_delay_real( xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp)); xfs_bmap_trace_post_update(fname, "RF", ip, idx, XFS_DATA_FORK); *dnew = temp; + /* DELTA: One in-core extent is split in two. */ + temp = PREV.br_startoff; + temp2 = PREV.br_blockcount; break; case 0: @@ -1194,6 +1241,9 @@ xfs_bmap_add_extent_delay_real( xfs_bmap_trace_post_update(fname, "0", ip, idx + 2, XFS_DATA_FORK); *dnew = temp + temp2; + /* DELTA: One in-core extent is split in three. */ + temp = PREV.br_startoff; + temp2 = PREV.br_blockcount; break; case MASK3(LEFT_FILLING, LEFT_CONTIG, RIGHT_CONTIG): @@ -1209,6 +1259,13 @@ xfs_bmap_add_extent_delay_real( ASSERT(0); } *curp = cur; + if (delta) { + temp2 += temp; + if (delta->xed_startoff > temp) + delta->xed_startoff = temp; + if (delta->xed_blockcount < temp2) + delta->xed_blockcount = temp2; + } done: *logflagsp = rval; return error; @@ -1235,7 +1292,8 @@ xfs_bmap_add_extent_unwritten_real( xfs_extnum_t idx, /* extent number to update/insert */ xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ xfs_bmbt_irec_t *new, /* new data to add to file extents */ - int *logflagsp) /* inode logging flags */ + int *logflagsp, /* inode logging flags */ + xfs_extdelta_t *delta) /* Change made to incore extents */ { xfs_btree_cur_t *cur; /* btree cursor */ xfs_bmbt_rec_t *ep; /* extent entry for idx */ @@ -1252,6 +1310,8 @@ xfs_bmap_add_extent_unwritten_real( /* left is 0, right is 1, prev is 2 */ int rval=0; /* return value (logging flags) */ int state = 0;/* state bits, accessed thru macros */ + xfs_filblks_t temp=0; + xfs_filblks_t temp2=0; enum { /* bit number definitions for state */ LEFT_CONTIG, RIGHT_CONTIG, LEFT_FILLING, RIGHT_FILLING, @@ -1380,6 +1440,11 @@ xfs_bmap_add_extent_unwritten_real( RIGHT.br_blockcount, LEFT.br_state))) goto done; } + /* DELTA: Three in-core extents are replaced by one. */ + temp = LEFT.br_startoff; + temp2 = LEFT.br_blockcount + + PREV.br_blockcount + + RIGHT.br_blockcount; break; case MASK3(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG): @@ -1419,6 +1484,10 @@ xfs_bmap_add_extent_unwritten_real( LEFT.br_state))) goto done; } + /* DELTA: Two in-core extents are replaced by one. */ + temp = LEFT.br_startoff; + temp2 = LEFT.br_blockcount + + PREV.br_blockcount; break; case MASK3(LEFT_FILLING, RIGHT_FILLING, RIGHT_CONTIG): @@ -1459,6 +1528,10 @@ xfs_bmap_add_extent_unwritten_real( newext))) goto done; } + /* DELTA: Two in-core extents are replaced by one. */ + temp = PREV.br_startoff; + temp2 = PREV.br_blockcount + + RIGHT.br_blockcount; break; case MASK2(LEFT_FILLING, RIGHT_FILLING): @@ -1487,6 +1560,9 @@ xfs_bmap_add_extent_unwritten_real( newext))) goto done; } + /* DELTA: The in-core extent described by new changed type. */ + temp = new->br_startoff; + temp2 = new->br_blockcount; break; case MASK2(LEFT_FILLING, LEFT_CONTIG): @@ -1534,6 +1610,10 @@ xfs_bmap_add_extent_unwritten_real( LEFT.br_state)) goto done; } + /* DELTA: The boundary between two in-core extents moved. */ + temp = LEFT.br_startoff; + temp2 = LEFT.br_blockcount + + PREV.br_blockcount; break; case MASK(LEFT_FILLING): @@ -1574,6 +1654,9 @@ xfs_bmap_add_extent_unwritten_real( goto done; ASSERT(i == 1); } + /* DELTA: One in-core extent is split in two. */ + temp = PREV.br_startoff; + temp2 = PREV.br_blockcount; break; case MASK2(RIGHT_FILLING, RIGHT_CONTIG): @@ -1617,6 +1700,10 @@ xfs_bmap_add_extent_unwritten_real( newext))) goto done; } + /* DELTA: The boundary between two in-core extents moved. */ + temp = PREV.br_startoff; + temp2 = PREV.br_blockcount + + RIGHT.br_blockcount; break; case MASK(RIGHT_FILLING): @@ -1657,6 +1744,9 @@ xfs_bmap_add_extent_unwritten_real( goto done; ASSERT(i == 1); } + /* DELTA: One in-core extent is split in two. */ + temp = PREV.br_startoff; + temp2 = PREV.br_blockcount; break; case 0: @@ -1710,6 +1800,9 @@ xfs_bmap_add_extent_unwritten_real( goto done; ASSERT(i == 1); } + /* DELTA: One in-core extent is split in three. */ + temp = PREV.br_startoff; + temp2 = PREV.br_blockcount; break; case MASK3(LEFT_FILLING, LEFT_CONTIG, RIGHT_CONTIG): @@ -1725,6 +1818,13 @@ xfs_bmap_add_extent_unwritten_real( ASSERT(0); } *curp = cur; + if (delta) { + temp2 += temp; + if (delta->xed_startoff > temp) + delta->xed_startoff = temp; + if (delta->xed_blockcount < temp2) + delta->xed_blockcount = temp2; + } done: *logflagsp = rval; return error; @@ -1753,6 +1853,7 @@ xfs_bmap_add_extent_hole_delay( xfs_btree_cur_t *cur, /* if null, not a btree */ xfs_bmbt_irec_t *new, /* new data to add to file extents */ int *logflagsp, /* inode logging flags */ + xfs_extdelta_t *delta, /* Change made to incore extents */ int rsvd) /* OK to allocate reserved blocks */ { xfs_bmbt_rec_t *ep; /* extent record for idx */ @@ -1765,7 +1866,8 @@ xfs_bmap_add_extent_hole_delay( xfs_filblks_t oldlen=0; /* old indirect size */ xfs_bmbt_irec_t right; /* right neighbor extent entry */ int state; /* state bits, accessed thru macros */ - xfs_filblks_t temp; /* temp for indirect calculations */ + xfs_filblks_t temp=0; /* temp for indirect calculations */ + xfs_filblks_t temp2=0; enum { /* bit number definitions for state */ LEFT_CONTIG, RIGHT_CONTIG, LEFT_DELAY, RIGHT_DELAY, @@ -1844,6 +1946,9 @@ xfs_bmap_add_extent_hole_delay( XFS_DATA_FORK); xfs_iext_remove(ifp, idx, 1); ip->i_df.if_lastex = idx - 1; + /* DELTA: Two in-core extents were replaced by one. */ + temp2 = temp; + temp = left.br_startoff; break; case MASK(LEFT_CONTIG): @@ -1864,6 +1969,9 @@ xfs_bmap_add_extent_hole_delay( xfs_bmap_trace_post_update(fname, "LC", ip, idx - 1, XFS_DATA_FORK); ip->i_df.if_lastex = idx - 1; + /* DELTA: One in-core extent grew into a hole. */ + temp2 = temp; + temp = left.br_startoff; break; case MASK(RIGHT_CONTIG): @@ -1881,6 +1989,9 @@ xfs_bmap_add_extent_hole_delay( NULLSTARTBLOCK((int)newlen), temp, right.br_state); xfs_bmap_trace_post_update(fname, "RC", ip, idx, XFS_DATA_FORK); ip->i_df.if_lastex = idx; + /* DELTA: One in-core extent grew into a hole. */ + temp2 = temp; + temp = new->br_startoff; break; case 0: @@ -1894,6 +2005,9 @@ xfs_bmap_add_extent_hole_delay( XFS_DATA_FORK); xfs_iext_insert(ifp, idx, 1, new); ip->i_df.if_lastex = idx; + /* DELTA: A new in-core extent was added in a hole. */ + temp2 = new->br_blockcount; + temp = new->br_startoff; break; } if (oldlen != newlen) { @@ -1904,6 +2018,13 @@ xfs_bmap_add_extent_hole_delay( * Nothing to do for disk quota accounting here. */ } + if (delta) { + temp2 += temp; + if (delta->xed_startoff > temp) + delta->xed_startoff = temp; + if (delta->xed_blockcount < temp2) + delta->xed_blockcount = temp2; + } *logflagsp = 0; return 0; #undef MASK @@ -1925,6 +2046,7 @@ xfs_bmap_add_extent_hole_real( xfs_btree_cur_t *cur, /* if null, not a btree */ xfs_bmbt_irec_t *new, /* new data to add to file extents */ int *logflagsp, /* inode logging flags */ + xfs_extdelta_t *delta, /* Change made to incore extents */ int whichfork) /* data or attr fork */ { xfs_bmbt_rec_t *ep; /* pointer to extent entry ins. point */ @@ -1936,7 +2058,10 @@ xfs_bmap_add_extent_hole_real( xfs_ifork_t *ifp; /* inode fork pointer */ xfs_bmbt_irec_t left; /* left neighbor extent entry */ xfs_bmbt_irec_t right; /* right neighbor extent entry */ + int rval=0; /* return value (logging flags) */ int state; /* state bits, accessed thru macros */ + xfs_filblks_t temp=0; + xfs_filblks_t temp2=0; enum { /* bit number definitions for state */ LEFT_CONTIG, RIGHT_CONTIG, LEFT_DELAY, RIGHT_DELAY, @@ -1993,6 +2118,7 @@ xfs_bmap_add_extent_hole_real( left.br_blockcount + new->br_blockcount + right.br_blockcount <= MAXEXTLEN)); + error = 0; /* * Select which case we're in here, and implement it. */ @@ -2018,25 +2144,35 @@ xfs_bmap_add_extent_hole_real( XFS_IFORK_NEXT_SET(ip, whichfork, XFS_IFORK_NEXTENTS(ip, whichfork) - 1); if (cur == NULL) { - *logflagsp = XFS_ILOG_CORE | XFS_ILOG_FEXT(whichfork); - return 0; + rval = XFS_ILOG_CORE | XFS_ILOG_FEXT(whichfork); + } else { + rval = XFS_ILOG_CORE; + if ((error = xfs_bmbt_lookup_eq(cur, + right.br_startoff, + right.br_startblock, + right.br_blockcount, &i))) + goto done; + ASSERT(i == 1); + if ((error = xfs_bmbt_delete(cur, &i))) + goto done; + ASSERT(i == 1); + if ((error = xfs_bmbt_decrement(cur, 0, &i))) + goto done; + ASSERT(i == 1); + if ((error = xfs_bmbt_update(cur, left.br_startoff, + left.br_startblock, + left.br_blockcount + + new->br_blockcount + + right.br_blockcount, + left.br_state))) + goto done; } - *logflagsp = XFS_ILOG_CORE; - if ((error = xfs_bmbt_lookup_eq(cur, right.br_startoff, - right.br_startblock, right.br_blockcount, &i))) - return error; - ASSERT(i == 1); - if ((error = xfs_bmbt_delete(cur, &i))) - return error; - ASSERT(i == 1); - if ((error = xfs_bmbt_decrement(cur, 0, &i))) - return error; - ASSERT(i == 1); - error = xfs_bmbt_update(cur, left.br_startoff, - left.br_startblock, - left.br_blockcount + new->br_blockcount + - right.br_blockcount, left.br_state); - return error; + /* DELTA: Two in-core extents were replaced by one. */ + temp = left.br_startoff; + temp2 = left.br_blockcount + + new->br_blockcount + + right.br_blockcount; + break; case MASK(LEFT_CONTIG): /* @@ -2050,19 +2186,27 @@ xfs_bmap_add_extent_hole_real( xfs_bmap_trace_post_update(fname, "LC", ip, idx - 1, whichfork); ifp->if_lastex = idx - 1; if (cur == NULL) { - *logflagsp = XFS_ILOG_FEXT(whichfork); - return 0; + rval = XFS_ILOG_FEXT(whichfork); + } else { + rval = 0; + if ((error = xfs_bmbt_lookup_eq(cur, + left.br_startoff, + left.br_startblock, + left.br_blockcount, &i))) + goto done; + ASSERT(i == 1); + if ((error = xfs_bmbt_update(cur, left.br_startoff, + left.br_startblock, + left.br_blockcount + + new->br_blockcount, + left.br_state))) + goto done; } - *logflagsp = 0; - if ((error = xfs_bmbt_lookup_eq(cur, left.br_startoff, - left.br_startblock, left.br_blockcount, &i))) - return error; - ASSERT(i == 1); - error = xfs_bmbt_update(cur, left.br_startoff, - left.br_startblock, - left.br_blockcount + new->br_blockcount, - left.br_state); - return error; + /* DELTA: One in-core extent grew. */ + temp = left.br_startoff; + temp2 = left.br_blockcount + + new->br_blockcount; + break; case MASK(RIGHT_CONTIG): /* @@ -2077,19 +2221,27 @@ xfs_bmap_add_extent_hole_real( xfs_bmap_trace_post_update(fname, "RC", ip, idx, whichfork); ifp->if_lastex = idx; if (cur == NULL) { - *logflagsp = XFS_ILOG_FEXT(whichfork); - return 0; + rval = XFS_ILOG_FEXT(whichfork); + } else { + rval = 0; + if ((error = xfs_bmbt_lookup_eq(cur, + right.br_startoff, + right.br_startblock, + right.br_blockcount, &i))) + goto done; + ASSERT(i == 1); + if ((error = xfs_bmbt_update(cur, new->br_startoff, + new->br_startblock, + new->br_blockcount + + right.br_blockcount, + right.br_state))) + goto done; } - *logflagsp = 0; - if ((error = xfs_bmbt_lookup_eq(cur, right.br_startoff, - right.br_startblock, right.br_blockcount, &i))) - return error; - ASSERT(i == 1); - error = xfs_bmbt_update(cur, new->br_startoff, - new->br_startblock, - new->br_blockcount + right.br_blockcount, - right.br_state); - return error; + /* DELTA: One in-core extent grew. */ + temp = new->br_startoff; + temp2 = new->br_blockcount + + right.br_blockcount; + break; case 0: /* @@ -2104,29 +2256,41 @@ xfs_bmap_add_extent_hole_real( XFS_IFORK_NEXT_SET(ip, whichfork, XFS_IFORK_NEXTENTS(ip, whichfork) + 1); if (cur == NULL) { - *logflagsp = XFS_ILOG_CORE | XFS_ILOG_FEXT(whichfork); - return 0; + rval = XFS_ILOG_CORE | XFS_ILOG_FEXT(whichfork); + } else { + rval = XFS_ILOG_CORE; + if ((error = xfs_bmbt_lookup_eq(cur, + new->br_startoff, + new->br_startblock, + new->br_blockcount, &i))) + goto done; + ASSERT(i == 0); + cur->bc_rec.b.br_state = new->br_state; + if ((error = xfs_bmbt_insert(cur, &i))) + goto done; + ASSERT(i == 1); } - *logflagsp = XFS_ILOG_CORE; - if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff, - new->br_startblock, new->br_blockcount, &i))) - return error; - ASSERT(i == 0); - cur->bc_rec.b.br_state = new->br_state; - if ((error = xfs_bmbt_insert(cur, &i))) - return error; - ASSERT(i == 1); - return 0; + /* DELTA: A new extent was added in a hole. */ + temp = new->br_startoff; + temp2 = new->br_blockcount; + break; } + if (delta) { + temp2 += temp; + if (delta->xed_startoff > temp) + delta->xed_startoff = temp; + if (delta->xed_blockcount < temp2) + delta->xed_blockcount = temp2; + } +done: + *logflagsp = rval; + return error; #undef MASK #undef MASK2 #undef STATE_SET #undef STATE_TEST #undef STATE_SET_TEST #undef SWITCH_STATE - /* NOTREACHED */ - ASSERT(0); - return 0; /* keep gcc quite */ } /* @@ -2885,6 +3049,7 @@ xfs_bmap_del_extent( xfs_btree_cur_t *cur, /* if null, not a btree */ xfs_bmbt_irec_t *del, /* data to remove from extents */ int *logflagsp, /* inode logging flags */ + xfs_extdelta_t *delta, /* Change made to incore extents */ int whichfork, /* data or attr fork */ int rsvd) /* OK to allocate reserved blocks */ { @@ -3193,6 +3358,14 @@ xfs_bmap_del_extent( if (da_old > da_new) xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, (int)(da_old - da_new), rsvd); + if (delta) { + /* DELTA: report the original extent. */ + if (delta->xed_startoff > got.br_startoff) + delta->xed_startoff = got.br_startoff; + if (delta->xed_blockcount < got.br_startoff+got.br_blockcount) + delta->xed_blockcount = got.br_startoff + + got.br_blockcount; + } done: *logflagsp = flags; return error; @@ -3753,7 +3926,7 @@ xfs_bunmap_trace( if (ip->i_rwtrace == NULL) return; ktrace_enter(ip->i_rwtrace, - (void *)(__psint_t)XFS_BUNMAPI, + (void *)(__psint_t)XFS_BUNMAP, (void *)ip, (void *)(__psint_t)((ip->i_d.di_size >> 32) & 0xffffffff), (void *)(__psint_t)(ip->i_d.di_size & 0xffffffff), @@ -4538,7 +4711,8 @@ xfs_bmapi( xfs_extlen_t total, /* total blocks needed */ xfs_bmbt_irec_t *mval, /* output: map values */ int *nmap, /* i/o: mval size/count */ - xfs_bmap_free_t *flist) /* i/o: list extents to free */ + xfs_bmap_free_t *flist, /* i/o: list extents to free */ + xfs_extdelta_t *delta) /* o: change made to incore extents */ { xfs_fsblock_t abno; /* allocated block number */ xfs_extlen_t alen; /* allocated extent length */ @@ -4650,6 +4824,10 @@ xfs_bmapi( end = bno + len; obno = bno; bma.ip = NULL; + if (delta) { + delta->xed_startoff = NULLFILEOFF; + delta->xed_blockcount = 0; + } while (bno < end && n < *nmap) { /* * Reading past eof, act as though there's a hole @@ -4886,8 +5064,8 @@ xfs_bmapi( got.br_state = XFS_EXT_UNWRITTEN; } error = xfs_bmap_add_extent(ip, lastx, &cur, &got, - firstblock, flist, &tmp_logflags, whichfork, - (flags & XFS_BMAPI_RSVBLOCKS)); + firstblock, flist, &tmp_logflags, delta, + whichfork, (flags & XFS_BMAPI_RSVBLOCKS)); logflags |= tmp_logflags; if (error) goto error0; @@ -4983,8 +5161,8 @@ xfs_bmapi( } mval->br_state = XFS_EXT_NORM; error = xfs_bmap_add_extent(ip, lastx, &cur, mval, - firstblock, flist, &tmp_logflags, whichfork, - (flags & XFS_BMAPI_RSVBLOCKS)); + firstblock, flist, &tmp_logflags, delta, + whichfork, (flags & XFS_BMAPI_RSVBLOCKS)); logflags |= tmp_logflags; if (error) goto error0; @@ -5073,7 +5251,14 @@ xfs_bmapi( ASSERT(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE || XFS_IFORK_NEXTENTS(ip, whichfork) > ifp->if_ext_max); error = 0; - + if (delta && delta->xed_startoff != NULLFILEOFF) { + /* A change was actually made. + * Note that delta->xed_blockount is an offset at this + * point and needs to be converted to a block count. + */ + ASSERT(delta->xed_blockcount > delta->xed_startoff); + delta->xed_blockcount -= delta->xed_startoff; + } error0: /* * Log everything. Do this after conversion, there's no point in @@ -5185,6 +5370,8 @@ xfs_bunmapi( xfs_fsblock_t *firstblock, /* first allocated block controls a.g. for allocs */ xfs_bmap_free_t *flist, /* i/o: list extents to free */ + xfs_extdelta_t *delta, /* o: change made to incore + extents */ int *done) /* set if not done yet */ { xfs_btree_cur_t *cur; /* bmap btree cursor */ @@ -5242,6 +5429,10 @@ xfs_bunmapi( bno = start + len - 1; ep = xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got, &prev); + if (delta) { + delta->xed_startoff = NULLFILEOFF; + delta->xed_blockcount = 0; + } /* * Check to see if the given block number is past the end of the * file, back up to the last block if so... @@ -5340,7 +5531,8 @@ xfs_bunmapi( } del.br_state = XFS_EXT_UNWRITTEN; error = xfs_bmap_add_extent(ip, lastx, &cur, &del, - firstblock, flist, &logflags, XFS_DATA_FORK, 0); + firstblock, flist, &logflags, delta, + XFS_DATA_FORK, 0); if (error) goto error0; goto nodelete; @@ -5394,7 +5586,7 @@ xfs_bunmapi( prev.br_state = XFS_EXT_UNWRITTEN; error = xfs_bmap_add_extent(ip, lastx - 1, &cur, &prev, firstblock, flist, &logflags, - XFS_DATA_FORK, 0); + delta, XFS_DATA_FORK, 0); if (error) goto error0; goto nodelete; @@ -5403,7 +5595,7 @@ xfs_bunmapi( del.br_state = XFS_EXT_UNWRITTEN; error = xfs_bmap_add_extent(ip, lastx, &cur, &del, firstblock, flist, &logflags, - XFS_DATA_FORK, 0); + delta, XFS_DATA_FORK, 0); if (error) goto error0; goto nodelete; @@ -5456,7 +5648,7 @@ xfs_bunmapi( goto error0; } error = xfs_bmap_del_extent(ip, tp, lastx, flist, cur, &del, - &tmp_logflags, whichfork, rsvd); + &tmp_logflags, delta, whichfork, rsvd); logflags |= tmp_logflags; if (error) goto error0; @@ -5513,6 +5705,14 @@ nodelete: ASSERT(ifp->if_ext_max == XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t)); error = 0; + if (delta && delta->xed_startoff != NULLFILEOFF) { + /* A change was actually made. + * Note that delta->xed_blockount is an offset at this + * point and needs to be converted to a block count. + */ + ASSERT(delta->xed_blockcount > delta->xed_startoff); + delta->xed_blockcount -= delta->xed_startoff; + } error0: /* * Log everything. Do this after conversion, there's no point in @@ -5689,7 +5889,8 @@ xfs_getbmap( nmap = (nexleft > subnex) ? subnex : nexleft; error = xfs_bmapi(NULL, ip, XFS_BB_TO_FSBT(mp, bmv->bmv_offset), XFS_BB_TO_FSB(mp, bmv->bmv_length), - bmapi_flags, NULL, 0, map, &nmap, NULL); + bmapi_flags, NULL, 0, map, &nmap, + NULL, NULL); if (error) goto unlock_and_return; ASSERT(nmap <= subnex); diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h index 8e0d73d9ccc..80e93409b78 100644 --- a/fs/xfs/xfs_bmap.h +++ b/fs/xfs/xfs_bmap.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. + * Copyright (c) 2000-2006 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -25,6 +25,20 @@ struct xfs_inode; struct xfs_mount; struct xfs_trans; +/* + * DELTA: describe a change to the in-core extent list. + * + * Internally the use of xed_blockount is somewhat funky. + * xed_blockcount contains an offset much of the time because this + * makes merging changes easier. (xfs_fileoff_t and xfs_filblks_t are + * the same underlying type). + */ +typedef struct xfs_extdelta +{ + xfs_fileoff_t xed_startoff; /* offset of range */ + xfs_filblks_t xed_blockcount; /* blocks in range */ +} xfs_extdelta_t; + /* * List of extents to be free "later". * The list is kept sorted on xbf_startblock. @@ -275,7 +289,9 @@ xfs_bmapi( xfs_extlen_t total, /* total blocks needed */ struct xfs_bmbt_irec *mval, /* output: map values */ int *nmap, /* i/o: mval size/count */ - xfs_bmap_free_t *flist); /* i/o: list extents to free */ + xfs_bmap_free_t *flist, /* i/o: list extents to free */ + xfs_extdelta_t *delta); /* o: change made to incore + extents */ /* * Map file blocks to filesystem blocks, simple version. @@ -309,6 +325,8 @@ xfs_bunmapi( xfs_fsblock_t *firstblock, /* first allocated block controls a.g. for allocs */ xfs_bmap_free_t *flist, /* i/o: list extents to free */ + xfs_extdelta_t *delta, /* o: change made to incore + extents */ int *done); /* set if not done yet */ /* diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c index 8988b905117..47b86f9f69f 100644 --- a/fs/xfs/xfs_da_btree.c +++ b/fs/xfs/xfs_da_btree.c @@ -1655,7 +1655,7 @@ xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno) XFS_BMAPI_AFLAG(w)|XFS_BMAPI_WRITE|XFS_BMAPI_METADATA| XFS_BMAPI_CONTIG, args->firstblock, args->total, &map, &nmap, - args->flist))) { + args->flist, NULL))) { return error; } ASSERT(nmap <= 1); @@ -1676,7 +1676,8 @@ xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno) XFS_BMAPI_AFLAG(w)|XFS_BMAPI_WRITE| XFS_BMAPI_METADATA, args->firstblock, args->total, - &mapp[mapi], &nmap, args->flist))) { + &mapp[mapi], &nmap, args->flist, + NULL))) { kmem_free(mapp, sizeof(*mapp) * count); return error; } @@ -1961,7 +1962,7 @@ xfs_da_shrink_inode(xfs_da_args_t *args, xfs_dablk_t dead_blkno, */ if ((error = xfs_bunmapi(tp, dp, dead_blkno, count, XFS_BMAPI_AFLAG(w)|XFS_BMAPI_METADATA, - 0, args->firstblock, args->flist, + 0, args->firstblock, args->flist, NULL, &done)) == ENOSPC) { if (w != XFS_DATA_FORK) goto done; @@ -2086,7 +2087,7 @@ xfs_da_do_buf( nfsb, XFS_BMAPI_METADATA | XFS_BMAPI_AFLAG(whichfork), - NULL, 0, mapp, &nmap, NULL))) + NULL, 0, mapp, &nmap, NULL, NULL))) goto exit0; } } else { diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c index 4968a6358e6..99daf8c0f90 100644 --- a/fs/xfs/xfs_dfrag.c +++ b/fs/xfs/xfs_dfrag.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. + * Copyright (c) 2000-2006 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -54,24 +54,14 @@ xfs_swapext( xfs_swapext_t __user *sxu) { xfs_swapext_t *sxp; - xfs_inode_t *ip=NULL, *tip=NULL, *ips[2]; - xfs_trans_t *tp; + xfs_inode_t *ip=NULL, *tip=NULL; xfs_mount_t *mp; - xfs_bstat_t *sbp; struct file *fp = NULL, *tfp = NULL; vnode_t *vp, *tvp; - static uint lock_flags = XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL; - int ilf_fields, tilf_fields; int error = 0; - xfs_ifork_t *tempifp, *ifp, *tifp; - __uint64_t tmp; - int aforkblks = 0; - int taforkblks = 0; - char locked = 0; sxp = kmem_alloc(sizeof(xfs_swapext_t), KM_MAYFAIL); - tempifp = kmem_alloc(sizeof(xfs_ifork_t), KM_MAYFAIL); - if (!sxp || !tempifp) { + if (!sxp) { error = XFS_ERROR(ENOMEM); goto error0; } @@ -118,14 +108,56 @@ xfs_swapext( mp = ip->i_mount; - sbp = &sxp->sx_stat; - if (XFS_FORCED_SHUTDOWN(mp)) { error = XFS_ERROR(EIO); goto error0; } - locked = 1; + error = XFS_SWAP_EXTENTS(mp, &ip->i_iocore, &tip->i_iocore, sxp); + + error0: + if (fp != NULL) + fput(fp); + if (tfp != NULL) + fput(tfp); + + if (sxp != NULL) + kmem_free(sxp, sizeof(xfs_swapext_t)); + + return error; +} + +int +xfs_swap_extents( + xfs_inode_t *ip, + xfs_inode_t *tip, + xfs_swapext_t *sxp) +{ + xfs_mount_t *mp; + xfs_inode_t *ips[2]; + xfs_trans_t *tp; + xfs_bstat_t *sbp = &sxp->sx_stat; + vnode_t *vp, *tvp; + xfs_ifork_t *tempifp, *ifp, *tifp; + int ilf_fields, tilf_fields; + static uint lock_flags = XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL; + int error = 0; + int aforkblks = 0; + int taforkblks = 0; + __uint64_t tmp; + char locked = 0; + + mp = ip->i_mount; + + tempifp = kmem_alloc(sizeof(xfs_ifork_t), KM_MAYFAIL); + if (!tempifp) { + error = XFS_ERROR(ENOMEM); + goto error0; + } + + sbp = &sxp->sx_stat; + vp = XFS_ITOV(ip); + tvp = XFS_ITOV(tip); /* Lock in i_ino order */ if (ip->i_ino < tip->i_ino) { @@ -137,6 +169,7 @@ xfs_swapext( } xfs_lock_inodes(ips, 2, 0, lock_flags); + locked = 1; /* Check permissions */ error = xfs_iaccess(ip, S_IWUSR, NULL); @@ -360,16 +393,7 @@ xfs_swapext( xfs_iunlock(ip, lock_flags); xfs_iunlock(tip, lock_flags); } - - if (fp != NULL) - fput(fp); - if (tfp != NULL) - fput(tfp); - - if (sxp != NULL) - kmem_free(sxp, sizeof(xfs_swapext_t)); if (tempifp != NULL) kmem_free(tempifp, sizeof(xfs_ifork_t)); - return error; } diff --git a/fs/xfs/xfs_dfrag.h b/fs/xfs/xfs_dfrag.h index f678559abc4..da178205be6 100644 --- a/fs/xfs/xfs_dfrag.h +++ b/fs/xfs/xfs_dfrag.h @@ -48,6 +48,9 @@ typedef struct xfs_swapext */ int xfs_swapext(struct xfs_swapext __user *sx); +int xfs_swap_extents(struct xfs_inode *ip, struct xfs_inode *tip, + struct xfs_swapext *sxp); + #endif /* __KERNEL__ */ #endif /* __XFS_DFRAG_H__ */ diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c index 022c8398ab6..80238a2263f 100644 --- a/fs/xfs/xfs_dir2.c +++ b/fs/xfs/xfs_dir2.c @@ -549,7 +549,7 @@ xfs_dir2_grow_inode( if ((error = xfs_bmapi(tp, dp, bno, count, XFS_BMAPI_WRITE|XFS_BMAPI_METADATA|XFS_BMAPI_CONTIG, args->firstblock, args->total, &map, &nmap, - args->flist))) { + args->flist, NULL))) { return error; } ASSERT(nmap <= 1); @@ -585,7 +585,8 @@ xfs_dir2_grow_inode( if ((error = xfs_bmapi(tp, dp, b, c, XFS_BMAPI_WRITE|XFS_BMAPI_METADATA, args->firstblock, args->total, - &mapp[mapi], &nmap, args->flist))) { + &mapp[mapi], &nmap, args->flist, + NULL))) { kmem_free(mapp, sizeof(*mapp) * count); return error; } @@ -786,7 +787,7 @@ xfs_dir2_shrink_inode( */ if ((error = xfs_bunmapi(tp, dp, da, mp->m_dirblkfsbs, XFS_BMAPI_METADATA, 0, args->firstblock, args->flist, - &done))) { + NULL, &done))) { /* * ENOSPC actually can happen if we're in a removename with * no space reservation, and the resulting block removal diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c index 0f5e2f2ce6e..5fe88d546c7 100644 --- a/fs/xfs/xfs_dir2_leaf.c +++ b/fs/xfs/xfs_dir2_leaf.c @@ -884,7 +884,7 @@ xfs_dir2_leaf_getdents( XFS_DIR2_BYTE_TO_DA(mp, XFS_DIR2_LEAF_OFFSET) - map_off, XFS_BMAPI_METADATA, NULL, 0, - &map[map_valid], &nmap, NULL); + &map[map_valid], &nmap, NULL, NULL); /* * Don't know if we should ignore this or * try to return an error. diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 94b60dd0380..020de5637e0 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. + * Copyright (c) 2000-2006 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -1285,7 +1285,7 @@ xfs_isize_check( (xfs_ufsize_t)XFS_MAXIOFFSET(mp)) - map_first), XFS_BMAPI_ENTIRE, NULL, 0, imaps, &nimaps, - NULL)) + NULL, NULL)) return; ASSERT(nimaps == 1); ASSERT(imaps[0].br_startblock == HOLESTARTBLOCK); @@ -1666,12 +1666,13 @@ xfs_itruncate_finish( * runs. */ XFS_BMAP_INIT(&free_list, &first_block); - error = xfs_bunmapi(ntp, ip, first_unmap_block, - unmap_len, + error = XFS_BUNMAPI(mp, ntp, &ip->i_iocore, + first_unmap_block, unmap_len, XFS_BMAPI_AFLAG(fork) | (sync ? 0 : XFS_BMAPI_ASYNC), XFS_ITRUNC_MAX_EXTENTS, - &first_block, &free_list, &done); + &first_block, &free_list, + NULL, &done); if (error) { /* * If the bunmapi call encounters an error, diff --git a/fs/xfs/xfs_iocore.c b/fs/xfs/xfs_iocore.c index a07815661a8..d3da194f8b7 100644 --- a/fs/xfs/xfs_iocore.c +++ b/fs/xfs/xfs_iocore.c @@ -26,6 +26,7 @@ #include "xfs_ag.h" #include "xfs_dir.h" #include "xfs_dir2.h" +#include "xfs_dfrag.h" #include "xfs_dmapi.h" #include "xfs_mount.h" #include "xfs_bmap_btree.h" @@ -68,6 +69,7 @@ xfs_ioinit( xfs_ioops_t xfs_iocore_xfs = { .xfs_ioinit = (xfs_ioinit_t) xfs_ioinit, .xfs_bmapi_func = (xfs_bmapi_t) xfs_bmapi, + .xfs_bunmapi_func = (xfs_bunmapi_t) xfs_bunmapi, .xfs_bmap_eof_func = (xfs_bmap_eof_t) xfs_bmap_eof, .xfs_iomap_write_direct = (xfs_iomap_write_direct_t) xfs_iomap_write_direct, @@ -84,6 +86,7 @@ xfs_ioops_t xfs_iocore_xfs = { .xfs_unlock = (xfs_unlk_t) xfs_iunlock, .xfs_size_func = (xfs_size_t) xfs_size_fn, .xfs_iodone = (xfs_iodone_t) fs_noerr, + .xfs_swap_extents_func = (xfs_swap_extents_t) xfs_swap_extents, }; void diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index d5dfedcb892..d79055207fb 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2005 Silicon Graphics, Inc. + * Copyright (c) 2000-2006 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -252,7 +252,7 @@ xfs_iomap( error = XFS_BMAPI(mp, NULL, io, offset_fsb, (xfs_filblks_t)(end_fsb - offset_fsb), bmapi_flags, NULL, 0, &imap, - &nimaps, NULL); + &nimaps, NULL, NULL); if (error) goto out; @@ -519,8 +519,8 @@ xfs_iomap_write_direct( */ XFS_BMAP_INIT(&free_list, &firstfsb); nimaps = 1; - error = xfs_bmapi(tp, ip, offset_fsb, count_fsb, - bmapi_flag, &firstfsb, 0, &imap, &nimaps, &free_list); + error = XFS_BMAPI(mp, tp, io, offset_fsb, count_fsb, bmapi_flag, + &firstfsb, 0, &imap, &nimaps, &free_list, NULL); if (error) goto error0; @@ -610,8 +610,8 @@ xfs_iomap_eof_want_preallocate( while (count_fsb > 0) { imaps = nimaps; firstblock = NULLFSBLOCK; - error = XFS_BMAPI(mp, NULL, io, start_fsb, count_fsb, - 0, &firstblock, 0, imap, &imaps, NULL); + error = XFS_BMAPI(mp, NULL, io, start_fsb, count_fsb, 0, + &firstblock, 0, imap, &imaps, NULL, NULL); if (error) return error; for (n = 0; n < imaps; n++) { @@ -695,11 +695,11 @@ retry: nimaps = XFS_WRITE_IMAPS; firstblock = NULLFSBLOCK; - error = xfs_bmapi(NULL, ip, offset_fsb, + error = XFS_BMAPI(mp, NULL, io, offset_fsb, (xfs_filblks_t)(last_fsb - offset_fsb), XFS_BMAPI_DELAY | XFS_BMAPI_WRITE | XFS_BMAPI_ENTIRE, &firstblock, 1, imap, - &nimaps, NULL); + &nimaps, NULL, NULL); if (error && (error != ENOSPC)) return XFS_ERROR(error); @@ -832,9 +832,9 @@ xfs_iomap_write_allocate( } /* Go get the actual blocks */ - error = xfs_bmapi(tp, ip, map_start_fsb, count_fsb, + error = XFS_BMAPI(mp, tp, io, map_start_fsb, count_fsb, XFS_BMAPI_WRITE, &first_block, 1, - imap, &nimaps, &free_list); + imap, &nimaps, &free_list, NULL); if (error) goto trans_cancel; @@ -955,9 +955,9 @@ xfs_iomap_write_unwritten( */ XFS_BMAP_INIT(&free_list, &firstfsb); nimaps = 1; - error = xfs_bmapi(tp, ip, offset_fsb, count_fsb, + error = XFS_BMAPI(mp, tp, io, offset_fsb, count_fsb, XFS_BMAPI_WRITE|XFS_BMAPI_CONVERT, &firstfsb, - 1, &imap, &nimaps, &free_list); + 1, &imap, &nimaps, &free_list, NULL); if (error) goto error_on_bmapi_transaction; diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 668ad23fd37..a682eb55810 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -63,6 +63,8 @@ struct xfs_perag; struct xfs_iocore; struct xfs_bmbt_irec; struct xfs_bmap_free; +struct xfs_extdelta; +struct xfs_swapext; extern struct vfsops xfs_vfsops; extern struct vnodeops xfs_vnodeops; @@ -194,7 +196,12 @@ typedef int (*xfs_bmapi_t)(struct xfs_trans *, void *, xfs_fileoff_t, xfs_filblks_t, int, xfs_fsblock_t *, xfs_extlen_t, struct xfs_bmbt_irec *, int *, - struct xfs_bmap_free *); + struct xfs_bmap_free *, struct xfs_extdelta *); +typedef int (*xfs_bunmapi_t)(struct xfs_trans *, + void *, xfs_fileoff_t, + xfs_filblks_t, int, xfs_extnum_t, + xfs_fsblock_t *, struct xfs_bmap_free *, + struct xfs_extdelta *, int *); typedef int (*xfs_bmap_eof_t)(void *, xfs_fileoff_t, int, int *); typedef int (*xfs_iomap_write_direct_t)( void *, xfs_off_t, size_t, int, @@ -214,10 +221,13 @@ typedef int (*xfs_lock_nowait_t)(void *, uint); typedef void (*xfs_unlk_t)(void *, unsigned int); typedef xfs_fsize_t (*xfs_size_t)(void *); typedef xfs_fsize_t (*xfs_iodone_t)(struct vfs *); +typedef int (*xfs_swap_extents_t)(void *, void *, + struct xfs_swapext*); typedef struct xfs_ioops { xfs_ioinit_t xfs_ioinit; xfs_bmapi_t xfs_bmapi_func; + xfs_bunmapi_t xfs_bunmapi_func; xfs_bmap_eof_t xfs_bmap_eof_func; xfs_iomap_write_direct_t xfs_iomap_write_direct; xfs_iomap_write_delay_t xfs_iomap_write_delay; @@ -230,13 +240,17 @@ typedef struct xfs_ioops { xfs_unlk_t xfs_unlock; xfs_size_t xfs_size_func; xfs_iodone_t xfs_iodone; + xfs_swap_extents_t xfs_swap_extents_func; } xfs_ioops_t; #define XFS_IOINIT(vfsp, args, flags) \ (*(mp)->m_io_ops.xfs_ioinit)(vfsp, args, flags) -#define XFS_BMAPI(mp, trans,io,bno,len,f,first,tot,mval,nmap,flist) \ +#define XFS_BMAPI(mp, trans,io,bno,len,f,first,tot,mval,nmap,flist,delta) \ (*(mp)->m_io_ops.xfs_bmapi_func) \ - (trans,(io)->io_obj,bno,len,f,first,tot,mval,nmap,flist) + (trans,(io)->io_obj,bno,len,f,first,tot,mval,nmap,flist,delta) +#define XFS_BUNMAPI(mp, trans,io,bno,len,f,nexts,first,flist,delta,done) \ + (*(mp)->m_io_ops.xfs_bunmapi_func) \ + (trans,(io)->io_obj,bno,len,f,nexts,first,flist,delta,done) #define XFS_BMAP_EOF(mp, io, endoff, whichfork, eof) \ (*(mp)->m_io_ops.xfs_bmap_eof_func) \ ((io)->io_obj, endoff, whichfork, eof) @@ -266,6 +280,9 @@ typedef struct xfs_ioops { (*(mp)->m_io_ops.xfs_size_func)((io)->io_obj) #define XFS_IODONE(vfsp) \ (*(mp)->m_io_ops.xfs_iodone)(vfsp) +#define XFS_SWAP_EXTENTS(mp, io, tio, sxp) \ + (*(mp)->m_io_ops.xfs_swap_extents_func) \ + ((io)->io_obj, (tio)->io_obj, sxp) #ifdef HAVE_PERCPU_SB diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index 5b413946b1c..f5944c8b378 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -141,7 +141,7 @@ xfs_growfs_rt_alloc( cancelflags |= XFS_TRANS_ABORT; error = xfs_bmapi(tp, ip, oblocks, nblocks - oblocks, XFS_BMAPI_WRITE | XFS_BMAPI_METADATA, &firstblock, - resblks, &map, &nmap, &flist); + resblks, &map, &nmap, &flist, NULL); if (!error && nmap < 1) error = XFS_ERROR(ENOSPC); if (error) diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 7027ae68ee3..567d14d06d9 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2005 Silicon Graphics, Inc. + * Copyright (c) 2000-2006 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -1000,7 +1000,7 @@ xfs_readlink( nmaps = SYMLINK_MAPS; error = xfs_bmapi(NULL, ip, 0, XFS_B_TO_FSB(mp, pathlen), - 0, NULL, 0, mval, &nmaps, NULL); + 0, NULL, 0, mval, &nmaps, NULL, NULL); if (error) { goto error_return; @@ -1208,8 +1208,8 @@ xfs_inactive_free_eofblocks( nimaps = 1; xfs_ilock(ip, XFS_ILOCK_SHARED); - error = xfs_bmapi(NULL, ip, end_fsb, map_len, 0, - NULL, 0, &imap, &nimaps, NULL); + error = XFS_BMAPI(mp, NULL, &ip->i_iocore, end_fsb, map_len, 0, + NULL, 0, &imap, &nimaps, NULL, NULL); xfs_iunlock(ip, XFS_ILOCK_SHARED); if (!error && (nimaps != 0) && @@ -1338,7 +1338,7 @@ xfs_inactive_symlink_rmt( nmaps = ARRAY_SIZE(mval); if ((error = xfs_bmapi(tp, ip, 0, XFS_B_TO_FSB(mp, size), XFS_BMAPI_METADATA, &first_block, 0, mval, &nmaps, - &free_list))) + &free_list, NULL))) goto error0; /* * Invalidate the block(s). @@ -1353,7 +1353,7 @@ xfs_inactive_symlink_rmt( * Unmap the dead block(s) to the free_list. */ if ((error = xfs_bunmapi(tp, ip, 0, size, XFS_BMAPI_METADATA, nmaps, - &first_block, &free_list, &done))) + &first_block, &free_list, NULL, &done))) goto error1; ASSERT(done); /* @@ -3457,7 +3457,7 @@ xfs_symlink( error = xfs_bmapi(tp, ip, first_fsb, fs_blocks, XFS_BMAPI_WRITE | XFS_BMAPI_METADATA, &first_block, resblks, mval, &nmaps, - &free_list); + &free_list, NULL); if (error) { goto error1; } @@ -4116,10 +4116,10 @@ retry: * Issue the xfs_bmapi() call to allocate the blocks */ XFS_BMAP_INIT(&free_list, &firstfsb); - error = xfs_bmapi(tp, ip, startoffset_fsb, + error = XFS_BMAPI(mp, tp, &ip->i_iocore, startoffset_fsb, allocatesize_fsb, bmapi_flag, &firstfsb, 0, imapp, &nimaps, - &free_list); + &free_list, NULL); if (error) { goto error0; } @@ -4199,8 +4199,8 @@ xfs_zero_remaining_bytes( for (offset = startoff; offset <= endoff; offset = lastoffset + 1) { offset_fsb = XFS_B_TO_FSBT(mp, offset); nimap = 1; - error = xfs_bmapi(NULL, ip, offset_fsb, 1, 0, NULL, 0, &imap, - &nimap, NULL); + error = XFS_BMAPI(mp, NULL, &ip->i_iocore, offset_fsb, 1, 0, + NULL, 0, &imap, &nimap, NULL, NULL); if (error || nimap < 1) break; ASSERT(imap.br_blockcount >= 1); @@ -4338,8 +4338,8 @@ xfs_free_file_space( */ if (rt && !XFS_SB_VERSION_HASEXTFLGBIT(&mp->m_sb)) { nimap = 1; - error = xfs_bmapi(NULL, ip, startoffset_fsb, 1, 0, NULL, 0, - &imap, &nimap, NULL); + error = XFS_BMAPI(mp, NULL, &ip->i_iocore, startoffset_fsb, + 1, 0, NULL, 0, &imap, &nimap, NULL, NULL); if (error) goto out_unlock_iolock; ASSERT(nimap == 0 || nimap == 1); @@ -4353,8 +4353,8 @@ xfs_free_file_space( startoffset_fsb += mp->m_sb.sb_rextsize - mod; } nimap = 1; - error = xfs_bmapi(NULL, ip, endoffset_fsb - 1, 1, 0, NULL, 0, - &imap, &nimap, NULL); + error = XFS_BMAPI(mp, NULL, &ip->i_iocore, endoffset_fsb - 1, + 1, 0, NULL, 0, &imap, &nimap, NULL, NULL); if (error) goto out_unlock_iolock; ASSERT(nimap == 0 || nimap == 1); @@ -4426,9 +4426,9 @@ xfs_free_file_space( * issue the bunmapi() call to free the blocks */ XFS_BMAP_INIT(&free_list, &firstfsb); - error = xfs_bunmapi(tp, ip, startoffset_fsb, + error = XFS_BUNMAPI(mp, tp, &ip->i_iocore, startoffset_fsb, endoffset_fsb - startoffset_fsb, - 0, 2, &firstfsb, &free_list, &done); + 0, 2, &firstfsb, &free_list, NULL, &done); if (error) { goto error0; } -- cgit v1.2.3 From ff9901c1e7c7be06a99c59cfc3133d2316cbc957 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 9 Jun 2006 14:48:37 +1000 Subject: [XFS] endianess annotations for xfs_dir2_data_entry_t SGI-PV: 943272 SGI-Modid: xfs-linux-melb:xfs-kern:25806a Signed-off-by: Christoph Hellwig Signed-off-by: Al Viro Signed-off-by: Nathan Scott --- fs/xfs/xfs_dir2_block.c | 16 ++++++++-------- fs/xfs/xfs_dir2_data.c | 2 +- fs/xfs/xfs_dir2_data.h | 8 ++++---- fs/xfs/xfs_dir2_leaf.c | 10 +++++----- fs/xfs/xfs_dir2_node.c | 8 ++++---- fs/xfs/xfs_dir2_sf.c | 10 +++++----- 6 files changed, 27 insertions(+), 27 deletions(-) diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c index 972ded59547..2621ff521db 100644 --- a/fs/xfs/xfs_dir2_block.c +++ b/fs/xfs/xfs_dir2_block.c @@ -400,7 +400,7 @@ xfs_dir2_block_addname( /* * Create the new data entry. */ - INT_SET(dep->inumber, ARCH_CONVERT, args->inumber); + dep->inumber = cpu_to_be64(args->inumber); dep->namelen = args->namelen; memcpy(dep->name, args->name, args->namelen); tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep); @@ -508,7 +508,7 @@ xfs_dir2_block_getdents( p.cook = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk, ptr - (char *)block); - p.ino = INT_GET(dep->inumber, ARCH_CONVERT); + p.ino = be64_to_cpu(dep->inumber); #if XFS_BIG_INUMS p.ino += mp->m_inoadd; #endif @@ -626,7 +626,7 @@ xfs_dir2_block_lookup( /* * Fill in inode number, release the block. */ - args->inumber = INT_GET(dep->inumber, ARCH_CONVERT); + args->inumber = be64_to_cpu(dep->inumber); xfs_da_brelse(args->trans, bp); return XFS_ERROR(EEXIST); } @@ -844,11 +844,11 @@ xfs_dir2_block_replace( */ dep = (xfs_dir2_data_entry_t *) ((char *)block + XFS_DIR2_DATAPTR_TO_OFF(mp, be32_to_cpu(blp[ent].address))); - ASSERT(INT_GET(dep->inumber, ARCH_CONVERT) != args->inumber); + ASSERT(be64_to_cpu(dep->inumber) != args->inumber); /* * Change the inode number to the new value. */ - INT_SET(dep->inumber, ARCH_CONVERT, args->inumber); + dep->inumber = cpu_to_be64(args->inumber); xfs_dir2_data_log_entry(args->trans, bp, dep); xfs_dir2_data_check(dp, bp); xfs_da_buf_done(bp); @@ -1130,7 +1130,7 @@ xfs_dir2_sf_to_block( */ dep = (xfs_dir2_data_entry_t *) ((char *)block + XFS_DIR2_DATA_DOT_OFFSET); - INT_SET(dep->inumber, ARCH_CONVERT, dp->i_ino); + dep->inumber = cpu_to_be64(dp->i_ino); dep->namelen = 1; dep->name[0] = '.'; tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep); @@ -1144,7 +1144,7 @@ xfs_dir2_sf_to_block( */ dep = (xfs_dir2_data_entry_t *) ((char *)block + XFS_DIR2_DATA_DOTDOT_OFFSET); - INT_SET(dep->inumber, ARCH_CONVERT, XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent)); + dep->inumber = cpu_to_be64(XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent)); dep->namelen = 2; dep->name[0] = dep->name[1] = '.'; tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep); @@ -1193,7 +1193,7 @@ xfs_dir2_sf_to_block( * Copy a real entry. */ dep = (xfs_dir2_data_entry_t *)((char *)block + newoffset); - INT_SET(dep->inumber, ARCH_CONVERT, XFS_DIR2_SF_GET_INUMBER(sfp, + dep->inumber = cpu_to_be64(XFS_DIR2_SF_GET_INUMBER(sfp, XFS_DIR2_SF_INUMBERP(sfep))); dep->namelen = sfep->namelen; memcpy(dep->name, sfep->name, dep->namelen); diff --git a/fs/xfs/xfs_dir2_data.c b/fs/xfs/xfs_dir2_data.c index bb3d03ff002..7be37d38961 100644 --- a/fs/xfs/xfs_dir2_data.c +++ b/fs/xfs/xfs_dir2_data.c @@ -133,7 +133,7 @@ xfs_dir2_data_check( */ dep = (xfs_dir2_data_entry_t *)p; ASSERT(dep->namelen != 0); - ASSERT(xfs_dir_ino_validate(mp, INT_GET(dep->inumber, ARCH_CONVERT)) == 0); + ASSERT(xfs_dir_ino_validate(mp, be64_to_cpu(dep->inumber)) == 0); ASSERT(be16_to_cpu(*XFS_DIR2_DATA_ENTRY_TAG_P(dep)) == (char *)dep - (char *)d); count++; diff --git a/fs/xfs/xfs_dir2_data.h b/fs/xfs/xfs_dir2_data.h index 0847cbb53e1..a6ae2d21c40 100644 --- a/fs/xfs/xfs_dir2_data.h +++ b/fs/xfs/xfs_dir2_data.h @@ -85,11 +85,11 @@ typedef struct xfs_dir2_data_hdr { * Tag appears as the last 2 bytes. */ typedef struct xfs_dir2_data_entry { - xfs_ino_t inumber; /* inode number */ - __uint8_t namelen; /* name length */ - __uint8_t name[1]; /* name bytes, no null */ + __be64 inumber; /* inode number */ + __u8 namelen; /* name length */ + __u8 name[1]; /* name bytes, no null */ /* variable offset */ - xfs_dir2_data_off_t tag; /* starting offset of us */ + __be16 tag; /* starting offset of us */ } xfs_dir2_data_entry_t; /* diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c index 5fe88d546c7..74ef99f2ee5 100644 --- a/fs/xfs/xfs_dir2_leaf.c +++ b/fs/xfs/xfs_dir2_leaf.c @@ -407,7 +407,7 @@ xfs_dir2_leaf_addname( * Initialize our new entry (at last). */ dep = (xfs_dir2_data_entry_t *)dup; - INT_SET(dep->inumber, ARCH_CONVERT, args->inumber); + dep->inumber = cpu_to_be64(args->inumber); dep->namelen = args->namelen; memcpy(dep->name, args->name, dep->namelen); tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep); @@ -1098,7 +1098,7 @@ xfs_dir2_leaf_getdents( p->cook = XFS_DIR2_BYTE_TO_DATAPTR(mp, curoff + length); - p->ino = INT_GET(dep->inumber, ARCH_CONVERT); + p->ino = be64_to_cpu(dep->inumber); #if XFS_BIG_INUMS p->ino += mp->m_inoadd; #endif @@ -1319,7 +1319,7 @@ xfs_dir2_leaf_lookup( /* * Return the found inode number. */ - args->inumber = INT_GET(dep->inumber, ARCH_CONVERT); + args->inumber = be64_to_cpu(dep->inumber); xfs_da_brelse(tp, dbp); xfs_da_brelse(tp, lbp); return XFS_ERROR(EEXIST); @@ -1606,11 +1606,11 @@ xfs_dir2_leaf_replace( dep = (xfs_dir2_data_entry_t *) ((char *)dbp->data + XFS_DIR2_DATAPTR_TO_OFF(dp->i_mount, be32_to_cpu(lep->address))); - ASSERT(args->inumber != INT_GET(dep->inumber, ARCH_CONVERT)); + ASSERT(args->inumber != be64_to_cpu(dep->inumber)); /* * Put the new inode number in, log it. */ - INT_SET(dep->inumber, ARCH_CONVERT, args->inumber); + dep->inumber = cpu_to_be64(args->inumber); tp = args->trans; xfs_dir2_data_log_entry(tp, dbp, dep); xfs_da_buf_done(dbp); diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c index ac511ab9c52..c0e8fcf5e13 100644 --- a/fs/xfs/xfs_dir2_node.c +++ b/fs/xfs/xfs_dir2_node.c @@ -580,7 +580,7 @@ xfs_dir2_leafn_lookup_int( if (dep->namelen == args->namelen && dep->name[0] == args->name[0] && memcmp(dep->name, args->name, args->namelen) == 0) { - args->inumber = INT_GET(dep->inumber, ARCH_CONVERT); + args->inumber = be64_to_cpu(dep->inumber); *indexp = index; state->extravalid = 1; state->extrablk.bp = curbp; @@ -1695,7 +1695,7 @@ xfs_dir2_node_addname_int( * Fill in the new entry and log it. */ dep = (xfs_dir2_data_entry_t *)dup; - INT_SET(dep->inumber, ARCH_CONVERT, args->inumber); + dep->inumber = cpu_to_be64(args->inumber); dep->namelen = args->namelen; memcpy(dep->name, args->name, dep->namelen); tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep); @@ -1905,11 +1905,11 @@ xfs_dir2_node_replace( dep = (xfs_dir2_data_entry_t *) ((char *)data + XFS_DIR2_DATAPTR_TO_OFF(state->mp, be32_to_cpu(lep->address))); - ASSERT(inum != INT_GET(dep->inumber, ARCH_CONVERT)); + ASSERT(inum != be64_to_cpu(dep->inumber)); /* * Fill in the new inode number and log the entry. */ - INT_SET(dep->inumber, ARCH_CONVERT, inum); + dep->inumber = cpu_to_be64(inum); xfs_dir2_data_log_entry(args->trans, state->extrablk.bp, dep); rval = 0; } diff --git a/fs/xfs/xfs_dir2_sf.c b/fs/xfs/xfs_dir2_sf.c index d98a41d1fe6..06afa1b324c 100644 --- a/fs/xfs/xfs_dir2_sf.c +++ b/fs/xfs/xfs_dir2_sf.c @@ -117,13 +117,13 @@ xfs_dir2_block_sfsize( dep->name[0] == '.' && dep->name[1] == '.'; #if XFS_BIG_INUMS if (!isdot) - i8count += INT_GET(dep->inumber, ARCH_CONVERT) > XFS_DIR2_MAX_SHORT_INUM; + i8count += be64_to_cpu(dep->inumber) > XFS_DIR2_MAX_SHORT_INUM; #endif if (!isdot && !isdotdot) { count++; namelen += dep->namelen; } else if (isdotdot) - parent = INT_GET(dep->inumber, ARCH_CONVERT); + parent = be64_to_cpu(dep->inumber); /* * Calculate the new size, see if we should give up yet. */ @@ -229,13 +229,13 @@ xfs_dir2_block_to_sf( * Skip . */ if (dep->namelen == 1 && dep->name[0] == '.') - ASSERT(INT_GET(dep->inumber, ARCH_CONVERT) == dp->i_ino); + ASSERT(be64_to_cpu(dep->inumber) == dp->i_ino); /* * Skip .., but make sure the inode number is right. */ else if (dep->namelen == 2 && dep->name[0] == '.' && dep->name[1] == '.') - ASSERT(INT_GET(dep->inumber, ARCH_CONVERT) == + ASSERT(be64_to_cpu(dep->inumber) == XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent)); /* * Normal entry, copy it into shortform. @@ -246,7 +246,7 @@ xfs_dir2_block_to_sf( (xfs_dir2_data_aoff_t) ((char *)dep - (char *)block)); memcpy(sfep->name, dep->name, dep->namelen); - temp=INT_GET(dep->inumber, ARCH_CONVERT); + temp = be64_to_cpu(dep->inumber); XFS_DIR2_SF_PUT_INUMBER(sfp, &temp, XFS_DIR2_SF_INUMBERP(sfep)); sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep); -- cgit v1.2.3 From 8034fff39bb9430d807375ec7a04097efba42cd2 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 9 Jun 2006 14:50:24 +1000 Subject: [XFS] endianess annotations for xfs_dir_leaf_hdr_t SGI-PV: 943272 SGI-Modid: xfs-linux-melb:xfs-kern:25807a Signed-off-by: Christoph Hellwig Signed-off-by: Al Viro Signed-off-by: Nathan Scott --- fs/xfs/xfs_da_btree.c | 2 +- fs/xfs/xfs_dir.c | 11 +- fs/xfs/xfs_dir_leaf.c | 326 ++++++++++++++++++++++++++------------------------ fs/xfs/xfs_dir_leaf.h | 14 +-- 4 files changed, 182 insertions(+), 171 deletions(-) diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c index 47b86f9f69f..296aa525ac4 100644 --- a/fs/xfs/xfs_da_btree.c +++ b/fs/xfs/xfs_da_btree.c @@ -1786,7 +1786,7 @@ xfs_da_swap_lastblock(xfs_da_args_t *args, xfs_dablk_t *dead_blknop, dead_leaf = (xfs_dir_leafblock_t *)dead_info; dead_level = 0; dead_hash = - INT_GET(dead_leaf->entries[INT_GET(dead_leaf->hdr.count, ARCH_CONVERT) - 1].hashval, ARCH_CONVERT); + INT_GET(dead_leaf->entries[be16_to_cpu(dead_leaf->hdr.count) - 1].hashval, ARCH_CONVERT); } else if (be16_to_cpu(dead_info->magic) == XFS_DIR2_LEAFN_MAGIC) { ASSERT(XFS_DIR_IS_V2(mp)); dead_leaf2 = (xfs_dir2_leaf_t *)dead_info; diff --git a/fs/xfs/xfs_dir.c b/fs/xfs/xfs_dir.c index 9cc702a839a..a3b0e97dbf9 100644 --- a/fs/xfs/xfs_dir.c +++ b/fs/xfs/xfs_dir.c @@ -638,8 +638,8 @@ xfs_dir_leaf_removename(xfs_da_args_t *args, int *count, int *totallen) retval = xfs_dir_leaf_lookup_int(bp, args, &index); if (retval == EEXIST) { (void)xfs_dir_leaf_remove(args->trans, bp, index); - *count = INT_GET(leaf->hdr.count, ARCH_CONVERT); - *totallen = INT_GET(leaf->hdr.namebytes, ARCH_CONVERT); + *count = be16_to_cpu(leaf->hdr.count); + *totallen = be16_to_cpu(leaf->hdr.namebytes); retval = 0; } xfs_da_buf_done(bp); @@ -925,7 +925,7 @@ xfs_dir_node_getdents(xfs_trans_t *trans, xfs_inode_t *dp, uio_t *uio, bp = NULL; } if (bp && - cookhash > INT_GET(leaf->entries[INT_GET(leaf->hdr.count, ARCH_CONVERT) - 1].hashval, ARCH_CONVERT)) { + cookhash > INT_GET(leaf->entries[be16_to_cpu(leaf->hdr.count) - 1].hashval, ARCH_CONVERT)) { xfs_dir_trace_g_dub("node: leaf hash too small", dp, uio, bno); xfs_da_brelse(trans, bp); @@ -1142,7 +1142,7 @@ void xfs_dir_trace_g_dul(char *where, xfs_inode_t *dp, uio_t *uio, xfs_dir_leafblock_t *leaf) { - int last = INT_GET(leaf->hdr.count, ARCH_CONVERT) - 1; + int last = be16_to_cpu(leaf->hdr.count) - 1; xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DUL, where, (void *)dp, (void *)dp->i_mount, @@ -1150,8 +1150,7 @@ xfs_dir_trace_g_dul(char *where, xfs_inode_t *dp, uio_t *uio, (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)), (void *)(unsigned long)uio->uio_resid, (void *)(unsigned long)be32_to_cpu(leaf->hdr.info.forw), - (void *)(unsigned long) - INT_GET(leaf->hdr.count, ARCH_CONVERT), + (void *)(unsigned long)be16_to_cpu(leaf->hdr.count), (void *)(unsigned long) INT_GET(leaf->entries[0].hashval, ARCH_CONVERT), (void *)(unsigned long) diff --git a/fs/xfs/xfs_dir_leaf.c b/fs/xfs/xfs_dir_leaf.c index 6d711869262..6a4d8caaba7 100644 --- a/fs/xfs/xfs_dir_leaf.c +++ b/fs/xfs/xfs_dir_leaf.c @@ -651,7 +651,7 @@ xfs_dir_leaf_to_shortform(xfs_da_args_t *iargs) */ hdr = &leaf->hdr; entry = &leaf->entries[0]; - for (i = INT_GET(hdr->count, ARCH_CONVERT)-1; i >= 0; entry++, i--) { + for (i = be16_to_cpu(hdr->count)-1; i >= 0; entry++, i--) { namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT)); if ((entry->namelen == 2) && (namest->name[0] == '.') && @@ -681,7 +681,7 @@ xfs_dir_leaf_to_shortform(xfs_da_args_t *iargs) args.trans = iargs->trans; args.justcheck = 0; args.addname = args.oknoent = 1; - for (i = 0; i < INT_GET(hdr->count, ARCH_CONVERT); entry++, i++) { + for (i = 0; i < be16_to_cpu(hdr->count); entry++, i++) { if (!entry->nameidx) continue; namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT)); @@ -744,7 +744,7 @@ xfs_dir_leaf_to_node(xfs_da_args_t *args) ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); node->btree[0].hashval = cpu_to_be32( INT_GET(leaf->entries[ - INT_GET(leaf->hdr.count, ARCH_CONVERT)-1].hashval, ARCH_CONVERT)); + be16_to_cpu(leaf->hdr.count)-1].hashval, ARCH_CONVERT)); xfs_da_buf_done(bp2); node->btree[0].before = cpu_to_be32(blkno); node->hdr.count = cpu_to_be16(1); @@ -783,11 +783,12 @@ xfs_dir_leaf_create(xfs_da_args_t *args, xfs_dablk_t blkno, xfs_dabuf_t **bpp) memset((char *)leaf, 0, XFS_LBSIZE(dp->i_mount)); hdr = &leaf->hdr; hdr->info.magic = cpu_to_be16(XFS_DIR_LEAF_MAGIC); - INT_SET(hdr->firstused, ARCH_CONVERT, XFS_LBSIZE(dp->i_mount)); + hdr->firstused = cpu_to_be16(XFS_LBSIZE(dp->i_mount)); if (!hdr->firstused) - INT_SET(hdr->firstused, ARCH_CONVERT, XFS_LBSIZE(dp->i_mount) - 1); - INT_SET(hdr->freemap[0].base, ARCH_CONVERT, sizeof(xfs_dir_leaf_hdr_t)); - INT_SET(hdr->freemap[0].size, ARCH_CONVERT, INT_GET(hdr->firstused, ARCH_CONVERT) - INT_GET(hdr->freemap[0].base, ARCH_CONVERT)); + hdr->firstused = cpu_to_be16(XFS_LBSIZE(dp->i_mount) - 1); + hdr->freemap[0].base = cpu_to_be16(sizeof(xfs_dir_leaf_hdr_t)); + hdr->freemap[0].size = cpu_to_be16(be16_to_cpu(hdr->firstused) - + be16_to_cpu(hdr->freemap[0].base)); xfs_da_log_buf(args->trans, bp, 0, XFS_LBSIZE(dp->i_mount) - 1); @@ -862,7 +863,7 @@ xfs_dir_leaf_add(xfs_dabuf_t *bp, xfs_da_args_t *args, int index) leaf = bp->data; ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); - ASSERT((index >= 0) && (index <= INT_GET(leaf->hdr.count, ARCH_CONVERT))); + ASSERT((index >= 0) && (index <= be16_to_cpu(leaf->hdr.count))); hdr = &leaf->hdr; entsize = XFS_DIR_LEAF_ENTSIZE_BYNAME(args->namelen); @@ -870,25 +871,25 @@ xfs_dir_leaf_add(xfs_dabuf_t *bp, xfs_da_args_t *args, int index) * Search through freemap for first-fit on new name length. * (may need to figure in size of entry struct too) */ - tablesize = (INT_GET(hdr->count, ARCH_CONVERT) + 1) * (uint)sizeof(xfs_dir_leaf_entry_t) - + (uint)sizeof(xfs_dir_leaf_hdr_t); + tablesize = (be16_to_cpu(hdr->count) + 1) * + sizeof(xfs_dir_leaf_entry_t) + sizeof(xfs_dir_leaf_hdr_t); map = &hdr->freemap[XFS_DIR_LEAF_MAPSIZE-1]; for (sum = 0, i = XFS_DIR_LEAF_MAPSIZE-1; i >= 0; map--, i--) { - if (tablesize > INT_GET(hdr->firstused, ARCH_CONVERT)) { - sum += INT_GET(map->size, ARCH_CONVERT); + if (tablesize > be16_to_cpu(hdr->firstused)) { + sum += be16_to_cpu(map->size); continue; } if (!map->size) continue; /* no space in this map */ tmp = entsize; - if (INT_GET(map->base, ARCH_CONVERT) < INT_GET(hdr->firstused, ARCH_CONVERT)) + if (be16_to_cpu(map->base) < be16_to_cpu(hdr->firstused)) tmp += (uint)sizeof(xfs_dir_leaf_entry_t); - if (INT_GET(map->size, ARCH_CONVERT) >= tmp) { + if (be16_to_cpu(map->size) >= tmp) { if (!args->justcheck) xfs_dir_leaf_add_work(bp, args, index, i); return 0; } - sum += INT_GET(map->size, ARCH_CONVERT); + sum += be16_to_cpu(map->size); } /* @@ -915,7 +916,7 @@ xfs_dir_leaf_add(xfs_dabuf_t *bp, xfs_da_args_t *args, int index) * After compaction, the block is guaranteed to have only one * free region, in freemap[0]. If it is not big enough, give up. */ - if (INT_GET(hdr->freemap[0].size, ARCH_CONVERT) < + if (be16_to_cpu(hdr->freemap[0].size) < (entsize + (uint)sizeof(xfs_dir_leaf_entry_t))) return XFS_ERROR(ENOSPC); @@ -944,31 +945,32 @@ xfs_dir_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int index, ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); hdr = &leaf->hdr; ASSERT((mapindex >= 0) && (mapindex < XFS_DIR_LEAF_MAPSIZE)); - ASSERT((index >= 0) && (index <= INT_GET(hdr->count, ARCH_CONVERT))); + ASSERT((index >= 0) && (index <= be16_to_cpu(hdr->count))); /* * Force open some space in the entry array and fill it in. */ entry = &leaf->entries[index]; - if (index < INT_GET(hdr->count, ARCH_CONVERT)) { - tmp = INT_GET(hdr->count, ARCH_CONVERT) - index; + if (index < be16_to_cpu(hdr->count)) { + tmp = be16_to_cpu(hdr->count) - index; tmp *= (uint)sizeof(xfs_dir_leaf_entry_t); memmove(entry + 1, entry, tmp); xfs_da_log_buf(args->trans, bp, XFS_DA_LOGRANGE(leaf, entry, tmp + (uint)sizeof(*entry))); } - INT_MOD(hdr->count, ARCH_CONVERT, +1); + be16_add(&hdr->count, 1); /* * Allocate space for the new string (at the end of the run). */ map = &hdr->freemap[mapindex]; mp = args->trans->t_mountp; - ASSERT(INT_GET(map->base, ARCH_CONVERT) < XFS_LBSIZE(mp)); - ASSERT(INT_GET(map->size, ARCH_CONVERT) >= XFS_DIR_LEAF_ENTSIZE_BYNAME(args->namelen)); - ASSERT(INT_GET(map->size, ARCH_CONVERT) < XFS_LBSIZE(mp)); - INT_MOD(map->size, ARCH_CONVERT, -(XFS_DIR_LEAF_ENTSIZE_BYNAME(args->namelen))); - INT_SET(entry->nameidx, ARCH_CONVERT, INT_GET(map->base, ARCH_CONVERT) + INT_GET(map->size, ARCH_CONVERT)); + ASSERT(be16_to_cpu(map->base) < XFS_LBSIZE(mp)); + ASSERT(be16_to_cpu(map->size) >= XFS_DIR_LEAF_ENTSIZE_BYNAME(args->namelen)); + ASSERT(be16_to_cpu(map->size) < XFS_LBSIZE(mp)); + + be16_add(&map->size, -(XFS_DIR_LEAF_ENTSIZE_BYNAME(args->namelen))); + INT_SET(entry->nameidx, ARCH_CONVERT, be16_to_cpu(map->base) + be16_to_cpu(map->size)); INT_SET(entry->hashval, ARCH_CONVERT, args->hashval); entry->namelen = args->namelen; xfs_da_log_buf(args->trans, bp, @@ -986,19 +988,21 @@ xfs_dir_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int index, /* * Update the control info for this leaf node */ - if (INT_GET(entry->nameidx, ARCH_CONVERT) < INT_GET(hdr->firstused, ARCH_CONVERT)) - INT_COPY(hdr->firstused, entry->nameidx, ARCH_CONVERT); - ASSERT(INT_GET(hdr->firstused, ARCH_CONVERT) >= ((INT_GET(hdr->count, ARCH_CONVERT)*sizeof(*entry))+sizeof(*hdr))); - tmp = (INT_GET(hdr->count, ARCH_CONVERT)-1) * (uint)sizeof(xfs_dir_leaf_entry_t) + if (INT_GET(entry->nameidx, ARCH_CONVERT) < be16_to_cpu(hdr->firstused)) + hdr->firstused = entry->nameidx; + ASSERT(be16_to_cpu(hdr->firstused) >= + ((be16_to_cpu(hdr->count)*sizeof(*entry))+sizeof(*hdr))); + tmp = (be16_to_cpu(hdr->count)-1) * (uint)sizeof(xfs_dir_leaf_entry_t) + (uint)sizeof(xfs_dir_leaf_hdr_t); map = &hdr->freemap[0]; for (i = 0; i < XFS_DIR_LEAF_MAPSIZE; map++, i++) { - if (INT_GET(map->base, ARCH_CONVERT) == tmp) { - INT_MOD(map->base, ARCH_CONVERT, (uint)sizeof(xfs_dir_leaf_entry_t)); - INT_MOD(map->size, ARCH_CONVERT, -((uint)sizeof(xfs_dir_leaf_entry_t))); + if (be16_to_cpu(map->base) == tmp) { + int entry_size = sizeof(xfs_dir_leaf_entry_t); + be16_add(&map->base, entry_size); + be16_add(&map->size, -entry_size); } } - INT_MOD(hdr->namebytes, ARCH_CONVERT, args->namelen); + be16_add(&hdr->namebytes, args->namelen); xfs_da_log_buf(args->trans, bp, XFS_DA_LOGRANGE(leaf, hdr, sizeof(*hdr))); } @@ -1042,23 +1046,24 @@ xfs_dir_leaf_compact(xfs_trans_t *trans, xfs_dabuf_t *bp, int musthave, hdr_s = &leaf_s->hdr; hdr_d = &leaf_d->hdr; hdr_d->info = hdr_s->info; /* struct copy */ - INT_SET(hdr_d->firstused, ARCH_CONVERT, lbsize); + hdr_d->firstused = cpu_to_be16(lbsize); if (!hdr_d->firstused) - INT_SET(hdr_d->firstused, ARCH_CONVERT, lbsize - 1); + hdr_d->firstused = cpu_to_be16(lbsize - 1); hdr_d->namebytes = 0; hdr_d->count = 0; hdr_d->holes = 0; - INT_SET(hdr_d->freemap[0].base, ARCH_CONVERT, sizeof(xfs_dir_leaf_hdr_t)); - INT_SET(hdr_d->freemap[0].size, ARCH_CONVERT, INT_GET(hdr_d->firstused, ARCH_CONVERT) - INT_GET(hdr_d->freemap[0].base, ARCH_CONVERT)); + hdr_d->freemap[0].base = cpu_to_be16(sizeof(xfs_dir_leaf_hdr_t)); + hdr_d->freemap[0].size = cpu_to_be16(be16_to_cpu(hdr_d->firstused) - + be16_to_cpu(hdr_d->freemap[0].base)); /* * Copy all entry's in the same (sorted) order, * but allocate filenames packed and in sequence. * This changes the source (leaf_s) as well. */ - xfs_dir_leaf_moveents(leaf_s, 0, leaf_d, 0, (int)INT_GET(hdr_s->count, ARCH_CONVERT), mp); + xfs_dir_leaf_moveents(leaf_s, 0, leaf_d, 0, be16_to_cpu(hdr_s->count), mp); - if (musthave && INT_GET(hdr_d->freemap[0].size, ARCH_CONVERT) < musthave) + if (musthave && be16_to_cpu(hdr_d->freemap[0].size) < musthave) rval = XFS_ERROR(ENOSPC); else rval = 0; @@ -1129,20 +1134,20 @@ xfs_dir_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, /* * Move any entries required from leaf to leaf: */ - if (count < INT_GET(hdr1->count, ARCH_CONVERT)) { + if (count < be16_to_cpu(hdr1->count)) { /* * Figure the total bytes to be added to the destination leaf. */ - count = INT_GET(hdr1->count, ARCH_CONVERT) - count; /* number entries being moved */ - space = INT_GET(hdr1->namebytes, ARCH_CONVERT) - totallen; + count = be16_to_cpu(hdr1->count) - count; /* number entries being moved */ + space = be16_to_cpu(hdr1->namebytes) - totallen; space += count * ((uint)sizeof(xfs_dir_leaf_name_t)-1); space += count * (uint)sizeof(xfs_dir_leaf_entry_t); /* * leaf2 is the destination, compact it if it looks tight. */ - max = INT_GET(hdr2->firstused, ARCH_CONVERT) - (uint)sizeof(xfs_dir_leaf_hdr_t); - max -= INT_GET(hdr2->count, ARCH_CONVERT) * (uint)sizeof(xfs_dir_leaf_entry_t); + max = be16_to_cpu(hdr2->firstused) - (uint)sizeof(xfs_dir_leaf_hdr_t); + max -= be16_to_cpu(hdr2->count) * (uint)sizeof(xfs_dir_leaf_entry_t); if (space > max) { xfs_dir_leaf_compact(state->args->trans, blk2->bp, 0, 0); @@ -1151,7 +1156,7 @@ xfs_dir_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, /* * Move high entries from leaf1 to low end of leaf2. */ - xfs_dir_leaf_moveents(leaf1, INT_GET(hdr1->count, ARCH_CONVERT) - count, + xfs_dir_leaf_moveents(leaf1, be16_to_cpu(hdr1->count) - count, leaf2, 0, count, state->mp); xfs_da_log_buf(state->args->trans, blk1->bp, 0, @@ -1159,20 +1164,20 @@ xfs_dir_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, xfs_da_log_buf(state->args->trans, blk2->bp, 0, state->blocksize-1); - } else if (count > INT_GET(hdr1->count, ARCH_CONVERT)) { + } else if (count > be16_to_cpu(hdr1->count)) { /* * Figure the total bytes to be added to the destination leaf. */ - count -= INT_GET(hdr1->count, ARCH_CONVERT); /* number entries being moved */ - space = totallen - INT_GET(hdr1->namebytes, ARCH_CONVERT); + count -= be16_to_cpu(hdr1->count); /* number entries being moved */ + space = totallen - be16_to_cpu(hdr1->namebytes); space += count * ((uint)sizeof(xfs_dir_leaf_name_t)-1); space += count * (uint)sizeof(xfs_dir_leaf_entry_t); /* * leaf1 is the destination, compact it if it looks tight. */ - max = INT_GET(hdr1->firstused, ARCH_CONVERT) - (uint)sizeof(xfs_dir_leaf_hdr_t); - max -= INT_GET(hdr1->count, ARCH_CONVERT) * (uint)sizeof(xfs_dir_leaf_entry_t); + max = be16_to_cpu(hdr1->firstused) - (uint)sizeof(xfs_dir_leaf_hdr_t); + max -= be16_to_cpu(hdr1->count) * (uint)sizeof(xfs_dir_leaf_entry_t); if (space > max) { xfs_dir_leaf_compact(state->args->trans, blk1->bp, 0, 0); @@ -1181,7 +1186,7 @@ xfs_dir_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, /* * Move low entries from leaf2 to high end of leaf1. */ - xfs_dir_leaf_moveents(leaf2, 0, leaf1, (int)INT_GET(hdr1->count, ARCH_CONVERT), + xfs_dir_leaf_moveents(leaf2, 0, leaf1, be16_to_cpu(hdr1->count), count, state->mp); xfs_da_log_buf(state->args->trans, blk1->bp, 0, @@ -1193,15 +1198,15 @@ xfs_dir_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, /* * Copy out last hashval in each block for B-tree code. */ - blk1->hashval = INT_GET(leaf1->entries[ INT_GET(leaf1->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT); - blk2->hashval = INT_GET(leaf2->entries[ INT_GET(leaf2->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT); + blk1->hashval = INT_GET(leaf1->entries[be16_to_cpu(leaf1->hdr.count)-1].hashval, ARCH_CONVERT); + blk2->hashval = INT_GET(leaf2->entries[be16_to_cpu(leaf2->hdr.count)-1].hashval, ARCH_CONVERT); /* * Adjust the expected index for insertion. * GROT: this doesn't work unless blk2 was originally empty. */ if (!state->inleaf) { - blk2->index = blk1->index - INT_GET(leaf1->hdr.count, ARCH_CONVERT); + blk2->index = blk1->index - be16_to_cpu(leaf1->hdr.count); } } @@ -1238,9 +1243,10 @@ xfs_dir_leaf_figure_balance(xfs_da_state_t *state, * Examine entries until we reduce the absolute difference in * byte usage between the two blocks to a minimum. */ - max = INT_GET(hdr1->count, ARCH_CONVERT) + INT_GET(hdr2->count, ARCH_CONVERT); + max = be16_to_cpu(hdr1->count) + be16_to_cpu(hdr2->count); half = (max+1) * (uint)(sizeof(*entry)+sizeof(xfs_dir_leaf_entry_t)-1); - half += INT_GET(hdr1->namebytes, ARCH_CONVERT) + INT_GET(hdr2->namebytes, ARCH_CONVERT) + state->args->namelen; + half += be16_to_cpu(hdr1->namebytes) + be16_to_cpu(hdr2->namebytes) + + state->args->namelen; half /= 2; lastdelta = state->blocksize; entry = &leaf1->entries[0]; @@ -1263,7 +1269,7 @@ xfs_dir_leaf_figure_balance(xfs_da_state_t *state, /* * Wrap around into the second block if necessary. */ - if (count == INT_GET(hdr1->count, ARCH_CONVERT)) { + if (count == be16_to_cpu(hdr1->count)) { leaf1 = leaf2; entry = &leaf1->entries[0]; } @@ -1328,11 +1334,11 @@ xfs_dir_leaf_toosmall(xfs_da_state_t *state, int *action) info = blk->bp->data; ASSERT(be16_to_cpu(info->magic) == XFS_DIR_LEAF_MAGIC); leaf = (xfs_dir_leafblock_t *)info; - count = INT_GET(leaf->hdr.count, ARCH_CONVERT); + count = be16_to_cpu(leaf->hdr.count); bytes = (uint)sizeof(xfs_dir_leaf_hdr_t) + count * (uint)sizeof(xfs_dir_leaf_entry_t) + count * ((uint)sizeof(xfs_dir_leaf_name_t)-1) + - INT_GET(leaf->hdr.namebytes, ARCH_CONVERT); + be16_to_cpu(leaf->hdr.namebytes); if (bytes > (state->blocksize >> 1)) { *action = 0; /* blk over 50%, don't try to join */ return 0; @@ -1386,13 +1392,13 @@ xfs_dir_leaf_toosmall(xfs_da_state_t *state, int *action) ASSERT(bp != NULL); leaf = (xfs_dir_leafblock_t *)info; - count = INT_GET(leaf->hdr.count, ARCH_CONVERT); + count = be16_to_cpu(leaf->hdr.count); bytes = state->blocksize - (state->blocksize>>2); - bytes -= INT_GET(leaf->hdr.namebytes, ARCH_CONVERT); + bytes -= be16_to_cpu(leaf->hdr.namebytes); leaf = bp->data; ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); - count += INT_GET(leaf->hdr.count, ARCH_CONVERT); - bytes -= INT_GET(leaf->hdr.namebytes, ARCH_CONVERT); + count += be16_to_cpu(leaf->hdr.count); + bytes -= be16_to_cpu(leaf->hdr.namebytes); bytes -= count * ((uint)sizeof(xfs_dir_leaf_name_t) - 1); bytes -= count * (uint)sizeof(xfs_dir_leaf_entry_t); bytes -= (uint)sizeof(xfs_dir_leaf_hdr_t); @@ -1451,11 +1457,12 @@ xfs_dir_leaf_remove(xfs_trans_t *trans, xfs_dabuf_t *bp, int index) ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); hdr = &leaf->hdr; mp = trans->t_mountp; - ASSERT((INT_GET(hdr->count, ARCH_CONVERT) > 0) && (INT_GET(hdr->count, ARCH_CONVERT) < (XFS_LBSIZE(mp)/8))); - ASSERT((index >= 0) && (index < INT_GET(hdr->count, ARCH_CONVERT))); - ASSERT(INT_GET(hdr->firstused, ARCH_CONVERT) >= ((INT_GET(hdr->count, ARCH_CONVERT)*sizeof(*entry))+sizeof(*hdr))); + ASSERT(hdr->count && (be16_to_cpu(hdr->count) < (XFS_LBSIZE(mp)/8))); + ASSERT((index >= 0) && (index < be16_to_cpu(hdr->count))); + ASSERT(be16_to_cpu(hdr->firstused) >= + ((be16_to_cpu(hdr->count)*sizeof(*entry))+sizeof(*hdr))); entry = &leaf->entries[index]; - ASSERT(INT_GET(entry->nameidx, ARCH_CONVERT) >= INT_GET(hdr->firstused, ARCH_CONVERT)); + ASSERT(INT_GET(entry->nameidx, ARCH_CONVERT) >= be16_to_cpu(hdr->firstused)); ASSERT(INT_GET(entry->nameidx, ARCH_CONVERT) < XFS_LBSIZE(mp)); /* @@ -1464,27 +1471,28 @@ xfs_dir_leaf_remove(xfs_trans_t *trans, xfs_dabuf_t *bp, int index) * find smallest free region in case we need to replace it, * adjust any map that borders the entry table, */ - tablesize = INT_GET(hdr->count, ARCH_CONVERT) * (uint)sizeof(xfs_dir_leaf_entry_t) + tablesize = be16_to_cpu(hdr->count) * (uint)sizeof(xfs_dir_leaf_entry_t) + (uint)sizeof(xfs_dir_leaf_hdr_t); map = &hdr->freemap[0]; - tmp = INT_GET(map->size, ARCH_CONVERT); + tmp = be16_to_cpu(map->size); before = after = -1; smallest = XFS_DIR_LEAF_MAPSIZE - 1; entsize = XFS_DIR_LEAF_ENTSIZE_BYENTRY(entry); for (i = 0; i < XFS_DIR_LEAF_MAPSIZE; map++, i++) { - ASSERT(INT_GET(map->base, ARCH_CONVERT) < XFS_LBSIZE(mp)); - ASSERT(INT_GET(map->size, ARCH_CONVERT) < XFS_LBSIZE(mp)); - if (INT_GET(map->base, ARCH_CONVERT) == tablesize) { - INT_MOD(map->base, ARCH_CONVERT, -((uint)sizeof(xfs_dir_leaf_entry_t))); - INT_MOD(map->size, ARCH_CONVERT, (uint)sizeof(xfs_dir_leaf_entry_t)); + ASSERT(be16_to_cpu(map->base) < XFS_LBSIZE(mp)); + ASSERT(be16_to_cpu(map->size) < XFS_LBSIZE(mp)); + if (be16_to_cpu(map->base) == tablesize) { + int entry_size = sizeof(xfs_dir_leaf_entry_t); + be16_add(&map->base, -entry_size); + be16_add(&map->size, entry_size); } - if ((INT_GET(map->base, ARCH_CONVERT) + INT_GET(map->size, ARCH_CONVERT)) == INT_GET(entry->nameidx, ARCH_CONVERT)) { + if ((be16_to_cpu(map->base) + be16_to_cpu(map->size)) == INT_GET(entry->nameidx, ARCH_CONVERT)) { before = i; - } else if (INT_GET(map->base, ARCH_CONVERT) == (INT_GET(entry->nameidx, ARCH_CONVERT) + entsize)) { + } else if (be16_to_cpu(map->base) == (INT_GET(entry->nameidx, ARCH_CONVERT) + entsize)) { after = i; - } else if (INT_GET(map->size, ARCH_CONVERT) < tmp) { - tmp = INT_GET(map->size, ARCH_CONVERT); + } else if (be16_to_cpu(map->size) < tmp) { + tmp = be16_to_cpu(map->size); smallest = i; } } @@ -1496,33 +1504,33 @@ xfs_dir_leaf_remove(xfs_trans_t *trans, xfs_dabuf_t *bp, int index) if ((before >= 0) || (after >= 0)) { if ((before >= 0) && (after >= 0)) { map = &hdr->freemap[before]; - INT_MOD(map->size, ARCH_CONVERT, entsize); - INT_MOD(map->size, ARCH_CONVERT, INT_GET(hdr->freemap[after].size, ARCH_CONVERT)); + be16_add(&map->size, entsize); + be16_add(&map->size, be16_to_cpu(hdr->freemap[after].size)); hdr->freemap[after].base = 0; hdr->freemap[after].size = 0; } else if (before >= 0) { map = &hdr->freemap[before]; - INT_MOD(map->size, ARCH_CONVERT, entsize); + be16_add(&map->size, entsize); } else { map = &hdr->freemap[after]; - INT_COPY(map->base, entry->nameidx, ARCH_CONVERT); - INT_MOD(map->size, ARCH_CONVERT, entsize); + map->base = entry->nameidx; + be16_add(&map->size, entsize); } } else { /* * Replace smallest region (if it is smaller than free'd entry) */ map = &hdr->freemap[smallest]; - if (INT_GET(map->size, ARCH_CONVERT) < entsize) { - INT_COPY(map->base, entry->nameidx, ARCH_CONVERT); - INT_SET(map->size, ARCH_CONVERT, entsize); + if (be16_to_cpu(map->size) < entsize) { + map->base = entry->nameidx; + map->size = cpu_to_be16(entsize); } } /* * Did we remove the first entry? */ - if (INT_GET(entry->nameidx, ARCH_CONVERT) == INT_GET(hdr->firstused, ARCH_CONVERT)) + if (INT_GET(entry->nameidx, ARCH_CONVERT) == be16_to_cpu(hdr->firstused)) smallest = 1; else smallest = 0; @@ -1534,13 +1542,13 @@ xfs_dir_leaf_remove(xfs_trans_t *trans, xfs_dabuf_t *bp, int index) memset((char *)namest, 0, entsize); xfs_da_log_buf(trans, bp, XFS_DA_LOGRANGE(leaf, namest, entsize)); - INT_MOD(hdr->namebytes, ARCH_CONVERT, -(entry->namelen)); - tmp = (INT_GET(hdr->count, ARCH_CONVERT) - index) * (uint)sizeof(xfs_dir_leaf_entry_t); + be16_add(&hdr->namebytes, -(entry->namelen)); + tmp = (be16_to_cpu(hdr->count) - index) * (uint)sizeof(xfs_dir_leaf_entry_t); memmove(entry, entry + 1, tmp); - INT_MOD(hdr->count, ARCH_CONVERT, -1); + be16_add(&hdr->count, -1); xfs_da_log_buf(trans, bp, XFS_DA_LOGRANGE(leaf, entry, tmp + (uint)sizeof(*entry))); - entry = &leaf->entries[INT_GET(hdr->count, ARCH_CONVERT)]; + entry = &leaf->entries[be16_to_cpu(hdr->count)]; memset((char *)entry, 0, sizeof(xfs_dir_leaf_entry_t)); /* @@ -1552,15 +1560,16 @@ xfs_dir_leaf_remove(xfs_trans_t *trans, xfs_dabuf_t *bp, int index) if (smallest) { tmp = XFS_LBSIZE(mp); entry = &leaf->entries[0]; - for (i = INT_GET(hdr->count, ARCH_CONVERT)-1; i >= 0; entry++, i--) { - ASSERT(INT_GET(entry->nameidx, ARCH_CONVERT) >= INT_GET(hdr->firstused, ARCH_CONVERT)); + for (i = be16_to_cpu(hdr->count)-1; i >= 0; entry++, i--) { + ASSERT(INT_GET(entry->nameidx, ARCH_CONVERT) >= + be16_to_cpu(hdr->firstused)); ASSERT(INT_GET(entry->nameidx, ARCH_CONVERT) < XFS_LBSIZE(mp)); if (INT_GET(entry->nameidx, ARCH_CONVERT) < tmp) tmp = INT_GET(entry->nameidx, ARCH_CONVERT); } - INT_SET(hdr->firstused, ARCH_CONVERT, tmp); + hdr->firstused = cpu_to_be16(tmp); if (!hdr->firstused) - INT_SET(hdr->firstused, ARCH_CONVERT, tmp - 1); + hdr->firstused = cpu_to_be16(tmp - 1); } else { hdr->holes = 1; /* mark as needing compaction */ } @@ -1572,9 +1581,9 @@ xfs_dir_leaf_remove(xfs_trans_t *trans, xfs_dabuf_t *bp, int index) * "join" the leaf with a sibling if so. */ tmp = (uint)sizeof(xfs_dir_leaf_hdr_t); - tmp += INT_GET(leaf->hdr.count, ARCH_CONVERT) * (uint)sizeof(xfs_dir_leaf_entry_t); - tmp += INT_GET(leaf->hdr.count, ARCH_CONVERT) * ((uint)sizeof(xfs_dir_leaf_name_t) - 1); - tmp += INT_GET(leaf->hdr.namebytes, ARCH_CONVERT); + tmp += be16_to_cpu(leaf->hdr.count) * (uint)sizeof(xfs_dir_leaf_entry_t); + tmp += be16_to_cpu(leaf->hdr.count) * ((uint)sizeof(xfs_dir_leaf_name_t) - 1); + tmp += be16_to_cpu(leaf->hdr.namebytes); if (tmp < mp->m_dir_magicpct) return 1; /* leaf is < 37% full */ return 0; @@ -1608,7 +1617,7 @@ xfs_dir_leaf_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk, /* * Save last hashval from dying block for later Btree fixup. */ - drop_blk->hashval = INT_GET(drop_leaf->entries[ drop_leaf->hdr.count-1 ].hashval, ARCH_CONVERT); + drop_blk->hashval = INT_GET(drop_leaf->entries[be16_to_cpu(drop_leaf->hdr.count)-1].hashval, ARCH_CONVERT); /* * Check if we need a temp buffer, or can we do it in place. @@ -1622,11 +1631,11 @@ xfs_dir_leaf_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk, */ if (xfs_dir_leaf_order(save_blk->bp, drop_blk->bp)) { xfs_dir_leaf_moveents(drop_leaf, 0, save_leaf, 0, - (int)INT_GET(drop_hdr->count, ARCH_CONVERT), mp); + be16_to_cpu(drop_hdr->count), mp); } else { xfs_dir_leaf_moveents(drop_leaf, 0, - save_leaf, INT_GET(save_hdr->count, ARCH_CONVERT), - (int)INT_GET(drop_hdr->count, ARCH_CONVERT), mp); + save_leaf, be16_to_cpu(save_hdr->count), + be16_to_cpu(drop_hdr->count), mp); } } else { /* @@ -1640,22 +1649,22 @@ xfs_dir_leaf_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk, tmp_hdr = &tmp_leaf->hdr; tmp_hdr->info = save_hdr->info; /* struct copy */ tmp_hdr->count = 0; - INT_SET(tmp_hdr->firstused, ARCH_CONVERT, state->blocksize); + tmp_hdr->firstused = cpu_to_be16(state->blocksize); if (!tmp_hdr->firstused) - INT_SET(tmp_hdr->firstused, ARCH_CONVERT, state->blocksize - 1); + tmp_hdr->firstused = cpu_to_be16(state->blocksize - 1); tmp_hdr->namebytes = 0; if (xfs_dir_leaf_order(save_blk->bp, drop_blk->bp)) { xfs_dir_leaf_moveents(drop_leaf, 0, tmp_leaf, 0, - (int)INT_GET(drop_hdr->count, ARCH_CONVERT), mp); + be16_to_cpu(drop_hdr->count), mp); xfs_dir_leaf_moveents(save_leaf, 0, - tmp_leaf, INT_GET(tmp_leaf->hdr.count, ARCH_CONVERT), - (int)INT_GET(save_hdr->count, ARCH_CONVERT), mp); + tmp_leaf, be16_to_cpu(tmp_leaf->hdr.count), + be16_to_cpu(save_hdr->count), mp); } else { xfs_dir_leaf_moveents(save_leaf, 0, tmp_leaf, 0, - (int)INT_GET(save_hdr->count, ARCH_CONVERT), mp); + be16_to_cpu(save_hdr->count), mp); xfs_dir_leaf_moveents(drop_leaf, 0, - tmp_leaf, INT_GET(tmp_leaf->hdr.count, ARCH_CONVERT), - (int)INT_GET(drop_hdr->count, ARCH_CONVERT), mp); + tmp_leaf, be16_to_cpu(tmp_leaf->hdr.count), + be16_to_cpu(drop_hdr->count), mp); } memcpy(save_leaf, tmp_leaf, state->blocksize); kmem_free(tmpbuffer, state->blocksize); @@ -1667,7 +1676,7 @@ xfs_dir_leaf_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk, /* * Copy out last hashval in each block for B-tree code. */ - save_blk->hashval = INT_GET(save_leaf->entries[ INT_GET(save_leaf->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT); + save_blk->hashval = INT_GET(save_leaf->entries[be16_to_cpu(save_leaf->hdr.count)-1 ].hashval, ARCH_CONVERT); } /*======================================================================== @@ -1697,13 +1706,13 @@ xfs_dir_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args, int *index) leaf = bp->data; ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); - ASSERT(INT_GET(leaf->hdr.count, ARCH_CONVERT) < (XFS_LBSIZE(args->dp->i_mount)/8)); + ASSERT(be16_to_cpu(leaf->hdr.count) < (XFS_LBSIZE(args->dp->i_mount)/8)); /* * Binary search. (note: small blocks will skip this loop) */ hashval = args->hashval; - probe = span = INT_GET(leaf->hdr.count, ARCH_CONVERT) / 2; + probe = span = be16_to_cpu(leaf->hdr.count) / 2; for (entry = &leaf->entries[probe]; span > 4; entry = &leaf->entries[probe]) { span /= 2; @@ -1715,7 +1724,7 @@ xfs_dir_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args, int *index) break; } ASSERT((probe >= 0) && \ - ((!leaf->hdr.count) || (probe < INT_GET(leaf->hdr.count, ARCH_CONVERT)))); + ((!leaf->hdr.count) || (probe < be16_to_cpu(leaf->hdr.count)))); ASSERT((span <= 4) || (INT_GET(entry->hashval, ARCH_CONVERT) == hashval)); /* @@ -1726,11 +1735,11 @@ xfs_dir_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args, int *index) entry--; probe--; } - while ((probe < INT_GET(leaf->hdr.count, ARCH_CONVERT)) && (INT_GET(entry->hashval, ARCH_CONVERT) < hashval)) { + while ((probe < be16_to_cpu(leaf->hdr.count)) && (INT_GET(entry->hashval, ARCH_CONVERT) < hashval)) { entry++; probe++; } - if ((probe == INT_GET(leaf->hdr.count, ARCH_CONVERT)) || (INT_GET(entry->hashval, ARCH_CONVERT) != hashval)) { + if ((probe == be16_to_cpu(leaf->hdr.count)) || (INT_GET(entry->hashval, ARCH_CONVERT) != hashval)) { *index = probe; ASSERT(args->oknoent); return XFS_ERROR(ENOENT); @@ -1739,7 +1748,7 @@ xfs_dir_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args, int *index) /* * Duplicate keys may be present, so search all of them for a match. */ - while ((probe < INT_GET(leaf->hdr.count, ARCH_CONVERT)) && (INT_GET(entry->hashval, ARCH_CONVERT) == hashval)) { + while ((probe < be16_to_cpu(leaf->hdr.count)) && (INT_GET(entry->hashval, ARCH_CONVERT) == hashval)) { namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT)); if (entry->namelen == args->namelen && namest->name[0] == args->name[0] && @@ -1752,7 +1761,7 @@ xfs_dir_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args, int *index) probe++; } *index = probe; - ASSERT(probe == INT_GET(leaf->hdr.count, ARCH_CONVERT) || args->oknoent); + ASSERT(probe == be16_to_cpu(leaf->hdr.count) || args->oknoent); return XFS_ERROR(ENOENT); } @@ -1787,22 +1796,22 @@ xfs_dir_leaf_moveents(xfs_dir_leafblock_t *leaf_s, int start_s, ASSERT(be16_to_cpu(leaf_d->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); hdr_s = &leaf_s->hdr; hdr_d = &leaf_d->hdr; - ASSERT((INT_GET(hdr_s->count, ARCH_CONVERT) > 0) && (INT_GET(hdr_s->count, ARCH_CONVERT) < (XFS_LBSIZE(mp)/8))); - ASSERT(INT_GET(hdr_s->firstused, ARCH_CONVERT) >= - ((INT_GET(hdr_s->count, ARCH_CONVERT)*sizeof(*entry_s))+sizeof(*hdr_s))); - ASSERT(INT_GET(hdr_d->count, ARCH_CONVERT) < (XFS_LBSIZE(mp)/8)); - ASSERT(INT_GET(hdr_d->firstused, ARCH_CONVERT) >= - ((INT_GET(hdr_d->count, ARCH_CONVERT)*sizeof(*entry_d))+sizeof(*hdr_d))); + ASSERT(hdr_s->count && (be16_to_cpu(hdr_s->count) < (XFS_LBSIZE(mp)/8))); + ASSERT(be16_to_cpu(hdr_s->firstused) >= + ((be16_to_cpu(hdr_s->count)*sizeof(*entry_s))+sizeof(*hdr_s))); + ASSERT(be16_to_cpu(hdr_d->count) < (XFS_LBSIZE(mp)/8)); + ASSERT(be16_to_cpu(hdr_d->firstused) >= + ((be16_to_cpu(hdr_d->count)*sizeof(*entry_d))+sizeof(*hdr_d))); - ASSERT(start_s < INT_GET(hdr_s->count, ARCH_CONVERT)); - ASSERT(start_d <= INT_GET(hdr_d->count, ARCH_CONVERT)); - ASSERT(count <= INT_GET(hdr_s->count, ARCH_CONVERT)); + ASSERT(start_s < be16_to_cpu(hdr_s->count)); + ASSERT(start_d <= be16_to_cpu(hdr_d->count)); + ASSERT(count <= be16_to_cpu(hdr_s->count)); /* * Move the entries in the destination leaf up to make a hole? */ - if (start_d < INT_GET(hdr_d->count, ARCH_CONVERT)) { - tmp = INT_GET(hdr_d->count, ARCH_CONVERT) - start_d; + if (start_d < be16_to_cpu(hdr_d->count)) { + tmp = be16_to_cpu(hdr_d->count) - start_d; tmp *= (uint)sizeof(xfs_dir_leaf_entry_t); entry_s = &leaf_d->entries[start_d]; entry_d = &leaf_d->entries[start_d + count]; @@ -1816,11 +1825,12 @@ xfs_dir_leaf_moveents(xfs_dir_leafblock_t *leaf_s, int start_s, entry_s = &leaf_s->entries[start_s]; entry_d = &leaf_d->entries[start_d]; for (i = 0; i < count; entry_s++, entry_d++, i++) { - ASSERT(INT_GET(entry_s->nameidx, ARCH_CONVERT) >= INT_GET(hdr_s->firstused, ARCH_CONVERT)); + ASSERT(INT_GET(entry_s->nameidx, ARCH_CONVERT) >= + be16_to_cpu(hdr_s->firstused)); tmp = XFS_DIR_LEAF_ENTSIZE_BYENTRY(entry_s); - INT_MOD(hdr_d->firstused, ARCH_CONVERT, -(tmp)); - entry_d->hashval = entry_s->hashval; /* INT_: direct copy */ - INT_COPY(entry_d->nameidx, hdr_d->firstused, ARCH_CONVERT); + be16_add(&hdr_d->firstused, -(tmp)); + entry_d->hashval = entry_s->hashval; + entry_d->nameidx = hdr_d->firstused; entry_d->namelen = entry_s->namelen; ASSERT(INT_GET(entry_d->nameidx, ARCH_CONVERT) + tmp <= XFS_LBSIZE(mp)); memcpy(XFS_DIR_LEAF_NAMESTRUCT(leaf_d, INT_GET(entry_d->nameidx, ARCH_CONVERT)), @@ -1828,20 +1838,20 @@ xfs_dir_leaf_moveents(xfs_dir_leafblock_t *leaf_s, int start_s, ASSERT(INT_GET(entry_s->nameidx, ARCH_CONVERT) + tmp <= XFS_LBSIZE(mp)); memset((char *)XFS_DIR_LEAF_NAMESTRUCT(leaf_s, INT_GET(entry_s->nameidx, ARCH_CONVERT)), 0, tmp); - INT_MOD(hdr_s->namebytes, ARCH_CONVERT, -(entry_d->namelen)); - INT_MOD(hdr_d->namebytes, ARCH_CONVERT, entry_d->namelen); - INT_MOD(hdr_s->count, ARCH_CONVERT, -1); - INT_MOD(hdr_d->count, ARCH_CONVERT, +1); - tmp = INT_GET(hdr_d->count, ARCH_CONVERT) * (uint)sizeof(xfs_dir_leaf_entry_t) + be16_add(&hdr_s->namebytes, -(entry_d->namelen)); + be16_add(&hdr_d->namebytes, entry_d->namelen); + be16_add(&hdr_s->count, -1); + be16_add(&hdr_d->count, +1); + tmp = be16_to_cpu(hdr_d->count) * (uint)sizeof(xfs_dir_leaf_entry_t) + (uint)sizeof(xfs_dir_leaf_hdr_t); - ASSERT(INT_GET(hdr_d->firstused, ARCH_CONVERT) >= tmp); + ASSERT(be16_to_cpu(hdr_d->firstused) >= tmp); } /* * Zero out the entries we just copied. */ - if (start_s == INT_GET(hdr_s->count, ARCH_CONVERT)) { + if (start_s == be16_to_cpu(hdr_s->count)) { tmp = count * (uint)sizeof(xfs_dir_leaf_entry_t); entry_s = &leaf_s->entries[start_s]; ASSERT((char *)entry_s + tmp <= (char *)leaf_s + XFS_LBSIZE(mp)); @@ -1851,14 +1861,14 @@ xfs_dir_leaf_moveents(xfs_dir_leafblock_t *leaf_s, int start_s, * Move the remaining entries down to fill the hole, * then zero the entries at the top. */ - tmp = INT_GET(hdr_s->count, ARCH_CONVERT) - count; + tmp = be16_to_cpu(hdr_s->count) - count; tmp *= (uint)sizeof(xfs_dir_leaf_entry_t); entry_s = &leaf_s->entries[start_s + count]; entry_d = &leaf_s->entries[start_s]; memcpy(entry_d, entry_s, tmp); tmp = count * (uint)sizeof(xfs_dir_leaf_entry_t); - entry_s = &leaf_s->entries[INT_GET(hdr_s->count, ARCH_CONVERT)]; + entry_s = &leaf_s->entries[be16_to_cpu(hdr_s->count)]; ASSERT((char *)entry_s + tmp <= (char *)leaf_s + XFS_LBSIZE(mp)); memset((char *)entry_s, 0, tmp); } @@ -1866,11 +1876,14 @@ xfs_dir_leaf_moveents(xfs_dir_leafblock_t *leaf_s, int start_s, /* * Fill in the freemap information */ - INT_SET(hdr_d->freemap[0].base, ARCH_CONVERT, (uint)sizeof(xfs_dir_leaf_hdr_t)); - INT_MOD(hdr_d->freemap[0].base, ARCH_CONVERT, INT_GET(hdr_d->count, ARCH_CONVERT) * (uint)sizeof(xfs_dir_leaf_entry_t)); - INT_SET(hdr_d->freemap[0].size, ARCH_CONVERT, INT_GET(hdr_d->firstused, ARCH_CONVERT) - INT_GET(hdr_d->freemap[0].base, ARCH_CONVERT)); - INT_SET(hdr_d->freemap[1].base, ARCH_CONVERT, (hdr_d->freemap[2].base = 0)); - INT_SET(hdr_d->freemap[1].size, ARCH_CONVERT, (hdr_d->freemap[2].size = 0)); + hdr_d->freemap[0].base = cpu_to_be16(sizeof(xfs_dir_leaf_hdr_t) + + be16_to_cpu(hdr_d->count) * sizeof(xfs_dir_leaf_entry_t)); + hdr_d->freemap[0].size = cpu_to_be16(be16_to_cpu(hdr_d->firstused) - + be16_to_cpu(hdr_d->freemap[0].base)); + hdr_d->freemap[1].base = 0; + hdr_d->freemap[1].size = 0; + hdr_d->freemap[2].base = 0; + hdr_d->freemap[2].size = 0; hdr_s->holes = 1; /* leaf may not be compact */ } @@ -1886,11 +1899,11 @@ xfs_dir_leaf_order(xfs_dabuf_t *leaf1_bp, xfs_dabuf_t *leaf2_bp) leaf2 = leaf2_bp->data; ASSERT((be16_to_cpu(leaf1->hdr.info.magic) == XFS_DIR_LEAF_MAGIC) && (be16_to_cpu(leaf2->hdr.info.magic) == XFS_DIR_LEAF_MAGIC)); - if ((INT_GET(leaf1->hdr.count, ARCH_CONVERT) > 0) && (INT_GET(leaf2->hdr.count, ARCH_CONVERT) > 0) && + if (leaf1->hdr.count && leaf2->hdr.count && ((INT_GET(leaf2->entries[ 0 ].hashval, ARCH_CONVERT) < INT_GET(leaf1->entries[ 0 ].hashval, ARCH_CONVERT)) || - (INT_GET(leaf2->entries[ INT_GET(leaf2->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT) < - INT_GET(leaf1->entries[ INT_GET(leaf1->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT)))) { + (INT_GET(leaf2->entries[be16_to_cpu(leaf2->hdr.count)-1].hashval, ARCH_CONVERT) < + INT_GET(leaf1->entries[be16_to_cpu(leaf1->hdr.count)-1].hashval, ARCH_CONVERT)))) { return 1; } return 0; @@ -1907,10 +1920,10 @@ xfs_dir_leaf_lasthash(xfs_dabuf_t *bp, int *count) leaf = bp->data; ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); if (count) - *count = INT_GET(leaf->hdr.count, ARCH_CONVERT); + *count = be16_to_cpu(leaf->hdr.count); if (!leaf->hdr.count) return(0); - return(INT_GET(leaf->entries[ INT_GET(leaf->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT)); + return(INT_GET(leaf->entries[be16_to_cpu(leaf->hdr.count)-1].hashval, ARCH_CONVERT)); } /* @@ -1956,8 +1969,7 @@ xfs_dir_leaf_getdents_int( * Re-find our place. */ for (i = entno = 0, entry = &leaf->entries[0]; - i < INT_GET(leaf->hdr.count, ARCH_CONVERT); - entry++, i++) { + i < be16_to_cpu(leaf->hdr.count); entry++, i++) { namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT)); @@ -1991,7 +2003,7 @@ xfs_dir_leaf_getdents_int( } } - if (i == INT_GET(leaf->hdr.count, ARCH_CONVERT)) { + if (i == be16_to_cpu(leaf->hdr.count)) { xfs_dir_trace_g_du("leaf: hash not found", dp, uio); if (!leaf->hdr.info.forw) uio->uio_offset = @@ -2012,7 +2024,7 @@ xfs_dir_leaf_getdents_int( /* * We're synchronized, start copying entries out to the user. */ - for (; entno >= 0 && i < INT_GET(leaf->hdr.count, ARCH_CONVERT); + for (; entno >= 0 && i < be16_to_cpu(leaf->hdr.count); entry++, i++, (entno = nextentno)) { int lastresid=0, retval; xfs_dircook_t lastoffset; @@ -2037,7 +2049,7 @@ xfs_dir_leaf_getdents_int( xfs_dir_trace_g_duc("leaf: middle cookie ", dp, uio, p.cook.o); - if (i < (INT_GET(leaf->hdr.count, ARCH_CONVERT) - 1)) { + if (i < (be16_to_cpu(leaf->hdr.count) - 1)) { nexthash = INT_GET(entry[1].hashval, ARCH_CONVERT); if (nexthash == INT_GET(entry->hashval, ARCH_CONVERT)) diff --git a/fs/xfs/xfs_dir_leaf.h b/fs/xfs/xfs_dir_leaf.h index eb8cd9a4667..c6979ab829c 100644 --- a/fs/xfs/xfs_dir_leaf.h +++ b/fs/xfs/xfs_dir_leaf.h @@ -68,17 +68,17 @@ struct xfs_trans; #define XFS_DIR_LEAF_MAPSIZE 3 /* how many freespace slots */ typedef struct xfs_dir_leaf_map { /* RLE map of free bytes */ - __uint16_t base; /* base of free region */ - __uint16_t size; /* run length of free region */ + __be16 base; /* base of free region */ + __be16 size; /* run length of free region */ } xfs_dir_leaf_map_t; typedef struct xfs_dir_leaf_hdr { /* constant-structure header block */ xfs_da_blkinfo_t info; /* block type, links, etc. */ - __uint16_t count; /* count of active leaf_entry's */ - __uint16_t namebytes; /* num bytes of name strings stored */ - __uint16_t firstused; /* first used byte in name area */ - __uint8_t holes; /* != 0 if blk needs compaction */ - __uint8_t pad1; + __be16 count; /* count of active leaf_entry's */ + __be16 namebytes; /* num bytes of name strings stored */ + __be16 firstused; /* first used byte in name area */ + __u8 holes; /* != 0 if blk needs compaction */ + __u8 pad1; xfs_dir_leaf_map_t freemap[XFS_DIR_LEAF_MAPSIZE]; } xfs_dir_leaf_hdr_t; -- cgit v1.2.3 From 1d8daf06f67c8920a640eb61b30c3176ecc52405 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 9 Jun 2006 14:50:37 +1000 Subject: [XFS] endianess annotations for xfs_dir_leaf_entry_t SGI-PV: 943272 SGI-Modid: xfs-linux-melb:xfs-kern:25808a Signed-off-by: Christoph Hellwig Signed-off-by: Al Viro Signed-off-by: Nathan Scott --- fs/xfs/xfs_da_btree.c | 4 +- fs/xfs/xfs_dir.c | 19 ++++---- fs/xfs/xfs_dir_leaf.c | 127 ++++++++++++++++++++++++++------------------------ fs/xfs/xfs_dir_leaf.h | 8 ++-- 4 files changed, 80 insertions(+), 78 deletions(-) diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c index 296aa525ac4..260c3d770c0 100644 --- a/fs/xfs/xfs_da_btree.c +++ b/fs/xfs/xfs_da_btree.c @@ -1785,8 +1785,8 @@ xfs_da_swap_lastblock(xfs_da_args_t *args, xfs_dablk_t *dead_blknop, ASSERT(XFS_DIR_IS_V1(mp)); dead_leaf = (xfs_dir_leafblock_t *)dead_info; dead_level = 0; - dead_hash = - INT_GET(dead_leaf->entries[be16_to_cpu(dead_leaf->hdr.count) - 1].hashval, ARCH_CONVERT); + dead_hash = be32_to_cpu(dead_leaf->entries[ + be16_to_cpu(dead_leaf->hdr.count) - 1].hashval); } else if (be16_to_cpu(dead_info->magic) == XFS_DIR2_LEAFN_MAGIC) { ASSERT(XFS_DIR_IS_V2(mp)); dead_leaf2 = (xfs_dir2_leaf_t *)dead_info; diff --git a/fs/xfs/xfs_dir.c b/fs/xfs/xfs_dir.c index a3b0e97dbf9..3cd8657a81f 100644 --- a/fs/xfs/xfs_dir.c +++ b/fs/xfs/xfs_dir.c @@ -710,7 +710,7 @@ xfs_dir_leaf_replace(xfs_da_args_t *args) if (retval == EEXIST) { leaf = bp->data; entry = &leaf->entries[index]; - namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT)); + namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, be16_to_cpu(entry->nameidx)); /* XXX - replace assert? */ XFS_DIR_SF_PUT_DIRINO(&inum, &namest->inumber); xfs_da_log_buf(args->trans, bp, @@ -918,14 +918,14 @@ xfs_dir_node_getdents(xfs_trans_t *trans, xfs_inode_t *dp, uio_t *uio, xfs_da_brelse(trans, bp); bp = NULL; } - if (bp && INT_GET(leaf->entries[0].hashval, ARCH_CONVERT) > cookhash) { + if (bp && be32_to_cpu(leaf->entries[0].hashval) > cookhash) { xfs_dir_trace_g_dub("node: leaf hash too large", dp, uio, bno); xfs_da_brelse(trans, bp); bp = NULL; } - if (bp && - cookhash > INT_GET(leaf->entries[be16_to_cpu(leaf->hdr.count) - 1].hashval, ARCH_CONVERT)) { + if (bp && cookhash > be32_to_cpu(leaf->entries[ + be16_to_cpu(leaf->hdr.count) - 1].hashval)) { xfs_dir_trace_g_dub("node: leaf hash too small", dp, uio, bno); xfs_da_brelse(trans, bp); @@ -1059,7 +1059,7 @@ xfs_dir_node_replace(xfs_da_args_t *args) bp = blk->bp; leaf = bp->data; entry = &leaf->entries[blk->index]; - namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT)); + namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, be16_to_cpu(entry->nameidx)); /* XXX - replace assert ? */ XFS_DIR_SF_PUT_DIRINO(&inum, &namest->inumber); xfs_da_log_buf(args->trans, bp, @@ -1151,10 +1151,8 @@ xfs_dir_trace_g_dul(char *where, xfs_inode_t *dp, uio_t *uio, (void *)(unsigned long)uio->uio_resid, (void *)(unsigned long)be32_to_cpu(leaf->hdr.info.forw), (void *)(unsigned long)be16_to_cpu(leaf->hdr.count), - (void *)(unsigned long) - INT_GET(leaf->entries[0].hashval, ARCH_CONVERT), - (void *)(unsigned long) - INT_GET(leaf->entries[last].hashval, ARCH_CONVERT), + (void *)(unsigned long)be32_to_cpu(leaf->entries[0].hashval), + (void *)(unsigned long)be32_to_cpu(leaf->entries[last].hashval), NULL, NULL, NULL); } @@ -1170,8 +1168,7 @@ xfs_dir_trace_g_due(char *where, xfs_inode_t *dp, uio_t *uio, (void *)((unsigned long)(uio->uio_offset >> 32)), (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)), (void *)(unsigned long)uio->uio_resid, - (void *)(unsigned long) - INT_GET(entry->hashval, ARCH_CONVERT), + (void *)(unsigned long)be32_to_cpu(entry->hashval), NULL, NULL, NULL, NULL, NULL, NULL); } diff --git a/fs/xfs/xfs_dir_leaf.c b/fs/xfs/xfs_dir_leaf.c index 6a4d8caaba7..e7121040cd9 100644 --- a/fs/xfs/xfs_dir_leaf.c +++ b/fs/xfs/xfs_dir_leaf.c @@ -652,7 +652,7 @@ xfs_dir_leaf_to_shortform(xfs_da_args_t *iargs) hdr = &leaf->hdr; entry = &leaf->entries[0]; for (i = be16_to_cpu(hdr->count)-1; i >= 0; entry++, i--) { - namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT)); + namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, be16_to_cpu(entry->nameidx)); if ((entry->namelen == 2) && (namest->name[0] == '.') && (namest->name[1] == '.')) { @@ -684,10 +684,10 @@ xfs_dir_leaf_to_shortform(xfs_da_args_t *iargs) for (i = 0; i < be16_to_cpu(hdr->count); entry++, i++) { if (!entry->nameidx) continue; - namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT)); + namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, be16_to_cpu(entry->nameidx)); args.name = (char *)(namest->name); args.namelen = entry->namelen; - args.hashval = INT_GET(entry->hashval, ARCH_CONVERT); + args.hashval = be32_to_cpu(entry->hashval); XFS_DIR_SF_GET_DIRINO(&namest->inumber, &args.inumber); xfs_dir_shortform_addname(&args); } @@ -742,9 +742,7 @@ xfs_dir_leaf_to_node(xfs_da_args_t *args) node = bp1->data; leaf = bp2->data; ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); - node->btree[0].hashval = cpu_to_be32( - INT_GET(leaf->entries[ - be16_to_cpu(leaf->hdr.count)-1].hashval, ARCH_CONVERT)); + node->btree[0].hashval = leaf->entries[be16_to_cpu(leaf->hdr.count)-1].hashval; xfs_da_buf_done(bp2); node->btree[0].before = cpu_to_be32(blkno); node->hdr.count = cpu_to_be16(1); @@ -970,8 +968,9 @@ xfs_dir_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int index, ASSERT(be16_to_cpu(map->size) < XFS_LBSIZE(mp)); be16_add(&map->size, -(XFS_DIR_LEAF_ENTSIZE_BYNAME(args->namelen))); - INT_SET(entry->nameidx, ARCH_CONVERT, be16_to_cpu(map->base) + be16_to_cpu(map->size)); - INT_SET(entry->hashval, ARCH_CONVERT, args->hashval); + entry->nameidx = cpu_to_be16(be16_to_cpu(map->base) + + be16_to_cpu(map->size)); + entry->hashval = cpu_to_be32(args->hashval); entry->namelen = args->namelen; xfs_da_log_buf(args->trans, bp, XFS_DA_LOGRANGE(leaf, entry, sizeof(*entry))); @@ -979,7 +978,7 @@ xfs_dir_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int index, /* * Copy the string and inode number into the new space. */ - namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT)); + namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, be16_to_cpu(entry->nameidx)); XFS_DIR_SF_PUT_DIRINO(&args->inumber, &namest->inumber); memcpy(namest->name, args->name, args->namelen); xfs_da_log_buf(args->trans, bp, @@ -988,7 +987,7 @@ xfs_dir_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int index, /* * Update the control info for this leaf node */ - if (INT_GET(entry->nameidx, ARCH_CONVERT) < be16_to_cpu(hdr->firstused)) + if (be16_to_cpu(entry->nameidx) < be16_to_cpu(hdr->firstused)) hdr->firstused = entry->nameidx; ASSERT(be16_to_cpu(hdr->firstused) >= ((be16_to_cpu(hdr->count)*sizeof(*entry))+sizeof(*hdr))); @@ -1198,8 +1197,10 @@ xfs_dir_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, /* * Copy out last hashval in each block for B-tree code. */ - blk1->hashval = INT_GET(leaf1->entries[be16_to_cpu(leaf1->hdr.count)-1].hashval, ARCH_CONVERT); - blk2->hashval = INT_GET(leaf2->entries[be16_to_cpu(leaf2->hdr.count)-1].hashval, ARCH_CONVERT); + blk1->hashval = be32_to_cpu(leaf1->entries[ + be16_to_cpu(leaf1->hdr.count)-1].hashval); + blk2->hashval = be32_to_cpu(leaf2->entries[ + be16_to_cpu(leaf2->hdr.count)-1].hashval); /* * Adjust the expected index for insertion. @@ -1462,8 +1463,8 @@ xfs_dir_leaf_remove(xfs_trans_t *trans, xfs_dabuf_t *bp, int index) ASSERT(be16_to_cpu(hdr->firstused) >= ((be16_to_cpu(hdr->count)*sizeof(*entry))+sizeof(*hdr))); entry = &leaf->entries[index]; - ASSERT(INT_GET(entry->nameidx, ARCH_CONVERT) >= be16_to_cpu(hdr->firstused)); - ASSERT(INT_GET(entry->nameidx, ARCH_CONVERT) < XFS_LBSIZE(mp)); + ASSERT(be16_to_cpu(entry->nameidx) >= be16_to_cpu(hdr->firstused)); + ASSERT(be16_to_cpu(entry->nameidx) < XFS_LBSIZE(mp)); /* * Scan through free region table: @@ -1487,9 +1488,11 @@ xfs_dir_leaf_remove(xfs_trans_t *trans, xfs_dabuf_t *bp, int index) be16_add(&map->size, entry_size); } - if ((be16_to_cpu(map->base) + be16_to_cpu(map->size)) == INT_GET(entry->nameidx, ARCH_CONVERT)) { + if ((be16_to_cpu(map->base) + be16_to_cpu(map->size)) == + be16_to_cpu(entry->nameidx)) { before = i; - } else if (be16_to_cpu(map->base) == (INT_GET(entry->nameidx, ARCH_CONVERT) + entsize)) { + } else if (be16_to_cpu(map->base) == + (be16_to_cpu(entry->nameidx) + entsize)) { after = i; } else if (be16_to_cpu(map->size) < tmp) { tmp = be16_to_cpu(map->size); @@ -1530,7 +1533,7 @@ xfs_dir_leaf_remove(xfs_trans_t *trans, xfs_dabuf_t *bp, int index) /* * Did we remove the first entry? */ - if (INT_GET(entry->nameidx, ARCH_CONVERT) == be16_to_cpu(hdr->firstused)) + if (be16_to_cpu(entry->nameidx) == be16_to_cpu(hdr->firstused)) smallest = 1; else smallest = 0; @@ -1538,7 +1541,7 @@ xfs_dir_leaf_remove(xfs_trans_t *trans, xfs_dabuf_t *bp, int index) /* * Compress the remaining entries and zero out the removed stuff. */ - namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT)); + namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, be16_to_cpu(entry->nameidx)); memset((char *)namest, 0, entsize); xfs_da_log_buf(trans, bp, XFS_DA_LOGRANGE(leaf, namest, entsize)); @@ -1561,11 +1564,11 @@ xfs_dir_leaf_remove(xfs_trans_t *trans, xfs_dabuf_t *bp, int index) tmp = XFS_LBSIZE(mp); entry = &leaf->entries[0]; for (i = be16_to_cpu(hdr->count)-1; i >= 0; entry++, i--) { - ASSERT(INT_GET(entry->nameidx, ARCH_CONVERT) >= + ASSERT(be16_to_cpu(entry->nameidx) >= be16_to_cpu(hdr->firstused)); - ASSERT(INT_GET(entry->nameidx, ARCH_CONVERT) < XFS_LBSIZE(mp)); - if (INT_GET(entry->nameidx, ARCH_CONVERT) < tmp) - tmp = INT_GET(entry->nameidx, ARCH_CONVERT); + ASSERT(be16_to_cpu(entry->nameidx) < XFS_LBSIZE(mp)); + if (be16_to_cpu(entry->nameidx) < tmp) + tmp = be16_to_cpu(entry->nameidx); } hdr->firstused = cpu_to_be16(tmp); if (!hdr->firstused) @@ -1617,7 +1620,8 @@ xfs_dir_leaf_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk, /* * Save last hashval from dying block for later Btree fixup. */ - drop_blk->hashval = INT_GET(drop_leaf->entries[be16_to_cpu(drop_leaf->hdr.count)-1].hashval, ARCH_CONVERT); + drop_blk->hashval = be32_to_cpu(drop_leaf->entries[ + be16_to_cpu(drop_leaf->hdr.count)-1].hashval); /* * Check if we need a temp buffer, or can we do it in place. @@ -1676,7 +1680,8 @@ xfs_dir_leaf_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk, /* * Copy out last hashval in each block for B-tree code. */ - save_blk->hashval = INT_GET(save_leaf->entries[be16_to_cpu(save_leaf->hdr.count)-1 ].hashval, ARCH_CONVERT); + save_blk->hashval = be32_to_cpu(save_leaf->entries[ + be16_to_cpu(save_leaf->hdr.count)-1].hashval); } /*======================================================================== @@ -1716,30 +1721,32 @@ xfs_dir_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args, int *index) for (entry = &leaf->entries[probe]; span > 4; entry = &leaf->entries[probe]) { span /= 2; - if (INT_GET(entry->hashval, ARCH_CONVERT) < hashval) + if (be32_to_cpu(entry->hashval) < hashval) probe += span; - else if (INT_GET(entry->hashval, ARCH_CONVERT) > hashval) + else if (be32_to_cpu(entry->hashval) > hashval) probe -= span; else break; } ASSERT((probe >= 0) && \ ((!leaf->hdr.count) || (probe < be16_to_cpu(leaf->hdr.count)))); - ASSERT((span <= 4) || (INT_GET(entry->hashval, ARCH_CONVERT) == hashval)); + ASSERT((span <= 4) || (be32_to_cpu(entry->hashval) == hashval)); /* * Since we may have duplicate hashval's, find the first matching * hashval in the leaf. */ - while ((probe > 0) && (INT_GET(entry->hashval, ARCH_CONVERT) >= hashval)) { + while ((probe > 0) && (be32_to_cpu(entry->hashval) >= hashval)) { entry--; probe--; } - while ((probe < be16_to_cpu(leaf->hdr.count)) && (INT_GET(entry->hashval, ARCH_CONVERT) < hashval)) { + while ((probe < be16_to_cpu(leaf->hdr.count)) && + (be32_to_cpu(entry->hashval) < hashval)) { entry++; probe++; } - if ((probe == be16_to_cpu(leaf->hdr.count)) || (INT_GET(entry->hashval, ARCH_CONVERT) != hashval)) { + if ((probe == be16_to_cpu(leaf->hdr.count)) || + (be32_to_cpu(entry->hashval) != hashval)) { *index = probe; ASSERT(args->oknoent); return XFS_ERROR(ENOENT); @@ -1748,8 +1755,9 @@ xfs_dir_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args, int *index) /* * Duplicate keys may be present, so search all of them for a match. */ - while ((probe < be16_to_cpu(leaf->hdr.count)) && (INT_GET(entry->hashval, ARCH_CONVERT) == hashval)) { - namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT)); + while ((probe < be16_to_cpu(leaf->hdr.count)) && + (be32_to_cpu(entry->hashval) == hashval)) { + namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, be16_to_cpu(entry->nameidx)); if (entry->namelen == args->namelen && namest->name[0] == args->name[0] && memcmp(args->name, namest->name, args->namelen) == 0) { @@ -1825,19 +1833,19 @@ xfs_dir_leaf_moveents(xfs_dir_leafblock_t *leaf_s, int start_s, entry_s = &leaf_s->entries[start_s]; entry_d = &leaf_d->entries[start_d]; for (i = 0; i < count; entry_s++, entry_d++, i++) { - ASSERT(INT_GET(entry_s->nameidx, ARCH_CONVERT) >= + ASSERT(be16_to_cpu(entry_s->nameidx) >= be16_to_cpu(hdr_s->firstused)); tmp = XFS_DIR_LEAF_ENTSIZE_BYENTRY(entry_s); be16_add(&hdr_d->firstused, -(tmp)); entry_d->hashval = entry_s->hashval; entry_d->nameidx = hdr_d->firstused; entry_d->namelen = entry_s->namelen; - ASSERT(INT_GET(entry_d->nameidx, ARCH_CONVERT) + tmp <= XFS_LBSIZE(mp)); - memcpy(XFS_DIR_LEAF_NAMESTRUCT(leaf_d, INT_GET(entry_d->nameidx, ARCH_CONVERT)), - XFS_DIR_LEAF_NAMESTRUCT(leaf_s, INT_GET(entry_s->nameidx, ARCH_CONVERT)), tmp); - ASSERT(INT_GET(entry_s->nameidx, ARCH_CONVERT) + tmp <= XFS_LBSIZE(mp)); - memset((char *)XFS_DIR_LEAF_NAMESTRUCT(leaf_s, INT_GET(entry_s->nameidx, ARCH_CONVERT)), - 0, tmp); + ASSERT(be16_to_cpu(entry_d->nameidx) + tmp <= XFS_LBSIZE(mp)); + memcpy(XFS_DIR_LEAF_NAMESTRUCT(leaf_d, be16_to_cpu(entry_d->nameidx)), + XFS_DIR_LEAF_NAMESTRUCT(leaf_s, be16_to_cpu(entry_s->nameidx)), tmp); + ASSERT(be16_to_cpu(entry_s->nameidx) + tmp <= XFS_LBSIZE(mp)); + memset((char *)XFS_DIR_LEAF_NAMESTRUCT(leaf_s, + be16_to_cpu(entry_s->nameidx)), 0, tmp); be16_add(&hdr_s->namebytes, -(entry_d->namelen)); be16_add(&hdr_d->namebytes, entry_d->namelen); be16_add(&hdr_s->count, -1); @@ -1900,10 +1908,12 @@ xfs_dir_leaf_order(xfs_dabuf_t *leaf1_bp, xfs_dabuf_t *leaf2_bp) ASSERT((be16_to_cpu(leaf1->hdr.info.magic) == XFS_DIR_LEAF_MAGIC) && (be16_to_cpu(leaf2->hdr.info.magic) == XFS_DIR_LEAF_MAGIC)); if (leaf1->hdr.count && leaf2->hdr.count && - ((INT_GET(leaf2->entries[ 0 ].hashval, ARCH_CONVERT) < - INT_GET(leaf1->entries[ 0 ].hashval, ARCH_CONVERT)) || - (INT_GET(leaf2->entries[be16_to_cpu(leaf2->hdr.count)-1].hashval, ARCH_CONVERT) < - INT_GET(leaf1->entries[be16_to_cpu(leaf1->hdr.count)-1].hashval, ARCH_CONVERT)))) { + ((be32_to_cpu(leaf2->entries[0].hashval) < + be32_to_cpu(leaf1->entries[0 ].hashval)) || + (be32_to_cpu(leaf2->entries[ + be16_to_cpu(leaf2->hdr.count)-1].hashval) < + be32_to_cpu(leaf1->entries[ + be16_to_cpu(leaf1->hdr.count)-1].hashval)))) { return 1; } return 0; @@ -1923,7 +1933,7 @@ xfs_dir_leaf_lasthash(xfs_dabuf_t *bp, int *count) *count = be16_to_cpu(leaf->hdr.count); if (!leaf->hdr.count) return(0); - return(INT_GET(leaf->entries[be16_to_cpu(leaf->hdr.count)-1].hashval, ARCH_CONVERT)); + return be32_to_cpu(leaf->entries[be16_to_cpu(leaf->hdr.count)-1].hashval); } /* @@ -1972,7 +1982,7 @@ xfs_dir_leaf_getdents_int( i < be16_to_cpu(leaf->hdr.count); entry++, i++) { namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, - INT_GET(entry->nameidx, ARCH_CONVERT)); + be16_to_cpu(entry->nameidx)); if (unlikely( ((char *)namest < (char *)leaf) || @@ -1982,19 +1992,16 @@ xfs_dir_leaf_getdents_int( xfs_dir_trace_g_du("leaf: corrupted", dp, uio); return XFS_ERROR(EFSCORRUPTED); } - if (INT_GET(entry->hashval, ARCH_CONVERT) >= cookhash) { - if ( entno < want_entno - && INT_GET(entry->hashval, ARCH_CONVERT) - == cookhash) { + if (be32_to_cpu(entry->hashval) >= cookhash) { + if (entno < want_entno && + be32_to_cpu(entry->hashval) == cookhash) { /* * Trying to get to a particular offset in a * run of equal-hashval entries. */ entno++; - } else if ( want_entno > 0 - && entno == want_entno - && INT_GET(entry->hashval, ARCH_CONVERT) - == cookhash) { + } else if (want_entno > 0 && entno == want_entno && + be32_to_cpu(entry->hashval) == cookhash) { break; } else { entno = 0; @@ -2035,7 +2042,7 @@ xfs_dir_leaf_getdents_int( * the inode number from this entry. */ namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, - INT_GET(entry->nameidx, ARCH_CONVERT)); + be16_to_cpu(entry->nameidx)); if (unlikely( ((char *)namest < (char *)leaf) || @@ -2050,9 +2057,9 @@ xfs_dir_leaf_getdents_int( dp, uio, p.cook.o); if (i < (be16_to_cpu(leaf->hdr.count) - 1)) { - nexthash = INT_GET(entry[1].hashval, ARCH_CONVERT); + nexthash = be32_to_cpu(entry[1].hashval); - if (nexthash == INT_GET(entry->hashval, ARCH_CONVERT)) + if (nexthash == be32_to_cpu(entry->hashval)) nextentno = entno + 1; else nextentno = 0; @@ -2088,8 +2095,7 @@ xfs_dir_leaf_getdents_int( return XFS_ERROR(EFSCORRUPTED); } - nexthash = INT_GET(leaf2->entries[0].hashval, - ARCH_CONVERT); + nexthash = be32_to_cpu(leaf2->entries[0].hashval); nextentno = -1; XFS_PUT_COOKIE(p.cook, mp, thishash, 0, nexthash); xfs_da_brelse(dp->i_transp, bp2); @@ -2113,9 +2119,9 @@ xfs_dir_leaf_getdents_int( * that share the same hashval. Hopefully the buffer * provided is big enough to handle it (see pv763517). */ + thishash = be32_to_cpu(entry->hashval); #if (BITS_PER_LONG == 32) - if ((thishash = INT_GET(entry->hashval, ARCH_CONVERT)) - != lasthash) { + if (thishash != lasthash) { XFS_PUT_COOKIE(lastoffset, mp, bno, entno, thishash); lastresid = uio->uio_resid; lasthash = thishash; @@ -2124,7 +2130,6 @@ xfs_dir_leaf_getdents_int( dp, uio, p.cook.o); } #else - thishash = INT_GET(entry->hashval, ARCH_CONVERT); XFS_PUT_COOKIE(lastoffset, mp, bno, entno, thishash); lastresid = uio->uio_resid; #endif /* BITS_PER_LONG == 32 */ diff --git a/fs/xfs/xfs_dir_leaf.h b/fs/xfs/xfs_dir_leaf.h index c6979ab829c..7ca5845195d 100644 --- a/fs/xfs/xfs_dir_leaf.h +++ b/fs/xfs/xfs_dir_leaf.h @@ -83,10 +83,10 @@ typedef struct xfs_dir_leaf_hdr { /* constant-structure header block */ } xfs_dir_leaf_hdr_t; typedef struct xfs_dir_leaf_entry { /* sorted on key, not name */ - xfs_dahash_t hashval; /* hash value of name */ - __uint16_t nameidx; /* index into buffer of name */ - __uint8_t namelen; /* length of name string */ - __uint8_t pad2; + __be32 hashval; /* hash value of name */ + __be16 nameidx; /* index into buffer of name */ + __u8 namelen; /* length of name string */ + __u8 pad2; } xfs_dir_leaf_entry_t; typedef struct xfs_dir_leaf_name { -- cgit v1.2.3 From 3f368a0d58cb8cadab298546286f94ca14220f65 Mon Sep 17 00:00:00 2001 From: Olaf Weber Date: Fri, 9 Jun 2006 14:51:11 +1000 Subject: [XFS] Originally the ATTR_DMI flag also had the functionality of the ATTR_NOLOCK flag, but this was split off some time ago, as ATTR_DMI needed to be used separately. Two asserts were added to guard correctness of the code during the transition. These are no longer required. SGI-PV: 952145 SGI-Modid: xfs-linux-melb:xfs-kern:209633a Signed-off-by: Olaf Weber Signed-off-by: Nathan Scott --- fs/xfs/xfs_vnodeops.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 567d14d06d9..2b814f04176 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -347,7 +347,6 @@ xfs_setattr( */ tp = NULL; lock_flags = XFS_ILOCK_EXCL; - ASSERT(flags & ATTR_NOLOCK ? flags & ATTR_DMI : 1); if (flags & ATTR_NOLOCK) need_iolock = 0; if (!(mask & XFS_AT_SIZE)) { @@ -4308,7 +4307,6 @@ xfs_free_file_space( return error; } - ASSERT(attr_flags & ATTR_NOLOCK ? attr_flags & ATTR_DMI : 1); if (attr_flags & ATTR_NOLOCK) need_iolock = 0; if (need_iolock) { -- cgit v1.2.3 From fe6c1e7240e3a7cb600030f9c909273365d52a9d Mon Sep 17 00:00:00 2001 From: Mandy Kirkconnell Date: Fri, 9 Jun 2006 14:51:25 +1000 Subject: [XFS] Fix size argument in kmem_free(). SGI-PV: 952291 SGI-Modid: xfs-linux-melb:xfs-kern:209807a Signed-off-by: Mandy Kirkconnell Signed-off-by: Nathan Scott --- fs/xfs/xfs_inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 020de5637e0..f5284453441 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -4181,7 +4181,7 @@ xfs_iext_direct_to_inline( */ memcpy(ifp->if_u2.if_inline_ext, ifp->if_u1.if_extents, nextents * sizeof(xfs_bmbt_rec_t)); - kmem_free(ifp->if_u1.if_extents, KM_SLEEP); + kmem_free(ifp->if_u1.if_extents, ifp->if_real_bytes); ifp->if_u1.if_extents = ifp->if_u2.if_inline_ext; ifp->if_real_bytes = 0; } -- cgit v1.2.3 From ba0b92d671c36cbebd66a306790c9b66a3224d83 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Fri, 9 Jun 2006 14:52:00 +1000 Subject: [XFS] Fix a comment typo, originally noticed by Ming Zhang. SGI-PV: 907752 SGI-Modid: xfs-linux-melb:xfs-kern:25921a Signed-off-by: Nathan Scott --- fs/xfs/xfs_fs.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/xfs/xfs_fs.h b/fs/xfs/xfs_fs.h index 14010f1fa82..df66f3a59fa 100644 --- a/fs/xfs/xfs_fs.h +++ b/fs/xfs/xfs_fs.h @@ -72,9 +72,9 @@ struct fsxattr { /* * Structure for XFS_IOC_GETBMAP. * On input, fill in bmv_offset and bmv_length of the first structure - * to indicate the area of interest in the file, and bmv_entry with the - * number of array elements given. The first structure is updated on - * return to give the offset and length for the next call. + * to indicate the area of interest in the file, and bmv_entries with + * the number of array elements given back. The first structure is + * updated on return to give the offset and length for the next call. */ #ifndef HAVE_GETBMAP struct getbmap { -- cgit v1.2.3 From fbc1462bcb421620a04eb390fc79a2615c9d01d0 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Fri, 9 Jun 2006 14:52:13 +1000 Subject: [XFS] Fix a noatime regression related to updating inode atime field on mmap only. SGI-PV: 952736 SGI-Modid: xfs-linux-melb:xfs-kern:25922a Signed-off-by: Nathan Scott --- fs/xfs/linux-2.6/xfs_file.c | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index c847416f6d1..7c9f7598807 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c @@ -362,15 +362,10 @@ xfs_vm_nopage( { struct inode *inode = area->vm_file->f_dentry->d_inode; vnode_t *vp = vn_from_inode(inode); - xfs_mount_t *mp = XFS_VFSTOM(vp->v_vfsp); - int error; ASSERT_ALWAYS(vp->v_vfsp->vfs_flag & VFS_DMI); - - error = XFS_SEND_MMAP(mp, area, 0); - if (error) + if (XFS_SEND_MMAP(XFS_VFSTOM(vp->v_vfsp), area, 0)) return NULL; - return filemap_nopage(area, address, type); } #endif /* CONFIG_XFS_DMAPI */ @@ -456,23 +451,14 @@ xfs_file_mmap( struct file *filp, struct vm_area_struct *vma) { - struct inode *ip = filp->f_dentry->d_inode; - vnode_t *vp = vn_from_inode(ip); - vattr_t vattr; - int error; - vma->vm_ops = &xfs_file_vm_ops; #ifdef CONFIG_XFS_DMAPI - if (vp->v_vfsp->vfs_flag & VFS_DMI) { + if (vn_from_inode(filp->f_dentry->d_inode)->v_vfsp->vfs_flag & VFS_DMI) vma->vm_ops = &xfs_dmapi_file_vm_ops; - } #endif /* CONFIG_XFS_DMAPI */ - vattr.va_mask = XFS_AT_UPDATIME; - VOP_SETATTR(vp, &vattr, XFS_AT_UPDATIME, NULL, error); - if (likely(!error)) - __vn_revalidate(vp, &vattr); /* update flags */ + file_accessed(filp); return 0; } -- cgit v1.2.3 From d3446eac3f50dade2f09ed212b112609ee78fb33 Mon Sep 17 00:00:00 2001 From: Barry Naujok Date: Fri, 9 Jun 2006 14:54:19 +1000 Subject: [XFS] Add degframentation exclusion support SGI-PV: 953061 SGI-Modid: xfs-linux-melb:xfs-kern:25986a Signed-off-by: Barry Naujok Signed-off-by: Nathan Scott --- fs/xfs/linux-2.6/xfs_globals.c | 1 + fs/xfs/linux-2.6/xfs_linux.h | 1 + fs/xfs/linux-2.6/xfs_sysctl.c | 5 +++++ fs/xfs/linux-2.6/xfs_sysctl.h | 2 ++ fs/xfs/xfs_dinode.h | 4 +++- fs/xfs/xfs_fs.h | 1 + fs/xfs/xfs_inode.c | 5 +++++ fs/xfs/xfs_vnodeops.c | 2 ++ 8 files changed, 20 insertions(+), 1 deletion(-) diff --git a/fs/xfs/linux-2.6/xfs_globals.c b/fs/xfs/linux-2.6/xfs_globals.c index 6e8085f3463..6c162c3dde7 100644 --- a/fs/xfs/linux-2.6/xfs_globals.c +++ b/fs/xfs/linux-2.6/xfs_globals.c @@ -45,6 +45,7 @@ xfs_param_t xfs_params = { .xfs_buf_age = { 1*100, 15*100, 7200*100}, .inherit_nosym = { 0, 0, 1 }, .rotorstep = { 1, 1, 255 }, + .inherit_nodfrg = { 0, 1, 1 }, }; /* diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h index e9fe43d7476..7d15cb91027 100644 --- a/fs/xfs/linux-2.6/xfs_linux.h +++ b/fs/xfs/linux-2.6/xfs_linux.h @@ -134,6 +134,7 @@ BUFFER_FNS(PrivateStart, unwritten); #define xfs_buf_age_centisecs xfs_params.xfs_buf_age.val #define xfs_inherit_nosymlinks xfs_params.inherit_nosym.val #define xfs_rotorstep xfs_params.rotorstep.val +#define xfs_inherit_nodefrag xfs_params.inherit_nodfrg.val #ifndef raw_smp_processor_id #define raw_smp_processor_id() smp_processor_id() diff --git a/fs/xfs/linux-2.6/xfs_sysctl.c b/fs/xfs/linux-2.6/xfs_sysctl.c index 7079cc83721..4af97682bec 100644 --- a/fs/xfs/linux-2.6/xfs_sysctl.c +++ b/fs/xfs/linux-2.6/xfs_sysctl.c @@ -120,6 +120,11 @@ STATIC ctl_table xfs_table[] = { &sysctl_intvec, NULL, &xfs_params.rotorstep.min, &xfs_params.rotorstep.max}, + {XFS_INHERIT_NODFRG, "inherit_nodefrag", &xfs_params.inherit_nodfrg.val, + sizeof(int), 0644, NULL, &proc_dointvec_minmax, + &sysctl_intvec, NULL, + &xfs_params.inherit_nodfrg.min, &xfs_params.inherit_nodfrg.max}, + /* please keep this the last entry */ #ifdef CONFIG_PROC_FS {XFS_STATS_CLEAR, "stats_clear", &xfs_params.stats_clear.val, diff --git a/fs/xfs/linux-2.6/xfs_sysctl.h b/fs/xfs/linux-2.6/xfs_sysctl.h index bc8c11f1372..a631fb8cc5a 100644 --- a/fs/xfs/linux-2.6/xfs_sysctl.h +++ b/fs/xfs/linux-2.6/xfs_sysctl.h @@ -46,6 +46,7 @@ typedef struct xfs_param { xfs_sysctl_val_t xfs_buf_age; /* Metadata buffer age before flush. */ xfs_sysctl_val_t inherit_nosym; /* Inherit the "nosymlinks" flag. */ xfs_sysctl_val_t rotorstep; /* inode32 AG rotoring control knob */ + xfs_sysctl_val_t inherit_nodfrg;/* Inherit the "nodefrag" inode flag. */ } xfs_param_t; /* @@ -84,6 +85,7 @@ enum { /* XFS_IO_BYPASS = 18 */ XFS_INHERIT_NOSYM = 19, XFS_ROTORSTEP = 20, + XFS_INHERIT_NODFRG = 21, }; extern xfs_param_t xfs_params; diff --git a/fs/xfs/xfs_dinode.h b/fs/xfs/xfs_dinode.h index 79d0d9e1fba..77d53778258 100644 --- a/fs/xfs/xfs_dinode.h +++ b/fs/xfs/xfs_dinode.h @@ -257,6 +257,7 @@ typedef enum xfs_dinode_fmt #define XFS_DIFLAG_NOSYMLINKS_BIT 10 /* disallow symlink creation */ #define XFS_DIFLAG_EXTSIZE_BIT 11 /* inode extent size allocator hint */ #define XFS_DIFLAG_EXTSZINHERIT_BIT 12 /* inherit inode extent size */ +#define XFS_DIFLAG_NODEFRAG_BIT 13 /* do not reorganize/defragment */ #define XFS_DIFLAG_REALTIME (1 << XFS_DIFLAG_REALTIME_BIT) #define XFS_DIFLAG_PREALLOC (1 << XFS_DIFLAG_PREALLOC_BIT) #define XFS_DIFLAG_NEWRTBM (1 << XFS_DIFLAG_NEWRTBM_BIT) @@ -270,12 +271,13 @@ typedef enum xfs_dinode_fmt #define XFS_DIFLAG_NOSYMLINKS (1 << XFS_DIFLAG_NOSYMLINKS_BIT) #define XFS_DIFLAG_EXTSIZE (1 << XFS_DIFLAG_EXTSIZE_BIT) #define XFS_DIFLAG_EXTSZINHERIT (1 << XFS_DIFLAG_EXTSZINHERIT_BIT) +#define XFS_DIFLAG_NODEFRAG (1 << XFS_DIFLAG_NODEFRAG_BIT) #define XFS_DIFLAG_ANY \ (XFS_DIFLAG_REALTIME | XFS_DIFLAG_PREALLOC | XFS_DIFLAG_NEWRTBM | \ XFS_DIFLAG_IMMUTABLE | XFS_DIFLAG_APPEND | XFS_DIFLAG_SYNC | \ XFS_DIFLAG_NOATIME | XFS_DIFLAG_NODUMP | XFS_DIFLAG_RTINHERIT | \ XFS_DIFLAG_PROJINHERIT | XFS_DIFLAG_NOSYMLINKS | XFS_DIFLAG_EXTSIZE | \ - XFS_DIFLAG_EXTSZINHERIT) + XFS_DIFLAG_EXTSZINHERIT | XFS_DIFLAG_NODEFRAG) #endif /* __XFS_DINODE_H__ */ diff --git a/fs/xfs/xfs_fs.h b/fs/xfs/xfs_fs.h index df66f3a59fa..0f0ad153595 100644 --- a/fs/xfs/xfs_fs.h +++ b/fs/xfs/xfs_fs.h @@ -67,6 +67,7 @@ struct fsxattr { #define XFS_XFLAG_NOSYMLINKS 0x00000400 /* disallow symlink creation */ #define XFS_XFLAG_EXTSIZE 0x00000800 /* extent size allocator hint */ #define XFS_XFLAG_EXTSZINHERIT 0x00001000 /* inherit inode extent size */ +#define XFS_XFLAG_NODEFRAG 0x00002000 /* do not defragment */ #define XFS_XFLAG_HASATTR 0x80000000 /* no DIFLAG for this */ /* diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index f5284453441..083fc0479e6 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -812,6 +812,8 @@ _xfs_dic2xflags( flags |= XFS_XFLAG_EXTSIZE; if (di_flags & XFS_DIFLAG_EXTSZINHERIT) flags |= XFS_XFLAG_EXTSZINHERIT; + if (di_flags & XFS_DIFLAG_NODEFRAG) + flags |= XFS_XFLAG_NODEFRAG; } return flags; @@ -1221,6 +1223,9 @@ xfs_ialloc( di_flags |= XFS_DIFLAG_NOSYMLINKS; if (pip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) di_flags |= XFS_DIFLAG_PROJINHERIT; + if ((pip->i_d.di_flags & XFS_DIFLAG_NODEFRAG) && + xfs_inherit_nodefrag) + di_flags |= XFS_DIFLAG_NODEFRAG; ip->i_d.di_flags |= di_flags; } /* FALLTHROUGH */ diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 2b814f04176..d1c6349e401 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -799,6 +799,8 @@ xfs_setattr( di_flags |= XFS_DIFLAG_NODUMP; if (vap->va_xflags & XFS_XFLAG_PROJINHERIT) di_flags |= XFS_DIFLAG_PROJINHERIT; + if (vap->va_xflags & XFS_XFLAG_NODEFRAG) + di_flags |= XFS_DIFLAG_NODEFRAG; if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) { if (vap->va_xflags & XFS_XFLAG_RTINHERIT) di_flags |= XFS_DIFLAG_RTINHERIT; -- cgit v1.2.3 From d210a28cd851082cec9b282443f8cc0e6fc09830 Mon Sep 17 00:00:00 2001 From: Yingping Lu Date: Fri, 9 Jun 2006 14:55:18 +1000 Subject: [XFS] In actual allocation of file system blocks and freeing extents, the transaction within each such operation may involve multiple locking of AGF buffer. While the freeing extent function has sorted the extents based on AGF number before entering into transaction, however, when the file system space is very limited, the allocation of space would try every AGF to get space allocated, this could potentially cause out-of-order locking, thus deadlock could happen. This fix mitigates the scarce space for allocation by setting aside a few blocks without reservation, and avoid deadlock by maintaining ascending order of AGF locking. SGI-PV: 947395 SGI-Modid: xfs-linux-melb:xfs-kern:210801a Signed-off-by: Yingping Lu Signed-off-by: Nathan Scott --- fs/xfs/xfs_alloc.c | 29 +++++++++++++++++++++++------ fs/xfs/xfs_alloc.h | 2 ++ fs/xfs/xfs_bmap.c | 5 ++++- fs/xfs/xfs_bmap_btree.c | 10 ++++------ fs/xfs/xfs_mount.c | 24 ++++++++++++++++++++++-- 5 files changed, 55 insertions(+), 15 deletions(-) diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c index 8558226281c..22af489d3f3 100644 --- a/fs/xfs/xfs_alloc.c +++ b/fs/xfs/xfs_alloc.c @@ -1862,7 +1862,7 @@ xfs_alloc_fix_freelist( (pag->pagf_longest - delta) : (pag->pagf_flcount > 0 || pag->pagf_longest > 0); if (args->minlen + args->alignment + args->minalignslop - 1 > longest || - (args->minleft && + (!(flags & XFS_ALLOC_FLAG_FREEING) && (int)(pag->pagf_freeblks + pag->pagf_flcount - need - args->total) < (int)args->minleft)) { @@ -1898,7 +1898,7 @@ xfs_alloc_fix_freelist( longest = (longest > delta) ? (longest - delta) : (be32_to_cpu(agf->agf_flcount) > 0 || longest > 0); if (args->minlen + args->alignment + args->minalignslop - 1 > longest || - (args->minleft && + (!(flags & XFS_ALLOC_FLAG_FREEING) && (int)(be32_to_cpu(agf->agf_freeblks) + be32_to_cpu(agf->agf_flcount) - need - args->total) < (int)args->minleft)) { @@ -1951,8 +1951,14 @@ xfs_alloc_fix_freelist( * the restrictions correctly. Can happen for free calls * on a completely full ag. */ - if (targs.agbno == NULLAGBLOCK) + if (targs.agbno == NULLAGBLOCK) { + if (!(flags & XFS_ALLOC_FLAG_FREEING)) { + xfs_trans_brelse(tp, agflbp); + args->agbp = NULL; + return 0; + } break; + } /* * Put each allocated block on the list. */ @@ -2360,8 +2366,19 @@ xfs_alloc_vextent( if (args->agno == sagno && type == XFS_ALLOCTYPE_START_BNO) args->type = XFS_ALLOCTYPE_THIS_AG; - if (++(args->agno) == mp->m_sb.sb_agcount) - args->agno = 0; + /* + * For the first allocation, we can try any AG to get + * space. However, if we already have allocated a + * block, we don't want to try AGs whose number is below + * sagno. Otherwise, we may end up with out-of-order + * locking of AGF, which might cause deadlock. + */ + if (++(args->agno) == mp->m_sb.sb_agcount) { + if (args->firstblock != NULLFSBLOCK) + args->agno = sagno; + else + args->agno = 0; + } /* * Reached the starting a.g., must either be done * or switch to non-trylock mode. @@ -2443,7 +2460,7 @@ xfs_free_extent( args.minlen = args.minleft = args.minalignslop = 0; down_read(&args.mp->m_peraglock); args.pag = &args.mp->m_perag[args.agno]; - if ((error = xfs_alloc_fix_freelist(&args, 0))) + if ((error = xfs_alloc_fix_freelist(&args, XFS_ALLOC_FLAG_FREEING))) goto error0; #ifdef DEBUG ASSERT(args.agbp != NULL); diff --git a/fs/xfs/xfs_alloc.h b/fs/xfs/xfs_alloc.h index 2d1f8928b26..650591f999a 100644 --- a/fs/xfs/xfs_alloc.h +++ b/fs/xfs/xfs_alloc.h @@ -41,6 +41,7 @@ typedef enum xfs_alloctype * Flags for xfs_alloc_fix_freelist. */ #define XFS_ALLOC_FLAG_TRYLOCK 0x00000001 /* use trylock for buffer locking */ +#define XFS_ALLOC_FLAG_FREEING 0x00000002 /* indicate caller is freeing extents*/ /* * Argument structure for xfs_alloc routines. @@ -70,6 +71,7 @@ typedef struct xfs_alloc_arg { char wasfromfl; /* set if allocation is from freelist */ char isfl; /* set if is freelist blocks - !acctg */ char userdata; /* set if this is user data */ + xfs_fsblock_t firstblock; /* io first block allocated */ } xfs_alloc_arg_t; /* diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 890ad352817..ad595dbefe1 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -2762,6 +2762,7 @@ xfs_bmap_btalloc( args.mp = mp; args.fsbno = ap->rval; args.maxlen = MIN(ap->alen, mp->m_sb.sb_agblocks); + args.firstblock = ap->firstblock; blen = 0; if (nullfb) { args.type = XFS_ALLOCTYPE_START_BNO; @@ -2821,7 +2822,7 @@ xfs_bmap_btalloc( else args.minlen = ap->alen; } else if (ap->low) { - args.type = XFS_ALLOCTYPE_FIRST_AG; + args.type = XFS_ALLOCTYPE_START_BNO; args.total = args.minlen = ap->minlen; } else { args.type = XFS_ALLOCTYPE_NEAR_BNO; @@ -3452,6 +3453,7 @@ xfs_bmap_extents_to_btree( XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_BTREE); args.tp = tp; args.mp = mp; + args.firstblock = *firstblock; if (*firstblock == NULLFSBLOCK) { args.type = XFS_ALLOCTYPE_START_BNO; args.fsbno = XFS_INO_TO_FSB(mp, ip->i_ino); @@ -3587,6 +3589,7 @@ xfs_bmap_local_to_extents( args.tp = tp; args.mp = ip->i_mount; + args.firstblock = *firstblock; ASSERT((ifp->if_flags & (XFS_IFINLINE|XFS_IFEXTENTS|XFS_IFEXTIREC)) == XFS_IFINLINE); /* diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c index bea44709afb..3b6dfc9b53a 100644 --- a/fs/xfs/xfs_bmap_btree.c +++ b/fs/xfs/xfs_bmap_btree.c @@ -1569,12 +1569,11 @@ xfs_bmbt_split( lbno = XFS_DADDR_TO_FSB(args.mp, XFS_BUF_ADDR(lbp)); left = XFS_BUF_TO_BMBT_BLOCK(lbp); args.fsbno = cur->bc_private.b.firstblock; + args.firstblock = args.fsbno; if (args.fsbno == NULLFSBLOCK) { args.fsbno = lbno; args.type = XFS_ALLOCTYPE_START_BNO; - } else if (cur->bc_private.b.flist->xbf_low) - args.type = XFS_ALLOCTYPE_FIRST_AG; - else + } else args.type = XFS_ALLOCTYPE_NEAR_BNO; args.mod = args.minleft = args.alignment = args.total = args.isfl = args.userdata = args.minalignslop = 0; @@ -2356,6 +2355,7 @@ xfs_bmbt_newroot( args.userdata = args.minalignslop = 0; args.minlen = args.maxlen = args.prod = 1; args.wasdel = cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL; + args.firstblock = args.fsbno; if (args.fsbno == NULLFSBLOCK) { #ifdef DEBUG if ((error = xfs_btree_check_lptr(cur, INT_GET(*pp, ARCH_CONVERT), level))) { @@ -2365,9 +2365,7 @@ xfs_bmbt_newroot( #endif args.fsbno = INT_GET(*pp, ARCH_CONVERT); args.type = XFS_ALLOCTYPE_START_BNO; - } else if (args.wasdel) - args.type = XFS_ALLOCTYPE_FIRST_AG; - else + } else args.type = XFS_ALLOCTYPE_NEAR_BNO; if ((error = xfs_alloc_vextent(&args))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index c0b1c290688..4b7be49cc4d 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -1254,6 +1254,26 @@ xfs_mod_sb(xfs_trans_t *tp, __int64_t fields) xfs_trans_log_buf(tp, bp, first, last); } + +/* + * In order to avoid ENOSPC-related deadlock caused by + * out-of-order locking of AGF buffer (PV 947395), we place + * constraints on the relationship among actual allocations for + * data blocks, freelist blocks, and potential file data bmap + * btree blocks. However, these restrictions may result in no + * actual space allocated for a delayed extent, for example, a data + * block in a certain AG is allocated but there is no additional + * block for the additional bmap btree block due to a split of the + * bmap btree of the file. The result of this may lead to an + * infinite loop in xfssyncd when the file gets flushed to disk and + * all delayed extents need to be actually allocated. To get around + * this, we explicitly set aside a few blocks which will not be + * reserved in delayed allocation. Considering the minimum number of + * needed freelist blocks is 4 fsbs, a potential split of file's bmap + * btree requires 1 fsb, so we set the number of set-aside blocks to 8. +*/ +#define SET_ASIDE_BLOCKS 8 + /* * xfs_mod_incore_sb_unlocked() is a utility routine common used to apply * a delta to a specified field in the in-core superblock. Simply @@ -1298,7 +1318,7 @@ xfs_mod_incore_sb_unlocked(xfs_mount_t *mp, xfs_sb_field_t field, return 0; case XFS_SBS_FDBLOCKS: - lcounter = (long long)mp->m_sb.sb_fdblocks; + lcounter = (long long)mp->m_sb.sb_fdblocks - SET_ASIDE_BLOCKS; res_used = (long long)(mp->m_resblks - mp->m_resblks_avail); if (delta > 0) { /* Putting blocks back */ @@ -1332,7 +1352,7 @@ xfs_mod_incore_sb_unlocked(xfs_mount_t *mp, xfs_sb_field_t field, } } - mp->m_sb.sb_fdblocks = lcounter; + mp->m_sb.sb_fdblocks = lcounter + SET_ASIDE_BLOCKS; return 0; case XFS_SBS_FREXTENTS: lcounter = (long long)mp->m_sb.sb_frextents; -- cgit v1.2.3 From 6d192a9b82212abf1e0e89da6e3a952afba7e4d6 Mon Sep 17 00:00:00 2001 From: Tim Shimmin Date: Fri, 9 Jun 2006 14:55:38 +1000 Subject: [XFS] inode items and EFI/EFDs have different ondisk format for 32bit and 64bit kernels allow recovery to handle both versions and do the necessary decoding SGI-PV: 952214 SGI-Modid: xfs-linux-melb:xfs-kern:26011a Signed-off-by: Tim Shimmin Signed-off-by: Nathan Scott --- fs/xfs/xfs_extfree_item.c | 56 ++++++++++++++++++++++++++++++ fs/xfs/xfs_extfree_item.h | 53 ++++++++++++++++++++++++++++- fs/xfs/xfs_inode_item.c | 49 ++++++++++++++++++++++++++ fs/xfs/xfs_inode_item.h | 61 +++++++++++++++++---------------- fs/xfs/xfs_log_recover.c | 87 ++++++++++++++++++++++++++++++----------------- 5 files changed, 245 insertions(+), 61 deletions(-) diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c index f19282ec854..8b028f12854 100644 --- a/fs/xfs/xfs_extfree_item.c +++ b/fs/xfs/xfs_extfree_item.c @@ -293,6 +293,62 @@ xfs_efi_init(xfs_mount_t *mp, return (efip); } +/* + * Copy an EFI format buffer from the given buf, and into the destination + * EFI format structure. + * The given buffer can be in 32 bit or 64 bit form (which has different padding), + * one of which will be the native format for this kernel. + * It will handle the conversion of formats if necessary. + */ +int +xfs_efi_copy_format(xfs_log_iovec_t *buf, xfs_efi_log_format_t *dst_efi_fmt) +{ + xfs_efi_log_format_t *src_efi_fmt = (xfs_efi_log_format_t *)buf->i_addr; + uint i; + uint len = sizeof(xfs_efi_log_format_t) + + (src_efi_fmt->efi_nextents - 1) * sizeof(xfs_extent_t); + uint len32 = sizeof(xfs_efi_log_format_32_t) + + (src_efi_fmt->efi_nextents - 1) * sizeof(xfs_extent_32_t); + uint len64 = sizeof(xfs_efi_log_format_64_t) + + (src_efi_fmt->efi_nextents - 1) * sizeof(xfs_extent_64_t); + + if (buf->i_len == len) { + memcpy((char *)dst_efi_fmt, (char*)src_efi_fmt, len); + return 0; + } else if (buf->i_len == len32) { + xfs_efi_log_format_32_t *src_efi_fmt_32 = + (xfs_efi_log_format_32_t *)buf->i_addr; + + dst_efi_fmt->efi_type = src_efi_fmt_32->efi_type; + dst_efi_fmt->efi_size = src_efi_fmt_32->efi_size; + dst_efi_fmt->efi_nextents = src_efi_fmt_32->efi_nextents; + dst_efi_fmt->efi_id = src_efi_fmt_32->efi_id; + for (i = 0; i < dst_efi_fmt->efi_nextents; i++) { + dst_efi_fmt->efi_extents[i].ext_start = + src_efi_fmt_32->efi_extents[i].ext_start; + dst_efi_fmt->efi_extents[i].ext_len = + src_efi_fmt_32->efi_extents[i].ext_len; + } + return 0; + } else if (buf->i_len == len64) { + xfs_efi_log_format_64_t *src_efi_fmt_64 = + (xfs_efi_log_format_64_t *)buf->i_addr; + + dst_efi_fmt->efi_type = src_efi_fmt_64->efi_type; + dst_efi_fmt->efi_size = src_efi_fmt_64->efi_size; + dst_efi_fmt->efi_nextents = src_efi_fmt_64->efi_nextents; + dst_efi_fmt->efi_id = src_efi_fmt_64->efi_id; + for (i = 0; i < dst_efi_fmt->efi_nextents; i++) { + dst_efi_fmt->efi_extents[i].ext_start = + src_efi_fmt_64->efi_extents[i].ext_start; + dst_efi_fmt->efi_extents[i].ext_len = + src_efi_fmt_64->efi_extents[i].ext_len; + } + return 0; + } + return EFSCORRUPTED; +} + /* * This is called by the efd item code below to release references to * the given efi item. Each efd calls this with the number of diff --git a/fs/xfs/xfs_extfree_item.h b/fs/xfs/xfs_extfree_item.h index 5bf681708fe..0ea45edaab0 100644 --- a/fs/xfs/xfs_extfree_item.h +++ b/fs/xfs/xfs_extfree_item.h @@ -26,6 +26,24 @@ typedef struct xfs_extent { xfs_extlen_t ext_len; } xfs_extent_t; +/* + * Since an xfs_extent_t has types (start:64, len: 32) + * there are different alignments on 32 bit and 64 bit kernels. + * So we provide the different variants for use by a + * conversion routine. + */ + +typedef struct xfs_extent_32 { + xfs_dfsbno_t ext_start; + xfs_extlen_t ext_len; +} __attribute__((packed)) xfs_extent_32_t; + +typedef struct xfs_extent_64 { + xfs_dfsbno_t ext_start; + xfs_extlen_t ext_len; + __uint32_t ext_pad; +} xfs_extent_64_t; + /* * This is the structure used to lay out an efi log item in the * log. The efi_extents field is a variable size array whose @@ -39,6 +57,22 @@ typedef struct xfs_efi_log_format { xfs_extent_t efi_extents[1]; /* array of extents to free */ } xfs_efi_log_format_t; +typedef struct xfs_efi_log_format_32 { + unsigned short efi_type; /* efi log item type */ + unsigned short efi_size; /* size of this item */ + uint efi_nextents; /* # extents to free */ + __uint64_t efi_id; /* efi identifier */ + xfs_extent_32_t efi_extents[1]; /* array of extents to free */ +} __attribute__((packed)) xfs_efi_log_format_32_t; + +typedef struct xfs_efi_log_format_64 { + unsigned short efi_type; /* efi log item type */ + unsigned short efi_size; /* size of this item */ + uint efi_nextents; /* # extents to free */ + __uint64_t efi_id; /* efi identifier */ + xfs_extent_64_t efi_extents[1]; /* array of extents to free */ +} xfs_efi_log_format_64_t; + /* * This is the structure used to lay out an efd log item in the * log. The efd_extents array is a variable size array whose @@ -52,6 +86,22 @@ typedef struct xfs_efd_log_format { xfs_extent_t efd_extents[1]; /* array of extents freed */ } xfs_efd_log_format_t; +typedef struct xfs_efd_log_format_32 { + unsigned short efd_type; /* efd log item type */ + unsigned short efd_size; /* size of this item */ + uint efd_nextents; /* # of extents freed */ + __uint64_t efd_efi_id; /* id of corresponding efi */ + xfs_extent_32_t efd_extents[1]; /* array of extents freed */ +} __attribute__((packed)) xfs_efd_log_format_32_t; + +typedef struct xfs_efd_log_format_64 { + unsigned short efd_type; /* efd log item type */ + unsigned short efd_size; /* size of this item */ + uint efd_nextents; /* # of extents freed */ + __uint64_t efd_efi_id; /* id of corresponding efi */ + xfs_extent_64_t efd_extents[1]; /* array of extents freed */ +} xfs_efd_log_format_64_t; + #ifdef __KERNEL__ @@ -103,7 +153,8 @@ extern struct kmem_zone *xfs_efd_zone; xfs_efi_log_item_t *xfs_efi_init(struct xfs_mount *, uint); xfs_efd_log_item_t *xfs_efd_init(struct xfs_mount *, xfs_efi_log_item_t *, uint); - +int xfs_efi_copy_format(xfs_log_iovec_t *buf, + xfs_efi_log_format_t *dst_efi_fmt); void xfs_efi_item_free(xfs_efi_log_item_t *); #endif /* __KERNEL__ */ diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index 7497a481b2f..cd65a565b4f 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c @@ -1084,3 +1084,52 @@ xfs_istale_done( { xfs_iflush_abort(iip->ili_inode); } + +/* + * convert an xfs_inode_log_format struct from either 32 or 64 bit versions + * (which can have different field alignments) to the native version + */ +int +xfs_inode_item_format_convert( + xfs_log_iovec_t *buf, + xfs_inode_log_format_t *in_f) +{ + if (buf->i_len == sizeof(xfs_inode_log_format_32_t)) { + xfs_inode_log_format_32_t *in_f32; + + in_f32 = (xfs_inode_log_format_32_t *)buf->i_addr; + in_f->ilf_type = in_f32->ilf_type; + in_f->ilf_size = in_f32->ilf_size; + in_f->ilf_fields = in_f32->ilf_fields; + in_f->ilf_asize = in_f32->ilf_asize; + in_f->ilf_dsize = in_f32->ilf_dsize; + in_f->ilf_ino = in_f32->ilf_ino; + /* copy biggest field of ilf_u */ + memcpy(in_f->ilf_u.ilfu_uuid.__u_bits, + in_f32->ilf_u.ilfu_uuid.__u_bits, + sizeof(uuid_t)); + in_f->ilf_blkno = in_f32->ilf_blkno; + in_f->ilf_len = in_f32->ilf_len; + in_f->ilf_boffset = in_f32->ilf_boffset; + return 0; + } else if (buf->i_len == sizeof(xfs_inode_log_format_64_t)){ + xfs_inode_log_format_64_t *in_f64; + + in_f64 = (xfs_inode_log_format_64_t *)buf->i_addr; + in_f->ilf_type = in_f64->ilf_type; + in_f->ilf_size = in_f64->ilf_size; + in_f->ilf_fields = in_f64->ilf_fields; + in_f->ilf_asize = in_f64->ilf_asize; + in_f->ilf_dsize = in_f64->ilf_dsize; + in_f->ilf_ino = in_f64->ilf_ino; + /* copy biggest field of ilf_u */ + memcpy(in_f->ilf_u.ilfu_uuid.__u_bits, + in_f64->ilf_u.ilfu_uuid.__u_bits, + sizeof(uuid_t)); + in_f->ilf_blkno = in_f64->ilf_blkno; + in_f->ilf_len = in_f64->ilf_len; + in_f->ilf_boffset = in_f64->ilf_boffset; + return 0; + } + return EFSCORRUPTED; +} diff --git a/fs/xfs/xfs_inode_item.h b/fs/xfs/xfs_inode_item.h index c5dbf93b666..5db6cd1b4cf 100644 --- a/fs/xfs/xfs_inode_item.h +++ b/fs/xfs/xfs_inode_item.h @@ -23,25 +23,6 @@ * log. The size of the inline data/extents/b-tree root to be logged * (if any) is indicated in the ilf_dsize field. Changes to this structure * must be added on to the end. - * - * Convention for naming inode log item versions : The current version - * is always named XFS_LI_INODE. When an inode log item gets superseded, - * add the latest version of IRIX that will generate logs with that item - * to the version name. - * - * -Version 1 of this structure (XFS_LI_5_3_INODE) included up to the first - * union (ilf_u) field. This was released with IRIX 5.3-XFS. - * -Version 2 of this structure (XFS_LI_6_1_INODE) is currently the entire - * structure. This was released with IRIX 6.0.1-XFS and IRIX 6.1. - * -Version 3 of this structure (XFS_LI_INODE) is the same as version 2 - * so a new structure definition wasn't necessary. However, we had - * to add a new type because the inode cluster size changed from 4K - * to 8K and the version number had to be rev'ved to keep older kernels - * from trying to recover logs with the 8K buffers in them. The logging - * code can handle recovery on different-sized clusters now so hopefully - * this'll be the last time we need to change the inode log item just - * for a change in the inode cluster size. This new version was - * released with IRIX 6.2. */ typedef struct xfs_inode_log_format { unsigned short ilf_type; /* inode log item type */ @@ -59,18 +40,38 @@ typedef struct xfs_inode_log_format { int ilf_boffset; /* off of inode in buffer */ } xfs_inode_log_format_t; -/* Initial version shipped with IRIX 5.3-XFS */ -typedef struct xfs_inode_log_format_v1 { - unsigned short ilf_type; /* inode log item type */ - unsigned short ilf_size; /* size of this item */ - uint ilf_fields; /* flags for fields logged */ - uint ilf_dsize; /* size of data/ext/root */ - xfs_ino_t ilf_ino; /* inode number */ +typedef struct xfs_inode_log_format_32 { + unsigned short ilf_type; /* 16: inode log item type */ + unsigned short ilf_size; /* 16: size of this item */ + uint ilf_fields; /* 32: flags for fields logged */ + ushort ilf_asize; /* 32: size of attr d/ext/root */ + ushort ilf_dsize; /* 32: size of data/ext/root */ + xfs_ino_t ilf_ino; /* 64: inode number */ union { - xfs_dev_t ilfu_rdev; /* rdev value for dev inode*/ - uuid_t ilfu_uuid; /* mount point value */ + xfs_dev_t ilfu_rdev; /* 32: rdev value for dev inode*/ + uuid_t ilfu_uuid; /* 128: mount point value */ + } ilf_u; + __int64_t ilf_blkno; /* 64: blkno of inode buffer */ + int ilf_len; /* 32: len of inode buffer */ + int ilf_boffset; /* 32: off of inode in buffer */ +} __attribute__((packed)) xfs_inode_log_format_32_t; + +typedef struct xfs_inode_log_format_64 { + unsigned short ilf_type; /* 16: inode log item type */ + unsigned short ilf_size; /* 16: size of this item */ + uint ilf_fields; /* 32: flags for fields logged */ + ushort ilf_asize; /* 32: size of attr d/ext/root */ + ushort ilf_dsize; /* 32: size of data/ext/root */ + __uint32_t ilf_pad; /* 32: pad for 64 bit boundary */ + xfs_ino_t ilf_ino; /* 64: inode number */ + union { + xfs_dev_t ilfu_rdev; /* 32: rdev value for dev inode*/ + uuid_t ilfu_uuid; /* 128: mount point value */ } ilf_u; -} xfs_inode_log_format_t_v1; + __int64_t ilf_blkno; /* 64: blkno of inode buffer */ + int ilf_len; /* 32: len of inode buffer */ + int ilf_boffset; /* 32: off of inode in buffer */ +} xfs_inode_log_format_64_t; /* * Flags for xfs_trans_log_inode flags field. @@ -172,6 +173,8 @@ extern void xfs_inode_item_destroy(struct xfs_inode *); extern void xfs_iflush_done(struct xfs_buf *, xfs_inode_log_item_t *); extern void xfs_istale_done(struct xfs_buf *, xfs_inode_log_item_t *); extern void xfs_iflush_abort(struct xfs_inode *); +extern int xfs_inode_item_format_convert(xfs_log_iovec_t *, + xfs_inode_log_format_t *); #endif /* __KERNEL__ */ diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 1f0016b0b4e..efffa75fd5c 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -2292,12 +2292,22 @@ xlog_recover_do_inode_trans( int attr_index; uint fields; xfs_dinode_core_t *dicp; + int need_free = 0; if (pass == XLOG_RECOVER_PASS1) { return 0; } - in_f = (xfs_inode_log_format_t *)item->ri_buf[0].i_addr; + if (item->ri_buf[0].i_len == sizeof(xfs_inode_log_format_t)) { + in_f = (xfs_inode_log_format_t *)item->ri_buf[0].i_addr; + } else { + in_f = (xfs_inode_log_format_t *)kmem_alloc( + sizeof(xfs_inode_log_format_t), KM_SLEEP); + need_free = 1; + error = xfs_inode_item_format_convert(&item->ri_buf[0], in_f); + if (error) + goto error; + } ino = in_f->ilf_ino; mp = log->l_mp; if (ITEM_TYPE(item) == XFS_LI_INODE) { @@ -2323,8 +2333,10 @@ xlog_recover_do_inode_trans( * Inode buffers can be freed, look out for it, * and do not replay the inode. */ - if (xlog_check_buffer_cancelled(log, imap.im_blkno, imap.im_len, 0)) - return 0; + if (xlog_check_buffer_cancelled(log, imap.im_blkno, imap.im_len, 0)) { + error = 0; + goto error; + } bp = xfs_buf_read_flags(mp->m_ddev_targp, imap.im_blkno, imap.im_len, XFS_BUF_LOCK); @@ -2333,7 +2345,7 @@ xlog_recover_do_inode_trans( bp, imap.im_blkno); error = XFS_BUF_GETERROR(bp); xfs_buf_relse(bp); - return error; + goto error; } error = 0; ASSERT(in_f->ilf_fields & XFS_ILOG_CORE); @@ -2350,7 +2362,8 @@ xlog_recover_do_inode_trans( dip, bp, ino); XFS_ERROR_REPORT("xlog_recover_do_inode_trans(1)", XFS_ERRLEVEL_LOW, mp); - return XFS_ERROR(EFSCORRUPTED); + error = EFSCORRUPTED; + goto error; } dicp = (xfs_dinode_core_t*)(item->ri_buf[1].i_addr); if (unlikely(dicp->di_magic != XFS_DINODE_MAGIC)) { @@ -2360,7 +2373,8 @@ xlog_recover_do_inode_trans( item, ino); XFS_ERROR_REPORT("xlog_recover_do_inode_trans(2)", XFS_ERRLEVEL_LOW, mp); - return XFS_ERROR(EFSCORRUPTED); + error = EFSCORRUPTED; + goto error; } /* Skip replay when the on disk inode is newer than the log one */ @@ -2376,7 +2390,8 @@ xlog_recover_do_inode_trans( /* do nothing */ } else { xfs_buf_relse(bp); - return 0; + error = 0; + goto error; } } /* Take the opportunity to reset the flush iteration count */ @@ -2391,7 +2406,8 @@ xlog_recover_do_inode_trans( xfs_fs_cmn_err(CE_ALERT, mp, "xfs_inode_recover: Bad regular inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld", item, dip, bp, ino); - return XFS_ERROR(EFSCORRUPTED); + error = EFSCORRUPTED; + goto error; } } else if (unlikely((dicp->di_mode & S_IFMT) == S_IFDIR)) { if ((dicp->di_format != XFS_DINODE_FMT_EXTENTS) && @@ -2403,7 +2419,8 @@ xlog_recover_do_inode_trans( xfs_fs_cmn_err(CE_ALERT, mp, "xfs_inode_recover: Bad dir inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld", item, dip, bp, ino); - return XFS_ERROR(EFSCORRUPTED); + error = EFSCORRUPTED; + goto error; } } if (unlikely(dicp->di_nextents + dicp->di_anextents > dicp->di_nblocks)){ @@ -2415,7 +2432,8 @@ xlog_recover_do_inode_trans( item, dip, bp, ino, dicp->di_nextents + dicp->di_anextents, dicp->di_nblocks); - return XFS_ERROR(EFSCORRUPTED); + error = EFSCORRUPTED; + goto error; } if (unlikely(dicp->di_forkoff > mp->m_sb.sb_inodesize)) { XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(6)", @@ -2424,7 +2442,8 @@ xlog_recover_do_inode_trans( xfs_fs_cmn_err(CE_ALERT, mp, "xfs_inode_recover: Bad inode log rec ptr 0x%p, dino ptr 0x%p, dino bp 0x%p, ino %Ld, forkoff 0x%x", item, dip, bp, ino, dicp->di_forkoff); - return XFS_ERROR(EFSCORRUPTED); + error = EFSCORRUPTED; + goto error; } if (unlikely(item->ri_buf[1].i_len > sizeof(xfs_dinode_core_t))) { XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(7)", @@ -2433,7 +2452,8 @@ xlog_recover_do_inode_trans( xfs_fs_cmn_err(CE_ALERT, mp, "xfs_inode_recover: Bad inode log record length %d, rec ptr 0x%p", item->ri_buf[1].i_len, item); - return XFS_ERROR(EFSCORRUPTED); + error = EFSCORRUPTED; + goto error; } /* The core is in in-core format */ @@ -2521,7 +2541,8 @@ xlog_recover_do_inode_trans( xlog_warn("XFS: xlog_recover_do_inode_trans: Invalid flag"); ASSERT(0); xfs_buf_relse(bp); - return XFS_ERROR(EIO); + error = EIO; + goto error; } } @@ -2537,7 +2558,10 @@ write_inode_buffer: error = xfs_bwrite(mp, bp); } - return (error); +error: + if (need_free) + kmem_free(in_f, sizeof(*in_f)); + return XFS_ERROR(error); } /* @@ -2674,32 +2698,32 @@ xlog_recover_do_dquot_trans( * structure into it, and adds the efi to the AIL with the given * LSN. */ -STATIC void +STATIC int xlog_recover_do_efi_trans( xlog_t *log, xlog_recover_item_t *item, xfs_lsn_t lsn, int pass) { + int error; xfs_mount_t *mp; xfs_efi_log_item_t *efip; xfs_efi_log_format_t *efi_formatp; SPLDECL(s); if (pass == XLOG_RECOVER_PASS1) { - return; + return 0; } efi_formatp = (xfs_efi_log_format_t *)item->ri_buf[0].i_addr; - ASSERT(item->ri_buf[0].i_len == - (sizeof(xfs_efi_log_format_t) + - ((efi_formatp->efi_nextents - 1) * sizeof(xfs_extent_t)))); mp = log->l_mp; efip = xfs_efi_init(mp, efi_formatp->efi_nextents); - memcpy((char *)&(efip->efi_format), (char *)efi_formatp, - sizeof(xfs_efi_log_format_t) + - ((efi_formatp->efi_nextents - 1) * sizeof(xfs_extent_t))); + if ((error = xfs_efi_copy_format(&(item->ri_buf[0]), + &(efip->efi_format)))) { + xfs_efi_item_free(efip); + return error; + } efip->efi_next_extent = efi_formatp->efi_nextents; efip->efi_flags |= XFS_EFI_COMMITTED; @@ -2708,6 +2732,7 @@ xlog_recover_do_efi_trans( * xfs_trans_update_ail() drops the AIL lock. */ xfs_trans_update_ail(mp, (xfs_log_item_t *)efip, lsn, s); + return 0; } @@ -2738,9 +2763,10 @@ xlog_recover_do_efd_trans( } efd_formatp = (xfs_efd_log_format_t *)item->ri_buf[0].i_addr; - ASSERT(item->ri_buf[0].i_len == - (sizeof(xfs_efd_log_format_t) + - ((efd_formatp->efd_nextents - 1) * sizeof(xfs_extent_t)))); + ASSERT((item->ri_buf[0].i_len == (sizeof(xfs_efd_log_format_32_t) + + ((efd_formatp->efd_nextents - 1) * sizeof(xfs_extent_32_t)))) || + (item->ri_buf[0].i_len == (sizeof(xfs_efd_log_format_64_t) + + ((efd_formatp->efd_nextents - 1) * sizeof(xfs_extent_64_t))))); efi_id = efd_formatp->efd_efi_id; /* @@ -2810,15 +2836,14 @@ xlog_recover_do_trans( if ((error = xlog_recover_do_buffer_trans(log, item, pass))) break; - } else if ((ITEM_TYPE(item) == XFS_LI_INODE) || - (ITEM_TYPE(item) == XFS_LI_6_1_INODE) || - (ITEM_TYPE(item) == XFS_LI_5_3_INODE)) { + } else if ((ITEM_TYPE(item) == XFS_LI_INODE)) { if ((error = xlog_recover_do_inode_trans(log, item, pass))) break; } else if (ITEM_TYPE(item) == XFS_LI_EFI) { - xlog_recover_do_efi_trans(log, item, trans->r_lsn, - pass); + if ((error = xlog_recover_do_efi_trans(log, item, trans->r_lsn, + pass))) + break; } else if (ITEM_TYPE(item) == XFS_LI_EFD) { xlog_recover_do_efd_trans(log, item, pass); } else if (ITEM_TYPE(item) == XFS_LI_DQUOT) { @@ -3798,7 +3823,7 @@ xlog_do_log_recovery( error = xlog_do_recovery_pass(log, head_blk, tail_blk, XLOG_RECOVER_PASS2); #ifdef DEBUG - { + if (!error) { int i; for (i = 0; i < XLOG_BC_TABLE_SIZE; i++) -- cgit v1.2.3 From 714250879ea61cdb1a39bb96fe9d934ee0c669a2 Mon Sep 17 00:00:00 2001 From: David Chinner Date: Fri, 9 Jun 2006 14:55:52 +1000 Subject: [XFS] Stop a BUG from occurring in generic_delete_inode by preventing transaction completion from marking the inode dirty while it is being cleaned up on it's way out of the system. SGI-PV: 952967 SGI-Modid: xfs-linux-melb:xfs-kern:26040a Signed-off-by: David Chinner Signed-off-by: Nathan Scott --- fs/xfs/xfs_inode.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 083fc0479e6..df695e96806 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -2757,7 +2757,8 @@ xfs_iunpin( if (vp) { struct inode *inode = vn_to_inode(vp); - if (!(inode->i_state & I_NEW)) + if (!(inode->i_state & + (I_NEW|I_FREEING|I_CLEAR))) mark_inode_dirty_sync(inode); } } -- cgit v1.2.3 From 87c199c2a79220ac9e216e72d18a15148f84d9e0 Mon Sep 17 00:00:00 2001 From: Tim Shimmin Date: Fri, 9 Jun 2006 14:56:16 +1000 Subject: [XFS] Over zealous with doing endian conversions. We endian converted the logged version of di_next_unlinked which is actually always stored in the correct ondisk format. This was pointed out to us by Shailendra Tripathi. And is evident in the xfs qa test of 121. SGI-PV: 953263 SGI-Modid: xfs-linux-melb:xfs-kern:26044a Signed-off-by: Tim Shimmin Signed-off-by: Nathan Scott --- fs/xfs/xfs_log_recover.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index efffa75fd5c..3abc98944c0 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. + * Copyright (c) 2000-2006 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -1889,7 +1889,7 @@ xlog_recover_do_inode_buffer( buffer_nextp = (xfs_agino_t *)xfs_buf_offset(bp, next_unlinked_offset); - INT_SET(*buffer_nextp, ARCH_CONVERT, *logged_nextp); + *buffer_nextp = *logged_nextp; } return 0; -- cgit v1.2.3 From 72c93bcc6348a385416603459c2fdb4cf6c43687 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Fri, 9 Jun 2006 14:57:01 +1000 Subject: [XFS] lock validator: lockdep: small xfs init_rwsem() cleanup init_rwsem() has no return value. This is not a problem if init_rwsem() is a function, but it's a problem if it's a do { ... } while (0) macro. (which lockdep introduces) SGI-PV: 904196 SGI-Modid: xfs-linux-melb:xfs-kern:26082a Signed-off-by: Ingo Molnar Signed-off-by: Arjan van de Ven Signed-off-by: Andrew Morton Signed-off-by: Nathan Scott --- fs/xfs/linux-2.6/mrlock.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/xfs/linux-2.6/mrlock.h b/fs/xfs/linux-2.6/mrlock.h index 1b262b790d9..32e1ce0f04c 100644 --- a/fs/xfs/linux-2.6/mrlock.h +++ b/fs/xfs/linux-2.6/mrlock.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2005 Silicon Graphics, Inc. + * Copyright (c) 2000-2006 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -28,7 +28,7 @@ typedef struct { } mrlock_t; #define mrinit(mrp, name) \ - ( (mrp)->mr_writer = 0, init_rwsem(&(mrp)->mr_lock) ) + do { (mrp)->mr_writer = 0; init_rwsem(&(mrp)->mr_lock); } while (0) #define mrlock_init(mrp, t,n,s) mrinit(mrp, n) #define mrfree(mrp) do { } while (0) #define mraccess(mrp) mraccessf(mrp, 0) -- cgit v1.2.3 From 3d80ede4799889ede2aa785c2511aef3e78d5bb1 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Fri, 9 Jun 2006 14:57:30 +1000 Subject: [XFS] Drop use of m_writeio_blocks when zeroing, its not meaningful anymore here. SGI-PV: 904196 SGI-Modid: xfs-linux-melb:xfs-kern:26094a Signed-off-by: Nathan Scott --- fs/xfs/linux-2.6/xfs_lrw.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c index 67b5e1c20de..6fbdca3eaa7 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.c +++ b/fs/xfs/linux-2.6/xfs_lrw.c @@ -510,7 +510,6 @@ xfs_zero_eof( xfs_fileoff_t end_zero_fsb; xfs_fileoff_t zero_count_fsb; xfs_fileoff_t last_fsb; - xfs_extlen_t buf_len_fsb; xfs_mount_t *mp = io->io_mount; int nimaps; int error = 0; @@ -579,16 +578,7 @@ xfs_zero_eof( } /* - * There are blocks in the range requested. - * Zero them a single write at a time. We actually - * don't zero the entire range returned if it is - * too big and simply loop around to get the rest. - * That is not the most efficient thing to do, but it - * is simple and this path should not be exercised often. - */ - buf_len_fsb = XFS_FILBLKS_MIN(imap.br_blockcount, - mp->m_writeio_blocks << 8); - /* + * There are blocks we need to zero. * Drop the inode lock while we're doing the I/O. * We'll still have the iolock to protect us. */ @@ -596,14 +586,13 @@ xfs_zero_eof( error = xfs_iozero(ip, XFS_FSB_TO_B(mp, start_zero_fsb), - XFS_FSB_TO_B(mp, buf_len_fsb), + XFS_FSB_TO_B(mp, imap.br_blockcount), end_size); - if (error) { goto out_lock; } - start_zero_fsb = imap.br_startoff + buf_len_fsb; + start_zero_fsb = imap.br_startoff + imap.br_blockcount; ASSERT(start_zero_fsb <= (end_zero_fsb + 1)); XFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD); -- cgit v1.2.3 From b76963fac4a17b661bad46e5a57b0f918c6f0cd1 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Fri, 9 Jun 2006 14:58:20 +1000 Subject: [XFS] getattr can return an error code, so propogate any from lower layers. SGI-PV: 904196 SGI-Modid: xfs-linux-melb:xfs-kern:26095a Signed-off-by: Nathan Scott --- fs/xfs/linux-2.6/xfs_iops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index 2e2e275c786..0da1d6b081e 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c @@ -643,7 +643,7 @@ xfs_vn_getattr( error = vn_revalidate(vp); if (!error) generic_fillattr(inode, stat); - return 0; + return -error; } STATIC int -- cgit v1.2.3 From 7d04a335b6b2d79e3742ffd28bd651204574e794 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Fri, 9 Jun 2006 14:58:38 +1000 Subject: [XFS] Shutdown the filesystem if all device paths have gone. Made shutdown vop flags consistent with sync vop flags declarations too. SGI-PV: 939911 SGI-Modid: xfs-linux-melb:xfs-kern:26096a Signed-off-by: Nathan Scott --- fs/xfs/linux-2.6/xfs_aops.c | 15 +++++++-------- fs/xfs/linux-2.6/xfs_aops.h | 2 +- fs/xfs/linux-2.6/xfs_vfs.h | 7 +++++++ fs/xfs/linux-2.6/xfs_vnode.c | 16 ++++++++++++++++ fs/xfs/linux-2.6/xfs_vnode.h | 2 ++ fs/xfs/quota/xfs_dquot.c | 2 +- fs/xfs/xfs_bmap.c | 4 ++-- fs/xfs/xfs_buf_item.c | 2 +- fs/xfs/xfs_fsops.c | 7 ++++--- fs/xfs/xfs_inode.c | 4 ++-- fs/xfs/xfs_log.c | 10 +++++----- fs/xfs/xfs_log_recover.c | 2 +- fs/xfs/xfs_mount.h | 9 --------- fs/xfs/xfs_rw.c | 36 ++++++++++++++++++++---------------- fs/xfs/xfs_trans.c | 4 ++-- fs/xfs/xfs_trans_ail.c | 5 +++-- fs/xfs/xfs_trans_buf.c | 6 +++--- fs/xfs/xfs_vnodeops.c | 2 +- 18 files changed, 78 insertions(+), 57 deletions(-) diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index 4d191ef39b6..1fcdc0abda6 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c @@ -136,9 +136,10 @@ xfs_destroy_ioend( for (bh = ioend->io_buffer_head; bh; bh = next) { next = bh->b_private; - bh->b_end_io(bh, ioend->io_uptodate); + bh->b_end_io(bh, !ioend->io_error); } - + if (unlikely(ioend->io_error)) + vn_ioerror(ioend->io_vnode, ioend->io_error, __FILE__,__LINE__); vn_iowake(ioend->io_vnode); mempool_free(ioend, xfs_ioend_pool); } @@ -185,7 +186,7 @@ xfs_end_bio_unwritten( size_t size = ioend->io_size; int error; - if (ioend->io_uptodate) + if (likely(!ioend->io_error)) VOP_BMAP(vp, offset, size, BMAPI_UNWRITTEN, NULL, NULL, error); xfs_destroy_ioend(ioend); } @@ -211,7 +212,7 @@ xfs_alloc_ioend( * all the I/O from calling the completion routine too early. */ atomic_set(&ioend->io_remaining, 1); - ioend->io_uptodate = 1; /* cleared if any I/O fails */ + ioend->io_error = 0; ioend->io_list = NULL; ioend->io_type = type; ioend->io_vnode = vn_from_inode(inode); @@ -271,16 +272,14 @@ xfs_end_bio( if (bio->bi_size) return 1; - ASSERT(ioend); ASSERT(atomic_read(&bio->bi_cnt) >= 1); + ioend->io_error = test_bit(BIO_UPTODATE, &bio->bi_flags) ? 0 : error; /* Toss bio and pass work off to an xfsdatad thread */ - if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) - ioend->io_uptodate = 0; bio->bi_private = NULL; bio->bi_end_io = NULL; - bio_put(bio); + xfs_finish_ioend(ioend); return 0; } diff --git a/fs/xfs/linux-2.6/xfs_aops.h b/fs/xfs/linux-2.6/xfs_aops.h index 60716543c68..41c7d2da638 100644 --- a/fs/xfs/linux-2.6/xfs_aops.h +++ b/fs/xfs/linux-2.6/xfs_aops.h @@ -30,7 +30,7 @@ typedef void (*xfs_ioend_func_t)(void *); typedef struct xfs_ioend { struct xfs_ioend *io_list; /* next ioend in chain */ unsigned int io_type; /* delalloc / unwritten */ - unsigned int io_uptodate; /* I/O status register */ + int io_error; /* I/O error code */ atomic_t io_remaining; /* hold count */ struct vnode *io_vnode; /* file being written to */ struct buffer_head *io_buffer_head;/* buffer linked list head */ diff --git a/fs/xfs/linux-2.6/xfs_vfs.h b/fs/xfs/linux-2.6/xfs_vfs.h index 841200c0309..2ca05043a0f 100644 --- a/fs/xfs/linux-2.6/xfs_vfs.h +++ b/fs/xfs/linux-2.6/xfs_vfs.h @@ -94,6 +94,13 @@ typedef enum { #define SYNC_REMOUNT 0x0080 /* remount readonly, no dummy LRs */ #define SYNC_QUIESCE 0x0100 /* quiesce filesystem for a snapshot */ +#define SHUTDOWN_META_IO_ERROR 0x0001 /* write attempt to metadata failed */ +#define SHUTDOWN_LOG_IO_ERROR 0x0002 /* write attempt to the log failed */ +#define SHUTDOWN_FORCE_UMOUNT 0x0004 /* shutdown from a forced unmount */ +#define SHUTDOWN_CORRUPT_INCORE 0x0008 /* corrupt in-memory data structures */ +#define SHUTDOWN_REMOTE_REQ 0x0010 /* shutdown came from remote cell */ +#define SHUTDOWN_DEVICE_REQ 0x0020 /* failed all paths to the device */ + typedef int (*vfs_mount_t)(bhv_desc_t *, struct xfs_mount_args *, struct cred *); typedef int (*vfs_parseargs_t)(bhv_desc_t *, char *, diff --git a/fs/xfs/linux-2.6/xfs_vnode.c b/fs/xfs/linux-2.6/xfs_vnode.c index d27c25b27cc..f17e39cff23 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.c +++ b/fs/xfs/linux-2.6/xfs_vnode.c @@ -54,6 +54,22 @@ vn_iowake( wake_up(vptosync(vp)); } +/* + * Volume managers supporting multiple paths can send back ENODEV when the + * final path disappears. In this case continuing to fill the page cache + * with dirty data which cannot be written out is evil, so prevent that. + */ +void +vn_ioerror( + struct vnode *vp, + int error, + char *f, + int l) +{ + if (unlikely(error == -ENODEV)) + VFS_FORCE_SHUTDOWN(vp->v_vfsp, SHUTDOWN_DEVICE_REQ, f, l); +} + struct vnode * vn_initialize( struct inode *inode) diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h index 2a8e16c2235..a64b7db6700 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.h +++ b/fs/xfs/linux-2.6/xfs_vnode.h @@ -514,6 +514,8 @@ extern void vn_revalidate_core(struct vnode *, vattr_t *); extern void vn_iowait(struct vnode *vp); extern void vn_iowake(struct vnode *vp); +extern void vn_ioerror(struct vnode *vp, int error, char *f, int l); + static inline int vn_count(struct vnode *vp) { return atomic_read(&vn_to_inode(vp)->i_count); diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c index 26ee5df4f83..46bec66bb4d 100644 --- a/fs/xfs/quota/xfs_dquot.c +++ b/fs/xfs/quota/xfs_dquot.c @@ -1261,7 +1261,7 @@ xfs_qm_dqflush( if (xfs_qm_dqcheck(&dqp->q_core, be32_to_cpu(ddqp->d_id), 0, XFS_QMOPT_DOWARN, "dqflush (incore copy)")) { - xfs_force_shutdown(dqp->q_mount, XFS_CORRUPT_INCORE); + xfs_force_shutdown(dqp->q_mount, SHUTDOWN_CORRUPT_INCORE); return XFS_ERROR(EIO); } diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index ad595dbefe1..b4529421823 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -4263,8 +4263,8 @@ xfs_bmap_finish( if (!XFS_FORCED_SHUTDOWN(mp)) xfs_force_shutdown(mp, (error == EFSCORRUPTED) ? - XFS_CORRUPT_INCORE : - XFS_METADATA_IO_ERROR); + SHUTDOWN_CORRUPT_INCORE : + SHUTDOWN_META_IO_ERROR); return error; } xfs_trans_log_efd_extent(ntp, efd, free->xbfi_startblock, diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index 5fed15682dd..59013e1f16e 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c @@ -1108,7 +1108,7 @@ xfs_buf_error_relse( XFS_BUF_ERROR(bp,0); xfs_buftrace("BUF_ERROR_RELSE", bp); if (! XFS_FORCED_SHUTDOWN(mp)) - xfs_force_shutdown(mp, XFS_METADATA_IO_ERROR); + xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR); /* * We have to unpin the pinned buffers so do the * callbacks. diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index dfa3527b20a..96f4b3e8fa4 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -578,17 +578,18 @@ xfs_fs_goingdown( struct super_block *sb = freeze_bdev(vfsp->vfs_super->s_bdev); if (sb && !IS_ERR(sb)) { - xfs_force_shutdown(mp, XFS_FORCE_UMOUNT); + xfs_force_shutdown(mp, SHUTDOWN_FORCE_UMOUNT); thaw_bdev(sb->s_bdev, sb); } break; } case XFS_FSOP_GOING_FLAGS_LOGFLUSH: - xfs_force_shutdown(mp, XFS_FORCE_UMOUNT); + xfs_force_shutdown(mp, SHUTDOWN_FORCE_UMOUNT); break; case XFS_FSOP_GOING_FLAGS_NOLOGFLUSH: - xfs_force_shutdown(mp, XFS_FORCE_UMOUNT|XFS_LOG_IO_ERROR); + xfs_force_shutdown(mp, + SHUTDOWN_FORCE_UMOUNT | SHUTDOWN_LOG_IO_ERROR); break; default: return XFS_ERROR(EINVAL); diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index df695e96806..b30bffa99ed 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -3206,7 +3206,7 @@ xfs_iflush( corrupt_out: xfs_buf_relse(bp); - xfs_force_shutdown(mp, XFS_CORRUPT_INCORE); + xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); xfs_iflush_abort(ip); /* * Unlocks the flush lock @@ -3228,7 +3228,7 @@ cluster_corrupt_out: xfs_buf_relse(bp); } - xfs_force_shutdown(mp, XFS_CORRUPT_INCORE); + xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); if(!bufwasdelwri) { /* diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 32e841d2f26..7d882d6c7d4 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -402,7 +402,7 @@ xfs_log_release_iclog(xfs_mount_t *mp, xlog_in_core_t *iclog = (xlog_in_core_t *)iclog_hndl; if (xlog_state_release_iclog(log, iclog)) { - xfs_force_shutdown(mp, XFS_LOG_IO_ERROR); + xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR); return EIO; } @@ -726,7 +726,7 @@ xfs_log_write(xfs_mount_t * mp, return XFS_ERROR(EIO); if ((error = xlog_write(mp, reg, nentries, tic, start_lsn, NULL, 0))) { - xfs_force_shutdown(mp, XFS_LOG_IO_ERROR); + xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR); } return error; } /* xfs_log_write */ @@ -956,7 +956,7 @@ xlog_iodone(xfs_buf_t *bp) XFS_ERRTAG_IODONE_IOERR, XFS_RANDOM_IODONE_IOERR)) { xfs_ioerror_alert("xlog_iodone", l->l_mp, bp, XFS_BUF_ADDR(bp)); XFS_BUF_STALE(bp); - xfs_force_shutdown(l->l_mp, XFS_LOG_IO_ERROR); + xfs_force_shutdown(l->l_mp, SHUTDOWN_LOG_IO_ERROR); /* * This flag will be propagated to the trans-committed * callback routines to let them know that the log-commit @@ -1261,7 +1261,7 @@ xlog_commit_record(xfs_mount_t *mp, ASSERT_ALWAYS(iclog); if ((error = xlog_write(mp, reg, 1, ticket, commitlsnp, iclog, XLOG_COMMIT_TRANS))) { - xfs_force_shutdown(mp, XFS_LOG_IO_ERROR); + xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR); } return error; } /* xlog_commit_record */ @@ -1790,7 +1790,7 @@ xlog_write(xfs_mount_t * mp, xfs_cmn_err(XFS_PTAG_LOGRES, CE_ALERT, mp, "xfs_log_write: reservation ran out. Need to up reservation"); /* If we did not panic, shutdown the filesystem */ - xfs_force_shutdown(mp, XFS_CORRUPT_INCORE); + xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); #endif } else ticket->t_curr_res -= len; diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 3abc98944c0..a17218e8153 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -282,7 +282,7 @@ xlog_recover_iodone( mp = XFS_BUF_FSPRIVATE(bp, xfs_mount_t *); xfs_ioerror_alert("xlog_recover_iodone", mp, bp, XFS_BUF_ADDR(bp)); - xfs_force_shutdown(mp, XFS_METADATA_IO_ERROR); + xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR); } XFS_BUF_SET_FSPRIVATE(bp, NULL); XFS_BUF_CLR_IODONE_FUNC(bp); diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index a682eb55810..2ca211214a9 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -513,15 +513,6 @@ xfs_preferred_iosize(xfs_mount_t *mp) #define xfs_force_shutdown(m,f) \ VFS_FORCE_SHUTDOWN((XFS_MTOVFS(m)), f, __FILE__, __LINE__) -/* - * Flags sent to xfs_force_shutdown. - */ -#define XFS_METADATA_IO_ERROR 0x1 -#define XFS_LOG_IO_ERROR 0x2 -#define XFS_FORCE_UMOUNT 0x4 -#define XFS_CORRUPT_INCORE 0x8 /* Corrupt in-memory data structures */ -#define XFS_SHUTDOWN_REMOTE_REQ 0x10 /* Shutdown came from remote cell */ - /* * Flags for xfs_mountfs */ diff --git a/fs/xfs/xfs_rw.c b/fs/xfs/xfs_rw.c index a59c102cf21..d33e4f5808e 100644 --- a/fs/xfs/xfs_rw.c +++ b/fs/xfs/xfs_rw.c @@ -109,12 +109,12 @@ xfs_do_force_shutdown( xfs_mount_t *mp; mp = XFS_BHVTOM(bdp); - logerror = flags & XFS_LOG_IO_ERROR; + logerror = flags & SHUTDOWN_LOG_IO_ERROR; - if (!(flags & XFS_FORCE_UMOUNT)) { - cmn_err(CE_NOTE, - "xfs_force_shutdown(%s,0x%x) called from line %d of file %s. Return address = 0x%p", - mp->m_fsname,flags,lnnum,fname,__return_address); + if (!(flags & SHUTDOWN_FORCE_UMOUNT)) { + cmn_err(CE_NOTE, "xfs_force_shutdown(%s,0x%x) called from " + "line %d of file %s. Return address = 0x%p", + mp->m_fsname, flags, lnnum, fname, __return_address); } /* * No need to duplicate efforts. @@ -125,33 +125,37 @@ xfs_do_force_shutdown( /* * This flags XFS_MOUNT_FS_SHUTDOWN, makes sure that we don't * queue up anybody new on the log reservations, and wakes up - * everybody who's sleeping on log reservations and tells - * them the bad news. + * everybody who's sleeping on log reservations to tell them + * the bad news. */ if (xfs_log_force_umount(mp, logerror)) return; - if (flags & XFS_CORRUPT_INCORE) { + if (flags & SHUTDOWN_CORRUPT_INCORE) { xfs_cmn_err(XFS_PTAG_SHUTDOWN_CORRUPT, CE_ALERT, mp, "Corruption of in-memory data detected. Shutting down filesystem: %s", mp->m_fsname); if (XFS_ERRLEVEL_HIGH <= xfs_error_level) { xfs_stack_trace(); } - } else if (!(flags & XFS_FORCE_UMOUNT)) { + } else if (!(flags & SHUTDOWN_FORCE_UMOUNT)) { if (logerror) { xfs_cmn_err(XFS_PTAG_SHUTDOWN_LOGERROR, CE_ALERT, mp, - "Log I/O Error Detected. Shutting down filesystem: %s", + "Log I/O Error Detected. Shutting down filesystem: %s", mp->m_fsname); - } else if (!(flags & XFS_SHUTDOWN_REMOTE_REQ)) { + } else if (flags & SHUTDOWN_DEVICE_REQ) { xfs_cmn_err(XFS_PTAG_SHUTDOWN_IOERROR, CE_ALERT, mp, - "I/O Error Detected. Shutting down filesystem: %s", + "All device paths lost. Shutting down filesystem: %s", + mp->m_fsname); + } else if (!(flags & SHUTDOWN_REMOTE_REQ)) { + xfs_cmn_err(XFS_PTAG_SHUTDOWN_IOERROR, CE_ALERT, mp, + "I/O Error Detected. Shutting down filesystem: %s", mp->m_fsname); } } - if (!(flags & XFS_FORCE_UMOUNT)) { - cmn_err(CE_ALERT, - "Please umount the filesystem, and rectify the problem(s)"); + if (!(flags & SHUTDOWN_FORCE_UMOUNT)) { + cmn_err(CE_ALERT, "Please umount the filesystem, " + "and rectify the problem(s)"); } } @@ -335,7 +339,7 @@ xfs_bwrite( * from bwrite and we could be tracing a buffer that has * been reused. */ - xfs_force_shutdown(mp, XFS_METADATA_IO_ERROR); + xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR); } return (error); } diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index 8d056cef5d1..c05da5871a5 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -846,7 +846,7 @@ shut_us_down: */ nvec = xfs_trans_count_vecs(tp); if (nvec == 0) { - xfs_force_shutdown(mp, XFS_LOG_IO_ERROR); + xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR); goto shut_us_down; } else if (nvec <= XFS_TRANS_LOGVEC_COUNT) { log_vector = log_vector_fast; @@ -1148,7 +1148,7 @@ xfs_trans_cancel( */ if ((tp->t_flags & XFS_TRANS_DIRTY) && !XFS_FORCED_SHUTDOWN(mp)) { XFS_ERROR_REPORT("xfs_trans_cancel", XFS_ERRLEVEL_LOW, mp); - xfs_force_shutdown(mp, XFS_CORRUPT_INCORE); + xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); } #ifdef DEBUG if (!(flags & XFS_TRANS_ABORT)) { diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c index 19ab24af1c1..e1ca7b6fde4 100644 --- a/fs/xfs/xfs_trans_ail.c +++ b/fs/xfs/xfs_trans_ail.c @@ -363,9 +363,10 @@ xfs_trans_delete_ail( AIL_UNLOCK(mp, s); else { xfs_cmn_err(XFS_PTAG_AILDELETE, CE_ALERT, mp, - "xfs_trans_delete_ail: attempting to delete a log item that is not in the AIL"); + "%s: attempting to delete a log item that is not in the AIL", + __FUNCTION__); AIL_UNLOCK(mp, s); - xfs_force_shutdown(mp, XFS_CORRUPT_INCORE); + xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); } } } diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c index c74c31ebc81..42291364570 100644 --- a/fs/xfs/xfs_trans_buf.c +++ b/fs/xfs/xfs_trans_buf.c @@ -369,7 +369,7 @@ xfs_trans_read_buf( */ if (tp->t_flags & XFS_TRANS_DIRTY) xfs_force_shutdown(tp->t_mountp, - XFS_METADATA_IO_ERROR); + SHUTDOWN_META_IO_ERROR); return error; } } @@ -414,7 +414,7 @@ xfs_trans_read_buf( xfs_ioerror_alert("xfs_trans_read_buf", mp, bp, blkno); if (tp->t_flags & XFS_TRANS_DIRTY) - xfs_force_shutdown(tp->t_mountp, XFS_METADATA_IO_ERROR); + xfs_force_shutdown(tp->t_mountp, SHUTDOWN_META_IO_ERROR); xfs_buf_relse(bp); return error; } @@ -423,7 +423,7 @@ xfs_trans_read_buf( if (xfs_error_target == target) { if (((xfs_req_num++) % xfs_error_mod) == 0) { xfs_force_shutdown(tp->t_mountp, - XFS_METADATA_IO_ERROR); + SHUTDOWN_META_IO_ERROR); xfs_buf_relse(bp); printk("Returning error in trans!\n"); return XFS_ERROR(EIO); diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index d1c6349e401..cb36a56392e 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -1761,7 +1761,7 @@ xfs_inactive( cmn_err(CE_NOTE, "xfs_inactive: xfs_ifree() returned an error = %d on %s", error, mp->m_fsname); - xfs_force_shutdown(mp, XFS_METADATA_IO_ERROR); + xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR); } xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT); } else { -- cgit v1.2.3 From e109007461cddfc80a908f0b015f4eeb485e1d85 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Fri, 9 Jun 2006 14:58:48 +1000 Subject: [XFS] Fix a buffer refcount leak in dir2 code on a forced shutdown. SGI-PV: 904196 SGI-Modid: xfs-linux-melb:xfs-kern:26097a Signed-off-by: Nathan Scott --- fs/xfs/xfs_dir2_node.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c index c0e8fcf5e13..a8d483c0a84 100644 --- a/fs/xfs/xfs_dir2_node.c +++ b/fs/xfs/xfs_dir2_node.c @@ -505,7 +505,6 @@ xfs_dir2_leafn_lookup_int( XFS_DATA_FORK))) { return error; } - curfdb = newfdb; free = curbp->data; ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC); @@ -527,8 +526,11 @@ xfs_dir2_leafn_lookup_int( if (unlikely(be16_to_cpu(free->bests[fi]) == NULLDATAOFF)) { XFS_ERROR_REPORT("xfs_dir2_leafn_lookup_int", XFS_ERRLEVEL_LOW, mp); + if (curfdb != newfdb) + xfs_da_brelse(tp, curbp); return XFS_ERROR(EFSCORRUPTED); } + curfdb = newfdb; if (be16_to_cpu(free->bests[fi]) >= length) { *indexp = index; state->extravalid = 1; -- cgit v1.2.3 From 59c1b082f5fff8269565039600a2ef18d48649b5 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Fri, 9 Jun 2006 14:59:13 +1000 Subject: [XFS] Make the pflags test/set wrappers more legible for us mere humans. SGI-PV: 953338 SGI-Modid: xfs-linux-melb:xfs-kern:26099a Signed-off-by: Nathan Scott --- fs/xfs/linux-2.6/kmem.h | 38 +------------------------------------- fs/xfs/linux-2.6/xfs_aops.c | 4 ++-- fs/xfs/linux-2.6/xfs_linux.h | 14 ++++++++++---- fs/xfs/xfs_trans.c | 25 +++++++++++-------------- 4 files changed, 24 insertions(+), 57 deletions(-) diff --git a/fs/xfs/linux-2.6/kmem.h b/fs/xfs/linux-2.6/kmem.h index 2cfd33d4d8a..939bd84bc7e 100644 --- a/fs/xfs/linux-2.6/kmem.h +++ b/fs/xfs/linux-2.6/kmem.h @@ -22,42 +22,6 @@ #include #include -/* - * Process flags handling - */ - -#define PFLAGS_TEST_NOIO() (current->flags & PF_NOIO) -#define PFLAGS_TEST_FSTRANS() (current->flags & PF_FSTRANS) - -#define PFLAGS_SET_NOIO() do { \ - current->flags |= PF_NOIO; \ -} while (0) - -#define PFLAGS_CLEAR_NOIO() do { \ - current->flags &= ~PF_NOIO; \ -} while (0) - -/* these could be nested, so we save state */ -#define PFLAGS_SET_FSTRANS(STATEP) do { \ - *(STATEP) = current->flags; \ - current->flags |= PF_FSTRANS; \ -} while (0) - -#define PFLAGS_CLEAR_FSTRANS(STATEP) do { \ - *(STATEP) = current->flags; \ - current->flags &= ~PF_FSTRANS; \ -} while (0) - -/* Restore the PF_FSTRANS state to what was saved in STATEP */ -#define PFLAGS_RESTORE_FSTRANS(STATEP) do { \ - current->flags = ((current->flags & ~PF_FSTRANS) | \ - (*(STATEP) & PF_FSTRANS)); \ -} while (0) - -#define PFLAGS_DUP(OSTATEP, NSTATEP) do { \ - *(NSTATEP) = *(OSTATEP); \ -} while (0) - /* * General memory allocation interfaces */ @@ -83,7 +47,7 @@ kmem_flags_convert(unsigned int __nocast flags) lflags = GFP_ATOMIC | __GFP_NOWARN; } else { lflags = GFP_KERNEL | __GFP_NOWARN; - if (PFLAGS_TEST_FSTRANS() || (flags & KM_NOFS)) + if ((current->flags & PF_FSTRANS) || (flags & KM_NOFS)) lflags &= ~__GFP_FS; } return lflags; diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index 1fcdc0abda6..5835e699a7f 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c @@ -1126,7 +1126,7 @@ xfs_vm_writepage( * then mark the page dirty again and leave the page * as is. */ - if (PFLAGS_TEST_FSTRANS() && need_trans) + if (current_test_flags(PF_FSTRANS) && need_trans) goto out_fail; /* @@ -1203,7 +1203,7 @@ xfs_vm_releasepage( /* If we are already inside a transaction or the thread cannot * do I/O, we cannot release this page. */ - if (PFLAGS_TEST_FSTRANS()) + if (current_test_flags(PF_FSTRANS)) return 0; /* diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h index 7d15cb91027..e9285395411 100644 --- a/fs/xfs/linux-2.6/xfs_linux.h +++ b/fs/xfs/linux-2.6/xfs_linux.h @@ -136,13 +136,19 @@ BUFFER_FNS(PrivateStart, unwritten); #define xfs_rotorstep xfs_params.rotorstep.val #define xfs_inherit_nodefrag xfs_params.inherit_nodfrg.val -#ifndef raw_smp_processor_id -#define raw_smp_processor_id() smp_processor_id() -#endif -#define current_cpu() raw_smp_processor_id() +#define current_cpu() (raw_smp_processor_id()) #define current_pid() (current->pid) #define current_fsuid(cred) (current->fsuid) #define current_fsgid(cred) (current->fsgid) +#define current_set_flags(f) (current->flags |= (f)) +#define current_test_flags(f) (current->flags & (f)) +#define current_clear_flags(f) (current->flags & ~(f)) +#define current_set_flags_nested(sp, f) \ + (*(sp) = current->flags, current->flags |= (f)) +#define current_clear_flags_nested(sp, f) \ + (*(sp) = current->flags, current->flags &= ~(f)) +#define current_restore_flags_nested(sp, f) \ + (current->flags = ((current->flags & ~(f)) | (*(sp) & (f)))) #define NBPP PAGE_SIZE #define DPPSHFT (PAGE_SHIFT - 9) diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index c05da5871a5..7a99ed3b187 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -303,7 +303,7 @@ xfs_trans_dup( tp->t_blk_res = tp->t_blk_res_used; ntp->t_rtx_res = tp->t_rtx_res - tp->t_rtx_res_used; tp->t_rtx_res = tp->t_rtx_res_used; - PFLAGS_DUP(&tp->t_pflags, &ntp->t_pflags); + ntp->t_pflags = tp->t_pflags; XFS_TRANS_DUP_DQINFO(tp->t_mountp, tp, ntp); @@ -335,14 +335,11 @@ xfs_trans_reserve( uint logcount) { int log_flags; - int error; - int rsvd; - - error = 0; - rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0; + int error = 0; + int rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0; /* Mark this thread as being in a transaction */ - PFLAGS_SET_FSTRANS(&tp->t_pflags); + current_set_flags_nested(&tp->t_pflags, PF_FSTRANS); /* * Attempt to reserve the needed disk blocks by decrementing @@ -353,7 +350,7 @@ xfs_trans_reserve( error = xfs_mod_incore_sb(tp->t_mountp, XFS_SBS_FDBLOCKS, -blocks, rsvd); if (error != 0) { - PFLAGS_RESTORE_FSTRANS(&tp->t_pflags); + current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS); return (XFS_ERROR(ENOSPC)); } tp->t_blk_res += blocks; @@ -426,9 +423,9 @@ undo_blocks: tp->t_blk_res = 0; } - PFLAGS_RESTORE_FSTRANS(&tp->t_pflags); + current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS); - return (error); + return error; } @@ -819,7 +816,7 @@ shut_us_down: if (commit_lsn == -1 && !shutdown) shutdown = XFS_ERROR(EIO); } - PFLAGS_RESTORE_FSTRANS(&tp->t_pflags); + current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS); xfs_trans_free_items(tp, shutdown? XFS_TRANS_ABORT : 0); xfs_trans_free_busy(tp); xfs_trans_free(tp); @@ -884,7 +881,7 @@ shut_us_down: * had pinned, clean up, free trans structure, and return error. */ if (error || commit_lsn == -1) { - PFLAGS_RESTORE_FSTRANS(&tp->t_pflags); + current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS); xfs_trans_uncommit(tp, flags|XFS_TRANS_ABORT); return XFS_ERROR(EIO); } @@ -926,7 +923,7 @@ shut_us_down: /* * Mark this thread as no longer being in a transaction */ - PFLAGS_RESTORE_FSTRANS(&tp->t_pflags); + current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS); /* * Once all the items of the transaction have been copied @@ -1182,7 +1179,7 @@ xfs_trans_cancel( } /* mark this thread as no longer being in a transaction */ - PFLAGS_RESTORE_FSTRANS(&tp->t_pflags); + current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS); xfs_trans_free_items(tp, flags); xfs_trans_free_busy(tp); -- cgit v1.2.3 From 7d4fb40ad7efe4586d1341d4731377fb4530836f Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Fri, 9 Jun 2006 15:27:16 +1000 Subject: [XFS] Start writeout earlier (on last close) in the case where we have a truncate down followed by delayed allocation (buffered writes) - worst case scenario for the notorious NULL files problem. This reduces the window where we are exposed to that problem significantly. SGI-PV: 917976 SGI-Modid: xfs-linux-melb:xfs-kern:26100a Signed-off-by: Nathan Scott --- fs/xfs/linux-2.6/xfs_aops.c | 13 +++++++ fs/xfs/linux-2.6/xfs_file.c | 15 +++++++ fs/xfs/linux-2.6/xfs_fs_subr.c | 53 +++++-------------------- fs/xfs/linux-2.6/xfs_vnode.h | 39 ++++++++++++------- fs/xfs/xfs_vnodeops.c | 88 +++++++++++++++++++++++++----------------- 5 files changed, 114 insertions(+), 94 deletions(-) diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index 5835e699a7f..c0a90431685 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c @@ -1157,6 +1157,18 @@ out_unlock: return error; } +STATIC int +xfs_vm_writepages( + struct address_space *mapping, + struct writeback_control *wbc) +{ + struct vnode *vp = vn_from_inode(mapping->host); + + if (VN_TRUNC(vp)) + VUNTRUNCATE(vp); + return generic_writepages(mapping, wbc); +} + /* * Called to move a page into cleanable state - and from there * to be released. Possibly the page is already clean. We always @@ -1451,6 +1463,7 @@ struct address_space_operations xfs_address_space_operations = { .readpage = xfs_vm_readpage, .readpages = xfs_vm_readpages, .writepage = xfs_vm_writepage, + .writepages = xfs_vm_writepages, .sync_page = block_sync_page, .releasepage = xfs_vm_releasepage, .invalidatepage = xfs_vm_invalidatepage, diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index 7c9f7598807..97615cc74ef 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c @@ -323,6 +323,17 @@ xfs_file_open( return -error; } +STATIC int +xfs_file_close( + struct file *filp) +{ + vnode_t *vp = vn_from_inode(filp->f_dentry->d_inode); + int error; + + VOP_CLOSE(vp, 0, file_count(filp) > 1 ? L_FALSE : L_TRUE, NULL, error); + return -error; +} + STATIC int xfs_file_release( struct inode *inode, @@ -349,6 +360,8 @@ xfs_file_fsync( if (datasync) flags |= FSYNC_DATA; + if (VN_TRUNC(vp)) + VUNTRUNCATE(vp); VOP_FSYNC(vp, flags, NULL, (xfs_off_t)0, (xfs_off_t)-1, error); return -error; } @@ -578,6 +591,7 @@ const struct file_operations xfs_file_operations = { #endif .mmap = xfs_file_mmap, .open = xfs_file_open, + .flush = xfs_file_close, .release = xfs_file_release, .fsync = xfs_file_fsync, #ifdef HAVE_FOP_OPEN_EXEC @@ -602,6 +616,7 @@ const struct file_operations xfs_invis_file_operations = { #endif .mmap = xfs_file_mmap, .open = xfs_file_open, + .flush = xfs_file_close, .release = xfs_file_release, .fsync = xfs_file_fsync, }; diff --git a/fs/xfs/linux-2.6/xfs_fs_subr.c b/fs/xfs/linux-2.6/xfs_fs_subr.c index 575f2a790f3..f0c56daf4d6 100644 --- a/fs/xfs/linux-2.6/xfs_fs_subr.c +++ b/fs/xfs/linux-2.6/xfs_fs_subr.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. + * Copyright (c) 2000-2002,2005-2006 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -15,40 +15,12 @@ * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - #include "xfs.h" -/* - * Stub for no-op vnode operations that return error status. - */ -int -fs_noerr(void) -{ - return 0; -} +int fs_noerr(void) { return 0; } +int fs_nosys(void) { return ENOSYS; } +void fs_noval(void) { return; } -/* - * Operation unsupported under this file system. - */ -int -fs_nosys(void) -{ - return ENOSYS; -} - -/* - * Stub for inactive, strategy, and read/write lock/unlock. Does nothing. - */ -/* ARGSUSED */ -void -fs_noval(void) -{ -} - -/* - * vnode pcache layer for vnode_tosspages. - * 'last' parameter unused but left in for IRIX compatibility - */ void fs_tosspages( bhv_desc_t *bdp, @@ -63,11 +35,6 @@ fs_tosspages( truncate_inode_pages(ip->i_mapping, first); } - -/* - * vnode pcache layer for vnode_flushinval_pages. - * 'last' parameter unused but left in for IRIX compatibility - */ void fs_flushinval_pages( bhv_desc_t *bdp, @@ -79,16 +46,13 @@ fs_flushinval_pages( struct inode *ip = vn_to_inode(vp); if (VN_CACHED(vp)) { + if (VN_TRUNC(vp)) + VUNTRUNCATE(vp); filemap_write_and_wait(ip->i_mapping); - truncate_inode_pages(ip->i_mapping, first); } } -/* - * vnode pcache layer for vnode_flush_pages. - * 'last' parameter unused but left in for IRIX compatibility - */ int fs_flush_pages( bhv_desc_t *bdp, @@ -100,12 +64,13 @@ fs_flush_pages( vnode_t *vp = BHV_TO_VNODE(bdp); struct inode *ip = vn_to_inode(vp); - if (VN_CACHED(vp)) { + if (VN_DIRTY(vp)) { + if (VN_TRUNC(vp)) + VUNTRUNCATE(vp); filemap_fdatawrite(ip->i_mapping); if (flags & XFS_B_ASYNC) return 0; filemap_fdatawait(ip->i_mapping); } - return 0; } diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h index a64b7db6700..569a4e7b5cc 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.h +++ b/fs/xfs/linux-2.6/xfs_vnode.h @@ -56,12 +56,18 @@ typedef xfs_ino_t vnumber_t; typedef struct dentry vname_t; typedef bhv_head_t vn_bhv_head_t; +typedef enum vflags { + VMODIFIED = 0x08, /* XFS inode state possibly differs */ + /* to the Linux inode state. */ + VTRUNCATED = 0x40, /* truncated down so flush-on-close */ +} vflags_t; + /* * MP locking protocols: * v_flag, v_vfsp VN_LOCK/VN_UNLOCK */ typedef struct vnode { - __u32 v_flag; /* vnode flags (see below) */ + vflags_t v_flag; /* vnode flags (see above) */ struct vfs *v_vfsp; /* ptr to containing VFS */ vnumber_t v_number; /* in-core vnode number */ vn_bhv_head_t v_bh; /* behavior head */ @@ -125,12 +131,6 @@ static inline struct inode *vn_to_inode(struct vnode *vnode) return &vnode->v_inode; } -/* - * Vnode flags. - */ -#define VMODIFIED 0x8 /* XFS inode state possibly differs */ - /* to the Linux inode state. */ - /* * Values for the VOP_RWLOCK and VOP_RWUNLOCK flags parameter. */ @@ -162,8 +162,10 @@ typedef enum vchange { VCHANGE_FLAGS_IOEXCL_COUNT = 4 } vchange_t; +typedef enum { L_FALSE, L_TRUE } lastclose_t; typedef int (*vop_open_t)(bhv_desc_t *, struct cred *); +typedef int (*vop_close_t)(bhv_desc_t *, int, lastclose_t, struct cred *); typedef ssize_t (*vop_read_t)(bhv_desc_t *, struct kiocb *, const struct iovec *, unsigned int, loff_t *, int, struct cred *); @@ -234,6 +236,7 @@ typedef int (*vop_iflush_t)(bhv_desc_t *, int); typedef struct vnodeops { bhv_position_t vn_position; /* position within behavior chain */ vop_open_t vop_open; + vop_close_t vop_close; vop_read_t vop_read; vop_write_t vop_write; vop_sendfile_t vop_sendfile; @@ -278,6 +281,10 @@ typedef struct vnodeops { */ #define _VOP_(op, vp) (*((vnodeops_t *)(vp)->v_fops)->op) +#define VOP_OPEN(vp, cr, rv) \ + rv = _VOP_(vop_open, vp)((vp)->v_fbhv, cr) +#define VOP_CLOSE(vp, f, last, cr, rv) \ + rv = _VOP_(vop_close, vp)((vp)->v_fbhv, f, last, cr) #define VOP_READ(vp,file,iov,segs,offset,ioflags,cr,rv) \ rv = _VOP_(vop_read, vp)((vp)->v_fbhv,file,iov,segs,offset,ioflags,cr) #define VOP_WRITE(vp,file,iov,segs,offset,ioflags,cr,rv) \ @@ -290,8 +297,6 @@ typedef struct vnodeops { rv = _VOP_(vop_splice_write, vp)((vp)->v_fbhv,f,o,pipe,cnt,fl,iofl,cr) #define VOP_BMAP(vp,of,sz,rw,b,n,rv) \ rv = _VOP_(vop_bmap, vp)((vp)->v_fbhv,of,sz,rw,b,n) -#define VOP_OPEN(vp, cr, rv) \ - rv = _VOP_(vop_open, vp)((vp)->v_fbhv, cr) #define VOP_GETATTR(vp, vap, f, cr, rv) \ rv = _VOP_(vop_getattr, vp)((vp)->v_fbhv, vap, f, cr) #define VOP_SETATTR(vp, vap, f, cr, rv) \ @@ -556,8 +561,6 @@ static inline struct vnode *vn_grab(struct vnode *vp) */ #define VN_LOCK(vp) mutex_spinlock(&(vp)->v_lock) #define VN_UNLOCK(vp, s) mutex_spinunlock(&(vp)->v_lock, s) -#define VN_FLAGSET(vp,b) vn_flagset(vp,b) -#define VN_FLAGCLR(vp,b) vn_flagclr(vp,b) static __inline__ void vn_flagset(struct vnode *vp, uint flag) { @@ -566,13 +569,22 @@ static __inline__ void vn_flagset(struct vnode *vp, uint flag) spin_unlock(&vp->v_lock); } -static __inline__ void vn_flagclr(struct vnode *vp, uint flag) +static __inline__ uint vn_flagclr(struct vnode *vp, uint flag) { + uint cleared; + spin_lock(&vp->v_lock); + cleared = (vp->v_flag & flag); vp->v_flag &= ~flag; spin_unlock(&vp->v_lock); + return cleared; } +#define VMODIFY(vp) vn_flagset(vp, VMODIFIED) +#define VUNMODIFY(vp) vn_flagclr(vp, VMODIFIED) +#define VTRUNCATE(vp) vn_flagset(vp, VTRUNCATED) +#define VUNTRUNCATE(vp) vn_flagclr(vp, VTRUNCATED) + /* * Dealing with bad inodes */ @@ -612,8 +624,7 @@ static inline void vn_atime_to_time_t(struct vnode *vp, time_t *tt) #define VN_CACHED(vp) (vn_to_inode(vp)->i_mapping->nrpages) #define VN_DIRTY(vp) mapping_tagged(vn_to_inode(vp)->i_mapping, \ PAGECACHE_TAG_DIRTY) -#define VMODIFY(vp) VN_FLAGSET(vp, VMODIFIED) -#define VUNMODIFY(vp) VN_FLAGCLR(vp, VMODIFIED) +#define VN_TRUNC(vp) ((vp)->v_flag & VTRUNCATED) /* * Flags to VOP_SETATTR/VOP_GETATTR. diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index cb36a56392e..35906bae92e 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -16,8 +16,6 @@ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include - #include "xfs.h" #include "xfs_fs.h" #include "xfs_types.h" @@ -58,32 +56,14 @@ #include "xfs_log_priv.h" #include "xfs_mac.h" - -/* - * The maximum pathlen is 1024 bytes. Since the minimum file system - * blocksize is 512 bytes, we can get a max of 2 extents back from - * bmapi. - */ -#define SYMLINK_MAPS 2 - -/* - * For xfs, we check that the file isn't too big to be opened by this kernel. - * No other open action is required for regular files. Devices are handled - * through the specfs file system, pipes through fifofs. Device and - * fifo vnodes are "wrapped" by specfs and fifofs vnodes, respectively, - * when a new vnode is first looked up or created. - */ STATIC int xfs_open( bhv_desc_t *bdp, cred_t *credp) { int mode; - vnode_t *vp; - xfs_inode_t *ip; - - vp = BHV_TO_VNODE(bdp); - ip = XFS_BHVTOI(bdp); + vnode_t *vp = BHV_TO_VNODE(bdp); + xfs_inode_t *ip = XFS_BHVTOI(bdp); if (XFS_FORCED_SHUTDOWN(ip->i_mount)) return XFS_ERROR(EIO); @@ -101,6 +81,36 @@ xfs_open( return 0; } +STATIC int +xfs_close( + bhv_desc_t *bdp, + int flags, + lastclose_t lastclose, + cred_t *credp) +{ + vnode_t *vp = BHV_TO_VNODE(bdp); + xfs_inode_t *ip = XFS_BHVTOI(bdp); + int error = 0; + + if (XFS_FORCED_SHUTDOWN(ip->i_mount)) + return XFS_ERROR(EIO); + + if (lastclose != L_TRUE || !VN_ISREG(vp)) + return 0; + + /* + * If we previously truncated this file and removed old data in + * the process, we want to initiate "early" writeout on the last + * close. This is an attempt to combat the notorious NULL files + * problem which is particularly noticable from a truncate down, + * buffered (re-)write (delalloc), followed by a crash. What we + * are effectively doing here is significantly reducing the time + * window where we'd otherwise be exposed to that problem. + */ + if (VUNTRUNCATE(vp) && VN_DIRTY(vp) && ip->i_delayed_blks > 0) + VOP_FLUSH_PAGES(vp, 0, -1, XFS_B_ASYNC, FI_NONE, error); + return error; +} /* * xfs_getattr @@ -665,9 +675,17 @@ xfs_setattr( ((ip->i_d.di_nlink != 0 || !(mp->m_flags & XFS_MOUNT_WSYNC)) ? 1 : 0)); - if (code) { + if (code) goto abort_return; - } + /* + * Truncated "down", so we're removing references + * to old data here - if we now delay flushing for + * a long time, we expose ourselves unduly to the + * notorious NULL files problem. So, we mark this + * vnode and flush it when the file is closed, and + * do not wait the usual (long) time for writeout. + */ + VTRUNCATE(vp); } /* * Have to do this even if the file's size doesn't change. @@ -936,6 +954,13 @@ xfs_access( } +/* + * The maximum pathlen is 1024 bytes. Since the minimum file system + * blocksize is 512 bytes, we can get a max of 2 extents back from + * bmapi. + */ +#define SYMLINK_MAPS 2 + /* * xfs_readlink * @@ -1470,9 +1495,6 @@ xfs_inactive_symlink_local( return 0; } -/* - * - */ STATIC int xfs_inactive_attrs( xfs_inode_t *ip, @@ -1531,10 +1553,10 @@ xfs_release( vp = BHV_TO_VNODE(bdp); ip = XFS_BHVTOI(bdp); + mp = ip->i_mount; - if (!VN_ISREG(vp) || (ip->i_d.di_mode == 0)) { + if (!VN_ISREG(vp) || (ip->i_d.di_mode == 0)) return 0; - } /* If this is a read-only mount, don't do this (would generate I/O) */ if (vp->v_vfsp->vfs_flag & VFS_RDONLY) @@ -1546,8 +1568,6 @@ xfs_release( return 0; #endif - mp = ip->i_mount; - if (ip->i_d.di_nlink != 0) { if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) && ((ip->i_d.di_size > 0) || (VN_CACHED(vp) > 0 || @@ -3745,7 +3765,6 @@ xfs_inode_flush( return error; } - int xfs_set_dmattrs ( bhv_desc_t *bdp, @@ -3786,10 +3805,6 @@ xfs_set_dmattrs ( return error; } - -/* - * xfs_reclaim - */ STATIC int xfs_reclaim( bhv_desc_t *bdp) @@ -4645,6 +4660,7 @@ xfs_change_file_space( vnodeops_t xfs_vnodeops = { BHV_IDENTITY_INIT(VN_BHV_XFS,VNODE_POSITION_XFS), .vop_open = xfs_open, + .vop_close = xfs_close, .vop_read = xfs_read, #ifdef HAVE_SENDFILE .vop_sendfile = xfs_sendfile, -- cgit v1.2.3 From ad723875ac238137207754d2633dd9c261c71558 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Fri, 9 Jun 2006 15:29:12 +1000 Subject: [XFS] Fix a typo in a header file comment. SGI-PV: 904196 SGI-Modid: xfs-linux-melb:xfs-kern:26101a Signed-off-by: Nathan Scott --- fs/xfs/linux-2.6/xfs_aops.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/xfs/linux-2.6/xfs_aops.h b/fs/xfs/linux-2.6/xfs_aops.h index 41c7d2da638..62c1d49025f 100644 --- a/fs/xfs/linux-2.6/xfs_aops.h +++ b/fs/xfs/linux-2.6/xfs_aops.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005 Silicon Graphics, Inc. + * Copyright (c) 2005-2006 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -43,4 +43,4 @@ typedef struct xfs_ioend { extern struct address_space_operations xfs_address_space_operations; extern int xfs_get_blocks(struct inode *, sector_t, struct buffer_head *, int); -#endif /* __XFS_IOPS_H__ */ +#endif /* __XFS_AOPS_H__ */ -- cgit v1.2.3 From 9c48876a05b6fbe41f1933fae3529c268d78cad0 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Fri, 9 Jun 2006 15:29:22 +1000 Subject: [XFS] Remove dead code from come bulkstat paths. SGI-PV: 904196 SGI-Modid: xfs-linux-melb:xfs-kern:26102a Signed-off-by: Nathan Scott --- fs/xfs/quota/xfs_qm.c | 4 +--- fs/xfs/xfs_itable.c | 16 ---------------- fs/xfs/xfs_itable.h | 1 - 3 files changed, 1 insertion(+), 20 deletions(-) diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c index 492840b2a35..00fb54d4899 100644 --- a/fs/xfs/quota/xfs_qm.c +++ b/fs/xfs/quota/xfs_qm.c @@ -1905,9 +1905,7 @@ xfs_qm_quotacheck( */ if ((error = xfs_bulkstat(mp, &lastino, &count, xfs_qm_dqusage_adjust, NULL, - structsz, NULL, - BULKSTAT_FG_IGET|BULKSTAT_FG_VFSLOCKED, - &done))) + structsz, NULL, BULKSTAT_FG_IGET, &done))) break; } while (! done); diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c index 94068d014f2..864b43d6584 100644 --- a/fs/xfs/xfs_itable.c +++ b/fs/xfs/xfs_itable.c @@ -41,11 +41,6 @@ #include "xfs_error.h" #include "xfs_btree.h" -#ifndef HAVE_USERACC -#define useracc(ubuffer, size, flags, foo) (0) -#define unuseracc(ubuffer, size, flags) -#endif - STATIC int xfs_bulkstat_one_iget( xfs_mount_t *mp, /* mount point for filesystem */ @@ -335,15 +330,6 @@ xfs_bulkstat( (XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_inodelog); nimask = ~(nicluster - 1); nbcluster = nicluster >> mp->m_sb.sb_inopblog; - /* - * Lock down the user's buffer. If a buffer was not sent, as in the case - * disk quota code calls here, we skip this. - */ - if (ubuffer && - (error = useracc(ubuffer, ubcount * statstruct_size, - (B_READ|B_PHYS), NULL))) { - return error; - } /* * Allocate a page-sized buffer for inode btree records. * We could try allocating something smaller, but for normal @@ -650,8 +636,6 @@ xfs_bulkstat( * Done, we're either out of filesystem or space to put the data. */ kmem_free(irbuf, NBPC); - if (ubuffer) - unuseracc(ubuffer, ubcount * statstruct_size, (B_READ|B_PHYS)); *ubcountp = ubelem; if (agno >= mp->m_sb.sb_agcount) { /* diff --git a/fs/xfs/xfs_itable.h b/fs/xfs/xfs_itable.h index 11eb4e1b18c..be5f12e07d2 100644 --- a/fs/xfs/xfs_itable.h +++ b/fs/xfs/xfs_itable.h @@ -45,7 +45,6 @@ typedef int (*bulkstat_one_pf)(struct xfs_mount *mp, */ #define BULKSTAT_FG_IGET 0x1 /* Go through the buffer cache */ #define BULKSTAT_FG_QUICK 0x2 /* No iget, walk the dinode cluster */ -#define BULKSTAT_FG_VFSLOCKED 0x4 /* Already have vfs lock */ /* * Return stat information in bulk (by-inode) for the filesystem. -- cgit v1.2.3 From b65745205fc00d8c7722ec74e9bd955f3861c7e2 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Fri, 9 Jun 2006 15:29:40 +1000 Subject: [XFS] Portability changes: remove prdev, stick to one diagnostic interface. SGI-PV: 953338 SGI-Modid: xfs-linux-melb:xfs-kern:26103a Signed-off-by: Nathan Scott --- fs/xfs/support/debug.c | 4 ++-- fs/xfs/support/debug.h | 3 --- fs/xfs/xfs_buf_item.c | 6 ++--- fs/xfs/xfs_inode.c | 5 ++-- fs/xfs/xfs_log_recover.c | 18 +++++++-------- fs/xfs/xfs_mount.c | 5 ++-- fs/xfs/xfs_rtalloc.c | 12 +++++----- fs/xfs/xfs_trans_buf.c | 4 ++-- fs/xfs/xfs_trans_item.c | 2 +- fs/xfs/xfs_vfsops.c | 59 +++++++++++++++++++++++++++++++----------------- 10 files changed, 67 insertions(+), 51 deletions(-) diff --git a/fs/xfs/support/debug.c b/fs/xfs/support/debug.c index b08b3d9345b..36fbeccdc72 100644 --- a/fs/xfs/support/debug.c +++ b/fs/xfs/support/debug.c @@ -47,7 +47,7 @@ cmn_err(register int level, char *fmt, ...) va_start(ap, fmt); if (*fmt == '!') fp++; len = vsprintf(message, fp, ap); - if (message[len-1] != '\n') + if (level != CE_DEBUG && message[len-1] != '\n') strcat(message, "\n"); printk("%s%s", err_level[level], message); va_end(ap); @@ -68,7 +68,7 @@ icmn_err(register int level, char *fmt, va_list ap) level = XFS_MAX_ERR_LEVEL; spin_lock_irqsave(&xfs_err_lock,flags); len = vsprintf(message, fmt, ap); - if (message[len-1] != '\n') + if (level != CE_DEBUG && message[len-1] != '\n') strcat(message, "\n"); spin_unlock_irqrestore(&xfs_err_lock,flags); printk("%s%s", err_level[level], message); diff --git a/fs/xfs/support/debug.h b/fs/xfs/support/debug.h index e3bf58112e7..4f54dca662a 100644 --- a/fs/xfs/support/debug.h +++ b/fs/xfs/support/debug.h @@ -33,9 +33,6 @@ extern void cmn_err(int, char *, ...) __attribute__ ((format (printf, 2, 3))); extern void assfail(char *expr, char *f, int l); -#define prdev(fmt,targ,args...) \ - printk("Device %s - " fmt "\n", XFS_BUFTARG_NAME(targ), ## args) - #define ASSERT_ALWAYS(expr) \ (unlikely((expr) != 0) ? (void)0 : assfail(#expr, __FILE__, __LINE__)) diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index 59013e1f16e..290912cbff6 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c @@ -1030,9 +1030,9 @@ xfs_buf_iodone_callbacks( if ((XFS_BUF_TARGET(bp) != lasttarg) || (time_after(jiffies, (lasttime + 5*HZ)))) { lasttime = jiffies; - prdev("XFS write error in file system meta-data " - "block 0x%llx in %s", - XFS_BUF_TARGET(bp), + cmn_err(CE_ALERT, "Device %s, XFS metadata write error" + " block 0x%llx in %s", + XFS_BUFTARG_NAME(XFS_BUF_TARGET(bp)), (__uint64_t)XFS_BUF_ADDR(bp), mp->m_fsname); } lasttarg = XFS_BUF_TARGET(bp); diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index b30bffa99ed..50119a00885 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -352,8 +352,9 @@ xfs_itobp( if (unlikely(XFS_TEST_ERROR(!di_ok, mp, XFS_ERRTAG_ITOBP_INOTOBP, XFS_RANDOM_ITOBP_INOTOBP))) { #ifdef DEBUG - prdev("bad inode magic/vsn daddr %lld #%d (magic=%x)", - mp->m_ddev_targp, + cmn_err(CE_ALERT, "Device %s - bad inode magic/vsn " + "daddr %lld #%d (magic=%x)", + XFS_BUFTARG_NAME(mp->m_ddev_targp), (unsigned long long)imap.im_blkno, i, INT_GET(dip->di_core.di_magic, ARCH_CONVERT)); #endif diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index a17218e8153..f952f9dbf74 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -193,14 +193,14 @@ xlog_header_check_dump( { int b; - printk("%s: SB : uuid = ", __FUNCTION__); + cmn_err(CE_DEBUG, "%s: SB : uuid = ", __FUNCTION__); for (b = 0; b < 16; b++) - printk("%02x",((unsigned char *)&mp->m_sb.sb_uuid)[b]); - printk(", fmt = %d\n", XLOG_FMT); - printk(" log : uuid = "); + cmn_err(CE_DEBUG, "%02x", ((uchar_t *)&mp->m_sb.sb_uuid)[b]); + cmn_err(CE_DEBUG, ", fmt = %d\n", XLOG_FMT); + cmn_err(CE_DEBUG, " log : uuid = "); for (b = 0; b < 16; b++) - printk("%02x",((unsigned char *)&head->h_fs_uuid)[b]); - printk(", fmt = %d\n", INT_GET(head->h_fmt, ARCH_CONVERT)); + cmn_err(CE_DEBUG, "%02x",((uchar_t *)&head->h_fs_uuid)[b]); + cmn_err(CE_DEBUG, ", fmt = %d\n", INT_GET(head->h_fmt, ARCH_CONVERT)); } #else #define xlog_header_check_dump(mp, head) @@ -3444,13 +3444,13 @@ xlog_unpack_data_checksum( if (rhead->h_chksum || ((log->l_flags & XLOG_CHKSUM_MISMATCH) == 0)) { cmn_err(CE_DEBUG, - "XFS: LogR chksum mismatch: was (0x%x) is (0x%x)", + "XFS: LogR chksum mismatch: was (0x%x) is (0x%x)\n", INT_GET(rhead->h_chksum, ARCH_CONVERT), chksum); cmn_err(CE_DEBUG, "XFS: Disregard message if filesystem was created with non-DEBUG kernel"); if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb)) { cmn_err(CE_DEBUG, - "XFS: LogR this is a LogV2 filesystem"); + "XFS: LogR this is a LogV2 filesystem\n"); } log->l_flags |= XLOG_CHKSUM_MISMATCH; } @@ -3999,7 +3999,7 @@ xlog_recover_finish( log->l_flags &= ~XLOG_RECOVERY_NEEDED; } else { cmn_err(CE_DEBUG, - "!Ending clean XFS mount for filesystem: %s", + "!Ending clean XFS mount for filesystem: %s\n", log->l_mp->m_fsname); } return 0; diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 4b7be49cc4d..9378408a69d 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -1006,8 +1006,9 @@ xfs_mountfs( if (unlikely((rip->i_d.di_mode & S_IFMT) != S_IFDIR)) { cmn_err(CE_WARN, "XFS: corrupted root inode"); - prdev("Root inode %llu is not a directory", - mp->m_ddev_targp, (unsigned long long)rip->i_ino); + cmn_err(CE_WARN, "Device %s - root %llu is not a directory", + XFS_BUFTARG_NAME(mp->m_ddev_targp), + (unsigned long long)rip->i_ino); xfs_iunlock(rip, XFS_ILOCK_EXCL); XFS_ERROR_REPORT("xfs_mountfs_int(2)", XFS_ERRLEVEL_LOW, mp); diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index f5944c8b378..af290cf37ac 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -2404,10 +2404,10 @@ xfs_rtprint_range( { xfs_extlen_t i; /* block number in the extent */ - printk("%Ld: ", (long long)start); + cmn_err(CE_DEBUG, "%Ld: ", (long long)start); for (i = 0; i < len; i++) - printk("%d", xfs_rtcheck_bit(mp, tp, start + i, 1)); - printk("\n"); + cmn_err(CE_DEBUG, "%d", xfs_rtcheck_bit(mp, tp, start + i, 1)); + cmn_err(CE_DEBUG, "\n"); } /* @@ -2431,17 +2431,17 @@ xfs_rtprint_summary( (void)xfs_rtget_summary(mp, tp, l, i, &sumbp, &sb, &c); if (c) { if (!p) { - printk("%Ld-%Ld:", 1LL << l, + cmn_err(CE_DEBUG, "%Ld-%Ld:", 1LL << l, XFS_RTMIN((1LL << l) + ((1LL << l) - 1LL), mp->m_sb.sb_rextents)); p = 1; } - printk(" %Ld:%d", (long long)i, c); + cmn_err(CE_DEBUG, " %Ld:%d", (long long)i, c); } } if (p) - printk("\n"); + cmn_err(CE_DEBUG, "\n"); } if (sumbp) xfs_trans_brelse(tp, sumbp); diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c index 42291364570..8cedd1583bc 100644 --- a/fs/xfs/xfs_trans_buf.c +++ b/fs/xfs/xfs_trans_buf.c @@ -320,7 +320,7 @@ xfs_trans_read_buf( if (xfs_error_target == target) { if (((xfs_req_num++) % xfs_error_mod) == 0) { xfs_buf_relse(bp); - printk("Returning error!\n"); + cmn_err(CE_DEBUG, "Returning error!\n"); return XFS_ERROR(EIO); } } @@ -425,7 +425,7 @@ xfs_trans_read_buf( xfs_force_shutdown(tp->t_mountp, SHUTDOWN_META_IO_ERROR); xfs_buf_relse(bp); - printk("Returning error in trans!\n"); + cmn_err(CE_DEBUG, "Returning trans error!\n"); return XFS_ERROR(EIO); } } diff --git a/fs/xfs/xfs_trans_item.c b/fs/xfs/xfs_trans_item.c index 1117d600d74..2912aac07c7 100644 --- a/fs/xfs/xfs_trans_item.c +++ b/fs/xfs/xfs_trans_item.c @@ -493,7 +493,7 @@ xfs_trans_add_busy(xfs_trans_t *tp, xfs_agnumber_t ag, xfs_extlen_t idx) break; } else { /* out-of-order vacancy */ - printk("OOO vacancy lbcp 0x%p\n", lbcp); + cmn_err(CE_DEBUG, "OOO vacancy lbcp 0x%p\n", lbcp); ASSERT(0); } } diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c index 36ea1b2094f..ec85a2e24b5 100644 --- a/fs/xfs/xfs_vfsops.c +++ b/fs/xfs/xfs_vfsops.c @@ -1708,42 +1708,48 @@ xfs_parseargs( if (!strcmp(this_char, MNTOPT_LOGBUFS)) { if (!value || !*value) { - printk("XFS: %s option requires an argument\n", + cmn_err(CE_WARN, + "XFS: %s option requires an argument", this_char); return EINVAL; } args->logbufs = simple_strtoul(value, &eov, 10); } else if (!strcmp(this_char, MNTOPT_LOGBSIZE)) { if (!value || !*value) { - printk("XFS: %s option requires an argument\n", + cmn_err(CE_WARN, + "XFS: %s option requires an argument", this_char); return EINVAL; } args->logbufsize = suffix_strtoul(value, &eov, 10); } else if (!strcmp(this_char, MNTOPT_LOGDEV)) { if (!value || !*value) { - printk("XFS: %s option requires an argument\n", + cmn_err(CE_WARN, + "XFS: %s option requires an argument", this_char); return EINVAL; } strncpy(args->logname, value, MAXNAMELEN); } else if (!strcmp(this_char, MNTOPT_MTPT)) { if (!value || !*value) { - printk("XFS: %s option requires an argument\n", + cmn_err(CE_WARN, + "XFS: %s option requires an argument", this_char); return EINVAL; } strncpy(args->mtpt, value, MAXNAMELEN); } else if (!strcmp(this_char, MNTOPT_RTDEV)) { if (!value || !*value) { - printk("XFS: %s option requires an argument\n", + cmn_err(CE_WARN, + "XFS: %s option requires an argument", this_char); return EINVAL; } strncpy(args->rtname, value, MAXNAMELEN); } else if (!strcmp(this_char, MNTOPT_BIOSIZE)) { if (!value || !*value) { - printk("XFS: %s option requires an argument\n", + cmn_err(CE_WARN, + "XFS: %s option requires an argument", this_char); return EINVAL; } @@ -1752,7 +1758,8 @@ xfs_parseargs( args->iosizelog = (uint8_t) iosize; } else if (!strcmp(this_char, MNTOPT_ALLOCSIZE)) { if (!value || !*value) { - printk("XFS: %s option requires an argument\n", + cmn_err(CE_WARN, + "XFS: %s option requires an argument", this_char); return EINVAL; } @@ -1761,7 +1768,8 @@ xfs_parseargs( args->iosizelog = ffs(iosize) - 1; } else if (!strcmp(this_char, MNTOPT_IHASHSIZE)) { if (!value || !*value) { - printk("XFS: %s option requires an argument\n", + cmn_err(CE_WARN, + "XFS: %s option requires an argument", this_char); return EINVAL; } @@ -1782,7 +1790,8 @@ xfs_parseargs( } else if (!strcmp(this_char, MNTOPT_INO64)) { args->flags |= XFSMNT_INO64; #if !XFS_BIG_INUMS - printk("XFS: %s option not allowed on this system\n", + cmn_err(CE_WARN, + "XFS: %s option not allowed on this system", this_char); return EINVAL; #endif @@ -1792,14 +1801,16 @@ xfs_parseargs( args->flags |= XFSMNT_SWALLOC; } else if (!strcmp(this_char, MNTOPT_SUNIT)) { if (!value || !*value) { - printk("XFS: %s option requires an argument\n", + cmn_err(CE_WARN, + "XFS: %s option requires an argument", this_char); return EINVAL; } dsunit = simple_strtoul(value, &eov, 10); } else if (!strcmp(this_char, MNTOPT_SWIDTH)) { if (!value || !*value) { - printk("XFS: %s option requires an argument\n", + cmn_err(CE_WARN, + "XFS: %s option requires an argument", this_char); return EINVAL; } @@ -1807,7 +1818,8 @@ xfs_parseargs( } else if (!strcmp(this_char, MNTOPT_64BITINODE)) { args->flags &= ~XFSMNT_32BITINODES; #if !XFS_BIG_INUMS - printk("XFS: %s option not allowed on this system\n", + cmn_err(CE_WARN, + "XFS: %s option not allowed on this system", this_char); return EINVAL; #endif @@ -1831,36 +1843,41 @@ xfs_parseargs( args->flags &= ~XFSMNT_ATTR2; } else if (!strcmp(this_char, "osyncisdsync")) { /* no-op, this is now the default */ -printk("XFS: osyncisdsync is now the default, option is deprecated.\n"); + cmn_err(CE_WARN, + "XFS: osyncisdsync is now the default, option is deprecated."); } else if (!strcmp(this_char, "irixsgid")) { -printk("XFS: irixsgid is now a sysctl(2) variable, option is deprecated.\n"); + cmn_err(CE_WARN, + "XFS: irixsgid is now a sysctl(2) variable, option is deprecated."); } else { - printk("XFS: unknown mount option [%s].\n", this_char); + cmn_err(CE_WARN, + "XFS: unknown mount option [%s].", this_char); return EINVAL; } } if (args->flags & XFSMNT_NORECOVERY) { if ((vfsp->vfs_flag & VFS_RDONLY) == 0) { - printk("XFS: no-recovery mounts must be read-only.\n"); + cmn_err(CE_WARN, + "XFS: no-recovery mounts must be read-only."); return EINVAL; } } if ((args->flags & XFSMNT_NOALIGN) && (dsunit || dswidth)) { - printk( - "XFS: sunit and swidth options incompatible with the noalign option\n"); + cmn_err(CE_WARN, + "XFS: sunit and swidth options incompatible with the noalign option"); return EINVAL; } if ((dsunit && !dswidth) || (!dsunit && dswidth)) { - printk("XFS: sunit and swidth must be specified together\n"); + cmn_err(CE_WARN, + "XFS: sunit and swidth must be specified together"); return EINVAL; } if (dsunit && (dswidth % dsunit != 0)) { - printk( - "XFS: stripe width (%d) must be a multiple of the stripe unit (%d)\n", + cmn_err(CE_WARN, + "XFS: stripe width (%d) must be a multiple of the stripe unit (%d)", dswidth, dsunit); return EINVAL; } -- cgit v1.2.3 From 932f2c323196c214e645d5a572a1d7b562c0f93f Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Fri, 9 Jun 2006 15:29:58 +1000 Subject: [XFS] statvfs component of directory/project quota support, code originally by Glen. SGI-PV: 932952 SGI-Modid: xfs-linux-melb:xfs-kern:26105a Signed-off-by: Nathan Scott --- fs/xfs/quota/xfs_qm_bhv.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/fs/xfs/quota/xfs_qm_bhv.c b/fs/xfs/quota/xfs_qm_bhv.c index 6838b36d95a..181dd90b29c 100644 --- a/fs/xfs/quota/xfs_qm_bhv.c +++ b/fs/xfs/quota/xfs_qm_bhv.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2005 Silicon Graphics, Inc. + * Copyright (c) 2000-2006 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -185,6 +185,61 @@ xfs_qm_mount( return error; } +/* + * Directory tree accounting is implemented using project quotas, where + * the project identifier is inherited from parent directories. + * A statvfs (df, etc.) of a directory that is using project quota should + * return a statvfs of the project, not the entire filesystem. + * This makes such trees appear as if they are filesystems in themselves. + */ +STATIC int +xfs_qm_statvfs( + struct bhv_desc *bhv, + xfs_statfs_t *statp, + struct vnode *vnode) +{ + xfs_mount_t *mp; + xfs_inode_t *ip; + xfs_dquot_t *dqp; + xfs_disk_dquot_t *dp; + __uint64_t limit; + int error; + + error = PVFS_STATVFS(BHV_NEXT(bhv), statp, vnode); + if (error || !vnode) + return error; + + mp = XFS_BHVTOM(bhv); + ip = xfs_vtoi(vnode); + + if (!(ip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)) + return 0; + if (!(mp->m_qflags & XFS_PQUOTA_ACCT)) + return 0; + if (!(mp->m_qflags & XFS_OQUOTA_ENFD)) + return 0; + + if (xfs_qm_dqget(mp, NULL, ip->i_d.di_projid, XFS_DQ_PROJ, 0, &dqp)) + return 0; + dp = &dqp->q_core; + + limit = dp->d_blk_softlimit ? dp->d_blk_softlimit : dp->d_blk_hardlimit; + if (limit && statp->f_blocks > limit) { + statp->f_blocks = limit; + statp->f_bfree = (statp->f_blocks > dp->d_bcount) ? + (statp->f_blocks - dp->d_bcount) : 0; + } + limit = dp->d_ino_softlimit ? dp->d_ino_softlimit : dp->d_ino_hardlimit; + if (limit && statp->f_files > limit) { + statp->f_files = limit; + statp->f_ffree = (statp->f_files > dp->d_icount) ? + (statp->f_ffree - dp->d_icount) : 0; + } + + xfs_qm_dqput(dqp); + return 0; +} + STATIC int xfs_qm_syncall( struct bhv_desc *bhv, @@ -351,6 +406,7 @@ struct bhv_vfsops xfs_qmops = { { .vfs_parseargs = xfs_qm_parseargs, .vfs_showargs = xfs_qm_showargs, .vfs_mount = xfs_qm_mount, + .vfs_statvfs = xfs_qm_statvfs, .vfs_sync = xfs_qm_syncall, .vfs_quotactl = xfs_qm_quotactl, }, }; -- cgit v1.2.3 From b83bd1388133e914c38bd31d69bc90143e6ab10c Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Fri, 9 Jun 2006 16:48:30 +1000 Subject: [XFS] Resolve a namespace collision on vfs/vfsops for FreeBSD porters. SGI-PV: 9533338 SGI-Modid: xfs-linux-melb:xfs-kern:26106a Signed-off-by: Nathan Scott --- fs/xfs/linux-2.6/xfs_export.c | 6 +- fs/xfs/linux-2.6/xfs_super.c | 141 ++++++++++++++++------------------------- fs/xfs/linux-2.6/xfs_vfs.c | 28 ++++---- fs/xfs/linux-2.6/xfs_vfs.h | 126 ++++++++++++++++++------------------ fs/xfs/linux-2.6/xfs_vnode.c | 2 +- fs/xfs/linux-2.6/xfs_vnode.h | 4 +- fs/xfs/quota/xfs_qm_bhv.c | 23 +++---- fs/xfs/quota/xfs_qm_syscalls.c | 2 +- fs/xfs/xfs_dmapi.h | 2 +- fs/xfs/xfs_fsops.c | 2 +- fs/xfs/xfs_iget.c | 2 +- fs/xfs/xfs_inode.c | 4 +- fs/xfs/xfs_inode.h | 1 - fs/xfs/xfs_iocore.c | 2 +- fs/xfs/xfs_log.c | 7 +- fs/xfs/xfs_mount.c | 8 +-- fs/xfs/xfs_mount.h | 22 +++---- fs/xfs/xfs_quota.h | 2 +- fs/xfs/xfs_vfsops.c | 23 ++++--- 19 files changed, 183 insertions(+), 224 deletions(-) diff --git a/fs/xfs/linux-2.6/xfs_export.c b/fs/xfs/linux-2.6/xfs_export.c index b768ea910bb..b5c579eeb8e 100644 --- a/fs/xfs/linux-2.6/xfs_export.c +++ b/fs/xfs/linux-2.6/xfs_export.c @@ -97,7 +97,7 @@ xfs_fs_encode_fh( int len; int is64 = 0; #if XFS_BIG_INUMS - vfs_t *vfs = vfs_from_sb(inode->i_sb); + bhv_vfs_t *vfs = vfs_from_sb(inode->i_sb); if (!(vfs->vfs_flag & VFS_32BITINODES)) { /* filesystem may contain 64bit inode numbers */ @@ -139,10 +139,10 @@ xfs_fs_get_dentry( vnode_t *vp; struct inode *inode; struct dentry *result; - vfs_t *vfsp = vfs_from_sb(sb); + bhv_vfs_t *vfsp = vfs_from_sb(sb); int error; - VFS_VGET(vfsp, &vp, (fid_t *)data, error); + error = bhv_vfs_vget(vfsp, &vp, (fid_t *)data); if (error || vp == NULL) return ERR_PTR(-ESTALE) ; diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 68f4793e8a1..97dbcb68b25 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -475,13 +475,13 @@ xfs_fs_clear_inode( */ STATIC void xfs_syncd_queue_work( - struct vfs *vfs, + struct bhv_vfs *vfs, void *data, - void (*syncer)(vfs_t *, void *)) + void (*syncer)(bhv_vfs_t *, void *)) { - vfs_sync_work_t *work; + struct bhv_vfs_sync_work *work; - work = kmem_alloc(sizeof(struct vfs_sync_work), KM_SLEEP); + work = kmem_alloc(sizeof(struct bhv_vfs_sync_work), KM_SLEEP); INIT_LIST_HEAD(&work->w_list); work->w_syncer = syncer; work->w_data = data; @@ -500,7 +500,7 @@ xfs_syncd_queue_work( */ STATIC void xfs_flush_inode_work( - vfs_t *vfs, + bhv_vfs_t *vfs, void *inode) { filemap_flush(((struct inode *)inode)->i_mapping); @@ -512,7 +512,7 @@ xfs_flush_inode( xfs_inode_t *ip) { struct inode *inode = vn_to_inode(XFS_ITOV(ip)); - struct vfs *vfs = XFS_MTOVFS(ip->i_mount); + struct bhv_vfs *vfs = XFS_MTOVFS(ip->i_mount); igrab(inode); xfs_syncd_queue_work(vfs, inode, xfs_flush_inode_work); @@ -525,7 +525,7 @@ xfs_flush_inode( */ STATIC void xfs_flush_device_work( - vfs_t *vfs, + bhv_vfs_t *vfs, void *inode) { sync_blockdev(vfs->vfs_super->s_bdev); @@ -537,7 +537,7 @@ xfs_flush_device( xfs_inode_t *ip) { struct inode *inode = vn_to_inode(XFS_ITOV(ip)); - struct vfs *vfs = XFS_MTOVFS(ip->i_mount); + struct bhv_vfs *vfs = XFS_MTOVFS(ip->i_mount); igrab(inode); xfs_syncd_queue_work(vfs, inode, xfs_flush_device_work); @@ -545,16 +545,16 @@ xfs_flush_device( xfs_log_force(ip->i_mount, (xfs_lsn_t)0, XFS_LOG_FORCE|XFS_LOG_SYNC); } -#define SYNCD_FLAGS (SYNC_FSDATA|SYNC_BDFLUSH|SYNC_ATTR|SYNC_REFCACHE) STATIC void vfs_sync_worker( - vfs_t *vfsp, + bhv_vfs_t *vfsp, void *unused) { int error; if (!(vfsp->vfs_flag & VFS_RDONLY)) - VFS_SYNC(vfsp, SYNCD_FLAGS, NULL, error); + error = bhv_vfs_sync(vfsp, SYNC_FSDATA | SYNC_BDFLUSH | \ + SYNC_ATTR | SYNC_REFCACHE, NULL); vfsp->vfs_sync_seq++; wmb(); wake_up(&vfsp->vfs_wait_single_sync_task); @@ -565,8 +565,8 @@ xfssyncd( void *arg) { long timeleft; - vfs_t *vfsp = (vfs_t *) arg; - struct vfs_sync_work *work, *n; + bhv_vfs_t *vfsp = (bhv_vfs_t *) arg; + bhv_vfs_sync_work_t *work, *n; LIST_HEAD (tmp); timeleft = xfs_syncd_centisecs * msecs_to_jiffies(10); @@ -600,7 +600,7 @@ xfssyncd( list_del(&work->w_list); if (work == &vfsp->vfs_sync_work) continue; - kmem_free(work, sizeof(struct vfs_sync_work)); + kmem_free(work, sizeof(struct bhv_vfs_sync_work)); } } @@ -609,7 +609,7 @@ xfssyncd( STATIC int xfs_fs_start_syncd( - vfs_t *vfsp) + bhv_vfs_t *vfsp) { vfsp->vfs_sync_work.w_syncer = vfs_sync_worker; vfsp->vfs_sync_work.w_vfs = vfsp; @@ -621,7 +621,7 @@ xfs_fs_start_syncd( STATIC void xfs_fs_stop_syncd( - vfs_t *vfsp) + bhv_vfs_t *vfsp) { kthread_stop(vfsp->vfs_sync_task); } @@ -630,35 +630,26 @@ STATIC void xfs_fs_put_super( struct super_block *sb) { - vfs_t *vfsp = vfs_from_sb(sb); + bhv_vfs_t *vfsp = vfs_from_sb(sb); int error; xfs_fs_stop_syncd(vfsp); - VFS_SYNC(vfsp, SYNC_ATTR|SYNC_DELWRI, NULL, error); - if (!error) - VFS_UNMOUNT(vfsp, 0, NULL, error); + bhv_vfs_sync(vfsp, SYNC_ATTR | SYNC_DELWRI, NULL); + error = bhv_vfs_unmount(vfsp, 0, NULL); if (error) { - printk("XFS unmount got error %d\n", error); - printk("%s: vfsp/0x%p left dangling!\n", __FUNCTION__, vfsp); - return; + printk("XFS: unmount got error=%d\n", error); + printk("%s: vfs=0x%p left dangling!\n", __FUNCTION__, vfsp); + } else { + vfs_deallocate(vfsp); } - - vfs_deallocate(vfsp); } STATIC void xfs_fs_write_super( struct super_block *sb) { - vfs_t *vfsp = vfs_from_sb(sb); - int error; - - if (sb->s_flags & MS_RDONLY) { - sb->s_dirt = 0; /* paranoia */ - return; - } - /* Push the log and superblock a little */ - VFS_SYNC(vfsp, SYNC_FSDATA, NULL, error); + if (!(sb->s_flags & MS_RDONLY)) + bhv_vfs_sync(vfs_from_sb(sb), SYNC_FSDATA, NULL); sb->s_dirt = 0; } @@ -667,16 +658,16 @@ xfs_fs_sync_super( struct super_block *sb, int wait) { - vfs_t *vfsp = vfs_from_sb(sb); - int error; - int flags = SYNC_FSDATA; + bhv_vfs_t *vfsp = vfs_from_sb(sb); + int error; + int flags; if (unlikely(sb->s_frozen == SB_FREEZE_WRITE)) flags = SYNC_QUIESCE; else flags = SYNC_FSDATA | (wait ? SYNC_WAIT : 0); - VFS_SYNC(vfsp, flags, NULL, error); + error = bhv_vfs_sync(vfsp, flags, NULL); sb->s_dirt = 0; if (unlikely(laptop_mode)) { @@ -706,11 +697,7 @@ xfs_fs_statfs( struct super_block *sb, struct kstatfs *statp) { - vfs_t *vfsp = vfs_from_sb(sb); - int error; - - VFS_STATVFS(vfsp, statp, NULL, error); - return -error; + return -bhv_vfs_statvfs(vfs_from_sb(sb), statp, NULL); } STATIC int @@ -719,13 +706,13 @@ xfs_fs_remount( int *flags, char *options) { - vfs_t *vfsp = vfs_from_sb(sb); + bhv_vfs_t *vfsp = vfs_from_sb(sb); struct xfs_mount_args *args = xfs_args_allocate(sb, 0); int error; - VFS_PARSEARGS(vfsp, options, args, 1, error); + error = bhv_vfs_parseargs(vfsp, options, args, 1); if (!error) - VFS_MNTUPDATE(vfsp, flags, args, error); + error = bhv_vfs_mntupdate(vfsp, flags, args); kmem_free(args, sizeof(*args)); return -error; } @@ -734,7 +721,7 @@ STATIC void xfs_fs_lockfs( struct super_block *sb) { - VFS_FREEZE(vfs_from_sb(sb)); + bhv_vfs_freeze(vfs_from_sb(sb)); } STATIC int @@ -742,11 +729,7 @@ xfs_fs_show_options( struct seq_file *m, struct vfsmount *mnt) { - struct vfs *vfsp = vfs_from_sb(mnt->mnt_sb); - int error; - - VFS_SHOWARGS(vfsp, m, error); - return error; + return -bhv_vfs_showargs(vfs_from_sb(mnt->mnt_sb), m); } STATIC int @@ -754,11 +737,7 @@ xfs_fs_quotasync( struct super_block *sb, int type) { - struct vfs *vfsp = vfs_from_sb(sb); - int error; - - VFS_QUOTACTL(vfsp, Q_XQUOTASYNC, 0, (caddr_t)NULL, error); - return -error; + return -bhv_vfs_quotactl(vfs_from_sb(sb), Q_XQUOTASYNC, 0, NULL); } STATIC int @@ -766,11 +745,7 @@ xfs_fs_getxstate( struct super_block *sb, struct fs_quota_stat *fqs) { - struct vfs *vfsp = vfs_from_sb(sb); - int error; - - VFS_QUOTACTL(vfsp, Q_XGETQSTAT, 0, (caddr_t)fqs, error); - return -error; + return -bhv_vfs_quotactl(vfs_from_sb(sb), Q_XGETQSTAT, 0, (caddr_t)fqs); } STATIC int @@ -779,11 +754,7 @@ xfs_fs_setxstate( unsigned int flags, int op) { - struct vfs *vfsp = vfs_from_sb(sb); - int error; - - VFS_QUOTACTL(vfsp, op, 0, (caddr_t)&flags, error); - return -error; + return -bhv_vfs_quotactl(vfs_from_sb(sb), op, 0, (caddr_t)&flags); } STATIC int @@ -793,13 +764,10 @@ xfs_fs_getxquota( qid_t id, struct fs_disk_quota *fdq) { - struct vfs *vfsp = vfs_from_sb(sb); - int error, getmode; - - getmode = (type == USRQUOTA) ? Q_XGETQUOTA : - ((type == GRPQUOTA) ? Q_XGETGQUOTA : Q_XGETPQUOTA); - VFS_QUOTACTL(vfsp, getmode, id, (caddr_t)fdq, error); - return -error; + return -bhv_vfs_quotactl(vfs_from_sb(sb), + (type == USRQUOTA) ? Q_XGETQUOTA : + ((type == GRPQUOTA) ? Q_XGETGQUOTA : + Q_XGETPQUOTA), id, (caddr_t)fdq); } STATIC int @@ -809,13 +777,10 @@ xfs_fs_setxquota( qid_t id, struct fs_disk_quota *fdq) { - struct vfs *vfsp = vfs_from_sb(sb); - int error, setmode; - - setmode = (type == USRQUOTA) ? Q_XSETQLIM : - ((type == GRPQUOTA) ? Q_XSETGQLIM : Q_XSETPQLIM); - VFS_QUOTACTL(vfsp, setmode, id, (caddr_t)fdq, error); - return -error; + return -bhv_vfs_quotactl(vfs_from_sb(sb), + (type == USRQUOTA) ? Q_XSETQLIM : + ((type == GRPQUOTA) ? Q_XSETGQLIM : + Q_XSETPQLIM), id, (caddr_t)fdq); } STATIC int @@ -825,14 +790,14 @@ xfs_fs_fill_super( int silent) { vnode_t *rootvp; - struct vfs *vfsp = vfs_allocate(sb); + struct bhv_vfs *vfsp = vfs_allocate(sb); struct xfs_mount_args *args = xfs_args_allocate(sb, silent); struct kstatfs statvfs; - int error, error2; + int error; bhv_insert_all_vfsops(vfsp); - VFS_PARSEARGS(vfsp, (char *)data, args, 0, error); + error = bhv_vfs_parseargs(vfsp, (char *)data, args, 0); if (error) { bhv_remove_all_vfsops(vfsp, 1); goto fail_vfsop; @@ -845,13 +810,13 @@ xfs_fs_fill_super( sb->s_qcop = &xfs_quotactl_operations; sb->s_op = &xfs_super_operations; - VFS_MOUNT(vfsp, args, NULL, error); + error = bhv_vfs_mount(vfsp, args, NULL); if (error) { bhv_remove_all_vfsops(vfsp, 1); goto fail_vfsop; } - VFS_STATVFS(vfsp, &statvfs, NULL, error); + error = bhv_vfs_statvfs(vfsp, &statvfs, NULL); if (error) goto fail_unmount; @@ -863,7 +828,7 @@ xfs_fs_fill_super( sb->s_time_gran = 1; set_posix_acl_flag(sb); - VFS_ROOT(vfsp, &rootvp, error); + error = bhv_vfs_root(vfsp, &rootvp); if (error) goto fail_unmount; @@ -892,7 +857,7 @@ fail_vnrele: } fail_unmount: - VFS_UNMOUNT(vfsp, 0, NULL, error2); + bhv_vfs_unmount(vfsp, 0, NULL); fail_vfsop: vfs_deallocate(vfsp); diff --git a/fs/xfs/linux-2.6/xfs_vfs.c b/fs/xfs/linux-2.6/xfs_vfs.c index 6f7c9f7a862..9f9bc894deb 100644 --- a/fs/xfs/linux-2.6/xfs_vfs.c +++ b/fs/xfs/linux-2.6/xfs_vfs.c @@ -226,13 +226,13 @@ vfs_freeze( ((*bhvtovfsops(next)->vfs_freeze)(next)); } -vfs_t * +bhv_vfs_t * vfs_allocate( struct super_block *sb) { - struct vfs *vfsp; + struct bhv_vfs *vfsp; - vfsp = kmem_zalloc(sizeof(vfs_t), KM_SLEEP); + vfsp = kmem_zalloc(sizeof(bhv_vfs_t), KM_SLEEP); bhv_head_init(VFS_BHVHEAD(vfsp), "vfs"); INIT_LIST_HEAD(&vfsp->vfs_sync_list); spin_lock_init(&vfsp->vfs_sync_lock); @@ -247,25 +247,25 @@ vfs_allocate( return vfsp; } -vfs_t * +bhv_vfs_t * vfs_from_sb( struct super_block *sb) { - return (vfs_t *)sb->s_fs_info; + return (bhv_vfs_t *)sb->s_fs_info; } void vfs_deallocate( - struct vfs *vfsp) + struct bhv_vfs *vfsp) { bhv_head_destroy(VFS_BHVHEAD(vfsp)); - kmem_free(vfsp, sizeof(vfs_t)); + kmem_free(vfsp, sizeof(bhv_vfs_t)); } void vfs_insertops( - struct vfs *vfsp, - struct bhv_vfsops *vfsops) + struct bhv_vfs *vfsp, + struct bhv_module_vfsops *vfsops) { struct bhv_desc *bdp; @@ -276,9 +276,9 @@ vfs_insertops( void vfs_insertbhv( - struct vfs *vfsp, + struct bhv_vfs *vfsp, struct bhv_desc *bdp, - struct vfsops *vfsops, + struct bhv_vfsops *vfsops, void *mount) { bhv_desc_init(bdp, mount, vfsp, vfsops); @@ -287,7 +287,7 @@ vfs_insertbhv( void bhv_remove_vfsops( - struct vfs *vfsp, + struct bhv_vfs *vfsp, int pos) { struct bhv_desc *bhv; @@ -301,7 +301,7 @@ bhv_remove_vfsops( void bhv_remove_all_vfsops( - struct vfs *vfsp, + struct bhv_vfs *vfsp, int freebase) { struct xfs_mount *mp; @@ -317,7 +317,7 @@ bhv_remove_all_vfsops( void bhv_insert_all_vfsops( - struct vfs *vfsp) + struct bhv_vfs *vfsp) { struct xfs_mount *mp; diff --git a/fs/xfs/linux-2.6/xfs_vfs.h b/fs/xfs/linux-2.6/xfs_vfs.h index 2ca05043a0f..55f0afd3e79 100644 --- a/fs/xfs/linux-2.6/xfs_vfs.h +++ b/fs/xfs/linux-2.6/xfs_vfs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2005 Silicon Graphics, Inc. + * Copyright (c) 2000-2006 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -21,42 +21,42 @@ #include #include "xfs_fs.h" +struct bhv_vfs; struct fid; -struct vfs; struct cred; struct vnode; -struct kstatfs; +struct statfs; struct seq_file; struct super_block; struct xfs_mount_args; typedef struct kstatfs xfs_statfs_t; -typedef struct vfs_sync_work { +typedef struct bhv_vfs_sync_work { struct list_head w_list; - struct vfs *w_vfs; + struct bhv_vfs *w_vfs; void *w_data; /* syncer routine argument */ - void (*w_syncer)(struct vfs *, void *); -} vfs_sync_work_t; + void (*w_syncer)(struct bhv_vfs *, void *); +} bhv_vfs_sync_work_t; -typedef struct vfs { +typedef struct bhv_vfs { u_int vfs_flag; /* flags */ xfs_fsid_t vfs_fsid; /* file system ID */ xfs_fsid_t *vfs_altfsid; /* An ID fixed for life of FS */ bhv_head_t vfs_bh; /* head of vfs behavior chain */ struct super_block *vfs_super; /* generic superblock pointer */ struct task_struct *vfs_sync_task; /* generalised sync thread */ - vfs_sync_work_t vfs_sync_work; /* work item for VFS_SYNC */ + bhv_vfs_sync_work_t vfs_sync_work; /* work item for VFS_SYNC */ struct list_head vfs_sync_list; /* sync thread work item list */ spinlock_t vfs_sync_lock; /* work item list lock */ - int vfs_sync_seq; /* sync thread generation no. */ + int vfs_sync_seq; /* sync thread generation no. */ wait_queue_head_t vfs_wait_single_sync_task; -} vfs_t; +} bhv_vfs_t; #define vfs_fbhv vfs_bh.bh_first /* 1st on vfs behavior chain */ -#define bhvtovfs(bdp) ( (struct vfs *)BHV_VOBJ(bdp) ) -#define bhvtovfsops(bdp) ( (struct vfsops *)BHV_OPS(bdp) ) +#define bhvtovfs(bdp) ( (struct bhv_vfs *)BHV_VOBJ(bdp) ) +#define bhvtovfsops(bdp) ( (struct bhv_vfsops *)BHV_OPS(bdp) ) #define VFS_BHVHEAD(vfs) ( &(vfs)->vfs_bh ) #define VFS_REMOVEBHV(vfs, bdp) ( bhv_remove(VFS_BHVHEAD(vfs), bdp) ) @@ -71,7 +71,7 @@ typedef enum { VFS_BHV_QM, /* quota manager */ VFS_BHV_IO, /* IO path */ VFS_BHV_END /* housekeeping end-of-range */ -} vfs_bhv_t; +} bhv_vfs_type_t; #define VFS_POSITION_XFS (BHV_POSITION_BASE) #define VFS_POSITION_DM (VFS_POSITION_BASE+10) @@ -81,8 +81,9 @@ typedef enum { #define VFS_RDONLY 0x0001 /* read-only vfs */ #define VFS_GRPID 0x0002 /* group-ID assigned from directory */ #define VFS_DMI 0x0004 /* filesystem has the DMI enabled */ -#define VFS_32BITINODES 0x0008 /* do not use inums above 32 bits */ -#define VFS_END 0x0008 /* max flag */ +#define VFS_UMOUNT 0x0008 /* unmount in progress */ +#define VFS_32BITINODES 0x0010 /* do not use inums above 32 bits */ +#define VFS_END 0x0010 /* max flag */ #define SYNC_ATTR 0x0001 /* sync attributes */ #define SYNC_CLOSE 0x0002 /* close file system down */ @@ -92,7 +93,7 @@ typedef enum { #define SYNC_FSDATA 0x0020 /* flush fs data (e.g. superblocks) */ #define SYNC_REFCACHE 0x0040 /* prune some of the nfs ref cache */ #define SYNC_REMOUNT 0x0080 /* remount readonly, no dummy LRs */ -#define SYNC_QUIESCE 0x0100 /* quiesce filesystem for a snapshot */ +#define SYNC_QUIESCE 0x0100 /* quiesce fileystem for a snapshot */ #define SHUTDOWN_META_IO_ERROR 0x0001 /* write attempt to metadata failed */ #define SHUTDOWN_LOG_IO_ERROR 0x0002 /* write attempt to the log failed */ @@ -120,7 +121,7 @@ typedef void (*vfs_init_vnode_t)(bhv_desc_t *, typedef void (*vfs_force_shutdown_t)(bhv_desc_t *, int, char *, int); typedef void (*vfs_freeze_t)(bhv_desc_t *); -typedef struct vfsops { +typedef struct bhv_vfsops { bhv_position_t vf_position; /* behavior chain position */ vfs_mount_t vfs_mount; /* mount file system */ vfs_parseargs_t vfs_parseargs; /* parse mount options */ @@ -136,44 +137,44 @@ typedef struct vfsops { vfs_init_vnode_t vfs_init_vnode; /* initialize a new vnode */ vfs_force_shutdown_t vfs_force_shutdown; /* crash and burn */ vfs_freeze_t vfs_freeze; /* freeze fs for snapshot */ -} vfsops_t; +} bhv_vfsops_t; /* * VFS's. Operates on vfs structure pointers (starts at bhv head). */ #define VHEAD(v) ((v)->vfs_fbhv) -#define VFS_MOUNT(v, ma,cr, rv) ((rv) = vfs_mount(VHEAD(v), ma,cr)) -#define VFS_PARSEARGS(v, o,ma,f, rv) ((rv) = vfs_parseargs(VHEAD(v), o,ma,f)) -#define VFS_SHOWARGS(v, m, rv) ((rv) = vfs_showargs(VHEAD(v), m)) -#define VFS_UNMOUNT(v, f, cr, rv) ((rv) = vfs_unmount(VHEAD(v), f,cr)) -#define VFS_MNTUPDATE(v, fl, args, rv) ((rv) = vfs_mntupdate(VHEAD(v), fl, args)) -#define VFS_ROOT(v, vpp, rv) ((rv) = vfs_root(VHEAD(v), vpp)) -#define VFS_STATVFS(v, sp,vp, rv) ((rv) = vfs_statvfs(VHEAD(v), sp,vp)) -#define VFS_SYNC(v, flag,cr, rv) ((rv) = vfs_sync(VHEAD(v), flag,cr)) -#define VFS_VGET(v, vpp,fidp, rv) ((rv) = vfs_vget(VHEAD(v), vpp,fidp)) -#define VFS_DMAPIOPS(v, p, rv) ((rv) = vfs_dmapiops(VHEAD(v), p)) -#define VFS_QUOTACTL(v, c,id,p, rv) ((rv) = vfs_quotactl(VHEAD(v), c,id,p)) -#define VFS_INIT_VNODE(v, vp,b,ul) ( vfs_init_vnode(VHEAD(v), vp,b,ul) ) -#define VFS_FORCE_SHUTDOWN(v, fl,f,l) ( vfs_force_shutdown(VHEAD(v), fl,f,l) ) -#define VFS_FREEZE(v) ( vfs_freeze(VHEAD(v)) ) +#define bhv_vfs_mount(v, ma,cr) vfs_mount(VHEAD(v), ma,cr) +#define bhv_vfs_parseargs(v, o,ma,f) vfs_parseargs(VHEAD(v), o,ma,f) +#define bhv_vfs_showargs(v, m) vfs_showargs(VHEAD(v), m) +#define bhv_vfs_unmount(v, f,cr) vfs_unmount(VHEAD(v), f,cr) +#define bhv_vfs_mntupdate(v, fl,args) vfs_mntupdate(VHEAD(v), fl,args) +#define bhv_vfs_root(v, vpp) vfs_root(VHEAD(v), vpp) +#define bhv_vfs_statvfs(v, sp,vp) vfs_statvfs(VHEAD(v), sp,vp) +#define bhv_vfs_sync(v, flag,cr) vfs_sync(VHEAD(v), flag,cr) +#define bhv_vfs_vget(v, vpp,fidp) vfs_vget(VHEAD(v), vpp,fidp) +#define bhv_vfs_dmapiops(v, p) vfs_dmapiops(VHEAD(v), p) +#define bhv_vfs_quotactl(v, c,id,p) vfs_quotactl(VHEAD(v), c,id,p) +#define bhv_vfs_init_vnode(v, vp,b,ul) vfs_init_vnode(VHEAD(v), vp,b,ul) +#define bhv_vfs_force_shutdown(v,u,f,l) vfs_force_shutdown(VHEAD(v), u,f,l) +#define bhv_vfs_freeze(v) vfs_freeze(VHEAD(v)) /* * PVFS's. Operates on behavior descriptor pointers. */ -#define PVFS_MOUNT(b, ma,cr, rv) ((rv) = vfs_mount(b, ma,cr)) -#define PVFS_PARSEARGS(b, o,ma,f, rv) ((rv) = vfs_parseargs(b, o,ma,f)) -#define PVFS_SHOWARGS(b, m, rv) ((rv) = vfs_showargs(b, m)) -#define PVFS_UNMOUNT(b, f,cr, rv) ((rv) = vfs_unmount(b, f,cr)) -#define PVFS_MNTUPDATE(b, fl, args, rv) ((rv) = vfs_mntupdate(b, fl, args)) -#define PVFS_ROOT(b, vpp, rv) ((rv) = vfs_root(b, vpp)) -#define PVFS_STATVFS(b, sp,vp, rv) ((rv) = vfs_statvfs(b, sp,vp)) -#define PVFS_SYNC(b, flag,cr, rv) ((rv) = vfs_sync(b, flag,cr)) -#define PVFS_VGET(b, vpp,fidp, rv) ((rv) = vfs_vget(b, vpp,fidp)) -#define PVFS_DMAPIOPS(b, p, rv) ((rv) = vfs_dmapiops(b, p)) -#define PVFS_QUOTACTL(b, c,id,p, rv) ((rv) = vfs_quotactl(b, c,id,p)) -#define PVFS_INIT_VNODE(b, vp,b2,ul) ( vfs_init_vnode(b, vp,b2,ul) ) -#define PVFS_FORCE_SHUTDOWN(b, fl,f,l) ( vfs_force_shutdown(b, fl,f,l) ) -#define PVFS_FREEZE(b) ( vfs_freeze(b) ) +#define bhv_next_vfs_mount(b, ma,cr) vfs_mount(b, ma,cr) +#define bhv_next_vfs_parseargs(b, o,ma,f) vfs_parseargs(b, o,ma,f) +#define bhv_next_vfs_showargs(b, m) vfs_showargs(b, m) +#define bhv_next_vfs_unmount(b, f,cr) vfs_unmount(b, f,cr) +#define bhv_next_vfs_mntupdate(b, fl,args) vfs_mntupdate(b, fl, args) +#define bhv_next_vfs_root(b, vpp) vfs_root(b, vpp) +#define bhv_next_vfs_statvfs(b, sp,vp) vfs_statvfs(b, sp,vp) +#define bhv_next_vfs_sync(b, flag,cr) vfs_sync(b, flag,cr) +#define bhv_next_vfs_vget(b, vpp,fidp) vfs_vget(b, vpp,fidp) +#define bhv_next_vfs_dmapiops(b, p) vfs_dmapiops(b, p) +#define bhv_next_vfs_quotactl(b, c,id,p) vfs_quotactl(b, c,id,p) +#define bhv_next_vfs_init_vnode(b, vp,b2,ul) vfs_init_vnode(b, vp,b2,ul) +#define bhv_next_force_shutdown(b, fl,f,l) vfs_force_shutdown(b, fl,f,l) +#define bhv_next_vfs_freeze(b) vfs_freeze(b) extern int vfs_mount(bhv_desc_t *, struct xfs_mount_args *, struct cred *); extern int vfs_parseargs(bhv_desc_t *, char *, struct xfs_mount_args *, int); @@ -190,25 +191,26 @@ extern void vfs_init_vnode(bhv_desc_t *, struct vnode *, bhv_desc_t *, int); extern void vfs_force_shutdown(bhv_desc_t *, int, char *, int); extern void vfs_freeze(bhv_desc_t *); -typedef struct bhv_vfsops { - struct vfsops bhv_common; +typedef struct bhv_module_vfsops { + struct bhv_vfsops bhv_common; void * bhv_custom; -} bhv_vfsops_t; +} bhv_module_vfsops_t; + +#define vfs_bhv_lookup(v, id) (bhv_lookup_range(&(v)->vfs_bh, (id), (id))) +#define vfs_bhv_custom(b) (((bhv_module_vfsops_t*)BHV_OPS(b))->bhv_custom) +#define vfs_bhv_set_custom(b,o) ((b)->bhv_custom = (void *)(o)) +#define vfs_bhv_clr_custom(b) ((b)->bhv_custom = NULL) -#define vfs_bhv_lookup(v, id) ( bhv_lookup_range(&(v)->vfs_bh, (id), (id)) ) -#define vfs_bhv_custom(b) ( ((bhv_vfsops_t *)BHV_OPS(b))->bhv_custom ) -#define vfs_bhv_set_custom(b,o) ( (b)->bhv_custom = (void *)(o)) -#define vfs_bhv_clr_custom(b) ( (b)->bhv_custom = NULL ) +extern bhv_vfs_t *vfs_allocate(struct super_block *); +extern bhv_vfs_t *vfs_from_sb(struct super_block *); +extern void vfs_deallocate(bhv_vfs_t *); +extern void vfs_insertbhv(bhv_vfs_t *, bhv_desc_t *, bhv_vfsops_t *, void *); -extern vfs_t *vfs_allocate(struct super_block *); -extern vfs_t *vfs_from_sb(struct super_block *); -extern void vfs_deallocate(vfs_t *); -extern void vfs_insertops(vfs_t *, bhv_vfsops_t *); -extern void vfs_insertbhv(vfs_t *, bhv_desc_t *, vfsops_t *, void *); +extern void vfs_insertops(bhv_vfs_t *, bhv_module_vfsops_t *); -extern void bhv_insert_all_vfsops(struct vfs *); -extern void bhv_remove_all_vfsops(struct vfs *, int); -extern void bhv_remove_vfsops(struct vfs *, int); +extern void bhv_insert_all_vfsops(struct bhv_vfs *); +extern void bhv_remove_all_vfsops(struct bhv_vfs *, int); +extern void bhv_remove_vfsops(struct bhv_vfs *, int); #define fs_frozen(vfsp) ((vfsp)->vfs_super->s_frozen) #define fs_check_frozen(vfsp, level) \ diff --git a/fs/xfs/linux-2.6/xfs_vnode.c b/fs/xfs/linux-2.6/xfs_vnode.c index f17e39cff23..82777f1a70a 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.c +++ b/fs/xfs/linux-2.6/xfs_vnode.c @@ -67,7 +67,7 @@ vn_ioerror( int l) { if (unlikely(error == -ENODEV)) - VFS_FORCE_SHUTDOWN(vp->v_vfsp, SHUTDOWN_DEVICE_REQ, f, l); + bhv_vfs_force_shutdown(vp->v_vfsp, SHUTDOWN_DEVICE_REQ, f, l); } struct vnode * diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h index 569a4e7b5cc..95343637ab6 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.h +++ b/fs/xfs/linux-2.6/xfs_vnode.h @@ -68,7 +68,7 @@ typedef enum vflags { */ typedef struct vnode { vflags_t v_flag; /* vnode flags (see above) */ - struct vfs *v_vfsp; /* ptr to containing VFS */ + struct bhv_vfs *v_vfsp; /* ptr to containing VFS */ vnumber_t v_number; /* in-core vnode number */ vn_bhv_head_t v_bh; /* behavior head */ spinlock_t v_lock; /* VN_LOCK/VN_UNLOCK */ @@ -503,7 +503,7 @@ extern vnode_t *vn_initialize(struct inode *); * vnode_map structures _must_ match vn_epoch and vnode structure sizes. */ typedef struct vnode_map { - vfs_t *v_vfsp; + bhv_vfs_t *v_vfsp; vnumber_t v_number; /* in-core vnode number */ xfs_ino_t v_ino; /* inode # */ } vmap_t; diff --git a/fs/xfs/quota/xfs_qm_bhv.c b/fs/xfs/quota/xfs_qm_bhv.c index 181dd90b29c..78f5962e578 100644 --- a/fs/xfs/quota/xfs_qm_bhv.c +++ b/fs/xfs/quota/xfs_qm_bhv.c @@ -129,7 +129,7 @@ xfs_qm_parseargs( return XFS_ERROR(EINVAL); } - PVFS_PARSEARGS(BHV_NEXT(bhv), options, args, update, error); + error = bhv_next_vfs_parseargs(BHV_NEXT(bhv), options, args, update); if (!error && !referenced) bhv_remove_vfsops(bhvtovfs(bhv), VFS_POSITION_QM); return error; @@ -140,9 +140,8 @@ xfs_qm_showargs( struct bhv_desc *bhv, struct seq_file *m) { - struct vfs *vfsp = bhvtovfs(bhv); + struct bhv_vfs *vfsp = bhvtovfs(bhv); struct xfs_mount *mp = XFS_VFSTOM(vfsp); - int error; if (mp->m_qflags & XFS_UQUOTA_ACCT) { (mp->m_qflags & XFS_UQUOTA_ENFD) ? @@ -165,8 +164,7 @@ xfs_qm_showargs( if (!(mp->m_qflags & XFS_ALL_QUOTA_ACCT)) seq_puts(m, "," MNTOPT_NOQUOTA); - PVFS_SHOWARGS(BHV_NEXT(bhv), m, error); - return error; + return bhv_next_vfs_showargs(BHV_NEXT(bhv), m); } STATIC int @@ -175,14 +173,12 @@ xfs_qm_mount( struct xfs_mount_args *args, struct cred *cr) { - struct vfs *vfsp = bhvtovfs(bhv); + struct bhv_vfs *vfsp = bhvtovfs(bhv); struct xfs_mount *mp = XFS_VFSTOM(vfsp); - int error; if (args->flags & (XFSMNT_UQUOTA | XFSMNT_GQUOTA | XFSMNT_PQUOTA)) xfs_qm_mount_quotainit(mp, args->flags); - PVFS_MOUNT(BHV_NEXT(bhv), args, cr, error); - return error; + return bhv_next_vfs_mount(BHV_NEXT(bhv), args, cr); } /* @@ -205,7 +201,7 @@ xfs_qm_statvfs( __uint64_t limit; int error; - error = PVFS_STATVFS(BHV_NEXT(bhv), statp, vnode); + error = bhv_next_vfs_statvfs(BHV_NEXT(bhv), statp, vnode); if (error || !vnode) return error; @@ -246,7 +242,7 @@ xfs_qm_syncall( int flags, cred_t *credp) { - struct vfs *vfsp = bhvtovfs(bhv); + struct bhv_vfs *vfsp = bhvtovfs(bhv); struct xfs_mount *mp = XFS_VFSTOM(vfsp); int error; @@ -265,8 +261,7 @@ xfs_qm_syncall( } } } - PVFS_SYNC(BHV_NEXT(bhv), flags, credp, error); - return error; + return bhv_next_vfs_sync(BHV_NEXT(bhv), flags, credp); } STATIC int @@ -401,7 +396,7 @@ STATIC struct xfs_qmops xfs_qmcore_xfs = { .xfs_dqtrxops = &xfs_trans_dquot_ops, }; -struct bhv_vfsops xfs_qmops = { { +struct bhv_module_vfsops xfs_qmops = { { BHV_IDENTITY_INIT(VFS_BHV_QM, VFS_POSITION_QM), .vfs_parseargs = xfs_qm_parseargs, .vfs_showargs = xfs_qm_showargs, diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c index c55db463bbf..afc7c1c696b 100644 --- a/fs/xfs/quota/xfs_qm_syscalls.c +++ b/fs/xfs/quota/xfs_qm_syscalls.c @@ -91,8 +91,8 @@ xfs_qm_quotactl( xfs_caddr_t addr) { xfs_mount_t *mp; + bhv_vfs_t *vfsp; int error; - struct vfs *vfsp; vfsp = bhvtovfs(bdp); mp = XFS_VFSTOM(vfsp); diff --git a/fs/xfs/xfs_dmapi.h b/fs/xfs/xfs_dmapi.h index 00b1540f810..4e7865ad6f0 100644 --- a/fs/xfs/xfs_dmapi.h +++ b/fs/xfs/xfs_dmapi.h @@ -189,6 +189,6 @@ typedef enum { #define AT_DELAY_FLAG(f) ((f&ATTR_NONBLOCK) ? DM_FLAGS_NDELAY : 0) -extern struct bhv_vfsops xfs_dmops; +extern struct bhv_module_vfsops xfs_dmops; #endif /* __XFS_DMAPI_H__ */ diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index 96f4b3e8fa4..502483c41f9 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -574,7 +574,7 @@ xfs_fs_goingdown( { switch (inflags) { case XFS_FSOP_GOING_FLAGS_DEFAULT: { - struct vfs *vfsp = XFS_MTOVFS(mp); + struct bhv_vfs *vfsp = XFS_MTOVFS(mp); struct super_block *sb = freeze_bdev(vfsp->vfs_super->s_bdev); if (sb && !IS_ERR(sb)) { diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index b5385432526..41f38eb60eb 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c @@ -468,7 +468,7 @@ finish_inode: * If we have a real type for an on-disk inode, we can set ops(&unlock) * now. If it's a new inode being created, xfs_ialloc will handle it. */ - VFS_INIT_VNODE(XFS_MTOVFS(mp), vp, XFS_ITOBHV(ip), 1); + bhv_vfs_init_vnode(XFS_MTOVFS(mp), vp, XFS_ITOBHV(ip), 1); return 0; } diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 50119a00885..0ed707ed664 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -1250,8 +1250,8 @@ xfs_ialloc( */ xfs_trans_log_inode(tp, ip, flags); - /* now that we have an i_mode we can set Linux inode ops (& unlock) */ - VFS_INIT_VNODE(XFS_MTOVFS(tp->t_mountp), vp, XFS_ITOBHV(ip), 1); + /* now that we have an i_mode we can setup inode ops and unlock */ + bhv_vfs_init_vnode(XFS_MTOVFS(tp->t_mountp), vp, XFS_ITOBHV(ip), 1); *ipp = ip; return 0; diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 3b544db1790..233668b748f 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -509,7 +509,6 @@ extern struct kmem_zone *xfs_chashlist_zone; extern struct kmem_zone *xfs_ifork_zone; extern struct kmem_zone *xfs_inode_zone; extern struct kmem_zone *xfs_ili_zone; -extern struct vnodeops xfs_vnodeops; #endif /* __KERNEL__ */ diff --git a/fs/xfs/xfs_iocore.c b/fs/xfs/xfs_iocore.c index d3da194f8b7..89441e69cdd 100644 --- a/fs/xfs/xfs_iocore.c +++ b/fs/xfs/xfs_iocore.c @@ -59,7 +59,7 @@ xfs_size_fn( STATIC int xfs_ioinit( - struct vfs *vfsp, + struct bhv_vfs *vfsp, struct xfs_mount_args *mntargs, int flags) { diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 7d882d6c7d4..9f70ab3e098 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -498,9 +498,8 @@ xfs_log_mount(xfs_mount_t *mp, * just worked. */ if (!(mp->m_flags & XFS_MOUNT_NORECOVERY)) { - int error; - vfs_t *vfsp = XFS_MTOVFS(mp); - int readonly = (vfsp->vfs_flag & VFS_RDONLY); + bhv_vfs_t *vfsp = XFS_MTOVFS(mp); + int error, readonly = (vfsp->vfs_flag & VFS_RDONLY); if (readonly) vfsp->vfs_flag &= ~VFS_RDONLY; @@ -816,7 +815,7 @@ xfs_log_need_covered(xfs_mount_t *mp) SPLDECL(s); int needed = 0, gen; xlog_t *log = mp->m_log; - vfs_t *vfsp = XFS_MTOVFS(mp); + bhv_vfs_t *vfsp = XFS_MTOVFS(mp); if (fs_frozen(vfsp) || XFS_FORCED_SHUTDOWN(mp) || (vfsp->vfs_flag & VFS_RDONLY)) diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 9378408a69d..56c4b7e51f4 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -196,7 +196,7 @@ xfs_mount_free( kmem_free(mp->m_logname, strlen(mp->m_logname) + 1); if (remove_bhv) { - struct vfs *vfsp = XFS_MTOVFS(mp); + struct bhv_vfs *vfsp = XFS_MTOVFS(mp); bhv_remove_all_vfsops(vfsp, 0); VFS_REMOVEBHV(vfsp, &mp->m_bhv); @@ -337,7 +337,7 @@ xfs_mount_validate_sb( xfs_agnumber_t xfs_initialize_perag( - struct vfs *vfs, + bhv_vfs_t *vfs, xfs_mount_t *mp, xfs_agnumber_t agcount) { @@ -651,7 +651,7 @@ xfs_mount_common(xfs_mount_t *mp, xfs_sb_t *sbp) */ int xfs_mountfs( - vfs_t *vfsp, + bhv_vfs_t *vfsp, xfs_mount_t *mp, int mfsi_flags) { @@ -1095,7 +1095,7 @@ xfs_mountfs( int xfs_unmountfs(xfs_mount_t *mp, struct cred *cr) { - struct vfs *vfsp = XFS_MTOVFS(mp); + struct bhv_vfs *vfsp = XFS_MTOVFS(mp); #if defined(DEBUG) || defined(INDUCE_IO_ERROR) int64_t fsid; #endif diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 2ca211214a9..7e612255f53 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -53,7 +53,7 @@ typedef struct xfs_trans_reservations { #else struct cred; struct log; -struct vfs; +struct bhv_vfs; struct vnode; struct xfs_mount_args; struct xfs_ihash; @@ -66,7 +66,7 @@ struct xfs_bmap_free; struct xfs_extdelta; struct xfs_swapext; -extern struct vfsops xfs_vfsops; +extern struct bhv_vfsops xfs_vfsops; extern struct vnodeops xfs_vnodeops; #define AIL_LOCK_T lock_t @@ -84,11 +84,11 @@ typedef int (*xfs_send_data_t)(int, struct vnode *, xfs_off_t, size_t, int, vrwlock_t *); typedef int (*xfs_send_mmap_t)(struct vm_area_struct *, uint); typedef int (*xfs_send_destroy_t)(struct vnode *, dm_right_t); -typedef int (*xfs_send_namesp_t)(dm_eventtype_t, struct vfs *, +typedef int (*xfs_send_namesp_t)(dm_eventtype_t, struct bhv_vfs *, struct vnode *, dm_right_t, struct vnode *, dm_right_t, char *, char *, mode_t, int, int); -typedef void (*xfs_send_unmount_t)(struct vfs *, struct vnode *, +typedef void (*xfs_send_unmount_t)(struct bhv_vfs *, struct vnode *, dm_right_t, mode_t, int, int); typedef struct xfs_dmops { @@ -190,7 +190,7 @@ typedef struct xfs_qmops { * Prototypes and functions for I/O core modularization. */ -typedef int (*xfs_ioinit_t)(struct vfs *, +typedef int (*xfs_ioinit_t)(struct bhv_vfs *, struct xfs_mount_args *, int); typedef int (*xfs_bmapi_t)(struct xfs_trans *, void *, xfs_fileoff_t, xfs_filblks_t, int, @@ -220,7 +220,7 @@ typedef void (*xfs_lock_demote_t)(void *, uint); typedef int (*xfs_lock_nowait_t)(void *, uint); typedef void (*xfs_unlk_t)(void *, unsigned int); typedef xfs_fsize_t (*xfs_size_t)(void *); -typedef xfs_fsize_t (*xfs_iodone_t)(struct vfs *); +typedef xfs_fsize_t (*xfs_iodone_t)(struct bhv_vfs *); typedef int (*xfs_swap_extents_t)(void *, void *, struct xfs_swapext*); @@ -511,7 +511,7 @@ xfs_preferred_iosize(xfs_mount_t *mp) #define XFS_FORCED_SHUTDOWN(mp) ((mp)->m_flags & XFS_MOUNT_FS_SHUTDOWN) #define xfs_force_shutdown(m,f) \ - VFS_FORCE_SHUTDOWN((XFS_MTOVFS(m)), f, __FILE__, __LINE__) + bhv_vfs_force_shutdown((XFS_MTOVFS(m)), f, __FILE__, __LINE__) /* * Flags for xfs_mountfs @@ -529,7 +529,7 @@ xfs_preferred_iosize(xfs_mount_t *mp) * Macros for getting from mount to vfs and back. */ #define XFS_MTOVFS(mp) xfs_mtovfs(mp) -static inline struct vfs *xfs_mtovfs(xfs_mount_t *mp) +static inline struct bhv_vfs *xfs_mtovfs(xfs_mount_t *mp) { return bhvtovfs(&mp->m_bhv); } @@ -541,7 +541,7 @@ static inline xfs_mount_t *xfs_bhvtom(bhv_desc_t *bdp) } #define XFS_VFSTOM(vfs) xfs_vfstom(vfs) -static inline xfs_mount_t *xfs_vfstom(vfs_t *vfs) +static inline xfs_mount_t *xfs_vfstom(bhv_vfs_t *vfs) { return XFS_BHVTOM(bhv_lookup(VFS_BHVHEAD(vfs), &xfs_vfsops)); } @@ -579,7 +579,7 @@ typedef struct xfs_mod_sb { extern xfs_mount_t *xfs_mount_init(void); extern void xfs_mod_sb(xfs_trans_t *, __int64_t); extern void xfs_mount_free(xfs_mount_t *mp, int remove_bhv); -extern int xfs_mountfs(struct vfs *, xfs_mount_t *mp, int); +extern int xfs_mountfs(struct bhv_vfs *, xfs_mount_t *mp, int); extern void xfs_mountfs_check_barriers(xfs_mount_t *mp); extern int xfs_unmountfs(xfs_mount_t *, struct cred *); @@ -597,7 +597,7 @@ extern void xfs_freesb(xfs_mount_t *); extern void xfs_do_force_shutdown(bhv_desc_t *, int, char *, int); extern int xfs_syncsub(xfs_mount_t *, int, int, int *); extern int xfs_sync_inodes(xfs_mount_t *, int, int, int *); -extern xfs_agnumber_t xfs_initialize_perag(struct vfs *, xfs_mount_t *, +extern xfs_agnumber_t xfs_initialize_perag(struct bhv_vfs *, xfs_mount_t *, xfs_agnumber_t); extern void xfs_xlatesb(void *, struct xfs_sb *, int, __int64_t); diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h index 7fbef974bce..acb853b33eb 100644 --- a/fs/xfs/xfs_quota.h +++ b/fs/xfs/xfs_quota.h @@ -365,7 +365,7 @@ typedef struct xfs_dqtrxops { extern int xfs_qm_dqcheck(xfs_disk_dquot_t *, xfs_dqid_t, uint, uint, char *); extern int xfs_mount_reset_sbqflags(struct xfs_mount *); -extern struct bhv_vfsops xfs_qmops; +extern struct bhv_module_vfsops xfs_qmops; #endif /* __KERNEL__ */ diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c index ec85a2e24b5..57ee2bebd24 100644 --- a/fs/xfs/xfs_vfsops.c +++ b/fs/xfs/xfs_vfsops.c @@ -212,7 +212,7 @@ xfs_cleanup(void) */ STATIC int xfs_start_flags( - struct vfs *vfs, + struct bhv_vfs *vfs, struct xfs_mount_args *ap, struct xfs_mount *mp) { @@ -337,7 +337,7 @@ xfs_start_flags( */ STATIC int xfs_finish_flags( - struct vfs *vfs, + struct bhv_vfs *vfs, struct xfs_mount_args *ap, struct xfs_mount *mp) { @@ -423,7 +423,7 @@ xfs_mount( struct xfs_mount_args *args, cred_t *credp) { - struct vfs *vfsp = bhvtovfs(bhvp); + struct bhv_vfs *vfsp = bhvtovfs(bhvp); struct bhv_desc *p; struct xfs_mount *mp = XFS_BHVTOM(bhvp); struct block_device *ddev, *logdev, *rtdev; @@ -552,7 +552,7 @@ xfs_unmount( int flags, cred_t *credp) { - struct vfs *vfsp = bhvtovfs(bdp); + bhv_vfs_t *vfsp = bhvtovfs(bdp); xfs_mount_t *mp = XFS_BHVTOM(bdp); xfs_inode_t *rip; vnode_t *rvp; @@ -665,9 +665,8 @@ xfs_mntupdate( int *flags, struct xfs_mount_args *args) { - struct vfs *vfsp = bhvtovfs(bdp); + bhv_vfs_t *vfsp = bhvtovfs(bdp); xfs_mount_t *mp = XFS_BHVTOM(bdp); - int error; if (!(*flags & MS_RDONLY)) { /* rw/ro -> rw */ if (vfsp->vfs_flag & VFS_RDONLY) @@ -679,7 +678,7 @@ xfs_mntupdate( mp->m_flags &= ~XFS_MOUNT_BARRIER; } } else if (!(vfsp->vfs_flag & VFS_RDONLY)) { /* rw -> ro */ - VFS_SYNC(vfsp, SYNC_FSDATA|SYNC_BDFLUSH|SYNC_ATTR, NULL, error); + bhv_vfs_sync(vfsp, SYNC_FSDATA|SYNC_BDFLUSH|SYNC_ATTR, NULL); xfs_quiesce_fs(mp); xfs_log_unmount_write(mp); xfs_unmountfs_writesb(mp); @@ -900,7 +899,7 @@ xfs_sync( /* * xfs sync routine for internal use * - * This routine supports all of the flags defined for the generic VFS_SYNC + * This routine supports all of the flags defined for the generic vfs_sync * interface as explained above under xfs_sync. In the interests of not * changing interfaces within the 6.5 family, additional internally- * required functions are specified within a separate xflags parameter, @@ -1421,7 +1420,7 @@ xfs_sync_inodes( /* * xfs sync routine for internal use * - * This routine supports all of the flags defined for the generic VFS_SYNC + * This routine supports all of the flags defined for the generic vfs_sync * interface as explained above under xfs_sync. In the interests of not * changing interfaces within the 6.5 family, additional internally- * required functions are specified within a separate xflags parameter, @@ -1686,7 +1685,7 @@ xfs_parseargs( struct xfs_mount_args *args, int update) { - struct vfs *vfsp = bhvtovfs(bhv); + bhv_vfs_t *vfsp = bhvtovfs(bhv); char *this_char, *value, *eov; int dsunit, dswidth, vol_dsunit, vol_dswidth; int iosize; @@ -1924,7 +1923,7 @@ xfs_showargs( }; struct proc_xfs_info *xfs_infop; struct xfs_mount *mp = XFS_BHVTOM(bhv); - struct vfs *vfsp = XFS_MTOVFS(mp); + struct bhv_vfs *vfsp = XFS_MTOVFS(mp); for (xfs_infop = xfs_info; xfs_infop->flag; xfs_infop++) { if (mp->m_flags & xfs_infop->flag) @@ -1984,7 +1983,7 @@ xfs_freeze( } -vfsops_t xfs_vfsops = { +bhv_vfsops_t xfs_vfsops = { BHV_IDENTITY_INIT(VFS_BHV_XFS,VFS_POSITION_XFS), .vfs_parseargs = xfs_parseargs, .vfs_showargs = xfs_showargs, -- cgit v1.2.3 From 67fcaa73adafb19139a7cd8ab133592b6a0a0901 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Fri, 9 Jun 2006 17:00:52 +1000 Subject: [XFS] Resolve a namespace collision on vnode/vnodeops for FreeBSD porters. SGI-PV: 953338 SGI-Modid: xfs-linux-melb:xfs-kern:26107a Signed-off-by: Nathan Scott --- fs/xfs/linux-2.6/xfs_aops.c | 33 ++--- fs/xfs/linux-2.6/xfs_aops.h | 2 +- fs/xfs/linux-2.6/xfs_export.c | 6 +- fs/xfs/linux-2.6/xfs_file.c | 120 ++++++---------- fs/xfs/linux-2.6/xfs_fs_subr.c | 6 +- fs/xfs/linux-2.6/xfs_ioctl.c | 61 ++++----- fs/xfs/linux-2.6/xfs_ioctl32.c | 4 +- fs/xfs/linux-2.6/xfs_iops.c | 99 ++++++------- fs/xfs/linux-2.6/xfs_lrw.c | 10 +- fs/xfs/linux-2.6/xfs_lrw.h | 4 +- fs/xfs/linux-2.6/xfs_super.c | 42 +++--- fs/xfs/linux-2.6/xfs_super.h | 2 +- fs/xfs/linux-2.6/xfs_vfs.c | 8 +- fs/xfs/linux-2.6/xfs_vfs.h | 55 ++++---- fs/xfs/linux-2.6/xfs_vnode.c | 32 ++--- fs/xfs/linux-2.6/xfs_vnode.h | 305 ++++++++++++++++------------------------- fs/xfs/quota/xfs_qm_bhv.c | 2 +- fs/xfs/quota/xfs_qm_syscalls.c | 2 +- fs/xfs/xfs_acl.c | 59 ++++---- fs/xfs/xfs_acl.h | 16 +-- fs/xfs/xfs_attr.c | 52 ++++--- fs/xfs/xfs_attr.h | 14 +- fs/xfs/xfs_bmap.c | 4 +- fs/xfs/xfs_cap.h | 10 +- fs/xfs/xfs_dfrag.c | 10 +- fs/xfs/xfs_iget.c | 16 +-- fs/xfs/xfs_inode.c | 20 +-- fs/xfs/xfs_inode.h | 6 +- fs/xfs/xfs_itable.c | 2 +- fs/xfs/xfs_mount.c | 2 +- fs/xfs/xfs_mount.h | 14 +- fs/xfs/xfs_rename.c | 6 +- fs/xfs/xfs_utils.c | 4 +- fs/xfs/xfs_utils.h | 3 +- fs/xfs/xfs_vfsops.c | 24 ++-- fs/xfs/xfs_vnodeops.c | 77 +++++------ 36 files changed, 496 insertions(+), 636 deletions(-) diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index c0a90431685..c5ea26d73be 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c @@ -76,7 +76,7 @@ xfs_page_trace( int mask) { xfs_inode_t *ip; - vnode_t *vp = vn_from_inode(inode); + bhv_vnode_t *vp = vn_from_inode(inode); loff_t isize = i_size_read(inode); loff_t offset = page_offset(page); int delalloc = -1, unmapped = -1, unwritten = -1; @@ -181,13 +181,12 @@ xfs_end_bio_unwritten( void *data) { xfs_ioend_t *ioend = data; - vnode_t *vp = ioend->io_vnode; + bhv_vnode_t *vp = ioend->io_vnode; xfs_off_t offset = ioend->io_offset; size_t size = ioend->io_size; - int error; if (likely(!ioend->io_error)) - VOP_BMAP(vp, offset, size, BMAPI_UNWRITTEN, NULL, NULL, error); + bhv_vop_bmap(vp, offset, size, BMAPI_UNWRITTEN, NULL, NULL); xfs_destroy_ioend(ioend); } @@ -240,10 +239,10 @@ xfs_map_blocks( xfs_iomap_t *mapp, int flags) { - vnode_t *vp = vn_from_inode(inode); + bhv_vnode_t *vp = vn_from_inode(inode); int error, nmaps = 1; - VOP_BMAP(vp, offset, count, flags, mapp, &nmaps, error); + error = bhv_vop_bmap(vp, offset, count, flags, mapp, &nmaps); if (!error && (flags & (BMAPI_WRITE|BMAPI_ALLOCATE))) VMODIFY(vp); return -error; @@ -1162,7 +1161,7 @@ xfs_vm_writepages( struct address_space *mapping, struct writeback_control *wbc) { - struct vnode *vp = vn_from_inode(mapping->host); + struct bhv_vnode *vp = vn_from_inode(mapping->host); if (VN_TRUNC(vp)) VUNTRUNCATE(vp); @@ -1242,7 +1241,7 @@ __xfs_get_blocks( int direct, bmapi_flags_t flags) { - vnode_t *vp = vn_from_inode(inode); + bhv_vnode_t *vp = vn_from_inode(inode); xfs_iomap_t iomap; xfs_off_t offset; ssize_t size; @@ -1252,8 +1251,8 @@ __xfs_get_blocks( offset = (xfs_off_t)iblock << inode->i_blkbits; ASSERT(bh_result->b_size >= (1 << inode->i_blkbits)); size = bh_result->b_size; - VOP_BMAP(vp, offset, size, - create ? flags : BMAPI_READ, &iomap, &niomap, error); + error = bhv_vop_bmap(vp, offset, size, + create ? flags : BMAPI_READ, &iomap, &niomap); if (error) return -error; if (niomap == 0) @@ -1381,13 +1380,13 @@ xfs_vm_direct_IO( { struct file *file = iocb->ki_filp; struct inode *inode = file->f_mapping->host; - vnode_t *vp = vn_from_inode(inode); + bhv_vnode_t *vp = vn_from_inode(inode); xfs_iomap_t iomap; int maps = 1; int error; ssize_t ret; - VOP_BMAP(vp, offset, 0, BMAPI_DEVICE, &iomap, &maps, error); + error = bhv_vop_bmap(vp, offset, 0, BMAPI_DEVICE, &iomap, &maps); if (error) return -error; @@ -1420,14 +1419,12 @@ xfs_vm_bmap( sector_t block) { struct inode *inode = (struct inode *)mapping->host; - vnode_t *vp = vn_from_inode(inode); - int error; + bhv_vnode_t *vp = vn_from_inode(inode); vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); - - VOP_RWLOCK(vp, VRWLOCK_READ); - VOP_FLUSH_PAGES(vp, (xfs_off_t)0, -1, 0, FI_REMAPF, error); - VOP_RWUNLOCK(vp, VRWLOCK_READ); + bhv_vop_rwlock(vp, VRWLOCK_READ); + bhv_vop_flush_pages(vp, (xfs_off_t)0, -1, 0, FI_REMAPF); + bhv_vop_rwunlock(vp, VRWLOCK_READ); return generic_block_bmap(mapping, block, xfs_get_blocks); } diff --git a/fs/xfs/linux-2.6/xfs_aops.h b/fs/xfs/linux-2.6/xfs_aops.h index 62c1d49025f..706d8c781b8 100644 --- a/fs/xfs/linux-2.6/xfs_aops.h +++ b/fs/xfs/linux-2.6/xfs_aops.h @@ -32,7 +32,7 @@ typedef struct xfs_ioend { unsigned int io_type; /* delalloc / unwritten */ int io_error; /* I/O error code */ atomic_t io_remaining; /* hold count */ - struct vnode *io_vnode; /* file being written to */ + struct bhv_vnode *io_vnode; /* file being written to */ struct buffer_head *io_buffer_head;/* buffer linked list head */ struct buffer_head *io_buffer_tail;/* buffer linked list tail */ size_t io_size; /* size of the extent */ diff --git a/fs/xfs/linux-2.6/xfs_export.c b/fs/xfs/linux-2.6/xfs_export.c index b5c579eeb8e..d32a9edc43a 100644 --- a/fs/xfs/linux-2.6/xfs_export.c +++ b/fs/xfs/linux-2.6/xfs_export.c @@ -136,7 +136,7 @@ xfs_fs_get_dentry( struct super_block *sb, void *data) { - vnode_t *vp; + bhv_vnode_t *vp; struct inode *inode; struct dentry *result; bhv_vfs_t *vfsp = vfs_from_sb(sb); @@ -160,12 +160,12 @@ xfs_fs_get_parent( struct dentry *child) { int error; - vnode_t *vp, *cvp; + bhv_vnode_t *vp, *cvp; struct dentry *parent; cvp = NULL; vp = vn_from_inode(child->d_inode); - VOP_LOOKUP(vp, &dotdot, &cvp, 0, NULL, NULL, error); + error = bhv_vop_lookup(vp, &dotdot, &cvp, 0, NULL, NULL); if (unlikely(error)) return ERR_PTR(-error); diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index 97615cc74ef..89b1a742135 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c @@ -58,15 +58,12 @@ __xfs_file_read( { struct iovec iov = {buf, count}; struct file *file = iocb->ki_filp; - vnode_t *vp = vn_from_inode(file->f_dentry->d_inode); - ssize_t rval; + bhv_vnode_t *vp = vn_from_inode(file->f_dentry->d_inode); BUG_ON(iocb->ki_pos != pos); - if (unlikely(file->f_flags & O_DIRECT)) ioflags |= IO_ISDIRECT; - VOP_READ(vp, iocb, &iov, 1, &iocb->ki_pos, ioflags, NULL, rval); - return rval; + return bhv_vop_read(vp, iocb, &iov, 1, &iocb->ki_pos, ioflags, NULL); } STATIC ssize_t @@ -100,15 +97,12 @@ __xfs_file_write( struct iovec iov = {(void __user *)buf, count}; struct file *file = iocb->ki_filp; struct inode *inode = file->f_mapping->host; - vnode_t *vp = vn_from_inode(inode); - ssize_t rval; + bhv_vnode_t *vp = vn_from_inode(inode); BUG_ON(iocb->ki_pos != pos); if (unlikely(file->f_flags & O_DIRECT)) ioflags |= IO_ISDIRECT; - - VOP_WRITE(vp, iocb, &iov, 1, &iocb->ki_pos, ioflags, NULL, rval); - return rval; + return bhv_vop_write(vp, iocb, &iov, 1, &iocb->ki_pos, ioflags, NULL); } STATIC ssize_t @@ -140,7 +134,7 @@ __xfs_file_readv( loff_t *ppos) { struct inode *inode = file->f_mapping->host; - vnode_t *vp = vn_from_inode(inode); + bhv_vnode_t *vp = vn_from_inode(inode); struct kiocb kiocb; ssize_t rval; @@ -149,7 +143,8 @@ __xfs_file_readv( if (unlikely(file->f_flags & O_DIRECT)) ioflags |= IO_ISDIRECT; - VOP_READ(vp, &kiocb, iov, nr_segs, &kiocb.ki_pos, ioflags, NULL, rval); + rval = bhv_vop_read(vp, &kiocb, iov, nr_segs, + &kiocb.ki_pos, ioflags, NULL); *ppos = kiocb.ki_pos; return rval; @@ -184,7 +179,7 @@ __xfs_file_writev( loff_t *ppos) { struct inode *inode = file->f_mapping->host; - vnode_t *vp = vn_from_inode(inode); + bhv_vnode_t *vp = vn_from_inode(inode); struct kiocb kiocb; ssize_t rval; @@ -193,7 +188,8 @@ __xfs_file_writev( if (unlikely(file->f_flags & O_DIRECT)) ioflags |= IO_ISDIRECT; - VOP_WRITE(vp, &kiocb, iov, nr_segs, &kiocb.ki_pos, ioflags, NULL, rval); + rval = bhv_vop_write(vp, &kiocb, iov, nr_segs, + &kiocb.ki_pos, ioflags, NULL); *ppos = kiocb.ki_pos; return rval; @@ -227,11 +223,8 @@ xfs_file_sendfile( read_actor_t actor, void *target) { - vnode_t *vp = vn_from_inode(filp->f_dentry->d_inode); - ssize_t rval; - - VOP_SENDFILE(vp, filp, pos, 0, count, actor, target, NULL, rval); - return rval; + return bhv_vop_sendfile(vn_from_inode(filp->f_dentry->d_inode), + filp, pos, 0, count, actor, target, NULL); } STATIC ssize_t @@ -242,11 +235,8 @@ xfs_file_sendfile_invis( read_actor_t actor, void *target) { - vnode_t *vp = vn_from_inode(filp->f_dentry->d_inode); - ssize_t rval; - - VOP_SENDFILE(vp, filp, pos, IO_INVIS, count, actor, target, NULL, rval); - return rval; + return bhv_vop_sendfile(vn_from_inode(filp->f_dentry->d_inode), + filp, pos, IO_INVIS, count, actor, target, NULL); } STATIC ssize_t @@ -257,11 +247,8 @@ xfs_file_splice_read( size_t len, unsigned int flags) { - vnode_t *vp = vn_from_inode(infilp->f_dentry->d_inode); - ssize_t rval; - - VOP_SPLICE_READ(vp, infilp, ppos, pipe, len, flags, 0, NULL, rval); - return rval; + return bhv_vop_splice_read(vn_from_inode(infilp->f_dentry->d_inode), + infilp, ppos, pipe, len, flags, 0, NULL); } STATIC ssize_t @@ -272,11 +259,9 @@ xfs_file_splice_read_invis( size_t len, unsigned int flags) { - vnode_t *vp = vn_from_inode(infilp->f_dentry->d_inode); - ssize_t rval; - - VOP_SPLICE_READ(vp, infilp, ppos, pipe, len, flags, IO_INVIS, NULL, rval); - return rval; + return bhv_vop_splice_read(vn_from_inode(infilp->f_dentry->d_inode), + infilp, ppos, pipe, len, flags, IO_INVIS, + NULL); } STATIC ssize_t @@ -287,11 +272,8 @@ xfs_file_splice_write( size_t len, unsigned int flags) { - vnode_t *vp = vn_from_inode(outfilp->f_dentry->d_inode); - ssize_t rval; - - VOP_SPLICE_WRITE(vp, pipe, outfilp, ppos, len, flags, 0, NULL, rval); - return rval; + return bhv_vop_splice_write(vn_from_inode(outfilp->f_dentry->d_inode), + pipe, outfilp, ppos, len, flags, 0, NULL); } STATIC ssize_t @@ -302,11 +284,9 @@ xfs_file_splice_write_invis( size_t len, unsigned int flags) { - vnode_t *vp = vn_from_inode(outfilp->f_dentry->d_inode); - ssize_t rval; - - VOP_SPLICE_WRITE(vp, pipe, outfilp, ppos, len, flags, IO_INVIS, NULL, rval); - return rval; + return bhv_vop_splice_write(vn_from_inode(outfilp->f_dentry->d_inode), + pipe, outfilp, ppos, len, flags, IO_INVIS, + NULL); } STATIC int @@ -314,24 +294,17 @@ xfs_file_open( struct inode *inode, struct file *filp) { - vnode_t *vp = vn_from_inode(inode); - int error; - if (!(filp->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS) return -EFBIG; - VOP_OPEN(vp, NULL, error); - return -error; + return -bhv_vop_open(vn_from_inode(inode), NULL); } STATIC int xfs_file_close( struct file *filp) { - vnode_t *vp = vn_from_inode(filp->f_dentry->d_inode); - int error; - - VOP_CLOSE(vp, 0, file_count(filp) > 1 ? L_FALSE : L_TRUE, NULL, error); - return -error; + return -bhv_vop_close(vn_from_inode(filp->f_dentry->d_inode), 0, + file_count(filp) > 1 ? L_FALSE : L_TRUE, NULL); } STATIC int @@ -339,12 +312,11 @@ xfs_file_release( struct inode *inode, struct file *filp) { - vnode_t *vp = vn_from_inode(inode); - int error = 0; + bhv_vnode_t *vp = vn_from_inode(inode); if (vp) - VOP_RELEASE(vp, error); - return -error; + return -bhv_vop_release(vp); + return 0; } STATIC int @@ -353,17 +325,14 @@ xfs_file_fsync( struct dentry *dentry, int datasync) { - struct inode *inode = dentry->d_inode; - vnode_t *vp = vn_from_inode(inode); - int error; + bhv_vnode_t *vp = vn_from_inode(dentry->d_inode); int flags = FSYNC_WAIT; if (datasync) flags |= FSYNC_DATA; if (VN_TRUNC(vp)) VUNTRUNCATE(vp); - VOP_FSYNC(vp, flags, NULL, (xfs_off_t)0, (xfs_off_t)-1, error); - return -error; + return -bhv_vop_fsync(vp, flags, NULL, (xfs_off_t)0, (xfs_off_t)-1); } #ifdef CONFIG_XFS_DMAPI @@ -374,7 +343,7 @@ xfs_vm_nopage( int *type) { struct inode *inode = area->vm_file->f_dentry->d_inode; - vnode_t *vp = vn_from_inode(inode); + bhv_vnode_t *vp = vn_from_inode(inode); ASSERT_ALWAYS(vp->v_vfsp->vfs_flag & VFS_DMI); if (XFS_SEND_MMAP(XFS_VFSTOM(vp->v_vfsp), area, 0)) @@ -390,7 +359,7 @@ xfs_file_readdir( filldir_t filldir) { int error = 0; - vnode_t *vp = vn_from_inode(filp->f_dentry->d_inode); + bhv_vnode_t *vp = vn_from_inode(filp->f_dentry->d_inode); uio_t uio; iovec_t iov; int eof = 0; @@ -425,7 +394,7 @@ xfs_file_readdir( start_offset = uio.uio_offset; - VOP_READDIR(vp, &uio, NULL, &eof, error); + error = bhv_vop_readdir(vp, &uio, NULL, &eof); if ((uio.uio_offset == start_offset) || error) { size = 0; break; @@ -475,18 +444,17 @@ xfs_file_mmap( return 0; } - STATIC long xfs_file_ioctl( struct file *filp, unsigned int cmd, - unsigned long arg) + unsigned long p) { int error; struct inode *inode = filp->f_dentry->d_inode; - vnode_t *vp = vn_from_inode(inode); + bhv_vnode_t *vp = vn_from_inode(inode); - VOP_IOCTL(vp, inode, filp, 0, cmd, (void __user *)arg, error); + error = bhv_vop_ioctl(vp, inode, filp, 0, cmd, (void __user *)p); VMODIFY(vp); /* NOTE: some of the ioctl's return positive #'s as a @@ -502,13 +470,13 @@ STATIC long xfs_file_ioctl_invis( struct file *filp, unsigned int cmd, - unsigned long arg) + unsigned long p) { - struct inode *inode = filp->f_dentry->d_inode; - vnode_t *vp = vn_from_inode(inode); int error; + struct inode *inode = filp->f_dentry->d_inode; + bhv_vnode_t *vp = vn_from_inode(inode); - VOP_IOCTL(vp, inode, filp, IO_INVIS, cmd, (void __user *)arg, error); + error = bhv_vop_ioctl(vp, inode, filp, IO_INVIS, cmd, (void __user *)p); VMODIFY(vp); /* NOTE: some of the ioctl's return positive #'s as a @@ -527,7 +495,7 @@ xfs_vm_mprotect( struct vm_area_struct *vma, unsigned int newflags) { - vnode_t *vp = vn_from_inode(vma->vm_file->f_dentry->d_inode); + bhv_vnode_t *vp = vn_from_inode(vma->vm_file->f_dentry->d_inode); int error = 0; if (vp->v_vfsp->vfs_flag & VFS_DMI) { @@ -553,7 +521,7 @@ STATIC int xfs_file_open_exec( struct inode *inode) { - vnode_t *vp = vn_from_inode(inode); + bhv_vnode_t *vp = vn_from_inode(inode); xfs_mount_t *mp = XFS_VFSTOM(vp->v_vfsp); int error = 0; xfs_inode_t *ip; diff --git a/fs/xfs/linux-2.6/xfs_fs_subr.c b/fs/xfs/linux-2.6/xfs_fs_subr.c index f0c56daf4d6..dc0562828e7 100644 --- a/fs/xfs/linux-2.6/xfs_fs_subr.c +++ b/fs/xfs/linux-2.6/xfs_fs_subr.c @@ -28,7 +28,7 @@ fs_tosspages( xfs_off_t last, int fiopt) { - vnode_t *vp = BHV_TO_VNODE(bdp); + bhv_vnode_t *vp = BHV_TO_VNODE(bdp); struct inode *ip = vn_to_inode(vp); if (VN_CACHED(vp)) @@ -42,7 +42,7 @@ fs_flushinval_pages( xfs_off_t last, int fiopt) { - vnode_t *vp = BHV_TO_VNODE(bdp); + bhv_vnode_t *vp = BHV_TO_VNODE(bdp); struct inode *ip = vn_to_inode(vp); if (VN_CACHED(vp)) { @@ -61,7 +61,7 @@ fs_flush_pages( uint64_t flags, int fiopt) { - vnode_t *vp = BHV_TO_VNODE(bdp); + bhv_vnode_t *vp = BHV_TO_VNODE(bdp); struct inode *ip = vn_to_inode(vp); if (VN_DIRTY(vp)) { diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c index 84478491609..73182503c16 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/fs/xfs/linux-2.6/xfs_ioctl.c @@ -78,7 +78,7 @@ xfs_find_handle( xfs_handle_t handle; xfs_fsop_handlereq_t hreq; struct inode *inode; - struct vnode *vp; + bhv_vnode_t *vp; if (copy_from_user(&hreq, arg, sizeof(hreq))) return -XFS_ERROR(EFAULT); @@ -192,7 +192,7 @@ xfs_vget_fsop_handlereq( xfs_mount_t *mp, struct inode *parinode, /* parent inode pointer */ xfs_fsop_handlereq_t *hreq, - vnode_t **vp, + bhv_vnode_t **vp, struct inode **inode) { void __user *hanp; @@ -202,7 +202,7 @@ xfs_vget_fsop_handlereq( xfs_handle_t handle; xfs_inode_t *ip; struct inode *inodep; - vnode_t *vpp; + bhv_vnode_t *vpp; xfs_ino_t ino; __u32 igen; int error; @@ -277,7 +277,7 @@ xfs_open_by_handle( struct file *filp; struct inode *inode; struct dentry *dentry; - vnode_t *vp; + bhv_vnode_t *vp; xfs_fsop_handlereq_t hreq; if (!capable(CAP_SYS_ADMIN)) @@ -362,7 +362,7 @@ xfs_readlink_by_handle( struct uio auio; struct inode *inode; xfs_fsop_handlereq_t hreq; - vnode_t *vp; + bhv_vnode_t *vp; __u32 olen; if (!capable(CAP_SYS_ADMIN)) @@ -393,9 +393,11 @@ xfs_readlink_by_handle( auio.uio_segflg = UIO_USERSPACE; auio.uio_resid = olen; - VOP_READLINK(vp, &auio, IO_INVIS, NULL, error); - + error = bhv_vop_readlink(vp, &auio, IO_INVIS, NULL); VN_RELE(vp); + if (error) + return -error; + return (olen - auio.uio_resid); } @@ -411,7 +413,7 @@ xfs_fssetdm_by_handle( xfs_fsop_setdm_handlereq_t dmhreq; struct inode *inode; bhv_desc_t *bdp; - vnode_t *vp; + bhv_vnode_t *vp; if (!capable(CAP_MKNOD)) return -XFS_ERROR(EPERM); @@ -452,7 +454,7 @@ xfs_attrlist_by_handle( attrlist_cursor_kern_t *cursor; xfs_fsop_attrlist_handlereq_t al_hreq; struct inode *inode; - vnode_t *vp; + bhv_vnode_t *vp; char *kbuf; if (!capable(CAP_SYS_ADMIN)) @@ -472,8 +474,8 @@ xfs_attrlist_by_handle( goto out_vn_rele; cursor = (attrlist_cursor_kern_t *)&al_hreq.pos; - VOP_ATTR_LIST(vp, kbuf, al_hreq.buflen, al_hreq.flags, - cursor, NULL, error); + error = bhv_vop_attr_list(vp, kbuf, al_hreq.buflen, al_hreq.flags, + cursor, NULL); if (error) goto out_kfree; @@ -490,7 +492,7 @@ xfs_attrlist_by_handle( STATIC int xfs_attrmulti_attr_get( - struct vnode *vp, + bhv_vnode_t *vp, char *name, char __user *ubuf, __uint32_t *len, @@ -505,7 +507,7 @@ xfs_attrmulti_attr_get( if (!kbuf) return ENOMEM; - VOP_ATTR_GET(vp, name, kbuf, len, flags, NULL, error); + error = bhv_vop_attr_get(vp, name, kbuf, len, flags, NULL); if (error) goto out_kfree; @@ -519,7 +521,7 @@ xfs_attrmulti_attr_get( STATIC int xfs_attrmulti_attr_set( - struct vnode *vp, + bhv_vnode_t *vp, char *name, const char __user *ubuf, __uint32_t len, @@ -542,7 +544,7 @@ xfs_attrmulti_attr_set( if (copy_from_user(kbuf, ubuf, len)) goto out_kfree; - VOP_ATTR_SET(vp, name, kbuf, len, flags, NULL, error); + error = bhv_vop_attr_set(vp, name, kbuf, len, flags, NULL); out_kfree: kfree(kbuf); @@ -551,20 +553,15 @@ xfs_attrmulti_attr_set( STATIC int xfs_attrmulti_attr_remove( - struct vnode *vp, + bhv_vnode_t *vp, char *name, __uint32_t flags) { - int error; - - if (IS_RDONLY(&vp->v_inode)) return -EROFS; if (IS_IMMUTABLE(&vp->v_inode) || IS_APPEND(&vp->v_inode)) return EPERM; - - VOP_ATTR_REMOVE(vp, name, flags, NULL, error); - return error; + return bhv_vop_attr_remove(vp, name, flags, NULL); } STATIC int @@ -578,7 +575,7 @@ xfs_attrmulti_by_handle( xfs_attr_multiop_t *ops; xfs_fsop_attrmulti_handlereq_t am_hreq; struct inode *inode; - vnode_t *vp; + bhv_vnode_t *vp; unsigned int i, size; char *attr_name; @@ -658,7 +655,7 @@ xfs_attrmulti_by_handle( STATIC int xfs_ioc_space( bhv_desc_t *bdp, - vnode_t *vp, + bhv_vnode_t *vp, struct file *filp, int flags, unsigned int cmd, @@ -682,7 +679,7 @@ xfs_ioc_fsgeometry( STATIC int xfs_ioc_xattr( - vnode_t *vp, + bhv_vnode_t *vp, xfs_inode_t *ip, struct file *filp, unsigned int cmd, @@ -711,7 +708,7 @@ xfs_ioctl( void __user *arg) { int error; - vnode_t *vp; + bhv_vnode_t *vp; xfs_inode_t *ip; xfs_mount_t *mp; @@ -962,7 +959,7 @@ xfs_ioctl( STATIC int xfs_ioc_space( bhv_desc_t *bdp, - vnode_t *vp, + bhv_vnode_t *vp, struct file *filp, int ioflags, unsigned int cmd, @@ -1153,7 +1150,7 @@ xfs_di2lxflags( STATIC int xfs_ioc_xattr( - vnode_t *vp, + bhv_vnode_t *vp, xfs_inode_t *ip, struct file *filp, unsigned int cmd, @@ -1173,7 +1170,7 @@ xfs_ioc_xattr( case XFS_IOC_FSGETXATTR: { vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \ XFS_AT_NEXTENTS | XFS_AT_PROJID; - VOP_GETATTR(vp, vattr, 0, NULL, error); + error = bhv_vop_getattr(vp, vattr, 0, NULL); if (unlikely(error)) { error = -error; break; @@ -1206,7 +1203,7 @@ xfs_ioc_xattr( vattr->va_extsize = fa.fsx_extsize; vattr->va_projid = fa.fsx_projid; - VOP_SETATTR(vp, vattr, attr_flags, NULL, error); + error = bhv_vop_setattr(vp, vattr, attr_flags, NULL); if (likely(!error)) __vn_revalidate(vp, vattr); /* update flags */ error = -error; @@ -1216,7 +1213,7 @@ xfs_ioc_xattr( case XFS_IOC_FSGETXATTRA: { vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \ XFS_AT_ANEXTENTS | XFS_AT_PROJID; - VOP_GETATTR(vp, vattr, 0, NULL, error); + error = bhv_vop_getattr(vp, vattr, 0, NULL); if (unlikely(error)) { error = -error; break; @@ -1262,7 +1259,7 @@ xfs_ioc_xattr( vattr->va_xflags = xfs_merge_ioc_xflags(flags, xfs_ip2xflags(ip)); - VOP_SETATTR(vp, vattr, attr_flags, NULL, error); + error = bhv_vop_setattr(vp, vattr, attr_flags, NULL); if (likely(!error)) __vn_revalidate(vp, vattr); /* update flags */ error = -error; diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c index 251bfe451a3..601f01c92f7 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl32.c +++ b/fs/xfs/linux-2.6/xfs_ioctl32.c @@ -114,7 +114,7 @@ xfs_compat_ioctl( unsigned long arg) { struct inode *inode = file->f_dentry->d_inode; - vnode_t *vp = vn_from_inode(inode); + bhv_vnode_t *vp = vn_from_inode(inode); int error; switch (cmd) { @@ -193,7 +193,7 @@ xfs_compat_ioctl( return -ENOIOCTLCMD; } - VOP_IOCTL(vp, inode, file, mode, cmd, (void __user *)arg, error); + error = bhv_vop_ioctl(vp, inode, file, mode, cmd, (void __user *)arg); VMODIFY(vp); return error; diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index 0da1d6b081e..0857658882e 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c @@ -61,7 +61,7 @@ */ xfs_inode_t * xfs_vtoi( - struct vnode *vp) + bhv_vnode_t *vp) { bhv_desc_t *bdp; @@ -80,7 +80,7 @@ void xfs_synchronize_atime( xfs_inode_t *ip) { - vnode_t *vp; + bhv_vnode_t *vp; vp = XFS_ITOV_NULL(ip); if (vp) { @@ -202,12 +202,8 @@ xfs_validate_fields( struct inode *ip, struct vattr *vattr) { - vnode_t *vp = vn_from_inode(ip); - int error; - vattr->va_mask = XFS_AT_NLINK|XFS_AT_SIZE|XFS_AT_NBLOCKS; - VOP_GETATTR(vp, vattr, ATTR_LAZY, NULL, error); - if (likely(!error)) { + if (!bhv_vop_getattr(vn_from_inode(ip), vattr, ATTR_LAZY, NULL)) { ip->i_nlink = vattr->va_nlink; ip->i_blocks = vattr->va_nblocks; @@ -225,7 +221,7 @@ xfs_validate_fields( */ STATIC int xfs_init_security( - struct vnode *vp, + bhv_vnode_t *vp, struct inode *dir) { struct inode *ip = vn_to_inode(vp); @@ -241,7 +237,7 @@ xfs_init_security( return -error; } - VOP_ATTR_SET(vp, name, value, length, ATTR_SECURE, NULL, error); + error = bhv_vop_attr_set(vp, name, value, length, ATTR_SECURE, NULL); if (!error) VMODIFY(vp); @@ -264,13 +260,12 @@ xfs_has_fs_struct(struct task_struct *task) STATIC inline void xfs_cleanup_inode( - vnode_t *dvp, - vnode_t *vp, + bhv_vnode_t *dvp, + bhv_vnode_t *vp, struct dentry *dentry, int mode) { struct dentry teardown = {}; - int error; /* Oh, the horror. * If we can't add the ACL or we fail in @@ -281,9 +276,9 @@ xfs_cleanup_inode( teardown.d_name = dentry->d_name; if (S_ISDIR(mode)) - VOP_RMDIR(dvp, &teardown, NULL, error); + bhv_vop_rmdir(dvp, &teardown, NULL); else - VOP_REMOVE(dvp, &teardown, NULL, error); + bhv_vop_remove(dvp, &teardown, NULL); VN_RELE(vp); } @@ -296,7 +291,7 @@ xfs_vn_mknod( { struct inode *ip; vattr_t vattr = { 0 }; - vnode_t *vp = NULL, *dvp = vn_from_inode(dir); + bhv_vnode_t *vp = NULL, *dvp = vn_from_inode(dir); xfs_acl_t *default_acl = NULL; attrexists_t test_default_acl = _ACL_DEFAULT_EXISTS; int error; @@ -330,10 +325,10 @@ xfs_vn_mknod( vattr.va_mask |= XFS_AT_RDEV; /*FALLTHROUGH*/ case S_IFREG: - VOP_CREATE(dvp, dentry, &vattr, &vp, NULL, error); + error = bhv_vop_create(dvp, dentry, &vattr, &vp, NULL); break; case S_IFDIR: - VOP_MKDIR(dvp, dentry, &vattr, &vp, NULL, error); + error = bhv_vop_mkdir(dvp, dentry, &vattr, &vp, NULL); break; default: error = EINVAL; @@ -396,14 +391,14 @@ xfs_vn_lookup( struct dentry *dentry, struct nameidata *nd) { - struct vnode *vp = vn_from_inode(dir), *cvp; + bhv_vnode_t *vp = vn_from_inode(dir), *cvp; int error; if (dentry->d_name.len >= MAXNAMELEN) return ERR_PTR(-ENAMETOOLONG); - VOP_LOOKUP(vp, dentry, &cvp, 0, NULL, NULL, error); - if (error) { + error = bhv_vop_lookup(vp, dentry, &cvp, 0, NULL, NULL); + if (unlikely(error)) { if (unlikely(error != ENOENT)) return ERR_PTR(-error); d_add(dentry, NULL); @@ -420,8 +415,8 @@ xfs_vn_link( struct dentry *dentry) { struct inode *ip; /* inode of guy being linked to */ - vnode_t *tdvp; /* target directory for new name/link */ - vnode_t *vp; /* vp of name being linked */ + bhv_vnode_t *tdvp; /* target directory for new name/link */ + bhv_vnode_t *vp; /* vp of name being linked */ vattr_t vattr; int error; @@ -432,7 +427,7 @@ xfs_vn_link( tdvp = vn_from_inode(dir); vp = vn_from_inode(ip); - VOP_LINK(tdvp, vp, dentry, NULL, error); + error = bhv_vop_link(tdvp, vp, dentry, NULL); if (likely(!error)) { VMODIFY(tdvp); VN_HOLD(vp); @@ -448,14 +443,14 @@ xfs_vn_unlink( struct dentry *dentry) { struct inode *inode; - vnode_t *dvp; /* directory containing name to remove */ + bhv_vnode_t *dvp; /* directory containing name to remove */ vattr_t vattr; int error; inode = dentry->d_inode; dvp = vn_from_inode(dir); - VOP_REMOVE(dvp, dentry, NULL, error); + error = bhv_vop_remove(dvp, dentry, NULL); if (likely(!error)) { xfs_validate_fields(dir, &vattr); /* size needs update */ xfs_validate_fields(inode, &vattr); @@ -470,27 +465,26 @@ xfs_vn_symlink( const char *symname) { struct inode *ip; - vattr_t vattr = { 0 }; - vnode_t *dvp; /* directory containing name of symlink */ - vnode_t *cvp; /* used to lookup symlink to put in dentry */ + vattr_t va = { 0 }; + bhv_vnode_t *dvp; /* directory containing name of symlink */ + bhv_vnode_t *cvp; /* used to lookup symlink to put in dentry */ int error; dvp = vn_from_inode(dir); cvp = NULL; - vattr.va_mode = S_IFLNK | + va.va_mode = S_IFLNK | (irix_symlink_mode ? 0777 & ~current->fs->umask : S_IRWXUGO); - vattr.va_mask = XFS_AT_TYPE|XFS_AT_MODE; + va.va_mask = XFS_AT_TYPE|XFS_AT_MODE; - error = 0; - VOP_SYMLINK(dvp, dentry, &vattr, (char *)symname, &cvp, NULL, error); + error = bhv_vop_symlink(dvp, dentry, &va, (char *)symname, &cvp, NULL); if (likely(!error && cvp)) { error = xfs_init_security(cvp, dir); if (likely(!error)) { ip = vn_to_inode(cvp); d_instantiate(dentry, ip); - xfs_validate_fields(dir, &vattr); - xfs_validate_fields(ip, &vattr); + xfs_validate_fields(dir, &va); + xfs_validate_fields(ip, &va); } else { xfs_cleanup_inode(dvp, cvp, dentry, 0); } @@ -504,11 +498,11 @@ xfs_vn_rmdir( struct dentry *dentry) { struct inode *inode = dentry->d_inode; - vnode_t *dvp = vn_from_inode(dir); + bhv_vnode_t *dvp = vn_from_inode(dir); vattr_t vattr; int error; - VOP_RMDIR(dvp, dentry, NULL, error); + error = bhv_vop_rmdir(dvp, dentry, NULL); if (likely(!error)) { xfs_validate_fields(inode, &vattr); xfs_validate_fields(dir, &vattr); @@ -524,15 +518,15 @@ xfs_vn_rename( struct dentry *ndentry) { struct inode *new_inode = ndentry->d_inode; - vnode_t *fvp; /* from directory */ - vnode_t *tvp; /* target directory */ + bhv_vnode_t *fvp; /* from directory */ + bhv_vnode_t *tvp; /* target directory */ vattr_t vattr; int error; fvp = vn_from_inode(odir); tvp = vn_from_inode(ndir); - VOP_RENAME(fvp, odentry, tvp, ndentry, NULL, error); + error = bhv_vop_rename(fvp, odentry, tvp, ndentry, NULL); if (likely(!error)) { if (new_inode) xfs_validate_fields(new_inode, &vattr); @@ -553,7 +547,7 @@ xfs_vn_follow_link( struct dentry *dentry, struct nameidata *nd) { - vnode_t *vp; + bhv_vnode_t *vp; uio_t *uio; iovec_t iov; int error; @@ -586,8 +580,8 @@ xfs_vn_follow_link( uio->uio_resid = MAXPATHLEN; uio->uio_iovcnt = 1; - VOP_READLINK(vp, uio, 0, NULL, error); - if (error) { + error = bhv_vop_readlink(vp, uio, 0, NULL); + if (unlikely(error)) { kfree(link); link = ERR_PTR(-error); } else { @@ -618,12 +612,7 @@ xfs_vn_permission( int mode, struct nameidata *nd) { - vnode_t *vp = vn_from_inode(inode); - int error; - - mode <<= 6; /* convert from linux to vnode access bits */ - VOP_ACCESS(vp, mode, NULL, error); - return -error; + return -bhv_vop_access(vn_from_inode(inode), mode << 6, NULL); } #else #define xfs_vn_permission NULL @@ -636,7 +625,7 @@ xfs_vn_getattr( struct kstat *stat) { struct inode *inode = dentry->d_inode; - vnode_t *vp = vn_from_inode(inode); + bhv_vnode_t *vp = vn_from_inode(inode); int error = 0; if (unlikely(vp->v_flag & VMODIFIED)) @@ -653,7 +642,7 @@ xfs_vn_setattr( { struct inode *inode = dentry->d_inode; unsigned int ia_valid = attr->ia_valid; - vnode_t *vp = vn_from_inode(inode); + bhv_vnode_t *vp = vn_from_inode(inode); vattr_t vattr = { 0 }; int flags = 0; int error; @@ -697,7 +686,7 @@ xfs_vn_setattr( flags |= ATTR_NONBLOCK; #endif - VOP_SETATTR(vp, &vattr, flags, NULL, error); + error = bhv_vop_setattr(vp, &vattr, flags, NULL); if (likely(!error)) __vn_revalidate(vp, &vattr); return -error; @@ -718,7 +707,7 @@ xfs_vn_setxattr( size_t size, int flags) { - vnode_t *vp = vn_from_inode(dentry->d_inode); + bhv_vnode_t *vp = vn_from_inode(dentry->d_inode); char *attr = (char *)name; attrnames_t *namesp; int xflags = 0; @@ -748,7 +737,7 @@ xfs_vn_getxattr( void *data, size_t size) { - vnode_t *vp = vn_from_inode(dentry->d_inode); + bhv_vnode_t *vp = vn_from_inode(dentry->d_inode); char *attr = (char *)name; attrnames_t *namesp; int xflags = 0; @@ -777,7 +766,7 @@ xfs_vn_listxattr( char *data, size_t size) { - vnode_t *vp = vn_from_inode(dentry->d_inode); + bhv_vnode_t *vp = vn_from_inode(dentry->d_inode); int error, xflags = ATTR_KERNAMELS; ssize_t result; @@ -796,7 +785,7 @@ xfs_vn_removexattr( struct dentry *dentry, const char *name) { - vnode_t *vp = vn_from_inode(dentry->d_inode); + bhv_vnode_t *vp = vn_from_inode(dentry->d_inode); char *attr = (char *)name; attrnames_t *namesp; int xflags = 0; diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c index 6fbdca3eaa7..a9b83018f0f 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.c +++ b/fs/xfs/linux-2.6/xfs_lrw.c @@ -206,7 +206,7 @@ xfs_read( xfs_fsize_t n; xfs_inode_t *ip; xfs_mount_t *mp; - vnode_t *vp; + bhv_vnode_t *vp; unsigned long seg; ip = XFS_BHVTOI(bdp); @@ -271,7 +271,7 @@ xfs_read( } if (unlikely((ioflags & IO_ISDIRECT) && VN_CACHED(vp))) - VOP_FLUSHINVAL_PAGES(vp, ctooff(offtoct(*offset)), + bhv_vop_flushinval_pages(vp, ctooff(offtoct(*offset)), -1, FI_REMAPF_LOCKED); xfs_rw_enter_trace(XFS_READ_ENTER, &ip->i_iocore, @@ -499,7 +499,7 @@ xfs_zero_last_block( int /* error (positive) */ xfs_zero_eof( - vnode_t *vp, + bhv_vnode_t *vp, xfs_iocore_t *io, xfs_off_t offset, /* starting I/O offset */ xfs_fsize_t isize, /* current inode size */ @@ -626,7 +626,7 @@ xfs_write( ssize_t ret = 0, error = 0; xfs_fsize_t isize, new_size; xfs_iocore_t *io; - vnode_t *vp; + bhv_vnode_t *vp; unsigned long seg; int iolock; int eventsent = 0; @@ -803,7 +803,7 @@ retry: if (need_flush) { xfs_inval_cached_trace(io, pos, -1, ctooff(offtoct(pos)), -1); - VOP_FLUSHINVAL_PAGES(vp, ctooff(offtoct(pos)), + bhv_vop_flushinval_pages(vp, ctooff(offtoct(pos)), -1, FI_REMAPF_LOCKED); } diff --git a/fs/xfs/linux-2.6/xfs_lrw.h b/fs/xfs/linux-2.6/xfs_lrw.h index dc49050688c..c77e62efb74 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.h +++ b/fs/xfs/linux-2.6/xfs_lrw.h @@ -18,8 +18,8 @@ #ifndef __XFS_LRW_H__ #define __XFS_LRW_H__ -struct vnode; struct bhv_desc; +struct bhv_vnode; struct xfs_mount; struct xfs_iocore; struct xfs_inode; @@ -82,7 +82,7 @@ extern int xfsbdstrat(struct xfs_mount *, struct xfs_buf *); extern int xfs_bdstrat_cb(struct xfs_buf *); extern int xfs_dev_is_read_only(struct xfs_mount *, char *); -extern int xfs_zero_eof(struct vnode *, struct xfs_iocore *, xfs_off_t, +extern int xfs_zero_eof(struct bhv_vnode *, struct xfs_iocore *, xfs_off_t, xfs_fsize_t, xfs_fsize_t); extern ssize_t xfs_read(struct bhv_desc *, struct kiocb *, const struct iovec *, unsigned int, diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 97dbcb68b25..b7aad3cfdfe 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -151,7 +151,7 @@ xfs_set_inodeops( STATIC __inline__ void xfs_revalidate_inode( xfs_mount_t *mp, - vnode_t *vp, + bhv_vnode_t *vp, xfs_inode_t *ip) { struct inode *inode = vn_to_inode(vp); @@ -206,7 +206,7 @@ xfs_revalidate_inode( void xfs_initialize_vnode( bhv_desc_t *bdp, - vnode_t *vp, + bhv_vnode_t *vp, bhv_desc_t *inode_bhv, int unlock) { @@ -336,7 +336,7 @@ STATIC struct inode * xfs_fs_alloc_inode( struct super_block *sb) { - vnode_t *vp; + bhv_vnode_t *vp; vp = kmem_zone_alloc(xfs_vnode_zone, KM_SLEEP); if (unlikely(!vp)) @@ -359,13 +359,13 @@ xfs_fs_inode_init_once( { if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR) - inode_init_once(vn_to_inode((vnode_t *)vnode)); + inode_init_once(vn_to_inode((bhv_vnode_t *)vnode)); } STATIC int xfs_init_zones(void) { - xfs_vnode_zone = kmem_zone_init_flags(sizeof(vnode_t), "xfs_vnode_t", + xfs_vnode_zone = kmem_zone_init_flags(sizeof(bhv_vnode_t), "xfs_vnode", KM_ZONE_HWALIGN | KM_ZONE_RECLAIM | KM_ZONE_SPREAD, xfs_fs_inode_init_once); @@ -409,22 +409,17 @@ xfs_fs_write_inode( struct inode *inode, int sync) { - vnode_t *vp = vn_from_inode(inode); + bhv_vnode_t *vp = vn_from_inode(inode); int error = 0, flags = FLUSH_INODE; if (vp) { vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); if (sync) flags |= FLUSH_SYNC; - VOP_IFLUSH(vp, flags, error); - if (error == EAGAIN) { - if (sync) - VOP_IFLUSH(vp, flags | FLUSH_LOG, error); - else - error = 0; - } + error = bhv_vop_iflush(vp, flags); + if (error == EAGAIN) + error = sync? bhv_vop_iflush(vp, flags | FLUSH_LOG) : 0; } - return -error; } @@ -432,8 +427,7 @@ STATIC void xfs_fs_clear_inode( struct inode *inode) { - vnode_t *vp = vn_from_inode(inode); - int error, cache; + bhv_vnode_t *vp = vn_from_inode(inode); vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); @@ -446,20 +440,18 @@ xfs_fs_clear_inode( * This can happen because xfs_iget_core calls xfs_idestroy if we * find an inode with di_mode == 0 but without IGET_CREATE set. */ - if (vp->v_fbhv) - VOP_INACTIVE(vp, NULL, cache); + if (VNHEAD(vp)) + bhv_vop_inactive(vp, NULL); VN_LOCK(vp); vp->v_flag &= ~VMODIFIED; VN_UNLOCK(vp, 0); - if (vp->v_fbhv) { - VOP_RECLAIM(vp, error); - if (error) - panic("vn_purge: cannot reclaim"); - } + if (VNHEAD(vp)) + if (bhv_vop_reclaim(vp)) + panic("%s: cannot reclaim 0x%p\n", __FUNCTION__, vp); - ASSERT(vp->v_fbhv == NULL); + ASSERT(VNHEAD(vp) == NULL); #ifdef XFS_VNODE_TRACE ktrace_free(vp->v_trace); @@ -789,7 +781,7 @@ xfs_fs_fill_super( void *data, int silent) { - vnode_t *rootvp; + struct bhv_vnode *rootvp; struct bhv_vfs *vfsp = vfs_allocate(sb); struct xfs_mount_args *args = xfs_args_allocate(sb, silent); struct kstatfs statvfs; diff --git a/fs/xfs/linux-2.6/xfs_super.h b/fs/xfs/linux-2.6/xfs_super.h index 376b96cb513..33dd1ca1324 100644 --- a/fs/xfs/linux-2.6/xfs_super.h +++ b/fs/xfs/linux-2.6/xfs_super.h @@ -105,7 +105,7 @@ struct block_device; extern __uint64_t xfs_max_file_offset(unsigned int); -extern void xfs_initialize_vnode(bhv_desc_t *, vnode_t *, bhv_desc_t *, int); +extern void xfs_initialize_vnode(bhv_desc_t *, bhv_vnode_t *, bhv_desc_t *, int); extern void xfs_flush_inode(struct xfs_inode *); extern void xfs_flush_device(struct xfs_inode *); diff --git a/fs/xfs/linux-2.6/xfs_vfs.c b/fs/xfs/linux-2.6/xfs_vfs.c index 9f9bc894deb..a91ecfa9c8a 100644 --- a/fs/xfs/linux-2.6/xfs_vfs.c +++ b/fs/xfs/linux-2.6/xfs_vfs.c @@ -104,7 +104,7 @@ vfs_mntupdate( int vfs_root( struct bhv_desc *bdp, - struct vnode **vpp) + struct bhv_vnode **vpp) { struct bhv_desc *next = bdp; @@ -118,7 +118,7 @@ int vfs_statvfs( struct bhv_desc *bdp, xfs_statfs_t *sp, - struct vnode *vp) + struct bhv_vnode *vp) { struct bhv_desc *next = bdp; @@ -145,7 +145,7 @@ vfs_sync( int vfs_vget( struct bhv_desc *bdp, - struct vnode **vpp, + struct bhv_vnode **vpp, struct fid *fidp) { struct bhv_desc *next = bdp; @@ -187,7 +187,7 @@ vfs_quotactl( void vfs_init_vnode( struct bhv_desc *bdp, - struct vnode *vp, + struct bhv_vnode *vp, struct bhv_desc *bp, int unlock) { diff --git a/fs/xfs/linux-2.6/xfs_vfs.h b/fs/xfs/linux-2.6/xfs_vfs.h index 55f0afd3e79..1a3a2dd4b97 100644 --- a/fs/xfs/linux-2.6/xfs_vfs.h +++ b/fs/xfs/linux-2.6/xfs_vfs.h @@ -22,9 +22,9 @@ #include "xfs_fs.h" struct bhv_vfs; +struct bhv_vnode; struct fid; struct cred; -struct vnode; struct statfs; struct seq_file; struct super_block; @@ -53,8 +53,6 @@ typedef struct bhv_vfs { wait_queue_head_t vfs_wait_single_sync_task; } bhv_vfs_t; -#define vfs_fbhv vfs_bh.bh_first /* 1st on vfs behavior chain */ - #define bhvtovfs(bdp) ( (struct bhv_vfs *)BHV_VOBJ(bdp) ) #define bhvtovfsops(bdp) ( (struct bhv_vfsops *)BHV_OPS(bdp) ) #define VFS_BHVHEAD(vfs) ( &(vfs)->vfs_bh ) @@ -110,14 +108,15 @@ typedef int (*vfs_showargs_t)(bhv_desc_t *, struct seq_file *); typedef int (*vfs_unmount_t)(bhv_desc_t *, int, struct cred *); typedef int (*vfs_mntupdate_t)(bhv_desc_t *, int *, struct xfs_mount_args *); -typedef int (*vfs_root_t)(bhv_desc_t *, struct vnode **); -typedef int (*vfs_statvfs_t)(bhv_desc_t *, xfs_statfs_t *, struct vnode *); +typedef int (*vfs_root_t)(bhv_desc_t *, struct bhv_vnode **); +typedef int (*vfs_statvfs_t)(bhv_desc_t *, xfs_statfs_t *, + struct bhv_vnode *); typedef int (*vfs_sync_t)(bhv_desc_t *, int, struct cred *); -typedef int (*vfs_vget_t)(bhv_desc_t *, struct vnode **, struct fid *); +typedef int (*vfs_vget_t)(bhv_desc_t *, struct bhv_vnode **, struct fid *); typedef int (*vfs_dmapiops_t)(bhv_desc_t *, caddr_t); typedef int (*vfs_quotactl_t)(bhv_desc_t *, int, int, caddr_t); typedef void (*vfs_init_vnode_t)(bhv_desc_t *, - struct vnode *, bhv_desc_t *, int); + struct bhv_vnode *, bhv_desc_t *, int); typedef void (*vfs_force_shutdown_t)(bhv_desc_t *, int, char *, int); typedef void (*vfs_freeze_t)(bhv_desc_t *); @@ -140,26 +139,26 @@ typedef struct bhv_vfsops { } bhv_vfsops_t; /* - * VFS's. Operates on vfs structure pointers (starts at bhv head). + * Virtual filesystem operations, operating from head bhv. */ -#define VHEAD(v) ((v)->vfs_fbhv) -#define bhv_vfs_mount(v, ma,cr) vfs_mount(VHEAD(v), ma,cr) -#define bhv_vfs_parseargs(v, o,ma,f) vfs_parseargs(VHEAD(v), o,ma,f) -#define bhv_vfs_showargs(v, m) vfs_showargs(VHEAD(v), m) -#define bhv_vfs_unmount(v, f,cr) vfs_unmount(VHEAD(v), f,cr) -#define bhv_vfs_mntupdate(v, fl,args) vfs_mntupdate(VHEAD(v), fl,args) -#define bhv_vfs_root(v, vpp) vfs_root(VHEAD(v), vpp) -#define bhv_vfs_statvfs(v, sp,vp) vfs_statvfs(VHEAD(v), sp,vp) -#define bhv_vfs_sync(v, flag,cr) vfs_sync(VHEAD(v), flag,cr) -#define bhv_vfs_vget(v, vpp,fidp) vfs_vget(VHEAD(v), vpp,fidp) -#define bhv_vfs_dmapiops(v, p) vfs_dmapiops(VHEAD(v), p) -#define bhv_vfs_quotactl(v, c,id,p) vfs_quotactl(VHEAD(v), c,id,p) -#define bhv_vfs_init_vnode(v, vp,b,ul) vfs_init_vnode(VHEAD(v), vp,b,ul) -#define bhv_vfs_force_shutdown(v,u,f,l) vfs_force_shutdown(VHEAD(v), u,f,l) -#define bhv_vfs_freeze(v) vfs_freeze(VHEAD(v)) +#define VFSHEAD(v) ((v)->vfs_bh.bh_first) +#define bhv_vfs_mount(v, ma,cr) vfs_mount(VFSHEAD(v), ma,cr) +#define bhv_vfs_parseargs(v, o,ma,f) vfs_parseargs(VFSHEAD(v), o,ma,f) +#define bhv_vfs_showargs(v, m) vfs_showargs(VFSHEAD(v), m) +#define bhv_vfs_unmount(v, f,cr) vfs_unmount(VFSHEAD(v), f,cr) +#define bhv_vfs_mntupdate(v, fl,args) vfs_mntupdate(VFSHEAD(v), fl,args) +#define bhv_vfs_root(v, vpp) vfs_root(VFSHEAD(v), vpp) +#define bhv_vfs_statvfs(v, sp,vp) vfs_statvfs(VFSHEAD(v), sp,vp) +#define bhv_vfs_sync(v, flag,cr) vfs_sync(VFSHEAD(v), flag,cr) +#define bhv_vfs_vget(v, vpp,fidp) vfs_vget(VFSHEAD(v), vpp,fidp) +#define bhv_vfs_dmapiops(v, p) vfs_dmapiops(VFSHEAD(v), p) +#define bhv_vfs_quotactl(v, c,id,p) vfs_quotactl(VFSHEAD(v), c,id,p) +#define bhv_vfs_init_vnode(v, vp,b,ul) vfs_init_vnode(VFSHEAD(v), vp,b,ul) +#define bhv_vfs_force_shutdown(v,u,f,l) vfs_force_shutdown(VFSHEAD(v), u,f,l) +#define bhv_vfs_freeze(v) vfs_freeze(VFSHEAD(v)) /* - * PVFS's. Operates on behavior descriptor pointers. + * Virtual filesystem operations, operating from next bhv. */ #define bhv_next_vfs_mount(b, ma,cr) vfs_mount(b, ma,cr) #define bhv_next_vfs_parseargs(b, o,ma,f) vfs_parseargs(b, o,ma,f) @@ -181,13 +180,13 @@ extern int vfs_parseargs(bhv_desc_t *, char *, struct xfs_mount_args *, int); extern int vfs_showargs(bhv_desc_t *, struct seq_file *); extern int vfs_unmount(bhv_desc_t *, int, struct cred *); extern int vfs_mntupdate(bhv_desc_t *, int *, struct xfs_mount_args *); -extern int vfs_root(bhv_desc_t *, struct vnode **); -extern int vfs_statvfs(bhv_desc_t *, xfs_statfs_t *, struct vnode *); +extern int vfs_root(bhv_desc_t *, struct bhv_vnode **); +extern int vfs_statvfs(bhv_desc_t *, xfs_statfs_t *, struct bhv_vnode *); extern int vfs_sync(bhv_desc_t *, int, struct cred *); -extern int vfs_vget(bhv_desc_t *, struct vnode **, struct fid *); +extern int vfs_vget(bhv_desc_t *, struct bhv_vnode **, struct fid *); extern int vfs_dmapiops(bhv_desc_t *, caddr_t); extern int vfs_quotactl(bhv_desc_t *, int, int, caddr_t); -extern void vfs_init_vnode(bhv_desc_t *, struct vnode *, bhv_desc_t *, int); +extern void vfs_init_vnode(bhv_desc_t *, struct bhv_vnode *, bhv_desc_t *, int); extern void vfs_force_shutdown(bhv_desc_t *, int, char *, int); extern void vfs_freeze(bhv_desc_t *); diff --git a/fs/xfs/linux-2.6/xfs_vnode.c b/fs/xfs/linux-2.6/xfs_vnode.c index 82777f1a70a..66e36e195f2 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.c +++ b/fs/xfs/linux-2.6/xfs_vnode.c @@ -39,7 +39,7 @@ vn_init(void) void vn_iowait( - struct vnode *vp) + bhv_vnode_t *vp) { wait_queue_head_t *wq = vptosync(vp); @@ -48,7 +48,7 @@ vn_iowait( void vn_iowake( - struct vnode *vp) + bhv_vnode_t *vp) { if (atomic_dec_and_test(&vp->v_iocount)) wake_up(vptosync(vp)); @@ -61,7 +61,7 @@ vn_iowake( */ void vn_ioerror( - struct vnode *vp, + bhv_vnode_t *vp, int error, char *f, int l) @@ -70,11 +70,11 @@ vn_ioerror( bhv_vfs_force_shutdown(vp->v_vfsp, SHUTDOWN_DEVICE_REQ, f, l); } -struct vnode * +bhv_vnode_t * vn_initialize( struct inode *inode) { - struct vnode *vp = vn_from_inode(inode); + bhv_vnode_t *vp = vn_from_inode(inode); XFS_STATS_INC(vn_active); XFS_STATS_INC(vn_alloc); @@ -110,7 +110,7 @@ vn_initialize( */ void vn_revalidate_core( - struct vnode *vp, + bhv_vnode_t *vp, vattr_t *vap) { struct inode *inode = vn_to_inode(vp); @@ -146,14 +146,14 @@ vn_revalidate_core( */ int __vn_revalidate( - struct vnode *vp, + bhv_vnode_t *vp, struct vattr *vattr) { int error; vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); vattr->va_mask = XFS_AT_STAT | XFS_AT_XFLAGS; - VOP_GETATTR(vp, vattr, 0, NULL, error); + error = bhv_vop_getattr(vp, vattr, 0, NULL); if (likely(!error)) { vn_revalidate_core(vp, vattr); VUNMODIFY(vp); @@ -163,7 +163,7 @@ __vn_revalidate( int vn_revalidate( - struct vnode *vp) + bhv_vnode_t *vp) { vattr_t vattr; @@ -173,9 +173,9 @@ vn_revalidate( /* * Add a reference to a referenced vnode. */ -struct vnode * +bhv_vnode_t * vn_hold( - struct vnode *vp) + bhv_vnode_t *vp) { struct inode *inode; @@ -208,31 +208,31 @@ vn_hold( * Vnode tracing code. */ void -vn_trace_entry(vnode_t *vp, const char *func, inst_t *ra) +vn_trace_entry(bhv_vnode_t *vp, const char *func, inst_t *ra) { KTRACE_ENTER(vp, VNODE_KTRACE_ENTRY, func, 0, ra); } void -vn_trace_exit(vnode_t *vp, const char *func, inst_t *ra) +vn_trace_exit(bhv_vnode_t *vp, const char *func, inst_t *ra) { KTRACE_ENTER(vp, VNODE_KTRACE_EXIT, func, 0, ra); } void -vn_trace_hold(vnode_t *vp, char *file, int line, inst_t *ra) +vn_trace_hold(bhv_vnode_t *vp, char *file, int line, inst_t *ra) { KTRACE_ENTER(vp, VNODE_KTRACE_HOLD, file, line, ra); } void -vn_trace_ref(vnode_t *vp, char *file, int line, inst_t *ra) +vn_trace_ref(bhv_vnode_t *vp, char *file, int line, inst_t *ra) { KTRACE_ENTER(vp, VNODE_KTRACE_REF, file, line, ra); } void -vn_trace_rele(vnode_t *vp, char *file, int line, inst_t *ra) +vn_trace_rele(bhv_vnode_t *vp, char *file, int line, inst_t *ra) { KTRACE_ENTER(vp, VNODE_KTRACE_RELE, file, line, ra); } diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h index 95343637ab6..cb16774aea7 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.h +++ b/fs/xfs/linux-2.6/xfs_vnode.h @@ -14,33 +14,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Portions Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. */ #ifndef __XFS_VNODE_H__ #define __XFS_VNODE_H__ @@ -51,7 +24,6 @@ struct vattr; struct xfs_iomap; struct attrlist_cursor_kern; - typedef xfs_ino_t vnumber_t; typedef struct dentry vname_t; typedef bhv_head_t vn_bhv_head_t; @@ -66,7 +38,7 @@ typedef enum vflags { * MP locking protocols: * v_flag, v_vfsp VN_LOCK/VN_UNLOCK */ -typedef struct vnode { +typedef struct bhv_vnode { vflags_t v_flag; /* vnode flags (see above) */ struct bhv_vfs *v_vfsp; /* ptr to containing VFS */ vnumber_t v_number; /* in-core vnode number */ @@ -78,7 +50,7 @@ typedef struct vnode { #endif struct inode v_inode; /* Linux inode */ /* inode MUST be last */ -} vnode_t; +} bhv_vnode_t; #define VN_ISLNK(vp) S_ISLNK((vp)->v_inode.i_mode) #define VN_ISREG(vp) S_ISREG((vp)->v_inode.i_mode) @@ -86,9 +58,6 @@ typedef struct vnode { #define VN_ISCHR(vp) S_ISCHR((vp)->v_inode.i_mode) #define VN_ISBLK(vp) S_ISBLK((vp)->v_inode.i_mode) -#define v_fbhv v_bh.bh_first /* first behavior */ -#define v_fops v_bh.bh_first->bd_ops /* first behavior ops */ - #define VNODE_POSITION_BASE BHV_POSITION_BASE /* chain bottom */ #define VNODE_POSITION_TOP BHV_POSITION_TOP /* chain top */ #define VNODE_POSITION_INVALID BHV_POSITION_INVALID /* invalid pos. num */ @@ -110,8 +79,8 @@ typedef enum { /* * Macros for dealing with the behavior descriptor inside of the vnode. */ -#define BHV_TO_VNODE(bdp) ((vnode_t *)BHV_VOBJ(bdp)) -#define BHV_TO_VNODE_NULL(bdp) ((vnode_t *)BHV_VOBJNULL(bdp)) +#define BHV_TO_VNODE(bdp) ((bhv_vnode_t *)BHV_VOBJ(bdp)) +#define BHV_TO_VNODE_NULL(bdp) ((bhv_vnode_t *)BHV_VOBJNULL(bdp)) #define VN_BHV_HEAD(vp) ((bhv_head_t *)(&((vp)->v_bh))) #define vn_bhv_head_init(bhp,name) bhv_head_init(bhp,name) @@ -122,17 +91,17 @@ typedef enum { /* * Vnode to Linux inode mapping. */ -static inline struct vnode *vn_from_inode(struct inode *inode) +static inline struct bhv_vnode *vn_from_inode(struct inode *inode) { - return (vnode_t *)list_entry(inode, vnode_t, v_inode); + return (bhv_vnode_t *)list_entry(inode, bhv_vnode_t, v_inode); } -static inline struct inode *vn_to_inode(struct vnode *vnode) +static inline struct inode *vn_to_inode(struct bhv_vnode *vnode) { return &vnode->v_inode; } /* - * Values for the VOP_RWLOCK and VOP_RWUNLOCK flags parameter. + * Values for the vop_rwlock/rwunlock flags parameter. */ typedef enum vrwlock { VRWLOCK_NONE, @@ -144,7 +113,7 @@ typedef enum vrwlock { } vrwlock_t; /* - * Return values for VOP_INACTIVE. A return value of + * Return values for bhv_vop_inactive. A return value of * VN_INACTIVE_NOCACHE implies that the file system behavior * has disassociated its state and bhv_desc_t from the vnode. */ @@ -152,7 +121,7 @@ typedef enum vrwlock { #define VN_INACTIVE_NOCACHE 1 /* - * Values for the cmd code given to VOP_VNODE_CHANGE. + * Values for the cmd code given to vop_vnode_change. */ typedef enum vchange { VCHANGE_FLAGS_FRLOCKS = 0, @@ -188,22 +157,22 @@ typedef int (*vop_getattr_t)(bhv_desc_t *, struct vattr *, int, typedef int (*vop_setattr_t)(bhv_desc_t *, struct vattr *, int, struct cred *); typedef int (*vop_access_t)(bhv_desc_t *, int, struct cred *); -typedef int (*vop_lookup_t)(bhv_desc_t *, vname_t *, vnode_t **, - int, vnode_t *, struct cred *); +typedef int (*vop_lookup_t)(bhv_desc_t *, vname_t *, bhv_vnode_t **, + int, bhv_vnode_t *, struct cred *); typedef int (*vop_create_t)(bhv_desc_t *, vname_t *, struct vattr *, - vnode_t **, struct cred *); + bhv_vnode_t **, struct cred *); typedef int (*vop_remove_t)(bhv_desc_t *, vname_t *, struct cred *); -typedef int (*vop_link_t)(bhv_desc_t *, vnode_t *, vname_t *, - struct cred *); -typedef int (*vop_rename_t)(bhv_desc_t *, vname_t *, vnode_t *, vname_t *, +typedef int (*vop_link_t)(bhv_desc_t *, bhv_vnode_t *, vname_t *, struct cred *); +typedef int (*vop_rename_t)(bhv_desc_t *, vname_t *, bhv_vnode_t *, + vname_t *, struct cred *); typedef int (*vop_mkdir_t)(bhv_desc_t *, vname_t *, struct vattr *, - vnode_t **, struct cred *); + bhv_vnode_t **, struct cred *); typedef int (*vop_rmdir_t)(bhv_desc_t *, vname_t *, struct cred *); typedef int (*vop_readdir_t)(bhv_desc_t *, struct uio *, struct cred *, int *); typedef int (*vop_symlink_t)(bhv_desc_t *, vname_t *, struct vattr *, - char *, vnode_t **, struct cred *); + char *, bhv_vnode_t **, struct cred *); typedef int (*vop_readlink_t)(bhv_desc_t *, struct uio *, int, struct cred *); typedef int (*vop_fsync_t)(bhv_desc_t *, int, struct cred *, @@ -224,7 +193,7 @@ typedef int (*vop_attr_remove_t)(bhv_desc_t *, const char *, int, struct cred *); typedef int (*vop_attr_list_t)(bhv_desc_t *, char *, int, int, struct attrlist_cursor_kern *, struct cred *); -typedef void (*vop_link_removed_t)(bhv_desc_t *, vnode_t *, int); +typedef void (*vop_link_removed_t)(bhv_desc_t *, bhv_vnode_t *, int); typedef void (*vop_vnode_change_t)(bhv_desc_t *, vchange_t, __psint_t); typedef void (*vop_ptossvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t, int); typedef void (*vop_pflushinvalvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t, int); @@ -233,7 +202,7 @@ typedef int (*vop_pflushvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t, typedef int (*vop_iflush_t)(bhv_desc_t *, int); -typedef struct vnodeops { +typedef struct bhv_vnodeops { bhv_position_t vn_position; /* position within behavior chain */ vop_open_t vop_open; vop_close_t vop_close; @@ -274,105 +243,80 @@ typedef struct vnodeops { vop_pflushvp_t vop_flush_pages; vop_release_t vop_release; vop_iflush_t vop_iflush; -} vnodeops_t; +} bhv_vnodeops_t; /* - * VOP's. - */ -#define _VOP_(op, vp) (*((vnodeops_t *)(vp)->v_fops)->op) - -#define VOP_OPEN(vp, cr, rv) \ - rv = _VOP_(vop_open, vp)((vp)->v_fbhv, cr) -#define VOP_CLOSE(vp, f, last, cr, rv) \ - rv = _VOP_(vop_close, vp)((vp)->v_fbhv, f, last, cr) -#define VOP_READ(vp,file,iov,segs,offset,ioflags,cr,rv) \ - rv = _VOP_(vop_read, vp)((vp)->v_fbhv,file,iov,segs,offset,ioflags,cr) -#define VOP_WRITE(vp,file,iov,segs,offset,ioflags,cr,rv) \ - rv = _VOP_(vop_write, vp)((vp)->v_fbhv,file,iov,segs,offset,ioflags,cr) -#define VOP_SENDFILE(vp,f,off,ioflags,cnt,act,targ,cr,rv) \ - rv = _VOP_(vop_sendfile, vp)((vp)->v_fbhv,f,off,ioflags,cnt,act,targ,cr) -#define VOP_SPLICE_READ(vp,f,o,pipe,cnt,fl,iofl,cr,rv) \ - rv = _VOP_(vop_splice_read, vp)((vp)->v_fbhv,f,o,pipe,cnt,fl,iofl,cr) -#define VOP_SPLICE_WRITE(vp,f,o,pipe,cnt,fl,iofl,cr,rv) \ - rv = _VOP_(vop_splice_write, vp)((vp)->v_fbhv,f,o,pipe,cnt,fl,iofl,cr) -#define VOP_BMAP(vp,of,sz,rw,b,n,rv) \ - rv = _VOP_(vop_bmap, vp)((vp)->v_fbhv,of,sz,rw,b,n) -#define VOP_GETATTR(vp, vap, f, cr, rv) \ - rv = _VOP_(vop_getattr, vp)((vp)->v_fbhv, vap, f, cr) -#define VOP_SETATTR(vp, vap, f, cr, rv) \ - rv = _VOP_(vop_setattr, vp)((vp)->v_fbhv, vap, f, cr) -#define VOP_ACCESS(vp, mode, cr, rv) \ - rv = _VOP_(vop_access, vp)((vp)->v_fbhv, mode, cr) -#define VOP_LOOKUP(vp,d,vpp,f,rdir,cr,rv) \ - rv = _VOP_(vop_lookup, vp)((vp)->v_fbhv,d,vpp,f,rdir,cr) -#define VOP_CREATE(dvp,d,vap,vpp,cr,rv) \ - rv = _VOP_(vop_create, dvp)((dvp)->v_fbhv,d,vap,vpp,cr) -#define VOP_REMOVE(dvp,d,cr,rv) \ - rv = _VOP_(vop_remove, dvp)((dvp)->v_fbhv,d,cr) -#define VOP_LINK(tdvp,fvp,d,cr,rv) \ - rv = _VOP_(vop_link, tdvp)((tdvp)->v_fbhv,fvp,d,cr) -#define VOP_RENAME(fvp,fnm,tdvp,tnm,cr,rv) \ - rv = _VOP_(vop_rename, fvp)((fvp)->v_fbhv,fnm,tdvp,tnm,cr) -#define VOP_MKDIR(dp,d,vap,vpp,cr,rv) \ - rv = _VOP_(vop_mkdir, dp)((dp)->v_fbhv,d,vap,vpp,cr) -#define VOP_RMDIR(dp,d,cr,rv) \ - rv = _VOP_(vop_rmdir, dp)((dp)->v_fbhv,d,cr) -#define VOP_READDIR(vp,uiop,cr,eofp,rv) \ - rv = _VOP_(vop_readdir, vp)((vp)->v_fbhv,uiop,cr,eofp) -#define VOP_SYMLINK(dvp,d,vap,tnm,vpp,cr,rv) \ - rv = _VOP_(vop_symlink, dvp) ((dvp)->v_fbhv,d,vap,tnm,vpp,cr) -#define VOP_READLINK(vp,uiop,fl,cr,rv) \ - rv = _VOP_(vop_readlink, vp)((vp)->v_fbhv,uiop,fl,cr) -#define VOP_FSYNC(vp,f,cr,b,e,rv) \ - rv = _VOP_(vop_fsync, vp)((vp)->v_fbhv,f,cr,b,e) -#define VOP_INACTIVE(vp, cr, rv) \ - rv = _VOP_(vop_inactive, vp)((vp)->v_fbhv, cr) -#define VOP_RELEASE(vp, rv) \ - rv = _VOP_(vop_release, vp)((vp)->v_fbhv) -#define VOP_FID2(vp, fidp, rv) \ - rv = _VOP_(vop_fid2, vp)((vp)->v_fbhv, fidp) -#define VOP_RWLOCK(vp,i) \ - (void)_VOP_(vop_rwlock, vp)((vp)->v_fbhv, i) -#define VOP_RWLOCK_TRY(vp,i) \ - _VOP_(vop_rwlock, vp)((vp)->v_fbhv, i) -#define VOP_RWUNLOCK(vp,i) \ - (void)_VOP_(vop_rwunlock, vp)((vp)->v_fbhv, i) -#define VOP_FRLOCK(vp,c,fl,flags,offset,fr,rv) \ - rv = _VOP_(vop_frlock, vp)((vp)->v_fbhv,c,fl,flags,offset,fr) -#define VOP_RECLAIM(vp, rv) \ - rv = _VOP_(vop_reclaim, vp)((vp)->v_fbhv) -#define VOP_ATTR_GET(vp, name, val, vallenp, fl, cred, rv) \ - rv = _VOP_(vop_attr_get, vp)((vp)->v_fbhv,name,val,vallenp,fl,cred) -#define VOP_ATTR_SET(vp, name, val, vallen, fl, cred, rv) \ - rv = _VOP_(vop_attr_set, vp)((vp)->v_fbhv,name,val,vallen,fl,cred) -#define VOP_ATTR_REMOVE(vp, name, flags, cred, rv) \ - rv = _VOP_(vop_attr_remove, vp)((vp)->v_fbhv,name,flags,cred) -#define VOP_ATTR_LIST(vp, buf, buflen, fl, cursor, cred, rv) \ - rv = _VOP_(vop_attr_list, vp)((vp)->v_fbhv,buf,buflen,fl,cursor,cred) -#define VOP_LINK_REMOVED(vp, dvp, linkzero) \ - (void)_VOP_(vop_link_removed, vp)((vp)->v_fbhv, dvp, linkzero) -#define VOP_VNODE_CHANGE(vp, cmd, val) \ - (void)_VOP_(vop_vnode_change, vp)((vp)->v_fbhv,cmd,val) -/* - * These are page cache functions that now go thru VOPs. - * 'last' parameter is unused and left in for IRIX compatibility - */ -#define VOP_TOSS_PAGES(vp, first, last, fiopt) \ - _VOP_(vop_tosspages, vp)((vp)->v_fbhv,first, last, fiopt) -/* - * 'last' parameter is unused and left in for IRIX compatibility - */ -#define VOP_FLUSHINVAL_PAGES(vp, first, last, fiopt) \ - _VOP_(vop_flushinval_pages, vp)((vp)->v_fbhv,first,last,fiopt) -/* - * 'last' parameter is unused and left in for IRIX compatibility + * Virtual node operations, operating from head bhv. */ -#define VOP_FLUSH_PAGES(vp, first, last, flags, fiopt, rv) \ - rv = _VOP_(vop_flush_pages, vp)((vp)->v_fbhv,first,last,flags,fiopt) -#define VOP_IOCTL(vp, inode, filp, fl, cmd, arg, rv) \ - rv = _VOP_(vop_ioctl, vp)((vp)->v_fbhv,inode,filp,fl,cmd,arg) -#define VOP_IFLUSH(vp, flags, rv) \ - rv = _VOP_(vop_iflush, vp)((vp)->v_fbhv, flags) +#define VNHEAD(vp) ((vp)->v_bh.bh_first) +#define VOP(op, vp) (*((bhv_vnodeops_t *)VNHEAD(vp)->bd_ops)->op) +#define bhv_vop_open(vp, cr) VOP(vop_open, vp)(VNHEAD(vp),cr) +#define bhv_vop_close(vp, f,last,cr) VOP(vop_close, vp)(VNHEAD(vp),f,last,cr) +#define bhv_vop_read(vp,file,iov,segs,offset,ioflags,cr) \ + VOP(vop_read, vp)(VNHEAD(vp),file,iov,segs,offset,ioflags,cr) +#define bhv_vop_write(vp,file,iov,segs,offset,ioflags,cr) \ + VOP(vop_write, vp)(VNHEAD(vp),file,iov,segs,offset,ioflags,cr) +#define bhv_vop_sendfile(vp,f,off,ioflags,cnt,act,targ,cr) \ + VOP(vop_sendfile, vp)(VNHEAD(vp),f,off,ioflags,cnt,act,targ,cr) +#define bhv_vop_splice_read(vp,f,o,pipe,cnt,fl,iofl,cr) \ + VOP(vop_splice_read, vp)(VNHEAD(vp),f,o,pipe,cnt,fl,iofl,cr) +#define bhv_vop_splice_write(vp,f,o,pipe,cnt,fl,iofl,cr) \ + VOP(vop_splice_write, vp)(VNHEAD(vp),f,o,pipe,cnt,fl,iofl,cr) +#define bhv_vop_bmap(vp,of,sz,rw,b,n) \ + VOP(vop_bmap, vp)(VNHEAD(vp),of,sz,rw,b,n) +#define bhv_vop_getattr(vp, vap,f,cr) \ + VOP(vop_getattr, vp)(VNHEAD(vp), vap,f,cr) +#define bhv_vop_setattr(vp, vap,f,cr) \ + VOP(vop_setattr, vp)(VNHEAD(vp), vap,f,cr) +#define bhv_vop_access(vp, mode,cr) VOP(vop_access, vp)(VNHEAD(vp), mode,cr) +#define bhv_vop_lookup(vp,d,vpp,f,rdir,cr) \ + VOP(vop_lookup, vp)(VNHEAD(vp),d,vpp,f,rdir,cr) +#define bhv_vop_create(dvp,d,vap,vpp,cr) \ + VOP(vop_create, dvp)(VNHEAD(dvp),d,vap,vpp,cr) +#define bhv_vop_remove(dvp,d,cr) VOP(vop_remove, dvp)(VNHEAD(dvp),d,cr) +#define bhv_vop_link(dvp,fvp,d,cr) VOP(vop_link, dvp)(VNHEAD(dvp),fvp,d,cr) +#define bhv_vop_rename(fvp,fnm,tdvp,tnm,cr) \ + VOP(vop_rename, fvp)(VNHEAD(fvp),fnm,tdvp,tnm,cr) +#define bhv_vop_mkdir(dp,d,vap,vpp,cr) \ + VOP(vop_mkdir, dp)(VNHEAD(dp),d,vap,vpp,cr) +#define bhv_vop_rmdir(dp,d,cr) VOP(vop_rmdir, dp)(VNHEAD(dp),d,cr) +#define bhv_vop_readdir(vp,uiop,cr,eofp) \ + VOP(vop_readdir, vp)(VNHEAD(vp),uiop,cr,eofp) +#define bhv_vop_symlink(dvp,d,vap,tnm,vpp,cr) \ + VOP(vop_symlink, dvp)(VNHEAD(dvp),d,vap,tnm,vpp,cr) +#define bhv_vop_readlink(vp,uiop,fl,cr) \ + VOP(vop_readlink, vp)(VNHEAD(vp),uiop,fl,cr) +#define bhv_vop_fsync(vp,f,cr,b,e) VOP(vop_fsync, vp)(VNHEAD(vp),f,cr,b,e) +#define bhv_vop_inactive(vp,cr) VOP(vop_inactive, vp)(VNHEAD(vp),cr) +#define bhv_vop_release(vp) VOP(vop_release, vp)(VNHEAD(vp)) +#define bhv_vop_fid2(vp,fidp) VOP(vop_fid2, vp)(VNHEAD(vp),fidp) +#define bhv_vop_rwlock(vp,i) VOP(vop_rwlock, vp)(VNHEAD(vp),i) +#define bhv_vop_rwlock_try(vp,i) VOP(vop_rwlock, vp)(VNHEAD(vp),i) +#define bhv_vop_rwunlock(vp,i) VOP(vop_rwunlock, vp)(VNHEAD(vp),i) +#define bhv_vop_frlock(vp,c,fl,flags,offset,fr) \ + VOP(vop_frlock, vp)(VNHEAD(vp),c,fl,flags,offset,fr) +#define bhv_vop_reclaim(vp) VOP(vop_reclaim, vp)(VNHEAD(vp)) +#define bhv_vop_attr_get(vp, name, val, vallenp, fl, cred) \ + VOP(vop_attr_get, vp)(VNHEAD(vp),name,val,vallenp,fl,cred) +#define bhv_vop_attr_set(vp, name, val, vallen, fl, cred) \ + VOP(vop_attr_set, vp)(VNHEAD(vp),name,val,vallen,fl,cred) +#define bhv_vop_attr_remove(vp, name, flags, cred) \ + VOP(vop_attr_remove, vp)(VNHEAD(vp),name,flags,cred) +#define bhv_vop_attr_list(vp, buf, buflen, fl, cursor, cred) \ + VOP(vop_attr_list, vp)(VNHEAD(vp),buf,buflen,fl,cursor,cred) +#define bhv_vop_link_removed(vp, dvp, linkzero) \ + VOP(vop_link_removed, vp)(VNHEAD(vp), dvp, linkzero) +#define bhv_vop_vnode_change(vp, cmd, val) \ + VOP(vop_vnode_change, vp)(VNHEAD(vp), cmd, val) +#define bhv_vop_toss_pages(vp, first, last, fiopt) \ + VOP(vop_tosspages, vp)(VNHEAD(vp), first, last, fiopt) +#define bhv_vop_flushinval_pages(vp, first, last, fiopt) \ + VOP(vop_flushinval_pages, vp)(VNHEAD(vp),first,last,fiopt) +#define bhv_vop_flush_pages(vp, first, last, flags, fiopt) \ + VOP(vop_flush_pages, vp)(VNHEAD(vp),first,last,flags,fiopt) +#define bhv_vop_ioctl(vp, inode, filp, fl, cmd, arg) \ + VOP(vop_ioctl, vp)(VNHEAD(vp),inode,filp,fl,cmd,arg) +#define bhv_vop_iflush(vp, flags) VOP(vop_iflush, vp)(VNHEAD(vp), flags) /* * Flags for read/write calls - same values as IRIX @@ -382,7 +326,7 @@ typedef struct vnodeops { #define IO_INVIS 0x00020 /* don't update inode timestamps */ /* - * Flags for VOP_IFLUSH call + * Flags for vop_iflush call */ #define FLUSH_SYNC 1 /* wait for flush to complete */ #define FLUSH_INODE 2 /* flush the inode itself */ @@ -390,8 +334,7 @@ typedef struct vnodeops { * this inode out to disk */ /* - * Flush/Invalidate options for VOP_TOSS_PAGES, VOP_FLUSHINVAL_PAGES and - * VOP_FLUSH_PAGES. + * Flush/Invalidate options for vop_toss/flush/flushinval_pages. */ #define FI_NONE 0 /* none */ #define FI_REMAPF 1 /* Do a remapf prior to the operation */ @@ -497,31 +440,17 @@ typedef struct vattr { (VN_ISREG(vp) && ((mode) & (VSGID|(VEXEC>>3))) == VSGID) extern void vn_init(void); -extern vnode_t *vn_initialize(struct inode *); - -/* - * vnode_map structures _must_ match vn_epoch and vnode structure sizes. - */ -typedef struct vnode_map { - bhv_vfs_t *v_vfsp; - vnumber_t v_number; /* in-core vnode number */ - xfs_ino_t v_ino; /* inode # */ -} vmap_t; - -#define VMAP(vp, vmap) {(vmap).v_vfsp = (vp)->v_vfsp, \ - (vmap).v_number = (vp)->v_number, \ - (vmap).v_ino = (vp)->v_inode.i_ino; } - -extern int vn_revalidate(struct vnode *); -extern int __vn_revalidate(struct vnode *, vattr_t *); -extern void vn_revalidate_core(struct vnode *, vattr_t *); +extern bhv_vnode_t *vn_initialize(struct inode *); +extern int vn_revalidate(struct bhv_vnode *); +extern int __vn_revalidate(struct bhv_vnode *, vattr_t *); +extern void vn_revalidate_core(struct bhv_vnode *, vattr_t *); -extern void vn_iowait(struct vnode *vp); -extern void vn_iowake(struct vnode *vp); +extern void vn_iowait(struct bhv_vnode *vp); +extern void vn_iowake(struct bhv_vnode *vp); -extern void vn_ioerror(struct vnode *vp, int error, char *f, int l); +extern void vn_ioerror(struct bhv_vnode *vp, int error, char *f, int l); -static inline int vn_count(struct vnode *vp) +static inline int vn_count(struct bhv_vnode *vp) { return atomic_read(&vn_to_inode(vp)->i_count); } @@ -529,7 +458,7 @@ static inline int vn_count(struct vnode *vp) /* * Vnode reference counting functions (and macros for compatibility). */ -extern vnode_t *vn_hold(struct vnode *); +extern bhv_vnode_t *vn_hold(struct bhv_vnode *); #if defined(XFS_VNODE_TRACE) #define VN_HOLD(vp) \ @@ -543,7 +472,7 @@ extern vnode_t *vn_hold(struct vnode *); #define VN_RELE(vp) (iput(vn_to_inode(vp))) #endif -static inline struct vnode *vn_grab(struct vnode *vp) +static inline struct bhv_vnode *vn_grab(struct bhv_vnode *vp) { struct inode *inode = igrab(vn_to_inode(vp)); return inode ? vn_from_inode(inode) : NULL; @@ -562,14 +491,14 @@ static inline struct vnode *vn_grab(struct vnode *vp) #define VN_LOCK(vp) mutex_spinlock(&(vp)->v_lock) #define VN_UNLOCK(vp, s) mutex_spinunlock(&(vp)->v_lock, s) -static __inline__ void vn_flagset(struct vnode *vp, uint flag) +static __inline__ void vn_flagset(struct bhv_vnode *vp, uint flag) { spin_lock(&vp->v_lock); vp->v_flag |= flag; spin_unlock(&vp->v_lock); } -static __inline__ uint vn_flagclr(struct vnode *vp, uint flag) +static __inline__ uint vn_flagclr(struct bhv_vnode *vp, uint flag) { uint cleared; @@ -588,12 +517,12 @@ static __inline__ uint vn_flagclr(struct vnode *vp, uint flag) /* * Dealing with bad inodes */ -static inline void vn_mark_bad(struct vnode *vp) +static inline void vn_mark_bad(struct bhv_vnode *vp) { make_bad_inode(vn_to_inode(vp)); } -static inline int VN_BAD(struct vnode *vp) +static inline int VN_BAD(struct bhv_vnode *vp) { return is_bad_inode(vn_to_inode(vp)); } @@ -601,18 +530,18 @@ static inline int VN_BAD(struct vnode *vp) /* * Extracting atime values in various formats */ -static inline void vn_atime_to_bstime(struct vnode *vp, xfs_bstime_t *bs_atime) +static inline void vn_atime_to_bstime(bhv_vnode_t *vp, xfs_bstime_t *bs_atime) { bs_atime->tv_sec = vp->v_inode.i_atime.tv_sec; bs_atime->tv_nsec = vp->v_inode.i_atime.tv_nsec; } -static inline void vn_atime_to_timespec(struct vnode *vp, struct timespec *ts) +static inline void vn_atime_to_timespec(bhv_vnode_t *vp, struct timespec *ts) { *ts = vp->v_inode.i_atime; } -static inline void vn_atime_to_time_t(struct vnode *vp, time_t *tt) +static inline void vn_atime_to_time_t(bhv_vnode_t *vp, time_t *tt) { *tt = vp->v_inode.i_atime.tv_sec; } @@ -627,7 +556,7 @@ static inline void vn_atime_to_time_t(struct vnode *vp, time_t *tt) #define VN_TRUNC(vp) ((vp)->v_flag & VTRUNCATED) /* - * Flags to VOP_SETATTR/VOP_GETATTR. + * Flags to vop_setattr/getattr. */ #define ATTR_UTIME 0x01 /* non-default utime(2) request */ #define ATTR_DMI 0x08 /* invocation from a DMI function */ @@ -637,7 +566,7 @@ static inline void vn_atime_to_time_t(struct vnode *vp, time_t *tt) #define ATTR_NOSIZETOK 0x400 /* Don't get the SIZE token */ /* - * Flags to VOP_FSYNC and VOP_RECLAIM. + * Flags to vop_fsync/reclaim. */ #define FSYNC_NOWAIT 0 /* asynchronous flush */ #define FSYNC_WAIT 0x1 /* synchronous fsync or forced reclaim */ @@ -656,11 +585,11 @@ static inline void vn_atime_to_time_t(struct vnode *vp, time_t *tt) #define VNODE_KTRACE_REF 4 #define VNODE_KTRACE_RELE 5 -extern void vn_trace_entry(struct vnode *, const char *, inst_t *); -extern void vn_trace_exit(struct vnode *, const char *, inst_t *); -extern void vn_trace_hold(struct vnode *, char *, int, inst_t *); -extern void vn_trace_ref(struct vnode *, char *, int, inst_t *); -extern void vn_trace_rele(struct vnode *, char *, int, inst_t *); +extern void vn_trace_entry(struct bhv_vnode *, const char *, inst_t *); +extern void vn_trace_exit(struct bhv_vnode *, const char *, inst_t *); +extern void vn_trace_hold(struct bhv_vnode *, char *, int, inst_t *); +extern void vn_trace_ref(struct bhv_vnode *, char *, int, inst_t *); +extern void vn_trace_rele(struct bhv_vnode *, char *, int, inst_t *); #define VN_TRACE(vp) \ vn_trace_ref(vp, __FILE__, __LINE__, (inst_t *)__return_address) diff --git a/fs/xfs/quota/xfs_qm_bhv.c b/fs/xfs/quota/xfs_qm_bhv.c index 78f5962e578..ad9ab104946 100644 --- a/fs/xfs/quota/xfs_qm_bhv.c +++ b/fs/xfs/quota/xfs_qm_bhv.c @@ -192,7 +192,7 @@ STATIC int xfs_qm_statvfs( struct bhv_desc *bhv, xfs_statfs_t *statp, - struct vnode *vnode) + struct bhv_vnode *vnode) { xfs_mount_t *mp; xfs_inode_t *ip; diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c index afc7c1c696b..c93072be679 100644 --- a/fs/xfs/quota/xfs_qm_syscalls.c +++ b/fs/xfs/quota/xfs_qm_syscalls.c @@ -1035,7 +1035,7 @@ xfs_qm_dqrele_all_inodes( { xfs_inode_t *ip, *topino; uint ireclaims; - vnode_t *vp; + bhv_vnode_t *vp; boolean_t vnode_refd; ASSERT(mp->m_quotainfo); diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c index 2539af34eb6..8c300da4e7a 100644 --- a/fs/xfs/xfs_acl.c +++ b/fs/xfs/xfs_acl.c @@ -39,15 +39,15 @@ #include #include -STATIC int xfs_acl_setmode(vnode_t *, xfs_acl_t *, int *); +STATIC int xfs_acl_setmode(bhv_vnode_t *, xfs_acl_t *, int *); STATIC void xfs_acl_filter_mode(mode_t, xfs_acl_t *); STATIC void xfs_acl_get_endian(xfs_acl_t *); STATIC int xfs_acl_access(uid_t, gid_t, xfs_acl_t *, mode_t, cred_t *); STATIC int xfs_acl_invalid(xfs_acl_t *); STATIC void xfs_acl_sync_mode(mode_t, xfs_acl_t *); -STATIC void xfs_acl_get_attr(vnode_t *, xfs_acl_t *, int, int, int *); -STATIC void xfs_acl_set_attr(vnode_t *, xfs_acl_t *, int, int *); -STATIC int xfs_acl_allow_set(vnode_t *, int); +STATIC void xfs_acl_get_attr(bhv_vnode_t *, xfs_acl_t *, int, int, int *); +STATIC void xfs_acl_set_attr(bhv_vnode_t *, xfs_acl_t *, int, int *); +STATIC int xfs_acl_allow_set(bhv_vnode_t *, int); kmem_zone_t *xfs_acl_zone; @@ -57,7 +57,7 @@ kmem_zone_t *xfs_acl_zone; */ int xfs_acl_vhasacl_access( - vnode_t *vp) + bhv_vnode_t *vp) { int error; @@ -70,7 +70,7 @@ xfs_acl_vhasacl_access( */ int xfs_acl_vhasacl_default( - vnode_t *vp) + bhv_vnode_t *vp) { int error; @@ -209,7 +209,7 @@ posix_acl_xfs_to_xattr( int xfs_acl_vget( - vnode_t *vp, + bhv_vnode_t *vp, void *acl, size_t size, int kind) @@ -244,7 +244,7 @@ xfs_acl_vget( vattr_t va; va.va_mask = XFS_AT_MODE; - VOP_GETATTR(vp, &va, 0, sys_cred, error); + error = bhv_vop_getattr(vp, &va, 0, sys_cred); if (error) goto out; xfs_acl_sync_mode(va.va_mode, xfs_acl); @@ -260,7 +260,7 @@ out: int xfs_acl_vremove( - vnode_t *vp, + bhv_vnode_t *vp, int kind) { int error; @@ -268,9 +268,9 @@ xfs_acl_vremove( VN_HOLD(vp); error = xfs_acl_allow_set(vp, kind); if (!error) { - VOP_ATTR_REMOVE(vp, kind == _ACL_TYPE_DEFAULT? - SGI_ACL_DEFAULT: SGI_ACL_FILE, - ATTR_ROOT, sys_cred, error); + error = bhv_vop_attr_remove(vp, kind == _ACL_TYPE_DEFAULT? + SGI_ACL_DEFAULT: SGI_ACL_FILE, + ATTR_ROOT, sys_cred); if (error == ENOATTR) error = 0; /* 'scool */ } @@ -280,7 +280,7 @@ xfs_acl_vremove( int xfs_acl_vset( - vnode_t *vp, + bhv_vnode_t *vp, void *acl, size_t size, int kind) @@ -370,7 +370,7 @@ xfs_acl_iaccess( STATIC int xfs_acl_allow_set( - vnode_t *vp, + bhv_vnode_t *vp, int kind) { vattr_t va; @@ -383,7 +383,7 @@ xfs_acl_allow_set( if (vp->v_vfsp->vfs_flag & VFS_RDONLY) return EROFS; va.va_mask = XFS_AT_UID; - VOP_GETATTR(vp, &va, 0, NULL, error); + error = bhv_vop_getattr(vp, &va, 0, NULL); if (error) return error; if (va.va_uid != current->fsuid && !capable(CAP_FOWNER)) @@ -606,7 +606,7 @@ xfs_acl_get_endian( */ STATIC void xfs_acl_get_attr( - vnode_t *vp, + bhv_vnode_t *vp, xfs_acl_t *aclp, int kind, int flags, @@ -616,9 +616,9 @@ xfs_acl_get_attr( ASSERT((flags & ATTR_KERNOVAL) ? (aclp == NULL) : 1); flags |= ATTR_ROOT; - VOP_ATTR_GET(vp, - kind == _ACL_TYPE_ACCESS ? SGI_ACL_FILE : SGI_ACL_DEFAULT, - (char *)aclp, &len, flags, sys_cred, *error); + *error = bhv_vop_attr_get(vp, kind == _ACL_TYPE_ACCESS ? + SGI_ACL_FILE : SGI_ACL_DEFAULT, + (char *)aclp, &len, flags, sys_cred); if (*error || (flags & ATTR_KERNOVAL)) return; xfs_acl_get_endian(aclp); @@ -629,7 +629,7 @@ xfs_acl_get_attr( */ STATIC void xfs_acl_set_attr( - vnode_t *vp, + bhv_vnode_t *vp, xfs_acl_t *aclp, int kind, int *error) @@ -654,15 +654,15 @@ xfs_acl_set_attr( INT_SET(newace->ae_perm, ARCH_CONVERT, ace->ae_perm); } INT_SET(newacl->acl_cnt, ARCH_CONVERT, aclp->acl_cnt); - VOP_ATTR_SET(vp, - kind == _ACL_TYPE_ACCESS ? SGI_ACL_FILE: SGI_ACL_DEFAULT, - (char *)newacl, len, ATTR_ROOT, sys_cred, *error); + *error = bhv_vop_attr_set(vp, kind == _ACL_TYPE_ACCESS ? + SGI_ACL_FILE: SGI_ACL_DEFAULT, + (char *)newacl, len, ATTR_ROOT, sys_cred); _ACL_FREE(newacl); } int xfs_acl_vtoacl( - vnode_t *vp, + bhv_vnode_t *vp, xfs_acl_t *access_acl, xfs_acl_t *default_acl) { @@ -678,7 +678,7 @@ xfs_acl_vtoacl( if (!error) { /* Got the ACL, need the mode... */ va.va_mask = XFS_AT_MODE; - VOP_GETATTR(vp, &va, 0, sys_cred, error); + error = bhv_vop_getattr(vp, &va, 0, sys_cred); } if (error) @@ -701,7 +701,7 @@ xfs_acl_vtoacl( */ int xfs_acl_inherit( - vnode_t *vp, + bhv_vnode_t *vp, vattr_t *vap, xfs_acl_t *pdaclp) { @@ -757,7 +757,7 @@ xfs_acl_inherit( */ STATIC int xfs_acl_setmode( - vnode_t *vp, + bhv_vnode_t *vp, xfs_acl_t *acl, int *basicperms) { @@ -776,7 +776,7 @@ xfs_acl_setmode( * mode. The m:: bits take precedence over the g:: bits. */ va.va_mask = XFS_AT_MODE; - VOP_GETATTR(vp, &va, 0, sys_cred, error); + error = bhv_vop_getattr(vp, &va, 0, sys_cred); if (error) return error; @@ -810,8 +810,7 @@ xfs_acl_setmode( if (gap && nomask) va.va_mode |= gap->ae_perm << 3; - VOP_SETATTR(vp, &va, 0, sys_cred, error); - return error; + return bhv_vop_setattr(vp, &va, 0, sys_cred); } /* diff --git a/fs/xfs/xfs_acl.h b/fs/xfs/xfs_acl.h index 538d0d65b04..a57ff4e6d39 100644 --- a/fs/xfs/xfs_acl.h +++ b/fs/xfs/xfs_acl.h @@ -50,7 +50,7 @@ typedef struct xfs_acl { #ifdef CONFIG_XFS_POSIX_ACL struct vattr; -struct vnode; +struct bhv_vnode; struct xfs_inode; extern struct kmem_zone *xfs_acl_zone; @@ -58,14 +58,14 @@ extern struct kmem_zone *xfs_acl_zone; (zone) = kmem_zone_init(sizeof(xfs_acl_t), (name)) #define xfs_acl_zone_destroy(zone) kmem_zone_destroy(zone) -extern int xfs_acl_inherit(struct vnode *, struct vattr *, xfs_acl_t *); +extern int xfs_acl_inherit(struct bhv_vnode *, struct vattr *, xfs_acl_t *); extern int xfs_acl_iaccess(struct xfs_inode *, mode_t, cred_t *); -extern int xfs_acl_vtoacl(struct vnode *, xfs_acl_t *, xfs_acl_t *); -extern int xfs_acl_vhasacl_access(struct vnode *); -extern int xfs_acl_vhasacl_default(struct vnode *); -extern int xfs_acl_vset(struct vnode *, void *, size_t, int); -extern int xfs_acl_vget(struct vnode *, void *, size_t, int); -extern int xfs_acl_vremove(struct vnode *vp, int); +extern int xfs_acl_vtoacl(struct bhv_vnode *, xfs_acl_t *, xfs_acl_t *); +extern int xfs_acl_vhasacl_access(struct bhv_vnode *); +extern int xfs_acl_vhasacl_default(struct bhv_vnode *); +extern int xfs_acl_vset(struct bhv_vnode *, void *, size_t, int); +extern int xfs_acl_vget(struct bhv_vnode *, void *, size_t, int); +extern int xfs_acl_vremove(struct bhv_vnode *, int); #define _ACL_TYPE_ACCESS 1 #define _ACL_TYPE_DEFAULT 2 diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c index 3ef41e75d08..4dcef8d1c32 100644 --- a/fs/xfs/xfs_attr.c +++ b/fs/xfs/xfs_attr.c @@ -2324,56 +2324,56 @@ xfs_attr_trace_enter(int type, char *where, STATIC int posix_acl_access_set( - vnode_t *vp, char *name, void *data, size_t size, int xflags) + bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags) { return xfs_acl_vset(vp, data, size, _ACL_TYPE_ACCESS); } STATIC int posix_acl_access_remove( - struct vnode *vp, char *name, int xflags) + bhv_vnode_t *vp, char *name, int xflags) { return xfs_acl_vremove(vp, _ACL_TYPE_ACCESS); } STATIC int posix_acl_access_get( - vnode_t *vp, char *name, void *data, size_t size, int xflags) + bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags) { return xfs_acl_vget(vp, data, size, _ACL_TYPE_ACCESS); } STATIC int posix_acl_access_exists( - vnode_t *vp) + bhv_vnode_t *vp) { return xfs_acl_vhasacl_access(vp); } STATIC int posix_acl_default_set( - vnode_t *vp, char *name, void *data, size_t size, int xflags) + bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags) { return xfs_acl_vset(vp, data, size, _ACL_TYPE_DEFAULT); } STATIC int posix_acl_default_get( - vnode_t *vp, char *name, void *data, size_t size, int xflags) + bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags) { return xfs_acl_vget(vp, data, size, _ACL_TYPE_DEFAULT); } STATIC int posix_acl_default_remove( - struct vnode *vp, char *name, int xflags) + bhv_vnode_t *vp, char *name, int xflags) { return xfs_acl_vremove(vp, _ACL_TYPE_DEFAULT); } STATIC int posix_acl_default_exists( - vnode_t *vp) + bhv_vnode_t *vp) { return xfs_acl_vhasacl_default(vp); } @@ -2406,21 +2406,18 @@ STATIC struct attrnames *attr_system_names[] = STATIC int attr_generic_set( - struct vnode *vp, char *name, void *data, size_t size, int xflags) + bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags) { - int error; - - VOP_ATTR_SET(vp, name, data, size, xflags, NULL, error); - return -error; + return -bhv_vop_attr_set(vp, name, data, size, xflags, NULL); } STATIC int attr_generic_get( - struct vnode *vp, char *name, void *data, size_t size, int xflags) + bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags) { int error, asize = size; - VOP_ATTR_GET(vp, name, data, &asize, xflags, NULL, error); + error = bhv_vop_attr_get(vp, name, data, &asize, xflags, NULL); if (!error) return asize; return -error; @@ -2428,12 +2425,9 @@ attr_generic_get( STATIC int attr_generic_remove( - struct vnode *vp, char *name, int xflags) + bhv_vnode_t *vp, char *name, int xflags) { - int error; - - VOP_ATTR_REMOVE(vp, name, xflags, NULL, error); - return -error; + return -bhv_vop_attr_remove(vp, name, xflags, NULL); } STATIC int @@ -2461,7 +2455,7 @@ attr_generic_listadd( STATIC int attr_system_list( - struct vnode *vp, + bhv_vnode_t *vp, void *data, size_t size, ssize_t *result) @@ -2483,12 +2477,12 @@ attr_system_list( int attr_generic_list( - struct vnode *vp, void *data, size_t size, int xflags, ssize_t *result) + bhv_vnode_t *vp, void *data, size_t size, int xflags, ssize_t *result) { attrlist_cursor_kern_t cursor = { 0 }; int error; - VOP_ATTR_LIST(vp, data, size, xflags, &cursor, NULL, error); + error = bhv_vop_attr_list(vp, data, size, xflags, &cursor, NULL); if (error > 0) return -error; *result = -error; @@ -2516,7 +2510,7 @@ attr_lookup_namespace( */ STATIC int attr_user_capable( - struct vnode *vp, + bhv_vnode_t *vp, cred_t *cred) { struct inode *inode = vn_to_inode(vp); @@ -2534,7 +2528,7 @@ attr_user_capable( STATIC int attr_trusted_capable( - struct vnode *vp, + bhv_vnode_t *vp, cred_t *cred) { struct inode *inode = vn_to_inode(vp); @@ -2548,7 +2542,7 @@ attr_trusted_capable( STATIC int attr_secure_capable( - struct vnode *vp, + bhv_vnode_t *vp, cred_t *cred) { return -ENOSECURITY; @@ -2556,7 +2550,7 @@ attr_secure_capable( STATIC int attr_system_set( - struct vnode *vp, char *name, void *data, size_t size, int xflags) + bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags) { attrnames_t *namesp; int error; @@ -2575,7 +2569,7 @@ attr_system_set( STATIC int attr_system_get( - struct vnode *vp, char *name, void *data, size_t size, int xflags) + bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags) { attrnames_t *namesp; @@ -2587,7 +2581,7 @@ attr_system_get( STATIC int attr_system_remove( - struct vnode *vp, char *name, int xflags) + bhv_vnode_t *vp, char *name, int xflags) { attrnames_t *namesp; diff --git a/fs/xfs/xfs_attr.h b/fs/xfs/xfs_attr.h index b2c7b9fcded..981633f6c07 100644 --- a/fs/xfs/xfs_attr.h +++ b/fs/xfs/xfs_attr.h @@ -36,13 +36,13 @@ *========================================================================*/ struct cred; -struct vnode; +struct bhv_vnode; -typedef int (*attrset_t)(struct vnode *, char *, void *, size_t, int); -typedef int (*attrget_t)(struct vnode *, char *, void *, size_t, int); -typedef int (*attrremove_t)(struct vnode *, char *, int); -typedef int (*attrexists_t)(struct vnode *); -typedef int (*attrcapable_t)(struct vnode *, struct cred *); +typedef int (*attrset_t)(struct bhv_vnode *, char *, void *, size_t, int); +typedef int (*attrget_t)(struct bhv_vnode *, char *, void *, size_t, int); +typedef int (*attrremove_t)(struct bhv_vnode *, char *, int); +typedef int (*attrexists_t)(struct bhv_vnode *); +typedef int (*attrcapable_t)(struct bhv_vnode *, struct cred *); typedef struct attrnames { char * attr_name; @@ -63,7 +63,7 @@ extern struct attrnames attr_trusted; extern struct attrnames *attr_namespaces[ATTR_NAMECOUNT]; extern attrnames_t *attr_lookup_namespace(char *, attrnames_t **, int); -extern int attr_generic_list(struct vnode *, void *, size_t, int, ssize_t *); +extern int attr_generic_list(struct bhv_vnode *, void *, size_t, int, ssize_t *); #define ATTR_DONTFOLLOW 0x0001 /* -- unused, from IRIX -- */ #define ATTR_ROOT 0x0002 /* use attrs in root (trusted) namespace */ diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index b4529421823..3050b4c647c 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -5759,7 +5759,7 @@ xfs_getbmap( __int64_t fixlen; /* length for -1 case */ int i; /* extent number */ xfs_inode_t *ip; /* xfs incore inode pointer */ - vnode_t *vp; /* corresponding vnode */ + bhv_vnode_t *vp; /* corresponding vnode */ int lock; /* lock state */ xfs_bmbt_irec_t *map; /* buffer for user's data */ xfs_mount_t *mp; /* file system mount point */ @@ -5856,7 +5856,7 @@ xfs_getbmap( if (whichfork == XFS_DATA_FORK && ip->i_delayed_blks) { /* xfs_fsize_t last_byte = xfs_file_last_byte(ip); */ - VOP_FLUSH_PAGES(vp, (xfs_off_t)0, -1, 0, FI_REMAPF, error); + error = bhv_vop_flush_pages(vp, (xfs_off_t)0, -1, 0, FI_REMAPF); } ASSERT(whichfork == XFS_ATTR_FORK || ip->i_delayed_blks == 0); diff --git a/fs/xfs/xfs_cap.h b/fs/xfs/xfs_cap.h index d0035c6e951..7a0e482dd43 100644 --- a/fs/xfs/xfs_cap.h +++ b/fs/xfs/xfs_cap.h @@ -49,12 +49,12 @@ typedef struct xfs_cap_set { #include -struct vnode; +struct bhv_vnode; -extern int xfs_cap_vhascap(struct vnode *); -extern int xfs_cap_vset(struct vnode *, void *, size_t); -extern int xfs_cap_vget(struct vnode *, void *, size_t); -extern int xfs_cap_vremove(struct vnode *vp); +extern int xfs_cap_vhascap(struct bhv_vnode *); +extern int xfs_cap_vset(struct bhv_vnode *, void *, size_t); +extern int xfs_cap_vget(struct bhv_vnode *, void *, size_t); +extern int xfs_cap_vremove(struct bhv_vnode *); #define _CAP_EXISTS xfs_cap_vhascap diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c index 99daf8c0f90..29a6c866f2c 100644 --- a/fs/xfs/xfs_dfrag.c +++ b/fs/xfs/xfs_dfrag.c @@ -57,7 +57,7 @@ xfs_swapext( xfs_inode_t *ip=NULL, *tip=NULL; xfs_mount_t *mp; struct file *fp = NULL, *tfp = NULL; - vnode_t *vp, *tvp; + bhv_vnode_t *vp, *tvp; int error = 0; sxp = kmem_alloc(sizeof(xfs_swapext_t), KM_MAYFAIL); @@ -137,7 +137,7 @@ xfs_swap_extents( xfs_inode_t *ips[2]; xfs_trans_t *tp; xfs_bstat_t *sbp = &sxp->sx_stat; - vnode_t *vp, *tvp; + bhv_vnode_t *vp, *tvp; xfs_ifork_t *tempifp, *ifp, *tifp; int ilf_fields, tilf_fields; static uint lock_flags = XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL; @@ -202,7 +202,7 @@ xfs_swap_extents( if (VN_CACHED(tvp) != 0) { xfs_inval_cached_trace(&tip->i_iocore, 0, -1, 0, -1); - VOP_FLUSHINVAL_PAGES(tvp, 0, -1, FI_REMAPF_LOCKED); + bhv_vop_flushinval_pages(tvp, 0, -1, FI_REMAPF_LOCKED); } /* Verify O_DIRECT for ftmp */ @@ -247,7 +247,7 @@ xfs_swap_extents( /* We need to fail if the file is memory mapped. Once we have tossed * all existing pages, the page fault will have no option * but to go to the filesystem for pages. By making the page fault call - * VOP_READ (or write in the case of autogrow) they block on the iolock + * vop_read (or write in the case of autogrow) they block on the iolock * until we have switched the extents. */ if (VN_MAPPED(vp)) { @@ -266,7 +266,7 @@ xfs_swap_extents( * fields change. */ - VOP_TOSS_PAGES(vp, 0, -1, FI_REMAPF); + bhv_vop_toss_pages(vp, 0, -1, FI_REMAPF); tp = xfs_trans_alloc(mp, XFS_TRANS_SWAPEXT); if ((error = xfs_trans_reserve(tp, 0, diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index 41f38eb60eb..da3c94c230d 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c @@ -186,7 +186,7 @@ xfs_ihash_promote( */ STATIC int xfs_iget_core( - vnode_t *vp, + bhv_vnode_t *vp, xfs_mount_t *mp, xfs_trans_t *tp, xfs_ino_t ino, @@ -198,7 +198,7 @@ xfs_iget_core( xfs_ihash_t *ih; xfs_inode_t *ip; xfs_inode_t *iq; - vnode_t *inode_vp; + bhv_vnode_t *inode_vp; ulong version; int error; /* REFERENCED */ @@ -489,7 +489,7 @@ xfs_iget( xfs_daddr_t bno) { struct inode *inode; - vnode_t *vp = NULL; + bhv_vnode_t *vp = NULL; int error; XFS_STATS_INC(xs_ig_attempts); @@ -543,7 +543,7 @@ retry: void xfs_inode_lock_init( xfs_inode_t *ip, - vnode_t *vp) + bhv_vnode_t *vp) { mrlock_init(&ip->i_lock, MRLOCK_ALLOW_EQUAL_PRI|MRLOCK_BARRIER, "xfsino", (long)vp->v_number); @@ -603,12 +603,10 @@ void xfs_iput(xfs_inode_t *ip, uint lock_flags) { - vnode_t *vp = XFS_ITOV(ip); + bhv_vnode_t *vp = XFS_ITOV(ip); vn_trace_entry(vp, "xfs_iput", (inst_t *)__return_address); - xfs_iunlock(ip, lock_flags); - VN_RELE(vp); } @@ -619,7 +617,7 @@ void xfs_iput_new(xfs_inode_t *ip, uint lock_flags) { - vnode_t *vp = XFS_ITOV(ip); + bhv_vnode_t *vp = XFS_ITOV(ip); struct inode *inode = vn_to_inode(vp); vn_trace_entry(vp, "xfs_iput_new", (inst_t *)__return_address); @@ -645,7 +643,7 @@ xfs_iput_new(xfs_inode_t *ip, void xfs_ireclaim(xfs_inode_t *ip) { - vnode_t *vp; + bhv_vnode_t *vp; /* * Remove from old hash list and mount list. diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 0ed707ed664..848783ba565 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -1086,7 +1086,7 @@ xfs_ialloc( { xfs_ino_t ino; xfs_inode_t *ip; - vnode_t *vp; + bhv_vnode_t *vp; uint flags; int error; @@ -1427,7 +1427,7 @@ xfs_itruncate_start( xfs_fsize_t last_byte; xfs_off_t toss_start; xfs_mount_t *mp; - vnode_t *vp; + bhv_vnode_t *vp; ASSERT(ismrlocked(&ip->i_iolock, MR_UPDATE) != 0); ASSERT((new_size == 0) || (new_size <= ip->i_d.di_size)); @@ -1440,9 +1440,9 @@ xfs_itruncate_start( vn_iowait(vp); /* wait for the completion of any pending DIOs */ /* - * Call VOP_TOSS_PAGES() or VOP_FLUSHINVAL_PAGES() to get rid of pages and buffers + * Call toss_pages or flushinval_pages to get rid of pages * overlapping the region being removed. We have to use - * the less efficient VOP_FLUSHINVAL_PAGES() in the case that the + * the less efficient flushinval_pages in the case that the * caller may not be able to finish the truncate without * dropping the inode's I/O lock. Make sure * to catch any pages brought in by buffers overlapping @@ -1451,10 +1451,10 @@ xfs_itruncate_start( * so that we don't toss things on the same block as * new_size but before it. * - * Before calling VOP_TOSS_PAGES() or VOP_FLUSHINVAL_PAGES(), make sure to + * Before calling toss_page or flushinval_pages, make sure to * call remapf() over the same region if the file is mapped. * This frees up mapped file references to the pages in the - * given range and for the VOP_FLUSHINVAL_PAGES() case it ensures + * given range and for the flushinval_pages case it ensures * that we get the latest mapped changes flushed out. */ toss_start = XFS_B_TO_FSB(mp, (xfs_ufsize_t)new_size); @@ -1472,9 +1472,9 @@ xfs_itruncate_start( last_byte); if (last_byte > toss_start) { if (flags & XFS_ITRUNC_DEFINITE) { - VOP_TOSS_PAGES(vp, toss_start, -1, FI_REMAPF_LOCKED); + bhv_vop_toss_pages(vp, toss_start, -1, FI_REMAPF_LOCKED); } else { - VOP_FLUSHINVAL_PAGES(vp, toss_start, -1, FI_REMAPF_LOCKED); + bhv_vop_flushinval_pages(vp, toss_start, -1, FI_REMAPF_LOCKED); } } @@ -2752,7 +2752,7 @@ xfs_iunpin( * the inode to become unpinned. */ if (!(ip->i_flags & (XFS_IRECLAIM|XFS_IRECLAIMABLE))) { - vnode_t *vp = XFS_ITOV_NULL(ip); + bhv_vnode_t *vp = XFS_ITOV_NULL(ip); /* make sync come back and flush this inode */ if (vp) { @@ -3512,7 +3512,7 @@ xfs_iflush_all( xfs_mount_t *mp) { xfs_inode_t *ip; - vnode_t *vp; + bhv_vnode_t *vp; again: XFS_MOUNT_ILOCK(mp); diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 233668b748f..d10b76ed1e5 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -102,9 +102,9 @@ typedef struct xfs_ifork { #ifdef __KERNEL__ struct bhv_desc; +struct bhv_vnode; struct cred; struct ktrace; -struct vnode; struct xfs_buf; struct xfs_bmap_free; struct xfs_bmbt_irec; @@ -400,7 +400,7 @@ void xfs_chash_init(struct xfs_mount *); void xfs_chash_free(struct xfs_mount *); xfs_inode_t *xfs_inode_incore(struct xfs_mount *, xfs_ino_t, struct xfs_trans *); -void xfs_inode_lock_init(xfs_inode_t *, struct vnode *); +void xfs_inode_lock_init(xfs_inode_t *, struct bhv_vnode *); int xfs_iget(struct xfs_mount *, struct xfs_trans *, xfs_ino_t, uint, uint, xfs_inode_t **, xfs_daddr_t); void xfs_iput(xfs_inode_t *, uint); @@ -461,7 +461,7 @@ void xfs_ichgtime(xfs_inode_t *, int); xfs_fsize_t xfs_file_last_byte(xfs_inode_t *); void xfs_lock_inodes(xfs_inode_t **, int, int, uint); -xfs_inode_t *xfs_vtoi(struct vnode *vp); +xfs_inode_t *xfs_vtoi(struct bhv_vnode *vp); void xfs_synchronize_atime(xfs_inode_t *); diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c index 864b43d6584..a0182ced29c 100644 --- a/fs/xfs/xfs_itable.c +++ b/fs/xfs/xfs_itable.c @@ -51,7 +51,7 @@ xfs_bulkstat_one_iget( { xfs_dinode_core_t *dic; /* dinode core info pointer */ xfs_inode_t *ip; /* incore inode pointer */ - vnode_t *vp; + bhv_vnode_t *vp; int error; error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_SHARED, &ip, bno); diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 56c4b7e51f4..5ce6416fbd3 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -658,7 +658,7 @@ xfs_mountfs( xfs_buf_t *bp; xfs_sb_t *sbp = &(mp->m_sb); xfs_inode_t *rip; - vnode_t *rvp = NULL; + bhv_vnode_t *rvp = NULL; int readio_log, writeio_log; xfs_daddr_t d; __uint64_t ret64; diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 7e612255f53..a7099906369 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -54,7 +54,7 @@ typedef struct xfs_trans_reservations { struct cred; struct log; struct bhv_vfs; -struct vnode; +struct bhv_vnode; struct xfs_mount_args; struct xfs_ihash; struct xfs_chash; @@ -67,7 +67,7 @@ struct xfs_extdelta; struct xfs_swapext; extern struct bhv_vfsops xfs_vfsops; -extern struct vnodeops xfs_vnodeops; +extern struct bhv_vnodeops xfs_vnodeops; #define AIL_LOCK_T lock_t #define AIL_LOCKINIT(x,y) spinlock_init(x,y) @@ -80,15 +80,15 @@ extern struct vnodeops xfs_vnodeops; * Prototypes and functions for the Data Migration subsystem. */ -typedef int (*xfs_send_data_t)(int, struct vnode *, +typedef int (*xfs_send_data_t)(int, struct bhv_vnode *, xfs_off_t, size_t, int, vrwlock_t *); typedef int (*xfs_send_mmap_t)(struct vm_area_struct *, uint); -typedef int (*xfs_send_destroy_t)(struct vnode *, dm_right_t); +typedef int (*xfs_send_destroy_t)(struct bhv_vnode *, dm_right_t); typedef int (*xfs_send_namesp_t)(dm_eventtype_t, struct bhv_vfs *, - struct vnode *, - dm_right_t, struct vnode *, dm_right_t, + struct bhv_vnode *, + dm_right_t, struct bhv_vnode *, dm_right_t, char *, char *, mode_t, int, int); -typedef void (*xfs_send_unmount_t)(struct bhv_vfs *, struct vnode *, +typedef void (*xfs_send_unmount_t)(struct bhv_vfs *, struct bhv_vnode *, dm_right_t, mode_t, int, int); typedef struct xfs_dmops { diff --git a/fs/xfs/xfs_rename.c b/fs/xfs/xfs_rename.c index 1f148762eb2..a20566b8912 100644 --- a/fs/xfs/xfs_rename.c +++ b/fs/xfs/xfs_rename.c @@ -226,7 +226,7 @@ int xfs_rename( bhv_desc_t *src_dir_bdp, vname_t *src_vname, - vnode_t *target_dir_vp, + bhv_vnode_t *target_dir_vp, vname_t *target_vname, cred_t *credp) { @@ -242,7 +242,7 @@ xfs_rename( int committed; xfs_inode_t *inodes[4]; int target_ip_dropped = 0; /* dropped target_ip link? */ - vnode_t *src_dir_vp; + bhv_vnode_t *src_dir_vp; int spaceres; int target_link_zero = 0; int num_inodes; @@ -609,7 +609,7 @@ xfs_rename( * Let interposed file systems know about removed links. */ if (target_ip_dropped) { - VOP_LINK_REMOVED(XFS_ITOV(target_ip), target_dir_vp, + bhv_vop_link_removed(XFS_ITOV(target_ip), target_dir_vp, target_link_zero); IRELE(target_ip); } diff --git a/fs/xfs/xfs_utils.c b/fs/xfs/xfs_utils.c index 34654ec6ae1..6ecc0ca5868 100644 --- a/fs/xfs/xfs_utils.c +++ b/fs/xfs/xfs_utils.c @@ -54,7 +54,7 @@ xfs_get_dir_entry( vname_t *dentry, xfs_inode_t **ipp) { - vnode_t *vp; + bhv_vnode_t *vp; vp = VNAME_TO_VNODE(dentry); @@ -73,7 +73,7 @@ xfs_dir_lookup_int( xfs_ino_t *inum, xfs_inode_t **ipp) { - vnode_t *dir_vp; + bhv_vnode_t *dir_vp; xfs_inode_t *dp; int error; diff --git a/fs/xfs/xfs_utils.h b/fs/xfs/xfs_utils.h index 472661a3b6d..cecf1031059 100644 --- a/fs/xfs/xfs_utils.h +++ b/fs/xfs/xfs_utils.h @@ -23,7 +23,8 @@ #define ITRACE(ip) vn_trace_ref(XFS_ITOV(ip), __FILE__, __LINE__, \ (inst_t *)__return_address) -extern int xfs_rename (bhv_desc_t *, vname_t *, vnode_t *, vname_t *, cred_t *); +extern int xfs_rename (bhv_desc_t *, vname_t *, bhv_vnode_t *, + vname_t *, cred_t *); extern int xfs_get_dir_entry (vname_t *, xfs_inode_t **); extern int xfs_dir_lookup_int (bhv_desc_t *, uint, vname_t *, xfs_ino_t *, xfs_inode_t **); diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c index 57ee2bebd24..d3f270a62c9 100644 --- a/fs/xfs/xfs_vfsops.c +++ b/fs/xfs/xfs_vfsops.c @@ -555,7 +555,7 @@ xfs_unmount( bhv_vfs_t *vfsp = bhvtovfs(bdp); xfs_mount_t *mp = XFS_BHVTOM(bdp); xfs_inode_t *rip; - vnode_t *rvp; + bhv_vnode_t *rvp; int unmount_event_wanted = 0; int unmount_event_flags = 0; int xfs_unmountfs_needed = 0; @@ -701,7 +701,7 @@ xfs_unmount_flush( xfs_inode_t *rip = mp->m_rootip; xfs_inode_t *rbmip; xfs_inode_t *rsumip = NULL; - vnode_t *rvp = XFS_ITOV(rip); + bhv_vnode_t *rvp = XFS_ITOV(rip); int error; xfs_ilock(rip, XFS_ILOCK_EXCL); @@ -780,9 +780,9 @@ fscorrupt_out2: STATIC int xfs_root( bhv_desc_t *bdp, - vnode_t **vpp) + bhv_vnode_t **vpp) { - vnode_t *vp; + bhv_vnode_t *vp; vp = XFS_ITOV((XFS_BHVTOM(bdp))->m_rootip); VN_HOLD(vp); @@ -801,7 +801,7 @@ STATIC int xfs_statvfs( bhv_desc_t *bdp, xfs_statfs_t *statp, - vnode_t *vp) + bhv_vnode_t *vp) { __uint64_t fakeinos; xfs_extlen_t lsize; @@ -916,7 +916,7 @@ xfs_sync_inodes( xfs_inode_t *ip = NULL; xfs_inode_t *ip_next; xfs_buf_t *bp; - vnode_t *vp = NULL; + bhv_vnode_t *vp = NULL; int error; int last_error; uint64_t fflag; @@ -1155,9 +1155,9 @@ xfs_sync_inodes( xfs_iunlock(ip, XFS_ILOCK_SHARED); if (XFS_FORCED_SHUTDOWN(mp)) { - VOP_TOSS_PAGES(vp, 0, -1, FI_REMAPF); + bhv_vop_toss_pages(vp, 0, -1, FI_REMAPF); } else { - VOP_FLUSHINVAL_PAGES(vp, 0, -1, FI_REMAPF); + bhv_vop_flushinval_pages(vp, 0, -1, FI_REMAPF); } xfs_ilock(ip, XFS_ILOCK_SHARED); @@ -1177,8 +1177,8 @@ xfs_sync_inodes( * across calls to the buffer cache. */ xfs_iunlock(ip, XFS_ILOCK_SHARED); - VOP_FLUSH_PAGES(vp, (xfs_off_t)0, -1, - fflag, FI_NONE, error); + error = bhv_vop_flush_pages(vp, (xfs_off_t)0, + -1, fflag, FI_NONE); xfs_ilock(ip, XFS_ILOCK_SHARED); } @@ -1230,9 +1230,7 @@ xfs_sync_inodes( * marker and free it. */ XFS_MOUNT_ILOCK(mp); - IPOINTER_REMOVE(ip, mp); - XFS_MOUNT_IUNLOCK(mp); ASSERT(!(lock_flags & @@ -1573,7 +1571,7 @@ xfs_syncsub( STATIC int xfs_vget( bhv_desc_t *bdp, - vnode_t **vpp, + bhv_vnode_t **vpp, fid_t *fidp) { xfs_mount_t *mp = XFS_BHVTOM(bdp); diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 35906bae92e..f3c2deeed0a 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -62,7 +62,7 @@ xfs_open( cred_t *credp) { int mode; - vnode_t *vp = BHV_TO_VNODE(bdp); + bhv_vnode_t *vp = BHV_TO_VNODE(bdp); xfs_inode_t *ip = XFS_BHVTOI(bdp); if (XFS_FORCED_SHUTDOWN(ip->i_mount)) @@ -88,9 +88,8 @@ xfs_close( lastclose_t lastclose, cred_t *credp) { - vnode_t *vp = BHV_TO_VNODE(bdp); + bhv_vnode_t *vp = BHV_TO_VNODE(bdp); xfs_inode_t *ip = XFS_BHVTOI(bdp); - int error = 0; if (XFS_FORCED_SHUTDOWN(ip->i_mount)) return XFS_ERROR(EIO); @@ -108,8 +107,8 @@ xfs_close( * window where we'd otherwise be exposed to that problem. */ if (VUNTRUNCATE(vp) && VN_DIRTY(vp) && ip->i_delayed_blks > 0) - VOP_FLUSH_PAGES(vp, 0, -1, XFS_B_ASYNC, FI_NONE, error); - return error; + return bhv_vop_flush_pages(vp, 0, -1, XFS_B_ASYNC, FI_NONE); + return 0; } /* @@ -124,7 +123,7 @@ xfs_getattr( { xfs_inode_t *ip; xfs_mount_t *mp; - vnode_t *vp; + bhv_vnode_t *vp; vp = BHV_TO_VNODE(bdp); vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); @@ -265,7 +264,7 @@ xfs_setattr( uid_t uid=0, iuid=0; gid_t gid=0, igid=0; int timeflags = 0; - vnode_t *vp; + bhv_vnode_t *vp; xfs_prid_t projid=0, iprojid=0; int mandlock_before, mandlock_after; struct xfs_dquot *udqp, *gdqp, *olddquot1, *olddquot2; @@ -888,7 +887,7 @@ xfs_setattr( */ mandlock_after = MANDLOCK(vp, ip->i_d.di_mode); if (mandlock_before != mandlock_after) { - VOP_VNODE_CHANGE(vp, VCHANGE_FLAGS_ENF_LOCKING, + bhv_vop_vnode_change(vp, VCHANGE_FLAGS_ENF_LOCKING, mandlock_after); } @@ -976,7 +975,7 @@ xfs_readlink( int count; xfs_off_t offset; int pathlen; - vnode_t *vp; + bhv_vnode_t *vp; int error = 0; xfs_mount_t *mp; int nmaps; @@ -1547,7 +1546,7 @@ xfs_release( bhv_desc_t *bdp) { xfs_inode_t *ip; - vnode_t *vp; + bhv_vnode_t *vp; xfs_mount_t *mp; int error; @@ -1600,8 +1599,8 @@ xfs_inactive( cred_t *credp) { xfs_inode_t *ip; - vnode_t *vp; - xfs_bmap_free_t free_list; + bhv_vnode_t *vp; + xfs_bmap_free_t free_list; xfs_fsblock_t first_block; int committed; xfs_trans_t *tp; @@ -1817,16 +1816,16 @@ STATIC int xfs_lookup( bhv_desc_t *dir_bdp, vname_t *dentry, - vnode_t **vpp, + bhv_vnode_t **vpp, int flags, - vnode_t *rdir, + bhv_vnode_t *rdir, cred_t *credp) { xfs_inode_t *dp, *ip; xfs_ino_t e_inum; int error; uint lock_mode; - vnode_t *dir_vp; + bhv_vnode_t *dir_vp; dir_vp = BHV_TO_VNODE(dir_bdp); vn_trace_entry(dir_vp, __FUNCTION__, (inst_t *)__return_address); @@ -1855,13 +1854,13 @@ xfs_create( bhv_desc_t *dir_bdp, vname_t *dentry, vattr_t *vap, - vnode_t **vpp, + bhv_vnode_t **vpp, cred_t *credp) { char *name = VNAME(dentry); - vnode_t *dir_vp; + bhv_vnode_t *dir_vp; xfs_inode_t *dp, *ip; - vnode_t *vp=NULL; + bhv_vnode_t *vp = NULL; xfs_trans_t *tp; xfs_mount_t *mp; xfs_dev_t rdev; @@ -2047,7 +2046,7 @@ xfs_create( * Propagate the fact that the vnode changed after the * xfs_inode locks have been released. */ - VOP_VNODE_CHANGE(vp, VCHANGE_FLAGS_TRUNCATED, 3); + bhv_vop_vnode_change(vp, VCHANGE_FLAGS_TRUNCATED, 3); *vpp = vp; @@ -2345,7 +2344,7 @@ xfs_remove( vname_t *dentry, cred_t *credp) { - vnode_t *dir_vp; + bhv_vnode_t *dir_vp; char *name = VNAME(dentry); xfs_inode_t *dp, *ip; xfs_trans_t *tp = NULL; @@ -2532,7 +2531,7 @@ xfs_remove( /* * Let interposed file systems know about removed links. */ - VOP_LINK_REMOVED(XFS_ITOV(ip), dir_vp, link_zero); + bhv_vop_link_removed(XFS_ITOV(ip), dir_vp, link_zero); IRELE(ip); @@ -2585,7 +2584,7 @@ xfs_remove( STATIC int xfs_link( bhv_desc_t *target_dir_bdp, - vnode_t *src_vp, + bhv_vnode_t *src_vp, vname_t *dentry, cred_t *credp) { @@ -2598,7 +2597,7 @@ xfs_link( xfs_fsblock_t first_block; int cancel_flags; int committed; - vnode_t *target_dir_vp; + bhv_vnode_t *target_dir_vp; int resblks; char *target_name = VNAME(dentry); int target_namelen; @@ -2757,13 +2756,13 @@ xfs_mkdir( bhv_desc_t *dir_bdp, vname_t *dentry, vattr_t *vap, - vnode_t **vpp, + bhv_vnode_t **vpp, cred_t *credp) { char *dir_name = VNAME(dentry); xfs_inode_t *dp; xfs_inode_t *cdp; /* inode of created dir */ - vnode_t *cvp; /* vnode of created dir */ + bhv_vnode_t *cvp; /* vnode of created dir */ xfs_trans_t *tp; xfs_mount_t *mp; int cancel_flags; @@ -2771,7 +2770,7 @@ xfs_mkdir( int committed; xfs_bmap_free_t free_list; xfs_fsblock_t first_block; - vnode_t *dir_vp; + bhv_vnode_t *dir_vp; boolean_t dp_joined_to_trans; boolean_t created = B_FALSE; int dm_event_sent = 0; @@ -3003,7 +3002,7 @@ xfs_rmdir( xfs_fsblock_t first_block; int cancel_flags; int committed; - vnode_t *dir_vp; + bhv_vnode_t *dir_vp; int dm_di_mode = 0; int last_cdp_link; int namelen; @@ -3202,7 +3201,7 @@ xfs_rmdir( /* * Let interposed file systems know about removed links. */ - VOP_LINK_REMOVED(XFS_ITOV(cdp), dir_vp, last_cdp_link); + bhv_vop_link_removed(XFS_ITOV(cdp), dir_vp, last_cdp_link); IRELE(cdp); @@ -3272,7 +3271,7 @@ xfs_symlink( vname_t *dentry, vattr_t *vap, char *target_path, - vnode_t **vpp, + bhv_vnode_t **vpp, cred_t *credp) { xfs_trans_t *tp; @@ -3284,7 +3283,7 @@ xfs_symlink( xfs_bmap_free_t free_list; xfs_fsblock_t first_block; boolean_t dp_joined_to_trans; - vnode_t *dir_vp; + bhv_vnode_t *dir_vp; uint cancel_flags; int committed; xfs_fileoff_t first_fsb; @@ -3562,7 +3561,7 @@ std_return: } if (!error) { - vnode_t *vp; + bhv_vnode_t *vp; ASSERT(ip); vp = XFS_ITOV(ip); @@ -3630,7 +3629,7 @@ xfs_rwlock( vrwlock_t locktype) { xfs_inode_t *ip; - vnode_t *vp; + bhv_vnode_t *vp; vp = BHV_TO_VNODE(bdp); if (VN_ISDIR(vp)) @@ -3661,7 +3660,7 @@ xfs_rwunlock( vrwlock_t locktype) { xfs_inode_t *ip; - vnode_t *vp; + bhv_vnode_t *vp; vp = BHV_TO_VNODE(bdp); if (VN_ISDIR(vp)) @@ -3810,7 +3809,7 @@ xfs_reclaim( bhv_desc_t *bdp) { xfs_inode_t *ip; - vnode_t *vp; + bhv_vnode_t *vp; vp = BHV_TO_VNODE(bdp); ip = XFS_BHVTOI(bdp); @@ -3865,7 +3864,7 @@ xfs_finish_reclaim( int sync_mode) { xfs_ihash_t *ih = ip->i_hash; - vnode_t *vp = XFS_ITOV_NULL(ip); + bhv_vnode_t *vp = XFS_ITOV_NULL(ip); int error; if (vp && VN_BAD(vp)) @@ -4275,7 +4274,7 @@ xfs_free_file_space( xfs_off_t len, int attr_flags) { - vnode_t *vp; + bhv_vnode_t *vp; int committed; int done; xfs_off_t end_dmi_offset; @@ -4341,7 +4340,7 @@ xfs_free_file_space( if (VN_CACHED(vp) != 0) { xfs_inval_cached_trace(&ip->i_iocore, ioffset, -1, ctooff(offtoct(ioffset)), -1); - VOP_FLUSHINVAL_PAGES(vp, ctooff(offtoct(ioffset)), + bhv_vop_flushinval_pages(vp, ctooff(offtoct(ioffset)), -1, FI_REMAPF_LOCKED); } @@ -4504,7 +4503,7 @@ xfs_change_file_space( xfs_off_t llen; xfs_trans_t *tp; vattr_t va; - vnode_t *vp; + bhv_vnode_t *vp; vp = BHV_TO_VNODE(bdp); vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); @@ -4657,7 +4656,7 @@ xfs_change_file_space( return error; } -vnodeops_t xfs_vnodeops = { +bhv_vnodeops_t xfs_vnodeops = { BHV_IDENTITY_INIT(VN_BHV_XFS,VNODE_POSITION_XFS), .vop_open = xfs_open, .vop_close = xfs_close, -- cgit v1.2.3 From 8285fb58e75bfdb447c7a2c533ec9efdb238f966 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Fri, 9 Jun 2006 17:07:12 +1000 Subject: [XFS] Resolve a namespace collision on remaining vtypes for FreeBSD porters. SGI-PV: 953338 SGI-Modid: xfs-linux-melb:xfs-kern:26108a Signed-off-by: Nathan Scott --- fs/xfs/linux-2.6/xfs_ioctl.c | 2 +- fs/xfs/linux-2.6/xfs_iops.c | 16 +++++------ fs/xfs/linux-2.6/xfs_lrw.c | 10 +++---- fs/xfs/linux-2.6/xfs_vfs.c | 4 +-- fs/xfs/linux-2.6/xfs_vfs.h | 8 +++--- fs/xfs/linux-2.6/xfs_vnode.c | 6 ++--- fs/xfs/linux-2.6/xfs_vnode.h | 64 ++++++++++++++++++++++---------------------- fs/xfs/quota/xfs_qm_bhv.c | 2 +- fs/xfs/xfs_acl.c | 10 +++---- fs/xfs/xfs_acl.h | 2 +- fs/xfs/xfs_mount.h | 2 +- fs/xfs/xfs_rename.c | 8 +++--- fs/xfs/xfs_rw.h | 7 ++--- fs/xfs/xfs_utils.c | 4 +-- fs/xfs/xfs_utils.h | 8 +++--- fs/xfs/xfs_vfsops.c | 2 +- fs/xfs/xfs_vnodeops.c | 32 +++++++++++----------- 17 files changed, 94 insertions(+), 93 deletions(-) diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c index 73182503c16..a0e247c7132 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/fs/xfs/linux-2.6/xfs_ioctl.c @@ -1157,7 +1157,7 @@ xfs_ioc_xattr( void __user *arg) { struct fsxattr fa; - struct vattr *vattr; + struct bhv_vattr *vattr; int error = 0; int attr_flags; unsigned int flags; diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index 0857658882e..484daef91d7 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c @@ -200,7 +200,7 @@ xfs_ichgtime_fast( STATIC void xfs_validate_fields( struct inode *ip, - struct vattr *vattr) + bhv_vattr_t *vattr) { vattr->va_mask = XFS_AT_NLINK|XFS_AT_SIZE|XFS_AT_NBLOCKS; if (!bhv_vop_getattr(vn_from_inode(ip), vattr, ATTR_LAZY, NULL)) { @@ -290,7 +290,7 @@ xfs_vn_mknod( dev_t rdev) { struct inode *ip; - vattr_t vattr = { 0 }; + bhv_vattr_t vattr = { 0 }; bhv_vnode_t *vp = NULL, *dvp = vn_from_inode(dir); xfs_acl_t *default_acl = NULL; attrexists_t test_default_acl = _ACL_DEFAULT_EXISTS; @@ -417,7 +417,7 @@ xfs_vn_link( struct inode *ip; /* inode of guy being linked to */ bhv_vnode_t *tdvp; /* target directory for new name/link */ bhv_vnode_t *vp; /* vp of name being linked */ - vattr_t vattr; + bhv_vattr_t vattr; int error; ip = old_dentry->d_inode; /* inode being linked to */ @@ -444,7 +444,7 @@ xfs_vn_unlink( { struct inode *inode; bhv_vnode_t *dvp; /* directory containing name to remove */ - vattr_t vattr; + bhv_vattr_t vattr; int error; inode = dentry->d_inode; @@ -465,7 +465,7 @@ xfs_vn_symlink( const char *symname) { struct inode *ip; - vattr_t va = { 0 }; + bhv_vattr_t va = { 0 }; bhv_vnode_t *dvp; /* directory containing name of symlink */ bhv_vnode_t *cvp; /* used to lookup symlink to put in dentry */ int error; @@ -499,7 +499,7 @@ xfs_vn_rmdir( { struct inode *inode = dentry->d_inode; bhv_vnode_t *dvp = vn_from_inode(dir); - vattr_t vattr; + bhv_vattr_t vattr; int error; error = bhv_vop_rmdir(dvp, dentry, NULL); @@ -520,7 +520,7 @@ xfs_vn_rename( struct inode *new_inode = ndentry->d_inode; bhv_vnode_t *fvp; /* from directory */ bhv_vnode_t *tvp; /* target directory */ - vattr_t vattr; + bhv_vattr_t vattr; int error; fvp = vn_from_inode(odir); @@ -643,7 +643,7 @@ xfs_vn_setattr( struct inode *inode = dentry->d_inode; unsigned int ia_valid = attr->ia_valid; bhv_vnode_t *vp = vn_from_inode(inode); - vattr_t vattr = { 0 }; + bhv_vattr_t vattr = { 0 }; int flags = 0; int error; diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c index a9b83018f0f..8696096f8d2 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.c +++ b/fs/xfs/linux-2.6/xfs_lrw.c @@ -258,7 +258,7 @@ xfs_read( if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ) && !(ioflags & IO_INVIS)) { - vrwlock_t locktype = VRWLOCK_READ; + bhv_vrwlock_t locktype = VRWLOCK_READ; int dmflags = FILP_DELAY_FLAG(file) | DM_SEM_FLAG_RD(ioflags); ret = -XFS_SEND_DATA(mp, DM_EVENT_READ, @@ -313,7 +313,7 @@ xfs_sendfile( if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_READ) && (!(ioflags & IO_INVIS))) { - vrwlock_t locktype = VRWLOCK_READ; + bhv_vrwlock_t locktype = VRWLOCK_READ; int error; error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp), @@ -357,7 +357,7 @@ xfs_splice_read( if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_READ) && (!(ioflags & IO_INVIS))) { - vrwlock_t locktype = VRWLOCK_READ; + bhv_vrwlock_t locktype = VRWLOCK_READ; int error; error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp), @@ -401,7 +401,7 @@ xfs_splice_write( if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_WRITE) && (!(ioflags & IO_INVIS))) { - vrwlock_t locktype = VRWLOCK_WRITE; + bhv_vrwlock_t locktype = VRWLOCK_WRITE; int error; error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, BHV_TO_VNODE(bdp), @@ -630,7 +630,7 @@ xfs_write( unsigned long seg; int iolock; int eventsent = 0; - vrwlock_t locktype; + bhv_vrwlock_t locktype; size_t ocount = 0, count; loff_t pos; int need_i_mutex = 1, need_flush = 0; diff --git a/fs/xfs/linux-2.6/xfs_vfs.c b/fs/xfs/linux-2.6/xfs_vfs.c index a91ecfa9c8a..4fc884bcb4f 100644 --- a/fs/xfs/linux-2.6/xfs_vfs.c +++ b/fs/xfs/linux-2.6/xfs_vfs.c @@ -117,7 +117,7 @@ vfs_root( int vfs_statvfs( struct bhv_desc *bdp, - xfs_statfs_t *sp, + bhv_statvfs_t *statp, struct bhv_vnode *vp) { struct bhv_desc *next = bdp; @@ -125,7 +125,7 @@ vfs_statvfs( ASSERT(next); while (! (bhvtovfsops(next))->vfs_statvfs) next = BHV_NEXT(next); - return ((*bhvtovfsops(next)->vfs_statvfs)(next, sp, vp)); + return ((*bhvtovfsops(next)->vfs_statvfs)(next, statp, vp)); } int diff --git a/fs/xfs/linux-2.6/xfs_vfs.h b/fs/xfs/linux-2.6/xfs_vfs.h index 1a3a2dd4b97..7b88eeae0f2 100644 --- a/fs/xfs/linux-2.6/xfs_vfs.h +++ b/fs/xfs/linux-2.6/xfs_vfs.h @@ -23,14 +23,14 @@ struct bhv_vfs; struct bhv_vnode; + struct fid; struct cred; -struct statfs; struct seq_file; struct super_block; struct xfs_mount_args; -typedef struct kstatfs xfs_statfs_t; +typedef struct kstatfs bhv_statvfs_t; typedef struct bhv_vfs_sync_work { struct list_head w_list; @@ -109,7 +109,7 @@ typedef int (*vfs_unmount_t)(bhv_desc_t *, int, struct cred *); typedef int (*vfs_mntupdate_t)(bhv_desc_t *, int *, struct xfs_mount_args *); typedef int (*vfs_root_t)(bhv_desc_t *, struct bhv_vnode **); -typedef int (*vfs_statvfs_t)(bhv_desc_t *, xfs_statfs_t *, +typedef int (*vfs_statvfs_t)(bhv_desc_t *, bhv_statvfs_t *, struct bhv_vnode *); typedef int (*vfs_sync_t)(bhv_desc_t *, int, struct cred *); typedef int (*vfs_vget_t)(bhv_desc_t *, struct bhv_vnode **, struct fid *); @@ -181,7 +181,7 @@ extern int vfs_showargs(bhv_desc_t *, struct seq_file *); extern int vfs_unmount(bhv_desc_t *, int, struct cred *); extern int vfs_mntupdate(bhv_desc_t *, int *, struct xfs_mount_args *); extern int vfs_root(bhv_desc_t *, struct bhv_vnode **); -extern int vfs_statvfs(bhv_desc_t *, xfs_statfs_t *, struct bhv_vnode *); +extern int vfs_statvfs(bhv_desc_t *, bhv_statvfs_t *, struct bhv_vnode *); extern int vfs_sync(bhv_desc_t *, int, struct cred *); extern int vfs_vget(bhv_desc_t *, struct bhv_vnode **, struct fid *); extern int vfs_dmapiops(bhv_desc_t *, caddr_t); diff --git a/fs/xfs/linux-2.6/xfs_vnode.c b/fs/xfs/linux-2.6/xfs_vnode.c index 66e36e195f2..6628d96b6fd 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.c +++ b/fs/xfs/linux-2.6/xfs_vnode.c @@ -111,7 +111,7 @@ vn_initialize( void vn_revalidate_core( bhv_vnode_t *vp, - vattr_t *vap) + bhv_vattr_t *vap) { struct inode *inode = vn_to_inode(vp); @@ -147,7 +147,7 @@ vn_revalidate_core( int __vn_revalidate( bhv_vnode_t *vp, - struct vattr *vattr) + bhv_vattr_t *vattr) { int error; @@ -165,7 +165,7 @@ int vn_revalidate( bhv_vnode_t *vp) { - vattr_t vattr; + bhv_vattr_t vattr; return __vn_revalidate(vp, &vattr); } diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h index cb16774aea7..35c6a01963a 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.h +++ b/fs/xfs/linux-2.6/xfs_vnode.h @@ -20,29 +20,29 @@ struct uio; struct file; -struct vattr; +struct bhv_vfs; +struct bhv_vattr; struct xfs_iomap; struct attrlist_cursor_kern; -typedef xfs_ino_t vnumber_t; -typedef struct dentry vname_t; -typedef bhv_head_t vn_bhv_head_t; +typedef struct dentry bhv_vname_t; +typedef __u64 bhv_vnumber_t; -typedef enum vflags { +typedef enum bhv_vflags { VMODIFIED = 0x08, /* XFS inode state possibly differs */ /* to the Linux inode state. */ VTRUNCATED = 0x40, /* truncated down so flush-on-close */ -} vflags_t; +} bhv_vflags_t; /* * MP locking protocols: * v_flag, v_vfsp VN_LOCK/VN_UNLOCK */ typedef struct bhv_vnode { - vflags_t v_flag; /* vnode flags (see above) */ - struct bhv_vfs *v_vfsp; /* ptr to containing VFS */ - vnumber_t v_number; /* in-core vnode number */ - vn_bhv_head_t v_bh; /* behavior head */ + bhv_vflags_t v_flag; /* vnode flags (see above) */ + bhv_vfs_t *v_vfsp; /* ptr to containing VFS */ + bhv_vnumber_t v_number; /* in-core vnode number */ + bhv_head_t v_bh; /* behavior head */ spinlock_t v_lock; /* VN_LOCK/VN_UNLOCK */ atomic_t v_iocount; /* outstanding I/O count */ #ifdef XFS_VNODE_TRACE @@ -103,14 +103,14 @@ static inline struct inode *vn_to_inode(struct bhv_vnode *vnode) /* * Values for the vop_rwlock/rwunlock flags parameter. */ -typedef enum vrwlock { +typedef enum bhv_vrwlock { VRWLOCK_NONE, VRWLOCK_READ, VRWLOCK_WRITE, VRWLOCK_WRITE_DIRECT, VRWLOCK_TRY_READ, VRWLOCK_TRY_WRITE -} vrwlock_t; +} bhv_vrwlock_t; /* * Return values for bhv_vop_inactive. A return value of @@ -123,13 +123,13 @@ typedef enum vrwlock { /* * Values for the cmd code given to vop_vnode_change. */ -typedef enum vchange { +typedef enum bhv_vchange { VCHANGE_FLAGS_FRLOCKS = 0, VCHANGE_FLAGS_ENF_LOCKING = 1, VCHANGE_FLAGS_TRUNCATED = 2, VCHANGE_FLAGS_PAGE_DIRTY = 3, VCHANGE_FLAGS_IOEXCL_COUNT = 4 -} vchange_t; +} bhv_vchange_t; typedef enum { L_FALSE, L_TRUE } lastclose_t; @@ -152,26 +152,26 @@ typedef ssize_t (*vop_splice_write_t)(bhv_desc_t *, struct pipe_inode_info *, struct cred *); typedef int (*vop_ioctl_t)(bhv_desc_t *, struct inode *, struct file *, int, unsigned int, void __user *); -typedef int (*vop_getattr_t)(bhv_desc_t *, struct vattr *, int, +typedef int (*vop_getattr_t)(bhv_desc_t *, struct bhv_vattr *, int, struct cred *); -typedef int (*vop_setattr_t)(bhv_desc_t *, struct vattr *, int, +typedef int (*vop_setattr_t)(bhv_desc_t *, struct bhv_vattr *, int, struct cred *); typedef int (*vop_access_t)(bhv_desc_t *, int, struct cred *); -typedef int (*vop_lookup_t)(bhv_desc_t *, vname_t *, bhv_vnode_t **, +typedef int (*vop_lookup_t)(bhv_desc_t *, bhv_vname_t *, bhv_vnode_t **, int, bhv_vnode_t *, struct cred *); -typedef int (*vop_create_t)(bhv_desc_t *, vname_t *, struct vattr *, +typedef int (*vop_create_t)(bhv_desc_t *, bhv_vname_t *, struct bhv_vattr *, bhv_vnode_t **, struct cred *); -typedef int (*vop_remove_t)(bhv_desc_t *, vname_t *, struct cred *); -typedef int (*vop_link_t)(bhv_desc_t *, bhv_vnode_t *, vname_t *, +typedef int (*vop_remove_t)(bhv_desc_t *, bhv_vname_t *, struct cred *); +typedef int (*vop_link_t)(bhv_desc_t *, bhv_vnode_t *, bhv_vname_t *, struct cred *); -typedef int (*vop_rename_t)(bhv_desc_t *, vname_t *, bhv_vnode_t *, - vname_t *, struct cred *); -typedef int (*vop_mkdir_t)(bhv_desc_t *, vname_t *, struct vattr *, +typedef int (*vop_rename_t)(bhv_desc_t *, bhv_vname_t *, bhv_vnode_t *, + bhv_vname_t *, struct cred *); +typedef int (*vop_mkdir_t)(bhv_desc_t *, bhv_vname_t *, struct bhv_vattr *, bhv_vnode_t **, struct cred *); -typedef int (*vop_rmdir_t)(bhv_desc_t *, vname_t *, struct cred *); +typedef int (*vop_rmdir_t)(bhv_desc_t *, bhv_vname_t *, struct cred *); typedef int (*vop_readdir_t)(bhv_desc_t *, struct uio *, struct cred *, int *); -typedef int (*vop_symlink_t)(bhv_desc_t *, vname_t *, struct vattr *, +typedef int (*vop_symlink_t)(bhv_desc_t *, bhv_vname_t *, struct bhv_vattr*, char *, bhv_vnode_t **, struct cred *); typedef int (*vop_readlink_t)(bhv_desc_t *, struct uio *, int, struct cred *); @@ -180,8 +180,8 @@ typedef int (*vop_fsync_t)(bhv_desc_t *, int, struct cred *, typedef int (*vop_inactive_t)(bhv_desc_t *, struct cred *); typedef int (*vop_fid2_t)(bhv_desc_t *, struct fid *); typedef int (*vop_release_t)(bhv_desc_t *); -typedef int (*vop_rwlock_t)(bhv_desc_t *, vrwlock_t); -typedef void (*vop_rwunlock_t)(bhv_desc_t *, vrwlock_t); +typedef int (*vop_rwlock_t)(bhv_desc_t *, bhv_vrwlock_t); +typedef void (*vop_rwunlock_t)(bhv_desc_t *, bhv_vrwlock_t); typedef int (*vop_bmap_t)(bhv_desc_t *, xfs_off_t, ssize_t, int, struct xfs_iomap *, int *); typedef int (*vop_reclaim_t)(bhv_desc_t *); @@ -194,7 +194,7 @@ typedef int (*vop_attr_remove_t)(bhv_desc_t *, const char *, typedef int (*vop_attr_list_t)(bhv_desc_t *, char *, int, int, struct attrlist_cursor_kern *, struct cred *); typedef void (*vop_link_removed_t)(bhv_desc_t *, bhv_vnode_t *, int); -typedef void (*vop_vnode_change_t)(bhv_desc_t *, vchange_t, __psint_t); +typedef void (*vop_vnode_change_t)(bhv_desc_t *, bhv_vchange_t, __psint_t); typedef void (*vop_ptossvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t, int); typedef void (*vop_pflushinvalvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t, int); typedef int (*vop_pflushvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t, @@ -346,7 +346,7 @@ typedef struct bhv_vnodeops { * Vnode attributes. va_mask indicates those attributes the caller * wants to set or extract. */ -typedef struct vattr { +typedef struct bhv_vattr { int va_mask; /* bit-mask of attributes present */ mode_t va_mode; /* file access mode and type */ xfs_nlink_t va_nlink; /* number of references to file */ @@ -366,7 +366,7 @@ typedef struct vattr { u_long va_nextents; /* number of extents in file */ u_long va_anextents; /* number of attr extents in file */ prid_t va_projid; /* project id */ -} vattr_t; +} bhv_vattr_t; /* * setattr or getattr attributes @@ -442,8 +442,8 @@ typedef struct vattr { extern void vn_init(void); extern bhv_vnode_t *vn_initialize(struct inode *); extern int vn_revalidate(struct bhv_vnode *); -extern int __vn_revalidate(struct bhv_vnode *, vattr_t *); -extern void vn_revalidate_core(struct bhv_vnode *, vattr_t *); +extern int __vn_revalidate(struct bhv_vnode *, bhv_vattr_t *); +extern void vn_revalidate_core(struct bhv_vnode *, bhv_vattr_t *); extern void vn_iowait(struct bhv_vnode *vp); extern void vn_iowake(struct bhv_vnode *vp); diff --git a/fs/xfs/quota/xfs_qm_bhv.c b/fs/xfs/quota/xfs_qm_bhv.c index ad9ab104946..d93d3a1064e 100644 --- a/fs/xfs/quota/xfs_qm_bhv.c +++ b/fs/xfs/quota/xfs_qm_bhv.c @@ -191,7 +191,7 @@ xfs_qm_mount( STATIC int xfs_qm_statvfs( struct bhv_desc *bhv, - xfs_statfs_t *statp, + bhv_statvfs_t *statp, struct bhv_vnode *vnode) { xfs_mount_t *mp; diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c index 8c300da4e7a..e1074955386 100644 --- a/fs/xfs/xfs_acl.c +++ b/fs/xfs/xfs_acl.c @@ -241,7 +241,7 @@ xfs_acl_vget( goto out; } if (kind == _ACL_TYPE_ACCESS) { - vattr_t va; + bhv_vattr_t va; va.va_mask = XFS_AT_MODE; error = bhv_vop_getattr(vp, &va, 0, sys_cred); @@ -373,7 +373,7 @@ xfs_acl_allow_set( bhv_vnode_t *vp, int kind) { - vattr_t va; + bhv_vattr_t va; int error; if (vp->v_inode.i_flags & (S_IMMUTABLE|S_APPEND)) @@ -666,7 +666,7 @@ xfs_acl_vtoacl( xfs_acl_t *access_acl, xfs_acl_t *default_acl) { - vattr_t va; + bhv_vattr_t va; int error = 0; if (access_acl) { @@ -702,7 +702,7 @@ xfs_acl_vtoacl( int xfs_acl_inherit( bhv_vnode_t *vp, - vattr_t *vap, + bhv_vattr_t *vap, xfs_acl_t *pdaclp) { xfs_acl_t *cacl; @@ -761,7 +761,7 @@ xfs_acl_setmode( xfs_acl_t *acl, int *basicperms) { - vattr_t va; + bhv_vattr_t va; xfs_acl_entry_t *ap; xfs_acl_entry_t *gap = NULL; int i, error, nomask = 1; diff --git a/fs/xfs/xfs_acl.h b/fs/xfs/xfs_acl.h index a57ff4e6d39..f853cf1a627 100644 --- a/fs/xfs/xfs_acl.h +++ b/fs/xfs/xfs_acl.h @@ -58,7 +58,7 @@ extern struct kmem_zone *xfs_acl_zone; (zone) = kmem_zone_init(sizeof(xfs_acl_t), (name)) #define xfs_acl_zone_destroy(zone) kmem_zone_destroy(zone) -extern int xfs_acl_inherit(struct bhv_vnode *, struct vattr *, xfs_acl_t *); +extern int xfs_acl_inherit(struct bhv_vnode *, struct bhv_vattr *, xfs_acl_t *); extern int xfs_acl_iaccess(struct xfs_inode *, mode_t, cred_t *); extern int xfs_acl_vtoacl(struct bhv_vnode *, xfs_acl_t *, xfs_acl_t *); extern int xfs_acl_vhasacl_access(struct bhv_vnode *); diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index a7099906369..761f42f989c 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -81,7 +81,7 @@ extern struct bhv_vnodeops xfs_vnodeops; */ typedef int (*xfs_send_data_t)(int, struct bhv_vnode *, - xfs_off_t, size_t, int, vrwlock_t *); + xfs_off_t, size_t, int, bhv_vrwlock_t *); typedef int (*xfs_send_mmap_t)(struct vm_area_struct *, uint); typedef int (*xfs_send_destroy_t)(struct bhv_vnode *, dm_right_t); typedef int (*xfs_send_namesp_t)(dm_eventtype_t, struct bhv_vfs *, diff --git a/fs/xfs/xfs_rename.c b/fs/xfs/xfs_rename.c index a20566b8912..7d5f9b6ffdb 100644 --- a/fs/xfs/xfs_rename.c +++ b/fs/xfs/xfs_rename.c @@ -87,8 +87,8 @@ STATIC int xfs_lock_for_rename( xfs_inode_t *dp1, /* old (source) directory inode */ xfs_inode_t *dp2, /* new (target) directory inode */ - vname_t *vname1,/* old entry name */ - vname_t *vname2,/* new entry name */ + bhv_vname_t *vname1,/* old entry name */ + bhv_vname_t *vname2,/* new entry name */ xfs_inode_t **ipp1, /* inode of old entry */ xfs_inode_t **ipp2, /* inode of new entry, if it already exists, NULL otherwise. */ @@ -225,9 +225,9 @@ xfs_lock_for_rename( int xfs_rename( bhv_desc_t *src_dir_bdp, - vname_t *src_vname, + bhv_vname_t *src_vname, bhv_vnode_t *target_dir_vp, - vname_t *target_vname, + bhv_vname_t *target_vname, cred_t *credp) { xfs_trans_t *tp; diff --git a/fs/xfs/xfs_rw.h b/fs/xfs/xfs_rw.h index e6379564447..a572b175dc8 100644 --- a/fs/xfs/xfs_rw.h +++ b/fs/xfs/xfs_rw.h @@ -87,9 +87,10 @@ extern void xfs_ioerror_alert(char *func, struct xfs_mount *mp, /* * Prototypes for functions in xfs_vnodeops.c. */ -extern int xfs_rwlock(bhv_desc_t *bdp, vrwlock_t write_lock); -extern void xfs_rwunlock(bhv_desc_t *bdp, vrwlock_t write_lock); -extern int xfs_setattr(bhv_desc_t *bdp, vattr_t *vap, int flags, cred_t *credp); +extern int xfs_rwlock(bhv_desc_t *bdp, bhv_vrwlock_t write_lock); +extern void xfs_rwunlock(bhv_desc_t *bdp, bhv_vrwlock_t write_lock); +extern int xfs_setattr(bhv_desc_t *, bhv_vattr_t *vap, int flags, + cred_t *credp); extern int xfs_change_file_space(bhv_desc_t *bdp, int cmd, xfs_flock64_t *bf, xfs_off_t offset, cred_t *credp, int flags); extern int xfs_set_dmattrs(bhv_desc_t *bdp, u_int evmask, u_int16_t state, diff --git a/fs/xfs/xfs_utils.c b/fs/xfs/xfs_utils.c index 6ecc0ca5868..37fdc2dc00b 100644 --- a/fs/xfs/xfs_utils.c +++ b/fs/xfs/xfs_utils.c @@ -51,7 +51,7 @@ */ int xfs_get_dir_entry( - vname_t *dentry, + bhv_vname_t *dentry, xfs_inode_t **ipp) { bhv_vnode_t *vp; @@ -69,7 +69,7 @@ int xfs_dir_lookup_int( bhv_desc_t *dir_bdp, uint lock_mode, - vname_t *dentry, + bhv_vname_t *dentry, xfs_ino_t *inum, xfs_inode_t **ipp) { diff --git a/fs/xfs/xfs_utils.h b/fs/xfs/xfs_utils.h index cecf1031059..fe953e98afa 100644 --- a/fs/xfs/xfs_utils.h +++ b/fs/xfs/xfs_utils.h @@ -23,10 +23,10 @@ #define ITRACE(ip) vn_trace_ref(XFS_ITOV(ip), __FILE__, __LINE__, \ (inst_t *)__return_address) -extern int xfs_rename (bhv_desc_t *, vname_t *, bhv_vnode_t *, - vname_t *, cred_t *); -extern int xfs_get_dir_entry (vname_t *, xfs_inode_t **); -extern int xfs_dir_lookup_int (bhv_desc_t *, uint, vname_t *, xfs_ino_t *, +extern int xfs_rename (bhv_desc_t *, bhv_vname_t *, bhv_vnode_t *, + bhv_vname_t *, cred_t *); +extern int xfs_get_dir_entry (bhv_vname_t *, xfs_inode_t **); +extern int xfs_dir_lookup_int (bhv_desc_t *, uint, bhv_vname_t *, xfs_ino_t *, xfs_inode_t **); extern int xfs_truncate_file (xfs_mount_t *, xfs_inode_t *); extern int xfs_dir_ialloc (xfs_trans_t **, xfs_inode_t *, mode_t, xfs_nlink_t, diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c index d3f270a62c9..7550583bd09 100644 --- a/fs/xfs/xfs_vfsops.c +++ b/fs/xfs/xfs_vfsops.c @@ -800,7 +800,7 @@ xfs_root( STATIC int xfs_statvfs( bhv_desc_t *bdp, - xfs_statfs_t *statp, + bhv_statvfs_t *statp, bhv_vnode_t *vp) { __uint64_t fakeinos; diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index f3c2deeed0a..26d96d1b25c 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -117,7 +117,7 @@ xfs_close( STATIC int xfs_getattr( bhv_desc_t *bdp, - vattr_t *vap, + bhv_vattr_t *vap, int flags, cred_t *credp) { @@ -250,7 +250,7 @@ xfs_getattr( int xfs_setattr( bhv_desc_t *bdp, - vattr_t *vap, + bhv_vattr_t *vap, int flags, cred_t *credp) { @@ -1815,7 +1815,7 @@ xfs_inactive( STATIC int xfs_lookup( bhv_desc_t *dir_bdp, - vname_t *dentry, + bhv_vname_t *dentry, bhv_vnode_t **vpp, int flags, bhv_vnode_t *rdir, @@ -1852,8 +1852,8 @@ xfs_lookup( STATIC int xfs_create( bhv_desc_t *dir_bdp, - vname_t *dentry, - vattr_t *vap, + bhv_vname_t *dentry, + bhv_vattr_t *vap, bhv_vnode_t **vpp, cred_t *credp) { @@ -2127,7 +2127,7 @@ int xfs_rm_attempts; STATIC int xfs_lock_dir_and_entry( xfs_inode_t *dp, - vname_t *dentry, + bhv_vname_t *dentry, xfs_inode_t *ip) /* inode of entry 'name' */ { int attempts; @@ -2341,7 +2341,7 @@ int remove_which_error_return = 0; STATIC int xfs_remove( bhv_desc_t *dir_bdp, - vname_t *dentry, + bhv_vname_t *dentry, cred_t *credp) { bhv_vnode_t *dir_vp; @@ -2585,7 +2585,7 @@ STATIC int xfs_link( bhv_desc_t *target_dir_bdp, bhv_vnode_t *src_vp, - vname_t *dentry, + bhv_vname_t *dentry, cred_t *credp) { xfs_inode_t *tdp, *sip; @@ -2754,8 +2754,8 @@ std_return: STATIC int xfs_mkdir( bhv_desc_t *dir_bdp, - vname_t *dentry, - vattr_t *vap, + bhv_vname_t *dentry, + bhv_vattr_t *vap, bhv_vnode_t **vpp, cred_t *credp) { @@ -2989,7 +2989,7 @@ std_return: STATIC int xfs_rmdir( bhv_desc_t *dir_bdp, - vname_t *dentry, + bhv_vname_t *dentry, cred_t *credp) { char *name = VNAME(dentry); @@ -3268,8 +3268,8 @@ xfs_readdir( STATIC int xfs_symlink( bhv_desc_t *dir_bdp, - vname_t *dentry, - vattr_t *vap, + bhv_vname_t *dentry, + bhv_vattr_t *vap, char *target_path, bhv_vnode_t **vpp, cred_t *credp) @@ -3626,7 +3626,7 @@ xfs_fid2( int xfs_rwlock( bhv_desc_t *bdp, - vrwlock_t locktype) + bhv_vrwlock_t locktype) { xfs_inode_t *ip; bhv_vnode_t *vp; @@ -3657,7 +3657,7 @@ xfs_rwlock( void xfs_rwunlock( bhv_desc_t *bdp, - vrwlock_t locktype) + bhv_vrwlock_t locktype) { xfs_inode_t *ip; bhv_vnode_t *vp; @@ -4502,7 +4502,7 @@ xfs_change_file_space( xfs_off_t startoffset; xfs_off_t llen; xfs_trans_t *tp; - vattr_t va; + bhv_vattr_t va; bhv_vnode_t *vp; vp = BHV_TO_VNODE(bdp); -- cgit v1.2.3 From 34327e138481137a81a2e33060b8eb0944013801 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Fri, 9 Jun 2006 17:11:55 +1000 Subject: [XFS] Cleanup a missed porting conversion, and freezing. SGI-PV: 953338 SGI-Modid: xfs-linux-melb:xfs-kern:26109a Signed-off-by: Nathan Scott --- fs/xfs/linux-2.6/xfs_lrw.c | 4 ++-- fs/xfs/linux-2.6/xfs_vfs.h | 7 +++---- fs/xfs/xfs_log.c | 2 +- fs/xfs/xfs_trans.c | 17 +++++------------ 4 files changed, 11 insertions(+), 19 deletions(-) diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c index 8696096f8d2..3e76c5c9dda 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.c +++ b/fs/xfs/linux-2.6/xfs_lrw.c @@ -668,11 +668,11 @@ xfs_write( io = &xip->i_iocore; mp = io->io_mount; + vfs_wait_for_freeze(vp->v_vfsp, SB_FREEZE_WRITE); + if (XFS_FORCED_SHUTDOWN(mp)) return -EIO; - fs_check_frozen(vp->v_vfsp, SB_FREEZE_WRITE); - if (ioflags & IO_ISDIRECT) { xfs_buftarg_t *target = (xip->i_d.di_flags & XFS_DIFLAG_REALTIME) ? diff --git a/fs/xfs/linux-2.6/xfs_vfs.h b/fs/xfs/linux-2.6/xfs_vfs.h index 7b88eeae0f2..91fc2c4b335 100644 --- a/fs/xfs/linux-2.6/xfs_vfs.h +++ b/fs/xfs/linux-2.6/xfs_vfs.h @@ -190,6 +190,9 @@ extern void vfs_init_vnode(bhv_desc_t *, struct bhv_vnode *, bhv_desc_t *, int); extern void vfs_force_shutdown(bhv_desc_t *, int, char *, int); extern void vfs_freeze(bhv_desc_t *); +#define vfs_test_for_freeze(vfs) ((vfs)->vfs_super->s_frozen) +#define vfs_wait_for_freeze(vfs,l) vfs_check_frozen((vfs)->vfs_super, (l)) + typedef struct bhv_module_vfsops { struct bhv_vfsops bhv_common; void * bhv_custom; @@ -211,8 +214,4 @@ extern void bhv_insert_all_vfsops(struct bhv_vfs *); extern void bhv_remove_all_vfsops(struct bhv_vfs *, int); extern void bhv_remove_vfsops(struct bhv_vfs *, int); -#define fs_frozen(vfsp) ((vfsp)->vfs_super->s_frozen) -#define fs_check_frozen(vfsp, level) \ - vfs_check_frozen(vfsp->vfs_super, level); - #endif /* __XFS_VFS_H__ */ diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 9f70ab3e098..95d679cd4e7 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -817,7 +817,7 @@ xfs_log_need_covered(xfs_mount_t *mp) xlog_t *log = mp->m_log; bhv_vfs_t *vfsp = XFS_MTOVFS(mp); - if (fs_frozen(vfsp) || XFS_FORCED_SHUTDOWN(mp) || + if (vfs_test_for_freeze(vfsp) || XFS_FORCED_SHUTDOWN(mp) || (vfsp->vfs_flag & VFS_RDONLY)) return 0; diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index 7a99ed3b187..39f0b1ed322 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -236,11 +236,8 @@ xfs_trans_alloc( xfs_mount_t *mp, uint type) { - fs_check_frozen(XFS_MTOVFS(mp), SB_FREEZE_TRANS); - atomic_inc(&mp->m_active_trans); - - return (_xfs_trans_alloc(mp, type)); - + vfs_wait_for_freeze(XFS_MTOVFS(mp), SB_FREEZE_TRANS); + return _xfs_trans_alloc(mp, type); } xfs_trans_t * @@ -250,12 +247,9 @@ _xfs_trans_alloc( { xfs_trans_t *tp; - ASSERT(xfs_trans_zone != NULL); - tp = kmem_zone_zalloc(xfs_trans_zone, KM_SLEEP); + atomic_inc(&mp->m_active_trans); - /* - * Initialize the transaction structure. - */ + tp = kmem_zone_zalloc(xfs_trans_zone, KM_SLEEP); tp->t_magic = XFS_TRANS_MAGIC; tp->t_type = type; tp->t_mountp = mp; @@ -263,8 +257,7 @@ _xfs_trans_alloc( tp->t_busy_free = XFS_LBC_NUM_SLOTS; XFS_LIC_INIT(&(tp->t_items)); XFS_LBC_INIT(&(tp->t_busy)); - - return (tp); + return tp; } /* -- cgit v1.2.3 From a916e2bd15b7572d9e791ae2a9333f74175470cd Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Fri, 9 Jun 2006 17:12:17 +1000 Subject: [XFS] Remove unused parameter from di2xflags routine. SGI-PV: 904192 SGI-Modid: xfs-linux-melb:xfs-kern:26110a Signed-off-by: Nathan Scott --- fs/xfs/xfs_inode.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 848783ba565..926d372ae0f 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -783,7 +783,6 @@ xfs_xlate_dinode_core( STATIC uint _xfs_dic2xflags( - xfs_dinode_core_t *dic, __uint16_t di_flags) { uint flags = 0; @@ -826,16 +825,16 @@ xfs_ip2xflags( { xfs_dinode_core_t *dic = &ip->i_d; - return _xfs_dic2xflags(dic, dic->di_flags) | - (XFS_CFORK_Q(dic) ? XFS_XFLAG_HASATTR : 0); + return _xfs_dic2xflags(dic->di_flags) | + (XFS_CFORK_Q(dic) ? XFS_XFLAG_HASATTR : 0); } uint xfs_dic2xflags( xfs_dinode_core_t *dic) { - return _xfs_dic2xflags(dic, INT_GET(dic->di_flags, ARCH_CONVERT)) | - (XFS_CFORK_Q_DISK(dic) ? XFS_XFLAG_HASATTR : 0); + return _xfs_dic2xflags(INT_GET(dic->di_flags, ARCH_CONVERT)) | + (XFS_CFORK_Q_DISK(dic) ? XFS_XFLAG_HASATTR : 0); } /* -- cgit v1.2.3 From 4d1a2ed3d8d6e306d20f5d99a5ae12ac4c8b787b Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Fri, 9 Jun 2006 17:12:28 +1000 Subject: [XFS] Fix up debug code so that bulkstat wont generate thousands of fsstress warnings. SGI-PV: 904196 SGI-Modid: xfs-linux-melb:xfs-kern:26111a Signed-off-by: Nathan Scott --- fs/xfs/xfs_ialloc.c | 3 +++ fs/xfs/xfs_inode.c | 22 ++++++++++++---------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c index deddbd03c16..7e5ccfec92b 100644 --- a/fs/xfs/xfs_ialloc.c +++ b/fs/xfs/xfs_ialloc.c @@ -1174,6 +1174,9 @@ xfs_dilocate( if (agno >= mp->m_sb.sb_agcount || agbno >= mp->m_sb.sb_agblocks || ino != XFS_AGINO_TO_INO(mp, agno, agino)) { #ifdef DEBUG + /* no diagnostics for bulkstat, ino comes from userspace */ + if (flags & XFS_IMAP_BULKSTAT) + return XFS_ERROR(EINVAL); if (agno >= mp->m_sb.sb_agcount) { xfs_fs_cmn_err(CE_ALERT, mp, "xfs_dilocate: agno (%d) >= " diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 926d372ae0f..9af9e32a6a1 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -256,13 +256,11 @@ xfs_itobp( xfs_daddr_t bno, uint imap_flags) { + xfs_imap_t imap; xfs_buf_t *bp; int error; - xfs_imap_t imap; -#ifdef __KERNEL__ int i; int ni; -#endif if (ip->i_blkno == (xfs_daddr_t)0) { /* @@ -319,7 +317,6 @@ xfs_itobp( */ error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, imap.im_blkno, (int)imap.im_len, XFS_BUF_LOCK, &bp); - if (error) { #ifdef DEBUG xfs_fs_cmn_err(CE_ALERT, mp, "xfs_itobp: " @@ -330,17 +327,21 @@ xfs_itobp( #endif /* DEBUG */ return error; } -#ifdef __KERNEL__ + /* * Validate the magic number and version of every inode in the buffer * (if DEBUG kernel) or the first inode in the buffer, otherwise. + * No validation is done here in userspace (xfs_repair). */ -#ifdef DEBUG +#if !defined(__KERNEL__) + ni = 0; +#elif defined(DEBUG) ni = (imap_flags & XFS_IMAP_BULKSTAT) ? 0 : (BBTOB(imap.im_len) >> mp->m_sb.sb_inodelog); -#else +#else /* usual case */ ni = (imap_flags & XFS_IMAP_BULKSTAT) ? 0 : 1; #endif + for (i = 0; i < ni; i++) { int di_ok; xfs_dinode_t *dip; @@ -352,8 +353,10 @@ xfs_itobp( if (unlikely(XFS_TEST_ERROR(!di_ok, mp, XFS_ERRTAG_ITOBP_INOTOBP, XFS_RANDOM_ITOBP_INOTOBP))) { #ifdef DEBUG - cmn_err(CE_ALERT, "Device %s - bad inode magic/vsn " - "daddr %lld #%d (magic=%x)", + if (!(imap_flags & XFS_IMAP_BULKSTAT)) + cmn_err(CE_ALERT, + "Device %s - bad inode magic/vsn " + "daddr %lld #%d (magic=%x)", XFS_BUFTARG_NAME(mp->m_ddev_targp), (unsigned long long)imap.im_blkno, i, INT_GET(dip->di_core.di_magic, ARCH_CONVERT)); @@ -364,7 +367,6 @@ xfs_itobp( return XFS_ERROR(EFSCORRUPTED); } } -#endif /* __KERNEL__ */ xfs_inobp_check(mp, bp); -- cgit v1.2.3 From 421ad134583bff86c0ae068e2ddcb17f530957ab Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Fri, 9 Jun 2006 17:12:46 +1000 Subject: [XFS] Fix mismerge of the fs_writable cleanup patch causing a freeze/thaw test hang. SGI-PV: 953563 SGI-Modid: xfs-linux-melb:xfs-kern:26182a Signed-off-by: Nathan Scott --- fs/xfs/xfs_fsops.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index 502483c41f9..650d35f537b 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -542,14 +542,13 @@ xfs_reserve_blocks( } void -xfs_fs_log_dummy(xfs_mount_t *mp) +xfs_fs_log_dummy( + xfs_mount_t *mp) { - xfs_trans_t *tp; - xfs_inode_t *ip; - + xfs_trans_t *tp; + xfs_inode_t *ip; tp = _xfs_trans_alloc(mp, XFS_TRANS_DUMMY1); - atomic_inc(&mp->m_active_trans); if (xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES(mp), 0, 0, 0)) { xfs_trans_cancel(tp, 0); return; -- cgit v1.2.3 From 477829ef2e9e831c56c98948cfef6dfcec305c3a Mon Sep 17 00:00:00 2001 From: Mandy Kirkconnell Date: Fri, 9 Jun 2006 17:13:04 +1000 Subject: [XFS] Fix nused counter. It's currently getting set to -1 rather than getting decremented by 1. Since nused never reaches 0, the "if (!free->hdr.nused)" check in xfs_dir2_leafn_remove() fails every time and xfs_dir2_shrink_inode() doesn't get called when it should. This causes extra blocks to be left on an empty directory and the directory in unable to be converted back to inline extent mode. SGI-PV: 951958 SGI-Modid: xfs-linux-melb:xfs-kern:211382a Signed-off-by: Mandy Kirkconnell Signed-off-by: Nathan Scott --- fs/xfs/xfs_dir2_node.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c index a8d483c0a84..b1f85cc7795 100644 --- a/fs/xfs/xfs_dir2_node.c +++ b/fs/xfs/xfs_dir2_node.c @@ -972,7 +972,7 @@ xfs_dir2_leafn_remove( /* * One less used entry in the free table. */ - free->hdr.nused = cpu_to_be32(-1); + be32_add(&free->hdr.nused, -1); xfs_dir2_free_log_header(tp, fbp); /* * If this was the last entry in the table, we can -- cgit v1.2.3 From b190f1138b0f30fbe837b3f09fb6ffdb2fc4da24 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Fri, 9 Jun 2006 17:13:15 +1000 Subject: [XFS] Fix broken const use inside local suffix_strtoul routine. SGI-PV: 904196 SGI-Modid: xfs-linux-melb:xfs-kern:26201a Signed-off-by: Nathan Scott --- fs/xfs/xfs_vfsops.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c index 7550583bd09..918531b6478 100644 --- a/fs/xfs/xfs_vfsops.c +++ b/fs/xfs/xfs_vfsops.c @@ -1654,10 +1654,10 @@ xfs_vget( #define MNTOPT_NOATTR2 "noattr2" /* do not use attr2 attribute format */ STATIC unsigned long -suffix_strtoul(const char *cp, char **endp, unsigned int base) +suffix_strtoul(char *s, char **endp, unsigned int base) { int last, shift_left_factor = 0; - char *value = (char *)cp; + char *value = s; last = strlen(value) - 1; if (value[last] == 'K' || value[last] == 'k') { @@ -1673,7 +1673,7 @@ suffix_strtoul(const char *cp, char **endp, unsigned int base) value[last] = '\0'; } - return simple_strtoul(cp, endp, base) << shift_left_factor; + return simple_strtoul((const char *)s, endp, base) << shift_left_factor; } STATIC int -- cgit v1.2.3 From 98a90c02792f22afd8161f96fc9b9f0f0eb0880e Mon Sep 17 00:00:00 2001 From: Renzo Davoli Date: Sun, 21 May 2006 20:06:58 +0200 Subject: [PATCH] powerpc: enable PPC_PTRACE_[GS]ETREGS on ppc32 I have tested PPC_PTRACE_GETREGS and PPC_PTRACE_SETREGS on umview. I do not understand why historically these tags has been defined as PPC_PTRACE_GETREGS and PPC_PTRACE_SETREGS instead of simply PTRACE_[GS]ETREGS. The other "originality" is that the address must be put into the "addr" field instead of the "data" field as stated in the manual. Signed-off-by: renzo davoli Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/ptrace.c | 2 -- include/asm-powerpc/ptrace.h | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index 4a677d1bd4e..5563e2e7d89 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c @@ -404,7 +404,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ret = ptrace_detach(child, data); break; -#ifdef CONFIG_PPC64 case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */ int i; unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; @@ -468,7 +467,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) } break; } -#endif /* CONFIG_PPC64 */ #ifdef CONFIG_ALTIVEC case PTRACE_GETVRREGS: diff --git a/include/asm-powerpc/ptrace.h b/include/asm-powerpc/ptrace.h index 9c550b31482..dc4cb9cc73a 100644 --- a/include/asm-powerpc/ptrace.h +++ b/include/asm-powerpc/ptrace.h @@ -229,13 +229,13 @@ do { \ #define PTRACE_GET_DEBUGREG 25 #define PTRACE_SET_DEBUGREG 26 -#ifdef __powerpc64__ /* Additional PTRACE requests implemented on PowerPC. */ #define PPC_PTRACE_GETREGS 0x99 /* Get GPRs 0 - 31 */ #define PPC_PTRACE_SETREGS 0x98 /* Set GPRs 0 - 31 */ #define PPC_PTRACE_GETFPREGS 0x97 /* Get FPRs 0 - 31 */ #define PPC_PTRACE_SETFPREGS 0x96 /* Set FPRs 0 - 31 */ +#ifdef __powerpc64__ /* Calls to trace a 64bit program from a 32bit program */ #define PPC_PTRACE_PEEKTEXT_3264 0x95 #define PPC_PTRACE_PEEKDATA_3264 0x94 -- cgit v1.2.3 From a5bba930d802009c259e56c8d53086d96f63813b Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 30 May 2006 13:51:37 +1000 Subject: [PATCH] powerpc vdso updates This patch cleans up some locking & error handling in the ppc vdso and moves the vdso base pointer from the thread struct to the mm context where it more logically belongs. It brings the powerpc implementation closer to Ingo's new x86 one and also adds an arch_vma_name() function allowing to print [vsdo] in /proc//maps if Ingo's x86 vdso patch is also applied. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/signal_32.c | 8 +++--- arch/powerpc/kernel/signal_64.c | 4 +-- arch/powerpc/kernel/vdso.c | 57 ++++++++++++++++++++++++++--------------- include/asm-powerpc/elf.h | 2 +- include/asm-powerpc/mmu.h | 1 + include/asm-powerpc/page.h | 3 +++ include/asm-powerpc/processor.h | 1 - 7 files changed, 47 insertions(+), 29 deletions(-) diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index 01e3c08cb55..22f07898484 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c @@ -757,10 +757,10 @@ static int handle_rt_signal(unsigned long sig, struct k_sigaction *ka, /* Save user registers on the stack */ frame = &rt_sf->uc.uc_mcontext; - if (vdso32_rt_sigtramp && current->thread.vdso_base) { + if (vdso32_rt_sigtramp && current->mm->context.vdso_base) { if (save_user_regs(regs, frame, 0)) goto badframe; - regs->link = current->thread.vdso_base + vdso32_rt_sigtramp; + regs->link = current->mm->context.vdso_base + vdso32_rt_sigtramp; } else { if (save_user_regs(regs, frame, __NR_rt_sigreturn)) goto badframe; @@ -1029,10 +1029,10 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka, || __put_user(sig, &sc->signal)) goto badframe; - if (vdso32_sigtramp && current->thread.vdso_base) { + if (vdso32_sigtramp && current->mm->context.vdso_base) { if (save_user_regs(regs, &frame->mctx, 0)) goto badframe; - regs->link = current->thread.vdso_base + vdso32_sigtramp; + regs->link = current->mm->context.vdso_base + vdso32_sigtramp; } else { if (save_user_regs(regs, &frame->mctx, __NR_sigreturn)) goto badframe; diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index 27f65b95184..23ba69c2691 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c @@ -394,8 +394,8 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, current->thread.fpscr.val = 0; /* Set up to return from userspace. */ - if (vdso64_rt_sigtramp && current->thread.vdso_base) { - regs->link = current->thread.vdso_base + vdso64_rt_sigtramp; + if (vdso64_rt_sigtramp && current->mm->context.vdso_base) { + regs->link = current->mm->context.vdso_base + vdso64_rt_sigtramp; } else { err |= setup_trampoline(__NR_rt_sigreturn, &frame->tramp[0]); if (err) diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c index 573afb68d69..bc3e15be308 100644 --- a/arch/powerpc/kernel/vdso.c +++ b/arch/powerpc/kernel/vdso.c @@ -223,6 +223,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, struct vm_area_struct *vma; unsigned long vdso_pages; unsigned long vdso_base; + int rc; #ifdef CONFIG_PPC64 if (test_thread_flag(TIF_32BIT)) { @@ -237,20 +238,13 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, vdso_base = VDSO32_MBASE; #endif - current->thread.vdso_base = 0; + current->mm->context.vdso_base = 0; /* vDSO has a problem and was disabled, just don't "enable" it for the * process */ if (vdso_pages == 0) return 0; - - vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); - if (vma == NULL) - return -ENOMEM; - - memset(vma, 0, sizeof(*vma)); - /* Add a page to the vdso size for the data page */ vdso_pages ++; @@ -259,17 +253,23 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, * at vdso_base which is the "natural" base for it, but we might fail * and end up putting it elsewhere. */ + down_write(&mm->mmap_sem); vdso_base = get_unmapped_area(NULL, vdso_base, vdso_pages << PAGE_SHIFT, 0, 0); - if (vdso_base & ~PAGE_MASK) { - kmem_cache_free(vm_area_cachep, vma); - return (int)vdso_base; + if (IS_ERR_VALUE(vdso_base)) { + rc = vdso_base; + goto fail_mmapsem; } - current->thread.vdso_base = vdso_base; + /* Allocate a VMA structure and fill it up */ + vma = kmem_cache_zalloc(vm_area_cachep, SLAB_KERNEL); + if (vma == NULL) { + rc = -ENOMEM; + goto fail_mmapsem; + } vma->vm_mm = mm; - vma->vm_start = current->thread.vdso_base; + vma->vm_start = vdso_base; vma->vm_end = vma->vm_start + (vdso_pages << PAGE_SHIFT); /* @@ -282,23 +282,38 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, * It's fine to use that for setting breakpoints in the vDSO code * pages though */ - vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC; + vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC; vma->vm_flags |= mm->def_flags; vma->vm_page_prot = protection_map[vma->vm_flags & 0x7]; vma->vm_ops = &vdso_vmops; - down_write(&mm->mmap_sem); - if (insert_vm_struct(mm, vma)) { - up_write(&mm->mmap_sem); - kmem_cache_free(vm_area_cachep, vma); - return -ENOMEM; - } + /* Insert new VMA */ + rc = insert_vm_struct(mm, vma); + if (rc) + goto fail_vma; + + /* Put vDSO base into mm struct and account for memory usage */ + current->mm->context.vdso_base = vdso_base; mm->total_vm += (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; up_write(&mm->mmap_sem); - return 0; + + fail_vma: + kmem_cache_free(vm_area_cachep, vma); + fail_mmapsem: + up_write(&mm->mmap_sem); + return rc; +} + +const char *arch_vma_name(struct vm_area_struct *vma) +{ + if (vma->vm_mm && vma->vm_start == vma->vm_mm->context.vdso_base) + return "[vdso]"; + return NULL; } + + static void * __init find_section32(Elf32_Ehdr *ehdr, const char *secname, unsigned long *size) { diff --git a/include/asm-powerpc/elf.h b/include/asm-powerpc/elf.h index 94d228f9c6a..319655ce66c 100644 --- a/include/asm-powerpc/elf.h +++ b/include/asm-powerpc/elf.h @@ -294,7 +294,7 @@ do { \ NEW_AUX_ENT(AT_DCACHEBSIZE, dcache_bsize); \ NEW_AUX_ENT(AT_ICACHEBSIZE, icache_bsize); \ NEW_AUX_ENT(AT_UCACHEBSIZE, ucache_bsize); \ - VDSO_AUX_ENT(AT_SYSINFO_EHDR, current->thread.vdso_base) \ + VDSO_AUX_ENT(AT_SYSINFO_EHDR, current->mm->context.vdso_base) \ } while (0) /* PowerPC64 relocations defined by the ABIs */ diff --git a/include/asm-powerpc/mmu.h b/include/asm-powerpc/mmu.h index 31f721994bd..96e47d1ce97 100644 --- a/include/asm-powerpc/mmu.h +++ b/include/asm-powerpc/mmu.h @@ -360,6 +360,7 @@ typedef struct { #ifdef CONFIG_HUGETLB_PAGE u16 low_htlb_areas, high_htlb_areas; #endif + unsigned long vdso_base; } mm_context_t; diff --git a/include/asm-powerpc/page.h b/include/asm-powerpc/page.h index ae610b62048..a315d0c0d96 100644 --- a/include/asm-powerpc/page.h +++ b/include/asm-powerpc/page.h @@ -192,6 +192,9 @@ extern void copy_user_page(void *to, void *from, unsigned long vaddr, struct page *p); extern int page_is_ram(unsigned long pfn); +struct vm_area_struct; +extern const char *arch_vma_name(struct vm_area_struct *vma); + #include #endif /* __ASSEMBLY__ */ diff --git a/include/asm-powerpc/processor.h b/include/asm-powerpc/processor.h index 93f83efeb31..d5c7ef1cca2 100644 --- a/include/asm-powerpc/processor.h +++ b/include/asm-powerpc/processor.h @@ -153,7 +153,6 @@ struct thread_struct { unsigned long start_tb; /* Start purr when proc switched in */ unsigned long accum_tb; /* Total accumilated purr for process */ #endif - unsigned long vdso_base; /* base of the vDSO library */ unsigned long dabr; /* Data address breakpoint register */ #ifdef CONFIG_ALTIVEC /* Complete AltiVec register set */ -- cgit v1.2.3 From c5cf0e30bf3d8cb56758abb612827647c0a821cf Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 30 May 2006 14:14:19 +1000 Subject: [PATCH] powerpc: Fix buglet with MMU hash management Our MMU hash management code would not set the "C" bit (changed bit) in the hardware PTE when updating a RO PTE into a RW PTE. That would cause the hardware to possibly to a write back to the hash table to set it on the first store access, which in addition to being a performance issue, might also hit a bug when running with native hash management (non-HV) as our code is specifically optimized for the case where no write back happens. Thus there is a very small therocial window were a hash PTE can become corrupted if that HPTE has just been upgraded to read write, a store access happens on it, and that races with another processor evicting that same slot. Since eviction (caused by an almost full hash) is extremely rare, the bug is very unlikely to happen fortunately. This fixes by allowing the updating of the protection bits in the native hash handling to also set (but not clear) the "C" bit, and, in order to also improve performances in the general case, by always setting that bit on newly inserted hash PTE so that writeback really never happens. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/mm/hash_low_64.S | 3 +++ arch/powerpc/mm/hash_native_64.c | 2 +- include/asm-powerpc/mmu.h | 2 ++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/mm/hash_low_64.S b/arch/powerpc/mm/hash_low_64.S index e0d02c4a261..106fba39198 100644 --- a/arch/powerpc/mm/hash_low_64.S +++ b/arch/powerpc/mm/hash_low_64.S @@ -136,6 +136,7 @@ _GLOBAL(__hash_page_4K) and r0,r0,r4 /* _PAGE_RW & _PAGE_DIRTY ->r0 bit 30*/ andc r0,r30,r0 /* r0 = pte & ~r0 */ rlwimi r3,r0,32-1,31,31 /* Insert result into PP lsb */ + ori r3,r3,HPTE_R_C /* Always add "C" bit for perf. */ /* We eventually do the icache sync here (maybe inline that * code rather than call a C function...) @@ -400,6 +401,7 @@ _GLOBAL(__hash_page_4K) and r0,r0,r4 /* _PAGE_RW & _PAGE_DIRTY ->r0 bit 30*/ andc r0,r30,r0 /* r0 = pte & ~r0 */ rlwimi r3,r0,32-1,31,31 /* Insert result into PP lsb */ + ori r3,r3,HPTE_R_C /* Always add "C" bit for perf. */ /* We eventually do the icache sync here (maybe inline that * code rather than call a C function...) @@ -671,6 +673,7 @@ _GLOBAL(__hash_page_64K) and r0,r0,r4 /* _PAGE_RW & _PAGE_DIRTY ->r0 bit 30*/ andc r0,r30,r0 /* r0 = pte & ~r0 */ rlwimi r3,r0,32-1,31,31 /* Insert result into PP lsb */ + ori r3,r3,HPTE_R_C /* Always add "C" bit for perf. */ /* We eventually do the icache sync here (maybe inline that * code rather than call a C function...) diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c index 33654d1b1b4..3b8205033f1 100644 --- a/arch/powerpc/mm/hash_native_64.c +++ b/arch/powerpc/mm/hash_native_64.c @@ -238,7 +238,7 @@ static long native_hpte_updatepp(unsigned long slot, unsigned long newpp, DBG_LOW(" -> hit\n"); /* Update the HPTE */ hptep->r = (hptep->r & ~(HPTE_R_PP | HPTE_R_N)) | - (newpp & (HPTE_R_PP | HPTE_R_N)); + (newpp & (HPTE_R_PP | HPTE_R_N | HPTE_R_C)); native_unlock_hpte(hptep); } diff --git a/include/asm-powerpc/mmu.h b/include/asm-powerpc/mmu.h index 96e47d1ce97..88539742010 100644 --- a/include/asm-powerpc/mmu.h +++ b/include/asm-powerpc/mmu.h @@ -96,6 +96,8 @@ extern char initial_stab[]; #define HPTE_R_FLAGS ASM_CONST(0x00000000000003ff) #define HPTE_R_PP ASM_CONST(0x0000000000000003) #define HPTE_R_N ASM_CONST(0x0000000000000004) +#define HPTE_R_C ASM_CONST(0x0000000000000080) +#define HPTE_R_R ASM_CONST(0x0000000000000100) /* Values for PP (assumes Ks=0, Kp=1) */ /* pp0 will always be 0 for linux */ -- cgit v1.2.3 From 03ac829b0046d5769eef3dd841cec33a211db96e Mon Sep 17 00:00:00 2001 From: Will Schmidt Date: Tue, 30 May 2006 13:38:40 -0500 Subject: [PATCH] powerpc: fix of_parse_dma_window My js20 appears to lack the ibm,#dma- properties, and boot fails with a "Kernel panic - not syncing: iommu_init_table: Can't allocate 0 bytes" message. This adds a fallback to the "#address-cells" property in case the "#ibm,dma-address-cells" property is missing. Tested on js20 and power5 lpar. Unless there is a more elegant solution... :-) Signed-off-by: Will Schmidt Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/prom_parse.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c index 23bb060330e..45df420383c 100644 --- a/arch/powerpc/kernel/prom_parse.c +++ b/arch/powerpc/kernel/prom_parse.c @@ -561,6 +561,9 @@ void of_parse_dma_window(struct device_node *dn, unsigned char *dma_window_prop, *busno = *(dma_window++); prop = get_property(dn, "ibm,#dma-address-cells", NULL); + if (!prop) + prop = get_property(dn, "#address-cells", NULL); + cells = prop ? *(u32 *)prop : prom_n_addr_cells(dn); *phys = of_read_addr(dma_window, cells); -- cgit v1.2.3 From 87af41beb9b70f06f760fc973b793488f2825853 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Fri, 5 May 2006 05:44:26 +1000 Subject: [PATCH] powerpc: add num_pmcs to 970MP cputable entry The 970MP cputable entry needs a num_pmcs entry for oprofile to work. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/cputable.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 0c487ee4d48..7dcc01be4b0 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -220,6 +220,7 @@ struct cpu_spec cpu_specs[] = { PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 128, .dcache_bsize = 128, + .num_pmcs = 8, .cpu_setup = __setup_cpu_ppc970, .oprofile_cpu_type = "ppc64/970", .oprofile_type = PPC_OPROFILE_POWER4, -- cgit v1.2.3 From 4a3ecc622465dbff7404139a8ad18bf4cb99f836 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 1 Jun 2006 20:36:04 -0700 Subject: [PATCH] powerpc kbuild warning fix From: Andrew Morton arch/powerpc/Kconfig:339:warning: leading whitespace ignored arch/powerpc/Kconfig:347:warning: leading whitespace ignored arch/powerpc/Kconfig:357:warning: leading whitespace ignored arch/powerpc/Kconfig:373:warning: leading whitespace ignored arch/powerpc/Kconfig:382:warning: leading whitespace ignored arch/powerpc/Kconfig:394:warning: leading whitespace ignored arch/powerpc/Kconfig:842:warning: leading whitespace ignored arch/powerpc/Kconfig:847:warning: leading whitespace ignored Cc: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Paul Mackerras --- arch/powerpc/Kconfig | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 75ba0ec49e5..7eb0ef2b003 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -340,7 +340,7 @@ endchoice config PPC_PSERIES depends on PPC_MULTIPLATFORM && PPC64 - bool " IBM pSeries & new (POWER5-based) iSeries" + bool "IBM pSeries & new (POWER5-based) iSeries" select PPC_I8259 select PPC_RTAS select RTAS_ERROR_LOGGING @@ -348,7 +348,7 @@ config PPC_PSERIES default y config PPC_CHRP - bool " Common Hardware Reference Platform (CHRP) based machines" + bool "Common Hardware Reference Platform (CHRP) based machines" depends on PPC_MULTIPLATFORM && PPC32 select PPC_I8259 select PPC_INDIRECT_PCI @@ -358,7 +358,7 @@ config PPC_CHRP default y config PPC_PMAC - bool " Apple PowerMac based machines" + bool "Apple PowerMac based machines" depends on PPC_MULTIPLATFORM select PPC_INDIRECT_PCI if PPC32 select PPC_MPC106 if PPC32 @@ -374,7 +374,7 @@ config PPC_PMAC64 default y config PPC_PREP - bool " PowerPC Reference Platform (PReP) based machines" + bool "PowerPC Reference Platform (PReP) based machines" depends on PPC_MULTIPLATFORM && PPC32 && BROKEN select PPC_I8259 select PPC_INDIRECT_PCI @@ -383,7 +383,7 @@ config PPC_PREP config PPC_MAPLE depends on PPC_MULTIPLATFORM && PPC64 - bool " Maple 970FX Evaluation Board" + bool "Maple 970FX Evaluation Board" select U3_DART select MPIC_BROKEN_U3 select GENERIC_TBSYNC @@ -395,7 +395,7 @@ config PPC_MAPLE For more informations, refer to config PPC_CELL - bool " Cell Broadband Processor Architecture" + bool "Cell Broadband Processor Architecture" depends on PPC_MULTIPLATFORM && PPC64 select PPC_RTAS select MMIO_NVRAM @@ -831,12 +831,12 @@ config PCI_8260 default y config 8260_PCI9 - bool " Enable workaround for MPC826x erratum PCI 9" + bool "Enable workaround for MPC826x erratum PCI 9" depends on PCI_8260 && !ADS8272 default y choice - prompt " IDMA channel for PCI 9 workaround" + prompt "IDMA channel for PCI 9 workaround" depends on 8260_PCI9 config 8260_PCI9_IDMA1 -- cgit v1.2.3 From 507279db1819aacf4022e790b3fc8bc8cf56debf Mon Sep 17 00:00:00 2001 From: John Rose Date: Mon, 5 Jun 2006 16:31:48 -0500 Subject: [PATCH] powerpc: reorg RTAS delay code This patch attempts to handle RTAS "busy" return codes in a more simple and consistent manner. Typical callers of RTAS shouldn't have to manage wait times and delay calls. This patch also changes the kernel to use msleep() rather than udelay() when a runtime delay is necessary. This will avoid CPU soft lockups for extended delay conditions. Signed-off-by: John Rose Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/rtas-rtc.c | 30 +++++++------- arch/powerpc/kernel/rtas.c | 85 +++++++++++++++++----------------------- arch/powerpc/kernel/rtas_flash.c | 25 ++---------- include/asm-powerpc/rtas.h | 8 +--- 4 files changed, 57 insertions(+), 91 deletions(-) diff --git a/arch/powerpc/kernel/rtas-rtc.c b/arch/powerpc/kernel/rtas-rtc.c index 34d073fb609..77578c093dd 100644 --- a/arch/powerpc/kernel/rtas-rtc.c +++ b/arch/powerpc/kernel/rtas-rtc.c @@ -14,19 +14,20 @@ unsigned long __init rtas_get_boot_time(void) { int ret[8]; - int error, wait_time; + int error; + unsigned int wait_time; u64 max_wait_tb; max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT; do { error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret); - if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) { - wait_time = rtas_extended_busy_delay_time(error); + + wait_time = rtas_busy_delay_time(error); + if (wait_time) { /* This is boot time so we spin. */ udelay(wait_time*1000); - error = RTAS_CLOCK_BUSY; } - } while (error == RTAS_CLOCK_BUSY && (get_tb() < max_wait_tb)); + } while (wait_time && (get_tb() < max_wait_tb)); if (error != 0 && printk_ratelimit()) { printk(KERN_WARNING "error: reading the clock failed (%d)\n", @@ -44,24 +45,25 @@ unsigned long __init rtas_get_boot_time(void) void rtas_get_rtc_time(struct rtc_time *rtc_tm) { int ret[8]; - int error, wait_time; + int error; + unsigned int wait_time; u64 max_wait_tb; max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT; do { error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret); - if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) { + + wait_time = rtas_busy_delay_time(error); + if (wait_time) { if (in_interrupt() && printk_ratelimit()) { memset(rtc_tm, 0, sizeof(struct rtc_time)); printk(KERN_WARNING "error: reading clock" " would delay interrupt\n"); return; /* delay not allowed */ } - wait_time = rtas_extended_busy_delay_time(error); msleep(wait_time); - error = RTAS_CLOCK_BUSY; } - } while (error == RTAS_CLOCK_BUSY && (get_tb() < max_wait_tb)); + } while (wait_time && (get_tb() < max_wait_tb)); if (error != 0 && printk_ratelimit()) { printk(KERN_WARNING "error: reading the clock failed (%d)\n", @@ -88,14 +90,14 @@ int rtas_set_rtc_time(struct rtc_time *tm) tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, 0); - if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) { + + wait_time = rtas_busy_delay_time(error); + if (wait_time) { if (in_interrupt()) return 1; /* probably decrementer */ - wait_time = rtas_extended_busy_delay_time(error); msleep(wait_time); - error = RTAS_CLOCK_BUSY; } - } while (error == RTAS_CLOCK_BUSY && (get_tb() < max_wait_tb)); + } while (wait_time && (get_tb() < max_wait_tb)); if (error != 0 && printk_ratelimit()) printk(KERN_WARNING "error: setting the clock failed (%d)\n", diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 0112318213a..13496f31985 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -370,24 +370,36 @@ int rtas_call(int token, int nargs, int nret, int *outputs, ...) return ret; } -/* Given an RTAS status code of 990n compute the hinted delay of 10^n - * (last digit) milliseconds. For now we bound at n=5 (100 sec). +/* For RTAS_BUSY (-2), delay for 1 millisecond. For an extended busy status + * code of 990n, perform the hinted delay of 10^n (last digit) milliseconds. */ -unsigned int rtas_extended_busy_delay_time(int status) +unsigned int rtas_busy_delay_time(int status) { - int order = status - 9900; - unsigned long ms; + int order; + unsigned int ms = 0; + + if (status == RTAS_BUSY) { + ms = 1; + } else if (status >= 9900 && status <= 9905) { + order = status - 9900; + for (ms = 1; order > 0; order--) + ms *= 10; + } - if (order < 0) - order = 0; /* RTC depends on this for -2 clock busy */ - else if (order > 5) - order = 5; /* bound */ + return ms; +} - /* Use microseconds for reasonable accuracy */ - for (ms = 1; order > 0; order--) - ms *= 10; +/* For an RTAS busy status code, perform the hinted delay. */ +unsigned int rtas_busy_delay(int status) +{ + unsigned int ms; - return ms; + might_sleep(); + ms = rtas_busy_delay_time(status); + if (ms) + msleep(ms); + + return ms; } int rtas_error_rc(int rtas_rc) @@ -438,22 +450,14 @@ int rtas_get_power_level(int powerdomain, int *level) int rtas_set_power_level(int powerdomain, int level, int *setlevel) { int token = rtas_token("set-power-level"); - unsigned int wait_time; int rc; if (token == RTAS_UNKNOWN_SERVICE) return -ENOENT; - while (1) { + do { rc = rtas_call(token, 2, 2, setlevel, powerdomain, level); - if (rc == RTAS_BUSY) - udelay(1); - else if (rtas_is_extended_busy(rc)) { - wait_time = rtas_extended_busy_delay_time(rc); - udelay(wait_time * 1000); - } else - break; - } + } while (rtas_busy_delay(rc)); if (rc < 0) return rtas_error_rc(rc); @@ -463,22 +467,14 @@ int rtas_set_power_level(int powerdomain, int level, int *setlevel) int rtas_get_sensor(int sensor, int index, int *state) { int token = rtas_token("get-sensor-state"); - unsigned int wait_time; int rc; if (token == RTAS_UNKNOWN_SERVICE) return -ENOENT; - while (1) { + do { rc = rtas_call(token, 2, 2, state, sensor, index); - if (rc == RTAS_BUSY) - udelay(1); - else if (rtas_is_extended_busy(rc)) { - wait_time = rtas_extended_busy_delay_time(rc); - udelay(wait_time * 1000); - } else - break; - } + } while (rtas_busy_delay(rc)); if (rc < 0) return rtas_error_rc(rc); @@ -488,23 +484,14 @@ int rtas_get_sensor(int sensor, int index, int *state) int rtas_set_indicator(int indicator, int index, int new_value) { int token = rtas_token("set-indicator"); - unsigned int wait_time; int rc; if (token == RTAS_UNKNOWN_SERVICE) return -ENOENT; - while (1) { + do { rc = rtas_call(token, 3, 1, NULL, indicator, index, new_value); - if (rc == RTAS_BUSY) - udelay(1); - else if (rtas_is_extended_busy(rc)) { - wait_time = rtas_extended_busy_delay_time(rc); - udelay(wait_time * 1000); - } - else - break; - } + } while (rtas_busy_delay(rc)); if (rc < 0) return rtas_error_rc(rc); @@ -555,13 +542,11 @@ void rtas_os_term(char *str) do { status = rtas_call(rtas_token("ibm,os-term"), 1, 1, NULL, __pa(rtas_os_term_buf)); + } while (rtas_busy_delay(status)); - if (status == RTAS_BUSY) - udelay(1); - else if (status != 0) - printk(KERN_EMERG "ibm,os-term call failed %d\n", + if (status != 0) + printk(KERN_EMERG "ibm,os-term call failed %d\n", status); - } while (status == RTAS_BUSY); } static int ibm_suspend_me_token = RTAS_UNKNOWN_SERVICE; @@ -789,7 +774,7 @@ EXPORT_SYMBOL(rtas_token); EXPORT_SYMBOL(rtas_call); EXPORT_SYMBOL(rtas_data_buf); EXPORT_SYMBOL(rtas_data_buf_lock); -EXPORT_SYMBOL(rtas_extended_busy_delay_time); +EXPORT_SYMBOL(rtas_busy_delay_time); EXPORT_SYMBOL(rtas_get_sensor); EXPORT_SYMBOL(rtas_get_power_level); EXPORT_SYMBOL(rtas_set_power_level); diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c index aaf384c3f04..1442b63a75d 100644 --- a/arch/powerpc/kernel/rtas_flash.c +++ b/arch/powerpc/kernel/rtas_flash.c @@ -365,20 +365,12 @@ static int rtas_excl_release(struct inode *inode, struct file *file) static void manage_flash(struct rtas_manage_flash_t *args_buf) { - unsigned int wait_time; s32 rc; - while (1) { + do { rc = rtas_call(rtas_token("ibm,manage-flash-image"), 1, 1, NULL, args_buf->op); - if (rc == RTAS_RC_BUSY) - udelay(1); - else if (rtas_is_extended_busy(rc)) { - wait_time = rtas_extended_busy_delay_time(rc); - udelay(wait_time * 1000); - } else - break; - } + } while (rtas_busy_delay(rc)); args_buf->status = rc; } @@ -451,27 +443,18 @@ static ssize_t manage_flash_write(struct file *file, const char __user *buf, static void validate_flash(struct rtas_validate_flash_t *args_buf) { int token = rtas_token("ibm,validate-flash-image"); - unsigned int wait_time; int update_results; s32 rc; rc = 0; - while(1) { + do { spin_lock(&rtas_data_buf_lock); memcpy(rtas_data_buf, args_buf->buf, VALIDATE_BUF_SIZE); rc = rtas_call(token, 2, 2, &update_results, (u32) __pa(rtas_data_buf), args_buf->buf_size); memcpy(args_buf->buf, rtas_data_buf, VALIDATE_BUF_SIZE); spin_unlock(&rtas_data_buf_lock); - - if (rc == RTAS_RC_BUSY) - udelay(1); - else if (rtas_is_extended_busy(rc)) { - wait_time = rtas_extended_busy_delay_time(rc); - udelay(wait_time * 1000); - } else - break; - } + } while (rtas_busy_delay(rc)); args_buf->status = rc; args_buf->update_results = update_results; diff --git a/include/asm-powerpc/rtas.h b/include/asm-powerpc/rtas.h index f43c6835e62..a3b4e55569c 100644 --- a/include/asm-powerpc/rtas.h +++ b/include/asm-powerpc/rtas.h @@ -177,12 +177,8 @@ extern unsigned long rtas_get_boot_time(void); extern void rtas_get_rtc_time(struct rtc_time *rtc_time); extern int rtas_set_rtc_time(struct rtc_time *rtc_time); -/* Given an RTAS status code of 9900..9905 compute the hinted delay */ -unsigned int rtas_extended_busy_delay_time(int status); -static inline int rtas_is_extended_busy(int status) -{ - return status >= 9900 && status <= 9909; -} +extern unsigned int rtas_busy_delay_time(int status); +extern unsigned int rtas_busy_delay(int status); extern void pSeries_log_error(char *buf, unsigned int err_type, int fatal); -- cgit v1.2.3 From 318facbee05417fb432603a8309a10cdb942a87b Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 6 Jun 2006 16:09:39 +0200 Subject: [PATCH] powerpc: implement pcibus_to_node and pcibus_to_cpumask On 64bit powerpc we can find out what node a pci bus hangs off, so implement the topology.h macros that export this information. For 32bit this seems a little more difficult, but I don't know of 32bit powerpc NUMA machines either, so let's leave it out for now. Signed-off-by: Christoph Hellwig Signed-off-by: Paul Mackerras --- include/asm-powerpc/topology.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/asm-powerpc/topology.h b/include/asm-powerpc/topology.h index 87362a05542..b7abd423c57 100644 --- a/include/asm-powerpc/topology.h +++ b/include/asm-powerpc/topology.h @@ -32,8 +32,13 @@ static inline int node_to_first_cpu(int node) int of_node_to_nid(struct device_node *device); +#ifdef CONFIG_PPC64 +#define pcibus_to_node(bus) (of_node_to_nid(bus->sysdata)) +#define pcibus_to_cpumask(bus) (node_to_cpumask(of_node_to_nid(bus->sysdata))) +#else #define pcibus_to_node(node) (-1) #define pcibus_to_cpumask(bus) (cpu_online_map) +#endif /* sched_domains SD_NODE_INIT for PPC64 machines */ #define SD_NODE_INIT (struct sched_domain) { \ -- cgit v1.2.3 From 8eb6c6e3b9c8bfed3d75536ab142d7694627c2e5 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 6 Jun 2006 16:11:35 +0200 Subject: [PATCH] powerpc: node-aware dma allocations Make sure dma_alloc_coherent allocates memory from the local node. This is important on Cell where we avoid going through the slow cpu interconnect. Note: I could only test this patch on Cell, it should be verified on some pseries machine by those that have the hardware. Signed-off-by: Christoph Hellwig Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/iommu.c | 14 ++++++++------ arch/powerpc/kernel/pci_iommu.c | 3 ++- arch/powerpc/kernel/vio.c | 2 +- include/asm-powerpc/iommu.h | 3 ++- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index 4eba60a3289..cbb794556d0 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c @@ -536,11 +536,12 @@ void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle, * to the dma address (mapping) of the first page. */ void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, - dma_addr_t *dma_handle, unsigned long mask, gfp_t flag) + dma_addr_t *dma_handle, unsigned long mask, gfp_t flag, int node) { void *ret = NULL; dma_addr_t mapping; unsigned int npages, order; + struct page *page; size = PAGE_ALIGN(size); npages = size >> PAGE_SHIFT; @@ -560,9 +561,10 @@ void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, return NULL; /* Alloc enough pages (and possibly more) */ - ret = (void *)__get_free_pages(flag, order); - if (!ret) + page = alloc_pages_node(flag, order, node); + if (!page) return NULL; + ret = page_address(page); memset(ret, 0, size); /* Set up tces to cover the allocated range */ @@ -570,9 +572,9 @@ void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, mask >> PAGE_SHIFT, order); if (mapping == DMA_ERROR_CODE) { free_pages((unsigned long)ret, order); - ret = NULL; - } else - *dma_handle = mapping; + return NULL; + } + *dma_handle = mapping; return ret; } diff --git a/arch/powerpc/kernel/pci_iommu.c b/arch/powerpc/kernel/pci_iommu.c index 48aa82d0162..7fb4cca021b 100644 --- a/arch/powerpc/kernel/pci_iommu.c +++ b/arch/powerpc/kernel/pci_iommu.c @@ -86,7 +86,8 @@ static void *pci_iommu_alloc_coherent(struct device *hwdev, size_t size, dma_addr_t *dma_handle, gfp_t flag) { return iommu_alloc_coherent(device_to_table(hwdev), size, dma_handle, - device_to_mask(hwdev), flag); + device_to_mask(hwdev), flag, + pcibus_to_node(to_pci_dev(hwdev)->bus)); } static void pci_iommu_free_coherent(struct device *hwdev, size_t size, diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index fe92727aca3..e746686d48b 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c @@ -394,7 +394,7 @@ static void *vio_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag) { return iommu_alloc_coherent(to_vio_dev(dev)->iommu_table, size, - dma_handle, ~0ul, flag); + dma_handle, ~0ul, flag, -1); } static void vio_free_coherent(struct device *dev, size_t size, diff --git a/include/asm-powerpc/iommu.h b/include/asm-powerpc/iommu.h index 18ca29e9105..9065f6c972a 100644 --- a/include/asm-powerpc/iommu.h +++ b/include/asm-powerpc/iommu.h @@ -76,7 +76,8 @@ extern void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist, int nelems, enum dma_data_direction direction); extern void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, - dma_addr_t *dma_handle, unsigned long mask, gfp_t flag); + dma_addr_t *dma_handle, unsigned long mask, + gfp_t flag, int node); extern void iommu_free_coherent(struct iommu_table *tbl, size_t size, void *vaddr, dma_addr_t dma_handle); extern dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr, -- cgit v1.2.3 From e78dbc800c37f035d476c4fdebdf43cdecfcb731 Mon Sep 17 00:00:00 2001 From: Michael Neuling Date: Thu, 8 Jun 2006 14:42:34 +1000 Subject: [PATCH] powerpc: oprofile support for POWER6 POWER6 moves some of the MMCRA bits and also requires some bits to be cleared each PMU interrupt. Signed-off-by: Michael Neuling Acked-by: Anton Blanchard Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/cputable.c | 13 +++++++++++- arch/powerpc/oprofile/op_model_power4.c | 37 +++++++++++++-------------------- include/asm-powerpc/cputable.h | 11 +++++++--- include/asm-powerpc/reg.h | 4 ++++ 4 files changed, 39 insertions(+), 26 deletions(-) diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 7dcc01be4b0..83f9ab139d4 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -237,6 +237,11 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 6, .oprofile_cpu_type = "ppc64/power5", .oprofile_type = PPC_OPROFILE_POWER4, + /* SIHV / SIPR bits are implemented on POWER4+ (GQ) + * and above but only works on POWER5 and above + */ + .oprofile_mmcra_sihv = MMCRA_SIHV, + .oprofile_mmcra_sipr = MMCRA_SIPR, .platform = "power5", }, { /* Power5 GS */ @@ -250,6 +255,8 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 6, .oprofile_cpu_type = "ppc64/power5+", .oprofile_type = PPC_OPROFILE_POWER4, + .oprofile_mmcra_sihv = MMCRA_SIHV, + .oprofile_mmcra_sipr = MMCRA_SIPR, .platform = "power5+", }, { /* Power6 */ @@ -260,9 +267,13 @@ struct cpu_spec cpu_specs[] = { .cpu_user_features = COMMON_USER_POWER6, .icache_bsize = 128, .dcache_bsize = 128, - .num_pmcs = 6, + .num_pmcs = 8, .oprofile_cpu_type = "ppc64/power6", .oprofile_type = PPC_OPROFILE_POWER4, + .oprofile_mmcra_sihv = POWER6_MMCRA_SIHV, + .oprofile_mmcra_sipr = POWER6_MMCRA_SIPR, + .oprofile_mmcra_clear = POWER6_MMCRA_THRM | + POWER6_MMCRA_OTHER, .platform = "power6", }, { /* Cell Broadband Engine */ diff --git a/arch/powerpc/oprofile/op_model_power4.c b/arch/powerpc/oprofile/op_model_power4.c index 4c2beab1fdc..506f6b79f89 100644 --- a/arch/powerpc/oprofile/op_model_power4.c +++ b/arch/powerpc/oprofile/op_model_power4.c @@ -24,10 +24,6 @@ static unsigned long reset_value[OP_MAX_COUNTER]; static int oprofile_running; -static int mmcra_has_sihv; -/* Unfortunately these bits vary between CPUs */ -static unsigned long mmcra_sihv = MMCRA_SIHV; -static unsigned long mmcra_sipr = MMCRA_SIPR; /* mmcr values are set in power4_reg_setup, used in power4_cpu_setup */ static u32 mmcr0_val; @@ -40,16 +36,6 @@ static void power4_reg_setup(struct op_counter_config *ctr, { int i; - /* - * SIHV / SIPR bits are only implemented on POWER4+ (GQ) and above. - * However we disable it on all POWER4 until we verify it works - * (I was seeing some strange behaviour last time I tried). - * - * It has been verified to work on POWER5 so we enable it there. - */ - if (cpu_has_feature(CPU_FTR_MMCRA_SIHV)) - mmcra_has_sihv = 1; - /* * The performance counter event settings are given in the mmcr0, * mmcr1 and mmcra values passed from the user in the @@ -202,18 +188,19 @@ static unsigned long get_pc(struct pt_regs *regs) unsigned long mmcra; /* Cant do much about it */ - if (!mmcra_has_sihv) + if (!cur_cpu_spec->oprofile_mmcra_sihv) return pc; mmcra = mfspr(SPRN_MMCRA); /* Were we in the hypervisor? */ - if (firmware_has_feature(FW_FEATURE_LPAR) && (mmcra & mmcra_sihv)) + if (firmware_has_feature(FW_FEATURE_LPAR) && + (mmcra & cur_cpu_spec->oprofile_mmcra_sihv)) /* function descriptor madness */ return *((unsigned long *)hypervisor_bucket); /* We were in userspace, nothing to do */ - if (mmcra & mmcra_sipr) + if (mmcra & cur_cpu_spec->oprofile_mmcra_sipr) return pc; #ifdef CONFIG_PPC_RTAS @@ -235,15 +222,14 @@ static unsigned long get_pc(struct pt_regs *regs) return pc; } -static int get_kernel(unsigned long pc) +static int get_kernel(unsigned long pc, unsigned long mmcra) { int is_kernel; - if (!mmcra_has_sihv) { + if (!cur_cpu_spec->oprofile_mmcra_sihv) { is_kernel = is_kernel_addr(pc); } else { - unsigned long mmcra = mfspr(SPRN_MMCRA); - is_kernel = ((mmcra & mmcra_sipr) == 0); + is_kernel = ((mmcra & cur_cpu_spec->oprofile_mmcra_sipr) == 0); } return is_kernel; @@ -257,9 +243,12 @@ static void power4_handle_interrupt(struct pt_regs *regs, int val; int i; unsigned int mmcr0; + unsigned long mmcra; + + mmcra = mfspr(SPRN_MMCRA); pc = get_pc(regs); - is_kernel = get_kernel(pc); + is_kernel = get_kernel(pc, mmcra); /* set the PMM bit (see comment below) */ mtmsrd(mfmsr() | MSR_PMM); @@ -287,6 +276,10 @@ static void power4_handle_interrupt(struct pt_regs *regs, */ mmcr0 &= ~MMCR0_PMAO; + /* Clear the appropriate bits in the MMCRA */ + mmcra &= ~cur_cpu_spec->oprofile_mmcra_clear; + mtspr(SPRN_MMCRA, mmcra); + /* * now clear the freeze bit, counting will not start until we * rfid from this exception, because only at that point will diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h index 9fcf0162d85..defc166379d 100644 --- a/include/asm-powerpc/cputable.h +++ b/include/asm-powerpc/cputable.h @@ -69,6 +69,13 @@ struct cpu_spec { /* Processor specific oprofile operations */ enum powerpc_oprofile_type oprofile_type; + /* Bit locations inside the mmcra change */ + unsigned long oprofile_mmcra_sihv; + unsigned long oprofile_mmcra_sipr; + + /* Bits to clear during an oprofile exception */ + unsigned long oprofile_mmcra_clear; + /* Name of processor class, for the ELF AT_PLATFORM entry */ char *platform; }; @@ -117,7 +124,6 @@ extern void do_cpu_ftr_fixups(unsigned long offset); #define CPU_FTR_SMT ASM_CONST(0x0000010000000000) #define CPU_FTR_COHERENT_ICACHE ASM_CONST(0x0000020000000000) #define CPU_FTR_LOCKLESS_TLBIE ASM_CONST(0x0000040000000000) -#define CPU_FTR_MMCRA_SIHV ASM_CONST(0x0000080000000000) #define CPU_FTR_CI_LARGE_PAGE ASM_CONST(0x0000100000000000) #define CPU_FTR_PAUSE_ZERO ASM_CONST(0x0000200000000000) #define CPU_FTR_PURR ASM_CONST(0x0000400000000000) @@ -134,7 +140,6 @@ extern void do_cpu_ftr_fixups(unsigned long offset); #define CPU_FTR_SMT ASM_CONST(0x0) #define CPU_FTR_COHERENT_ICACHE ASM_CONST(0x0) #define CPU_FTR_LOCKLESS_TLBIE ASM_CONST(0x0) -#define CPU_FTR_MMCRA_SIHV ASM_CONST(0x0) #define CPU_FTR_CI_LARGE_PAGE ASM_CONST(0x0) #define CPU_FTR_PURR ASM_CONST(0x0) #endif @@ -320,7 +325,7 @@ extern void do_cpu_ftr_fixups(unsigned long offset); CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \ CPU_FTR_MMCRA | CPU_FTR_SMT | \ CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \ - CPU_FTR_MMCRA_SIHV | CPU_FTR_PURR) + CPU_FTR_PURR) #define CPU_FTRS_POWER6 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \ CPU_FTR_MMCRA | CPU_FTR_SMT | \ diff --git a/include/asm-powerpc/reg.h b/include/asm-powerpc/reg.h index 0257189d501..3779b21a7c7 100644 --- a/include/asm-powerpc/reg.h +++ b/include/asm-powerpc/reg.h @@ -443,6 +443,10 @@ #define MMCRA_SIHV 0x10000000UL /* state of MSR HV when SIAR set */ #define MMCRA_SIPR 0x08000000UL /* state of MSR PR when SIAR set */ #define MMCRA_SAMPLE_ENABLE 0x00000001UL /* enable sampling */ +#define POWER6_MMCRA_SIHV 0x0000040000000000ULL +#define POWER6_MMCRA_SIPR 0x0000020000000000ULL +#define POWER6_MMCRA_THRM 0x00000020UL +#define POWER6_MMCRA_OTHER 0x0000000EUL #define SPRN_PMC1 787 #define SPRN_PMC2 788 #define SPRN_PMC3 789 -- cgit v1.2.3 From 3b5e905ee3bd23e9311951890aba57a0dbc81ca4 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Wed, 7 Jun 2006 12:06:20 +1000 Subject: [PATCH] powerpc: Add udbg-immortal kernel option When debugging early kernel crashes that happen after console_init() and before a proper console driver takes over, we often have to go hack into udbg.c to prevent it from unregistering so we can "see" what is happening. This patch adds a kernel command line option "udbg-immortal" instead to avoid having to modify the kernel. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/udbg.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c index 3774e80094f..67d9fd9ae2b 100644 --- a/arch/powerpc/kernel/udbg.c +++ b/arch/powerpc/kernel/udbg.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -141,12 +142,14 @@ static int early_console_initialized; void __init disable_early_printk(void) { -#if 1 if (!early_console_initialized) return; + if (strstr(saved_command_line, "udbg-immortal")) { + printk(KERN_INFO "early console immortal !\n"); + return; + } unregister_console(&udbg_console); early_console_initialized = 0; -#endif } /* called by setup_system */ -- cgit v1.2.3 From 651d765d0b2c72d33430487c8b6ef64c60cd2134 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Wed, 7 Jun 2006 16:10:19 +1000 Subject: [PATCH] Add a prctl to change the endianness of a process. This new prctl is intended for changing the execution mode of the processor, on processors that support both a little-endian mode and a big-endian mode. It is intended for use by programs such as instruction set emulators (for example an x86 emulator on PowerPC), which may find it convenient to use the processor in an alternate endianness mode when executing translated instructions. Note that this does not imply the existence of a fully-fledged ABI for both endiannesses, or of compatibility code for converting system calls done in the non-native endianness mode. The program is expected to arrange for all of its system call arguments to be presented in the native endianness. Switching between big and little-endian mode will require some care in constructing the instruction sequence for the switch. Generally the instructions up to the instruction that invokes the prctl system call will have to be in the old endianness, and subsequent instructions will have to be in the new endianness. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras --- include/linux/prctl.h | 7 +++++++ kernel/sys.c | 13 +++++++++++++ 2 files changed, 20 insertions(+) diff --git a/include/linux/prctl.h b/include/linux/prctl.h index bf022c43a18..52a9be41250 100644 --- a/include/linux/prctl.h +++ b/include/linux/prctl.h @@ -52,4 +52,11 @@ #define PR_SET_NAME 15 /* Set process name */ #define PR_GET_NAME 16 /* Get process name */ +/* Get/set process endian */ +#define PR_GET_ENDIAN 19 +#define PR_SET_ENDIAN 20 +# define PR_ENDIAN_BIG 0 +# define PR_ENDIAN_LITTLE 1 /* True little endian mode */ +# define PR_ENDIAN_PPC_LITTLE 2 /* "PowerPC" pseudo little endian */ + #endif /* _LINUX_PRCTL_H */ diff --git a/kernel/sys.c b/kernel/sys.c index 0b6ec0e7936..12d2d753dc3 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -57,6 +57,12 @@ #ifndef GET_FPEXC_CTL # define GET_FPEXC_CTL(a,b) (-EINVAL) #endif +#ifndef GET_ENDIAN +# define GET_ENDIAN(a,b) (-EINVAL) +#endif +#ifndef SET_ENDIAN +# define SET_ENDIAN(a,b) (-EINVAL) +#endif /* * this is where the system-wide overflow UID and GID are defined, for @@ -2057,6 +2063,13 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3, return -EFAULT; return 0; } + case PR_GET_ENDIAN: + error = GET_ENDIAN(current, arg2); + break; + case PR_SET_ENDIAN: + error = SET_ENDIAN(current, arg2); + break; + default: error = -EINVAL; break; -- cgit v1.2.3 From fab5db97e44f76461f76b24adfa8ccb14d4df498 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Wed, 7 Jun 2006 16:14:40 +1000 Subject: [PATCH] powerpc: Implement support for setting little-endian mode via prctl This adds the PowerPC part of the code to allow processes to change their endian mode via prctl. This also extends the alignment exception handler to be able to fix up alignment exceptions that occur in little-endian mode, both for "PowerPC" little-endian and true little-endian. We always enter signal handlers in big-endian mode -- the support for little-endian mode does not amount to the creation of a little-endian user/kernel ABI. If the signal handler returns, the endian mode is restored to what it was when the signal was delivered. We have two new kernel CPU feature bits, one for PPC little-endian and one for true little-endian. Most of the classic 32-bit processors support PPC little-endian, and this is reflected in the CPU feature table. There are two corresponding feature bits reported to userland in the AT_HWCAP aux vector entry. This is based on an earlier patch by Anton Blanchard. Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/align.c | 189 +++++++++++++++++++++++++--------------- arch/powerpc/kernel/cputable.c | 84 ++++++++++-------- arch/powerpc/kernel/process.c | 44 ++++++++++ arch/powerpc/kernel/signal_32.c | 15 +++- arch/powerpc/kernel/signal_64.c | 12 ++- arch/powerpc/kernel/traps.c | 2 +- include/asm-powerpc/cputable.h | 52 ++++++----- include/asm-powerpc/processor.h | 6 ++ 8 files changed, 267 insertions(+), 137 deletions(-) diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c index faaec9c6f78..4734b5de599 100644 --- a/arch/powerpc/kernel/align.c +++ b/arch/powerpc/kernel/align.c @@ -35,17 +35,19 @@ struct aligninfo { #define INVALID { 0, 0 } -#define LD 1 /* load */ -#define ST 2 /* store */ -#define SE 4 /* sign-extend value */ -#define F 8 /* to/from fp regs */ -#define U 0x10 /* update index register */ -#define M 0x20 /* multiple load/store */ -#define SW 0x40 /* byte swap int or ... */ -#define S 0x40 /* ... single-precision fp */ -#define SX 0x40 /* byte count in XER */ +/* Bits in the flags field */ +#define LD 0 /* load */ +#define ST 1 /* store */ +#define SE 2 /* sign-extend value */ +#define F 4 /* to/from fp regs */ +#define U 8 /* update index register */ +#define M 0x10 /* multiple load/store */ +#define SW 0x20 /* byte swap */ +#define S 0x40 /* single-precision fp or... */ +#define SX 0x40 /* ... byte count in XER */ #define HARD 0x80 /* string, stwcx. */ +/* DSISR bits reported for a DCBZ instruction: */ #define DCBZ 0x5f /* 8xx/82xx dcbz faults when cache not enabled */ #define SWAP(a, b) (t = (a), (a) = (b), (b) = t) @@ -256,12 +258,16 @@ static int emulate_dcbz(struct pt_regs *regs, unsigned char __user *addr) #define REG_BYTE(rp, i) *((u8 *)(rp) + (i)) #endif +#define SWIZ_PTR(p) ((unsigned char __user *)((p) ^ swiz)) + static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr, unsigned int reg, unsigned int nb, - unsigned int flags, unsigned int instr) + unsigned int flags, unsigned int instr, + unsigned long swiz) { unsigned long *rptr; - unsigned int nb0, i; + unsigned int nb0, i, bswiz; + unsigned long p; /* * We do not try to emulate 8 bytes multiple as they aren't really @@ -280,9 +286,12 @@ static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr, if (nb == 0) return 1; } else { - if (__get_user(instr, - (unsigned int __user *)regs->nip)) + unsigned long pc = regs->nip ^ (swiz & 4); + + if (__get_user(instr, (unsigned int __user *)pc)) return -EFAULT; + if (swiz == 0 && (flags & SW)) + instr = cpu_to_le32(instr); nb = (instr >> 11) & 0x1f; if (nb == 0) nb = 32; @@ -300,7 +309,10 @@ static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr, return -EFAULT; /* bad address */ rptr = ®s->gpr[reg]; - if (flags & LD) { + p = (unsigned long) addr; + bswiz = (flags & SW)? 3: 0; + + if (!(flags & ST)) { /* * This zeroes the top 4 bytes of the affected registers * in 64-bit mode, and also zeroes out any remaining @@ -311,26 +323,28 @@ static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr, memset(®s->gpr[0], 0, ((nb0 + 3) / 4) * sizeof(unsigned long)); - for (i = 0; i < nb; ++i) - if (__get_user(REG_BYTE(rptr, i), addr + i)) + for (i = 0; i < nb; ++i, ++p) + if (__get_user(REG_BYTE(rptr, i ^ bswiz), SWIZ_PTR(p))) return -EFAULT; if (nb0 > 0) { rptr = ®s->gpr[0]; addr += nb; - for (i = 0; i < nb0; ++i) - if (__get_user(REG_BYTE(rptr, i), addr + i)) + for (i = 0; i < nb0; ++i, ++p) + if (__get_user(REG_BYTE(rptr, i ^ bswiz), + SWIZ_PTR(p))) return -EFAULT; } } else { - for (i = 0; i < nb; ++i) - if (__put_user(REG_BYTE(rptr, i), addr + i)) + for (i = 0; i < nb; ++i, ++p) + if (__put_user(REG_BYTE(rptr, i ^ bswiz), SWIZ_PTR(p))) return -EFAULT; if (nb0 > 0) { rptr = ®s->gpr[0]; addr += nb; - for (i = 0; i < nb0; ++i) - if (__put_user(REG_BYTE(rptr, i), addr + i)) + for (i = 0; i < nb0; ++i, ++p) + if (__put_user(REG_BYTE(rptr, i ^ bswiz), + SWIZ_PTR(p))) return -EFAULT; } } @@ -352,7 +366,7 @@ int fix_alignment(struct pt_regs *regs) unsigned int reg, areg; unsigned int dsisr; unsigned char __user *addr; - unsigned char __user *p; + unsigned long p, swiz; int ret, t; union { u64 ll; @@ -380,11 +394,15 @@ int fix_alignment(struct pt_regs *regs) * let's make one up from the instruction */ if (cpu_has_feature(CPU_FTR_NODSISRALIGN)) { - unsigned int real_instr; - if (unlikely(__get_user(real_instr, - (unsigned int __user *)regs->nip))) + unsigned long pc = regs->nip; + + if (cpu_has_feature(CPU_FTR_PPC_LE) && (regs->msr & MSR_LE)) + pc ^= 4; + if (unlikely(__get_user(instr, (unsigned int __user *)pc))) return -EFAULT; - dsisr = make_dsisr(real_instr); + if (cpu_has_feature(CPU_FTR_REAL_LE) && (regs->msr & MSR_LE)) + instr = cpu_to_le32(instr); + dsisr = make_dsisr(instr); } /* extract the operation and registers from the dsisr */ @@ -397,6 +415,24 @@ int fix_alignment(struct pt_regs *regs) nb = aligninfo[instr].len; flags = aligninfo[instr].flags; + /* Byteswap little endian loads and stores */ + swiz = 0; + if (regs->msr & MSR_LE) { + flags ^= SW; + /* + * So-called "PowerPC little endian" mode works by + * swizzling addresses rather than by actually doing + * any byte-swapping. To emulate this, we XOR each + * byte address with 7. We also byte-swap, because + * the processor's address swizzling depends on the + * operand size (it xors the address with 7 for bytes, + * 6 for halfwords, 4 for words, 0 for doublewords) but + * we will xor with 7 and load/store each byte separately. + */ + if (cpu_has_feature(CPU_FTR_PPC_LE)) + swiz = 7; + } + /* DAR has the operand effective address */ addr = (unsigned char __user *)regs->dar; @@ -412,7 +448,8 @@ int fix_alignment(struct pt_regs *regs) * function */ if (flags & M) - return emulate_multiple(regs, addr, reg, nb, flags, instr); + return emulate_multiple(regs, addr, reg, nb, + flags, instr, swiz); /* Verify the address of the operand */ if (unlikely(user_mode(regs) && @@ -431,51 +468,71 @@ int fix_alignment(struct pt_regs *regs) /* If we are loading, get the data from user space, else * get it from register values */ - if (flags & LD) { + if (!(flags & ST)) { data.ll = 0; ret = 0; - p = addr; + p = (unsigned long) addr; switch (nb) { case 8: - ret |= __get_user(data.v[0], p++); - ret |= __get_user(data.v[1], p++); - ret |= __get_user(data.v[2], p++); - ret |= __get_user(data.v[3], p++); + ret |= __get_user(data.v[0], SWIZ_PTR(p++)); + ret |= __get_user(data.v[1], SWIZ_PTR(p++)); + ret |= __get_user(data.v[2], SWIZ_PTR(p++)); + ret |= __get_user(data.v[3], SWIZ_PTR(p++)); case 4: - ret |= __get_user(data.v[4], p++); - ret |= __get_user(data.v[5], p++); + ret |= __get_user(data.v[4], SWIZ_PTR(p++)); + ret |= __get_user(data.v[5], SWIZ_PTR(p++)); case 2: - ret |= __get_user(data.v[6], p++); - ret |= __get_user(data.v[7], p++); + ret |= __get_user(data.v[6], SWIZ_PTR(p++)); + ret |= __get_user(data.v[7], SWIZ_PTR(p++)); if (unlikely(ret)) return -EFAULT; } - } else if (flags & F) + } else if (flags & F) { data.dd = current->thread.fpr[reg]; - else + if (flags & S) { + /* Single-precision FP store requires conversion... */ +#ifdef CONFIG_PPC_FPU + preempt_disable(); + enable_kernel_fp(); + cvt_df(&data.dd, (float *)&data.v[4], ¤t->thread); + preempt_enable(); +#else + return 0; +#endif + } + } else data.ll = regs->gpr[reg]; - /* Perform other misc operations like sign extension, byteswap, + if (flags & SW) { + switch (nb) { + case 8: + SWAP(data.v[0], data.v[7]); + SWAP(data.v[1], data.v[6]); + SWAP(data.v[2], data.v[5]); + SWAP(data.v[3], data.v[4]); + break; + case 4: + SWAP(data.v[4], data.v[7]); + SWAP(data.v[5], data.v[6]); + break; + case 2: + SWAP(data.v[6], data.v[7]); + break; + } + } + + /* Perform other misc operations like sign extension * or floating point single precision conversion */ - switch (flags & ~U) { + switch (flags & ~(U|SW)) { case LD+SE: /* sign extend */ if ( nb == 2 ) data.ll = data.x16.low16; else /* nb must be 4 */ data.ll = data.x32.low32; break; - case LD+S: /* byte-swap */ - case ST+S: - if (nb == 2) { - SWAP(data.v[6], data.v[7]); - } else { - SWAP(data.v[4], data.v[7]); - SWAP(data.v[5], data.v[6]); - } - break; - /* Single-precision FP load and store require conversions... */ + /* Single-precision FP load requires conversion... */ case LD+F+S: #ifdef CONFIG_PPC_FPU preempt_disable(); @@ -484,16 +541,6 @@ int fix_alignment(struct pt_regs *regs) preempt_enable(); #else return 0; -#endif - break; - case ST+F+S: -#ifdef CONFIG_PPC_FPU - preempt_disable(); - enable_kernel_fp(); - cvt_df(&data.dd, (float *)&data.v[4], ¤t->thread); - preempt_enable(); -#else - return 0; #endif break; } @@ -501,19 +548,19 @@ int fix_alignment(struct pt_regs *regs) /* Store result to memory or update registers */ if (flags & ST) { ret = 0; - p = addr; + p = (unsigned long) addr; switch (nb) { case 8: - ret |= __put_user(data.v[0], p++); - ret |= __put_user(data.v[1], p++); - ret |= __put_user(data.v[2], p++); - ret |= __put_user(data.v[3], p++); + ret |= __put_user(data.v[0], SWIZ_PTR(p++)); + ret |= __put_user(data.v[1], SWIZ_PTR(p++)); + ret |= __put_user(data.v[2], SWIZ_PTR(p++)); + ret |= __put_user(data.v[3], SWIZ_PTR(p++)); case 4: - ret |= __put_user(data.v[4], p++); - ret |= __put_user(data.v[5], p++); + ret |= __put_user(data.v[4], SWIZ_PTR(p++)); + ret |= __put_user(data.v[5], SWIZ_PTR(p++)); case 2: - ret |= __put_user(data.v[6], p++); - ret |= __put_user(data.v[7], p++); + ret |= __put_user(data.v[6], SWIZ_PTR(p++)); + ret |= __put_user(data.v[7], SWIZ_PTR(p++)); } if (unlikely(ret)) return -EFAULT; diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 83f9ab139d4..dfe2fcfb20a 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -54,7 +54,8 @@ extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec); #define COMMON_USER_POWER5_PLUS (COMMON_USER_PPC64 | PPC_FEATURE_POWER5_PLUS|\ PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP) #define COMMON_USER_POWER6 (COMMON_USER_PPC64 | PPC_FEATURE_ARCH_2_05 |\ - PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP) + PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP | \ + PPC_FEATURE_TRUE_LE) #define COMMON_USER_BOOKE (PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | \ PPC_FEATURE_BOOKE) @@ -74,7 +75,7 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x00400000, .cpu_name = "POWER3 (630)", .cpu_features = CPU_FTRS_POWER3, - .cpu_user_features = COMMON_USER_PPC64, + .cpu_user_features = COMMON_USER_PPC64|PPC_FEATURE_PPC_LE, .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 8, @@ -87,7 +88,7 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x00410000, .cpu_name = "POWER3 (630+)", .cpu_features = CPU_FTRS_POWER3, - .cpu_user_features = COMMON_USER_PPC64, + .cpu_user_features = COMMON_USER_PPC64|PPC_FEATURE_PPC_LE, .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 8, @@ -318,7 +319,7 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x00030000, .cpu_name = "603", .cpu_features = CPU_FTRS_603, - .cpu_user_features = COMMON_USER, + .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .cpu_setup = __setup_cpu_603, @@ -329,7 +330,7 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x00060000, .cpu_name = "603e", .cpu_features = CPU_FTRS_603, - .cpu_user_features = COMMON_USER, + .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .cpu_setup = __setup_cpu_603, @@ -340,7 +341,7 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x00070000, .cpu_name = "603ev", .cpu_features = CPU_FTRS_603, - .cpu_user_features = COMMON_USER, + .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .cpu_setup = __setup_cpu_603, @@ -351,7 +352,7 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x00040000, .cpu_name = "604", .cpu_features = CPU_FTRS_604, - .cpu_user_features = COMMON_USER, + .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 2, @@ -363,7 +364,7 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x00090000, .cpu_name = "604e", .cpu_features = CPU_FTRS_604, - .cpu_user_features = COMMON_USER, + .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, @@ -375,7 +376,7 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x00090000, .cpu_name = "604r", .cpu_features = CPU_FTRS_604, - .cpu_user_features = COMMON_USER, + .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, @@ -387,7 +388,7 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x000a0000, .cpu_name = "604ev", .cpu_features = CPU_FTRS_604, - .cpu_user_features = COMMON_USER, + .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, @@ -399,7 +400,7 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x00084202, .cpu_name = "740/750", .cpu_features = CPU_FTRS_740_NOTAU, - .cpu_user_features = COMMON_USER, + .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, @@ -411,7 +412,7 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x00080100, .cpu_name = "750CX", .cpu_features = CPU_FTRS_750, - .cpu_user_features = COMMON_USER, + .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, @@ -423,7 +424,7 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x00082200, .cpu_name = "750CX", .cpu_features = CPU_FTRS_750, - .cpu_user_features = COMMON_USER, + .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, @@ -435,7 +436,7 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x00082210, .cpu_name = "750CXe", .cpu_features = CPU_FTRS_750, - .cpu_user_features = COMMON_USER, + .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, @@ -447,7 +448,7 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x00083214, .cpu_name = "750CXe", .cpu_features = CPU_FTRS_750, - .cpu_user_features = COMMON_USER, + .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, @@ -459,7 +460,7 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x00083000, .cpu_name = "745/755", .cpu_features = CPU_FTRS_750, - .cpu_user_features = COMMON_USER, + .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, @@ -471,7 +472,7 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x70000100, .cpu_name = "750FX", .cpu_features = CPU_FTRS_750FX1, - .cpu_user_features = COMMON_USER, + .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, @@ -483,7 +484,7 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x70000200, .cpu_name = "750FX", .cpu_features = CPU_FTRS_750FX2, - .cpu_user_features = COMMON_USER, + .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, @@ -495,7 +496,7 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x70000000, .cpu_name = "750FX", .cpu_features = CPU_FTRS_750FX, - .cpu_user_features = COMMON_USER, + .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, @@ -507,7 +508,7 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x70020000, .cpu_name = "750GX", .cpu_features = CPU_FTRS_750GX, - .cpu_user_features = COMMON_USER, + .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, @@ -519,7 +520,7 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x00080000, .cpu_name = "740/750", .cpu_features = CPU_FTRS_740, - .cpu_user_features = COMMON_USER, + .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, @@ -531,7 +532,8 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x000c1101, .cpu_name = "7400 (1.1)", .cpu_features = CPU_FTRS_7400_NOTAU, - .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, + .cpu_user_features = COMMON_USER | + PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, @@ -543,7 +545,8 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x000c0000, .cpu_name = "7400", .cpu_features = CPU_FTRS_7400, - .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, + .cpu_user_features = COMMON_USER | + PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, @@ -555,7 +558,8 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x800c0000, .cpu_name = "7410", .cpu_features = CPU_FTRS_7400, - .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, + .cpu_user_features = COMMON_USER | + PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, @@ -567,7 +571,8 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x80000200, .cpu_name = "7450", .cpu_features = CPU_FTRS_7450_20, - .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, + .cpu_user_features = COMMON_USER | + PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, @@ -581,7 +586,8 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x80000201, .cpu_name = "7450", .cpu_features = CPU_FTRS_7450_21, - .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, + .cpu_user_features = COMMON_USER | + PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, @@ -595,7 +601,8 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x80000000, .cpu_name = "7450", .cpu_features = CPU_FTRS_7450_23, - .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, + .cpu_user_features = COMMON_USER | + PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, @@ -609,7 +616,8 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x80010100, .cpu_name = "7455", .cpu_features = CPU_FTRS_7455_1, - .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, + .cpu_user_features = COMMON_USER | + PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, @@ -623,7 +631,8 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x80010200, .cpu_name = "7455", .cpu_features = CPU_FTRS_7455_20, - .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, + .cpu_user_features = COMMON_USER | + PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, @@ -637,7 +646,8 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x80010000, .cpu_name = "7455", .cpu_features = CPU_FTRS_7455, - .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, + .cpu_user_features = COMMON_USER | + PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, @@ -651,7 +661,8 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x80020100, .cpu_name = "7447/7457", .cpu_features = CPU_FTRS_7447_10, - .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, + .cpu_user_features = COMMON_USER | + PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, @@ -665,7 +676,8 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x80020101, .cpu_name = "7447/7457", .cpu_features = CPU_FTRS_7447_10, - .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, + .cpu_user_features = COMMON_USER | + PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, @@ -679,7 +691,7 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x80020000, .cpu_name = "7447/7457", .cpu_features = CPU_FTRS_7447, - .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, + .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, @@ -693,7 +705,8 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x80030000, .cpu_name = "7447A", .cpu_features = CPU_FTRS_7447A, - .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, + .cpu_user_features = COMMON_USER | + PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, @@ -707,7 +720,8 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x80040000, .cpu_name = "7448", .cpu_features = CPU_FTRS_7447A, - .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, + .cpu_user_features = COMMON_USER | + PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 2dd47d2dd99..2d35d83961b 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -708,6 +708,50 @@ int get_fpexc_mode(struct task_struct *tsk, unsigned long adr) return put_user(val, (unsigned int __user *) adr); } +int set_endian(struct task_struct *tsk, unsigned int val) +{ + struct pt_regs *regs = tsk->thread.regs; + + if ((val == PR_ENDIAN_LITTLE && !cpu_has_feature(CPU_FTR_REAL_LE)) || + (val == PR_ENDIAN_PPC_LITTLE && !cpu_has_feature(CPU_FTR_PPC_LE))) + return -EINVAL; + + if (regs == NULL) + return -EINVAL; + + if (val == PR_ENDIAN_BIG) + regs->msr &= ~MSR_LE; + else if (val == PR_ENDIAN_LITTLE || val == PR_ENDIAN_PPC_LITTLE) + regs->msr |= MSR_LE; + else + return -EINVAL; + + return 0; +} + +int get_endian(struct task_struct *tsk, unsigned long adr) +{ + struct pt_regs *regs = tsk->thread.regs; + unsigned int val; + + if (!cpu_has_feature(CPU_FTR_PPC_LE) && + !cpu_has_feature(CPU_FTR_REAL_LE)) + return -EINVAL; + + if (regs == NULL) + return -EINVAL; + + if (regs->msr & MSR_LE) { + if (cpu_has_feature(CPU_FTR_REAL_LE)) + val = PR_ENDIAN_LITTLE; + else + val = PR_ENDIAN_PPC_LITTLE; + } else + val = PR_ENDIAN_BIG; + + return put_user(val, (unsigned int __user *)adr); +} + #define TRUNC_PTR(x) ((typeof(x))(((unsigned long)(x)) & 0xffffffff)) int sys_clone(unsigned long clone_flags, unsigned long usp, diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index 22f07898484..237faeec2ec 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c @@ -419,9 +419,7 @@ static long restore_user_regs(struct pt_regs *regs, { long err; unsigned int save_r2 = 0; -#if defined(CONFIG_ALTIVEC) || defined(CONFIG_SPE) unsigned long msr; -#endif /* * restore general registers but not including MSR or SOFTE. Also @@ -430,11 +428,16 @@ static long restore_user_regs(struct pt_regs *regs, if (!sig) save_r2 = (unsigned int)regs->gpr[2]; err = restore_general_regs(regs, sr); + err |= __get_user(msr, &sr->mc_gregs[PT_MSR]); if (!sig) regs->gpr[2] = (unsigned long) save_r2; if (err) return 1; + /* if doing signal return, restore the previous little-endian mode */ + if (sig) + regs->msr = (regs->msr & ~MSR_LE) | (msr & MSR_LE); + /* * Do this before updating the thread state in * current->thread.fpr/vr/evr. That way, if we get preempted @@ -455,7 +458,7 @@ static long restore_user_regs(struct pt_regs *regs, /* force the process to reload the altivec registers from current->thread when it next does altivec instructions */ regs->msr &= ~MSR_VEC; - if (!__get_user(msr, &sr->mc_gregs[PT_MSR]) && (msr & MSR_VEC) != 0) { + if (msr & MSR_VEC) { /* restore altivec registers from the stack */ if (__copy_from_user(current->thread.vr, &sr->mc_vregs, sizeof(sr->mc_vregs))) @@ -472,7 +475,7 @@ static long restore_user_regs(struct pt_regs *regs, /* force the process to reload the spe registers from current->thread when it next does spe instructions */ regs->msr &= ~MSR_SPE; - if (!__get_user(msr, &sr->mc_gregs[PT_MSR]) && (msr & MSR_SPE) != 0) { + if (msr & MSR_SPE) { /* restore spe registers from the stack */ if (__copy_from_user(current->thread.evr, &sr->mc_vregs, ELF_NEVRREG * sizeof(u32))) @@ -777,6 +780,8 @@ static int handle_rt_signal(unsigned long sig, struct k_sigaction *ka, regs->gpr[5] = (unsigned long) &rt_sf->uc; regs->gpr[6] = (unsigned long) rt_sf; regs->nip = (unsigned long) ka->sa.sa_handler; + /* enter the signal handler in big-endian mode */ + regs->msr &= ~MSR_LE; regs->trap = 0; return 1; @@ -1047,6 +1052,8 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka, regs->gpr[3] = sig; regs->gpr[4] = (unsigned long) sc; regs->nip = (unsigned long) ka->sa.sa_handler; + /* enter the signal handler in big-endian mode */ + regs->msr &= ~MSR_LE; regs->trap = 0; return 1; diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index 23ba69c2691..66a5fbe3198 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c @@ -141,9 +141,7 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig, unsigned long err = 0; unsigned long save_r13 = 0; elf_greg_t *gregs = (elf_greg_t *)regs; -#ifdef CONFIG_ALTIVEC unsigned long msr; -#endif int i; /* If this is not a signal return, we preserve the TLS in r13 */ @@ -154,7 +152,12 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig, err |= __copy_from_user(regs, &sc->gp_regs, PT_MSR*sizeof(unsigned long)); - /* skip MSR and SOFTE */ + /* get MSR separately, transfer the LE bit if doing signal return */ + err |= __get_user(msr, &sc->gp_regs[PT_MSR]); + if (sig) + regs->msr = (regs->msr & ~MSR_LE) | (msr & MSR_LE); + + /* skip SOFTE */ for (i = PT_MSR+1; i <= PT_RESULT; i++) { if (i == PT_SOFTE) continue; @@ -179,7 +182,6 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig, #ifdef CONFIG_ALTIVEC err |= __get_user(v_regs, &sc->v_regs); - err |= __get_user(msr, &sc->gp_regs[PT_MSR]); if (err) return err; /* Copy 33 vec registers (vr0..31 and vscr) from the stack */ @@ -410,6 +412,8 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, /* Set up "regs" so we "return" to the signal handler. */ err |= get_user(regs->nip, &funct_desc_ptr->entry); + /* enter the signal handler in big-endian mode */ + regs->msr &= ~MSR_LE; regs->gpr[1] = newsp; err |= get_user(regs->gpr[2], &funct_desc_ptr->toc); regs->gpr[3] = signr; diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 064a5256469..03def571549 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -658,7 +658,7 @@ static int emulate_instruction(struct pt_regs *regs) u32 instword; u32 rd; - if (!user_mode(regs)) + if (!user_mode(regs) || (regs->msr & MSR_LE)) return -EINVAL; CHECK_FULL_REGS(regs); diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h index defc166379d..69f2c242797 100644 --- a/include/asm-powerpc/cputable.h +++ b/include/asm-powerpc/cputable.h @@ -24,6 +24,9 @@ #define PPC_FEATURE_ICACHE_SNOOP 0x00002000 #define PPC_FEATURE_ARCH_2_05 0x00001000 +#define PPC_FEATURE_TRUE_LE 0x00000002 +#define PPC_FEATURE_PPC_LE 0x00000001 + #ifdef __KERNEL__ #ifndef __ASSEMBLY__ @@ -111,6 +114,8 @@ extern void do_cpu_ftr_fixups(unsigned long offset); #define CPU_FTR_NO_BTIC ASM_CONST(0x0000000000040000) #define CPU_FTR_BIG_PHYS ASM_CONST(0x0000000000080000) #define CPU_FTR_NODSISRALIGN ASM_CONST(0x0000000000100000) +#define CPU_FTR_PPC_LE ASM_CONST(0x0000000000200000) +#define CPU_FTR_REAL_LE ASM_CONST(0x0000000000400000) #ifdef __powerpc64__ /* Add the 64b processor unique features in the top half of the word */ @@ -197,92 +202,95 @@ extern void do_cpu_ftr_fixups(unsigned long offset); #define CPU_FTRS_PPC601 (CPU_FTR_COMMON | CPU_FTR_601 | CPU_FTR_HPTE_TABLE) #define CPU_FTRS_603 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | \ - CPU_FTR_MAYBE_CAN_NAP) + CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE) #define CPU_FTRS_604 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ - CPU_FTR_USE_TB | CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE) + CPU_FTR_USE_TB | CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE | \ + CPU_FTR_PPC_LE) #define CPU_FTRS_740_NOTAU (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ - CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP) + CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE) #define CPU_FTRS_740 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ - CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP) + CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \ + CPU_FTR_PPC_LE) #define CPU_FTRS_750 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ - CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP) + CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \ + CPU_FTR_PPC_LE) #define CPU_FTRS_750FX1 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \ - CPU_FTR_DUAL_PLL_750FX | CPU_FTR_NO_DPM) + CPU_FTR_DUAL_PLL_750FX | CPU_FTR_NO_DPM | CPU_FTR_PPC_LE) #define CPU_FTRS_750FX2 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \ - CPU_FTR_NO_DPM) + CPU_FTR_NO_DPM | CPU_FTR_PPC_LE) #define CPU_FTRS_750FX (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \ - CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS) + CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE) #define CPU_FTRS_750GX (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \ CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | \ CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \ - CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS) + CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE) #define CPU_FTRS_7400_NOTAU (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | \ - CPU_FTR_MAYBE_CAN_NAP) + CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE) #define CPU_FTRS_7400 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | \ - CPU_FTR_MAYBE_CAN_NAP) + CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE) #define CPU_FTRS_7450_20 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ - CPU_FTR_NEED_COHERENT) + CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE) #define CPU_FTRS_7450_21 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_USE_TB | \ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | \ - CPU_FTR_NEED_COHERENT) + CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE) #define CPU_FTRS_7450_23 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_USE_TB | \ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ - CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_NEED_COHERENT) + CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE) #define CPU_FTRS_7455_1 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_USE_TB | \ CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | \ CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_HAS_HIGH_BATS | \ - CPU_FTR_NEED_COHERENT) + CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE) #define CPU_FTRS_7455_20 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_USE_TB | \ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | \ - CPU_FTR_NEED_COHERENT | CPU_FTR_HAS_HIGH_BATS) + CPU_FTR_NEED_COHERENT | CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE) #define CPU_FTRS_7455 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_USE_TB | \ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \ - CPU_FTR_NEED_COHERENT) + CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE) #define CPU_FTRS_7447_10 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_USE_TB | \ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \ - CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC) + CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC | CPU_FTR_PPC_LE) #define CPU_FTRS_7447 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_USE_TB | \ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \ - CPU_FTR_NEED_COHERENT) + CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE) #define CPU_FTRS_7447A (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_USE_TB | \ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \ - CPU_FTR_NEED_COHERENT) + CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE) #define CPU_FTRS_82XX (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB) #define CPU_FTRS_G2_LE (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \ @@ -312,7 +320,7 @@ extern void do_cpu_ftr_fixups(unsigned long offset); #define CPU_FTRS_GENERIC_32 (CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN) #ifdef __powerpc64__ #define CPU_FTRS_POWER3 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ - CPU_FTR_HPTE_TABLE | CPU_FTR_IABR) + CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | CPU_FTR_PPC_LE) #define CPU_FTRS_RS64 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | \ CPU_FTR_MMCRA | CPU_FTR_CTRL) @@ -330,7 +338,7 @@ extern void do_cpu_ftr_fixups(unsigned long offset); CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \ CPU_FTR_MMCRA | CPU_FTR_SMT | \ CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \ - CPU_FTR_PURR | CPU_FTR_CI_LARGE_PAGE) + CPU_FTR_PURR | CPU_FTR_CI_LARGE_PAGE | CPU_FTR_REAL_LE) #define CPU_FTRS_CELL (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \ CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \ diff --git a/include/asm-powerpc/processor.h b/include/asm-powerpc/processor.h index d5c7ef1cca2..fa616326815 100644 --- a/include/asm-powerpc/processor.h +++ b/include/asm-powerpc/processor.h @@ -211,6 +211,12 @@ unsigned long get_wchan(struct task_struct *p); extern int get_fpexc_mode(struct task_struct *tsk, unsigned long adr); extern int set_fpexc_mode(struct task_struct *tsk, unsigned int val); +#define GET_ENDIAN(tsk, adr) get_endian((tsk), (adr)) +#define SET_ENDIAN(tsk, val) set_endian((tsk), (val)) + +extern int get_endian(struct task_struct *tsk, unsigned long adr); +extern int set_endian(struct task_struct *tsk, unsigned int val); + static inline unsigned int __unpack_fe01(unsigned long msr_bits) { return ((msr_bits & MSR_FE0) >> 10) | ((msr_bits & MSR_FE1) >> 8); -- cgit v1.2.3 From e9370ae15dc2f8ba1e1889ce26f13cda565b6ecb Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Wed, 7 Jun 2006 16:15:39 +1000 Subject: [PATCH] powerpc: Implement PR_[GS]ET_UNALIGN prctls for powerpc This gives the ability to control whether alignment exceptions get fixed up or reported to the process as a SIGBUS, using the existing PR_SET_UNALIGN and PR_GET_UNALIGN prctls. We do not implement the option of logging a message on alignment exceptions. Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/process.c | 11 +++++++++++ arch/powerpc/kernel/traps.c | 6 ++++-- include/asm-powerpc/processor.h | 7 +++++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 2d35d83961b..e4732459c48 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -752,6 +752,17 @@ int get_endian(struct task_struct *tsk, unsigned long adr) return put_user(val, (unsigned int __user *)adr); } +int set_unalign_ctl(struct task_struct *tsk, unsigned int val) +{ + tsk->thread.align_ctl = val; + return 0; +} + +int get_unalign_ctl(struct task_struct *tsk, unsigned long adr) +{ + return put_user(tsk->thread.align_ctl, (unsigned int __user *)adr); +} + #define TRUNC_PTR(x) ((typeof(x))(((unsigned long)(x)) & 0xffffffff)) int sys_clone(unsigned long clone_flags, unsigned long usp, diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 03def571549..91a6e04d974 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -805,9 +805,11 @@ void __kprobes program_check_exception(struct pt_regs *regs) void alignment_exception(struct pt_regs *regs) { - int fixed; + int fixed = 0; - fixed = fix_alignment(regs); + /* we don't implement logging of alignment exceptions */ + if (!(current->thread.align_ctl & PR_UNALIGN_SIGBUS)) + fixed = fix_alignment(regs); if (fixed == 1) { regs->nip += 4; /* skip over emulated instruction */ diff --git a/include/asm-powerpc/processor.h b/include/asm-powerpc/processor.h index fa616326815..d2c2c95f913 100644 --- a/include/asm-powerpc/processor.h +++ b/include/asm-powerpc/processor.h @@ -149,6 +149,7 @@ struct thread_struct { unsigned int val; /* Floating point status */ } fpscr; int fpexc_mode; /* floating-point exception mode */ + unsigned int align_ctl; /* alignment handling control */ #ifdef CONFIG_PPC64 unsigned long start_tb; /* Start purr when proc switched in */ unsigned long accum_tb; /* Total accumilated purr for process */ @@ -217,6 +218,12 @@ extern int set_fpexc_mode(struct task_struct *tsk, unsigned int val); extern int get_endian(struct task_struct *tsk, unsigned long adr); extern int set_endian(struct task_struct *tsk, unsigned int val); +#define GET_UNALIGN_CTL(tsk, adr) get_unalign_ctl((tsk), (adr)) +#define SET_UNALIGN_CTL(tsk, val) set_unalign_ctl((tsk), (val)) + +extern int get_unalign_ctl(struct task_struct *tsk, unsigned long adr); +extern int set_unalign_ctl(struct task_struct *tsk, unsigned int val); + static inline unsigned int __unpack_fe01(unsigned long msr_bits) { return ((msr_bits & MSR_FE0) >> 10) | ((msr_bits & MSR_FE1) >> 8); -- cgit v1.2.3 From b53744612f276ad20c5d7ef33ac991ec13101417 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Wed, 7 Jun 2006 17:10:03 +1000 Subject: [PATCH] powerpc: Make rtas console _much_ faster Currently the hvc_rtas driver is painfully slow to use. Our "benchmark" is ls -R /etc, which spits out about 27866 characters. The theoretical maximum speed would be about 2.2 seconds, the current code takes ~50 seconds. The core of the problem is that sometimes when the tty layer asks us to push characters the firmware isn't able to handle some or all of them, and so returns an error. The current code sees this and just returns to the tty code with the buffer half sent. The khvcd thread will eventually wake up and try to push more characters, which will usually work because by then the firmware's had time to make room. But the khvcd thread only wakes up every 10 milliseconds, which isn't fast enough. So change the khvcd thread logic so that if there's an incomplete write we yield() and then immediately try writing again. Doing so makes POLL_QUICK and POLL_WRITE synonymous, so remove POLL_QUICK. With this patch our "benchmark" takes ~2.8 seconds. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- drivers/char/hvc_console.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index 2b6a56b2bf3..a5c6a9d7ff0 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c @@ -553,7 +553,6 @@ static int hvc_chars_in_buffer(struct tty_struct *tty) #define HVC_POLL_READ 0x00000001 #define HVC_POLL_WRITE 0x00000002 -#define HVC_POLL_QUICK 0x00000004 static int hvc_poll(struct hvc_struct *hp) { @@ -568,6 +567,7 @@ static int hvc_poll(struct hvc_struct *hp) /* Push pending writes */ if (hp->n_outbuf > 0) hvc_push(hp); + /* Reschedule us if still some write pending */ if (hp->n_outbuf > 0) poll_mask |= HVC_POLL_WRITE; @@ -680,7 +680,7 @@ int khvcd(void *unused) poll_mask |= HVC_POLL_READ; if (hvc_kicked) continue; - if (poll_mask & HVC_POLL_QUICK) { + if (poll_mask & HVC_POLL_WRITE) { yield(); continue; } -- cgit v1.2.3 From 6b81e80049a8815dc457fec4dadb6ae535c3b988 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Wed, 7 Jun 2006 17:10:09 +1000 Subject: [PATCH] powerpc: Cleanup hvc_rtas.c a little A few cleanups in hvc_rtas.c: 1. Remove unused RTASCONS_PUT_ATTEMPTS 2. Remove unused rtascons_put_delay. 3. Use i as a loop counter like everyone else on earth. 4. Remove pointless variables, eg. x = foo; if (x) return something_else; 5. Whitespace cleanups and formatting. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- drivers/char/hvc_rtas.c | 37 ++++++++++++++++--------------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/drivers/char/hvc_rtas.c b/drivers/char/hvc_rtas.c index 83364ea63cb..57106e02fd2 100644 --- a/drivers/char/hvc_rtas.c +++ b/drivers/char/hvc_rtas.c @@ -41,37 +41,28 @@ #define hvc_rtas_cookie 0x67781e15 struct hvc_struct *hvc_rtas_dev; -#define RTASCONS_PUT_ATTEMPTS 16 - static int rtascons_put_char_token = RTAS_UNKNOWN_SERVICE; static int rtascons_get_char_token = RTAS_UNKNOWN_SERVICE; -static int rtascons_put_delay = 100; -module_param_named(put_delay, rtascons_put_delay, int, 0644); -static inline int hvc_rtas_write_console(uint32_t vtermno, const char *buf, int count) +static inline int hvc_rtas_write_console(uint32_t vtermno, const char *buf, + int count) { - int done; + int i; - /* if there is more than one character to be displayed, wait a bit */ - for (done = 0; done < count; done++) { - int result; - result = rtas_call(rtascons_put_char_token, 1, 1, NULL, buf[done]); - if (result) + for (i = 0; i < count; i++) { + if (rtas_call(rtascons_put_char_token, 1, 1, NULL, buf[i])) break; } - /* the calling routine expects to receive the number of bytes sent */ - return done; + + return i; } static int hvc_rtas_read_console(uint32_t vtermno, char *buf, int count) { - int i; + int i, c; for (i = 0; i < count; i++) { - int c, err; - - err = rtas_call(rtascons_get_char_token, 0, 2, &c); - if (err) + if (rtas_call(rtascons_get_char_token, 0, 2, &c)) break; buf[i] = c; @@ -106,7 +97,9 @@ static int hvc_rtas_init(void) hp = hvc_alloc(hvc_rtas_cookie, NO_IRQ, &hvc_rtas_get_put_ops); if (IS_ERR(hp)) return PTR_ERR(hp); + hvc_rtas_dev = hp; + return 0; } module_init(hvc_rtas_init); @@ -114,8 +107,8 @@ module_init(hvc_rtas_init); /* This will tear down the tty portion of the driver */ static void __exit hvc_rtas_exit(void) { - /* Really the fun isn't over until the worker thread breaks down and the - * tty cleans up */ + /* Really the fun isn't over until the worker thread breaks down and + * the tty cleans up */ if (hvc_rtas_dev) hvc_remove(hvc_rtas_dev); } @@ -127,12 +120,14 @@ static int hvc_rtas_console_init(void) rtascons_put_char_token = rtas_token("put-term-char"); if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE) return -EIO; + rtascons_get_char_token = rtas_token("get-term-char"); if (rtascons_get_char_token == RTAS_UNKNOWN_SERVICE) return -EIO; - hvc_instantiate(hvc_rtas_cookie, 0, &hvc_rtas_get_put_ops ); + hvc_instantiate(hvc_rtas_cookie, 0, &hvc_rtas_get_put_ops); add_preferred_console("hvc", 0, NULL); + return 0; } console_initcall(hvc_rtas_console_init); -- cgit v1.2.3 From 050613545b389825c1f5beb67fa2667b727f866d Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sat, 10 Jun 2006 18:17:35 +1000 Subject: powerpc: Fix bug in iommu_alloc_coherent causing hang during boot In commit 8eb6c6e3b9c8bfed3d75536ab142d7694627c2e5, Christoph Hellwig made iommu_alloc_coherent able to do node-local allocations, but unfortunately got the order of the arguments to alloc_pages_node wrong. This fixes it. Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index cbb794556d0..cef8cba8329 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c @@ -561,7 +561,7 @@ void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, return NULL; /* Alloc enough pages (and possibly more) */ - page = alloc_pages_node(flag, order, node); + page = alloc_pages_node(node, flag, order); if (!page) return NULL; ret = page_address(page); -- cgit v1.2.3 From cbd5f69b98bb5d7a0d207230bcf8fa51fca3f3cf Mon Sep 17 00:00:00 2001 From: "Leubner, Achim" Date: Fri, 9 Jun 2006 11:34:29 -0700 Subject: [SCSI] remove the scsi_request interface from the gdth driver Initial pass at converting the gdth driver away from the scsi_request interface so that the request interface can be removed post 2.6.18 without breaking gdth. Based on changes from Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/scsi/gdth.c | 511 ++++++++++++++++++++------------------------ drivers/scsi/gdth.h | 8 +- drivers/scsi/gdth_kcompat.h | 14 +- drivers/scsi/gdth_proc.c | 245 ++++----------------- drivers/scsi/gdth_proc.h | 16 +- 5 files changed, 297 insertions(+), 497 deletions(-) diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index 9b918fd43bf..e720bb017c1 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c @@ -4,9 +4,9 @@ * Intel Corporation: Storage RAID Controllers * * * * gdth.c * - * Copyright (C) 1995-04 ICP vortex GmbH, Achim Leubner * + * Copyright (C) 1995-06 ICP vortex GmbH, Achim Leubner * * Copyright (C) 2002-04 Intel Corporation * - * Copyright (C) 2003-04 Adaptec Inc. * + * Copyright (C) 2003-06 Adaptec Inc. * * * * * * Additions/Fixes: * @@ -27,9 +27,14 @@ * along with this kernel; if not, write to the Free Software * * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * * - * Linux kernel 2.2.x, 2.4.x, 2.6.x supported * + * Linux kernel 2.4.x, 2.6.x supported * * * * $Log: gdth.c,v $ + * Revision 1.74 2006/04/10 13:44:47 achim + * Community changes for 2.6.x + * Kernel 2.2.x no longer supported + * scsi_request interface removed, thanks to Christoph Hellwig + * * Revision 1.73 2004/03/31 13:33:03 achim * Special command 0xfd implemented to detect 64-bit DMA support * @@ -94,7 +99,7 @@ * Bugfix free_irq() * * Revision 1.56 2001/08/09 11:19:39 achim - * struct scsi_host_template changes + * Scsi_Host_Template changes * * Revision 1.55 2001/08/09 10:11:28 achim * Command HOST_UNFREEZE_IO before cache service init. @@ -388,7 +393,13 @@ #include #include #include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,6) #include +#else +#define DMA_32BIT_MASK 0x00000000ffffffffULL +#define DMA_64BIT_MASK 0xffffffffffffffffULL +#endif + #ifdef GDTH_RTC #include #endif @@ -408,8 +419,8 @@ #include "scsi.h" #include -#include "gdth.h" #include "gdth_kcompat.h" +#include "gdth.h" static void gdth_delay(int milliseconds); static void gdth_eval_mapping(ulong32 size, ulong32 *cyls, int *heads, int *secs); @@ -464,6 +475,8 @@ static int gdth_ioctl(struct inode *inode, struct file *filep, static void gdth_flush(int hanum); static int gdth_halt(struct notifier_block *nb, ulong event, void *buf); +static int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *)); +static void gdth_scsi_done(struct scsi_cmnd *scp); #ifdef DEBUG_GDTH static unchar DebugState = DEBUG_GDTH; @@ -643,6 +656,7 @@ static int probe_eisa_isa = 0; static int force_dma32 = 0; /* parameters for modprobe/insmod */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11) module_param_array(irq, int, NULL, 0); module_param(disable, int, 0); module_param(reserve_mode, int, 0); @@ -655,6 +669,20 @@ module_param(virt_ctr, int, 0); module_param(shared_access, int, 0); module_param(probe_eisa_isa, int, 0); module_param(force_dma32, int, 0); +#else +MODULE_PARM(irq, "i"); +MODULE_PARM(disable, "i"); +MODULE_PARM(reserve_mode, "i"); +MODULE_PARM(reserve_list, "4-" __MODULE_STRING(MAX_RES_ARGS) "i"); +MODULE_PARM(reverse_scan, "i"); +MODULE_PARM(hdr_channel, "i"); +MODULE_PARM(max_ids, "i"); +MODULE_PARM(rescan, "i"); +MODULE_PARM(virt_ctr, "i"); +MODULE_PARM(shared_access, "i"); +MODULE_PARM(probe_eisa_isa, "i"); +MODULE_PARM(force_dma32, "i"); +#endif MODULE_AUTHOR("Achim Leubner"); MODULE_LICENSE("GPL"); @@ -683,6 +711,91 @@ static void gdth_delay(int milliseconds) } } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +static void gdth_scsi_done(struct scsi_cmnd *scp) +{ + TRACE2(("gdth_scsi_done()\n")); + + if (scp->sc_request) + complete((struct completion *)scp->sc_request); +} + +int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd, + int timeout, u32 *info) +{ + Scsi_Cmnd *scp; + DECLARE_COMPLETION(wait); + int rval; + + scp = kmalloc(sizeof(*scp), GFP_KERNEL); + if (!scp) + return -ENOMEM; + memset(scp, 0, sizeof(*scp)); + scp->device = sdev; + /* use sc_request field to save the ptr. to completion struct. */ + scp->sc_request = (struct scsi_request *)&wait; + scp->timeout_per_command = timeout*HZ; + scp->request_buffer = gdtcmd; + scp->cmd_len = 12; + memcpy(scp->cmnd, cmnd, 12); + scp->SCp.this_residual = IOCTL_PRI; /* priority */ + scp->done = gdth_scsi_done; /* some fn. test this */ + gdth_queuecommand(scp, gdth_scsi_done); + wait_for_completion(&wait); + + rval = scp->SCp.Status; + if (info) + *info = scp->SCp.Message; + kfree(scp); + return rval; +} +#else +static void gdth_scsi_done(Scsi_Cmnd *scp) +{ + TRACE2(("gdth_scsi_done()\n")); + + scp->request.rq_status = RQ_SCSI_DONE; + if (scp->request.waiting) + complete(scp->request.waiting); +} + +int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd, + int timeout, u32 *info) +{ + Scsi_Cmnd *scp = scsi_allocate_device(sdev, 1, FALSE); + unsigned bufflen = gdtcmd ? sizeof(gdth_cmd_str) : 0; + DECLARE_COMPLETION(wait); + int rval; + + if (!scp) + return -ENOMEM; + scp->cmd_len = 12; + scp->use_sg = 0; + scp->SCp.this_residual = IOCTL_PRI; /* priority */ + scp->request.rq_status = RQ_SCSI_BUSY; + scp->request.waiting = &wait; + scsi_do_cmd(scp, cmnd, gdtcmd, bufflen, gdth_scsi_done, timeout*HZ, 1); + wait_for_completion(&wait); + + rval = scp->SCp.Status; + if (info) + *info = scp->SCp.Message; + + scsi_release_command(scp); + return rval; +} +#endif + +int gdth_execute(struct Scsi_Host *shost, gdth_cmd_str *gdtcmd, char *cmnd, + int timeout, u32 *info) +{ + struct scsi_device *sdev = scsi_get_host_dev(shost); + int rval = __gdth_execute(sdev, gdtcmd, cmnd, timeout, info); + + scsi_free_host_dev(sdev); + return rval; +} + static void gdth_eval_mapping(ulong32 size, ulong32 *cyls, int *heads, int *secs) { *cyls = size /HEADS/SECS; @@ -773,7 +886,7 @@ static struct pci_device_id gdthtable[] __attribute_used__ = { MODULE_DEVICE_TABLE(pci,gdthtable); static void __init gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt, - ushort vendor, ushort device) + ushort vendor, ushort device) { ulong base0, base1, base2; struct pci_dev *pdev; @@ -2248,14 +2361,16 @@ static void gdth_putq(int hanum,Scsi_Cmnd *scp,unchar priority) ha = HADATA(gdth_ctr_tab[hanum]); spin_lock_irqsave(&ha->smp_lock, flags); - scp->SCp.this_residual = (int)priority; - b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel; - t = scp->device->id; - if (priority >= DEFAULT_PRI) { - if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) || - (b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock)) { - TRACE2(("gdth_putq(): locked IO -> update_timeout()\n")); - scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0); + if (scp->done != gdth_scsi_done) { + scp->SCp.this_residual = (int)priority; + b = virt_ctr ? NUMDATA(scp->device->host)->busnum:scp->device->channel; + t = scp->device->id; + if (priority >= DEFAULT_PRI) { + if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) || + (b==ha->virt_bus && thdr[t].lock)) { + TRACE2(("gdth_putq(): locked IO ->update_timeout()\n")); + scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0); + } } } @@ -2309,14 +2424,18 @@ static void gdth_next(int hanum) for (nscp = pscp = ha->req_first; nscp; nscp = (Scsi_Cmnd *)nscp->SCp.ptr) { if (nscp != pscp && nscp != (Scsi_Cmnd *)pscp->SCp.ptr) pscp = (Scsi_Cmnd *)pscp->SCp.ptr; - b = virt_ctr ? NUMDATA(nscp->device->host)->busnum : nscp->device->channel; - t = nscp->device->id; - l = nscp->device->lun; - if (nscp->SCp.this_residual >= DEFAULT_PRI) { - if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) || - (b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock)) - continue; - } + if (nscp->done != gdth_scsi_done) { + b = virt_ctr ? + NUMDATA(nscp->device->host)->busnum : nscp->device->channel; + t = nscp->device->id; + l = nscp->device->lun; + if (nscp->SCp.this_residual >= DEFAULT_PRI) { + if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) || + (b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock)) + continue; + } + } else + b = t = l = 0; if (firsttime) { if (gdth_test_busy(hanum)) { /* controller busy ? */ @@ -2331,7 +2450,7 @@ static void gdth_next(int hanum) firsttime = FALSE; } - if (nscp->done != gdth_scsi_done || nscp->cmnd[0] != 0xff) { + if (nscp->done != gdth_scsi_done) { if (nscp->SCp.phase == -1) { nscp->SCp.phase = CACHESERVICE; /* default: cache svc. */ if (nscp->cmnd[0] == TEST_UNIT_READY) { @@ -2394,7 +2513,7 @@ static void gdth_next(int hanum) else nscp->scsi_done(nscp); } - } else if (nscp->done == gdth_scsi_done && nscp->cmnd[0] == 0xff) { + } else if (nscp->done == gdth_scsi_done) { if (!(cmd_index=gdth_special_cmd(hanum,nscp))) this_cmd = FALSE; next_cmd = FALSE; @@ -2548,7 +2667,7 @@ static void gdth_copy_internal_data(int hanum,Scsi_Cmnd *scp, if (scp->use_sg) { sl = (struct scatterlist *)scp->request_buffer; for (i=0,cpsum=0; iuse_sg; ++i,++sl) { - unsigned long flags; + unsigned long flags; cpnow = (ushort)sl->length; TRACE(("copy_internal() now %d sum %d count %d %d\n", cpnow,cpsum,cpcount,(ushort)scp->bufflen)); @@ -2560,12 +2679,19 @@ static void gdth_copy_internal_data(int hanum,Scsi_Cmnd *scp, hanum); return; } - local_irq_save(flags); - address = kmap_atomic(sl->page, KM_BIO_SRC_IRQ) + sl->offset; + local_irq_save(flags); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + address = kmap_atomic(sl->page, KM_BIO_SRC_IRQ) + sl->offset; + memcpy(address,buffer,cpnow); + flush_dcache_page(sl->page); + kunmap_atomic(address, KM_BIO_SRC_IRQ); +#else + address = kmap_atomic(sl->page, KM_BH_IRQ) + sl->offset; memcpy(address,buffer,cpnow); - flush_dcache_page(sl->page); - kunmap_atomic(address, KM_BIO_SRC_IRQ); - local_irq_restore(flags); + flush_dcache_page(sl->page); + kunmap_atomic(address, KM_BH_IRQ); +#endif + local_irq_restore(flags); if (cpsum == cpcount) break; buffer += cpnow; @@ -2946,9 +3072,9 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b) offset = (ulong)scp->sense_buffer & ~PAGE_MASK; sense_paddr = pci_map_page(ha->pdev,page,offset, 16,PCI_DMA_FROMDEVICE); - scp->SCp.buffer = (struct scatterlist *)((ulong32)sense_paddr); + *(ulong32 *)&scp->SCp.buffer = (ulong32)sense_paddr; /* high part, if 64bit */ - scp->host_scribble = (char *)(ulong32)((ulong64)sense_paddr >> 32); + *(ulong32 *)&scp->host_scribble = (ulong32)((ulong64)sense_paddr >> 32); cmdp->OpCode = GDT_WRITE; /* always */ cmdp->BoardNode = LOCALBOARD; if (mode64) { @@ -3022,7 +3148,7 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b) } #endif - } else { + } else if (scp->request_bufflen) { scp->SCp.Status = GDTH_MAP_SINGLE; scp->SCp.Message = PCI_DMA_BIDIRECTIONAL; page = virt_to_page(scp->request_buffer); @@ -3309,7 +3435,7 @@ static irqreturn_t gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs) } if (!gdth_polling) - spin_lock_irqsave(&ha2->smp_lock, flags); + spin_lock_irqsave(&ha2->smp_lock, flags); wait_index = 0; /* search controller */ @@ -3642,9 +3768,10 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp) scp->request_bufflen,scp->SCp.Message); if (scp->SCp.buffer) { dma_addr_t addr; - addr = (dma_addr_t)(ulong32)scp->SCp.buffer; + addr = (dma_addr_t)*(ulong32 *)&scp->SCp.buffer; if (scp->host_scribble) - addr += (dma_addr_t)((ulong64)(ulong32)scp->host_scribble << 32); + addr += (dma_addr_t) + ((ulong64)(*(ulong32 *)&scp->host_scribble) << 32); pci_unmap_page(ha->pdev,addr,16,PCI_DMA_FROMDEVICE); } @@ -4154,7 +4281,11 @@ int __init option_setup(char *str) return 1; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) static int __init gdth_detect(struct scsi_host_template *shtp) +#else +static int __init gdth_detect(Scsi_Host_Template *shtp) +#endif { struct Scsi_Host *shp; gdth_pci_str pcistr[MAXHA]; @@ -4188,7 +4319,7 @@ static int __init gdth_detect(struct scsi_host_template *shtp) return 0; } - printk("GDT-HA: Storage RAID Controller Driver. Version: %s \n",GDTH_VERSION_STR); + printk("GDT-HA: Storage RAID Controller Driver. Version: %s\n",GDTH_VERSION_STR); /* initializations */ gdth_polling = TRUE; b = 0; gdth_clear_events(); @@ -4751,7 +4882,7 @@ static int gdth_eh_bus_reset(Scsi_Cmnd *scp) gdth_internal_cmd(hanum, SCSIRAWSERVICE, GDT_RESET_BUS, BUS_L2P(ha,b), 0, 0); gdth_polling = FALSE; - spin_unlock_irqrestore(&ha->smp_lock, flags); + spin_unlock_irqrestore(&ha->smp_lock, flags); } return SUCCESS; } @@ -4819,7 +4950,9 @@ static int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *)) priority = DEFAULT_PRI; if (scp->done == gdth_scsi_done) priority = scp->SCp.this_residual; - gdth_update_timeout(hanum, scp, scp->timeout_per_command * 6); + else + gdth_update_timeout(hanum, scp, scp->timeout_per_command * 6); + gdth_putq( hanum, scp, priority ); gdth_next( hanum ); return 0; @@ -4922,11 +5055,7 @@ static int ioc_resetdrv(void __user *arg, char *cmnd) gdth_cmd_str cmd; int hanum; gdth_ha_str *ha; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - Scsi_Request *srp; -#else - Scsi_Cmnd *scp; -#endif + int rval; if (copy_from_user(&res, arg, sizeof(gdth_ioctl_reset)) || res.ionode >= gdth_ctr_count || res.number >= MAX_HDRIVES) @@ -4943,25 +5072,11 @@ static int ioc_resetdrv(void __user *arg, char *cmnd) cmd.u.cache64.DeviceNo = res.number; else cmd.u.cache.DeviceNo = res.number; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - srp = scsi_allocate_request(ha->sdev, GFP_KERNEL); - if (!srp) - return -ENOMEM; - srp->sr_cmd_len = 12; - srp->sr_use_sg = 0; - gdth_do_req(srp, &cmd, cmnd, 30); - res.status = (ushort)srp->sr_command->SCp.Status; - scsi_release_request(srp); -#else - scp = scsi_allocate_device(ha->sdev, 1, FALSE); - if (!scp) - return -ENOMEM; - scp->cmd_len = 12; - scp->use_sg = 0; - gdth_do_cmd(scp, &cmd, cmnd, 30); - res.status = (ushort)scp->SCp.Status; - scsi_release_command(scp); -#endif + + rval = __gdth_execute(ha->sdev, &cmd, cmnd, 30, NULL); + if (rval < 0) + return rval; + res.status = rval; if (copy_to_user(arg, &res, sizeof(gdth_ioctl_reset))) return -EFAULT; @@ -4974,12 +5089,8 @@ static int ioc_general(void __user *arg, char *cmnd) char *buf = NULL; ulong64 paddr; int hanum; - gdth_ha_str *ha; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - Scsi_Request *srp; -#else - Scsi_Cmnd *scp; -#endif + gdth_ha_str *ha; + int rval; if (copy_from_user(&gen, arg, sizeof(gdth_ioctl_general)) || gen.ionode >= gdth_ctr_count) @@ -5071,27 +5182,10 @@ static int ioc_general(void __user *arg, char *cmnd) } } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - srp = scsi_allocate_request(ha->sdev, GFP_KERNEL); - if (!srp) - return -ENOMEM; - srp->sr_cmd_len = 12; - srp->sr_use_sg = 0; - gdth_do_req(srp, &gen.command, cmnd, gen.timeout); - gen.status = srp->sr_command->SCp.Status; - gen.info = srp->sr_command->SCp.Message; - scsi_release_request(srp); -#else - scp = scsi_allocate_device(ha->sdev, 1, FALSE); - if (!scp) - return -ENOMEM; - scp->cmd_len = 12; - scp->use_sg = 0; - gdth_do_cmd(scp, &gen.command, cmnd, gen.timeout); - gen.status = scp->SCp.Status; - gen.info = scp->SCp.Message; - scsi_release_command(scp); -#endif + rval = __gdth_execute(ha->sdev, &gen.command, cmnd, gen.timeout, &gen.info); + if (rval < 0) + return rval; + gen.status = rval; if (copy_to_user(arg + sizeof(gdth_ioctl_general), buf, gen.data_len + gen.sense_len)) { @@ -5114,40 +5208,22 @@ static int ioc_hdrlist(void __user *arg, char *cmnd) gdth_ha_str *ha; unchar i; int hanum, rc = -ENOMEM; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - Scsi_Request *srp; -#else - Scsi_Cmnd *scp; -#endif - + u32 cluster_type = 0; + rsc = kmalloc(sizeof(*rsc), GFP_KERNEL); cmd = kmalloc(sizeof(*cmd), GFP_KERNEL); if (!rsc || !cmd) - goto free_fail; + goto free_fail; if (copy_from_user(rsc, arg, sizeof(gdth_ioctl_rescan)) || rsc->ionode >= gdth_ctr_count) { rc = -EFAULT; - goto free_fail; + goto free_fail; } hanum = rsc->ionode; ha = HADATA(gdth_ctr_tab[hanum]); memset(cmd, 0, sizeof(gdth_cmd_str)); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - srp = scsi_allocate_request(ha->sdev, GFP_KERNEL); - if (!srp) - goto free_fail; - srp->sr_cmd_len = 12; - srp->sr_use_sg = 0; -#else - scp = scsi_allocate_device(ha->sdev, 1, FALSE); - if (!scp) - goto free_fail; - scp->cmd_len = 12; - scp->use_sg = 0; -#endif - for (i = 0; i < MAX_HDRIVES; ++i) { if (!ha->hdr[i].present) { rsc->hdr_list[i].bus = 0xff; @@ -5164,27 +5240,15 @@ static int ioc_hdrlist(void __user *arg, char *cmnd) cmd->u.cache64.DeviceNo = i; else cmd->u.cache.DeviceNo = i; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - gdth_do_req(srp, cmd, cmnd, 30); - if (srp->sr_command->SCp.Status == S_OK) - rsc->hdr_list[i].cluster_type = srp->sr_command->SCp.Message; -#else - gdth_do_cmd(scp, cmd, cmnd, 30); - if (scp->SCp.Status == S_OK) - rsc->hdr_list[i].cluster_type = scp->SCp.Message; -#endif + if (__gdth_execute(ha->sdev, cmd, cmnd, 30, &cluster_type) == S_OK) + rsc->hdr_list[i].cluster_type = cluster_type; } } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - scsi_release_request(srp); -#else - scsi_release_command(scp); -#endif - + if (copy_to_user(arg, rsc, sizeof(gdth_ioctl_rescan))) rc = -EFAULT; else - rc = 0; + rc = 0; free_fail: kfree(rsc); @@ -5202,40 +5266,21 @@ static int ioc_rescan(void __user *arg, char *cmnd) int rc = -ENOMEM; ulong flags; gdth_ha_str *ha; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - Scsi_Request *srp; -#else - Scsi_Cmnd *scp; -#endif rsc = kmalloc(sizeof(*rsc), GFP_KERNEL); cmd = kmalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd || !rsc) - goto free_fail; + goto free_fail; if (copy_from_user(rsc, arg, sizeof(gdth_ioctl_rescan)) || rsc->ionode >= gdth_ctr_count) { - rc = -EFAULT; - goto free_fail; + rc = -EFAULT; + goto free_fail; } hanum = rsc->ionode; ha = HADATA(gdth_ctr_tab[hanum]); memset(cmd, 0, sizeof(gdth_cmd_str)); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - srp = scsi_allocate_request(ha->sdev, GFP_KERNEL); - if (!srp) - goto free_fail; - srp->sr_cmd_len = 12; - srp->sr_use_sg = 0; -#else - scp = scsi_allocate_device(ha->sdev, 1, FALSE); - if (!scp) - goto free_fail; - scp->cmd_len = 12; - scp->use_sg = 0; -#endif - if (rsc->flag == 0) { /* old method: re-init. cache service */ cmd->Service = CACHESERVICE; @@ -5246,19 +5291,8 @@ static int ioc_rescan(void __user *arg, char *cmnd) cmd->OpCode = GDT_INIT; cmd->u.cache.DeviceNo = LINUX_OS; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - gdth_do_req(srp, cmd, cmnd, 30); - status = (ushort)srp->sr_command->SCp.Status; - info = (ulong32)srp->sr_command->SCp.Message; -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - gdth_do_cmd(scp, cmd, cmnd, 30); - status = (ushort)scp->SCp.Status; - info = (ulong32)scp->SCp.Message; -#else - gdth_do_cmd(&scp, cmd, cmnd, 30); - status = (ushort)scp.SCp.Status; - info = (ulong32)scp.SCp.Message; -#endif + + status = __gdth_execute(ha->sdev, cmd, cmnd, 30, &info); i = 0; hdr_cnt = (status == S_OK ? (ushort)info : 0); } else { @@ -5273,15 +5307,9 @@ static int ioc_rescan(void __user *arg, char *cmnd) cmd->u.cache64.DeviceNo = i; else cmd->u.cache.DeviceNo = i; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - gdth_do_req(srp, cmd, cmnd, 30); - status = (ushort)srp->sr_command->SCp.Status; - info = (ulong32)srp->sr_command->SCp.Message; -#else - gdth_do_cmd(scp, cmd, cmnd, 30); - status = (ushort)scp->SCp.Status; - info = (ulong32)scp->SCp.Message; -#endif + + status = __gdth_execute(ha->sdev, cmd, cmnd, 30, &info); + spin_lock_irqsave(&ha->smp_lock, flags); rsc->hdr_list[i].bus = ha->virt_bus; rsc->hdr_list[i].target = i; @@ -5313,15 +5341,9 @@ static int ioc_rescan(void __user *arg, char *cmnd) cmd->u.cache64.DeviceNo = i; else cmd->u.cache.DeviceNo = i; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - gdth_do_req(srp, cmd, cmnd, 30); - status = (ushort)srp->sr_command->SCp.Status; - info = (ulong32)srp->sr_command->SCp.Message; -#else - gdth_do_cmd(scp, cmd, cmnd, 30); - status = (ushort)scp->SCp.Status; - info = (ulong32)scp->SCp.Message; -#endif + + status = __gdth_execute(ha->sdev, cmd, cmnd, 30, &info); + spin_lock_irqsave(&ha->smp_lock, flags); ha->hdr[i].devtype = (status == S_OK ? (ushort)info : 0); spin_unlock_irqrestore(&ha->smp_lock, flags); @@ -5332,15 +5354,9 @@ static int ioc_rescan(void __user *arg, char *cmnd) cmd->u.cache64.DeviceNo = i; else cmd->u.cache.DeviceNo = i; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - gdth_do_req(srp, cmd, cmnd, 30); - status = (ushort)srp->sr_command->SCp.Status; - info = (ulong32)srp->sr_command->SCp.Message; -#else - gdth_do_cmd(scp, cmd, cmnd, 30); - status = (ushort)scp->SCp.Status; - info = (ulong32)scp->SCp.Message; -#endif + + status = __gdth_execute(ha->sdev, cmd, cmnd, 30, &info); + spin_lock_irqsave(&ha->smp_lock, flags); ha->hdr[i].cluster_type = ((status == S_OK && !shared_access) ? (ushort)info : 0); @@ -5353,29 +5369,18 @@ static int ioc_rescan(void __user *arg, char *cmnd) cmd->u.cache64.DeviceNo = i; else cmd->u.cache.DeviceNo = i; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - gdth_do_req(srp, cmd, cmnd, 30); - status = (ushort)srp->sr_command->SCp.Status; - info = (ulong32)srp->sr_command->SCp.Message; -#else - gdth_do_cmd(scp, cmd, cmnd, 30); - status = (ushort)scp->SCp.Status; - info = (ulong32)scp->SCp.Message; -#endif + + status = __gdth_execute(ha->sdev, cmd, cmnd, 30, &info); + spin_lock_irqsave(&ha->smp_lock, flags); ha->hdr[i].rw_attribs = (status == S_OK ? (ushort)info : 0); spin_unlock_irqrestore(&ha->smp_lock, flags); } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - scsi_release_request(srp); -#else - scsi_release_command(scp); -#endif if (copy_to_user(arg, rsc, sizeof(gdth_ioctl_rescan))) rc = -EFAULT; else - rc = 0; + rc = 0; free_fail: kfree(rsc); @@ -5515,17 +5520,18 @@ static int gdth_ioctl(struct inode *inode, struct file *filep, hanum = res.ionode; ha = HADATA(gdth_ctr_tab[hanum]); - /* Because we need a Scsi_Cmnd struct., we make a scsi_allocate device also for kernels >=2.6.x */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - scp = scsi_get_command(ha->sdev, GFP_KERNEL); + scp = kmalloc(sizeof(*scp), GFP_KERNEL); if (!scp) return -ENOMEM; + memset(scp, 0, sizeof(*scp)); + scp->device = ha->sdev; scp->cmd_len = 12; scp->use_sg = 0; scp->device->channel = virt_ctr ? 0 : res.number; rval = gdth_eh_bus_reset(scp); res.status = (rval == SUCCESS ? S_OK : S_GENERR); - scsi_put_command(scp); + kfree(scp); #else scp = scsi_allocate_device(ha->sdev, 1, FALSE); if (!scp) @@ -5558,34 +5564,12 @@ static void gdth_flush(int hanum) int i; gdth_ha_str *ha; gdth_cmd_str gdtcmd; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - Scsi_Request *srp; -#else - Scsi_Cmnd *scp; -#endif - struct scsi_device *sdev; char cmnd[MAX_COMMAND_SIZE]; memset(cmnd, 0xff, MAX_COMMAND_SIZE); TRACE2(("gdth_flush() hanum %d\n",hanum)); ha = HADATA(gdth_ctr_tab[hanum]); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - srp = scsi_allocate_request(sdev, GFP_KERNEL); - if (!srp) - return; - srp->sr_cmd_len = 12; - srp->sr_use_sg = 0; -#else - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - scp = scsi_allocate_device(sdev, 1, FALSE); - if (!scp) - return; - scp->cmd_len = 12; - scp->use_sg = 0; -#endif - for (i = 0; i < MAX_HDRIVES; ++i) { if (ha->hdr[i].present) { gdtcmd.BoardNode = LOCALBOARD; @@ -5601,20 +5585,10 @@ static void gdth_flush(int hanum) gdtcmd.u.cache.sg_canz = 0; } TRACE2(("gdth_flush(): flush ha %d drive %d\n", hanum, i)); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - gdth_do_req(srp, &gdtcmd, cmnd, 30); -#else - gdth_do_cmd(scp, &gdtcmd, cmnd, 30); -#endif + + gdth_execute(gdth_ctr_tab[hanum], &gdtcmd, cmnd, 30, NULL); } } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - scsi_release_request(srp); - scsi_free_host_dev(sdev); -#else - scsi_release_command(scp); - scsi_free_host_dev(sdev); -#endif } /* shutdown routine */ @@ -5623,18 +5597,11 @@ static int gdth_halt(struct notifier_block *nb, ulong event, void *buf) int hanum; #ifndef __alpha__ gdth_cmd_str gdtcmd; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - Scsi_Request *srp; - struct scsi_device *sdev; -#else - Scsi_Cmnd *scp; - struct scsi_device *sdev; -#endif char cmnd[MAX_COMMAND_SIZE]; #endif if (notifier_disabled) - return NOTIFY_OK; + return NOTIFY_OK; TRACE2(("gdth_halt() event %d\n",(int)event)); if (event != SYS_RESTART && event != SYS_HALT && event != SYS_POWER_OFF) @@ -5652,31 +5619,7 @@ static int gdth_halt(struct notifier_block *nb, ulong event, void *buf) gdtcmd.Service = CACHESERVICE; gdtcmd.OpCode = GDT_RESET; TRACE2(("gdth_halt(): reset controller %d\n", hanum)); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - srp = scsi_allocate_request(sdev, GFP_KERNEL); - if (!srp) { - unregister_reboot_notifier(&gdth_notifier); - return NOTIFY_OK; - } - srp->sr_cmd_len = 12; - srp->sr_use_sg = 0; - gdth_do_req(srp, &gdtcmd, cmnd, 10); - scsi_release_request(srp); - scsi_free_host_dev(sdev); -#else - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - scp = scsi_allocate_device(sdev, 1, FALSE); - if (!scp) { - unregister_reboot_notifier(&gdth_notifier); - return NOTIFY_OK; - } - scp->cmd_len = 12; - scp->use_sg = 0; - gdth_do_cmd(scp, &gdtcmd, cmnd, 10); - scsi_release_command(scp); - scsi_free_host_dev(sdev); -#endif + gdth_execute(gdth_ctr_tab[hanum], &gdtcmd, cmnd, 10, NULL); #endif } printk("Done.\n"); @@ -5687,7 +5630,22 @@ static int gdth_halt(struct notifier_block *nb, ulong event, void *buf) return NOTIFY_OK; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +/* configure lun */ +static int gdth_slave_configure(struct scsi_device *sdev) +{ + scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun); + sdev->skip_ms_page_3f = 1; + sdev->skip_ms_page_8 = 1; + return 0; +} +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) static struct scsi_host_template driver_template = { +#else +static Scsi_Host_Template driver_template = { +#endif .proc_name = "gdth", .proc_info = gdth_proc_info, .name = "GDT SCSI Disk Array Controller", @@ -5698,6 +5656,9 @@ static struct scsi_host_template driver_template = { .eh_bus_reset_handler = gdth_eh_bus_reset, .bios_param = gdth_bios_param, .can_queue = GDTH_MAXCMDS, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + .slave_configure = gdth_slave_configure, +#endif .this_id = -1, .sg_tablesize = GDTH_MAXSG, .cmd_per_lun = GDTH_MAXC_P_L, diff --git a/drivers/scsi/gdth.h b/drivers/scsi/gdth.h index cc4882fb97a..47eae029975 100644 --- a/drivers/scsi/gdth.h +++ b/drivers/scsi/gdth.h @@ -4,13 +4,13 @@ /* * Header file for the GDT Disk Array/Storage RAID controllers driver for Linux * - * gdth.h Copyright (C) 1995-03 ICP vortex, Achim Leubner + * gdth.h Copyright (C) 1995-06 ICP vortex, Achim Leubner * See gdth.c for further informations and * below for supported controller types * * * - * $Id: gdth.h,v 1.57 2004/03/31 11:52:09 achim Exp $ + * $Id: gdth.h,v 1.58 2006/01/11 16:14:09 achim Exp $ */ #include @@ -26,9 +26,9 @@ /* defines, macros */ /* driver version */ -#define GDTH_VERSION_STR "3.04" +#define GDTH_VERSION_STR "3.05" #define GDTH_VERSION 3 -#define GDTH_SUBVERSION 4 +#define GDTH_SUBVERSION 5 /* protocol version */ #define PROTOCOL_VERSION 1 diff --git a/drivers/scsi/gdth_kcompat.h b/drivers/scsi/gdth_kcompat.h index e6cf0edfa0c..2a302eee669 100644 --- a/drivers/scsi/gdth_kcompat.h +++ b/drivers/scsi/gdth_kcompat.h @@ -1,5 +1,3 @@ - - #ifndef IRQ_HANDLED typedef void irqreturn_t; #define IRQ_NONE @@ -10,6 +8,18 @@ typedef void irqreturn_t; #define MODULE_LICENSE(x) #endif +#ifndef __iomem +#define __iomem +#endif + +#ifndef __attribute_used__ +#define __attribute_used__ __devinitdata +#endif + +#ifndef __user +#define __user +#endif + #ifndef SERVICE_ACTION_IN #define SERVICE_ACTION_IN 0x9e #endif diff --git a/drivers/scsi/gdth_proc.c b/drivers/scsi/gdth_proc.c index 5e8657f9cdf..32982eb75c8 100644 --- a/drivers/scsi/gdth_proc.c +++ b/drivers/scsi/gdth_proc.c @@ -1,5 +1,5 @@ /* gdth_proc.c - * $Id: gdth_proc.c,v 1.42 2004/03/05 15:50:20 achim Exp $ + * $Id: gdth_proc.c,v 1.43 2006/01/11 16:15:00 achim Exp $ */ #include @@ -51,57 +51,26 @@ int gdth_proc_info(char *buffer,char **start,off_t offset,int length,int hostno, static int gdth_set_info(char *buffer,int length,struct Scsi_Host *host, int hanum,int busnum) { - int ret_val = -EINVAL; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - Scsi_Request *scp; - struct scsi_device *sdev; -#else - Scsi_Cmnd *scp; - struct scsi_device *sdev; -#endif - TRACE2(("gdth_set_info() ha %d bus %d\n",hanum,busnum)); + int ret_val = -EINVAL; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - sdev = scsi_get_host_dev(host); - scp = scsi_allocate_request(sdev, GFP_KERNEL); - if (!scp) - return -ENOMEM; - scp->sr_cmd_len = 12; - scp->sr_use_sg = 0; -#else - sdev = scsi_get_host_dev(host); - scp = scsi_allocate_device(sdev, 1, FALSE); - if (!scp) - return -ENOMEM; - scp->cmd_len = 12; - scp->use_sg = 0; -#endif + TRACE2(("gdth_set_info() ha %d bus %d\n",hanum,busnum)); if (length >= 4) { if (strncmp(buffer,"gdth",4) == 0) { buffer += 5; length -= 5; - ret_val = gdth_set_asc_info( buffer, length, hanum, scp ); + ret_val = gdth_set_asc_info(host, buffer, length, hanum); } } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - scsi_release_request(scp); - scsi_free_host_dev(sdev); -#else - scsi_release_command(scp); - scsi_free_host_dev(sdev); -#endif + return ret_val; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Request *scp) -#else -static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd *scp) -#endif +static int gdth_set_asc_info(struct Scsi_Host *host, char *buffer, + int length,int hanum) { - int orig_length, drive, wb_mode; - int i, found; + int orig_length, drive, wb_mode; + int i, found; gdth_ha_str *ha; gdth_cmd_str gdtcmd; gdth_cpar_str *pcpar; @@ -146,11 +115,8 @@ static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd *scp) gdtcmd.u.cache.DeviceNo = i; gdtcmd.u.cache.BlockNo = 1; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - gdth_do_req(scp, &gdtcmd, cmnd, 30); -#else - gdth_do_cmd(scp, &gdtcmd, cmnd, 30); -#endif + + gdth_execute(host, &gdtcmd, cmnd, 30, NULL); } } if (!found) @@ -202,11 +168,9 @@ static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd *scp) gdtcmd.u.ioctl.subfunc = CACHE_CONFIG; gdtcmd.u.ioctl.channel = INVALID_CHANNEL; pcpar->write_back = wb_mode==1 ? 0:1; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - gdth_do_req(scp, &gdtcmd, cmnd, 30); -#else - gdth_do_cmd(scp, &gdtcmd, cmnd, 30); -#endif + + gdth_execute(host, &gdtcmd, cmnd, 30, NULL); + gdth_ioctl_free(hanum, GDTH_SCRATCH, ha->pscratch, paddr); printk("Done.\n"); return(orig_length); @@ -230,13 +194,6 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length, gdth_cmd_str *gdtcmd; gdth_evt_str *estr; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - Scsi_Request *scp; - struct scsi_device *sdev; -#else - Scsi_Cmnd *scp; - struct scsi_device *sdev; -#endif char hrec[161]; struct timeval tv; @@ -252,7 +209,7 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length, gdtcmd = kmalloc(sizeof(*gdtcmd), GFP_KERNEL); estr = kmalloc(sizeof(*estr), GFP_KERNEL); if (!gdtcmd || !estr) - goto free_fail; + goto free_fail; memset(cmnd, 0xff, 12); memset(gdtcmd, 0, sizeof(gdth_cmd_str)); @@ -260,28 +217,6 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length, TRACE2(("gdth_get_info() ha %d bus %d\n",hanum,busnum)); ha = HADATA(gdth_ctr_tab[hanum]); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - sdev = scsi_get_host_dev(host); - scp = scsi_allocate_request(sdev, GFP_KERNEL); - if (!scp) - goto free_fail; - scp->sr_cmd_len = 12; - scp->sr_use_sg = 0; -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - sdev = scsi_get_host_dev(host); - scp = scsi_allocate_device(sdev, 1, FALSE); - if (!scp) - goto free_fail; - scp->cmd_len = 12; - scp->use_sg = 0; -#else - memset(&sdev,0,sizeof(struct scsi_device)); - memset(&scp, 0,sizeof(Scsi_Cmnd)); - sdev.host = scp.host = host; - sdev.id = scp.target = sdev.host->this_id; - scp.device = &sdev; -#endif - /* request is i.e. "cat /proc/scsi/gdth/0" */ /* format: %-15s\t%-10s\t%-15s\t%s */ @@ -386,16 +321,9 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length, sizeof(pds->list[0]); if (pds->entries > cnt) pds->entries = cnt; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - gdth_do_req(scp, gdtcmd, cmnd, 30); - if (scp->sr_command->SCp.Status != S_OK) -#else - gdth_do_cmd(scp, gdtcmd, cmnd, 30); - if (scp->SCp.Status != S_OK) -#endif - { + + if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) != S_OK) pds->count = 0; - } /* other IOCTLs must fit into area GDTH_SCRATCH/4 */ for (j = 0; j < ha->raw[i].pdev_cnt; ++j) { @@ -410,14 +338,8 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length, gdtcmd->u.ioctl.subfunc = SCSI_DR_INFO | L_CTRL_PATTERN; gdtcmd->u.ioctl.channel = ha->raw[i].address | ha->raw[i].id_list[j]; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - gdth_do_req(scp, gdtcmd, cmnd, 30); - if (scp->sr_command->SCp.Status == S_OK) -#else - gdth_do_cmd(scp, gdtcmd, cmnd, 30); - if (scp->SCp.Status == S_OK) -#endif - { + + if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) == S_OK) { strncpy(hrec,pdi->vendor,8); strncpy(hrec+8,pdi->product,16); strncpy(hrec+24,pdi->revision,4); @@ -466,14 +388,8 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length, gdtcmd->u.ioctl.channel = ha->raw[i].address | ha->raw[i].id_list[j]; pdef->sddc_type = 0x08; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - gdth_do_req(scp, gdtcmd, cmnd, 30); - if (scp->sr_command->SCp.Status == S_OK) -#else - gdth_do_cmd(scp, gdtcmd, cmnd, 30); - if (scp->SCp.Status == S_OK) -#endif - { + + if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) == S_OK) { size = sprintf(buffer+len, " Grown Defects:\t%d\n", pdef->sddc_cnt); @@ -519,16 +435,8 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length, gdtcmd->u.ioctl.param_size = sizeof(gdth_cdrinfo_str); gdtcmd->u.ioctl.subfunc = CACHE_DRV_INFO; gdtcmd->u.ioctl.channel = drv_no; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - gdth_do_req(scp, gdtcmd, cmnd, 30); - if (scp->sr_command->SCp.Status != S_OK) -#else - gdth_do_cmd(scp, gdtcmd, cmnd, 30); - if (scp->SCp.Status != S_OK) -#endif - { + if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) != S_OK) break; - } pcdi->ld_dtype >>= 16; j++; if (pcdi->ld_dtype > 2) { @@ -629,14 +537,7 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length, gdtcmd->u.ioctl.param_size = sizeof(gdth_arrayinf_str); gdtcmd->u.ioctl.subfunc = ARRAY_INFO | LA_CTRL_PATTERN; gdtcmd->u.ioctl.channel = i; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - gdth_do_req(scp, gdtcmd, cmnd, 30); - if (scp->sr_command->SCp.Status == S_OK) -#else - gdth_do_cmd(scp, gdtcmd, cmnd, 30); - if (scp->SCp.Status == S_OK) -#endif - { + if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) == S_OK) { if (pai->ai_state == 0) strcpy(hrec, "idle"); else if (pai->ai_state == 2) @@ -710,14 +611,7 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length, gdtcmd->u.ioctl.channel = i; phg->entries = MAX_HDRIVES; phg->offset = GDTOFFSOF(gdth_hget_str, entry[0]); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - gdth_do_req(scp, gdtcmd, cmnd, 30); - if (scp->sr_command->SCp.Status != S_OK) -#else - gdth_do_cmd(scp, gdtcmd, cmnd, 30); - if (scp->SCp.Status != S_OK) -#endif - { + if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) == S_OK) { ha->hdr[i].ldr_no = i; ha->hdr[i].rw_attribs = 0; ha->hdr[i].start_sec = 0; @@ -791,13 +685,6 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length, } stop_output: -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - scsi_release_request(scp); - scsi_free_host_dev(sdev); -#else - scsi_release_command(scp); - scsi_free_host_dev(sdev); -#endif *start = buffer +(offset-begin); len -= (offset-begin); if (len > length) @@ -812,64 +699,6 @@ free_fail: return rc; } - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -static void gdth_do_req(Scsi_Request *scp, gdth_cmd_str *gdtcmd, - char *cmnd, int timeout) -{ - unsigned bufflen; - DECLARE_COMPLETION(wait); - - TRACE2(("gdth_do_req()\n")); - if (gdtcmd != NULL) { - bufflen = sizeof(gdth_cmd_str); - } else { - bufflen = 0; - } - scp->sr_request->rq_status = RQ_SCSI_BUSY; - scp->sr_request->waiting = &wait; - scsi_do_req(scp, cmnd, gdtcmd, bufflen, gdth_scsi_done, timeout*HZ, 1); - wait_for_completion(&wait); -} - -#else -static void gdth_do_cmd(Scsi_Cmnd *scp, gdth_cmd_str *gdtcmd, - char *cmnd, int timeout) -{ - unsigned bufflen; - DECLARE_COMPLETION(wait); - - TRACE2(("gdth_do_cmd()\n")); - if (gdtcmd != NULL) { - scp->SCp.this_residual = IOCTL_PRI; - bufflen = sizeof(gdth_cmd_str); - } else { - scp->SCp.this_residual = DEFAULT_PRI; - bufflen = 0; - } - - scp->request.rq_status = RQ_SCSI_BUSY; - scp->request.waiting = &wait; - scsi_do_cmd(scp, cmnd, gdtcmd, bufflen, gdth_scsi_done, timeout*HZ, 1); - wait_for_completion(&wait); -} -#endif - -void gdth_scsi_done(Scsi_Cmnd *scp) -{ - TRACE2(("gdth_scsi_done()\n")); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - scp->request->rq_status = RQ_SCSI_DONE; - if (scp->request->waiting != NULL) - complete(scp->request->waiting); -#else - scp->request.rq_status = RQ_SCSI_DONE; - if (scp->request.waiting != NULL) - complete(scp->request.waiting); -#endif -} - static char *gdth_ioctl_alloc(int hanum, int size, int scratch, ulong64 *paddr) { @@ -976,11 +805,14 @@ static void gdth_stop_timeout(int hanum, int busnum, int id) spin_lock_irqsave(&ha->smp_lock, flags); for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) { - b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel; - t = scp->device->id; - if (t == (unchar)id && b == (unchar)busnum) { - TRACE2(("gdth_stop_timeout(): update_timeout()\n")); - scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0); + if (scp->done != gdth_scsi_done) { + b = virt_ctr ? + NUMDATA(scp->device->host)->busnum : scp->device->channel; + t = scp->device->id; + if (t == (unchar)id && b == (unchar)busnum) { + TRACE2(("gdth_stop_timeout(): update_timeout()\n")); + scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0); + } } } spin_unlock_irqrestore(&ha->smp_lock, flags); @@ -997,11 +829,14 @@ static void gdth_start_timeout(int hanum, int busnum, int id) spin_lock_irqsave(&ha->smp_lock, flags); for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) { - b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel; - t = scp->device->id; - if (t == (unchar)id && b == (unchar)busnum) { - TRACE2(("gdth_start_timeout(): update_timeout()\n")); - gdth_update_timeout(hanum, scp, scp->SCp.buffers_residual); + if (scp->done != gdth_scsi_done) { + b = virt_ctr ? + NUMDATA(scp->device->host)->busnum : scp->device->channel; + t = scp->device->id; + if (t == (unchar)id && b == (unchar)busnum) { + TRACE2(("gdth_start_timeout(): update_timeout()\n")); + gdth_update_timeout(hanum, scp, scp->SCp.buffers_residual); + } } } spin_unlock_irqrestore(&ha->smp_lock, flags); diff --git a/drivers/scsi/gdth_proc.h b/drivers/scsi/gdth_proc.h index 295e825e2c6..a679eeb6820 100644 --- a/drivers/scsi/gdth_proc.h +++ b/drivers/scsi/gdth_proc.h @@ -5,20 +5,16 @@ * $Id: gdth_proc.h,v 1.16 2004/01/14 13:09:01 achim Exp $ */ +int gdth_execute(struct Scsi_Host *shost, gdth_cmd_str *gdtcmd, char *cmnd, + int timeout, u32 *info); + static int gdth_set_info(char *buffer,int length,struct Scsi_Host *host, int hanum,int busnum); static int gdth_get_info(char *buffer,char **start,off_t offset,int length, struct Scsi_Host *host,int hanum,int busnum); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -static void gdth_do_req(Scsi_Request *srp, gdth_cmd_str *cmd, - char *cmnd, int timeout); -static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Request *scp); -#else -static void gdth_do_cmd(Scsi_Cmnd *scp, gdth_cmd_str *cmd, - char *cmnd, int timeout); -static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd *scp); -#endif +static int gdth_set_asc_info(struct Scsi_Host *host, char *buffer, + int length, int hanum); static char *gdth_ioctl_alloc(int hanum, int size, int scratch, ulong64 *paddr); @@ -28,7 +24,5 @@ static void gdth_stop_timeout(int hanum, int busnum, int id); static void gdth_start_timeout(int hanum, int busnum, int id); static int gdth_update_timeout(int hanum, Scsi_Cmnd *scp, int timeout); -void gdth_scsi_done(Scsi_Cmnd *scp); - #endif -- cgit v1.2.3 From ede1e6f8b43246a9796583346839669b1f4b77d4 Mon Sep 17 00:00:00 2001 From: HighPoint Linux Team Date: Tue, 16 May 2006 14:38:09 +0800 Subject: [SCSI] hptiop: HighPoint RocketRAID 3xxx controller driver HighPoint RocketRAID 3220/3320 series 8 channel PCI-X SATA RAID Host Adapters. Fixes from original submission: Merge Andrew Morton's patches: - Provide locking for global list - Fix debug printks - uninline function with multiple callsites - coding style fixups - remove unneeded casts of void* - kfree(NULL) is legal - Don't "succeed" if register_chrdev() failed - otherwise we'll later unregister a not-registered chrdev. - Don't return from hptiop_do_ioctl() with the spinlock held. - uninline __hpt_do_ioctl() Update for Arjan van de Ven's comments: - put all asm/ includes after the linux/ ones - replace mdelay with msleep - add pci posting flush - do not set pci command reqister in map_pci_bar - do not try merging sg elements in hptiop_buildsgl() - remove unused outstandingcommands member from hba structure - remove unimplemented hptiop_abort() handler - remove typedef u32 hpt_id_t Other updates: - fix endianess Signed-off-by: HighPoint Linux Team Signed-off-by: James Bottomley --- Documentation/scsi/hptiop.txt | 92 +++ MAINTAINERS | 6 + drivers/scsi/Kconfig | 10 + drivers/scsi/Makefile | 1 + drivers/scsi/hptiop.c | 1501 +++++++++++++++++++++++++++++++++++++++++ drivers/scsi/hptiop.h | 465 +++++++++++++ 6 files changed, 2075 insertions(+) create mode 100644 Documentation/scsi/hptiop.txt create mode 100644 drivers/scsi/hptiop.c create mode 100644 drivers/scsi/hptiop.h diff --git a/Documentation/scsi/hptiop.txt b/Documentation/scsi/hptiop.txt new file mode 100644 index 00000000000..d28a31247d4 --- /dev/null +++ b/Documentation/scsi/hptiop.txt @@ -0,0 +1,92 @@ +HIGHPOINT ROCKETRAID 3xxx RAID DRIVER (hptiop) + +Controller Register Map +------------------------- + +The controller IOP is accessed via PCI BAR0. + + BAR0 offset Register + 0x10 Inbound Message Register 0 + 0x14 Inbound Message Register 1 + 0x18 Outbound Message Register 0 + 0x1C Outbound Message Register 1 + 0x20 Inbound Doorbell Register + 0x24 Inbound Interrupt Status Register + 0x28 Inbound Interrupt Mask Register + 0x30 Outbound Interrupt Status Register + 0x34 Outbound Interrupt Mask Register + 0x40 Inbound Queue Port + 0x44 Outbound Queue Port + + +I/O Request Workflow +---------------------- + +All queued requests are handled via inbound/outbound queue port. +A request packet can be allocated in either IOP or host memory. + +To send a request to the controller: + + - Get a free request packet by reading the inbound queue port or + allocate a free request in host DMA coherent memory. + + The value returned from the inbound queue port is an offset + relative to the IOP BAR0. + + Requests allocated in host memory must be aligned on 32-bytes boundary. + + - Fill the packet. + + - Post the packet to IOP by writing it to inbound queue. For requests + allocated in IOP memory, write the offset to inbound queue port. For + requests allocated in host memory, write (0x80000000|(bus_addr>>5)) + to the inbound queue port. + + - The IOP process the request. When the request is completed, it + will be put into outbound queue. An outbound interrupt will be + generated. + + For requests allocated in IOP memory, the request offset is posted to + outbound queue. + + For requests allocated in host memory, (0x80000000|(bus_addr>>5)) + is posted to the outbound queue. If IOP_REQUEST_FLAG_OUTPUT_CONTEXT + flag is set in the request, the low 32-bit context value will be + posted instead. + + - The host read the outbound queue and complete the request. + + For requests allocated in IOP memory, the host driver free the request + by writing it to the outbound queue. + +Non-queued requests (reset/flush etc) can be sent via inbound message +register 0. An outbound message with the same value indicates the completion +of an inbound message. + + +User-level Interface +--------------------- + +The driver exposes following sysfs attributes: + + NAME R/W Description + driver-version R driver version string + firmware-version R firmware version string + +The driver registers char device "hptiop" to communicate with HighPoint RAID +management software. Its ioctl routine acts as a general binary interface +between the IOP firmware and HighPoint RAID management software. New management +functions can be implemented in application/firmware without modification +in driver code. + + +----------------------------------------------------------------------------- +Copyright (C) 2006 HighPoint Technologies, Inc. All Rights Reserved. + + This file is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + linux@highpoint-tech.com + http://www.highpoint-tech.com diff --git a/MAINTAINERS b/MAINTAINERS index 6d3c401ccdb..db647bf8830 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1117,6 +1117,12 @@ L: linux-hams@vger.kernel.org W: http://www.nt.tuwien.ac.at/~kkudielk/Linux/ S: Maintained +HIGHPOINT ROCKETRAID 3xxx RAID DRIVER +P: HighPoint Linux Team +M: linux@highpoint-tech.com +W: http://www.highpoint-tech.com +S: Supported + HIPPI P: Jes Sorensen M: jes@trained-monkey.org diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 3e7302692db..13ad88a064b 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -530,6 +530,16 @@ config SCSI_PDC_ADMA If unsure, say N. +config SCSI_HPTIOP + tristate "HighPoint RocketRAID 3xxx Controller support" + depends on SCSI && PCI + help + This option enables support for HighPoint RocketRAID 3xxx + controllers. + + To compile this driver as a module, choose M here; the module + will be called hptiop. If unsure, say N. + config SCSI_SATA_QSTOR tristate "Pacific Digital SATA QStor support" depends on SCSI_SATA && PCI diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 3ce80ab4824..9ae4361e352 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -136,6 +136,7 @@ obj-$(CONFIG_SCSI_SATA_NV) += libata.o sata_nv.o obj-$(CONFIG_SCSI_SATA_ULI) += libata.o sata_uli.o obj-$(CONFIG_SCSI_SATA_MV) += libata.o sata_mv.o obj-$(CONFIG_SCSI_PDC_ADMA) += libata.o pdc_adma.o +obj-$(CONFIG_SCSI_HPTIOP) += hptiop.o obj-$(CONFIG_ARM) += arm/ diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c new file mode 100644 index 00000000000..8302f3ba31c --- /dev/null +++ b/drivers/scsi/hptiop.c @@ -0,0 +1,1501 @@ +/* + * HighPoint RR3xxx controller driver for Linux + * Copyright (C) 2006 HighPoint Technologies, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Please report bugs/comments/suggestions to linux@highpoint-tech.com + * + * For more information, visit http://www.highpoint-tech.com + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hptiop.h" + +MODULE_AUTHOR("HighPoint Technologies, Inc."); +MODULE_DESCRIPTION("HighPoint RocketRAID 3xxx SATA Controller Driver"); + +static char driver_name[] = "hptiop"; +static const char driver_name_long[] = "RocketRAID 3xxx SATA Controller driver"; +static const char driver_ver[] = "v1.0 (060426)"; + +static DEFINE_SPINLOCK(hptiop_hba_list_lock); +static LIST_HEAD(hptiop_hba_list); +static int hptiop_cdev_major = -1; + +static void hptiop_host_request_callback(struct hptiop_hba *hba, u32 tag); +static void hptiop_iop_request_callback(struct hptiop_hba *hba, u32 tag); +static void hptiop_message_callback(struct hptiop_hba *hba, u32 msg); + +static inline void hptiop_pci_posting_flush(struct hpt_iopmu __iomem *iop) +{ + readl(&iop->outbound_intstatus); +} + +static int iop_wait_ready(struct hpt_iopmu __iomem *iop, u32 millisec) +{ + u32 req = 0; + int i; + + for (i = 0; i < millisec; i++) { + req = readl(&iop->inbound_queue); + if (req != IOPMU_QUEUE_EMPTY) + break; + msleep(1); + } + + if (req != IOPMU_QUEUE_EMPTY) { + writel(req, &iop->outbound_queue); + hptiop_pci_posting_flush(iop); + return 0; + } + + return -1; +} + +static void hptiop_request_callback(struct hptiop_hba *hba, u32 tag) +{ + if ((tag & IOPMU_QUEUE_MASK_HOST_BITS) == IOPMU_QUEUE_ADDR_HOST_BIT) + return hptiop_host_request_callback(hba, + tag & ~IOPMU_QUEUE_ADDR_HOST_BIT); + else + return hptiop_iop_request_callback(hba, tag); +} + +static inline void hptiop_drain_outbound_queue(struct hptiop_hba *hba) +{ + u32 req; + + while ((req = readl(&hba->iop->outbound_queue)) != IOPMU_QUEUE_EMPTY) { + + if (req & IOPMU_QUEUE_MASK_HOST_BITS) + hptiop_request_callback(hba, req); + else { + struct hpt_iop_request_header __iomem * p; + + p = (struct hpt_iop_request_header __iomem *) + ((char __iomem *)hba->iop + req); + + if (readl(&p->flags) & IOP_REQUEST_FLAG_SYNC_REQUEST) { + if (readl(&p->context)) + hptiop_request_callback(hba, req); + else + writel(1, &p->context); + } + else + hptiop_request_callback(hba, req); + } + } +} + +static int __iop_intr(struct hptiop_hba *hba) +{ + struct hpt_iopmu __iomem *iop = hba->iop; + u32 status; + int ret = 0; + + status = readl(&iop->outbound_intstatus); + + if (status & IOPMU_OUTBOUND_INT_MSG0) { + u32 msg = readl(&iop->outbound_msgaddr0); + dprintk("received outbound msg %x\n", msg); + writel(IOPMU_OUTBOUND_INT_MSG0, &iop->outbound_intstatus); + hptiop_message_callback(hba, msg); + ret = 1; + } + + if (status & IOPMU_OUTBOUND_INT_POSTQUEUE) { + hptiop_drain_outbound_queue(hba); + ret = 1; + } + + return ret; +} + +static int iop_send_sync_request(struct hptiop_hba *hba, + void __iomem *_req, u32 millisec) +{ + struct hpt_iop_request_header __iomem *req = _req; + u32 i; + + writel(readl(&req->flags) | IOP_REQUEST_FLAG_SYNC_REQUEST, + &req->flags); + + writel(0, &req->context); + + writel((unsigned long)req - (unsigned long)hba->iop, + &hba->iop->inbound_queue); + + hptiop_pci_posting_flush(hba->iop); + + for (i = 0; i < millisec; i++) { + __iop_intr(hba); + if (readl(&req->context)) + return 0; + msleep(1); + } + + return -1; +} + +static int iop_send_sync_msg(struct hptiop_hba *hba, u32 msg, u32 millisec) +{ + u32 i; + + hba->msg_done = 0; + + writel(msg, &hba->iop->inbound_msgaddr0); + + hptiop_pci_posting_flush(hba->iop); + + for (i = 0; i < millisec; i++) { + spin_lock_irq(hba->host->host_lock); + __iop_intr(hba); + spin_unlock_irq(hba->host->host_lock); + if (hba->msg_done) + break; + msleep(1); + } + + return hba->msg_done? 0 : -1; +} + +static int iop_get_config(struct hptiop_hba *hba, + struct hpt_iop_request_get_config *config) +{ + u32 req32; + struct hpt_iop_request_get_config __iomem *req; + + req32 = readl(&hba->iop->inbound_queue); + if (req32 == IOPMU_QUEUE_EMPTY) + return -1; + + req = (struct hpt_iop_request_get_config __iomem *) + ((unsigned long)hba->iop + req32); + + writel(0, &req->header.flags); + writel(IOP_REQUEST_TYPE_GET_CONFIG, &req->header.type); + writel(sizeof(struct hpt_iop_request_get_config), &req->header.size); + writel(IOP_RESULT_PENDING, &req->header.result); + + if (iop_send_sync_request(hba, req, 20000)) { + dprintk("Get config send cmd failed\n"); + return -1; + } + + memcpy_fromio(config, req, sizeof(*config)); + writel(req32, &hba->iop->outbound_queue); + return 0; +} + +static int iop_set_config(struct hptiop_hba *hba, + struct hpt_iop_request_set_config *config) +{ + u32 req32; + struct hpt_iop_request_set_config __iomem *req; + + req32 = readl(&hba->iop->inbound_queue); + if (req32 == IOPMU_QUEUE_EMPTY) + return -1; + + req = (struct hpt_iop_request_set_config __iomem *) + ((unsigned long)hba->iop + req32); + + memcpy_toio((u8 __iomem *)req + sizeof(struct hpt_iop_request_header), + (u8 *)config + sizeof(struct hpt_iop_request_header), + sizeof(struct hpt_iop_request_set_config) - + sizeof(struct hpt_iop_request_header)); + + writel(0, &req->header.flags); + writel(IOP_REQUEST_TYPE_SET_CONFIG, &req->header.type); + writel(sizeof(struct hpt_iop_request_set_config), &req->header.size); + writel(IOP_RESULT_PENDING, &req->header.result); + + if (iop_send_sync_request(hba, req, 20000)) { + dprintk("Set config send cmd failed\n"); + return -1; + } + + writel(req32, &hba->iop->outbound_queue); + return 0; +} + +static int hptiop_initialize_iop(struct hptiop_hba *hba) +{ + struct hpt_iopmu __iomem *iop = hba->iop; + + /* enable interrupts */ + writel(~(IOPMU_OUTBOUND_INT_POSTQUEUE | IOPMU_OUTBOUND_INT_MSG0), + &iop->outbound_intmask); + + hba->initialized = 1; + + /* start background tasks */ + if (iop_send_sync_msg(hba, + IOPMU_INBOUND_MSG0_START_BACKGROUND_TASK, 5000)) { + printk(KERN_ERR "scsi%d: fail to start background task\n", + hba->host->host_no); + return -1; + } + return 0; +} + +static int hptiop_map_pci_bar(struct hptiop_hba *hba) +{ + u32 mem_base_phy, length; + void __iomem *mem_base_virt; + struct pci_dev *pcidev = hba->pcidev; + + if (!(pci_resource_flags(pcidev, 0) & IORESOURCE_MEM)) { + printk(KERN_ERR "scsi%d: pci resource invalid\n", + hba->host->host_no); + return -1; + } + + mem_base_phy = pci_resource_start(pcidev, 0); + length = pci_resource_len(pcidev, 0); + mem_base_virt = ioremap(mem_base_phy, length); + + if (!mem_base_virt) { + printk(KERN_ERR "scsi%d: Fail to ioremap memory space\n", + hba->host->host_no); + return -1; + } + + hba->iop = mem_base_virt; + dprintk("hptiop_map_pci_bar: iop=%p\n", hba->iop); + return 0; +} + +static void hptiop_message_callback(struct hptiop_hba *hba, u32 msg) +{ + dprintk("iop message 0x%x\n", msg); + + if (!hba->initialized) + return; + + if (msg == IOPMU_INBOUND_MSG0_RESET) { + atomic_set(&hba->resetting, 0); + wake_up(&hba->reset_wq); + } + else if (msg <= IOPMU_INBOUND_MSG0_MAX) + hba->msg_done = 1; +} + +static inline struct hptiop_request *get_req(struct hptiop_hba *hba) +{ + struct hptiop_request *ret; + + dprintk("get_req : req=%p\n", hba->req_list); + + ret = hba->req_list; + if (ret) + hba->req_list = ret->next; + + return ret; +} + +static inline void free_req(struct hptiop_hba *hba, struct hptiop_request *req) +{ + dprintk("free_req(%d, %p)\n", req->index, req); + req->next = hba->req_list; + hba->req_list = req; +} + +static void hptiop_host_request_callback(struct hptiop_hba *hba, u32 tag) +{ + struct hpt_iop_request_scsi_command *req; + struct scsi_cmnd *scp; + + req = (struct hpt_iop_request_scsi_command *)hba->reqs[tag].req_virt; + dprintk("hptiop_host_request_callback: req=%p, type=%d, " + "result=%d, context=0x%x tag=%d\n", + req, req->header.type, req->header.result, + req->header.context, tag); + + BUG_ON(!req->header.result); + BUG_ON(req->header.type != cpu_to_le32(IOP_REQUEST_TYPE_SCSI_COMMAND)); + + scp = hba->reqs[tag].scp; + + if (HPT_SCP(scp)->mapped) { + if (scp->use_sg) + pci_unmap_sg(hba->pcidev, + (struct scatterlist *)scp->request_buffer, + scp->use_sg, + scp->sc_data_direction + ); + else + pci_unmap_single(hba->pcidev, + HPT_SCP(scp)->dma_handle, + scp->request_bufflen, + scp->sc_data_direction + ); + } + + switch (le32_to_cpu(req->header.result)) { + case IOP_RESULT_SUCCESS: + scp->result = (DID_OK<<16); + break; + case IOP_RESULT_BAD_TARGET: + scp->result = (DID_BAD_TARGET<<16); + break; + case IOP_RESULT_BUSY: + scp->result = (DID_BUS_BUSY<<16); + break; + case IOP_RESULT_RESET: + scp->result = (DID_RESET<<16); + break; + case IOP_RESULT_FAIL: + scp->result = (DID_ERROR<<16); + break; + case IOP_RESULT_INVALID_REQUEST: + scp->result = (DID_ABORT<<16); + break; + case IOP_RESULT_MODE_SENSE_CHECK_CONDITION: + scp->result = SAM_STAT_CHECK_CONDITION; + memset(&scp->sense_buffer, + 0, sizeof(scp->sense_buffer)); + memcpy(&scp->sense_buffer, + &req->sg_list, le32_to_cpu(req->dataxfer_length)); + break; + + default: + scp->result = ((DRIVER_INVALID|SUGGEST_ABORT)<<24) | + (DID_ABORT<<16); + break; + } + + dprintk("scsi_done(%p)\n", scp); + scp->scsi_done(scp); + free_req(hba, &hba->reqs[tag]); +} + +void hptiop_iop_request_callback(struct hptiop_hba *hba, u32 tag) +{ + struct hpt_iop_request_header __iomem *req; + struct hpt_iop_request_ioctl_command __iomem *p; + struct hpt_ioctl_k *arg; + + req = (struct hpt_iop_request_header __iomem *) + ((unsigned long)hba->iop + tag); + dprintk("hptiop_iop_request_callback: req=%p, type=%d, " + "result=%d, context=0x%x tag=%d\n", + req, readl(&req->type), readl(&req->result), + readl(&req->context), tag); + + BUG_ON(!readl(&req->result)); + BUG_ON(readl(&req->type) != IOP_REQUEST_TYPE_IOCTL_COMMAND); + + p = (struct hpt_iop_request_ioctl_command __iomem *)req; + arg = (struct hpt_ioctl_k *)(unsigned long) + (readl(&req->context) | + ((u64)readl(&req->context_hi32)<<32)); + + if (readl(&req->result) == IOP_RESULT_SUCCESS) { + arg->result = HPT_IOCTL_RESULT_OK; + + if (arg->outbuf_size) + memcpy_fromio(arg->outbuf, + &p->buf[(readl(&p->inbuf_size) + 3)& ~3], + arg->outbuf_size); + + if (arg->bytes_returned) + *arg->bytes_returned = arg->outbuf_size; + } + else + arg->result = HPT_IOCTL_RESULT_FAILED; + + arg->done(arg); + writel(tag, &hba->iop->outbound_queue); +} + +static irqreturn_t hptiop_intr(int irq, void *dev_id, struct pt_regs *regs) +{ + struct hptiop_hba *hba = dev_id; + int handled; + unsigned long flags; + + spin_lock_irqsave(hba->host->host_lock, flags); + handled = __iop_intr(hba); + spin_unlock_irqrestore(hba->host->host_lock, flags); + + return handled; +} + +static int hptiop_buildsgl(struct scsi_cmnd *scp, struct hpt_iopsg *psg) +{ + struct Scsi_Host *host = scp->device->host; + struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata; + struct scatterlist *sglist = (struct scatterlist *)scp->request_buffer; + + /* + * though we'll not get non-use_sg fields anymore, + * keep use_sg checking anyway + */ + if (scp->use_sg) { + int idx; + + HPT_SCP(scp)->sgcnt = pci_map_sg(hba->pcidev, + sglist, scp->use_sg, + scp->sc_data_direction); + HPT_SCP(scp)->mapped = 1; + BUG_ON(HPT_SCP(scp)->sgcnt > hba->max_sg_descriptors); + + for (idx = 0; idx < HPT_SCP(scp)->sgcnt; idx++) { + psg[idx].pci_address = + cpu_to_le64(sg_dma_address(&sglist[idx])); + psg[idx].size = cpu_to_le32(sg_dma_len(&sglist[idx])); + psg[idx].eot = (idx == HPT_SCP(scp)->sgcnt - 1) ? + cpu_to_le32(1) : 0; + } + + return HPT_SCP(scp)->sgcnt; + } else { + HPT_SCP(scp)->dma_handle = pci_map_single( + hba->pcidev, + scp->request_buffer, + scp->request_bufflen, + scp->sc_data_direction + ); + HPT_SCP(scp)->mapped = 1; + psg->pci_address = cpu_to_le64(HPT_SCP(scp)->dma_handle); + psg->size = cpu_to_le32(scp->request_bufflen); + psg->eot = cpu_to_le32(1); + return 1; + } +} + +static int hptiop_queuecommand(struct scsi_cmnd *scp, + void (*done)(struct scsi_cmnd *)) +{ + struct Scsi_Host *host = scp->device->host; + struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata; + struct hpt_iop_request_scsi_command *req; + int sg_count = 0; + struct hptiop_request *_req; + + BUG_ON(!done); + scp->scsi_done = done; + + /* + * hptiop_shutdown will flash controller cache. + */ + if (scp->cmnd[0] == SYNCHRONIZE_CACHE) { + scp->result = DID_OK<<16; + goto cmd_done; + } + + _req = get_req(hba); + if (_req == NULL) { + dprintk("hptiop_queuecmd : no free req\n"); + scp->result = DID_BUS_BUSY << 16; + goto cmd_done; + } + + _req->scp = scp; + + dprintk("hptiop_queuecmd(scp=%p) %d/%d/%d/%d cdb=(%x-%x-%x) " + "req_index=%d, req=%p\n", + scp, + host->host_no, scp->device->channel, + scp->device->id, scp->device->lun, + *((u32 *)&scp->cmnd), + *((u32 *)&scp->cmnd + 1), + *((u32 *)&scp->cmnd + 2), + _req->index, _req->req_virt); + + scp->result = 0; + + if (scp->device->channel || scp->device->lun || + scp->device->id > hba->max_devices) { + scp->result = DID_BAD_TARGET << 16; + free_req(hba, _req); + goto cmd_done; + } + + req = (struct hpt_iop_request_scsi_command *)_req->req_virt; + + /* build S/G table */ + if (scp->request_bufflen) + sg_count = hptiop_buildsgl(scp, req->sg_list); + else + HPT_SCP(scp)->mapped = 0; + + req->header.flags = cpu_to_le32(IOP_REQUEST_FLAG_OUTPUT_CONTEXT); + req->header.type = cpu_to_le32(IOP_REQUEST_TYPE_SCSI_COMMAND); + req->header.result = cpu_to_le32(IOP_RESULT_PENDING); + req->header.context = cpu_to_le32(IOPMU_QUEUE_ADDR_HOST_BIT | + (u32)_req->index); + req->header.context_hi32 = 0; + req->dataxfer_length = cpu_to_le32(scp->bufflen); + req->channel = scp->device->channel; + req->target = scp->device->id; + req->lun = scp->device->lun; + req->header.size = cpu_to_le32( + sizeof(struct hpt_iop_request_scsi_command) + - sizeof(struct hpt_iopsg) + + sg_count * sizeof(struct hpt_iopsg)); + + memcpy(req->cdb, scp->cmnd, sizeof(req->cdb)); + + writel(IOPMU_QUEUE_ADDR_HOST_BIT | _req->req_shifted_phy, + &hba->iop->inbound_queue); + + return 0; + +cmd_done: + dprintk("scsi_done(scp=%p)\n", scp); + scp->scsi_done(scp); + return 0; +} + +static const char *hptiop_info(struct Scsi_Host *host) +{ + return driver_name_long; +} + +static int hptiop_reset_hba(struct hptiop_hba *hba) +{ + if (atomic_xchg(&hba->resetting, 1) == 0) { + atomic_inc(&hba->reset_count); + writel(IOPMU_INBOUND_MSG0_RESET, + &hba->iop->outbound_msgaddr0); + hptiop_pci_posting_flush(hba->iop); + } + + wait_event_timeout(hba->reset_wq, + atomic_read(&hba->resetting) == 0, 60 * HZ); + + if (atomic_read(&hba->resetting)) { + /* IOP is in unkown state, abort reset */ + printk(KERN_ERR "scsi%d: reset failed\n", hba->host->host_no); + return -1; + } + + if (iop_send_sync_msg(hba, + IOPMU_INBOUND_MSG0_START_BACKGROUND_TASK, 5000)) { + dprintk("scsi%d: fail to start background task\n", + hba->host->host_no); + } + + return 0; +} + +static int hptiop_reset(struct scsi_cmnd *scp) +{ + struct Scsi_Host * host = scp->device->host; + struct hptiop_hba * hba = (struct hptiop_hba *)host->hostdata; + + printk(KERN_WARNING "hptiop_reset(%d/%d/%d) scp=%p\n", + scp->device->host->host_no, scp->device->channel, + scp->device->id, scp); + + return hptiop_reset_hba(hba)? FAILED : SUCCESS; +} + +static int hptiop_adjust_disk_queue_depth(struct scsi_device *sdev, + int queue_depth) +{ + if(queue_depth > 256) + queue_depth = 256; + scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth); + return queue_depth; +} + +struct hptiop_getinfo { + char __user *buffer; + loff_t buflength; + loff_t bufoffset; + loff_t buffillen; + loff_t filpos; +}; + +static void hptiop_copy_mem_info(struct hptiop_getinfo *pinfo, + char *data, int datalen) +{ + if (pinfo->filpos < pinfo->bufoffset) { + if (pinfo->filpos + datalen <= pinfo->bufoffset) { + pinfo->filpos += datalen; + return; + } else { + data += (pinfo->bufoffset - pinfo->filpos); + datalen -= (pinfo->bufoffset - pinfo->filpos); + pinfo->filpos = pinfo->bufoffset; + } + } + + pinfo->filpos += datalen; + if (pinfo->buffillen == pinfo->buflength) + return; + + if (pinfo->buflength - pinfo->buffillen < datalen) + datalen = pinfo->buflength - pinfo->buffillen; + + if (copy_to_user(pinfo->buffer + pinfo->buffillen, data, datalen)) + return; + + pinfo->buffillen += datalen; +} + +static int hptiop_copy_info(struct hptiop_getinfo *pinfo, char *fmt, ...) +{ + va_list args; + char buf[128]; + int len; + + va_start(args, fmt); + len = vsnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + hptiop_copy_mem_info(pinfo, buf, len); + return len; +} + +static void hptiop_ioctl_done(struct hpt_ioctl_k *arg) +{ + arg->done = NULL; + wake_up(&arg->hba->ioctl_wq); +} + +static void hptiop_do_ioctl(struct hpt_ioctl_k *arg) +{ + struct hptiop_hba *hba = arg->hba; + u32 val; + struct hpt_iop_request_ioctl_command __iomem *req; + int ioctl_retry = 0; + + dprintk("scsi%d: hptiop_do_ioctl\n", hba->host->host_no); + + /* + * check (in + out) buff size from application. + * outbuf must be dword aligned. + */ + if (((arg->inbuf_size + 3) & ~3) + arg->outbuf_size > + hba->max_request_size + - sizeof(struct hpt_iop_request_header) + - 4 * sizeof(u32)) { + dprintk("scsi%d: ioctl buf size (%d/%d) is too large\n", + hba->host->host_no, + arg->inbuf_size, arg->outbuf_size); + arg->result = HPT_IOCTL_RESULT_FAILED; + return; + } + +retry: + spin_lock_irq(hba->host->host_lock); + + val = readl(&hba->iop->inbound_queue); + if (val == IOPMU_QUEUE_EMPTY) { + spin_unlock_irq(hba->host->host_lock); + dprintk("scsi%d: no free req for ioctl\n", hba->host->host_no); + arg->result = -1; + return; + } + + req = (struct hpt_iop_request_ioctl_command __iomem *) + ((unsigned long)hba->iop + val); + + writel(HPT_CTL_CODE_LINUX_TO_IOP(arg->ioctl_code), + &req->ioctl_code); + writel(arg->inbuf_size, &req->inbuf_size); + writel(arg->outbuf_size, &req->outbuf_size); + + /* + * use the buffer on the IOP local memory first, then copy it + * back to host. + * the caller's request buffer shoudl be little-endian. + */ + if (arg->inbuf_size) + memcpy_toio(req->buf, arg->inbuf, arg->inbuf_size); + + /* correct the controller ID for IOP */ + if ((arg->ioctl_code == HPT_IOCTL_GET_CHANNEL_INFO || + arg->ioctl_code == HPT_IOCTL_GET_CONTROLLER_INFO_V2 || + arg->ioctl_code == HPT_IOCTL_GET_CONTROLLER_INFO) + && arg->inbuf_size >= sizeof(u32)) + writel(0, req->buf); + + writel(IOP_REQUEST_TYPE_IOCTL_COMMAND, &req->header.type); + writel(0, &req->header.flags); + writel(offsetof(struct hpt_iop_request_ioctl_command, buf) + + arg->inbuf_size, &req->header.size); + writel((u32)(unsigned long)arg, &req->header.context); + writel(BITS_PER_LONG > 32 ? (u32)((unsigned long)arg>>32) : 0, + &req->header.context_hi32); + writel(IOP_RESULT_PENDING, &req->header.result); + + arg->result = HPT_IOCTL_RESULT_FAILED; + arg->done = hptiop_ioctl_done; + + writel(val, &hba->iop->inbound_queue); + hptiop_pci_posting_flush(hba->iop); + + spin_unlock_irq(hba->host->host_lock); + + wait_event_timeout(hba->ioctl_wq, arg->done == NULL, 60 * HZ); + + if (arg->done != NULL) { + hptiop_reset_hba(hba); + if (ioctl_retry++ < 3) + goto retry; + } + + dprintk("hpt_iop_ioctl %x result %d\n", + arg->ioctl_code, arg->result); +} + +static int __hpt_do_ioctl(struct hptiop_hba *hba, u32 code, void *inbuf, + u32 insize, void *outbuf, u32 outsize) +{ + struct hpt_ioctl_k arg; + arg.hba = hba; + arg.ioctl_code = code; + arg.inbuf = inbuf; + arg.outbuf = outbuf; + arg.inbuf_size = insize; + arg.outbuf_size = outsize; + arg.bytes_returned = NULL; + hptiop_do_ioctl(&arg); + return arg.result; +} + +static inline int hpt_id_valid(__le32 id) +{ + return id != 0 && id != cpu_to_le32(0xffffffff); +} + +static int hptiop_get_controller_info(struct hptiop_hba *hba, + struct hpt_controller_info *pinfo) +{ + int id = 0; + + return __hpt_do_ioctl(hba, HPT_IOCTL_GET_CONTROLLER_INFO, + &id, sizeof(int), pinfo, sizeof(*pinfo)); +} + + +static int hptiop_get_channel_info(struct hptiop_hba *hba, int bus, + struct hpt_channel_info *pinfo) +{ + u32 ids[2]; + + ids[0] = 0; + ids[1] = bus; + return __hpt_do_ioctl(hba, HPT_IOCTL_GET_CHANNEL_INFO, + ids, sizeof(ids), pinfo, sizeof(*pinfo)); + +} + +static int hptiop_get_logical_devices(struct hptiop_hba *hba, + __le32 *pids, int maxcount) +{ + int i; + u32 count = maxcount - 1; + + if (__hpt_do_ioctl(hba, HPT_IOCTL_GET_LOGICAL_DEVICES, + &count, sizeof(u32), + pids, sizeof(u32) * maxcount)) + return -1; + + maxcount = le32_to_cpu(pids[0]); + for (i = 0; i < maxcount; i++) + pids[i] = pids[i+1]; + + return maxcount; +} + +static int hptiop_get_device_info_v3(struct hptiop_hba *hba, __le32 id, + struct hpt_logical_device_info_v3 *pinfo) +{ + return __hpt_do_ioctl(hba, HPT_IOCTL_GET_DEVICE_INFO_V3, + &id, sizeof(u32), + pinfo, sizeof(*pinfo)); +} + +static const char *get_array_status(struct hpt_logical_device_info_v3 *devinfo) +{ + static char s[64]; + u32 flags = le32_to_cpu(devinfo->u.array.flags); + u32 trans_prog = le32_to_cpu(devinfo->u.array.transforming_progress); + u32 reb_prog = le32_to_cpu(devinfo->u.array.rebuilding_progress); + + if (flags & ARRAY_FLAG_DISABLED) + return "Disabled"; + else if (flags & ARRAY_FLAG_TRANSFORMING) + sprintf(s, "Expanding/Migrating %d.%d%%%s%s", + trans_prog / 100, + trans_prog % 100, + (flags & (ARRAY_FLAG_NEEDBUILDING|ARRAY_FLAG_BROKEN))? + ", Critical" : "", + ((flags & ARRAY_FLAG_NEEDINITIALIZING) && + !(flags & ARRAY_FLAG_REBUILDING) && + !(flags & ARRAY_FLAG_INITIALIZING))? + ", Unintialized" : ""); + else if ((flags & ARRAY_FLAG_BROKEN) && + devinfo->u.array.array_type != AT_RAID6) + return "Critical"; + else if (flags & ARRAY_FLAG_REBUILDING) + sprintf(s, + (flags & ARRAY_FLAG_NEEDINITIALIZING)? + "%sBackground initializing %d.%d%%" : + "%sRebuilding %d.%d%%", + (flags & ARRAY_FLAG_BROKEN)? "Critical, " : "", + reb_prog / 100, + reb_prog % 100); + else if (flags & ARRAY_FLAG_VERIFYING) + sprintf(s, "%sVerifying %d.%d%%", + (flags & ARRAY_FLAG_BROKEN)? "Critical, " : "", + reb_prog / 100, + reb_prog % 100); + else if (flags & ARRAY_FLAG_INITIALIZING) + sprintf(s, "%sForground initializing %d.%d%%", + (flags & ARRAY_FLAG_BROKEN)? "Critical, " : "", + reb_prog / 100, + reb_prog % 100); + else if (flags & ARRAY_FLAG_NEEDTRANSFORM) + sprintf(s,"%s%s%s", "Need Expanding/Migrating", + (flags & ARRAY_FLAG_BROKEN)? "Critical, " : "", + ((flags & ARRAY_FLAG_NEEDINITIALIZING) && + !(flags & ARRAY_FLAG_REBUILDING) && + !(flags & ARRAY_FLAG_INITIALIZING))? + ", Unintialized" : ""); + else if (flags & ARRAY_FLAG_NEEDINITIALIZING && + !(flags & ARRAY_FLAG_REBUILDING) && + !(flags & ARRAY_FLAG_INITIALIZING)) + sprintf(s,"%sUninitialized", + (flags & ARRAY_FLAG_BROKEN)? "Critical, " : ""); + else if ((flags & ARRAY_FLAG_NEEDBUILDING) || + (flags & ARRAY_FLAG_BROKEN)) + return "Critical"; + else + return "Normal"; + return s; +} + +static void hptiop_dump_devinfo(struct hptiop_hba *hba, + struct hptiop_getinfo *pinfo, __le32 id, int indent) +{ + struct hpt_logical_device_info_v3 devinfo; + int i; + u64 capacity; + + for (i = 0; i < indent; i++) + hptiop_copy_info(pinfo, "\t"); + + if (hptiop_get_device_info_v3(hba, id, &devinfo)) { + hptiop_copy_info(pinfo, "unknown\n"); + return; + } + + switch (devinfo.type) { + + case LDT_DEVICE: { + struct hd_driveid *driveid; + u32 flags = le32_to_cpu(devinfo.u.device.flags); + + driveid = (struct hd_driveid *)devinfo.u.device.ident; + /* model[] is 40 chars long, but we just want 20 chars here */ + driveid->model[20] = 0; + + if (indent) + if (flags & DEVICE_FLAG_DISABLED) + hptiop_copy_info(pinfo,"Missing\n"); + else + hptiop_copy_info(pinfo, "CH%d %s\n", + devinfo.u.device.path_id + 1, + driveid->model); + else { + capacity = le64_to_cpu(devinfo.capacity) * 512; + do_div(capacity, 1000000); + hptiop_copy_info(pinfo, + "CH%d %s, %lluMB, %s %s%s%s%s\n", + devinfo.u.device.path_id + 1, + driveid->model, + capacity, + (flags & DEVICE_FLAG_DISABLED)? + "Disabled" : "Normal", + devinfo.u.device.read_ahead_enabled? + "[RA]" : "", + devinfo.u.device.write_cache_enabled? + "[WC]" : "", + devinfo.u.device.TCQ_enabled? + "[TCQ]" : "", + devinfo.u.device.NCQ_enabled? + "[NCQ]" : "" + ); + } + break; + } + + case LDT_ARRAY: + if (devinfo.target_id != INVALID_TARGET_ID) + hptiop_copy_info(pinfo, "[DISK %d_%d] ", + devinfo.vbus_id, devinfo.target_id); + + capacity = le64_to_cpu(devinfo.capacity) * 512; + do_div(capacity, 1000000); + hptiop_copy_info(pinfo, "%s (%s), %lluMB, %s\n", + devinfo.u.array.name, + devinfo.u.array.array_type==AT_RAID0? "RAID0" : + devinfo.u.array.array_type==AT_RAID1? "RAID1" : + devinfo.u.array.array_type==AT_RAID5? "RAID5" : + devinfo.u.array.array_type==AT_RAID6? "RAID6" : + devinfo.u.array.array_type==AT_JBOD? "JBOD" : + "unknown", + capacity, + get_array_status(&devinfo)); + for (i = 0; i < devinfo.u.array.ndisk; i++) { + if (hpt_id_valid(devinfo.u.array.members[i])) { + if (cpu_to_le16(1<private_data; + struct hptiop_getinfo info; + int i, j, ndev; + struct hpt_controller_info con_info; + struct hpt_channel_info chan_info; + __le32 ids[32]; + + info.buffer = buf; + info.buflength = count; + info.bufoffset = ppos ? *ppos : 0; + info.filpos = 0; + info.buffillen = 0; + + if (hptiop_get_controller_info(hba, &con_info)) + return -EIO; + + for (i = 0; i < con_info.num_buses; i++) { + if (hptiop_get_channel_info(hba, i, &chan_info) == 0) { + if (hpt_id_valid(chan_info.devices[0])) + hptiop_dump_devinfo(hba, &info, + chan_info.devices[0], 0); + if (hpt_id_valid(chan_info.devices[1])) + hptiop_dump_devinfo(hba, &info, + chan_info.devices[1], 0); + } + } + + ndev = hptiop_get_logical_devices(hba, ids, + sizeof(ids) / sizeof(ids[0])); + + /* + * if hptiop_get_logical_devices fails, ndev==-1 and it just + * output nothing here + */ + for (j = 0; j < ndev; j++) + hptiop_dump_devinfo(hba, &info, ids[j], 0); + + if (ppos) + *ppos += info.buffillen; + + return info.buffillen; +} + +static int hptiop_cdev_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct hptiop_hba *hba = file->private_data; + struct hpt_ioctl_u ioctl_u; + struct hpt_ioctl_k ioctl_k; + u32 bytes_returned; + int err = -EINVAL; + + if (copy_from_user(&ioctl_u, + (void __user *)arg, sizeof(struct hpt_ioctl_u))) + return -EINVAL; + + if (ioctl_u.magic != HPT_IOCTL_MAGIC) + return -EINVAL; + + ioctl_k.ioctl_code = ioctl_u.ioctl_code; + ioctl_k.inbuf = NULL; + ioctl_k.inbuf_size = ioctl_u.inbuf_size; + ioctl_k.outbuf = NULL; + ioctl_k.outbuf_size = ioctl_u.outbuf_size; + ioctl_k.hba = hba; + ioctl_k.bytes_returned = &bytes_returned; + + /* verify user buffer */ + if ((ioctl_k.inbuf_size && !access_ok(VERIFY_READ, + ioctl_u.inbuf, ioctl_k.inbuf_size)) || + (ioctl_k.outbuf_size && !access_ok(VERIFY_WRITE, + ioctl_u.outbuf, ioctl_k.outbuf_size)) || + (ioctl_u.bytes_returned && !access_ok(VERIFY_WRITE, + ioctl_u.bytes_returned, sizeof(u32))) || + ioctl_k.inbuf_size + ioctl_k.outbuf_size > 0x10000) { + + dprintk("scsi%d: got bad user address\n", hba->host->host_no); + return -EINVAL; + } + + /* map buffer to kernel. */ + if (ioctl_k.inbuf_size) { + ioctl_k.inbuf = kmalloc(ioctl_k.inbuf_size, GFP_KERNEL); + if (!ioctl_k.inbuf) { + dprintk("scsi%d: fail to alloc inbuf\n", + hba->host->host_no); + err = -ENOMEM; + goto err_exit; + } + + if (copy_from_user(ioctl_k.inbuf, + ioctl_u.inbuf, ioctl_k.inbuf_size)) { + goto err_exit; + } + } + + if (ioctl_k.outbuf_size) { + ioctl_k.outbuf = kmalloc(ioctl_k.outbuf_size, GFP_KERNEL); + if (!ioctl_k.outbuf) { + dprintk("scsi%d: fail to alloc outbuf\n", + hba->host->host_no); + err = -ENOMEM; + goto err_exit; + } + } + + hptiop_do_ioctl(&ioctl_k); + + if (ioctl_k.result == HPT_IOCTL_RESULT_OK) { + if (ioctl_k.outbuf_size && + copy_to_user(ioctl_u.outbuf, + ioctl_k.outbuf, ioctl_k.outbuf_size)) + goto err_exit; + + if (ioctl_u.bytes_returned && + copy_to_user(ioctl_u.bytes_returned, + &bytes_returned, sizeof(u32))) + goto err_exit; + + err = 0; + } + +err_exit: + kfree(ioctl_k.inbuf); + kfree(ioctl_k.outbuf); + + return err; +} + +static int hptiop_cdev_open(struct inode *inode, struct file *file) +{ + struct hptiop_hba *hba; + unsigned i = 0, minor = iminor(inode); + int ret = -ENODEV; + + spin_lock(&hptiop_hba_list_lock); + list_for_each_entry(hba, &hptiop_hba_list, link) { + if (i == minor) { + file->private_data = hba; + ret = 0; + goto out; + } + i++; + } + +out: + spin_unlock(&hptiop_hba_list_lock); + return ret; +} + +static struct file_operations hptiop_cdev_fops = { + .owner = THIS_MODULE, + .read = hptiop_cdev_read, + .ioctl = hptiop_cdev_ioctl, + .open = hptiop_cdev_open, +}; + +static ssize_t hptiop_show_fw_version(struct class_device *class_dev, char *buf) +{ + struct Scsi_Host *host = class_to_shost(class_dev); + struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata; + + return snprintf(buf, PAGE_SIZE, "%d.%d.%d.%d\n", + hba->firmware_version >> 24, + (hba->firmware_version >> 16) & 0xff, + (hba->firmware_version >> 8) & 0xff, + hba->firmware_version & 0xff); +} + +static struct class_device_attribute hptiop_attr_version = { + .attr = { + .name = "driver-version", + .mode = S_IRUGO, + }, + .show = hptiop_show_version, +}; + +static struct class_device_attribute hptiop_attr_fw_version = { + .attr = { + .name = "firmware-version", + .mode = S_IRUGO, + }, + .show = hptiop_show_fw_version, +}; + +static struct class_device_attribute *hptiop_attrs[] = { + &hptiop_attr_version, + &hptiop_attr_fw_version, + NULL +}; + +static struct scsi_host_template driver_template = { + .module = THIS_MODULE, + .name = driver_name, + .queuecommand = hptiop_queuecommand, + .eh_device_reset_handler = hptiop_reset, + .eh_bus_reset_handler = hptiop_reset, + .info = hptiop_info, + .unchecked_isa_dma = 0, + .emulated = 0, + .use_clustering = ENABLE_CLUSTERING, + .proc_name = driver_name, + .shost_attrs = hptiop_attrs, + .this_id = -1, + .change_queue_depth = hptiop_adjust_disk_queue_depth, +}; + +static int __devinit hptiop_probe(struct pci_dev *pcidev, + const struct pci_device_id *id) +{ + struct Scsi_Host *host = NULL; + struct hptiop_hba *hba; + struct hpt_iop_request_get_config iop_config; + struct hpt_iop_request_set_config set_config; + dma_addr_t start_phy; + void *start_virt; + u32 offset, i, req_size; + + dprintk("hptiop_probe(%p)\n", pcidev); + + if (pci_enable_device(pcidev)) { + printk(KERN_ERR "hptiop: fail to enable pci device\n"); + return -ENODEV; + } + + printk(KERN_INFO "adapter at PCI %d:%d:%d, IRQ %d\n", + pcidev->bus->number, pcidev->devfn >> 3, pcidev->devfn & 7, + pcidev->irq); + + pci_set_master(pcidev); + + /* Enable 64bit DMA if possible */ + if (pci_set_dma_mask(pcidev, DMA_64BIT_MASK)) { + if (pci_set_dma_mask(pcidev, DMA_32BIT_MASK)) { + printk(KERN_ERR "hptiop: fail to set dma_mask\n"); + goto disable_pci_device; + } + } + + if (pci_request_regions(pcidev, driver_name)) { + printk(KERN_ERR "hptiop: pci_request_regions failed\n"); + goto disable_pci_device; + } + + host = scsi_host_alloc(&driver_template, sizeof(struct hptiop_hba)); + if (!host) { + printk(KERN_ERR "hptiop: fail to alloc scsi host\n"); + goto free_pci_regions; + } + + hba = (struct hptiop_hba *)host->hostdata; + + hba->pcidev = pcidev; + hba->host = host; + hba->initialized = 0; + + atomic_set(&hba->resetting, 0); + atomic_set(&hba->reset_count, 0); + + init_waitqueue_head(&hba->reset_wq); + init_waitqueue_head(&hba->ioctl_wq); + + host->max_lun = 1; + host->max_channel = 0; + host->io_port = 0; + host->n_io_port = 0; + host->irq = pcidev->irq; + + if (hptiop_map_pci_bar(hba)) + goto free_scsi_host; + + if (iop_wait_ready(hba->iop, 20000)) { + printk(KERN_ERR "scsi%d: firmware not ready\n", + hba->host->host_no); + goto unmap_pci_bar; + } + + if (iop_get_config(hba, &iop_config)) { + printk(KERN_ERR "scsi%d: get config failed\n", + hba->host->host_no); + goto unmap_pci_bar; + } + + hba->max_requests = min(le32_to_cpu(iop_config.max_requests), + HPTIOP_MAX_REQUESTS); + hba->max_devices = le32_to_cpu(iop_config.max_devices); + hba->max_request_size = le32_to_cpu(iop_config.request_size); + hba->max_sg_descriptors = le32_to_cpu(iop_config.max_sg_count); + hba->firmware_version = le32_to_cpu(iop_config.firmware_version); + hba->sdram_size = le32_to_cpu(iop_config.sdram_size); + + host->max_sectors = le32_to_cpu(iop_config.data_transfer_length) >> 9; + host->max_id = le32_to_cpu(iop_config.max_devices); + host->sg_tablesize = le32_to_cpu(iop_config.max_sg_count); + host->can_queue = le32_to_cpu(iop_config.max_requests); + host->cmd_per_lun = le32_to_cpu(iop_config.max_requests); + host->max_cmd_len = 16; + + set_config.vbus_id = cpu_to_le32(host->host_no); + set_config.iop_id = cpu_to_le32(host->host_no); + + if (iop_set_config(hba, &set_config)) { + printk(KERN_ERR "scsi%d: set config failed\n", + hba->host->host_no); + goto unmap_pci_bar; + } + + if (scsi_add_host(host, &pcidev->dev)) { + printk(KERN_ERR "scsi%d: scsi_add_host failed\n", + hba->host->host_no); + goto unmap_pci_bar; + } + + pci_set_drvdata(pcidev, host); + + if (request_irq(pcidev->irq, hptiop_intr, SA_SHIRQ, + driver_name, hba)) { + printk(KERN_ERR "scsi%d: request irq %d failed\n", + hba->host->host_no, pcidev->irq); + goto remove_scsi_host; + } + + /* Allocate request mem */ + req_size = sizeof(struct hpt_iop_request_scsi_command) + + sizeof(struct hpt_iopsg) * (hba->max_sg_descriptors - 1); + if ((req_size& 0x1f) != 0) + req_size = (req_size + 0x1f) & ~0x1f; + + dprintk("req_size=%d, max_requests=%d\n", req_size, hba->max_requests); + + hba->req_size = req_size; + start_virt = dma_alloc_coherent(&pcidev->dev, + hba->req_size*hba->max_requests + 0x20, + &start_phy, GFP_KERNEL); + + if (!start_virt) { + printk(KERN_ERR "scsi%d: fail to alloc request mem\n", + hba->host->host_no); + goto free_request_irq; + } + + hba->dma_coherent = start_virt; + hba->dma_coherent_handle = start_phy; + + if ((start_phy & 0x1f) != 0) + { + offset = ((start_phy + 0x1f) & ~0x1f) - start_phy; + start_phy += offset; + start_virt += offset; + } + + hba->req_list = start_virt; + for (i = 0; i < hba->max_requests; i++) { + hba->reqs[i].next = NULL; + hba->reqs[i].req_virt = start_virt; + hba->reqs[i].req_shifted_phy = start_phy >> 5; + hba->reqs[i].index = i; + free_req(hba, &hba->reqs[i]); + start_virt = (char *)start_virt + hba->req_size; + start_phy = start_phy + hba->req_size; + } + + /* Enable Interrupt and start background task */ + if (hptiop_initialize_iop(hba)) + goto free_request_mem; + + spin_lock(&hptiop_hba_list_lock); + list_add_tail(&hba->link, &hptiop_hba_list); + spin_unlock(&hptiop_hba_list_lock); + + scsi_scan_host(host); + + dprintk("scsi%d: hptiop_probe successfully\n", hba->host->host_no); + return 0; + +free_request_mem: + dma_free_coherent(&hba->pcidev->dev, + hba->req_size*hba->max_requests + 0x20, + hba->dma_coherent, hba->dma_coherent_handle); + +free_request_irq: + free_irq(hba->pcidev->irq, hba); + +remove_scsi_host: + scsi_remove_host(host); + +unmap_pci_bar: + iounmap(hba->iop); + +free_pci_regions: + pci_release_regions(pcidev) ; + +free_scsi_host: + scsi_host_put(host); + +disable_pci_device: + pci_disable_device(pcidev); + + dprintk("scsi%d: hptiop_probe fail\n", host->host_no); + return -ENODEV; +} + +static void hptiop_shutdown(struct pci_dev *pcidev) +{ + struct Scsi_Host *host = pci_get_drvdata(pcidev); + struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata; + struct hpt_iopmu __iomem *iop = hba->iop; + u32 int_mask; + + dprintk("hptiop_shutdown(%p)\n", hba); + + /* stop the iop */ + if (iop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_SHUTDOWN, 60000)) + printk(KERN_ERR "scsi%d: shutdown the iop timeout\n", + hba->host->host_no); + + /* disable all outbound interrupts */ + int_mask = readl(&iop->outbound_intmask); + writel(int_mask | + IOPMU_OUTBOUND_INT_MSG0 | IOPMU_OUTBOUND_INT_POSTQUEUE, + &iop->outbound_intmask); + hptiop_pci_posting_flush(iop); +} + +static void hptiop_remove(struct pci_dev *pcidev) +{ + struct Scsi_Host *host = pci_get_drvdata(pcidev); + struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata; + + dprintk("scsi%d: hptiop_remove\n", hba->host->host_no); + + spin_lock(&hptiop_hba_list_lock); + list_del_init(&hba->link); + spin_unlock(&hptiop_hba_list_lock); + + hptiop_shutdown(pcidev); + + free_irq(hba->pcidev->irq, hba); + + dma_free_coherent(&hba->pcidev->dev, + hba->req_size * hba->max_requests + 0x20, + hba->dma_coherent, + hba->dma_coherent_handle); + + iounmap(hba->iop); + + pci_release_regions(hba->pcidev); + pci_set_drvdata(hba->pcidev, NULL); + pci_disable_device(hba->pcidev); + + scsi_remove_host(host); + scsi_host_put(host); +} + +static struct pci_device_id hptiop_id_table[] = { + { PCI_DEVICE(0x1103, 0x3220) }, + { PCI_DEVICE(0x1103, 0x3320) }, + {}, +}; + +MODULE_DEVICE_TABLE(pci, hptiop_id_table); + +static struct pci_driver hptiop_pci_driver = { + .name = driver_name, + .id_table = hptiop_id_table, + .probe = hptiop_probe, + .remove = hptiop_remove, + .shutdown = hptiop_shutdown, +}; + +static int __init hptiop_module_init(void) +{ + int error; + + printk(KERN_INFO "%s %s\n", driver_name_long, driver_ver); + + error = pci_register_driver(&hptiop_pci_driver); + if (error < 0) + return error; + + hptiop_cdev_major = register_chrdev(0, "hptiop", &hptiop_cdev_fops); + if (hptiop_cdev_major < 0) { + printk(KERN_WARNING "unable to register hptiop device.\n"); + return hptiop_cdev_major; + } + + return 0; +} + +static void __exit hptiop_module_exit(void) +{ + dprintk("hptiop_module_exit\n"); + unregister_chrdev(hptiop_cdev_major, "hptiop"); + pci_unregister_driver(&hptiop_pci_driver); +} + + +module_init(hptiop_module_init); +module_exit(hptiop_module_exit); + +MODULE_LICENSE("GPL"); diff --git a/drivers/scsi/hptiop.h b/drivers/scsi/hptiop.h new file mode 100644 index 00000000000..f04f7e81d1a --- /dev/null +++ b/drivers/scsi/hptiop.h @@ -0,0 +1,465 @@ +/* + * HighPoint RR3xxx controller driver for Linux + * Copyright (C) 2006 HighPoint Technologies, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Please report bugs/comments/suggestions to linux@highpoint-tech.com + * + * For more information, visit http://www.highpoint-tech.com + */ +#ifndef _HPTIOP_H_ +#define _HPTIOP_H_ + +/* + * logical device type. + * Identify array (logical device) and physical device. + */ +#define LDT_ARRAY 1 +#define LDT_DEVICE 2 + +/* + * Array types + */ +#define AT_UNKNOWN 0 +#define AT_RAID0 1 +#define AT_RAID1 2 +#define AT_RAID5 3 +#define AT_RAID6 4 +#define AT_JBOD 7 + +#define MAX_NAME_LENGTH 36 +#define MAX_ARRAYNAME_LEN 16 + +#define MAX_ARRAY_MEMBERS_V1 8 +#define MAX_ARRAY_MEMBERS_V2 16 + +/* keep definition for source code compatiblity */ +#define MAX_ARRAY_MEMBERS MAX_ARRAY_MEMBERS_V1 + +/* + * array flags + */ +#define ARRAY_FLAG_DISABLED 0x00000001 /* The array is disabled */ +#define ARRAY_FLAG_NEEDBUILDING 0x00000002 /* need to be rebuilt */ +#define ARRAY_FLAG_REBUILDING 0x00000004 /* in rebuilding process */ +#define ARRAY_FLAG_BROKEN 0x00000008 /* broken but still working */ +#define ARRAY_FLAG_BOOTDISK 0x00000010 /* has a active partition */ +#define ARRAY_FLAG_BOOTMARK 0x00000040 /* array has boot mark set */ +#define ARRAY_FLAG_NEED_AUTOREBUILD 0x00000080 /* auto-rebuild should start */ +#define ARRAY_FLAG_VERIFYING 0x00000100 /* is being verified */ +#define ARRAY_FLAG_INITIALIZING 0x00000200 /* is being initialized */ +#define ARRAY_FLAG_TRANSFORMING 0x00000400 /* tranform in progress */ +#define ARRAY_FLAG_NEEDTRANSFORM 0x00000800 /* array need tranform */ +#define ARRAY_FLAG_NEEDINITIALIZING 0x00001000 /* initialization not done */ +#define ARRAY_FLAG_BROKEN_REDUNDANT 0x00002000 /* broken but redundant */ + +/* + * device flags + */ +#define DEVICE_FLAG_DISABLED 0x00000001 /* device is disabled */ +#define DEVICE_FLAG_UNINITIALIZED 0x00010000 /* device is not initialized */ +#define DEVICE_FLAG_LEGACY 0x00020000 /* lagacy drive */ +#define DEVICE_FLAG_IS_SPARE 0x80000000 /* is a spare disk */ + +/* + * ioctl codes + */ +#define HPT_CTL_CODE(x) (x+0xFF00) +#define HPT_CTL_CODE_LINUX_TO_IOP(x) ((x)-0xff00) + +#define HPT_IOCTL_GET_CONTROLLER_INFO HPT_CTL_CODE(2) +#define HPT_IOCTL_GET_CHANNEL_INFO HPT_CTL_CODE(3) +#define HPT_IOCTL_GET_LOGICAL_DEVICES HPT_CTL_CODE(4) +#define HPT_IOCTL_GET_DRIVER_CAPABILITIES HPT_CTL_CODE(19) +#define HPT_IOCTL_GET_DEVICE_INFO_V3 HPT_CTL_CODE(46) +#define HPT_IOCTL_GET_CONTROLLER_INFO_V2 HPT_CTL_CODE(47) + +/* + * Controller information. + */ +struct hpt_controller_info { + u8 chip_type; /* chip type */ + u8 interrupt_level; /* IRQ level */ + u8 num_buses; /* bus count */ + u8 chip_flags; + + u8 product_id[MAX_NAME_LENGTH];/* product name */ + u8 vendor_id[MAX_NAME_LENGTH]; /* vendor name */ +} +__attribute__((packed)); + +/* + * Channel information. + */ +struct hpt_channel_info { + __le32 io_port; /* IDE Base Port Address */ + __le32 control_port; /* IDE Control Port Address */ + __le32 devices[2]; /* device connected to this channel */ +} +__attribute__((packed)); + +/* + * Array information. + */ +struct hpt_array_info_v3 { + u8 name[MAX_ARRAYNAME_LEN]; /* array name */ + u8 description[64]; /* array description */ + u8 create_manager[16]; /* who created it */ + __le32 create_time; /* when created it */ + + u8 array_type; /* array type */ + u8 block_size_shift; /* stripe size */ + u8 ndisk; /* Number of ID in Members[] */ + u8 reserved; + + __le32 flags; /* working flags, see ARRAY_FLAG_XXX */ + __le32 members[MAX_ARRAY_MEMBERS_V2]; /* member array/disks */ + + __le32 rebuilding_progress; + __le64 rebuilt_sectors; /* rebuilding point (LBA) for single member */ + + __le32 transform_source; + __le32 transform_target; /* destination device ID */ + __le32 transforming_progress; + __le32 signature; /* persistent identification*/ + __le16 critical_members; /* bit mask of critical members */ + __le16 reserve2; + __le32 reserve; +} +__attribute__((packed)); + +/* + * physical device information. + */ +#define MAX_PARENTS_PER_DISK 8 + +struct hpt_device_info_v2 { + u8 ctlr_id; /* controller id */ + u8 path_id; /* bus */ + u8 target_id; /* id */ + u8 device_mode_setting; /* Current Data Transfer mode: 0-4 PIO0-4 */ + /* 5-7 MW DMA0-2, 8-13 UDMA0-5 */ + u8 device_type; /* device type */ + u8 usable_mode; /* highest usable mode */ + +#ifdef __BIG_ENDIAN_BITFIELD + u8 NCQ_enabled: 1; + u8 NCQ_supported: 1; + u8 TCQ_enabled: 1; + u8 TCQ_supported: 1; + u8 write_cache_enabled: 1; + u8 write_cache_supported: 1; + u8 read_ahead_enabled: 1; + u8 read_ahead_supported: 1; + u8 reserved6: 6; + u8 spin_up_mode: 2; +#else + u8 read_ahead_supported: 1; + u8 read_ahead_enabled: 1; + u8 write_cache_supported: 1; + u8 write_cache_enabled: 1; + u8 TCQ_supported: 1; + u8 TCQ_enabled: 1; + u8 NCQ_supported: 1; + u8 NCQ_enabled: 1; + u8 spin_up_mode: 2; + u8 reserved6: 6; +#endif + + __le32 flags; /* working flags, see DEVICE_FLAG_XXX */ + u8 ident[150]; /* (partitial) Identify Data of this device */ + + __le64 total_free; + __le64 max_free; + __le64 bad_sectors; + __le32 parent_arrays[MAX_PARENTS_PER_DISK]; +} +__attribute__((packed)); + +/* + * Logical device information. + */ +#define INVALID_TARGET_ID 0xFF +#define INVALID_BUS_ID 0xFF + +struct hpt_logical_device_info_v3 { + u8 type; /* LDT_ARRAY or LDT_DEVICE */ + u8 cache_policy; /* refer to CACHE_POLICY_xxx */ + u8 vbus_id; /* vbus sequence in vbus_list */ + u8 target_id; /* OS target id. 0xFF is invalid */ + /* OS name: DISK $VBusId_$TargetId */ + __le64 capacity; /* array capacity */ + __le32 parent_array; /* don't use this field for physical + device. use ParentArrays field in + hpt_device_info_v2 */ + /* reserved statistic fields */ + __le32 stat1; + __le32 stat2; + __le32 stat3; + __le32 stat4; + + union { + struct hpt_array_info_v3 array; + struct hpt_device_info_v2 device; + } __attribute__((packed)) u; + +} +__attribute__((packed)); + +/* + * ioctl structure + */ +#define HPT_IOCTL_MAGIC 0xA1B2C3D4 + +struct hpt_ioctl_u { + u32 magic; /* used to check if it's a valid ioctl packet */ + u32 ioctl_code; /* operation control code */ + void __user *inbuf; /* input data buffer */ + u32 inbuf_size; /* size of input data buffer */ + void __user *outbuf; /* output data buffer */ + u32 outbuf_size; /* size of output data buffer */ + void __user *bytes_returned; /* count of bytes returned */ +} +__attribute__((packed)); + + +struct hpt_iopmu +{ + __le32 resrved0[4]; + __le32 inbound_msgaddr0; + __le32 inbound_msgaddr1; + __le32 outbound_msgaddr0; + __le32 outbound_msgaddr1; + __le32 inbound_doorbell; + __le32 inbound_intstatus; + __le32 inbound_intmask; + __le32 outbound_doorbell; + __le32 outbound_intstatus; + __le32 outbound_intmask; + __le32 reserved1[2]; + __le32 inbound_queue; + __le32 outbound_queue; +}; + +#define IOPMU_QUEUE_EMPTY 0xffffffff +#define IOPMU_QUEUE_MASK_HOST_BITS 0xf0000000 +#define IOPMU_QUEUE_ADDR_HOST_BIT 0x80000000 + +#define IOPMU_OUTBOUND_INT_MSG0 1 +#define IOPMU_OUTBOUND_INT_MSG1 2 +#define IOPMU_OUTBOUND_INT_DOORBELL 4 +#define IOPMU_OUTBOUND_INT_POSTQUEUE 8 +#define IOPMU_OUTBOUND_INT_PCI 0x10 + +#define IOPMU_INBOUND_INT_MSG0 1 +#define IOPMU_INBOUND_INT_MSG1 2 +#define IOPMU_INBOUND_INT_DOORBELL 4 +#define IOPMU_INBOUND_INT_ERROR 8 +#define IOPMU_INBOUND_INT_POSTQUEUE 0x10 + +enum hpt_iopmu_message { + /* host-to-iop messages */ + IOPMU_INBOUND_MSG0_NOP = 0, + IOPMU_INBOUND_MSG0_RESET, + IOPMU_INBOUND_MSG0_FLUSH, + IOPMU_INBOUND_MSG0_SHUTDOWN, + IOPMU_INBOUND_MSG0_STOP_BACKGROUND_TASK, + IOPMU_INBOUND_MSG0_START_BACKGROUND_TASK, + IOPMU_INBOUND_MSG0_MAX = 0xff, + /* iop-to-host messages */ + IOPMU_OUTBOUND_MSG0_REGISTER_DEVICE_0 = 0x100, + IOPMU_OUTBOUND_MSG0_REGISTER_DEVICE_MAX = 0x1ff, + IOPMU_OUTBOUND_MSG0_UNREGISTER_DEVICE_0 = 0x200, + IOPMU_OUTBOUND_MSG0_UNREGISTER_DEVICE_MAX = 0x2ff, + IOPMU_OUTBOUND_MSG0_REVALIDATE_DEVICE_0 = 0x300, + IOPMU_OUTBOUND_MSG0_REVALIDATE_DEVICE_MAX = 0x3ff, +}; + +struct hpt_iop_request_header +{ + __le32 size; + __le32 type; + __le32 flags; + __le32 result; + __le32 context; /* host context */ + __le32 context_hi32; +}; + +#define IOP_REQUEST_FLAG_SYNC_REQUEST 1 +#define IOP_REQUEST_FLAG_BIST_REQUEST 2 +#define IOP_REQUEST_FLAG_REMAPPED 4 +#define IOP_REQUEST_FLAG_OUTPUT_CONTEXT 8 + +enum hpt_iop_request_type { + IOP_REQUEST_TYPE_GET_CONFIG = 0, + IOP_REQUEST_TYPE_SET_CONFIG, + IOP_REQUEST_TYPE_BLOCK_COMMAND, + IOP_REQUEST_TYPE_SCSI_COMMAND, + IOP_REQUEST_TYPE_IOCTL_COMMAND, + IOP_REQUEST_TYPE_MAX +}; + +enum hpt_iop_result_type { + IOP_RESULT_PENDING = 0, + IOP_RESULT_SUCCESS, + IOP_RESULT_FAIL, + IOP_RESULT_BUSY, + IOP_RESULT_RESET, + IOP_RESULT_INVALID_REQUEST, + IOP_RESULT_BAD_TARGET, + IOP_RESULT_MODE_SENSE_CHECK_CONDITION, +}; + +struct hpt_iop_request_get_config +{ + struct hpt_iop_request_header header; + __le32 interface_version; + __le32 firmware_version; + __le32 max_requests; + __le32 request_size; + __le32 max_sg_count; + __le32 data_transfer_length; + __le32 alignment_mask; + __le32 max_devices; + __le32 sdram_size; +}; + +struct hpt_iop_request_set_config +{ + struct hpt_iop_request_header header; + __le32 iop_id; + __le32 vbus_id; + __le32 reserve[6]; +}; + +struct hpt_iopsg +{ + __le32 size; + __le32 eot; /* non-zero: end of table */ + __le64 pci_address; +}; + +struct hpt_iop_request_block_command +{ + struct hpt_iop_request_header header; + u8 channel; + u8 target; + u8 lun; + u8 pad1; + __le16 command; /* IOP_BLOCK_COMMAND_{READ,WRITE} */ + __le16 sectors; + __le64 lba; + struct hpt_iopsg sg_list[1]; +}; + +#define IOP_BLOCK_COMMAND_READ 1 +#define IOP_BLOCK_COMMAND_WRITE 2 +#define IOP_BLOCK_COMMAND_VERIFY 3 +#define IOP_BLOCK_COMMAND_FLUSH 4 +#define IOP_BLOCK_COMMAND_SHUTDOWN 5 + +struct hpt_iop_request_scsi_command +{ + struct hpt_iop_request_header header; + u8 channel; + u8 target; + u8 lun; + u8 pad1; + u8 cdb[16]; + __le32 dataxfer_length; + struct hpt_iopsg sg_list[1]; +}; + +struct hpt_iop_request_ioctl_command +{ + struct hpt_iop_request_header header; + __le32 ioctl_code; + __le32 inbuf_size; + __le32 outbuf_size; + __le32 bytes_returned; + u8 buf[1]; + /* out data should be put at buf[(inbuf_size+3)&~3] */ +}; + +#define HPTIOP_MAX_REQUESTS 256u + +struct hptiop_request { + struct hptiop_request * next; + void * req_virt; + u32 req_shifted_phy; + struct scsi_cmnd * scp; + int index; +}; + +struct hpt_scsi_pointer { + int mapped; + int sgcnt; + dma_addr_t dma_handle; +}; + +#define HPT_SCP(scp) ((struct hpt_scsi_pointer *)&(scp)->SCp) + +struct hptiop_hba { + struct hpt_iopmu __iomem * iop; + struct Scsi_Host * host; + struct pci_dev * pcidev; + + struct list_head link; + + /* IOP config info */ + u32 firmware_version; + u32 sdram_size; + u32 max_devices; + u32 max_requests; + u32 max_request_size; + u32 max_sg_descriptors; + + u32 req_size; /* host-allocated request buffer size */ + int initialized; + int msg_done; + + struct hptiop_request * req_list; + struct hptiop_request reqs[HPTIOP_MAX_REQUESTS]; + + /* used to free allocated dma area */ + void * dma_coherent; + dma_addr_t dma_coherent_handle; + + atomic_t reset_count; + atomic_t resetting; + + wait_queue_head_t reset_wq; + wait_queue_head_t ioctl_wq; +}; + +struct hpt_ioctl_k +{ + struct hptiop_hba * hba; + u32 ioctl_code; + u32 inbuf_size; + u32 outbuf_size; + void * inbuf; + void * outbuf; + u32 * bytes_returned; + void (*done)(struct hpt_ioctl_k *); + int result; /* HPT_IOCTL_RESULT_ */ +}; + +#define HPT_IOCTL_RESULT_OK 0 +#define HPT_IOCTL_RESULT_FAILED (-1) + +#if 0 +#define dprintk(fmt, args...) do { printk(fmt, ##args); } while(0) +#else +#define dprintk(fmt, args...) +#endif + +#endif -- cgit v1.2.3 From 9dc399de0840a478adb71278becf598d3ab3aacc Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 9 Jun 2006 22:25:23 +0200 Subject: [SCSI] Remove last page_address from dc395x.c Dynamically map scattergather buffer instead of using page_address(). Signed-off-by: Guennadi Liakhovetski Signed-off-by: James Bottomley --- drivers/scsi/dc395x.c | 59 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 24 deletions(-) diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c index 0c56095f814..18324525493 100644 --- a/drivers/scsi/dc395x.c +++ b/drivers/scsi/dc395x.c @@ -3347,21 +3347,14 @@ static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, { u8 tempcnt, status; struct scsi_cmnd *cmd = srb->cmd; - struct ScsiInqData *ptr; enum dma_data_direction dir = cmd->sc_data_direction; - - if (cmd->use_sg) { - struct scatterlist* sg = (struct scatterlist *)cmd->request_buffer; - ptr = (struct ScsiInqData *)(page_address(sg->page) + sg->offset); - } else { - ptr = (struct ScsiInqData *)(cmd->request_buffer); - } + int ckc_only = 1; dprintkdbg(DBG_1, "srb_done: (pid#%li) <%02i-%i>\n", srb->cmd->pid, srb->cmd->device->id, srb->cmd->device->lun); - dprintkdbg(DBG_SG, "srb_done: srb=%p sg=%i(%i/%i) buf=%p addr=%p\n", + dprintkdbg(DBG_SG, "srb_done: srb=%p sg=%i(%i/%i) buf=%p\n", srb, cmd->use_sg, srb->sg_index, srb->sg_count, - cmd->request_buffer, ptr); + cmd->request_buffer); status = srb->target_status; if (srb->flag & AUTO_REQSENSE) { dprintkdbg(DBG_0, "srb_done: AUTO_REQSENSE1\n"); @@ -3500,29 +3493,47 @@ static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, srb->segment_x[0].address, cmd->request_bufflen, dir); } - - if ((cmd->result & RES_DID) == 0 && cmd->cmnd[0] == INQUIRY - && cmd->cmnd[2] == 0 && cmd->request_bufflen >= 8 - && dir != PCI_DMA_NONE && ptr && (ptr->Vers & 0x07) >= 2) - dcb->inquiry7 = ptr->Flags; + ckc_only = 0; /* Check Error Conditions */ ckc_e: + if (cmd->cmnd[0] == INQUIRY) { + unsigned char *base = NULL; + struct ScsiInqData *ptr; + unsigned long flags = 0; + + if (cmd->use_sg) { + struct scatterlist* sg = (struct scatterlist *)cmd->request_buffer; + size_t offset = 0, len = sizeof(struct ScsiInqData); + + local_irq_save(flags); + base = scsi_kmap_atomic_sg(sg, cmd->use_sg, &offset, &len); + ptr = (struct ScsiInqData *)(base + offset); + } else + ptr = (struct ScsiInqData *)(cmd->request_buffer); + + if (!ckc_only && (cmd->result & RES_DID) == 0 + && cmd->cmnd[2] == 0 && cmd->request_bufflen >= 8 + && dir != PCI_DMA_NONE && ptr && (ptr->Vers & 0x07) >= 2) + dcb->inquiry7 = ptr->Flags; + /*if( srb->cmd->cmnd[0] == INQUIRY && */ /* (host_byte(cmd->result) == DID_OK || status_byte(cmd->result) & CHECK_CONDITION) ) */ - if (cmd->cmnd[0] == INQUIRY && (cmd->result == (DID_OK << 16) - || status_byte(cmd-> - result) & - CHECK_CONDITION)) { - - if (!dcb->init_tcq_flag) { - add_dev(acb, dcb, ptr); - dcb->init_tcq_flag = 1; + if ((cmd->result == (DID_OK << 16) + || status_byte(cmd->result) & + CHECK_CONDITION)) { + if (!dcb->init_tcq_flag) { + add_dev(acb, dcb, ptr); + dcb->init_tcq_flag = 1; + } } + if (cmd->use_sg) { + scsi_kunmap_atomic_sg(base); + local_irq_restore(flags); + } } - /* Here is the info for Doug Gilbert's sg3 ... */ cmd->resid = srb->total_xfer_length; /* This may be interpreted by sb. or not ... */ -- cgit v1.2.3 From 6391a11375de5e2bb1eb8481e54619761dc65d9f Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Thu, 8 Jun 2006 22:23:48 -0700 Subject: [SCSI] drivers/scsi: Use ARRAY_SIZE macro Use ARRAY_SIZE macro instead of sizeof(x)/sizeof(x[0]) and remove duplicates of the macro. Signed-off-by: Tobias Klauser Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/scsi/3w-xxxx.c | 6 +++--- drivers/scsi/53c700.c | 19 ++++++++----------- drivers/scsi/53c7xx.c | 14 +++++++------- drivers/scsi/NCR53c406a.c | 8 ++++---- drivers/scsi/aacraid/aachba.c | 18 ++++++++---------- drivers/scsi/aacraid/commctrl.c | 2 +- drivers/scsi/aha1542.c | 31 ++++++++++++++----------------- drivers/scsi/aic7xxx/aic7770.c | 2 +- drivers/scsi/aic7xxx/aic79xx.h | 2 -- drivers/scsi/aic7xxx/aic79xx_core.c | 10 +++++----- drivers/scsi/aic7xxx/aic79xx_osm.c | 20 ++++++++++---------- drivers/scsi/aic7xxx/aic79xx_pci.c | 2 +- drivers/scsi/aic7xxx/aic79xx_proc.c | 4 +--- drivers/scsi/aic7xxx/aic7xxx.h | 2 -- drivers/scsi/aic7xxx/aic7xxx_core.c | 8 ++++---- drivers/scsi/aic7xxx/aic7xxx_osm.c | 12 ++++++------ drivers/scsi/aic7xxx/aic7xxx_pci.c | 2 +- drivers/scsi/aic7xxx/aic7xxx_proc.c | 4 +--- drivers/scsi/aic7xxx_old.c | 2 +- drivers/scsi/constants.c | 33 +++++++++++++-------------------- drivers/scsi/dtc.c | 18 +++++++++--------- drivers/scsi/fd_mcs.c | 2 +- drivers/scsi/fdomain.c | 10 +++++----- drivers/scsi/g_NCR5380.c | 19 +++++++++---------- drivers/scsi/gdth.c | 4 ++-- drivers/scsi/ibmmca.c | 16 +++++++--------- drivers/scsi/in2000.c | 2 +- drivers/scsi/initio.c | 3 +-- drivers/scsi/ips.c | 2 +- drivers/scsi/osst.c | 4 ++-- drivers/scsi/pas16.c | 8 ++++---- drivers/scsi/qla1280.c | 7 ++----- drivers/scsi/qlogicpti.c | 2 +- drivers/scsi/raid_class.c | 4 ++-- drivers/scsi/scsi_lib.c | 2 +- drivers/scsi/scsi_sysfs.c | 8 ++++---- drivers/scsi/scsi_transport_fc.c | 6 +++--- drivers/scsi/scsi_transport_sas.c | 4 ++-- drivers/scsi/scsi_transport_spi.c | 4 ++-- drivers/scsi/sd.c | 2 +- drivers/scsi/seagate.c | 4 ++-- drivers/scsi/sg.c | 6 ++---- drivers/scsi/st.c | 2 +- drivers/scsi/sym53c8xx_2/sym_hipd.c | 3 +-- drivers/scsi/t128.c | 10 +++++----- drivers/scsi/wd33c93.c | 2 +- drivers/scsi/wd7000.c | 12 ++++++------ 47 files changed, 167 insertions(+), 200 deletions(-) diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c index 37a58c6dad2..17dbd4ac869 100644 --- a/drivers/scsi/3w-xxxx.c +++ b/drivers/scsi/3w-xxxx.c @@ -405,7 +405,7 @@ static int tw_decode_sense(TW_Device_Extension *tw_dev, int request_id, int fill /* Attempt to return intelligent sense information */ if (fill_sense) { if ((command->status == 0xc7) || (command->status == 0xcb)) { - for (i=0;i<(sizeof(tw_sense_table)/sizeof(tw_sense_table[0]));i++) { + for (i = 0; i < ARRAY_SIZE(tw_sense_table); i++) { if (command->flags == tw_sense_table[i][0]) { /* Valid bit and 'current errors' */ @@ -625,7 +625,7 @@ static int tw_aen_complete(TW_Device_Extension *tw_dev, int request_id) if (aen == 0x0ff) { printk(KERN_WARNING "3w-xxxx: scsi%d: AEN: INFO: AEN queue overflow.\n", tw_dev->host->host_no); } else { - table_max = sizeof(tw_aen_string)/sizeof(char *); + table_max = ARRAY_SIZE(tw_aen_string); if ((aen & 0x0ff) < table_max) { if ((tw_aen_string[aen & 0xff][strlen(tw_aen_string[aen & 0xff])-1]) == '#') { printk(KERN_WARNING "3w-xxxx: scsi%d: AEN: %s%d.\n", tw_dev->host->host_no, tw_aen_string[aen & 0xff], aen >> 8); @@ -786,7 +786,7 @@ static int tw_aen_drain_queue(TW_Device_Extension *tw_dev) if (aen == 0x0ff) { printk(KERN_WARNING "3w-xxxx: AEN: INFO: AEN queue overflow.\n"); } else { - table_max = sizeof(tw_aen_string)/sizeof(char *); + table_max = ARRAY_SIZE(tw_aen_string); if ((aen & 0x0ff) < table_max) { if ((tw_aen_string[aen & 0xff][strlen(tw_aen_string[aen & 0xff])-1]) == '#') { printk(KERN_WARNING "3w-xxxx: AEN: %s%d.\n", tw_aen_string[aen & 0xff], aen >> 8); diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c index b767918b9a9..4958c3b93c3 100644 --- a/drivers/scsi/53c700.c +++ b/drivers/scsi/53c700.c @@ -316,7 +316,7 @@ NCR_700_detect(struct scsi_host_template *tpnt, BUG_ON(!dma_is_consistent(pScript) && L1_CACHE_BYTES < dma_get_cache_alignment()); hostdata->slots = (struct NCR_700_command_slot *)(memory + SLOTS_OFFSET); hostdata->dev = dev; - + pSlots = pScript + SLOTS_OFFSET; /* Fill in the missing routines from the host template */ @@ -332,19 +332,18 @@ NCR_700_detect(struct scsi_host_template *tpnt, tpnt->slave_destroy = NCR_700_slave_destroy; tpnt->change_queue_depth = NCR_700_change_queue_depth; tpnt->change_queue_type = NCR_700_change_queue_type; - + if(tpnt->name == NULL) tpnt->name = "53c700"; if(tpnt->proc_name == NULL) tpnt->proc_name = "53c700"; - host = scsi_host_alloc(tpnt, 4); if (!host) return NULL; memset(hostdata->slots, 0, sizeof(struct NCR_700_command_slot) * NCR_700_COMMAND_SLOTS_PER_HOST); - for(j = 0; j < NCR_700_COMMAND_SLOTS_PER_HOST; j++) { + for (j = 0; j < NCR_700_COMMAND_SLOTS_PER_HOST; j++) { dma_addr_t offset = (dma_addr_t)((unsigned long)&hostdata->slots[j].SG[0] - (unsigned long)&hostdata->slots[0].SG[0]); hostdata->slots[j].pSG = (struct NCR_700_SG_List *)((unsigned long)(pSlots + offset)); @@ -355,14 +354,12 @@ NCR_700_detect(struct scsi_host_template *tpnt, hostdata->slots[j].state = NCR_700_SLOT_FREE; } - for(j = 0; j < sizeof(SCRIPT)/sizeof(SCRIPT[0]); j++) { + for (j = 0; j < ARRAY_SIZE(SCRIPT); j++) script[j] = bS_to_host(SCRIPT[j]); - } /* adjust all labels to be bus physical */ - for(j = 0; j < PATCHES; j++) { + for (j = 0; j < PATCHES; j++) script[LABELPATCHES[j]] = bS_to_host(pScript + SCRIPT[LABELPATCHES[j]]); - } /* now patch up fixed addresses. */ script_patch_32(script, MessageLocation, pScript + MSGOUT_OFFSET); @@ -385,17 +382,17 @@ NCR_700_detect(struct scsi_host_template *tpnt, host->hostdata[0] = (unsigned long)hostdata; /* kick the chip */ NCR_700_writeb(0xff, host, CTEST9_REG); - if(hostdata->chip710) + if (hostdata->chip710) hostdata->rev = (NCR_700_readb(host, CTEST8_REG)>>4) & 0x0f; else hostdata->rev = (NCR_700_readb(host, CTEST7_REG)>>4) & 0x0f; hostdata->fast = (NCR_700_readb(host, CTEST9_REG) == 0); - if(banner == 0) { + if (banner == 0) { printk(KERN_NOTICE "53c700: Version " NCR_700_VERSION " By James.Bottomley@HansenPartnership.com\n"); banner = 1; } printk(KERN_NOTICE "scsi%d: %s rev %d %s\n", host->host_no, - hostdata->chip710 ? "53c710" : + hostdata->chip710 ? "53c710" : (hostdata->fast ? "53c700-66" : "53c700"), hostdata->rev, hostdata->differential ? "(Differential)" : ""); diff --git a/drivers/scsi/53c7xx.c b/drivers/scsi/53c7xx.c index cfc991271cc..765769a629e 100644 --- a/drivers/scsi/53c7xx.c +++ b/drivers/scsi/53c7xx.c @@ -361,7 +361,7 @@ int CmdPageStart = (0 - Ent_dsa_zero - sizeof(struct NCR53c7x0_cmd)) & 0xff; static char *setup_strings[] = {"","","","","","","",""}; -#define MAX_SETUP_STRINGS (sizeof(setup_strings) / sizeof(char *)) +#define MAX_SETUP_STRINGS ARRAY_SIZE(setup_strings) #define SETUP_BUFFER_SIZE 200 static char setup_buffer[SETUP_BUFFER_SIZE]; static char setup_used[MAX_SETUP_STRINGS]; @@ -2190,15 +2190,15 @@ static const struct { */ -static void +static void synchronous (struct Scsi_Host *host, int target, char *msg) { struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0]; int desire, divisor, i, limit; unsigned char scntl3, sxfer; /* The diagnostic message fits on one line, even with max. width integers */ - char buf[80]; - + char buf[80]; + /* Desired transfer clock in Hz */ desire = 1000000000L / (msg[3] * 4); /* Scale the available SCSI clock by 10 so we get tenths */ @@ -2209,14 +2209,14 @@ synchronous (struct Scsi_Host *host, int target, char *msg) { msg[4] = 8; if (hostdata->options & OPTION_DEBUG_SDTR) - printk("scsi%d : optimal synchronous divisor of %d.%01d\n", + printk("scsi%d : optimal synchronous divisor of %d.%01d\n", host->host_no, divisor / 10, divisor % 10); - limit = (sizeof(syncs) / sizeof(syncs[0]) -1); + limit = ARRAY_SIZE(syncs) - 1; for (i = 0; (i < limit) && (divisor > syncs[i].div); ++i); if (hostdata->options & OPTION_DEBUG_SDTR) - printk("scsi%d : selected synchronous divisor of %d.%01d\n", + printk("scsi%d : selected synchronous divisor of %d.%01d\n", host->host_no, syncs[i].div / 10, syncs[i].div % 10); msg[3] = ((1000000000L / hostdata->scsi_clock) * syncs[i].div / 10 / 4); diff --git a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c index ae37d3ab9c4..8472c535902 100644 --- a/drivers/scsi/NCR53c406a.c +++ b/drivers/scsi/NCR53c406a.c @@ -213,16 +213,16 @@ static void *addresses[] = { (void *) 0xd8000, (void *) 0xc8000 }; -#define ADDRESS_COUNT (sizeof( addresses ) / sizeof( unsigned )) +#define ADDRESS_COUNT ARRAY_SIZE(addresses) #endif /* USE_BIOS */ /* possible i/o port addresses */ static unsigned short ports[] = { 0x230, 0x330, 0x280, 0x290, 0x330, 0x340, 0x300, 0x310, 0x348, 0x350 }; -#define PORT_COUNT (sizeof( ports ) / sizeof( unsigned short )) +#define PORT_COUNT ARRAY_SIZE(ports) /* possible interrupt channels */ static unsigned short intrs[] = { 10, 11, 12, 15 }; -#define INTR_COUNT (sizeof( intrs ) / sizeof( unsigned short )) +#define INTR_COUNT ARRAY_SIZE(intrs) /* signatures for NCR 53c406a based controllers */ #if USE_BIOS @@ -236,7 +236,7 @@ struct signature { { "Copyright (C) Acculogic, Inc.\r\n2.8M Diskette Extension Bios ver 4.04.03 03/01/1993", 61, 82},}; -#define SIGNATURE_COUNT (sizeof( signatures ) / sizeof( struct signature )) +#define SIGNATURE_COUNT ARRAY_SIZE(signatures) #endif /* USE_BIOS */ /* ============================================================ */ diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index e4b38f896cb..ea9e038813e 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -641,13 +641,13 @@ static void setinqstr(struct aac_dev *dev, void *data, int tindex) cp[sizeof(str->pid)] = c; } else { struct aac_driver_ident *mp = aac_get_driver_ident(dev->cardtype); - - inqstrcpy (mp->vname, str->vid); + + inqstrcpy (mp->vname, str->vid); /* last six chars reserved for vol type */ inqstrcpy (mp->model, str->pid); } - if (tindex < (sizeof(container_types)/sizeof(char *))){ + if (tindex < ARRAY_SIZE(container_types)){ char *findit = str->pid; for ( ; *findit != ' '; findit++); /* walk till we find a space */ @@ -1576,7 +1576,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) * see: .c i.e. aac.c */ if (scmd_id(scsicmd) == host->this_id) { - setinqstr(dev, (void *) (inq_data.inqd_vid), (sizeof(container_types)/sizeof(char *))); + setinqstr(dev, (void *) (inq_data.inqd_vid), ARRAY_SIZE(container_types)); inq_data.inqd_pdt = INQD_PDT_PROC; /* Processor device */ aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data)); scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; @@ -2381,7 +2381,7 @@ static struct aac_srb_status_info srb_status_info[] = { { SRB_STATUS_SUCCESS, "Success"}, { SRB_STATUS_ABORTED, "Aborted Command"}, { SRB_STATUS_ABORT_FAILED, "Abort Failed"}, - { SRB_STATUS_ERROR, "Error Event"}, + { SRB_STATUS_ERROR, "Error Event"}, { SRB_STATUS_BUSY, "Device Busy"}, { SRB_STATUS_INVALID_REQUEST, "Invalid Request"}, { SRB_STATUS_INVALID_PATH_ID, "Invalid Path ID"}, @@ -2400,7 +2400,7 @@ static struct aac_srb_status_info srb_status_info[] = { { SRB_STATUS_BAD_SRB_BLOCK_LENGTH,"Bad Srb Block Length"}, { SRB_STATUS_REQUEST_FLUSHED, "Request Flushed"}, { SRB_STATUS_DELAYED_RETRY, "Delayed Retry"}, - { SRB_STATUS_INVALID_LUN, "Invalid LUN"}, + { SRB_STATUS_INVALID_LUN, "Invalid LUN"}, { SRB_STATUS_INVALID_TARGET_ID, "Invalid TARGET ID"}, { SRB_STATUS_BAD_FUNCTION, "Bad Function"}, { SRB_STATUS_ERROR_RECOVERY, "Error Recovery"}, @@ -2415,11 +2415,9 @@ char *aac_get_status_string(u32 status) { int i; - for(i=0; i < (sizeof(srb_status_info)/sizeof(struct aac_srb_status_info)); i++ ){ - if(srb_status_info[i].status == status){ + for (i = 0; i < ARRAY_SIZE(srb_status_info); i++) + if (srb_status_info[i].status == status) return srb_status_info[i].str; - } - } return "Bad Status Code"; } diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c index 9f75144e524..255421de9d1 100644 --- a/drivers/scsi/aacraid/commctrl.c +++ b/drivers/scsi/aacraid/commctrl.c @@ -535,7 +535,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) default: data_dir = DMA_NONE; } - if (user_srbcmd->sg.count > (sizeof(sg_list)/sizeof(sg_list[0]))) { + if (user_srbcmd->sg.count > ARRAY_SIZE(sg_list)) { dprintk((KERN_DEBUG"aacraid: too many sg entries %d\n", le32_to_cpu(srbcmd->sg.count))); rcode = -EINVAL; diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c index 51bad7a1e77..86c6bd23459 100644 --- a/drivers/scsi/aha1542.c +++ b/drivers/scsi/aha1542.c @@ -1011,7 +1011,7 @@ static int __init do_setup(char *str) int count=setup_idx; - get_options(str, sizeof(ints)/sizeof(int), ints); + get_options(str, ARRAY_SIZE(ints), ints); aha1542_setup(str,ints); return countqinfifo) - wrap_qinpos); + + ARRAY_SIZE(ahd->qinfifo) - wrap_qinpos); } void @@ -8619,7 +8619,7 @@ ahd_check_patch(struct ahd_softc *ahd, struct patch **start_patch, struct patch *last_patch; u_int num_patches; - num_patches = sizeof(patches)/sizeof(struct patch); + num_patches = ARRAY_SIZE(patches); last_patch = &patches[num_patches]; cur_patch = *start_patch; diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index 66e4a47bb9e..e0ccdf36220 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c @@ -916,7 +916,7 @@ ahd_linux_setup_iocell_info(u_long index, int instance, int targ, int32_t value) { if ((instance >= 0) - && (instance < NUM_ELEMENTS(aic79xx_iocell_info))) { + && (instance < ARRAY_SIZE(aic79xx_iocell_info))) { uint8_t *iocell_info; iocell_info = (uint8_t*)&aic79xx_iocell_info[instance]; @@ -934,7 +934,7 @@ ahd_linux_setup_tag_info_global(char *p) tags = simple_strtoul(p + 1, NULL, 0) & 0xff; printf("Setting Global Tags= %d\n", tags); - for (i = 0; i < NUM_ELEMENTS(aic79xx_tag_info); i++) { + for (i = 0; i < ARRAY_SIZE(aic79xx_tag_info); i++) { for (j = 0; j < AHD_NUM_TARGETS; j++) { aic79xx_tag_info[i].tag_commands[j] = tags; } @@ -946,7 +946,7 @@ ahd_linux_setup_tag_info(u_long arg, int instance, int targ, int32_t value) { if ((instance >= 0) && (targ >= 0) - && (instance < NUM_ELEMENTS(aic79xx_tag_info)) + && (instance < ARRAY_SIZE(aic79xx_tag_info)) && (targ < AHD_NUM_TARGETS)) { aic79xx_tag_info[instance].tag_commands[targ] = value & 0x1FF; if (bootverbose) @@ -1072,21 +1072,21 @@ aic79xx_setup(char *s) end = strchr(s, '\0'); /* - * XXX ia64 gcc isn't smart enough to know that NUM_ELEMENTS + * XXX ia64 gcc isn't smart enough to know that ARRAY_SIZE * will never be 0 in this case. - */ - n = 0; + */ + n = 0; while ((p = strsep(&s, ",.")) != NULL) { if (*p == '\0') continue; - for (i = 0; i < NUM_ELEMENTS(options); i++) { + for (i = 0; i < ARRAY_SIZE(options); i++) { n = strlen(options[i].name); if (strncmp(options[i].name, p, n) == 0) break; } - if (i == NUM_ELEMENTS(options)) + if (i == ARRAY_SIZE(options)) continue; if (strncmp(p, "global_tag_depth", n) == 0) { @@ -1294,7 +1294,7 @@ ahd_platform_init(struct ahd_softc *ahd) /* * Lookup and commit any modified IO Cell options. */ - if (ahd->unit < NUM_ELEMENTS(aic79xx_iocell_info)) { + if (ahd->unit < ARRAY_SIZE(aic79xx_iocell_info)) { struct ahd_linux_iocell_opts *iocell_opts; iocell_opts = &aic79xx_iocell_info[ahd->unit]; @@ -1426,7 +1426,7 @@ ahd_linux_user_tagdepth(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) tags = 0; if ((ahd->user_discenable & devinfo->target_mask) != 0) { - if (ahd->unit >= NUM_ELEMENTS(aic79xx_tag_info)) { + if (ahd->unit >= ARRAY_SIZE(aic79xx_tag_info)) { if (warned_user == 0) { printf(KERN_WARNING diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c index 757242e522c..14850f31aaf 100644 --- a/drivers/scsi/aic7xxx/aic79xx_pci.c +++ b/drivers/scsi/aic7xxx/aic79xx_pci.c @@ -201,7 +201,7 @@ struct ahd_pci_identity ahd_pci_ident_table [] = } }; -const u_int ahd_num_pci_devs = NUM_ELEMENTS(ahd_pci_ident_table); +const u_int ahd_num_pci_devs = ARRAY_SIZE(ahd_pci_ident_table); #define DEVCONFIG 0x40 #define PCIXINITPAT 0x0000E000ul diff --git a/drivers/scsi/aic7xxx/aic79xx_proc.c b/drivers/scsi/aic7xxx/aic79xx_proc.c index 39a27840fce..24fd59a230b 100644 --- a/drivers/scsi/aic7xxx/aic79xx_proc.c +++ b/drivers/scsi/aic7xxx/aic79xx_proc.c @@ -76,11 +76,9 @@ static u_int ahd_calc_syncsrate(u_int period_factor) { int i; - int num_syncrates; - num_syncrates = sizeof(scsi_syncrates) / sizeof(scsi_syncrates[0]); /* See if the period is in the "exception" table */ - for (i = 0; i < num_syncrates; i++) { + for (i = 0; i < ARRAY_SIZE(scsi_syncrates); i++) { if (period_factor == scsi_syncrates[i].period_factor) { /* Period in kHz */ diff --git a/drivers/scsi/aic7xxx/aic7xxx.h b/drivers/scsi/aic7xxx/aic7xxx.h index 91d294c6334..e24e6067401 100644 --- a/drivers/scsi/aic7xxx/aic7xxx.h +++ b/drivers/scsi/aic7xxx/aic7xxx.h @@ -69,8 +69,6 @@ struct seeprom_descriptor; #define FALSE 0 #endif -#define NUM_ELEMENTS(array) (sizeof(array) / sizeof(*array)) - #define ALL_CHANNELS '\0' #define ALL_TARGETS_MASK 0xFFFF #define INITIATOR_WILDCARD (~0) diff --git a/drivers/scsi/aic7xxx/aic7xxx_core.c b/drivers/scsi/aic7xxx/aic7xxx_core.c index 50a3dd047cf..93e4e40944b 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_core.c +++ b/drivers/scsi/aic7xxx/aic7xxx_core.c @@ -68,7 +68,7 @@ char *ahc_chip_names[] = "aic7892", "aic7899" }; -static const u_int num_chip_names = NUM_ELEMENTS(ahc_chip_names); +static const u_int num_chip_names = ARRAY_SIZE(ahc_chip_names); /* * Hardware error codes. @@ -88,7 +88,7 @@ static struct ahc_hard_error_entry ahc_hard_errors[] = { { PCIERRSTAT, "PCI Error detected" }, { CIOPARERR, "CIOBUS Parity Error" }, }; -static const u_int num_errors = NUM_ELEMENTS(ahc_hard_errors); +static const u_int num_errors = ARRAY_SIZE(ahc_hard_errors); static struct ahc_phase_table_entry ahc_phase_table[] = { @@ -108,7 +108,7 @@ static struct ahc_phase_table_entry ahc_phase_table[] = * In most cases we only wish to itterate over real phases, so * exclude the last element from the count. */ -static const u_int num_phases = NUM_ELEMENTS(ahc_phase_table) - 1; +static const u_int num_phases = ARRAY_SIZE(ahc_phase_table) - 1; /* * Valid SCSIRATE values. (p. 3-17) @@ -6367,7 +6367,7 @@ ahc_check_patch(struct ahc_softc *ahc, struct patch **start_patch, struct patch *last_patch; u_int num_patches; - num_patches = sizeof(patches)/sizeof(struct patch); + num_patches = ARRAY_SIZE(patches); last_patch = &patches[num_patches]; cur_patch = *start_patch; diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index 2c801672d8b..eadfefdd8d7 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -886,7 +886,7 @@ ahc_linux_setup_tag_info_global(char *p) tags = simple_strtoul(p + 1, NULL, 0) & 0xff; printf("Setting Global Tags= %d\n", tags); - for (i = 0; i < NUM_ELEMENTS(aic7xxx_tag_info); i++) { + for (i = 0; i < ARRAY_SIZE(aic7xxx_tag_info); i++) { for (j = 0; j < AHC_NUM_TARGETS; j++) { aic7xxx_tag_info[i].tag_commands[j] = tags; } @@ -898,7 +898,7 @@ ahc_linux_setup_tag_info(u_long arg, int instance, int targ, int32_t value) { if ((instance >= 0) && (targ >= 0) - && (instance < NUM_ELEMENTS(aic7xxx_tag_info)) + && (instance < ARRAY_SIZE(aic7xxx_tag_info)) && (targ < AHC_NUM_TARGETS)) { aic7xxx_tag_info[instance].tag_commands[targ] = value & 0xff; if (bootverbose) @@ -1020,7 +1020,7 @@ aic7xxx_setup(char *s) end = strchr(s, '\0'); /* - * XXX ia64 gcc isn't smart enough to know that NUM_ELEMENTS + * XXX ia64 gcc isn't smart enough to know that ARRAY_SIZE * will never be 0 in this case. */ n = 0; @@ -1028,13 +1028,13 @@ aic7xxx_setup(char *s) while ((p = strsep(&s, ",.")) != NULL) { if (*p == '\0') continue; - for (i = 0; i < NUM_ELEMENTS(options); i++) { + for (i = 0; i < ARRAY_SIZE(options); i++) { n = strlen(options[i].name); if (strncmp(options[i].name, p, n) == 0) break; } - if (i == NUM_ELEMENTS(options)) + if (i == ARRAY_SIZE(options)) continue; if (strncmp(p, "global_tag_depth", n) == 0) { @@ -1360,7 +1360,7 @@ ahc_linux_user_tagdepth(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) tags = 0; if ((ahc->user_discenable & devinfo->target_mask) != 0) { - if (ahc->unit >= NUM_ELEMENTS(aic7xxx_tag_info)) { + if (ahc->unit >= ARRAY_SIZE(aic7xxx_tag_info)) { if (warned_user == 0) { printf(KERN_WARNING diff --git a/drivers/scsi/aic7xxx/aic7xxx_pci.c b/drivers/scsi/aic7xxx/aic7xxx_pci.c index 5f586140e05..b1156fbd4a1 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_pci.c +++ b/drivers/scsi/aic7xxx/aic7xxx_pci.c @@ -553,7 +553,7 @@ struct ahc_pci_identity ahc_pci_ident_table [] = } }; -const u_int ahc_num_pci_devs = NUM_ELEMENTS(ahc_pci_ident_table); +const u_int ahc_num_pci_devs = ARRAY_SIZE(ahc_pci_ident_table); #define AHC_394X_SLOT_CHANNEL_A 4 #define AHC_394X_SLOT_CHANNEL_B 5 diff --git a/drivers/scsi/aic7xxx/aic7xxx_proc.c b/drivers/scsi/aic7xxx/aic7xxx_proc.c index 04a3506cf34..5914b4aa4a8 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_proc.c +++ b/drivers/scsi/aic7xxx/aic7xxx_proc.c @@ -77,11 +77,9 @@ static u_int ahc_calc_syncsrate(u_int period_factor) { int i; - int num_syncrates; - num_syncrates = sizeof(scsi_syncrates) / sizeof(scsi_syncrates[0]); /* See if the period is in the "exception" table */ - for (i = 0; i < num_syncrates; i++) { + for (i = 0; i < ARRAY_SIZE(scsi_syncrates); i++) { if (period_factor == scsi_syncrates[i].period_factor) { /* Period in kHz */ diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c index 770f1647e4d..5dba1c63122 100644 --- a/drivers/scsi/aic7xxx_old.c +++ b/drivers/scsi/aic7xxx_old.c @@ -1565,7 +1565,7 @@ aic7xxx_check_patch(struct aic7xxx_host *p, struct sequencer_patch *last_patch; int num_patches; - num_patches = sizeof(sequencer_patches)/sizeof(struct sequencer_patch); + num_patches = ARRAY_SIZE(sequencer_patches); last_patch = &sequencer_patches[num_patches]; cur_patch = *start_patch; diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c index 30a335349ce..e24835b38b5 100644 --- a/drivers/scsi/constants.c +++ b/drivers/scsi/constants.c @@ -114,8 +114,7 @@ static const struct value_name_pair maint_in_arr[] = { {0xd, "Report supported task management functions"}, {0xe, "Report priority"}, }; -#define MAINT_IN_SZ \ - (int)(sizeof(maint_in_arr) / sizeof(maint_in_arr[0])) +#define MAINT_IN_SZ ARRAY_SIZE(maint_in_arr) static const struct value_name_pair maint_out_arr[] = { {0x6, "Set device identifier"}, @@ -123,34 +122,29 @@ static const struct value_name_pair maint_out_arr[] = { {0xb, "Change aliases"}, {0xe, "Set priority"}, }; -#define MAINT_OUT_SZ \ - (int)(sizeof(maint_out_arr) / sizeof(maint_out_arr[0])) +#define MAINT_OUT_SZ ARRAY_SIZE(maint_out_arr) static const struct value_name_pair serv_in12_arr[] = { {0x1, "Read media serial number"}, }; -#define SERV_IN12_SZ \ - (int)(sizeof(serv_in12_arr) / sizeof(serv_in12_arr[0])) +#define SERV_IN12_SZ ARRAY_SIZE(serv_in12_arr) static const struct value_name_pair serv_out12_arr[] = { {-1, "dummy entry"}, }; -#define SERV_OUT12_SZ \ - (int)(sizeof(serv_out12_arr) / sizeof(serv_in12_arr[0])) +#define SERV_OUT12_SZ ARRAY_SIZE(serv_out12_arr) static const struct value_name_pair serv_in16_arr[] = { {0x10, "Read capacity(16)"}, {0x11, "Read long(16)"}, }; -#define SERV_IN16_SZ \ - (int)(sizeof(serv_in16_arr) / sizeof(serv_in16_arr[0])) +#define SERV_IN16_SZ ARRAY_SIZE(serv_in16_arr) static const struct value_name_pair serv_out16_arr[] = { {0x11, "Write long(16)"}, {0x1f, "Notify data transfer device(16)"}, }; -#define SERV_OUT16_SZ \ - (int)(sizeof(serv_out16_arr) / sizeof(serv_in16_arr[0])) +#define SERV_OUT16_SZ ARRAY_SIZE(serv_out16_arr) static const struct value_name_pair variable_length_arr[] = { {0x1, "Rebuild(32)"}, @@ -190,8 +184,7 @@ static const struct value_name_pair variable_length_arr[] = { {0x8f7e, "Perform SCSI command (osd)"}, {0x8f7f, "Perform task management function (osd)"}, }; -#define VARIABLE_LENGTH_SZ \ - (int)(sizeof(variable_length_arr) / sizeof(variable_length_arr[0])) +#define VARIABLE_LENGTH_SZ ARRAY_SIZE(variable_length_arr) static const char * get_sa_name(const struct value_name_pair * arr, int arr_sz, int service_action) @@ -1290,10 +1283,10 @@ EXPORT_SYMBOL(scsi_print_command); #ifdef CONFIG_SCSI_CONSTANTS static const char * const hostbyte_table[]={ -"DID_OK", "DID_NO_CONNECT", "DID_BUS_BUSY", "DID_TIME_OUT", "DID_BAD_TARGET", +"DID_OK", "DID_NO_CONNECT", "DID_BUS_BUSY", "DID_TIME_OUT", "DID_BAD_TARGET", "DID_ABORT", "DID_PARITY", "DID_ERROR", "DID_RESET", "DID_BAD_INTR", "DID_PASSTHROUGH", "DID_SOFT_ERROR", "DID_IMM_RETRY"}; -#define NUM_HOSTBYTE_STRS (sizeof(hostbyte_table) / sizeof(const char *)) +#define NUM_HOSTBYTE_STRS ARRAY_SIZE(hostbyte_table) void scsi_print_hostbyte(int scsiresult) { @@ -1303,7 +1296,7 @@ void scsi_print_hostbyte(int scsiresult) if (hb < NUM_HOSTBYTE_STRS) printk("(%s) ", hostbyte_table[hb]); else - printk("is invalid "); + printk("is invalid "); } #else void scsi_print_hostbyte(int scsiresult) @@ -1315,14 +1308,14 @@ void scsi_print_hostbyte(int scsiresult) #ifdef CONFIG_SCSI_CONSTANTS static const char * const driverbyte_table[]={ -"DRIVER_OK", "DRIVER_BUSY", "DRIVER_SOFT", "DRIVER_MEDIA", "DRIVER_ERROR", +"DRIVER_OK", "DRIVER_BUSY", "DRIVER_SOFT", "DRIVER_MEDIA", "DRIVER_ERROR", "DRIVER_INVALID", "DRIVER_TIMEOUT", "DRIVER_HARD", "DRIVER_SENSE"}; -#define NUM_DRIVERBYTE_STRS (sizeof(driverbyte_table) / sizeof(const char *)) +#define NUM_DRIVERBYTE_STRS ARRAY_SIZE(driverbyte_table) static const char * const driversuggest_table[]={"SUGGEST_OK", "SUGGEST_RETRY", "SUGGEST_ABORT", "SUGGEST_REMAP", "SUGGEST_DIE", "SUGGEST_5", "SUGGEST_6", "SUGGEST_7", "SUGGEST_SENSE"}; -#define NUM_SUGGEST_STRS (sizeof(driversuggest_table) / sizeof(const char *)) +#define NUM_SUGGEST_STRS ARRAY_SIZE(driversuggest_table) void scsi_print_driverbyte(int scsiresult) { diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c index 310d2f48866..c5108c8c887 100644 --- a/drivers/scsi/dtc.c +++ b/drivers/scsi/dtc.c @@ -145,35 +145,35 @@ static struct override { 0, IRQ_AUTO}}; #endif -#define NO_OVERRIDES (sizeof(overrides) / sizeof(struct override)) +#define NO_OVERRIDES ARRAY_SIZE(overrides) static struct base { unsigned long address; int noauto; -} bases[] __initdata = { - { 0xcc000, 0 }, - { 0xc8000, 0 }, - { 0xdc000, 0 }, +} bases[] __initdata = { + { 0xcc000, 0 }, + { 0xc8000, 0 }, + { 0xdc000, 0 }, { 0xd8000, 0 } }; -#define NO_BASES (sizeof (bases) / sizeof (struct base)) +#define NO_BASES ARRAY_SIZE(bases) static const struct signature { const char *string; int offset; -} signatures[] = { +} signatures[] = { {"DATA TECHNOLOGY CORPORATION BIOS", 0x25}, }; -#define NO_SIGNATURES (sizeof (signatures) / sizeof (struct signature)) +#define NO_SIGNATURES ARRAY_SIZE(signatures) #ifndef MODULE /* * Function : dtc_setup(char *str, int *ints) * * Purpose : LILO command line initialization of the overrides array, - * + * * Inputs : str - unused, ints - array of integer parameters with ints[0] * equal to the number of ints. * diff --git a/drivers/scsi/fd_mcs.c b/drivers/scsi/fd_mcs.c index cca485a2b43..70a1606bd58 100644 --- a/drivers/scsi/fd_mcs.c +++ b/drivers/scsi/fd_mcs.c @@ -279,7 +279,7 @@ static struct fd_mcs_adapters_struct fd_mcs_adapters[] = { 2}, }; -#define FD_BRDS sizeof(fd_mcs_adapters)/sizeof(struct fd_mcs_adapters_struct) +#define FD_BRDS ARRAY_SIZE(fd_mcs_adapters) static irqreturn_t fd_mcs_intr(int irq, void *dev_id, struct pt_regs *regs); diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c index 7334244397d..e16013f0ad6 100644 --- a/drivers/scsi/fdomain.c +++ b/drivers/scsi/fdomain.c @@ -420,10 +420,10 @@ static unsigned long addresses[] = { 0xd0000, 0xe0000, }; -#define ADDRESS_COUNT (sizeof( addresses ) / sizeof( unsigned )) - +#define ADDRESS_COUNT ARRAY_SIZE(addresses) + static unsigned short ports[] = { 0x140, 0x150, 0x160, 0x170 }; -#define PORT_COUNT (sizeof( ports ) / sizeof( unsigned short )) +#define PORT_COUNT ARRAY_SIZE(ports) static unsigned short ints[] = { 3, 5, 10, 11, 12, 14, 15, 0 }; @@ -502,7 +502,7 @@ static struct signature { geometry location are verified). */ }; -#define SIGNATURE_COUNT (sizeof( signatures ) / sizeof( struct signature )) +#define SIGNATURE_COUNT ARRAY_SIZE(signatures) static void print_banner( struct Scsi_Host *shpnt ) { @@ -519,7 +519,7 @@ static void print_banner( struct Scsi_Host *shpnt ) if (bios_minor >= 0) printk("%d", bios_minor); else printk("?."); - + printk( " at 0x%lx using scsi id %d\n", bios_base, shpnt->this_id ); } diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index e6bcfe94934..5f313c93b7a 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -138,10 +138,9 @@ static struct override { [1] __initdata = { { 0,},}; #endif +#define NO_OVERRIDES ARRAY_SIZE(overrides) -#define NO_OVERRIDES (sizeof(overrides) / sizeof(struct override)) - -#ifndef MODULE +#ifndef MODULE /** * internal_setup - handle lilo command string override @@ -210,7 +209,7 @@ static int __init do_NCR5380_setup(char *str) { int ints[10]; - get_options(str, sizeof(ints) / sizeof(int), ints); + get_options(str, ARRAY_SIZE(ints), ints); internal_setup(BOARD_NCR5380, str, ints); return 1; } @@ -218,7 +217,7 @@ static int __init do_NCR5380_setup(char *str) /** * do_NCR53C400_setup - set up entry point * @str: unused - * @ints: integer parameters from kernel setup code + * @ints: integer parameters from kernel setup code * * Setup function invoked at boot to parse the ncr53c400= command * line. @@ -228,7 +227,7 @@ static int __init do_NCR53C400_setup(char *str) { int ints[10]; - get_options(str, sizeof(ints) / sizeof(int), ints); + get_options(str, ARRAY_SIZE(ints), ints); internal_setup(BOARD_NCR53C400, str, ints); return 1; } @@ -236,7 +235,7 @@ static int __init do_NCR53C400_setup(char *str) /** * do_NCR53C400A_setup - set up entry point * @str: unused - * @ints: integer parameters from kernel setup code + * @ints: integer parameters from kernel setup code * * Setup function invoked at boot to parse the ncr53c400a= command * line. @@ -246,7 +245,7 @@ static int __init do_NCR53C400A_setup(char *str) { int ints[10]; - get_options(str, sizeof(ints) / sizeof(int), ints); + get_options(str, ARRAY_SIZE(ints), ints); internal_setup(BOARD_NCR53C400A, str, ints); return 1; } @@ -254,7 +253,7 @@ static int __init do_NCR53C400A_setup(char *str) /** * do_DTC3181E_setup - set up entry point * @str: unused - * @ints: integer parameters from kernel setup code + * @ints: integer parameters from kernel setup code * * Setup function invoked at boot to parse the dtc3181e= command * line. @@ -264,7 +263,7 @@ static int __init do_DTC3181E_setup(char *str) { int ints[10]; - get_options(str, sizeof(ints) / sizeof(int), ints); + get_options(str, ARRAY_SIZE(ints), ints); internal_setup(BOARD_DTC3181E, str, ints); return 1; } diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index e720bb017c1..fc4d9f61cf3 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c @@ -569,8 +569,8 @@ static struct timer_list gdth_timer; #endif #define PTR2USHORT(a) (ushort)(ulong)(a) -#define GDTOFFSOF(a,b) (size_t)&(((a*)0)->b) -#define INDEX_OK(i,t) ((i)b) +#define INDEX_OK(i,t) ((i)hostdata)) #define HADATA(a) (&((gdth_ext_str *)((a)->hostdata))->haext) diff --git a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c index 24eb59e143a..0c6dc31bb14 100644 --- a/drivers/scsi/ibmmca.c +++ b/drivers/scsi/ibmmca.c @@ -1441,7 +1441,7 @@ static int ibmmca_getinfo(char *buf, int slot, void *dev_id) struct Scsi_Host *dev = dev_id; spin_lock_irqsave(dev->host_lock, flags); - + shpnt = dev; /* assign host-structure to local pointer */ len = 0; /* set filled text-buffer index to 0 */ /* get the _special contents of the hostdata structure */ @@ -1456,7 +1456,7 @@ static int ibmmca_getinfo(char *buf, int slot, void *dev_id) /* if the integrated subsystem has been found automatically: */ len += sprintf(buf + len, "Adapter category: integrated\n" "Chip revision level: %d\n" "Chip status: %s\n" "8 kByte NVRAM status: %s\n", ((pos[2] & 0xf0) >> 4), (pos[2] & 1) ? "enabled" : "disabled", (pos[2] & 2) ? "locked" : "accessible"); - } else if ((speciale >= 0) && (speciale < (sizeof(subsys_list) / sizeof(struct subsys_list_struct)))) { + } else if ((speciale >= 0) && (speciale < ARRAY_SIZE(subsys_list))) { /* if the subsystem is a slot adapter */ len += sprintf(buf + len, "Adapter category: slot-card\n" "ROM Segment Address: "); if ((pos[2] & 0xf0) == 0xf0) @@ -1477,16 +1477,16 @@ static int ibmmca_getinfo(char *buf, int slot, void *dev_id) while (len % sizeof(int) != (sizeof(int) - 1)) len += sprintf(buf + len, " "); len += sprintf(buf + len, "\n"); - + spin_unlock_irqrestore(shpnt->host_lock, flags); - + return len; } int ibmmca_detect(struct scsi_host_template * scsi_template) { struct Scsi_Host *shpnt; - int port, id, i, j, k, list_size, slot; + int port, id, i, j, k, slot; int devices_on_irq_11 = 0; int devices_on_irq_14 = 0; int IRQ14_registered = 0; @@ -1603,8 +1603,7 @@ int ibmmca_detect(struct scsi_host_template * scsi_template) /* now look for other adapters in MCA slots, */ /* determine the number of known IBM-SCSI-subsystem types */ /* see the pos[2] dependence to get the adapter port-offset. */ - list_size = sizeof(subsys_list) / sizeof(struct subsys_list_struct); - for (i = 0; i < list_size; i++) { + for (i = 0; i < ARRAY_SIZE(subsys_list); i++) { /* scan each slot for a fitting adapter id */ slot = 0; /* start at slot 0 */ while ((slot = mca_find_adapter(subsys_list[i].mca_id, slot)) @@ -1669,8 +1668,7 @@ int ibmmca_detect(struct scsi_host_template * scsi_template) /* now check for SCSI-adapters, mapped to the integrated SCSI * area. E.g. a W/Cache in MCA-slot 9(!). Do the check correct here, * as this is a known effect on some models 95xx. */ - list_size = sizeof(subsys_list) / sizeof(struct subsys_list_struct); - for (i = 0; i < list_size; i++) { + for (i = 0; i < ARRAY_SIZE(subsys_list); i++) { /* scan each slot for a fitting adapter id */ slot = mca_find_adapter(subsys_list[i].mca_id, MCA_INTEGSCSI); if (slot != MCA_NOTFOUND) { /* scan through all slots */ diff --git a/drivers/scsi/in2000.c b/drivers/scsi/in2000.c index 89a57a62e8c..883bc92b4d9 100644 --- a/drivers/scsi/in2000.c +++ b/drivers/scsi/in2000.c @@ -1809,7 +1809,7 @@ static int in2000_abort(Scsi_Cmnd * cmd) #define MAX_IN2000_HOSTS 3 -#define MAX_SETUP_ARGS (sizeof(setup_args) / sizeof(char *)) +#define MAX_SETUP_ARGS ARRAY_SIZE(setup_args) #define SETUP_BUFFER_SIZE 200 static char setup_buffer[SETUP_BUFFER_SIZE]; static char setup_used[MAX_SETUP_ARGS]; diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c index 0cc7f65b584..913ba95f85b 100644 --- a/drivers/scsi/initio.c +++ b/drivers/scsi/initio.c @@ -154,7 +154,6 @@ static unsigned int i91u_debug = DEBUG_DEFAULT; #endif -#define TULSZ(sz) (sizeof(sz) / sizeof(sz[0])) #define TUL_RDWORD(x,y) (short)(inl((int)((ULONG)((ULONG)x+(UCHAR)y)) )) typedef struct PCI_ID_Struc { @@ -2771,7 +2770,7 @@ static int tul_NewReturnNumberOfAdapters(void) init_i91uAdapter_table(); - for (i = 0; i < TULSZ(i91u_pci_devices); i++) + for (i = 0; i < ARRAY_SIZE(i91u_pci_devices); i++) { while ((pDev = pci_find_device(i91u_pci_devices[i].vendor_id, i91u_pci_devices[i].device_id, pDev)) != NULL) { if (pci_enable_device(pDev)) diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index 350c08c6088..5353b28b293 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c @@ -556,7 +556,7 @@ ips_setup(char *ips_str) * We now have key/value pairs. * Update the variables */ - for (i = 0; i < (sizeof (options) / sizeof (options[0])); i++) { + for (i = 0; i < ARRAY_SIZE(options); i++) { if (strnicmp (key, options[i].option_name, strlen(options[i].option_name)) == 0) { diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index e3bd4bc339f..ce0ba3a174f 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c @@ -5492,7 +5492,7 @@ static int __init osst_setup (char *str) char *stp; stp = get_options(str, ARRAY_SIZE(ints), ints); - + if (ints[0] > 0) { for (i = 0; i < ints[0] && i < ARRAY_SIZE(parms); i++) *parms[i].val = ints[i + 1]; @@ -5507,7 +5507,7 @@ static int __init osst_setup (char *str) break; } } - if (i >= sizeof(parms) / sizeof(struct osst_dev_parm)) + if (i >= ARRAY_SIZE(parms)) printk(KERN_INFO "osst :I: Illegal parameter in '%s'\n", stp); stp = strchr(stp, ','); diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c index f09e94af9ad..1bf96ed8f93 100644 --- a/drivers/scsi/pas16.c +++ b/drivers/scsi/pas16.c @@ -156,7 +156,7 @@ static int default_irqs[] __initdata = static struct override { unsigned short io_port; int irq; -} overrides +} overrides #ifdef PAS16_OVERRIDE [] __initdata = PAS16_OVERRIDE; #else @@ -164,19 +164,19 @@ static struct override { {0,IRQ_AUTO}}; #endif -#define NO_OVERRIDES (sizeof(overrides) / sizeof(struct override)) +#define NO_OVERRIDES ARRAY_SIZE(overrides) static struct base { unsigned short io_port; int noauto; -} bases[] __initdata = +} bases[] __initdata = { {PAS16_DEFAULT_BASE_1, 0}, {PAS16_DEFAULT_BASE_2, 0}, {PAS16_DEFAULT_BASE_3, 0}, {PAS16_DEFAULT_BASE_4, 0} }; -#define NO_BASES (sizeof (bases) / sizeof (struct base)) +#define NO_BASES ARRAY_SIZE(bases) static const unsigned short pas16_offset[ 8 ] = { diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c index 5a48e55f941..77bb2351500 100644 --- a/drivers/scsi/qla1280.c +++ b/drivers/scsi/qla1280.c @@ -4239,15 +4239,12 @@ qla1280_get_token(char *str) { char *sep; long ret = -1; - int i, len; - - len = sizeof(setup_token)/sizeof(struct setup_tokens); + int i; sep = strchr(str, ':'); if (sep) { - for (i = 0; i < len; i++){ - + for (i = 0; i < ARRAY_SIZE(setup_token); i++) { if (!strncmp(setup_token[i].token, str, (sep - str))) { ret = setup_token[i].val; break; diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c index c7e78dcf09d..00f4b846360 100644 --- a/drivers/scsi/qlogicpti.c +++ b/drivers/scsi/qlogicpti.c @@ -132,7 +132,7 @@ static const u_char mbox_param[] = { PACKB(0, 0) /* 0x0042 */ }; -#define MAX_MBOX_COMMAND (sizeof(mbox_param)/sizeof(u_short)) +#define MAX_MBOX_COMMAND ARRAY_SIZE(mbox_param) /* queue length's _must_ be power of two: */ #define QUEUE_DEPTH(in, out, ql) ((in - out) & (ql)) diff --git a/drivers/scsi/raid_class.c b/drivers/scsi/raid_class.c index 50c398aab55..327b33a57b0 100644 --- a/drivers/scsi/raid_class.c +++ b/drivers/scsi/raid_class.c @@ -131,7 +131,7 @@ static const char *raid_state_name(enum raid_state state) int i; char *name = NULL; - for (i = 0; i < sizeof(raid_states)/sizeof(raid_states[0]); i++) { + for (i = 0; i < ARRAY_SIZE(raid_states); i++) { if (raid_states[i].value == state) { name = raid_states[i].name; break; @@ -161,7 +161,7 @@ static const char *raid_level_name(enum raid_level level) int i; char *name = NULL; - for (i = 0; i < sizeof(raid_levels)/sizeof(raid_levels[0]); i++) { + for (i = 0; i < ARRAY_SIZE(raid_levels); i++) { if (raid_levels[i].value == level) { name = raid_levels[i].name; break; diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 68d413c444f..3ca7b9d3086 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -30,7 +30,7 @@ #include "scsi_logging.h" -#define SG_MEMPOOL_NR (sizeof(scsi_sg_pools)/sizeof(struct scsi_host_sg_pool)) +#define SG_MEMPOOL_NR ARRAY_SIZE(scsi_sg_pools) #define SG_MEMPOOL_SIZE 32 struct scsi_host_sg_pool { diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index a6fde52946d..5ec7a4fb014 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -39,7 +39,7 @@ const char *scsi_device_state_name(enum scsi_device_state state) int i; char *name = NULL; - for (i = 0; i < sizeof(sdev_states)/sizeof(sdev_states[0]); i++) { + for (i = 0; i < ARRAY_SIZE(sdev_states); i++) { if (sdev_states[i].value == state) { name = sdev_states[i].name; break; @@ -65,7 +65,7 @@ const char *scsi_host_state_name(enum scsi_host_state state) int i; char *name = NULL; - for (i = 0; i < sizeof(shost_states)/sizeof(shost_states[0]); i++) { + for (i = 0; i < ARRAY_SIZE(shost_states); i++) { if (shost_states[i].value == state) { name = shost_states[i].name; break; @@ -160,7 +160,7 @@ store_shost_state(struct class_device *class_dev, const char *buf, size_t count) struct Scsi_Host *shost = class_to_shost(class_dev); enum scsi_host_state state = 0; - for (i = 0; i < sizeof(shost_states)/sizeof(shost_states[0]); i++) { + for (i = 0; i < ARRAY_SIZE(shost_states); i++) { const int len = strlen(shost_states[i].name); if (strncmp(shost_states[i].name, buf, len) == 0 && buf[len] == '\n') { @@ -466,7 +466,7 @@ store_state_field(struct device *dev, struct device_attribute *attr, const char struct scsi_device *sdev = to_scsi_device(dev); enum scsi_device_state state = 0; - for (i = 0; i < sizeof(sdev_states)/sizeof(sdev_states[0]); i++) { + for (i = 0; i < ARRAY_SIZE(sdev_states); i++) { const int len = strlen(sdev_states[i].name); if (strncmp(sdev_states[i].name, buf, len) == 0 && buf[len] == '\n') { diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 95c5478dcdf..f2db7a41cf1 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -50,7 +50,7 @@ static const char *get_fc_##title##_name(enum table_type table_key) \ int i; \ char *name = NULL; \ \ - for (i = 0; i < sizeof(table)/sizeof(table[0]); i++) { \ + for (i = 0; i < ARRAY_SIZE(table); i++) { \ if (table[i].value == table_key) { \ name = table[i].name; \ break; \ @@ -65,7 +65,7 @@ static int get_fc_##title##_match(const char *table_key, \ { \ int i; \ \ - for (i = 0; i < sizeof(table)/sizeof(table[0]); i++) { \ + for (i = 0; i < ARRAY_SIZE(table); i++) { \ if (strncmp(table_key, table[i].name, \ table[i].matchlen) == 0) { \ *value = table[i].value; \ @@ -140,7 +140,7 @@ get_fc_##title##_names(u32 table_key, char *buf) \ ssize_t len = 0; \ int i; \ \ - for (i = 0; i < sizeof(table)/sizeof(table[0]); i++) { \ + for (i = 0; i < ARRAY_SIZE(table); i++) { \ if (table[i].value & table_key) { \ len += sprintf(buf + len, "%s%s", \ prefix, table[i].name); \ diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index 8b6d65e21ba..ce4f806bd8e 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -65,7 +65,7 @@ get_sas_##title##_names(u32 table_key, char *buf) \ ssize_t len = 0; \ int i; \ \ - for (i = 0; i < sizeof(table)/sizeof(table[0]); i++) { \ + for (i = 0; i < ARRAY_SIZE(table); i++) { \ if (table[i].value & table_key) { \ len += sprintf(buf + len, "%s%s", \ prefix, table[i].name); \ @@ -83,7 +83,7 @@ get_sas_##title##_names(u32 table_key, char *buf) \ ssize_t len = 0; \ int i; \ \ - for (i = 0; i < sizeof(table)/sizeof(table[0]); i++) { \ + for (i = 0; i < ARRAY_SIZE(table); i++) { \ if (table[i].value == table_key) { \ len += sprintf(buf + len, "%s", \ table[i].name); \ diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index 780aaedcbce..5829f97a206 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c @@ -146,7 +146,7 @@ static inline const char *spi_signal_to_string(enum spi_signal_type type) { int i; - for (i = 0; i < sizeof(signal_types)/sizeof(signal_types[0]); i++) { + for (i = 0; i < ARRAY_SIZE(signal_types); i++) { if (type == signal_types[i].value) return signal_types[i].name; } @@ -156,7 +156,7 @@ static inline enum spi_signal_type spi_signal_to_value(const char *name) { int i, len; - for (i = 0; i < sizeof(signal_types)/sizeof(signal_types[0]); i++) { + for (i = 0; i < ARRAY_SIZE(signal_types); i++) { len = strlen(signal_types[i].name); if (strncmp(name, signal_types[i].name, len) == 0 && (name[len] == '\n' || name[len] == '\0')) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index a112e49e946..35419901124 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -175,7 +175,7 @@ static ssize_t sd_store_cache_type(struct class_device *cdev, const char *buf, * it's not worth the risk */ return -EINVAL; - for (i = 0; i < sizeof(sd_cache_types)/sizeof(sd_cache_types[0]); i++) { + for (i = 0; i < ARRAY_SIZE(sd_cache_types); i++) { const int len = strlen(sd_cache_types[i]); if (strncmp(sd_cache_types[i], buf, len) == 0 && buf[len] == '\n') { diff --git a/drivers/scsi/seagate.c b/drivers/scsi/seagate.c index 0ff83ddf13f..7fa4da4ea64 100644 --- a/drivers/scsi/seagate.c +++ b/drivers/scsi/seagate.c @@ -312,7 +312,7 @@ static Signature __initdata signatures[] = { {"IBM F1 V1.2009/22/93", 5, 25, FD}, }; -#define NUM_SIGNATURES (sizeof(signatures) / sizeof(Signature)) +#define NUM_SIGNATURES ARRAY_SIZE(signatures) #endif /* n OVERRIDE */ /* @@ -457,7 +457,7 @@ int __init seagate_st0x_detect (struct scsi_host_template * tpnt) * space for the on-board RAM instead. */ - for (i = 0; i < (sizeof (seagate_bases) / sizeof (unsigned int)); ++i) { + for (i = 0; i < ARRAY_SIZE(seagate_bases); ++i) { void __iomem *p = ioremap(seagate_bases[i], 0x2000); if (!p) continue; diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index b098942445e..98b9312ba8d 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -2635,8 +2635,7 @@ static int sg_proc_init(void) { int k, mask; - int num_leaves = - sizeof (sg_proc_leaf_arr) / sizeof (sg_proc_leaf_arr[0]); + int num_leaves = ARRAY_SIZE(sg_proc_leaf_arr); struct proc_dir_entry *pdep; struct sg_proc_leaf * leaf; @@ -2661,8 +2660,7 @@ static void sg_proc_cleanup(void) { int k; - int num_leaves = - sizeof (sg_proc_leaf_arr) / sizeof (sg_proc_leaf_arr[0]); + int num_leaves = ARRAY_SIZE(sg_proc_leaf_arr); if (!sg_proc_sgp) return; diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index d40e7c871c3..2691248b2cb 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -3839,7 +3839,7 @@ static int __init st_setup(char *str) break; } } - if (i >= sizeof(parms) / sizeof(struct st_dev_parm)) + if (i >= ARRAY_SIZE(parms)) printk(KERN_WARNING "st: invalid parameter in '%s'\n", stp); stp = strchr(stp, ','); diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c index a671bdc0745..940fa1e6f99 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.c +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c @@ -1276,8 +1276,7 @@ static struct sym_chip sym_dev_table[] = { FE_RAM|FE_IO256|FE_LEDC} }; -#define sym_num_devs \ - (sizeof(sym_dev_table) / sizeof(sym_dev_table[0])) +#define sym_num_devs (ARRAY_SIZE(sym_dev_table)) /* * Look up the chip table. diff --git a/drivers/scsi/t128.c b/drivers/scsi/t128.c index 21305fc9147..a24f661b027 100644 --- a/drivers/scsi/t128.c +++ b/drivers/scsi/t128.c @@ -126,15 +126,15 @@ static struct override { unsigned long address; int irq; -} overrides +} overrides #ifdef T128_OVERRIDE [] __initdata = T128_OVERRIDE; #else - [4] __initdata = {{0, IRQ_AUTO}, {0, IRQ_AUTO}, + [4] __initdata = {{0, IRQ_AUTO}, {0, IRQ_AUTO}, {0 ,IRQ_AUTO}, {0, IRQ_AUTO}}; #endif -#define NO_OVERRIDES (sizeof(overrides) / sizeof(struct override)) +#define NO_OVERRIDES ARRAY_SIZE(overrides) static struct base { unsigned int address; @@ -143,7 +143,7 @@ static struct base { { 0xcc000, 0}, { 0xc8000, 0}, { 0xdc000, 0}, { 0xd8000, 0} }; -#define NO_BASES (sizeof (bases) / sizeof (struct base)) +#define NO_BASES ARRAY_SIZE(bases) static struct signature { const char *string; @@ -152,7 +152,7 @@ static struct signature { {"TSROM: SCSI BIOS, Version 1.12", 0x36}, }; -#define NO_SIGNATURES (sizeof (signatures) / sizeof (struct signature)) +#define NO_SIGNATURES ARRAY_SIZE(signatures) /* * Function : t128_setup(char *str, int *ints) diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c index d8a72609a31..9341703dee0 100644 --- a/drivers/scsi/wd33c93.c +++ b/drivers/scsi/wd33c93.c @@ -1701,7 +1701,7 @@ wd33c93_abort(struct scsi_cmnd * cmd) } #define MAX_WD33C93_HOSTS 4 -#define MAX_SETUP_ARGS ((int)(sizeof(setup_args) / sizeof(char *))) +#define MAX_SETUP_ARGS ARRAY_SIZE(setup_args) #define SETUP_BUFFER_SIZE 200 static char setup_buffer[SETUP_BUFFER_SIZE]; static char setup_used[MAX_SETUP_ARGS]; diff --git a/drivers/scsi/wd7000.c b/drivers/scsi/wd7000.c index fb54a87a80a..e55f0ee7e7e 100644 --- a/drivers/scsi/wd7000.c +++ b/drivers/scsi/wd7000.c @@ -267,7 +267,7 @@ static const long wd7000_biosaddr[] = { 0xc0000, 0xc2000, 0xc4000, 0xc6000, 0xc8000, 0xca000, 0xcc000, 0xce000, 0xd0000, 0xd2000, 0xd4000, 0xd6000, 0xd8000, 0xda000, 0xdc000, 0xde000 }; -#define NUM_ADDRS (sizeof(wd7000_biosaddr)/sizeof(long)) +#define NUM_ADDRS ARRAY_SIZE(wd7000_biosaddr) static const unsigned short wd7000_iobase[] = { 0x0300, 0x0308, 0x0310, 0x0318, 0x0320, 0x0328, 0x0330, 0x0338, @@ -275,13 +275,13 @@ static const unsigned short wd7000_iobase[] = { 0x0380, 0x0388, 0x0390, 0x0398, 0x03a0, 0x03a8, 0x03b0, 0x03b8, 0x03c0, 0x03c8, 0x03d0, 0x03d8, 0x03e0, 0x03e8, 0x03f0, 0x03f8 }; -#define NUM_IOPORTS (sizeof(wd7000_iobase)/sizeof(unsigned short)) +#define NUM_IOPORTS ARRAY_SIZE(wd7000_iobase) static const short wd7000_irq[] = { 3, 4, 5, 7, 9, 10, 11, 12, 14, 15 }; -#define NUM_IRQS (sizeof(wd7000_irq)/sizeof(short)) +#define NUM_IRQS ARRAY_SIZE(wd7000_irq) static const short wd7000_dma[] = { 5, 6, 7 }; -#define NUM_DMAS (sizeof(wd7000_dma)/sizeof(short)) +#define NUM_DMAS ARRAY_SIZE(wd7000_dma) /* * The following is set up by wd7000_detect, and used thereafter for @@ -317,7 +317,7 @@ static Config configs[] = { {7, 6, 0x350, BUS_ON, BUS_OFF}, /* My configuration (Zaga) */ {-1, -1, 0x0, BUS_ON, BUS_OFF} /* Empty slot */ }; -#define NUM_CONFIGS (sizeof(configs)/sizeof(Config)) +#define NUM_CONFIGS ARRAY_SIZE(configs) /* * The following list defines strings to look for in the BIOS that identify @@ -333,7 +333,7 @@ typedef struct signature { static const Signature signatures[] = { {"SSTBIOS", 0x0000d, 7} /* "SSTBIOS" @ offset 0x0000d */ }; -#define NUM_SIGNATURES (sizeof(signatures)/sizeof(Signature)) +#define NUM_SIGNATURES ARRAY_SIZE(signatures) /* -- cgit v1.2.3 From b9f051eb6cc013b90cb6062a1e2502e9c0adf0f4 Mon Sep 17 00:00:00 2001 From: Arthur Othieno Date: Thu, 8 Jun 2006 22:23:45 -0700 Subject: [SCSI] scsi: remove Documentation/scsi/cpqfc.txt cpqfc driver flushed out with: [SCSI] remove broken driver cpqfc (commit ca61f10ab2b874b889e89d14ea09fae2dcccdca6) but somehow Documentation/scsi/cpqfc.txt managed to survive the blast. Signed-off-by: Arthur Othieno Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- Documentation/scsi/00-INDEX | 2 - Documentation/scsi/cpqfc.txt | 272 ------------------------------------------- 2 files changed, 274 deletions(-) delete mode 100644 Documentation/scsi/cpqfc.txt diff --git a/Documentation/scsi/00-INDEX b/Documentation/scsi/00-INDEX index e7da8c3a255..12354830c6b 100644 --- a/Documentation/scsi/00-INDEX +++ b/Documentation/scsi/00-INDEX @@ -30,8 +30,6 @@ aic7xxx.txt - info on driver for Adaptec controllers aic7xxx_old.txt - info on driver for Adaptec controllers, old generation -cpqfc.txt - - info on driver for Compaq Tachyon TS adapters dpti.txt - info on driver for DPT SmartRAID and Adaptec I2O RAID based adapters dtc3x80.txt diff --git a/Documentation/scsi/cpqfc.txt b/Documentation/scsi/cpqfc.txt deleted file mode 100644 index dd33e61c064..00000000000 --- a/Documentation/scsi/cpqfc.txt +++ /dev/null @@ -1,272 +0,0 @@ -Notes for CPQFCTS driver for Compaq Tachyon TS -Fibre Channel Host Bus Adapter, PCI 64-bit, 66MHz -for Linux (RH 6.1, 6.2 kernel 2.2.12-32, 2.2.14-5) -SMP tested -Tested in single and dual HBA configuration, 32 and 64bit busses, -33 and 66MHz. Only supports FC-AL. -SEST size 512 Exchanges (simultaneous I/Os) limited by module kmalloc() - max of 128k bytes contiguous. - -Ver 2.5.4 Oct 03, 2002 - * fixed memcpy of sense buffer in ioctl to copy the smaller defined size -Ver 2.5.3 Aug 01, 2002 - * fix the passthru ioctl to handle the Scsi_Cmnd->request being a pointer -Ver 2.5.1 Jul 30, 2002 - * fix ioctl to pay attention to the specified LUN. -Ver 2.5.0 Nov 29, 2001 - * eliminated io_request_lock. This change makes the driver specific - to the 2.5.x kernels. - * silenced excessively noisy printks. - -Ver 2.1.2 July 23, 2002 - * initialize DumCmnd->lun in cpqfcTS_ioctl (used in fcFindLoggedInPorts as LUN index) - -Ver 2.1.1 Oct 18, 2001 - * reinitialize Cmnd->SCp.sent_command (used to identify commands as - passthrus) on calling scsi_done, since the scsi mid layer does not - use (or reinitialize) this field to prevent subsequent comands from - having it set incorrectly. - -Ver 2.1.0 Aug 27, 2001 - * Revise driver to use new kernel 2.4.x PCI DMA API, instead of - virt_to_bus(). (enables driver to work w/ ia64 systems with >2Gb RAM.) - Rework main scatter-gather code to handle cases where SG element - lengths are larger than 0x7FFFF bytes and use as many scatter - gather pages as necessary. (Steve Cameron) - * Makefile changes to bring cpqfc into line w/ rest of SCSI drivers - (thanks to Keith Owens) - -Ver 2.0.5 Aug 06, 2001 - * Reject non-existent luns in the driver rather than letting the - hardware do it. (some HW behaves differently than others in this area.) - * Changed Makefile to rely on "make dep" instead of explicit dependencies - * ifdef'ed out fibre channel analyzer triggering debug code - * fixed a jiffies wrapping issue - -Ver 2.0.4 Aug 01, 2001 - * Incorporated fix for target device reset from Steeleye - * Fixed passthrough ioctl so it doesn't hang. - * Fixed hang in launch_FCworker_thread() that occurred on some machines. - * Avoid problem when number of volumes in a single cabinet > 8 - -Ver 2.0.2 July 23, 2001 - Changed the semiphore changes so the driver would compile in 2.4.7. - This version is for 2.4.7 and beyond. - -Ver 2.0.1 May 7, 2001 - Merged version 1.3.6 fixes into version 2.0.0. - -Ver 2.0.0 May 7, 2001 - Fixed problem so spinlock is being initialized to UNLOCKED. - Fixed updated driver so it compiles in the 2.4 tree. - - Ver 1.3.6 Feb 27, 2001 - Added Target_Device_Reset function for SCSI error handling - Fixed problem with not reseting addressing mode after implicit logout - - -Ver 1.3.4 Sep 7, 2000 - Added Modinfo information - Fixed problem with statically linking the driver - -Ver 1.3.3, Aug 23, 2000 - Fixed device/function number in ioctl - -Ver 1.3.2, July 27, 2000 - Add include for Alpha compile on 2.2.14 kernel (cpq*i2c.c) - Change logic for different FCP-RSP sense_buffer location for HSG80 target - And search for Agilent Tachyon XL2 HBAs (not finished! - in test) - -Tested with -(storage): - Compaq RA-4x000, RAID firmware ver 2.40 - 2.54 - Seagate FC drives model ST39102FC, rev 0006 - Hitachi DK31CJ-72FC rev J8A8 - IBM DDYF-T18350R rev F60K - Compaq FC-SCSI bridge w/ DLT 35/70 Gb DLT (tape) -(servers): - Compaq PL-1850R - Compaq PL-6500 Xeon (400MHz) - Compaq PL-8500 (500MHz, 66MHz, 64bit PCI) - Compaq Alpha DS20 (RH 6.1) -(hubs): - Vixel Rapport 1000 (7-port "dumb") - Gadzoox Gibralter (12-port "dumb") - Gadzoox Capellix 2000, 3000 -(switches): - Brocade 2010, 2400, 2800, rev 2.0.3a (& later) - Gadzoox 3210 (Fabric blade beta) - Vixel 7100 (Fabric beta firmare - known hot plug issues) -using "qa_test" (esp. io_test script) suite modified from Unix tests. - -Installation: -make menuconfig - (select SCSI low-level, Compaq FC HBA) -make modules -make modules_install - -e.g. insmod -f cpqfc - -Due to Fabric/switch delays, driver requires 4 seconds -to initialize. If adapters are found, there will be a entries at -/proc/scsi/cpqfcTS/* - -sample contents of startup messages - -************************* - scsi_register allocating 3596 bytes for CPQFCHBA - ioremap'd Membase: c887e600 - HBA Tachyon RevId 1.2 -Allocating 119808 for 576 Exchanges @ c0dc0000 -Allocating 112904 for LinkQ @ c0c20000 (576 elements) -Allocating 110600 for TachSEST for 512 Exchanges - cpqfcTS: writing IMQ BASE 7C0000h PI 7C4000h - cpqfcTS: SEST c0e40000(virt): Wrote base E40000h @ c887e740 -cpqfcTS: New FC port 0000E8h WWN: 500507650642499D SCSI Chan/Trgt 0/0 -cpqfcTS: New FC port 0000EFh WWN: 50000E100000D5A6 SCSI Chan/Trgt 0/1 -cpqfcTS: New FC port 0000E4h WWN: 21000020370097BB SCSI Chan/Trgt 0/2 -cpqfcTS: New FC port 0000E2h WWN: 2100002037009946 SCSI Chan/Trgt 0/3 -cpqfcTS: New FC port 0000E1h WWN: 21000020370098FE SCSI Chan/Trgt 0/4 -cpqfcTS: New FC port 0000E0h WWN: 21000020370097B2 SCSI Chan/Trgt 0/5 -cpqfcTS: New FC port 0000DCh WWN: 2100002037006CC1 SCSI Chan/Trgt 0/6 -cpqfcTS: New FC port 0000DAh WWN: 21000020370059F6 SCSI Chan/Trgt 0/7 -cpqfcTS: New FC port 00000Fh WWN: 500805F1FADB0E20 SCSI Chan/Trgt 0/8 -cpqfcTS: New FC port 000008h WWN: 500805F1FADB0EBA SCSI Chan/Trgt 0/9 -cpqfcTS: New FC port 000004h WWN: 500805F1FADB1EB9 SCSI Chan/Trgt 0/10 -cpqfcTS: New FC port 000002h WWN: 500805F1FADB1ADE SCSI Chan/Trgt 0/11 -cpqfcTS: New FC port 000001h WWN: 500805F1FADBA2CA SCSI Chan/Trgt 0/12 -scsi4 : Compaq FibreChannel HBA Tachyon TS HPFC-5166A/1.2: WWN 500508B200193F50 - on PCI bus 0 device 0xa0fc irq 5 IObaseL 0x3400, MEMBASE 0xc6ef8600 -PCI bus width 32 bits, bus speed 33 MHz -FCP-SCSI Driver v1.3.0 -GBIC detected: Short-wave. LPSM 0h Monitor -scsi : 5 hosts. - Vendor: IBM Model: DDYF-T18350R Rev: F60K - Type: Direct-Access ANSI SCSI revision: 03 -Detected scsi disk sdb at scsi4, channel 0, id 0, lun 0 - Vendor: HITACHI Model: DK31CJ-72FC Rev: J8A8 - Type: Direct-Access ANSI SCSI revision: 02 -Detected scsi disk sdc at scsi4, channel 0, id 1, lun 0 - Vendor: SEAGATE Model: ST39102FC Rev: 0006 - Type: Direct-Access ANSI SCSI revision: 02 -Detected scsi disk sdd at scsi4, channel 0, id 2, lun 0 - Vendor: SEAGATE Model: ST39102FC Rev: 0006 - Type: Direct-Access ANSI SCSI revision: 02 -Detected scsi disk sde at scsi4, channel 0, id 3, lun 0 - Vendor: SEAGATE Model: ST39102FC Rev: 0006 - Type: Direct-Access ANSI SCSI revision: 02 -Detected scsi disk sdf at scsi4, channel 0, id 4, lun 0 - Vendor: SEAGATE Model: ST39102FC Rev: 0006 - Type: Direct-Access ANSI SCSI revision: 02 -Detected scsi disk sdg at scsi4, channel 0, id 5, lun 0 - Vendor: SEAGATE Model: ST39102FC Rev: 0006 - Type: Direct-Access ANSI SCSI revision: 02 -Detected scsi disk sdh at scsi4, channel 0, id 6, lun 0 - Vendor: SEAGATE Model: ST39102FC Rev: 0006 - Type: Direct-Access ANSI SCSI revision: 02 -Detected scsi disk sdi at scsi4, channel 0, id 7, lun 0 - Vendor: COMPAQ Model: LOGICAL VOLUME Rev: 2.48 - Type: Direct-Access ANSI SCSI revision: 02 -Detected scsi disk sdj at scsi4, channel 0, id 8, lun 0 - Vendor: COMPAQ Model: LOGICAL VOLUME Rev: 2.48 - Type: Direct-Access ANSI SCSI revision: 02 -Detected scsi disk sdk at scsi4, channel 0, id 8, lun 1 - Vendor: COMPAQ Model: LOGICAL VOLUME Rev: 2.40 - Type: Direct-Access ANSI SCSI revision: 02 -Detected scsi disk sdl at scsi4, channel 0, id 9, lun 0 - Vendor: COMPAQ Model: LOGICAL VOLUME Rev: 2.40 - Type: Direct-Access ANSI SCSI revision: 02 -Detected scsi disk sdm at scsi4, channel 0, id 9, lun 1 - Vendor: COMPAQ Model: LOGICAL VOLUME Rev: 2.54 - Type: Direct-Access ANSI SCSI revision: 02 -Detected scsi disk sdn at scsi4, channel 0, id 10, lun 0 - Vendor: COMPAQ Model: LOGICAL VOLUME Rev: 2.54 - Type: Direct-Access ANSI SCSI revision: 02 -Detected scsi disk sdo at scsi4, channel 0, id 11, lun 0 - Vendor: COMPAQ Model: LOGICAL VOLUME Rev: 2.54 - Type: Direct-Access ANSI SCSI revision: 02 -Detected scsi disk sdp at scsi4, channel 0, id 11, lun 1 - Vendor: COMPAQ Model: LOGICAL VOLUME Rev: 2.54 - Type: Direct-Access ANSI SCSI revision: 02 -Detected scsi disk sdq at scsi4, channel 0, id 12, lun 0 - Vendor: COMPAQ Model: LOGICAL VOLUME Rev: 2.54 - Type: Direct-Access ANSI SCSI revision: 02 -Detected scsi disk sdr at scsi4, channel 0, id 12, lun 1 -resize_dma_pool: unknown device type 12 -resize_dma_pool: unknown device type 12 -SCSI device sdb: hdwr sector= 512 bytes. Sectors= 35843670 [17501 MB] [17.5 GB] - sdb: sdb1 -SCSI device sdc: hdwr sector= 512 bytes. Sectors= 144410880 [70513 MB] [70.5 GB] - sdc: sdc1 -SCSI device sdd: hdwr sector= 512 bytes. Sectors= 17783240 [8683 MB] [8.7 GB] - sdd: sdd1 -SCSI device sde: hdwr sector= 512 bytes. Sectors= 17783240 [8683 MB] [8.7 GB] - sde: sde1 -SCSI device sdf: hdwr sector= 512 bytes. Sectors= 17783240 [8683 MB] [8.7 GB] - sdf: sdf1 -SCSI device sdg: hdwr sector= 512 bytes. Sectors= 17783240 [8683 MB] [8.7 GB] - sdg: sdg1 -SCSI device sdh: hdwr sector= 512 bytes. Sectors= 17783240 [8683 MB] [8.7 GB] - sdh: sdh1 -SCSI device sdi: hdwr sector= 512 bytes. Sectors= 17783240 [8683 MB] [8.7 GB] - sdi: sdi1 -SCSI device sdj: hdwr sector= 512 bytes. Sectors= 2056160 [1003 MB] [1.0 GB] - sdj: sdj1 -SCSI device sdk: hdwr sector= 512 bytes. Sectors= 2052736 [1002 MB] [1.0 GB] - sdk: sdk1 -SCSI device sdl: hdwr sector= 512 bytes. Sectors= 17764320 [8673 MB] [8.7 GB] - sdl: sdl1 -SCSI device sdm: hdwr sector= 512 bytes. Sectors= 8380320 [4091 MB] [4.1 GB] - sdm: sdm1 -SCSI device sdn: hdwr sector= 512 bytes. Sectors= 17764320 [8673 MB] [8.7 GB] - sdn: sdn1 -SCSI device sdo: hdwr sector= 512 bytes. Sectors= 17764320 [8673 MB] [8.7 GB] - sdo: sdo1 -SCSI device sdp: hdwr sector= 512 bytes. Sectors= 17764320 [8673 MB] [8.7 GB] - sdp: sdp1 -SCSI device sdq: hdwr sector= 512 bytes. Sectors= 2056160 [1003 MB] [1.0 GB] - sdq: sdq1 -SCSI device sdr: hdwr sector= 512 bytes. Sectors= 2052736 [1002 MB] [1.0 GB] - sdr: sdr1 - -************************* - -If a GBIC of type Short-wave, Long-wave, or Copper is detected, it will -print out; otherwise, "none" is displayed. If the cabling is correct -and a loop circuit is completed, you should see "Monitor"; otherwise, -"LoopFail" (on open circuit) or some LPSM number/state with bit 3 set. - - -ERRATA: -1. Normally, Linux Scsi queries FC devices with INQUIRY strings. All LUNs -found according to INQUIRY should get READ commands at sector 0 to find -partition table, etc. Older kernels only query the first 4 devices. Some -Linux kernels only look for one LUN per target (i.e. FC device). - -2. Physically removing a device, or a malfunctioning system which hides a -device, leads to a 30-second timeout and subsequent _abort call. -In some process contexts, this will hang the kernel (crashing the system). -Single bit errors in frames and virtually all hot plugging events are -gracefully handled with internal driver timer and Abort processing. - -3. Some SCSI drives with error conditions will not handle the 7 second timeout -in this software driver, leading to infinite retries on timed out SCSI commands. -The 7 secs balances the need to quickly recover from lost frames (esp. on sequence -initiatives) and time needed by older/slower/error-state drives in responding. -This can be easily changed in "Exchanges[].timeOut". - -4. Due to the nature of FC soft addressing, there is no assurance that the -same LUNs (drives) will have the same path (e.g. /dev/sdb1) from one boot to -next. Dynamic soft address changes (i.e. 24-bit FC port_id) are -supported during run time (e.g. due to hot plug event) by the use of WWN to -SCSI Nexus (channel/target/LUN) mapping. - -5. Compaq RA4x00 firmware version 2.54 and later supports SSP (Selective -Storage Presentation), which maps LUNs to a WWN. If RA4x00 firmware prior -2.54 (e.g. older controller) is used, or the FC HBA is replaced (another WWN -is used), logical volumes on the RA4x00 will no longer be visible. - - -Send questions/comments to: -Amy Vanzant-Hodge (fibrechannel@compaq.com) - -- cgit v1.2.3 From b2d8bfe18578c4e50e8ba52011c9b260a1b51dac Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sat, 10 Jun 2006 10:49:07 -0500 Subject: [SCSI] aic7xxx: expose the bus setting to sysfs Read the transciever register and display in the host transport properties. I'm still not entirely sure what this does for multiple transciever adapters (like some 160 ones) however, I suspect it displays the transciever state of the switchable bus segment. Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx/aic7xxx.h | 1 + drivers/scsi/aic7xxx/aic7xxx_osm.c | 17 ++++++++ drivers/scsi/aic7xxx/aic7xxx_pci.c | 81 ++++++++++++++++++++++++++++++++++---- 3 files changed, 92 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/aic7xxx/aic7xxx.h b/drivers/scsi/aic7xxx/aic7xxx.h index e24e6067401..62ff8c3dc2b 100644 --- a/drivers/scsi/aic7xxx/aic7xxx.h +++ b/drivers/scsi/aic7xxx/aic7xxx.h @@ -231,6 +231,7 @@ typedef enum { AHC_TARGETMODE = 0x20000, /* Has tested target mode support */ AHC_MULTIROLE = 0x40000, /* Space for two roles at a time */ AHC_REMOVABLE = 0x80000, /* Hot-Swap supported */ + AHC_HVD = 0x100000, /* HVD rather than SE */ AHC_AIC7770_FE = AHC_FENONE, /* * The real 7850 does not support Ultra modes, but there are diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index eadfefdd8d7..debf3e2a079 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -2537,6 +2537,22 @@ static void ahc_linux_set_iu(struct scsi_target *starget, int iu) } #endif +static void ahc_linux_get_signalling(struct Scsi_Host *shost) +{ + struct ahc_softc *ahc = *(struct ahc_softc **)shost->hostdata; + u8 mode = ahc_inb(ahc, SBLKCTL); + + if (mode & ENAB40) + spi_signalling(shost) = SPI_SIGNAL_LVD; + else if (mode & ENAB20) + spi_signalling(shost) = + ahc->features & AHC_HVD ? + SPI_SIGNAL_HVD : + SPI_SIGNAL_SE; + else + spi_signalling(shost) = SPI_SIGNAL_UNKNOWN; +} + static struct spi_function_template ahc_linux_transport_functions = { .set_offset = ahc_linux_set_offset, .show_offset = 1, @@ -2552,6 +2568,7 @@ static struct spi_function_template ahc_linux_transport_functions = { .set_qas = ahc_linux_set_qas, .show_qas = 1, #endif + .get_signalling = ahc_linux_get_signalling, }; diff --git a/drivers/scsi/aic7xxx/aic7xxx_pci.c b/drivers/scsi/aic7xxx/aic7xxx_pci.c index b1156fbd4a1..02fed4a02eb 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_pci.c +++ b/drivers/scsi/aic7xxx/aic7xxx_pci.c @@ -144,16 +144,22 @@ static ahc_device_setup_t ahc_aic785X_setup; static ahc_device_setup_t ahc_aic7860_setup; static ahc_device_setup_t ahc_apa1480_setup; static ahc_device_setup_t ahc_aic7870_setup; +static ahc_device_setup_t ahc_aic7870h_setup; static ahc_device_setup_t ahc_aha394X_setup; +static ahc_device_setup_t ahc_aha394Xh_setup; static ahc_device_setup_t ahc_aha494X_setup; +static ahc_device_setup_t ahc_aha494Xh_setup; static ahc_device_setup_t ahc_aha398X_setup; static ahc_device_setup_t ahc_aic7880_setup; +static ahc_device_setup_t ahc_aic7880h_setup; static ahc_device_setup_t ahc_aha2940Pro_setup; static ahc_device_setup_t ahc_aha394XU_setup; +static ahc_device_setup_t ahc_aha394XUh_setup; static ahc_device_setup_t ahc_aha398XU_setup; static ahc_device_setup_t ahc_aic7890_setup; static ahc_device_setup_t ahc_aic7892_setup; static ahc_device_setup_t ahc_aic7895_setup; +static ahc_device_setup_t ahc_aic7895h_setup; static ahc_device_setup_t ahc_aic7896_setup; static ahc_device_setup_t ahc_aic7899_setup; static ahc_device_setup_t ahc_aha29160C_setup; @@ -225,19 +231,19 @@ struct ahc_pci_identity ahc_pci_ident_table [] = ID_AHA_2944, ID_ALL_MASK, "Adaptec 2944 SCSI adapter", - ahc_aic7870_setup + ahc_aic7870h_setup }, { ID_AHA_3944, ID_ALL_MASK, "Adaptec 3944 SCSI adapter", - ahc_aha394X_setup + ahc_aha394Xh_setup }, { ID_AHA_4944, ID_ALL_MASK, "Adaptec 4944 SCSI adapter", - ahc_aha494X_setup + ahc_aha494Xh_setup }, /* aic7880 based controllers */ { @@ -256,13 +262,13 @@ struct ahc_pci_identity ahc_pci_ident_table [] = ID_AHA_2944U & ID_DEV_VENDOR_MASK, ID_DEV_VENDOR_MASK, "Adaptec 2944 Ultra SCSI adapter", - ahc_aic7880_setup + ahc_aic7880h_setup }, { ID_AHA_3944U & ID_DEV_VENDOR_MASK, ID_DEV_VENDOR_MASK, "Adaptec 3944 Ultra SCSI adapter", - ahc_aha394XU_setup + ahc_aha394XUh_setup }, { ID_AHA_398XU & ID_DEV_VENDOR_MASK, @@ -278,7 +284,7 @@ struct ahc_pci_identity ahc_pci_ident_table [] = ID_AHA_4944U & ID_DEV_VENDOR_MASK, ID_DEV_VENDOR_MASK, "Adaptec 4944 Ultra SCSI adapter", - ahc_aic7880_setup + ahc_aic7880h_setup }, { ID_AHA_2930U & ID_DEV_VENDOR_MASK, @@ -414,7 +420,7 @@ struct ahc_pci_identity ahc_pci_ident_table [] = ID_AHA_3944AU, ID_ALL_MASK, "Adaptec 3944A Ultra SCSI adapter", - ahc_aic7895_setup + ahc_aic7895h_setup }, { ID_AIC7895_ARO, @@ -2120,6 +2126,16 @@ ahc_aic7870_setup(struct ahc_softc *ahc) return (0); } +static int +ahc_aic7870h_setup(struct ahc_softc *ahc) +{ + int error = ahc_aic7870_setup(ahc); + + ahc->features |= AHC_HVD; + + return error; +} + static int ahc_aha394X_setup(struct ahc_softc *ahc) { @@ -2131,6 +2147,16 @@ ahc_aha394X_setup(struct ahc_softc *ahc) return (error); } +static int +ahc_aha394Xh_setup(struct ahc_softc *ahc) +{ + int error = ahc_aha394X_setup(ahc); + + ahc->features |= AHC_HVD; + + return error; +} + static int ahc_aha398X_setup(struct ahc_softc *ahc) { @@ -2153,6 +2179,16 @@ ahc_aha494X_setup(struct ahc_softc *ahc) return (error); } +static int +ahc_aha494Xh_setup(struct ahc_softc *ahc) +{ + int error = ahc_aha494X_setup(ahc); + + ahc->features |= AHC_HVD; + + return error; +} + static int ahc_aic7880_setup(struct ahc_softc *ahc) { @@ -2174,6 +2210,17 @@ ahc_aic7880_setup(struct ahc_softc *ahc) return (0); } +static int +ahc_aic7880h_setup(struct ahc_softc *ahc) +{ + int error = ahc_aic7880_setup(ahc); + + ahc->features |= AHC_HVD; + + return error; +} + + static int ahc_aha2940Pro_setup(struct ahc_softc *ahc) { @@ -2193,6 +2240,16 @@ ahc_aha394XU_setup(struct ahc_softc *ahc) return (error); } +static int +ahc_aha394XUh_setup(struct ahc_softc *ahc) +{ + int error = ahc_aha394XU_setup(ahc); + + ahc->features |= AHC_HVD; + + return error; +} + static int ahc_aha398XU_setup(struct ahc_softc *ahc) { @@ -2291,6 +2348,16 @@ ahc_aic7895_setup(struct ahc_softc *ahc) return (0); } +static int +ahc_aic7895h_setup(struct ahc_softc *ahc) +{ + int error = ahc_aic7895_setup(ahc); + + ahc->features |= AHC_HVD; + + return error; +} + static int ahc_aic7896_setup(struct ahc_softc *ahc) { -- cgit v1.2.3 From 60eef25701d25e99c991dd0f4a9f3832a0c3ad3e Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sat, 10 Jun 2006 10:51:23 -0500 Subject: [SCSI] spi transport: don't allow dt to be set on SE or HVD buses This is really just a belt and braces test. The standards require disks to respond DT not capable on a non-LVD bus ... however, not all disks follow the standards ... Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_spi.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index 5829f97a206..ace49d5bd9c 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c @@ -785,6 +785,7 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) { struct spi_internal *i = to_spi_internal(sdev->host->transportt); struct scsi_target *starget = sdev->sdev_target; + struct Scsi_Host *shost = sdev->host; int len = sdev->inquiry_len; /* first set us up for narrow async */ DV_SET(offset, 0); @@ -844,6 +845,14 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) if (spi_min_period(starget) == 8) DV_SET(pcomp_en, 1); } + /* now that we've done all this, actually check the bus + * signal type (if known). Some devices are stupid on + * a SE bus and still claim they can try LVD only settings */ + if (i->f->get_signalling) + i->f->get_signalling(shost); + if (spi_signalling(shost) == SPI_SIGNAL_SE || + spi_signalling(shost) == SPI_SIGNAL_HVD) + DV_SET(dt, 0); /* Do the read only INQUIRY tests */ spi_dv_retrain(sdev, buffer, buffer + sdev->inquiry_len, spi_dv_device_compare_inquiry); -- cgit v1.2.3 From 80d3ac77a84987d5132726f3d7cef342a280f7d9 Mon Sep 17 00:00:00 2001 From: Michael Reed Date: Wed, 24 May 2006 15:07:09 -0500 Subject: [SCSI] mptfusion: move fc event/reset handling to mptfc Move fibre channel event and reset handling to mptfc. This will result in fewer changes over time that need to be applied to either mptbase.c or mptscsih.c. Signed-off-by: Michael Reed Signed-off-by: James Bottomley --- drivers/message/fusion/mptbase.c | 112 ----------------------- drivers/message/fusion/mptbase.h | 1 - drivers/message/fusion/mptfc.c | 187 +++++++++++++++++++++++++++++++++++++- drivers/message/fusion/mptscsih.c | 21 ----- 4 files changed, 184 insertions(+), 137 deletions(-) diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 164375eea89..330c29080e3 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -1188,7 +1188,6 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) ioc->pcidev = pdev; ioc->diagPending = 0; spin_lock_init(&ioc->diagLock); - spin_lock_init(&ioc->fc_rescan_work_lock); spin_lock_init(&ioc->initializing_hba_lock); /* Initialize the event logging. @@ -1847,14 +1846,6 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) mpt_findImVolumes(ioc); } else if (ioc->bus_type == FC) { - /* - * Pre-fetch FC port WWN and stuff... - * (FCPortPage0_t stuff) - */ - for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { - (void) mptbase_GetFcPortPage0(ioc, ii); - } - if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) && (ioc->lan_cnfg_page0.Header.PageLength == 0)) { /* @@ -4184,108 +4175,6 @@ GetLanConfigPages(MPT_ADAPTER *ioc) return rc; } -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * mptbase_GetFcPortPage0 - Fetch FCPort config Page0. - * @ioc: Pointer to MPT_ADAPTER structure - * @portnum: IOC Port number - * - * Return: 0 for success - * -ENOMEM if no memory available - * -EPERM if not allowed due to ISR context - * -EAGAIN if no msg frames currently available - * -EFAULT for non-successful reply or no reply (timeout) - */ -int -mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum) -{ - ConfigPageHeader_t hdr; - CONFIGPARMS cfg; - FCPortPage0_t *ppage0_alloc; - FCPortPage0_t *pp0dest; - dma_addr_t page0_dma; - int data_sz; - int copy_sz; - int rc; - int count = 400; - - - /* Get FCPort Page 0 header */ - hdr.PageVersion = 0; - hdr.PageLength = 0; - hdr.PageNumber = 0; - hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT; - cfg.cfghdr.hdr = &hdr; - cfg.physAddr = -1; - cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; - cfg.dir = 0; - cfg.pageAddr = portnum; - cfg.timeout = 0; - - if ((rc = mpt_config(ioc, &cfg)) != 0) - return rc; - - if (hdr.PageLength == 0) - return 0; - - data_sz = hdr.PageLength * 4; - rc = -ENOMEM; - ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma); - if (ppage0_alloc) { - - try_again: - memset((u8 *)ppage0_alloc, 0, data_sz); - cfg.physAddr = page0_dma; - cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; - - if ((rc = mpt_config(ioc, &cfg)) == 0) { - /* save the data */ - pp0dest = &ioc->fc_port_page0[portnum]; - copy_sz = min_t(int, sizeof(FCPortPage0_t), data_sz); - memcpy(pp0dest, ppage0_alloc, copy_sz); - - /* - * Normalize endianness of structure data, - * by byte-swapping all > 1 byte fields! - */ - pp0dest->Flags = le32_to_cpu(pp0dest->Flags); - pp0dest->PortIdentifier = le32_to_cpu(pp0dest->PortIdentifier); - pp0dest->WWNN.Low = le32_to_cpu(pp0dest->WWNN.Low); - pp0dest->WWNN.High = le32_to_cpu(pp0dest->WWNN.High); - pp0dest->WWPN.Low = le32_to_cpu(pp0dest->WWPN.Low); - pp0dest->WWPN.High = le32_to_cpu(pp0dest->WWPN.High); - pp0dest->SupportedServiceClass = le32_to_cpu(pp0dest->SupportedServiceClass); - pp0dest->SupportedSpeeds = le32_to_cpu(pp0dest->SupportedSpeeds); - pp0dest->CurrentSpeed = le32_to_cpu(pp0dest->CurrentSpeed); - pp0dest->MaxFrameSize = le32_to_cpu(pp0dest->MaxFrameSize); - pp0dest->FabricWWNN.Low = le32_to_cpu(pp0dest->FabricWWNN.Low); - pp0dest->FabricWWNN.High = le32_to_cpu(pp0dest->FabricWWNN.High); - pp0dest->FabricWWPN.Low = le32_to_cpu(pp0dest->FabricWWPN.Low); - pp0dest->FabricWWPN.High = le32_to_cpu(pp0dest->FabricWWPN.High); - pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount); - pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators); - - /* - * if still doing discovery, - * hang loose a while until finished - */ - if (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) { - if (count-- > 0) { - msleep_interruptible(100); - goto try_again; - } - printk(MYIOC_s_INFO_FMT "Firmware discovery not" - " complete.\n", - ioc->name); - } - } - - pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma); - } - - return rc; -} - /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * mptbase_sas_persist_operation - Perform operation on SAS Persitent Table @@ -6495,7 +6384,6 @@ EXPORT_SYMBOL(mpt_findImVolumes); EXPORT_SYMBOL(mpt_alloc_fw_memory); EXPORT_SYMBOL(mpt_free_fw_memory); EXPORT_SYMBOL(mptbase_sas_persist_operation); -EXPORT_SYMBOL(mptbase_GetFcPortPage0); /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index f673cca507e..693c95c9034 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -1027,7 +1027,6 @@ extern void mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size); extern void mpt_free_fw_memory(MPT_ADAPTER *ioc); extern int mpt_findImVolumes(MPT_ADAPTER *ioc); extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); -extern int mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum); /* * Public data decl's... diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index 856487741ef..e518bc97f8c 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c @@ -596,6 +596,110 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) return err; } +/* + * mptfc_GetFcPortPage0 - Fetch FCPort config Page0. + * @ioc: Pointer to MPT_ADAPTER structure + * @portnum: IOC Port number + * + * Return: 0 for success + * -ENOMEM if no memory available + * -EPERM if not allowed due to ISR context + * -EAGAIN if no msg frames currently available + * -EFAULT for non-successful reply or no reply (timeout) + * -EINVAL portnum arg out of range (hardwired to two elements) + */ +static int +mptfc_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum) +{ + ConfigPageHeader_t hdr; + CONFIGPARMS cfg; + FCPortPage0_t *ppage0_alloc; + FCPortPage0_t *pp0dest; + dma_addr_t page0_dma; + int data_sz; + int copy_sz; + int rc; + int count = 400; + + if (portnum > 1) + return -EINVAL; + + /* Get FCPort Page 0 header */ + hdr.PageVersion = 0; + hdr.PageLength = 0; + hdr.PageNumber = 0; + hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT; + cfg.cfghdr.hdr = &hdr; + cfg.physAddr = -1; + cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; + cfg.dir = 0; + cfg.pageAddr = portnum; + cfg.timeout = 0; + + if ((rc = mpt_config(ioc, &cfg)) != 0) + return rc; + + if (hdr.PageLength == 0) + return 0; + + data_sz = hdr.PageLength * 4; + rc = -ENOMEM; + ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma); + if (ppage0_alloc) { + + try_again: + memset((u8 *)ppage0_alloc, 0, data_sz); + cfg.physAddr = page0_dma; + cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; + + if ((rc = mpt_config(ioc, &cfg)) == 0) { + /* save the data */ + pp0dest = &ioc->fc_port_page0[portnum]; + copy_sz = min_t(int, sizeof(FCPortPage0_t), data_sz); + memcpy(pp0dest, ppage0_alloc, copy_sz); + + /* + * Normalize endianness of structure data, + * by byte-swapping all > 1 byte fields! + */ + pp0dest->Flags = le32_to_cpu(pp0dest->Flags); + pp0dest->PortIdentifier = le32_to_cpu(pp0dest->PortIdentifier); + pp0dest->WWNN.Low = le32_to_cpu(pp0dest->WWNN.Low); + pp0dest->WWNN.High = le32_to_cpu(pp0dest->WWNN.High); + pp0dest->WWPN.Low = le32_to_cpu(pp0dest->WWPN.Low); + pp0dest->WWPN.High = le32_to_cpu(pp0dest->WWPN.High); + pp0dest->SupportedServiceClass = le32_to_cpu(pp0dest->SupportedServiceClass); + pp0dest->SupportedSpeeds = le32_to_cpu(pp0dest->SupportedSpeeds); + pp0dest->CurrentSpeed = le32_to_cpu(pp0dest->CurrentSpeed); + pp0dest->MaxFrameSize = le32_to_cpu(pp0dest->MaxFrameSize); + pp0dest->FabricWWNN.Low = le32_to_cpu(pp0dest->FabricWWNN.Low); + pp0dest->FabricWWNN.High = le32_to_cpu(pp0dest->FabricWWNN.High); + pp0dest->FabricWWPN.Low = le32_to_cpu(pp0dest->FabricWWPN.Low); + pp0dest->FabricWWPN.High = le32_to_cpu(pp0dest->FabricWWPN.High); + pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount); + pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators); + + /* + * if still doing discovery, + * hang loose a while until finished + */ + if (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) { + if (count-- > 0) { + msleep_interruptible(100); + goto try_again; + } + printk(MYIOC_s_INFO_FMT "Firmware discovery not" + " complete.\n", + ioc->name); + } + } + + pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma); + } + + return rc; +} + static void mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum) { @@ -651,7 +755,7 @@ mptfc_rescan_devices(void *arg) * will reregister existing rports */ for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { - (void) mptbase_GetFcPortPage0(ioc, ii); + (void) mptfc_GetFcPortPage0(ioc, ii); mptfc_init_host_attr(ioc,ii); /* refresh */ mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev); } @@ -753,6 +857,7 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto out_mptfc_probe; } + spin_lock_init(&ioc->fc_rescan_work_lock); INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices,(void *)ioc); spin_lock_irqsave(&ioc->FreeQlock, flags); @@ -888,6 +993,14 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (!ioc->fc_rescan_work_q) goto out_mptfc_probe; + /* + * Pre-fetch FC port WWN and stuff... + * (FCPortPage0_t stuff) + */ + for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { + (void) mptfc_GetFcPortPage0(ioc, ii); + } + /* * scan for rports - * by doing it via the workqueue, some locking is eliminated @@ -917,6 +1030,74 @@ static struct pci_driver mptfc_driver = { #endif }; +static int +mptfc_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) +{ + MPT_SCSI_HOST *hd; + u8 event = le32_to_cpu(pEvReply->Event) & 0xFF; + unsigned long flags; + int rc=1; + + devtverboseprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n", + ioc->name, event)); + + if (ioc->sh == NULL || + ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL)) + return 1; + + switch (event) { + case MPI_EVENT_RESCAN: + spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags); + if (ioc->fc_rescan_work_q) { + if (ioc->fc_rescan_work_count++ == 0) { + queue_work(ioc->fc_rescan_work_q, + &ioc->fc_rescan_work); + } + } + spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags); + break; + default: + rc = mptscsih_event_process(ioc,pEvReply); + break; + } + return rc; +} + +static int +mptfc_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) +{ + int rc; + unsigned long flags; + + rc = mptscsih_ioc_reset(ioc,reset_phase); + if (rc == 0) + return rc; + + + dtmprintk((KERN_WARNING MYNAM + ": IOC %s_reset routed to FC host driver!\n", + reset_phase==MPT_IOC_SETUP_RESET ? "setup" : ( + reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post"))); + + if (reset_phase == MPT_IOC_SETUP_RESET) { + } + + else if (reset_phase == MPT_IOC_PRE_RESET) { + } + + else { /* MPT_IOC_POST_RESET */ + spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags); + if (ioc->fc_rescan_work_q) { + if (ioc->fc_rescan_work_count++ == 0) { + queue_work(ioc->fc_rescan_work_q, + &ioc->fc_rescan_work); + } + } + spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags); + } + return 1; +} + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mptfc_init - Register MPT adapter(s) as SCSI host(s) with @@ -945,12 +1126,12 @@ mptfc_init(void) mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER); mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER); - if (mpt_event_register(mptfcDoneCtx, mptscsih_event_process) == 0) { + if (mpt_event_register(mptfcDoneCtx, mptfc_event_process) == 0) { devtverboseprintk((KERN_INFO MYNAM ": Registered for IOC event notifications\n")); } - if (mpt_reset_register(mptfcDoneCtx, mptscsih_ioc_reset) == 0) { + if (mpt_reset_register(mptfcDoneCtx, mptfc_ioc_reset) == 0) { dprintk((KERN_INFO MYNAM ": Registered for IOC reset notifications\n")); } diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 84fa271eb8f..2d81831cf62 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -2521,18 +2521,6 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) hd->cmdPtr = NULL; } - /* 7. FC: Rescan for blocked rports which might have returned. - */ - if (ioc->bus_type == FC) { - spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags); - if (ioc->fc_rescan_work_q) { - if (ioc->fc_rescan_work_count++ == 0) { - queue_work(ioc->fc_rescan_work_q, - &ioc->fc_rescan_work); - } - } - spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags); - } dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name)); } @@ -2546,7 +2534,6 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) { MPT_SCSI_HOST *hd; u8 event = le32_to_cpu(pEvReply->Event) & 0xFF; - unsigned long flags; devtverboseprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n", ioc->name, event)); @@ -2569,14 +2556,6 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) break; case MPI_EVENT_RESCAN: /* 06 */ - spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags); - if (ioc->fc_rescan_work_q) { - if (ioc->fc_rescan_work_count++ == 0) { - queue_work(ioc->fc_rescan_work_q, - &ioc->fc_rescan_work); - } - } - spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags); break; /* -- cgit v1.2.3 From ca2f938efe71ca48cbc689db4df8d4f04b5d8f07 Mon Sep 17 00:00:00 2001 From: Michael Reed Date: Wed, 24 May 2006 15:07:24 -0500 Subject: [SCSI] mptfc: set fibre channel fw target missing timers to one second The fibre channel firmware provides a timer which is similar in purpose to the fibre channel transport's device loss timer. The effect of this timer is to extend the total time that a target will be missing beyond the value associated with the transport's timer. This patch changes the firmware timer to a default of one second which significantly reduces the lag between when a target goes missing and the notification of the fibre channel transport. Signed-off-by: Michael Reed Signed-off-by: James Bottomley --- drivers/message/fusion/mptbase.h | 10 +++ drivers/message/fusion/mptfc.c | 171 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 172 insertions(+), 9 deletions(-) diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index 693c95c9034..29f6b986946 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -487,6 +487,15 @@ typedef struct _RaidCfgData { int isRaid; /* bit field, 1 if RAID */ }RaidCfgData; +typedef struct _FcCfgData { + /* will ultimately hold fc_port_page0 also */ + struct { + FCPortPage1_t *data; + dma_addr_t dma; + int pg_sz; + } fc_port_page1[2]; +} FcCfgData; + #define MPT_RPORT_INFO_FLAGS_REGISTERED 0x01 /* rport registered */ #define MPT_RPORT_INFO_FLAGS_MISSING 0x02 /* missing from DevPage0 scan */ @@ -565,6 +574,7 @@ typedef struct _MPT_ADAPTER SpiCfgData spi_data; /* Scsi config. data */ RaidCfgData raid_data; /* Raid config. data */ SasCfgData sas_data; /* Sas config. data */ + FcCfgData fc_data; /* Fc config. data */ MPT_IOCTL *ioctl; /* ioctl data pointer */ struct proc_dir_entry *ioc_dentry; struct _MPT_ADAPTER *alt_ioc; /* ptr to 929 bound adapter port */ diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index e518bc97f8c..918aca0146f 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c @@ -169,13 +169,6 @@ static struct fc_function_template mptfc_transport_functions = { }; -/* FIXME! values controlling firmware RESCAN event - * need to be set low to allow dev_loss_tmo to - * work as expected. Currently, firmware doesn't - * notify driver of RESCAN event until some number - * of seconds elapse. This value can be set via - * lsiutil. - */ static void mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout) { @@ -700,6 +693,153 @@ mptfc_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum) return rc; } +static int +mptfc_WriteFcPortPage1(MPT_ADAPTER *ioc, int portnum) +{ + ConfigPageHeader_t hdr; + CONFIGPARMS cfg; + int rc; + + if (portnum > 1) + return -EINVAL; + + if (!(ioc->fc_data.fc_port_page1[portnum].data)) + return -EINVAL; + + /* get fcport page 1 header */ + hdr.PageVersion = 0; + hdr.PageLength = 0; + hdr.PageNumber = 1; + hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT; + cfg.cfghdr.hdr = &hdr; + cfg.physAddr = -1; + cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; + cfg.dir = 0; + cfg.pageAddr = portnum; + cfg.timeout = 0; + + if ((rc = mpt_config(ioc, &cfg)) != 0) + return rc; + + if (hdr.PageLength == 0) + return -ENODEV; + + if (hdr.PageLength*4 != ioc->fc_data.fc_port_page1[portnum].pg_sz) + return -EINVAL; + + cfg.physAddr = ioc->fc_data.fc_port_page1[portnum].dma; + cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; + cfg.dir = 1; + + rc = mpt_config(ioc, &cfg); + + return rc; +} + +static int +mptfc_GetFcPortPage1(MPT_ADAPTER *ioc, int portnum) +{ + ConfigPageHeader_t hdr; + CONFIGPARMS cfg; + FCPortPage1_t *page1_alloc; + dma_addr_t page1_dma; + int data_sz; + int rc; + + if (portnum > 1) + return -EINVAL; + + /* get fcport page 1 header */ + hdr.PageVersion = 0; + hdr.PageLength = 0; + hdr.PageNumber = 1; + hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT; + cfg.cfghdr.hdr = &hdr; + cfg.physAddr = -1; + cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; + cfg.dir = 0; + cfg.pageAddr = portnum; + cfg.timeout = 0; + + if ((rc = mpt_config(ioc, &cfg)) != 0) + return rc; + + if (hdr.PageLength == 0) + return -ENODEV; + +start_over: + + if (ioc->fc_data.fc_port_page1[portnum].data == NULL) { + data_sz = hdr.PageLength * 4; + if (data_sz < sizeof(FCPortPage1_t)) + data_sz = sizeof(FCPortPage1_t); + + page1_alloc = (FCPortPage1_t *) pci_alloc_consistent(ioc->pcidev, + data_sz, + &page1_dma); + if (!page1_alloc) + return -ENOMEM; + } + else { + page1_alloc = ioc->fc_data.fc_port_page1[portnum].data; + page1_dma = ioc->fc_data.fc_port_page1[portnum].dma; + data_sz = ioc->fc_data.fc_port_page1[portnum].pg_sz; + if (hdr.PageLength * 4 > data_sz) { + ioc->fc_data.fc_port_page1[portnum].data = NULL; + pci_free_consistent(ioc->pcidev, data_sz, (u8 *) + page1_alloc, page1_dma); + goto start_over; + } + } + + memset(page1_alloc,0,data_sz); + + cfg.physAddr = page1_dma; + cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; + + if ((rc = mpt_config(ioc, &cfg)) == 0) { + ioc->fc_data.fc_port_page1[portnum].data = page1_alloc; + ioc->fc_data.fc_port_page1[portnum].pg_sz = data_sz; + ioc->fc_data.fc_port_page1[portnum].dma = page1_dma; + } + else { + ioc->fc_data.fc_port_page1[portnum].data = NULL; + pci_free_consistent(ioc->pcidev, data_sz, (u8 *) + page1_alloc, page1_dma); + } + + return rc; +} + +static void +mptfc_SetFcPortPage1_defaults(MPT_ADAPTER *ioc) +{ + int ii; + FCPortPage1_t *pp1; + + #define MPTFC_FW_DEVICE_TIMEOUT (1) + #define MPTFC_FW_IO_PEND_TIMEOUT (1) + #define ON_FLAGS (MPI_FCPORTPAGE1_FLAGS_IMMEDIATE_ERROR_REPLY) + #define OFF_FLAGS (MPI_FCPORTPAGE1_FLAGS_VERBOSE_RESCAN_EVENTS) + + for (ii=0; iifacts.NumberOfPorts; ii++) { + if (mptfc_GetFcPortPage1(ioc, ii) != 0) + continue; + pp1 = ioc->fc_data.fc_port_page1[ii].data; + if ((pp1->InitiatorDeviceTimeout == MPTFC_FW_DEVICE_TIMEOUT) + && (pp1->InitiatorIoPendTimeout == MPTFC_FW_IO_PEND_TIMEOUT) + && ((pp1->Flags & ON_FLAGS) == ON_FLAGS) + && ((pp1->Flags & OFF_FLAGS) == 0)) + continue; + pp1->InitiatorDeviceTimeout = MPTFC_FW_DEVICE_TIMEOUT; + pp1->InitiatorIoPendTimeout = MPTFC_FW_IO_PEND_TIMEOUT; + pp1->Flags &= ~OFF_FLAGS; + pp1->Flags |= ON_FLAGS; + mptfc_WriteFcPortPage1(ioc, ii); + } +} + + static void mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum) { @@ -1000,6 +1140,7 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { (void) mptfc_GetFcPortPage0(ioc, ii); } + mptfc_SetFcPortPage1_defaults(ioc); /* * scan for rports - @@ -1086,6 +1227,7 @@ mptfc_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) } else { /* MPT_IOC_POST_RESET */ + mptfc_SetFcPortPage1_defaults(ioc); spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags); if (ioc->fc_rescan_work_q) { if (ioc->fc_rescan_work_count++ == 0) { @@ -1112,8 +1254,8 @@ mptfc_init(void) show_mptmod_ver(my_NAME, my_VERSION); - /* sanity check module parameter */ - if (mptfc_dev_loss_tmo == 0) + /* sanity check module parameters */ + if (mptfc_dev_loss_tmo <= 0) mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO; mptfc_transport_template = @@ -1156,6 +1298,7 @@ mptfc_remove(struct pci_dev *pdev) struct mptfc_rport_info *p, *n; struct workqueue_struct *work_q; unsigned long flags; + int ii; /* destroy workqueue */ if ((work_q=ioc->fc_rescan_work_q)) { @@ -1172,6 +1315,16 @@ mptfc_remove(struct pci_dev *pdev) kfree(p); } + for (ii=0; iifacts.NumberOfPorts; ii++) { + if (ioc->fc_data.fc_port_page1[ii].data) { + pci_free_consistent(ioc->pcidev, + ioc->fc_data.fc_port_page1[ii].pg_sz, + (u8 *) ioc->fc_data.fc_port_page1[ii].data, + ioc->fc_data.fc_port_page1[ii].dma); + ioc->fc_data.fc_port_page1[ii].data = NULL; + } + } + mptscsih_remove(pdev); } -- cgit v1.2.3 From 419835e285c3e39cd62c8c8426da0aebea9cd89f Mon Sep 17 00:00:00 2001 From: Michael Reed Date: Wed, 24 May 2006 15:07:40 -0500 Subject: [SCSI] mptfc: fix fibre channel infinite request/response loop While doing board reset testing I was able to put the system in an infinite request/response loop between the scsi layer and mptscsih_qcmd() by aborting the reset. This patch installs a "SETUP RESET" handler which calls fc_remote_port_delete() for all registered rports. This blocks the target which prevents the loop. Additionally, should the reset fail to complete, the transport will now terminate i/o to the target. Signed-off-by: Michael Reed Signed-off-by: James Bottomley --- drivers/message/fusion/mptbase.h | 1 + drivers/message/fusion/mptfc.c | 36 ++++++++++++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index 29f6b986946..6d36ff5ee72 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -635,6 +635,7 @@ typedef struct _MPT_ADAPTER int num_ports; struct work_struct mptscsih_persistTask; + struct work_struct fc_setup_reset_work; struct list_head fc_rports; spinlock_t fc_rescan_work_lock; int fc_rescan_work_count; diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index 918aca0146f..770df553047 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c @@ -580,10 +580,10 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) #ifdef DMPT_DEBUG_FC if (unlikely(err)) { dfcprintk ((MYIOC_s_INFO_FMT - "mptfc_qcmd.%d: %d:%d, mptscsih_qcmd returns non-zero.\n", + "mptfc_qcmd.%d: %d:%d, mptscsih_qcmd returns non-zero, (%x).\n", ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->name, ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->sh->host_no, - SCpnt->device->id,SCpnt->device->lun)); + SCpnt->device->id,SCpnt->device->lun,err)); } #endif return err; @@ -872,6 +872,31 @@ mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum) fc_host_tgtid_bind_type(ioc->sh) = FC_TGTID_BIND_BY_WWPN; } +static void +mptfc_setup_reset(void *arg) +{ + MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg; + u64 pn; + struct mptfc_rport_info *ri; + + /* reset about to happen, delete (block) all rports */ + list_for_each_entry(ri, &ioc->fc_rports, list) { + if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) { + ri->flags &= ~MPT_RPORT_INFO_FLAGS_REGISTERED; + fc_remote_port_delete(ri->rport); /* won't sleep */ + ri->rport = NULL; + + pn = (u64)ri->pg0.WWPN.High << 32 | + (u64)ri->pg0.WWPN.Low; + dfcprintk ((MYIOC_s_INFO_FMT + "mptfc_setup_reset.%d: %llx deleted\n", + ioc->name, + ioc->sh->host_no, + (unsigned long long)pn)); + } + } +} + static void mptfc_rescan_devices(void *arg) { @@ -999,6 +1024,7 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) spin_lock_init(&ioc->fc_rescan_work_lock); INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices,(void *)ioc); + INIT_WORK(&ioc->fc_setup_reset_work, mptfc_setup_reset, (void *)ioc); spin_lock_irqsave(&ioc->FreeQlock, flags); @@ -1221,6 +1247,12 @@ mptfc_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post"))); if (reset_phase == MPT_IOC_SETUP_RESET) { + spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags); + if (ioc->fc_rescan_work_q) { + queue_work(ioc->fc_rescan_work_q, + &ioc->fc_setup_reset_work); + } + spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags); } else if (reset_phase == MPT_IOC_PRE_RESET) { -- cgit v1.2.3 From d6be06c84da9626b10443c664ee55bda96fb3514 Mon Sep 17 00:00:00 2001 From: Michael Reed Date: Wed, 24 May 2006 15:07:57 -0500 Subject: [SCSI] mptfc: abort of board reset leaves port dead requiring reboot The driver uses msleep_interruptible() in the code path responsible for resetting the card's ports via the lsiutil command. If a is received during the reset it can leave a port in such a state that the only way to regain its use is to reboot the system. Changing from msleep_interruptible() to msleep() corrects the problem. Signed-off-by: Michael Reed Signed-off-by: James Bottomley --- drivers/message/fusion/mptbase.c | 30 +++++++++++++++--------------- drivers/message/fusion/mptfc.c | 2 +- drivers/message/fusion/mptscsih.c | 2 +- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 330c29080e3..08779d79a1f 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -2291,7 +2291,7 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag) } if (sleepFlag == CAN_SLEEP) { - msleep_interruptible(1); + msleep(1); } else { mdelay (1); /* 1 msec delay */ } @@ -2679,7 +2679,7 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag) state = mpt_GetIocState(ioc, 1); while (state != MPI_IOC_STATE_OPERATIONAL && --cntdn) { if (sleepFlag == CAN_SLEEP) { - msleep_interruptible(1); + msleep(1); } else { mdelay(1); } @@ -2931,7 +2931,7 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag) /* wait 1 msec */ if (sleepFlag == CAN_SLEEP) { - msleep_interruptible(1); + msleep(1); } else { mdelay (1); } @@ -2948,7 +2948,7 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag) } /* wait .1 sec */ if (sleepFlag == CAN_SLEEP) { - msleep_interruptible (100); + msleep (100); } else { mdelay (100); } @@ -3038,7 +3038,7 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag) /* wait 1 msec */ if (sleepFlag == CAN_SLEEP) { - msleep_interruptible (1); + msleep (1); } else { mdelay (1); } @@ -3086,7 +3086,7 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag) return 0; } if (sleepFlag == CAN_SLEEP) { - msleep_interruptible (10); + msleep (10); } else { mdelay (10); } @@ -3137,7 +3137,7 @@ KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag) SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag); if (sleepFlag == CAN_SLEEP) { - msleep_interruptible (1000); + msleep (1000); } else { mdelay (1000); } @@ -3159,7 +3159,7 @@ KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag) return hard_reset_done; } if (sleepFlag == CAN_SLEEP) { - msleep_interruptible (10); + msleep (10); } else { mdelay (10); } @@ -3230,7 +3230,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) /* wait 100 msec */ if (sleepFlag == CAN_SLEEP) { - msleep_interruptible (100); + msleep (100); } else { mdelay (100); } @@ -3309,7 +3309,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) /* wait 1 sec */ if (sleepFlag == CAN_SLEEP) { - msleep_interruptible (1000); + msleep (1000); } else { mdelay (1000); } @@ -3337,7 +3337,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) /* wait 1 sec */ if (sleepFlag == CAN_SLEEP) { - msleep_interruptible (1000); + msleep (1000); } else { mdelay (1000); } @@ -3371,7 +3371,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) /* wait 100 msec */ if (sleepFlag == CAN_SLEEP) { - msleep_interruptible (100); + msleep (100); } else { mdelay (100); } @@ -3465,7 +3465,7 @@ SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag) } if (sleepFlag == CAN_SLEEP) { - msleep_interruptible(1); + msleep(1); } else { mdelay (1); /* 1 msec delay */ } @@ -3905,7 +3905,7 @@ WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag) intstat = CHIPREG_READ32(&ioc->chip->IntStatus); if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS)) break; - msleep_interruptible (1); + msleep (1); count++; } } else { @@ -3954,7 +3954,7 @@ WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag) intstat = CHIPREG_READ32(&ioc->chip->IntStatus); if (intstat & MPI_HIS_DOORBELL_INTERRUPT) break; - msleep_interruptible(1); + msleep(1); count++; } } else { diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index 770df553047..74714e5bcf0 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c @@ -678,7 +678,7 @@ mptfc_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum) */ if (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) { if (count-- > 0) { - msleep_interruptible(100); + msleep(100); goto try_again; } printk(MYIOC_s_INFO_FMT "Firmware discovery not" diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 2d81831cf62..8242b16e316 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -1922,7 +1922,7 @@ mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout ) break; } spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); - msleep_interruptible(250); + msleep(250); } while (--loop_count); return status; -- cgit v1.2.3 From 1951d099dfd8fa529e86f4ac81d1a34554fbe302 Mon Sep 17 00:00:00 2001 From: Michael Reed Date: Wed, 24 May 2006 15:08:10 -0500 Subject: [SCSI] mptfusion: change driver revision to 3.03.10 Bump driver version number to reflect addition of various fibre channel patches. Signed-off-by: Michael Reed Signed-off-by: James Bottomley --- drivers/message/fusion/mptbase.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index 6d36ff5ee72..4720f9ae86a 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -76,8 +76,8 @@ #define COPYRIGHT "Copyright (c) 1999-2005 " MODULEAUTHOR #endif -#define MPT_LINUX_VERSION_COMMON "3.03.09" -#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.09" +#define MPT_LINUX_VERSION_COMMON "3.03.10" +#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.10" #define WHAT_MAGIC_STRING "@" "(" "#" ")" #define show_mptmod_ver(s,ver) \ -- cgit v1.2.3 From beb40487508290f5d6565598c60a3f44261beef2 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sat, 10 Jun 2006 18:01:03 +0200 Subject: [SCSI] remove scsi_request infrastructure With Achim patch the last user (gdth) is switched away from scsi_request so we an kill it now. Also disables some code in i2o_scsi that was broken since the sg driver stopped using scsi_requests. Signed-off-by: Christoph Hellwig Signed-off-by: James Bottomley --- drivers/message/i2o/i2o_scsi.c | 4 +- drivers/scsi/constants.c | 12 +--- drivers/scsi/gdth.c | 8 +-- drivers/scsi/ipr.c | 1 - drivers/scsi/libata-scsi.c | 2 +- drivers/scsi/qlogicpti.c | 1 - drivers/scsi/scsi.c | 157 ----------------------------------------- drivers/scsi/scsi.h | 1 - drivers/scsi/scsi_error.c | 12 +--- drivers/scsi/scsi_ioctl.c | 2 +- drivers/scsi/scsi_lib.c | 80 +-------------------- drivers/scsi/scsi_priv.h | 10 --- drivers/scsi/scsi_scan.c | 2 +- drivers/scsi/scsi_typedefs.h | 1 - include/scsi/scsi_cmnd.h | 6 -- include/scsi/scsi_dbg.h | 2 - include/scsi/scsi_eh.h | 3 - include/scsi/scsi_request.h | 54 -------------- include/scsi/sg_request.h | 26 ------- 19 files changed, 14 insertions(+), 370 deletions(-) delete mode 100644 include/scsi/scsi_request.h delete mode 100644 include/scsi/sg_request.h diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c index c08ddac3717..6ebf38213f9 100644 --- a/drivers/message/i2o/i2o_scsi.c +++ b/drivers/message/i2o/i2o_scsi.c @@ -65,9 +65,7 @@ #include #include #include -#include #include -#include #define OSM_NAME "scsi-osm" #define OSM_VERSION "1.316" @@ -588,6 +586,7 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, mptr = &msg->body[0]; +#if 0 /* this code can't work */ #ifdef CONFIG_I2O_EXT_ADAPTEC if (c->adaptec) { u32 adpt_flags = 0; @@ -624,6 +623,7 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, *mptr++ = cpu_to_le32(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC); *mptr++ = cpu_to_le32(adpt_flags | tid); } +#endif #endif msg->u.head[1] = cpu_to_le32(cmd | HOST_TID << 12 | tid); diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c index e24835b38b5..d92d5040a9f 100644 --- a/drivers/scsi/constants.c +++ b/drivers/scsi/constants.c @@ -13,9 +13,9 @@ #include #include +#include #include #include -#include #include #include @@ -1261,16 +1261,6 @@ void scsi_print_sense(const char *devclass, struct scsi_cmnd *cmd) } EXPORT_SYMBOL(scsi_print_sense); -void scsi_print_req_sense(const char *devclass, struct scsi_request *sreq) -{ - const char *name = devclass; - - if (sreq->sr_request->rq_disk) - name = sreq->sr_request->rq_disk->disk_name; - __scsi_print_sense(name, sreq->sr_sense_buffer, SCSI_SENSE_BUFFERSIZE); -} -EXPORT_SYMBOL(scsi_print_req_sense); - void scsi_print_command(struct scsi_cmnd *cmd) { /* Assume appended output (i.e. not at start of line) */ diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index fc4d9f61cf3..76071a15830 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c @@ -716,8 +716,8 @@ static void gdth_scsi_done(struct scsi_cmnd *scp) { TRACE2(("gdth_scsi_done()\n")); - if (scp->sc_request) - complete((struct completion *)scp->sc_request); + if (scp->request) + complete((struct completion *)scp->request); } int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd, @@ -732,8 +732,8 @@ int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd, return -ENOMEM; memset(scp, 0, sizeof(*scp)); scp->device = sdev; - /* use sc_request field to save the ptr. to completion struct. */ - scp->sc_request = (struct scsi_request *)&wait; + /* use request field to save the ptr. to completion struct. */ + scp->request = (struct request *)&wait; scp->timeout_per_command = timeout*HZ; scp->request_buffer = gdtcmd; scp->cmd_len = 12; diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 8b80e59c8c5..96b65b307dd 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -79,7 +79,6 @@ #include #include #include -#include #include "ipr.h" /* diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 994015726ec..f1e129b7c97 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -38,9 +38,9 @@ #include #include #include +#include #include #include -#include #include #include #include diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c index 00f4b846360..417a121fcd4 100644 --- a/drivers/scsi/qlogicpti.c +++ b/drivers/scsi/qlogicpti.c @@ -43,7 +43,6 @@ #include #include #include -#include #include #include diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 73994e2ac2c..3e90ba797df 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -63,7 +63,6 @@ #include #include #include -#include #include "scsi_priv.h" #include "scsi_logging.h" @@ -116,79 +115,6 @@ const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE] = { }; EXPORT_SYMBOL(scsi_device_types); -/* - * Function: scsi_allocate_request - * - * Purpose: Allocate a request descriptor. - * - * Arguments: device - device for which we want a request - * gfp_mask - allocation flags passed to kmalloc - * - * Lock status: No locks assumed to be held. This function is SMP-safe. - * - * Returns: Pointer to request block. - */ -struct scsi_request *scsi_allocate_request(struct scsi_device *sdev, - gfp_t gfp_mask) -{ - const int offset = ALIGN(sizeof(struct scsi_request), 4); - const int size = offset + sizeof(struct request); - struct scsi_request *sreq; - - sreq = kzalloc(size, gfp_mask); - if (likely(sreq != NULL)) { - sreq->sr_request = (struct request *)(((char *)sreq) + offset); - sreq->sr_device = sdev; - sreq->sr_host = sdev->host; - sreq->sr_magic = SCSI_REQ_MAGIC; - sreq->sr_data_direction = DMA_BIDIRECTIONAL; - } - - return sreq; -} -EXPORT_SYMBOL(scsi_allocate_request); - -void __scsi_release_request(struct scsi_request *sreq) -{ - struct request *req = sreq->sr_request; - - /* unlikely because the tag was usually ended earlier by the - * mid-layer. However, for layering reasons ULD's don't end - * the tag of commands they generate. */ - if (unlikely(blk_rq_tagged(req))) { - unsigned long flags; - struct request_queue *q = req->q; - - spin_lock_irqsave(q->queue_lock, flags); - blk_queue_end_tag(q, req); - spin_unlock_irqrestore(q->queue_lock, flags); - } - - - if (likely(sreq->sr_command != NULL)) { - struct scsi_cmnd *cmd = sreq->sr_command; - - sreq->sr_command = NULL; - scsi_next_command(cmd); - } -} - -/* - * Function: scsi_release_request - * - * Purpose: Release a request descriptor. - * - * Arguments: sreq - request to release - * - * Lock status: No locks assumed to be held. This function is SMP-safe. - */ -void scsi_release_request(struct scsi_request *sreq) -{ - __scsi_release_request(sreq); - kfree(sreq); -} -EXPORT_SYMBOL(scsi_release_request); - struct scsi_host_cmd_pool { kmem_cache_t *slab; unsigned int users; @@ -646,73 +572,6 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) return rtn; } -/* - * Function: scsi_init_cmd_from_req - * - * Purpose: Queue a SCSI command - * Purpose: Initialize a struct scsi_cmnd from a struct scsi_request - * - * Arguments: cmd - command descriptor. - * sreq - Request from the queue. - * - * Lock status: None needed. - * - * Returns: Nothing. - * - * Notes: Mainly transfer data from the request structure to the - * command structure. The request structure is allocated - * using the normal memory allocator, and requests can pile - * up to more or less any depth. The command structure represents - * a consumable resource, as these are allocated into a pool - * when the SCSI subsystem initializes. The preallocation is - * required so that in low-memory situations a disk I/O request - * won't cause the memory manager to try and write out a page. - * The request structure is generally used by ioctls and character - * devices. - */ -void scsi_init_cmd_from_req(struct scsi_cmnd *cmd, struct scsi_request *sreq) -{ - sreq->sr_command = cmd; - - cmd->cmd_len = sreq->sr_cmd_len; - cmd->use_sg = sreq->sr_use_sg; - - cmd->request = sreq->sr_request; - memcpy(cmd->data_cmnd, sreq->sr_cmnd, sizeof(cmd->data_cmnd)); - cmd->serial_number = 0; - cmd->bufflen = sreq->sr_bufflen; - cmd->buffer = sreq->sr_buffer; - cmd->retries = 0; - cmd->allowed = sreq->sr_allowed; - cmd->done = sreq->sr_done; - cmd->timeout_per_command = sreq->sr_timeout_per_command; - cmd->sc_data_direction = sreq->sr_data_direction; - cmd->sglist_len = sreq->sr_sglist_len; - cmd->underflow = sreq->sr_underflow; - cmd->sc_request = sreq; - memcpy(cmd->cmnd, sreq->sr_cmnd, sizeof(sreq->sr_cmnd)); - - /* - * Zero the sense buffer. Some host adapters automatically request - * sense on error. 0 is not a valid sense code. - */ - memset(cmd->sense_buffer, 0, sizeof(sreq->sr_sense_buffer)); - cmd->request_buffer = sreq->sr_buffer; - cmd->request_bufflen = sreq->sr_bufflen; - cmd->old_use_sg = cmd->use_sg; - if (cmd->cmd_len == 0) - cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]); - cmd->old_cmd_len = cmd->cmd_len; - cmd->sc_old_data_direction = cmd->sc_data_direction; - cmd->old_underflow = cmd->underflow; - - /* - * Start the timer ticking. - */ - cmd->result = 0; - - SCSI_LOG_MLQUEUE(3, printk("Leaving scsi_init_cmd_from_req()\n")); -} /* * Per-CPU I/O completion queue. @@ -809,7 +668,6 @@ void scsi_finish_command(struct scsi_cmnd *cmd) { struct scsi_device *sdev = cmd->device; struct Scsi_Host *shost = sdev->host; - struct scsi_request *sreq; scsi_device_unbusy(sdev); @@ -839,21 +697,6 @@ void scsi_finish_command(struct scsi_cmnd *cmd) * We can get here with use_sg=0, causing a panic in the upper level */ cmd->use_sg = cmd->old_use_sg; - - /* - * If there is an associated request structure, copy the data over - * before we call the completion function. - */ - sreq = cmd->sc_request; - if (sreq) { - sreq->sr_result = sreq->sr_command->result; - if (sreq->sr_result) { - memcpy(sreq->sr_sense_buffer, - sreq->sr_command->sense_buffer, - sizeof(sreq->sr_sense_buffer)); - } - } - cmd->done(cmd); } EXPORT_SYMBOL(scsi_finish_command); diff --git a/drivers/scsi/scsi.h b/drivers/scsi/scsi.h index 5ee5d80a993..f51e466893e 100644 --- a/drivers/scsi/scsi.h +++ b/drivers/scsi/scsi.h @@ -25,7 +25,6 @@ #include #include #include -#include #include #include diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 1c75646f968..471a4310292 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -26,13 +26,13 @@ #include #include +#include #include #include #include #include #include #include -#include #include "scsi_priv.h" #include "scsi_logging.h" @@ -1671,8 +1671,6 @@ scsi_reset_provider(struct scsi_device *dev, int flag) scmd->cmd_len = 0; scmd->sc_data_direction = DMA_BIDIRECTIONAL; - scmd->sc_request = NULL; - scmd->sc_magic = SCSI_CMND_MAGIC; init_timer(&scmd->eh_timeout); @@ -1769,14 +1767,6 @@ int scsi_normalize_sense(const u8 *sense_buffer, int sb_len, } EXPORT_SYMBOL(scsi_normalize_sense); -int scsi_request_normalize_sense(struct scsi_request *sreq, - struct scsi_sense_hdr *sshdr) -{ - return scsi_normalize_sense(sreq->sr_sense_buffer, - sizeof(sreq->sr_sense_buffer), sshdr); -} -EXPORT_SYMBOL(scsi_request_normalize_sense); - int scsi_command_normalize_sense(struct scsi_cmnd *cmd, struct scsi_sense_hdr *sshdr) { diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c index a89aff61d3d..a89c4115cfb 100644 --- a/drivers/scsi/scsi_ioctl.c +++ b/drivers/scsi/scsi_ioctl.c @@ -15,11 +15,11 @@ #include #include +#include #include #include #include #include -#include #include #include diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index bdce9d1f5b7..3302d8068c4 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -19,12 +19,12 @@ #include #include +#include #include #include #include #include #include -#include #include "scsi_priv.h" #include "scsi_logging.h" @@ -83,7 +83,7 @@ static void scsi_unprep_request(struct request *req) struct scsi_cmnd *cmd = req->special; req->flags &= ~REQ_DONTPREP; - req->special = (req->flags & REQ_SPECIAL) ? cmd->sc_request : NULL; + req->special = NULL; scsi_put_command(cmd); } @@ -161,72 +161,6 @@ int scsi_queue_insert(struct scsi_cmnd *cmd, int reason) return 0; } -/* - * Function: scsi_do_req - * - * Purpose: Queue a SCSI request - * - * Arguments: sreq - command descriptor. - * cmnd - actual SCSI command to be performed. - * buffer - data buffer. - * bufflen - size of data buffer. - * done - completion function to be run. - * timeout - how long to let it run before timeout. - * retries - number of retries we allow. - * - * Lock status: No locks held upon entry. - * - * Returns: Nothing. - * - * Notes: This function is only used for queueing requests for things - * like ioctls and character device requests - this is because - * we essentially just inject a request into the queue for the - * device. - * - * In order to support the scsi_device_quiesce function, we - * now inject requests on the *head* of the device queue - * rather than the tail. - */ -void scsi_do_req(struct scsi_request *sreq, const void *cmnd, - void *buffer, unsigned bufflen, - void (*done)(struct scsi_cmnd *), - int timeout, int retries) -{ - /* - * If the upper level driver is reusing these things, then - * we should release the low-level block now. Another one will - * be allocated later when this request is getting queued. - */ - __scsi_release_request(sreq); - - /* - * Our own function scsi_done (which marks the host as not busy, - * disables the timeout counter, etc) will be called by us or by the - * scsi_hosts[host].queuecommand() function needs to also call - * the completion function for the high level driver. - */ - memcpy(sreq->sr_cmnd, cmnd, sizeof(sreq->sr_cmnd)); - sreq->sr_bufflen = bufflen; - sreq->sr_buffer = buffer; - sreq->sr_allowed = retries; - sreq->sr_done = done; - sreq->sr_timeout_per_command = timeout; - - if (sreq->sr_cmd_len == 0) - sreq->sr_cmd_len = COMMAND_SIZE(sreq->sr_cmnd[0]); - - /* - * head injection *required* here otherwise quiesce won't work - * - * Because users of this function are apt to reuse requests with no - * modification, we have to sanitise the request flags here - */ - sreq->sr_request->flags &= ~REQ_DONTPREP; - blk_insert_request(sreq->sr_device->request_queue, sreq->sr_request, - 1, sreq); -} -EXPORT_SYMBOL(scsi_do_req); - /** * scsi_execute - insert request and wait for the result * @sdev: scsi device @@ -1300,15 +1234,7 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) * at request->cmd, as this tells us the real story. */ if (req->flags & REQ_SPECIAL && req->special) { - struct scsi_request *sreq = req->special; - - if (sreq->sr_magic == SCSI_REQ_MAGIC) { - cmd = scsi_get_command(sreq->sr_device, GFP_ATOMIC); - if (unlikely(!cmd)) - goto defer; - scsi_init_cmd_from_req(cmd, sreq); - } else - cmd = req->special; + cmd = req->special; } else if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) { if(unlikely(specials_only) && !(req->flags & REQ_SPECIAL)) { diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index 27c48274e8c..a1727a0e1bd 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -8,16 +8,9 @@ struct request_queue; struct scsi_cmnd; struct scsi_device; struct scsi_host_template; -struct scsi_request; struct Scsi_Host; -/* - * Magic values for certain scsi structs. Shouldn't ever be used. - */ -#define SCSI_CMND_MAGIC 0xE25C23A5 -#define SCSI_REQ_MAGIC 0x75F6D354 - /* * Scsi Error Handler Flags */ @@ -34,9 +27,6 @@ extern void scsi_exit_hosts(void); extern int scsi_dispatch_cmd(struct scsi_cmnd *cmd); extern int scsi_setup_command_freelist(struct Scsi_Host *shost); extern void scsi_destroy_command_freelist(struct Scsi_Host *shost); -extern void scsi_init_cmd_from_req(struct scsi_cmnd *cmd, - struct scsi_request *sreq); -extern void __scsi_release_request(struct scsi_request *sreq); extern void __scsi_done(struct scsi_cmnd *cmd); extern int scsi_retry_command(struct scsi_cmnd *cmd); #ifdef CONFIG_SCSI_LOGGING diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index fd97d07577a..0f7e6f94d66 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -33,11 +33,11 @@ #include #include +#include #include #include #include #include -#include #include #include diff --git a/drivers/scsi/scsi_typedefs.h b/drivers/scsi/scsi_typedefs.h index 29f038b42f6..2ed4c5cb708 100644 --- a/drivers/scsi/scsi_typedefs.h +++ b/drivers/scsi/scsi_typedefs.h @@ -1,3 +1,2 @@ typedef struct scsi_cmnd Scsi_Cmnd; -typedef struct scsi_request Scsi_Request; diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index 7602b9b15a0..b0caabec1bd 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -9,7 +9,6 @@ struct request; struct scatterlist; struct scsi_device; -struct scsi_request; /* embedded in scsi_cmnd */ @@ -29,13 +28,8 @@ struct scsi_pointer { }; struct scsi_cmnd { - int sc_magic; - struct scsi_device *device; - struct scsi_request *sc_request; - struct list_head list; /* scsi_cmnd participates in queue lists */ - struct list_head eh_entry; /* entry for the host eh_cmd_q */ int eh_eflags; /* Used by error handlr */ void (*done) (struct scsi_cmnd *); /* Mid-level done function */ diff --git a/include/scsi/scsi_dbg.h b/include/scsi/scsi_dbg.h index 4d69dee66d4..3bbbfbe8cbf 100644 --- a/include/scsi/scsi_dbg.h +++ b/include/scsi/scsi_dbg.h @@ -2,14 +2,12 @@ #define _SCSI_SCSI_DBG_H struct scsi_cmnd; -struct scsi_request; struct scsi_sense_hdr; extern void scsi_print_command(struct scsi_cmnd *); extern void scsi_print_sense_hdr(const char *, struct scsi_sense_hdr *); extern void __scsi_print_command(unsigned char *); extern void scsi_print_sense(const char *, struct scsi_cmnd *); -extern void scsi_print_req_sense(const char *, struct scsi_request *); extern void __scsi_print_sense(const char *name, const unsigned char *sense_buffer, int sense_len); diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h index d160880b2a8..c5c0f6762a0 100644 --- a/include/scsi/scsi_eh.h +++ b/include/scsi/scsi_eh.h @@ -3,7 +3,6 @@ struct scsi_cmnd; struct scsi_device; -struct scsi_request; struct Scsi_Host; /* @@ -43,8 +42,6 @@ extern void scsi_report_device_reset(struct Scsi_Host *, int, int); extern int scsi_block_when_processing_errors(struct scsi_device *); extern int scsi_normalize_sense(const u8 *sense_buffer, int sb_len, struct scsi_sense_hdr *sshdr); -extern int scsi_request_normalize_sense(struct scsi_request *sreq, - struct scsi_sense_hdr *sshdr); extern int scsi_command_normalize_sense(struct scsi_cmnd *cmd, struct scsi_sense_hdr *sshdr); diff --git a/include/scsi/scsi_request.h b/include/scsi/scsi_request.h deleted file mode 100644 index 98d69fdb851..00000000000 --- a/include/scsi/scsi_request.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef _SCSI_SCSI_REQUEST_H -#define _SCSI_SCSI_REQUEST_H - -#include - -struct request; -struct scsi_cmnd; -struct scsi_device; -struct Scsi_Host; - - -/* - * This is essentially a slimmed down version of Scsi_Cmnd. The point of - * having this is that requests that are injected into the queue as result - * of things like ioctls and character devices shouldn't be using a - * Scsi_Cmnd until such a time that the command is actually at the head - * of the queue and being sent to the driver. - */ -struct scsi_request { - int sr_magic; - int sr_result; /* Status code from lower level driver */ - unsigned char sr_sense_buffer[SCSI_SENSE_BUFFERSIZE]; /* obtained by REQUEST SENSE - * when CHECK CONDITION is - * received on original command - * (auto-sense) */ - - struct Scsi_Host *sr_host; - struct scsi_device *sr_device; - struct scsi_cmnd *sr_command; - struct request *sr_request; /* A copy of the command we are - working on */ - unsigned sr_bufflen; /* Size of data buffer */ - void *sr_buffer; /* Data buffer */ - int sr_allowed; - enum dma_data_direction sr_data_direction; - unsigned char sr_cmd_len; - unsigned char sr_cmnd[MAX_COMMAND_SIZE]; - void (*sr_done) (struct scsi_cmnd *); /* Mid-level done function */ - int sr_timeout_per_command; - unsigned short sr_use_sg; /* Number of pieces of scatter-gather */ - unsigned short sr_sglist_len; /* size of malloc'd scatter-gather list */ - unsigned sr_underflow; /* Return error if less than - this amount is transferred */ - void *upper_private_data; /* reserved for owner (usually upper - level driver) of this request */ -}; - -extern struct scsi_request *scsi_allocate_request(struct scsi_device *, gfp_t); -extern void scsi_release_request(struct scsi_request *); -extern void scsi_do_req(struct scsi_request *, const void *cmnd, - void *buffer, unsigned bufflen, - void (*done) (struct scsi_cmnd *), - int timeout, int retries); -#endif /* _SCSI_SCSI_REQUEST_H */ diff --git a/include/scsi/sg_request.h b/include/scsi/sg_request.h deleted file mode 100644 index 57ff525bdd3..00000000000 --- a/include/scsi/sg_request.h +++ /dev/null @@ -1,26 +0,0 @@ -typedef struct scsi_request Scsi_Request; - -static Scsi_Request *dummy_cmdp; /* only used for sizeof */ - -typedef struct sg_scatter_hold { /* holding area for scsi scatter gather info */ - unsigned short k_use_sg; /* Count of kernel scatter-gather pieces */ - unsigned short sglist_len; /* size of malloc'd scatter-gather list ++ */ - unsigned bufflen; /* Size of (aggregate) data buffer */ - unsigned b_malloc_len; /* actual len malloc'ed in buffer */ - void *buffer; /* Data buffer or scatter list (k_use_sg>0) */ - char dio_in_use; /* 0->indirect IO (or mmap), 1->dio */ - unsigned char cmd_opcode; /* first byte of command */ -} Sg_scatter_hold; - -typedef struct sg_request { /* SG_MAX_QUEUE requests outstanding per file */ - Scsi_Request *my_cmdp; /* != 0 when request with lower levels */ - struct sg_request *nextrp; /* NULL -> tail request (slist) */ - struct sg_fd *parentfp; /* NULL -> not in use */ - Sg_scatter_hold data; /* hold buffer, perhaps scatter list */ - sg_io_hdr_t header; /* scsi command+info, see */ - unsigned char sense_b[sizeof (dummy_cmdp->sr_sense_buffer)]; - char res_used; /* 1 -> using reserve buffer, 0 -> not ... */ - char orphan; /* 1 -> drop on sight, 0 -> normal */ - char sg_io_owned; /* 1 -> packet belongs to SG_IO */ - volatile char done; /* 0->before bh, 1->before read, 2->read */ -} Sg_request; -- cgit v1.2.3 From 8d7feac3c7504425aaf61dc7d804685a6b89ee43 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sat, 10 Jun 2006 18:37:19 +0200 Subject: [SCSI] remove RQ_SCSI_* flags The RQ_SCSI_* flags are a vestiage of a long past history. The EH code still sets them but we never make use of that information. The other users is pluto.c which never had a chance to work but needs to be kept compiling to keep Davem happy, so copy over the definition there. We could probably get rid of RQ_ACTIVE/RQ_INACTIVE aswell with some work, there's only two more or less bogus looking uses in ubd and scsi. Signed-off-by: Christoph Hellwig Signed-off-by: James Bottomley --- drivers/scsi/pluto.c | 3 +++ drivers/scsi/scsi_error.c | 3 --- include/linux/blkdev.h | 3 --- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/pluto.c b/drivers/scsi/pluto.c index 46624ab9c3d..83a67179993 100644 --- a/drivers/scsi/pluto.c +++ b/drivers/scsi/pluto.c @@ -27,6 +27,9 @@ #include +#define RQ_SCSI_BUSY 0xffff +#define RQ_SCSI_DONE 0xfffe + /* #define PLUTO_DEBUG */ #define pluto_printk printk ("PLUTO %s: ", fc->name); printk diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 471a4310292..1c7d993fa8a 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -452,7 +452,6 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, int timeout) (sdev->lun << 5 & 0xe0); shost->eh_action = &done; - scmd->request->rq_status = RQ_SCSI_BUSY; spin_lock_irqsave(shost->host_lock, flags); scsi_log_send(scmd); @@ -461,7 +460,6 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, int timeout) timeleft = wait_for_completion_timeout(&done, timeout); - scmd->request->rq_status = RQ_SCSI_DONE; shost->eh_action = NULL; scsi_log_completion(scmd, SUCCESS); @@ -1657,7 +1655,6 @@ scsi_reset_provider(struct scsi_device *dev, int flag) scmd->request = &req; memset(&scmd->eh_timeout, 0, sizeof(scmd->eh_timeout)); - scmd->request->rq_status = RQ_SCSI_BUSY; memset(&scmd->cmnd, '\0', sizeof(scmd->cmnd)); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 59e1259b1c4..c889c459fd1 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -439,9 +439,6 @@ struct request_queue #define RQ_INACTIVE (-1) #define RQ_ACTIVE 1 -#define RQ_SCSI_BUSY 0xffff -#define RQ_SCSI_DONE 0xfffe -#define RQ_SCSI_DISCONNECTING 0xffe0 #define QUEUE_FLAG_CLUSTER 0 /* cluster several segments into 1 */ #define QUEUE_FLAG_QUEUED 1 /* uses generic tag queueing */ -- cgit v1.2.3 From 0a1b622ef495d8ebba9ad8982414c6661c16b604 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 11 Jun 2006 11:01:38 +0900 Subject: [PATCH] libata: add missing finish_wait() call in ata_port_wait_eh() Add missing finish_wait() call after wait loop in ata_port_wait_eh(). Signed-off-by: Tejun Heo --- drivers/scsi/libata-eh.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c index d4b80b64342..6285257a890 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/scsi/libata-eh.c @@ -334,6 +334,7 @@ void ata_port_wait_eh(struct ata_port *ap) schedule(); spin_lock_irqsave(&ap->host_set->lock, flags); } + finish_wait(&ap->eh_wait_q, &wait); spin_unlock_irqrestore(&ap->host_set->lock, flags); -- cgit v1.2.3 From 9a9c77dc4c4eed9dfb74080e768c0b3c9d905496 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 11 Jun 2006 11:19:00 +0900 Subject: [PATCH] libata: cosmetic change in struct ata_port Cosmetic change in struct ata_port. Signed-off-by: Tejun Heo --- include/linux/libata.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/linux/libata.h b/include/linux/libata.h index a2a33a90291..39e6b77de1a 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -520,7 +520,8 @@ struct ata_port { struct ata_host_set *host_set; struct device *dev; - struct work_struct port_task, hotplug_task; + struct work_struct port_task; + struct work_struct hotplug_task; unsigned int hsm_task_state; -- cgit v1.2.3 From 6218a761bbc27acc65248c80024875bcc06d52b1 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sun, 11 Jun 2006 14:15:17 +1000 Subject: powerpc: add context.vdso_base for 32-bit too This adds a vdso_base element to the mm_context_t for 32-bit compiles (both for ARCH=powerpc and ARCH=ppc). This fixes the compile errors that have been reported in arch/powerpc/kernel/signal_32.c. Signed-off-by: Paul Mackerras --- arch/powerpc/mm/mmu_context_32.c | 2 +- arch/powerpc/mm/ppc_mmu_32.c | 2 +- arch/powerpc/mm/tlb_32.c | 6 +++--- arch/powerpc/platforms/powermac/cpufreq_32.c | 2 +- arch/powerpc/platforms/powermac/setup.c | 2 +- arch/ppc/mm/mmu_context.c | 2 +- drivers/macintosh/via-pmu.c | 4 ++-- include/asm-ppc/mmu.h | 6 ++++-- include/asm-ppc/mmu_context.h | 27 ++++++++++++++++----------- include/asm-ppc/pgtable.h | 2 +- 10 files changed, 31 insertions(+), 24 deletions(-) diff --git a/arch/powerpc/mm/mmu_context_32.c b/arch/powerpc/mm/mmu_context_32.c index a8816e0f6a8..e326e4249e1 100644 --- a/arch/powerpc/mm/mmu_context_32.c +++ b/arch/powerpc/mm/mmu_context_32.c @@ -30,7 +30,7 @@ #include #include -mm_context_t next_mmu_context; +unsigned long next_mmu_context; unsigned long context_map[LAST_CONTEXT / BITS_PER_LONG + 1]; #ifdef FEW_CONTEXTS atomic_t nr_free_contexts; diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c index ed7fcfe5fd3..1df731e42b5 100644 --- a/arch/powerpc/mm/ppc_mmu_32.c +++ b/arch/powerpc/mm/ppc_mmu_32.c @@ -190,7 +190,7 @@ void hash_preload(struct mm_struct *mm, unsigned long ea, return; pmd = pmd_offset(pgd_offset(mm, ea), ea); if (!pmd_none(*pmd)) - add_hash_page(mm->context, ea, pmd_val(*pmd)); + add_hash_page(mm->context.id, ea, pmd_val(*pmd)); } /* diff --git a/arch/powerpc/mm/tlb_32.c b/arch/powerpc/mm/tlb_32.c index ad580f3742e..02eb23e036d 100644 --- a/arch/powerpc/mm/tlb_32.c +++ b/arch/powerpc/mm/tlb_32.c @@ -42,7 +42,7 @@ void flush_hash_entry(struct mm_struct *mm, pte_t *ptep, unsigned long addr) if (Hash != 0) { ptephys = __pa(ptep) & PAGE_MASK; - flush_hash_pages(mm->context, addr, ptephys, 1); + flush_hash_pages(mm->context.id, addr, ptephys, 1); } } @@ -102,7 +102,7 @@ static void flush_range(struct mm_struct *mm, unsigned long start, pmd_t *pmd; unsigned long pmd_end; int count; - unsigned int ctx = mm->context; + unsigned int ctx = mm->context.id; if (Hash == 0) { _tlbia(); @@ -172,7 +172,7 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr) mm = (vmaddr < TASK_SIZE)? vma->vm_mm: &init_mm; pmd = pmd_offset(pgd_offset(mm, vmaddr), vmaddr); if (!pmd_none(*pmd)) - flush_hash_pages(mm->context, vmaddr, pmd_val(*pmd), 1); + flush_hash_pages(mm->context.id, vmaddr, pmd_val(*pmd), 1); FINISH_FLUSH; } diff --git a/arch/powerpc/platforms/powermac/cpufreq_32.c b/arch/powerpc/platforms/powermac/cpufreq_32.c index cfd6527a0d7..af2a8f9f122 100644 --- a/arch/powerpc/platforms/powermac/cpufreq_32.c +++ b/arch/powerpc/platforms/powermac/cpufreq_32.c @@ -314,7 +314,7 @@ static int pmu_set_cpu_speed(int low_speed) _set_L3CR(save_l3cr); /* Restore userland MMU context */ - set_context(current->active_mm->context, current->active_mm->pgd); + set_context(current->active_mm->context.id, current->active_mm->pgd); #ifdef DEBUG_FREQ printk(KERN_DEBUG "HID1, after: %x\n", mfspr(SPRN_HID1)); diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index b9200fb0781..9cc7db7a8bd 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -458,7 +458,7 @@ static int pmac_pm_finish(suspend_state_t state) printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state); /* Restore userland MMU context */ - set_context(current->active_mm->context, current->active_mm->pgd); + set_context(current->active_mm->context.id, current->active_mm->pgd); return 0; } diff --git a/arch/ppc/mm/mmu_context.c b/arch/ppc/mm/mmu_context.c index b4a4b3f02a1..8784f371503 100644 --- a/arch/ppc/mm/mmu_context.c +++ b/arch/ppc/mm/mmu_context.c @@ -30,7 +30,7 @@ #include #include -mm_context_t next_mmu_context; +unsigned long next_mmu_context; unsigned long context_map[LAST_CONTEXT / BITS_PER_LONG + 1]; #ifdef FEW_CONTEXTS atomic_t nr_free_contexts; diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index 0b5ff553e39..c63d4e7984b 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c @@ -2268,7 +2268,7 @@ static int powerbook_sleep_grackle(void) _set_L2CR(save_l2cr); /* Restore userland MMU context */ - set_context(current->active_mm->context, current->active_mm->pgd); + set_context(current->active_mm->context.id, current->active_mm->pgd); /* Power things up */ pmu_unlock(); @@ -2366,7 +2366,7 @@ powerbook_sleep_Core99(void) _set_L3CR(save_l3cr); /* Restore userland MMU context */ - set_context(current->active_mm->context, current->active_mm->pgd); + set_context(current->active_mm->context.id, current->active_mm->pgd); /* Tell PMU we are ready */ pmu_unlock(); diff --git a/include/asm-ppc/mmu.h b/include/asm-ppc/mmu.h index 9205db404c7..80ae60481fb 100644 --- a/include/asm-ppc/mmu.h +++ b/include/asm-ppc/mmu.h @@ -24,8 +24,10 @@ extern phys_addr_t fixup_bigphys_addr(phys_addr_t, phys_addr_t); #define PHYS_FMT "%16Lx" #endif -/* Default "unsigned long" context */ -typedef unsigned long mm_context_t; +typedef struct { + unsigned long id; + unsigned long vdso_base; +} mm_context_t; /* Hardware Page Table Entry */ typedef struct _PTE { diff --git a/include/asm-ppc/mmu_context.h b/include/asm-ppc/mmu_context.h index 4f152cca13c..4454ecf1aed 100644 --- a/include/asm-ppc/mmu_context.h +++ b/include/asm-ppc/mmu_context.h @@ -71,7 +71,7 @@ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) #else /* PPC 6xx, 7xx CPUs */ -#define NO_CONTEXT ((mm_context_t) -1) +#define NO_CONTEXT ((unsigned long) -1) #define LAST_CONTEXT 32767 #define FIRST_CONTEXT 1 #endif @@ -86,7 +86,7 @@ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) * can be used for debugging on all processors (if you happen to have * an Abatron). */ -extern void set_context(mm_context_t context, pgd_t *pgd); +extern void set_context(unsigned long contextid, pgd_t *pgd); /* * Bitmap of contexts in use. @@ -99,7 +99,7 @@ extern unsigned long context_map[]; * Its use is an optimization only, we can't rely on this context * number to be free, but it usually will be. */ -extern mm_context_t next_mmu_context; +extern unsigned long next_mmu_context; /* * If we don't have sufficient contexts to give one to every task @@ -118,9 +118,9 @@ extern void steal_context(void); */ static inline void get_mmu_context(struct mm_struct *mm) { - mm_context_t ctx; + unsigned long ctx; - if (mm->context != NO_CONTEXT) + if (mm->context.id != NO_CONTEXT) return; #ifdef FEW_CONTEXTS while (atomic_dec_if_positive(&nr_free_contexts) < 0) @@ -133,7 +133,7 @@ static inline void get_mmu_context(struct mm_struct *mm) ctx = 0; } next_mmu_context = (ctx + 1) & LAST_CONTEXT; - mm->context = ctx; + mm->context.id = ctx; #ifdef FEW_CONTEXTS context_mm[ctx] = mm; #endif @@ -142,7 +142,12 @@ static inline void get_mmu_context(struct mm_struct *mm) /* * Set up the context for a new address space. */ -#define init_new_context(tsk,mm) (((mm)->context = NO_CONTEXT), 0) +static inline int init_new_context(struct task_struct *t, struct mm_struct *mm) +{ + mm->context.id = NO_CONTEXT; + mm->context.vdso_base = 0; + return 0; +} /* * We're finished using the context for an address space. @@ -150,9 +155,9 @@ static inline void get_mmu_context(struct mm_struct *mm) static inline void destroy_context(struct mm_struct *mm) { preempt_disable(); - if (mm->context != NO_CONTEXT) { - clear_bit(mm->context, context_map); - mm->context = NO_CONTEXT; + if (mm->context.id != NO_CONTEXT) { + clear_bit(mm->context.id, context_map); + mm->context.id = NO_CONTEXT; #ifdef FEW_CONTEXTS atomic_inc(&nr_free_contexts); #endif @@ -180,7 +185,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, /* Setup new userspace context */ get_mmu_context(next); - set_context(next->context, next->pgd); + set_context(next->context.id, next->pgd); } #define deactivate_mm(tsk,mm) do { } while (0) diff --git a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h index 570b355162f..f886066bd15 100644 --- a/include/asm-ppc/pgtable.h +++ b/include/asm-ppc/pgtable.h @@ -663,7 +663,7 @@ static inline int __ptep_test_and_clear_young(unsigned int context, unsigned lon return (old & _PAGE_ACCESSED) != 0; } #define ptep_test_and_clear_young(__vma, __addr, __ptep) \ - __ptep_test_and_clear_young((__vma)->vm_mm->context, __addr, __ptep) + __ptep_test_and_clear_young((__vma)->vm_mm->context.id, __addr, __ptep) #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma, -- cgit v1.2.3 From 1049cb478783c74ca8c99ef70e7d2bf920b9335b Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 8 Jun 2006 22:15:42 -0700 Subject: [PATCH] libata: add missing ->data_xfer for pdc_adma pdc_adma use libata-core PIO path but were left out during ->data_xfer conversion. Initialize with proper callbacks. This patch is against the current libata-dev#ALL. Controllers which implement their own PIO HSM (ahci and sil24) don't need ->data_xfer, so the above two are the only drivers which were left out during conversion. From: "Barry K. Nathan" Signed-off-by: Barry K. Nathan Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/scsi/pdc_adma.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c index eb910e4c7d7..7ebe8e03aa9 100644 --- a/drivers/scsi/pdc_adma.c +++ b/drivers/scsi/pdc_adma.c @@ -168,6 +168,7 @@ static const struct ata_port_operations adma_ata_ops = { .qc_prep = adma_qc_prep, .qc_issue = adma_qc_issue, .eng_timeout = adma_eng_timeout, + .data_xfer = ata_mmio_data_xfer, .irq_handler = adma_intr, .irq_clear = adma_irq_clear, .port_start = adma_port_start, -- cgit v1.2.3 From b47725743cc53203d275ede5c54985ad92c15f42 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Tue, 6 Jun 2006 07:31:14 +0400 Subject: [PATCH] sata_sil24: endian anotations With help from Tejun Heo. Signed-off-by: Alexey Dobriyan Signed-off-by: Jeff Garzik --- drivers/scsi/sata_sil24.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 97e93392f92..c8b477c6724 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -37,9 +37,9 @@ * Port request block (PRB) 32 bytes */ struct sil24_prb { - u16 ctrl; - u16 prot; - u32 rx_cnt; + __le16 ctrl; + __le16 prot; + __le32 rx_cnt; u8 fis[6 * 4]; }; @@ -47,17 +47,17 @@ struct sil24_prb { * Scatter gather entry (SGE) 16 bytes */ struct sil24_sge { - u64 addr; - u32 cnt; - u32 flags; + __le64 addr; + __le32 cnt; + __le32 flags; }; /* * Port multiplier */ struct sil24_port_multiplier { - u32 diag; - u32 sactive; + __le32 diag; + __le32 sactive; }; enum { -- cgit v1.2.3 From bd5d825c9434b83925a88bd30eb9eef51908a3c9 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Sun, 11 Jun 2006 23:17:01 -0400 Subject: libata: Adjust initial debugging levels through preprocessor defines. Signed-off-by: Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 40d16124cc9..3f1aa77621f 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -5181,7 +5181,15 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host, ap->hw_sata_spd_limit = UINT_MAX; ap->active_tag = ATA_TAG_POISON; ap->last_ctl = 0xFF; - ap->msg_enable = ATA_MSG_DRV; + +#if defined(ATA_VERBOSE_DEBUG) + /* turn on all debugging levels */ + ap->msg_enable = 0x00FF; +#elif defined(ATA_DEBUG) + ap->msg_enable = ATA_MSG_DRV | ATA_MSG_INFO | ATA_MSG_CTL | ATA_MSG_WARN | ATA_MSG_ERR; +#else + ap->msg_enable = ATA_MSG_DRV | ATA_MSG_ERR; +#endif INIT_WORK(&ap->port_task, NULL, NULL); INIT_WORK(&ap->hotplug_task, ata_scsi_hotplug, ap); -- cgit v1.2.3 From 233277cad6dacca6a8e53743641cf43ef7f37c4a Mon Sep 17 00:00:00 2001 From: Brian King Date: Wed, 7 Jun 2006 11:25:31 -0500 Subject: [PATCH] libata: Setup nbytes in ata_sg_init_one Setup nbytes in ata_sg_init_one to the total transfer length of the command. This is needed by some HBAs that need to know the total transfer length of each command. Signed-off-by: Brian King Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 3f1aa77621f..76b633a2f30 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3287,6 +3287,7 @@ void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen) qc->n_elem = 1; qc->orig_n_elem = 1; qc->buf_virt = buf; + qc->nbytes = buflen; sg = qc->__sg; sg_init_one(sg, buf, buflen); -- cgit v1.2.3 From 39b07ce6d9f7cd4da8567baed844801e0aaa7b1a Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Sun, 11 Jun 2006 23:59:44 -0400 Subject: libata: more verbose request_irq() failure Suggested by Jarek P. --- drivers/scsi/libata-core.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 76b633a2f30..51b3a0ddb23 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -5293,6 +5293,7 @@ int ata_device_add(const struct ata_probe_ent *ent) unsigned int count = 0, i; struct device *dev = ent->dev; struct ata_host_set *host_set; + int rc; DPRINTK("ENTER\n"); /* alloc a container for our list of ATA ports (buses) */ @@ -5344,9 +5345,13 @@ int ata_device_add(const struct ata_probe_ent *ent) goto err_free_ret; /* obtain irq, that is shared between channels */ - if (request_irq(ent->irq, ent->port_ops->irq_handler, ent->irq_flags, - DRV_NAME, host_set)) + rc = request_irq(ent->irq, ent->port_ops->irq_handler, ent->irq_flags, + DRV_NAME, host_set); + if (rc) { + dev_printk(KERN_ERR, dev, "irq %lu request failed: %d\n", + ent->irq, rc); goto err_out; + } /* perform each probe synchronously */ DPRINTK("probe begin\n"); -- cgit v1.2.3 From 3057ac3c1a992ee135cbb7b7d1a12e58d81f0739 Mon Sep 17 00:00:00 2001 From: "zhao, forrest" Date: Mon, 12 Jun 2006 12:01:34 +0800 Subject: [PATCH] Snoop SET FEATURES - WRITE CACHE ENABLE/DISABLE command(v5) This patch makes libata snoop 'SET FEATURES - WRITE CACHE ENABLE/DISABLE' command, executing requisite revalidation processes to update cached data. Signed-off-by: Forrest Zhao Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 1 + drivers/scsi/libata-eh.c | 3 +++ drivers/scsi/libata-scsi.c | 36 ++++++++++++++++++++++++++++++++++++ drivers/scsi/libata.h | 1 + include/linux/ata.h | 3 +++ 5 files changed, 44 insertions(+) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 51b3a0ddb23..ddaad1a4f1f 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -5194,6 +5194,7 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host, INIT_WORK(&ap->port_task, NULL, NULL); INIT_WORK(&ap->hotplug_task, ata_scsi_hotplug, ap); + INIT_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan, ap); INIT_LIST_HEAD(&ap->eh_done_q); init_waitqueue_head(&ap->eh_wait_q); diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c index 6285257a890..f82799e2258 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/scsi/libata-eh.c @@ -1554,6 +1554,9 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap, if (rc) break; + /* schedule the scsi_rescan_device() here */ + queue_work(ata_aux_wq, &(ap->scsi_rescan_task)); + ehc->i.action &= ~ATA_EH_REVALIDATE; } else if (dev->class == ATA_DEV_UNKNOWN && ehc->tries[dev->devno] && diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 5f90d8e3354..45a49be6504 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -1306,6 +1306,17 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) u8 *cdb = cmd->cmnd; int need_sense = (qc->err_mask != 0); + /* We snoop the SET_FEATURES - Write Cache ON/OFF command, and + * schedule EH_REVALIDATE operation to update the IDENTIFY DEVICE + * cache + */ + if (!need_sense && (qc->tf.command == ATA_CMD_SET_FEATURES) && + ((qc->tf.feature == SETFEATURES_WC_ON) || + (qc->tf.feature == SETFEATURES_WC_OFF))) { + qc->ap->eh_info.action |= ATA_EH_REVALIDATE; + ata_port_schedule_eh(qc->ap); + } + /* For ATA pass thru (SAT) commands, generate a sense block if * user mandated it or if there's an error. Note that if we * generate because the user forced us to, a check condition @@ -2992,3 +3003,28 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel, return rc; } + +/** + * ata_scsi_dev_rescan - initiate scsi_rescan_device() + * @data: Pointer to ATA port to perform scsi_rescan_device() + * + * After ATA pass thru (SAT) commands are executed successfully, + * libata need to propagate the changes to SCSI layer. + * + * LOCKING: + * Kernel thread context (may sleep). + */ +void ata_scsi_dev_rescan(void *data) +{ + struct ata_port *ap = data; + struct ata_device *dev; + unsigned int i; + + for (i = 0; i < ATA_MAX_DEVICES; i++) { + dev = &ap->device[i]; + + if (ata_dev_enabled(dev)) + scsi_rescan_device(&(dev->sdev->sdev_gendev)); + } +} + diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index 1dd496f1f7a..bdd48889709 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -104,6 +104,7 @@ extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args, unsigned int (*actor) (struct ata_scsi_args *args, u8 *rbuf, unsigned int buflen)); extern void ata_schedule_scsi_eh(struct Scsi_Host *shost); +extern void ata_scsi_dev_rescan(void *data); /* libata-eh.c */ extern enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd); diff --git a/include/linux/ata.h b/include/linux/ata.h index c494e1c0531..3671af86969 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -181,6 +181,9 @@ enum { XFER_PIO_0 = 0x08, XFER_PIO_SLOW = 0x00, + SETFEATURES_WC_ON = 0x02, /* Enable write cache */ + SETFEATURES_WC_OFF = 0x82, /* Disable write cache */ + /* ATAPI stuff */ ATAPI_PKT_DMA = (1 << 0), ATAPI_DMADIR = (1 << 2), /* ATAPI data dir: -- cgit v1.2.3 From 3b01b8af2414b6684051da4a1507dfacdbf24f86 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Mon, 12 Jun 2006 00:22:04 -0400 Subject: libata: fix build, by adding required workqueue member to port struct --- include/linux/libata.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/libata.h b/include/linux/libata.h index 39e6b77de1a..61eea5795d5 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -522,6 +522,7 @@ struct ata_port { struct work_struct port_task; struct work_struct hotplug_task; + struct work_struct scsi_rescan_task; unsigned int hsm_task_state; -- cgit v1.2.3 From 23fa9618094975f803ed0c6a44604b16747b9637 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 12 Jun 2006 14:18:51 +0900 Subject: [PATCH] sata_sil: add controller unplug detection in sil_interrupt() Short-circuit interrupt handling if BMDMA2 is reported as 0xffffffff indicating device removal. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/sata_sil.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index 0898cbe6458..a7e99a1def2 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -419,7 +419,8 @@ static irqreturn_t sil_interrupt(int irq, void *dev_instance, if (unlikely(!ap || ap->flags & ATA_FLAG_DISABLED)) continue; - if (!(bmdma2 & (SIL_DMA_COMPLETE | SIL_DMA_SATA_IRQ))) + if (bmdma2 == 0xffffffff || + !(bmdma2 & (SIL_DMA_COMPLETE | SIL_DMA_SATA_IRQ))) continue; sil_host_intr(ap, bmdma2); -- cgit v1.2.3 From 551e8889509c30cda31e464e5cbe7572c4e1febd Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 12 Jun 2006 14:09:49 +0900 Subject: [PATCH] libata: fix comment above ata_exec_internal() Add RETURNS comment above ata_exec_internal() and kill extra blank line. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index ddaad1a4f1f..014855e5a43 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -981,8 +981,10 @@ void ata_qc_complete_internal(struct ata_queued_cmd *qc) * * LOCKING: * None. Should be called with kernel context, might sleep. + * + * RETURNS: + * Zero on success, AC_ERR_* mask on failure */ - unsigned ata_exec_internal(struct ata_device *dev, struct ata_taskfile *tf, const u8 *cdb, int dma_dir, void *buf, unsigned int buflen) -- cgit v1.2.3 From f9be7113b56eb5d013a611d9c65e8d1d2d3f7c94 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 12 Jun 2006 14:11:01 +0900 Subject: [PATCH] libata: fix ATA_EH_REVALIDATE clearing ATA_EH_REVALIDATE should be cleared after all devices on the target port have been revalidated. Fix ata_eh_revalidate_and_attach() accordingly. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-eh.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c index f82799e2258..782dfba573a 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/scsi/libata-eh.c @@ -1556,8 +1556,6 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap, /* schedule the scsi_rescan_device() here */ queue_work(ata_aux_wq, &(ap->scsi_rescan_task)); - - ehc->i.action &= ~ATA_EH_REVALIDATE; } else if (dev->class == ATA_DEV_UNKNOWN && ehc->tries[dev->devno] && ata_class_enabled(ehc->classes[dev->devno])) { @@ -1578,7 +1576,9 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap, } } - if (rc) + if (rc == 0) + ehc->i.action &= ~ATA_EH_REVALIDATE; + else *r_failed_dev = dev; DPRINTK("EXIT\n"); -- cgit v1.2.3 From aeb2ecd6096182cc080d37679080c0f088dcd4a4 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 12 Jun 2006 14:11:43 +0900 Subject: [PATCH] libata: fast exit from EH while unloading Make EH exit fast if the port is being unloaded. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-eh.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c index 782dfba573a..531a4e11c07 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/scsi/libata-eh.c @@ -1680,6 +1680,10 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, down_xfermask = 0; rc = 0; + /* if UNLOADING, finish immediately */ + if (ap->flags & ATA_FLAG_UNLOADING) + goto out; + /* skip EH if possible. */ if (ata_eh_skip_recovery(ap)) ehc->i.action = 0; -- cgit v1.2.3 From 430644312810645a6e05855db50a978df9ba3ad3 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Mon, 12 Jun 2006 18:38:21 +1000 Subject: powerpc: Remove unused paca->pgdir field The pgdir field in the paca was a leftover from the dynamic VSIDs patch, and is not used in the current kernel code. This removes it. Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/asm-offsets.c | 3 --- arch/powerpc/mm/slb.c | 3 --- arch/powerpc/mm/stab.c | 4 ---- include/asm-powerpc/mmu_context.h | 12 ------------ include/asm-powerpc/paca.h | 3 --- 5 files changed, 25 deletions(-) diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 8f85c5e8a55..aa0486d552a 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -122,9 +122,6 @@ int main(void) DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache)); DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr)); DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id)); -#ifdef CONFIG_PPC_64K_PAGES - DEFINE(PACAPGDIR, offsetof(struct paca_struct, pgdir)); -#endif #ifdef CONFIG_HUGETLB_PAGE DEFINE(PACALOWHTLBAREAS, offsetof(struct paca_struct, context.low_htlb_areas)); DEFINE(PACAHIGHHTLBAREAS, offsetof(struct paca_struct, context.high_htlb_areas)); diff --git a/arch/powerpc/mm/slb.c b/arch/powerpc/mm/slb.c index ffc8ed4de62..2cc61736fee 100644 --- a/arch/powerpc/mm/slb.c +++ b/arch/powerpc/mm/slb.c @@ -122,9 +122,6 @@ void switch_slb(struct task_struct *tsk, struct mm_struct *mm) get_paca()->slb_cache_ptr = 0; get_paca()->context = mm->context; -#ifdef CONFIG_PPC_64K_PAGES - get_paca()->pgdir = mm->pgd; -#endif /* CONFIG_PPC_64K_PAGES */ /* * preload some userspace segments into the SLB. diff --git a/arch/powerpc/mm/stab.c b/arch/powerpc/mm/stab.c index 4a9291d9fef..691320c90b7 100644 --- a/arch/powerpc/mm/stab.c +++ b/arch/powerpc/mm/stab.c @@ -200,10 +200,6 @@ void switch_stab(struct task_struct *tsk, struct mm_struct *mm) __get_cpu_var(stab_cache_ptr) = 0; -#ifdef CONFIG_PPC_64K_PAGES - get_paca()->pgdir = mm->pgd; -#endif /* CONFIG_PPC_64K_PAGES */ - /* Now preload some entries for the new task */ if (test_tsk_thread_flag(tsk, TIF_32BIT)) unmapped_base = TASK_UNMAPPED_BASE_USER32; diff --git a/include/asm-powerpc/mmu_context.h b/include/asm-powerpc/mmu_context.h index 1b8a25fd48f..8c6b1a6d944 100644 --- a/include/asm-powerpc/mmu_context.h +++ b/include/asm-powerpc/mmu_context.h @@ -20,16 +20,9 @@ * 2 of the License, or (at your option) any later version. */ -/* - * Getting into a kernel thread, there is no valid user segment, mark - * paca->pgdir NULL so that SLB miss on user addresses will fault - */ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) { -#ifdef CONFIG_PPC_64K_PAGES - get_paca()->pgdir = NULL; -#endif /* CONFIG_PPC_64K_PAGES */ } #define NO_CONTEXT 0 @@ -52,13 +45,8 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, cpu_set(smp_processor_id(), next->cpu_vm_mask); /* No need to flush userspace segments if the mm doesnt change */ -#ifdef CONFIG_PPC_64K_PAGES - if (prev == next && get_paca()->pgdir == next->pgd) - return; -#else if (prev == next) return; -#endif /* CONFIG_PPC_64K_PAGES */ #ifdef CONFIG_ALTIVEC if (cpu_has_feature(CPU_FTR_ALTIVEC)) diff --git a/include/asm-powerpc/paca.h b/include/asm-powerpc/paca.h index 706325f99a8..c17fd54d995 100644 --- a/include/asm-powerpc/paca.h +++ b/include/asm-powerpc/paca.h @@ -79,9 +79,6 @@ struct paca_struct { u64 exmc[10]; /* used for machine checks */ u64 exslb[10]; /* used for SLB/segment table misses * on the linear mapping */ -#ifdef CONFIG_PPC_64K_PAGES - pgd_t *pgdir; -#endif /* CONFIG_PPC_64K_PAGES */ mm_context_t context; u16 slb_cache[SLB_CACHE_ENTRIES]; -- cgit v1.2.3 From d4c85325a817d3351e61c4be64b437116e8483b4 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 12 Jun 2006 18:45:55 +0900 Subject: [PATCH] sata_sil: update device hotplug handling, take #2 SIEN on some 3112 controllers doesn't mask SATA IRQ properly. IRQ stays asserted even after SIEN is masked and IRQ is acked. Also, even while frozen, any SATA PHY event including hardreset raises SATA IRQ. Clearing SError seems to be the only way to deassert SATA IRQ. This patch makes sil_host_intr() clear SError on SATA IRQs and ignore SATA IRQs reported while frozen so that hardreset doesn't trigger hotplug event (which ends up hardresetting again). In such cases, the port still gets re-frozen to minimize the danger of screaming interrupts. This results in one nil EH repeat on controllers with broken SIEN but other than that does no harm. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/sata_sil.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index a7e99a1def2..bc9f918a7f2 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -344,7 +344,25 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2) u8 status; if (unlikely(bmdma2 & SIL_DMA_SATA_IRQ)) { - ata_ehi_hotplugged(&ap->eh_info); + u32 serror; + + /* SIEN doesn't mask SATA IRQs on some 3112s. Those + * controllers continue to assert IRQ as long as + * SError bits are pending. Clear SError immediately. + */ + serror = sil_scr_read(ap, SCR_ERROR); + sil_scr_write(ap, SCR_ERROR, serror); + + /* Trigger hotplug and accumulate SError only if the + * port isn't already frozen. Otherwise, PHY events + * during hardreset makes controllers with broken SIEN + * repeat probing needlessly. + */ + if (!(ap->flags & ATA_FLAG_FROZEN)) { + ata_ehi_hotplugged(&ap->eh_info); + ap->eh_info.serror |= serror; + } + goto freeze; } -- cgit v1.2.3 From d01712698c7c52bc71f41192e864dccc90a1217d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 12 Jun 2006 22:51:14 +0900 Subject: [PATCH] libata: fix oops caused rescanning NULL sdev Depending on timing, ata_scsi_dev_rescan() might encounter a device which is enabled but not yet attached to sdev. On such cases, the original code caused oops. This patch makes ata_scsi_dev_rescan() rescan only device which are attached to sdevs. While at it, properly indent leading comment and add description about how it's synchronized with sdev attach/detach. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-scsi.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 45a49be6504..32c1df69091 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -3005,14 +3005,16 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel, } /** - * ata_scsi_dev_rescan - initiate scsi_rescan_device() - * @data: Pointer to ATA port to perform scsi_rescan_device() + * ata_scsi_dev_rescan - initiate scsi_rescan_device() + * @data: Pointer to ATA port to perform scsi_rescan_device() * - * After ATA pass thru (SAT) commands are executed successfully, - * libata need to propagate the changes to SCSI layer. + * After ATA pass thru (SAT) commands are executed successfully, + * libata need to propagate the changes to SCSI layer. This + * function must be executed from ata_aux_wq such that sdev + * attach/detach don't race with rescan. * - * LOCKING: - * Kernel thread context (may sleep). + * LOCKING: + * Kernel thread context (may sleep). */ void ata_scsi_dev_rescan(void *data) { @@ -3023,8 +3025,7 @@ void ata_scsi_dev_rescan(void *data) for (i = 0; i < ATA_MAX_DEVICES; i++) { dev = &ap->device[i]; - if (ata_dev_enabled(dev)) + if (ata_dev_enabled(dev) && dev->sdev) scsi_rescan_device(&(dev->sdev->sdev_gendev)); } } - -- cgit v1.2.3 From f0eb62b81dd16bfc4034916418c3406ba20011e1 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 12 Jun 2006 23:05:38 +0900 Subject: [PATCH] libata: add host_set->next for legacy two host_sets case, take #3 For a legacy ATA controller, libata registers two separate host sets. There was no connection between the two hosts making it impossible to traverse all ports related to the controller. This patch adds host_set->next which points to the second host_set and makes ata_pci_remove_one() remove all associated host_sets. * On device removal, all ports hanging off the device are properly detached. Prior to this patch, ports on the first host_set weren't detached casuing oops on driver unloading. * On device removal, both host_sets are properly freed This will also be used by new power management code to suspend and resume all ports of a controller. host_set/port representation will be improved to handle legacy controllers better and this host_set linking will go away with it. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-bmdma.c | 15 +++++++++++++-- drivers/scsi/libata-core.c | 4 ++++ include/linux/libata.h | 3 ++- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/libata-bmdma.c b/drivers/scsi/libata-bmdma.c index 4bc05371737..13fab97c840 100644 --- a/drivers/scsi/libata-bmdma.c +++ b/drivers/scsi/libata-bmdma.c @@ -1076,10 +1076,21 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, /* FIXME: check ata_device_add return */ if (legacy_mode) { - if (legacy_mode & (1 << 0)) + struct device *dev = &pdev->dev; + struct ata_host_set *host_set = NULL; + + if (legacy_mode & (1 << 0)) { ata_device_add(probe_ent); - if (legacy_mode & (1 << 1)) + host_set = dev_get_drvdata(dev); + } + + if (legacy_mode & (1 << 1)) { ata_device_add(probe_ent2); + if (host_set) { + host_set->next = dev_get_drvdata(dev); + dev_set_drvdata(dev, host_set); + } + } } else ata_device_add(probe_ent); diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 014855e5a43..d73cb3672d6 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -5621,8 +5621,12 @@ void ata_pci_remove_one (struct pci_dev *pdev) { struct device *dev = pci_dev_to_dev(pdev); struct ata_host_set *host_set = dev_get_drvdata(dev); + struct ata_host_set *host_set2 = host_set->next; ata_host_set_remove(host_set); + if (host_set2) + ata_host_set_remove(host_set2); + pci_release_regions(pdev); pci_disable_device(pdev); dev_set_drvdata(dev, NULL); diff --git a/include/linux/libata.h b/include/linux/libata.h index 61eea5795d5..f03b8664af1 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -356,7 +356,8 @@ struct ata_host_set { unsigned long flags; int simplex_claimed; /* Keep seperate in case we ever need to do this locked */ - struct ata_port * ports[0]; + struct ata_host_set *next; /* for legacy mode */ + struct ata_port *ports[0]; }; struct ata_queued_cmd { -- cgit v1.2.3 From c5943d36aebb79589ac3983eec418bbeca897573 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Mon, 12 Jun 2006 09:09:18 -0500 Subject: [SCSI] scsi_transport_sas: fix panic in sas_free_rphy This is a hold over from the end device/expander conversion. Apparently the rphy list pointer is never initialised, so list_del() on the uninitialised pointer can panic the system Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_sas.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index 6da6721eb0d..1fe6b2d0185 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -747,6 +747,18 @@ static void sas_end_device_release(struct device *dev) kfree(edev); } +/** + * sas_rphy_initialize - common rphy intialization + * @rphy: rphy to initialise + * + * Used by both sas_end_device_alloc() and sas_expander_alloc() to + * initialise the common rphy component of each. + */ +static void sas_rphy_initialize(struct sas_rphy *rphy) +{ + INIT_LIST_HEAD(&rphy->list); +} + /** * sas_end_device_alloc - allocate an rphy for an end device * @@ -771,6 +783,7 @@ struct sas_rphy *sas_end_device_alloc(struct sas_phy *parent) sprintf(rdev->rphy.dev.bus_id, "end_device-%d:%d-%d", shost->host_no, parent->port_identifier, parent->number); rdev->rphy.identify.device_type = SAS_END_DEVICE; + sas_rphy_initialize(&rdev->rphy); transport_setup_device(&rdev->rphy.dev); return &rdev->rphy; @@ -809,6 +822,7 @@ struct sas_rphy *sas_expander_alloc(struct sas_phy *parent, sprintf(rdev->rphy.dev.bus_id, "expander-%d:%d", shost->host_no, rdev->rphy.scsi_target_id); rdev->rphy.identify.device_type = type; + sas_rphy_initialize(&rdev->rphy); transport_setup_device(&rdev->rphy.dev); return &rdev->rphy; -- cgit v1.2.3 From 821499a8241019be5591fad5ab925759fbcd9f32 Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Mon, 12 Jun 2006 10:53:58 -0700 Subject: [SCSI] aacraid: Fix return code interpretation Received from Mark Salyzyn clear_user return is 0 for success, the code fragment is written to assume that it is the count of the number of bytes zero'd. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley --- drivers/scsi/aacraid/linit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 9647dabc661..03fe2abcc4f 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -564,7 +564,7 @@ static long aac_compat_do_ioctl(struct aac_dev *dev, unsigned cmd, unsigned long f = compat_alloc_user_space(sizeof(*f)); ret = 0; - if (clear_user(f, sizeof(*f)) != sizeof(*f)) + if (clear_user(f, sizeof(*f))) ret = -EFAULT; if (copy_in_user(f, (void __user *)arg, sizeof(struct fib_ioctl) - sizeof(u32))) ret = -EFAULT; -- cgit v1.2.3 From f54b1bdff1b470ff4461de3a73a7ceaf3a52e10a Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Mon, 12 Jun 2006 17:52:16 -0400 Subject: video1394: be quiet When working with multiple cameras and intensive applications, our logs get flooded with video1394 information which isn't of much interest. Any objections to demoting these messages to debug messages? Signed-off-by: Daniel Drake Signed-off-by: Ben Collins --- drivers/ieee1394/video1394.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c index 4e3bd62c458..295d0f8c3d0 100644 --- a/drivers/ieee1394/video1394.c +++ b/drivers/ieee1394/video1394.c @@ -331,7 +331,7 @@ alloc_dma_iso_ctx(struct ti_ohci *ohci, int type, int num_desc, spin_lock_init(&d->lock); - PRINT(KERN_INFO, ohci->host->id, "Iso %s DMA: %d buffers " + DBGMSG(ohci->host->id, "Iso %s DMA: %d buffers " "of size %d allocated for a frame size %d, each with %d prgs", (type == OHCI_ISO_RECEIVE) ? "receive" : "transmit", d->num_desc - 1, d->buf_size, d->frame_size, d->nb_cmd); @@ -759,7 +759,7 @@ static int __video1394_ioctl(struct file *file, } else { mask = (u64)0x1<host->id, "mask: %08X%08X usage: %08X%08X\n", + DBGMSG(ohci->host->id, "mask: %08X%08X usage: %08X%08X\n", (u32)(mask>>32),(u32)(mask&0xffffffff), (u32)(ohci->ISO_channel_usage>>32), (u32)(ohci->ISO_channel_usage&0xffffffff)); @@ -805,7 +805,7 @@ static int __video1394_ioctl(struct file *file, v.buf_size = d->buf_size; list_add_tail(&d->link, &ctx->context_list); - PRINT(KERN_INFO, ohci->host->id, + DBGMSG(ohci->host->id, "iso context %d listen on channel %d", d->ctx, v.channel); } @@ -828,7 +828,7 @@ static int __video1394_ioctl(struct file *file, list_add_tail(&d->link, &ctx->context_list); - PRINT(KERN_INFO, ohci->host->id, + DBGMSG(ohci->host->id, "Iso context %d talk on channel %d", d->ctx, v.channel); } @@ -873,7 +873,7 @@ static int __video1394_ioctl(struct file *file, d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, channel); if (d == NULL) return -ESRCH; - PRINT(KERN_INFO, ohci->host->id, "Iso context %d " + DBGMSG(ohci->host->id, "Iso context %d " "stop talking on channel %d", d->ctx, channel); free_dma_iso_ctx(d); @@ -935,7 +935,7 @@ static int __video1394_ioctl(struct file *file, else { /* Wake up dma context if necessary */ if (!(reg_read(ohci, d->ctrlSet) & 0x400)) { - PRINT(KERN_INFO, ohci->host->id, + DBGMSG(ohci->host->id, "Waking up iso dma ctx=%d", d->ctx); reg_write(ohci, d->ctrlSet, 0x1000); } @@ -1106,7 +1106,7 @@ static int __video1394_ioctl(struct file *file, else { /* Wake up dma context if necessary */ if (!(reg_read(ohci, d->ctrlSet) & 0x400)) { - PRINT(KERN_INFO, ohci->host->id, + DBGMSG(ohci->host->id, "Waking up iso transmit dma ctx=%d", d->ctx); put_timestamp(ohci, d, d->last_buffer); @@ -1232,7 +1232,7 @@ static int video1394_release(struct inode *inode, struct file *file) "is not being used", d->channel); else ohci->ISO_channel_usage &= ~mask; - PRINT(KERN_INFO, ohci->host->id, "On release: Iso %s context " + DBGMSG(ohci->host->id, "On release: Iso %s context " "%d stop listening on channel %d", d->type == OHCI_ISO_RECEIVE ? "receive" : "transmit", d->ctx, d->channel); -- cgit v1.2.3 From 9bb2bcdb4b6f9a04363c8ea4cf72c592d6c7af71 Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Mon, 12 Jun 2006 17:52:59 -0400 Subject: ieee1394: speed up of dma_region_sync_for_cpu when attempting to find the 'last' part of the dma region continue the search from where we left off, instead of starting the search over. Signed-off-by: Jim Westfall Signed-off-by: Ben Collins --- drivers/ieee1394/dma.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/ieee1394/dma.c b/drivers/ieee1394/dma.c index 9fb2769d9ab..ca5167de707 100644 --- a/drivers/ieee1394/dma.c +++ b/drivers/ieee1394/dma.c @@ -145,12 +145,12 @@ void dma_region_free(struct dma_region *dma) /* find the scatterlist index and remaining offset corresponding to a given offset from the beginning of the buffer */ static inline int dma_region_find(struct dma_region *dma, unsigned long offset, - unsigned long *rem) + unsigned int start, unsigned long *rem) { int i; unsigned long off = offset; - for (i = 0; i < dma->n_dma_pages; i++) { + for (i = start; i < dma->n_dma_pages; i++) { if (off < sg_dma_len(&dma->sglist[i])) { *rem = off; break; @@ -170,7 +170,7 @@ dma_addr_t dma_region_offset_to_bus(struct dma_region * dma, unsigned long rem = 0; struct scatterlist *sg = - &dma->sglist[dma_region_find(dma, offset, &rem)]; + &dma->sglist[dma_region_find(dma, offset, 0, &rem)]; return sg_dma_address(sg) + rem; } @@ -178,13 +178,13 @@ void dma_region_sync_for_cpu(struct dma_region *dma, unsigned long offset, unsigned long len) { int first, last; - unsigned long rem; + unsigned long rem = 0; if (!len) len = 1; - first = dma_region_find(dma, offset, &rem); - last = dma_region_find(dma, offset + len - 1, &rem); + first = dma_region_find(dma, offset, 0, &rem); + last = dma_region_find(dma, rem + len - 1, first, &rem); pci_dma_sync_sg_for_cpu(dma->dev, &dma->sglist[first], last - first + 1, dma->direction); @@ -194,13 +194,13 @@ void dma_region_sync_for_device(struct dma_region *dma, unsigned long offset, unsigned long len) { int first, last; - unsigned long rem; + unsigned long rem = 0; if (!len) len = 1; - first = dma_region_find(dma, offset, &rem); - last = dma_region_find(dma, offset + len - 1, &rem); + first = dma_region_find(dma, offset, 0, &rem); + last = dma_region_find(dma, rem + len - 1, first, &rem); pci_dma_sync_sg_for_device(dma->dev, &dma->sglist[first], last - first + 1, dma->direction); -- cgit v1.2.3 From ff34d3bddf2a1d7ae1e96a25e73e16042778c4c4 Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Mon, 12 Jun 2006 17:53:31 -0400 Subject: ohci1394: Remove superfluous call to free_dma_rcv_ctx, spotted by Adrian Bunk. Also remove some superfluous comments. Signed-off-by: Stefan Richter Signed-off-by: Ben Collins --- drivers/ieee1394/ohci1394.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index 11f13778f13..8c43065a605 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c @@ -3462,24 +3462,13 @@ static void ohci1394_pci_remove(struct pci_dev *pdev) case OHCI_INIT_HAVE_TXRX_BUFFERS__MAYBE: /* The ohci_soft_reset() stops all DMA contexts, so we * dont need to do this. */ - /* Free AR dma */ free_dma_rcv_ctx(&ohci->ar_req_context); free_dma_rcv_ctx(&ohci->ar_resp_context); - - /* Free AT dma */ free_dma_trm_ctx(&ohci->at_req_context); free_dma_trm_ctx(&ohci->at_resp_context); - - /* Free IR dma */ free_dma_rcv_ctx(&ohci->ir_legacy_context); - - /* Free IT dma */ free_dma_trm_ctx(&ohci->it_legacy_context); - /* Free IR legacy dma */ - free_dma_rcv_ctx(&ohci->ir_legacy_context); - - case OHCI_INIT_HAVE_SELFID_BUFFER: pci_free_consistent(ohci->dev, OHCI1394_SI_DMA_BUF_SIZE, ohci->selfid_buf_cpu, -- cgit v1.2.3 From 4b9a334703cf99a1a5b9f64cf9f028e3e1ae91ff Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Mon, 12 Jun 2006 18:10:18 -0400 Subject: sbp2: make TSB42AA9 workaround specific to Momobay CX-1 The workarounds are not required for DViCO Momobay FX-3A and AFAIR not for Momobay CX-2. These contain an TSB42AA9A but feature the same firmware_revision value as the older DViCO Momobay CX-1. Signed-off-by: Stefan Richter Signed-off-by: Ben Collins --- drivers/ieee1394/sbp2.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 5413dc43b9f..24cd1e250d8 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -306,8 +306,9 @@ static const struct { u32 model_id; unsigned workarounds; } sbp2_workarounds_table[] = { - /* TSB42AA9 */ { + /* DViCO Momobay CX-1 with TSB42AA9 bridge */ { .firmware_revision = 0x002800, + .model_id = 0x001010, .workarounds = SBP2_WORKAROUND_INQUIRY_36 | SBP2_WORKAROUND_MODE_SENSE_8, }, -- cgit v1.2.3 From fa7614de60d10460a607c3ca22ea080d021c3fef Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Mon, 12 Jun 2006 18:11:07 -0400 Subject: From: Arjan van de Ven Semaphore to mutex conversion. The conversion was generated via scripts, and the result was validated automatically via a script as well. Signed-off-by: Arjan van de Ven Signed-off-by: Ingo Molnar Cc: Ben Collins Cc: Jody McIntyre Signed-off-by: Andrew Morton Signed-off-by: Ben Collins --- drivers/ieee1394/hosts.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/ieee1394/hosts.c b/drivers/ieee1394/hosts.c index ba09741fc82..2d47b11777a 100644 --- a/drivers/ieee1394/hosts.c +++ b/drivers/ieee1394/hosts.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "csr1212.h" #include "ieee1394.h" @@ -105,7 +106,7 @@ static int alloc_hostnum_cb(struct hpsb_host *host, void *__data) * Return Value: a pointer to the &hpsb_host if succesful, %NULL if * no memory was available. */ -static DECLARE_MUTEX(host_num_alloc); +static DEFINE_MUTEX(host_num_alloc); struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra, struct device *dev) @@ -148,7 +149,7 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra, h->topology_map = h->csr.topology_map + 3; h->speed_map = (u8 *)(h->csr.speed_map + 2); - down(&host_num_alloc); + mutex_lock(&host_num_alloc); while (nodemgr_for_each_host(&hostnum, alloc_hostnum_cb)) hostnum++; @@ -167,7 +168,7 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra, class_device_register(&h->class_dev); get_device(&h->device); - up(&host_num_alloc); + mutex_unlock(&host_num_alloc); return h; } -- cgit v1.2.3 From 7597028a833b6bfafae0a8fbc18992a278467adf Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Mon, 12 Jun 2006 18:12:10 -0400 Subject: raw1394: fix whitespace after x86_64 compat patch Signed-off-by: Stefan Richter Signed-off-by: Ben Collins --- drivers/ieee1394/raw1394.c | 54 ++++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c index f7de546f2ed..20ce539580f 100644 --- a/drivers/ieee1394/raw1394.c +++ b/drivers/ieee1394/raw1394.c @@ -408,34 +408,34 @@ static void fcp_request(struct hpsb_host *host, int nodeid, int direction, #ifdef CONFIG_COMPAT struct compat_raw1394_req { - __u32 type; - __s32 error; - __u32 misc; + __u32 type; + __s32 error; + __u32 misc; - __u32 generation; - __u32 length; + __u32 generation; + __u32 length; - __u64 address; + __u64 address; - __u64 tag; + __u64 tag; - __u64 sendb; - __u64 recvb; -} __attribute__((packed)); + __u64 sendb; + __u64 recvb; +} __attribute__((packed)); static const char __user *raw1394_compat_write(const char __user *buf) { - struct compat_raw1394_req __user *cr = (typeof(cr)) buf; + struct compat_raw1394_req __user *cr = (typeof(cr)) buf; struct raw1394_request __user *r; r = compat_alloc_user_space(sizeof(struct raw1394_request)); #define C(x) __copy_in_user(&r->x, &cr->x, sizeof(r->x)) if (copy_in_user(r, cr, sizeof(struct compat_raw1394_req)) || - C(address) || - C(tag) || - C(sendb) || - C(recvb)) + C(address) || + C(tag) || + C(sendb) || + C(recvb)) return ERR_PTR(-EFAULT); return (const char __user *)r; } @@ -443,11 +443,11 @@ static const char __user *raw1394_compat_write(const char __user *buf) #define P(x) __put_user(r->x, &cr->x) -static int +static int raw1394_compat_read(const char __user *buf, struct raw1394_request *r) { - struct compat_raw1394_req __user *cr = (typeof(cr)) r; - if (!access_ok(VERIFY_WRITE,cr,sizeof(struct compat_raw1394_req)) || + struct compat_raw1394_req __user *cr = (typeof(cr)) r; + if (!access_ok(VERIFY_WRITE, cr, sizeof(struct compat_raw1394_req)) || P(type) || P(error) || P(misc) || @@ -512,18 +512,17 @@ static ssize_t raw1394_read(struct file *file, char __user * buffer, } #ifdef CONFIG_COMPAT - if (count == sizeof(struct compat_raw1394_req) && - sizeof(struct compat_raw1394_req) != - sizeof(struct raw1394_request)) { + if (count == sizeof(struct compat_raw1394_req) && + sizeof(struct compat_raw1394_req) != + sizeof(struct raw1394_request)) { ret = raw1394_compat_read(buffer, &req->req); - - } else + } else #endif { if (copy_to_user(buffer, &req->req, sizeof(req->req))) { ret = -EFAULT; goto out; - } + } ret = (ssize_t) sizeof(struct raw1394_request); } out: @@ -2348,7 +2347,6 @@ static int state_connected(struct file_info *fi, struct pending_request *req) return handle_async_request(fi, req, node); } - static ssize_t raw1394_write(struct file *file, const char __user * buffer, size_t count, loff_t * offset_is_ignored) { @@ -2357,9 +2355,9 @@ static ssize_t raw1394_write(struct file *file, const char __user * buffer, ssize_t retval = 0; #ifdef CONFIG_COMPAT - if (count == sizeof(struct compat_raw1394_req) && - sizeof(struct compat_raw1394_req) != - sizeof(struct raw1394_request)) { + if (count == sizeof(struct compat_raw1394_req) && + sizeof(struct compat_raw1394_req) != + sizeof(struct raw1394_request)) { buffer = raw1394_compat_write(buffer); if (IS_ERR(buffer)) return PTR_ERR(buffer); -- cgit v1.2.3 From 57fdb58fa5a140bdd52cf4c4ffc30df73676f0a5 Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Mon, 12 Jun 2006 18:12:21 -0400 Subject: ieee1394/ohci1394: CycleTooLong interrupt management This patch modifies the ohci1394.c file to enable and manage the "cycle too long" interrupt. If this interrupt occurs, the "LinkControl.CycleMaster" bit of the host controller is reseted. This implies, that the host controller does not send "cycle start" packet anymore freezing then the isochronous communication. The management of the interrupt added by the patch is that when the interrupt occurs, the OHCI irq handler prints a kernel log warning and then sets the "LinkControl.CycleMaster" bit again resuming the isochronous communication. Signed-off-by: Jean-Baptiste Mur Signed-off-by: Stefan Richter Signed-off-by: Ben Collins --- drivers/ieee1394/ohci1394.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index 8c43065a605..643094c3339 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c @@ -580,6 +580,7 @@ static void ohci_initialize(struct ti_ohci *ohci) OHCI1394_isochRx | OHCI1394_isochTx | OHCI1394_postedWriteErr | + OHCI1394_cycleTooLong | OHCI1394_cycleInconsistent); /* Enable link */ @@ -2386,6 +2387,15 @@ static irqreturn_t ohci_irq_handler(int irq, void *dev_id, PRINT(KERN_ERR, "physical posted write error"); /* no recovery strategy yet, had to involve protocol drivers */ } + if (event & OHCI1394_cycleTooLong) { + if(printk_ratelimit()) + PRINT(KERN_WARNING, "isochronous cycle too long"); + else + DBGMSG("OHCI1394_cycleTooLong"); + reg_write(ohci, OHCI1394_LinkControlSet, + OHCI1394_LinkControl_CycleMaster); + event &= ~OHCI1394_cycleTooLong; + } if (event & OHCI1394_cycleInconsistent) { /* We subscribe to the cycleInconsistent event only to * clear the corresponding event bit... otherwise, -- cgit v1.2.3 From 647dcb5fae0ebb5da1272ed2773df0d3f152c303 Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Mon, 12 Jun 2006 18:12:37 -0400 Subject: ieee1394: support for slow links or slow 1394b phy ports Add support for the following types of hardware: + nodes that have a link speed < PHY speed + 1394b PHYs that are less than S800 capable + 1394b/1394a adapter cable between two 1394b PHYs Also, S1600 and S3200 are now supported if IEEE1394_SPEED_MAX is raised. A probing function is added to nodemgr's config ROM fetching routine which adjusts the allowable speed if an access problem was encountered. Pros and Cons of the approach: + minimum code footprint to support this less widely used hardware + nearly no overhead for unaffected hardware - ineffective before nodemgr began to read the ROM of affected nodes - ineffective if ieee1394 is loaded with disable_nodemgr=1 The speed map CSRs which are published to the bus are not touched by the patch. Signed-off-by: Stefan Richter Cc: Hakan Ardo Cc: Calculex Cc: Robert J. Kosinski Signed-off-by: Ben Collins --- drivers/ieee1394/eth1394.c | 6 ++-- drivers/ieee1394/hosts.h | 11 ++++---- drivers/ieee1394/ieee1394_core.c | 14 +++++---- drivers/ieee1394/nodemgr.c | 61 ++++++++++++++++++++++++++++++++++++++-- drivers/ieee1394/sbp2.c | 4 +-- 5 files changed, 76 insertions(+), 20 deletions(-) diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c index 30fa0d43a43..b2d2c4dd075 100644 --- a/drivers/ieee1394/eth1394.c +++ b/drivers/ieee1394/eth1394.c @@ -502,10 +502,8 @@ static void ether1394_reset_priv (struct net_device *dev, int set_mtu) /* Determine speed limit */ for (i = 0; i < host->node_count; i++) - if (max_speed > host->speed_map[NODEID_TO_NODE(host->node_id) * - 64 + i]) - max_speed = host->speed_map[NODEID_TO_NODE(host->node_id) * - 64 + i]; + if (max_speed > host->speed[i]) + max_speed = host->speed[i]; priv->bc_sspd = max_speed; /* We'll use our maxpayload as the default mtu */ diff --git a/drivers/ieee1394/hosts.h b/drivers/ieee1394/hosts.h index 07d188ca849..d1a47607cb8 100644 --- a/drivers/ieee1394/hosts.h +++ b/drivers/ieee1394/hosts.h @@ -30,12 +30,13 @@ struct hpsb_host { unsigned char iso_listen_count[64]; - int node_count; /* number of identified nodes on this bus */ - int selfid_count; /* total number of SelfIDs received */ - int nodes_active; /* number of nodes that are actually active */ + int node_count; /* number of identified nodes on this bus */ + int selfid_count; /* total number of SelfIDs received */ + int nodes_active; /* number of nodes with active link layer */ + u8 speed[63]; /* speed between each node and local node */ - nodeid_t node_id; /* node ID of this host */ - nodeid_t irm_id; /* ID of this bus' isochronous resource manager */ + nodeid_t node_id; /* node ID of this host */ + nodeid_t irm_id; /* ID of this bus' isochronous resource manager */ nodeid_t busmgr_id; /* ID of this bus' bus manager */ /* this nodes state */ diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c index be6854e25ad..c83e2b8295e 100644 --- a/drivers/ieee1394/ieee1394_core.c +++ b/drivers/ieee1394/ieee1394_core.c @@ -285,9 +285,9 @@ static int check_selfids(struct hpsb_host *host) static void build_speed_map(struct hpsb_host *host, int nodecount) { - u8 speedcap[nodecount]; u8 cldcnt[nodecount]; u8 *map = host->speed_map; + u8 *speedcap = host->speed; struct selfid *sid; struct ext_selfid *esid; int i, j, n; @@ -354,6 +354,11 @@ static void build_speed_map(struct hpsb_host *host, int nodecount) } } } + + /* assume maximum speed for 1394b PHYs, nodemgr will correct it */ + for (n = 0; n < nodecount; n++) + if (speedcap[n] == 3) + speedcap[n] = IEEE1394_SPEED_MAX; } @@ -554,11 +559,10 @@ int hpsb_send_packet(struct hpsb_packet *packet) return 0; } - if (packet->type == hpsb_async && packet->node_id != ALL_NODES) { + if (packet->type == hpsb_async && + NODEID_TO_NODE(packet->node_id) != ALL_NODES) packet->speed_code = - host->speed_map[NODEID_TO_NODE(host->node_id) * 64 - + NODEID_TO_NODE(packet->node_id)]; - } + host->speed[NODEID_TO_NODE(packet->node_id)]; dump_packet("send packet", packet->header, packet->header_size, packet->speed_code); diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index 082c7fd239f..948f1b8c423 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c @@ -38,6 +38,7 @@ struct nodemgr_csr_info { struct hpsb_host *host; nodeid_t nodeid; unsigned int generation; + unsigned int speed_unverified:1; }; @@ -57,23 +58,75 @@ static char *nodemgr_find_oui_name(int oui) return NULL; } +/* + * Correct the speed map entry. This is necessary + * - for nodes with link speed < phy speed, + * - for 1394b nodes with negotiated phy port speed < IEEE1394_SPEED_MAX. + * A possible speed is determined by trial and error, using quadlet reads. + */ +static int nodemgr_check_speed(struct nodemgr_csr_info *ci, u64 addr, + quadlet_t *buffer) +{ + quadlet_t q; + u8 i, *speed, old_speed, good_speed; + int ret; + + speed = ci->host->speed + NODEID_TO_NODE(ci->nodeid); + old_speed = *speed; + good_speed = IEEE1394_SPEED_MAX + 1; + + /* Try every speed from S100 to old_speed. + * If we did it the other way around, a too low speed could be caught + * if the retry succeeded for some other reason, e.g. because the link + * just finished its initialization. */ + for (i = IEEE1394_SPEED_100; i <= old_speed; i++) { + *speed = i; + ret = hpsb_read(ci->host, ci->nodeid, ci->generation, addr, + &q, sizeof(quadlet_t)); + if (ret) + break; + *buffer = q; + good_speed = i; + } + if (good_speed <= IEEE1394_SPEED_MAX) { + HPSB_DEBUG("Speed probe of node " NODE_BUS_FMT " yields %s", + NODE_BUS_ARGS(ci->host, ci->nodeid), + hpsb_speedto_str[good_speed]); + *speed = good_speed; + ci->speed_unverified = 0; + return 0; + } + *speed = old_speed; + return ret; +} static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr, u16 length, void *buffer, void *__ci) { struct nodemgr_csr_info *ci = (struct nodemgr_csr_info*)__ci; - int i, ret = 0; + int i, ret; for (i = 1; ; i++) { ret = hpsb_read(ci->host, ci->nodeid, ci->generation, addr, buffer, length); - if (!ret || i == 3) + if (!ret) { + ci->speed_unverified = 0; + break; + } + /* Give up after 3rd failure. */ + if (i == 3) break; + /* The ieee1394_core guessed the node's speed capability from + * the self ID. Check whether a lower speed works. */ + if (ci->speed_unverified && length == sizeof(quadlet_t)) { + ret = nodemgr_check_speed(ci, addr, buffer); + if (!ret) + break; + } if (msleep_interruptible(334)) return -EINTR; } - return ret; } @@ -1204,6 +1257,8 @@ static void nodemgr_node_scan_one(struct host_info *hi, ci->host = host; ci->nodeid = nodeid; ci->generation = generation; + ci->speed_unverified = + host->speed[NODEID_TO_NODE(nodeid)] > IEEE1394_SPEED_100; /* We need to detect when the ConfigROM's generation has changed, * so we only update the node's info when it needs to be. */ diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 24cd1e250d8..c30e03a0e63 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -1664,10 +1664,8 @@ static int sbp2_max_speed_and_size(struct scsi_id_instance_data *scsi_id) SBP2_DEBUG_ENTER(); - /* Initial setting comes from the hosts speed map */ scsi_id->speed_code = - hi->host->speed_map[NODEID_TO_NODE(hi->host->node_id) * 64 + - NODEID_TO_NODE(scsi_id->ne->nodeid)]; + hi->host->speed[NODEID_TO_NODE(scsi_id->ne->nodeid)]; /* Bump down our speed if the user requested it */ if (scsi_id->speed_code > max_speed) { -- cgit v1.2.3 From eaf88450d21fc839c3e77fa6942b8d4192bdfe53 Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Mon, 12 Jun 2006 18:12:49 -0400 Subject: ieee1394: save RAM by using a single tlabel for broadcast transactions Since broadcast transactions are already complete when the request has been sent, the same transaction label can be reused all over again, see IEEE 1394 7.3.2.5 and 6.2.4.3. Therefore we can reduce the footprint of struct hpsb_host by the size of one struct hpsb_tlabel_pool. Signed-off-by: Stefan Richter Signed-off-by: Ben Collins --- drivers/ieee1394/hosts.h | 16 ++++++++-------- drivers/ieee1394/ieee1394_transactions.c | 10 ++++++++-- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/drivers/ieee1394/hosts.h b/drivers/ieee1394/hosts.h index d1a47607cb8..9ddc6628e71 100644 --- a/drivers/ieee1394/hosts.h +++ b/drivers/ieee1394/hosts.h @@ -30,14 +30,14 @@ struct hpsb_host { unsigned char iso_listen_count[64]; - int node_count; /* number of identified nodes on this bus */ - int selfid_count; /* total number of SelfIDs received */ - int nodes_active; /* number of nodes with active link layer */ - u8 speed[63]; /* speed between each node and local node */ + int node_count; /* number of identified nodes on this bus */ + int selfid_count; /* total number of SelfIDs received */ + int nodes_active; /* number of nodes with active link layer */ + u8 speed[ALL_NODES]; /* speed between each node and local node */ - nodeid_t node_id; /* node ID of this host */ - nodeid_t irm_id; /* ID of this bus' isochronous resource manager */ - nodeid_t busmgr_id; /* ID of this bus' bus manager */ + nodeid_t node_id; /* node ID of this host */ + nodeid_t irm_id; /* ID of this bus' isochronous resource manager */ + nodeid_t busmgr_id; /* ID of this bus' bus manager */ /* this nodes state */ unsigned in_bus_reset:1; @@ -56,7 +56,7 @@ struct hpsb_host { struct csr_control csr; /* Per node tlabel pool allocation */ - struct hpsb_tlabel_pool tpool[64]; + struct hpsb_tlabel_pool tpool[ALL_NODES]; struct hpsb_host_driver *driver; diff --git a/drivers/ieee1394/ieee1394_transactions.c b/drivers/ieee1394/ieee1394_transactions.c index 3fe2f6c4a25..a114b91d606 100644 --- a/drivers/ieee1394/ieee1394_transactions.c +++ b/drivers/ieee1394/ieee1394_transactions.c @@ -136,8 +136,11 @@ int hpsb_get_tlabel(struct hpsb_packet *packet) { unsigned long flags; struct hpsb_tlabel_pool *tp; + int n = NODEID_TO_NODE(packet->node_id); - tp = &packet->host->tpool[packet->node_id & NODE_MASK]; + if (unlikely(n == ALL_NODES)) + return 0; + tp = &packet->host->tpool[n]; if (irqs_disabled() || in_atomic()) { if (down_trylock(&tp->count)) @@ -175,8 +178,11 @@ void hpsb_free_tlabel(struct hpsb_packet *packet) { unsigned long flags; struct hpsb_tlabel_pool *tp; + int n = NODEID_TO_NODE(packet->node_id); - tp = &packet->host->tpool[packet->node_id & NODE_MASK]; + if (unlikely(n == ALL_NODES)) + return; + tp = &packet->host->tpool[n]; BUG_ON(packet->tlabel > 63 || packet->tlabel < 0); -- cgit v1.2.3 From fe42b05a9929e159355bde6025ae46db2ac88658 Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Mon, 12 Jun 2006 18:12:59 -0400 Subject: sbp2: remove manipulation of inquiry response This code became ineffective a few Linux releases ago and is not required anyway. Note from Christoph Hellwig: scsi_cmnd.request_buffer is always a scatterlist these days. Checking random bites into it and then mangling the data in sbp2_check_sbp2_response will cause really bad memory corruption when you're not lucky enough to have the check not trigger by luck. Signed-off-by: Stefan Richter Signed-off-by: Ben Collins --- drivers/ieee1394/sbp2.c | 34 ---------------------------------- drivers/ieee1394/sbp2.h | 5 ++--- 2 files changed, 2 insertions(+), 37 deletions(-) diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index c30e03a0e63..11c353a4653 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -2111,33 +2111,6 @@ static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense return sbp2_status[8] & 0x3f; /* return scsi status */ } -/* - * This function is called after a command is completed, in order to do any necessary SBP-2 - * response data translations for the SCSI stack - */ -static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id, - struct scsi_cmnd *SCpnt) -{ - u8 *scsi_buf = SCpnt->request_buffer; - - SBP2_DEBUG_ENTER(); - - if (SCpnt->cmnd[0] == INQUIRY && (SCpnt->cmnd[1] & 3) == 0) { - /* - * Make sure data length is ok. Minimum length is 36 bytes - */ - if (scsi_buf[4] == 0) { - scsi_buf[4] = 36 - 5; - } - - /* - * Fix ansi revision and response data format - */ - scsi_buf[2] |= 2; - scsi_buf[3] = (scsi_buf[3] & 0xf0) | 2; - } -} - /* * This function deals with status writes from the SBP-2 device */ @@ -2476,13 +2449,6 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id, SCpnt->result = DID_ERROR << 16; } - /* - * Take care of any sbp2 response data mucking here (RBC stuff, etc.) - */ - if (SCpnt->result == DID_OK << 16) { - sbp2_check_sbp2_response(scsi_id, SCpnt); - } - /* * If a bus reset is in progress and there was an error, complete * the command as busy so that it will get retried. diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h index f4ccc9d0fba..2f53b16afc5 100644 --- a/drivers/ieee1394/sbp2.h +++ b/drivers/ieee1394/sbp2.h @@ -395,9 +395,8 @@ static int sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id, static int sbp2_send_command(struct scsi_id_instance_data *scsi_id, struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)); -static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense_data); -static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id, - struct scsi_cmnd *SCpnt); +static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, + unchar *sense_data); static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id, struct unit_directory *ud); static int sbp2_set_busy_timeout(struct scsi_id_instance_data *scsi_id); -- cgit v1.2.3 From 20f4578156995e95613497baf16d5b2d54921e5d Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Mon, 12 Jun 2006 18:13:11 -0400 Subject: sbp2: log number of supported concurrent logins Since this is useful information, promote it from a debug macro to a regular log message. The message appears only if the user set exclusive_login=0, therefore won't clutter the logs in normal use. Also update the comment on exclusive_login. Signed-off-by: Stefan Richter Signed-off-by: Jody McIntyre Signed-off-by: Ben Collins --- drivers/ieee1394/sbp2.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 11c353a4653..18996efdf1a 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -127,10 +127,12 @@ MODULE_PARM_DESC(max_sectors, "Change max sectors per I/O supported (default = " * talking to a single sbp2 device at the same time (filesystem coherency, * etc.). If you're running an sbp2 device that supports multiple logins, * and you're either running read-only filesystems or some sort of special - * filesystem supporting multiple hosts (one such filesystem is OpenGFS, - * see opengfs.sourceforge.net for more info), then set exclusive_login - * to zero. Note: The Oxsemi OXFW911 sbp2 chipset supports up to four - * concurrent logins. + * filesystem supporting multiple hosts, e.g. OpenGFS, Oracle Cluster + * File System, or Lustre, then set exclusive_login to zero. + * + * So far only bridges from Oxford Semiconductor are known to support + * concurrent logins. Depending on firmware, four or two concurrent logins + * are possible on OXFW911 and newer Oxsemi bridges. */ static int exclusive_login = 1; module_param(exclusive_login, int, 0644); @@ -1214,13 +1216,11 @@ static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id) SBP2_DEBUG("length_max_logins = %x", (unsigned int)scsi_id->query_logins_response->length_max_logins); - SBP2_DEBUG("Query logins to SBP-2 device successful"); - max_logins = RESPONSE_GET_MAX_LOGINS(scsi_id->query_logins_response->length_max_logins); - SBP2_DEBUG("Maximum concurrent logins supported: %d", max_logins); + SBP2_INFO("Maximum concurrent logins supported: %d", max_logins); active_logins = RESPONSE_GET_ACTIVE_LOGINS(scsi_id->query_logins_response->length_max_logins); - SBP2_DEBUG("Number of active logins: %d", active_logins); + SBP2_INFO("Number of active logins: %d", active_logins); if (active_logins >= max_logins) { return -EIO; -- cgit v1.2.3 From 8aef63ff033fb0e7ba02d8e760d268eb0aafc58c Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Mon, 12 Jun 2006 18:13:21 -0400 Subject: ieee1394: extend lowlevel API for address range properties Host adapter hardware imposes certain restrictions and features on address ranges. Instead of hard-wire such ranges into the ieee1394 core or even into protocol drivers, let lowlevel drivers specify these ranges via struct hpsb_host. Patch "ohci1394: set address range properties" must be applied too, else hpsb_allocate_and_register_addrspace() won't work properly. Signed-off-by: Stefan Richter Signed-off-by: Ben Collins --- drivers/ieee1394/highlevel.c | 4 +++- drivers/ieee1394/hosts.h | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/ieee1394/highlevel.c b/drivers/ieee1394/highlevel.c index 491e6032bde..29c5255b933 100644 --- a/drivers/ieee1394/highlevel.c +++ b/drivers/ieee1394/highlevel.c @@ -312,8 +312,10 @@ u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl, return retval; } + /* default range, + * avoids controller's posted write area (see OHCI 1.1 clause 1.5) */ if (start == ~0ULL && end == ~0ULL) { - start = CSR1212_ALL_SPACE_BASE + 0xffff00000000ULL; /* ohci1394.c limit */ + start = host->middle_addr_space; end = CSR1212_ALL_SPACE_END; } diff --git a/drivers/ieee1394/hosts.h b/drivers/ieee1394/hosts.h index 9ddc6628e71..9ad4b246307 100644 --- a/drivers/ieee1394/hosts.h +++ b/drivers/ieee1394/hosts.h @@ -73,6 +73,8 @@ struct hpsb_host { unsigned int config_roms; struct list_head addr_space; + u64 low_addr_space; /* upper bound of physical DMA area */ + u64 middle_addr_space; /* upper bound of posted write area */ }; -- cgit v1.2.3 From 4611ed38030a2ce3661de999c3487e5a1eed0dc0 Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Mon, 12 Jun 2006 18:13:32 -0400 Subject: ohci1394: set address range properties This patch supplies the API extension introduced by patch "ieee1394: extend lowlevel API for address range properties" with proper addresses. Like in patch ''ohci1394, sbp2: fix "scsi_add_device failed" with PL-3507 based devices'', 1 TeraByte is chosen as physical upper bound. This leaves a window for the middle address range. This choice is only relevant for adapters which actually have a programmable pysical upper bound register. (Only ALi and Fujitsu adapters are known for this. Most adapters have a fixed bound at 4 GB.) The middle address range is suitable for posted writes. AFAIK, PCILynx does not support physical DMA nor posted writes, therefore no equivalent change in the pcilynx driver is necessary. There is also a driver for GP2Lynx, although not in mainline Linux. I assume this hardware does not support these OHCI features either. Signed-off-by: Stefan Richter Signed-off-by: Ben Collins --- drivers/ieee1394/ohci1394.c | 11 ++++++++++- drivers/ieee1394/ohci1394.h | 10 ++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index 643094c3339..63b71fa997f 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c @@ -553,7 +553,8 @@ static void ohci_initialize(struct ti_ohci *ohci) * register content. * To actually enable physical responses is the job of our interrupt * handler which programs the physical request filter. */ - reg_write(ohci, OHCI1394_PhyUpperBound, 0x01000000); + reg_write(ohci, OHCI1394_PhyUpperBound, + OHCI1394_PHYS_UPPER_BOUND_PROGRAMMED >> 16); DBGMSG("physUpperBoundOffset=%08x", reg_read(ohci, OHCI1394_PhyUpperBound)); @@ -3414,6 +3415,14 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev, host->csr.max_rec = (reg_read(ohci, OHCI1394_BusOptions) >> 12) & 0xf; host->csr.lnk_spd = reg_read(ohci, OHCI1394_BusOptions) & 0x7; + if (phys_dma) { + host->low_addr_space = + (u64) reg_read(ohci, OHCI1394_PhyUpperBound) << 16; + if (!host->low_addr_space) + host->low_addr_space = OHCI1394_PHYS_UPPER_BOUND_FIXED; + } + host->middle_addr_space = OHCI1394_MIDDLE_ADDRESS_SPACE; + /* Tell the highlevel this host is ready */ if (hpsb_add_host(host)) FAIL(-ENOMEM, "Failed to register host with highlevel"); diff --git a/drivers/ieee1394/ohci1394.h b/drivers/ieee1394/ohci1394.h index 7df0962144e..fa05f113f7f 100644 --- a/drivers/ieee1394/ohci1394.h +++ b/drivers/ieee1394/ohci1394.h @@ -443,6 +443,16 @@ static inline u32 reg_read(const struct ti_ohci *ohci, int offset) #define OHCI1394_TCODE_PHY 0xE +/* Node offset map (phys DMA area, posted write area). + * The value of OHCI1394_PHYS_UPPER_BOUND_PROGRAMMED may be modified but must + * be lower than OHCI1394_MIDDLE_ADDRESS_SPACE. + * OHCI1394_PHYS_UPPER_BOUND_FIXED and OHCI1394_MIDDLE_ADDRESS_SPACE are + * constants given by the OHCI spec. + */ +#define OHCI1394_PHYS_UPPER_BOUND_FIXED 0x000100000000ULL /* 4 GB */ +#define OHCI1394_PHYS_UPPER_BOUND_PROGRAMMED 0x010000000000ULL /* 1 TB */ +#define OHCI1394_MIDDLE_ADDRESS_SPACE 0xffff00000000ULL + void ohci1394_init_iso_tasklet(struct ohci1394_iso_tasklet *tasklet, int type, void (*func)(unsigned long), -- cgit v1.2.3 From fa9b73997cc621b9a15c96f07dda26775e61ac6a Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Mon, 12 Jun 2006 18:13:42 -0400 Subject: ohci1394: make phys_dma parameter read-only Being able to switch physical DMA on and off at run time would be a nice feature but a PITA to support by highlevel drivers and userspace apps. Therefore allow it only to be set when the driver is being loaded. Signed-off-by: Stefan Richter Signed-off-by: Ben Collins --- drivers/ieee1394/ohci1394.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index 63b71fa997f..c858f5f94d3 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c @@ -163,7 +163,7 @@ printk(level "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, ohci->host->id , /* Module Parameters */ static int phys_dma = 1; -module_param(phys_dma, int, 0644); +module_param(phys_dma, int, 0444); MODULE_PARM_DESC(phys_dma, "Enable physical dma (default = 1)."); static void dma_trm_tasklet(unsigned long data); -- cgit v1.2.3 From 40ae6c5e88790c2558013640ca4e0a5017c54162 Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Mon, 12 Jun 2006 18:13:49 -0400 Subject: sbp2: remove ohci1394 specific constant Signed-off-by: Stefan Richter Signed-off-by: Ben Collins --- drivers/ieee1394/sbp2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 18996efdf1a..c50aae948f0 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -847,7 +847,7 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud scsi_id->status_fifo_addr = hpsb_allocate_and_register_addrspace( &sbp2_highlevel, ud->ne->host, &sbp2_ops, sizeof(struct sbp2_status_block), sizeof(quadlet_t), - 0x010000000000ULL, CSR1212_ALL_SPACE_END); + ud->ne->host->low_addr_space, CSR1212_ALL_SPACE_END); if (scsi_id->status_fifo_addr == ~0ULL) { SBP2_ERR("failed to allocate status FIFO address range"); goto failed_alloc; -- cgit v1.2.3 From fd23ade80e2bef156aa096459c31c010dacbea1e Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Mon, 12 Jun 2006 18:14:14 -0400 Subject: sbp2: fix S800 transfers if phys_dma is off If sbp2 is forced to move data via ARM handler, the maximum packet size allowed for S800 transfers exceeds ohci1394's buffer size on platforms where PAGE_SIZE is 4096. Signed-off-by: Stefan Richter Signed-off-by: Ben Collins --- drivers/ieee1394/sbp2.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index c50aae948f0..251656ec7d9 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -1649,6 +1649,8 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id, } } +#define SBP2_PAYLOAD_TO_BYTES(p) (1 << ((p) + 2)) + /* * This function is called in order to determine the max speed and packet * size we can use in our ORBs. Note, that we (the driver and host) only @@ -1661,6 +1663,7 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id, static int sbp2_max_speed_and_size(struct scsi_id_instance_data *scsi_id) { struct sbp2scsi_host_info *hi = scsi_id->hi; + u8 payload; SBP2_DEBUG_ENTER(); @@ -1676,15 +1679,22 @@ static int sbp2_max_speed_and_size(struct scsi_id_instance_data *scsi_id) /* Payload size is the lesser of what our speed supports and what * our host supports. */ - scsi_id->max_payload_size = - min(sbp2_speedto_max_payload[scsi_id->speed_code], - (u8) (hi->host->csr.max_rec - 1)); + payload = min(sbp2_speedto_max_payload[scsi_id->speed_code], + (u8) (hi->host->csr.max_rec - 1)); + + /* If physical DMA is off, work around limitation in ohci1394: + * packet size must not exceed PAGE_SIZE */ + if (scsi_id->ne->host->low_addr_space < (1ULL << 32)) + while (SBP2_PAYLOAD_TO_BYTES(payload) + 24 > PAGE_SIZE && + payload) + payload--; HPSB_DEBUG("Node " NODE_BUS_FMT ": Max speed [%s] - Max payload [%u]", NODE_BUS_ARGS(hi->host, scsi_id->ne->nodeid), hpsb_speedto_str[scsi_id->speed_code], - 1 << ((u32) scsi_id->max_payload_size + 2)); + SBP2_PAYLOAD_TO_BYTES(payload)); + scsi_id->max_payload_size = payload; return 0; } -- cgit v1.2.3 From d0aef39f9b5941beb322924986ddee8c4903cd72 Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Mon, 12 Jun 2006 18:14:27 -0400 Subject: Update feature removal of obsolete raw1394 ISO requests. Signed-off-by: Jody McIntyre Signed-off-by: Ben Collins --- Documentation/feature-removal-schedule.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 43ab119963d..7d263343c0e 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -49,11 +49,11 @@ Who: Paul E. McKenney --------------------------- What: raw1394: requests of type RAW1394_REQ_ISO_SEND, RAW1394_REQ_ISO_LISTEN -When: November 2005 +When: November 2006 Why: Deprecated in favour of the new ioctl-based rawiso interface, which is more efficient. You should really be using libraw1394 for raw1394 access anyway. -Who: Jody McIntyre +Who: Jody McIntyre --------------------------- -- cgit v1.2.3 From bccbccdbf8f866a8e01967a48241db548e12adf2 Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Mon, 12 Jun 2006 18:14:36 -0400 Subject: sbp2: provide helptext for CONFIG_IEEE1394_SBP2_PHYS_DMA and mark it experimental It appears I will not get it fixed overnight. Signed-off-by: Stefan Richter Signed-off-by: Ben Collins --- drivers/ieee1394/Kconfig | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/ieee1394/Kconfig b/drivers/ieee1394/Kconfig index 39142e2f804..06783c1e3dc 100644 --- a/drivers/ieee1394/Kconfig +++ b/drivers/ieee1394/Kconfig @@ -128,8 +128,17 @@ config IEEE1394_SBP2 1394 bus. SBP-2 devices include harddrives and DVD devices. config IEEE1394_SBP2_PHYS_DMA - bool "Enable Phys DMA support for SBP2 (Debug)" - depends on IEEE1394 && IEEE1394_SBP2 + bool "Enable replacement for physical DMA in SBP2" + depends on IEEE1394 && IEEE1394_SBP2 && EXPERIMENTAL + help + This builds sbp2 for use with non-OHCI host adapters which do not + support physical DMA or for when ohci1394 is run with phys_dma=0. + Physical DMA is data movement without assistence of the drivers' + interrupt handlers. This option includes the interrupt handlers + that are required in absence of this hardware feature. + + This option is buggy and currently broken on some architectures. + If unsure, say N. config IEEE1394_ETH1394 tristate "Ethernet over 1394" -- cgit v1.2.3 From 05db5055b1844bf39d1429a0c43078959198cd1d Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Mon, 12 Jun 2006 18:14:47 -0400 Subject: sbp2: use __attribute__((packed)) for on-the-wire structures It seems to have worked without the attribute during all the years just because sizes of all struct members are multiples of 32 bits. Signed-off-by: Stefan Richter Signed-off-by: Ben Collins --- drivers/ieee1394/sbp2.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h index 2f53b16afc5..b22ce1aa8fe 100644 --- a/drivers/ieee1394/sbp2.h +++ b/drivers/ieee1394/sbp2.h @@ -52,7 +52,7 @@ struct sbp2_command_orb { u32 data_descriptor_lo; u32 misc; u8 cdb[12]; -}; +} __attribute__((packed)); #define SBP2_LOGIN_REQUEST 0x0 #define SBP2_QUERY_LOGINS_REQUEST 0x1 @@ -80,7 +80,7 @@ struct sbp2_login_orb { u32 passwd_resp_lengths; u32 status_fifo_hi; u32 status_fifo_lo; -}; +} __attribute__((packed)); #define RESPONSE_GET_LOGIN_ID(value) (value & 0xffff) #define RESPONSE_GET_LENGTH(value) ((value >> 16) & 0xffff) @@ -91,7 +91,7 @@ struct sbp2_login_response { u32 command_block_agent_hi; u32 command_block_agent_lo; u32 reconnect_hold; -}; +} __attribute__((packed)); #define ORB_SET_LOGIN_ID(value) (value & 0xffff) @@ -106,7 +106,7 @@ struct sbp2_query_logins_orb { u32 reserved_resp_length; u32 status_fifo_hi; u32 status_fifo_lo; -}; +} __attribute__((packed)); #define RESPONSE_GET_MAX_LOGINS(value) (value & 0xffff) #define RESPONSE_GET_ACTIVE_LOGINS(value) ((RESPONSE_GET_LENGTH(value) - 4) / 12) @@ -116,7 +116,7 @@ struct sbp2_query_logins_response { u32 misc_IDs; u32 initiator_misc_hi; u32 initiator_misc_lo; -}; +} __attribute__((packed)); struct sbp2_reconnect_orb { u32 reserved1; @@ -127,7 +127,7 @@ struct sbp2_reconnect_orb { u32 reserved5; u32 status_fifo_hi; u32 status_fifo_lo; -}; +} __attribute__((packed)); struct sbp2_logout_orb { u32 reserved1; @@ -138,7 +138,7 @@ struct sbp2_logout_orb { u32 reserved5; u32 status_fifo_hi; u32 status_fifo_lo; -}; +} __attribute__((packed)); #define PAGE_TABLE_SET_SEGMENT_BASE_HI(value) (value & 0xffff) #define PAGE_TABLE_SET_SEGMENT_LENGTH(value) ((value & 0xffff) << 16) @@ -146,7 +146,7 @@ struct sbp2_logout_orb { struct sbp2_unrestricted_page_table { u32 length_segment_base_hi; u32 segment_base_lo; -}; +} __attribute__((packed)); #define RESP_STATUS_REQUEST_COMPLETE 0x0 #define RESP_STATUS_TRANSPORT_FAILURE 0x1 @@ -191,7 +191,7 @@ struct sbp2_status_block { u32 ORB_offset_hi_misc; u32 ORB_offset_lo; u8 command_set_dependent[24]; -}; +} __attribute__((packed)); /* * Miscellaneous SBP2 related config rom defines -- cgit v1.2.3 From b21efb59c5d317a2a972b9d66939cbfeababd982 Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Mon, 12 Jun 2006 18:15:03 -0400 Subject: Fix broken suspend/resume in ohci1394 I've been experimenting to track down the cause of suspend/resume problems on my Compaq Presario X1050 laptop: http://bugzilla.kernel.org/show_bug.cgi?id=6075 Essentially the ACPI Embedded Controller and keyboard controller would get into a bizarre, confused state after resume. I found that unloading the ohci1394 module before suspend and reloading it after resume made the problem go away. Diffing the dmesg output from resume, with and without the module loaded, I found that with the module loaded I was missing these: PM: Writing back config space on device 0000:02:00.0 at offset 1. (Was 2100080, writing 2100007) PM: Writing back config space on device 0000:02:00.0 at offset 3. (Was 0, writing 8008) PM: Writing back config space on device 0000:02:00.0 at offset 4. (Was 0, writing 90200000) PM: Writing back config space on device 0000:02:00.0 at offset 5. (Was 1, writing 2401) PM: Writing back config space on device 0000:02:00.0 at offset f. (Was 20000100, writing 2000010a) The default PCI driver performs the pci_restore_state when no driver is loaded for the device. When the ohci1394 driver is loaded, it is supposed to do this, however it appears not to do so. I created the patch below and tested it, and it appears to resolve the suspend problems I was having with the module loaded. I only added in the pci_save_state and pci_restore_state - however, though I know little of this hardware, surely the driver should really be doing more than this when suspending and resuming? Currently it does almost nothing, what if there are commands in progress, etc? Signed-off-by: Robert Hancock Cc: Jody McIntyre Cc: Ben Collins Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Ben Collins --- drivers/ieee1394/ohci1394.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index c858f5f94d3..96b994bde48 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c @@ -3547,6 +3547,7 @@ static int ohci1394_pci_resume (struct pci_dev *pdev) } #endif /* CONFIG_PPC_PMAC */ + pci_restore_state(pdev); pci_enable_device(pdev); return 0; @@ -3566,6 +3567,8 @@ static int ohci1394_pci_suspend (struct pci_dev *pdev, pm_message_t state) } #endif + pci_save_state(pdev); + return 0; } -- cgit v1.2.3 From 02f4213fc43dbddc3a3ab9fa4d2dc2501a2d30dc Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Mon, 12 Jun 2006 18:15:11 -0400 Subject: [PATCH] eth1394: endian fixes Signed-off-by: Alexey Dobriyan Signed-off-by: Ben Collins --- drivers/ieee1394/eth1394.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c index b2d2c4dd075..3ec3b13e491 100644 --- a/drivers/ieee1394/eth1394.c +++ b/drivers/ieee1394/eth1394.c @@ -933,7 +933,7 @@ static inline u16 ether1394_parse_encap(struct sk_buff *skb, *(u32*)arp_ptr = arp1394->sip; /* move sender IP addr */ arp_ptr += arp->ar_pln; /* skip over sender IP addr */ - if (arp->ar_op == 1) + if (arp->ar_op == htons(ARPOP_REQUEST)) /* just set ARP req target unique ID to 0 */ *((u64*)arp_ptr) = 0; else @@ -1393,7 +1393,7 @@ static inline void ether1394_arp_to_1394arp(struct sk_buff *skb, /* We need to encapsulate the standard header with our own. We use the * ethernet header's proto for our own. */ static inline unsigned int ether1394_encapsulate_prep(unsigned int max_payload, - int proto, + __be16 proto, union eth1394_hdr *hdr, u16 dg_size, u16 dgl) { @@ -1624,7 +1624,7 @@ static int ether1394_tx (struct sk_buff *skb, struct net_device *dev) gfp_t kmflags = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL; struct eth1394hdr *eth; struct eth1394_priv *priv = netdev_priv(dev); - int proto; + __be16 proto; unsigned long flags; nodeid_t dest_node; eth1394_tx_type tx_type; -- cgit v1.2.3 From e269d276792684a13ab0d9acd8c024ec7d6c5f4d Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Mon, 12 Jun 2006 18:15:20 -0400 Subject: sbp2: fix deregistration of status fifo address space The proper designator of an invalid CSR address is ~(u64)0, not (u64)0. Use the correct value in initialization and deregistration. Also, scsi_id->sbp2_lun does not need to be initialized twice. (scsi_id was kzalloc'd.) Signed-off-by: Stefan Richter Signed-off-by: Ben Collins --- drivers/ieee1394/sbp2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 251656ec7d9..975a56bfab3 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -794,12 +794,12 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud scsi_id->ud = ud; scsi_id->speed_code = IEEE1394_SPEED_100; scsi_id->max_payload_size = sbp2_speedto_max_payload[IEEE1394_SPEED_100]; + scsi_id->status_fifo_addr = ~0ULL; atomic_set(&scsi_id->sbp2_login_complete, 0); INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_inuse); INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_completed); INIT_LIST_HEAD(&scsi_id->scsi_list); spin_lock_init(&scsi_id->sbp2_command_orb_lock); - scsi_id->sbp2_lun = 0; ud->device.driver_data = scsi_id; @@ -1090,7 +1090,7 @@ static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id) SBP2_DMA_FREE("single query logins data"); } - if (scsi_id->status_fifo_addr) + if (scsi_id->status_fifo_addr != ~0ULL) hpsb_unregister_addrspace(&sbp2_highlevel, hi->host, scsi_id->status_fifo_addr); -- cgit v1.2.3 From 6737231ead125c7cee7ce4d3a74179bdac085529 Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Mon, 12 Jun 2006 18:15:31 -0400 Subject: ieee1394: add preprocessor constant for invalid csr address Replace occurrences of the magic value ~(u64)0 for invalid CSR address spaces by a named constant for better readability. Signed-off-by: Stefan Richter Signed-off-by: Ben Collins --- drivers/ieee1394/csr1212.c | 2 +- drivers/ieee1394/csr1212.h | 1 + drivers/ieee1394/eth1394.c | 16 +++++++--------- drivers/ieee1394/eth1394.h | 2 -- drivers/ieee1394/highlevel.c | 9 +++++---- drivers/ieee1394/sbp2.c | 8 ++++---- 6 files changed, 18 insertions(+), 20 deletions(-) diff --git a/drivers/ieee1394/csr1212.c b/drivers/ieee1394/csr1212.c index 15773544234..586f71e7346 100644 --- a/drivers/ieee1394/csr1212.c +++ b/drivers/ieee1394/csr1212.c @@ -779,7 +779,7 @@ static int csr1212_append_new_cache(struct csr1212_csr *csr, size_t romsize) romsize = (romsize + (csr->max_rom - 1)) & ~(csr->max_rom - 1); csr_addr = csr->ops->allocate_addr_range(romsize, csr->max_rom, csr->private); - if (csr_addr == ~0ULL) { + if (csr_addr == CSR1212_INVALID_ADDR_SPACE) { return CSR1212_ENOMEM; } if (csr_addr < CSR1212_REGISTER_SPACE_BASE) { diff --git a/drivers/ieee1394/csr1212.h b/drivers/ieee1394/csr1212.h index cecd5871f2d..17ddd72dee4 100644 --- a/drivers/ieee1394/csr1212.h +++ b/drivers/ieee1394/csr1212.h @@ -192,6 +192,7 @@ #define CSR1212_EXTENDED_ROM_SIZE (0x10000 * sizeof(u_int32_t)) +#define CSR1212_INVALID_ADDR_SPACE -1 /* Config ROM image structures */ struct csr1212_bus_info_block_img { diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c index 3ec3b13e491..cf80fed6163 100644 --- a/drivers/ieee1394/eth1394.c +++ b/drivers/ieee1394/eth1394.c @@ -367,7 +367,7 @@ static int eth1394_probe(struct device *dev) spin_lock_init(&node_info->pdg.lock); INIT_LIST_HEAD(&node_info->pdg.list); node_info->pdg.sz = 0; - node_info->fifo = ETHER1394_INVALID_ADDR; + node_info->fifo = CSR1212_INVALID_ADDR_SPACE; ud->device.driver_data = node_info; new_node->ud = ud; @@ -566,13 +566,11 @@ static void ether1394_add_host (struct hpsb_host *host) if (!(host->config_roms & HPSB_CONFIG_ROM_ENTRY_IP1394)) return; - fifo_addr = hpsb_allocate_and_register_addrspace(ð1394_highlevel, - host, - &addr_ops, - ETHER1394_REGION_ADDR_LEN, - ETHER1394_REGION_ADDR_LEN, - -1, -1); - if (fifo_addr == ~0ULL) + fifo_addr = hpsb_allocate_and_register_addrspace( + ð1394_highlevel, host, &addr_ops, + ETHER1394_REGION_ADDR_LEN, ETHER1394_REGION_ADDR_LEN, + CSR1212_INVALID_ADDR_SPACE, CSR1212_INVALID_ADDR_SPACE); + if (fifo_addr == CSR1212_INVALID_ADDR_SPACE) goto out; /* We should really have our own alloc_hpsbdev() function in @@ -1686,7 +1684,7 @@ static int ether1394_tx (struct sk_buff *skb, struct net_device *dev) goto fail; } node_info = (struct eth1394_node_info*)node->ud->device.driver_data; - if (node_info->fifo == ETHER1394_INVALID_ADDR) { + if (node_info->fifo == CSR1212_INVALID_ADDR_SPACE) { ret = -EAGAIN; goto fail; } diff --git a/drivers/ieee1394/eth1394.h b/drivers/ieee1394/eth1394.h index a77213cfc48..c45cbff9138 100644 --- a/drivers/ieee1394/eth1394.h +++ b/drivers/ieee1394/eth1394.h @@ -32,8 +32,6 @@ * S3200 (per Table 16-3 of IEEE 1394b-2002). */ #define ETHER1394_REGION_ADDR_LEN 4096 -#define ETHER1394_INVALID_ADDR ~0ULL - /* GASP identifier numbers for IPv4 over IEEE 1394 */ #define ETHER1394_GASP_SPECIFIER_ID 0x00005E #define ETHER1394_GASP_SPECIFIER_ID_HI ((ETHER1394_GASP_SPECIFIER_ID >> 8) & 0xffff) diff --git a/drivers/ieee1394/highlevel.c b/drivers/ieee1394/highlevel.c index 29c5255b933..165dcd66956 100644 --- a/drivers/ieee1394/highlevel.c +++ b/drivers/ieee1394/highlevel.c @@ -301,7 +301,7 @@ u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl, { struct hpsb_address_serve *as, *a1, *a2; struct list_head *entry; - u64 retval = ~0ULL; + u64 retval = CSR1212_INVALID_ADDR_SPACE; unsigned long flags; u64 align_mask = ~(alignment - 1); @@ -314,9 +314,10 @@ u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl, /* default range, * avoids controller's posted write area (see OHCI 1.1 clause 1.5) */ - if (start == ~0ULL && end == ~0ULL) { + if (start == CSR1212_INVALID_ADDR_SPACE && + end == CSR1212_INVALID_ADDR_SPACE) { start = host->middle_addr_space; - end = CSR1212_ALL_SPACE_END; + end = CSR1212_ALL_SPACE_END; } if (((start|end) & ~align_mask) || (start >= end) || (end > 0x1000000000000ULL)) { @@ -360,7 +361,7 @@ u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl, write_unlock_irqrestore(&addr_space_lock, flags); - if (retval == ~0ULL) { + if (retval == CSR1212_INVALID_ADDR_SPACE) { kfree(as); } diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 975a56bfab3..1d5ceb7ecc8 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -794,7 +794,7 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud scsi_id->ud = ud; scsi_id->speed_code = IEEE1394_SPEED_100; scsi_id->max_payload_size = sbp2_speedto_max_payload[IEEE1394_SPEED_100]; - scsi_id->status_fifo_addr = ~0ULL; + scsi_id->status_fifo_addr = CSR1212_INVALID_ADDR_SPACE; atomic_set(&scsi_id->sbp2_login_complete, 0); INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_inuse); INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_completed); @@ -848,7 +848,7 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud &sbp2_highlevel, ud->ne->host, &sbp2_ops, sizeof(struct sbp2_status_block), sizeof(quadlet_t), ud->ne->host->low_addr_space, CSR1212_ALL_SPACE_END); - if (scsi_id->status_fifo_addr == ~0ULL) { + if (scsi_id->status_fifo_addr == CSR1212_INVALID_ADDR_SPACE) { SBP2_ERR("failed to allocate status FIFO address range"); goto failed_alloc; } @@ -1090,9 +1090,9 @@ static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id) SBP2_DMA_FREE("single query logins data"); } - if (scsi_id->status_fifo_addr != ~0ULL) + if (scsi_id->status_fifo_addr != CSR1212_INVALID_ADDR_SPACE) hpsb_unregister_addrspace(&sbp2_highlevel, hi->host, - scsi_id->status_fifo_addr); + scsi_id->status_fifo_addr); scsi_id->ud->device.driver_data = NULL; -- cgit v1.2.3 From dd082c670523231dc9a26dafee1dc22b57df2921 Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Mon, 12 Jun 2006 18:15:40 -0400 Subject: ieee1394: sbp2: Kconfig fix We only support x86 and ppc, due to the use of bus_to_virt() and friends. Signed-off-by: Stefan Richter Signed-off-by: Andrew Morton Signed-off-by: Ben Collins --- drivers/ieee1394/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ieee1394/Kconfig b/drivers/ieee1394/Kconfig index 06783c1e3dc..186737539cf 100644 --- a/drivers/ieee1394/Kconfig +++ b/drivers/ieee1394/Kconfig @@ -129,7 +129,7 @@ config IEEE1394_SBP2 config IEEE1394_SBP2_PHYS_DMA bool "Enable replacement for physical DMA in SBP2" - depends on IEEE1394 && IEEE1394_SBP2 && EXPERIMENTAL + depends on IEEE1394 && IEEE1394_SBP2 && EXPERIMENTAL && (X86_32 || PPC_32) help This builds sbp2 for use with non-OHCI host adapters which do not support physical DMA or for when ohci1394 is run with phys_dma=0. -- cgit v1.2.3 From f654240f330d77eb198af4abde89131e2a0e4f90 Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Mon, 12 Jun 2006 18:15:50 -0400 Subject: ieee1394_core: switch to kthread API This gets also rid of the MODPOST warning "drivers/ieee1394/ieee1394.o - Section mismatch: reference to .exit.text: from .smp_locks after '' (at offset 0x18)". Signed-off-by: Christoph Hellwig Signed-off-by: Jody McIntyre Signed-off-by: Stefan Richter Signed-off-by: Andrew Morton Signed-off-by: Ben Collins --- drivers/ieee1394/ieee1394_core.c | 48 +++++++++++++--------------------------- 1 file changed, 15 insertions(+), 33 deletions(-) diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c index c83e2b8295e..49354de9fb8 100644 --- a/drivers/ieee1394/ieee1394_core.c +++ b/drivers/ieee1394/ieee1394_core.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -1001,11 +1002,8 @@ void abort_timedouts(unsigned long __opaque) * packets that have a "complete" function are sent here. This way, the * completion is run out of kernel context, and doesn't block the rest of * the stack. */ -static int khpsbpkt_pid = -1, khpsbpkt_kill; -static DECLARE_COMPLETION(khpsbpkt_complete); +static struct task_struct *khpsbpkt_thread; static struct sk_buff_head hpsbpkt_queue; -static DECLARE_MUTEX_LOCKED(khpsbpkt_sig); - static void queue_packet_complete(struct hpsb_packet *packet) { @@ -1015,9 +1013,7 @@ static void queue_packet_complete(struct hpsb_packet *packet) } if (packet->complete_routine != NULL) { skb_queue_tail(&hpsbpkt_queue, packet->skb); - - /* Signal the kernel thread to handle this */ - up(&khpsbpkt_sig); + wake_up_process(khpsbpkt_thread); } return; } @@ -1029,19 +1025,9 @@ static int hpsbpkt_thread(void *__hi) void (*complete_routine)(void*); void *complete_data; - daemonize("khpsbpkt"); - current->flags |= PF_NOFREEZE; - while (1) { - if (down_interruptible(&khpsbpkt_sig)) { - printk("khpsbpkt: received unexpected signal?!\n" ); - break; - } - - if (khpsbpkt_kill) - break; - + while (!kthread_should_stop()) { while ((skb = skb_dequeue(&hpsbpkt_queue)) != NULL) { packet = (struct hpsb_packet *)skb->data; @@ -1052,9 +1038,13 @@ static int hpsbpkt_thread(void *__hi) complete_routine(complete_data); } - } - complete_and_exit(&khpsbpkt_complete, 0); + set_current_state(TASK_INTERRUPTIBLE); + if (!skb_peek(&hpsbpkt_queue)) + schedule(); + __set_current_state(TASK_RUNNING); + } + return 0; } static int __init ieee1394_init(void) @@ -1069,10 +1059,10 @@ static int __init ieee1394_init(void) HPSB_ERR("Some features may not be available\n"); } - khpsbpkt_pid = kernel_thread(hpsbpkt_thread, NULL, CLONE_KERNEL); - if (khpsbpkt_pid < 0) { + khpsbpkt_thread = kthread_run(hpsbpkt_thread, NULL, "khpsbpkt"); + if (IS_ERR(khpsbpkt_thread)) { HPSB_ERR("Failed to start hpsbpkt thread!\n"); - ret = -ENOMEM; + ret = PTR_ERR(khpsbpkt_thread); goto exit_cleanup_config_roms; } @@ -1152,10 +1142,7 @@ release_all_bus: release_chrdev: unregister_chrdev_region(IEEE1394_CORE_DEV, 256); exit_release_kernel_thread: - if (khpsbpkt_pid >= 0) { - kill_proc(khpsbpkt_pid, SIGTERM, 1); - wait_for_completion(&khpsbpkt_complete); - } + kthread_stop(khpsbpkt_thread); exit_cleanup_config_roms: hpsb_cleanup_config_roms(); return ret; @@ -1176,12 +1163,7 @@ static void __exit ieee1394_cleanup(void) bus_remove_file(&ieee1394_bus_type, fw_bus_attrs[i]); bus_unregister(&ieee1394_bus_type); - if (khpsbpkt_pid >= 0) { - khpsbpkt_kill = 1; - mb(); - up(&khpsbpkt_sig); - wait_for_completion(&khpsbpkt_complete); - } + kthread_stop(khpsbpkt_thread); hpsb_cleanup_config_roms(); -- cgit v1.2.3 From 445151932e869fd76b23bccff75ae2a600ccf3c9 Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Mon, 12 Jun 2006 18:16:01 -0400 Subject: ieee1394: hl_irqs_lock is taken in hardware interrupt context ohci1394 and pcilynx call highlevel_host_reset from their hardware interrupt handler (via hpsb_selfid_complete). Therefore all readers and writers of hl_irqs_lock have to disable interrupts. Reported by Jiri Slaby and J. A. Magallon. Signed-off-by: Stefan Richter Signed-off-by: Ben Collins --- drivers/ieee1394/highlevel.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/drivers/ieee1394/highlevel.c b/drivers/ieee1394/highlevel.c index 165dcd66956..d255d407e06 100644 --- a/drivers/ieee1394/highlevel.c +++ b/drivers/ieee1394/highlevel.c @@ -210,6 +210,8 @@ static int highlevel_for_each_host_reg(struct hpsb_host *host, void *__data) void hpsb_register_highlevel(struct hpsb_highlevel *hl) { + unsigned long flags; + INIT_LIST_HEAD(&hl->addr_list); INIT_LIST_HEAD(&hl->host_info_list); @@ -219,9 +221,9 @@ void hpsb_register_highlevel(struct hpsb_highlevel *hl) list_add_tail(&hl->hl_list, &hl_drivers); up_write(&hl_drivers_sem); - write_lock(&hl_irqs_lock); + write_lock_irqsave(&hl_irqs_lock, flags); list_add_tail(&hl->irq_list, &hl_irqs); - write_unlock(&hl_irqs_lock); + write_unlock_irqrestore(&hl_irqs_lock, flags); if (hl->add_host) nodemgr_for_each_host(hl, highlevel_for_each_host_reg); @@ -282,9 +284,11 @@ static int highlevel_for_each_host_unreg(struct hpsb_host *host, void *__data) void hpsb_unregister_highlevel(struct hpsb_highlevel *hl) { - write_lock(&hl_irqs_lock); + unsigned long flags; + + write_lock_irqsave(&hl_irqs_lock, flags); list_del(&hl->irq_list); - write_unlock(&hl_irqs_lock); + write_unlock_irqrestore(&hl_irqs_lock, flags); down_write(&hl_drivers_sem); list_del(&hl->hl_list); @@ -517,42 +521,45 @@ void highlevel_remove_host(struct hpsb_host *host) void highlevel_host_reset(struct hpsb_host *host) { + unsigned long flags; struct hpsb_highlevel *hl; - read_lock(&hl_irqs_lock); + read_lock_irqsave(&hl_irqs_lock, flags); list_for_each_entry(hl, &hl_irqs, irq_list) { if (hl->host_reset) hl->host_reset(host); } - read_unlock(&hl_irqs_lock); + read_unlock_irqrestore(&hl_irqs_lock, flags); } void highlevel_iso_receive(struct hpsb_host *host, void *data, size_t length) { + unsigned long flags; struct hpsb_highlevel *hl; int channel = (((quadlet_t *)data)[0] >> 8) & 0x3f; - read_lock(&hl_irqs_lock); + read_lock_irqsave(&hl_irqs_lock, flags); list_for_each_entry(hl, &hl_irqs, irq_list) { if (hl->iso_receive) hl->iso_receive(host, channel, data, length); } - read_unlock(&hl_irqs_lock); + read_unlock_irqrestore(&hl_irqs_lock, flags); } void highlevel_fcp_request(struct hpsb_host *host, int nodeid, int direction, void *data, size_t length) { + unsigned long flags; struct hpsb_highlevel *hl; int cts = ((quadlet_t *)data)[0] >> 4; - read_lock(&hl_irqs_lock); + read_lock_irqsave(&hl_irqs_lock, flags); list_for_each_entry(hl, &hl_irqs, irq_list) { if (hl->fcp_request) hl->fcp_request(host, nodeid, direction, cts, data, length); } - read_unlock(&hl_irqs_lock); + read_unlock_irqrestore(&hl_irqs_lock, flags); } int highlevel_read(struct hpsb_host *host, int nodeid, void *data, -- cgit v1.2.3 From 2c4b69bd7bff85ae9e8b2032179aee9c04da70ba Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Mon, 12 Jun 2006 18:16:16 -0400 Subject: ieee1394: adjust code formatting in highlevel.c Replace spaces by tabulators, wrap lines at 80 columns, delete some blank lines and superfluous braces. Collapse some if()-within-if() constructs. Replace a literal CSR address by its preprocessor constant. Signed-off-by: Stefan Richter Signed-off-by: Ben Collins --- drivers/ieee1394/highlevel.c | 415 +++++++++++++++++++------------------------ 1 file changed, 182 insertions(+), 233 deletions(-) diff --git a/drivers/ieee1394/highlevel.c b/drivers/ieee1394/highlevel.c index d255d407e06..25b22609e79 100644 --- a/drivers/ieee1394/highlevel.c +++ b/drivers/ieee1394/highlevel.c @@ -53,7 +53,7 @@ static struct hpsb_address_serve dummy_zero_addr, dummy_max_addr; static struct hl_host_info *hl_get_hostinfo(struct hpsb_highlevel *hl, - struct hpsb_host *host) + struct hpsb_host *host) { struct hl_host_info *hi = NULL; @@ -68,24 +68,18 @@ static struct hl_host_info *hl_get_hostinfo(struct hpsb_highlevel *hl, } } read_unlock(&hl->host_info_lock); - return NULL; } - /* Returns a per host/driver data structure that was previously stored by * hpsb_create_hostinfo. */ void *hpsb_get_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host) { struct hl_host_info *hi = hl_get_hostinfo(hl, host); - if (hi) - return hi->data; - - return NULL; + return hi ? hi->data : NULL; } - /* If size is zero, then the return here is only valid for error checking */ void *hpsb_create_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host, size_t data_size) @@ -96,8 +90,8 @@ void *hpsb_create_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host, hi = hl_get_hostinfo(hl, host); if (hi) { - HPSB_ERR("%s called hpsb_create_hostinfo when hostinfo already exists", - hl->name); + HPSB_ERR("%s called hpsb_create_hostinfo when hostinfo already" + " exists", hl->name); return NULL; } @@ -120,7 +114,6 @@ void *hpsb_create_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host, return data; } - int hpsb_set_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host, void *data) { @@ -132,16 +125,14 @@ int hpsb_set_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host, hi->data = data; return 0; } else - HPSB_ERR("%s called hpsb_set_hostinfo when hostinfo already has data", - hl->name); + HPSB_ERR("%s called hpsb_set_hostinfo when hostinfo " + "already has data", hl->name); } else HPSB_ERR("%s called hpsb_set_hostinfo when no hostinfo exists", hl->name); - return -EINVAL; } - void hpsb_destroy_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host) { struct hl_host_info *hi; @@ -154,23 +145,20 @@ void hpsb_destroy_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host) write_unlock_irqrestore(&hl->host_info_lock, flags); kfree(hi); } - return; } - -void hpsb_set_hostinfo_key(struct hpsb_highlevel *hl, struct hpsb_host *host, unsigned long key) +void hpsb_set_hostinfo_key(struct hpsb_highlevel *hl, struct hpsb_host *host, + unsigned long key) { struct hl_host_info *hi; hi = hl_get_hostinfo(hl, host); if (hi) hi->key = key; - return; } - void *hpsb_get_hostinfo_bykey(struct hpsb_highlevel *hl, unsigned long key) { struct hl_host_info *hi; @@ -187,24 +175,18 @@ void *hpsb_get_hostinfo_bykey(struct hpsb_highlevel *hl, unsigned long key) } } read_unlock(&hl->host_info_lock); - return data; } - static int highlevel_for_each_host_reg(struct hpsb_host *host, void *__data) { struct hpsb_highlevel *hl = __data; hl->add_host(host); - if (host->update_config_rom) { - if (hpsb_update_config_rom_image(host) < 0) { - HPSB_ERR("Failed to generate Configuration ROM image for host " - "%s-%d", hl->name, host->id); - } - } - + if (host->update_config_rom && hpsb_update_config_rom_image(host) < 0) + HPSB_ERR("Failed to generate Configuration ROM image for host " + "%s-%d", hl->name, host->id); return 0; } @@ -212,13 +194,13 @@ void hpsb_register_highlevel(struct hpsb_highlevel *hl) { unsigned long flags; - INIT_LIST_HEAD(&hl->addr_list); + INIT_LIST_HEAD(&hl->addr_list); INIT_LIST_HEAD(&hl->host_info_list); rwlock_init(&hl->host_info_lock); down_write(&hl_drivers_sem); - list_add_tail(&hl->hl_list, &hl_drivers); + list_add_tail(&hl->hl_list, &hl_drivers); up_write(&hl_drivers_sem); write_lock_irqsave(&hl_irqs_lock, flags); @@ -227,8 +209,7 @@ void hpsb_register_highlevel(struct hpsb_highlevel *hl) if (hl->add_host) nodemgr_for_each_host(hl, highlevel_for_each_host_reg); - - return; + return; } static void __delete_addr(struct hpsb_address_serve *as) @@ -238,7 +219,8 @@ static void __delete_addr(struct hpsb_address_serve *as) kfree(as); } -static void __unregister_host(struct hpsb_highlevel *hl, struct hpsb_host *host, int update_cr) +static void __unregister_host(struct hpsb_highlevel *hl, struct hpsb_host *host, + int update_cr) { unsigned long flags; struct list_head *lh, *next; @@ -253,7 +235,6 @@ static void __unregister_host(struct hpsb_highlevel *hl, struct hpsb_host *host, write_lock_irqsave(&addr_space_lock, flags); list_for_each_safe (lh, next, &hl->addr_list) { as = list_entry(lh, struct hpsb_address_serve, hl_list); - if (as->host == host) __delete_addr(as); } @@ -261,15 +242,12 @@ static void __unregister_host(struct hpsb_highlevel *hl, struct hpsb_host *host, /* Now update the config-rom to reflect anything removed by the * highlevel driver. */ - if (update_cr && host->update_config_rom) { - if (hpsb_update_config_rom_image(host) < 0) { - HPSB_ERR("Failed to generate Configuration ROM image for host " - "%s-%d", hl->name, host->id); - } - } + if (update_cr && host->update_config_rom && + hpsb_update_config_rom_image(host) < 0) + HPSB_ERR("Failed to generate Configuration ROM image for host " + "%s-%d", hl->name, host->id); - /* And finally, remove all the host info associated between these - * two. */ + /* Finally remove all the host info associated between these two. */ hpsb_destroy_hostinfo(hl, host); } @@ -278,7 +256,6 @@ static int highlevel_for_each_host_unreg(struct hpsb_host *host, void *__data) struct hpsb_highlevel *hl = __data; __unregister_host(hl, host, 1); - return 0; } @@ -291,7 +268,7 @@ void hpsb_unregister_highlevel(struct hpsb_highlevel *hl) write_unlock_irqrestore(&hl_irqs_lock, flags); down_write(&hl_drivers_sem); - list_del(&hl->hl_list); + list_del(&hl->hl_list); up_write(&hl_drivers_sem); nodemgr_for_each_host(hl, highlevel_for_each_host_unreg); @@ -324,9 +301,11 @@ u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl, end = CSR1212_ALL_SPACE_END; } - if (((start|end) & ~align_mask) || (start >= end) || (end > 0x1000000000000ULL)) { - HPSB_ERR("%s called with invalid addresses (start = %012Lx end = %012Lx)", - __FUNCTION__, (unsigned long long)start, (unsigned long long)end); + if (((start|end) & ~align_mask) || (start >= end) || + (end > CSR1212_ALL_SPACE_END)) { + HPSB_ERR("%s called with invalid addresses " + "(start = %012Lx end = %012Lx)", __FUNCTION__, + (unsigned long long)start,(unsigned long long)end); return retval; } @@ -340,20 +319,21 @@ u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl, as->host = host; write_lock_irqsave(&addr_space_lock, flags); - list_for_each(entry, &host->addr_space) { u64 a1sa, a1ea; u64 a2sa, a2ea; a1 = list_entry(entry, struct hpsb_address_serve, host_list); - a2 = list_entry(entry->next, struct hpsb_address_serve, host_list); + a2 = list_entry(entry->next, struct hpsb_address_serve, + host_list); a1sa = a1->start & align_mask; a1ea = (a1->end + alignment -1) & align_mask; a2sa = a2->start & align_mask; a2ea = (a2->end + alignment -1) & align_mask; - if ((a2sa - a1ea >= size) && (a2sa - start >= size) && (a2sa > start)) { + if ((a2sa - a1ea >= size) && (a2sa - start >= size) && + (a2sa > start)) { as->start = max(start, a1ea); as->end = as->start + size; list_add(&as->host_list, entry); @@ -362,47 +342,45 @@ u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl, break; } } - write_unlock_irqrestore(&addr_space_lock, flags); - if (retval == CSR1212_INVALID_ADDR_SPACE) { + if (retval == CSR1212_INVALID_ADDR_SPACE) kfree(as); - } - return retval; } int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host, - struct hpsb_address_ops *ops, u64 start, u64 end) + struct hpsb_address_ops *ops, u64 start, u64 end) { - struct hpsb_address_serve *as; + struct hpsb_address_serve *as; struct list_head *lh; - int retval = 0; - unsigned long flags; + int retval = 0; + unsigned long flags; - if (((start|end) & 3) || (start >= end) || (end > 0x1000000000000ULL)) { - HPSB_ERR("%s called with invalid addresses", __FUNCTION__); - return 0; - } + if (((start|end) & 3) || (start >= end) || + (end > CSR1212_ALL_SPACE_END)) { + HPSB_ERR("%s called with invalid addresses", __FUNCTION__); + return 0; + } as = kmalloc(sizeof(*as), GFP_ATOMIC); if (!as) return 0; - INIT_LIST_HEAD(&as->host_list); - INIT_LIST_HEAD(&as->hl_list); - as->op = ops; - as->start = start; - as->end = end; + INIT_LIST_HEAD(&as->host_list); + INIT_LIST_HEAD(&as->hl_list); + as->op = ops; + as->start = start; + as->end = end; as->host = host; write_lock_irqsave(&addr_space_lock, flags); - list_for_each(lh, &host->addr_space) { struct hpsb_address_serve *as_this = list_entry(lh, struct hpsb_address_serve, host_list); struct hpsb_address_serve *as_next = - list_entry(lh->next, struct hpsb_address_serve, host_list); + list_entry(lh->next, struct hpsb_address_serve, + host_list); if (as_this->end > as->start) break; @@ -418,60 +396,51 @@ int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host, if (retval == 0) kfree(as); - - return retval; + return retval; } int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host, - u64 start) + u64 start) { - int retval = 0; - struct hpsb_address_serve *as; - struct list_head *lh, *next; - unsigned long flags; - - write_lock_irqsave(&addr_space_lock, flags); + int retval = 0; + struct hpsb_address_serve *as; + struct list_head *lh, *next; + unsigned long flags; + write_lock_irqsave(&addr_space_lock, flags); list_for_each_safe (lh, next, &hl->addr_list) { - as = list_entry(lh, struct hpsb_address_serve, hl_list); - if (as->start == start && as->host == host) { + as = list_entry(lh, struct hpsb_address_serve, hl_list); + if (as->start == start && as->host == host) { __delete_addr(as); - retval = 1; - break; - } - } - - write_unlock_irqrestore(&addr_space_lock, flags); - - return retval; + retval = 1; + break; + } + } + write_unlock_irqrestore(&addr_space_lock, flags); + return retval; } int hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host, - unsigned int channel) + unsigned int channel) { - if (channel > 63) { - HPSB_ERR("%s called with invalid channel", __FUNCTION__); - return -EINVAL; - } - - if (host->iso_listen_count[channel]++ == 0) { - return host->driver->devctl(host, ISO_LISTEN_CHANNEL, channel); - } - + if (channel > 63) { + HPSB_ERR("%s called with invalid channel", __FUNCTION__); + return -EINVAL; + } + if (host->iso_listen_count[channel]++ == 0) + return host->driver->devctl(host, ISO_LISTEN_CHANNEL, channel); return 0; } void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host, - unsigned int channel) + unsigned int channel) { - if (channel > 63) { - HPSB_ERR("%s called with invalid channel", __FUNCTION__); - return; - } - - if (--host->iso_listen_count[channel] == 0) { - host->driver->devctl(host, ISO_UNLISTEN_CHANNEL, channel); - } + if (channel > 63) { + HPSB_ERR("%s called with invalid channel", __FUNCTION__); + return; + } + if (--host->iso_listen_count[channel] == 0) + host->driver->devctl(host, ISO_UNLISTEN_CHANNEL, channel); } static void init_hpsb_highlevel(struct hpsb_host *host) @@ -492,26 +461,24 @@ static void init_hpsb_highlevel(struct hpsb_host *host) void highlevel_add_host(struct hpsb_host *host) { - struct hpsb_highlevel *hl; + struct hpsb_highlevel *hl; init_hpsb_highlevel(host); down_read(&hl_drivers_sem); - list_for_each_entry(hl, &hl_drivers, hl_list) { + list_for_each_entry(hl, &hl_drivers, hl_list) { if (hl->add_host) hl->add_host(host); - } - up_read(&hl_drivers_sem); - if (host->update_config_rom) { - if (hpsb_update_config_rom_image(host) < 0) - HPSB_ERR("Failed to generate Configuration ROM image for " - "host %s-%d", hl->name, host->id); } + up_read(&hl_drivers_sem); + if (host->update_config_rom && hpsb_update_config_rom_image(host) < 0) + HPSB_ERR("Failed to generate Configuration ROM image for host " + "%s-%d", hl->name, host->id); } void highlevel_remove_host(struct hpsb_host *host) { - struct hpsb_highlevel *hl; + struct hpsb_highlevel *hl; down_read(&hl_drivers_sem); list_for_each_entry(hl, &hl_drivers, hl_list) @@ -522,186 +489,168 @@ void highlevel_remove_host(struct hpsb_host *host) void highlevel_host_reset(struct hpsb_host *host) { unsigned long flags; - struct hpsb_highlevel *hl; + struct hpsb_highlevel *hl; read_lock_irqsave(&hl_irqs_lock, flags); list_for_each_entry(hl, &hl_irqs, irq_list) { - if (hl->host_reset) - hl->host_reset(host); - } + if (hl->host_reset) + hl->host_reset(host); + } read_unlock_irqrestore(&hl_irqs_lock, flags); } void highlevel_iso_receive(struct hpsb_host *host, void *data, size_t length) { unsigned long flags; - struct hpsb_highlevel *hl; - int channel = (((quadlet_t *)data)[0] >> 8) & 0x3f; + struct hpsb_highlevel *hl; + int channel = (((quadlet_t *)data)[0] >> 8) & 0x3f; - read_lock_irqsave(&hl_irqs_lock, flags); + read_lock_irqsave(&hl_irqs_lock, flags); list_for_each_entry(hl, &hl_irqs, irq_list) { - if (hl->iso_receive) - hl->iso_receive(host, channel, data, length); - } - read_unlock_irqrestore(&hl_irqs_lock, flags); + if (hl->iso_receive) + hl->iso_receive(host, channel, data, length); + } + read_unlock_irqrestore(&hl_irqs_lock, flags); } void highlevel_fcp_request(struct hpsb_host *host, int nodeid, int direction, void *data, size_t length) { unsigned long flags; - struct hpsb_highlevel *hl; - int cts = ((quadlet_t *)data)[0] >> 4; + struct hpsb_highlevel *hl; + int cts = ((quadlet_t *)data)[0] >> 4; - read_lock_irqsave(&hl_irqs_lock, flags); + read_lock_irqsave(&hl_irqs_lock, flags); list_for_each_entry(hl, &hl_irqs, irq_list) { - if (hl->fcp_request) - hl->fcp_request(host, nodeid, direction, cts, data, + if (hl->fcp_request) + hl->fcp_request(host, nodeid, direction, cts, data, length); - } - read_unlock_irqrestore(&hl_irqs_lock, flags); + } + read_unlock_irqrestore(&hl_irqs_lock, flags); } -int highlevel_read(struct hpsb_host *host, int nodeid, void *data, - u64 addr, unsigned int length, u16 flags) +int highlevel_read(struct hpsb_host *host, int nodeid, void *data, u64 addr, + unsigned int length, u16 flags) { - struct hpsb_address_serve *as; - unsigned int partlength; - int rcode = RCODE_ADDRESS_ERROR; - - read_lock(&addr_space_lock); + struct hpsb_address_serve *as; + unsigned int partlength; + int rcode = RCODE_ADDRESS_ERROR; + read_lock(&addr_space_lock); list_for_each_entry(as, &host->addr_space, host_list) { if (as->start > addr) break; - if (as->end > addr) { - partlength = min(as->end - addr, (u64) length); + if (as->end > addr) { + partlength = min(as->end - addr, (u64) length); - if (as->op->read) { - rcode = as->op->read(host, nodeid, data, + if (as->op->read) + rcode = as->op->read(host, nodeid, data, addr, partlength, flags); - } else { - rcode = RCODE_TYPE_ERROR; - } + else + rcode = RCODE_TYPE_ERROR; data += partlength; - length -= partlength; - addr += partlength; + length -= partlength; + addr += partlength; - if ((rcode != RCODE_COMPLETE) || !length) { - break; - } - } - } - - read_unlock(&addr_space_lock); - - if (length && (rcode == RCODE_COMPLETE)) { - rcode = RCODE_ADDRESS_ERROR; - } + if ((rcode != RCODE_COMPLETE) || !length) + break; + } + } + read_unlock(&addr_space_lock); - return rcode; + if (length && (rcode == RCODE_COMPLETE)) + rcode = RCODE_ADDRESS_ERROR; + return rcode; } -int highlevel_write(struct hpsb_host *host, int nodeid, int destid, - void *data, u64 addr, unsigned int length, u16 flags) +int highlevel_write(struct hpsb_host *host, int nodeid, int destid, void *data, + u64 addr, unsigned int length, u16 flags) { - struct hpsb_address_serve *as; - unsigned int partlength; - int rcode = RCODE_ADDRESS_ERROR; - - read_lock(&addr_space_lock); + struct hpsb_address_serve *as; + unsigned int partlength; + int rcode = RCODE_ADDRESS_ERROR; + read_lock(&addr_space_lock); list_for_each_entry(as, &host->addr_space, host_list) { if (as->start > addr) break; - if (as->end > addr) { - partlength = min(as->end - addr, (u64) length); + if (as->end > addr) { + partlength = min(as->end - addr, (u64) length); - if (as->op->write) { - rcode = as->op->write(host, nodeid, destid, - data, addr, partlength, flags); - } else { - rcode = RCODE_TYPE_ERROR; - } + if (as->op->write) + rcode = as->op->write(host, nodeid, destid, + data, addr, partlength, + flags); + else + rcode = RCODE_TYPE_ERROR; data += partlength; - length -= partlength; - addr += partlength; + length -= partlength; + addr += partlength; - if ((rcode != RCODE_COMPLETE) || !length) { - break; - } - } - } - - read_unlock(&addr_space_lock); - - if (length && (rcode == RCODE_COMPLETE)) { - rcode = RCODE_ADDRESS_ERROR; - } + if ((rcode != RCODE_COMPLETE) || !length) + break; + } + } + read_unlock(&addr_space_lock); - return rcode; + if (length && (rcode == RCODE_COMPLETE)) + rcode = RCODE_ADDRESS_ERROR; + return rcode; } - int highlevel_lock(struct hpsb_host *host, int nodeid, quadlet_t *store, - u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode, u16 flags) + u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode, + u16 flags) { - struct hpsb_address_serve *as; - int rcode = RCODE_ADDRESS_ERROR; - - read_lock(&addr_space_lock); + struct hpsb_address_serve *as; + int rcode = RCODE_ADDRESS_ERROR; + read_lock(&addr_space_lock); list_for_each_entry(as, &host->addr_space, host_list) { if (as->start > addr) break; - if (as->end > addr) { - if (as->op->lock) { - rcode = as->op->lock(host, nodeid, store, addr, - data, arg, ext_tcode, flags); - } else { - rcode = RCODE_TYPE_ERROR; - } - - break; - } - } - - read_unlock(&addr_space_lock); - - return rcode; + if (as->end > addr) { + if (as->op->lock) + rcode = as->op->lock(host, nodeid, store, addr, + data, arg, ext_tcode, + flags); + else + rcode = RCODE_TYPE_ERROR; + break; + } + } + read_unlock(&addr_space_lock); + return rcode; } int highlevel_lock64(struct hpsb_host *host, int nodeid, octlet_t *store, - u64 addr, octlet_t data, octlet_t arg, int ext_tcode, u16 flags) + u64 addr, octlet_t data, octlet_t arg, int ext_tcode, + u16 flags) { - struct hpsb_address_serve *as; - int rcode = RCODE_ADDRESS_ERROR; + struct hpsb_address_serve *as; + int rcode = RCODE_ADDRESS_ERROR; - read_lock(&addr_space_lock); + read_lock(&addr_space_lock); list_for_each_entry(as, &host->addr_space, host_list) { if (as->start > addr) break; - if (as->end > addr) { - if (as->op->lock64) { - rcode = as->op->lock64(host, nodeid, store, - addr, data, arg, - ext_tcode, flags); - } else { - rcode = RCODE_TYPE_ERROR; - } - - break; - } - } - - read_unlock(&addr_space_lock); - - return rcode; + if (as->end > addr) { + if (as->op->lock64) + rcode = as->op->lock64(host, nodeid, store, + addr, data, arg, + ext_tcode, flags); + else + rcode = RCODE_TYPE_ERROR; + break; + } + } + read_unlock(&addr_space_lock); + return rcode; } -- cgit v1.2.3 From 7136b8073f0123918e3e50269ae021bbb09e1a81 Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Mon, 12 Jun 2006 18:16:25 -0400 Subject: eth1394: replace __constant_htons by htons ...and __constant_ntohs, __constant_ntohl, __constant_cpu_to_be32 too where possible. Htons and friends are resolved to constants in these places anyway. Also fix an endianess glitch in a log message, spotted by Alexey Dobriyan. Signed-off-by: Stefan Richter Signed-off-by: Ben Collins --- drivers/ieee1394/eth1394.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c index cf80fed6163..5bda15904a0 100644 --- a/drivers/ieee1394/eth1394.c +++ b/drivers/ieee1394/eth1394.c @@ -770,7 +770,7 @@ static int ether1394_rebuild_header(struct sk_buff *skb) default: ETH1394_PRINT(KERN_DEBUG, dev->name, "unable to resolve type %04x addresses.\n", - eth->h_proto); + ntohs(eth->h_proto)); break; } @@ -792,9 +792,8 @@ static int ether1394_header_cache(struct neighbour *neigh, struct hh_cache *hh) (16 - ETH1394_HLEN)); struct net_device *dev = neigh->dev; - if (type == __constant_htons(ETH_P_802_3)) { + if (type == htons(ETH_P_802_3)) return -1; - } eth->h_proto = type; memcpy(eth->h_dest, neigh->ha, dev->addr_len); @@ -883,7 +882,7 @@ static inline u16 ether1394_parse_encap(struct sk_buff *skb, /* If this is an ARP packet, convert it. First, we want to make * use of some of the fields, since they tell us a little bit * about the sending machine. */ - if (ether_type == __constant_htons (ETH_P_ARP)) { + if (ether_type == htons(ETH_P_ARP)) { struct eth1394_arp *arp1394 = (struct eth1394_arp*)skb->data; struct arphdr *arp = (struct arphdr *)skb->data; unsigned char *arp_ptr = (unsigned char *)(arp + 1); @@ -939,8 +938,8 @@ static inline u16 ether1394_parse_encap(struct sk_buff *skb, } /* Now add the ethernet header. */ - if (dev->hard_header (skb, dev, __constant_ntohs (ether_type), - &dest_hw, NULL, skb->len) >= 0) + if (dev->hard_header(skb, dev, ntohs(ether_type), &dest_hw, NULL, + skb->len) >= 0) ret = ether1394_type_trans(skb, dev); return ret; @@ -1510,8 +1509,8 @@ static inline void ether1394_prep_gasp_packet(struct hpsb_packet *p, p->data = ((quadlet_t*)skb->data) - 2; p->data[0] = cpu_to_be32((priv->host->node_id << 16) | ETHER1394_GASP_SPECIFIER_ID_HI); - p->data[1] = __constant_cpu_to_be32((ETHER1394_GASP_SPECIFIER_ID_LO << 24) | - ETHER1394_GASP_VERSION); + p->data[1] = cpu_to_be32((ETHER1394_GASP_SPECIFIER_ID_LO << 24) | + ETHER1394_GASP_VERSION); /* Setting the node id to ALL_NODES (not LOCAL_BUS | ALL_NODES) * prevents hpsb_send_packet() from setting the speed to an arbitrary @@ -1666,9 +1665,9 @@ static int ether1394_tx (struct sk_buff *skb, struct net_device *dev) /* Set the transmission type for the packet. ARP packets and IP * broadcast packets are sent via GASP. */ if (memcmp(eth->h_dest, dev->broadcast, ETH1394_ALEN) == 0 || - proto == __constant_htons(ETH_P_ARP) || - (proto == __constant_htons(ETH_P_IP) && - IN_MULTICAST(__constant_ntohl(skb->nh.iph->daddr)))) { + proto == htons(ETH_P_ARP) || + (proto == htons(ETH_P_IP) && + IN_MULTICAST(ntohl(skb->nh.iph->daddr)))) { tx_type = ETH1394_GASP; dest_node = LOCAL_BUS | ALL_NODES; max_payload = priv->bc_maxpayload - ETHER1394_GASP_OVERHEAD; @@ -1700,7 +1699,7 @@ static int ether1394_tx (struct sk_buff *skb, struct net_device *dev) } /* If this is an ARP packet, convert it */ - if (proto == __constant_htons (ETH_P_ARP)) + if (proto == htons(ETH_P_ARP)) ether1394_arp_to_1394arp (skb, dev); ptask->hdr.words.word1 = 0; -- cgit v1.2.3 From 31925323b1b51bb65db729e029472a8b1f635b7d Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Tue, 13 Jun 2006 13:43:00 +1000 Subject: powerpc: Fix some missed ppc32 mm->context.id conversions Signed-off-by: Paul Mackerras --- arch/ppc/mm/init.c | 2 +- arch/ppc/mm/tlb.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c index 386e000bcb7..c9bd184a295 100644 --- a/arch/ppc/mm/init.c +++ b/arch/ppc/mm/init.c @@ -583,7 +583,7 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, mm = (address < TASK_SIZE)? vma->vm_mm: &init_mm; pmd = pmd_offset(pgd_offset(mm, address), address); if (!pmd_none(*pmd)) - add_hash_page(mm->context, address, pmd_val(*pmd)); + add_hash_page(mm->context.id, address, pmd_val(*pmd)); } #endif } diff --git a/arch/ppc/mm/tlb.c b/arch/ppc/mm/tlb.c index 6c3dc3c44c8..606b023196a 100644 --- a/arch/ppc/mm/tlb.c +++ b/arch/ppc/mm/tlb.c @@ -42,7 +42,7 @@ void flush_hash_entry(struct mm_struct *mm, pte_t *ptep, unsigned long addr) if (Hash != 0) { ptephys = __pa(ptep) & PAGE_MASK; - flush_hash_pages(mm->context, addr, ptephys, 1); + flush_hash_pages(mm->context.id, addr, ptephys, 1); } } @@ -102,7 +102,7 @@ static void flush_range(struct mm_struct *mm, unsigned long start, pmd_t *pmd; unsigned long pmd_end; int count; - unsigned int ctx = mm->context; + unsigned int ctx = mm->context.id; if (Hash == 0) { _tlbia(); @@ -166,7 +166,7 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr) mm = (vmaddr < TASK_SIZE)? vma->vm_mm: &init_mm; pmd = pmd_offset(pgd_offset(mm, vmaddr), vmaddr); if (!pmd_none(*pmd)) - flush_hash_pages(mm->context, vmaddr, pmd_val(*pmd), 1); + flush_hash_pages(mm->context.id, vmaddr, pmd_val(*pmd), 1); FINISH_FLUSH; } -- cgit v1.2.3 From d7ede1aa5dfff53e76dbabac5b8087341686f662 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Tue, 13 Jun 2006 16:28:11 +1000 Subject: [XFS] Minor XFS documentation updates. Signed-off-by: Nathan Scott --- MAINTAINERS | 2 +- fs/xfs/Kconfig | 21 +++++++++++---------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index c3c5842402d..60972f8a5c6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3179,7 +3179,7 @@ XFS FILESYSTEM P: Silicon Graphics Inc M: xfs-masters@oss.sgi.com M: nathans@sgi.com -L: linux-xfs@oss.sgi.com +L: xfs@oss.sgi.com W: http://oss.sgi.com/projects/xfs S: Supported diff --git a/fs/xfs/Kconfig b/fs/xfs/Kconfig index bac27d66151..236f9cf3714 100644 --- a/fs/xfs/Kconfig +++ b/fs/xfs/Kconfig @@ -65,18 +65,19 @@ config XFS_POSIX_ACL If you don't know what Access Control Lists are, say N. config XFS_RT - bool "XFS Realtime support (EXPERIMENTAL)" - depends on XFS_FS && EXPERIMENTAL + bool "XFS Realtime subvolume support" + depends on XFS_FS help If you say Y here you will be able to mount and use XFS filesystems - which contain a realtime subvolume. The realtime subvolume is a - separate area of disk space where only file data is stored. The - realtime subvolume is designed to provide very deterministic - data rates suitable for media streaming applications. - - See the xfs man page in section 5 for a bit more information. + which contain a realtime subvolume. The realtime subvolume is a + separate area of disk space where only file data is stored. It was + originally designed to provide deterministic data rates suitable + for media streaming applications, but is also useful as a generic + mechanism for ensuring data and metadata/log I/Os are completely + separated. Regular file I/Os are isolated to a separate device + from all other requests, and this can be done quite transparently + to applications via the inherit-realtime directory inode flag. - This feature is unsupported at this time, is not yet fully - functional, and may cause serious problems. + See the xfs man page in section 5 for additional information. If unsure, say N. -- cgit v1.2.3 From bf717b11aec20965d48dea36dea3eea18a75d18c Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Tue, 13 Jun 2006 20:27:03 -0400 Subject: [libata] Update docs to reflect current driver API --- Documentation/DocBook/libata.tmpl | 104 +++++++++++++++++++++++++++++--------- drivers/scsi/libata-core.c | 2 +- 2 files changed, 81 insertions(+), 25 deletions(-) diff --git a/Documentation/DocBook/libata.tmpl b/Documentation/DocBook/libata.tmpl index f869b03929d..e97c3231454 100644 --- a/Documentation/DocBook/libata.tmpl +++ b/Documentation/DocBook/libata.tmpl @@ -169,6 +169,22 @@ void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf); + PIO data read/write + +void (*data_xfer) (struct ata_device *, unsigned char *, unsigned int, int); + + + +All bmdma-style drivers must implement this hook. This is the low-level +operation that actually copies the data bytes during a PIO data +transfer. +Typically the driver +will choose one of ata_pio_data_xfer_noirq(), ata_pio_data_xfer(), or +ata_mmio_data_xfer(). + + + + ATA command execute void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf); @@ -204,11 +220,10 @@ command. u8 (*check_status)(struct ata_port *ap); u8 (*check_altstatus)(struct ata_port *ap); -u8 (*check_err)(struct ata_port *ap); - Reads the Status/AltStatus/Error ATA shadow register from + Reads the Status/AltStatus ATA shadow register from hardware. On some hardware, reading the Status register has the side effect of clearing the interrupt condition. Most drivers for taskfile-based hardware use @@ -269,23 +284,6 @@ void (*set_mode) (struct ata_port *ap); - Reset ATA bus - -void (*phy_reset) (struct ata_port *ap); - - - - The very first step in the probe phase. Actions vary depending - on the bus type, typically. After waking up the device and probing - for device presence (PATA and SATA), typically a soft reset - (SRST) will be performed. Drivers typically use the helper - functions ata_bus_reset() or sata_phy_reset() for this hook. - Many SATA drivers use sata_phy_reset() or call it from within - their own phy_reset() functions. - - - - Control PCI IDE BMDMA engine void (*bmdma_setup) (struct ata_queued_cmd *qc); @@ -354,16 +352,74 @@ int (*qc_issue) (struct ata_queued_cmd *qc); - Timeout (error) handling + Exception and probe handling (EH) void (*eng_timeout) (struct ata_port *ap); +void (*phy_reset) (struct ata_port *ap); + + + +Deprecated. Use ->error_handler() instead. + + + +void (*freeze) (struct ata_port *ap); +void (*thaw) (struct ata_port *ap); + + + +ata_port_freeze() is called when HSM violations or some other +condition disrupts normal operation of the port. A frozen port +is not allowed to perform any operation until the port is +thawed, which usually follows a successful reset. + + + +The optional ->freeze() callback can be used for freezing the port +hardware-wise (e.g. mask interrupt and stop DMA engine). If a +port cannot be frozen hardware-wise, the interrupt handler +must ack and clear interrupts unconditionally while the port +is frozen. + + +The optional ->thaw() callback is called to perform the opposite of ->freeze(): +prepare the port for normal operation once again. Unmask interrupts, +start DMA engine, etc. + + + +void (*error_handler) (struct ata_port *ap); + + + +->error_handler() is a driver's hook into probe, hotplug, and recovery +and other exceptional conditions. The primary responsibility of an +implementation is to call ata_do_eh() or ata_bmdma_drive_eh() with a set +of EH hooks as arguments: + + + +'prereset' hook (may be NULL) is called during an EH reset, before any other actions +are taken. + + + +'postreset' hook (may be NULL) is called after the EH reset is performed. Based on +existing conditions, severity of the problem, and hardware capabilities, + + + +Either 'softreset' (may be NULL) or 'hardreset' (may be NULL) will be +called to perform the low-level EH reset. + + + +void (*post_internal_cmd) (struct ata_queued_cmd *qc); -This is a high level error handling function, called from the -error handling thread, when a command times out. Most newer -hardware will implement its own error handling code here. IDE BMDMA -drivers may use the helper function ata_eng_timeout(). +Perform any hardware-specific actions necessary to finish processing +after executing a probe-time or EH-time command via ata_exec_internal(). diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index d73cb3672d6..89c3fbe6e67 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3496,7 +3496,7 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words) /** * ata_mmio_data_xfer - Transfer data by MMIO - * @dev: device for this I/O + * @adev: device for this I/O * @buf: data buffer * @buflen: buffer length * @write_data: read/write -- cgit v1.2.3 From 61686124f47d7c4b78610346c5f8f9d8a6d46bb5 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Fri, 17 Mar 2006 16:44:00 -0500 Subject: [ACPI] ACPICA 20060317 Implemented the use of a cache object for all internal namespace nodes. Since there are about 1000 static nodes in a typical system, this will decrease memory use for cache implementations that minimize per-allocation overhead (such as a slab allocator.) Removed the reference count mechanism for internal namespace nodes, since it was deemed unnecessary. This reduces the size of each namespace node by about 5%-10% on all platforms. Nodes are now 20 bytes for the 32-bit case, and 32 bytes for the 64-bit case. Optimized several internal data structures to reduce object size on 64-bit platforms by packing data within the 64-bit alignment. This includes the frequently used ACPI_OPERAND_OBJECT, of which there can be ~1000 static instances corresponding to the namespace objects. Added two new strings for the predefined _OSI method: "Windows 2001.1 SP1" and "Windows 2006". Split the allocation tracking mechanism out to a separate file, from utalloc.c to uttrack.c. This mechanism appears to be only useful for application-level code. Kernels may wish to not include uttrack.c in distributions. Removed all remnants of the obsolete ACPI_REPORT_* macros and the associated code. (These macros have been replaced by the ACPI_ERROR and ACPI_WARNING macros.) Signed-off-by: Bob Moore Signed-off-by: Len Brown --- drivers/acpi/bus.c | 4 +- drivers/acpi/dispatcher/dsmthdat.c | 12 +- drivers/acpi/dispatcher/dswscope.c | 2 +- drivers/acpi/dispatcher/dswstate.c | 12 +- drivers/acpi/events/evgpeblk.c | 2 +- drivers/acpi/events/evmisc.c | 3 +- drivers/acpi/events/evregion.c | 15 +- drivers/acpi/executer/excreate.c | 7 +- drivers/acpi/executer/exdump.c | 2 - drivers/acpi/namespace/nsalloc.c | 104 +------ drivers/acpi/namespace/nsutils.c | 4 +- drivers/acpi/osl.c | 5 +- drivers/acpi/parser/psscope.c | 12 +- drivers/acpi/parser/psutils.c | 2 +- drivers/acpi/resources/rscalc.c | 2 +- drivers/acpi/resources/rscreate.c | 7 +- drivers/acpi/resources/rslist.c | 110 +++---- drivers/acpi/resources/rsxface.c | 4 +- drivers/acpi/utilities/utalloc.c | 590 ++----------------------------------- drivers/acpi/utilities/utcache.c | 6 +- drivers/acpi/utilities/utdelete.c | 3 +- drivers/acpi/utilities/utglobal.c | 8 +- drivers/acpi/utilities/utmisc.c | 33 --- drivers/acpi/utilities/utresrc.c | 150 +++++++--- drivers/acpi/utilities/utstate.c | 10 +- include/acpi/acconfig.h | 5 +- include/acpi/acevents.h | 2 +- include/acpi/acglobal.h | 1 + include/acpi/aclocal.h | 208 ++++++------- include/acpi/acmacros.h | 20 +- include/acpi/acobject.h | 181 ++++++------ include/acpi/acoutput.h | 2 +- include/acpi/acparser.h | 7 +- include/acpi/acpixf.h | 4 +- include/acpi/acresrc.h | 5 +- include/acpi/acstruct.h | 39 +-- include/acpi/actypes.h | 36 +-- include/acpi/acutils.h | 49 ++- include/acpi/amlresrc.h | 31 +- include/acpi/platform/acenv.h | 12 +- 40 files changed, 558 insertions(+), 1153 deletions(-) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 606f8733a77..9c4ac0191f6 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -596,6 +596,8 @@ void __init acpi_early_init(void) if (acpi_disabled) return_VOID; + printk(KERN_INFO PREFIX "Core revision %08x\n", ACPI_CA_VERSION); + /* enable workarounds, unless strict ACPI spec. compliance */ if (!acpi_strict) acpi_gbl_enable_interpreter_slack = TRUE; @@ -743,8 +745,6 @@ static int __init acpi_init(void) ACPI_FUNCTION_TRACE("acpi_init"); - printk(KERN_INFO PREFIX "Subsystem revision %08x\n", ACPI_CA_VERSION); - if (acpi_disabled) { printk(KERN_INFO PREFIX "Interpreter disabled.\n"); return_VALUE(-ENODEV); diff --git a/drivers/acpi/dispatcher/dsmthdat.c b/drivers/acpi/dispatcher/dsmthdat.c index 2ed48439835..ce4de18f122 100644 --- a/drivers/acpi/dispatcher/dsmthdat.c +++ b/drivers/acpi/dispatcher/dsmthdat.c @@ -100,10 +100,10 @@ void acpi_ds_method_data_init(struct acpi_walk_state *walk_state) ACPI_MOVE_32_TO_32(&walk_state->arguments[i].name, NAMEOF_ARG_NTE); walk_state->arguments[i].name.integer |= (i << 24); - walk_state->arguments[i].descriptor = ACPI_DESC_TYPE_NAMED; + walk_state->arguments[i].descriptor_type = ACPI_DESC_TYPE_NAMED; walk_state->arguments[i].type = ACPI_TYPE_ANY; - walk_state->arguments[i].flags = ANOBJ_END_OF_PEER_LIST | - ANOBJ_METHOD_ARG; + walk_state->arguments[i].flags = + ANOBJ_END_OF_PEER_LIST | ANOBJ_METHOD_ARG; } /* Init the method locals */ @@ -113,11 +113,11 @@ void acpi_ds_method_data_init(struct acpi_walk_state *walk_state) NAMEOF_LOCAL_NTE); walk_state->local_variables[i].name.integer |= (i << 24); - walk_state->local_variables[i].descriptor = + walk_state->local_variables[i].descriptor_type = ACPI_DESC_TYPE_NAMED; walk_state->local_variables[i].type = ACPI_TYPE_ANY; - walk_state->local_variables[i].flags = ANOBJ_END_OF_PEER_LIST | - ANOBJ_METHOD_LOCAL; + walk_state->local_variables[i].flags = + ANOBJ_END_OF_PEER_LIST | ANOBJ_METHOD_LOCAL; } return_VOID; diff --git a/drivers/acpi/dispatcher/dswscope.c b/drivers/acpi/dispatcher/dswscope.c index e2954fff8c5..3cd6895ed2c 100644 --- a/drivers/acpi/dispatcher/dswscope.c +++ b/drivers/acpi/dispatcher/dswscope.c @@ -128,7 +128,7 @@ acpi_ds_scope_stack_push(struct acpi_namespace_node *node, /* Init new scope object */ - scope_info->common.data_type = ACPI_DESC_TYPE_STATE_WSCOPE; + scope_info->common.descriptor_type = ACPI_DESC_TYPE_STATE_WSCOPE; scope_info->scope.node = node; scope_info->common.value = (u16) type; diff --git a/drivers/acpi/dispatcher/dswstate.c b/drivers/acpi/dispatcher/dswstate.c index d2846ffc977..4840eae47d3 100644 --- a/drivers/acpi/dispatcher/dswstate.c +++ b/drivers/acpi/dispatcher/dswstate.c @@ -337,7 +337,7 @@ acpi_status acpi_ds_result_stack_push(struct acpi_walk_state * walk_state) return (AE_NO_MEMORY); } - state->common.data_type = ACPI_DESC_TYPE_STATE_RESULT; + state->common.descriptor_type = ACPI_DESC_TYPE_STATE_RESULT; acpi_ut_push_generic_state(&walk_state->results, state); ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Results=%p State=%p\n", @@ -620,7 +620,7 @@ struct acpi_walk_state *acpi_ds_pop_walk_state(struct acpi_thread_state *thread) * * PARAMETERS: owner_id - ID for object creation * Origin - Starting point for this walk - * mth_desc - Method object + * method_desc - Method object * Thread - Current thread state * * RETURN: Pointer to the new walk state. @@ -634,7 +634,7 @@ struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id, union acpi_parse_object *origin, union acpi_operand_object - *mth_desc, + *method_desc, struct acpi_thread_state *thread) { @@ -648,10 +648,10 @@ struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id, return_PTR(NULL); } - walk_state->data_type = ACPI_DESC_TYPE_WALK; + walk_state->descriptor_type = ACPI_DESC_TYPE_WALK; + walk_state->method_desc = method_desc; walk_state->owner_id = owner_id; walk_state->origin = origin; - walk_state->method_desc = mth_desc; walk_state->thread = thread; walk_state->parser_state.start_op = origin; @@ -819,7 +819,7 @@ void acpi_ds_delete_walk_state(struct acpi_walk_state *walk_state) return; } - if (walk_state->data_type != ACPI_DESC_TYPE_WALK) { + if (walk_state->descriptor_type != ACPI_DESC_TYPE_WALK) { ACPI_ERROR((AE_INFO, "%p is not a valid walk state", walk_state)); return; diff --git a/drivers/acpi/events/evgpeblk.c b/drivers/acpi/events/evgpeblk.c index e8e72986f0d..4e90c1f837c 100644 --- a/drivers/acpi/events/evgpeblk.c +++ b/drivers/acpi/events/evgpeblk.c @@ -131,7 +131,7 @@ u8 acpi_ev_valid_gpe_event(struct acpi_gpe_event_info *gpe_event_info) * ******************************************************************************/ -acpi_status acpi_ev_walk_gpe_list(ACPI_GPE_CALLBACK gpe_walk_callback) +acpi_status acpi_ev_walk_gpe_list(acpi_gpe_callback gpe_walk_callback) { struct acpi_gpe_block_info *gpe_block; struct acpi_gpe_xrupt_info *gpe_xrupt_info; diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c index 334407239f2..b216b3229e2 100644 --- a/drivers/acpi/events/evmisc.c +++ b/drivers/acpi/events/evmisc.c @@ -185,7 +185,8 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node, return (AE_NO_MEMORY); } - notify_info->common.data_type = ACPI_DESC_TYPE_STATE_NOTIFY; + notify_info->common.descriptor_type = + ACPI_DESC_TYPE_STATE_NOTIFY; notify_info->notify.node = node; notify_info->notify.value = (u16) notify_value; notify_info->notify.handler_obj = handler_obj; diff --git a/drivers/acpi/events/evregion.c b/drivers/acpi/events/evregion.c index 2b900ef05fa..0337ad222b2 100644 --- a/drivers/acpi/events/evregion.c +++ b/drivers/acpi/events/evregion.c @@ -250,7 +250,6 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function) cleanup: acpi_ut_remove_reference(params[0]); - return_ACPI_STATUS(status); } @@ -389,9 +388,8 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, acpi_ut_get_region_name(region_obj->region. space_id))); - if (! - (handler_desc->address_space. - hflags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { + if (!(handler_desc->address_space.handler_flags & + ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { /* * For handlers other than the default (supplied) handlers, we must * exit the interpreter because the handler *might* block -- we don't @@ -412,9 +410,8 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, space_id))); } - if (! - (handler_desc->address_space. - hflags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { + if (!(handler_desc->address_space.handler_flags & + ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { /* * We just returned from a non-default handler, we must re-enter the * interpreter @@ -772,7 +769,7 @@ acpi_ev_install_space_handler(struct acpi_namespace_node * node, union acpi_operand_object *handler_obj; acpi_status status; acpi_object_type type; - u16 flags = 0; + u8 flags = 0; ACPI_FUNCTION_TRACE("ev_install_space_handler"); @@ -930,7 +927,7 @@ acpi_ev_install_space_handler(struct acpi_namespace_node * node, /* Init handler obj */ handler_obj->address_space.space_id = (u8) space_id; - handler_obj->address_space.hflags = flags; + handler_obj->address_space.handler_flags = flags; handler_obj->address_space.region_list = NULL; handler_obj->address_space.node = node; handler_obj->address_space.handler = handler; diff --git a/drivers/acpi/executer/excreate.c b/drivers/acpi/executer/excreate.c index 68057540283..763e132da4c 100644 --- a/drivers/acpi/executer/excreate.c +++ b/drivers/acpi/executer/excreate.c @@ -243,8 +243,9 @@ acpi_status acpi_ex_create_mutex(struct acpi_walk_state *walk_state) obj_desc->mutex.node = (struct acpi_namespace_node *)walk_state->operands[0]; - status = acpi_ns_attach_object(obj_desc->mutex.node, - obj_desc, ACPI_TYPE_MUTEX); + status = + acpi_ns_attach_object(obj_desc->mutex.node, obj_desc, + ACPI_TYPE_MUTEX); cleanup: /* @@ -464,9 +465,9 @@ acpi_status acpi_ex_create_processor(struct acpi_walk_state *walk_state) /* Initialize the processor object from the operands */ obj_desc->processor.proc_id = (u8) operand[1]->integer.value; + obj_desc->processor.length = (u8) operand[3]->integer.value; obj_desc->processor.address = (acpi_io_address) operand[2]->integer.value; - obj_desc->processor.length = (u8) operand[3]->integer.value; /* Install the processor object in the parent Node */ diff --git a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c index 502293c35af..56db58b8e23 100644 --- a/drivers/acpi/executer/exdump.c +++ b/drivers/acpi/executer/exdump.c @@ -267,8 +267,6 @@ static struct acpi_exdump_info acpi_ex_dump_node[6] = { {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_node), NULL}, {ACPI_EXD_UINT8, ACPI_EXD_NSOFFSET(flags), "Flags"}, {ACPI_EXD_UINT8, ACPI_EXD_NSOFFSET(owner_id), "Owner Id"}, - {ACPI_EXD_UINT16, ACPI_EXD_NSOFFSET(reference_count), - "Reference Count"}, {ACPI_EXD_POINTER, ACPI_EXD_NSOFFSET(child), "Child List"}, {ACPI_EXD_POINTER, ACPI_EXD_NSOFFSET(peer), "Next Peer"} }; diff --git a/drivers/acpi/namespace/nsalloc.c b/drivers/acpi/namespace/nsalloc.c index acd4b6732ac..8b921c96d6a 100644 --- a/drivers/acpi/namespace/nsalloc.c +++ b/drivers/acpi/namespace/nsalloc.c @@ -47,9 +47,6 @@ #define _COMPONENT ACPI_NAMESPACE ACPI_MODULE_NAME("nsalloc") -/* Local prototypes */ -static void acpi_ns_remove_reference(struct acpi_namespace_node *node); - /******************************************************************************* * * FUNCTION: acpi_ns_create_node @@ -61,14 +58,13 @@ static void acpi_ns_remove_reference(struct acpi_namespace_node *node); * DESCRIPTION: Create a namespace node * ******************************************************************************/ - struct acpi_namespace_node *acpi_ns_create_node(u32 name) { struct acpi_namespace_node *node; ACPI_FUNCTION_TRACE("ns_create_node"); - node = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_namespace_node)); + node = acpi_os_acquire_object(acpi_gbl_namespace_cache); if (!node) { return_PTR(NULL); } @@ -76,9 +72,7 @@ struct acpi_namespace_node *acpi_ns_create_node(u32 name) ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_allocated++); node->name.integer = name; - node->reference_count = 1; ACPI_SET_DESCRIPTOR_TYPE(node, ACPI_DESC_TYPE_NAMED); - return_PTR(node); } @@ -139,10 +133,10 @@ void acpi_ns_delete_node(struct acpi_namespace_node *node) ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_freed++); /* - * Detach an object if there is one then delete the node + * Detach an object if there is one, then delete the node */ acpi_ns_detach_object(node); - ACPI_FREE(node); + (void)acpi_os_release_object(acpi_gbl_namespace_cache, node); return_VOID; } @@ -217,16 +211,6 @@ void acpi_ns_install_node(struct acpi_walk_state *walk_state, struct acpi_namesp acpi_ut_get_node_name(parent_node), acpi_ut_get_type_name(parent_node->type), parent_node)); - - /* - * Increment the reference count(s) of all parents up to - * the root! - */ - while ((node = acpi_ns_get_parent_node(node)) != NULL) { - node->reference_count++; - } - - return_VOID; } /******************************************************************************* @@ -246,7 +230,6 @@ void acpi_ns_delete_children(struct acpi_namespace_node *parent_node) { struct acpi_namespace_node *child_node; struct acpi_namespace_node *next_node; - struct acpi_namespace_node *node; u8 flags; ACPI_FUNCTION_TRACE_PTR("ns_delete_children", parent_node); @@ -292,26 +275,10 @@ void acpi_ns_delete_children(struct acpi_namespace_node *parent_node) */ acpi_ns_detach_object(child_node); - /* - * Decrement the reference count(s) of all parents up to - * the root! (counts were incremented when the node was created) - */ - node = child_node; - while ((node = acpi_ns_get_parent_node(node)) != NULL) { - node->reference_count--; - } - - /* There should be only one reference remaining on this node */ - - if (child_node->reference_count != 1) { - ACPI_WARNING((AE_INFO, - "Existing references (%d) on node being deleted (%p)", - child_node->reference_count, child_node)); - } - /* Now we can delete the node */ - ACPI_FREE(child_node); + (void)acpi_os_release_object(acpi_gbl_namespace_cache, + child_node); /* And move on to the next child in the list */ @@ -358,8 +325,9 @@ void acpi_ns_delete_namespace_subtree(struct acpi_namespace_node *parent_node) /* Get the next node in this scope (NULL if none) */ - child_node = acpi_ns_get_next_node(ACPI_TYPE_ANY, parent_node, - child_node); + child_node = + acpi_ns_get_next_node(ACPI_TYPE_ANY, parent_node, + child_node); if (child_node) { /* Found a child node - detach any attached object */ @@ -404,57 +372,6 @@ void acpi_ns_delete_namespace_subtree(struct acpi_namespace_node *parent_node) return_VOID; } -/******************************************************************************* - * - * FUNCTION: acpi_ns_remove_reference - * - * PARAMETERS: Node - Named node whose reference count is to be - * decremented - * - * RETURN: None. - * - * DESCRIPTION: Remove a Node reference. Decrements the reference count - * of all parent Nodes up to the root. Any node along - * the way that reaches zero references is freed. - * - ******************************************************************************/ - -static void acpi_ns_remove_reference(struct acpi_namespace_node *node) -{ - struct acpi_namespace_node *parent_node; - struct acpi_namespace_node *this_node; - - ACPI_FUNCTION_ENTRY(); - - /* - * Decrement the reference count(s) of this node and all - * nodes up to the root, Delete anything with zero remaining references. - */ - this_node = node; - while (this_node) { - - /* Prepare to move up to parent */ - - parent_node = acpi_ns_get_parent_node(this_node); - - /* Decrement the reference count on this node */ - - this_node->reference_count--; - - /* Delete the node if no more references */ - - if (!this_node->reference_count) { - - /* Delete all children and delete the node */ - - acpi_ns_delete_children(this_node); - acpi_ns_delete_node(this_node); - } - - this_node = parent_node; - } -} - /******************************************************************************* * * FUNCTION: acpi_ns_delete_namespace_by_owner @@ -482,9 +399,9 @@ void acpi_ns_delete_namespace_by_owner(acpi_owner_id owner_id) return_VOID; } + deletion_node = NULL; parent_node = acpi_gbl_root_node; child_node = NULL; - deletion_node = NULL; level = 1; /* @@ -501,7 +418,8 @@ void acpi_ns_delete_namespace_by_owner(acpi_owner_id owner_id) child_node); if (deletion_node) { - acpi_ns_remove_reference(deletion_node); + acpi_ns_delete_children(deletion_node); + acpi_ns_delete_node(deletion_node); deletion_node = NULL; } diff --git a/drivers/acpi/namespace/nsutils.c b/drivers/acpi/namespace/nsutils.c index 586014ecf24..9fa38ffc2e6 100644 --- a/drivers/acpi/namespace/nsutils.c +++ b/drivers/acpi/namespace/nsutils.c @@ -81,7 +81,7 @@ acpi_ns_report_error(char *module_name, u32 bad_name; char *name = NULL; - acpi_ut_report_error(module_name, line_number); + acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number); if (lookup_status == AE_BAD_CHARACTER) { @@ -139,7 +139,7 @@ acpi_ns_report_method_error(char *module_name, acpi_status status; struct acpi_namespace_node *node = prefix_node; - acpi_ut_report_error(module_name, line_number); + acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number); if (path) { status = acpi_ns_get_node_by_path(path, prefix_node, diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 56d97f1d108..006b31a5655 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -1126,14 +1126,13 @@ acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object) * * RETURN: Status * - * DESCRIPTION: Get an object from the specified cache. If cache is empty, - * the object is allocated. + * DESCRIPTION: Return a zero-filled object. * ******************************************************************************/ void *acpi_os_acquire_object(acpi_cache_t * cache) { - void *object = kmem_cache_alloc(cache, GFP_KERNEL); + void *object = kmem_cache_zalloc(cache, GFP_KERNEL); WARN_ON(!object); return object; } diff --git a/drivers/acpi/parser/psscope.c b/drivers/acpi/parser/psscope.c index edb7c9ba6ec..9233a4044d6 100644 --- a/drivers/acpi/parser/psscope.c +++ b/drivers/acpi/parser/psscope.c @@ -113,7 +113,7 @@ acpi_ps_init_scope(struct acpi_parse_state * parser_state, return_ACPI_STATUS(AE_NO_MEMORY); } - scope->common.data_type = ACPI_DESC_TYPE_STATE_RPSCOPE; + scope->common.descriptor_type = ACPI_DESC_TYPE_STATE_RPSCOPE; scope->parse_scope.op = root_op; scope->parse_scope.arg_count = ACPI_VAR_ARGS; scope->parse_scope.arg_end = parser_state->aml_end; @@ -143,7 +143,7 @@ acpi_ps_init_scope(struct acpi_parse_state * parser_state, acpi_status acpi_ps_push_scope(struct acpi_parse_state *parser_state, union acpi_parse_object *op, - u32 remaining_args, u32 arg_count) + u32 remaining_args, u8 arg_count) { union acpi_generic_state *scope; @@ -154,7 +154,7 @@ acpi_ps_push_scope(struct acpi_parse_state *parser_state, return_ACPI_STATUS(AE_NO_MEMORY); } - scope->common.data_type = ACPI_DESC_TYPE_STATE_PSCOPE; + scope->common.descriptor_type = ACPI_DESC_TYPE_STATE_PSCOPE; scope->parse_scope.op = op; scope->parse_scope.arg_list = remaining_args; scope->parse_scope.arg_count = arg_count; @@ -196,7 +196,7 @@ acpi_ps_push_scope(struct acpi_parse_state *parser_state, void acpi_ps_pop_scope(struct acpi_parse_state *parser_state, - union acpi_parse_object **op, u32 * arg_list, u32 * arg_count) + union acpi_parse_object **op, u32 * arg_list, u8 * arg_count) { union acpi_generic_state *scope = parser_state->scope; @@ -207,7 +207,7 @@ acpi_ps_pop_scope(struct acpi_parse_state *parser_state, if (scope->common.next) { scope = acpi_ut_pop_generic_state(&parser_state->scope); - /* return to parsing previous op */ + /* Return to parsing previous op */ *op = scope->parse_scope.op; *arg_list = scope->parse_scope.arg_list; @@ -218,7 +218,7 @@ acpi_ps_pop_scope(struct acpi_parse_state *parser_state, acpi_ut_delete_generic_state(scope); } else { - /* empty parse stack, prepare to fetch next opcode */ + /* Empty parse stack, prepare to fetch next opcode */ *op = NULL; *arg_list = 0; diff --git a/drivers/acpi/parser/psutils.c b/drivers/acpi/parser/psutils.c index a4c33a4bfe3..43e3190583e 100644 --- a/drivers/acpi/parser/psutils.c +++ b/drivers/acpi/parser/psutils.c @@ -89,7 +89,7 @@ void acpi_ps_init_op(union acpi_parse_object *op, u16 opcode) { ACPI_FUNCTION_ENTRY(); - op->common.data_type = ACPI_DESC_TYPE_PARSER; + op->common.descriptor_type = ACPI_DESC_TYPE_PARSER; op->common.aml_opcode = opcode; ACPI_DISASM_ONLY_MEMBERS(ACPI_STRNCPY(op->common.aml_op_name, diff --git a/drivers/acpi/resources/rscalc.c b/drivers/acpi/resources/rscalc.c index 8e406d992f3..dd5caa2c8fd 100644 --- a/drivers/acpi/resources/rscalc.c +++ b/drivers/acpi/resources/rscalc.c @@ -456,7 +456,7 @@ acpi_rs_get_list_length(u8 * aml_buffer, *size_needed += buffer_size; ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, - "Type %.2X, Aml %.2X internal %.2X\n", + "Type %.2X, aml_length %.2X internal_length %.2X\n", acpi_ut_get_resource_type(aml_buffer), acpi_ut_get_descriptor_length(aml_buffer), buffer_size)); diff --git a/drivers/acpi/resources/rscreate.c b/drivers/acpi/resources/rscreate.c index 67c052af7bb..01488cfc9ba 100644 --- a/drivers/acpi/resources/rscreate.c +++ b/drivers/acpi/resources/rscreate.c @@ -75,6 +75,7 @@ acpi_rs_create_resource_list(union acpi_operand_object *aml_buffer, u8 *aml_start; acpi_size list_size_needed = 0; u32 aml_buffer_length; + void *resource; ACPI_FUNCTION_TRACE("rs_create_resource_list"); @@ -107,8 +108,10 @@ acpi_rs_create_resource_list(union acpi_operand_object *aml_buffer, /* Do the conversion */ - status = acpi_rs_convert_aml_to_resources(aml_start, aml_buffer_length, - output_buffer->pointer); + resource = output_buffer->pointer; + status = acpi_ut_walk_aml_resources(aml_start, aml_buffer_length, + acpi_rs_convert_aml_to_resources, + &resource); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } diff --git a/drivers/acpi/resources/rslist.c b/drivers/acpi/resources/rslist.c index 6f2d8de3952..50bbb19bf4a 100644 --- a/drivers/acpi/resources/rslist.c +++ b/drivers/acpi/resources/rslist.c @@ -51,92 +51,60 @@ ACPI_MODULE_NAME("rslist") * * FUNCTION: acpi_rs_convert_aml_to_resources * - * PARAMETERS: Aml - Pointer to the resource byte stream - * aml_length - Length of Aml - * output_buffer - Pointer to the buffer that will - * contain the output structures + * PARAMETERS: acpi_walk_aml_callback + * resource_ptr - Pointer to the buffer that will + * contain the output structures * * RETURN: Status * - * DESCRIPTION: Takes the resource byte stream and parses it, creating a - * linked list of resources in the caller's output buffer + * DESCRIPTION: Convert an AML resource to an internal representation of the + * resource that is aligned and easier to access. * ******************************************************************************/ acpi_status -acpi_rs_convert_aml_to_resources(u8 * aml, u32 aml_length, u8 * output_buffer) +acpi_rs_convert_aml_to_resources(u8 * aml, + u32 length, + u32 offset, + u8 resource_index, void **resource_ptr) { - struct acpi_resource *resource = (void *)output_buffer; + struct acpi_resource *resource = *resource_ptr; acpi_status status; - u8 resource_index; - u8 *end_aml; ACPI_FUNCTION_TRACE("rs_convert_aml_to_resources"); - end_aml = aml + aml_length; - - /* Loop until end-of-buffer or an end_tag is found */ - - while (aml < end_aml) { - /* - * Check that the input buffer and all subsequent pointers into it - * are aligned on a native word boundary. Most important on IA64 - */ - if (ACPI_IS_MISALIGNED(resource)) { - ACPI_WARNING((AE_INFO, - "Misaligned resource pointer %p", - resource)); - } - - /* Validate the Resource Type and Resource Length */ - - status = acpi_ut_validate_resource(aml, &resource_index); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Convert the AML byte stream resource to a local resource struct */ - - status = - acpi_rs_convert_aml_to_resource(resource, - ACPI_CAST_PTR(union - aml_resource, - aml), - acpi_gbl_get_resource_dispatch - [resource_index]); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "Could not convert AML resource (Type %X)", - *aml)); - return_ACPI_STATUS(status); - } - - ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, - "Type %.2X, Aml %.2X internal %.2X\n", - acpi_ut_get_resource_type(aml), - acpi_ut_get_descriptor_length(aml), - resource->length)); - - /* Normal exit on completion of an end_tag resource descriptor */ - - if (acpi_ut_get_resource_type(aml) == - ACPI_RESOURCE_NAME_END_TAG) { - return_ACPI_STATUS(AE_OK); - } - - /* Point to the next input AML resource */ - - aml += acpi_ut_get_descriptor_length(aml); - - /* Point to the next structure in the output buffer */ + /* + * Check that the input buffer and all subsequent pointers into it + * are aligned on a native word boundary. Most important on IA64 + */ + if (ACPI_IS_MISALIGNED(resource)) { + ACPI_WARNING((AE_INFO, + "Misaligned resource pointer %p", resource)); + } - resource = - ACPI_ADD_PTR(struct acpi_resource, resource, - resource->length); + /* Convert the AML byte stream resource to a local resource struct */ + + status = + acpi_rs_convert_aml_to_resource(resource, + ACPI_CAST_PTR(union aml_resource, + aml), + acpi_gbl_get_resource_dispatch + [resource_index]); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "Could not convert AML resource (Type %X)", + *aml)); + return_ACPI_STATUS(status); } - /* Did not find an end_tag resource descriptor */ + ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, + "Type %.2X, aml_length %.2X internal_length %.2X\n", + acpi_ut_get_resource_type(aml), length, + resource->length)); - return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); + /* Point to the next structure in the output buffer */ + + *resource_ptr = ACPI_ADD_PTR(void, resource, resource->length); + return_ACPI_STATUS(AE_OK); } /******************************************************************************* diff --git a/drivers/acpi/resources/rsxface.c b/drivers/acpi/resources/rsxface.c index b3feebbd8ca..1d00d285a5a 100644 --- a/drivers/acpi/resources/rsxface.c +++ b/drivers/acpi/resources/rsxface.c @@ -242,7 +242,7 @@ ACPI_EXPORT_SYMBOL(acpi_get_possible_resources) acpi_status acpi_walk_resources(acpi_handle device_handle, char *name, - ACPI_WALK_RESOURCE_CALLBACK user_function, void *context) + acpi_walk_resource_callback user_function, void *context) { acpi_status status; struct acpi_buffer buffer; @@ -469,7 +469,7 @@ ACPI_EXPORT_SYMBOL(acpi_get_vendor_resource) * * FUNCTION: acpi_rs_match_vendor_resource * - * PARAMETERS: ACPI_WALK_RESOURCE_CALLBACK + * PARAMETERS: acpi_walk_resource_callback * * RETURN: Status * diff --git a/drivers/acpi/utilities/utalloc.c b/drivers/acpi/utilities/utalloc.c index 7b35eb84d05..3b29aecaaca 100644 --- a/drivers/acpi/utilities/utalloc.c +++ b/drivers/acpi/utilities/utalloc.c @@ -46,24 +46,6 @@ #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utalloc") -/* Local prototypes */ -#ifdef ACPI_DBG_TRACK_ALLOCATIONS -static struct acpi_debug_mem_block *acpi_ut_find_allocation(void *allocation); - -static acpi_status -acpi_ut_track_allocation(struct acpi_debug_mem_block *address, - acpi_size size, - u8 alloc_type, u32 component, char *module, u32 line); - -static acpi_status -acpi_ut_remove_allocation(struct acpi_debug_mem_block *address, - u32 component, char *module, u32 line); - -static acpi_status -acpi_ut_create_list(char *list_name, - u16 object_size, struct acpi_memory_list **return_cache); -#endif - /******************************************************************************* * * FUNCTION: acpi_ut_create_caches @@ -75,7 +57,6 @@ acpi_ut_create_list(char *list_name, * DESCRIPTION: Create all local caches * ******************************************************************************/ - acpi_status acpi_ut_create_caches(void) { acpi_status status; @@ -101,7 +82,16 @@ acpi_status acpi_ut_create_caches(void) /* Object Caches, for frequently used objects */ status = - acpi_os_create_cache("acpi_state", sizeof(union acpi_generic_state), + acpi_os_create_cache("Acpi-Namespace", + sizeof(struct acpi_namespace_node), + ACPI_MAX_NAMESPACE_CACHE_DEPTH, + &acpi_gbl_namespace_cache); + if (ACPI_FAILURE(status)) { + return (status); + } + + status = + acpi_os_create_cache("Acpi-State", sizeof(union acpi_generic_state), ACPI_MAX_STATE_CACHE_DEPTH, &acpi_gbl_state_cache); if (ACPI_FAILURE(status)) { @@ -109,7 +99,7 @@ acpi_status acpi_ut_create_caches(void) } status = - acpi_os_create_cache("acpi_parse", + acpi_os_create_cache("Acpi-Parse", sizeof(struct acpi_parse_obj_common), ACPI_MAX_PARSE_CACHE_DEPTH, &acpi_gbl_ps_node_cache); @@ -118,7 +108,7 @@ acpi_status acpi_ut_create_caches(void) } status = - acpi_os_create_cache("acpi_parse_ext", + acpi_os_create_cache("Acpi-parse_ext", sizeof(struct acpi_parse_obj_named), ACPI_MAX_EXTPARSE_CACHE_DEPTH, &acpi_gbl_ps_node_ext_cache); @@ -127,7 +117,7 @@ acpi_status acpi_ut_create_caches(void) } status = - acpi_os_create_cache("acpi_operand", + acpi_os_create_cache("Acpi-Operand", sizeof(union acpi_operand_object), ACPI_MAX_OBJECT_CACHE_DEPTH, &acpi_gbl_operand_cache); @@ -153,6 +143,9 @@ acpi_status acpi_ut_create_caches(void) acpi_status acpi_ut_delete_caches(void) { + (void)acpi_os_delete_cache(acpi_gbl_namespace_cache); + acpi_gbl_namespace_cache = NULL; + (void)acpi_os_delete_cache(acpi_gbl_state_cache); acpi_gbl_state_cache = NULL; @@ -288,7 +281,7 @@ acpi_ut_initialize_buffer(struct acpi_buffer * buffer, * * RETURN: Address of the allocated memory on success, NULL on failure. * - * DESCRIPTION: The subsystem's equivalent of malloc. + * DESCRIPTION: Subsystem equivalent of malloc. * ******************************************************************************/ @@ -301,8 +294,8 @@ void *acpi_ut_allocate(acpi_size size, u32 component, char *module, u32 line) /* Check for an inadvertent size of zero bytes */ if (!size) { - ACPI_ERROR((module, line, - "ut_allocate: Attempt to allocate zero bytes, allocating 1 byte")); + ACPI_WARNING((module, line, + "Attempt to allocate zero bytes, allocating 1 byte")); size = 1; } @@ -311,9 +304,8 @@ void *acpi_ut_allocate(acpi_size size, u32 component, char *module, u32 line) /* Report allocation error */ - ACPI_ERROR((module, line, - "ut_allocate: Could not allocate size %X", - (u32) size)); + ACPI_WARNING((module, line, + "Could not allocate size %X", (u32) size)); return_PTR(NULL); } @@ -323,7 +315,7 @@ void *acpi_ut_allocate(acpi_size size, u32 component, char *module, u32 line) /******************************************************************************* * - * FUNCTION: acpi_ut_callocate + * FUNCTION: acpi_ut_allocate_zeroed * * PARAMETERS: Size - Size of the allocation * Component - Component type of caller @@ -332,546 +324,24 @@ void *acpi_ut_allocate(acpi_size size, u32 component, char *module, u32 line) * * RETURN: Address of the allocated memory on success, NULL on failure. * - * DESCRIPTION: Subsystem equivalent of calloc. + * DESCRIPTION: Subsystem equivalent of calloc. Allocate and zero memory. * ******************************************************************************/ -void *acpi_ut_callocate(acpi_size size, u32 component, char *module, u32 line) +void *acpi_ut_allocate_zeroed(acpi_size size, + u32 component, char *module, u32 line) { void *allocation; - ACPI_FUNCTION_TRACE_U32("ut_callocate", size); - - /* Check for an inadvertent size of zero bytes */ - - if (!size) { - ACPI_ERROR((module, line, - "Attempt to allocate zero bytes, allocating 1 byte")); - size = 1; - } - - allocation = acpi_os_allocate(size); - if (!allocation) { - - /* Report allocation error */ - - ACPI_ERROR((module, line, - "Could not allocate size %X", (u32) size)); - return_PTR(NULL); - } - - /* Clear the memory block */ - - ACPI_MEMSET(allocation, 0, size); - return_PTR(allocation); -} - -#ifdef ACPI_DBG_TRACK_ALLOCATIONS -/* - * These procedures are used for tracking memory leaks in the subsystem, and - * they get compiled out when the ACPI_DBG_TRACK_ALLOCATIONS is not set. - * - * Each memory allocation is tracked via a doubly linked list. Each - * element contains the caller's component, module name, function name, and - * line number. acpi_ut_allocate and acpi_ut_callocate call - * acpi_ut_track_allocation to add an element to the list; deletion - * occurs in the body of acpi_ut_free. - */ - -/******************************************************************************* - * - * FUNCTION: acpi_ut_create_list - * - * PARAMETERS: cache_name - Ascii name for the cache - * object_size - Size of each cached object - * return_cache - Where the new cache object is returned - * - * RETURN: Status - * - * DESCRIPTION: Create a local memory list for tracking purposed - * - ******************************************************************************/ - -static acpi_status -acpi_ut_create_list(char *list_name, - u16 object_size, struct acpi_memory_list **return_cache) -{ - struct acpi_memory_list *cache; - - cache = acpi_os_allocate(sizeof(struct acpi_memory_list)); - if (!cache) { - return (AE_NO_MEMORY); - } - - ACPI_MEMSET(cache, 0, sizeof(struct acpi_memory_list)); - - cache->list_name = list_name; - cache->object_size = object_size; - - *return_cache = cache; - return (AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_allocate_and_track - * - * PARAMETERS: Size - Size of the allocation - * Component - Component type of caller - * Module - Source file name of caller - * Line - Line number of caller - * - * RETURN: Address of the allocated memory on success, NULL on failure. - * - * DESCRIPTION: The subsystem's equivalent of malloc. - * - ******************************************************************************/ - -void *acpi_ut_allocate_and_track(acpi_size size, - u32 component, char *module, u32 line) -{ - struct acpi_debug_mem_block *allocation; - acpi_status status; - - allocation = - acpi_ut_allocate(size + sizeof(struct acpi_debug_mem_header), - component, module, line); - if (!allocation) { - return (NULL); - } - - status = acpi_ut_track_allocation(allocation, size, - ACPI_MEM_MALLOC, component, module, - line); - if (ACPI_FAILURE(status)) { - acpi_os_free(allocation); - return (NULL); - } - - acpi_gbl_global_list->total_allocated++; - acpi_gbl_global_list->current_total_size += (u32) size; - - return ((void *)&allocation->user_space); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_callocate_and_track - * - * PARAMETERS: Size - Size of the allocation - * Component - Component type of caller - * Module - Source file name of caller - * Line - Line number of caller - * - * RETURN: Address of the allocated memory on success, NULL on failure. - * - * DESCRIPTION: Subsystem equivalent of calloc. - * - ******************************************************************************/ - -void *acpi_ut_callocate_and_track(acpi_size size, - u32 component, char *module, u32 line) -{ - struct acpi_debug_mem_block *allocation; - acpi_status status; - - allocation = - acpi_ut_callocate(size + sizeof(struct acpi_debug_mem_header), - component, module, line); - if (!allocation) { - - /* Report allocation error */ - - ACPI_ERROR((module, line, - "Could not allocate size %X", (u32) size)); - return (NULL); - } - - status = acpi_ut_track_allocation(allocation, size, - ACPI_MEM_CALLOC, component, module, - line); - if (ACPI_FAILURE(status)) { - acpi_os_free(allocation); - return (NULL); - } - - acpi_gbl_global_list->total_allocated++; - acpi_gbl_global_list->current_total_size += (u32) size; - - return ((void *)&allocation->user_space); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_free_and_track - * - * PARAMETERS: Allocation - Address of the memory to deallocate - * Component - Component type of caller - * Module - Source file name of caller - * Line - Line number of caller - * - * RETURN: None - * - * DESCRIPTION: Frees the memory at Allocation - * - ******************************************************************************/ - -void -acpi_ut_free_and_track(void *allocation, u32 component, char *module, u32 line) -{ - struct acpi_debug_mem_block *debug_block; - acpi_status status; - - ACPI_FUNCTION_TRACE_PTR("ut_free", allocation); - - if (NULL == allocation) { - ACPI_ERROR((module, line, "Attempt to delete a NULL address")); - - return_VOID; - } - - debug_block = ACPI_CAST_PTR(struct acpi_debug_mem_block, - (((char *)allocation) - - sizeof(struct acpi_debug_mem_header))); - - acpi_gbl_global_list->total_freed++; - acpi_gbl_global_list->current_total_size -= debug_block->size; - - status = acpi_ut_remove_allocation(debug_block, - component, module, line); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Could not free memory")); - } - - acpi_os_free(debug_block); - ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "%p freed\n", allocation)); - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_find_allocation - * - * PARAMETERS: Allocation - Address of allocated memory - * - * RETURN: A list element if found; NULL otherwise. - * - * DESCRIPTION: Searches for an element in the global allocation tracking list. - * - ******************************************************************************/ - -static struct acpi_debug_mem_block *acpi_ut_find_allocation(void *allocation) -{ - struct acpi_debug_mem_block *element; - ACPI_FUNCTION_ENTRY(); - element = acpi_gbl_global_list->list_head; - - /* Search for the address. */ - - while (element) { - if (element == allocation) { - return (element); - } - - element = element->next; - } - - return (NULL); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_track_allocation - * - * PARAMETERS: Allocation - Address of allocated memory - * Size - Size of the allocation - * alloc_type - MEM_MALLOC or MEM_CALLOC - * Component - Component type of caller - * Module - Source file name of caller - * Line - Line number of caller - * - * RETURN: None. - * - * DESCRIPTION: Inserts an element into the global allocation tracking list. - * - ******************************************************************************/ - -static acpi_status -acpi_ut_track_allocation(struct acpi_debug_mem_block *allocation, - acpi_size size, - u8 alloc_type, u32 component, char *module, u32 line) -{ - struct acpi_memory_list *mem_list; - struct acpi_debug_mem_block *element; - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE_PTR("ut_track_allocation", allocation); - - mem_list = acpi_gbl_global_list; - status = acpi_ut_acquire_mutex(ACPI_MTX_MEMORY); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* - * Search list for this address to make sure it is not already on the list. - * This will catch several kinds of problems. - */ - element = acpi_ut_find_allocation(allocation); - if (element) { - ACPI_ERROR((AE_INFO, - "ut_track_allocation: Allocation already present in list! (%p)", - allocation)); + allocation = acpi_ut_allocate(size, component, module, line); + if (allocation) { - ACPI_ERROR((AE_INFO, "Element %p Address %p", - element, allocation)); + /* Clear the memory block */ - goto unlock_and_exit; + ACPI_MEMSET(allocation, 0, size); } - /* Fill in the instance data. */ - - allocation->size = (u32) size; - allocation->alloc_type = alloc_type; - allocation->component = component; - allocation->line = line; - - ACPI_STRNCPY(allocation->module, module, ACPI_MAX_MODULE_NAME); - allocation->module[ACPI_MAX_MODULE_NAME - 1] = 0; - - /* Insert at list head */ - - if (mem_list->list_head) { - ((struct acpi_debug_mem_block *)(mem_list->list_head))-> - previous = allocation; - } - - allocation->next = mem_list->list_head; - allocation->previous = NULL; - - mem_list->list_head = allocation; - - unlock_and_exit: - status = acpi_ut_release_mutex(ACPI_MTX_MEMORY); - return_ACPI_STATUS(status); + return (allocation); } - -/******************************************************************************* - * - * FUNCTION: acpi_ut_remove_allocation - * - * PARAMETERS: Allocation - Address of allocated memory - * Component - Component type of caller - * Module - Source file name of caller - * Line - Line number of caller - * - * RETURN: - * - * DESCRIPTION: Deletes an element from the global allocation tracking list. - * - ******************************************************************************/ - -static acpi_status -acpi_ut_remove_allocation(struct acpi_debug_mem_block *allocation, - u32 component, char *module, u32 line) -{ - struct acpi_memory_list *mem_list; - acpi_status status; - - ACPI_FUNCTION_TRACE("ut_remove_allocation"); - - mem_list = acpi_gbl_global_list; - if (NULL == mem_list->list_head) { - - /* No allocations! */ - - ACPI_ERROR((module, line, - "Empty allocation list, nothing to free!")); - - return_ACPI_STATUS(AE_OK); - } - - status = acpi_ut_acquire_mutex(ACPI_MTX_MEMORY); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Unlink */ - - if (allocation->previous) { - (allocation->previous)->next = allocation->next; - } else { - mem_list->list_head = allocation->next; - } - - if (allocation->next) { - (allocation->next)->previous = allocation->previous; - } - - /* Mark the segment as deleted */ - - ACPI_MEMSET(&allocation->user_space, 0xEA, allocation->size); - - ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Freeing size 0%X\n", - allocation->size)); - - status = acpi_ut_release_mutex(ACPI_MTX_MEMORY); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_dump_allocation_info - * - * PARAMETERS: - * - * RETURN: None - * - * DESCRIPTION: Print some info about the outstanding allocations. - * - ******************************************************************************/ - -#ifdef ACPI_FUTURE_USAGE -void acpi_ut_dump_allocation_info(void) -{ -/* - struct acpi_memory_list *mem_list; -*/ - - ACPI_FUNCTION_TRACE("ut_dump_allocation_info"); - -/* - ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, - ("%30s: %4d (%3d Kb)\n", "Current allocations", - mem_list->current_count, - ROUND_UP_TO_1K (mem_list->current_size))); - - ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, - ("%30s: %4d (%3d Kb)\n", "Max concurrent allocations", - mem_list->max_concurrent_count, - ROUND_UP_TO_1K (mem_list->max_concurrent_size))); - - ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, - ("%30s: %4d (%3d Kb)\n", "Total (all) internal objects", - running_object_count, - ROUND_UP_TO_1K (running_object_size))); - - ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, - ("%30s: %4d (%3d Kb)\n", "Total (all) allocations", - running_alloc_count, - ROUND_UP_TO_1K (running_alloc_size))); - - ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, - ("%30s: %4d (%3d Kb)\n", "Current Nodes", - acpi_gbl_current_node_count, - ROUND_UP_TO_1K (acpi_gbl_current_node_size))); - - ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, - ("%30s: %4d (%3d Kb)\n", "Max Nodes", - acpi_gbl_max_concurrent_node_count, - ROUND_UP_TO_1K ((acpi_gbl_max_concurrent_node_count * - sizeof (struct acpi_namespace_node))))); -*/ - return_VOID; -} -#endif /* ACPI_FUTURE_USAGE */ - -/******************************************************************************* - * - * FUNCTION: acpi_ut_dump_allocations - * - * PARAMETERS: Component - Component(s) to dump info for. - * Module - Module to dump info for. NULL means all. - * - * RETURN: None - * - * DESCRIPTION: Print a list of all outstanding allocations. - * - ******************************************************************************/ - -void acpi_ut_dump_allocations(u32 component, char *module) -{ - struct acpi_debug_mem_block *element; - union acpi_descriptor *descriptor; - u32 num_outstanding = 0; - - ACPI_FUNCTION_TRACE("ut_dump_allocations"); - - /* - * Walk the allocation list. - */ - if (ACPI_FAILURE(acpi_ut_acquire_mutex(ACPI_MTX_MEMORY))) { - return; - } - - element = acpi_gbl_global_list->list_head; - while (element) { - if ((element->component & component) && - ((module == NULL) - || (0 == ACPI_STRCMP(module, element->module)))) { - - /* Ignore allocated objects that are in a cache */ - - descriptor = - ACPI_CAST_PTR(union acpi_descriptor, - &element->user_space); - if (descriptor->descriptor_id != ACPI_DESC_TYPE_CACHED) { - acpi_os_printf("%p Len %04X %9.9s-%d [%s] ", - descriptor, element->size, - element->module, element->line, - acpi_ut_get_descriptor_name - (descriptor)); - - /* Most of the elements will be Operand objects. */ - - switch (ACPI_GET_DESCRIPTOR_TYPE(descriptor)) { - case ACPI_DESC_TYPE_OPERAND: - acpi_os_printf("%12.12s R%hd", - acpi_ut_get_type_name - (descriptor->object. - common.type), - descriptor->object. - common.reference_count); - break; - - case ACPI_DESC_TYPE_PARSER: - acpi_os_printf("aml_opcode %04hX", - descriptor->op.asl. - aml_opcode); - break; - - case ACPI_DESC_TYPE_NAMED: - acpi_os_printf("%4.4s", - acpi_ut_get_node_name - (&descriptor->node)); - break; - - default: - break; - } - - acpi_os_printf("\n"); - num_outstanding++; - } - } - element = element->next; - } - - (void)acpi_ut_release_mutex(ACPI_MTX_MEMORY); - - /* Print summary */ - - if (!num_outstanding) { - ACPI_INFO((AE_INFO, "No outstanding allocations")); - } else { - ACPI_ERROR((AE_INFO, - "%d(%X) Outstanding allocations", - num_outstanding, num_outstanding)); - } - - return_VOID; -} - -#endif /* #ifdef ACPI_DBG_TRACK_ALLOCATIONS */ diff --git a/drivers/acpi/utilities/utcache.c b/drivers/acpi/utilities/utcache.c index 5d2f4b2802a..593b08ccd6b 100644 --- a/drivers/acpi/utilities/utcache.c +++ b/drivers/acpi/utilities/utcache.c @@ -272,9 +272,9 @@ void *acpi_os_acquire_object(struct acpi_memory_list *cache) cache->current_depth--; ACPI_MEM_TRACKING(cache->hits++); - ACPI_MEM_TRACKING(ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Object %p from %s cache\n", - object, cache->list_name))); + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Object %p from %s cache\n", object, + cache->list_name)); status = acpi_ut_release_mutex(ACPI_MTX_CACHES); if (ACPI_FAILURE(status)) { diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c index 9c6867fcf00..51356e8eb99 100644 --- a/drivers/acpi/utilities/utdelete.c +++ b/drivers/acpi/utilities/utdelete.c @@ -200,8 +200,7 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object) */ handler_desc = object->region.handler; if (handler_desc) { - if (handler_desc->address_space. - hflags & + if (handler_desc->address_space.handler_flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) { obj_pointer = second_desc->extra.region_context; diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c index 5bc8da7acc6..8a05bb5ef4f 100644 --- a/drivers/acpi/utilities/utglobal.c +++ b/drivers/acpi/utilities/utglobal.c @@ -191,12 +191,14 @@ const char *acpi_gbl_valid_osi_strings[ACPI_NUM_OSI_STRINGS] = { "Linux", "Windows 2000", "Windows 2001", - "Windows 2001.1", "Windows 2001 SP0", "Windows 2001 SP1", "Windows 2001 SP2", "Windows 2001 SP3", "Windows 2001 SP4", + "Windows 2001.1", + "Windows 2001.1 SP1", /* Added 03/2006 */ + "Windows 2006", /* Added 03/2006 */ /* Feature Group Strings */ @@ -633,7 +635,7 @@ char *acpi_ut_get_node_name(void *object) /* Descriptor must be a namespace node */ - if (node->descriptor != ACPI_DESC_TYPE_NAMED) { + if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) { return ("####"); } @@ -855,7 +857,7 @@ void acpi_ut_init_globals(void) acpi_gbl_root_node = NULL; acpi_gbl_root_node_struct.name.integer = ACPI_ROOT_NAME; - acpi_gbl_root_node_struct.descriptor = ACPI_DESC_TYPE_NAMED; + acpi_gbl_root_node_struct.descriptor_type = ACPI_DESC_TYPE_NAMED; acpi_gbl_root_node_struct.type = ACPI_TYPE_DEVICE; acpi_gbl_root_node_struct.child = NULL; acpi_gbl_root_node_struct.peer = NULL; diff --git a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c index 77268ba8629..017a87ebc40 100644 --- a/drivers/acpi/utilities/utmisc.c +++ b/drivers/acpi/utilities/utmisc.c @@ -881,36 +881,3 @@ acpi_ut_info(char *module_name, u32 line_number, char *format, ...) acpi_os_vprintf(format, args); acpi_os_printf(" [%X]\n", ACPI_CA_VERSION); } - -/******************************************************************************* - * - * FUNCTION: acpi_ut_report_error, Warning, Info - * - * PARAMETERS: module_name - Caller's module name (for error output) - * line_number - Caller's line number (for error output) - * - * RETURN: None - * - * DESCRIPTION: Print error message - * - * Note: Legacy only, should be removed when no longer used by drivers. - * - ******************************************************************************/ - -void acpi_ut_report_error(char *module_name, u32 line_number) -{ - - acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number); -} - -void acpi_ut_report_warning(char *module_name, u32 line_number) -{ - - acpi_os_printf("ACPI Warning (%s-%04d): ", module_name, line_number); -} - -void acpi_ut_report_info(char *module_name, u32 line_number) -{ - - acpi_os_printf("ACPI (%s-%04d): ", module_name, line_number); -} diff --git a/drivers/acpi/utilities/utresrc.c b/drivers/acpi/utilities/utresrc.c index 27158dd0f87..4c24e6d5400 100644 --- a/drivers/acpi/utilities/utresrc.c +++ b/drivers/acpi/utilities/utresrc.c @@ -238,6 +238,104 @@ static const u8 acpi_gbl_resource_types[] = { ACPI_FIXED_LENGTH }; +/******************************************************************************* + * + * FUNCTION: acpi_ut_walk_aml_resources + * + * PARAMETERS: Aml - Pointer to the raw AML resource template + * aml_length - Length of the entire template + * user_function - Called once for each descriptor found. If + * NULL, a pointer to the end_tag is returned + * Context - Passed to user_function + * + * RETURN: Status + * + * DESCRIPTION: Walk a raw AML resource list(buffer). User function called + * once for each resource found. + * + ******************************************************************************/ + +acpi_status +acpi_ut_walk_aml_resources(u8 * aml, + acpi_size aml_length, + acpi_walk_aml_callback user_function, void *context) +{ + acpi_status status; + u8 *end_aml; + u8 resource_index; + u32 length; + u32 offset = 0; + + ACPI_FUNCTION_TRACE("ut_walk_aml_resources"); + + /* The absolute minimum resource template is one end_tag descriptor */ + + if (aml_length < sizeof(struct aml_resource_end_tag)) { + return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); + } + + /* Point to the end of the resource template buffer */ + + end_aml = aml + aml_length; + + /* Walk the byte list, abort on any invalid descriptor type or length */ + + while (aml < end_aml) { + + /* Validate the Resource Type and Resource Length */ + + status = acpi_ut_validate_resource(aml, &resource_index); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Get the length of this descriptor */ + + length = acpi_ut_get_descriptor_length(aml); + + /* Invoke the user function */ + + if (user_function) { + status = + user_function(aml, length, offset, resource_index, + context); + if (ACPI_FAILURE(status)) { + return (status); + } + } + + /* An end_tag descriptor terminates this resource template */ + + if (acpi_ut_get_resource_type(aml) == + ACPI_RESOURCE_NAME_END_TAG) { + /* + * There must be at least one more byte in the buffer for + * the 2nd byte of the end_tag + */ + if ((aml + 1) >= end_aml) { + return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); + } + + /* Return the pointer to the end_tag if requested */ + + if (!user_function) { + *(void **)context = aml; + } + + /* Normal exit */ + + return_ACPI_STATUS(AE_OK); + } + + aml += length; + offset += length; + } + + /* Did not find an end_tag descriptor */ + + return (AE_AML_NO_RESOURCE_END_TAG); +} + /******************************************************************************* * * FUNCTION: acpi_ut_validate_resource @@ -498,61 +596,21 @@ acpi_ut_get_resource_end_tag(union acpi_operand_object * obj_desc, u8 ** end_tag) { acpi_status status; - u8 *aml; - u8 *end_aml; ACPI_FUNCTION_TRACE("ut_get_resource_end_tag"); - /* Get start and end pointers */ - - aml = obj_desc->buffer.pointer; - end_aml = aml + obj_desc->buffer.length; - /* Allow a buffer length of zero */ if (!obj_desc->buffer.length) { - *end_tag = aml; + *end_tag = obj_desc->buffer.pointer; return_ACPI_STATUS(AE_OK); } - /* Walk the resource template, one descriptor per iteration */ - - while (aml < end_aml) { - - /* Validate the Resource Type and Resource Length */ - - status = acpi_ut_validate_resource(aml, NULL); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* end_tag resource indicates the end of the resource template */ - - if (acpi_ut_get_resource_type(aml) == - ACPI_RESOURCE_NAME_END_TAG) { - /* - * There must be at least one more byte in the buffer for - * the 2nd byte of the end_tag - */ - if ((aml + 1) >= end_aml) { - return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); - } - - /* Return the pointer to the end_tag */ - - *end_tag = aml; - return_ACPI_STATUS(AE_OK); - } - - /* - * Point to the next resource descriptor in the AML buffer. The - * descriptor length is guaranteed to be non-zero by resource - * validation above. - */ - aml += acpi_ut_get_descriptor_length(aml); - } + /* Validate the template and get a pointer to the end_tag */ - /* Did not find an end_tag resource descriptor */ + status = acpi_ut_walk_aml_resources(obj_desc->buffer.pointer, + obj_desc->buffer.length, NULL, + end_tag); - return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); + return_ACPI_STATUS(status); } diff --git a/drivers/acpi/utilities/utstate.c b/drivers/acpi/utilities/utstate.c index 69f2bfdc26a..637c5f96487 100644 --- a/drivers/acpi/utilities/utstate.c +++ b/drivers/acpi/utilities/utstate.c @@ -162,7 +162,7 @@ union acpi_generic_state *acpi_ut_create_generic_state(void) /* Initialize */ memset(state, 0, sizeof(union acpi_generic_state)); - state->common.data_type = ACPI_DESC_TYPE_STATE; + state->common.descriptor_type = ACPI_DESC_TYPE_STATE; } return (state); @@ -196,7 +196,7 @@ struct acpi_thread_state *acpi_ut_create_thread_state(void) /* Init fields specific to the update struct */ - state->common.data_type = ACPI_DESC_TYPE_STATE_THREAD; + state->common.descriptor_type = ACPI_DESC_TYPE_STATE_THREAD; state->thread.thread_id = acpi_os_get_thread_id(); return_PTR((struct acpi_thread_state *)state); @@ -233,7 +233,7 @@ union acpi_generic_state *acpi_ut_create_update_state(union acpi_operand_object /* Init fields specific to the update struct */ - state->common.data_type = ACPI_DESC_TYPE_STATE_UPDATE; + state->common.descriptor_type = ACPI_DESC_TYPE_STATE_UPDATE; state->update.object = object; state->update.value = action; @@ -270,7 +270,7 @@ union acpi_generic_state *acpi_ut_create_pkg_state(void *internal_object, /* Init fields specific to the update struct */ - state->common.data_type = ACPI_DESC_TYPE_STATE_PACKAGE; + state->common.descriptor_type = ACPI_DESC_TYPE_STATE_PACKAGE; state->pkg.source_object = (union acpi_operand_object *)internal_object; state->pkg.dest_object = external_object; state->pkg.index = index; @@ -307,7 +307,7 @@ union acpi_generic_state *acpi_ut_create_control_state(void) /* Init fields specific to the control struct */ - state->common.data_type = ACPI_DESC_TYPE_STATE_CONTROL; + state->common.descriptor_type = ACPI_DESC_TYPE_STATE_CONTROL; state->common.state = ACPI_CONTROL_CONDITIONAL_EXECUTING; return_PTR(state); diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h index ebe793fc137..f3acfd9249f 100644 --- a/include/acpi/acconfig.h +++ b/include/acpi/acconfig.h @@ -63,7 +63,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20060310 +#define ACPI_CA_VERSION 0x20060317 /* * OS name, used for the _OS object. The _OS object is essentially obsolete, @@ -81,6 +81,7 @@ #define ACPI_MAX_PARSE_CACHE_DEPTH 96 /* Parse tree objects */ #define ACPI_MAX_EXTPARSE_CACHE_DEPTH 96 /* Parse tree objects */ #define ACPI_MAX_OBJECT_CACHE_DEPTH 96 /* Interpreter operand objects */ +#define ACPI_MAX_NAMESPACE_CACHE_DEPTH 96 /* Namespace objects */ /* * Should the subsystem abort the loading of an ACPI table if the @@ -189,7 +190,7 @@ /* Number of strings associated with the _OSI reserved method */ -#define ACPI_NUM_OSI_STRINGS 10 +#define ACPI_NUM_OSI_STRINGS 12 /****************************************************************************** * diff --git a/include/acpi/acevents.h b/include/acpi/acevents.h index f2717be4fe0..272bd0480ec 100644 --- a/include/acpi/acevents.h +++ b/include/acpi/acevents.h @@ -93,7 +93,7 @@ struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device, */ u8 acpi_ev_valid_gpe_event(struct acpi_gpe_event_info *gpe_event_info); -acpi_status acpi_ev_walk_gpe_list(ACPI_GPE_CALLBACK gpe_walk_callback); +acpi_status acpi_ev_walk_gpe_list(acpi_gpe_callback gpe_walk_callback); acpi_status acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info, diff --git a/include/acpi/acglobal.h b/include/acpi/acglobal.h index 734cc77bf2c..f9eb5925511 100644 --- a/include/acpi/acglobal.h +++ b/include/acpi/acglobal.h @@ -203,6 +203,7 @@ ACPI_EXTERN struct acpi_memory_list *acpi_gbl_ns_node_list; /* Object caches */ +ACPI_EXTERN acpi_cache_t *acpi_gbl_namespace_cache; ACPI_EXTERN acpi_cache_t *acpi_gbl_state_cache; ACPI_EXTERN acpi_cache_t *acpi_gbl_ps_node_cache; ACPI_EXTERN acpi_cache_t *acpi_gbl_ps_node_ext_cache; diff --git a/include/acpi/aclocal.h b/include/acpi/aclocal.h index 94fbf96ed3d..5956431784d 100644 --- a/include/acpi/aclocal.h +++ b/include/acpi/aclocal.h @@ -44,7 +44,10 @@ #ifndef __ACLOCAL_H__ #define __ACLOCAL_H__ +/* acpisrc:struct_defs -- for acpisrc conversion */ + #define ACPI_WAIT_FOREVER 0xFFFF /* u16, as per ACPI spec */ +#define ACPI_INFINITE_CONCURRENCY 0xFF typedef void *acpi_mutex; typedef u32 acpi_mutex_handle; @@ -144,6 +147,8 @@ struct acpi_mutex_info { #define ACPI_FIELD_DWORD_GRANULARITY 4 #define ACPI_FIELD_QWORD_GRANULARITY 8 +#define ACPI_ENTRY_NOT_FOUND NULL + /***************************************************************************** * * Namespace typedefs and structs @@ -158,49 +163,45 @@ typedef enum { ACPI_IMODE_EXECUTE = 0x0E } acpi_interpreter_mode; -/* - * The Node describes a named object that appears in the AML - * An acpi_node is used to store Nodes. - * - * data_type is used to differentiate between internal descriptors, and MUST - * be the first byte in this structure. - */ union acpi_name_union { u32 integer; char ascii[4]; }; +/* + * The Namespace Node describes a named object that appears in the AML. + * descriptor_type is used to differentiate between internal descriptors. + * + * The node is optimized for both 32-bit and 64-bit platforms: + * 20 bytes for the 32-bit case, 32 bytes for the 64-bit case. + */ struct acpi_namespace_node { - u8 descriptor; /* Used to differentiate object descriptor types */ - u8 type; /* Type associated with this name */ - u16 reference_count; /* Current count of references and children */ + union acpi_operand_object *object; /* Interpreter object */ + u8 descriptor_type; /* Differentiate object descriptor types */ + u8 flags; /* Miscellaneous flags */ + acpi_owner_id owner_id; /* Node creator */ + u8 type; /* ACPI Type associated with this name */ union acpi_name_union name; /* ACPI Name, always 4 chars per ACPI spec */ - union acpi_operand_object *object; /* Pointer to attached ACPI object (optional) */ struct acpi_namespace_node *child; /* First child */ - struct acpi_namespace_node *peer; /* Next peer */ - u8 owner_id; /* Who created this node */ - u8 flags; + struct acpi_namespace_node *peer; /* Peer. Parent if ANOBJ_END_OF_PEER_LIST set */ - /* Fields used by the ASL compiler and disassembler only */ + /* Fields used by the ASL compiler and disassembler only: */ #ifdef ACPI_LARGE_NAMESPACE_NODE - u32 value; union acpi_parse_object *op; + u32 value; #endif }; -#define ACPI_ENTRY_NOT_FOUND NULL - -/* Node flags */ +/* Namespace Node flags */ -#define ANOBJ_RESERVED 0x01 -#define ANOBJ_END_OF_PEER_LIST 0x02 -#define ANOBJ_DATA_WIDTH_32 0x04 /* Parent table is 64-bits */ -#define ANOBJ_METHOD_ARG 0x08 -#define ANOBJ_METHOD_LOCAL 0x10 -#define ANOBJ_METHOD_NO_RETVAL 0x20 -#define ANOBJ_METHOD_SOME_NO_RETVAL 0x40 -#define ANOBJ_IS_BIT_OFFSET 0x80 +#define ANOBJ_END_OF_PEER_LIST 0x01 /* End-of-list, Peer field points to parent */ +#define ANOBJ_DATA_WIDTH_32 0x02 /* Parent table uses 32-bit math */ +#define ANOBJ_METHOD_ARG 0x04 /* Node is a method argument */ +#define ANOBJ_METHOD_LOCAL 0x08 /* Node is a method local */ +#define ANOBJ_METHOD_NO_RETVal 0x10 /* i_aSL only: Method has no return value */ +#define ANOBJ_METHOD_SOME_NO_RETVal 0x20 /* i_aSL only: Method has at least one return value */ +#define ANOBJ_IS_BIT_OFFSet 0x40 /* i_aSL only: Reference is a bit offset */ /* * ACPI Table Descriptor. One per ACPI table @@ -212,8 +213,8 @@ struct acpi_table_desc { struct acpi_table_header *pointer; u8 *aml_start; u64 physical_address; - u32 aml_length; acpi_size length; + u32 aml_length; acpi_owner_id owner_id; u8 type; u8 allocation; @@ -276,6 +277,9 @@ struct acpi_create_field_info { u8 field_type; }; +typedef +acpi_status(*ACPI_INTERNAL_METHOD) (struct acpi_walk_state * walk_state); + /* * Bitmapped ACPI types. Used internally only */ @@ -377,7 +381,7 @@ struct acpi_gpe_walk_info { struct acpi_gpe_block_info *gpe_block; }; -typedef acpi_status(*ACPI_GPE_CALLBACK) (struct acpi_gpe_xrupt_info * +typedef acpi_status(*acpi_gpe_callback) (struct acpi_gpe_xrupt_info * gpe_xrupt_info, struct acpi_gpe_block_info * gpe_block); @@ -416,13 +420,14 @@ struct acpi_field_info { #define ACPI_CONTROL_PREDICATE_FALSE 0xC3 #define ACPI_CONTROL_PREDICATE_TRUE 0xC4 -#define ACPI_STATE_COMMON /* Two 32-bit fields and a pointer */\ - u8 data_type; /* To differentiate various internal objs */\ - u8 flags; \ - u16 value; \ - u16 state; \ - u16 reserved; \ - void *next; +#define ACPI_STATE_COMMON \ + void *next; \ + u8 descriptor_type; /* To differentiate various internal objs */\ + u8 flags; \ + u16 value; \ + u16 state; + + /* There are 2 bytes available here until the next natural alignment boundary */ struct acpi_common_state { ACPI_STATE_COMMON}; @@ -438,12 +443,12 @@ struct acpi_update_state { * Pkg state - used to traverse nested package structures */ struct acpi_pkg_state { - ACPI_STATE_COMMON union acpi_operand_object *source_object; + ACPI_STATE_COMMON u16 index; + union acpi_operand_object *source_object; union acpi_operand_object *dest_object; struct acpi_walk_state *walk_state; void *this_target_obj; u32 num_packages; - u16 index; }; /* @@ -451,10 +456,10 @@ struct acpi_pkg_state { * Allows nesting of these constructs */ struct acpi_control_state { - ACPI_STATE_COMMON union acpi_parse_object *predicate_op; + ACPI_STATE_COMMON u16 opcode; + union acpi_parse_object *predicate_op; u8 *aml_predicate_start; /* Start of if/while predicate */ u8 *package_end; /* End of if/while block */ - u16 opcode; }; /* @@ -465,11 +470,11 @@ struct acpi_scope_state { }; struct acpi_pscope_state { - ACPI_STATE_COMMON union acpi_parse_object *op; /* Current op being parsed */ + ACPI_STATE_COMMON u8 arg_count; /* Number of fixed arguments */ + union acpi_parse_object *op; /* Current op being parsed */ u8 *arg_end; /* Current argument end */ u8 *pkg_end; /* Current package end */ u32 arg_list; /* Next argument to parse */ - u32 arg_count; /* Number of fixed arguments */ }; /* @@ -477,10 +482,10 @@ struct acpi_pscope_state { * states are created when there are nested control methods executing. */ struct acpi_thread_state { - ACPI_STATE_COMMON struct acpi_walk_state *walk_state_list; /* Head of list of walk_states for this thread */ + ACPI_STATE_COMMON u8 current_sync_level; /* Mutex Sync (nested acquire) level */ + struct acpi_walk_state *walk_state_list; /* Head of list of walk_states for this thread */ union acpi_operand_object *acquired_mutex_list; /* List of all currently acquired mutexes */ acpi_thread_id thread_id; /* Running thread ID */ - u8 current_sync_level; /* Mutex Sync (nested acquire) level */ }; /* @@ -488,10 +493,9 @@ struct acpi_thread_state { * AML arguments */ struct acpi_result_values { - ACPI_STATE_COMMON - union acpi_operand_object *obj_desc[ACPI_OBJ_NUM_OPERANDS]; - u8 num_results; + ACPI_STATE_COMMON u8 num_results; u8 last_insert; + union acpi_operand_object *obj_desc[ACPI_OBJ_NUM_OPERANDS]; }; typedef @@ -546,7 +550,7 @@ struct acpi_opcode_info { #endif u32 parse_args; /* Grammar/Parse time arguments */ u32 runtime_args; /* Interpret time arguments */ - u32 flags; /* Misc flags */ + u16 flags; /* Misc flags */ u8 object_type; /* Corresponding internal object type */ u8 class; /* Opcode class */ u8 type; /* Opcode type */ @@ -563,29 +567,28 @@ union acpi_parse_value { }; #define ACPI_PARSE_COMMON \ - u8 data_type; /* To differentiate various internal objs */\ - u8 flags; /* Type of Op */\ - u16 aml_opcode; /* AML opcode */\ - u32 aml_offset; /* Offset of declaration in AML */\ - union acpi_parse_object *parent; /* Parent op */\ - union acpi_parse_object *next; /* Next op */\ + union acpi_parse_object *parent; /* Parent op */\ + u8 descriptor_type; /* To differentiate various internal objs */\ + u8 flags; /* Type of Op */\ + u16 aml_opcode; /* AML opcode */\ + u32 aml_offset; /* Offset of declaration in AML */\ + union acpi_parse_object *next; /* Next op */\ + struct acpi_namespace_node *node; /* For use by interpreter */\ + union acpi_parse_value value; /* Value or args associated with the opcode */\ ACPI_DISASM_ONLY_MEMBERS (\ - u8 disasm_flags; /* Used during AML disassembly */\ - u8 disasm_opcode; /* Subtype used for disassembly */\ - char aml_op_name[16]) /* Op name (debug only) */\ - /* NON-DEBUG members below: */\ - struct acpi_namespace_node *node; /* For use by interpreter */\ - union acpi_parse_value value; /* Value or args associated with the opcode */ - -#define ACPI_DASM_BUFFER 0x00 -#define ACPI_DASM_RESOURCE 0x01 -#define ACPI_DASM_STRING 0x02 -#define ACPI_DASM_UNICODE 0x03 -#define ACPI_DASM_EISAID 0x04 -#define ACPI_DASM_MATCHOP 0x05 + u8 disasm_flags; /* Used during AML disassembly */\ + u8 disasm_opcode; /* Subtype used for disassembly */\ + char aml_op_name[16]) /* Op name (debug only) */ + +#define ACPI_DASM_BUFFER 0x00 +#define ACPI_DASM_RESOURCE 0x01 +#define ACPI_DASM_STRING 0x02 +#define ACPI_DASM_UNICODE 0x03 +#define ACPI_DASM_EISAID 0x04 +#define ACPI_DASM_MATCHOP 0x05 /* - * generic operation (for example: If, While, Store) + * Generic operation (for example: If, While, Store) */ struct acpi_parse_obj_common { ACPI_PARSE_COMMON}; @@ -601,7 +604,7 @@ struct acpi_parse_obj_named { u32 name; /* 4-byte name or zero if no name */ }; -/* The parse node is the fundamental element of the parse tree */ +/* this version is used by the i_aSL compiler only */ #define ACPI_MAX_PARSEOP_NAME 20 @@ -643,7 +646,6 @@ union acpi_parse_object { * method. */ struct acpi_parse_state { - u32 aml_size; u8 *aml_start; /* First AML byte */ u8 *aml; /* Next AML byte */ u8 *aml_end; /* (last + 1) AML byte */ @@ -653,22 +655,23 @@ struct acpi_parse_state { struct acpi_namespace_node *start_node; union acpi_generic_state *scope; /* Current scope */ union acpi_parse_object *start_scope; + u32 aml_size; }; /* Parse object flags */ -#define ACPI_PARSEOP_GENERIC 0x01 -#define ACPI_PARSEOP_NAMED 0x02 -#define ACPI_PARSEOP_DEFERRED 0x04 -#define ACPI_PARSEOP_BYTELIST 0x08 -#define ACPI_PARSEOP_IN_CACHE 0x80 +#define ACPI_PARSEOP_GENERIC 0x01 +#define ACPI_PARSEOP_NAMED 0x02 +#define ACPI_PARSEOP_DEFERRED 0x04 +#define ACPI_PARSEOP_BYTELIST 0x08 +#define ACPI_PARSEOP_IN_CACHE 0x80 /* Parse object disasm_flags */ -#define ACPI_PARSEOP_IGNORE 0x01 -#define ACPI_PARSEOP_PARAMLIST 0x02 -#define ACPI_PARSEOP_EMPTY_TERMLIST 0x04 -#define ACPI_PARSEOP_SPECIAL 0x10 +#define ACPI_PARSEOP_IGNORE 0x01 +#define ACPI_PARSEOP_PARAMLIST 0x02 +#define ACPI_PARSEOP_EMPTY_TERMLIST 0x04 +#define ACPI_PARSEOP_SPECIAL 0x10 /***************************************************************************** * @@ -676,8 +679,8 @@ struct acpi_parse_state { * ****************************************************************************/ -#define PCI_ROOT_HID_STRING "PNP0A03" -#define PCI_EXPRESS_ROOT_HID_STRING "PNP0A08" +#define PCI_ROOT_HID_STRING "PNP0A03" +#define PCI_EXPRESS_ROOT_HID_STRING "PNP0A08" struct acpi_bit_register_info { u8 parent_register; @@ -710,13 +713,14 @@ struct acpi_bit_register_info { #define ACPI_BITMASK_PCIEXP_WAKE_STATUS 0x4000 /* ACPI 3.0 */ #define ACPI_BITMASK_WAKE_STATUS 0x8000 -#define ACPI_BITMASK_ALL_FIXED_STATUS (ACPI_BITMASK_TIMER_STATUS | \ - ACPI_BITMASK_BUS_MASTER_STATUS | \ - ACPI_BITMASK_GLOBAL_LOCK_STATUS | \ - ACPI_BITMASK_POWER_BUTTON_STATUS | \ - ACPI_BITMASK_SLEEP_BUTTON_STATUS | \ - ACPI_BITMASK_RT_CLOCK_STATUS | \ - ACPI_BITMASK_WAKE_STATUS) +#define ACPI_BITMASK_ALL_FIXED_STATUS (\ + ACPI_BITMASK_TIMER_STATUS | \ + ACPI_BITMASK_BUS_MASTER_STATUS | \ + ACPI_BITMASK_GLOBAL_LOCK_STATUS | \ + ACPI_BITMASK_POWER_BUTTON_STATUS | \ + ACPI_BITMASK_SLEEP_BUTTON_STATUS | \ + ACPI_BITMASK_RT_CLOCK_STATUS | \ + ACPI_BITMASK_WAKE_STATUS) #define ACPI_BITMASK_TIMER_ENABLE 0x0001 #define ACPI_BITMASK_GLOBAL_LOCK_ENABLE 0x0020 @@ -820,7 +824,7 @@ struct acpi_bit_register_info { * ****************************************************************************/ -#define ACPI_ASCII_ZERO 0x30 +#define ACPI_ASCII_ZERO 0x30 /***************************************************************************** * @@ -842,9 +846,9 @@ struct acpi_integrity_info { u32 objects; }; -#define ACPI_DB_REDIRECTABLE_OUTPUT 0x01 -#define ACPI_DB_CONSOLE_OUTPUT 0x02 -#define ACPI_DB_DUPLICATE_OUTPUT 0x03 +#define ACPI_DB_REDIRECTABLE_OUTPUT 0x01 +#define ACPI_DB_CONSOLE_OUTPUT 0x02 +#define ACPI_DB_DUPLICATE_OUTPUT 0x03 /***************************************************************************** * @@ -854,18 +858,18 @@ struct acpi_integrity_info { /* Entry for a memory allocation (debug only) */ -#define ACPI_MEM_MALLOC 0 -#define ACPI_MEM_CALLOC 1 -#define ACPI_MAX_MODULE_NAME 16 +#define ACPI_MEM_MALLOC 0 +#define ACPI_MEM_CALLOC 1 +#define ACPI_MAX_MODULE_NAME 16 #define ACPI_COMMON_DEBUG_MEM_HEADER \ - struct acpi_debug_mem_block *previous; \ - struct acpi_debug_mem_block *next; \ - u32 size; \ - u32 component; \ - u32 line; \ - char module[ACPI_MAX_MODULE_NAME]; \ - u8 alloc_type; + struct acpi_debug_mem_block *previous; \ + struct acpi_debug_mem_block *next; \ + u32 size; \ + u32 component; \ + u32 line; \ + char module[ACPI_MAX_MODULE_NAME]; \ + u8 alloc_type; struct acpi_debug_mem_header { ACPI_COMMON_DEBUG_MEM_HEADER}; diff --git a/include/acpi/acmacros.h b/include/acpi/acmacros.h index c8aa73fc6dd..c495670aa11 100644 --- a/include/acpi/acmacros.h +++ b/include/acpi/acmacros.h @@ -400,8 +400,8 @@ * * The "Descriptor" field is the first field in both structures. */ -#define ACPI_GET_DESCRIPTOR_TYPE(d) (((union acpi_descriptor *)(void *)(d))->descriptor_id) -#define ACPI_SET_DESCRIPTOR_TYPE(d,t) (((union acpi_descriptor *)(void *)(d))->descriptor_id = t) +#define ACPI_GET_DESCRIPTOR_TYPE(d) (((union acpi_descriptor *)(void *)(d))->common.descriptor_type) +#define ACPI_SET_DESCRIPTOR_TYPE(d,t) (((union acpi_descriptor *)(void *)(d))->common.descriptor_type = t) /* Macro to test the object type */ @@ -490,7 +490,6 @@ #define ACPI_ERROR(plist) #define ACPI_ERROR_NAMESPACE(s,e) #define ACPI_ERROR_METHOD(s,n,p,e) - #endif /* @@ -532,13 +531,13 @@ #endif #define ACPI_FUNCTION_TRACE(a) ACPI_FUNCTION_NAME(a) \ - acpi_ut_trace(ACPI_DEBUG_PARAMETERS) + acpi_ut_trace(ACPI_DEBUG_PARAMETERS) #define ACPI_FUNCTION_TRACE_PTR(a,b) ACPI_FUNCTION_NAME(a) \ - acpi_ut_trace_ptr(ACPI_DEBUG_PARAMETERS,(void *)b) + acpi_ut_trace_ptr(ACPI_DEBUG_PARAMETERS,(void *)b) #define ACPI_FUNCTION_TRACE_U32(a,b) ACPI_FUNCTION_NAME(a) \ - acpi_ut_trace_u32(ACPI_DEBUG_PARAMETERS,(u32)b) + acpi_ut_trace_u32(ACPI_DEBUG_PARAMETERS,(u32)b) #define ACPI_FUNCTION_TRACE_STR(a,b) ACPI_FUNCTION_NAME(a) \ - acpi_ut_trace_str(ACPI_DEBUG_PARAMETERS,(char *)b) + acpi_ut_trace_str(ACPI_DEBUG_PARAMETERS,(char *)b) #define ACPI_FUNCTION_ENTRY() acpi_ut_track_stack_ptr() @@ -658,6 +657,7 @@ #define ACPI_DUMP_STACK_ENTRY(a) #define ACPI_DUMP_OPERANDS(a,b,c,d,e) #define ACPI_DUMP_ENTRY(a,b) +#define ACPI_DUMP_TABLES(a,b) #define ACPI_DUMP_PATHNAME(a,b,c,d) #define ACPI_DUMP_RESOURCE_LIST(a) #define ACPI_DUMP_BUFFER(a,b) @@ -714,7 +714,7 @@ /* Memory allocation */ #define ACPI_ALLOCATE(a) acpi_ut_allocate((acpi_size)(a),_COMPONENT,_acpi_module_name,__LINE__) -#define ACPI_ALLOCATE_ZEROED(a) acpi_ut_callocate((acpi_size)(a), _COMPONENT,_acpi_module_name,__LINE__) +#define ACPI_ALLOCATE_ZEROED(a) acpi_ut_allocate_zeroed((acpi_size)(a), _COMPONENT,_acpi_module_name,__LINE__) #define ACPI_FREE(a) acpi_os_free(a) #define ACPI_MEM_TRACKING(a) @@ -723,9 +723,9 @@ /* Memory allocation */ #define ACPI_ALLOCATE(a) acpi_ut_allocate_and_track((acpi_size)(a),_COMPONENT,_acpi_module_name,__LINE__) -#define ACPI_ALLOCATE_ZEROED(a) acpi_ut_callocate_and_track((acpi_size)(a), _COMPONENT,_acpi_module_name,__LINE__) +#define ACPI_ALLOCATE_ZEROED(a) acpi_ut_allocate_zeroed_and_track((acpi_size)(a), _COMPONENT,_acpi_module_name,__LINE__) #define ACPI_FREE(a) acpi_ut_free_and_track(a,_COMPONENT,_acpi_module_name,__LINE__) -#define ACPI_MEM_TRACKING(a) a +#define ACPI_MEM_TRACKING(a) a #endif /* ACPI_DBG_TRACK_ALLOCATIONS */ diff --git a/include/acpi/acobject.h b/include/acpi/acobject.h index d130cfed8d5..28241aa15de 100644 --- a/include/acpi/acobject.h +++ b/include/acpi/acobject.h @@ -1,7 +1,7 @@ /****************************************************************************** * - * Name: acobject.h - Definition of union acpi_operand_object (Internal object only) + * Name: acobject.h - Definition of union acpi_operand_object (Internal object only) * *****************************************************************************/ @@ -45,10 +45,12 @@ #ifndef _ACOBJECT_H #define _ACOBJECT_H +/* acpisrc:struct_defs -- for acpisrc conversion */ + /* - * The union acpi_operand_object is used to pass AML operands from the dispatcher + * The union acpi_operand_object is used to pass AML operands from the dispatcher * to the interpreter, and to keep track of the various handlers such as - * address space handlers and notify handlers. The object is a constant + * address space handlers and notify handlers. The object is a constant * size in order to allow it to be cached and reused. */ @@ -61,17 +63,21 @@ /* * Common area for all objects. * - * data_type is used to differentiate between internal descriptors, and MUST - * be the first byte in this structure. + * descriptor_type is used to differentiate between internal descriptors, and + * must be in the same place across all descriptors */ -#define ACPI_OBJECT_COMMON_HEADER /* SIZE/ALIGNMENT: 32 bits, one ptr plus trailing 8-bit flag */\ - u8 descriptor; /* To differentiate various internal objs */\ - u8 type; /* acpi_object_type */\ - u16 reference_count; /* For object deletion management */\ - union acpi_operand_object *next_object; /* Objects linked to parent NS node */\ - u8 flags; - -/* Values for flag byte above */ +#define ACPI_OBJECT_COMMON_HEADER \ + union acpi_operand_object *next_object; /* Objects linked to parent NS node */\ + u8 descriptor_type; /* To differentiate various internal objs */\ + u8 type; /* acpi_object_type */\ + u16 reference_count; /* For object deletion management */\ + u8 flags; + /* + * Note: There are 3 bytes available here before the + * next natural alignment boundary (for both 32/64 cases) + */ + +/* Values for Flag byte above */ #define AOPOBJ_AML_CONSTANT 0x01 #define AOPOBJ_STATIC_POINTER 0x02 @@ -80,36 +86,6 @@ #define AOPOBJ_SETUP_COMPLETE 0x10 #define AOPOBJ_SINGLE_DATUM 0x20 -/* - * Common bitfield for the field objects - * "Field Datum" -- a datum from the actual field object - * "Buffer Datum" -- a datum from a user buffer, read from or to be written to the field - */ -#define ACPI_COMMON_FIELD_INFO /* SIZE/ALIGNMENT: 24 bits + three 32-bit values */\ - u8 field_flags; /* Access, update, and lock bits */\ - u8 attribute; /* From access_as keyword */\ - u8 access_byte_width; /* Read/Write size in bytes */\ - u32 bit_length; /* Length of field in bits */\ - u32 base_byte_offset; /* Byte offset within containing object */\ - u8 start_field_bit_offset;/* Bit offset within first field datum (0-63) */\ - u8 access_bit_width; /* Read/Write size in bits (8-64) */\ - u32 value; /* Value to store into the Bank or Index register */\ - struct acpi_namespace_node *node; /* Link back to parent node */ - -/* - * Fields common to both Strings and Buffers - */ -#define ACPI_COMMON_BUFFER_INFO \ - u32 length; - -/* - * Common fields for objects that support ASL notifications - */ -#define ACPI_COMMON_NOTIFY_INFO \ - union acpi_operand_object *system_notify; /* Handler for system notifies */\ - union acpi_operand_object *device_notify; /* Handler for driver notifies */\ - union acpi_operand_object *handler; /* Handler for Address space */ - /****************************************************************************** * * Basic data types @@ -125,25 +101,31 @@ struct acpi_object_integer { /* * Note: The String and Buffer object must be identical through the Pointer - * element. There is code that depends on this. + * and length elements. There is code that depends on this. + * + * Fields common to both Strings and Buffers */ +#define ACPI_COMMON_BUFFER_INFO(_type) \ + _type *pointer; \ + u32 length; + struct acpi_object_string { /* Null terminated, ASCII characters only */ - ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_BUFFER_INFO char *pointer; /* String in AML stream or allocated string */ + ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_BUFFER_INFO(char) /* String in AML stream or allocated string */ }; struct acpi_object_buffer { - ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_BUFFER_INFO u8 * pointer; /* Buffer in AML stream or allocated buffer */ - struct acpi_namespace_node *node; /* Link back to parent node */ - u8 *aml_start; + ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_BUFFER_INFO(u8) /* Buffer in AML stream or allocated buffer */ u32 aml_length; + u8 *aml_start; + struct acpi_namespace_node *node; /* Link back to parent node */ }; struct acpi_object_package { - ACPI_OBJECT_COMMON_HEADER u32 count; /* # of elements in package */ - u32 aml_length; - u8 *aml_start; - struct acpi_namespace_node *node; /* Link back to parent node */ + ACPI_OBJECT_COMMON_HEADER struct acpi_namespace_node *node; /* Link back to parent node */ union acpi_operand_object **elements; /* Array of pointers to acpi_objects */ + u8 *aml_start; + u32 aml_length; + u32 count; /* # of elements in package */ }; /****************************************************************************** @@ -156,23 +138,6 @@ struct acpi_object_event { ACPI_OBJECT_COMMON_HEADER void *semaphore; }; -#define ACPI_INFINITE_CONCURRENCY 0xFF - -typedef -acpi_status(*ACPI_INTERNAL_METHOD) (struct acpi_walk_state * walk_state); - -struct acpi_object_method { - ACPI_OBJECT_COMMON_HEADER u8 method_flags; - u8 param_count; - u32 aml_length; - void *semaphore; - u8 *aml_start; - ACPI_INTERNAL_METHOD implementation; - u8 concurrency; - u8 thread_count; - acpi_owner_id owner_id; -}; - struct acpi_object_mutex { ACPI_OBJECT_COMMON_HEADER u8 sync_level; /* 0-15, specified in Mutex() call */ u16 acquisition_depth; /* Allow multiple Acquires, same thread */ @@ -186,11 +151,23 @@ struct acpi_object_mutex { struct acpi_object_region { ACPI_OBJECT_COMMON_HEADER u8 space_id; - union acpi_operand_object *handler; /* Handler for region access */ struct acpi_namespace_node *node; /* Containing namespace node */ + union acpi_operand_object *handler; /* Handler for region access */ union acpi_operand_object *next; - u32 length; acpi_physical_address address; + u32 length; +}; + +struct acpi_object_method { + ACPI_OBJECT_COMMON_HEADER u8 method_flags; + u8 param_count; + u8 concurrency; + void *semaphore; + u8 *aml_start; + ACPI_INTERNAL_METHOD implementation; + u32 aml_length; + u8 thread_count; + acpi_owner_id owner_id; }; /****************************************************************************** @@ -199,6 +176,14 @@ struct acpi_object_region { * *****************************************************************************/ +/* + * Common fields for objects that support ASL notifications + */ +#define ACPI_COMMON_NOTIFY_INFO \ + union acpi_operand_object *system_notify; /* Handler for system notifies */\ + union acpi_operand_object *device_notify; /* Handler for driver notifies */\ + union acpi_operand_object *handler; /* Handler for Address space */ + struct acpi_object_notify_common { /* COMMON NOTIFY for POWER, PROCESSOR, DEVICE, and THERMAL */ ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_NOTIFY_INFO}; @@ -213,9 +198,9 @@ struct acpi_object_power_resource { }; struct acpi_object_processor { - ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_NOTIFY_INFO u32 proc_id; - u32 length; - acpi_io_address address; + ACPI_OBJECT_COMMON_HEADER u8 proc_id; + u8 length; + ACPI_COMMON_NOTIFY_INFO acpi_io_address address; }; struct acpi_object_thermal_zone { @@ -227,9 +212,24 @@ ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_NOTIFY_INFO}; * *****************************************************************************/ +/* + * Common bitfield for the field objects + * "Field Datum" -- a datum from the actual field object + * "Buffer Datum" -- a datum from a user buffer, read from or to be written to the field + */ +#define ACPI_COMMON_FIELD_INFO \ + u8 field_flags; /* Access, update, and lock bits */\ + u8 attribute; /* From access_as keyword */\ + u8 access_byte_width; /* Read/Write size in bytes */\ + struct acpi_namespace_node *node; /* Link back to parent node */\ + u32 bit_length; /* Length of field in bits */\ + u32 base_byte_offset; /* Byte offset within containing object */\ + u32 value; /* Value to store into the Bank or Index register */\ + u8 start_field_bit_offset;/* Bit offset within first field datum (0-63) */\ + u8 access_bit_width; /* Read/Write size in bits (8-64) */ + struct acpi_object_field_common { /* COMMON FIELD (for BUFFER, REGION, BANK, and INDEX fields) */ - ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO union acpi_operand_object *region_obj; /* Containing Operation Region object */ - /* (REGION/BANK fields only) */ + ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO union acpi_operand_object *region_obj; /* Parent Operation Region object (REGION/BANK fields only) */ }; struct acpi_object_region_field { @@ -269,13 +269,9 @@ struct acpi_object_notify_handler { void *context; }; -/* Flags for address handler */ - -#define ACPI_ADDR_HANDLER_DEFAULT_INSTALLED 0x1 - struct acpi_object_addr_handler { ACPI_OBJECT_COMMON_HEADER u8 space_id; - u16 hflags; + u8 handler_flags; acpi_adr_space_handler handler; struct acpi_namespace_node *node; /* Parent device */ void *context; @@ -284,6 +280,10 @@ struct acpi_object_addr_handler { union acpi_operand_object *next; }; +/* Flags for address handler (handler_flags) */ + +#define ACPI_ADDR_HANDLER_DEFAULT_INSTALLED 0x01 + /****************************************************************************** * * Special internal objects @@ -297,10 +297,10 @@ struct acpi_object_addr_handler { struct acpi_object_reference { ACPI_OBJECT_COMMON_HEADER u8 target_type; /* Used for index_op */ u16 opcode; - u32 offset; /* Used for arg_op, local_op, and index_op */ - void *object; /* name_op=>HANDLE to obj, index_op=>union acpi_operand_object */ + void *object; /* name_op=>HANDLE to obj, index_op=>union acpi_operand_object */ struct acpi_namespace_node *node; union acpi_operand_object **where; + u32 offset; /* Used for arg_op, local_op, and index_op */ }; /* @@ -311,12 +311,10 @@ struct acpi_object_reference { * Currently: Region and field_unit types */ struct acpi_object_extra { - ACPI_OBJECT_COMMON_HEADER u8 byte_fill1; - u16 word_fill1; - u32 aml_length; - u8 *aml_start; - struct acpi_namespace_node *method_REG; /* _REG method for this region (if any) */ + ACPI_OBJECT_COMMON_HEADER struct acpi_namespace_node *method_REG; /* _REG method for this region (if any) */ void *region_context; /* Region-specific data */ + u8 *aml_start; + u32 aml_length; }; /* Additional data that can be attached to namespace nodes */ @@ -391,8 +389,13 @@ union acpi_operand_object { #define ACPI_DESC_TYPE_NAMED 0x0F #define ACPI_DESC_TYPE_MAX 0x0F +struct acpi_common_descriptor { + void *common_pointer; + u8 descriptor_type; /* To differentiate various internal objs */ +}; + union acpi_descriptor { - u8 descriptor_id; /* To differentiate various internal objs */ + struct acpi_common_descriptor common; union acpi_operand_object object; struct acpi_namespace_node node; union acpi_parse_object op; diff --git a/include/acpi/acoutput.h b/include/acpi/acoutput.h index 7785d481dc3..621fe23bb4f 100644 --- a/include/acpi/acoutput.h +++ b/include/acpi/acoutput.h @@ -144,7 +144,7 @@ /* * These two levels are essentially obsolete, all instances in the - * ACPICA core code have been replaced by REPORT_ERROR and REPORT_WARNING + * ACPICA core code have been replaced by ACPI_ERROR and ACPI_WARNING * (Kept here because some drivers may still use them) */ #define ACPI_DB_ERROR ACPI_DEBUG_LEVEL (ACPI_LV_ERROR) diff --git a/include/acpi/acparser.h b/include/acpi/acparser.h index 5a1ff484af3..53ac4ce8753 100644 --- a/include/acpi/acparser.h +++ b/include/acpi/acparser.h @@ -48,7 +48,7 @@ /* variable # arguments */ -#define ACPI_VAR_ARGS ACPI_UINT32_MAX +#define ACPI_VAR_ARGS ACPI_UINT8_MAX #define ACPI_PARSE_DELETE_TREE 0x0001 #define ACPI_PARSE_NO_TREE_DELETE 0x0000 @@ -146,13 +146,12 @@ u8 acpi_ps_has_completed_scope(struct acpi_parse_state *parser_state); void acpi_ps_pop_scope(struct acpi_parse_state *parser_state, - union acpi_parse_object **op, - u32 * arg_list, u32 * arg_count); + union acpi_parse_object **op, u32 * arg_list, u8 * arg_count); acpi_status acpi_ps_push_scope(struct acpi_parse_state *parser_state, union acpi_parse_object *op, - u32 remaining_args, u32 arg_count); + u32 remaining_args, u8 arg_count); void acpi_ps_cleanup_scope(struct acpi_parse_state *state); diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 66cf2ecef57..049e9aa1b86 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -268,7 +268,7 @@ acpi_status acpi_remove_gpe_block(acpi_handle gpe_device); * Resource interfaces */ typedef -acpi_status(*ACPI_WALK_RESOURCE_CALLBACK) (struct acpi_resource * resource, +acpi_status(*acpi_walk_resource_callback) (struct acpi_resource * resource, void *context); acpi_status @@ -290,7 +290,7 @@ acpi_get_possible_resources(acpi_handle device_handle, acpi_status acpi_walk_resources(acpi_handle device_handle, char *name, - ACPI_WALK_RESOURCE_CALLBACK user_function, void *context); + acpi_walk_resource_callback user_function, void *context); acpi_status acpi_set_current_resources(acpi_handle device_handle, diff --git a/include/acpi/acresrc.h b/include/acpi/acresrc.h index fa02e808338..bdd6584bbcf 100644 --- a/include/acpi/acresrc.h +++ b/include/acpi/acresrc.h @@ -198,8 +198,9 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object, acpi_size * buffer_size_needed); acpi_status -acpi_rs_convert_aml_to_resources(u8 * aml_buffer, - u32 aml_buffer_length, u8 * output_buffer); +acpi_rs_convert_aml_to_resources(u8 * aml, + u32 length, + u32 offset, u8 resource_index, void **context); acpi_status acpi_rs_convert_resources_to_aml(struct acpi_resource *resource, diff --git a/include/acpi/acstruct.h b/include/acpi/acstruct.h index d8c1c2cdac0..04e8966a377 100644 --- a/include/acpi/acstruct.h +++ b/include/acpi/acstruct.h @@ -44,6 +44,8 @@ #ifndef __ACSTRUCT_H__ #define __ACSTRUCT_H__ +/* acpisrc:struct_defs -- for acpisrc conversion */ + /***************************************************************************** * * Tree walking typedefs and structs @@ -64,54 +66,55 @@ #define ACPI_WALK_CONST_OPTIONAL 4 struct acpi_walk_state { - u8 data_type; /* To differentiate various internal objs MUST BE FIRST! */ + struct acpi_walk_state *next; /* Next walk_state in list */ + u8 descriptor_type; /* To differentiate various internal objs */ u8 walk_type; - acpi_owner_id owner_id; /* Owner of objects created during the walk */ - u8 last_predicate; /* Result of last predicate */ - u8 current_result; /* */ + u16 opcode; /* Current AML opcode */ u8 next_op_info; /* Info about next_op */ u8 num_operands; /* Stack pointer for Operands[] array */ + acpi_owner_id owner_id; /* Owner of objects created during the walk */ + u8 last_predicate; /* Result of last predicate */ + u8 current_result; u8 return_used; - u16 opcode; /* Current AML opcode */ u8 scope_depth; u8 pass_number; /* Parse pass during table load */ - u32 arg_count; /* push for fixed or var args */ u32 aml_offset; u32 arg_types; u32 method_breakpoint; /* For single stepping */ u32 user_breakpoint; /* User AML breakpoint */ u32 parse_flags; + + struct acpi_parse_state parser_state; /* Current state of parser */ u32 prev_arg_types; + u8 arg_count; /* push for fixed or var args */ - u8 *aml_last_while; struct acpi_namespace_node arguments[ACPI_METHOD_NUM_ARGS]; /* Control method arguments */ + struct acpi_namespace_node local_variables[ACPI_METHOD_NUM_LOCALS]; /* Control method locals */ + union acpi_operand_object *operands[ACPI_OBJ_NUM_OPERANDS + 1]; /* Operands passed to the interpreter (+1 for NULL terminator) */ + union acpi_operand_object **params; + + u8 *aml_last_while; union acpi_operand_object **caller_return_desc; union acpi_generic_state *control_state; /* List of control states (nested IFs) */ struct acpi_namespace_node *deferred_node; /* Used when executing deferred opcodes */ struct acpi_gpe_event_info *gpe_event_info; /* Info for GPE (_Lxx/_Exx methods only */ union acpi_operand_object *implicit_return_obj; - struct acpi_namespace_node local_variables[ACPI_METHOD_NUM_LOCALS]; /* Control method locals */ struct acpi_namespace_node *method_call_node; /* Called method Node */ union acpi_parse_object *method_call_op; /* method_call Op if running a method */ union acpi_operand_object *method_desc; /* Method descriptor if running a method */ struct acpi_namespace_node *method_node; /* Method node if running a method. */ union acpi_parse_object *op; /* Current parser op */ - union acpi_operand_object *operands[ACPI_OBJ_NUM_OPERANDS + 1]; /* Operands passed to the interpreter (+1 for NULL terminator) */ const struct acpi_opcode_info *op_info; /* Info on current opcode */ union acpi_parse_object *origin; /* Start of walk [Obsolete] */ - union acpi_operand_object **params; - struct acpi_parse_state parser_state; /* Current state of parser */ union acpi_operand_object *result_obj; union acpi_generic_state *results; /* Stack of accumulated results */ union acpi_operand_object *return_desc; /* Return object, if any */ union acpi_generic_state *scope_info; /* Stack of nested scopes */ - union acpi_parse_object *prev_op; /* Last op that was processed */ union acpi_parse_object *next_op; /* next op to be processed */ + struct acpi_thread_state *thread; acpi_parse_downwards descending_callback; acpi_parse_upwards ascending_callback; - struct acpi_thread_state *thread; - struct acpi_walk_state *next; /* Next walk_state in list */ }; /* Info used by acpi_ps_init_objects */ @@ -151,11 +154,11 @@ struct acpi_walk_info { /* Display Types */ -#define ACPI_DISPLAY_SUMMARY (u8) 0 -#define ACPI_DISPLAY_OBJECTS (u8) 1 -#define ACPI_DISPLAY_MASK (u8) 1 +#define ACPI_DISPLAY_SUMMARY (u8) 0 +#define ACPI_DISPLAY_OBJECTS (u8) 1 +#define ACPI_DISPLAY_MASK (u8) 1 -#define ACPI_DISPLAY_SHORT (u8) 2 +#define ACPI_DISPLAY_SHORT (u8) 2 struct acpi_get_devices_info { acpi_walk_callback user_function; diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index 520f315dd53..091dd256717 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -44,6 +44,8 @@ #ifndef __ACTYPES_H__ #define __ACTYPES_H__ +/* acpisrc:struct_defs -- for acpisrc conversion */ + /* * ACPI_MACHINE_WIDTH must be specified in an OS- or compiler-dependent header * and must be either 16, 32, or 64 @@ -250,7 +252,7 @@ typedef acpi_native_uint acpi_size; /* Use C99 uintptr_t for pointer casting if available, "void *" otherwise */ #ifndef acpi_uintptr_t -#define acpi_uintptr_t void * +#define acpi_uintptr_t void * #endif /* @@ -259,7 +261,7 @@ typedef acpi_native_uint acpi_size; * manager implementation is to be used (ACPI_USE_LOCAL_CACHE) */ #ifndef acpi_cache_t -#define acpi_cache_t struct acpi_memory_list +#define acpi_cache_t struct acpi_memory_list #endif /* @@ -267,7 +269,7 @@ typedef acpi_native_uint acpi_size; * lock and unlock OSL interfaces. */ #ifndef acpi_cpu_flags -#define acpi_cpu_flags acpi_native_uint +#define acpi_cpu_flags acpi_native_uint #endif /* @@ -300,7 +302,7 @@ typedef acpi_native_uint acpi_size; * thread_id is returned by acpi_os_get_thread_id. */ #ifndef acpi_thread_id -#define acpi_thread_id acpi_native_uint +#define acpi_thread_id acpi_native_uint #endif /******************************************************************************* @@ -869,7 +871,7 @@ acpi_status(*acpi_adr_space_handler) (u32 function, void *handler_context, void *region_context); -#define ACPI_DEFAULT_HANDLER NULL +#define ACPI_DEFAULT_HANDLER NULL typedef acpi_status(*acpi_adr_space_setup) (acpi_handle region_handle, @@ -926,8 +928,8 @@ struct acpi_compatible_id_list { #define ACPI_STA_BATTERY_PRESENT 0x10 #define ACPI_COMMON_OBJ_INFO \ - acpi_object_type type; /* ACPI object type */ \ - acpi_name name /* ACPI object Name */ + acpi_object_type type; /* ACPI object type */ \ + acpi_name name /* ACPI object Name */ struct acpi_obj_info_header { ACPI_COMMON_OBJ_INFO; @@ -1182,12 +1184,12 @@ struct acpi_resource_source { /* Fields common to all address descriptors, 16/32/64 bit */ #define ACPI_RESOURCE_ADDRESS_COMMON \ - u8 resource_type; \ - u8 producer_consumer; \ - u8 decode; \ - u8 min_address_fixed; \ - u8 max_address_fixed; \ - union acpi_resource_attribute info; + u8 resource_type; \ + u8 producer_consumer; \ + u8 decode; \ + u8 min_address_fixed; \ + u8 max_address_fixed; \ + union acpi_resource_attribute info; struct acpi_resource_address { ACPI_RESOURCE_ADDRESS_COMMON}; @@ -1308,10 +1310,6 @@ struct acpi_resource { #define ACPI_NEXT_RESOURCE(res) (struct acpi_resource *)((u8 *) res + res->length) -/* - * END: of definitions for Resource Attributes - */ - struct acpi_pci_routing_table { u32 length; u32 pin; @@ -1320,8 +1318,4 @@ struct acpi_pci_routing_table { char source[4]; /* pad to 64 bits so sizeof() works in all cases */ }; -/* - * END: of definitions for PCI Routing tables - */ - #endif /* __ACTYPES_H__ */ diff --git a/include/acpi/acutils.h b/include/acpi/acutils.h index 71ff78c7544..5e69a80c785 100644 --- a/include/acpi/acutils.h +++ b/include/acpi/acutils.h @@ -77,6 +77,12 @@ extern const char *acpi_gbl_TYPdecode[4]; #define ACPI_VARIABLE_LENGTH 2 #define ACPI_SMALL_VARIABLE_LENGTH 3 +typedef +acpi_status(*acpi_walk_aml_callback) (u8 * aml, + u32 length, + u32 offset, + u8 resource_index, void *context); + typedef acpi_status(*acpi_pkg_callback) (u8 object_type, union acpi_operand_object * source_object, @@ -469,6 +475,25 @@ acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer); #define ACPI_ANY_BASE 0 +u32 acpi_ut_dword_byte_swap(u32 value); + +void acpi_ut_set_integer_width(u8 revision); + +#ifdef ACPI_DEBUG_OUTPUT +void +acpi_ut_display_init_pathname(u8 type, + struct acpi_namespace_node *obj_handle, + char *path); +#endif + +/* + * utresrc + */ +acpi_status +acpi_ut_walk_aml_resources(u8 * aml, + acpi_size aml_length, + acpi_walk_aml_callback user_function, void *context); + acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index); u32 acpi_ut_get_descriptor_length(void *aml); @@ -483,18 +508,6 @@ acpi_status acpi_ut_get_resource_end_tag(union acpi_operand_object *obj_desc, u8 ** end_tag); -u32 acpi_ut_dword_byte_swap(u32 value); - -void acpi_ut_set_integer_width(u8 revision); - -#ifdef ACPI_DEBUG_OUTPUT -void -acpi_ut_display_init_pathname(u8 type, - struct acpi_namespace_node *obj_handle, - char *path); - -#endif - /* * utmutex - mutex support */ @@ -521,14 +534,15 @@ acpi_ut_initialize_buffer(struct acpi_buffer *buffer, void *acpi_ut_allocate(acpi_size size, u32 component, char *module, u32 line); -void *acpi_ut_callocate(acpi_size size, u32 component, char *module, u32 line); +void *acpi_ut_allocate_zeroed(acpi_size size, + u32 component, char *module, u32 line); #ifdef ACPI_DBG_TRACK_ALLOCATIONS void *acpi_ut_allocate_and_track(acpi_size size, u32 component, char *module, u32 line); -void *acpi_ut_callocate_and_track(acpi_size size, - u32 component, char *module, u32 line); +void *acpi_ut_allocate_zeroed_and_track(acpi_size size, + u32 component, char *module, u32 line); void acpi_ut_free_and_track(void *address, u32 component, char *module, u32 line); @@ -538,6 +552,11 @@ void acpi_ut_dump_allocation_info(void); #endif /* ACPI_FUTURE_USAGE */ void acpi_ut_dump_allocations(u32 component, char *module); + +acpi_status +acpi_ut_create_list(char *list_name, + u16 object_size, struct acpi_memory_list **return_cache); + #endif #endif /* _ACUTILS_H */ diff --git a/include/acpi/amlresrc.h b/include/acpi/amlresrc.h index e5b42eb3819..64736860bdd 100644 --- a/include/acpi/amlresrc.h +++ b/include/acpi/amlresrc.h @@ -42,9 +42,17 @@ * POSSIBILITY OF SUCH DAMAGES. */ +/* acpisrc:struct_defs -- for acpisrc conversion */ + #ifndef __AMLRESRC_H #define __AMLRESRC_H +/*! [Begin] no source code translation */ + +/* + * Resource descriptor tags, as defined in the ACPI specification. + * Used to symbolically reference fields within a descriptor. + */ #define ACPI_RESTAG_ADDRESS "_ADR" #define ACPI_RESTAG_ALIGNMENT "_ALN" #define ACPI_RESTAG_ADDRESSSPACE "_ASI" @@ -57,12 +65,12 @@ #define ACPI_RESTAG_DMATYPE "_TYP" /* Compatible(0), A(1), B(2), F(3) */ #define ACPI_RESTAG_GRANULARITY "_GRA" #define ACPI_RESTAG_INTERRUPT "_INT" -#define ACPI_RESTAG_INTERRUPTLEVEL "_LL_" /* active_lo(1), active_hi(0) */ -#define ACPI_RESTAG_INTERRUPTSHARE "_SHR" /* Shareable(1), no_share(0) */ +#define ACPI_RESTAG_INTERRUPTLEVEL "_LL_" /* ActiveLo(1), ActiveHi(0) */ +#define ACPI_RESTAG_INTERRUPTSHARE "_SHR" /* Shareable(1), NoShare(0) */ #define ACPI_RESTAG_INTERRUPTTYPE "_HE_" /* Edge(1), Level(0) */ #define ACPI_RESTAG_LENGTH "_LEN" #define ACPI_RESTAG_MEMATTRIBUTES "_MTP" /* Memory(0), Reserved(1), ACPI(2), NVS(3) */ -#define ACPI_RESTAG_MEMTYPE "_MEM" /* non_cache(0), Cacheable(1) Cache+combine(2), Cache+prefetch(3) */ +#define ACPI_RESTAG_MEMTYPE "_MEM" /* NonCache(0), Cacheable(1) Cache+combine(2), Cache+prefetch(3) */ #define ACPI_RESTAG_MAXADDR "_MAX" #define ACPI_RESTAG_MINADDR "_MIN" #define ACPI_RESTAG_MAXTYPE "_MAF" @@ -70,11 +78,12 @@ #define ACPI_RESTAG_REGISTERBITOFFSET "_RBO" #define ACPI_RESTAG_REGISTERBITWIDTH "_RBW" #define ACPI_RESTAG_RANGETYPE "_RNG" -#define ACPI_RESTAG_READWRITETYPE "_RW_" /* read_only(0), Writeable (1) */ +#define ACPI_RESTAG_READWRITETYPE "_RW_" /* ReadOnly(0), Writeable (1) */ #define ACPI_RESTAG_TRANSLATION "_TRA" #define ACPI_RESTAG_TRANSTYPE "_TRS" /* Sparse(1), Dense(0) */ #define ACPI_RESTAG_TYPE "_TTP" /* Translation(1), Static (0) */ -#define ACPI_RESTAG_XFERTYPE "_SIz" /* 8(0), 8_and16(1), 16(2) */ +#define ACPI_RESTAG_XFERTYPE "_SIZ" /* 8(0), 8And16(1), 16(2) */ +/*! [End] no source code translation !*/ /* Default sizes for "small" resource descriptors */ @@ -109,7 +118,7 @@ struct asl_resource_node { * SMALL descriptors */ #define AML_RESOURCE_SMALL_HEADER_COMMON \ - u8 descriptor_type; + u8 descriptor_type; struct aml_resource_small_header { AML_RESOURCE_SMALL_HEADER_COMMON}; @@ -162,8 +171,8 @@ struct aml_resource_end_tag { * LARGE descriptors */ #define AML_RESOURCE_LARGE_HEADER_COMMON \ - u8 descriptor_type;\ - u16 resource_length; + u8 descriptor_type;\ + u16 resource_length; struct aml_resource_large_header { AML_RESOURCE_LARGE_HEADER_COMMON}; @@ -194,9 +203,9 @@ struct aml_resource_fixed_memory32 { }; #define AML_RESOURCE_ADDRESS_COMMON \ - u8 resource_type; \ - u8 flags; \ - u8 specific_flags; + u8 resource_type; \ + u8 flags; \ + u8 specific_flags; struct aml_resource_address { AML_RESOURCE_LARGE_HEADER_COMMON AML_RESOURCE_ADDRESS_COMMON}; diff --git a/include/acpi/platform/acenv.h b/include/acpi/platform/acenv.h index d5a7f566c01..2270bdd5e53 100644 --- a/include/acpi/platform/acenv.h +++ b/include/acpi/platform/acenv.h @@ -70,6 +70,7 @@ #define ACPI_DEBUGGER #define ACPI_DISASSEMBLER #define ACPI_MUTEX_DEBUG +#define ACPI_DBG_TRACK_ALLOCATIONS #endif #ifdef ACPI_ASL_COMPILER @@ -165,17 +166,6 @@ #endif -/* - * Memory allocation tracking. Used only if - * 1) This is the debug version - * 2) This is NOT a 16-bit version of the code (not enough real-mode memory) - */ -#ifdef ACPI_DEBUG_OUTPUT -#if ACPI_MACHINE_WIDTH != 16 -#define ACPI_DBG_TRACK_ALLOCATIONS -#endif -#endif - /*! [End] no source code translation !*/ /* -- cgit v1.2.3 From 793c2388cae3fd023b3b5166354931752d42353c Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Fri, 31 Mar 2006 00:00:00 -0500 Subject: ACPI: ACPICA 20060331 Implemented header file support for the following additional ACPI tables: ASF!, BOOT, CPEP, DBGP, MCFG, SPCR, SPMI, TCPA, and WDRT. With this support, all current and known ACPI tables are now defined in the ACPICA headers and are available for use by device drivers and other software. Implemented support to allow tables that contain ACPI names with invalid characters to be loaded. Previously, this would cause the table load to fail, but since there are several known cases of such tables on existing machines, this change was made to enable ACPI support for them. Also, this matches the behavior of the Microsoft ACPI implementation. https://bugzilla.novell.com/show_bug.cgi?id=147621 Fixed a couple regressions introduced during the memory optimization in the 20060317 release. The namespace node definition required additional reorganization and an internal datatype that had been changed to 8-bit was restored to 32-bit. (Valery Podrezov) Fixed a problem where a null pointer passed to acpi_ut_delete_generic_state() could be passed through to acpi_os_release_object which is unexpected. Such null pointers are now trapped and ignored, matching the behavior of the previous implementation before the deployment of acpi_os_release_object(). (Valery Podrezov, Fiodor Suietov) Fixed a memory mapping leak during the deletion of a SystemMemory operation region where a cached memory mapping was not deleted. This became a noticeable problem for operation regions that are defined within frequently used control methods. (Dana Meyers) Reorganized the ACPI table header files into two main files: one for the ACPI tables consumed by the ACPICA core, and another for the miscellaneous ACPI tables that are consumed by the drivers and other software. The various FADT definitions were merged into one common section and three different tables (ACPI 1.0, 1.0+, and 2.0) Signed-off-by: Bob Moore Signed-off-by: Len Brown --- arch/i386/kernel/acpi/boot.c | 4 +- drivers/acpi/bus.c | 2 +- drivers/acpi/dispatcher/dsmethod.c | 2 +- drivers/acpi/dispatcher/dswexec.c | 1 - drivers/acpi/events/evrgnini.c | 13 +- drivers/acpi/executer/exdump.c | 6 +- drivers/acpi/executer/exnames.c | 2 +- drivers/acpi/hardware/hwtimer.c | 4 +- drivers/acpi/namespace/nsalloc.c | 2 + drivers/acpi/namespace/nsdump.c | 3 + drivers/acpi/namespace/nssearch.c | 50 +-- drivers/acpi/parser/psloop.c | 12 + drivers/acpi/parser/psscope.c | 4 +- drivers/acpi/resources/rslist.c | 8 +- drivers/acpi/system.c | 2 +- drivers/acpi/tables.c | 4 +- drivers/acpi/tables/tbconvrt.c | 31 +- drivers/acpi/tables/tbrsdt.c | 3 +- drivers/acpi/tables/tbutils.c | 122 ++++--- drivers/acpi/tables/tbxfroot.c | 9 +- drivers/acpi/utilities/utdebug.c | 38 ++- drivers/acpi/utilities/utdelete.c | 16 +- drivers/acpi/utilities/utglobal.c | 2 +- drivers/acpi/utilities/utinit.c | 6 +- drivers/acpi/utilities/utmisc.c | 104 +++++- drivers/acpi/utilities/utresrc.c | 6 +- drivers/acpi/utilities/utstate.c | 10 +- include/acpi/acconfig.h | 2 +- include/acpi/acdisasm.h | 141 +++++++- include/acpi/acglobal.h | 7 +- include/acpi/aclocal.h | 14 +- include/acpi/acmacros.h | 7 +- include/acpi/acobject.h | 4 + include/acpi/acparser.h | 9 +- include/acpi/acpi_bus.h | 2 +- include/acpi/acpiosxf.h | 2 - include/acpi/acstruct.h | 2 +- include/acpi/actables.h | 6 +- include/acpi/actbl.h | 400 +++++++++++++---------- include/acpi/actbl1.h | 639 +++++++++++++++++++++++++++++++++---- include/acpi/actbl2.h | 230 +------------ include/acpi/acutils.h | 10 +- include/acpi/platform/acenv.h | 4 +- 43 files changed, 1314 insertions(+), 631 deletions(-) diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c index 033066176b3..a6fe9122520 100644 --- a/arch/i386/kernel/acpi/boot.c +++ b/arch/i386/kernel/acpi/boot.c @@ -621,9 +621,9 @@ extern u32 pmtmr_ioport; static int __init acpi_parse_fadt(unsigned long phys, unsigned long size) { - struct fadt_descriptor_rev2 *fadt = NULL; + struct fadt_descriptor *fadt = NULL; - fadt = (struct fadt_descriptor_rev2 *)__acpi_map_table(phys, size); + fadt = (struct fadt_descriptor *)__acpi_map_table(phys, size); if (!fadt) { printk(KERN_WARNING PREFIX "Unable to map FADT\n"); return 0; diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 9c4ac0191f6..b3a214db56f 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -43,7 +43,7 @@ ACPI_MODULE_NAME("acpi_bus") extern void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger); #endif -FADT_DESCRIPTOR acpi_fadt; +struct fadt_descriptor acpi_fadt; EXPORT_SYMBOL(acpi_fadt); struct acpi_device *acpi_root; diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c index 238916ce541..7dc59fc7344 100644 --- a/drivers/acpi/dispatcher/dsmethod.c +++ b/drivers/acpi/dispatcher/dsmethod.c @@ -502,7 +502,7 @@ void acpi_ds_terminate_control_method(struct acpi_walk_state *walk_state) * Delete any namespace entries created immediately underneath * the method */ - if (method_node->child) { + if (method_node && method_node->child) { acpi_ns_delete_namespace_subtree(method_node); } diff --git a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c index 198949f4104..8b740b370eb 100644 --- a/drivers/acpi/dispatcher/dswexec.c +++ b/drivers/acpi/dispatcher/dswexec.c @@ -49,7 +49,6 @@ #include #include #include -#include #define _COMPONENT ACPI_DISPATCHER ACPI_MODULE_NAME("dswexec") diff --git a/drivers/acpi/events/evrgnini.c b/drivers/acpi/events/evrgnini.c index db98747fe54..d1809f4240a 100644 --- a/drivers/acpi/events/evrgnini.c +++ b/drivers/acpi/events/evrgnini.c @@ -75,7 +75,18 @@ acpi_ev_system_memory_region_setup(acpi_handle handle, if (function == ACPI_REGION_DEACTIVATE) { if (*region_context) { - ACPI_FREE(*region_context); + local_region_context = + (struct acpi_mem_space_context *)*region_context; + + /* Delete a cached mapping if present */ + + if (local_region_context->mapped_length) { + acpi_os_unmap_memory(local_region_context-> + mapped_logical_address, + local_region_context-> + mapped_length); + } + ACPI_FREE(local_region_context); *region_context = NULL; } return_ACPI_STATUS(AE_OK); diff --git a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c index 56db58b8e23..1dfebf9e707 100644 --- a/drivers/acpi/executer/exdump.c +++ b/drivers/acpi/executer/exdump.c @@ -61,6 +61,10 @@ static void acpi_ex_out_pointer(char *title, void *value); static void acpi_ex_out_address(char *title, acpi_physical_address value); +static void +acpi_ex_dump_object(union acpi_operand_object *obj_desc, + struct acpi_exdump_info *info); + static void acpi_ex_dump_reference_obj(union acpi_operand_object *obj_desc); static void @@ -263,7 +267,7 @@ static struct acpi_exdump_info acpi_ex_dump_field_common[7] = { {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(common_field.node), "Parent Node"} }; -static struct acpi_exdump_info acpi_ex_dump_node[6] = { +static struct acpi_exdump_info acpi_ex_dump_node[5] = { {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_node), NULL}, {ACPI_EXD_UINT8, ACPI_EXD_NSOFFSET(flags), "Flags"}, {ACPI_EXD_UINT8, ACPI_EXD_NSOFFSET(owner_id), "Owner Id"}, diff --git a/drivers/acpi/executer/exnames.c b/drivers/acpi/executer/exnames.c index 80bbc20756a..085b18f8dd0 100644 --- a/drivers/acpi/executer/exnames.c +++ b/drivers/acpi/executer/exnames.c @@ -179,7 +179,7 @@ static acpi_status acpi_ex_name_segment(u8 ** in_aml_address, char *name_string) for (index = 0; (index < ACPI_NAME_SIZE) - && (acpi_ut_valid_acpi_character(*aml_address)); index++) { + && (acpi_ut_valid_acpi_char(*aml_address, 0)); index++) { char_buf[index] = *aml_address++; ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "%c\n", char_buf[index])); } diff --git a/drivers/acpi/hardware/hwtimer.c b/drivers/acpi/hardware/hwtimer.c index 9d53e46bc33..a559ac17b13 100644 --- a/drivers/acpi/hardware/hwtimer.c +++ b/drivers/acpi/hardware/hwtimer.c @@ -66,7 +66,7 @@ acpi_status acpi_get_timer_resolution(u32 * resolution) return_ACPI_STATUS(AE_BAD_PARAMETER); } - if (0 == acpi_gbl_FADT->tmr_val_ext) { + if (acpi_gbl_FADT->tmr_val_ext == 0) { *resolution = 24; } else { *resolution = 32; @@ -153,7 +153,7 @@ acpi_get_timer_duration(u32 start_ticks, u32 end_ticks, u32 * time_elapsed) if (start_ticks < end_ticks) { delta_ticks = end_ticks - start_ticks; } else if (start_ticks > end_ticks) { - if (0 == acpi_gbl_FADT->tmr_val_ext) { + if (acpi_gbl_FADT->tmr_val_ext == 0) { /* 24-bit Timer */ diff --git a/drivers/acpi/namespace/nsalloc.c b/drivers/acpi/namespace/nsalloc.c index 8b921c96d6a..c92c03693a1 100644 --- a/drivers/acpi/namespace/nsalloc.c +++ b/drivers/acpi/namespace/nsalloc.c @@ -211,6 +211,8 @@ void acpi_ns_install_node(struct acpi_walk_state *walk_state, struct acpi_namesp acpi_ut_get_node_name(parent_node), acpi_ut_get_type_name(parent_node->type), parent_node)); + + return_VOID; } /******************************************************************************* diff --git a/drivers/acpi/namespace/nsdump.c b/drivers/acpi/namespace/nsdump.c index e275373b170..5662d2def62 100644 --- a/drivers/acpi/namespace/nsdump.c +++ b/drivers/acpi/namespace/nsdump.c @@ -204,6 +204,9 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, } if (!acpi_ut_valid_acpi_name(this_node->name.integer)) { + this_node->name.integer = + acpi_ut_repair_name(this_node->name.integer); + ACPI_WARNING((AE_INFO, "Invalid ACPI Name %08X", this_node->name.integer)); } diff --git a/drivers/acpi/namespace/nssearch.c b/drivers/acpi/namespace/nssearch.c index c929f45071c..51adec5a23d 100644 --- a/drivers/acpi/namespace/nssearch.c +++ b/drivers/acpi/namespace/nssearch.c @@ -128,9 +128,8 @@ acpi_ns_search_node(u32 target_name, next_node->object); } - /* - * Found matching entry. - */ + /* Found matching entry */ + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Name [%4.4s] (%s) %p found in scope [%4.4s] %p\n", ACPI_CAST_PTR(char, &target_name), @@ -248,10 +247,8 @@ acpi_ns_search_parent_tree(u32 target_name, return_ACPI_STATUS(status); } - /* - * Not found here, go up another level - * (until we reach the root) - */ + /* Not found here, go up another level (until we reach the root) */ + parent_node = acpi_ns_get_parent_node(parent_node); } @@ -307,12 +304,29 @@ acpi_ns_search_and_enter(u32 target_name, return_ACPI_STATUS(AE_BAD_PARAMETER); } - /* Name must consist of printable characters */ - + /* + * Name must consist of valid ACPI characters. We will repair the name if + * necessary because we don't want to abort because of this, but we want + * all namespace names to be printable. A warning message is appropriate. + * + * This issue came up because there are in fact machines that exhibit + * this problem, and we want to be able to enable ACPI support for them, + * even though there are a few bad names. + */ if (!acpi_ut_valid_acpi_name(target_name)) { - ACPI_ERROR((AE_INFO, "Bad character in ACPI Name: %X", - target_name)); - return_ACPI_STATUS(AE_BAD_CHARACTER); + target_name = acpi_ut_repair_name(target_name); + + /* Report warning only if in strict mode or debug mode */ + + if (!acpi_gbl_enable_interpreter_slack) { + ACPI_WARNING((AE_INFO, + "Found bad character(s) in name, repaired: [%4.4s]\n", + ACPI_CAST_PTR(char, &target_name))); + } else { + ACPI_DEBUG_PRINT((ACPI_DB_WARN, + "Found bad character(s) in name, repaired: [%4.4s]\n", + ACPI_CAST_PTR(char, &target_name))); + } } /* Try to find the name in the namespace level specified by the caller */ @@ -328,10 +342,8 @@ acpi_ns_search_and_enter(u32 target_name, status = AE_ALREADY_EXISTS; } - /* - * Either found it or there was an error - * -- finished either way - */ + /* Either found it or there was an error: finished either way */ + return_ACPI_STATUS(status); } @@ -357,9 +369,8 @@ acpi_ns_search_and_enter(u32 target_name, } } - /* - * In execute mode, just search, never add names. Exit now. - */ + /* In execute mode, just search, never add names. Exit now */ + if (interpreter_mode == ACPI_IMODE_EXECUTE) { ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%4.4s Not found in %p [Not adding]\n", @@ -379,6 +390,5 @@ acpi_ns_search_and_enter(u32 target_name, acpi_ns_install_node(walk_state, node, new_node, type); *return_node = new_node; - return_ACPI_STATUS(AE_OK); } diff --git a/drivers/acpi/parser/psloop.c b/drivers/acpi/parser/psloop.c index 14052cb648c..3a29ce68037 100644 --- a/drivers/acpi/parser/psloop.c +++ b/drivers/acpi/parser/psloop.c @@ -747,7 +747,19 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } + + status2 = + acpi_ds_result_stack_pop + (walk_state); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } + + acpi_ut_delete_generic_state + (acpi_ut_pop_generic_state + (&walk_state->control_state)); } + acpi_ps_pop_scope(parser_state, &op, &walk_state->arg_types, &walk_state->arg_count); diff --git a/drivers/acpi/parser/psscope.c b/drivers/acpi/parser/psscope.c index 9233a4044d6..424ab1c20da 100644 --- a/drivers/acpi/parser/psscope.c +++ b/drivers/acpi/parser/psscope.c @@ -143,7 +143,7 @@ acpi_ps_init_scope(struct acpi_parse_state * parser_state, acpi_status acpi_ps_push_scope(struct acpi_parse_state *parser_state, union acpi_parse_object *op, - u32 remaining_args, u8 arg_count) + u32 remaining_args, u32 arg_count) { union acpi_generic_state *scope; @@ -196,7 +196,7 @@ acpi_ps_push_scope(struct acpi_parse_state *parser_state, void acpi_ps_pop_scope(struct acpi_parse_state *parser_state, - union acpi_parse_object **op, u32 * arg_list, u8 * arg_count) + union acpi_parse_object **op, u32 * arg_list, u32 * arg_count) { union acpi_generic_state *scope = parser_state->scope; diff --git a/drivers/acpi/resources/rslist.c b/drivers/acpi/resources/rslist.c index 50bbb19bf4a..1b2d1e717e7 100644 --- a/drivers/acpi/resources/rslist.c +++ b/drivers/acpi/resources/rslist.c @@ -64,10 +64,11 @@ ACPI_MODULE_NAME("rslist") acpi_status acpi_rs_convert_aml_to_resources(u8 * aml, u32 length, - u32 offset, - u8 resource_index, void **resource_ptr) + u32 offset, u8 resource_index, void **context) { - struct acpi_resource *resource = *resource_ptr; + struct acpi_resource **resource_ptr = + ACPI_CAST_INDIRECT_PTR(struct acpi_resource, context); + struct acpi_resource *resource; acpi_status status; ACPI_FUNCTION_TRACE("rs_convert_aml_to_resources"); @@ -76,6 +77,7 @@ acpi_rs_convert_aml_to_resources(u8 * aml, * Check that the input buffer and all subsequent pointers into it * are aligned on a native word boundary. Most important on IA64 */ + resource = *resource_ptr; if (ACPI_IS_MISALIGNED(resource)) { ACPI_WARNING((AE_INFO, "Misaligned resource pointer %p", resource)); diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c index e4308c7a674..1943bec1884 100644 --- a/drivers/acpi/system.c +++ b/drivers/acpi/system.c @@ -39,7 +39,7 @@ ACPI_MODULE_NAME("acpi_system") #define ACPI_SYSTEM_FILE_EVENT "event" #define ACPI_SYSTEM_FILE_DSDT "dsdt" #define ACPI_SYSTEM_FILE_FADT "fadt" -extern FADT_DESCRIPTOR acpi_fadt; +extern struct fadt_descriptor acpi_fadt; /* -------------------------------------------------------------------------- FS Interface (/proc) diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index 7f37c7cc5ef..ed5e8816d83 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -282,8 +282,8 @@ acpi_get_table_header_early(enum acpi_table_id id, /* Map the DSDT header via the pointer in the FADT */ if (id == ACPI_DSDT) { - struct fadt_descriptor_rev2 *fadt = - (struct fadt_descriptor_rev2 *)*header; + struct fadt_descriptor *fadt = + (struct fadt_descriptor *)*header; if (fadt->revision == 3 && fadt->Xdsdt) { *header = (void *)__acpi_map_table(fadt->Xdsdt, diff --git a/drivers/acpi/tables/tbconvrt.c b/drivers/acpi/tables/tbconvrt.c index 5155b27cf03..a913a927d32 100644 --- a/drivers/acpi/tables/tbconvrt.c +++ b/drivers/acpi/tables/tbconvrt.c @@ -54,12 +54,12 @@ acpi_tb_init_generic_address(struct acpi_generic_address *new_gas_struct, acpi_physical_address address); static void -acpi_tb_convert_fadt1(struct fadt_descriptor_rev2 *local_fadt, +acpi_tb_convert_fadt1(struct fadt_descriptor *local_fadt, struct fadt_descriptor_rev1 *original_fadt); static void -acpi_tb_convert_fadt2(struct fadt_descriptor_rev2 *local_fadt, - struct fadt_descriptor_rev2 *original_fadt); +acpi_tb_convert_fadt2(struct fadt_descriptor *local_fadt, + struct fadt_descriptor *original_fadt); u8 acpi_fadt_is_v1; ACPI_EXPORT_SYMBOL(acpi_fadt_is_v1) @@ -120,7 +120,7 @@ acpi_status acpi_tb_convert_to_xsdt(struct acpi_table_desc *table_info) { acpi_size table_size; u32 i; - XSDT_DESCRIPTOR *new_table; + struct xsdt_descriptor *new_table; ACPI_FUNCTION_ENTRY(); @@ -151,12 +151,12 @@ acpi_status acpi_tb_convert_to_xsdt(struct acpi_table_desc *table_info) if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) { ACPI_STORE_ADDRESS(new_table->table_offset_entry[i], (ACPI_CAST_PTR - (struct rsdt_descriptor_rev1, + (struct rsdt_descriptor, table_info->pointer))-> table_offset_entry[i]); } else { new_table->table_offset_entry[i] = - (ACPI_CAST_PTR(XSDT_DESCRIPTOR, + (ACPI_CAST_PTR(struct xsdt_descriptor, table_info->pointer))-> table_offset_entry[i]; } @@ -218,7 +218,7 @@ acpi_tb_init_generic_address(struct acpi_generic_address *new_gas_struct, ******************************************************************************/ static void -acpi_tb_convert_fadt1(struct fadt_descriptor_rev2 *local_fadt, +acpi_tb_convert_fadt1(struct fadt_descriptor *local_fadt, struct fadt_descriptor_rev1 *original_fadt) { @@ -364,14 +364,13 @@ acpi_tb_convert_fadt1(struct fadt_descriptor_rev2 *local_fadt, ******************************************************************************/ static void -acpi_tb_convert_fadt2(struct fadt_descriptor_rev2 *local_fadt, - struct fadt_descriptor_rev2 *original_fadt) +acpi_tb_convert_fadt2(struct fadt_descriptor *local_fadt, + struct fadt_descriptor *original_fadt) { /* We have an ACPI 2.0 FADT but we must copy it to our local buffer */ - ACPI_MEMCPY(local_fadt, original_fadt, - sizeof(struct fadt_descriptor_rev2)); + ACPI_MEMCPY(local_fadt, original_fadt, sizeof(struct fadt_descriptor)); /* * "X" fields are optional extensions to the original V1.0 fields, so @@ -490,7 +489,7 @@ acpi_tb_convert_fadt2(struct fadt_descriptor_rev2 *local_fadt, acpi_status acpi_tb_convert_table_fadt(void) { - struct fadt_descriptor_rev2 *local_fadt; + struct fadt_descriptor *local_fadt; struct acpi_table_desc *table_desc; ACPI_FUNCTION_TRACE("tb_convert_table_fadt"); @@ -507,13 +506,13 @@ acpi_status acpi_tb_convert_table_fadt(void) /* Allocate buffer for the ACPI 2.0(+) FADT */ - local_fadt = ACPI_ALLOCATE_ZEROED(sizeof(struct fadt_descriptor_rev2)); + local_fadt = ACPI_ALLOCATE_ZEROED(sizeof(struct fadt_descriptor)); if (!local_fadt) { return_ACPI_STATUS(AE_NO_MEMORY); } if (acpi_gbl_FADT->revision >= FADT2_REVISION_ID) { - if (acpi_gbl_FADT->length < sizeof(struct fadt_descriptor_rev2)) { + if (acpi_gbl_FADT->length < sizeof(struct fadt_descriptor)) { /* Length is too short to be a V2.0 table */ @@ -538,7 +537,7 @@ acpi_status acpi_tb_convert_table_fadt(void) /* Global FADT pointer will point to the new common V2.0 FADT */ acpi_gbl_FADT = local_fadt; - acpi_gbl_FADT->length = sizeof(FADT_DESCRIPTOR); + acpi_gbl_FADT->length = sizeof(struct fadt_descriptor); /* Free the original table */ @@ -550,7 +549,7 @@ acpi_status acpi_tb_convert_table_fadt(void) table_desc->pointer = ACPI_CAST_PTR(struct acpi_table_header, acpi_gbl_FADT); table_desc->allocation = ACPI_MEM_ALLOCATED; - table_desc->length = sizeof(struct fadt_descriptor_rev2); + table_desc->length = sizeof(struct fadt_descriptor); /* Dump the entire FADT */ diff --git a/drivers/acpi/tables/tbrsdt.c b/drivers/acpi/tables/tbrsdt.c index 946d2f2d611..9e0ebe625ed 100644 --- a/drivers/acpi/tables/tbrsdt.c +++ b/drivers/acpi/tables/tbrsdt.c @@ -280,7 +280,8 @@ acpi_status acpi_tb_get_table_rsdt(void) return_ACPI_STATUS(status); } - acpi_gbl_XSDT = ACPI_CAST_PTR(XSDT_DESCRIPTOR, table_info.pointer); + acpi_gbl_XSDT = + ACPI_CAST_PTR(struct xsdt_descriptor, table_info.pointer); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "XSDT located at %p\n", acpi_gbl_XSDT)); return_ACPI_STATUS(status); diff --git a/drivers/acpi/tables/tbutils.c b/drivers/acpi/tables/tbutils.c index b463d4b8882..f8d28ae8811 100644 --- a/drivers/acpi/tables/tbutils.c +++ b/drivers/acpi/tables/tbutils.c @@ -193,73 +193,119 @@ acpi_tb_validate_table_header(struct acpi_table_header *table_header) /******************************************************************************* * - * FUNCTION: acpi_tb_verify_table_checksum + * FUNCTION: acpi_tb_sum_table * - * PARAMETERS: *table_header - ACPI table to verify + * PARAMETERS: Buffer - Buffer to sum + * Length - Size of the buffer * - * RETURN: 8 bit checksum of table + * RETURN: 8 bit sum of buffer * - * DESCRIPTION: Does an 8 bit checksum of table and returns status. A correct - * table should have a checksum of 0. + * DESCRIPTION: Computes an 8 bit sum of the buffer(length) and returns it. * ******************************************************************************/ -acpi_status -acpi_tb_verify_table_checksum(struct acpi_table_header * table_header) +u8 acpi_tb_sum_table(void *buffer, u32 length) +{ + acpi_native_uint i; + u8 sum = 0; + + if (!buffer || !length) { + return (0); + } + + for (i = 0; i < length; i++) { + sum = (u8) (sum + ((u8 *) buffer)[i]); + } + return (sum); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_generate_checksum + * + * PARAMETERS: Table - Pointer to a valid ACPI table (with a + * standard ACPI header) + * + * RETURN: 8 bit checksum of buffer + * + * DESCRIPTION: Computes an 8 bit checksum of the table. + * + ******************************************************************************/ + +u8 acpi_tb_generate_checksum(struct acpi_table_header * table) { u8 checksum; - acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("tb_verify_table_checksum"); + /* Sum the entire table as-is */ - /* Compute the checksum on the table */ + checksum = acpi_tb_sum_table(table, table->length); - checksum = - acpi_tb_generate_checksum(table_header, table_header->length); + /* Subtract off the existing checksum value in the table */ - /* Return the appropriate exception */ + checksum = (u8) (checksum - table->checksum); - if (checksum) { - ACPI_WARNING((AE_INFO, - "Invalid checksum in table [%4.4s] (%02X, sum %02X is not zero)", - table_header->signature, - (u32) table_header->checksum, (u32) checksum)); + /* Compute the final checksum */ - status = AE_BAD_CHECKSUM; - } - return_ACPI_STATUS(status); + checksum = (u8) (0 - checksum); + return (checksum); } /******************************************************************************* * - * FUNCTION: acpi_tb_generate_checksum + * FUNCTION: acpi_tb_set_checksum * - * PARAMETERS: Buffer - Buffer to checksum - * Length - Size of the buffer + * PARAMETERS: Table - Pointer to a valid ACPI table (with a + * standard ACPI header) * - * RETURN: 8 bit checksum of buffer + * RETURN: None. Sets the table checksum field * - * DESCRIPTION: Computes an 8 bit checksum of the buffer(length) and returns it. + * DESCRIPTION: Computes an 8 bit checksum of the table and inserts the + * checksum into the table header. * ******************************************************************************/ -u8 acpi_tb_generate_checksum(void *buffer, u32 length) +void acpi_tb_set_checksum(struct acpi_table_header *table) { - u8 *end_buffer; - u8 *rover; - u8 sum = 0; - if (buffer && length) { + table->checksum = acpi_tb_generate_checksum(table); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_verify_table_checksum + * + * PARAMETERS: *table_header - ACPI table to verify + * + * RETURN: 8 bit checksum of table + * + * DESCRIPTION: Generates an 8 bit checksum of table and returns and compares + * it to the existing checksum value. + * + ******************************************************************************/ + +acpi_status +acpi_tb_verify_table_checksum(struct acpi_table_header *table_header) +{ + u8 checksum; + + ACPI_FUNCTION_TRACE("tb_verify_table_checksum"); + + /* Compute the checksum on the table */ - /* Buffer and Length are valid */ + checksum = acpi_tb_generate_checksum(table_header); - end_buffer = ACPI_ADD_PTR(u8, buffer, length); + /* Checksum ok? */ - for (rover = buffer; rover < end_buffer; rover++) { - sum = (u8) (sum + *rover); - } + if (checksum == table_header->checksum) { + return_ACPI_STATUS(AE_OK); } - return (sum); + + ACPI_WARNING((AE_INFO, + "Incorrect checksum in table [%4.4s] - is %2.2X, should be %2.2X", + table_header->signature, table_header->checksum, + checksum)); + + return_ACPI_STATUS(AE_BAD_CHECKSUM); } #ifdef ACPI_OBSOLETE_FUNCTIONS @@ -278,7 +324,7 @@ u8 acpi_tb_generate_checksum(void *buffer, u32 length) acpi_status acpi_tb_handle_to_object(u16 table_id, - struct acpi_table_desc ** return_table_desc) + struct acpi_table_desc **return_table_desc) { u32 i; struct acpi_table_desc *table_desc; diff --git a/drivers/acpi/tables/tbxfroot.c b/drivers/acpi/tables/tbxfroot.c index 1b6d8c510e9..550284f5d1e 100644 --- a/drivers/acpi/tables/tbxfroot.c +++ b/drivers/acpi/tables/tbxfroot.c @@ -81,15 +81,14 @@ acpi_status acpi_tb_validate_rsdp(struct rsdp_descriptor *rsdp) /* Check the standard checksum */ - if (acpi_tb_generate_checksum(rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) { + if (acpi_tb_sum_table(rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) { return (AE_BAD_CHECKSUM); } /* Check extended checksum if table version >= 2 */ if ((rsdp->revision >= 2) && - (acpi_tb_generate_checksum(rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != - 0)) { + (acpi_tb_sum_table(rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0)) { return (AE_BAD_CHECKSUM); } @@ -308,12 +307,12 @@ acpi_get_firmware_table(acpi_string signature, if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) { address.pointer.value = (ACPI_CAST_PTR - (RSDT_DESCRIPTOR, + (struct rsdt_descriptor, rsdt_info->pointer))->table_offset_entry[i]; } else { address.pointer.value = (ACPI_CAST_PTR - (XSDT_DESCRIPTOR, + (struct xsdt_descriptor, rsdt_info->pointer))->table_offset_entry[i]; } diff --git a/drivers/acpi/utilities/utdebug.c b/drivers/acpi/utilities/utdebug.c index a8c350643d5..5ec1cfcc611 100644 --- a/drivers/acpi/utilities/utdebug.c +++ b/drivers/acpi/utilities/utdebug.c @@ -517,20 +517,13 @@ acpi_ut_ptr_exit(u32 line_number, * ******************************************************************************/ -void acpi_ut_dump_buffer(u8 * buffer, u32 count, u32 display, u32 component_id) +void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display) { acpi_native_uint i = 0; acpi_native_uint j; u32 temp32; u8 buf_char; - /* Only dump the buffer if tracing is enabled */ - - if (!((ACPI_LV_TABLES & acpi_dbg_level) && - (component_id & acpi_dbg_layer))) { - return; - } - if ((count < 4) || (count & 0x01)) { display = DB_BYTE_DISPLAY; } @@ -556,6 +549,7 @@ void acpi_ut_dump_buffer(u8 * buffer, u32 count, u32 display, u32 component_id) } switch (display) { + case DB_BYTE_DISPLAY: default: /* Default is BYTE display */ acpi_os_printf("%02X ", buffer[i + j]); @@ -613,3 +607,31 @@ void acpi_ut_dump_buffer(u8 * buffer, u32 count, u32 display, u32 component_id) return; } + +/******************************************************************************* + * + * FUNCTION: acpi_ut_dump_buffer + * + * PARAMETERS: Buffer - Buffer to dump + * Count - Amount to dump, in bytes + * Display - BYTE, WORD, DWORD, or QWORD display + * component_iD - Caller's component ID + * + * RETURN: None + * + * DESCRIPTION: Generic dump buffer in both hex and ascii. + * + ******************************************************************************/ + +void acpi_ut_dump_buffer(u8 * buffer, u32 count, u32 display, u32 component_id) +{ + + /* Only dump the buffer if tracing is enabled */ + + if (!((ACPI_LV_TABLES & acpi_dbg_level) && + (component_id & acpi_dbg_layer))) { + return; + } + + acpi_ut_dump_buffer2(buffer, count, display); +} diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c index 51356e8eb99..b4e34a2f81f 100644 --- a/drivers/acpi/utilities/utdelete.c +++ b/drivers/acpi/utilities/utdelete.c @@ -202,8 +202,20 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object) if (handler_desc) { if (handler_desc->address_space.handler_flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) { - obj_pointer = - second_desc->extra.region_context; + + /* Deactivate region and free region context */ + + if (handler_desc->address_space.setup) { + (void)handler_desc-> + address_space.setup(object, + ACPI_REGION_DEACTIVATE, + handler_desc-> + address_space. + context, + &second_desc-> + extra. + region_context); + } } acpi_ut_remove_reference(handler_desc); diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c index 8a05bb5ef4f..e8ae417c984 100644 --- a/drivers/acpi/utilities/utglobal.c +++ b/drivers/acpi/utilities/utglobal.c @@ -642,7 +642,7 @@ char *acpi_ut_get_node_name(void *object) /* Name must be a valid ACPI name */ if (!acpi_ut_valid_acpi_name(node->name.integer)) { - return ("????"); + node->name.integer = acpi_ut_repair_name(node->name.integer); } /* Return the name */ diff --git a/drivers/acpi/utilities/utinit.c b/drivers/acpi/utilities/utinit.c index 40313de6977..7538b165b6e 100644 --- a/drivers/acpi/utilities/utinit.c +++ b/drivers/acpi/utilities/utinit.c @@ -50,7 +50,7 @@ ACPI_MODULE_NAME("utinit") /* Local prototypes */ static void -acpi_ut_fadt_register_error(char *register_name, u32 value, acpi_size offset); +acpi_ut_fadt_register_error(char *register_name, u32 value, u8 offset); static void acpi_ut_terminate(void); @@ -69,12 +69,12 @@ static void acpi_ut_terminate(void); ******************************************************************************/ static void -acpi_ut_fadt_register_error(char *register_name, u32 value, acpi_size offset) +acpi_ut_fadt_register_error(char *register_name, u32 value, u8 offset) { ACPI_WARNING((AE_INFO, "Invalid FADT value %s=%X at offset %X FADT=%p", - register_name, value, (u32) offset, acpi_gbl_FADT)); + register_name, value, offset, acpi_gbl_FADT)); } /****************************************************************************** diff --git a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c index 017a87ebc40..4623d7e215d 100644 --- a/drivers/acpi/utilities/utmisc.c +++ b/drivers/acpi/utilities/utmisc.c @@ -47,6 +47,33 @@ #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utmisc") +/******************************************************************************* + * + * FUNCTION: acpi_ut_is_aml_table + * + * PARAMETERS: Table - An ACPI table + * + * RETURN: TRUE if table contains executable AML; FALSE otherwise + * + * DESCRIPTION: Check ACPI Signature for a table that contains AML code. + * Currently, these are DSDT,SSDT,PSDT. All other table types are + * data tables that do not contain AML code. + * + ******************************************************************************/ +u8 acpi_ut_is_aml_table(struct acpi_table_header *table) +{ + + /* Ignore tables that contain AML */ + + if (ACPI_COMPARE_NAME(table->signature, DSDT_SIG) || + ACPI_COMPARE_NAME(table->signature, PSDT_SIG) || + ACPI_COMPARE_NAME(table->signature, SSDT_SIG)) { + return (TRUE); + } + + return (FALSE); +} + /******************************************************************************* * * FUNCTION: acpi_ut_allocate_owner_id @@ -60,6 +87,7 @@ ACPI_MODULE_NAME("utmisc") * when the method exits or the table is unloaded. * ******************************************************************************/ + acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id) { acpi_native_uint i; @@ -467,6 +495,41 @@ acpi_ut_display_init_pathname(u8 type, } #endif +/******************************************************************************* + * + * FUNCTION: acpi_ut_valid_acpi_char + * + * PARAMETERS: Char - The character to be examined + * + * RETURN: TRUE if the character is valid, FALSE otherwise + * + * DESCRIPTION: Check for a valid ACPI character. Must be one of: + * 1) Upper case alpha + * 2) numeric + * 3) underscore + * + * We allow a '!' as the last character because of the ASF! table + * + ******************************************************************************/ + +u8 acpi_ut_valid_acpi_char(char character, acpi_native_uint position) +{ + + if (!((character >= 'A' && character <= 'Z') || + (character >= '0' && character <= '9') || (character == '_'))) { + + /* Allow a '!' in the last position */ + + if (character == '!' && position == 3) { + return (TRUE); + } + + return (FALSE); + } + + return (TRUE); +} + /******************************************************************************* * * FUNCTION: acpi_ut_valid_acpi_name @@ -484,19 +547,13 @@ acpi_ut_display_init_pathname(u8 type, u8 acpi_ut_valid_acpi_name(u32 name) { - char *name_ptr = (char *)&name; - char character; acpi_native_uint i; ACPI_FUNCTION_ENTRY(); for (i = 0; i < ACPI_NAME_SIZE; i++) { - character = *name_ptr; - name_ptr++; - - if (!((character == '_') || - (character >= 'A' && character <= 'Z') || - (character >= '0' && character <= '9'))) { + if (!acpi_ut_valid_acpi_char + ((ACPI_CAST_PTR(char, &name))[i], i)) { return (FALSE); } } @@ -506,24 +563,37 @@ u8 acpi_ut_valid_acpi_name(u32 name) /******************************************************************************* * - * FUNCTION: acpi_ut_valid_acpi_character + * FUNCTION: acpi_ut_repair_name * - * PARAMETERS: Character - The character to be examined + * PARAMETERS: Name - The ACPI name to be repaired * - * RETURN: 1 if Character may appear in a name, else 0 + * RETURN: Repaired version of the name * - * DESCRIPTION: Check for a printable character + * DESCRIPTION: Repair an ACPI name: Change invalid characters to '*' and + * return the new name. * ******************************************************************************/ -u8 acpi_ut_valid_acpi_character(char character) +acpi_name acpi_ut_repair_name(acpi_name name) { + char *name_ptr = ACPI_CAST_PTR(char, &name); + char new_name[ACPI_NAME_SIZE]; + acpi_native_uint i; - ACPI_FUNCTION_ENTRY(); + for (i = 0; i < ACPI_NAME_SIZE; i++) { + new_name[i] = name_ptr[i]; + + /* + * Replace a bad character with something printable, yet technically + * still invalid. This prevents any collisions with existing "good" + * names in the namespace. + */ + if (!acpi_ut_valid_acpi_char(name_ptr[i], i)) { + new_name[i] = '*'; + } + } - return ((u8) ((character == '_') || - (character >= 'A' && character <= 'Z') || - (character >= '0' && character <= '9'))); + return (*ACPI_CAST_PTR(u32, new_name)); } /******************************************************************************* diff --git a/drivers/acpi/utilities/utresrc.c b/drivers/acpi/utilities/utresrc.c index 4c24e6d5400..1e680794c6d 100644 --- a/drivers/acpi/utilities/utresrc.c +++ b/drivers/acpi/utilities/utresrc.c @@ -258,7 +258,7 @@ static const u8 acpi_gbl_resource_types[] = { acpi_status acpi_ut_walk_aml_resources(u8 * aml, acpi_size aml_length, - acpi_walk_aml_callback user_function, void *context) + acpi_walk_aml_callback user_function, void **context) { acpi_status status; u8 *end_aml; @@ -319,7 +319,7 @@ acpi_ut_walk_aml_resources(u8 * aml, /* Return the pointer to the end_tag if requested */ if (!user_function) { - *(void **)context = aml; + *context = aml; } /* Normal exit */ @@ -610,7 +610,7 @@ acpi_ut_get_resource_end_tag(union acpi_operand_object * obj_desc, status = acpi_ut_walk_aml_resources(obj_desc->buffer.pointer, obj_desc->buffer.length, NULL, - end_tag); + (void **)end_tag); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/utilities/utstate.c b/drivers/acpi/utilities/utstate.c index 637c5f96487..aec5034cd97 100644 --- a/drivers/acpi/utilities/utstate.c +++ b/drivers/acpi/utilities/utstate.c @@ -321,8 +321,8 @@ union acpi_generic_state *acpi_ut_create_control_state(void) * * RETURN: None * - * DESCRIPTION: Put a state object back into the global state cache. The object - * is not actually freed at this time. + * DESCRIPTION: Release a state object to the state cache. NULL state objects + * are ignored. * ******************************************************************************/ @@ -330,6 +330,10 @@ void acpi_ut_delete_generic_state(union acpi_generic_state *state) { ACPI_FUNCTION_TRACE("ut_delete_generic_state"); - (void)acpi_os_release_object(acpi_gbl_state_cache, state); + /* Ignore null state */ + + if (state) { + (void)acpi_os_release_object(acpi_gbl_state_cache, state); + } return_VOID; } diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h index f3acfd9249f..b6bba7db52d 100644 --- a/include/acpi/acconfig.h +++ b/include/acpi/acconfig.h @@ -63,7 +63,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20060317 +#define ACPI_CA_VERSION 0x20060331 /* * OS name, used for the _OS object. The _OS object is essentially obsolete, diff --git a/include/acpi/acdisasm.h b/include/acpi/acdisasm.h index f004461a775..70b52ffa969 100644 --- a/include/acpi/acdisasm.h +++ b/include/acpi/acdisasm.h @@ -59,14 +59,52 @@ struct acpi_external_list { extern struct acpi_external_list *acpi_gbl_external_list; -/* Strings used for decoding flags to ASL keywords */ +typedef const struct acpi_dmtable_info { + u8 opcode; + u8 offset; + char *name; -extern const char *acpi_gbl_word_decode[4]; -extern const char *acpi_gbl_irq_decode[2]; -extern const char *acpi_gbl_lock_rule[ACPI_NUM_LOCK_RULES]; -extern const char *acpi_gbl_access_types[ACPI_NUM_ACCESS_TYPES]; -extern const char *acpi_gbl_update_rules[ACPI_NUM_UPDATE_RULES]; -extern const char *acpi_gbl_match_ops[ACPI_NUM_MATCH_OPS]; +} acpi_dmtable_info; + +/* + * Values for Opcode above. + * Note: 0-7 must not change, used as a flag shift value + */ +#define ACPI_DMT_FLAG0 0 +#define ACPI_DMT_FLAG1 1 +#define ACPI_DMT_FLAG2 2 +#define ACPI_DMT_FLAG3 3 +#define ACPI_DMT_FLAG4 4 +#define ACPI_DMT_FLAG5 5 +#define ACPI_DMT_FLAG6 6 +#define ACPI_DMT_FLAG7 7 +#define ACPI_DMT_FLAGS0 8 +#define ACPI_DMT_FLAGS2 9 +#define ACPI_DMT_UINT8 10 +#define ACPI_DMT_UINT16 11 +#define ACPI_DMT_UINT24 12 +#define ACPI_DMT_UINT32 13 +#define ACPI_DMT_UINT56 14 +#define ACPI_DMT_UINT64 15 +#define ACPI_DMT_STRING 16 +#define ACPI_DMT_NAME4 17 +#define ACPI_DMT_NAME6 18 +#define ACPI_DMT_NAME8 19 +#define ACPI_DMT_CHKSUM 20 +#define ACPI_DMT_SPACEID 21 +#define ACPI_DMT_GAS 22 +#define ACPI_DMT_MADT 23 +#define ACPI_DMT_SRAT 24 +#define ACPI_DMT_EXIT 25 + +typedef +void (*ACPI_TABLE_HANDLER) (struct acpi_table_header * table); + +struct acpi_dmtable_data { + char *signature; + struct acpi_dmtable_info *table_info; + ACPI_TABLE_HANDLER table_handler; +}; struct acpi_op_walk_info { u32 level; @@ -84,6 +122,95 @@ struct acpi_resource_tag { char *tag; }; +/* Strings used for decoding flags to ASL keywords */ + +extern const char *acpi_gbl_word_decode[4]; +extern const char *acpi_gbl_irq_decode[2]; +extern const char *acpi_gbl_lock_rule[ACPI_NUM_LOCK_RULES]; +extern const char *acpi_gbl_access_types[ACPI_NUM_ACCESS_TYPES]; +extern const char *acpi_gbl_update_rules[ACPI_NUM_UPDATE_RULES]; +extern const char *acpi_gbl_match_ops[ACPI_NUM_MATCH_OPS]; + +extern struct acpi_dmtable_info acpi_dm_table_info_asf0[]; +extern struct acpi_dmtable_info acpi_dm_table_info_asf1[]; +extern struct acpi_dmtable_info acpi_dm_table_info_asf2[]; +extern struct acpi_dmtable_info acpi_dm_table_info_asf3[]; +extern struct acpi_dmtable_info acpi_dm_table_info_asf4[]; +extern struct acpi_dmtable_info acpi_dm_table_info_asf_hdr[]; +extern struct acpi_dmtable_info acpi_dm_table_info_boot[]; +extern struct acpi_dmtable_info acpi_dm_table_info_cpep[]; +extern struct acpi_dmtable_info acpi_dm_table_info_cpep0[]; +extern struct acpi_dmtable_info acpi_dm_table_info_dbgp[]; +extern struct acpi_dmtable_info acpi_dm_table_info_ecdt[]; +extern struct acpi_dmtable_info acpi_dm_table_info_facs[]; +extern struct acpi_dmtable_info acpi_dm_table_info_fadt1[]; +extern struct acpi_dmtable_info acpi_dm_table_info_fadt2[]; +extern struct acpi_dmtable_info acpi_dm_table_info_gas[]; +extern struct acpi_dmtable_info acpi_dm_table_info_header[]; +extern struct acpi_dmtable_info acpi_dm_table_info_hpet[]; +extern struct acpi_dmtable_info acpi_dm_table_info_madt[]; +extern struct acpi_dmtable_info acpi_dm_table_info_madt0[]; +extern struct acpi_dmtable_info acpi_dm_table_info_madt1[]; +extern struct acpi_dmtable_info acpi_dm_table_info_madt2[]; +extern struct acpi_dmtable_info acpi_dm_table_info_madt3[]; +extern struct acpi_dmtable_info acpi_dm_table_info_madt4[]; +extern struct acpi_dmtable_info acpi_dm_table_info_madt5[]; +extern struct acpi_dmtable_info acpi_dm_table_info_madt6[]; +extern struct acpi_dmtable_info acpi_dm_table_info_madt7[]; +extern struct acpi_dmtable_info acpi_dm_table_info_madt8[]; +extern struct acpi_dmtable_info acpi_dm_table_info_madt_hdr[]; +extern struct acpi_dmtable_info acpi_dm_table_info_mcfg[]; +extern struct acpi_dmtable_info acpi_dm_table_info_mcfg0[]; +extern struct acpi_dmtable_info acpi_dm_table_info_rsdp1[]; +extern struct acpi_dmtable_info acpi_dm_table_info_rsdp2[]; +extern struct acpi_dmtable_info acpi_dm_table_info_sbst[]; +extern struct acpi_dmtable_info acpi_dm_table_info_slit[]; +extern struct acpi_dmtable_info acpi_dm_table_info_spcr[]; +extern struct acpi_dmtable_info acpi_dm_table_info_spmi[]; +extern struct acpi_dmtable_info acpi_dm_table_info_srat[]; +extern struct acpi_dmtable_info acpi_dm_table_info_srat0[]; +extern struct acpi_dmtable_info acpi_dm_table_info_srat1[]; +extern struct acpi_dmtable_info acpi_dm_table_info_tcpa[]; +extern struct acpi_dmtable_info acpi_dm_table_info_wdrt[]; + +/* + * dmtable + */ +void acpi_dm_dump_data_table(struct acpi_table_header *table); + +void +acpi_dm_dump_table(u32 table_length, + u32 table_offset, + void *table, + u32 sub_table_length, struct acpi_dmtable_info *info); + +void acpi_dm_line_header(u32 offset, u32 byte_length, char *name); + +void acpi_dm_line_header2(u32 offset, u32 byte_length, char *name, u32 value); + +/* + * dmtbdump + */ +void acpi_dm_dump_asf(struct acpi_table_header *table); + +void acpi_dm_dump_cpep(struct acpi_table_header *table); + +void acpi_dm_dump_fadt(struct acpi_table_header *table); + +void acpi_dm_dump_srat(struct acpi_table_header *table); + +void acpi_dm_dump_mcfg(struct acpi_table_header *table); + +void acpi_dm_dump_madt(struct acpi_table_header *table); + +u32 acpi_dm_dump_rsdp(struct acpi_table_header *table); + +void acpi_dm_dump_rsdt(struct acpi_table_header *table); + +void acpi_dm_dump_slit(struct acpi_table_header *table); + +void acpi_dm_dump_xsdt(struct acpi_table_header *table); + /* * dmwalk */ diff --git a/include/acpi/acglobal.h b/include/acpi/acglobal.h index f9eb5925511..17c5b462676 100644 --- a/include/acpi/acglobal.h +++ b/include/acpi/acglobal.h @@ -107,6 +107,7 @@ ACPI_EXTERN u32 acpi_gbl_trace_flags; * 3) Allow access to uninitialized locals/args (auto-init to integer 0) * 4) Allow ANY object type to be a source operand for the Store() operator * 5) Allow unresolved references (invalid target name) in package objects + * 6) Enable warning messages for behavior that is not ACPI spec compliant */ ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_enable_interpreter_slack, FALSE); @@ -149,10 +150,10 @@ ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_leave_wake_gpes_disabled, TRUE); ACPI_EXTERN u32 acpi_gbl_table_flags; ACPI_EXTERN u32 acpi_gbl_rsdt_table_count; ACPI_EXTERN struct rsdp_descriptor *acpi_gbl_RSDP; -ACPI_EXTERN XSDT_DESCRIPTOR *acpi_gbl_XSDT; -ACPI_EXTERN FADT_DESCRIPTOR *acpi_gbl_FADT; +ACPI_EXTERN struct xsdt_descriptor *acpi_gbl_XSDT; +ACPI_EXTERN struct fadt_descriptor *acpi_gbl_FADT; ACPI_EXTERN struct acpi_table_header *acpi_gbl_DSDT; -ACPI_EXTERN FACS_DESCRIPTOR *acpi_gbl_FACS; +ACPI_EXTERN struct facs_descriptor *acpi_gbl_FACS; ACPI_EXTERN struct acpi_common_facs acpi_gbl_common_fACS; /* * Since there may be multiple SSDTs and PSDTs, a single pointer is not diff --git a/include/acpi/aclocal.h b/include/acpi/aclocal.h index 5956431784d..99785bae59b 100644 --- a/include/acpi/aclocal.h +++ b/include/acpi/aclocal.h @@ -174,22 +174,28 @@ union acpi_name_union { * * The node is optimized for both 32-bit and 64-bit platforms: * 20 bytes for the 32-bit case, 32 bytes for the 64-bit case. + * + * Note: The descriptor_type and Type fields must appear in the identical + * position in both the struct acpi_namespace_node and union acpi_operand_object + * structures. */ struct acpi_namespace_node { union acpi_operand_object *object; /* Interpreter object */ u8 descriptor_type; /* Differentiate object descriptor types */ + u8 type; /* ACPI Type associated with this name */ u8 flags; /* Miscellaneous flags */ acpi_owner_id owner_id; /* Node creator */ - u8 type; /* ACPI Type associated with this name */ union acpi_name_union name; /* ACPI Name, always 4 chars per ACPI spec */ struct acpi_namespace_node *child; /* First child */ struct acpi_namespace_node *peer; /* Peer. Parent if ANOBJ_END_OF_PEER_LIST set */ - /* Fields used by the ASL compiler and disassembler only: */ - + /* + * The following fields are used by the ASL compiler and disassembler only + */ #ifdef ACPI_LARGE_NAMESPACE_NODE union acpi_parse_object *op; u32 value; + u32 length; #endif }; @@ -470,7 +476,7 @@ struct acpi_scope_state { }; struct acpi_pscope_state { - ACPI_STATE_COMMON u8 arg_count; /* Number of fixed arguments */ + ACPI_STATE_COMMON u32 arg_count; /* Number of fixed arguments */ union acpi_parse_object *op; /* Current op being parsed */ u8 *arg_end; /* Current argument end */ u8 *pkg_end; /* Current package end */ diff --git a/include/acpi/acmacros.h b/include/acpi/acmacros.h index c495670aa11..60ceed4c81b 100644 --- a/include/acpi/acmacros.h +++ b/include/acpi/acmacros.h @@ -130,7 +130,6 @@ #define ACPI_TO_POINTER(i) ACPI_ADD_PTR (void,(void *) NULL,(acpi_native_uint) i) #define ACPI_TO_INTEGER(p) ACPI_PTR_DIFF (p,(void *) NULL) #define ACPI_OFFSET(d,f) (acpi_size) ACPI_PTR_DIFF (&(((d *)0)->f),(void *) NULL) -#define ACPI_FADT_OFFSET(f) ACPI_OFFSET (FADT_DESCRIPTOR, f) #if ACPI_MACHINE_WIDTH == 16 #define ACPI_STORE_POINTER(d,s) ACPI_MOVE_32_TO_32(d,s) @@ -141,6 +140,12 @@ #define ACPI_PTR_TO_PHYSADDR(i) ACPI_TO_INTEGER(i) #endif +#ifndef ACPI_MISALIGNMENT_NOT_SUPPORTED +#define ACPI_COMPARE_NAME(a,b) (*ACPI_CAST_PTR (u32,(a)) == *ACPI_CAST_PTR (u32,(b))) +#else +#define ACPI_COMPARE_NAME(a,b) (!ACPI_STRNCMP (ACPI_CAST_PTR (char,(a)), ACPI_CAST_PTR (char,(b)), 4)) +#endif + /* * Macros for moving data around to/from buffers that are possibly unaligned. * If the hardware supports the transfer of unaligned data, just do the store. diff --git a/include/acpi/acobject.h b/include/acpi/acobject.h index 28241aa15de..d9442d346b9 100644 --- a/include/acpi/acobject.h +++ b/include/acpi/acobject.h @@ -65,6 +65,10 @@ * * descriptor_type is used to differentiate between internal descriptors, and * must be in the same place across all descriptors + * + * Note: The descriptor_type and Type fields must appear in the identical + * position in both the struct acpi_namespace_node and union acpi_operand_object + * structures. */ #define ACPI_OBJECT_COMMON_HEADER \ union acpi_operand_object *next_object; /* Objects linked to parent NS node */\ diff --git a/include/acpi/acparser.h b/include/acpi/acparser.h index 53ac4ce8753..de14492a598 100644 --- a/include/acpi/acparser.h +++ b/include/acpi/acparser.h @@ -46,9 +46,9 @@ #define OP_HAS_RETURN_VALUE 1 -/* variable # arguments */ +/* Variable number of arguments. This field must be 32 bits */ -#define ACPI_VAR_ARGS ACPI_UINT8_MAX +#define ACPI_VAR_ARGS ACPI_UINT32_MAX #define ACPI_PARSE_DELETE_TREE 0x0001 #define ACPI_PARSE_NO_TREE_DELETE 0x0000 @@ -146,12 +146,13 @@ u8 acpi_ps_has_completed_scope(struct acpi_parse_state *parser_state); void acpi_ps_pop_scope(struct acpi_parse_state *parser_state, - union acpi_parse_object **op, u32 * arg_list, u8 * arg_count); + union acpi_parse_object **op, + u32 * arg_list, u32 * arg_count); acpi_status acpi_ps_push_scope(struct acpi_parse_state *parser_state, union acpi_parse_object *op, - u32 remaining_args, u8 arg_count); + u32 remaining_args, u32 arg_count); void acpi_ps_cleanup_scope(struct acpi_parse_state *state); diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 6dca3d54208..43f8c2a23a2 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -59,7 +59,7 @@ acpi_evaluate_reference(acpi_handle handle, #define ACPI_BUS_FILE_ROOT "acpi" extern struct proc_dir_entry *acpi_root_dir; -extern FADT_DESCRIPTOR acpi_fadt; +extern struct fadt_descriptor acpi_fadt; enum acpi_bus_removal_type { ACPI_BUS_REMOVAL_NORMAL = 0, diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h index 91c3cdff28b..42307d948c1 100644 --- a/include/acpi/acpiosxf.h +++ b/include/acpi/acpiosxf.h @@ -169,8 +169,6 @@ acpi_os_queue_for_execution(u32 priority, void acpi_os_wait_events_complete(void *context); -void acpi_os_wait_events_complete(void *context); - void acpi_os_sleep(acpi_integer milliseconds); void acpi_os_stall(u32 microseconds); diff --git a/include/acpi/acstruct.h b/include/acpi/acstruct.h index 04e8966a377..b8a6d6110d5 100644 --- a/include/acpi/acstruct.h +++ b/include/acpi/acstruct.h @@ -86,7 +86,7 @@ struct acpi_walk_state { struct acpi_parse_state parser_state; /* Current state of parser */ u32 prev_arg_types; - u8 arg_count; /* push for fixed or var args */ + u32 arg_count; /* push for fixed or var args */ struct acpi_namespace_node arguments[ACPI_METHOD_NUM_ARGS]; /* Control method arguments */ struct acpi_namespace_node local_variables[ACPI_METHOD_NUM_LOCALS]; /* Control method locals */ diff --git a/include/acpi/actables.h b/include/acpi/actables.h index 30a47542e1c..4dbaf02fe52 100644 --- a/include/acpi/actables.h +++ b/include/acpi/actables.h @@ -136,7 +136,11 @@ acpi_status acpi_tb_is_table_installed(struct acpi_table_desc *new_table_desc); acpi_status acpi_tb_verify_table_checksum(struct acpi_table_header *table_header); -u8 acpi_tb_generate_checksum(void *buffer, u32 length); +u8 acpi_tb_sum_table(void *buffer, u32 length); + +u8 acpi_tb_generate_checksum(struct acpi_table_header *table); + +void acpi_tb_set_checksum(struct acpi_table_header *table); acpi_status acpi_tb_validate_table_header(struct acpi_table_header *table_header); diff --git a/include/acpi/actbl.h b/include/acpi/actbl.h index ed53f842dad..e1a40135f70 100644 --- a/include/acpi/actbl.h +++ b/include/acpi/actbl.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Name: actbl.h - Table data structures defined in ACPI specification + * Name: actbl.h - Basic ACPI Table Definitions * *****************************************************************************/ @@ -45,66 +45,45 @@ #define __ACTBL_H__ /* - * Note about bitfields: The u8 type is used for bitfields in ACPI tables. - * This is the only type that is even remotely portable. Anything else is not - * portable, so do not use any other bitfield types. - */ - -/* - * Values for description table header signatures + * Values for description table header signatures. Useful because they make + * it more difficult to inadvertently type in the wrong signature. */ -#define RSDP_NAME "RSDP" -#define RSDP_SIG "RSD PTR " /* RSDT Pointer signature */ -#define APIC_SIG "APIC" /* Multiple APIC Description Table */ #define DSDT_SIG "DSDT" /* Differentiated System Description Table */ #define FADT_SIG "FACP" /* Fixed ACPI Description Table */ #define FACS_SIG "FACS" /* Firmware ACPI Control Structure */ #define PSDT_SIG "PSDT" /* Persistent System Description Table */ +#define RSDP_SIG "RSD PTR " /* Root System Description Pointer */ #define RSDT_SIG "RSDT" /* Root System Description Table */ #define XSDT_SIG "XSDT" /* Extended System Description Table */ #define SSDT_SIG "SSDT" /* Secondary System Description Table */ -#define SBST_SIG "SBST" /* Smart Battery Specification Table */ -#define SPIC_SIG "SPIC" /* IOSAPIC table */ -#define BOOT_SIG "BOOT" /* Boot table */ - -#define GL_OWNED 0x02 /* Ownership of global lock is bit 1 */ +#define RSDP_NAME "RSDP" /* - * Common table types. The base code can remain - * constant if the underlying tables are changed + * All tables and structures must be byte-packed to match the ACPI + * specification, since the tables are provided by the system BIOS */ -#define RSDT_DESCRIPTOR struct rsdt_descriptor_rev2 -#define XSDT_DESCRIPTOR struct xsdt_descriptor_rev2 -#define FACS_DESCRIPTOR struct facs_descriptor_rev2 -#define FADT_DESCRIPTOR struct fadt_descriptor_rev2 - #pragma pack(1) /* - * ACPI Version-independent tables + * These are the ACPI tables that are directly consumed by the subsystem. + * + * The RSDP and FACS do not use the common ACPI table header. All other ACPI + * tables use the header. * - * NOTE: The tables that are specific to ACPI versions (1.0, 2.0, etc.) - * are in separate files. + * Note about bitfields: The u8 type is used for bitfields in ACPI tables. + * This is the only type that is even remotely portable. Anything else is not + * portable, so do not use any other bitfield types. */ -struct rsdp_descriptor { /* Root System Descriptor Pointer */ - char signature[8]; /* ACPI signature, contains "RSD PTR " */ - u8 checksum; /* ACPI 1.0 checksum */ - char oem_id[6]; /* OEM identification */ - u8 revision; /* Must be (0) for ACPI 1.0 or (2) for ACPI 2.0+ */ - u32 rsdt_physical_address; /* 32-bit physical address of the RSDT */ - u32 length; /* XSDT Length in bytes, including header */ - u64 xsdt_physical_address; /* 64-bit physical address of the XSDT */ - u8 extended_checksum; /* Checksum of entire table (ACPI 2.0) */ - char reserved[3]; /* Reserved, must be zero */ -}; -struct acpi_common_facs { /* Common FACS for internal use */ - u32 *global_lock; - u64 *firmware_waking_vector; - u8 vector_width; -}; +/******************************************************************************* + * + * ACPI Table Header. This common header is used by all tables except the + * RSDP and FACS. The define is used for direct inclusion of header into + * other ACPI tables + * + ******************************************************************************/ -#define ACPI_TABLE_HEADER_DEF /* ACPI common table header */ \ +#define ACPI_TABLE_HEADER_DEF \ char signature[4]; /* ASCII table signature */\ u32 length; /* Length of table in bytes, including this header */\ u8 revision; /* ACPI Specification minor version # */\ @@ -112,153 +91,238 @@ struct acpi_common_facs { /* Common FACS for internal use */ char oem_id[6]; /* ASCII OEM identification */\ char oem_table_id[8]; /* ASCII OEM table identification */\ u32 oem_revision; /* OEM revision number */\ - char asl_compiler_id [4]; /* ASCII ASL compiler vendor ID */\ + char asl_compiler_id[4]; /* ASCII ASL compiler vendor ID */\ u32 asl_compiler_revision; /* ASL compiler version */ -struct acpi_table_header { /* ACPI common table header */ +struct acpi_table_header { ACPI_TABLE_HEADER_DEF}; /* - * MADT values and structures + * GAS - Generic Address Structure (ACPI 2.0+) */ +struct acpi_generic_address { + u8 address_space_id; /* Address space where struct or register exists */ + u8 register_bit_width; /* Size in bits of given register */ + u8 register_bit_offset; /* Bit offset within the register */ + u8 access_width; /* Minimum Access size (ACPI 3.0) */ + u64 address; /* 64-bit address of struct or register */ +}; -/* Values for MADT PCATCompat */ +/******************************************************************************* + * + * RSDP - Root System Description Pointer (Signature is "RSD PTR ") + * + ******************************************************************************/ + +struct rsdp_descriptor { + char signature[8]; /* ACPI signature, contains "RSD PTR " */ + u8 checksum; /* ACPI 1.0 checksum */ + char oem_id[6]; /* OEM identification */ + u8 revision; /* Must be (0) for ACPI 1.0 or (2) for ACPI 2.0+ */ + u32 rsdt_physical_address; /* 32-bit physical address of the RSDT */ + u32 length; /* Table length in bytes, including header (ACPI 2.0+) */ + u64 xsdt_physical_address; /* 64-bit physical address of the XSDT (ACPI 2.0+) */ + u8 extended_checksum; /* Checksum of entire table (ACPI 2.0+) */ + u8 reserved[3]; /* Reserved, must be zero */ +}; -#define DUAL_PIC 0 -#define MULTIPLE_APIC 1 +#define ACPI_RSDP_REV0_SIZE 20 /* Size of original ACPI 1.0 RSDP */ -/* Master MADT */ +/******************************************************************************* + * + * RSDT/XSDT - Root System Description Tables + * + ******************************************************************************/ -struct multiple_apic_table { - ACPI_TABLE_HEADER_DEF /* ACPI common table header */ - u32 local_apic_address; /* Physical address of local APIC */ +struct rsdt_descriptor { + ACPI_TABLE_HEADER_DEF u32 table_offset_entry[1]; /* Array of pointers to ACPI tables */ +}; + +struct xsdt_descriptor { + ACPI_TABLE_HEADER_DEF u64 table_offset_entry[1]; /* Array of pointers to ACPI tables */ +}; + +/******************************************************************************* + * + * FACS - Firmware ACPI Control Structure (FACS) + * + ******************************************************************************/ + +struct facs_descriptor { + char signature[4]; /* ASCII table signature */ + u32 length; /* Length of structure, in bytes */ + u32 hardware_signature; /* Hardware configuration signature */ + u32 firmware_waking_vector; /* 32-bit physical address of the Firmware Waking Vector */ + u32 global_lock; /* Global Lock for shared hardware resources */ /* Flags (32 bits) */ - u8 PCATcompat:1; /* 00: System also has dual 8259s */ + u8 S4bios_f:1; /* 00: S4BIOS support is present */ u8:7; /* 01-07: Reserved, must be zero */ u8 reserved1[3]; /* 08-31: Reserved, must be zero */ -}; -/* Values for Type in APIC_HEADER_DEF */ + u64 xfirmware_waking_vector; /* 64-bit version of the Firmware Waking Vector (ACPI 2.0+) */ + u8 version; /* Version of this table (ACPI 2.0+) */ + u8 reserved[31]; /* Reserved, must be zero */ +}; -#define APIC_PROCESSOR 0 -#define APIC_IO 1 -#define APIC_XRUPT_OVERRIDE 2 -#define APIC_NMI 3 -#define APIC_LOCAL_NMI 4 -#define APIC_ADDRESS_OVERRIDE 5 -#define APIC_IO_SAPIC 6 -#define APIC_LOCAL_SAPIC 7 -#define APIC_XRUPT_SOURCE 8 -#define APIC_RESERVED 9 /* 9 and greater are reserved */ +#define ACPI_GLOCK_PENDING 0x01 /* 00: Pending global lock ownership */ +#define ACPI_GLOCK_OWNED 0x02 /* 01: Global lock is owned */ /* - * MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE) + * Common FACS - This is a version-independent FACS structure used for internal use only */ -#define APIC_HEADER_DEF /* Common APIC sub-structure header */\ - u8 type; \ - u8 length; - -struct apic_header { -APIC_HEADER_DEF}; - -/* Values for MPS INTI flags */ - -#define POLARITY_CONFORMS 0 -#define POLARITY_ACTIVE_HIGH 1 -#define POLARITY_RESERVED 2 -#define POLARITY_ACTIVE_LOW 3 - -#define TRIGGER_CONFORMS 0 -#define TRIGGER_EDGE 1 -#define TRIGGER_RESERVED 2 -#define TRIGGER_LEVEL 3 - -/* Common flag definitions (16 bits each) */ - -#define MPS_INTI_FLAGS \ - u8 polarity : 2; /* 00-01: Polarity of APIC I/O input signals */\ - u8 trigger_mode : 2; /* 02-03: Trigger mode of APIC input signals */\ - u8 : 4; /* 04-07: Reserved, must be zero */\ - u8 reserved1; /* 08-15: Reserved, must be zero */ - -#define LOCAL_APIC_FLAGS \ - u8 processor_enabled: 1; /* 00: Processor is usable if set */\ - u8 : 7; /* 01-07: Reserved, must be zero */\ - u8 reserved2; /* 08-15: Reserved, must be zero */ - -/* Sub-structures for MADT */ - -struct madt_processor_apic { - APIC_HEADER_DEF u8 processor_id; /* ACPI processor id */ - u8 local_apic_id; /* Processor's local APIC id */ - LOCAL_APIC_FLAGS}; - -struct madt_io_apic { - APIC_HEADER_DEF u8 io_apic_id; /* I/O APIC ID */ - u8 reserved; /* Reserved - must be zero */ - u32 address; /* APIC physical address */ - u32 interrupt; /* Global system interrupt where INTI - * lines start */ +struct acpi_common_facs { + u32 *global_lock; + u64 *firmware_waking_vector; + u8 vector_width; }; -struct madt_interrupt_override { - APIC_HEADER_DEF u8 bus; /* 0 - ISA */ - u8 source; /* Interrupt source (IRQ) */ - u32 interrupt; /* Global system interrupt */ - MPS_INTI_FLAGS}; +/******************************************************************************* + * + * FADT - Fixed ACPI Description Table (Signature "FACP") + * + ******************************************************************************/ + +/* Fields common to all versions of the FADT */ + +#define ACPI_FADT_COMMON \ + ACPI_TABLE_HEADER_DEF \ + u32 V1_firmware_ctrl; /* 32-bit physical address of FACS */ \ + u32 V1_dsdt; /* 32-bit physical address of DSDT */ \ + u8 reserved1; /* System Interrupt Model isn't used in ACPI 2.0*/ \ + u8 prefer_PM_profile; /* Conveys preferred power management profile to OSPM. */ \ + u16 sci_int; /* System vector of SCI interrupt */ \ + u32 smi_cmd; /* Port address of SMI command port */ \ + u8 acpi_enable; /* Value to write to smi_cmd to enable ACPI */ \ + u8 acpi_disable; /* Value to write to smi_cmd to disable ACPI */ \ + u8 S4bios_req; /* Value to write to SMI CMD to enter S4BIOS state */ \ + u8 pstate_cnt; /* Processor performance state control*/ \ + u32 V1_pm1a_evt_blk; /* Port address of Power Mgt 1a Event Reg Blk */ \ + u32 V1_pm1b_evt_blk; /* Port address of Power Mgt 1b Event Reg Blk */ \ + u32 V1_pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */ \ + u32 V1_pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */ \ + u32 V1_pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */ \ + u32 V1_pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */ \ + u32 V1_gpe0_blk; /* Port addr of General Purpose acpi_event 0 Reg Blk */ \ + u32 V1_gpe1_blk; /* Port addr of General Purpose acpi_event 1 Reg Blk */ \ + u8 pm1_evt_len; /* Byte length of ports at pm1_x_evt_blk */ \ + u8 pm1_cnt_len; /* Byte length of ports at pm1_x_cnt_blk */ \ + u8 pm2_cnt_len; /* Byte Length of ports at pm2_cnt_blk */ \ + u8 pm_tm_len; /* Byte Length of ports at pm_tm_blk */ \ + u8 gpe0_blk_len; /* Byte Length of ports at gpe0_blk */ \ + u8 gpe1_blk_len; /* Byte Length of ports at gpe1_blk */ \ + u8 gpe1_base; /* Offset in gpe model where gpe1 events start */ \ + u8 cst_cnt; /* Support for the _CST object and C States change notification.*/ \ + u16 plvl2_lat; /* Worst case HW latency to enter/exit C2 state */ \ + u16 plvl3_lat; /* Worst case HW latency to enter/exit C3 state */ \ + u16 flush_size; /* Processor's memory cache line width, in bytes */ \ + u16 flush_stride; /* Number of flush strides that need to be read */ \ + u8 duty_offset; /* Processor's duty cycle index in processor's P_CNT reg*/ \ + u8 duty_width; /* Processor's duty cycle value bit width in P_CNT register.*/ \ + u8 day_alrm; /* Index to day-of-month alarm in RTC CMOS RAM */ \ + u8 mon_alrm; /* Index to month-of-year alarm in RTC CMOS RAM */ \ + u8 century; /* Index to century in RTC CMOS RAM */ \ + u16 iapc_boot_arch; /* IA-PC Boot Architecture Flags. See Table 5-10 for description*/ \ + u8 reserved2; /* Reserved, must be zero */ -struct madt_nmi_source { - APIC_HEADER_DEF MPS_INTI_FLAGS u32 interrupt; /* Global system interrupt */ +/* + * ACPI 2.0+ FADT + */ +struct fadt_descriptor { + ACPI_FADT_COMMON + /* Flags (32 bits) */ + u8 wb_invd:1; /* 00: The wbinvd instruction works properly */ + u8 wb_invd_flush:1; /* 01: The wbinvd flushes but does not invalidate */ + u8 proc_c1:1; /* 02: All processors support C1 state */ + u8 plvl2_up:1; /* 03: C2 state works on MP system */ + u8 pwr_button:1; /* 04: Power button is handled as a generic feature */ + u8 sleep_button:1; /* 05: Sleep button is handled as a generic feature, or not present */ + u8 fixed_rTC:1; /* 06: RTC wakeup stat not in fixed register space */ + u8 rtcs4:1; /* 07: RTC wakeup stat not possible from S4 */ + u8 tmr_val_ext:1; /* 08: tmr_val is 32 bits 0=24-bits */ + u8 dock_cap:1; /* 09: Docking supported */ + u8 reset_reg_sup:1; /* 10: System reset via the FADT RESET_REG supported */ + u8 sealed_case:1; /* 11: No internal expansion capabilities and case is sealed */ + u8 headless:1; /* 12: No local video capabilities or local input devices */ + u8 cpu_sw_sleep:1; /* 13: Must execute native instruction after writing SLP_TYPx register */ + + u8 pci_exp_wak:1; /* 14: System supports PCIEXP_WAKE (STS/EN) bits (ACPI 3.0) */ + u8 use_platform_clock:1; /* 15: OSPM should use platform-provided timer (ACPI 3.0) */ + u8 S4rtc_sts_valid:1; /* 16: Contents of RTC_STS valid after S4 wake (ACPI 3.0) */ + u8 remote_power_on_capable:1; /* 17: System is compatible with remote power on (ACPI 3.0) */ + u8 force_apic_cluster_model:1; /* 18: All local APICs must use cluster model (ACPI 3.0) */ + u8 force_apic_physical_destination_mode:1; /* 19: all local x_aPICs must use physical dest mode (ACPI 3.0) */ + u8:4; /* 20-23: Reserved, must be zero */ + u8 reserved3; /* 24-31: Reserved, must be zero */ + + struct acpi_generic_address reset_register; /* Reset register address in GAS format */ + u8 reset_value; /* Value to write to the reset_register port to reset the system */ + u8 reserved4[3]; /* These three bytes must be zero */ + u64 xfirmware_ctrl; /* 64-bit physical address of FACS */ + u64 Xdsdt; /* 64-bit physical address of DSDT */ + struct acpi_generic_address xpm1a_evt_blk; /* Extended Power Mgt 1a acpi_event Reg Blk address */ + struct acpi_generic_address xpm1b_evt_blk; /* Extended Power Mgt 1b acpi_event Reg Blk address */ + struct acpi_generic_address xpm1a_cnt_blk; /* Extended Power Mgt 1a Control Reg Blk address */ + struct acpi_generic_address xpm1b_cnt_blk; /* Extended Power Mgt 1b Control Reg Blk address */ + struct acpi_generic_address xpm2_cnt_blk; /* Extended Power Mgt 2 Control Reg Blk address */ + struct acpi_generic_address xpm_tmr_blk; /* Extended Power Mgt Timer Ctrl Reg Blk address */ + struct acpi_generic_address xgpe0_blk; /* Extended General Purpose acpi_event 0 Reg Blk address */ + struct acpi_generic_address xgpe1_blk; /* Extended General Purpose acpi_event 1 Reg Blk address */ }; -struct madt_local_apic_nmi { - APIC_HEADER_DEF u8 processor_id; /* ACPI processor id */ - MPS_INTI_FLAGS u8 lint; /* LINTn to which NMI is connected */ +/* + * "Down-revved" ACPI 2.0 FADT descriptor + * Defined here to allow compiler to generate the length of the struct + */ +struct fadt_descriptor_rev2_minus { + ACPI_FADT_COMMON u32 flags; + struct acpi_generic_address reset_register; /* Reset register address in GAS format */ + u8 reset_value; /* Value to write to the reset_register port to reset the system. */ + u8 reserved7[3]; /* Reserved, must be zero */ }; -struct madt_address_override { - APIC_HEADER_DEF u16 reserved; /* Reserved, must be zero */ - u64 address; /* APIC physical address */ +/* + * ACPI 1.0 FADT + * Defined here to allow compiler to generate the length of the struct + */ +struct fadt_descriptor_rev1 { + ACPI_FADT_COMMON u32 flags; }; -struct madt_io_sapic { - APIC_HEADER_DEF u8 io_sapic_id; /* I/O SAPIC ID */ - u8 reserved; /* Reserved, must be zero */ - u32 interrupt_base; /* Glocal interrupt for SAPIC start */ - u64 address; /* SAPIC physical address */ -}; +/* FADT: Prefered Power Management Profiles */ -struct madt_local_sapic { - APIC_HEADER_DEF u8 processor_id; /* ACPI processor id */ - u8 local_sapic_id; /* SAPIC ID */ - u8 local_sapic_eid; /* SAPIC EID */ - u8 reserved[3]; /* Reserved, must be zero */ - LOCAL_APIC_FLAGS u32 processor_uID; /* Numeric UID - ACPI 3.0 */ - char processor_uIDstring[1]; /* String UID - ACPI 3.0 */ -}; +#define PM_UNSPECIFIED 0 +#define PM_DESKTOP 1 +#define PM_MOBILE 2 +#define PM_WORKSTATION 3 +#define PM_ENTERPRISE_SERVER 4 +#define PM_SOHO_SERVER 5 +#define PM_APPLIANCE_PC 6 -struct madt_interrupt_source { - APIC_HEADER_DEF MPS_INTI_FLAGS u8 interrupt_type; /* 1=PMI, 2=INIT, 3=corrected */ - u8 processor_id; /* Processor ID */ - u8 processor_eid; /* Processor EID */ - u8 io_sapic_vector; /* Vector value for PMI interrupts */ - u32 interrupt; /* Global system interrupt */ - u32 flags; /* Interrupt Source Flags */ -}; +/* FADT: Boot Arch Flags */ -/* - * Smart Battery - */ -struct smart_battery_table { - ACPI_TABLE_HEADER_DEF u32 warning_level; - u32 low_level; - u32 critical_level; -}; +#define BAF_LEGACY_DEVICES 0x0001 +#define BAF_8042_KEYBOARD_CONTROLLER 0x0002 + +#define FADT2_REVISION_ID 3 +#define FADT2_MINUS_REVISION_ID 2 + +/* Reset to default packing */ #pragma pack() +/* + * This macro is temporary until the table bitfield flag definitions + * are removed and replaced by a Flags field. + */ +#define ACPI_FLAG_OFFSET(d,f,o) (u8) (ACPI_OFFSET (d,f) + \ + sizeof(((d *)0)->f) + o) +/* + * Get the remaining ACPI tables + */ +#include "actbl1.h" + /* * ACPI Table information. We save the table address, length, * and type of memory allocation (mapped or allocated) for each @@ -290,27 +354,17 @@ struct acpi_table_support { u8 flags; }; -/* - * Get the ACPI version-specific tables - */ -#include "actbl1.h" /* Acpi 1.0 table definitions */ -#include "actbl2.h" /* Acpi 2.0 table definitions */ - extern u8 acpi_fadt_is_v1; /* is set to 1 if FADT is revision 1, * needed for certain workarounds */ +/* Macros used to generate offsets to specific table fields */ -#pragma pack(1) -/* - * High performance timer - */ -struct hpet_table { - ACPI_TABLE_HEADER_DEF u32 hardware_id; - struct acpi_generic_address base_address; - u8 hpet_number; - u16 clock_tick; - u8 attributes; -}; +#define ACPI_FACS_OFFSET(f) (u8) ACPI_OFFSET (struct facs_descriptor,f) +#define ACPI_FADT_OFFSET(f) (u8) ACPI_OFFSET (struct fadt_descriptor, f) +#define ACPI_GAS_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_generic_address,f) +#define ACPI_HDR_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_table_header,f) +#define ACPI_RSDP_OFFSET(f) (u8) ACPI_OFFSET (struct rsdp_descriptor,f) -#pragma pack() +#define ACPI_FADT_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct fadt_descriptor,f,o) +#define ACPI_FACS_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct facs_descriptor,f,o) #endif /* __ACTBL_H__ */ diff --git a/include/acpi/actbl1.h b/include/acpi/actbl1.h index cd428d57add..745a6445a4f 100644 --- a/include/acpi/actbl1.h +++ b/include/acpi/actbl1.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Name: actbl1.h - ACPI 1.0 tables + * Name: actbl1.h - Additional ACPI table definitions * *****************************************************************************/ @@ -44,92 +44,599 @@ #ifndef __ACTBL1_H__ #define __ACTBL1_H__ +/******************************************************************************* + * + * Additional ACPI Tables + * + * These tables are not consumed directly by the ACPICA subsystem, but are + * included here to support device drivers and the AML disassembler. + * + ******************************************************************************/ + +/* + * Values for description table header signatures. Useful because they make + * it more difficult to inadvertently type in the wrong signature. + */ +#define ACPI_SIG_ASF "ASF!" /* Alert Standard Format table */ +#define ACPI_SIG_BOOT "BOOT" /* Simple Boot Flag Table */ +#define ACPI_SIG_CPEP "CPEP" /* Corrected Platform Error Polling table */ +#define ACPI_SIG_DBGP "DBGP" /* Debug Port table */ +#define ACPI_SIG_ECDT "ECDT" /* Embedded Controller Boot Resources Table */ +#define ACPI_SIG_HPET "HPET" /* High Precision Event Timer table */ +#define ACPI_SIG_MADT "APIC" /* Multiple APIC Description Table */ +#define ACPI_SIG_MCFG "MCFG" /* PCI Memory Mapped Configuration table */ +#define ACPI_SIG_SBST "SBST" /* Smart Battery Specification Table */ +#define ACPI_SIG_SLIT "SLIT" /* System Locality Distance Information Table */ +#define ACPI_SIG_SPCR "SPCR" /* Serial Port Console Redirection table */ +#define ACPI_SIG_SPMI "SPMI" /* Server Platform Management Interface table */ +#define ACPI_SIG_SRAT "SRAT" /* System Resource Affinity Table */ +#define ACPI_SIG_TCPA "TCPA" /* Trusted Computing Platform Alliance table */ +#define ACPI_SIG_WDRT "WDRT" /* Watchdog Resource Table */ + +/* Legacy names */ + +#define APIC_SIG "APIC" /* Multiple APIC Description Table */ +#define BOOT_SIG "BOOT" /* Simple Boot Flag Table */ +#define SBST_SIG "SBST" /* Smart Battery Specification Table */ + +/* + * All tables must be byte-packed to match the ACPI specification, since + * the tables are provided by the system BIOS. + */ #pragma pack(1) /* - * ACPI 1.0 Root System Description Table (RSDT) + * Note about bitfields: The u8 type is used for bitfields in ACPI tables. + * This is the only type that is even remotely portable. Anything else is not + * portable, so do not use any other bitfield types. */ -struct rsdt_descriptor_rev1 { - ACPI_TABLE_HEADER_DEF /* ACPI common table header */ - u32 table_offset_entry[1]; /* Array of pointers to ACPI tables */ -}; + +/******************************************************************************* + * + * ASF - Alert Standard Format table (Signature "ASF!") + * + ******************************************************************************/ + +struct acpi_table_asf { +ACPI_TABLE_HEADER_DEF}; + +#define ACPI_ASF_HEADER_DEF \ + u8 type; \ + u8 reserved; \ + u16 length; + +struct acpi_asf_header { +ACPI_ASF_HEADER_DEF}; + +/* Values for Type field */ + +#define ASF_INFO 0 +#define ASF_ALERT 1 +#define ASF_CONTROL 2 +#define ASF_BOOT 3 +#define ASF_ADDRESS 4 +#define ASF_RESERVED 5 /* - * ACPI 1.0 Firmware ACPI Control Structure (FACS) + * ASF subtables */ -struct facs_descriptor_rev1 { - char signature[4]; /* ASCII table signature */ - u32 length; /* Length of structure in bytes */ - u32 hardware_signature; /* Hardware configuration signature */ - u32 firmware_waking_vector; /* ACPI OS waking vector */ - u32 global_lock; /* Global Lock */ + +/* 0: ASF Information */ + +struct acpi_asf_info { + ACPI_ASF_HEADER_DEF u8 min_reset_value; + u8 min_poll_interval; + u16 system_id; + u32 mfg_id; + u8 flags; + u8 reserved2[3]; +}; + +/* 1: ASF Alerts */ + +struct acpi_asf_alert { + ACPI_ASF_HEADER_DEF u8 assert_mask; + u8 deassert_mask; + u8 alerts; + u8 data_length; + u8 array[1]; +}; + +/* 2: ASF Remote Control */ + +struct acpi_asf_remote { + ACPI_ASF_HEADER_DEF u8 controls; + u8 data_length; + u16 reserved2; + u8 array[1]; +}; + +/* 3: ASF RMCP Boot Options */ + +struct acpi_asf_rmcp { + ACPI_ASF_HEADER_DEF u8 capabilities[7]; + u8 completion_code; + u32 enterprise_id; + u8 command; + u16 parameter; + u16 boot_options; + u16 oem_parameters; +}; + +/* 4: ASF Address */ + +struct acpi_asf_address { + ACPI_ASF_HEADER_DEF u8 eprom_address; + u8 devices; + u8 smbus_addresses[1]; +}; + +/******************************************************************************* + * + * BOOT - Simple Boot Flag Table + * + ******************************************************************************/ + +struct acpi_table_boot { + ACPI_TABLE_HEADER_DEF u8 cmos_index; /* Index in CMOS RAM for the boot register */ + u8 reserved[3]; +}; + +/******************************************************************************* + * + * CPEP - Corrected Platform Error Polling table + * + ******************************************************************************/ + +struct acpi_table_cpep { + ACPI_TABLE_HEADER_DEF u64 reserved; +}; + +/* Subtable */ + +struct acpi_cpep_polling { + u8 type; + u8 length; + u8 processor_id; /* Processor ID */ + u8 processor_eid; /* Processor EID */ + u32 polling_interval; /* Polling interval (msec) */ +}; + +/******************************************************************************* + * + * DBGP - Debug Port table + * + ******************************************************************************/ + +struct acpi_table_dbgp { + ACPI_TABLE_HEADER_DEF u8 interface_type; /* 0=full 16550, 1=subset of 16550 */ + u8 reserved[3]; + struct acpi_generic_address debug_port; +}; + +/******************************************************************************* + * + * ECDT - Embedded Controller Boot Resources Table + * + ******************************************************************************/ + +struct ec_boot_resources { + ACPI_TABLE_HEADER_DEF struct acpi_generic_address ec_control; /* Address of EC command/status register */ + struct acpi_generic_address ec_data; /* Address of EC data register */ + u32 uid; /* Unique ID - must be same as the EC _UID method */ + u8 gpe_bit; /* The GPE for the EC */ + u8 ec_id[1]; /* Full namepath of the EC in the ACPI namespace */ +}; + +/******************************************************************************* + * + * HPET - High Precision Event Timer table + * + ******************************************************************************/ + +struct acpi_hpet_table { + ACPI_TABLE_HEADER_DEF u32 hardware_id; /* Hardware ID of event timer block */ + struct acpi_generic_address base_address; /* Address of event timer block */ + u8 hpet_number; /* HPET sequence number */ + u16 clock_tick; /* Main counter min tick, periodic mode */ + u8 attributes; +}; + +#if 0 /* HPET flags to be converted to macros */ +struct { /* Flags (8 bits) */ + u8 page_protect:1; /* 00: No page protection */ + u8 page_protect4:1; /* 01: 4_kB page protected */ + u8 page_protect64:1; /* 02: 64_kB page protected */ + u8:5; /* 03-07: Reserved, must be zero */ +} flags; +#endif + +/******************************************************************************* + * + * MADT - Multiple APIC Description Table + * + ******************************************************************************/ + +struct multiple_apic_table { + ACPI_TABLE_HEADER_DEF u32 local_apic_address; /* Physical address of local APIC */ /* Flags (32 bits) */ - u8 S4bios_f:1; /* 00: S4BIOS support is present */ + u8 PCATcompat:1; /* 00: System also has dual 8259s */ u8:7; /* 01-07: Reserved, must be zero */ u8 reserved1[3]; /* 08-31: Reserved, must be zero */ - - u8 reserved2[40]; /* Reserved, must be zero */ }; +/* Values for MADT PCATCompat */ + +#define DUAL_PIC 0 +#define MULTIPLE_APIC 1 + +/* Common MADT Sub-table header */ + +#define APIC_HEADER_DEF \ + u8 type; \ + u8 length; + +struct apic_header { +APIC_HEADER_DEF}; + +/* Values for Type in struct apic_header */ + +#define APIC_PROCESSOR 0 +#define APIC_IO 1 +#define APIC_XRUPT_OVERRIDE 2 +#define APIC_NMI 3 +#define APIC_LOCAL_NMI 4 +#define APIC_ADDRESS_OVERRIDE 5 +#define APIC_IO_SAPIC 6 +#define APIC_LOCAL_SAPIC 7 +#define APIC_XRUPT_SOURCE 8 +#define APIC_RESERVED 9 /* 9 and greater are reserved */ + +/* Flag definitions for MADT sub-tables */ + +#define ACPI_MADT_IFLAGS /* INTI flags (16 bits) */ \ + u8 polarity : 2; /* 00-01: Polarity of APIC I/O input signals */\ + u8 trigger_mode : 2; /* 02-03: Trigger mode of APIC input signals */\ + u8 : 4; /* 04-07: Reserved, must be zero */\ + u8 reserved1; /* 08-15: Reserved, must be zero */ + +#define ACPI_MADT_LFLAGS /* Local Sapic flags (32 bits) */ \ + u8 processor_enabled: 1; /* 00: Processor is usable if set */\ + u8 : 7; /* 01-07: Reserved, must be zero */\ + u8 reserved2[3]; /* 08-31: Reserved, must be zero */ + +/* Values for MPS INTI flags */ + +#define POLARITY_CONFORMS 0 +#define POLARITY_ACTIVE_HIGH 1 +#define POLARITY_RESERVED 2 +#define POLARITY_ACTIVE_LOW 3 + +#define TRIGGER_CONFORMS 0 +#define TRIGGER_EDGE 1 +#define TRIGGER_RESERVED 2 +#define TRIGGER_LEVEL 3 + /* - * ACPI 1.0 Fixed ACPI Description Table (FADT) + * MADT Sub-tables, correspond to Type in struct apic_header */ -struct fadt_descriptor_rev1 { - ACPI_TABLE_HEADER_DEF /* ACPI common table header */ - u32 firmware_ctrl; /* Physical address of FACS */ - u32 dsdt; /* Physical address of DSDT */ - u8 model; /* System Interrupt Model */ - u8 reserved1; /* Reserved, must be zero */ - u16 sci_int; /* System vector of SCI interrupt */ - u32 smi_cmd; /* Port address of SMI command port */ - u8 acpi_enable; /* Value to write to smi_cmd to enable ACPI */ - u8 acpi_disable; /* Value to write to smi_cmd to disable ACPI */ - u8 S4bios_req; /* Value to write to SMI CMD to enter S4BIOS state */ - u8 reserved2; /* Reserved, must be zero */ - u32 pm1a_evt_blk; /* Port address of Power Mgt 1a acpi_event Reg Blk */ - u32 pm1b_evt_blk; /* Port address of Power Mgt 1b acpi_event Reg Blk */ - u32 pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */ - u32 pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */ - u32 pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */ - u32 pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */ - u32 gpe0_blk; /* Port addr of General Purpose acpi_event 0 Reg Blk */ - u32 gpe1_blk; /* Port addr of General Purpose acpi_event 1 Reg Blk */ - u8 pm1_evt_len; /* Byte length of ports at pm1_x_evt_blk */ - u8 pm1_cnt_len; /* Byte length of ports at pm1_x_cnt_blk */ - u8 pm2_cnt_len; /* Byte Length of ports at pm2_cnt_blk */ - u8 pm_tm_len; /* Byte Length of ports at pm_tm_blk */ - u8 gpe0_blk_len; /* Byte Length of ports at gpe0_blk */ - u8 gpe1_blk_len; /* Byte Length of ports at gpe1_blk */ - u8 gpe1_base; /* Offset in gpe model where gpe1 events start */ - u8 reserved3; /* Reserved, must be zero */ - u16 plvl2_lat; /* Worst case HW latency to enter/exit C2 state */ - u16 plvl3_lat; /* Worst case HW latency to enter/exit C3 state */ - u16 flush_size; /* Size of area read to flush caches */ - u16 flush_stride; /* Stride used in flushing caches */ - u8 duty_offset; /* Bit location of duty cycle field in p_cnt reg */ - u8 duty_width; /* Bit width of duty cycle field in p_cnt reg */ - u8 day_alrm; /* Index to day-of-month alarm in RTC CMOS RAM */ - u8 mon_alrm; /* Index to month-of-year alarm in RTC CMOS RAM */ - u8 century; /* Index to century in RTC CMOS RAM */ - u8 reserved4[3]; /* Reserved, must be zero */ + +/* 0: processor APIC */ + +struct madt_processor_apic { + APIC_HEADER_DEF u8 processor_id; /* ACPI processor id */ + u8 local_apic_id; /* Processor's local APIC id */ + ACPI_MADT_LFLAGS}; + +/* 1: IO APIC */ + +struct madt_io_apic { + APIC_HEADER_DEF u8 io_apic_id; /* I/O APIC ID */ + u8 reserved; /* Reserved - must be zero */ + u32 address; /* APIC physical address */ + u32 interrupt; /* Global system interrupt where INTI lines start */ +}; + +/* 2: Interrupt Override */ + +struct madt_interrupt_override { + APIC_HEADER_DEF u8 bus; /* 0 - ISA */ + u8 source; /* Interrupt source (IRQ) */ + u32 interrupt; /* Global system interrupt */ + ACPI_MADT_IFLAGS}; + +/* 3: NMI Sources */ + +struct madt_nmi_source { + APIC_HEADER_DEF ACPI_MADT_IFLAGS u32 interrupt; /* Global system interrupt */ +}; + +/* 4: Local APIC NMI */ + +struct madt_local_apic_nmi { + APIC_HEADER_DEF u8 processor_id; /* ACPI processor id */ + ACPI_MADT_IFLAGS u8 lint; /* LINTn to which NMI is connected */ +}; + +/* 5: Address Override */ + +struct madt_address_override { + APIC_HEADER_DEF u16 reserved; /* Reserved, must be zero */ + u64 address; /* APIC physical address */ +}; + +/* 6: I/O Sapic */ + +struct madt_io_sapic { + APIC_HEADER_DEF u8 io_sapic_id; /* I/O SAPIC ID */ + u8 reserved; /* Reserved, must be zero */ + u32 interrupt_base; /* Glocal interrupt for SAPIC start */ + u64 address; /* SAPIC physical address */ +}; + +/* 7: Local Sapic */ + +struct madt_local_sapic { + APIC_HEADER_DEF u8 processor_id; /* ACPI processor id */ + u8 local_sapic_id; /* SAPIC ID */ + u8 local_sapic_eid; /* SAPIC EID */ + u8 reserved[3]; /* Reserved, must be zero */ + ACPI_MADT_LFLAGS u32 processor_uID; /* Numeric UID - ACPI 3.0 */ + char processor_uIDstring[1]; /* String UID - ACPI 3.0 */ +}; + +/* 8: Platform Interrupt Source */ + +struct madt_interrupt_source { + APIC_HEADER_DEF ACPI_MADT_IFLAGS u8 interrupt_type; /* 1=PMI, 2=INIT, 3=corrected */ + u8 processor_id; /* Processor ID */ + u8 processor_eid; /* Processor EID */ + u8 io_sapic_vector; /* Vector value for PMI interrupts */ + u32 interrupt; /* Global system interrupt */ + u32 flags; /* Interrupt Source Flags */ +}; + +#ifdef DUPLICATE_DEFINITION_WITH_LINUX_ACPI_H +/******************************************************************************* + * + * MCFG - PCI Memory Mapped Configuration table and sub-table + * + ******************************************************************************/ + +struct acpi_table_mcfg { + ACPI_TABLE_HEADER_DEF u8 reserved[8]; +}; + +struct acpi_mcfg_allocation { + u64 base_address; /* Base address, processor-relative */ + u16 pci_segment; /* PCI segment group number */ + u8 start_bus_number; /* Starting PCI Bus number */ + u8 end_bus_number; /* Final PCI Bus number */ + u32 reserved; +}; +#endif + +/******************************************************************************* + * + * SBST - Smart Battery Specification Table + * + ******************************************************************************/ + +struct smart_battery_table { + ACPI_TABLE_HEADER_DEF u32 warning_level; + u32 low_level; + u32 critical_level; +}; + +/******************************************************************************* + * + * SLIT - System Locality Distance Information Table + * + ******************************************************************************/ + +struct system_locality_info { + ACPI_TABLE_HEADER_DEF u64 locality_count; + u8 entry[1][1]; +}; + +/******************************************************************************* + * + * SPCR - Serial Port Console Redirection table + * + ******************************************************************************/ + +struct acpi_table_spcr { + ACPI_TABLE_HEADER_DEF u8 interface_type; /* 0=full 16550, 1=subset of 16550 */ + u8 reserved[3]; + struct acpi_generic_address serial_port; + u8 interrupt_type; + u8 pc_interrupt; + u32 interrupt; + u8 baud_rate; + u8 parity; + u8 stop_bits; + u8 flow_control; + u8 terminal_type; + u8 reserved2; + u16 pci_device_id; + u16 pci_vendor_id; + u8 pci_bus; + u8 pci_device; + u8 pci_function; + u32 pci_flags; + u8 pci_segment; + u32 reserved3; +}; + +/******************************************************************************* + * + * SPMI - Server Platform Management Interface table + * + ******************************************************************************/ + +struct acpi_table_spmi { + ACPI_TABLE_HEADER_DEF u8 reserved; + u8 interface_type; + u16 spec_revision; /* Version of IPMI */ + u8 interrupt_type; + u8 gpe_number; /* GPE assigned */ + u8 reserved2; + u8 pci_device_flag; + u32 interrupt; + struct acpi_generic_address ipmi_register; + u8 pci_segment; + u8 pci_bus; + u8 pci_device; + u8 pci_function; +}; + +/******************************************************************************* + * + * SRAT - System Resource Affinity Table + * + ******************************************************************************/ + +struct system_resource_affinity { + ACPI_TABLE_HEADER_DEF u32 reserved1; /* Must be value '1' */ + u64 reserved2; /* Reserved, must be zero */ +}; + +/* SRAT common sub-table header */ + +#define SRAT_SUBTABLE_HEADER \ + u8 type; \ + u8 length; + +/* Values for Type above */ + +#define SRAT_CPU_AFFINITY 0 +#define SRAT_MEMORY_AFFINITY 1 +#define SRAT_RESERVED 2 + +/* SRAT sub-tables */ + +struct static_resource_alloc { + SRAT_SUBTABLE_HEADER u8 proximity_domain_lo; + u8 apic_id; + + /* Flags (32 bits) */ + + u8 enabled:1; /* 00: Use affinity structure */ + u8:7; /* 01-07: Reserved, must be zero */ + u8 reserved3[3]; /* 08-31: Reserved, must be zero */ + + u8 local_sapic_eid; + u8 proximity_domain_hi[3]; + u32 reserved4; /* Reserved, must be zero */ +}; + +struct memory_affinity { + SRAT_SUBTABLE_HEADER u32 proximity_domain; + u16 reserved3; + u64 base_address; + u64 address_length; + u32 reserved4; /* Flags (32 bits) */ - u8 wb_invd:1; /* 00: The wbinvd instruction works properly */ - u8 wb_invd_flush:1; /* 01: The wbinvd flushes but does not invalidate */ - u8 proc_c1:1; /* 02: All processors support C1 state */ - u8 plvl2_up:1; /* 03: C2 state works on MP system */ - u8 pwr_button:1; /* 04: Power button is handled as a generic feature */ - u8 sleep_button:1; /* 05: Sleep button is handled as a generic feature, or not present */ - u8 fixed_rTC:1; /* 06: RTC wakeup stat not in fixed register space */ - u8 rtcs4:1; /* 07: RTC wakeup stat not possible from S4 */ - u8 tmr_val_ext:1; /* 08: tmr_val width is 32 bits (0 = 24 bits) */ - u8:7; /* 09-15: Reserved, must be zero */ - u8 reserved5[2]; /* 16-31: Reserved, must be zero */ + u8 enabled:1; /* 00: Use affinity structure */ + u8 hot_pluggable:1; /* 01: Memory region is hot pluggable */ + u8 non_volatile:1; /* 02: Memory is non-volatile */ + u8:5; /* 03-07: Reserved, must be zero */ + u8 reserved5[3]; /* 08-31: Reserved, must be zero */ + + u64 reserved6; /* Reserved, must be zero */ +}; + +/******************************************************************************* + * + * TCPA - Trusted Computing Platform Alliance table + * + ******************************************************************************/ + +struct acpi_table_tcpa { + ACPI_TABLE_HEADER_DEF u16 reserved; + u32 max_log_length; /* Maximum length for the event log area */ + u64 log_address; /* Address of the event log area */ }; +/******************************************************************************* + * + * WDRT - Watchdog Resource Table + * + ******************************************************************************/ + +struct acpi_table_wdrt { + ACPI_TABLE_HEADER_DEF u32 header_length; /* Watchdog Header Length */ + u8 pci_segment; /* PCI Segment number */ + u8 pci_bus; /* PCI Bus number */ + u8 pci_device; /* PCI Device number */ + u8 pci_function; /* PCI Function number */ + u32 timer_period; /* Period of one timer count (msec) */ + u32 max_count; /* Maximum counter value supported */ + u32 min_count; /* Minimum counter value */ + u8 flags; + u8 reserved[3]; + u32 entries; /* Number of watchdog entries that follow */ +}; + +#if 0 /* Flags, will be converted to macros */ +u8 enabled:1; /* 00: Timer enabled */ +u8:6; /* 01-06: Reserved */ +u8 sleep_stop:1; /* 07: Timer stopped in sleep state */ +#endif + +/* Macros used to generate offsets to specific table fields */ + +#define ACPI_ASF0_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_asf_info,f) +#define ACPI_ASF1_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_asf_alert,f) +#define ACPI_ASF2_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_asf_remote,f) +#define ACPI_ASF3_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_asf_rmcp,f) +#define ACPI_ASF4_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_asf_address,f) +#define ACPI_BOOT_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_table_boot,f) +#define ACPI_CPEP_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_table_cpep,f) +#define ACPI_CPEP0_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_cpep_polling,f) +#define ACPI_DBGP_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_table_dbgp,f) +#define ACPI_ECDT_OFFSET(f) (u8) ACPI_OFFSET (struct ec_boot_resources,f) +#define ACPI_HPET_OFFSET(f) (u8) ACPI_OFFSET (struct hpet_table,f) +#define ACPI_MADT_OFFSET(f) (u8) ACPI_OFFSET (struct multiple_apic_table,f) +#define ACPI_MADT0_OFFSET(f) (u8) ACPI_OFFSET (struct madt_processor_apic,f) +#define ACPI_MADT1_OFFSET(f) (u8) ACPI_OFFSET (struct madt_io_apic,f) +#define ACPI_MADT2_OFFSET(f) (u8) ACPI_OFFSET (struct madt_interrupt_override,f) +#define ACPI_MADT3_OFFSET(f) (u8) ACPI_OFFSET (struct madt_nmi_source,f) +#define ACPI_MADT4_OFFSET(f) (u8) ACPI_OFFSET (struct madt_local_apic_nmi,f) +#define ACPI_MADT5_OFFSET(f) (u8) ACPI_OFFSET (struct madt_address_override,f) +#define ACPI_MADT6_OFFSET(f) (u8) ACPI_OFFSET (struct madt_io_sapic,f) +#define ACPI_MADT7_OFFSET(f) (u8) ACPI_OFFSET (struct madt_local_sapic,f) +#define ACPI_MADT8_OFFSET(f) (u8) ACPI_OFFSET (struct madt_interrupt_source,f) +#define ACPI_MADTH_OFFSET(f) (u8) ACPI_OFFSET (struct apic_header,f) +#define ACPI_MCFG_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_table_mcfg,f) +#define ACPI_MCFG0_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_mcfg_allocation,f) +#define ACPI_SBST_OFFSET(f) (u8) ACPI_OFFSET (struct smart_battery_table,f) +#define ACPI_SLIT_OFFSET(f) (u8) ACPI_OFFSET (struct system_locality_info,f) +#define ACPI_SPCR_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_table_spcr,f) +#define ACPI_SPMI_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_table_spmi,f) +#define ACPI_SRAT_OFFSET(f) (u8) ACPI_OFFSET (struct system_resource_affinity,f) +#define ACPI_SRAT0_OFFSET(f) (u8) ACPI_OFFSET (struct static_resource_alloc,f) +#define ACPI_SRAT1_OFFSET(f) (u8) ACPI_OFFSET (struct memory_affinity,f) +#define ACPI_TCPA_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_table_tcpa,f) +#define ACPI_WDRT_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_table_wdrt,f) + +#define ACPI_HPET_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct hpet_table,f,o) +#define ACPI_SRAT0_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct static_resource_alloc,f,o) +#define ACPI_SRAT1_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct memory_affinity,f,o) +#define ACPI_MADT_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct multiple_apic_table,f,o) +#define ACPI_MADT0_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct madt_processor_apic,f,o) +#define ACPI_MADT2_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct madt_interrupt_override,f,o) +#define ACPI_MADT3_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct madt_nmi_source,f,o) +#define ACPI_MADT4_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct madt_local_apic_nmi,f,o) +#define ACPI_MADT7_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct madt_local_sapic,f,o) +#define ACPI_MADT8_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct madt_interrupt_source,f,o) + +/* Reset to default packing */ + #pragma pack() #endif /* __ACTBL1_H__ */ diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h index dfc7ac1094b..67efe6cad27 100644 --- a/include/acpi/actbl2.h +++ b/include/acpi/actbl2.h @@ -44,234 +44,6 @@ #ifndef __ACTBL2_H__ #define __ACTBL2_H__ -/* - * Prefered Power Management Profiles - */ -#define PM_UNSPECIFIED 0 -#define PM_DESKTOP 1 -#define PM_MOBILE 2 -#define PM_WORKSTATION 3 -#define PM_ENTERPRISE_SERVER 4 -#define PM_SOHO_SERVER 5 -#define PM_APPLIANCE_PC 6 - -/* - * ACPI Boot Arch Flags - */ -#define BAF_LEGACY_DEVICES 0x0001 -#define BAF_8042_KEYBOARD_CONTROLLER 0x0002 - -#define FADT2_REVISION_ID 3 -#define FADT2_MINUS_REVISION_ID 2 - -#pragma pack(1) - -/* - * ACPI 2.0 Root System Description Table (RSDT) - */ -struct rsdt_descriptor_rev2 { - ACPI_TABLE_HEADER_DEF /* ACPI common table header */ - u32 table_offset_entry[1]; /* Array of pointers to ACPI tables */ -}; - -/* - * ACPI 2.0 Extended System Description Table (XSDT) - */ -struct xsdt_descriptor_rev2 { - ACPI_TABLE_HEADER_DEF /* ACPI common table header */ - u64 table_offset_entry[1]; /* Array of pointers to ACPI tables */ -}; - -/* - * ACPI 2.0 Firmware ACPI Control Structure (FACS) - */ -struct facs_descriptor_rev2 { - char signature[4]; /* ASCII table signature */ - u32 length; /* Length of structure, in bytes */ - u32 hardware_signature; /* Hardware configuration signature */ - u32 firmware_waking_vector; /* 32-bit physical address of the Firmware Waking Vector. */ - u32 global_lock; /* Global Lock used to synchronize access to shared hardware resources */ - - /* Flags (32 bits) */ - - u8 S4bios_f:1; /* 00: S4BIOS support is present */ - u8:7; /* 01-07: Reserved, must be zero */ - u8 reserved1[3]; /* 08-31: Reserved, must be zero */ - - u64 xfirmware_waking_vector; /* 64-bit physical address of the Firmware Waking Vector. */ - u8 version; /* Version of this table */ - u8 reserved3[31]; /* Reserved, must be zero */ -}; - -/* - * ACPI 2.0+ Generic Address Structure (GAS) - */ -struct acpi_generic_address { - u8 address_space_id; /* Address space where struct or register exists. */ - u8 register_bit_width; /* Size in bits of given register */ - u8 register_bit_offset; /* Bit offset within the register */ - u8 access_width; /* Minimum Access size (ACPI 3.0) */ - u64 address; /* 64-bit address of struct or register */ -}; - -#define FADT_REV2_COMMON \ - u32 V1_firmware_ctrl; /* 32-bit physical address of FACS */ \ - u32 V1_dsdt; /* 32-bit physical address of DSDT */ \ - u8 reserved1; /* System Interrupt Model isn't used in ACPI 2.0*/ \ - u8 prefer_PM_profile; /* Conveys preferred power management profile to OSPM. */ \ - u16 sci_int; /* System vector of SCI interrupt */ \ - u32 smi_cmd; /* Port address of SMI command port */ \ - u8 acpi_enable; /* Value to write to smi_cmd to enable ACPI */ \ - u8 acpi_disable; /* Value to write to smi_cmd to disable ACPI */ \ - u8 S4bios_req; /* Value to write to SMI CMD to enter S4BIOS state */ \ - u8 pstate_cnt; /* Processor performance state control*/ \ - u32 V1_pm1a_evt_blk; /* Port address of Power Mgt 1a acpi_event Reg Blk */ \ - u32 V1_pm1b_evt_blk; /* Port address of Power Mgt 1b acpi_event Reg Blk */ \ - u32 V1_pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */ \ - u32 V1_pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */ \ - u32 V1_pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */ \ - u32 V1_pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */ \ - u32 V1_gpe0_blk; /* Port addr of General Purpose acpi_event 0 Reg Blk */ \ - u32 V1_gpe1_blk; /* Port addr of General Purpose acpi_event 1 Reg Blk */ \ - u8 pm1_evt_len; /* Byte length of ports at pm1_x_evt_blk */ \ - u8 pm1_cnt_len; /* Byte length of ports at pm1_x_cnt_blk */ \ - u8 pm2_cnt_len; /* Byte Length of ports at pm2_cnt_blk */ \ - u8 pm_tm_len; /* Byte Length of ports at pm_tm_blk */ \ - u8 gpe0_blk_len; /* Byte Length of ports at gpe0_blk */ \ - u8 gpe1_blk_len; /* Byte Length of ports at gpe1_blk */ \ - u8 gpe1_base; /* Offset in gpe model where gpe1 events start */ \ - u8 cst_cnt; /* Support for the _CST object and C States change notification.*/ \ - u16 plvl2_lat; /* Worst case HW latency to enter/exit C2 state */ \ - u16 plvl3_lat; /* Worst case HW latency to enter/exit C3 state */ \ - u16 flush_size; /* Number of flush strides that need to be read */ \ - u16 flush_stride; /* Processor's memory cache line width, in bytes */ \ - u8 duty_offset; /* Processor's duty cycle index in processor's P_CNT reg*/ \ - u8 duty_width; /* Processor's duty cycle value bit width in P_CNT register.*/ \ - u8 day_alrm; /* Index to day-of-month alarm in RTC CMOS RAM */ \ - u8 mon_alrm; /* Index to month-of-year alarm in RTC CMOS RAM */ \ - u8 century; /* Index to century in RTC CMOS RAM */ \ - u16 iapc_boot_arch; /* IA-PC Boot Architecture Flags. See Table 5-10 for description*/ - -/* - * ACPI 2.0+ Fixed ACPI Description Table (FADT) - */ -struct fadt_descriptor_rev2 { - ACPI_TABLE_HEADER_DEF /* ACPI common table header */ - FADT_REV2_COMMON u8 reserved2; /* Reserved, must be zero */ - - /* Flags (32 bits) */ - - u8 wb_invd:1; /* 00: The wbinvd instruction works properly */ - u8 wb_invd_flush:1; /* 01: The wbinvd flushes but does not invalidate */ - u8 proc_c1:1; /* 02: All processors support C1 state */ - u8 plvl2_up:1; /* 03: C2 state works on MP system */ - u8 pwr_button:1; /* 04: Power button is handled as a generic feature */ - u8 sleep_button:1; /* 05: Sleep button is handled as a generic feature, or not present */ - u8 fixed_rTC:1; /* 06: RTC wakeup stat not in fixed register space */ - u8 rtcs4:1; /* 07: RTC wakeup stat not possible from S4 */ - u8 tmr_val_ext:1; /* 08: tmr_val is 32 bits 0=24-bits */ - u8 dock_cap:1; /* 09: Docking supported */ - u8 reset_reg_sup:1; /* 10: System reset via the FADT RESET_REG supported */ - u8 sealed_case:1; /* 11: No internal expansion capabilities and case is sealed */ - u8 headless:1; /* 12: No local video capabilities or local input devices */ - u8 cpu_sw_sleep:1; /* 13: Must execute native instruction after writing SLP_TYPx register */ - - u8 pci_exp_wak:1; /* 14: System supports PCIEXP_WAKE (STS/EN) bits (ACPI 3.0) */ - u8 use_platform_clock:1; /* 15: OSPM should use platform-provided timer (ACPI 3.0) */ - u8 S4rtc_sts_valid:1; /* 16: Contents of RTC_STS valid after S4 wake (ACPI 3.0) */ - u8 remote_power_on_capable:1; /* 17: System is compatible with remote power on (ACPI 3.0) */ - u8 force_apic_cluster_model:1; /* 18: All local APICs must use cluster model (ACPI 3.0) */ - u8 force_apic_physical_destination_mode:1; /* 19: all local x_aPICs must use physical dest mode (ACPI 3.0) */ - u8:4; /* 20-23: Reserved, must be zero */ - u8 reserved3; /* 24-31: Reserved, must be zero */ - - struct acpi_generic_address reset_register; /* Reset register address in GAS format */ - u8 reset_value; /* Value to write to the reset_register port to reset the system */ - u8 reserved4[3]; /* These three bytes must be zero */ - u64 xfirmware_ctrl; /* 64-bit physical address of FACS */ - u64 Xdsdt; /* 64-bit physical address of DSDT */ - struct acpi_generic_address xpm1a_evt_blk; /* Extended Power Mgt 1a acpi_event Reg Blk address */ - struct acpi_generic_address xpm1b_evt_blk; /* Extended Power Mgt 1b acpi_event Reg Blk address */ - struct acpi_generic_address xpm1a_cnt_blk; /* Extended Power Mgt 1a Control Reg Blk address */ - struct acpi_generic_address xpm1b_cnt_blk; /* Extended Power Mgt 1b Control Reg Blk address */ - struct acpi_generic_address xpm2_cnt_blk; /* Extended Power Mgt 2 Control Reg Blk address */ - struct acpi_generic_address xpm_tmr_blk; /* Extended Power Mgt Timer Ctrl Reg Blk address */ - struct acpi_generic_address xgpe0_blk; /* Extended General Purpose acpi_event 0 Reg Blk address */ - struct acpi_generic_address xgpe1_blk; /* Extended General Purpose acpi_event 1 Reg Blk address */ -}; - -/* "Down-revved" ACPI 2.0 FADT descriptor */ - -struct fadt_descriptor_rev2_minus { - ACPI_TABLE_HEADER_DEF /* ACPI common table header */ - FADT_REV2_COMMON u8 reserved2; /* Reserved, must be zero */ - u32 flags; - struct acpi_generic_address reset_register; /* Reset register address in GAS format */ - u8 reset_value; /* Value to write to the reset_register port to reset the system. */ - u8 reserved7[3]; /* Reserved, must be zero */ -}; - -/* ECDT - Embedded Controller Boot Resources Table */ - -struct ec_boot_resources { - ACPI_TABLE_HEADER_DEF struct acpi_generic_address ec_control; /* Address of EC command/status register */ - struct acpi_generic_address ec_data; /* Address of EC data register */ - u32 uid; /* Unique ID - must be same as the EC _UID method */ - u8 gpe_bit; /* The GPE for the EC */ - u8 ec_id[1]; /* Full namepath of the EC in the ACPI namespace */ -}; - -/* SRAT - System Resource Affinity Table */ - -struct static_resource_alloc { - u8 type; - u8 length; - u8 proximity_domain_lo; - u8 apic_id; - - /* Flags (32 bits) */ - - u8 enabled:1; /* 00: Use affinity structure */ - u8:7; /* 01-07: Reserved, must be zero */ - u8 reserved3[3]; /* 08-31: Reserved, must be zero */ - - u8 local_sapic_eid; - u8 proximity_domain_hi[3]; - u32 reserved4; /* Reserved, must be zero */ -}; - -struct memory_affinity { - u8 type; - u8 length; - u32 proximity_domain; - u16 reserved3; - u64 base_address; - u64 address_length; - u32 reserved4; - - /* Flags (32 bits) */ - - u8 enabled:1; /* 00: Use affinity structure */ - u8 hot_pluggable:1; /* 01: Memory region is hot pluggable */ - u8 non_volatile:1; /* 02: Memory is non-volatile */ - u8:5; /* 03-07: Reserved, must be zero */ - u8 reserved5[3]; /* 08-31: Reserved, must be zero */ - - u64 reserved6; /* Reserved, must be zero */ -}; - -struct system_resource_affinity { - ACPI_TABLE_HEADER_DEF u32 reserved1; /* Must be value '1' */ - u64 reserved2; /* Reserved, must be zero */ -}; - -/* SLIT - System Locality Distance Information Table */ - -struct system_locality_info { - ACPI_TABLE_HEADER_DEF u64 locality_count; - u8 entry[1][1]; -}; - -#pragma pack() +/* Code moved to both actbl.h and actbl1.h */ #endif /* __ACTBL2_H__ */ diff --git a/include/acpi/acutils.h b/include/acpi/acutils.h index 5e69a80c785..115b0cbc370 100644 --- a/include/acpi/acutils.h +++ b/include/acpi/acutils.h @@ -283,6 +283,8 @@ acpi_ut_ptr_exit(u32 line_number, void acpi_ut_dump_buffer(u8 * buffer, u32 count, u32 display, u32 component_id); +void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display); + void acpi_ut_report_error(char *module_name, u32 line_number); void acpi_ut_report_info(char *module_name, u32 line_number); @@ -451,6 +453,8 @@ acpi_ut_short_divide(acpi_integer in_dividend, /* * utmisc */ +u8 acpi_ut_is_aml_table(struct acpi_table_header *table); + acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id); void acpi_ut_release_owner_id(acpi_owner_id * owner_id); @@ -466,7 +470,9 @@ void acpi_ut_print_string(char *string, u8 max_length); u8 acpi_ut_valid_acpi_name(u32 name); -u8 acpi_ut_valid_acpi_character(char character); +acpi_name acpi_ut_repair_name(acpi_name name); + +u8 acpi_ut_valid_acpi_char(char character, acpi_native_uint position); acpi_status acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer); @@ -492,7 +498,7 @@ acpi_ut_display_init_pathname(u8 type, acpi_status acpi_ut_walk_aml_resources(u8 * aml, acpi_size aml_length, - acpi_walk_aml_callback user_function, void *context); + acpi_walk_aml_callback user_function, void **context); acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index); diff --git a/include/acpi/platform/acenv.h b/include/acpi/platform/acenv.h index 2270bdd5e53..fd189d425c7 100644 --- a/include/acpi/platform/acenv.h +++ b/include/acpi/platform/acenv.h @@ -60,6 +60,7 @@ #define ACPI_DISASSEMBLER #define ACPI_NO_METHOD_EXECUTION #define ACPI_LARGE_NAMESPACE_NODE +#define ACPI_DATA_TABLE_DISASSEMBLY #endif #ifdef ACPI_EXEC_APP @@ -79,6 +80,7 @@ #define ACPI_DISASSEMBLER #define ACPI_CONSTANT_EVAL_ONLY #define ACPI_LARGE_NAMESPACE_NODE +#define ACPI_DATA_TABLE_DISASSEMBLY #endif #ifdef ACPI_APPLICATION @@ -140,7 +142,7 @@ #elif defined(MSDOS) /* Must appear after WIN32 and WIN64 check */ #include "acdos16.h" -#elif defined(__FreeBSD__) +#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) #include "acfreebsd.h" #elif defined(__NetBSD__) -- cgit v1.2.3 From b229cf92eee616c7cb5ad8cdb35a19b119f00bc8 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Fri, 21 Apr 2006 17:15:00 -0400 Subject: ACPI: ACPICA 20060421 Removed a device initialization optimization introduced in 20051216 where the _STA method was not run unless an _INI was also present for the same device. This optimization could cause problems because it could allow _INI methods to be run within a not-present device subtree (If a not-present device had no _INI, _STA would not be run, the not-present status would not be discovered, and the children of the device would be incorrectly traversed.) Implemented a new _STA optimization where namespace subtrees that do not contain _INI are identified and ignored during device initialization. Selectively running _STA can significantly improve boot time on large machines (with assistance from Len Brown.) Implemented support for the device initialization case where the returned _STA flags indicate a device not-present but functioning. In this case, _INI is not run, but the device children are examined for presence, as per the ACPI specification. Implemented an additional change to the IndexField support in order to conform to MS behavior. The value written to the Index Register is not simply a byte offset, it is a byte offset in units of the access width of the parent Index Field. (Fiodor Suietov) Defined and deployed a new OSL interface, acpi_os_validate_address(). This interface is called during the creation of all AML operation regions, and allows the host OS to exert control over what addresses it will allow the AML code to access. Operation Regions whose addresses are disallowed will cause a runtime exception when they are actually accessed (will not affect or abort table loading.) Defined and deployed a new OSL interface, acpi_os_validate_interface(). This interface allows the host OS to match the various "optional" interface/behavior strings for the _OSI predefined control method as appropriate (with assistance from Bjorn Helgaas.) Restructured and corrected various problems in the exception handling code paths within DsCallControlMethod and DsTerminateControlMethod in dsmethod (with assistance from Takayoshi Kochi.) Modified the Linux source converter to ignore quoted string literals while converting identifiers from mixed to lower case. This will correct problems with the disassembler and other areas where such strings must not be modified. The ACPI_FUNCTION_* macros no longer require quotes around the function name. This allows the Linux source converter to convert the names, now that the converter ignores quoted strings. Signed-off-by: Bob Moore Signed-off-by: Len Brown --- drivers/acpi/asus_acpi.c | 2 +- drivers/acpi/bus.c | 2 +- drivers/acpi/dispatcher/dsfield.c | 12 +- drivers/acpi/dispatcher/dsinit.c | 6 +- drivers/acpi/dispatcher/dsmethod.c | 180 ++++++++++++++----------- drivers/acpi/dispatcher/dsmthdat.c | 22 +-- drivers/acpi/dispatcher/dsobject.c | 10 +- drivers/acpi/dispatcher/dsopcode.c | 59 ++++++--- drivers/acpi/dispatcher/dsutils.c | 16 +-- drivers/acpi/dispatcher/dswexec.c | 20 +-- drivers/acpi/dispatcher/dswload.c | 16 +-- drivers/acpi/dispatcher/dswscope.c | 6 +- drivers/acpi/dispatcher/dswstate.c | 42 +++--- drivers/acpi/events/evevent.c | 8 +- drivers/acpi/events/evgpe.c | 18 +-- drivers/acpi/events/evgpeblk.c | 42 +++--- drivers/acpi/events/evmisc.c | 12 +- drivers/acpi/events/evregion.c | 18 +-- drivers/acpi/events/evrgnini.c | 18 +-- drivers/acpi/events/evsci.c | 8 +- drivers/acpi/events/evxface.c | 14 +- drivers/acpi/events/evxfevnt.c | 26 ++-- drivers/acpi/events/evxfregn.c | 6 +- drivers/acpi/executer/exconfig.c | 18 +-- drivers/acpi/executer/exconvrt.c | 10 +- drivers/acpi/executer/excreate.c | 18 +-- drivers/acpi/executer/exdump.c | 24 ++-- drivers/acpi/executer/exfield.c | 12 +- drivers/acpi/executer/exfldio.c | 30 +++-- drivers/acpi/executer/exmisc.c | 10 +- drivers/acpi/executer/exmutex.c | 12 +- drivers/acpi/executer/exnames.c | 16 +-- drivers/acpi/executer/exoparg1.c | 12 +- drivers/acpi/executer/exoparg2.c | 10 +- drivers/acpi/executer/exoparg3.c | 6 +- drivers/acpi/executer/exoparg6.c | 2 +- drivers/acpi/executer/exprep.c | 40 +++--- drivers/acpi/executer/exregion.c | 14 +- drivers/acpi/executer/exresnte.c | 6 +- drivers/acpi/executer/exresolv.c | 14 +- drivers/acpi/executer/exresop.c | 8 +- drivers/acpi/executer/exstore.c | 13 +- drivers/acpi/executer/exstoren.c | 4 +- drivers/acpi/executer/exstorob.c | 4 +- drivers/acpi/executer/exsystem.c | 10 +- drivers/acpi/executer/exutils.c | 10 +- drivers/acpi/hardware/hwacpi.c | 6 +- drivers/acpi/hardware/hwgpe.c | 6 +- drivers/acpi/hardware/hwregs.c | 24 ++-- drivers/acpi/hardware/hwsleep.c | 12 +- drivers/acpi/hardware/hwtimer.c | 6 +- drivers/acpi/namespace/nsaccess.c | 6 +- drivers/acpi/namespace/nsalloc.c | 12 +- drivers/acpi/namespace/nsdump.c | 8 +- drivers/acpi/namespace/nsdumpdv.c | 4 +- drivers/acpi/namespace/nseval.c | 10 +- drivers/acpi/namespace/nsinit.c | 265 ++++++++++++++++++++++++++----------- drivers/acpi/namespace/nsload.c | 24 ++-- drivers/acpi/namespace/nsnames.c | 4 +- drivers/acpi/namespace/nsobject.c | 12 +- drivers/acpi/namespace/nsparse.c | 4 +- drivers/acpi/namespace/nssearch.c | 8 +- drivers/acpi/namespace/nsutils.c | 18 +-- drivers/acpi/namespace/nswalk.c | 2 +- drivers/acpi/namespace/nsxfeval.c | 8 +- drivers/acpi/osl.c | 63 ++++++++- drivers/acpi/parser/psargs.c | 18 +-- drivers/acpi/parser/psloop.c | 6 +- drivers/acpi/parser/psopcode.c | 4 +- drivers/acpi/parser/psparse.c | 28 ++-- drivers/acpi/parser/psscope.c | 8 +- drivers/acpi/parser/psutils.c | 2 +- drivers/acpi/parser/pswalk.c | 2 +- drivers/acpi/parser/psxface.c | 7 +- drivers/acpi/resources/rscalc.c | 8 +- drivers/acpi/resources/rscreate.c | 24 ++-- drivers/acpi/resources/rsdump.c | 42 +++--- drivers/acpi/resources/rslist.c | 6 +- drivers/acpi/resources/rsmisc.c | 4 +- drivers/acpi/resources/rsutils.c | 10 +- drivers/acpi/resources/rsxface.c | 14 +- drivers/acpi/system.c | 4 +- drivers/acpi/tables/tbconvrt.c | 6 +- drivers/acpi/tables/tbget.c | 16 +-- drivers/acpi/tables/tbgetall.c | 10 +- drivers/acpi/tables/tbinstal.c | 41 +++--- drivers/acpi/tables/tbrsdt.c | 25 ++-- drivers/acpi/tables/tbutils.c | 10 +- drivers/acpi/tables/tbxface.c | 24 ++-- drivers/acpi/tables/tbxfroot.c | 24 ++-- drivers/acpi/utilities/utalloc.c | 4 +- drivers/acpi/utilities/utcache.c | 2 +- drivers/acpi/utilities/utcopy.c | 16 +-- drivers/acpi/utilities/utdelete.c | 12 +- drivers/acpi/utilities/uteval.c | 88 +++++++++--- drivers/acpi/utilities/utglobal.c | 38 +----- drivers/acpi/utilities/utinit.c | 4 +- drivers/acpi/utilities/utmath.c | 8 +- drivers/acpi/utilities/utmisc.c | 16 +-- drivers/acpi/utilities/utmutex.c | 12 +- drivers/acpi/utilities/utobject.c | 16 +-- drivers/acpi/utilities/utresrc.c | 106 +++++++-------- drivers/acpi/utilities/utstate.c | 14 +- drivers/acpi/utilities/utxface.c | 20 +-- include/acpi/acconfig.h | 12 +- include/acpi/acdisasm.h | 12 +- include/acpi/acdispat.h | 4 +- include/acpi/acexcep.h | 6 +- include/acpi/acglobal.h | 7 +- include/acpi/aclocal.h | 9 +- include/acpi/acmacros.h | 12 +- include/acpi/acobject.h | 3 +- include/acpi/acoutput.h | 8 +- include/acpi/acpiosxf.h | 7 + include/acpi/actypes.h | 23 ++-- include/acpi/acutils.h | 38 +++--- include/acpi/platform/acenv.h | 25 ++-- 117 files changed, 1240 insertions(+), 993 deletions(-) diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c index f4c87750dbf..216c072dee5 100644 --- a/drivers/acpi/asus_acpi.c +++ b/drivers/acpi/asus_acpi.c @@ -970,7 +970,7 @@ static int __init asus_hotk_get_info(void) * HID), this bit will be moved. A global variable asus_info contains * the DSDT header. */ - status = acpi_get_table(ACPI_TABLE_DSDT, 1, &dsdt); + status = acpi_get_table(ACPI_TABLE_ID_DSDT, 1, &dsdt); if (ACPI_FAILURE(status)) printk(KERN_WARNING " Couldn't get the DSDT table header\n"); else diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index b3a214db56f..b77f03d51f0 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -619,7 +619,7 @@ void __init acpi_early_init(void) /* * Get a separate copy of the FADT for use by other drivers. */ - status = acpi_get_table(ACPI_TABLE_FADT, 1, &buffer); + status = acpi_get_table(ACPI_TABLE_ID_FADT, 1, &buffer); if (ACPI_FAILURE(status)) { printk(KERN_ERR PREFIX "Unable to get the FADT\n"); goto error0; diff --git a/drivers/acpi/dispatcher/dsfield.c b/drivers/acpi/dispatcher/dsfield.c index 3d33bcc9867..a6d77efb41a 100644 --- a/drivers/acpi/dispatcher/dsfield.c +++ b/drivers/acpi/dispatcher/dsfield.c @@ -87,7 +87,7 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op, union acpi_operand_object *second_desc = NULL; u32 flags; - ACPI_FUNCTION_TRACE("ds_create_buffer_field"); + ACPI_FUNCTION_TRACE(ds_create_buffer_field); /* Get the name_string argument */ @@ -210,7 +210,7 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info, acpi_status status; acpi_integer position; - ACPI_FUNCTION_TRACE_PTR("ds_get_field_names", info); + ACPI_FUNCTION_TRACE_PTR(ds_get_field_names, info); /* First field starts at bit zero */ @@ -342,7 +342,7 @@ acpi_ds_create_field(union acpi_parse_object *op, union acpi_parse_object *arg; struct acpi_create_field_info info; - ACPI_FUNCTION_TRACE_PTR("ds_create_field", op); + ACPI_FUNCTION_TRACE_PTR(ds_create_field, op); /* First arg is the name of the parent op_region (must already exist) */ @@ -399,7 +399,7 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, struct acpi_namespace_node *node; u8 type = 0; - ACPI_FUNCTION_TRACE_PTR("ds_init_field_objects", op); + ACPI_FUNCTION_TRACE_PTR(ds_init_field_objects, op); switch (walk_state->opcode) { case AML_FIELD_OP: @@ -482,7 +482,7 @@ acpi_ds_create_bank_field(union acpi_parse_object *op, union acpi_parse_object *arg; struct acpi_create_field_info info; - ACPI_FUNCTION_TRACE_PTR("ds_create_bank_field", op); + ACPI_FUNCTION_TRACE_PTR(ds_create_bank_field, op); /* First arg is the name of the parent op_region (must already exist) */ @@ -555,7 +555,7 @@ acpi_ds_create_index_field(union acpi_parse_object *op, union acpi_parse_object *arg; struct acpi_create_field_info info; - ACPI_FUNCTION_TRACE_PTR("ds_create_index_field", op); + ACPI_FUNCTION_TRACE_PTR(ds_create_index_field, op); /* First arg is the name of the Index register (must already exist) */ diff --git a/drivers/acpi/dispatcher/dsinit.c b/drivers/acpi/dispatcher/dsinit.c index e65a07ad242..bbdf990e9f6 100644 --- a/drivers/acpi/dispatcher/dsinit.c +++ b/drivers/acpi/dispatcher/dsinit.c @@ -184,7 +184,7 @@ acpi_ds_init_one_object(acpi_handle obj_handle, * * RETURN: Status * - * DESCRIPTION: Walk the namespace starting at "start_node" and perform any + * DESCRIPTION: Walk the namespace starting at "StartNode" and perform any * necessary initialization on the objects found therein * ******************************************************************************/ @@ -196,7 +196,7 @@ acpi_ds_initialize_objects(struct acpi_table_desc * table_desc, acpi_status status; struct acpi_init_walk_info info; - ACPI_FUNCTION_TRACE("ds_initialize_objects"); + ACPI_FUNCTION_TRACE(ds_initialize_objects); ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "**** Starting initialization of namespace objects ****\n")); @@ -213,7 +213,7 @@ acpi_ds_initialize_objects(struct acpi_table_desc * table_desc, status = acpi_walk_namespace(ACPI_TYPE_ANY, start_node, ACPI_UINT32_MAX, acpi_ds_init_one_object, &info, NULL); if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "During walk_namespace")); + ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace")); } ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c index 7dc59fc7344..651f2b68531 100644 --- a/drivers/acpi/dispatcher/dsmethod.c +++ b/drivers/acpi/dispatcher/dsmethod.c @@ -134,7 +134,7 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node * method_node, { acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE_PTR("ds_begin_method_execution", method_node); + ACPI_FUNCTION_TRACE_PTR(ds_begin_method_execution, method_node); if (!method_node) { return_ACPI_STATUS(AE_NULL_ENTRY); @@ -170,11 +170,14 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node * method_node, /* * Get a unit from the method semaphore. This releases the - * interpreter if we block + * interpreter if we block (then reacquires it) */ status = acpi_ex_system_wait_semaphore(obj_desc->method.semaphore, ACPI_WAIT_FOREVER); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } } /* @@ -185,7 +188,7 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node * method_node, if (!obj_desc->method.owner_id) { status = acpi_ut_allocate_owner_id(&obj_desc->method.owner_id); if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + goto cleanup; } } @@ -195,6 +198,14 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node * method_node, */ obj_desc->method.thread_count++; return_ACPI_STATUS(status); + + cleanup: + /* On error, must signal the method semaphore if present */ + + if (obj_desc->method.semaphore) { + (void)acpi_os_signal_semaphore(obj_desc->method.semaphore, 1); + } + return_ACPI_STATUS(status); } /******************************************************************************* @@ -223,7 +234,7 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread, struct acpi_parameter_info info; u32 i; - ACPI_FUNCTION_TRACE_PTR("ds_call_control_method", this_walk_state); + ACPI_FUNCTION_TRACE_PTR(ds_call_control_method, this_walk_state); ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Execute method %p, currentstate=%p\n", @@ -242,26 +253,31 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread, return_ACPI_STATUS(AE_NULL_OBJECT); } - /* Init for new method, wait on concurrency semaphore */ + /* Init for new method, possibly wait on concurrency semaphore */ status = acpi_ds_begin_method_execution(method_node, obj_desc, this_walk_state->method_node); if (ACPI_FAILURE(status)) { - goto cleanup; + return_ACPI_STATUS(status); } + /* + * 1) Parse the method. All "normal" methods are parsed for each execution. + * Internal methods (_OSI, etc.) do not require parsing. + */ if (!(obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY)) { - /* 1) Parse: Create a new walk state for the preempting walk */ + /* Create a new walk state for the parse */ next_walk_state = acpi_ds_create_walk_state(obj_desc->method.owner_id, op, obj_desc, NULL); if (!next_walk_state) { - return_ACPI_STATUS(AE_NO_MEMORY); + status = AE_NO_MEMORY; + goto cleanup; } - /* Create and init a Root Node */ + /* Create and init a parse tree root */ op = acpi_ps_create_scope_op(); if (!op) { @@ -274,17 +290,20 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread, obj_desc->method.aml_length, NULL, 1); if (ACPI_FAILURE(status)) { - acpi_ds_delete_walk_state(next_walk_state); + acpi_ps_delete_parse_tree(op); goto cleanup; } - /* Begin AML parse */ + /* Begin AML parse (deletes next_walk_state) */ status = acpi_ps_parse_aml(next_walk_state); acpi_ps_delete_parse_tree(op); + if (ACPI_FAILURE(status)) { + goto cleanup; + } } - /* 2) Execute: Create a new state for the preempting walk */ + /* 2) Begin method execution. Create a new walk state */ next_walk_state = acpi_ds_create_walk_state(obj_desc->method.owner_id, NULL, obj_desc, thread); @@ -292,6 +311,7 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread, status = AE_NO_MEMORY; goto cleanup; } + /* * The resolved arguments were put on the previous walk state's operand * stack. Operands on the previous walk state stack always @@ -326,6 +346,8 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread, "Starting nested execution, newstate=%p\n", next_walk_state)); + /* Invoke an internal method if necessary */ + if (obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) { status = obj_desc->method.implementation(next_walk_state); } @@ -333,16 +355,14 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread, return_ACPI_STATUS(status); cleanup: - /* Decrement the thread count on the method parse tree */ - if (next_walk_state && (next_walk_state->method_desc)) { - next_walk_state->method_desc->method.thread_count--; - } + /* On error, we must terminate the method properly */ - /* On error, we must delete the new walk state */ + acpi_ds_terminate_control_method(obj_desc, next_walk_state); + if (next_walk_state) { + acpi_ds_delete_walk_state(next_walk_state); + } - acpi_ds_terminate_control_method(next_walk_state); - acpi_ds_delete_walk_state(next_walk_state); return_ACPI_STATUS(status); } @@ -366,15 +386,15 @@ acpi_ds_restart_control_method(struct acpi_walk_state *walk_state, { acpi_status status; - ACPI_FUNCTION_TRACE_PTR("ds_restart_control_method", walk_state); + ACPI_FUNCTION_TRACE_PTR(ds_restart_control_method, walk_state); ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "****Restart [%4.4s] Op %p return_value_from_callee %p\n", + "****Restart [%4.4s] Op %p ReturnValueFromCallee %p\n", (char *)&walk_state->method_node->name, walk_state->method_call_op, return_desc)); ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - " return_from_this_method_used?=%X res_stack %p Walk %p\n", + " ReturnFromThisMethodUsed?=%X ResStack %p Walk %p\n", walk_state->return_used, walk_state->results, walk_state)); @@ -426,7 +446,8 @@ acpi_ds_restart_control_method(struct acpi_walk_state *walk_state, * * FUNCTION: acpi_ds_terminate_control_method * - * PARAMETERS: walk_state - State of the method + * PARAMETERS: method_desc - Method object + * walk_state - State associated with the method * * RETURN: None * @@ -436,28 +457,27 @@ acpi_ds_restart_control_method(struct acpi_walk_state *walk_state, * ******************************************************************************/ -void acpi_ds_terminate_control_method(struct acpi_walk_state *walk_state) +void +acpi_ds_terminate_control_method(union acpi_operand_object *method_desc, + struct acpi_walk_state *walk_state) { - union acpi_operand_object *obj_desc; struct acpi_namespace_node *method_node; acpi_status status; - ACPI_FUNCTION_TRACE_PTR("ds_terminate_control_method", walk_state); - - if (!walk_state) { - return_VOID; - } + ACPI_FUNCTION_TRACE_PTR(ds_terminate_control_method, walk_state); - /* The current method object was saved in the walk state */ + /* method_desc is required, walk_state is optional */ - obj_desc = walk_state->method_desc; - if (!obj_desc) { + if (!method_desc) { return_VOID; } - /* Delete all arguments and locals */ + if (walk_state) { - acpi_ds_method_data_delete_all(walk_state); + /* Delete all arguments and locals */ + + acpi_ds_method_data_delete_all(walk_state); + } /* * Lock the parser while we terminate this method. @@ -471,60 +491,66 @@ void acpi_ds_terminate_control_method(struct acpi_walk_state *walk_state) /* Signal completion of the execution of this method if necessary */ - if (walk_state->method_desc->method.semaphore) { + if (method_desc->method.semaphore) { status = - acpi_os_signal_semaphore(walk_state->method_desc->method. - semaphore, 1); + acpi_os_signal_semaphore(method_desc->method.semaphore, 1); if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, - "Could not signal method semaphore")); - /* Ignore error and continue cleanup */ + /* Ignore error and continue */ + + ACPI_EXCEPTION((AE_INFO, status, + "Could not signal method semaphore")); } } - /* - * There are no more threads executing this method. Perform - * additional cleanup. - * - * The method Node is stored in the walk state - */ - method_node = walk_state->method_node; + if (walk_state) { + /* + * Delete any objects created by this method during execution. + * The method Node is stored in the walk state + */ + method_node = walk_state->method_node; - /* Lock namespace for possible update */ + /* Lock namespace for possible update */ - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - goto exit; - } + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + goto exit; + } - /* - * Delete any namespace entries created immediately underneath - * the method - */ - if (method_node && method_node->child) { - acpi_ns_delete_namespace_subtree(method_node); + /* + * Delete any namespace entries created immediately underneath + * the method + */ + if (method_node && method_node->child) { + acpi_ns_delete_namespace_subtree(method_node); + } + + /* + * Delete any namespace entries created anywhere else within + * the namespace by the execution of this method + */ + acpi_ns_delete_namespace_by_owner(method_desc->method.owner_id); + status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); } - /* - * Delete any namespace entries created anywhere else within - * the namespace by the execution of this method - */ - acpi_ns_delete_namespace_by_owner(walk_state->method_desc->method. - owner_id); - status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + /* Decrement the thread count on the method */ + + if (method_desc->method.thread_count) { + method_desc->method.thread_count--; + } else { + ACPI_ERROR((AE_INFO, "Invalid zero thread count in method")); + } /* Are there any other threads currently executing this method? */ - if (walk_state->method_desc->method.thread_count) { + if (method_desc->method.thread_count) { /* * Additional threads. Do not release the owner_id in this case, * we immediately reuse it for the next thread executing this method */ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "*** Completed execution of one thread, %d threads remaining\n", - walk_state->method_desc->method. - thread_count)); + method_desc->method.thread_count)); } else { /* This is the only executing thread for this method */ @@ -538,18 +564,16 @@ void acpi_ds_terminate_control_method(struct acpi_walk_state *walk_state) * This code is here because we must wait until the last thread exits * before creating the synchronization semaphore. */ - if ((walk_state->method_desc->method.concurrency == 1) && - (!walk_state->method_desc->method.semaphore)) { + if ((method_desc->method.concurrency == 1) && + (!method_desc->method.semaphore)) { status = acpi_os_create_semaphore(1, 1, - &walk_state-> - method_desc->method. + &method_desc->method. semaphore); } /* No more threads, we can free the owner_id */ - acpi_ut_release_owner_id(&walk_state->method_desc->method. - owner_id); + acpi_ut_release_owner_id(&method_desc->method.owner_id); } exit: @@ -586,7 +610,7 @@ acpi_status acpi_ds_parse_method(struct acpi_namespace_node *node) union acpi_parse_object *op; struct acpi_walk_state *walk_state; - ACPI_FUNCTION_TRACE_PTR("ds_parse_method", node); + ACPI_FUNCTION_TRACE_PTR(ds_parse_method, node); /* Parameter Validation */ @@ -595,7 +619,7 @@ acpi_status acpi_ds_parse_method(struct acpi_namespace_node *node) } ACPI_DEBUG_PRINT((ACPI_DB_PARSE, - "**** Parsing [%4.4s] **** named_obj=%p\n", + "**** Parsing [%4.4s] **** NamedObj=%p\n", acpi_ut_get_node_name(node), node)); /* Extract the method object from the method Node */ @@ -674,7 +698,7 @@ acpi_status acpi_ds_parse_method(struct acpi_namespace_node *node) } ACPI_DEBUG_PRINT((ACPI_DB_PARSE, - "**** [%4.4s] Parsed **** named_obj=%p Op=%p\n", + "**** [%4.4s] Parsed **** NamedObj=%p Op=%p\n", acpi_ut_get_node_name(node), node, op)); /* diff --git a/drivers/acpi/dispatcher/dsmthdat.c b/drivers/acpi/dispatcher/dsmthdat.c index ce4de18f122..b47c54fad86 100644 --- a/drivers/acpi/dispatcher/dsmthdat.c +++ b/drivers/acpi/dispatcher/dsmthdat.c @@ -92,7 +92,7 @@ void acpi_ds_method_data_init(struct acpi_walk_state *walk_state) { u32 i; - ACPI_FUNCTION_TRACE("ds_method_data_init"); + ACPI_FUNCTION_TRACE(ds_method_data_init); /* Init the method arguments */ @@ -140,7 +140,7 @@ void acpi_ds_method_data_delete_all(struct acpi_walk_state *walk_state) { u32 index; - ACPI_FUNCTION_TRACE("ds_method_data_delete_all"); + ACPI_FUNCTION_TRACE(ds_method_data_delete_all); /* Detach the locals */ @@ -199,7 +199,7 @@ acpi_ds_method_data_init_args(union acpi_operand_object **params, acpi_status status; u32 index = 0; - ACPI_FUNCTION_TRACE_PTR("ds_method_data_init_args", params); + ACPI_FUNCTION_TRACE_PTR(ds_method_data_init_args, params); if (!params) { ACPI_DEBUG_PRINT((ACPI_DB_EXEC, @@ -251,7 +251,7 @@ acpi_ds_method_data_get_node(u16 opcode, struct acpi_walk_state *walk_state, struct acpi_namespace_node **node) { - ACPI_FUNCTION_TRACE("ds_method_data_get_node"); + ACPI_FUNCTION_TRACE(ds_method_data_get_node); /* * Method Locals and Arguments are supported @@ -318,10 +318,10 @@ acpi_ds_method_data_set_value(u16 opcode, acpi_status status; struct acpi_namespace_node *node; - ACPI_FUNCTION_TRACE("ds_method_data_set_value"); + ACPI_FUNCTION_TRACE(ds_method_data_set_value); ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "new_obj %p Opcode %X, Refs=%d [%s]\n", object, + "NewObj %p Opcode %X, Refs=%d [%s]\n", object, opcode, object->common.reference_count, acpi_ut_get_type_name(object->common.type))); @@ -372,7 +372,7 @@ acpi_ds_method_data_get_value(u16 opcode, struct acpi_namespace_node *node; union acpi_operand_object *object; - ACPI_FUNCTION_TRACE("ds_method_data_get_value"); + ACPI_FUNCTION_TRACE(ds_method_data_get_value); /* Validate the object descriptor */ @@ -477,7 +477,7 @@ acpi_ds_method_data_delete_value(u16 opcode, struct acpi_namespace_node *node; union acpi_operand_object *object; - ACPI_FUNCTION_TRACE("ds_method_data_delete_value"); + ACPI_FUNCTION_TRACE(ds_method_data_delete_value); /* Get the namespace node for the arg/local */ @@ -538,7 +538,7 @@ acpi_ds_store_object_to_local(u16 opcode, union acpi_operand_object *current_obj_desc; union acpi_operand_object *new_obj_desc; - ACPI_FUNCTION_TRACE("ds_store_object_to_local"); + ACPI_FUNCTION_TRACE(ds_store_object_to_local); ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Opcode=%X Index=%d Obj=%p\n", opcode, index, obj_desc)); @@ -614,7 +614,7 @@ acpi_ds_store_object_to_local(u16 opcode, && (current_obj_desc->reference.opcode == AML_REF_OF_OP)) { ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Arg (%p) is an obj_ref(Node), storing in node %p\n", + "Arg (%p) is an ObjRef(Node), storing in node %p\n", new_obj_desc, current_obj_desc)); @@ -688,7 +688,7 @@ acpi_ds_method_data_get_type(u16 opcode, struct acpi_namespace_node *node; union acpi_operand_object *object; - ACPI_FUNCTION_TRACE("ds_method_data_get_type"); + ACPI_FUNCTION_TRACE(ds_method_data_get_type); /* Get the namespace node for the arg/local */ diff --git a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c index ce54715f13a..72190abb1d5 100644 --- a/drivers/acpi/dispatcher/dsobject.c +++ b/drivers/acpi/dispatcher/dsobject.c @@ -81,7 +81,7 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, union acpi_operand_object *obj_desc; acpi_status status; - ACPI_FUNCTION_TRACE("ds_build_internal_object"); + ACPI_FUNCTION_TRACE(ds_build_internal_object); *obj_desc_ptr = NULL; if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) { @@ -187,7 +187,7 @@ acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state, union acpi_parse_object *byte_list; u32 byte_list_length = 0; - ACPI_FUNCTION_TRACE("ds_build_internal_buffer_obj"); + ACPI_FUNCTION_TRACE(ds_build_internal_buffer_obj); /* * If we are evaluating a Named buffer object "Name (xxxx, Buffer)". @@ -293,7 +293,7 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, acpi_status status = AE_OK; acpi_native_uint i; - ACPI_FUNCTION_TRACE("ds_build_internal_package_obj"); + ACPI_FUNCTION_TRACE(ds_build_internal_package_obj); /* Find the parent of a possibly nested package */ @@ -400,7 +400,7 @@ acpi_ds_create_node(struct acpi_walk_state *walk_state, acpi_status status; union acpi_operand_object *obj_desc; - ACPI_FUNCTION_TRACE_PTR("ds_create_node", op); + ACPI_FUNCTION_TRACE_PTR(ds_create_node, op); /* * Because of the execution pass through the non-control-method @@ -469,7 +469,7 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state, union acpi_operand_object *obj_desc; acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("ds_init_object_from_op"); + ACPI_FUNCTION_TRACE(ds_init_object_from_op); obj_desc = *ret_obj_desc; op_info = acpi_ps_get_opcode_info(opcode); diff --git a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c index 8a690a9963f..5b974a8fe61 100644 --- a/drivers/acpi/dispatcher/dsopcode.c +++ b/drivers/acpi/dispatcher/dsopcode.c @@ -91,7 +91,7 @@ acpi_ds_execute_arguments(struct acpi_namespace_node *node, union acpi_parse_object *op; struct acpi_walk_state *walk_state; - ACPI_FUNCTION_TRACE("ds_execute_arguments"); + ACPI_FUNCTION_TRACE(ds_execute_arguments); /* * Allocate a new parser op to be the root of the parsed tree @@ -193,7 +193,7 @@ acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc) struct acpi_namespace_node *node; acpi_status status; - ACPI_FUNCTION_TRACE_PTR("ds_get_buffer_field_arguments", obj_desc); + ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_field_arguments, obj_desc); if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { return_ACPI_STATUS(AE_OK); @@ -206,7 +206,7 @@ acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc) ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname (ACPI_TYPE_BUFFER_FIELD, node, NULL)); - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] buffer_field Arg Init\n", + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BufferField Arg Init\n", acpi_ut_get_node_name(node))); /* Execute the AML code for the term_arg arguments */ @@ -235,7 +235,7 @@ acpi_status acpi_ds_get_buffer_arguments(union acpi_operand_object *obj_desc) struct acpi_namespace_node *node; acpi_status status; - ACPI_FUNCTION_TRACE_PTR("ds_get_buffer_arguments", obj_desc); + ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_arguments, obj_desc); if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { return_ACPI_STATUS(AE_OK); @@ -279,7 +279,7 @@ acpi_status acpi_ds_get_package_arguments(union acpi_operand_object *obj_desc) struct acpi_namespace_node *node; acpi_status status; - ACPI_FUNCTION_TRACE_PTR("ds_get_package_arguments", obj_desc); + ACPI_FUNCTION_TRACE_PTR(ds_get_package_arguments, obj_desc); if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { return_ACPI_STATUS(AE_OK); @@ -324,7 +324,7 @@ acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc) acpi_status status; union acpi_operand_object *extra_desc; - ACPI_FUNCTION_TRACE_PTR("ds_get_region_arguments", obj_desc); + ACPI_FUNCTION_TRACE_PTR(ds_get_region_arguments, obj_desc); if (obj_desc->region.flags & AOPOBJ_DATA_VALID) { return_ACPI_STATUS(AE_OK); @@ -342,8 +342,7 @@ acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc) ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname (ACPI_TYPE_REGION, node, NULL)); - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "[%4.4s] op_region Arg Init at AML %p\n", + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] OpRegion Arg Init at AML %p\n", acpi_ut_get_node_name(node), extra_desc->extra.aml_start)); @@ -352,6 +351,28 @@ acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc) status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node), extra_desc->extra.aml_length, extra_desc->extra.aml_start); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Validate the region address/length via the host OS */ + + status = acpi_os_validate_address(obj_desc->region.space_id, + obj_desc->region.address, + (acpi_size) obj_desc->region.length); + if (ACPI_FAILURE(status)) { + /* + * Invalid address/length. We will emit an error message and mark + * the region as invalid, so that it will cause an additional error if + * it is ever used. Then return AE_OK. + */ + ACPI_EXCEPTION((AE_INFO, status, + "During address validation of OpRegion [%4.4s]", + node->name.ascii)); + obj_desc->common.flags |= AOPOBJ_INVALID; + status = AE_OK; + } + return_ACPI_STATUS(status); } @@ -411,7 +432,7 @@ acpi_ds_init_buffer_field(u16 aml_opcode, u8 field_flags; acpi_status status; - ACPI_FUNCTION_TRACE_PTR("ds_init_buffer_field", obj_desc); + ACPI_FUNCTION_TRACE_PTR(ds_init_buffer_field, obj_desc); /* Host object must be a Buffer */ @@ -457,7 +478,7 @@ acpi_ds_init_buffer_field(u16 aml_opcode, if (bit_count == 0) { ACPI_ERROR((AE_INFO, - "Attempt to create_field of length zero")); + "Attempt to CreateField of length zero")); status = AE_AML_OPERAND_VALUE; goto cleanup; } @@ -595,7 +616,7 @@ acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state, struct acpi_namespace_node *node; union acpi_parse_object *next_op; - ACPI_FUNCTION_TRACE_PTR("ds_eval_buffer_field_operands", op); + ACPI_FUNCTION_TRACE_PTR(ds_eval_buffer_field_operands, op); /* * This is where we evaluate the address and length fields of the @@ -627,7 +648,7 @@ acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state, ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE, acpi_ps_get_opcode_name(op->common.aml_opcode), walk_state->num_operands, - "after acpi_ex_resolve_operands"); + "after AcpiExResolveOperands"); if (ACPI_FAILURE(status)) { ACPI_ERROR((AE_INFO, "(%s) bad operand(s) (%X)", @@ -686,7 +707,7 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state, struct acpi_namespace_node *node; union acpi_parse_object *next_op; - ACPI_FUNCTION_TRACE_PTR("ds_eval_region_operands", op); + ACPI_FUNCTION_TRACE_PTR(ds_eval_region_operands, op); /* * This is where we evaluate the address and length fields of the @@ -719,7 +740,7 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state, ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE, acpi_ps_get_opcode_name(op->common.aml_opcode), - 1, "after acpi_ex_resolve_operands"); + 1, "after AcpiExResolveOperands"); obj_desc = acpi_ns_get_attached_object(node); if (!obj_desc) { @@ -745,7 +766,7 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state, operand_desc->integer.value; acpi_ut_remove_reference(operand_desc); - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "rgn_obj %p Addr %8.8X%8.8X Len %X\n", + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", obj_desc, ACPI_FORMAT_UINT64(obj_desc->region.address), obj_desc->region.length)); @@ -781,7 +802,7 @@ acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state, union acpi_operand_object *arg_desc; u32 length; - ACPI_FUNCTION_TRACE("ds_eval_data_object_operands"); + ACPI_FUNCTION_TRACE(ds_eval_data_object_operands); /* The first operand (for all of these data objects) is the length */ @@ -875,7 +896,7 @@ acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state, acpi_status status = AE_OK; union acpi_generic_state *control_state; - ACPI_FUNCTION_NAME("ds_exec_begin_control_op"); + ACPI_FUNCTION_NAME(ds_exec_begin_control_op); ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p Opcode=%2.2X State=%p\n", op, op->common.aml_opcode, walk_state)); @@ -953,7 +974,7 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state, acpi_status status = AE_OK; union acpi_generic_state *control_state; - ACPI_FUNCTION_NAME("ds_exec_end_control_op"); + ACPI_FUNCTION_NAME(ds_exec_end_control_op); switch (op->common.aml_opcode) { case AML_IF_OP: @@ -1099,7 +1120,7 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state, } ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "Completed RETURN_OP State=%p, ret_val=%p\n", + "Completed RETURN_OP State=%p, RetVal=%p\n", walk_state, walk_state->return_desc)); /* End the control method execution right now */ diff --git a/drivers/acpi/dispatcher/dsutils.c b/drivers/acpi/dispatcher/dsutils.c index ab24aa88e2f..05230baf5de 100644 --- a/drivers/acpi/dispatcher/dsutils.c +++ b/drivers/acpi/dispatcher/dsutils.c @@ -68,7 +68,7 @@ ACPI_MODULE_NAME("dsutils") ******************************************************************************/ void acpi_ds_clear_implicit_return(struct acpi_walk_state *walk_state) { - ACPI_FUNCTION_NAME("ds_clear_implicit_return"); + ACPI_FUNCTION_NAME(ds_clear_implicit_return); /* * Slack must be enabled for this feature @@ -115,7 +115,7 @@ u8 acpi_ds_do_implicit_return(union acpi_operand_object *return_desc, struct acpi_walk_state *walk_state, u8 add_reference) { - ACPI_FUNCTION_NAME("ds_do_implicit_return"); + ACPI_FUNCTION_NAME(ds_do_implicit_return); /* * Slack must be enabled for this feature, and we must @@ -171,7 +171,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op, { const struct acpi_opcode_info *parent_info; - ACPI_FUNCTION_TRACE_PTR("ds_is_result_used", op); + ACPI_FUNCTION_TRACE_PTR(ds_is_result_used, op); /* Must have both an Op and a Result Object */ @@ -341,7 +341,7 @@ acpi_ds_delete_result_if_not_used(union acpi_parse_object *op, union acpi_operand_object *obj_desc; acpi_status status; - ACPI_FUNCTION_TRACE_PTR("ds_delete_result_if_not_used", result_obj); + ACPI_FUNCTION_TRACE_PTR(ds_delete_result_if_not_used, result_obj); if (!op) { ACPI_ERROR((AE_INFO, "Null Op")); @@ -384,7 +384,7 @@ acpi_status acpi_ds_resolve_operands(struct acpi_walk_state *walk_state) u32 i; acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE_PTR("ds_resolve_operands", walk_state); + ACPI_FUNCTION_TRACE_PTR(ds_resolve_operands, walk_state); /* * Attempt to resolve each of the valid operands @@ -419,7 +419,7 @@ void acpi_ds_clear_operands(struct acpi_walk_state *walk_state) { u32 i; - ACPI_FUNCTION_TRACE_PTR("ds_clear_operands", walk_state); + ACPI_FUNCTION_TRACE_PTR(ds_clear_operands, walk_state); /* Remove a reference on each operand on the stack */ @@ -467,7 +467,7 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, acpi_interpreter_mode interpreter_mode; const struct acpi_opcode_info *op_info; - ACPI_FUNCTION_TRACE_PTR("ds_create_operand", arg); + ACPI_FUNCTION_TRACE_PTR(ds_create_operand, arg); /* A valid name must be looked up in the namespace */ @@ -701,7 +701,7 @@ acpi_ds_create_operands(struct acpi_walk_state *walk_state, union acpi_parse_object *arg; u32 arg_count = 0; - ACPI_FUNCTION_TRACE_PTR("ds_create_operands", first_arg); + ACPI_FUNCTION_TRACE_PTR(ds_create_operands, first_arg); /* For all arguments in the list... */ diff --git a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c index 8b740b370eb..8afb20384e9 100644 --- a/drivers/acpi/dispatcher/dswexec.c +++ b/drivers/acpi/dispatcher/dswexec.c @@ -92,7 +92,7 @@ acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state, union acpi_operand_object *obj_desc; union acpi_operand_object *local_obj_desc = NULL; - ACPI_FUNCTION_TRACE_PTR("ds_get_predicate_value", walk_state); + ACPI_FUNCTION_TRACE_PTR(ds_get_predicate_value, walk_state); walk_state->control_state->common.state = 0; @@ -122,7 +122,7 @@ acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state, if (!obj_desc) { ACPI_ERROR((AE_INFO, - "No predicate obj_desc=%p State=%p", + "No predicate ObjDesc=%p State=%p", obj_desc, walk_state)); return_ACPI_STATUS(AE_AML_NO_OPERAND); @@ -139,7 +139,7 @@ acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state, if (ACPI_GET_OBJECT_TYPE(local_obj_desc) != ACPI_TYPE_INTEGER) { ACPI_ERROR((AE_INFO, - "Bad predicate (not an integer) obj_desc=%p State=%p Type=%X", + "Bad predicate (not an integer) ObjDesc=%p State=%p Type=%X", obj_desc, walk_state, ACPI_GET_OBJECT_TYPE(obj_desc))); @@ -213,7 +213,7 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state, acpi_status status = AE_OK; u32 opcode_class; - ACPI_FUNCTION_TRACE_PTR("ds_exec_begin_op", walk_state); + ACPI_FUNCTION_TRACE_PTR(ds_exec_begin_op, walk_state); op = walk_state->op; if (!op) { @@ -353,7 +353,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) union acpi_parse_object *next_op; union acpi_parse_object *first_arg; - ACPI_FUNCTION_TRACE_PTR("ds_exec_end_op", walk_state); + ACPI_FUNCTION_TRACE_PTR(ds_exec_end_op, walk_state); op = walk_state->op; op_type = walk_state->op_info->type; @@ -423,7 +423,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) acpi_ps_get_opcode_name (walk_state->opcode), walk_state->num_operands, - "after ex_resolve_operands"); + "after ExResolveOperands"); } } @@ -437,7 +437,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) acpi_gbl_op_type_dispatch[op_type] (walk_state); } else { /* - * Treat constructs of the form "Store(local_x,local_x)" as noops when the + * Treat constructs of the form "Store(LocalX,LocalX)" as noops when the * Local is uninitialized. */ if ((status == AE_AML_UNINITIALIZED_LOCAL) && @@ -570,7 +570,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) case AML_TYPE_CREATE_FIELD: ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Executing create_field Buffer/Index Op=%p\n", + "Executing CreateField Buffer/Index Op=%p\n", op)); status = acpi_ds_load2_end_op(walk_state); @@ -585,7 +585,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) case AML_TYPE_CREATE_OBJECT: ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Executing create_object (Buffer/Package) Op=%p\n", + "Executing CreateObject (Buffer/Package) Op=%p\n", op)); switch (op->common.parent->common.aml_opcode) { @@ -658,7 +658,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) if (op->common.aml_opcode == AML_REGION_OP) { ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Executing op_region Address/Length Op=%p\n", + "Executing OpRegion Address/Length Op=%p\n", op)); status = diff --git a/drivers/acpi/dispatcher/dswload.c b/drivers/acpi/dispatcher/dswload.c index 1ad7870101f..a8deb700cf3 100644 --- a/drivers/acpi/dispatcher/dswload.c +++ b/drivers/acpi/dispatcher/dswload.c @@ -127,7 +127,7 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, char *path; u32 flags; - ACPI_FUNCTION_TRACE("ds_load1_begin_op"); + ACPI_FUNCTION_TRACE(ds_load1_begin_op); op = walk_state->op; ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, @@ -361,7 +361,7 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state) acpi_object_type object_type; acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("ds_load1_end_op"); + ACPI_FUNCTION_TRACE(ds_load1_end_op); op = walk_state->op; ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, @@ -448,7 +448,7 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state) * arguments.) */ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "LOADING-Method: State=%p Op=%p named_obj=%p\n", + "LOADING-Method: State=%p Op=%p NamedObj=%p\n", walk_state, op, op->named.node)); if (!acpi_ns_get_attached_object(op->named.node)) { @@ -514,7 +514,7 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, acpi_object_type object_type; char *buffer_ptr; - ACPI_FUNCTION_TRACE("ds_load2_begin_op"); + ACPI_FUNCTION_TRACE(ds_load2_begin_op); op = walk_state->op; ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, @@ -785,7 +785,7 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) u32 i; #endif - ACPI_FUNCTION_TRACE("ds_load2_end_op"); + ACPI_FUNCTION_TRACE(ds_load2_end_op); op = walk_state->op; ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Opcode [%s] Op %p State %p\n", @@ -879,7 +879,7 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) */ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "Create-Load [%s] State=%p Op=%p named_obj=%p\n", + "Create-Load [%s] State=%p Op=%p NamedObj=%p\n", acpi_ps_get_opcode_name(op->common.aml_opcode), walk_state, op, node)); @@ -1054,7 +1054,7 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) * arguments.) */ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "LOADING-Method: State=%p Op=%p named_obj=%p\n", + "LOADING-Method: State=%p Op=%p NamedObj=%p\n", walk_state, op, op->named.node)); if (!acpi_ns_get_attached_object(op->named.node)) { @@ -1099,7 +1099,7 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) case AML_CLASS_METHOD_CALL: ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "RESOLVING-method_call: State=%p Op=%p named_obj=%p\n", + "RESOLVING-MethodCall: State=%p Op=%p NamedObj=%p\n", walk_state, op, node)); /* diff --git a/drivers/acpi/dispatcher/dswscope.c b/drivers/acpi/dispatcher/dswscope.c index 3cd6895ed2c..c9228972f5f 100644 --- a/drivers/acpi/dispatcher/dswscope.c +++ b/drivers/acpi/dispatcher/dswscope.c @@ -63,7 +63,7 @@ void acpi_ds_scope_stack_clear(struct acpi_walk_state *walk_state) { union acpi_generic_state *scope_info; - ACPI_FUNCTION_NAME("ds_scope_stack_clear"); + ACPI_FUNCTION_NAME(ds_scope_stack_clear); while (walk_state->scope_info) { @@ -103,7 +103,7 @@ acpi_ds_scope_stack_push(struct acpi_namespace_node *node, union acpi_generic_state *scope_info; union acpi_generic_state *old_scope_info; - ACPI_FUNCTION_TRACE("ds_scope_stack_push"); + ACPI_FUNCTION_TRACE(ds_scope_stack_push); if (!node) { @@ -178,7 +178,7 @@ acpi_status acpi_ds_scope_stack_pop(struct acpi_walk_state *walk_state) union acpi_generic_state *scope_info; union acpi_generic_state *new_scope_info; - ACPI_FUNCTION_TRACE("ds_scope_stack_pop"); + ACPI_FUNCTION_TRACE(ds_scope_stack_pop); /* * Pop scope info object off the stack. diff --git a/drivers/acpi/dispatcher/dswstate.c b/drivers/acpi/dispatcher/dswstate.c index 4840eae47d3..82c1e219bf1 100644 --- a/drivers/acpi/dispatcher/dswstate.c +++ b/drivers/acpi/dispatcher/dswstate.c @@ -87,7 +87,7 @@ acpi_ds_result_remove(union acpi_operand_object **object, { union acpi_generic_state *state; - ACPI_FUNCTION_NAME("ds_result_remove"); + ACPI_FUNCTION_NAME(ds_result_remove); state = walk_state->results; if (!state) { @@ -150,7 +150,7 @@ acpi_ds_result_pop(union acpi_operand_object ** object, acpi_native_uint index; union acpi_generic_state *state; - ACPI_FUNCTION_NAME("ds_result_pop"); + ACPI_FUNCTION_NAME(ds_result_pop); state = walk_state->results; if (!state) { @@ -212,7 +212,7 @@ acpi_ds_result_pop_from_bottom(union acpi_operand_object ** object, acpi_native_uint index; union acpi_generic_state *state; - ACPI_FUNCTION_NAME("ds_result_pop_from_bottom"); + ACPI_FUNCTION_NAME(ds_result_pop_from_bottom); state = walk_state->results; if (!state) { @@ -277,7 +277,7 @@ acpi_ds_result_push(union acpi_operand_object * object, { union acpi_generic_state *state; - ACPI_FUNCTION_NAME("ds_result_push"); + ACPI_FUNCTION_NAME(ds_result_push); state = walk_state->results; if (!state) { @@ -330,7 +330,7 @@ acpi_status acpi_ds_result_stack_push(struct acpi_walk_state * walk_state) { union acpi_generic_state *state; - ACPI_FUNCTION_NAME("ds_result_stack_push"); + ACPI_FUNCTION_NAME(ds_result_stack_push); state = acpi_ut_create_generic_state(); if (!state) { @@ -362,7 +362,7 @@ acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state * walk_state) { union acpi_generic_state *state; - ACPI_FUNCTION_NAME("ds_result_stack_pop"); + ACPI_FUNCTION_NAME(ds_result_stack_pop); /* Check for stack underflow */ @@ -375,7 +375,7 @@ acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state * walk_state) state = acpi_ut_pop_generic_state(&walk_state->results); ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Result=%p remaining_results=%X State=%p\n", + "Result=%p RemainingResults=%X State=%p\n", state, state->results.num_results, walk_state)); acpi_ut_delete_generic_state(state); @@ -399,7 +399,7 @@ acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state * walk_state) acpi_status acpi_ds_obj_stack_push(void *object, struct acpi_walk_state * walk_state) { - ACPI_FUNCTION_NAME("ds_obj_stack_push"); + ACPI_FUNCTION_NAME(ds_obj_stack_push); /* Check for stack overflow */ @@ -444,7 +444,7 @@ acpi_ds_obj_stack_pop(u32 pop_count, struct acpi_walk_state * walk_state) { u32 i; - ACPI_FUNCTION_NAME("ds_obj_stack_pop"); + ACPI_FUNCTION_NAME(ds_obj_stack_pop); for (i = 0; i < pop_count; i++) { @@ -491,7 +491,7 @@ acpi_ds_obj_stack_pop_and_delete(u32 pop_count, u32 i; union acpi_operand_object *obj_desc; - ACPI_FUNCTION_NAME("ds_obj_stack_pop_and_delete"); + ACPI_FUNCTION_NAME(ds_obj_stack_pop_and_delete); for (i = 0; i < pop_count; i++) { @@ -539,13 +539,13 @@ acpi_ds_obj_stack_pop_and_delete(u32 pop_count, struct acpi_walk_state *acpi_ds_get_current_walk_state(struct acpi_thread_state *thread) { - ACPI_FUNCTION_NAME("ds_get_current_walk_state"); + ACPI_FUNCTION_NAME(ds_get_current_walk_state); if (!thread) { return (NULL); } - ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Current walk_state %p\n", + ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Current WalkState %p\n", thread->walk_state_list)); return (thread->walk_state_list); @@ -568,7 +568,7 @@ void acpi_ds_push_walk_state(struct acpi_walk_state *walk_state, struct acpi_thread_state *thread) { - ACPI_FUNCTION_TRACE("ds_push_walk_state"); + ACPI_FUNCTION_TRACE(ds_push_walk_state); walk_state->next = thread->walk_state_list; thread->walk_state_list = walk_state; @@ -594,7 +594,7 @@ struct acpi_walk_state *acpi_ds_pop_walk_state(struct acpi_thread_state *thread) { struct acpi_walk_state *walk_state; - ACPI_FUNCTION_TRACE("ds_pop_walk_state"); + ACPI_FUNCTION_TRACE(ds_pop_walk_state); walk_state = thread->walk_state_list; @@ -641,7 +641,7 @@ struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id, struct acpi_walk_state *walk_state; acpi_status status; - ACPI_FUNCTION_TRACE("ds_create_walk_state"); + ACPI_FUNCTION_TRACE(ds_create_walk_state); walk_state = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_walk_state)); if (!walk_state) { @@ -709,7 +709,7 @@ acpi_ds_init_aml_walk(struct acpi_walk_state *walk_state, struct acpi_parse_state *parser_state = &walk_state->parser_state; union acpi_parse_object *extra_op; - ACPI_FUNCTION_TRACE("ds_init_aml_walk"); + ACPI_FUNCTION_TRACE(ds_init_aml_walk); walk_state->parser_state.aml = walk_state->parser_state.aml_start = aml_start; @@ -813,7 +813,7 @@ void acpi_ds_delete_walk_state(struct acpi_walk_state *walk_state) { union acpi_generic_state *state; - ACPI_FUNCTION_TRACE_PTR("ds_delete_walk_state", walk_state); + ACPI_FUNCTION_TRACE_PTR(ds_delete_walk_state, walk_state); if (!walk_state) { return; @@ -882,7 +882,7 @@ acpi_ds_result_insert(void *object, { union acpi_generic_state *state; - ACPI_FUNCTION_NAME("ds_result_insert"); + ACPI_FUNCTION_NAME(ds_result_insert); state = walk_state->results; if (!state) { @@ -940,7 +940,7 @@ acpi_status acpi_ds_obj_stack_delete_all(struct acpi_walk_state * walk_state) { u32 i; - ACPI_FUNCTION_TRACE_PTR("ds_obj_stack_delete_all", walk_state); + ACPI_FUNCTION_TRACE_PTR(ds_obj_stack_delete_all, walk_state); /* The stack size is configurable, but fixed */ @@ -972,7 +972,7 @@ acpi_status acpi_ds_obj_stack_pop_object(union acpi_operand_object **object, struct acpi_walk_state *walk_state) { - ACPI_FUNCTION_NAME("ds_obj_stack_pop_object"); + ACPI_FUNCTION_NAME(ds_obj_stack_pop_object); /* Check for stack underflow */ @@ -1028,7 +1028,7 @@ acpi_ds_obj_stack_pop_object(union acpi_operand_object **object, void *acpi_ds_obj_stack_get_value(u32 index, struct acpi_walk_state *walk_state) { - ACPI_FUNCTION_TRACE_PTR("ds_obj_stack_get_value", walk_state); + ACPI_FUNCTION_TRACE_PTR(ds_obj_stack_get_value, walk_state); /* Can't do it if the stack is empty */ diff --git a/drivers/acpi/events/evevent.c b/drivers/acpi/events/evevent.c index c8d9752e312..919037d6acf 100644 --- a/drivers/acpi/events/evevent.c +++ b/drivers/acpi/events/evevent.c @@ -68,7 +68,7 @@ acpi_status acpi_ev_initialize_events(void) { acpi_status status; - ACPI_FUNCTION_TRACE("ev_initialize_events"); + ACPI_FUNCTION_TRACE(ev_initialize_events); /* Make sure we have ACPI tables */ @@ -118,7 +118,7 @@ acpi_status acpi_ev_install_fadt_gpes(void) { acpi_status status; - ACPI_FUNCTION_TRACE("ev_install_fadt_gpes"); + ACPI_FUNCTION_TRACE(ev_install_fadt_gpes); /* Namespace must be locked */ @@ -157,7 +157,7 @@ acpi_status acpi_ev_install_xrupt_handlers(void) { acpi_status status; - ACPI_FUNCTION_TRACE("ev_install_xrupt_handlers"); + ACPI_FUNCTION_TRACE(ev_install_xrupt_handlers); /* Install the SCI handler */ @@ -241,7 +241,7 @@ u32 acpi_ev_fixed_event_detect(void) u32 fixed_enable; acpi_native_uint i; - ACPI_FUNCTION_NAME("ev_fixed_event_detect"); + ACPI_FUNCTION_NAME(ev_fixed_event_detect); /* * Read the fixed feature status and enable registers, as all the cases diff --git a/drivers/acpi/events/evgpe.c b/drivers/acpi/events/evgpe.c index 7d7b81af972..25fd12a29a2 100644 --- a/drivers/acpi/events/evgpe.c +++ b/drivers/acpi/events/evgpe.c @@ -69,7 +69,7 @@ acpi_ev_set_gpe_type(struct acpi_gpe_event_info *gpe_event_info, u8 type) { acpi_status status; - ACPI_FUNCTION_TRACE("ev_set_gpe_type"); + ACPI_FUNCTION_TRACE(ev_set_gpe_type); /* Validate type and update register enable masks */ @@ -115,7 +115,7 @@ acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info, struct acpi_gpe_register_info *gpe_register_info; u8 register_bit; - ACPI_FUNCTION_TRACE("ev_update_gpe_enable_masks"); + ACPI_FUNCTION_TRACE(ev_update_gpe_enable_masks); gpe_register_info = gpe_event_info->register_info; if (!gpe_register_info) { @@ -178,7 +178,7 @@ acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info, { acpi_status status; - ACPI_FUNCTION_TRACE("ev_enable_gpe"); + ACPI_FUNCTION_TRACE(ev_enable_gpe); /* Make sure HW enable masks are updated */ @@ -244,7 +244,7 @@ acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info) { acpi_status status; - ACPI_FUNCTION_TRACE("ev_disable_gpe"); + ACPI_FUNCTION_TRACE(ev_disable_gpe); if (!(gpe_event_info->flags & ACPI_GPE_ENABLE_MASK)) { return_ACPI_STATUS(AE_OK); @@ -385,7 +385,7 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) acpi_native_uint i; acpi_native_uint j; - ACPI_FUNCTION_NAME("ev_gpe_detect"); + ACPI_FUNCTION_NAME(ev_gpe_detect); /* Check for the case where there are no GPEs */ @@ -504,7 +504,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) struct acpi_gpe_event_info local_gpe_event_info; struct acpi_parameter_info info; - ACPI_FUNCTION_TRACE("ev_asynch_execute_gpe_method"); + ACPI_FUNCTION_TRACE(ev_asynch_execute_gpe_method); status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); if (ACPI_FAILURE(status)) { @@ -598,7 +598,7 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number) { acpi_status status; - ACPI_FUNCTION_TRACE("ev_gpe_dispatch"); + ACPI_FUNCTION_TRACE(ev_gpe_dispatch); /* * If edge-triggered, clear the GPE status bit now. Note that @@ -721,7 +721,7 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number) * * DESCRIPTION: Determine if a a GPE is "wake-only". * - * Called from Notify() code in interpreter when a "device_wake" + * Called from Notify() code in interpreter when a "DeviceWake" * Notify comes in. * ******************************************************************************/ @@ -731,7 +731,7 @@ acpi_ev_check_for_wake_only_gpe(struct acpi_gpe_event_info *gpe_event_info) { acpi_status status; - ACPI_FUNCTION_TRACE("ev_check_for_wake_only_gpe"); + ACPI_FUNCTION_TRACE(ev_check_for_wake_only_gpe); if ((gpe_event_info) && /* Only >0 for _Lxx/_Exx */ ((gpe_event_info->flags & ACPI_GPE_SYSTEM_MASK) == ACPI_GPE_SYSTEM_RUNNING)) { /* System state at GPE time */ diff --git a/drivers/acpi/events/evgpeblk.c b/drivers/acpi/events/evgpeblk.c index 4e90c1f837c..95ddeb48bc0 100644 --- a/drivers/acpi/events/evgpeblk.c +++ b/drivers/acpi/events/evgpeblk.c @@ -138,7 +138,7 @@ acpi_status acpi_ev_walk_gpe_list(acpi_gpe_callback gpe_walk_callback) acpi_status status = AE_OK; acpi_cpu_flags flags; - ACPI_FUNCTION_TRACE("ev_walk_gpe_list"); + ACPI_FUNCTION_TRACE(ev_walk_gpe_list); flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); @@ -192,7 +192,7 @@ acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info, acpi_native_uint i; acpi_native_uint j; - ACPI_FUNCTION_TRACE("ev_delete_gpe_handlers"); + ACPI_FUNCTION_TRACE(ev_delete_gpe_handlers); /* Examine each GPE Register within the block */ @@ -251,7 +251,7 @@ acpi_ev_save_method_info(acpi_handle obj_handle, u8 type; acpi_status status; - ACPI_FUNCTION_TRACE("ev_save_method_info"); + ACPI_FUNCTION_TRACE(ev_save_method_info); /* * _Lxx and _Exx GPE method support @@ -282,9 +282,9 @@ acpi_ev_save_method_info(acpi_handle obj_handle, default: /* Unknown method type, just ignore it! */ - ACPI_ERROR((AE_INFO, - "Unknown GPE method type: %s (name not of form _Lxx or _Exx)", - name)); + ACPI_DEBUG_PRINT((ACPI_DB_LOAD, + "Ignoring unknown GPE method type: %s (name not of form _Lxx or _Exx)", + name)); return_ACPI_STATUS(AE_OK); } @@ -295,9 +295,9 @@ acpi_ev_save_method_info(acpi_handle obj_handle, /* Conversion failed; invalid method, just ignore it */ - ACPI_ERROR((AE_INFO, - "Could not extract GPE number from name: %s (name is not of form _Lxx or _Exx)", - name)); + ACPI_DEBUG_PRINT((ACPI_DB_LOAD, + "Could not extract GPE number from name: %s (name is not of form _Lxx or _Exx)", + name)); return_ACPI_STATUS(AE_OK); } @@ -368,7 +368,7 @@ acpi_ev_match_prw_and_gpe(acpi_handle obj_handle, u32 gpe_number; acpi_status status; - ACPI_FUNCTION_TRACE("ev_match_prw_and_gpe"); + ACPI_FUNCTION_TRACE(ev_match_prw_and_gpe); /* Check for a _PRW method under this device */ @@ -489,7 +489,7 @@ static struct acpi_gpe_xrupt_info *acpi_ev_get_gpe_xrupt_block(u32 acpi_status status; acpi_cpu_flags flags; - ACPI_FUNCTION_TRACE("ev_get_gpe_xrupt_block"); + ACPI_FUNCTION_TRACE(ev_get_gpe_xrupt_block); /* No need for lock since we are not changing any list elements here */ @@ -563,7 +563,7 @@ acpi_ev_delete_gpe_xrupt(struct acpi_gpe_xrupt_info *gpe_xrupt) acpi_status status; acpi_cpu_flags flags; - ACPI_FUNCTION_TRACE("ev_delete_gpe_xrupt"); + ACPI_FUNCTION_TRACE(ev_delete_gpe_xrupt); /* We never want to remove the SCI interrupt handler */ @@ -621,7 +621,7 @@ acpi_ev_install_gpe_block(struct acpi_gpe_block_info *gpe_block, acpi_status status; acpi_cpu_flags flags; - ACPI_FUNCTION_TRACE("ev_install_gpe_block"); + ACPI_FUNCTION_TRACE(ev_install_gpe_block); status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); if (ACPI_FAILURE(status)) { @@ -674,7 +674,7 @@ acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block) acpi_status status; acpi_cpu_flags flags; - ACPI_FUNCTION_TRACE("ev_install_gpe_block"); + ACPI_FUNCTION_TRACE(ev_install_gpe_block); status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); if (ACPI_FAILURE(status)) { @@ -744,7 +744,7 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block) acpi_native_uint j; acpi_status status; - ACPI_FUNCTION_TRACE("ev_create_gpe_info_blocks"); + ACPI_FUNCTION_TRACE(ev_create_gpe_info_blocks); /* Allocate the GPE register information block */ @@ -754,7 +754,7 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block) acpi_gpe_register_info)); if (!gpe_register_info) { ACPI_ERROR((AE_INFO, - "Could not allocate the gpe_register_info table")); + "Could not allocate the GpeRegisterInfo table")); return_ACPI_STATUS(AE_NO_MEMORY); } @@ -769,7 +769,7 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block) acpi_gpe_event_info)); if (!gpe_event_info) { ACPI_ERROR((AE_INFO, - "Could not allocate the gpe_event_info table")); + "Could not allocate the GpeEventInfo table")); status = AE_NO_MEMORY; goto error_exit; } @@ -888,7 +888,7 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, acpi_status status; struct acpi_gpe_block_info *gpe_block; - ACPI_FUNCTION_TRACE("ev_create_gpe_block"); + ACPI_FUNCTION_TRACE(ev_create_gpe_block); if (!register_count) { return_ACPI_STATUS(AE_OK); @@ -981,7 +981,7 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device, acpi_native_uint i; acpi_native_uint j; - ACPI_FUNCTION_TRACE("ev_initialize_gpe_block"); + ACPI_FUNCTION_TRACE(ev_initialize_gpe_block); /* Ignore a null GPE block (e.g., if no GPE block 1 exists) */ @@ -1051,7 +1051,7 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device, status = acpi_hw_enable_runtime_gpe_block(NULL, gpe_block); if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, "Could not enable GPEs in gpe_block %p", + ACPI_ERROR((AE_INFO, "Could not enable GPEs in GpeBlock %p", gpe_block)); } @@ -1077,7 +1077,7 @@ acpi_status acpi_ev_gpe_initialize(void) u32 gpe_number_max = 0; acpi_status status; - ACPI_FUNCTION_TRACE("ev_gpe_initialize"); + ACPI_FUNCTION_TRACE(ev_gpe_initialize); status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c index b216b3229e2..97e05481aa7 100644 --- a/drivers/acpi/events/evmisc.c +++ b/drivers/acpi/events/evmisc.c @@ -124,7 +124,7 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node, union acpi_generic_state *notify_info; acpi_status status = AE_OK; - ACPI_FUNCTION_NAME("ev_queue_notify_request"); + ACPI_FUNCTION_NAME(ev_queue_notify_request); /* * For value 3 (Ejection Request), some device method may need to be run. @@ -376,7 +376,7 @@ acpi_status acpi_ev_init_global_lock_handler(void) { acpi_status status; - ACPI_FUNCTION_TRACE("ev_init_global_lock_handler"); + ACPI_FUNCTION_TRACE(ev_init_global_lock_handler); acpi_gbl_global_lock_present = TRUE; status = acpi_install_fixed_event_handler(ACPI_EVENT_GLOBAL, @@ -418,7 +418,7 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout) acpi_status status = AE_OK; u8 acquired = FALSE; - ACPI_FUNCTION_TRACE("ev_acquire_global_lock"); + ACPI_FUNCTION_TRACE(ev_acquire_global_lock); #ifndef ACPI_APPLICATION /* Make sure that we actually have a global lock */ @@ -486,7 +486,7 @@ acpi_status acpi_ev_release_global_lock(void) u8 pending = FALSE; acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("ev_release_global_lock"); + ACPI_FUNCTION_TRACE(ev_release_global_lock); if (!acpi_gbl_global_lock_thread_count) { ACPI_WARNING((AE_INFO, @@ -540,7 +540,7 @@ void acpi_ev_terminate(void) acpi_native_uint i; acpi_status status; - ACPI_FUNCTION_TRACE("ev_terminate"); + ACPI_FUNCTION_TRACE(ev_terminate); if (acpi_gbl_events_initialized) { /* @@ -580,7 +580,7 @@ void acpi_ev_terminate(void) if (acpi_gbl_original_mode == ACPI_SYS_MODE_LEGACY) { status = acpi_disable(); if (ACPI_FAILURE(status)) { - ACPI_WARNING((AE_INFO, "acpi_disable failed")); + ACPI_WARNING((AE_INFO, "AcpiDisable failed")); } } return_VOID; diff --git a/drivers/acpi/events/evregion.c b/drivers/acpi/events/evregion.c index 0337ad222b2..eb29e96f053 100644 --- a/drivers/acpi/events/evregion.c +++ b/drivers/acpi/events/evregion.c @@ -83,7 +83,7 @@ acpi_status acpi_ev_install_region_handlers(void) acpi_status status; acpi_native_uint i; - ACPI_FUNCTION_TRACE("ev_install_region_handlers"); + ACPI_FUNCTION_TRACE(ev_install_region_handlers); status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { @@ -153,7 +153,7 @@ acpi_status acpi_ev_initialize_op_regions(void) acpi_status status; acpi_native_uint i; - ACPI_FUNCTION_TRACE("ev_initialize_op_regions"); + ACPI_FUNCTION_TRACE(ev_initialize_op_regions); status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { @@ -198,7 +198,7 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function) union acpi_operand_object *region_obj2; acpi_status status; - ACPI_FUNCTION_TRACE("ev_execute_reg_method"); + ACPI_FUNCTION_TRACE(ev_execute_reg_method); region_obj2 = acpi_ns_get_secondary_object(region_obj); if (!region_obj2) { @@ -284,7 +284,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, union acpi_operand_object *region_obj2; void *region_context = NULL; - ACPI_FUNCTION_TRACE("ev_address_space_dispatch"); + ACPI_FUNCTION_TRACE(ev_address_space_dispatch); region_obj2 = acpi_ns_get_secondary_object(region_obj); if (!region_obj2) { @@ -451,7 +451,7 @@ acpi_ev_detach_region(union acpi_operand_object *region_obj, union acpi_operand_object *region_obj2; acpi_status status; - ACPI_FUNCTION_TRACE("ev_detach_region"); + ACPI_FUNCTION_TRACE(ev_detach_region); region_obj2 = acpi_ns_get_secondary_object(region_obj); if (!region_obj2) { @@ -585,7 +585,7 @@ acpi_ev_attach_region(union acpi_operand_object *handler_obj, u8 acpi_ns_is_locked) { - ACPI_FUNCTION_TRACE("ev_attach_region"); + ACPI_FUNCTION_TRACE(ev_attach_region); ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, "Adding Region [%4.4s] %p to address handler %p [%s]\n", @@ -638,7 +638,7 @@ acpi_ev_install_handler(acpi_handle obj_handle, struct acpi_namespace_node *node; acpi_status status; - ACPI_FUNCTION_NAME("ev_install_handler"); + ACPI_FUNCTION_NAME(ev_install_handler); handler_obj = (union acpi_operand_object *)context; @@ -771,7 +771,7 @@ acpi_ev_install_space_handler(struct acpi_namespace_node * node, acpi_object_type type; u8 flags = 0; - ACPI_FUNCTION_TRACE("ev_install_space_handler"); + ACPI_FUNCTION_TRACE(ev_install_space_handler); /* * This registration is valid for only the types below @@ -985,7 +985,7 @@ acpi_ev_execute_reg_methods(struct acpi_namespace_node *node, { acpi_status status; - ACPI_FUNCTION_TRACE("ev_execute_reg_methods"); + ACPI_FUNCTION_TRACE(ev_execute_reg_methods); /* * Run all _REG methods for all Operation Regions for this diff --git a/drivers/acpi/events/evrgnini.c b/drivers/acpi/events/evrgnini.c index d1809f4240a..1cecd577b89 100644 --- a/drivers/acpi/events/evrgnini.c +++ b/drivers/acpi/events/evrgnini.c @@ -71,7 +71,7 @@ acpi_ev_system_memory_region_setup(acpi_handle handle, (union acpi_operand_object *)handle; struct acpi_mem_space_context *local_region_context; - ACPI_FUNCTION_TRACE("ev_system_memory_region_setup"); + ACPI_FUNCTION_TRACE(ev_system_memory_region_setup); if (function == ACPI_REGION_DEACTIVATE) { if (*region_context) { @@ -129,7 +129,7 @@ acpi_ev_io_space_region_setup(acpi_handle handle, u32 function, void *handler_context, void **region_context) { - ACPI_FUNCTION_TRACE("ev_io_space_region_setup"); + ACPI_FUNCTION_TRACE(ev_io_space_region_setup); if (function == ACPI_REGION_DEACTIVATE) { *region_context = NULL; @@ -172,7 +172,7 @@ acpi_ev_pci_config_region_setup(acpi_handle handle, (union acpi_operand_object *)handle; struct acpi_device_id object_hID; - ACPI_FUNCTION_TRACE("ev_pci_config_region_setup"); + ACPI_FUNCTION_TRACE(ev_pci_config_region_setup); handler_obj = region_obj->region.handler; if (!handler_obj) { @@ -248,7 +248,7 @@ acpi_ev_pci_config_region_setup(acpi_handle handle, } else { ACPI_EXCEPTION((AE_INFO, status, - "Could not install pci_config handler for Root Bridge %4.4s", + "Could not install PciConfig handler for Root Bridge %4.4s", acpi_ut_get_node_name (pci_root_node))); } @@ -350,7 +350,7 @@ acpi_ev_pci_bar_region_setup(acpi_handle handle, u32 function, void *handler_context, void **region_context) { - ACPI_FUNCTION_TRACE("ev_pci_bar_region_setup"); + ACPI_FUNCTION_TRACE(ev_pci_bar_region_setup); return_ACPI_STATUS(AE_OK); } @@ -377,7 +377,7 @@ acpi_ev_cmos_region_setup(acpi_handle handle, u32 function, void *handler_context, void **region_context) { - ACPI_FUNCTION_TRACE("ev_cmos_region_setup"); + ACPI_FUNCTION_TRACE(ev_cmos_region_setup); return_ACPI_STATUS(AE_OK); } @@ -402,7 +402,7 @@ acpi_ev_default_region_setup(acpi_handle handle, u32 function, void *handler_context, void **region_context) { - ACPI_FUNCTION_TRACE("ev_default_region_setup"); + ACPI_FUNCTION_TRACE(ev_default_region_setup); if (function == ACPI_REGION_DEACTIVATE) { *region_context = NULL; @@ -448,7 +448,7 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj, acpi_name *reg_name_ptr = (acpi_name *) METHOD_NAME__REG; union acpi_operand_object *region_obj2; - ACPI_FUNCTION_TRACE_U32("ev_initialize_region", acpi_ns_locked); + ACPI_FUNCTION_TRACE_U32(ev_initialize_region, acpi_ns_locked); if (!region_obj) { return_ACPI_STATUS(AE_BAD_PARAMETER); @@ -588,7 +588,7 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj, /* If we get here, there is no handler for this region */ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, - "No handler for region_type %s(%X) (region_obj %p)\n", + "No handler for RegionType %s(%X) (RegionObj %p)\n", acpi_ut_get_region_name(space_id), space_id, region_obj)); diff --git a/drivers/acpi/events/evsci.c b/drivers/acpi/events/evsci.c index 9a622169008..8106215ad55 100644 --- a/drivers/acpi/events/evsci.c +++ b/drivers/acpi/events/evsci.c @@ -69,7 +69,7 @@ static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context) struct acpi_gpe_xrupt_info *gpe_xrupt_list = context; u32 interrupt_handled = ACPI_INTERRUPT_NOT_HANDLED; - ACPI_FUNCTION_TRACE("ev_sci_xrupt_handler"); + ACPI_FUNCTION_TRACE(ev_sci_xrupt_handler); /* * We are guaranteed by the ACPI CA initialization/shutdown code that @@ -108,7 +108,7 @@ u32 ACPI_SYSTEM_XFACE acpi_ev_gpe_xrupt_handler(void *context) struct acpi_gpe_xrupt_info *gpe_xrupt_list = context; u32 interrupt_handled = ACPI_INTERRUPT_NOT_HANDLED; - ACPI_FUNCTION_TRACE("ev_gpe_xrupt_handler"); + ACPI_FUNCTION_TRACE(ev_gpe_xrupt_handler); /* * We are guaranteed by the ACPI CA initialization/shutdown code that @@ -140,7 +140,7 @@ u32 acpi_ev_install_sci_handler(void) { u32 status = AE_OK; - ACPI_FUNCTION_TRACE("ev_install_sci_handler"); + ACPI_FUNCTION_TRACE(ev_install_sci_handler); status = acpi_os_install_interrupt_handler((u32) acpi_gbl_FADT->sci_int, acpi_ev_sci_xrupt_handler, @@ -171,7 +171,7 @@ acpi_status acpi_ev_remove_sci_handler(void) { acpi_status status; - ACPI_FUNCTION_TRACE("ev_remove_sci_handler"); + ACPI_FUNCTION_TRACE(ev_remove_sci_handler); /* Just let the OS remove the handler and disable the level */ diff --git a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c index 7d1cebc871f..76c34a66e0e 100644 --- a/drivers/acpi/events/evxface.c +++ b/drivers/acpi/events/evxface.c @@ -66,7 +66,7 @@ acpi_status acpi_install_exception_handler(acpi_exception_handler handler) { acpi_status status; - ACPI_FUNCTION_TRACE("acpi_install_exception_handler"); + ACPI_FUNCTION_TRACE(acpi_install_exception_handler); status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); if (ACPI_FAILURE(status)) { @@ -113,7 +113,7 @@ acpi_install_fixed_event_handler(u32 event, { acpi_status status; - ACPI_FUNCTION_TRACE("acpi_install_fixed_event_handler"); + ACPI_FUNCTION_TRACE(acpi_install_fixed_event_handler); /* Parameter validation */ @@ -179,7 +179,7 @@ acpi_remove_fixed_event_handler(u32 event, acpi_event_handler handler) { acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("acpi_remove_fixed_event_handler"); + ACPI_FUNCTION_TRACE(acpi_remove_fixed_event_handler); /* Parameter validation */ @@ -243,7 +243,7 @@ acpi_install_notify_handler(acpi_handle device, struct acpi_namespace_node *node; acpi_status status; - ACPI_FUNCTION_TRACE("acpi_install_notify_handler"); + ACPI_FUNCTION_TRACE(acpi_install_notify_handler); /* Parameter validation */ @@ -408,7 +408,7 @@ acpi_remove_notify_handler(acpi_handle device, struct acpi_namespace_node *node; acpi_status status; - ACPI_FUNCTION_TRACE("acpi_remove_notify_handler"); + ACPI_FUNCTION_TRACE(acpi_remove_notify_handler); /* Parameter validation */ @@ -563,7 +563,7 @@ acpi_install_gpe_handler(acpi_handle gpe_device, acpi_status status; acpi_cpu_flags flags; - ACPI_FUNCTION_TRACE("acpi_install_gpe_handler"); + ACPI_FUNCTION_TRACE(acpi_install_gpe_handler); /* Parameter validation */ @@ -653,7 +653,7 @@ acpi_remove_gpe_handler(acpi_handle gpe_device, acpi_status status; acpi_cpu_flags flags; - ACPI_FUNCTION_TRACE("acpi_remove_gpe_handler"); + ACPI_FUNCTION_TRACE(acpi_remove_gpe_handler); /* Parameter validation */ diff --git a/drivers/acpi/events/evxfevnt.c b/drivers/acpi/events/evxfevnt.c index 4a36559fa81..7ebc2efac93 100644 --- a/drivers/acpi/events/evxfevnt.c +++ b/drivers/acpi/events/evxfevnt.c @@ -63,7 +63,7 @@ acpi_status acpi_enable(void) { acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("acpi_enable"); + ACPI_FUNCTION_TRACE(acpi_enable); /* Make sure we have the FADT */ @@ -109,7 +109,7 @@ acpi_status acpi_disable(void) { acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("acpi_disable"); + ACPI_FUNCTION_TRACE(acpi_disable); if (!acpi_gbl_FADT) { ACPI_WARNING((AE_INFO, "No FADT information present!")); @@ -155,7 +155,7 @@ acpi_status acpi_enable_event(u32 event, u32 flags) acpi_status status = AE_OK; u32 value; - ACPI_FUNCTION_TRACE("acpi_enable_event"); + ACPI_FUNCTION_TRACE(acpi_enable_event); /* Decode the Fixed Event */ @@ -213,7 +213,7 @@ acpi_status acpi_set_gpe_type(acpi_handle gpe_device, u32 gpe_number, u8 type) acpi_status status = AE_OK; struct acpi_gpe_event_info *gpe_event_info; - ACPI_FUNCTION_TRACE("acpi_set_gpe_type"); + ACPI_FUNCTION_TRACE(acpi_set_gpe_type); /* Ensure that we have a valid GPE number */ @@ -256,7 +256,7 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) acpi_status status = AE_OK; struct acpi_gpe_event_info *gpe_event_info; - ACPI_FUNCTION_TRACE("acpi_enable_gpe"); + ACPI_FUNCTION_TRACE(acpi_enable_gpe); /* Use semaphore lock if not executing at interrupt level */ @@ -307,7 +307,7 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) acpi_status status = AE_OK; struct acpi_gpe_event_info *gpe_event_info; - ACPI_FUNCTION_TRACE("acpi_disable_gpe"); + ACPI_FUNCTION_TRACE(acpi_disable_gpe); /* Use semaphore lock if not executing at interrupt level */ @@ -354,7 +354,7 @@ acpi_status acpi_disable_event(u32 event, u32 flags) acpi_status status = AE_OK; u32 value; - ACPI_FUNCTION_TRACE("acpi_disable_event"); + ACPI_FUNCTION_TRACE(acpi_disable_event); /* Decode the Fixed Event */ @@ -407,7 +407,7 @@ acpi_status acpi_clear_event(u32 event) { acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("acpi_clear_event"); + ACPI_FUNCTION_TRACE(acpi_clear_event); /* Decode the Fixed Event */ @@ -446,7 +446,7 @@ acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) acpi_status status = AE_OK; struct acpi_gpe_event_info *gpe_event_info; - ACPI_FUNCTION_TRACE("acpi_clear_gpe"); + ACPI_FUNCTION_TRACE(acpi_clear_gpe); /* Use semaphore lock if not executing at interrupt level */ @@ -494,7 +494,7 @@ acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status) { acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("acpi_get_event_status"); + ACPI_FUNCTION_TRACE(acpi_get_event_status); if (!event_status) { return_ACPI_STATUS(AE_BAD_PARAMETER); @@ -539,7 +539,7 @@ acpi_get_gpe_status(acpi_handle gpe_device, acpi_status status = AE_OK; struct acpi_gpe_event_info *gpe_event_info; - ACPI_FUNCTION_TRACE("acpi_get_gpe_status"); + ACPI_FUNCTION_TRACE(acpi_get_gpe_status); /* Use semaphore lock if not executing at interrupt level */ @@ -596,7 +596,7 @@ acpi_install_gpe_block(acpi_handle gpe_device, struct acpi_namespace_node *node; struct acpi_gpe_block_info *gpe_block; - ACPI_FUNCTION_TRACE("acpi_install_gpe_block"); + ACPI_FUNCTION_TRACE(acpi_install_gpe_block); if ((!gpe_device) || (!gpe_block_address) || (!register_count)) { return_ACPI_STATUS(AE_BAD_PARAMETER); @@ -684,7 +684,7 @@ acpi_status acpi_remove_gpe_block(acpi_handle gpe_device) acpi_status status; struct acpi_namespace_node *node; - ACPI_FUNCTION_TRACE("acpi_remove_gpe_block"); + ACPI_FUNCTION_TRACE(acpi_remove_gpe_block); if (!gpe_device) { return_ACPI_STATUS(AE_BAD_PARAMETER); diff --git a/drivers/acpi/events/evxfregn.c b/drivers/acpi/events/evxfregn.c index 63a070bb9d1..e8b86a0baad 100644 --- a/drivers/acpi/events/evxfregn.c +++ b/drivers/acpi/events/evxfregn.c @@ -73,7 +73,7 @@ acpi_install_address_space_handler(acpi_handle device, struct acpi_namespace_node *node; acpi_status status; - ACPI_FUNCTION_TRACE("acpi_install_address_space_handler"); + ACPI_FUNCTION_TRACE(acpi_install_address_space_handler); /* Parameter validation */ @@ -139,7 +139,7 @@ acpi_remove_address_space_handler(acpi_handle device, struct acpi_namespace_node *node; acpi_status status; - ACPI_FUNCTION_TRACE("acpi_remove_address_space_handler"); + ACPI_FUNCTION_TRACE(acpi_remove_address_space_handler); /* Parameter validation */ @@ -228,7 +228,7 @@ acpi_remove_address_space_handler(acpi_handle device, /* The handler does not exist */ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, - "Unable to remove address handler %p for %s(%X), dev_node %p, obj %p\n", + "Unable to remove address handler %p for %s(%X), DevNode %p, obj %p\n", handler, acpi_ut_get_region_name(space_id), space_id, node, obj_desc)); diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c index e0deffb5679..9c46f333864 100644 --- a/drivers/acpi/executer/exconfig.c +++ b/drivers/acpi/executer/exconfig.c @@ -82,7 +82,7 @@ acpi_ex_add_table(struct acpi_table_header *table, struct acpi_table_desc table_info; union acpi_operand_object *obj_desc; - ACPI_FUNCTION_TRACE("ex_add_table"); + ACPI_FUNCTION_TRACE(ex_add_table); /* Create an object to be the table handle */ @@ -100,7 +100,7 @@ acpi_ex_add_table(struct acpi_table_header *table, ACPI_MEMSET(&table_info, 0, sizeof(struct acpi_table_desc)); - table_info.type = ACPI_TABLE_SSDT; + table_info.type = ACPI_TABLE_ID_SSDT; table_info.pointer = table; table_info.length = (acpi_size) table->length; table_info.allocation = ACPI_MEM_ALLOCATED; @@ -162,7 +162,7 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, struct acpi_namespace_node *parameter_node = NULL; union acpi_operand_object *ddb_handle; - ACPI_FUNCTION_TRACE("ex_load_table_op"); + ACPI_FUNCTION_TRACE(ex_load_table_op); #if 0 /* @@ -300,7 +300,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, struct acpi_table_header table_header; u32 i; - ACPI_FUNCTION_TRACE("ex_load_op"); + ACPI_FUNCTION_TRACE(ex_load_op); /* Object can be either an op_region or a Field */ @@ -411,12 +411,8 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, /* The table must be either an SSDT or a PSDT */ - if ((!ACPI_STRNCMP(table_ptr->signature, - acpi_gbl_table_data[ACPI_TABLE_PSDT].signature, - acpi_gbl_table_data[ACPI_TABLE_PSDT].sig_length)) && - (!ACPI_STRNCMP(table_ptr->signature, - acpi_gbl_table_data[ACPI_TABLE_SSDT].signature, - acpi_gbl_table_data[ACPI_TABLE_SSDT].sig_length))) { + if ((!ACPI_COMPARE_NAME(table_ptr->signature, PSDT_SIG)) && + (!ACPI_COMPARE_NAME(table_ptr->signature, SSDT_SIG))) { ACPI_ERROR((AE_INFO, "Table has invalid signature [%4.4s], must be SSDT or PSDT", table_ptr->signature)); @@ -470,7 +466,7 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle) union acpi_operand_object *table_desc = ddb_handle; struct acpi_table_desc *table_info; - ACPI_FUNCTION_TRACE("ex_unload_table"); + ACPI_FUNCTION_TRACE(ex_unload_table); /* * Validate the handle diff --git a/drivers/acpi/executer/exconvrt.c b/drivers/acpi/executer/exconvrt.c index a2c93c9ba07..b732e399b1e 100644 --- a/drivers/acpi/executer/exconvrt.c +++ b/drivers/acpi/executer/exconvrt.c @@ -79,7 +79,7 @@ acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc, u32 count; acpi_status status; - ACPI_FUNCTION_TRACE_PTR("ex_convert_to_integer", obj_desc); + ACPI_FUNCTION_TRACE_PTR(ex_convert_to_integer, obj_desc); switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { case ACPI_TYPE_INTEGER: @@ -199,7 +199,7 @@ acpi_ex_convert_to_buffer(union acpi_operand_object *obj_desc, union acpi_operand_object *return_desc; u8 *new_buf; - ACPI_FUNCTION_TRACE_PTR("ex_convert_to_buffer", obj_desc); + ACPI_FUNCTION_TRACE_PTR(ex_convert_to_buffer, obj_desc); switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { case ACPI_TYPE_BUFFER: @@ -402,7 +402,7 @@ acpi_ex_convert_to_string(union acpi_operand_object * obj_desc, u16 base = 16; u8 separator = ','; - ACPI_FUNCTION_TRACE_PTR("ex_convert_to_string", obj_desc); + ACPI_FUNCTION_TRACE_PTR(ex_convert_to_string, obj_desc); switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { case ACPI_TYPE_STRING: @@ -569,7 +569,7 @@ acpi_ex_convert_to_target_type(acpi_object_type destination_type, { acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("ex_convert_to_target_type"); + ACPI_FUNCTION_TRACE(ex_convert_to_target_type); /* Default behavior */ @@ -659,7 +659,7 @@ acpi_ex_convert_to_target_type(acpi_object_type destination_type, default: ACPI_ERROR((AE_INFO, - "Unknown Target type ID 0x%X aml_opcode %X dest_type %s", + "Unknown Target type ID 0x%X AmlOpcode %X DestType %s", GET_CURRENT_ARG_TYPE(walk_state->op_info-> runtime_args), walk_state->opcode, diff --git a/drivers/acpi/executer/excreate.c b/drivers/acpi/executer/excreate.c index 763e132da4c..106dc7219df 100644 --- a/drivers/acpi/executer/excreate.c +++ b/drivers/acpi/executer/excreate.c @@ -69,7 +69,7 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state) struct acpi_namespace_node *alias_node; acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("ex_create_alias"); + ACPI_FUNCTION_TRACE(ex_create_alias); /* Get the source/alias operands (both namespace nodes) */ @@ -164,7 +164,7 @@ acpi_status acpi_ex_create_event(struct acpi_walk_state *walk_state) acpi_status status; union acpi_operand_object *obj_desc; - ACPI_FUNCTION_TRACE("ex_create_event"); + ACPI_FUNCTION_TRACE(ex_create_event); obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_EVENT); if (!obj_desc) { @@ -216,7 +216,7 @@ acpi_status acpi_ex_create_mutex(struct acpi_walk_state *walk_state) acpi_status status = AE_OK; union acpi_operand_object *obj_desc; - ACPI_FUNCTION_TRACE_PTR("ex_create_mutex", ACPI_WALK_OPERANDS); + ACPI_FUNCTION_TRACE_PTR(ex_create_mutex, ACPI_WALK_OPERANDS); /* Create the new mutex object */ @@ -281,7 +281,7 @@ acpi_ex_create_region(u8 * aml_start, struct acpi_namespace_node *node; union acpi_operand_object *region_obj2; - ACPI_FUNCTION_TRACE("ex_create_region"); + ACPI_FUNCTION_TRACE(ex_create_region); /* Get the Namespace Node */ @@ -301,7 +301,7 @@ acpi_ex_create_region(u8 * aml_start, */ if ((region_space >= ACPI_NUM_PREDEFINED_REGIONS) && (region_space < ACPI_USER_REGION_BEGIN)) { - ACPI_ERROR((AE_INFO, "Invalid address_space type %X", + ACPI_ERROR((AE_INFO, "Invalid AddressSpace type %X", region_space)); return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID); } @@ -365,7 +365,7 @@ acpi_status acpi_ex_create_table_region(struct acpi_walk_state *walk_state) struct acpi_table_header *table; union acpi_operand_object *region_obj2; - ACPI_FUNCTION_TRACE("ex_create_table_region"); + ACPI_FUNCTION_TRACE(ex_create_table_region); /* Get the Node from the object stack */ @@ -453,7 +453,7 @@ acpi_status acpi_ex_create_processor(struct acpi_walk_state *walk_state) union acpi_operand_object *obj_desc; acpi_status status; - ACPI_FUNCTION_TRACE_PTR("ex_create_processor", walk_state); + ACPI_FUNCTION_TRACE_PTR(ex_create_processor, walk_state); /* Create the processor object */ @@ -500,7 +500,7 @@ acpi_status acpi_ex_create_power_resource(struct acpi_walk_state *walk_state) acpi_status status; union acpi_operand_object *obj_desc; - ACPI_FUNCTION_TRACE_PTR("ex_create_power_resource", walk_state); + ACPI_FUNCTION_TRACE_PTR(ex_create_power_resource, walk_state); /* Create the power resource object */ @@ -550,7 +550,7 @@ acpi_ex_create_method(u8 * aml_start, acpi_status status; u8 method_flags; - ACPI_FUNCTION_TRACE_PTR("ex_create_method", walk_state); + ACPI_FUNCTION_TRACE_PTR(ex_create_method, walk_state); /* Create a new method object */ diff --git a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c index 1dfebf9e707..7b9718e976b 100644 --- a/drivers/acpi/executer/exdump.c +++ b/drivers/acpi/executer/exdump.c @@ -123,7 +123,7 @@ static struct acpi_exdump_info acpi_ex_dump_event[2] = { static struct acpi_exdump_info acpi_ex_dump_method[8] = { {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_method), NULL}, - {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.param_count), "param_count"}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.param_count), "ParamCount"}, {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.concurrency), "Concurrency"}, {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(method.semaphore), "Semaphore"}, {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.owner_id), "Owner Id"}, @@ -332,7 +332,7 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc, if (!info) { acpi_os_printf - ("ex_dump_object: Display not implemented for object type %s\n", + ("ExDumpObject: Display not implemented for object type %s\n", acpi_ut_get_object_type_name(obj_desc)); return; } @@ -456,7 +456,7 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) u32 length; u32 index; - ACPI_FUNCTION_NAME("ex_dump_operand") + ACPI_FUNCTION_NAME(ex_dump_operand) if (! ((ACPI_LV_EXEC & acpi_dbg_level) @@ -525,7 +525,7 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) case AML_REF_OF_OP: - acpi_os_printf("Reference: (ref_of) %p\n", + acpi_os_printf("Reference: (RefOf) %p\n", obj_desc->reference.object); break; @@ -614,7 +614,7 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) case ACPI_TYPE_PACKAGE: - acpi_os_printf("Package [Len %X] element_array %p\n", + acpi_os_printf("Package [Len %X] ElementArray %p\n", obj_desc->package.count, obj_desc->package.elements); @@ -666,13 +666,13 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) case ACPI_TYPE_LOCAL_BANK_FIELD: - acpi_os_printf("bank_field\n"); + acpi_os_printf("BankField\n"); break; case ACPI_TYPE_LOCAL_REGION_FIELD: acpi_os_printf - ("region_field: Bits=%X acc_width=%X Lock=%X Update=%X at byte=%X bit=%X of below:\n", + ("RegionField: Bits=%X AccWidth=%X Lock=%X Update=%X at byte=%X bit=%X of below:\n", obj_desc->field.bit_length, obj_desc->field.access_byte_width, obj_desc->field.field_flags & AML_FIELD_LOCK_RULE_MASK, @@ -685,12 +685,12 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) case ACPI_TYPE_LOCAL_INDEX_FIELD: - acpi_os_printf("index_field\n"); + acpi_os_printf("IndexField\n"); break; case ACPI_TYPE_BUFFER_FIELD: - acpi_os_printf("buffer_field: %X bits at byte %X bit %X of\n", + acpi_os_printf("BufferField: %X bits at byte %X bit %X of\n", obj_desc->buffer_field.bit_length, obj_desc->buffer_field.base_byte_offset, obj_desc->buffer_field.start_field_bit_offset); @@ -781,7 +781,7 @@ acpi_ex_dump_operands(union acpi_operand_object **operands, { acpi_native_uint i; - ACPI_FUNCTION_NAME("ex_dump_operands"); + ACPI_FUNCTION_NAME(ex_dump_operands); if (!ident) { ident = "?"; @@ -1021,7 +1021,7 @@ acpi_ex_dump_package_obj(union acpi_operand_object *obj_desc, void acpi_ex_dump_object_descriptor(union acpi_operand_object *obj_desc, u32 flags) { - ACPI_FUNCTION_TRACE("ex_dump_object_descriptor"); + ACPI_FUNCTION_TRACE(ex_dump_object_descriptor); if (!obj_desc) { return_VOID; @@ -1050,7 +1050,7 @@ acpi_ex_dump_object_descriptor(union acpi_operand_object *obj_desc, u32 flags) if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != ACPI_DESC_TYPE_OPERAND) { acpi_os_printf - ("ex_dump_object_descriptor: %p is not an ACPI operand object: [%s]\n", + ("ExDumpObjectDescriptor: %p is not an ACPI operand object: [%s]\n", obj_desc, acpi_ut_get_descriptor_name(obj_desc)); return_VOID; } diff --git a/drivers/acpi/executer/exfield.c b/drivers/acpi/executer/exfield.c index 36c265a00c2..9ea9c3a67ca 100644 --- a/drivers/acpi/executer/exfield.c +++ b/drivers/acpi/executer/exfield.c @@ -73,7 +73,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, void *buffer; u8 locked; - ACPI_FUNCTION_TRACE_PTR("ex_read_data_from_field", obj_desc); + ACPI_FUNCTION_TRACE_PTR(ex_read_data_from_field, obj_desc); /* Parameter validation */ @@ -164,11 +164,11 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, } ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "field_read [TO]: Obj %p, Type %X, Buf %p, byte_len %X\n", + "FieldRead [TO]: Obj %p, Type %X, Buf %p, ByteLen %X\n", obj_desc, ACPI_GET_OBJECT_TYPE(obj_desc), buffer, (u32) length)); ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "field_read [FROM]: bit_len %X, bit_off %X, byte_off %X\n", + "FieldRead [FROM]: BitLen %X, BitOff %X, ByteOff %X\n", obj_desc->common_field.bit_length, obj_desc->common_field.start_field_bit_offset, obj_desc->common_field.base_byte_offset)); @@ -220,7 +220,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, u8 locked; union acpi_operand_object *buffer_desc; - ACPI_FUNCTION_TRACE_PTR("ex_write_data_to_field", obj_desc); + ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc); /* Parameter validation */ @@ -349,14 +349,14 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, } ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "field_write [FROM]: Obj %p (%s:%X), Buf %p, byte_len %X\n", + "FieldWrite [FROM]: Obj %p (%s:%X), Buf %p, ByteLen %X\n", source_desc, acpi_ut_get_type_name(ACPI_GET_OBJECT_TYPE (source_desc)), ACPI_GET_OBJECT_TYPE(source_desc), buffer, length)); ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "field_write [TO]: Obj %p (%s:%X), bit_len %X, bit_off %X, byte_off %X\n", + "FieldWrite [TO]: Obj %p (%s:%X), BitLen %X, BitOff %X, ByteOff %X\n", obj_desc, acpi_ut_get_type_name(ACPI_GET_OBJECT_TYPE(obj_desc)), ACPI_GET_OBJECT_TYPE(obj_desc), diff --git a/drivers/acpi/executer/exfldio.c b/drivers/acpi/executer/exfldio.c index d5a4b2627c1..ca9925c0d01 100644 --- a/drivers/acpi/executer/exfldio.c +++ b/drivers/acpi/executer/exfldio.c @@ -87,7 +87,7 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc, acpi_status status = AE_OK; union acpi_operand_object *rgn_desc; - ACPI_FUNCTION_TRACE_U32("ex_setup_region", field_datum_byte_offset); + ACPI_FUNCTION_TRACE_U32(ex_setup_region, field_datum_byte_offset); rgn_desc = obj_desc->common_field.region_obj; @@ -112,6 +112,16 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc, } } + /* Exit if Address/Length have been disallowed by the host OS */ + + if (rgn_desc->common.flags & AOPOBJ_INVALID) { + return_ACPI_STATUS(AE_AML_ILLEGAL_ADDRESS); + } + + /* + * Exit now for SMBus address space, it has a non-linear address space + * and the request cannot be directly validated + */ if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS) { /* SMBus has a non-linear address space */ @@ -218,7 +228,7 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc, union acpi_operand_object *rgn_desc; acpi_physical_address address; - ACPI_FUNCTION_TRACE("ex_access_region"); + ACPI_FUNCTION_TRACE(ex_access_region); /* * Ensure that the region operands are fully evaluated and verify @@ -247,7 +257,7 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc, } ACPI_DEBUG_PRINT_RAW((ACPI_DB_BFIELD, - " Region [%s:%X], Width %X, byte_base %X, Offset %X at %8.8X%8.8X\n", + " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %8.8X%8.8X\n", acpi_ut_get_region_name(rgn_desc->region. space_id), rgn_desc->region.space_id, @@ -353,7 +363,7 @@ acpi_ex_field_datum_io(union acpi_operand_object *obj_desc, acpi_status status; acpi_integer local_value; - ACPI_FUNCTION_TRACE_U32("ex_field_datum_io", field_datum_byte_offset); + ACPI_FUNCTION_TRACE_U32(ex_field_datum_io, field_datum_byte_offset); if (read_write == ACPI_READ) { if (!value) { @@ -488,7 +498,7 @@ acpi_ex_field_datum_io(union acpi_operand_object *obj_desc, } ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "I/O to Data Register: value_ptr %p\n", + "I/O to Data Register: ValuePtr %p\n", value)); if (read_write == ACPI_READ) { @@ -561,7 +571,7 @@ acpi_ex_write_with_update_rule(union acpi_operand_object *obj_desc, acpi_integer merged_value; acpi_integer current_value; - ACPI_FUNCTION_TRACE_U32("ex_write_with_update_rule", mask); + ACPI_FUNCTION_TRACE_U32(ex_write_with_update_rule, mask); /* Start with the new bits */ @@ -617,7 +627,7 @@ acpi_ex_write_with_update_rule(union acpi_operand_object *obj_desc, default: ACPI_ERROR((AE_INFO, - "Unknown update_rule value: %X", + "Unknown UpdateRule value: %X", (obj_desc->common_field. field_flags & AML_FIELD_UPDATE_RULE_MASK))); @@ -626,7 +636,7 @@ acpi_ex_write_with_update_rule(union acpi_operand_object *obj_desc, } ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "Mask %8.8X%8.8X, datum_offset %X, Width %X, Value %8.8X%8.8X, merged_value %8.8X%8.8X\n", + "Mask %8.8X%8.8X, DatumOffset %X, Width %X, Value %8.8X%8.8X, MergedValue %8.8X%8.8X\n", ACPI_FORMAT_UINT64(mask), field_datum_byte_offset, obj_desc->common_field.access_byte_width, @@ -669,7 +679,7 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc, u32 field_datum_count; u32 i; - ACPI_FUNCTION_TRACE("ex_extract_from_field"); + ACPI_FUNCTION_TRACE(ex_extract_from_field); /* Validate target buffer and clear it */ @@ -784,7 +794,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, u32 field_datum_count; u32 i; - ACPI_FUNCTION_TRACE("ex_insert_into_field"); + ACPI_FUNCTION_TRACE(ex_insert_into_field); /* Validate input buffer */ diff --git a/drivers/acpi/executer/exmisc.c b/drivers/acpi/executer/exmisc.c index 74f2c1a9bda..794d9b8de95 100644 --- a/drivers/acpi/executer/exmisc.c +++ b/drivers/acpi/executer/exmisc.c @@ -72,7 +72,7 @@ acpi_ex_get_object_reference(union acpi_operand_object *obj_desc, union acpi_operand_object *reference_obj; union acpi_operand_object *referenced_obj; - ACPI_FUNCTION_TRACE_PTR("ex_get_object_reference", obj_desc); + ACPI_FUNCTION_TRACE_PTR(ex_get_object_reference, obj_desc); *return_desc = NULL; @@ -168,7 +168,7 @@ acpi_ex_concat_template(union acpi_operand_object *operand0, acpi_size length1; acpi_size new_length; - ACPI_FUNCTION_TRACE("ex_concat_template"); + ACPI_FUNCTION_TRACE(ex_concat_template); /* * Find the end_tag descriptor in each resource template. @@ -250,7 +250,7 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0, char *new_buf; acpi_status status; - ACPI_FUNCTION_TRACE("ex_do_concatenate"); + ACPI_FUNCTION_TRACE(ex_do_concatenate); /* * Convert the second operand if necessary. The first operand @@ -489,7 +489,7 @@ acpi_ex_do_logical_numeric_op(u16 opcode, acpi_status status = AE_OK; u8 local_result = FALSE; - ACPI_FUNCTION_TRACE("ex_do_logical_numeric_op"); + ACPI_FUNCTION_TRACE(ex_do_logical_numeric_op); switch (opcode) { case AML_LAND_OP: /* LAnd (Integer0, Integer1) */ @@ -557,7 +557,7 @@ acpi_ex_do_logical_op(u16 opcode, u8 local_result = FALSE; int compare; - ACPI_FUNCTION_TRACE("ex_do_logical_op"); + ACPI_FUNCTION_TRACE(ex_do_logical_op); /* * Convert the second operand if necessary. The first operand diff --git a/drivers/acpi/executer/exmutex.c b/drivers/acpi/executer/exmutex.c index eaee1de5e90..93098d68cad 100644 --- a/drivers/acpi/executer/exmutex.c +++ b/drivers/acpi/executer/exmutex.c @@ -61,7 +61,7 @@ acpi_ex_link_mutex(union acpi_operand_object *obj_desc, * * RETURN: None * - * DESCRIPTION: Remove a mutex from the "acquired_mutex" list + * DESCRIPTION: Remove a mutex from the "AcquiredMutex" list * ******************************************************************************/ @@ -95,7 +95,7 @@ void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc) * * RETURN: None * - * DESCRIPTION: Add a mutex to the "acquired_mutex" list for this walk + * DESCRIPTION: Add a mutex to the "AcquiredMutex" list for this walk * ******************************************************************************/ @@ -144,7 +144,7 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc, { acpi_status status; - ACPI_FUNCTION_TRACE_PTR("ex_acquire_mutex", obj_desc); + ACPI_FUNCTION_TRACE_PTR(ex_acquire_mutex, obj_desc); if (!obj_desc) { return_ACPI_STATUS(AE_BAD_PARAMETER); @@ -165,7 +165,7 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc, */ if (walk_state->thread->current_sync_level > obj_desc->mutex.sync_level) { ACPI_ERROR((AE_INFO, - "Cannot acquire Mutex [%4.4s], incorrect sync_level", + "Cannot acquire Mutex [%4.4s], incorrect SyncLevel", acpi_ut_get_node_name(obj_desc->mutex.node))); return_ACPI_STATUS(AE_AML_MUTEX_ORDER); } @@ -234,7 +234,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, { acpi_status status; - ACPI_FUNCTION_TRACE("ex_release_mutex"); + ACPI_FUNCTION_TRACE(ex_release_mutex); if (!obj_desc) { return_ACPI_STATUS(AE_BAD_PARAMETER); @@ -279,7 +279,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, */ if (obj_desc->mutex.sync_level > walk_state->thread->current_sync_level) { ACPI_ERROR((AE_INFO, - "Cannot release Mutex [%4.4s], incorrect sync_level", + "Cannot release Mutex [%4.4s], incorrect SyncLevel", acpi_ut_get_node_name(obj_desc->mutex.node))); return_ACPI_STATUS(AE_AML_MUTEX_ORDER); } diff --git a/drivers/acpi/executer/exnames.c b/drivers/acpi/executer/exnames.c index 085b18f8dd0..d3d70364626 100644 --- a/drivers/acpi/executer/exnames.c +++ b/drivers/acpi/executer/exnames.c @@ -77,7 +77,7 @@ static char *acpi_ex_allocate_name_string(u32 prefix_count, u32 num_name_segs) char *name_string; u32 size_needed; - ACPI_FUNCTION_TRACE("ex_allocate_name_string"); + ACPI_FUNCTION_TRACE(ex_allocate_name_string); /* * Allow room for all \ and ^ prefixes, all segments and a multi_name_prefix. @@ -162,7 +162,7 @@ static acpi_status acpi_ex_name_segment(u8 ** in_aml_address, char *name_string) u32 index; char char_buf[5]; - ACPI_FUNCTION_TRACE("ex_name_segment"); + ACPI_FUNCTION_TRACE(ex_name_segment); /* * If first character is a digit, then we know that we aren't looking at a @@ -253,7 +253,7 @@ acpi_ex_get_name_string(acpi_object_type data_type, u32 prefix_count = 0; u8 has_prefix = FALSE; - ACPI_FUNCTION_TRACE_PTR("ex_get_name_string", aml_address); + ACPI_FUNCTION_TRACE_PTR(ex_get_name_string, aml_address); if (ACPI_TYPE_LOCAL_REGION_FIELD == data_type || ACPI_TYPE_LOCAL_BANK_FIELD == data_type || @@ -277,7 +277,7 @@ acpi_ex_get_name_string(acpi_object_type data_type, case AML_ROOT_PREFIX: ACPI_DEBUG_PRINT((ACPI_DB_LOAD, - "root_prefix(\\) at %p\n", + "RootPrefix(\\) at %p\n", aml_address)); /* @@ -295,7 +295,7 @@ acpi_ex_get_name_string(acpi_object_type data_type, do { ACPI_DEBUG_PRINT((ACPI_DB_LOAD, - "parent_prefix (^) at %p\n", + "ParentPrefix (^) at %p\n", aml_address)); aml_address++; @@ -319,7 +319,7 @@ acpi_ex_get_name_string(acpi_object_type data_type, case AML_DUAL_NAME_PREFIX: ACPI_DEBUG_PRINT((ACPI_DB_LOAD, - "dual_name_prefix at %p\n", + "DualNamePrefix at %p\n", aml_address)); aml_address++; @@ -346,7 +346,7 @@ acpi_ex_get_name_string(acpi_object_type data_type, case AML_MULTI_NAME_PREFIX_OP: ACPI_DEBUG_PRINT((ACPI_DB_LOAD, - "multi_name_prefix at %p\n", + "MultiNamePrefix at %p\n", aml_address)); /* Fetch count of segments remaining in name path */ @@ -382,7 +382,7 @@ acpi_ex_get_name_string(acpi_object_type data_type, if (prefix_count == ACPI_UINT32_MAX) { ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "name_seg is \"\\\" followed by NULL\n")); + "NameSeg is \"\\\" followed by NULL\n")); } /* Consume the NULL byte */ diff --git a/drivers/acpi/executer/exoparg1.c b/drivers/acpi/executer/exoparg1.c index d00f766246f..05b89c5878e 100644 --- a/drivers/acpi/executer/exoparg1.c +++ b/drivers/acpi/executer/exoparg1.c @@ -89,7 +89,7 @@ acpi_status acpi_ex_opcode_0A_0T_1R(struct acpi_walk_state *walk_state) acpi_status status = AE_OK; union acpi_operand_object *return_desc = NULL; - ACPI_FUNCTION_TRACE_STR("ex_opcode_0A_0T_1R", + ACPI_FUNCTION_TRACE_STR(ex_opcode_0A_0T_1R, acpi_ps_get_opcode_name(walk_state->opcode)); /* Examine the AML opcode */ @@ -150,7 +150,7 @@ acpi_status acpi_ex_opcode_1A_0T_0R(struct acpi_walk_state *walk_state) union acpi_operand_object **operand = &walk_state->operands[0]; acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE_STR("ex_opcode_1A_0T_0R", + ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_0T_0R, acpi_ps_get_opcode_name(walk_state->opcode)); /* Examine the AML opcode */ @@ -216,7 +216,7 @@ acpi_status acpi_ex_opcode_1A_1T_0R(struct acpi_walk_state *walk_state) acpi_status status = AE_OK; union acpi_operand_object **operand = &walk_state->operands[0]; - ACPI_FUNCTION_TRACE_STR("ex_opcode_1A_1T_0R", + ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_1T_0R, acpi_ps_get_opcode_name(walk_state->opcode)); /* Examine the AML opcode */ @@ -264,7 +264,7 @@ acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state) acpi_integer power_of_ten; acpi_integer digit; - ACPI_FUNCTION_TRACE_STR("ex_opcode_1A_1T_1R", + ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_1T_1R, acpi_ps_get_opcode_name(walk_state->opcode)); /* Examine the AML opcode */ @@ -590,7 +590,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) u32 type; acpi_integer value; - ACPI_FUNCTION_TRACE_STR("ex_opcode_1A_0T_1R", + ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_0T_1R, acpi_ps_get_opcode_name(walk_state->opcode)); /* Examine the AML opcode */ @@ -975,7 +975,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) default: ACPI_ERROR((AE_INFO, - "Unknown Index target_type %X in obj %p", + "Unknown Index TargetType %X in obj %p", operand[0]->reference. target_type, operand[0])); status = AE_AML_OPERAND_TYPE; diff --git a/drivers/acpi/executer/exoparg2.c b/drivers/acpi/executer/exoparg2.c index 690e43db0ab..7d2cbc11316 100644 --- a/drivers/acpi/executer/exoparg2.c +++ b/drivers/acpi/executer/exoparg2.c @@ -92,7 +92,7 @@ acpi_status acpi_ex_opcode_2A_0T_0R(struct acpi_walk_state *walk_state) u32 value; acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE_STR("ex_opcode_2A_0T_0R", + ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_0T_0R, acpi_ps_get_opcode_name(walk_state->opcode)); /* Examine the opcode */ @@ -121,7 +121,7 @@ acpi_status acpi_ex_opcode_2A_0T_0R(struct acpi_walk_state *walk_state) #ifdef ACPI_GPE_NOTIFY_CHECK /* * GPE method wake/notify check. Here, we want to ensure that we - * don't receive any "device_wake" Notifies from a GPE _Lxx or _Exx + * don't receive any "DeviceWake" Notifies from a GPE _Lxx or _Exx * GPE method during system runtime. If we do, the GPE is marked * as "wake-only" and disabled. * @@ -186,7 +186,7 @@ acpi_status acpi_ex_opcode_2A_2T_1R(struct acpi_walk_state *walk_state) union acpi_operand_object *return_desc2 = NULL; acpi_status status; - ACPI_FUNCTION_TRACE_STR("ex_opcode_2A_2T_1R", + ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_2T_1R, acpi_ps_get_opcode_name(walk_state->opcode)); /* Execute the opcode */ @@ -283,7 +283,7 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state) acpi_status status = AE_OK; acpi_size length; - ACPI_FUNCTION_TRACE_STR("ex_opcode_2A_1T_1R", + ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_1T_1R, acpi_ps_get_opcode_name(walk_state->opcode)); /* Execute the opcode */ @@ -514,7 +514,7 @@ acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state) acpi_status status = AE_OK; u8 logical_result = FALSE; - ACPI_FUNCTION_TRACE_STR("ex_opcode_2A_0T_1R", + ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_0T_1R, acpi_ps_get_opcode_name(walk_state->opcode)); /* Create the internal return object */ diff --git a/drivers/acpi/executer/exoparg3.c b/drivers/acpi/executer/exoparg3.c index 4897e6c3431..e2d945dfd50 100644 --- a/drivers/acpi/executer/exoparg3.c +++ b/drivers/acpi/executer/exoparg3.c @@ -88,14 +88,14 @@ acpi_status acpi_ex_opcode_3A_0T_0R(struct acpi_walk_state *walk_state) struct acpi_signal_fatal_info *fatal; acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE_STR("ex_opcode_3A_0T_0R", + ACPI_FUNCTION_TRACE_STR(ex_opcode_3A_0T_0R, acpi_ps_get_opcode_name(walk_state->opcode)); switch (walk_state->opcode) { case AML_FATAL_OP: /* Fatal (fatal_type fatal_code fatal_arg) */ ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "fatal_op: Type %X Code %X Arg %X <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", + "FatalOp: Type %X Code %X Arg %X <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", (u32) operand[0]->integer.value, (u32) operand[1]->integer.value, (u32) operand[2]->integer.value)); @@ -150,7 +150,7 @@ acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state) acpi_integer index; acpi_size length; - ACPI_FUNCTION_TRACE_STR("ex_opcode_3A_1T_1R", + ACPI_FUNCTION_TRACE_STR(ex_opcode_3A_1T_1R, acpi_ps_get_opcode_name(walk_state->opcode)); switch (walk_state->opcode) { diff --git a/drivers/acpi/executer/exoparg6.c b/drivers/acpi/executer/exoparg6.c index 33e4fb1addc..f0c0ba6eb40 100644 --- a/drivers/acpi/executer/exoparg6.c +++ b/drivers/acpi/executer/exoparg6.c @@ -220,7 +220,7 @@ acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state * walk_state) acpi_integer index; union acpi_operand_object *this_element; - ACPI_FUNCTION_TRACE_STR("ex_opcode_6A_0T_1R", + ACPI_FUNCTION_TRACE_STR(ex_opcode_6A_0T_1R, acpi_ps_get_opcode_name(walk_state->opcode)); switch (walk_state->opcode) { diff --git a/drivers/acpi/executer/exprep.c b/drivers/acpi/executer/exprep.c index 916234bf811..44d064f427b 100644 --- a/drivers/acpi/executer/exprep.c +++ b/drivers/acpi/executer/exprep.c @@ -97,7 +97,7 @@ acpi_ex_generate_access(u32 field_bit_offset, u32 minimum_accesses = 0xFFFFFFFF; u32 accesses; - ACPI_FUNCTION_TRACE("ex_generate_access"); + ACPI_FUNCTION_TRACE(ex_generate_access); /* Round Field start offset and length to "minimal" byte boundaries */ @@ -146,7 +146,7 @@ acpi_ex_generate_access(u32 field_bit_offset, accesses = field_end_offset - field_start_offset; ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "access_width %d end is within region\n", + "AccessWidth %d end is within region\n", access_byte_width)); ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, @@ -173,7 +173,7 @@ acpi_ex_generate_access(u32 field_bit_offset, } } else { ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "access_width %d end is NOT within region\n", + "AccessWidth %d end is NOT within region\n", access_byte_width)); if (access_byte_width == 1) { ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, @@ -228,7 +228,7 @@ acpi_ex_decode_field_access(union acpi_operand_object *obj_desc, u32 byte_alignment; u32 bit_length; - ACPI_FUNCTION_TRACE("ex_decode_field_access"); + ACPI_FUNCTION_TRACE(ex_decode_field_access); access = (field_flags & AML_FIELD_ACCESS_TYPE_MASK); @@ -322,7 +322,7 @@ acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc, u32 byte_alignment; u32 nearest_byte_address; - ACPI_FUNCTION_TRACE("ex_prep_common_field_object"); + ACPI_FUNCTION_TRACE(ex_prep_common_field_object); /* * Note: the structure being initialized is the @@ -415,13 +415,13 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) u32 type; acpi_status status; - ACPI_FUNCTION_TRACE("ex_prep_field_value"); + ACPI_FUNCTION_TRACE(ex_prep_field_value); /* Parameter validation */ if (info->field_type != ACPI_TYPE_LOCAL_INDEX_FIELD) { if (!info->region_node) { - ACPI_ERROR((AE_INFO, "Null region_node")); + ACPI_ERROR((AE_INFO, "Null RegionNode")); return_ACPI_STATUS(AE_AML_NO_OPERAND); } @@ -467,7 +467,7 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) acpi_ut_add_reference(obj_desc->field.region_obj); ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "region_field: bit_off %X, Off %X, Gran %X, Region %p\n", + "RegionField: BitOff %X, Off %X, Gran %X, Region %p\n", obj_desc->field.start_field_bit_offset, obj_desc->field.base_byte_offset, obj_desc->field.access_byte_width, @@ -488,7 +488,7 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) acpi_ut_add_reference(obj_desc->bank_field.bank_obj); ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "Bank Field: bit_off %X, Off %X, Gran %X, Region %p, bank_reg %p\n", + "Bank Field: BitOff %X, Off %X, Gran %X, Region %p, BankReg %p\n", obj_desc->bank_field.start_field_bit_offset, obj_desc->bank_field.base_byte_offset, obj_desc->field.access_byte_width, @@ -519,23 +519,29 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) acpi_ut_add_reference(obj_desc->index_field.index_obj); /* - * February 2006: Changed to match MS behavior + * April 2006: Changed to match MS behavior * * The value written to the Index register is the byte offset of the - * target field. + * target field in units of the granularity of the index_field * * Previously, the value was calculated as an index in terms of the * width of the Data register, as below: * - * obj_desc->index_field.Value = (u32) - * (Info->field_bit_position / ACPI_MUL_8 ( - * obj_desc->Field.access_byte_width)); + * obj_desc->index_field.Value = (u32) + * (Info->field_bit_position / ACPI_MUL_8 ( + * obj_desc->Field.access_byte_width)); + * + * February 2006: Tried value as a byte offset: + * obj_desc->index_field.Value = (u32) + * ACPI_DIV_8 (Info->field_bit_position); */ obj_desc->index_field.value = - (u32) ACPI_DIV_8(info->field_bit_position); + (u32) ACPI_ROUND_DOWN(ACPI_DIV_8(info->field_bit_position), + obj_desc->index_field. + access_byte_width); ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "index_field: bit_off %X, Off %X, Value %X, Gran %X, Index %p, Data %p\n", + "IndexField: BitOff %X, Off %X, Value %X, Gran %X, Index %p, Data %p\n", obj_desc->index_field.start_field_bit_offset, obj_desc->index_field.base_byte_offset, obj_desc->index_field.value, @@ -557,7 +563,7 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) acpi_ns_get_type(info->field_node)); ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "Set named_obj %p [%4.4s], obj_desc %p\n", + "Set NamedObj %p [%4.4s], ObjDesc %p\n", info->field_node, acpi_ut_get_node_name(info->field_node), obj_desc)); diff --git a/drivers/acpi/executer/exregion.c b/drivers/acpi/executer/exregion.c index fdeda7beae4..4fba452a559 100644 --- a/drivers/acpi/executer/exregion.c +++ b/drivers/acpi/executer/exregion.c @@ -81,7 +81,7 @@ acpi_ex_system_memory_space_handler(u32 function, u32 remainder; #endif - ACPI_FUNCTION_TRACE("ex_system_memory_space_handler"); + ACPI_FUNCTION_TRACE(ex_system_memory_space_handler); /* Validate and translate the bit width */ @@ -103,7 +103,7 @@ acpi_ex_system_memory_space_handler(u32 function, break; default: - ACPI_ERROR((AE_INFO, "Invalid system_memory width %d", + ACPI_ERROR((AE_INFO, "Invalid SystemMemory width %d", bit_width)); return_ACPI_STATUS(AE_AML_OPERAND_VALUE); } @@ -284,7 +284,7 @@ acpi_ex_system_io_space_handler(u32 function, acpi_status status = AE_OK; u32 value32; - ACPI_FUNCTION_TRACE("ex_system_io_space_handler"); + ACPI_FUNCTION_TRACE(ex_system_io_space_handler); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "System-IO (width %d) R/W %d Address=%8.8X%8.8X\n", @@ -343,7 +343,7 @@ acpi_ex_pci_config_space_handler(u32 function, struct acpi_pci_id *pci_id; u16 pci_register; - ACPI_FUNCTION_TRACE("ex_pci_config_space_handler"); + ACPI_FUNCTION_TRACE(ex_pci_config_space_handler); /* * The arguments to acpi_os(Read|Write)pci_configuration are: @@ -415,7 +415,7 @@ acpi_ex_cmos_space_handler(u32 function, { acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("ex_cmos_space_handler"); + ACPI_FUNCTION_TRACE(ex_cmos_space_handler); return_ACPI_STATUS(status); } @@ -447,7 +447,7 @@ acpi_ex_pci_bar_space_handler(u32 function, { acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("ex_pci_bar_space_handler"); + ACPI_FUNCTION_TRACE(ex_pci_bar_space_handler); return_ACPI_STATUS(status); } @@ -482,7 +482,7 @@ acpi_ex_data_table_space_handler(u32 function, u32 i; char *logical_addr_ptr; - ACPI_FUNCTION_TRACE("ex_data_table_space_handler"); + ACPI_FUNCTION_TRACE(ex_data_table_space_handler); logical_addr_ptr = ACPI_PHYSADDR_TO_PTR(address); diff --git a/drivers/acpi/executer/exresnte.c b/drivers/acpi/executer/exresnte.c index 417d914d9e1..f9b9f500859 100644 --- a/drivers/acpi/executer/exresnte.c +++ b/drivers/acpi/executer/exresnte.c @@ -87,7 +87,7 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, struct acpi_namespace_node *node; acpi_object_type entry_type; - ACPI_FUNCTION_TRACE("ex_resolve_node_to_value"); + ACPI_FUNCTION_TRACE(ex_resolve_node_to_value); /* * The stack pointer points to a struct acpi_namespace_node (Node). Get the @@ -97,7 +97,7 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, source_desc = acpi_ns_get_attached_object(node); entry_type = acpi_ns_get_type((acpi_handle) node); - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Entry=%p source_desc=%p [%s]\n", + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Entry=%p SourceDesc=%p [%s]\n", node, source_desc, acpi_ut_get_type_name(entry_type))); @@ -202,7 +202,7 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, case ACPI_TYPE_LOCAL_INDEX_FIELD: ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "field_read Node=%p source_desc=%p Type=%X\n", + "FieldRead Node=%p SourceDesc=%p Type=%X\n", node, source_desc, entry_type)); status = diff --git a/drivers/acpi/executer/exresolv.c b/drivers/acpi/executer/exresolv.c index 22dabdd1060..006bba035d5 100644 --- a/drivers/acpi/executer/exresolv.c +++ b/drivers/acpi/executer/exresolv.c @@ -78,7 +78,7 @@ acpi_ex_resolve_to_value(union acpi_operand_object **stack_ptr, { acpi_status status; - ACPI_FUNCTION_TRACE_PTR("ex_resolve_to_value", stack_ptr); + ACPI_FUNCTION_TRACE_PTR(ex_resolve_to_value, stack_ptr); if (!stack_ptr || !*stack_ptr) { ACPI_ERROR((AE_INFO, "Internal - null pointer")); @@ -144,7 +144,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, union acpi_operand_object *obj_desc; u16 opcode; - ACPI_FUNCTION_TRACE("ex_resolve_object_to_value"); + ACPI_FUNCTION_TRACE(ex_resolve_object_to_value); stack_desc = *stack_ptr; @@ -190,7 +190,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, } ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "[Arg/Local %X] value_obj is %p\n", + "[Arg/Local %X] ValueObj is %p\n", stack_desc->reference.offset, obj_desc)); @@ -239,7 +239,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, /* Invalid reference object */ ACPI_ERROR((AE_INFO, - "Unknown target_type %X in Index/Reference obj %p", + "Unknown TargetType %X in Index/Reference obj %p", stack_desc->reference.target_type, stack_desc)); status = AE_AML_INTERNAL; @@ -293,7 +293,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, case ACPI_TYPE_LOCAL_INDEX_FIELD: ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "field_read source_desc=%p Type=%X\n", + "FieldRead SourceDesc=%p Type=%X\n", stack_desc, ACPI_GET_OBJECT_TYPE(stack_desc))); @@ -337,7 +337,7 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, acpi_object_type type; acpi_status status; - ACPI_FUNCTION_TRACE("acpi_ex_resolve_multiple"); + ACPI_FUNCTION_TRACE(acpi_ex_resolve_multiple); /* Operand can be either a namespace node or an operand descriptor */ @@ -488,7 +488,7 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, case AML_DEBUG_OP: - /* The Debug Object is of type "debug_object" */ + /* The Debug Object is of type "DebugObject" */ type = ACPI_TYPE_DEBUG_OBJECT; goto exit; diff --git a/drivers/acpi/executer/exresop.c b/drivers/acpi/executer/exresop.c index 42b9089dccc..4c93d097233 100644 --- a/drivers/acpi/executer/exresop.c +++ b/drivers/acpi/executer/exresop.c @@ -144,7 +144,7 @@ acpi_ex_resolve_operands(u16 opcode, acpi_object_type type_needed; u16 target_op = 0; - ACPI_FUNCTION_TRACE_U32("ex_resolve_operands", opcode); + ACPI_FUNCTION_TRACE_U32(ex_resolve_operands, opcode); op_info = acpi_ps_get_opcode_info(opcode); if (op_info->class == AML_CLASS_UNKNOWN) { @@ -159,7 +159,7 @@ acpi_ex_resolve_operands(u16 opcode, } ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Opcode %X [%s] required_operand_types=%8.8X\n", + "Opcode %X [%s] RequiredOperandTypes=%8.8X\n", opcode, op_info->name, arg_types)); /* @@ -249,7 +249,7 @@ acpi_ex_resolve_operands(u16 opcode, ACPI_DEBUG_ONLY_MEMBERS(ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, - "Operand is a Reference, ref_opcode [%s]\n", + "Operand is a Reference, RefOpcode [%s]\n", (acpi_ps_get_opcode_info (obj_desc-> reference. @@ -626,7 +626,7 @@ acpi_ex_resolve_operands(u16 opcode, default: ACPI_ERROR((AE_INFO, - "Needed [Region/region_field], found [%s] %p", + "Needed [Region/RegionField], found [%s] %p", acpi_ut_get_object_type_name (obj_desc), obj_desc)); diff --git a/drivers/acpi/executer/exstore.c b/drivers/acpi/executer/exstore.c index 287476f319f..0456405ba01 100644 --- a/drivers/acpi/executer/exstore.c +++ b/drivers/acpi/executer/exstore.c @@ -82,7 +82,7 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, { u32 i; - ACPI_FUNCTION_TRACE_PTR("ex_do_debug_object", source_desc); + ACPI_FUNCTION_TRACE_PTR(ex_do_debug_object, source_desc); ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[ACPI Debug] %*s", level, " ")); @@ -245,7 +245,7 @@ acpi_ex_store(union acpi_operand_object *source_desc, acpi_status status = AE_OK; union acpi_operand_object *ref_desc = dest_desc; - ACPI_FUNCTION_TRACE_PTR("ex_store", dest_desc); + ACPI_FUNCTION_TRACE_PTR(ex_store, dest_desc); /* Validate parameters */ @@ -297,7 +297,7 @@ acpi_ex_store(union acpi_operand_object *source_desc, ACPI_DUMP_STACK_ENTRY(source_desc); ACPI_DUMP_STACK_ENTRY(dest_desc); - ACPI_DUMP_OPERANDS(&dest_desc, ACPI_IMODE_EXECUTE, "ex_store", + ACPI_DUMP_OPERANDS(&dest_desc, ACPI_IMODE_EXECUTE, "ExStore", 2, "Target is not a Reference or Constant object"); @@ -396,7 +396,7 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc, u8 value = 0; u32 i; - ACPI_FUNCTION_TRACE("ex_store_object_to_index"); + ACPI_FUNCTION_TRACE(ex_store_object_to_index); /* * Destination must be a reference pointer, and @@ -503,8 +503,7 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc, break; default: - ACPI_ERROR((AE_INFO, - "Target is not a Package or buffer_field")); + ACPI_ERROR((AE_INFO, "Target is not a Package or BufferField")); status = AE_AML_OPERAND_TYPE; break; } @@ -549,7 +548,7 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, union acpi_operand_object *new_desc; acpi_object_type target_type; - ACPI_FUNCTION_TRACE_PTR("ex_store_object_to_node", source_desc); + ACPI_FUNCTION_TRACE_PTR(ex_store_object_to_node, source_desc); /* Get current type of the node, and object attached to Node */ diff --git a/drivers/acpi/executer/exstoren.c b/drivers/acpi/executer/exstoren.c index 969f9cbbbee..591aaf0e18b 100644 --- a/drivers/acpi/executer/exstoren.c +++ b/drivers/acpi/executer/exstoren.c @@ -72,7 +72,7 @@ acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr, union acpi_operand_object *source_desc = *source_desc_ptr; acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("ex_resolve_object"); + ACPI_FUNCTION_TRACE(ex_resolve_object); /* Ensure we have a Target that can be stored to */ @@ -201,7 +201,7 @@ acpi_ex_store_object_to_object(union acpi_operand_object *source_desc, union acpi_operand_object *actual_src_desc; acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE_PTR("ex_store_object_to_object", source_desc); + ACPI_FUNCTION_TRACE_PTR(ex_store_object_to_object, source_desc); actual_src_desc = source_desc; if (!dest_desc) { diff --git a/drivers/acpi/executer/exstorob.c b/drivers/acpi/executer/exstorob.c index db42461101e..18925f5b313 100644 --- a/drivers/acpi/executer/exstorob.c +++ b/drivers/acpi/executer/exstorob.c @@ -67,7 +67,7 @@ acpi_ex_store_buffer_to_buffer(union acpi_operand_object *source_desc, u32 length; u8 *buffer; - ACPI_FUNCTION_TRACE_PTR("ex_store_buffer_to_buffer", source_desc); + ACPI_FUNCTION_TRACE_PTR(ex_store_buffer_to_buffer, source_desc); /* We know that source_desc is a buffer by now */ @@ -158,7 +158,7 @@ acpi_ex_store_string_to_string(union acpi_operand_object *source_desc, u32 length; u8 *buffer; - ACPI_FUNCTION_TRACE_PTR("ex_store_string_to_string", source_desc); + ACPI_FUNCTION_TRACE_PTR(ex_store_string_to_string, source_desc); /* We know that source_desc is a string by now */ diff --git a/drivers/acpi/executer/exsystem.c b/drivers/acpi/executer/exsystem.c index 6a2e47a0e11..52beee3674a 100644 --- a/drivers/acpi/executer/exsystem.c +++ b/drivers/acpi/executer/exsystem.c @@ -68,7 +68,7 @@ acpi_status acpi_ex_system_wait_semaphore(acpi_handle semaphore, u16 timeout) acpi_status status; acpi_status status2; - ACPI_FUNCTION_TRACE("ex_system_wait_semaphore"); + ACPI_FUNCTION_TRACE(ex_system_wait_semaphore); status = acpi_os_wait_semaphore(semaphore, 1, 0); if (ACPI_SUCCESS(status)) { @@ -193,7 +193,7 @@ acpi_ex_system_acquire_mutex(union acpi_operand_object * time_desc, { acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE_PTR("ex_system_acquire_mutex", obj_desc); + ACPI_FUNCTION_TRACE_PTR(ex_system_acquire_mutex, obj_desc); if (!obj_desc) { return_ACPI_STATUS(AE_BAD_PARAMETER); @@ -231,7 +231,7 @@ acpi_status acpi_ex_system_release_mutex(union acpi_operand_object *obj_desc) { acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("ex_system_release_mutex"); + ACPI_FUNCTION_TRACE(ex_system_release_mutex); if (!obj_desc) { return_ACPI_STATUS(AE_BAD_PARAMETER); @@ -265,7 +265,7 @@ acpi_status acpi_ex_system_signal_event(union acpi_operand_object *obj_desc) { acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("ex_system_signal_event"); + ACPI_FUNCTION_TRACE(ex_system_signal_event); if (obj_desc) { status = acpi_os_signal_semaphore(obj_desc->event.semaphore, 1); @@ -295,7 +295,7 @@ acpi_ex_system_wait_event(union acpi_operand_object *time_desc, { acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("ex_system_wait_event"); + ACPI_FUNCTION_TRACE(ex_system_wait_event); if (obj_desc) { status = diff --git a/drivers/acpi/executer/exutils.c b/drivers/acpi/executer/exutils.c index 8543d1a0ed3..3ef8cd703e0 100644 --- a/drivers/acpi/executer/exutils.c +++ b/drivers/acpi/executer/exutils.c @@ -87,7 +87,7 @@ acpi_status acpi_ex_enter_interpreter(void) { acpi_status status; - ACPI_FUNCTION_TRACE("ex_enter_interpreter"); + ACPI_FUNCTION_TRACE(ex_enter_interpreter); status = acpi_ut_acquire_mutex(ACPI_MTX_EXECUTE); if (ACPI_FAILURE(status)) { @@ -123,7 +123,7 @@ void acpi_ex_exit_interpreter(void) { acpi_status status; - ACPI_FUNCTION_TRACE("ex_exit_interpreter"); + ACPI_FUNCTION_TRACE(ex_exit_interpreter); status = acpi_ut_release_mutex(ACPI_MTX_EXECUTE); if (ACPI_FAILURE(status)) { @@ -189,7 +189,7 @@ u8 acpi_ex_acquire_global_lock(u32 field_flags) u8 locked = FALSE; acpi_status status; - ACPI_FUNCTION_TRACE("ex_acquire_global_lock"); + ACPI_FUNCTION_TRACE(ex_acquire_global_lock); /* Only attempt lock if the always_lock bit is set */ @@ -226,7 +226,7 @@ void acpi_ex_release_global_lock(u8 locked_by_me) { acpi_status status; - ACPI_FUNCTION_TRACE("ex_release_global_lock"); + ACPI_FUNCTION_TRACE(ex_release_global_lock); /* Only attempt unlock if the caller locked it */ @@ -266,7 +266,7 @@ static u32 acpi_ex_digits_needed(acpi_integer value, u32 base) u32 num_digits; acpi_integer current_value; - ACPI_FUNCTION_TRACE("ex_digits_needed"); + ACPI_FUNCTION_TRACE(ex_digits_needed); /* acpi_integer is unsigned, so we don't worry about a '-' prefix */ diff --git a/drivers/acpi/hardware/hwacpi.c b/drivers/acpi/hardware/hwacpi.c index ea2f13271ff..de50fab2a91 100644 --- a/drivers/acpi/hardware/hwacpi.c +++ b/drivers/acpi/hardware/hwacpi.c @@ -63,7 +63,7 @@ acpi_status acpi_hw_initialize(void) { acpi_status status; - ACPI_FUNCTION_TRACE("hw_initialize"); + ACPI_FUNCTION_TRACE(hw_initialize); /* We must have the ACPI tables by the time we get here */ @@ -100,7 +100,7 @@ acpi_status acpi_hw_set_mode(u32 mode) acpi_status status; u32 retry; - ACPI_FUNCTION_TRACE("hw_set_mode"); + ACPI_FUNCTION_TRACE(hw_set_mode); /* * ACPI 2.0 clarified that if SMI_CMD in FADT is zero, @@ -198,7 +198,7 @@ u32 acpi_hw_get_mode(void) acpi_status status; u32 value; - ACPI_FUNCTION_TRACE("hw_get_mode"); + ACPI_FUNCTION_TRACE(hw_get_mode); /* * ACPI 2.0 clarified that if SMI_CMD in FADT is zero, diff --git a/drivers/acpi/hardware/hwgpe.c b/drivers/acpi/hardware/hwgpe.c index 729b68eb3e3..608a3a60ee1 100644 --- a/drivers/acpi/hardware/hwgpe.c +++ b/drivers/acpi/hardware/hwgpe.c @@ -370,7 +370,7 @@ acpi_status acpi_hw_disable_all_gpes(void) { acpi_status status; - ACPI_FUNCTION_TRACE("hw_disable_all_gpes"); + ACPI_FUNCTION_TRACE(hw_disable_all_gpes); status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block); status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block); @@ -393,7 +393,7 @@ acpi_status acpi_hw_enable_all_runtime_gpes(void) { acpi_status status; - ACPI_FUNCTION_TRACE("hw_enable_all_runtime_gpes"); + ACPI_FUNCTION_TRACE(hw_enable_all_runtime_gpes); status = acpi_ev_walk_gpe_list(acpi_hw_enable_runtime_gpe_block); return_ACPI_STATUS(status); @@ -415,7 +415,7 @@ acpi_status acpi_hw_enable_all_wakeup_gpes(void) { acpi_status status; - ACPI_FUNCTION_TRACE("hw_enable_all_wakeup_gpes"); + ACPI_FUNCTION_TRACE(hw_enable_all_wakeup_gpes); status = acpi_ev_walk_gpe_list(acpi_hw_enable_wakeup_gpe_block); return_ACPI_STATUS(status); diff --git a/drivers/acpi/hardware/hwregs.c b/drivers/acpi/hardware/hwregs.c index 3d1f41c6bfe..ec9f5a11a8b 100644 --- a/drivers/acpi/hardware/hwregs.c +++ b/drivers/acpi/hardware/hwregs.c @@ -66,7 +66,7 @@ acpi_status acpi_hw_clear_acpi_status(u32 flags) { acpi_status status; - ACPI_FUNCTION_TRACE("hw_clear_acpi_status"); + ACPI_FUNCTION_TRACE(hw_clear_acpi_status); ACPI_DEBUG_PRINT((ACPI_DB_IO, "About to write %04X to %04X\n", ACPI_BITMASK_ALL_FIXED_STATUS, @@ -130,7 +130,7 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 * sleep_type_a, u8 * sleep_type_b) struct acpi_parameter_info info; char *sleep_state_name; - ACPI_FUNCTION_TRACE("acpi_get_sleep_type_data"); + ACPI_FUNCTION_TRACE(acpi_get_sleep_type_data); /* Validate parameters */ @@ -148,7 +148,7 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 * sleep_type_a, u8 * sleep_type_b) status = acpi_ns_evaluate_by_name(sleep_state_name, &info); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "%s while evaluating sleep_state [%s]\n", + "%s while evaluating SleepState [%s]\n", acpi_format_exception(status), sleep_state_name)); @@ -208,7 +208,7 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 * sleep_type_a, u8 * sleep_type_b) if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, - "While evaluating sleep_state [%s], bad Sleep object %p type %s", + "While evaluating SleepState [%s], bad Sleep object %p type %s", sleep_state_name, info.return_object, acpi_ut_get_object_type_name(info. return_object))); @@ -236,7 +236,7 @@ struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id) ACPI_FUNCTION_ENTRY(); if (register_id > ACPI_BITREG_MAX) { - ACPI_ERROR((AE_INFO, "Invalid bit_register ID: %X", + ACPI_ERROR((AE_INFO, "Invalid BitRegister ID: %X", register_id)); return (NULL); } @@ -265,7 +265,7 @@ acpi_status acpi_get_register(u32 register_id, u32 * return_value, u32 flags) struct acpi_bit_register_info *bit_reg_info; acpi_status status; - ACPI_FUNCTION_TRACE("acpi_get_register"); + ACPI_FUNCTION_TRACE(acpi_get_register); /* Get the info structure corresponding to the requested ACPI Register */ @@ -331,13 +331,13 @@ acpi_status acpi_set_register(u32 register_id, u32 value, u32 flags) struct acpi_bit_register_info *bit_reg_info; acpi_status status; - ACPI_FUNCTION_TRACE_U32("acpi_set_register", register_id); + ACPI_FUNCTION_TRACE_U32(acpi_set_register, register_id); /* Get the info structure corresponding to the requested ACPI Register */ bit_reg_info = acpi_hw_get_bit_register_info(register_id); if (!bit_reg_info) { - ACPI_ERROR((AE_INFO, "Bad ACPI HW register_id: %X", + ACPI_ERROR((AE_INFO, "Bad ACPI HW RegisterId: %X", register_id)); return_ACPI_STATUS(AE_BAD_PARAMETER); } @@ -494,7 +494,7 @@ acpi_hw_register_read(u8 use_lock, u32 register_id, u32 * return_value) u32 value2 = 0; acpi_status status; - ACPI_FUNCTION_TRACE("hw_register_read"); + ACPI_FUNCTION_TRACE(hw_register_read); if (ACPI_MTX_LOCK == use_lock) { status = acpi_ut_acquire_mutex(ACPI_MTX_HARDWARE); @@ -607,7 +607,7 @@ acpi_status acpi_hw_register_write(u8 use_lock, u32 register_id, u32 value) { acpi_status status; - ACPI_FUNCTION_TRACE("hw_register_write"); + ACPI_FUNCTION_TRACE(hw_register_write); if (ACPI_MTX_LOCK == use_lock) { status = acpi_ut_acquire_mutex(ACPI_MTX_HARDWARE); @@ -729,7 +729,7 @@ acpi_hw_low_level_read(u32 width, u32 * value, struct acpi_generic_address *reg) u64 address; acpi_status status; - ACPI_FUNCTION_NAME("hw_low_level_read"); + ACPI_FUNCTION_NAME(hw_low_level_read); /* * Must have a valid pointer to a GAS structure, and @@ -801,7 +801,7 @@ acpi_hw_low_level_write(u32 width, u32 value, struct acpi_generic_address * reg) u64 address; acpi_status status; - ACPI_FUNCTION_NAME("hw_low_level_write"); + ACPI_FUNCTION_NAME(hw_low_level_write); /* * Must have a valid pointer to a GAS structure, and diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c index 685debafbb7..8bb43cae60c 100644 --- a/drivers/acpi/hardware/hwsleep.c +++ b/drivers/acpi/hardware/hwsleep.c @@ -63,7 +63,7 @@ acpi_status acpi_set_firmware_waking_vector(acpi_physical_address physical_address) { - ACPI_FUNCTION_TRACE("acpi_set_firmware_waking_vector"); + ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector); /* Set the vector */ @@ -98,7 +98,7 @@ acpi_status acpi_get_firmware_waking_vector(acpi_physical_address * physical_address) { - ACPI_FUNCTION_TRACE("acpi_get_firmware_waking_vector"); + ACPI_FUNCTION_TRACE(acpi_get_firmware_waking_vector); if (!physical_address) { return_ACPI_STATUS(AE_BAD_PARAMETER); @@ -142,7 +142,7 @@ acpi_status acpi_enter_sleep_state_prep(u8 sleep_state) struct acpi_object_list arg_list; union acpi_object arg; - ACPI_FUNCTION_TRACE("acpi_enter_sleep_state_prep"); + ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_prep); /* * _PSW methods could be run here to enable wake-on keyboard, LAN, etc. @@ -230,7 +230,7 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) u32 in_value; acpi_status status; - ACPI_FUNCTION_TRACE("acpi_enter_sleep_state"); + ACPI_FUNCTION_TRACE(acpi_enter_sleep_state); if ((acpi_gbl_sleep_type_a > ACPI_SLEEP_TYPE_MAX) || (acpi_gbl_sleep_type_b > ACPI_SLEEP_TYPE_MAX)) { @@ -399,7 +399,7 @@ acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void) u32 in_value; acpi_status status; - ACPI_FUNCTION_TRACE("acpi_enter_sleep_state_s4bios"); + ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_s4bios); status = acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK); @@ -468,7 +468,7 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state) u32 PM1Acontrol; u32 PM1Bcontrol; - ACPI_FUNCTION_TRACE("acpi_leave_sleep_state"); + ACPI_FUNCTION_TRACE(acpi_leave_sleep_state); /* * Set SLP_TYPE and SLP_EN to state S0. diff --git a/drivers/acpi/hardware/hwtimer.c b/drivers/acpi/hardware/hwtimer.c index a559ac17b13..c4ec47c939f 100644 --- a/drivers/acpi/hardware/hwtimer.c +++ b/drivers/acpi/hardware/hwtimer.c @@ -60,7 +60,7 @@ ACPI_MODULE_NAME("hwtimer") ******************************************************************************/ acpi_status acpi_get_timer_resolution(u32 * resolution) { - ACPI_FUNCTION_TRACE("acpi_get_timer_resolution"); + ACPI_FUNCTION_TRACE(acpi_get_timer_resolution); if (!resolution) { return_ACPI_STATUS(AE_BAD_PARAMETER); @@ -92,7 +92,7 @@ acpi_status acpi_get_timer(u32 * ticks) { acpi_status status; - ACPI_FUNCTION_TRACE("acpi_get_timer"); + ACPI_FUNCTION_TRACE(acpi_get_timer); if (!ticks) { return_ACPI_STATUS(AE_BAD_PARAMETER); @@ -140,7 +140,7 @@ acpi_get_timer_duration(u32 start_ticks, u32 end_ticks, u32 * time_elapsed) u32 delta_ticks; acpi_integer quotient; - ACPI_FUNCTION_TRACE("acpi_get_timer_duration"); + ACPI_FUNCTION_TRACE(acpi_get_timer_duration); if (!time_elapsed) { return_ACPI_STATUS(AE_BAD_PARAMETER); diff --git a/drivers/acpi/namespace/nsaccess.c b/drivers/acpi/namespace/nsaccess.c index d4914fda6a3..5e3f63a90fb 100644 --- a/drivers/acpi/namespace/nsaccess.c +++ b/drivers/acpi/namespace/nsaccess.c @@ -70,7 +70,7 @@ acpi_status acpi_ns_root_initialize(void) union acpi_operand_object *obj_desc; acpi_string val = NULL; - ACPI_FUNCTION_TRACE("ns_root_initialize"); + ACPI_FUNCTION_TRACE(ns_root_initialize); status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { @@ -314,7 +314,7 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, u32 local_flags = flags & ~(ACPI_NS_ERROR_IF_FOUND | ACPI_NS_SEARCH_PARENT); - ACPI_FUNCTION_TRACE("ns_lookup"); + ACPI_FUNCTION_TRACE(ns_lookup); if (!return_node) { return_ACPI_STATUS(AE_BAD_PARAMETER); @@ -615,7 +615,7 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, /* Complain about a type mismatch */ ACPI_WARNING((AE_INFO, - "ns_lookup: Type mismatch on %4.4s (%s), searching for (%s)", + "NsLookup: Type mismatch on %4.4s (%s), searching for (%s)", ACPI_CAST_PTR(char, &simple_name), acpi_ut_get_type_name(this_node->type), acpi_ut_get_type_name diff --git a/drivers/acpi/namespace/nsalloc.c b/drivers/acpi/namespace/nsalloc.c index c92c03693a1..dc3f0739a46 100644 --- a/drivers/acpi/namespace/nsalloc.c +++ b/drivers/acpi/namespace/nsalloc.c @@ -62,7 +62,7 @@ struct acpi_namespace_node *acpi_ns_create_node(u32 name) { struct acpi_namespace_node *node; - ACPI_FUNCTION_TRACE("ns_create_node"); + ACPI_FUNCTION_TRACE(ns_create_node); node = acpi_os_acquire_object(acpi_gbl_namespace_cache); if (!node) { @@ -94,7 +94,7 @@ void acpi_ns_delete_node(struct acpi_namespace_node *node) struct acpi_namespace_node *prev_node; struct acpi_namespace_node *next_node; - ACPI_FUNCTION_TRACE_PTR("ns_delete_node", node); + ACPI_FUNCTION_TRACE_PTR(ns_delete_node, node); parent_node = acpi_ns_get_parent_node(node); @@ -167,7 +167,7 @@ void acpi_ns_install_node(struct acpi_walk_state *walk_state, struct acpi_namesp acpi_owner_id owner_id = 0; struct acpi_namespace_node *child_node; - ACPI_FUNCTION_TRACE("ns_install_node"); + ACPI_FUNCTION_TRACE(ns_install_node); /* * Get the owner ID from the Walk state @@ -234,7 +234,7 @@ void acpi_ns_delete_children(struct acpi_namespace_node *parent_node) struct acpi_namespace_node *next_node; u8 flags; - ACPI_FUNCTION_TRACE_PTR("ns_delete_children", parent_node); + ACPI_FUNCTION_TRACE_PTR(ns_delete_children, parent_node); if (!parent_node) { return_VOID; @@ -313,7 +313,7 @@ void acpi_ns_delete_namespace_subtree(struct acpi_namespace_node *parent_node) struct acpi_namespace_node *child_node = NULL; u32 level = 1; - ACPI_FUNCTION_TRACE("ns_delete_namespace_subtree"); + ACPI_FUNCTION_TRACE(ns_delete_namespace_subtree); if (!parent_node) { return_VOID; @@ -395,7 +395,7 @@ void acpi_ns_delete_namespace_by_owner(acpi_owner_id owner_id) u32 level; struct acpi_namespace_node *parent_node; - ACPI_FUNCTION_TRACE_U32("ns_delete_namespace_by_owner", owner_id); + ACPI_FUNCTION_TRACE_U32(ns_delete_namespace_by_owner, owner_id); if (owner_id == 0) { return_VOID; diff --git a/drivers/acpi/namespace/nsdump.c b/drivers/acpi/namespace/nsdump.c index 5662d2def62..d72df66aa96 100644 --- a/drivers/acpi/namespace/nsdump.c +++ b/drivers/acpi/namespace/nsdump.c @@ -75,7 +75,7 @@ void acpi_ns_print_pathname(u32 num_segments, char *pathname) { acpi_native_uint i; - ACPI_FUNCTION_NAME("ns_print_pathname"); + ACPI_FUNCTION_NAME(ns_print_pathname); if (!(acpi_dbg_level & ACPI_LV_NAMES) || !(acpi_dbg_layer & ACPI_NAMESPACE)) { @@ -123,7 +123,7 @@ void acpi_ns_dump_pathname(acpi_handle handle, char *msg, u32 level, u32 component) { - ACPI_FUNCTION_TRACE("ns_dump_pathname"); + ACPI_FUNCTION_TRACE(ns_dump_pathname); /* Do this only if the requested debug level and component are enabled */ @@ -167,7 +167,7 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, u32 dbg_level; u32 i; - ACPI_FUNCTION_NAME("ns_dump_one_object"); + ACPI_FUNCTION_NAME(ns_dump_one_object); /* Is output enabled? */ @@ -675,7 +675,7 @@ void acpi_ns_dump_tables(acpi_handle search_base, u32 max_depth) { acpi_handle search_handle = search_base; - ACPI_FUNCTION_TRACE("ns_dump_tables"); + ACPI_FUNCTION_TRACE(ns_dump_tables); if (!acpi_gbl_root_node) { /* diff --git a/drivers/acpi/namespace/nsdumpdv.c b/drivers/acpi/namespace/nsdumpdv.c index 2b311da01ef..c6bf5d30fca 100644 --- a/drivers/acpi/namespace/nsdumpdv.c +++ b/drivers/acpi/namespace/nsdumpdv.c @@ -74,7 +74,7 @@ acpi_ns_dump_one_device(acpi_handle obj_handle, acpi_status status; u32 i; - ACPI_FUNCTION_NAME("ns_dump_one_device"); + ACPI_FUNCTION_NAME(ns_dump_one_device); status = acpi_ns_dump_one_object(obj_handle, level, context, return_value); @@ -115,7 +115,7 @@ void acpi_ns_dump_root_devices(void) acpi_handle sys_bus_handle; acpi_status status; - ACPI_FUNCTION_NAME("ns_dump_root_devices"); + ACPI_FUNCTION_NAME(ns_dump_root_devices); /* Only dump the table if tracing is enabled */ diff --git a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c index f5d8e71b82c..4b054062b46 100644 --- a/drivers/acpi/namespace/nseval.c +++ b/drivers/acpi/namespace/nseval.c @@ -85,7 +85,7 @@ acpi_ns_evaluate_relative(char *pathname, struct acpi_parameter_info *info) union acpi_generic_state *scope_info; char *internal_path = NULL; - ACPI_FUNCTION_TRACE("ns_evaluate_relative"); + ACPI_FUNCTION_TRACE(ns_evaluate_relative); /* * Must have a valid object handle @@ -182,7 +182,7 @@ acpi_ns_evaluate_by_name(char *pathname, struct acpi_parameter_info *info) acpi_status status; char *internal_path = NULL; - ACPI_FUNCTION_TRACE("ns_evaluate_by_name"); + ACPI_FUNCTION_TRACE(ns_evaluate_by_name); /* Build an internal name string for the method */ @@ -262,7 +262,7 @@ acpi_status acpi_ns_evaluate_by_handle(struct acpi_parameter_info *info) { acpi_status status; - ACPI_FUNCTION_TRACE("ns_evaluate_by_handle"); + ACPI_FUNCTION_TRACE(ns_evaluate_by_handle); /* Check if namespace has been initialized */ @@ -368,7 +368,7 @@ acpi_ns_execute_control_method(struct acpi_parameter_info *info) { acpi_status status; - ACPI_FUNCTION_TRACE("ns_execute_control_method"); + ACPI_FUNCTION_TRACE(ns_execute_control_method); /* Verify that there is a method associated with this object */ @@ -436,7 +436,7 @@ static acpi_status acpi_ns_get_object_value(struct acpi_parameter_info *info) acpi_status status = AE_OK; struct acpi_namespace_node *resolved_node = info->node; - ACPI_FUNCTION_TRACE("ns_get_object_value"); + ACPI_FUNCTION_TRACE(ns_get_object_value); /* * Objects require additional resolution steps (e.g., the Node may be a diff --git a/drivers/acpi/namespace/nsinit.c b/drivers/acpi/namespace/nsinit.c index 57b2537643c..bf1d8dbc0b8 100644 --- a/drivers/acpi/namespace/nsinit.c +++ b/drivers/acpi/namespace/nsinit.c @@ -58,6 +58,10 @@ static acpi_status acpi_ns_init_one_device(acpi_handle obj_handle, u32 nesting_level, void *context, void **return_value); +static acpi_status +acpi_ns_find_ini_methods(acpi_handle obj_handle, + u32 nesting_level, void *context, void **return_value); + /******************************************************************************* * * FUNCTION: acpi_ns_initialize_objects @@ -76,7 +80,7 @@ acpi_status acpi_ns_initialize_objects(void) acpi_status status; struct acpi_init_walk_info info; - ACPI_FUNCTION_TRACE("ns_initialize_objects"); + ACPI_FUNCTION_TRACE(ns_initialize_objects); ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "**** Starting initialization of namespace objects ****\n")); @@ -93,7 +97,7 @@ acpi_status acpi_ns_initialize_objects(void) ACPI_UINT32_MAX, acpi_ns_init_one_object, &info, NULL); if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "During walk_namespace")); + ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace")); } ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, @@ -133,7 +137,7 @@ acpi_status acpi_ns_initialize_devices(void) acpi_status status; struct acpi_device_walk_info info; - ACPI_FUNCTION_TRACE("ns_initialize_devices"); + ACPI_FUNCTION_TRACE(ns_initialize_devices); /* Init counters */ @@ -142,28 +146,29 @@ acpi_status acpi_ns_initialize_devices(void) info.num_INI = 0; ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, - "Executing all Device _STA and_INI methods:")); + "Initializing Device/Processor/Thermal objects by executing _INI methods:")); + + /* Tree analysis: find all subtrees that contain _INI methods */ - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, FALSE, + acpi_ns_find_ini_methods, &info, NULL); if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace")); } - /* Walk namespace for all objects */ + /* Walk namespace to execute all _INIs on present devices */ status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, TRUE, + ACPI_UINT32_MAX, FALSE, acpi_ns_init_one_device, &info, NULL); - - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "During walk_namespace")); + ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace")); } ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, - "\n%hd Devices found - executed %hd _STA, %hd _INI methods\n", - info.device_count, info.num_STA, info.num_INI)); + "\nExecuted %hd _INI methods requiring %hd _STA executions (examined %hd objects)\n", + info.num_INI, info.num_STA, info.device_count)); return_ACPI_STATUS(status); } @@ -200,7 +205,7 @@ acpi_ns_init_one_object(acpi_handle obj_handle, (struct acpi_namespace_node *)obj_handle; union acpi_operand_object *obj_desc; - ACPI_FUNCTION_NAME("ns_init_one_object"); + ACPI_FUNCTION_NAME(ns_init_one_object); info->object_count++; @@ -309,6 +314,72 @@ acpi_ns_init_one_object(acpi_handle obj_handle, return (AE_OK); } +/******************************************************************************* + * + * FUNCTION: acpi_ns_find_ini_methods + * + * PARAMETERS: acpi_walk_callback + * + * RETURN: acpi_status + * + * DESCRIPTION: Called during namespace walk. Finds objects named _INI under + * device/processor/thermal objects, and marks the entire subtree + * with a SUBTREE_HAS_INI flag. This flag is used during the + * subsequent device initialization walk to avoid entire subtrees + * that do not contain an _INI. + * + ******************************************************************************/ + +static acpi_status +acpi_ns_find_ini_methods(acpi_handle obj_handle, + u32 nesting_level, void *context, void **return_value) +{ + struct acpi_device_walk_info *info = + ACPI_CAST_PTR(struct acpi_device_walk_info, context); + struct acpi_namespace_node *node; + struct acpi_namespace_node *parent_node; + + /* Keep count of device/processor/thermal objects */ + + node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle); + if ((node->type == ACPI_TYPE_DEVICE) || + (node->type == ACPI_TYPE_PROCESSOR) || + (node->type == ACPI_TYPE_THERMAL)) { + info->device_count++; + return (AE_OK); + } + + /* We are only looking for methods named _INI */ + + if (!ACPI_COMPARE_NAME(node->name.ascii, METHOD_NAME__INI)) { + return (AE_OK); + } + + /* + * The only _INI methods that we care about are those that are + * present under Device, Processor, and Thermal objects. + */ + parent_node = acpi_ns_get_parent_node(node); + switch (parent_node->type) { + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_THERMAL: + + /* Mark parent and bubble up the INI present flag to the root */ + + while (parent_node) { + parent_node->flags |= ANOBJ_SUBTREE_HAS_INI; + parent_node = acpi_ns_get_parent_node(parent_node); + } + break; + + default: + break; + } + + return (AE_OK); +} + /******************************************************************************* * * FUNCTION: acpi_ns_init_one_device @@ -328,64 +399,49 @@ acpi_ns_init_one_device(acpi_handle obj_handle, u32 nesting_level, void *context, void **return_value) { struct acpi_device_walk_info *info = - (struct acpi_device_walk_info *)context; + ACPI_CAST_PTR(struct acpi_device_walk_info, context); struct acpi_parameter_info pinfo; u32 flags; acpi_status status; - struct acpi_namespace_node *ini_node; struct acpi_namespace_node *device_node; - ACPI_FUNCTION_TRACE("ns_init_one_device"); + ACPI_FUNCTION_TRACE(ns_init_one_device); - device_node = acpi_ns_map_handle_to_node(obj_handle); - if (!device_node) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } + /* We are interested in Devices, Processors and thermal_zones only */ - /* - * We will run _STA/_INI on Devices, Processors and thermal_zones only - */ + device_node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle); if ((device_node->type != ACPI_TYPE_DEVICE) && (device_node->type != ACPI_TYPE_PROCESSOR) && (device_node->type != ACPI_TYPE_THERMAL)) { return_ACPI_STATUS(AE_OK); } - if ((acpi_dbg_level <= ACPI_LV_ALL_EXCEPTIONS) && - (!(acpi_dbg_level & ACPI_LV_INFO))) { - ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, ".")); - } - - info->device_count++; - /* - * Check if the _INI method exists for this device - - * if _INI does not exist, there is no need to run _STA - * No _INI means device requires no initialization + * Because of an earlier namespace analysis, all subtrees that contain an + * _INI method are tagged. + * + * If this device subtree does not contain any _INI methods, we + * can exit now and stop traversing this entire subtree. */ - status = acpi_ns_search_node(*ACPI_CAST_PTR(u32, METHOD_NAME__INI), - device_node, ACPI_TYPE_METHOD, &ini_node); - if (ACPI_FAILURE(status)) { - - /* No _INI method found - move on to next device */ - - return_ACPI_STATUS(AE_OK); + if (!(device_node->flags & ANOBJ_SUBTREE_HAS_INI)) { + return_ACPI_STATUS(AE_CTRL_DEPTH); } /* - * Run _STA to determine if we can run _INI on the device - - * the device must be present before _INI can be run. - * However, _STA is not required - assume device present if no _STA + * Run _STA to determine if this device is present and functioning. We + * must know this information for two important reasons (from ACPI spec): + * + * 1) We can only run _INI if the device is present. + * 2) We must abort the device tree walk on this subtree if the device is + * not present and is not functional (we will not examine the children) + * + * The _STA method is not required to be present under the device, we + * assume the device is present if _STA does not exist. */ - ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname(ACPI_TYPE_METHOD, - device_node, - METHOD_NAME__STA)); + ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname + (ACPI_TYPE_METHOD, device_node, METHOD_NAME__STA)); - pinfo.node = device_node; - pinfo.parameters = NULL; - pinfo.parameter_type = ACPI_PARAM_ARGS; - - status = acpi_ut_execute_STA(pinfo.node, &flags); + status = acpi_ut_execute_STA(device_node, &flags); if (ACPI_FAILURE(status)) { /* Ignore error and move on to next device */ @@ -393,55 +449,108 @@ acpi_ns_init_one_device(acpi_handle obj_handle, return_ACPI_STATUS(AE_OK); } + /* + * Flags == -1 means that _STA was not found. In this case, we assume that + * the device is both present and functional. + * + * From the ACPI spec, description of _STA: + * + * "If a device object (including the processor object) does not have an + * _STA object, then OSPM assumes that all of the above bits are set (in + * other words, the device is present, ..., and functioning)" + */ if (flags != ACPI_UINT32_MAX) { info->num_STA++; } + /* + * Examine the PRESENT and FUNCTIONING status bits + * + * Note: ACPI spec does not seem to specify behavior for the present but + * not functioning case, so we assume functioning if present. + */ if (!(flags & ACPI_STA_DEVICE_PRESENT)) { - /* Don't look at children of a not present device */ - - return_ACPI_STATUS(AE_CTRL_DEPTH); + /* Device is not present, we must examine the Functioning bit */ + + if (flags & ACPI_STA_DEVICE_FUNCTIONING) { + /* + * Device is not present but is "functioning". In this case, + * we will not run _INI, but we continue to examine the children + * of this device. + * + * From the ACPI spec, description of _STA: (Note - no mention + * of whether to run _INI or not on the device in question) + * + * "_STA may return bit 0 clear (not present) with bit 3 set + * (device is functional). This case is used to indicate a valid + * device for which no device driver should be loaded (for example, + * a bridge device.) Children of this device may be present and + * valid. OSPM should continue enumeration below a device whose + * _STA returns this bit combination" + */ + return_ACPI_STATUS(AE_OK); + } else { + /* + * Device is not present and is not functioning. We must abort the + * walk of this subtree immediately -- don't look at the children + * of such a device. + * + * From the ACPI spec, description of _INI: + * + * "If the _STA method indicates that the device is not present, + * OSPM will not run the _INI and will not examine the children + * of the device for _INI methods" + */ + return_ACPI_STATUS(AE_CTRL_DEPTH); + } } /* - * The device is present and _INI exists. Run the _INI method. - * (We already have the _INI node from above) + * The device is present or is assumed present if no _STA exists. + * Run the _INI if it exists (not required to exist) + * + * Note: We know there is an _INI within this subtree, but it may not be + * under this particular device, it may be lower in the branch. */ - ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname(ACPI_TYPE_METHOD, - pinfo.node, - METHOD_NAME__INI)); + ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname + (ACPI_TYPE_METHOD, device_node, METHOD_NAME__INI)); - pinfo.node = ini_node; - status = acpi_ns_evaluate_by_handle(&pinfo); - if (ACPI_FAILURE(status)) { - - /* Ignore error and move on to next device */ - -#ifdef ACPI_DEBUG_OUTPUT - char *scope_name = acpi_ns_get_external_pathname(ini_node); + pinfo.node = device_node; + pinfo.parameters = NULL; + pinfo.parameter_type = ACPI_PARAM_ARGS; - ACPI_WARNING((AE_INFO, "%s._INI failed: %s", - scope_name, acpi_format_exception(status))); + status = acpi_ns_evaluate_relative(METHOD_NAME__INI, &pinfo); + if (ACPI_SUCCESS(status)) { - ACPI_FREE(scope_name); -#endif - } else { /* Delete any return object (especially if implicit_return is enabled) */ if (pinfo.return_object) { acpi_ut_remove_reference(pinfo.return_object); } - /* Count of successful INIs */ - info->num_INI++; + if ((acpi_dbg_level <= ACPI_LV_ALL_EXCEPTIONS) && + (!(acpi_dbg_level & ACPI_LV_INFO))) { + ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, ".")); + } } +#ifdef ACPI_DEBUG_OUTPUT + else if (status != AE_NOT_FOUND) { - if (acpi_gbl_init_handler) { + /* Ignore error and move on to next device */ + + char *scope_name = acpi_ns_get_external_pathname(pinfo.node); - /* External initialization handler is present, call it */ + ACPI_EXCEPTION((AE_INFO, status, "during %s._INI execution", + scope_name)); + ACPI_FREE(scope_name); + } +#endif + /* If an external initialization handler is present, call it */ + + if (acpi_gbl_init_handler) { status = acpi_gbl_init_handler(pinfo.node, ACPI_INIT_DEVICE_INI); } diff --git a/drivers/acpi/namespace/nsload.c b/drivers/acpi/namespace/nsload.c index 80acfd35f3e..fe75d888e18 100644 --- a/drivers/acpi/namespace/nsload.c +++ b/drivers/acpi/namespace/nsload.c @@ -77,7 +77,7 @@ acpi_ns_load_table(struct acpi_table_desc *table_desc, { acpi_status status; - ACPI_FUNCTION_TRACE("ns_load_table"); + ACPI_FUNCTION_TRACE(ns_load_table); /* Check if table contains valid AML (must be DSDT, PSDT, SSDT, etc.) */ @@ -169,7 +169,7 @@ static acpi_status acpi_ns_load_table_by_type(acpi_table_type table_type) acpi_status status; struct acpi_table_desc *table_desc; - ACPI_FUNCTION_TRACE("ns_load_table_by_type"); + ACPI_FUNCTION_TRACE(ns_load_table_by_type); status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES); if (ACPI_FAILURE(status)) { @@ -181,11 +181,11 @@ static acpi_status acpi_ns_load_table_by_type(acpi_table_type table_type) * DSDT (one), SSDT/PSDT (multiple) */ switch (table_type) { - case ACPI_TABLE_DSDT: + case ACPI_TABLE_ID_DSDT: ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Namespace load: DSDT\n")); - table_desc = acpi_gbl_table_lists[ACPI_TABLE_DSDT].next; + table_desc = acpi_gbl_table_lists[ACPI_TABLE_ID_DSDT].next; /* If table already loaded into namespace, just return */ @@ -201,8 +201,8 @@ static acpi_status acpi_ns_load_table_by_type(acpi_table_type table_type) } break; - case ACPI_TABLE_SSDT: - case ACPI_TABLE_PSDT: + case ACPI_TABLE_ID_SSDT: + case ACPI_TABLE_ID_PSDT: ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Namespace load: %d SSDT or PSDTs\n", @@ -259,7 +259,7 @@ acpi_status acpi_ns_load_namespace(void) { acpi_status status; - ACPI_FUNCTION_TRACE("acpi_load_name_space"); + ACPI_FUNCTION_TRACE(acpi_load_name_space); /* There must be at least a DSDT installed */ @@ -272,15 +272,15 @@ acpi_status acpi_ns_load_namespace(void) * Load the namespace. The DSDT is required, * but the SSDT and PSDT tables are optional. */ - status = acpi_ns_load_table_by_type(ACPI_TABLE_DSDT); + status = acpi_ns_load_table_by_type(ACPI_TABLE_ID_DSDT); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* Ignore exceptions from these */ - (void)acpi_ns_load_table_by_type(ACPI_TABLE_SSDT); - (void)acpi_ns_load_table_by_type(ACPI_TABLE_PSDT); + (void)acpi_ns_load_table_by_type(ACPI_TABLE_ID_SSDT); + (void)acpi_ns_load_table_by_type(ACPI_TABLE_ID_PSDT); ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, "ACPI Namespace successfully loaded at root %p\n", @@ -315,7 +315,7 @@ static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle) acpi_handle dummy; u32 level; - ACPI_FUNCTION_TRACE("ns_delete_subtree"); + ACPI_FUNCTION_TRACE(ns_delete_subtree); parent_handle = start_handle; child_handle = NULL; @@ -395,7 +395,7 @@ acpi_status acpi_ns_unload_namespace(acpi_handle handle) { acpi_status status; - ACPI_FUNCTION_TRACE("ns_unload_name_space"); + ACPI_FUNCTION_TRACE(ns_unload_name_space); /* Parameter validation */ diff --git a/drivers/acpi/namespace/nsnames.c b/drivers/acpi/namespace/nsnames.c index ba812f43897..97b8332c974 100644 --- a/drivers/acpi/namespace/nsnames.c +++ b/drivers/acpi/namespace/nsnames.c @@ -132,7 +132,7 @@ char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node) char *name_buffer; acpi_size size; - ACPI_FUNCTION_TRACE_PTR("ns_get_external_pathname", node); + ACPI_FUNCTION_TRACE_PTR(ns_get_external_pathname, node); /* Calculate required buffer size based on depth below root */ @@ -213,7 +213,7 @@ acpi_ns_handle_to_pathname(acpi_handle target_handle, struct acpi_namespace_node *node; acpi_size required_size; - ACPI_FUNCTION_TRACE_PTR("ns_handle_to_pathname", target_handle); + ACPI_FUNCTION_TRACE_PTR(ns_handle_to_pathname, target_handle); node = acpi_ns_map_handle_to_node(target_handle); if (!node) { diff --git a/drivers/acpi/namespace/nsobject.c b/drivers/acpi/namespace/nsobject.c index 39dc87b228f..aabe8794b90 100644 --- a/drivers/acpi/namespace/nsobject.c +++ b/drivers/acpi/namespace/nsobject.c @@ -76,7 +76,7 @@ acpi_ns_attach_object(struct acpi_namespace_node *node, union acpi_operand_object *last_obj_desc; acpi_object_type object_type = ACPI_TYPE_ANY; - ACPI_FUNCTION_TRACE("ns_attach_object"); + ACPI_FUNCTION_TRACE(ns_attach_object); /* * Parameter validation @@ -85,7 +85,7 @@ acpi_ns_attach_object(struct acpi_namespace_node *node, /* Invalid handle */ - ACPI_ERROR((AE_INFO, "Null named_obj handle")); + ACPI_ERROR((AE_INFO, "Null NamedObj handle")); return_ACPI_STATUS(AE_BAD_PARAMETER); } @@ -111,7 +111,7 @@ acpi_ns_attach_object(struct acpi_namespace_node *node, if (node->object == object) { ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Obj %p already installed in name_obj %p\n", + "Obj %p already installed in NameObj %p\n", object, node)); return_ACPI_STATUS(AE_OK); @@ -204,7 +204,7 @@ void acpi_ns_detach_object(struct acpi_namespace_node *node) { union acpi_operand_object *obj_desc; - ACPI_FUNCTION_TRACE("ns_detach_object"); + ACPI_FUNCTION_TRACE(ns_detach_object); obj_desc = node->object; @@ -255,7 +255,7 @@ union acpi_operand_object *acpi_ns_get_attached_object(struct acpi_namespace_node *node) { - ACPI_FUNCTION_TRACE_PTR("ns_get_attached_object", node); + ACPI_FUNCTION_TRACE_PTR(ns_get_attached_object, node); if (!node) { ACPI_WARNING((AE_INFO, "Null Node ptr")); @@ -290,7 +290,7 @@ union acpi_operand_object *acpi_ns_get_secondary_object(union acpi_operand_object *obj_desc) { - ACPI_FUNCTION_TRACE_PTR("ns_get_secondary_object", obj_desc); + ACPI_FUNCTION_TRACE_PTR(ns_get_secondary_object, obj_desc); if ((!obj_desc) || (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA) || diff --git a/drivers/acpi/namespace/nsparse.c b/drivers/acpi/namespace/nsparse.c index 64daf3028de..155505a4ef6 100644 --- a/drivers/acpi/namespace/nsparse.c +++ b/drivers/acpi/namespace/nsparse.c @@ -68,7 +68,7 @@ acpi_ns_one_complete_parse(u8 pass_number, struct acpi_table_desc *table_desc) acpi_status status; struct acpi_walk_state *walk_state; - ACPI_FUNCTION_TRACE("ns_one_complete_parse"); + ACPI_FUNCTION_TRACE(ns_one_complete_parse); /* Create and init a Root Node */ @@ -124,7 +124,7 @@ acpi_ns_parse_table(struct acpi_table_desc *table_desc, { acpi_status status; - ACPI_FUNCTION_TRACE("ns_parse_table"); + ACPI_FUNCTION_TRACE(ns_parse_table); /* * AML Parse, pass 1 diff --git a/drivers/acpi/namespace/nssearch.c b/drivers/acpi/namespace/nssearch.c index 51adec5a23d..34ac512a2d5 100644 --- a/drivers/acpi/namespace/nssearch.c +++ b/drivers/acpi/namespace/nssearch.c @@ -89,7 +89,7 @@ acpi_ns_search_node(u32 target_name, { struct acpi_namespace_node *next_node; - ACPI_FUNCTION_TRACE("ns_search_node"); + ACPI_FUNCTION_TRACE(ns_search_node); #ifdef ACPI_DEBUG_OUTPUT if (ACPI_LV_NAMES & acpi_dbg_level) { @@ -203,7 +203,7 @@ acpi_ns_search_parent_tree(u32 target_name, acpi_status status; struct acpi_namespace_node *parent_node; - ACPI_FUNCTION_TRACE("ns_search_parent_tree"); + ACPI_FUNCTION_TRACE(ns_search_parent_tree); parent_node = acpi_ns_get_parent_node(node); @@ -293,13 +293,13 @@ acpi_ns_search_and_enter(u32 target_name, acpi_status status; struct acpi_namespace_node *new_node; - ACPI_FUNCTION_TRACE("ns_search_and_enter"); + ACPI_FUNCTION_TRACE(ns_search_and_enter); /* Parameter validation */ if (!node || !target_name || !return_node) { ACPI_ERROR((AE_INFO, - "Null param: Node %p Name %X return_node %p", + "Null param: Node %p Name %X ReturnNode %p", node, target_name, return_node)); return_ACPI_STATUS(AE_BAD_PARAMETER); } diff --git a/drivers/acpi/namespace/nsutils.c b/drivers/acpi/namespace/nsutils.c index 9fa38ffc2e6..d1d55032b45 100644 --- a/drivers/acpi/namespace/nsutils.c +++ b/drivers/acpi/namespace/nsutils.c @@ -241,7 +241,7 @@ static u8 acpi_ns_valid_path_separator(char sep) acpi_object_type acpi_ns_get_type(struct acpi_namespace_node * node) { - ACPI_FUNCTION_TRACE("ns_get_type"); + ACPI_FUNCTION_TRACE(ns_get_type); if (!node) { ACPI_WARNING((AE_INFO, "Null Node parameter")); @@ -266,7 +266,7 @@ acpi_object_type acpi_ns_get_type(struct acpi_namespace_node * node) u32 acpi_ns_local(acpi_object_type type) { - ACPI_FUNCTION_TRACE("ns_local"); + ACPI_FUNCTION_TRACE(ns_local); if (!acpi_ut_valid_object_type(type)) { @@ -366,7 +366,7 @@ acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info) char *result = NULL; acpi_native_uint i; - ACPI_FUNCTION_TRACE("ns_build_internal_name"); + ACPI_FUNCTION_TRACE(ns_build_internal_name); /* Setup the correct prefixes, counts, and pointers */ @@ -477,7 +477,7 @@ acpi_status acpi_ns_internalize_name(char *external_name, char **converted_name) struct acpi_namestring_info info; acpi_status status; - ACPI_FUNCTION_TRACE("ns_internalize_name"); + ACPI_FUNCTION_TRACE(ns_internalize_name); if ((!external_name) || (*external_name == 0) || (!converted_name)) { return_ACPI_STATUS(AE_BAD_PARAMETER); @@ -537,7 +537,7 @@ acpi_ns_externalize_name(u32 internal_name_length, acpi_native_uint i = 0; acpi_native_uint j = 0; - ACPI_FUNCTION_TRACE("ns_externalize_name"); + ACPI_FUNCTION_TRACE(ns_externalize_name); if (!internal_name_length || !internal_name || !converted_name) { return_ACPI_STATUS(AE_BAD_PARAMETER); @@ -756,7 +756,7 @@ void acpi_ns_terminate(void) { union acpi_operand_object *obj_desc; - ACPI_FUNCTION_TRACE("ns_terminate"); + ACPI_FUNCTION_TRACE(ns_terminate); /* * 1) Free the entire namespace -- all nodes and objects @@ -796,7 +796,7 @@ void acpi_ns_terminate(void) u32 acpi_ns_opens_scope(acpi_object_type type) { - ACPI_FUNCTION_TRACE_STR("ns_opens_scope", acpi_ut_get_type_name(type)); + ACPI_FUNCTION_TRACE_STR(ns_opens_scope, acpi_ut_get_type_name(type)); if (!acpi_ut_valid_object_type(type)) { @@ -840,7 +840,7 @@ acpi_ns_get_node_by_path(char *pathname, acpi_status status; char *internal_path = NULL; - ACPI_FUNCTION_TRACE_PTR("ns_get_node_by_path", pathname); + ACPI_FUNCTION_TRACE_PTR(ns_get_node_by_path, pathname); if (pathname) { @@ -966,7 +966,7 @@ acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node * child_node) { struct acpi_namespace_node *parent_node; - ACPI_FUNCTION_TRACE("ns_find_parent_name"); + ACPI_FUNCTION_TRACE(ns_find_parent_name); if (child_node) { diff --git a/drivers/acpi/namespace/nswalk.c b/drivers/acpi/namespace/nswalk.c index 6bbc734bfee..c8f6bef16ed 100644 --- a/drivers/acpi/namespace/nswalk.c +++ b/drivers/acpi/namespace/nswalk.c @@ -164,7 +164,7 @@ acpi_ns_walk_namespace(acpi_object_type type, acpi_object_type child_type; u32 level; - ACPI_FUNCTION_TRACE("ns_walk_namespace"); + ACPI_FUNCTION_TRACE(ns_walk_namespace); /* Special case for the namespace Root Node */ diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c index 7cdedc96a40..998b29611b1 100644 --- a/drivers/acpi/namespace/nsxfeval.c +++ b/drivers/acpi/namespace/nsxfeval.c @@ -80,7 +80,7 @@ acpi_evaluate_object_typed(acpi_handle handle, acpi_status status; u8 must_free = FALSE; - ACPI_FUNCTION_TRACE("acpi_evaluate_object_typed"); + ACPI_FUNCTION_TRACE(acpi_evaluate_object_typed); /* Return buffer must be valid */ @@ -175,7 +175,7 @@ acpi_evaluate_object(acpi_handle handle, acpi_size buffer_space_needed; u32 i; - ACPI_FUNCTION_TRACE("acpi_evaluate_object"); + ACPI_FUNCTION_TRACE(acpi_evaluate_object); info.node = handle; info.parameters = NULL; @@ -395,7 +395,7 @@ acpi_walk_namespace(acpi_object_type type, { acpi_status status; - ACPI_FUNCTION_TRACE("acpi_walk_namespace"); + ACPI_FUNCTION_TRACE(acpi_walk_namespace); /* Parameter validation */ @@ -553,7 +553,7 @@ acpi_get_devices(char *HID, acpi_status status; struct acpi_get_devices_info info; - ACPI_FUNCTION_TRACE("acpi_get_devices"); + ACPI_FUNCTION_TRACE(acpi_get_devices); /* Parameter validation */ diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 006b31a5655..109c3f8ae7d 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -1042,12 +1042,12 @@ void acpi_os_release_lock(acpi_handle handle, acpi_cpu_flags flags) * * FUNCTION: acpi_os_create_cache * - * PARAMETERS: CacheName - Ascii name for the cache - * ObjectSize - Size of each cached object - * MaxDepth - Maximum depth of the cache (in objects) - * ReturnCache - Where the new cache object is returned + * PARAMETERS: name - Ascii name for the cache + * size - Size of each cached object + * depth - Maximum depth of the cache (in objects) + * cache - Where the new cache object is returned * - * RETURN: Status + * RETURN: status * * DESCRIPTION: Create a cache object * @@ -1057,7 +1057,10 @@ acpi_status acpi_os_create_cache(char *name, u16 size, u16 depth, acpi_cache_t ** cache) { *cache = kmem_cache_create(name, size, 0, 0, NULL, NULL); - return AE_OK; + if (cache == NULL) + return AE_ERROR; + else + return AE_OK; } /******************************************************************************* @@ -1137,4 +1140,52 @@ void *acpi_os_acquire_object(acpi_cache_t * cache) return object; } +/****************************************************************************** + * + * FUNCTION: acpi_os_validate_interface + * + * PARAMETERS: interface - Requested interface to be validated + * + * RETURN: AE_OK if interface is supported, AE_SUPPORT otherwise + * + * DESCRIPTION: Match an interface string to the interfaces supported by the + * host. Strings originate from an AML call to the _OSI method. + * + *****************************************************************************/ + +acpi_status +acpi_os_validate_interface (char *interface) +{ + + return AE_SUPPORT; +} + + +/****************************************************************************** + * + * FUNCTION: acpi_os_validate_address + * + * PARAMETERS: space_id - ACPI space ID + * address - Physical address + * length - Address length + * + * RETURN: AE_OK if address/length is valid for the space_id. Otherwise, + * should return AE_AML_ILLEGAL_ADDRESS. + * + * DESCRIPTION: Validate a system address via the host OS. Used to validate + * the addresses accessed by AML operation regions. + * + *****************************************************************************/ + +acpi_status +acpi_os_validate_address ( + u8 space_id, + acpi_physical_address address, + acpi_size length) +{ + + return AE_OK; +} + + #endif diff --git a/drivers/acpi/parser/psargs.c b/drivers/acpi/parser/psargs.c index 1c5934fe185..bf88e076c3e 100644 --- a/drivers/acpi/parser/psargs.c +++ b/drivers/acpi/parser/psargs.c @@ -79,7 +79,7 @@ acpi_ps_get_next_package_length(struct acpi_parse_state *parser_state) acpi_native_uint byte_count; u8 byte_zero_mask = 0x3F; /* Default [0:5] */ - ACPI_FUNCTION_TRACE("ps_get_next_package_length"); + ACPI_FUNCTION_TRACE(ps_get_next_package_length); /* * Byte 0 bits [6:7] contain the number of additional bytes @@ -128,7 +128,7 @@ u8 *acpi_ps_get_next_package_end(struct acpi_parse_state *parser_state) u8 *start = parser_state->aml; u32 package_length; - ACPI_FUNCTION_TRACE("ps_get_next_package_end"); + ACPI_FUNCTION_TRACE(ps_get_next_package_end); /* Function below updates parser_state->Aml */ @@ -157,7 +157,7 @@ char *acpi_ps_get_next_namestring(struct acpi_parse_state *parser_state) u8 *start = parser_state->aml; u8 *end = parser_state->aml; - ACPI_FUNCTION_TRACE("ps_get_next_namestring"); + ACPI_FUNCTION_TRACE(ps_get_next_namestring); /* Point past any namestring prefix characters (backslash or carat) */ @@ -237,7 +237,7 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state, struct acpi_namespace_node *node; union acpi_generic_state scope_info; - ACPI_FUNCTION_TRACE("ps_get_next_namepath"); + ACPI_FUNCTION_TRACE(ps_get_next_namepath); path = acpi_ps_get_next_namestring(parser_state); acpi_ps_init_op(arg, AML_INT_NAMEPATH_OP); @@ -391,7 +391,7 @@ acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state, u16 opcode; u8 *aml = parser_state->aml; - ACPI_FUNCTION_TRACE_U32("ps_get_next_simple_arg", arg_type); + ACPI_FUNCTION_TRACE_U32(ps_get_next_simple_arg, arg_type); switch (arg_type) { case ARGP_BYTEDATA: @@ -456,7 +456,7 @@ acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state, default: - ACPI_ERROR((AE_INFO, "Invalid arg_type %X", arg_type)); + ACPI_ERROR((AE_INFO, "Invalid ArgType %X", arg_type)); return_VOID; } @@ -487,7 +487,7 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state u16 opcode; u32 name; - ACPI_FUNCTION_TRACE("ps_get_next_field"); + ACPI_FUNCTION_TRACE(ps_get_next_field); /* Determine field type */ @@ -593,7 +593,7 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state, u32 subop; acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE_PTR("ps_get_next_arg", parser_state); + ACPI_FUNCTION_TRACE_PTR(ps_get_next_arg, parser_state); switch (arg_type) { case ARGP_BYTEDATA: @@ -718,7 +718,7 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state, default: - ACPI_ERROR((AE_INFO, "Invalid arg_type: %X", arg_type)); + ACPI_ERROR((AE_INFO, "Invalid ArgType: %X", arg_type)); status = AE_AML_OPERAND_TYPE; break; } diff --git a/drivers/acpi/parser/psloop.c b/drivers/acpi/parser/psloop.c index 3a29ce68037..e1541db3753 100644 --- a/drivers/acpi/parser/psloop.c +++ b/drivers/acpi/parser/psloop.c @@ -83,7 +83,7 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) struct acpi_parse_state *parser_state; u8 *aml_op_start = NULL; - ACPI_FUNCTION_TRACE_PTR("ps_parse_loop", walk_state); + ACPI_FUNCTION_TRACE_PTR(ps_parse_loop, walk_state); if (walk_state->descending_callback == NULL) { return_ACPI_STATUS(AE_BAD_PARAMETER); @@ -129,7 +129,7 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) } ACPI_EXCEPTION((AE_INFO, status, - "get_predicate Failed")); + "GetPredicate Failed")); return_ACPI_STATUS(status); } @@ -375,7 +375,7 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) if (walk_state->op_info) { ACPI_DEBUG_PRINT((ACPI_DB_PARSE, - "Opcode %4.4X [%s] Op %p Aml %p aml_offset %5.5X\n", + "Opcode %4.4X [%s] Op %p Aml %p AmlOffset %5.5X\n", (u32) op->common.aml_opcode, walk_state->op_info->name, op, parser_state->aml, diff --git a/drivers/acpi/parser/psopcode.c b/drivers/acpi/parser/psopcode.c index 9eb8d066388..4bd25e32769 100644 --- a/drivers/acpi/parser/psopcode.c +++ b/drivers/acpi/parser/psopcode.c @@ -725,7 +725,7 @@ static const u8 acpi_gbl_long_op_index[NUM_EXTENDED_OPCODE] = { const struct acpi_opcode_info *acpi_ps_get_opcode_info(u16 opcode) { - ACPI_FUNCTION_NAME("ps_get_opcode_info"); + ACPI_FUNCTION_NAME(ps_get_opcode_info); /* * Detect normal 8-bit opcode or extended 16-bit opcode @@ -781,7 +781,7 @@ char *acpi_ps_get_opcode_name(u16 opcode) return (op->name); #else - return ("AE_NOT_CONFIGURED"); + return ("OpcodeName unavailable"); #endif } diff --git a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c index 83d8916bc1a..796f6b71992 100644 --- a/drivers/acpi/parser/psparse.c +++ b/drivers/acpi/parser/psparse.c @@ -138,7 +138,7 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state, const struct acpi_opcode_info *parent_info; union acpi_parse_object *replacement_op = NULL; - ACPI_FUNCTION_TRACE_PTR("ps_complete_this_op", op); + ACPI_FUNCTION_TRACE_PTR(ps_complete_this_op, op); /* Check for null Op, can happen if AML code is corrupt */ @@ -333,7 +333,7 @@ acpi_ps_next_parse_state(struct acpi_walk_state *walk_state, struct acpi_parse_state *parser_state = &walk_state->parser_state; acpi_status status = AE_CTRL_PENDING; - ACPI_FUNCTION_TRACE_PTR("ps_next_parse_state", op); + ACPI_FUNCTION_TRACE_PTR(ps_next_parse_state, op); switch (callback_status) { case AE_CTRL_TERMINATE: @@ -453,10 +453,10 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state) struct acpi_thread_state *prev_walk_list = acpi_gbl_current_walk_list; struct acpi_walk_state *previous_walk_state; - ACPI_FUNCTION_TRACE("ps_parse_aml"); + ACPI_FUNCTION_TRACE(ps_parse_aml); ACPI_DEBUG_PRINT((ACPI_DB_PARSE, - "Entered with walk_state=%p Aml=%p size=%X\n", + "Entered with WalkState=%p Aml=%p size=%X\n", walk_state, walk_state->parser_state.aml, walk_state->parser_state.aml_size)); @@ -555,21 +555,9 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state) */ if (((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) == ACPI_PARSE_EXECUTE) || (ACPI_FAILURE(status))) { - if (walk_state->method_desc) { - - /* Decrement the thread count on the method parse tree */ - - if (walk_state->method_desc->method. - thread_count) { - walk_state->method_desc->method. - thread_count--; - } else { - ACPI_ERROR((AE_INFO, - "Invalid zero thread count in method")); - } - } - - acpi_ds_terminate_control_method(walk_state); + acpi_ds_terminate_control_method(walk_state-> + method_desc, + walk_state); } /* Delete this walk state and all linked control states */ @@ -578,7 +566,7 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state) previous_walk_state = walk_state; ACPI_DEBUG_PRINT((ACPI_DB_PARSE, - "return_value=%p, implicit_value=%p State=%p\n", + "ReturnValue=%p, ImplicitValue=%p State=%p\n", walk_state->return_desc, walk_state->implicit_return_obj, walk_state)); diff --git a/drivers/acpi/parser/psscope.c b/drivers/acpi/parser/psscope.c index 424ab1c20da..a3e0314de24 100644 --- a/drivers/acpi/parser/psscope.c +++ b/drivers/acpi/parser/psscope.c @@ -106,7 +106,7 @@ acpi_ps_init_scope(struct acpi_parse_state * parser_state, { union acpi_generic_state *scope; - ACPI_FUNCTION_TRACE_PTR("ps_init_scope", root_op); + ACPI_FUNCTION_TRACE_PTR(ps_init_scope, root_op); scope = acpi_ut_create_generic_state(); if (!scope) { @@ -147,7 +147,7 @@ acpi_ps_push_scope(struct acpi_parse_state *parser_state, { union acpi_generic_state *scope; - ACPI_FUNCTION_TRACE_PTR("ps_push_scope", op); + ACPI_FUNCTION_TRACE_PTR(ps_push_scope, op); scope = acpi_ut_create_generic_state(); if (!scope) { @@ -200,7 +200,7 @@ acpi_ps_pop_scope(struct acpi_parse_state *parser_state, { union acpi_generic_state *scope = parser_state->scope; - ACPI_FUNCTION_TRACE("ps_pop_scope"); + ACPI_FUNCTION_TRACE(ps_pop_scope); /* Only pop the scope if there is in fact a next scope */ @@ -247,7 +247,7 @@ void acpi_ps_cleanup_scope(struct acpi_parse_state *parser_state) { union acpi_generic_state *scope; - ACPI_FUNCTION_TRACE_PTR("ps_cleanup_scope", parser_state); + ACPI_FUNCTION_TRACE_PTR(ps_cleanup_scope, parser_state); if (!parser_state) { return_VOID; diff --git a/drivers/acpi/parser/psutils.c b/drivers/acpi/parser/psutils.c index 43e3190583e..182474ae8ce 100644 --- a/drivers/acpi/parser/psutils.c +++ b/drivers/acpi/parser/psutils.c @@ -172,7 +172,7 @@ union acpi_parse_object *acpi_ps_alloc_op(u16 opcode) void acpi_ps_free_op(union acpi_parse_object *op) { - ACPI_FUNCTION_NAME("ps_free_op"); + ACPI_FUNCTION_NAME(ps_free_op); if (op->common.aml_opcode == AML_INT_RETURN_VALUE_OP) { ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Free retval op: %p\n", diff --git a/drivers/acpi/parser/pswalk.c b/drivers/acpi/parser/pswalk.c index 3d08b8c6db4..a84a547a0f1 100644 --- a/drivers/acpi/parser/pswalk.c +++ b/drivers/acpi/parser/pswalk.c @@ -64,7 +64,7 @@ void acpi_ps_delete_parse_tree(union acpi_parse_object *subtree_root) union acpi_parse_object *next = NULL; union acpi_parse_object *parent = NULL; - ACPI_FUNCTION_TRACE_PTR("ps_delete_parse_tree", subtree_root); + ACPI_FUNCTION_TRACE_PTR(ps_delete_parse_tree, subtree_root); /* Visit all nodes in the subtree */ diff --git a/drivers/acpi/parser/psxface.c b/drivers/acpi/parser/psxface.c index e09a820ee29..6b1411f1087 100644 --- a/drivers/acpi/parser/psxface.c +++ b/drivers/acpi/parser/psxface.c @@ -216,7 +216,7 @@ acpi_status acpi_ps_execute_method(struct acpi_parameter_info *info) { acpi_status status; - ACPI_FUNCTION_TRACE("ps_execute_method"); + ACPI_FUNCTION_TRACE(ps_execute_method); /* Validate the Info and method Node */ @@ -286,8 +286,7 @@ acpi_status acpi_ps_execute_method(struct acpi_parameter_info *info) * a control exception code */ if (info->return_object) { - ACPI_DEBUG_PRINT((ACPI_DB_PARSE, - "Method returned obj_desc=%p\n", + ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Method returned ObjDesc=%p\n", info->return_object)); ACPI_DUMP_STACK_ENTRY(info->return_object); @@ -350,7 +349,7 @@ static acpi_status acpi_ps_execute_pass(struct acpi_parameter_info *info) union acpi_parse_object *op; struct acpi_walk_state *walk_state; - ACPI_FUNCTION_TRACE("ps_execute_pass"); + ACPI_FUNCTION_TRACE(ps_execute_pass); /* Create and init a Root Node */ diff --git a/drivers/acpi/resources/rscalc.c b/drivers/acpi/resources/rscalc.c index dd5caa2c8fd..a573ad5d41d 100644 --- a/drivers/acpi/resources/rscalc.c +++ b/drivers/acpi/resources/rscalc.c @@ -190,7 +190,7 @@ acpi_rs_get_aml_length(struct acpi_resource * resource, acpi_size * size_needed) acpi_size aml_size_needed = 0; acpi_rs_length total_size; - ACPI_FUNCTION_TRACE("rs_get_aml_length"); + ACPI_FUNCTION_TRACE(rs_get_aml_length); /* Traverse entire list of internal resource descriptors */ @@ -345,7 +345,7 @@ acpi_rs_get_list_length(u8 * aml_buffer, u8 resource_index; u8 minimum_aml_resource_length; - ACPI_FUNCTION_TRACE("rs_get_list_length"); + ACPI_FUNCTION_TRACE(rs_get_list_length); *size_needed = 0; end_aml = aml_buffer + aml_buffer_length; @@ -456,7 +456,7 @@ acpi_rs_get_list_length(u8 * aml_buffer, *size_needed += buffer_size; ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, - "Type %.2X, aml_length %.2X internal_length %.2X\n", + "Type %.2X, AmlLength %.2X InternalLength %.2X\n", acpi_ut_get_resource_type(aml_buffer), acpi_ut_get_descriptor_length(aml_buffer), buffer_size)); @@ -503,7 +503,7 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object, u8 name_found; u32 table_index; - ACPI_FUNCTION_TRACE("rs_get_pci_routing_table_length"); + ACPI_FUNCTION_TRACE(rs_get_pci_routing_table_length); number_of_elements = package_object->package.count; diff --git a/drivers/acpi/resources/rscreate.c b/drivers/acpi/resources/rscreate.c index 01488cfc9ba..4c322daaf88 100644 --- a/drivers/acpi/resources/rscreate.c +++ b/drivers/acpi/resources/rscreate.c @@ -77,9 +77,9 @@ acpi_rs_create_resource_list(union acpi_operand_object *aml_buffer, u32 aml_buffer_length; void *resource; - ACPI_FUNCTION_TRACE("rs_create_resource_list"); + ACPI_FUNCTION_TRACE(rs_create_resource_list); - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "aml_buffer = %p\n", aml_buffer)); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "AmlBuffer = %p\n", aml_buffer)); /* Params already validated, so we don't re-validate here */ @@ -93,7 +93,7 @@ acpi_rs_create_resource_list(union acpi_operand_object *aml_buffer, status = acpi_rs_get_list_length(aml_start, aml_buffer_length, &list_size_needed); - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Status=%X list_size_needed=%X\n", + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Status=%X ListSizeNeeded=%X\n", status, (u32) list_size_needed)); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); @@ -116,7 +116,7 @@ acpi_rs_create_resource_list(union acpi_operand_object *aml_buffer, return_ACPI_STATUS(status); } - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "output_buffer %p Length %X\n", + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "OutputBuffer %p Length %X\n", output_buffer->pointer, (u32) output_buffer->length)); return_ACPI_STATUS(AE_OK); } @@ -158,7 +158,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, acpi_status status; struct acpi_buffer path_buffer; - ACPI_FUNCTION_TRACE("rs_create_pci_routing_table"); + ACPI_FUNCTION_TRACE(rs_create_pci_routing_table); /* Params already validated, so we don't re-validate here */ @@ -170,7 +170,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, return_ACPI_STATUS(status); } - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "buffer_size_needed = %X\n", + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "BufferSizeNeeded = %X\n", (u32) buffer_size_needed)); /* Validate/Allocate/Clear caller buffer */ @@ -344,7 +344,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, user_prt->source_index = (u32) obj_desc->integer.value; } else { ACPI_ERROR((AE_INFO, - "(PRT[%X].source_index) Need Integer, found %s", + "(PRT[%X].SourceIndex) Need Integer, found %s", index, acpi_ut_get_object_type_name(obj_desc))); return_ACPI_STATUS(AE_BAD_DATA); @@ -355,7 +355,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, top_object_list++; } - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "output_buffer %p Length %X\n", + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "OutputBuffer %p Length %X\n", output_buffer->pointer, (u32) output_buffer->length)); return_ACPI_STATUS(AE_OK); } @@ -385,9 +385,9 @@ acpi_rs_create_aml_resources(struct acpi_resource *linked_list_buffer, acpi_status status; acpi_size aml_size_needed = 0; - ACPI_FUNCTION_TRACE("rs_create_aml_resources"); + ACPI_FUNCTION_TRACE(rs_create_aml_resources); - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "linked_list_buffer = %p\n", + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "LinkedListBuffer = %p\n", linked_list_buffer)); /* @@ -398,7 +398,7 @@ acpi_rs_create_aml_resources(struct acpi_resource *linked_list_buffer, */ status = acpi_rs_get_aml_length(linked_list_buffer, &aml_size_needed); - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "aml_size_needed=%X, %s\n", + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "AmlSizeNeeded=%X, %s\n", (u32) aml_size_needed, acpi_format_exception(status))); if (ACPI_FAILURE(status)) { @@ -422,7 +422,7 @@ acpi_rs_create_aml_resources(struct acpi_resource *linked_list_buffer, return_ACPI_STATUS(status); } - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "output_buffer %p Length %X\n", + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "OutputBuffer %p Length %X\n", output_buffer->pointer, (u32) output_buffer->length)); return_ACPI_STATUS(AE_OK); } diff --git a/drivers/acpi/resources/rsdump.c b/drivers/acpi/resources/rsdump.c index e7de061cf88..9c99a723a86 100644 --- a/drivers/acpi/resources/rsdump.c +++ b/drivers/acpi/resources/rsdump.c @@ -91,11 +91,11 @@ acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table); struct acpi_rsdump_info acpi_rs_dump_irq[6] = { {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_irq), "IRQ", NULL}, {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.triggering), "Triggering", - acpi_gbl_HEdecode}, + acpi_gbl_he_decode}, {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.polarity), "Polarity", - acpi_gbl_LLdecode}, + acpi_gbl_ll_decode}, {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.sharable), "Sharing", - acpi_gbl_SHRdecode}, + acpi_gbl_shr_decode}, {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(irq.interrupt_count), "Interrupt Count", NULL}, {ACPI_RSD_SHORTLIST, ACPI_RSD_OFFSET(irq.interrupts[0]), @@ -105,11 +105,11 @@ struct acpi_rsdump_info acpi_rs_dump_irq[6] = { struct acpi_rsdump_info acpi_rs_dump_dma[6] = { {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_dma), "DMA", NULL}, {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(dma.type), "Speed", - acpi_gbl_TYPdecode}, + acpi_gbl_typ_decode}, {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(dma.bus_master), "Mastering", - acpi_gbl_BMdecode}, + acpi_gbl_bm_decode}, {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(dma.transfer), "Transfer Type", - acpi_gbl_SIZdecode}, + acpi_gbl_siz_decode}, {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(dma.channel_count), "Channel Count", NULL}, {ACPI_RSD_SHORTLIST, ACPI_RSD_OFFSET(dma.channels[0]), "Channel List", @@ -158,7 +158,7 @@ struct acpi_rsdump_info acpi_rs_dump_vendor[3] = { }; struct acpi_rsdump_info acpi_rs_dump_end_tag[1] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_end_tag), "end_tag", + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_end_tag), "EndTag", NULL} }; @@ -166,7 +166,7 @@ struct acpi_rsdump_info acpi_rs_dump_memory24[6] = { {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory24), "24-Bit Memory Range", NULL}, {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(memory24.write_protect), - "Write Protect", acpi_gbl_RWdecode}, + "Write Protect", acpi_gbl_rw_decode}, {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.minimum), "Address Minimum", NULL}, {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.maximum), "Address Maximum", @@ -181,7 +181,7 @@ struct acpi_rsdump_info acpi_rs_dump_memory32[6] = { {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory32), "32-Bit Memory Range", NULL}, {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(memory32.write_protect), - "Write Protect", acpi_gbl_RWdecode}, + "Write Protect", acpi_gbl_rw_decode}, {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.minimum), "Address Minimum", NULL}, {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.maximum), "Address Maximum", @@ -196,7 +196,7 @@ struct acpi_rsdump_info acpi_rs_dump_fixed_memory32[4] = { {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_fixed_memory32), "32-Bit Fixed Memory Range", NULL}, {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(fixed_memory32.write_protect), - "Write Protect", acpi_gbl_RWdecode}, + "Write Protect", acpi_gbl_rw_decode}, {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(fixed_memory32.address), "Address", NULL}, {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(fixed_memory32.address_length), @@ -278,11 +278,11 @@ struct acpi_rsdump_info acpi_rs_dump_ext_irq[8] = { {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.producer_consumer), "Type", acpi_gbl_consume_decode}, {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.triggering), - "Triggering", acpi_gbl_HEdecode}, + "Triggering", acpi_gbl_he_decode}, {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.polarity), "Polarity", - acpi_gbl_LLdecode}, + acpi_gbl_ll_decode}, {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.sharable), "Sharing", - acpi_gbl_SHRdecode}, + acpi_gbl_shr_decode}, {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(extended_irq.resource_source), NULL, NULL}, {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(extended_irq.interrupt_count), @@ -314,7 +314,7 @@ static struct acpi_rsdump_info acpi_rs_dump_general_flags[5] = { {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.producer_consumer), "Consumer/Producer", acpi_gbl_consume_decode}, {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.decode), "Address Decode", - acpi_gbl_DECdecode}, + acpi_gbl_dec_decode}, {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.min_address_fixed), "Min Relocatability", acpi_gbl_min_decode}, {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.max_address_fixed), @@ -325,24 +325,24 @@ static struct acpi_rsdump_info acpi_rs_dump_memory_flags[5] = { {ACPI_RSD_LITERAL, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory_flags), "Resource Type", (void *)"Memory Range"}, {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.mem.write_protect), - "Write Protect", acpi_gbl_RWdecode}, + "Write Protect", acpi_gbl_rw_decode}, {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.mem.caching), - "Caching", acpi_gbl_MEMdecode}, + "Caching", acpi_gbl_mem_decode}, {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.mem.range_type), - "Range Type", acpi_gbl_MTPdecode}, + "Range Type", acpi_gbl_mtp_decode}, {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.mem.translation), - "Translation", acpi_gbl_TTPdecode} + "Translation", acpi_gbl_ttp_decode} }; static struct acpi_rsdump_info acpi_rs_dump_io_flags[4] = { {ACPI_RSD_LITERAL, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_io_flags), "Resource Type", (void *)"I/O Range"}, {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.io.range_type), - "Range Type", acpi_gbl_RNGdecode}, + "Range Type", acpi_gbl_rng_decode}, {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.io.translation), - "Translation", acpi_gbl_TTPdecode}, + "Translation", acpi_gbl_ttp_decode}, {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.io.translation_type), - "Translation Type", acpi_gbl_TRSdecode} + "Translation Type", acpi_gbl_trs_decode} }; /* diff --git a/drivers/acpi/resources/rslist.c b/drivers/acpi/resources/rslist.c index 1b2d1e717e7..29423ce030c 100644 --- a/drivers/acpi/resources/rslist.c +++ b/drivers/acpi/resources/rslist.c @@ -71,7 +71,7 @@ acpi_rs_convert_aml_to_resources(u8 * aml, struct acpi_resource *resource; acpi_status status; - ACPI_FUNCTION_TRACE("rs_convert_aml_to_resources"); + ACPI_FUNCTION_TRACE(rs_convert_aml_to_resources); /* * Check that the input buffer and all subsequent pointers into it @@ -99,7 +99,7 @@ acpi_rs_convert_aml_to_resources(u8 * aml, } ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, - "Type %.2X, aml_length %.2X internal_length %.2X\n", + "Type %.2X, AmlLength %.2X InternalLength %.2X\n", acpi_ut_get_resource_type(aml), length, resource->length)); @@ -136,7 +136,7 @@ acpi_rs_convert_resources_to_aml(struct acpi_resource *resource, u8 *end_aml = output_buffer + aml_size_needed; acpi_status status; - ACPI_FUNCTION_TRACE("rs_convert_resources_to_aml"); + ACPI_FUNCTION_TRACE(rs_convert_resources_to_aml); /* Walk the resource descriptor list, convert each descriptor */ diff --git a/drivers/acpi/resources/rsmisc.c b/drivers/acpi/resources/rsmisc.c index 6a731f4028d..faf6e106b78 100644 --- a/drivers/acpi/resources/rsmisc.c +++ b/drivers/acpi/resources/rsmisc.c @@ -81,7 +81,7 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, u16 item_count = 0; u16 temp16 = 0; - ACPI_FUNCTION_TRACE("rs_convert_aml_to_resource"); + ACPI_FUNCTION_TRACE(rs_convert_aml_to_resource); if (((acpi_native_uint) resource) & 0x3) { @@ -332,7 +332,7 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, u16 temp16 = 0; u16 item_count = 0; - ACPI_FUNCTION_TRACE("rs_convert_resource_to_aml"); + ACPI_FUNCTION_TRACE(rs_convert_resource_to_aml); /* * First table entry must be ACPI_RSC_INITxxx and must contain the diff --git a/drivers/acpi/resources/rsutils.c b/drivers/acpi/resources/rsutils.c index 9bcf0b637d2..aa98eebc9b7 100644 --- a/drivers/acpi/resources/rsutils.c +++ b/drivers/acpi/resources/rsutils.c @@ -461,7 +461,7 @@ acpi_rs_get_prt_method_data(acpi_handle handle, struct acpi_buffer * ret_buffer) union acpi_operand_object *obj_desc; acpi_status status; - ACPI_FUNCTION_TRACE("rs_get_prt_method_data"); + ACPI_FUNCTION_TRACE(rs_get_prt_method_data); /* Parameters guaranteed valid by caller */ @@ -509,7 +509,7 @@ acpi_rs_get_crs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer) union acpi_operand_object *obj_desc; acpi_status status; - ACPI_FUNCTION_TRACE("rs_get_crs_method_data"); + ACPI_FUNCTION_TRACE(rs_get_crs_method_data); /* Parameters guaranteed valid by caller */ @@ -559,7 +559,7 @@ acpi_rs_get_prs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer) union acpi_operand_object *obj_desc; acpi_status status; - ACPI_FUNCTION_TRACE("rs_get_prs_method_data"); + ACPI_FUNCTION_TRACE(rs_get_prs_method_data); /* Parameters guaranteed valid by caller */ @@ -611,7 +611,7 @@ acpi_rs_get_method_data(acpi_handle handle, union acpi_operand_object *obj_desc; acpi_status status; - ACPI_FUNCTION_TRACE("rs_get_method_data"); + ACPI_FUNCTION_TRACE(rs_get_method_data); /* Parameters guaranteed valid by caller */ @@ -662,7 +662,7 @@ acpi_rs_set_srs_method_data(acpi_handle handle, struct acpi_buffer *in_buffer) acpi_status status; struct acpi_buffer buffer; - ACPI_FUNCTION_TRACE("rs_set_srs_method_data"); + ACPI_FUNCTION_TRACE(rs_set_srs_method_data); /* Parameters guaranteed valid by caller */ diff --git a/drivers/acpi/resources/rsxface.c b/drivers/acpi/resources/rsxface.c index 1d00d285a5a..8c1628c12cc 100644 --- a/drivers/acpi/resources/rsxface.c +++ b/drivers/acpi/resources/rsxface.c @@ -95,7 +95,7 @@ acpi_get_irq_routing_table(acpi_handle device_handle, { acpi_status status; - ACPI_FUNCTION_TRACE("acpi_get_irq_routing_table "); + ACPI_FUNCTION_TRACE(acpi_get_irq_routing_table); /* * Must have a valid handle and buffer, So we have to have a handle @@ -147,7 +147,7 @@ acpi_get_current_resources(acpi_handle device_handle, { acpi_status status; - ACPI_FUNCTION_TRACE("acpi_get_current_resources"); + ACPI_FUNCTION_TRACE(acpi_get_current_resources); /* * Must have a valid handle and buffer, So we have to have a handle @@ -197,7 +197,7 @@ acpi_get_possible_resources(acpi_handle device_handle, { acpi_status status; - ACPI_FUNCTION_TRACE("acpi_get_possible_resources"); + ACPI_FUNCTION_TRACE(acpi_get_possible_resources); /* * Must have a valid handle and buffer, So we have to have a handle @@ -249,13 +249,13 @@ acpi_walk_resources(acpi_handle device_handle, struct acpi_resource *resource; struct acpi_resource *resource_end; - ACPI_FUNCTION_TRACE("acpi_walk_resources"); + ACPI_FUNCTION_TRACE(acpi_walk_resources); /* Parameter validation */ if (!device_handle || !user_function || !name || - (ACPI_STRNCMP(name, METHOD_NAME__CRS, sizeof(METHOD_NAME__CRS)) && - ACPI_STRNCMP(name, METHOD_NAME__PRS, sizeof(METHOD_NAME__PRS)))) { + (!ACPI_COMPARE_NAME(name, METHOD_NAME__CRS) && + !ACPI_COMPARE_NAME(name, METHOD_NAME__PRS))) { return_ACPI_STATUS(AE_BAD_PARAMETER); } @@ -339,7 +339,7 @@ acpi_set_current_resources(acpi_handle device_handle, { acpi_status status; - ACPI_FUNCTION_TRACE("acpi_set_current_resources"); + ACPI_FUNCTION_TRACE(acpi_set_current_resources); /* Must have a valid handle and buffer */ diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c index 1943bec1884..a934ac42178 100644 --- a/drivers/acpi/system.c +++ b/drivers/acpi/system.c @@ -82,7 +82,7 @@ acpi_system_read_dsdt(struct file *file, ACPI_FUNCTION_TRACE("acpi_system_read_dsdt"); - status = acpi_get_table(ACPI_TABLE_DSDT, 1, &dsdt); + status = acpi_get_table(ACPI_TABLE_ID_DSDT, 1, &dsdt); if (ACPI_FAILURE(status)) return_VALUE(-ENODEV); @@ -110,7 +110,7 @@ acpi_system_read_fadt(struct file *file, ACPI_FUNCTION_TRACE("acpi_system_read_fadt"); - status = acpi_get_table(ACPI_TABLE_FADT, 1, &fadt); + status = acpi_get_table(ACPI_TABLE_ID_FADT, 1, &fadt); if (ACPI_FAILURE(status)) return_VALUE(-ENODEV); diff --git a/drivers/acpi/tables/tbconvrt.c b/drivers/acpi/tables/tbconvrt.c index a913a927d32..d697fcb35d5 100644 --- a/drivers/acpi/tables/tbconvrt.c +++ b/drivers/acpi/tables/tbconvrt.c @@ -492,7 +492,7 @@ acpi_status acpi_tb_convert_table_fadt(void) struct fadt_descriptor *local_fadt; struct acpi_table_desc *table_desc; - ACPI_FUNCTION_TRACE("tb_convert_table_fadt"); + ACPI_FUNCTION_TRACE(tb_convert_table_fadt); /* * acpi_gbl_FADT is valid. Validate the FADT length. The table must be @@ -541,7 +541,7 @@ acpi_status acpi_tb_convert_table_fadt(void) /* Free the original table */ - table_desc = acpi_gbl_table_lists[ACPI_TABLE_FADT].next; + table_desc = acpi_gbl_table_lists[ACPI_TABLE_ID_FADT].next; acpi_tb_delete_single_table(table_desc); /* Install the new table */ @@ -579,7 +579,7 @@ acpi_status acpi_tb_convert_table_fadt(void) acpi_status acpi_tb_build_common_facs(struct acpi_table_desc *table_info) { - ACPI_FUNCTION_TRACE("tb_build_common_facs"); + ACPI_FUNCTION_TRACE(tb_build_common_facs); /* Absolute minimum length is 24, but the ACPI spec says 64 */ diff --git a/drivers/acpi/tables/tbget.c b/drivers/acpi/tables/tbget.c index b7bd20b9a75..3a4f46ca388 100644 --- a/drivers/acpi/tables/tbget.c +++ b/drivers/acpi/tables/tbget.c @@ -78,7 +78,7 @@ acpi_tb_get_table(struct acpi_pointer *address, acpi_status status; struct acpi_table_header header; - ACPI_FUNCTION_TRACE("tb_get_table"); + ACPI_FUNCTION_TRACE(tb_get_table); /* Get the header in order to get signature and table size */ @@ -124,7 +124,7 @@ acpi_tb_get_table_header(struct acpi_pointer *address, acpi_status status = AE_OK; struct acpi_table_header *header = NULL; - ACPI_FUNCTION_TRACE("tb_get_table_header"); + ACPI_FUNCTION_TRACE(tb_get_table_header); /* * Flags contains the current processor mode (Virtual or Physical @@ -202,7 +202,7 @@ acpi_tb_get_table_body(struct acpi_pointer *address, { acpi_status status; - ACPI_FUNCTION_TRACE("tb_get_table_body"); + ACPI_FUNCTION_TRACE(tb_get_table_body); if (!table_info || !address) { return_ACPI_STATUS(AE_BAD_PARAMETER); @@ -246,7 +246,7 @@ acpi_tb_table_override(struct acpi_table_header *header, acpi_status status; struct acpi_pointer address; - ACPI_FUNCTION_TRACE("tb_table_override"); + ACPI_FUNCTION_TRACE(tb_table_override); /* * The OSL will examine the header and decide whether to override this @@ -318,7 +318,7 @@ acpi_tb_get_this_table(struct acpi_pointer *address, u8 allocation; acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("tb_get_this_table"); + ACPI_FUNCTION_TRACE(tb_get_this_table); /* * Flags contains the current processor mode (Virtual or Physical @@ -383,7 +383,7 @@ acpi_tb_get_this_table(struct acpi_pointer *address, * Validate checksum for _most_ tables, * even the ones whose signature we don't recognize */ - if (table_info->type != ACPI_TABLE_FACS) { + if (table_info->type != ACPI_TABLE_ID_FACS) { status = acpi_tb_verify_table_checksum(full_table); #if (!ACPI_CHECKSUM_ABORT) @@ -433,13 +433,13 @@ acpi_tb_get_table_ptr(acpi_table_type table_type, struct acpi_table_desc *table_desc; u32 i; - ACPI_FUNCTION_TRACE("tb_get_table_ptr"); + ACPI_FUNCTION_TRACE(tb_get_table_ptr); if (!acpi_gbl_DSDT) { return_ACPI_STATUS(AE_NO_ACPI_TABLES); } - if (table_type > ACPI_TABLE_MAX) { + if (table_type > ACPI_TABLE_ID_MAX) { return_ACPI_STATUS(AE_BAD_PARAMETER); } diff --git a/drivers/acpi/tables/tbgetall.c b/drivers/acpi/tables/tbgetall.c index b4ec61d7cf0..ad982112e4c 100644 --- a/drivers/acpi/tables/tbgetall.c +++ b/drivers/acpi/tables/tbgetall.c @@ -77,7 +77,7 @@ acpi_tb_get_primary_table(struct acpi_pointer *address, acpi_status status; struct acpi_table_header header; - ACPI_FUNCTION_TRACE("tb_get_primary_table"); + ACPI_FUNCTION_TRACE(tb_get_primary_table); /* Ignore a NULL address in the RSDT */ @@ -140,7 +140,7 @@ acpi_tb_get_secondary_table(struct acpi_pointer *address, acpi_status status; struct acpi_table_header header; - ACPI_FUNCTION_TRACE_STR("tb_get_secondary_table", signature); + ACPI_FUNCTION_TRACE_STR(tb_get_secondary_table, signature); /* Get the header in order to match the signature */ @@ -151,7 +151,7 @@ acpi_tb_get_secondary_table(struct acpi_pointer *address, /* Signature must match request */ - if (ACPI_STRNCMP(header.signature, signature, ACPI_NAME_SIZE)) { + if (!ACPI_COMPARE_NAME(header.signature, signature)) { ACPI_ERROR((AE_INFO, "Incorrect table signature - wanted [%s] found [%4.4s]", signature, header.signature)); @@ -207,7 +207,7 @@ acpi_status acpi_tb_get_required_tables(void) struct acpi_table_desc table_info; struct acpi_pointer address; - ACPI_FUNCTION_TRACE("tb_get_required_tables"); + ACPI_FUNCTION_TRACE(tb_get_required_tables); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%d ACPI tables in RSDT\n", acpi_gbl_rsdt_table_count)); @@ -306,6 +306,6 @@ acpi_status acpi_tb_get_required_tables(void) /* Always delete the RSDP mapping, we are done with it */ - acpi_tb_delete_tables_by_type(ACPI_TABLE_RSDP); + acpi_tb_delete_tables_by_type(ACPI_TABLE_ID_RSDP); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c index ce57a195577..7ca2df75bb1 100644 --- a/drivers/acpi/tables/tbinstal.c +++ b/drivers/acpi/tables/tbinstal.c @@ -73,11 +73,11 @@ acpi_tb_match_signature(char *signature, { acpi_native_uint i; - ACPI_FUNCTION_TRACE("tb_match_signature"); + ACPI_FUNCTION_TRACE(tb_match_signature); /* Search for a signature match among the known table types */ - for (i = 0; i < NUM_ACPI_TABLE_TYPES; i++) { + for (i = 0; i < (ACPI_TABLE_ID_MAX + 1); i++) { if (!(acpi_gbl_table_data[i].flags & search_type)) { continue; } @@ -123,7 +123,7 @@ acpi_status acpi_tb_install_table(struct acpi_table_desc *table_info) { acpi_status status; - ACPI_FUNCTION_TRACE("tb_install_table"); + ACPI_FUNCTION_TRACE(tb_install_table); /* Lock tables while installing */ @@ -188,7 +188,7 @@ acpi_tb_recognize_table(struct acpi_table_desc *table_info, u8 search_type) struct acpi_table_header *table_header; acpi_status status; - ACPI_FUNCTION_TRACE("tb_recognize_table"); + ACPI_FUNCTION_TRACE(tb_recognize_table); /* Ensure that we have a valid table pointer */ @@ -219,7 +219,6 @@ acpi_tb_recognize_table(struct acpi_table_desc *table_info, u8 search_type) /* Return the table type and length via the info struct */ table_info->length = (acpi_size) table_header->length; - return_ACPI_STATUS(status); } @@ -244,7 +243,7 @@ acpi_tb_init_table_descriptor(acpi_table_type table_type, struct acpi_table_desc *table_desc; acpi_status status; - ACPI_FUNCTION_TRACE_U32("tb_init_table_descriptor", table_type); + ACPI_FUNCTION_TRACE_U32(tb_init_table_descriptor, table_type); /* Allocate a descriptor for this table */ @@ -313,15 +312,14 @@ acpi_tb_init_table_descriptor(acpi_table_type table_type, /* Finish initialization of the table descriptor */ + table_desc->loaded_into_namespace = FALSE; table_desc->type = (u8) table_type; table_desc->pointer = table_info->pointer; table_desc->length = table_info->length; table_desc->allocation = table_info->allocation; table_desc->aml_start = (u8 *) (table_desc->pointer + 1), - table_desc->aml_length = (u32) (table_desc->length - - (u32) sizeof(struct - acpi_table_header)); - table_desc->loaded_into_namespace = FALSE; + table_desc->aml_length = (u32) + (table_desc->length - (u32) sizeof(struct acpi_table_header)); /* * Set the appropriate global pointer (if there is one) to point to the @@ -336,7 +334,6 @@ acpi_tb_init_table_descriptor(acpi_table_type table_type, table_info->owner_id = table_desc->owner_id; table_info->installed_desc = table_desc; - return_ACPI_STATUS(AE_OK); } @@ -360,7 +357,7 @@ void acpi_tb_delete_all_tables(void) * Free memory allocated for ACPI tables * Memory can either be mapped or allocated */ - for (type = 0; type < NUM_ACPI_TABLE_TYPES; type++) { + for (type = 0; type < (ACPI_TABLE_ID_MAX + 1); type++) { acpi_tb_delete_tables_by_type(type); } } @@ -384,9 +381,9 @@ void acpi_tb_delete_tables_by_type(acpi_table_type type) u32 count; u32 i; - ACPI_FUNCTION_TRACE_U32("tb_delete_tables_by_type", type); + ACPI_FUNCTION_TRACE_U32(tb_delete_tables_by_type, type); - if (type > ACPI_TABLE_MAX) { + if (type > ACPI_TABLE_ID_MAX) { return_VOID; } @@ -397,28 +394,28 @@ void acpi_tb_delete_tables_by_type(acpi_table_type type) /* Clear the appropriate "typed" global table pointer */ switch (type) { - case ACPI_TABLE_RSDP: + case ACPI_TABLE_ID_RSDP: acpi_gbl_RSDP = NULL; break; - case ACPI_TABLE_DSDT: + case ACPI_TABLE_ID_DSDT: acpi_gbl_DSDT = NULL; break; - case ACPI_TABLE_FADT: + case ACPI_TABLE_ID_FADT: acpi_gbl_FADT = NULL; break; - case ACPI_TABLE_FACS: + case ACPI_TABLE_ID_FACS: acpi_gbl_FACS = NULL; break; - case ACPI_TABLE_XSDT: + case ACPI_TABLE_ID_XSDT: acpi_gbl_XSDT = NULL; break; - case ACPI_TABLE_SSDT: - case ACPI_TABLE_PSDT: + case ACPI_TABLE_ID_SSDT: + case ACPI_TABLE_ID_PSDT: default: break; } @@ -504,7 +501,7 @@ struct acpi_table_desc *acpi_tb_uninstall_table(struct acpi_table_desc { struct acpi_table_desc *next_desc; - ACPI_FUNCTION_TRACE_PTR("tb_uninstall_table", table_desc); + ACPI_FUNCTION_TRACE_PTR(tb_uninstall_table, table_desc); if (!table_desc) { return_PTR(NULL); diff --git a/drivers/acpi/tables/tbrsdt.c b/drivers/acpi/tables/tbrsdt.c index 9e0ebe625ed..9e226438a3f 100644 --- a/drivers/acpi/tables/tbrsdt.c +++ b/drivers/acpi/tables/tbrsdt.c @@ -64,7 +64,7 @@ acpi_status acpi_tb_verify_rsdp(struct acpi_pointer *address) acpi_status status; struct rsdp_descriptor *rsdp; - ACPI_FUNCTION_TRACE("tb_verify_rsdp"); + ACPI_FUNCTION_TRACE(tb_verify_rsdp); switch (address->pointer_type) { case ACPI_LOGICAL_POINTER: @@ -103,7 +103,7 @@ acpi_status acpi_tb_verify_rsdp(struct acpi_pointer *address) /* Save the table pointers and allocation info */ - status = acpi_tb_init_table_descriptor(ACPI_TABLE_RSDP, &table_info); + status = acpi_tb_init_table_descriptor(ACPI_TABLE_ID_RSDP, &table_info); if (ACPI_FAILURE(status)) { goto cleanup; } @@ -174,22 +174,19 @@ void acpi_tb_get_rsdt_address(struct acpi_pointer *out_address) acpi_status acpi_tb_validate_rsdt(struct acpi_table_header *table_ptr) { - int no_match; + char *signature; ACPI_FUNCTION_ENTRY(); - /* - * Search for appropriate signature, RSDT or XSDT - */ + /* Search for appropriate signature, RSDT or XSDT */ + if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) { - no_match = ACPI_STRNCMP((char *)table_ptr, RSDT_SIG, - sizeof(RSDT_SIG) - 1); + signature = RSDT_SIG; } else { - no_match = ACPI_STRNCMP((char *)table_ptr, XSDT_SIG, - sizeof(XSDT_SIG) - 1); + signature = XSDT_SIG; } - if (no_match) { + if (!ACPI_COMPARE_NAME(table_ptr->signature, signature)) { /* Invalid RSDT or XSDT signature */ @@ -235,13 +232,13 @@ acpi_status acpi_tb_get_table_rsdt(void) acpi_status status; struct acpi_pointer address; - ACPI_FUNCTION_TRACE("tb_get_table_rsdt"); + ACPI_FUNCTION_TRACE(tb_get_table_rsdt); /* Get the RSDT/XSDT via the RSDP */ acpi_tb_get_rsdt_address(&address); - table_info.type = ACPI_TABLE_XSDT; + table_info.type = ACPI_TABLE_ID_XSDT; status = acpi_tb_get_table(&address, &table_info); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, @@ -275,7 +272,7 @@ acpi_status acpi_tb_get_table_rsdt(void) /* Save the table pointers and allocation info */ - status = acpi_tb_init_table_descriptor(ACPI_TABLE_XSDT, &table_info); + status = acpi_tb_init_table_descriptor(ACPI_TABLE_ID_XSDT, &table_info); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } diff --git a/drivers/acpi/tables/tbutils.c b/drivers/acpi/tables/tbutils.c index f8d28ae8811..5f144037651 100644 --- a/drivers/acpi/tables/tbutils.c +++ b/drivers/acpi/tables/tbutils.c @@ -71,7 +71,7 @@ acpi_status acpi_tb_is_table_installed(struct acpi_table_desc *new_table_desc) { struct acpi_table_desc *table_desc; - ACPI_FUNCTION_TRACE("tb_is_table_installed"); + ACPI_FUNCTION_TRACE(tb_is_table_installed); /* Get the list descriptor and first table descriptor */ @@ -100,7 +100,7 @@ acpi_status acpi_tb_is_table_installed(struct acpi_table_desc *new_table_desc) /* Match: this table is already installed */ ACPI_DEBUG_PRINT((ACPI_DB_TABLES, - "Table [%4.4s] already installed: Rev %X oem_table_id [%8.8s]\n", + "Table [%4.4s] already installed: Rev %X OemTableId [%8.8s]\n", new_table_desc->pointer->signature, new_table_desc->pointer->revision, new_table_desc->pointer-> @@ -288,7 +288,7 @@ acpi_tb_verify_table_checksum(struct acpi_table_header *table_header) { u8 checksum; - ACPI_FUNCTION_TRACE("tb_verify_table_checksum"); + ACPI_FUNCTION_TRACE(tb_verify_table_checksum); /* Compute the checksum on the table */ @@ -329,7 +329,7 @@ acpi_tb_handle_to_object(u16 table_id, u32 i; struct acpi_table_desc *table_desc; - ACPI_FUNCTION_NAME("tb_handle_to_object"); + ACPI_FUNCTION_NAME(tb_handle_to_object); for (i = 0; i < ACPI_TABLE_MAX; i++) { table_desc = acpi_gbl_table_lists[i].next; @@ -343,7 +343,7 @@ acpi_tb_handle_to_object(u16 table_id, } } - ACPI_ERROR((AE_INFO, "table_id=%X does not exist", table_id)); + ACPI_ERROR((AE_INFO, "TableId=%X does not exist", table_id)); return (AE_BAD_PARAMETER); } #endif diff --git a/drivers/acpi/tables/tbxface.c b/drivers/acpi/tables/tbxface.c index 53c627e401b..4e91f298481 100644 --- a/drivers/acpi/tables/tbxface.c +++ b/drivers/acpi/tables/tbxface.c @@ -66,7 +66,7 @@ acpi_status acpi_load_tables(void) struct acpi_pointer rsdp_address; acpi_status status; - ACPI_FUNCTION_TRACE("acpi_load_tables"); + ACPI_FUNCTION_TRACE(acpi_load_tables); /* Get the RSDP */ @@ -145,7 +145,7 @@ acpi_status acpi_load_table(struct acpi_table_header *table_ptr) struct acpi_table_desc table_info; struct acpi_pointer address; - ACPI_FUNCTION_TRACE("acpi_load_table"); + ACPI_FUNCTION_TRACE(acpi_load_table); if (!table_ptr) { return_ACPI_STATUS(AE_BAD_PARAMETER); @@ -188,12 +188,12 @@ acpi_status acpi_load_table(struct acpi_table_header *table_ptr) /* Convert the table to common format if necessary */ switch (table_info.type) { - case ACPI_TABLE_FADT: + case ACPI_TABLE_ID_FADT: status = acpi_tb_convert_table_fadt(); break; - case ACPI_TABLE_FACS: + case ACPI_TABLE_ID_FACS: status = acpi_tb_build_common_facs(&table_info); break; @@ -234,11 +234,11 @@ acpi_status acpi_unload_table(acpi_table_type table_type) { struct acpi_table_desc *table_desc; - ACPI_FUNCTION_TRACE("acpi_unload_table"); + ACPI_FUNCTION_TRACE(acpi_unload_table); /* Parameter validation */ - if (table_type > ACPI_TABLE_MAX) { + if (table_type > ACPI_TABLE_ID_MAX) { return_ACPI_STATUS(AE_BAD_PARAMETER); } @@ -292,16 +292,16 @@ acpi_get_table_header(acpi_table_type table_type, struct acpi_table_header *tbl_ptr; acpi_status status; - ACPI_FUNCTION_TRACE("acpi_get_table_header"); + ACPI_FUNCTION_TRACE(acpi_get_table_header); if ((instance == 0) || - (table_type == ACPI_TABLE_RSDP) || (!out_table_header)) { + (table_type == ACPI_TABLE_ID_RSDP) || (!out_table_header)) { return_ACPI_STATUS(AE_BAD_PARAMETER); } /* Check the table type and instance */ - if ((table_type > ACPI_TABLE_MAX) || + if ((table_type > ACPI_TABLE_ID_MAX) || (ACPI_IS_SINGLE_TABLE(acpi_gbl_table_data[table_type].flags) && instance > 1)) { return_ACPI_STATUS(AE_BAD_PARAMETER); @@ -361,7 +361,7 @@ acpi_get_table(acpi_table_type table_type, acpi_status status; acpi_size table_length; - ACPI_FUNCTION_TRACE("acpi_get_table"); + ACPI_FUNCTION_TRACE(acpi_get_table); /* Parameter validation */ @@ -376,7 +376,7 @@ acpi_get_table(acpi_table_type table_type, /* Check the table type and instance */ - if ((table_type > ACPI_TABLE_MAX) || + if ((table_type > ACPI_TABLE_ID_MAX) || (ACPI_IS_SINGLE_TABLE(acpi_gbl_table_data[table_type].flags) && instance > 1)) { return_ACPI_STATUS(AE_BAD_PARAMETER); @@ -399,7 +399,7 @@ acpi_get_table(acpi_table_type table_type, /* Get the table length */ - if (table_type == ACPI_TABLE_RSDP) { + if (table_type == ACPI_TABLE_ID_RSDP) { /* RSD PTR is the only "table" without a header */ diff --git a/drivers/acpi/tables/tbxfroot.c b/drivers/acpi/tables/tbxfroot.c index 550284f5d1e..3107e741d51 100644 --- a/drivers/acpi/tables/tbxfroot.c +++ b/drivers/acpi/tables/tbxfroot.c @@ -119,7 +119,7 @@ acpi_tb_find_table(char *signature, acpi_status status; struct acpi_table_header *table; - ACPI_FUNCTION_TRACE("tb_find_table"); + ACPI_FUNCTION_TRACE(tb_find_table); /* Validate string lengths */ @@ -129,7 +129,7 @@ acpi_tb_find_table(char *signature, return_ACPI_STATUS(AE_AML_STRING_LIMIT); } - if (!ACPI_STRNCMP(signature, DSDT_SIG, ACPI_NAME_SIZE)) { + if (ACPI_COMPARE_NAME(signature, DSDT_SIG)) { /* * The DSDT pointer is contained in the FADT, not the RSDT. * This code should suffice, because the only code that would perform @@ -154,10 +154,12 @@ acpi_tb_find_table(char *signature, /* Check oem_id and oem_table_id */ - if ((oem_id[0] && ACPI_STRNCMP(oem_id, table->oem_id, - sizeof(table->oem_id))) || - (oem_table_id[0] && ACPI_STRNCMP(oem_table_id, table->oem_table_id, - sizeof(table->oem_table_id)))) { + if ((oem_id[0] && + ACPI_STRNCMP(oem_id, table->oem_id, + sizeof(table->oem_id))) || + (oem_table_id[0] && + ACPI_STRNCMP(oem_table_id, table->oem_table_id, + sizeof(table->oem_table_id)))) { return_ACPI_STATUS(AE_AML_NAME_NOT_FOUND); } @@ -201,7 +203,7 @@ acpi_get_firmware_table(acpi_string signature, u32 i; u32 j; - ACPI_FUNCTION_TRACE("acpi_get_firmware_table"); + ACPI_FUNCTION_TRACE(acpi_get_firmware_table); /* * Ensure that at least the table manager is initialized. We don't @@ -325,7 +327,7 @@ acpi_get_firmware_table(acpi_string signature, /* Compare table signatures and table instance */ - if (!ACPI_STRNCMP(header->signature, signature, ACPI_NAME_SIZE)) { + if (ACPI_COMPARE_NAME(header->signature, signature)) { /* An instance of the table was found */ @@ -388,7 +390,7 @@ acpi_status acpi_find_root_pointer(u32 flags, struct acpi_pointer *rsdp_address) struct acpi_table_desc table_info; acpi_status status; - ACPI_FUNCTION_TRACE("acpi_find_root_pointer"); + ACPI_FUNCTION_TRACE(acpi_find_root_pointer); /* Get the RSDP */ @@ -425,7 +427,7 @@ static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length) u8 *mem_rover; u8 *end_address; - ACPI_FUNCTION_TRACE("tb_scan_memory_for_rsdp"); + ACPI_FUNCTION_TRACE(tb_scan_memory_for_rsdp); end_address = start_address + length; @@ -490,7 +492,7 @@ acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags) u32 physical_address; acpi_status status; - ACPI_FUNCTION_TRACE("tb_find_rsdp"); + ACPI_FUNCTION_TRACE(tb_find_rsdp); /* * Scan supports either logical addressing or physical addressing diff --git a/drivers/acpi/utilities/utalloc.c b/drivers/acpi/utilities/utalloc.c index 3b29aecaaca..65a7c2ed9aa 100644 --- a/drivers/acpi/utilities/utalloc.c +++ b/drivers/acpi/utilities/utalloc.c @@ -108,7 +108,7 @@ acpi_status acpi_ut_create_caches(void) } status = - acpi_os_create_cache("Acpi-parse_ext", + acpi_os_create_cache("Acpi-ParseExt", sizeof(struct acpi_parse_obj_named), ACPI_MAX_EXTPARSE_CACHE_DEPTH, &acpi_gbl_ps_node_ext_cache); @@ -289,7 +289,7 @@ void *acpi_ut_allocate(acpi_size size, u32 component, char *module, u32 line) { void *allocation; - ACPI_FUNCTION_TRACE_U32("ut_allocate", size); + ACPI_FUNCTION_TRACE_U32(ut_allocate, size); /* Check for an inadvertent size of zero bytes */ diff --git a/drivers/acpi/utilities/utcache.c b/drivers/acpi/utilities/utcache.c index 593b08ccd6b..56270a30718 100644 --- a/drivers/acpi/utilities/utcache.c +++ b/drivers/acpi/utilities/utcache.c @@ -244,7 +244,7 @@ void *acpi_os_acquire_object(struct acpi_memory_list *cache) acpi_status status; void *object; - ACPI_FUNCTION_NAME("os_acquire_object"); + ACPI_FUNCTION_NAME(os_acquire_object); if (!cache) { return (NULL); diff --git a/drivers/acpi/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c index 371cddc0d57..5e1a80d1bc3 100644 --- a/drivers/acpi/utilities/utcopy.c +++ b/drivers/acpi/utilities/utcopy.c @@ -109,7 +109,7 @@ acpi_ut_copy_isimple_to_esimple(union acpi_operand_object *internal_object, { acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("ut_copy_isimple_to_esimple"); + ACPI_FUNCTION_TRACE(ut_copy_isimple_to_esimple); *buffer_space_used = 0; @@ -325,7 +325,7 @@ acpi_ut_copy_ipackage_to_epackage(union acpi_operand_object *internal_object, acpi_status status; struct acpi_pkg_info info; - ACPI_FUNCTION_TRACE("ut_copy_ipackage_to_epackage"); + ACPI_FUNCTION_TRACE(ut_copy_ipackage_to_epackage); /* * First package at head of the buffer @@ -383,7 +383,7 @@ acpi_ut_copy_iobject_to_eobject(union acpi_operand_object *internal_object, { acpi_status status; - ACPI_FUNCTION_TRACE("ut_copy_iobject_to_eobject"); + ACPI_FUNCTION_TRACE(ut_copy_iobject_to_eobject); if (ACPI_GET_OBJECT_TYPE(internal_object) == ACPI_TYPE_PACKAGE) { /* @@ -442,7 +442,7 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object, { union acpi_operand_object *internal_object; - ACPI_FUNCTION_TRACE("ut_copy_esimple_to_isimple"); + ACPI_FUNCTION_TRACE(ut_copy_esimple_to_isimple); /* * Simple types supported are: String, Buffer, Integer @@ -552,7 +552,7 @@ acpi_ut_copy_epackage_to_ipackage(union acpi_operand_object *internal_object, union acpi_operand_object *this_internal_obj; union acpi_object *this_external_obj; - ACPI_FUNCTION_TRACE("ut_copy_epackage_to_ipackage"); + ACPI_FUNCTION_TRACE(ut_copy_epackage_to_ipackage); /* * First package at head of the buffer @@ -600,7 +600,7 @@ acpi_ut_copy_eobject_to_iobject(union acpi_object *external_object, { acpi_status status; - ACPI_FUNCTION_TRACE("ut_copy_eobject_to_iobject"); + ACPI_FUNCTION_TRACE(ut_copy_eobject_to_iobject); if (external_object->type == ACPI_TYPE_PACKAGE) { /* @@ -854,7 +854,7 @@ acpi_ut_copy_ipackage_to_ipackage(union acpi_operand_object *source_obj, { acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("ut_copy_ipackage_to_ipackage"); + ACPI_FUNCTION_TRACE(ut_copy_ipackage_to_ipackage); dest_obj->common.type = ACPI_GET_OBJECT_TYPE(source_obj); dest_obj->common.flags = source_obj->common.flags; @@ -910,7 +910,7 @@ acpi_ut_copy_iobject_to_iobject(union acpi_operand_object *source_desc, { acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("ut_copy_iobject_to_iobject"); + ACPI_FUNCTION_TRACE(ut_copy_iobject_to_iobject); /* Create the top level object */ diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c index b4e34a2f81f..0bb4b59b280 100644 --- a/drivers/acpi/utilities/utdelete.c +++ b/drivers/acpi/utilities/utdelete.c @@ -76,7 +76,7 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object) union acpi_operand_object *second_desc; union acpi_operand_object *next_desc; - ACPI_FUNCTION_TRACE_PTR("ut_delete_internal_obj", object); + ACPI_FUNCTION_TRACE_PTR(ut_delete_internal_obj, object); if (!object) { return_VOID; @@ -276,7 +276,7 @@ void acpi_ut_delete_internal_object_list(union acpi_operand_object **obj_list) { union acpi_operand_object **internal_obj; - ACPI_FUNCTION_TRACE("ut_delete_internal_object_list"); + ACPI_FUNCTION_TRACE(ut_delete_internal_object_list); /* Walk the null-terminated internal list */ @@ -309,7 +309,7 @@ acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action) u16 count; u16 new_count; - ACPI_FUNCTION_NAME("ut_update_ref_count"); + ACPI_FUNCTION_NAME(ut_update_ref_count); if (!object) { return; @@ -425,7 +425,7 @@ acpi_ut_update_object_reference(union acpi_operand_object * object, u16 action) union acpi_generic_state *state; acpi_native_uint i; - ACPI_FUNCTION_TRACE_PTR("ut_update_object_reference", object); + ACPI_FUNCTION_TRACE_PTR(ut_update_object_reference, object); while (object) { @@ -570,7 +570,7 @@ acpi_ut_update_object_reference(union acpi_operand_object * object, u16 action) void acpi_ut_add_reference(union acpi_operand_object *object) { - ACPI_FUNCTION_TRACE_PTR("ut_add_reference", object); + ACPI_FUNCTION_TRACE_PTR(ut_add_reference, object); /* Ensure that we have a valid object */ @@ -603,7 +603,7 @@ void acpi_ut_add_reference(union acpi_operand_object *object) void acpi_ut_remove_reference(union acpi_operand_object *object) { - ACPI_FUNCTION_TRACE_PTR("ut_remove_reference", object); + ACPI_FUNCTION_TRACE_PTR(ut_remove_reference, object); /* * Allow a NULL pointer to be passed in, just ignore it. This saves diff --git a/drivers/acpi/utilities/uteval.c b/drivers/acpi/utilities/uteval.c index 68b9eff4b32..444d3a502c4 100644 --- a/drivers/acpi/utilities/uteval.c +++ b/drivers/acpi/utilities/uteval.c @@ -56,6 +56,34 @@ static acpi_status acpi_ut_translate_one_cid(union acpi_operand_object *obj_desc, struct acpi_compatible_id *one_cid); +/* + * Strings supported by the _OSI predefined (internal) method. + */ +static const char *acpi_interfaces_supported[] = { + /* Operating System Vendor Strings */ + + "Linux", + "Windows 2000", + "Windows 2001", + "Windows 2001 SP0", + "Windows 2001 SP1", + "Windows 2001 SP2", + "Windows 2001 SP3", + "Windows 2001 SP4", + "Windows 2001.1", + "Windows 2001.1 SP1", /* Added 03/2006 */ + "Windows 2006", /* Added 03/2006 */ + + /* Feature Group Strings */ + + "Extended Address Space Descriptor" + /* + * All "optional" feature group strings (features that are implemented + * by the host) should be implemented in the host version of + * acpi_os_validate_interface and should not be added here. + */ +}; + /******************************************************************************* * * FUNCTION: acpi_ut_osi_implementation @@ -64,18 +92,18 @@ acpi_ut_translate_one_cid(union acpi_operand_object *obj_desc, * * RETURN: Status * - * DESCRIPTION: Implementation of _OSI predefined control method - * Supported = _OSI (String) + * DESCRIPTION: Implementation of the _OSI predefined control method * ******************************************************************************/ acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state) { + acpi_status status; union acpi_operand_object *string_desc; union acpi_operand_object *return_desc; acpi_native_uint i; - ACPI_FUNCTION_TRACE("ut_osi_implementation"); + ACPI_FUNCTION_TRACE(ut_osi_implementation); /* Validate the string input argument */ @@ -84,29 +112,47 @@ acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state) return_ACPI_STATUS(AE_TYPE); } - /* Create a return object (Default value = 0) */ + /* Create a return object */ return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); if (!return_desc) { return_ACPI_STATUS(AE_NO_MEMORY); } - /* Compare input string to table of supported strings */ + /* Default return value is SUPPORTED */ - for (i = 0; i < ACPI_NUM_OSI_STRINGS; i++) { - if (!ACPI_STRCMP(string_desc->string.pointer, - ACPI_CAST_PTR(char, - acpi_gbl_valid_osi_strings[i]))) - { + return_desc->integer.value = ACPI_UINT32_MAX; + walk_state->return_desc = return_desc; + + /* Compare input string to static table of supported interfaces */ - /* This string is supported */ + for (i = 0; i < ACPI_ARRAY_LENGTH(acpi_interfaces_supported); i++) { + if (!ACPI_STRCMP + (string_desc->string.pointer, + acpi_interfaces_supported[i])) { - return_desc->integer.value = 0xFFFFFFFF; - break; + /* The interface is supported */ + + return_ACPI_STATUS(AE_CTRL_TERMINATE); } } - walk_state->return_desc = return_desc; + /* + * Did not match the string in the static table, call the host OSL to + * check for a match with one of the optional strings (such as + * "Module Device", "3.0 Thermal Model", etc.) + */ + status = acpi_os_validate_interface(string_desc->string.pointer); + if (ACPI_SUCCESS(status)) { + + /* The interface is supported */ + + return_ACPI_STATUS(AE_CTRL_TERMINATE); + } + + /* The interface is not supported */ + + return_desc->integer.value = 0; return_ACPI_STATUS(AE_CTRL_TERMINATE); } @@ -139,7 +185,7 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node, acpi_status status; u32 return_btype; - ACPI_FUNCTION_TRACE("ut_evaluate_object"); + ACPI_FUNCTION_TRACE(ut_evaluate_object); info.node = prefix_node; info.parameters = NULL; @@ -258,7 +304,7 @@ acpi_ut_evaluate_numeric_object(char *object_name, union acpi_operand_object *obj_desc; acpi_status status; - ACPI_FUNCTION_TRACE("ut_evaluate_numeric_object"); + ACPI_FUNCTION_TRACE(ut_evaluate_numeric_object); status = acpi_ut_evaluate_object(device_node, object_name, ACPI_BTYPE_INTEGER, &obj_desc); @@ -334,7 +380,7 @@ acpi_ut_execute_HID(struct acpi_namespace_node *device_node, union acpi_operand_object *obj_desc; acpi_status status; - ACPI_FUNCTION_TRACE("ut_execute_HID"); + ACPI_FUNCTION_TRACE(ut_execute_HID); status = acpi_ut_evaluate_object(device_node, METHOD_NAME__HID, ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING, @@ -438,7 +484,7 @@ acpi_ut_execute_CID(struct acpi_namespace_node * device_node, struct acpi_compatible_id_list *cid_list; acpi_native_uint i; - ACPI_FUNCTION_TRACE("ut_execute_CID"); + ACPI_FUNCTION_TRACE(ut_execute_CID); /* Evaluate the _CID method for this device */ @@ -536,7 +582,7 @@ acpi_ut_execute_UID(struct acpi_namespace_node *device_node, union acpi_operand_object *obj_desc; acpi_status status; - ACPI_FUNCTION_TRACE("ut_execute_UID"); + ACPI_FUNCTION_TRACE(ut_execute_UID); status = acpi_ut_evaluate_object(device_node, METHOD_NAME__UID, ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING, @@ -586,7 +632,7 @@ acpi_ut_execute_STA(struct acpi_namespace_node *device_node, u32 * flags) union acpi_operand_object *obj_desc; acpi_status status; - ACPI_FUNCTION_TRACE("ut_execute_STA"); + ACPI_FUNCTION_TRACE(ut_execute_STA); status = acpi_ut_evaluate_object(device_node, METHOD_NAME__STA, ACPI_BTYPE_INTEGER, &obj_desc); @@ -636,7 +682,7 @@ acpi_ut_execute_sxds(struct acpi_namespace_node *device_node, u8 * highest) acpi_status status; u32 i; - ACPI_FUNCTION_TRACE("ut_execute_Sxds"); + ACPI_FUNCTION_TRACE(ut_execute_sxds); for (i = 0; i < 4; i++) { highest[i] = 0xFF; diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c index e8ae417c984..e666c71be0b 100644 --- a/drivers/acpi/utilities/utglobal.c +++ b/drivers/acpi/utilities/utglobal.c @@ -181,30 +181,6 @@ const char *acpi_gbl_highest_dstate_names[4] = { "_S4D" }; -/* - * Strings supported by the _OSI predefined (internal) method. - * When adding strings, be sure to update ACPI_NUM_OSI_STRINGS. - */ -const char *acpi_gbl_valid_osi_strings[ACPI_NUM_OSI_STRINGS] = { - /* Operating System Vendor Strings */ - - "Linux", - "Windows 2000", - "Windows 2001", - "Windows 2001 SP0", - "Windows 2001 SP1", - "Windows 2001 SP2", - "Windows 2001 SP3", - "Windows 2001 SP4", - "Windows 2001.1", - "Windows 2001.1 SP1", /* Added 03/2006 */ - "Windows 2006", /* Added 03/2006 */ - - /* Feature Group Strings */ - - "Extended Address Space Descriptor" -}; - /******************************************************************************* * * Namespace globals @@ -317,9 +293,9 @@ char acpi_ut_hex_to_ascii_char(acpi_integer integer, u32 position) * ******************************************************************************/ -struct acpi_table_list acpi_gbl_table_lists[NUM_ACPI_TABLE_TYPES]; +struct acpi_table_list acpi_gbl_table_lists[ACPI_TABLE_ID_MAX + 1]; -struct acpi_table_support acpi_gbl_table_data[NUM_ACPI_TABLE_TYPES] = { +struct acpi_table_support acpi_gbl_table_data[ACPI_TABLE_ID_MAX + 1] = { /*********** Name, Signature, Global typed pointer Signature size, Type How many allowed?, Contains valid AML? */ /* RSDP 0 */ {RSDP_NAME, RSDP_SIG, NULL, sizeof(RSDP_SIG) - 1, @@ -483,9 +459,9 @@ char *acpi_ut_get_region_name(u8 space_id) { if (space_id >= ACPI_USER_REGION_BEGIN) { - return ("user_defined_region"); + return ("UserDefinedRegion"); } else if (space_id >= ACPI_NUM_PREDEFINED_REGIONS) { - return ("invalid_space_id"); + return ("InvalidSpaceId"); } return (ACPI_CAST_PTR(char, acpi_gbl_region_types[space_id])); @@ -519,7 +495,7 @@ char *acpi_ut_get_event_name(u32 event_id) { if (event_id > ACPI_EVENT_MAX) { - return ("invalid_event_iD"); + return ("InvalidEventID"); } return (ACPI_CAST_PTR(char, acpi_gbl_event_types[event_id])); @@ -774,7 +750,7 @@ void acpi_ut_init_globals(void) acpi_status status; u32 i; - ACPI_FUNCTION_TRACE("ut_init_globals"); + ACPI_FUNCTION_TRACE(ut_init_globals); /* Create all memory caches */ @@ -785,7 +761,7 @@ void acpi_ut_init_globals(void) /* ACPI table structure */ - for (i = 0; i < NUM_ACPI_TABLE_TYPES; i++) { + for (i = 0; i < (ACPI_TABLE_ID_MAX + 1); i++) { acpi_gbl_table_lists[i].next = NULL; acpi_gbl_table_lists[i].count = 0; } diff --git a/drivers/acpi/utilities/utinit.c b/drivers/acpi/utilities/utinit.c index 7538b165b6e..c65747d3c88 100644 --- a/drivers/acpi/utilities/utinit.c +++ b/drivers/acpi/utilities/utinit.c @@ -176,7 +176,7 @@ static void acpi_ut_terminate(void) struct acpi_gpe_xrupt_info *gpe_xrupt_info; struct acpi_gpe_xrupt_info *next_gpe_xrupt_info; - ACPI_FUNCTION_TRACE("ut_terminate"); + ACPI_FUNCTION_TRACE(ut_terminate); /* Free global tables, etc. */ /* Free global GPE blocks and related info structures */ @@ -216,7 +216,7 @@ static void acpi_ut_terminate(void) void acpi_ut_subsystem_shutdown(void) { - ACPI_FUNCTION_TRACE("ut_subsystem_shutdown"); + ACPI_FUNCTION_TRACE(ut_subsystem_shutdown); /* Just exit if subsystem is already shutdown */ diff --git a/drivers/acpi/utilities/utmath.c b/drivers/acpi/utilities/utmath.c index 4a3360484e7..19d74bedce2 100644 --- a/drivers/acpi/utilities/utmath.c +++ b/drivers/acpi/utilities/utmath.c @@ -77,7 +77,7 @@ acpi_ut_short_divide(acpi_integer dividend, union uint64_overlay quotient; u32 remainder32; - ACPI_FUNCTION_TRACE("ut_short_divide"); + ACPI_FUNCTION_TRACE(ut_short_divide); /* Always check for a zero divisor */ @@ -139,7 +139,7 @@ acpi_ut_divide(acpi_integer in_dividend, union uint64_overlay partial2; union uint64_overlay partial3; - ACPI_FUNCTION_TRACE("ut_divide"); + ACPI_FUNCTION_TRACE(ut_divide); /* Always check for a zero divisor */ @@ -261,7 +261,7 @@ acpi_ut_short_divide(acpi_integer in_dividend, acpi_integer * out_quotient, u32 * out_remainder) { - ACPI_FUNCTION_TRACE("ut_short_divide"); + ACPI_FUNCTION_TRACE(ut_short_divide); /* Always check for a zero divisor */ @@ -287,7 +287,7 @@ acpi_ut_divide(acpi_integer in_dividend, acpi_integer in_divisor, acpi_integer * out_quotient, acpi_integer * out_remainder) { - ACPI_FUNCTION_TRACE("ut_divide"); + ACPI_FUNCTION_TRACE(ut_divide); /* Always check for a zero divisor */ diff --git a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c index 4623d7e215d..874467117ce 100644 --- a/drivers/acpi/utilities/utmisc.c +++ b/drivers/acpi/utilities/utmisc.c @@ -95,7 +95,7 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id) acpi_native_uint k; acpi_status status; - ACPI_FUNCTION_TRACE("ut_allocate_owner_id"); + ACPI_FUNCTION_TRACE(ut_allocate_owner_id); /* Guard against multiple allocations of ID to the same location */ @@ -152,7 +152,7 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id) (acpi_owner_id) ((k + 1) + ACPI_MUL_32(j)); ACPI_DEBUG_PRINT((ACPI_DB_VALUES, - "Allocated owner_id: %2.2X\n", + "Allocated OwnerId: %2.2X\n", (unsigned int)*owner_id)); goto exit; } @@ -173,7 +173,7 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id) */ status = AE_OWNER_ID_LIMIT; ACPI_ERROR((AE_INFO, - "Could not allocate new owner_id (255 max), AE_OWNER_ID_LIMIT")); + "Could not allocate new OwnerId (255 max), AE_OWNER_ID_LIMIT")); exit: (void)acpi_ut_release_mutex(ACPI_MTX_CACHES); @@ -201,7 +201,7 @@ void acpi_ut_release_owner_id(acpi_owner_id * owner_id_ptr) acpi_native_uint index; u32 bit; - ACPI_FUNCTION_TRACE_U32("ut_release_owner_id", owner_id); + ACPI_FUNCTION_TRACE_U32(ut_release_owner_id, owner_id); /* Always clear the input owner_id (zero is an invalid ID) */ @@ -210,7 +210,7 @@ void acpi_ut_release_owner_id(acpi_owner_id * owner_id_ptr) /* Zero is not a valid owner_iD */ if (owner_id == 0) { - ACPI_ERROR((AE_INFO, "Invalid owner_id: %2.2X", owner_id)); + ACPI_ERROR((AE_INFO, "Invalid OwnerId: %2.2X", owner_id)); return_VOID; } @@ -236,7 +236,7 @@ void acpi_ut_release_owner_id(acpi_owner_id * owner_id_ptr) acpi_gbl_owner_id_mask[index] ^= bit; } else { ACPI_ERROR((AE_INFO, - "Release of non-allocated owner_id: %2.2X", + "Release of non-allocated OwnerId: %2.2X", owner_id + 1)); } @@ -618,7 +618,7 @@ acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer) acpi_integer return_value = 0; acpi_integer quotient; - ACPI_FUNCTION_TRACE("ut_stroul64"); + ACPI_FUNCTION_TRACE(ut_stroul64); if ((!string) || !(*string)) { goto error_exit; @@ -794,7 +794,7 @@ acpi_ut_walk_package_tree(union acpi_operand_object * source_object, u32 this_index; union acpi_operand_object *this_source_obj; - ACPI_FUNCTION_TRACE("ut_walk_package_tree"); + ACPI_FUNCTION_TRACE(ut_walk_package_tree); state = acpi_ut_create_pkg_state(source_object, target_object, 0); if (!state) { diff --git a/drivers/acpi/utilities/utmutex.c b/drivers/acpi/utilities/utmutex.c index 0ac6700a45f..b851f7be5d5 100644 --- a/drivers/acpi/utilities/utmutex.c +++ b/drivers/acpi/utilities/utmutex.c @@ -68,7 +68,7 @@ acpi_status acpi_ut_mutex_initialize(void) u32 i; acpi_status status; - ACPI_FUNCTION_TRACE("ut_mutex_initialize"); + ACPI_FUNCTION_TRACE(ut_mutex_initialize); /* * Create each of the predefined mutex objects @@ -100,7 +100,7 @@ void acpi_ut_mutex_terminate(void) { u32 i; - ACPI_FUNCTION_TRACE("ut_mutex_terminate"); + ACPI_FUNCTION_TRACE(ut_mutex_terminate); /* * Delete each predefined mutex object @@ -129,7 +129,7 @@ static acpi_status acpi_ut_create_mutex(acpi_mutex_handle mutex_id) { acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE_U32("ut_create_mutex", mutex_id); + ACPI_FUNCTION_TRACE_U32(ut_create_mutex, mutex_id); if (mutex_id > MAX_MUTEX) { return_ACPI_STATUS(AE_BAD_PARAMETER); @@ -163,7 +163,7 @@ static acpi_status acpi_ut_delete_mutex(acpi_mutex_handle mutex_id) { acpi_status status; - ACPI_FUNCTION_TRACE_U32("ut_delete_mutex", mutex_id); + ACPI_FUNCTION_TRACE_U32(ut_delete_mutex, mutex_id); if (mutex_id > MAX_MUTEX) { return_ACPI_STATUS(AE_BAD_PARAMETER); @@ -194,7 +194,7 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id) acpi_status status; acpi_thread_id this_thread_id; - ACPI_FUNCTION_NAME("ut_acquire_mutex"); + ACPI_FUNCTION_NAME(ut_acquire_mutex); if (mutex_id > MAX_MUTEX) { return (AE_BAD_PARAMETER); @@ -277,7 +277,7 @@ acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id) acpi_status status; acpi_thread_id this_thread_id; - ACPI_FUNCTION_NAME("ut_release_mutex"); + ACPI_FUNCTION_NAME(ut_release_mutex); this_thread_id = acpi_os_get_thread_id(); ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, diff --git a/drivers/acpi/utilities/utobject.c b/drivers/acpi/utilities/utobject.c index 8e3dcbd23f5..ba7d8ac702d 100644 --- a/drivers/acpi/utilities/utobject.c +++ b/drivers/acpi/utilities/utobject.c @@ -92,7 +92,7 @@ union acpi_operand_object *acpi_ut_create_internal_object_dbg(char *module_name, union acpi_operand_object *object; union acpi_operand_object *second_object; - ACPI_FUNCTION_TRACE_STR("ut_create_internal_object_dbg", + ACPI_FUNCTION_TRACE_STR(ut_create_internal_object_dbg, acpi_ut_get_type_name(type)); /* Allocate the raw object descriptor */ @@ -161,7 +161,7 @@ union acpi_operand_object *acpi_ut_create_buffer_object(acpi_size buffer_size) union acpi_operand_object *buffer_desc; u8 *buffer = NULL; - ACPI_FUNCTION_TRACE_U32("ut_create_buffer_object", buffer_size); + ACPI_FUNCTION_TRACE_U32(ut_create_buffer_object, buffer_size); /* Create a new Buffer object */ @@ -215,7 +215,7 @@ union acpi_operand_object *acpi_ut_create_string_object(acpi_size string_size) union acpi_operand_object *string_desc; char *string; - ACPI_FUNCTION_TRACE_U32("ut_create_string_object", string_size); + ACPI_FUNCTION_TRACE_U32(ut_create_string_object, string_size); /* Create a new String object */ @@ -261,7 +261,7 @@ union acpi_operand_object *acpi_ut_create_string_object(acpi_size string_size) u8 acpi_ut_valid_internal_object(void *object) { - ACPI_FUNCTION_NAME("ut_valid_internal_object"); + ACPI_FUNCTION_NAME(ut_valid_internal_object); /* Check for a null pointer */ @@ -309,7 +309,7 @@ void *acpi_ut_allocate_object_desc_dbg(char *module_name, { union acpi_operand_object *object; - ACPI_FUNCTION_TRACE("ut_allocate_object_desc_dbg"); + ACPI_FUNCTION_TRACE(ut_allocate_object_desc_dbg); object = acpi_os_acquire_object(acpi_gbl_operand_cache); if (!object) { @@ -344,7 +344,7 @@ void *acpi_ut_allocate_object_desc_dbg(char *module_name, void acpi_ut_delete_object_desc(union acpi_operand_object *object) { - ACPI_FUNCTION_TRACE_PTR("ut_delete_object_desc", object); + ACPI_FUNCTION_TRACE_PTR(ut_delete_object_desc, object); /* Object must be an union acpi_operand_object */ @@ -383,7 +383,7 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object, acpi_size length; acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE_PTR("ut_get_simple_object_size", internal_object); + ACPI_FUNCTION_TRACE_PTR(ut_get_simple_object_size, internal_object); /* * Handle a null object (Could be a uninitialized package @@ -562,7 +562,7 @@ acpi_ut_get_package_object_size(union acpi_operand_object *internal_object, acpi_status status; struct acpi_pkg_info info; - ACPI_FUNCTION_TRACE_PTR("ut_get_package_object_size", internal_object); + ACPI_FUNCTION_TRACE_PTR(ut_get_package_object_size, internal_object); info.length = 0; info.object_space = 0; diff --git a/drivers/acpi/utilities/utresrc.c b/drivers/acpi/utilities/utresrc.c index 1e680794c6d..5a2de92831d 100644 --- a/drivers/acpi/utilities/utresrc.c +++ b/drivers/acpi/utilities/utresrc.c @@ -45,113 +45,113 @@ #include #define _COMPONENT ACPI_UTILITIES -ACPI_MODULE_NAME("utmisc") +ACPI_MODULE_NAME("utresrc") #if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER) /* * Strings used to decode resource descriptors. * Used by both the disasssembler and the debugger resource dump routines */ -const char *acpi_gbl_BMdecode[2] = { - "not_bus_master", - "bus_master" +const char *acpi_gbl_bm_decode[] = { + "NotBusMaster", + "BusMaster" }; -const char *acpi_gbl_config_decode[4] = { +const char *acpi_gbl_config_decode[] = { "0 - Good Configuration", "1 - Acceptable Configuration", "2 - Suboptimal Configuration", "3 - ***Invalid Configuration***", }; -const char *acpi_gbl_consume_decode[2] = { - "resource_producer", - "resource_consumer" +const char *acpi_gbl_consume_decode[] = { + "ResourceProducer", + "ResourceConsumer" }; -const char *acpi_gbl_DECdecode[2] = { - "pos_decode", - "sub_decode" +const char *acpi_gbl_dec_decode[] = { + "PosDecode", + "SubDecode" }; -const char *acpi_gbl_HEdecode[2] = { +const char *acpi_gbl_he_decode[] = { "Level", "Edge" }; -const char *acpi_gbl_io_decode[2] = { +const char *acpi_gbl_io_decode[] = { "Decode10", "Decode16" }; -const char *acpi_gbl_LLdecode[2] = { - "active_high", - "active_low" +const char *acpi_gbl_ll_decode[] = { + "ActiveHigh", + "ActiveLow" }; -const char *acpi_gbl_max_decode[2] = { - "max_not_fixed", - "max_fixed" +const char *acpi_gbl_max_decode[] = { + "MaxNotFixed", + "MaxFixed" }; -const char *acpi_gbl_MEMdecode[4] = { - "non_cacheable", +const char *acpi_gbl_mem_decode[] = { + "NonCacheable", "Cacheable", - "write_combining", + "WriteCombining", "Prefetchable" }; -const char *acpi_gbl_min_decode[2] = { - "min_not_fixed", - "min_fixed" +const char *acpi_gbl_min_decode[] = { + "MinNotFixed", + "MinFixed" }; -const char *acpi_gbl_MTPdecode[4] = { - "address_range_memory", - "address_range_reserved", - "address_range_aCPI", - "address_range_nVS" +const char *acpi_gbl_mtp_decode[] = { + "AddressRangeMemory", + "AddressRangeReserved", + "AddressRangeACPI", + "AddressRangeNVS" }; -const char *acpi_gbl_RNGdecode[4] = { - "invalid_ranges", - "non_iSAonly_ranges", - "ISAonly_ranges", - "entire_range" +const char *acpi_gbl_rng_decode[] = { + "InvalidRanges", + "NonISAOnlyRanges", + "ISAOnlyRanges", + "EntireRange" }; -const char *acpi_gbl_RWdecode[2] = { - "read_only", - "read_write" +const char *acpi_gbl_rw_decode[] = { + "ReadOnly", + "ReadWrite" }; -const char *acpi_gbl_SHRdecode[2] = { +const char *acpi_gbl_shr_decode[] = { "Exclusive", "Shared" }; -const char *acpi_gbl_SIZdecode[4] = { +const char *acpi_gbl_siz_decode[] = { "Transfer8", "Transfer8_16", "Transfer16", - "invalid_size" + "InvalidSize" }; -const char *acpi_gbl_TRSdecode[2] = { - "dense_translation", - "sparse_translation" +const char *acpi_gbl_trs_decode[] = { + "DenseTranslation", + "SparseTranslation" }; -const char *acpi_gbl_TTPdecode[2] = { - "type_static", - "type_translation" +const char *acpi_gbl_ttp_decode[] = { + "TypeStatic", + "TypeTranslation" }; -const char *acpi_gbl_TYPdecode[4] = { +const char *acpi_gbl_typ_decode[] = { "Compatibility", - "type_a", - "type_b", - "type_f" + "TypeA", + "TypeB", + "TypeF" }; #endif @@ -266,7 +266,7 @@ acpi_ut_walk_aml_resources(u8 * aml, u32 length; u32 offset = 0; - ACPI_FUNCTION_TRACE("ut_walk_aml_resources"); + ACPI_FUNCTION_TRACE(ut_walk_aml_resources); /* The absolute minimum resource template is one end_tag descriptor */ @@ -597,7 +597,7 @@ acpi_ut_get_resource_end_tag(union acpi_operand_object * obj_desc, { acpi_status status; - ACPI_FUNCTION_TRACE("ut_get_resource_end_tag"); + ACPI_FUNCTION_TRACE(ut_get_resource_end_tag); /* Allow a buffer length of zero */ diff --git a/drivers/acpi/utilities/utstate.c b/drivers/acpi/utilities/utstate.c index aec5034cd97..0f5c5bb5def 100644 --- a/drivers/acpi/utilities/utstate.c +++ b/drivers/acpi/utilities/utstate.c @@ -96,7 +96,7 @@ void acpi_ut_push_generic_state(union acpi_generic_state **list_head, union acpi_generic_state *state) { - ACPI_FUNCTION_TRACE("ut_push_generic_state"); + ACPI_FUNCTION_TRACE(ut_push_generic_state); /* Push the state object onto the front of the list (stack) */ @@ -123,7 +123,7 @@ union acpi_generic_state *acpi_ut_pop_generic_state(union acpi_generic_state { union acpi_generic_state *state; - ACPI_FUNCTION_TRACE("ut_pop_generic_state"); + ACPI_FUNCTION_TRACE(ut_pop_generic_state); /* Remove the state object at the head of the list (stack) */ @@ -185,7 +185,7 @@ struct acpi_thread_state *acpi_ut_create_thread_state(void) { union acpi_generic_state *state; - ACPI_FUNCTION_TRACE("ut_create_thread_state"); + ACPI_FUNCTION_TRACE(ut_create_thread_state); /* Create the generic state object */ @@ -222,7 +222,7 @@ union acpi_generic_state *acpi_ut_create_update_state(union acpi_operand_object { union acpi_generic_state *state; - ACPI_FUNCTION_TRACE_PTR("ut_create_update_state", object); + ACPI_FUNCTION_TRACE_PTR(ut_create_update_state, object); /* Create the generic state object */ @@ -259,7 +259,7 @@ union acpi_generic_state *acpi_ut_create_pkg_state(void *internal_object, { union acpi_generic_state *state; - ACPI_FUNCTION_TRACE_PTR("ut_create_pkg_state", internal_object); + ACPI_FUNCTION_TRACE_PTR(ut_create_pkg_state, internal_object); /* Create the generic state object */ @@ -296,7 +296,7 @@ union acpi_generic_state *acpi_ut_create_control_state(void) { union acpi_generic_state *state; - ACPI_FUNCTION_TRACE("ut_create_control_state"); + ACPI_FUNCTION_TRACE(ut_create_control_state); /* Create the generic state object */ @@ -328,7 +328,7 @@ union acpi_generic_state *acpi_ut_create_control_state(void) void acpi_ut_delete_generic_state(union acpi_generic_state *state) { - ACPI_FUNCTION_TRACE("ut_delete_generic_state"); + ACPI_FUNCTION_TRACE(ut_delete_generic_state); /* Ignore null state */ diff --git a/drivers/acpi/utilities/utxface.c b/drivers/acpi/utilities/utxface.c index ac90048a8a5..3538f69c82a 100644 --- a/drivers/acpi/utilities/utxface.c +++ b/drivers/acpi/utilities/utxface.c @@ -65,7 +65,7 @@ acpi_status acpi_initialize_subsystem(void) { acpi_status status; - ACPI_FUNCTION_TRACE("acpi_initialize_subsystem"); + ACPI_FUNCTION_TRACE(acpi_initialize_subsystem); ACPI_DEBUG_EXEC(acpi_ut_init_stack_ptr_trace()); @@ -125,7 +125,7 @@ acpi_status acpi_enable_subsystem(u32 flags) { acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("acpi_enable_subsystem"); + ACPI_FUNCTION_TRACE(acpi_enable_subsystem); /* * We must initialize the hardware before we can enable ACPI. @@ -151,7 +151,7 @@ acpi_status acpi_enable_subsystem(u32 flags) status = acpi_enable(); if (ACPI_FAILURE(status)) { - ACPI_WARNING((AE_INFO, "acpi_enable failed")); + ACPI_WARNING((AE_INFO, "AcpiEnable failed")); return_ACPI_STATUS(status); } } @@ -246,7 +246,7 @@ acpi_status acpi_initialize_objects(u32 flags) { acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("acpi_initialize_objects"); + ACPI_FUNCTION_TRACE(acpi_initialize_objects); /* * Run all _REG methods @@ -257,7 +257,7 @@ acpi_status acpi_initialize_objects(u32 flags) */ if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) { ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "[Init] Executing _REG op_region methods\n")); + "[Init] Executing _REG OpRegion methods\n")); status = acpi_ev_initialize_op_regions(); if (ACPI_FAILURE(status)) { @@ -322,7 +322,7 @@ acpi_status acpi_terminate(void) { acpi_status status; - ACPI_FUNCTION_TRACE("acpi_terminate"); + ACPI_FUNCTION_TRACE(acpi_terminate); /* Terminate the AML Debugger if present */ @@ -400,7 +400,7 @@ acpi_status acpi_get_system_info(struct acpi_buffer * out_buffer) acpi_status status; u32 i; - ACPI_FUNCTION_TRACE("acpi_get_system_info"); + ACPI_FUNCTION_TRACE(acpi_get_system_info); /* Parameter validation */ @@ -451,8 +451,8 @@ acpi_status acpi_get_system_info(struct acpi_buffer * out_buffer) /* Current status of the ACPI tables, per table type */ - info_ptr->num_table_types = NUM_ACPI_TABLE_TYPES; - for (i = 0; i < NUM_ACPI_TABLE_TYPES; i++) { + info_ptr->num_table_types = ACPI_TABLE_ID_MAX + 1; + for (i = 0; i < (ACPI_TABLE_ID_MAX + 1); i++) { info_ptr->table_info[i].count = acpi_gbl_table_lists[i].count; } @@ -507,7 +507,7 @@ ACPI_EXPORT_SYMBOL(acpi_install_initialization_handler) ****************************************************************************/ acpi_status acpi_purge_cached_objects(void) { - ACPI_FUNCTION_TRACE("acpi_purge_cached_objects"); + ACPI_FUNCTION_TRACE(acpi_purge_cached_objects); (void)acpi_os_purge_cache(acpi_gbl_state_cache); (void)acpi_os_purge_cache(acpi_gbl_operand_cache); diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h index b6bba7db52d..11e72e6cdc0 100644 --- a/include/acpi/acconfig.h +++ b/include/acpi/acconfig.h @@ -63,7 +63,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20060331 +#define ACPI_CA_VERSION 0x20060421 /* * OS name, used for the _OS object. The _OS object is essentially obsolete, @@ -171,13 +171,15 @@ #define ACPI_MAX_ADDRESS_SPACE 255 /* Array sizes. Used for range checking also */ +#define ACPI_MAX_MATCH_OPCODE 5 +#if 0 #define ACPI_NUM_ACCESS_TYPES 6 #define ACPI_NUM_UPDATE_RULES 3 #define ACPI_NUM_LOCK_RULES 2 -#define ACPI_NUM_MATCH_OPS 6 -#define ACPI_NUM_OPCODES 256 #define ACPI_NUM_FIELD_NAMES 2 +#define ACPI_NUM_OPCODES 256 +#endif /* RSDP checksums */ @@ -188,10 +190,6 @@ #define ACPI_SMBUS_BUFFER_SIZE 34 -/* Number of strings associated with the _OSI reserved method */ - -#define ACPI_NUM_OSI_STRINGS 12 - /****************************************************************************** * * ACPI AML Debugger diff --git a/include/acpi/acdisasm.h b/include/acpi/acdisasm.h index 70b52ffa969..6f2556582f0 100644 --- a/include/acpi/acdisasm.h +++ b/include/acpi/acdisasm.h @@ -124,12 +124,12 @@ struct acpi_resource_tag { /* Strings used for decoding flags to ASL keywords */ -extern const char *acpi_gbl_word_decode[4]; -extern const char *acpi_gbl_irq_decode[2]; -extern const char *acpi_gbl_lock_rule[ACPI_NUM_LOCK_RULES]; -extern const char *acpi_gbl_access_types[ACPI_NUM_ACCESS_TYPES]; -extern const char *acpi_gbl_update_rules[ACPI_NUM_UPDATE_RULES]; -extern const char *acpi_gbl_match_ops[ACPI_NUM_MATCH_OPS]; +extern const char *acpi_gbl_word_decode[]; +extern const char *acpi_gbl_irq_decode[]; +extern const char *acpi_gbl_lock_rule[]; +extern const char *acpi_gbl_access_types[]; +extern const char *acpi_gbl_update_rules[]; +extern const char *acpi_gbl_match_ops[]; extern struct acpi_dmtable_info acpi_dm_table_info_asf0[]; extern struct acpi_dmtable_info acpi_dm_table_info_asf1[]; diff --git a/include/acpi/acdispat.h b/include/acpi/acdispat.h index c41a926ff31..fcf03eb4137 100644 --- a/include/acpi/acdispat.h +++ b/include/acpi/acdispat.h @@ -194,7 +194,9 @@ acpi_status acpi_ds_restart_control_method(struct acpi_walk_state *walk_state, union acpi_operand_object *return_desc); -void acpi_ds_terminate_control_method(struct acpi_walk_state *walk_state); +void +acpi_ds_terminate_control_method(union acpi_operand_object *method_desc, + struct acpi_walk_state *walk_state); acpi_status acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node, diff --git a/include/acpi/acexcep.h b/include/acpi/acexcep.h index dc768aa580e..797ca1ea521 100644 --- a/include/acpi/acexcep.h +++ b/include/acpi/acexcep.h @@ -160,8 +160,9 @@ #define AE_AML_BAD_RESOURCE_VALUE (acpi_status) (0x001F | AE_CODE_AML) #define AE_AML_CIRCULAR_REFERENCE (acpi_status) (0x0020 | AE_CODE_AML) #define AE_AML_BAD_RESOURCE_LENGTH (acpi_status) (0x0021 | AE_CODE_AML) +#define AE_AML_ILLEGAL_ADDRESS (acpi_status) (0x0022 | AE_CODE_AML) -#define AE_CODE_AML_MAX 0x0021 +#define AE_CODE_AML_MAX 0x0022 /* * Internal exceptions used for control @@ -275,7 +276,8 @@ char const *acpi_gbl_exception_names_aml[] = { "AE_AML_NO_RESOURCE_END_TAG", "AE_AML_BAD_RESOURCE_VALUE", "AE_AML_CIRCULAR_REFERENCE", - "AE_AML_BAD_RESOURCE_LENGTH" + "AE_AML_BAD_RESOURCE_LENGTH", + "AE_AML_ILLEGAL_ADDRESS" }; char const *acpi_gbl_exception_names_ctrl[] = { diff --git a/include/acpi/acglobal.h b/include/acpi/acglobal.h index 17c5b462676..5f2daf402ee 100644 --- a/include/acpi/acglobal.h +++ b/include/acpi/acglobal.h @@ -115,7 +115,7 @@ ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_enable_interpreter_slack, FALSE); * Automatically serialize ALL control methods? Default is FALSE, meaning * to use the Serialized/not_serialized method flags on a per method basis. * Only change this if the ASL code is poorly written and cannot handle - * reentrancy even though methods are marked "not_serialized". + * reentrancy even though methods are marked "NotSerialized". */ ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_all_methods_serialized, FALSE); @@ -178,8 +178,8 @@ ACPI_EXTERN u8 acpi_gbl_integer_nybble_width; /* * ACPI Table info arrays */ -extern struct acpi_table_list acpi_gbl_table_lists[NUM_ACPI_TABLE_TYPES]; -extern struct acpi_table_support acpi_gbl_table_data[NUM_ACPI_TABLE_TYPES]; +extern struct acpi_table_list acpi_gbl_table_lists[ACPI_TABLE_ID_MAX + 1]; +extern struct acpi_table_support acpi_gbl_table_data[ACPI_TABLE_ID_MAX + 1]; /* * Predefined mutex objects. This array contains the @@ -246,7 +246,6 @@ extern const char *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT]; extern const char *acpi_gbl_highest_dstate_names[4]; extern const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES]; extern const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS]; -extern const char *acpi_gbl_valid_osi_strings[ACPI_NUM_OSI_STRINGS]; /***************************************************************************** * diff --git a/include/acpi/aclocal.h b/include/acpi/aclocal.h index 99785bae59b..06a9bd0a9ce 100644 --- a/include/acpi/aclocal.h +++ b/include/acpi/aclocal.h @@ -105,14 +105,14 @@ static char *acpi_gbl_mutex_names[] = { "ACPI_MTX_Parser", "ACPI_MTX_Dispatcher", "ACPI_MTX_Tables", - "ACPI_MTX_op_regions", + "ACPI_MTX_OpRegions", "ACPI_MTX_Namespace", "ACPI_MTX_Events", "ACPI_MTX_Hardware", "ACPI_MTX_Caches", "ACPI_MTX_Memory", - "ACPI_MTX_debug_cmd_complete", - "ACPI_MTX_debug_cmd_ready", + "ACPI_MTX_DebugCmdComplete", + "ACPI_MTX_DebugCmdReady", }; #endif @@ -205,9 +205,12 @@ struct acpi_namespace_node { #define ANOBJ_DATA_WIDTH_32 0x02 /* Parent table uses 32-bit math */ #define ANOBJ_METHOD_ARG 0x04 /* Node is a method argument */ #define ANOBJ_METHOD_LOCAL 0x08 /* Node is a method local */ +#define ANOBJ_SUBTREE_HAS_INI 0x10 /* Used to optimize device initialization */ + #define ANOBJ_METHOD_NO_RETVal 0x10 /* i_aSL only: Method has no return value */ #define ANOBJ_METHOD_SOME_NO_RETVal 0x20 /* i_aSL only: Method has at least one return value */ #define ANOBJ_IS_BIT_OFFSet 0x40 /* i_aSL only: Reference is a bit offset */ +#define ANOBJ_IS_REFERENCed 0x80 /* i_aSL only: Object was referenced */ /* * ACPI Table Descriptor. One per ACPI table diff --git a/include/acpi/acmacros.h b/include/acpi/acmacros.h index 60ceed4c81b..b7547aba91b 100644 --- a/include/acpi/acmacros.h +++ b/include/acpi/acmacros.h @@ -56,6 +56,10 @@ #define ACPI_CLEAR_BIT(target,bit) ((target) &= ~(bit)) #define ACPI_MIN(a,b) (((a)<(b))?(a):(b)) +/* Size calculation */ + +#define ACPI_ARRAY_LENGTH(x) (sizeof(x) / sizeof((x)[0])) + #if ACPI_MACHINE_WIDTH == 16 /* @@ -143,7 +147,7 @@ #ifndef ACPI_MISALIGNMENT_NOT_SUPPORTED #define ACPI_COMPARE_NAME(a,b) (*ACPI_CAST_PTR (u32,(a)) == *ACPI_CAST_PTR (u32,(b))) #else -#define ACPI_COMPARE_NAME(a,b) (!ACPI_STRNCMP (ACPI_CAST_PTR (char,(a)), ACPI_CAST_PTR (char,(b)), 4)) +#define ACPI_COMPARE_NAME(a,b) (!ACPI_STRNCMP (ACPI_CAST_PTR (char,(a)), ACPI_CAST_PTR (char,(b)), ACPI_NAME_SIZE)) #endif /* @@ -522,12 +526,12 @@ #define ACPI_GET_FUNCTION_NAME _acpi_function_name /* * The Name parameter should be the procedure name as a quoted string. - * This is declared as a local string ("my_function_name") so that it can + * This is declared as a local string ("MyFunctionName") so that it can * be also used by the function exit macros below. * Note: (const char) is used to be compatible with the debug interfaces * and macros such as __FUNCTION__. */ -#define ACPI_FUNCTION_NAME(name) const char *_acpi_function_name = name; +#define ACPI_FUNCTION_NAME(name) const char *_acpi_function_name = #name; #else /* Compiler supports __FUNCTION__ (or equivalent) -- Ignore this macro */ @@ -551,7 +555,7 @@ * WARNING: These macros include a return statement. This is usually considered * bad form, but having a separate exit macro is very ugly and difficult to maintain. * One of the FUNCTION_TRACE macros above must be used in conjunction with these macros - * so that "_acpi_function_name" is defined. + * so that "_AcpiFunctionName" is defined. * * Note: the DO_WHILE0 macro is used to prevent some compilers from complaining * about these constructs. diff --git a/include/acpi/acobject.h b/include/acpi/acobject.h index d9442d346b9..1747d94084d 100644 --- a/include/acpi/acobject.h +++ b/include/acpi/acobject.h @@ -89,6 +89,7 @@ #define AOPOBJ_OBJECT_INITIALIZED 0x08 #define AOPOBJ_SETUP_COMPLETE 0x10 #define AOPOBJ_SINGLE_DATUM 0x20 +#define AOPOBJ_INVALID 0x40 /* Used if host OS won't allow an op_region address */ /****************************************************************************** * @@ -248,7 +249,7 @@ struct acpi_object_bank_field { struct acpi_object_index_field { ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO /* - * No "region_obj" pointer needed since the Index and Data registers + * No "RegionObj" pointer needed since the Index and Data registers * are each field definitions unto themselves. */ union acpi_operand_object *index_obj; /* Index register */ diff --git a/include/acpi/acoutput.h b/include/acpi/acoutput.h index 621fe23bb4f..8d5039d0b43 100644 --- a/include/acpi/acoutput.h +++ b/include/acpi/acoutput.h @@ -50,7 +50,7 @@ * component basis and a per-exception-type basis. */ -/* Component IDs are used in the global "debug_layer" */ +/* Component IDs are used in the global "DebugLayer" */ #define ACPI_UTILITIES 0x00000001 #define ACPI_HARDWARE 0x00000002 @@ -121,7 +121,7 @@ #define ACPI_LV_INTERRUPTS 0x08000000 #define ACPI_LV_VERBOSITY3 0x0F000000 | ACPI_LV_VERBOSITY2 -/* Exceptionally verbose output -- also used in the global "debug_level" */ +/* Exceptionally verbose output -- also used in the global "DebugLevel" */ #define ACPI_LV_AML_DISASSEMBLE 0x10000000 #define ACPI_LV_VERBOSE_INFO 0x20000000 @@ -135,7 +135,7 @@ */ #define ACPI_DEBUG_LEVEL(dl) (u32) dl,ACPI_DEBUG_PARAMETERS -/* Exception level -- used in the global "debug_level" */ +/* Exception level -- used in the global "DebugLevel" */ #define ACPI_DB_INIT ACPI_DEBUG_LEVEL (ACPI_LV_INIT) #define ACPI_DB_DEBUG_OBJECT ACPI_DEBUG_LEVEL (ACPI_LV_DEBUG_OBJECT) @@ -150,7 +150,7 @@ #define ACPI_DB_ERROR ACPI_DEBUG_LEVEL (ACPI_LV_ERROR) #define ACPI_DB_WARN ACPI_DEBUG_LEVEL (ACPI_LV_WARN) -/* Trace level -- also used in the global "debug_level" */ +/* Trace level -- also used in the global "DebugLevel" */ #define ACPI_DB_INIT_NAMES ACPI_DEBUG_LEVEL (ACPI_LV_INIT_NAMES) #define ACPI_DB_THREADS ACPI_DEBUG_LEVEL (ACPI_LV_THREADS) diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h index 42307d948c1..a5264fac696 100644 --- a/include/acpi/acpiosxf.h +++ b/include/acpi/acpiosxf.h @@ -212,6 +212,13 @@ acpi_os_derive_pci_id(acpi_handle rhandle, /* * Miscellaneous */ + +acpi_status acpi_os_validate_interface(char *interface); + +acpi_status +acpi_os_validate_address(u8 space_id, + acpi_physical_address address, acpi_size length); + u8 acpi_os_readable(void *pointer, acpi_size length); #ifdef ACPI_FUTURE_USAGE diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index 091dd256717..6d4e743a753 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -490,15 +490,15 @@ typedef u64 acpi_integer; */ typedef u32 acpi_table_type; -#define ACPI_TABLE_RSDP (acpi_table_type) 0 -#define ACPI_TABLE_DSDT (acpi_table_type) 1 -#define ACPI_TABLE_FADT (acpi_table_type) 2 -#define ACPI_TABLE_FACS (acpi_table_type) 3 -#define ACPI_TABLE_PSDT (acpi_table_type) 4 -#define ACPI_TABLE_SSDT (acpi_table_type) 5 -#define ACPI_TABLE_XSDT (acpi_table_type) 6 -#define ACPI_TABLE_MAX 6 -#define NUM_ACPI_TABLE_TYPES (ACPI_TABLE_MAX+1) +#define ACPI_TABLE_ID_RSDP (acpi_table_type) 0 +#define ACPI_TABLE_ID_DSDT (acpi_table_type) 1 +#define ACPI_TABLE_ID_FADT (acpi_table_type) 2 +#define ACPI_TABLE_ID_FACS (acpi_table_type) 3 +#define ACPI_TABLE_ID_PSDT (acpi_table_type) 4 +#define ACPI_TABLE_ID_SSDT (acpi_table_type) 5 +#define ACPI_TABLE_ID_XSDT (acpi_table_type) 6 +#define ACPI_TABLE_ID_MAX 6 +#define ACPI_NUM_TABLE_TYPES (ACPI_TABLE_ID_MAX+1) /* * Types associated with ACPI names and objects. The first group of @@ -829,7 +829,7 @@ struct acpi_system_info { u32 debug_level; u32 debug_layer; u32 num_table_types; - struct acpi_table_info table_info[NUM_ACPI_TABLE_TYPES]; + struct acpi_table_info table_info[ACPI_TABLE_ID_MAX + 1]; }; /* @@ -924,7 +924,8 @@ struct acpi_compatible_id_list { #define ACPI_STA_DEVICE_PRESENT 0x01 #define ACPI_STA_DEVICE_ENABLED 0x02 #define ACPI_STA_DEVICE_UI 0x04 -#define ACPI_STA_DEVICE_OK 0x08 +#define ACPI_STA_DEVICE_FUNCTIONING 0x08 +#define ACPI_STA_DEVICE_OK 0x08 /* Synonym */ #define ACPI_STA_BATTERY_PRESENT 0x10 #define ACPI_COMMON_OBJ_INFO \ diff --git a/include/acpi/acutils.h b/include/acpi/acutils.h index 115b0cbc370..ba039ea1a05 100644 --- a/include/acpi/acutils.h +++ b/include/acpi/acutils.h @@ -50,24 +50,24 @@ extern const u8 acpi_gbl_resource_aml_sizes[]; #if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER) -extern const char *acpi_gbl_BMdecode[2]; -extern const char *acpi_gbl_config_decode[4]; -extern const char *acpi_gbl_consume_decode[2]; -extern const char *acpi_gbl_DECdecode[2]; -extern const char *acpi_gbl_HEdecode[2]; -extern const char *acpi_gbl_io_decode[2]; -extern const char *acpi_gbl_LLdecode[2]; -extern const char *acpi_gbl_max_decode[2]; -extern const char *acpi_gbl_MEMdecode[4]; -extern const char *acpi_gbl_min_decode[2]; -extern const char *acpi_gbl_MTPdecode[4]; -extern const char *acpi_gbl_RNGdecode[4]; -extern const char *acpi_gbl_RWdecode[2]; -extern const char *acpi_gbl_SHRdecode[2]; -extern const char *acpi_gbl_SIZdecode[4]; -extern const char *acpi_gbl_TRSdecode[2]; -extern const char *acpi_gbl_TTPdecode[2]; -extern const char *acpi_gbl_TYPdecode[4]; +extern const char *acpi_gbl_bm_decode[]; +extern const char *acpi_gbl_config_decode[]; +extern const char *acpi_gbl_consume_decode[]; +extern const char *acpi_gbl_dec_decode[]; +extern const char *acpi_gbl_he_decode[]; +extern const char *acpi_gbl_io_decode[]; +extern const char *acpi_gbl_ll_decode[]; +extern const char *acpi_gbl_max_decode[]; +extern const char *acpi_gbl_mem_decode[]; +extern const char *acpi_gbl_min_decode[]; +extern const char *acpi_gbl_mtp_decode[]; +extern const char *acpi_gbl_rng_decode[]; +extern const char *acpi_gbl_rw_decode[]; +extern const char *acpi_gbl_shr_decode[]; +extern const char *acpi_gbl_siz_decode[]; +extern const char *acpi_gbl_trs_decode[]; +extern const char *acpi_gbl_ttp_decode[]; +extern const char *acpi_gbl_typ_decode[]; #endif /* Types for Resource descriptor entries */ @@ -81,7 +81,7 @@ typedef acpi_status(*acpi_walk_aml_callback) (u8 * aml, u32 length, u32 offset, - u8 resource_index, void *context); + u8 resource_index, void **context); typedef acpi_status(*acpi_pkg_callback) (u8 object_type, diff --git a/include/acpi/platform/acenv.h b/include/acpi/platform/acenv.h index fd189d425c7..453a469fd39 100644 --- a/include/acpi/platform/acenv.h +++ b/include/acpi/platform/acenv.h @@ -49,16 +49,18 @@ */ #ifdef ACPI_LIBRARY +/* + * Note: The non-debug version of the acpi_library does not contain any + * debug support, for minimimal size. The debug version uses ACPI_FULL_DEBUG + */ #define ACPI_USE_LOCAL_CACHE #endif -#ifdef ACPI_DUMP_APP -#ifndef MSDOS +#ifdef ACPI_ASL_COMPILER #define ACPI_DEBUG_OUTPUT -#endif #define ACPI_APPLICATION #define ACPI_DISASSEMBLER -#define ACPI_NO_METHOD_EXECUTION +#define ACPI_CONSTANT_EVAL_ONLY #define ACPI_LARGE_NAMESPACE_NODE #define ACPI_DATA_TABLE_DISASSEMBLY #endif @@ -66,19 +68,20 @@ #ifdef ACPI_EXEC_APP #undef DEBUGGER_THREADING #define DEBUGGER_THREADING DEBUGGER_SINGLE_THREADED -#define ACPI_DEBUG_OUTPUT +#define ACPI_FULL_DEBUG #define ACPI_APPLICATION #define ACPI_DEBUGGER -#define ACPI_DISASSEMBLER #define ACPI_MUTEX_DEBUG #define ACPI_DBG_TRACK_ALLOCATIONS #endif -#ifdef ACPI_ASL_COMPILER +#ifdef ACPI_DASM_APP +#ifndef MSDOS #define ACPI_DEBUG_OUTPUT +#endif #define ACPI_APPLICATION #define ACPI_DISASSEMBLER -#define ACPI_CONSTANT_EVAL_ONLY +#define ACPI_NO_METHOD_EXECUTION #define ACPI_LARGE_NAMESPACE_NODE #define ACPI_DATA_TABLE_DISASSEMBLY #endif @@ -88,6 +91,12 @@ #define ACPI_USE_LOCAL_CACHE #endif +#ifdef ACPI_FULL_DEBUG +#define ACPI_DEBUGGER +#define ACPI_DEBUG_OUTPUT +#define ACPI_DISASSEMBLER +#endif + /* * Environment configuration. The purpose of this file is to interface to the * local generation environment. -- cgit v1.2.3 From 958dd242b691f64ab4632b4903dbb1e16fee8269 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Fri, 12 May 2006 17:12:00 -0400 Subject: ACPI: ACPICA 20060512 Replaced the acpi_os_queue_for_execution() with a new interface named acpi_os_execute(). The major difference is that the new interface does not have a Priority parameter, this appeared to be useless and has been replaced by a Type parameter. The Type tells the OS what type of execution is being requested, such as global lock handler, notify handler, GPE handler, etc. This allows the host to queue and execute the request as appropriate for the request type, possibly using different work queues and different priorities for the various request types. This enables fixes for multithreading deadlock problems such as http://bugzilla.kernel.org/show_bug.cgi?id=5534 (Alexey Starikovskiy and Bob Moore) Fixed a possible memory leak associated with the support for the so-called "implicit return" ACPI extension. Reported by FreeBSD (Fiodor Suietov) http://bugzilla.kernel.org/show_bug.cgi?id=6514 Fixed a problem with the Load() operator where a table load from an operation region could overwrite an internal table buffer by up to 7 bytes and cause alignment faults on IPF systems. (With assistance from Luming Yu) Signed-off-by: Bob Moore Signed-off-by: Len Brown --- drivers/acpi/dispatcher/dsmethod.c | 23 +++++++++++++++------ drivers/acpi/dispatcher/dsmthdat.c | 6 +++--- drivers/acpi/dispatcher/dswload.c | 41 +++++++++++++++++++++++++++++++++----- drivers/acpi/events/evgpe.c | 8 ++++---- drivers/acpi/events/evmisc.c | 10 ++++------ drivers/acpi/events/evregion.c | 7 ++++--- drivers/acpi/executer/exconfig.c | 17 +++++++++++----- drivers/acpi/executer/exstorob.c | 2 +- drivers/acpi/namespace/nsaccess.c | 8 ++++---- drivers/acpi/namespace/nssearch.c | 7 ++++++- drivers/acpi/resources/rscalc.c | 4 ++-- drivers/acpi/resources/rscreate.c | 2 +- drivers/acpi/resources/rsutils.c | 5 +++-- drivers/acpi/tables/tbrsdt.c | 6 ++---- drivers/acpi/tables/tbxfroot.c | 16 +++++++-------- drivers/acpi/utilities/utglobal.c | 8 -------- include/acpi/acconfig.h | 2 +- include/acpi/acdisasm.h | 8 +++++++- include/acpi/acevents.h | 2 +- include/acpi/acglobal.h | 8 -------- include/acpi/aclocal.h | 14 ++++++++----- include/acpi/acmacros.h | 10 +++++----- include/acpi/acnamesp.h | 1 + include/acpi/acpiosxf.h | 19 +++++++++++------- include/acpi/actbl.h | 6 +++--- include/acpi/actypes.h | 6 +++--- include/acpi/amlcode.h | 6 ++++-- include/acpi/amlresrc.h | 19 ++++++++---------- 28 files changed, 161 insertions(+), 110 deletions(-) diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c index 651f2b68531..e348db0e541 100644 --- a/drivers/acpi/dispatcher/dsmethod.c +++ b/drivers/acpi/dispatcher/dsmethod.c @@ -385,6 +385,7 @@ acpi_ds_restart_control_method(struct acpi_walk_state *walk_state, union acpi_operand_object *return_desc) { acpi_status status; + int same_as_implicit_return; ACPI_FUNCTION_TRACE_PTR(ds_restart_control_method, walk_state); @@ -402,6 +403,11 @@ acpi_ds_restart_control_method(struct acpi_walk_state *walk_state, if (return_desc) { + /* Is the implicit return object the same as the return desc? */ + + same_as_implicit_return = + (walk_state->implicit_return_obj == return_desc); + /* Are we actually going to use the return value? */ if (walk_state->return_used) { @@ -422,18 +428,23 @@ acpi_ds_restart_control_method(struct acpi_walk_state *walk_state, } /* - * The following code is the - * optional support for a so-called "implicit return". Some AML code - * assumes that the last value of the method is "implicitly" returned - * to the caller. Just save the last result as the return value. + * The following code is the optional support for the so-called + * "implicit return". Some AML code assumes that the last value of the + * method is "implicitly" returned to the caller, in the absence of an + * explicit return value. + * + * Just save the last result of the method as the return value. + * * NOTE: this is optional because the ASL language does not actually * support this behavior. */ else if (!acpi_ds_do_implicit_return - (return_desc, walk_state, FALSE)) { + (return_desc, walk_state, FALSE) + || same_as_implicit_return) { /* * Delete the return value if it will not be used by the - * calling method + * calling method or remove one reference if the explicit return + * is the same as the implicit return value. */ acpi_ut_remove_reference(return_desc); } diff --git a/drivers/acpi/dispatcher/dsmthdat.c b/drivers/acpi/dispatcher/dsmthdat.c index b47c54fad86..459160ff905 100644 --- a/drivers/acpi/dispatcher/dsmthdat.c +++ b/drivers/acpi/dispatcher/dsmthdat.c @@ -336,7 +336,7 @@ acpi_ds_method_data_set_value(u16 opcode, * Increment ref count so object can't be deleted while installed. * NOTE: We do not copy the object in order to preserve the call by * reference semantics of ACPI Control Method invocation. - * (See ACPI specification 2.0_c) + * (See ACPI Specification 2.0_c) */ acpi_ut_add_reference(object); @@ -351,7 +351,7 @@ acpi_ds_method_data_set_value(u16 opcode, * FUNCTION: acpi_ds_method_data_get_value * * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP - * Index - which local_var or argument to get + * Index - Which local_var or argument to get * walk_state - Current walk state object * dest_desc - Where Arg or Local value is returned * @@ -459,7 +459,7 @@ acpi_ds_method_data_get_value(u16 opcode, * FUNCTION: acpi_ds_method_data_delete_value * * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP - * Index - which local_var or argument to delete + * Index - Which local_var or argument to delete * walk_state - Current walk state object * * RETURN: None diff --git a/drivers/acpi/dispatcher/dswload.c b/drivers/acpi/dispatcher/dswload.c index a8deb700cf3..35074399c61 100644 --- a/drivers/acpi/dispatcher/dswload.c +++ b/drivers/acpi/dispatcher/dswload.c @@ -178,12 +178,12 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, * Target of Scope() not found. Generate an External for it, and * insert the name into the namespace. */ - acpi_dm_add_to_external_list(path); + acpi_dm_add_to_external_list(path, ACPI_TYPE_DEVICE, 0); status = acpi_ns_lookup(walk_state->scope_info, path, object_type, ACPI_IMODE_LOAD_PASS1, ACPI_NS_SEARCH_PARENT, walk_state, - &(node)); + &node); } #endif if (ACPI_FAILURE(status)) { @@ -301,10 +301,41 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, status = acpi_ns_lookup(walk_state->scope_info, path, object_type, ACPI_IMODE_LOAD_PASS1, flags, walk_state, - &(node)); + &node); if (ACPI_FAILURE(status)) { - ACPI_ERROR_NAMESPACE(path, status); - return_ACPI_STATUS(status); + if (status == AE_ALREADY_EXISTS) { + + /* The name already exists in this scope */ + + if (node->flags & ANOBJ_IS_EXTERNAL) { + /* + * Allow one create on an object or segment that was + * previously declared External + */ + node->flags &= ~ANOBJ_IS_EXTERNAL; + node->type = (u8) object_type; + + /* Just retyped a node, probably will need to open a scope */ + + if (acpi_ns_opens_scope(object_type)) { + status = + acpi_ds_scope_stack_push + (node, object_type, + walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS + (status); + } + } + status = AE_OK; + } + } + + if (ACPI_FAILURE(status)) { + + ACPI_ERROR_NAMESPACE(path, status); + return_ACPI_STATUS(status); + } } break; } diff --git a/drivers/acpi/events/evgpe.c b/drivers/acpi/events/evgpe.c index 25fd12a29a2..aa179dc7801 100644 --- a/drivers/acpi/events/evgpe.c +++ b/drivers/acpi/events/evgpe.c @@ -489,7 +489,7 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) * RETURN: None * * DESCRIPTION: Perform the actual execution of a GPE control method. This - * function is called from an invocation of acpi_os_queue_for_execution + * function is called from an invocation of acpi_os_exece * (and therefore does NOT execute at interrupt level) so that * the control method itself is not executed in the context of * an interrupt handler. @@ -674,9 +674,9 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number) * Execute the method associated with the GPE * NOTE: Level-triggered GPEs are cleared after the method completes. */ - status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE, - acpi_ev_asynch_execute_gpe_method, - gpe_event_info); + status = acpi_os_execute(OSL_GPE_HANDLER, + acpi_ev_asynch_execute_gpe_method, + gpe_event_info); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Unable to queue handler for GPE[%2X] - event disabled", diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c index 97e05481aa7..24e0b8d36f3 100644 --- a/drivers/acpi/events/evmisc.c +++ b/drivers/acpi/events/evmisc.c @@ -191,9 +191,8 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node, notify_info->notify.value = (u16) notify_value; notify_info->notify.handler_obj = handler_obj; - status = acpi_os_queue_for_execution(OSD_PRIORITY_HIGH, - acpi_ev_notify_dispatch, - notify_info); + status = acpi_os_execute(OSL_NOTIFY_HANDLER, + acpi_ev_notify_dispatch, notify_info); if (ACPI_FAILURE(status)) { acpi_ut_delete_generic_state(notify_info); } @@ -346,9 +345,8 @@ static u32 acpi_ev_global_lock_handler(void *context) /* Run the Global Lock thread which will signal all waiting threads */ - status = acpi_os_queue_for_execution(OSD_PRIORITY_HIGH, - acpi_ev_global_lock_thread, - context); + status = acpi_os_execute(OSL_GLOBAL_LOCK_HANDLER, + acpi_ev_global_lock_thread, context); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Could not queue Global Lock thread")); diff --git a/drivers/acpi/events/evregion.c b/drivers/acpi/events/evregion.c index eb29e96f053..edf9d2e1dff 100644 --- a/drivers/acpi/events/evregion.c +++ b/drivers/acpi/events/evregion.c @@ -261,7 +261,8 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function) * Function - Read or Write operation * Address - Where in the space to read or write * bit_width - Field width in bits (8, 16, 32, or 64) - * Value - Pointer to in or out value + * Value - Pointer to in or out value, must be + * full 64-bit acpi_integer * * RETURN: Status * @@ -274,7 +275,7 @@ acpi_status acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, u32 function, acpi_physical_address address, - u32 bit_width, void *value) + u32 bit_width, acpi_integer * value) { acpi_status status; acpi_status status2; @@ -1007,7 +1008,7 @@ acpi_ev_execute_reg_methods(struct acpi_namespace_node *node, * * PARAMETERS: walk_namespace callback * - * DESCRIPTION: Run _REg method for region objects of the requested space_iD + * DESCRIPTION: Run _REG method for region objects of the requested space_iD * ******************************************************************************/ diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c index 9c46f333864..9ae3cb55979 100644 --- a/drivers/acpi/executer/exconfig.c +++ b/drivers/acpi/executer/exconfig.c @@ -298,6 +298,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, struct acpi_table_header *table_ptr = NULL; acpi_physical_address address; struct acpi_table_header table_header; + acpi_integer temp; u32 i; ACPI_FUNCTION_TRACE(ex_load_op); @@ -326,7 +327,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, address = obj_desc->region.address; - /* Get the table length from the table header */ + /* Get part of the table header to get the table length */ table_header.length = 0; for (i = 0; i < 8; i++) { @@ -334,11 +335,14 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, acpi_ev_address_space_dispatch(obj_desc, ACPI_READ, (acpi_physical_address) (i + address), 8, - ((u8 *) & - table_header) + i); + &temp); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } + + /* Get the one valid byte of the returned 64-bit value */ + + ACPI_CAST_PTR(u8, &table_header)[i] = (u8) temp; } /* Sanity check the table length */ @@ -361,11 +365,14 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, acpi_ev_address_space_dispatch(obj_desc, ACPI_READ, (acpi_physical_address) (i + address), 8, - ((u8 *) table_ptr + - i)); + &temp); if (ACPI_FAILURE(status)) { goto cleanup; } + + /* Get the one valid byte of the returned 64-bit value */ + + ACPI_CAST_PTR(u8, table_ptr)[i] = (u8) temp; } break; diff --git a/drivers/acpi/executer/exstorob.c b/drivers/acpi/executer/exstorob.c index 18925f5b313..99ebe5adfcd 100644 --- a/drivers/acpi/executer/exstorob.c +++ b/drivers/acpi/executer/exstorob.c @@ -103,7 +103,7 @@ acpi_ex_store_buffer_to_buffer(union acpi_operand_object *source_desc, * NOTE: ACPI versions up to 3.0 specified that the buffer must be * truncated if the string is smaller than the buffer. However, "other" * implementations of ACPI never did this and thus became the defacto - * standard. ACPi 3.0_a changes this behavior such that the buffer + * standard. ACPI 3.0_a changes this behavior such that the buffer * is no longer truncated. */ diff --git a/drivers/acpi/namespace/nsaccess.c b/drivers/acpi/namespace/nsaccess.c index 5e3f63a90fb..ba8ad569188 100644 --- a/drivers/acpi/namespace/nsaccess.c +++ b/drivers/acpi/namespace/nsaccess.c @@ -157,7 +157,7 @@ acpi_status acpi_ns_root_initialize(void) #if defined (ACPI_ASL_COMPILER) - /* save the parameter count for the i_aSL compiler */ + /* Save the parameter count for the i_aSL compiler */ new_node->value = obj_desc->method.param_count; #else @@ -311,8 +311,7 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, acpi_object_type type_to_check_for; acpi_object_type this_search_type; u32 search_parent_flag = ACPI_NS_SEARCH_PARENT; - u32 local_flags = flags & ~(ACPI_NS_ERROR_IF_FOUND | - ACPI_NS_SEARCH_PARENT); + u32 local_flags; ACPI_FUNCTION_TRACE(ns_lookup); @@ -320,8 +319,9 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, return_ACPI_STATUS(AE_BAD_PARAMETER); } - acpi_gbl_ns_lookup_count++; + local_flags = flags & ~(ACPI_NS_ERROR_IF_FOUND | ACPI_NS_SEARCH_PARENT); *return_node = ACPI_ENTRY_NOT_FOUND; + acpi_gbl_ns_lookup_count++; if (!acpi_gbl_root_node) { return_ACPI_STATUS(AE_NO_NAMESPACE); diff --git a/drivers/acpi/namespace/nssearch.c b/drivers/acpi/namespace/nssearch.c index 34ac512a2d5..d2473476afa 100644 --- a/drivers/acpi/namespace/nssearch.c +++ b/drivers/acpi/namespace/nssearch.c @@ -299,7 +299,7 @@ acpi_ns_search_and_enter(u32 target_name, if (!node || !target_name || !return_node) { ACPI_ERROR((AE_INFO, - "Null param: Node %p Name %X ReturnNode %p", + "Null parameter: Node %p Name %X ReturnNode %p", node, target_name, return_node)); return_ACPI_STATUS(AE_BAD_PARAMETER); } @@ -385,6 +385,11 @@ acpi_ns_search_and_enter(u32 target_name, if (!new_node) { return_ACPI_STATUS(AE_NO_MEMORY); } +#ifdef ACPI_ASL_COMPILER + if (flags & ACPI_NS_EXTERNAL) { + new_node->flags |= ANOBJ_IS_EXTERNAL; + } +#endif /* Install the new object into the parent's list of children */ diff --git a/drivers/acpi/resources/rscalc.c b/drivers/acpi/resources/rscalc.c index a573ad5d41d..cf87b023002 100644 --- a/drivers/acpi/resources/rscalc.c +++ b/drivers/acpi/resources/rscalc.c @@ -451,7 +451,7 @@ acpi_rs_get_list_length(u8 * aml_buffer, */ buffer_size = acpi_gbl_resource_struct_sizes[resource_index] + extra_struct_bytes; - buffer_size = ACPI_ROUND_UP_TO_NATIVE_WORD(buffer_size); + buffer_size = (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(buffer_size); *size_needed += buffer_size; @@ -579,7 +579,7 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object, /* Round up the size since each element must be aligned */ - temp_size_needed = ACPI_ROUND_UP_to_64_bIT(temp_size_needed); + temp_size_needed = ACPI_ROUND_UP_TO_64BIT(temp_size_needed); /* Point to the next union acpi_operand_object */ diff --git a/drivers/acpi/resources/rscreate.c b/drivers/acpi/resources/rscreate.c index 4c322daaf88..008058acdd3 100644 --- a/drivers/acpi/resources/rscreate.c +++ b/drivers/acpi/resources/rscreate.c @@ -335,7 +335,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, /* Now align the current length */ user_prt->length = - (u32) ACPI_ROUND_UP_to_64_bIT(user_prt->length); + (u32) ACPI_ROUND_UP_TO_64BIT(user_prt->length); /* 4) Fourth subobject: Dereference the PRT.source_index */ diff --git a/drivers/acpi/resources/rsutils.c b/drivers/acpi/resources/rsutils.c index aa98eebc9b7..0e493f2fec4 100644 --- a/drivers/acpi/resources/rsutils.c +++ b/drivers/acpi/resources/rsutils.c @@ -354,6 +354,7 @@ acpi_rs_get_resource_source(acpi_rs_length resource_length, * Zero the entire area of the buffer. */ total_length = + (u32) ACPI_STRLEN(ACPI_CAST_PTR(char, &aml_resource_source[1])) + 1; total_length = (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(total_length); @@ -528,7 +529,7 @@ acpi_rs_get_crs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer) */ status = acpi_rs_create_resource_list(obj_desc, ret_buffer); - /* on exit, we must delete the object returned by evaluate_object */ + /* On exit, we must delete the object returned by evaluate_object */ acpi_ut_remove_reference(obj_desc); return_ACPI_STATUS(status); @@ -578,7 +579,7 @@ acpi_rs_get_prs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer) */ status = acpi_rs_create_resource_list(obj_desc, ret_buffer); - /* on exit, we must delete the object returned by evaluate_object */ + /* On exit, we must delete the object returned by evaluate_object */ acpi_ut_remove_reference(obj_desc); return_ACPI_STATUS(status); diff --git a/drivers/acpi/tables/tbrsdt.c b/drivers/acpi/tables/tbrsdt.c index 9e226438a3f..494965229fa 100644 --- a/drivers/acpi/tables/tbrsdt.c +++ b/drivers/acpi/tables/tbrsdt.c @@ -196,10 +196,8 @@ acpi_status acpi_tb_validate_rsdt(struct acpi_table_header *table_ptr) ACPI_DUMP_BUFFER(acpi_gbl_RSDP, 20); ACPI_ERROR((AE_INFO, - "RSDT/XSDT signature at %X (%p) is invalid", - acpi_gbl_RSDP->rsdt_physical_address, - (void *)(acpi_native_uint) acpi_gbl_RSDP-> - rsdt_physical_address)); + "RSDT/XSDT signature at %X is invalid", + acpi_gbl_RSDP->rsdt_physical_address)); if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) { ACPI_ERROR((AE_INFO, "Looking for RSDT")); diff --git a/drivers/acpi/tables/tbxfroot.c b/drivers/acpi/tables/tbxfroot.c index 3107e741d51..da2648bbdbc 100644 --- a/drivers/acpi/tables/tbxfroot.c +++ b/drivers/acpi/tables/tbxfroot.c @@ -472,10 +472,10 @@ static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length) * * RETURN: Status, RSDP physical address * - * DESCRIPTION: search lower 1_mbyte of memory for the root system descriptor + * DESCRIPTION: Search lower 1_mbyte of memory for the root system descriptor * pointer structure. If it is found, set *RSDP to point to it. * - * NOTE1: The RSDp must be either in the first 1_k of the Extended + * NOTE1: The RSDP must be either in the first 1_k of the Extended * BIOS Data Area or between E0000 and FFFFF (From ACPI Spec.) * Only a 32-bit physical address is necessary. * @@ -525,7 +525,7 @@ acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags) if (physical_address > 0x400) { /* - * 1b) Search EBDA paragraphs (EBDa is required to be a + * 1b) Search EBDA paragraphs (EBDA is required to be a * minimum of 1_k length) */ status = acpi_os_map_memory((acpi_physical_address) @@ -550,7 +550,7 @@ acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags) /* Return the physical address */ physical_address += - ACPI_PTR_DIFF(mem_rover, table_ptr); + (u32) ACPI_PTR_DIFF(mem_rover, table_ptr); table_info->physical_address = (acpi_physical_address) physical_address; @@ -584,9 +584,9 @@ acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags) /* Return the physical address */ - physical_address = - ACPI_HI_RSDP_WINDOW_BASE + ACPI_PTR_DIFF(mem_rover, - table_ptr); + physical_address = (u32) + (ACPI_HI_RSDP_WINDOW_BASE + + ACPI_PTR_DIFF(mem_rover, table_ptr)); table_info->physical_address = (acpi_physical_address) physical_address; @@ -607,7 +607,7 @@ acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags) if (physical_address > 0x400) { /* - * 1b) Search EBDA paragraphs (EBDa is required to be a minimum of + * 1b) Search EBDA paragraphs (EBDA is required to be a minimum of * 1_k length) */ mem_rover = diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c index e666c71be0b..9450f9b5bfb 100644 --- a/drivers/acpi/utilities/utglobal.c +++ b/drivers/acpi/utilities/utglobal.c @@ -443,7 +443,6 @@ struct acpi_fixed_event_info acpi_gbl_fixed_event_info[ACPI_NUM_FIXED_EVENTS] = /* Region type decoding */ const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS] = { -/*! [Begin] no source code translation (keep these ASL Keywords as-is) */ "SystemMemory", "SystemIO", "PCI_Config", @@ -452,7 +451,6 @@ const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS] = { "CMOS", "PCIBARTarget", "DataTable" -/*! [End] no source code translation !*/ }; char *acpi_ut_get_region_name(u8 space_id) @@ -482,13 +480,11 @@ char *acpi_ut_get_region_name(u8 space_id) /* Event type decoding */ static const char *acpi_gbl_event_types[ACPI_NUM_FIXED_EVENTS] = { -/*! [Begin] no source code translation (keep these strings as-is) */ "PM_Timer", "GlobalLock", "PowerButton", "SleepButton", "RealTimeClock", -/*! [End] no source code translation !*/ }; char *acpi_ut_get_event_name(u32 event_id) @@ -526,7 +522,6 @@ static const char acpi_gbl_bad_type[] = "UNDEFINED"; /* Printable names of the ACPI object types */ static const char *acpi_gbl_ns_type_names[] = { -/*! [Begin] no source code translation (keep these strings as-is) */ /* 00 */ "Untyped", /* 01 */ "Integer", /* 02 */ "String", @@ -558,7 +553,6 @@ static const char *acpi_gbl_ns_type_names[] = { /* 28 */ "Extra", /* 29 */ "Data", /* 30 */ "Invalid" -/*! [End] no source code translation !*/ }; char *acpi_ut_get_type_name(acpi_object_type type) @@ -641,7 +635,6 @@ char *acpi_ut_get_node_name(void *object) /* Printable names of object descriptor types */ static const char *acpi_gbl_desc_type_names[] = { -/*! [Begin] no source code translation (keep these ASL Keywords as-is) */ /* 00 */ "Invalid", /* 01 */ "Cached", /* 02 */ "State-Generic", @@ -658,7 +651,6 @@ static const char *acpi_gbl_desc_type_names[] = { /* 13 */ "Parser", /* 14 */ "Operand", /* 15 */ "Node" -/*! [End] no source code translation !*/ }; char *acpi_ut_get_descriptor_name(void *object) diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h index 11e72e6cdc0..0177ed3dc80 100644 --- a/include/acpi/acconfig.h +++ b/include/acpi/acconfig.h @@ -63,7 +63,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20060421 +#define ACPI_CA_VERSION 0x20060512 /* * OS name, used for the _OS object. The _OS object is essentially obsolete, diff --git a/include/acpi/acdisasm.h b/include/acpi/acdisasm.h index 6f2556582f0..9a7d6921f53 100644 --- a/include/acpi/acdisasm.h +++ b/include/acpi/acdisasm.h @@ -54,7 +54,11 @@ struct acpi_external_list { char *path; + char *internal_path; struct acpi_external_list *next; + u32 value; + u16 length; + u8 type; }; extern struct acpi_external_list *acpi_gbl_external_list; @@ -108,6 +112,8 @@ struct acpi_dmtable_data { struct acpi_op_walk_info { u32 level; + u32 last_level; + u32 count; u32 bit_offset; u32 flags; struct acpi_walk_state *walk_state; @@ -390,7 +396,7 @@ acpi_dm_vendor_small_descriptor(union aml_resource *resource, /* * dmutils */ -void acpi_dm_add_to_external_list(char *path); +void acpi_dm_add_to_external_list(char *path, u8 type, u32 value); /* * dmrestag diff --git a/include/acpi/acevents.h b/include/acpi/acevents.h index 272bd0480ec..234142828e1 100644 --- a/include/acpi/acevents.h +++ b/include/acpi/acevents.h @@ -138,7 +138,7 @@ acpi_status acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, u32 function, acpi_physical_address address, - u32 bit_width, void *value); + u32 bit_width, acpi_integer * value); acpi_status acpi_ev_attach_region(union acpi_operand_object *handler_obj, diff --git a/include/acpi/acglobal.h b/include/acpi/acglobal.h index 5f2daf402ee..9297f293b2c 100644 --- a/include/acpi/acglobal.h +++ b/include/acpi/acglobal.h @@ -290,14 +290,6 @@ ACPI_EXTERN struct acpi_thread_state *acpi_gbl_current_walk_list; ACPI_EXTERN u8 acpi_gbl_cm_single_step; -/***************************************************************************** - * - * Parser globals - * - ****************************************************************************/ - -ACPI_EXTERN union acpi_parse_object *acpi_gbl_parsed_namespace_root; - /***************************************************************************** * * Hardware globals diff --git a/include/acpi/aclocal.h b/include/acpi/aclocal.h index 06a9bd0a9ce..98c697e3c48 100644 --- a/include/acpi/aclocal.h +++ b/include/acpi/aclocal.h @@ -207,10 +207,11 @@ struct acpi_namespace_node { #define ANOBJ_METHOD_LOCAL 0x08 /* Node is a method local */ #define ANOBJ_SUBTREE_HAS_INI 0x10 /* Used to optimize device initialization */ -#define ANOBJ_METHOD_NO_RETVal 0x10 /* i_aSL only: Method has no return value */ -#define ANOBJ_METHOD_SOME_NO_RETVal 0x20 /* i_aSL only: Method has at least one return value */ -#define ANOBJ_IS_BIT_OFFSet 0x40 /* i_aSL only: Reference is a bit offset */ -#define ANOBJ_IS_REFERENCed 0x80 /* i_aSL only: Object was referenced */ +#define ANOBJ_IS_EXTERNAL 0x08 /* i_aSL only: This object created via External() */ +#define ANOBJ_METHOD_NO_RETVAL 0x10 /* i_aSL only: Method has no return value */ +#define ANOBJ_METHOD_SOME_NO_RETVAL 0x20 /* i_aSL only: Method has at least one return value */ +#define ANOBJ_IS_BIT_OFFSET 0x40 /* i_aSL only: Reference is a bit offset */ +#define ANOBJ_IS_REFERENCED 0x80 /* i_aSL only: Object was referenced */ /* * ACPI Table Descriptor. One per ACPI table @@ -595,6 +596,9 @@ union acpi_parse_value { #define ACPI_DASM_UNICODE 0x03 #define ACPI_DASM_EISAID 0x04 #define ACPI_DASM_MATCHOP 0x05 +#define ACPI_DASM_LNOT_PREFIX 0x06 +#define ACPI_DASM_LNOT_SUFFIX 0x07 +#define ACPI_DASM_IGNORE 0x08 /* * Generic operation (for example: If, While, Store) @@ -613,7 +617,7 @@ struct acpi_parse_obj_named { u32 name; /* 4-byte name or zero if no name */ }; -/* this version is used by the i_aSL compiler only */ +/* This version is used by the i_aSL compiler only */ #define ACPI_MAX_PARSEOP_NAME 20 diff --git a/include/acpi/acmacros.h b/include/acpi/acmacros.h index b7547aba91b..38f9aa4bef0 100644 --- a/include/acpi/acmacros.h +++ b/include/acpi/acmacros.h @@ -103,7 +103,7 @@ * printf() format helpers */ -/* Split 64-bit integer into two 32-bit values. Use with %8.8X%8.8X */ +/* Split 64-bit integer into two 32-bit values. Use with %8.8_x%8.8_x */ #define ACPI_FORMAT_UINT64(i) ACPI_HIDWORD(i),ACPI_LODWORD(i) @@ -359,12 +359,12 @@ /* Note: sizeof(acpi_native_uint) evaluates to either 2, 4, or 8 */ -#define ACPI_ROUND_DOWN_to_32_bIT(a) ACPI_ROUND_DOWN(a,4) -#define ACPI_ROUND_DOWN_to_64_bIT(a) ACPI_ROUND_DOWN(a,8) +#define ACPI_ROUND_DOWN_TO_32BIT(a) ACPI_ROUND_DOWN(a,4) +#define ACPI_ROUND_DOWN_TO_64BIT(a) ACPI_ROUND_DOWN(a,8) #define ACPI_ROUND_DOWN_TO_NATIVE_WORD(a) ACPI_ROUND_DOWN(a,sizeof(acpi_native_uint)) -#define ACPI_ROUND_UP_to_32_bIT(a) ACPI_ROUND_UP(a,4) -#define ACPI_ROUND_UP_to_64_bIT(a) ACPI_ROUND_UP(a,8) +#define ACPI_ROUND_UP_TO_32BIT(a) ACPI_ROUND_UP(a,4) +#define ACPI_ROUND_UP_TO_64BIT(a) ACPI_ROUND_UP(a,8) #define ACPI_ROUND_UP_TO_NATIVE_WORD(a) ACPI_ROUND_UP(a,sizeof(acpi_native_uint)) #define ACPI_ROUND_BITS_UP_TO_BYTES(a) ACPI_DIV_8((a) + 7) diff --git a/include/acpi/acnamesp.h b/include/acpi/acnamesp.h index 132d64af24f..2ef8540c0fb 100644 --- a/include/acpi/acnamesp.h +++ b/include/acpi/acnamesp.h @@ -64,6 +64,7 @@ #define ACPI_NS_NO_PEER_SEARCH 0x04 #define ACPI_NS_ERROR_IF_FOUND 0x08 #define ACPI_NS_PREFIX_IS_SCOPE 0x10 +#define ACPI_NS_EXTERNAL 0x20 #define ACPI_NS_WALK_UNLOCK TRUE #define ACPI_NS_WALK_NO_UNLOCK FALSE diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h index a5264fac696..982e7ea177e 100644 --- a/include/acpi/acpiosxf.h +++ b/include/acpi/acpiosxf.h @@ -50,12 +50,17 @@ #include "platform/acenv.h" #include "actypes.h" -/* Priorities for acpi_os_queue_for_execution */ +/* Types for acpi_os_execute */ -#define OSD_PRIORITY_GPE 1 -#define OSD_PRIORITY_HIGH 2 -#define OSD_PRIORITY_MED 3 -#define OSD_PRIORITY_LO 4 +typedef enum { + OSL_GLOBAL_LOCK_HANDLER, + OSL_NOTIFY_HANDLER, + OSL_GPE_HANDLER, + OSL_DEBUGGER_THREAD, + OSL_EC_POLL_HANDLER, + OSL_EC_BURST_HANDLER, + +} acpi_execute_type; #define ACPI_NO_UNIT_LIMIT ((u32) -1) #define ACPI_MUTEX_SEM 1 @@ -164,8 +169,8 @@ acpi_os_remove_interrupt_handler(u32 gsi, acpi_osd_handler service_routine); acpi_thread_id acpi_os_get_thread_id(void); acpi_status -acpi_os_queue_for_execution(u32 priority, - acpi_osd_exec_callback function, void *context); +acpi_os_execute(acpi_execute_type type, + acpi_osd_exec_callback function, void *context); void acpi_os_wait_events_complete(void *context); diff --git a/include/acpi/actbl.h b/include/acpi/actbl.h index e1a40135f70..b125ceed9cb 100644 --- a/include/acpi/actbl.h +++ b/include/acpi/actbl.h @@ -206,8 +206,8 @@ struct acpi_common_facs { u32 V1_pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */ \ u32 V1_gpe0_blk; /* Port addr of General Purpose acpi_event 0 Reg Blk */ \ u32 V1_gpe1_blk; /* Port addr of General Purpose acpi_event 1 Reg Blk */ \ - u8 pm1_evt_len; /* Byte length of ports at pm1_x_evt_blk */ \ - u8 pm1_cnt_len; /* Byte length of ports at pm1_x_cnt_blk */ \ + u8 pm1_evt_len; /* Byte Length of ports at pm1_x_evt_blk */ \ + u8 pm1_cnt_len; /* Byte Length of ports at pm1_x_cnt_blk */ \ u8 pm2_cnt_len; /* Byte Length of ports at pm2_cnt_blk */ \ u8 pm_tm_len; /* Byte Length of ports at pm_tm_blk */ \ u8 gpe0_blk_len; /* Byte Length of ports at gpe0_blk */ \ @@ -252,7 +252,7 @@ struct fadt_descriptor { u8 S4rtc_sts_valid:1; /* 16: Contents of RTC_STS valid after S4 wake (ACPI 3.0) */ u8 remote_power_on_capable:1; /* 17: System is compatible with remote power on (ACPI 3.0) */ u8 force_apic_cluster_model:1; /* 18: All local APICs must use cluster model (ACPI 3.0) */ - u8 force_apic_physical_destination_mode:1; /* 19: all local x_aPICs must use physical dest mode (ACPI 3.0) */ + u8 force_apic_physical_destination_mode:1; /* 19: All local x_aPICs must use physical dest mode (ACPI 3.0) */ u8:4; /* 20-23: Reserved, must be zero */ u8 reserved3; /* 24-31: Reserved, must be zero */ diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index 6d4e743a753..77cf1236b05 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -971,7 +971,7 @@ struct acpi_mem_space_context { * Definitions for Resource Attributes */ typedef u16 acpi_rs_length; /* Resource Length field is fixed at 16 bits */ -typedef u32 acpi_rsdesc_size; /* Max Resource Descriptor size is (length+3) = (64_k-1)+3 */ +typedef u32 acpi_rsdesc_size; /* Max Resource Descriptor size is (Length+3) = (64_k-1)+3 */ /* * Memory Attributes @@ -986,8 +986,8 @@ typedef u32 acpi_rsdesc_size; /* Max Resource Descriptor size is (length+3) = (6 /* * IO Attributes - * The ISA Io ranges are: n000-n0_ffh, n400-n4_ffh, n800-n8_ffh, n_c00-n_cFFh. - * The non-ISA Io ranges are: n100-n3_ffh, n500-n7_ffh, n900-n_bFfh, n_cd0-n_fFFh. + * The ISA IO ranges are: n000-n0_fFh, n400-n4_fFh, n800-n8_fFh, n_c00-n_cFFh. + * The non-ISA IO ranges are: n100-n3_fFh, n500-n7_fFh, n900-n_bFFh, n_cd0-n_fFFh. */ #define ACPI_NON_ISA_ONLY_RANGES (u8) 0x01 #define ACPI_ISA_ONLY_RANGES (u8) 0x02 diff --git a/include/acpi/amlcode.h b/include/acpi/amlcode.h index 37964a59aef..cf18426a87b 100644 --- a/include/acpi/amlcode.h +++ b/include/acpi/amlcode.h @@ -180,8 +180,10 @@ #define AML_BANK_FIELD_OP (u16) 0x5b87 #define AML_DATA_REGION_OP (u16) 0x5b88 /* ACPI 2.0 */ -/* Bogus opcodes (they are actually two separate opcodes) */ - +/* + * Combination opcodes (actually two one-byte opcodes) + * Used by the disassembler and i_aSL compiler + */ #define AML_LGREATEREQUAL_OP (u16) 0x9295 #define AML_LLESSEQUAL_OP (u16) 0x9294 #define AML_LNOTEQUAL_OP (u16) 0x9293 diff --git a/include/acpi/amlresrc.h b/include/acpi/amlresrc.h index 64736860bdd..be03818af9d 100644 --- a/include/acpi/amlresrc.h +++ b/include/acpi/amlresrc.h @@ -47,8 +47,6 @@ #ifndef __AMLRESRC_H #define __AMLRESRC_H -/*! [Begin] no source code translation */ - /* * Resource descriptor tags, as defined in the ACPI specification. * Used to symbolically reference fields within a descriptor. @@ -65,12 +63,12 @@ #define ACPI_RESTAG_DMATYPE "_TYP" /* Compatible(0), A(1), B(2), F(3) */ #define ACPI_RESTAG_GRANULARITY "_GRA" #define ACPI_RESTAG_INTERRUPT "_INT" -#define ACPI_RESTAG_INTERRUPTLEVEL "_LL_" /* ActiveLo(1), ActiveHi(0) */ -#define ACPI_RESTAG_INTERRUPTSHARE "_SHR" /* Shareable(1), NoShare(0) */ +#define ACPI_RESTAG_INTERRUPTLEVEL "_LL_" /* active_lo(1), active_hi(0) */ +#define ACPI_RESTAG_INTERRUPTSHARE "_SHR" /* Shareable(1), no_share(0) */ #define ACPI_RESTAG_INTERRUPTTYPE "_HE_" /* Edge(1), Level(0) */ #define ACPI_RESTAG_LENGTH "_LEN" #define ACPI_RESTAG_MEMATTRIBUTES "_MTP" /* Memory(0), Reserved(1), ACPI(2), NVS(3) */ -#define ACPI_RESTAG_MEMTYPE "_MEM" /* NonCache(0), Cacheable(1) Cache+combine(2), Cache+prefetch(3) */ +#define ACPI_RESTAG_MEMTYPE "_MEM" /* non_cache(0), Cacheable(1) Cache+combine(2), Cache+prefetch(3) */ #define ACPI_RESTAG_MAXADDR "_MAX" #define ACPI_RESTAG_MINADDR "_MIN" #define ACPI_RESTAG_MAXTYPE "_MAF" @@ -78,12 +76,11 @@ #define ACPI_RESTAG_REGISTERBITOFFSET "_RBO" #define ACPI_RESTAG_REGISTERBITWIDTH "_RBW" #define ACPI_RESTAG_RANGETYPE "_RNG" -#define ACPI_RESTAG_READWRITETYPE "_RW_" /* ReadOnly(0), Writeable (1) */ +#define ACPI_RESTAG_READWRITETYPE "_RW_" /* read_only(0), Writeable (1) */ #define ACPI_RESTAG_TRANSLATION "_TRA" #define ACPI_RESTAG_TRANSTYPE "_TRS" /* Sparse(1), Dense(0) */ #define ACPI_RESTAG_TYPE "_TTP" /* Translation(1), Static (0) */ -#define ACPI_RESTAG_XFERTYPE "_SIZ" /* 8(0), 8And16(1), 16(2) */ -/*! [End] no source code translation !*/ +#define ACPI_RESTAG_XFERTYPE "_SIZ" /* 8(0), 8_and16(1), 16(2) */ /* Default sizes for "small" resource descriptors */ @@ -306,9 +303,9 @@ union aml_resource { /* Utility overlays */ struct aml_resource_address address; - u32 u32_item; - u16 u16_item; - u8 U8item; + u32 dword_item; + u16 word_item; + u8 byte_item; }; #endif -- cgit v1.2.3 From b8d35192c55fb055792ff0641408eaaec7c88988 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Fri, 5 May 2006 03:23:00 -0400 Subject: ACPI: execute Notify() handlers on new thread http://bugzilla.kernel.org/show_bug.cgi?id=5534 Thanks to Peter Wainwright for isolating the issue. Thanks to Andi Kleen and Bob Moore for feedback. Thanks to Richard Mace and others for testing. Updates by Konstantin Karasyov. Signed-off-by: Konstantin Karasyov Signed-off-by: Len Brown --- drivers/acpi/ec.c | 5 ++-- drivers/acpi/osl.c | 80 +++++++++++++++++++++++++++++++++----------------- drivers/acpi/thermal.c | 3 +- 3 files changed, 56 insertions(+), 32 deletions(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 79b09d76c18..1e3222762bf 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -763,8 +763,7 @@ static u32 acpi_ec_gpe_poll_handler(void *data) acpi_disable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR); - status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE, - acpi_ec_gpe_query, ec); + status = acpi_os_execute(OSL_EC_POLL_HANDLER, acpi_ec_gpe_query, ec); if (status == AE_OK) return ACPI_INTERRUPT_HANDLED; @@ -799,7 +798,7 @@ static u32 acpi_ec_gpe_intr_handler(void *data) if (value & ACPI_EC_FLAG_SCI) { atomic_add(1, &ec->intr.pending_gpe); - status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE, + status = acpi_os_execute(OSL_EC_BURST_HANDLER, acpi_ec_gpe_query, ec); return status == AE_OK ? ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 109c3f8ae7d..e80ca4730a4 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -600,23 +601,41 @@ static void acpi_os_execute_deferred(void *context) return_VOID; } -acpi_status -acpi_os_queue_for_execution(u32 priority, +static int acpi_os_execute_thread(void *context) +{ + struct acpi_os_dpc *dpc = (struct acpi_os_dpc *)context; + if (dpc) { + dpc->function(dpc->context); + kfree(dpc); + } + do_exit(0); +} + +/******************************************************************************* + * + * FUNCTION: acpi_os_execute + * + * PARAMETERS: Type - Type of the callback + * Function - Function to be executed + * Context - Function parameters + * + * RETURN: Status + * + * DESCRIPTION: Depending on type, either queues function for deferred execution or + * immediately executes function on a separate thread. + * + ******************************************************************************/ + +acpi_status acpi_os_execute(acpi_execute_type type, acpi_osd_exec_callback function, void *context) { acpi_status status = AE_OK; struct acpi_os_dpc *dpc; struct work_struct *task; - - ACPI_FUNCTION_TRACE("os_queue_for_execution"); - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Scheduling function [%p(%p)] for deferred execution.\n", - function, context)); + struct task_struct *p; if (!function) - return_ACPI_STATUS(AE_BAD_PARAMETER); - + return AE_BAD_PARAMETER; /* * Allocate/initialize DPC structure. Note that this memory will be * freed by the callee. The kernel handles the tq_struct list in a @@ -627,30 +646,37 @@ acpi_os_queue_for_execution(u32 priority, * We can save time and code by allocating the DPC and tq_structs * from the same memory. */ - - dpc = - kmalloc(sizeof(struct acpi_os_dpc) + sizeof(struct work_struct), - GFP_ATOMIC); + if (type == OSL_NOTIFY_HANDLER) { + dpc = kmalloc(sizeof(struct acpi_os_dpc), GFP_KERNEL); + } else { + dpc = kmalloc(sizeof(struct acpi_os_dpc) + + sizeof(struct work_struct), GFP_ATOMIC); + } if (!dpc) - return_ACPI_STATUS(AE_NO_MEMORY); - + return AE_NO_MEMORY; dpc->function = function; dpc->context = context; - task = (void *)(dpc + 1); - INIT_WORK(task, acpi_os_execute_deferred, (void *)dpc); - - if (!queue_work(kacpid_wq, task)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Call to queue_work() failed.\n")); - kfree(dpc); - status = AE_ERROR; + if (type == OSL_NOTIFY_HANDLER) { + p = kthread_create(acpi_os_execute_thread, dpc, "kacpid_notify"); + if (!IS_ERR(p)) { + wake_up_process(p); + } else { + status = AE_NO_MEMORY; + kfree(dpc); + } + } else { + task = (void *)(dpc + 1); + INIT_WORK(task, acpi_os_execute_deferred, (void *)dpc); + if (!queue_work(kacpid_wq, task)) { + status = AE_ERROR; + kfree(dpc); + } } - - return_ACPI_STATUS(status); + return status; } -EXPORT_SYMBOL(acpi_os_queue_for_execution); +EXPORT_SYMBOL(acpi_os_execute); void acpi_os_wait_events_complete(void *context) { diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 19f3ea48475..fba9c230a84 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -684,8 +684,7 @@ static void acpi_thermal_run(unsigned long data) { struct acpi_thermal *tz = (struct acpi_thermal *)data; if (!tz->zombie) - acpi_os_queue_for_execution(OSD_PRIORITY_GPE, - acpi_thermal_check, (void *)data); + acpi_os_execute(OSL_GPE_HANDLER, acpi_thermal_check, (void *)data); } static void acpi_thermal_check(void *data) -- cgit v1.2.3 From 4119532c95547821dbe72d6916dfa1b2148475b3 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Fri, 26 May 2006 16:36:00 -0400 Subject: ACPI: ACPICA 20060526 Restructured, flattened, and simplified the internal interfaces for namespace object evaluation - resulting in smaller code, less CPU stack use, and fewer interfaces. (With assistance from Mikhail Kouzmich) Fixed a problem with the CopyObject operator where the first parameter was not typed correctly for the parser, interpreter, compiler, and disassembler. Caused various errors and unexpected behavior. Fixed a problem where a ShiftLeft or ShiftRight of more than 64 bits produced incorrect results with some C compilers. Since the behavior of C compilers when the shift value is larger than the datatype width is apparently not well defined, the interpreter now detects this condition and simply returns zero as expected in all such cases. (BZ 395) Fixed problem reports (Valery Podrezov) integrated: - Update String-to-Integer conversion to match ACPI 3.0A spec http://bugzilla.kernel.org/show_bug.cgi?id=5329 Allow interpreter to handle nested method declarations http://bugzilla.kernel.org/show_bug.cgi?id=5361 Fixed problem reports (Fiodor Suietov) integrated: - acpi_terminate() doesn't free debug memory allocation list objects (BZ 355) - After Core Subsystem shutdown, acpi_subsystem_status() returns AE_OK (BZ 356) - acpi_os_unmap_memory() for RSDP can be invoked inconsistently (BZ 357) - Resource Manager should return AE_TYPE for non-device objects (BZ 358) - Incomplete cleanup branch in AcpiNsEvaluateRelative (BZ 359) - Use acpi_os_free() instead of ACPI_FREE in acpi_rs_set_srs_method_data (BZ 360) - Incomplete cleanup branch in acpi_ps_parse_aml (BZ 361) - Incomplete cleanup branch in acpi_ds_delete_walk_state (BZ 362) - acpi_get_table_header returns AE_NO_ACPI_TABLES until DSDT is loaded (BZ 365) - Status of the Global Initialization Handler call not used (BZ 366) - Incorrect object parameter to Global Initialization Handler (BZ 367) Signed-off-by: Bob Moore Signed-off-by: Len Brown --- drivers/acpi/dispatcher/dsmethod.c | 20 +- drivers/acpi/dispatcher/dswexec.c | 2 +- drivers/acpi/dispatcher/dswstate.c | 5 +- drivers/acpi/events/evgpe.c | 39 ++- drivers/acpi/events/evmisc.c | 18 +- drivers/acpi/events/evregion.c | 65 +++-- drivers/acpi/events/evrgnini.c | 5 +- drivers/acpi/executer/exconfig.c | 10 +- drivers/acpi/executer/exfldio.c | 24 +- drivers/acpi/executer/exmisc.c | 14 ++ drivers/acpi/executer/exoparg1.c | 18 +- drivers/acpi/executer/exregion.c | 15 +- drivers/acpi/hardware/hwregs.c | 51 ++-- drivers/acpi/namespace/nsaccess.c | 6 +- drivers/acpi/namespace/nseval.c | 485 +++++++++---------------------------- drivers/acpi/namespace/nsinit.c | 57 +++-- drivers/acpi/namespace/nssearch.c | 82 ++++--- drivers/acpi/namespace/nsutils.c | 63 +++-- drivers/acpi/namespace/nsxfeval.c | 119 +++++---- drivers/acpi/namespace/nsxfname.c | 5 +- drivers/acpi/parser/psparse.c | 1 + drivers/acpi/parser/psxface.c | 37 +-- drivers/acpi/resources/rsutils.c | 95 ++++---- drivers/acpi/resources/rsxface.c | 368 ++++++++++++++++------------ drivers/acpi/tables/tbget.c | 40 +-- drivers/acpi/tables/tbrsdt.c | 11 +- drivers/acpi/utilities/utalloc.c | 51 ++-- drivers/acpi/utilities/utdelete.c | 24 +- drivers/acpi/utilities/uteval.c | 45 ++-- drivers/acpi/utilities/utinit.c | 8 +- drivers/acpi/utilities/utmisc.c | 109 ++++++--- include/acpi/acconfig.h | 2 +- include/acpi/acdispat.h | 2 +- include/acpi/acnamesp.h | 22 +- include/acpi/acopcode.h | 2 +- include/acpi/acparser.h | 2 +- include/acpi/acpiosxf.h | 11 +- include/acpi/acresrc.h | 15 +- include/acpi/acstruct.h | 90 ++++--- 39 files changed, 981 insertions(+), 1057 deletions(-) diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c index e348db0e541..21f05998627 100644 --- a/drivers/acpi/dispatcher/dsmethod.c +++ b/drivers/acpi/dispatcher/dsmethod.c @@ -231,7 +231,7 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread, struct acpi_namespace_node *method_node; struct acpi_walk_state *next_walk_state = NULL; union acpi_operand_object *obj_desc; - struct acpi_parameter_info info; + struct acpi_evaluate_info *info; u32 i; ACPI_FUNCTION_TRACE_PTR(ds_call_control_method, this_walk_state); @@ -319,12 +319,24 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread, */ this_walk_state->operands[this_walk_state->num_operands] = NULL; - info.parameters = &this_walk_state->operands[0]; - info.parameter_type = ACPI_PARAM_ARGS; + /* + * Allocate and initialize the evaluation information block + * TBD: this is somewhat inefficient, should change interface to + * ds_init_aml_walk. For now, keeps this struct off the CPU stack + */ + info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); + if (!info) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + info->parameters = &this_walk_state->operands[0]; + info->parameter_type = ACPI_PARAM_ARGS; status = acpi_ds_init_aml_walk(next_walk_state, NULL, method_node, obj_desc->method.aml_start, - obj_desc->method.aml_length, &info, 3); + obj_desc->method.aml_length, info, 3); + + ACPI_FREE(info); if (ACPI_FAILURE(status)) { goto cleanup; } diff --git a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c index 8afb20384e9..3acbd9145d7 100644 --- a/drivers/acpi/dispatcher/dswexec.c +++ b/drivers/acpi/dispatcher/dswexec.c @@ -295,7 +295,7 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state, case AML_CLASS_NAMED_OBJECT: - if (walk_state->walk_type == ACPI_WALK_METHOD) { + if (walk_state->walk_type & ACPI_WALK_METHOD) { /* * Found a named object declaration during method execution; * we must enter this object into the namespace. The created diff --git a/drivers/acpi/dispatcher/dswstate.c b/drivers/acpi/dispatcher/dswstate.c index 82c1e219bf1..7817e552267 100644 --- a/drivers/acpi/dispatcher/dswstate.c +++ b/drivers/acpi/dispatcher/dswstate.c @@ -703,7 +703,7 @@ acpi_ds_init_aml_walk(struct acpi_walk_state *walk_state, struct acpi_namespace_node *method_node, u8 * aml_start, u32 aml_length, - struct acpi_parameter_info *info, u8 pass_number) + struct acpi_evaluate_info *info, u8 pass_number) { acpi_status status; struct acpi_parse_state *parser_state = &walk_state->parser_state; @@ -825,9 +825,12 @@ void acpi_ds_delete_walk_state(struct acpi_walk_state *walk_state) return; } + /* There should not be any open scopes */ + if (walk_state->parser_state.scope) { ACPI_ERROR((AE_INFO, "%p walk still has a scope list", walk_state)); + acpi_ps_cleanup_scope(&walk_state->parser_state); } /* Always must free any linked control states */ diff --git a/drivers/acpi/events/evgpe.c b/drivers/acpi/events/evgpe.c index aa179dc7801..23fe53ba737 100644 --- a/drivers/acpi/events/evgpe.c +++ b/drivers/acpi/events/evgpe.c @@ -488,9 +488,9 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) * * RETURN: None * - * DESCRIPTION: Perform the actual execution of a GPE control method. This - * function is called from an invocation of acpi_os_exece - * (and therefore does NOT execute at interrupt level) so that + * DESCRIPTION: Perform the actual execution of a GPE control method. This + * function is called from an invocation of acpi_os_execute and + * therefore does NOT execute at interrupt level - so that * the control method itself is not executed in the context of * an interrupt handler. * @@ -502,7 +502,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) u32 gpe_number = 0; acpi_status status; struct acpi_gpe_event_info local_gpe_event_info; - struct acpi_parameter_info info; + struct acpi_evaluate_info *info; ACPI_FUNCTION_TRACE(ev_asynch_execute_gpe_method); @@ -540,16 +540,29 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) */ if ((local_gpe_event_info.flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_METHOD) { - /* - * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the _Lxx/_Exx - * control method that corresponds to this GPE - */ - info.node = local_gpe_event_info.dispatch.method_node; - info.parameters = - ACPI_CAST_PTR(union acpi_operand_object *, gpe_event_info); - info.parameter_type = ACPI_PARAM_GPE; - status = acpi_ns_evaluate_by_handle(&info); + /* Allocate the evaluation information block */ + + info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); + if (!info) { + status = AE_NO_MEMORY; + } else { + /* + * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the _Lxx/_Exx + * control method that corresponds to this GPE + */ + info->prefix_node = + local_gpe_event_info.dispatch.method_node; + info->parameters = + ACPI_CAST_PTR(union acpi_operand_object *, + gpe_event_info); + info->parameter_type = ACPI_PARAM_GPE; + info->flags = ACPI_IGNORE_RETURN_VALUE; + + status = acpi_ns_evaluate(info); + ACPI_FREE(info); + } + if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "While evaluating method [%4.4s] for GPE[%2X]", diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c index 24e0b8d36f3..6eef4efddcf 100644 --- a/drivers/acpi/events/evmisc.c +++ b/drivers/acpi/events/evmisc.c @@ -49,12 +49,13 @@ #define _COMPONENT ACPI_EVENTS ACPI_MODULE_NAME("evmisc") +/* Names for Notify() values, used for debug output */ #ifdef ACPI_DEBUG_OUTPUT static const char *acpi_notify_value_names[] = { "Bus Check", "Device Check", "Device Wake", - "Eject request", + "Eject Request", "Device Check Light", "Frequency Mismatch", "Bus Mode Mismatch", @@ -191,8 +192,9 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node, notify_info->notify.value = (u16) notify_value; notify_info->notify.handler_obj = handler_obj; - status = acpi_os_execute(OSL_NOTIFY_HANDLER, - acpi_ev_notify_dispatch, notify_info); + status = + acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_notify_dispatch, + notify_info); if (ACPI_FAILURE(status)) { acpi_ut_delete_generic_state(notify_info); } @@ -345,8 +347,9 @@ static u32 acpi_ev_global_lock_handler(void *context) /* Run the Global Lock thread which will signal all waiting threads */ - status = acpi_os_execute(OSL_GLOBAL_LOCK_HANDLER, - acpi_ev_global_lock_thread, context); + status = + acpi_os_execute(OSL_GLOBAL_LOCK_HANDLER, + acpi_ev_global_lock_thread, context); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Could not queue Global Lock thread")); @@ -462,8 +465,9 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout) * Acquire the global lock semaphore first. * Since this wait will block, we must release the interpreter */ - status = acpi_ex_system_wait_semaphore(acpi_gbl_global_lock_semaphore, - timeout); + status = + acpi_ex_system_wait_semaphore(acpi_gbl_global_lock_semaphore, + timeout); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/events/evregion.c b/drivers/acpi/events/evregion.c index edf9d2e1dff..094a17e4c86 100644 --- a/drivers/acpi/events/evregion.c +++ b/drivers/acpi/events/evregion.c @@ -193,8 +193,8 @@ acpi_status acpi_ev_initialize_op_regions(void) acpi_status acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function) { - struct acpi_parameter_info info; - union acpi_operand_object *params[3]; + struct acpi_evaluate_info *info; + union acpi_operand_object *args[3]; union acpi_operand_object *region_obj2; acpi_status status; @@ -209,47 +209,60 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function) return_ACPI_STATUS(AE_OK); } + /* Allocate and initialize the evaluation information block */ + + info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); + if (!info) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + info->prefix_node = region_obj2->extra.method_REG; + info->pathname = NULL; + info->parameters = args; + info->parameter_type = ACPI_PARAM_ARGS; + info->flags = ACPI_IGNORE_RETURN_VALUE; + /* * The _REG method has two arguments: * - * Arg0, Integer: Operation region space ID - * Same value as region_obj->Region.space_id - * Arg1, Integer: connection status - * 1 for connecting the handler, - * 0 for disconnecting the handler - * Passed as a parameter + * Arg0 - Integer: + * Operation region space ID Same value as region_obj->Region.space_id + * + * Arg1 - Integer: + * connection status 1 for connecting the handler, 0 for disconnecting + * the handler (Passed as a parameter) */ - params[0] = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); - if (!params[0]) { - return_ACPI_STATUS(AE_NO_MEMORY); + args[0] = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); + if (!args[0]) { + status = AE_NO_MEMORY; + goto cleanup1; } - params[1] = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); - if (!params[1]) { + args[1] = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); + if (!args[1]) { status = AE_NO_MEMORY; - goto cleanup; + goto cleanup2; } /* Setup the parameter objects */ - params[0]->integer.value = region_obj->region.space_id; - params[1]->integer.value = function; - params[2] = NULL; - - info.node = region_obj2->extra.method_REG; - info.parameters = params; - info.parameter_type = ACPI_PARAM_ARGS; + args[0]->integer.value = region_obj->region.space_id; + args[1]->integer.value = function; + args[2] = NULL; /* Execute the method, no return value */ ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname - (ACPI_TYPE_METHOD, info.node, NULL)); - status = acpi_ns_evaluate_by_handle(&info); + (ACPI_TYPE_METHOD, info->prefix_node, NULL)); + + status = acpi_ns_evaluate(info); + acpi_ut_remove_reference(args[1]); - acpi_ut_remove_reference(params[1]); + cleanup2: + acpi_ut_remove_reference(args[0]); - cleanup: - acpi_ut_remove_reference(params[0]); + cleanup1: + ACPI_FREE(info); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/events/evrgnini.c b/drivers/acpi/events/evrgnini.c index 1cecd577b89..5b3c7a85eb9 100644 --- a/drivers/acpi/events/evrgnini.c +++ b/drivers/acpi/events/evrgnini.c @@ -475,8 +475,9 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj, /* Find any "_REG" method associated with this region definition */ - status = acpi_ns_search_node(*reg_name_ptr, node, - ACPI_TYPE_METHOD, &method_node); + status = + acpi_ns_search_one_scope(*reg_name_ptr, node, ACPI_TYPE_METHOD, + &method_node); if (ACPI_SUCCESS(status)) { /* * The _REG method is optional and there can be only one per region diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c index 9ae3cb55979..823352435e0 100644 --- a/drivers/acpi/executer/exconfig.c +++ b/drivers/acpi/executer/exconfig.c @@ -214,9 +214,8 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, * location within the namespace where the table will be loaded. */ status = - acpi_ns_get_node_by_path(operand[3]->string.pointer, - start_node, ACPI_NS_SEARCH_PARENT, - &parent_node); + acpi_ns_get_node(start_node, operand[3]->string.pointer, + ACPI_NS_SEARCH_PARENT, &parent_node); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -237,9 +236,8 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, /* Find the node referenced by the parameter_path_string */ status = - acpi_ns_get_node_by_path(operand[4]->string.pointer, - start_node, ACPI_NS_SEARCH_PARENT, - ¶meter_node); + acpi_ns_get_node(start_node, operand[4]->string.pointer, + ACPI_NS_SEARCH_PARENT, ¶meter_node); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } diff --git a/drivers/acpi/executer/exfldio.c b/drivers/acpi/executer/exfldio.c index ca9925c0d01..3b7c4352ec5 100644 --- a/drivers/acpi/executer/exfldio.c +++ b/drivers/acpi/executer/exfldio.c @@ -145,10 +145,10 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc, * length of one field datum (access width) must fit within the region. * (Region length is specified in bytes) */ - if (rgn_desc->region.length < (obj_desc->common_field.base_byte_offset + - field_datum_byte_offset + - obj_desc->common_field. - access_byte_width)) { + if (rgn_desc->region.length < + (obj_desc->common_field.base_byte_offset + + field_datum_byte_offset + + obj_desc->common_field.access_byte_width)) { if (acpi_gbl_enable_interpreter_slack) { /* * Slack mode only: We will go ahead and allow access to this @@ -811,13 +811,15 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, mask = ACPI_MASK_BITS_BELOW(obj_desc->common_field.start_field_bit_offset); - datum_count = - ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length, - obj_desc->common_field.access_bit_width); - field_datum_count = - ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length + - obj_desc->common_field.start_field_bit_offset, - obj_desc->common_field.access_bit_width); + + datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length, + obj_desc->common_field.access_bit_width); + + field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length + + obj_desc->common_field. + start_field_bit_offset, + obj_desc->common_field. + access_bit_width); /* Get initial Datum from the input buffer */ diff --git a/drivers/acpi/executer/exmisc.c b/drivers/acpi/executer/exmisc.c index 794d9b8de95..bd98aab017c 100644 --- a/drivers/acpi/executer/exmisc.c +++ b/drivers/acpi/executer/exmisc.c @@ -445,10 +445,24 @@ acpi_ex_do_math_op(u16 opcode, acpi_integer integer0, acpi_integer integer1) case AML_SHIFT_LEFT_OP: /* shift_left (Operand, shift_count, Result) */ + /* + * We need to check if the shiftcount is larger than the integer bit + * width since the behavior of this is not well-defined in the C language. + */ + if (integer1 >= acpi_gbl_integer_bit_width) { + return (0); + } return (integer0 << integer1); case AML_SHIFT_RIGHT_OP: /* shift_right (Operand, shift_count, Result) */ + /* + * We need to check if the shiftcount is larger than the integer bit + * width since the behavior of this is not well-defined in the C language. + */ + if (integer1 >= acpi_gbl_integer_bit_width) { + return (0); + } return (integer0 >> integer1); case AML_SUBTRACT_OP: /* Subtract (Integer0, Integer1, Result) */ diff --git a/drivers/acpi/executer/exoparg1.c b/drivers/acpi/executer/exoparg1.c index 05b89c5878e..8284c52875b 100644 --- a/drivers/acpi/executer/exoparg1.c +++ b/drivers/acpi/executer/exoparg1.c @@ -874,16 +874,14 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) * Field, so we need to resolve the node to a value. */ status = - acpi_ns_get_node_by_path(operand[0]->string. - pointer, - walk_state-> - scope_info->scope. - node, - ACPI_NS_SEARCH_PARENT, - ACPI_CAST_INDIRECT_PTR - (struct - acpi_namespace_node, - &return_desc)); + acpi_ns_get_node(walk_state->scope_info-> + scope.node, + operand[0]->string.pointer, + ACPI_NS_SEARCH_PARENT, + ACPI_CAST_INDIRECT_PTR + (struct + acpi_namespace_node, + &return_desc)); if (ACPI_FAILURE(status)) { goto cleanup; } diff --git a/drivers/acpi/executer/exregion.c b/drivers/acpi/executer/exregion.c index 4fba452a559..3cc97ba48b3 100644 --- a/drivers/acpi/executer/exregion.c +++ b/drivers/acpi/executer/exregion.c @@ -477,23 +477,16 @@ acpi_ex_data_table_space_handler(u32 function, acpi_integer * value, void *handler_context, void *region_context) { - acpi_status status = AE_OK; - u32 byte_width = ACPI_DIV_8(bit_width); - u32 i; - char *logical_addr_ptr; - ACPI_FUNCTION_TRACE(ex_data_table_space_handler); - logical_addr_ptr = ACPI_PHYSADDR_TO_PTR(address); - /* Perform the memory read or write */ switch (function) { case ACPI_READ: - for (i = 0; i < byte_width; i++) { - ((char *)value)[i] = logical_addr_ptr[i]; - } + ACPI_MEMCPY(ACPI_CAST_PTR(char, value), + ACPI_PHYSADDR_TO_PTR(address), + ACPI_DIV_8(bit_width)); break; case ACPI_WRITE: @@ -502,5 +495,5 @@ acpi_ex_data_table_space_handler(u32 function, return_ACPI_STATUS(AE_SUPPORT); } - return_ACPI_STATUS(status); + return_ACPI_STATUS(AE_OK); } diff --git a/drivers/acpi/hardware/hwregs.c b/drivers/acpi/hardware/hwregs.c index ec9f5a11a8b..5a3aa8dd8cb 100644 --- a/drivers/acpi/hardware/hwregs.c +++ b/drivers/acpi/hardware/hwregs.c @@ -127,8 +127,7 @@ acpi_status acpi_get_sleep_type_data(u8 sleep_state, u8 * sleep_type_a, u8 * sleep_type_b) { acpi_status status = AE_OK; - struct acpi_parameter_info info; - char *sleep_state_name; + struct acpi_evaluate_info *info; ACPI_FUNCTION_TRACE(acpi_get_sleep_type_data); @@ -138,34 +137,39 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 * sleep_type_a, u8 * sleep_type_b) return_ACPI_STATUS(AE_BAD_PARAMETER); } - /* Evaluate the namespace object containing the values for this state */ + /* Allocate the evaluation information block */ + + info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); + if (!info) { + return_ACPI_STATUS(AE_NO_MEMORY); + } - info.parameters = NULL; - info.return_object = NULL; - sleep_state_name = + info->pathname = ACPI_CAST_PTR(char, acpi_gbl_sleep_state_names[sleep_state]); - status = acpi_ns_evaluate_by_name(sleep_state_name, &info); + /* Evaluate the namespace object containing the values for this state */ + + status = acpi_ns_evaluate(info); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%s while evaluating SleepState [%s]\n", acpi_format_exception(status), - sleep_state_name)); + info->pathname)); - return_ACPI_STATUS(status); + goto cleanup; } /* Must have a return object */ - if (!info.return_object) { + if (!info->return_object) { ACPI_ERROR((AE_INFO, "No Sleep State object returned from [%s]", - sleep_state_name)); + info->pathname)); status = AE_NOT_EXIST; } /* It must be of type Package */ - else if (ACPI_GET_OBJECT_TYPE(info.return_object) != ACPI_TYPE_PACKAGE) { + else if (ACPI_GET_OBJECT_TYPE(info->return_object) != ACPI_TYPE_PACKAGE) { ACPI_ERROR((AE_INFO, "Sleep State return object is not a Package")); status = AE_AML_OPERAND_TYPE; @@ -178,7 +182,7 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 * sleep_type_a, u8 * sleep_type_b) * by BIOS vendors seems to be to have 2 or more elements, at least * one per sleep type (A/B). */ - else if (info.return_object->package.count < 2) { + else if (info->return_object->package.count < 2) { ACPI_ERROR((AE_INFO, "Sleep State return package does not have at least two elements")); status = AE_AML_NO_OPERAND; @@ -186,35 +190,38 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 * sleep_type_a, u8 * sleep_type_b) /* The first two elements must both be of type Integer */ - else if ((ACPI_GET_OBJECT_TYPE(info.return_object->package.elements[0]) + else if ((ACPI_GET_OBJECT_TYPE(info->return_object->package.elements[0]) != ACPI_TYPE_INTEGER) || - (ACPI_GET_OBJECT_TYPE(info.return_object->package.elements[1]) + (ACPI_GET_OBJECT_TYPE(info->return_object->package.elements[1]) != ACPI_TYPE_INTEGER)) { ACPI_ERROR((AE_INFO, "Sleep State return package elements are not both Integers (%s, %s)", - acpi_ut_get_object_type_name(info.return_object-> + acpi_ut_get_object_type_name(info->return_object-> package.elements[0]), - acpi_ut_get_object_type_name(info.return_object-> + acpi_ut_get_object_type_name(info->return_object-> package.elements[1]))); status = AE_AML_OPERAND_TYPE; } else { /* Valid _Sx_ package size, type, and value */ *sleep_type_a = (u8) - (info.return_object->package.elements[0])->integer.value; + (info->return_object->package.elements[0])->integer.value; *sleep_type_b = (u8) - (info.return_object->package.elements[1])->integer.value; + (info->return_object->package.elements[1])->integer.value; } if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "While evaluating SleepState [%s], bad Sleep object %p type %s", - sleep_state_name, info.return_object, - acpi_ut_get_object_type_name(info. + info->pathname, info->return_object, + acpi_ut_get_object_type_name(info-> return_object))); } - acpi_ut_remove_reference(info.return_object); + acpi_ut_remove_reference(info->return_object); + + cleanup: + ACPI_FREE(info); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/namespace/nsaccess.c b/drivers/acpi/namespace/nsaccess.c index ba8ad569188..48fadade52e 100644 --- a/drivers/acpi/namespace/nsaccess.c +++ b/drivers/acpi/namespace/nsaccess.c @@ -259,10 +259,8 @@ acpi_status acpi_ns_root_initialize(void) /* Save a handle to "_GPE", it is always present */ if (ACPI_SUCCESS(status)) { - status = - acpi_ns_get_node_by_path("\\_GPE", NULL, - ACPI_NS_NO_UPSEARCH, - &acpi_gbl_fadt_gpe_device); + status = acpi_ns_get_node(NULL, "\\_GPE", ACPI_NS_NO_UPSEARCH, + &acpi_gbl_fadt_gpe_device); } return_ACPI_STATUS(status); diff --git a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c index 4b054062b46..4b0a4a8c984 100644 --- a/drivers/acpi/namespace/nseval.c +++ b/drivers/acpi/namespace/nseval.c @@ -1,7 +1,6 @@ /******************************************************************************* * - * Module Name: nseval - Object evaluation interfaces -- includes control - * method lookup and execution. + * Module Name: nseval - Object evaluation, includes control method execution * ******************************************************************************/ @@ -50,196 +49,14 @@ #define _COMPONENT ACPI_NAMESPACE ACPI_MODULE_NAME("nseval") -/* Local prototypes */ -static acpi_status -acpi_ns_execute_control_method(struct acpi_parameter_info *info); - -static acpi_status acpi_ns_get_object_value(struct acpi_parameter_info *info); - -/******************************************************************************* - * - * FUNCTION: acpi_ns_evaluate_relative - * - * PARAMETERS: Pathname - Name of method to execute, If NULL, the - * handle is the object to execute - * Info - Method info block, contains: - * return_object - Where to put method's return value (if - * any). If NULL, no value is returned. - * Params - List of parameters to pass to the method, - * terminated by NULL. Params itself may be - * NULL if no parameters are being passed. - * - * RETURN: Status - * - * DESCRIPTION: Evaluate the object or find and execute the requested method - * - * MUTEX: Locks Namespace - * - ******************************************************************************/ - -acpi_status -acpi_ns_evaluate_relative(char *pathname, struct acpi_parameter_info *info) -{ - acpi_status status; - struct acpi_namespace_node *node = NULL; - union acpi_generic_state *scope_info; - char *internal_path = NULL; - - ACPI_FUNCTION_TRACE(ns_evaluate_relative); - - /* - * Must have a valid object handle - */ - if (!info || !info->node) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - /* Build an internal name string for the method */ - - status = acpi_ns_internalize_name(pathname, &internal_path); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - scope_info = acpi_ut_create_generic_state(); - if (!scope_info) { - goto cleanup1; - } - - /* Get the prefix handle and Node */ - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - info->node = acpi_ns_map_handle_to_node(info->node); - if (!info->node) { - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - status = AE_BAD_PARAMETER; - goto cleanup; - } - - /* Lookup the name in the namespace */ - - scope_info->scope.node = info->node; - status = acpi_ns_lookup(scope_info, internal_path, ACPI_TYPE_ANY, - ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, NULL, - &node); - - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - - if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Object [%s] not found [%s]\n", - pathname, acpi_format_exception(status))); - goto cleanup; - } - - /* - * Now that we have a handle to the object, we can attempt to evaluate it. - */ - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s [%p] Value %p\n", - pathname, node, acpi_ns_get_attached_object(node))); - - info->node = node; - status = acpi_ns_evaluate_by_handle(info); - - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, - "*** Completed eval of object %s ***\n", pathname)); - - cleanup: - acpi_ut_delete_generic_state(scope_info); - - cleanup1: - ACPI_FREE(internal_path); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_evaluate_by_name - * - * PARAMETERS: Pathname - Fully qualified pathname to the object - * Info - Method info block, contains: - * return_object - Where to put method's return value (if - * any). If NULL, no value is returned. - * Params - List of parameters to pass to the method, - * terminated by NULL. Params itself may be - * NULL if no parameters are being passed. - * - * RETURN: Status - * - * DESCRIPTION: Evaluate the object or rind and execute the requested method - * passing the given parameters - * - * MUTEX: Locks Namespace - * - ******************************************************************************/ - -acpi_status -acpi_ns_evaluate_by_name(char *pathname, struct acpi_parameter_info *info) -{ - acpi_status status; - char *internal_path = NULL; - - ACPI_FUNCTION_TRACE(ns_evaluate_by_name); - - /* Build an internal name string for the method */ - - status = acpi_ns_internalize_name(pathname, &internal_path); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - /* Lookup the name in the namespace */ - - status = acpi_ns_lookup(NULL, internal_path, ACPI_TYPE_ANY, - ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, NULL, - &info->node); - - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - - if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, - "Object at [%s] was not found, status=%.4X\n", - pathname, status)); - goto cleanup; - } - - /* - * Now that we have a handle to the object, we can attempt to evaluate it. - */ - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s [%p] Value %p\n", - pathname, info->node, - acpi_ns_get_attached_object(info->node))); - - status = acpi_ns_evaluate_by_handle(info); - - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, - "*** Completed eval of object %s ***\n", pathname)); - - cleanup: - - /* Cleanup */ - - if (internal_path) { - ACPI_FREE(internal_path); - } - - return_ACPI_STATUS(status); -} - /******************************************************************************* * - * FUNCTION: acpi_ns_evaluate_by_handle + * FUNCTION: acpi_ns_evaluate * - * PARAMETERS: Info - Method info block, contains: - * Node - Method/Object Node to execute + * PARAMETERS: Info - Evaluation info block, contains: + * prefix_node - Prefix or Method/Object Node to execute + * Pathname - Name of method to execute, If NULL, the + * Node is the object to execute * Parameters - List of parameters to pass to the method, * terminated by NULL. Params itself may be * NULL if no parameters are being passed. @@ -248,29 +65,21 @@ acpi_ns_evaluate_by_name(char *pathname, struct acpi_parameter_info *info) * parameter_type - Type of Parameter list * return_object - Where to put method's return value (if * any). If NULL, no value is returned. + * Flags - ACPI_IGNORE_RETURN_VALUE to delete return * * RETURN: Status * - * DESCRIPTION: Evaluate object or execute the requested method passing the - * given parameters + * DESCRIPTION: Execute a control method or return the current value of an + * ACPI namespace object. * - * MUTEX: Locks Namespace + * MUTEX: Locks interpreter * ******************************************************************************/ - -acpi_status acpi_ns_evaluate_by_handle(struct acpi_parameter_info *info) +acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info) { acpi_status status; - ACPI_FUNCTION_TRACE(ns_evaluate_by_handle); - - /* Check if namespace has been initialized */ - - if (!acpi_gbl_root_node) { - return_ACPI_STATUS(AE_NO_NAMESPACE); - } - - /* Parameter Validation */ + ACPI_FUNCTION_TRACE(ns_evaluate); if (!info) { return_ACPI_STATUS(AE_BAD_PARAMETER); @@ -280,203 +89,120 @@ acpi_status acpi_ns_evaluate_by_handle(struct acpi_parameter_info *info) info->return_object = NULL; - /* Get the prefix handle and Node */ - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + /* + * Get the actual namespace node for the target object. Handles these cases: + * + * 1) Null node, Pathname (absolute path) + * 2) Node, Pathname (path relative to Node) + * 3) Node, Null Pathname + */ + status = acpi_ns_get_node(info->prefix_node, info->pathname, + ACPI_NS_NO_UPSEARCH, &info->resolved_node); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } - info->node = acpi_ns_map_handle_to_node(info->node); - if (!info->node) { - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - /* * For a method alias, we must grab the actual method node so that proper * scoping context will be established before execution. */ - if (acpi_ns_get_type(info->node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) { - info->node = + if (acpi_ns_get_type(info->resolved_node) == + ACPI_TYPE_LOCAL_METHOD_ALIAS) { + info->resolved_node = ACPI_CAST_PTR(struct acpi_namespace_node, - info->node->object); + info->resolved_node->object); } + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s [%p] Value %p\n", info->pathname, + info->resolved_node, + acpi_ns_get_attached_object(info->resolved_node))); + /* * Two major cases here: - * 1) The object is an actual control method -- execute it. - * 2) The object is not a method -- just return it's current value * - * In both cases, the namespace is unlocked by the acpi_ns* procedure + * 1) The object is a control method -- execute it + * 2) The object is not a method -- just return it's current value */ - if (acpi_ns_get_type(info->node) == ACPI_TYPE_METHOD) { + if (acpi_ns_get_type(info->resolved_node) == ACPI_TYPE_METHOD) { /* - * Case 1) We have an actual control method to execute + * 1) Object is a control method - execute it */ - status = acpi_ns_execute_control_method(info); - } else { - /* - * Case 2) Object is NOT a method, just return its current value - */ - status = acpi_ns_get_object_value(info); - } - - /* - * Check if there is a return value on the stack that must be dealt with - */ - if (status == AE_CTRL_RETURN_VALUE) { - - /* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */ - - status = AE_OK; - } - - /* - * Namespace was unlocked by the handling acpi_ns* function, so we - * just return - */ - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_execute_control_method - * - * PARAMETERS: Info - Method info block, contains: - * Node - Method Node to execute - * obj_desc - Method object - * Parameters - List of parameters to pass to the method, - * terminated by NULL. Params itself may be - * NULL if no parameters are being passed. - * return_object - Where to put method's return value (if - * any). If NULL, no value is returned. - * parameter_type - Type of Parameter list - * return_object - Where to put method's return value (if - * any). If NULL, no value is returned. - * - * RETURN: Status - * - * DESCRIPTION: Execute the requested method passing the given parameters - * - * MUTEX: Assumes namespace is locked - * - ******************************************************************************/ - -static acpi_status -acpi_ns_execute_control_method(struct acpi_parameter_info *info) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(ns_execute_control_method); - - /* Verify that there is a method associated with this object */ - - info->obj_desc = acpi_ns_get_attached_object(info->node); - if (!info->obj_desc) { - ACPI_ERROR((AE_INFO, "No attached method object")); - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - return_ACPI_STATUS(AE_NULL_OBJECT); - } - - ACPI_DUMP_PATHNAME(info->node, "Execute Method:", - ACPI_LV_INFO, _COMPONENT); - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Method at AML address %p Length %X\n", - info->obj_desc->method.aml_start + 1, - info->obj_desc->method.aml_length - 1)); - - /* - * Unlock the namespace before execution. This allows namespace access - * via the external Acpi* interfaces while a method is being executed. - * However, any namespace deletion must acquire both the namespace and - * interpreter locks to ensure that no thread is using the portion of the - * namespace that is being deleted. - */ - status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } + /* Verify that there is a method object associated with this node */ - /* - * Execute the method via the interpreter. The interpreter is locked - * here before calling into the AML parser - */ - status = acpi_ex_enter_interpreter(); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } + info->obj_desc = + acpi_ns_get_attached_object(info->resolved_node); + if (!info->obj_desc) { + ACPI_ERROR((AE_INFO, + "Control method has no attached sub-object")); + return_ACPI_STATUS(AE_NULL_OBJECT); + } - status = acpi_ps_execute_method(info); - acpi_ex_exit_interpreter(); + ACPI_DUMP_PATHNAME(info->resolved_node, "Execute Method:", + ACPI_LV_INFO, _COMPONENT); - return_ACPI_STATUS(status); -} + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Method at AML address %p Length %X\n", + info->obj_desc->method.aml_start + 1, + info->obj_desc->method.aml_length - 1)); -/******************************************************************************* - * - * FUNCTION: acpi_ns_get_object_value - * - * PARAMETERS: Info - Method info block, contains: - * Node - Object's NS node - * return_object - Where to put object value (if - * any). If NULL, no value is returned. - * - * RETURN: Status - * - * DESCRIPTION: Return the current value of the object - * - * MUTEX: Assumes namespace is locked, leaves namespace unlocked - * - ******************************************************************************/ + /* + * Any namespace deletion must acquire both the namespace and + * interpreter locks to ensure that no thread is using the portion of + * the namespace that is being deleted. + * + * Execute the method via the interpreter. The interpreter is locked + * here before calling into the AML parser + */ + status = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } -static acpi_status acpi_ns_get_object_value(struct acpi_parameter_info *info) -{ - acpi_status status = AE_OK; - struct acpi_namespace_node *resolved_node = info->node; + status = acpi_ps_execute_method(info); + acpi_ex_exit_interpreter(); + } else { + /* + * 2) Object is not a method, return its current value + */ - ACPI_FUNCTION_TRACE(ns_get_object_value); + /* + * Objects require additional resolution steps (e.g., the Node may be + * a field that must be read, etc.) -- we can't just grab the object + * out of the node. + * + * Use resolve_node_to_value() to get the associated value. + * + * NOTE: we can get away with passing in NULL for a walk state because + * resolved_node is guaranteed to not be a reference to either a method + * local or a method argument (because this interface is never called + * from a running method.) + * + * Even though we do not directly invoke the interpreter for object + * resolution, we must lock it because we could access an opregion. + * The opregion access code assumes that the interpreter is locked. + */ + status = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } - /* - * Objects require additional resolution steps (e.g., the Node may be a - * field that must be read, etc.) -- we can't just grab the object out of - * the node. - */ + /* Function has a strange interface */ - /* - * Use resolve_node_to_value() to get the associated value. This call always - * deletes obj_desc (allocated above). - * - * NOTE: we can get away with passing in NULL for a walk state because - * obj_desc is guaranteed to not be a reference to either a method local or - * a method argument (because this interface can only be called from the - * acpi_evaluate external interface, never called from a running method.) - * - * Even though we do not directly invoke the interpreter for this, we must - * enter it because we could access an opregion. The opregion access code - * assumes that the interpreter is locked. - * - * We must release the namespace lock before entering the intepreter. - */ - status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } + status = + acpi_ex_resolve_node_to_value(&info->resolved_node, NULL); + acpi_ex_exit_interpreter(); - status = acpi_ex_enter_interpreter(); - if (ACPI_SUCCESS(status)) { - status = acpi_ex_resolve_node_to_value(&resolved_node, NULL); /* * If acpi_ex_resolve_node_to_value() succeeded, the return value was placed * in resolved_node. */ - acpi_ex_exit_interpreter(); - if (ACPI_SUCCESS(status)) { status = AE_CTRL_RETURN_VALUE; - info->return_object = ACPI_CAST_PTR - (union acpi_operand_object, resolved_node); + info->return_object = + ACPI_CAST_PTR(union acpi_operand_object, + info->resolved_node); + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Returning object %p [%s]\n", info->return_object, @@ -485,7 +211,30 @@ static acpi_status acpi_ns_get_object_value(struct acpi_parameter_info *info) } } - /* Namespace is unlocked */ + /* + * Check if there is a return value that must be dealt with + */ + if (status == AE_CTRL_RETURN_VALUE) { + + /* If caller does not want the return value, delete it */ + if (info->flags & ACPI_IGNORE_RETURN_VALUE) { + acpi_ut_remove_reference(info->return_object); + info->return_object = NULL; + } + + /* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */ + + status = AE_OK; + } + + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, + "*** Completed evaluation of object %s ***\n", + info->pathname)); + + /* + * Namespace was unlocked by the handling acpi_ns* function, so we + * just return + */ return_ACPI_STATUS(status); } diff --git a/drivers/acpi/namespace/nsinit.c b/drivers/acpi/namespace/nsinit.c index bf1d8dbc0b8..1c9ca6e0531 100644 --- a/drivers/acpi/namespace/nsinit.c +++ b/drivers/acpi/namespace/nsinit.c @@ -154,7 +154,16 @@ acpi_status acpi_ns_initialize_devices(void) ACPI_UINT32_MAX, FALSE, acpi_ns_find_ini_methods, &info, NULL); if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace")); + goto error_exit; + } + + /* Allocate the evaluation information block */ + + info.evaluate_info = + ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); + if (!info.evaluate_info) { + status = AE_NO_MEMORY; + goto error_exit; } /* Walk namespace to execute all _INIs on present devices */ @@ -162,8 +171,10 @@ acpi_status acpi_ns_initialize_devices(void) status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, FALSE, acpi_ns_init_one_device, &info, NULL); + + ACPI_FREE(info.evaluate_info); if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace")); + goto error_exit; } ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, @@ -171,6 +182,10 @@ acpi_status acpi_ns_initialize_devices(void) info.num_INI, info.num_STA, info.device_count)); return_ACPI_STATUS(status); + + error_exit: + ACPI_EXCEPTION((AE_INFO, status, "During device initialization")); + return_ACPI_STATUS(status); } /******************************************************************************* @@ -398,9 +413,9 @@ static acpi_status acpi_ns_init_one_device(acpi_handle obj_handle, u32 nesting_level, void *context, void **return_value) { - struct acpi_device_walk_info *info = + struct acpi_device_walk_info *walk_info = ACPI_CAST_PTR(struct acpi_device_walk_info, context); - struct acpi_parameter_info pinfo; + struct acpi_evaluate_info *info = walk_info->evaluate_info; u32 flags; acpi_status status; struct acpi_namespace_node *device_node; @@ -460,7 +475,7 @@ acpi_ns_init_one_device(acpi_handle obj_handle, * other words, the device is present, ..., and functioning)" */ if (flags != ACPI_UINT32_MAX) { - info->num_STA++; + walk_info->num_STA++; } /* @@ -516,20 +531,16 @@ acpi_ns_init_one_device(acpi_handle obj_handle, ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname (ACPI_TYPE_METHOD, device_node, METHOD_NAME__INI)); - pinfo.node = device_node; - pinfo.parameters = NULL; - pinfo.parameter_type = ACPI_PARAM_ARGS; + info->prefix_node = device_node; + info->pathname = METHOD_NAME__INI; + info->parameters = NULL; + info->parameter_type = ACPI_PARAM_ARGS; + info->flags = ACPI_IGNORE_RETURN_VALUE; - status = acpi_ns_evaluate_relative(METHOD_NAME__INI, &pinfo); + status = acpi_ns_evaluate(info); if (ACPI_SUCCESS(status)) { + walk_info->num_INI++; - /* Delete any return object (especially if implicit_return is enabled) */ - - if (pinfo.return_object) { - acpi_ut_remove_reference(pinfo.return_object); - } - - info->num_INI++; if ((acpi_dbg_level <= ACPI_LV_ALL_EXCEPTIONS) && (!(acpi_dbg_level & ACPI_LV_INFO))) { ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, ".")); @@ -540,20 +551,24 @@ acpi_ns_init_one_device(acpi_handle obj_handle, /* Ignore error and move on to next device */ - char *scope_name = acpi_ns_get_external_pathname(pinfo.node); + char *scope_name = + acpi_ns_get_external_pathname(info->resolved_node); ACPI_EXCEPTION((AE_INFO, status, "during %s._INI execution", scope_name)); ACPI_FREE(scope_name); + status = AE_OK; } #endif - /* If an external initialization handler is present, call it */ - + /* + * The _INI method has been run if present; call the Global Initialization + * Handler for this device. + */ if (acpi_gbl_init_handler) { status = - acpi_gbl_init_handler(pinfo.node, ACPI_INIT_DEVICE_INI); + acpi_gbl_init_handler(device_node, ACPI_INIT_DEVICE_INI); } - return_ACPI_STATUS(AE_OK); + return_ACPI_STATUS(status); } diff --git a/drivers/acpi/namespace/nssearch.c b/drivers/acpi/namespace/nssearch.c index d2473476afa..500e2bbcfaf 100644 --- a/drivers/acpi/namespace/nssearch.c +++ b/drivers/acpi/namespace/nssearch.c @@ -56,16 +56,16 @@ acpi_ns_search_parent_tree(u32 target_name, /******************************************************************************* * - * FUNCTION: acpi_ns_search_node + * FUNCTION: acpi_ns_search_one_scope * * PARAMETERS: target_name - Ascii ACPI name to search for - * Node - Starting node where search will begin + * parent_node - Starting node where search will begin * Type - Object type to match * return_node - Where the matched Named obj is returned * * RETURN: Status * - * DESCRIPTION: Search a single level of the namespace. Performs a + * DESCRIPTION: Search a single level of the namespace. Performs a * simple search of the specified level, and does not add * entries or search parents. * @@ -75,32 +75,37 @@ acpi_ns_search_parent_tree(u32 target_name, * * All namespace searching is linear in this implementation, but * could be easily modified to support any improved search - * algorithm. However, the linear search was chosen for simplicity + * algorithm. However, the linear search was chosen for simplicity * and because the trees are small and the other interpreter * execution overhead is relatively high. * + * Note: CPU execution analysis has shown that the AML interpreter spends + * a very small percentage of its time searching the namespace. Therefore, + * the linear search seems to be sufficient, as there would seem to be + * little value in improving the search. + * ******************************************************************************/ acpi_status -acpi_ns_search_node(u32 target_name, - struct acpi_namespace_node *node, - acpi_object_type type, - struct acpi_namespace_node **return_node) +acpi_ns_search_one_scope(u32 target_name, + struct acpi_namespace_node *parent_node, + acpi_object_type type, + struct acpi_namespace_node **return_node) { - struct acpi_namespace_node *next_node; + struct acpi_namespace_node *node; - ACPI_FUNCTION_TRACE(ns_search_node); + ACPI_FUNCTION_TRACE(ns_search_one_scope); #ifdef ACPI_DEBUG_OUTPUT if (ACPI_LV_NAMES & acpi_dbg_level) { char *scope_name; - scope_name = acpi_ns_get_external_pathname(node); + scope_name = acpi_ns_get_external_pathname(parent_node); if (scope_name) { ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Searching %s (%p) For [%4.4s] (%s)\n", - scope_name, node, ACPI_CAST_PTR(char, - &target_name), + scope_name, parent_node, + ACPI_CAST_PTR(char, &target_name), acpi_ut_get_type_name(type))); ACPI_FREE(scope_name); @@ -112,20 +117,20 @@ acpi_ns_search_node(u32 target_name, * Search for name at this namespace level, which is to say that we * must search for the name among the children of this object */ - next_node = node->child; - while (next_node) { + node = parent_node->child; + while (node) { /* Check for match against the name */ - if (next_node->name.integer == target_name) { + if (node->name.integer == target_name) { /* Resolve a control method alias if any */ - if (acpi_ns_get_type(next_node) == + if (acpi_ns_get_type(node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) { - next_node = + node = ACPI_CAST_PTR(struct acpi_namespace_node, - next_node->object); + node->object); } /* Found matching entry */ @@ -133,12 +138,12 @@ acpi_ns_search_node(u32 target_name, ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Name [%4.4s] (%s) %p found in scope [%4.4s] %p\n", ACPI_CAST_PTR(char, &target_name), - acpi_ut_get_type_name(next_node-> - type), - next_node, - acpi_ut_get_node_name(node), node)); + acpi_ut_get_type_name(node->type), + node, + acpi_ut_get_node_name(parent_node), + parent_node)); - *return_node = next_node; + *return_node = node; return_ACPI_STATUS(AE_OK); } @@ -146,7 +151,7 @@ acpi_ns_search_node(u32 target_name, * The last entry in the list points back to the parent, * so a flag is used to indicate the end-of-list */ - if (next_node->flags & ANOBJ_END_OF_PEER_LIST) { + if (node->flags & ANOBJ_END_OF_PEER_LIST) { /* Searched entire list, we are done */ @@ -155,7 +160,7 @@ acpi_ns_search_node(u32 target_name, /* Didn't match name, move on to the next peer object */ - next_node = next_node->peer; + node = node->peer; } /* Searched entire namespace level, not found */ @@ -164,7 +169,8 @@ acpi_ns_search_node(u32 target_name, "Name [%4.4s] (%s) not found in search in scope [%4.4s] %p first child %p\n", ACPI_CAST_PTR(char, &target_name), acpi_ut_get_type_name(type), - acpi_ut_get_node_name(node), node, node->child)); + acpi_ut_get_node_name(parent_node), parent_node, + parent_node->child)); return_ACPI_STATUS(AE_NOT_FOUND); } @@ -181,14 +187,14 @@ acpi_ns_search_node(u32 target_name, * RETURN: Status * * DESCRIPTION: Called when a name has not been found in the current namespace - * level. Before adding it or giving up, ACPI scope rules require + * level. Before adding it or giving up, ACPI scope rules require * searching enclosing scopes in cases identified by acpi_ns_local(). * * "A name is located by finding the matching name in the current * name space, and then in the parent name space. If the parent * name space does not contain the name, the search continues * recursively until either the name is found or the name space - * does not have a parent (the root of the name space). This + * does not have a parent (the root of the name space). This * indicates that the name is not found" (From ACPI Specification, * section 5.3) * @@ -237,11 +243,12 @@ acpi_ns_search_parent_tree(u32 target_name, */ while (parent_node) { /* - * Search parent scope. Use TYPE_ANY because we don't care about the + * Search parent scope. Use TYPE_ANY because we don't care about the * object type at this point, we only care about the existence of - * the actual name we are searching for. Typechecking comes later. + * the actual name we are searching for. Typechecking comes later. */ - status = acpi_ns_search_node(target_name, parent_node, + status = + acpi_ns_search_one_scope(target_name, parent_node, ACPI_TYPE_ANY, return_node); if (ACPI_SUCCESS(status)) { return_ACPI_STATUS(status); @@ -273,7 +280,7 @@ acpi_ns_search_parent_tree(u32 target_name, * RETURN: Status * * DESCRIPTION: Search for a name segment in a single namespace level, - * optionally adding it if it is not found. If the passed + * optionally adding it if it is not found. If the passed * Type is not Any and the type previously stored in the * entry was Any (i.e. unknown), update the stored type. * @@ -332,7 +339,7 @@ acpi_ns_search_and_enter(u32 target_name, /* Try to find the name in the namespace level specified by the caller */ *return_node = ACPI_ENTRY_NOT_FOUND; - status = acpi_ns_search_node(target_name, node, type, return_node); + status = acpi_ns_search_one_scope(target_name, node, type, return_node); if (status != AE_NOT_FOUND) { /* * If we found it AND the request specifies that a find is an error, @@ -348,10 +355,10 @@ acpi_ns_search_and_enter(u32 target_name, } /* - * The name was not found. If we are NOT performing the first pass + * The name was not found. If we are NOT performing the first pass * (name entry) of loading the namespace, search the parent tree (all the * way to the root if necessary.) We don't want to perform the parent - * search when the namespace is actually being loaded. We want to perform + * search when the namespace is actually being loaded. We want to perform * the search when namespace references are being resolved (load pass 2) * and during the execution phase. */ @@ -386,6 +393,9 @@ acpi_ns_search_and_enter(u32 target_name, return_ACPI_STATUS(AE_NO_MEMORY); } #ifdef ACPI_ASL_COMPILER + /* + * Node is an object defined by an External() statement + */ if (flags & ACPI_NS_EXTERNAL) { new_node->flags |= ANOBJ_IS_EXTERNAL; } diff --git a/drivers/acpi/namespace/nsutils.c b/drivers/acpi/namespace/nsutils.c index d1d55032b45..aa4e799d9a8 100644 --- a/drivers/acpi/namespace/nsutils.c +++ b/drivers/acpi/namespace/nsutils.c @@ -142,8 +142,9 @@ acpi_ns_report_method_error(char *module_name, acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number); if (path) { - status = acpi_ns_get_node_by_path(path, prefix_node, - ACPI_NS_NO_UPSEARCH, &node); + status = + acpi_ns_get_node(prefix_node, path, ACPI_NS_NO_UPSEARCH, + &node); if (ACPI_FAILURE(status)) { acpi_os_printf("[Could not get node by pathname]"); } @@ -685,13 +686,9 @@ struct acpi_namespace_node *acpi_ns_map_handle_to_node(acpi_handle handle) ACPI_FUNCTION_ENTRY(); /* - * Simple implementation. + * Simple implementation */ - if (!handle) { - return (NULL); - } - - if (handle == ACPI_ROOT_OBJECT) { + if ((!handle) || (handle == ACPI_ROOT_OBJECT)) { return (acpi_gbl_root_node); } @@ -701,7 +698,7 @@ struct acpi_namespace_node *acpi_ns_map_handle_to_node(acpi_handle handle) return (NULL); } - return ((struct acpi_namespace_node *)handle); + return (ACPI_CAST_PTR(struct acpi_namespace_node, handle)); } /******************************************************************************* @@ -811,12 +808,12 @@ u32 acpi_ns_opens_scope(acpi_object_type type) /******************************************************************************* * - * FUNCTION: acpi_ns_get_node_by_path + * FUNCTION: acpi_ns_get_node * * PARAMETERS: *Pathname - Name to be found, in external (ASL) format. The * \ (backslash) and ^ (carat) prefixes, and the * . (period) to separate segments are supported. - * start_node - Root of subtree to be searched, or NS_ALL for the + * prefix_node - Root of subtree to be searched, or NS_ALL for the * root of the name space. If Name is fully * qualified (first s8 is '\'), the passed value * of Scope will not be accessed. @@ -832,24 +829,29 @@ u32 acpi_ns_opens_scope(acpi_object_type type) ******************************************************************************/ acpi_status -acpi_ns_get_node_by_path(char *pathname, - struct acpi_namespace_node *start_node, - u32 flags, struct acpi_namespace_node **return_node) +acpi_ns_get_node(struct acpi_namespace_node *prefix_node, + char *pathname, + u32 flags, struct acpi_namespace_node **return_node) { union acpi_generic_state scope_info; acpi_status status; - char *internal_path = NULL; + char *internal_path; - ACPI_FUNCTION_TRACE_PTR(ns_get_node_by_path, pathname); + ACPI_FUNCTION_TRACE_PTR(ns_get_node, pathname); - if (pathname) { + if (!pathname) { + *return_node = prefix_node; + if (!prefix_node) { + *return_node = acpi_gbl_root_node; + } + return_ACPI_STATUS(AE_OK); + } - /* Convert path to internal representation */ + /* Convert path to internal representation */ - status = acpi_ns_internalize_name(pathname, &internal_path); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } + status = acpi_ns_internalize_name(pathname, &internal_path); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); } /* Must lock namespace during lookup */ @@ -861,26 +863,23 @@ acpi_ns_get_node_by_path(char *pathname, /* Setup lookup scope (search starting point) */ - scope_info.scope.node = start_node; + scope_info.scope.node = prefix_node; /* Lookup the name in the namespace */ - status = acpi_ns_lookup(&scope_info, internal_path, - ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, - (flags | ACPI_NS_DONT_OPEN_SCOPE), - NULL, return_node); + status = acpi_ns_lookup(&scope_info, internal_path, ACPI_TYPE_ANY, + ACPI_IMODE_EXECUTE, + (flags | ACPI_NS_DONT_OPEN_SCOPE), NULL, + return_node); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s, %s\n", - internal_path, - acpi_format_exception(status))); + pathname, acpi_format_exception(status))); } (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); cleanup: - if (internal_path) { - ACPI_FREE(internal_path); - } + ACPI_FREE(internal_path); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c index 998b29611b1..6d9bd45af30 100644 --- a/drivers/acpi/namespace/nsxfeval.c +++ b/drivers/acpi/namespace/nsxfeval.c @@ -171,51 +171,61 @@ acpi_evaluate_object(acpi_handle handle, { acpi_status status; acpi_status status2; - struct acpi_parameter_info info; + struct acpi_evaluate_info *info; acpi_size buffer_space_needed; u32 i; ACPI_FUNCTION_TRACE(acpi_evaluate_object); - info.node = handle; - info.parameters = NULL; - info.return_object = NULL; - info.parameter_type = ACPI_PARAM_ARGS; + /* Allocate and initialize the evaluation information block */ + + info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); + if (!info) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + info->pathname = pathname; + info->parameter_type = ACPI_PARAM_ARGS; + + /* Convert and validate the device handle */ + + info->prefix_node = acpi_ns_map_handle_to_node(handle); + if (!info->prefix_node) { + status = AE_BAD_PARAMETER; + goto cleanup; + } /* - * If there are parameters to be passed to the object - * (which must be a control method), the external objects - * must be converted to internal objects + * If there are parameters to be passed to a control method, the external + * objects must all be converted to internal objects */ if (external_params && external_params->count) { /* * Allocate a new parameter block for the internal objects * Add 1 to count to allow for null terminated internal list */ - info.parameters = ACPI_ALLOCATE_ZEROED(((acpi_size) - external_params->count + - 1) * sizeof(void *)); - if (!info.parameters) { - return_ACPI_STATUS(AE_NO_MEMORY); + info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size) + external_params-> + count + + 1) * sizeof(void *)); + if (!info->parameters) { + status = AE_NO_MEMORY; + goto cleanup; } - /* - * Convert each external object in the list to an - * internal object - */ + /* Convert each external object in the list to an internal object */ + for (i = 0; i < external_params->count; i++) { status = acpi_ut_copy_eobject_to_iobject(&external_params-> pointer[i], - &info. + &info-> parameters[i]); if (ACPI_FAILURE(status)) { - acpi_ut_delete_internal_object_list(info. - parameters); - return_ACPI_STATUS(status); + goto cleanup; } } - info.parameters[external_params->count] = NULL; + info->parameters[external_params->count] = NULL; } /* @@ -228,12 +238,13 @@ acpi_evaluate_object(acpi_handle handle, /* The path is fully qualified, just evaluate by name */ - status = acpi_ns_evaluate_by_name(pathname, &info); + info->prefix_node = NULL; + status = acpi_ns_evaluate(info); } else if (!handle) { /* - * A handle is optional iff a fully qualified pathname - * is specified. Since we've already handled fully - * qualified names above, this is an error + * A handle is optional iff a fully qualified pathname is specified. + * Since we've already handled fully qualified names above, this is + * an error */ if (!pathname) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, @@ -246,22 +257,9 @@ acpi_evaluate_object(acpi_handle handle, status = AE_BAD_PARAMETER; } else { - /* - * We get here if we have a handle -- and if we have a - * pathname it is relative. The handle will be validated - * in the lower procedures - */ - if (!pathname) { - /* - * The null pathname case means the handle is for - * the actual object to be evaluated - */ - status = acpi_ns_evaluate_by_handle(&info); - } else { - /* Both a Handle and a relative Pathname */ + /* We have a namespace a node and a possible relative path */ - status = acpi_ns_evaluate_relative(pathname, &info); - } + status = acpi_ns_evaluate(info); } /* @@ -269,10 +267,10 @@ acpi_evaluate_object(acpi_handle handle, * copy the return value to an external object. */ if (return_buffer) { - if (!info.return_object) { + if (!info->return_object) { return_buffer->length = 0; } else { - if (ACPI_GET_DESCRIPTOR_TYPE(info.return_object) == + if (ACPI_GET_DESCRIPTOR_TYPE(info->return_object) == ACPI_DESC_TYPE_NAMED) { /* * If we received a NS Node as a return object, this means that @@ -283,17 +281,16 @@ acpi_evaluate_object(acpi_handle handle, * support for various types at a later date if necessary. */ status = AE_TYPE; - info.return_object = NULL; /* No need to delete a NS Node */ + info->return_object = NULL; /* No need to delete a NS Node */ return_buffer->length = 0; } if (ACPI_SUCCESS(status)) { - /* - * Find out how large a buffer is needed - * to contain the returned object - */ + + /* Get the size of the returned object */ + status = - acpi_ut_get_object_size(info.return_object, + acpi_ut_get_object_size(info->return_object, &buffer_space_needed); if (ACPI_SUCCESS(status)) { @@ -319,7 +316,7 @@ acpi_evaluate_object(acpi_handle handle, status = acpi_ut_copy_iobject_to_eobject - (info.return_object, + (info->return_object, return_buffer); } } @@ -327,31 +324,33 @@ acpi_evaluate_object(acpi_handle handle, } } - if (info.return_object) { + if (info->return_object) { /* - * Delete the internal return object. NOTE: Interpreter - * must be locked to avoid race condition. + * Delete the internal return object. NOTE: Interpreter must be + * locked to avoid race condition. */ status2 = acpi_ex_enter_interpreter(); if (ACPI_SUCCESS(status2)) { - /* - * Delete the internal return object. (Or at least - * decrement the reference count by one) - */ - acpi_ut_remove_reference(info.return_object); + + /* Remove one reference on the return object (should delete it) */ + + acpi_ut_remove_reference(info->return_object); acpi_ex_exit_interpreter(); } } + cleanup: + /* Free the input parameter list (if we created one) */ - if (info.parameters) { + if (info->parameters) { /* Free the allocated parameter block */ - acpi_ut_delete_internal_object_list(info.parameters); + acpi_ut_delete_internal_object_list(info->parameters); } + ACPI_FREE(info); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/namespace/nsxfname.c b/drivers/acpi/namespace/nsxfname.c index 1303e2b062b..978213a6c19 100644 --- a/drivers/acpi/namespace/nsxfname.c +++ b/drivers/acpi/namespace/nsxfname.c @@ -112,9 +112,8 @@ acpi_get_handle(acpi_handle parent, /* * Find the Node and convert to a handle */ - status = - acpi_ns_get_node_by_path(pathname, prefix_node, ACPI_NS_NO_UPSEARCH, - &node); + status = acpi_ns_get_node(prefix_node, pathname, ACPI_NS_NO_UPSEARCH, + &node); *ret_handle = NULL; if (ACPI_SUCCESS(status)) { diff --git a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c index 796f6b71992..7ee2f2e7752 100644 --- a/drivers/acpi/parser/psparse.c +++ b/drivers/acpi/parser/psparse.c @@ -464,6 +464,7 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state) thread = acpi_ut_create_thread_state(); if (!thread) { + acpi_ds_delete_walk_state(walk_state); return_ACPI_STATUS(AE_NO_MEMORY); } diff --git a/drivers/acpi/parser/psxface.c b/drivers/acpi/parser/psxface.c index 6b1411f1087..5d996c1140a 100644 --- a/drivers/acpi/parser/psxface.c +++ b/drivers/acpi/parser/psxface.c @@ -50,14 +50,14 @@ ACPI_MODULE_NAME("psxface") /* Local Prototypes */ -static void acpi_ps_start_trace(struct acpi_parameter_info *info); +static void acpi_ps_start_trace(struct acpi_evaluate_info *info); -static void acpi_ps_stop_trace(struct acpi_parameter_info *info); +static void acpi_ps_stop_trace(struct acpi_evaluate_info *info); -static acpi_status acpi_ps_execute_pass(struct acpi_parameter_info *info); +static acpi_status acpi_ps_execute_pass(struct acpi_evaluate_info *info); static void -acpi_ps_update_parameter_list(struct acpi_parameter_info *info, u16 action); +acpi_ps_update_parameter_list(struct acpi_evaluate_info *info, u16 action); /******************************************************************************* * @@ -113,7 +113,7 @@ acpi_debug_trace(char *name, u32 debug_level, u32 debug_layer, u32 flags) * ******************************************************************************/ -static void acpi_ps_start_trace(struct acpi_parameter_info *info) +static void acpi_ps_start_trace(struct acpi_evaluate_info *info) { acpi_status status; @@ -125,7 +125,7 @@ static void acpi_ps_start_trace(struct acpi_parameter_info *info) } if ((!acpi_gbl_trace_method_name) || - (acpi_gbl_trace_method_name != info->node->name.integer)) { + (acpi_gbl_trace_method_name != info->resolved_node->name.integer)) { goto exit; } @@ -158,7 +158,7 @@ static void acpi_ps_start_trace(struct acpi_parameter_info *info) * ******************************************************************************/ -static void acpi_ps_stop_trace(struct acpi_parameter_info *info) +static void acpi_ps_stop_trace(struct acpi_evaluate_info *info) { acpi_status status; @@ -170,7 +170,7 @@ static void acpi_ps_stop_trace(struct acpi_parameter_info *info) } if ((!acpi_gbl_trace_method_name) || - (acpi_gbl_trace_method_name != info->node->name.integer)) { + (acpi_gbl_trace_method_name != info->resolved_node->name.integer)) { goto exit; } @@ -212,7 +212,7 @@ static void acpi_ps_stop_trace(struct acpi_parameter_info *info) * ******************************************************************************/ -acpi_status acpi_ps_execute_method(struct acpi_parameter_info *info) +acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info) { acpi_status status; @@ -220,14 +220,15 @@ acpi_status acpi_ps_execute_method(struct acpi_parameter_info *info) /* Validate the Info and method Node */ - if (!info || !info->node) { + if (!info || !info->resolved_node) { return_ACPI_STATUS(AE_NULL_ENTRY); } /* Init for new method, wait on concurrency semaphore */ status = - acpi_ds_begin_method_execution(info->node, info->obj_desc, NULL); + acpi_ds_begin_method_execution(info->resolved_node, info->obj_desc, + NULL); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -248,7 +249,7 @@ acpi_status acpi_ps_execute_method(struct acpi_parameter_info *info) */ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Begin Method Parse **** Entry=%p obj=%p\n", - info->node, info->obj_desc)); + info->resolved_node, info->obj_desc)); info->pass_number = 1; status = acpi_ps_execute_pass(info); @@ -261,7 +262,7 @@ acpi_status acpi_ps_execute_method(struct acpi_parameter_info *info) */ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Begin Method Execution **** Entry=%p obj=%p\n", - info->node, info->obj_desc)); + info->resolved_node, info->obj_desc)); info->pass_number = 3; status = acpi_ps_execute_pass(info); @@ -300,7 +301,7 @@ acpi_status acpi_ps_execute_method(struct acpi_parameter_info *info) * * FUNCTION: acpi_ps_update_parameter_list * - * PARAMETERS: Info - See struct acpi_parameter_info + * PARAMETERS: Info - See struct acpi_evaluate_info * (Used: parameter_type and Parameters) * Action - Add or Remove reference * @@ -311,7 +312,7 @@ acpi_status acpi_ps_execute_method(struct acpi_parameter_info *info) ******************************************************************************/ static void -acpi_ps_update_parameter_list(struct acpi_parameter_info *info, u16 action) +acpi_ps_update_parameter_list(struct acpi_evaluate_info *info, u16 action) { acpi_native_uint i; @@ -334,7 +335,7 @@ acpi_ps_update_parameter_list(struct acpi_parameter_info *info, u16 action) * * FUNCTION: acpi_ps_execute_pass * - * PARAMETERS: Info - See struct acpi_parameter_info + * PARAMETERS: Info - See struct acpi_evaluate_info * (Used: pass_number, Node, and obj_desc) * * RETURN: Status @@ -343,7 +344,7 @@ acpi_ps_update_parameter_list(struct acpi_parameter_info *info, u16 action) * ******************************************************************************/ -static acpi_status acpi_ps_execute_pass(struct acpi_parameter_info *info) +static acpi_status acpi_ps_execute_pass(struct acpi_evaluate_info *info) { acpi_status status; union acpi_parse_object *op; @@ -368,7 +369,7 @@ static acpi_status acpi_ps_execute_pass(struct acpi_parameter_info *info) goto cleanup; } - status = acpi_ds_init_aml_walk(walk_state, op, info->node, + status = acpi_ds_init_aml_walk(walk_state, op, info->resolved_node, info->obj_desc->method.aml_start, info->obj_desc->method.aml_length, info->pass_number == 1 ? NULL : info, diff --git a/drivers/acpi/resources/rsutils.c b/drivers/acpi/resources/rsutils.c index 0e493f2fec4..a9cbee8e8b4 100644 --- a/drivers/acpi/resources/rsutils.c +++ b/drivers/acpi/resources/rsutils.c @@ -442,7 +442,7 @@ acpi_rs_set_resource_source(union aml_resource * aml, * * FUNCTION: acpi_rs_get_prt_method_data * - * PARAMETERS: Handle - Handle to the containing object + * PARAMETERS: Node - Device node * ret_buffer - Pointer to a buffer structure for the * results * @@ -457,7 +457,8 @@ acpi_rs_set_resource_source(union aml_resource * aml, ******************************************************************************/ acpi_status -acpi_rs_get_prt_method_data(acpi_handle handle, struct acpi_buffer * ret_buffer) +acpi_rs_get_prt_method_data(struct acpi_namespace_node * node, + struct acpi_buffer * ret_buffer) { union acpi_operand_object *obj_desc; acpi_status status; @@ -468,7 +469,7 @@ acpi_rs_get_prt_method_data(acpi_handle handle, struct acpi_buffer * ret_buffer) /* Execute the method, no parameters */ - status = acpi_ut_evaluate_object(handle, METHOD_NAME__PRT, + status = acpi_ut_evaluate_object(node, METHOD_NAME__PRT, ACPI_BTYPE_PACKAGE, &obj_desc); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); @@ -490,7 +491,7 @@ acpi_rs_get_prt_method_data(acpi_handle handle, struct acpi_buffer * ret_buffer) * * FUNCTION: acpi_rs_get_crs_method_data * - * PARAMETERS: Handle - Handle to the containing object + * PARAMETERS: Node - Device node * ret_buffer - Pointer to a buffer structure for the * results * @@ -505,7 +506,8 @@ acpi_rs_get_prt_method_data(acpi_handle handle, struct acpi_buffer * ret_buffer) ******************************************************************************/ acpi_status -acpi_rs_get_crs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer) +acpi_rs_get_crs_method_data(struct acpi_namespace_node *node, + struct acpi_buffer *ret_buffer) { union acpi_operand_object *obj_desc; acpi_status status; @@ -516,7 +518,7 @@ acpi_rs_get_crs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer) /* Execute the method, no parameters */ - status = acpi_ut_evaluate_object(handle, METHOD_NAME__CRS, + status = acpi_ut_evaluate_object(node, METHOD_NAME__CRS, ACPI_BTYPE_BUFFER, &obj_desc); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); @@ -539,7 +541,7 @@ acpi_rs_get_crs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer) * * FUNCTION: acpi_rs_get_prs_method_data * - * PARAMETERS: Handle - Handle to the containing object + * PARAMETERS: Node - Device node * ret_buffer - Pointer to a buffer structure for the * results * @@ -555,7 +557,8 @@ acpi_rs_get_crs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer) #ifdef ACPI_FUTURE_USAGE acpi_status -acpi_rs_get_prs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer) +acpi_rs_get_prs_method_data(struct acpi_namespace_node *node, + struct acpi_buffer *ret_buffer) { union acpi_operand_object *obj_desc; acpi_status status; @@ -566,7 +569,7 @@ acpi_rs_get_prs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer) /* Execute the method, no parameters */ - status = acpi_ut_evaluate_object(handle, METHOD_NAME__PRS, + status = acpi_ut_evaluate_object(node, METHOD_NAME__PRS, ACPI_BTYPE_BUFFER, &obj_desc); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); @@ -641,7 +644,7 @@ acpi_rs_get_method_data(acpi_handle handle, * * FUNCTION: acpi_rs_set_srs_method_data * - * PARAMETERS: Handle - Handle to the containing object + * PARAMETERS: Node - Device node * in_buffer - Pointer to a buffer structure of the * parameter * @@ -653,23 +656,37 @@ acpi_rs_get_method_data(acpi_handle handle, * If the function fails an appropriate status will be returned * and the contents of the callers buffer is undefined. * + * Note: Parameters guaranteed valid by caller + * ******************************************************************************/ acpi_status -acpi_rs_set_srs_method_data(acpi_handle handle, struct acpi_buffer *in_buffer) +acpi_rs_set_srs_method_data(struct acpi_namespace_node *node, + struct acpi_buffer *in_buffer) { - struct acpi_parameter_info info; - union acpi_operand_object *params[2]; + struct acpi_evaluate_info *info; + union acpi_operand_object *args[2]; acpi_status status; struct acpi_buffer buffer; ACPI_FUNCTION_TRACE(rs_set_srs_method_data); - /* Parameters guaranteed valid by caller */ + /* Allocate and initialize the evaluation information block */ + + info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); + if (!info) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + info->prefix_node = node; + info->pathname = METHOD_NAME__SRS; + info->parameters = args; + info->parameter_type = ACPI_PARAM_ARGS; + info->flags = ACPI_IGNORE_RETURN_VALUE; /* * The in_buffer parameter will point to a linked list of - * resource parameters. It needs to be formatted into a + * resource parameters. It needs to be formatted into a * byte stream to be sent in as an input parameter to _SRS * * Convert the linked list into a byte stream @@ -677,42 +694,36 @@ acpi_rs_set_srs_method_data(acpi_handle handle, struct acpi_buffer *in_buffer) buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; status = acpi_rs_create_aml_resources(in_buffer->pointer, &buffer); if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + goto cleanup; } - /* Init the param object */ + /* Create and initialize the method parameter object */ - params[0] = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER); - if (!params[0]) { - acpi_os_free(buffer.pointer); - return_ACPI_STATUS(AE_NO_MEMORY); + args[0] = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER); + if (!args[0]) { + /* + * Must free the buffer allocated above (otherwise it is freed + * later) + */ + ACPI_FREE(buffer.pointer); + status = AE_NO_MEMORY; + goto cleanup; } - /* Set up the parameter object */ - - params[0]->buffer.length = (u32) buffer.length; - params[0]->buffer.pointer = buffer.pointer; - params[0]->common.flags = AOPOBJ_DATA_VALID; - params[1] = NULL; + args[0]->buffer.length = (u32) buffer.length; + args[0]->buffer.pointer = buffer.pointer; + args[0]->common.flags = AOPOBJ_DATA_VALID; + args[1] = NULL; - info.node = handle; - info.parameters = params; - info.parameter_type = ACPI_PARAM_ARGS; + /* Execute the method, no return value is expected */ - /* Execute the method, no return value */ + status = acpi_ns_evaluate(info); - status = acpi_ns_evaluate_relative(METHOD_NAME__SRS, &info); - if (ACPI_SUCCESS(status)) { - - /* Delete any return object (especially if implicit_return is enabled) */ - - if (info.return_object) { - acpi_ut_remove_reference(info.return_object); - } - } + /* Clean up and return the status from acpi_ns_evaluate */ - /* Clean up and return the status from acpi_ns_evaluate_relative */ + acpi_ut_remove_reference(args[0]); - acpi_ut_remove_reference(params[0]); + cleanup: + ACPI_FREE(info); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/resources/rsxface.c b/drivers/acpi/resources/rsxface.c index 8c1628c12cc..1999e2ab7da 100644 --- a/drivers/acpi/resources/rsxface.c +++ b/drivers/acpi/resources/rsxface.c @@ -43,6 +43,7 @@ #include #include +#include #define _COMPONENT ACPI_RESOURCES ACPI_MODULE_NAME("rsxface") @@ -66,19 +67,80 @@ ACPI_MODULE_NAME("rsxface") static acpi_status acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context); +static acpi_status +acpi_rs_validate_parameters(acpi_handle device_handle, + struct acpi_buffer *buffer, + struct acpi_namespace_node **return_node); + +/******************************************************************************* + * + * FUNCTION: acpi_rs_validate_parameters + * + * PARAMETERS: device_handle - Handle to a device + * Buffer - Pointer to a data buffer + * return_node - Pointer to where the device node is returned + * + * RETURN: Status + * + * DESCRIPTION: Common parameter validation for resource interfaces + * + ******************************************************************************/ + +static acpi_status +acpi_rs_validate_parameters(acpi_handle device_handle, + struct acpi_buffer *buffer, + struct acpi_namespace_node **return_node) +{ + acpi_status status; + struct acpi_namespace_node *node; + + ACPI_FUNCTION_TRACE(rs_validate_parameters); + + /* + * Must have a valid handle to an ACPI device + */ + if (!device_handle) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + node = acpi_ns_map_handle_to_node(device_handle); + if (!node) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + if (node->type != ACPI_TYPE_DEVICE) { + return_ACPI_STATUS(AE_TYPE); + } + + /* + * Validate the user buffer object + * + * if there is a non-zero buffer length we also need a valid pointer in + * the buffer. If it's a zero buffer length, we'll be returning the + * needed buffer size (later), so keep going. + */ + status = acpi_ut_validate_buffer(buffer); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + *return_node = node; + return_ACPI_STATUS(AE_OK); +} + /******************************************************************************* * * FUNCTION: acpi_get_irq_routing_table * - * PARAMETERS: device_handle - a handle to the Bus device we are querying - * ret_buffer - a pointer to a buffer to receive the + * PARAMETERS: device_handle - Handle to the Bus device we are querying + * ret_buffer - Pointer to a buffer to receive the * current resources for the device * * RETURN: Status * * DESCRIPTION: This function is called to get the IRQ routing table for a - * specific bus. The caller must first acquire a handle for the - * desired bus. The routine table is placed in the buffer pointed + * specific bus. The caller must first acquire a handle for the + * desired bus. The routine table is placed in the buffer pointed * to by the ret_buffer variable parameter. * * If the function fails an appropriate status will be returned @@ -94,25 +156,18 @@ acpi_get_irq_routing_table(acpi_handle device_handle, struct acpi_buffer *ret_buffer) { acpi_status status; + struct acpi_namespace_node *node; ACPI_FUNCTION_TRACE(acpi_get_irq_routing_table); - /* - * Must have a valid handle and buffer, So we have to have a handle - * and a return buffer structure, and if there is a non-zero buffer length - * we also need a valid pointer in the buffer. If it's a zero buffer length, - * we'll be returning the needed buffer size, so keep going. - */ - if (!device_handle) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } + /* Validate parameters then dispatch to internal routine */ - status = acpi_ut_validate_buffer(ret_buffer); + status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } - status = acpi_rs_get_prt_method_data(device_handle, ret_buffer); + status = acpi_rs_get_prt_method_data(node, ret_buffer); return_ACPI_STATUS(status); } @@ -122,16 +177,16 @@ ACPI_EXPORT_SYMBOL(acpi_get_irq_routing_table) * * FUNCTION: acpi_get_current_resources * - * PARAMETERS: device_handle - a handle to the device object for the + * PARAMETERS: device_handle - Handle to the device object for the * device we are querying - * ret_buffer - a pointer to a buffer to receive the + * ret_buffer - Pointer to a buffer to receive the * current resources for the device * * RETURN: Status * * DESCRIPTION: This function is called to get the current resources for a - * specific device. The caller must first acquire a handle for - * the desired device. The resource data is placed in the buffer + * specific device. The caller must first acquire a handle for + * the desired device. The resource data is placed in the buffer * pointed to by the ret_buffer variable parameter. * * If the function fails an appropriate status will be returned @@ -146,25 +201,18 @@ acpi_get_current_resources(acpi_handle device_handle, struct acpi_buffer *ret_buffer) { acpi_status status; + struct acpi_namespace_node *node; ACPI_FUNCTION_TRACE(acpi_get_current_resources); - /* - * Must have a valid handle and buffer, So we have to have a handle - * and a return buffer structure, and if there is a non-zero buffer length - * we also need a valid pointer in the buffer. If it's a zero buffer length, - * we'll be returning the needed buffer size, so keep going. - */ - if (!device_handle) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } + /* Validate parameters then dispatch to internal routine */ - status = acpi_ut_validate_buffer(ret_buffer); + status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } - status = acpi_rs_get_crs_method_data(device_handle, ret_buffer); + status = acpi_rs_get_crs_method_data(node, ret_buffer); return_ACPI_STATUS(status); } @@ -175,16 +223,16 @@ ACPI_EXPORT_SYMBOL(acpi_get_current_resources) * * FUNCTION: acpi_get_possible_resources * - * PARAMETERS: device_handle - a handle to the device object for the + * PARAMETERS: device_handle - Handle to the device object for the * device we are querying - * ret_buffer - a pointer to a buffer to receive the + * ret_buffer - Pointer to a buffer to receive the * resources for the device * * RETURN: Status * * DESCRIPTION: This function is called to get a list of the possible resources - * for a specific device. The caller must first acquire a handle - * for the desired device. The resource data is placed in the + * for a specific device. The caller must first acquire a handle + * for the desired device. The resource data is placed in the * buffer pointed to by the ret_buffer variable. * * If the function fails an appropriate status will be returned @@ -196,140 +244,38 @@ acpi_get_possible_resources(acpi_handle device_handle, struct acpi_buffer *ret_buffer) { acpi_status status; + struct acpi_namespace_node *node; ACPI_FUNCTION_TRACE(acpi_get_possible_resources); - /* - * Must have a valid handle and buffer, So we have to have a handle - * and a return buffer structure, and if there is a non-zero buffer length - * we also need a valid pointer in the buffer. If it's a zero buffer length, - * we'll be returning the needed buffer size, so keep going. - */ - if (!device_handle) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } + /* Validate parameters then dispatch to internal routine */ - status = acpi_ut_validate_buffer(ret_buffer); + status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } - status = acpi_rs_get_prs_method_data(device_handle, ret_buffer); + status = acpi_rs_get_prs_method_data(node, ret_buffer); return_ACPI_STATUS(status); } ACPI_EXPORT_SYMBOL(acpi_get_possible_resources) #endif /* ACPI_FUTURE_USAGE */ -/******************************************************************************* - * - * FUNCTION: acpi_walk_resources - * - * PARAMETERS: device_handle - Handle to the device object for the - * device we are querying - * Name - Method name of the resources we want - * (METHOD_NAME__CRS or METHOD_NAME__PRS) - * user_function - Called for each resource - * Context - Passed to user_function - * - * RETURN: Status - * - * DESCRIPTION: Retrieves the current or possible resource list for the - * specified device. The user_function is called once for - * each resource in the list. - * - ******************************************************************************/ -acpi_status -acpi_walk_resources(acpi_handle device_handle, - char *name, - acpi_walk_resource_callback user_function, void *context) -{ - acpi_status status; - struct acpi_buffer buffer; - struct acpi_resource *resource; - struct acpi_resource *resource_end; - - ACPI_FUNCTION_TRACE(acpi_walk_resources); - - /* Parameter validation */ - - if (!device_handle || !user_function || !name || - (!ACPI_COMPARE_NAME(name, METHOD_NAME__CRS) && - !ACPI_COMPARE_NAME(name, METHOD_NAME__PRS))) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - /* Get the _CRS or _PRS resource list */ - - buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; - status = acpi_rs_get_method_data(device_handle, name, &buffer); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Buffer now contains the resource list */ - - resource = ACPI_CAST_PTR(struct acpi_resource, buffer.pointer); - resource_end = - ACPI_ADD_PTR(struct acpi_resource, buffer.pointer, buffer.length); - - /* Walk the resource list until the end_tag is found (or buffer end) */ - - while (resource < resource_end) { - - /* Sanity check the resource */ - - if (resource->type > ACPI_RESOURCE_TYPE_MAX) { - status = AE_AML_INVALID_RESOURCE_TYPE; - break; - } - - /* Invoke the user function, abort on any error returned */ - - status = user_function(resource, context); - if (ACPI_FAILURE(status)) { - if (status == AE_CTRL_TERMINATE) { - - /* This is an OK termination by the user function */ - - status = AE_OK; - } - break; - } - - /* end_tag indicates end-of-list */ - - if (resource->type == ACPI_RESOURCE_TYPE_END_TAG) { - break; - } - - /* Get the next resource descriptor */ - - resource = - ACPI_ADD_PTR(struct acpi_resource, resource, - resource->length); - } - - ACPI_FREE(buffer.pointer); - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_walk_resources) - /******************************************************************************* * * FUNCTION: acpi_set_current_resources * - * PARAMETERS: device_handle - a handle to the device object for the - * device we are changing the resources of - * in_buffer - a pointer to a buffer containing the + * PARAMETERS: device_handle - Handle to the device object for the + * device we are setting resources + * in_buffer - Pointer to a buffer containing the * resources to be set for the device * * RETURN: Status * * DESCRIPTION: This function is called to set the current resources for a - * specific device. The caller must first acquire a handle for - * the desired device. The resource data is passed to the routine + * specific device. The caller must first acquire a handle for + * the desired device. The resource data is passed to the routine * the buffer pointed to by the in_buffer variable. * ******************************************************************************/ @@ -338,17 +284,24 @@ acpi_set_current_resources(acpi_handle device_handle, struct acpi_buffer *in_buffer) { acpi_status status; + struct acpi_namespace_node *node; ACPI_FUNCTION_TRACE(acpi_set_current_resources); - /* Must have a valid handle and buffer */ + /* Validate the buffer, don't allow zero length */ - if ((!device_handle) || - (!in_buffer) || (!in_buffer->pointer) || (!in_buffer->length)) { + if ((!in_buffer) || (!in_buffer->pointer) || (!in_buffer->length)) { return_ACPI_STATUS(AE_BAD_PARAMETER); } - status = acpi_rs_set_srs_method_data(device_handle, in_buffer); + /* Validate parameters then dispatch to internal routine */ + + status = acpi_rs_validate_parameters(device_handle, in_buffer, &node); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + status = acpi_rs_set_srs_method_data(node, in_buffer); return_ACPI_STATUS(status); } @@ -358,15 +311,14 @@ ACPI_EXPORT_SYMBOL(acpi_set_current_resources) * * FUNCTION: acpi_resource_to_address64 * - * PARAMETERS: Resource - Pointer to a resource - * Out - Pointer to the users's return - * buffer (a struct - * struct acpi_resource_address64) + * PARAMETERS: Resource - Pointer to a resource + * Out - Pointer to the users's return buffer + * (a struct acpi_resource_address64) * * RETURN: Status * * DESCRIPTION: If the resource is an address16, address32, or address64, - * copy it to the address64 return buffer. This saves the + * copy it to the address64 return buffer. This saves the * caller from having to duplicate code for different-sized * addresses. * @@ -418,12 +370,12 @@ ACPI_EXPORT_SYMBOL(acpi_resource_to_address64) * * FUNCTION: acpi_get_vendor_resource * - * PARAMETERS: device_handle - Handle for the parent device object - * Name - Method name for the parent resource - * (METHOD_NAME__CRS or METHOD_NAME__PRS) - * Uuid - Pointer to the UUID to be matched. - * includes both subtype and 16-byte UUID - * ret_buffer - Where the vendor resource is returned + * PARAMETERS: device_handle - Handle for the parent device object + * Name - Method name for the parent resource + * (METHOD_NAME__CRS or METHOD_NAME__PRS) + * Uuid - Pointer to the UUID to be matched. + * includes both subtype and 16-byte UUID + * ret_buffer - Where the vendor resource is returned * * RETURN: Status * @@ -525,3 +477,99 @@ acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context) } ACPI_EXPORT_SYMBOL(acpi_rs_match_vendor_resource) + +/******************************************************************************* + * + * FUNCTION: acpi_walk_resources + * + * PARAMETERS: device_handle - Handle to the device object for the + * device we are querying + * Name - Method name of the resources we want + * (METHOD_NAME__CRS or METHOD_NAME__PRS) + * user_function - Called for each resource + * Context - Passed to user_function + * + * RETURN: Status + * + * DESCRIPTION: Retrieves the current or possible resource list for the + * specified device. The user_function is called once for + * each resource in the list. + * + ******************************************************************************/ + +acpi_status +acpi_walk_resources(acpi_handle device_handle, + char *name, + acpi_walk_resource_callback user_function, void *context) +{ + acpi_status status; + struct acpi_buffer buffer; + struct acpi_resource *resource; + struct acpi_resource *resource_end; + + ACPI_FUNCTION_TRACE(acpi_walk_resources); + + /* Parameter validation */ + + if (!device_handle || !user_function || !name || + (!ACPI_COMPARE_NAME(name, METHOD_NAME__CRS) && + !ACPI_COMPARE_NAME(name, METHOD_NAME__PRS))) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Get the _CRS or _PRS resource list */ + + buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; + status = acpi_rs_get_method_data(device_handle, name, &buffer); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Buffer now contains the resource list */ + + resource = ACPI_CAST_PTR(struct acpi_resource, buffer.pointer); + resource_end = + ACPI_ADD_PTR(struct acpi_resource, buffer.pointer, buffer.length); + + /* Walk the resource list until the end_tag is found (or buffer end) */ + + while (resource < resource_end) { + + /* Sanity check the resource */ + + if (resource->type > ACPI_RESOURCE_TYPE_MAX) { + status = AE_AML_INVALID_RESOURCE_TYPE; + break; + } + + /* Invoke the user function, abort on any error returned */ + + status = user_function(resource, context); + if (ACPI_FAILURE(status)) { + if (status == AE_CTRL_TERMINATE) { + + /* This is an OK termination by the user function */ + + status = AE_OK; + } + break; + } + + /* end_tag indicates end-of-list */ + + if (resource->type == ACPI_RESOURCE_TYPE_END_TAG) { + break; + } + + /* Get the next resource descriptor */ + + resource = + ACPI_ADD_PTR(struct acpi_resource, resource, + resource->length); + } + + ACPI_FREE(buffer.pointer); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_walk_resources) diff --git a/drivers/acpi/tables/tbget.c b/drivers/acpi/tables/tbget.c index 3a4f46ca388..99eacceff56 100644 --- a/drivers/acpi/tables/tbget.c +++ b/drivers/acpi/tables/tbget.c @@ -417,7 +417,7 @@ acpi_tb_get_this_table(struct acpi_pointer *address, * * PARAMETERS: table_type - one of the defined table types * Instance - Which table of this type - * table_ptr_loc - pointer to location to place the pointer for + * return_table - pointer to location to place the pointer for * return * * RETURN: Status @@ -428,58 +428,34 @@ acpi_tb_get_this_table(struct acpi_pointer *address, acpi_status acpi_tb_get_table_ptr(acpi_table_type table_type, - u32 instance, struct acpi_table_header **table_ptr_loc) + u32 instance, struct acpi_table_header **return_table) { struct acpi_table_desc *table_desc; u32 i; ACPI_FUNCTION_TRACE(tb_get_table_ptr); - if (!acpi_gbl_DSDT) { - return_ACPI_STATUS(AE_NO_ACPI_TABLES); - } - if (table_type > ACPI_TABLE_ID_MAX) { return_ACPI_STATUS(AE_BAD_PARAMETER); } - /* - * For all table types (Single/Multiple), the first - * instance is always in the list head. - */ - if (instance == 1) { - - /* Get the first */ - - *table_ptr_loc = NULL; - if (acpi_gbl_table_lists[table_type].next) { - *table_ptr_loc = - acpi_gbl_table_lists[table_type].next->pointer; - } - return_ACPI_STATUS(AE_OK); - } - - /* Check for instance out of range */ + /* Check for instance out of range of the current table count */ if (instance > acpi_gbl_table_lists[table_type].count) { return_ACPI_STATUS(AE_NOT_EXIST); } - /* Walk the list to get the desired table - * Since the if (Instance == 1) check above checked for the - * first table, setting table_desc equal to the .Next member - * is actually pointing to the second table. Therefore, we - * need to walk from the 2nd table until we reach the Instance - * that the user is looking for and return its table pointer. + /* + * Walk the list to get the desired table + * Note: Instance is one-based */ table_desc = acpi_gbl_table_lists[table_type].next; - for (i = 2; i < instance; i++) { + for (i = 1; i < instance; i++) { table_desc = table_desc->next; } /* We are now pointing to the requested table's descriptor */ - *table_ptr_loc = table_desc->pointer; - + *return_table = table_desc->pointer; return_ACPI_STATUS(AE_OK); } diff --git a/drivers/acpi/tables/tbrsdt.c b/drivers/acpi/tables/tbrsdt.c index 494965229fa..abcb08c2592 100644 --- a/drivers/acpi/tables/tbrsdt.c +++ b/drivers/acpi/tables/tbrsdt.c @@ -78,7 +78,7 @@ acpi_status acpi_tb_verify_rsdp(struct acpi_pointer *address) */ status = acpi_os_map_memory(address->pointer.physical, sizeof(struct rsdp_descriptor), - (void *)&rsdp); + ACPI_CAST_PTR(void, &rsdp)); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -95,11 +95,16 @@ acpi_status acpi_tb_verify_rsdp(struct acpi_pointer *address) goto cleanup; } - /* The RSDP supplied is OK */ + /* RSDP is ok. Init the table info */ table_info.pointer = ACPI_CAST_PTR(struct acpi_table_header, rsdp); table_info.length = sizeof(struct rsdp_descriptor); - table_info.allocation = ACPI_MEM_MAPPED; + + if (address->pointer_type == ACPI_PHYSICAL_POINTER) { + table_info.allocation = ACPI_MEM_MAPPED; + } else { + table_info.allocation = ACPI_MEM_NOT_ALLOCATED; + } /* Save the table pointers and allocation info */ diff --git a/drivers/acpi/utilities/utalloc.c b/drivers/acpi/utilities/utalloc.c index 65a7c2ed9aa..7940fc1bd69 100644 --- a/drivers/acpi/utilities/utalloc.c +++ b/drivers/acpi/utilities/utalloc.c @@ -61,24 +61,6 @@ acpi_status acpi_ut_create_caches(void) { acpi_status status; -#ifdef ACPI_DBG_TRACK_ALLOCATIONS - - /* Memory allocation lists */ - - status = acpi_ut_create_list("Acpi-Global", 0, &acpi_gbl_global_list); - if (ACPI_FAILURE(status)) { - return (status); - } - - status = - acpi_ut_create_list("Acpi-Namespace", - sizeof(struct acpi_namespace_node), - &acpi_gbl_ns_node_list); - if (ACPI_FAILURE(status)) { - return (status); - } -#endif - /* Object Caches, for frequently used objects */ status = @@ -125,6 +107,24 @@ acpi_status acpi_ut_create_caches(void) return (status); } +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + + /* Memory allocation lists */ + + status = acpi_ut_create_list("Acpi-Global", 0, &acpi_gbl_global_list); + if (ACPI_FAILURE(status)) { + return (status); + } + + status = + acpi_ut_create_list("Acpi-Namespace", + sizeof(struct acpi_namespace_node), + &acpi_gbl_ns_node_list); + if (ACPI_FAILURE(status)) { + return (status); + } +#endif + return (AE_OK); } @@ -158,6 +158,21 @@ acpi_status acpi_ut_delete_caches(void) (void)acpi_os_delete_cache(acpi_gbl_ps_node_ext_cache); acpi_gbl_ps_node_ext_cache = NULL; +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + + /* Debug only - display leftover memory allocation, if any */ + + acpi_ut_dump_allocations(ACPI_UINT32_MAX, NULL); + + /* Free memory lists */ + + acpi_os_free(acpi_gbl_global_list); + acpi_gbl_global_list = NULL; + + acpi_os_free(acpi_gbl_ns_node_list); + acpi_gbl_ns_node_list = NULL; +#endif + return (AE_OK); } diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c index 0bb4b59b280..67b9f325c6f 100644 --- a/drivers/acpi/utilities/utdelete.c +++ b/drivers/acpi/utilities/utdelete.c @@ -319,11 +319,9 @@ acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action) new_count = count; /* - * Perform the reference count action - * (increment, decrement, or force delete) + * Perform the reference count action (increment, decrement, force delete) */ switch (action) { - case REF_INCREMENT: new_count++; @@ -360,7 +358,6 @@ acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action) if (new_count == 0) { acpi_ut_delete_internal_obj(object); } - break; case REF_FORCE_DELETE: @@ -385,13 +382,10 @@ acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action) * (A deleted object will have a huge reference count) */ if (count > ACPI_MAX_REFERENCE_COUNT) { - ACPI_WARNING((AE_INFO, - "Large Reference Count (%X) in object %p", - count, object)); + "Large Reference Count (%X) in object %p", count, + object)); } - - return; } /******************************************************************************* @@ -417,7 +411,7 @@ acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action) ******************************************************************************/ acpi_status -acpi_ut_update_object_reference(union acpi_operand_object * object, u16 action) +acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) { acpi_status status = AE_OK; union acpi_generic_state *state_list = NULL; @@ -521,11 +515,11 @@ acpi_ut_update_object_reference(union acpi_operand_object * object, u16 action) case ACPI_TYPE_REGION: default: - break; /* No subobjects */ + break; /* No subobjects for all other types */ } /* - * Now we can update the count in the main object. This can only + * Now we can update the count in the main object. This can only * happen after we update the sub-objects in case this causes the * main object to be deleted. */ @@ -606,8 +600,8 @@ void acpi_ut_remove_reference(union acpi_operand_object *object) ACPI_FUNCTION_TRACE_PTR(ut_remove_reference, object); /* - * Allow a NULL pointer to be passed in, just ignore it. This saves - * each caller from having to check. Also, ignore NS nodes. + * Allow a NULL pointer to be passed in, just ignore it. This saves + * each caller from having to check. Also, ignore NS nodes. * */ if (!object || @@ -627,7 +621,7 @@ void acpi_ut_remove_reference(union acpi_operand_object *object) /* * Decrement the reference count, and only actually delete the object - * if the reference count becomes 0. (Must also decrement the ref count + * if the reference count becomes 0. (Must also decrement the ref count * of all subobjects!) */ (void)acpi_ut_update_object_reference(object, REF_DECREMENT); diff --git a/drivers/acpi/utilities/uteval.c b/drivers/acpi/utilities/uteval.c index 444d3a502c4..d6d7121583c 100644 --- a/drivers/acpi/utilities/uteval.c +++ b/drivers/acpi/utilities/uteval.c @@ -181,19 +181,26 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node, u32 expected_return_btypes, union acpi_operand_object **return_desc) { - struct acpi_parameter_info info; + struct acpi_evaluate_info *info; acpi_status status; u32 return_btype; ACPI_FUNCTION_TRACE(ut_evaluate_object); - info.node = prefix_node; - info.parameters = NULL; - info.parameter_type = ACPI_PARAM_ARGS; + /* Allocate the evaluation information block */ + + info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); + if (!info) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + info->prefix_node = prefix_node; + info->pathname = path; + info->parameter_type = ACPI_PARAM_ARGS; /* Evaluate the object/method */ - status = acpi_ns_evaluate_relative(path, &info); + status = acpi_ns_evaluate(info); if (ACPI_FAILURE(status)) { if (status == AE_NOT_FOUND) { ACPI_DEBUG_PRINT((ACPI_DB_EXEC, @@ -205,25 +212,25 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node, prefix_node, path, status); } - return_ACPI_STATUS(status); + goto cleanup; } /* Did we get a return object? */ - if (!info.return_object) { + if (!info->return_object) { if (expected_return_btypes) { ACPI_ERROR_METHOD("No object was returned from", prefix_node, path, AE_NOT_EXIST); - return_ACPI_STATUS(AE_NOT_EXIST); + status = AE_NOT_EXIST; } - return_ACPI_STATUS(AE_OK); + goto cleanup; } /* Map the return object type to the bitmapped type */ - switch (ACPI_GET_OBJECT_TYPE(info.return_object)) { + switch (ACPI_GET_OBJECT_TYPE(info->return_object)) { case ACPI_TYPE_INTEGER: return_btype = ACPI_BTYPE_INTEGER; break; @@ -251,8 +258,8 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node, * happen frequently if the "implicit return" feature is enabled. * Just delete the return object and return AE_OK. */ - acpi_ut_remove_reference(info.return_object); - return_ACPI_STATUS(AE_OK); + acpi_ut_remove_reference(info->return_object); + goto cleanup; } /* Is the return object one of the expected types? */ @@ -264,19 +271,23 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node, ACPI_ERROR((AE_INFO, "Type returned from %s was incorrect: %s, expected Btypes: %X", path, - acpi_ut_get_object_type_name(info.return_object), + acpi_ut_get_object_type_name(info->return_object), expected_return_btypes)); /* On error exit, we must delete the return object */ - acpi_ut_remove_reference(info.return_object); - return_ACPI_STATUS(AE_TYPE); + acpi_ut_remove_reference(info->return_object); + status = AE_TYPE; + goto cleanup; } /* Object type is OK, return it */ - *return_desc = info.return_object; - return_ACPI_STATUS(AE_OK); + *return_desc = info->return_object; + + cleanup: + ACPI_FREE(info); + return_ACPI_STATUS(status); } /******************************************************************************* diff --git a/drivers/acpi/utilities/utinit.c b/drivers/acpi/utilities/utinit.c index c65747d3c88..ff76055eb7d 100644 --- a/drivers/acpi/utilities/utinit.c +++ b/drivers/acpi/utilities/utinit.c @@ -228,6 +228,7 @@ void acpi_ut_subsystem_shutdown(void) /* Subsystem appears active, go ahead and shut it down */ acpi_gbl_shutdown = TRUE; + acpi_gbl_startup_flags = 0; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Shutting down ACPI Subsystem\n")); /* Close the acpi_event Handling */ @@ -245,12 +246,5 @@ void acpi_ut_subsystem_shutdown(void) /* Purge the local caches */ (void)acpi_ut_delete_caches(); - - /* Debug only - display leftover memory allocation, if any */ - -#ifdef ACPI_DBG_TRACK_ALLOCATIONS - acpi_ut_dump_allocations(ACPI_UINT32_MAX, NULL); -#endif - return_VOID; } diff --git a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c index 874467117ce..5c75d35ad1c 100644 --- a/drivers/acpi/utilities/utmisc.c +++ b/drivers/acpi/utilities/utmisc.c @@ -601,7 +601,8 @@ acpi_name acpi_ut_repair_name(acpi_name name) * FUNCTION: acpi_ut_strtoul64 * * PARAMETERS: String - Null terminated string - * Base - Radix of the string: 10, 16, or ACPI_ANY_BASE + * Base - Radix of the string: 16 or ACPI_ANY_BASE; + * ACPI_ANY_BASE means 'in behalf of to_integer' * ret_integer - Where the converted integer is returned * * RETURN: Status and Converted value @@ -617,16 +618,17 @@ acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer) u32 this_digit = 0; acpi_integer return_value = 0; acpi_integer quotient; + acpi_integer dividend; + u32 to_integer_op = (base == ACPI_ANY_BASE); + u32 mode32 = (acpi_gbl_integer_byte_width == 4); + u8 valid_digits = 0; + u8 sign_of0x = 0; + u8 term = 0; ACPI_FUNCTION_TRACE(ut_stroul64); - if ((!string) || !(*string)) { - goto error_exit; - } - switch (base) { case ACPI_ANY_BASE: - case 10: case 16: break; @@ -635,39 +637,45 @@ acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer) return_ACPI_STATUS(AE_BAD_PARAMETER); } + if (!string) { + goto error_exit; + } + /* Skip over any white space in the buffer */ - while (ACPI_IS_SPACE(*string) || *string == '\t') { + while ((*string) && (ACPI_IS_SPACE(*string) || *string == '\t')) { string++; } - /* - * If the input parameter Base is zero, then we need to - * determine if it is decimal or hexadecimal: - */ - if (base == 0) { + if (to_integer_op) { + /* + * Base equal to ACPI_ANY_BASE means 'to_integer operation case'. + * We need to determine if it is decimal or hexadecimal. + */ if ((*string == '0') && (ACPI_TOLOWER(*(string + 1)) == 'x')) { + sign_of0x = 1; base = 16; + + /* Skip over the leading '0x' */ string += 2; } else { base = 10; } } - /* - * For hexadecimal base, skip over the leading - * 0 or 0x, if they are present. - */ - if ((base == 16) && - (*string == '0') && (ACPI_TOLOWER(*(string + 1)) == 'x')) { - string += 2; + /* Any string left? Check that '0x' is not followed by white space. */ + + if (!(*string) || ACPI_IS_SPACE(*string) || *string == '\t') { + if (to_integer_op) { + goto error_exit; + } else { + goto all_done; + } } - /* Any string left? */ + dividend = (mode32) ? ACPI_UINT32_MAX : ACPI_UINT64_MAX; - if (!(*string)) { - goto error_exit; - } + /* At least one character in the string here */ /* Main loop: convert the string to a 64-bit integer */ @@ -677,14 +685,12 @@ acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer) /* Convert ASCII 0-9 to Decimal value */ this_digit = ((u8) * string) - '0'; - } else { - if (base == 10) { + } else if (base == 10) { - /* Digit is out of range */ - - goto error_exit; - } + /* Digit is out of range; possible in to_integer case only */ + term = 1; + } else { this_digit = (u8) ACPI_TOUPPER(*string); if (ACPI_IS_XDIGIT((char)this_digit)) { @@ -692,22 +698,49 @@ acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer) this_digit = this_digit - 'A' + 10; } else { - /* - * We allow non-hex chars, just stop now, same as end-of-string. - * See ACPI spec, string-to-integer conversion. - */ + term = 1; + } + } + + if (term) { + if (to_integer_op) { + goto error_exit; + } else { break; } + } else if ((valid_digits == 0) && (this_digit == 0) + && !sign_of0x) { + + /* Skip zeros */ + string++; + continue; + } + + valid_digits++; + + if (sign_of0x + && ((valid_digits > 16) + || ((valid_digits > 8) && mode32))) { + /* + * This is to_integer operation case. + * No any restrictions for string-to-integer conversion, + * see ACPI spec. + */ + goto error_exit; } /* Divide the digit into the correct position */ (void) - acpi_ut_short_divide((ACPI_INTEGER_MAX - - (acpi_integer) this_digit), base, - "ient, NULL); + acpi_ut_short_divide((dividend - (acpi_integer) this_digit), + base, "ient, NULL); + if (return_value > quotient) { - goto error_exit; + if (to_integer_op) { + goto error_exit; + } else { + break; + } } return_value *= base; @@ -717,6 +750,8 @@ acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer) /* All done, normal exit */ + all_done: + *ret_integer = return_value; return_ACPI_STATUS(AE_OK); diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h index 0177ed3dc80..8b52e44ad2a 100644 --- a/include/acpi/acconfig.h +++ b/include/acpi/acconfig.h @@ -63,7 +63,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20060512 +#define ACPI_CA_VERSION 0x20060526 /* * OS name, used for the _OS object. The _OS object is essentially obsolete, diff --git a/include/acpi/acdispat.h b/include/acpi/acdispat.h index fcf03eb4137..288f84903af 100644 --- a/include/acpi/acdispat.h +++ b/include/acpi/acdispat.h @@ -304,7 +304,7 @@ acpi_ds_init_aml_walk(struct acpi_walk_state *walk_state, struct acpi_namespace_node *method_node, u8 * aml_start, u32 aml_length, - struct acpi_parameter_info *info, u8 pass_number); + struct acpi_evaluate_info *info, u8 pass_number); acpi_status acpi_ds_obj_stack_pop_and_delete(u32 pop_count, diff --git a/include/acpi/acnamesp.h b/include/acpi/acnamesp.h index 2ef8540c0fb..83b52f9f899 100644 --- a/include/acpi/acnamesp.h +++ b/include/acpi/acnamesp.h @@ -173,13 +173,7 @@ acpi_ns_dump_objects(acpi_object_type type, /* * nseval - Namespace evaluation functions */ -acpi_status acpi_ns_evaluate_by_handle(struct acpi_parameter_info *info); - -acpi_status -acpi_ns_evaluate_by_name(char *pathname, struct acpi_parameter_info *info); - -acpi_status -acpi_ns_evaluate_relative(char *pathname, struct acpi_parameter_info *info); +acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info); /* * nsnames - Name and Scope manipulation @@ -202,9 +196,9 @@ u8 acpi_ns_pattern_match(struct acpi_namespace_node *obj_node, char *search_for); acpi_status -acpi_ns_get_node_by_path(char *external_pathname, - struct acpi_namespace_node *in_prefix_node, - u32 flags, struct acpi_namespace_node **out_node); +acpi_ns_get_node(struct acpi_namespace_node *prefix_node, + char *external_pathname, + u32 flags, struct acpi_namespace_node **out_node); acpi_size acpi_ns_get_pathname_length(struct acpi_namespace_node *node); @@ -247,10 +241,10 @@ acpi_ns_search_and_enter(u32 entry_name, u32 flags, struct acpi_namespace_node **ret_node); acpi_status -acpi_ns_search_node(u32 entry_name, - struct acpi_namespace_node *node, - acpi_object_type type, - struct acpi_namespace_node **ret_node); +acpi_ns_search_one_scope(u32 entry_name, + struct acpi_namespace_node *node, + acpi_object_type type, + struct acpi_namespace_node **ret_node); void acpi_ns_install_node(struct acpi_walk_state *walk_state, diff --git a/include/acpi/acopcode.h b/include/acpi/acopcode.h index e6d78bd9e90..7659a46bc43 100644 --- a/include/acpi/acopcode.h +++ b/include/acpi/acopcode.h @@ -94,7 +94,7 @@ #define ARGP_CONCAT_RES_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) #define ARGP_COND_REF_OF_OP ARGP_LIST2 (ARGP_SUPERNAME, ARGP_SUPERNAME) #define ARGP_CONTINUE_OP ARG_NONE -#define ARGP_COPY_OP ARGP_LIST2 (ARGP_SUPERNAME, ARGP_SIMPLENAME) +#define ARGP_COPY_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_SIMPLENAME) #define ARGP_CREATE_BIT_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME) #define ARGP_CREATE_BYTE_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME) #define ARGP_CREATE_DWORD_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME) diff --git a/include/acpi/acparser.h b/include/acpi/acparser.h index de14492a598..9d49d3c41cd 100644 --- a/include/acpi/acparser.h +++ b/include/acpi/acparser.h @@ -71,7 +71,7 @@ /* * psxface - Parser external interfaces */ -acpi_status acpi_ps_execute_method(struct acpi_parameter_info *info); +acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info); /* * psargs - Parse AML opcode arguments diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h index 982e7ea177e..8f473c83b7c 100644 --- a/include/acpi/acpiosxf.h +++ b/include/acpi/acpiosxf.h @@ -58,8 +58,7 @@ typedef enum { OSL_GPE_HANDLER, OSL_DEBUGGER_THREAD, OSL_EC_POLL_HANDLER, - OSL_EC_BURST_HANDLER, - + OSL_EC_BURST_HANDLER } acpi_execute_type; #define ACPI_NO_UNIT_LIMIT ((u32) -1) @@ -217,7 +216,6 @@ acpi_os_derive_pci_id(acpi_handle rhandle, /* * Miscellaneous */ - acpi_status acpi_os_validate_interface(char *interface); acpi_status @@ -265,11 +263,4 @@ char *acpi_os_get_next_filename(void *dir_handle); void acpi_os_close_directory(void *dir_handle); -/* - * Debug - */ -void -acpi_os_dbg_assert(void *failed_assertion, - void *file_name, u32 line_number, char *message); - #endif /* __ACPIOSXF_H__ */ diff --git a/include/acpi/acresrc.h b/include/acpi/acresrc.h index bdd6584bbcf..ad11fc13fbe 100644 --- a/include/acpi/acresrc.h +++ b/include/acpi/acresrc.h @@ -164,23 +164,26 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, /* * rsutils */ + acpi_status -acpi_rs_get_prt_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer); +acpi_rs_get_prt_method_data(struct acpi_namespace_node *node, + struct acpi_buffer *ret_buffer); acpi_status -acpi_rs_get_crs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer); +acpi_rs_get_crs_method_data(struct acpi_namespace_node *node, + struct acpi_buffer *ret_buffer); -#ifdef ACPI_FUTURE_USAGE acpi_status -acpi_rs_get_prs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer); -#endif /* ACPI_FUTURE_USAGE */ +acpi_rs_get_prs_method_data(struct acpi_namespace_node *node, + struct acpi_buffer *ret_buffer); acpi_status acpi_rs_get_method_data(acpi_handle handle, char *path, struct acpi_buffer *ret_buffer); acpi_status -acpi_rs_set_srs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer); +acpi_rs_set_srs_method_data(struct acpi_namespace_node *node, + struct acpi_buffer *ret_buffer); /* * rscalc diff --git a/include/acpi/acstruct.h b/include/acpi/acstruct.h index b8a6d6110d5..5e8095f0f78 100644 --- a/include/acpi/acstruct.h +++ b/include/acpi/acstruct.h @@ -53,17 +53,25 @@ ****************************************************************************/ /* - * Walk state - current state of a parse tree walk. Used for both a leisurely stroll through - * the tree (for whatever reason), and for control method execution. + * Walk state - current state of a parse tree walk. Used for both a leisurely + * stroll through the tree (for whatever reason), and for control method + * execution. */ #define ACPI_NEXT_OP_DOWNWARD 1 #define ACPI_NEXT_OP_UPWARD 2 +/* + * Groups of definitions for walk_type used for different implementations of + * walkers (never simultaneously) - flags for interpreter: + */ #define ACPI_WALK_NON_METHOD 0 -#define ACPI_WALK_METHOD 1 -#define ACPI_WALK_METHOD_RESTART 2 -#define ACPI_WALK_CONST_REQUIRED 3 -#define ACPI_WALK_CONST_OPTIONAL 4 +#define ACPI_WALK_METHOD 0x01 +#define ACPI_WALK_METHOD_RESTART 0x02 + +/* Flags for i_aSL compiler only */ + +#define ACPI_WALK_CONST_REQUIRED 0x10 +#define ACPI_WALK_CONST_OPTIONAL 0x20 struct acpi_walk_state { struct acpi_walk_state *next; /* Next walk_state in list */ @@ -134,32 +142,6 @@ struct acpi_init_walk_info { struct acpi_table_desc *table_desc; }; -/* Info used by acpi_ns_initialize_devices */ - -struct acpi_device_walk_info { - u16 device_count; - u16 num_STA; - u16 num_INI; - struct acpi_table_desc *table_desc; -}; - -/* TBD: [Restructure] Merge with struct above */ - -struct acpi_walk_info { - u32 debug_level; - u32 count; - acpi_owner_id owner_id; - u8 display_type; -}; - -/* Display Types */ - -#define ACPI_DISPLAY_SUMMARY (u8) 0 -#define ACPI_DISPLAY_OBJECTS (u8) 1 -#define ACPI_DISPLAY_MASK (u8) 1 - -#define ACPI_DISPLAY_SHORT (u8) 2 - struct acpi_get_devices_info { acpi_walk_callback user_function; void *context; @@ -192,16 +174,21 @@ union acpi_aml_operands { } mid; }; -/* Internal method parameter list */ - -struct acpi_parameter_info { - struct acpi_namespace_node *node; +/* + * Structure used to pass object evaluation parameters. + * Purpose is to reduce CPU stack use. + */ +struct acpi_evaluate_info { + struct acpi_namespace_node *prefix_node; + char *pathname; union acpi_operand_object *obj_desc; union acpi_operand_object **parameters; + struct acpi_namespace_node *resolved_node; union acpi_operand_object *return_object; u8 pass_number; u8 parameter_type; u8 return_object_type; + u8 flags; }; /* Types for parameter_type above */ @@ -209,4 +196,35 @@ struct acpi_parameter_info { #define ACPI_PARAM_ARGS 0 #define ACPI_PARAM_GPE 1 +/* Values for Flags above */ + +#define ACPI_IGNORE_RETURN_VALUE 1 + +/* Info used by acpi_ns_initialize_devices */ + +struct acpi_device_walk_info { + u16 device_count; + u16 num_STA; + u16 num_INI; + struct acpi_table_desc *table_desc; + struct acpi_evaluate_info *evaluate_info; +}; + +/* TBD: [Restructure] Merge with struct above */ + +struct acpi_walk_info { + u32 debug_level; + u32 count; + acpi_owner_id owner_id; + u8 display_type; +}; + +/* Display Types */ + +#define ACPI_DISPLAY_SUMMARY (u8) 0 +#define ACPI_DISPLAY_OBJECTS (u8) 1 +#define ACPI_DISPLAY_MASK (u8) 1 + +#define ACPI_DISPLAY_SHORT (u8) 2 + #endif -- cgit v1.2.3 From 4c90ece249992c7a2e3fc921e5cdb8eb92193067 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 8 Jun 2006 16:29:00 -0400 Subject: ACPI: ACPICA 20060608 Converted the locking mutex used for the ACPI hardware to a spinlock. This change should eliminate all problems caused by attempting to acquire a semaphore at interrupt level, and it means that all ACPICA external interfaces that directly access the ACPI hardware can be safely called from interrupt level. Fixed a regression introduced in 20060526 where the ACPI device initialization could be prematurely aborted with an AE_NOT_FOUND if a device did not have an optional _INI method. Fixed an IndexField issue where a write to the Data Register should be limited in size to the AccessSize (width) of the IndexField itself. (BZ 433, Fiodor Suietov) Fixed problem reports (Valery Podrezov) integrated: - Allow store of ThermalZone objects to Debug object. http://bugzilla.kernel.org/show_bug.cgi?id=5369 http://bugzilla.kernel.org/show_bug.cgi?id=5370 Fixed problem reports (Fiodor Suietov) integrated: - acpi_get_table_header() doesn't handle multiple instances correctly (BZ 364) Removed four global mutexes that were obsolete and were no longer being used. Signed-off-by: Bob Moore Signed-off-by: Len Brown --- drivers/acpi/dispatcher/dsmethod.c | 4 +-- drivers/acpi/events/evgpe.c | 17 ++++++++--- drivers/acpi/executer/exfldio.c | 8 ++++-- drivers/acpi/executer/exoparg1.c | 10 +++---- drivers/acpi/executer/exresnte.c | 6 ++-- drivers/acpi/executer/exresolv.c | 20 +++++++++++-- drivers/acpi/executer/exutils.c | 4 +-- drivers/acpi/hardware/hwregs.c | 59 ++++++++++++-------------------------- drivers/acpi/namespace/nsinit.c | 5 +++- drivers/acpi/osl.c | 3 -- drivers/acpi/tables/tbutils.c | 17 ++++------- drivers/acpi/utilities/utglobal.c | 4 +-- drivers/acpi/utilities/utmutex.c | 26 +++++++++++------ include/acpi/acconfig.h | 11 ++----- include/acpi/acglobal.h | 6 +++- include/acpi/aclocal.h | 55 ++++++++++++++++++----------------- 16 files changed, 132 insertions(+), 123 deletions(-) diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c index 21f05998627..bc9aca4e740 100644 --- a/drivers/acpi/dispatcher/dsmethod.c +++ b/drivers/acpi/dispatcher/dsmethod.c @@ -507,7 +507,7 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc, * If this is the last thread executing the method, * we have additional cleanup to perform */ - status = acpi_ut_acquire_mutex(ACPI_MTX_PARSER); + status = acpi_ut_acquire_mutex(ACPI_MTX_CONTROL_METHOD); if (ACPI_FAILURE(status)) { return_VOID; } @@ -600,7 +600,7 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc, } exit: - (void)acpi_ut_release_mutex(ACPI_MTX_PARSER); + (void)acpi_ut_release_mutex(ACPI_MTX_CONTROL_METHOD); return_VOID; } diff --git a/drivers/acpi/events/evgpe.c b/drivers/acpi/events/evgpe.c index 23fe53ba737..f01d339407f 100644 --- a/drivers/acpi/events/evgpe.c +++ b/drivers/acpi/events/evgpe.c @@ -382,6 +382,7 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) u32 status_reg; u32 enable_reg; acpi_cpu_flags flags; + acpi_cpu_flags hw_flags; acpi_native_uint i; acpi_native_uint j; @@ -393,9 +394,12 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) return (int_status); } - /* Examine all GPE blocks attached to this interrupt level */ + /* We need to hold the GPE lock now, hardware lock in the loop */ flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); + + /* Examine all GPE blocks attached to this interrupt level */ + gpe_block = gpe_xrupt_list->gpe_block_list_head; while (gpe_block) { /* @@ -409,6 +413,8 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) gpe_register_info = &gpe_block->register_info[i]; + hw_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock); + /* Read the Status Register */ status = @@ -417,6 +423,8 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) &gpe_register_info-> status_address); if (ACPI_FAILURE(status)) { + acpi_os_release_lock(acpi_gbl_hardware_lock, + hw_flags); goto unlock_and_exit; } @@ -427,6 +435,8 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) &enable_reg, &gpe_register_info-> enable_address); + acpi_os_release_lock(acpi_gbl_hardware_lock, hw_flags); + if (ACPI_FAILURE(status)) { goto unlock_and_exit; } @@ -499,7 +509,6 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) { struct acpi_gpe_event_info *gpe_event_info = (void *)context; - u32 gpe_number = 0; acpi_status status; struct acpi_gpe_event_info local_gpe_event_info; struct acpi_evaluate_info *info; @@ -565,10 +574,10 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, - "While evaluating method [%4.4s] for GPE[%2X]", + "While evaluating GPE method [%4.4s]", acpi_ut_get_node_name (local_gpe_event_info.dispatch. - method_node), gpe_number)); + method_node))); } } diff --git a/drivers/acpi/executer/exfldio.c b/drivers/acpi/executer/exfldio.c index 3b7c4352ec5..051053f7ccc 100644 --- a/drivers/acpi/executer/exfldio.c +++ b/drivers/acpi/executer/exfldio.c @@ -785,6 +785,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, { acpi_status status; acpi_integer mask; + acpi_integer width_mask; acpi_integer merged_datum; acpi_integer raw_datum = 0; u32 field_offset = 0; @@ -809,8 +810,11 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, /* Compute the number of datums (access width data items) */ + width_mask = + ACPI_MASK_BITS_ABOVE(obj_desc->common_field.access_bit_width); mask = - ACPI_MASK_BITS_BELOW(obj_desc->common_field.start_field_bit_offset); + width_mask & ACPI_MASK_BITS_BELOW(obj_desc->common_field. + start_field_bit_offset); datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length, obj_desc->common_field.access_bit_width); @@ -850,7 +854,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, merged_datum = raw_datum >> (obj_desc->common_field.access_bit_width - obj_desc->common_field.start_field_bit_offset); - mask = ACPI_INTEGER_MAX; + mask = width_mask; if (i == datum_count) { break; diff --git a/drivers/acpi/executer/exoparg1.c b/drivers/acpi/executer/exoparg1.c index 8284c52875b..6374d8be88e 100644 --- a/drivers/acpi/executer/exoparg1.c +++ b/drivers/acpi/executer/exoparg1.c @@ -322,8 +322,9 @@ acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state) /* Since the bit position is one-based, subtract from 33 (65) */ - return_desc->integer.value = temp32 == 0 ? 0 : - (ACPI_INTEGER_BIT_SIZE + 1) - temp32; + return_desc->integer.value = + temp32 == + 0 ? 0 : (ACPI_INTEGER_BIT_SIZE + 1) - temp32; break; case AML_FROM_BCD_OP: /* from_bcd (BCDValue, Result) */ @@ -698,6 +699,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) if (ACPI_FAILURE(status)) { goto cleanup; } + /* Allocate a descriptor to hold the type. */ return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); @@ -967,7 +969,6 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) acpi_ut_add_reference (return_desc); } - break; default: @@ -987,7 +988,6 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) if (ACPI_GET_DESCRIPTOR_TYPE(return_desc) == ACPI_DESC_TYPE_NAMED) { - return_desc = acpi_ns_get_attached_object((struct acpi_namespace_node @@ -1002,7 +1002,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) default: ACPI_ERROR((AE_INFO, - "Unknown opcode in ref(%p) - %X", + "Unknown opcode in reference(%p) - %X", operand[0], operand[0]->reference.opcode)); diff --git a/drivers/acpi/executer/exresnte.c b/drivers/acpi/executer/exresnte.c index f9b9f500859..3089b05a136 100644 --- a/drivers/acpi/executer/exresnte.c +++ b/drivers/acpi/executer/exresnte.c @@ -114,10 +114,11 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, /* * Several object types require no further processing: - * 1) Devices rarely have an attached object, return the Node + * 1) Device/Thermal objects don't have a "real" subobject, return the Node * 2) Method locals and arguments have a pseudo-Node */ - if (entry_type == ACPI_TYPE_DEVICE || + if ((entry_type == ACPI_TYPE_DEVICE) || + (entry_type == ACPI_TYPE_THERMAL) || (node->flags & (ANOBJ_METHOD_ARG | ANOBJ_METHOD_LOCAL))) { return_ACPI_STATUS(AE_OK); } @@ -216,7 +217,6 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, case ACPI_TYPE_METHOD: case ACPI_TYPE_POWER: case ACPI_TYPE_PROCESSOR: - case ACPI_TYPE_THERMAL: case ACPI_TYPE_EVENT: case ACPI_TYPE_REGION: diff --git a/drivers/acpi/executer/exresolv.c b/drivers/acpi/executer/exresolv.c index 006bba035d5..6499de87801 100644 --- a/drivers/acpi/executer/exresolv.c +++ b/drivers/acpi/executer/exresolv.c @@ -257,10 +257,24 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, case AML_INT_NAMEPATH_OP: /* Reference to a named object */ - /* Get the object pointed to by the namespace node */ + /* Dereference the name */ + + if ((stack_desc->reference.node->type == + ACPI_TYPE_DEVICE) + || (stack_desc->reference.node->type == + ACPI_TYPE_THERMAL)) { + + /* These node types do not have 'real' subobjects */ + + *stack_ptr = (void *)stack_desc->reference.node; + } else { + /* Get the object pointed to by the namespace node */ + + *stack_ptr = + (stack_desc->reference.node)->object; + acpi_ut_add_reference(*stack_ptr); + } - *stack_ptr = (stack_desc->reference.node)->object; - acpi_ut_add_reference(*stack_ptr); acpi_ut_remove_reference(stack_desc); break; diff --git a/drivers/acpi/executer/exutils.c b/drivers/acpi/executer/exutils.c index 3ef8cd703e0..982c8b65876 100644 --- a/drivers/acpi/executer/exutils.c +++ b/drivers/acpi/executer/exutils.c @@ -89,7 +89,7 @@ acpi_status acpi_ex_enter_interpreter(void) ACPI_FUNCTION_TRACE(ex_enter_interpreter); - status = acpi_ut_acquire_mutex(ACPI_MTX_EXECUTE); + status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER); if (ACPI_FAILURE(status)) { ACPI_ERROR((AE_INFO, "Could not acquire interpreter mutex")); } @@ -125,7 +125,7 @@ void acpi_ex_exit_interpreter(void) ACPI_FUNCTION_TRACE(ex_exit_interpreter); - status = acpi_ut_release_mutex(ACPI_MTX_EXECUTE); + status = acpi_ut_release_mutex(ACPI_MTX_INTERPRETER); if (ACPI_FAILURE(status)) { ACPI_ERROR((AE_INFO, "Could not release interpreter mutex")); } diff --git a/drivers/acpi/hardware/hwregs.c b/drivers/acpi/hardware/hwregs.c index 5a3aa8dd8cb..ae142de1950 100644 --- a/drivers/acpi/hardware/hwregs.c +++ b/drivers/acpi/hardware/hwregs.c @@ -61,10 +61,13 @@ ACPI_MODULE_NAME("hwregs") * DESCRIPTION: Clears all fixed and general purpose status bits * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED * + * NOTE: TBD: Flags parameter is obsolete, to be removed + * ******************************************************************************/ acpi_status acpi_hw_clear_acpi_status(u32 flags) { acpi_status status; + acpi_cpu_flags lock_flags = 0; ACPI_FUNCTION_TRACE(hw_clear_acpi_status); @@ -72,12 +75,7 @@ acpi_status acpi_hw_clear_acpi_status(u32 flags) ACPI_BITMASK_ALL_FIXED_STATUS, (u16) acpi_gbl_FADT->xpm1a_evt_blk.address)); - if (flags & ACPI_MTX_LOCK) { - status = acpi_ut_acquire_mutex(ACPI_MTX_HARDWARE); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } + lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock); status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_STATUS, @@ -102,9 +100,7 @@ acpi_status acpi_hw_clear_acpi_status(u32 flags) status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block); unlock_and_exit: - if (flags & ACPI_MTX_LOCK) { - (void)acpi_ut_release_mutex(ACPI_MTX_HARDWARE); - } + acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags); return_ACPI_STATUS(status); } @@ -264,6 +260,8 @@ struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id) * * DESCRIPTION: ACPI bit_register read function. * + * NOTE: TBD: Flags parameter is obsolete, to be removed + * ******************************************************************************/ acpi_status acpi_get_register(u32 register_id, u32 * return_value, u32 flags) @@ -281,23 +279,12 @@ acpi_status acpi_get_register(u32 register_id, u32 * return_value, u32 flags) return_ACPI_STATUS(AE_BAD_PARAMETER); } - if (flags & ACPI_MTX_LOCK) { - status = acpi_ut_acquire_mutex(ACPI_MTX_HARDWARE); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - /* Read from the register */ - status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK, + status = acpi_hw_register_read(ACPI_MTX_LOCK, bit_reg_info->parent_register, ®ister_value); - if (flags & ACPI_MTX_LOCK) { - (void)acpi_ut_release_mutex(ACPI_MTX_HARDWARE); - } - if (ACPI_SUCCESS(status)) { /* Normalize the value that was read */ @@ -331,12 +318,15 @@ ACPI_EXPORT_SYMBOL(acpi_get_register) * * DESCRIPTION: ACPI Bit Register write function. * + * NOTE: TBD: Flags parameter is obsolete, to be removed + * ******************************************************************************/ acpi_status acpi_set_register(u32 register_id, u32 value, u32 flags) { u32 register_value = 0; struct acpi_bit_register_info *bit_reg_info; acpi_status status; + acpi_cpu_flags lock_flags; ACPI_FUNCTION_TRACE_U32(acpi_set_register, register_id); @@ -349,12 +339,7 @@ acpi_status acpi_set_register(u32 register_id, u32 value, u32 flags) return_ACPI_STATUS(AE_BAD_PARAMETER); } - if (flags & ACPI_MTX_LOCK) { - status = acpi_ut_acquire_mutex(ACPI_MTX_HARDWARE); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } + lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock); /* Always do a register read first so we can insert the new bits */ @@ -462,9 +447,7 @@ acpi_status acpi_set_register(u32 register_id, u32 value, u32 flags) unlock_and_exit: - if (flags & ACPI_MTX_LOCK) { - (void)acpi_ut_release_mutex(ACPI_MTX_HARDWARE); - } + acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags); /* Normalize the value that was read */ @@ -500,14 +483,12 @@ acpi_hw_register_read(u8 use_lock, u32 register_id, u32 * return_value) u32 value1 = 0; u32 value2 = 0; acpi_status status; + acpi_cpu_flags lock_flags = 0; ACPI_FUNCTION_TRACE(hw_register_read); if (ACPI_MTX_LOCK == use_lock) { - status = acpi_ut_acquire_mutex(ACPI_MTX_HARDWARE); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } + lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock); } switch (register_id) { @@ -585,7 +566,7 @@ acpi_hw_register_read(u8 use_lock, u32 register_id, u32 * return_value) unlock_and_exit: if (ACPI_MTX_LOCK == use_lock) { - (void)acpi_ut_release_mutex(ACPI_MTX_HARDWARE); + acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags); } if (ACPI_SUCCESS(status)) { @@ -613,14 +594,12 @@ acpi_hw_register_read(u8 use_lock, u32 register_id, u32 * return_value) acpi_status acpi_hw_register_write(u8 use_lock, u32 register_id, u32 value) { acpi_status status; + acpi_cpu_flags lock_flags = 0; ACPI_FUNCTION_TRACE(hw_register_write); if (ACPI_MTX_LOCK == use_lock) { - status = acpi_ut_acquire_mutex(ACPI_MTX_HARDWARE); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } + lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock); } switch (register_id) { @@ -710,7 +689,7 @@ acpi_status acpi_hw_register_write(u8 use_lock, u32 register_id, u32 value) unlock_and_exit: if (ACPI_MTX_LOCK == use_lock) { - (void)acpi_ut_release_mutex(ACPI_MTX_HARDWARE); + acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags); } return_ACPI_STATUS(status); diff --git a/drivers/acpi/namespace/nsinit.c b/drivers/acpi/namespace/nsinit.c index 1c9ca6e0531..aec8488c001 100644 --- a/drivers/acpi/namespace/nsinit.c +++ b/drivers/acpi/namespace/nsinit.c @@ -557,10 +557,13 @@ acpi_ns_init_one_device(acpi_handle obj_handle, ACPI_EXCEPTION((AE_INFO, status, "during %s._INI execution", scope_name)); ACPI_FREE(scope_name); - status = AE_OK; } #endif + /* Ignore errors from above */ + + status = AE_OK; + /* * The _INI method has been run if present; call the Global Initialization * Handler for this device. diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index e80ca4730a4..1bb558adee6 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -795,9 +795,6 @@ acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout) ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Waiting for semaphore[%p|%d|%d]\n", handle, units, timeout)); - if (in_atomic()) - timeout = 0; - switch (timeout) { /* * No Wait: diff --git a/drivers/acpi/tables/tbutils.c b/drivers/acpi/tables/tbutils.c index 5f144037651..209a401801e 100644 --- a/drivers/acpi/tables/tbutils.c +++ b/drivers/acpi/tables/tbutils.c @@ -160,12 +160,8 @@ acpi_tb_validate_table_header(struct acpi_table_header *table_header) ACPI_MOVE_32_TO_32(&signature, table_header->signature); if (!acpi_ut_valid_acpi_name(signature)) { - ACPI_ERROR((AE_INFO, - "Table signature at %p [%p] has invalid characters", - table_header, &signature)); - - ACPI_WARNING((AE_INFO, "Invalid table signature found: [%4.4s]", - ACPI_CAST_PTR(char, &signature))); + ACPI_ERROR((AE_INFO, "Invalid table signature 0x%8.8X", + signature)); ACPI_DUMP_BUFFER(table_header, sizeof(struct acpi_table_header)); @@ -176,12 +172,9 @@ acpi_tb_validate_table_header(struct acpi_table_header *table_header) if (table_header->length < sizeof(struct acpi_table_header)) { ACPI_ERROR((AE_INFO, - "Invalid length in table header %p name %4.4s", - table_header, (char *)&signature)); - - ACPI_WARNING((AE_INFO, - "Invalid table header length (0x%X) found", - (u32) table_header->length)); + "Invalid length 0x%X in table with signature %4.4s", + (u32) table_header->length, + ACPI_CAST_PTR(char, &signature))); ACPI_DUMP_BUFFER(table_header, sizeof(struct acpi_table_header)); diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c index 9450f9b5bfb..e5999c65c0b 100644 --- a/drivers/acpi/utilities/utglobal.c +++ b/drivers/acpi/utilities/utglobal.c @@ -691,7 +691,7 @@ char *acpi_ut_get_descriptor_name(void *object) char *acpi_ut_get_mutex_name(u32 mutex_id) { - if (mutex_id > MAX_MUTEX) { + if (mutex_id > ACPI_MAX_MUTEX) { return ("Invalid Mutex ID"); } @@ -760,7 +760,7 @@ void acpi_ut_init_globals(void) /* Mutex locked flags */ - for (i = 0; i < NUM_MUTEX; i++) { + for (i = 0; i < ACPI_NUM_MUTEX; i++) { acpi_gbl_mutex_info[i].mutex = NULL; acpi_gbl_mutex_info[i].thread_id = ACPI_MUTEX_NOT_ACQUIRED; acpi_gbl_mutex_info[i].use_count = 0; diff --git a/drivers/acpi/utilities/utmutex.c b/drivers/acpi/utilities/utmutex.c index b851f7be5d5..25eb34369af 100644 --- a/drivers/acpi/utilities/utmutex.c +++ b/drivers/acpi/utilities/utmutex.c @@ -73,14 +73,21 @@ acpi_status acpi_ut_mutex_initialize(void) /* * Create each of the predefined mutex objects */ - for (i = 0; i < NUM_MUTEX; i++) { + for (i = 0; i < ACPI_NUM_MUTEX; i++) { status = acpi_ut_create_mutex(i); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } } + /* Create the spinlocks for use at interrupt level */ + status = acpi_os_create_lock(&acpi_gbl_gpe_lock); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + status = acpi_os_create_lock(&acpi_gbl_hardware_lock); return_ACPI_STATUS(status); } @@ -105,11 +112,14 @@ void acpi_ut_mutex_terminate(void) /* * Delete each predefined mutex object */ - for (i = 0; i < NUM_MUTEX; i++) { + for (i = 0; i < ACPI_NUM_MUTEX; i++) { (void)acpi_ut_delete_mutex(i); } + /* Delete the spinlocks */ + acpi_os_delete_lock(acpi_gbl_gpe_lock); + acpi_os_delete_lock(acpi_gbl_hardware_lock); return_VOID; } @@ -131,7 +141,7 @@ static acpi_status acpi_ut_create_mutex(acpi_mutex_handle mutex_id) ACPI_FUNCTION_TRACE_U32(ut_create_mutex, mutex_id); - if (mutex_id > MAX_MUTEX) { + if (mutex_id > ACPI_MAX_MUTEX) { return_ACPI_STATUS(AE_BAD_PARAMETER); } @@ -165,7 +175,7 @@ static acpi_status acpi_ut_delete_mutex(acpi_mutex_handle mutex_id) ACPI_FUNCTION_TRACE_U32(ut_delete_mutex, mutex_id); - if (mutex_id > MAX_MUTEX) { + if (mutex_id > ACPI_MAX_MUTEX) { return_ACPI_STATUS(AE_BAD_PARAMETER); } @@ -196,7 +206,7 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id) ACPI_FUNCTION_NAME(ut_acquire_mutex); - if (mutex_id > MAX_MUTEX) { + if (mutex_id > ACPI_MAX_MUTEX) { return (AE_BAD_PARAMETER); } @@ -213,7 +223,7 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id) * the mutex ordering rule. This indicates a coding error somewhere in * the ACPI subsystem code. */ - for (i = mutex_id; i < MAX_MUTEX; i++) { + for (i = mutex_id; i < ACPI_MAX_MUTEX; i++) { if (acpi_gbl_mutex_info[i].thread_id == this_thread_id) { if (i == mutex_id) { ACPI_ERROR((AE_INFO, @@ -284,7 +294,7 @@ acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id) "Thread %X releasing Mutex [%s]\n", this_thread_id, acpi_ut_get_mutex_name(mutex_id))); - if (mutex_id > MAX_MUTEX) { + if (mutex_id > ACPI_MAX_MUTEX) { return (AE_BAD_PARAMETER); } @@ -309,7 +319,7 @@ acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id) * ordering rule. This indicates a coding error somewhere in * the ACPI subsystem code. */ - for (i = mutex_id; i < MAX_MUTEX; i++) { + for (i = mutex_id; i < ACPI_MAX_MUTEX; i++) { if (acpi_gbl_mutex_info[i].thread_id == this_thread_id) { if (i == mutex_id) { continue; diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h index 8b52e44ad2a..b9beceb3314 100644 --- a/include/acpi/acconfig.h +++ b/include/acpi/acconfig.h @@ -63,7 +63,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20060526 +#define ACPI_CA_VERSION 0x20060608 /* * OS name, used for the _OS object. The _OS object is essentially obsolete, @@ -171,15 +171,8 @@ #define ACPI_MAX_ADDRESS_SPACE 255 /* Array sizes. Used for range checking also */ -#define ACPI_MAX_MATCH_OPCODE 5 -#if 0 -#define ACPI_NUM_ACCESS_TYPES 6 -#define ACPI_NUM_UPDATE_RULES 3 -#define ACPI_NUM_LOCK_RULES 2 -#define ACPI_NUM_FIELD_NAMES 2 -#define ACPI_NUM_OPCODES 256 -#endif +#define ACPI_MAX_MATCH_OPCODE 5 /* RSDP checksums */ diff --git a/include/acpi/acglobal.h b/include/acpi/acglobal.h index 9297f293b2c..14531d48f6b 100644 --- a/include/acpi/acglobal.h +++ b/include/acpi/acglobal.h @@ -186,7 +186,7 @@ extern struct acpi_table_support acpi_gbl_table_data[ACPI_TABLE_ID_MAX + 1]; * actual OS mutex handles, indexed by the local ACPI_MUTEX_HANDLEs. * (The table maps local handles to the real OS handles) */ -ACPI_EXTERN struct acpi_mutex_info acpi_gbl_mutex_info[NUM_MUTEX]; +ACPI_EXTERN struct acpi_mutex_info acpi_gbl_mutex_info[ACPI_NUM_MUTEX]; /***************************************************************************** * @@ -314,7 +314,11 @@ ACPI_EXTERN struct acpi_fixed_event_handler ACPI_EXTERN struct acpi_gpe_xrupt_info *acpi_gbl_gpe_xrupt_list_head; ACPI_EXTERN struct acpi_gpe_block_info *acpi_gbl_gpe_fadt_blocks[ACPI_MAX_GPE_BLOCKS]; + +/* Spinlocks */ + ACPI_EXTERN acpi_handle acpi_gbl_gpe_lock; +ACPI_EXTERN acpi_handle acpi_gbl_hardware_lock; /***************************************************************************** * diff --git a/include/acpi/aclocal.h b/include/acpi/aclocal.h index 98c697e3c48..1eeca7adca9 100644 --- a/include/acpi/aclocal.h +++ b/include/acpi/aclocal.h @@ -72,52 +72,55 @@ union acpi_parse_object; * Predefined handles for the mutex objects used within the subsystem * All mutex objects are automatically created by acpi_ut_mutex_initialize. * - * The acquire/release ordering protocol is implied via this list. Mutexes + * The acquire/release ordering protocol is implied via this list. Mutexes * with a lower value must be acquired before mutexes with a higher value. * - * NOTE: any changes here must be reflected in the acpi_gbl_mutex_names table also! + * NOTE: any changes here must be reflected in the acpi_gbl_mutex_names + * table below also! */ -#define ACPI_MTX_EXECUTE 0 -#define ACPI_MTX_INTERPRETER 1 -#define ACPI_MTX_PARSER 2 -#define ACPI_MTX_DISPATCHER 3 -#define ACPI_MTX_TABLES 4 -#define ACPI_MTX_OP_REGIONS 5 -#define ACPI_MTX_NAMESPACE 6 -#define ACPI_MTX_EVENTS 7 -#define ACPI_MTX_HARDWARE 8 -#define ACPI_MTX_CACHES 9 -#define ACPI_MTX_MEMORY 10 -#define ACPI_MTX_DEBUG_CMD_COMPLETE 11 -#define ACPI_MTX_DEBUG_CMD_READY 12 - -#define MAX_MUTEX 12 -#define NUM_MUTEX MAX_MUTEX+1 +#define ACPI_MTX_INTERPRETER 0 /* AML Interpreter, main lock */ +#define ACPI_MTX_CONTROL_METHOD 1 /* Control method termination [TBD: may no longer be necessary] */ +#define ACPI_MTX_TABLES 2 /* Data for ACPI tables */ +#define ACPI_MTX_NAMESPACE 3 /* ACPI Namespace */ +#define ACPI_MTX_EVENTS 4 /* Data for ACPI events */ +#define ACPI_MTX_CACHES 5 /* Internal caches, general purposes */ +#define ACPI_MTX_MEMORY 6 /* Debug memory tracking lists */ +#define ACPI_MTX_DEBUG_CMD_COMPLETE 7 /* AML debugger */ +#define ACPI_MTX_DEBUG_CMD_READY 8 /* AML debugger */ + +#define ACPI_MAX_MUTEX 8 +#define ACPI_NUM_MUTEX ACPI_MAX_MUTEX+1 #if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) #ifdef DEFINE_ACPI_GLOBALS -/* Names for the mutexes used in the subsystem */ +/* Debug names for the mutexes above */ -static char *acpi_gbl_mutex_names[] = { - "ACPI_MTX_Execute", +static char *acpi_gbl_mutex_names[ACPI_NUM_MUTEX] = { "ACPI_MTX_Interpreter", - "ACPI_MTX_Parser", - "ACPI_MTX_Dispatcher", + "ACPI_MTX_Method", "ACPI_MTX_Tables", - "ACPI_MTX_OpRegions", "ACPI_MTX_Namespace", "ACPI_MTX_Events", - "ACPI_MTX_Hardware", "ACPI_MTX_Caches", "ACPI_MTX_Memory", "ACPI_MTX_DebugCmdComplete", - "ACPI_MTX_DebugCmdReady", + "ACPI_MTX_DebugCmdReady" }; #endif #endif +/* + * Predefined handles for spinlocks used within the subsystem. + * These spinlocks are created by acpi_ut_mutex_initialize + */ +#define ACPI_LOCK_GPES 0 +#define ACPI_LOCK_HARDWARE 1 + +#define ACPI_MAX_LOCK 1 +#define ACPI_NUM_LOCK ACPI_MAX_LOCK+1 + /* Owner IDs are used to track namespace nodes for selective deletion */ typedef u8 acpi_owner_id; -- cgit v1.2.3 From bf72aeba2ffef599d1d386425c9e46b82be657cd Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Thu, 15 Jun 2006 10:45:18 +1000 Subject: powerpc: Use 64k pages without needing cache-inhibited large pages Some POWER5+ machines can do 64k hardware pages for normal memory but not for cache-inhibited pages. This patch lets us use 64k hardware pages for most user processes on such machines (assuming the kernel has been configured with CONFIG_PPC_64K_PAGES=y). User processes start out using 64k pages and get switched to 4k pages if they use any non-cacheable mappings. With this, we use 64k pages for the vmalloc region and 4k pages for the imalloc region. If anything creates a non-cacheable mapping in the vmalloc region, the vmalloc region will get switched to 4k pages. I don't know of any driver other than the DRM that would do this, though, and these machines don't have AGP. When a region gets switched from 64k pages to 4k pages, we do not have to clear out all the 64k HPTEs from the hash table immediately. We use the _PAGE_COMBO bit in the Linux PTE to indicate whether the page was hashed in as a 64k page or a set of 4k pages. If hash_page is trying to insert a 4k page for a Linux PTE and it sees that it has already been inserted as a 64k page, it first invalidates the 64k HPTE before inserting the 4k HPTE. The hash invalidation routines also use the _PAGE_COMBO bit, to determine whether to look for a 64k HPTE or a set of 4k HPTEs to remove. With those two changes, we can tolerate a mix of 4k and 64k HPTEs in the hash table, and they will all get removed when the address space is torn down. Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/asm-offsets.c | 2 + arch/powerpc/kernel/prom.c | 3 ++ arch/powerpc/mm/hash_low_64.S | 28 +++++++++++++ arch/powerpc/mm/hash_utils_64.c | 84 ++++++++++++++++++++++++++++++++++----- arch/powerpc/mm/mmu_context_64.c | 3 ++ arch/powerpc/mm/slb.c | 29 +++++++------- arch/powerpc/mm/slb_low.S | 17 +++++--- arch/powerpc/mm/tlb_64.c | 5 ++- include/asm-powerpc/mmu.h | 13 ++++++ include/asm-powerpc/paca.h | 1 + include/asm-powerpc/pgtable-4k.h | 2 + include/asm-powerpc/pgtable-64k.h | 2 + include/asm-powerpc/pgtable.h | 10 +---- 13 files changed, 160 insertions(+), 39 deletions(-) diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index aa0486d552a..ff294054892 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -122,6 +122,8 @@ int main(void) DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache)); DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr)); DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id)); + DEFINE(PACACONTEXTSLLP, offsetof(struct paca_struct, context.sllp)); + DEFINE(PACAVMALLOCSLLP, offsetof(struct paca_struct, vmalloc_sllp)); #ifdef CONFIG_HUGETLB_PAGE DEFINE(PACALOWHTLBAREAS, offsetof(struct paca_struct, context.low_htlb_areas)); DEFINE(PACAHIGHHTLBAREAS, offsetof(struct paca_struct, context.high_htlb_areas)); diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 969f4abcc0b..d77d24a89b3 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -948,7 +948,10 @@ static struct ibm_pa_feature { {CPU_FTR_CTRL, 0, 0, 3, 0}, {CPU_FTR_NOEXECUTE, 0, 0, 6, 0}, {CPU_FTR_NODSISRALIGN, 0, 1, 1, 1}, +#if 0 + /* put this back once we know how to test if firmware does 64k IO */ {CPU_FTR_CI_LARGE_PAGE, 0, 1, 2, 0}, +#endif }; static void __init check_cpu_pa_features(unsigned long node) diff --git a/arch/powerpc/mm/hash_low_64.S b/arch/powerpc/mm/hash_low_64.S index 106fba39198..52e91423895 100644 --- a/arch/powerpc/mm/hash_low_64.S +++ b/arch/powerpc/mm/hash_low_64.S @@ -369,6 +369,7 @@ _GLOBAL(__hash_page_4K) rlwinm r30,r4,32-9+7,31-7,31-7 /* _PAGE_RW -> _PAGE_DIRTY */ or r30,r30,r31 ori r30,r30,_PAGE_BUSY | _PAGE_ACCESSED | _PAGE_HASHPTE + oris r30,r30,_PAGE_COMBO@h /* Write the linux PTE atomically (setting busy) */ stdcx. r30,0,r6 bne- 1b @@ -428,6 +429,14 @@ END_FTR_SECTION(CPU_FTR_NOEXECUTE|CPU_FTR_COHERENT_ICACHE, CPU_FTR_NOEXECUTE) andi. r0,r31,_PAGE_HASHPTE li r26,0 /* Default hidx */ beq htab_insert_pte + + /* + * Check if the pte was already inserted into the hash table + * as a 64k HW page, and invalidate the 64k HPTE if so. + */ + andis. r0,r31,_PAGE_COMBO@h + beq htab_inval_old_hpte + ld r6,STK_PARM(r6)(r1) ori r26,r6,0x8000 /* Load the hidx mask */ ld r26,0(r26) @@ -498,6 +507,19 @@ _GLOBAL(htab_call_hpte_remove) /* Try all again */ b htab_insert_pte + /* + * Call out to C code to invalidate an 64k HW HPTE that is + * useless now that the segment has been switched to 4k pages. + */ +htab_inval_old_hpte: + mr r3,r29 /* virtual addr */ + mr r4,r31 /* PTE.pte */ + li r5,0 /* PTE.hidx */ + li r6,MMU_PAGE_64K /* psize */ + ld r7,STK_PARM(r8)(r1) /* local */ + bl .flush_hash_page + b htab_insert_pte + htab_bail_ok: li r3,0 b htab_bail @@ -638,6 +660,12 @@ _GLOBAL(__hash_page_64K) * is changing this PTE anyway and might hash it. */ bne- ht64_bail_ok +BEGIN_FTR_SECTION + /* Check if PTE has the cache-inhibit bit set */ + andi. r0,r31,_PAGE_NO_CACHE + /* If so, bail out and refault as a 4k page */ + bne- ht64_bail_ok +END_FTR_SECTION_IFCLR(CPU_FTR_CI_LARGE_PAGE) /* Prepare new PTE value (turn access RW into DIRTY, then * add BUSY,HASHPTE and ACCESSED) */ diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index b43ed92ef47..d03fd2b4445 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -92,10 +92,15 @@ unsigned long htab_size_bytes; unsigned long htab_hash_mask; int mmu_linear_psize = MMU_PAGE_4K; int mmu_virtual_psize = MMU_PAGE_4K; +int mmu_vmalloc_psize = MMU_PAGE_4K; +int mmu_io_psize = MMU_PAGE_4K; #ifdef CONFIG_HUGETLB_PAGE int mmu_huge_psize = MMU_PAGE_16M; unsigned int HPAGE_SHIFT; #endif +#ifdef CONFIG_PPC_64K_PAGES +int mmu_ci_restrictions; +#endif /* There are definitions of page sizes arrays to be used when none * is provided by the firmware. @@ -308,20 +313,31 @@ static void __init htab_init_page_sizes(void) else if (mmu_psize_defs[MMU_PAGE_1M].shift) mmu_linear_psize = MMU_PAGE_1M; +#ifdef CONFIG_PPC_64K_PAGES /* * Pick a size for the ordinary pages. Default is 4K, we support - * 64K if cache inhibited large pages are supported by the - * processor + * 64K for user mappings and vmalloc if supported by the processor. + * We only use 64k for ioremap if the processor + * (and firmware) support cache-inhibited large pages. + * If not, we use 4k and set mmu_ci_restrictions so that + * hash_page knows to switch processes that use cache-inhibited + * mappings to 4k pages. */ -#ifdef CONFIG_PPC_64K_PAGES - if (mmu_psize_defs[MMU_PAGE_64K].shift && - cpu_has_feature(CPU_FTR_CI_LARGE_PAGE)) + if (mmu_psize_defs[MMU_PAGE_64K].shift) { mmu_virtual_psize = MMU_PAGE_64K; + mmu_vmalloc_psize = MMU_PAGE_64K; + if (cpu_has_feature(CPU_FTR_CI_LARGE_PAGE)) + mmu_io_psize = MMU_PAGE_64K; + else + mmu_ci_restrictions = 1; + } #endif - printk(KERN_DEBUG "Page orders: linear mapping = %d, others = %d\n", + printk(KERN_DEBUG "Page orders: linear mapping = %d, " + "virtual = %d, io = %d\n", mmu_psize_defs[mmu_linear_psize].shift, - mmu_psize_defs[mmu_virtual_psize].shift); + mmu_psize_defs[mmu_virtual_psize].shift, + mmu_psize_defs[mmu_io_psize].shift); #ifdef CONFIG_HUGETLB_PAGE /* Init large page size. Currently, we pick 16M or 1M depending @@ -556,6 +572,7 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap) pte_t *ptep; cpumask_t tmp; int rc, user_region = 0, local = 0; + int psize; DBG_LOW("hash_page(ea=%016lx, access=%lx, trap=%lx\n", ea, access, trap); @@ -575,10 +592,15 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap) return 1; } vsid = get_vsid(mm->context.id, ea); + psize = mm->context.user_psize; break; case VMALLOC_REGION_ID: mm = &init_mm; vsid = get_kernel_vsid(ea); + if (ea < VMALLOC_END) + psize = mmu_vmalloc_psize; + else + psize = mmu_io_psize; break; default: /* Not a valid range @@ -629,7 +651,40 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap) #ifndef CONFIG_PPC_64K_PAGES rc = __hash_page_4K(ea, access, vsid, ptep, trap, local); #else - if (mmu_virtual_psize == MMU_PAGE_64K) + if (mmu_ci_restrictions) { + /* If this PTE is non-cacheable, switch to 4k */ + if (psize == MMU_PAGE_64K && + (pte_val(*ptep) & _PAGE_NO_CACHE)) { + if (user_region) { + psize = MMU_PAGE_4K; + mm->context.user_psize = MMU_PAGE_4K; + mm->context.sllp = SLB_VSID_USER | + mmu_psize_defs[MMU_PAGE_4K].sllp; + } else if (ea < VMALLOC_END) { + /* + * some driver did a non-cacheable mapping + * in vmalloc space, so switch vmalloc + * to 4k pages + */ + printk(KERN_ALERT "Reducing vmalloc segment " + "to 4kB pages because of " + "non-cacheable mapping\n"); + psize = mmu_vmalloc_psize = MMU_PAGE_4K; + } + } + if (user_region) { + if (psize != get_paca()->context.user_psize) { + get_paca()->context = mm->context; + slb_flush_and_rebolt(); + } + } else if (get_paca()->vmalloc_sllp != + mmu_psize_defs[mmu_vmalloc_psize].sllp) { + get_paca()->vmalloc_sllp = + mmu_psize_defs[mmu_vmalloc_psize].sllp; + slb_flush_and_rebolt(); + } + } + if (psize == MMU_PAGE_64K) rc = __hash_page_64K(ea, access, vsid, ptep, trap, local); else rc = __hash_page_4K(ea, access, vsid, ptep, trap, local); @@ -681,7 +736,18 @@ void hash_preload(struct mm_struct *mm, unsigned long ea, #ifndef CONFIG_PPC_64K_PAGES __hash_page_4K(ea, access, vsid, ptep, trap, local); #else - if (mmu_virtual_psize == MMU_PAGE_64K) + if (mmu_ci_restrictions) { + /* If this PTE is non-cacheable, switch to 4k */ + if (mm->context.user_psize == MMU_PAGE_64K && + (pte_val(*ptep) & _PAGE_NO_CACHE)) { + mm->context.user_psize = MMU_PAGE_4K; + mm->context.sllp = SLB_VSID_USER | + mmu_psize_defs[MMU_PAGE_4K].sllp; + get_paca()->context = mm->context; + slb_flush_and_rebolt(); + } + } + if (mm->context.user_psize == MMU_PAGE_64K) __hash_page_64K(ea, access, vsid, ptep, trap, local); else __hash_page_4K(ea, access, vsid, ptep, trap, local); diff --git a/arch/powerpc/mm/mmu_context_64.c b/arch/powerpc/mm/mmu_context_64.c index 714a84dd8d5..65d18dca266 100644 --- a/arch/powerpc/mm/mmu_context_64.c +++ b/arch/powerpc/mm/mmu_context_64.c @@ -49,6 +49,9 @@ again: } mm->context.id = index; + mm->context.user_psize = mmu_virtual_psize; + mm->context.sllp = SLB_VSID_USER | + mmu_psize_defs[mmu_virtual_psize].sllp; return 0; } diff --git a/arch/powerpc/mm/slb.c b/arch/powerpc/mm/slb.c index 2cc61736fee..6a8bf6c6000 100644 --- a/arch/powerpc/mm/slb.c +++ b/arch/powerpc/mm/slb.c @@ -60,19 +60,19 @@ static inline void create_slbe(unsigned long ea, unsigned long flags, : "memory" ); } -static void slb_flush_and_rebolt(void) +void slb_flush_and_rebolt(void) { /* If you change this make sure you change SLB_NUM_BOLTED * appropriately too. */ - unsigned long linear_llp, virtual_llp, lflags, vflags; + unsigned long linear_llp, vmalloc_llp, lflags, vflags; unsigned long ksp_esid_data; WARN_ON(!irqs_disabled()); linear_llp = mmu_psize_defs[mmu_linear_psize].sllp; - virtual_llp = mmu_psize_defs[mmu_virtual_psize].sllp; + vmalloc_llp = mmu_psize_defs[mmu_vmalloc_psize].sllp; lflags = SLB_VSID_KERNEL | linear_llp; - vflags = SLB_VSID_KERNEL | virtual_llp; + vflags = SLB_VSID_KERNEL | vmalloc_llp; ksp_esid_data = mk_esid_data(get_paca()->kstack, 2); if ((ksp_esid_data & ESID_MASK) == PAGE_OFFSET) @@ -164,11 +164,10 @@ static inline void patch_slb_encoding(unsigned int *insn_addr, void slb_initialize(void) { - unsigned long linear_llp, virtual_llp; + unsigned long linear_llp, vmalloc_llp, io_llp; static int slb_encoding_inited; extern unsigned int *slb_miss_kernel_load_linear; - extern unsigned int *slb_miss_kernel_load_virtual; - extern unsigned int *slb_miss_user_load_normal; + extern unsigned int *slb_miss_kernel_load_io; #ifdef CONFIG_HUGETLB_PAGE extern unsigned int *slb_miss_user_load_huge; unsigned long huge_llp; @@ -178,18 +177,19 @@ void slb_initialize(void) /* Prepare our SLB miss handler based on our page size */ linear_llp = mmu_psize_defs[mmu_linear_psize].sllp; - virtual_llp = mmu_psize_defs[mmu_virtual_psize].sllp; + io_llp = mmu_psize_defs[mmu_io_psize].sllp; + vmalloc_llp = mmu_psize_defs[mmu_vmalloc_psize].sllp; + get_paca()->vmalloc_sllp = SLB_VSID_KERNEL | vmalloc_llp; + if (!slb_encoding_inited) { slb_encoding_inited = 1; patch_slb_encoding(slb_miss_kernel_load_linear, SLB_VSID_KERNEL | linear_llp); - patch_slb_encoding(slb_miss_kernel_load_virtual, - SLB_VSID_KERNEL | virtual_llp); - patch_slb_encoding(slb_miss_user_load_normal, - SLB_VSID_USER | virtual_llp); + patch_slb_encoding(slb_miss_kernel_load_io, + SLB_VSID_KERNEL | io_llp); DBG("SLB: linear LLP = %04x\n", linear_llp); - DBG("SLB: virtual LLP = %04x\n", virtual_llp); + DBG("SLB: io LLP = %04x\n", io_llp); #ifdef CONFIG_HUGETLB_PAGE patch_slb_encoding(slb_miss_user_load_huge, SLB_VSID_USER | huge_llp); @@ -204,7 +204,7 @@ void slb_initialize(void) unsigned long lflags, vflags; lflags = SLB_VSID_KERNEL | linear_llp; - vflags = SLB_VSID_KERNEL | virtual_llp; + vflags = SLB_VSID_KERNEL | vmalloc_llp; /* Invalidate the entire SLB (even slot 0) & all the ERATS */ asm volatile("isync":::"memory"); @@ -212,7 +212,6 @@ void slb_initialize(void) asm volatile("isync; slbia; isync":::"memory"); create_slbe(PAGE_OFFSET, lflags, 0); - /* VMALLOC space has 4K pages always for now */ create_slbe(VMALLOC_START, vflags, 1); /* We don't bolt the stack for the time being - we're in boot, diff --git a/arch/powerpc/mm/slb_low.S b/arch/powerpc/mm/slb_low.S index abfaabf667b..8548dcf8ef8 100644 --- a/arch/powerpc/mm/slb_low.S +++ b/arch/powerpc/mm/slb_low.S @@ -59,10 +59,19 @@ _GLOBAL(slb_miss_kernel_load_linear) li r11,0 b slb_finish_load -1: /* vmalloc/ioremap mapping encoding bits, the "li" instruction below +1: /* vmalloc/ioremap mapping encoding bits, the "li" instructions below * will be patched by the kernel at boot */ -_GLOBAL(slb_miss_kernel_load_virtual) +BEGIN_FTR_SECTION + /* check whether this is in vmalloc or ioremap space */ + clrldi r11,r10,48 + cmpldi r11,(VMALLOC_SIZE >> 28) - 1 + bgt 5f + lhz r11,PACAVMALLOCSLLP(r13) + b slb_finish_load +5: +END_FTR_SECTION_IFCLR(CPU_FTR_CI_LARGE_PAGE) +_GLOBAL(slb_miss_kernel_load_io) li r11,0 b slb_finish_load @@ -96,9 +105,7 @@ _GLOBAL(slb_miss_user_load_huge) 1: #endif /* CONFIG_HUGETLB_PAGE */ -_GLOBAL(slb_miss_user_load_normal) - li r11,0 - + lhz r11,PACACONTEXTSLLP(r13) 2: ld r9,PACACONTEXTID(r13) rldimi r10,r9,USER_ESID_BITS,0 diff --git a/arch/powerpc/mm/tlb_64.c b/arch/powerpc/mm/tlb_64.c index f734b11566c..e7449b068c8 100644 --- a/arch/powerpc/mm/tlb_64.c +++ b/arch/powerpc/mm/tlb_64.c @@ -131,7 +131,7 @@ void hpte_update(struct mm_struct *mm, unsigned long addr, { struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); unsigned long vsid; - unsigned int psize = mmu_virtual_psize; + unsigned int psize; int i; i = batch->index; @@ -148,7 +148,8 @@ void hpte_update(struct mm_struct *mm, unsigned long addr, #else BUG(); #endif - } + } else + psize = pte_pagesize_index(pte); /* * This can happen when we are in the middle of a TLB batch and diff --git a/include/asm-powerpc/mmu.h b/include/asm-powerpc/mmu.h index 88539742010..3a5ebe229af 100644 --- a/include/asm-powerpc/mmu.h +++ b/include/asm-powerpc/mmu.h @@ -165,6 +165,16 @@ struct mmu_psize_def extern struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT]; extern int mmu_linear_psize; extern int mmu_virtual_psize; +extern int mmu_vmalloc_psize; +extern int mmu_io_psize; + +/* + * If the processor supports 64k normal pages but not 64k cache + * inhibited pages, we have to be prepared to switch processes + * to use 4k pages when they create cache-inhibited mappings. + * If this is the case, mmu_ci_restrictions will be set to 1. + */ +extern int mmu_ci_restrictions; #ifdef CONFIG_HUGETLB_PAGE /* @@ -256,6 +266,7 @@ extern long iSeries_hpte_insert(unsigned long hpte_group, extern void stabs_alloc(void); extern void slb_initialize(void); +extern void slb_flush_and_rebolt(void); extern void stab_initialize(unsigned long stab); #endif /* __ASSEMBLY__ */ @@ -359,6 +370,8 @@ typedef unsigned long mm_context_id_t; typedef struct { mm_context_id_t id; + u16 user_psize; /* page size index */ + u16 sllp; /* SLB entry page size encoding */ #ifdef CONFIG_HUGETLB_PAGE u16 low_htlb_areas, high_htlb_areas; #endif diff --git a/include/asm-powerpc/paca.h b/include/asm-powerpc/paca.h index c17fd54d995..17406353e2c 100644 --- a/include/asm-powerpc/paca.h +++ b/include/asm-powerpc/paca.h @@ -81,6 +81,7 @@ struct paca_struct { * on the linear mapping */ mm_context_t context; + u16 vmalloc_sllp; u16 slb_cache[SLB_CACHE_ENTRIES]; u16 slb_cache_ptr; diff --git a/include/asm-powerpc/pgtable-4k.h b/include/asm-powerpc/pgtable-4k.h index b2e18629932..e7036155672 100644 --- a/include/asm-powerpc/pgtable-4k.h +++ b/include/asm-powerpc/pgtable-4k.h @@ -78,6 +78,8 @@ #define pte_iterate_hashed_end() } while(0) +#define pte_pagesize_index(pte) MMU_PAGE_4K + /* * 4-level page tables related bits */ diff --git a/include/asm-powerpc/pgtable-64k.h b/include/asm-powerpc/pgtable-64k.h index 653915014dc..4b7126c53f3 100644 --- a/include/asm-powerpc/pgtable-64k.h +++ b/include/asm-powerpc/pgtable-64k.h @@ -90,6 +90,8 @@ #define pte_iterate_hashed_end() } while(0); } } while(0) +#define pte_pagesize_index(pte) \ + (((pte) & _PAGE_COMBO)? MMU_PAGE_4K: MMU_PAGE_64K) #endif /* __ASSEMBLY__ */ #endif /* __KERNEL__ */ diff --git a/include/asm-powerpc/pgtable.h b/include/asm-powerpc/pgtable.h index e9f1f4627e6..260a0fabe97 100644 --- a/include/asm-powerpc/pgtable.h +++ b/include/asm-powerpc/pgtable.h @@ -47,8 +47,8 @@ struct mm_struct; /* * Define the address range of the vmalloc VM area. */ -#define VMALLOC_START (0xD000000000000000ul) -#define VMALLOC_SIZE (0x80000000000UL) +#define VMALLOC_START ASM_CONST(0xD000000000000000) +#define VMALLOC_SIZE ASM_CONST(0x80000000000) #define VMALLOC_END (VMALLOC_START + VMALLOC_SIZE) /* @@ -413,12 +413,6 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, flush_tlb_pending(); } pte = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS); - -#ifdef CONFIG_PPC_64K_PAGES - if (mmu_virtual_psize != MMU_PAGE_64K) - pte = __pte(pte_val(pte) | _PAGE_COMBO); -#endif /* CONFIG_PPC_64K_PAGES */ - *ptep = pte; } -- cgit v1.2.3 From 0f582bc1f2cccacd613c411fbea55873d17c3429 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Thu, 15 Jun 2006 18:03:32 +1000 Subject: powerpc: Simplify push_end definition in pci_32.c The push_end macro in arch/powerpc/kernel/pci_32.c uses integer division and multiplication to achieve the effect of rounding a resource end address up and then advancing it to the end of a power-of-2 sized region. This changes it to an equivalent computation that only needs an integer add and OR. This is partly based on an earlier patch by Mel Gorman. Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/pci_32.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c index b129d2e4b75..c858eb4bef1 100644 --- a/arch/powerpc/kernel/pci_32.c +++ b/arch/powerpc/kernel/pci_32.c @@ -1113,9 +1113,10 @@ check_for_io_childs(struct pci_bus *bus, struct resource* res, int *found_vga) int i; int rc = 0; -#define push_end(res, size) do { unsigned long __sz = (size) ; \ - res->end = ((res->end + __sz) / (__sz + 1)) * (__sz + 1) + __sz; \ - } while (0) +#define push_end(res, mask) do { \ + BUG_ON((mask+1) & mask); \ + res->end = (res->end + mask) | mask; \ +} while (0) list_for_each_entry(dev, &bus->devices, bus_list) { u16 class = dev->class >> 8; -- cgit v1.2.3 From bb53bb3dcb12d79efdee3d82bff46a204af377f3 Mon Sep 17 00:00:00 2001 From: Jake Moilanen Date: Wed, 7 Jun 2006 16:05:46 -0500 Subject: [POWERPC] Add support for PCI-Express nodes in the device tree This adds support to recognize the PCIe device_type "pciex" and made the portdrv buildable. Signed-off-by: Jake Moilanen Signed-off-by: Paul Mackerras --- arch/powerpc/Kconfig | 2 ++ arch/powerpc/kernel/pci_64.c | 2 +- arch/powerpc/kernel/rtas_pci.c | 4 +++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 7eb0ef2b003..4ef2478cb84 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -853,6 +853,8 @@ config 8260_PCI9_IDMA4 endchoice +source "drivers/pci/pcie/Kconfig" + source "drivers/pci/Kconfig" source "drivers/pcmcia/Kconfig" diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 30a4e6a1368..74dc76653e1 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -388,7 +388,7 @@ struct pci_dev *of_create_pci_dev(struct device_node *node, dev->current_state = 4; /* unknown power state */ - if (!strcmp(type, "pci")) { + if (!strcmp(type, "pci") || !strcmp(type, "pciex")) { /* a PCI-PCI bridge */ dev->hdr_type = PCI_HEADER_TYPE_BRIDGE; dev->rom_base_reg = PCI_ROM_ADDRESS1; diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c index 57b539a03fa..6eb7e49b394 100644 --- a/arch/powerpc/kernel/rtas_pci.c +++ b/arch/powerpc/kernel/rtas_pci.c @@ -313,7 +313,9 @@ unsigned long __init find_and_init_phbs(void) for (node = of_get_next_child(root, NULL); node != NULL; node = of_get_next_child(root, node)) { - if (node->type == NULL || strcmp(node->type, "pci") != 0) + + if (node->type == NULL || (strcmp(node->type, "pci") != 0 && + strcmp(node->type, "pciex") != 0)) continue; phb = pcibios_alloc_controller(node); -- cgit v1.2.3 From 204face4fb3ba2ca09a4073e7debc595e14c2388 Mon Sep 17 00:00:00 2001 From: Jake Moilanen Date: Wed, 7 Jun 2006 16:15:10 -0500 Subject: [POWERPC] MSI abstraction Instead of trying to make PPC64 MSI fit in a Intel-centric MSI layer, a simple short-term solution is to hook the pci_{en/dis}able_msi() calls and make a machdep call. The rest of the MSI functions are superfluous for what is needed at this time. Many of which can have machdep calls added as needed. Ben and Michael Ellerman are looking into rewrite the MSI layer to be more generic. However, in the meantime this works as a interim solution. Signed-off-by: Jake Moilanen Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/irq.c | 25 +++++++++++++++++++++++++ include/asm-powerpc/machdep.h | 5 +++++ 2 files changed, 30 insertions(+) diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 57d560c6889..bfcec4cc70a 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -436,6 +437,30 @@ void do_softirq(void) } EXPORT_SYMBOL(do_softirq); +#ifdef CONFIG_PCI_MSI +int pci_enable_msi(struct pci_dev * pdev) +{ + if (ppc_md.enable_msi) + return ppc_md.enable_msi(pdev); + else + return -1; +} + +void pci_disable_msi(struct pci_dev * pdev) +{ + if (ppc_md.disable_msi) + ppc_md.disable_msi(pdev); +} + +void pci_scan_msi_device(struct pci_dev *dev) {} +int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) {return -1;} +void pci_disable_msix(struct pci_dev *dev) {} +void msi_remove_pci_irq_vectors(struct pci_dev *dev) {} +void disable_msi_mode(struct pci_dev *dev, int pos, int type) {} +void pci_no_msi(void) {} + +#endif + #ifdef CONFIG_PPC64 static int __init setup_noirqdistrib(char *str) { diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h index 0f9254c1891..fc984bd11d8 100644 --- a/include/asm-powerpc/machdep.h +++ b/include/asm-powerpc/machdep.h @@ -238,6 +238,11 @@ struct machdep_calls { */ void (*machine_kexec)(struct kimage *image); #endif /* CONFIG_KEXEC */ + +#ifdef CONFIG_PCI_MSI + int (*enable_msi)(struct pci_dev *pdev); + void (*disable_msi)(struct pci_dev *pdev); +#endif /* CONFIG_PCI_MSI */ }; extern void power4_idle(void); -- cgit v1.2.3 From 30d8caf7c625203b295a78f143820cdc3124830b Mon Sep 17 00:00:00 2001 From: "mostrows@watson.ibm.com" Date: Fri, 9 Jun 2006 09:06:12 -0400 Subject: [POWERPC] Editable kernel command-line in zImage binary. zImage will set /chosen/bootargs (if it is otherwise empty) with the contents of a buffer in the section "__builtin_cmdline". This permits tools to edit zImage binaries to set the command-line eventually processed by vmlinux. -- Signed-off-by: Michal Ostrowski Signed-off-by: Paul Mackerras --- arch/powerpc/boot/main.c | 27 +++++++++++++++++++++++++++ arch/powerpc/boot/prom.h | 7 +++++++ 2 files changed, 34 insertions(+) diff --git a/arch/powerpc/boot/main.c b/arch/powerpc/boot/main.c index 816446f0e49..b66634c9ea3 100644 --- a/arch/powerpc/boot/main.c +++ b/arch/powerpc/boot/main.c @@ -33,6 +33,14 @@ extern char _vmlinux_end[]; extern char _initrd_start[]; extern char _initrd_end[]; +/* A buffer that may be edited by tools operating on a zImage binary so as to + * edit the command line passed to vmlinux (by setting /chosen/bootargs). + * The buffer is put in it's own section so that tools may locate it easier. + */ +static char builtin_cmdline[512] + __attribute__((section("__builtin_cmdline"))); + + struct addr_range { unsigned long addr; unsigned long size; @@ -204,6 +212,23 @@ static int is_elf32(void *hdr) return 1; } +void export_cmdline(void* chosen_handle) +{ + int len; + char cmdline[2] = { 0, 0 }; + + if (builtin_cmdline[0] == 0) + return; + + len = getprop(chosen_handle, "bootargs", cmdline, sizeof(cmdline)); + if (len > 0 && cmdline[0] != 0) + return; + + setprop(chosen_handle, "bootargs", builtin_cmdline, + strlen(builtin_cmdline) + 1); +} + + void start(unsigned long a1, unsigned long a2, void *promptr, void *sp) { int len; @@ -289,6 +314,8 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp) memmove((void *)vmlinux.addr,(void *)vmlinuz.addr,vmlinuz.size); } + export_cmdline(chosen_handle); + /* Skip over the ELF header */ #ifdef DEBUG printf("... skipping 0x%lx bytes of ELF header\n\r", diff --git a/arch/powerpc/boot/prom.h b/arch/powerpc/boot/prom.h index 3e2ddd4a5a8..a57b184c564 100644 --- a/arch/powerpc/boot/prom.h +++ b/arch/powerpc/boot/prom.h @@ -31,4 +31,11 @@ static inline int getprop(void *phandle, const char *name, return call_prom("getprop", 4, 1, phandle, name, buf, buflen); } + +static inline int setprop(void *phandle, const char *name, + void *buf, int buflen) +{ + return call_prom("setprop", 4, 1, phandle, name, buf, buflen); +} + #endif /* _PPC_BOOT_PROM_H_ */ -- cgit v1.2.3 From 3a2c48cfc97f9046abbd810f1efb1aa824bcfaf1 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Sat, 10 Jun 2006 20:18:39 +1000 Subject: [POWERPC] 64bit FPSCR support Forthcoming machines will extend the FPSCR to 64 bits. We already had a 64-bit save area for the FPSCR, but we need to use a new form of the mtfsf instruction. Fortunately this new form is decoded as an ordinary mtfsf by existing 64-bit processors. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/fpu.S | 6 +++--- arch/powerpc/kernel/vector.S | 4 ++-- include/asm-powerpc/reg.h | 13 +++++++++++++ 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/arch/powerpc/kernel/fpu.S b/arch/powerpc/kernel/fpu.S index 340730fb8c9..01f71200c60 100644 --- a/arch/powerpc/kernel/fpu.S +++ b/arch/powerpc/kernel/fpu.S @@ -72,7 +72,7 @@ _GLOBAL(load_up_fpu) std r12,_MSR(r1) #endif lfd fr0,THREAD_FPSCR(r5) - mtfsf 0xff,fr0 + MTFSF_L(fr0) REST_32FPRS(0, r5) #ifndef CONFIG_SMP subi r4,r5,THREAD @@ -127,7 +127,7 @@ _GLOBAL(giveup_fpu) _GLOBAL(cvt_fd) lfd 0,THREAD_FPSCR(r5) /* load up fpscr value */ - mtfsf 0xff,0 + MTFSF_L(0) lfs 0,0(r3) stfd 0,0(r4) mffs 0 @@ -136,7 +136,7 @@ _GLOBAL(cvt_fd) _GLOBAL(cvt_df) lfd 0,THREAD_FPSCR(r5) /* load up fpscr value */ - mtfsf 0xff,0 + MTFSF_L(0) lfd 0,0(r3) stfs 0,0(r4) mffs 0 diff --git a/arch/powerpc/kernel/vector.S b/arch/powerpc/kernel/vector.S index 66b3d03c5fa..9416b4ab92e 100644 --- a/arch/powerpc/kernel/vector.S +++ b/arch/powerpc/kernel/vector.S @@ -53,12 +53,12 @@ fpenable: stfd fr31,8(r1) LDCONST(fr1, fpzero) mffs fr31 - mtfsf 0xff,fr1 + MTFSF_L(fr1) blr fpdisable: mtlr r12 - mtfsf 0xff,fr31 + MTFSF_L(fr31) lfd fr31,8(r1) lfd fr1,16(r1) lfd fr0,24(r1) diff --git a/include/asm-powerpc/reg.h b/include/asm-powerpc/reg.h index 3779b21a7c7..bfc7dc14ffc 100644 --- a/include/asm-powerpc/reg.h +++ b/include/asm-powerpc/reg.h @@ -499,6 +499,19 @@ #define MMCR0_PMC2_LOADMISSTIME 0x5 #endif +/* + * An mtfsf instruction with the L bit set. On CPUs that support this a + * full 64bits of FPSCR is restored and on other CPUs it is ignored. + * + * Until binutils gets the new form of mtfsf, hardwire the instruction. + */ +#ifdef CONFIG_PPC64 +#define MTFSF_L(REG) \ + .long (0xfc00058e | ((0xff) << 17) | ((REG) << 11) | (1 << 25)) +#else +#define MTFSF_L(REG) mtfsf 0xff, (REG) +#endif + /* Processor Version Register (PVR) field extraction */ #define PVR_VER(pvr) (((pvr) >> 16) & 0xFFFF) /* Version field */ -- cgit v1.2.3 From 8555a0029b1b0840237b750e55d4835a52cc719b Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Sat, 10 Jun 2006 20:23:54 +1000 Subject: [POWERPC] Optimise some TOC usage Micro-optimisation - add no-minimal-toc to some more arch/powerpc Makefiles. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras --- arch/powerpc/lib/Makefile | 4 ++++ arch/powerpc/oprofile/Makefile | 4 ++++ arch/powerpc/platforms/pseries/Makefile | 4 ++++ arch/powerpc/sysdev/Makefile | 4 ++++ 4 files changed, 16 insertions(+) diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile index ae354d65b82..ff709645824 100644 --- a/arch/powerpc/lib/Makefile +++ b/arch/powerpc/lib/Makefile @@ -2,6 +2,10 @@ # Makefile for ppc-specific library files.. # +ifeq ($(CONFIG_PPC64),y) +EXTRA_CFLAGS += -mno-minimal-toc +endif + ifeq ($(CONFIG_PPC_MERGE),y) obj-y := string.o strcase.o obj-$(CONFIG_PPC32) += div64.o copy_32.o checksum_32.o diff --git a/arch/powerpc/oprofile/Makefile b/arch/powerpc/oprofile/Makefile index f5f9859a833..3145d610b5b 100644 --- a/arch/powerpc/oprofile/Makefile +++ b/arch/powerpc/oprofile/Makefile @@ -1,3 +1,7 @@ +ifeq ($(CONFIG_PPC64),y) +EXTRA_CFLAGS += -mno-minimal-toc +endif + obj-$(CONFIG_OPROFILE) += oprofile.o DRIVER_OBJS := $(addprefix ../../../drivers/oprofile/, \ diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index b46ce3b9bb3..e5e0ff46690 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile @@ -1,3 +1,7 @@ +ifeq ($(CONFIG_PPC64),y) +EXTRA_CFLAGS += -mno-minimal-toc +endif + obj-y := pci.o lpar.o hvCall.o nvram.o reconfig.o \ setup.o iommu.o ras.o rtasd.o pci_dlpar.o \ firmware.o diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index 4c2b356774e..cef95b02373 100644 --- a/arch/powerpc/sysdev/Makefile +++ b/arch/powerpc/sysdev/Makefile @@ -1,3 +1,7 @@ +ifeq ($(CONFIG_PPC64),y) +EXTRA_CFLAGS += -mno-minimal-toc +endif + obj-$(CONFIG_MPIC) += mpic.o obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o obj-$(CONFIG_PPC_I8259) += i8259.o -- cgit v1.2.3 From 227318bbde6c8309b1d20ab46532ec2b737e1fee Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Sat, 10 Jun 2006 20:32:01 +1000 Subject: [POWERPC] Remove stale 64bit on 32bit kernel code Remove some stale POWER3/POWER4/970 on 32bit kernel support. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras --- arch/powerpc/Makefile | 1 - arch/powerpc/kernel/cputable.c | 8 -------- arch/powerpc/mm/hash_low_32.S | 34 ---------------------------------- arch/powerpc/mm/ppc_mmu_32.c | 10 ---------- arch/um/sys-ppc/misc.S | 6 +----- include/asm-powerpc/cputable.h | 19 ------------------- include/asm-ppc/mmu.h | 17 ----------------- 7 files changed, 1 insertion(+), 94 deletions(-) diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index ed5b26aa8be..01667d1d571 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile @@ -108,7 +108,6 @@ ifeq ($(CONFIG_6xx),y) CFLAGS += -mcpu=powerpc endif -cpu-as-$(CONFIG_PPC64BRIDGE) += -Wa,-mppc64bridge cpu-as-$(CONFIG_4xx) += -Wa,-m405 cpu-as-$(CONFIG_6xx) += -Wa,-maltivec cpu-as-$(CONFIG_POWER4) += -Wa,-maltivec diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index dfe2fcfb20a..abf7d42a8b0 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -189,17 +189,11 @@ struct cpu_spec cpu_specs[] = { .oprofile_type = PPC_OPROFILE_POWER4, .platform = "ppc970", }, -#endif /* CONFIG_PPC64 */ -#if defined(CONFIG_PPC64) || defined(CONFIG_POWER4) { /* PPC970FX */ .pvr_mask = 0xffff0000, .pvr_value = 0x003c0000, .cpu_name = "PPC970FX", -#ifdef CONFIG_PPC32 - .cpu_features = CPU_FTRS_970_32, -#else .cpu_features = CPU_FTRS_PPC970, -#endif .cpu_user_features = COMMON_USER_POWER4 | PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 128, @@ -210,8 +204,6 @@ struct cpu_spec cpu_specs[] = { .oprofile_type = PPC_OPROFILE_POWER4, .platform = "ppc970", }, -#endif /* defined(CONFIG_PPC64) || defined(CONFIG_POWER4) */ -#ifdef CONFIG_PPC64 { /* PPC970MP */ .pvr_mask = 0xffff0000, .pvr_value = 0x00440000, diff --git a/arch/powerpc/mm/hash_low_32.S b/arch/powerpc/mm/hash_low_32.S index ea469eefa14..94255beeecd 100644 --- a/arch/powerpc/mm/hash_low_32.S +++ b/arch/powerpc/mm/hash_low_32.S @@ -74,12 +74,6 @@ _GLOBAL(hash_page_sync) */ .text _GLOBAL(hash_page) -#ifdef CONFIG_PPC64BRIDGE - mfmsr r0 - clrldi r0,r0,1 /* make sure it's in 32-bit mode */ - MTMSRD(r0) - isync -#endif tophys(r7,0) /* gets -KERNELBASE into r7 */ #ifdef CONFIG_SMP addis r8,r7,mmu_hash_lock@h @@ -285,7 +279,6 @@ Hash_base = 0xc0180000 Hash_bits = 12 /* e.g. 256kB hash table */ Hash_msk = (((1 << Hash_bits) - 1) * 64) -#ifndef CONFIG_PPC64BRIDGE /* defines for the PTE format for 32-bit PPCs */ #define PTE_SIZE 8 #define PTEG_SIZE 64 @@ -299,21 +292,6 @@ Hash_msk = (((1 << Hash_bits) - 1) * 64) #define SET_V(r) oris r,r,PTE_V@h #define CLR_V(r,t) rlwinm r,r,0,1,31 -#else -/* defines for the PTE format for 64-bit PPCs */ -#define PTE_SIZE 16 -#define PTEG_SIZE 128 -#define LG_PTEG_SIZE 7 -#define LDPTEu ldu -#define STPTE std -#define CMPPTE cmpd -#define PTE_H 2 -#define PTE_V 1 -#define TST_V(r) andi. r,r,PTE_V -#define SET_V(r) ori r,r,PTE_V -#define CLR_V(r,t) li t,PTE_V; andc r,r,t -#endif /* CONFIG_PPC64BRIDGE */ - #define HASH_LEFT 31-(LG_PTEG_SIZE+Hash_bits-1) #define HASH_RIGHT 31-LG_PTEG_SIZE @@ -331,14 +309,8 @@ BEGIN_FTR_SECTION END_FTR_SECTION_IFSET(CPU_FTR_NEED_COHERENT) /* Construct the high word of the PPC-style PTE (r5) */ -#ifndef CONFIG_PPC64BRIDGE rlwinm r5,r3,7,1,24 /* put VSID in 0x7fffff80 bits */ rlwimi r5,r4,10,26,31 /* put in API (abbrev page index) */ -#else /* CONFIG_PPC64BRIDGE */ - clrlwi r3,r3,8 /* reduce vsid to 24 bits */ - sldi r5,r3,12 /* shift vsid into position */ - rlwimi r5,r4,16,20,24 /* put in API (abbrev page index) */ -#endif /* CONFIG_PPC64BRIDGE */ SET_V(r5) /* set V (valid) bit */ /* Get the address of the primary PTE group in the hash table (r3) */ @@ -516,14 +488,8 @@ _GLOBAL(flush_hash_pages) add r3,r3,r0 /* note code below trims to 24 bits */ /* Construct the high word of the PPC-style PTE (r11) */ -#ifndef CONFIG_PPC64BRIDGE rlwinm r11,r3,7,1,24 /* put VSID in 0x7fffff80 bits */ rlwimi r11,r4,10,26,31 /* put in API (abbrev page index) */ -#else /* CONFIG_PPC64BRIDGE */ - clrlwi r3,r3,8 /* reduce vsid to 24 bits */ - sldi r11,r3,12 /* shift vsid into position */ - rlwimi r11,r4,16,20,24 /* put in API (abbrev page index) */ -#endif /* CONFIG_PPC64BRIDGE */ SET_V(r11) /* set V (valid) bit */ #ifdef CONFIG_SMP diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c index 1df731e42b5..ab5cd724b12 100644 --- a/arch/powerpc/mm/ppc_mmu_32.c +++ b/arch/powerpc/mm/ppc_mmu_32.c @@ -42,11 +42,7 @@ unsigned long _SDR1; union ubat { /* BAT register values to be loaded */ BAT bat; -#ifdef CONFIG_PPC64BRIDGE - u64 word[2]; -#else u32 word[2]; -#endif } BATS[4][2]; /* 4 pairs of IBAT, DBAT */ struct batrange { /* stores address ranges mapped by BATs */ @@ -220,15 +216,9 @@ void __init MMU_init_hw(void) if ( ppc_md.progress ) ppc_md.progress("hash:enter", 0x105); -#ifdef CONFIG_PPC64BRIDGE -#define LG_HPTEG_SIZE 7 /* 128 bytes per HPTEG */ -#define SDR1_LOW_BITS (lg_n_hpteg - 11) -#define MIN_N_HPTEG 2048 /* min 256kB hash table */ -#else #define LG_HPTEG_SIZE 6 /* 64 bytes per HPTEG */ #define SDR1_LOW_BITS ((n_hpteg - 1) >> 10) #define MIN_N_HPTEG 1024 /* min 64kB hash table */ -#endif /* * Allow 1 HPTE (1/8 HPTEG) for each page of memory. diff --git a/arch/um/sys-ppc/misc.S b/arch/um/sys-ppc/misc.S index 11b7bd768cf..f0c971db47e 100644 --- a/arch/um/sys-ppc/misc.S +++ b/arch/um/sys-ppc/misc.S @@ -23,14 +23,10 @@ #define CACHE_LINE_SIZE 16 #define LG_CACHE_LINE_SIZE 4 #define MAX_COPY_PREFETCH 1 -#elif !defined(CONFIG_PPC64BRIDGE) +#else #define CACHE_LINE_SIZE 32 #define LG_CACHE_LINE_SIZE 5 #define MAX_COPY_PREFETCH 4 -#else -#define CACHE_LINE_SIZE 128 -#define LG_CACHE_LINE_SIZE 7 -#define MAX_COPY_PREFETCH 1 #endif /* CONFIG_4xx || CONFIG_8xx */ .text diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h index 69f2c242797..da6f417d2ca 100644 --- a/include/asm-powerpc/cputable.h +++ b/include/asm-powerpc/cputable.h @@ -300,13 +300,6 @@ extern void do_cpu_ftr_fixups(unsigned long offset); CPU_FTR_COMMON) #define CPU_FTRS_CLASSIC32 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE) -#define CPU_FTRS_POWER3_32 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ - CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE) -#define CPU_FTRS_POWER4_32 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ - CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_NODSISRALIGN) -#define CPU_FTRS_970_32 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ - CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_ALTIVEC_COMP | \ - CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_NODSISRALIGN) #define CPU_FTRS_8XX (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB) #define CPU_FTRS_40X (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ CPU_FTR_NODSISRALIGN) @@ -367,12 +360,6 @@ enum { #else CPU_FTRS_GENERIC_32 | #endif -#ifdef CONFIG_PPC64BRIDGE - CPU_FTRS_POWER3_32 | -#endif -#ifdef CONFIG_POWER4 - CPU_FTRS_POWER4_32 | CPU_FTRS_970_32 | -#endif #ifdef CONFIG_8xx CPU_FTRS_8XX | #endif @@ -412,12 +399,6 @@ enum { #else CPU_FTRS_GENERIC_32 & #endif -#ifdef CONFIG_PPC64BRIDGE - CPU_FTRS_POWER3_32 & -#endif -#ifdef CONFIG_POWER4 - CPU_FTRS_POWER4_32 & CPU_FTRS_970_32 & -#endif #ifdef CONFIG_8xx CPU_FTRS_8XX & #endif diff --git a/include/asm-ppc/mmu.h b/include/asm-ppc/mmu.h index 80ae60481fb..8915c4c3ecb 100644 --- a/include/asm-ppc/mmu.h +++ b/include/asm-ppc/mmu.h @@ -31,20 +31,11 @@ typedef struct { /* Hardware Page Table Entry */ typedef struct _PTE { -#ifdef CONFIG_PPC64BRIDGE - unsigned long long vsid:52; - unsigned long api:5; - unsigned long :5; - unsigned long h:1; - unsigned long v:1; - unsigned long long rpn:52; -#else /* CONFIG_PPC64BRIDGE */ unsigned long v:1; /* Entry is valid */ unsigned long vsid:24; /* Virtual segment identifier */ unsigned long h:1; /* Hash algorithm indicator */ unsigned long api:6; /* Abbreviated page index */ unsigned long rpn:20; /* Real (physical) page number */ -#endif /* CONFIG_PPC64BRIDGE */ unsigned long :3; /* Unused */ unsigned long r:1; /* Referenced */ unsigned long c:1; /* Changed */ @@ -85,11 +76,7 @@ typedef struct _P601_BATU { /* Upper part of BAT for 601 processor */ } P601_BATU; typedef struct _BATU { /* Upper part of BAT (all except 601) */ -#ifdef CONFIG_PPC64BRIDGE - unsigned long long bepi:47; -#else /* CONFIG_PPC64BRIDGE */ unsigned long bepi:15; /* Effective page index (virtual address) */ -#endif /* CONFIG_PPC64BRIDGE */ unsigned long :4; /* Unused */ unsigned long bl:11; /* Block size mask */ unsigned long vs:1; /* Supervisor valid */ @@ -104,11 +91,7 @@ typedef struct _P601_BATL { /* Lower part of BAT for 601 processor */ } P601_BATL; typedef struct _BATL { /* Lower part of BAT (all except 601) */ -#ifdef CONFIG_PPC64BRIDGE - unsigned long long brpn:47; -#else /* CONFIG_PPC64BRIDGE */ unsigned long brpn:15; /* Real page index (physical address) */ -#endif /* CONFIG_PPC64BRIDGE */ unsigned long :10; /* Unused */ unsigned long w:1; /* Write-thru cache */ unsigned long i:1; /* Cache inhibit */ -- cgit v1.2.3 From f2b09c8189bc7b64a42753e98f7006b11bae1bdc Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Sat, 10 Jun 2006 20:37:24 +1000 Subject: [POWERPC] Update pseries defconfig pseries defconfig updates: - Enable jsm and re-enable qlogic FC drivers as modules. - Enable ocfs2, autofs4 and fuse filesystems as modules. - Enable Kprobes. - Enable ebus, binfmt_misc, sas attrs, md5 reshape, hvc rtas backend and some infiniband options. - Finally disable debug options: DEBUG_MUTEXES and DEBUG_STACK_USAGE. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras --- arch/powerpc/configs/pseries_defconfig | 75 +++++++++++++++++++--------------- 1 file changed, 43 insertions(+), 32 deletions(-) diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig index 58e68ce09b0..31708ad4574 100644 --- a/arch/powerpc/configs/pseries_defconfig +++ b/arch/powerpc/configs/pseries_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.17-rc1 -# Wed Apr 19 11:48:00 2006 +# Linux kernel version: 2.6.17-rc4 +# Sun May 28 07:26:56 2006 # CONFIG_PPC64=y CONFIG_64BIT=y @@ -11,6 +11,7 @@ CONFIG_GENERIC_HARDIRQS=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_PPC=y CONFIG_EARLY_PRINTK=y CONFIG_COMPAT=y @@ -126,8 +127,9 @@ CONFIG_RTAS_PROC=y CONFIG_RTAS_FLASH=m # CONFIG_MMIO_NVRAM is not set CONFIG_IBMVIO=y -# CONFIG_IBMEBUS is not set +CONFIG_IBMEBUS=y # CONFIG_PPC_MPC106 is not set +# CONFIG_PPC_970_NAP is not set # CONFIG_CPU_FREQ is not set # CONFIG_WANT_EARLY_SERIAL is not set @@ -143,7 +145,7 @@ CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT is not set # CONFIG_PREEMPT_BKL is not set CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set +CONFIG_BINFMT_MISC=m CONFIG_FORCE_MAX_ZONEORDER=13 CONFIG_IOMMU_VMERGE=y CONFIG_HOTPLUG_CPU=y @@ -155,6 +157,7 @@ CONFIG_EEH=y CONFIG_SCANLOG=m CONFIG_LPARCFG=y CONFIG_NUMA=y +CONFIG_NODES_SHIFT=4 CONFIG_ARCH_SELECT_MEMORY_MODEL=y CONFIG_ARCH_SPARSEMEM_ENABLE=y CONFIG_ARCH_SPARSEMEM_DEFAULT=y @@ -467,7 +470,7 @@ CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SPI_ATTRS=y CONFIG_SCSI_FC_ATTRS=y CONFIG_SCSI_ISCSI_ATTRS=m -# CONFIG_SCSI_SAS_ATTRS is not set +CONFIG_SCSI_SAS_ATTRS=m # # SCSI low-level drivers @@ -499,13 +502,18 @@ CONFIG_SCSI_SYM53C8XX_2=y CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 -# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set +CONFIG_SCSI_SYM53C8XX_MMIO=y CONFIG_SCSI_IPR=y CONFIG_SCSI_IPR_TRACE=y CONFIG_SCSI_IPR_DUMP=y -# CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set -# CONFIG_SCSI_QLA_FC is not set +CONFIG_SCSI_QLA_FC=m +CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE=y +CONFIG_SCSI_QLA21XX=m +CONFIG_SCSI_QLA22XX=m +CONFIG_SCSI_QLA2300=m +CONFIG_SCSI_QLA2322=m +CONFIG_SCSI_QLA24XX=m CONFIG_SCSI_LPFC=m # CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set @@ -521,7 +529,7 @@ CONFIG_MD_RAID0=y CONFIG_MD_RAID1=y CONFIG_MD_RAID10=m CONFIG_MD_RAID5=y -# CONFIG_MD_RAID5_RESHAPE is not set +CONFIG_MD_RAID5_RESHAPE=y CONFIG_MD_RAID6=m CONFIG_MD_MULTIPATH=m CONFIG_MD_FAULTY=m @@ -764,7 +772,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4 CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_SERIAL_ICOM=m -# CONFIG_SERIAL_JSM is not set +CONFIG_SERIAL_JSM=m CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 @@ -773,7 +781,7 @@ CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_TIPAR is not set CONFIG_HVC_DRIVER=y CONFIG_HVC_CONSOLE=y -# CONFIG_HVC_RTAS is not set +CONFIG_HVC_RTAS=y CONFIG_HVCS=m # @@ -1031,9 +1039,7 @@ CONFIG_USB_HIDDEV=y # CONFIG_USB_ACECAD is not set # CONFIG_USB_KBTAB is not set # CONFIG_USB_POWERMATE is not set -# CONFIG_USB_MTOUCH is not set -# CONFIG_USB_ITMTOUCH is not set -# CONFIG_USB_EGALAX is not set +# CONFIG_USB_TOUCHSCREEN is not set # CONFIG_USB_YEALINK is not set # CONFIG_USB_XPAD is not set # CONFIG_USB_ATI_REMOTE is not set @@ -1104,17 +1110,26 @@ CONFIG_USB_MON=y # # CONFIG_NEW_LEDS is not set +# +# LED drivers +# + +# +# LED Triggers +# + # # InfiniBand support # CONFIG_INFINIBAND=m -# CONFIG_INFINIBAND_USER_MAD is not set -# CONFIG_INFINIBAND_USER_ACCESS is not set +CONFIG_INFINIBAND_USER_MAD=m +CONFIG_INFINIBAND_USER_ACCESS=m CONFIG_INFINIBAND_MTHCA=m -# CONFIG_INFINIBAND_MTHCA_DEBUG is not set +CONFIG_INFINIBAND_MTHCA_DEBUG=y CONFIG_INFINIBAND_IPOIB=m -# CONFIG_INFINIBAND_IPOIB_DEBUG is not set -# CONFIG_INFINIBAND_SRP is not set +CONFIG_INFINIBAND_IPOIB_DEBUG=y +# CONFIG_INFINIBAND_IPOIB_DEBUG_DATA is not set +CONFIG_INFINIBAND_SRP=m # # EDAC - error detection and reporting (RAS) (EXPERIMENTAL) @@ -1159,15 +1174,15 @@ CONFIG_XFS_EXPORT=y CONFIG_XFS_SECURITY=y CONFIG_XFS_POSIX_ACL=y # CONFIG_XFS_RT is not set -# CONFIG_OCFS2_FS is not set +CONFIG_OCFS2_FS=m # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set CONFIG_INOTIFY=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y -CONFIG_AUTOFS_FS=m -# CONFIG_AUTOFS4_FS is not set -# CONFIG_FUSE_FS is not set +# CONFIG_AUTOFS_FS is not set +CONFIG_AUTOFS4_FS=m +CONFIG_FUSE_FS=m # # CD-ROM/DVD Filesystems @@ -1199,7 +1214,7 @@ CONFIG_TMPFS=y CONFIG_HUGETLBFS=y CONFIG_HUGETLB_PAGE=y CONFIG_RAMFS=y -# CONFIG_CONFIGFS_FS is not set +CONFIG_CONFIGFS_FS=m # # Miscellaneous filesystems @@ -1317,7 +1332,7 @@ CONFIG_ZLIB_DEFLATE=m # CONFIG_PROFILING=y CONFIG_OPROFILE=y -# CONFIG_KPROBES is not set +CONFIG_KPROBES=y # # Kernel hacking @@ -1329,7 +1344,7 @@ CONFIG_LOG_BUF_SHIFT=17 CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set -CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_MUTEXES is not set # CONFIG_DEBUG_SPINLOCK is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set # CONFIG_DEBUG_KOBJECT is not set @@ -1339,17 +1354,13 @@ CONFIG_DEBUG_FS=y CONFIG_FORCED_INLINING=y # CONFIG_RCU_TORTURE_TEST is not set CONFIG_DEBUG_STACKOVERFLOW=y -CONFIG_DEBUG_STACK_USAGE=y +# CONFIG_DEBUG_STACK_USAGE is not set CONFIG_DEBUGGER=y CONFIG_XMON=y CONFIG_XMON_DEFAULT=y CONFIG_IRQSTACKS=y # CONFIG_BOOTX_TEXT is not set -# CONFIG_PPC_EARLY_DEBUG_LPAR is not set -# CONFIG_PPC_EARLY_DEBUG_G5 is not set -# CONFIG_PPC_EARLY_DEBUG_RTAS is not set -# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set -# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set +# CONFIG_PPC_EARLY_DEBUG is not set # # Security options -- cgit v1.2.3 From 357518fa34d9dceda42bfc09642356a58370050d Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Sat, 10 Jun 2006 20:53:06 +1000 Subject: [POWERPC] pcibus_to_node fixes of_node_to_nid returns -1 if the associativity cannot be found. This means pcibus_to_cpumask has to be careful not to pass a negative index into node_to_cpumask. Since pcibus_to_node could be used a lot, and of_node_to_nid is slow (it walks a list doing strcmps), lets also cache the node in the pci_controller struct. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/pci_64.c | 13 ++++++++++++- include/asm-powerpc/pci-bridge.h | 8 ++++++++ include/asm-powerpc/topology.h | 14 +++++++------- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 74dc76653e1..5ad87c426be 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -227,8 +227,10 @@ struct pci_controller * pcibios_alloc_controller(struct device_node *dev) pci_setup_pci_controller(phb); phb->arch_data = dev; phb->is_dynamic = mem_init_done; - if (dev) + if (dev) { + PHB_SET_NODE(phb, of_node_to_nid(dev)); add_linux_pci_domain(dev, phb); + } return phb; } @@ -1415,3 +1417,12 @@ long sys_pciconfig_iobase(long which, unsigned long in_bus, return -EOPNOTSUPP; } + +#ifdef CONFIG_NUMA +int pcibus_to_node(struct pci_bus *bus) +{ + struct pci_controller *phb = pci_bus_to_host(bus); + return phb->node; +} +EXPORT_SYMBOL(pcibus_to_node); +#endif diff --git a/include/asm-powerpc/pci-bridge.h b/include/asm-powerpc/pci-bridge.h index 84a3075db52..4f55573762b 100644 --- a/include/asm-powerpc/pci-bridge.h +++ b/include/asm-powerpc/pci-bridge.h @@ -6,6 +6,7 @@ #include #else +#include #include #include @@ -22,6 +23,7 @@ struct pci_controller { struct pci_bus *bus; char is_dynamic; + int node; void *arch_data; struct list_head list_node; @@ -165,6 +167,12 @@ static inline unsigned long pci_address_to_pio(phys_addr_t address) #define PCI_PROBE_NORMAL 0 /* Do normal PCI probing */ #define PCI_PROBE_DEVTREE 1 /* Instantiate from device tree */ +#ifdef CONFIG_NUMA +#define PHB_SET_NODE(PHB, NODE) ((PHB)->node = (NODE)) +#else +#define PHB_SET_NODE(PHB, NODE) ((PHB)->node = -1) +#endif + #endif /* CONFIG_PPC64 */ #endif /* __KERNEL__ */ #endif diff --git a/include/asm-powerpc/topology.h b/include/asm-powerpc/topology.h index b7abd423c57..f4c759b5f6c 100644 --- a/include/asm-powerpc/topology.h +++ b/include/asm-powerpc/topology.h @@ -32,13 +32,13 @@ static inline int node_to_first_cpu(int node) int of_node_to_nid(struct device_node *device); -#ifdef CONFIG_PPC64 -#define pcibus_to_node(bus) (of_node_to_nid(bus->sysdata)) -#define pcibus_to_cpumask(bus) (node_to_cpumask(of_node_to_nid(bus->sysdata))) -#else -#define pcibus_to_node(node) (-1) -#define pcibus_to_cpumask(bus) (cpu_online_map) -#endif +struct pci_bus; +extern int pcibus_to_node(struct pci_bus *bus); + +#define pcibus_to_cpumask(bus) (pcibus_to_node(bus) == -1 ? \ + CPU_MASK_ALL : \ + node_to_cpumask(pcibus_to_node(bus)) \ + ) /* sched_domains SD_NODE_INIT for PPC64 machines */ #define SD_NODE_INIT (struct sched_domain) { \ -- cgit v1.2.3 From ca1588e71b70534e18368a46a3aad9b25dff941d Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Sat, 10 Jun 2006 20:58:08 +1000 Subject: [POWERPC] node local IOMMU tables Allocate IOMMU tables local to the relevant node. Signed-off-by: Anton Blanchard Acked-by: Olof Johansson Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/iommu.c | 9 +++++---- arch/powerpc/kernel/vio.c | 6 +++--- arch/powerpc/platforms/iseries/iommu.c | 2 +- arch/powerpc/platforms/pseries/iommu.c | 23 +++++++++++++---------- arch/powerpc/sysdev/dart_iommu.c | 2 +- include/asm-powerpc/iommu.h | 3 ++- 6 files changed, 25 insertions(+), 20 deletions(-) diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index cef8cba8329..7cb77c20fc5 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c @@ -418,10 +418,11 @@ void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist, * Build a iommu_table structure. This contains a bit map which * is used to manage allocation of the tce space. */ -struct iommu_table *iommu_init_table(struct iommu_table *tbl) +struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid) { unsigned long sz; static int welcomed = 0; + struct page *page; /* Set aside 1/4 of the table for large allocations. */ tbl->it_halfpoint = tbl->it_size * 3 / 4; @@ -429,10 +430,10 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl) /* number of bytes needed for the bitmap */ sz = (tbl->it_size + 7) >> 3; - tbl->it_map = (unsigned long *)__get_free_pages(GFP_ATOMIC, get_order(sz)); - if (!tbl->it_map) + page = alloc_pages_node(nid, GFP_ATOMIC, get_order(sz)); + if (!page) panic("iommu_init_table: Can't allocate %ld bytes\n", sz); - + tbl->it_map = page_address(page); memset(tbl->it_map, 0, sz); tbl->it_hint = 0; diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index e746686d48b..cdf5867838a 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c @@ -60,9 +60,9 @@ static void __init iommu_vio_init(void) vio_iommu_table = veth_iommu_table; vio_iommu_table.it_offset += veth_iommu_table.it_size; - if (!iommu_init_table(&veth_iommu_table)) + if (!iommu_init_table(&veth_iommu_table, -1)) printk("Virtual Bus VETH TCE table failed.\n"); - if (!iommu_init_table(&vio_iommu_table)) + if (!iommu_init_table(&vio_iommu_table, -1)) printk("Virtual Bus VIO TCE table failed.\n"); } #endif @@ -98,7 +98,7 @@ static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev) tbl->it_busno = 0; tbl->it_type = TCE_VB; - return iommu_init_table(tbl); + return iommu_init_table(tbl, -1); } } diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c index a992f6af249..e3bd2015f2c 100644 --- a/arch/powerpc/platforms/iseries/iommu.c +++ b/arch/powerpc/platforms/iseries/iommu.c @@ -173,7 +173,7 @@ void iommu_devnode_init_iSeries(struct device_node *dn) /* Look for existing tce table */ pdn->iommu_table = iommu_table_find(tbl); if (pdn->iommu_table == NULL) - pdn->iommu_table = iommu_init_table(tbl); + pdn->iommu_table = iommu_init_table(tbl, -1); else kfree(tbl); } diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 44a507e6fb3..2f66dc6503f 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -368,10 +368,11 @@ static void iommu_bus_setup_pSeries(struct pci_bus *bus) pci->phb->dma_window_size = 0x8000000ul; pci->phb->dma_window_base_cur = 0x8000000ul; - tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); + tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL, + pci->phb->node); iommu_table_setparms(pci->phb, dn, tbl); - pci->iommu_table = iommu_init_table(tbl); + pci->iommu_table = iommu_init_table(tbl, pci->phb->node); /* Divide the rest (1.75GB) among the children */ pci->phb->dma_window_size = 0x80000000ul; @@ -414,12 +415,12 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus) ppci->bussubno = bus->number; - tbl = (struct iommu_table *)kmalloc(sizeof(struct iommu_table), - GFP_KERNEL); + tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL, + ppci->phb->node); iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window); - ppci->iommu_table = iommu_init_table(tbl); + ppci->iommu_table = iommu_init_table(tbl, ppci->phb->node); } if (pdn != dn) @@ -442,9 +443,11 @@ static void iommu_dev_setup_pSeries(struct pci_dev *dev) */ if (!dev->bus->self) { DBG(" --> first child, no bridge. Allocating iommu table.\n"); - tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); + tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL, + PCI_DN(dn)->phb->node); iommu_table_setparms(PCI_DN(dn)->phb, dn, tbl); - PCI_DN(mydn)->iommu_table = iommu_init_table(tbl); + PCI_DN(dn)->iommu_table = iommu_init_table(tbl, + PCI_DN(dn)->phb->node); return; } @@ -526,12 +529,12 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev) /* iommu_table_setparms_lpar needs bussubno. */ pci->bussubno = pci->phb->bus->number; - tbl = (struct iommu_table *)kmalloc(sizeof(struct iommu_table), - GFP_KERNEL); + tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL, + pci->phb->node); iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window); - pci->iommu_table = iommu_init_table(tbl); + pci->iommu_table = iommu_init_table(tbl, pci->phb->node); } if (pdn != dn) diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c index 38087bd6e3c..6232091cc72 100644 --- a/arch/powerpc/sysdev/dart_iommu.c +++ b/arch/powerpc/sysdev/dart_iommu.c @@ -246,7 +246,7 @@ static void iommu_table_dart_setup(void) iommu_table_dart.it_base = (unsigned long)dart_vbase; iommu_table_dart.it_index = 0; iommu_table_dart.it_blocksize = 1; - iommu_init_table(&iommu_table_dart); + iommu_init_table(&iommu_table_dart, -1); /* Reserve the last page of the DART to avoid possible prefetch * past the DART mapped area diff --git a/include/asm-powerpc/iommu.h b/include/asm-powerpc/iommu.h index 9065f6c972a..32dac0ac683 100644 --- a/include/asm-powerpc/iommu.h +++ b/include/asm-powerpc/iommu.h @@ -67,7 +67,8 @@ extern void iommu_free_table(struct device_node *dn); /* Initializes an iommu_table based in values set in the passed-in * structure */ -extern struct iommu_table *iommu_init_table(struct iommu_table * tbl); +extern struct iommu_table *iommu_init_table(struct iommu_table * tbl, + int nid); extern int iommu_map_sg(struct device *dev, struct iommu_table *tbl, struct scatterlist *sglist, int nelems, unsigned long mask, -- cgit v1.2.3 From df310656c7552ae7b8252e4b3d8e300cff164b16 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Sat, 10 Jun 2006 23:04:39 +1000 Subject: [POWERPC] cleanup dma_mapping_ops For pseries IOMMU bypass I want to be able to fall back to the regular IOMMU ops. Do this by creating a dma_mapping_ops struct, and convert the others while at it. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/pci_direct_iommu.c | 18 +++++++++++------- arch/powerpc/kernel/pci_iommu.c | 18 +++++++++++------- arch/powerpc/platforms/cell/iommu.c | 18 +++++++++++------- 3 files changed, 33 insertions(+), 21 deletions(-) diff --git a/arch/powerpc/kernel/pci_direct_iommu.c b/arch/powerpc/kernel/pci_direct_iommu.c index e1a32f802c0..72ce082ce73 100644 --- a/arch/powerpc/kernel/pci_direct_iommu.c +++ b/arch/powerpc/kernel/pci_direct_iommu.c @@ -82,13 +82,17 @@ static int pci_direct_dma_supported(struct device *dev, u64 mask) return mask < 0x100000000ull; } +static struct dma_mapping_ops pci_direct_ops = { + .alloc_coherent = pci_direct_alloc_coherent, + .free_coherent = pci_direct_free_coherent, + .map_single = pci_direct_map_single, + .unmap_single = pci_direct_unmap_single, + .map_sg = pci_direct_map_sg, + .unmap_sg = pci_direct_unmap_sg, + .dma_supported = pci_direct_dma_supported, +}; + void __init pci_direct_iommu_init(void) { - pci_dma_ops.alloc_coherent = pci_direct_alloc_coherent; - pci_dma_ops.free_coherent = pci_direct_free_coherent; - pci_dma_ops.map_single = pci_direct_map_single; - pci_dma_ops.unmap_single = pci_direct_unmap_single; - pci_dma_ops.map_sg = pci_direct_map_sg; - pci_dma_ops.unmap_sg = pci_direct_unmap_sg; - pci_dma_ops.dma_supported = pci_direct_dma_supported; + pci_dma_ops = pci_direct_ops; } diff --git a/arch/powerpc/kernel/pci_iommu.c b/arch/powerpc/kernel/pci_iommu.c index 7fb4cca021b..0688b2534ac 100644 --- a/arch/powerpc/kernel/pci_iommu.c +++ b/arch/powerpc/kernel/pci_iommu.c @@ -148,13 +148,17 @@ static int pci_iommu_dma_supported(struct device *dev, u64 mask) return 1; } +struct dma_mapping_ops pci_iommu_ops = { + .alloc_coherent = pci_iommu_alloc_coherent, + .free_coherent = pci_iommu_free_coherent, + .map_single = pci_iommu_map_single, + .unmap_single = pci_iommu_unmap_single, + .map_sg = pci_iommu_map_sg, + .unmap_sg = pci_iommu_unmap_sg, + .dma_supported = pci_iommu_dma_supported, +}; + void pci_iommu_init(void) { - pci_dma_ops.alloc_coherent = pci_iommu_alloc_coherent; - pci_dma_ops.free_coherent = pci_iommu_free_coherent; - pci_dma_ops.map_single = pci_iommu_map_single; - pci_dma_ops.unmap_single = pci_iommu_unmap_single; - pci_dma_ops.map_sg = pci_iommu_map_sg; - pci_dma_ops.unmap_sg = pci_iommu_unmap_sg; - pci_dma_ops.dma_supported = pci_iommu_dma_supported; + pci_dma_ops = pci_iommu_ops; } diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c index a49ceb799a8..a35004e14c6 100644 --- a/arch/powerpc/platforms/cell/iommu.c +++ b/arch/powerpc/platforms/cell/iommu.c @@ -473,6 +473,16 @@ static int cell_dma_supported(struct device *dev, u64 mask) return mask < 0x100000000ull; } +static struct dma_mapping_ops cell_iommu_ops = { + .alloc_coherent = cell_alloc_coherent, + .free_coherent = cell_free_coherent, + .map_single = cell_map_single, + .unmap_single = cell_unmap_single, + .map_sg = cell_map_sg, + .unmap_sg = cell_unmap_sg, + .dma_supported = cell_dma_supported, +}; + void cell_init_iommu(void) { int setup_bus = 0; @@ -498,11 +508,5 @@ void cell_init_iommu(void) } } - pci_dma_ops.alloc_coherent = cell_alloc_coherent; - pci_dma_ops.free_coherent = cell_free_coherent; - pci_dma_ops.map_single = cell_map_single; - pci_dma_ops.unmap_single = cell_unmap_single; - pci_dma_ops.map_sg = cell_map_sg; - pci_dma_ops.unmap_sg = cell_unmap_sg; - pci_dma_ops.dma_supported = cell_dma_supported; + pci_dma_ops = cell_iommu_ops; } -- cgit v1.2.3 From 9e6e3c2c796f1e0ef335804d5c87073e365dea50 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Sat, 10 Jun 2006 23:14:51 +1000 Subject: [POWERPC] Fix HV bit handling on non partitioned machines On non partitioned machines we currently set the HV bit in kernel space only. It turns out we are supposed to maintain the HV bit in both user and kernel space. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras --- include/asm-powerpc/reg.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/asm-powerpc/reg.h b/include/asm-powerpc/reg.h index bfc7dc14ffc..f2ed7577aa3 100644 --- a/include/asm-powerpc/reg.h +++ b/include/asm-powerpc/reg.h @@ -93,8 +93,8 @@ #define MSR_LE __MASK(MSR_LE_LG) /* Little Endian */ #ifdef CONFIG_PPC64 -#define MSR_ MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_ISF -#define MSR_KERNEL MSR_ | MSR_SF | MSR_HV +#define MSR_ MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_ISF |MSR_HV +#define MSR_KERNEL MSR_ | MSR_SF #define MSR_USER32 MSR_ | MSR_PR | MSR_EE #define MSR_USER64 MSR_USER32 | MSR_SF -- cgit v1.2.3 From bd19c8994a828e70b5472f0ce9df5831c6c3db84 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Sun, 11 Jun 2006 01:15:55 +1000 Subject: [POWERPC] system call micro optimisation In the syscall path we currently have: crclr so mfcr r9 If we shift the crclr up we can avoid a stall on some CPUs. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/entry_64.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 19ad5c6b181..221062c960c 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -57,6 +57,7 @@ system_call_common: beq- 1f ld r1,PACAKSAVE(r13) 1: std r10,0(r1) + crclr so std r11,_NIP(r1) std r12,_MSR(r1) std r0,GPR0(r1) @@ -75,7 +76,6 @@ system_call_common: std r11,GPR11(r1) std r11,GPR12(r1) std r9,GPR13(r1) - crclr so mfcr r9 mflr r10 li r11,0xc01 -- cgit v1.2.3 From 6fe87675314b4b1ac7ba339e2a4ab8d739b600d6 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Sun, 11 Jun 2006 11:40:43 +1000 Subject: [POWERPC] update pmac32_defconfig Some updates to the pmac32_defconfig to make it more useful: - Enable LSF (large single files) since we enable LBD (large block devices) - Enable IPSEC related options - Enable remaining raid/dm options as modules - Disable eth1394, I doubt any has that hardware and it has a nasty habit of auto loading first and skewing network device numbering - Enable dummy and tun as modules, always useful to have them around - Enable EHCI, no wonder my usb2 disk was so slow - Enable USB storage - Enable ext3 acls - Disable autofs and enable autofsv4 instead - Enable nfs v3/v4 client and server. Dont want to be left in the dark ages of pre v3 - Enable all crypto as modules, things like cryptsetup want some of them I havent enabled the BCM43xx, perhaps we should now? Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras --- arch/powerpc/configs/pmac32_defconfig | 204 +++++++++++++++++++++------------- 1 file changed, 124 insertions(+), 80 deletions(-) diff --git a/arch/powerpc/configs/pmac32_defconfig b/arch/powerpc/configs/pmac32_defconfig index 57a027971d6..addc79381c3 100644 --- a/arch/powerpc/configs/pmac32_defconfig +++ b/arch/powerpc/configs/pmac32_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.16-rc6 -# Wed Mar 15 16:21:32 2006 +# Linux kernel version: 2.6.17-rc5 +# Mon May 29 14:47:49 2006 # # CONFIG_PPC64 is not set CONFIG_PPC32=y @@ -9,6 +9,7 @@ CONFIG_PPC_MERGE=y CONFIG_MMU=y CONFIG_GENERIC_HARDIRQS=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_PPC=y CONFIG_EARLY_PRINTK=y @@ -27,11 +28,11 @@ CONFIG_CLASSIC32=y # CONFIG_PPC_52xx is not set # CONFIG_PPC_82xx is not set # CONFIG_PPC_83xx is not set +# CONFIG_PPC_85xx is not set # CONFIG_40x is not set # CONFIG_44x is not set # CONFIG_8xx is not set # CONFIG_E200 is not set -# CONFIG_E500 is not set CONFIG_6xx=y CONFIG_PPC_FPU=y CONFIG_ALTIVEC=y @@ -59,6 +60,7 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y +# CONFIG_RELAY is not set CONFIG_INITRAMFS_SOURCE="" # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # CONFIG_EMBEDDED is not set @@ -73,10 +75,6 @@ CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y CONFIG_SHMEM=y -CONFIG_CC_ALIGN_FUNCTIONS=0 -CONFIG_CC_ALIGN_LABELS=0 -CONFIG_CC_ALIGN_LOOPS=0 -CONFIG_CC_ALIGN_JUMPS=0 CONFIG_SLAB=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 @@ -88,7 +86,6 @@ CONFIG_BASE_SMALL=0 CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y -CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y @@ -97,6 +94,8 @@ CONFIG_KMOD=y # Block layer # CONFIG_LBD=y +# CONFIG_BLK_DEV_IO_TRACE is not set +CONFIG_LSF=y # # IO Schedulers @@ -124,6 +123,7 @@ CONFIG_MPIC=y # CONFIG_PPC_RTAS is not set # CONFIG_MMIO_NVRAM is not set CONFIG_PPC_MPC106=y +# CONFIG_PPC_970_NAP is not set CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_TABLE=y # CONFIG_CPU_FREQ_DEBUG is not set @@ -182,7 +182,6 @@ CONFIG_GENERIC_ISA_DMA=y CONFIG_PPC_INDIRECT_PCI=y CONFIG_PCI=y CONFIG_PCI_DOMAINS=y -CONFIG_PCI_LEGACY_PROC=y # CONFIG_PCI_DEBUG is not set # @@ -239,7 +238,9 @@ CONFIG_NET=y CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y -# CONFIG_NET_KEY is not set +CONFIG_XFRM=y +CONFIG_XFRM_USER=y +CONFIG_NET_KEY=y CONFIG_INET=y CONFIG_IP_MULTICAST=y # CONFIG_IP_ADVANCED_ROUTER is not set @@ -250,9 +251,10 @@ CONFIG_IP_FIB_HASH=y # CONFIG_IP_MROUTE is not set # CONFIG_ARPD is not set CONFIG_SYN_COOKIES=y -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set +CONFIG_INET_AH=y +CONFIG_INET_ESP=y # CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set # CONFIG_INET_TUNNEL is not set CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y @@ -264,6 +266,8 @@ CONFIG_TCP_CONG_BIC=y # # CONFIG_IP_VS is not set # CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set @@ -278,12 +282,15 @@ CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m CONFIG_NETFILTER_XT_TARGET_NOTRACK=m CONFIG_NETFILTER_XT_MATCH_COMMENT=m CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m -# CONFIG_NETFILTER_XT_MATCH_DCCP is not set +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m CONFIG_NETFILTER_XT_MATCH_HELPER=m CONFIG_NETFILTER_XT_MATCH_LENGTH=m CONFIG_NETFILTER_XT_MATCH_LIMIT=m CONFIG_NETFILTER_XT_MATCH_MAC=m CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m CONFIG_NETFILTER_XT_MATCH_REALM=m CONFIG_NETFILTER_XT_MATCH_SCTP=m @@ -305,15 +312,15 @@ CONFIG_IP_NF_NETBIOS_NS=m CONFIG_IP_NF_TFTP=m CONFIG_IP_NF_AMANDA=m CONFIG_IP_NF_PPTP=m +CONFIG_IP_NF_H323=m # CONFIG_IP_NF_QUEUE is not set CONFIG_IP_NF_IPTABLES=m CONFIG_IP_NF_MATCH_IPRANGE=m -CONFIG_IP_NF_MATCH_MULTIPORT=m CONFIG_IP_NF_MATCH_TOS=m CONFIG_IP_NF_MATCH_RECENT=m CONFIG_IP_NF_MATCH_ECN=m CONFIG_IP_NF_MATCH_DSCP=m -CONFIG_IP_NF_MATCH_AH_ESP=m +CONFIG_IP_NF_MATCH_AH=m CONFIG_IP_NF_MATCH_TTL=m CONFIG_IP_NF_MATCH_OWNER=m CONFIG_IP_NF_MATCH_ADDRTYPE=m @@ -335,6 +342,7 @@ CONFIG_IP_NF_NAT_FTP=m CONFIG_IP_NF_NAT_TFTP=m CONFIG_IP_NF_NAT_AMANDA=m CONFIG_IP_NF_NAT_PPTP=m +CONFIG_IP_NF_NAT_H323=m CONFIG_IP_NF_MANGLE=m CONFIG_IP_NF_TARGET_TOS=m CONFIG_IP_NF_TARGET_ECN=m @@ -350,10 +358,12 @@ CONFIG_IP_NF_ARP_MANGLE=m # CONFIG_IP_DCCP=m CONFIG_INET_DCCP_DIAG=m +CONFIG_IP_DCCP_ACKVEC=y # # DCCP CCIDs Configuration (EXPERIMENTAL) # +CONFIG_IP_DCCP_CCID2=m CONFIG_IP_DCCP_CCID3=m CONFIG_IP_DCCP_TFRC_LIB=m @@ -361,7 +371,6 @@ CONFIG_IP_DCCP_TFRC_LIB=m # DCCP Kernel Hacking # # CONFIG_IP_DCCP_DEBUG is not set -# CONFIG_IP_DCCP_UNLOAD_HACK is not set # # SCTP Configuration (EXPERIMENTAL) @@ -477,6 +486,8 @@ CONFIG_IEEE80211=m CONFIG_IEEE80211_CRYPT_WEP=m CONFIG_IEEE80211_CRYPT_CCMP=m CONFIG_IEEE80211_CRYPT_TKIP=m +# CONFIG_IEEE80211_SOFTMAC is not set +CONFIG_WIRELESS_EXT=y # # Device Drivers @@ -662,9 +673,8 @@ CONFIG_SCSI_SYM53C8XX_2=y CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 -# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set +CONFIG_SCSI_SYM53C8XX_MMIO=y # CONFIG_SCSI_IPR is not set -# CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set # CONFIG_SCSI_QLA_FC is not set # CONFIG_SCSI_LPFC is not set @@ -694,16 +704,17 @@ CONFIG_BLK_DEV_MD=m CONFIG_MD_LINEAR=m CONFIG_MD_RAID0=m CONFIG_MD_RAID1=m -# CONFIG_MD_RAID10 is not set +CONFIG_MD_RAID10=m CONFIG_MD_RAID5=m +CONFIG_MD_RAID5_RESHAPE=y CONFIG_MD_RAID6=m CONFIG_MD_MULTIPATH=m CONFIG_MD_FAULTY=m CONFIG_BLK_DEV_DM=m CONFIG_DM_CRYPT=m -# CONFIG_DM_SNAPSHOT is not set -# CONFIG_DM_MIRROR is not set -# CONFIG_DM_ZERO is not set +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_ZERO=m # CONFIG_DM_MULTIPATH is not set # @@ -740,7 +751,7 @@ CONFIG_IEEE1394_OHCI1394=m CONFIG_IEEE1394_VIDEO1394=m CONFIG_IEEE1394_SBP2=m # CONFIG_IEEE1394_SBP2_PHYS_DMA is not set -CONFIG_IEEE1394_ETH1394=m +# CONFIG_IEEE1394_ETH1394 is not set CONFIG_IEEE1394_DV1394=m CONFIG_IEEE1394_RAWIO=m @@ -769,10 +780,10 @@ CONFIG_THERM_ADT746X=m # Network device support # CONFIG_NETDEVICES=y -# CONFIG_DUMMY is not set +CONFIG_DUMMY=m # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set +CONFIG_TUN=m # # ARCnet devices @@ -857,6 +868,7 @@ CONFIG_PCNET32=y # Wireless LAN (non-hamradio) # CONFIG_NET_RADIO=y +# CONFIG_NET_WIRELESS_RTNETLINK is not set # # Obsolete Wireless cards support (pre-802.11) @@ -992,6 +1004,7 @@ CONFIG_HW_CONSOLE=y # Serial drivers # CONFIG_SERIAL_8250=m +CONFIG_SERIAL_8250_PCI=m # CONFIG_SERIAL_8250_CS is not set CONFIG_SERIAL_8250_NR_UARTS=4 CONFIG_SERIAL_8250_RUNTIME_UARTS=4 @@ -1027,6 +1040,7 @@ CONFIG_GEN_RTC=y # Ftape, the floppy tape device driver # CONFIG_AGP=m +# CONFIG_AGP_VIA is not set CONFIG_AGP_UNINORTH=m CONFIG_DRM=m # CONFIG_DRM_TDFX is not set @@ -1081,7 +1095,6 @@ CONFIG_I2C_POWERMAC=y # CONFIG_I2C_PARPORT_LIGHT is not set # CONFIG_I2C_PROSAVAGE is not set # CONFIG_I2C_SAVAGE4 is not set -# CONFIG_SCx200_ACB is not set # CONFIG_I2C_SIS5595 is not set # CONFIG_I2C_SIS630 is not set # CONFIG_I2C_SIS96X is not set @@ -1100,10 +1113,8 @@ CONFIG_I2C_POWERMAC=y # CONFIG_SENSORS_PCF8574 is not set # CONFIG_SENSORS_PCA9539 is not set # CONFIG_SENSORS_PCF8591 is not set -# CONFIG_SENSORS_RTC8564 is not set # CONFIG_SENSORS_M41T00 is not set # CONFIG_SENSORS_MAX6875 is not set -# CONFIG_RTC_X1205_I2C is not set # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set @@ -1130,19 +1141,17 @@ CONFIG_I2C_POWERMAC=y # Misc devices # -# -# Multimedia Capabilities Port drivers -# - # # Multimedia devices # # CONFIG_VIDEO_DEV is not set +CONFIG_VIDEO_V4L2=y # # Digital Video Broadcasting Devices # # CONFIG_DVB is not set +# CONFIG_USB_DABUSB is not set # # Graphics support @@ -1152,6 +1161,7 @@ CONFIG_FB_CFB_FILLRECT=y CONFIG_FB_CFB_COPYAREA=y CONFIG_FB_CFB_IMAGEBLIT=y CONFIG_FB_MACMODES=y +CONFIG_FB_FIRMWARE_EDID=y CONFIG_FB_MODE_HELPERS=y CONFIG_FB_TILEBLITTING=y # CONFIG_FB_CIRRUS is not set @@ -1175,7 +1185,6 @@ CONFIG_FB_MATROX_MYSTIQUE=y # CONFIG_FB_MATROX_G is not set # CONFIG_FB_MATROX_I2C is not set # CONFIG_FB_MATROX_MULTIHEAD is not set -# CONFIG_FB_RADEON_OLD is not set CONFIG_FB_RADEON=y CONFIG_FB_RADEON_I2C=y # CONFIG_FB_RADEON_DEBUG is not set @@ -1234,9 +1243,11 @@ CONFIG_SND_SEQ_DUMMY=m CONFIG_SND_OSSEMUL=y CONFIG_SND_MIXER_OSS=m CONFIG_SND_PCM_OSS=m +CONFIG_SND_PCM_OSS_PLUGINS=y CONFIG_SND_SEQUENCER_OSS=y # CONFIG_SND_DYNAMIC_MINORS is not set CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_VERBOSE_PROCFS=y # CONFIG_SND_VERBOSE_PRINTK is not set # CONFIG_SND_DEBUG is not set @@ -1253,6 +1264,7 @@ CONFIG_SND_DUMMY=m # PCI devices # # CONFIG_SND_AD1889 is not set +# CONFIG_SND_ALS300 is not set # CONFIG_SND_ALS4000 is not set # CONFIG_SND_ALI5451 is not set # CONFIG_SND_ATIIXP is not set @@ -1285,6 +1297,7 @@ CONFIG_SND_DUMMY=m # CONFIG_SND_MIXART is not set # CONFIG_SND_NM256 is not set # CONFIG_SND_PCXHR is not set +# CONFIG_SND_RIPTIDE is not set # CONFIG_SND_RME32 is not set # CONFIG_SND_RME96 is not set # CONFIG_SND_RME9652 is not set @@ -1310,6 +1323,8 @@ CONFIG_SND_USB_AUDIO=m # # PCMCIA devices # +# CONFIG_SND_VXPOCKET is not set +# CONFIG_SND_PDAUDIOCF is not set # # Open Sound System @@ -1321,6 +1336,7 @@ CONFIG_SND_USB_AUDIO=m # CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y CONFIG_USB=y # CONFIG_USB_DEBUG is not set @@ -1336,7 +1352,9 @@ CONFIG_USB_DYNAMIC_MINORS=y # # USB Host Controller Drivers # -# CONFIG_USB_EHCI_HCD is not set +CONFIG_USB_EHCI_HCD=m +CONFIG_USB_EHCI_SPLIT_ISO=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y # CONFIG_USB_ISP116X_HCD is not set CONFIG_USB_OHCI_HCD=y # CONFIG_USB_OHCI_BIG_ENDIAN is not set @@ -1347,7 +1365,6 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y # # USB Device Class drivers # -# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set CONFIG_USB_ACM=m CONFIG_USB_PRINTER=m @@ -1358,7 +1375,17 @@ CONFIG_USB_PRINTER=m # # may also be needed; see USB_STORAGE Help for more information # -# CONFIG_USB_STORAGE is not set +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set # CONFIG_USB_LIBUSUAL is not set # @@ -1374,9 +1401,7 @@ CONFIG_USB_HIDINPUT_POWERBOOK=y # CONFIG_USB_ACECAD is not set # CONFIG_USB_KBTAB is not set # CONFIG_USB_POWERMATE is not set -# CONFIG_USB_MTOUCH is not set -# CONFIG_USB_ITMTOUCH is not set -# CONFIG_USB_EGALAX is not set +# CONFIG_USB_TOUCHSCREEN is not set # CONFIG_USB_YEALINK is not set # CONFIG_USB_XPAD is not set # CONFIG_USB_ATI_REMOTE is not set @@ -1390,15 +1415,6 @@ CONFIG_USB_APPLETOUCH=y # CONFIG_USB_MDC800 is not set # CONFIG_USB_MICROTEK is not set -# -# USB Multimedia devices -# -# CONFIG_USB_DABUSB is not set - -# -# Video4Linux support is needed for USB Multimedia device support -# - # # USB Network Adapters # @@ -1429,6 +1445,7 @@ CONFIG_USB_SERIAL=m # CONFIG_USB_SERIAL_GENERIC is not set # CONFIG_USB_SERIAL_AIRPRIME is not set # CONFIG_USB_SERIAL_ANYDATA is not set +# CONFIG_USB_SERIAL_ARK3116 is not set # CONFIG_USB_SERIAL_BELKIN is not set # CONFIG_USB_SERIAL_WHITEHEAT is not set # CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set @@ -1436,6 +1453,7 @@ CONFIG_USB_SERIAL=m # CONFIG_USB_SERIAL_CYPRESS_M8 is not set # CONFIG_USB_SERIAL_EMPEG is not set # CONFIG_USB_SERIAL_FTDI_SIO is not set +# CONFIG_USB_SERIAL_FUNSOFT is not set CONFIG_USB_SERIAL_VISOR=m CONFIG_USB_SERIAL_IPAQ=m # CONFIG_USB_SERIAL_IR is not set @@ -1460,6 +1478,7 @@ CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y # CONFIG_USB_SERIAL_KLSI is not set # CONFIG_USB_SERIAL_KOBIL_SCT is not set # CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_NAVMAN is not set # CONFIG_USB_SERIAL_PL2303 is not set # CONFIG_USB_SERIAL_HP4X is not set # CONFIG_USB_SERIAL_SAFE is not set @@ -1484,6 +1503,7 @@ CONFIG_USB_EZUSB=y # CONFIG_USB_PHIDGETKIT is not set # CONFIG_USB_PHIDGETSERVO is not set # CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_SISUSBVGA is not set # CONFIG_USB_LD is not set # CONFIG_USB_TEST is not set @@ -1501,6 +1521,19 @@ CONFIG_USB_EZUSB=y # # CONFIG_MMC is not set +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + # # InfiniBand support # @@ -1510,6 +1543,11 @@ CONFIG_USB_EZUSB=y # EDAC - error detection and reporting (RAS) (EXPERIMENTAL) # +# +# Real Time Clock +# +# CONFIG_RTC_CLASS is not set + # # File systems # @@ -1518,14 +1556,14 @@ CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XIP is not set CONFIG_EXT3_FS=y CONFIG_EXT3_FS_XATTR=y -# CONFIG_EXT3_FS_POSIX_ACL is not set +CONFIG_EXT3_FS_POSIX_ACL=y # CONFIG_EXT3_FS_SECURITY is not set CONFIG_JBD=y # CONFIG_JBD_DEBUG is not set CONFIG_FS_MBCACHE=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set -# CONFIG_FS_POSIX_ACL is not set +CONFIG_FS_POSIX_ACL=y # CONFIG_XFS_FS is not set # CONFIG_OCFS2_FS is not set # CONFIG_MINIX_FS is not set @@ -1534,7 +1572,7 @@ CONFIG_INOTIFY=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set +CONFIG_AUTOFS4_FS=m CONFIG_FUSE_FS=m # @@ -1566,7 +1604,6 @@ CONFIG_SYSFS=y CONFIG_TMPFS=y # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y -CONFIG_RELAYFS_FS=m # CONFIG_CONFIGFS_FS is not set # @@ -1590,17 +1627,24 @@ CONFIG_HFSPLUS_FS=m # Network File Systems # CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set -# CONFIG_NFS_V4 is not set +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y # CONFIG_NFS_DIRECTIO is not set -CONFIG_NFSD=y -# CONFIG_NFSD_V3 is not set -# CONFIG_NFSD_TCP is not set +CONFIG_NFSD=m +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_NFSD_TCP=y CONFIG_LOCKD=y -CONFIG_EXPORTFS=y +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_NFS_ACL_SUPPORT=y CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y -# CONFIG_RPCSEC_GSS_KRB5 is not set +CONFIG_SUNRPC_GSS=y +CONFIG_RPCSEC_GSS_KRB5=y # CONFIG_RPCSEC_GSS_SPKM3 is not set CONFIG_SMB_FS=m # CONFIG_SMB_NLS_DEFAULT is not set @@ -1681,7 +1725,7 @@ CONFIG_NLS_UTF8=m CONFIG_CRC_CCITT=y CONFIG_CRC16=y CONFIG_CRC32=y -# CONFIG_LIBCRC32C is not set +CONFIG_LIBCRC32C=m CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=y CONFIG_TEXTSEARCH=y @@ -1735,29 +1779,29 @@ CONFIG_BOOTX_TEXT=y # Cryptographic options # CONFIG_CRYPTO=y -# CONFIG_CRYPTO_HMAC is not set -# CONFIG_CRYPTO_NULL is not set -# CONFIG_CRYPTO_MD4 is not set -# CONFIG_CRYPTO_MD5 is not set -# CONFIG_CRYPTO_SHA1 is not set -# CONFIG_CRYPTO_SHA256 is not set -# CONFIG_CRYPTO_SHA512 is not set -# CONFIG_CRYPTO_WP512 is not set -# CONFIG_CRYPTO_TGR192 is not set -# CONFIG_CRYPTO_DES is not set -# CONFIG_CRYPTO_BLOWFISH is not set -# CONFIG_CRYPTO_TWOFISH is not set -# CONFIG_CRYPTO_SERPENT is not set +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_DES=y +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_SERPENT=m CONFIG_CRYPTO_AES=m -# CONFIG_CRYPTO_CAST5 is not set -# CONFIG_CRYPTO_CAST6 is not set -# CONFIG_CRYPTO_TEA is not set +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_TEA=m CONFIG_CRYPTO_ARC4=m -# CONFIG_CRYPTO_KHAZAD is not set -# CONFIG_CRYPTO_ANUBIS is not set -# CONFIG_CRYPTO_DEFLATE is not set +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_DEFLATE=m CONFIG_CRYPTO_MICHAEL_MIC=m -# CONFIG_CRYPTO_CRC32C is not set +CONFIG_CRYPTO_CRC32C=m # CONFIG_CRYPTO_TEST is not set # -- cgit v1.2.3 From 0e4aa9c2009187fff1c999fe0aaa134c1a84f48a Mon Sep 17 00:00:00 2001 From: Amos Waterland Date: Mon, 12 Jun 2006 23:45:02 -0400 Subject: [POWERPC] Fix builtin command line interaction with firmware It seems that prom_init's early_cmdline_parse is broken on at least Apple 970 xserves and IBM JS20 blades with SLOF. The firmware of these machines returns -1 and 1 respectively when getprop is called for the bootargs property of /chosen, causing Linux to ignore its builtin command line in favor of a null string. This patch makes Linux use its builtin command line if getprop returns an error or a null string. Signed-off-by: Amos Waterland Acked-by: Segher Boessenkool Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/prom_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 57d8a16438a..8c28eb0cbda 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -567,7 +567,7 @@ static void __init early_cmdline_parse(void) if ((long)_prom->chosen > 0) l = prom_getprop(_prom->chosen, "bootargs", p, COMMAND_LINE_SIZE-1); #ifdef CONFIG_CMDLINE - if (l == 0) /* dbl check */ + if (l <= 0 || p[0] == '\0') /* dbl check */ strlcpy(RELOC(prom_cmd_line), RELOC(CONFIG_CMDLINE), sizeof(prom_cmd_line)); #endif /* CONFIG_CMDLINE */ -- cgit v1.2.3 From 368a6ba5d188552aea2a668301a259164c9f355e Mon Sep 17 00:00:00 2001 From: Dave C Boutcher Date: Mon, 12 Jun 2006 19:49:20 -0500 Subject: [POWERPC] check firmware state before suspending Currently the kernel blindly halts all the processors and calls the ibm,suspend-me rtas call. If the firmware is not in the correct state, we then re-start all the processors and return. It is much smarter to first check the firmware state, and only if it is waiting, call the ibm,suspend-me call. Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/rtas.c | 22 ++++++++++++++++++++++ include/asm-powerpc/hvcall.h | 10 ++++++++++ include/asm-powerpc/rtas.h | 1 + 3 files changed, 33 insertions(+) diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 13496f31985..fd15e3e3bb3 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -593,9 +593,31 @@ out: static int rtas_ibm_suspend_me(struct rtas_args *args) { int i; + long state; + long rc; + unsigned long dummy; struct rtas_suspend_me_data data; + /* Make sure the state is valid */ + rc = plpar_hcall(H_VASI_STATE, + ((u64)args->args[0] << 32) | args->args[1], + 0, 0, 0, + &state, &dummy, &dummy); + + if (rc) { + printk(KERN_ERR "rtas_ibm_suspend_me: vasi_state returned %ld\n",rc); + return rc; + } else if (state == H_VASI_ENABLED) { + args->args[args->nargs] = RTAS_NOT_SUSPENDABLE; + return 0; + } else if (state != H_VASI_SUSPENDING) { + printk(KERN_ERR "rtas_ibm_suspend_me: vasi_state returned state %ld\n", + state); + args->args[args->nargs] = -1; + return 0; + } + data.waiting = 1; data.args = args; diff --git a/include/asm-powerpc/hvcall.h b/include/asm-powerpc/hvcall.h index 6cc7e1fb7bf..0d3c4e85711 100644 --- a/include/asm-powerpc/hvcall.h +++ b/include/asm-powerpc/hvcall.h @@ -102,6 +102,15 @@ #define H_PP1 (1UL<<(63-62)) #define H_PP2 (1UL<<(63-63)) +/* VASI States */ +#define H_VASI_INVALID 0 +#define H_VASI_ENABLED 1 +#define H_VASI_ABORTED 2 +#define H_VASI_SUSPENDING 3 +#define H_VASI_SUSPENDED 4 +#define H_VASI_RESUMED 5 +#define H_VASI_COMPLETED 6 + /* DABRX flags */ #define H_DABRX_HYPERVISOR (1UL<<(63-61)) #define H_DABRX_KERNEL (1UL<<(63-62)) @@ -190,6 +199,7 @@ #define H_QUERY_INT_STATE 0x1E4 #define H_POLL_PENDING 0x1D8 #define H_JOIN 0x298 +#define H_VASI_STATE 0x2A4 #define H_ENABLE_CRQ 0x2B0 #ifndef __ASSEMBLY__ diff --git a/include/asm-powerpc/rtas.h b/include/asm-powerpc/rtas.h index a3b4e55569c..02e213e3d69 100644 --- a/include/asm-powerpc/rtas.h +++ b/include/asm-powerpc/rtas.h @@ -24,6 +24,7 @@ #define RTAS_RMOBUF_MAX (64 * 1024) /* RTAS return status codes */ +#define RTAS_NOT_SUSPENDABLE -9004 #define RTAS_BUSY -2 /* RTAS Busy */ #define RTAS_EXTENDED_DELAY_MIN 9900 #define RTAS_EXTENDED_DELAY_MAX 9905 -- cgit v1.2.3 From 4312dc76a88146c4f1d693fc4643d1df12aaf755 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 13 Jun 2006 17:43:42 +0200 Subject: [POWERPC] make pmf irq_client functions safe against pmf interrupts coming in This fixes the pmf irq_client functions to be safe against pmf interrupts coming in while a client is registered/unregistered. Signed-off-by: Johannes Berg Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/powermac/pfunc_core.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/powerpc/platforms/powermac/pfunc_core.c b/arch/powerpc/platforms/powermac/pfunc_core.c index f08173b0f06..047f954a89e 100644 --- a/arch/powerpc/platforms/powermac/pfunc_core.c +++ b/arch/powerpc/platforms/powermac/pfunc_core.c @@ -871,10 +871,17 @@ int pmf_register_irq_client(struct device_node *target, spin_unlock_irqrestore(&pmf_lock, flags); if (func == NULL) return -ENODEV; + + /* guard against manipulations of list */ mutex_lock(&pmf_irq_mutex); if (list_empty(&func->irq_clients)) func->dev->handlers->irq_enable(func); + + /* guard against pmf_do_irq while changing list */ + spin_lock_irqsave(&pmf_lock, flags); list_add(&client->link, &func->irq_clients); + spin_unlock_irqrestore(&pmf_lock, flags); + client->func = func; mutex_unlock(&pmf_irq_mutex); @@ -885,12 +892,19 @@ EXPORT_SYMBOL_GPL(pmf_register_irq_client); void pmf_unregister_irq_client(struct pmf_irq_client *client) { struct pmf_function *func = client->func; + unsigned long flags; BUG_ON(func == NULL); + /* guard against manipulations of list */ mutex_lock(&pmf_irq_mutex); client->func = NULL; + + /* guard against pmf_do_irq while changing list */ + spin_lock_irqsave(&pmf_lock, flags); list_del(&client->link); + spin_unlock_irqrestore(&pmf_lock, flags); + if (list_empty(&func->irq_clients)) func->dev->handlers->irq_disable(func); mutex_unlock(&pmf_irq_mutex); -- cgit v1.2.3 From 2ba73b1d6fa62ddaa235c3c5fdf6095cae6ba748 Mon Sep 17 00:00:00 2001 From: Matthias Fuchs Date: Wed, 14 Jun 2006 15:35:05 +0200 Subject: [POWERPC] ppc32: fix CPCI405 board support Hi, this patch brings the CPCI405 board support up to date and fixes several outstanding issues: -add bios_fixup() -enable RTC only when CONFIG_GEN_RTC defined -corrected CompactPCI interrupt map -added cpci405_early_serial_map for correct UART clocking -removed unused code Matthias Signed-off-by: Matthias Fuchs Signed-off-by: Paul Mackerras --- arch/ppc/platforms/4xx/Kconfig | 2 +- arch/ppc/platforms/4xx/cpci405.c | 139 +++++++++++++++++++++++++++++++++++---- arch/ppc/platforms/4xx/cpci405.h | 30 ++++----- 3 files changed, 140 insertions(+), 31 deletions(-) diff --git a/arch/ppc/platforms/4xx/Kconfig b/arch/ppc/platforms/4xx/Kconfig index 174ddbc9758..293bd489e7d 100644 --- a/arch/ppc/platforms/4xx/Kconfig +++ b/arch/ppc/platforms/4xx/Kconfig @@ -183,7 +183,7 @@ config IBM_EMAC4 config BIOS_FIXUP bool - depends on BUBINGA || EP405 || SYCAMORE || WALNUT + depends on BUBINGA || EP405 || SYCAMORE || WALNUT || CPCI405 default y # OAK doesn't exist but wanted to keep this around for any future 403GCX boards diff --git a/arch/ppc/platforms/4xx/cpci405.c b/arch/ppc/platforms/4xx/cpci405.c index 6571e39fbe4..970b69831e6 100644 --- a/arch/ppc/platforms/4xx/cpci405.c +++ b/arch/ppc/platforms/4xx/cpci405.c @@ -1,10 +1,12 @@ /* * Board setup routines for the esd CPCI-405 cPCI Board. * - * Author: Stefan Roese - * stefan.roese@esd-electronics.com + * Copyright 2001-2006 esd electronic system design - hannover germany * - * Copyright 2001 esd electronic system design - hannover germany + * Authors: Matthias Fuchs + * matthias.fuchs@esd-electronics.com + * Stefan Roese + * stefan.roese@esd-electronics.com * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -20,9 +22,17 @@ #include #include #include +#include +#include #include +#include +#include +#ifdef CONFIG_GEN_RTC void *cpci405_nvram; +#endif + +extern bd_t __res; /* * Some IRQs unique to CPCI-405. @@ -36,18 +46,69 @@ ppc405_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) * A B C D */ { - {28, 28, 28, 28}, /* IDSEL 15 - cPCI slot 8 */ - {29, 29, 29, 29}, /* IDSEL 16 - cPCI slot 7 */ - {30, 30, 30, 30}, /* IDSEL 17 - cPCI slot 6 */ - {27, 27, 27, 27}, /* IDSEL 18 - cPCI slot 5 */ - {28, 28, 28, 28}, /* IDSEL 19 - cPCI slot 4 */ - {29, 29, 29, 29}, /* IDSEL 20 - cPCI slot 3 */ - {30, 30, 30, 30}, /* IDSEL 21 - cPCI slot 2 */ + {28, 29, 30, 27}, /* IDSEL 15 - cPCI slot 8 */ + {29, 30, 27, 28}, /* IDSEL 16 - cPCI slot 7 */ + {30, 27, 28, 29}, /* IDSEL 17 - cPCI slot 6 */ + {27, 28, 29, 30}, /* IDSEL 18 - cPCI slot 5 */ + {28, 29, 30, 27}, /* IDSEL 19 - cPCI slot 4 */ + {29, 30, 27, 28}, /* IDSEL 20 - cPCI slot 3 */ + {30, 27, 28, 29}, /* IDSEL 21 - cPCI slot 2 */ }; const long min_idsel = 15, max_idsel = 21, irqs_per_slot = 4; return PCI_IRQ_TABLE_LOOKUP; }; +/* The serial clock for the chip is an internal clock determined by + * different clock speeds/dividers. + * Calculate the proper input baud rate and setup the serial driver. + */ +static void __init +cpci405_early_serial_map(void) +{ + u32 uart_div; + int uart_clock; + struct uart_port port; + + /* Calculate the serial clock input frequency + * + * The uart clock is the cpu frequency (provided in the board info + * structure) divided by the external UART Divisor. + */ + uart_div = ((mfdcr(DCRN_CHCR_BASE) & CHR0_UDIV) >> 1) + 1; + uart_clock = __res.bi_procfreq / uart_div; + + /* Setup serial port access */ + memset(&port, 0, sizeof(port)); +#if defined(CONFIG_UART0_TTYS0) + port.membase = (void*)UART0_IO_BASE; + port.irq = UART0_INT; +#else + port.membase = (void*)UART1_IO_BASE; + port.irq = UART1_INT; +#endif + port.uartclk = uart_clock; + port.regshift = 0; + port.iotype = UPIO_MEM; + port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; + port.line = 0; + + if (early_serial_setup(&port) != 0) { + printk("Early serial init of port 0 failed\n"); + } +#if defined(CONFIG_UART0_TTYS0) + port.membase = (void*)UART1_IO_BASE; + port.irq = UART1_INT; +#else + port.membase = (void*)UART0_IO_BASE; + port.irq = UART0_INT; +#endif + port.line = 1; + + if (early_serial_setup(&port) != 0) { + printk("Early serial init of port 1 failed\n"); + } +} + void __init cpci405_setup_arch(void) { @@ -55,14 +116,68 @@ cpci405_setup_arch(void) ibm_ocp_set_emac(0, 0); - TODC_INIT(TODC_TYPE_MK48T35, cpci405_nvram, cpci405_nvram, cpci405_nvram, 8); + cpci405_early_serial_map(); + +#ifdef CONFIG_GEN_RTC + TODC_INIT(TODC_TYPE_MK48T35, + cpci405_nvram, cpci405_nvram, cpci405_nvram, 8); +#endif +} + +void __init +bios_fixup(struct pci_controller *hose, struct pcil0_regs *pcip) +{ + unsigned int bar_response, bar; + + /* Disable region first */ + out_le32((void *) &(pcip->pmm[0].ma), 0x00000000); + /* PLB starting addr, PCI: 0x80000000 */ + out_le32((void *) &(pcip->pmm[0].la), 0x80000000); + /* PCI start addr, 0x80000000 */ + out_le32((void *) &(pcip->pmm[0].pcila), PPC405_PCI_MEM_BASE); + /* 512MB range of PLB to PCI */ + out_le32((void *) &(pcip->pmm[0].pciha), 0x00000000); + /* Enable no pre-fetch, enable region */ + out_le32((void *) &(pcip->pmm[0].ma), ((0xffffffff - + (PPC405_PCI_UPPER_MEM - + PPC405_PCI_MEM_BASE)) | 0x01)); + + /* Disable region one */ + out_le32((void *) &(pcip->pmm[1].ma), 0x00000000); + out_le32((void *) &(pcip->pmm[1].la), 0x00000000); + out_le32((void *) &(pcip->pmm[1].pcila), 0x00000000); + out_le32((void *) &(pcip->pmm[1].pciha), 0x00000000); + out_le32((void *) &(pcip->pmm[1].ma), 0x00000000); + out_le32((void *) &(pcip->ptm1ms), 0x00000001); + + /* Disable region two */ + out_le32((void *) &(pcip->pmm[2].ma), 0x00000000); + out_le32((void *) &(pcip->pmm[2].la), 0x00000000); + out_le32((void *) &(pcip->pmm[2].pcila), 0x00000000); + out_le32((void *) &(pcip->pmm[2].pciha), 0x00000000); + out_le32((void *) &(pcip->pmm[2].ma), 0x00000000); + out_le32((void *) &(pcip->ptm2ms), 0x00000000); + out_le32((void *) &(pcip->ptm2la), 0x00000000); + + /* Zero config bars */ + for (bar = PCI_BASE_ADDRESS_1; bar <= PCI_BASE_ADDRESS_2; bar += 4) { + early_write_config_dword(hose, hose->first_busno, + PCI_FUNC(hose->first_busno), bar, + 0x00000000); + early_read_config_dword(hose, hose->first_busno, + PCI_FUNC(hose->first_busno), bar, + &bar_response); + } } void __init cpci405_map_io(void) { ppc4xx_map_io(); + +#ifdef CONFIG_GEN_RTC cpci405_nvram = ioremap(CPCI405_NVRAM_PADDR, CPCI405_NVRAM_SIZE); +#endif } void __init @@ -74,9 +189,11 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5, ppc_md.setup_arch = cpci405_setup_arch; ppc_md.setup_io_mappings = cpci405_map_io; +#ifdef CONFIG_GEN_RTC ppc_md.time_init = todc_time_init; ppc_md.set_rtc_time = todc_set_rtc_time; ppc_md.get_rtc_time = todc_get_rtc_time; ppc_md.nvram_read_val = todc_direct_read_val; ppc_md.nvram_write_val = todc_direct_write_val; +#endif } diff --git a/arch/ppc/platforms/4xx/cpci405.h b/arch/ppc/platforms/4xx/cpci405.h index e27f7cb650d..f5a5c0cd062 100644 --- a/arch/ppc/platforms/4xx/cpci405.h +++ b/arch/ppc/platforms/4xx/cpci405.h @@ -1,37 +1,29 @@ /* * CPCI-405 board specific definitions * - * Copyright (c) 2001 Stefan Roese (stefan.roese@esd-electronics.com) + * Copyright 2001-2006 esd electronic system design - hannover germany + * + * Authors: Matthias Fuchs + * matthias.fuchs@esd-electronics.com + * Stefan Roese + * stefan.roese@esd-electronics.com */ #ifdef __KERNEL__ -#ifndef __ASM_CPCI405_H__ -#define __ASM_CPCI405_H__ +#ifndef __CPCI405_H__ +#define __CPCI405_H__ #include - -/* We have a 405GP core */ #include - #include -#ifndef __ASSEMBLY__ -/* Some 4xx parts use a different timebase frequency from the internal clock. -*/ -#define bi_tbfreq bi_intfreq - /* Map for the NVRAM space */ #define CPCI405_NVRAM_PADDR ((uint)0xf0200000) #define CPCI405_NVRAM_SIZE ((uint)32*1024) -#ifdef CONFIG_PPC405GP_INTERNAL_CLOCK -#define BASE_BAUD 201600 -#else -#define BASE_BAUD 691200 -#endif +#define BASE_BAUD 0 -#define PPC4xx_MACHINE_NAME "esd CPCI-405" +#define PPC4xx_MACHINE_NAME "esd CPCI-405" -#endif /* !__ASSEMBLY__ */ -#endif /* __ASM_CPCI405_H__ */ +#endif /* __CPCI405_H__ */ #endif /* __KERNEL__ */ -- cgit v1.2.3 From 74f4903363579d3336c294ebb11f02c8f35845ca Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Tue, 30 May 2006 11:55:42 -0500 Subject: [PATCH] wireless: Changes to ieee80211.h for user space regulatory daemon Attached are two small patches for include/net/ieee80211.h to prepare for later submission of code to implement a user-space daemon that supplies 802.11 regulatory information. The first change adds a bit indicating that 802.11h rules are to be applied to a channel. As discussed earlier in this list, a single bit is unlikely to be sufficient; however, at this time I have been unable to find any regulations implementing differences between 802.11a and 802.11h other than DFS, radar detection and passive scanning. A single bit is thus sufficient to convey to the driver that these rules should be obeyed. The second change adds comments to the freq and max_power fields of struct ieee80211_channel to indicate the units that are used. Signed-Off-By: Larry Finger Signed-off-by: John W. Linville --- include/net/ieee80211.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h index d5147770ad4..ecc42864b00 100644 --- a/include/net/ieee80211.h +++ b/include/net/ieee80211.h @@ -968,6 +968,7 @@ enum ieee80211_state { enum { IEEE80211_CH_PASSIVE_ONLY = (1 << 0), + IEEE80211_CH_80211H_RULES = (1 << 1), IEEE80211_CH_B_ONLY = (1 << 2), IEEE80211_CH_NO_IBSS = (1 << 3), IEEE80211_CH_UNIFORM_SPREADING = (1 << 4), @@ -976,10 +977,10 @@ enum { }; struct ieee80211_channel { - u32 freq; + u32 freq; /* in MHz */ u8 channel; u8 flags; - u8 max_power; + u8 max_power; /* in dBm */ }; struct ieee80211_geo { -- cgit v1.2.3 From 78ff56a06edc3407996173daf63e48f6b90c7062 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Mon, 5 Jun 2006 20:24:10 +0200 Subject: [PATCH] bcm43xx: redesign locking Redesign the bcm43xx locking. This is pre-work to get a preemptible periodic work handler. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx.h | 100 ++++++++++++++-------- drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c | 33 ++++---- drivers/net/wireless/bcm43xx/bcm43xx_leds.c | 4 +- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 113 ++++++++++++------------- drivers/net/wireless/bcm43xx/bcm43xx_phy.c | 2 +- drivers/net/wireless/bcm43xx/bcm43xx_pio.c | 5 +- drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c | 38 ++++----- drivers/net/wireless/bcm43xx/bcm43xx_wx.c | 107 ++++++++++++----------- 8 files changed, 211 insertions(+), 191 deletions(-) diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index e66fdb1f3cf..d8f917c21ea 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -636,6 +636,17 @@ struct bcm43xx_key { u8 algorithm; }; +/* Driver initialization status. */ +enum { + BCM43xx_STAT_UNINIT, /* Uninitialized. */ + BCM43xx_STAT_INITIALIZING, /* init_board() in progress. */ + BCM43xx_STAT_INITIALIZED, /* Fully operational. */ + BCM43xx_STAT_SHUTTINGDOWN, /* free_board() in progress. */ + BCM43xx_STAT_RESTARTING, /* controller_restart() called. */ +}; +#define bcm43xx_status(bcm) atomic_read(&(bcm)->init_status) +#define bcm43xx_set_status(bcm, stat) atomic_set(&(bcm)->init_status, (stat)) + struct bcm43xx_private { struct ieee80211_device *ieee; struct ieee80211softmac_device *softmac; @@ -646,18 +657,17 @@ struct bcm43xx_private { void __iomem *mmio_addr; - /* Do not use the lock directly. Use the bcm43xx_lock* helper - * functions, to be MMIO-safe. */ - spinlock_t _lock; + /* Locking, see "theory of locking" text below. */ + spinlock_t irq_lock; + struct mutex mutex; - /* Driver status flags. */ - u32 initialized:1, /* init_board() succeed */ - was_initialized:1, /* for PCI suspend/resume. */ - shutting_down:1, /* free_board() in progress */ + /* Driver initialization status BCM43xx_STAT_*** */ + atomic_t init_status; + + u16 was_initialized:1, /* for PCI suspend/resume. */ __using_pio:1, /* Internal, use bcm43xx_using_pio(). */ bad_frames_preempt:1, /* Use "Bad Frames Preemption" (default off) */ reg124_set_0x4:1, /* Some variable to keep track of IRQ stuff. */ - powersaving:1, /* TRUE if we are in PowerSaving mode. FALSE otherwise. */ short_preamble:1, /* TRUE, if short preamble is enabled. */ firmware_norelease:1; /* Do not release the firmware. Used on suspend. */ @@ -721,7 +731,7 @@ struct bcm43xx_private { struct tasklet_struct isr_tasklet; /* Periodic tasks */ - struct timer_list periodic_tasks; + struct work_struct periodic_work; unsigned int periodic_state; struct work_struct restart_work; @@ -746,21 +756,55 @@ struct bcm43xx_private { #endif }; -/* bcm43xx_(un)lock() protect struct bcm43xx_private. - * Note that _NO_ MMIO writes are allowed. If you want to - * write to the device through MMIO in the critical section, use - * the *_mmio lock functions. - * MMIO read-access is allowed, though. - */ -#define bcm43xx_lock(bcm, flags) spin_lock_irqsave(&(bcm)->_lock, flags) -#define bcm43xx_unlock(bcm, flags) spin_unlock_irqrestore(&(bcm)->_lock, flags) -/* bcm43xx_(un)lock_mmio() protect struct bcm43xx_private and MMIO. - * MMIO write-access to the device is allowed. - * All MMIO writes are flushed on unlock, so it is guaranteed to not - * interfere with other threads writing MMIO registers. + +/* *** THEORY OF LOCKING *** + * + * We have two different locks in the bcm43xx driver. + * => bcm->mutex: General sleeping mutex. Protects struct bcm43xx_private + * and the device registers. + * => bcm->irq_lock: IRQ spinlock. Protects against IRQ handler concurrency. + * + * We have three types of helper function pairs to utilize these locks. + * (Always use the helper functions.) + * 1) bcm43xx_{un}lock_noirq(): + * Takes bcm->mutex. Does _not_ protect against IRQ concurrency, + * so it is almost always unsafe, if device IRQs are enabled. + * So only use this, if device IRQs are masked. + * Locking may sleep. + * You can sleep within the critical section. + * 2) bcm43xx_{un}lock_irqonly(): + * Takes bcm->irq_lock. Does _not_ protect against + * bcm43xx_lock_noirq() critical sections. + * Does only protect against the IRQ handler path and other + * irqonly() critical sections. + * Locking does not sleep. + * You must not sleep within the critical section. + * 3) bcm43xx_{un}lock_irqsafe(): + * This is the cummulative lock and takes both, mutex and irq_lock. + * Protects against noirq() and irqonly() critical sections (and + * the IRQ handler path). + * Locking may sleep. + * You must not sleep within the critical section. */ -#define bcm43xx_lock_mmio(bcm, flags) bcm43xx_lock(bcm, flags) -#define bcm43xx_unlock_mmio(bcm, flags) do { mmiowb(); bcm43xx_unlock(bcm, flags); } while (0) + +/* Lock type 1 */ +#define bcm43xx_lock_noirq(bcm) mutex_lock(&(bcm)->mutex) +#define bcm43xx_unlock_noirq(bcm) mutex_unlock(&(bcm)->mutex) +/* Lock type 2 */ +#define bcm43xx_lock_irqonly(bcm, flags) \ + spin_lock_irqsave(&(bcm)->irq_lock, flags) +#define bcm43xx_unlock_irqonly(bcm, flags) \ + spin_unlock_irqrestore(&(bcm)->irq_lock, flags) +/* Lock type 3 */ +#define bcm43xx_lock_irqsafe(bcm, flags) do { \ + bcm43xx_lock_noirq(bcm); \ + bcm43xx_lock_irqonly(bcm, flags); \ + } while (0) +#define bcm43xx_unlock_irqsafe(bcm, flags) do { \ + bcm43xx_unlock_irqonly(bcm, flags); \ + bcm43xx_unlock_noirq(bcm); \ + } while (0) + static inline struct bcm43xx_private * bcm43xx_priv(struct net_device *dev) @@ -843,16 +887,6 @@ struct bcm43xx_radioinfo * bcm43xx_current_radio(struct bcm43xx_private *bcm) return &(bcm->core_80211_ext[bcm->current_80211_core_idx].radio); } -/* Are we running in init_board() context? */ -static inline -int bcm43xx_is_initializing(struct bcm43xx_private *bcm) -{ - if (bcm->initialized) - return 0; - if (bcm->shutting_down) - return 0; - return 1; -} static inline struct bcm43xx_lopair * bcm43xx_get_lopair(struct bcm43xx_phyinfo *phy, diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c index 7497fb16076..ce2e40b29b4 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c @@ -77,8 +77,8 @@ static ssize_t devinfo_read_file(struct file *file, char __user *userbuf, down(&big_buffer_sem); - bcm43xx_lock_mmio(bcm, flags); - if (!bcm->initialized) { + bcm43xx_lock_irqsafe(bcm, flags); + if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { fappend("Board not initialized.\n"); goto out; } @@ -121,7 +121,7 @@ static ssize_t devinfo_read_file(struct file *file, char __user *userbuf, fappend("\n"); out: - bcm43xx_unlock_mmio(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); up(&big_buffer_sem); return res; @@ -159,8 +159,8 @@ static ssize_t spromdump_read_file(struct file *file, char __user *userbuf, unsigned long flags; down(&big_buffer_sem); - bcm43xx_lock_mmio(bcm, flags); - if (!bcm->initialized) { + bcm43xx_lock_irqsafe(bcm, flags); + if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { fappend("Board not initialized.\n"); goto out; } @@ -169,7 +169,7 @@ static ssize_t spromdump_read_file(struct file *file, char __user *userbuf, fappend("boardflags: 0x%04x\n", bcm->sprom.boardflags); out: - bcm43xx_unlock_mmio(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); up(&big_buffer_sem); return res; @@ -188,8 +188,8 @@ static ssize_t tsf_read_file(struct file *file, char __user *userbuf, u64 tsf; down(&big_buffer_sem); - bcm43xx_lock_mmio(bcm, flags); - if (!bcm->initialized) { + bcm43xx_lock_irqsafe(bcm, flags); + if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { fappend("Board not initialized.\n"); goto out; } @@ -199,7 +199,7 @@ static ssize_t tsf_read_file(struct file *file, char __user *userbuf, (unsigned int)(tsf & 0xFFFFFFFFULL)); out: - bcm43xx_unlock_mmio(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); up(&big_buffer_sem); return res; @@ -221,8 +221,8 @@ static ssize_t tsf_write_file(struct file *file, const char __user *user_buf, res = -EFAULT; goto out_up; } - bcm43xx_lock_mmio(bcm, flags); - if (!bcm->initialized) { + bcm43xx_lock_irqsafe(bcm, flags); + if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { printk(KERN_INFO PFX "debugfs: Board not initialized.\n"); res = -EFAULT; goto out_unlock; @@ -233,10 +233,11 @@ static ssize_t tsf_write_file(struct file *file, const char __user *user_buf, goto out_unlock; } bcm43xx_tsf_write(bcm, tsf); + mmiowb(); res = buf_size; out_unlock: - bcm43xx_unlock_mmio(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); out_up: up(&big_buffer_sem); return res; @@ -257,7 +258,7 @@ static ssize_t txstat_read_file(struct file *file, char __user *userbuf, int i, cnt, j = 0; down(&big_buffer_sem); - bcm43xx_lock(bcm, flags); + bcm43xx_lock_irqsafe(bcm, flags); fappend("Last %d logged xmitstatus blobs (Latest first):\n\n", BCM43xx_NR_LOGGED_XMITSTATUS); @@ -293,14 +294,14 @@ static ssize_t txstat_read_file(struct file *file, char __user *userbuf, i = BCM43xx_NR_LOGGED_XMITSTATUS - 1; } - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); - bcm43xx_lock(bcm, flags); + bcm43xx_lock_irqsafe(bcm, flags); if (*ppos == pos) { /* Done. Drop the copied data. */ e->xmitstatus_printing = 0; } - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); up(&big_buffer_sem); return res; } diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c index 4b2c02c0b31..ec80692d638 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c @@ -51,12 +51,12 @@ static void bcm43xx_led_blink(unsigned long d) struct bcm43xx_private *bcm = led->bcm; unsigned long flags; - bcm43xx_lock_mmio(bcm, flags); + bcm43xx_lock_irqonly(bcm, flags); if (led->blink_interval) { bcm43xx_led_changestate(led); mod_timer(&led->blink_timer, jiffies + led->blink_interval); } - bcm43xx_unlock_mmio(bcm, flags); + bcm43xx_unlock_irqonly(bcm, flags); } static void bcm43xx_led_blink_start(struct bcm43xx_led *led, diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 736dde96c4a..835a2df1fe3 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -504,14 +504,14 @@ static int bcm43xx_disable_interrupts_sync(struct bcm43xx_private *bcm, u32 *old u32 old; unsigned long flags; - bcm43xx_lock_mmio(bcm, flags); - if (bcm43xx_is_initializing(bcm) || bcm->shutting_down) { - bcm43xx_unlock_mmio(bcm, flags); + bcm43xx_lock_irqonly(bcm, flags); + if (unlikely(bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)) { + bcm43xx_unlock_irqonly(bcm, flags); return -EBUSY; } old = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); tasklet_disable(&bcm->isr_tasklet); - bcm43xx_unlock_mmio(bcm, flags); + bcm43xx_unlock_irqonly(bcm, flags); if (oldstate) *oldstate = old; @@ -1389,7 +1389,7 @@ void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy) bcm43xx_dmacontroller_rx_reset(bcm, BCM43xx_MMIO_DMA4_BASE); #endif } - if (bcm->shutting_down) { + if (bcm43xx_status(bcm) == BCM43xx_STAT_SHUTTINGDOWN) { bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) & ~(BCM43xx_SBF_MAC_ENABLED | 0x00000002)); @@ -1709,7 +1709,7 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) # define bcmirq_handled(irq) do { /* nothing */ } while (0) #endif /* CONFIG_BCM43XX_DEBUG*/ - bcm43xx_lock_mmio(bcm, flags); + bcm43xx_lock_irqonly(bcm, flags); reason = bcm->irq_reason; dma_reason[0] = bcm->dma_reason[0]; dma_reason[1] = bcm->dma_reason[1]; @@ -1734,7 +1734,8 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) dma_reason[0], dma_reason[1], dma_reason[2], dma_reason[3]); bcm43xx_controller_restart(bcm, "DMA error"); - bcm43xx_unlock_mmio(bcm, flags); + mmiowb(); + bcm43xx_unlock_irqonly(bcm, flags); return; } if (unlikely((dma_reason[0] & BCM43xx_DMAIRQ_NONFATALMASK) | @@ -1821,7 +1822,8 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) if (!modparam_noleds) bcm43xx_leds_update(bcm, activity); bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate); - bcm43xx_unlock_mmio(bcm, flags); + mmiowb(); + bcm43xx_unlock_irqonly(bcm, flags); } static void pio_irq_workaround(struct bcm43xx_private *bcm, @@ -1870,7 +1872,7 @@ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_re if (!bcm) return IRQ_NONE; - spin_lock(&bcm->_lock); + spin_lock(&bcm->irq_lock); reason = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); if (reason == 0xffffffff) { @@ -1899,7 +1901,7 @@ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_re * completely, but some careful work is needed to fix this. I think it * is best to stay with this cheap workaround for now... . */ - if (likely(bcm->initialized)) { + if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)) { /* disable all IRQs. They are enabled again in the bottom half. */ bcm->irq_savedstate = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); /* save the reason code and call our bottom half. */ @@ -1909,7 +1911,7 @@ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_re out: mmiowb(); - spin_unlock(&bcm->_lock); + spin_unlock(&bcm->irq_lock); return ret; } @@ -3106,15 +3108,14 @@ static void bcm43xx_periodic_every15sec(struct bcm43xx_private *bcm) //TODO for APHY (temperature?) } -static void bcm43xx_periodic_task_handler(unsigned long d) +static void bcm43xx_periodic_work_handler(void *d) { - struct bcm43xx_private *bcm = (struct bcm43xx_private *)d; + struct bcm43xx_private *bcm = d; unsigned long flags; unsigned int state; - bcm43xx_lock_mmio(bcm, flags); + bcm43xx_lock_irqsafe(bcm, flags); - assert(bcm->initialized); state = bcm->periodic_state; if (state % 8 == 0) bcm43xx_periodic_every120sec(bcm); @@ -3125,26 +3126,24 @@ static void bcm43xx_periodic_task_handler(unsigned long d) bcm43xx_periodic_every15sec(bcm); bcm->periodic_state = state + 1; - mod_timer(&bcm->periodic_tasks, jiffies + (HZ * 15)); + schedule_delayed_work(&bcm->periodic_work, HZ * 15); - bcm43xx_unlock_mmio(bcm, flags); + mmiowb(); + bcm43xx_unlock_irqsafe(bcm, flags); } static void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm) { - del_timer_sync(&bcm->periodic_tasks); + cancel_rearming_delayed_work(&bcm->periodic_work); } static void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm) { - struct timer_list *timer = &(bcm->periodic_tasks); + struct work_struct *work = &(bcm->periodic_work); - assert(bcm->initialized); - setup_timer(timer, - bcm43xx_periodic_task_handler, - (unsigned long)bcm); - timer->expires = jiffies; - add_timer(timer); + assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED); + INIT_WORK(work, bcm43xx_periodic_work_handler, bcm); + schedule_work(work); } static void bcm43xx_security_init(struct bcm43xx_private *bcm) @@ -3158,16 +3157,12 @@ static void bcm43xx_security_init(struct bcm43xx_private *bcm) static void bcm43xx_free_board(struct bcm43xx_private *bcm) { int i, err; - unsigned long flags; + bcm43xx_lock_noirq(bcm); bcm43xx_sysfs_unregister(bcm); - bcm43xx_periodic_tasks_delete(bcm); - bcm43xx_lock(bcm, flags); - bcm->initialized = 0; - bcm->shutting_down = 1; - bcm43xx_unlock(bcm, flags); + bcm43xx_set_status(bcm, BCM43xx_STAT_SHUTTINGDOWN); for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { if (!bcm->core_80211[i].available) @@ -3182,23 +3177,19 @@ static void bcm43xx_free_board(struct bcm43xx_private *bcm) bcm43xx_pctl_set_crystal(bcm, 0); - bcm43xx_lock(bcm, flags); - bcm->shutting_down = 0; - bcm43xx_unlock(bcm, flags); + bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT); + bcm43xx_unlock_noirq(bcm); } static int bcm43xx_init_board(struct bcm43xx_private *bcm) { int i, err; int connect_phy; - unsigned long flags; might_sleep(); - bcm43xx_lock(bcm, flags); - bcm->initialized = 0; - bcm->shutting_down = 0; - bcm43xx_unlock(bcm, flags); + bcm43xx_lock_noirq(bcm); + bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZING); err = bcm43xx_pctl_set_crystal(bcm, 1); if (err) @@ -3265,9 +3256,7 @@ static int bcm43xx_init_board(struct bcm43xx_private *bcm) } /* Initialization of the board is done. Flag it as such. */ - bcm43xx_lock(bcm, flags); - bcm->initialized = 1; - bcm43xx_unlock(bcm, flags); + bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZED); bcm43xx_periodic_tasks_setup(bcm); bcm43xx_sysfs_register(bcm); @@ -3278,6 +3267,8 @@ static int bcm43xx_init_board(struct bcm43xx_private *bcm) assert(err == 0); out: + bcm43xx_unlock_noirq(bcm); + return err; err_80211_unwind: @@ -3534,8 +3525,8 @@ static void bcm43xx_ieee80211_set_chan(struct net_device *net_dev, struct bcm43xx_radioinfo *radio; unsigned long flags; - bcm43xx_lock_mmio(bcm, flags); - if (bcm->initialized) { + bcm43xx_lock_irqsafe(bcm, flags); + if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { bcm43xx_mac_suspend(bcm); bcm43xx_radio_selectchannel(bcm, channel, 0); bcm43xx_mac_enable(bcm); @@ -3543,7 +3534,7 @@ static void bcm43xx_ieee80211_set_chan(struct net_device *net_dev, radio = bcm43xx_current_radio(bcm); radio->initial_channel = channel; } - bcm43xx_unlock_mmio(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); } /* set_security() callback in struct ieee80211_device */ @@ -3557,7 +3548,7 @@ static void bcm43xx_ieee80211_set_security(struct net_device *net_dev, dprintk(KERN_INFO PFX "set security called"); - bcm43xx_lock_mmio(bcm, flags); + bcm43xx_lock_irqsafe(bcm, flags); for (keyidx = 0; keyidxflags & (1<encrypt); } dprintk("\n"); - if (bcm->initialized && !bcm->ieee->host_encrypt) { + if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED && + !bcm->ieee->host_encrypt) { if (secinfo->enabled) { /* upload WEP keys to hardware */ char null_address[6] = { 0 }; @@ -3621,7 +3613,7 @@ static void bcm43xx_ieee80211_set_security(struct net_device *net_dev, } else bcm43xx_clear_keys(bcm); } - bcm43xx_unlock_mmio(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); } /* hard_start_xmit() callback in struct ieee80211_device */ @@ -3633,10 +3625,10 @@ static int bcm43xx_ieee80211_hard_start_xmit(struct ieee80211_txb *txb, int err = -ENODEV; unsigned long flags; - bcm43xx_lock_mmio(bcm, flags); - if (likely(bcm->initialized)) + bcm43xx_lock_irqonly(bcm, flags); + if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)) err = bcm43xx_tx(bcm, txb); - bcm43xx_unlock_mmio(bcm, flags); + bcm43xx_unlock_irqonly(bcm, flags); return err; } @@ -3651,9 +3643,9 @@ static void bcm43xx_net_tx_timeout(struct net_device *net_dev) struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); unsigned long flags; - bcm43xx_lock_mmio(bcm, flags); + bcm43xx_lock_irqonly(bcm, flags); bcm43xx_controller_restart(bcm, "TX timeout"); - bcm43xx_unlock_mmio(bcm, flags); + bcm43xx_unlock_irqonly(bcm, flags); } #ifdef CONFIG_NET_POLL_CONTROLLER @@ -3692,6 +3684,7 @@ static int bcm43xx_init_private(struct bcm43xx_private *bcm, { int err; + bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT); bcm->ieee = netdev_priv(net_dev); bcm->softmac = ieee80211_priv(net_dev); bcm->softmac->set_channel = bcm43xx_ieee80211_set_chan; @@ -3700,7 +3693,8 @@ static int bcm43xx_init_private(struct bcm43xx_private *bcm, bcm->pci_dev = pci_dev; bcm->net_dev = net_dev; bcm->bad_frames_preempt = modparam_bad_frames_preempt; - spin_lock_init(&bcm->_lock); + spin_lock_init(&bcm->irq_lock); + mutex_init(&bcm->mutex); tasklet_init(&bcm->isr_tasklet, (void (*)(unsigned long))bcm43xx_interrupt_tasklet, (unsigned long)bcm); @@ -3831,7 +3825,7 @@ static void bcm43xx_chip_reset(void *_bcm) struct net_device *net_dev = bcm->net_dev; struct pci_dev *pci_dev = bcm->pci_dev; int err; - int was_initialized = bcm->initialized; + int was_initialized = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED); netif_stop_queue(bcm->net_dev); tasklet_disable(&bcm->isr_tasklet); @@ -3866,6 +3860,7 @@ failure: */ void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason) { + bcm43xx_set_status(bcm, BCM43xx_STAT_RESTARTING); bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */ printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason); @@ -3884,11 +3879,11 @@ static int bcm43xx_suspend(struct pci_dev *pdev, pm_message_t state) dprintk(KERN_INFO PFX "Suspending...\n"); - bcm43xx_lock(bcm, flags); - bcm->was_initialized = bcm->initialized; - if (bcm->initialized) + bcm43xx_lock_irqsafe(bcm, flags); + bcm->was_initialized = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED); + if (bcm->was_initialized) try_to_shutdown = 1; - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); netif_device_detach(net_dev); if (try_to_shutdown) { diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c index b0abac51553..952c2f8b8b5 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c @@ -1648,7 +1648,7 @@ void bcm43xx_phy_set_baseband_attenuation(struct bcm43xx_private *bcm, void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm) { static const u8 pairorder[10] = { 3, 1, 5, 7, 9, 2, 0, 4, 6, 8 }; - const int is_initializing = bcm43xx_is_initializing(bcm); + const int is_initializing = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZING); struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u16 h, i, oldi = 0, j; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c index 0aa1bd269a2..e77e9d859f8 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c @@ -262,7 +262,7 @@ static void tx_tasklet(unsigned long d) int err; u16 txctl; - bcm43xx_lock_mmio(bcm, flags); + bcm43xx_lock_irqonly(bcm, flags); txctl = bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL); if (txctl & BCM43xx_PIO_TXCTL_SUSPEND) @@ -298,7 +298,7 @@ static void tx_tasklet(unsigned long d) continue; } out_unlock: - bcm43xx_unlock_mmio(bcm, flags); + bcm43xx_unlock_irqonly(bcm, flags); } static void setup_txqueues(struct bcm43xx_pioqueue *queue) @@ -374,7 +374,6 @@ static void cancel_transfers(struct bcm43xx_pioqueue *queue) struct bcm43xx_pio_txpacket *packet, *tmp_packet; netif_tx_disable(queue->bcm->net_dev); - assert(queue->bcm->shutting_down); tasklet_disable(&queue->txtask); list_for_each_entry_safe(packet, tmp_packet, &queue->txrunning, list) diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c index b438f48e891..6a23bdc7541 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c @@ -120,12 +120,12 @@ static ssize_t bcm43xx_attr_sprom_show(struct device *dev, GFP_KERNEL); if (!sprom) return -ENOMEM; - bcm43xx_lock_mmio(bcm, flags); - assert(bcm->initialized); + bcm43xx_lock_irqsafe(bcm, flags); err = bcm43xx_sprom_read(bcm, sprom); if (!err) err = sprom2hex(sprom, buf, PAGE_SIZE); - bcm43xx_unlock_mmio(bcm, flags); + mmiowb(); + bcm43xx_unlock_irqsafe(bcm, flags); kfree(sprom); return err; @@ -150,10 +150,10 @@ static ssize_t bcm43xx_attr_sprom_store(struct device *dev, err = hex2sprom(sprom, buf, count); if (err) goto out_kfree; - bcm43xx_lock_mmio(bcm, flags); - assert(bcm->initialized); + bcm43xx_lock_irqsafe(bcm, flags); err = bcm43xx_sprom_write(bcm, sprom); - bcm43xx_unlock_mmio(bcm, flags); + mmiowb(); + bcm43xx_unlock_irqsafe(bcm, flags); out_kfree: kfree(sprom); @@ -170,15 +170,13 @@ static ssize_t bcm43xx_attr_interfmode_show(struct device *dev, char *buf) { struct bcm43xx_private *bcm = dev_to_bcm(dev); - unsigned long flags; int err; ssize_t count = 0; if (!capable(CAP_NET_ADMIN)) return -EPERM; - bcm43xx_lock(bcm, flags); - assert(bcm->initialized); + bcm43xx_lock_noirq(bcm); switch (bcm43xx_current_radio(bcm)->interfmode) { case BCM43xx_RADIO_INTERFMODE_NONE: @@ -195,7 +193,7 @@ static ssize_t bcm43xx_attr_interfmode_show(struct device *dev, } err = 0; - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_noirq(bcm); return err ? err : count; @@ -231,16 +229,15 @@ static ssize_t bcm43xx_attr_interfmode_store(struct device *dev, return -EINVAL; } - bcm43xx_lock_mmio(bcm, flags); - assert(bcm->initialized); + bcm43xx_lock_irqsafe(bcm, flags); err = bcm43xx_radio_set_interference_mitigation(bcm, mode); if (err) { printk(KERN_ERR PFX "Interference Mitigation not " "supported by device\n"); } - - bcm43xx_unlock_mmio(bcm, flags); + mmiowb(); + bcm43xx_unlock_irqsafe(bcm, flags); return err ? err : count; } @@ -254,15 +251,13 @@ static ssize_t bcm43xx_attr_preamble_show(struct device *dev, char *buf) { struct bcm43xx_private *bcm = dev_to_bcm(dev); - unsigned long flags; int err; ssize_t count; if (!capable(CAP_NET_ADMIN)) return -EPERM; - bcm43xx_lock(bcm, flags); - assert(bcm->initialized); + bcm43xx_lock_noirq(bcm); if (bcm->short_preamble) count = snprintf(buf, PAGE_SIZE, "1 (Short Preamble enabled)\n"); @@ -270,7 +265,7 @@ static ssize_t bcm43xx_attr_preamble_show(struct device *dev, count = snprintf(buf, PAGE_SIZE, "0 (Short Preamble disabled)\n"); err = 0; - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_noirq(bcm); return err ? err : count; } @@ -290,13 +285,12 @@ static ssize_t bcm43xx_attr_preamble_store(struct device *dev, value = get_boolean(buf, count); if (value < 0) return value; - bcm43xx_lock(bcm, flags); - assert(bcm->initialized); + bcm43xx_lock_irqsafe(bcm, flags); bcm->short_preamble = !!value; err = 0; - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); return err ? err : count; } @@ -310,7 +304,7 @@ int bcm43xx_sysfs_register(struct bcm43xx_private *bcm) struct device *dev = &bcm->pci_dev->dev; int err; - assert(bcm->initialized); + assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED); err = device_create_file(dev, &dev_attr_sprom); if (err) diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c index b45063974ae..c35cb3a0777 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c @@ -55,13 +55,13 @@ static int bcm43xx_wx_get_name(struct net_device *net_dev, char *extra) { struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - unsigned long flags; int i; + unsigned long flags; struct bcm43xx_phyinfo *phy; char suffix[7] = { 0 }; int have_a = 0, have_b = 0, have_g = 0; - bcm43xx_lock(bcm, flags); + bcm43xx_lock_irqsafe(bcm, flags); for (i = 0; i < bcm->nr_80211_available; i++) { phy = &(bcm->core_80211_ext[i].phy); switch (phy->type) { @@ -77,7 +77,7 @@ static int bcm43xx_wx_get_name(struct net_device *net_dev, assert(0); } } - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); i = 0; if (have_a) { @@ -111,7 +111,7 @@ static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev, int freq; int err = -EINVAL; - bcm43xx_lock_mmio(bcm, flags); + bcm43xx_lock_irqsafe(bcm, flags); if ((data->freq.m >= 0) && (data->freq.m <= 1000)) { channel = data->freq.m; freq = bcm43xx_channel_to_freq(bcm, channel); @@ -121,7 +121,7 @@ static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev, } if (!bcm43xx_is_valid_channel(bcm, channel)) goto out_unlock; - if (bcm->initialized) { + if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { //ieee80211softmac_disassoc(softmac, $REASON); bcm43xx_mac_suspend(bcm); err = bcm43xx_radio_selectchannel(bcm, channel, 0); @@ -131,7 +131,7 @@ static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev, err = 0; } out_unlock: - bcm43xx_unlock_mmio(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); return err; } @@ -147,11 +147,10 @@ static int bcm43xx_wx_get_channelfreq(struct net_device *net_dev, int err = -ENODEV; u16 channel; - bcm43xx_lock(bcm, flags); + bcm43xx_lock_irqsafe(bcm, flags); radio = bcm43xx_current_radio(bcm); channel = radio->channel; if (channel == 0xFF) { - assert(!bcm->initialized); channel = radio->initial_channel; if (channel == 0xFF) goto out_unlock; @@ -163,7 +162,7 @@ static int bcm43xx_wx_get_channelfreq(struct net_device *net_dev, err = 0; out_unlock: - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); return err; } @@ -181,13 +180,13 @@ static int bcm43xx_wx_set_mode(struct net_device *net_dev, if (mode == IW_MODE_AUTO) mode = BCM43xx_INITIAL_IWMODE; - bcm43xx_lock_mmio(bcm, flags); - if (bcm->initialized) { + bcm43xx_lock_irqsafe(bcm, flags); + if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { if (bcm->ieee->iw_mode != mode) bcm43xx_set_iwmode(bcm, mode); } else bcm->ieee->iw_mode = mode; - bcm43xx_unlock_mmio(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); return 0; } @@ -200,9 +199,9 @@ static int bcm43xx_wx_get_mode(struct net_device *net_dev, struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); unsigned long flags; - bcm43xx_lock(bcm, flags); + bcm43xx_lock_irqsafe(bcm, flags); data->mode = bcm->ieee->iw_mode; - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); return 0; } @@ -255,7 +254,7 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev, IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; - bcm43xx_lock(bcm, flags); + bcm43xx_lock_irqsafe(bcm, flags); phy = bcm43xx_current_phy(bcm); range->num_bitrates = 0; @@ -302,7 +301,7 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev, } range->num_frequency = j; - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); return 0; } @@ -313,14 +312,13 @@ static int bcm43xx_wx_set_nick(struct net_device *net_dev, char *extra) { struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - unsigned long flags; size_t len; - bcm43xx_lock(bcm, flags); + bcm43xx_lock_noirq(bcm); len = min((size_t)data->data.length, (size_t)IW_ESSID_MAX_SIZE); memcpy(bcm->nick, extra, len); bcm->nick[len] = '\0'; - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_noirq(bcm); return 0; } @@ -331,15 +329,14 @@ static int bcm43xx_wx_get_nick(struct net_device *net_dev, char *extra) { struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - unsigned long flags; size_t len; - bcm43xx_lock(bcm, flags); + bcm43xx_lock_noirq(bcm); len = strlen(bcm->nick) + 1; memcpy(extra, bcm->nick, len); data->data.length = (__u16)len; data->data.flags = 1; - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_noirq(bcm); return 0; } @@ -353,7 +350,7 @@ static int bcm43xx_wx_set_rts(struct net_device *net_dev, unsigned long flags; int err = -EINVAL; - bcm43xx_lock(bcm, flags); + bcm43xx_lock_irqsafe(bcm, flags); if (data->rts.disabled) { bcm->rts_threshold = BCM43xx_MAX_RTS_THRESHOLD; err = 0; @@ -364,7 +361,7 @@ static int bcm43xx_wx_set_rts(struct net_device *net_dev, err = 0; } } - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); return err; } @@ -377,11 +374,11 @@ static int bcm43xx_wx_get_rts(struct net_device *net_dev, struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); unsigned long flags; - bcm43xx_lock(bcm, flags); + bcm43xx_lock_irqsafe(bcm, flags); data->rts.value = bcm->rts_threshold; data->rts.fixed = 0; data->rts.disabled = (bcm->rts_threshold == BCM43xx_MAX_RTS_THRESHOLD); - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); return 0; } @@ -395,7 +392,7 @@ static int bcm43xx_wx_set_frag(struct net_device *net_dev, unsigned long flags; int err = -EINVAL; - bcm43xx_lock(bcm, flags); + bcm43xx_lock_irqsafe(bcm, flags); if (data->frag.disabled) { bcm->ieee->fts = MAX_FRAG_THRESHOLD; err = 0; @@ -406,7 +403,7 @@ static int bcm43xx_wx_set_frag(struct net_device *net_dev, err = 0; } } - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); return err; } @@ -419,11 +416,11 @@ static int bcm43xx_wx_get_frag(struct net_device *net_dev, struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); unsigned long flags; - bcm43xx_lock(bcm, flags); + bcm43xx_lock_irqsafe(bcm, flags); data->frag.value = bcm->ieee->fts; data->frag.fixed = 0; data->frag.disabled = (bcm->ieee->fts == MAX_FRAG_THRESHOLD); - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); return 0; } @@ -445,8 +442,8 @@ static int bcm43xx_wx_set_xmitpower(struct net_device *net_dev, return -EOPNOTSUPP; } - bcm43xx_lock_mmio(bcm, flags); - if (!bcm->initialized) + bcm43xx_lock_irqsafe(bcm, flags); + if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) goto out_unlock; radio = bcm43xx_current_radio(bcm); phy = bcm43xx_current_phy(bcm); @@ -469,7 +466,7 @@ static int bcm43xx_wx_set_xmitpower(struct net_device *net_dev, err = 0; out_unlock: - bcm43xx_unlock_mmio(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); return err; } @@ -484,8 +481,8 @@ static int bcm43xx_wx_get_xmitpower(struct net_device *net_dev, unsigned long flags; int err = -ENODEV; - bcm43xx_lock(bcm, flags); - if (!bcm->initialized) + bcm43xx_lock_irqsafe(bcm, flags); + if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) goto out_unlock; radio = bcm43xx_current_radio(bcm); /* desired dBm value is in Q5.2 */ @@ -496,7 +493,7 @@ static int bcm43xx_wx_get_xmitpower(struct net_device *net_dev, err = 0; out_unlock: - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); return err; } @@ -583,8 +580,8 @@ static int bcm43xx_wx_set_interfmode(struct net_device *net_dev, return -EINVAL; } - bcm43xx_lock_mmio(bcm, flags); - if (bcm->initialized) { + bcm43xx_lock_irqsafe(bcm, flags); + if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { err = bcm43xx_radio_set_interference_mitigation(bcm, mode); if (err) { printk(KERN_ERR PFX "Interference Mitigation not " @@ -598,7 +595,7 @@ static int bcm43xx_wx_set_interfmode(struct net_device *net_dev, } else bcm43xx_current_radio(bcm)->interfmode = mode; } - bcm43xx_unlock_mmio(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); return err; } @@ -612,9 +609,9 @@ static int bcm43xx_wx_get_interfmode(struct net_device *net_dev, unsigned long flags; int mode; - bcm43xx_lock(bcm, flags); + bcm43xx_lock_irqsafe(bcm, flags); mode = bcm43xx_current_radio(bcm)->interfmode; - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); switch (mode) { case BCM43xx_RADIO_INTERFMODE_NONE: @@ -644,9 +641,9 @@ static int bcm43xx_wx_set_shortpreamble(struct net_device *net_dev, int on; on = *((int *)extra); - bcm43xx_lock(bcm, flags); + bcm43xx_lock_irqsafe(bcm, flags); bcm->short_preamble = !!on; - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); return 0; } @@ -660,9 +657,9 @@ static int bcm43xx_wx_get_shortpreamble(struct net_device *net_dev, unsigned long flags; int on; - bcm43xx_lock(bcm, flags); + bcm43xx_lock_irqsafe(bcm, flags); on = bcm->short_preamble; - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); if (on) strncpy(extra, "1 (Short Preamble enabled)", MAX_WX_STRING); @@ -684,11 +681,11 @@ static int bcm43xx_wx_set_swencryption(struct net_device *net_dev, on = *((int *)extra); - bcm43xx_lock(bcm, flags); + bcm43xx_lock_irqsafe(bcm, flags); bcm->ieee->host_encrypt = !!on; bcm->ieee->host_decrypt = !!on; bcm->ieee->host_build_iv = !on; - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); return 0; } @@ -702,9 +699,9 @@ static int bcm43xx_wx_get_swencryption(struct net_device *net_dev, unsigned long flags; int on; - bcm43xx_lock(bcm, flags); + bcm43xx_lock_irqsafe(bcm, flags); on = bcm->ieee->host_encrypt; - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); if (on) strncpy(extra, "1 (SW encryption enabled) ", MAX_WX_STRING); @@ -767,11 +764,11 @@ static int bcm43xx_wx_sprom_read(struct net_device *net_dev, if (!sprom) goto out; - bcm43xx_lock_mmio(bcm, flags); + bcm43xx_lock_irqsafe(bcm, flags); err = -ENODEV; - if (bcm->initialized) + if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) err = bcm43xx_sprom_read(bcm, sprom); - bcm43xx_unlock_mmio(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); if (!err) data->data.length = sprom2hex(sprom, extra); kfree(sprom); @@ -812,11 +809,11 @@ static int bcm43xx_wx_sprom_write(struct net_device *net_dev, if (err) goto out_kfree; - bcm43xx_lock_mmio(bcm, flags); + bcm43xx_lock_irqsafe(bcm, flags); err = -ENODEV; - if (bcm->initialized) + if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) err = bcm43xx_sprom_write(bcm, sprom); - bcm43xx_unlock_mmio(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); out_kfree: kfree(sprom); out: -- cgit v1.2.3 From 91769e7dd9cef7988dc4280f74ed168351beb5b8 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Mon, 5 Jun 2006 20:24:21 +0200 Subject: [PATCH] bcm43xx: preemptible periodic work Make the heavy periodic work preemptible to avoid disabling local IRQs for several msecs. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 97 +++++++++++++++++++++++++---- drivers/net/wireless/bcm43xx/bcm43xx_phy.c | 7 ++- drivers/net/wireless/bcm43xx/bcm43xx_pio.c | 39 +++++++++++- drivers/net/wireless/bcm43xx/bcm43xx_pio.h | 13 ++++ 4 files changed, 143 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 835a2df1fe3..77d0e390b02 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -498,11 +498,21 @@ static inline u32 bcm43xx_interrupt_disable(struct bcm43xx_private *bcm, u32 mas return old_mask; } +/* Synchronize IRQ top- and bottom-half. + * IRQs must be masked before calling this. + * This must not be called with the irq_lock held. + */ +static void bcm43xx_synchronize_irq(struct bcm43xx_private *bcm) +{ + synchronize_irq(bcm->irq); + tasklet_disable(&bcm->isr_tasklet); +} + /* Make sure we don't receive more data from the device. */ static int bcm43xx_disable_interrupts_sync(struct bcm43xx_private *bcm, u32 *oldstate) { - u32 old; unsigned long flags; + u32 old; bcm43xx_lock_irqonly(bcm, flags); if (unlikely(bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)) { @@ -510,8 +520,9 @@ static int bcm43xx_disable_interrupts_sync(struct bcm43xx_private *bcm, u32 *old return -EBUSY; } old = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); - tasklet_disable(&bcm->isr_tasklet); bcm43xx_unlock_irqonly(bcm, flags); + bcm43xx_synchronize_irq(bcm); + if (oldstate) *oldstate = old; @@ -3108,14 +3119,10 @@ static void bcm43xx_periodic_every15sec(struct bcm43xx_private *bcm) //TODO for APHY (temperature?) } -static void bcm43xx_periodic_work_handler(void *d) +static void do_periodic_work(struct bcm43xx_private *bcm) { - struct bcm43xx_private *bcm = d; - unsigned long flags; unsigned int state; - bcm43xx_lock_irqsafe(bcm, flags); - state = bcm->periodic_state; if (state % 8 == 0) bcm43xx_periodic_every120sec(bcm); @@ -3123,13 +3130,79 @@ static void bcm43xx_periodic_work_handler(void *d) bcm43xx_periodic_every60sec(bcm); if (state % 2 == 0) bcm43xx_periodic_every30sec(bcm); - bcm43xx_periodic_every15sec(bcm); + if (state % 1 == 0) + bcm43xx_periodic_every15sec(bcm); bcm->periodic_state = state + 1; schedule_delayed_work(&bcm->periodic_work, HZ * 15); +} - mmiowb(); - bcm43xx_unlock_irqsafe(bcm, flags); +/* Estimate a "Badness" value based on the periodic work + * state-machine state. "Badness" is worse (bigger), if the + * periodic work will take longer. + */ +static int estimate_periodic_work_badness(unsigned int state) +{ + int badness = 0; + + if (state % 8 == 0) /* every 120 sec */ + badness += 10; + if (state % 4 == 0) /* every 60 sec */ + badness += 5; + if (state % 2 == 0) /* every 30 sec */ + badness += 1; + if (state % 1 == 0) /* every 15 sec */ + badness += 1; + +#define BADNESS_LIMIT 4 + return badness; +} + +static void bcm43xx_periodic_work_handler(void *d) +{ + struct bcm43xx_private *bcm = d; + unsigned long flags; + u32 savedirqs = 0; + int badness; + + badness = estimate_periodic_work_badness(bcm->periodic_state); + if (badness > BADNESS_LIMIT) { + /* Periodic work will take a long time, so we want it to + * be preemtible. + */ + bcm43xx_lock_irqonly(bcm, flags); + netif_stop_queue(bcm->net_dev); + if (bcm43xx_using_pio(bcm)) + bcm43xx_pio_freeze_txqueues(bcm); + savedirqs = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); + bcm43xx_unlock_irqonly(bcm, flags); + bcm43xx_lock_noirq(bcm); + bcm43xx_synchronize_irq(bcm); + } else { + /* Periodic work should take short time, so we want low + * locking overhead. + */ + bcm43xx_lock_irqsafe(bcm, flags); + } + + do_periodic_work(bcm); + + if (badness > BADNESS_LIMIT) { + bcm43xx_lock_irqonly(bcm, flags); + if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)) { + tasklet_enable(&bcm->isr_tasklet); + bcm43xx_interrupt_enable(bcm, savedirqs); + if (bcm43xx_using_pio(bcm)) + bcm43xx_pio_thaw_txqueues(bcm); + } + netif_wake_queue(bcm->net_dev); + mmiowb(); + bcm43xx_unlock_irqonly(bcm, flags); + bcm43xx_unlock_noirq(bcm); + } else { + mmiowb(); + bcm43xx_unlock_irqsafe(bcm, flags); + } } static void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm) @@ -3670,9 +3743,11 @@ static int bcm43xx_net_open(struct net_device *net_dev) static int bcm43xx_net_stop(struct net_device *net_dev) { struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + int err; ieee80211softmac_stop(net_dev); - bcm43xx_disable_interrupts_sync(bcm, NULL); + err = bcm43xx_disable_interrupts_sync(bcm, NULL); + assert(!err); bcm43xx_free_board(bcm); return 0; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c index 952c2f8b8b5..f8200deecc8 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c @@ -1410,7 +1410,10 @@ static inline u16 bcm43xx_phy_lo_g_deviation_subval(struct bcm43xx_private *bcm, u16 control) { struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + u16 ret; + unsigned long flags; + local_irq_save(flags); if (phy->connected) { bcm43xx_phy_write(bcm, 0x15, 0xE300); control <<= 8; @@ -1430,8 +1433,10 @@ u16 bcm43xx_phy_lo_g_deviation_subval(struct bcm43xx_private *bcm, u16 control) bcm43xx_phy_write(bcm, 0x0015, control | 0xFFE0); udelay(8); } + ret = bcm43xx_phy_read(bcm, 0x002D); + local_irq_restore(flags); - return bcm43xx_phy_read(bcm, 0x002D); + return ret; } static u32 bcm43xx_phy_lo_g_singledeviation(struct bcm43xx_private *bcm, u16 control) diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c index e77e9d859f8..574085c4615 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c @@ -264,6 +264,8 @@ static void tx_tasklet(unsigned long d) bcm43xx_lock_irqonly(bcm, flags); + if (queue->tx_frozen) + goto out_unlock; txctl = bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL); if (txctl & BCM43xx_PIO_TXCTL_SUSPEND) goto out_unlock; @@ -633,5 +635,40 @@ void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue) bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL) & ~BCM43xx_PIO_TXCTL_SUSPEND); bcm43xx_power_saving_ctl_bits(queue->bcm, -1, -1); - tasklet_schedule(&queue->txtask); + if (!list_empty(&queue->txqueue)) + tasklet_schedule(&queue->txtask); +} + +void bcm43xx_pio_freeze_txqueues(struct bcm43xx_private *bcm) +{ + struct bcm43xx_pio *pio; + + assert(bcm43xx_using_pio(bcm)); + pio = bcm43xx_current_pio(bcm); + pio->queue0->tx_frozen = 1; + pio->queue1->tx_frozen = 1; + pio->queue2->tx_frozen = 1; + pio->queue3->tx_frozen = 1; } + +void bcm43xx_pio_thaw_txqueues(struct bcm43xx_private *bcm) +{ + struct bcm43xx_pio *pio; + + assert(bcm43xx_using_pio(bcm)); + pio = bcm43xx_current_pio(bcm); + pio->queue0->tx_frozen = 0; + pio->queue1->tx_frozen = 0; + pio->queue2->tx_frozen = 0; + pio->queue3->tx_frozen = 0; + if (!list_empty(&pio->queue0->txqueue)) + tasklet_schedule(&pio->queue0->txtask); + if (!list_empty(&pio->queue1->txqueue)) + tasklet_schedule(&pio->queue1->txtask); + if (!list_empty(&pio->queue2->txqueue)) + tasklet_schedule(&pio->queue2->txtask); + if (!list_empty(&pio->queue3->txqueue)) + tasklet_schedule(&pio->queue3->txtask); +} + + diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h index dfc78209e3a..bc78a3c2caf 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h @@ -54,6 +54,7 @@ struct bcm43xx_pioqueue { u16 mmio_base; u8 tx_suspended:1, + tx_frozen:1, need_workarounds:1; /* Workarounds needed for core.rev < 3 */ /* Adjusted size of the device internal TX buffer. */ @@ -108,8 +109,12 @@ void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm, struct bcm43xx_xmitstatus *status); void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue); +/* Suspend a TX queue on hardware level. */ void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue); void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue); +/* Suspend (freeze) the TX tasklet (software level). */ +void bcm43xx_pio_freeze_txqueues(struct bcm43xx_private *bcm); +void bcm43xx_pio_thaw_txqueues(struct bcm43xx_private *bcm); #else /* CONFIG_BCM43XX_PIO */ @@ -145,6 +150,14 @@ static inline void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue) { } +static inline +void bcm43xx_pio_freeze_txqueues(struct bcm43xx_private *bcm) +{ +} +static inline +void bcm43xx_pio_thaw_txqueues(struct bcm43xx_private *bcm) +{ +} #endif /* CONFIG_BCM43XX_PIO */ #endif /* BCM43xx_PIO_H_ */ -- cgit v1.2.3 From 12a3768792dc27f11a5edb96e38db32bcdc5fd27 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Jun 2006 22:20:07 +0200 Subject: [PATCH] pci: bcm43xx avoid pci_find_device bcm43xx avoid pci_find_device Change pci_find_device to safer pci_get_device with support for more devices. Signed-off-by: Jiri Slaby Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 77d0e390b02..085d7857fe3 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -2146,6 +2146,13 @@ out: return err; } +#ifdef CONFIG_BCM947XX +static struct pci_device_id bcm43xx_47xx_ids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4324) }, + { 0 } +}; +#endif + static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm) { int res; @@ -2155,11 +2162,15 @@ static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm) bcm->irq = bcm->pci_dev->irq; #ifdef CONFIG_BCM947XX if (bcm->pci_dev->bus->number == 0) { - struct pci_dev *d = NULL; - /* FIXME: we will probably need more device IDs here... */ - d = pci_find_device(PCI_VENDOR_ID_BROADCOM, 0x4324, NULL); - if (d != NULL) { - bcm->irq = d->irq; + struct pci_dev *d; + struct pci_device_id *id; + for (id = bcm43xx_47xx_ids; id->vendor; id++) { + d = pci_get_device(id->vendor, id->device, NULL); + if (d != NULL) { + bcm->irq = d->irq; + pci_dev_put(d); + break; + } } } #endif -- cgit v1.2.3 From 7bd6b91800c996da328bd57e40e62b3f73760fbe Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 8 Jun 2006 09:47:42 -0500 Subject: [PATCH] wireless: correct dump of WPA IE In net/ieee80211/softmac/ieee80211softmac_wx.c, there is a bug that prints extended sign information whenever the byte value exceeds 0x7f. The following patch changes the printk to use a u8 cast to limit the output to 2 digits. This bug was first noticed by Dan Williams . This patch applies to the current master branch of the Linville tree. Signed-Off-By: Larry Finger Signed-off-by: John W. Linville --- net/ieee80211/softmac/ieee80211softmac_wx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c index 22aa6199185..0e65ff4e33f 100644 --- a/net/ieee80211/softmac/ieee80211softmac_wx.c +++ b/net/ieee80211/softmac/ieee80211softmac_wx.c @@ -388,7 +388,7 @@ ieee80211softmac_wx_set_genie(struct net_device *dev, memcpy(mac->wpa.IE, extra, wrqu->data.length); dprintk(KERN_INFO PFX "generic IE set to "); for (i=0;idata.length;i++) - dprintk("%.2x", mac->wpa.IE[i]); + dprintk("%.2x", (u8)mac->wpa.IE[i]); dprintk("\n"); mac->wpa.IElen = wrqu->data.length; } else { -- cgit v1.2.3 From 89c318ed3985da1271e00ad586f2dce8a6e75656 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Thu, 8 Jun 2006 22:19:49 -0700 Subject: [PATCH] ipw2200 locking fix Well, this is not 100% if when the card fires two consecutive interrupts. Though unlikely, it's better to protect early than seeing some "weird" bugs one day. I proposed attached patch. If you can help to test, that will be appreciated (I cannot see the lockdep warning on my box somehow). Cc: Frederik Deweerdt Cc: Arjan van de Ven Cc: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2200.c | 41 ++++++++++++++++++++++++++++++++--------- drivers/net/wireless/ipw2200.h | 1 + 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 39f82f21974..081a8999666 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -533,7 +533,7 @@ static inline void ipw_clear_bit(struct ipw_priv *priv, u32 reg, u32 mask) ipw_write32(priv, reg, ipw_read32(priv, reg) & ~mask); } -static inline void ipw_enable_interrupts(struct ipw_priv *priv) +static inline void __ipw_enable_interrupts(struct ipw_priv *priv) { if (priv->status & STATUS_INT_ENABLED) return; @@ -541,7 +541,7 @@ static inline void ipw_enable_interrupts(struct ipw_priv *priv) ipw_write32(priv, IPW_INTA_MASK_R, IPW_INTA_MASK_ALL); } -static inline void ipw_disable_interrupts(struct ipw_priv *priv) +static inline void __ipw_disable_interrupts(struct ipw_priv *priv) { if (!(priv->status & STATUS_INT_ENABLED)) return; @@ -549,6 +549,24 @@ static inline void ipw_disable_interrupts(struct ipw_priv *priv) ipw_write32(priv, IPW_INTA_MASK_R, ~IPW_INTA_MASK_ALL); } +static inline void ipw_enable_interrupts(struct ipw_priv *priv) +{ + unsigned long flags; + + spin_lock_irqsave(&priv->irq_lock, flags); + __ipw_enable_interrupts(priv); + spin_unlock_irqrestore(&priv->irq_lock, flags); +} + +static inline void ipw_disable_interrupts(struct ipw_priv *priv) +{ + unsigned long flags; + + spin_lock_irqsave(&priv->irq_lock, flags); + __ipw_disable_interrupts(priv); + spin_unlock_irqrestore(&priv->irq_lock, flags); +} + #ifdef CONFIG_IPW2200_DEBUG static char *ipw_error_desc(u32 val) { @@ -1856,7 +1874,7 @@ static void ipw_irq_tasklet(struct ipw_priv *priv) unsigned long flags; int rc = 0; - spin_lock_irqsave(&priv->lock, flags); + spin_lock_irqsave(&priv->irq_lock, flags); inta = ipw_read32(priv, IPW_INTA_RW); inta_mask = ipw_read32(priv, IPW_INTA_MASK_R); @@ -1865,6 +1883,10 @@ static void ipw_irq_tasklet(struct ipw_priv *priv) /* Add any cached INTA values that need to be handled */ inta |= priv->isr_inta; + spin_unlock_irqrestore(&priv->irq_lock, flags); + + spin_lock_irqsave(&priv->lock, flags); + /* handle all the justifications for the interrupt */ if (inta & IPW_INTA_BIT_RX_TRANSFER) { ipw_rx(priv); @@ -1993,10 +2015,10 @@ static void ipw_irq_tasklet(struct ipw_priv *priv) IPW_ERROR("Unhandled INTA bits 0x%08x\n", inta & ~handled); } + spin_unlock_irqrestore(&priv->lock, flags); + /* enable all interrupts */ ipw_enable_interrupts(priv); - - spin_unlock_irqrestore(&priv->lock, flags); } #define IPW_CMD(x) case IPW_CMD_ ## x : return #x @@ -10460,7 +10482,7 @@ static irqreturn_t ipw_isr(int irq, void *data, struct pt_regs *regs) if (!priv) return IRQ_NONE; - spin_lock(&priv->lock); + spin_lock(&priv->irq_lock); if (!(priv->status & STATUS_INT_ENABLED)) { /* Shared IRQ */ @@ -10482,7 +10504,7 @@ static irqreturn_t ipw_isr(int irq, void *data, struct pt_regs *regs) } /* tell the device to stop sending interrupts */ - ipw_disable_interrupts(priv); + __ipw_disable_interrupts(priv); /* ack current interrupts */ inta &= (IPW_INTA_MASK_ALL & inta_mask); @@ -10493,11 +10515,11 @@ static irqreturn_t ipw_isr(int irq, void *data, struct pt_regs *regs) tasklet_schedule(&priv->irq_tasklet); - spin_unlock(&priv->lock); + spin_unlock(&priv->irq_lock); return IRQ_HANDLED; none: - spin_unlock(&priv->lock); + spin_unlock(&priv->irq_lock); return IRQ_NONE; } @@ -11477,6 +11499,7 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) #ifdef CONFIG_IPW2200_DEBUG ipw_debug_level = debug; #endif + spin_lock_init(&priv->irq_lock); spin_lock_init(&priv->lock); for (i = 0; i < IPW_IBSS_MAC_HASH_SIZE; i++) INIT_LIST_HEAD(&priv->ibss_mac_hash[i]); diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h index 6044c0be2c8..ea12ad66b8e 100644 --- a/drivers/net/wireless/ipw2200.h +++ b/drivers/net/wireless/ipw2200.h @@ -1173,6 +1173,7 @@ struct ipw_priv { struct ieee80211_device *ieee; spinlock_t lock; + spinlock_t irq_lock; struct mutex mutex; /* basic pci-network driver stuff */ -- cgit v1.2.3 From 1668b19f75cb949f930814a23b74201ad6f76a53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20Alejandro=20L=C3=B3pez-Valencia?= Date: Thu, 15 Jun 2006 22:46:44 +0200 Subject: sundance: PCI ID for ip100a MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Patch provided by Pedro Alejandro López-Valencia in http://bugzilla.kernel.org/show_bug.cgi?id=6691 The patch is derived from IC+ GPL'ed rework of sundance driver available at http://www.icplus.com.tw/pp-IP100A.html Patch closes http://bugzilla.kernel.org/show_bug.cgi?id=5858 as well. Signed-off-by: Francois Romieu Cc: Pedro Alejandro López-Valencia --- drivers/net/sundance.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c index 61eec46cb11..f13b2a195c7 100644 --- a/drivers/net/sundance.c +++ b/drivers/net/sundance.c @@ -94,11 +94,13 @@ Version LK1.10 (Philippe De Muyter phdm@macqel.be): - Make 'unblock interface after Tx underrun' work + Version LK1.11 (Pedro Alejandro Lopez-Valencia palopezv at gmail.com): + - Add support for IC Plus Corporation IP100A chipset */ #define DRV_NAME "sundance" -#define DRV_VERSION "1.01+LK1.10" -#define DRV_RELDATE "28-Oct-2005" +#define DRV_VERSION "1.01+LK1.11" +#define DRV_RELDATE "14-Jun-2006" /* The user-configurable values. @@ -287,6 +289,7 @@ static struct pci_device_id sundance_pci_tbl[] = { {0x1186, 0x1002, 0x1186, 0x1040, 0, 0, 3}, {0x1186, 0x1002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4}, {0x13F0, 0x0201, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5}, + {0x13F0, 0x0200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6}, {0,} }; MODULE_DEVICE_TABLE(pci, sundance_pci_tbl); @@ -305,6 +308,7 @@ static const struct pci_id_info pci_id_tbl[] = { {"D-Link DFE-530TXS FAST Ethernet Adapter"}, {"D-Link DL10050-based FAST Ethernet Adapter"}, {"Sundance Technology Alta"}, + {"IC Plus Corporation IP100A FAST Ethernet Adapter"}, {NULL,}, /* 0 terminated list. */ }; -- cgit v1.2.3 From 785fcccd68bd4dc436f75fd4cd40e8557966c86d Mon Sep 17 00:00:00 2001 From: Len Brown Date: Thu, 15 Jun 2006 22:19:31 -0400 Subject: ACPI: resolve merge conflict between sem2mutex and processor_perflib.c Signed-off-by: Len Brown --- drivers/acpi/processor_perflib.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index f02c5ea9084..41aaaba74b1 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -624,7 +624,7 @@ int acpi_processor_preregister_performance( struct acpi_processor *match_pr; struct acpi_psd_package *match_pdomain; - down(&performance_sem); + mutex_lock(&performance_mutex); retval = 0; @@ -772,7 +772,7 @@ err_ret: pr->performance = NULL; /* Will be set for real in register */ } - up(&performance_sem); + mutex_unlock(&performance_mutex); return retval; } EXPORT_SYMBOL(acpi_processor_preregister_performance); -- cgit v1.2.3 From 872d83d00f67021e036d75aab3b7c6e3fc7e29ee Mon Sep 17 00:00:00 2001 From: Arnaud Patard Date: Thu, 27 Apr 2006 05:25:00 -0400 Subject: ACPI: suppress power button event on S3 resume http://bugzilla.kernel.org/show_bug.cgi?id=6612 Note that this fix depends on a fix in ACPICA 20060608 to replace a semaphore with a spin-lock. Signed-off-by: Arnaud Patard Acked-by: "Yu, Luming" Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/sleep/main.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c index 930427fc0c4..62ce87d7165 100644 --- a/drivers/acpi/sleep/main.c +++ b/drivers/acpi/sleep/main.c @@ -105,6 +105,14 @@ static int acpi_pm_enter(suspend_state_t pm_state) default: return -EINVAL; } + + /* ACPI 3.0 specs (P62) says that it's the responsabilty + * of the OSPM to clear the status bit [ implying that the + * POWER_BUTTON event should not reach userspace ] + */ + if (ACPI_SUCCESS(status) && (acpi_state == ACPI_STATE_S3)) + acpi_clear_event(ACPI_EVENT_POWER_BUTTON); + local_irq_restore(flags); printk(KERN_DEBUG "Back to C!\n"); -- cgit v1.2.3 From 1d47bec290a6f1f366192946840efef5076d9fc7 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Mon, 19 Jun 2006 08:39:16 +1000 Subject: [XFS] Remove unnecessary local from open_exec dmapi path. SGI-PV: 904196 SGI-Modid: xfs-linux-melb:xfs-kern:26247a Signed-off-by: Nathan Scott --- fs/xfs/linux-2.6/xfs_file.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index 89b1a742135..cf65a8364d5 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c @@ -522,23 +522,18 @@ xfs_file_open_exec( struct inode *inode) { bhv_vnode_t *vp = vn_from_inode(inode); - xfs_mount_t *mp = XFS_VFSTOM(vp->v_vfsp); - int error = 0; - xfs_inode_t *ip; - if (vp->v_vfsp->vfs_flag & VFS_DMI) { - ip = xfs_vtoi(vp); - if (!ip) { - error = -EINVAL; - goto open_exec_out; - } - if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ)) { - error = -XFS_SEND_DATA(mp, DM_EVENT_READ, vp, + if (unlikely(vp->v_vfsp->vfs_flag & VFS_DMI)) { + xfs_mount_t *mp = XFS_VFSTOM(vp->v_vfsp); + xfs_inode_t *ip = xfs_vtoi(vp); + + if (!ip) + return -EINVAL; + if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ)) + return -XFS_SEND_DATA(mp, DM_EVENT_READ, vp, 0, 0, 0, NULL); - } } -open_exec_out: - return error; + return 0; } #endif /* HAVE_FOP_OPEN_EXEC */ -- cgit v1.2.3 From 1e69dd0eb354d6f1a77098a3946b5ba57d4e3109 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Mon, 19 Jun 2006 08:39:53 +1000 Subject: [XFS] Push some common code out of write path into core XFS code for sharing. SGI-PV: 904196 SGI-Modid: xfs-linux-melb:xfs-kern:26248a Signed-off-by: Nathan Scott --- fs/xfs/linux-2.6/xfs_lrw.c | 76 ++-------------------------------------- fs/xfs/xfs_rw.c | 86 +++++++++++++++++++++++++++++++++++++++++++++- fs/xfs/xfs_rw.h | 3 +- 3 files changed, 90 insertions(+), 75 deletions(-) diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c index 3e76c5c9dda..8e546870481 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.c +++ b/fs/xfs/linux-2.6/xfs_lrw.c @@ -892,79 +892,9 @@ retry: /* Handle various SYNC-type writes */ if ((file->f_flags & O_SYNC) || IS_SYNC(inode)) { - /* - * If we're treating this as O_DSYNC and we have not updated the - * size, force the log. - */ - if (!(mp->m_flags & XFS_MOUNT_OSYNCISOSYNC) && - !(xip->i_update_size)) { - xfs_inode_log_item_t *iip = xip->i_itemp; - - /* - * If an allocation transaction occurred - * without extending the size, then we have to force - * the log up the proper point to ensure that the - * allocation is permanent. We can't count on - * the fact that buffered writes lock out direct I/O - * writes - the direct I/O write could have extended - * the size nontransactionally, then finished before - * we started. xfs_write_file will think that the file - * didn't grow but the update isn't safe unless the - * size change is logged. - * - * Force the log if we've committed a transaction - * against the inode or if someone else has and - * the commit record hasn't gone to disk (e.g. - * the inode is pinned). This guarantees that - * all changes affecting the inode are permanent - * when we return. - */ - if (iip && iip->ili_last_lsn) { - xfs_log_force(mp, iip->ili_last_lsn, - XFS_LOG_FORCE | XFS_LOG_SYNC); - } else if (xfs_ipincount(xip) > 0) { - xfs_log_force(mp, (xfs_lsn_t)0, - XFS_LOG_FORCE | XFS_LOG_SYNC); - } - - } else { - xfs_trans_t *tp; - - /* - * O_SYNC or O_DSYNC _with_ a size update are handled - * the same way. - * - * If the write was synchronous then we need to make - * sure that the inode modification time is permanent. - * We'll have updated the timestamp above, so here - * we use a synchronous transaction to log the inode. - * It's not fast, but it's necessary. - * - * If this a dsync write and the size got changed - * non-transactionally, then we need to ensure that - * the size change gets logged in a synchronous - * transaction. - */ - - tp = xfs_trans_alloc(mp, XFS_TRANS_WRITE_SYNC); - if ((error = xfs_trans_reserve(tp, 0, - XFS_SWRITE_LOG_RES(mp), - 0, 0, 0))) { - /* Transaction reserve failed */ - xfs_trans_cancel(tp, 0); - } else { - /* Transaction reserve successful */ - xfs_ilock(xip, XFS_ILOCK_EXCL); - xfs_trans_ijoin(tp, xip, XFS_ILOCK_EXCL); - xfs_trans_ihold(tp, xip); - xfs_trans_log_inode(tp, xip, XFS_ILOG_CORE); - xfs_trans_set_sync(tp); - error = xfs_trans_commit(tp, 0, NULL); - xfs_iunlock(xip, XFS_ILOCK_EXCL); - } - if (error) - goto out_unlock_internal; - } + error = xfs_write_sync_logforce(mp, xip); + if (error) + goto out_unlock_internal; xfs_rwunlock(bdp, locktype); if (need_i_mutex) diff --git a/fs/xfs/xfs_rw.c b/fs/xfs/xfs_rw.c index d33e4f5808e..c55e28189ab 100644 --- a/fs/xfs/xfs_rw.c +++ b/fs/xfs/xfs_rw.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. + * Copyright (c) 2000-2006 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -91,6 +91,90 @@ xfs_write_clear_setuid( return 0; } +/* + * Handle logging requirements of various synchronous types of write. + */ +int +xfs_write_sync_logforce( + xfs_mount_t *mp, + xfs_inode_t *ip) +{ + int error = 0; + + /* + * If we're treating this as O_DSYNC and we have not updated the + * size, force the log. + */ + if (!(mp->m_flags & XFS_MOUNT_OSYNCISOSYNC) && + !(ip->i_update_size)) { + xfs_inode_log_item_t *iip = ip->i_itemp; + + /* + * If an allocation transaction occurred + * without extending the size, then we have to force + * the log up the proper point to ensure that the + * allocation is permanent. We can't count on + * the fact that buffered writes lock out direct I/O + * writes - the direct I/O write could have extended + * the size nontransactionally, then finished before + * we started. xfs_write_file will think that the file + * didn't grow but the update isn't safe unless the + * size change is logged. + * + * Force the log if we've committed a transaction + * against the inode or if someone else has and + * the commit record hasn't gone to disk (e.g. + * the inode is pinned). This guarantees that + * all changes affecting the inode are permanent + * when we return. + */ + if (iip && iip->ili_last_lsn) { + xfs_log_force(mp, iip->ili_last_lsn, + XFS_LOG_FORCE | XFS_LOG_SYNC); + } else if (xfs_ipincount(ip) > 0) { + xfs_log_force(mp, (xfs_lsn_t)0, + XFS_LOG_FORCE | XFS_LOG_SYNC); + } + + } else { + xfs_trans_t *tp; + + /* + * O_SYNC or O_DSYNC _with_ a size update are handled + * the same way. + * + * If the write was synchronous then we need to make + * sure that the inode modification time is permanent. + * We'll have updated the timestamp above, so here + * we use a synchronous transaction to log the inode. + * It's not fast, but it's necessary. + * + * If this a dsync write and the size got changed + * non-transactionally, then we need to ensure that + * the size change gets logged in a synchronous + * transaction. + */ + tp = xfs_trans_alloc(mp, XFS_TRANS_WRITE_SYNC); + if ((error = xfs_trans_reserve(tp, 0, + XFS_SWRITE_LOG_RES(mp), + 0, 0, 0))) { + /* Transaction reserve failed */ + xfs_trans_cancel(tp, 0); + } else { + /* Transaction reserve successful */ + xfs_ilock(ip, XFS_ILOCK_EXCL); + xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); + xfs_trans_ihold(tp, ip); + xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); + xfs_trans_set_sync(tp); + error = xfs_trans_commit(tp, 0, NULL); + xfs_iunlock(ip, XFS_ILOCK_EXCL); + } + } + + return error; +} + /* * Force a shutdown of the filesystem instantly while keeping * the filesystem consistent. We don't do an unmount here; just shutdown diff --git a/fs/xfs/xfs_rw.h b/fs/xfs/xfs_rw.h index a572b175dc8..188b296ff50 100644 --- a/fs/xfs/xfs_rw.h +++ b/fs/xfs/xfs_rw.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. + * Copyright (c) 2000-2006 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -75,6 +75,7 @@ xfs_fsb_to_db_io(struct xfs_iocore *io, xfs_fsblock_t fsb) * Prototypes for functions in xfs_rw.c. */ extern int xfs_write_clear_setuid(struct xfs_inode *ip); +extern int xfs_write_sync_logforce(struct xfs_mount *mp, struct xfs_inode *ip); extern int xfs_bwrite(struct xfs_mount *mp, struct xfs_buf *bp); extern int xfs_bioerror(struct xfs_buf *bp); extern int xfs_bioerror_relse(struct xfs_buf *bp); -- cgit v1.2.3 From 6fe90e6d1451a05db37b2a582410ddcb45af3606 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Mon, 19 Jun 2006 08:40:12 +1000 Subject: [XFS] Remove an incorrect use of unlikely() on a relatively likely code path. SGI-PV: 904196 SGI-Modid: xfs-linux-melb:xfs-kern:26249a Signed-off-by: Nathan Scott --- fs/xfs/xfs_bmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 3050b4c647c..4d0ca14039a 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -2834,7 +2834,7 @@ xfs_bmap_btalloc( args.prod = ap->ip->i_d.di_extsize; if ((args.mod = (xfs_extlen_t)do_mod(ap->off, args.prod))) args.mod = (xfs_extlen_t)(args.prod - args.mod); - } else if (unlikely(mp->m_sb.sb_blocksize >= NBPP)) { + } else if (mp->m_sb.sb_blocksize >= NBPP) { args.prod = 1; args.mod = 0; } else { -- cgit v1.2.3 From a805bad5daae8d4f92ce46f467484d4867e996d4 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Mon, 19 Jun 2006 08:40:27 +1000 Subject: [XFS] Remove unneeded conditional code on NFS export interface related code paths. SGI-PV: 904196 SGI-Modid: xfs-linux-melb:xfs-kern:26250a Signed-off-by: Nathan Scott --- fs/xfs/Kconfig | 6 ------ fs/xfs/linux-2.6/xfs_super.c | 4 +--- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/fs/xfs/Kconfig b/fs/xfs/Kconfig index 236f9cf3714..26b364c9d62 100644 --- a/fs/xfs/Kconfig +++ b/fs/xfs/Kconfig @@ -1,6 +1,5 @@ config XFS_FS tristate "XFS filesystem support" - select EXPORTFS if NFSD!=n help XFS is a high performance journaling filesystem which originated on the SGI IRIX platform. It is completely multi-threaded, can @@ -18,11 +17,6 @@ config XFS_FS system of your root partition is compiled as a module, you'll need to use an initial ramdisk (initrd) to boot. -config XFS_EXPORT - bool - depends on XFS_FS && EXPORTFS - default y - config XFS_QUOTA bool "XFS Quota support" depends on XFS_FS diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index b7aad3cfdfe..7fae922d54d 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2005 Silicon Graphics, Inc. + * Copyright (c) 2000-2006 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -796,9 +796,7 @@ xfs_fs_fill_super( } sb_min_blocksize(sb, BBSIZE); -#ifdef CONFIG_XFS_EXPORT sb->s_export_op = &xfs_export_operations; -#endif sb->s_qcop = &xfs_quotactl_operations; sb->s_op = &xfs_super_operations; -- cgit v1.2.3 From 0d8fee3270f8a5e4bf95fbed3e81e21b57f8a5a0 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 19 Jun 2006 08:41:30 +1000 Subject: [XFS] Kill direct access to ->count in valusema(); all we ever use it for is check if semaphore is actually locked, which can be trivially done in portable way. Code gets more reabable, while we are at it... SGI-PV: 953915 SGI-Modid: xfs-linux-melb:xfs-kern:26274a Signed-off-by: Al Viro Signed-off-by: Nathan Scott --- fs/xfs/linux-2.6/sema.h | 19 ++++++++++--------- fs/xfs/quota/xfs_dquot.h | 4 ++-- fs/xfs/quota/xfs_dquot_item.c | 4 ++-- fs/xfs/xfs_iget.c | 2 +- fs/xfs/xfs_inode.c | 4 ++-- fs/xfs/xfs_inode_item.c | 6 +++--- 6 files changed, 20 insertions(+), 19 deletions(-) diff --git a/fs/xfs/linux-2.6/sema.h b/fs/xfs/linux-2.6/sema.h index 194a84490bd..b25090094cc 100644 --- a/fs/xfs/linux-2.6/sema.h +++ b/fs/xfs/linux-2.6/sema.h @@ -34,20 +34,21 @@ typedef struct semaphore sema_t; #define initnsema(sp, val, name) sema_init(sp, val) #define psema(sp, b) down(sp) #define vsema(sp) up(sp) -#define valusema(sp) (atomic_read(&(sp)->count)) -#define freesema(sema) +#define freesema(sema) do { } while (0) + +static inline int issemalocked(sema_t *sp) +{ + return down_trylock(sp) || (up(sp), 0); +} /* * Map cpsema (try to get the sema) to down_trylock. We need to switch * the return values since cpsema returns 1 (acquired) 0 (failed) and * down_trylock returns the reverse 0 (acquired) 1 (failed). */ - -#define cpsema(sp) (down_trylock(sp) ? 0 : 1) - -/* - * Didn't do cvsema(sp). Not sure how to map this to up/down/... - * It does a vsema if the values is < 0 other wise nothing. - */ +static inline int cpsema(sema_t *sp) +{ + return down_trylock(sp) ? 0 : 1; +} #endif /* __XFS_SUPPORT_SEMA_H__ */ diff --git a/fs/xfs/quota/xfs_dquot.h b/fs/xfs/quota/xfs_dquot.h index c0c629663a5..78d3ab95c5f 100644 --- a/fs/xfs/quota/xfs_dquot.h +++ b/fs/xfs/quota/xfs_dquot.h @@ -119,7 +119,7 @@ XFS_DQ_IS_LOCKED(xfs_dquot_t *dqp) */ #define xfs_dqflock(dqp) { psema(&((dqp)->q_flock), PINOD | PRECALC);\ (dqp)->dq_flags |= XFS_DQ_FLOCKED; } -#define xfs_dqfunlock(dqp) { ASSERT(valusema(&((dqp)->q_flock)) <= 0); \ +#define xfs_dqfunlock(dqp) { ASSERT(issemalocked(&((dqp)->q_flock))); \ vsema(&((dqp)->q_flock)); \ (dqp)->dq_flags &= ~(XFS_DQ_FLOCKED); } @@ -128,7 +128,7 @@ XFS_DQ_IS_LOCKED(xfs_dquot_t *dqp) #define XFS_DQ_PINUNLOCK(dqp, s) mutex_spinunlock( \ &(XFS_DQ_TO_QINF(dqp)->qi_pinlock), s) -#define XFS_DQ_IS_FLUSH_LOCKED(dqp) (valusema(&((dqp)->q_flock)) <= 0) +#define XFS_DQ_IS_FLUSH_LOCKED(dqp) (issemalocked(&((dqp)->q_flock))) #define XFS_DQ_IS_ON_FREELIST(dqp) ((dqp)->dq_flnext != (dqp)) #define XFS_DQ_IS_DIRTY(dqp) ((dqp)->dq_flags & XFS_DQ_DIRTY) #define XFS_QM_ISUDQ(dqp) ((dqp)->dq_flags & XFS_DQ_USER) diff --git a/fs/xfs/quota/xfs_dquot_item.c b/fs/xfs/quota/xfs_dquot_item.c index 546f48af882..21ad5a55e01 100644 --- a/fs/xfs/quota/xfs_dquot_item.c +++ b/fs/xfs/quota/xfs_dquot_item.c @@ -248,7 +248,7 @@ xfs_qm_dquot_logitem_pushbuf( * inode flush completed and the inode was taken off the AIL. * So, just get out. */ - if ((valusema(&(dqp->q_flock)) > 0) || + if (!issemalocked(&(dqp->q_flock)) || ((qip->qli_item.li_flags & XFS_LI_IN_AIL) == 0)) { qip->qli_pushbuf_flag = 0; xfs_dqunlock(dqp); @@ -261,7 +261,7 @@ xfs_qm_dquot_logitem_pushbuf( if (bp != NULL) { if (XFS_BUF_ISDELAYWRITE(bp)) { dopush = ((qip->qli_item.li_flags & XFS_LI_IN_AIL) && - (valusema(&(dqp->q_flock)) <= 0)); + issemalocked(&(dqp->q_flock))); qip->qli_pushbuf_flag = 0; xfs_dqunlock(dqp); diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index da3c94c230d..7894b72a717 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c @@ -1031,6 +1031,6 @@ xfs_iflock_nowait(xfs_inode_t *ip) void xfs_ifunlock(xfs_inode_t *ip) { - ASSERT(valusema(&(ip->i_flock)) <= 0); + ASSERT(issemalocked(&(ip->i_flock))); vsema(&(ip->i_flock)); } diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 9af9e32a6a1..e799f0d0087 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -3015,7 +3015,7 @@ xfs_iflush( XFS_STATS_INC(xs_iflush_count); ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE|MR_ACCESS)); - ASSERT(valusema(&ip->i_flock) <= 0); + ASSERT(issemalocked(&(ip->i_flock))); ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE || ip->i_d.di_nextents > ip->i_df.if_ext_max); @@ -3273,7 +3273,7 @@ xfs_iflush_int( SPLDECL(s); ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE|MR_ACCESS)); - ASSERT(valusema(&ip->i_flock) <= 0); + ASSERT(issemalocked(&(ip->i_flock))); ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE || ip->i_d.di_nextents > ip->i_df.if_ext_max); diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index cd65a565b4f..2caa91b8971 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c @@ -794,7 +794,7 @@ xfs_inode_item_pushbuf( * inode flush completed and the inode was taken off the AIL. * So, just get out. */ - if ((valusema(&(ip->i_flock)) > 0) || + if (!issemalocked(&(ip->i_flock)) || ((iip->ili_item.li_flags & XFS_LI_IN_AIL) == 0)) { iip->ili_pushbuf_flag = 0; xfs_iunlock(ip, XFS_ILOCK_SHARED); @@ -816,7 +816,7 @@ xfs_inode_item_pushbuf( * If not, we can flush it async. */ dopush = ((iip->ili_item.li_flags & XFS_LI_IN_AIL) && - (valusema(&(ip->i_flock)) <= 0)); + issemalocked(&(ip->i_flock))); iip->ili_pushbuf_flag = 0; xfs_iunlock(ip, XFS_ILOCK_SHARED); xfs_buftrace("INODE ITEM PUSH", bp); @@ -864,7 +864,7 @@ xfs_inode_item_push( ip = iip->ili_inode; ASSERT(ismrlocked(&(ip->i_lock), MR_ACCESS)); - ASSERT(valusema(&(ip->i_flock)) <= 0); + ASSERT(issemalocked(&(ip->i_flock))); /* * Since we were able to lock the inode's flush lock and * we found it on the AIL, the inode must be dirty. This -- cgit v1.2.3 From a3fd4a1b9ced850ac1a9d5bb9f8fab494d07f3fa Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 4 Jun 2006 17:51:15 +0100 Subject: [MMC] Convert all hosts except mmci to use data->blksz The MMC specification allows non-power of two block sizes. As such, we should not pass the log2 block size to host drivers, but instead pass the byte size. However, ARM MMCI can only work with log2 block size, so continue to pass both the log2 block size and byte block size. This means that for the moment, the byte block size must remain a power of two, but this is the first stage of removing this restriction for other hosts. Signed-off-by: Russell King --- drivers/mmc/at91_mci.c | 2 +- drivers/mmc/imxmmc.c | 2 +- drivers/mmc/omap.c | 6 +++--- drivers/mmc/sdhci.c | 8 ++++---- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/mmc/at91_mci.c b/drivers/mmc/at91_mci.c index 88f0eef9cf3..42284e1d462 100644 --- a/drivers/mmc/at91_mci.c +++ b/drivers/mmc/at91_mci.c @@ -411,7 +411,7 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_ } if (data) { - block_length = 1 << data->blksz_bits; + block_length = data->blksz; blocks = data->blocks; /* always set data start - also set direction flag for read */ diff --git a/drivers/mmc/imxmmc.c b/drivers/mmc/imxmmc.c index a4eb1d0e7a7..5c62f4e6ad0 100644 --- a/drivers/mmc/imxmmc.c +++ b/drivers/mmc/imxmmc.c @@ -228,7 +228,7 @@ static int imxmci_busy_wait_for_status(struct imxmci_host *host, static void imxmci_setup_data(struct imxmci_host *host, struct mmc_data *data) { unsigned int nob = data->blocks; - unsigned int blksz = 1 << data->blksz_bits; + unsigned int blksz = data->blksz; unsigned int datasz = nob * blksz; int i; diff --git a/drivers/mmc/omap.c b/drivers/mmc/omap.c index becb3c68c34..c25244b3657 100644 --- a/drivers/mmc/omap.c +++ b/drivers/mmc/omap.c @@ -584,10 +584,10 @@ mmc_omap_prepare_dma(struct mmc_omap_host *host, struct mmc_data *data) int sync_dev = 0; data_addr = io_v2p((u32) host->base) + OMAP_MMC_REG_DATA; - frame = 1 << data->blksz_bits; + frame = data->blksz; count = sg_dma_len(sg); - if ((data->blocks == 1) && (count > (1 << data->blksz_bits))) + if ((data->blocks == 1) && (count > data->blksz)) count = frame; host->dma_len = count; @@ -776,7 +776,7 @@ mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req) } - block_size = 1 << data->blksz_bits; + block_size = data->blksz; OMAP_MMC_WRITE(host->base, NBLK, data->blocks - 1); OMAP_MMC_WRITE(host->base, BLEN, block_size - 1); diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index 6bfcdbc7491..8e9100bd57e 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -268,7 +268,7 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) } DBG("blksz %04x blks %04x flags %08x\n", - 1 << data->blksz_bits, data->blocks, data->flags); + data->blksz, data->blocks, data->flags); DBG("tsac %d ms nsac %d clk\n", data->timeout_ns / 1000000, data->timeout_clks); @@ -282,7 +282,7 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) writew(mode, host->ioaddr + SDHCI_TRANSFER_MODE); - writew(1 << data->blksz_bits, host->ioaddr + SDHCI_BLOCK_SIZE); + writew(data->blksz, host->ioaddr + SDHCI_BLOCK_SIZE); writew(data->blocks, host->ioaddr + SDHCI_BLOCK_COUNT); if (host->flags & SDHCI_USE_DMA) { @@ -294,7 +294,7 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) writel(sg_dma_address(data->sg), host->ioaddr + SDHCI_DMA_ADDRESS); } else { - host->size = (1 << data->blksz_bits) * data->blocks; + host->size = data->blksz * data->blocks; host->cur_sg = data->sg; host->num_sg = data->sg_len; @@ -335,7 +335,7 @@ static void sdhci_finish_data(struct sdhci_host *host) blocks = 0; else blocks = readw(host->ioaddr + SDHCI_BLOCK_COUNT); - data->bytes_xfered = (1 << data->blksz_bits) * (data->blocks - blocks); + data->bytes_xfered = data->blksz * (data->blocks - blocks); if ((data->error == MMC_ERR_NONE) && blocks) { printk(KERN_ERR "%s: Controller signalled completion even " -- cgit v1.2.3 From b44fb7a09e6bb7d77c1b4b402591f6f953c1e51c Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Mon, 19 Jun 2006 13:06:05 +0100 Subject: [ARM] 3565/1: AT91RM9200 MMC update Patch from Andrew Victor This patch includes code cleanups and minor fixes to the AT91RM9200 MMC driver. 1. Replace calls to DBG() with pr_debug(). 2. 'host' can never be null, so don't bother checking for that case. 3. Remove SA_SAMPLE_RANDOM from request_irq(). [Patch from Matt Mackall] 4. clk_get() doesn't return NULL on error - need to test returned value with IS_ERR(). 5. Free resources if clk_get() or request_irq() fails. Signed-off-by: Andrew Victor Signed-off-by: Russell King --- drivers/mmc/at91_mci.c | 139 +++++++++++++++++++++++-------------------------- 1 file changed, 65 insertions(+), 74 deletions(-) diff --git a/drivers/mmc/at91_mci.c b/drivers/mmc/at91_mci.c index 42284e1d462..3228516b7d1 100644 --- a/drivers/mmc/at91_mci.c +++ b/drivers/mmc/at91_mci.c @@ -81,13 +81,6 @@ #undef SUPPORT_4WIRE -#ifdef CONFIG_MMC_DEBUG -#define DBG(fmt...) \ - printk(fmt) -#else -#define DBG(fmt...) do { } while (0) -#endif - static struct clk *mci_clk; #define FL_SENT_COMMAND (1 << 0) @@ -202,50 +195,50 @@ static void at91mci_pre_dma_read(struct at91mci_host *host) struct mmc_command *cmd; struct mmc_data *data; - DBG("pre dma read\n"); + pr_debug("pre dma read\n"); cmd = host->cmd; if (!cmd) { - DBG("no command\n"); + pr_debug("no command\n"); return; } data = cmd->data; if (!data) { - DBG("no data\n"); + pr_debug("no data\n"); return; } for (i = 0; i < 2; i++) { /* nothing left to transfer */ if (host->transfer_index >= data->sg_len) { - DBG("Nothing left to transfer (index = %d)\n", host->transfer_index); + pr_debug("Nothing left to transfer (index = %d)\n", host->transfer_index); break; } /* Check to see if this needs filling */ if (i == 0) { if (at91_mci_read(AT91_PDC_RCR) != 0) { - DBG("Transfer active in current\n"); + pr_debug("Transfer active in current\n"); continue; } } else { if (at91_mci_read(AT91_PDC_RNCR) != 0) { - DBG("Transfer active in next\n"); + pr_debug("Transfer active in next\n"); continue; } } /* Setup the next transfer */ - DBG("Using transfer index %d\n", host->transfer_index); + pr_debug("Using transfer index %d\n", host->transfer_index); sg = &data->sg[host->transfer_index++]; - DBG("sg = %p\n", sg); + pr_debug("sg = %p\n", sg); sg->dma_address = dma_map_page(NULL, sg->page, sg->offset, sg->length, DMA_FROM_DEVICE); - DBG("dma address = %08X, length = %d\n", sg->dma_address, sg->length); + pr_debug("dma address = %08X, length = %d\n", sg->dma_address, sg->length); if (i == 0) { at91_mci_write(AT91_PDC_RPR, sg->dma_address); @@ -257,7 +250,7 @@ static void at91mci_pre_dma_read(struct at91mci_host *host) } } - DBG("pre dma read done\n"); + pr_debug("pre dma read done\n"); } /* @@ -268,17 +261,17 @@ static void at91mci_post_dma_read(struct at91mci_host *host) struct mmc_command *cmd; struct mmc_data *data; - DBG("post dma read\n"); + pr_debug("post dma read\n"); cmd = host->cmd; if (!cmd) { - DBG("no command\n"); + pr_debug("no command\n"); return; } data = cmd->data; if (!data) { - DBG("no data\n"); + pr_debug("no data\n"); return; } @@ -289,17 +282,17 @@ static void at91mci_post_dma_read(struct at91mci_host *host) struct scatterlist *sg; - DBG("finishing index %d\n", host->in_use_index); + pr_debug("finishing index %d\n", host->in_use_index); sg = &data->sg[host->in_use_index++]; - DBG("Unmapping page %08X\n", sg->dma_address); + pr_debug("Unmapping page %08X\n", sg->dma_address); dma_unmap_page(NULL, sg->dma_address, sg->length, DMA_FROM_DEVICE); /* Swap the contents of the buffer */ buffer = kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset; - DBG("buffer = %p, length = %d\n", buffer, sg->length); + pr_debug("buffer = %p, length = %d\n", buffer, sg->length); data->bytes_xfered += sg->length; @@ -320,7 +313,7 @@ static void at91mci_post_dma_read(struct at91mci_host *host) at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS); } - DBG("post dma read done\n"); + pr_debug("post dma read done\n"); } /* @@ -331,7 +324,7 @@ static void at91_mci_handle_transmitted(struct at91mci_host *host) struct mmc_command *cmd; struct mmc_data *data; - DBG("Handling the transmit\n"); + pr_debug("Handling the transmit\n"); /* Disable the transfer */ at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS); @@ -387,12 +380,12 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_ /* Not sure if this is needed */ #if 0 if ((at91_mci_read(AT91_MCI_SR) & AT91_MCI_RTOE) && (cmd->opcode == 1)) { - DBG("Clearing timeout\n"); + pr_debug("Clearing timeout\n"); at91_mci_write(AT91_MCI_ARGR, 0); at91_mci_write(AT91_MCI_CMDR, AT91_MCI_OPDCMD); while (!(at91_mci_read(AT91_MCI_SR) & AT91_MCI_CMDRDY)) { /* spin */ - DBG("Clearing: SR = %08X\n", at91_mci_read(AT91_MCI_SR)); + pr_debug("Clearing: SR = %08X\n", at91_mci_read(AT91_MCI_SR)); } } #endif @@ -439,7 +432,7 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_ /* * Set the arguments and send the command */ - DBG("Sending command %d as %08X, arg = %08X, blocks = %d, length = %d (MR = %08lX)\n", + pr_debug("Sending command %d as %08X, arg = %08X, blocks = %d, length = %d (MR = %08lX)\n", cmd->opcode, cmdr, cmd->arg, blocks, block_length, at91_mci_read(AT91_MCI_MR)); if (!data) { @@ -491,7 +484,7 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_ at91mci_sg_to_dma(host, data); - DBG("Transmitting %d bytes\n", host->total_length); + pr_debug("Transmitting %d bytes\n", host->total_length); at91_mci_write(AT91_PDC_TPR, host->physical_address); at91_mci_write(AT91_PDC_TCR, host->total_length / 4); @@ -525,7 +518,7 @@ static void at91mci_process_command(struct at91mci_host *host, struct mmc_comman ier = at91_mci_send_command(host, cmd); - DBG("setting ier to %08X\n", ier); + pr_debug("setting ier to %08X\n", ier); /* Stop on errors or the required value */ at91_mci_write(AT91_MCI_IER, 0xffff0000 | ier); @@ -570,7 +563,7 @@ static void at91mci_completed_command(struct at91mci_host *host) status = at91_mci_read(AT91_MCI_SR); - DBG("Status = %08X [%08X %08X %08X %08X]\n", + pr_debug("Status = %08X [%08X %08X %08X %08X]\n", status, cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]); if (status & (AT91_MCI_RINDE | AT91_MCI_RDIRE | AT91_MCI_RCRCE | @@ -590,7 +583,7 @@ static void at91mci_completed_command(struct at91mci_host *host) else cmd->error = MMC_ERR_FAILED; - DBG("Error detected and set to %d (cmd = %d, retries = %d)\n", + pr_debug("Error detected and set to %d (cmd = %d, retries = %d)\n", cmd->error, cmd->opcode, cmd->retries); } } @@ -621,10 +614,7 @@ static void at91_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) struct at91mci_host *host = mmc_priv(mmc); unsigned long at91_master_clock = clk_get_rate(mci_clk); - if (host) - host->bus_mode = ios->bus_mode; - else - printk("MMC: No host for bus_mode\n"); + host->bus_mode = ios->bus_mode; if (ios->clock == 0) { /* Disable the MCI controller */ @@ -640,15 +630,15 @@ static void at91_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) else clkdiv = (at91_master_clock / ios->clock) / 2; - DBG("clkdiv = %d. mcck = %ld\n", clkdiv, + pr_debug("clkdiv = %d. mcck = %ld\n", clkdiv, at91_master_clock / (2 * (clkdiv + 1))); } if (ios->bus_width == MMC_BUS_WIDTH_4 && host->board->wire4) { - DBG("MMC: Setting controller bus width to 4\n"); + pr_debug("MMC: Setting controller bus width to 4\n"); at91_mci_write(AT91_MCI_SDCR, at91_mci_read(AT91_MCI_SDCR) | AT91_MCI_SDCBUS); } else { - DBG("MMC: Setting controller bus width to 1\n"); + pr_debug("MMC: Setting controller bus width to 1\n"); at91_mci_write(AT91_MCI_SDCR, at91_mci_read(AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS); } @@ -656,7 +646,7 @@ static void at91_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) at91_mci_write(AT91_MCI_MR, (at91_mci_read(AT91_MCI_MR) & ~AT91_MCI_CLKDIV) | clkdiv); /* maybe switch power to the card */ - if (host && host->board->vcc_pin) { + if (host->board->vcc_pin) { switch (ios->power_mode) { case MMC_POWER_OFF: at91_set_gpio_output(host->board->vcc_pin, 0); @@ -679,11 +669,8 @@ static irqreturn_t at91_mci_irq(int irq, void *devid, struct pt_regs *regs) unsigned int int_status; - if (host == NULL) - return IRQ_HANDLED; - int_status = at91_mci_read(AT91_MCI_SR); - DBG("MCI irq: status = %08X, %08lX, %08lX\n", int_status, at91_mci_read(AT91_MCI_IMR), + pr_debug("MCI irq: status = %08X, %08lX, %08lX\n", int_status, at91_mci_read(AT91_MCI_IMR), int_status & at91_mci_read(AT91_MCI_IMR)); if ((int_status & at91_mci_read(AT91_MCI_IMR)) & 0xffff0000) @@ -692,75 +679,75 @@ static irqreturn_t at91_mci_irq(int irq, void *devid, struct pt_regs *regs) int_status &= at91_mci_read(AT91_MCI_IMR); if (int_status & AT91_MCI_UNRE) - DBG("MMC: Underrun error\n"); + pr_debug("MMC: Underrun error\n"); if (int_status & AT91_MCI_OVRE) - DBG("MMC: Overrun error\n"); + pr_debug("MMC: Overrun error\n"); if (int_status & AT91_MCI_DTOE) - DBG("MMC: Data timeout\n"); + pr_debug("MMC: Data timeout\n"); if (int_status & AT91_MCI_DCRCE) - DBG("MMC: CRC error in data\n"); + pr_debug("MMC: CRC error in data\n"); if (int_status & AT91_MCI_RTOE) - DBG("MMC: Response timeout\n"); + pr_debug("MMC: Response timeout\n"); if (int_status & AT91_MCI_RENDE) - DBG("MMC: Response end bit error\n"); + pr_debug("MMC: Response end bit error\n"); if (int_status & AT91_MCI_RCRCE) - DBG("MMC: Response CRC error\n"); + pr_debug("MMC: Response CRC error\n"); if (int_status & AT91_MCI_RDIRE) - DBG("MMC: Response direction error\n"); + pr_debug("MMC: Response direction error\n"); if (int_status & AT91_MCI_RINDE) - DBG("MMC: Response index error\n"); + pr_debug("MMC: Response index error\n"); /* Only continue processing if no errors */ if (!completed) { if (int_status & AT91_MCI_TXBUFE) { - DBG("TX buffer empty\n"); + pr_debug("TX buffer empty\n"); at91_mci_handle_transmitted(host); } if (int_status & AT91_MCI_RXBUFF) { - DBG("RX buffer full\n"); + pr_debug("RX buffer full\n"); at91_mci_write(AT91_MCI_IER, AT91_MCI_CMDRDY); } if (int_status & AT91_MCI_ENDTX) { - DBG("Transmit has ended\n"); + pr_debug("Transmit has ended\n"); } if (int_status & AT91_MCI_ENDRX) { - DBG("Receive has ended\n"); + pr_debug("Receive has ended\n"); at91mci_post_dma_read(host); } if (int_status & AT91_MCI_NOTBUSY) { - DBG("Card is ready\n"); + pr_debug("Card is ready\n"); at91_mci_write(AT91_MCI_IER, AT91_MCI_CMDRDY); } if (int_status & AT91_MCI_DTIP) { - DBG("Data transfer in progress\n"); + pr_debug("Data transfer in progress\n"); } if (int_status & AT91_MCI_BLKE) { - DBG("Block transfer has ended\n"); + pr_debug("Block transfer has ended\n"); } if (int_status & AT91_MCI_TXRDY) { - DBG("Ready to transmit\n"); + pr_debug("Ready to transmit\n"); } if (int_status & AT91_MCI_RXRDY) { - DBG("Ready to receive\n"); + pr_debug("Ready to receive\n"); } if (int_status & AT91_MCI_CMDRDY) { - DBG("Command ready\n"); + pr_debug("Command ready\n"); completed = 1; } } at91_mci_write(AT91_MCI_IDR, int_status); if (completed) { - DBG("Completed command\n"); + pr_debug("Completed command\n"); at91_mci_write(AT91_MCI_IDR, 0xffffffff); at91mci_completed_command(host); } @@ -779,10 +766,10 @@ static irqreturn_t at91_mmc_det_irq(int irq, void *_host, struct pt_regs *regs) */ if (present != host->present) { host->present = present; - DBG("%s: card %s\n", mmc_hostname(host->mmc), + pr_debug("%s: card %s\n", mmc_hostname(host->mmc), present ? "insert" : "remove"); if (!present) { - DBG("****** Resetting SD-card bus width ******\n"); + pr_debug("****** Resetting SD-card bus width ******\n"); at91_mci_write(AT91_MCI_SDCR, 0); } mmc_detect_change(host->mmc, msecs_to_jiffies(100)); @@ -822,13 +809,13 @@ static int at91_mci_probe(struct platform_device *pdev) struct at91mci_host *host; int ret; - DBG("Probe MCI devices\n"); + pr_debug("Probe MCI devices\n"); at91_mci_disable(); at91_mci_enable(); mmc = mmc_alloc_host(sizeof(struct at91mci_host), &pdev->dev); if (!mmc) { - DBG("Failed to allocate mmc host\n"); + pr_debug("Failed to allocate mmc host\n"); return -ENOMEM; } @@ -854,8 +841,9 @@ static int at91_mci_probe(struct platform_device *pdev) * Get Clock */ mci_clk = clk_get(&pdev->dev, "mci_clk"); - if (!mci_clk) { + if (IS_ERR(mci_clk)) { printk(KERN_ERR "AT91 MMC: no clock defined.\n"); + mmc_free_host(mmc); return -ENODEV; } clk_enable(mci_clk); /* Enable the peripheral clock */ @@ -865,7 +853,10 @@ static int at91_mci_probe(struct platform_device *pdev) */ ret = request_irq(AT91_ID_MCI, at91_mci_irq, SA_SHIRQ, DRIVER_NAME, host); if (ret) { - DBG("Failed to request MCI interrupt\n"); + printk(KERN_ERR "Failed to request MCI interrupt\n"); + clk_disable(mci_clk); + clk_put(mci_clk); + mmc_free_host(mmc); return ret; } @@ -886,12 +877,12 @@ static int at91_mci_probe(struct platform_device *pdev) */ if (host->board->det_pin) { ret = request_irq(host->board->det_pin, at91_mmc_det_irq, - SA_SAMPLE_RANDOM, DRIVER_NAME, host); + 0, DRIVER_NAME, host); if (ret) - DBG("couldn't allocate MMC detect irq\n"); + printk(KERN_ERR "couldn't allocate MMC detect irq\n"); } - DBG(KERN_INFO "Added MCI driver\n"); + pr_debug(KERN_INFO "Added MCI driver\n"); return 0; } @@ -924,7 +915,7 @@ static int at91_mci_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); - DBG("Removed\n"); + pr_debug("MCI Removed\n"); return 0; } -- cgit v1.2.3 From b7408aff2d325581dcafffa5dbcc09c42ae64b5d Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Mon, 19 Jun 2006 13:08:39 +0100 Subject: [ARM] 3563/1: LED: Set the LOCOMO LED driver default triggers Patch from Richard Purdie Set the default triggers for the LOCOMO LED driver. Signed-off-by: Richard Purdie Signed-off-by: Russell King --- drivers/leds/leds-locomo.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/leds/leds-locomo.c b/drivers/leds/leds-locomo.c index 749a86c2adb..8419e29b71f 100644 --- a/drivers/leds/leds-locomo.c +++ b/drivers/leds/leds-locomo.c @@ -45,11 +45,13 @@ static void locomoled_brightness_set1(struct led_classdev *led_cdev, static struct led_classdev locomo_led0 = { .name = "locomo:amber", + .default_trigger = "sharpsl-charge", .brightness_set = locomoled_brightness_set0, }; static struct led_classdev locomo_led1 = { .name = "locomo:green", + .default_trigger = "nand-disk", .brightness_set = locomoled_brightness_set1, }; -- cgit v1.2.3 From 91f8ed835ffb34b4108cc16eefd3303e4068bee0 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Mon, 19 Jun 2006 13:20:23 +0100 Subject: [ARM] 3578/1: AT91RM9200 Clock update Patch from Andrew Victor Some updates to the clock infrastructure for the AT91RM9200. 1. Hard-coded values replaced with names defined in at91rm9200_sys.h. 2. Added the four PIO clocks, which are enabled at startup. 3. At startup, disable all unused clocks. 4. Minor bugfix for usage counts associated with MCK. [Patch from David Brownell] 5. Added at91_clock_associate() function to associate device & function with a particular clock. [Patch from David Brownell] Signed-off-by: Andrew Victor Signed-off-by: Russell King --- arch/arm/mach-at91rm9200/clock.c | 121 ++++++++++++++++++++++++++++++++------- 1 file changed, 101 insertions(+), 20 deletions(-) diff --git a/arch/arm/mach-at91rm9200/clock.c b/arch/arm/mach-at91rm9200/clock.c index 8b95467c6d6..30042d2bac5 100644 --- a/arch/arm/mach-at91rm9200/clock.c +++ b/arch/arm/mach-at91rm9200/clock.c @@ -32,8 +32,6 @@ #include "generic.h" -#undef DEBUG - /* * There's a lot more which can be done with clocks, including cpufreq * integration, slow clock mode support (for system suspend), letting @@ -41,7 +39,9 @@ */ struct clk { - const char *name; + const char *name; /* unique clock name */ + const char *function; /* function of the clock */ + struct device *dev; /* device associated with function */ unsigned long rate_hz; struct clk *parent; u32 pmc_mask; @@ -71,15 +71,14 @@ static struct clk clk32k = { }; static struct clk main_clk = { .name = "main", - .pmc_mask = 1 << 0, /* in PMC_SR */ - .users = 1, + .pmc_mask = AT91_PMC_MOSCS, /* in PMC_SR */ .id = 1, .primary = 1, }; static struct clk plla = { .name = "plla", .parent = &main_clk, - .pmc_mask = 1 << 1, /* in PMC_SR */ + .pmc_mask = AT91_PMC_LOCKA, /* in PMC_SR */ .id = 2, .primary = 1, .pll = 1, @@ -105,7 +104,7 @@ static void pllb_mode(struct clk *clk, int is_on) static struct clk pllb = { .name = "pllb", .parent = &main_clk, - .pmc_mask = 1 << 2, /* in PMC_SR */ + .pmc_mask = AT91_PMC_LOCKB, /* in PMC_SR */ .mode = pllb_mode, .id = 3, .primary = 1, @@ -177,8 +176,7 @@ static struct clk pck3 = { */ static struct clk mck = { .name = "mck", - .pmc_mask = 1 << 3, /* in PMC_SR */ - .users = 1, /* (must be) always on */ + .pmc_mask = AT91_PMC_MCKRDY, /* in PMC_SR */ }; static void pmc_periph_mode(struct clk *clk, int is_on) @@ -249,6 +247,30 @@ static struct clk spi_clk = { .pmc_mask = 1 << AT91_ID_SPI, .mode = pmc_periph_mode, }; +static struct clk pioA_clk = { + .name = "pioA_clk", + .parent = &mck, + .pmc_mask = 1 << AT91_ID_PIOA, + .mode = pmc_periph_mode, +}; +static struct clk pioB_clk = { + .name = "pioB_clk", + .parent = &mck, + .pmc_mask = 1 << AT91_ID_PIOB, + .mode = pmc_periph_mode, +}; +static struct clk pioC_clk = { + .name = "pioC_clk", + .parent = &mck, + .pmc_mask = 1 << AT91_ID_PIOC, + .mode = pmc_periph_mode, +}; +static struct clk pioD_clk = { + .name = "pioD_clk", + .parent = &mck, + .pmc_mask = 1 << AT91_ID_PIOD, + .mode = pmc_periph_mode, +}; static struct clk *const clock_list[] = { /* four primary clocks -- MUST BE FIRST! */ @@ -279,21 +301,46 @@ static struct clk *const clock_list[] = { &udc_clk, &twi_clk, &spi_clk, + &pioA_clk, + &pioB_clk, + &pioC_clk, + &pioD_clk, // ssc0..ssc2 // tc0..tc5 + // irq0..irq6 &ohci_clk, ðer_clk, }; +/* + * Associate a particular clock with a function (eg, "uart") and device. + * The drivers can then request the same 'function' with several different + * devices and not care about which clock name to use. + */ +void __init at91_clock_associate(const char *id, struct device *dev, const char *func) +{ + struct clk *clk = clk_get(NULL, id); + + if (!dev || !clk || !IS_ERR(clk_get(dev, func))) + return; + + clk->function = func; + clk->dev = dev; +} + /* clocks are all static for now; no refcounting necessary */ struct clk *clk_get(struct device *dev, const char *id) { int i; for (i = 0; i < ARRAY_SIZE(clock_list); i++) { - if (strcmp(id, clock_list[i]->name) == 0) - return clock_list[i]; + struct clk *clk = clock_list[i]; + + if (strcmp(id, clk->name) == 0) + return clk; + if (clk->function && (dev == clk->dev) && strcmp(id, clk->function) == 0) + return clk; } return ERR_PTR(-ENOENT); @@ -593,6 +640,30 @@ fail: return 0; } + +/* + * Several unused clocks may be active. Turn them off. + */ +static void at91_periphclk_reset(void) +{ + unsigned long reg; + int i; + + reg = at91_sys_read(AT91_PMC_PCSR); + + for (i = 0; i < ARRAY_SIZE(clock_list); i++) { + struct clk *clk = clock_list[i]; + + if (clk->mode != pmc_periph_mode) + continue; + + if (clk->users > 0) + reg &= ~clk->pmc_mask; + } + + at91_sys_write(AT91_PMC_PCDR, reg); +} + int __init at91_clock_init(unsigned long main_clock) { unsigned tmp, freq, mckr; @@ -626,7 +697,6 @@ int __init at91_clock_init(unsigned long main_clock) */ at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) | AT91_PMC_USB96M; pllb.rate_hz = at91_pll_rate(&pllb, main_clock, at91_pllb_usb_init); - at91_sys_write(AT91_PMC_PCDR, (1 << AT91_ID_UHP) | (1 << AT91_ID_UDP)); at91_sys_write(AT91_PMC_SCDR, AT91_PMC_UHP | AT91_PMC_UDP); at91_sys_write(AT91_CKGR_PLLBR, 0); at91_sys_write(AT91_PMC_SCER, AT91_PMC_MCKUDP); @@ -640,11 +710,13 @@ int __init at91_clock_init(unsigned long main_clock) */ mckr = at91_sys_read(AT91_PMC_MCKR); mck.parent = clock_list[mckr & AT91_PMC_CSS]; - mck.parent->users++; freq = mck.parent->rate_hz; freq /= (1 << ((mckr >> 2) & 3)); /* prescale */ mck.rate_hz = freq / (1 + ((mckr >> 8) & 3)); /* mdiv */ + /* MCK and CPU clock are "always on" */ + clk_enable(&mck); + printk("Clocks: CPU %u MHz, master %u MHz, main %u.%03u MHz\n", freq / 1000000, (unsigned) mck.rate_hz / 1000000, (unsigned) main_clock / 1000000, @@ -663,19 +735,28 @@ int __init at91_clock_init(unsigned long main_clock) continue; pckr = at91_sys_read(AT91_PMC_PCKR(clk->id)); - parent = clock_list[pckr & 3]; + parent = clock_list[pckr & AT91_PMC_CSS]; clk->parent = parent; clk->rate_hz = parent->rate_hz / (1 << ((pckr >> 2) & 3)); + + if (clk->users == 0) { + /* not being used, so switch it off */ + at91_sys_write(AT91_PMC_SCDR, clk->pmc_mask); + } } #else - /* disable unused clocks */ + /* disable all programmable clocks */ at91_sys_write(AT91_PMC_SCDR, AT91_PMC_PCK0 | AT91_PMC_PCK1 | AT91_PMC_PCK2 | AT91_PMC_PCK3); -#endif /* CONFIG_AT91_PROGRAMMABLE_CLOCKS */ +#endif - /* FIXME several unused clocks may still be active... provide - * a CONFIG option to turn off all unused clocks at some point - * before driver init starts. - */ + /* enable the PIO clocks */ + clk_enable(&pioA_clk); + clk_enable(&pioB_clk); + clk_enable(&pioC_clk); + clk_enable(&pioD_clk); + + /* disable all other unused peripheral clocks */ + at91_periphclk_reset(); return 0; } -- cgit v1.2.3 From ab76fb13d73488ded53c87b77b1b5e38df2acf74 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 19 Jun 2006 13:24:32 +0100 Subject: [ARM] 3566/1: netX: register definitions Patch from Sascha Hauer This patch adds the register definitions for Hilscher's netX network processors. Signed-off-by: Robert Schwebel Signed-off-by: Sascha Hauer Signed-off-by: Russell King --- include/asm-arm/arch-netx/netx-regs.h | 410 ++++++++++++++++++++++++++++++++++ 1 file changed, 410 insertions(+) create mode 100644 include/asm-arm/arch-netx/netx-regs.h diff --git a/include/asm-arm/arch-netx/netx-regs.h b/include/asm-arm/arch-netx/netx-regs.h new file mode 100644 index 00000000000..8ab45bea83c --- /dev/null +++ b/include/asm-arm/arch-netx/netx-regs.h @@ -0,0 +1,410 @@ +/* + * include/asm-arm/arch-netx/netx-regs.h + * + * Copyright (c) 2005 Sascha Hauer , Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ASM_ARCH_NETX_REGS_H +#define __ASM_ARCH_NETX_REGS_H + +/* offsets relative to the beginning of the io space */ +#define NETX_OFS_SYSTEM 0x00000 +#define NETX_OFS_MEMCR 0x00100 +#define NETX_OFS_DPMAS 0x03000 +#define NETX_OFS_GPIO 0x00800 +#define NETX_OFS_PIO 0x00900 +#define NETX_OFS_UART0 0x00a00 +#define NETX_OFS_UART1 0x00a40 +#define NETX_OFS_UART2 0x00a80 +#define NETX_OF_MIIMU 0x00b00 +#define NETX_OFS_SPI 0x00c00 +#define NETX_OFS_I2C 0x00d00 +#define NETX_OFS_SYSTIME 0x01100 +#define NETX_OFS_RTC 0x01200 +#define NETX_OFS_EXTBUS 0x03600 +#define NETX_OFS_LCD 0x04000 +#define NETX_OFS_USB 0x20000 +#define NETX_OFS_XMAC0 0x60000 +#define NETX_OFS_XMAC1 0x61000 +#define NETX_OFS_XMAC2 0x62000 +#define NETX_OFS_XMAC3 0x63000 +#define NETX_OFS_XMAC(no) (0x60000 + (no) * 0x1000) +#define NETX_OFS_PFIFO 0x64000 +#define NETX_OFS_XPEC0 0x70000 +#define NETX_OFS_XPEC1 0x74000 +#define NETX_OFS_XPEC2 0x78000 +#define NETX_OFS_XPEC3 0x7c000 +#define NETX_OFS_XPEC(no) (0x70000 + (no) * 0x4000) +#define NETX_OFS_VIC 0xff000 + +/* physical addresses */ +#define NETX_PA_SYSTEM (NETX_IO_PHYS + NETX_OFS_SYSTEM) +#define NETX_PA_MEMCR (NETX_IO_PHYS + NETX_OFS_MEMCR) +#define NETX_PA_DPMAS (NETX_IO_PHYS + NETX_OFS_DPMAS) +#define NETX_PA_GPIO (NETX_IO_PHYS + NETX_OFS_GPIO) +#define NETX_PA_PIO (NETX_IO_PHYS + NETX_OFS_PIO) +#define NETX_PA_UART0 (NETX_IO_PHYS + NETX_OFS_UART0) +#define NETX_PA_UART1 (NETX_IO_PHYS + NETX_OFS_UART1) +#define NETX_PA_UART2 (NETX_IO_PHYS + NETX_OFS_UART2) +#define NETX_PA_MIIMU (NETX_IO_PHYS + NETX_OF_MIIMU) +#define NETX_PA_SPI (NETX_IO_PHYS + NETX_OFS_SPI) +#define NETX_PA_I2C (NETX_IO_PHYS + NETX_OFS_I2C) +#define NETX_PA_SYSTIME (NETX_IO_PHYS + NETX_OFS_SYSTIME) +#define NETX_PA_RTC (NETX_IO_PHYS + NETX_OFS_RTC) +#define NETX_PA_EXTBUS (NETX_IO_PHYS + NETX_OFS_EXTBUS) +#define NETX_PA_LCD (NETX_IO_PHYS + NETX_OFS_LCD) +#define NETX_PA_USB (NETX_IO_PHYS + NETX_OFS_USB) +#define NETX_PA_XMAC0 (NETX_IO_PHYS + NETX_OFS_XMAC0) +#define NETX_PA_XMAC1 (NETX_IO_PHYS + NETX_OFS_XMAC1) +#define NETX_PA_XMAC2 (NETX_IO_PHYS + NETX_OFS_XMAC2) +#define NETX_PA_XMAC3 (NETX_IO_PHYS + NETX_OFS_XMAC3) +#define NETX_PA_XMAC(no) (NETX_IO_PHYS + NETX_OFS_XMAC(no)) +#define NETX_PA_PFIFO (NETX_IO_PHYS + NETX_OFS_PFIFO) +#define NETX_PA_XPEC0 (NETX_IO_PHYS + NETX_OFS_XPEC0) +#define NETX_PA_XPEC1 (NETX_IO_PHYS + NETX_OFS_XPEC1) +#define NETX_PA_XPEC2 (NETX_IO_PHYS + NETX_OFS_XPEC2) +#define NETX_PA_XPEC3 (NETX_IO_PHYS + NETX_OFS_XPEC3) +#define NETX_PA_XPEC(no) (NETX_IO_PHYS + NETX_OFS_XPEC(no)) +#define NETX_PA_VIC (NETX_IO_PHYS + NETX_OFS_VIC) + +/* virual addresses */ +#define NETX_VA_SYSTEM (NETX_IO_VIRT + NETX_OFS_SYSTEM) +#define NETX_VA_MEMCR (NETX_IO_VIRT + NETX_OFS_MEMCR) +#define NETX_VA_DPMAS (NETX_IO_VIRT + NETX_OFS_DPMAS) +#define NETX_VA_GPIO (NETX_IO_VIRT + NETX_OFS_GPIO) +#define NETX_VA_PIO (NETX_IO_VIRT + NETX_OFS_PIO) +#define NETX_VA_UART0 (NETX_IO_VIRT + NETX_OFS_UART0) +#define NETX_VA_UART1 (NETX_IO_VIRT + NETX_OFS_UART1) +#define NETX_VA_UART2 (NETX_IO_VIRT + NETX_OFS_UART2) +#define NETX_VA_MIIMU (NETX_IO_VIRT + NETX_OF_MIIMU) +#define NETX_VA_SPI (NETX_IO_VIRT + NETX_OFS_SPI) +#define NETX_VA_I2C (NETX_IO_VIRT + NETX_OFS_I2C) +#define NETX_VA_SYSTIME (NETX_IO_VIRT + NETX_OFS_SYSTIME) +#define NETX_VA_RTC (NETX_IO_VIRT + NETX_OFS_RTC) +#define NETX_VA_EXTBUS (NETX_IO_VIRT + NETX_OFS_EXTBUS) +#define NETX_VA_LCD (NETX_IO_VIRT + NETX_OFS_LCD) +#define NETX_VA_USB (NETX_IO_VIRT + NETX_OFS_USB) +#define NETX_VA_XMAC0 (NETX_IO_VIRT + NETX_OFS_XMAC0) +#define NETX_VA_XMAC1 (NETX_IO_VIRT + NETX_OFS_XMAC1) +#define NETX_VA_XMAC2 (NETX_IO_VIRT + NETX_OFS_XMAC2) +#define NETX_VA_XMAC3 (NETX_IO_VIRT + NETX_OFS_XMAC3) +#define NETX_VA_XMAC(no) (NETX_IO_VIRT + NETX_OFS_XMAC(no)) +#define NETX_VA_PFIFO (NETX_IO_VIRT + NETX_OFS_PFIFO) +#define NETX_VA_XPEC0 (NETX_IO_VIRT + NETX_OFS_XPEC0) +#define NETX_VA_XPEC1 (NETX_IO_VIRT + NETX_OFS_XPEC1) +#define NETX_VA_XPEC2 (NETX_IO_VIRT + NETX_OFS_XPEC2) +#define NETX_VA_XPEC3 (NETX_IO_VIRT + NETX_OFS_XPEC3) +#define NETX_VA_XPEC(no) (NETX_IO_VIRT + NETX_OFS_XPEC(no)) +#define NETX_VA_VIC (NETX_IO_VIRT + NETX_OFS_VIC) + +/********************************* + * System functions * + *********************************/ + +/* Registers */ +#define NETX_SYSTEM_REG(ofs) __io(NETX_VA_SYSTEM + (ofs)) +#define NETX_SYSTEM_BOO_SR NETX_SYSTEM_REG(0x00) +#define NETX_SYSTEM_IOC_CR NETX_SYSTEM_REG(0x04) +#define NETX_SYSTEM_IOC_MR NETX_SYSTEM_REG(0x08) + +/* FIXME: Docs are not consistent */ +#define NETX_SYSTEM_RES_CR NETX_SYSTEM_REG(0x08) +/* #define NETX_SYSTEM_RES_CR NETX_SYSTEM_REG(0x0c) */ + +#define NETX_SYSTEM_PHY_CONTROL NETX_SYSTEM_REG(0x10) +#define NETX_SYSTEM_REV NETX_SYSTEM_REG(0x34) +#define NETX_SYSTEM_IOC_ACCESS_KEY NETX_SYSTEM_REG(0x70) +#define NETX_SYSTEM_WDG_TR NETX_SYSTEM_REG(0x200) +#define NETX_SYSTEM_WDG_CTR NETX_SYSTEM_REG(0x204) +#define NETX_SYSTEM_WDG_IRQ_TIMEOUT NETX_SYSTEM_REG(0x208) +#define NETX_SYSTEM_WDG_RES_TIMEOUT NETX_SYSTEM_REG(0x20c) + +/* Bits */ +#define NETX_SYSTEM_RES_CR_RSTIN (1<<0) +#define NETX_SYSTEM_RES_CR_WDG_RES (1<<1) +#define NETX_SYSTEM_RES_CR_HOST_RES (1<<2) +#define NETX_SYSTEM_RES_CR_FIRMW_RES (1<<3) +#define NETX_SYSTEM_RES_CR_XPEC0_RES (1<<4) +#define NETX_SYSTEM_RES_CR_XPEC1_RES (1<<5) +#define NETX_SYSTEM_RES_CR_XPEC2_RES (1<<6) +#define NETX_SYSTEM_RES_CR_XPEC3_RES (1<<7) +#define NETX_SYSTEM_RES_CR_DIS_XPEC0_RES (1<<16) +#define NETX_SYSTEM_RES_CR_DIS_XPEC1_RES (1<<17) +#define NETX_SYSTEM_RES_CR_DIS_XPEC2_RES (1<<18) +#define NETX_SYSTEM_RES_CR_DIS_XPEC3_RES (1<<19) +#define NETX_SYSTEM_RES_CR_FIRMW_FLG0 (1<<20) +#define NETX_SYSTEM_RES_CR_FIRMW_FLG1 (1<<21) +#define NETX_SYSTEM_RES_CR_FIRMW_FLG2 (1<<22) +#define NETX_SYSTEM_RES_CR_FIRMW_FLG3 (1<<23) +#define NETX_SYSTEM_RES_CR_FIRMW_RES_EN (1<<24) +#define NETX_SYSTEM_RES_CR_RSTOUT (1<<25) +#define NETX_SYSTEM_RES_CR_EN_RSTOUT (1<<26) + +#define PHY_CONTROL_RESET (1<<31) +#define PHY_CONTROL_SIM_BYP (1<<30) +#define PHY_CONTROL_CLK_XLATIN (1<<29) +#define PHY_CONTROL_PHY1_EN (1<<21) +#define PHY_CONTROL_PHY1_NP_MSG_CODE +#define PHY_CONTROL_PHY1_AUTOMDIX (1<<17) +#define PHY_CONTROL_PHY1_FIXMODE (1<<16) +#define PHY_CONTROL_PHY1_MODE(mode) (((mode) & 0x7) << 13) +#define PHY_CONTROL_PHY0_EN (1<<12) +#define PHY_CONTROL_PHY0_NP_MSG_CODE +#define PHY_CONTROL_PHY0_AUTOMDIX (1<<8) +#define PHY_CONTROL_PHY0_FIXMODE (1<<7) +#define PHY_CONTROL_PHY0_MODE(mode) (((mode) & 0x7) << 4) +#define PHY_CONTROL_PHY_ADDRESS(adr) ((adr) & 0xf) + +#define PHY_MODE_10BASE_T_HALF 0 +#define PHY_MODE_10BASE_T_FULL 1 +#define PHY_MODE_100BASE_TX_FX_FULL 2 +#define PHY_MODE_100BASE_TX_FX_HALF 3 +#define PHY_MODE_100BASE_TX_HALF 4 +#define PHY_MODE_REPEATER 5 +#define PHY_MODE_POWER_DOWN 6 +#define PHY_MODE_ALL 7 + +/* Bits */ +#define VECT_CNTL_ENABLE (1 << 5) + +/******************************* + * GPIO and timer module * + *******************************/ + +/* Registers */ +#define NETX_GPIO_REG(ofs) __io(NETX_VA_GPIO + (ofs)) +#define NETX_GPIO_CFG(gpio) NETX_GPIO_REG(0x0 + ((gpio)<<2)) +#define NETX_GPIO_THRESHOLD_CAPTURE(gpio) NETX_GPIO_REG(0x40 + ((gpio)<<2)) +#define NETX_GPIO_COUNTER_CTRL(counter) NETX_GPIO_REG(0x80 + ((counter)<<2)) +#define NETX_GPIO_COUNTER_MAX(counter) NETX_GPIO_REG(0x94 + ((counter)<<2)) +#define NETX_GPIO_COUNTER_CURRENT(counter) NETX_GPIO_REG(0xa8 + ((counter)<<2)) +#define NETX_GPIO_IRQ_ENABLE NETX_GPIO_REG(0xbc) +#define NETX_GPIO_IRQ_DISABLE NETX_GPIO_REG(0xc0) +#define NETX_GPIO_SYSTIME_NS_CMP NETX_GPIO_REG(0xc4) +#define NETX_GPIO_LINE NETX_GPIO_REG(0xc8) +#define NETX_GPIO_IRQ NETX_GPIO_REG(0xd0) + +/* Bits */ +#define NETX_GPIO_CFG_IOCFG_GP_INPUT (0x0) +#define NETX_GPIO_CFG_IOCFG_GP_OUTPUT (0x1) +#define NETX_GPIO_CFG_IOCFG_GP_UART (0x2) +#define NETX_GPIO_CFG_INV (1<<2) +#define NETX_GPIO_CFG_MODE_INPUT_READ (0<<3) +#define NETX_GPIO_CFG_MODE_INPUT_CAPTURE_CONT_RISING (1<<3) +#define NETX_GPIO_CFG_MODE_INPUT_CAPTURE_ONCE_RISING (2<<3) +#define NETX_GPIO_CFG_MODE_INPUT_CAPTURE_HIGH_LEVEL (3<<3) +#define NETX_GPIO_CFG_COUNT_REF_COUNTER0 (0<<5) +#define NETX_GPIO_CFG_COUNT_REF_COUNTER1 (1<<5) +#define NETX_GPIO_CFG_COUNT_REF_COUNTER2 (2<<5) +#define NETX_GPIO_CFG_COUNT_REF_COUNTER3 (3<<5) +#define NETX_GPIO_CFG_COUNT_REF_COUNTER4 (4<<5) +#define NETX_GPIO_CFG_COUNT_REF_SYSTIME (7<<5) + +#define NETX_GPIO_COUNTER_CTRL_RUN (1<<0) +#define NETX_GPIO_COUNTER_CTRL_SYM (1<<1) +#define NETX_GPIO_COUNTER_CTRL_ONCE (1<<2) +#define NETX_GPIO_COUNTER_CTRL_IRQ_EN (1<<3) +#define NETX_GPIO_COUNTER_CTRL_CNT_EVENT (1<<4) +#define NETX_GPIO_COUNTER_CTRL_RST_EN (1<<5) +#define NETX_GPIO_COUNTER_CTRL_SEL_EVENT (1<<6) +#define NETX_GPIO_COUNTER_CTRL_GPIO_REF /* FIXME */ + +#define GPIO_BIT(gpio) (1<<(gpio)) +#define COUNTER_BIT(counter) ((1<<16)<<(counter)) + +/******************************* + * PIO * + *******************************/ + +/* Registers */ +#define NETX_PIO_REG(ofs) __io(NETX_VA_PIO + (ofs)) +#define NETX_PIO_INPIO NETX_PIO_REG(0x0) +#define NETX_PIO_OUTPIO NETX_PIO_REG(0x4) +#define NETX_PIO_OEPIO NETX_PIO_REG(0x8) + +/******************************* + * MII Unit * + *******************************/ + +/* Registers */ +#define NETX_MIIMU __io(NETX_VA_MIIMU) + +/* Bits */ +#define MIIMU_SNRDY (1<<0) +#define MIIMU_PREAMBLE (1<<1) +#define MIIMU_OPMODE_WRITE (1<<2) +#define MIIMU_MDC_PERIOD (1<<3) +#define MIIMU_PHY_NRES (1<<4) +#define MIIMU_RTA (1<<5) +#define MIIMU_REGADDR(adr) (((adr) & 0x1f) << 6) +#define MIIMU_PHYADDR(adr) (((adr) & 0x1f) << 11) +#define MIIMU_DATA(data) (((data) & 0xffff) << 16) + +/******************************* + * xmac / xpec * + *******************************/ + +/* XPEC register offsets relative to NETX_VA_XPEC(no) */ +#define NETX_XPEC_R0_OFS 0x00 +#define NETX_XPEC_R1_OFS 0x04 +#define NETX_XPEC_R2_OFS 0x08 +#define NETX_XPEC_R3_OFS 0x0c +#define NETX_XPEC_R4_OFS 0x10 +#define NETX_XPEC_R5_OFS 0x14 +#define NETX_XPEC_R6_OFS 0x18 +#define NETX_XPEC_R7_OFS 0x1c +#define NETX_XPEC_RANGE01_OFS 0x20 +#define NETX_XPEC_RANGE23_OFS 0x24 +#define NETX_XPEC_RANGE45_OFS 0x28 +#define NETX_XPEC_RANGE67_OFS 0x2c +#define NETX_XPEC_PC_OFS 0x48 +#define NETX_XPEC_TIMER_OFS(timer) (0x30 + ((timer)<<2)) +#define NETX_XPEC_IRQ_OFS 0x8c +#define NETX_XPEC_SYSTIME_NS_OFS 0x90 +#define NETX_XPEC_FIFO_DATA_OFS 0x94 +#define NETX_XPEC_SYSTIME_S_OFS 0x98 +#define NETX_XPEC_ADC_OFS 0x9c +#define NETX_XPEC_URX_COUNT_OFS 0x40 +#define NETX_XPEC_UTX_COUNT_OFS 0x44 +#define NETX_XPEC_PC_OFS 0x48 +#define NETX_XPEC_ZERO_OFS 0x4c +#define NETX_XPEC_STATCFG_OFS 0x50 +#define NETX_XPEC_EC_MASKA_OFS 0x54 +#define NETX_XPEC_EC_MASKB_OFS 0x58 +#define NETX_XPEC_EC_MASK0_OFS 0x5c +#define NETX_XPEC_EC_MASK8_OFS 0x7c +#define NETX_XPEC_EC_MASK9_OFS 0x80 +#define NETX_XPEC_XPU_HOLD_PC_OFS 0x100 +#define NETX_XPEC_RAM_START_OFS 0x2000 + +/* Bits */ +#define XPU_HOLD_PC (1<<0) + +/* XMAC register offsets relative to NETX_VA_XMAC(no) */ +#define NETX_XMAC_RPU_PROGRAM_START_OFS 0x000 +#define NETX_XMAC_RPU_PROGRAM_END_OFS 0x3ff +#define NETX_XMAC_TPU_PROGRAM_START_OFS 0x400 +#define NETX_XMAC_TPU_PROGRAM_END_OFS 0x7ff +#define NETX_XMAC_RPU_HOLD_PC_OFS 0xa00 +#define NETX_XMAC_TPU_HOLD_PC_OFS 0xa04 +#define NETX_XMAC_STATUS_SHARED0_OFS 0x840 +#define NETX_XMAC_CONFIG_SHARED0_OFS 0x844 +#define NETX_XMAC_STATUS_SHARED1_OFS 0x848 +#define NETX_XMAC_CONFIG_SHARED1_OFS 0x84c +#define NETX_XMAC_STATUS_SHARED2_OFS 0x850 +#define NETX_XMAC_CONFIG_SHARED2_OFS 0x854 +#define NETX_XMAC_STATUS_SHARED3_OFS 0x858 +#define NETX_XMAC_CONFIG_SHARED3_OFS 0x85c + +#define RPU_HOLD_PC (1<<15) +#define TPU_HOLD_PC (1<<15) + +/******************************* + * Pointer FIFO * + *******************************/ + +/* Registers */ +#define NETX_PFIFO_REG(ofs) __io(NETX_VA_PFIFO + (ofs)) +#define NETX_PFIFO_BASE(pfifo) NETX_PFIFO_REG(0x00 + ((pfifo)<<2)) +#define NETX_PFIFO_BORDER_BASE(pfifo) NETX_PFIFO_REG(0x80 + ((pfifo)<<2)) +#define NETX_PFIFO_RESET NETX_PFIFO_REG(0x100) +#define NETX_PFIFO_FULL NETX_PFIFO_REG(0x104) +#define NETX_PFIFO_EMPTY NETX_PFIFO_REG(0x108) +#define NETX_PFIFO_OVEFLOW NETX_PFIFO_REG(0x10c) +#define NETX_PFIFO_UNDERRUN NETX_PFIFO_REG(0x110) +#define NETX_PFIFO_FILL_LEVEL(pfifo) NETX_PFIFO_REG(0x180 + ((pfifo)<<2)) +#define NETX_PFIFO_XPEC_ISR(xpec) NETX_PFIFO_REG(0x400 + ((xpec) << 2)) + +/******************************* + * Dual Port Memory * + *******************************/ + +/* Registers */ +#define NETX_DPMAS_REG(ofs) __io(NETX_VA_DPMAS + (ofs)) +#define NETX_DPMAS_SYS_STAT NETX_DPMAS_REG(0x4d8) +#define NETX_DPMAS_INT_STAT NETX_DPMAS_REG(0x4e0) +#define NETX_DPMAS_INT_EN NETX_DPMAS_REG(0x4f0) +#define NETX_DPMAS_IF_CONF0 NETX_DPMAS_REG(0x608) +#define NETX_DPMAS_IF_CONF1 NETX_DPMAS_REG(0x60c) +#define NETX_DPMAS_EXT_CONFIG(cs) NETX_DPMAS_REG(0x610 + 4 * (cs)) +#define NETX_DPMAS_IO_MODE0 NETX_DPMAS_REG(0x620) /* I/O 32..63 */ +#define NETX_DPMAS_DRV_EN0 NETX_DPMAS_REG(0x624) +#define NETX_DPMAS_DATA0 NETX_DPMAS_REG(0x628) +#define NETX_DPMAS_IO_MODE1 NETX_DPMAS_REG(0x630) /* I/O 64..84 */ +#define NETX_DPMAS_DRV_EN1 NETX_DPMAS_REG(0x634) +#define NETX_DPMAS_DATA1 NETX_DPMAS_REG(0x638) + +/* Bits */ +#define NETX_DPMAS_INT_EN_GLB_EN (1<<31) +#define NETX_DPMAS_INT_EN_MEM_LCK (1<<30) +#define NETX_DPMAS_INT_EN_WDG (1<<29) +#define NETX_DPMAS_INT_EN_PIO72 (1<<28) +#define NETX_DPMAS_INT_EN_PIO47 (1<<27) +#define NETX_DPMAS_INT_EN_PIO40 (1<<26) +#define NETX_DPMAS_INT_EN_PIO36 (1<<25) +#define NETX_DPMAS_INT_EN_PIO35 (1<<24) + +#define NETX_DPMAS_IF_CONF0_HIF_DISABLED (0<<28) +#define NETX_DPMAS_IF_CONF0_HIF_EXT_BUS (1<<28) +#define NETX_DPMAS_IF_CONF0_HIF_UP_8BIT (2<<28) +#define NETX_DPMAS_IF_CONF0_HIF_UP_16BIT (3<<28) +#define NETX_DPMAS_IF_CONF0_HIF_IO (4<<28) +#define NETX_DPMAS_IF_CONF0_WAIT_DRV_PP (1<<14) +#define NETX_DPMAS_IF_CONF0_WAIT_DRV_OD (2<<14) +#define NETX_DPMAS_IF_CONF0_WAIT_DRV_TRI (3<<14) + +#define NETX_DPMAS_IF_CONF1_IRQ_POL_PIO35 (1<<26) +#define NETX_DPMAS_IF_CONF1_IRQ_POL_PIO36 (1<<27) +#define NETX_DPMAS_IF_CONF1_IRQ_POL_PIO40 (1<<28) +#define NETX_DPMAS_IF_CONF1_IRQ_POL_PIO47 (1<<29) +#define NETX_DPMAS_IF_CONF1_IRQ_POL_PIO72 (1<<30) + +#define NETX_EXT_CONFIG_TALEWIDTH(x) (((x) & 0x7) << 29) +#define NETX_EXT_CONFIG_TADRHOLD(x) (((x) & 0x7) << 26) +#define NETX_EXT_CONFIG_TCSON(x) (((x) & 0x7) << 23) +#define NETX_EXT_CONFIG_TRDON(x) (((x) & 0x7) << 20) +#define NETX_EXT_CONFIG_TWRON(x) (((x) & 0x7) << 17) +#define NETX_EXT_CONFIG_TWROFF(x) (((x) & 0x1f) << 12) +#define NETX_EXT_CONFIG_TRDWRCYC(x) (((x) & 0x1f) << 7) +#define NETX_EXT_CONFIG_WAIT_POL (1<<6) +#define NETX_EXT_CONFIG_WAIT_EN (1<<5) +#define NETX_EXT_CONFIG_NRD_MODE (1<<4) +#define NETX_EXT_CONFIG_DS_MODE (1<<3) +#define NETX_EXT_CONFIG_NWR_MODE (1<<2) +#define NETX_EXT_CONFIG_16BIT (1<<1) +#define NETX_EXT_CONFIG_CS_ENABLE (1<<0) + +#define NETX_DPMAS_IO_MODE0_WRL (1<<13) +#define NETX_DPMAS_IO_MODE0_WAIT (1<<14) +#define NETX_DPMAS_IO_MODE0_READY (1<<15) +#define NETX_DPMAS_IO_MODE0_CS0 (1<<19) +#define NETX_DPMAS_IO_MODE0_EXTRD (1<<20) + +#define NETX_DPMAS_IO_MODE1_CS2 (1<<15) +#define NETX_DPMAS_IO_MODE1_CS1 (1<<16) +#define NETX_DPMAS_IO_MODE1_SAMPLE_NPOR (0<<30) +#define NETX_DPMAS_IO_MODE1_SAMPLE_100MHZ (1<<30) +#define NETX_DPMAS_IO_MODE1_SAMPLE_NPIO36 (2<<30) +#define NETX_DPMAS_IO_MODE1_SAMPLE_PIO36 (3<<30) + +/******************************* + * I2C * + *******************************/ +#define NETX_I2C_REG(ofs) __io(NETX_VA_I2C, (ofs)) +#define NETX_I2C_CTRL NETX_I2C_REG(0x0) +#define NETX_I2C_DATA NETX_I2C_REG(0x4) + +#endif /* __ASM_ARCH_NETX_REGS_H */ -- cgit v1.2.3 From f8441e13449638e9fc3c160c35ada3b6f1f8d9c0 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 19 Jun 2006 13:29:07 +0100 Subject: [ARM] 3571/1: netX: serial driver for Hilscher netX Patch from Sascha Hauer This patch adds the serial driver for Hilscher's netX network processors. Signed-off-by: Robert Schwebel Signed-off-by: Sascha Hauer Signed-off-by: Russell King --- drivers/serial/Kconfig | 19 ++ drivers/serial/Makefile | 1 + drivers/serial/netx-serial.c | 749 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 769 insertions(+) create mode 100644 drivers/serial/netx-serial.c diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 7d22dc0478d..5fff79e7127 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -936,4 +936,23 @@ config SERIAL_SGI_IOC3 If you have an SGI Altix with an IOC3 serial card, say Y or M. Otherwise, say N. +config SERIAL_NETX + bool "NetX serial port support" + depends on ARM && ARCH_NETX + select SERIAL_CORE + help + If you have a machine based on a Hilscher NetX SoC you + can enable its onboard serial port by enabling this option. + + To compile this driver as a module, choose M here: the + module will be called netx-serial. + +config SERIAL_NETX_CONSOLE + bool "Console on NetX serial port" + depends on SERIAL_NETX + select SERIAL_CORE_CONSOLE + help + If you have enabled the serial port on the Motorola IMX + CPU you can make it the console by answering Y to this option. + endmenu diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 0a71bf68a03..927faee0362 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -55,3 +55,4 @@ obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o obj-$(CONFIG_SERIAL_SGI_IOC4) += ioc4_serial.o obj-$(CONFIG_SERIAL_SGI_IOC3) += ioc3_serial.o obj-$(CONFIG_SERIAL_AT91) += at91_serial.o +obj-$(CONFIG_SERIAL_NETX) += netx-serial.o diff --git a/drivers/serial/netx-serial.c b/drivers/serial/netx-serial.c new file mode 100644 index 00000000000..c1adc9e4b23 --- /dev/null +++ b/drivers/serial/netx-serial.c @@ -0,0 +1,749 @@ +/* + * drivers/serial/netx-serial.c + * + * Copyright (c) 2005 Sascha Hauer , Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#if defined(CONFIG_SERIAL_NETX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* We've been assigned a range on the "Low-density serial ports" major */ +#define SERIAL_NX_MAJOR 204 +#define MINOR_START 170 + +#ifdef CONFIG_SERIAL_NETX_CONSOLE + +enum uart_regs { + UART_DR = 0x00, + UART_SR = 0x04, + UART_LINE_CR = 0x08, + UART_BAUDDIV_MSB = 0x0c, + UART_BAUDDIV_LSB = 0x10, + UART_CR = 0x14, + UART_FR = 0x18, + UART_IIR = 0x1c, + UART_ILPR = 0x20, + UART_RTS_CR = 0x24, + UART_RTS_LEAD = 0x28, + UART_RTS_TRAIL = 0x2c, + UART_DRV_ENABLE = 0x30, + UART_BRM_CR = 0x34, + UART_RXFIFO_IRQLEVEL = 0x38, + UART_TXFIFO_IRQLEVEL = 0x3c, +}; + +#define SR_FE (1<<0) +#define SR_PE (1<<1) +#define SR_BE (1<<2) +#define SR_OE (1<<3) + +#define LINE_CR_BRK (1<<0) +#define LINE_CR_PEN (1<<1) +#define LINE_CR_EPS (1<<2) +#define LINE_CR_STP2 (1<<3) +#define LINE_CR_FEN (1<<4) +#define LINE_CR_5BIT (0<<5) +#define LINE_CR_6BIT (1<<5) +#define LINE_CR_7BIT (2<<5) +#define LINE_CR_8BIT (3<<5) +#define LINE_CR_BITS_MASK (3<<5) + +#define CR_UART_EN (1<<0) +#define CR_SIREN (1<<1) +#define CR_SIRLP (1<<2) +#define CR_MSIE (1<<3) +#define CR_RIE (1<<4) +#define CR_TIE (1<<5) +#define CR_RTIE (1<<6) +#define CR_LBE (1<<7) + +#define FR_CTS (1<<0) +#define FR_DSR (1<<1) +#define FR_DCD (1<<2) +#define FR_BUSY (1<<3) +#define FR_RXFE (1<<4) +#define FR_TXFF (1<<5) +#define FR_RXFF (1<<6) +#define FR_TXFE (1<<7) + +#define IIR_MIS (1<<0) +#define IIR_RIS (1<<1) +#define IIR_TIS (1<<2) +#define IIR_RTIS (1<<3) +#define IIR_MASK 0xf + +#define RTS_CR_AUTO (1<<0) +#define RTS_CR_RTS (1<<1) +#define RTS_CR_COUNT (1<<2) +#define RTS_CR_MOD2 (1<<3) +#define RTS_CR_RTS_POL (1<<4) +#define RTS_CR_CTS_CTR (1<<5) +#define RTS_CR_CTS_POL (1<<6) +#define RTS_CR_STICK (1<<7) + +#define UART_PORT_SIZE 0x40 +#define DRIVER_NAME "netx-uart" + +struct netx_port { + struct uart_port port; +}; + +static void netx_stop_tx(struct uart_port *port) +{ + unsigned int val; + val = readl(port->membase + UART_CR); + writel(val & ~CR_TIE, port->membase + UART_CR); +} + +static void netx_stop_rx(struct uart_port *port) +{ + unsigned int val; + val = readl(port->membase + UART_CR); + writel(val & ~CR_RIE, port->membase + UART_CR); +} + +static void netx_enable_ms(struct uart_port *port) +{ + unsigned int val; + val = readl(port->membase + UART_CR); + writel(val | CR_MSIE, port->membase + UART_CR); +} + +static inline void netx_transmit_buffer(struct uart_port *port) +{ + struct circ_buf *xmit = &port->info->xmit; + + if (port->x_char) { + writel(port->x_char, port->membase + UART_DR); + port->icount.tx++; + port->x_char = 0; + return; + } + + if (uart_tx_stopped(port) || uart_circ_empty(xmit)) { + netx_stop_tx(port); + return; + } + + do { + /* send xmit->buf[xmit->tail] + * out the port here */ + writel(xmit->buf[xmit->tail], port->membase + UART_DR); + xmit->tail = (xmit->tail + 1) & + (UART_XMIT_SIZE - 1); + port->icount.tx++; + if (uart_circ_empty(xmit)) + break; + } while (!(readl(port->membase + UART_FR) & FR_TXFF)); + + if (uart_circ_empty(xmit)) + netx_stop_tx(port); +} + +static void netx_start_tx(struct uart_port *port) +{ + writel( + readl(port->membase + UART_CR) | CR_TIE, port->membase + UART_CR); + + if (!(readl(port->membase + UART_FR) & FR_TXFF)) + netx_transmit_buffer(port); +} + +static unsigned int netx_tx_empty(struct uart_port *port) +{ + return readl(port->membase + UART_FR) & FR_BUSY ? 0 : TIOCSER_TEMT; +} + +static void netx_txint(struct uart_port *port) +{ + struct circ_buf *xmit = &port->info->xmit; + + if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { + netx_stop_tx(port); + return; + } + + netx_transmit_buffer(port); + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(port); +} + +static void netx_rxint(struct uart_port *port, struct pt_regs *regs) +{ + unsigned char rx, flg, status; + struct tty_struct *tty = port->info->tty; + + while (!(readl(port->membase + UART_FR) & FR_RXFE)) { + rx = readl(port->membase + UART_DR); + flg = TTY_NORMAL; + port->icount.rx++; + status = readl(port->membase + UART_SR); + if (status & SR_BE) { + writel(0, port->membase + UART_SR); + if (uart_handle_break(port)) + continue; + } + + if (unlikely(status & (SR_FE | SR_PE | SR_OE))) { + + if (status & SR_PE) + port->icount.parity++; + else if (status & SR_FE) + port->icount.frame++; + if (status & SR_OE) + port->icount.overrun++; + + status &= port->read_status_mask; + + if (status & SR_BE) + flg = TTY_BREAK; + else if (status & SR_PE) + flg = TTY_PARITY; + else if (status & SR_FE) + flg = TTY_FRAME; + } + + if (uart_handle_sysrq_char(port, rx, regs)) + continue; + + uart_insert_char(port, status, SR_OE, rx, flg); + } + + tty_flip_buffer_push(tty); + return; +} + +static irqreturn_t netx_int(int irq, void *dev_id, struct pt_regs *regs) +{ + struct uart_port *port = (struct uart_port *)dev_id; + unsigned long flags; + unsigned char status; + + spin_lock_irqsave(&port->lock,flags); + + status = readl(port->membase + UART_IIR) & IIR_MASK; + while (status) { + if (status & IIR_RIS) + netx_rxint(port, regs); + if (status & IIR_TIS) + netx_txint(port); + if (status & IIR_MIS) { + if (readl(port->membase + UART_FR) & FR_CTS) + uart_handle_cts_change(port, 1); + else + uart_handle_cts_change(port, 0); + } + writel(0, port->membase + UART_IIR); + status = readl(port->membase + UART_IIR) & IIR_MASK; + } + + spin_unlock_irqrestore(&port->lock,flags); + return IRQ_HANDLED; +} + +static unsigned int netx_get_mctrl(struct uart_port *port) +{ + unsigned int ret = TIOCM_DSR | TIOCM_CAR; + + if (readl(port->membase + UART_FR) & FR_CTS) + ret |= TIOCM_CTS; + + return ret; +} + +static void netx_set_mctrl(struct uart_port *port, unsigned int mctrl) +{ + unsigned int val; + + if (mctrl & TIOCM_RTS) { + val = readl(port->membase + UART_RTS_CR); + writel(val | RTS_CR_RTS, port->membase + UART_RTS_CR); + } +} + +static void netx_break_ctl(struct uart_port *port, int break_state) +{ + unsigned int line_cr; + spin_lock_irq(&port->lock); + + line_cr = readl(port->membase + UART_LINE_CR); + if (break_state != 0) + line_cr |= LINE_CR_BRK; + else + line_cr &= ~LINE_CR_BRK; + writel(line_cr, port->membase + UART_LINE_CR); + + spin_unlock_irq(&port->lock); +} + +static int netx_startup(struct uart_port *port) +{ + int ret; + + ret = request_irq(port->irq, netx_int, 0, + DRIVER_NAME, port); + if (ret) { + dev_err(port->dev, "unable to grab irq%d\n",port->irq); + goto exit; + } + + writel(readl(port->membase + UART_LINE_CR) | LINE_CR_FEN, + port->membase + UART_LINE_CR); + + writel(CR_MSIE | CR_RIE | CR_TIE | CR_RTIE | CR_UART_EN, + port->membase + UART_CR); + +exit: + return ret; +} + +static void netx_shutdown(struct uart_port *port) +{ + writel(0, port->membase + UART_CR) ; + + free_irq(port->irq, port); +} + +static void +netx_set_termios(struct uart_port *port, struct termios *termios, + struct termios *old) +{ + unsigned int baud, quot; + unsigned char old_cr; + unsigned char line_cr = LINE_CR_FEN; + unsigned char rts_cr = 0; + + switch (termios->c_cflag & CSIZE) { + case CS5: + line_cr |= LINE_CR_5BIT; + break; + case CS6: + line_cr |= LINE_CR_6BIT; + break; + case CS7: + line_cr |= LINE_CR_7BIT; + break; + case CS8: + line_cr |= LINE_CR_8BIT; + break; + } + + if (termios->c_cflag & CSTOPB) + line_cr |= LINE_CR_STP2; + + if (termios->c_cflag & PARENB) { + line_cr |= LINE_CR_PEN; + if (!(termios->c_cflag & PARODD)) + line_cr |= LINE_CR_EPS; + } + + if (termios->c_cflag & CRTSCTS) + rts_cr = RTS_CR_AUTO | RTS_CR_CTS_CTR | RTS_CR_RTS_POL; + + baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); + quot = baud * 4096; + quot /= 1000; + quot *= 256; + quot /= 100000; + + spin_lock_irq(&port->lock); + + uart_update_timeout(port, termios->c_cflag, baud); + + old_cr = readl(port->membase + UART_CR); + + /* disable interrupts */ + writel(old_cr & ~(CR_MSIE | CR_RIE | CR_TIE | CR_RTIE), + port->membase + UART_CR); + + /* drain transmitter */ + while (readl(port->membase + UART_FR) & FR_BUSY); + + /* disable UART */ + writel(old_cr & ~CR_UART_EN, port->membase + UART_CR); + + /* modem status interrupts */ + old_cr &= ~CR_MSIE; + if (UART_ENABLE_MS(port, termios->c_cflag)) + old_cr |= CR_MSIE; + + writel((quot>>8) & 0xff, port->membase + UART_BAUDDIV_MSB); + writel(quot & 0xff, port->membase + UART_BAUDDIV_LSB); + writel(line_cr, port->membase + UART_LINE_CR); + + writel(rts_cr, port->membase + UART_RTS_CR); + + /* + * Characters to ignore + */ + port->ignore_status_mask = 0; + if (termios->c_iflag & IGNPAR) + port->ignore_status_mask |= SR_PE; + if (termios->c_iflag & IGNBRK) { + port->ignore_status_mask |= SR_BE; + /* + * If we're ignoring parity and break indicators, + * ignore overruns too (for real raw support). + */ + if (termios->c_iflag & IGNPAR) + port->ignore_status_mask |= SR_PE; + } + + port->read_status_mask = 0; + if (termios->c_iflag & (BRKINT | PARMRK)) + port->read_status_mask |= SR_BE; + if (termios->c_iflag & INPCK) + port->read_status_mask |= SR_PE | SR_FE; + + writel(old_cr, port->membase + UART_CR); + + spin_unlock_irq(&port->lock); +} + +static const char *netx_type(struct uart_port *port) +{ + return port->type == PORT_NETX ? "NETX" : NULL; +} + +static void netx_release_port(struct uart_port *port) +{ + release_mem_region(port->mapbase, UART_PORT_SIZE); +} + +static int netx_request_port(struct uart_port *port) +{ + return request_mem_region(port->mapbase, UART_PORT_SIZE, + DRIVER_NAME) != NULL ? 0 : -EBUSY; +} + +static void netx_config_port(struct uart_port *port, int flags) +{ + if (flags & UART_CONFIG_TYPE && netx_request_port(port) == 0) + port->type = PORT_NETX; +} + +static int +netx_verify_port(struct uart_port *port, struct serial_struct *ser) +{ + int ret = 0; + + if (ser->type != PORT_UNKNOWN && ser->type != PORT_NETX) + ret = -EINVAL; + + return ret; +} + +static struct uart_ops netx_pops = { + .tx_empty = netx_tx_empty, + .set_mctrl = netx_set_mctrl, + .get_mctrl = netx_get_mctrl, + .stop_tx = netx_stop_tx, + .start_tx = netx_start_tx, + .stop_rx = netx_stop_rx, + .enable_ms = netx_enable_ms, + .break_ctl = netx_break_ctl, + .startup = netx_startup, + .shutdown = netx_shutdown, + .set_termios = netx_set_termios, + .type = netx_type, + .release_port = netx_release_port, + .request_port = netx_request_port, + .config_port = netx_config_port, + .verify_port = netx_verify_port, +}; + +static struct netx_port netx_ports[] = { + { + .port = { + .type = PORT_NETX, + .iotype = UPIO_MEM, + .membase = (char __iomem *)io_p2v(NETX_PA_UART0), + .mapbase = NETX_PA_UART0, + .irq = NETX_IRQ_UART0, + .uartclk = 100000000, + .fifosize = 16, + .flags = UPF_BOOT_AUTOCONF, + .ops = &netx_pops, + .line = 0, + }, + }, { + .port = { + .type = PORT_NETX, + .iotype = UPIO_MEM, + .membase = (char __iomem *)io_p2v(NETX_PA_UART1), + .mapbase = NETX_PA_UART1, + .irq = NETX_IRQ_UART1, + .uartclk = 100000000, + .fifosize = 16, + .flags = UPF_BOOT_AUTOCONF, + .ops = &netx_pops, + .line = 1, + }, + }, { + .port = { + .type = PORT_NETX, + .iotype = UPIO_MEM, + .membase = (char __iomem *)io_p2v(NETX_PA_UART2), + .mapbase = NETX_PA_UART2, + .irq = NETX_IRQ_UART2, + .uartclk = 100000000, + .fifosize = 16, + .flags = UPF_BOOT_AUTOCONF, + .ops = &netx_pops, + .line = 2, + }, + } +}; + +static void netx_console_putchar(struct uart_port *port, int ch) +{ + while (readl(port->membase + UART_FR) & FR_BUSY); + writel(ch, port->membase + UART_DR); +} + +static void +netx_console_write(struct console *co, const char *s, unsigned int count) +{ + struct uart_port *port = &netx_ports[co->index].port; + unsigned char cr_save; + + cr_save = readl(port->membase + UART_CR); + writel(cr_save | CR_UART_EN, port->membase + UART_CR); + + uart_console_write(port, s, count, netx_console_putchar); + + while (readl(port->membase + UART_FR) & FR_BUSY); + writel(cr_save, port->membase + UART_CR); +} + +static void __init +netx_console_get_options(struct uart_port *port, int *baud, + int *parity, int *bits, int *flow) +{ + unsigned char line_cr; + + *baud = (readl(port->membase + UART_BAUDDIV_MSB) << 8) | + readl(port->membase + UART_BAUDDIV_LSB); + *baud *= 1000; + *baud /= 4096; + *baud *= 1000; + *baud /= 256; + *baud *= 100; + + line_cr = readl(port->membase + UART_LINE_CR); + *parity = 'n'; + if (line_cr & LINE_CR_PEN) { + if (line_cr & LINE_CR_EPS) + *parity = 'e'; + else + *parity = 'o'; + } + + switch (line_cr & LINE_CR_BITS_MASK) { + case LINE_CR_8BIT: + *bits = 8; + break; + case LINE_CR_7BIT: + *bits = 7; + break; + case LINE_CR_6BIT: + *bits = 6; + break; + case LINE_CR_5BIT: + *bits = 5; + break; + } + + if (readl(port->membase + UART_RTS_CR) & RTS_CR_AUTO) + *flow = 'r'; +} + +static int __init +netx_console_setup(struct console *co, char *options) +{ + struct netx_port *sport; + int baud = 9600; + int bits = 8; + int parity = 'n'; + int flow = 'n'; + + /* + * Check whether an invalid uart number has been specified, and + * if so, search for the first available port that does have + * console support. + */ + if (co->index == -1 || co->index >= ARRAY_SIZE(netx_ports)) + co->index = 0; + sport = &netx_ports[co->index]; + + if (options) { + uart_parse_options(options, &baud, &parity, &bits, &flow); + } else { + /* if the UART is enabled, assume it has been correctly setup + * by the bootloader and get the options + */ + if (readl(sport->port.membase + UART_CR) & CR_UART_EN) { + netx_console_get_options(&sport->port, &baud, + &parity, &bits, &flow); + } + + } + + return uart_set_options(&sport->port, co, baud, parity, bits, flow); +} + +static struct uart_driver netx_reg; +static struct console netx_console = { + .name = "ttyNX", + .write = netx_console_write, + .device = uart_console_device, + .setup = netx_console_setup, + .flags = CON_PRINTBUFFER, + .index = -1, + .data = &netx_reg, +}; + +static int __init netx_console_init(void) +{ + register_console(&netx_console); + return 0; +} +console_initcall(netx_console_init); + +#define NETX_CONSOLE &netx_console +#else +#define NETX_CONSOLE NULL +#endif + +static struct uart_driver netx_reg = { + .owner = THIS_MODULE, + .driver_name = DRIVER_NAME, + .dev_name = "ttyNX", + .major = SERIAL_NX_MAJOR, + .minor = MINOR_START, + .nr = ARRAY_SIZE(netx_ports), + .cons = NETX_CONSOLE, +}; + +static int serial_netx_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct netx_port *sport = platform_get_drvdata(pdev); + + if (sport) + uart_suspend_port(&netx_reg, &sport->port); + + return 0; +} + +static int serial_netx_resume(struct platform_device *pdev) +{ + struct netx_port *sport = platform_get_drvdata(pdev); + + if (sport) + uart_resume_port(&netx_reg, &sport->port); + + return 0; +} + +static int serial_netx_probe(struct platform_device *pdev) +{ + struct uart_port *port = &netx_ports[pdev->id].port; + + dev_info(&pdev->dev, "initialising\n"); + + port->dev = &pdev->dev; + + writel(1, port->membase + UART_RXFIFO_IRQLEVEL); + uart_add_one_port(&netx_reg, &netx_ports[pdev->id].port); + platform_set_drvdata(pdev, &netx_ports[pdev->id]); + + return 0; +} + +static int serial_netx_remove(struct platform_device *pdev) +{ + struct netx_port *sport = platform_get_drvdata(pdev); + + platform_set_drvdata(pdev, NULL); + + if (sport) + uart_remove_one_port(&netx_reg, &sport->port); + + return 0; +} + +static struct platform_driver serial_netx_driver = { + .probe = serial_netx_probe, + .remove = serial_netx_remove, + + .suspend = serial_netx_suspend, + .resume = serial_netx_resume, + + .driver = { + .name = DRIVER_NAME, + }, +}; + +static int __init netx_serial_init(void) +{ + int ret; + + printk(KERN_INFO "Serial: NetX driver\n"); + + ret = uart_register_driver(&netx_reg); + if (ret) + return ret; + + ret = platform_driver_register(&serial_netx_driver); + if (ret != 0) + uart_unregister_driver(&netx_reg); + + return 0; +} + +static void __exit netx_serial_exit(void) +{ + platform_driver_unregister(&serial_netx_driver); + uart_unregister_driver(&netx_reg); +} + +module_init(netx_serial_init); +module_exit(netx_serial_exit); + +MODULE_AUTHOR("Sascha Hauer"); +MODULE_DESCRIPTION("NetX serial port driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 3095faf5295f2da9118469c925d2cfb7775ad287 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 19 Jun 2006 13:30:58 +0100 Subject: [ARM] 3572/1: netX: framebuffer driver for Hilscher netX Patch from Sascha Hauer This patch adds framebuffer support for Hilscher's netX network processors. Signed-off-by: Robert Schwebel Signed-off-by: Sascha Hauer Signed-off-by: Russell King --- arch/arm/mach-netx/fb.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++ arch/arm/mach-netx/fb.h | 24 ++++++++++ 2 files changed, 138 insertions(+) create mode 100644 arch/arm/mach-netx/fb.c create mode 100644 arch/arm/mach-netx/fb.h diff --git a/arch/arm/mach-netx/fb.c b/arch/arm/mach-netx/fb.c new file mode 100644 index 00000000000..e169b683e4d --- /dev/null +++ b/arch/arm/mach-netx/fb.c @@ -0,0 +1,114 @@ +/* + * arch/arm/mach-netx/fb.c + * + * Copyright (c) 2005 Sascha Hauer , Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include +#include + +struct clk {}; + +static struct clk fb_clk; + +static struct clcd_panel *netx_panel; + +void netx_clcd_enable(struct clcd_fb *fb) +{ +} + +int netx_clcd_setup(struct clcd_fb *fb) +{ + dma_addr_t dma; + + fb->panel = netx_panel; + + fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, 1024*1024, + &dma, GFP_KERNEL); + if (!fb->fb.screen_base) { + printk(KERN_ERR "CLCD: unable to map framebuffer\n"); + return -ENOMEM; + } + + fb->fb.fix.smem_start = dma; + fb->fb.fix.smem_len = 1024*1024; + + return 0; +} + +int netx_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma) +{ + return dma_mmap_writecombine(&fb->dev->dev, vma, + fb->fb.screen_base, + fb->fb.fix.smem_start, + fb->fb.fix.smem_len); +} + +void netx_clcd_remove(struct clcd_fb *fb) +{ + dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len, + fb->fb.screen_base, fb->fb.fix.smem_start); +} + +void clk_disable(struct clk *clk) +{ +} + +int clk_set_rate(struct clk *clk, unsigned long rate) +{ + return 0; +} + +int clk_enable(struct clk *clk) +{ + return 0; +} + +struct clk *clk_get(struct device *dev, const char *id) +{ + return &fb_clk; +} + +void clk_put(struct clk *clk) +{ +} + +static struct amba_device fb_device = { + .dev = { + .bus_id = "fb", + .coherent_dma_mask = ~0, + }, + .res = { + .start = 0x00104000, + .end = 0x00104fff, + .flags = IORESOURCE_MEM, + }, + .irq = { NETX_IRQ_LCD, NO_IRQ }, + .periphid = 0x10112400, +}; + +int netx_fb_init(struct clcd_board *board, struct clcd_panel *panel) +{ + netx_panel = panel; + fb_device.dev.platform_data = board; + return amba_device_register(&fb_device, &iomem_resource); +} diff --git a/arch/arm/mach-netx/fb.h b/arch/arm/mach-netx/fb.h new file mode 100644 index 00000000000..4919cf33a5f --- /dev/null +++ b/arch/arm/mach-netx/fb.h @@ -0,0 +1,24 @@ +/* + * arch/arm/mach-netx/fb.h + * + * Copyright (c) 2005 Sascha Hauer , Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +void netx_clcd_enable(struct clcd_fb *fb); +int netx_clcd_setup(struct clcd_fb *fb); +int netx_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma); +void netx_clcd_remove(struct clcd_fb *fb); +int netx_fb_init(struct clcd_board *board, struct clcd_panel *panel); -- cgit v1.2.3 From 963151f2471d0e6475d8b2d3a005417aec1766f7 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Mon, 19 Jun 2006 15:23:41 +0100 Subject: [ARM] 3579/1: AT91RM9200 Timer simplification Patch from Andrew Victor Use a global variable 'last_crtr' to store the time of the last timer tick instead of the ST_RTAR register. It's faster, frees up the ST_RTAR register for other uses, and hopefully makes the code more understandable. [Patch from Peter Menzebach] Also add the SA_TIMER flag to Timer IRQ. (It seems to be required for the realtime preempt patch). Signed-off-by: Andrew Victor Signed-off-by: Russell King --- arch/arm/mach-at91rm9200/time.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/arch/arm/mach-at91rm9200/time.c b/arch/arm/mach-at91rm9200/time.c index 7ffcf443b99..36798a8d532 100644 --- a/arch/arm/mach-at91rm9200/time.c +++ b/arch/arm/mach-at91rm9200/time.c @@ -31,6 +31,8 @@ #include #include +static unsigned long last_crtr; + /* * The ST_CRTR is updated asynchronously to the master clock. It is therefore * necessary to read it twice (with the same value) to ensure accuracy. @@ -56,7 +58,7 @@ static unsigned long at91rm9200_gettimeoffset(void) { unsigned long elapsed; - elapsed = (read_CRTR() - at91_sys_read(AT91_ST_RTAR)) & AT91_ST_ALMV; + elapsed = (read_CRTR() - last_crtr) & AT91_ST_ALMV; return (unsigned long)(elapsed * (tick_nsec / 1000)) / LATCH; } @@ -66,15 +68,12 @@ static unsigned long at91rm9200_gettimeoffset(void) */ static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - unsigned long rtar; - if (at91_sys_read(AT91_ST_SR) & AT91_ST_PITS) { /* This is a shared interrupt */ write_seqlock(&xtime_lock); - while (((read_CRTR() - at91_sys_read(AT91_ST_RTAR)) & AT91_ST_ALMV) >= LATCH) { + while (((read_CRTR() - last_crtr) & AT91_ST_ALMV) >= LATCH) { timer_tick(regs); - rtar = (at91_sys_read(AT91_ST_RTAR) + LATCH) & AT91_ST_ALMV; - at91_sys_write(AT91_ST_RTAR, rtar); + last_crtr = (last_crtr + LATCH) & AT91_ST_ALMV; } write_sequnlock(&xtime_lock); @@ -87,7 +86,7 @@ static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id, struct pt_r static struct irqaction at91rm9200_timer_irq = { .name = "at91_tick", - .flags = SA_SHIRQ | SA_INTERRUPT, + .flags = SA_SHIRQ | SA_INTERRUPT | SA_TIMER, .handler = at91rm9200_timer_interrupt }; -- cgit v1.2.3 From 2a6f9902c6a799a9c0218b37e39b75690c3b9a70 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Mon, 19 Jun 2006 15:26:50 +0100 Subject: [ARM] 3580/1: AT91RM9200 Timer suspend/resume support Patch from Andrew Victor Added suspend/resume support for the AT91RM9200 timer. Signed-off-by: Andrew Victor Signed-off-by: Russell King --- arch/arm/mach-at91rm9200/time.c | 44 ++++++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/arch/arm/mach-at91rm9200/time.c b/arch/arm/mach-at91rm9200/time.c index 36798a8d532..fc2d7d5e463 100644 --- a/arch/arm/mach-at91rm9200/time.c +++ b/arch/arm/mach-at91rm9200/time.c @@ -90,6 +90,20 @@ static struct irqaction at91rm9200_timer_irq = { .handler = at91rm9200_timer_interrupt }; +void at91rm9200_timer_reset(void) +{ + last_crtr = 0; + + /* Real time counter incremented every 30.51758 microseconds */ + at91_sys_write(AT91_ST_RTMR, 1); + + /* Set Period Interval timer */ + at91_sys_write(AT91_ST_PIMR, LATCH); + + /* Enable Period Interval Timer interrupt */ + at91_sys_write(AT91_ST_IER, AT91_ST_PITS); +} + /* * Set up timer interrupt. */ @@ -99,28 +113,30 @@ void __init at91rm9200_timer_init(void) at91_sys_write(AT91_ST_IDR, AT91_ST_PITS | AT91_ST_WDOVF | AT91_ST_RTTINC | AT91_ST_ALMS); (void) at91_sys_read(AT91_ST_SR); /* Clear any pending interrupts */ - /* - * Make IRQs happen for the system timer. - */ + /* Make IRQs happen for the system timer */ setup_irq(AT91_ID_SYS, &at91rm9200_timer_irq); - /* Set initial alarm to 0 */ - at91_sys_write(AT91_ST_RTAR, 0); - - /* Real time counter incremented every 30.51758 microseconds */ - at91_sys_write(AT91_ST_RTMR, 1); - - /* Set Period Interval timer */ - at91_sys_write(AT91_ST_PIMR, LATCH); - /* Change the kernel's 'tick' value to 10009 usec. (the default is 10000) */ tick_usec = (LATCH * 1000000) / CLOCK_TICK_RATE; - /* Enable Period Interval Timer interrupt */ - at91_sys_write(AT91_ST_IER, AT91_ST_PITS); + /* Initialize and enable the timer interrupt */ + at91rm9200_timer_reset(); +} + +#ifdef CONFIG_PM +static void at91rm9200_timer_suspend(void) +{ + /* disable Period Interval Timer interrupt */ + at91_sys_write(AT91_ST_IDR, AT91_ST_PITS); } +#else +#define at91rm9200_timer_suspend NULL +#endif struct sys_timer at91rm9200_timer = { .init = at91rm9200_timer_init, .offset = at91rm9200_gettimeoffset, + .suspend = at91rm9200_timer_suspend, + .resume = at91rm9200_timer_reset, }; + -- cgit v1.2.3 From 10e8e1fb758eed5cfb0cae1b770f842624851e7b Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Mon, 19 Jun 2006 15:26:51 +0100 Subject: [ARM] 3581/1: AT91RM9200 Internal SRAM Patch from Andrew Victor This patch maps the AT91RM9200's internal SRAM into the virtual memory address space - just below the internal peripheral registers. Signed-off-by: Andrew Victor Signed-off-by: Russell King --- arch/arm/mach-at91rm9200/common.c | 6 ++++++ include/asm-arm/arch-at91rm9200/hardware.h | 5 ++++- include/asm-arm/arch-at91rm9200/vmalloc.h | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-at91rm9200/common.c b/arch/arm/mach-at91rm9200/common.c index 3848fd2d559..40d29a73b5c 100644 --- a/arch/arm/mach-at91rm9200/common.c +++ b/arch/arm/mach-at91rm9200/common.c @@ -17,6 +17,7 @@ #include #include +#include "generic.h" static struct map_desc at91rm9200_io_desc[] __initdata = { { @@ -94,6 +95,11 @@ static struct map_desc at91rm9200_io_desc[] __initdata = { .pfn = __phys_to_pfn(AT91_BASE_TCB0), .length = SZ_16K, .type = MT_DEVICE, + }, { + .virtual = AT91_SRAM_VIRT_BASE, + .pfn = __phys_to_pfn(AT91_SRAM_BASE), + .length = AT91_SRAM_SIZE, + .type = MT_DEVICE, }, }; diff --git a/include/asm-arm/arch-at91rm9200/hardware.h b/include/asm-arm/arch-at91rm9200/hardware.h index 59e6f44d3a0..87f40df5714 100644 --- a/include/asm-arm/arch-at91rm9200/hardware.h +++ b/include/asm-arm/arch-at91rm9200/hardware.h @@ -50,9 +50,12 @@ #define AT91_VA_BASE_TCB0 AT91_IO_P2V(AT91_BASE_TCB0) /* Internal SRAM */ -#define AT91_BASE_SRAM 0x00200000 /* Internal SRAM base address */ +#define AT91_SRAM_BASE 0x00200000 /* Internal SRAM base address */ #define AT91_SRAM_SIZE 0x00004000 /* Internal SRAM SIZE (16Kb) */ + /* Internal SRAM is mapped below the IO devices */ +#define AT91_SRAM_VIRT_BASE (AT91_IO_VIRT_BASE - AT91_SRAM_SIZE) + /* Serial ports */ #define AT91_NR_UART 5 /* 4 USART3's and one DBGU port */ diff --git a/include/asm-arm/arch-at91rm9200/vmalloc.h b/include/asm-arm/arch-at91rm9200/vmalloc.h index 34d9718feb9..4c367eb57f4 100644 --- a/include/asm-arm/arch-at91rm9200/vmalloc.h +++ b/include/asm-arm/arch-at91rm9200/vmalloc.h @@ -21,6 +21,6 @@ #ifndef __ASM_ARCH_VMALLOC_H #define __ASM_ARCH_VMALLOC_H -#define VMALLOC_END (AT91_IO_VIRT_BASE & PGDIR_MASK) +#define VMALLOC_END (AT91_SRAM_VIRT_BASE & PGDIR_MASK) #endif -- cgit v1.2.3 From 37f2e4bc120bd784e7f69f961233e1c16b74d170 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Mon, 19 Jun 2006 15:26:52 +0100 Subject: [ARM] 3582/1: AT91RM9200 IRQ trigger types Patch from Andrew Victor The AIC interrupt controller's set_irq_type() can also be used for internal interrupts. IRQT_LOW and IRQT_FALLING are the only options not supported for the internal interrupts. [Original patch from Karl Olsen] Signed-off-by: Andrew Victor Signed-off-by: Russell King --- arch/arm/mach-at91rm9200/irq.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-at91rm9200/irq.c b/arch/arm/mach-at91rm9200/irq.c index cb62bc83a1d..cc545b2c438 100644 --- a/arch/arm/mach-at91rm9200/irq.c +++ b/arch/arm/mach-at91rm9200/irq.c @@ -92,10 +92,6 @@ static int at91rm9200_irq_type(unsigned irq, unsigned type) { unsigned int smr, srctype; - /* change triggering only for FIQ and external IRQ0..IRQ6 */ - if ((irq < AT91_ID_IRQ0) && (irq != AT91_ID_FIQ)) - return -EINVAL; - switch (type) { case IRQT_HIGH: srctype = AT91_AIC_SRCTYPE_HIGH; @@ -104,9 +100,13 @@ static int at91rm9200_irq_type(unsigned irq, unsigned type) srctype = AT91_AIC_SRCTYPE_RISING; break; case IRQT_LOW: + if ((irq > AT91_ID_FIQ) && (irq < AT91_ID_IRQ0)) /* only supported on external interrupts */ + return -EINVAL; srctype = AT91_AIC_SRCTYPE_LOW; break; case IRQT_FALLING: + if ((irq > AT91_ID_FIQ) && (irq < AT91_ID_IRQ0)) /* only supported on external interrupts */ + return -EINVAL; srctype = AT91_AIC_SRCTYPE_FALLING; break; default: -- cgit v1.2.3 From 683c66bf75ce277b90d658da0c1a0bf1a55cce4c Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Mon, 19 Jun 2006 15:26:53 +0100 Subject: [ARM] 3583/1: AT91RM9200 IRQ suspend/resume support Patch from Andrew Victor Added suspend/resume/set_wake support for the AT91RM9200's AIC interrupt controller. Signed-off-by: Andrew Victor Signed-off-by: Russell King --- arch/arm/mach-at91rm9200/irq.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/arch/arm/mach-at91rm9200/irq.c b/arch/arm/mach-at91rm9200/irq.c index cc545b2c438..70f4d7ac153 100644 --- a/arch/arm/mach-at91rm9200/irq.c +++ b/arch/arm/mach-at91rm9200/irq.c @@ -118,11 +118,47 @@ static int at91rm9200_irq_type(unsigned irq, unsigned type) return 0; } +#ifdef CONFIG_PM + +static u32 wakeups; +static u32 backups; + +static int at91rm9200_irq_set_wake(unsigned irq, unsigned value) +{ + if (unlikely(irq >= 32)) + return -EINVAL; + + if (value) + wakeups |= (1 << irq); + else + wakeups &= ~(1 << irq); + + return 0; +} + +void at91_irq_suspend(void) +{ + backups = at91_sys_read(AT91_AIC_IMR); + at91_sys_write(AT91_AIC_IDCR, backups); + at91_sys_write(AT91_AIC_IECR, wakeups); +} + +void at91_irq_resume(void) +{ + at91_sys_write(AT91_AIC_IDCR, wakeups); + at91_sys_write(AT91_AIC_IECR, backups); +} + +#else +#define at91rm9200_irq_set_wake NULL +#endif + static struct irqchip at91rm9200_irq_chip = { .ack = at91rm9200_mask_irq, .mask = at91rm9200_mask_irq, .unmask = at91rm9200_unmask_irq, .set_type = at91rm9200_irq_type, + .set_wake = at91rm9200_irq_set_wake, }; /* -- cgit v1.2.3 From 814138ffa488824393d2f49f2720dcd197a7d4cf Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Mon, 19 Jun 2006 15:26:54 +0100 Subject: [ARM] 3584/1: AT91RM9200 GPIO suspend/resume support Patch from Andrew Victor This patch adds suspend/resume/set_wake support for the AT91RM9200's GPIO interrupts. Original patch from David Brownell. Signed-off-by: Andrew Victor Signed-off-by: Russell King --- arch/arm/mach-at91rm9200/gpio.c | 87 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 84 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-at91rm9200/gpio.c b/arch/arm/mach-at91rm9200/gpio.c index 5ab46274e1a..3430ea05466 100644 --- a/arch/arm/mach-at91rm9200/gpio.c +++ b/arch/arm/mach-at91rm9200/gpio.c @@ -213,6 +213,84 @@ EXPORT_SYMBOL(at91_get_gpio_value); /*--------------------------------------------------------------------------*/ +#ifdef CONFIG_PM + +static u32 wakeups[BGA_GPIO_BANKS]; +static u32 backups[BGA_GPIO_BANKS]; + +static int gpio_irq_set_wake(unsigned pin, unsigned state) +{ + unsigned mask = pin_to_mask(pin); + + pin -= PIN_BASE; + pin /= 32; + + if (unlikely(pin >= BGA_GPIO_BANKS)) + return -EINVAL; + + if (state) + wakeups[pin] |= mask; + else + wakeups[pin] &= ~mask; + + return 0; +} + +void at91_gpio_suspend(void) +{ + int i; + + for (i = 0; i < BGA_GPIO_BANKS; i++) { + u32 pio = pio_controller_offset[i]; + + /* + * Note: drivers should have disabled GPIO interrupts that + * aren't supposed to be wakeup sources. + * But that is not much good on ARM..... disable_irq() does + * not update the hardware immediately, so the hardware mask + * (IMR) has the wrong value (not current, too much is + * permitted). + * + * Our workaround is to disable all non-wakeup IRQs ... + * which is exactly what correct drivers asked for in the + * first place! + */ + backups[i] = at91_sys_read(pio + PIO_IMR); + at91_sys_write(pio_controller_offset[i] + PIO_IDR, backups[i]); + at91_sys_write(pio_controller_offset[i] + PIO_IER, wakeups[i]); + + if (!wakeups[i]) { + disable_irq_wake(AT91_ID_PIOA + i); + at91_sys_write(AT91_PMC_PCDR, 1 << (AT91_ID_PIOA + i)); + } else { + enable_irq_wake(AT91_ID_PIOA + i); +#ifdef CONFIG_PM_DEBUG + printk(KERN_DEBUG "GPIO-%c may wake for %08x\n", "ABCD"[i], wakeups[i]); +#endif + } + } +} + +void at91_gpio_resume(void) +{ + int i; + + for (i = 0; i < BGA_GPIO_BANKS; i++) { + at91_sys_write(pio_controller_offset[i] + PIO_IDR, wakeups[i]); + at91_sys_write(pio_controller_offset[i] + PIO_IER, backups[i]); + } + + at91_sys_write(AT91_PMC_PCER, + (1 << AT91_ID_PIOA) + | (1 << AT91_ID_PIOB) + | (1 << AT91_ID_PIOC) + | (1 << AT91_ID_PIOD)); +} + +#else +#define gpio_irq_set_wake NULL +#endif + /* Several AIC controller irqs are dispatched through this GPIO handler. * To use any AT91_PIN_* as an externally triggered IRQ, first call @@ -252,6 +330,7 @@ static struct irqchip gpio_irqchip = { .mask = gpio_irq_mask, .unmask = gpio_irq_unmask, .set_type = gpio_irq_type, + .set_wake = gpio_irq_set_wake, }; static void gpio_irq_handler(unsigned irq, struct irqdesc *desc, struct pt_regs *regs) @@ -266,6 +345,7 @@ static void gpio_irq_handler(unsigned irq, struct irqdesc *desc, struct pt_regs /* temporarily mask (level sensitive) parent IRQ */ desc->chip->ack(irq); for (;;) { + /* reading ISR acks the pending (edge triggered) GPIO interrupt */ isr = __raw_readl(pio + PIO_ISR) & __raw_readl(pio + PIO_IMR); if (!isr) break; @@ -315,15 +395,16 @@ void __init at91_gpio_irq_setup(unsigned banks) set_irq_chipdata(id, controller); for (i = 0; i < 32; i++, pin++) { + /* + * Can use the "simple" and not "edge" handler since it's + * shorter, and the AIC handles interupts sanely. + */ set_irq_chip(pin, &gpio_irqchip); set_irq_handler(pin, do_simple_IRQ); set_irq_flags(pin, IRQF_VALID); } set_irq_chained_handler(id, gpio_irq_handler); - - /* enable the PIO peripheral clock */ - at91_sys_write(AT91_PMC_PCER, 1 << id); } pr_info("AT91: %d gpio irqs in %d banks\n", pin - PIN_BASE, banks); } -- cgit v1.2.3 From bb6d8c8828123e01e2ae6c9d9c4870477889fd94 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 19 Jun 2006 15:27:53 +0100 Subject: [ARM] 3567/2: arm: base support for Hilscher netX Patch from Sascha Hauer This patch adds the base support for Hilscher's netX network processors. Signed-off-by: Robert Schwebel Signed-off-by: Sascha Hauer Signed-off-by: Russell King --- arch/arm/Kconfig | 8 ++ arch/arm/Makefile | 1 + arch/arm/mach-netx/Makefile | 11 ++ arch/arm/mach-netx/Makefile.boot | 2 + arch/arm/mach-netx/generic.c | 193 ++++++++++++++++++++++++++++++++ arch/arm/mach-netx/generic.h | 24 ++++ arch/arm/mach-netx/time.c | 88 +++++++++++++++ arch/arm/mm/Kconfig | 4 +- include/asm-arm/arch-netx/debug-macro.S | 38 +++++++ include/asm-arm/arch-netx/dma.h | 21 ++++ include/asm-arm/arch-netx/entry-macro.S | 35 ++++++ include/asm-arm/arch-netx/hardware.h | 39 +++++++ include/asm-arm/arch-netx/io.h | 29 +++++ include/asm-arm/arch-netx/irqs.h | 70 ++++++++++++ include/asm-arm/arch-netx/memory.h | 36 ++++++ include/asm-arm/arch-netx/param.h | 18 +++ include/asm-arm/arch-netx/system.h | 38 +++++++ include/asm-arm/arch-netx/timex.h | 20 ++++ include/asm-arm/arch-netx/uncompress.h | 76 +++++++++++++ include/asm-arm/arch-netx/vmalloc.h | 19 ++++ 20 files changed, 768 insertions(+), 2 deletions(-) create mode 100644 arch/arm/mach-netx/Makefile create mode 100644 arch/arm/mach-netx/Makefile.boot create mode 100644 arch/arm/mach-netx/generic.c create mode 100644 arch/arm/mach-netx/generic.h create mode 100644 arch/arm/mach-netx/time.c create mode 100644 include/asm-arm/arch-netx/debug-macro.S create mode 100644 include/asm-arm/arch-netx/dma.h create mode 100644 include/asm-arm/arch-netx/entry-macro.S create mode 100644 include/asm-arm/arch-netx/hardware.h create mode 100644 include/asm-arm/arch-netx/io.h create mode 100644 include/asm-arm/arch-netx/irqs.h create mode 100644 include/asm-arm/arch-netx/memory.h create mode 100644 include/asm-arm/arch-netx/param.h create mode 100644 include/asm-arm/arch-netx/system.h create mode 100644 include/asm-arm/arch-netx/timex.h create mode 100644 include/asm-arm/arch-netx/uncompress.h create mode 100644 include/asm-arm/arch-netx/vmalloc.h diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index f47cf9af3bc..dfb97fe045d 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -275,6 +275,12 @@ config ARCH_PNX4008 help This enables support for Philips PNX4008 mobile platform. +config ARCH_NETX + bool "Hilscher NetX based" + select ARM_VIC + help + This enables support for systems based on the Hilscher NetX Soc + endchoice source "arch/arm/mach-clps711x/Kconfig" @@ -319,6 +325,8 @@ source "arch/arm/mach-realview/Kconfig" source "arch/arm/mach-at91rm9200/Kconfig" +source "arch/arm/mach-netx/Kconfig" + # Definitions to make life easier config ARCH_ACORN bool diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 6c97aa70d3b..282b14e2f46 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -117,6 +117,7 @@ endif machine-$(CONFIG_ARCH_AT91RM9200) := at91rm9200 machine-$(CONFIG_ARCH_EP93XX) := ep93xx machine-$(CONFIG_ARCH_PNX4008) := pnx4008 + machine-$(CONFIG_ARCH_NETX) := netx ifeq ($(CONFIG_ARCH_EBSA110),y) # This is what happens if you forget the IOCS16 line. diff --git a/arch/arm/mach-netx/Makefile b/arch/arm/mach-netx/Makefile new file mode 100644 index 00000000000..257d02ef66d --- /dev/null +++ b/arch/arm/mach-netx/Makefile @@ -0,0 +1,11 @@ +# +# Makefile for the linux kernel. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). + +# Object file lists. + +obj-y += time.o generic.o + diff --git a/arch/arm/mach-netx/Makefile.boot b/arch/arm/mach-netx/Makefile.boot new file mode 100644 index 00000000000..b81cf6aff0a --- /dev/null +++ b/arch/arm/mach-netx/Makefile.boot @@ -0,0 +1,2 @@ + zreladdr-y := 0x80008000 + diff --git a/arch/arm/mach-netx/generic.c b/arch/arm/mach-netx/generic.c new file mode 100644 index 00000000000..af0b13534cf --- /dev/null +++ b/arch/arm/mach-netx/generic.c @@ -0,0 +1,193 @@ +/* + * arch/arm/mach-netx/generic.c + * + * Copyright (C) 2005 Sascha Hauer , Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct map_desc netx_io_desc[] __initdata = { + { + .virtual = NETX_IO_VIRT, + .pfn = __phys_to_pfn(NETX_IO_PHYS), + .length = NETX_IO_SIZE, + .type = MT_DEVICE + } +}; + +void __init netx_map_io(void) +{ + iotable_init(netx_io_desc, ARRAY_SIZE(netx_io_desc)); +} + +static struct resource netx_rtc_resources[] = { + [0] = { + .start = 0x00101200, + .end = 0x00101220, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device netx_rtc_device = { + .name = "netx-rtc", + .id = 0, + .num_resources = ARRAY_SIZE(netx_rtc_resources), + .resource = netx_rtc_resources, +}; + +static struct platform_device *devices[] __initdata = { + &netx_rtc_device, +}; + +#if 0 +#define DEBUG_IRQ(fmt...) printk(fmt) +#else +#define DEBUG_IRQ(fmt...) while (0) {} +#endif + +static void +netx_hif_demux_handler(unsigned int irq_unused, struct irqdesc *desc, + struct pt_regs *regs) +{ + unsigned int irq = NETX_IRQ_HIF_CHAINED(0); + unsigned int stat; + + stat = ((readl(NETX_DPMAS_INT_EN) & + readl(NETX_DPMAS_INT_STAT)) >> 24) & 0x1f; + + desc = irq_desc + NETX_IRQ_HIF_CHAINED(0); + + while (stat) { + if (stat & 1) { + DEBUG_IRQ("handling irq %d\n", irq); + desc_handle_irq(irq, desc, regs); + } + irq++; + desc++; + stat >>= 1; + } +} + +static int +netx_hif_irq_type(unsigned int _irq, unsigned int type) +{ + unsigned int val, irq; + + val = readl(NETX_DPMAS_IF_CONF1); + + irq = _irq - NETX_IRQ_HIF_CHAINED(0); + + if (type & __IRQT_RISEDGE) { + DEBUG_IRQ("rising edges\n"); + val |= (1 << 26) << irq; + } + if (type & __IRQT_FALEDGE) { + DEBUG_IRQ("falling edges\n"); + val &= ~((1 << 26) << irq); + } + if (type & __IRQT_LOWLVL) { + DEBUG_IRQ("low level\n"); + val &= ~((1 << 26) << irq); + } + if (type & __IRQT_HIGHLVL) { + DEBUG_IRQ("high level\n"); + val |= (1 << 26) << irq; + } + + writel(val, NETX_DPMAS_IF_CONF1); + + return 0; +} + +static void +netx_hif_ack_irq(unsigned int _irq) +{ + unsigned int val, irq; + + irq = _irq - NETX_IRQ_HIF_CHAINED(0); + writel((1 << 24) << irq, NETX_DPMAS_INT_STAT); + + val = readl(NETX_DPMAS_INT_EN); + val &= ~((1 << 24) << irq); + writel(val, NETX_DPMAS_INT_EN); + + DEBUG_IRQ("%s: irq %d\n", __FUNCTION__, _irq); +} + +static void +netx_hif_mask_irq(unsigned int _irq) +{ + unsigned int val, irq; + + irq = _irq - NETX_IRQ_HIF_CHAINED(0); + val = readl(NETX_DPMAS_INT_EN); + val &= ~((1 << 24) << irq); + writel(val, NETX_DPMAS_INT_EN); + DEBUG_IRQ("%s: irq %d\n", __FUNCTION__, _irq); +} + +static void +netx_hif_unmask_irq(unsigned int _irq) +{ + unsigned int val, irq; + + irq = _irq - NETX_IRQ_HIF_CHAINED(0); + val = readl(NETX_DPMAS_INT_EN); + val |= (1 << 24) << irq; + writel(val, NETX_DPMAS_INT_EN); + DEBUG_IRQ("%s: irq %d\n", __FUNCTION__, _irq); +} + +static struct irqchip netx_hif_chip = { + .ack = netx_hif_ack_irq, + .mask = netx_hif_mask_irq, + .unmask = netx_hif_unmask_irq, + .set_type = netx_hif_irq_type, +}; + +void __init netx_init_irq(void) +{ + int irq; + + vic_init(__io(io_p2v(NETX_PA_VIC)), 0, ~0); + + for (irq = NETX_IRQ_HIF_CHAINED(0); irq <= NETX_IRQ_HIF_LAST; irq++) { + set_irq_chip(irq, &netx_hif_chip); + set_irq_handler(irq, do_level_IRQ); + set_irq_flags(irq, IRQF_VALID); + } + + writel(NETX_DPMAS_INT_EN_GLB_EN, NETX_DPMAS_INT_EN); + set_irq_chained_handler(NETX_IRQ_HIF, netx_hif_demux_handler); +} + +static int __init netx_init(void) +{ + return platform_add_devices(devices, ARRAY_SIZE(devices)); +} + +subsys_initcall(netx_init); + diff --git a/arch/arm/mach-netx/generic.h b/arch/arm/mach-netx/generic.h new file mode 100644 index 00000000000..ede2d35341c --- /dev/null +++ b/arch/arm/mach-netx/generic.h @@ -0,0 +1,24 @@ +/* + * arch/arm/mach-netx/generic.h + * + * Copyright (c) 2005 Sascha Hauer , Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +extern void __init netx_map_io(void); +extern void __init netx_init_irq(void); + +struct sys_timer; +extern struct sys_timer netx_timer; diff --git a/arch/arm/mach-netx/time.c b/arch/arm/mach-netx/time.c new file mode 100644 index 00000000000..edfbdf40c60 --- /dev/null +++ b/arch/arm/mach-netx/time.c @@ -0,0 +1,88 @@ +/* + * arch/arm/mach-netx/time.c + * + * Copyright (c) 2005 Sascha Hauer , Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include +#include +#include +#include + +/* + * Returns number of us since last clock interrupt. Note that interrupts + * will have been disabled by do_gettimeoffset() + */ +static unsigned long netx_gettimeoffset(void) +{ + return readl(NETX_GPIO_COUNTER_CURRENT(0)) / 100; +} + +/* + * IRQ handler for the timer + */ +static irqreturn_t +netx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + write_seqlock(&xtime_lock); + + timer_tick(regs); + write_sequnlock(&xtime_lock); + + /* acknowledge interrupt */ + writel(COUNTER_BIT(0), NETX_GPIO_IRQ); + + return IRQ_HANDLED; +} + + +static struct irqaction netx_timer_irq = { + .name = "NetX Timer Tick", + .flags = SA_INTERRUPT | SA_TIMER, + .handler = netx_timer_interrupt, +}; + +/* + * Set up timer interrupt + */ +static void __init netx_timer_init(void) +{ + /* disable timer initially */ + writel(0, NETX_GPIO_COUNTER_CTRL(0)); + + /* Reset the timer value to zero */ + writel(0, NETX_GPIO_COUNTER_CURRENT(0)); + + writel(LATCH, NETX_GPIO_COUNTER_MAX(0)); + + /* acknowledge interrupt */ + writel(COUNTER_BIT(0), NETX_GPIO_IRQ); + + /* Enable the interrupt in the specific timer register and start timer */ + writel(COUNTER_BIT(0), NETX_GPIO_IRQ_ENABLE); + writel(NETX_GPIO_COUNTER_CTRL_IRQ_EN | NETX_GPIO_COUNTER_CTRL_RUN, + NETX_GPIO_COUNTER_CTRL(0)); + + setup_irq(NETX_IRQ_TIMER0, &netx_timer_irq); +} + +struct sys_timer netx_timer = { + .init = netx_timer_init, + .offset = netx_gettimeoffset, +}; diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index 1ff2f073a55..4221d054a1e 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -121,8 +121,8 @@ config CPU_ARM925T # ARM926T config CPU_ARM926T bool "Support ARM926T processor" - depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB || ARCH_PNX4008 - default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || ARCH_PNX4008 + depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB || ARCH_PNX4008 || ARCH_NETX + default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || ARCH_PNX4008 || ARCH_NETX select CPU_32v5 select CPU_ABRT_EV5TJ select CPU_CACHE_VIVT diff --git a/include/asm-arm/arch-netx/debug-macro.S b/include/asm-arm/arch-netx/debug-macro.S new file mode 100644 index 00000000000..a940d0e80cb --- /dev/null +++ b/include/asm-arm/arch-netx/debug-macro.S @@ -0,0 +1,38 @@ +/* linux/include/asm-arm/arch-netx/debug-macro.S + * + * Debugging macro include header + * + * Copyright (C) 1994-1999 Russell King + * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * +*/ + +#include "hardware.h" + + .macro addruart,rx + mrc p15, 0, \rx, c1, c0 + tst \rx, #1 @ MMU enabled? + moveq \rx, #0x00100000 @ physical + movne \rx, #io_p2v(0x00100000) @ virtual + orr \rx, \rx, #0x00000a00 + .endm + + .macro senduart,rd,rx + str \rd, [\rx, #0] + .endm + + .macro busyuart,rd,rx +1002: ldr \rd, [\rx, #0x18] + tst \rd, #(1 << 3) + bne 1002b + .endm + + .macro waituart,rd,rx +1001: ldr \rd, [\rx, #0x18] + tst \rd, #(1 << 3) + bne 1001b + .endm diff --git a/include/asm-arm/arch-netx/dma.h b/include/asm-arm/arch-netx/dma.h new file mode 100644 index 00000000000..4eda5feed81 --- /dev/null +++ b/include/asm-arm/arch-netx/dma.h @@ -0,0 +1,21 @@ +/* + * linux/include/asm-arm/arch-netx/dma.h + * + * Copyright (C) 2005 Sascha Hauer , Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define MAX_DMA_CHANNELS 0 +#define MAX_DMA_ADDRESS ~0 diff --git a/include/asm-arm/arch-netx/entry-macro.S b/include/asm-arm/arch-netx/entry-macro.S new file mode 100644 index 00000000000..658df4d60ff --- /dev/null +++ b/include/asm-arm/arch-netx/entry-macro.S @@ -0,0 +1,35 @@ +/* + * include/asm-arm/arch-netx/entry-macro.S + * + * Low-level IRQ helper macros for Hilscher netX based platforms + * + * Copyright (C) 2005 Sascha Hauer , Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include + + .macro disable_fiq + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + mov \base, #io_p2v(0x00100000) + add \base, \base, #0x000ff000 + + ldr \irqstat, [\base, #0] + clz \irqnr, \irqstat + rsb \irqnr, \irqnr, #31 + cmp \irqstat, #0 + .endm + diff --git a/include/asm-arm/arch-netx/hardware.h b/include/asm-arm/arch-netx/hardware.h new file mode 100644 index 00000000000..7786c45455c --- /dev/null +++ b/include/asm-arm/arch-netx/hardware.h @@ -0,0 +1,39 @@ +/* + * include/asm-arm/arch-netx/hardware.h + * + * Copyright (C) 2005 Sascha Hauer , Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __ASM_ARCH_HARDWARE_H +#define __ASM_ARCH_HARDWARE_H + +#define NETX_IO_PHYS 0x00100000 +#define NETX_IO_VIRT 0xe0000000 +#define NETX_IO_SIZE 0x00100000 + +#define SRAM_INTERNAL_PHYS_0 0x00000 +#define SRAM_INTERNAL_PHYS_1 0x08000 +#define SRAM_INTERNAL_PHYS_2 0x10000 +#define SRAM_INTERNAL_PHYS_3 0x18000 +#define SRAM_INTERNAL_PHYS(no) ((no) * 0x8000) + +#define XPEC_MEM_SIZE 0x4000 +#define XMAC_MEM_SIZE 0x1000 +#define SRAM_MEM_SIZE 0x8000 + +#define io_p2v(x) ((x) - NETX_IO_PHYS + NETX_IO_VIRT) +#define io_v2p(x) ((x) - NETX_IO_VIRT + NETX_IO_PHYS) + +#endif diff --git a/include/asm-arm/arch-netx/io.h b/include/asm-arm/arch-netx/io.h new file mode 100644 index 00000000000..81b7bc47747 --- /dev/null +++ b/include/asm-arm/arch-netx/io.h @@ -0,0 +1,29 @@ +/* + * linux/include/asm-arm/arch-netx/io.h + * + * Copyright (C) 2005 Sascha Hauer , Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ASM_ARM_ARCH_IO_H +#define __ASM_ARM_ARCH_IO_H + +#define IO_SPACE_LIMIT 0xffffffff + +#define __io(a) ((void __iomem *)(a)) +#define __mem_pci(a) (a) +#define __mem_isa(a) (a) + +#endif diff --git a/include/asm-arm/arch-netx/irqs.h b/include/asm-arm/arch-netx/irqs.h new file mode 100644 index 00000000000..a487dc6e266 --- /dev/null +++ b/include/asm-arm/arch-netx/irqs.h @@ -0,0 +1,70 @@ +/* + * include/asm-arm/arch-netx/irqs.h + * + * Copyright (C) 2005 Sascha Hauer , Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define NETX_IRQ_VIC_START 0 +#define NETX_IRQ_SOFTINT 0 +#define NETX_IRQ_TIMER0 1 +#define NETX_IRQ_TIMER1 2 +#define NETX_IRQ_TIMER2 3 +#define NETX_IRQ_SYSTIME_NS 4 +#define NETX_IRQ_SYSTIME_S 5 +#define NETX_IRQ_GPIO_15 6 +#define NETX_IRQ_WATCHDOG 7 +#define NETX_IRQ_UART0 8 +#define NETX_IRQ_UART1 9 +#define NETX_IRQ_UART2 10 +#define NETX_IRQ_USB 11 +#define NETX_IRQ_SPI 12 +#define NETX_IRQ_I2C 13 +#define NETX_IRQ_LCD 14 +#define NETX_IRQ_HIF 15 +#define NETX_IRQ_GPIO_0_14 16 +#define NETX_IRQ_XPEC0 17 +#define NETX_IRQ_XPEC1 18 +#define NETX_IRQ_XPEC2 19 +#define NETX_IRQ_XPEC3 20 +#define NETX_IRQ_XPEC(no) (17 + (no)) +#define NETX_IRQ_MSYNC0 21 +#define NETX_IRQ_MSYNC1 22 +#define NETX_IRQ_MSYNC2 23 +#define NETX_IRQ_MSYNC3 24 +#define NETX_IRQ_IRQ_PHY 25 +#define NETX_IRQ_ISO_AREA 26 +/* int 27 is reserved */ +/* int 28 is reserved */ +#define NETX_IRQ_TIMER3 29 +#define NETX_IRQ_TIMER4 30 +/* int 31 is reserved */ + +#define NETX_IRQS 32 + +/* for multiplexed irqs on gpio 0..14 */ +#define NETX_IRQ_GPIO(x) (NETX_IRQS + (x)) +#define NETX_IRQ_GPIO_LAST NETX_IRQ_GPIO(14) + +/* Host interface interrupts */ +#define NETX_IRQ_HIF_CHAINED(x) (NETX_IRQ_GPIO_LAST + 1 + (x)) +#define NETX_IRQ_HIF_PIO35 NETX_IRQ_HIF_CHAINED(0) +#define NETX_IRQ_HIF_PIO36 NETX_IRQ_HIF_CHAINED(1) +#define NETX_IRQ_HIF_PIO40 NETX_IRQ_HIF_CHAINED(2) +#define NETX_IRQ_HIF_PIO47 NETX_IRQ_HIF_CHAINED(3) +#define NETX_IRQ_HIF_PIO72 NETX_IRQ_HIF_CHAINED(4) +#define NETX_IRQ_HIF_LAST NETX_IRQ_HIF_CHAINED(4) + +#define NR_IRQS (NETX_IRQ_HIF_LAST + 1) diff --git a/include/asm-arm/arch-netx/memory.h b/include/asm-arm/arch-netx/memory.h new file mode 100644 index 00000000000..6d8d2df3e99 --- /dev/null +++ b/include/asm-arm/arch-netx/memory.h @@ -0,0 +1,36 @@ +/* + * linux/include/asm-arm/arch-netx/memory.h + * + * Copyright (C) 2005 Sascha Hauer , Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ASM_ARCH_MEMORY_H +#define __ASM_ARCH_MEMORY_H + +#define PHYS_OFFSET UL(0x80000000) + +/* + * Virtual view <-> DMA view memory address translations + * virt_to_bus: Used to translate the virtual address to an + * address suitable to be passed to set_dma_addr + * bus_to_virt: Used to convert an address for DMA operations + * to an address that the kernel can use. + */ +#define __virt_to_bus(x) __virt_to_phys(x) +#define __bus_to_virt(x) __phys_to_virt(x) + +#endif + diff --git a/include/asm-arm/arch-netx/param.h b/include/asm-arm/arch-netx/param.h new file mode 100644 index 00000000000..7a80c26178a --- /dev/null +++ b/include/asm-arm/arch-netx/param.h @@ -0,0 +1,18 @@ +/* + * linux/include/asm-arm/arch-netx/param.h + * + * Copyright (C) 2005 Sascha Hauer , Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ diff --git a/include/asm-arm/arch-netx/system.h b/include/asm-arm/arch-netx/system.h new file mode 100644 index 00000000000..52adf368d76 --- /dev/null +++ b/include/asm-arm/arch-netx/system.h @@ -0,0 +1,38 @@ +/* + * include/asm-arm/arch-netx/system.h + * + * Copyright (C) 2005 Sascha Hauer , Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __ASM_ARCH_SYSTEM_H +#define __ASM_ARCH_SYSTEM_H + +#include +#include +#include "netx-regs.h" + +static inline void arch_idle(void) +{ + cpu_do_idle(); +} + +static inline void arch_reset(char mode) +{ + writel(NETX_SYSTEM_RES_CR_FIRMW_RES_EN | NETX_SYSTEM_RES_CR_FIRMW_RES, + NETX_SYSTEM_RES_CR); +} + +#endif + diff --git a/include/asm-arm/arch-netx/timex.h b/include/asm-arm/arch-netx/timex.h new file mode 100644 index 00000000000..7fdb42da0b4 --- /dev/null +++ b/include/asm-arm/arch-netx/timex.h @@ -0,0 +1,20 @@ +/* + * include/asm-arm/arch-netx/timex.h + * + * Copyright (C) 2005 Sascha Hauer , Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define CLOCK_TICK_RATE 100000000 diff --git a/include/asm-arm/arch-netx/uncompress.h b/include/asm-arm/arch-netx/uncompress.h new file mode 100644 index 00000000000..f8943454710 --- /dev/null +++ b/include/asm-arm/arch-netx/uncompress.h @@ -0,0 +1,76 @@ +/* + * include/asm-arm/arch-netx/uncompress.h + * + * Copyright (C) 2005 Sascha Hauer , Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * The following code assumes the serial port has already been + * initialized by the bootloader. We search for the first enabled + * port in the most probable order. If you didn't setup a port in + * your bootloader then nothing will appear (which might be desired). + * + * This does not append a newline + */ + +#define REG(x) (*(volatile unsigned long *)(x)) + +#define UART1_BASE 0x100a00 +#define UART2_BASE 0x100a80 + +#define UART_DR 0x0 + +#define UART_CR 0x14 +#define CR_UART_EN (1<<0) + +#define UART_FR 0x18 +#define FR_BUSY (1<<3) +#define FR_TXFF (1<<5) + +static void putc(char c) +{ + unsigned long base; + + if (REG(UART1_BASE + UART_CR) & CR_UART_EN) + base = UART1_BASE; + else if (REG(UART2_BASE + UART_CR) & CR_UART_EN) + base = UART2_BASE; + else + return; + + while (REG(base + UART_FR) & FR_TXFF); + REG(base + UART_DR) = c; +} + +static inline void flush(void) +{ + unsigned long base; + + if (REG(UART1_BASE + UART_CR) & CR_UART_EN) + base = UART1_BASE; + else if (REG(UART2_BASE + UART_CR) & CR_UART_EN) + base = UART2_BASE; + else + return; + + while (REG(base + UART_FR) & FR_BUSY); +} + +/* + * nothing to do + */ +#define arch_decomp_setup() +#define arch_decomp_wdog() diff --git a/include/asm-arm/arch-netx/vmalloc.h b/include/asm-arm/arch-netx/vmalloc.h new file mode 100644 index 00000000000..da2da5a595d --- /dev/null +++ b/include/asm-arm/arch-netx/vmalloc.h @@ -0,0 +1,19 @@ +/* + * linux/include/asm-arm/arch-netx/vmalloc.h + * + * Copyright (C) 2005 Sascha Hauer , Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#define VMALLOC_END (PAGE_OFFSET + 0x10000000) -- cgit v1.2.3 From ef70cd4d247defcd7c0f789a5a98deab0afadf53 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 19 Jun 2006 15:28:19 +0100 Subject: [ARM] 3568/2: netX: pointer fifo driver Patch from Sascha Hauer This patch adds support for the pointer FIFOs on netX. Signed-off-by: Robert Schwebel Signed-off-by: Sascha Hauer Signed-off-by: Russell King --- arch/arm/mach-netx/Makefile | 2 +- arch/arm/mach-netx/pfifo.c | 68 +++++++++++++++++++++++++++++++++++++++ include/asm-arm/arch-netx/pfifo.h | 54 +++++++++++++++++++++++++++++++ 3 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-netx/pfifo.c create mode 100644 include/asm-arm/arch-netx/pfifo.h diff --git a/arch/arm/mach-netx/Makefile b/arch/arm/mach-netx/Makefile index 257d02ef66d..cd424083e5b 100644 --- a/arch/arm/mach-netx/Makefile +++ b/arch/arm/mach-netx/Makefile @@ -7,5 +7,5 @@ # Object file lists. -obj-y += time.o generic.o +obj-y += time.o generic.o pfifo.o diff --git a/arch/arm/mach-netx/pfifo.c b/arch/arm/mach-netx/pfifo.c new file mode 100644 index 00000000000..44dea61a9de --- /dev/null +++ b/arch/arm/mach-netx/pfifo.c @@ -0,0 +1,68 @@ +/* + * arch/arm/mach-netx/pfifo.c + * + * Copyright (c) 2005 Sascha Hauer , Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include +#include +#include +#include + +static DEFINE_MUTEX(pfifo_lock); + +static unsigned int pfifo_used = 0; + +int pfifo_request(unsigned int pfifo_mask) +{ + int err = 0; + unsigned int val; + + mutex_lock(&pfifo_lock); + + if (pfifo_mask & pfifo_used) { + err = -EBUSY; + goto out; + } + + pfifo_used |= pfifo_mask; + + val = readl(NETX_PFIFO_RESET); + writel(val | pfifo_mask, NETX_PFIFO_RESET); + writel(val, NETX_PFIFO_RESET); + +out: + mutex_unlock(&pfifo_lock); + return err; +} + +void pfifo_free(unsigned int pfifo_mask) +{ + mutex_lock(&pfifo_lock); + pfifo_used &= ~pfifo_mask; + mutex_unlock(&pfifo_lock); +} + +EXPORT_SYMBOL(pfifo_push); +EXPORT_SYMBOL(pfifo_pop); +EXPORT_SYMBOL(pfifo_fill_level); +EXPORT_SYMBOL(pfifo_empty); +EXPORT_SYMBOL(pfifo_request); +EXPORT_SYMBOL(pfifo_free); diff --git a/include/asm-arm/arch-netx/pfifo.h b/include/asm-arm/arch-netx/pfifo.h new file mode 100644 index 00000000000..4af2ee4a32c --- /dev/null +++ b/include/asm-arm/arch-netx/pfifo.h @@ -0,0 +1,54 @@ +/* + * include/asm-arm/arch-netx/pfifo.h + * + * Copyright (c) 2005 Sascha Hauer , Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef ASM_ARCH_PFIFO_H +#define ASM_ARCH_PFIFO_H + +static inline int pfifo_push(int no, unsigned int pointer) +{ + writel(pointer, NETX_PFIFO_BASE(no)); + return 0; +} + +static inline unsigned int pfifo_pop(int no) +{ + return readl(NETX_PFIFO_BASE(no)); +} + +static inline int pfifo_fill_level(int no) +{ + + return readl(NETX_PFIFO_FILL_LEVEL(no)); +} + +static inline int pfifo_full(int no) +{ + return readl(NETX_PFIFO_FULL) & (1< Date: Mon, 19 Jun 2006 15:28:20 +0100 Subject: [ARM] 3569/2: netX: driver for XMAC/XPEC engines Patch from Sascha Hauer The netX processors have generic network bitstream engines (XMAC/XPEC). This driver adds support for firmware loading and start, stop, reset commands. Signed-off-by: Robert Schwebel Signed-off-by: Sascha Hauer Signed-off-by: Russell King --- arch/arm/mach-netx/Makefile | 2 +- arch/arm/mach-netx/xc.c | 255 +++++++++++++++++++++++++++++++++++++++++ include/asm-arm/arch-netx/xc.h | 42 +++++++ 3 files changed, 298 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-netx/xc.c create mode 100644 include/asm-arm/arch-netx/xc.h diff --git a/arch/arm/mach-netx/Makefile b/arch/arm/mach-netx/Makefile index cd424083e5b..b2b7dd25f21 100644 --- a/arch/arm/mach-netx/Makefile +++ b/arch/arm/mach-netx/Makefile @@ -7,5 +7,5 @@ # Object file lists. -obj-y += time.o generic.o pfifo.o +obj-y += time.o generic.o pfifo.o xc.o diff --git a/arch/arm/mach-netx/xc.c b/arch/arm/mach-netx/xc.c new file mode 100644 index 00000000000..172a058ddd6 --- /dev/null +++ b/arch/arm/mach-netx/xc.c @@ -0,0 +1,255 @@ +/* + * arch/arm/mach-netx/xc.c + * + * Copyright (c) 2005 Sascha Hauer , Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include + +static DEFINE_MUTEX(xc_lock); + +static int xc_in_use = 0; + +struct fw_desc { + unsigned int ofs; + unsigned int size; + unsigned int patch_ofs; + unsigned int patch_entries; +}; + +struct fw_header { + unsigned int magic; + unsigned int type; + unsigned int version; + unsigned int reserved[5]; + struct fw_desc fw_desc[3]; +} __attribute__ ((packed)); + +int xc_stop(struct xc *x) +{ + writel(RPU_HOLD_PC, x->xmac_base + NETX_XMAC_RPU_HOLD_PC_OFS); + writel(TPU_HOLD_PC, x->xmac_base + NETX_XMAC_TPU_HOLD_PC_OFS); + writel(XPU_HOLD_PC, x->xpec_base + NETX_XPEC_XPU_HOLD_PC_OFS); + return 0; +} + +int xc_start(struct xc *x) +{ + writel(0, x->xmac_base + NETX_XMAC_RPU_HOLD_PC_OFS); + writel(0, x->xmac_base + NETX_XMAC_TPU_HOLD_PC_OFS); + writel(0, x->xpec_base + NETX_XPEC_XPU_HOLD_PC_OFS); + return 0; +} + +int xc_running(struct xc *x) +{ + return (readl(x->xmac_base + NETX_XMAC_RPU_HOLD_PC_OFS) & RPU_HOLD_PC) + || (readl(x->xmac_base + NETX_XMAC_TPU_HOLD_PC_OFS) & TPU_HOLD_PC) + || (readl(x->xpec_base + NETX_XPEC_XPU_HOLD_PC_OFS) & XPU_HOLD_PC) ? + 0 : 1; +} + +int xc_reset(struct xc *x) +{ + writel(0, x->xpec_base + NETX_XPEC_PC_OFS); + return 0; +} + +static int xc_check_ptr(struct xc *x, unsigned long adr, unsigned int size) +{ + if (adr >= NETX_PA_XMAC(x->no) && + adr + size < NETX_PA_XMAC(x->no) + XMAC_MEM_SIZE) + return 0; + + if (adr >= NETX_PA_XPEC(x->no) && + adr + size < NETX_PA_XPEC(x->no) + XPEC_MEM_SIZE) + return 0; + + dev_err(x->dev, "Illegal pointer in firmware found. aborting\n"); + + return -1; +} + +static int xc_patch(struct xc *x, void *patch, int count) +{ + unsigned int val, adr; + unsigned int *data = patch; + + int i; + for (i = 0; i < count; i++) { + adr = *data++; + val = *data++; + if (xc_check_ptr(x, adr, 4) < 0) + return -EINVAL; + + writel(val, (void __iomem *)io_p2v(adr)); + } + return 0; +} + +int xc_request_firmware(struct xc *x) +{ + int ret; + char name[16]; + const struct firmware *fw; + struct fw_header *head; + unsigned int size; + int i; + void *src; + unsigned long dst; + + sprintf(name, "xc%d.bin", x->no); + + ret = request_firmware(&fw, name, x->dev); + + if (ret < 0) { + dev_err(x->dev, "request_firmware failed\n"); + return ret; + } + + head = (struct fw_header *)fw->data; + if (head->magic != 0x4e657458) { + if (head->magic == 0x5874654e) { + dev_err(x->dev, + "firmware magic is 'XteN'. Endianess problems?\n"); + ret = -ENODEV; + goto exit_release_firmware; + } + dev_err(x->dev, "unrecognized firmware magic 0x%08x\n", + head->magic); + ret = -ENODEV; + goto exit_release_firmware; + } + + x->type = head->type; + x->version = head->version; + + ret = -EINVAL; + + for (i = 0; i < 3; i++) { + src = fw->data + head->fw_desc[i].ofs; + dst = *(unsigned int *)src; + src += sizeof (unsigned int); + size = head->fw_desc[i].size - sizeof (unsigned int); + + if (xc_check_ptr(x, dst, size)) + goto exit_release_firmware; + + memcpy((void *)io_p2v(dst), src, size); + + src = fw->data + head->fw_desc[i].patch_ofs; + size = head->fw_desc[i].patch_entries; + ret = xc_patch(x, src, size); + if (ret < 0) + goto exit_release_firmware; + } + + ret = 0; + + exit_release_firmware: + release_firmware(fw); + + return ret; +} + +struct xc *request_xc(int xcno, struct device *dev) +{ + struct xc *x = NULL; + + mutex_lock(&xc_lock); + + if (xcno > 3) + goto exit; + if (xc_in_use & (1 << xcno)) + goto exit; + + x = kmalloc(sizeof (struct xc), GFP_KERNEL); + if (!x) + goto exit; + + if (!request_mem_region + (NETX_PA_XPEC(xcno), XPEC_MEM_SIZE, dev->kobj.name)) + goto exit_free; + + if (!request_mem_region + (NETX_PA_XMAC(xcno), XMAC_MEM_SIZE, dev->kobj.name)) + goto exit_release_1; + + if (!request_mem_region + (SRAM_INTERNAL_PHYS(xcno), SRAM_MEM_SIZE, dev->kobj.name)) + goto exit_release_2; + + x->xpec_base = (void * __iomem)io_p2v(NETX_PA_XPEC(xcno)); + x->xmac_base = (void * __iomem)io_p2v(NETX_PA_XMAC(xcno)); + x->sram_base = ioremap(SRAM_INTERNAL_PHYS(xcno), SRAM_MEM_SIZE); + if (!x->sram_base) + goto exit_release_3; + + x->irq = NETX_IRQ_XPEC(xcno); + + x->no = xcno; + x->dev = dev; + + xc_in_use |= (1 << xcno); + + goto exit; + + exit_release_3: + release_mem_region(SRAM_INTERNAL_PHYS(xcno), SRAM_MEM_SIZE); + exit_release_2: + release_mem_region(NETX_PA_XMAC(xcno), XMAC_MEM_SIZE); + exit_release_1: + release_mem_region(NETX_PA_XPEC(xcno), XPEC_MEM_SIZE); + exit_free: + kfree(x); + x = NULL; + exit: + mutex_unlock(&xc_lock); + return x; +} + +void free_xc(struct xc *x) +{ + int xcno = x->no; + + mutex_lock(&xc_lock); + + iounmap(x->sram_base); + release_mem_region(SRAM_INTERNAL_PHYS(xcno), SRAM_MEM_SIZE); + release_mem_region(NETX_PA_XMAC(xcno), XMAC_MEM_SIZE); + release_mem_region(NETX_PA_XPEC(xcno), XPEC_MEM_SIZE); + xc_in_use &= ~(1 << x->no); + kfree(x); + + mutex_unlock(&xc_lock); +} + +EXPORT_SYMBOL(free_xc); +EXPORT_SYMBOL(request_xc); +EXPORT_SYMBOL(xc_request_firmware); +EXPORT_SYMBOL(xc_reset); +EXPORT_SYMBOL(xc_running); +EXPORT_SYMBOL(xc_start); +EXPORT_SYMBOL(xc_stop); diff --git a/include/asm-arm/arch-netx/xc.h b/include/asm-arm/arch-netx/xc.h new file mode 100644 index 00000000000..659af19512a --- /dev/null +++ b/include/asm-arm/arch-netx/xc.h @@ -0,0 +1,42 @@ +/* + * linux/include/asm-arm/arch-netx/xc.h + * + * Copyright (C) 2005 Sascha Hauer , Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ASM_ARCH_XC_H +#define __ASM_ARCH_XC_H + +struct xc { + int no; + unsigned int type; + unsigned int version; + void __iomem *xpec_base; + void __iomem *xmac_base; + void __iomem *sram_base; + int irq; + struct device *dev; +}; + +int xc_reset(struct xc *x); +int xc_stop(struct xc* x); +int xc_start(struct xc *x); +int xc_running(struct xc *x); +int xc_request_firmware(struct xc* x); +struct xc* request_xc(int xcno, struct device *dev); +void free_xc(struct xc *x); + +#endif /* __ASM_ARCH_XC_H */ -- cgit v1.2.3 From 693532dcff871543639743e9c2e2b99c492f8f8d Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 19 Jun 2006 15:29:43 +0100 Subject: [ARM] 3574/1: netX: board support for NXDKN development board Patch from Sascha Hauer This patch adds the board specific code for the Hilscher NXDKN development board. Signed-off-by: Robert Schwebel Signed-off-by: Sascha Hauer Signed-off-by: Russell King --- arch/arm/mach-netx/Kconfig | 10 +++++ arch/arm/mach-netx/Makefile | 3 ++ arch/arm/mach-netx/nxdkn.c | 103 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 116 insertions(+) create mode 100644 arch/arm/mach-netx/Kconfig create mode 100644 arch/arm/mach-netx/nxdkn.c diff --git a/arch/arm/mach-netx/Kconfig b/arch/arm/mach-netx/Kconfig new file mode 100644 index 00000000000..a236dd0c64f --- /dev/null +++ b/arch/arm/mach-netx/Kconfig @@ -0,0 +1,10 @@ +menu "NetX Implementations" + depends on ARCH_NETX + +config MACH_NXDKN + bool "Enable Hilscher nxdkn Eval Board support" + depends on ARCH_NETX + help + Board support for the Hilscher NetX Eval Board + +endmenu diff --git a/arch/arm/mach-netx/Makefile b/arch/arm/mach-netx/Makefile index b2b7dd25f21..c5e3b18b798 100644 --- a/arch/arm/mach-netx/Makefile +++ b/arch/arm/mach-netx/Makefile @@ -9,3 +9,6 @@ obj-y += time.o generic.o pfifo.o xc.o +# Specific board support +obj-$(CONFIG_MACH_NXDKN) += nxdkn.o + diff --git a/arch/arm/mach-netx/nxdkn.c b/arch/arm/mach-netx/nxdkn.c new file mode 100644 index 00000000000..7e26c42d1ac --- /dev/null +++ b/arch/arm/mach-netx/nxdkn.c @@ -0,0 +1,103 @@ +/* + * arch/arm/mach-netx/nxdkn.c + * + * Copyright (c) 2005 Sascha Hauer , Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "generic.h" + +static struct netxeth_platform_data eth0_platform_data = { + .xcno = 0, +}; + +static struct platform_device nxdkn_eth0_device = { + .name = "netx-eth", + .id = 0, + .num_resources = 0, + .resource = NULL, + .dev = { + .platform_data = ð0_platform_data, + } +}; + +static struct netxeth_platform_data eth1_platform_data = { + .xcno = 1, +}; + +static struct platform_device nxdkn_eth1_device = { + .name = "netx-eth", + .id = 1, + .num_resources = 0, + .resource = NULL, + .dev = { + .platform_data = ð1_platform_data, + } +}; + +static struct resource netx_uart0_resources[] = { + [0] = { + .start = 0x00100A00, + .end = 0x00100A3F, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = (NETX_IRQ_UART0), + .end = (NETX_IRQ_UART0), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device netx_uart0_device = { + .name = "netx-uart", + .id = 0, + .num_resources = ARRAY_SIZE(netx_uart0_resources), + .resource = netx_uart0_resources, +}; + +static struct platform_device *devices[] __initdata = { + &nxdkn_eth0_device, + &nxdkn_eth1_device, + &netx_uart0_device, +}; + +static void __init nxdkn_init(void) +{ + platform_add_devices(devices, ARRAY_SIZE(devices)); +} + +MACHINE_START(NXDKN, "Hilscher nxdkn") + .phys_io = 0x00100000, + .io_pg_offst = (io_p2v(0x00100000) >> 18) & 0xfffc, + .boot_params = 0x80000100, + .map_io = netx_map_io, + .init_irq = netx_init_irq, + .timer = &netx_timer, + .init_machine = nxdkn_init, +MACHINE_END -- cgit v1.2.3 From af614ba072dab2940471fec1f30bd59b8272fc6b Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 19 Jun 2006 15:29:44 +0100 Subject: [ARM] 3575/1: netX: board support for NXDB500 development board Patch from Sascha Hauer This patch adds the board specific code for the Hilscher NXDB500 development board. Signed-off-by: Robert Schwebel Signed-off-by: Sascha Hauer Signed-off-by: Russell King --- arch/arm/mach-netx/Kconfig | 7 ++ arch/arm/mach-netx/Makefile | 2 +- arch/arm/mach-netx/nxdb500.c | 210 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 218 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-netx/nxdb500.c diff --git a/arch/arm/mach-netx/Kconfig b/arch/arm/mach-netx/Kconfig index a236dd0c64f..93dda3bd347 100644 --- a/arch/arm/mach-netx/Kconfig +++ b/arch/arm/mach-netx/Kconfig @@ -7,4 +7,11 @@ config MACH_NXDKN help Board support for the Hilscher NetX Eval Board +config MACH_NXDB500 + bool "Enable Hilscher nxdb500 Eval Board support" + depends on ARCH_NETX + select ARM_AMBA + help + Board support for the Hilscher nxdb500 Eval Board + endmenu diff --git a/arch/arm/mach-netx/Makefile b/arch/arm/mach-netx/Makefile index c5e3b18b798..eafb24fd0e1 100644 --- a/arch/arm/mach-netx/Makefile +++ b/arch/arm/mach-netx/Makefile @@ -11,4 +11,4 @@ obj-y += time.o generic.o pfifo.o xc.o # Specific board support obj-$(CONFIG_MACH_NXDKN) += nxdkn.o - +obj-$(CONFIG_MACH_NXDB500) += nxdb500.o fb.o diff --git a/arch/arm/mach-netx/nxdb500.c b/arch/arm/mach-netx/nxdb500.c new file mode 100644 index 00000000000..e4a133d6284 --- /dev/null +++ b/arch/arm/mach-netx/nxdb500.c @@ -0,0 +1,210 @@ +/* + * arch/arm/mach-netx/nxdb500.c + * + * Copyright (c) 2005 Sascha Hauer , Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "generic.h" +#include "fb.h" + +static struct clcd_panel qvga = { + .mode = { + .name = "QVGA", + .refresh = 60, + .xres = 240, + .yres = 320, + .pixclock = 187617, + .left_margin = 6, + .right_margin = 26, + .upper_margin = 0, + .lower_margin = 6, + .hsync_len = 6, + .vsync_len = 1, + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED, + }, + .width = -1, + .height = -1, + .tim2 = 16, + .cntl = CNTL_LCDTFT | CNTL_BGR, + .bpp = 16, + .grayscale = 0, +}; + +static inline int nxdb500_check(struct clcd_fb *fb, struct fb_var_screeninfo *var) +{ + var->green.length = 5; + var->green.msb_right = 0; + + return clcdfb_check(fb, var); +} + +static int nxdb500_clcd_setup(struct clcd_fb *fb) +{ + unsigned int val; + + fb->fb.var.green.length = 5; + fb->fb.var.green.msb_right = 0; + + /* enable asic control */ + val = readl(NETX_SYSTEM_IOC_ACCESS_KEY); + writel(val, NETX_SYSTEM_IOC_ACCESS_KEY); + + writel(3, NETX_SYSTEM_IOC_CR); + + val = readl(NETX_PIO_OUTPIO); + writel(val | 1, NETX_PIO_OUTPIO); + + val = readl(NETX_PIO_OEPIO); + writel(val | 1, NETX_PIO_OEPIO); + return netx_clcd_setup(fb); +} + +static struct clcd_board clcd_data = { + .name = "netX", + .check = nxdb500_check, + .decode = clcdfb_decode, + .enable = netx_clcd_enable, + .setup = nxdb500_clcd_setup, + .mmap = netx_clcd_mmap, + .remove = netx_clcd_remove, +}; + +static struct netxeth_platform_data eth0_platform_data = { + .xcno = 0, +}; + +static struct platform_device netx_eth0_device = { + .name = "netx-eth", + .id = 0, + .num_resources = 0, + .resource = NULL, + .dev = { + .platform_data = ð0_platform_data, + } +}; + +static struct netxeth_platform_data eth1_platform_data = { + .xcno = 1, +}; + +static struct platform_device netx_eth1_device = { + .name = "netx-eth", + .id = 1, + .num_resources = 0, + .resource = NULL, + .dev = { + .platform_data = ð1_platform_data, + } +}; + +static struct resource netx_uart0_resources[] = { + [0] = { + .start = 0x00100A00, + .end = 0x00100A3F, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = (NETX_IRQ_UART0), + .end = (NETX_IRQ_UART0), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device netx_uart0_device = { + .name = "netx-uart", + .id = 0, + .num_resources = ARRAY_SIZE(netx_uart0_resources), + .resource = netx_uart0_resources, +}; + +static struct resource netx_uart1_resources[] = { + [0] = { + .start = 0x00100A40, + .end = 0x00100A7F, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = (NETX_IRQ_UART1), + .end = (NETX_IRQ_UART1), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device netx_uart1_device = { + .name = "netx-uart", + .id = 1, + .num_resources = ARRAY_SIZE(netx_uart1_resources), + .resource = netx_uart1_resources, +}; + +static struct resource netx_uart2_resources[] = { + [0] = { + .start = 0x00100A80, + .end = 0x00100ABF, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = (NETX_IRQ_UART2), + .end = (NETX_IRQ_UART2), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device netx_uart2_device = { + .name = "netx-uart", + .id = 2, + .num_resources = ARRAY_SIZE(netx_uart2_resources), + .resource = netx_uart2_resources, +}; + +static struct platform_device *devices[] __initdata = { + &netx_eth0_device, + &netx_eth1_device, + &netx_uart0_device, + &netx_uart1_device, + &netx_uart2_device, +}; + +static void __init nxdb500_init(void) +{ + netx_fb_init(&clcd_data, &qvga); + platform_add_devices(devices, ARRAY_SIZE(devices)); +} + +MACHINE_START(NXDB500, "Hilscher nxdb500") + .phys_io = 0x00100000, + .io_pg_offst = (io_p2v(0x00100000) >> 18) & 0xfffc, + .boot_params = 0x80000100, + .map_io = netx_map_io, + .init_irq = netx_init_irq, + .timer = &netx_timer, + .init_machine = nxdb500_init, +MACHINE_END -- cgit v1.2.3 From 2697c5e1f799f201366d5fd7d25e96a21587f1a9 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 19 Jun 2006 15:29:45 +0100 Subject: [ARM] 3576/1: netX: board support for NXEB500HMI development board Patch from Sascha Hauer This patch adds the board specific code for the Hilscher NXEB500HMI development board. Signed-off-by: Robert Schwebel Signed-off-by: Sascha Hauer Signed-off-by: Russell King --- arch/arm/mach-netx/Kconfig | 7 ++ arch/arm/mach-netx/Makefile | 1 + arch/arm/mach-netx/nxeb500hmi.c | 187 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 195 insertions(+) create mode 100644 arch/arm/mach-netx/nxeb500hmi.c diff --git a/arch/arm/mach-netx/Kconfig b/arch/arm/mach-netx/Kconfig index 93dda3bd347..3d90ef19be2 100644 --- a/arch/arm/mach-netx/Kconfig +++ b/arch/arm/mach-netx/Kconfig @@ -14,4 +14,11 @@ config MACH_NXDB500 help Board support for the Hilscher nxdb500 Eval Board +config MACH_NXEB500HMI + bool "Enable Hilscher nxeb500hmi Eval Board support" + depends on ARCH_NETX + select ARM_AMBA + help + Board support for the Hilscher nxeb500hmi Eval Board + endmenu diff --git a/arch/arm/mach-netx/Makefile b/arch/arm/mach-netx/Makefile index eafb24fd0e1..18785ff3765 100644 --- a/arch/arm/mach-netx/Makefile +++ b/arch/arm/mach-netx/Makefile @@ -12,3 +12,4 @@ obj-y += time.o generic.o pfifo.o xc.o # Specific board support obj-$(CONFIG_MACH_NXDKN) += nxdkn.o obj-$(CONFIG_MACH_NXDB500) += nxdb500.o fb.o +obj-$(CONFIG_MACH_NXEB500HMI) += nxeb500hmi.o fb.o diff --git a/arch/arm/mach-netx/nxeb500hmi.c b/arch/arm/mach-netx/nxeb500hmi.c new file mode 100644 index 00000000000..53e10a9849f --- /dev/null +++ b/arch/arm/mach-netx/nxeb500hmi.c @@ -0,0 +1,187 @@ +/* + * arch/arm/mach-netx/nxeb500hmi.c + * + * Copyright (c) 2005 Sascha Hauer , Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "generic.h" +#include "fb.h" + +static struct clcd_panel qvga = { + .mode = { + .name = "QVGA", + .refresh = 60, + .xres = 240, + .yres = 320, + .pixclock = 187617, + .left_margin = 6, + .right_margin = 26, + .upper_margin = 0, + .lower_margin = 6, + .hsync_len = 6, + .vsync_len = 1, + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED, + }, + .width = -1, + .height = -1, + .tim2 = 16, + .cntl = CNTL_LCDTFT | CNTL_BGR, + .bpp = 16, + .grayscale = 0, +}; + +static inline int nxeb500hmi_check(struct clcd_fb *fb, struct fb_var_screeninfo *var) +{ + var->green.length = 5; + var->green.msb_right = 0; + + return clcdfb_check(fb, var); +} + +static int nxeb500hmi_clcd_setup(struct clcd_fb *fb) +{ + unsigned int val; + + fb->fb.var.green.length = 5; + fb->fb.var.green.msb_right = 0; + + /* enable asic control */ + val = readl(NETX_SYSTEM_IOC_ACCESS_KEY); + writel(val, NETX_SYSTEM_IOC_ACCESS_KEY); + + writel(3, NETX_SYSTEM_IOC_CR); + + /* GPIO 14 is used for display enable on newer boards */ + writel(9, NETX_GPIO_CFG(14)); + + val = readl(NETX_PIO_OUTPIO); + writel(val | 1, NETX_PIO_OUTPIO); + + val = readl(NETX_PIO_OEPIO); + writel(val | 1, NETX_PIO_OEPIO); + return netx_clcd_setup(fb); +} + +static struct clcd_board clcd_data = { + .name = "netX", + .check = nxeb500hmi_check, + .decode = clcdfb_decode, + .enable = netx_clcd_enable, + .setup = nxeb500hmi_clcd_setup, + .mmap = netx_clcd_mmap, + .remove = netx_clcd_remove, +}; + +static struct netxeth_platform_data eth0_platform_data = { + .xcno = 0, +}; + +static struct platform_device netx_eth0_device = { + .name = "netx-eth", + .id = 0, + .num_resources = 0, + .resource = NULL, + .dev = { + .platform_data = ð0_platform_data, + } +}; + +static struct netxeth_platform_data eth1_platform_data = { + .xcno = 1, +}; + +static struct platform_device netx_eth1_device = { + .name = "netx-eth", + .id = 1, + .num_resources = 0, + .resource = NULL, + .dev = { + .platform_data = ð1_platform_data, + } +}; + +static struct resource netx_cf_resources[] = { + [0] = { + .start = 0x20000000, + .end = 0x25ffffff, + .flags = IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT, + }, +}; + +static struct platform_device netx_cf_device = { + .name = "netx-cf", + .id = 0, + .resource = netx_cf_resources, + .num_resources = ARRAY_SIZE(netx_cf_resources), +}; + +static struct resource netx_uart0_resources[] = { + [0] = { + .start = 0x00100A00, + .end = 0x00100A3F, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = (NETX_IRQ_UART0), + .end = (NETX_IRQ_UART0), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device netx_uart0_device = { + .name = "netx-uart", + .id = 0, + .num_resources = ARRAY_SIZE(netx_uart0_resources), + .resource = netx_uart0_resources, +}; + +static struct platform_device *devices[] __initdata = { + &netx_eth0_device, + &netx_eth1_device, + &netx_cf_device, + &netx_uart0_device, +}; + +static void __init nxeb500hmi_init(void) +{ + netx_fb_init(&clcd_data, &qvga); + platform_add_devices(devices, ARRAY_SIZE(devices)); +} + +MACHINE_START(NXEB500HMI, "Hilscher nxeb500hmi") + .phys_io = 0x00100000, + .io_pg_offst = (io_p2v(0x00100000) >> 18) & 0xfffc, + .boot_params = 0x80000100, + .map_io = netx_map_io, + .init_irq = netx_init_irq, + .timer = &netx_timer, + .init_machine = nxeb500hmi_init, +MACHINE_END -- cgit v1.2.3 From 5e6423871772b89120c9fb356d2eabb67fea60bd Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 19 Jun 2006 15:30:21 +0100 Subject: [ARM] 3577/1: netX: Default config for netx based boards Patch from Sascha Hauer This patch adds the default config file for netx based boards. Signed-off-by: Robert Schwebel Signed-off-by: Sascha Hauer Signed-off-by: Russell King --- arch/arm/configs/netx_defconfig | 926 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 926 insertions(+) create mode 100644 arch/arm/configs/netx_defconfig diff --git a/arch/arm/configs/netx_defconfig b/arch/arm/configs/netx_defconfig new file mode 100644 index 00000000000..61115a77338 --- /dev/null +++ b/arch/arm/configs/netx_defconfig @@ -0,0 +1,926 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.17-rc6 +# Tue Jun 6 15:26:53 2006 +# +CONFIG_ARM=y +CONFIG_MMU=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_VECTORS_BASE=0xffff0000 + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +# CONFIG_RELAY is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_UID16=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_EMBEDDED is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set +CONFIG_OBSOLETE_INTERMODULE=y + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y + +# +# Block layer +# +# CONFIG_BLK_DEV_IO_TRACE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" + +# +# System Type +# +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_IOP3XX is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_AT91RM9200 is not set +CONFIG_ARCH_NETX=y + +# +# NetX Implementations +# +CONFIG_MACH_NXDKN=y +CONFIG_MACH_NXDB500=y +CONFIG_MACH_NXEB500HMI=y + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_ARM926T=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5TJ=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set +# CONFIG_CPU_CACHE_ROUND_ROBIN is not set +CONFIG_ARM_VIC=y + +# +# Bus support +# +CONFIG_ARM_AMBA=y + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_PREEMPT=y +# CONFIG_NO_IDLE_HZ is not set +CONFIG_HZ=100 +# CONFIG_AEABI is not set +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4096 +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="console=ttySMX0,115200" +# CONFIG_XIP_KERNEL is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +# CONFIG_FPE_NWFPE is not set +# CONFIG_FPE_FASTFPE is not set +# CONFIG_VFP is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set +# CONFIG_ARTHUR is not set + +# +# Power management options +# +# CONFIG_PM is not set +# CONFIG_APM is not set + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=m +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +CONFIG_NET_IPGRE=m +# CONFIG_NET_IPGRE_BROADCAST is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y +CONFIG_INET_XFRM_TUNNEL=y +CONFIG_INET_TUNNEL=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set +CONFIG_IPV6=m +# CONFIG_IPV6_PRIVACY is not set +# CONFIG_IPV6_ROUTER_PREF is not set +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +# CONFIG_IPV6_TUNNEL is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set + +# +# Core Netfilter Configuration +# +# CONFIG_NETFILTER_NETLINK is not set +# CONFIG_NETFILTER_XTABLES is not set + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +# CONFIG_IP_NF_CT_ACCT is not set +# CONFIG_IP_NF_CONNTRACK_MARK is not set +# CONFIG_IP_NF_CONNTRACK_EVENTS is not set +# CONFIG_IP_NF_CT_PROTO_SCTP is not set +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +# CONFIG_IP_NF_NETBIOS_NS is not set +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +# CONFIG_IP_NF_PPTP is not set +# CONFIG_IP_NF_H323 is not set +CONFIG_IP_NF_QUEUE=m + +# +# IPv6: Netfilter Configuration (EXPERIMENTAL) +# +# CONFIG_IP6_NF_QUEUE is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +CONFIG_NET_PKTGEN=m +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_DEBUG_DRIVER is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=y +# CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +CONFIG_MTD_RAM=y +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_ARM_INTEGRATOR is not set +CONFIG_MTD_PLATRAM=y + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_CRYPTOLOOP=m +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# I2O device support +# + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# PHY device support +# +# CONFIG_PHYLIB is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_SMC91X is not set +CONFIG_NET_NETX=y +# CONFIG_DM9000 is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_AMBAKMI is not set +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_AMBA_PL010 is not set +# CONFIG_SERIAL_AMBA_PL011 is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_NETX=y +CONFIG_SERIAL_NETX_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +CONFIG_NVRAM=m +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +# CONFIG_HWMON is not set +# CONFIG_HWMON_VID is not set + +# +# Misc devices +# + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set +CONFIG_VIDEO_V4L2=y + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_MACMODES is not set +CONFIG_FB_FIRMWARE_EDID=y +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set +CONFIG_FB_ARMCLCD=y +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Logo configuration +# +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y +CONFIG_LOGO_LINUX_CLUT224=y +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +# CONFIG_USB_ARCH_HAS_OHCI is not set +# CONFIG_USB_ARCH_HAS_EHCI is not set +# CONFIG_USB is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# Real Time Clock +# +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=m + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=m +CONFIG_RTC_INTF_PROC=m +CONFIG_RTC_INTF_DEV=m + +# +# RTC drivers +# +# CONFIG_RTC_DRV_M48T86 is not set +CONFIG_RTC_DRV_NETX=m +# CONFIG_RTC_DRV_TEST is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +CONFIG_NFS_V4=y +CONFIG_NFS_DIRECTIO=y +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +CONFIG_DEBUG_PREEMPT=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_DEBUG_VM is not set +CONFIG_FRAME_POINTER=y +# CONFIG_UNWIND_INFO is not set +CONFIG_FORCED_INLINING=y +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_WAITQ is not set +CONFIG_DEBUG_ERRORS=y +# CONFIG_DEBUG_LL is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +CONFIG_CRYPTO_DES=y +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +# CONFIG_CRYPTO_TEA is not set +CONFIG_CRYPTO_ARC4=m +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_CRC32C=m +# CONFIG_CRYPTO_TEST is not set + +# +# Hardware crypto devices +# + +# +# Library routines +# +CONFIG_CRC_CCITT=m +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +CONFIG_LIBCRC32C=m +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y -- cgit v1.2.3 From 441ff855f3edf5d355bea30f557bbed6bcd42c6c Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 19 Jun 2006 15:35:36 +0100 Subject: [ARM] Fix byte order macros for Thumb The byte order functions are visible to userspace. Unfortunately, __arch_swab32() contains an assembly instruction which is invalid when compiling for Thumb. This reverts to the C version when compiling for Thumb. Signed-off-by: H. Peter Anvin Signed-off-by: Russell King --- include/asm-arm/byteorder.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/include/asm-arm/byteorder.h b/include/asm-arm/byteorder.h index 17eaf8bdf09..e6f7fcdc73b 100644 --- a/include/asm-arm/byteorder.h +++ b/include/asm-arm/byteorder.h @@ -22,16 +22,18 @@ static inline __attribute_const__ __u32 ___arch__swab32(__u32 x) { __u32 t; - if (__builtin_constant_p(x)) { - t = x ^ ((x << 16) | (x >> 16)); /* eor r1,r0,r0,ror #16 */ - } else { +#ifndef __thumb__ + if (!__builtin_constant_p(x)) { /* * The compiler needs a bit of a hint here to always do the * right thing and not screw it up to different degrees * depending on the gcc version. */ asm ("eor\t%0, %1, %1, ror #16" : "=r" (t) : "r" (x)); - } + } else +#endif + t = x ^ ((x << 16) | (x >> 16)); /* eor r1,r0,r0,ror #16 */ + x = (x << 24) | (x >> 8); /* mov r0,r0,ror #8 */ t &= ~0x00FF0000; /* bic r1,r1,#0x00FF0000 */ x ^= (t >> 8); /* eor r0,r0,r1,lsr #8 */ -- cgit v1.2.3 From 5af29e56c221d709bdbd5fccaf190e21f290a30e Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 19 Jun 2006 15:37:31 +0100 Subject: [ARM] Fix badge4 build error The Badge4 PCMCIA driver was referencing structure elements which had been renamed. Fix the missing renames. Signed-off-by: Russell King --- drivers/pcmcia/sa1100_badge4.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/pcmcia/sa1100_badge4.c b/drivers/pcmcia/sa1100_badge4.c index c6b262b653d..19b1e127622 100644 --- a/drivers/pcmcia/sa1100_badge4.c +++ b/drivers/pcmcia/sa1100_badge4.c @@ -128,8 +128,8 @@ badge4_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state static struct pcmcia_low_level badge4_pcmcia_ops = { .owner = THIS_MODULE, - .init = sa1111_pcmcia_hw_init, - .shutdown = sa1111_pcmcia_hw_shutdown, + .hw_init = sa1111_pcmcia_hw_init, + .hw_shutdown = sa1111_pcmcia_hw_shutdown, .socket_state = sa1111_pcmcia_socket_state, .configure_socket = badge4_pcmcia_configure_socket, -- cgit v1.2.3 From 2e83640270b4a76a3855131953c82bbc1919e589 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Mon, 19 Jun 2006 16:31:55 +0100 Subject: [ARM] 3585/1: AT91RM9200 Platform devices Patch from Andrew Victor This patch updates the platform device support for the AT91RM9200. The changes include: 1. USB Host device renamed to "at91_ohci" since the driver is also usable on the AT91SAM9261 processor. 2. Enabling multidrive on the USB Device's pullup pin should not be done for all boards. Moved into board-specific files. [Patch from David Brownell] 3. Move enabling of PCMCIA/Compact Flash pins out of the driver. 4. Added SPI device and resources. 5. Added Watchdog device and resources. [Patch from David Brownell] 6. Added UART device and resources. 7. The simple devices (watchdog, rtc, i2c) are now automatically registered and don't have to be registered separately in each board-specific file. [Patch from David Brownell] Signed-off-by: Andrew Victor Signed-off-by: Russell King --- arch/arm/mach-at91rm9200/devices.c | 406 +++++++++++++++++++++++++++++++++++-- 1 file changed, 389 insertions(+), 17 deletions(-) diff --git a/arch/arm/mach-at91rm9200/devices.c b/arch/arm/mach-at91rm9200/devices.c index bfe47bd6e50..bf753e306a3 100644 --- a/arch/arm/mach-at91rm9200/devices.c +++ b/arch/arm/mach-at91rm9200/devices.c @@ -16,9 +16,15 @@ #include #include +#include #include -#include +#include +#include "generic.h" + +#define SZ_512 0x00000200 +#define SZ_256 0x00000100 +#define SZ_16 0x00000010 /* -------------------------------------------------------------------- * USB Host @@ -28,7 +34,7 @@ static u64 ohci_dmamask = 0xffffffffUL; static struct at91_usbh_data usbh_data; -static struct resource at91_usbh_resource[] = { +static struct resource at91_usbh_resources[] = { [0] = { .start = AT91_UHP_BASE, .end = AT91_UHP_BASE + SZ_1M - 1, @@ -42,15 +48,15 @@ static struct resource at91_usbh_resource[] = { }; static struct platform_device at91rm9200_usbh_device = { - .name = "at91rm9200-ohci", + .name = "at91_ohci", .id = -1, .dev = { .dma_mask = &ohci_dmamask, .coherent_dma_mask = 0xffffffff, .platform_data = &usbh_data, }, - .resource = at91_usbh_resource, - .num_resources = ARRAY_SIZE(at91_usbh_resource), + .resource = at91_usbh_resources, + .num_resources = ARRAY_SIZE(at91_usbh_resources), }; void __init at91_add_device_usbh(struct at91_usbh_data *data) @@ -74,11 +80,16 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data) {} static struct at91_udc_data udc_data; static struct resource at91_udc_resources[] = { - { + [0] = { .start = AT91_BASE_UDP, .end = AT91_BASE_UDP + SZ_16K - 1, .flags = IORESOURCE_MEM, - } + }, + [1] = { + .start = AT91_ID_UDP, + .end = AT91_ID_UDP, + .flags = IORESOURCE_IRQ, + }, }; static struct platform_device at91rm9200_udc_device = { @@ -100,10 +111,8 @@ void __init at91_add_device_udc(struct at91_udc_data *data) at91_set_gpio_input(data->vbus_pin, 0); at91_set_deglitch(data->vbus_pin, 1); } - if (data->pullup_pin) { + if (data->pullup_pin) at91_set_gpio_output(data->pullup_pin, 0); - at91_set_multi_drive(data->pullup_pin, 1); - } udc_data = *data; platform_device_register(&at91rm9200_udc_device); @@ -197,7 +206,7 @@ static struct at91_cf_data cf_data; static struct resource at91_cf_resources[] = { [0] = { .start = AT91_CF_BASE, - /* ties up CS4, CS5, and CS6 */ + /* ties up CS4, CS5 and CS6 */ .end = AT91_CF_BASE + (0x30000000 - 1), .flags = IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT, }, @@ -231,6 +240,12 @@ void __init at91_add_device_cf(struct at91_cf_data *data) at91_set_gpio_output(data->vcc_pin, 0); at91_set_gpio_output(data->rst_pin, 0); + /* force poweron defaults for these pins ... */ + at91_set_A_periph(AT91_PIN_PC9, 0); /* A25/CFRNW */ + at91_set_A_periph(AT91_PIN_PC10, 0); /* NCS4/CFCS */ + at91_set_A_periph(AT91_PIN_PC11, 0); /* NCS5/CFCE1 */ + at91_set_A_periph(AT91_PIN_PC12, 0); /* NCS6/CFCE2 */ + cf_data = *data; platform_device_register(&at91rm9200_cf_device); } @@ -319,6 +334,7 @@ void __init at91_add_device_mmc(struct at91_mmc_data *data) void __init at91_add_device_mmc(struct at91_mmc_data *data) {} #endif + /* -------------------------------------------------------------------- * NAND / SmartMedia * -------------------------------------------------------------------- */ @@ -399,23 +415,111 @@ void __init at91_add_device_i2c(void) {} #endif +/* -------------------------------------------------------------------- + * SPI + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_SPI_AT91) || defined(CONFIG_SPI_AT91_MODULE) || defined(CONFIG_AT91_SPI) || defined(CONFIG_AT91_SPI_MODULE) +static u64 spi_dmamask = 0xffffffffUL; + +static struct resource at91_spi_resources[] = { + [0] = { + .start = AT91_BASE_SPI, + .end = AT91_BASE_SPI + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91_ID_SPI, + .end = AT91_ID_SPI, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91rm9200_spi_device = { + .name = "at91_spi", + .id = 0, + .dev = { + .dma_mask = &spi_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .resource = at91_spi_resources, + .num_resources = ARRAY_SIZE(at91_spi_resources), +}; + +static const unsigned at91_spi_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PA5, AT91_PIN_PA6 }; + +void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) +{ + int i; + unsigned long cs_pin; + + at91_set_A_periph(AT91_PIN_PA0, 0); /* MISO */ + at91_set_A_periph(AT91_PIN_PA1, 0); /* MOSI */ + at91_set_A_periph(AT91_PIN_PA2, 0); /* SPCK */ + + /* Enable SPI chip-selects */ + for (i = 0; i < nr_devices; i++) { + if (devices[i].controller_data) + cs_pin = (unsigned long) devices[i].controller_data; + else + cs_pin = at91_spi_standard_cs[devices[i].chip_select]; + +#ifdef CONFIG_SPI_AT91_MANUAL_CS + at91_set_gpio_output(cs_pin, 1); +#else + at91_set_A_periph(cs_pin, 0); +#endif + + /* pass chip-select pin to driver */ + devices[i].controller_data = (void *) cs_pin; + } + + spi_register_board_info(devices, nr_devices); + at91_clock_associate("spi0_clk", &at91rm9200_spi_device.dev, "spi"); + platform_device_register(&at91rm9200_spi_device); +} +#else +void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {} +#endif + + /* -------------------------------------------------------------------- * RTC * -------------------------------------------------------------------- */ -#if defined(CONFIG_AT91_RTC) || defined(CONFIG_AT91_RTC_MODULE) +#if defined(CONFIG_RTC_DRV_AT91) || defined(CONFIG_RTC_DRV_AT91_MODULE) static struct platform_device at91rm9200_rtc_device = { .name = "at91_rtc", .id = -1, .num_resources = 0, }; -void __init at91_add_device_rtc(void) +static void __init at91_add_device_rtc(void) { platform_device_register(&at91rm9200_rtc_device); } #else -void __init at91_add_device_rtc(void) {} +static void __init at91_add_device_rtc(void) {} +#endif + + +/* -------------------------------------------------------------------- + * Watchdog + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_AT91_WATCHDOG) || defined(CONFIG_AT91_WATCHDOG_MODULE) +static struct platform_device at91rm9200_wdt_device = { + .name = "at91_wdt", + .id = -1, + .num_resources = 0, +}; + +static void __init at91_add_device_watchdog(void) +{ + platform_device_register(&at91rm9200_wdt_device); +} +#else +static void __init at91_add_device_watchdog(void) {} #endif @@ -429,13 +533,281 @@ u8 at91_leds_timer; void __init at91_init_leds(u8 cpu_led, u8 timer_led) { - at91_leds_cpu = cpu_led; - at91_leds_timer = timer_led; + at91_leds_cpu = cpu_led; + at91_leds_timer = timer_led; } - #else void __init at91_init_leds(u8 cpu_led, u8 timer_led) {} #endif +/* -------------------------------------------------------------------- + * UART + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_SERIAL_AT91) +static struct resource dbgu_resources[] = { + [0] = { + .start = AT91_VA_BASE_SYS + AT91_DBGU, + .end = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91_ID_SYS, + .end = AT91_ID_SYS, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct at91_uart_data dbgu_data = { + .use_dma_tx = 0, + .use_dma_rx = 0, /* DBGU not capable of receive DMA */ +}; + +static struct platform_device at91rm9200_dbgu_device = { + .name = "at91_usart", + .id = 0, + .dev = { + .platform_data = &dbgu_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = dbgu_resources, + .num_resources = ARRAY_SIZE(dbgu_resources), +}; + +static inline void configure_dbgu_pins(void) +{ + at91_set_A_periph(AT91_PIN_PA30, 0); /* DRXD */ + at91_set_A_periph(AT91_PIN_PA31, 1); /* DTXD */ +} + +static struct resource uart0_resources[] = { + [0] = { + .start = AT91_BASE_US0, + .end = AT91_BASE_US0 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91_ID_US0, + .end = AT91_ID_US0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct at91_uart_data uart0_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91rm9200_uart0_device = { + .name = "at91_usart", + .id = 1, + .dev = { + .platform_data = &uart0_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart0_resources, + .num_resources = ARRAY_SIZE(uart0_resources), +}; + +static inline void configure_usart0_pins(void) +{ + at91_set_A_periph(AT91_PIN_PA17, 1); /* TXD0 */ + at91_set_A_periph(AT91_PIN_PA18, 0); /* RXD0 */ + at91_set_A_periph(AT91_PIN_PA20, 0); /* CTS0 */ + + /* + * AT91RM9200 Errata #39 - RTS0 is not internally connected to PA21. + * We need to drive the pin manually. Default is off (RTS is active low). + */ + at91_set_gpio_output(AT91_PIN_PA21, 1); +} + +static struct resource uart1_resources[] = { + [0] = { + .start = AT91_BASE_US1, + .end = AT91_BASE_US1 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91_ID_US1, + .end = AT91_ID_US1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct at91_uart_data uart1_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91rm9200_uart1_device = { + .name = "at91_usart", + .id = 2, + .dev = { + .platform_data = &uart1_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart1_resources, + .num_resources = ARRAY_SIZE(uart1_resources), +}; + +static inline void configure_usart1_pins(void) +{ + at91_set_A_periph(AT91_PIN_PB18, 0); /* RI1 */ + at91_set_A_periph(AT91_PIN_PB19, 0); /* DTR1 */ + at91_set_A_periph(AT91_PIN_PB20, 1); /* TXD1 */ + at91_set_A_periph(AT91_PIN_PB21, 0); /* RXD1 */ + at91_set_A_periph(AT91_PIN_PB23, 0); /* DCD1 */ + at91_set_A_periph(AT91_PIN_PB24, 0); /* CTS1 */ + at91_set_A_periph(AT91_PIN_PB25, 0); /* DSR1 */ + at91_set_A_periph(AT91_PIN_PB26, 0); /* RTS1 */ +} + +static struct resource uart2_resources[] = { + [0] = { + .start = AT91_BASE_US2, + .end = AT91_BASE_US2 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91_ID_US2, + .end = AT91_ID_US2, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct at91_uart_data uart2_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91rm9200_uart2_device = { + .name = "at91_usart", + .id = 3, + .dev = { + .platform_data = &uart2_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart2_resources, + .num_resources = ARRAY_SIZE(uart2_resources), +}; + +static inline void configure_usart2_pins(void) +{ + at91_set_A_periph(AT91_PIN_PA22, 0); /* RXD2 */ + at91_set_A_periph(AT91_PIN_PA23, 1); /* TXD2 */ +} + +static struct resource uart3_resources[] = { + [0] = { + .start = AT91_BASE_US3, + .end = AT91_BASE_US3 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91_ID_US3, + .end = AT91_ID_US3, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct at91_uart_data uart3_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91rm9200_uart3_device = { + .name = "at91_usart", + .id = 4, + .dev = { + .platform_data = &uart3_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart3_resources, + .num_resources = ARRAY_SIZE(uart3_resources), +}; + +static inline void configure_usart3_pins(void) +{ + at91_set_B_periph(AT91_PIN_PA5, 1); /* TXD3 */ + at91_set_B_periph(AT91_PIN_PA6, 0); /* RXD3 */ +} + +struct platform_device *at91_uarts[AT91_NR_UART]; /* the UARTs to use */ +struct platform_device *at91_default_console_device; /* the serial console device */ + +void __init at91_init_serial(struct at91_uart_config *config) +{ + int i; + + /* Fill in list of supported UARTs */ + for (i = 0; i < config->nr_tty; i++) { + switch (config->tty_map[i]) { + case 0: + configure_usart0_pins(); + at91_uarts[i] = &at91rm9200_uart0_device; + at91_clock_associate("usart0_clk", &at91rm9200_uart0_device.dev, "usart"); + break; + case 1: + configure_usart1_pins(); + at91_uarts[i] = &at91rm9200_uart1_device; + at91_clock_associate("usart1_clk", &at91rm9200_uart1_device.dev, "usart"); + break; + case 2: + configure_usart2_pins(); + at91_uarts[i] = &at91rm9200_uart2_device; + at91_clock_associate("usart2_clk", &at91rm9200_uart2_device.dev, "usart"); + break; + case 3: + configure_usart3_pins(); + at91_uarts[i] = &at91rm9200_uart3_device; + at91_clock_associate("usart3_clk", &at91rm9200_uart3_device.dev, "usart"); + break; + case 4: + configure_dbgu_pins(); + at91_uarts[i] = &at91rm9200_dbgu_device; + at91_clock_associate("mck", &at91rm9200_dbgu_device.dev, "usart"); + break; + default: + continue; + } + at91_uarts[i]->id = i; /* update ID number to mapped ID */ + } + + /* Set serial console device */ + if (config->console_tty < AT91_NR_UART) + at91_default_console_device = at91_uarts[config->console_tty]; + if (!at91_default_console_device) + printk(KERN_INFO "AT91: No default serial console defined.\n"); +} + +void __init at91_add_device_serial(void) +{ + int i; + + for (i = 0; i < AT91_NR_UART; i++) { + if (at91_uarts[i]) + platform_device_register(at91_uarts[i]); + } +} +#else +void __init at91_init_serial(struct at91_uart_config *config) {} +void __init at91_add_device_serial(void) {} +#endif + + /* -------------------------------------------------------------------- */ + +/* + * These devices are always present and don't need any board-specific + * setup. + */ +static int __init at91_add_standard_devices(void) +{ + at91_add_device_rtc(); + at91_add_device_watchdog(); + return 0; +} + +arch_initcall(at91_add_standard_devices); -- cgit v1.2.3 From 7238d7ee82d325212e83630047e9844943225118 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Mon, 19 Jun 2006 16:57:00 +0100 Subject: [ARM] 3586/1: AT91RM9200 header update Patch from Andrew Victor Added definition for the bits in the Chip ID register. Corrected the capitalization of AT91_RTC_AMPM register name. Signed-off-by: Andrew Victor Signed-off-by: Russell King --- include/asm-arm/arch-at91rm9200/at91rm9200_sys.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_sys.h b/include/asm-arm/arch-at91rm9200/at91rm9200_sys.h index 2910d359f91..0f4c12d5f0c 100644 --- a/include/asm-arm/arch-at91rm9200/at91rm9200_sys.h +++ b/include/asm-arm/arch-at91rm9200/at91rm9200_sys.h @@ -68,8 +68,17 @@ #define AT91_DBGU_RHR (AT91_DBGU + 0x18) /* Receiver Holding Register */ #define AT91_DBGU_THR (AT91_DBGU + 0x1c) /* Transmitter Holding Register */ #define AT91_DBGU_BRGR (AT91_DBGU + 0x20) /* Baud Rate Generator Register */ + #define AT91_DBGU_CIDR (AT91_DBGU + 0x40) /* Chip ID Register */ #define AT91_DBGU_EXID (AT91_DBGU + 0x44) /* Chip ID Extension Register */ +#define AT91_CIDR_VERSION (0x1f << 0) /* Version of the Device */ +#define AT91_CIDR_EPROC (7 << 5) /* Embedded Processor */ +#define AT91_CIDR_NVPSIZ (0xf << 8) /* Nonvolatile Program Memory Size */ +#define AT91_CIDR_NVPSIZ2 (0xf << 12) /* Second Nonvolatile Program Memory Size */ +#define AT91_CIDR_SRAMSIZ (0xf << 16) /* Internal SRAM Size */ +#define AT91_CIDR_ARCH (0xff << 20) /* Architecture Identifier */ +#define AT91_CIDR_NVPTYP (7 << 28) /* Nonvolatile Program Memory Type */ +#define AT91_CIDR_EXT (1 << 31) /* Extension Flag */ /* @@ -241,7 +250,7 @@ #define AT91_RTC_SEC (0x7f << 0) /* Current Second */ #define AT91_RTC_MIN (0x7f << 8) /* Current Minute */ #define AT91_RTC_HOUR (0x3f << 16) /* Current Hour */ -#define At91_RTC_AMPM (1 << 22) /* Ante Meridiem Post Meridiem Indicator */ +#define AT91_RTC_AMPM (1 << 22) /* Ante Meridiem Post Meridiem Indicator */ #define AT91_RTC_CALR (AT91_RTC + 0x0c) /* Calendar Register */ #define AT91_RTC_CENT (0x7f << 0) /* Current Century */ -- cgit v1.2.3 From 82c583e3ae31ffa76d1280197274cc1e1cde3179 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Mon, 19 Jun 2006 16:57:00 +0100 Subject: [ARM] 3587/1: AT91RM9200 hardware headers Patch from Andrew Victor These headers define the registers and bits for the SPI (Serial Peripheral Interface), SSC (Synchronous Serial), TC (Timer/Counter) and UDP (USB Device) peripherals integrated in the AT91RM9200 processor. (They will probably also be usable for the AT91SAM9 series of SoC processors) Signed-off-by: Andrew Victor Signed-off-by: Russell King --- include/asm-arm/arch-at91rm9200/at91rm9200_spi.h | 81 +++++++++++++ include/asm-arm/arch-at91rm9200/at91rm9200_ssc.h | 96 +++++++++++++++ include/asm-arm/arch-at91rm9200/at91rm9200_tc.h | 146 +++++++++++++++++++++++ include/asm-arm/arch-at91rm9200/at91rm9200_udp.h | 77 ++++++++++++ 4 files changed, 400 insertions(+) create mode 100644 include/asm-arm/arch-at91rm9200/at91rm9200_spi.h create mode 100644 include/asm-arm/arch-at91rm9200/at91rm9200_ssc.h create mode 100644 include/asm-arm/arch-at91rm9200/at91rm9200_tc.h create mode 100644 include/asm-arm/arch-at91rm9200/at91rm9200_udp.h diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_spi.h b/include/asm-arm/arch-at91rm9200/at91rm9200_spi.h new file mode 100644 index 00000000000..bff5ea45f60 --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/at91rm9200_spi.h @@ -0,0 +1,81 @@ +/* + * include/asm-arm/arch-at91rm9200/at91rm9200_spi.h + * + * Copyright (C) 2005 Ivan Kokshaysky + * Copyright (C) SAN People + * + * Serial Peripheral Interface (SPI) registers. + * Based on AT91RM9200 datasheet revision E. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef AT91RM9200_SPI_H +#define AT91RM9200_SPI_H + +#define AT91_SPI_CR 0x00 /* Control Register */ +#define AT91_SPI_SPIEN (1 << 0) /* SPI Enable */ +#define AT91_SPI_SPIDIS (1 << 1) /* SPI Disable */ +#define AT91_SPI_SWRST (1 << 7) /* SPI Software Reset */ +#define AT91_SPI_LASTXFER (1 << 24) /* Last Transfer [SAM9261 only] */ + +#define AT91_SPI_MR 0x04 /* Mode Register */ +#define AT91_SPI_MSTR (1 << 0) /* Master/Slave Mode */ +#define AT91_SPI_PS (1 << 1) /* Peripheral Select */ +#define AT91_SPI_PS_FIXED (0 << 1) +#define AT91_SPI_PS_VARIABLE (1 << 1) +#define AT91_SPI_PCSDEC (1 << 2) /* Chip Select Decode */ +#define AT91_SPI_DIV32 (1 << 3) /* Clock Selection */ +#define AT91_SPI_MODFDIS (1 << 4) /* Mode Fault Detection */ +#define AT91_SPI_LLB (1 << 7) /* Local Loopback Enable */ +#define AT91_SPI_PCS (0xf << 16) /* Peripheral Chip Select */ +#define AT91_SPI_DLYBCS (0xff << 24) /* Delay Between Chip Selects */ + +#define AT91_SPI_RDR 0x08 /* Receive Data Register */ +#define AT91_SPI_RD (0xffff << 0) /* Receive Data */ +#define AT91_SPI_PCS (0xf << 16) /* Peripheral Chip Select */ + +#define AT91_SPI_TDR 0x0c /* Transmit Data Register */ +#define AT91_SPI_TD (0xffff << 0) /* Transmit Data */ +#define AT91_SPI_PCS (0xf << 16) /* Peripheral Chip Select */ +#define AT91_SPI_LASTXFER (1 << 24) /* Last Transfer [SAM9261 only] */ + +#define AT91_SPI_SR 0x10 /* Status Register */ +#define AT91_SPI_RDRF (1 << 0) /* Receive Data Register Full */ +#define AT91_SPI_TDRE (1 << 1) /* Transmit Data Register Full */ +#define AT91_SPI_MODF (1 << 2) /* Mode Fault Error */ +#define AT91_SPI_OVRES (1 << 3) /* Overrun Error Status */ +#define AT91_SPI_ENDRX (1 << 4) /* End of RX buffer */ +#define AT91_SPI_ENDTX (1 << 5) /* End of TX buffer */ +#define AT91_SPI_RXBUFF (1 << 6) /* RX Buffer Full */ +#define AT91_SPI_TXBUFE (1 << 7) /* TX Buffer Empty */ +#define AT91_SPI_NSSR (1 << 8) /* NSS Rising [SAM9261 only] */ +#define AT91_SPI_TXEMPTY (1 << 9) /* Transmission Register Empty [SAM9261 only] */ +#define AT91_SPI_SPIENS (1 << 16) /* SPI Enable Status */ + +#define AT91_SPI_IER 0x14 /* Interrupt Enable Register */ +#define AT91_SPI_IDR 0x18 /* Interrupt Disable Register */ +#define AT91_SPI_IMR 0x1c /* Interrupt Mask Register */ + +#define AT91_SPI_CSR(n) (0x30 + ((n) * 4)) /* Chip Select Registers 0-3 */ +#define AT91_SPI_CPOL (1 << 0) /* Clock Polarity */ +#define AT91_SPI_NCPHA (1 << 1) /* Clock Phase */ +#define AT91_SPI_CSAAT (1 << 3) /* Chip Select Active After Transfer [SAM9261 only] */ +#define AT91_SPI_BITS (0xf << 4) /* Bits Per Transfer */ +#define AT91_SPI_BITS_8 (0 << 4) +#define AT91_SPI_BITS_9 (1 << 4) +#define AT91_SPI_BITS_10 (2 << 4) +#define AT91_SPI_BITS_11 (3 << 4) +#define AT91_SPI_BITS_12 (4 << 4) +#define AT91_SPI_BITS_13 (5 << 4) +#define AT91_SPI_BITS_14 (6 << 4) +#define AT91_SPI_BITS_15 (7 << 4) +#define AT91_SPI_BITS_16 (8 << 4) +#define AT91_SPI_SCBR (0xff << 8) /* Serial Clock Baud Rate */ +#define AT91_SPI_DLYBS (0xff << 16) /* Delay before SPCK */ +#define AT91_SPI_DLYBCT (0xff << 24) /* Delay between Consecutive Transfers */ + +#endif diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_ssc.h b/include/asm-arm/arch-at91rm9200/at91rm9200_ssc.h new file mode 100644 index 00000000000..ac880227147 --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/at91rm9200_ssc.h @@ -0,0 +1,96 @@ +/* + * include/asm-arm/arch-at91rm9200/at91rm9200_ssc.h + * + * Copyright (C) SAN People + * + * Serial Synchronous Controller (SSC) registers. + * Based on AT91RM9200 datasheet revision E. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef AT91RM9200_SSC_H +#define AT91RM9200_SSC_H + +#define AT91_SSC_CR 0x00 /* Control Register */ +#define AT91_SSC_RXEN (1 << 0) /* Receive Enable */ +#define AT91_SSC_RXDIS (1 << 1) /* Receive Disable */ +#define AT91_SSC_TXEN (1 << 8) /* Transmit Enable */ +#define AT91_SSC_TXDIS (1 << 9) /* Transmit Disable */ +#define AT91_SSC_SWRST (1 << 15) /* Software Reset */ + +#define AT91_SSC_CMR 0x04 /* Clock Mode Register */ +#define AT91_SSC_CMR_DIV (0xfff << 0) /* Clock Divider */ + +#define AT91_SSC_RCMR 0x10 /* Receive Clock Mode Register */ +#define AT91_SSC_CKS (3 << 0) /* Clock Selection */ +#define AT91_SSC_CKS_DIV (0 << 0) +#define AT91_SSC_CKS_CLOCK (1 << 0) +#define AT91_SSC_CKS_PIN (2 << 0) +#define AT91_SSC_CKO (7 << 2) /* Clock Output Mode Selection */ +#define AT91_SSC_CKO_NONE (0 << 2) +#define AT91_SSC_CKO_CONTINUOUS (1 << 2) +#define AT91_SSC_CKI (1 << 5) /* Clock Inversion */ +#define AT91_SSC_CKI_FALLING (0 << 5) +#define AT91_SSC_CK_RISING (1 << 5) +#define AT91_SSC_START (0xf << 8) /* Start Selection */ +#define AT91_SSC_START_CONTINUOUS (0 << 8) +#define AT91_SSC_START_TX_RX (1 << 8) +#define AT91_SSC_START_LOW_RF (2 << 8) +#define AT91_SSC_START_HIGH_RF (3 << 8) +#define AT91_SSC_START_FALLING_RF (4 << 8) +#define AT91_SSC_START_RISING_RF (5 << 8) +#define AT91_SSC_START_LEVEL_RF (6 << 8) +#define AT91_SSC_START_EDGE_RF (7 << 8) +#define AT91_SSC_STTDLY (0xff << 16) /* Start Delay */ +#define AT91_SSC_PERIOD (0xff << 24) /* Period Divider Selection */ + +#define AT91_SSC_RFMR 0x14 /* Receive Frame Mode Register */ +#define AT91_SSC_DATALEN (0x1f << 0) /* Data Length */ +#define AT91_SSC_LOOP (1 << 5) /* Loop Mode */ +#define AT91_SSC_MSBF (1 << 7) /* Most Significant Bit First */ +#define AT91_SSC_DATNB (0xf << 8) /* Data Number per Frame */ +#define AT91_SSC_FSLEN (0xf << 16) /* Frame Sync Length */ +#define AT91_SSC_FSOS (7 << 20) /* Frame Sync Output Selection */ +#define AT91_SSC_FSOS_NONE (0 << 20) +#define AT91_SSC_FSOS_NEGATIVE (1 << 20) +#define AT91_SSC_FSOS_POSITIVE (2 << 20) +#define AT91_SSC_FSOS_LOW (3 << 20) +#define AT91_SSC_FSOS_HIGH (4 << 20) +#define AT91_SSC_FSOS_TOGGLE (5 << 20) +#define AT91_SSC_FSEDGE (1 << 24) /* Frame Sync Edge Detection */ +#define AT91_SSC_FSEDGE_POSITIVE (0 << 24) +#define AT91_SSC_FSEDGE_NEGATIVE (1 << 24) + +#define AT91_SSC_TCMR 0x18 /* Transmit Clock Mode Register */ +#define AT91_SSC_TFMR 0x1c /* Transmit Fram Mode Register */ +#define AT91_SSC_DATDEF (1 << 5) /* Data Default Value */ +#define AT91_SSC_FSDEN (1 << 23) /* Frame Sync Data Enable */ + +#define AT91_SSC_RHR 0x20 /* Receive Holding Register */ +#define AT91_SSC_THR 0x24 /* Transmit Holding Register */ +#define AT91_SSC_RSHR 0x30 /* Receive Sync Holding Register */ +#define AT91_SSC_TSHR 0x34 /* Transmit Sync Holding Register */ + +#define AT91_SSC_SR 0x40 /* Status Register */ +#define AT91_SSC_TXRDY (1 << 0) /* Transmit Ready */ +#define AT91_SSC_TXEMPTY (1 << 1) /* Transmit Empty */ +#define AT91_SSC_ENDTX (1 << 2) /* End of Transmission */ +#define AT91_SSC_TXBUFE (1 << 3) /* Transmit Buffer Empty */ +#define AT91_SSC_RXRDY (1 << 4) /* Receive Ready */ +#define AT91_SSC_OVRUN (1 << 5) /* Receive Overrun */ +#define AT91_SSC_ENDRX (1 << 6) /* End of Reception */ +#define AT91_SSC_RXBUFF (1 << 7) /* Receive Buffer Full */ +#define AT91_SSC_TXSYN (1 << 10) /* Transmit Sync */ +#define AT91_SSC_RXSYN (1 << 11) /* Receive Sync */ +#define AT91_SSC_TXENA (1 << 16) /* Transmit Enable */ +#define AT91_SSC_RXENA (1 << 17) /* Receive Enable */ + +#define AT91_SSC_IER 0x44 /* Interrupt Enable Register */ +#define AT91_SSC_IDR 0x48 /* Interrupt Disable Register */ +#define AT91_SSC_IMR 0x4c /* Interrupt Mask Register */ + +#endif diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_tc.h b/include/asm-arm/arch-at91rm9200/at91rm9200_tc.h new file mode 100644 index 00000000000..f4da752bb0c --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/at91rm9200_tc.h @@ -0,0 +1,146 @@ +/* + * include/asm-arm/arch-at91rm9200/at91rm9200_tc.h + * + * Copyright (C) SAN People + * + * Timer/Counter Unit (TC) registers. + * Based on AT91RM9200 datasheet revision E. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef AT91RM9200_TC_H +#define AT91RM9200_TC_H + +#define AT91_TC_BCR 0xc0 /* TC Block Control Register */ +#define AT91_TC_SYNC (1 << 0) /* Synchro Command */ + +#define AT91_TC_BMR 0xc4 /* TC Block Mode Register */ +#define AT91_TC_TC0XC0S (3 << 0) /* External Clock Signal 0 Selection */ +#define AT91_TC_TC0XC0S_TCLK0 (0 << 0) +#define AT91_TC_TC0XC0S_NONE (1 << 0) +#define AT91_TC_TC0XC0S_TIOA1 (2 << 0) +#define AT91_TC_TC0XC0S_TIOA2 (3 << 0) +#define AT91_TC_TC1XC1S (3 << 2) /* External Clock Signal 1 Selection */ +#define AT91_TC_TC1XC1S_TCLK1 (0 << 2) +#define AT91_TC_TC1XC1S_NONE (1 << 2) +#define AT91_TC_TC1XC1S_TIOA0 (2 << 2) +#define AT91_TC_TC1XC1S_TIOA2 (3 << 2) +#define AT91_TC_TC2XC2S (3 << 4) /* External Clock Signal 2 Selection */ +#define AT91_TC_TC2XC2S_TCLK2 (0 << 4) +#define AT91_TC_TC2XC2S_NONE (1 << 4) +#define AT91_TC_TC2XC2S_TIOA0 (2 << 4) +#define AT91_TC_TC2XC2S_TIOA1 (3 << 4) + + +#define AT91_TC_CCR 0x00 /* Channel Control Register */ +#define AT91_TC_CLKEN (1 << 0) /* Counter Clock Enable Command */ +#define AT91_TC_CLKDIS (1 << 1) /* Counter CLock Disable Command */ +#define AT91_TC_SWTRG (1 << 2) /* Software Trigger Command */ + +#define AT91_TC_CMR 0x04 /* Channel Mode Register */ +#define AT91_TC_TCCLKS (7 << 0) /* Capture/Waveform Mode: Clock Selection */ +#define AT91_TC_TIMER_CLOCK1 (0 << 0) +#define AT91_TC_TIMER_CLOCK2 (1 << 0) +#define AT91_TC_TIMER_CLOCK3 (2 << 0) +#define AT91_TC_TIMER_CLOCK4 (3 << 0) +#define AT91_TC_TIMER_CLOCK5 (4 << 0) +#define AT91_TC_XC0 (5 << 0) +#define AT91_TC_XC1 (6 << 0) +#define AT91_TC_XC2 (7 << 0) +#define AT91_TC_CLKI (1 << 3) /* Capture/Waveform Mode: Clock Invert */ +#define AT91_TC_BURST (3 << 4) /* Capture/Waveform Mode: Burst Signal Selection */ +#define AT91_TC_LDBSTOP (1 << 6) /* Capture Mode: Counter Clock Stopped with TB Loading */ +#define AT91_TC_LDBDIS (1 << 7) /* Capture Mode: Counter Clock Disable with RB Loading */ +#define AT91_TC_ETRGEDG (3 << 8) /* Capture Mode: External Trigger Edge Selection */ +#define AT91_TC_ABETRG (1 << 10) /* Capture Mode: TIOA or TIOB External Trigger Selection */ +#define AT91_TC_CPCTRG (1 << 14) /* Capture Mode: RC Compare Trigger Enable */ +#define AT91_TC_WAVE (1 << 15) /* Capture/Waveform mode */ +#define AT91_TC_LDRA (3 << 16) /* Capture Mode: RA Loading Selection */ +#define AT91_TC_LDRB (3 << 18) /* Capture Mode: RB Loading Selection */ + +#define AT91_TC_CPCSTOP (1 << 6) /* Waveform Mode: Counter Clock Stopped with RC Compare */ +#define AT91_TC_CPCDIS (1 << 7) /* Waveform Mode: Counter Clock Disable with RC Compare */ +#define AT91_TC_EEVTEDG (3 << 8) /* Waveform Mode: External Event Edge Selection */ +#define AT91_TC_EEVTEDG_NONE (0 << 8) +#define AT91_TC_EEVTEDG_RISING (1 << 8) +#define AT91_TC_EEVTEDG_FALLING (2 << 8) +#define AT91_TC_EEVTEDG_BOTH (3 << 8) +#define AT91_TC_EEVT (3 << 10) /* Waveform Mode: External Event Selection */ +#define AT91_TC_EEVT_TIOB (0 << 10) +#define AT91_TC_EEVT_XC0 (1 << 10) +#define AT91_TC_EEVT_XC1 (2 << 10) +#define AT91_TC_EEVT_XC2 (3 << 10) +#define AT91_TC_ENETRG (1 << 12) /* Waveform Mode: External Event Trigger Enable */ +#define AT91_TC_WAVESEL (3 << 13) /* Waveform Mode: Waveform Selection */ +#define AT91_TC_WAVESEL_UP (0 << 13) +#define AT91_TC_WAVESEL_UP_AUTO (2 << 13) +#define AT91_TC_WAVESEL_UPDOWN (1 << 13) +#define AT91_TC_WAVESEL_UPDOWN_AUTO (3 << 13) +#define AT91_TC_ACPA (3 << 16) /* Waveform Mode: RA Compare Effect on TIOA */ +#define AT91_TC_ACPA_NONE (0 << 16) +#define AT91_TC_ACPA_SET (1 << 16) +#define AT91_TC_ACPA_CLEAR (2 << 16) +#define AT91_TC_ACPA_TOGGLE (3 << 16) +#define AT91_TC_ACPC (3 << 18) /* Waveform Mode: RC Compre Effect on TIOA */ +#define AT91_TC_ACPC_NONE (0 << 18) +#define AT91_TC_ACPC_SET (1 << 18) +#define AT91_TC_ACPC_CLEAR (2 << 18) +#define AT91_TC_ACPC_TOGGLE (3 << 18) +#define AT91_TC_AEEVT (3 << 20) /* Waveform Mode: External Event Effect on TIOA */ +#define AT91_TC_AEEVT_NONE (0 << 20) +#define AT91_TC_AEEVT_SET (1 << 20) +#define AT91_TC_AEEVT_CLEAR (2 << 20) +#define AT91_TC_AEEVT_TOGGLE (3 << 20) +#define AT91_TC_ASWTRG (3 << 22) /* Waveform Mode: Software Trigger Effect on TIOA */ +#define AT91_TC_ASWTRG_NONE (0 << 22) +#define AT91_TC_ASWTRG_SET (1 << 22) +#define AT91_TC_ASWTRG_CLEAR (2 << 22) +#define AT91_TC_ASWTRG_TOGGLE (3 << 22) +#define AT91_TC_BCPB (3 << 24) /* Waveform Mode: RB Compare Effect on TIOB */ +#define AT91_TC_BCPB_NONE (0 << 24) +#define AT91_TC_BCPB_SET (1 << 24) +#define AT91_TC_BCPB_CLEAR (2 << 24) +#define AT91_TC_BCPB_TOGGLE (3 << 24) +#define AT91_TC_BCPC (3 << 26) /* Waveform Mode: RC Compare Effect on TIOB */ +#define AT91_TC_BCPC_NONE (0 << 26) +#define AT91_TC_BCPC_SET (1 << 26) +#define AT91_TC_BCPC_CLEAR (2 << 26) +#define AT91_TC_BCPC_TOGGLE (3 << 26) +#define AT91_TC_BEEVT (3 << 28) /* Waveform Mode: External Event Effect on TIOB */ +#define AT91_TC_BEEVT_NONE (0 << 28) +#define AT91_TC_BEEVT_SET (1 << 28) +#define AT91_TC_BEEVT_CLEAR (2 << 28) +#define AT91_TC_BEEVT_TOGGLE (3 << 28) +#define AT91_TC_BSWTRG (3 << 30) /* Waveform Mode: Software Trigger Effect on TIOB */ +#define AT91_TC_BSWTRG_NONE (0 << 30) +#define AT91_TC_BSWTRG_SET (1 << 30) +#define AT91_TC_BSWTRG_CLEAR (2 << 30) +#define AT91_TC_BSWTRG_TOGGLE (3 << 30) + +#define AT91_TC_CV 0x10 /* Counter Value */ +#define AT91_TC_RA 0x14 /* Register A */ +#define AT91_TC_RB 0x18 /* Register B */ +#define AT91_TC_RC 0x1c /* Register C */ + +#define AT91_TC_SR 0x20 /* Status Register */ +#define AT91_TC_COVFS (1 << 0) /* Counter Overflow Status */ +#define AT91_TC_LOVRS (1 << 1) /* Load Overrun Status */ +#define AT91_TC_CPAS (1 << 2) /* RA Compare Status */ +#define AT91_TC_CPBS (1 << 3) /* RB Compare Status */ +#define AT91_TC_CPCS (1 << 4) /* RC Compare Status */ +#define AT91_TC_LDRAS (1 << 5) /* RA Loading Status */ +#define AT91_TC_LDRBS (1 << 6) /* RB Loading Status */ +#define AT91_TC_ETRGS (1 << 7) /* External Trigger Status */ +#define AT91_TC_CLKSTA (1 << 16) /* Clock Enabling Status */ +#define AT91_TC_MTIOA (1 << 17) /* TIOA Mirror */ +#define AT91_TC_MTIOB (1 << 18) /* TIOB Mirror */ + +#define AT91_TC_IER 0x24 /* Interrupt Enable Register */ +#define AT91_TC_IDR 0x28 /* Interrupt Disable Register */ +#define AT91_TC_IMR 0x2c /* Interrupt Mask Register */ + +#endif diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_udp.h b/include/asm-arm/arch-at91rm9200/at91rm9200_udp.h new file mode 100644 index 00000000000..951e3f61cef --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/at91rm9200_udp.h @@ -0,0 +1,77 @@ +/* + * include/asm-arm/arch-at91rm9200/at91rm9200_udp.h + * + * Copyright (C) 2005 Ivan Kokshaysky + * Copyright (C) SAN People + * + * USB Device Port (UDP) registers. + * Based on AT91RM9200 datasheet revision E. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef AT91RM9200_UDP_H +#define AT91RM9200_UDP_H + +#define AT91_UDP_FRM_NUM 0x00 /* Frame Number Register */ +#define AT91_UDP_NUM (0x7ff << 0) /* Frame Number */ +#define AT91_UDP_FRM_ERR (1 << 16) /* Frame Error */ +#define AT91_UDP_FRM_OK (1 << 17) /* Frame OK */ + +#define AT91_UDP_GLB_STAT 0x04 /* Global State Register */ +#define AT91_UDP_FADDEN (1 << 0) /* Function Address Enable */ +#define AT91_UDP_CONFG (1 << 1) /* Configured */ +#define AT91_UDP_ESR (1 << 2) /* Enable Send Resume */ +#define AT91_UDP_RSMINPR (1 << 3) /* Resume has been sent */ +#define AT91_UDP_RMWUPE (1 << 4) /* Remote Wake Up Enable */ + +#define AT91_UDP_FADDR 0x08 /* Function Address Register */ +#define AT91_UDP_FADD (0x7f << 0) /* Function Address Value */ +#define AT91_UDP_FEN (1 << 8) /* Function Enable */ + +#define AT91_UDP_IER 0x10 /* Interrupt Enable Register */ +#define AT91_UDP_IDR 0x14 /* Interrupt Disable Register */ +#define AT91_UDP_IMR 0x18 /* Interrupt Mask Register */ + +#define AT91_UDP_ISR 0x1c /* Interrupt Status Register */ +#define AT91_UDP_EP(n) (1 << (n)) /* Endpoint Interrupt Status */ +#define AT91_UDP_RXSUSP (1 << 8) /* USB Suspend Interrupt Status */ +#define AT91_UDP_RXRSM (1 << 9) /* USB Resume Interrupt Status */ +#define AT91_UDP_EXTRSM (1 << 10) /* External Resume Interrupt Status */ +#define AT91_UDP_SOFINT (1 << 11) /* Start of Frame Interrupt Status */ +#define AT91_UDP_ENDBUSRES (1 << 12) /* End of Bus Reset Interrpt Status */ +#define AT91_UDP_WAKEUP (1 << 13) /* USB Wakeup Interrupt Status */ + +#define AT91_UDP_ICR 0x20 /* Interrupt Clear Register */ +#define AT91_UDP_RST_EP 0x28 /* Reset Endpoint Register */ + +#define AT91_UDP_CSR(n) (0x30 + ((n) * 4)) /* Endpoint Control/Status Registers 0-7 */ +#define AT91_UDP_TXCOMP (1 << 0) /* Generates IN packet with data previously written in DPR */ +#define AT91_UDP_RX_DATA_BK0 (1 << 1) /* Receive Data Bank 0 */ +#define AT91_UDP_RXSETUP (1 << 2) /* Send STALL to the host */ +#define AT91_UDP_STALLSENT (1 << 3) /* Stall Sent / Isochronous error (Isochronous endpoints) */ +#define AT91_UDP_TXPKTRDY (1 << 4) /* Transmit Packet Ready */ +#define AT91_UDP_FORCESTALL (1 << 5) /* Force Stall */ +#define AT91_UDP_RX_DATA_BK1 (1 << 6) /* Receive Data Bank 1 */ +#define AT91_UDP_DIR (1 << 7) /* Transfer Direction */ +#define AT91_UDP_EPTYPE (7 << 8) /* Endpoint Type */ +#define AT91_UDP_EPTYPE_CTRL (0 << 8) +#define AT91_UDP_EPTYPE_ISO_OUT (1 << 8) +#define AT91_UDP_EPTYPE_BULK_OUT (2 << 8) +#define AT91_UDP_EPTYPE_INT_OUT (3 << 8) +#define AT91_UDP_EPTYPE_ISO_IN (5 << 8) +#define AT91_UDP_EPTYPE_BULK_IN (6 << 8) +#define AT91_UDP_EPTYPE_INT_IN (7 << 8) +#define AT91_UDP_DTGLE (1 << 11) /* Data Toggle */ +#define AT91_UDP_EPEDS (1 << 15) /* Endpoint Enable/Disable */ +#define AT91_UDP_RXBYTECNT (0x7ff << 16) /* Number of bytes in FIFO */ + +#define AT91_UDP_FDR(n) (0x50 + ((n) * 4)) /* Endpoint FIFO Data Registers 0-7 */ + +#define AT91_UDP_TXVC 0x74 /* Transceiver Control Register */ +#define AT91_UDP_TXVC_TXVDIS (1 << 8) /* Transceiver Disable */ + +#endif -- cgit v1.2.3 From 466e6227e6a54d9b94b50972612fe8bf0450f786 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Mon, 19 Jun 2006 17:26:23 +0100 Subject: [ARM] 3588/1: AT91RM9200 CSB337/637 board update Patch from Andrew Victor This patch updates the support for the Cogent CSB337 and CSB637 boards. The changes include: 1. Use the new at91_uart_config structure and device registration functions for the UARTs. 2. Registration of I2C and SPI platform devices. 3. The CSB337 board uses PB0 & PB1 (and not PB2) for the LEDs. [Patch from David Brownell] Signed-off-by: Andrew Victor Signed-off-by: Russell King --- arch/arm/mach-at91rm9200/board-csb337.c | 43 +++++++++++++++++++-------------- arch/arm/mach-at91rm9200/board-csb637.c | 30 +++++++++++------------ 2 files changed, 39 insertions(+), 34 deletions(-) diff --git a/arch/arm/mach-at91rm9200/board-csb337.c b/arch/arm/mach-at91rm9200/board-csb337.c index f45104ceea8..3b9de181ae3 100644 --- a/arch/arm/mach-at91rm9200/board-csb337.c +++ b/arch/arm/mach-at91rm9200/board-csb337.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -35,8 +36,8 @@ #include #include -#include #include +#include #include "generic.h" @@ -54,32 +55,24 @@ static void __init csb337_init_irq(void) * 0 .. 3 = USART0 .. USART3 * 4 = DBGU */ -#define CSB337_UART_MAP { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */ -#define CSB337_SERIAL_CONSOLE 0 /* ttyS0 */ +static struct at91_uart_config __initdata csb337_uart_config = { + .console_tty = 0, /* ttyS0 */ + .nr_tty = 2, + .tty_map = { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */ +}; static void __init csb337_map_io(void) { - int serial[AT91_NR_UART] = CSB337_UART_MAP; - int i; - at91rm9200_map_io(); /* Initialize clocks: 3.6864 MHz crystal */ at91_clock_init(3686400); /* Setup the LEDs */ - at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2); - -#ifdef CONFIG_SERIAL_AT91 - at91_console_port = CSB337_SERIAL_CONSOLE; - memcpy(at91_serial_map, serial, sizeof(serial)); - - /* Register UARTs */ - for (i = 0; i < AT91_NR_UART; i++) { - if (serial[i] >= 0) - at91_register_uart(i, serial[i]); - } -#endif + at91_init_leds(AT91_PIN_PB0, AT91_PIN_PB1); + + /* Setup the serial ports and console */ + at91_init_serial(&csb337_uart_config); } static struct at91_eth_data __initdata csb337_eth_data = { @@ -118,17 +111,31 @@ static struct at91_mmc_data __initdata csb337_mmc_data = { .wp_pin = AT91_PIN_PD6, }; +static struct spi_board_info csb337_spi_devices[] = { + { /* CAN controller */ + .modalias = "sak82c900", + .chip_select = 0, + .max_speed_hz = 6 * 1000 * 1000, + }, +}; + static void __init csb337_board_init(void) { + /* Serial */ + at91_add_device_serial(); /* Ethernet */ at91_add_device_eth(&csb337_eth_data); /* USB Host */ at91_add_device_usbh(&csb337_usbh_data); /* USB Device */ at91_add_device_udc(&csb337_udc_data); + /* I2C */ + at91_add_device_i2c(); /* Compact Flash */ at91_set_gpio_input(AT91_PIN_PB22, 1); /* IOIS16 */ at91_add_device_cf(&csb337_cf_data); + /* SPI */ + at91_add_device_spi(csb337_spi_devices, ARRAY_SIZE(csb337_spi_devices)); /* MMC */ at91_add_device_mmc(&csb337_mmc_data); } diff --git a/arch/arm/mach-at91rm9200/board-csb637.c b/arch/arm/mach-at91rm9200/board-csb637.c index f2c2d6e79bc..2c4470d110d 100644 --- a/arch/arm/mach-at91rm9200/board-csb637.c +++ b/arch/arm/mach-at91rm9200/board-csb637.c @@ -35,8 +35,8 @@ #include #include -#include #include +#include #include "generic.h" @@ -54,14 +54,14 @@ static void __init csb637_init_irq(void) * 0 .. 3 = USART0 .. USART3 * 4 = DBGU */ -#define CSB637_UART_MAP { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */ -#define CSB637_SERIAL_CONSOLE 0 /* ttyS0 */ +static struct at91_uart_config __initdata csb637_uart_config = { + .console_tty = 0, /* ttyS0 */ + .nr_tty = 2, + .tty_map = { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */ +}; static void __init csb637_map_io(void) { - int serial[AT91_NR_UART] = CSB637_UART_MAP; - int i; - at91rm9200_map_io(); /* Initialize clocks: 3.6864 MHz crystal */ @@ -70,16 +70,8 @@ static void __init csb637_map_io(void) /* Setup the LEDs */ at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2); -#ifdef CONFIG_SERIAL_AT91 - at91_console_port = CSB637_SERIAL_CONSOLE; - memcpy(at91_serial_map, serial, sizeof(serial)); - - /* Register UARTs */ - for (i = 0; i < AT91_NR_UART; i++) { - if (serial[i] >= 0) - at91_register_uart(i, serial[i]); - } -#endif + /* Setup the serial ports and console */ + at91_init_serial(&csb637_uart_config); } static struct at91_eth_data __initdata csb637_eth_data = { @@ -98,12 +90,18 @@ static struct at91_udc_data __initdata csb637_udc_data = { static void __init csb637_board_init(void) { + /* Serial */ + at91_add_device_serial(); /* Ethernet */ at91_add_device_eth(&csb637_eth_data); /* USB Host */ at91_add_device_usbh(&csb637_usbh_data); /* USB Device */ at91_add_device_udc(&csb637_udc_data); + /* I2C */ + at91_add_device_i2c(); + /* SPI */ + at91_add_device_spi(NULL, 0); } MACHINE_START(CSB637, "Cogent CSB637") -- cgit v1.2.3 From 067bbada4cc574eaa4fa577483ecae4012049477 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Mon, 19 Jun 2006 18:16:45 +0100 Subject: [ARM] 3589/1: AT91RM9200 DK/EK board update Patch from Andrew Victor This patch updates the support for the Atmel DK and EK boards. The changes include: 1. Use the new at91_uart_config structure and device registration functions for the UARTs. 2. Registration of I2C and SPI platform devices. 3. The USB Device pullup line is connected to reset, so multidrive needs to be enabled on the line. [Patch from David Brownell]. Signed-off-by: Andrew Victor Signed-off-by: Russell King --- arch/arm/mach-at91rm9200/board-dk.c | 57 ++++++++++++++++++++++++++----------- arch/arm/mach-at91rm9200/board-ek.c | 47 +++++++++++++++++++----------- 2 files changed, 72 insertions(+), 32 deletions(-) diff --git a/arch/arm/mach-at91rm9200/board-dk.c b/arch/arm/mach-at91rm9200/board-dk.c index 2d7200ed66e..eb02ca95be7 100644 --- a/arch/arm/mach-at91rm9200/board-dk.c +++ b/arch/arm/mach-at91rm9200/board-dk.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -38,8 +39,8 @@ #include #include -#include #include +#include #include "generic.h" @@ -57,14 +58,14 @@ static void __init dk_init_irq(void) * 0 .. 3 = USART0 .. USART3 * 4 = DBGU */ -#define DK_UART_MAP { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */ -#define DK_SERIAL_CONSOLE 0 /* ttyS0 */ +static struct at91_uart_config __initdata dk_uart_config = { + .console_tty = 0, /* ttyS0 */ + .nr_tty = 2, + .tty_map = { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */ +}; static void __init dk_map_io(void) { - int serial[AT91_NR_UART] = DK_UART_MAP; - int i; - at91rm9200_map_io(); /* Initialize clocks: 18.432 MHz crystal */ @@ -73,16 +74,8 @@ static void __init dk_map_io(void) /* Setup the LEDs */ at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2); -#ifdef CONFIG_SERIAL_AT91 - at91_console_port = DK_SERIAL_CONSOLE; - memcpy(at91_serial_map, serial, sizeof(serial)); - - /* Register UARTs */ - for (i = 0; i < AT91_NR_UART; i++) { - if (at91_serial_map[i] >= 0) - at91_register_uart(i, at91_serial_map[i]); - } -#endif + /* Setup the serial ports and console */ + at91_init_serial(&dk_uart_config); } static struct at91_eth_data __initdata dk_eth_data = { @@ -111,16 +104,48 @@ static struct at91_mmc_data __initdata dk_mmc_data = { .wire4 = 1, }; +static struct spi_board_info dk_spi_devices[] = { + { /* DataFlash chip */ + .modalias = "mtd_dataflash", + .chip_select = 0, + .max_speed_hz = 15 * 1000 * 1000, + }, + { /* UR6HCPS2-SP40 PS2-to-SPI adapter */ + .modalias = "ur6hcps2", + .chip_select = 1, + .max_speed_hz = 250 * 1000, + }, + { /* TLV1504 ADC, 4 channels, 10 bits; one is a temp sensor */ + .modalias = "tlv1504", + .chip_select = 2, + .max_speed_hz = 20 * 1000 * 1000, + }, +#ifdef CONFIG_MTD_AT91_DATAFLASH_CARD + { /* DataFlash card */ + .modalias = "mtd_dataflash", + .chip_select = 3, + .max_speed_hz = 15 * 1000 * 1000, + } +#endif +}; + static void __init dk_board_init(void) { + /* Serial */ + at91_add_device_serial(); /* Ethernet */ at91_add_device_eth(&dk_eth_data); /* USB Host */ at91_add_device_usbh(&dk_usbh_data); /* USB Device */ at91_add_device_udc(&dk_udc_data); + at91_set_multi_drive(dk_udc_data.pullup_pin, 1); /* pullup_pin is connected to reset */ /* Compact Flash */ at91_add_device_cf(&dk_cf_data); + /* I2C */ + at91_add_device_i2c(); + /* SPI */ + at91_add_device_spi(dk_spi_devices, ARRAY_SIZE(dk_spi_devices)); #ifdef CONFIG_MTD_AT91_DATAFLASH_CARD /* DataFlash card */ at91_set_gpio_output(AT91_PIN_PB7, 0); diff --git a/arch/arm/mach-at91rm9200/board-ek.c b/arch/arm/mach-at91rm9200/board-ek.c index 80d90f5135a..4d7468e4267 100644 --- a/arch/arm/mach-at91rm9200/board-ek.c +++ b/arch/arm/mach-at91rm9200/board-ek.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -38,8 +39,8 @@ #include #include -#include #include +#include #include "generic.h" @@ -57,14 +58,14 @@ static void __init ek_init_irq(void) * 0 .. 3 = USART0 .. USART3 * 4 = DBGU */ -#define EK_UART_MAP { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */ -#define EK_SERIAL_CONSOLE 0 /* ttyS0 */ +static struct at91_uart_config __initdata ek_uart_config = { + .console_tty = 0, /* ttyS0 */ + .nr_tty = 2, + .tty_map = { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */ +}; static void __init ek_map_io(void) { - int serial[AT91_NR_UART] = EK_UART_MAP; - int i; - at91rm9200_map_io(); /* Initialize clocks: 18.432 MHz crystal */ @@ -73,16 +74,8 @@ static void __init ek_map_io(void) /* Setup the LEDs */ at91_init_leds(AT91_PIN_PB1, AT91_PIN_PB2); -#ifdef CONFIG_SERIAL_AT91 - at91_console_port = EK_SERIAL_CONSOLE; - memcpy(at91_serial_map, serial, sizeof(serial)); - - /* Register UARTs */ - for (i = 0; i < AT91_NR_UART; i++) { - if (serial[i] >= 0) - at91_register_uart(i, serial[i]); - } -#endif + /* Setup the serial ports and console */ + at91_init_serial(&ek_uart_config); } static struct at91_eth_data __initdata ek_eth_data = { @@ -106,14 +99,36 @@ static struct at91_mmc_data __initdata ek_mmc_data = { .wp_pin = AT91_PIN_PA17, }; +static struct spi_board_info ek_spi_devices[] = { + { /* DataFlash chip */ + .modalias = "mtd_dataflash", + .chip_select = 0, + .max_speed_hz = 15 * 1000 * 1000, + }, +#ifdef CONFIG_MTD_AT91_DATAFLASH_CARD + { /* DataFlash card */ + .modalias = "mtd_dataflash", + .chip_select = 3, + .max_speed_hz = 15 * 1000 * 1000, + }, +#endif +}; + static void __init ek_board_init(void) { + /* Serial */ + at91_add_device_serial(); /* Ethernet */ at91_add_device_eth(&ek_eth_data); /* USB Host */ at91_add_device_usbh(&ek_usbh_data); /* USB Device */ at91_add_device_udc(&ek_udc_data); + at91_set_multi_drive(ek_udc_data.pullup_pin, 1); /* pullup_pin is connected to reset */ + /* I2C */ + at91_add_device_i2c(); + /* SPI */ + at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices)); #ifdef CONFIG_MTD_AT91_DATAFLASH_CARD /* DataFlash card */ at91_set_gpio_output(AT91_PIN_PB22, 0); -- cgit v1.2.3 From 82dc0772a892f8b430a2d567c981fe47a11489c3 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Mon, 19 Jun 2006 18:16:46 +0100 Subject: [ARM] 3590/1: AT91RM9200 Platform devices support Patch from Andrew Victor This patch includes the structures and exported functions required for the platform-device support (added in patch 3585/1). Also adds the arch_identify() function for run-time detection of which AT91 processor the code is running on. [Original patch from Ivan Kokshaysky] Signed-off-by: Andrew Victor Signed-off-by: Russell King --- include/asm-arm/arch-at91rm9200/board.h | 23 ++++++++++++++++++++--- include/asm-arm/arch-at91rm9200/system.h | 8 ++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/include/asm-arm/arch-at91rm9200/board.h b/include/asm-arm/arch-at91rm9200/board.h index 4fdef13d01d..587948d5675 100644 --- a/include/asm-arm/arch-at91rm9200/board.h +++ b/include/asm-arm/arch-at91rm9200/board.h @@ -39,6 +39,8 @@ extern int at91_serial_map[AT91_NR_UART]; extern int at91_console_port; #include +#include +#include /* USB Device */ struct at91_udc_data { @@ -91,10 +93,25 @@ struct at91_nand_data { extern void __init at91_add_device_nand(struct at91_nand_data *data); /* I2C*/ -void __init at91_add_device_i2c(void); +extern void __init at91_add_device_i2c(void); - /* RTC */ -void __init at91_add_device_rtc(void); + /* SPI */ +extern void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices); + + /* Serial */ +struct at91_uart_config { + unsigned short console_tty; /* tty number of serial console */ + unsigned short nr_tty; /* number of serial tty's */ + short tty_map[]; /* map UART to tty number */ +}; +extern struct platform_device *at91_default_console_device; +extern void __init at91_init_serial(struct at91_uart_config *config); + +struct at91_uart_data { + short use_dma_tx; /* use transmit DMA? */ + short use_dma_rx; /* use receive DMA? */ +}; +extern void __init at91_add_device_serial(void); /* LEDs */ extern u8 at91_leds_cpu; diff --git a/include/asm-arm/arch-at91rm9200/system.h b/include/asm-arm/arch-at91rm9200/system.h index 29c42655f05..945e66507a7 100644 --- a/include/asm-arm/arch-at91rm9200/system.h +++ b/include/asm-arm/arch-at91rm9200/system.h @@ -48,4 +48,12 @@ static inline void arch_reset(char mode) at91_sys_write(AT91_ST_CR, AT91_ST_WDRST); } +#define ARCH_ID_AT91RM9200 0x09200080 +#define ARCH_ID_AT91SAM9261 0x019000a0 + +static inline unsigned long arch_identify(void) +{ + return at91_sys_read(AT91_DBGU_CIDR) & (AT91_CIDR_EPROC | AT91_CIDR_ARCH); +} + #endif -- cgit v1.2.3 From bf1c56a3aaa67ac74bc74e631ecc2a2673597cae Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Mon, 19 Jun 2006 18:30:04 +0100 Subject: [ARM] 3591/1: Anubis: IDE device definitions Patch from Ben Dooks Platform device definitions for the two IDE ports on the Simtec Anubis board. Signed-off-by: Ben Dooks Signed-off-by: Russell King --- arch/arm/mach-s3c2410/mach-anubis.c | 50 +++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/arch/arm/mach-s3c2410/mach-anubis.c b/arch/arm/mach-s3c2410/mach-anubis.c index 52bf718137d..4a92d6f92d6 100644 --- a/arch/arm/mach-s3c2410/mach-anubis.c +++ b/arch/arm/mach-s3c2410/mach-anubis.c @@ -239,6 +239,54 @@ static struct s3c2410_platform_nand anubis_nand_info = { .select_chip = anubis_nand_select, }; +/* IDE channels */ + +static struct resource anubis_ide0_resource[] = { + { + .start = S3C2410_CS3, + .end = S3C2410_CS3 + (8*32) - 1, + .flags = IORESOURCE_MEM, + }, { + .start = S3C2410_CS3 + (1<<26), + .end = S3C2410_CS3 + (1<<26) + (8*32) - 1, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_IDE0, + .end = IRQ_IDE0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device anubis_device_ide0 = { + .name = "simtec-ide", + .id = 0, + .num_resources = ARRAY_SIZE(anubis_ide0_resource), + .resource = anubis_ide0_resource, +}; + +static struct resource anubis_ide1_resource[] = { + { + .start = S3C2410_CS4, + .end = S3C2410_CS4 + (8*32) - 1, + .flags = IORESOURCE_MEM, + }, { + .start = S3C2410_CS4 + (1<<26), + .end = S3C2410_CS4 + (1<<26) + (8*32) - 1, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_IDE0, + .end = IRQ_IDE0, + .flags = IORESOURCE_IRQ, + }, +}; + + +static struct platform_device anubis_device_ide1 = { + .name = "simtec-ide", + .id = 1, + .num_resources = ARRAY_SIZE(anubis_ide1_resource), + .resource = anubis_ide1_resource, +}; /* Standard Anubis devices */ @@ -249,6 +297,8 @@ static struct platform_device *anubis_devices[] __initdata = { &s3c_device_i2c, &s3c_device_rtc, &s3c_device_nand, + &anubis_device_ide0, + &anubis_device_ide1, }; static struct clk *anubis_clocks[] = { -- cgit v1.2.3 From afefc4158f3c8529e4bb99c1dc119fd792bac220 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Mon, 19 Jun 2006 19:53:19 +0100 Subject: [ARM] 3592/1: AT91RM9200 Serial driver update Patch from Andrew Victor This patch includes a number of updates to the AT91RM9200 serial driver. Changes include: 1. Conversion to a platform_driver. [Ivan Kokshaysky] 2. Replaced all references to AT91RM9200 with AT91. This driver can now also be used for the AT91SAM9216. 3. Allow TIOCM_LOOP to configure local loopback mode. 4. Cleaned up the 'read_status_mask' usage and interrupt handler code. [Chip Coldwell] 5. Suspend/resume support. [David Brownell] There are a few 'unused variable' warning when compiling this - I removed the new DMA support to keep this first patch simpler. Signed-off-by: Andrew Victor Signed-off-by: Russell King --- drivers/serial/Kconfig | 17 +- drivers/serial/at91_serial.c | 463 +++++++++++++++++++------------ include/asm-arm/mach/serial_at91.h | 34 +++ include/asm-arm/mach/serial_at91rm9200.h | 36 --- include/linux/serial_core.h | 4 +- 5 files changed, 325 insertions(+), 229 deletions(-) create mode 100644 include/asm-arm/mach/serial_at91.h delete mode 100644 include/asm-arm/mach/serial_at91rm9200.h diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 7d22dc0478d..5ea778fc1ca 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -300,21 +300,22 @@ config SERIAL_AMBA_PL011_CONSOLE kernel at boot time.) config SERIAL_AT91 - bool "AT91RM9200 serial port support" - depends on ARM && ARCH_AT91RM9200 + bool "AT91RM9200 / AT91SAM9261 serial port support" + depends on ARM && (ARCH_AT91RM9200 || ARCH_AT91SAM9261) select SERIAL_CORE help - This enables the driver for the on-chip UARTs of the AT91RM9200 - processor. + This enables the driver for the on-chip UARTs of the Atmel + AT91RM9200 and AT91SAM926 processor. config SERIAL_AT91_CONSOLE - bool "Support for console on AT91RM9200 serial port" + bool "Support for console on AT91RM9200 / AT91SAM9261 serial port" depends on SERIAL_AT91=y select SERIAL_CORE_CONSOLE help - Say Y here if you wish to use a UART on the AT91RM9200 as the system - console (the system console is the device which receives all kernel - messages and warnings and which allows logins in single user mode). + Say Y here if you wish to use a UART on the Atmel AT91RM9200 or + AT91SAM9261 as the system console (the system console is the device + which receives all kernel messages and warnings and which allows + logins in single user mode). config SERIAL_AT91_TTYAT bool "Install as device ttyAT0-4 instead of ttyS0-4" diff --git a/drivers/serial/at91_serial.c b/drivers/serial/at91_serial.c index 6547fe0cef9..db5b25fafed 100644 --- a/drivers/serial/at91_serial.c +++ b/drivers/serial/at91_serial.c @@ -2,7 +2,6 @@ * linux/drivers/char/at91_serial.c * * Driver for Atmel AT91RM9200 Serial ports - * * Copyright (C) 2003 Rick Bronson * * Based on drivers/char/serial_sa1100.c, by Deep Blue Solutions Ltd. @@ -30,17 +29,19 @@ #include #include #include +#include #include #include #include +#include #include #include -#include +#include +#include #include -#include - +#include #if defined(CONFIG_SERIAL_AT91_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) #define SUPPORT_SYSRQ @@ -67,7 +68,6 @@ #endif -#define AT91_VA_BASE_DBGU ((unsigned long) AT91_VA_BASE_SYS + AT91_DBGU) #define AT91_ISR_PASS_LIMIT 256 #define UART_PUT_CR(port,v) writel(v, (port)->membase + AT91_US_CR) @@ -87,16 +87,33 @@ /* PDC registers */ #define UART_PUT_PTCR(port,v) writel(v, (port)->membase + AT91_PDC_PTCR) +#define UART_GET_PTSR(port) readl((port)->membase + AT91_PDC_PTSR) + #define UART_PUT_RPR(port,v) writel(v, (port)->membase + AT91_PDC_RPR) +#define UART_GET_RPR(port) readl((port)->membase + AT91_PDC_RPR) #define UART_PUT_RCR(port,v) writel(v, (port)->membase + AT91_PDC_RCR) -#define UART_GET_RCR(port) readl((port)->membase + AT91_PDC_RCR) #define UART_PUT_RNPR(port,v) writel(v, (port)->membase + AT91_PDC_RNPR) #define UART_PUT_RNCR(port,v) writel(v, (port)->membase + AT91_PDC_RNCR) +#define UART_PUT_TPR(port,v) writel(v, (port)->membase + AT91_PDC_TPR) +#define UART_PUT_TCR(port,v) writel(v, (port)->membase + AT91_PDC_TCR) +//#define UART_PUT_TNPR(port,v) writel(v, (port)->membase + AT91_PDC_TNPR) +//#define UART_PUT_TNCR(port,v) writel(v, (port)->membase + AT91_PDC_TNCR) static int (*at91_open)(struct uart_port *); static void (*at91_close)(struct uart_port *); +/* + * We wrap our port structure around the generic uart_port. + */ +struct at91_uart_port { + struct uart_port uart; /* uart */ + struct clk *clk; /* uart clock */ + unsigned short suspended; /* is port suspended? */ +}; + +static struct at91_uart_port at91_ports[AT91_NR_UART]; + #ifdef SUPPORT_SYSRQ static struct console at91_console; #endif @@ -115,16 +132,19 @@ static u_int at91_tx_empty(struct uart_port *port) static void at91_set_mctrl(struct uart_port *port, u_int mctrl) { unsigned int control = 0; + unsigned int mode; - /* - * Errata #39: RTS0 is not internally connected to PA21. We need to drive - * the pin manually. - */ - if (port->mapbase == AT91_VA_BASE_US0) { - if (mctrl & TIOCM_RTS) - at91_sys_write(AT91_PIOA + PIO_CODR, AT91_PA21_RTS0); - else - at91_sys_write(AT91_PIOA + PIO_SODR, AT91_PA21_RTS0); + if (arch_identify() == ARCH_ID_AT91RM9200) { + /* + * AT91RM9200 Errata #39: RTS0 is not internally connected to PA21. + * We need to drive the pin manually. + */ + if (port->mapbase == AT91_BASE_US0) { + if (mctrl & TIOCM_RTS) + at91_sys_write(AT91_PIOA + PIO_CODR, AT91_PA21_RTS0); + else + at91_sys_write(AT91_PIOA + PIO_SODR, AT91_PA21_RTS0); + } } if (mctrl & TIOCM_RTS) @@ -137,7 +157,15 @@ static void at91_set_mctrl(struct uart_port *port, u_int mctrl) else control |= AT91_US_DTRDIS; - UART_PUT_CR(port,control); + UART_PUT_CR(port, control); + + /* Local loopback mode? */ + mode = UART_GET_MR(port) & ~AT91_US_CHMODE; + if (mctrl & TIOCM_LOOP) + mode |= AT91_US_CHMODE_LOC_LOOP; + else + mode |= AT91_US_CHMODE_NORMAL; + UART_PUT_MR(port, mode); } /* @@ -169,8 +197,9 @@ static u_int at91_get_mctrl(struct uart_port *port) */ static void at91_stop_tx(struct uart_port *port) { + struct at91_uart_port *at91_port = (struct at91_uart_port *) port; + UART_PUT_IDR(port, AT91_US_TXRDY); - port->read_status_mask &= ~AT91_US_TXRDY; } /* @@ -178,7 +207,8 @@ static void at91_stop_tx(struct uart_port *port) */ static void at91_start_tx(struct uart_port *port) { - port->read_status_mask |= AT91_US_TXRDY; + struct at91_uart_port *at91_port = (struct at91_uart_port *) port; + UART_PUT_IER(port, AT91_US_TXRDY); } @@ -187,6 +217,8 @@ static void at91_start_tx(struct uart_port *port) */ static void at91_stop_rx(struct uart_port *port) { + struct at91_uart_port *at91_port = (struct at91_uart_port *) port; + UART_PUT_IDR(port, AT91_US_RXRDY); } @@ -195,7 +227,6 @@ static void at91_stop_rx(struct uart_port *port) */ static void at91_enable_ms(struct uart_port *port) { - port->read_status_mask |= (AT91_US_RIIC | AT91_US_DSRIC | AT91_US_DCDIC | AT91_US_CTSIC); UART_PUT_IER(port, AT91_US_RIIC | AT91_US_DSRIC | AT91_US_DCDIC | AT91_US_CTSIC); } @@ -218,8 +249,8 @@ static void at91_rx_chars(struct uart_port *port, struct pt_regs *regs) struct tty_struct *tty = port->info->tty; unsigned int status, ch, flg; - status = UART_GET_CSR(port) & port->read_status_mask; - while (status & (AT91_US_RXRDY)) { + status = UART_GET_CSR(port); + while (status & AT91_US_RXRDY) { ch = UART_GET_CHAR(port); port->icount.rx++; @@ -230,40 +261,38 @@ static void at91_rx_chars(struct uart_port *port, struct pt_regs *regs) * note that the error handling code is * out of the main execution path */ - if (unlikely(status & (AT91_US_PARE | AT91_US_FRAME | AT91_US_OVRE))) { + if (unlikely(status & (AT91_US_PARE | AT91_US_FRAME | AT91_US_OVRE | AT91_US_RXBRK))) { UART_PUT_CR(port, AT91_US_RSTSTA); /* clear error */ - if (status & (AT91_US_PARE)) + if (status & AT91_US_RXBRK) { + status &= ~(AT91_US_PARE | AT91_US_FRAME); /* ignore side-effect */ + port->icount.brk++; + if (uart_handle_break(port)) + goto ignore_char; + } + if (status & AT91_US_PARE) port->icount.parity++; - if (status & (AT91_US_FRAME)) + if (status & AT91_US_FRAME) port->icount.frame++; - if (status & (AT91_US_OVRE)) + if (status & AT91_US_OVRE) port->icount.overrun++; - if (status & AT91_US_PARE) + status &= port->read_status_mask; + + if (status & AT91_US_RXBRK) + flg = TTY_BREAK; + else if (status & AT91_US_PARE) flg = TTY_PARITY; else if (status & AT91_US_FRAME) flg = TTY_FRAME; - if (status & AT91_US_OVRE) { - /* - * overrun does *not* affect the character - * we read from the FIFO - */ - tty_insert_flip_char(tty, ch, flg); - ch = 0; - flg = TTY_OVERRUN; - } -#ifdef SUPPORT_SYSRQ - port->sysrq = 0; -#endif } if (uart_handle_sysrq_char(port, ch, regs)) goto ignore_char; - tty_insert_flip_char(tty, ch, flg); + uart_insert_char(port, status, AT91_US_OVRE, ch, flg); ignore_char: - status = UART_GET_CSR(port) & port->read_status_mask; + status = UART_GET_CSR(port); } tty_flip_buffer_push(tty); @@ -308,40 +337,35 @@ static void at91_tx_chars(struct uart_port *port) static irqreturn_t at91_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct uart_port *port = dev_id; + struct at91_uart_port *at91_port = (struct at91_uart_port *) port; unsigned int status, pending, pass_counter = 0; status = UART_GET_CSR(port); - pending = status & port->read_status_mask; - if (pending) { - do { - if (pending & AT91_US_RXRDY) - at91_rx_chars(port, regs); - - /* Clear the relevent break bits */ - if (pending & AT91_US_RXBRK) { - UART_PUT_CR(port, AT91_US_RSTSTA); - port->icount.brk++; - uart_handle_break(port); - } + pending = status & UART_GET_IMR(port); + while (pending) { + /* Interrupt receive */ + if (pending & AT91_US_RXRDY) + at91_rx_chars(port, regs); + + // TODO: All reads to CSR will clear these interrupts! + if (pending & AT91_US_RIIC) port->icount.rng++; + if (pending & AT91_US_DSRIC) port->icount.dsr++; + if (pending & AT91_US_DCDIC) + uart_handle_dcd_change(port, !(status & AT91_US_DCD)); + if (pending & AT91_US_CTSIC) + uart_handle_cts_change(port, !(status & AT91_US_CTS)); + if (pending & (AT91_US_RIIC | AT91_US_DSRIC | AT91_US_DCDIC | AT91_US_CTSIC)) + wake_up_interruptible(&port->info->delta_msr_wait); + + /* Interrupt transmit */ + if (pending & AT91_US_TXRDY) + at91_tx_chars(port); + + if (pass_counter++ > AT91_ISR_PASS_LIMIT) + break; - // TODO: All reads to CSR will clear these interrupts! - if (pending & AT91_US_RIIC) port->icount.rng++; - if (pending & AT91_US_DSRIC) port->icount.dsr++; - if (pending & AT91_US_DCDIC) - uart_handle_dcd_change(port, !(status & AT91_US_DCD)); - if (pending & AT91_US_CTSIC) - uart_handle_cts_change(port, !(status & AT91_US_CTS)); - if (pending & (AT91_US_RIIC | AT91_US_DSRIC | AT91_US_DCDIC | AT91_US_CTSIC)) - wake_up_interruptible(&port->info->delta_msr_wait); - - if (pending & AT91_US_TXRDY) - at91_tx_chars(port); - if (pass_counter++ > AT91_ISR_PASS_LIMIT) - break; - - status = UART_GET_CSR(port); - pending = status & port->read_status_mask; - } while (pending); + status = UART_GET_CSR(port); + pending = status & UART_GET_IMR(port); } return IRQ_HANDLED; } @@ -351,6 +375,7 @@ static irqreturn_t at91_interrupt(int irq, void *dev_id, struct pt_regs *regs) */ static int at91_startup(struct uart_port *port) { + struct at91_uart_port *at91_port = (struct at91_uart_port *) port; int retval; /* @@ -381,14 +406,14 @@ static int at91_startup(struct uart_port *port) } } - port->read_status_mask = AT91_US_RXRDY | AT91_US_TXRDY | AT91_US_OVRE - | AT91_US_FRAME | AT91_US_PARE | AT91_US_RXBRK; /* * Finally, enable the serial port */ UART_PUT_CR(port, AT91_US_RSTSTA | AT91_US_RSTRX); UART_PUT_CR(port, AT91_US_TXEN | AT91_US_RXEN); /* enable xmit & rcvr */ - UART_PUT_IER(port, AT91_US_RXRDY); /* do receive only */ + + UART_PUT_IER(port, AT91_US_RXRDY); /* enable receive only */ + return 0; } @@ -397,6 +422,8 @@ static int at91_startup(struct uart_port *port) */ static void at91_shutdown(struct uart_port *port) { + struct at91_uart_port *at91_port = (struct at91_uart_port *) port; + /* * Disable all interrupts, port and break condition. */ @@ -421,21 +448,22 @@ static void at91_shutdown(struct uart_port *port) */ static void at91_serial_pm(struct uart_port *port, unsigned int state, unsigned int oldstate) { + struct at91_uart_port *at91_port = (struct at91_uart_port *) port; + switch (state) { case 0: /* * Enable the peripheral clock for this serial port. * This is called on uart_open() or a resume event. */ - at91_sys_write(AT91_PMC_PCER, 1 << port->irq); + clk_enable(at91_port->clk); break; case 3: /* * Disable the peripheral clock for this serial port. * This is called on uart_close() or a suspend event. */ - if (port->irq != AT91_ID_SYS) /* is this a shared clock? */ - at91_sys_write(AT91_PMC_PCDR, 1 << port->irq); + clk_disable(at91_port->clk); break; default: printk(KERN_ERR "at91_serial: unknown pm %d\n", state); @@ -494,9 +522,9 @@ static void at91_set_termios(struct uart_port *port, struct termios * termios, s spin_lock_irqsave(&port->lock, flags); - port->read_status_mask |= AT91_US_OVRE; + port->read_status_mask = AT91_US_OVRE; if (termios->c_iflag & INPCK) - port->read_status_mask |= AT91_US_FRAME | AT91_US_PARE; + port->read_status_mask |= (AT91_US_FRAME | AT91_US_PARE); if (termios->c_iflag & (BRKINT | PARMRK)) port->read_status_mask |= AT91_US_RXBRK; @@ -552,7 +580,7 @@ static void at91_set_termios(struct uart_port *port, struct termios * termios, s */ static const char *at91_type(struct uart_port *port) { - return (port->type == PORT_AT91RM9200) ? "AT91_SERIAL" : NULL; + return (port->type == PORT_AT91) ? "AT91_SERIAL" : NULL; } /* @@ -560,8 +588,15 @@ static const char *at91_type(struct uart_port *port) */ static void at91_release_port(struct uart_port *port) { - release_mem_region(port->mapbase, - (port->mapbase == AT91_VA_BASE_DBGU) ? 512 : SZ_16K); + struct platform_device *pdev = to_platform_device(port->dev); + int size = pdev->resource[0].end - pdev->resource[0].start + 1; + + release_mem_region(port->mapbase, size); + + if (port->flags & UPF_IOREMAP) { + iounmap(port->membase); + port->membase = NULL; + } } /* @@ -569,10 +604,21 @@ static void at91_release_port(struct uart_port *port) */ static int at91_request_port(struct uart_port *port) { - return request_mem_region(port->mapbase, - (port->mapbase == AT91_VA_BASE_DBGU) ? 512 : SZ_16K, - "at91_serial") != NULL ? 0 : -EBUSY; + struct platform_device *pdev = to_platform_device(port->dev); + int size = pdev->resource[0].end - pdev->resource[0].start + 1; + + if (!request_mem_region(port->mapbase, size, "at91_serial")) + return -EBUSY; + + if (port->flags & UPF_IOREMAP) { + port->membase = ioremap(port->mapbase, size); + if (port->membase == NULL) { + release_mem_region(port->mapbase, size); + return -ENOMEM; + } + } + return 0; } /* @@ -581,7 +627,7 @@ static int at91_request_port(struct uart_port *port) static void at91_config_port(struct uart_port *port, int flags) { if (flags & UART_CONFIG_TYPE) { - port->type = PORT_AT91RM9200; + port->type = PORT_AT91; at91_request_port(port); } } @@ -592,7 +638,7 @@ static void at91_config_port(struct uart_port *port, int flags) static int at91_verify_port(struct uart_port *port, struct serial_struct *ser) { int ret = 0; - if (ser->type != PORT_UNKNOWN && ser->type != PORT_AT91RM9200) + if (ser->type != PORT_UNKNOWN && ser->type != PORT_AT91) ret = -EINVAL; if (port->irq != ser->irq) ret = -EINVAL; @@ -624,33 +670,47 @@ static struct uart_ops at91_pops = { .type = at91_type, .release_port = at91_release_port, .request_port = at91_request_port, - .config_port = at91_config_port, - .verify_port = at91_verify_port, + .config_port = at91_config_port, + .verify_port = at91_verify_port, .pm = at91_serial_pm, }; -static struct uart_port at91_ports[AT91_NR_UART]; - -void __init at91_init_ports(void) +/* + * Configure the port from the platform device resource info. + */ +static void __devinit at91_init_port(struct at91_uart_port *at91_port, struct platform_device *pdev) { - static int first = 1; - int i; - - if (!first) - return; - first = 0; + struct uart_port *port = &at91_port->uart; + struct at91_uart_data *data = pdev->dev.platform_data; + + port->iotype = UPIO_MEM; + port->flags = UPF_BOOT_AUTOCONF; + port->ops = &at91_pops; + port->fifosize = 1; + port->line = pdev->id; + port->dev = &pdev->dev; + + port->mapbase = pdev->resource[0].start; + port->irq = pdev->resource[1].start; + + if (port->mapbase == AT91_VA_BASE_SYS + AT91_DBGU) /* Part of system perpherals - already mapped */ + port->membase = (void __iomem *) port->mapbase; + else { + port->flags |= UPF_IOREMAP; + port->membase = NULL; + } - for (i = 0; i < AT91_NR_UART; i++) { - at91_ports[i].iotype = UPIO_MEM; - at91_ports[i].flags = UPF_BOOT_AUTOCONF; - at91_ports[i].uartclk = at91_master_clock; - at91_ports[i].ops = &at91_pops; - at91_ports[i].fifosize = 1; - at91_ports[i].line = i; - } + if (!at91_port->clk) { /* for console, the clock could already be configured */ + at91_port->clk = clk_get(&pdev->dev, "usart"); + clk_enable(at91_port->clk); + port->uartclk = clk_get_rate(at91_port->clk); + } } -void __init at91_register_uart_fns(struct at91rm9200_port_fns *fns) +/* + * Register board-specific modem-control line handlers. + */ +void __init at91_register_uart_fns(struct at91_port_fns *fns) { if (fns->enable_ms) at91_pops.enable_ms = fns->enable_ms; @@ -664,51 +724,6 @@ void __init at91_register_uart_fns(struct at91rm9200_port_fns *fns) at91_pops.set_wake = fns->set_wake; } -/* - * Setup ports. - */ -void __init at91_register_uart(int idx, int port) -{ - if ((idx < 0) || (idx >= AT91_NR_UART)) { - printk(KERN_ERR "%s: bad index number %d\n", __FUNCTION__, idx); - return; - } - - switch (port) { - case 0: - at91_ports[idx].membase = (void __iomem *) AT91_VA_BASE_US0; - at91_ports[idx].mapbase = AT91_VA_BASE_US0; - at91_ports[idx].irq = AT91_ID_US0; - AT91_CfgPIO_USART0(); - break; - case 1: - at91_ports[idx].membase = (void __iomem *) AT91_VA_BASE_US1; - at91_ports[idx].mapbase = AT91_VA_BASE_US1; - at91_ports[idx].irq = AT91_ID_US1; - AT91_CfgPIO_USART1(); - break; - case 2: - at91_ports[idx].membase = (void __iomem *) AT91_VA_BASE_US2; - at91_ports[idx].mapbase = AT91_VA_BASE_US2; - at91_ports[idx].irq = AT91_ID_US2; - AT91_CfgPIO_USART2(); - break; - case 3: - at91_ports[idx].membase = (void __iomem *) AT91_VA_BASE_US3; - at91_ports[idx].mapbase = AT91_VA_BASE_US3; - at91_ports[idx].irq = AT91_ID_US3; - AT91_CfgPIO_USART3(); - break; - case 4: - at91_ports[idx].membase = (void __iomem *) AT91_VA_BASE_DBGU; - at91_ports[idx].mapbase = AT91_VA_BASE_DBGU; - at91_ports[idx].irq = AT91_ID_SYS; - AT91_CfgPIO_DBGU(); - break; - default: - printk(KERN_ERR "%s : bad port number %d\n", __FUNCTION__, port); - } -} #ifdef CONFIG_SERIAL_AT91_CONSOLE static void at91_console_putchar(struct uart_port *port, int ch) @@ -723,7 +738,7 @@ static void at91_console_putchar(struct uart_port *port, int ch) */ static void at91_console_write(struct console *co, const char *s, u_int count) { - struct uart_port *port = at91_ports + co->index; + struct uart_port *port = &at91_ports[co->index].uart; unsigned int status, imr; /* @@ -778,23 +793,15 @@ static void __init at91_console_get_options(struct uart_port *port, int *baud, i static int __init at91_console_setup(struct console *co, char *options) { - struct uart_port *port; + struct uart_port *port = &at91_ports[co->index].uart; int baud = 115200; int bits = 8; int parity = 'n'; int flow = 'n'; - /* - * Check whether an invalid uart number has been specified, and - * if so, search for the first available port that does have - * console support. - */ - port = uart_get_console(at91_ports, AT91_NR_UART, co); + if (port->membase == 0) /* Port not initialized yet - delay setup */ + return -ENODEV; - /* - * Enable the serial console, in-case bootloader did not do it. - */ - at91_sys_write(AT91_PMC_PCER, 1 << port->irq); /* enable clock */ UART_PUT_IDR(port, -1); /* disable interrupts */ UART_PUT_CR(port, AT91_US_RSTSTA | AT91_US_RSTRX); UART_PUT_CR(port, AT91_US_TXEN | AT91_US_RXEN); @@ -821,23 +828,40 @@ static struct console at91_console = { #define AT91_CONSOLE_DEVICE &at91_console -static int __init at91_console_init(void) +/* + * Early console initialization (before VM subsystem initialized). + */ +static int __init at91_console_init(void) { - at91_init_ports(); + if (at91_default_console_device) { + add_preferred_console(AT91_DEVICENAME, at91_default_console_device->id, NULL); + at91_init_port(&(at91_ports[at91_default_console_device->id]), at91_default_console_device); + register_console(&at91_console); + } - at91_console.index = at91_console_port; - register_console(&at91_console); return 0; } console_initcall(at91_console_init); +/* + * Late console initialization. + */ +static int __init at91_late_console_init(void) +{ + if (at91_default_console_device && !(at91_console.flags & CON_ENABLED)) + register_console(&at91_console); + + return 0; +} +core_initcall(at91_late_console_init); + #else #define AT91_CONSOLE_DEVICE NULL #endif static struct uart_driver at91_uart = { .owner = THIS_MODULE, - .driver_name = AT91_DEVICENAME, + .driver_name = "at91_serial", .dev_name = AT91_DEVICENAME, .devfs_name = AT91_DEVICENAME, .major = SERIAL_AT91_MAJOR, @@ -846,33 +870,106 @@ static struct uart_driver at91_uart = { .cons = AT91_CONSOLE_DEVICE, }; -static int __init at91_serial_init(void) +#ifdef CONFIG_PM +static int at91_serial_suspend(struct platform_device *pdev, pm_message_t state) { - int ret, i; + struct uart_port *port = platform_get_drvdata(pdev); + struct at91_uart_port *at91_port = (struct at91_uart_port *) port; + + if (device_may_wakeup(&pdev->dev) && !at91_suspend_entering_slow_clock()) + enable_irq_wake(port->irq); + else { + disable_irq_wake(port->irq); + uart_suspend_port(&at91_uart, port); + at91_port->suspended = 1; + } - at91_init_ports(); + return 0; +} - ret = uart_register_driver(&at91_uart); - if (ret) - return ret; +static int at91_serial_resume(struct platform_device *pdev) +{ + struct uart_port *port = platform_get_drvdata(pdev); + struct at91_uart_port *at91_port = (struct at91_uart_port *) port; - for (i = 0; i < AT91_NR_UART; i++) { - if (at91_serial_map[i] >= 0) - uart_add_one_port(&at91_uart, &at91_ports[i]); + if (at91_port->suspended) { + uart_resume_port(&at91_uart, port); + at91_port->suspended = 0; } return 0; } +#else +#define at91_serial_suspend NULL +#define at91_serial_resume NULL +#endif -static void __exit at91_serial_exit(void) +static int __devinit at91_serial_probe(struct platform_device *pdev) { - int i; + struct at91_uart_port *port; + int ret; - for (i = 0; i < AT91_NR_UART; i++) { - if (at91_serial_map[i] >= 0) - uart_remove_one_port(&at91_uart, &at91_ports[i]); - } + port = &at91_ports[pdev->id]; + at91_init_port(port, pdev); + ret = uart_add_one_port(&at91_uart, &port->uart); + if (!ret) { + device_init_wakeup(&pdev->dev, 1); + platform_set_drvdata(pdev, port); + } + + return ret; +} + +static int __devexit at91_serial_remove(struct platform_device *pdev) +{ + struct uart_port *port = platform_get_drvdata(pdev); + struct at91_uart_port *at91_port = (struct at91_uart_port *) port; + int ret = 0; + + clk_disable(at91_port->clk); + clk_put(at91_port->clk); + + device_init_wakeup(&pdev->dev, 0); + platform_set_drvdata(pdev, NULL); + + if (port) { + ret = uart_remove_one_port(&at91_uart, port); + kfree(port); + } + + return ret; +} + +static struct platform_driver at91_serial_driver = { + .probe = at91_serial_probe, + .remove = __devexit_p(at91_serial_remove), + .suspend = at91_serial_suspend, + .resume = at91_serial_resume, + .driver = { + .name = "at91_usart", + .owner = THIS_MODULE, + }, +}; + +static int __init at91_serial_init(void) +{ + int ret; + + ret = uart_register_driver(&at91_uart); + if (ret) + return ret; + + ret = platform_driver_register(&at91_serial_driver); + if (ret) + uart_unregister_driver(&at91_uart); + + return ret; +} + +static void __exit at91_serial_exit(void) +{ + platform_driver_unregister(&at91_serial_driver); uart_unregister_driver(&at91_uart); } diff --git a/include/asm-arm/mach/serial_at91.h b/include/asm-arm/mach/serial_at91.h new file mode 100644 index 00000000000..18bc4e00e47 --- /dev/null +++ b/include/asm-arm/mach/serial_at91.h @@ -0,0 +1,34 @@ +/* + * linux/include/asm-arm/mach/serial_at91.h + * + * Based on serial_sa1100.h by Nicolas Pitre + * + * Copyright (C) 2002 ATMEL Rousset + * + * Low level machine dependent UART functions. + */ +#include + +struct uart_port; + +/* + * This is a temporary structure for registering these + * functions; it is intended to be discarded after boot. + */ +struct at91_port_fns { + void (*set_mctrl)(struct uart_port *, u_int); + u_int (*get_mctrl)(struct uart_port *); + void (*enable_ms)(struct uart_port *); + void (*pm)(struct uart_port *, u_int, u_int); + int (*set_wake)(struct uart_port *, u_int); + int (*open)(struct uart_port *); + void (*close)(struct uart_port *); +}; + +#if defined(CONFIG_SERIAL_AT91) +void at91_register_uart_fns(struct at91_port_fns *fns); +#else +#define at91_register_uart_fns(fns) do { } while (0) +#endif + + diff --git a/include/asm-arm/mach/serial_at91rm9200.h b/include/asm-arm/mach/serial_at91rm9200.h deleted file mode 100644 index 98f4b0cb883..00000000000 --- a/include/asm-arm/mach/serial_at91rm9200.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * linux/include/asm-arm/mach/serial_at91rm9200.h - * - * Based on serial_sa1100.h by Nicolas Pitre - * - * Copyright (C) 2002 ATMEL Rousset - * - * Low level machine dependent UART functions. - */ -#include - -struct uart_port; - -/* - * This is a temporary structure for registering these - * functions; it is intended to be discarded after boot. - */ -struct at91rm9200_port_fns { - void (*set_mctrl)(struct uart_port *, u_int); - u_int (*get_mctrl)(struct uart_port *); - void (*enable_ms)(struct uart_port *); - void (*pm)(struct uart_port *, u_int, u_int); - int (*set_wake)(struct uart_port *, u_int); - int (*open)(struct uart_port *); - void (*close)(struct uart_port *); -}; - -#if defined(CONFIG_SERIAL_AT91) -void at91_register_uart_fns(struct at91rm9200_port_fns *fns); -void at91_register_uart(int idx, int port); -#else -#define at91_register_uart_fns(fns) do { } while (0) -#define at91_register_uart(idx,port) do { } while (0) -#endif - - diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index bd14858121e..56c2a1db4a9 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -67,8 +67,8 @@ /* Parisc type numbers. */ #define PORT_MUX 48 -/* Atmel AT91RM9200 SoC */ -#define PORT_AT91RM9200 49 +/* Atmel AT91xxx SoC */ +#define PORT_AT91 49 /* Macintosh Zilog type numbers */ #define PORT_MAC_ZILOG 50 /* m68k : not yet implemented */ -- cgit v1.2.3 From 74617fb6b825ea370ae72565f7543306bc08ef6e Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Mon, 19 Jun 2006 19:57:12 +0100 Subject: [ARM] 3593/1: Add reboot and shutdown handlers for Zaurus handhelds Patch from Richard Purdie Add functionality to allow machine specific reboot handlers on ARM. Add machine specific reboot and poweroff handlers for all PXA Zaurus models. Signed-off-by: Richard Purdie Signed-off-by: Russell King --- arch/arm/kernel/process.c | 61 ++++++++++++++++++++++----------------- arch/arm/mach-pxa/corgi.c | 25 ++++++++++++++++ arch/arm/mach-pxa/poodle.c | 17 +++++++++++ arch/arm/mach-pxa/spitz.c | 25 ++++++++++++++++ arch/arm/mach-pxa/tosa.c | 25 ++++++++++++++++ include/asm-arm/arch-pxa/system.h | 1 + include/asm-arm/system.h | 3 ++ 7 files changed, 131 insertions(+), 26 deletions(-) diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 7df6e1aaa32..17c38dbf2f3 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -71,8 +72,36 @@ static int __init hlt_setup(char *__unused) __setup("nohlt", nohlt_setup); __setup("hlt", hlt_setup); +void arm_machine_restart(char mode) +{ + /* + * Clean and disable cache, and turn off interrupts + */ + cpu_proc_fin(); + + /* + * Tell the mm system that we are going to reboot - + * we may need it to insert some 1:1 mappings so that + * soft boot works. + */ + setup_mm_for_reboot(mode); + + /* + * Now call the architecture specific reboot code. + */ + arch_reset(mode); + + /* + * Whoops - the architecture was unable to reboot. + * Tell the user! + */ + mdelay(1000); + printk("Reboot failed -- System halted\n"); + while (1); +} + /* - * The following aren't currently used. + * Function pointers to optional machine specific functions */ void (*pm_idle)(void); EXPORT_SYMBOL(pm_idle); @@ -80,6 +109,10 @@ EXPORT_SYMBOL(pm_idle); void (*pm_power_off)(void); EXPORT_SYMBOL(pm_power_off); +void (*arm_pm_restart)(char str) = arm_machine_restart; +EXPORT_SYMBOL_GPL(arm_pm_restart); + + /* * This is our default idle handler. We need to disable * interrupts here to ensure we don't miss a wakeup call. @@ -151,33 +184,9 @@ void machine_power_off(void) pm_power_off(); } - void machine_restart(char * __unused) { - /* - * Clean and disable cache, and turn off interrupts - */ - cpu_proc_fin(); - - /* - * Tell the mm system that we are going to reboot - - * we may need it to insert some 1:1 mappings so that - * soft boot works. - */ - setup_mm_for_reboot(reboot_mode); - - /* - * Now call the architecture specific reboot code. - */ - arch_reset(reboot_mode); - - /* - * Whoops - the architecture was unable to reboot. - * Tell the user! - */ - mdelay(1000); - printk("Reboot failed -- System halted\n"); - while (1); + arm_pm_restart(reboot_mode); } void __show_regs(struct pt_regs *regs) diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c index d6d72603636..bf6648a8390 100644 --- a/arch/arm/mach-pxa/corgi.c +++ b/arch/arm/mach-pxa/corgi.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -26,6 +27,7 @@ #include #include #include +#include #include #include @@ -310,8 +312,31 @@ static struct platform_device *devices[] __initdata = { &corgiled_device, }; +static void corgi_poweroff(void) +{ + RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR; + + if (!machine_is_corgi()) + /* Green LED off tells the bootloader to halt */ + reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_LED_GREEN); + arm_machine_restart('h'); +} + +static void corgi_restart(char mode) +{ + RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR; + + if (!machine_is_corgi()) + /* Green LED on tells the bootloader to reboot */ + set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_LED_GREEN); + arm_machine_restart('h'); +} + static void __init corgi_init(void) { + pm_power_off = corgi_poweroff; + arm_pm_restart = corgi_restart; + /* setup sleep mode values */ PWER = 0x00000002; PFER = 0x00000000; diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c index a042473deed..1d516d317e8 100644 --- a/arch/arm/mach-pxa/poodle.c +++ b/arch/arm/mach-pxa/poodle.c @@ -18,11 +18,13 @@ #include #include #include +#include #include #include #include #include +#include #include #include @@ -247,10 +249,25 @@ static struct platform_device *devices[] __initdata = { &poodle_scoop_device, }; +static void poodle_poweroff(void) +{ + RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR; + arm_machine_restart('h'); +} + +static void poodle_restart(char mode) +{ + RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR; + arm_machine_restart('h'); +} + static void __init poodle_init(void) { int ret = 0; + pm_power_off = poodle_poweroff; + arm_pm_restart = poodle_restart; + /* setup sleep mode values */ PWER = 0x00000002; PFER = 0x00000000; diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index 44bcb8097c7..eb9937f6f5c 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -27,6 +28,7 @@ #include #include #include +#include #include #include @@ -432,8 +434,31 @@ static struct platform_device *devices[] __initdata = { &spitzled_device, }; +static void spitz_poweroff(void) +{ + RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR; + + pxa_gpio_mode(SPITZ_GPIO_ON_RESET | GPIO_OUT); + GPSR(SPITZ_GPIO_ON_RESET) = GPIO_bit(SPITZ_GPIO_ON_RESET); + + mdelay(1000); + arm_machine_restart('h'); +} + +static void spitz_restart(char mode) +{ + /* Bootloader magic for a reboot */ + if((MSC0 & 0xffff0000) == 0x7ff00000) + MSC0 = (MSC0 & 0xffff) | 0x7ee00000; + + spitz_poweroff(); +} + static void __init common_init(void) { + pm_power_off = spitz_poweroff; + arm_pm_restart = spitz_restart; + PMCR = 0x00; /* setup sleep mode values */ diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index 76c0e7f0a21..afa223b9e7a 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c @@ -19,12 +19,14 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -266,8 +268,31 @@ static struct platform_device *devices[] __initdata = { &tosaled_device, }; +static void tosa_poweroff(void) +{ + RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR; + + pxa_gpio_mode(TOSA_GPIO_ON_RESET | GPIO_OUT); + GPSR(TOSA_GPIO_ON_RESET) = GPIO_bit(TOSA_GPIO_ON_RESET); + + mdelay(1000); + arm_machine_restart('h'); +} + +static void tosa_restart(char mode) +{ + /* Bootloader magic for a reboot */ + if((MSC0 & 0xffff0000) == 0x7ff00000) + MSC0 = (MSC0 & 0xffff) | 0x7ee00000; + + tosa_poweroff(); +} + static void __init tosa_init(void) { + pm_power_off = tosa_poweroff; + arm_pm_restart = tosa_restart; + pxa_gpio_mode(TOSA_GPIO_ON_RESET | GPIO_IN); pxa_gpio_mode(TOSA_GPIO_TC6393_INT | GPIO_IN); pxa_gpio_mode(TOSA_GPIO_USB_IN | GPIO_IN); diff --git a/include/asm-arm/arch-pxa/system.h b/include/asm-arm/arch-pxa/system.h index 840a46bfbc5..1d56a3ef89f 100644 --- a/include/asm-arm/arch-pxa/system.h +++ b/include/asm-arm/arch-pxa/system.h @@ -10,6 +10,7 @@ * published by the Free Software Foundation. */ +#include #include "hardware.h" #include "pxa-regs.h" diff --git a/include/asm-arm/system.h b/include/asm-arm/system.h index 7c9568d3030..e6b762b3148 100644 --- a/include/asm-arm/system.h +++ b/include/asm-arm/system.h @@ -108,6 +108,9 @@ extern void __show_regs(struct pt_regs *); extern int cpu_architecture(void); extern void cpu_init(void); +void arm_machine_restart(char mode); +extern void (*arm_pm_restart)(char str); + /* * Intel's XScale3 core supports some v6 features (supersections, L2) * but advertises itself as v5 as it does not support the v6 ISA. For -- cgit v1.2.3 From 88660351cb6daa85baf9700f12dff3af564dc14a Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Mon, 19 Jun 2006 19:58:51 +0100 Subject: [ARM] 3561/1: Poodle: Correct the MMC/SD power control Patch from Richard Purdie Correct the Poodle power control for the MMC/SD port. Also add write protection switch support. Signed-off-by: Richard Purdie Signed-off-by: Russell King --- arch/arm/mach-pxa/poodle.c | 22 ++++++++++++++++++---- include/asm-arm/arch-pxa/poodle.h | 2 ++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c index 1d516d317e8..234877a09df 100644 --- a/arch/arm/mach-pxa/poodle.c +++ b/arch/arm/mach-pxa/poodle.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -143,7 +144,9 @@ static int poodle_mci_init(struct device *dev, irqreturn_t (*poodle_detect_int)( pxa_gpio_mode(GPIO6_MMCCLK_MD); pxa_gpio_mode(GPIO8_MMCCS0_MD); pxa_gpio_mode(POODLE_GPIO_nSD_DETECT | GPIO_IN); + pxa_gpio_mode(POODLE_GPIO_nSD_WP | GPIO_IN); pxa_gpio_mode(POODLE_GPIO_SD_PWR | GPIO_OUT); + pxa_gpio_mode(POODLE_GPIO_SD_PWR1 | GPIO_OUT); poodle_mci_platform_data.detect_delay = msecs_to_jiffies(250); @@ -162,12 +165,22 @@ static void poodle_mci_setpower(struct device *dev, unsigned int vdd) { struct pxamci_platform_data* p_d = dev->platform_data; - if (( 1 << vdd) & p_d->ocr_mask) - GPSR1 = GPIO_bit(POODLE_GPIO_SD_PWR); - else - GPCR1 = GPIO_bit(POODLE_GPIO_SD_PWR); + if (( 1 << vdd) & p_d->ocr_mask) { + GPSR(POODLE_GPIO_SD_PWR) = GPIO_bit(POODLE_GPIO_SD_PWR); + mdelay(2); + GPSR(POODLE_GPIO_SD_PWR1) = GPIO_bit(POODLE_GPIO_SD_PWR1); + } else { + GPCR(POODLE_GPIO_SD_PWR1) = GPIO_bit(POODLE_GPIO_SD_PWR1); + GPCR(POODLE_GPIO_SD_PWR) = GPIO_bit(POODLE_GPIO_SD_PWR); + } +} + +static int poodle_mci_get_ro(struct device *dev) +{ + return GPLR(POODLE_GPIO_nSD_WP) & GPIO_bit(POODLE_GPIO_nSD_WP); } + static void poodle_mci_exit(struct device *dev, void *data) { free_irq(POODLE_IRQ_GPIO_nSD_DETECT, data); @@ -176,6 +189,7 @@ static void poodle_mci_exit(struct device *dev, void *data) static struct pxamci_platform_data poodle_mci_platform_data = { .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, .init = poodle_mci_init, + .get_ro = poodle_mci_get_ro, .setpower = poodle_mci_setpower, .exit = poodle_mci_exit, }; diff --git a/include/asm-arm/arch-pxa/poodle.h b/include/asm-arm/arch-pxa/poodle.h index 6b5ac5144e7..6079e0aa1ab 100644 --- a/include/asm-arm/arch-pxa/poodle.h +++ b/include/asm-arm/arch-pxa/poodle.h @@ -31,6 +31,7 @@ #define POODLE_GPIO_CF_CD (14) #define POODLE_GPIO_CF_STSCHG (14) #define POODLE_GPIO_SD_PWR (33) +#define POODLE_GPIO_SD_PWR1 (3) #define POODLE_GPIO_nSD_CLK (6) #define POODLE_GPIO_nSD_WP (7) #define POODLE_GPIO_nSD_INT (8) @@ -42,6 +43,7 @@ #define POODLE_GPIO_BYPASS_ON (36) #define POODLE_GPIO_CHRG_ON (38) #define POODLE_GPIO_CHRG_FULL (16) +#define POODLE_GPIO_DISCHARGE_ON (42) /* Enable battery discharge */ /* PXA GPIOs */ #define POODLE_IRQ_GPIO_ON_KEY IRQ_GPIO(0) -- cgit v1.2.3 From f8703dc8cb10eca7f6fe6ef364d8e106fe07f034 Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Mon, 19 Jun 2006 19:58:52 +0100 Subject: [ARM] 3564/1: sharpsl_pm: Abstract some machine specific parameters Patch from Richard Purdie Abstract some machine specific parameters from the sharpsl_pm core into the machine specific drivers. This allows the core to support tosa/poodle. Signed-off-by: Richard Purdie Signed-off-by: Russell King --- arch/arm/common/sharpsl_pm.c | 28 +++++++++++----------------- arch/arm/mach-pxa/corgi_pm.c | 23 ++++++++++++++++++++--- arch/arm/mach-pxa/sharpsl_pm.c | 7 +++++-- arch/arm/mach-pxa/spitz_pm.c | 15 +++++++++++++++ include/asm-arm/hardware/sharpsl_pm.h | 11 +++++++++++ 5 files changed, 62 insertions(+), 22 deletions(-) diff --git a/arch/arm/common/sharpsl_pm.c b/arch/arm/common/sharpsl_pm.c index 3cd8c9ee451..045e37e0733 100644 --- a/arch/arm/common/sharpsl_pm.c +++ b/arch/arm/common/sharpsl_pm.c @@ -49,13 +49,6 @@ #define SHARPSL_CHARGE_CO_CHECK_TIME 5 /* 5 msec */ #define SHARPSL_CHARGE_RETRY_CNT 1 /* eqv. 10 min */ -#define SHARPSL_CHARGE_ON_VOLT 0x99 /* 2.9V */ -#define SHARPSL_CHARGE_ON_TEMP 0xe0 /* 2.9V */ -#define SHARPSL_CHARGE_ON_ACIN_HIGH 0x9b /* 6V */ -#define SHARPSL_CHARGE_ON_ACIN_LOW 0x34 /* 2V */ -#define SHARPSL_FATAL_ACIN_VOLT 182 /* 3.45V */ -#define SHARPSL_FATAL_NOACIN_VOLT 170 /* 3.40V */ - /* * Prototypes */ @@ -82,12 +75,13 @@ DEFINE_LED_TRIGGER(sharpsl_charge_led_trigger); static int get_percentage(int voltage) { int i = sharpsl_pm.machinfo->bat_levels - 1; + int bl_status = sharpsl_pm.machinfo->backlight_get_status ? sharpsl_pm.machinfo->backlight_get_status() : 0; struct battery_thresh *thresh; if (sharpsl_pm.charge_mode == CHRG_ON) - thresh=sharpsl_pm.machinfo->bat_levels_acin; + thresh = bl_status ? sharpsl_pm.machinfo->bat_levels_acin_bl : sharpsl_pm.machinfo->bat_levels_acin; else - thresh=sharpsl_pm.machinfo->bat_levels_noac; + thresh = bl_status ? sharpsl_pm.machinfo->bat_levels_noac_bl : sharpsl_pm.machinfo->bat_levels_noac; while (i > 0 && (voltage > thresh[i].voltage)) i--; @@ -131,7 +125,7 @@ static void sharpsl_battery_thread(void *private_) sharpsl_pm.battstat.ac_status = (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN) ? APM_AC_ONLINE : APM_AC_OFFLINE); /* Corgi cannot confirm when battery fully charged so periodically kick! */ - if (machine_is_corgi() && (sharpsl_pm.charge_mode == CHRG_ON) + if (!sharpsl_pm.machinfo->batfull_irq && (sharpsl_pm.charge_mode == CHRG_ON) && time_after(jiffies, sharpsl_pm.charge_start_time + SHARPSL_CHARGE_ON_TIME_INTERVAL)) schedule_work(&toggle_charger); @@ -166,11 +160,11 @@ static void sharpsl_battery_thread(void *private_) && ((sharpsl_pm.battstat.mainbat_status == APM_BATTERY_STATUS_LOW) || (sharpsl_pm.battstat.mainbat_status == APM_BATTERY_STATUS_CRITICAL))) { if (!(sharpsl_pm.flags & SHARPSL_BL_LIMIT)) { - corgibl_limit_intensity(1); + sharpsl_pm.machinfo->backlight_limit(1); sharpsl_pm.flags |= SHARPSL_BL_LIMIT; } } else if (sharpsl_pm.flags & SHARPSL_BL_LIMIT) { - corgibl_limit_intensity(0); + sharpsl_pm.machinfo->backlight_limit(0); sharpsl_pm.flags &= ~SHARPSL_BL_LIMIT; } @@ -418,7 +412,7 @@ static int sharpsl_check_battery_temp(void) val = get_select_val(buff); dev_dbg(sharpsl_pm.dev, "Temperature: %d\n", val); - if (val > SHARPSL_CHARGE_ON_TEMP) + if (val > sharpsl_pm.machinfo->charge_on_temp) return -1; return 0; @@ -450,7 +444,7 @@ static int sharpsl_check_battery_voltage(void) val = get_select_val(buff); dev_dbg(sharpsl_pm.dev, "Battery Voltage: %d\n", val); - if (val < SHARPSL_CHARGE_ON_VOLT) + if (val < sharpsl_pm.machinfo->charge_on_volt) return -1; return 0; @@ -468,7 +462,7 @@ static int sharpsl_ac_check(void) temp = get_select_val(buff); dev_dbg(sharpsl_pm.dev, "AC Voltage: %d\n",temp); - if ((temp > SHARPSL_CHARGE_ON_ACIN_HIGH) || (temp < SHARPSL_CHARGE_ON_ACIN_LOW)) { + if ((temp > sharpsl_pm.machinfo->charge_acin_high) || (temp < sharpsl_pm.machinfo->charge_acin_low)) { dev_err(sharpsl_pm.dev, "Error: AC check failed.\n"); return -1; } @@ -627,8 +621,8 @@ static int sharpsl_fatal_check(void) temp = get_select_val(buff); dev_dbg(sharpsl_pm.dev, "sharpsl_fatal_check: acin: %d, discharge voltage: %d, no discharge: %d\n", acin, temp, sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT)); - if ((acin && (temp < SHARPSL_FATAL_ACIN_VOLT)) || - (!acin && (temp < SHARPSL_FATAL_NOACIN_VOLT))) + if ((acin && (temp < sharpsl_pm.machinfo->fatal_acin_volt)) || + (!acin && (temp < sharpsl_pm.machinfo->fatal_noacin_volt))) return -1; return 0; } diff --git a/arch/arm/mach-pxa/corgi_pm.c b/arch/arm/mach-pxa/corgi_pm.c index 7a1ab73e9e1..4c3de4008a4 100644 --- a/arch/arm/mach-pxa/corgi_pm.c +++ b/arch/arm/mach-pxa/corgi_pm.c @@ -27,6 +27,13 @@ #include #include "sharpsl.h" +#define SHARPSL_CHARGE_ON_VOLT 0x99 /* 2.9V */ +#define SHARPSL_CHARGE_ON_TEMP 0xe0 /* 2.9V */ +#define SHARPSL_CHARGE_ON_ACIN_HIGH 0x9b /* 6V */ +#define SHARPSL_CHARGE_ON_ACIN_LOW 0x34 /* 2V */ +#define SHARPSL_FATAL_ACIN_VOLT 182 /* 3.45V */ +#define SHARPSL_FATAL_NOACIN_VOLT 170 /* 3.40V */ + static void corgi_charger_init(void) { pxa_gpio_mode(CORGI_GPIO_ADC_TEMP_ON | GPIO_OUT); @@ -195,9 +202,16 @@ static struct sharpsl_charger_machinfo corgi_pm_machinfo = { .read_devdata = corgipm_read_devdata, .charger_wakeup = corgi_charger_wakeup, .should_wakeup = corgi_should_wakeup, - .bat_levels = 40, - .bat_levels_noac = spitz_battery_levels_noac, - .bat_levels_acin = spitz_battery_levels_acin, + .backlight_limit = corgibl_limit_intensity, + .charge_on_volt = SHARPSL_CHARGE_ON_VOLT, + .charge_on_temp = SHARPSL_CHARGE_ON_TEMP, + .charge_acin_high = SHARPSL_CHARGE_ON_ACIN_HIGH, + .charge_acin_low = SHARPSL_CHARGE_ON_ACIN_LOW, + .fatal_acin_volt = SHARPSL_FATAL_ACIN_VOLT, + .fatal_noacin_volt= SHARPSL_FATAL_NOACIN_VOLT, + .bat_levels = 40, + .bat_levels_noac = spitz_battery_levels_noac, + .bat_levels_acin = spitz_battery_levels_acin, .status_high_acin = 188, .status_low_acin = 178, .status_high_noac = 185, @@ -214,6 +228,9 @@ static int __devinit corgipm_init(void) if (!corgipm_device) return -ENOMEM; + if (!machine_is_corgi()) + corgi_pm_machinfo.batfull_irq = 1; + corgipm_device->dev.platform_data = &corgi_pm_machinfo; ret = platform_device_add(corgipm_device); diff --git a/arch/arm/mach-pxa/sharpsl_pm.c b/arch/arm/mach-pxa/sharpsl_pm.c index 6d402b262d8..0f1648780c4 100644 --- a/arch/arm/mach-pxa/sharpsl_pm.c +++ b/arch/arm/mach-pxa/sharpsl_pm.c @@ -128,6 +128,9 @@ struct battery_thresh spitz_battery_levels_noac[] = { */ int sharpsl_pm_pxa_read_max1111(int channel) { + if (machine_is_tosa()) // Ugly, better move this function into another module + return 0; + return corgi_ssp_max1111_get((channel << MAXCTRL_SEL_SH) | MAXCTRL_PD0 | MAXCTRL_PD1 | MAXCTRL_SGL | MAXCTRL_UNI | MAXCTRL_STR); } @@ -156,7 +159,7 @@ void sharpsl_pm_pxa_init(void) else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal),IRQT_FALLING); } - if (!machine_is_corgi()) + if (sharpsl_pm.machinfo->batfull_irq) { /* Register interrupt handler. */ if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull), sharpsl_chrg_full_isr, SA_INTERRUPT, "CO", sharpsl_chrg_full_isr)) { @@ -174,6 +177,6 @@ void sharpsl_pm_pxa_remove(void) if (sharpsl_pm.machinfo->gpio_fatal) free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal), sharpsl_fatal_isr); - if (!machine_is_corgi()) + if (sharpsl_pm.machinfo->batfull_irq) free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull), sharpsl_chrg_full_isr); } diff --git a/arch/arm/mach-pxa/spitz_pm.c b/arch/arm/mach-pxa/spitz_pm.c index 5e5bdc89848..40be833079c 100644 --- a/arch/arm/mach-pxa/spitz_pm.c +++ b/arch/arm/mach-pxa/spitz_pm.c @@ -27,6 +27,13 @@ #include #include "sharpsl.h" +#define SHARPSL_CHARGE_ON_VOLT 0x99 /* 2.9V */ +#define SHARPSL_CHARGE_ON_TEMP 0xe0 /* 2.9V */ +#define SHARPSL_CHARGE_ON_ACIN_HIGH 0x9b /* 6V */ +#define SHARPSL_CHARGE_ON_ACIN_LOW 0x34 /* 2V */ +#define SHARPSL_FATAL_ACIN_VOLT 182 /* 3.45V */ +#define SHARPSL_FATAL_NOACIN_VOLT 170 /* 3.40V */ + static int spitz_last_ac_status; static void spitz_charger_init(void) @@ -190,6 +197,7 @@ struct sharpsl_charger_machinfo spitz_pm_machinfo = { .gpio_batlock = SPITZ_GPIO_BAT_COVER, .gpio_acin = SPITZ_GPIO_AC_IN, .gpio_batfull = SPITZ_GPIO_CHRG_FULL, + .batfull_irq = 1, .gpio_fatal = SPITZ_GPIO_FATAL_BAT, .discharge = spitz_discharge, .discharge1 = spitz_discharge1, @@ -200,6 +208,13 @@ struct sharpsl_charger_machinfo spitz_pm_machinfo = { .read_devdata = spitzpm_read_devdata, .charger_wakeup = spitz_charger_wakeup, .should_wakeup = spitz_should_wakeup, + .backlight_limit = corgibl_limit_intensity, + .charge_on_volt = SHARPSL_CHARGE_ON_VOLT, + .charge_on_temp = SHARPSL_CHARGE_ON_TEMP, + .charge_acin_high = SHARPSL_CHARGE_ON_ACIN_HIGH, + .charge_acin_low = SHARPSL_CHARGE_ON_ACIN_LOW, + .fatal_acin_volt = SHARPSL_FATAL_ACIN_VOLT, + .fatal_noacin_volt= SHARPSL_FATAL_NOACIN_VOLT, .bat_levels = 40, .bat_levels_noac = spitz_battery_levels_noac, .bat_levels_acin = spitz_battery_levels_acin, diff --git a/include/asm-arm/hardware/sharpsl_pm.h b/include/asm-arm/hardware/sharpsl_pm.h index 36983e5f366..ecf15b83956 100644 --- a/include/asm-arm/hardware/sharpsl_pm.h +++ b/include/asm-arm/hardware/sharpsl_pm.h @@ -16,6 +16,7 @@ struct sharpsl_charger_machinfo { void (*exit)(void); int gpio_acin; int gpio_batfull; + int batfull_irq; int gpio_batlock; int gpio_fatal; void (*discharge)(int); @@ -34,9 +35,19 @@ struct sharpsl_charger_machinfo { #define SHARPSL_STATUS_FATAL 7 unsigned long (*charger_wakeup)(void); int (*should_wakeup)(unsigned int resume_on_alarm); + void (*backlight_limit)(int); + int (*backlight_get_status) (void); + int charge_on_volt; + int charge_on_temp; + int charge_acin_high; + int charge_acin_low; + int fatal_acin_volt; + int fatal_noacin_volt; int bat_levels; struct battery_thresh *bat_levels_noac; struct battery_thresh *bat_levels_acin; + struct battery_thresh *bat_levels_noac_bl; + struct battery_thresh *bat_levels_acin_bl; int status_high_acin; int status_low_acin; int status_high_noac; -- cgit v1.2.3 From faed568413e89f87cd60aa8b292cc4b9996bae42 Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Mon, 19 Jun 2006 20:46:05 +0100 Subject: [ARM] 3594/1: Poodle: Add touchscreen support + other updates Patch from Richard Purdie Poodle Updates: * Update corgi_ssp to make the GPIO chip selects optional * Enable corgi_ssp for use by poodle * Add corgi touchscreen platform device for poodle * Export locomo platform device. * Set framebuffer device parent correctly Signed-off-by: Richard Purdie Signed-off-by: Russell King --- arch/arm/mach-pxa/Kconfig | 1 + arch/arm/mach-pxa/Makefile | 2 +- arch/arm/mach-pxa/corgi_ssp.c | 42 ++++++++++++++++-------- arch/arm/mach-pxa/poodle.c | 69 +++++++++++++++++++++++++++++++++++++-- include/asm-arm/arch-pxa/poodle.h | 2 ++ 5 files changed, 99 insertions(+), 17 deletions(-) diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index 0104fd142e7..ea5137f319c 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -61,6 +61,7 @@ config MACH_POODLE bool "Enable Sharp SL-5600 (Poodle) Support" depends PXA_SHARPSL_25x select SHARP_LOCOMO + select PXA_SSP config MACH_CORGI bool "Enable Sharp SL-C700 (Corgi) Support" diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index 4e8a983e2b8..1610690be41 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile @@ -15,7 +15,7 @@ obj-$(CONFIG_ARCH_PXA_IDP) += idp.o obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o corgi_ssp.o corgi_lcd.o sharpsl_pm.o corgi_pm.o obj-$(CONFIG_PXA_SHARP_Cxx00) += spitz.o corgi_ssp.o corgi_lcd.o sharpsl_pm.o spitz_pm.o obj-$(CONFIG_MACH_AKITA) += akita-ioexp.o -obj-$(CONFIG_MACH_POODLE) += poodle.o +obj-$(CONFIG_MACH_POODLE) += poodle.o corgi_ssp.o obj-$(CONFIG_MACH_TOSA) += tosa.o # Support for blinky lights diff --git a/arch/arm/mach-pxa/corgi_ssp.c b/arch/arm/mach-pxa/corgi_ssp.c index 8a25a1c8019..f9421318cb7 100644 --- a/arch/arm/mach-pxa/corgi_ssp.c +++ b/arch/arm/mach-pxa/corgi_ssp.c @@ -50,12 +50,14 @@ unsigned long corgi_ssp_ads7846_putget(ulong data) unsigned long ret,flag; spin_lock_irqsave(&corgi_ssp_lock, flag); - GPCR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); + if (ssp_machinfo->cs_ads7846 >= 0) + GPCR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); ssp_write_word(&corgi_ssp_dev,data); ret = ssp_read_word(&corgi_ssp_dev); - GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); + if (ssp_machinfo->cs_ads7846 >= 0) + GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); spin_unlock_irqrestore(&corgi_ssp_lock, flag); return ret; @@ -68,12 +70,14 @@ unsigned long corgi_ssp_ads7846_putget(ulong data) void corgi_ssp_ads7846_lock(void) { spin_lock(&corgi_ssp_lock); - GPCR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); + if (ssp_machinfo->cs_ads7846 >= 0) + GPCR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); } void corgi_ssp_ads7846_unlock(void) { - GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); + if (ssp_machinfo->cs_ads7846 >= 0) + GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); spin_unlock(&corgi_ssp_lock); } @@ -110,11 +114,13 @@ unsigned long corgi_ssp_dac_put(ulong data) ssp_config(&corgi_ssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), sscr1, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_lcdcon)); ssp_enable(&corgi_ssp_dev); - GPCR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon); + if (ssp_machinfo->cs_lcdcon >= 0) + GPCR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon); ssp_write_word(&corgi_ssp_dev,data); /* Read null data back from device to prevent SSP overflow */ ssp_read_word(&corgi_ssp_dev); - GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon); + if (ssp_machinfo->cs_lcdcon >= 0) + GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon); ssp_disable(&corgi_ssp_dev); ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_ads7846)); @@ -147,7 +153,8 @@ int corgi_ssp_max1111_get(ulong data) int voltage,voltage1,voltage2; spin_lock_irqsave(&corgi_ssp_lock, flag); - GPCR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111); + if (ssp_machinfo->cs_max1111 >= 0) + GPCR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111); ssp_disable(&corgi_ssp_dev); ssp_config(&corgi_ssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_max1111)); ssp_enable(&corgi_ssp_dev); @@ -169,7 +176,8 @@ int corgi_ssp_max1111_get(ulong data) ssp_disable(&corgi_ssp_dev); ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_ads7846)); ssp_enable(&corgi_ssp_dev); - GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111); + if (ssp_machinfo->cs_max1111 >= 0) + GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111); spin_unlock_irqrestore(&corgi_ssp_lock, flag); if (voltage1 & 0xc0 || voltage2 & 0x3f) @@ -196,9 +204,12 @@ static int __init corgi_ssp_probe(struct platform_device *dev) int ret; /* Chip Select - Disable All */ - pxa_gpio_mode(ssp_machinfo->cs_lcdcon | GPIO_OUT | GPIO_DFLT_HIGH); - pxa_gpio_mode(ssp_machinfo->cs_max1111 | GPIO_OUT | GPIO_DFLT_HIGH); - pxa_gpio_mode(ssp_machinfo->cs_ads7846 | GPIO_OUT | GPIO_DFLT_HIGH); + if (ssp_machinfo->cs_lcdcon >= 0) + pxa_gpio_mode(ssp_machinfo->cs_lcdcon | GPIO_OUT | GPIO_DFLT_HIGH); + if (ssp_machinfo->cs_max1111 >= 0) + pxa_gpio_mode(ssp_machinfo->cs_max1111 | GPIO_OUT | GPIO_DFLT_HIGH); + if (ssp_machinfo->cs_ads7846 >= 0) + pxa_gpio_mode(ssp_machinfo->cs_ads7846 | GPIO_OUT | GPIO_DFLT_HIGH); ret = ssp_init(&corgi_ssp_dev, ssp_machinfo->port, 0); @@ -229,9 +240,12 @@ static int corgi_ssp_suspend(struct platform_device *dev, pm_message_t state) static int corgi_ssp_resume(struct platform_device *dev) { - GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon); /* High - Disable LCD Control/Timing Gen */ - GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111); /* High - Disable MAX1111*/ - GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); /* High - Disable ADS7846*/ + if (ssp_machinfo->cs_lcdcon >= 0) + GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon); /* High - Disable LCD Control/Timing Gen */ + if (ssp_machinfo->cs_max1111 >= 0) + GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111); /* High - Disable MAX1111*/ + if (ssp_machinfo->cs_ads7846 >= 0) + GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); /* High - Disable ADS7846*/ ssp_restore_state(&corgi_ssp_dev,&corgi_ssp_state); ssp_enable(&corgi_ssp_dev); diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c index 234877a09df..9a9fa87cea9 100644 --- a/arch/arm/mach-pxa/poodle.c +++ b/arch/arm/mach-pxa/poodle.c @@ -37,12 +37,15 @@ #include #include #include +#include +#include #include #include #include #include "generic.h" +#include "sharpsl.h" static struct resource poodle_scoop_resources[] = { [0] = { @@ -120,13 +123,71 @@ static struct resource locomo_resources[] = { }, }; -static struct platform_device locomo_device = { +struct platform_device poodle_locomo_device = { .name = "locomo", .id = 0, .num_resources = ARRAY_SIZE(locomo_resources), .resource = locomo_resources, }; +EXPORT_SYMBOL(poodle_locomo_device); + +/* + * Poodle SSP Device + */ + +struct platform_device poodle_ssp_device = { + .name = "corgi-ssp", + .id = -1, +}; + +struct corgissp_machinfo poodle_ssp_machinfo = { + .port = 1, + .cs_lcdcon = -1, + .cs_ads7846 = -1, + .cs_max1111 = -1, + .clk_lcdcon = 2, + .clk_ads7846 = 36, + .clk_max1111 = 2, +}; + + +/* + * Poodle Touch Screen Device + */ +static struct resource poodlets_resources[] = { + [0] = { + .start = POODLE_IRQ_GPIO_TP_INT, + .end = POODLE_IRQ_GPIO_TP_INT, + .flags = IORESOURCE_IRQ, + }, +}; + +static unsigned long poodle_get_hsync_len(void) +{ + return 0; +} + +static void poodle_null_hsync(void) +{ +} + +static struct corgits_machinfo poodle_ts_machinfo = { + .get_hsync_len = poodle_get_hsync_len, + .put_hsync = poodle_null_hsync, + .wait_hsync = poodle_null_hsync, +}; + +static struct platform_device poodle_ts_device = { + .name = "corgi-ts", + .dev = { + .platform_data = &poodle_ts_machinfo, + }, + .id = -1, + .num_resources = ARRAY_SIZE(poodlets_resources), + .resource = poodlets_resources, +}; + /* * MMC/SD Device @@ -259,8 +320,10 @@ static struct pxafb_mach_info poodle_fb_info __initdata = { }; static struct platform_device *devices[] __initdata = { - &locomo_device, + &poodle_locomo_device, &poodle_scoop_device, + &poodle_ssp_device, + &poodle_ts_device, }; static void poodle_poweroff(void) @@ -319,6 +382,7 @@ static void __init poodle_init(void) GPSR1 = 0x00000000; GPSR2 = 0x00000000; + set_pxa_fb_parent(&poodle_locomo_device.dev); set_pxa_fb_info(&poodle_fb_info); pxa_gpio_mode(POODLE_GPIO_USB_PULLUP | GPIO_OUT); pxa_gpio_mode(POODLE_GPIO_IR_ON | GPIO_OUT); @@ -332,6 +396,7 @@ static void __init poodle_init(void) if (ret) { printk(KERN_WARNING "poodle: Unable to register LoCoMo device\n"); } + corgi_ssp_set_machinfo(&poodle_ssp_machinfo); } static void __init fixup_poodle(struct machine_desc *desc, diff --git a/include/asm-arm/arch-pxa/poodle.h b/include/asm-arm/arch-pxa/poodle.h index 6079e0aa1ab..4d6a4031576 100644 --- a/include/asm-arm/arch-pxa/poodle.h +++ b/include/asm-arm/arch-pxa/poodle.h @@ -70,4 +70,6 @@ #define POODLE_SCOOP_IO_DIR ( POODLE_SCOOP_VPEN | POODLE_SCOOP_HS_OUT ) #define POODLE_SCOOP_IO_OUT ( 0 ) +extern struct platform_device poodle_locomo_device; + #endif /* __ASM_ARCH_POODLE_H */ -- cgit v1.2.3 From e55dea58c5609aece6156a6cd2306b820a7794ef Mon Sep 17 00:00:00 2001 From: Prarit Bhargava Date: Tue, 4 Apr 2006 09:26:46 -0400 Subject: [PATCH] PCI Hotplug: Tollhouse HP: SGI hotplug driver changes SGI hotplug driver changes required to support Tollhouse system PCI hotplug, and implements the PRF_HOTPLUG_SUPPORT feature bit. Signed-off-by: Prarit Bhargava Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/sgi_hotplug.c | 42 +++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c index 8cb9abde736..cfee9db52c4 100644 --- a/drivers/pci/hotplug/sgi_hotplug.c +++ b/drivers/pci/hotplug/sgi_hotplug.c @@ -18,11 +18,13 @@ #include #include +#include #include #include #include #include #include +#include #include #include @@ -102,8 +104,7 @@ static struct hotplug_slot_attribute sn_slot_path_attr = __ATTR_RO(path); static int sn_pci_slot_valid(struct pci_bus *pci_bus, int device) { struct pcibus_info *pcibus_info; - int bricktype; - int bus_num; + u16 busnum, segment, ioboard_type; pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus); @@ -111,12 +112,14 @@ static int sn_pci_slot_valid(struct pci_bus *pci_bus, int device) if (!(pcibus_info->pbi_valid_devices & (1 << device))) return -EPERM; - bricktype = MODULE_GET_BTYPE(pcibus_info->pbi_moduleid); - bus_num = pcibus_info->pbi_buscommon.bs_persist_busnum & 0xf; + ioboard_type = sn_ioboard_to_pci_bus(pci_bus); + busnum = pcibus_info->pbi_buscommon.bs_persist_busnum; + segment = pci_domain_nr(pci_bus) & 0xf; /* Do not allow hotplug operations on base I/O cards */ - if ((bricktype == L1_BRICKTYPE_IX || bricktype == L1_BRICKTYPE_IA) && - (bus_num == 1 && device != 1)) + if ((ioboard_type == L1_BRICKTYPE_IX || + ioboard_type == L1_BRICKTYPE_IA) && + (segment == 1 && busnum == 0 && device != 1)) return -EPERM; return 1; @@ -125,23 +128,23 @@ static int sn_pci_slot_valid(struct pci_bus *pci_bus, int device) static int sn_pci_bus_valid(struct pci_bus *pci_bus) { struct pcibus_info *pcibus_info; - int asic_type; - int bricktype; - - pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus); + u32 asic_type; + u16 ioboard_type; /* Don't register slots hanging off the TIOCA bus */ + pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus); asic_type = pcibus_info->pbi_buscommon.bs_asic_type; if (asic_type == PCIIO_ASIC_TYPE_TIOCA) return -EPERM; /* Only register slots in I/O Bricks that support hotplug */ - bricktype = MODULE_GET_BTYPE(pcibus_info->pbi_moduleid); - switch (bricktype) { + ioboard_type = sn_ioboard_to_pci_bus(pci_bus); + switch (ioboard_type) { case L1_BRICKTYPE_IX: case L1_BRICKTYPE_PX: case L1_BRICKTYPE_IA: case L1_BRICKTYPE_PA: + case L1_BOARDTYPE_PCIX3SLOT: return 1; break; default: @@ -175,14 +178,11 @@ static int sn_hp_slot_private_alloc(struct hotplug_slot *bss_hotplug_slot, slot->pci_bus = pci_bus; sprintf(bss_hotplug_slot->name, "%04x:%02x:%02x", pci_domain_nr(pci_bus), - ((int)pcibus_info->pbi_buscommon.bs_persist_busnum) & 0xf, + ((u16)pcibus_info->pbi_buscommon.bs_persist_busnum), device + 1); - sprintf(slot->physical_path, "module_%c%c%c%c%.2d", - '0'+RACK_GET_CLASS(MODULE_GET_RACK(pcibus_info->pbi_moduleid)), - '0'+RACK_GET_GROUP(MODULE_GET_RACK(pcibus_info->pbi_moduleid)), - '0'+RACK_GET_NUM(MODULE_GET_RACK(pcibus_info->pbi_moduleid)), - MODULE_GET_BTCHAR(pcibus_info->pbi_moduleid), - MODULE_GET_BPOS(pcibus_info->pbi_moduleid)); + + sn_generate_path(pci_bus, slot->physical_path); + slot->hotplug_slot = bss_hotplug_slot; list_add(&slot->hp_list, &sn_hp_list); @@ -553,8 +553,8 @@ static int sn_pci_hotplug_init(void) int rc; int registered = 0; - if (sn_sal_rev() < SGI_HOTPLUG_PROM_REV) { - printk(KERN_ERR "%s: PROM version must be greater than 4.30\n", + if (!sn_prom_feature_available(PRF_HOTPLUG_SUPPORT)) { + printk(KERN_ERR "%s: PROM version does not support hotplug.\n", __FUNCTION__); return -EPERM; } -- cgit v1.2.3 From 92c9be95549632da09088320f202fa5c05b21ddf Mon Sep 17 00:00:00 2001 From: MUNEDA Takahiro Date: Wed, 22 Mar 2006 14:49:09 +0900 Subject: [PATCH] acpiphp: configure _PRT - V3 Current acpiphp does not free acpi_device structs when the PCI devices are removed. When the PCI device is added, acpi_bus_add() fails because acpi_device struct has already exists. So, _PRT method does not evaluate. This patch fixes this issue. Signed-off-by: MUNEDA Takahiro Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/acpiphp_glue.c | 71 ++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 38 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 053ee843863..fadd264b64c 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -797,36 +797,6 @@ static unsigned char acpiphp_max_busnr(struct pci_bus *bus) } - -/** - * get_func - get a pointer to acpiphp_func given a slot, device - * @slot: slot to search - * @dev: pci_dev struct to match. - * - * This function will increase the reference count of pci_dev, - * so callers should call pci_dev_put when complete. - * - */ -static struct acpiphp_func * -get_func(struct acpiphp_slot *slot, struct pci_dev *dev) -{ - struct acpiphp_func *func = NULL; - struct pci_bus *bus = slot->bridge->pci_bus; - struct pci_dev *pdev; - - list_for_each_entry(func, &slot->funcs, sibling) { - pdev = pci_get_slot(bus, PCI_DEVFN(slot->device, - func->function)); - if (pdev) { - if (pdev == dev) - break; - pci_dev_put(pdev); - } - } - return func; -} - - /** * acpiphp_bus_add - add a new bus to acpi subsystem * @func: acpiphp_func of the bridge @@ -872,6 +842,28 @@ acpiphp_bus_add_out: } +/** + * acpiphp_bus_trim - trim a bus from acpi subsystem + * @handle: handle to acpi namespace + * + */ +int acpiphp_bus_trim(acpi_handle handle) +{ + struct acpi_device *device; + int retval; + + retval = acpi_bus_get_device(handle, &device); + if (retval) { + dbg("acpi_device not found\n"); + return retval; + } + + retval = acpi_bus_trim(device, 1); + if (retval) + err("cannot remove from acpi list\n"); + + return retval; +} /** * enable_device - enable, configure a slot @@ -918,19 +910,17 @@ static int enable_device(struct acpiphp_slot *slot) if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) { max = pci_scan_bridge(bus, dev, max, pass); - if (pass && dev->subordinate) { + if (pass && dev->subordinate) pci_bus_size_bridges(dev->subordinate); - func = get_func(slot, dev); - if (func) { - acpiphp_bus_add(func); - /* side effect of get_func */ - pci_dev_put(dev); - } - } } } } + list_for_each (l, &slot->funcs) { + func = list_entry(l, struct acpiphp_func, sibling); + acpiphp_bus_add(func); + } + pci_bus_assign_resources(bus); acpiphp_sanitize_bus(bus); pci_enable_bridges(bus); @@ -967,6 +957,11 @@ static int disable_device(struct acpiphp_slot *slot) list_for_each (l, &slot->funcs) { func = list_entry(l, struct acpiphp_func, sibling); + + acpiphp_bus_trim(func->handle); + /* try to remove anyway. + * acpiphp_bus_add might have been failed */ + if (!func->pci_dev) continue; -- cgit v1.2.3 From 551bcb75b3d9f23348a524210ccfff26d865e425 Mon Sep 17 00:00:00 2001 From: MUNEDA Takahiro Date: Wed, 22 Mar 2006 14:49:20 +0900 Subject: [PATCH] acpiphp: hotplug slot hotplug o hotplug slots add When the hot-added PCI device is p2p bridge, acpiphp calls find_p2p_bridge() to add hotplug slots. o hotplug slots remove When the hot-removing PCI device is p2p bridge, acpiphp calls cleanup_p2p_bridge() to remove hotplug slots. o notify handler exchange When the p2p bridge is added, acpiphp changes the notify hanlder. If no bridge device is inserted into the hotpluggable PCI slot, acpiphp installs the notify handler for function. After the p2p bridge hot-add, acpiphp has to install the notify handler for bridge. Because, the role of the handlers are not same. The hot-remove case is ditto. Signed-off-by: MUNEDA Takahiro Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/acpiphp.h | 5 ++ drivers/pci/hotplug/acpiphp_glue.c | 126 ++++++++++++++++++++++++++++++++++--- 2 files changed, 122 insertions(+), 9 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index 467ac70a46f..17a93f890db 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -75,6 +75,10 @@ struct acpiphp_bridge { struct list_head list; acpi_handle handle; struct acpiphp_slot *slots; + + /* Ejectable PCI-to-PCI bridge (PCI bridge and PCI function) */ + struct acpiphp_func *func; + int type; int nr_slots; @@ -122,6 +126,7 @@ struct acpiphp_slot { */ struct acpiphp_func { struct acpiphp_slot *slot; /* parent */ + struct acpiphp_bridge *bridge; /* Ejectable PCI-to-PCI bridge */ struct list_head sibling; struct pci_dev *pci_dev; diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index fadd264b64c..631efce3a6c 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -319,6 +319,13 @@ static void init_bridge_misc(struct acpiphp_bridge *bridge) /* install notify handler */ if (bridge->type != BRIDGE_TYPE_HOST) { + if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) { + status = acpi_remove_notify_handler(bridge->func->handle, + ACPI_SYSTEM_NOTIFY, + handle_hotplug_event_func); + if (ACPI_FAILURE(status)) + err("failed to remove notify handler\n"); + } status = acpi_install_notify_handler(bridge->handle, ACPI_SYSTEM_NOTIFY, handle_hotplug_event_bridge, @@ -331,6 +338,66 @@ static void init_bridge_misc(struct acpiphp_bridge *bridge) } +/* find acpiphp_func from acpiphp_bridge */ +static struct acpiphp_func *acpiphp_bridge_handle_to_function(acpi_handle handle) +{ + struct list_head *node, *l; + struct acpiphp_bridge *bridge; + struct acpiphp_slot *slot; + struct acpiphp_func *func; + + list_for_each(node, &bridge_list) { + bridge = list_entry(node, struct acpiphp_bridge, list); + for (slot = bridge->slots; slot; slot = slot->next) { + list_for_each(l, &slot->funcs) { + func = list_entry(l, struct acpiphp_func, + sibling); + if (func->handle == handle) + return func; + } + } + } + + return NULL; +} + + +static inline void config_p2p_bridge_flags(struct acpiphp_bridge *bridge) +{ + acpi_handle dummy_handle; + + if (ACPI_SUCCESS(acpi_get_handle(bridge->handle, + "_STA", &dummy_handle))) + bridge->flags |= BRIDGE_HAS_STA; + + if (ACPI_SUCCESS(acpi_get_handle(bridge->handle, + "_EJ0", &dummy_handle))) + bridge->flags |= BRIDGE_HAS_EJ0; + + if (ACPI_SUCCESS(acpi_get_handle(bridge->handle, + "_PS0", &dummy_handle))) + bridge->flags |= BRIDGE_HAS_PS0; + + if (ACPI_SUCCESS(acpi_get_handle(bridge->handle, + "_PS3", &dummy_handle))) + bridge->flags |= BRIDGE_HAS_PS3; + + /* is this ejectable p2p bridge? */ + if (bridge->flags & BRIDGE_HAS_EJ0) { + struct acpiphp_func *func; + + dbg("found ejectable p2p bridge\n"); + + /* make link between PCI bridge and PCI function */ + func = acpiphp_bridge_handle_to_function(bridge->handle); + if (!func) + return; + bridge->func = func; + func->bridge = bridge; + } +} + + /* allocate and initialize host bridge data structure */ static void add_host_bridge(acpi_handle *handle, struct pci_bus *pci_bus) { @@ -364,6 +431,7 @@ static void add_p2p_bridge(acpi_handle *handle, struct pci_dev *pci_dev) bridge->type = BRIDGE_TYPE_P2P; bridge->handle = handle; + config_p2p_bridge_flags(bridge); bridge->pci_dev = pci_dev_get(pci_dev); bridge->pci_bus = pci_dev->subordinate; @@ -423,7 +491,7 @@ find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv) status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, find_p2p_bridge, dev->subordinate, NULL); if (ACPI_FAILURE(status)) - warn("find_p2p_bridge faied (error code = 0x%x)\n", status); + warn("find_p2p_bridge failed (error code = 0x%x)\n", status); out: pci_dev_put(dev); @@ -486,7 +554,7 @@ static int add_bridge(acpi_handle handle) find_p2p_bridge, pci_bus, NULL); if (ACPI_FAILURE(status)) - warn("find_p2p_bridge faied (error code = 0x%x)\n",status); + warn("find_p2p_bridge failed (error code = 0x%x)\n", status); return 0; } @@ -516,6 +584,16 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) if (ACPI_FAILURE(status)) err("failed to remove notify handler\n"); + if ((bridge->type != BRIDGE_TYPE_HOST) && + ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func)) { + status = acpi_install_notify_handler(bridge->func->handle, + ACPI_SYSTEM_NOTIFY, + handle_hotplug_event_func, + bridge->func); + if (ACPI_FAILURE(status)) + err("failed to install interrupt notify handler\n"); + } + slot = bridge->slots; while (slot) { struct acpiphp_slot *next = slot->next; @@ -549,6 +627,11 @@ cleanup_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv) { struct acpiphp_bridge *bridge; + /* cleanup p2p bridges under this P2P bridge + in a depth-first manner */ + acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, + cleanup_p2p_bridge, NULL, NULL); + if (!(bridge = acpiphp_handle_to_bridge(handle))) return AE_OK; cleanup_bridge(bridge); @@ -559,15 +642,14 @@ static void remove_bridge(acpi_handle handle) { struct acpiphp_bridge *bridge; + /* cleanup p2p bridges under this host bridge + in a depth-first manner */ + acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, + (u32)1, cleanup_p2p_bridge, NULL, NULL); + bridge = acpiphp_handle_to_bridge(handle); - if (bridge) { + if (bridge) cleanup_bridge(bridge); - } else { - /* clean-up p2p bridges under this host bridge */ - acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, - ACPI_UINT32_MAX, cleanup_p2p_bridge, - NULL, NULL); - } } static struct pci_dev * get_apic_pci_info(acpi_handle handle) @@ -881,6 +963,7 @@ static int enable_device(struct acpiphp_slot *slot) struct acpiphp_func *func; int retval = 0; int num, max, pass; + acpi_status status; if (slot->flags & SLOT_ENABLED) goto err_exit; @@ -933,6 +1016,17 @@ static int enable_device(struct acpiphp_slot *slot) func = list_entry(l, struct acpiphp_func, sibling); func->pci_dev = pci_get_slot(bus, PCI_DEVFN(slot->device, func->function)); + if (!func->pci_dev) + continue; + + if (func->pci_dev->hdr_type != PCI_HEADER_TYPE_BRIDGE && + func->pci_dev->hdr_type != PCI_HEADER_TYPE_CARDBUS) + continue; + + status = find_p2p_bridge(func->handle, (u32)1, bus, NULL); + if (ACPI_FAILURE(status)) + warn("find_p2p_bridge failed (error code = 0x%x)\n", + status); } slot->flags |= SLOT_ENABLED; @@ -958,6 +1052,13 @@ static int disable_device(struct acpiphp_slot *slot) list_for_each (l, &slot->funcs) { func = list_entry(l, struct acpiphp_func, sibling); + if (func->bridge) { + /* cleanup p2p bridges under this P2P bridge */ + cleanup_p2p_bridge(func->bridge->handle, + (u32)1, NULL, NULL); + func->bridge = NULL; + } + acpiphp_bus_trim(func->handle); /* try to remove anyway. * acpiphp_bus_add might have been failed */ @@ -1292,6 +1393,13 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont case ACPI_NOTIFY_EJECT_REQUEST: /* request device eject */ dbg("%s: Device eject notify on %s\n", __FUNCTION__, objname); + if ((bridge->type != BRIDGE_TYPE_HOST) && + (bridge->flags & BRIDGE_HAS_EJ0)) { + struct acpiphp_slot *slot; + slot = bridge->func->slot; + if (!acpiphp_disable_slot(slot)) + acpiphp_eject_slot(slot); + } break; case ACPI_NOTIFY_FREQUENCY_MISMATCH: -- cgit v1.2.3 From c14424736e76f3d8477a41de531e6b5dcce3d5b0 Mon Sep 17 00:00:00 2001 From: MUNEDA Takahiro Date: Wed, 22 Mar 2006 14:49:27 +0900 Subject: [PATCH] acpiphp: host and p2p hotplug I encountered the problem that when there are some hotplug slots are under the host bridge, the hotplug slots under the p2p bridge are not treated as hotpluggable. This patch fixes this BUG. Signed-off-by: MUNEDA Takahiro Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/acpiphp_glue.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 631efce3a6c..bbe27c16bc3 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -546,7 +546,6 @@ static int add_bridge(acpi_handle handle) if (detect_ejectable_slots(handle) > 0) { dbg("found PCI host-bus bridge with hot-pluggable slots\n"); add_host_bridge(handle, pci_bus); - return 0; } /* search P2P bridges under this host bridge */ -- cgit v1.2.3 From cde0e5d722c77d1194f40de54a99c90afe365480 Mon Sep 17 00:00:00 2001 From: MUNEDA Takahiro Date: Wed, 22 Mar 2006 14:49:33 +0900 Subject: [PATCH] acpiphp: turn off slot power at error case When acpiphp_enable_slot() is failed, acpiphp does not change the slot->flags. Therefore, when user tries to read power status, acpiphp_get_power_status() returns the enable status whether the slot is not really enabled. This patch fixes this BUG. Signed-off-by: MUNEDA Takahiro Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/acpiphp_glue.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index bbe27c16bc3..610a530232f 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -1592,9 +1592,15 @@ int acpiphp_enable_slot(struct acpiphp_slot *slot) if (retval) goto err_exit; - if (get_slot_status(slot) == ACPI_STA_ALL) + if (get_slot_status(slot) == ACPI_STA_ALL) { /* configure all functions */ retval = enable_device(slot); + if (retval) + power_off_slot(slot); + } else { + dbg("%s: Slot status is not ACPI_STA_ALL\n", __FUNCTION__); + power_off_slot(slot); + } err_exit: mutex_unlock(&slot->crit_sect); -- cgit v1.2.3 From 81b26bcacd5df0f65344fb430b1bf7fe9cfbfe2a Mon Sep 17 00:00:00 2001 From: Kristen Accardi Date: Tue, 18 Apr 2006 14:36:43 -0700 Subject: [PATCH] PCI Hotplug: don't use acpi_os_free acpi_os_free should not be used by drivers outside of acpi/*/*.c. Replace with kfree(). Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/acpi_pcihp.c | 16 ++++++++-------- drivers/pci/hotplug/acpiphp_glue.c | 2 +- drivers/pci/hotplug/pciehp_hpc.c | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c index 39af9c325f3..64cb30d7fc9 100644 --- a/drivers/pci/hotplug/acpi_pcihp.c +++ b/drivers/pci/hotplug/acpi_pcihp.c @@ -58,7 +58,7 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) if (!ret_buf.pointer) { printk(KERN_ERR "%s:%s alloc for _HPP fail\n", __FUNCTION__, (char *)string.pointer); - acpi_os_free(string.pointer); + kfree(string.pointer); return AE_NO_MEMORY; } status = acpi_evaluate_object(handle, METHOD_NAME__HPP, @@ -69,7 +69,7 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) if (ACPI_FAILURE(status)) { pr_debug("%s:%s _HPP fail=0x%x\n", __FUNCTION__, (char *)string.pointer, status); - acpi_os_free(string.pointer); + kfree(string.pointer); return status; } } @@ -109,8 +109,8 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) pr_debug(" _HPP: enable PERR =0x%x\n", hpp->enable_perr); free_and_return: - acpi_os_free(string.pointer); - acpi_os_free(ret_buf.pointer); + kfree(string.pointer); + kfree(ret_buf.pointer); return status; } @@ -136,7 +136,7 @@ acpi_status acpi_run_oshp(acpi_handle handle) pr_debug("%s:%s OSHP passes\n", __FUNCTION__, (char *)string.pointer); - acpi_os_free(string.pointer); + kfree(string.pointer); return status; } EXPORT_SYMBOL_GPL(acpi_run_oshp); @@ -192,19 +192,19 @@ int acpi_root_bridge(acpi_handle handle) if ((info->valid & ACPI_VALID_HID) && !strcmp(PCI_ROOT_HID_STRING, info->hardware_id.value)) { - acpi_os_free(buffer.pointer); + kfree(buffer.pointer); return 1; } if (info->valid & ACPI_VALID_CID) { for (i=0; i < info->compatibility_id.count; i++) { if (!strcmp(PCI_ROOT_HID_STRING, info->compatibility_id.id[i].value)) { - acpi_os_free(buffer.pointer); + kfree(buffer.pointer); return 1; } } } - acpi_os_free(buffer.pointer); + kfree(buffer.pointer); } return 0; } diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 610a530232f..2a83e6bdab6 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -715,7 +715,7 @@ static int get_gsi_base(acpi_handle handle, u32 *gsi_base) break; } out: - acpi_os_free(buffer.pointer); + kfree(buffer.pointer); return result; } diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 6c14d9e46b2..7f459dfeadd 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -1288,7 +1288,7 @@ int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev) if (ACPI_SUCCESS(status)) { dbg("Gained control for hotplug HW for pci %s (%s)\n", pci_name(dev), (char *)string.pointer); - acpi_os_free(string.pointer); + kfree(string.pointer); return 0; } if (acpi_root_bridge(handle)) @@ -1302,7 +1302,7 @@ int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev) err("Cannot get control of hotplug hardware for pci %s\n", pci_name(dev)); - acpi_os_free(string.pointer); + kfree(string.pointer); return -1; } #endif -- cgit v1.2.3 From 2433ee2654f0ac86f7886e5a8d01bee7f3c7c6db Mon Sep 17 00:00:00 2001 From: Kristen Accardi Date: Mon, 24 Apr 2006 15:50:59 -0700 Subject: [PATCH] pciehp: dont call pci_enable_dev Don't call pci_enable_device from pciehp because the pcie port service driver already does this. Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/pciehp_hpc.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 7f459dfeadd..081dfef4fe6 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -1404,9 +1404,6 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, pdev->subsystem_vendor, pdev->subsystem_device); - if (pci_enable_device(pdev)) - goto abort_free_ctlr; - mutex_init(&ctrl->crit_sect); /* setup wait queue */ init_waitqueue_head(&ctrl->queue); -- cgit v1.2.3 From 7430e34c70106a9576fc61d77604d164b187a1b7 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Tue, 2 May 2006 10:54:50 +0900 Subject: [PATCH] acpi_pcihp: Fix programming _HPP values This patch fixes the problem that hotplug parameters are not programed when PCI cards are hot-added by ACPIPHP, SHPCHP and PCIEHP driver. The pci_dev structure being hot-added is not bound to ACPI handle, so we need to trace PCI bus tree to find ACPI handle. Signed-off-by: Kenji Kaneshige Cc: Kristen Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/acpi_pcihp.c | 34 ++++++++++++++++++++++++---------- drivers/pci/hotplug/acpiphp_glue.c | 3 ++- drivers/pci/hotplug/pci_hotplug.h | 2 +- drivers/pci/hotplug/pciehp.h | 2 +- drivers/pci/hotplug/shpchp.h | 2 +- 5 files changed, 29 insertions(+), 14 deletions(-) diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c index 64cb30d7fc9..9395fec7342 100644 --- a/drivers/pci/hotplug/acpi_pcihp.c +++ b/drivers/pci/hotplug/acpi_pcihp.c @@ -145,14 +145,27 @@ EXPORT_SYMBOL_GPL(acpi_run_oshp); /* acpi_get_hp_params_from_firmware * - * @dev - the pci_dev of the newly added device + * @bus - the pci_bus of the bus on which the device is newly added * @hpp - allocated by the caller */ -acpi_status acpi_get_hp_params_from_firmware(struct pci_dev *dev, +acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus, struct hotplug_params *hpp) { acpi_status status = AE_NOT_FOUND; - struct pci_dev *pdev = dev; + acpi_handle handle, phandle; + struct pci_bus *pbus = bus; + struct pci_dev *pdev; + + do { + pdev = pbus->self; + if (!pdev) { + handle = acpi_get_pci_rootbridge_handle( + pci_domain_nr(pbus), pbus->number); + break; + } + handle = DEVICE_ACPI_HANDLE(&(pdev->dev)); + pbus = pbus->parent; + } while (!handle); /* * _HPP settings apply to all child buses, until another _HPP is @@ -160,15 +173,16 @@ acpi_status acpi_get_hp_params_from_firmware(struct pci_dev *dev, * look for it in the parent device scope since that would apply to * this pci dev. If we don't find any _HPP, use hardcoded defaults */ - while (pdev && (ACPI_FAILURE(status))) { - acpi_handle handle = DEVICE_ACPI_HANDLE(&(pdev->dev)); - if (!handle) - break; + while (handle) { status = acpi_run_hpp(handle, hpp); - if (!(pdev->bus->parent)) + if (ACPI_SUCCESS(status)) + break; + if (acpi_root_bridge(handle)) + break; + status = acpi_get_parent(handle, &phandle); + if (ACPI_FAILURE(status)) break; - /* Check if a parent object supports _HPP */ - pdev = pdev->bus->parent->self; + handle = phandle; } return status; } diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 2a83e6bdab6..4b0988e9380 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -286,7 +286,7 @@ static void decode_hpp(struct acpiphp_bridge *bridge) { acpi_status status; - status = acpi_get_hp_params_from_firmware(bridge->pci_dev, &bridge->hpp); + status = acpi_get_hp_params_from_firmware(bridge->pci_bus, &bridge->hpp); if (ACPI_FAILURE(status)) { /* use default numbers */ bridge->hpp.cache_line_size = 0x10; @@ -1250,6 +1250,7 @@ static void acpiphp_set_hpp_values(acpi_handle handle, struct pci_bus *bus) memset(&bridge, 0, sizeof(bridge)); bridge.handle = handle; + bridge.pci_bus = bus; bridge.pci_dev = bus->self; decode_hpp(&bridge); list_for_each_entry(dev, &bus->devices, bus_list) diff --git a/drivers/pci/hotplug/pci_hotplug.h b/drivers/pci/hotplug/pci_hotplug.h index eb0d01d4723..6913ace70e9 100644 --- a/drivers/pci/hotplug/pci_hotplug.h +++ b/drivers/pci/hotplug/pci_hotplug.h @@ -188,7 +188,7 @@ struct hotplug_params { #include #include extern acpi_status acpi_run_oshp(acpi_handle handle); -extern acpi_status acpi_get_hp_params_from_firmware(struct pci_dev *dev, +extern acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus, struct hotplug_params *hpp); int acpi_root_bridge(acpi_handle handle); #endif diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 92c1f0f1e1a..ce89f581586 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -284,7 +284,7 @@ struct hpc_ops { static inline int pciehp_get_hp_params_from_firmware(struct pci_dev *dev, struct hotplug_params *hpp) { - if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev, hpp))) + if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev->bus, hpp))) return -ENODEV; return 0; } diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index 5c70f43908c..b70fddbce93 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -196,7 +196,7 @@ extern void queue_pushbutton_work(void *data); static inline int get_hp_params_from_firmware(struct pci_dev *dev, struct hotplug_params *hpp) { - if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev, hpp))) + if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev->bus, hpp))) return -ENODEV; return 0; } -- cgit v1.2.3 From aad20cabaa3d6dfa1e0ebc8fb0537a96d3518b8f Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Wed, 10 May 2006 22:20:34 +0900 Subject: [PATCH] acpi_pcihp: Remove improper error message about OSHP This patch converts the improper error message about OSHP evaluation to debug message which is displayed only when pci_hotplug.ko is loaded with debugging mode enabled. To do this, this patch adds a new module parameter "debug_acpi" to pci_hotplug.ko for enabling/disabling debug messages in acpi_pcihp.c. Signed-off-by: Kenji Kaneshige Cc: Kristen Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/acpi_pcihp.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c index 9395fec7342..afac5c37325 100644 --- a/drivers/pci/hotplug/acpi_pcihp.c +++ b/drivers/pci/hotplug/acpi_pcihp.c @@ -25,6 +25,7 @@ */ #include +#include #include #include #include @@ -33,10 +34,19 @@ #include #include "pci_hotplug.h" +#define MY_NAME "acpi_pcihp" + +#define dbg(fmt, arg...) do { if (debug_acpi) printk(KERN_DEBUG "%s: %s: " fmt , MY_NAME , __FUNCTION__ , ## arg); } while (0) +#define err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg) +#define info(format, arg...) printk(KERN_INFO "%s: " format , MY_NAME , ## arg) +#define warn(format, arg...) printk(KERN_WARNING "%s: " format , MY_NAME , ## arg) + #define METHOD_NAME__SUN "_SUN" #define METHOD_NAME__HPP "_HPP" #define METHOD_NAME_OSHP "OSHP" +static int debug_acpi; + static acpi_status acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) @@ -130,8 +140,12 @@ acpi_status acpi_run_oshp(acpi_handle handle) /* run OSHP */ status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL); if (ACPI_FAILURE(status)) - printk(KERN_ERR "%s:%s OSHP fails=0x%x\n", __FUNCTION__, - (char *)string.pointer, status); + if (status != AE_NOT_FOUND) + printk(KERN_ERR "%s:%s OSHP fails=0x%x\n", + __FUNCTION__, (char *)string.pointer, status); + else + dbg("%s:%s OSHP not found\n", + __FUNCTION__, (char *)string.pointer); else pr_debug("%s:%s OSHP passes\n", __FUNCTION__, (char *)string.pointer); @@ -223,3 +237,6 @@ int acpi_root_bridge(acpi_handle handle) return 0; } EXPORT_SYMBOL_GPL(acpi_root_bridge); + +module_param(debug_acpi, bool, 0644); +MODULE_PARM_DESC(debug_acpi, "Debugging mode for ACPI enabled or not"); -- cgit v1.2.3 From e22b73501608901bab7ee9b1f8cb67f15e8efb7a Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Tue, 2 May 2006 10:57:14 +0900 Subject: [PATCH] acpi_pcihp: Add support for _HPX This patch adds support for _HPX (Hot Plug Parameter Extensions) defined in ACPI3.0a spec. Signed-off-by: Kenji Kaneshige Cc: Kristen Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/acpi_pcihp.c | 188 +++++++++++++++++++++++++++++++++++-- drivers/pci/hotplug/acpiphp_glue.c | 31 +++--- drivers/pci/hotplug/pci_hotplug.h | 48 +++++++++- drivers/pci/hotplug/shpchp_pci.c | 31 +++--- 4 files changed, 262 insertions(+), 36 deletions(-) diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c index afac5c37325..51cb9f817c2 100644 --- a/drivers/pci/hotplug/acpi_pcihp.c +++ b/drivers/pci/hotplug/acpi_pcihp.c @@ -47,6 +47,171 @@ static int debug_acpi; +static acpi_status +decode_type0_hpx_record(union acpi_object *record, struct hotplug_params *hpx) +{ + int i; + union acpi_object *fields = record->package.elements; + u32 revision = fields[1].integer.value; + + switch (revision) { + case 1: + if (record->package.count != 6) + return AE_ERROR; + for (i = 2; i < 6; i++) + if (fields[i].type != ACPI_TYPE_INTEGER) + return AE_ERROR; + hpx->t0 = &hpx->type0_data; + hpx->t0->revision = revision; + hpx->t0->cache_line_size = fields[2].integer.value; + hpx->t0->latency_timer = fields[3].integer.value; + hpx->t0->enable_serr = fields[4].integer.value; + hpx->t0->enable_perr = fields[5].integer.value; + break; + default: + printk(KERN_WARNING + "%s: Type 0 Revision %d record not supported\n", + __FUNCTION__, revision); + return AE_ERROR; + } + return AE_OK; +} + +static acpi_status +decode_type1_hpx_record(union acpi_object *record, struct hotplug_params *hpx) +{ + int i; + union acpi_object *fields = record->package.elements; + u32 revision = fields[1].integer.value; + + switch (revision) { + case 1: + if (record->package.count != 5) + return AE_ERROR; + for (i = 2; i < 5; i++) + if (fields[i].type != ACPI_TYPE_INTEGER) + return AE_ERROR; + hpx->t1 = &hpx->type1_data; + hpx->t1->revision = revision; + hpx->t1->max_mem_read = fields[2].integer.value; + hpx->t1->avg_max_split = fields[3].integer.value; + hpx->t1->tot_max_split = fields[4].integer.value; + break; + default: + printk(KERN_WARNING + "%s: Type 1 Revision %d record not supported\n", + __FUNCTION__, revision); + return AE_ERROR; + } + return AE_OK; +} + +static acpi_status +decode_type2_hpx_record(union acpi_object *record, struct hotplug_params *hpx) +{ + int i; + union acpi_object *fields = record->package.elements; + u32 revision = fields[1].integer.value; + + switch (revision) { + case 1: + if (record->package.count != 18) + return AE_ERROR; + for (i = 2; i < 18; i++) + if (fields[i].type != ACPI_TYPE_INTEGER) + return AE_ERROR; + hpx->t2 = &hpx->type2_data; + hpx->t2->revision = revision; + hpx->t2->unc_err_mask_and = fields[2].integer.value; + hpx->t2->unc_err_mask_or = fields[3].integer.value; + hpx->t2->unc_err_sever_and = fields[4].integer.value; + hpx->t2->unc_err_sever_or = fields[5].integer.value; + hpx->t2->cor_err_mask_and = fields[6].integer.value; + hpx->t2->cor_err_mask_or = fields[7].integer.value; + hpx->t2->adv_err_cap_and = fields[8].integer.value; + hpx->t2->adv_err_cap_or = fields[9].integer.value; + hpx->t2->pci_exp_devctl_and = fields[10].integer.value; + hpx->t2->pci_exp_devctl_or = fields[11].integer.value; + hpx->t2->pci_exp_lnkctl_and = fields[12].integer.value; + hpx->t2->pci_exp_lnkctl_or = fields[13].integer.value; + hpx->t2->sec_unc_err_sever_and = fields[14].integer.value; + hpx->t2->sec_unc_err_sever_or = fields[15].integer.value; + hpx->t2->sec_unc_err_mask_and = fields[16].integer.value; + hpx->t2->sec_unc_err_mask_or = fields[17].integer.value; + break; + default: + printk(KERN_WARNING + "%s: Type 2 Revision %d record not supported\n", + __FUNCTION__, revision); + return AE_ERROR; + } + return AE_OK; +} + +static acpi_status +acpi_run_hpx(acpi_handle handle, struct hotplug_params *hpx) +{ + acpi_status status; + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + union acpi_object *package, *record, *fields; + u32 type; + int i; + + /* Clear the return buffer with zeros */ + memset(hpx, 0, sizeof(struct hotplug_params)); + + status = acpi_evaluate_object(handle, "_HPX", NULL, &buffer); + if (ACPI_FAILURE(status)) + return status; + + package = (union acpi_object *)buffer.pointer; + if (package->type != ACPI_TYPE_PACKAGE) { + status = AE_ERROR; + goto exit; + } + + for (i = 0; i < package->package.count; i++) { + record = &package->package.elements[i]; + if (record->type != ACPI_TYPE_PACKAGE) { + status = AE_ERROR; + goto exit; + } + + fields = record->package.elements; + if (fields[0].type != ACPI_TYPE_INTEGER || + fields[1].type != ACPI_TYPE_INTEGER) { + status = AE_ERROR; + goto exit; + } + + type = fields[0].integer.value; + switch (type) { + case 0: + status = decode_type0_hpx_record(record, hpx); + if (ACPI_FAILURE(status)) + goto exit; + break; + case 1: + status = decode_type1_hpx_record(record, hpx); + if (ACPI_FAILURE(status)) + goto exit; + break; + case 2: + status = decode_type2_hpx_record(record, hpx); + if (ACPI_FAILURE(status)) + goto exit; + break; + default: + printk(KERN_ERR "%s: Type %d record not supported\n", + __FUNCTION__, type); + status = AE_ERROR; + goto exit; + } + } + exit: + kfree(buffer.pointer); + return status; +} static acpi_status acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) @@ -60,6 +225,9 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); + /* Clear the return buffer with zeros */ + memset(hpp, 0, sizeof(struct hotplug_params)); + /* get _hpp */ status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf); switch (status) { @@ -108,15 +276,16 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) } } - hpp->cache_line_size = nui[0]; - hpp->latency_timer = nui[1]; - hpp->enable_serr = nui[2]; - hpp->enable_perr = nui[3]; + hpp->t0 = &hpp->type0_data; + hpp->t0->cache_line_size = nui[0]; + hpp->t0->latency_timer = nui[1]; + hpp->t0->enable_serr = nui[2]; + hpp->t0->enable_perr = nui[3]; - pr_debug(" _HPP: cache_line_size=0x%x\n", hpp->cache_line_size); - pr_debug(" _HPP: latency timer =0x%x\n", hpp->latency_timer); - pr_debug(" _HPP: enable SERR =0x%x\n", hpp->enable_serr); - pr_debug(" _HPP: enable PERR =0x%x\n", hpp->enable_perr); + pr_debug(" _HPP: cache_line_size=0x%x\n", hpp->t0->cache_line_size); + pr_debug(" _HPP: latency timer =0x%x\n", hpp->t0->latency_timer); + pr_debug(" _HPP: enable SERR =0x%x\n", hpp->t0->enable_serr); + pr_debug(" _HPP: enable PERR =0x%x\n", hpp->t0->enable_perr); free_and_return: kfree(string.pointer); @@ -188,6 +357,9 @@ acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus, * this pci dev. If we don't find any _HPP, use hardcoded defaults */ while (handle) { + status = acpi_run_hpx(handle, hpp); + if (ACPI_SUCCESS(status)) + break; status = acpi_run_hpp(handle, hpp); if (ACPI_SUCCESS(status)) break; diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 4b0988e9380..d370f999782 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -287,12 +287,18 @@ static void decode_hpp(struct acpiphp_bridge *bridge) acpi_status status; status = acpi_get_hp_params_from_firmware(bridge->pci_bus, &bridge->hpp); - if (ACPI_FAILURE(status)) { + if (ACPI_FAILURE(status) || + !bridge->hpp.t0 || (bridge->hpp.t0->revision > 1)) { /* use default numbers */ - bridge->hpp.cache_line_size = 0x10; - bridge->hpp.latency_timer = 0x40; - bridge->hpp.enable_serr = 0; - bridge->hpp.enable_perr = 0; + printk(KERN_WARNING + "%s: Could not get hotplug parameters. Use defaults\n", + __FUNCTION__); + bridge->hpp.t0 = &bridge->hpp.type0_data; + bridge->hpp.t0->revision = 0; + bridge->hpp.t0->cache_line_size = 0x10; + bridge->hpp.t0->latency_timer = 0x40; + bridge->hpp.t0->enable_serr = 0; + bridge->hpp.t0->enable_perr = 0; } } @@ -1206,16 +1212,17 @@ static void program_hpp(struct pci_dev *dev, struct acpiphp_bridge *bridge) (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE && (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI))) return; + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, - bridge->hpp.cache_line_size); + bridge->hpp.t0->cache_line_size); pci_write_config_byte(dev, PCI_LATENCY_TIMER, - bridge->hpp.latency_timer); + bridge->hpp.t0->latency_timer); pci_read_config_word(dev, PCI_COMMAND, &pci_cmd); - if (bridge->hpp.enable_serr) + if (bridge->hpp.t0->enable_serr) pci_cmd |= PCI_COMMAND_SERR; else pci_cmd &= ~PCI_COMMAND_SERR; - if (bridge->hpp.enable_perr) + if (bridge->hpp.t0->enable_perr) pci_cmd |= PCI_COMMAND_PARITY; else pci_cmd &= ~PCI_COMMAND_PARITY; @@ -1224,13 +1231,13 @@ static void program_hpp(struct pci_dev *dev, struct acpiphp_bridge *bridge) /* Program bridge control value and child devices */ if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, - bridge->hpp.latency_timer); + bridge->hpp.t0->latency_timer); pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl); - if (bridge->hpp.enable_serr) + if (bridge->hpp.t0->enable_serr) pci_bctl |= PCI_BRIDGE_CTL_SERR; else pci_bctl &= ~PCI_BRIDGE_CTL_SERR; - if (bridge->hpp.enable_perr) + if (bridge->hpp.t0->enable_perr) pci_bctl |= PCI_BRIDGE_CTL_PARITY; else pci_bctl &= ~PCI_BRIDGE_CTL_PARITY; diff --git a/drivers/pci/hotplug/pci_hotplug.h b/drivers/pci/hotplug/pci_hotplug.h index 6913ace70e9..e929b7c1142 100644 --- a/drivers/pci/hotplug/pci_hotplug.h +++ b/drivers/pci/hotplug/pci_hotplug.h @@ -176,11 +176,51 @@ extern int pci_hp_change_slot_info (struct hotplug_slot *slot, struct hotplug_slot_info *info); extern struct subsystem pci_hotplug_slots_subsys; +/* PCI Setting Record (Type 0) */ +struct hpp_type0 { + u32 revision; + u8 cache_line_size; + u8 latency_timer; + u8 enable_serr; + u8 enable_perr; +}; + +/* PCI-X Setting Record (Type 1) */ +struct hpp_type1 { + u32 revision; + u8 max_mem_read; + u8 avg_max_split; + u16 tot_max_split; +}; + +/* PCI Express Setting Record (Type 2) */ +struct hpp_type2 { + u32 revision; + u32 unc_err_mask_and; + u32 unc_err_mask_or; + u32 unc_err_sever_and; + u32 unc_err_sever_or; + u32 cor_err_mask_and; + u32 cor_err_mask_or; + u32 adv_err_cap_and; + u32 adv_err_cap_or; + u16 pci_exp_devctl_and; + u16 pci_exp_devctl_or; + u16 pci_exp_lnkctl_and; + u16 pci_exp_lnkctl_or; + u32 sec_unc_err_sever_and; + u32 sec_unc_err_sever_or; + u32 sec_unc_err_mask_and; + u32 sec_unc_err_mask_or; +}; + struct hotplug_params { - u8 cache_line_size; - u8 latency_timer; - u8 enable_serr; - u8 enable_perr; + struct hpp_type0 *t0; /* Type0: NULL if not available */ + struct hpp_type1 *t1; /* Type1: NULL if not available */ + struct hpp_type2 *t2; /* Type2: NULL if not available */ + struct hpp_type0 type0_data; + struct hpp_type1 type1_data; + struct hpp_type2 type2_data; }; #ifdef CONFIG_ACPI diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c index 257adc23399..0a6b25ef194 100644 --- a/drivers/pci/hotplug/shpchp_pci.c +++ b/drivers/pci/hotplug/shpchp_pci.c @@ -47,21 +47,28 @@ static void program_fw_provided_values(struct pci_dev *dev) return; /* use default values if we can't get them from firmware */ - if (get_hp_params_from_firmware(dev, &hpp)) { - hpp.cache_line_size = 8; - hpp.latency_timer = 0x40; - hpp.enable_serr = 0; - hpp.enable_perr = 0; + if (get_hp_params_from_firmware(dev, &hpp) || + !hpp.t0 || (hpp.t0->revision > 1)) { + printk(KERN_WARNING + "%s: Could not get hotplug parameters. Use defaults\n", + __FUNCTION__); + hpp.t0 = &hpp.type0_data; + hpp.t0->revision = 0; + hpp.t0->cache_line_size = 8; + hpp.t0->latency_timer = 0x40; + hpp.t0->enable_serr = 0; + hpp.t0->enable_perr = 0; } - pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, hpp.cache_line_size); - pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp.latency_timer); + pci_write_config_byte(dev, + PCI_CACHE_LINE_SIZE, hpp.t0->cache_line_size); + pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp.t0->latency_timer); pci_read_config_word(dev, PCI_COMMAND, &pci_cmd); - if (hpp.enable_serr) + if (hpp.t0->enable_serr) pci_cmd |= PCI_COMMAND_SERR; else pci_cmd &= ~PCI_COMMAND_SERR; - if (hpp.enable_perr) + if (hpp.t0->enable_perr) pci_cmd |= PCI_COMMAND_PARITY; else pci_cmd &= ~PCI_COMMAND_PARITY; @@ -70,13 +77,13 @@ static void program_fw_provided_values(struct pci_dev *dev) /* Program bridge control value and child devices */ if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, - hpp.latency_timer); + hpp.t0->latency_timer); pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl); - if (hpp.enable_serr) + if (hpp.t0->enable_serr) pci_bctl |= PCI_BRIDGE_CTL_SERR; else pci_bctl &= ~PCI_BRIDGE_CTL_SERR; - if (hpp.enable_perr) + if (hpp.t0->enable_perr) pci_bctl |= PCI_BRIDGE_CTL_PARITY; else pci_bctl &= ~PCI_BRIDGE_CTL_PARITY; -- cgit v1.2.3 From 40abb96c51bbcb06785e233e96f40c35657ade83 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Mon, 8 May 2006 18:34:09 +0900 Subject: [PATCH] pciehp: Fix programming hotplug parameters Current PCHEHP driver doesn't have any code to program hotplug parameters from firmware. So hotplug parameters are never programed at hot-add time. This patch add support for programming hotplug parameters to PCIEHP driver. Signed-off-by: Kenji Kaneshige Cc: Kristen Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/pciehp_pci.c | 141 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 139 insertions(+), 2 deletions(-) diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c index 4017fb03a0b..6aa6a1be455 100644 --- a/drivers/pci/hotplug/pciehp_pci.c +++ b/drivers/pci/hotplug/pciehp_pci.c @@ -34,6 +34,144 @@ #include "../pci.h" #include "pciehp.h" +static void program_hpp_type0(struct pci_dev *dev, struct hpp_type0 *hpp) +{ + u16 pci_cmd, pci_bctl; + + if (hpp->revision > 1) { + printk(KERN_WARNING "%s: Rev.%d type0 record not supported\n", + __FUNCTION__, hpp->revision); + return; + } + + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, hpp->cache_line_size); + pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp->latency_timer); + pci_read_config_word(dev, PCI_COMMAND, &pci_cmd); + if (hpp->enable_serr) + pci_cmd |= PCI_COMMAND_SERR; + else + pci_cmd &= ~PCI_COMMAND_SERR; + if (hpp->enable_perr) + pci_cmd |= PCI_COMMAND_PARITY; + else + pci_cmd &= ~PCI_COMMAND_PARITY; + pci_write_config_word(dev, PCI_COMMAND, pci_cmd); + + /* Program bridge control value */ + if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { + pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, + hpp->latency_timer); + pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl); + if (hpp->enable_serr) + pci_bctl |= PCI_BRIDGE_CTL_SERR; + else + pci_bctl &= ~PCI_BRIDGE_CTL_SERR; + if (hpp->enable_perr) + pci_bctl |= PCI_BRIDGE_CTL_PARITY; + else + pci_bctl &= ~PCI_BRIDGE_CTL_PARITY; + pci_write_config_word(dev, PCI_BRIDGE_CONTROL, pci_bctl); + } +} + +static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp) +{ + int pos; + u16 reg16; + u32 reg32; + + if (hpp->revision > 1) { + printk(KERN_WARNING "%s: Rev.%d type2 record not supported\n", + __FUNCTION__, hpp->revision); + return; + } + + /* Find PCI Express capability */ + pos = pci_find_capability(dev, PCI_CAP_ID_EXP); + if (!pos) + return; + + /* Initialize Device Control Register */ + pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, ®16); + reg16 = (reg16 & hpp->pci_exp_devctl_and) | hpp->pci_exp_devctl_or; + pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, reg16); + + /* Initialize Link Control Register */ + if (dev->subordinate) { + pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, ®16); + reg16 = (reg16 & hpp->pci_exp_lnkctl_and) + | hpp->pci_exp_lnkctl_or; + pci_write_config_word(dev, pos + PCI_EXP_LNKCTL, reg16); + } + + /* Find Advanced Error Reporting Enhanced Capability */ + pos = 256; + do { + pci_read_config_dword(dev, pos, ®32); + if (PCI_EXT_CAP_ID(reg32) == PCI_EXT_CAP_ID_ERR) + break; + } while ((pos = PCI_EXT_CAP_NEXT(reg32))); + if (!pos) + return; + + /* Initialize Uncorrectable Error Mask Register */ + pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, ®32); + reg32 = (reg32 & hpp->unc_err_mask_and) | hpp->unc_err_mask_or; + pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, reg32); + + /* Initialize Uncorrectable Error Severity Register */ + pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, ®32); + reg32 = (reg32 & hpp->unc_err_sever_and) | hpp->unc_err_sever_or; + pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, reg32); + + /* Initialize Correctable Error Mask Register */ + pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, ®32); + reg32 = (reg32 & hpp->cor_err_mask_and) | hpp->cor_err_mask_or; + pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, reg32); + + /* Initialize Advanced Error Capabilities and Control Register */ + pci_read_config_dword(dev, pos + PCI_ERR_CAP, ®32); + reg32 = (reg32 & hpp->adv_err_cap_and) | hpp->adv_err_cap_or; + pci_write_config_dword(dev, pos + PCI_ERR_CAP, reg32); + + /* + * FIXME: The following two registers are not supported yet. + * + * o Secondary Uncorrectable Error Severity Register + * o Secondary Uncorrectable Error Mask Register + */ +} + +static void program_fw_provided_values(struct pci_dev *dev) +{ + struct pci_dev *cdev; + struct hotplug_params hpp; + + /* Program hpp values for this device */ + if (!(dev->hdr_type == PCI_HEADER_TYPE_NORMAL || + (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE && + (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI))) + return; + + if (pciehp_get_hp_params_from_firmware(dev, &hpp)) { + printk(KERN_WARNING "%s: Could not get hotplug parameters\n", + __FUNCTION__); + return; + } + + if (hpp.t2) + program_hpp_type2(dev, hpp.t2); + if (hpp.t0) + program_hpp_type0(dev, hpp.t0); + + /* Program child devices */ + if (dev->subordinate) { + list_for_each_entry(cdev, &dev->subordinate->devices, + bus_list) + program_fw_provided_values(cdev); + } +} + static int pciehp_add_bridge(struct pci_dev *dev) { struct pci_bus *parent = dev->bus; @@ -92,8 +230,7 @@ int pciehp_configure_device(struct slot *p_slot) (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) { pciehp_add_bridge(dev); } - /* TBD: program firmware provided _HPP values */ - /* program_fw_provided_values(dev); */ + program_fw_provided_values(dev); } pci_bus_assign_resources(parent); -- cgit v1.2.3 From 75d97c59a192ca0fe2577974dac0c16a73a377eb Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Tue, 2 May 2006 11:08:42 +0900 Subject: [PATCH] SHPC: Cleanup SHPC register access This patch cleans up the code to access SHPC working register sets. This patch has no functional changes. Signed-off-by: Kenji Kaneshige Cc: Kristen Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp_hpc.c | 192 +++++++++++++++++++++++---------------- 1 file changed, 112 insertions(+), 80 deletions(-) diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index 66123cf4dea..3abeb54964a 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c @@ -208,6 +208,49 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs); static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds); static int hpc_check_cmd_status(struct controller *ctrl); +static inline u8 shpc_readb(struct controller *ctrl, int reg) +{ + return readb(ctrl->hpc_ctlr_handle->creg + reg); +} + +static inline void shpc_writeb(struct controller *ctrl, int reg, u8 val) +{ + writeb(val, ctrl->hpc_ctlr_handle->creg + reg); +} + +static inline u16 shpc_readw(struct controller *ctrl, int reg) +{ + return readw(ctrl->hpc_ctlr_handle->creg + reg); +} + +static inline void shpc_writew(struct controller *ctrl, int reg, u16 val) +{ + writew(val, ctrl->hpc_ctlr_handle->creg + reg); +} + +static inline u32 shpc_readl(struct controller *ctrl, int reg) +{ + return readl(ctrl->hpc_ctlr_handle->creg + reg); +} + +static inline void shpc_writel(struct controller *ctrl, int reg, u32 val) +{ + writel(val, ctrl->hpc_ctlr_handle->creg + reg); +} + +static inline int shpc_indirect_read(struct controller *ctrl, int index, + u32 *value) +{ + int rc; + u32 cap_offset = ctrl->cap_offset; + struct pci_dev *pdev = ctrl->pci_dev; + + rc = pci_write_config_byte(pdev, cap_offset + DWORD_SELECT, index); + if (rc) + return rc; + return pci_read_config_dword(pdev, cap_offset + DWORD_DATA, value); +} + /* This is the interrupt polling timeout function. */ static void int_poll_timeout(unsigned long lphp_ctlr) { @@ -273,6 +316,7 @@ static inline int shpc_wait_cmd(struct controller *ctrl) static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) { struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; + struct controller *ctrl = slot->ctrl; u16 cmd_status; int retval = 0; u16 temp_word; @@ -289,7 +333,7 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) } for (i = 0; i < 10; i++) { - cmd_status = readw(php_ctlr->creg + CMD_STATUS); + cmd_status = shpc_readw(ctrl, CMD_STATUS); if (!(cmd_status & 0x1)) break; @@ -297,7 +341,7 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) msleep(100); } - cmd_status = readw(php_ctlr->creg + CMD_STATUS); + cmd_status = shpc_readw(ctrl, CMD_STATUS); if (cmd_status & 0x1) { /* After 1 sec and and the controller is still busy */ @@ -314,7 +358,7 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) * command. */ slot->ctrl->cmd_busy = 1; - writew(temp_word, php_ctlr->creg + CMD); + shpc_writew(ctrl, CMD, temp_word); /* * Wait for command completion. @@ -338,7 +382,6 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) static int hpc_check_cmd_status(struct controller *ctrl) { - struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle; u16 cmd_status; int retval = 0; @@ -349,7 +392,7 @@ static int hpc_check_cmd_status(struct controller *ctrl) return -1; } - cmd_status = readw(php_ctlr->creg + CMD_STATUS) & 0x000F; + cmd_status = shpc_readw(ctrl, CMD_STATUS) & 0x000F; switch (cmd_status >> 1) { case 0: @@ -378,7 +421,7 @@ static int hpc_check_cmd_status(struct controller *ctrl) static int hpc_get_attention_status(struct slot *slot, u8 *status) { - struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; + struct controller *ctrl = slot->ctrl; u32 slot_reg; u16 slot_status; u8 atten_led_state; @@ -390,7 +433,7 @@ static int hpc_get_attention_status(struct slot *slot, u8 *status) return -1; } - slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot)); + slot_reg = shpc_readl(ctrl, SLOT1 + 4*(slot->hp_slot)); slot_status = (u16) slot_reg; atten_led_state = (slot_status & 0x0030) >> 4; @@ -418,7 +461,7 @@ static int hpc_get_attention_status(struct slot *slot, u8 *status) static int hpc_get_power_status(struct slot * slot, u8 *status) { - struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; + struct controller *ctrl = slot->ctrl; u32 slot_reg; u16 slot_status; u8 slot_state; @@ -431,7 +474,7 @@ static int hpc_get_power_status(struct slot * slot, u8 *status) return -1; } - slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot)); + slot_reg = shpc_readl(ctrl, SLOT1 + 4*(slot->hp_slot)); slot_status = (u16) slot_reg; slot_state = (slot_status & 0x0003); @@ -460,7 +503,7 @@ static int hpc_get_power_status(struct slot * slot, u8 *status) static int hpc_get_latch_status(struct slot *slot, u8 *status) { - struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; + struct controller *ctrl = slot->ctrl; u32 slot_reg; u16 slot_status; @@ -471,7 +514,7 @@ static int hpc_get_latch_status(struct slot *slot, u8 *status) return -1; } - slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot)); + slot_reg = shpc_readl(ctrl, SLOT1 + 4*(slot->hp_slot)); slot_status = (u16)slot_reg; *status = ((slot_status & 0x0100) == 0) ? 0 : 1; /* 0 -> close; 1 -> open */ @@ -483,7 +526,7 @@ static int hpc_get_latch_status(struct slot *slot, u8 *status) static int hpc_get_adapter_status(struct slot *slot, u8 *status) { - struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; + struct controller *ctrl = slot->ctrl; u32 slot_reg; u16 slot_status; u8 card_state; @@ -495,7 +538,7 @@ static int hpc_get_adapter_status(struct slot *slot, u8 *status) return -1; } - slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot)); + slot_reg = shpc_readl(ctrl, SLOT1 + 4*(slot->hp_slot)); slot_status = (u16)slot_reg; card_state = (u8)((slot_status & 0x0C00) >> 10); *status = (card_state != 0x3) ? 1 : 0; @@ -506,7 +549,7 @@ static int hpc_get_adapter_status(struct slot *slot, u8 *status) static int hpc_get_prog_int(struct slot *slot, u8 *prog_int) { - struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; + struct controller *ctrl = slot->ctrl; DBG_ENTER_ROUTINE @@ -515,7 +558,7 @@ static int hpc_get_prog_int(struct slot *slot, u8 *prog_int) return -1; } - *prog_int = readb(php_ctlr->creg + PROG_INTERFACE); + *prog_int = shpc_readb(ctrl, PROG_INTERFACE); DBG_LEAVE_ROUTINE return 0; @@ -524,8 +567,8 @@ static int hpc_get_prog_int(struct slot *slot, u8 *prog_int) static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value) { int retval = 0; - struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; - u32 slot_reg = readl(php_ctlr->creg + SLOT1 + 4 * slot->hp_slot); + struct controller *ctrl = slot->ctrl; + u32 slot_reg = shpc_readl(ctrl, SLOT1 + 4 * slot->hp_slot); u8 pcix_cap = (slot_reg >> 12) & 7; u8 m66_cap = (slot_reg >> 9) & 1; @@ -564,7 +607,7 @@ static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value) static int hpc_get_mode1_ECC_cap(struct slot *slot, u8 *mode) { - struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; + struct controller *ctrl = slot->ctrl; u16 sec_bus_status; u8 pi; int retval = 0; @@ -576,8 +619,8 @@ static int hpc_get_mode1_ECC_cap(struct slot *slot, u8 *mode) return -1; } - pi = readb(php_ctlr->creg + PROG_INTERFACE); - sec_bus_status = readw(php_ctlr->creg + SEC_BUS_CONFIG); + pi = shpc_readb(ctrl, PROG_INTERFACE); + sec_bus_status = shpc_readw(ctrl, SEC_BUS_CONFIG); if (pi == 2) { *mode = (sec_bus_status & 0x0100) >> 8; @@ -593,7 +636,7 @@ static int hpc_get_mode1_ECC_cap(struct slot *slot, u8 *mode) static int hpc_query_power_fault(struct slot * slot) { - struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; + struct controller *ctrl = slot->ctrl; u32 slot_reg; u16 slot_status; u8 pwr_fault_state, status; @@ -605,7 +648,7 @@ static int hpc_query_power_fault(struct slot * slot) return -1; } - slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot)); + slot_reg = shpc_readl(ctrl, SLOT1 + 4*(slot->hp_slot)); slot_status = (u16) slot_reg; pwr_fault_state = (slot_status & 0x0040) >> 7; status = (pwr_fault_state == 1) ? 0 : 1; @@ -724,7 +767,7 @@ int shpc_get_ctlr_slot_config(struct controller *ctrl, int *updown, /* physical_slot_num increament: 1 or -1 */ int *flags) { - struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle; + u32 slot_config; DBG_ENTER_ROUTINE @@ -733,12 +776,13 @@ int shpc_get_ctlr_slot_config(struct controller *ctrl, return -1; } - *first_device_num = php_ctlr->slot_device_offset; /* Obtained in shpc_init() */ - *num_ctlr_slots = php_ctlr->num_slots; /* Obtained in shpc_init() */ + slot_config = shpc_readl(ctrl, SLOT_CONFIG); + *first_device_num = (slot_config & FIRST_DEV_NUM) >> 8; + *num_ctlr_slots = slot_config & SLOT_NUM; + *physical_slot_num = (slot_config & PSN) >> 16; + *updown = ((slot_config & UPDOWN) >> 29) ? 1 : -1; - *physical_slot_num = (readl(php_ctlr->creg + SLOT_CONFIG) & PSN) >> 16; dbg("%s: physical_slot_num = %x\n", __FUNCTION__, *physical_slot_num); - *updown = ((readl(php_ctlr->creg + SLOT_CONFIG) & UPDOWN ) >> 29) ? 1 : -1; DBG_LEAVE_ROUTINE return 0; @@ -761,7 +805,7 @@ static void hpc_release_ctlr(struct controller *ctrl) * Mask all slot event interrupts */ for (i = 0; i < ctrl->num_slots; i++) - writel(0xffff3fff, php_ctlr->creg + SLOT1 + (4 * i)); + shpc_writel(ctrl, SLOT1 + (4 * i), 0xffff3fff); cleanup_slots(ctrl); @@ -901,12 +945,12 @@ static int hpc_slot_disable(struct slot * slot) static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value) { int retval; - struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; + struct controller *ctrl = slot->ctrl; u8 pi, cmd; DBG_ENTER_ROUTINE - pi = readb(php_ctlr->creg + PROG_INTERFACE); + pi = shpc_readb(ctrl, PROG_INTERFACE); if ((pi == 1) && (value > PCI_SPEED_133MHz_PCIX)) return -EINVAL; @@ -992,7 +1036,7 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs) return IRQ_NONE; /* Check to see if it was our interrupt */ - intr_loc = readl(php_ctlr->creg + INTR_LOC); + intr_loc = shpc_readl(ctrl, INTR_LOC); if (!intr_loc) return IRQ_NONE; @@ -1001,11 +1045,11 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs) if(!shpchp_poll_mode) { /* Mask Global Interrupt Mask - see implementation note on p. 139 */ /* of SHPC spec rev 1.0*/ - temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE); + temp_dword = shpc_readl(ctrl, SERR_INTR_ENABLE); temp_dword |= 0x00000001; - writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE); + shpc_writel(ctrl, SERR_INTR_ENABLE, temp_dword); - intr_loc2 = readl(php_ctlr->creg + INTR_LOC); + intr_loc2 = shpc_readl(ctrl, INTR_LOC); dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2); } @@ -1015,9 +1059,9 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs) * RO only - clear by writing 1 to the Command Completion * Detect bit in Controller SERR-INT register */ - temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE); + temp_dword = shpc_readl(ctrl, SERR_INTR_ENABLE); temp_dword &= 0xfffdffff; - writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE); + shpc_writel(ctrl, SERR_INTR_ENABLE, temp_dword); ctrl->cmd_busy = 0; wake_up_interruptible(&ctrl->queue); } @@ -1028,7 +1072,7 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs) for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) { /* To find out which slot has interrupt pending */ if ((intr_loc >> hp_slot) & 0x01) { - temp_dword = readl(php_ctlr->creg + SLOT1 + (4*hp_slot)); + temp_dword = shpc_readl(ctrl, SLOT1 + (4*hp_slot)); dbg("%s: Slot %x with intr, slot register = %x\n", __FUNCTION__, hp_slot, temp_dword); temp_byte = (temp_dword >> 16) & 0xFF; @@ -1047,18 +1091,18 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs) /* Clear all slot events */ temp_dword = 0xe01f3fff; - writel(temp_dword, php_ctlr->creg + SLOT1 + (4*hp_slot)); + shpc_writel(ctrl, SLOT1 + (4*hp_slot), temp_dword); - intr_loc2 = readl(php_ctlr->creg + INTR_LOC); + intr_loc2 = shpc_readl(ctrl, INTR_LOC); dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2); } } out: if (!shpchp_poll_mode) { /* Unmask Global Interrupt Mask */ - temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE); + temp_dword = shpc_readl(ctrl, SERR_INTR_ENABLE); temp_dword &= 0xfffffffe; - writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE); + shpc_writel(ctrl, SERR_INTR_ENABLE, temp_dword); } return IRQ_HANDLED; @@ -1067,11 +1111,11 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs) static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value) { int retval = 0; - struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; + struct controller *ctrl = slot->ctrl; enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN; - u8 pi = readb(php_ctlr->creg + PROG_INTERFACE); - u32 slot_avail1 = readl(php_ctlr->creg + SLOT_AVAIL1); - u32 slot_avail2 = readl(php_ctlr->creg + SLOT_AVAIL2); + u8 pi = shpc_readb(ctrl, PROG_INTERFACE); + u32 slot_avail1 = shpc_readl(ctrl, SLOT_AVAIL1); + u32 slot_avail2 = shpc_readl(ctrl, SLOT_AVAIL2); DBG_ENTER_ROUTINE @@ -1114,10 +1158,10 @@ static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value) static int hpc_get_cur_bus_speed (struct slot *slot, enum pci_bus_speed *value) { int retval = 0; - struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; + struct controller *ctrl = slot->ctrl; enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN; - u16 sec_bus_reg = readw(php_ctlr->creg + SEC_BUS_CONFIG); - u8 pi = readb(php_ctlr->creg + PROG_INTERFACE); + u16 sec_bus_reg = shpc_readw(ctrl, SEC_BUS_CONFIG); + u8 pi = shpc_readb(ctrl, PROG_INTERFACE); u8 speed_mode = (pi == 2) ? (sec_bus_reg & 0xF) : (sec_bus_reg & 0x7); DBG_ENTER_ROUTINE @@ -1206,19 +1250,6 @@ static struct hpc_ops shpchp_hpc_ops = { .release_ctlr = hpc_release_ctlr, }; -inline static int shpc_indirect_creg_read(struct controller *ctrl, int index, - u32 *value) -{ - int rc; - u32 cap_offset = ctrl->cap_offset; - struct pci_dev *pdev = ctrl->pci_dev; - - rc = pci_write_config_byte(pdev, cap_offset + DWORD_SELECT, index); - if (rc) - return rc; - return pci_read_config_dword(pdev, cap_offset + DWORD_DATA, value); -} - int shpc_init(struct controller * ctrl, struct pci_dev * pdev) { struct php_ctlr_state_s *php_ctlr, *p; @@ -1227,7 +1258,7 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) u8 hp_slot; static int first = 1; u32 shpc_base_offset; - u32 tempdword, slot_reg; + u32 tempdword, slot_reg, slot_config; u8 i; DBG_ENTER_ROUTINE @@ -1257,13 +1288,13 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) } dbg("%s: cap_offset = %x\n", __FUNCTION__, ctrl->cap_offset); - rc = shpc_indirect_creg_read(ctrl, 0, &shpc_base_offset); + rc = shpc_indirect_read(ctrl, 0, &shpc_base_offset); if (rc) { err("%s: cannot read base_offset\n", __FUNCTION__); goto abort_free_ctlr; } - rc = shpc_indirect_creg_read(ctrl, 3, &tempdword); + rc = shpc_indirect_read(ctrl, 3, &tempdword); if (rc) { err("%s: cannot read slot config\n", __FUNCTION__); goto abort_free_ctlr; @@ -1272,7 +1303,7 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) dbg("%s: num_slots (indirect) %x\n", __FUNCTION__, num_slots); for (i = 0; i < 9 + num_slots; i++) { - rc = shpc_indirect_creg_read(ctrl, i, &tempdword); + rc = shpc_indirect_read(ctrl, i, &tempdword); if (rc) { err("%s: cannot read creg (index = %d)\n", __FUNCTION__, i); @@ -1326,29 +1357,33 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) php_ctlr->power_fault_callback = shpchp_handle_power_fault; php_ctlr->callback_instance_id = instance_id; + ctrl->hpc_ctlr_handle = php_ctlr; + ctrl->hpc_ops = &shpchp_hpc_ops; + /* Return PCI Controller Info */ - php_ctlr->slot_device_offset = (readl(php_ctlr->creg + SLOT_CONFIG) & FIRST_DEV_NUM ) >> 8; - php_ctlr->num_slots = readl(php_ctlr->creg + SLOT_CONFIG) & SLOT_NUM; + slot_config = shpc_readl(ctrl, SLOT_CONFIG); + php_ctlr->slot_device_offset = (slot_config & FIRST_DEV_NUM) >> 8; + php_ctlr->num_slots = slot_config & SLOT_NUM; dbg("%s: slot_device_offset %x\n", __FUNCTION__, php_ctlr->slot_device_offset); dbg("%s: num_slots %x\n", __FUNCTION__, php_ctlr->num_slots); /* Mask Global Interrupt Mask & Command Complete Interrupt Mask */ - tempdword = readl(php_ctlr->creg + SERR_INTR_ENABLE); + tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE); dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword); tempdword = 0x0003000f; - writel(tempdword, php_ctlr->creg + SERR_INTR_ENABLE); - tempdword = readl(php_ctlr->creg + SERR_INTR_ENABLE); + shpc_writel(ctrl, SERR_INTR_ENABLE, tempdword); + tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE); dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword); /* Mask the MRL sensor SERR Mask of individual slot in * Slot SERR-INT Mask & clear all the existing event if any */ for (hp_slot = 0; hp_slot < php_ctlr->num_slots; hp_slot++) { - slot_reg = readl(php_ctlr->creg + SLOT1 + 4*hp_slot ); + slot_reg = shpc_readl(ctrl, SLOT1 + 4*hp_slot ); dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__, hp_slot, slot_reg); tempdword = 0xffff3fff; - writel(tempdword, php_ctlr->creg + SLOT1 + (4*hp_slot)); + shpc_writel(ctrl, SLOT1 + (4*hp_slot), tempdword); } if (shpchp_poll_mode) {/* Install interrupt polling code */ @@ -1392,24 +1427,21 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) } spin_unlock(&list_lock); - ctlr_seq_num++; - ctrl->hpc_ctlr_handle = php_ctlr; - ctrl->hpc_ops = &shpchp_hpc_ops; for (hp_slot = 0; hp_slot < php_ctlr->num_slots; hp_slot++) { - slot_reg = readl(php_ctlr->creg + SLOT1 + 4*hp_slot ); + slot_reg = shpc_readl(ctrl, SLOT1 + 4*hp_slot ); dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__, hp_slot, slot_reg); tempdword = 0xe01f3fff; - writel(tempdword, php_ctlr->creg + SLOT1 + (4*hp_slot)); + shpc_writel(ctrl, SLOT1 + (4*hp_slot), tempdword); } if (!shpchp_poll_mode) { /* Unmask all general input interrupts and SERR */ - tempdword = readl(php_ctlr->creg + SERR_INTR_ENABLE); + tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE); tempdword = 0x0000000a; - writel(tempdword, php_ctlr->creg + SERR_INTR_ENABLE); - tempdword = readl(php_ctlr->creg + SERR_INTR_ENABLE); + shpc_writel(ctrl, SERR_INTR_ENABLE, tempdword); + tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE); dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword); } -- cgit v1.2.3 From 2b34da7e61383b4b7773d2d4e776e58725794347 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Tue, 2 May 2006 11:09:42 +0900 Subject: [PATCH] SHPC: Cleanup SHPC Logical Slot Register access This patch cleans up the code to access slot logical registers. This patch has no functional changes. Signed-off-by: Kenji Kaneshige Cc: Kristen Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp_hpc.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index 3abeb54964a..a5337cf1436 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c @@ -90,6 +90,11 @@ #define MRLSENSOR 0x40000000 #define ATTN_BUTTON 0x80000000 +/* + * Logical Slot Register definitions + */ +#define SLOT_REG(i) (SLOT1 + (4 * i)) + /* Slot Status Field Definitions */ /* Slot State */ #define PWR_ONLY 0x0001 @@ -433,7 +438,7 @@ static int hpc_get_attention_status(struct slot *slot, u8 *status) return -1; } - slot_reg = shpc_readl(ctrl, SLOT1 + 4*(slot->hp_slot)); + slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); slot_status = (u16) slot_reg; atten_led_state = (slot_status & 0x0030) >> 4; @@ -474,7 +479,7 @@ static int hpc_get_power_status(struct slot * slot, u8 *status) return -1; } - slot_reg = shpc_readl(ctrl, SLOT1 + 4*(slot->hp_slot)); + slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); slot_status = (u16) slot_reg; slot_state = (slot_status & 0x0003); @@ -514,7 +519,7 @@ static int hpc_get_latch_status(struct slot *slot, u8 *status) return -1; } - slot_reg = shpc_readl(ctrl, SLOT1 + 4*(slot->hp_slot)); + slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); slot_status = (u16)slot_reg; *status = ((slot_status & 0x0100) == 0) ? 0 : 1; /* 0 -> close; 1 -> open */ @@ -538,7 +543,7 @@ static int hpc_get_adapter_status(struct slot *slot, u8 *status) return -1; } - slot_reg = shpc_readl(ctrl, SLOT1 + 4*(slot->hp_slot)); + slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); slot_status = (u16)slot_reg; card_state = (u8)((slot_status & 0x0C00) >> 10); *status = (card_state != 0x3) ? 1 : 0; @@ -568,7 +573,7 @@ static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value) { int retval = 0; struct controller *ctrl = slot->ctrl; - u32 slot_reg = shpc_readl(ctrl, SLOT1 + 4 * slot->hp_slot); + u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); u8 pcix_cap = (slot_reg >> 12) & 7; u8 m66_cap = (slot_reg >> 9) & 1; @@ -648,7 +653,7 @@ static int hpc_query_power_fault(struct slot * slot) return -1; } - slot_reg = shpc_readl(ctrl, SLOT1 + 4*(slot->hp_slot)); + slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); slot_status = (u16) slot_reg; pwr_fault_state = (slot_status & 0x0040) >> 7; status = (pwr_fault_state == 1) ? 0 : 1; @@ -805,7 +810,7 @@ static void hpc_release_ctlr(struct controller *ctrl) * Mask all slot event interrupts */ for (i = 0; i < ctrl->num_slots; i++) - shpc_writel(ctrl, SLOT1 + (4 * i), 0xffff3fff); + shpc_writel(ctrl, SLOT_REG(i), 0xffff3fff); cleanup_slots(ctrl); @@ -1072,7 +1077,7 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs) for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) { /* To find out which slot has interrupt pending */ if ((intr_loc >> hp_slot) & 0x01) { - temp_dword = shpc_readl(ctrl, SLOT1 + (4*hp_slot)); + temp_dword = shpc_readl(ctrl, SLOT_REG(hp_slot)); dbg("%s: Slot %x with intr, slot register = %x\n", __FUNCTION__, hp_slot, temp_dword); temp_byte = (temp_dword >> 16) & 0xFF; @@ -1091,7 +1096,7 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs) /* Clear all slot events */ temp_dword = 0xe01f3fff; - shpc_writel(ctrl, SLOT1 + (4*hp_slot), temp_dword); + shpc_writel(ctrl, SLOT_REG(hp_slot), temp_dword); intr_loc2 = shpc_readl(ctrl, INTR_LOC); dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2); @@ -1379,11 +1384,11 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) * Slot SERR-INT Mask & clear all the existing event if any */ for (hp_slot = 0; hp_slot < php_ctlr->num_slots; hp_slot++) { - slot_reg = shpc_readl(ctrl, SLOT1 + 4*hp_slot ); + slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot)); dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__, hp_slot, slot_reg); tempdword = 0xffff3fff; - shpc_writel(ctrl, SLOT1 + (4*hp_slot), tempdword); + shpc_writel(ctrl, SLOT_REG(hp_slot), tempdword); } if (shpchp_poll_mode) {/* Install interrupt polling code */ @@ -1430,11 +1435,11 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) ctlr_seq_num++; for (hp_slot = 0; hp_slot < php_ctlr->num_slots; hp_slot++) { - slot_reg = shpc_readl(ctrl, SLOT1 + 4*hp_slot ); + slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot)); dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__, hp_slot, slot_reg); tempdword = 0xe01f3fff; - shpc_writel(ctrl, SLOT1 + (4*hp_slot), tempdword); + shpc_writel(ctrl, SLOT_REG(hp_slot), tempdword); } if (!shpchp_poll_mode) { /* Unmask all general input interrupts and SERR */ -- cgit v1.2.3 From 5858759c2098c6792af1afa6d5ded94044740f9c Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Tue, 2 May 2006 11:10:37 +0900 Subject: [PATCH] SHPC: Cleanup SHPC Logical Slot Register bits access This patch cleans up the code to access bits in slot logical registers. This patch has no functional change. Signed-off-by: Kenji Kaneshige Cc: Kristen Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp_hpc.c | 151 +++++++++++++++++---------------------- 1 file changed, 64 insertions(+), 87 deletions(-) diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index a5337cf1436..9731ee8224f 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c @@ -95,43 +95,40 @@ */ #define SLOT_REG(i) (SLOT1 + (4 * i)) -/* Slot Status Field Definitions */ -/* Slot State */ -#define PWR_ONLY 0x0001 -#define ENABLED 0x0002 -#define DISABLED 0x0003 - -/* Power Indicator State */ -#define PWR_LED_ON 0x0004 -#define PWR_LED_BLINK 0x0008 -#define PWR_LED_OFF 0x000c - -/* Attention Indicator State */ -#define ATTEN_LED_ON 0x0010 -#define ATTEN_LED_BLINK 0x0020 -#define ATTEN_LED_OFF 0x0030 - -/* Power Fault */ -#define pwr_fault 0x0040 - -/* Attention Button */ -#define ATTEN_BUTTON 0x0080 - -/* MRL Sensor */ -#define MRL_SENSOR 0x0100 - -/* 66 MHz Capable */ -#define IS_66MHZ_CAP 0x0200 - -/* PRSNT1#/PRSNT2# */ -#define SLOT_EMP 0x0c00 - -/* PCI-X Capability */ -#define NON_PCIX 0x0000 -#define PCIX_66 0x1000 -#define PCIX_133 0x3000 -#define PCIX_266 0x4000 /* For PI = 2 only */ -#define PCIX_533 0x5000 /* For PI = 2 only */ +#define SLOT_STATE_SHIFT (0) +#define SLOT_STATE_MASK (3 << 0) +#define SLOT_STATE_PWRONLY (1) +#define SLOT_STATE_ENABLED (2) +#define SLOT_STATE_DISABLED (3) +#define PWR_LED_STATE_SHIFT (2) +#define PWR_LED_STATE_MASK (3 << 2) +#define ATN_LED_STATE_SHIFT (4) +#define ATN_LED_STATE_MASK (3 << 4) +#define ATN_LED_STATE_ON (1) +#define ATN_LED_STATE_BLINK (2) +#define ATN_LED_STATE_OFF (3) +#define POWER_FAULT (1 << 6) +#define ATN_BUTTON (1 << 7) +#define MRL_SENSOR (1 << 8) +#define MHZ66_CAP (1 << 9) +#define PRSNT_SHIFT (10) +#define PRSNT_MASK (3 << 10) +#define PCIX_CAP_SHIFT (12) +#define PCIX_CAP_MASK_PI1 (3 << 12) +#define PCIX_CAP_MASK_PI2 (7 << 12) +#define PRSNT_CHANGE_DETECTED (1 << 16) +#define ISO_PFAULT_DETECTED (1 << 17) +#define BUTTON_PRESS_DETECTED (1 << 18) +#define MRL_CHANGE_DETECTED (1 << 19) +#define CON_PFAULT_DETECTED (1 << 20) +#define PRSNT_CHANGE_INTR_MASK (1 << 24) +#define ISO_PFAULT_INTR_MASK (1 << 25) +#define BUTTON_PRESS_INTR_MASK (1 << 26) +#define MRL_CHANGE_INTR_MASK (1 << 27) +#define CON_PFAULT_INTR_MASK (1 << 28) +#define MRL_CHANGE_SERR_MASK (1 << 29) +#define CON_PFAULT_SERR_MASK (1 << 30) +#define SLOT_REG_RSVDZ_MASK (1 << 15) | (7 << 21) /* SHPC 'write' operations/commands */ @@ -428,8 +425,7 @@ static int hpc_get_attention_status(struct slot *slot, u8 *status) { struct controller *ctrl = slot->ctrl; u32 slot_reg; - u16 slot_status; - u8 atten_led_state; + u8 state; DBG_ENTER_ROUTINE @@ -439,24 +435,20 @@ static int hpc_get_attention_status(struct slot *slot, u8 *status) } slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); - slot_status = (u16) slot_reg; - atten_led_state = (slot_status & 0x0030) >> 4; + state = (slot_reg & ATN_LED_STATE_MASK) >> ATN_LED_STATE_SHIFT; - switch (atten_led_state) { - case 0: - *status = 0xFF; /* Reserved */ - break; - case 1: + switch (state) { + case ATN_LED_STATE_ON: *status = 1; /* On */ break; - case 2: + case ATN_LED_STATE_BLINK: *status = 2; /* Blink */ break; - case 3: + case ATN_LED_STATE_OFF: *status = 0; /* Off */ break; default: - *status = 0xFF; + *status = 0xFF; /* Reserved */ break; } @@ -468,9 +460,7 @@ static int hpc_get_power_status(struct slot * slot, u8 *status) { struct controller *ctrl = slot->ctrl; u32 slot_reg; - u16 slot_status; - u8 slot_state; - int retval = 0; + u8 state; DBG_ENTER_ROUTINE @@ -480,29 +470,25 @@ static int hpc_get_power_status(struct slot * slot, u8 *status) } slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); - slot_status = (u16) slot_reg; - slot_state = (slot_status & 0x0003); + state = (slot_reg & SLOT_STATE_MASK) >> SLOT_STATE_SHIFT; - switch (slot_state) { - case 0: - *status = 0xFF; - break; - case 1: + switch (state) { + case SLOT_STATE_PWRONLY: *status = 2; /* Powered only */ break; - case 2: + case SLOT_STATE_ENABLED: *status = 1; /* Enabled */ break; - case 3: + case SLOT_STATE_DISABLED: *status = 0; /* Disabled */ break; default: - *status = 0xFF; + *status = 0xFF; /* Reserved */ break; } DBG_LEAVE_ROUTINE - return retval; + return 0; } @@ -510,7 +496,6 @@ static int hpc_get_latch_status(struct slot *slot, u8 *status) { struct controller *ctrl = slot->ctrl; u32 slot_reg; - u16 slot_status; DBG_ENTER_ROUTINE @@ -520,10 +505,7 @@ static int hpc_get_latch_status(struct slot *slot, u8 *status) } slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); - slot_status = (u16)slot_reg; - - *status = ((slot_status & 0x0100) == 0) ? 0 : 1; /* 0 -> close; 1 -> open */ - + *status = !!(slot_reg & MRL_SENSOR); /* 0 -> close; 1 -> open */ DBG_LEAVE_ROUTINE return 0; @@ -533,8 +515,7 @@ static int hpc_get_adapter_status(struct slot *slot, u8 *status) { struct controller *ctrl = slot->ctrl; u32 slot_reg; - u16 slot_status; - u8 card_state; + u8 state; DBG_ENTER_ROUTINE @@ -544,9 +525,8 @@ static int hpc_get_adapter_status(struct slot *slot, u8 *status) } slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); - slot_status = (u16)slot_reg; - card_state = (u8)((slot_status & 0x0C00) >> 10); - *status = (card_state != 0x3) ? 1 : 0; + state = (slot_reg & PRSNT_MASK) >> PRSNT_SHIFT; + *status = (state != 0x3) ? 1 : 0; DBG_LEAVE_ROUTINE return 0; @@ -574,8 +554,8 @@ static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value) int retval = 0; struct controller *ctrl = slot->ctrl; u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); - u8 pcix_cap = (slot_reg >> 12) & 7; - u8 m66_cap = (slot_reg >> 9) & 1; + u8 pcix_cap = (slot_reg & PCIX_CAP_MASK_PI2) >> PCIX_CAP_SHIFT; + u8 m66_cap = !!(slot_reg & MHZ66_CAP); DBG_ENTER_ROUTINE @@ -643,8 +623,6 @@ static int hpc_query_power_fault(struct slot * slot) { struct controller *ctrl = slot->ctrl; u32 slot_reg; - u16 slot_status; - u8 pwr_fault_state, status; DBG_ENTER_ROUTINE @@ -654,13 +632,10 @@ static int hpc_query_power_fault(struct slot * slot) } slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); - slot_status = (u16) slot_reg; - pwr_fault_state = (slot_status & 0x0040) >> 7; - status = (pwr_fault_state == 1) ? 0 : 1; DBG_LEAVE_ROUTINE /* Note: Logic 0 => fault */ - return status; + return !(slot_reg & POWER_FAULT); } static int hpc_set_attention_status(struct slot *slot, u8 value) @@ -1019,7 +994,6 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs) struct controller *ctrl = NULL; struct php_ctlr_state_s *php_ctlr; u8 schedule_flag = 0; - u8 temp_byte; u32 temp_dword, intr_loc, intr_loc2; int hp_slot; @@ -1080,17 +1054,20 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs) temp_dword = shpc_readl(ctrl, SLOT_REG(hp_slot)); dbg("%s: Slot %x with intr, slot register = %x\n", __FUNCTION__, hp_slot, temp_dword); - temp_byte = (temp_dword >> 16) & 0xFF; - if ((php_ctlr->switch_change_callback) && (temp_byte & 0x08)) + if ((php_ctlr->switch_change_callback) && + (temp_dword & MRL_CHANGE_DETECTED)) schedule_flag += php_ctlr->switch_change_callback( hp_slot, php_ctlr->callback_instance_id); - if ((php_ctlr->attention_button_callback) && (temp_byte & 0x04)) + if ((php_ctlr->attention_button_callback) && + (temp_dword & BUTTON_PRESS_DETECTED)) schedule_flag += php_ctlr->attention_button_callback( hp_slot, php_ctlr->callback_instance_id); - if ((php_ctlr->presence_change_callback) && (temp_byte & 0x01)) + if ((php_ctlr->presence_change_callback) && + (temp_dword & PRSNT_CHANGE_DETECTED)) schedule_flag += php_ctlr->presence_change_callback( hp_slot , php_ctlr->callback_instance_id); - if ((php_ctlr->power_fault_callback) && (temp_byte & 0x12)) + if ((php_ctlr->power_fault_callback) && + (temp_dword & (ISO_PFAULT_DETECTED | CON_PFAULT_DETECTED))) schedule_flag += php_ctlr->power_fault_callback( hp_slot, php_ctlr->callback_instance_id); -- cgit v1.2.3 From 795eb5c4a73bee30e8c2dbb29174b329da56051c Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Tue, 2 May 2006 11:11:54 +0900 Subject: [PATCH] SHPC: Fix SHPC Logical Slot Register bits access Current SHPCHP driver doesn't take care of RsvdP/RsvdZ[*] bits in logical slot registers. This might cause unpredicable results. This patch fixes this bug. [*] RsvdP and RsvdZ are defined in SHPC spec as follows: RsvdP - Reserved and Preserved. Register bits of this type are reserved for future use as R/W bits. The value read is undefined. Writes are ignored. Software must follow These rules when accessing RsvdP bits: - Software must ignore RsvdP bits when testing values read from these registers. - Software must not depend on RsvdP bit's ability to retain information when written - Software must always write back the value read in the RsvdP bits when writing one of these registers. RsvdZ - Reserved and Zero. Register bits of this type are reserved for future use as R/WC bits. The value read is undefined. Writes are ignored. Software must follow these rules when accessing RsvdZ bits: - Software must ignore RsvdZ bits when testing values read from these registers. - Software must not depends on a RsvdZ bit's ability to retain information when written. - Software must always write 0 to RsvdZ bits when writing one of these register. Signed-off-by: Kenji Kaneshige Cc: Kristen Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp_hpc.c | 49 ++++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index 9731ee8224f..285a21d3652 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c @@ -554,11 +554,25 @@ static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value) int retval = 0; struct controller *ctrl = slot->ctrl; u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); - u8 pcix_cap = (slot_reg & PCIX_CAP_MASK_PI2) >> PCIX_CAP_SHIFT; u8 m66_cap = !!(slot_reg & MHZ66_CAP); + u8 pi, pcix_cap; DBG_ENTER_ROUTINE + if ((retval = hpc_get_prog_int(slot, &pi))) + return retval; + + switch (pi) { + case 1: + pcix_cap = (slot_reg & PCIX_CAP_MASK_PI1) >> PCIX_CAP_SHIFT; + break; + case 2: + pcix_cap = (slot_reg & PCIX_CAP_MASK_PI2) >> PCIX_CAP_SHIFT; + break; + default: + return -ENODEV; + } + dbg("%s: slot_reg = %x, pcix_cap = %x, m66_cap = %x\n", __FUNCTION__, slot_reg, pcix_cap, m66_cap); @@ -773,6 +787,7 @@ static void hpc_release_ctlr(struct controller *ctrl) struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle; struct php_ctlr_state_s *p, *p_prev; int i; + u32 slot_reg; DBG_ENTER_ROUTINE @@ -782,10 +797,17 @@ static void hpc_release_ctlr(struct controller *ctrl) } /* - * Mask all slot event interrupts + * Mask event interrupts and SERRs of all slots */ - for (i = 0; i < ctrl->num_slots; i++) - shpc_writel(ctrl, SLOT_REG(i), 0xffff3fff); + for (i = 0; i < ctrl->num_slots; i++) { + slot_reg = shpc_readl(ctrl, SLOT_REG(i)); + slot_reg |= (PRSNT_CHANGE_INTR_MASK | ISO_PFAULT_INTR_MASK | + BUTTON_PRESS_INTR_MASK | MRL_CHANGE_INTR_MASK | + CON_PFAULT_INTR_MASK | MRL_CHANGE_SERR_MASK | + CON_PFAULT_SERR_MASK); + slot_reg &= ~SLOT_REG_RSVDZ_MASK; + shpc_writel(ctrl, SLOT_REG(i), slot_reg); + } cleanup_slots(ctrl); @@ -1072,7 +1094,7 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs) hp_slot, php_ctlr->callback_instance_id); /* Clear all slot events */ - temp_dword = 0xe01f3fff; + temp_dword &= ~SLOT_REG_RSVDZ_MASK; shpc_writel(ctrl, SLOT_REG(hp_slot), temp_dword); intr_loc2 = shpc_readl(ctrl, INTR_LOC); @@ -1364,8 +1386,12 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot)); dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__, hp_slot, slot_reg); - tempdword = 0xffff3fff; - shpc_writel(ctrl, SLOT_REG(hp_slot), tempdword); + slot_reg |= (PRSNT_CHANGE_INTR_MASK | ISO_PFAULT_INTR_MASK | + BUTTON_PRESS_INTR_MASK | MRL_CHANGE_INTR_MASK | + CON_PFAULT_INTR_MASK | MRL_CHANGE_SERR_MASK | + CON_PFAULT_SERR_MASK); + slot_reg &= ~SLOT_REG_RSVDZ_MASK; + shpc_writel(ctrl, SLOT_REG(hp_slot), slot_reg); } if (shpchp_poll_mode) {/* Install interrupt polling code */ @@ -1411,12 +1437,17 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) ctlr_seq_num++; + /* + * Unmask all event interrupts of all slots + */ for (hp_slot = 0; hp_slot < php_ctlr->num_slots; hp_slot++) { slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot)); dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__, hp_slot, slot_reg); - tempdword = 0xe01f3fff; - shpc_writel(ctrl, SLOT_REG(hp_slot), tempdword); + slot_reg &= ~(PRSNT_CHANGE_INTR_MASK | ISO_PFAULT_INTR_MASK | + BUTTON_PRESS_INTR_MASK | MRL_CHANGE_INTR_MASK | + CON_PFAULT_INTR_MASK | SLOT_REG_RSVDZ_MASK); + shpc_writel(ctrl, SLOT_REG(hp_slot), slot_reg); } if (!shpchp_poll_mode) { /* Unmask all general input interrupts and SERR */ -- cgit v1.2.3 From e7138723692e43b7d43578746ad21bf194847527 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Tue, 2 May 2006 11:12:37 +0900 Subject: [PATCH] SHPC: Fix SHPC Contoller SERR-INT Register bits access Current SHPCHP driver doesn't take care of RsvdP/RsvdZ[*] bits in controller SERR-INT register. This might cause unpredicable results. This patch fixes this bug. [*] RsvdP and RsvdZ are defined in SHPC spec as follows: RsvdP - Reserved and Preserved. Register bits of this type are reserved for future use as R/W bits. The value read is undefined. Writes are ignored. Software must follow These rules when accessing RsvdP bits: - Software must ignore RsvdP bits when testing values read from these registers. - Software must not depend on RsvdP bit's ability to retain information when written - Software must always write back the value read in the RsvdP bits when writing one of these registers. RsvdZ - Reserved and Zero. Register bits of this type are reserved for future use as R/WC bits. The value read is undefined. Writes are ignored. Software must follow these rules when accessing RsvdZ bits: - Software must ignore RsvdZ bits when testing values read from these registers. - Software must not depends on a RsvdZ bit's ability to retain information when written. - Software must always write 0 to RsvdZ bits when writing one of these register. Signed-off-by: Kenji Kaneshige Cc: Kristen Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp_hpc.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index 285a21d3652..e2a8671545f 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c @@ -90,6 +90,17 @@ #define MRLSENSOR 0x40000000 #define ATTN_BUTTON 0x80000000 +/* + * Controller SERR-INT Register + */ +#define GLOBAL_INTR_MASK (1 << 0) +#define GLOBAL_SERR_MASK (1 << 1) +#define COMMAND_INTR_MASK (1 << 2) +#define ARBITER_SERR_MASK (1 << 3) +#define COMMAND_DETECTED (1 << 16) +#define ARBITER_DETECTED (1 << 17) +#define SERR_INTR_RSVDZ_MASK 0xfffc0000 + /* * Logical Slot Register definitions */ @@ -1047,7 +1058,8 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs) /* Mask Global Interrupt Mask - see implementation note on p. 139 */ /* of SHPC spec rev 1.0*/ temp_dword = shpc_readl(ctrl, SERR_INTR_ENABLE); - temp_dword |= 0x00000001; + temp_dword |= GLOBAL_INTR_MASK; + temp_dword &= ~SERR_INTR_RSVDZ_MASK; shpc_writel(ctrl, SERR_INTR_ENABLE, temp_dword); intr_loc2 = shpc_readl(ctrl, INTR_LOC); @@ -1061,7 +1073,7 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs) * Detect bit in Controller SERR-INT register */ temp_dword = shpc_readl(ctrl, SERR_INTR_ENABLE); - temp_dword &= 0xfffdffff; + temp_dword &= ~SERR_INTR_RSVDZ_MASK; shpc_writel(ctrl, SERR_INTR_ENABLE, temp_dword); ctrl->cmd_busy = 0; wake_up_interruptible(&ctrl->queue); @@ -1105,7 +1117,7 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs) if (!shpchp_poll_mode) { /* Unmask Global Interrupt Mask */ temp_dword = shpc_readl(ctrl, SERR_INTR_ENABLE); - temp_dword &= 0xfffffffe; + temp_dword &= ~(GLOBAL_INTR_MASK | SERR_INTR_RSVDZ_MASK); shpc_writel(ctrl, SERR_INTR_ENABLE, temp_dword); } @@ -1374,7 +1386,9 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) /* Mask Global Interrupt Mask & Command Complete Interrupt Mask */ tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE); dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword); - tempdword = 0x0003000f; + tempdword |= (GLOBAL_INTR_MASK | GLOBAL_SERR_MASK | + COMMAND_INTR_MASK | ARBITER_SERR_MASK); + tempdword &= ~SERR_INTR_RSVDZ_MASK; shpc_writel(ctrl, SERR_INTR_ENABLE, tempdword); tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE); dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword); @@ -1452,7 +1466,8 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) if (!shpchp_poll_mode) { /* Unmask all general input interrupts and SERR */ tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE); - tempdword = 0x0000000a; + tempdword &= ~(GLOBAL_INTR_MASK | COMMAND_INTR_MASK | + SERR_INTR_RSVDZ_MASK); shpc_writel(ctrl, SERR_INTR_ENABLE, tempdword); tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE); dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword); -- cgit v1.2.3 From d49f2c49c39bbd0cb2069fe11c1630c709061037 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Wed, 3 May 2006 23:34:17 +0900 Subject: [PATCH] shpchp: Mask Global SERR and Intr at controller release time Global SERR and Interrupt should be masked at shpchp driver unload time. Signed-off-by: Kenji Kaneshige Cc: Kristen Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp_hpc.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index e2a8671545f..8b63f772a6f 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c @@ -798,7 +798,7 @@ static void hpc_release_ctlr(struct controller *ctrl) struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle; struct php_ctlr_state_s *p, *p_prev; int i; - u32 slot_reg; + u32 slot_reg, serr_int; DBG_ENTER_ROUTINE @@ -822,6 +822,15 @@ static void hpc_release_ctlr(struct controller *ctrl) cleanup_slots(ctrl); + /* + * Mask SERR and System Interrut generation + */ + serr_int = shpc_readl(ctrl, SERR_INTR_ENABLE); + serr_int |= (GLOBAL_INTR_MASK | GLOBAL_SERR_MASK | + COMMAND_INTR_MASK | ARBITER_SERR_MASK); + serr_int &= ~SERR_INTR_RSVDZ_MASK; + shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int); + if (shpchp_poll_mode) { del_timer(&php_ctlr->int_poll_timer); } else { -- cgit v1.2.3 From 82d5f4aaf182c306d2c2ef4d3a89d0fb8e386aa8 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Wed, 3 May 2006 23:42:04 +0900 Subject: [PATCH] shpchp: Create shpchpd at controller probe time The workqueue thread of shpchp driver should be created only when SHPC based hotplug slots are detected on the system. Signed-off-by: Kenji Kaneshige Cc: Kristen Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp_core.c | 8 -------- drivers/pci/hotplug/shpchp_hpc.c | 19 +++++++++++++++++++ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index 3be4d492ccc..a14e7de1984 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -491,16 +491,9 @@ static int __init shpcd_init(void) shpchp_poll_mode = 1; #endif - shpchp_wq = create_singlethread_workqueue("shpchpd"); - if (!shpchp_wq) - return -ENOMEM; - retval = pci_register_driver(&shpc_driver); dbg("%s: pci_register_driver = %d\n", __FUNCTION__, retval); info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); - if (retval) { - destroy_workqueue(shpchp_wq); - } return retval; } @@ -508,7 +501,6 @@ static void __exit shpcd_cleanup(void) { dbg("unload_shpchpd()\n"); pci_unregister_driver(&shpc_driver); - destroy_workqueue(shpchp_wq); info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); } diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index 8b63f772a6f..5e8f589d0b6 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c @@ -216,6 +216,8 @@ static struct php_ctlr_state_s *php_ctlr_list_head; /* HPC state linked list */ static int ctlr_seq_num = 0; /* Controller sequenc # */ static spinlock_t list_lock; +static atomic_t shpchp_num_controllers = ATOMIC_INIT(0); + static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs); static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds); @@ -866,6 +868,13 @@ static void hpc_release_ctlr(struct controller *ctrl) kfree(php_ctlr); + /* + * If this is the last controller to be released, destroy the + * shpchpd work queue + */ + if (atomic_dec_and_test(&shpchp_num_controllers)) + destroy_workqueue(shpchp_wq); + DBG_LEAVE_ROUTINE } @@ -1460,6 +1469,16 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) ctlr_seq_num++; + /* + * If this is the first controller to be initialized, + * initialize the shpchpd work queue + */ + if (atomic_add_return(1, &shpchp_num_controllers) == 1) { + shpchp_wq = create_singlethread_workqueue("shpchpd"); + if (!shpchp_wq) + return -ENOMEM; + } + /* * Unmask all event interrupts of all slots */ -- cgit v1.2.3 From 466ee36b62b4b294ecf68a2eee2e18c6ff8c9be4 Mon Sep 17 00:00:00 2001 From: Mike Habeck Date: Sat, 6 May 2006 09:01:59 -0500 Subject: [PATCH] SGI Hotplug: Incorrect power status This is a repost of a patch submitted by Prarit Bhargava on 01-19-06 that never got integrated. The get_power_status function is currently reporting a bitwise mapping of the slot if the slot is powered on. It should return 1 if powered on and 0 if powered off. Signed-off-by: Mike Habeck Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/sgi_hotplug.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c index cfee9db52c4..f31d83c2c63 100644 --- a/drivers/pci/hotplug/sgi_hotplug.c +++ b/drivers/pci/hotplug/sgi_hotplug.c @@ -461,10 +461,12 @@ static inline int get_power_status(struct hotplug_slot *bss_hotplug_slot, { struct slot *slot = bss_hotplug_slot->private; struct pcibus_info *pcibus_info; + u32 power; pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus); mutex_lock(&sn_hotplug_mutex); - *value = pcibus_info->pbi_enabled_devices & (1 << slot->device_num); + power = pcibus_info->pbi_enabled_devices & (1 << slot->device_num); + *value = power ? 1 : 0; mutex_unlock(&sn_hotplug_mutex); return 0; } -- cgit v1.2.3 From 56bfada3e1a25c0da6f4590a4b04c67ec10910c2 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Fri, 12 May 2006 11:22:24 +0900 Subject: [PATCH] pciehp: Replace pci_find_slot() with pci_get_slot() This patch replaces pci_find_slot() with pci_get_slot() in PCIEHP driver. This patch enables PCI Express Hotplug on the system which has multiple PCI domains. Signed-off-by: Kenji Kaneshige Cc: Kristen Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/pciehp_pci.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c index 6aa6a1be455..922b1831c68 100644 --- a/drivers/pci/hotplug/pciehp_pci.c +++ b/drivers/pci/hotplug/pciehp_pci.c @@ -204,10 +204,11 @@ int pciehp_configure_device(struct slot *p_slot) struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate; int num, fn; - dev = pci_find_slot(p_slot->bus, PCI_DEVFN(p_slot->device, 0)); + dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, 0)); if (dev) { err("Device %s already exists at %x:%x, cannot hot-add\n", pci_name(dev), p_slot->bus, p_slot->device); + pci_dev_put(dev); return -EINVAL; } @@ -243,18 +244,20 @@ int pciehp_unconfigure_device(struct slot *p_slot) int rc = 0; int j; u8 bctl = 0; + struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate; dbg("%s: bus/dev = %x/%x\n", __FUNCTION__, p_slot->bus, p_slot->device); for (j=0; j<8 ; j++) { - struct pci_dev* temp = pci_find_slot(p_slot->bus, + struct pci_dev* temp = pci_get_slot(parent, (p_slot->device << 3) | j); if (!temp) continue; if ((temp->class >> 16) == PCI_BASE_CLASS_DISPLAY) { err("Cannot remove display device %s\n", pci_name(temp)); + pci_dev_put(temp); continue; } if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) { @@ -262,10 +265,12 @@ int pciehp_unconfigure_device(struct slot *p_slot) if (bctl & PCI_BRIDGE_CTL_VGA) { err("Cannot remove display device %s\n", pci_name(temp)); + pci_dev_put(temp); continue; } } pci_remove_bus_device(temp); + pci_dev_put(temp); } /* * Some PCI Express root ports require fixup after hot-plug operation. -- cgit v1.2.3 From 6e33706b191ff8687f103a86de842b690fd8fb9d Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Fri, 12 May 2006 11:23:39 +0900 Subject: [PATCH] pciehp: Add missing pci_dev_put The PCIEHP driver leaks reference counter of pci_dev structures. This patch adds missing pci_dev_put() calls to PCIEHP driver. Signed-off-by: Kenji Kaneshige Cc: Kristen Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/pciehp_pci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c index 922b1831c68..854aaea09e4 100644 --- a/drivers/pci/hotplug/pciehp_pci.c +++ b/drivers/pci/hotplug/pciehp_pci.c @@ -225,6 +225,7 @@ int pciehp_configure_device(struct slot *p_slot) if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) { err("Cannot hot-add display device %s\n", pci_name(dev)); + pci_dev_put(dev); continue; } if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || @@ -232,6 +233,7 @@ int pciehp_configure_device(struct slot *p_slot) pciehp_add_bridge(dev); } program_fw_provided_values(dev); + pci_dev_put(dev); } pci_bus_assign_resources(parent); -- cgit v1.2.3 From 132066a9c84af6f5e8d893145a9c63f849143867 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Fri, 12 May 2006 13:39:45 +0900 Subject: [PATCH] pciehp: Implement get_address callback This patch implements .get_address callback of hotplug_slot_ops for PCIEHP driver. With this patch, we can see bus address of hotplug slots as follows: # cat /sys/bus/pci/slots/0010_0000/address 0000:0a:00 Signed-off-by: Kenji Kaneshige Cc: Kristen Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/pciehp_core.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 601cf9045b2..c67b7c3f1dd 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -69,6 +69,7 @@ static int get_power_status (struct hotplug_slot *slot, u8 *value); static int get_attention_status (struct hotplug_slot *slot, u8 *value); static int get_latch_status (struct hotplug_slot *slot, u8 *value); static int get_adapter_status (struct hotplug_slot *slot, u8 *value); +static int get_address (struct hotplug_slot *slot, u32 *value); static int get_max_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); static int get_cur_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); @@ -81,6 +82,7 @@ static struct hotplug_slot_ops pciehp_hotplug_slot_ops = { .get_attention_status = get_attention_status, .get_latch_status = get_latch_status, .get_adapter_status = get_adapter_status, + .get_address = get_address, .get_max_bus_speed = get_max_bus_speed, .get_cur_bus_speed = get_cur_bus_speed, }; @@ -331,6 +333,18 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) return 0; } +static int get_address(struct hotplug_slot *hotplug_slot, u32 *value) +{ + struct slot *slot = hotplug_slot->private; + struct pci_bus *bus = slot->ctrl->pci_dev->subordinate; + + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + + *value = (pci_domain_nr(bus) << 16) | (slot->bus << 8) | slot->device; + + return 0; +} + static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) { struct slot *slot = hotplug_slot->private; -- cgit v1.2.3 From d4fbf600666569c3921d12bdcfcfdb2cdb4fd5fb Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Fri, 12 May 2006 11:05:59 +0900 Subject: [PATCH] shpchp: Remove unnecessary hpc_ctlr_handle check This patch removes unnecessary error check for hpc_ctlr_handle. Signed-off-by: Kenji Kaneshige Cc: Kristen Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp_hpc.c | 197 ++++----------------------------------- 1 file changed, 16 insertions(+), 181 deletions(-) diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index 5e8f589d0b6..5135ceb404d 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c @@ -330,7 +330,6 @@ static inline int shpc_wait_cmd(struct controller *ctrl) static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) { - struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; struct controller *ctrl = slot->ctrl; u16 cmd_status; int retval = 0; @@ -341,12 +340,6 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) mutex_lock(&slot->ctrl->cmd_lock); - if (!php_ctlr) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - retval = -EINVAL; - goto out; - } - for (i = 0; i < 10; i++) { cmd_status = shpc_readw(ctrl, CMD_STATUS); @@ -401,11 +394,6 @@ static int hpc_check_cmd_status(struct controller *ctrl) int retval = 0; DBG_ENTER_ROUTINE - - if (!ctrl->hpc_ctlr_handle) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return -1; - } cmd_status = shpc_readw(ctrl, CMD_STATUS) & 0x000F; @@ -442,11 +430,6 @@ static int hpc_get_attention_status(struct slot *slot, u8 *status) DBG_ENTER_ROUTINE - if (!slot->ctrl->hpc_ctlr_handle) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return -1; - } - slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); state = (slot_reg & ATN_LED_STATE_MASK) >> ATN_LED_STATE_SHIFT; @@ -477,11 +460,6 @@ static int hpc_get_power_status(struct slot * slot, u8 *status) DBG_ENTER_ROUTINE - if (!slot->ctrl->hpc_ctlr_handle) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return -1; - } - slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); state = (slot_reg & SLOT_STATE_MASK) >> SLOT_STATE_SHIFT; @@ -512,11 +490,6 @@ static int hpc_get_latch_status(struct slot *slot, u8 *status) DBG_ENTER_ROUTINE - if (!slot->ctrl->hpc_ctlr_handle) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return -1; - } - slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); *status = !!(slot_reg & MRL_SENSOR); /* 0 -> close; 1 -> open */ @@ -532,11 +505,6 @@ static int hpc_get_adapter_status(struct slot *slot, u8 *status) DBG_ENTER_ROUTINE - if (!slot->ctrl->hpc_ctlr_handle) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return -1; - } - slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); state = (slot_reg & PRSNT_MASK) >> PRSNT_SHIFT; *status = (state != 0x3) ? 1 : 0; @@ -550,11 +518,6 @@ static int hpc_get_prog_int(struct slot *slot, u8 *prog_int) struct controller *ctrl = slot->ctrl; DBG_ENTER_ROUTINE - - if (!slot->ctrl->hpc_ctlr_handle) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return -1; - } *prog_int = shpc_readb(ctrl, PROG_INTERFACE); @@ -626,11 +589,6 @@ static int hpc_get_mode1_ECC_cap(struct slot *slot, u8 *mode) DBG_ENTER_ROUTINE - if (!slot->ctrl->hpc_ctlr_handle) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return -1; - } - pi = shpc_readb(ctrl, PROG_INTERFACE); sec_bus_status = shpc_readw(ctrl, SEC_BUS_CONFIG); @@ -653,11 +611,6 @@ static int hpc_query_power_fault(struct slot * slot) DBG_ENTER_ROUTINE - if (!slot->ctrl->hpc_ctlr_handle) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return -1; - } - slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); DBG_LEAVE_ROUTINE @@ -667,19 +620,7 @@ static int hpc_query_power_fault(struct slot * slot) static int hpc_set_attention_status(struct slot *slot, u8 value) { - struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; u8 slot_cmd = 0; - int rc = 0; - - if (!slot->ctrl->hpc_ctlr_handle) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return -1; - } - - if (slot->hp_slot >= php_ctlr->num_slots) { - err("%s: Invalid HPC slot number!\n", __FUNCTION__); - return -1; - } switch (value) { case 0 : @@ -695,76 +636,23 @@ static int hpc_set_attention_status(struct slot *slot, u8 value) return -1; } - shpc_write_cmd(slot, slot->hp_slot, slot_cmd); - - return rc; + return shpc_write_cmd(slot, slot->hp_slot, slot_cmd); } static void hpc_set_green_led_on(struct slot *slot) { - struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; - u8 slot_cmd; - - if (!slot->ctrl->hpc_ctlr_handle) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return ; - } - - if (slot->hp_slot >= php_ctlr->num_slots) { - err("%s: Invalid HPC slot number!\n", __FUNCTION__); - return ; - } - - slot_cmd = 0x04; - - shpc_write_cmd(slot, slot->hp_slot, slot_cmd); - - return; + shpc_write_cmd(slot, slot->hp_slot, 0x04); } static void hpc_set_green_led_off(struct slot *slot) { - struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; - u8 slot_cmd; - - if (!slot->ctrl->hpc_ctlr_handle) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return ; - } - - if (slot->hp_slot >= php_ctlr->num_slots) { - err("%s: Invalid HPC slot number!\n", __FUNCTION__); - return ; - } - - slot_cmd = 0x0C; - - shpc_write_cmd(slot, slot->hp_slot, slot_cmd); - - return; + shpc_write_cmd(slot, slot->hp_slot, 0x0c); } static void hpc_set_green_led_blink(struct slot *slot) { - struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; - u8 slot_cmd; - - if (!slot->ctrl->hpc_ctlr_handle) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return ; - } - - if (slot->hp_slot >= php_ctlr->num_slots) { - err("%s: Invalid HPC slot number!\n", __FUNCTION__); - return ; - } - - slot_cmd = 0x08; - - shpc_write_cmd(slot, slot->hp_slot, slot_cmd); - - return; + shpc_write_cmd(slot, slot->hp_slot, 0x08); } int shpc_get_ctlr_slot_config(struct controller *ctrl, @@ -778,11 +666,6 @@ int shpc_get_ctlr_slot_config(struct controller *ctrl, DBG_ENTER_ROUTINE - if (!ctrl->hpc_ctlr_handle) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return -1; - } - slot_config = shpc_readl(ctrl, SLOT_CONFIG); *first_device_num = (slot_config & FIRST_DEV_NUM) >> 8; *num_ctlr_slots = slot_config & SLOT_NUM; @@ -804,11 +687,6 @@ static void hpc_release_ctlr(struct controller *ctrl) DBG_ENTER_ROUTINE - if (!ctrl->hpc_ctlr_handle) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return ; - } - /* * Mask event interrupts and SERRs of all slots */ @@ -881,96 +759,53 @@ DBG_LEAVE_ROUTINE static int hpc_power_on_slot(struct slot * slot) { - struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; - u8 slot_cmd; - int retval = 0; + int retval; DBG_ENTER_ROUTINE - if (!slot->ctrl->hpc_ctlr_handle) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return -1; - } - - if (slot->hp_slot >= php_ctlr->num_slots) { - err("%s: Invalid HPC slot number!\n", __FUNCTION__); - return -1; - } - slot_cmd = 0x01; - - retval = shpc_write_cmd(slot, slot->hp_slot, slot_cmd); - + retval = shpc_write_cmd(slot, slot->hp_slot, 0x01); if (retval) { err("%s: Write command failed!\n", __FUNCTION__); - return -1; + return retval; } DBG_LEAVE_ROUTINE - return retval; + return 0; } static int hpc_slot_enable(struct slot * slot) { - struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; - u8 slot_cmd; - int retval = 0; + int retval; DBG_ENTER_ROUTINE - if (!slot->ctrl->hpc_ctlr_handle) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return -1; - } - - if (slot->hp_slot >= php_ctlr->num_slots) { - err("%s: Invalid HPC slot number!\n", __FUNCTION__); - return -1; - } /* 3A => Slot - Enable, Power Indicator - Blink, Attention Indicator - Off */ - slot_cmd = 0x3A; - - retval = shpc_write_cmd(slot, slot->hp_slot, slot_cmd); - + retval = shpc_write_cmd(slot, slot->hp_slot, 0x3a); if (retval) { err("%s: Write command failed!\n", __FUNCTION__); - return -1; + return retval; } DBG_LEAVE_ROUTINE - return retval; + return 0; } static int hpc_slot_disable(struct slot * slot) { - struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; - u8 slot_cmd; - int retval = 0; + int retval; DBG_ENTER_ROUTINE - if (!slot->ctrl->hpc_ctlr_handle) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return -1; - } - - if (slot->hp_slot >= php_ctlr->num_slots) { - err("%s: Invalid HPC slot number!\n", __FUNCTION__); - return -1; - } - /* 1F => Slot - Disable, Power Indicator - Off, Attention Indicator - On */ - slot_cmd = 0x1F; - - retval = shpc_write_cmd(slot, slot->hp_slot, slot_cmd); - + retval = shpc_write_cmd(slot, slot->hp_slot, 0x1f); if (retval) { err("%s: Write command failed!\n", __FUNCTION__); - return -1; + return retval; } DBG_LEAVE_ROUTINE - return retval; + return 0; } static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value) -- cgit v1.2.3 From c4cecc1937cafd8505151452a9f7eea876a5bd9c Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Fri, 12 May 2006 11:10:56 +0900 Subject: [PATCH] shpchp: Cleanup interrupt handler This patch cleans up the interrupt handler of shpchp driver. This patch has no functional changes. Signed-off-by: Kenji Kaneshige Cc: Kristen Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp_hpc.c | 125 ++++++++++++++++++--------------------- 1 file changed, 57 insertions(+), 68 deletions(-) diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index 5135ceb404d..e0f8c1bbaf1 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c @@ -90,6 +90,12 @@ #define MRLSENSOR 0x40000000 #define ATTN_BUTTON 0x80000000 +/* + * Interrupt Locator Register definitions + */ +#define CMD_INTR_PENDING (1 << 0) +#define SLOT_INTR_PENDING(i) (1 << (i + 1)) + /* * Controller SERR-INT Register */ @@ -218,7 +224,7 @@ static spinlock_t list_lock; static atomic_t shpchp_num_controllers = ATOMIC_INIT(0); -static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs); +static irqreturn_t shpc_isr(int irq, void *dev_id, struct pt_regs *regs); static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds); static int hpc_check_cmd_status(struct controller *ctrl); @@ -279,7 +285,7 @@ static void int_poll_timeout(unsigned long lphp_ctlr) } /* Poll for interrupt events. regs == NULL => polling */ - shpc_isr( 0, (void *)php_ctlr, NULL ); + shpc_isr(0, php_ctlr->callback_instance_id, NULL ); init_timer(&php_ctlr->int_poll_timer); if (!shpchp_poll_time) @@ -875,103 +881,86 @@ static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value) return retval; } -static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs) +static irqreturn_t shpc_isr(int irq, void *dev_id, struct pt_regs *regs) { - struct controller *ctrl = NULL; - struct php_ctlr_state_s *php_ctlr; - u8 schedule_flag = 0; - u32 temp_dword, intr_loc, intr_loc2; + struct controller *ctrl = (struct controller *)dev_id; + struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle; + u32 serr_int, slot_reg, intr_loc, intr_loc2; int hp_slot; - if (!dev_id) - return IRQ_NONE; - - if (!shpchp_poll_mode) { - ctrl = (struct controller *)dev_id; - php_ctlr = ctrl->hpc_ctlr_handle; - } else { - php_ctlr = (struct php_ctlr_state_s *) dev_id; - ctrl = (struct controller *)php_ctlr->callback_instance_id; - } - - if (!ctrl) - return IRQ_NONE; - - if (!php_ctlr || !php_ctlr->creg) - return IRQ_NONE; - /* Check to see if it was our interrupt */ intr_loc = shpc_readl(ctrl, INTR_LOC); - if (!intr_loc) return IRQ_NONE; + dbg("%s: intr_loc = %x\n",__FUNCTION__, intr_loc); if(!shpchp_poll_mode) { - /* Mask Global Interrupt Mask - see implementation note on p. 139 */ - /* of SHPC spec rev 1.0*/ - temp_dword = shpc_readl(ctrl, SERR_INTR_ENABLE); - temp_dword |= GLOBAL_INTR_MASK; - temp_dword &= ~SERR_INTR_RSVDZ_MASK; - shpc_writel(ctrl, SERR_INTR_ENABLE, temp_dword); + /* + * Mask Global Interrupt Mask - see implementation + * note on p. 139 of SHPC spec rev 1.0 + */ + serr_int = shpc_readl(ctrl, SERR_INTR_ENABLE); + serr_int |= GLOBAL_INTR_MASK; + serr_int &= ~SERR_INTR_RSVDZ_MASK; + shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int); intr_loc2 = shpc_readl(ctrl, INTR_LOC); dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2); } - if (intr_loc & 0x0001) { + if (intr_loc & CMD_INTR_PENDING) { /* * Command Complete Interrupt Pending * RO only - clear by writing 1 to the Command Completion * Detect bit in Controller SERR-INT register */ - temp_dword = shpc_readl(ctrl, SERR_INTR_ENABLE); - temp_dword &= ~SERR_INTR_RSVDZ_MASK; - shpc_writel(ctrl, SERR_INTR_ENABLE, temp_dword); + serr_int = shpc_readl(ctrl, SERR_INTR_ENABLE); + serr_int &= ~SERR_INTR_RSVDZ_MASK; + shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int); + ctrl->cmd_busy = 0; wake_up_interruptible(&ctrl->queue); } - if ((intr_loc = (intr_loc >> 1)) == 0) + if (!(intr_loc & ~CMD_INTR_PENDING)) goto out; for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) { - /* To find out which slot has interrupt pending */ - if ((intr_loc >> hp_slot) & 0x01) { - temp_dword = shpc_readl(ctrl, SLOT_REG(hp_slot)); - dbg("%s: Slot %x with intr, slot register = %x\n", - __FUNCTION__, hp_slot, temp_dword); - if ((php_ctlr->switch_change_callback) && - (temp_dword & MRL_CHANGE_DETECTED)) - schedule_flag += php_ctlr->switch_change_callback( - hp_slot, php_ctlr->callback_instance_id); - if ((php_ctlr->attention_button_callback) && - (temp_dword & BUTTON_PRESS_DETECTED)) - schedule_flag += php_ctlr->attention_button_callback( - hp_slot, php_ctlr->callback_instance_id); - if ((php_ctlr->presence_change_callback) && - (temp_dword & PRSNT_CHANGE_DETECTED)) - schedule_flag += php_ctlr->presence_change_callback( - hp_slot , php_ctlr->callback_instance_id); - if ((php_ctlr->power_fault_callback) && - (temp_dword & (ISO_PFAULT_DETECTED | CON_PFAULT_DETECTED))) - schedule_flag += php_ctlr->power_fault_callback( - hp_slot, php_ctlr->callback_instance_id); - - /* Clear all slot events */ - temp_dword &= ~SLOT_REG_RSVDZ_MASK; - shpc_writel(ctrl, SLOT_REG(hp_slot), temp_dword); - - intr_loc2 = shpc_readl(ctrl, INTR_LOC); - dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2); - } + /* To find out which slot has interrupt pending */ + if (!(intr_loc & SLOT_INTR_PENDING(hp_slot))) + continue; + + slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot)); + dbg("%s: Slot %x with intr, slot register = %x\n", + __FUNCTION__, hp_slot, slot_reg); + + if (slot_reg & MRL_CHANGE_DETECTED) + php_ctlr->switch_change_callback( + hp_slot, php_ctlr->callback_instance_id); + + if (slot_reg & BUTTON_PRESS_DETECTED) + php_ctlr->attention_button_callback( + hp_slot, php_ctlr->callback_instance_id); + + if (slot_reg & PRSNT_CHANGE_DETECTED) + php_ctlr->presence_change_callback( + hp_slot , php_ctlr->callback_instance_id); + + if (slot_reg & (ISO_PFAULT_DETECTED | CON_PFAULT_DETECTED)) + php_ctlr->power_fault_callback( + hp_slot, php_ctlr->callback_instance_id); + + /* Clear all slot events */ + slot_reg &= ~SLOT_REG_RSVDZ_MASK; + shpc_writel(ctrl, SLOT_REG(hp_slot), slot_reg); } out: if (!shpchp_poll_mode) { /* Unmask Global Interrupt Mask */ - temp_dword = shpc_readl(ctrl, SERR_INTR_ENABLE); - temp_dword &= ~(GLOBAL_INTR_MASK | SERR_INTR_RSVDZ_MASK); - shpc_writel(ctrl, SERR_INTR_ENABLE, temp_dword); + serr_int = shpc_readl(ctrl, SERR_INTR_ENABLE); + serr_int &= ~(GLOBAL_INTR_MASK | SERR_INTR_RSVDZ_MASK); + shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int); } return IRQ_HANDLED; -- cgit v1.2.3 From 4085399da3c2176ba8ed64e93a2722907d41df3f Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Fri, 12 May 2006 11:11:48 +0900 Subject: [PATCH] shpchp: Cleanup SHPC commands This patch cleans up the code related to issuing SHPC commands. This patch has no functional changes. Signed-off-by: Kenji Kaneshige Cc: Kristen Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp_hpc.c | 98 ++++++++++++++++++++-------------------- 1 file changed, 48 insertions(+), 50 deletions(-) diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index e0f8c1bbaf1..f6b3bf3ee7c 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c @@ -147,39 +147,37 @@ #define CON_PFAULT_SERR_MASK (1 << 30) #define SLOT_REG_RSVDZ_MASK (1 << 15) | (7 << 21) -/* SHPC 'write' operations/commands */ - -/* Slot operation - 0x00h to 0x3Fh */ - -#define NO_CHANGE 0x00 - -/* Slot state - Bits 0 & 1 of controller command register */ -#define SET_SLOT_PWR 0x01 -#define SET_SLOT_ENABLE 0x02 -#define SET_SLOT_DISABLE 0x03 - -/* Power indicator state - Bits 2 & 3 of controller command register*/ -#define SET_PWR_ON 0x04 -#define SET_PWR_BLINK 0x08 -#define SET_PWR_OFF 0x0C - -/* Attention indicator state - Bits 4 & 5 of controller command register*/ -#define SET_ATTN_ON 0x010 -#define SET_ATTN_BLINK 0x020 -#define SET_ATTN_OFF 0x030 - -/* Set bus speed/mode A - 0x40h to 0x47h */ -#define SETA_PCI_33MHZ 0x40 +/* + * SHPC Command Code definitnions + * + * Slot Operation 00h - 3Fh + * Set Bus Segment Speed/Mode A 40h - 47h + * Power-Only All Slots 48h + * Enable All Slots 49h + * Set Bus Segment Speed/Mode B (PI=2) 50h - 5Fh + * Reserved Command Codes 60h - BFh + * Vendor Specific Commands C0h - FFh + */ +#define SET_SLOT_PWR 0x01 /* Slot Operation */ +#define SET_SLOT_ENABLE 0x02 +#define SET_SLOT_DISABLE 0x03 +#define SET_PWR_ON 0x04 +#define SET_PWR_BLINK 0x08 +#define SET_PWR_OFF 0x0c +#define SET_ATTN_ON 0x10 +#define SET_ATTN_BLINK 0x20 +#define SET_ATTN_OFF 0x30 +#define SETA_PCI_33MHZ 0x40 /* Set Bus Segment Speed/Mode A */ #define SETA_PCI_66MHZ 0x41 #define SETA_PCIX_66MHZ 0x42 #define SETA_PCIX_100MHZ 0x43 #define SETA_PCIX_133MHZ 0x44 -#define RESERV_1 0x45 -#define RESERV_2 0x46 -#define RESERV_3 0x47 - -/* Set bus speed/mode B - 0x50h to 0x5fh */ -#define SETB_PCI_33MHZ 0x50 +#define SETA_RESERVED1 0x45 +#define SETA_RESERVED2 0x46 +#define SETA_RESERVED3 0x47 +#define SET_PWR_ONLY_ALL 0x48 /* Power-Only All Slots */ +#define SET_ENABLE_ALL 0x49 /* Enable All Slots */ +#define SETB_PCI_33MHZ 0x50 /* Set Bus Segment Speed/Mode B */ #define SETB_PCI_66MHZ 0x51 #define SETB_PCIX_66MHZ_PM 0x52 #define SETB_PCIX_100MHZ_PM 0x53 @@ -193,23 +191,21 @@ #define SETB_PCIX_66MHZ_533 0x5b #define SETB_PCIX_100MHZ_533 0x5c #define SETB_PCIX_133MHZ_533 0x5d +#define SETB_RESERVED1 0x5e +#define SETB_RESERVED2 0x5f - -/* Power-on all slots - 0x48h */ -#define SET_PWR_ON_ALL 0x48 - -/* Enable all slots - 0x49h */ -#define SET_ENABLE_ALL 0x49 - -/* SHPC controller command error code */ +/* + * SHPC controller command error code + */ #define SWITCH_OPEN 0x1 #define INVALID_CMD 0x2 #define INVALID_SPEED_MODE 0x4 -/* For accessing SHPC Working Register Set */ +/* + * For accessing SHPC Working Register Set via PCI Configuration Space + */ #define DWORD_SELECT 0x2 #define DWORD_DATA 0x4 -#define BASE_OFFSET 0x0 /* Field Offset in Logical Slot Register - byte boundary */ #define SLOT_EVENT_LATCH 0x2 @@ -630,13 +626,13 @@ static int hpc_set_attention_status(struct slot *slot, u8 value) switch (value) { case 0 : - slot_cmd = 0x30; /* OFF */ + slot_cmd = SET_ATTN_OFF; /* OFF */ break; case 1: - slot_cmd = 0x10; /* ON */ + slot_cmd = SET_ATTN_ON; /* ON */ break; case 2: - slot_cmd = 0x20; /* BLINK */ + slot_cmd = SET_ATTN_BLINK; /* BLINK */ break; default: return -1; @@ -648,17 +644,17 @@ static int hpc_set_attention_status(struct slot *slot, u8 value) static void hpc_set_green_led_on(struct slot *slot) { - shpc_write_cmd(slot, slot->hp_slot, 0x04); + shpc_write_cmd(slot, slot->hp_slot, SET_PWR_ON); } static void hpc_set_green_led_off(struct slot *slot) { - shpc_write_cmd(slot, slot->hp_slot, 0x0c); + shpc_write_cmd(slot, slot->hp_slot, SET_PWR_OFF); } static void hpc_set_green_led_blink(struct slot *slot) { - shpc_write_cmd(slot, slot->hp_slot, 0x08); + shpc_write_cmd(slot, slot->hp_slot, SET_PWR_BLINK); } int shpc_get_ctlr_slot_config(struct controller *ctrl, @@ -769,7 +765,7 @@ static int hpc_power_on_slot(struct slot * slot) DBG_ENTER_ROUTINE - retval = shpc_write_cmd(slot, slot->hp_slot, 0x01); + retval = shpc_write_cmd(slot, slot->hp_slot, SET_SLOT_PWR); if (retval) { err("%s: Write command failed!\n", __FUNCTION__); return retval; @@ -786,8 +782,9 @@ static int hpc_slot_enable(struct slot * slot) DBG_ENTER_ROUTINE - /* 3A => Slot - Enable, Power Indicator - Blink, Attention Indicator - Off */ - retval = shpc_write_cmd(slot, slot->hp_slot, 0x3a); + /* Slot - Enable, Power Indicator - Blink, Attention Indicator - Off */ + retval = shpc_write_cmd(slot, slot->hp_slot, + SET_SLOT_ENABLE | SET_PWR_BLINK | SET_ATTN_OFF); if (retval) { err("%s: Write command failed!\n", __FUNCTION__); return retval; @@ -803,8 +800,9 @@ static int hpc_slot_disable(struct slot * slot) DBG_ENTER_ROUTINE - /* 1F => Slot - Disable, Power Indicator - Off, Attention Indicator - On */ - retval = shpc_write_cmd(slot, slot->hp_slot, 0x1f); + /* Slot - Disable, Power Indicator - Off, Attention Indicator - On */ + retval = shpc_write_cmd(slot, slot->hp_slot, + SET_SLOT_DISABLE | SET_PWR_OFF | SET_ATTN_ON); if (retval) { err("%s: Write command failed!\n", __FUNCTION__); return retval; -- cgit v1.2.3 From f42639572680f4d69d9522f91c65e793ebeca098 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Fri, 12 May 2006 11:13:02 +0900 Subject: [PATCH] shpchp: Cleanup interrupt polling timer This patch cleans up the interrupt polling timer code in shpchp_hpc.c. This has no functional changes. Signed-off-by: Kenji Kaneshige Cc: Kristen Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp_hpc.c | 59 ++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 33 deletions(-) diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index f6b3bf3ee7c..3a8186c405f 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c @@ -221,8 +221,7 @@ static spinlock_t list_lock; static atomic_t shpchp_num_controllers = ATOMIC_INIT(0); static irqreturn_t shpc_isr(int irq, void *dev_id, struct pt_regs *regs); - -static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds); +static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int sec); static int hpc_check_cmd_status(struct controller *ctrl); static inline u8 shpc_readb(struct controller *ctrl, int reg) @@ -268,47 +267,41 @@ static inline int shpc_indirect_read(struct controller *ctrl, int index, return pci_read_config_dword(pdev, cap_offset + DWORD_DATA, value); } -/* This is the interrupt polling timeout function. */ +/* + * This is the interrupt polling timeout function. + */ static void int_poll_timeout(unsigned long lphp_ctlr) { - struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *)lphp_ctlr; - - DBG_ENTER_ROUTINE + struct php_ctlr_state_s *php_ctlr = + (struct php_ctlr_state_s *)lphp_ctlr; - if ( !php_ctlr ) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return; - } + DBG_ENTER_ROUTINE - /* Poll for interrupt events. regs == NULL => polling */ - shpc_isr(0, php_ctlr->callback_instance_id, NULL ); + /* Poll for interrupt events. regs == NULL => polling */ + shpc_isr(0, php_ctlr->callback_instance_id, NULL); - init_timer(&php_ctlr->int_poll_timer); + init_timer(&php_ctlr->int_poll_timer); if (!shpchp_poll_time) - shpchp_poll_time = 2; /* reset timer to poll in 2 secs if user doesn't specify at module installation*/ + shpchp_poll_time = 2; /* default polling interval is 2 sec */ - start_int_poll_timer(php_ctlr, shpchp_poll_time); - - return; + start_int_poll_timer(php_ctlr, shpchp_poll_time); + + DBG_LEAVE_ROUTINE } -/* This function starts the interrupt polling timer. */ -static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds) +/* + * This function starts the interrupt polling timer. + */ +static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int sec) { - if (!php_ctlr) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return; - } - - if ( ( seconds <= 0 ) || ( seconds > 60 ) ) - seconds = 2; /* Clamp to sane value */ - - php_ctlr->int_poll_timer.function = &int_poll_timeout; - php_ctlr->int_poll_timer.data = (unsigned long)php_ctlr; /* Instance data */ - php_ctlr->int_poll_timer.expires = jiffies + seconds * HZ; - add_timer(&php_ctlr->int_poll_timer); - - return; + /* Clamp to sane value */ + if ((sec <= 0) || (sec > 60)) + sec = 2; + + php_ctlr->int_poll_timer.function = &int_poll_timeout; + php_ctlr->int_poll_timer.data = (unsigned long)php_ctlr; + php_ctlr->int_poll_timer.expires = jiffies + sec * HZ; + add_timer(&php_ctlr->int_poll_timer); } static inline int shpc_wait_cmd(struct controller *ctrl) -- cgit v1.2.3 From ea83bc1dabdca9da643972b591259a7657459ff5 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Fri, 12 May 2006 11:12:23 +0900 Subject: [PATCH] shpchp: Remove Unused hpc_evelnt_lock This patch removes unused hpc_event_lock. This patch has no functional change. Signed-off-by: Kenji Kaneshige Cc: Kristen Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp_hpc.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index 3a8186c405f..45facaad39b 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c @@ -211,8 +211,6 @@ #define SLOT_EVENT_LATCH 0x2 #define SLOT_SERR_INT_MASK 0x3 -static spinlock_t hpc_event_lock; - DEFINE_DBG_BUFFER /* Debug string buffer for entire HPC defined here */ static struct php_ctlr_state_s *php_ctlr_list_head; /* HPC state linked list */ static int ctlr_seq_num = 0; /* Controller sequenc # */ @@ -1105,7 +1103,6 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) void *instance_id = ctrl; int rc, num_slots = 0; u8 hp_slot; - static int first = 1; u32 shpc_base_offset; u32 tempdword, slot_reg, slot_config; u8 i; @@ -1167,11 +1164,6 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) ctrl->mmio_size = 0x24 + 0x4 * num_slots; } - if (first) { - spin_lock_init(&hpc_event_lock); - first = 0; - } - info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, pdev->subsystem_vendor, pdev->subsystem_device); -- cgit v1.2.3 From 99ff124d1673a1e3f19061ebc82634608d1119ed Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Fri, 12 May 2006 11:13:50 +0900 Subject: [PATCH] shpchp: Cleanup improper info messages Current SHPCHP driver shows device number of slots in info messages, but it is useless and should be replaced with slot name. This patch replaces the device number shown in the info messages with the slot name. Signed-off-by: Kenji Kaneshige Cc: Kristen Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp.h | 6 +++--- drivers/pci/hotplug/shpchp_ctrl.c | 32 ++++++++++++++++---------------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index b70fddbce93..7208b95c6ee 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -168,9 +168,9 @@ struct controller { * error Messages */ #define msg_initialization_err "Initialization failure, error=%d\n" -#define msg_button_on "PCI slot #%d - powering on due to button press.\n" -#define msg_button_off "PCI slot #%d - powering off due to button press.\n" -#define msg_button_cancel "PCI slot #%d - action canceled due to button press.\n" +#define msg_button_on "PCI slot #%s - powering on due to button press.\n" +#define msg_button_off "PCI slot #%s - powering off due to button press.\n" +#define msg_button_cancel "PCI slot #%s - action canceled due to button press.\n" /* sysfs functions for the hotplug controller info */ extern void shpchp_create_ctrl_files (struct controller *ctrl); diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index 4e6381481c5..c39901dbff2 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -72,7 +72,7 @@ u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id) /* * Button pressed - See if need to TAKE ACTION!!! */ - info("Button pressed on Slot(%d)\n", ctrl->first_slot + hp_slot); + info("Button pressed on Slot(%s)\n", p_slot->name); event_type = INT_BUTTON_PRESS; queue_interrupt_event(p_slot, event_type); @@ -101,7 +101,7 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id) /* * Switch opened */ - info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot); + info("Latch open on Slot(%s)\n", p_slot->name); event_type = INT_SWITCH_OPEN; if (p_slot->pwr_save && p_slot->presence_save) { event_type = INT_POWER_FAULT; @@ -111,7 +111,7 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id) /* * Switch closed */ - info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot); + info("Latch close on Slot(%s)\n", p_slot->name); event_type = INT_SWITCH_CLOSE; } @@ -139,13 +139,13 @@ u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id) /* * Card Present */ - info("Card present on Slot(%d)\n", ctrl->first_slot + hp_slot); + info("Card present on Slot(%s)\n", p_slot->name); event_type = INT_PRESENCE_ON; } else { /* * Not Present */ - info("Card not present on Slot(%d)\n", ctrl->first_slot + hp_slot); + info("Card not present on Slot(%s)\n", p_slot->name); event_type = INT_PRESENCE_OFF; } @@ -169,14 +169,14 @@ u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id) /* * Power fault Cleared */ - info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot); + info("Power fault cleared on Slot(%s)\n", p_slot->name); p_slot->status = 0x00; event_type = INT_POWER_FAULT_CLEAR; } else { /* * Power fault */ - info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot); + info("Power fault on Slot(%s)\n", p_slot->name); event_type = INT_POWER_FAULT; /* set power fault status for this board */ p_slot->status = 0xFF; @@ -496,10 +496,10 @@ static void handle_button_press_event(struct slot *p_slot) p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (getstatus) { p_slot->state = BLINKINGOFF_STATE; - info(msg_button_off, p_slot->number); + info(msg_button_off, p_slot->name); } else { p_slot->state = BLINKINGON_STATE; - info(msg_button_on, p_slot->number); + info(msg_button_on, p_slot->name); } /* blink green LED and turn off amber */ p_slot->hpc_ops->green_led_blink(p_slot); @@ -522,7 +522,7 @@ static void handle_button_press_event(struct slot *p_slot) else p_slot->hpc_ops->green_led_off(p_slot); p_slot->hpc_ops->set_attention_status(p_slot, 0); - info(msg_button_cancel, p_slot->number); + info(msg_button_cancel, p_slot->name); p_slot->state = STATIC_STATE; break; case POWEROFF_STATE: @@ -575,17 +575,17 @@ static int shpchp_enable_slot (struct slot *p_slot) mutex_lock(&p_slot->ctrl->crit_sect); rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); if (rc || !getstatus) { - info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); + info("No adapter on slot(%s)\n", p_slot->name); goto out; } rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); if (rc || getstatus) { - info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); + info("Latch open on slot(%s)\n", p_slot->name); goto out; } rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (rc || getstatus) { - info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number); + info("Already enabled on slot(%s)\n", p_slot->name); goto out; } @@ -634,17 +634,17 @@ static int shpchp_disable_slot (struct slot *p_slot) rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); if (rc || !getstatus) { - info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); + info("No adapter on slot(%s)\n", p_slot->name); goto out; } rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); if (rc || getstatus) { - info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); + info("Latch open on slot(%s)\n", p_slot->name); goto out; } rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (rc || !getstatus) { - info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number); + info("Already disabled slot(%s)\n", p_slot->name); goto out; } -- cgit v1.2.3 From 9df7fde52c33075b9f9148ee31215c03824fcc38 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Thu, 1 Jun 2006 11:41:44 +0200 Subject: [PATCH] PCI Hotplug: fake NULL pointer dereferences in IBM Hot Plug Controller Driver Remove checks for value, since the hotplug core always provides a valid value. Signed-off-by: Eric Sesterhenn Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/ibmphp_core.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c index e13d5b87241..59392946c2b 100644 --- a/drivers/pci/hotplug/ibmphp_core.c +++ b/drivers/pci/hotplug/ibmphp_core.c @@ -285,7 +285,7 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 * value) (ulong) hotplug_slot, (ulong) value); ibmphp_lock_operations(); - if (hotplug_slot && value) { + if (hotplug_slot) { pslot = hotplug_slot->private; if (pslot) { memcpy(&myslot, pslot, sizeof(struct slot)); @@ -315,7 +315,7 @@ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 * value) debug("get_latch_status - Entry hotplug_slot[%lx] pvalue[%lx]\n", (ulong) hotplug_slot, (ulong) value); ibmphp_lock_operations(); - if (hotplug_slot && value) { + if (hotplug_slot) { pslot = hotplug_slot->private; if (pslot) { memcpy(&myslot, pslot, sizeof(struct slot)); @@ -342,7 +342,7 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 * value) debug("get_power_status - Entry hotplug_slot[%lx] pvalue[%lx]\n", (ulong) hotplug_slot, (ulong) value); ibmphp_lock_operations(); - if (hotplug_slot && value) { + if (hotplug_slot) { pslot = hotplug_slot->private; if (pslot) { memcpy(&myslot, pslot, sizeof(struct slot)); @@ -369,7 +369,7 @@ static int get_adapter_present(struct hotplug_slot *hotplug_slot, u8 * value) debug("get_adapter_status - Entry hotplug_slot[%lx] pvalue[%lx]\n", (ulong) hotplug_slot, (ulong) value); ibmphp_lock_operations(); - if (hotplug_slot && value) { + if (hotplug_slot) { pslot = hotplug_slot->private; if (pslot) { memcpy(&myslot, pslot, sizeof(struct slot)); @@ -401,7 +401,7 @@ static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_spe ibmphp_lock_operations(); - if (hotplug_slot && value) { + if (hotplug_slot) { pslot = hotplug_slot->private; if (pslot) { rc = 0; @@ -441,7 +441,7 @@ static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_spe ibmphp_lock_operations(); - if (hotplug_slot && value) { + if (hotplug_slot) { pslot = hotplug_slot->private; if (pslot) { rc = get_cur_bus_info(&pslot); -- cgit v1.2.3 From 9c64f9774805ba5d5ad4129899bdd822f61874e9 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Tue, 9 May 2006 00:50:31 -0700 Subject: [PATCH] PCI Hotplug: Fix recovery path from errors during pcie_init() Signed-off-by: Jan Beulich Cc: Kristen Accardi Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/pciehp_hpc.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 081dfef4fe6..d77138ecb09 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -1471,7 +1471,7 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) rc = hp_register_read_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word); if (rc) { err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); - goto abort_free_ctlr; + goto abort_free_irq; } intr_enable = intr_enable | PRSN_DETECT_ENABLE; @@ -1497,19 +1497,19 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) rc = hp_register_write_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word); if (rc) { err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); - goto abort_free_ctlr; + goto abort_free_irq; } rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status); if (rc) { err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); - goto abort_free_ctlr; + goto abort_disable_intr; } temp_word = 0x1F; /* Clear all events */ rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word); if (rc) { err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); - goto abort_free_ctlr; + goto abort_disable_intr; } if (pciehp_force) { @@ -1518,7 +1518,7 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) } else { rc = pciehp_get_hp_hw_control_from_firmware(ctrl->pci_dev); if (rc) - goto abort_free_ctlr; + goto abort_disable_intr; } /* Add this HPC instance into the HPC list */ @@ -1545,6 +1545,21 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) return 0; /* We end up here for the many possible ways to fail this API. */ +abort_disable_intr: + rc = hp_register_read_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word); + if (!rc) { + temp_word &= ~(intr_enable | HP_INTR_ENABLE); + rc = hp_register_write_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word); + } + if (rc) + err("%s : disabling interrupts failed\n", __FUNCTION__); + +abort_free_irq: + if (pciehp_poll_mode) + del_timer_sync(&php_ctlr->int_poll_timer); + else + free_irq(php_ctlr->irq, ctrl); + abort_free_ctlr: pcie_cap_base = saved_cap_base; kfree(php_ctlr); -- cgit v1.2.3 From 75c3628db75c573870379094a5f90f690ee99b76 Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Thu, 8 Jun 2006 13:55:42 -0700 Subject: [SCSI] aacraid: Update supported product information Received From Mark Salyzyn Some of the cards product names changed. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley --- Documentation/scsi/aacraid.txt | 8 ++++---- drivers/scsi/aacraid/linit.c | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Documentation/scsi/aacraid.txt b/Documentation/scsi/aacraid.txt index 820fd079350..be55670851a 100644 --- a/Documentation/scsi/aacraid.txt +++ b/Documentation/scsi/aacraid.txt @@ -24,10 +24,10 @@ Supported Cards/Chipsets 9005:0285:9005:0296 Adaptec 2240S (SabreExpress) 9005:0285:9005:0290 Adaptec 2410SA (Jaguar) 9005:0285:9005:0293 Adaptec 21610SA (Corsair-16) - 9005:0285:103c:3227 Adaptec 2610SA (Bearcat) + 9005:0285:103c:3227 Adaptec 2610SA (Bearcat HP release) 9005:0285:9005:0292 Adaptec 2810SA (Corsair-8) 9005:0285:9005:0294 Adaptec Prowler - 9005:0286:9005:029d Adaptec 2420SA (Intruder) + 9005:0286:9005:029d Adaptec 2420SA (Intruder HP release) 9005:0286:9005:029c Adaptec 2620SA (Intruder) 9005:0286:9005:029b Adaptec 2820SA (Intruder) 9005:0286:9005:02a7 Adaptec 2830SA (Skyray) @@ -38,7 +38,7 @@ Supported Cards/Chipsets 9005:0285:9005:0297 Adaptec 4005SAS (AvonPark) 9005:0285:9005:0299 Adaptec 4800SAS (Marauder-X) 9005:0285:9005:029a Adaptec 4805SAS (Marauder-E) - 9005:0286:9005:02a2 Adaptec 4810SAS (Hurricane) + 9005:0286:9005:02a2 Adaptec 3800SAS (Hurricane44) 1011:0046:9005:0364 Adaptec 5400S (Mustang) 1011:0046:9005:0365 Adaptec 5400S (Mustang) 9005:0283:9005:0283 Adaptec Catapult (3210S with arc firmware) @@ -72,7 +72,7 @@ Supported Cards/Chipsets 9005:0286:9005:02a1 ICP ICP9087MA (Lancer) 9005:0286:9005:02a4 ICP ICP9085LI (Marauder-X) 9005:0286:9005:02a5 ICP ICP5085BR (Marauder-E) - 9005:0286:9005:02a3 ICP ICP5085AU (Hurricane) + 9005:0286:9005:02a3 ICP ICP5445AU (Hurricane44) 9005:0286:9005:02a6 ICP ICP9067MA (Intruder-6) 9005:0286:9005:02a9 ICP ICP5087AU (Skyray) 9005:0286:9005:02aa ICP ICP5047AU (Skyray) diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 03fe2abcc4f..e42a479ce64 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -119,7 +119,7 @@ static struct pci_device_id aac_pci_tbl[] = { { 0x9005, 0x0286, 0x9005, 0x029f, 0, 0, 26 }, /* ICP9014R0 (Lancer) */ { 0x9005, 0x0286, 0x9005, 0x02a0, 0, 0, 27 }, /* ICP9047MA (Lancer) */ { 0x9005, 0x0286, 0x9005, 0x02a1, 0, 0, 28 }, /* ICP9087MA (Lancer) */ - { 0x9005, 0x0286, 0x9005, 0x02a3, 0, 0, 29 }, /* ICP5085AU (Hurricane) */ + { 0x9005, 0x0286, 0x9005, 0x02a3, 0, 0, 29 }, /* ICP5445AU (Hurricane44) */ { 0x9005, 0x0285, 0x9005, 0x02a4, 0, 0, 30 }, /* ICP9085LI (Marauder-X) */ { 0x9005, 0x0285, 0x9005, 0x02a5, 0, 0, 31 }, /* ICP5085BR (Marauder-E) */ { 0x9005, 0x0286, 0x9005, 0x02a6, 0, 0, 32 }, /* ICP9067MA (Intruder-6) */ @@ -143,7 +143,7 @@ static struct pci_device_id aac_pci_tbl[] = { { 0x9005, 0x0285, 0x9005, 0x0298, 0, 0, 48 }, /* ASR-4000SAS (BlackBird) */ { 0x9005, 0x0285, 0x9005, 0x0299, 0, 0, 49 }, /* ASR-4800SAS (Marauder-X) */ { 0x9005, 0x0285, 0x9005, 0x029a, 0, 0, 50 }, /* ASR-4805SAS (Marauder-E) */ - { 0x9005, 0x0286, 0x9005, 0x02a2, 0, 0, 51 }, /* ASR-4810SAS (Hurricane */ + { 0x9005, 0x0286, 0x9005, 0x02a2, 0, 0, 51 }, /* ASR-3800SAS (Hurricane44) */ { 0x9005, 0x0285, 0x1028, 0x0287, 0, 0, 52 }, /* Perc 320/DC*/ { 0x1011, 0x0046, 0x9005, 0x0365, 0, 0, 53 }, /* Adaptec 5400S (Mustang)*/ @@ -195,7 +195,7 @@ static struct aac_driver_ident aac_drivers[] = { { aac_rkt_init, "aacraid", "ICP ", "ICP9014R0 ", 1 }, /* ICP9014R0 (Lancer) */ { aac_rkt_init, "aacraid", "ICP ", "ICP9047MA ", 1 }, /* ICP9047MA (Lancer) */ { aac_rkt_init, "aacraid", "ICP ", "ICP9087MA ", 1 }, /* ICP9087MA (Lancer) */ - { aac_rkt_init, "aacraid", "ICP ", "ICP5085AU ", 1 }, /* ICP5085AU (Hurricane) */ + { aac_rkt_init, "aacraid", "ICP ", "ICP5445AU ", 1 }, /* ICP5445AU (Hurricane44) */ { aac_rx_init, "aacraid", "ICP ", "ICP9085LI ", 1 }, /* ICP9085LI (Marauder-X) */ { aac_rx_init, "aacraid", "ICP ", "ICP5085BR ", 1 }, /* ICP5085BR (Marauder-E) */ { aac_rkt_init, "aacraid", "ICP ", "ICP9067MA ", 1 }, /* ICP9067MA (Intruder-6) */ @@ -217,7 +217,7 @@ static struct aac_driver_ident aac_drivers[] = { { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4000SAS ", 1 }, /* ASR-4000SAS (BlackBird & AvonPark) */ { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4800SAS ", 1 }, /* ASR-4800SAS (Marauder-X) */ { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4805SAS ", 1 }, /* ASR-4805SAS (Marauder-E) */ - { aac_rkt_init, "aacraid", "ADAPTEC ", "ASR-4810SAS ", 1 }, /* ASR-4810SAS (Hurricane) */ + { aac_rkt_init, "aacraid", "ADAPTEC ", "ASR-3800SAS ", 1 }, /* ASR-3800SAS (Hurricane44) */ { aac_rx_init, "percraid", "DELL ", "PERC 320/DC ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Perc 320/DC*/ { aac_sa_init, "aacraid", "ADAPTEC ", "Adaptec 5400S ", 4, AAC_QUIRK_34SG }, /* Adaptec 5400S (Mustang)*/ -- cgit v1.2.3 From a623e14dafe72329dd1defe36ee2cd4ff4b2e6f1 Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Thu, 8 Jun 2006 13:55:57 -0700 Subject: [SCSI] aacraid: small misc. cleanups Received from Mark Salyzyn Spelling correction, orphaned comment removal & update branch name. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley --- drivers/scsi/aacraid/aacraid.h | 6 +----- drivers/scsi/aacraid/comminit.c | 2 +- drivers/scsi/aacraid/dpcsup.c | 4 ++-- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index e6b41dbbec8..d0eecd4bec8 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -12,7 +12,7 @@ #ifndef AAC_DRIVER_BUILD # define AAC_DRIVER_BUILD 2409 -# define AAC_DRIVER_BRANCH "-mh1" +# define AAC_DRIVER_BRANCH "-mh2" #endif #define MAXIMUM_NUM_CONTAINERS 32 @@ -821,10 +821,6 @@ struct fib { fib_callback callback; void *callback_data; u32 flags; // u32 dmb was ulong - /* - * The following is used to put this fib context onto the - * Outstanding I/O queue. - */ /* * And for the internal issue/reply queues (we may be able * to merge these two) diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c index 1d43c17642c..35b0a6ebd3f 100644 --- a/drivers/scsi/aacraid/comminit.c +++ b/drivers/scsi/aacraid/comminit.c @@ -103,7 +103,7 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co * This assumes the memory is mapped zero->n, which isnt * always true on real computers. It also has some slight problems * with the GART on x86-64. I've btw never tried DMA from PCI space - * on this platform but don't be suprised if its problematic. + * on this platform but don't be surprised if its problematic. */ #ifndef CONFIG_GART_IOMMU if ((num_physpages << (PAGE_SHIFT - 12)) <= AAC_MAX_HOSTPHYSMEMPAGES) { diff --git a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c index bd6a67dd250..b2a5c7262f3 100644 --- a/drivers/scsi/aacraid/dpcsup.c +++ b/drivers/scsi/aacraid/dpcsup.c @@ -85,9 +85,9 @@ unsigned int aac_response_normal(struct aac_queue * q) * continue. The caller has already been notified that * the fib timed out. */ - if (!(fib->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) { + if (!(fib->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) dev->queues->queue[AdapNormCmdQueue].numpending--; - } else { + else { printk(KERN_WARNING "aacraid: FIB timeout (%x).\n", fib->flags); printk(KERN_DEBUG"aacraid: hwfib=%p fib index=%i fib=%p\n",hwfib, hwfib->header.SenderData,fib); continue; -- cgit v1.2.3 From 4f2ddba39a550eba9233d9f0e8309092da0ba293 Mon Sep 17 00:00:00 2001 From: HighPoint Linux Team Date: Wed, 14 Jun 2006 16:50:57 +0800 Subject: [SCSI] hptiop: HighPoint RocketRAID 3xxx controller driver Updates: - don't bypass SYNCHRONIZE_CACHE command - return SCSI_MLQUEUE_HOST_BUSY when no free request slots - move scsi_remove_host() to the begin of hpt_remove(), or it will not work after resources being released. Signed-off-by: HighPoint Linux Team Signed-off-by: James Bottomley --- drivers/scsi/hptiop.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c index 8302f3ba31c..a96751cad8c 100644 --- a/drivers/scsi/hptiop.c +++ b/drivers/scsi/hptiop.c @@ -504,19 +504,10 @@ static int hptiop_queuecommand(struct scsi_cmnd *scp, BUG_ON(!done); scp->scsi_done = done; - /* - * hptiop_shutdown will flash controller cache. - */ - if (scp->cmnd[0] == SYNCHRONIZE_CACHE) { - scp->result = DID_OK<<16; - goto cmd_done; - } - _req = get_req(hba); if (_req == NULL) { dprintk("hptiop_queuecmd : no free req\n"); - scp->result = DID_BUS_BUSY << 16; - goto cmd_done; + return SCSI_MLQUEUE_HOST_BUSY; } _req->scp = scp; @@ -1429,6 +1420,8 @@ static void hptiop_remove(struct pci_dev *pcidev) dprintk("scsi%d: hptiop_remove\n", hba->host->host_no); + scsi_remove_host(host); + spin_lock(&hptiop_hba_list_lock); list_del_init(&hba->link); spin_unlock(&hptiop_hba_list_lock); @@ -1448,7 +1441,6 @@ static void hptiop_remove(struct pci_dev *pcidev) pci_set_drvdata(hba->pcidev, NULL); pci_disable_device(hba->pcidev); - scsi_remove_host(host); scsi_host_put(host); } -- cgit v1.2.3 From 6db874fbdbedba5e15e76cc03b42f52ea70338c0 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Tue, 13 Jun 2006 21:40:34 -0500 Subject: [SCSI] hptiop: don't use cmnd->bufflen use cmnd->request_bufflen instead. Signed-off-by: James Bottomley --- drivers/scsi/hptiop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c index a96751cad8c..f77808329e7 100644 --- a/drivers/scsi/hptiop.c +++ b/drivers/scsi/hptiop.c @@ -545,7 +545,7 @@ static int hptiop_queuecommand(struct scsi_cmnd *scp, req->header.context = cpu_to_le32(IOPMU_QUEUE_ADDR_HOST_BIT | (u32)_req->index); req->header.context_hi32 = 0; - req->dataxfer_length = cpu_to_le32(scp->bufflen); + req->dataxfer_length = cpu_to_le32(scp->request_bufflen); req->channel = scp->device->channel; req->target = scp->device->id; req->lun = scp->device->lun; -- cgit v1.2.3 From 67d59dfdeb21df2c16dcd478b66177e91178ecd0 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Tue, 13 Jun 2006 21:31:19 -0500 Subject: [SCSI] 53c700: remove reliance on deprecated cmnd fields This one's quite tricky. The 53c700 uses the now deprecated fields of the command structure for saving the prior command when it does autosense. To fix this, we have to add extra fields to the LUN to accommodate a copy of the real command. Signed-off-by: James Bottomley --- drivers/scsi/53c700.c | 86 ++++++++++++++++++++++++++++----------------------- drivers/scsi/53c700.h | 2 ++ 2 files changed, 49 insertions(+), 39 deletions(-) diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c index 4958c3b93c3..3c683dc2354 100644 --- a/drivers/scsi/53c700.c +++ b/drivers/scsi/53c700.c @@ -183,6 +183,10 @@ STATIC struct device_attribute *NCR_700_dev_attrs[]; STATIC struct scsi_transport_template *NCR_700_transport_template = NULL; +struct NCR_700_sense { + unsigned char cmnd[MAX_COMMAND_SIZE]; +}; + static char *NCR_700_phase[] = { "", "after selection", @@ -537,6 +541,7 @@ find_empty_slot(struct NCR_700_Host_Parameters *hostdata) * finish routine. If we cannot queue the command when it * is properly build, we then change to NCR_700_SLOT_QUEUED */ slot->state = NCR_700_SLOT_BUSY; + slot->flags = 0; hostdata->command_slot_count++; return slot; @@ -586,7 +591,7 @@ NCR_700_unmap(struct NCR_700_Host_Parameters *hostdata, struct scsi_cmnd *SCp, if(SCp->sc_data_direction != DMA_NONE && SCp->sc_data_direction != DMA_BIDIRECTIONAL) { if(SCp->use_sg) { - dma_unmap_sg(hostdata->dev, SCp->buffer, + dma_unmap_sg(hostdata->dev, SCp->request_buffer, SCp->use_sg, SCp->sc_data_direction); } else { dma_unmap_single(hostdata->dev, slot->dma_handle, @@ -608,30 +613,23 @@ NCR_700_scsi_done(struct NCR_700_Host_Parameters *hostdata, (struct NCR_700_command_slot *)SCp->host_scribble; NCR_700_unmap(hostdata, SCp, slot); - dma_unmap_single(hostdata->dev, slot->pCmd, - sizeof(SCp->cmnd), DMA_TO_DEVICE); - if(SCp->cmnd[0] == REQUEST_SENSE && SCp->cmnd[6] == NCR_700_INTERNAL_SENSE_MAGIC) { + if (slot->flags == NCR_700_FLAG_AUTOSENSE) { + struct NCR_700_sense *sense = SCp->device->hostdata; #ifdef NCR_700_DEBUG printk(" ORIGINAL CMD %p RETURNED %d, new return is %d sense is\n", SCp, SCp->cmnd[7], result); scsi_print_sense("53c700", SCp); #endif + dma_unmap_single(hostdata->dev, slot->dma_handle, sizeof(SCp->sense_buffer), DMA_FROM_DEVICE); /* restore the old result if the request sense was * successful */ if(result == 0) - result = SCp->cmnd[7]; - /* now restore the original command */ - memcpy((void *) SCp->cmnd, (void *) SCp->data_cmnd, - sizeof(SCp->data_cmnd)); - SCp->request_buffer = SCp->buffer; - SCp->request_bufflen = SCp->bufflen; - SCp->use_sg = SCp->old_use_sg; - SCp->cmd_len = SCp->old_cmd_len; - SCp->sc_data_direction = SCp->sc_old_data_direction; - SCp->underflow = SCp->old_underflow; - - } + result = sense->cmnd[7]; + } else + dma_unmap_single(hostdata->dev, slot->pCmd, + sizeof(SCp->cmnd), DMA_TO_DEVICE); + free_slot(slot, hostdata); #ifdef NCR_700_DEBUG if(NCR_700_get_depth(SCp->device) == 0 || @@ -979,6 +977,7 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp, "broken device is looping in contingent allegiance: ignoring\n"); NCR_700_scsi_done(hostdata, SCp, hostdata->status[0]); } else { + struct NCR_700_sense *sense = SCp->device->hostdata; #ifdef NCR_DEBUG scsi_print_command(SCp); printk(" cmd %p has status %d, requesting sense\n", @@ -992,27 +991,25 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp, * data associated with the command * here */ NCR_700_unmap(hostdata, SCp, slot); - - SCp->cmnd[0] = REQUEST_SENSE; - SCp->cmnd[1] = (SCp->device->lun & 0x7) << 5; - SCp->cmnd[2] = 0; - SCp->cmnd[3] = 0; - SCp->cmnd[4] = sizeof(SCp->sense_buffer); - SCp->cmnd[5] = 0; - SCp->cmd_len = 6; + dma_unmap_single(hostdata->dev, slot->pCmd, + sizeof(SCp->cmnd), + DMA_TO_DEVICE); + + sense->cmnd[0] = REQUEST_SENSE; + sense->cmnd[1] = (SCp->device->lun & 0x7) << 5; + sense->cmnd[2] = 0; + sense->cmnd[3] = 0; + sense->cmnd[4] = sizeof(SCp->sense_buffer); + sense->cmnd[5] = 0; /* Here's a quiet hack: the * REQUEST_SENSE command is six bytes, * so store a flag indicating that * this was an internal sense request * and the original status at the end * of the command */ - SCp->cmnd[6] = NCR_700_INTERNAL_SENSE_MAGIC; - SCp->cmnd[7] = hostdata->status[0]; - SCp->use_sg = 0; - SCp->sc_data_direction = DMA_FROM_DEVICE; - dma_sync_single_for_device(hostdata->dev, slot->pCmd, - SCp->cmd_len, DMA_TO_DEVICE); - SCp->request_bufflen = sizeof(SCp->sense_buffer); + sense->cmnd[6] = NCR_700_INTERNAL_SENSE_MAGIC; + sense->cmnd[7] = hostdata->status[0]; + slot->pCmd = dma_map_single(hostdata->dev, sense->cmnd, sizeof(sense->cmnd), DMA_TO_DEVICE); slot->dma_handle = dma_map_single(hostdata->dev, SCp->sense_buffer, sizeof(SCp->sense_buffer), DMA_FROM_DEVICE); slot->SG[0].ins = bS_to_host(SCRIPT_MOVE_DATA_IN | sizeof(SCp->sense_buffer)); slot->SG[0].pAddr = bS_to_host(slot->dma_handle); @@ -1024,6 +1021,7 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp, /* queue the command for reissue */ slot->state = NCR_700_SLOT_QUEUED; + slot->flags = NCR_700_FLAG_AUTOSENSE; hostdata->state = NCR_700_HOST_FREE; hostdata->cmd = NULL; } @@ -1244,7 +1242,7 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp, if(SCp->use_sg) { for(i = 0; i < SCp->use_sg + 1; i++) { - printk(KERN_INFO " SG[%d].length = %d, move_insn=%08x, addr %08x\n", i, ((struct scatterlist *)SCp->buffer)[i].length, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].ins, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].pAddr); + printk(KERN_INFO " SG[%d].length = %d, move_insn=%08x, addr %08x\n", i, ((struct scatterlist *)SCp->request_buffer)[i].length, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].ins, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].pAddr); } } } @@ -1403,12 +1401,14 @@ NCR_700_start_command(struct scsi_cmnd *SCp) /* keep interrupts disabled until we have the command correctly * set up so we cannot take a selection interrupt */ - hostdata->msgout[0] = NCR_700_identify(SCp->cmnd[0] != REQUEST_SENSE, + hostdata->msgout[0] = NCR_700_identify((SCp->cmnd[0] != REQUEST_SENSE && + slot->flags != NCR_700_FLAG_AUTOSENSE), SCp->device->lun); /* for INQUIRY or REQUEST_SENSE commands, we cannot be sure * if the negotiated transfer parameters still hold, so * always renegotiate them */ - if(SCp->cmnd[0] == INQUIRY || SCp->cmnd[0] == REQUEST_SENSE) { + if(SCp->cmnd[0] == INQUIRY || SCp->cmnd[0] == REQUEST_SENSE || + slot->flags == NCR_700_FLAG_AUTOSENSE) { NCR_700_clear_flag(SCp->device, NCR_700_DEV_NEGOTIATED_SYNC); } @@ -1417,7 +1417,8 @@ NCR_700_start_command(struct scsi_cmnd *SCp) * will refuse all tags, so send the request sense as untagged * */ if((hostdata->tag_negotiated & (1<tag != SCSI_NO_TAG && SCp->cmnd[0] != REQUEST_SENSE)) { + && (slot->tag != SCSI_NO_TAG && SCp->cmnd[0] != REQUEST_SENSE && + slot->flags != NCR_700_FLAG_AUTOSENSE)) { count += scsi_populate_tag_msg(SCp, &hostdata->msgout[count]); } @@ -1863,8 +1864,9 @@ NCR_700_queuecommand(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *)) __u32 count = 0; if(SCp->use_sg) { - sg_count = dma_map_sg(hostdata->dev, SCp->buffer, - SCp->use_sg, direction); + sg_count = dma_map_sg(hostdata->dev, + SCp->request_buffer, SCp->use_sg, + direction); } else { vPtr = dma_map_single(hostdata->dev, SCp->request_buffer, @@ -1879,7 +1881,7 @@ NCR_700_queuecommand(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *)) for(i = 0; i < sg_count; i++) { if(SCp->use_sg) { - struct scatterlist *sg = SCp->buffer; + struct scatterlist *sg = SCp->request_buffer; vPtr = sg_dma_address(&sg[i]); count = sg_dma_len(&sg[i]); @@ -2042,6 +2044,11 @@ NCR_700_slave_configure(struct scsi_device *SDp) struct NCR_700_Host_Parameters *hostdata = (struct NCR_700_Host_Parameters *)SDp->host->hostdata[0]; + SDp->hostdata = kmalloc(GFP_KERNEL, sizeof(struct NCR_700_sense)); + + if (!SDp->hostdata) + return -ENOMEM; + /* to do here: allocate memory; build a queue_full list */ if(SDp->tagged_supported) { scsi_set_tag_type(SDp, MSG_ORDERED_TAG); @@ -2065,7 +2072,8 @@ NCR_700_slave_configure(struct scsi_device *SDp) STATIC void NCR_700_slave_destroy(struct scsi_device *SDp) { - /* to do here: deallocate memory */ + kfree(SDp->hostdata); + SDp->hostdata = NULL; } static int diff --git a/drivers/scsi/53c700.h b/drivers/scsi/53c700.h index a8c83bb0363..d8041952b1b 100644 --- a/drivers/scsi/53c700.h +++ b/drivers/scsi/53c700.h @@ -163,6 +163,8 @@ struct NCR_700_command_slot { #define NCR_700_SLOT_BUSY (1|NCR_700_SLOT_MAGIC) /* slot has command active on HA */ #define NCR_700_SLOT_QUEUED (2|NCR_700_SLOT_MAGIC) /* slot has command to be made active on HA */ __u8 state; + #define NCR_700_FLAG_AUTOSENSE 0x01 + __u8 flags; int tag; __u32 resume_offset; struct scsi_cmnd *cmnd; -- cgit v1.2.3 From da2f4d679c8070ba5b6a920281e495917b293aa0 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Tue, 20 Jun 2006 13:01:38 +1000 Subject: [XFS] Map EFSCORRUPTED to an actual error code, not just a made up one (990). Turns out some ye-olde unices used EUCLEAN as Filesystem-needs-cleaning, so now we use that too. SGI-PV: 953954 SGI-Modid: xfs-linux-melb:xfs-kern:26286a Signed-off-by: Nathan Scott --- fs/xfs/linux-2.6/xfs_linux.h | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h index e9285395411..aa26ab906c8 100644 --- a/fs/xfs/linux-2.6/xfs_linux.h +++ b/fs/xfs/linux-2.6/xfs_linux.h @@ -194,25 +194,9 @@ BUFFER_FNS(PrivateStart, unwritten); /* bytes to clicks */ #define btoc(x) (((__psunsigned_t)(x)+(NBPC-1))>>BPCSHIFT) -#ifndef ENOATTR #define ENOATTR ENODATA /* Attribute not found */ -#endif - -/* Note: EWRONGFS never visible outside the kernel */ -#define EWRONGFS EINVAL /* Mount with wrong filesystem type */ - -/* - * XXX EFSCORRUPTED needs a real value in errno.h. asm-i386/errno.h won't - * return codes out of its known range in errno. - * XXX Also note: needs to be < 1000 and fairly unique on Linux (mustn't - * conflict with any code we use already or any code a driver may use) - * XXX Some options (currently we do #2): - * 1/ New error code ["Filesystem is corrupted", _after_ glibc updated] - * 2/ 990 ["Unknown error 990"] - * 3/ EUCLEAN ["Structure needs cleaning"] - * 4/ Convert EFSCORRUPTED to EIO [just prior to return into userspace] - */ -#define EFSCORRUPTED 990 /* Filesystem is corrupted */ +#define EWRONGFS EINVAL /* Mount with wrong filesystem type */ +#define EFSCORRUPTED EUCLEAN /* Filesystem is corrupted */ #define SYNCHRONIZE() barrier() #define __return_address __builtin_return_address(0) -- cgit v1.2.3 From f6c2d1fa6310a71b1c2e05fc6d9ff9b91489fa0e Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Tue, 20 Jun 2006 13:04:51 +1000 Subject: [XFS] Remove version 1 directory code. Never functioned on Linux, just pure bloat. SGI-PV: 952969 SGI-Modid: xfs-linux-melb:xfs-kern:26251a Signed-off-by: Nathan Scott --- fs/xfs/linux-2.6/xfs_aops.c | 2 - fs/xfs/linux-2.6/xfs_export.c | 1 - fs/xfs/linux-2.6/xfs_file.c | 2 - fs/xfs/linux-2.6/xfs_ioctl.c | 2 - fs/xfs/linux-2.6/xfs_iops.c | 2 - fs/xfs/linux-2.6/xfs_lrw.c | 2 - fs/xfs/linux-2.6/xfs_super.c | 2 - fs/xfs/linux-2.6/xfs_vfs.c | 1 - fs/xfs/quota/xfs_dquot.c | 2 - fs/xfs/quota/xfs_dquot_item.c | 2 - fs/xfs/quota/xfs_qm.c | 2 - fs/xfs/quota/xfs_qm_bhv.c | 2 - fs/xfs/quota/xfs_qm_stats.c | 2 - fs/xfs/quota/xfs_qm_syscalls.c | 2 - fs/xfs/quota/xfs_trans_dquot.c | 2 - fs/xfs/xfs_acl.c | 2 - fs/xfs/xfs_alloc.c | 2 - fs/xfs/xfs_alloc_btree.c | 2 - fs/xfs/xfs_attr.c | 2 - fs/xfs/xfs_attr_leaf.c | 2 - fs/xfs/xfs_bmap.c | 8 +- fs/xfs/xfs_bmap_btree.c | 2 - fs/xfs/xfs_btree.c | 2 - fs/xfs/xfs_buf_item.c | 1 - fs/xfs/xfs_da_btree.c | 185 +--- fs/xfs/xfs_da_btree.h | 4 - fs/xfs/xfs_dfrag.c | 2 - fs/xfs/xfs_dinode.h | 1 - fs/xfs/xfs_dir.c | 1213 ---------------------- fs/xfs/xfs_dir.h | 142 --- fs/xfs/xfs_dir2.c | 391 +++---- fs/xfs/xfs_dir2.h | 32 +- fs/xfs/xfs_dir2_block.c | 15 +- fs/xfs/xfs_dir2_data.c | 3 - fs/xfs/xfs_dir2_leaf.c | 2 - fs/xfs/xfs_dir2_node.c | 2 - fs/xfs/xfs_dir2_sf.c | 3 - fs/xfs/xfs_dir2_trace.c | 2 - fs/xfs/xfs_dir_leaf.c | 2230 ---------------------------------------- fs/xfs/xfs_dir_leaf.h | 231 ----- fs/xfs/xfs_dir_sf.h | 155 --- fs/xfs/xfs_dmops.c | 1 - fs/xfs/xfs_error.c | 2 - fs/xfs/xfs_extfree_item.c | 1 - fs/xfs/xfs_fsops.c | 2 - fs/xfs/xfs_ialloc.c | 2 - fs/xfs/xfs_ialloc_btree.c | 2 - fs/xfs/xfs_iget.c | 2 - fs/xfs/xfs_inode.c | 9 - fs/xfs/xfs_inode_item.c | 2 - fs/xfs/xfs_iocore.c | 2 - fs/xfs/xfs_iomap.c | 2 - fs/xfs/xfs_itable.c | 2 - fs/xfs/xfs_log.c | 2 - fs/xfs/xfs_log_recover.c | 2 - fs/xfs/xfs_mount.c | 15 +- fs/xfs/xfs_mount.h | 2 - fs/xfs/xfs_qmops.c | 1 - fs/xfs/xfs_rename.c | 54 +- fs/xfs/xfs_rtalloc.c | 2 - fs/xfs/xfs_rw.c | 2 - fs/xfs/xfs_trans.c | 2 - fs/xfs/xfs_trans.h | 7 +- fs/xfs/xfs_trans_ail.c | 1 - fs/xfs/xfs_trans_buf.c | 2 - fs/xfs/xfs_trans_extfree.c | 1 - fs/xfs/xfs_trans_inode.c | 2 - fs/xfs/xfs_trans_space.h | 11 +- fs/xfs/xfs_utils.c | 5 +- fs/xfs/xfs_vfsops.c | 8 - fs/xfs/xfs_vnodeops.c | 68 +- 71 files changed, 285 insertions(+), 4595 deletions(-) diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index c5ea26d73be..3e807b828e2 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c @@ -21,7 +21,6 @@ #include "xfs_inum.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_trans.h" #include "xfs_dmapi.h" @@ -29,7 +28,6 @@ #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" diff --git a/fs/xfs/linux-2.6/xfs_export.c b/fs/xfs/linux-2.6/xfs_export.c index d32a9edc43a..5fb75d9151f 100644 --- a/fs/xfs/linux-2.6/xfs_export.c +++ b/fs/xfs/linux-2.6/xfs_export.c @@ -21,7 +21,6 @@ #include "xfs_log.h" #include "xfs_trans.h" #include "xfs_sb.h" -#include "xfs_dir.h" #include "xfs_mount.h" #include "xfs_export.h" diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index cf65a8364d5..70662371bb1 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c @@ -21,7 +21,6 @@ #include "xfs_inum.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_trans.h" #include "xfs_dmapi.h" @@ -32,7 +31,6 @@ #include "xfs_alloc.h" #include "xfs_btree.h" #include "xfs_attr_sf.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_dinode.h" #include "xfs_inode.h" diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c index a0e247c7132..6e52a5dd38d 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/fs/xfs/linux-2.6/xfs_ioctl.c @@ -23,7 +23,6 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_alloc.h" #include "xfs_dmapi.h" @@ -31,7 +30,6 @@ #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" -#include "xfs_dir_sf.h" #include "xfs_attr_sf.h" #include "xfs_dir2_sf.h" #include "xfs_dinode.h" diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index 484daef91d7..12810baeb5d 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c @@ -23,7 +23,6 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_alloc.h" #include "xfs_dmapi.h" @@ -32,7 +31,6 @@ #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c index 8e546870481..5d9cfd91ad0 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.c +++ b/fs/xfs/linux-2.6/xfs_lrw.c @@ -23,7 +23,6 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_alloc.h" #include "xfs_dmapi.h" @@ -32,7 +31,6 @@ #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 7fae922d54d..f2a0778536f 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -23,7 +23,6 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_alloc.h" #include "xfs_dmapi.h" @@ -32,7 +31,6 @@ #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" diff --git a/fs/xfs/linux-2.6/xfs_vfs.c b/fs/xfs/linux-2.6/xfs_vfs.c index 4fc884bcb4f..6145e8bd0be 100644 --- a/fs/xfs/linux-2.6/xfs_vfs.c +++ b/fs/xfs/linux-2.6/xfs_vfs.c @@ -23,7 +23,6 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_imap.h" #include "xfs_alloc.h" diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c index 46bec66bb4d..3aa77153185 100644 --- a/fs/xfs/quota/xfs_dquot.c +++ b/fs/xfs/quota/xfs_dquot.c @@ -23,7 +23,6 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_alloc.h" #include "xfs_dmapi.h" @@ -32,7 +31,6 @@ #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" diff --git a/fs/xfs/quota/xfs_dquot_item.c b/fs/xfs/quota/xfs_dquot_item.c index 21ad5a55e01..5b2dcc58b24 100644 --- a/fs/xfs/quota/xfs_dquot_item.c +++ b/fs/xfs/quota/xfs_dquot_item.c @@ -23,7 +23,6 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_alloc.h" #include "xfs_dmapi.h" @@ -32,7 +31,6 @@ #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c index 00fb54d4899..e23e45535c4 100644 --- a/fs/xfs/quota/xfs_qm.c +++ b/fs/xfs/quota/xfs_qm.c @@ -24,7 +24,6 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_alloc.h" #include "xfs_dmapi.h" @@ -33,7 +32,6 @@ #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" diff --git a/fs/xfs/quota/xfs_qm_bhv.c b/fs/xfs/quota/xfs_qm_bhv.c index d93d3a1064e..e95e99f7168 100644 --- a/fs/xfs/quota/xfs_qm_bhv.c +++ b/fs/xfs/quota/xfs_qm_bhv.c @@ -24,7 +24,6 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_alloc.h" #include "xfs_dmapi.h" @@ -33,7 +32,6 @@ #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" diff --git a/fs/xfs/quota/xfs_qm_stats.c b/fs/xfs/quota/xfs_qm_stats.c index 0570f773355..6f858fb81a3 100644 --- a/fs/xfs/quota/xfs_qm_stats.c +++ b/fs/xfs/quota/xfs_qm_stats.c @@ -23,7 +23,6 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_alloc.h" #include "xfs_dmapi.h" @@ -32,7 +31,6 @@ #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c index c93072be679..ed620c4d159 100644 --- a/fs/xfs/quota/xfs_qm_syscalls.c +++ b/fs/xfs/quota/xfs_qm_syscalls.c @@ -26,7 +26,6 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_alloc.h" #include "xfs_dmapi.h" @@ -35,7 +34,6 @@ #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" diff --git a/fs/xfs/quota/xfs_trans_dquot.c b/fs/xfs/quota/xfs_trans_dquot.c index 9168918db25..0242e9666e8 100644 --- a/fs/xfs/quota/xfs_trans_dquot.c +++ b/fs/xfs/quota/xfs_trans_dquot.c @@ -23,7 +23,6 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_alloc.h" #include "xfs_dmapi.h" @@ -33,7 +32,6 @@ #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" #include "xfs_attr_sf.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_dinode.h" #include "xfs_inode.h" diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c index e1074955386..4b0cb474be4 100644 --- a/fs/xfs/xfs_acl.c +++ b/fs/xfs/xfs_acl.c @@ -21,12 +21,10 @@ #include "xfs_bit.h" #include "xfs_inum.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c index 22af489d3f3..eef6763f3a6 100644 --- a/fs/xfs/xfs_alloc.c +++ b/fs/xfs/xfs_alloc.c @@ -24,14 +24,12 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_dmapi.h" #include "xfs_mount.h" #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" diff --git a/fs/xfs/xfs_alloc_btree.c b/fs/xfs/xfs_alloc_btree.c index a1d92da86cc..7446556e802 100644 --- a/fs/xfs/xfs_alloc_btree.c +++ b/fs/xfs/xfs_alloc_btree.c @@ -24,14 +24,12 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_dmapi.h" #include "xfs_mount.h" #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c index 4dcef8d1c32..1a210104327 100644 --- a/fs/xfs/xfs_attr.c +++ b/fs/xfs/xfs_attr.c @@ -27,7 +27,6 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_dmapi.h" #include "xfs_mount.h" @@ -35,7 +34,6 @@ #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c index 5c44343d4a3..9455051f012 100644 --- a/fs/xfs/xfs_attr_leaf.c +++ b/fs/xfs/xfs_attr_leaf.c @@ -24,7 +24,6 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_dmapi.h" #include "xfs_mount.h" @@ -34,7 +33,6 @@ #include "xfs_ialloc_btree.h" #include "xfs_alloc.h" #include "xfs_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 4d0ca14039a..3a613753906 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -24,13 +24,11 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_da_btree.h" #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" @@ -40,13 +38,15 @@ #include "xfs_mount.h" #include "xfs_ialloc.h" #include "xfs_itable.h" +#include "xfs_dir2_data.h" +#include "xfs_dir2_leaf.h" +#include "xfs_dir2_block.h" #include "xfs_inode_item.h" #include "xfs_extfree_item.h" #include "xfs_alloc.h" #include "xfs_bmap.h" #include "xfs_rtalloc.h" #include "xfs_error.h" -#include "xfs_dir_leaf.h" #include "xfs_attr_leaf.h" #include "xfs_rw.h" #include "xfs_quota.h" @@ -516,7 +516,7 @@ xfs_bmap_add_attrfork_local( dargs.total = mp->m_dirblkfsbs; dargs.whichfork = XFS_DATA_FORK; dargs.trans = tp; - error = XFS_DIR_SHORTFORM_TO_SINGLE(mp, &dargs); + error = xfs_dir2_sf_to_block(&dargs); } else error = xfs_bmap_local_to_extents(tp, ip, firstblock, 1, flags, XFS_DATA_FORK); diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c index 3b6dfc9b53a..18fb7385d71 100644 --- a/fs/xfs/xfs_bmap_btree.c +++ b/fs/xfs/xfs_bmap_btree.c @@ -24,14 +24,12 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_dmapi.h" #include "xfs_mount.h" #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" diff --git a/fs/xfs/xfs_btree.c b/fs/xfs/xfs_btree.c index 52d5d095fc3..ee2255bd656 100644 --- a/fs/xfs/xfs_btree.c +++ b/fs/xfs/xfs_btree.c @@ -24,14 +24,12 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_dmapi.h" #include "xfs_mount.h" #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index 290912cbff6..a4aa53974f7 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c @@ -23,7 +23,6 @@ #include "xfs_inum.h" #include "xfs_trans.h" #include "xfs_sb.h" -#include "xfs_dir.h" #include "xfs_dmapi.h" #include "xfs_mount.h" #include "xfs_buf_item.h" diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c index 260c3d770c0..32ab61d17ac 100644 --- a/fs/xfs/xfs_da_btree.c +++ b/fs/xfs/xfs_da_btree.c @@ -24,7 +24,6 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_dmapi.h" #include "xfs_mount.h" @@ -32,7 +31,6 @@ #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" @@ -43,7 +41,6 @@ #include "xfs_bmap.h" #include "xfs_attr.h" #include "xfs_attr_leaf.h" -#include "xfs_dir_leaf.h" #include "xfs_dir2_data.h" #include "xfs_dir2_leaf.h" #include "xfs_dir2_block.h" @@ -159,7 +156,7 @@ xfs_da_split(xfs_da_state_t *state) max = state->path.active - 1; ASSERT((max >= 0) && (max < XFS_DA_NODE_MAXDEPTH)); ASSERT(state->path.blk[max].magic == XFS_ATTR_LEAF_MAGIC || - state->path.blk[max].magic == XFS_DIRX_LEAF_MAGIC(state->mp)); + state->path.blk[max].magic == XFS_DIR2_LEAFN_MAGIC); addblk = &state->path.blk[max]; /* initial dummy value */ for (i = max; (i >= 0) && addblk; state->path.active--, i--) { @@ -199,38 +196,7 @@ xfs_da_split(xfs_da_state_t *state) return(error); /* GROT: attr inconsistent */ addblk = newblk; break; - case XFS_DIR_LEAF_MAGIC: - ASSERT(XFS_DIR_IS_V1(state->mp)); - error = xfs_dir_leaf_split(state, oldblk, newblk); - if ((error != 0) && (error != ENOSPC)) { - return(error); /* GROT: dir is inconsistent */ - } - if (!error) { - addblk = newblk; - break; - } - /* - * Entry wouldn't fit, split the leaf again. - */ - state->extravalid = 1; - if (state->inleaf) { - state->extraafter = 0; /* before newblk */ - error = xfs_dir_leaf_split(state, oldblk, - &state->extrablk); - if (error) - return(error); /* GROT: dir incon. */ - addblk = newblk; - } else { - state->extraafter = 1; /* after newblk */ - error = xfs_dir_leaf_split(state, newblk, - &state->extrablk); - if (error) - return(error); /* GROT: dir incon. */ - addblk = newblk; - } - break; case XFS_DIR2_LEAFN_MAGIC: - ASSERT(XFS_DIR_IS_V2(state->mp)); error = xfs_dir2_leafn_split(state, oldblk, newblk); if (error) return error; @@ -363,7 +329,6 @@ xfs_da_root_split(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, size = (int)((char *)&oldroot->btree[be16_to_cpu(oldroot->hdr.count)] - (char *)oldroot); } else { - ASSERT(XFS_DIR_IS_V2(mp)); ASSERT(be16_to_cpu(oldroot->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC); leaf = (xfs_dir2_leaf_t *)oldroot; size = (int)((char *)&leaf->ents[be16_to_cpu(leaf->hdr.count)] - @@ -379,8 +344,7 @@ xfs_da_root_split(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, * Set up the new root node. */ error = xfs_da_node_create(args, - args->whichfork == XFS_DATA_FORK && - XFS_DIR_IS_V2(mp) ? mp->m_dirleafblk : 0, + (args->whichfork == XFS_DATA_FORK) ? mp->m_dirleafblk : 0, be16_to_cpu(node->hdr.level) + 1, &bp, args->whichfork); if (error) return(error); @@ -427,10 +391,9 @@ xfs_da_node_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk, ASSERT(be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC); /* - * With V2 the extra block is data or freespace. + * With V2 dirs the extra block is data or freespace. */ - useextra = state->extravalid && (XFS_DIR_IS_V1(state->mp) || - state->args->whichfork == XFS_ATTR_FORK); + useextra = state->extravalid && state->args->whichfork == XFS_ATTR_FORK; newcount = 1 + useextra; /* * Do we have to split the node? @@ -624,7 +587,7 @@ xfs_da_node_add(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk, ASSERT(be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC); ASSERT((oldblk->index >= 0) && (oldblk->index <= be16_to_cpu(node->hdr.count))); ASSERT(newblk->blkno != 0); - if (state->args->whichfork == XFS_DATA_FORK && XFS_DIR_IS_V2(mp)) + if (state->args->whichfork == XFS_DATA_FORK) ASSERT(newblk->blkno >= mp->m_dirleafblk && newblk->blkno < mp->m_dirfreeblk); @@ -670,7 +633,7 @@ xfs_da_join(xfs_da_state_t *state) save_blk = &state->altpath.blk[ state->path.active-1 ]; ASSERT(state->path.blk[0].magic == XFS_DA_NODE_MAGIC); ASSERT(drop_blk->magic == XFS_ATTR_LEAF_MAGIC || - drop_blk->magic == XFS_DIRX_LEAF_MAGIC(state->mp)); + drop_blk->magic == XFS_DIR2_LEAFN_MAGIC); /* * Walk back up the tree joining/deallocating as necessary. @@ -693,17 +656,7 @@ xfs_da_join(xfs_da_state_t *state) return(0); xfs_attr_leaf_unbalance(state, drop_blk, save_blk); break; - case XFS_DIR_LEAF_MAGIC: - ASSERT(XFS_DIR_IS_V1(state->mp)); - error = xfs_dir_leaf_toosmall(state, &action); - if (error) - return(error); - if (action == 0) - return(0); - xfs_dir_leaf_unbalance(state, drop_blk, save_blk); - break; case XFS_DIR2_LEAFN_MAGIC: - ASSERT(XFS_DIR_IS_V2(state->mp)); error = xfs_dir2_leafn_toosmall(state, &action); if (error) return error; @@ -790,7 +743,7 @@ xfs_da_root_join(xfs_da_state_t *state, xfs_da_state_blk_t *root_blk) ASSERT(bp != NULL); blkinfo = bp->data; if (be16_to_cpu(oldroot->hdr.level) == 1) { - ASSERT(be16_to_cpu(blkinfo->magic) == XFS_DIRX_LEAF_MAGIC(state->mp) || + ASSERT(be16_to_cpu(blkinfo->magic) == XFS_DIR2_LEAFN_MAGIC || be16_to_cpu(blkinfo->magic) == XFS_ATTR_LEAF_MAGIC); } else { ASSERT(be16_to_cpu(blkinfo->magic) == XFS_DA_NODE_MAGIC); @@ -951,14 +904,7 @@ xfs_da_fixhashpath(xfs_da_state_t *state, xfs_da_state_path_t *path) if (count == 0) return; break; - case XFS_DIR_LEAF_MAGIC: - ASSERT(XFS_DIR_IS_V1(state->mp)); - lasthash = xfs_dir_leaf_lasthash(blk->bp, &count); - if (count == 0) - return; - break; case XFS_DIR2_LEAFN_MAGIC: - ASSERT(XFS_DIR_IS_V2(state->mp)); lasthash = xfs_dir2_leafn_lasthash(blk->bp, &count); if (count == 0) return; @@ -1117,10 +1063,7 @@ xfs_da_node_lookup_int(xfs_da_state_t *state, int *result) * Descend thru the B-tree searching each level for the right * node to use, until the right hashval is found. */ - if (args->whichfork == XFS_DATA_FORK && XFS_DIR_IS_V2(state->mp)) - blkno = state->mp->m_dirleafblk; - else - blkno = 0; + blkno = (args->whichfork == XFS_DATA_FORK)? state->mp->m_dirleafblk : 0; for (blk = &state->path.blk[0], state->path.active = 1; state->path.active <= XFS_DA_NODE_MAXDEPTH; blk++, state->path.active++) { @@ -1137,7 +1080,7 @@ xfs_da_node_lookup_int(xfs_da_state_t *state, int *result) } curr = blk->bp->data; ASSERT(be16_to_cpu(curr->magic) == XFS_DA_NODE_MAGIC || - be16_to_cpu(curr->magic) == XFS_DIRX_LEAF_MAGIC(state->mp) || + be16_to_cpu(curr->magic) == XFS_DIR2_LEAFN_MAGIC || be16_to_cpu(curr->magic) == XFS_ATTR_LEAF_MAGIC); /* @@ -1190,16 +1133,10 @@ xfs_da_node_lookup_int(xfs_da_state_t *state, int *result) blk->index = probe; blkno = be32_to_cpu(btree->before); } - } - else if (be16_to_cpu(curr->magic) == XFS_ATTR_LEAF_MAGIC) { + } else if (be16_to_cpu(curr->magic) == XFS_ATTR_LEAF_MAGIC) { blk->hashval = xfs_attr_leaf_lasthash(blk->bp, NULL); break; - } - else if (be16_to_cpu(curr->magic) == XFS_DIR_LEAF_MAGIC) { - blk->hashval = xfs_dir_leaf_lasthash(blk->bp, NULL); - break; - } - else if (be16_to_cpu(curr->magic) == XFS_DIR2_LEAFN_MAGIC) { + } else if (be16_to_cpu(curr->magic) == XFS_DIR2_LEAFN_MAGIC) { blk->hashval = xfs_dir2_leafn_lasthash(blk->bp, NULL); break; } @@ -1212,12 +1149,7 @@ xfs_da_node_lookup_int(xfs_da_state_t *state, int *result) * next leaf and keep searching. */ for (;;) { - if (blk->magic == XFS_DIR_LEAF_MAGIC) { - ASSERT(XFS_DIR_IS_V1(state->mp)); - retval = xfs_dir_leaf_lookup_int(blk->bp, args, - &blk->index); - } else if (blk->magic == XFS_DIR2_LEAFN_MAGIC) { - ASSERT(XFS_DIR_IS_V2(state->mp)); + if (blk->magic == XFS_DIR2_LEAFN_MAGIC) { retval = xfs_dir2_leafn_lookup_int(blk->bp, args, &blk->index, state); } @@ -1270,7 +1202,7 @@ xfs_da_blk_link(xfs_da_state_t *state, xfs_da_state_blk_t *old_blk, old_info = old_blk->bp->data; new_info = new_blk->bp->data; ASSERT(old_blk->magic == XFS_DA_NODE_MAGIC || - old_blk->magic == XFS_DIRX_LEAF_MAGIC(state->mp) || + old_blk->magic == XFS_DIR2_LEAFN_MAGIC || old_blk->magic == XFS_ATTR_LEAF_MAGIC); ASSERT(old_blk->magic == be16_to_cpu(old_info->magic)); ASSERT(new_blk->magic == be16_to_cpu(new_info->magic)); @@ -1280,12 +1212,7 @@ xfs_da_blk_link(xfs_da_state_t *state, xfs_da_state_blk_t *old_blk, case XFS_ATTR_LEAF_MAGIC: before = xfs_attr_leaf_order(old_blk->bp, new_blk->bp); break; - case XFS_DIR_LEAF_MAGIC: - ASSERT(XFS_DIR_IS_V1(state->mp)); - before = xfs_dir_leaf_order(old_blk->bp, new_blk->bp); - break; case XFS_DIR2_LEAFN_MAGIC: - ASSERT(XFS_DIR_IS_V2(state->mp)); before = xfs_dir2_leafn_order(old_blk->bp, new_blk->bp); break; case XFS_DA_NODE_MAGIC: @@ -1404,7 +1331,7 @@ xfs_da_blk_unlink(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk, save_info = save_blk->bp->data; drop_info = drop_blk->bp->data; ASSERT(save_blk->magic == XFS_DA_NODE_MAGIC || - save_blk->magic == XFS_DIRX_LEAF_MAGIC(state->mp) || + save_blk->magic == XFS_DIR2_LEAFN_MAGIC || save_blk->magic == XFS_ATTR_LEAF_MAGIC); ASSERT(save_blk->magic == be16_to_cpu(save_info->magic)); ASSERT(drop_blk->magic == be16_to_cpu(drop_info->magic)); @@ -1529,7 +1456,7 @@ xfs_da_path_shift(xfs_da_state_t *state, xfs_da_state_path_t *path, ASSERT(blk->bp != NULL); info = blk->bp->data; ASSERT(be16_to_cpu(info->magic) == XFS_DA_NODE_MAGIC || - be16_to_cpu(info->magic) == XFS_DIRX_LEAF_MAGIC(state->mp) || + be16_to_cpu(info->magic) == XFS_DIR2_LEAFN_MAGIC || be16_to_cpu(info->magic) == XFS_ATTR_LEAF_MAGIC); blk->magic = be16_to_cpu(info->magic); if (blk->magic == XFS_DA_NODE_MAGIC) { @@ -1548,20 +1475,13 @@ xfs_da_path_shift(xfs_da_state_t *state, xfs_da_state_path_t *path, blk->hashval = xfs_attr_leaf_lasthash(blk->bp, NULL); break; - case XFS_DIR_LEAF_MAGIC: - ASSERT(XFS_DIR_IS_V1(state->mp)); - blk->hashval = xfs_dir_leaf_lasthash(blk->bp, - NULL); - break; case XFS_DIR2_LEAFN_MAGIC: - ASSERT(XFS_DIR_IS_V2(state->mp)); blk->hashval = xfs_dir2_leafn_lasthash(blk->bp, NULL); break; default: ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC || - blk->magic == - XFS_DIRX_LEAF_MAGIC(state->mp)); + blk->magic == XFS_DIR2_LEAFN_MAGIC); break; } } @@ -1620,7 +1540,6 @@ xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno) xfs_bmbt_irec_t *mapp; xfs_inode_t *dp; int nmap, error, w, count, c, got, i, mapi; - xfs_fsize_t size; xfs_trans_t *tp; xfs_mount_t *mp; @@ -1631,7 +1550,7 @@ xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno) /* * For new directories adjust the file offset and block count. */ - if (w == XFS_DATA_FORK && XFS_DIR_IS_V2(mp)) { + if (w == XFS_DATA_FORK) { bno = mp->m_dirleafblk; count = mp->m_dirblkfsbs; } else { @@ -1641,10 +1560,9 @@ xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno) /* * Find a spot in the file space to put the new block. */ - if ((error = xfs_bmap_first_unused(tp, dp, count, &bno, w))) { + if ((error = xfs_bmap_first_unused(tp, dp, count, &bno, w))) return error; - } - if (w == XFS_DATA_FORK && XFS_DIR_IS_V2(mp)) + if (w == XFS_DATA_FORK) ASSERT(bno >= mp->m_dirleafblk && bno < mp->m_dirfreeblk); /* * Try mapping it in one filesystem block. @@ -1706,19 +1624,6 @@ xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno) if (mapp != &map) kmem_free(mapp, sizeof(*mapp) * count); *new_blkno = (xfs_dablk_t)bno; - /* - * For version 1 directories, adjust the file size if it changed. - */ - if (w == XFS_DATA_FORK && XFS_DIR_IS_V1(mp)) { - ASSERT(mapi == 1); - if ((error = xfs_bmap_last_offset(tp, dp, &bno, w))) - return error; - size = XFS_FSB_TO_B(mp, bno); - if (size != dp->i_d.di_size) { - dp->i_d.di_size = size; - xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE); - } - } return 0; } @@ -1743,7 +1648,6 @@ xfs_da_swap_lastblock(xfs_da_args_t *args, xfs_dablk_t *dead_blknop, int error, w, entno, level, dead_level; xfs_da_blkinfo_t *dead_info, *sib_info; xfs_da_intnode_t *par_node, *dead_node; - xfs_dir_leafblock_t *dead_leaf; xfs_dir2_leaf_t *dead_leaf2; xfs_dahash_t dead_hash; @@ -1754,11 +1658,8 @@ xfs_da_swap_lastblock(xfs_da_args_t *args, xfs_dablk_t *dead_blknop, w = args->whichfork; ASSERT(w == XFS_DATA_FORK); mp = ip->i_mount; - if (XFS_DIR_IS_V2(mp)) { - lastoff = mp->m_dirfreeblk; - error = xfs_bmap_last_before(tp, ip, &lastoff, w); - } else - error = xfs_bmap_last_offset(tp, ip, &lastoff, w); + lastoff = mp->m_dirfreeblk; + error = xfs_bmap_last_before(tp, ip, &lastoff, w); if (error) return error; if (unlikely(lastoff == 0)) { @@ -1781,14 +1682,7 @@ xfs_da_swap_lastblock(xfs_da_args_t *args, xfs_dablk_t *dead_blknop, /* * Get values from the moved block. */ - if (be16_to_cpu(dead_info->magic) == XFS_DIR_LEAF_MAGIC) { - ASSERT(XFS_DIR_IS_V1(mp)); - dead_leaf = (xfs_dir_leafblock_t *)dead_info; - dead_level = 0; - dead_hash = be32_to_cpu(dead_leaf->entries[ - be16_to_cpu(dead_leaf->hdr.count) - 1].hashval); - } else if (be16_to_cpu(dead_info->magic) == XFS_DIR2_LEAFN_MAGIC) { - ASSERT(XFS_DIR_IS_V2(mp)); + if (be16_to_cpu(dead_info->magic) == XFS_DIR2_LEAFN_MAGIC) { dead_leaf2 = (xfs_dir2_leaf_t *)dead_info; dead_level = 0; dead_hash = be32_to_cpu(dead_leaf2->ents[be16_to_cpu(dead_leaf2->hdr.count) - 1].hashval); @@ -1843,7 +1737,7 @@ xfs_da_swap_lastblock(xfs_da_args_t *args, xfs_dablk_t *dead_blknop, xfs_da_buf_done(sib_buf); sib_buf = NULL; } - par_blkno = XFS_DIR_IS_V1(mp) ? 0 : mp->m_dirleafblk; + par_blkno = mp->m_dirleafblk; level = -1; /* * Walk down the tree looking for the parent of the moved block. @@ -1942,8 +1836,6 @@ xfs_da_shrink_inode(xfs_da_args_t *args, xfs_dablk_t dead_blkno, { xfs_inode_t *dp; int done, error, w, count; - xfs_fileoff_t bno; - xfs_fsize_t size; xfs_trans_t *tp; xfs_mount_t *mp; @@ -1951,7 +1843,7 @@ xfs_da_shrink_inode(xfs_da_args_t *args, xfs_dablk_t dead_blkno, w = args->whichfork; tp = args->trans; mp = dp->i_mount; - if (w == XFS_DATA_FORK && XFS_DIR_IS_V2(mp)) + if (w == XFS_DATA_FORK) count = mp->m_dirblkfsbs; else count = 1; @@ -1965,31 +1857,14 @@ xfs_da_shrink_inode(xfs_da_args_t *args, xfs_dablk_t dead_blkno, 0, args->firstblock, args->flist, NULL, &done)) == ENOSPC) { if (w != XFS_DATA_FORK) - goto done; + break; if ((error = xfs_da_swap_lastblock(args, &dead_blkno, &dead_buf))) - goto done; - } else if (error) - goto done; - else + break; + } else { break; - } - ASSERT(done); - xfs_da_binval(tp, dead_buf); - /* - * Adjust the directory size for version 1. - */ - if (w == XFS_DATA_FORK && XFS_DIR_IS_V1(mp)) { - if ((error = xfs_bmap_last_offset(tp, dp, &bno, w))) - return error; - size = XFS_FSB_TO_B(dp->i_mount, bno); - if (size != dp->i_d.di_size) { - dp->i_d.di_size = size; - xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE); } } - return 0; -done: xfs_da_binval(tp, dead_buf); return error; } @@ -2050,10 +1925,7 @@ xfs_da_do_buf( xfs_dabuf_t *rbp; mp = dp->i_mount; - if (whichfork == XFS_DATA_FORK && XFS_DIR_IS_V2(mp)) - nfsb = mp->m_dirblkfsbs; - else - nfsb = 1; + nfsb = (whichfork == XFS_DATA_FORK) ? mp->m_dirblkfsbs : 1; mappedbno = *mappedbnop; /* * Caller doesn't have a mapping. -2 means don't complain @@ -2199,7 +2071,6 @@ xfs_da_do_buf( magic1 = be32_to_cpu(data->hdr.magic); if (unlikely( XFS_TEST_ERROR((magic != XFS_DA_NODE_MAGIC) && - (magic != XFS_DIR_LEAF_MAGIC) && (magic != XFS_ATTR_LEAF_MAGIC) && (magic != XFS_DIR2_LEAF1_MAGIC) && (magic != XFS_DIR2_LEAFN_MAGIC) && diff --git a/fs/xfs/xfs_da_btree.h b/fs/xfs/xfs_da_btree.h index 243a730d5ec..4ab865ec8b8 100644 --- a/fs/xfs/xfs_da_btree.h +++ b/fs/xfs/xfs_da_btree.h @@ -36,14 +36,10 @@ struct zone; * level in the Btree, and to identify which type of block this is. */ #define XFS_DA_NODE_MAGIC 0xfebe /* magic number: non-leaf blocks */ -#define XFS_DIR_LEAF_MAGIC 0xfeeb /* magic number: directory leaf blks */ #define XFS_ATTR_LEAF_MAGIC 0xfbee /* magic number: attribute leaf blks */ #define XFS_DIR2_LEAF1_MAGIC 0xd2f1 /* magic number: v2 dirlf single blks */ #define XFS_DIR2_LEAFN_MAGIC 0xd2ff /* magic number: v2 dirlf multi blks */ -#define XFS_DIRX_LEAF_MAGIC(mp) \ - (XFS_DIR_IS_V1(mp) ? XFS_DIR_LEAF_MAGIC : XFS_DIR2_LEAFN_MAGIC) - typedef struct xfs_da_blkinfo { __be32 forw; /* previous block in list */ __be32 back; /* following block in list */ diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c index 29a6c866f2c..80562b60fb9 100644 --- a/fs/xfs/xfs_dfrag.c +++ b/fs/xfs/xfs_dfrag.c @@ -24,14 +24,12 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_dmapi.h" #include "xfs_mount.h" #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" diff --git a/fs/xfs/xfs_dinode.h b/fs/xfs/xfs_dinode.h index 77d53778258..b33826961c4 100644 --- a/fs/xfs/xfs_dinode.h +++ b/fs/xfs/xfs_dinode.h @@ -85,7 +85,6 @@ typedef struct xfs_dinode union { xfs_bmdr_block_t di_bmbt; /* btree root block */ xfs_bmbt_rec_32_t di_bmx[1]; /* extent list */ - xfs_dir_shortform_t di_dirsf; /* shortform directory */ xfs_dir2_sf_t di_dir2sf; /* shortform directory v2 */ char di_c[1]; /* local contents */ xfs_dev_t di_dev; /* device for S_IFCHR/S_IFBLK */ diff --git a/fs/xfs/xfs_dir.c b/fs/xfs/xfs_dir.c index 3cd8657a81f..e69de29bb2d 100644 --- a/fs/xfs/xfs_dir.c +++ b/fs/xfs/xfs_dir.c @@ -1,1213 +0,0 @@ -/* - * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -#include "xfs.h" -#include "xfs_fs.h" -#include "xfs_types.h" -#include "xfs_log.h" -#include "xfs_inum.h" -#include "xfs_trans.h" -#include "xfs_sb.h" -#include "xfs_dir.h" -#include "xfs_dir2.h" -#include "xfs_dmapi.h" -#include "xfs_mount.h" -#include "xfs_da_btree.h" -#include "xfs_bmap_btree.h" -#include "xfs_alloc_btree.h" -#include "xfs_ialloc_btree.h" -#include "xfs_alloc.h" -#include "xfs_btree.h" -#include "xfs_dir_sf.h" -#include "xfs_dir2_sf.h" -#include "xfs_attr_sf.h" -#include "xfs_dinode.h" -#include "xfs_inode.h" -#include "xfs_bmap.h" -#include "xfs_dir_leaf.h" -#include "xfs_error.h" - -/* - * xfs_dir.c - * - * Provide the external interfaces to manage directories. - */ - -/*======================================================================== - * Function prototypes for the kernel. - *========================================================================*/ - -/* - * Functions for the dirops interfaces. - */ -static void xfs_dir_mount(struct xfs_mount *mp); - -static int xfs_dir_isempty(struct xfs_inode *dp); - -static int xfs_dir_init(struct xfs_trans *trans, - struct xfs_inode *dir, - struct xfs_inode *parent_dir); - -static int xfs_dir_createname(struct xfs_trans *trans, - struct xfs_inode *dp, - char *name_string, - int name_len, - xfs_ino_t inode_number, - xfs_fsblock_t *firstblock, - xfs_bmap_free_t *flist, - xfs_extlen_t total); - -static int xfs_dir_lookup(struct xfs_trans *tp, - struct xfs_inode *dp, - char *name_string, - int name_length, - xfs_ino_t *inode_number); - -static int xfs_dir_removename(struct xfs_trans *trans, - struct xfs_inode *dp, - char *name_string, - int name_length, - xfs_ino_t ino, - xfs_fsblock_t *firstblock, - xfs_bmap_free_t *flist, - xfs_extlen_t total); - -static int xfs_dir_getdents(struct xfs_trans *tp, - struct xfs_inode *dp, - struct uio *uiop, - int *eofp); - -static int xfs_dir_replace(struct xfs_trans *tp, - struct xfs_inode *dp, - char *name_string, - int name_length, - xfs_ino_t inode_number, - xfs_fsblock_t *firstblock, - xfs_bmap_free_t *flist, - xfs_extlen_t total); - -static int xfs_dir_canenter(struct xfs_trans *tp, - struct xfs_inode *dp, - char *name_string, - int name_length); - -static int xfs_dir_shortform_validate_ondisk(xfs_mount_t *mp, - xfs_dinode_t *dip); - -xfs_dirops_t xfsv1_dirops = { - .xd_mount = xfs_dir_mount, - .xd_isempty = xfs_dir_isempty, - .xd_init = xfs_dir_init, - .xd_createname = xfs_dir_createname, - .xd_lookup = xfs_dir_lookup, - .xd_removename = xfs_dir_removename, - .xd_getdents = xfs_dir_getdents, - .xd_replace = xfs_dir_replace, - .xd_canenter = xfs_dir_canenter, - .xd_shortform_validate_ondisk = xfs_dir_shortform_validate_ondisk, - .xd_shortform_to_single = xfs_dir_shortform_to_leaf, -}; - -/* - * Internal routines when dirsize == XFS_LBSIZE(mp). - */ -STATIC int xfs_dir_leaf_lookup(xfs_da_args_t *args); -STATIC int xfs_dir_leaf_removename(xfs_da_args_t *args, int *number_entries, - int *total_namebytes); -STATIC int xfs_dir_leaf_getdents(xfs_trans_t *trans, xfs_inode_t *dp, - uio_t *uio, int *eofp, - xfs_dirent_t *dbp, - xfs_dir_put_t put); -STATIC int xfs_dir_leaf_replace(xfs_da_args_t *args); - -/* - * Internal routines when dirsize > XFS_LBSIZE(mp). - */ -STATIC int xfs_dir_node_addname(xfs_da_args_t *args); -STATIC int xfs_dir_node_lookup(xfs_da_args_t *args); -STATIC int xfs_dir_node_removename(xfs_da_args_t *args); -STATIC int xfs_dir_node_getdents(xfs_trans_t *trans, xfs_inode_t *dp, - uio_t *uio, int *eofp, - xfs_dirent_t *dbp, - xfs_dir_put_t put); -STATIC int xfs_dir_node_replace(xfs_da_args_t *args); - -#if defined(XFS_DIR_TRACE) -ktrace_t *xfs_dir_trace_buf; -#endif - - -/*======================================================================== - * Overall external interface routines. - *========================================================================*/ - -xfs_dahash_t xfs_dir_hash_dot, xfs_dir_hash_dotdot; - -/* - * One-time startup routine called from xfs_init(). - */ -void -xfs_dir_startup(void) -{ - xfs_dir_hash_dot = xfs_da_hashname(".", 1); - xfs_dir_hash_dotdot = xfs_da_hashname("..", 2); -} - -/* - * Initialize directory-related fields in the mount structure. - */ -static void -xfs_dir_mount(xfs_mount_t *mp) -{ - uint shortcount, leafcount, count; - - mp->m_dirversion = 1; - if (!(mp->m_flags & XFS_MOUNT_ATTR2)) { - shortcount = (mp->m_attroffset - - (uint)sizeof(xfs_dir_sf_hdr_t)) / - (uint)sizeof(xfs_dir_sf_entry_t); - leafcount = (XFS_LBSIZE(mp) - - (uint)sizeof(xfs_dir_leaf_hdr_t)) / - ((uint)sizeof(xfs_dir_leaf_entry_t) + - (uint)sizeof(xfs_dir_leaf_name_t)); - } else { - shortcount = (XFS_BMDR_SPACE_CALC(MINABTPTRS) - - (uint)sizeof(xfs_dir_sf_hdr_t)) / - (uint)sizeof(xfs_dir_sf_entry_t); - leafcount = (XFS_LBSIZE(mp) - - (uint)sizeof(xfs_dir_leaf_hdr_t)) / - ((uint)sizeof(xfs_dir_leaf_entry_t) + - (uint)sizeof(xfs_dir_leaf_name_t)); - } - count = shortcount > leafcount ? shortcount : leafcount; - mp->m_dircook_elog = xfs_da_log2_roundup(count + 1); - ASSERT(mp->m_dircook_elog <= mp->m_sb.sb_blocklog); - mp->m_dir_node_ents = mp->m_attr_node_ents = - (XFS_LBSIZE(mp) - (uint)sizeof(xfs_da_node_hdr_t)) / - (uint)sizeof(xfs_da_node_entry_t); - mp->m_dir_magicpct = (XFS_LBSIZE(mp) * 37) / 100; - mp->m_dirblksize = mp->m_sb.sb_blocksize; - mp->m_dirblkfsbs = 1; -} - -/* - * Return 1 if directory contains only "." and "..". - */ -static int -xfs_dir_isempty(xfs_inode_t *dp) -{ - xfs_dir_sf_hdr_t *hdr; - - ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); - if (dp->i_d.di_size == 0) - return(1); - if (dp->i_d.di_size > XFS_IFORK_DSIZE(dp)) - return(0); - hdr = (xfs_dir_sf_hdr_t *)dp->i_df.if_u1.if_data; - return(hdr->count == 0); -} - -/* - * Initialize a directory with its "." and ".." entries. - */ -static int -xfs_dir_init(xfs_trans_t *trans, xfs_inode_t *dir, xfs_inode_t *parent_dir) -{ - xfs_da_args_t args; - int error; - - memset((char *)&args, 0, sizeof(args)); - args.dp = dir; - args.trans = trans; - - ASSERT((dir->i_d.di_mode & S_IFMT) == S_IFDIR); - if ((error = xfs_dir_ino_validate(trans->t_mountp, parent_dir->i_ino))) - return error; - - return(xfs_dir_shortform_create(&args, parent_dir->i_ino)); -} - -/* - * Generic handler routine to add a name to a directory. - * Transitions directory from shortform to Btree as necessary. - */ -static int /* error */ -xfs_dir_createname(xfs_trans_t *trans, xfs_inode_t *dp, char *name, - int namelen, xfs_ino_t inum, xfs_fsblock_t *firstblock, - xfs_bmap_free_t *flist, xfs_extlen_t total) -{ - xfs_da_args_t args; - int retval, newsize, done; - - ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); - - if ((retval = xfs_dir_ino_validate(trans->t_mountp, inum))) - return (retval); - - XFS_STATS_INC(xs_dir_create); - /* - * Fill in the arg structure for this request. - */ - args.name = name; - args.namelen = namelen; - args.hashval = xfs_da_hashname(name, namelen); - args.inumber = inum; - args.dp = dp; - args.firstblock = firstblock; - args.flist = flist; - args.total = total; - args.whichfork = XFS_DATA_FORK; - args.trans = trans; - args.justcheck = 0; - args.addname = args.oknoent = 1; - - /* - * Decide on what work routines to call based on the inode size. - */ - done = 0; - if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) { - newsize = XFS_DIR_SF_ENTSIZE_BYNAME(args.namelen); - if ((dp->i_d.di_size + newsize) <= XFS_IFORK_DSIZE(dp)) { - retval = xfs_dir_shortform_addname(&args); - done = 1; - } else { - if (total == 0) - return XFS_ERROR(ENOSPC); - retval = xfs_dir_shortform_to_leaf(&args); - done = retval != 0; - } - } - if (!done && xfs_bmap_one_block(dp, XFS_DATA_FORK)) { - retval = xfs_dir_leaf_addname(&args); - done = retval != ENOSPC; - if (!done) { - if (total == 0) - return XFS_ERROR(ENOSPC); - retval = xfs_dir_leaf_to_node(&args); - done = retval != 0; - } - } - if (!done) { - retval = xfs_dir_node_addname(&args); - } - return(retval); -} - -/* - * Generic handler routine to check if a name can be added to a directory, - * without adding any blocks to the directory. - */ -static int /* error */ -xfs_dir_canenter(xfs_trans_t *trans, xfs_inode_t *dp, char *name, int namelen) -{ - xfs_da_args_t args; - int retval, newsize; - - ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); - /* - * Fill in the arg structure for this request. - */ - args.name = name; - args.namelen = namelen; - args.hashval = xfs_da_hashname(name, namelen); - args.inumber = 0; - args.dp = dp; - args.firstblock = NULL; - args.flist = NULL; - args.total = 0; - args.whichfork = XFS_DATA_FORK; - args.trans = trans; - args.justcheck = args.addname = args.oknoent = 1; - - /* - * Decide on what work routines to call based on the inode size. - */ - if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) { - newsize = XFS_DIR_SF_ENTSIZE_BYNAME(args.namelen); - if ((dp->i_d.di_size + newsize) <= XFS_IFORK_DSIZE(dp)) - retval = 0; - else - retval = XFS_ERROR(ENOSPC); - } else if (xfs_bmap_one_block(dp, XFS_DATA_FORK)) { - retval = xfs_dir_leaf_addname(&args); - } else { - retval = xfs_dir_node_addname(&args); - } - return(retval); -} - -/* - * Generic handler routine to remove a name from a directory. - * Transitions directory from Btree to shortform as necessary. - */ -static int /* error */ -xfs_dir_removename(xfs_trans_t *trans, xfs_inode_t *dp, char *name, - int namelen, xfs_ino_t ino, xfs_fsblock_t *firstblock, - xfs_bmap_free_t *flist, xfs_extlen_t total) -{ - xfs_da_args_t args; - int count, totallen, newsize, retval; - - ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); - XFS_STATS_INC(xs_dir_remove); - /* - * Fill in the arg structure for this request. - */ - args.name = name; - args.namelen = namelen; - args.hashval = xfs_da_hashname(name, namelen); - args.inumber = ino; - args.dp = dp; - args.firstblock = firstblock; - args.flist = flist; - args.total = total; - args.whichfork = XFS_DATA_FORK; - args.trans = trans; - args.justcheck = args.addname = args.oknoent = 0; - - /* - * Decide on what work routines to call based on the inode size. - */ - if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) { - retval = xfs_dir_shortform_removename(&args); - } else if (xfs_bmap_one_block(dp, XFS_DATA_FORK)) { - retval = xfs_dir_leaf_removename(&args, &count, &totallen); - if (retval == 0) { - newsize = XFS_DIR_SF_ALLFIT(count, totallen); - if (newsize <= XFS_IFORK_DSIZE(dp)) { - retval = xfs_dir_leaf_to_shortform(&args); - } - } - } else { - retval = xfs_dir_node_removename(&args); - } - return(retval); -} - -static int /* error */ -xfs_dir_lookup(xfs_trans_t *trans, xfs_inode_t *dp, char *name, int namelen, - xfs_ino_t *inum) -{ - xfs_da_args_t args; - int retval; - - ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); - - XFS_STATS_INC(xs_dir_lookup); - /* - * Fill in the arg structure for this request. - */ - args.name = name; - args.namelen = namelen; - args.hashval = xfs_da_hashname(name, namelen); - args.inumber = 0; - args.dp = dp; - args.firstblock = NULL; - args.flist = NULL; - args.total = 0; - args.whichfork = XFS_DATA_FORK; - args.trans = trans; - args.justcheck = args.addname = 0; - args.oknoent = 1; - - /* - * Decide on what work routines to call based on the inode size. - */ - if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) { - retval = xfs_dir_shortform_lookup(&args); - } else if (xfs_bmap_one_block(dp, XFS_DATA_FORK)) { - retval = xfs_dir_leaf_lookup(&args); - } else { - retval = xfs_dir_node_lookup(&args); - } - if (retval == EEXIST) - retval = 0; - *inum = args.inumber; - return(retval); -} - -/* - * Implement readdir. - */ -static int /* error */ -xfs_dir_getdents(xfs_trans_t *trans, xfs_inode_t *dp, uio_t *uio, int *eofp) -{ - xfs_dirent_t *dbp; - int alignment, retval; - xfs_dir_put_t put; - - XFS_STATS_INC(xs_dir_getdents); - ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); - - /* - * If our caller has given us a single contiguous memory buffer, - * just work directly within that buffer. If it's in user memory, - * lock it down first. - */ - alignment = sizeof(xfs_off_t) - 1; - if ((uio->uio_iovcnt == 1) && - (((__psint_t)uio->uio_iov[0].iov_base & alignment) == 0) && - ((uio->uio_iov[0].iov_len & alignment) == 0)) { - dbp = NULL; - put = xfs_dir_put_dirent64_direct; - } else { - dbp = kmem_alloc(sizeof(*dbp) + MAXNAMELEN, KM_SLEEP); - put = xfs_dir_put_dirent64_uio; - } - - /* - * Decide on what work routines to call based on the inode size. - */ - *eofp = 0; - - if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) { - retval = xfs_dir_shortform_getdents(dp, uio, eofp, dbp, put); - } else if (xfs_bmap_one_block(dp, XFS_DATA_FORK)) { - retval = xfs_dir_leaf_getdents(trans, dp, uio, eofp, dbp, put); - } else { - retval = xfs_dir_node_getdents(trans, dp, uio, eofp, dbp, put); - } - if (dbp != NULL) - kmem_free(dbp, sizeof(*dbp) + MAXNAMELEN); - - return(retval); -} - -static int /* error */ -xfs_dir_replace(xfs_trans_t *trans, xfs_inode_t *dp, char *name, int namelen, - xfs_ino_t inum, xfs_fsblock_t *firstblock, - xfs_bmap_free_t *flist, xfs_extlen_t total) -{ - xfs_da_args_t args; - int retval; - - ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); - - if ((retval = xfs_dir_ino_validate(trans->t_mountp, inum))) - return retval; - - /* - * Fill in the arg structure for this request. - */ - args.name = name; - args.namelen = namelen; - args.hashval = xfs_da_hashname(name, namelen); - args.inumber = inum; - args.dp = dp; - args.firstblock = firstblock; - args.flist = flist; - args.total = total; - args.whichfork = XFS_DATA_FORK; - args.trans = trans; - args.justcheck = args.addname = args.oknoent = 0; - - /* - * Decide on what work routines to call based on the inode size. - */ - if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) { - retval = xfs_dir_shortform_replace(&args); - } else if (xfs_bmap_one_block(dp, XFS_DATA_FORK)) { - retval = xfs_dir_leaf_replace(&args); - } else { - retval = xfs_dir_node_replace(&args); - } - - return(retval); -} - -static int -xfs_dir_shortform_validate_ondisk(xfs_mount_t *mp, xfs_dinode_t *dp) -{ - xfs_ino_t ino; - int namelen_sum; - int count; - xfs_dir_shortform_t *sf; - xfs_dir_sf_entry_t *sfe; - int i; - - - - if ((INT_GET(dp->di_core.di_mode, ARCH_CONVERT) & S_IFMT) != S_IFDIR) { - return 0; - } - if (INT_GET(dp->di_core.di_format, ARCH_CONVERT) != XFS_DINODE_FMT_LOCAL) { - return 0; - } - if (INT_GET(dp->di_core.di_size, ARCH_CONVERT) < sizeof(sf->hdr)) { - xfs_fs_cmn_err(CE_WARN, mp, "Invalid shortform size: dp 0x%p", - dp); - return 1; - } - sf = (xfs_dir_shortform_t *)(&dp->di_u.di_dirsf); - ino = XFS_GET_DIR_INO8(sf->hdr.parent); - if (xfs_dir_ino_validate(mp, ino)) - return 1; - - count = sf->hdr.count; - if ((count < 0) || ((count * 10) > XFS_LITINO(mp))) { - xfs_fs_cmn_err(CE_WARN, mp, - "Invalid shortform count: dp 0x%p", dp); - return(1); - } - - if (count == 0) { - return 0; - } - - namelen_sum = 0; - sfe = &sf->list[0]; - for (i = sf->hdr.count - 1; i >= 0; i--) { - ino = XFS_GET_DIR_INO8(sfe->inumber); - xfs_dir_ino_validate(mp, ino); - if (sfe->namelen >= XFS_LITINO(mp)) { - xfs_fs_cmn_err(CE_WARN, mp, - "Invalid shortform namelen: dp 0x%p", dp); - return 1; - } - namelen_sum += sfe->namelen; - sfe = XFS_DIR_SF_NEXTENTRY(sfe); - } - if (namelen_sum >= XFS_LITINO(mp)) { - xfs_fs_cmn_err(CE_WARN, mp, - "Invalid shortform namelen: dp 0x%p", dp); - return 1; - } - - return 0; -} - -/*======================================================================== - * External routines when dirsize == XFS_LBSIZE(dp->i_mount). - *========================================================================*/ - -/* - * Add a name to the leaf directory structure - * This is the external routine. - */ -int -xfs_dir_leaf_addname(xfs_da_args_t *args) -{ - int index, retval; - xfs_dabuf_t *bp; - - retval = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp, - XFS_DATA_FORK); - if (retval) - return(retval); - ASSERT(bp != NULL); - - retval = xfs_dir_leaf_lookup_int(bp, args, &index); - if (retval == ENOENT) - retval = xfs_dir_leaf_add(bp, args, index); - xfs_da_buf_done(bp); - return(retval); -} - -/* - * Remove a name from the leaf directory structure - * This is the external routine. - */ -STATIC int -xfs_dir_leaf_removename(xfs_da_args_t *args, int *count, int *totallen) -{ - xfs_dir_leafblock_t *leaf; - int index, retval; - xfs_dabuf_t *bp; - - retval = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp, - XFS_DATA_FORK); - if (retval) - return(retval); - ASSERT(bp != NULL); - leaf = bp->data; - ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); - retval = xfs_dir_leaf_lookup_int(bp, args, &index); - if (retval == EEXIST) { - (void)xfs_dir_leaf_remove(args->trans, bp, index); - *count = be16_to_cpu(leaf->hdr.count); - *totallen = be16_to_cpu(leaf->hdr.namebytes); - retval = 0; - } - xfs_da_buf_done(bp); - return(retval); -} - -/* - * Look up a name in a leaf directory structure. - * This is the external routine. - */ -STATIC int -xfs_dir_leaf_lookup(xfs_da_args_t *args) -{ - int index, retval; - xfs_dabuf_t *bp; - - retval = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp, - XFS_DATA_FORK); - if (retval) - return(retval); - ASSERT(bp != NULL); - retval = xfs_dir_leaf_lookup_int(bp, args, &index); - xfs_da_brelse(args->trans, bp); - return(retval); -} - -/* - * Copy out directory entries for getdents(), for leaf directories. - */ -STATIC int -xfs_dir_leaf_getdents(xfs_trans_t *trans, xfs_inode_t *dp, uio_t *uio, - int *eofp, xfs_dirent_t *dbp, xfs_dir_put_t put) -{ - xfs_dabuf_t *bp; - int retval, eob; - - retval = xfs_da_read_buf(dp->i_transp, dp, 0, -1, &bp, XFS_DATA_FORK); - if (retval) - return(retval); - ASSERT(bp != NULL); - retval = xfs_dir_leaf_getdents_int(bp, dp, 0, uio, &eob, dbp, put, -1); - xfs_da_brelse(trans, bp); - *eofp = (eob == 0); - return(retval); -} - -/* - * Look up a name in a leaf directory structure, replace the inode number. - * This is the external routine. - */ -STATIC int -xfs_dir_leaf_replace(xfs_da_args_t *args) -{ - int index, retval; - xfs_dabuf_t *bp; - xfs_ino_t inum; - xfs_dir_leafblock_t *leaf; - xfs_dir_leaf_entry_t *entry; - xfs_dir_leaf_name_t *namest; - - inum = args->inumber; - retval = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp, - XFS_DATA_FORK); - if (retval) - return(retval); - ASSERT(bp != NULL); - retval = xfs_dir_leaf_lookup_int(bp, args, &index); - if (retval == EEXIST) { - leaf = bp->data; - entry = &leaf->entries[index]; - namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, be16_to_cpu(entry->nameidx)); - /* XXX - replace assert? */ - XFS_DIR_SF_PUT_DIRINO(&inum, &namest->inumber); - xfs_da_log_buf(args->trans, bp, - XFS_DA_LOGRANGE(leaf, namest, sizeof(namest->inumber))); - xfs_da_buf_done(bp); - retval = 0; - } else - xfs_da_brelse(args->trans, bp); - return(retval); -} - - -/*======================================================================== - * External routines when dirsize > XFS_LBSIZE(mp). - *========================================================================*/ - -/* - * Add a name to a Btree-format directory. - * - * This will involve walking down the Btree, and may involve splitting - * leaf nodes and even splitting intermediate nodes up to and including - * the root node (a special case of an intermediate node). - */ -STATIC int -xfs_dir_node_addname(xfs_da_args_t *args) -{ - xfs_da_state_t *state; - xfs_da_state_blk_t *blk; - int retval, error; - - /* - * Fill in bucket of arguments/results/context to carry around. - */ - state = xfs_da_state_alloc(); - state->args = args; - state->mp = args->dp->i_mount; - state->blocksize = state->mp->m_sb.sb_blocksize; - state->node_ents = state->mp->m_dir_node_ents; - - /* - * Search to see if name already exists, and get back a pointer - * to where it should go. - */ - error = xfs_da_node_lookup_int(state, &retval); - if (error) - retval = error; - if (retval != ENOENT) - goto error; - blk = &state->path.blk[ state->path.active-1 ]; - ASSERT(blk->magic == XFS_DIR_LEAF_MAGIC); - retval = xfs_dir_leaf_add(blk->bp, args, blk->index); - if (retval == 0) { - /* - * Addition succeeded, update Btree hashvals. - */ - if (!args->justcheck) - xfs_da_fixhashpath(state, &state->path); - } else { - /* - * Addition failed, split as many Btree elements as required. - */ - if (args->total == 0) { - ASSERT(retval == ENOSPC); - goto error; - } - retval = xfs_da_split(state); - } -error: - xfs_da_state_free(state); - - return(retval); -} - -/* - * Remove a name from a B-tree directory. - * - * This will involve walking down the Btree, and may involve joining - * leaf nodes and even joining intermediate nodes up to and including - * the root node (a special case of an intermediate node). - */ -STATIC int -xfs_dir_node_removename(xfs_da_args_t *args) -{ - xfs_da_state_t *state; - xfs_da_state_blk_t *blk; - int retval, error; - - state = xfs_da_state_alloc(); - state->args = args; - state->mp = args->dp->i_mount; - state->blocksize = state->mp->m_sb.sb_blocksize; - state->node_ents = state->mp->m_dir_node_ents; - - /* - * Search to see if name exists, and get back a pointer to it. - */ - error = xfs_da_node_lookup_int(state, &retval); - if (error) - retval = error; - if (retval != EEXIST) { - xfs_da_state_free(state); - return(retval); - } - - /* - * Remove the name and update the hashvals in the tree. - */ - blk = &state->path.blk[ state->path.active-1 ]; - ASSERT(blk->magic == XFS_DIR_LEAF_MAGIC); - retval = xfs_dir_leaf_remove(args->trans, blk->bp, blk->index); - xfs_da_fixhashpath(state, &state->path); - - /* - * Check to see if the tree needs to be collapsed. - */ - error = 0; - if (retval) { - error = xfs_da_join(state); - } - - xfs_da_state_free(state); - if (error) - return(error); - return(0); -} - -/* - * Look up a filename in a int directory. - * Use an internal routine to actually do all the work. - */ -STATIC int -xfs_dir_node_lookup(xfs_da_args_t *args) -{ - xfs_da_state_t *state; - int retval, error, i; - - state = xfs_da_state_alloc(); - state->args = args; - state->mp = args->dp->i_mount; - state->blocksize = state->mp->m_sb.sb_blocksize; - state->node_ents = state->mp->m_dir_node_ents; - - /* - * Search to see if name exists, - * and get back a pointer to it. - */ - error = xfs_da_node_lookup_int(state, &retval); - if (error) { - retval = error; - } - - /* - * If not in a transaction, we have to release all the buffers. - */ - for (i = 0; i < state->path.active; i++) { - xfs_da_brelse(args->trans, state->path.blk[i].bp); - state->path.blk[i].bp = NULL; - } - - xfs_da_state_free(state); - return(retval); -} - -STATIC int -xfs_dir_node_getdents(xfs_trans_t *trans, xfs_inode_t *dp, uio_t *uio, - int *eofp, xfs_dirent_t *dbp, xfs_dir_put_t put) -{ - xfs_da_intnode_t *node; - xfs_da_node_entry_t *btree; - xfs_dir_leafblock_t *leaf = NULL; - xfs_dablk_t bno, nextbno; - xfs_dahash_t cookhash; - xfs_mount_t *mp; - int error, eob, i; - xfs_dabuf_t *bp; - xfs_daddr_t nextda; - - /* - * Pick up our context. - */ - mp = dp->i_mount; - bp = NULL; - bno = XFS_DA_COOKIE_BNO(mp, uio->uio_offset); - cookhash = XFS_DA_COOKIE_HASH(mp, uio->uio_offset); - - xfs_dir_trace_g_du("node: start", dp, uio); - - /* - * Re-find our place, even if we're confused about what our place is. - * - * First we check the block number from the magic cookie, it is a - * cache of where we ended last time. If we find a leaf block, and - * the starting hashval in that block is less than our desired - * hashval, then we run with it. - */ - if (bno > 0) { - error = xfs_da_read_buf(trans, dp, bno, -2, &bp, XFS_DATA_FORK); - if ((error != 0) && (error != EFSCORRUPTED)) - return(error); - if (bp) - leaf = bp->data; - if (bp && be16_to_cpu(leaf->hdr.info.magic) != XFS_DIR_LEAF_MAGIC) { - xfs_dir_trace_g_dub("node: block not a leaf", - dp, uio, bno); - xfs_da_brelse(trans, bp); - bp = NULL; - } - if (bp && be32_to_cpu(leaf->entries[0].hashval) > cookhash) { - xfs_dir_trace_g_dub("node: leaf hash too large", - dp, uio, bno); - xfs_da_brelse(trans, bp); - bp = NULL; - } - if (bp && cookhash > be32_to_cpu(leaf->entries[ - be16_to_cpu(leaf->hdr.count) - 1].hashval)) { - xfs_dir_trace_g_dub("node: leaf hash too small", - dp, uio, bno); - xfs_da_brelse(trans, bp); - bp = NULL; - } - } - - /* - * If we did not find a leaf block from the blockno in the cookie, - * or we there was no blockno in the cookie (eg: first time thru), - * the we start at the top of the Btree and re-find our hashval. - */ - if (bp == NULL) { - xfs_dir_trace_g_du("node: start at root" , dp, uio); - bno = 0; - for (;;) { - error = xfs_da_read_buf(trans, dp, bno, -1, &bp, - XFS_DATA_FORK); - if (error) - return(error); - if (bp == NULL) - return(XFS_ERROR(EFSCORRUPTED)); - node = bp->data; - if (be16_to_cpu(node->hdr.info.magic) != XFS_DA_NODE_MAGIC) - break; - btree = &node->btree[0]; - xfs_dir_trace_g_dun("node: node detail", dp, uio, node); - for (i = 0; i < be16_to_cpu(node->hdr.count); btree++, i++) { - if (be32_to_cpu(btree->hashval) >= cookhash) { - bno = be32_to_cpu(btree->before); - break; - } - } - if (i == be16_to_cpu(node->hdr.count)) { - xfs_da_brelse(trans, bp); - xfs_dir_trace_g_du("node: hash beyond EOF", - dp, uio); - uio->uio_offset = XFS_DA_MAKE_COOKIE(mp, 0, 0, - XFS_DA_MAXHASH); - *eofp = 1; - return(0); - } - xfs_dir_trace_g_dub("node: going to block", - dp, uio, bno); - xfs_da_brelse(trans, bp); - } - } - ASSERT(cookhash != XFS_DA_MAXHASH); - - /* - * We've dropped down to the (first) leaf block that contains the - * hashval we are interested in. Continue rolling upward thru the - * leaf blocks until we fill up our buffer. - */ - for (;;) { - leaf = bp->data; - if (unlikely(be16_to_cpu(leaf->hdr.info.magic) != XFS_DIR_LEAF_MAGIC)) { - xfs_dir_trace_g_dul("node: not a leaf", dp, uio, leaf); - xfs_da_brelse(trans, bp); - XFS_CORRUPTION_ERROR("xfs_dir_node_getdents(1)", - XFS_ERRLEVEL_LOW, mp, leaf); - return XFS_ERROR(EFSCORRUPTED); - } - xfs_dir_trace_g_dul("node: leaf detail", dp, uio, leaf); - if ((nextbno = be32_to_cpu(leaf->hdr.info.forw))) { - nextda = xfs_da_reada_buf(trans, dp, nextbno, - XFS_DATA_FORK); - } else - nextda = -1; - error = xfs_dir_leaf_getdents_int(bp, dp, bno, uio, &eob, dbp, - put, nextda); - xfs_da_brelse(trans, bp); - bno = nextbno; - if (eob) { - xfs_dir_trace_g_dub("node: E-O-B", dp, uio, bno); - *eofp = 0; - return(error); - } - if (bno == 0) - break; - error = xfs_da_read_buf(trans, dp, bno, nextda, &bp, - XFS_DATA_FORK); - if (error) - return(error); - if (unlikely(bp == NULL)) { - XFS_ERROR_REPORT("xfs_dir_node_getdents(2)", - XFS_ERRLEVEL_LOW, mp); - return(XFS_ERROR(EFSCORRUPTED)); - } - } - *eofp = 1; - xfs_dir_trace_g_du("node: E-O-F", dp, uio); - return(0); -} - -/* - * Look up a filename in an int directory, replace the inode number. - * Use an internal routine to actually do the lookup. - */ -STATIC int -xfs_dir_node_replace(xfs_da_args_t *args) -{ - xfs_da_state_t *state; - xfs_da_state_blk_t *blk; - xfs_dir_leafblock_t *leaf; - xfs_dir_leaf_entry_t *entry; - xfs_dir_leaf_name_t *namest; - xfs_ino_t inum; - int retval, error, i; - xfs_dabuf_t *bp; - - state = xfs_da_state_alloc(); - state->args = args; - state->mp = args->dp->i_mount; - state->blocksize = state->mp->m_sb.sb_blocksize; - state->node_ents = state->mp->m_dir_node_ents; - inum = args->inumber; - - /* - * Search to see if name exists, - * and get back a pointer to it. - */ - error = xfs_da_node_lookup_int(state, &retval); - if (error) { - retval = error; - } - - if (retval == EEXIST) { - blk = &state->path.blk[state->path.active - 1]; - ASSERT(blk->magic == XFS_DIR_LEAF_MAGIC); - bp = blk->bp; - leaf = bp->data; - entry = &leaf->entries[blk->index]; - namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, be16_to_cpu(entry->nameidx)); - /* XXX - replace assert ? */ - XFS_DIR_SF_PUT_DIRINO(&inum, &namest->inumber); - xfs_da_log_buf(args->trans, bp, - XFS_DA_LOGRANGE(leaf, namest, sizeof(namest->inumber))); - xfs_da_buf_done(bp); - blk->bp = NULL; - retval = 0; - } else { - i = state->path.active - 1; - xfs_da_brelse(args->trans, state->path.blk[i].bp); - state->path.blk[i].bp = NULL; - } - for (i = 0; i < state->path.active - 1; i++) { - xfs_da_brelse(args->trans, state->path.blk[i].bp); - state->path.blk[i].bp = NULL; - } - - xfs_da_state_free(state); - return(retval); -} - -#if defined(XFS_DIR_TRACE) -/* - * Add a trace buffer entry for an inode and a uio. - */ -void -xfs_dir_trace_g_du(char *where, xfs_inode_t *dp, uio_t *uio) -{ - xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DU, where, - (void *)dp, (void *)dp->i_mount, - (void *)((unsigned long)(uio->uio_offset >> 32)), - (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)), - (void *)(unsigned long)uio->uio_resid, - NULL, NULL, NULL, NULL, NULL, NULL, NULL); -} - -/* - * Add a trace buffer entry for an inode and a uio. - */ -void -xfs_dir_trace_g_dub(char *where, xfs_inode_t *dp, uio_t *uio, xfs_dablk_t bno) -{ - xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DUB, where, - (void *)dp, (void *)dp->i_mount, - (void *)((unsigned long)(uio->uio_offset >> 32)), - (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)), - (void *)(unsigned long)uio->uio_resid, - (void *)(unsigned long)bno, - NULL, NULL, NULL, NULL, NULL, NULL); -} - -/* - * Add a trace buffer entry for an inode and a uio. - */ -void -xfs_dir_trace_g_dun(char *where, xfs_inode_t *dp, uio_t *uio, - xfs_da_intnode_t *node) -{ - int last = be16_to_cpu(node->hdr.count) - 1; - - xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DUN, where, - (void *)dp, (void *)dp->i_mount, - (void *)((unsigned long)(uio->uio_offset >> 32)), - (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)), - (void *)(unsigned long)uio->uio_resid, - (void *)(unsigned long)be32_to_cpu(node->hdr.info.forw), - (void *)(unsigned long) - be16_to_cpu(node->hdr.count), - (void *)(unsigned long) - be32_to_cpu(node->btree[0].hashval), - (void *)(unsigned long) - be32_to_cpu(node->btree[last].hashval), - NULL, NULL, NULL); -} - -/* - * Add a trace buffer entry for an inode and a uio. - */ -void -xfs_dir_trace_g_dul(char *where, xfs_inode_t *dp, uio_t *uio, - xfs_dir_leafblock_t *leaf) -{ - int last = be16_to_cpu(leaf->hdr.count) - 1; - - xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DUL, where, - (void *)dp, (void *)dp->i_mount, - (void *)((unsigned long)(uio->uio_offset >> 32)), - (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)), - (void *)(unsigned long)uio->uio_resid, - (void *)(unsigned long)be32_to_cpu(leaf->hdr.info.forw), - (void *)(unsigned long)be16_to_cpu(leaf->hdr.count), - (void *)(unsigned long)be32_to_cpu(leaf->entries[0].hashval), - (void *)(unsigned long)be32_to_cpu(leaf->entries[last].hashval), - NULL, NULL, NULL); -} - -/* - * Add a trace buffer entry for an inode and a uio. - */ -void -xfs_dir_trace_g_due(char *where, xfs_inode_t *dp, uio_t *uio, - xfs_dir_leaf_entry_t *entry) -{ - xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DUE, where, - (void *)dp, (void *)dp->i_mount, - (void *)((unsigned long)(uio->uio_offset >> 32)), - (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)), - (void *)(unsigned long)uio->uio_resid, - (void *)(unsigned long)be32_to_cpu(entry->hashval), - NULL, NULL, NULL, NULL, NULL, NULL); -} - -/* - * Add a trace buffer entry for an inode and a uio. - */ -void -xfs_dir_trace_g_duc(char *where, xfs_inode_t *dp, uio_t *uio, xfs_off_t cookie) -{ - xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DUC, where, - (void *)dp, (void *)dp->i_mount, - (void *)((unsigned long)(uio->uio_offset >> 32)), - (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)), - (void *)(unsigned long)uio->uio_resid, - (void *)((unsigned long)(cookie >> 32)), - (void *)((unsigned long)(cookie & 0xFFFFFFFF)), - NULL, NULL, NULL, NULL, NULL); -} - -/* - * Add a trace buffer entry for the arguments given to the routine, - * generic form. - */ -void -xfs_dir_trace_enter(int type, char *where, - void * a0, void * a1, - void * a2, void * a3, - void * a4, void * a5, - void * a6, void * a7, - void * a8, void * a9, - void * a10, void * a11) -{ - ASSERT(xfs_dir_trace_buf); - ktrace_enter(xfs_dir_trace_buf, (void *)(unsigned long)type, - (void *)where, - (void *)a0, (void *)a1, (void *)a2, - (void *)a3, (void *)a4, (void *)a5, - (void *)a6, (void *)a7, (void *)a8, - (void *)a9, (void *)a10, (void *)a11, - NULL, NULL); -} -#endif /* XFS_DIR_TRACE */ diff --git a/fs/xfs/xfs_dir.h b/fs/xfs/xfs_dir.h index 8cc8afb9f6c..e69de29bb2d 100644 --- a/fs/xfs/xfs_dir.h +++ b/fs/xfs/xfs_dir.h @@ -1,142 +0,0 @@ -/* - * Copyright (c) 2000,2005 Silicon Graphics, Inc. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -#ifndef __XFS_DIR_H__ -#define __XFS_DIR_H__ - -/* - * Large directories are structured around Btrees where all the data - * elements are in the leaf nodes. Filenames are hashed into an int, - * then that int is used as the index into the Btree. Since the hashval - * of a filename may not be unique, we may have duplicate keys. The - * internal links in the Btree are logical block offsets into the file. - * - * Small directories use a different format and are packed as tightly - * as possible so as to fit into the literal area of the inode. - */ - -/*======================================================================== - * Function prototypes for the kernel. - *========================================================================*/ - -struct uio; -struct xfs_bmap_free; -struct xfs_da_args; -struct xfs_dinode; -struct xfs_inode; -struct xfs_mount; -struct xfs_trans; - -/* - * Directory function types. - * Put in structures (xfs_dirops_t) for v1 and v2 directories. - */ -typedef void (*xfs_dir_mount_t)(struct xfs_mount *mp); -typedef int (*xfs_dir_isempty_t)(struct xfs_inode *dp); -typedef int (*xfs_dir_init_t)(struct xfs_trans *tp, - struct xfs_inode *dp, - struct xfs_inode *pdp); -typedef int (*xfs_dir_createname_t)(struct xfs_trans *tp, - struct xfs_inode *dp, - char *name, - int namelen, - xfs_ino_t inum, - xfs_fsblock_t *first, - struct xfs_bmap_free *flist, - xfs_extlen_t total); -typedef int (*xfs_dir_lookup_t)(struct xfs_trans *tp, - struct xfs_inode *dp, - char *name, - int namelen, - xfs_ino_t *inum); -typedef int (*xfs_dir_removename_t)(struct xfs_trans *tp, - struct xfs_inode *dp, - char *name, - int namelen, - xfs_ino_t ino, - xfs_fsblock_t *first, - struct xfs_bmap_free *flist, - xfs_extlen_t total); -typedef int (*xfs_dir_getdents_t)(struct xfs_trans *tp, - struct xfs_inode *dp, - struct uio *uio, - int *eofp); -typedef int (*xfs_dir_replace_t)(struct xfs_trans *tp, - struct xfs_inode *dp, - char *name, - int namelen, - xfs_ino_t inum, - xfs_fsblock_t *first, - struct xfs_bmap_free *flist, - xfs_extlen_t total); -typedef int (*xfs_dir_canenter_t)(struct xfs_trans *tp, - struct xfs_inode *dp, - char *name, - int namelen); -typedef int (*xfs_dir_shortform_validate_ondisk_t)(struct xfs_mount *mp, - struct xfs_dinode *dip); -typedef int (*xfs_dir_shortform_to_single_t)(struct xfs_da_args *args); - -typedef struct xfs_dirops { - xfs_dir_mount_t xd_mount; - xfs_dir_isempty_t xd_isempty; - xfs_dir_init_t xd_init; - xfs_dir_createname_t xd_createname; - xfs_dir_lookup_t xd_lookup; - xfs_dir_removename_t xd_removename; - xfs_dir_getdents_t xd_getdents; - xfs_dir_replace_t xd_replace; - xfs_dir_canenter_t xd_canenter; - xfs_dir_shortform_validate_ondisk_t xd_shortform_validate_ondisk; - xfs_dir_shortform_to_single_t xd_shortform_to_single; -} xfs_dirops_t; - -/* - * Overall external interface routines. - */ -void xfs_dir_startup(void); /* called exactly once */ - -#define XFS_DIR_MOUNT(mp) \ - ((mp)->m_dirops.xd_mount(mp)) -#define XFS_DIR_ISEMPTY(mp,dp) \ - ((mp)->m_dirops.xd_isempty(dp)) -#define XFS_DIR_INIT(mp,tp,dp,pdp) \ - ((mp)->m_dirops.xd_init(tp,dp,pdp)) -#define XFS_DIR_CREATENAME(mp,tp,dp,name,namelen,inum,first,flist,total) \ - ((mp)->m_dirops.xd_createname(tp,dp,name,namelen,inum,first,flist,\ - total)) -#define XFS_DIR_LOOKUP(mp,tp,dp,name,namelen,inum) \ - ((mp)->m_dirops.xd_lookup(tp,dp,name,namelen,inum)) -#define XFS_DIR_REMOVENAME(mp,tp,dp,name,namelen,ino,first,flist,total) \ - ((mp)->m_dirops.xd_removename(tp,dp,name,namelen,ino,first,flist,total)) -#define XFS_DIR_GETDENTS(mp,tp,dp,uio,eofp) \ - ((mp)->m_dirops.xd_getdents(tp,dp,uio,eofp)) -#define XFS_DIR_REPLACE(mp,tp,dp,name,namelen,inum,first,flist,total) \ - ((mp)->m_dirops.xd_replace(tp,dp,name,namelen,inum,first,flist,total)) -#define XFS_DIR_CANENTER(mp,tp,dp,name,namelen) \ - ((mp)->m_dirops.xd_canenter(tp,dp,name,namelen)) -#define XFS_DIR_SHORTFORM_VALIDATE_ONDISK(mp,dip) \ - ((mp)->m_dirops.xd_shortform_validate_ondisk(mp,dip)) -#define XFS_DIR_SHORTFORM_TO_SINGLE(mp,args) \ - ((mp)->m_dirops.xd_shortform_to_single(args)) - -#define XFS_DIR_IS_V1(mp) ((mp)->m_dirversion == 1) -#define XFS_DIR_IS_V2(mp) ((mp)->m_dirversion == 2) -extern xfs_dirops_t xfsv1_dirops; -extern xfs_dirops_t xfsv2_dirops; - -#endif /* __XFS_DIR_H__ */ diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c index 80238a2263f..8edbe1adb95 100644 --- a/fs/xfs/xfs_dir2.c +++ b/fs/xfs/xfs_dir2.c @@ -24,21 +24,18 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_dmapi.h" #include "xfs_mount.h" #include "xfs_da_btree.h" #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_inode_item.h" #include "xfs_bmap.h" -#include "xfs_dir_leaf.h" #include "xfs_dir2_data.h" #include "xfs_dir2_leaf.h" #include "xfs_dir2_block.h" @@ -46,69 +43,14 @@ #include "xfs_dir2_trace.h" #include "xfs_error.h" -/* - * Declarations for interface routines. - */ -static void xfs_dir2_mount(xfs_mount_t *mp); -static int xfs_dir2_isempty(xfs_inode_t *dp); -static int xfs_dir2_init(xfs_trans_t *tp, xfs_inode_t *dp, - xfs_inode_t *pdp); -static int xfs_dir2_createname(xfs_trans_t *tp, xfs_inode_t *dp, - char *name, int namelen, xfs_ino_t inum, - xfs_fsblock_t *first, - xfs_bmap_free_t *flist, xfs_extlen_t total); -static int xfs_dir2_lookup(xfs_trans_t *tp, xfs_inode_t *dp, char *name, - int namelen, xfs_ino_t *inum); -static int xfs_dir2_removename(xfs_trans_t *tp, xfs_inode_t *dp, - char *name, int namelen, xfs_ino_t ino, - xfs_fsblock_t *first, - xfs_bmap_free_t *flist, xfs_extlen_t total); -static int xfs_dir2_getdents(xfs_trans_t *tp, xfs_inode_t *dp, uio_t *uio, - int *eofp); -static int xfs_dir2_replace(xfs_trans_t *tp, xfs_inode_t *dp, char *name, - int namelen, xfs_ino_t inum, - xfs_fsblock_t *first, xfs_bmap_free_t *flist, - xfs_extlen_t total); -static int xfs_dir2_canenter(xfs_trans_t *tp, xfs_inode_t *dp, char *name, - int namelen); -static int xfs_dir2_shortform_validate_ondisk(xfs_mount_t *mp, - xfs_dinode_t *dip); - -/* - * Utility routine declarations. - */ static int xfs_dir2_put_dirent64_direct(xfs_dir2_put_args_t *pa); static int xfs_dir2_put_dirent64_uio(xfs_dir2_put_args_t *pa); -/* - * Directory operations vector. - */ -xfs_dirops_t xfsv2_dirops = { - .xd_mount = xfs_dir2_mount, - .xd_isempty = xfs_dir2_isempty, - .xd_init = xfs_dir2_init, - .xd_createname = xfs_dir2_createname, - .xd_lookup = xfs_dir2_lookup, - .xd_removename = xfs_dir2_removename, - .xd_getdents = xfs_dir2_getdents, - .xd_replace = xfs_dir2_replace, - .xd_canenter = xfs_dir2_canenter, - .xd_shortform_validate_ondisk = xfs_dir2_shortform_validate_ondisk, - .xd_shortform_to_single = xfs_dir2_sf_to_block, -}; - -/* - * Interface routines. - */ - -/* - * Initialize directory-related fields in the mount structure. - */ -static void -xfs_dir2_mount( - xfs_mount_t *mp) /* filesystem mount point */ +void +xfs_dir_mount( + xfs_mount_t *mp) { - mp->m_dirversion = 2; + ASSERT(XFS_SB_VERSION_HASDIRV2(&mp->m_sb)); ASSERT((1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) <= XFS_MAX_BLOCKSIZE); mp->m_dirblksize = 1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog); @@ -128,73 +70,99 @@ xfs_dir2_mount( /* * Return 1 if directory contains only "." and "..". */ -static int /* return code */ -xfs_dir2_isempty( - xfs_inode_t *dp) /* incore inode structure */ +int +xfs_dir_isempty( + xfs_inode_t *dp) { - xfs_dir2_sf_t *sfp; /* shortform directory structure */ + xfs_dir2_sf_t *sfp; ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); - /* - * Might happen during shutdown. - */ - if (dp->i_d.di_size == 0) { + if (dp->i_d.di_size == 0) /* might happen during shutdown. */ return 1; - } if (dp->i_d.di_size > XFS_IFORK_DSIZE(dp)) return 0; sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data; return !sfp->hdr.count; } +/* + * Validate a given inode number. + */ +int +xfs_dir_ino_validate( + xfs_mount_t *mp, + xfs_ino_t ino) +{ + xfs_agblock_t agblkno; + xfs_agino_t agino; + xfs_agnumber_t agno; + int ino_ok; + int ioff; + + agno = XFS_INO_TO_AGNO(mp, ino); + agblkno = XFS_INO_TO_AGBNO(mp, ino); + ioff = XFS_INO_TO_OFFSET(mp, ino); + agino = XFS_OFFBNO_TO_AGINO(mp, agblkno, ioff); + ino_ok = + agno < mp->m_sb.sb_agcount && + agblkno < mp->m_sb.sb_agblocks && + agblkno != 0 && + ioff < (1 << mp->m_sb.sb_inopblog) && + XFS_AGINO_TO_INO(mp, agno, agino) == ino; + if (unlikely(XFS_TEST_ERROR(!ino_ok, mp, XFS_ERRTAG_DIR_INO_VALIDATE, + XFS_RANDOM_DIR_INO_VALIDATE))) { + xfs_fs_cmn_err(CE_WARN, mp, "Invalid inode number 0x%Lx", + (unsigned long long) ino); + XFS_ERROR_REPORT("xfs_dir_ino_validate", XFS_ERRLEVEL_LOW, mp); + return XFS_ERROR(EFSCORRUPTED); + } + return 0; +} + /* * Initialize a directory with its "." and ".." entries. */ -static int /* error */ -xfs_dir2_init( - xfs_trans_t *tp, /* transaction pointer */ - xfs_inode_t *dp, /* incore directory inode */ - xfs_inode_t *pdp) /* incore parent directory inode */ +int +xfs_dir_init( + xfs_trans_t *tp, + xfs_inode_t *dp, + xfs_inode_t *pdp) { - xfs_da_args_t args; /* operation arguments */ - int error; /* error return value */ + xfs_da_args_t args; + int error; memset((char *)&args, 0, sizeof(args)); args.dp = dp; args.trans = tp; ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); - if ((error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino))) { + if ((error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino))) return error; - } return xfs_dir2_sf_create(&args, pdp->i_ino); } /* Enter a name in a directory. */ -static int /* error */ -xfs_dir2_createname( - xfs_trans_t *tp, /* transaction pointer */ - xfs_inode_t *dp, /* incore directory inode */ - char *name, /* new entry name */ - int namelen, /* new entry name length */ +int +xfs_dir_createname( + xfs_trans_t *tp, + xfs_inode_t *dp, + char *name, + int namelen, xfs_ino_t inum, /* new entry inode number */ xfs_fsblock_t *first, /* bmap's firstblock */ xfs_bmap_free_t *flist, /* bmap's freeblock list */ xfs_extlen_t total) /* bmap's total block count */ { - xfs_da_args_t args; /* operation arguments */ - int rval; /* return value */ + xfs_da_args_t args; + int rval; int v; /* type-checking value */ ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); - if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum))) { + if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum))) return rval; - } XFS_STATS_INC(xs_dir_create); - /* - * Fill in the arg structure for this request. - */ + args.name = name; args.namelen = namelen; args.hashval = xfs_da_hashname(name, namelen); @@ -207,18 +175,16 @@ xfs_dir2_createname( args.trans = tp; args.justcheck = 0; args.addname = args.oknoent = 1; - /* - * Decide on what work routines to call based on the inode size. - */ + if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) rval = xfs_dir2_sf_addname(&args); - else if ((rval = xfs_dir2_isblock(tp, dp, &v))) { + else if ((rval = xfs_dir2_isblock(tp, dp, &v))) return rval; - } else if (v) + else if (v) rval = xfs_dir2_block_addname(&args); - else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) { + else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) return rval; - } else if (v) + else if (v) rval = xfs_dir2_leaf_addname(&args); else rval = xfs_dir2_node_addname(&args); @@ -228,24 +194,21 @@ xfs_dir2_createname( /* * Lookup a name in a directory, give back the inode number. */ -static int /* error */ -xfs_dir2_lookup( - xfs_trans_t *tp, /* transaction pointer */ - xfs_inode_t *dp, /* incore directory inode */ - char *name, /* lookup name */ - int namelen, /* lookup name length */ +int +xfs_dir_lookup( + xfs_trans_t *tp, + xfs_inode_t *dp, + char *name, + int namelen, xfs_ino_t *inum) /* out: inode number */ { - xfs_da_args_t args; /* operation arguments */ - int rval; /* return value */ + xfs_da_args_t args; + int rval; int v; /* type-checking value */ ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); XFS_STATS_INC(xs_dir_lookup); - /* - * Fill in the arg structure for this request. - */ args.name = name; args.namelen = namelen; args.hashval = xfs_da_hashname(name, namelen); @@ -258,18 +221,16 @@ xfs_dir2_lookup( args.trans = tp; args.justcheck = args.addname = 0; args.oknoent = 1; - /* - * Decide on what work routines to call based on the inode size. - */ + if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) rval = xfs_dir2_sf_lookup(&args); - else if ((rval = xfs_dir2_isblock(tp, dp, &v))) { + else if ((rval = xfs_dir2_isblock(tp, dp, &v))) return rval; - } else if (v) + else if (v) rval = xfs_dir2_block_lookup(&args); - else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) { + else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) return rval; - } else if (v) + else if (v) rval = xfs_dir2_leaf_lookup(&args); else rval = xfs_dir2_node_lookup(&args); @@ -283,26 +244,24 @@ xfs_dir2_lookup( /* * Remove an entry from a directory. */ -static int /* error */ -xfs_dir2_removename( - xfs_trans_t *tp, /* transaction pointer */ - xfs_inode_t *dp, /* incore directory inode */ - char *name, /* name of entry to remove */ - int namelen, /* name length of entry to remove */ - xfs_ino_t ino, /* inode number of entry to remove */ +int +xfs_dir_removename( + xfs_trans_t *tp, + xfs_inode_t *dp, + char *name, + int namelen, + xfs_ino_t ino, xfs_fsblock_t *first, /* bmap's firstblock */ xfs_bmap_free_t *flist, /* bmap's freeblock list */ xfs_extlen_t total) /* bmap's total block count */ { - xfs_da_args_t args; /* operation arguments */ - int rval; /* return value */ + xfs_da_args_t args; + int rval; int v; /* type-checking value */ ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); XFS_STATS_INC(xs_dir_remove); - /* - * Fill in the arg structure for this request. - */ + args.name = name; args.namelen = namelen; args.hashval = xfs_da_hashname(name, namelen); @@ -314,18 +273,16 @@ xfs_dir2_removename( args.whichfork = XFS_DATA_FORK; args.trans = tp; args.justcheck = args.addname = args.oknoent = 0; - /* - * Decide on what work routines to call based on the inode size. - */ + if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) rval = xfs_dir2_sf_removename(&args); - else if ((rval = xfs_dir2_isblock(tp, dp, &v))) { + else if ((rval = xfs_dir2_isblock(tp, dp, &v))) return rval; - } else if (v) + else if (v) rval = xfs_dir2_block_removename(&args); - else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) { + else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) return rval; - } else if (v) + else if (v) rval = xfs_dir2_leaf_removename(&args); else rval = xfs_dir2_node_removename(&args); @@ -335,10 +292,10 @@ xfs_dir2_removename( /* * Read a directory. */ -static int /* error */ -xfs_dir2_getdents( - xfs_trans_t *tp, /* transaction pointer */ - xfs_inode_t *dp, /* incore directory inode */ +int +xfs_dir_getdents( + xfs_trans_t *tp, + xfs_inode_t *dp, uio_t *uio, /* caller's buffer control */ int *eofp) /* out: eof reached */ { @@ -367,14 +324,11 @@ xfs_dir2_getdents( } *eofp = 0; - /* - * Decide on what work routines to call based on the inode size. - */ if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) rval = xfs_dir2_sf_getdents(dp, uio, eofp, dbp, put); - else if ((rval = xfs_dir2_isblock(tp, dp, &v))) { + else if ((rval = xfs_dir2_isblock(tp, dp, &v))) ; - } else if (v) + else if (v) rval = xfs_dir2_block_getdents(tp, dp, uio, eofp, dbp, put); else rval = xfs_dir2_leaf_getdents(tp, dp, uio, eofp, dbp, put); @@ -386,29 +340,26 @@ xfs_dir2_getdents( /* * Replace the inode number of a directory entry. */ -static int /* error */ -xfs_dir2_replace( - xfs_trans_t *tp, /* transaction pointer */ - xfs_inode_t *dp, /* incore directory inode */ +int +xfs_dir_replace( + xfs_trans_t *tp, + xfs_inode_t *dp, char *name, /* name of entry to replace */ - int namelen, /* name length of entry to replace */ + int namelen, xfs_ino_t inum, /* new inode number */ xfs_fsblock_t *first, /* bmap's firstblock */ xfs_bmap_free_t *flist, /* bmap's freeblock list */ xfs_extlen_t total) /* bmap's total block count */ { - xfs_da_args_t args; /* operation arguments */ - int rval; /* return value */ + xfs_da_args_t args; + int rval; int v; /* type-checking value */ ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); - if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum))) { + if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum))) return rval; - } - /* - * Fill in the arg structure for this request. - */ + args.name = name; args.namelen = namelen; args.hashval = xfs_da_hashname(name, namelen); @@ -420,18 +371,16 @@ xfs_dir2_replace( args.whichfork = XFS_DATA_FORK; args.trans = tp; args.justcheck = args.addname = args.oknoent = 0; - /* - * Decide on what work routines to call based on the inode size. - */ + if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) rval = xfs_dir2_sf_replace(&args); - else if ((rval = xfs_dir2_isblock(tp, dp, &v))) { + else if ((rval = xfs_dir2_isblock(tp, dp, &v))) return rval; - } else if (v) + else if (v) rval = xfs_dir2_block_replace(&args); - else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) { + else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) return rval; - } else if (v) + else if (v) rval = xfs_dir2_leaf_replace(&args); else rval = xfs_dir2_node_replace(&args); @@ -441,21 +390,19 @@ xfs_dir2_replace( /* * See if this entry can be added to the directory without allocating space. */ -static int /* error */ -xfs_dir2_canenter( - xfs_trans_t *tp, /* transaction pointer */ - xfs_inode_t *dp, /* incore directory inode */ +int +xfs_dir_canenter( + xfs_trans_t *tp, + xfs_inode_t *dp, char *name, /* name of entry to add */ - int namelen) /* name length of entry to add */ + int namelen) { - xfs_da_args_t args; /* operation arguments */ - int rval; /* return value */ + xfs_da_args_t args; + int rval; int v; /* type-checking value */ ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); - /* - * Fill in the arg structure for this request. - */ + args.name = name; args.namelen = namelen; args.hashval = xfs_da_hashname(name, namelen); @@ -467,37 +414,22 @@ xfs_dir2_canenter( args.whichfork = XFS_DATA_FORK; args.trans = tp; args.justcheck = args.addname = args.oknoent = 1; - /* - * Decide on what work routines to call based on the inode size. - */ + if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) rval = xfs_dir2_sf_addname(&args); - else if ((rval = xfs_dir2_isblock(tp, dp, &v))) { + else if ((rval = xfs_dir2_isblock(tp, dp, &v))) return rval; - } else if (v) + else if (v) rval = xfs_dir2_block_addname(&args); - else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) { + else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) return rval; - } else if (v) + else if (v) rval = xfs_dir2_leaf_addname(&args); else rval = xfs_dir2_node_addname(&args); return rval; } -/* - * Dummy routine for shortform inode validation. - * Can't really do this. - */ -/* ARGSUSED */ -static int /* error */ -xfs_dir2_shortform_validate_ondisk( - xfs_mount_t *mp, /* filesystem mount point */ - xfs_dinode_t *dip) /* ondisk inode */ -{ - return 0; -} - /* * Utility routines. */ @@ -507,24 +439,24 @@ xfs_dir2_shortform_validate_ondisk( * This routine is for data and free blocks, not leaf/node blocks * which are handled by xfs_da_grow_inode. */ -int /* error */ +int xfs_dir2_grow_inode( - xfs_da_args_t *args, /* operation arguments */ + xfs_da_args_t *args, int space, /* v2 dir's space XFS_DIR2_xxx_SPACE */ xfs_dir2_db_t *dbp) /* out: block number added */ { xfs_fileoff_t bno; /* directory offset of new block */ int count; /* count of filesystem blocks */ xfs_inode_t *dp; /* incore directory inode */ - int error; /* error return value */ + int error; int got; /* blocks actually mapped */ - int i; /* temp mapping index */ + int i; xfs_bmbt_irec_t map; /* single structure for bmap */ int mapi; /* mapping index */ xfs_bmbt_irec_t *mapp; /* bmap mapping structure(s) */ - xfs_mount_t *mp; /* filesystem mount point */ + xfs_mount_t *mp; int nmap; /* number of bmap entries */ - xfs_trans_t *tp; /* transaction pointer */ + xfs_trans_t *tp; xfs_dir2_trace_args_s("grow_inode", args, space); dp = args->dp; @@ -538,9 +470,8 @@ xfs_dir2_grow_inode( /* * Find the first hole for our block. */ - if ((error = xfs_bmap_first_unused(tp, dp, count, &bno, XFS_DATA_FORK))) { + if ((error = xfs_bmap_first_unused(tp, dp, count, &bno, XFS_DATA_FORK))) return error; - } nmap = 1; ASSERT(args->firstblock != NULL); /* @@ -549,13 +480,9 @@ xfs_dir2_grow_inode( if ((error = xfs_bmapi(tp, dp, bno, count, XFS_BMAPI_WRITE|XFS_BMAPI_METADATA|XFS_BMAPI_CONTIG, args->firstblock, args->total, &map, &nmap, - args->flist, NULL))) { + args->flist, NULL))) return error; - } ASSERT(nmap <= 1); - /* - * Got it in 1. - */ if (nmap == 1) { mapp = ↦ mapi = 1; @@ -646,20 +573,19 @@ xfs_dir2_grow_inode( /* * See if the directory is a single-block form directory. */ -int /* error */ +int xfs_dir2_isblock( - xfs_trans_t *tp, /* transaction pointer */ - xfs_inode_t *dp, /* incore directory inode */ + xfs_trans_t *tp, + xfs_inode_t *dp, int *vp) /* out: 1 is block, 0 is not block */ { xfs_fileoff_t last; /* last file offset */ - xfs_mount_t *mp; /* filesystem mount point */ - int rval; /* return value */ + xfs_mount_t *mp; + int rval; mp = dp->i_mount; - if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK))) { + if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK))) return rval; - } rval = XFS_FSB_TO_B(mp, last) == mp->m_dirblksize; ASSERT(rval == 0 || dp->i_d.di_size == mp->m_dirblksize); *vp = rval; @@ -669,20 +595,19 @@ xfs_dir2_isblock( /* * See if the directory is a single-leaf form directory. */ -int /* error */ +int xfs_dir2_isleaf( - xfs_trans_t *tp, /* transaction pointer */ - xfs_inode_t *dp, /* incore directory inode */ + xfs_trans_t *tp, + xfs_inode_t *dp, int *vp) /* out: 1 is leaf, 0 is not leaf */ { xfs_fileoff_t last; /* last file offset */ - xfs_mount_t *mp; /* filesystem mount point */ - int rval; /* return value */ + xfs_mount_t *mp; + int rval; mp = dp->i_mount; - if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK))) { + if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK))) return rval; - } *vp = last == mp->m_dirleafblk + (1 << mp->m_sb.sb_dirblklog); return 0; } @@ -690,9 +615,9 @@ xfs_dir2_isleaf( /* * Getdents put routine for 64-bit ABI, direct form. */ -static int /* error */ +static int xfs_dir2_put_dirent64_direct( - xfs_dir2_put_args_t *pa) /* argument bundle */ + xfs_dir2_put_args_t *pa) { xfs_dirent_t *idbp; /* dirent pointer */ iovec_t *iovp; /* io vector */ @@ -727,9 +652,9 @@ xfs_dir2_put_dirent64_direct( /* * Getdents put routine for 64-bit ABI, uio form. */ -static int /* error */ +static int xfs_dir2_put_dirent64_uio( - xfs_dir2_put_args_t *pa) /* argument bundle */ + xfs_dir2_put_args_t *pa) { xfs_dirent_t *idbp; /* dirent pointer */ int namelen; /* entry name length */ @@ -765,17 +690,17 @@ xfs_dir2_put_dirent64_uio( */ int xfs_dir2_shrink_inode( - xfs_da_args_t *args, /* operation arguments */ - xfs_dir2_db_t db, /* directory block number */ - xfs_dabuf_t *bp) /* block's buffer */ + xfs_da_args_t *args, + xfs_dir2_db_t db, + xfs_dabuf_t *bp) { xfs_fileoff_t bno; /* directory file offset */ xfs_dablk_t da; /* directory file offset */ int done; /* bunmap is finished */ - xfs_inode_t *dp; /* incore directory inode */ - int error; /* error return value */ - xfs_mount_t *mp; /* filesystem mount point */ - xfs_trans_t *tp; /* transaction pointer */ + xfs_inode_t *dp; + int error; + xfs_mount_t *mp; + xfs_trans_t *tp; xfs_dir2_trace_args_db("shrink_inode", args, db, bp); dp = args->dp; diff --git a/fs/xfs/xfs_dir2.h b/fs/xfs/xfs_dir2.h index 7dd364b1e03..86560b6f794 100644 --- a/fs/xfs/xfs_dir2.h +++ b/fs/xfs/xfs_dir2.h @@ -22,7 +22,9 @@ struct uio; struct xfs_dabuf; struct xfs_da_args; struct xfs_dir2_put_args; +struct xfs_bmap_free; struct xfs_inode; +struct xfs_mount; struct xfs_trans; /* @@ -73,7 +75,35 @@ typedef struct xfs_dir2_put_args { } xfs_dir2_put_args_t; /* - * Other interfaces used by the rest of the dir v2 code. + * Generic directory interface routines + */ +extern void xfs_dir_startup(void); +extern void xfs_dir_mount(struct xfs_mount *mp); +extern int xfs_dir_isempty(struct xfs_inode *dp); +extern int xfs_dir_init(struct xfs_trans *tp, struct xfs_inode *dp, + struct xfs_inode *pdp); +extern int xfs_dir_createname(struct xfs_trans *tp, struct xfs_inode *dp, + char *name, int namelen, xfs_ino_t inum, + xfs_fsblock_t *first, + struct xfs_bmap_free *flist, xfs_extlen_t tot); +extern int xfs_dir_lookup(struct xfs_trans *tp, struct xfs_inode *dp, + char *name, int namelen, xfs_ino_t *inum); +extern int xfs_dir_removename(struct xfs_trans *tp, struct xfs_inode *dp, + char *name, int namelen, xfs_ino_t ino, + xfs_fsblock_t *first, + struct xfs_bmap_free *flist, xfs_extlen_t tot); +extern int xfs_dir_getdents(struct xfs_trans *tp, struct xfs_inode *dp, + uio_t *uio, int *eofp); +extern int xfs_dir_replace(struct xfs_trans *tp, struct xfs_inode *dp, + char *name, int namelen, xfs_ino_t inum, + xfs_fsblock_t *first, + struct xfs_bmap_free *flist, xfs_extlen_t tot); +extern int xfs_dir_canenter(struct xfs_trans *tp, struct xfs_inode *dp, + char *name, int namelen); +extern int xfs_dir_ino_validate(struct xfs_mount *mp, xfs_ino_t ino); + +/* + * Utility routines for v2 directories. */ extern int xfs_dir2_grow_inode(struct xfs_da_args *args, int space, xfs_dir2_db_t *dbp); diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c index 2621ff521db..9d7438bba30 100644 --- a/fs/xfs/xfs_dir2_block.c +++ b/fs/xfs/xfs_dir2_block.c @@ -22,19 +22,16 @@ #include "xfs_inum.h" #include "xfs_trans.h" #include "xfs_sb.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_dmapi.h" #include "xfs_mount.h" #include "xfs_da_btree.h" #include "xfs_bmap_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_inode_item.h" -#include "xfs_dir_leaf.h" #include "xfs_dir2_data.h" #include "xfs_dir2_leaf.h" #include "xfs_dir2_block.h" @@ -51,6 +48,18 @@ static int xfs_dir2_block_lookup_int(xfs_da_args_t *args, xfs_dabuf_t **bpp, int *entno); static int xfs_dir2_block_sort(const void *a, const void *b); +static xfs_dahash_t xfs_dir_hash_dot, xfs_dir_hash_dotdot; + +/* + * One-time startup routine called from xfs_init(). + */ +void +xfs_dir_startup(void) +{ + xfs_dir_hash_dot = xfs_da_hashname(".", 1); + xfs_dir_hash_dotdot = xfs_da_hashname("..", 2); +} + /* * Add an entry to a block directory. */ diff --git a/fs/xfs/xfs_dir2_data.c b/fs/xfs/xfs_dir2_data.c index 7be37d38961..f7c79921707 100644 --- a/fs/xfs/xfs_dir2_data.c +++ b/fs/xfs/xfs_dir2_data.c @@ -22,18 +22,15 @@ #include "xfs_inum.h" #include "xfs_trans.h" #include "xfs_sb.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_dmapi.h" #include "xfs_mount.h" #include "xfs_da_btree.h" #include "xfs_bmap_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" #include "xfs_inode.h" -#include "xfs_dir_leaf.h" #include "xfs_dir2_data.h" #include "xfs_dir2_leaf.h" #include "xfs_dir2_block.h" diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c index 74ef99f2ee5..b1cf1fbf423 100644 --- a/fs/xfs/xfs_dir2_leaf.c +++ b/fs/xfs/xfs_dir2_leaf.c @@ -24,14 +24,12 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_dmapi.h" #include "xfs_mount.h" #include "xfs_da_btree.h" #include "xfs_bmap_btree.h" #include "xfs_attr_sf.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_dinode.h" #include "xfs_inode.h" diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c index b1f85cc7795..9ca71719b68 100644 --- a/fs/xfs/xfs_dir2_node.c +++ b/fs/xfs/xfs_dir2_node.c @@ -22,13 +22,11 @@ #include "xfs_inum.h" #include "xfs_trans.h" #include "xfs_sb.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_dmapi.h" #include "xfs_mount.h" #include "xfs_da_btree.h" #include "xfs_bmap_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" diff --git a/fs/xfs/xfs_dir2_sf.c b/fs/xfs/xfs_dir2_sf.c index 06afa1b324c..0cd77b17bf9 100644 --- a/fs/xfs/xfs_dir2_sf.c +++ b/fs/xfs/xfs_dir2_sf.c @@ -22,19 +22,16 @@ #include "xfs_inum.h" #include "xfs_trans.h" #include "xfs_sb.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_dmapi.h" #include "xfs_mount.h" #include "xfs_da_btree.h" #include "xfs_bmap_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_inode_item.h" -#include "xfs_dir_leaf.h" #include "xfs_error.h" #include "xfs_dir2_data.h" #include "xfs_dir2_leaf.h" diff --git a/fs/xfs/xfs_dir2_trace.c b/fs/xfs/xfs_dir2_trace.c index c626943b411..f3fb2ffd6f5 100644 --- a/fs/xfs/xfs_dir2_trace.c +++ b/fs/xfs/xfs_dir2_trace.c @@ -19,11 +19,9 @@ #include "xfs_fs.h" #include "xfs_types.h" #include "xfs_inum.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_da_btree.h" #include "xfs_bmap_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" diff --git a/fs/xfs/xfs_dir_leaf.c b/fs/xfs/xfs_dir_leaf.c index e7121040cd9..e69de29bb2d 100644 --- a/fs/xfs/xfs_dir_leaf.c +++ b/fs/xfs/xfs_dir_leaf.c @@ -1,2230 +0,0 @@ -/* - * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -#include "xfs.h" -#include "xfs_fs.h" -#include "xfs_types.h" -#include "xfs_log.h" -#include "xfs_inum.h" -#include "xfs_trans.h" -#include "xfs_sb.h" -#include "xfs_dir.h" -#include "xfs_dir2.h" -#include "xfs_dmapi.h" -#include "xfs_mount.h" -#include "xfs_da_btree.h" -#include "xfs_bmap_btree.h" -#include "xfs_alloc_btree.h" -#include "xfs_ialloc_btree.h" -#include "xfs_dir_sf.h" -#include "xfs_dir2_sf.h" -#include "xfs_attr_sf.h" -#include "xfs_dinode.h" -#include "xfs_inode.h" -#include "xfs_inode_item.h" -#include "xfs_alloc.h" -#include "xfs_btree.h" -#include "xfs_bmap.h" -#include "xfs_dir_leaf.h" -#include "xfs_error.h" - -/* - * xfs_dir_leaf.c - * - * Routines to implement leaf blocks of directories as Btrees of hashed names. - */ - -/*======================================================================== - * Function prototypes for the kernel. - *========================================================================*/ - -/* - * Routines used for growing the Btree. - */ -STATIC void xfs_dir_leaf_add_work(xfs_dabuf_t *leaf_buffer, xfs_da_args_t *args, - int insertion_index, - int freemap_index); -STATIC int xfs_dir_leaf_compact(xfs_trans_t *trans, xfs_dabuf_t *leaf_buffer, - int musthave, int justcheck); -STATIC void xfs_dir_leaf_rebalance(xfs_da_state_t *state, - xfs_da_state_blk_t *blk1, - xfs_da_state_blk_t *blk2); -STATIC int xfs_dir_leaf_figure_balance(xfs_da_state_t *state, - xfs_da_state_blk_t *leaf_blk_1, - xfs_da_state_blk_t *leaf_blk_2, - int *number_entries_in_blk1, - int *number_namebytes_in_blk1); - -STATIC int xfs_dir_leaf_create(struct xfs_da_args *args, - xfs_dablk_t which_block, - struct xfs_dabuf **bpp); - -/* - * Utility routines. - */ -STATIC void xfs_dir_leaf_moveents(xfs_dir_leafblock_t *src_leaf, - int src_start, - xfs_dir_leafblock_t *dst_leaf, - int dst_start, int move_count, - xfs_mount_t *mp); - - -/*======================================================================== - * External routines when dirsize < XFS_IFORK_DSIZE(dp). - *========================================================================*/ - - -/* - * Validate a given inode number. - */ -int -xfs_dir_ino_validate(xfs_mount_t *mp, xfs_ino_t ino) -{ - xfs_agblock_t agblkno; - xfs_agino_t agino; - xfs_agnumber_t agno; - int ino_ok; - int ioff; - - agno = XFS_INO_TO_AGNO(mp, ino); - agblkno = XFS_INO_TO_AGBNO(mp, ino); - ioff = XFS_INO_TO_OFFSET(mp, ino); - agino = XFS_OFFBNO_TO_AGINO(mp, agblkno, ioff); - ino_ok = - agno < mp->m_sb.sb_agcount && - agblkno < mp->m_sb.sb_agblocks && - agblkno != 0 && - ioff < (1 << mp->m_sb.sb_inopblog) && - XFS_AGINO_TO_INO(mp, agno, agino) == ino; - if (unlikely(XFS_TEST_ERROR(!ino_ok, mp, XFS_ERRTAG_DIR_INO_VALIDATE, - XFS_RANDOM_DIR_INO_VALIDATE))) { - xfs_fs_cmn_err(CE_WARN, mp, "Invalid inode number 0x%Lx", - (unsigned long long) ino); - XFS_ERROR_REPORT("xfs_dir_ino_validate", XFS_ERRLEVEL_LOW, mp); - return XFS_ERROR(EFSCORRUPTED); - } - return 0; -} - -/* - * Create the initial contents of a shortform directory. - */ -int -xfs_dir_shortform_create(xfs_da_args_t *args, xfs_ino_t parent) -{ - xfs_dir_sf_hdr_t *hdr; - xfs_inode_t *dp; - - dp = args->dp; - ASSERT(dp != NULL); - ASSERT(dp->i_d.di_size == 0); - if (dp->i_d.di_format == XFS_DINODE_FMT_EXTENTS) { - dp->i_df.if_flags &= ~XFS_IFEXTENTS; /* just in case */ - dp->i_d.di_format = XFS_DINODE_FMT_LOCAL; - xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE); - dp->i_df.if_flags |= XFS_IFINLINE; - } - ASSERT(dp->i_df.if_flags & XFS_IFINLINE); - ASSERT(dp->i_df.if_bytes == 0); - xfs_idata_realloc(dp, sizeof(*hdr), XFS_DATA_FORK); - hdr = (xfs_dir_sf_hdr_t *)dp->i_df.if_u1.if_data; - XFS_DIR_SF_PUT_DIRINO(&parent, &hdr->parent); - - hdr->count = 0; - dp->i_d.di_size = sizeof(*hdr); - xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA); - return 0; -} - -/* - * Add a name to the shortform directory structure. - * Overflow from the inode has already been checked for. - */ -int -xfs_dir_shortform_addname(xfs_da_args_t *args) -{ - xfs_dir_shortform_t *sf; - xfs_dir_sf_entry_t *sfe; - int i, offset, size; - xfs_inode_t *dp; - - dp = args->dp; - ASSERT(dp->i_df.if_flags & XFS_IFINLINE); - /* - * Catch the case where the conversion from shortform to leaf - * failed part way through. - */ - if (dp->i_d.di_size < sizeof(xfs_dir_sf_hdr_t)) { - ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount)); - return XFS_ERROR(EIO); - } - ASSERT(dp->i_df.if_bytes == dp->i_d.di_size); - ASSERT(dp->i_df.if_u1.if_data != NULL); - sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data; - sfe = &sf->list[0]; - for (i = sf->hdr.count-1; i >= 0; i--) { - if (sfe->namelen == args->namelen && - args->name[0] == sfe->name[0] && - memcmp(args->name, sfe->name, args->namelen) == 0) - return XFS_ERROR(EEXIST); - sfe = XFS_DIR_SF_NEXTENTRY(sfe); - } - - offset = (int)((char *)sfe - (char *)sf); - size = XFS_DIR_SF_ENTSIZE_BYNAME(args->namelen); - xfs_idata_realloc(dp, size, XFS_DATA_FORK); - sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data; - sfe = (xfs_dir_sf_entry_t *)((char *)sf + offset); - - XFS_DIR_SF_PUT_DIRINO(&args->inumber, &sfe->inumber); - sfe->namelen = args->namelen; - memcpy(sfe->name, args->name, sfe->namelen); - sf->hdr.count++; - - dp->i_d.di_size += size; - xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA); - - return 0; -} - -/* - * Remove a name from the shortform directory structure. - */ -int -xfs_dir_shortform_removename(xfs_da_args_t *args) -{ - xfs_dir_shortform_t *sf; - xfs_dir_sf_entry_t *sfe; - int base, size = 0, i; - xfs_inode_t *dp; - - dp = args->dp; - ASSERT(dp->i_df.if_flags & XFS_IFINLINE); - /* - * Catch the case where the conversion from shortform to leaf - * failed part way through. - */ - if (dp->i_d.di_size < sizeof(xfs_dir_sf_hdr_t)) { - ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount)); - return XFS_ERROR(EIO); - } - ASSERT(dp->i_df.if_bytes == dp->i_d.di_size); - ASSERT(dp->i_df.if_u1.if_data != NULL); - base = sizeof(xfs_dir_sf_hdr_t); - sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data; - sfe = &sf->list[0]; - for (i = sf->hdr.count-1; i >= 0; i--) { - size = XFS_DIR_SF_ENTSIZE_BYENTRY(sfe); - if (sfe->namelen == args->namelen && - sfe->name[0] == args->name[0] && - memcmp(sfe->name, args->name, args->namelen) == 0) - break; - base += size; - sfe = XFS_DIR_SF_NEXTENTRY(sfe); - } - if (i < 0) { - ASSERT(args->oknoent); - return XFS_ERROR(ENOENT); - } - - if ((base + size) != dp->i_d.di_size) { - memmove(&((char *)sf)[base], &((char *)sf)[base+size], - dp->i_d.di_size - (base+size)); - } - sf->hdr.count--; - - xfs_idata_realloc(dp, -size, XFS_DATA_FORK); - dp->i_d.di_size -= size; - xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA); - - return 0; -} - -/* - * Look up a name in a shortform directory structure. - */ -int -xfs_dir_shortform_lookup(xfs_da_args_t *args) -{ - xfs_dir_shortform_t *sf; - xfs_dir_sf_entry_t *sfe; - int i; - xfs_inode_t *dp; - - dp = args->dp; - ASSERT(dp->i_df.if_flags & XFS_IFINLINE); - /* - * Catch the case where the conversion from shortform to leaf - * failed part way through. - */ - if (dp->i_d.di_size < sizeof(xfs_dir_sf_hdr_t)) { - ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount)); - return XFS_ERROR(EIO); - } - ASSERT(dp->i_df.if_bytes == dp->i_d.di_size); - ASSERT(dp->i_df.if_u1.if_data != NULL); - sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data; - if (args->namelen == 2 && - args->name[0] == '.' && args->name[1] == '.') { - XFS_DIR_SF_GET_DIRINO(&sf->hdr.parent, &args->inumber); - return(XFS_ERROR(EEXIST)); - } - if (args->namelen == 1 && args->name[0] == '.') { - args->inumber = dp->i_ino; - return(XFS_ERROR(EEXIST)); - } - sfe = &sf->list[0]; - for (i = sf->hdr.count-1; i >= 0; i--) { - if (sfe->namelen == args->namelen && - sfe->name[0] == args->name[0] && - memcmp(args->name, sfe->name, args->namelen) == 0) { - XFS_DIR_SF_GET_DIRINO(&sfe->inumber, &args->inumber); - return(XFS_ERROR(EEXIST)); - } - sfe = XFS_DIR_SF_NEXTENTRY(sfe); - } - ASSERT(args->oknoent); - return(XFS_ERROR(ENOENT)); -} - -/* - * Convert from using the shortform to the leaf. - */ -int -xfs_dir_shortform_to_leaf(xfs_da_args_t *iargs) -{ - xfs_inode_t *dp; - xfs_dir_shortform_t *sf; - xfs_dir_sf_entry_t *sfe; - xfs_da_args_t args; - xfs_ino_t inumber; - char *tmpbuffer; - int retval, i, size; - xfs_dablk_t blkno; - xfs_dabuf_t *bp; - - dp = iargs->dp; - /* - * Catch the case where the conversion from shortform to leaf - * failed part way through. - */ - if (dp->i_d.di_size < sizeof(xfs_dir_sf_hdr_t)) { - ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount)); - return XFS_ERROR(EIO); - } - ASSERT(dp->i_df.if_bytes == dp->i_d.di_size); - ASSERT(dp->i_df.if_u1.if_data != NULL); - size = dp->i_df.if_bytes; - tmpbuffer = kmem_alloc(size, KM_SLEEP); - ASSERT(tmpbuffer != NULL); - - memcpy(tmpbuffer, dp->i_df.if_u1.if_data, size); - - sf = (xfs_dir_shortform_t *)tmpbuffer; - XFS_DIR_SF_GET_DIRINO(&sf->hdr.parent, &inumber); - - xfs_idata_realloc(dp, -size, XFS_DATA_FORK); - dp->i_d.di_size = 0; - xfs_trans_log_inode(iargs->trans, dp, XFS_ILOG_CORE); - retval = xfs_da_grow_inode(iargs, &blkno); - if (retval) - goto out; - - ASSERT(blkno == 0); - retval = xfs_dir_leaf_create(iargs, blkno, &bp); - if (retval) - goto out; - xfs_da_buf_done(bp); - - args.name = "."; - args.namelen = 1; - args.hashval = xfs_dir_hash_dot; - args.inumber = dp->i_ino; - args.dp = dp; - args.firstblock = iargs->firstblock; - args.flist = iargs->flist; - args.total = iargs->total; - args.whichfork = XFS_DATA_FORK; - args.trans = iargs->trans; - args.justcheck = 0; - args.addname = args.oknoent = 1; - retval = xfs_dir_leaf_addname(&args); - if (retval) - goto out; - - args.name = ".."; - args.namelen = 2; - args.hashval = xfs_dir_hash_dotdot; - args.inumber = inumber; - retval = xfs_dir_leaf_addname(&args); - if (retval) - goto out; - - sfe = &sf->list[0]; - for (i = 0; i < sf->hdr.count; i++) { - args.name = (char *)(sfe->name); - args.namelen = sfe->namelen; - args.hashval = xfs_da_hashname((char *)(sfe->name), - sfe->namelen); - XFS_DIR_SF_GET_DIRINO(&sfe->inumber, &args.inumber); - retval = xfs_dir_leaf_addname(&args); - if (retval) - goto out; - sfe = XFS_DIR_SF_NEXTENTRY(sfe); - } - retval = 0; - -out: - kmem_free(tmpbuffer, size); - return retval; -} - -STATIC int -xfs_dir_shortform_compare(const void *a, const void *b) -{ - xfs_dir_sf_sort_t *sa, *sb; - - sa = (xfs_dir_sf_sort_t *)a; - sb = (xfs_dir_sf_sort_t *)b; - if (sa->hash < sb->hash) - return -1; - else if (sa->hash > sb->hash) - return 1; - else - return sa->entno - sb->entno; -} - -/* - * Copy out directory entries for getdents(), for shortform directories. - */ -/*ARGSUSED*/ -int -xfs_dir_shortform_getdents(xfs_inode_t *dp, uio_t *uio, int *eofp, - xfs_dirent_t *dbp, xfs_dir_put_t put) -{ - xfs_dir_shortform_t *sf; - xfs_dir_sf_entry_t *sfe; - int retval, i, sbsize, nsbuf, lastresid=0, want_entno; - xfs_mount_t *mp; - xfs_dahash_t cookhash, hash; - xfs_dir_put_args_t p; - xfs_dir_sf_sort_t *sbuf, *sbp; - - mp = dp->i_mount; - sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data; - cookhash = XFS_DA_COOKIE_HASH(mp, uio->uio_offset); - want_entno = XFS_DA_COOKIE_ENTRY(mp, uio->uio_offset); - nsbuf = sf->hdr.count + 2; - sbsize = (nsbuf + 1) * sizeof(*sbuf); - sbp = sbuf = kmem_alloc(sbsize, KM_SLEEP); - - xfs_dir_trace_g_du("sf: start", dp, uio); - - /* - * Collect all the entries into the buffer. - * Entry 0 is . - */ - sbp->entno = 0; - sbp->seqno = 0; - sbp->hash = xfs_dir_hash_dot; - sbp->ino = dp->i_ino; - sbp->name = "."; - sbp->namelen = 1; - sbp++; - - /* - * Entry 1 is .. - */ - sbp->entno = 1; - sbp->seqno = 0; - sbp->hash = xfs_dir_hash_dotdot; - sbp->ino = XFS_GET_DIR_INO8(sf->hdr.parent); - sbp->name = ".."; - sbp->namelen = 2; - sbp++; - - /* - * Scan the directory data for the rest of the entries. - */ - for (i = 0, sfe = &sf->list[0]; i < sf->hdr.count; i++) { - - if (unlikely( - ((char *)sfe < (char *)sf) || - ((char *)sfe >= ((char *)sf + dp->i_df.if_bytes)))) { - xfs_dir_trace_g_du("sf: corrupted", dp, uio); - XFS_CORRUPTION_ERROR("xfs_dir_shortform_getdents", - XFS_ERRLEVEL_LOW, mp, sfe); - kmem_free(sbuf, sbsize); - return XFS_ERROR(EFSCORRUPTED); - } - - sbp->entno = i + 2; - sbp->seqno = 0; - sbp->hash = xfs_da_hashname((char *)sfe->name, sfe->namelen); - sbp->ino = XFS_GET_DIR_INO8(sfe->inumber); - sbp->name = (char *)sfe->name; - sbp->namelen = sfe->namelen; - sfe = XFS_DIR_SF_NEXTENTRY(sfe); - sbp++; - } - - /* - * Sort the entries on hash then entno. - */ - xfs_sort(sbuf, nsbuf, sizeof(*sbuf), xfs_dir_shortform_compare); - /* - * Stuff in last entry. - */ - sbp->entno = nsbuf; - sbp->hash = XFS_DA_MAXHASH; - sbp->seqno = 0; - /* - * Figure out the sequence numbers in case there's a hash duplicate. - */ - for (hash = sbuf->hash, sbp = sbuf + 1; - sbp < &sbuf[nsbuf + 1]; sbp++) { - if (sbp->hash == hash) - sbp->seqno = sbp[-1].seqno + 1; - else - hash = sbp->hash; - } - - /* - * Set up put routine. - */ - p.dbp = dbp; - p.put = put; - p.uio = uio; - - /* - * Find our place. - */ - for (sbp = sbuf; sbp < &sbuf[nsbuf + 1]; sbp++) { - if (sbp->hash > cookhash || - (sbp->hash == cookhash && sbp->seqno >= want_entno)) - break; - } - - /* - * Did we fail to find anything? We stop at the last entry, - * the one we put maxhash into. - */ - if (sbp == &sbuf[nsbuf]) { - kmem_free(sbuf, sbsize); - xfs_dir_trace_g_du("sf: hash beyond end", dp, uio); - uio->uio_offset = XFS_DA_MAKE_COOKIE(mp, 0, 0, XFS_DA_MAXHASH); - *eofp = 1; - return 0; - } - - /* - * Loop putting entries into the user buffer. - */ - while (sbp < &sbuf[nsbuf]) { - /* - * Save the first resid in a run of equal-hashval entries - * so that we can back them out if they don't all fit. - */ - if (sbp->seqno == 0 || sbp == sbuf) - lastresid = uio->uio_resid; - XFS_PUT_COOKIE(p.cook, mp, 0, sbp[1].seqno, sbp[1].hash); - p.ino = sbp->ino; -#if XFS_BIG_INUMS - p.ino += mp->m_inoadd; -#endif - p.name = sbp->name; - p.namelen = sbp->namelen; - retval = p.put(&p); - if (!p.done) { - uio->uio_offset = - XFS_DA_MAKE_COOKIE(mp, 0, 0, sbp->hash); - kmem_free(sbuf, sbsize); - uio->uio_resid = lastresid; - xfs_dir_trace_g_du("sf: E-O-B", dp, uio); - return retval; - } - sbp++; - } - kmem_free(sbuf, sbsize); - uio->uio_offset = p.cook.o; - *eofp = 1; - xfs_dir_trace_g_du("sf: E-O-F", dp, uio); - return 0; -} - -/* - * Look up a name in a shortform directory structure, replace the inode number. - */ -int -xfs_dir_shortform_replace(xfs_da_args_t *args) -{ - xfs_dir_shortform_t *sf; - xfs_dir_sf_entry_t *sfe; - xfs_inode_t *dp; - int i; - - dp = args->dp; - ASSERT(dp->i_df.if_flags & XFS_IFINLINE); - /* - * Catch the case where the conversion from shortform to leaf - * failed part way through. - */ - if (dp->i_d.di_size < sizeof(xfs_dir_sf_hdr_t)) { - ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount)); - return XFS_ERROR(EIO); - } - ASSERT(dp->i_df.if_bytes == dp->i_d.di_size); - ASSERT(dp->i_df.if_u1.if_data != NULL); - sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data; - if (args->namelen == 2 && - args->name[0] == '.' && args->name[1] == '.') { - /* XXX - replace assert? */ - XFS_DIR_SF_PUT_DIRINO(&args->inumber, &sf->hdr.parent); - xfs_trans_log_inode(args->trans, dp, XFS_ILOG_DDATA); - return 0; - } - ASSERT(args->namelen != 1 || args->name[0] != '.'); - sfe = &sf->list[0]; - for (i = sf->hdr.count-1; i >= 0; i--) { - if (sfe->namelen == args->namelen && - sfe->name[0] == args->name[0] && - memcmp(args->name, sfe->name, args->namelen) == 0) { - ASSERT(memcmp((char *)&args->inumber, - (char *)&sfe->inumber, sizeof(xfs_ino_t))); - XFS_DIR_SF_PUT_DIRINO(&args->inumber, &sfe->inumber); - xfs_trans_log_inode(args->trans, dp, XFS_ILOG_DDATA); - return 0; - } - sfe = XFS_DIR_SF_NEXTENTRY(sfe); - } - ASSERT(args->oknoent); - return XFS_ERROR(ENOENT); -} - -/* - * Convert a leaf directory to shortform structure - */ -int -xfs_dir_leaf_to_shortform(xfs_da_args_t *iargs) -{ - xfs_dir_leafblock_t *leaf; - xfs_dir_leaf_hdr_t *hdr; - xfs_dir_leaf_entry_t *entry; - xfs_dir_leaf_name_t *namest; - xfs_da_args_t args; - xfs_inode_t *dp; - xfs_ino_t parent = 0; - char *tmpbuffer; - int retval, i; - xfs_dabuf_t *bp; - - dp = iargs->dp; - tmpbuffer = kmem_alloc(XFS_LBSIZE(dp->i_mount), KM_SLEEP); - ASSERT(tmpbuffer != NULL); - - retval = xfs_da_read_buf(iargs->trans, iargs->dp, 0, -1, &bp, - XFS_DATA_FORK); - if (retval) - goto out; - ASSERT(bp != NULL); - memcpy(tmpbuffer, bp->data, XFS_LBSIZE(dp->i_mount)); - leaf = (xfs_dir_leafblock_t *)tmpbuffer; - ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); - memset(bp->data, 0, XFS_LBSIZE(dp->i_mount)); - - /* - * Find and special case the parent inode number - */ - hdr = &leaf->hdr; - entry = &leaf->entries[0]; - for (i = be16_to_cpu(hdr->count)-1; i >= 0; entry++, i--) { - namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, be16_to_cpu(entry->nameidx)); - if ((entry->namelen == 2) && - (namest->name[0] == '.') && - (namest->name[1] == '.')) { - XFS_DIR_SF_GET_DIRINO(&namest->inumber, &parent); - entry->nameidx = 0; - } else if ((entry->namelen == 1) && (namest->name[0] == '.')) { - entry->nameidx = 0; - } - } - retval = xfs_da_shrink_inode(iargs, 0, bp); - if (retval) - goto out; - retval = xfs_dir_shortform_create(iargs, parent); - if (retval) - goto out; - - /* - * Copy the rest of the filenames - */ - entry = &leaf->entries[0]; - args.dp = dp; - args.firstblock = iargs->firstblock; - args.flist = iargs->flist; - args.total = iargs->total; - args.whichfork = XFS_DATA_FORK; - args.trans = iargs->trans; - args.justcheck = 0; - args.addname = args.oknoent = 1; - for (i = 0; i < be16_to_cpu(hdr->count); entry++, i++) { - if (!entry->nameidx) - continue; - namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, be16_to_cpu(entry->nameidx)); - args.name = (char *)(namest->name); - args.namelen = entry->namelen; - args.hashval = be32_to_cpu(entry->hashval); - XFS_DIR_SF_GET_DIRINO(&namest->inumber, &args.inumber); - xfs_dir_shortform_addname(&args); - } - -out: - kmem_free(tmpbuffer, XFS_LBSIZE(dp->i_mount)); - return retval; -} - -/* - * Convert from using a single leaf to a root node and a leaf. - */ -int -xfs_dir_leaf_to_node(xfs_da_args_t *args) -{ - xfs_dir_leafblock_t *leaf; - xfs_da_intnode_t *node; - xfs_inode_t *dp; - xfs_dabuf_t *bp1, *bp2; - xfs_dablk_t blkno; - int retval; - - dp = args->dp; - retval = xfs_da_grow_inode(args, &blkno); - ASSERT(blkno == 1); - if (retval) - return retval; - retval = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp1, - XFS_DATA_FORK); - if (retval) - return retval; - ASSERT(bp1 != NULL); - retval = xfs_da_get_buf(args->trans, args->dp, 1, -1, &bp2, - XFS_DATA_FORK); - if (retval) { - xfs_da_buf_done(bp1); - return retval; - } - ASSERT(bp2 != NULL); - memcpy(bp2->data, bp1->data, XFS_LBSIZE(dp->i_mount)); - xfs_da_buf_done(bp1); - xfs_da_log_buf(args->trans, bp2, 0, XFS_LBSIZE(dp->i_mount) - 1); - - /* - * Set up the new root node. - */ - retval = xfs_da_node_create(args, 0, 1, &bp1, XFS_DATA_FORK); - if (retval) { - xfs_da_buf_done(bp2); - return retval; - } - node = bp1->data; - leaf = bp2->data; - ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); - node->btree[0].hashval = leaf->entries[be16_to_cpu(leaf->hdr.count)-1].hashval; - xfs_da_buf_done(bp2); - node->btree[0].before = cpu_to_be32(blkno); - node->hdr.count = cpu_to_be16(1); - xfs_da_log_buf(args->trans, bp1, - XFS_DA_LOGRANGE(node, &node->btree[0], sizeof(node->btree[0]))); - xfs_da_buf_done(bp1); - - return retval; -} - - -/*======================================================================== - * Routines used for growing the Btree. - *========================================================================*/ - -/* - * Create the initial contents of a leaf directory - * or a leaf in a node directory. - */ -STATIC int -xfs_dir_leaf_create(xfs_da_args_t *args, xfs_dablk_t blkno, xfs_dabuf_t **bpp) -{ - xfs_dir_leafblock_t *leaf; - xfs_dir_leaf_hdr_t *hdr; - xfs_inode_t *dp; - xfs_dabuf_t *bp; - int retval; - - dp = args->dp; - ASSERT(dp != NULL); - retval = xfs_da_get_buf(args->trans, dp, blkno, -1, &bp, XFS_DATA_FORK); - if (retval) - return retval; - ASSERT(bp != NULL); - leaf = bp->data; - memset((char *)leaf, 0, XFS_LBSIZE(dp->i_mount)); - hdr = &leaf->hdr; - hdr->info.magic = cpu_to_be16(XFS_DIR_LEAF_MAGIC); - hdr->firstused = cpu_to_be16(XFS_LBSIZE(dp->i_mount)); - if (!hdr->firstused) - hdr->firstused = cpu_to_be16(XFS_LBSIZE(dp->i_mount) - 1); - hdr->freemap[0].base = cpu_to_be16(sizeof(xfs_dir_leaf_hdr_t)); - hdr->freemap[0].size = cpu_to_be16(be16_to_cpu(hdr->firstused) - - be16_to_cpu(hdr->freemap[0].base)); - - xfs_da_log_buf(args->trans, bp, 0, XFS_LBSIZE(dp->i_mount) - 1); - - *bpp = bp; - return 0; -} - -/* - * Split the leaf node, rebalance, then add the new entry. - */ -int -xfs_dir_leaf_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk, - xfs_da_state_blk_t *newblk) -{ - xfs_dablk_t blkno; - xfs_da_args_t *args; - int error; - - /* - * Allocate space for a new leaf node. - */ - args = state->args; - ASSERT(args != NULL); - ASSERT(oldblk->magic == XFS_DIR_LEAF_MAGIC); - error = xfs_da_grow_inode(args, &blkno); - if (error) - return error; - error = xfs_dir_leaf_create(args, blkno, &newblk->bp); - if (error) - return error; - newblk->blkno = blkno; - newblk->magic = XFS_DIR_LEAF_MAGIC; - - /* - * Rebalance the entries across the two leaves. - */ - xfs_dir_leaf_rebalance(state, oldblk, newblk); - error = xfs_da_blk_link(state, oldblk, newblk); - if (error) - return error; - - /* - * Insert the new entry in the correct block. - */ - if (state->inleaf) { - error = xfs_dir_leaf_add(oldblk->bp, args, oldblk->index); - } else { - error = xfs_dir_leaf_add(newblk->bp, args, newblk->index); - } - - /* - * Update last hashval in each block since we added the name. - */ - oldblk->hashval = xfs_dir_leaf_lasthash(oldblk->bp, NULL); - newblk->hashval = xfs_dir_leaf_lasthash(newblk->bp, NULL); - return error; -} - -/* - * Add a name to the leaf directory structure. - * - * Must take into account fragmented leaves and leaves where spacemap has - * lost some freespace information (ie: holes). - */ -int -xfs_dir_leaf_add(xfs_dabuf_t *bp, xfs_da_args_t *args, int index) -{ - xfs_dir_leafblock_t *leaf; - xfs_dir_leaf_hdr_t *hdr; - xfs_dir_leaf_map_t *map; - int tablesize, entsize, sum, i, tmp, error; - - leaf = bp->data; - ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); - ASSERT((index >= 0) && (index <= be16_to_cpu(leaf->hdr.count))); - hdr = &leaf->hdr; - entsize = XFS_DIR_LEAF_ENTSIZE_BYNAME(args->namelen); - - /* - * Search through freemap for first-fit on new name length. - * (may need to figure in size of entry struct too) - */ - tablesize = (be16_to_cpu(hdr->count) + 1) * - sizeof(xfs_dir_leaf_entry_t) + sizeof(xfs_dir_leaf_hdr_t); - map = &hdr->freemap[XFS_DIR_LEAF_MAPSIZE-1]; - for (sum = 0, i = XFS_DIR_LEAF_MAPSIZE-1; i >= 0; map--, i--) { - if (tablesize > be16_to_cpu(hdr->firstused)) { - sum += be16_to_cpu(map->size); - continue; - } - if (!map->size) - continue; /* no space in this map */ - tmp = entsize; - if (be16_to_cpu(map->base) < be16_to_cpu(hdr->firstused)) - tmp += (uint)sizeof(xfs_dir_leaf_entry_t); - if (be16_to_cpu(map->size) >= tmp) { - if (!args->justcheck) - xfs_dir_leaf_add_work(bp, args, index, i); - return 0; - } - sum += be16_to_cpu(map->size); - } - - /* - * If there are no holes in the address space of the block, - * and we don't have enough freespace, then compaction will do us - * no good and we should just give up. - */ - if (!hdr->holes && (sum < entsize)) - return XFS_ERROR(ENOSPC); - - /* - * Compact the entries to coalesce free space. - * Pass the justcheck flag so the checking pass can return - * an error, without changing anything, if it won't fit. - */ - error = xfs_dir_leaf_compact(args->trans, bp, - args->total == 0 ? - entsize + - (uint)sizeof(xfs_dir_leaf_entry_t) : 0, - args->justcheck); - if (error) - return error; - /* - * After compaction, the block is guaranteed to have only one - * free region, in freemap[0]. If it is not big enough, give up. - */ - if (be16_to_cpu(hdr->freemap[0].size) < - (entsize + (uint)sizeof(xfs_dir_leaf_entry_t))) - return XFS_ERROR(ENOSPC); - - if (!args->justcheck) - xfs_dir_leaf_add_work(bp, args, index, 0); - return 0; -} - -/* - * Add a name to a leaf directory structure. - */ -STATIC void -xfs_dir_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int index, - int mapindex) -{ - xfs_dir_leafblock_t *leaf; - xfs_dir_leaf_hdr_t *hdr; - xfs_dir_leaf_entry_t *entry; - xfs_dir_leaf_name_t *namest; - xfs_dir_leaf_map_t *map; - /* REFERENCED */ - xfs_mount_t *mp; - int tmp, i; - - leaf = bp->data; - ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); - hdr = &leaf->hdr; - ASSERT((mapindex >= 0) && (mapindex < XFS_DIR_LEAF_MAPSIZE)); - ASSERT((index >= 0) && (index <= be16_to_cpu(hdr->count))); - - /* - * Force open some space in the entry array and fill it in. - */ - entry = &leaf->entries[index]; - if (index < be16_to_cpu(hdr->count)) { - tmp = be16_to_cpu(hdr->count) - index; - tmp *= (uint)sizeof(xfs_dir_leaf_entry_t); - memmove(entry + 1, entry, tmp); - xfs_da_log_buf(args->trans, bp, - XFS_DA_LOGRANGE(leaf, entry, tmp + (uint)sizeof(*entry))); - } - be16_add(&hdr->count, 1); - - /* - * Allocate space for the new string (at the end of the run). - */ - map = &hdr->freemap[mapindex]; - mp = args->trans->t_mountp; - ASSERT(be16_to_cpu(map->base) < XFS_LBSIZE(mp)); - ASSERT(be16_to_cpu(map->size) >= XFS_DIR_LEAF_ENTSIZE_BYNAME(args->namelen)); - ASSERT(be16_to_cpu(map->size) < XFS_LBSIZE(mp)); - - be16_add(&map->size, -(XFS_DIR_LEAF_ENTSIZE_BYNAME(args->namelen))); - entry->nameidx = cpu_to_be16(be16_to_cpu(map->base) + - be16_to_cpu(map->size)); - entry->hashval = cpu_to_be32(args->hashval); - entry->namelen = args->namelen; - xfs_da_log_buf(args->trans, bp, - XFS_DA_LOGRANGE(leaf, entry, sizeof(*entry))); - - /* - * Copy the string and inode number into the new space. - */ - namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, be16_to_cpu(entry->nameidx)); - XFS_DIR_SF_PUT_DIRINO(&args->inumber, &namest->inumber); - memcpy(namest->name, args->name, args->namelen); - xfs_da_log_buf(args->trans, bp, - XFS_DA_LOGRANGE(leaf, namest, XFS_DIR_LEAF_ENTSIZE_BYENTRY(entry))); - - /* - * Update the control info for this leaf node - */ - if (be16_to_cpu(entry->nameidx) < be16_to_cpu(hdr->firstused)) - hdr->firstused = entry->nameidx; - ASSERT(be16_to_cpu(hdr->firstused) >= - ((be16_to_cpu(hdr->count)*sizeof(*entry))+sizeof(*hdr))); - tmp = (be16_to_cpu(hdr->count)-1) * (uint)sizeof(xfs_dir_leaf_entry_t) - + (uint)sizeof(xfs_dir_leaf_hdr_t); - map = &hdr->freemap[0]; - for (i = 0; i < XFS_DIR_LEAF_MAPSIZE; map++, i++) { - if (be16_to_cpu(map->base) == tmp) { - int entry_size = sizeof(xfs_dir_leaf_entry_t); - be16_add(&map->base, entry_size); - be16_add(&map->size, -entry_size); - } - } - be16_add(&hdr->namebytes, args->namelen); - xfs_da_log_buf(args->trans, bp, - XFS_DA_LOGRANGE(leaf, hdr, sizeof(*hdr))); -} - -/* - * Garbage collect a leaf directory block by copying it to a new buffer. - */ -STATIC int -xfs_dir_leaf_compact(xfs_trans_t *trans, xfs_dabuf_t *bp, int musthave, - int justcheck) -{ - xfs_dir_leafblock_t *leaf_s, *leaf_d; - xfs_dir_leaf_hdr_t *hdr_s, *hdr_d; - xfs_mount_t *mp; - char *tmpbuffer; - char *tmpbuffer2=NULL; - int rval; - int lbsize; - - mp = trans->t_mountp; - lbsize = XFS_LBSIZE(mp); - tmpbuffer = kmem_alloc(lbsize, KM_SLEEP); - ASSERT(tmpbuffer != NULL); - memcpy(tmpbuffer, bp->data, lbsize); - - /* - * Make a second copy in case xfs_dir_leaf_moveents() - * below destroys the original. - */ - if (musthave || justcheck) { - tmpbuffer2 = kmem_alloc(lbsize, KM_SLEEP); - memcpy(tmpbuffer2, bp->data, lbsize); - } - memset(bp->data, 0, lbsize); - - /* - * Copy basic information - */ - leaf_s = (xfs_dir_leafblock_t *)tmpbuffer; - leaf_d = bp->data; - hdr_s = &leaf_s->hdr; - hdr_d = &leaf_d->hdr; - hdr_d->info = hdr_s->info; /* struct copy */ - hdr_d->firstused = cpu_to_be16(lbsize); - if (!hdr_d->firstused) - hdr_d->firstused = cpu_to_be16(lbsize - 1); - hdr_d->namebytes = 0; - hdr_d->count = 0; - hdr_d->holes = 0; - hdr_d->freemap[0].base = cpu_to_be16(sizeof(xfs_dir_leaf_hdr_t)); - hdr_d->freemap[0].size = cpu_to_be16(be16_to_cpu(hdr_d->firstused) - - be16_to_cpu(hdr_d->freemap[0].base)); - - /* - * Copy all entry's in the same (sorted) order, - * but allocate filenames packed and in sequence. - * This changes the source (leaf_s) as well. - */ - xfs_dir_leaf_moveents(leaf_s, 0, leaf_d, 0, be16_to_cpu(hdr_s->count), mp); - - if (musthave && be16_to_cpu(hdr_d->freemap[0].size) < musthave) - rval = XFS_ERROR(ENOSPC); - else - rval = 0; - - if (justcheck || rval == ENOSPC) { - ASSERT(tmpbuffer2); - memcpy(bp->data, tmpbuffer2, lbsize); - } else { - xfs_da_log_buf(trans, bp, 0, lbsize - 1); - } - - kmem_free(tmpbuffer, lbsize); - if (musthave || justcheck) - kmem_free(tmpbuffer2, lbsize); - return rval; -} - -/* - * Redistribute the directory entries between two leaf nodes, - * taking into account the size of the new entry. - * - * NOTE: if new block is empty, then it will get the upper half of old block. - */ -STATIC void -xfs_dir_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, - xfs_da_state_blk_t *blk2) -{ - xfs_da_state_blk_t *tmp_blk; - xfs_dir_leafblock_t *leaf1, *leaf2; - xfs_dir_leaf_hdr_t *hdr1, *hdr2; - int count, totallen, max, space, swap; - - /* - * Set up environment. - */ - ASSERT(blk1->magic == XFS_DIR_LEAF_MAGIC); - ASSERT(blk2->magic == XFS_DIR_LEAF_MAGIC); - leaf1 = blk1->bp->data; - leaf2 = blk2->bp->data; - ASSERT(be16_to_cpu(leaf1->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); - ASSERT(be16_to_cpu(leaf2->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); - - /* - * Check ordering of blocks, reverse if it makes things simpler. - */ - swap = 0; - if (xfs_dir_leaf_order(blk1->bp, blk2->bp)) { - tmp_blk = blk1; - blk1 = blk2; - blk2 = tmp_blk; - leaf1 = blk1->bp->data; - leaf2 = blk2->bp->data; - swap = 1; - } - hdr1 = &leaf1->hdr; - hdr2 = &leaf2->hdr; - - /* - * Examine entries until we reduce the absolute difference in - * byte usage between the two blocks to a minimum. Then get - * the direction to copy and the number of elements to move. - */ - state->inleaf = xfs_dir_leaf_figure_balance(state, blk1, blk2, - &count, &totallen); - if (swap) - state->inleaf = !state->inleaf; - - /* - * Move any entries required from leaf to leaf: - */ - if (count < be16_to_cpu(hdr1->count)) { - /* - * Figure the total bytes to be added to the destination leaf. - */ - count = be16_to_cpu(hdr1->count) - count; /* number entries being moved */ - space = be16_to_cpu(hdr1->namebytes) - totallen; - space += count * ((uint)sizeof(xfs_dir_leaf_name_t)-1); - space += count * (uint)sizeof(xfs_dir_leaf_entry_t); - - /* - * leaf2 is the destination, compact it if it looks tight. - */ - max = be16_to_cpu(hdr2->firstused) - (uint)sizeof(xfs_dir_leaf_hdr_t); - max -= be16_to_cpu(hdr2->count) * (uint)sizeof(xfs_dir_leaf_entry_t); - if (space > max) { - xfs_dir_leaf_compact(state->args->trans, blk2->bp, - 0, 0); - } - - /* - * Move high entries from leaf1 to low end of leaf2. - */ - xfs_dir_leaf_moveents(leaf1, be16_to_cpu(hdr1->count) - count, - leaf2, 0, count, state->mp); - - xfs_da_log_buf(state->args->trans, blk1->bp, 0, - state->blocksize-1); - xfs_da_log_buf(state->args->trans, blk2->bp, 0, - state->blocksize-1); - - } else if (count > be16_to_cpu(hdr1->count)) { - /* - * Figure the total bytes to be added to the destination leaf. - */ - count -= be16_to_cpu(hdr1->count); /* number entries being moved */ - space = totallen - be16_to_cpu(hdr1->namebytes); - space += count * ((uint)sizeof(xfs_dir_leaf_name_t)-1); - space += count * (uint)sizeof(xfs_dir_leaf_entry_t); - - /* - * leaf1 is the destination, compact it if it looks tight. - */ - max = be16_to_cpu(hdr1->firstused) - (uint)sizeof(xfs_dir_leaf_hdr_t); - max -= be16_to_cpu(hdr1->count) * (uint)sizeof(xfs_dir_leaf_entry_t); - if (space > max) { - xfs_dir_leaf_compact(state->args->trans, blk1->bp, - 0, 0); - } - - /* - * Move low entries from leaf2 to high end of leaf1. - */ - xfs_dir_leaf_moveents(leaf2, 0, leaf1, be16_to_cpu(hdr1->count), - count, state->mp); - - xfs_da_log_buf(state->args->trans, blk1->bp, 0, - state->blocksize-1); - xfs_da_log_buf(state->args->trans, blk2->bp, 0, - state->blocksize-1); - } - - /* - * Copy out last hashval in each block for B-tree code. - */ - blk1->hashval = be32_to_cpu(leaf1->entries[ - be16_to_cpu(leaf1->hdr.count)-1].hashval); - blk2->hashval = be32_to_cpu(leaf2->entries[ - be16_to_cpu(leaf2->hdr.count)-1].hashval); - - /* - * Adjust the expected index for insertion. - * GROT: this doesn't work unless blk2 was originally empty. - */ - if (!state->inleaf) { - blk2->index = blk1->index - be16_to_cpu(leaf1->hdr.count); - } -} - -/* - * Examine entries until we reduce the absolute difference in - * byte usage between the two blocks to a minimum. - * GROT: Is this really necessary? With other than a 512 byte blocksize, - * GROT: there will always be enough room in either block for a new entry. - * GROT: Do a double-split for this case? - */ -STATIC int -xfs_dir_leaf_figure_balance(xfs_da_state_t *state, - xfs_da_state_blk_t *blk1, - xfs_da_state_blk_t *blk2, - int *countarg, int *namebytesarg) -{ - xfs_dir_leafblock_t *leaf1, *leaf2; - xfs_dir_leaf_hdr_t *hdr1, *hdr2; - xfs_dir_leaf_entry_t *entry; - int count, max, totallen, half; - int lastdelta, foundit, tmp; - - /* - * Set up environment. - */ - leaf1 = blk1->bp->data; - leaf2 = blk2->bp->data; - hdr1 = &leaf1->hdr; - hdr2 = &leaf2->hdr; - foundit = 0; - totallen = 0; - - /* - * Examine entries until we reduce the absolute difference in - * byte usage between the two blocks to a minimum. - */ - max = be16_to_cpu(hdr1->count) + be16_to_cpu(hdr2->count); - half = (max+1) * (uint)(sizeof(*entry)+sizeof(xfs_dir_leaf_entry_t)-1); - half += be16_to_cpu(hdr1->namebytes) + be16_to_cpu(hdr2->namebytes) + - state->args->namelen; - half /= 2; - lastdelta = state->blocksize; - entry = &leaf1->entries[0]; - for (count = 0; count < max; entry++, count++) { - -#define XFS_DIR_ABS(A) (((A) < 0) ? -(A) : (A)) - /* - * The new entry is in the first block, account for it. - */ - if (count == blk1->index) { - tmp = totallen + (uint)sizeof(*entry) - + XFS_DIR_LEAF_ENTSIZE_BYNAME(state->args->namelen); - if (XFS_DIR_ABS(half - tmp) > lastdelta) - break; - lastdelta = XFS_DIR_ABS(half - tmp); - totallen = tmp; - foundit = 1; - } - - /* - * Wrap around into the second block if necessary. - */ - if (count == be16_to_cpu(hdr1->count)) { - leaf1 = leaf2; - entry = &leaf1->entries[0]; - } - - /* - * Figure out if next leaf entry would be too much. - */ - tmp = totallen + (uint)sizeof(*entry) - + XFS_DIR_LEAF_ENTSIZE_BYENTRY(entry); - if (XFS_DIR_ABS(half - tmp) > lastdelta) - break; - lastdelta = XFS_DIR_ABS(half - tmp); - totallen = tmp; -#undef XFS_DIR_ABS - } - - /* - * Calculate the number of namebytes that will end up in lower block. - * If new entry not in lower block, fix up the count. - */ - totallen -= - count * (uint)(sizeof(*entry)+sizeof(xfs_dir_leaf_entry_t)-1); - if (foundit) { - totallen -= (sizeof(*entry)+sizeof(xfs_dir_leaf_entry_t)-1) + - state->args->namelen; - } - - *countarg = count; - *namebytesarg = totallen; - return foundit; -} - -/*======================================================================== - * Routines used for shrinking the Btree. - *========================================================================*/ - -/* - * Check a leaf block and its neighbors to see if the block should be - * collapsed into one or the other neighbor. Always keep the block - * with the smaller block number. - * If the current block is over 50% full, don't try to join it, return 0. - * If the block is empty, fill in the state structure and return 2. - * If it can be collapsed, fill in the state structure and return 1. - * If nothing can be done, return 0. - */ -int -xfs_dir_leaf_toosmall(xfs_da_state_t *state, int *action) -{ - xfs_dir_leafblock_t *leaf; - xfs_da_state_blk_t *blk; - xfs_da_blkinfo_t *info; - int count, bytes, forward, error, retval, i; - xfs_dablk_t blkno; - xfs_dabuf_t *bp; - - /* - * Check for the degenerate case of the block being over 50% full. - * If so, it's not worth even looking to see if we might be able - * to coalesce with a sibling. - */ - blk = &state->path.blk[ state->path.active-1 ]; - info = blk->bp->data; - ASSERT(be16_to_cpu(info->magic) == XFS_DIR_LEAF_MAGIC); - leaf = (xfs_dir_leafblock_t *)info; - count = be16_to_cpu(leaf->hdr.count); - bytes = (uint)sizeof(xfs_dir_leaf_hdr_t) + - count * (uint)sizeof(xfs_dir_leaf_entry_t) + - count * ((uint)sizeof(xfs_dir_leaf_name_t)-1) + - be16_to_cpu(leaf->hdr.namebytes); - if (bytes > (state->blocksize >> 1)) { - *action = 0; /* blk over 50%, don't try to join */ - return 0; - } - - /* - * Check for the degenerate case of the block being empty. - * If the block is empty, we'll simply delete it, no need to - * coalesce it with a sibling block. We choose (arbitrarily) - * to merge with the forward block unless it is NULL. - */ - if (count == 0) { - /* - * Make altpath point to the block we want to keep and - * path point to the block we want to drop (this one). - */ - forward = (info->forw != 0); - memcpy(&state->altpath, &state->path, sizeof(state->path)); - error = xfs_da_path_shift(state, &state->altpath, forward, - 0, &retval); - if (error) - return error; - if (retval) { - *action = 0; - } else { - *action = 2; - } - return 0; - } - - /* - * Examine each sibling block to see if we can coalesce with - * at least 25% free space to spare. We need to figure out - * whether to merge with the forward or the backward block. - * We prefer coalescing with the lower numbered sibling so as - * to shrink a directory over time. - */ - forward = (be32_to_cpu(info->forw) < be32_to_cpu(info->back)); /* start with smaller blk num */ - for (i = 0; i < 2; forward = !forward, i++) { - if (forward) - blkno = be32_to_cpu(info->forw); - else - blkno = be32_to_cpu(info->back); - if (blkno == 0) - continue; - error = xfs_da_read_buf(state->args->trans, state->args->dp, - blkno, -1, &bp, - XFS_DATA_FORK); - if (error) - return error; - ASSERT(bp != NULL); - - leaf = (xfs_dir_leafblock_t *)info; - count = be16_to_cpu(leaf->hdr.count); - bytes = state->blocksize - (state->blocksize>>2); - bytes -= be16_to_cpu(leaf->hdr.namebytes); - leaf = bp->data; - ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); - count += be16_to_cpu(leaf->hdr.count); - bytes -= be16_to_cpu(leaf->hdr.namebytes); - bytes -= count * ((uint)sizeof(xfs_dir_leaf_name_t) - 1); - bytes -= count * (uint)sizeof(xfs_dir_leaf_entry_t); - bytes -= (uint)sizeof(xfs_dir_leaf_hdr_t); - if (bytes >= 0) - break; /* fits with at least 25% to spare */ - - xfs_da_brelse(state->args->trans, bp); - } - if (i >= 2) { - *action = 0; - return 0; - } - xfs_da_buf_done(bp); - - /* - * Make altpath point to the block we want to keep (the lower - * numbered block) and path point to the block we want to drop. - */ - memcpy(&state->altpath, &state->path, sizeof(state->path)); - if (blkno < blk->blkno) { - error = xfs_da_path_shift(state, &state->altpath, forward, - 0, &retval); - } else { - error = xfs_da_path_shift(state, &state->path, forward, - 0, &retval); - } - if (error) - return error; - if (retval) { - *action = 0; - } else { - *action = 1; - } - return 0; -} - -/* - * Remove a name from the leaf directory structure. - * - * Return 1 if leaf is less than 37% full, 0 if >= 37% full. - * If two leaves are 37% full, when combined they will leave 25% free. - */ -int -xfs_dir_leaf_remove(xfs_trans_t *trans, xfs_dabuf_t *bp, int index) -{ - xfs_dir_leafblock_t *leaf; - xfs_dir_leaf_hdr_t *hdr; - xfs_dir_leaf_map_t *map; - xfs_dir_leaf_entry_t *entry; - xfs_dir_leaf_name_t *namest; - int before, after, smallest, entsize; - int tablesize, tmp, i; - xfs_mount_t *mp; - - leaf = bp->data; - ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); - hdr = &leaf->hdr; - mp = trans->t_mountp; - ASSERT(hdr->count && (be16_to_cpu(hdr->count) < (XFS_LBSIZE(mp)/8))); - ASSERT((index >= 0) && (index < be16_to_cpu(hdr->count))); - ASSERT(be16_to_cpu(hdr->firstused) >= - ((be16_to_cpu(hdr->count)*sizeof(*entry))+sizeof(*hdr))); - entry = &leaf->entries[index]; - ASSERT(be16_to_cpu(entry->nameidx) >= be16_to_cpu(hdr->firstused)); - ASSERT(be16_to_cpu(entry->nameidx) < XFS_LBSIZE(mp)); - - /* - * Scan through free region table: - * check for adjacency of free'd entry with an existing one, - * find smallest free region in case we need to replace it, - * adjust any map that borders the entry table, - */ - tablesize = be16_to_cpu(hdr->count) * (uint)sizeof(xfs_dir_leaf_entry_t) - + (uint)sizeof(xfs_dir_leaf_hdr_t); - map = &hdr->freemap[0]; - tmp = be16_to_cpu(map->size); - before = after = -1; - smallest = XFS_DIR_LEAF_MAPSIZE - 1; - entsize = XFS_DIR_LEAF_ENTSIZE_BYENTRY(entry); - for (i = 0; i < XFS_DIR_LEAF_MAPSIZE; map++, i++) { - ASSERT(be16_to_cpu(map->base) < XFS_LBSIZE(mp)); - ASSERT(be16_to_cpu(map->size) < XFS_LBSIZE(mp)); - if (be16_to_cpu(map->base) == tablesize) { - int entry_size = sizeof(xfs_dir_leaf_entry_t); - be16_add(&map->base, -entry_size); - be16_add(&map->size, entry_size); - } - - if ((be16_to_cpu(map->base) + be16_to_cpu(map->size)) == - be16_to_cpu(entry->nameidx)) { - before = i; - } else if (be16_to_cpu(map->base) == - (be16_to_cpu(entry->nameidx) + entsize)) { - after = i; - } else if (be16_to_cpu(map->size) < tmp) { - tmp = be16_to_cpu(map->size); - smallest = i; - } - } - - /* - * Coalesce adjacent freemap regions, - * or replace the smallest region. - */ - if ((before >= 0) || (after >= 0)) { - if ((before >= 0) && (after >= 0)) { - map = &hdr->freemap[before]; - be16_add(&map->size, entsize); - be16_add(&map->size, be16_to_cpu(hdr->freemap[after].size)); - hdr->freemap[after].base = 0; - hdr->freemap[after].size = 0; - } else if (before >= 0) { - map = &hdr->freemap[before]; - be16_add(&map->size, entsize); - } else { - map = &hdr->freemap[after]; - map->base = entry->nameidx; - be16_add(&map->size, entsize); - } - } else { - /* - * Replace smallest region (if it is smaller than free'd entry) - */ - map = &hdr->freemap[smallest]; - if (be16_to_cpu(map->size) < entsize) { - map->base = entry->nameidx; - map->size = cpu_to_be16(entsize); - } - } - - /* - * Did we remove the first entry? - */ - if (be16_to_cpu(entry->nameidx) == be16_to_cpu(hdr->firstused)) - smallest = 1; - else - smallest = 0; - - /* - * Compress the remaining entries and zero out the removed stuff. - */ - namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, be16_to_cpu(entry->nameidx)); - memset((char *)namest, 0, entsize); - xfs_da_log_buf(trans, bp, XFS_DA_LOGRANGE(leaf, namest, entsize)); - - be16_add(&hdr->namebytes, -(entry->namelen)); - tmp = (be16_to_cpu(hdr->count) - index) * (uint)sizeof(xfs_dir_leaf_entry_t); - memmove(entry, entry + 1, tmp); - be16_add(&hdr->count, -1); - xfs_da_log_buf(trans, bp, - XFS_DA_LOGRANGE(leaf, entry, tmp + (uint)sizeof(*entry))); - entry = &leaf->entries[be16_to_cpu(hdr->count)]; - memset((char *)entry, 0, sizeof(xfs_dir_leaf_entry_t)); - - /* - * If we removed the first entry, re-find the first used byte - * in the name area. Note that if the entry was the "firstused", - * then we don't have a "hole" in our block resulting from - * removing the name. - */ - if (smallest) { - tmp = XFS_LBSIZE(mp); - entry = &leaf->entries[0]; - for (i = be16_to_cpu(hdr->count)-1; i >= 0; entry++, i--) { - ASSERT(be16_to_cpu(entry->nameidx) >= - be16_to_cpu(hdr->firstused)); - ASSERT(be16_to_cpu(entry->nameidx) < XFS_LBSIZE(mp)); - if (be16_to_cpu(entry->nameidx) < tmp) - tmp = be16_to_cpu(entry->nameidx); - } - hdr->firstused = cpu_to_be16(tmp); - if (!hdr->firstused) - hdr->firstused = cpu_to_be16(tmp - 1); - } else { - hdr->holes = 1; /* mark as needing compaction */ - } - - xfs_da_log_buf(trans, bp, XFS_DA_LOGRANGE(leaf, hdr, sizeof(*hdr))); - - /* - * Check if leaf is less than 50% full, caller may want to - * "join" the leaf with a sibling if so. - */ - tmp = (uint)sizeof(xfs_dir_leaf_hdr_t); - tmp += be16_to_cpu(leaf->hdr.count) * (uint)sizeof(xfs_dir_leaf_entry_t); - tmp += be16_to_cpu(leaf->hdr.count) * ((uint)sizeof(xfs_dir_leaf_name_t) - 1); - tmp += be16_to_cpu(leaf->hdr.namebytes); - if (tmp < mp->m_dir_magicpct) - return 1; /* leaf is < 37% full */ - return 0; -} - -/* - * Move all the directory entries from drop_leaf into save_leaf. - */ -void -xfs_dir_leaf_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk, - xfs_da_state_blk_t *save_blk) -{ - xfs_dir_leafblock_t *drop_leaf, *save_leaf, *tmp_leaf; - xfs_dir_leaf_hdr_t *drop_hdr, *save_hdr, *tmp_hdr; - xfs_mount_t *mp; - char *tmpbuffer; - - /* - * Set up environment. - */ - mp = state->mp; - ASSERT(drop_blk->magic == XFS_DIR_LEAF_MAGIC); - ASSERT(save_blk->magic == XFS_DIR_LEAF_MAGIC); - drop_leaf = drop_blk->bp->data; - save_leaf = save_blk->bp->data; - ASSERT(be16_to_cpu(drop_leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); - ASSERT(be16_to_cpu(save_leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); - drop_hdr = &drop_leaf->hdr; - save_hdr = &save_leaf->hdr; - - /* - * Save last hashval from dying block for later Btree fixup. - */ - drop_blk->hashval = be32_to_cpu(drop_leaf->entries[ - be16_to_cpu(drop_leaf->hdr.count)-1].hashval); - - /* - * Check if we need a temp buffer, or can we do it in place. - * Note that we don't check "leaf" for holes because we will - * always be dropping it, toosmall() decided that for us already. - */ - if (save_hdr->holes == 0) { - /* - * dest leaf has no holes, so we add there. May need - * to make some room in the entry array. - */ - if (xfs_dir_leaf_order(save_blk->bp, drop_blk->bp)) { - xfs_dir_leaf_moveents(drop_leaf, 0, save_leaf, 0, - be16_to_cpu(drop_hdr->count), mp); - } else { - xfs_dir_leaf_moveents(drop_leaf, 0, - save_leaf, be16_to_cpu(save_hdr->count), - be16_to_cpu(drop_hdr->count), mp); - } - } else { - /* - * Destination has holes, so we make a temporary copy - * of the leaf and add them both to that. - */ - tmpbuffer = kmem_alloc(state->blocksize, KM_SLEEP); - ASSERT(tmpbuffer != NULL); - memset(tmpbuffer, 0, state->blocksize); - tmp_leaf = (xfs_dir_leafblock_t *)tmpbuffer; - tmp_hdr = &tmp_leaf->hdr; - tmp_hdr->info = save_hdr->info; /* struct copy */ - tmp_hdr->count = 0; - tmp_hdr->firstused = cpu_to_be16(state->blocksize); - if (!tmp_hdr->firstused) - tmp_hdr->firstused = cpu_to_be16(state->blocksize - 1); - tmp_hdr->namebytes = 0; - if (xfs_dir_leaf_order(save_blk->bp, drop_blk->bp)) { - xfs_dir_leaf_moveents(drop_leaf, 0, tmp_leaf, 0, - be16_to_cpu(drop_hdr->count), mp); - xfs_dir_leaf_moveents(save_leaf, 0, - tmp_leaf, be16_to_cpu(tmp_leaf->hdr.count), - be16_to_cpu(save_hdr->count), mp); - } else { - xfs_dir_leaf_moveents(save_leaf, 0, tmp_leaf, 0, - be16_to_cpu(save_hdr->count), mp); - xfs_dir_leaf_moveents(drop_leaf, 0, - tmp_leaf, be16_to_cpu(tmp_leaf->hdr.count), - be16_to_cpu(drop_hdr->count), mp); - } - memcpy(save_leaf, tmp_leaf, state->blocksize); - kmem_free(tmpbuffer, state->blocksize); - } - - xfs_da_log_buf(state->args->trans, save_blk->bp, 0, - state->blocksize - 1); - - /* - * Copy out last hashval in each block for B-tree code. - */ - save_blk->hashval = be32_to_cpu(save_leaf->entries[ - be16_to_cpu(save_leaf->hdr.count)-1].hashval); -} - -/*======================================================================== - * Routines used for finding things in the Btree. - *========================================================================*/ - -/* - * Look up a name in a leaf directory structure. - * This is the internal routine, it uses the caller's buffer. - * - * Note that duplicate keys are allowed, but only check within the - * current leaf node. The Btree code must check in adjacent leaf nodes. - * - * Return in *index the index into the entry[] array of either the found - * entry, or where the entry should have been (insert before that entry). - * - * Don't change the args->inumber unless we find the filename. - */ -int -xfs_dir_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args, int *index) -{ - xfs_dir_leafblock_t *leaf; - xfs_dir_leaf_entry_t *entry; - xfs_dir_leaf_name_t *namest; - int probe, span; - xfs_dahash_t hashval; - - leaf = bp->data; - ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); - ASSERT(be16_to_cpu(leaf->hdr.count) < (XFS_LBSIZE(args->dp->i_mount)/8)); - - /* - * Binary search. (note: small blocks will skip this loop) - */ - hashval = args->hashval; - probe = span = be16_to_cpu(leaf->hdr.count) / 2; - for (entry = &leaf->entries[probe]; span > 4; - entry = &leaf->entries[probe]) { - span /= 2; - if (be32_to_cpu(entry->hashval) < hashval) - probe += span; - else if (be32_to_cpu(entry->hashval) > hashval) - probe -= span; - else - break; - } - ASSERT((probe >= 0) && \ - ((!leaf->hdr.count) || (probe < be16_to_cpu(leaf->hdr.count)))); - ASSERT((span <= 4) || (be32_to_cpu(entry->hashval) == hashval)); - - /* - * Since we may have duplicate hashval's, find the first matching - * hashval in the leaf. - */ - while ((probe > 0) && (be32_to_cpu(entry->hashval) >= hashval)) { - entry--; - probe--; - } - while ((probe < be16_to_cpu(leaf->hdr.count)) && - (be32_to_cpu(entry->hashval) < hashval)) { - entry++; - probe++; - } - if ((probe == be16_to_cpu(leaf->hdr.count)) || - (be32_to_cpu(entry->hashval) != hashval)) { - *index = probe; - ASSERT(args->oknoent); - return XFS_ERROR(ENOENT); - } - - /* - * Duplicate keys may be present, so search all of them for a match. - */ - while ((probe < be16_to_cpu(leaf->hdr.count)) && - (be32_to_cpu(entry->hashval) == hashval)) { - namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, be16_to_cpu(entry->nameidx)); - if (entry->namelen == args->namelen && - namest->name[0] == args->name[0] && - memcmp(args->name, namest->name, args->namelen) == 0) { - XFS_DIR_SF_GET_DIRINO(&namest->inumber, &args->inumber); - *index = probe; - return XFS_ERROR(EEXIST); - } - entry++; - probe++; - } - *index = probe; - ASSERT(probe == be16_to_cpu(leaf->hdr.count) || args->oknoent); - return XFS_ERROR(ENOENT); -} - -/*======================================================================== - * Utility routines. - *========================================================================*/ - -/* - * Move the indicated entries from one leaf to another. - * NOTE: this routine modifies both source and destination leaves. - */ -/* ARGSUSED */ -STATIC void -xfs_dir_leaf_moveents(xfs_dir_leafblock_t *leaf_s, int start_s, - xfs_dir_leafblock_t *leaf_d, int start_d, - int count, xfs_mount_t *mp) -{ - xfs_dir_leaf_hdr_t *hdr_s, *hdr_d; - xfs_dir_leaf_entry_t *entry_s, *entry_d; - int tmp, i; - - /* - * Check for nothing to do. - */ - if (count == 0) - return; - - /* - * Set up environment. - */ - ASSERT(be16_to_cpu(leaf_s->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); - ASSERT(be16_to_cpu(leaf_d->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); - hdr_s = &leaf_s->hdr; - hdr_d = &leaf_d->hdr; - ASSERT(hdr_s->count && (be16_to_cpu(hdr_s->count) < (XFS_LBSIZE(mp)/8))); - ASSERT(be16_to_cpu(hdr_s->firstused) >= - ((be16_to_cpu(hdr_s->count)*sizeof(*entry_s))+sizeof(*hdr_s))); - ASSERT(be16_to_cpu(hdr_d->count) < (XFS_LBSIZE(mp)/8)); - ASSERT(be16_to_cpu(hdr_d->firstused) >= - ((be16_to_cpu(hdr_d->count)*sizeof(*entry_d))+sizeof(*hdr_d))); - - ASSERT(start_s < be16_to_cpu(hdr_s->count)); - ASSERT(start_d <= be16_to_cpu(hdr_d->count)); - ASSERT(count <= be16_to_cpu(hdr_s->count)); - - /* - * Move the entries in the destination leaf up to make a hole? - */ - if (start_d < be16_to_cpu(hdr_d->count)) { - tmp = be16_to_cpu(hdr_d->count) - start_d; - tmp *= (uint)sizeof(xfs_dir_leaf_entry_t); - entry_s = &leaf_d->entries[start_d]; - entry_d = &leaf_d->entries[start_d + count]; - memcpy(entry_d, entry_s, tmp); - } - - /* - * Copy all entry's in the same (sorted) order, - * but allocate filenames packed and in sequence. - */ - entry_s = &leaf_s->entries[start_s]; - entry_d = &leaf_d->entries[start_d]; - for (i = 0; i < count; entry_s++, entry_d++, i++) { - ASSERT(be16_to_cpu(entry_s->nameidx) >= - be16_to_cpu(hdr_s->firstused)); - tmp = XFS_DIR_LEAF_ENTSIZE_BYENTRY(entry_s); - be16_add(&hdr_d->firstused, -(tmp)); - entry_d->hashval = entry_s->hashval; - entry_d->nameidx = hdr_d->firstused; - entry_d->namelen = entry_s->namelen; - ASSERT(be16_to_cpu(entry_d->nameidx) + tmp <= XFS_LBSIZE(mp)); - memcpy(XFS_DIR_LEAF_NAMESTRUCT(leaf_d, be16_to_cpu(entry_d->nameidx)), - XFS_DIR_LEAF_NAMESTRUCT(leaf_s, be16_to_cpu(entry_s->nameidx)), tmp); - ASSERT(be16_to_cpu(entry_s->nameidx) + tmp <= XFS_LBSIZE(mp)); - memset((char *)XFS_DIR_LEAF_NAMESTRUCT(leaf_s, - be16_to_cpu(entry_s->nameidx)), 0, tmp); - be16_add(&hdr_s->namebytes, -(entry_d->namelen)); - be16_add(&hdr_d->namebytes, entry_d->namelen); - be16_add(&hdr_s->count, -1); - be16_add(&hdr_d->count, +1); - tmp = be16_to_cpu(hdr_d->count) * (uint)sizeof(xfs_dir_leaf_entry_t) - + (uint)sizeof(xfs_dir_leaf_hdr_t); - ASSERT(be16_to_cpu(hdr_d->firstused) >= tmp); - - } - - /* - * Zero out the entries we just copied. - */ - if (start_s == be16_to_cpu(hdr_s->count)) { - tmp = count * (uint)sizeof(xfs_dir_leaf_entry_t); - entry_s = &leaf_s->entries[start_s]; - ASSERT((char *)entry_s + tmp <= (char *)leaf_s + XFS_LBSIZE(mp)); - memset((char *)entry_s, 0, tmp); - } else { - /* - * Move the remaining entries down to fill the hole, - * then zero the entries at the top. - */ - tmp = be16_to_cpu(hdr_s->count) - count; - tmp *= (uint)sizeof(xfs_dir_leaf_entry_t); - entry_s = &leaf_s->entries[start_s + count]; - entry_d = &leaf_s->entries[start_s]; - memcpy(entry_d, entry_s, tmp); - - tmp = count * (uint)sizeof(xfs_dir_leaf_entry_t); - entry_s = &leaf_s->entries[be16_to_cpu(hdr_s->count)]; - ASSERT((char *)entry_s + tmp <= (char *)leaf_s + XFS_LBSIZE(mp)); - memset((char *)entry_s, 0, tmp); - } - - /* - * Fill in the freemap information - */ - hdr_d->freemap[0].base = cpu_to_be16(sizeof(xfs_dir_leaf_hdr_t) + - be16_to_cpu(hdr_d->count) * sizeof(xfs_dir_leaf_entry_t)); - hdr_d->freemap[0].size = cpu_to_be16(be16_to_cpu(hdr_d->firstused) - - be16_to_cpu(hdr_d->freemap[0].base)); - hdr_d->freemap[1].base = 0; - hdr_d->freemap[1].size = 0; - hdr_d->freemap[2].base = 0; - hdr_d->freemap[2].size = 0; - hdr_s->holes = 1; /* leaf may not be compact */ -} - -/* - * Compare two leaf blocks "order". - */ -int -xfs_dir_leaf_order(xfs_dabuf_t *leaf1_bp, xfs_dabuf_t *leaf2_bp) -{ - xfs_dir_leafblock_t *leaf1, *leaf2; - - leaf1 = leaf1_bp->data; - leaf2 = leaf2_bp->data; - ASSERT((be16_to_cpu(leaf1->hdr.info.magic) == XFS_DIR_LEAF_MAGIC) && - (be16_to_cpu(leaf2->hdr.info.magic) == XFS_DIR_LEAF_MAGIC)); - if (leaf1->hdr.count && leaf2->hdr.count && - ((be32_to_cpu(leaf2->entries[0].hashval) < - be32_to_cpu(leaf1->entries[0 ].hashval)) || - (be32_to_cpu(leaf2->entries[ - be16_to_cpu(leaf2->hdr.count)-1].hashval) < - be32_to_cpu(leaf1->entries[ - be16_to_cpu(leaf1->hdr.count)-1].hashval)))) { - return 1; - } - return 0; -} - -/* - * Pick up the last hashvalue from a leaf block. - */ -xfs_dahash_t -xfs_dir_leaf_lasthash(xfs_dabuf_t *bp, int *count) -{ - xfs_dir_leafblock_t *leaf; - - leaf = bp->data; - ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); - if (count) - *count = be16_to_cpu(leaf->hdr.count); - if (!leaf->hdr.count) - return(0); - return be32_to_cpu(leaf->entries[be16_to_cpu(leaf->hdr.count)-1].hashval); -} - -/* - * Copy out directory entries for getdents(), for leaf directories. - */ -int -xfs_dir_leaf_getdents_int( - xfs_dabuf_t *bp, - xfs_inode_t *dp, - xfs_dablk_t bno, - uio_t *uio, - int *eobp, - xfs_dirent_t *dbp, - xfs_dir_put_t put, - xfs_daddr_t nextda) -{ - xfs_dir_leafblock_t *leaf; - xfs_dir_leaf_entry_t *entry; - xfs_dir_leaf_name_t *namest; - int entno, want_entno, i, nextentno; - xfs_mount_t *mp; - xfs_dahash_t cookhash; - xfs_dahash_t nexthash = 0; -#if (BITS_PER_LONG == 32) - xfs_dahash_t lasthash = XFS_DA_MAXHASH; -#endif - xfs_dir_put_args_t p; - - mp = dp->i_mount; - leaf = bp->data; - if (be16_to_cpu(leaf->hdr.info.magic) != XFS_DIR_LEAF_MAGIC) { - *eobp = 1; - return XFS_ERROR(ENOENT); /* XXX wrong code */ - } - - want_entno = XFS_DA_COOKIE_ENTRY(mp, uio->uio_offset); - - cookhash = XFS_DA_COOKIE_HASH(mp, uio->uio_offset); - - xfs_dir_trace_g_dul("leaf: start", dp, uio, leaf); - - /* - * Re-find our place. - */ - for (i = entno = 0, entry = &leaf->entries[0]; - i < be16_to_cpu(leaf->hdr.count); entry++, i++) { - - namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, - be16_to_cpu(entry->nameidx)); - - if (unlikely( - ((char *)namest < (char *)leaf) || - ((char *)namest >= (char *)leaf + XFS_LBSIZE(mp)))) { - XFS_CORRUPTION_ERROR("xfs_dir_leaf_getdents_int(1)", - XFS_ERRLEVEL_LOW, mp, leaf); - xfs_dir_trace_g_du("leaf: corrupted", dp, uio); - return XFS_ERROR(EFSCORRUPTED); - } - if (be32_to_cpu(entry->hashval) >= cookhash) { - if (entno < want_entno && - be32_to_cpu(entry->hashval) == cookhash) { - /* - * Trying to get to a particular offset in a - * run of equal-hashval entries. - */ - entno++; - } else if (want_entno > 0 && entno == want_entno && - be32_to_cpu(entry->hashval) == cookhash) { - break; - } else { - entno = 0; - break; - } - } - } - - if (i == be16_to_cpu(leaf->hdr.count)) { - xfs_dir_trace_g_du("leaf: hash not found", dp, uio); - if (!leaf->hdr.info.forw) - uio->uio_offset = - XFS_DA_MAKE_COOKIE(mp, 0, 0, XFS_DA_MAXHASH); - /* - * Don't set uio_offset if there's another block: - * the node code will be setting uio_offset anyway. - */ - *eobp = 0; - return 0; - } - xfs_dir_trace_g_due("leaf: hash found", dp, uio, entry); - - p.dbp = dbp; - p.put = put; - p.uio = uio; - - /* - * We're synchronized, start copying entries out to the user. - */ - for (; entno >= 0 && i < be16_to_cpu(leaf->hdr.count); - entry++, i++, (entno = nextentno)) { - int lastresid=0, retval; - xfs_dircook_t lastoffset; - xfs_dahash_t thishash; - - /* - * Check for a damaged directory leaf block and pick up - * the inode number from this entry. - */ - namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, - be16_to_cpu(entry->nameidx)); - - if (unlikely( - ((char *)namest < (char *)leaf) || - ((char *)namest >= (char *)leaf + XFS_LBSIZE(mp)))) { - XFS_CORRUPTION_ERROR("xfs_dir_leaf_getdents_int(2)", - XFS_ERRLEVEL_LOW, mp, leaf); - xfs_dir_trace_g_du("leaf: corrupted", dp, uio); - return XFS_ERROR(EFSCORRUPTED); - } - - xfs_dir_trace_g_duc("leaf: middle cookie ", - dp, uio, p.cook.o); - - if (i < (be16_to_cpu(leaf->hdr.count) - 1)) { - nexthash = be32_to_cpu(entry[1].hashval); - - if (nexthash == be32_to_cpu(entry->hashval)) - nextentno = entno + 1; - else - nextentno = 0; - XFS_PUT_COOKIE(p.cook, mp, bno, nextentno, nexthash); - xfs_dir_trace_g_duc("leaf: middle cookie ", - dp, uio, p.cook.o); - - } else if ((thishash = be32_to_cpu(leaf->hdr.info.forw))) { - xfs_dabuf_t *bp2; - xfs_dir_leafblock_t *leaf2; - - ASSERT(nextda != -1); - - retval = xfs_da_read_buf(dp->i_transp, dp, thishash, - nextda, &bp2, XFS_DATA_FORK); - if (retval) - return retval; - - ASSERT(bp2 != NULL); - - leaf2 = bp2->data; - - if (unlikely( - (be16_to_cpu(leaf2->hdr.info.magic) - != XFS_DIR_LEAF_MAGIC) - || (be32_to_cpu(leaf2->hdr.info.back) - != bno))) { /* GROT */ - XFS_CORRUPTION_ERROR("xfs_dir_leaf_getdents_int(3)", - XFS_ERRLEVEL_LOW, mp, - leaf2); - xfs_da_brelse(dp->i_transp, bp2); - - return XFS_ERROR(EFSCORRUPTED); - } - - nexthash = be32_to_cpu(leaf2->entries[0].hashval); - nextentno = -1; - XFS_PUT_COOKIE(p.cook, mp, thishash, 0, nexthash); - xfs_da_brelse(dp->i_transp, bp2); - xfs_dir_trace_g_duc("leaf: next blk cookie", - dp, uio, p.cook.o); - } else { - nextentno = -1; - XFS_PUT_COOKIE(p.cook, mp, 0, 0, XFS_DA_MAXHASH); - } - - /* - * Save off the cookie so we can fall back should the - * 'put' into the outgoing buffer fails. To handle a run - * of equal-hashvals, the off_t structure on 64bit - * builds has entno built into the cookie to ID the - * entry. On 32bit builds, we only have space for the - * hashval so we can't ID specific entries within a group - * of same hashval entries. For this, lastoffset is set - * to the first in the run of equal hashvals so we don't - * include any entries unless we can include all entries - * that share the same hashval. Hopefully the buffer - * provided is big enough to handle it (see pv763517). - */ - thishash = be32_to_cpu(entry->hashval); -#if (BITS_PER_LONG == 32) - if (thishash != lasthash) { - XFS_PUT_COOKIE(lastoffset, mp, bno, entno, thishash); - lastresid = uio->uio_resid; - lasthash = thishash; - } else { - xfs_dir_trace_g_duc("leaf: DUP COOKIES, skipped", - dp, uio, p.cook.o); - } -#else - XFS_PUT_COOKIE(lastoffset, mp, bno, entno, thishash); - lastresid = uio->uio_resid; -#endif /* BITS_PER_LONG == 32 */ - - /* - * Put the current entry into the outgoing buffer. If we fail - * then restore the UIO to the first entry in the current - * run of equal-hashval entries (probably one 1 entry long). - */ - p.ino = XFS_GET_DIR_INO8(namest->inumber); -#if XFS_BIG_INUMS - p.ino += mp->m_inoadd; -#endif - p.name = (char *)namest->name; - p.namelen = entry->namelen; - - retval = p.put(&p); - - if (!p.done) { - uio->uio_offset = lastoffset.o; - uio->uio_resid = lastresid; - - *eobp = 1; - - xfs_dir_trace_g_du("leaf: E-O-B", dp, uio); - - return retval; - } - } - - uio->uio_offset = p.cook.o; - - *eobp = 0; - - xfs_dir_trace_g_du("leaf: E-O-F", dp, uio); - - return 0; -} - -/* - * Format a dirent64 structure and copy it out the the user's buffer. - */ -int -xfs_dir_put_dirent64_direct(xfs_dir_put_args_t *pa) -{ - iovec_t *iovp; - int reclen, namelen; - xfs_dirent_t *idbp; - uio_t *uio; - - namelen = pa->namelen; - reclen = DIRENTSIZE(namelen); - uio = pa->uio; - if (reclen > uio->uio_resid) { - pa->done = 0; - return 0; - } - iovp = uio->uio_iov; - idbp = (xfs_dirent_t *)iovp->iov_base; - iovp->iov_base = (char *)idbp + reclen; - iovp->iov_len -= reclen; - uio->uio_resid -= reclen; - idbp->d_reclen = reclen; - idbp->d_ino = pa->ino; - idbp->d_off = pa->cook.o; - idbp->d_name[namelen] = '\0'; - pa->done = 1; - memcpy(idbp->d_name, pa->name, namelen); - return 0; -} - -/* - * Format a dirent64 structure and copy it out the the user's buffer. - */ -int -xfs_dir_put_dirent64_uio(xfs_dir_put_args_t *pa) -{ - int retval, reclen, namelen; - xfs_dirent_t *idbp; - uio_t *uio; - - namelen = pa->namelen; - reclen = DIRENTSIZE(namelen); - uio = pa->uio; - if (reclen > uio->uio_resid) { - pa->done = 0; - return 0; - } - idbp = pa->dbp; - idbp->d_reclen = reclen; - idbp->d_ino = pa->ino; - idbp->d_off = pa->cook.o; - idbp->d_name[namelen] = '\0'; - memcpy(idbp->d_name, pa->name, namelen); - retval = uio_read((caddr_t)idbp, reclen, uio); - pa->done = (retval == 0); - return retval; -} diff --git a/fs/xfs/xfs_dir_leaf.h b/fs/xfs/xfs_dir_leaf.h index 7ca5845195d..e69de29bb2d 100644 --- a/fs/xfs/xfs_dir_leaf.h +++ b/fs/xfs/xfs_dir_leaf.h @@ -1,231 +0,0 @@ -/* - * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -#ifndef __XFS_DIR_LEAF_H__ -#define __XFS_DIR_LEAF_H__ - -/* - * Directory layout, internal structure, access macros, etc. - * - * Large directories are structured around Btrees where all the data - * elements are in the leaf nodes. Filenames are hashed into an int, - * then that int is used as the index into the Btree. Since the hashval - * of a filename may not be unique, we may have duplicate keys. The - * internal links in the Btree are logical block offsets into the file. - */ - -struct uio; -struct xfs_bmap_free; -struct xfs_dabuf; -struct xfs_da_args; -struct xfs_da_state; -struct xfs_da_state_blk; -struct xfs_dir_put_args; -struct xfs_inode; -struct xfs_mount; -struct xfs_trans; - -/*======================================================================== - * Directory Structure when equal to XFS_LBSIZE(mp) bytes. - *========================================================================*/ - -/* - * This is the structure of the leaf nodes in the Btree. - * - * Struct leaf_entry's are packed from the top. Names grow from the bottom - * but are not packed. The freemap contains run-length-encoded entries - * for the free bytes after the leaf_entry's, but only the N largest such, - * smaller runs are dropped. When the freemap doesn't show enough space - * for an allocation, we compact the namelist area and try again. If we - * still don't have enough space, then we have to split the block. - * - * Since we have duplicate hash keys, for each key that matches, compare - * the actual string. The root and intermediate node search always takes - * the first-in-the-block key match found, so we should only have to work - * "forw"ard. If none matches, continue with the "forw"ard leaf nodes - * until the hash key changes or the filename is found. - * - * The parent directory and the self-pointer are explicitly represented - * (ie: there are entries for "." and ".."). - * - * Note that the count being a __uint16_t limits us to something like a - * blocksize of 1.3MB in the face of worst case (short) filenames. - */ -#define XFS_DIR_LEAF_MAPSIZE 3 /* how many freespace slots */ - -typedef struct xfs_dir_leaf_map { /* RLE map of free bytes */ - __be16 base; /* base of free region */ - __be16 size; /* run length of free region */ -} xfs_dir_leaf_map_t; - -typedef struct xfs_dir_leaf_hdr { /* constant-structure header block */ - xfs_da_blkinfo_t info; /* block type, links, etc. */ - __be16 count; /* count of active leaf_entry's */ - __be16 namebytes; /* num bytes of name strings stored */ - __be16 firstused; /* first used byte in name area */ - __u8 holes; /* != 0 if blk needs compaction */ - __u8 pad1; - xfs_dir_leaf_map_t freemap[XFS_DIR_LEAF_MAPSIZE]; -} xfs_dir_leaf_hdr_t; - -typedef struct xfs_dir_leaf_entry { /* sorted on key, not name */ - __be32 hashval; /* hash value of name */ - __be16 nameidx; /* index into buffer of name */ - __u8 namelen; /* length of name string */ - __u8 pad2; -} xfs_dir_leaf_entry_t; - -typedef struct xfs_dir_leaf_name { - xfs_dir_ino_t inumber; /* inode number for this key */ - __uint8_t name[1]; /* name string itself */ -} xfs_dir_leaf_name_t; - -typedef struct xfs_dir_leafblock { - xfs_dir_leaf_hdr_t hdr; /* constant-structure header block */ - xfs_dir_leaf_entry_t entries[1]; /* var sized array */ - xfs_dir_leaf_name_t namelist[1]; /* grows from bottom of buf */ -} xfs_dir_leafblock_t; - -/* - * Length of name for which a 512-byte block filesystem - * can get a double split. - */ -#define XFS_DIR_LEAF_CAN_DOUBLE_SPLIT_LEN \ - (512 - (uint)sizeof(xfs_dir_leaf_hdr_t) - \ - (uint)sizeof(xfs_dir_leaf_entry_t) * 2 - \ - (uint)sizeof(xfs_dir_leaf_name_t) * 2 - (MAXNAMELEN - 2) + 1 + 1) - -typedef int (*xfs_dir_put_t)(struct xfs_dir_put_args *pa); - -typedef union { - xfs_off_t o; /* offset (cookie) */ - /* - * Watch the order here (endian-ness dependent). - */ - struct { -#ifndef XFS_NATIVE_HOST - xfs_dahash_t h; /* hash value */ - __uint32_t be; /* block and entry */ -#else - __uint32_t be; /* block and entry */ - xfs_dahash_t h; /* hash value */ -#endif /* XFS_NATIVE_HOST */ - } s; -} xfs_dircook_t; - -#define XFS_PUT_COOKIE(c,mp,bno,entry,hash) \ - ((c).s.be = XFS_DA_MAKE_BNOENTRY(mp, bno, entry), (c).s.h = (hash)) - -typedef struct xfs_dir_put_args { - xfs_dircook_t cook; /* cookie of (next) entry */ - xfs_intino_t ino; /* inode number */ - struct xfs_dirent *dbp; /* buffer pointer */ - char *name; /* directory entry name */ - int namelen; /* length of name */ - int done; /* output: set if value was stored */ - xfs_dir_put_t put; /* put function ptr (i/o) */ - struct uio *uio; /* uio control structure */ -} xfs_dir_put_args_t; - -#define XFS_DIR_LEAF_ENTSIZE_BYNAME(len) \ - xfs_dir_leaf_entsize_byname(len) -static inline int xfs_dir_leaf_entsize_byname(int len) -{ - return (uint)sizeof(xfs_dir_leaf_name_t)-1 + len; -} - -#define XFS_DIR_LEAF_ENTSIZE_BYENTRY(entry) \ - xfs_dir_leaf_entsize_byentry(entry) -static inline int xfs_dir_leaf_entsize_byentry(xfs_dir_leaf_entry_t *entry) -{ - return (uint)sizeof(xfs_dir_leaf_name_t)-1 + (entry)->namelen; -} - -#define XFS_DIR_LEAF_NAMESTRUCT(leafp,offset) \ - xfs_dir_leaf_namestruct(leafp,offset) -static inline xfs_dir_leaf_name_t * -xfs_dir_leaf_namestruct(xfs_dir_leafblock_t *leafp, int offset) -{ - return (xfs_dir_leaf_name_t *)&((char *)(leafp))[offset]; -} - -/*======================================================================== - * Function prototypes for the kernel. - *========================================================================*/ - -/* - * Internal routines when dirsize < XFS_LITINO(mp). - */ -int xfs_dir_shortform_create(struct xfs_da_args *args, xfs_ino_t parent); -int xfs_dir_shortform_addname(struct xfs_da_args *args); -int xfs_dir_shortform_lookup(struct xfs_da_args *args); -int xfs_dir_shortform_to_leaf(struct xfs_da_args *args); -int xfs_dir_shortform_removename(struct xfs_da_args *args); -int xfs_dir_shortform_getdents(struct xfs_inode *dp, struct uio *uio, int *eofp, - struct xfs_dirent *dbp, xfs_dir_put_t put); -int xfs_dir_shortform_replace(struct xfs_da_args *args); - -/* - * Internal routines when dirsize == XFS_LBSIZE(mp). - */ -int xfs_dir_leaf_to_node(struct xfs_da_args *args); -int xfs_dir_leaf_to_shortform(struct xfs_da_args *args); - -/* - * Routines used for growing the Btree. - */ -int xfs_dir_leaf_split(struct xfs_da_state *state, - struct xfs_da_state_blk *oldblk, - struct xfs_da_state_blk *newblk); -int xfs_dir_leaf_add(struct xfs_dabuf *leaf_buffer, - struct xfs_da_args *args, int insertion_index); -int xfs_dir_leaf_addname(struct xfs_da_args *args); -int xfs_dir_leaf_lookup_int(struct xfs_dabuf *leaf_buffer, - struct xfs_da_args *args, - int *index_found_at); -int xfs_dir_leaf_remove(struct xfs_trans *trans, - struct xfs_dabuf *leaf_buffer, - int index_to_remove); -int xfs_dir_leaf_getdents_int(struct xfs_dabuf *bp, struct xfs_inode *dp, - xfs_dablk_t bno, struct uio *uio, - int *eobp, struct xfs_dirent *dbp, - xfs_dir_put_t put, xfs_daddr_t nextda); - -/* - * Routines used for shrinking the Btree. - */ -int xfs_dir_leaf_toosmall(struct xfs_da_state *state, int *retval); -void xfs_dir_leaf_unbalance(struct xfs_da_state *state, - struct xfs_da_state_blk *drop_blk, - struct xfs_da_state_blk *save_blk); - -/* - * Utility routines. - */ -uint xfs_dir_leaf_lasthash(struct xfs_dabuf *bp, int *count); -int xfs_dir_leaf_order(struct xfs_dabuf *leaf1_bp, - struct xfs_dabuf *leaf2_bp); -int xfs_dir_put_dirent64_direct(xfs_dir_put_args_t *pa); -int xfs_dir_put_dirent64_uio(xfs_dir_put_args_t *pa); -int xfs_dir_ino_validate(struct xfs_mount *mp, xfs_ino_t ino); - -/* - * Global data. - */ -extern xfs_dahash_t xfs_dir_hash_dot, xfs_dir_hash_dotdot; - -#endif /* __XFS_DIR_LEAF_H__ */ diff --git a/fs/xfs/xfs_dir_sf.h b/fs/xfs/xfs_dir_sf.h index 5b20b4d3f57..e69de29bb2d 100644 --- a/fs/xfs/xfs_dir_sf.h +++ b/fs/xfs/xfs_dir_sf.h @@ -1,155 +0,0 @@ -/* - * Copyright (c) 2000,2005 Silicon Graphics, Inc. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -#ifndef __XFS_DIR_SF_H__ -#define __XFS_DIR_SF_H__ - -/* - * Directory layout when stored internal to an inode. - * - * Small directories are packed as tightly as possible so as to - * fit into the literal area of the inode. - */ - -typedef struct { __uint8_t i[sizeof(xfs_ino_t)]; } xfs_dir_ino_t; - -/* - * The parent directory has a dedicated field, and the self-pointer must - * be calculated on the fly. - * - * Entries are packed toward the top as tight as possible. The header - * and the elements much be memcpy'd out into a work area to get correct - * alignment for the inode number fields. - */ -typedef struct xfs_dir_sf_hdr { /* constant-structure header block */ - xfs_dir_ino_t parent; /* parent dir inode number */ - __uint8_t count; /* count of active entries */ -} xfs_dir_sf_hdr_t; - -typedef struct xfs_dir_sf_entry { - xfs_dir_ino_t inumber; /* referenced inode number */ - __uint8_t namelen; /* actual length of name (no NULL) */ - __uint8_t name[1]; /* name */ -} xfs_dir_sf_entry_t; - -typedef struct xfs_dir_shortform { - xfs_dir_sf_hdr_t hdr; - xfs_dir_sf_entry_t list[1]; /* variable sized array */ -} xfs_dir_shortform_t; - -/* - * We generate this then sort it, so that readdirs are returned in - * hash-order. Else seekdir won't work. - */ -typedef struct xfs_dir_sf_sort { - __uint8_t entno; /* .=0, ..=1, else entry# + 2 */ - __uint8_t seqno; /* sequence # with same hash value */ - __uint8_t namelen; /* length of name value (no null) */ - xfs_dahash_t hash; /* this entry's hash value */ - xfs_intino_t ino; /* this entry's inode number */ - char *name; /* name value, pointer into buffer */ -} xfs_dir_sf_sort_t; - -#define XFS_DIR_SF_GET_DIRINO(from,to) xfs_dir_sf_get_dirino(from, to) -static inline void xfs_dir_sf_get_dirino(xfs_dir_ino_t *from, xfs_ino_t *to) -{ - *(to) = XFS_GET_DIR_INO8(*from); -} - -#define XFS_DIR_SF_PUT_DIRINO(from,to) xfs_dir_sf_put_dirino(from, to) -static inline void xfs_dir_sf_put_dirino(xfs_ino_t *from, xfs_dir_ino_t *to) -{ - XFS_PUT_DIR_INO8(*(from), *(to)); -} - -#define XFS_DIR_SF_ENTSIZE_BYNAME(len) xfs_dir_sf_entsize_byname(len) -static inline int xfs_dir_sf_entsize_byname(int len) -{ - return (uint)sizeof(xfs_dir_sf_entry_t)-1 + (len); -} - -#define XFS_DIR_SF_ENTSIZE_BYENTRY(sfep) xfs_dir_sf_entsize_byentry(sfep) -static inline int xfs_dir_sf_entsize_byentry(xfs_dir_sf_entry_t *sfep) -{ - return (uint)sizeof(xfs_dir_sf_entry_t)-1 + (sfep)->namelen; -} - -#define XFS_DIR_SF_NEXTENTRY(sfep) xfs_dir_sf_nextentry(sfep) -static inline xfs_dir_sf_entry_t *xfs_dir_sf_nextentry(xfs_dir_sf_entry_t *sfep) -{ - return (xfs_dir_sf_entry_t *) \ - ((char *)(sfep) + XFS_DIR_SF_ENTSIZE_BYENTRY(sfep)); -} - -#define XFS_DIR_SF_ALLFIT(count,totallen) \ - xfs_dir_sf_allfit(count,totallen) -static inline int xfs_dir_sf_allfit(int count, int totallen) -{ - return ((uint)sizeof(xfs_dir_sf_hdr_t) + \ - ((uint)sizeof(xfs_dir_sf_entry_t)-1)*(count) + (totallen)); -} - -#if defined(XFS_DIR_TRACE) - -/* - * Kernel tracing support for directories. - */ -struct uio; -struct xfs_inode; -struct xfs_da_intnode; -struct xfs_dinode; -struct xfs_dir_leafblock; -struct xfs_dir_leaf_entry; - -#define XFS_DIR_TRACE_SIZE 4096 /* size of global trace buffer */ -extern ktrace_t *xfs_dir_trace_buf; - -/* - * Trace record types. - */ -#define XFS_DIR_KTRACE_G_DU 1 /* dp, uio */ -#define XFS_DIR_KTRACE_G_DUB 2 /* dp, uio, bno */ -#define XFS_DIR_KTRACE_G_DUN 3 /* dp, uio, node */ -#define XFS_DIR_KTRACE_G_DUL 4 /* dp, uio, leaf */ -#define XFS_DIR_KTRACE_G_DUE 5 /* dp, uio, leaf entry */ -#define XFS_DIR_KTRACE_G_DUC 6 /* dp, uio, cookie */ - -void xfs_dir_trace_g_du(char *where, struct xfs_inode *dp, struct uio *uio); -void xfs_dir_trace_g_dub(char *where, struct xfs_inode *dp, struct uio *uio, - xfs_dablk_t bno); -void xfs_dir_trace_g_dun(char *where, struct xfs_inode *dp, struct uio *uio, - struct xfs_da_intnode *node); -void xfs_dir_trace_g_dul(char *where, struct xfs_inode *dp, struct uio *uio, - struct xfs_dir_leafblock *leaf); -void xfs_dir_trace_g_due(char *where, struct xfs_inode *dp, struct uio *uio, - struct xfs_dir_leaf_entry *entry); -void xfs_dir_trace_g_duc(char *where, struct xfs_inode *dp, struct uio *uio, - xfs_off_t cookie); -void xfs_dir_trace_enter(int type, char *where, - void *a0, void *a1, void *a2, void *a3, - void *a4, void *a5, void *a6, void *a7, - void *a8, void *a9, void *a10, void *a11); -#else -#define xfs_dir_trace_g_du(w,d,u) -#define xfs_dir_trace_g_dub(w,d,u,b) -#define xfs_dir_trace_g_dun(w,d,u,n) -#define xfs_dir_trace_g_dul(w,d,u,l) -#define xfs_dir_trace_g_due(w,d,u,e) -#define xfs_dir_trace_g_duc(w,d,u,c) -#endif /* DEBUG */ - -#endif /* __XFS_DIR_SF_H__ */ diff --git a/fs/xfs/xfs_dmops.c b/fs/xfs/xfs_dmops.c index 629795b3b3d..1e4a35ddf7f 100644 --- a/fs/xfs/xfs_dmops.c +++ b/fs/xfs/xfs_dmops.c @@ -23,7 +23,6 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_dmapi.h" #include "xfs_mount.h" diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c index 2a21c502401..b95681b03d8 100644 --- a/fs/xfs/xfs_error.c +++ b/fs/xfs/xfs_error.c @@ -22,12 +22,10 @@ #include "xfs_inum.h" #include "xfs_trans.h" #include "xfs_sb.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_dmapi.h" #include "xfs_mount.h" #include "xfs_bmap_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c index 8b028f12854..6cf6d8769b9 100644 --- a/fs/xfs/xfs_extfree_item.c +++ b/fs/xfs/xfs_extfree_item.c @@ -23,7 +23,6 @@ #include "xfs_trans.h" #include "xfs_buf_item.h" #include "xfs_sb.h" -#include "xfs_dir.h" #include "xfs_dmapi.h" #include "xfs_mount.h" #include "xfs_trans_priv.h" diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index 650d35f537b..077629bab53 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -24,14 +24,12 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_dmapi.h" #include "xfs_mount.h" #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c index 7e5ccfec92b..33164a85aa9 100644 --- a/fs/xfs/xfs_ialloc.c +++ b/fs/xfs/xfs_ialloc.c @@ -24,14 +24,12 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_dmapi.h" #include "xfs_mount.h" #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" diff --git a/fs/xfs/xfs_ialloc_btree.c b/fs/xfs/xfs_ialloc_btree.c index 60c65683462..616eeeb6953 100644 --- a/fs/xfs/xfs_ialloc_btree.c +++ b/fs/xfs/xfs_ialloc_btree.c @@ -24,14 +24,12 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_dmapi.h" #include "xfs_mount.h" #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index 7894b72a717..0724df7fabb 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c @@ -24,14 +24,12 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_dmapi.h" #include "xfs_mount.h" #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index e799f0d0087..5fa0adb7e17 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -26,14 +26,12 @@ #include "xfs_trans_priv.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_dmapi.h" #include "xfs_mount.h" #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" @@ -2925,13 +2923,6 @@ xfs_iflush_fork( ASSERT(ifp->if_bytes <= XFS_IFORK_SIZE(ip, whichfork)); memcpy(cp, ifp->if_u1.if_data, ifp->if_bytes); } - if (whichfork == XFS_DATA_FORK) { - if (unlikely(XFS_DIR_SHORTFORM_VALIDATE_ONDISK(mp, dip))) { - XFS_ERROR_REPORT("xfs_iflush_fork", - XFS_ERRLEVEL_LOW, mp); - return XFS_ERROR(EFSCORRUPTED); - } - } break; case XFS_DINODE_FMT_EXTENTS: diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index 2caa91b8971..f8e80d8e723 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c @@ -25,7 +25,6 @@ #include "xfs_buf_item.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_dmapi.h" #include "xfs_mount.h" @@ -33,7 +32,6 @@ #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" diff --git a/fs/xfs/xfs_iocore.c b/fs/xfs/xfs_iocore.c index 89441e69cdd..06d710c9ce4 100644 --- a/fs/xfs/xfs_iocore.c +++ b/fs/xfs/xfs_iocore.c @@ -24,7 +24,6 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_dfrag.h" #include "xfs_dmapi.h" @@ -32,7 +31,6 @@ #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index d79055207fb..f1949c16df1 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -23,7 +23,6 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_alloc.h" #include "xfs_dmapi.h" @@ -32,7 +31,6 @@ #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c index a0182ced29c..46249e4d1fe 100644 --- a/fs/xfs/xfs_itable.c +++ b/fs/xfs/xfs_itable.c @@ -24,14 +24,12 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_dmapi.h" #include "xfs_mount.h" #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 95d679cd4e7..d8f5d4cbe8b 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -24,7 +24,6 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_dmapi.h" #include "xfs_mount.h" @@ -36,7 +35,6 @@ #include "xfs_ialloc_btree.h" #include "xfs_log_recover.h" #include "xfs_trans_priv.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index f952f9dbf74..55b4237c215 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -24,7 +24,6 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_dmapi.h" #include "xfs_mount.h" @@ -32,7 +31,6 @@ #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 5ce6416fbd3..10dbf203c62 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -24,14 +24,12 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_dmapi.h" #include "xfs_mount.h" #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" @@ -934,18 +932,7 @@ xfs_mountfs( vfsp->vfs_altfsid = (xfs_fsid_t *)mp->m_fixedfsid; mp->m_dmevmask = 0; /* not persistent; set after each mount */ - /* - * Select the right directory manager. - */ - mp->m_dirops = - XFS_SB_VERSION_HASDIRV2(&mp->m_sb) ? - xfsv2_dirops : - xfsv1_dirops; - - /* - * Initialize directory manager's entries. - */ - XFS_DIR_MOUNT(mp); + xfs_dir_mount(mp); /* * Initialize the attribute manager's entries. diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 761f42f989c..b2bd4be4200 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -403,8 +403,6 @@ typedef struct xfs_mount { __uint8_t m_inode_quiesce;/* call quiesce on new inodes. field governed by m_ilock */ __uint8_t m_sectbb_log; /* sectlog - BBSHIFT */ - __uint8_t m_dirversion; /* 1 or 2 */ - xfs_dirops_t m_dirops; /* table of dir funcs */ int m_dirblksize; /* directory block sz--bytes */ int m_dirblkfsbs; /* directory block sz--fsbs */ xfs_dablk_t m_dirdatablk; /* blockno of dir data v2 */ diff --git a/fs/xfs/xfs_qmops.c b/fs/xfs/xfs_qmops.c index 1408a32eef8..320d63ff9ca 100644 --- a/fs/xfs/xfs_qmops.c +++ b/fs/xfs/xfs_qmops.c @@ -23,7 +23,6 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_dmapi.h" #include "xfs_mount.h" diff --git a/fs/xfs/xfs_rename.c b/fs/xfs/xfs_rename.c index 7d5f9b6ffdb..d98171deaa1 100644 --- a/fs/xfs/xfs_rename.c +++ b/fs/xfs/xfs_rename.c @@ -22,13 +22,11 @@ #include "xfs_inum.h" #include "xfs_trans.h" #include "xfs_sb.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_dmapi.h" #include "xfs_mount.h" #include "xfs_da_btree.h" #include "xfs_bmap_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" @@ -40,7 +38,6 @@ #include "xfs_refcache.h" #include "xfs_utils.h" #include "xfs_trans_space.h" -#include "xfs_dir_leaf.h" /* @@ -398,34 +395,29 @@ xfs_rename( * fit before actually inserting it. */ if (spaceres == 0 && - (error = XFS_DIR_CANENTER(mp, tp, target_dp, target_name, - target_namelen))) { + (error = xfs_dir_canenter(tp, target_dp, target_name, + target_namelen))) goto error_return; - } /* * If target does not exist and the rename crosses * directories, adjust the target directory link count * to account for the ".." reference from the new entry. */ - error = XFS_DIR_CREATENAME(mp, tp, target_dp, target_name, + error = xfs_dir_createname(tp, target_dp, target_name, target_namelen, src_ip->i_ino, &first_block, &free_list, spaceres); - if (error == ENOSPC) { + if (error == ENOSPC) goto error_return; - } - if (error) { + if (error) goto abort_return; - } xfs_ichgtime(target_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); if (new_parent && src_is_directory) { error = xfs_bumplink(tp, target_dp); - if (error) { + if (error) goto abort_return; - } } } else { /* target_ip != NULL */ - /* * If target exists and it's a directory, check that both * target and source are directories and that target can be @@ -435,7 +427,7 @@ xfs_rename( /* * Make sure target dir is empty. */ - if (!(XFS_DIR_ISEMPTY(target_ip->i_mount, target_ip)) || + if (!(xfs_dir_isempty(target_ip)) || (target_ip->i_d.di_nlink > 2)) { error = XFS_ERROR(EEXIST); goto error_return; @@ -451,12 +443,11 @@ xfs_rename( * In case there is already an entry with the same * name at the destination directory, remove it first. */ - error = XFS_DIR_REPLACE(mp, tp, target_dp, target_name, - target_namelen, src_ip->i_ino, &first_block, - &free_list, spaceres); - if (error) { + error = xfs_dir_replace(tp, target_dp, target_name, + target_namelen, src_ip->i_ino, + &first_block, &free_list, spaceres); + if (error) goto abort_return; - } xfs_ichgtime(target_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); /* @@ -464,9 +455,8 @@ xfs_rename( * dir no longer points to it. */ error = xfs_droplink(tp, target_ip); - if (error) { + if (error) goto abort_return; - } target_ip_dropped = 1; if (src_is_directory) { @@ -474,9 +464,8 @@ xfs_rename( * Drop the link from the old "." entry. */ error = xfs_droplink(tp, target_ip); - if (error) { + if (error) goto abort_return; - } } /* Do this test while we still hold the locks */ @@ -488,18 +477,15 @@ xfs_rename( * Remove the source. */ if (new_parent && src_is_directory) { - /* * Rewrite the ".." entry to point to the new * directory. */ - error = XFS_DIR_REPLACE(mp, tp, src_ip, "..", 2, - target_dp->i_ino, &first_block, - &free_list, spaceres); + error = xfs_dir_replace(tp, src_ip, "..", 2, target_dp->i_ino, + &first_block, &free_list, spaceres); ASSERT(error != EEXIST); - if (error) { + if (error) goto abort_return; - } xfs_ichgtime(src_ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); } else { @@ -527,16 +513,14 @@ xfs_rename( * entry that's moved no longer points to it. */ error = xfs_droplink(tp, src_dp); - if (error) { + if (error) goto abort_return; - } } - error = XFS_DIR_REMOVENAME(mp, tp, src_dp, src_name, src_namelen, + error = xfs_dir_removename(tp, src_dp, src_name, src_namelen, src_ip->i_ino, &first_block, &free_list, spaceres); - if (error) { + if (error) goto abort_return; - } xfs_ichgtime(src_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); /* diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index af290cf37ac..0c1e42b037e 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -24,14 +24,12 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_dmapi.h" #include "xfs_mount.h" #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" diff --git a/fs/xfs/xfs_rw.c b/fs/xfs/xfs_rw.c index c55e28189ab..defb2febaaf 100644 --- a/fs/xfs/xfs_rw.c +++ b/fs/xfs/xfs_rw.c @@ -24,14 +24,12 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_dmapi.h" #include "xfs_mount.h" #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index 39f0b1ed322..ee2721e0de4 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -24,7 +24,6 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_dmapi.h" #include "xfs_mount.h" @@ -33,7 +32,6 @@ #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index 100d9a4b38e..cb65c3a603f 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h @@ -805,12 +805,9 @@ typedef struct xfs_trans { ((mp)->m_sb.sb_inodesize + \ (mp)->m_sb.sb_sectsize * 2 + \ (mp)->m_dirblksize + \ - (XFS_DIR_IS_V1(mp) ? 0 : \ - XFS_FSB_TO_B(mp, (XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1))) + \ + XFS_FSB_TO_B(mp, (XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1)) + \ XFS_ALLOCFREE_LOG_RES(mp, 1) + \ - (128 * (4 + \ - (XFS_DIR_IS_V1(mp) ? 0 : \ - XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1) + \ + (128 * (4 + (XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1) + \ XFS_ALLOCFREE_LOG_COUNT(mp, 1)))) #define XFS_ADDAFORK_LOG_RES(mp) ((mp)->m_reservations.tr_addafork) diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c index e1ca7b6fde4..558c87ff0c4 100644 --- a/fs/xfs/xfs_trans_ail.c +++ b/fs/xfs/xfs_trans_ail.c @@ -22,7 +22,6 @@ #include "xfs_inum.h" #include "xfs_trans.h" #include "xfs_sb.h" -#include "xfs_dir.h" #include "xfs_dmapi.h" #include "xfs_mount.h" #include "xfs_trans_priv.h" diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c index 8cedd1583bc..60b6b898022 100644 --- a/fs/xfs/xfs_trans_buf.c +++ b/fs/xfs/xfs_trans_buf.c @@ -24,14 +24,12 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_dmapi.h" #include "xfs_mount.h" #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" diff --git a/fs/xfs/xfs_trans_extfree.c b/fs/xfs/xfs_trans_extfree.c index 7d7d627f25d..b290270dd4a 100644 --- a/fs/xfs/xfs_trans_extfree.c +++ b/fs/xfs/xfs_trans_extfree.c @@ -22,7 +22,6 @@ #include "xfs_inum.h" #include "xfs_trans.h" #include "xfs_sb.h" -#include "xfs_dir.h" #include "xfs_dmapi.h" #include "xfs_mount.h" #include "xfs_trans_priv.h" diff --git a/fs/xfs/xfs_trans_inode.c b/fs/xfs/xfs_trans_inode.c index 7c5894d59f8..b8db1d5cde5 100644 --- a/fs/xfs/xfs_trans_inode.c +++ b/fs/xfs/xfs_trans_inode.c @@ -24,14 +24,12 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_dmapi.h" #include "xfs_mount.h" #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" diff --git a/fs/xfs/xfs_trans_space.h b/fs/xfs/xfs_trans_space.h index 7fe3792b18d..4ea2e5074bd 100644 --- a/fs/xfs/xfs_trans_space.h +++ b/fs/xfs/xfs_trans_space.h @@ -30,8 +30,7 @@ XFS_EXTENTADD_SPACE_RES(mp,w)) #define XFS_DAENTER_1B(mp,w) ((w) == XFS_DATA_FORK ? (mp)->m_dirblkfsbs : 1) #define XFS_DAENTER_DBS(mp,w) \ - (XFS_DA_NODE_MAXDEPTH + \ - ((XFS_DIR_IS_V2(mp) && (w) == XFS_DATA_FORK) ? 2 : 0)) + (XFS_DA_NODE_MAXDEPTH + (((w) == XFS_DATA_FORK) ? 2 : 0)) #define XFS_DAENTER_BLOCKS(mp,w) \ (XFS_DAENTER_1B(mp,w) * XFS_DAENTER_DBS(mp,w)) #define XFS_DAENTER_BMAP1B(mp,w) \ @@ -41,10 +40,7 @@ #define XFS_DAENTER_SPACE_RES(mp,w) \ (XFS_DAENTER_BLOCKS(mp,w) + XFS_DAENTER_BMAPS(mp,w)) #define XFS_DAREMOVE_SPACE_RES(mp,w) XFS_DAENTER_BMAPS(mp,w) -#define XFS_DIRENTER_MAX_SPLIT(mp,nl) \ - (((mp)->m_sb.sb_blocksize == 512 && \ - XFS_DIR_IS_V1(mp) && \ - (nl) >= XFS_DIR_LEAF_CAN_DOUBLE_SPLIT_LEN) ? 2 : 1) +#define XFS_DIRENTER_MAX_SPLIT(mp,nl) 1 #define XFS_DIRENTER_SPACE_RES(mp,nl) \ (XFS_DAENTER_SPACE_RES(mp, XFS_DATA_FORK) * \ XFS_DIRENTER_MAX_SPLIT(mp,nl)) @@ -57,8 +53,7 @@ * Space reservation values for various transactions. */ #define XFS_ADDAFORK_SPACE_RES(mp) \ - ((mp)->m_dirblkfsbs + \ - (XFS_DIR_IS_V1(mp) ? 0 : XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK))) + ((mp)->m_dirblkfsbs + XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK)) #define XFS_ATTRRM_SPACE_RES(mp) \ XFS_DAREMOVE_SPACE_RES(mp, XFS_ATTR_FORK) /* This macro is not used - see inline code in xfs_attr_set */ diff --git a/fs/xfs/xfs_utils.c b/fs/xfs/xfs_utils.c index 37fdc2dc00b..9014d7e4448 100644 --- a/fs/xfs/xfs_utils.c +++ b/fs/xfs/xfs_utils.c @@ -24,12 +24,10 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_dmapi.h" #include "xfs_mount.h" #include "xfs_bmap_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" @@ -82,8 +80,7 @@ xfs_dir_lookup_int( dp = XFS_BHVTOI(dir_bdp); - error = XFS_DIR_LOOKUP(dp->i_mount, NULL, dp, - VNAME(dentry), VNAMELEN(dentry), inum); + error = xfs_dir_lookup(NULL, dp, VNAME(dentry), VNAMELEN(dentry), inum); if (!error) { /* * Unlock the directory. We do this because we can't diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c index 918531b6478..6c96391f3f1 100644 --- a/fs/xfs/xfs_vfsops.c +++ b/fs/xfs/xfs_vfsops.c @@ -24,7 +24,6 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_dmapi.h" #include "xfs_mount.h" @@ -32,7 +31,6 @@ #include "xfs_bmap_btree.h" #include "xfs_ialloc_btree.h" #include "xfs_alloc_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" @@ -131,9 +129,6 @@ xfs_init(void) #ifdef XFS_BMBT_TRACE xfs_bmbt_trace_buf = ktrace_alloc(XFS_BMBT_TRACE_SIZE, KM_SLEEP); #endif -#ifdef XFS_DIR_TRACE - xfs_dir_trace_buf = ktrace_alloc(XFS_DIR_TRACE_SIZE, KM_SLEEP); -#endif #ifdef XFS_ATTR_TRACE xfs_attr_trace_buf = ktrace_alloc(XFS_ATTR_TRACE_SIZE, KM_SLEEP); #endif @@ -177,9 +172,6 @@ xfs_cleanup(void) #ifdef XFS_ATTR_TRACE ktrace_free(xfs_attr_trace_buf); #endif -#ifdef XFS_DIR_TRACE - ktrace_free(xfs_dir_trace_buf); -#endif #ifdef XFS_BMBT_TRACE ktrace_free(xfs_bmbt_trace_buf); #endif diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 26d96d1b25c..00a6b7dc24a 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -25,7 +25,6 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_dmapi.h" #include "xfs_mount.h" @@ -33,13 +32,11 @@ #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_inode_item.h" -#include "xfs_dir_leaf.h" #include "xfs_itable.h" #include "xfs_btree.h" #include "xfs_ialloc.h" @@ -1958,8 +1955,7 @@ xfs_create( if (error) goto error_return; - if (resblks == 0 && - (error = XFS_DIR_CANENTER(mp, tp, dp, name, namelen))) + if (resblks == 0 && (error = xfs_dir_canenter(tp, dp, name, namelen))) goto error_return; rdev = (vap->va_mask & XFS_AT_RDEV) ? vap->va_rdev : 0; error = xfs_dir_ialloc(&tp, dp, vap->va_mode, 1, @@ -1990,9 +1986,9 @@ xfs_create( xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL); dp_joined_to_trans = B_TRUE; - error = XFS_DIR_CREATENAME(mp, tp, dp, name, namelen, ip->i_ino, - &first_block, &free_list, - resblks ? resblks - XFS_IALLOC_SPACE_RES(mp) : 0); + error = xfs_dir_createname(tp, dp, name, namelen, ip->i_ino, + &first_block, &free_list, resblks ? + resblks - XFS_IALLOC_SPACE_RES(mp) : 0); if (error) { ASSERT(error != ENOSPC); goto abort_return; @@ -2468,8 +2464,8 @@ xfs_remove( * Entry must exist since we did a lookup in xfs_lock_dir_and_entry. */ XFS_BMAP_INIT(&free_list, &first_block); - error = XFS_DIR_REMOVENAME(mp, tp, dp, name, namelen, ip->i_ino, - &first_block, &free_list, 0); + error = xfs_dir_removename(tp, dp, name, namelen, ip->i_ino, + &first_block, &free_list, 0); if (error) { ASSERT(error != ENOENT); REMOVE_DEBUG_TRACE(__LINE__); @@ -2688,13 +2684,12 @@ xfs_link( } if (resblks == 0 && - (error = XFS_DIR_CANENTER(mp, tp, tdp, target_name, - target_namelen))) + (error = xfs_dir_canenter(tp, tdp, target_name, target_namelen))) goto error_return; XFS_BMAP_INIT(&free_list, &first_block); - error = XFS_DIR_CREATENAME(mp, tp, tdp, target_name, target_namelen, + error = xfs_dir_createname(tp, tdp, target_name, target_namelen, sip->i_ino, &first_block, &free_list, resblks); if (error) @@ -2860,7 +2855,7 @@ xfs_mkdir( goto error_return; if (resblks == 0 && - (error = XFS_DIR_CANENTER(mp, tp, dp, dir_name, dir_namelen))) + (error = xfs_dir_canenter(tp, dp, dir_name, dir_namelen))) goto error_return; /* * create the directory inode. @@ -2887,9 +2882,9 @@ xfs_mkdir( XFS_BMAP_INIT(&free_list, &first_block); - error = XFS_DIR_CREATENAME(mp, tp, dp, dir_name, dir_namelen, - cdp->i_ino, &first_block, &free_list, - resblks ? resblks - XFS_IALLOC_SPACE_RES(mp) : 0); + error = xfs_dir_createname(tp, dp, dir_name, dir_namelen, cdp->i_ino, + &first_block, &free_list, resblks ? + resblks - XFS_IALLOC_SPACE_RES(mp) : 0); if (error) { ASSERT(error != ENOSPC); goto error1; @@ -2903,16 +2898,14 @@ xfs_mkdir( */ dp->i_gen++; - error = XFS_DIR_INIT(mp, tp, cdp, dp); - if (error) { + error = xfs_dir_init(tp, cdp, dp); + if (error) goto error2; - } cdp->i_gen = 1; error = xfs_bumplink(tp, dp); - if (error) { + if (error) goto error2; - } cvp = XFS_ITOV(cdp); @@ -3121,16 +3114,15 @@ xfs_rmdir( error = XFS_ERROR(ENOTEMPTY); goto error_return; } - if (!XFS_DIR_ISEMPTY(mp, cdp)) { + if (!xfs_dir_isempty(cdp)) { error = XFS_ERROR(ENOTEMPTY); goto error_return; } - error = XFS_DIR_REMOVENAME(mp, tp, dp, name, namelen, cdp->i_ino, - &first_block, &free_list, resblks); - if (error) { + error = xfs_dir_removename(tp, dp, name, namelen, cdp->i_ino, + &first_block, &free_list, resblks); + if (error) goto error1; - } xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); @@ -3229,8 +3221,6 @@ xfs_rmdir( /* - * xfs_readdir - * * Read dp's entries starting at uiop->uio_offset and translate them into * bufsize bytes worth of struct dirents starting at bufbase. */ @@ -3250,21 +3240,16 @@ xfs_readdir( (inst_t *)__return_address); dp = XFS_BHVTOI(dir_bdp); - if (XFS_FORCED_SHUTDOWN(dp->i_mount)) { + if (XFS_FORCED_SHUTDOWN(dp->i_mount)) return XFS_ERROR(EIO); - } lock_mode = xfs_ilock_map_shared(dp); - error = XFS_DIR_GETDENTS(dp->i_mount, tp, dp, uiop, eofp); + error = xfs_dir_getdents(tp, dp, uiop, eofp); xfs_iunlock_map_shared(dp, lock_mode); return error; } -/* - * xfs_symlink - * - */ STATIC int xfs_symlink( bhv_desc_t *dir_bdp, @@ -3328,7 +3313,7 @@ xfs_symlink( int len, total; char *path; - for(total = 0, path = target_path; total < pathlen;) { + for (total = 0, path = target_path; total < pathlen;) { /* * Skip any slashes. */ @@ -3422,7 +3407,7 @@ xfs_symlink( * Check for ability to enter directory entry, if no space reserved. */ if (resblks == 0 && - (error = XFS_DIR_CANENTER(mp, tp, dp, link_name, link_namelen))) + (error = xfs_dir_canenter(tp, dp, link_name, link_namelen))) goto error_return; /* * Initialize the bmap freelist prior to calling either @@ -3509,11 +3494,10 @@ xfs_symlink( /* * Create the directory entry for the symlink. */ - error = XFS_DIR_CREATENAME(mp, tp, dp, link_name, link_namelen, - ip->i_ino, &first_block, &free_list, resblks); - if (error) { + error = xfs_dir_createname(tp, dp, link_name, link_namelen, ip->i_ino, + &first_block, &free_list, resblks); + if (error) goto error1; - } xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE); -- cgit v1.2.3 From d7b849da47a59d2be6d6aea1effb0efa91c30424 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Tue, 20 Jun 2006 14:01:29 +1000 Subject: [XFS] Fix a Makefile issue related to exports.o handling. Signed-off-by: Nathan Scott --- fs/xfs/Makefile-linux-2.6 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/xfs/Makefile-linux-2.6 b/fs/xfs/Makefile-linux-2.6 index 5d73eaa1971..6f3a5558493 100644 --- a/fs/xfs/Makefile-linux-2.6 +++ b/fs/xfs/Makefile-linux-2.6 @@ -59,7 +59,6 @@ xfs-$(CONFIG_XFS_POSIX_ACL) += xfs_acl.o xfs-$(CONFIG_PROC_FS) += $(XFS_LINUX)/xfs_stats.o xfs-$(CONFIG_SYSCTL) += $(XFS_LINUX)/xfs_sysctl.o xfs-$(CONFIG_COMPAT) += $(XFS_LINUX)/xfs_ioctl32.o -xfs-$(CONFIG_XFS_EXPORT) += $(XFS_LINUX)/xfs_export.o xfs-y += xfs_alloc.o \ @@ -117,6 +116,7 @@ xfs-y += $(addprefix $(XFS_LINUX)/, \ kmem.o \ xfs_aops.o \ xfs_buf.o \ + xfs_export.o \ xfs_file.o \ xfs_fs_subr.o \ xfs_globals.o \ -- cgit v1.2.3 From d8ce75324135ea7100124c1fff4ec5090a350607 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Tue, 20 Jun 2006 14:53:51 +1000 Subject: [XFS] Remove files from the build that are now unused. Signed-off-by: Nathan Scott --- fs/xfs/Makefile-linux-2.6 | 2 -- fs/xfs/xfs_dir.c | 0 fs/xfs/xfs_dir.h | 0 fs/xfs/xfs_dir_leaf.c | 0 fs/xfs/xfs_dir_leaf.h | 0 fs/xfs/xfs_dir_sf.h | 0 6 files changed, 2 deletions(-) delete mode 100644 fs/xfs/xfs_dir.c delete mode 100644 fs/xfs/xfs_dir.h delete mode 100644 fs/xfs/xfs_dir_leaf.c delete mode 100644 fs/xfs/xfs_dir_leaf.h delete mode 100644 fs/xfs/xfs_dir_sf.h diff --git a/fs/xfs/Makefile-linux-2.6 b/fs/xfs/Makefile-linux-2.6 index 6f3a5558493..9e7f85986d0 100644 --- a/fs/xfs/Makefile-linux-2.6 +++ b/fs/xfs/Makefile-linux-2.6 @@ -72,14 +72,12 @@ xfs-y += xfs_alloc.o \ xfs_btree.o \ xfs_buf_item.o \ xfs_da_btree.o \ - xfs_dir.o \ xfs_dir2.o \ xfs_dir2_block.o \ xfs_dir2_data.o \ xfs_dir2_leaf.o \ xfs_dir2_node.o \ xfs_dir2_sf.o \ - xfs_dir_leaf.o \ xfs_error.o \ xfs_extfree_item.o \ xfs_fsops.o \ diff --git a/fs/xfs/xfs_dir.c b/fs/xfs/xfs_dir.c deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/fs/xfs/xfs_dir.h b/fs/xfs/xfs_dir.h deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/fs/xfs/xfs_dir_leaf.c b/fs/xfs/xfs_dir_leaf.c deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/fs/xfs/xfs_dir_leaf.h b/fs/xfs/xfs_dir_leaf.h deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/fs/xfs/xfs_dir_sf.h b/fs/xfs/xfs_dir_sf.h deleted file mode 100644 index e69de29bb2d..00000000000 -- cgit v1.2.3 From e7bdd7a531320eb4a4a8160afbe0c7cc98ac7187 Mon Sep 17 00:00:00 2001 From: "Langsdorf, Mark" Date: Thu, 8 Jun 2006 10:30:17 -0500 Subject: [CPUFREQ] Clarify powernow-k8 cpu_family statements This patch clarifies the meaning of the cpu_family if statements in the hw pstate driver patch for powernow-k8 Signed-off-by: Mark Langsdorf Signed-off-by: Dave Jones --- arch/i386/kernel/cpu/cpufreq/powernow-k8.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c index b4277f58f40..d8be4b01488 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c @@ -120,7 +120,7 @@ static int pending_bit_stuck(void) { u32 lo, hi; - if (cpu_family) + if (cpu_family == CPU_HW_PSTATE) return 0; rdmsr(MSR_FIDVID_STATUS, lo, hi); @@ -136,7 +136,7 @@ static int query_current_values_with_pending_wait(struct powernow_k8_data *data) u32 lo, hi; u32 i = 0; - if (cpu_family) { + if (cpu_family == CPU_HW_PSTATE) { rdmsr(MSR_PSTATE_STATUS, lo, hi); i = lo & HW_PSTATE_MASK; rdmsr(MSR_PSTATE_DEF_BASE + i, lo, hi); @@ -598,7 +598,7 @@ static void print_basics(struct powernow_k8_data *data) int j; for (j = 0; j < data->numps; j++) { if (data->powernow_table[j].frequency != CPUFREQ_ENTRY_INVALID) { - if (cpu_family) { + if (cpu_family == CPU_HW_PSTATE) { printk(KERN_INFO PFX " %d : fid 0x%x gid 0x%x (%d MHz)\n", j, (data->powernow_table[j].index & 0xff00) >> 8, (data->powernow_table[j].index & 0xff0000) >> 16, data->powernow_table[j].frequency/1000); @@ -758,7 +758,7 @@ static int find_psb_table(struct powernow_k8_data *data) #ifdef CONFIG_X86_POWERNOW_K8_ACPI static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index) { - if (!data->acpi_data.state_count || cpu_family) + if (!data->acpi_data.state_count || (cpu_family == CPU_HW_PSTATE)) return; data->irt = (data->acpi_data.states[index].control >> IRT_SHIFT) & IRT_MASK; @@ -801,7 +801,7 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data) goto err_out; } - if (cpu_family) + if (cpu_family == CPU_HW_PSTATE) ret_val = fill_powernow_table_pstate(data, powernow_table); else ret_val = fill_powernow_table_fidvid(data, powernow_table); @@ -1082,7 +1082,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi if (query_current_values_with_pending_wait(data)) goto err_out; - if (cpu_family) + if (cpu_family == CPU_HW_PSTATE) dprintk("targ: curr fid 0x%x, did 0x%x\n", data->currfid, data->currvid); else { @@ -1103,7 +1103,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi powernow_k8_acpi_pst_values(data, newstate); - if (cpu_family) + if (cpu_family == CPU_HW_PSTATE) ret = transition_frequency_pstate(data, newstate); else ret = transition_frequency_fidvid(data, newstate); @@ -1115,7 +1115,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi } mutex_unlock(&fidvid_mutex); - if (cpu_family) + if (cpu_family == CPU_HW_PSTATE) pol->cur = find_khz_freq_from_fiddid(data->currfid, data->currdid); else pol->cur = find_khz_freq_from_fid(data->currfid); @@ -1197,14 +1197,14 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol) if (query_current_values_with_pending_wait(data)) goto err_out; - if (!cpu_family) + if (cpu_family == CPU_OPTERON) fidvid_msr_init(); /* run on any CPU again */ set_cpus_allowed(current, oldmask); pol->governor = CPUFREQ_DEFAULT_GOVERNOR; - if (cpu_family) + if (cpu_family == CPU_HW_PSTATE) pol->cpus = cpumask_of_cpu(pol->cpu); else pol->cpus = cpu_core_map[pol->cpu]; @@ -1215,7 +1215,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol) pol->cpuinfo.transition_latency = (((data->rvo + 8) * data->vstable * VST_UNITS_20US) + (3 * (1 << data->irt) * 10)) * 1000; - if (cpu_family) + if (cpu_family == CPU_HW_PSTATE) pol->cur = find_khz_freq_from_fiddid(data->currfid, data->currdid); else pol->cur = find_khz_freq_from_fid(data->currfid); @@ -1232,7 +1232,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol) cpufreq_frequency_table_get_attr(data->powernow_table, pol->cpu); - if (cpu_family) + if (cpu_family == CPU_HW_PSTATE) dprintk("cpu_init done, current fid 0x%x, did 0x%x\n", data->currfid, data->currdid); else -- cgit v1.2.3 From 6cad647da228486f36a9794137ad459e39b02590 Mon Sep 17 00:00:00 2001 From: "Langsdorf, Mark" Date: Thu, 8 Jun 2006 10:33:19 -0500 Subject: [CPUFREQ] correct powernow-k8 fid/vid masks for extended parts The fid/vid masks for parts using the extended parts are slightly incorrect and can result in incorrect fid/vid codes being applied. No instances of this problem have been reported in the field but it could be a problem with future parts. Signed-off-by: Mark Langsdorf Signed-off-by: Dave Jones --- arch/i386/kernel/cpu/cpufreq/powernow-k8.c | 4 ++-- arch/i386/kernel/cpu/cpufreq/powernow-k8.h | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c index d8be4b01488..756d0a333ed 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c @@ -885,8 +885,8 @@ static int fill_powernow_table_fidvid(struct powernow_k8_data *data, struct cpuf u32 vid; if (data->exttype) { - fid = data->acpi_data.states[i].status & FID_MASK; - vid = (data->acpi_data.states[i].status >> VID_SHIFT) & VID_MASK; + fid = data->acpi_data.states[i].status & EXT_FID_MASK; + vid = (data->acpi_data.states[i].status >> VID_SHIFT) & EXT_VID_MASK; } else { fid = data->acpi_data.states[i].control & FID_MASK; vid = (data->acpi_data.states[i].control >> VID_SHIFT) & VID_MASK; diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h index bf8ad9e43da..0fb2a3001ba 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h @@ -169,7 +169,9 @@ struct powernow_k8_data { #define MVS_MASK 3 #define VST_MASK 0x7f #define VID_MASK 0x1f -#define FID_MASK 0x3f +#define FID_MASK 0x1f +#define EXT_VID_MASK 0x3f +#define EXT_FID_MASK 0x3f /* -- cgit v1.2.3 From d3dcd4efe2ad1ad1865b2fe5c863c1ebd9482a84 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Mon, 19 Jun 2006 23:39:45 -0700 Subject: [NETFILTER]: xt_sctp: fix endless loop caused by 0 chunk length Fix endless loop in the SCTP match similar to those already fixed in the SCTP conntrack helper (was CVE-2006-1527). Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/netfilter/xt_sctp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/netfilter/xt_sctp.c b/net/netfilter/xt_sctp.c index b5110e5b54b..9316c753692 100644 --- a/net/netfilter/xt_sctp.c +++ b/net/netfilter/xt_sctp.c @@ -62,7 +62,7 @@ match_packet(const struct sk_buff *skb, do { sch = skb_header_pointer(skb, offset, sizeof(_sch), &_sch); - if (sch == NULL) { + if (sch == NULL || sch->length == 0) { duprintf("Dropping invalid SCTP packet.\n"); *hotdrop = 1; return 0; -- cgit v1.2.3 From d6cc7f1a3b33c89c91b3dfce1ff053178893470e Mon Sep 17 00:00:00 2001 From: Evgeniy Polyakov Date: Mon, 19 Jun 2006 23:42:53 -0700 Subject: [CONNECTOR]: Initialize subsystem earlier. Attached patch declares connector init function as subsys_init() and returns -EAGAIN in case connector is not initialized yet. Signed-off-by: Evgeniy Polyakov Signed-off-by: David S. Miller --- drivers/connector/connector.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c index 35897079a78..79d581c8652 100644 --- a/drivers/connector/connector.c +++ b/drivers/connector/connector.c @@ -308,6 +308,9 @@ int cn_add_callback(struct cb_id *id, char *name, void (*callback)(void *)) int err; struct cn_dev *dev = &cdev; + if (!cn_already_initialized) + return -EAGAIN; + err = cn_queue_add_callback(dev->cbdev, name, id, callback); if (err) return err; @@ -435,7 +438,7 @@ static void cn_callback(void *data) mutex_unlock(¬ify_lock); } -static int __init cn_init(void) +static int __devinit cn_init(void) { struct cn_dev *dev = &cdev; int err; @@ -456,21 +459,22 @@ static int __init cn_init(void) sock_release(dev->nls->sk_socket); return -EINVAL; } + + cn_already_initialized = 1; err = cn_add_callback(&dev->id, "connector", &cn_callback); if (err) { + cn_already_initialized = 0; cn_queue_free_dev(dev->cbdev); if (dev->nls->sk_socket) sock_release(dev->nls->sk_socket); return -EINVAL; } - cn_already_initialized = 1; - return 0; } -static void __exit cn_fini(void) +static void __devexit cn_fini(void) { struct cn_dev *dev = &cdev; @@ -482,7 +486,7 @@ static void __exit cn_fini(void) sock_release(dev->nls->sk_socket); } -module_init(cn_init); +subsys_initcall(cn_init); module_exit(cn_fini); EXPORT_SYMBOL_GPL(cn_add_callback); -- cgit v1.2.3 From 48d83325b61043e3bbd24dd37b9fe433744cf330 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 19 Jun 2006 23:57:59 -0700 Subject: [NET]: Prevent multiple qdisc runs Having two or more qdisc_run's contend against each other is bad because it can induce packet reordering if the packets have to be requeued. It appears that this is an unintended consequence of relinquinshing the queue lock while transmitting. That in turn is needed for devices that spend a lot of time in their transmit routine. There are no advantages to be had as devices with queues are inherently single-threaded (the loopback device is not but then it doesn't have a queue). Even if you were to add a queue to a parallel virtual device (e.g., bolt a tbf filter in front of an ipip tunnel device), you would still want to process the queue in sequence to ensure that the packets are ordered correctly. The solution here is to steal a bit from net_device to prevent this. BTW, as qdisc_restart is no longer used by anyone as a module inside the kernel (IIRC it used to with netif_wake_queue), I have not exported the new __qdisc_run function. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- include/linux/netdevice.h | 1 + include/net/pkt_sched.h | 7 ++++--- net/sched/sch_generic.c | 11 +++++++++-- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index e432b743dda..39919c882a2 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -233,6 +233,7 @@ enum netdev_state_t __LINK_STATE_RX_SCHED, __LINK_STATE_LINKWATCH_PENDING, __LINK_STATE_DORMANT, + __LINK_STATE_QDISC_RUNNING, }; diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h index b94d1ad92c4..75b5b9333fc 100644 --- a/include/net/pkt_sched.h +++ b/include/net/pkt_sched.h @@ -218,12 +218,13 @@ extern struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r, struct rtattr *tab); extern void qdisc_put_rtab(struct qdisc_rate_table *tab); -extern int qdisc_restart(struct net_device *dev); +extern void __qdisc_run(struct net_device *dev); static inline void qdisc_run(struct net_device *dev) { - while (!netif_queue_stopped(dev) && qdisc_restart(dev) < 0) - /* NOTHING */; + if (!netif_queue_stopped(dev) && + !test_and_set_bit(__LINK_STATE_QDISC_RUNNING, &dev->state)) + __qdisc_run(dev); } extern int tc_classify(struct sk_buff *skb, struct tcf_proto *tp, diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index b1e4c5e20ac..d7aca8ef524 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -90,7 +90,7 @@ void qdisc_unlock_tree(struct net_device *dev) NOTE: Called under dev->queue_lock with locally disabled BH. */ -int qdisc_restart(struct net_device *dev) +static inline int qdisc_restart(struct net_device *dev) { struct Qdisc *q = dev->qdisc; struct sk_buff *skb; @@ -179,6 +179,14 @@ requeue: return q->q.qlen; } +void __qdisc_run(struct net_device *dev) +{ + while (qdisc_restart(dev) < 0 && !netif_queue_stopped(dev)) + /* NOTHING */; + + clear_bit(__LINK_STATE_QDISC_RUNNING, &dev->state); +} + static void dev_watchdog(unsigned long arg) { struct net_device *dev = (struct net_device *)arg; @@ -620,6 +628,5 @@ EXPORT_SYMBOL(qdisc_create_dflt); EXPORT_SYMBOL(qdisc_alloc); EXPORT_SYMBOL(qdisc_destroy); EXPORT_SYMBOL(qdisc_reset); -EXPORT_SYMBOL(qdisc_restart); EXPORT_SYMBOL(qdisc_lock_tree); EXPORT_SYMBOL(qdisc_unlock_tree); -- cgit v1.2.3 From 65fd28f743be6e3e3fd8eefa9a517656636fee42 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 20 Jun 2006 00:07:52 -0700 Subject: [SCTP]: Fix unintentional change to SCTP_ASSERT when !SCTP_DEBUG A local debugging change slipped into a previous changeset. When SCTP_DEBUG is off SCTP_ASSERT should do nothing. Signed-off-by: David S. Miller --- include/net/sctp/sctp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index b2b40f951ae..aa6033ca7cd 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -255,7 +255,7 @@ extern int sctp_debug_flag; #define SCTP_DEBUG_PRINTK_IPADDR(whatever...) #define SCTP_ENABLE_DEBUG #define SCTP_DISABLE_DEBUG -#define SCTP_ASSERT(expr, str, func) BUG_ON(!(expr)) +#define SCTP_ASSERT(expr, str, func) #endif /* SCTP_DEBUG */ -- cgit v1.2.3 From a8cbdcea341ac2f404ee81aa1c19d54aaa0416b4 Mon Sep 17 00:00:00 2001 From: Bob Breuer Date: Tue, 20 Jun 2006 00:28:33 -0700 Subject: [SPARC]: Add topology_init() Fix a crash in SMP mode by adding the missing topology_init. Also makes /proc/cpuinfo backwards compatible with 2.4. Signed-off-by: Bob Breuer Signed-off-by: David S. Miller --- arch/sparc/kernel/setup.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c index 3509e430553..8531a8e1583 100644 --- a/arch/sparc/kernel/setup.c +++ b/arch/sparc/kernel/setup.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -389,6 +390,8 @@ console_initcall(set_preferred_console); extern char *sparc_cpu_type; extern char *sparc_fpu_type; +static int ncpus_probed; + static int show_cpuinfo(struct seq_file *m, void *__unused) { seq_printf(m, @@ -411,7 +414,7 @@ static int show_cpuinfo(struct seq_file *m, void *__unused) romvec->pv_printrev >> 16, romvec->pv_printrev & 0xffff, &cputypval, - num_possible_cpus(), + ncpus_probed, num_online_cpus() #ifndef CONFIG_SMP , cpu_data(0).udelay_val/(500000/HZ), @@ -471,3 +474,30 @@ void sun_do_break(void) int serial_console = -1; int stop_a_enabled = 1; + +static int __init topology_init(void) +{ + int i, ncpus, err; + + /* Count the number of physically present processors in + * the machine, even on uniprocessor, so that /proc/cpuinfo + * output is consistent with 2.4.x + */ + ncpus = 0; + while (!cpu_find_by_instance(ncpus, NULL, NULL)) + ncpus++; + ncpus_probed = ncpus; + + err = 0; + for_each_online_cpu(i) { + struct cpu *p = kzalloc(sizeof(*p), GFP_KERNEL); + if (!p) + err = -ENOMEM; + else + register_cpu(p, i, NULL); + } + + return err; +} + +subsys_initcall(topology_init); -- cgit v1.2.3 From 7202fb496af235506a3c6fea836fe4c9957f730e Mon Sep 17 00:00:00 2001 From: Bob Breuer Date: Tue, 20 Jun 2006 00:30:31 -0700 Subject: [SPARC]: Setup cpu_possible_map Setup cpu_possible_map so the secondary cpus will get started. Signed-off-by: Bob Breuer Signed-off-by: David S. Miller --- arch/sparc/kernel/setup.c | 2 ++ arch/sparc/kernel/smp.c | 30 ++++++++++++++++++++++-------- include/asm-sparc/smp.h | 8 +++++++- 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c index 8531a8e1583..2cbf282f0d0 100644 --- a/arch/sparc/kernel/setup.c +++ b/arch/sparc/kernel/setup.c @@ -349,6 +349,8 @@ void __init setup_arch(char **cmdline_p) init_mm.context = (unsigned long) NO_CONTEXT; init_task.thread.kregs = &fake_swapper_regs; + smp_setup_cpu_possible_map(); + paging_init(); } diff --git a/arch/sparc/kernel/smp.c b/arch/sparc/kernel/smp.c index 40b42c88e6a..d0ccb8ad1d5 100644 --- a/arch/sparc/kernel/smp.c +++ b/arch/sparc/kernel/smp.c @@ -267,22 +267,18 @@ int setup_profiling_timer(unsigned int multiplier) void __init smp_prepare_cpus(unsigned int max_cpus) { extern void smp4m_boot_cpus(void); - int i, cpuid, ncpus, extra; + int i, cpuid, extra; BUG_ON(sparc_cpu_model != sun4m); printk("Entering SMP Mode...\n"); - ncpus = 1; extra = 0; for (i = 0; !cpu_find_by_instance(i, NULL, &cpuid); i++) { - if (cpuid == boot_cpu_id) - continue; - if (cpuid < NR_CPUS && ncpus++ < max_cpus) - cpu_set(cpuid, phys_cpu_present_map); - else + if (cpuid >= NR_CPUS) extra++; } - if (max_cpus >= NR_CPUS && extra) + /* i = number of cpus */ + if (extra && max_cpus > i - extra) printk("Warning: NR_CPUS is too low to start all cpus\n"); smp_store_cpu_info(boot_cpu_id); @@ -290,6 +286,24 @@ void __init smp_prepare_cpus(unsigned int max_cpus) smp4m_boot_cpus(); } +/* Set this up early so that things like the scheduler can init + * properly. We use the same cpu mask for both the present and + * possible cpu map. + */ +void __init smp_setup_cpu_possible_map(void) +{ + int instance, mid; + + instance = 0; + while (!cpu_find_by_instance(instance, NULL, &mid)) { + if (mid < NR_CPUS) { + cpu_set(mid, phys_cpu_present_map); + cpu_set(mid, cpu_present_map); + } + instance++; + } +} + void __devinit smp_prepare_boot_cpu(void) { int cpuid = hard_smp_processor_id(); diff --git a/include/asm-sparc/smp.h b/include/asm-sparc/smp.h index 98c46e3fbe8..c1a289327a7 100644 --- a/include/asm-sparc/smp.h +++ b/include/asm-sparc/smp.h @@ -146,6 +146,8 @@ static inline int hard_smp_processor_id(void) #define prof_multiplier(__cpu) cpu_data(__cpu).multiplier #define prof_counter(__cpu) cpu_data(__cpu).counter +void smp_setup_cpu_possible_map(void); + #endif /* !(__ASSEMBLY__) */ /* Sparc specific messages. */ @@ -162,7 +164,11 @@ static inline int hard_smp_processor_id(void) #define MBOX_IDLECPU2 0xFD #define MBOX_STOPCPU2 0xFE -#endif /* SMP */ +#else /* SMP */ + +#define smp_setup_cpu_possible_map() do { } while (0) + +#endif /* !(SMP) */ #define NO_PROC_ID 0xFF -- cgit v1.2.3 From 61fc12d8e5c94176e7c2e04a2eab4c6e36d8dd41 Mon Sep 17 00:00:00 2001 From: Bob Breuer Date: Tue, 20 Jun 2006 00:35:13 -0700 Subject: [SPARC]: Add missing rw can_lock macros Fix a link failure by adding the missing can_lock macros for the rw locks. Signed-off-by: Bob Breuer Signed-off-by: David S. Miller --- include/asm-sparc/spinlock.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/asm-sparc/spinlock.h b/include/asm-sparc/spinlock.h index 3350c90c786..1c75474ba1d 100644 --- a/include/asm-sparc/spinlock.h +++ b/include/asm-sparc/spinlock.h @@ -154,6 +154,9 @@ static inline int __raw_write_trylock(raw_rwlock_t *rw) #define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock) #define __raw_read_trylock(lock) generic__raw_read_trylock(lock) +#define __raw_read_can_lock(rw) (!((rw)->lock & 0xff)) +#define __raw_write_can_lock(rw) (!(rw)->lock) + #endif /* !(__ASSEMBLY__) */ #endif /* __SPARC_SPINLOCK_H */ -- cgit v1.2.3 From 92d452f0eb10774fb7779abf876baf9dfb295e6f Mon Sep 17 00:00:00 2001 From: Bob Breuer Date: Tue, 20 Jun 2006 00:36:10 -0700 Subject: [SPARC]: Mark smp init functions as cpuinit Fix the smp related section mismatch warnings by marking the smp init functions as cpuinit. Signed-off-by: Bob Breuer Signed-off-by: David S. Miller --- arch/sparc/kernel/smp.c | 6 +++--- arch/sparc/kernel/sun4m_smp.c | 9 ++------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/arch/sparc/kernel/smp.c b/arch/sparc/kernel/smp.c index d0ccb8ad1d5..6135d4faeee 100644 --- a/arch/sparc/kernel/smp.c +++ b/arch/sparc/kernel/smp.c @@ -58,7 +58,7 @@ cpumask_t smp_commenced_mask = CPU_MASK_NONE; /* Used to make bitops atomic */ unsigned char bitops_spinlock = 0; -void __init smp_store_cpu_info(int id) +void __cpuinit smp_store_cpu_info(int id) { int cpu_node; @@ -304,7 +304,7 @@ void __init smp_setup_cpu_possible_map(void) } } -void __devinit smp_prepare_boot_cpu(void) +void __init smp_prepare_boot_cpu(void) { int cpuid = hard_smp_processor_id(); @@ -320,7 +320,7 @@ void __devinit smp_prepare_boot_cpu(void) cpu_set(cpuid, phys_cpu_present_map); } -int __devinit __cpu_up(unsigned int cpu) +int __cpuinit __cpu_up(unsigned int cpu) { extern int smp4m_boot_one_cpu(int); int ret; diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c index 70b375a4c2c..3b32096134a 100644 --- a/arch/sparc/kernel/sun4m_smp.c +++ b/arch/sparc/kernel/sun4m_smp.c @@ -66,7 +66,7 @@ static inline unsigned long swap(volatile unsigned long *ptr, unsigned long val) static void smp_setup_percpu_timer(void); extern void cpu_probe(void); -void __init smp4m_callin(void) +void __cpuinit smp4m_callin(void) { int cpuid = hard_smp_processor_id(); @@ -112,13 +112,8 @@ void __init smp4m_callin(void) local_irq_enable(); cpu_set(cpuid, cpu_online_map); - /* last one in gets all the interrupts (for testing) */ - set_irq_udt(boot_cpu_id); } -extern void init_IRQ(void); -extern void cpu_panic(void); - /* * Cycle through the processors asking the PROM to start each one. */ @@ -134,7 +129,7 @@ void __init smp4m_boot_cpus(void) local_flush_cache_all(); } -int smp4m_boot_one_cpu(int i) +int __cpuinit smp4m_boot_one_cpu(int i) { extern unsigned long sun4m_cpu_startup; unsigned long *entry = &sun4m_cpu_startup; -- cgit v1.2.3 From 3185d4d2873a46ca1620d784013f285522091aa0 Mon Sep 17 00:00:00 2001 From: Bob Breuer Date: Tue, 20 Jun 2006 00:36:56 -0700 Subject: [SPARC]: Fix iommu_flush_iotlb end address Fix the calculation of the end address when flushing iotlb entries to ram. This bug has been a cause of esp dma errors, and it affects HyperSPARC systems much worse than SuperSPARC systems. Signed-off-by: Bob Breuer Signed-off-by: David S. Miller --- arch/sparc/mm/iommu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/sparc/mm/iommu.c b/arch/sparc/mm/iommu.c index 77840c80478..7215849db39 100644 --- a/arch/sparc/mm/iommu.c +++ b/arch/sparc/mm/iommu.c @@ -144,8 +144,9 @@ static void iommu_flush_iotlb(iopte_t *iopte, unsigned int niopte) unsigned long start; unsigned long end; - start = (unsigned long)iopte & PAGE_MASK; + start = (unsigned long)iopte; end = PAGE_ALIGN(start + niopte*sizeof(iopte_t)); + start &= PAGE_MASK; if (viking_mxcc_present) { while(start < end) { viking_mxcc_flush_page(start); -- cgit v1.2.3 From fd0504c3217d6d1bc8f33f53fb536299cae8feda Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 20 Jun 2006 01:20:00 -0700 Subject: [SPARC64]: Send all device interrupts via one PIL. This is the first in a series of cleanups that will hopefully allow a seamless attempt at using the generic IRQ handling infrastructure in the Linux kernel. Define PIL_DEVICE_IRQ and vector all device interrupts through there. Get rid of the ugly pil0_dummy_{bucket,desc}, instead vector the timer interrupt directly to a specific handler since the timer interrupt is the only event that will be signaled on PIL 14. The irq_worklist is now in the per-cpu trap_block[]. Signed-off-by: David S. Miller --- arch/sparc64/kernel/entry.S | 11 +-- arch/sparc64/kernel/irq.c | 163 +++++++++++++++++---------------------- arch/sparc64/kernel/sun4v_ivec.S | 13 +--- arch/sparc64/kernel/time.c | 16 +--- arch/sparc64/kernel/traps.c | 4 +- arch/sparc64/kernel/ttable.S | 10 +-- include/asm-sparc64/cpudata.h | 19 ++--- include/asm-sparc64/pil.h | 7 +- 8 files changed, 101 insertions(+), 142 deletions(-) diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S index 6d0b3ed77a0..c87365e59e7 100644 --- a/arch/sparc64/kernel/entry.S +++ b/arch/sparc64/kernel/entry.S @@ -22,6 +22,7 @@ #include #include #include +#include #define curptr g6 @@ -434,17 +435,13 @@ do_ivec: sllx %g3, 5, %g3 or %g2, %lo(ivector_table), %g2 add %g2, %g3, %g3 - ldub [%g3 + 0x04], %g4 /* pil */ - mov 1, %g2 - sllx %g2, %g4, %g2 - sllx %g4, 2, %g4 TRAP_LOAD_IRQ_WORK(%g6, %g1) - lduw [%g6 + %g4], %g5 /* g5 = irq_work(cpu, pil) */ + lduw [%g6], %g5 /* g5 = irq_work(cpu) */ stw %g5, [%g3 + 0x00] /* bucket->irq_chain = g5 */ - stw %g3, [%g6 + %g4] /* irq_work(cpu, pil) = bucket */ - wr %g2, 0x0, %set_softint + stw %g3, [%g6] /* irq_work(cpu) = bucket */ + wr %g0, 1 << PIL_DEVICE_IRQ, %set_softint retry do_ivec_xcall: mov 0x50, %g1 diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index 11e645c9ec5..0fb1738a4f3 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c @@ -68,11 +68,7 @@ struct ino_bucket ivector_table[NUM_IVECS] __attribute__ ((aligned (SMP_CACHE_BY * access to this structure takes a TLB miss it could cause * the 5-level sparc v9 trap stack to overflow. */ -struct irq_work_struct { - unsigned int irq_worklists[16]; -}; -struct irq_work_struct __irq_work[NR_CPUS]; -#define irq_work(__cpu, __pil) &(__irq_work[(__cpu)].irq_worklists[(__pil)]) +#define irq_work(__cpu) &(trap_block[(__cpu)].irq_worklist) static struct irqaction *irq_action[NR_IRQS+1]; @@ -91,10 +87,8 @@ static void register_irq_proc (unsigned int irq); */ #define put_ino_in_irqaction(action, irq) \ action->flags &= 0xffffffffffffUL; \ - if (__bucket(irq) == &pil0_dummy_bucket) \ - action->flags |= 0xdeadUL << 48; \ - else \ - action->flags |= __irq_ino(irq) << 48; + action->flags |= __irq_ino(irq) << 48; + #define get_ino_in_irqaction(action) (action->flags >> 48) #define put_smpaff_in_irqaction(action, smpaff) (action)->mask = (smpaff) @@ -251,15 +245,6 @@ void disable_irq(unsigned int irq) } } -/* The timer is the one "weird" interrupt which is generated by - * the CPU %tick register and not by some normal vectored interrupt - * source. To handle this special case, we use this dummy INO bucket. - */ -static struct irq_desc pil0_dummy_desc; -static struct ino_bucket pil0_dummy_bucket = { - .irq_info = &pil0_dummy_desc, -}; - static void build_irq_error(const char *msg, unsigned int ino, int pil, int inofixup, unsigned long iclr, unsigned long imap, struct ino_bucket *bucket) @@ -276,15 +261,7 @@ unsigned int build_irq(int pil, int inofixup, unsigned long iclr, unsigned long struct ino_bucket *bucket; int ino; - if (pil == 0) { - if (iclr != 0UL || imap != 0UL) { - prom_printf("Invalid dummy bucket for PIL0 (%lx:%lx)\n", - iclr, imap); - prom_halt(); - } - return __irq(&pil0_dummy_bucket); - } - + BUG_ON(pil == 0); BUG_ON(tlb_type == hypervisor); /* RULE: Both must be specified in all other cases. */ @@ -371,7 +348,7 @@ static void atomic_bucket_insert(struct ino_bucket *bucket) __asm__ __volatile__("rdpr %%pstate, %0" : "=r" (pstate)); __asm__ __volatile__("wrpr %0, %1, %%pstate" : : "r" (pstate), "i" (PSTATE_IE)); - ent = irq_work(smp_processor_id(), bucket->pil); + ent = irq_work(smp_processor_id()); bucket->irq_chain = *ent; *ent = __irq(bucket); __asm__ __volatile__("wrpr %0, 0x0, %%pstate" : : "r" (pstate)); @@ -437,7 +414,7 @@ int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_ if (unlikely(!bucket->irq_info)) return -ENODEV; - if ((bucket != &pil0_dummy_bucket) && (irqflags & SA_SAMPLE_RANDOM)) { + if (irqflags & SA_SAMPLE_RANDOM) { /* * This function might sleep, we want to call it first, * outside of the atomic block. In SA_STATIC_ALLOC case, @@ -465,12 +442,9 @@ int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_ } bucket->flags |= IBF_ACTIVE; - pending = 0; - if (bucket != &pil0_dummy_bucket) { - pending = bucket->pending; - if (pending) - bucket->pending = 0; - } + pending = bucket->pending; + if (pending) + bucket->pending = 0; action->handler = handler; action->flags = irqflags; @@ -487,13 +461,12 @@ int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_ /* We ate the IVEC already, this makes sure it does not get lost. */ if (pending) { atomic_bucket_insert(bucket); - set_softint(1 << bucket->pil); + set_softint(1 << PIL_DEVICE_IRQ); } spin_unlock_irqrestore(&irq_action_lock, flags); - if (bucket != &pil0_dummy_bucket) - register_irq_proc(__irq_ino(irq)); + register_irq_proc(__irq_ino(irq)); #ifdef CONFIG_SMP distribute_irqs(); @@ -533,7 +506,9 @@ void free_irq(unsigned int irq, void *dev_id) { struct irqaction *action; struct ino_bucket *bucket; + struct irq_desc *desc; unsigned long flags; + int ent, i; spin_lock_irqsave(&irq_action_lock, flags); @@ -549,42 +524,39 @@ void free_irq(unsigned int irq, void *dev_id) spin_lock_irqsave(&irq_action_lock, flags); bucket = __bucket(irq); - if (bucket != &pil0_dummy_bucket) { - struct irq_desc *desc = bucket->irq_info; - int ent, i; + desc = bucket->irq_info; - for (i = 0; i < MAX_IRQ_DESC_ACTION; i++) { - struct irqaction *p = &desc->action[i]; + for (i = 0; i < MAX_IRQ_DESC_ACTION; i++) { + struct irqaction *p = &desc->action[i]; - if (p == action) { - desc->action_active_mask &= ~(1 << i); - break; - } + if (p == action) { + desc->action_active_mask &= ~(1 << i); + break; } + } - if (!desc->action_active_mask) { - unsigned long imap = bucket->imap; - - /* This unique interrupt source is now inactive. */ - bucket->flags &= ~IBF_ACTIVE; + if (!desc->action_active_mask) { + unsigned long imap = bucket->imap; - /* See if any other buckets share this bucket's IMAP - * and are still active. - */ - for (ent = 0; ent < NUM_IVECS; ent++) { - struct ino_bucket *bp = &ivector_table[ent]; - if (bp != bucket && - bp->imap == imap && - (bp->flags & IBF_ACTIVE) != 0) - break; - } + /* This unique interrupt source is now inactive. */ + bucket->flags &= ~IBF_ACTIVE; - /* Only disable when no other sub-irq levels of - * the same IMAP are active. - */ - if (ent == NUM_IVECS) - disable_irq(irq); + /* See if any other buckets share this bucket's IMAP + * and are still active. + */ + for (ent = 0; ent < NUM_IVECS; ent++) { + struct ino_bucket *bp = &ivector_table[ent]; + if (bp != bucket && + bp->imap == imap && + (bp->flags & IBF_ACTIVE) != 0) + break; } + + /* Only disable when no other sub-irq levels of + * the same IMAP are active. + */ + if (ent == NUM_IVECS) + disable_irq(irq); } spin_unlock_irqrestore(&irq_action_lock, flags); @@ -625,7 +597,7 @@ void synchronize_irq(unsigned int irq) } #endif /* CONFIG_SMP */ -static void process_bucket(int irq, struct ino_bucket *bp, struct pt_regs *regs) +static void process_bucket(struct ino_bucket *bp, struct pt_regs *regs) { struct irq_desc *desc = bp->irq_info; unsigned char flags = bp->flags; @@ -676,51 +648,54 @@ static void process_bucket(int irq, struct ino_bucket *bp, struct pt_regs *regs) /* Test and add entropy */ if (random & SA_SAMPLE_RANDOM) - add_interrupt_randomness(irq); + add_interrupt_randomness(bp->pil); } out: bp->flags &= ~IBF_INPROGRESS; } +#ifndef CONFIG_SMP +extern irqreturn_t timer_interrupt(int, void *, struct pt_regs *); + +void timer_irq(int irq, struct pt_regs *regs) +{ + unsigned long clr_mask = 1 << irq; + unsigned long tick_mask = tick_ops->softint_mask; + + if (get_softint() & tick_mask) { + irq = 0; + clr_mask = tick_mask; + } + clear_softint(clr_mask); + + irq_enter(); + kstat_this_cpu.irqs[irq]++; + timer_interrupt(irq, NULL, regs); + irq_exit(); +} +#endif + void handler_irq(int irq, struct pt_regs *regs) { struct ino_bucket *bp; int cpu = smp_processor_id(); -#ifndef CONFIG_SMP - /* - * Check for TICK_INT on level 14 softint. + /* XXX at this point we should be able to assert that + * XXX irq is PIL_DEVICE_IRQ... */ - { - unsigned long clr_mask = 1 << irq; - unsigned long tick_mask = tick_ops->softint_mask; - - if ((irq == 14) && (get_softint() & tick_mask)) { - irq = 0; - clr_mask = tick_mask; - } - clear_softint(clr_mask); - } -#else clear_softint(1 << irq); -#endif irq_enter(); - kstat_this_cpu.irqs[irq]++; /* Sliiiick... */ -#ifndef CONFIG_SMP - bp = ((irq != 0) ? - __bucket(xchg32(irq_work(cpu, irq), 0)) : - &pil0_dummy_bucket); -#else - bp = __bucket(xchg32(irq_work(cpu, irq), 0)); -#endif + bp = __bucket(xchg32(irq_work(cpu), 0)); while (bp) { struct ino_bucket *nbp = __bucket(bp->irq_chain); + kstat_this_cpu.irqs[bp->pil]++; + bp->irq_chain = 0; - process_bucket(irq, bp, regs); + process_bucket(bp, regs); bp = nbp; } irq_exit(); @@ -929,7 +904,7 @@ void init_irqwork_curcpu(void) { int cpu = hard_smp_processor_id(); - memset(__irq_work + cpu, 0, sizeof(struct irq_work_struct)); + trap_block[cpu].irq_worklist = 0; } static void __cpuinit register_one_mondo(unsigned long paddr, unsigned long type) diff --git a/arch/sparc64/kernel/sun4v_ivec.S b/arch/sparc64/kernel/sun4v_ivec.S index b49a68bdda4..f70e4774649 100644 --- a/arch/sparc64/kernel/sun4v_ivec.S +++ b/arch/sparc64/kernel/sun4v_ivec.S @@ -5,6 +5,7 @@ #include #include +#include .text .align 32 @@ -106,19 +107,13 @@ sun4v_dev_mondo: or %g4, %lo(ivector_table), %g4 add %g4, %g3, %g4 - /* Load IRQ %pil into %g5. */ - ldub [%g4 + 0x04], %g5 - /* Insert ivector_table[] entry into __irq_work[] queue. */ - sllx %g5, 2, %g3 - lduw [%g1 + %g3], %g2 /* g2 = irq_work(cpu, pil) */ + lduw [%g1], %g2 /* g2 = irq_work(cpu) */ stw %g2, [%g4 + 0x00] /* bucket->irq_chain = g2 */ - stw %g4, [%g1 + %g3] /* irq_work(cpu, pil) = bucket */ + stw %g4, [%g1] /* irq_work(cpu) = bucket */ /* Signal the interrupt by setting (1 << pil) in %softint. */ - mov 1, %g2 - sllx %g2, %g5, %g2 - wr %g2, 0x0, %set_softint + wr %g0, 1 << PIL_DEVICE_IRQ, %set_softint sun4v_dev_mondo_queue_empty: retry diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index e55b5c6ece0..0f00a99927e 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -457,7 +457,7 @@ static inline void timer_check_rtc(void) } } -static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) +irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) { unsigned long ticks, compare, pstate; @@ -1020,19 +1020,9 @@ static unsigned long sparc64_init_timers(void) return clock; } -static void sparc64_start_timers(irqreturn_t (*cfunc)(int, void *, struct pt_regs *)) +static void sparc64_start_timers(void) { unsigned long pstate; - int err; - - /* Register IRQ handler. */ - err = request_irq(build_irq(0, 0, 0UL, 0UL), cfunc, 0, - "timer", NULL); - - if (err) { - prom_printf("Serious problem, cannot register TICK_INT\n"); - prom_halt(); - } /* Guarantee that the following sequences execute * uninterrupted. @@ -1116,7 +1106,7 @@ void __init time_init(void) /* Now that the interpolator is registered, it is * safe to start the timer ticking. */ - sparc64_start_timers(timer_interrupt); + sparc64_start_timers(); timer_ticks_per_nsec_quotient = (((NSEC_PER_SEC << SPARC64_NSEC_PER_CYC_SHIFT) + diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index 563db528e03..5059cbd4fee 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c @@ -2544,7 +2544,9 @@ void __init trap_init(void) (TRAP_PER_CPU_TSB_HUGE != offsetof(struct trap_per_cpu, tsb_huge)) || (TRAP_PER_CPU_TSB_HUGE_TEMP != - offsetof(struct trap_per_cpu, tsb_huge_temp))) + offsetof(struct trap_per_cpu, tsb_huge_temp)) || + (TRAP_PER_CPU_IRQ_WORKLIST != + offsetof(struct trap_per_cpu, irq_worklist))) trap_per_cpu_offsets_are_bolixed_dave(); if ((TSB_CONFIG_TSB != diff --git a/arch/sparc64/kernel/ttable.S b/arch/sparc64/kernel/ttable.S index 5d901519db5..ee45ca2d7a0 100644 --- a/arch/sparc64/kernel/ttable.S +++ b/arch/sparc64/kernel/ttable.S @@ -58,13 +58,11 @@ tl0_irq2: BTRAP(0x42) tl0_irq3: BTRAP(0x43) tl0_irq4: BTRAP(0x44) #endif -tl0_irq5: TRAP_IRQ(handler_irq, 5) TRAP_IRQ(handler_irq, 6) -tl0_irq7: TRAP_IRQ(handler_irq, 7) TRAP_IRQ(handler_irq, 8) -tl0_irq9: TRAP_IRQ(handler_irq, 9) TRAP_IRQ(handler_irq, 10) -tl0_irq11: TRAP_IRQ(handler_irq, 11) TRAP_IRQ(handler_irq, 12) -tl0_irq13: TRAP_IRQ(handler_irq, 13) +tl0_irq5: TRAP_IRQ(handler_irq, 5) +tl0_irq6: BTRAP(0x46) BTRAP(0x47) BTRAP(0x48) BTRAP(0x49) +tl0_irq10: BTRAP(0x4a) BTRAP(0x4b) BTRAP(0x4c) BTRAP(0x4d) #ifndef CONFIG_SMP -tl0_irq14: TRAP_IRQ(handler_irq, 14) +tl0_irq14: TRAP_IRQ(timer_irq, 14) #else tl0_irq14: TICK_SMP_IRQ #endif diff --git a/include/asm-sparc64/cpudata.h b/include/asm-sparc64/cpudata.h index 9d6a6dbaf12..f2cc9411b4c 100644 --- a/include/asm-sparc64/cpudata.h +++ b/include/asm-sparc64/cpudata.h @@ -74,8 +74,10 @@ struct trap_per_cpu { unsigned long tsb_huge; unsigned long tsb_huge_temp; -/* Dcache line 8: Unused, needed to keep trap_block a power-of-2 in size. */ - unsigned long __pad2[4]; +/* Dcache line 8: IRQ work list, and keep trap_block a power-of-2 in size. */ + unsigned int irq_worklist; + unsigned int __pad1; + unsigned long __pad2[3]; } __attribute__((aligned(64))); extern struct trap_per_cpu trap_block[NR_CPUS]; extern void init_cur_cpu_trap(struct thread_info *); @@ -119,6 +121,7 @@ extern struct sun4v_2insn_patch_entry __sun4v_2insn_patch, #define TRAP_PER_CPU_CPU_LIST_PA 0xc8 #define TRAP_PER_CPU_TSB_HUGE 0xd0 #define TRAP_PER_CPU_TSB_HUGE_TEMP 0xd8 +#define TRAP_PER_CPU_IRQ_WORKLIST 0xe0 #define TRAP_BLOCK_SZ_SHIFT 8 @@ -171,11 +174,8 @@ extern struct sun4v_2insn_patch_entry __sun4v_2insn_patch, /* Clobbers TMP, loads local processor's IRQ work area into DEST. */ #define TRAP_LOAD_IRQ_WORK(DEST, TMP) \ - __GET_CPUID(TMP) \ - sethi %hi(__irq_work), DEST; \ - sllx TMP, 6, TMP; \ - or DEST, %lo(__irq_work), DEST; \ - add DEST, TMP, DEST; + TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \ + add DEST, TRAP_PER_CPU_IRQ_WORKLIST, DEST; /* Clobbers TMP, loads DEST with current thread info pointer. */ #define TRAP_LOAD_THREAD_REG(DEST, TMP) \ @@ -211,9 +211,10 @@ extern struct sun4v_2insn_patch_entry __sun4v_2insn_patch, TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \ ldx [DEST + TRAP_PER_CPU_PGD_PADDR], DEST; +/* Clobbers TMP, loads local processor's IRQ work area into DEST. */ #define TRAP_LOAD_IRQ_WORK(DEST, TMP) \ - sethi %hi(__irq_work), DEST; \ - or DEST, %lo(__irq_work), DEST; + TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \ + add DEST, TRAP_PER_CPU_IRQ_WORKLIST, DEST; #define TRAP_LOAD_THREAD_REG(DEST, TMP) \ TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \ diff --git a/include/asm-sparc64/pil.h b/include/asm-sparc64/pil.h index 79f827eb3f5..72927749aeb 100644 --- a/include/asm-sparc64/pil.h +++ b/include/asm-sparc64/pil.h @@ -5,9 +5,9 @@ /* To avoid some locking problems, we hard allocate certain PILs * for SMP cross call messages that must do a etrap/rtrap. * - * A cli() does not block the cross call delivery, so when SMP - * locking is an issue we reschedule the event into a PIL interrupt - * which is blocked by cli(). + * A local_irq_disable() does not block the cross call delivery, so + * when SMP locking is an issue we reschedule the event into a PIL + * interrupt which is blocked by local_irq_disable(). * * In fact any XCALL which has to etrap/rtrap has a problem because * it is difficult to prevent rtrap from running BH's, and that would @@ -17,6 +17,7 @@ #define PIL_SMP_RECEIVE_SIGNAL 2 #define PIL_SMP_CAPTURE 3 #define PIL_SMP_CTX_NEW_VERSION 4 +#define PIL_DEVICE_IRQ 5 #ifndef __ASSEMBLY__ #define PIL_RESERVED(PIL) ((PIL) == PIL_SMP_CALL_FUNC || \ -- cgit v1.2.3 From 6a76267f0e52d920e6bb6da75541e6116d7304da Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 20 Jun 2006 01:20:30 -0700 Subject: [SPARC64]: bp->pil can never be zero Only pil0_dummy_bucket had a pil of zero and we just killed that off, so we can delete all special case code that used bp->pil==0 as a way to identify a dummy bucket. Signed-off-by: David S. Miller --- arch/sparc64/kernel/irq.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index 0fb1738a4f3..ad134bbc151 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c @@ -633,23 +633,22 @@ static void process_bucket(struct ino_bucket *bp, struct pt_regs *regs) if (!action_mask) break; } - if (bp->pil != 0) { - if (tlb_type == hypervisor) { - unsigned int ino = __irq_ino(bp); - int err; - err = sun4v_intr_setstate(ino, HV_INTR_STATE_IDLE); - if (err != HV_EOK) - printk("sun4v_intr_setstate(%x): " - "err(%d)\n", ino, err); - } else { - upa_writel(ICLR_IDLE, bp->iclr); - } + if (tlb_type == hypervisor) { + unsigned int ino = __irq_ino(bp); + int err; - /* Test and add entropy */ - if (random & SA_SAMPLE_RANDOM) - add_interrupt_randomness(bp->pil); + err = sun4v_intr_setstate(ino, HV_INTR_STATE_IDLE); + if (err != HV_EOK) + printk("sun4v_intr_setstate(%x): " + "err(%d)\n", ino, err); + } else { + upa_writel(ICLR_IDLE, bp->iclr); } + + /* Test and add entropy */ + if (random & SA_SAMPLE_RANDOM) + add_interrupt_randomness(bp->pil); out: bp->flags &= ~IBF_INPROGRESS; } -- cgit v1.2.3 From c6387a48cf5958e43c201fc27a158c328927531a Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 20 Jun 2006 01:21:29 -0700 Subject: [SPARC]: Kill __irq_itoa(). This ugly hack was long overdue to die. It was a way to print out Sparc interrupts in a more freindly format, since IRQ numbers were arbitrary opaque 32-bit integers which vectored into PIL levels. These 32-bit integers were not necessarily in the 0-->NR_IRQS range, but the PILs they vectored to were. The idea now is that we will increase NR_IRQS a little bit and use a virtual<-->real IRQ number mapping scheme similar to PowerPC. That makes this IRQ printing hack irrelevant, and furthermore only a handful of drivers actually used __irq_itoa() making it even less useful. Signed-off-by: David S. Miller --- arch/sparc/kernel/pcic.c | 8 -------- arch/sparc/kernel/sparc_ksyms.c | 1 - arch/sparc/kernel/sun4c_irq.c | 3 --- arch/sparc/kernel/sun4d_irq.c | 12 ------------ arch/sparc/kernel/sun4m_irq.c | 8 -------- drivers/atm/fore200e.c | 4 ---- drivers/char/rtc.c | 4 ---- drivers/fc4/soc.c | 2 +- drivers/fc4/socal.c | 2 +- drivers/ide/ide-probe.c | 7 +------ drivers/ide/setup-pci.c | 5 ----- drivers/ieee1394/ohci1394.c | 4 ---- drivers/ieee1394/pcilynx.c | 4 ---- drivers/message/fusion/mptbase.c | 16 ---------------- drivers/net/3c59x.c | 5 ----- drivers/net/acenic.c | 6 +----- drivers/net/sunhme.c | 5 ----- drivers/net/sunlance.c | 2 +- drivers/sbus/char/cpwatchdog.c | 4 ++-- drivers/sbus/char/uctrl.c | 2 +- drivers/scsi/esp.c | 4 ++-- drivers/scsi/qlogicpti.c | 6 +++--- drivers/scsi/sym53c8xx_2/sym_glue.c | 6 ------ drivers/serial/sunsu.c | 4 ++-- drivers/serial/sunzilog.c | 4 ++-- drivers/usb/core/hcd.c | 12 ++---------- drivers/usb/gadget/goku_udc.c | 11 ++--------- drivers/usb/gadget/net2280.c | 14 ++++---------- include/asm-sparc/irq.h | 2 -- include/asm-sparc64/irq.h | 8 -------- sound/sparc/amd7930.c | 8 ++++---- sound/sparc/cs4231.c | 13 ++++++------- sound/sparc/dbri.c | 4 ++-- 33 files changed, 37 insertions(+), 163 deletions(-) diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c index 42002b742de..bcdf5ad0f03 100644 --- a/arch/sparc/kernel/pcic.c +++ b/arch/sparc/kernel/pcic.c @@ -896,13 +896,6 @@ static inline unsigned long get_irqmask(int irq_nr) return 1 << irq_nr; } -static inline char *pcic_irq_itoa(unsigned int irq) -{ - static char buff[16]; - sprintf(buff, "%d", irq); - return buff; -} - static void pcic_disable_irq(unsigned int irq_nr) { unsigned long mask, flags; @@ -955,7 +948,6 @@ void __init sun4m_pci_init_IRQ(void) BTFIXUPSET_CALL(clear_clock_irq, pcic_clear_clock_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(clear_profile_irq, pcic_clear_profile_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(load_profile_irq, pcic_load_profile_irq, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(__irq_itoa, pcic_irq_itoa, BTFIXUPCALL_NORM); } int pcibios_assign_resource(struct pci_dev *pdev, int resource) diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c index 4b376fae752..fd7deabf998 100644 --- a/arch/sparc/kernel/sparc_ksyms.c +++ b/arch/sparc/kernel/sparc_ksyms.c @@ -163,7 +163,6 @@ EXPORT_SYMBOL(BTFIXUP_CALL(__hard_smp_processor_id)); #endif EXPORT_SYMBOL(BTFIXUP_CALL(enable_irq)); EXPORT_SYMBOL(BTFIXUP_CALL(disable_irq)); -EXPORT_SYMBOL(BTFIXUP_CALL(__irq_itoa)); EXPORT_SYMBOL(BTFIXUP_CALL(mmu_unlockarea)); EXPORT_SYMBOL(BTFIXUP_CALL(mmu_lockarea)); EXPORT_SYMBOL(BTFIXUP_CALL(mmu_get_scsi_sgl)); diff --git a/arch/sparc/kernel/sun4c_irq.c b/arch/sparc/kernel/sun4c_irq.c index 3d6a99073c4..0f2d8d9cbdb 100644 --- a/arch/sparc/kernel/sun4c_irq.c +++ b/arch/sparc/kernel/sun4c_irq.c @@ -198,8 +198,6 @@ static void __init sun4c_init_timers(irqreturn_t (*counter_fn)(int, void *, stru static void sun4c_nop(void) {} #endif -extern char *sun4m_irq_itoa(unsigned int irq); - void __init sun4c_init_IRQ(void) { struct linux_prom_registers int_regs[2]; @@ -238,7 +236,6 @@ void __init sun4c_init_IRQ(void) BTFIXUPSET_CALL(clear_clock_irq, sun4c_clear_clock_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(clear_profile_irq, sun4c_clear_profile_irq, BTFIXUPCALL_NOP); BTFIXUPSET_CALL(load_profile_irq, sun4c_load_profile_irq, BTFIXUPCALL_NOP); - BTFIXUPSET_CALL(__irq_itoa, sun4m_irq_itoa, BTFIXUPCALL_NORM); sparc_init_timers = sun4c_init_timers; #ifdef CONFIG_SMP BTFIXUPSET_CALL(set_cpu_int, sun4c_nop, BTFIXUPCALL_NOP); diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c index ca656d9bd6f..9c30e35c88f 100644 --- a/arch/sparc/kernel/sun4d_irq.c +++ b/arch/sparc/kernel/sun4d_irq.c @@ -560,17 +560,6 @@ void __init sun4d_init_sbi_irq(void) } } -static char *sun4d_irq_itoa(unsigned int irq) -{ - static char buff[16]; - - if (irq < (1 << 5)) - sprintf(buff, "%d", irq); - else - sprintf(buff, "%d,%x", sbus_to_pil[(irq >> 2) & 7], irq); - return buff; -} - void __init sun4d_init_IRQ(void) { local_irq_disable(); @@ -581,7 +570,6 @@ void __init sun4d_init_IRQ(void) BTFIXUPSET_CALL(clear_clock_irq, sun4d_clear_clock_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(clear_profile_irq, sun4d_clear_profile_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(load_profile_irq, sun4d_load_profile_irq, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(__irq_itoa, sun4d_irq_itoa, BTFIXUPCALL_NORM); sparc_init_timers = sun4d_init_timers; #ifdef CONFIG_SMP BTFIXUPSET_CALL(set_cpu_int, sun4d_set_cpu_int, BTFIXUPCALL_NORM); diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c index 39d712c3c80..a296c13ac18 100644 --- a/arch/sparc/kernel/sun4m_irq.c +++ b/arch/sparc/kernel/sun4m_irq.c @@ -229,13 +229,6 @@ static void sun4m_load_profile_irq(int cpu, unsigned int limit) sun4m_timers->cpu_timers[cpu].l14_timer_limit = limit; } -char *sun4m_irq_itoa(unsigned int irq) -{ - static char buff[16]; - sprintf(buff, "%d", irq); - return buff; -} - static void __init sun4m_init_timers(irqreturn_t (*counter_fn)(int, void *, struct pt_regs *)) { int reg_count, irq, cpu; @@ -388,7 +381,6 @@ void __init sun4m_init_IRQ(void) BTFIXUPSET_CALL(clear_clock_irq, sun4m_clear_clock_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(clear_profile_irq, sun4m_clear_profile_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(load_profile_irq, sun4m_load_profile_irq, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(__irq_itoa, sun4m_irq_itoa, BTFIXUPCALL_NORM); sparc_init_timers = sun4m_init_timers; #ifdef CONFIG_SMP BTFIXUPSET_CALL(set_cpu_int, sun4m_send_ipi, BTFIXUPCALL_NORM); diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c index 05983a312d5..92923bf2723 100644 --- a/drivers/atm/fore200e.c +++ b/drivers/atm/fore200e.c @@ -167,13 +167,9 @@ fore200e_atm2fore_aal(int aal) static char* fore200e_irq_itoa(int irq) { -#if defined(__sparc_v9__) - return __irq_itoa(irq); -#else static char str[8]; sprintf(str, "%d", irq); return str; -#endif } diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index 7cac6d05d72..f6686fcce80 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c @@ -960,10 +960,6 @@ found: * PCI Slot 2 INTA# (and some INTx# in Slot 1). */ if (request_irq(rtc_irq, rtc_interrupt, SA_SHIRQ, "rtc", (void *)&rtc_port)) { - /* - * Standard way for sparc to print irq's is to use - * __irq_itoa(). I think for EBus it's ok to use %d. - */ printk(KERN_ERR "rtc: cannot register IRQ %d\n", rtc_irq); return -EIO; } diff --git a/drivers/fc4/soc.c b/drivers/fc4/soc.c index ec1f94738c5..cf8768b8d1f 100644 --- a/drivers/fc4/soc.c +++ b/drivers/fc4/soc.c @@ -643,7 +643,7 @@ static inline void soc_init(struct sbus_dev *sdev, int no) return; } - SOD(("SOC uses IRQ%s\n", __irq_itoa(irq))) + SOD(("SOC uses IRQ %d\n", irq)) s->port[0].fc.irq = irq; s->port[1].fc.irq = irq; diff --git a/drivers/fc4/socal.c b/drivers/fc4/socal.c index 922e9613b2c..f52d1e5bd5a 100644 --- a/drivers/fc4/socal.c +++ b/drivers/fc4/socal.c @@ -767,7 +767,7 @@ static inline void socal_init(struct sbus_dev *sdev, int no) return; } - SOD(("SOCAL uses IRQ %s\n", __irq_itoa(irq))) + SOD(("SOCAL uses IRQ %d\n", irq)) s->port[0].fc.irq = irq; s->port[1].fc.irq = irq; diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 1b7b4c531bc..9ebf8ae2a5e 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -1138,16 +1138,11 @@ static int init_irq (ide_hwif_t *hwif) spin_unlock_irq(&ide_lock); } -#if !defined(__mc68000__) && !defined(CONFIG_APUS) && !defined(__sparc__) +#if !defined(__mc68000__) && !defined(CONFIG_APUS) printk("%s at 0x%03lx-0x%03lx,0x%03lx on irq %d", hwif->name, hwif->io_ports[IDE_DATA_OFFSET], hwif->io_ports[IDE_DATA_OFFSET]+7, hwif->io_ports[IDE_CONTROL_OFFSET], hwif->irq); -#elif defined(__sparc__) - printk("%s at 0x%03lx-0x%03lx,0x%03lx on irq %s", hwif->name, - hwif->io_ports[IDE_DATA_OFFSET], - hwif->io_ports[IDE_DATA_OFFSET]+7, - hwif->io_ports[IDE_CONTROL_OFFSET], __irq_itoa(hwif->irq)); #else printk("%s at 0x%08lx on irq %d", hwif->name, hwif->io_ports[IDE_DATA_OFFSET], hwif->irq); diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c index 462ed3006c3..c11e3b2e67a 100644 --- a/drivers/ide/setup-pci.c +++ b/drivers/ide/setup-pci.c @@ -694,13 +694,8 @@ static int do_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t *d, goto out; } if (noisy) -#ifdef __sparc__ - printk(KERN_INFO "%s: 100%% native mode on irq %s\n", - d->name, __irq_itoa(pciirq)); -#else printk(KERN_INFO "%s: 100%% native mode on irq %d\n", d->name, pciirq); -#endif } /* FIXME: silent failure can happen */ diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index 11f13778f13..c031650a1c7 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c @@ -586,11 +586,7 @@ static void ohci_initialize(struct ti_ohci *ohci) reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_linkEnable); buf = reg_read(ohci, OHCI1394_Version); -#ifndef __sparc__ sprintf (irq_buf, "%d", ohci->dev->irq); -#else - sprintf (irq_buf, "%s", __irq_itoa(ohci->dev->irq)); -#endif PRINT(KERN_INFO, "OHCI-1394 %d.%d (PCI): IRQ=[%s] " "MMIO=[%lx-%lx] Max Packet=[%d] IR/IT contexts=[%d/%d]", ((((buf) >> 16) & 0xf) + (((buf) >> 20) & 0xf) * 10), diff --git a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c index e2edc41e1b6..e29dfd280be 100644 --- a/drivers/ieee1394/pcilynx.c +++ b/drivers/ieee1394/pcilynx.c @@ -1252,11 +1252,7 @@ static int __devinit add_card(struct pci_dev *dev, /* Fix buggy cards with autoboot pin not tied low: */ reg_write(lynx, DMA0_CHAN_CTRL, 0); -#ifndef __sparc__ sprintf (irq_buf, "%d", dev->irq); -#else - sprintf (irq_buf, "%s", __irq_itoa(dev->irq)); -#endif if (!request_irq(dev->irq, lynx_irq_handler, SA_SHIRQ, PCILYNX_DRIVER_NAME, lynx)) { diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index a30084076ac..59690cbabfc 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -63,9 +63,6 @@ #ifdef CONFIG_MTRR #include #endif -#ifdef __sparc__ -#include /* needed for __irq_itoa() proto */ -#endif #include "mptbase.h" @@ -1394,13 +1391,8 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) r = request_irq(pdev->irq, mpt_interrupt, SA_SHIRQ, ioc->name, ioc); if (r < 0) { -#ifndef __sparc__ printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %d!\n", ioc->name, pdev->irq); -#else - printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %s!\n", - ioc->name, __irq_itoa(pdev->irq)); -#endif list_del(&ioc->list); iounmap(mem); kfree(ioc); @@ -1412,11 +1404,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) pci_set_master(pdev); /* ?? */ pci_set_drvdata(pdev, ioc); -#ifndef __sparc__ dprintk((KERN_INFO MYNAM ": %s installed at interrupt %d\n", ioc->name, pdev->irq)); -#else - dprintk((KERN_INFO MYNAM ": %s installed at interrupt %s\n", ioc->name, __irq_itoa(pdev->irq))); -#endif } /* Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets. @@ -5647,11 +5635,7 @@ mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int sh a[5], a[4], a[3], a[2], a[1], a[0]); } -#ifndef __sparc__ y += sprintf(buffer+len+y, ", IRQ=%d", ioc->pci_irq); -#else - y += sprintf(buffer+len+y, ", IRQ=%s", __irq_itoa(ioc->pci_irq)); -#endif if (!ioc->active) y += sprintf(buffer+len+y, " (disabled)"); diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 274b0138d44..e27778926eb 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -1382,17 +1382,12 @@ static int __devinit vortex_probe1(struct device *gendev, for (i = 0; i < 6; i++) iowrite8(dev->dev_addr[i], ioaddr + i); -#ifdef __sparc__ - if (print_info) - printk(", IRQ %s\n", __irq_itoa(dev->irq)); -#else if (print_info) printk(", IRQ %d\n", dev->irq); /* Tell them about an invalid IRQ. */ if (dev->irq <= 0 || dev->irq >= NR_IRQS) printk(KERN_WARNING " *** Warning: IRQ %d is unlikely to work! ***\n", dev->irq); -#endif EL3WINDOW(4); step = (ioread8(ioaddr + Wn4_NetDiag) & 0x1e) >> 1; diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c index b508812e97a..23ff22ba5d3 100644 --- a/drivers/net/acenic.c +++ b/drivers/net/acenic.c @@ -579,11 +579,7 @@ static int __devinit acenic_probe_one(struct pci_dev *pdev, } printk("Gigabit Ethernet at 0x%08lx, ", dev->base_addr); -#ifdef __sparc__ - printk("irq %s\n", __irq_itoa(pdev->irq)); -#else - printk("irq %i\n", pdev->irq); -#endif + printk("irq %d\n", pdev->irq); #ifdef CONFIG_ACENIC_OMIT_TIGON_I if ((readl(&ap->regs->HostCtrl) >> 28) == 4) { diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index 9f046cae2f7..bd5d2668a36 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c @@ -2221,13 +2221,8 @@ static int happy_meal_open(struct net_device *dev) if (request_irq(dev->irq, &happy_meal_interrupt, SA_SHIRQ, dev->name, (void *)dev)) { HMD(("EAGAIN\n")); -#ifdef __sparc__ - printk(KERN_ERR "happy_meal(SBUS): Can't order irq %s to go.\n", - __irq_itoa(dev->irq)); -#else printk(KERN_ERR "happy_meal(SBUS): Can't order irq %d to go.\n", dev->irq); -#endif return -EAGAIN; } diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c index b7d87d4690b..6381243d8d0 100644 --- a/drivers/net/sunlance.c +++ b/drivers/net/sunlance.c @@ -936,7 +936,7 @@ static int lance_open(struct net_device *dev) if (request_irq(dev->irq, &lance_interrupt, SA_SHIRQ, lancestr, (void *) dev)) { - printk(KERN_ERR "Lance: Can't get irq %s\n", __irq_itoa(dev->irq)); + printk(KERN_ERR "Lance: Can't get irq %d\n", dev->irq); return -EAGAIN; } diff --git a/drivers/sbus/char/cpwatchdog.c b/drivers/sbus/char/cpwatchdog.c index fd2cc7782f7..5bf3dd901b6 100644 --- a/drivers/sbus/char/cpwatchdog.c +++ b/drivers/sbus/char/cpwatchdog.c @@ -304,8 +304,8 @@ static int wd_open(struct inode *inode, struct file *f) SA_SHIRQ, WD_OBPNAME, (void *)wd_dev.regs)) { - printk("%s: Cannot register IRQ %s\n", - WD_OBPNAME, __irq_itoa(wd_dev.irq)); + printk("%s: Cannot register IRQ %d\n", + WD_OBPNAME, wd_dev.irq); return(-EBUSY); } wd_dev.initialized = 1; diff --git a/drivers/sbus/char/uctrl.c b/drivers/sbus/char/uctrl.c index e2d9a7c8542..575b1f7ed41 100644 --- a/drivers/sbus/char/uctrl.c +++ b/drivers/sbus/char/uctrl.c @@ -400,7 +400,7 @@ static int __init ts102_uctrl_init(void) } driver->regs->uctrl_intr = UCTRL_INTR_RXNE_REQ|UCTRL_INTR_RXNE_MSK; - printk("uctrl: 0x%x (irq %s)\n", driver->regs, __irq_itoa(driver->irq)); + printk("uctrl: 0x%x (irq %d)\n", driver->regs, driver->irq); uctrl_get_event_status(); uctrl_get_external_status(); return 0; diff --git a/drivers/scsi/esp.c b/drivers/scsi/esp.c index 87a8c3d2072..0a3e45d7a97 100644 --- a/drivers/scsi/esp.c +++ b/drivers/scsi/esp.c @@ -821,8 +821,8 @@ static int __init esp_register_irq(struct esp *esp) return -1; } - printk("esp%d: IRQ %s ", esp->esp_id, - __irq_itoa(esp->ehost->irq)); + printk("esp%d: IRQ %d ", esp->esp_id, + esp->ehost->irq); return 0; } diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c index c7e78dcf09d..7c27ecc6fb5 100644 --- a/drivers/scsi/qlogicpti.c +++ b/drivers/scsi/qlogicpti.c @@ -725,7 +725,7 @@ static int __init qpti_register_irq(struct qlogicpti *qpti) SA_SHIRQ, "Qlogic/PTI", qpti)) goto fail; - printk("qpti%d: IRQ %s ", qpti->qpti_id, __irq_itoa(qpti->irq)); + printk("qpti%d: IRQ %d ", qpti->qpti_id, qpti->irq); return 0; @@ -988,8 +988,8 @@ const char *qlogicpti_info(struct Scsi_Host *host) static char buf[80]; struct qlogicpti *qpti = (struct qlogicpti *) host->hostdata; - sprintf(buf, "PTI Qlogic,ISP SBUS SCSI irq %s regs at %p", - __irq_itoa(qpti->qhost->irq), qpti->qregs); + sprintf(buf, "PTI Qlogic,ISP SBUS SCSI irq %d regs at %p", + qpti->qhost->irq, qpti->qregs); return buf; } diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index 9c83b4d39a2..7677fba2ceb 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -54,14 +54,8 @@ #define NAME53C "sym53c" #define NAME53C8XX "sym53c8xx" -/* SPARC just has to be different ... */ -#ifdef __sparc__ -#define IRQ_FMT "%s" -#define IRQ_PRM(x) __irq_itoa(x) -#else #define IRQ_FMT "%d" #define IRQ_PRM(x) (x) -#endif struct sym_driver_setup sym_driver_setup = SYM_LINUX_DRIVER_SETUP; unsigned int sym_debug_flags = 0; diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index 2b4f96541b8..4cdb610cdd3 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c @@ -1295,9 +1295,9 @@ static int __init sunsu_kbd_ms_init(struct uart_sunsu_port *up, int channel) if (up->port.type == PORT_UNKNOWN) return -1; - printk(KERN_INFO "su%d at 0x%p (irq = %s) is a %s\n", + printk(KERN_INFO "su%d at 0x%p (irq = %d) is a %s\n", channel, - up->port.membase, __irq_itoa(up->port.irq), + up->port.membase, up->port.irq, sunsu_type(&up->port)); #ifdef CONFIG_SERIO diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c index cd49ebbf4a4..5b6569728a9 100644 --- a/drivers/serial/sunzilog.c +++ b/drivers/serial/sunzilog.c @@ -1540,8 +1540,8 @@ static void __init sunzilog_init_kbdms(struct uart_sunzilog_port *up, int channe up->cflag = B4800 | CS8 | CLOCAL | CREAD; baud = 4800; } - printk(KERN_INFO "zs%d at 0x%p (irq = %s) is a SunZilog\n", - channel, up->port.membase, __irq_itoa(zilog_irq)); + printk(KERN_INFO "zs%d at 0x%p (irq = %d) is a SunZilog\n", + channel, up->port.membase, zilog_irq); up->curregs[R15] = BRKIE; brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR); diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index e2e00ba4e1e..4bf914d00a1 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1826,24 +1826,16 @@ int usb_add_hcd(struct usb_hcd *hcd, /* enable irqs just before we start the controller */ if (hcd->driver->irq) { - char buf[8], *bufp = buf; - -#ifdef __sparc__ - bufp = __irq_itoa(irqnum); -#else - sprintf(buf, "%d", irqnum); -#endif - snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d", hcd->driver->description, hcd->self.busnum); if ((retval = request_irq(irqnum, &usb_hcd_irq, irqflags, hcd->irq_descr, hcd)) != 0) { dev_err(hcd->self.controller, - "request interrupt %s failed\n", bufp); + "request interrupt %d failed\n", irqnum); goto err_request_irq; } hcd->irq = irqnum; - dev_info(hcd->self.controller, "irq %s, %s 0x%08llx\n", bufp, + dev_info(hcd->self.controller, "irq %d, %s 0x%08llx\n", irqnum, (hcd->driver->flags & HCD_MEMORY) ? "io mem" : "io base", (unsigned long long)hcd->rsrc_start); diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c index 66b81bbf6be..5378c175729 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c @@ -1850,7 +1850,6 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id) unsigned long resource, len; void __iomem *base = NULL; int retval; - char buf [8], *bufp; /* if you want to support more than one controller in a system, * usb_gadget_driver_{register,unregister}() must change. @@ -1913,20 +1912,14 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id) pci_set_drvdata(pdev, dev); INFO(dev, "%s\n", driver_desc); INFO(dev, "version: " DRIVER_VERSION " %s\n", dmastr()); -#ifndef __sparc__ - scnprintf(buf, sizeof buf, "%d", pdev->irq); - bufp = buf; -#else - bufp = __irq_itoa(pdev->irq); -#endif - INFO(dev, "irq %s, pci mem %p\n", bufp, base); + INFO(dev, "irq %d, pci mem %p\n", pdev->irq, base); /* init to known state, then setup irqs */ udc_reset(dev); udc_reinit (dev); if (request_irq(pdev->irq, goku_irq, SA_SHIRQ/*|SA_SAMPLE_RANDOM*/, driver_name, dev) != 0) { - DBG(dev, "request interrupt %s failed\n", bufp); + DBG(dev, "request interrupt %d failed\n", pdev->irq); retval = -EBUSY; goto done; } diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index 0b929349395..020d3c42b1a 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c @@ -2822,7 +2822,6 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id) unsigned long resource, len; void __iomem *base = NULL; int retval, i; - char buf [8], *bufp; /* if you want to support more than one controller in a system, * usb_gadget_driver_{register,unregister}() must change. @@ -2896,15 +2895,10 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id) retval = -ENODEV; goto done; } -#ifndef __sparc__ - scnprintf (buf, sizeof buf, "%d", pdev->irq); - bufp = buf; -#else - bufp = __irq_itoa(pdev->irq); -#endif + if (request_irq (pdev->irq, net2280_irq, SA_SHIRQ, driver_name, dev) != 0) { - ERROR (dev, "request interrupt %s failed\n", bufp); + ERROR (dev, "request interrupt %d failed\n", pdev->irq); retval = -EBUSY; goto done; } @@ -2953,8 +2947,8 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id) /* done */ INFO (dev, "%s\n", driver_desc); - INFO (dev, "irq %s, pci mem %p, chip rev %04x\n", - bufp, base, dev->chiprev); + INFO (dev, "irq %d, pci mem %p, chip rev %04x\n", + pdev->irq, base, dev->chiprev); INFO (dev, "version: " DRIVER_VERSION "; dma %s\n", use_dma ? (use_dma_chaining ? "chaining" : "enabled") diff --git a/include/asm-sparc/irq.h b/include/asm-sparc/irq.h index cee356b0dae..a6115c6ed6e 100644 --- a/include/asm-sparc/irq.h +++ b/include/asm-sparc/irq.h @@ -17,8 +17,6 @@ #define __irq_ino(irq) irq #define __irq_pil(irq) irq -BTFIXUPDEF_CALL(char *, __irq_itoa, unsigned int) -#define __irq_itoa(irq) BTFIXUP_CALL(__irq_itoa)(irq) #define NR_IRQS 16 diff --git a/include/asm-sparc64/irq.h b/include/asm-sparc64/irq.h index de33d6e1afb..bbdf89e6faa 100644 --- a/include/asm-sparc64/irq.h +++ b/include/asm-sparc64/irq.h @@ -99,14 +99,6 @@ extern struct ino_bucket ivector_table[NUM_IVECS]; #define __bucket(irq) ((struct ino_bucket *)(unsigned long)(irq)) #define __irq(bucket) ((unsigned int)(unsigned long)(bucket)) -static __inline__ char *__irq_itoa(unsigned int irq) -{ - static char buff[16]; - - sprintf(buff, "%d,%x", __irq_pil(irq), (unsigned int)__irq_ino(irq)); - return buff; -} - #define NR_IRQS 16 #define irq_canonicalize(irq) (irq) diff --git a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c index 55493340f46..dfe9bac7fa3 100644 --- a/sound/sparc/amd7930.c +++ b/sound/sparc/amd7930.c @@ -977,9 +977,9 @@ static int __init snd_amd7930_create(struct snd_card *card, if (request_irq(irq_prop->pri, snd_amd7930_interrupt, SA_INTERRUPT | SA_SHIRQ, "amd7930", amd)) { - snd_printk("amd7930-%d: Unable to grab IRQ %s\n", + snd_printk("amd7930-%d: Unable to grab IRQ %d\n", dev, - __irq_itoa(irq_prop->pri)); + irq_prop->pri); snd_amd7930_free(amd); return -EBUSY; } @@ -1063,11 +1063,11 @@ static int __init amd7930_attach(int prom_node, struct sbus_dev *sdev) strcpy(card->driver, "AMD7930"); strcpy(card->shortname, "Sun AMD7930"); - sprintf(card->longname, "%s at 0x%02lx:0x%08lx, irq %s", + sprintf(card->longname, "%s at 0x%02lx:0x%08lx, irq %d", card->shortname, rp->flags & 0xffL, rp->start, - __irq_itoa(irq_prop.pri)); + irq_prop.pri); if ((err = snd_amd7930_create(card, sdev, rp, reg_prop.reg_size, &irq_prop, dev, &amd)) < 0) diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c index 8804f26ddb3..b3efc9aa291 100644 --- a/sound/sparc/cs4231.c +++ b/sound/sparc/cs4231.c @@ -2003,9 +2003,8 @@ static int __init snd_cs4231_sbus_create(struct snd_card *card, if (request_irq(sdev->irqs[0], snd_cs4231_sbus_interrupt, SA_SHIRQ, "cs4231", chip)) { - snd_printdd("cs4231-%d: Unable to grab SBUS IRQ %s\n", - dev, - __irq_itoa(sdev->irqs[0])); + snd_printdd("cs4231-%d: Unable to grab SBUS IRQ %d\n", + dev, sdev->irqs[0]); snd_cs4231_sbus_free(chip); return -EBUSY; } @@ -2038,11 +2037,11 @@ static int __init cs4231_sbus_attach(struct sbus_dev *sdev) if (err) return err; - sprintf(card->longname, "%s at 0x%02lx:0x%08lx, irq %s", + sprintf(card->longname, "%s at 0x%02lx:0x%08lx, irq %d", card->shortname, rp->flags & 0xffL, rp->start, - __irq_itoa(sdev->irqs[0])); + sdev->irqs[0]); if ((err = snd_cs4231_sbus_create(card, sdev, dev, &cp)) < 0) { snd_card_free(card); @@ -2244,10 +2243,10 @@ static int __init cs4231_ebus_attach(struct linux_ebus_device *edev) if (err) return err; - sprintf(card->longname, "%s at 0x%lx, irq %s", + sprintf(card->longname, "%s at 0x%lx, irq %d", card->shortname, edev->resource[0].start, - __irq_itoa(edev->irqs[0])); + edev->irqs[0]); if ((err = snd_cs4231_ebus_create(card, edev, dev, &chip)) < 0) { snd_card_free(card); diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c index 2164b7d290c..e622d08215c 100644 --- a/sound/sparc/dbri.c +++ b/sound/sparc/dbri.c @@ -2645,9 +2645,9 @@ static int __init dbri_attach(int prom_node, struct sbus_dev *sdev) strcpy(card->driver, "DBRI"); strcpy(card->shortname, "Sun DBRI"); rp = &sdev->resource[0]; - sprintf(card->longname, "%s at 0x%02lx:0x%08lx, irq %s", + sprintf(card->longname, "%s at 0x%02lx:0x%08lx, irq %d", card->shortname, - rp->flags & 0xffL, rp->start, __irq_itoa(irq.pri)); + rp->flags & 0xffL, rp->start, irq.pri); if ((err = snd_dbri_create(card, sdev, &irq, dev)) < 0) { snd_card_free(card); -- cgit v1.2.3 From 37cdcd9e82108f9b899f1631f66ade2e45738a6e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 20 Jun 2006 01:21:57 -0700 Subject: [SPARC64]: Kill ino_bucket->pil And reuse that struct member for virt_irq, which will be used in future changesets for the implementation of mapping between real and virtual IRQ numbers. This nicely kills off a ton of SBUS and PCI controller PIL assignment code which is no longer necessary. Signed-off-by: David S. Miller --- arch/sparc64/kernel/devices.c | 2 +- arch/sparc64/kernel/irq.c | 70 ++++++++++---------------- arch/sparc64/kernel/pci_psycho.c | 77 +---------------------------- arch/sparc64/kernel/pci_sabre.c | 81 +----------------------------- arch/sparc64/kernel/pci_schizo.c | 104 +-------------------------------------- arch/sparc64/kernel/pci_sun4v.c | 32 +----------- arch/sparc64/kernel/sbus.c | 47 ++---------------- include/asm-sparc64/irq.h | 11 ++--- 8 files changed, 43 insertions(+), 381 deletions(-) diff --git a/arch/sparc64/kernel/devices.c b/arch/sparc64/kernel/devices.c index 007e8922cd1..0684899d998 100644 --- a/arch/sparc64/kernel/devices.c +++ b/arch/sparc64/kernel/devices.c @@ -157,7 +157,7 @@ unsigned int sun4v_vdev_device_interrupt(unsigned int dev_node) return 0; } - return sun4v_build_irq(sun4v_vdev_devhandle, irq, 5, 0); + return sun4v_build_irq(sun4v_vdev_devhandle, irq, 0); } static const char *cpu_mid_prop(void) diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index ad134bbc151..f2668f2bed9 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c @@ -70,7 +70,7 @@ struct ino_bucket ivector_table[NUM_IVECS] __attribute__ ((aligned (SMP_CACHE_BY */ #define irq_work(__cpu) &(trap_block[(__cpu)].irq_worklist) -static struct irqaction *irq_action[NR_IRQS+1]; +static struct irqaction *irq_action[NR_IRQS]; /* This only synchronizes entities which modify IRQ handler * state and some selected user-level spots that want to @@ -116,12 +116,9 @@ int show_interrupts(struct seq_file *p, void *v) kstat_cpu(j).irqs[i]); } #endif - seq_printf(p, " %s:%lx", action->name, - get_ino_in_irqaction(action)); - for (action = action->next; action; action = action->next) { - seq_printf(p, ", %s:%lx", action->name, - get_ino_in_irqaction(action)); - } + seq_printf(p, " %s", action->name); + for (action = action->next; action; action = action->next) + seq_printf(p, ", %s", action->name); seq_putc(p, '\n'); } out_unlock: @@ -245,48 +242,47 @@ void disable_irq(unsigned int irq) } } -static void build_irq_error(const char *msg, unsigned int ino, int pil, int inofixup, +static void build_irq_error(const char *msg, unsigned int ino, int inofixup, unsigned long iclr, unsigned long imap, struct ino_bucket *bucket) { - prom_printf("IRQ: INO %04x (%d:%016lx:%016lx) --> " - "(%d:%d:%016lx:%016lx), halting...\n", - ino, bucket->pil, bucket->iclr, bucket->imap, - pil, inofixup, iclr, imap); + prom_printf("IRQ: INO %04x (%016lx:%016lx) --> " + "(%d:%016lx:%016lx), halting...\n", + ino, bucket->iclr, bucket->imap, + inofixup, iclr, imap); prom_halt(); } -unsigned int build_irq(int pil, int inofixup, unsigned long iclr, unsigned long imap) +unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap) { struct ino_bucket *bucket; int ino; - BUG_ON(pil == 0); BUG_ON(tlb_type == hypervisor); /* RULE: Both must be specified in all other cases. */ if (iclr == 0UL || imap == 0UL) { - prom_printf("Invalid build_irq %d %d %016lx %016lx\n", - pil, inofixup, iclr, imap); + prom_printf("Invalid build_irq %d %016lx %016lx\n", + inofixup, iclr, imap); prom_halt(); } ino = (upa_readl(imap) & (IMAP_IGN | IMAP_INO)) + inofixup; if (ino > NUM_IVECS) { - prom_printf("Invalid INO %04x (%d:%d:%016lx:%016lx)\n", - ino, pil, inofixup, iclr, imap); + prom_printf("Invalid INO %04x (%d:%016lx:%016lx)\n", + ino, inofixup, iclr, imap); prom_halt(); } bucket = &ivector_table[ino]; if (bucket->flags & IBF_ACTIVE) build_irq_error("IRQ: Trying to build active INO bucket.\n", - ino, pil, inofixup, iclr, imap, bucket); + ino, inofixup, iclr, imap, bucket); if (bucket->irq_info) { if (bucket->imap != imap || bucket->iclr != iclr) build_irq_error("IRQ: Trying to reinit INO bucket.\n", - ino, pil, inofixup, iclr, imap, bucket); + ino, inofixup, iclr, imap, bucket); goto out; } @@ -302,14 +298,13 @@ unsigned int build_irq(int pil, int inofixup, unsigned long iclr, unsigned long */ bucket->imap = imap; bucket->iclr = iclr; - bucket->pil = pil; bucket->flags = 0; out: return __irq(bucket); } -unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino, int pil, unsigned char flags) +unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino, unsigned char flags) { struct ino_bucket *bucket; unsigned long sysino; @@ -328,7 +323,6 @@ unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino, int pil, unsign bucket->imap = ~0UL - sysino; bucket->iclr = ~0UL - sysino; - bucket->pil = pil; bucket->flags = flags; bucket->irq_info = kzalloc(sizeof(struct irq_desc), GFP_ATOMIC); @@ -356,16 +350,12 @@ static void atomic_bucket_insert(struct ino_bucket *bucket) static int check_irq_sharing(int pil, unsigned long irqflags) { - struct irqaction *action, *tmp; + struct irqaction *action; action = *(irq_action + pil); if (action) { - if ((action->flags & SA_SHIRQ) && (irqflags & SA_SHIRQ)) { - for (tmp = action; tmp->next; tmp = tmp->next) - ; - } else { + if (!(action->flags & SA_SHIRQ) || !(irqflags & SA_SHIRQ)) return -EBUSY; - } } return 0; } @@ -425,12 +415,12 @@ int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_ * installing a new handler, but is this really a problem, * only the sysadmin is able to do this. */ - rand_initialize_irq(irq); + rand_initialize_irq(PIL_DEVICE_IRQ); } spin_lock_irqsave(&irq_action_lock, flags); - if (check_irq_sharing(bucket->pil, irqflags)) { + if (check_irq_sharing(PIL_DEVICE_IRQ, irqflags)) { spin_unlock_irqrestore(&irq_action_lock, flags); return -EBUSY; } @@ -454,7 +444,7 @@ int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_ put_ino_in_irqaction(action, irq); put_smpaff_in_irqaction(action, CPU_MASK_NONE); - append_irq_action(bucket->pil, action); + append_irq_action(PIL_DEVICE_IRQ, action); enable_irq(irq); @@ -478,16 +468,15 @@ EXPORT_SYMBOL(request_irq); static struct irqaction *unlink_irq_action(unsigned int irq, void *dev_id) { - struct ino_bucket *bucket = __bucket(irq); struct irqaction *action, **pp; - pp = irq_action + bucket->pil; + pp = irq_action + PIL_DEVICE_IRQ; action = *pp; if (unlikely(!action)) return NULL; if (unlikely(!action->handler)) { - printk("Freeing free IRQ %d\n", bucket->pil); + printk("Freeing free IRQ %d\n", PIL_DEVICE_IRQ); return NULL; } @@ -648,7 +637,7 @@ static void process_bucket(struct ino_bucket *bp, struct pt_regs *regs) /* Test and add entropy */ if (random & SA_SAMPLE_RANDOM) - add_interrupt_randomness(bp->pil); + add_interrupt_randomness(PIL_DEVICE_IRQ); out: bp->flags &= ~IBF_INPROGRESS; } @@ -691,7 +680,7 @@ void handler_irq(int irq, struct pt_regs *regs) while (bp) { struct ino_bucket *nbp = __bucket(bp->irq_chain); - kstat_this_cpu.irqs[bp->pil]++; + kstat_this_cpu.irqs[bp->virt_irq]++; bp->irq_chain = 0; process_bucket(bp, regs); @@ -817,16 +806,9 @@ static void distribute_irqs(void) spin_lock_irqsave(&irq_action_lock, flags); cpu = 0; - /* - * Skip the timer at [0], and very rare error/power intrs at [15]. - * Also level [12], it causes problems on Ex000 systems. - */ for (level = 1; level < NR_IRQS; level++) { struct irqaction *p = irq_action[level]; - if (level == 12) - continue; - while(p) { cpu = retarget_one_irq(p, cpu); p = p->next; diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index d17878b145c..5743e1316a9 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -276,74 +276,6 @@ static unsigned long __onboard_imap_off[] = { ((ino & 0x20) ? (PSYCHO_ICLR_SCSI + (((ino) & 0x1f) << 3)) : \ (PSYCHO_ICLR_A_SLOT0 + (((ino) & 0x1f)<<3))) -/* PCI PSYCHO INO number to Sparc PIL level. */ -static unsigned char psycho_pil_table[] = { -/*0x00*/0, 0, 0, 0, /* PCI A slot 0 Int A, B, C, D */ -/*0x04*/0, 0, 0, 0, /* PCI A slot 1 Int A, B, C, D */ -/*0x08*/0, 0, 0, 0, /* PCI A slot 2 Int A, B, C, D */ -/*0x0c*/0, 0, 0, 0, /* PCI A slot 3 Int A, B, C, D */ -/*0x10*/0, 0, 0, 0, /* PCI B slot 0 Int A, B, C, D */ -/*0x14*/0, 0, 0, 0, /* PCI B slot 1 Int A, B, C, D */ -/*0x18*/0, 0, 0, 0, /* PCI B slot 2 Int A, B, C, D */ -/*0x1c*/0, 0, 0, 0, /* PCI B slot 3 Int A, B, C, D */ -/*0x20*/5, /* SCSI */ -/*0x21*/5, /* Ethernet */ -/*0x22*/8, /* Parallel Port */ -/*0x23*/13, /* Audio Record */ -/*0x24*/14, /* Audio Playback */ -/*0x25*/15, /* PowerFail */ -/*0x26*/5, /* second SCSI */ -/*0x27*/11, /* Floppy */ -/*0x28*/5, /* Spare Hardware */ -/*0x29*/9, /* Keyboard */ -/*0x2a*/5, /* Mouse */ -/*0x2b*/12, /* Serial */ -/*0x2c*/10, /* Timer 0 */ -/*0x2d*/11, /* Timer 1 */ -/*0x2e*/15, /* Uncorrectable ECC */ -/*0x2f*/15, /* Correctable ECC */ -/*0x30*/15, /* PCI Bus A Error */ -/*0x31*/15, /* PCI Bus B Error */ -/*0x32*/15, /* Power Management */ -}; - -static int psycho_ino_to_pil(struct pci_dev *pdev, unsigned int ino) -{ - int ret; - - ret = psycho_pil_table[ino]; - if (ret == 0 && pdev == NULL) { - ret = 5; - } else if (ret == 0) { - switch ((pdev->class >> 16) & 0xff) { - case PCI_BASE_CLASS_STORAGE: - ret = 5; - break; - - case PCI_BASE_CLASS_NETWORK: - ret = 6; - break; - - case PCI_BASE_CLASS_DISPLAY: - ret = 9; - break; - - case PCI_BASE_CLASS_MULTIMEDIA: - case PCI_BASE_CLASS_MEMORY: - case PCI_BASE_CLASS_BRIDGE: - case PCI_BASE_CLASS_SERIAL: - ret = 10; - break; - - default: - ret = 5; - break; - }; - } - - return ret; -} - static unsigned int psycho_irq_build(struct pci_pbm_info *pbm, struct pci_dev *pdev, unsigned int ino) @@ -351,7 +283,7 @@ static unsigned int psycho_irq_build(struct pci_pbm_info *pbm, struct ino_bucket *bucket; unsigned long imap, iclr; unsigned long imap_off, iclr_off; - int pil, inofixup = 0; + int inofixup = 0; ino &= PCI_IRQ_INO; if (ino < PSYCHO_ONBOARD_IRQ_BASE) { @@ -367,11 +299,6 @@ static unsigned int psycho_irq_build(struct pci_pbm_info *pbm, } /* Now build the IRQ bucket. */ - pil = psycho_ino_to_pil(pdev, ino); - - if (PIL_RESERVED(pil)) - BUG(); - imap = pbm->controller_regs + imap_off; imap += 4; @@ -382,7 +309,7 @@ static unsigned int psycho_irq_build(struct pci_pbm_info *pbm, if ((ino & 0x20) == 0) inofixup = ino & 0x03; - bucket = __bucket(build_irq(pil, inofixup, iclr, imap)); + bucket = __bucket(build_irq(inofixup, iclr, imap)); bucket->flags |= IBF_PCI; return __irq(bucket); diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index f67bb7f078c..caa7aeed5d1 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -523,78 +523,6 @@ static unsigned long __onboard_imap_off[] = { ((ino & 0x20) ? (SABRE_ICLR_SCSI + (((ino) & 0x1f) << 3)) : \ (SABRE_ICLR_A_SLOT0 + (((ino) & 0x1f)<<3))) -/* PCI SABRE INO number to Sparc PIL level. */ -static unsigned char sabre_pil_table[] = { -/*0x00*/0, 0, 0, 0, /* PCI A slot 0 Int A, B, C, D */ -/*0x04*/0, 0, 0, 0, /* PCI A slot 1 Int A, B, C, D */ -/*0x08*/0, 0, 0, 0, /* PCI A slot 2 Int A, B, C, D */ -/*0x0c*/0, 0, 0, 0, /* PCI A slot 3 Int A, B, C, D */ -/*0x10*/0, 0, 0, 0, /* PCI B slot 0 Int A, B, C, D */ -/*0x14*/0, 0, 0, 0, /* PCI B slot 1 Int A, B, C, D */ -/*0x18*/0, 0, 0, 0, /* PCI B slot 2 Int A, B, C, D */ -/*0x1c*/0, 0, 0, 0, /* PCI B slot 3 Int A, B, C, D */ -/*0x20*/5, /* SCSI */ -/*0x21*/5, /* Ethernet */ -/*0x22*/8, /* Parallel Port */ -/*0x23*/13, /* Audio Record */ -/*0x24*/14, /* Audio Playback */ -/*0x25*/15, /* PowerFail */ -/*0x26*/5, /* second SCSI */ -/*0x27*/11, /* Floppy */ -/*0x28*/5, /* Spare Hardware */ -/*0x29*/9, /* Keyboard */ -/*0x2a*/5, /* Mouse */ -/*0x2b*/12, /* Serial */ -/*0x2c*/10, /* Timer 0 */ -/*0x2d*/11, /* Timer 1 */ -/*0x2e*/15, /* Uncorrectable ECC */ -/*0x2f*/15, /* Correctable ECC */ -/*0x30*/15, /* PCI Bus A Error */ -/*0x31*/15, /* PCI Bus B Error */ -/*0x32*/15, /* Power Management */ -}; - -static int sabre_ino_to_pil(struct pci_dev *pdev, unsigned int ino) -{ - int ret; - - if (pdev && - pdev->vendor == PCI_VENDOR_ID_SUN && - pdev->device == PCI_DEVICE_ID_SUN_RIO_USB) - return 9; - - ret = sabre_pil_table[ino]; - if (ret == 0 && pdev == NULL) { - ret = 5; - } else if (ret == 0) { - switch ((pdev->class >> 16) & 0xff) { - case PCI_BASE_CLASS_STORAGE: - ret = 5; - break; - - case PCI_BASE_CLASS_NETWORK: - ret = 6; - break; - - case PCI_BASE_CLASS_DISPLAY: - ret = 9; - break; - - case PCI_BASE_CLASS_MULTIMEDIA: - case PCI_BASE_CLASS_MEMORY: - case PCI_BASE_CLASS_BRIDGE: - case PCI_BASE_CLASS_SERIAL: - ret = 10; - break; - - default: - ret = 5; - break; - }; - } - return ret; -} - /* When a device lives behind a bridge deeper in the PCI bus topology * than APB, a special sequence must run to make sure all pending DMA * transfers at the time of IRQ delivery are visible in the coherency @@ -619,7 +547,7 @@ static unsigned int sabre_irq_build(struct pci_pbm_info *pbm, struct ino_bucket *bucket; unsigned long imap, iclr; unsigned long imap_off, iclr_off; - int pil, inofixup = 0; + int inofixup = 0; ino &= PCI_IRQ_INO; if (ino < SABRE_ONBOARD_IRQ_BASE) { @@ -635,11 +563,6 @@ static unsigned int sabre_irq_build(struct pci_pbm_info *pbm, } /* Now build the IRQ bucket. */ - pil = sabre_ino_to_pil(pdev, ino); - - if (PIL_RESERVED(pil)) - BUG(); - imap = pbm->controller_regs + imap_off; imap += 4; @@ -650,7 +573,7 @@ static unsigned int sabre_irq_build(struct pci_pbm_info *pbm, if ((ino & 0x20) == 0) inofixup = ino & 0x03; - bucket = __bucket(build_irq(pil, inofixup, iclr, imap)); + bucket = __bucket(build_irq(inofixup, iclr, imap)); bucket->flags |= IBF_PCI; if (pdev) { diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index 7fe4de03ac2..ca49ef08236 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c @@ -232,101 +232,6 @@ static unsigned long schizo_iclr_offset(unsigned long ino) return SCHIZO_ICLR_BASE + (ino * 8UL); } -/* PCI SCHIZO INO number to Sparc PIL level. This table only matters for - * INOs which will not have an associated PCI device struct, ie. onboard - * EBUS devices and PCI controller internal error interrupts. - */ -static unsigned char schizo_pil_table[] = { -/*0x00*/0, 0, 0, 0, /* PCI slot 0 Int A, B, C, D */ -/*0x04*/0, 0, 0, 0, /* PCI slot 1 Int A, B, C, D */ -/*0x08*/0, 0, 0, 0, /* PCI slot 2 Int A, B, C, D */ -/*0x0c*/0, 0, 0, 0, /* PCI slot 3 Int A, B, C, D */ -/*0x10*/0, 0, 0, 0, /* PCI slot 4 Int A, B, C, D */ -/*0x14*/0, 0, 0, 0, /* PCI slot 5 Int A, B, C, D */ -/*0x18*/5, /* SCSI */ -/*0x19*/5, /* second SCSI */ -/*0x1a*/0, /* UNKNOWN */ -/*0x1b*/0, /* UNKNOWN */ -/*0x1c*/8, /* Parallel */ -/*0x1d*/5, /* Ethernet */ -/*0x1e*/8, /* Firewire-1394 */ -/*0x1f*/9, /* USB */ -/*0x20*/13, /* Audio Record */ -/*0x21*/14, /* Audio Playback */ -/*0x22*/12, /* Serial */ -/*0x23*/5, /* EBUS I2C */ -/*0x24*/10, /* RTC Clock */ -/*0x25*/11, /* Floppy */ -/*0x26*/0, /* UNKNOWN */ -/*0x27*/0, /* UNKNOWN */ -/*0x28*/0, /* UNKNOWN */ -/*0x29*/0, /* UNKNOWN */ -/*0x2a*/10, /* UPA 1 */ -/*0x2b*/10, /* UPA 2 */ -/*0x2c*/0, /* UNKNOWN */ -/*0x2d*/0, /* UNKNOWN */ -/*0x2e*/0, /* UNKNOWN */ -/*0x2f*/0, /* UNKNOWN */ -/*0x30*/15, /* Uncorrectable ECC */ -/*0x31*/15, /* Correctable ECC */ -/*0x32*/15, /* PCI Bus A Error */ -/*0x33*/15, /* PCI Bus B Error */ -/*0x34*/15, /* Safari Bus Error */ -/*0x35*/0, /* Reserved */ -/*0x36*/0, /* Reserved */ -/*0x37*/0, /* Reserved */ -/*0x38*/0, /* Reserved for NewLink */ -/*0x39*/0, /* Reserved for NewLink */ -/*0x3a*/0, /* Reserved for NewLink */ -/*0x3b*/0, /* Reserved for NewLink */ -/*0x3c*/0, /* Reserved for NewLink */ -/*0x3d*/0, /* Reserved for NewLink */ -/*0x3e*/0, /* Reserved for NewLink */ -/*0x3f*/0, /* Reserved for NewLink */ -}; - -static int schizo_ino_to_pil(struct pci_dev *pdev, unsigned int ino) -{ - int ret; - - if (pdev && - pdev->vendor == PCI_VENDOR_ID_SUN && - pdev->device == PCI_DEVICE_ID_SUN_RIO_USB) - return 9; - - ret = schizo_pil_table[ino]; - if (ret == 0 && pdev == NULL) { - ret = 5; - } else if (ret == 0) { - switch ((pdev->class >> 16) & 0xff) { - case PCI_BASE_CLASS_STORAGE: - ret = 5; - break; - - case PCI_BASE_CLASS_NETWORK: - ret = 6; - break; - - case PCI_BASE_CLASS_DISPLAY: - ret = 9; - break; - - case PCI_BASE_CLASS_MULTIMEDIA: - case PCI_BASE_CLASS_MEMORY: - case PCI_BASE_CLASS_BRIDGE: - case PCI_BASE_CLASS_SERIAL: - ret = 10; - break; - - default: - ret = 5; - break; - }; - } - - return ret; -} - static void tomatillo_wsync_handler(struct ino_bucket *bucket, void *_arg1, void *_arg2) { unsigned long sync_reg = (unsigned long) _arg2; @@ -372,17 +277,12 @@ static unsigned int schizo_irq_build(struct pci_pbm_info *pbm, struct ino_bucket *bucket; unsigned long imap, iclr; unsigned long imap_off, iclr_off; - int pil, ign_fixup; + int ign_fixup; ino &= PCI_IRQ_INO; imap_off = schizo_imap_offset(ino); /* Now build the IRQ bucket. */ - pil = schizo_ino_to_pil(pdev, ino); - - if (PIL_RESERVED(pil)) - BUG(); - imap = pbm->pbm_regs + imap_off; imap += 4; @@ -405,7 +305,7 @@ static unsigned int schizo_irq_build(struct pci_pbm_info *pbm, ign_fixup = (1 << 6); } - bucket = __bucket(build_irq(pil, ign_fixup, iclr, imap)); + bucket = __bucket(build_irq(ign_fixup, iclr, imap)); bucket->flags |= IBF_PCI; if (pdev && pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) { diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index 0c089520297..b97c81ba883 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c @@ -843,38 +843,8 @@ static unsigned int pci_sun4v_irq_build(struct pci_pbm_info *pbm, unsigned int devino) { u32 devhandle = pbm->devhandle; - int pil; - pil = 5; - if (pdev) { - switch ((pdev->class >> 16) & 0xff) { - case PCI_BASE_CLASS_STORAGE: - pil = 5; - break; - - case PCI_BASE_CLASS_NETWORK: - pil = 6; - break; - - case PCI_BASE_CLASS_DISPLAY: - pil = 9; - break; - - case PCI_BASE_CLASS_MULTIMEDIA: - case PCI_BASE_CLASS_MEMORY: - case PCI_BASE_CLASS_BRIDGE: - case PCI_BASE_CLASS_SERIAL: - pil = 10; - break; - - default: - pil = 5; - break; - }; - } - BUG_ON(PIL_RESERVED(pil)); - - return sun4v_build_irq(devhandle, devino, pil, IBF_PCI); + return sun4v_build_irq(devhandle, devino, IBF_PCI); } static void pci_sun4v_base_address_update(struct pci_dev *pdev, int resource) diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c index 1d6ffdeabd4..8812417247d 100644 --- a/arch/sparc64/kernel/sbus.c +++ b/arch/sparc64/kernel/sbus.c @@ -691,36 +691,6 @@ void sbus_set_sbus64(struct sbus_dev *sdev, int bursts) upa_writeq(val, cfg_reg); } -/* SBUS SYSIO INO number to Sparc PIL level. */ -static unsigned char sysio_ino_to_pil[] = { - 0, 5, 5, 7, 5, 7, 8, 9, /* SBUS slot 0 */ - 0, 5, 5, 7, 5, 7, 8, 9, /* SBUS slot 1 */ - 0, 5, 5, 7, 5, 7, 8, 9, /* SBUS slot 2 */ - 0, 5, 5, 7, 5, 7, 8, 9, /* SBUS slot 3 */ - 5, /* Onboard SCSI */ - 5, /* Onboard Ethernet */ -/*XXX*/ 8, /* Onboard BPP */ - 0, /* Bogon */ - 13, /* Audio */ -/*XXX*/15, /* PowerFail */ - 0, /* Bogon */ - 0, /* Bogon */ - 12, /* Zilog Serial Channels (incl. Keyboard/Mouse lines) */ - 11, /* Floppy */ - 0, /* Spare Hardware (bogon for now) */ - 0, /* Keyboard (bogon for now) */ - 0, /* Mouse (bogon for now) */ - 0, /* Serial (bogon for now) */ - 0, 0, /* Bogon, Bogon */ - 10, /* Timer 0 */ - 11, /* Timer 1 */ - 0, 0, /* Bogon, Bogon */ - 15, /* Uncorrectable SBUS Error */ - 15, /* Correctable SBUS Error */ - 15, /* SBUS Error */ -/*XXX*/ 0, /* Power Management (bogon for now) */ -}; - /* INO number to IMAP register offset for SYSIO external IRQ's. * This should conform to both Sunfire/Wildfire server and Fusion * desktop designs. @@ -812,21 +782,12 @@ unsigned int sbus_build_irq(void *buscookie, unsigned int ino) struct sbus_iommu *iommu = sbus->iommu; unsigned long reg_base = iommu->sbus_control_reg - 0x2000UL; unsigned long imap, iclr; - int pil, sbus_level = 0; - - pil = sysio_ino_to_pil[ino]; - if (!pil) { - printk("sbus_irq_build: Bad SYSIO INO[%x]\n", ino); - panic("Bad SYSIO IRQ translations..."); - } - - if (PIL_RESERVED(pil)) - BUG(); + int sbus_level = 0; imap = sysio_irq_offsets[ino]; if (imap == ((unsigned long)-1)) { - prom_printf("get_irq_translations: Bad SYSIO INO[%x] cpu[%d]\n", - ino, pil); + prom_printf("get_irq_translations: Bad SYSIO INO[%x]\n", + ino); prom_halt(); } imap += reg_base; @@ -860,7 +821,7 @@ unsigned int sbus_build_irq(void *buscookie, unsigned int ino) iclr += ((unsigned long)sbus_level - 1UL) * 8UL; } - return build_irq(pil, sbus_level, iclr, imap); + return build_irq(sbus_level, iclr, imap); } /* Error interrupt handling. */ diff --git a/include/asm-sparc64/irq.h b/include/asm-sparc64/irq.h index bbdf89e6faa..d66c7cd820c 100644 --- a/include/asm-sparc64/irq.h +++ b/include/asm-sparc64/irq.h @@ -37,14 +37,14 @@ struct irq_desc { * line. Keep this in mind please. */ struct ino_bucket { - /* Next handler in per-CPU PIL worklist. We know that + /* Next handler in per-CPU IRQ worklist. We know that * bucket pointers have the high 32-bits clear, so to * save space we only store the bits we need. */ /*0x00*/unsigned int irq_chain; - /* PIL to schedule this IVEC at. */ -/*0x04*/unsigned char pil; + /* Virtual interrupt number assigned to this INO. */ +/*0x04*/unsigned char virt_irq; /* If an IVEC arrives while irq_info is NULL, we * set this to notify request_irq() about the event. @@ -95,7 +95,6 @@ extern struct ino_bucket ivector_table[NUM_IVECS]; #define __irq_ino(irq) \ (((struct ino_bucket *)(unsigned long)(irq)) - &ivector_table[0]) -#define __irq_pil(irq) ((struct ino_bucket *)(unsigned long)(irq))->pil #define __bucket(irq) ((struct ino_bucket *)(unsigned long)(irq)) #define __irq(bucket) ((unsigned int)(unsigned long)(bucket)) @@ -105,8 +104,8 @@ extern struct ino_bucket ivector_table[NUM_IVECS]; extern void disable_irq(unsigned int); #define disable_irq_nosync disable_irq extern void enable_irq(unsigned int); -extern unsigned int build_irq(int pil, int inofixup, unsigned long iclr, unsigned long imap); -extern unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino, int pil, unsigned char flags); +extern unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap); +extern unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino, unsigned char flags); extern unsigned int sbus_build_irq(void *sbus, unsigned int ino); static __inline__ void set_softint(unsigned long bits) -- cgit v1.2.3 From 8047e247c899f80c33a23ad7e9e250224f0d26a5 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 20 Jun 2006 01:22:35 -0700 Subject: [SPARC64]: Virtualize IRQ numbers. Inspired by PowerPC XICS interrupt support code. All IRQs are virtualized in order to keep NR_IRQS from needing to be too large. Interrupts on sparc64 are arbitrary 11-bit values, but we don't need to define NR_IRQS to 2048 if we virtualize the IRQs. As PCI and SBUS controller drivers build device IRQs, we divy out virtual IRQ numbers incrementally starting at 1. Zero is a special virtual IRQ used for the timer interrupt. So device drivers all see virtual IRQs, and all the normal interfaces such as request_irq(), enable_irq(), etc. translate that into a real IRQ number in order to configure the IRQ. At this point knowledge of the struct ino_bucket is almost entirely contained within arch/sparc64/kernel/irq.c There are a few small bits in the PCI controller drivers that need to be swept away before we can remove ino_bucket's definition out of asm-sparc64/irq.h and privately into kernel/irq.c Signed-off-by: David S. Miller --- arch/sparc64/kernel/irq.c | 263 ++++++++++++++++++++++++++------------- arch/sparc64/kernel/pci_psycho.c | 6 +- arch/sparc64/kernel/pci_sabre.c | 18 +-- arch/sparc64/kernel/pci_schizo.c | 86 ++++++------- arch/sparc64/kernel/sbus.c | 2 +- include/asm-sparc64/irq.h | 13 +- 6 files changed, 242 insertions(+), 146 deletions(-) diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index f2668f2bed9..49ad9cd0f8c 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c @@ -70,7 +70,10 @@ struct ino_bucket ivector_table[NUM_IVECS] __attribute__ ((aligned (SMP_CACHE_BY */ #define irq_work(__cpu) &(trap_block[(__cpu)].irq_worklist) -static struct irqaction *irq_action[NR_IRQS]; +static struct irqaction timer_irq_action = { + .name = "timer", +}; +static struct irqaction *irq_action[NR_IRQS] = { &timer_irq_action, }; /* This only synchronizes entities which modify IRQ handler * state and some selected user-level spots that want to @@ -79,6 +82,59 @@ static struct irqaction *irq_action[NR_IRQS]; */ static DEFINE_SPINLOCK(irq_action_lock); +static unsigned int virt_to_real_irq_table[NR_IRQS]; +static unsigned char virt_irq_cur = 1; + +static unsigned char virt_irq_alloc(unsigned int real_irq) +{ + unsigned char ent; + + BUILD_BUG_ON(NR_IRQS >= 256); + + ent = virt_irq_cur; + if (ent >= NR_IRQS) { + printk(KERN_ERR "IRQ: Out of virtual IRQs.\n"); + return 0; + } + + virt_irq_cur = ent + 1; + virt_to_real_irq_table[ent] = real_irq; + + return ent; +} + +#if 0 /* Currently unused. */ +static unsigned char real_to_virt_irq(unsigned int real_irq) +{ + struct ino_bucket *bucket = __bucket(real_irq); + + return bucket->virt_irq; +} +#endif + +static unsigned int virt_to_real_irq(unsigned char virt_irq) +{ + return virt_to_real_irq_table[virt_irq]; +} + +void irq_install_pre_handler(int virt_irq, + void (*func)(struct ino_bucket *, void *, void *), + void *arg1, void *arg2) +{ + unsigned int real_irq = virt_to_real_irq(virt_irq); + struct ino_bucket *bucket; + struct irq_desc *d; + + if (unlikely(!real_irq)) + return; + + bucket = __bucket(real_irq); + d = bucket->irq_info; + d->pre_handler = func; + d->pre_handler_arg1 = arg1; + d->pre_handler_arg2 = arg2; +} + static void register_irq_proc (unsigned int irq); /* @@ -164,14 +220,18 @@ static unsigned int sun4u_compute_tid(unsigned long imap, unsigned long cpuid) return tid; } -/* Now these are always passed a true fully specified sun4u INO. */ -void enable_irq(unsigned int irq) +void enable_irq(unsigned int virt_irq) { - struct ino_bucket *bucket = __bucket(irq); + unsigned int real_irq = virt_to_real_irq(virt_irq); + struct ino_bucket *bucket; unsigned long imap, cpuid; + if (unlikely(!real_irq)) + return; + + bucket = __bucket(real_irq); imap = bucket->imap; - if (imap == 0UL) + if (unlikely(imap == 0UL)) return; preempt_disable(); @@ -182,7 +242,7 @@ void enable_irq(unsigned int irq) cpuid = real_hard_smp_processor_id(); if (tlb_type == hypervisor) { - unsigned int ino = __irq_ino(irq); + unsigned int ino = __irq_ino(real_irq); int err; err = sun4v_intr_settarget(ino, cpuid); @@ -211,34 +271,39 @@ void enable_irq(unsigned int irq) preempt_enable(); } -/* This now gets passed true ino's as well. */ -void disable_irq(unsigned int irq) +void disable_irq(unsigned int virt_irq) { - struct ino_bucket *bucket = __bucket(irq); + unsigned int real_irq = virt_to_real_irq(virt_irq); + struct ino_bucket *bucket; unsigned long imap; + if (unlikely(!real_irq)) + return; + + bucket = __bucket(real_irq); imap = bucket->imap; - if (imap != 0UL) { - if (tlb_type == hypervisor) { - unsigned int ino = __irq_ino(irq); - int err; - - err = sun4v_intr_setenabled(ino, HV_INTR_DISABLED); - if (err != HV_EOK) - printk("sun4v_intr_setenabled(%x): " - "err(%d)\n", ino, err); - } else { - u32 tmp; - - /* NOTE: We do not want to futz with the IRQ clear registers - * and move the state to IDLE, the SCSI code does call - * disable_irq() to assure atomicity in the queue cmd - * SCSI adapter driver code. Thus we'd lose interrupts. - */ - tmp = upa_readl(imap); - tmp &= ~IMAP_VALID; - upa_writel(tmp, imap); - } + if (unlikely(imap == 0UL)) + return; + + if (tlb_type == hypervisor) { + unsigned int ino = __irq_ino(real_irq); + int err; + + err = sun4v_intr_setenabled(ino, HV_INTR_DISABLED); + if (err != HV_EOK) + printk("sun4v_intr_setenabled(%x): " + "err(%d)\n", ino, err); + } else { + u32 tmp; + + /* NOTE: We do not want to futz with the IRQ clear registers + * and move the state to IDLE, the SCSI code does call + * disable_irq() to assure atomicity in the queue cmd + * SCSI adapter driver code. Thus we'd lose interrupts. + */ + tmp = upa_readl(imap); + tmp &= ~IMAP_VALID; + upa_writel(tmp, imap); } } @@ -253,14 +318,14 @@ static void build_irq_error(const char *msg, unsigned int ino, int inofixup, prom_halt(); } -unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap) +unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap, unsigned char flags) { struct ino_bucket *bucket; int ino; BUG_ON(tlb_type == hypervisor); - /* RULE: Both must be specified in all other cases. */ + /* RULE: Both must be specified. */ if (iclr == 0UL || imap == 0UL) { prom_printf("Invalid build_irq %d %016lx %016lx\n", inofixup, iclr, imap); @@ -298,10 +363,12 @@ unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap) */ bucket->imap = imap; bucket->iclr = iclr; - bucket->flags = 0; + if (!bucket->virt_irq) + bucket->virt_irq = virt_irq_alloc(__irq(bucket)); + bucket->flags = flags; out: - return __irq(bucket); + return bucket->virt_irq; } unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino, unsigned char flags) @@ -322,7 +389,8 @@ unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino, unsigned char f */ bucket->imap = ~0UL - sysino; bucket->iclr = ~0UL - sysino; - + if (!bucket->virt_irq) + bucket->virt_irq = virt_irq_alloc(__irq(bucket)); bucket->flags = flags; bucket->irq_info = kzalloc(sizeof(struct irq_desc), GFP_ATOMIC); @@ -331,7 +399,7 @@ unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino, unsigned char f prom_halt(); } - return __irq(bucket); + return bucket->virt_irq; } static void atomic_bucket_insert(struct ino_bucket *bucket) @@ -390,37 +458,42 @@ static struct irqaction *get_action_slot(struct ino_bucket *bucket) return NULL; } -int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), +int request_irq(unsigned int virt_irq, + irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long irqflags, const char *name, void *dev_id) { struct irqaction *action; - struct ino_bucket *bucket = __bucket(irq); + struct ino_bucket *bucket; unsigned long flags; + unsigned int real_irq; int pending = 0; + real_irq = virt_to_real_irq(virt_irq); + if (unlikely(!real_irq)) + return -EINVAL; + if (unlikely(!handler)) return -EINVAL; + bucket = __bucket(real_irq); if (unlikely(!bucket->irq_info)) return -ENODEV; if (irqflags & SA_SAMPLE_RANDOM) { /* - * This function might sleep, we want to call it first, - * outside of the atomic block. In SA_STATIC_ALLOC case, - * random driver's kmalloc will fail, but it is safe. - * If already initialized, random driver will not reinit. - * Yes, this might clear the entropy pool if the wrong - * driver is attempted to be loaded, without actually - * installing a new handler, but is this really a problem, - * only the sysadmin is able to do this. - */ - rand_initialize_irq(PIL_DEVICE_IRQ); + * This function might sleep, we want to call it first, + * outside of the atomic block. + * Yes, this might clear the entropy pool if the wrong + * driver is attempted to be loaded, without actually + * installing a new handler, but is this really a problem, + * only the sysadmin is able to do this. + */ + rand_initialize_irq(virt_irq); } spin_lock_irqsave(&irq_action_lock, flags); - if (check_irq_sharing(PIL_DEVICE_IRQ, irqflags)) { + if (check_irq_sharing(virt_irq, irqflags)) { spin_unlock_irqrestore(&irq_action_lock, flags); return -EBUSY; } @@ -441,12 +514,12 @@ int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_ action->name = name; action->next = NULL; action->dev_id = dev_id; - put_ino_in_irqaction(action, irq); + put_ino_in_irqaction(action, __irq_ino(real_irq)); put_smpaff_in_irqaction(action, CPU_MASK_NONE); - append_irq_action(PIL_DEVICE_IRQ, action); + append_irq_action(virt_irq, action); - enable_irq(irq); + enable_irq(virt_irq); /* We ate the IVEC already, this makes sure it does not get lost. */ if (pending) { @@ -456,7 +529,7 @@ int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_ spin_unlock_irqrestore(&irq_action_lock, flags); - register_irq_proc(__irq_ino(irq)); + register_irq_proc(virt_irq); #ifdef CONFIG_SMP distribute_irqs(); @@ -466,17 +539,17 @@ int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_ EXPORT_SYMBOL(request_irq); -static struct irqaction *unlink_irq_action(unsigned int irq, void *dev_id) +static struct irqaction *unlink_irq_action(unsigned int virt_irq, void *dev_id) { struct irqaction *action, **pp; - pp = irq_action + PIL_DEVICE_IRQ; + pp = irq_action + virt_irq; action = *pp; if (unlikely(!action)) return NULL; if (unlikely(!action->handler)) { - printk("Freeing free IRQ %d\n", PIL_DEVICE_IRQ); + printk("Freeing free IRQ %d\n", virt_irq); return NULL; } @@ -491,28 +564,33 @@ static struct irqaction *unlink_irq_action(unsigned int irq, void *dev_id) return action; } -void free_irq(unsigned int irq, void *dev_id) +void free_irq(unsigned int virt_irq, void *dev_id) { struct irqaction *action; struct ino_bucket *bucket; struct irq_desc *desc; unsigned long flags; + unsigned int real_irq; int ent, i; + real_irq = virt_to_real_irq(virt_irq); + if (unlikely(!real_irq)) + return; + spin_lock_irqsave(&irq_action_lock, flags); - action = unlink_irq_action(irq, dev_id); + action = unlink_irq_action(virt_irq, dev_id); spin_unlock_irqrestore(&irq_action_lock, flags); if (unlikely(!action)) return; - synchronize_irq(irq); + synchronize_irq(virt_irq); spin_lock_irqsave(&irq_action_lock, flags); - bucket = __bucket(irq); + bucket = __bucket(real_irq); desc = bucket->irq_info; for (i = 0; i < MAX_IRQ_DESC_ACTION; i++) { @@ -545,7 +623,7 @@ void free_irq(unsigned int irq, void *dev_id) * the same IMAP are active. */ if (ent == NUM_IVECS) - disable_irq(irq); + disable_irq(virt_irq); } spin_unlock_irqrestore(&irq_action_lock, flags); @@ -554,10 +632,15 @@ void free_irq(unsigned int irq, void *dev_id) EXPORT_SYMBOL(free_irq); #ifdef CONFIG_SMP -void synchronize_irq(unsigned int irq) +void synchronize_irq(unsigned int virt_irq) { - struct ino_bucket *bucket = __bucket(irq); + unsigned int real_irq = virt_to_real_irq(virt_irq); + struct ino_bucket *bucket; + + if (unlikely(!real_irq)) + return; + bucket = __bucket(real_irq); #if 0 /* The following is how I wish I could implement this. * Unfortunately the ICLR registers are read-only, you can @@ -616,7 +699,7 @@ static void process_bucket(struct ino_bucket *bp, struct pt_regs *regs) action_mask &= ~mask; - if (p->handler(__irq(bp), p->dev_id, regs) == IRQ_HANDLED) + if (p->handler(bp->virt_irq, p->dev_id, regs) == IRQ_HANDLED) random |= p->flags; if (!action_mask) @@ -637,7 +720,7 @@ static void process_bucket(struct ino_bucket *bp, struct pt_regs *regs) /* Test and add entropy */ if (random & SA_SAMPLE_RANDOM) - add_interrupt_randomness(PIL_DEVICE_IRQ); + add_interrupt_randomness(bp->virt_irq); out: bp->flags &= ~IBF_INPROGRESS; } @@ -657,7 +740,7 @@ void timer_irq(int irq, struct pt_regs *regs) clear_softint(clr_mask); irq_enter(); - kstat_this_cpu.irqs[irq]++; + kstat_this_cpu.irqs[0]++; timer_interrupt(irq, NULL, regs); irq_exit(); } @@ -1022,13 +1105,13 @@ void __init init_IRQ(void) : "g1"); } -static struct proc_dir_entry * root_irq_dir; -static struct proc_dir_entry * irq_dir [NUM_IVECS]; +static struct proc_dir_entry *root_irq_dir; +static struct proc_dir_entry *irq_dir[NR_IRQS]; #ifdef CONFIG_SMP -static int irq_affinity_read_proc (char *page, char **start, off_t off, - int count, int *eof, void *data) +static int irq_affinity_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) { struct ino_bucket *bp = ivector_table + (long)data; struct irq_desc *desc = bp->irq_info; @@ -1047,11 +1130,20 @@ static int irq_affinity_read_proc (char *page, char **start, off_t off, return len; } -static inline void set_intr_affinity(int irq, cpumask_t hw_aff) +static inline void set_intr_affinity(int virt_irq, cpumask_t hw_aff) { - struct ino_bucket *bp = ivector_table + irq; - struct irq_desc *desc = bp->irq_info; - struct irqaction *ap = desc->action; + struct ino_bucket *bp; + struct irq_desc *desc; + struct irqaction *ap; + unsigned int real_irq; + + real_irq = virt_to_real_irq(virt_irq); + if (unlikely(!real_irq)) + return; + + bp = __bucket(real_irq); + desc = bp->irq_info; + ap = desc->action; /* Users specify affinity in terms of hw cpu ids. * As soon as we do this, handler_irq() might see and take action. @@ -1060,13 +1152,16 @@ static inline void set_intr_affinity(int irq, cpumask_t hw_aff) /* Migration is simply done by the next cpu to service this * interrupt. + * + * XXX Broken, this doesn't happen anymore... */ } -static int irq_affinity_write_proc (struct file *file, const char __user *buffer, - unsigned long count, void *data) +static int irq_affinity_write_proc(struct file *file, + const char __user *buffer, + unsigned long count, void *data) { - int irq = (long) data, full_count = count, err; + int virt_irq = (long) data, full_count = count, err; cpumask_t new_value; err = cpumask_parse(buffer, count, new_value); @@ -1080,7 +1175,7 @@ static int irq_affinity_write_proc (struct file *file, const char __user *buffer if (cpus_empty(new_value)) return -EINVAL; - set_intr_affinity(irq, new_value); + set_intr_affinity(virt_irq, new_value); return full_count; } @@ -1089,18 +1184,18 @@ static int irq_affinity_write_proc (struct file *file, const char __user *buffer #define MAX_NAMELEN 10 -static void register_irq_proc (unsigned int irq) +static void register_irq_proc(unsigned int virt_irq) { char name [MAX_NAMELEN]; - if (!root_irq_dir || irq_dir[irq]) + if (!root_irq_dir || irq_dir[virt_irq]) return; memset(name, 0, MAX_NAMELEN); - sprintf(name, "%x", irq); + sprintf(name, "%d", virt_irq); /* create /proc/irq/1234 */ - irq_dir[irq] = proc_mkdir(name, root_irq_dir); + irq_dir[virt_irq] = proc_mkdir(name, root_irq_dir); #ifdef CONFIG_SMP /* XXX SMP affinity not supported on starfire yet. */ @@ -1112,7 +1207,7 @@ static void register_irq_proc (unsigned int irq) if (entry) { entry->nlink = 1; - entry->data = (void *)(long)irq; + entry->data = (void *)(long)virt_irq; entry->read_proc = irq_affinity_read_proc; entry->write_proc = irq_affinity_write_proc; } @@ -1120,7 +1215,7 @@ static void register_irq_proc (unsigned int irq) #endif } -void init_irq_proc (void) +void init_irq_proc(void) { /* create /proc/irq */ root_irq_dir = proc_mkdir("irq", NULL); diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index 5743e1316a9..f2d1097f541 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -280,7 +280,6 @@ static unsigned int psycho_irq_build(struct pci_pbm_info *pbm, struct pci_dev *pdev, unsigned int ino) { - struct ino_bucket *bucket; unsigned long imap, iclr; unsigned long imap_off, iclr_off; int inofixup = 0; @@ -309,10 +308,7 @@ static unsigned int psycho_irq_build(struct pci_pbm_info *pbm, if ((ino & 0x20) == 0) inofixup = ino & 0x03; - bucket = __bucket(build_irq(inofixup, iclr, imap)); - bucket->flags |= IBF_PCI; - - return __irq(bucket); + return build_irq(inofixup, iclr, imap, IBF_PCI); } /* PSYCHO error handling support. */ diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index caa7aeed5d1..846c1205aa9 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -544,10 +544,10 @@ static unsigned int sabre_irq_build(struct pci_pbm_info *pbm, struct pci_dev *pdev, unsigned int ino) { - struct ino_bucket *bucket; unsigned long imap, iclr; unsigned long imap_off, iclr_off; int inofixup = 0; + int virt_irq; ino &= PCI_IRQ_INO; if (ino < SABRE_ONBOARD_IRQ_BASE) { @@ -573,23 +573,23 @@ static unsigned int sabre_irq_build(struct pci_pbm_info *pbm, if ((ino & 0x20) == 0) inofixup = ino & 0x03; - bucket = __bucket(build_irq(inofixup, iclr, imap)); - bucket->flags |= IBF_PCI; + virt_irq = build_irq(inofixup, iclr, imap, IBF_PCI); if (pdev) { struct pcidev_cookie *pcp = pdev->sysdata; if (pdev->bus->number != pcp->pbm->pci_first_busno) { struct pci_controller_info *p = pcp->pbm->parent; - struct irq_desc *d = bucket->irq_info; - d->pre_handler = sabre_wsync_handler; - d->pre_handler_arg1 = pdev; - d->pre_handler_arg2 = (void *) - p->pbm_A.controller_regs + SABRE_WRSYNC; + irq_install_pre_handler(virt_irq, + sabre_wsync_handler, + pdev, + (void *) + p->pbm_A.controller_regs + + SABRE_WRSYNC); } } - return __irq(bucket); + return virt_irq; } /* SABRE error handling support. */ diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index ca49ef08236..0c400b5fa5b 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c @@ -270,25 +270,33 @@ static void tomatillo_wsync_handler(struct ino_bucket *bucket, void *_arg1, void } } +static unsigned long schizo_ino_to_iclr(struct pci_pbm_info *pbm, + unsigned int ino) +{ + ino &= PCI_IRQ_INO; + return pbm->pbm_regs + schizo_iclr_offset(ino) + 4; +} + +static unsigned long schizo_ino_to_imap(struct pci_pbm_info *pbm, + unsigned int ino) +{ + ino &= PCI_IRQ_INO; + return pbm->pbm_regs + schizo_imap_offset(ino) + 4; +} + static unsigned int schizo_irq_build(struct pci_pbm_info *pbm, struct pci_dev *pdev, unsigned int ino) { - struct ino_bucket *bucket; unsigned long imap, iclr; - unsigned long imap_off, iclr_off; int ign_fixup; + int virt_irq; ino &= PCI_IRQ_INO; - imap_off = schizo_imap_offset(ino); /* Now build the IRQ bucket. */ - imap = pbm->pbm_regs + imap_off; - imap += 4; - - iclr_off = schizo_iclr_offset(ino); - iclr = pbm->pbm_regs + iclr_off; - iclr += 4; + imap = schizo_ino_to_imap(pbm, ino); + iclr = schizo_ino_to_iclr(pbm, ino); /* On Schizo, no inofixup occurs. This is because each * INO has it's own IMAP register. On Psycho and Sabre @@ -305,19 +313,17 @@ static unsigned int schizo_irq_build(struct pci_pbm_info *pbm, ign_fixup = (1 << 6); } - bucket = __bucket(build_irq(ign_fixup, iclr, imap)); - bucket->flags |= IBF_PCI; + virt_irq = build_irq(ign_fixup, iclr, imap, IBF_PCI); if (pdev && pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) { - struct irq_desc *p = bucket->irq_info; - - p->pre_handler = tomatillo_wsync_handler; - p->pre_handler_arg1 = ((pbm->chip_version <= 4) ? - (void *) 1 : (void *) 0); - p->pre_handler_arg2 = (void *) pbm->sync_reg; + irq_install_pre_handler(virt_irq, + tomatillo_wsync_handler, + ((pbm->chip_version <= 4) ? + (void *) 1 : (void *) 0), + (void *) pbm->sync_reg); } - return __irq(bucket); + return virt_irq; } /* SCHIZO error handling support. */ @@ -358,7 +364,6 @@ struct pci_pbm_info *pbm_for_ino(struct pci_controller_info *p, u32 ino) static void schizo_clear_other_err_intr(struct pci_controller_info *p, int irq) { struct pci_pbm_info *pbm; - struct ino_bucket *bucket; unsigned long iclr; /* Do not clear the interrupt for the other PCI bus. @@ -376,11 +381,11 @@ static void schizo_clear_other_err_intr(struct pci_controller_info *p, int irq) else pbm = &p->pbm_A; - irq = schizo_irq_build(pbm, NULL, - (pbm->portid << 6) | (irq & IMAP_INO)); - bucket = __bucket(irq); - iclr = bucket->iclr; + schizo_irq_build(pbm, NULL, + (pbm->portid << 6) | (irq & IMAP_INO)); + iclr = schizo_ino_to_iclr(pbm, + (pbm->portid << 6) | (irq & IMAP_INO)); upa_writel(ICLR_IDLE, iclr); } @@ -1125,7 +1130,6 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p) { struct pci_pbm_info *pbm; unsigned int irq; - struct ino_bucket *bucket; u64 tmp, err_mask, err_no_mask; /* Build IRQs and register handlers. */ @@ -1137,8 +1141,7 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p) pbm->name); prom_halt(); } - bucket = __bucket(irq); - tmp = upa_readl(bucket->imap); + tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_UE_INO)); upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_UE_INO) + 4)); @@ -1150,8 +1153,7 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p) pbm->name); prom_halt(); } - bucket = __bucket(irq); - tmp = upa_readl(bucket->imap); + tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_CE_INO)); upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_CE_INO) + 4)); @@ -1164,8 +1166,8 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p) pbm->name); prom_halt(); } - bucket = __bucket(irq); - tmp = upa_readl(bucket->imap); + tmp = upa_readl(schizo_ino_to_imap(pbm, ((pbm->portid << 6) | + SCHIZO_PCIERR_A_INO))); upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_PCIERR_A_INO) + 4)); @@ -1178,8 +1180,8 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p) pbm->name); prom_halt(); } - bucket = __bucket(irq); - tmp = upa_readl(bucket->imap); + tmp = upa_readl(schizo_ino_to_imap(pbm, ((pbm->portid << 6) | + SCHIZO_PCIERR_B_INO))); upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_PCIERR_B_INO) + 4)); @@ -1191,8 +1193,8 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p) pbm->name); prom_halt(); } - bucket = __bucket(irq); - tmp = upa_readl(bucket->imap); + tmp = upa_readl(schizo_ino_to_imap(pbm, ((pbm->portid << 6) | + SCHIZO_SERR_INO))); upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_SERR_INO) + 4)); @@ -1263,7 +1265,6 @@ static void schizo_register_error_handlers(struct pci_controller_info *p) { struct pci_pbm_info *pbm; unsigned int irq; - struct ino_bucket *bucket; u64 tmp, err_mask, err_no_mask; /* Build IRQs and register handlers. */ @@ -1275,8 +1276,7 @@ static void schizo_register_error_handlers(struct pci_controller_info *p) pbm->name); prom_halt(); } - bucket = __bucket(irq); - tmp = upa_readl(bucket->imap); + tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_UE_INO)); upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_UE_INO) + 4)); pbm = pbm_for_ino(p, SCHIZO_CE_INO); @@ -1287,8 +1287,7 @@ static void schizo_register_error_handlers(struct pci_controller_info *p) pbm->name); prom_halt(); } - bucket = __bucket(irq); - tmp = upa_readl(bucket->imap); + tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_CE_INO)); upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_CE_INO) + 4)); pbm = pbm_for_ino(p, SCHIZO_PCIERR_A_INO); @@ -1299,8 +1298,7 @@ static void schizo_register_error_handlers(struct pci_controller_info *p) pbm->name); prom_halt(); } - bucket = __bucket(irq); - tmp = upa_readl(bucket->imap); + tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_PCIERR_A_INO)); upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_PCIERR_A_INO) + 4)); pbm = pbm_for_ino(p, SCHIZO_PCIERR_B_INO); @@ -1311,8 +1309,7 @@ static void schizo_register_error_handlers(struct pci_controller_info *p) pbm->name); prom_halt(); } - bucket = __bucket(irq); - tmp = upa_readl(bucket->imap); + tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_PCIERR_B_INO)); upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_PCIERR_B_INO) + 4)); pbm = pbm_for_ino(p, SCHIZO_SERR_INO); @@ -1323,8 +1320,7 @@ static void schizo_register_error_handlers(struct pci_controller_info *p) pbm->name); prom_halt(); } - bucket = __bucket(irq); - tmp = upa_readl(bucket->imap); + tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_SERR_INO)); upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_SERR_INO) + 4)); /* Enable UE and CE interrupts for controller. */ diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c index 8812417247d..5544cf5d38b 100644 --- a/arch/sparc64/kernel/sbus.c +++ b/arch/sparc64/kernel/sbus.c @@ -821,7 +821,7 @@ unsigned int sbus_build_irq(void *buscookie, unsigned int ino) iclr += ((unsigned long)sbus_level - 1UL) * 8UL; } - return build_irq(sbus_level, iclr, imap); + return build_irq(sbus_level, iclr, imap, 0); } /* Error interrupt handling. */ diff --git a/include/asm-sparc64/irq.h b/include/asm-sparc64/irq.h index d66c7cd820c..9edcd90495f 100644 --- a/include/asm-sparc64/irq.h +++ b/include/asm-sparc64/irq.h @@ -98,13 +98,22 @@ extern struct ino_bucket ivector_table[NUM_IVECS]; #define __bucket(irq) ((struct ino_bucket *)(unsigned long)(irq)) #define __irq(bucket) ((unsigned int)(unsigned long)(bucket)) -#define NR_IRQS 16 +/* The largest number of unique interrupt sources we support. + * If this needs to ever be larger than 255, you need to change + * the type of ino_bucket->virt_irq as appropriate. + * + * ino_bucket->virt_irq allocation is made during {sun4v_,}build_irq(). + */ +#define NR_IRQS 255 +extern void irq_install_pre_handler(int virt_irq, + void (*func)(struct ino_bucket *, void *, void *), + void *arg1, void *arg2); #define irq_canonicalize(irq) (irq) extern void disable_irq(unsigned int); #define disable_irq_nosync disable_irq extern void enable_irq(unsigned int); -extern unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap); +extern unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap, unsigned char flags); extern unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino, unsigned char flags); extern unsigned int sbus_build_irq(void *sbus, unsigned int ino); -- cgit v1.2.3 From e18e2a00efc8352c131eb8d5a460149fb5776f1c Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 20 Jun 2006 01:23:32 -0700 Subject: [SPARC64]: Move over to GENERIC_HARDIRQS. This is the long overdue conversion of sparc64 over to the generic IRQ layer. The kernel image is slightly larger, but the BSS is ~60K smaller due to the reduced size of struct ino_bucket. A lot of IRQ implementation details, including ino_bucket, were moved out of asm-sparc64/irq.h and are now private to arch/sparc64/kernel/irq.c, and most of the code in irq.c totally disappeared. One thing that's different at the moment is IRQ distribution, we do it at enable_irq() time. If the cpu mask is ALL then we round-robin using a global rotating cpu counter, else we pick the first cpu in the mask to support single cpu targetting. This is similar to what powerpc's XICS IRQ support code does. This works fine on my UP SB1000, and the SMP build goes fine and runs on that machine, but lots of testing on different setups is needed. Signed-off-by: David S. Miller --- arch/sparc64/Kconfig | 4 + arch/sparc64/kernel/devices.c | 2 +- arch/sparc64/kernel/entry.S | 2 +- arch/sparc64/kernel/irq.c | 957 +++++++++++------------------------- arch/sparc64/kernel/pci.c | 38 -- arch/sparc64/kernel/pci_psycho.c | 2 +- arch/sparc64/kernel/pci_sabre.c | 4 +- arch/sparc64/kernel/pci_schizo.c | 6 +- arch/sparc64/kernel/pci_sun4v.c | 2 +- arch/sparc64/kernel/sbus.c | 2 +- arch/sparc64/kernel/sparc64_ksyms.c | 4 - arch/sparc64/kernel/sun4v_ivec.S | 2 +- include/asm-sparc64/hardirq.h | 2 + include/asm-sparc64/hw_irq.h | 2 +- include/asm-sparc64/irq.h | 78 +-- 15 files changed, 305 insertions(+), 802 deletions(-) diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig index 43a66f5407f..a7a111db25b 100644 --- a/arch/sparc64/Kconfig +++ b/arch/sparc64/Kconfig @@ -87,6 +87,10 @@ config SYSVIPC_COMPAT depends on COMPAT && SYSVIPC default y +config GENERIC_HARDIRQS + bool + default y + menu "General machine setup" config SMP diff --git a/arch/sparc64/kernel/devices.c b/arch/sparc64/kernel/devices.c index 0684899d998..0dd95ae50e1 100644 --- a/arch/sparc64/kernel/devices.c +++ b/arch/sparc64/kernel/devices.c @@ -157,7 +157,7 @@ unsigned int sun4v_vdev_device_interrupt(unsigned int dev_node) return 0; } - return sun4v_build_irq(sun4v_vdev_devhandle, irq, 0); + return sun4v_build_irq(sun4v_vdev_devhandle, irq); } static const char *cpu_mid_prop(void) diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S index c87365e59e7..be85ce2a4ad 100644 --- a/arch/sparc64/kernel/entry.S +++ b/arch/sparc64/kernel/entry.S @@ -432,7 +432,7 @@ do_ivec: membar #Sync sethi %hi(ivector_table), %g2 - sllx %g3, 5, %g3 + sllx %g3, 3, %g3 or %g2, %lo(ivector_table), %g2 add %g2, %g3, %g3 diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index 49ad9cd0f8c..a8c9dc8d195 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -42,10 +43,6 @@ #include #include -#ifdef CONFIG_SMP -static void distribute_irqs(void); -#endif - /* UPA nodes send interrupt packet to UltraSparc with first data reg * value low 5 (7 on Starfire) bits holding the IRQ identifier being * delivered. We must translate this into a non-vector IRQ so we can @@ -57,10 +54,29 @@ static void distribute_irqs(void); * The IVEC handler does not need to act atomically, the PIL dispatch * code uses CAS to get an atomic snapshot of the list and clear it * at the same time. + * + * If you make changes to ino_bucket, please update hand coded assembler + * of the vectored interrupt trap handler(s) in entry.S and sun4v_ivec.S */ +struct ino_bucket { + /* Next handler in per-CPU IRQ worklist. We know that + * bucket pointers have the high 32-bits clear, so to + * save space we only store the bits we need. + */ +/*0x00*/unsigned int irq_chain; + /* Virtual interrupt number assigned to this INO. */ +/*0x04*/unsigned int virt_irq; +}; + +#define NUM_IVECS (IMAP_INR + 1) struct ino_bucket ivector_table[NUM_IVECS] __attribute__ ((aligned (SMP_CACHE_BYTES))); +#define __irq_ino(irq) \ + (((struct ino_bucket *)(unsigned long)(irq)) - &ivector_table[0]) +#define __bucket(irq) ((struct ino_bucket *)(unsigned long)(irq)) +#define __irq(bucket) ((unsigned int)(unsigned long)(bucket)) + /* This has to be in the main kernel image, it cannot be * turned into per-cpu data. The reason is that the main * kernel image is locked into the TLB and this structure @@ -70,18 +86,6 @@ struct ino_bucket ivector_table[NUM_IVECS] __attribute__ ((aligned (SMP_CACHE_BY */ #define irq_work(__cpu) &(trap_block[(__cpu)].irq_worklist) -static struct irqaction timer_irq_action = { - .name = "timer", -}; -static struct irqaction *irq_action[NR_IRQS] = { &timer_irq_action, }; - -/* This only synchronizes entities which modify IRQ handler - * state and some selected user-level spots that want to - * read things in the table. IRQ handler processing orders - * its' accesses such that no locking is needed. - */ -static DEFINE_SPINLOCK(irq_action_lock); - static unsigned int virt_to_real_irq_table[NR_IRQS]; static unsigned char virt_irq_cur = 1; @@ -117,69 +121,45 @@ static unsigned int virt_to_real_irq(unsigned char virt_irq) return virt_to_real_irq_table[virt_irq]; } -void irq_install_pre_handler(int virt_irq, - void (*func)(struct ino_bucket *, void *, void *), - void *arg1, void *arg2) -{ - unsigned int real_irq = virt_to_real_irq(virt_irq); - struct ino_bucket *bucket; - struct irq_desc *d; - - if (unlikely(!real_irq)) - return; - - bucket = __bucket(real_irq); - d = bucket->irq_info; - d->pre_handler = func; - d->pre_handler_arg1 = arg1; - d->pre_handler_arg2 = arg2; -} - -static void register_irq_proc (unsigned int irq); - /* - * Upper 2b of irqaction->flags holds the ino. - * irqaction->mask holds the smp affinity information. + * /proc/interrupts printing: */ -#define put_ino_in_irqaction(action, irq) \ - action->flags &= 0xffffffffffffUL; \ - action->flags |= __irq_ino(irq) << 48; - -#define get_ino_in_irqaction(action) (action->flags >> 48) - -#define put_smpaff_in_irqaction(action, smpaff) (action)->mask = (smpaff) -#define get_smpaff_in_irqaction(action) ((action)->mask) int show_interrupts(struct seq_file *p, void *v) { + int i = *(loff_t *) v, j; + struct irqaction * action; unsigned long flags; - int i = *(loff_t *) v; - struct irqaction *action; -#ifdef CONFIG_SMP - int j; -#endif - spin_lock_irqsave(&irq_action_lock, flags); - if (i <= NR_IRQS) { - if (!(action = *(i + irq_action))) - goto out_unlock; - seq_printf(p, "%3d: ", i); + if (i == 0) { + seq_printf(p, " "); + for_each_online_cpu(j) + seq_printf(p, "CPU%d ",j); + seq_putc(p, '\n'); + } + + if (i < NR_IRQS) { + spin_lock_irqsave(&irq_desc[i].lock, flags); + action = irq_desc[i].action; + if (!action) + goto skip; + seq_printf(p, "%3d: ",i); #ifndef CONFIG_SMP seq_printf(p, "%10u ", kstat_irqs(i)); #else - for_each_online_cpu(j) { - seq_printf(p, "%10u ", - kstat_cpu(j).irqs[i]); - } + for_each_online_cpu(j) + seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); #endif - seq_printf(p, " %s", action->name); - for (action = action->next; action; action = action->next) + seq_printf(p, " %9s", irq_desc[i].handler->typename); + seq_printf(p, " %s", action->name); + + for (action=action->next; action; action = action->next) seq_printf(p, ", %s", action->name); + seq_putc(p, '\n'); +skip: + spin_unlock_irqrestore(&irq_desc[i].lock, flags); } -out_unlock: - spin_unlock_irqrestore(&irq_action_lock, flags); - return 0; } @@ -220,509 +200,321 @@ static unsigned int sun4u_compute_tid(unsigned long imap, unsigned long cpuid) return tid; } -void enable_irq(unsigned int virt_irq) -{ - unsigned int real_irq = virt_to_real_irq(virt_irq); - struct ino_bucket *bucket; - unsigned long imap, cpuid; - - if (unlikely(!real_irq)) - return; +struct irq_handler_data { + unsigned long iclr; + unsigned long imap; - bucket = __bucket(real_irq); - imap = bucket->imap; - if (unlikely(imap == 0UL)) - return; - - preempt_disable(); - - /* This gets the physical processor ID, even on uniprocessor, - * so we can always program the interrupt target correctly. - */ - cpuid = real_hard_smp_processor_id(); - - if (tlb_type == hypervisor) { - unsigned int ino = __irq_ino(real_irq); - int err; - - err = sun4v_intr_settarget(ino, cpuid); - if (err != HV_EOK) - printk("sun4v_intr_settarget(%x,%lu): err(%d)\n", - ino, cpuid, err); - err = sun4v_intr_setenabled(ino, HV_INTR_ENABLED); - if (err != HV_EOK) - printk("sun4v_intr_setenabled(%x): err(%d)\n", - ino, err); - } else { - unsigned int tid = sun4u_compute_tid(imap, cpuid); - - /* NOTE NOTE NOTE, IGN and INO are read-only, IGN is a product - * of this SYSIO's preconfigured IGN in the SYSIO Control - * Register, the hardware just mirrors that value here. - * However for Graphics and UPA Slave devices the full - * IMAP_INR field can be set by the programmer here. - * - * Things like FFB can now be handled via the new IRQ - * mechanism. - */ - upa_writel(tid | IMAP_VALID, imap); - } - - preempt_enable(); -} + void (*pre_handler)(unsigned int, void *, void *); + void *pre_handler_arg1; + void *pre_handler_arg2; +}; -void disable_irq(unsigned int virt_irq) +static inline struct ino_bucket *virt_irq_to_bucket(unsigned int virt_irq) { unsigned int real_irq = virt_to_real_irq(virt_irq); - struct ino_bucket *bucket; - unsigned long imap; + struct ino_bucket *bucket = NULL; - if (unlikely(!real_irq)) - return; - - bucket = __bucket(real_irq); - imap = bucket->imap; - if (unlikely(imap == 0UL)) - return; - - if (tlb_type == hypervisor) { - unsigned int ino = __irq_ino(real_irq); - int err; + if (likely(real_irq)) + bucket = __bucket(real_irq); - err = sun4v_intr_setenabled(ino, HV_INTR_DISABLED); - if (err != HV_EOK) - printk("sun4v_intr_setenabled(%x): " - "err(%d)\n", ino, err); - } else { - u32 tmp; - - /* NOTE: We do not want to futz with the IRQ clear registers - * and move the state to IDLE, the SCSI code does call - * disable_irq() to assure atomicity in the queue cmd - * SCSI adapter driver code. Thus we'd lose interrupts. - */ - tmp = upa_readl(imap); - tmp &= ~IMAP_VALID; - upa_writel(tmp, imap); - } + return bucket; } -static void build_irq_error(const char *msg, unsigned int ino, int inofixup, - unsigned long iclr, unsigned long imap, - struct ino_bucket *bucket) +#ifdef CONFIG_SMP +static int irq_choose_cpu(unsigned int virt_irq) { - prom_printf("IRQ: INO %04x (%016lx:%016lx) --> " - "(%d:%016lx:%016lx), halting...\n", - ino, bucket->iclr, bucket->imap, - inofixup, iclr, imap); - prom_halt(); -} + cpumask_t mask = irq_affinity[virt_irq]; + int cpuid; -unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap, unsigned char flags) -{ - struct ino_bucket *bucket; - int ino; + if (cpus_equal(mask, CPU_MASK_ALL)) { + static int irq_rover; + static DEFINE_SPINLOCK(irq_rover_lock); + unsigned long flags; - BUG_ON(tlb_type == hypervisor); + /* Round-robin distribution... */ + do_round_robin: + spin_lock_irqsave(&irq_rover_lock, flags); - /* RULE: Both must be specified. */ - if (iclr == 0UL || imap == 0UL) { - prom_printf("Invalid build_irq %d %016lx %016lx\n", - inofixup, iclr, imap); - prom_halt(); - } - - ino = (upa_readl(imap) & (IMAP_IGN | IMAP_INO)) + inofixup; - if (ino > NUM_IVECS) { - prom_printf("Invalid INO %04x (%d:%016lx:%016lx)\n", - ino, inofixup, iclr, imap); - prom_halt(); - } + while (!cpu_online(irq_rover)) { + if (++irq_rover >= NR_CPUS) + irq_rover = 0; + } + cpuid = irq_rover; + do { + if (++irq_rover >= NR_CPUS) + irq_rover = 0; + } while (!cpu_online(irq_rover)); - bucket = &ivector_table[ino]; - if (bucket->flags & IBF_ACTIVE) - build_irq_error("IRQ: Trying to build active INO bucket.\n", - ino, inofixup, iclr, imap, bucket); + spin_unlock_irqrestore(&irq_rover_lock, flags); + } else { + cpumask_t tmp; - if (bucket->irq_info) { - if (bucket->imap != imap || bucket->iclr != iclr) - build_irq_error("IRQ: Trying to reinit INO bucket.\n", - ino, inofixup, iclr, imap, bucket); + cpus_and(tmp, cpu_online_map, mask); - goto out; - } + if (cpus_empty(tmp)) + goto do_round_robin; - bucket->irq_info = kzalloc(sizeof(struct irq_desc), GFP_ATOMIC); - if (!bucket->irq_info) { - prom_printf("IRQ: Error, kmalloc(irq_desc) failed.\n"); - prom_halt(); + cpuid = first_cpu(tmp); } - /* Ok, looks good, set it up. Don't touch the irq_chain or - * the pending flag. - */ - bucket->imap = imap; - bucket->iclr = iclr; - if (!bucket->virt_irq) - bucket->virt_irq = virt_irq_alloc(__irq(bucket)); - bucket->flags = flags; - -out: - return bucket->virt_irq; + return cpuid; +} +#else +static int irq_choose_cpu(unsigned int virt_irq) +{ + return real_hard_smp_processor_id(); } +#endif -unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino, unsigned char flags) +static void sun4u_irq_enable(unsigned int virt_irq) { - struct ino_bucket *bucket; - unsigned long sysino; + irq_desc_t *desc = irq_desc + virt_irq; + struct irq_handler_data *data = desc->handler_data; - sysino = sun4v_devino_to_sysino(devhandle, devino); + if (likely(data)) { + unsigned long cpuid, imap; + unsigned int tid; - bucket = &ivector_table[sysino]; + cpuid = irq_choose_cpu(virt_irq); + imap = data->imap; - /* Catch accidental accesses to these things. IMAP/ICLR handling - * is done by hypervisor calls on sun4v platforms, not by direct - * register accesses. - * - * But we need to make them look unique for the disable_irq() logic - * in free_irq(). - */ - bucket->imap = ~0UL - sysino; - bucket->iclr = ~0UL - sysino; - if (!bucket->virt_irq) - bucket->virt_irq = virt_irq_alloc(__irq(bucket)); - bucket->flags = flags; + tid = sun4u_compute_tid(imap, cpuid); - bucket->irq_info = kzalloc(sizeof(struct irq_desc), GFP_ATOMIC); - if (!bucket->irq_info) { - prom_printf("IRQ: Error, kmalloc(irq_desc) failed.\n"); - prom_halt(); + upa_writel(tid | IMAP_VALID, imap); } - - return bucket->virt_irq; } -static void atomic_bucket_insert(struct ino_bucket *bucket) +static void sun4u_irq_disable(unsigned int virt_irq) { - unsigned long pstate; - unsigned int *ent; + irq_desc_t *desc = irq_desc + virt_irq; + struct irq_handler_data *data = desc->handler_data; - __asm__ __volatile__("rdpr %%pstate, %0" : "=r" (pstate)); - __asm__ __volatile__("wrpr %0, %1, %%pstate" - : : "r" (pstate), "i" (PSTATE_IE)); - ent = irq_work(smp_processor_id()); - bucket->irq_chain = *ent; - *ent = __irq(bucket); - __asm__ __volatile__("wrpr %0, 0x0, %%pstate" : : "r" (pstate)); -} + if (likely(data)) { + unsigned long imap = data->imap; + u32 tmp = upa_readl(imap); -static int check_irq_sharing(int pil, unsigned long irqflags) -{ - struct irqaction *action; - - action = *(irq_action + pil); - if (action) { - if (!(action->flags & SA_SHIRQ) || !(irqflags & SA_SHIRQ)) - return -EBUSY; + tmp &= ~IMAP_VALID; + upa_writel(tmp, imap); } - return 0; } -static void append_irq_action(int pil, struct irqaction *action) +static void sun4u_irq_end(unsigned int virt_irq) { - struct irqaction **pp = irq_action + pil; + irq_desc_t *desc = irq_desc + virt_irq; + struct irq_handler_data *data = desc->handler_data; - while (*pp) - pp = &((*pp)->next); - *pp = action; + if (likely(data)) + upa_writel(ICLR_IDLE, data->iclr); } -static struct irqaction *get_action_slot(struct ino_bucket *bucket) +static void sun4v_irq_enable(unsigned int virt_irq) { - struct irq_desc *desc = bucket->irq_info; - int max_irq, i; + struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); + unsigned int ino = bucket - &ivector_table[0]; - max_irq = 1; - if (bucket->flags & IBF_PCI) - max_irq = MAX_IRQ_DESC_ACTION; - for (i = 0; i < max_irq; i++) { - struct irqaction *p = &desc->action[i]; - u32 mask = (1 << i); + if (likely(bucket)) { + unsigned long cpuid; + int err; - if (desc->action_active_mask & mask) - continue; + cpuid = irq_choose_cpu(virt_irq); - desc->action_active_mask |= mask; - return p; + err = sun4v_intr_settarget(ino, cpuid); + if (err != HV_EOK) + printk("sun4v_intr_settarget(%x,%lu): err(%d)\n", + ino, cpuid, err); + err = sun4v_intr_setenabled(ino, HV_INTR_ENABLED); + if (err != HV_EOK) + printk("sun4v_intr_setenabled(%x): err(%d)\n", + ino, err); } - return NULL; } -int request_irq(unsigned int virt_irq, - irqreturn_t (*handler)(int, void *, struct pt_regs *), - unsigned long irqflags, const char *name, void *dev_id) +static void sun4v_irq_disable(unsigned int virt_irq) { - struct irqaction *action; - struct ino_bucket *bucket; - unsigned long flags; - unsigned int real_irq; - int pending = 0; - - real_irq = virt_to_real_irq(virt_irq); - if (unlikely(!real_irq)) - return -EINVAL; - - if (unlikely(!handler)) - return -EINVAL; - - bucket = __bucket(real_irq); - if (unlikely(!bucket->irq_info)) - return -ENODEV; - - if (irqflags & SA_SAMPLE_RANDOM) { - /* - * This function might sleep, we want to call it first, - * outside of the atomic block. - * Yes, this might clear the entropy pool if the wrong - * driver is attempted to be loaded, without actually - * installing a new handler, but is this really a problem, - * only the sysadmin is able to do this. - */ - rand_initialize_irq(virt_irq); - } - - spin_lock_irqsave(&irq_action_lock, flags); + struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); + unsigned int ino = bucket - &ivector_table[0]; - if (check_irq_sharing(virt_irq, irqflags)) { - spin_unlock_irqrestore(&irq_action_lock, flags); - return -EBUSY; - } + if (likely(bucket)) { + int err; - action = get_action_slot(bucket); - if (!action) { - spin_unlock_irqrestore(&irq_action_lock, flags); - return -ENOMEM; + err = sun4v_intr_setenabled(ino, HV_INTR_DISABLED); + if (err != HV_EOK) + printk("sun4v_intr_setenabled(%x): " + "err(%d)\n", ino, err); } +} - bucket->flags |= IBF_ACTIVE; - pending = bucket->pending; - if (pending) - bucket->pending = 0; - - action->handler = handler; - action->flags = irqflags; - action->name = name; - action->next = NULL; - action->dev_id = dev_id; - put_ino_in_irqaction(action, __irq_ino(real_irq)); - put_smpaff_in_irqaction(action, CPU_MASK_NONE); - - append_irq_action(virt_irq, action); +static void sun4v_irq_end(unsigned int virt_irq) +{ + struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); + unsigned int ino = bucket - &ivector_table[0]; - enable_irq(virt_irq); + if (likely(bucket)) { + int err; - /* We ate the IVEC already, this makes sure it does not get lost. */ - if (pending) { - atomic_bucket_insert(bucket); - set_softint(1 << PIL_DEVICE_IRQ); + err = sun4v_intr_setstate(ino, HV_INTR_STATE_IDLE); + if (err != HV_EOK) + printk("sun4v_intr_setstate(%x): " + "err(%d)\n", ino, err); } - - spin_unlock_irqrestore(&irq_action_lock, flags); - - register_irq_proc(virt_irq); - -#ifdef CONFIG_SMP - distribute_irqs(); -#endif - return 0; } -EXPORT_SYMBOL(request_irq); - -static struct irqaction *unlink_irq_action(unsigned int virt_irq, void *dev_id) +static void run_pre_handler(unsigned int virt_irq) { - struct irqaction *action, **pp; - - pp = irq_action + virt_irq; - action = *pp; - if (unlikely(!action)) - return NULL; + struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); + irq_desc_t *desc = irq_desc + virt_irq; + struct irq_handler_data *data = desc->handler_data; - if (unlikely(!action->handler)) { - printk("Freeing free IRQ %d\n", virt_irq); - return NULL; + if (likely(data->pre_handler)) { + data->pre_handler(__irq_ino(__irq(bucket)), + data->pre_handler_arg1, + data->pre_handler_arg2); } - - while (action && action->dev_id != dev_id) { - pp = &action->next; - action = *pp; - } - - if (likely(action)) - *pp = action->next; - - return action; } -void free_irq(unsigned int virt_irq, void *dev_id) -{ - struct irqaction *action; - struct ino_bucket *bucket; - struct irq_desc *desc; - unsigned long flags; - unsigned int real_irq; - int ent, i; - - real_irq = virt_to_real_irq(virt_irq); - if (unlikely(!real_irq)) - return; +static struct hw_interrupt_type sun4u_irq = { + .typename = "sun4u", + .enable = sun4u_irq_enable, + .disable = sun4u_irq_disable, + .end = sun4u_irq_end, +}; - spin_lock_irqsave(&irq_action_lock, flags); +static struct hw_interrupt_type sun4u_irq_ack = { + .typename = "sun4u+ack", + .enable = sun4u_irq_enable, + .disable = sun4u_irq_disable, + .ack = run_pre_handler, + .end = sun4u_irq_end, +}; - action = unlink_irq_action(virt_irq, dev_id); +static struct hw_interrupt_type sun4v_irq = { + .typename = "sun4v", + .enable = sun4v_irq_enable, + .disable = sun4v_irq_disable, + .end = sun4v_irq_end, +}; - spin_unlock_irqrestore(&irq_action_lock, flags); +static struct hw_interrupt_type sun4v_irq_ack = { + .typename = "sun4v+ack", + .enable = sun4v_irq_enable, + .disable = sun4v_irq_disable, + .ack = run_pre_handler, + .end = sun4v_irq_end, +}; - if (unlikely(!action)) - return; +void irq_install_pre_handler(int virt_irq, + void (*func)(unsigned int, void *, void *), + void *arg1, void *arg2) +{ + irq_desc_t *desc = irq_desc + virt_irq; + struct irq_handler_data *data = desc->handler_data; - synchronize_irq(virt_irq); + data->pre_handler = func; + data->pre_handler_arg1 = arg1; + data->pre_handler_arg2 = arg2; - spin_lock_irqsave(&irq_action_lock, flags); + desc->handler = (desc->handler == &sun4u_irq ? + &sun4u_irq_ack : &sun4v_irq_ack); +} - bucket = __bucket(real_irq); - desc = bucket->irq_info; +unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap) +{ + struct ino_bucket *bucket; + struct irq_handler_data *data; + irq_desc_t *desc; + int ino; - for (i = 0; i < MAX_IRQ_DESC_ACTION; i++) { - struct irqaction *p = &desc->action[i]; + BUG_ON(tlb_type == hypervisor); - if (p == action) { - desc->action_active_mask &= ~(1 << i); - break; - } + ino = (upa_readl(imap) & (IMAP_IGN | IMAP_INO)) + inofixup; + bucket = &ivector_table[ino]; + if (!bucket->virt_irq) { + bucket->virt_irq = virt_irq_alloc(__irq(bucket)); + irq_desc[bucket->virt_irq].handler = &sun4u_irq; } - if (!desc->action_active_mask) { - unsigned long imap = bucket->imap; - - /* This unique interrupt source is now inactive. */ - bucket->flags &= ~IBF_ACTIVE; - - /* See if any other buckets share this bucket's IMAP - * and are still active. - */ - for (ent = 0; ent < NUM_IVECS; ent++) { - struct ino_bucket *bp = &ivector_table[ent]; - if (bp != bucket && - bp->imap == imap && - (bp->flags & IBF_ACTIVE) != 0) - break; - } + desc = irq_desc + bucket->virt_irq; + if (unlikely(desc->handler_data)) + goto out; - /* Only disable when no other sub-irq levels of - * the same IMAP are active. - */ - if (ent == NUM_IVECS) - disable_irq(virt_irq); + data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC); + if (unlikely(!data)) { + prom_printf("IRQ: kzalloc(irq_handler_data) failed.\n"); + prom_halt(); } + desc->handler_data = data; - spin_unlock_irqrestore(&irq_action_lock, flags); -} + data->imap = imap; + data->iclr = iclr; -EXPORT_SYMBOL(free_irq); +out: + return bucket->virt_irq; +} -#ifdef CONFIG_SMP -void synchronize_irq(unsigned int virt_irq) +unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino) { - unsigned int real_irq = virt_to_real_irq(virt_irq); struct ino_bucket *bucket; + struct irq_handler_data *data; + unsigned long sysino; + irq_desc_t *desc; - if (unlikely(!real_irq)) - return; + BUG_ON(tlb_type != hypervisor); - bucket = __bucket(real_irq); -#if 0 - /* The following is how I wish I could implement this. - * Unfortunately the ICLR registers are read-only, you can - * only write ICLR_foo values to them. To get the current - * IRQ status you would need to get at the IRQ diag registers - * in the PCI/SBUS controller and the layout of those vary - * from one controller to the next, sigh... -DaveM - */ - unsigned long iclr = bucket->iclr; - - while (1) { - u32 tmp = upa_readl(iclr); - - if (tmp == ICLR_TRANSMIT || - tmp == ICLR_PENDING) { - cpu_relax(); - continue; - } - break; + sysino = sun4v_devino_to_sysino(devhandle, devino); + bucket = &ivector_table[sysino]; + if (!bucket->virt_irq) { + bucket->virt_irq = virt_irq_alloc(__irq(bucket)); + irq_desc[bucket->virt_irq].handler = &sun4v_irq; } -#else - /* So we have to do this with a INPROGRESS bit just like x86. */ - while (bucket->flags & IBF_INPROGRESS) - cpu_relax(); -#endif -} -#endif /* CONFIG_SMP */ - -static void process_bucket(struct ino_bucket *bp, struct pt_regs *regs) -{ - struct irq_desc *desc = bp->irq_info; - unsigned char flags = bp->flags; - u32 action_mask, i; - int random; - - bp->flags |= IBF_INPROGRESS; - if (unlikely(!(flags & IBF_ACTIVE))) { - bp->pending = 1; + desc = irq_desc + bucket->virt_irq; + if (unlikely(desc->handler_data)) goto out; - } - - if (desc->pre_handler) - desc->pre_handler(bp, - desc->pre_handler_arg1, - desc->pre_handler_arg2); - action_mask = desc->action_active_mask; - random = 0; - for (i = 0; i < MAX_IRQ_DESC_ACTION; i++) { - struct irqaction *p = &desc->action[i]; - u32 mask = (1 << i); + data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC); + if (unlikely(!data)) { + prom_printf("IRQ: kzalloc(irq_handler_data) failed.\n"); + prom_halt(); + } + desc->handler_data = data; - if (!(action_mask & mask)) - continue; + /* Catch accidental accesses to these things. IMAP/ICLR handling + * is done by hypervisor calls on sun4v platforms, not by direct + * register accesses. + */ + data->imap = ~0UL; + data->iclr = ~0UL; - action_mask &= ~mask; +out: + return bucket->virt_irq; +} - if (p->handler(bp->virt_irq, p->dev_id, regs) == IRQ_HANDLED) - random |= p->flags; +void hw_resend_irq(struct hw_interrupt_type *handler, unsigned int virt_irq) +{ + struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); + unsigned long pstate; + unsigned int *ent; - if (!action_mask) - break; - } + __asm__ __volatile__("rdpr %%pstate, %0" : "=r" (pstate)); + __asm__ __volatile__("wrpr %0, %1, %%pstate" + : : "r" (pstate), "i" (PSTATE_IE)); + ent = irq_work(smp_processor_id()); + bucket->irq_chain = *ent; + *ent = __irq(bucket); + set_softint(1 << PIL_DEVICE_IRQ); + __asm__ __volatile__("wrpr %0, 0x0, %%pstate" : : "r" (pstate)); +} - if (tlb_type == hypervisor) { - unsigned int ino = __irq_ino(bp); - int err; +void ack_bad_irq(unsigned int virt_irq) +{ + struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); + unsigned int ino = 0xdeadbeef; - err = sun4v_intr_setstate(ino, HV_INTR_STATE_IDLE); - if (err != HV_EOK) - printk("sun4v_intr_setstate(%x): " - "err(%d)\n", ino, err); - } else { - upa_writel(ICLR_IDLE, bp->iclr); - } + if (bucket) + ino = bucket - &ivector_table[0]; - /* Test and add entropy */ - if (random & SA_SAMPLE_RANDOM) - add_interrupt_randomness(bp->virt_irq); -out: - bp->flags &= ~IBF_INPROGRESS; + printk(KERN_CRIT "Unexpected IRQ from ino[%x] virt_irq[%u]\n", + ino, virt_irq); } #ifndef CONFIG_SMP @@ -740,35 +532,33 @@ void timer_irq(int irq, struct pt_regs *regs) clear_softint(clr_mask); irq_enter(); + kstat_this_cpu.irqs[0]++; timer_interrupt(irq, NULL, regs); + irq_exit(); } #endif void handler_irq(int irq, struct pt_regs *regs) { - struct ino_bucket *bp; - int cpu = smp_processor_id(); + struct ino_bucket *bucket; - /* XXX at this point we should be able to assert that - * XXX irq is PIL_DEVICE_IRQ... - */ clear_softint(1 << irq); irq_enter(); /* Sliiiick... */ - bp = __bucket(xchg32(irq_work(cpu), 0)); - while (bp) { - struct ino_bucket *nbp = __bucket(bp->irq_chain); + bucket = __bucket(xchg32(irq_work(smp_processor_id()), 0)); + while (bucket) { + struct ino_bucket *next = __bucket(bucket->irq_chain); - kstat_this_cpu.irqs[bp->virt_irq]++; + bucket->irq_chain = 0; + __do_IRQ(bucket->virt_irq, regs); - bp->irq_chain = 0; - process_bucket(bp, regs); - bp = nbp; + bucket = next; } + irq_exit(); } @@ -833,74 +623,6 @@ main_interrupt: EXPORT_SYMBOL(sparc_floppy_irq); #endif -/* We really don't need these at all on the Sparc. We only have - * stubs here because they are exported to modules. - */ -unsigned long probe_irq_on(void) -{ - return 0; -} - -EXPORT_SYMBOL(probe_irq_on); - -int probe_irq_off(unsigned long mask) -{ - return 0; -} - -EXPORT_SYMBOL(probe_irq_off); - -#ifdef CONFIG_SMP -static int retarget_one_irq(struct irqaction *p, int goal_cpu) -{ - struct ino_bucket *bucket = get_ino_in_irqaction(p) + ivector_table; - - while (!cpu_online(goal_cpu)) { - if (++goal_cpu >= NR_CPUS) - goal_cpu = 0; - } - - if (tlb_type == hypervisor) { - unsigned int ino = __irq_ino(bucket); - - sun4v_intr_settarget(ino, goal_cpu); - sun4v_intr_setenabled(ino, HV_INTR_ENABLED); - } else { - unsigned long imap = bucket->imap; - unsigned int tid = sun4u_compute_tid(imap, goal_cpu); - - upa_writel(tid | IMAP_VALID, imap); - } - - do { - if (++goal_cpu >= NR_CPUS) - goal_cpu = 0; - } while (!cpu_online(goal_cpu)); - - return goal_cpu; -} - -/* Called from request_irq. */ -static void distribute_irqs(void) -{ - unsigned long flags; - int cpu, level; - - spin_lock_irqsave(&irq_action_lock, flags); - cpu = 0; - - for (level = 1; level < NR_IRQS; level++) { - struct irqaction *p = irq_action[level]; - - while(p) { - cpu = retarget_one_irq(p, cpu); - p = p->next; - } - } - spin_unlock_irqrestore(&irq_action_lock, flags); -} -#endif - struct sun5_timer { u64 count0; u64 limit0; @@ -1076,6 +798,10 @@ void __cpuinit sun4v_init_mondo_queues(int use_bootmem, int cpu, int alloc, int } } +static struct irqaction timer_irq_action = { + .name = "timer", +}; + /* Only invoked on boot processor. */ void __init init_IRQ(void) { @@ -1103,121 +829,6 @@ void __init init_IRQ(void) : /* No outputs */ : "i" (PSTATE_IE) : "g1"); -} -static struct proc_dir_entry *root_irq_dir; -static struct proc_dir_entry *irq_dir[NR_IRQS]; - -#ifdef CONFIG_SMP - -static int irq_affinity_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - struct ino_bucket *bp = ivector_table + (long)data; - struct irq_desc *desc = bp->irq_info; - struct irqaction *ap = desc->action; - cpumask_t mask; - int len; - - mask = get_smpaff_in_irqaction(ap); - if (cpus_empty(mask)) - mask = cpu_online_map; - - len = cpumask_scnprintf(page, count, mask); - if (count - len < 2) - return -EINVAL; - len += sprintf(page + len, "\n"); - return len; + irq_desc[0].action = &timer_irq_action; } - -static inline void set_intr_affinity(int virt_irq, cpumask_t hw_aff) -{ - struct ino_bucket *bp; - struct irq_desc *desc; - struct irqaction *ap; - unsigned int real_irq; - - real_irq = virt_to_real_irq(virt_irq); - if (unlikely(!real_irq)) - return; - - bp = __bucket(real_irq); - desc = bp->irq_info; - ap = desc->action; - - /* Users specify affinity in terms of hw cpu ids. - * As soon as we do this, handler_irq() might see and take action. - */ - put_smpaff_in_irqaction(ap, hw_aff); - - /* Migration is simply done by the next cpu to service this - * interrupt. - * - * XXX Broken, this doesn't happen anymore... - */ -} - -static int irq_affinity_write_proc(struct file *file, - const char __user *buffer, - unsigned long count, void *data) -{ - int virt_irq = (long) data, full_count = count, err; - cpumask_t new_value; - - err = cpumask_parse(buffer, count, new_value); - - /* - * Do not allow disabling IRQs completely - it's a too easy - * way to make the system unusable accidentally :-) At least - * one online CPU still has to be targeted. - */ - cpus_and(new_value, new_value, cpu_online_map); - if (cpus_empty(new_value)) - return -EINVAL; - - set_intr_affinity(virt_irq, new_value); - - return full_count; -} - -#endif - -#define MAX_NAMELEN 10 - -static void register_irq_proc(unsigned int virt_irq) -{ - char name [MAX_NAMELEN]; - - if (!root_irq_dir || irq_dir[virt_irq]) - return; - - memset(name, 0, MAX_NAMELEN); - sprintf(name, "%d", virt_irq); - - /* create /proc/irq/1234 */ - irq_dir[virt_irq] = proc_mkdir(name, root_irq_dir); - -#ifdef CONFIG_SMP - /* XXX SMP affinity not supported on starfire yet. */ - if (this_is_starfire == 0) { - struct proc_dir_entry *entry; - - /* create /proc/irq/1234/smp_affinity */ - entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]); - - if (entry) { - entry->nlink = 1; - entry->data = (void *)(long)virt_irq; - entry->read_proc = irq_affinity_read_proc; - entry->write_proc = irq_affinity_write_proc; - } - } -#endif -} - -void init_irq_proc(void) -{ - /* create /proc/irq */ - root_irq_dir = proc_mkdir("irq", NULL); -} - diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index f97ddeb105a..9472580a431 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -47,12 +47,6 @@ struct pci_controller_info *pci_controller_root = NULL; /* Each PCI controller found gets a unique index. */ int pci_num_controllers = 0; -/* At boot time the user can give the kernel a command - * line option which controls if and how PCI devices - * are reordered at PCI bus probing time. - */ -int pci_device_reorder = 0; - volatile int pci_poke_in_progress; volatile int pci_poke_cpu = -1; volatile int pci_poke_faulted; @@ -316,27 +310,6 @@ static void __init pci_scan_each_controller_bus(void) p->scan_bus(p); } -/* Reorder the pci_dev chain, so that onboard devices come first - * and then come the pluggable cards. - */ -static void __init pci_reorder_devs(void) -{ - struct list_head *pci_onboard = &pci_devices; - struct list_head *walk = pci_onboard->next; - - while (walk != pci_onboard) { - struct pci_dev *pdev = pci_dev_g(walk); - struct list_head *walk_next = walk->next; - - if (pdev->irq && (__irq_ino(pdev->irq) & 0x20)) { - list_del(walk); - list_add(walk, pci_onboard); - } - - walk = walk_next; - } -} - extern void clock_probe(void); extern void power_init(void); @@ -348,9 +321,6 @@ static int __init pcibios_init(void) pci_scan_each_controller_bus(); - if (pci_device_reorder) - pci_reorder_devs(); - isa_init(); ebus_init(); clock_probe(); @@ -441,14 +411,6 @@ EXPORT_SYMBOL(pcibios_bus_to_resource); char * __init pcibios_setup(char *str) { - if (!strcmp(str, "onboardfirst")) { - pci_device_reorder = 1; - return NULL; - } - if (!strcmp(str, "noreorder")) { - pci_device_reorder = 0; - return NULL; - } return str; } diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index f2d1097f541..24db22aa972 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -308,7 +308,7 @@ static unsigned int psycho_irq_build(struct pci_pbm_info *pbm, if ((ino & 0x20) == 0) inofixup = ino & 0x03; - return build_irq(inofixup, iclr, imap, IBF_PCI); + return build_irq(inofixup, iclr, imap); } /* PSYCHO error handling support. */ diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index 846c1205aa9..b7d997b55f0 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -530,7 +530,7 @@ static unsigned long __onboard_imap_off[] = { * side of the non-APB bridge, then perform a read of Sabre's DMA * write-sync register. */ -static void sabre_wsync_handler(struct ino_bucket *bucket, void *_arg1, void *_arg2) +static void sabre_wsync_handler(unsigned int ino, void *_arg1, void *_arg2) { struct pci_dev *pdev = _arg1; unsigned long sync_reg = (unsigned long) _arg2; @@ -573,7 +573,7 @@ static unsigned int sabre_irq_build(struct pci_pbm_info *pbm, if ((ino & 0x20) == 0) inofixup = ino & 0x03; - virt_irq = build_irq(inofixup, iclr, imap, IBF_PCI); + virt_irq = build_irq(inofixup, iclr, imap); if (pdev) { struct pcidev_cookie *pcp = pdev->sysdata; diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index 0c400b5fa5b..cc662e915d3 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c @@ -232,10 +232,10 @@ static unsigned long schizo_iclr_offset(unsigned long ino) return SCHIZO_ICLR_BASE + (ino * 8UL); } -static void tomatillo_wsync_handler(struct ino_bucket *bucket, void *_arg1, void *_arg2) +static void tomatillo_wsync_handler(unsigned int ino, void *_arg1, void *_arg2) { unsigned long sync_reg = (unsigned long) _arg2; - u64 mask = 1UL << (__irq_ino(__irq(bucket)) & IMAP_INO); + u64 mask = 1UL << (ino & IMAP_INO); u64 val; int limit; @@ -313,7 +313,7 @@ static unsigned int schizo_irq_build(struct pci_pbm_info *pbm, ign_fixup = (1 << 6); } - virt_irq = build_irq(ign_fixup, iclr, imap, IBF_PCI); + virt_irq = build_irq(ign_fixup, iclr, imap); if (pdev && pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) { irq_install_pre_handler(virt_irq, diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index b97c81ba883..5419480edf4 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c @@ -844,7 +844,7 @@ static unsigned int pci_sun4v_irq_build(struct pci_pbm_info *pbm, { u32 devhandle = pbm->devhandle; - return sun4v_build_irq(devhandle, devino, IBF_PCI); + return sun4v_build_irq(devhandle, devino); } static void pci_sun4v_base_address_update(struct pci_dev *pdev, int resource) diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c index 5544cf5d38b..8812417247d 100644 --- a/arch/sparc64/kernel/sbus.c +++ b/arch/sparc64/kernel/sbus.c @@ -821,7 +821,7 @@ unsigned int sbus_build_irq(void *buscookie, unsigned int ino) iclr += ((unsigned long)sbus_level - 1UL) * 8UL; } - return build_irq(sbus_level, iclr, imap, 0); + return build_irq(sbus_level, iclr, imap); } /* Error interrupt handling. */ diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index 38e569f786d..af72bf5c3db 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c @@ -175,10 +175,6 @@ EXPORT_SYMBOL(set_bit); EXPORT_SYMBOL(clear_bit); EXPORT_SYMBOL(change_bit); -EXPORT_SYMBOL(ivector_table); -EXPORT_SYMBOL(enable_irq); -EXPORT_SYMBOL(disable_irq); - EXPORT_SYMBOL(__flushw_user); EXPORT_SYMBOL(tlb_type); diff --git a/arch/sparc64/kernel/sun4v_ivec.S b/arch/sparc64/kernel/sun4v_ivec.S index f70e4774649..49703c3c576 100644 --- a/arch/sparc64/kernel/sun4v_ivec.S +++ b/arch/sparc64/kernel/sun4v_ivec.S @@ -103,7 +103,7 @@ sun4v_dev_mondo: /* Get &ivector_table[IVEC] into %g4. */ sethi %hi(ivector_table), %g4 - sllx %g3, 5, %g3 + sllx %g3, 3, %g3 or %g4, %lo(ivector_table), %g4 add %g4, %g3, %g4 diff --git a/include/asm-sparc64/hardirq.h b/include/asm-sparc64/hardirq.h index f0cf71376ec..7c29fd1a87a 100644 --- a/include/asm-sparc64/hardirq.h +++ b/include/asm-sparc64/hardirq.h @@ -12,6 +12,8 @@ #define local_softirq_pending() \ (local_cpu_data().__softirq_pending) +void ack_bad_irq(unsigned int irq); + #define HARDIRQ_BITS 8 #endif /* !(__SPARC64_HARDIRQ_H) */ diff --git a/include/asm-sparc64/hw_irq.h b/include/asm-sparc64/hw_irq.h index 153cae2ddae..599b3b07345 100644 --- a/include/asm-sparc64/hw_irq.h +++ b/include/asm-sparc64/hw_irq.h @@ -1,6 +1,6 @@ #ifndef __ASM_SPARC64_HW_IRQ_H #define __ASM_SPARC64_HW_IRQ_H -/* Dummy include. */ +extern void hw_resend_irq(struct hw_interrupt_type *handler, unsigned int virt_irq); #endif diff --git a/include/asm-sparc64/irq.h b/include/asm-sparc64/irq.h index 9edcd90495f..77a4f63cba7 100644 --- a/include/asm-sparc64/irq.h +++ b/include/asm-sparc64/irq.h @@ -16,58 +16,6 @@ #include #include -struct ino_bucket; - -#define MAX_IRQ_DESC_ACTION 4 - -struct irq_desc { - void (*pre_handler)(struct ino_bucket *, void *, void *); - void *pre_handler_arg1; - void *pre_handler_arg2; - u32 action_active_mask; - struct irqaction action[MAX_IRQ_DESC_ACTION]; -}; - -/* You should not mess with this directly. That's the job of irq.c. - * - * If you make changes here, please update hand coded assembler of - * the vectored interrupt trap handler in entry.S -DaveM - * - * This is currently one DCACHE line, two buckets per L2 cache - * line. Keep this in mind please. - */ -struct ino_bucket { - /* Next handler in per-CPU IRQ worklist. We know that - * bucket pointers have the high 32-bits clear, so to - * save space we only store the bits we need. - */ -/*0x00*/unsigned int irq_chain; - - /* Virtual interrupt number assigned to this INO. */ -/*0x04*/unsigned char virt_irq; - - /* If an IVEC arrives while irq_info is NULL, we - * set this to notify request_irq() about the event. - */ -/*0x05*/unsigned char pending; - - /* Miscellaneous flags. */ -/*0x06*/unsigned char flags; - - /* Currently unused. */ -/*0x07*/unsigned char __pad; - - /* Reference to IRQ descriptor for this bucket. */ -/*0x08*/struct irq_desc *irq_info; - - /* Sun5 Interrupt Clear Register. */ -/*0x10*/unsigned long iclr; - - /* Sun5 Interrupt Mapping Register. */ -/*0x18*/unsigned long imap; - -}; - /* IMAP/ICLR register defines */ #define IMAP_VALID 0x80000000 /* IRQ Enabled */ #define IMAP_TID_UPA 0x7c000000 /* UPA TargetID */ @@ -85,19 +33,6 @@ struct ino_bucket { #define ICLR_TRANSMIT 0x00000001 /* Transmit state */ #define ICLR_PENDING 0x00000003 /* Pending state */ -/* Only 8-bits are available, be careful. -DaveM */ -#define IBF_PCI 0x02 /* PSYCHO/SABRE/SCHIZO PCI interrupt. */ -#define IBF_ACTIVE 0x04 /* Interrupt is active and has a handler.*/ -#define IBF_INPROGRESS 0x10 /* IRQ is being serviced. */ - -#define NUM_IVECS (IMAP_INR + 1) -extern struct ino_bucket ivector_table[NUM_IVECS]; - -#define __irq_ino(irq) \ - (((struct ino_bucket *)(unsigned long)(irq)) - &ivector_table[0]) -#define __bucket(irq) ((struct ino_bucket *)(unsigned long)(irq)) -#define __irq(bucket) ((unsigned int)(unsigned long)(bucket)) - /* The largest number of unique interrupt sources we support. * If this needs to ever be larger than 255, you need to change * the type of ino_bucket->virt_irq as appropriate. @@ -107,14 +42,11 @@ extern struct ino_bucket ivector_table[NUM_IVECS]; #define NR_IRQS 255 extern void irq_install_pre_handler(int virt_irq, - void (*func)(struct ino_bucket *, void *, void *), + void (*func)(unsigned int, void *, void *), void *arg1, void *arg2); #define irq_canonicalize(irq) (irq) -extern void disable_irq(unsigned int); -#define disable_irq_nosync disable_irq -extern void enable_irq(unsigned int); -extern unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap, unsigned char flags); -extern unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino, unsigned char flags); +extern unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap); +extern unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino); extern unsigned int sbus_build_irq(void *sbus, unsigned int ino); static __inline__ void set_softint(unsigned long bits) @@ -140,8 +72,4 @@ static __inline__ unsigned long get_softint(void) return retval; } -struct irqaction; -struct pt_regs; -int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); - #endif -- cgit v1.2.3 From c8bfcd95def89cb69a04c58e1de7995d696c8760 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 20 Jun 2006 01:23:56 -0700 Subject: [SPARC64]: Don't double-export synchronize_irq. It is done by the generic IRQ layer now. Signed-off-by: David S. Miller --- arch/sparc64/kernel/sparc64_ksyms.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index af72bf5c3db..4ac35dd2088 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c @@ -125,9 +125,6 @@ EXPORT_SYMBOL(__write_lock); EXPORT_SYMBOL(__write_unlock); EXPORT_SYMBOL(__write_trylock); -/* Hard IRQ locking */ -EXPORT_SYMBOL(synchronize_irq); - #if defined(CONFIG_MCOUNT) extern void _mcount(void); EXPORT_SYMBOL(_mcount); -- cgit v1.2.3 From 4c5eb38af2131d867842cdd09fa83a3ed77bfd26 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 20 Jun 2006 01:27:08 -0700 Subject: [SPARC64]: Update defconfig. Signed-off-by: David S. Miller --- arch/sparc64/defconfig | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig index f09a70b8aab..9da75f89fe2 100644 --- a/arch/sparc64/defconfig +++ b/arch/sparc64/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.17-rc3 -# Fri May 12 12:43:49 2006 +# Linux kernel version: 2.6.17 +# Tue Jun 20 01:26:43 2006 # CONFIG_SPARC=y CONFIG_SPARC64=y @@ -87,6 +87,7 @@ CONFIG_DEFAULT_AS=y # CONFIG_DEFAULT_NOOP is not set CONFIG_DEFAULT_IOSCHED="anticipatory" CONFIG_SYSVIPC_COMPAT=y +CONFIG_GENERIC_HARDIRQS=y # # General machine setup @@ -183,6 +184,8 @@ CONFIG_INET_ESP=y CONFIG_INET_IPCOMP=y CONFIG_INET_XFRM_TUNNEL=y CONFIG_INET_TUNNEL=y +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y CONFIG_TCP_CONG_ADVANCED=y @@ -198,6 +201,9 @@ CONFIG_TCP_CONG_HSTCP=m CONFIG_TCP_CONG_HYBLA=m CONFIG_TCP_CONG_VEGAS=m CONFIG_TCP_CONG_SCALABLE=m +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_CONG_VENO=m +CONFIG_TCP_CONG_COMPOUND=m CONFIG_IPV6=m CONFIG_IPV6_PRIVACY=y CONFIG_IPV6_ROUTER_PREF=y @@ -207,7 +213,10 @@ CONFIG_INET6_ESP=m CONFIG_INET6_IPCOMP=m CONFIG_INET6_XFRM_TUNNEL=m CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m CONFIG_IPV6_TUNNEL=m +# CONFIG_NETWORK_SECMARK is not set # CONFIG_NETFILTER is not set # @@ -260,6 +269,7 @@ CONFIG_VLAN_8021Q=m # Network testing # CONFIG_NET_PKTGEN=m +CONFIG_NET_TCPPROBE=m # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set @@ -562,6 +572,7 @@ CONFIG_BNX2=m # CONFIG_CHELSIO_T1 is not set # CONFIG_IXGB is not set # CONFIG_S2IO is not set +# CONFIG_MYRI10GE is not set # # Token Ring devices @@ -811,6 +822,7 @@ CONFIG_HWMON=y # Multimedia devices # # CONFIG_VIDEO_DEV is not set +CONFIG_VIDEO_V4L2=y # # Digital Video Broadcasting Devices @@ -1134,6 +1146,19 @@ CONFIG_USB_HIDDEV=y # # CONFIG_RTC_CLASS is not set +# +# DMA Engine support +# +# CONFIG_DMA_ENGINE is not set + +# +# DMA Clients +# + +# +# DMA Devices +# + # # Misc Linux/SPARC drivers # -- cgit v1.2.3 From 612eff0e3715a6faff5ba1b74873b99e036c59fe Mon Sep 17 00:00:00 2001 From: Brian Haley Date: Thu, 15 Jun 2006 14:36:36 -0400 Subject: [PATCH] s2io: netpoll support This adds netpoll support for things like netconsole/kgdboe to the s2io 10GbE driver. Signed-off-by: Brian Haley Signed-off-by: Jeff Garzik --- drivers/net/s2io.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index cac9fdd2e1d..11daed495b9 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -2626,6 +2626,50 @@ no_rx: } #endif +/** + * s2io_netpoll - Rx interrupt service handler for netpoll support + * @dev : pointer to the device structure. + * Description: + * Polling 'interrupt' - used by things like netconsole to send skbs + * without having to re-enable interrupts. It's not called while + * the interrupt routine is executing. + */ + +#ifdef CONFIG_NET_POLL_CONTROLLER +static void s2io_netpoll(struct net_device *dev) +{ + nic_t *nic = dev->priv; + mac_info_t *mac_control; + struct config_param *config; + XENA_dev_config_t __iomem *bar0 = nic->bar0; + u64 val64; + int i; + + disable_irq(dev->irq); + + atomic_inc(&nic->isr_cnt); + mac_control = &nic->mac_control; + config = &nic->config; + + val64 = readq(&bar0->rx_traffic_int); + writeq(val64, &bar0->rx_traffic_int); + + for (i = 0; i < config->rx_ring_num; i++) + rx_intr_handler(&mac_control->rings[i]); + + for (i = 0; i < config->rx_ring_num; i++) { + if (fill_rx_buffers(nic, i) == -ENOMEM) { + DBG_PRINT(ERR_DBG, "%s:Out of memory", dev->name); + DBG_PRINT(ERR_DBG, " in Rx Netpoll!!\n"); + break; + } + } + atomic_dec(&nic->isr_cnt); + enable_irq(dev->irq); + return; +} +#endif + /** * rx_intr_handler - Rx interrupt handler * @nic: device private variable. @@ -6967,6 +7011,10 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) dev->weight = 32; #endif +#ifdef CONFIG_NET_POLL_CONTROLLER + dev->poll_controller = s2io_netpoll; +#endif + dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; if (sp->high_dma_flag == TRUE) dev->features |= NETIF_F_HIGHDMA; -- cgit v1.2.3 From 638ebcc81f40b160f5e8b161e690e9b1b9503c1e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 17 Jun 2006 15:49:55 +0900 Subject: [PATCH] sata_nv: kill not-working hotplug code sata_nv contained hotplug code which is mainly for demonstrating how hotplug event is handled. This patch kills the demo code in prepration for real hotplug implementation. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/sata_nv.c | 169 ------------------------------------------------- 1 file changed, 169 deletions(-) diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c index 90551246aa4..70f81941f76 100644 --- a/drivers/scsi/sata_nv.c +++ b/drivers/scsi/sata_nv.c @@ -64,12 +64,6 @@ enum { NV_INT_STATUS_SDEV_PM = 0x20, NV_INT_STATUS_SDEV_ADDED = 0x40, NV_INT_STATUS_SDEV_REMOVED = 0x80, - NV_INT_STATUS_PDEV_HOTPLUG = (NV_INT_STATUS_PDEV_ADDED | - NV_INT_STATUS_PDEV_REMOVED), - NV_INT_STATUS_SDEV_HOTPLUG = (NV_INT_STATUS_SDEV_ADDED | - NV_INT_STATUS_SDEV_REMOVED), - NV_INT_STATUS_HOTPLUG = (NV_INT_STATUS_PDEV_HOTPLUG | - NV_INT_STATUS_SDEV_HOTPLUG), NV_INT_ENABLE = 0x11, NV_INT_ENABLE_CK804 = 0x441, @@ -81,12 +75,6 @@ enum { NV_INT_ENABLE_SDEV_PM = 0x20, NV_INT_ENABLE_SDEV_ADDED = 0x40, NV_INT_ENABLE_SDEV_REMOVED = 0x80, - NV_INT_ENABLE_PDEV_HOTPLUG = (NV_INT_ENABLE_PDEV_ADDED | - NV_INT_ENABLE_PDEV_REMOVED), - NV_INT_ENABLE_SDEV_HOTPLUG = (NV_INT_ENABLE_SDEV_ADDED | - NV_INT_ENABLE_SDEV_REMOVED), - NV_INT_ENABLE_HOTPLUG = (NV_INT_ENABLE_PDEV_HOTPLUG | - NV_INT_ENABLE_SDEV_HOTPLUG), NV_INT_CONFIG = 0x12, NV_INT_CONFIG_METHD = 0x01, // 0 = INT, 1 = SMI @@ -102,12 +90,6 @@ static irqreturn_t nv_interrupt (int irq, void *dev_instance, static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg); static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); static void nv_host_stop (struct ata_host_set *host_set); -static void nv_enable_hotplug(struct ata_probe_ent *probe_ent); -static void nv_disable_hotplug(struct ata_host_set *host_set); -static int nv_check_hotplug(struct ata_host_set *host_set); -static void nv_enable_hotplug_ck804(struct ata_probe_ent *probe_ent); -static void nv_disable_hotplug_ck804(struct ata_host_set *host_set); -static int nv_check_hotplug_ck804(struct ata_host_set *host_set); enum nv_host_type { @@ -158,34 +140,18 @@ static const struct pci_device_id nv_pci_tbl[] = { struct nv_host_desc { enum nv_host_type host_type; - void (*enable_hotplug)(struct ata_probe_ent *probe_ent); - void (*disable_hotplug)(struct ata_host_set *host_set); - int (*check_hotplug)(struct ata_host_set *host_set); - }; static struct nv_host_desc nv_device_tbl[] = { { .host_type = GENERIC, - .enable_hotplug = NULL, - .disable_hotplug= NULL, - .check_hotplug = NULL, }, { .host_type = NFORCE2, - .enable_hotplug = nv_enable_hotplug, - .disable_hotplug= nv_disable_hotplug, - .check_hotplug = nv_check_hotplug, }, { .host_type = NFORCE3, - .enable_hotplug = nv_enable_hotplug, - .disable_hotplug= nv_disable_hotplug, - .check_hotplug = nv_check_hotplug, }, { .host_type = CK804, - .enable_hotplug = nv_enable_hotplug_ck804, - .disable_hotplug= nv_disable_hotplug_ck804, - .check_hotplug = nv_check_hotplug_ck804, }, }; @@ -275,7 +241,6 @@ static irqreturn_t nv_interrupt (int irq, void *dev_instance, struct pt_regs *regs) { struct ata_host_set *host_set = dev_instance; - struct nv_host *host = host_set->private_data; unsigned int i; unsigned int handled = 0; unsigned long flags; @@ -301,9 +266,6 @@ static irqreturn_t nv_interrupt (int irq, void *dev_instance, } - if (host->host_desc->check_hotplug) - handled += host->host_desc->check_hotplug(host_set); - spin_unlock_irqrestore(&host_set->lock, flags); return IRQ_RETVAL(handled); @@ -329,10 +291,6 @@ static void nv_host_stop (struct ata_host_set *host_set) { struct nv_host *host = host_set->private_data; - // Disable hotplug event interrupts. - if (host->host_desc->disable_hotplug) - host->host_desc->disable_hotplug(host_set); - kfree(host); ata_pci_host_stop(host_set); @@ -409,10 +367,6 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) if (rc != NV_PORTS) goto err_out_iounmap; - // Enable hotplug event interrupts. - if (host->host_desc->enable_hotplug) - host->host_desc->enable_hotplug(probe_ent); - kfree(probe_ent); return 0; @@ -432,129 +386,6 @@ err_out: return rc; } -static void nv_enable_hotplug(struct ata_probe_ent *probe_ent) -{ - u8 intr_mask; - - outb(NV_INT_STATUS_HOTPLUG, - probe_ent->port[0].scr_addr + NV_INT_STATUS); - - intr_mask = inb(probe_ent->port[0].scr_addr + NV_INT_ENABLE); - intr_mask |= NV_INT_ENABLE_HOTPLUG; - - outb(intr_mask, probe_ent->port[0].scr_addr + NV_INT_ENABLE); -} - -static void nv_disable_hotplug(struct ata_host_set *host_set) -{ - u8 intr_mask; - - intr_mask = inb(host_set->ports[0]->ioaddr.scr_addr + NV_INT_ENABLE); - - intr_mask &= ~(NV_INT_ENABLE_HOTPLUG); - - outb(intr_mask, host_set->ports[0]->ioaddr.scr_addr + NV_INT_ENABLE); -} - -static int nv_check_hotplug(struct ata_host_set *host_set) -{ - u8 intr_status; - - intr_status = inb(host_set->ports[0]->ioaddr.scr_addr + NV_INT_STATUS); - - // Clear interrupt status. - outb(0xff, host_set->ports[0]->ioaddr.scr_addr + NV_INT_STATUS); - - if (intr_status & NV_INT_STATUS_HOTPLUG) { - if (intr_status & NV_INT_STATUS_PDEV_ADDED) - printk(KERN_WARNING "nv_sata: " - "Primary device added\n"); - - if (intr_status & NV_INT_STATUS_PDEV_REMOVED) - printk(KERN_WARNING "nv_sata: " - "Primary device removed\n"); - - if (intr_status & NV_INT_STATUS_SDEV_ADDED) - printk(KERN_WARNING "nv_sata: " - "Secondary device added\n"); - - if (intr_status & NV_INT_STATUS_SDEV_REMOVED) - printk(KERN_WARNING "nv_sata: " - "Secondary device removed\n"); - - return 1; - } - - return 0; -} - -static void nv_enable_hotplug_ck804(struct ata_probe_ent *probe_ent) -{ - struct pci_dev *pdev = to_pci_dev(probe_ent->dev); - u8 intr_mask; - u8 regval; - - pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, ®val); - regval |= NV_MCP_SATA_CFG_20_SATA_SPACE_EN; - pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval); - - writeb(NV_INT_STATUS_HOTPLUG, probe_ent->mmio_base + NV_INT_STATUS_CK804); - - intr_mask = readb(probe_ent->mmio_base + NV_INT_ENABLE_CK804); - intr_mask |= NV_INT_ENABLE_HOTPLUG; - - writeb(intr_mask, probe_ent->mmio_base + NV_INT_ENABLE_CK804); -} - -static void nv_disable_hotplug_ck804(struct ata_host_set *host_set) -{ - struct pci_dev *pdev = to_pci_dev(host_set->dev); - u8 intr_mask; - u8 regval; - - intr_mask = readb(host_set->mmio_base + NV_INT_ENABLE_CK804); - - intr_mask &= ~(NV_INT_ENABLE_HOTPLUG); - - writeb(intr_mask, host_set->mmio_base + NV_INT_ENABLE_CK804); - - pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, ®val); - regval &= ~NV_MCP_SATA_CFG_20_SATA_SPACE_EN; - pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval); -} - -static int nv_check_hotplug_ck804(struct ata_host_set *host_set) -{ - u8 intr_status; - - intr_status = readb(host_set->mmio_base + NV_INT_STATUS_CK804); - - // Clear interrupt status. - writeb(0xff, host_set->mmio_base + NV_INT_STATUS_CK804); - - if (intr_status & NV_INT_STATUS_HOTPLUG) { - if (intr_status & NV_INT_STATUS_PDEV_ADDED) - printk(KERN_WARNING "nv_sata: " - "Primary device added\n"); - - if (intr_status & NV_INT_STATUS_PDEV_REMOVED) - printk(KERN_WARNING "nv_sata: " - "Primary device removed\n"); - - if (intr_status & NV_INT_STATUS_SDEV_ADDED) - printk(KERN_WARNING "nv_sata: " - "Secondary device added\n"); - - if (intr_status & NV_INT_STATUS_SDEV_REMOVED) - printk(KERN_WARNING "nv_sata: " - "Secondary device removed\n"); - - return 1; - } - - return 0; -} - static int __init nv_init(void) { return pci_module_init(&nv_pci_driver); -- cgit v1.2.3 From e6faf082cd75d6dcdcf89258ddf40c6855df87a1 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 17 Jun 2006 15:49:55 +0900 Subject: [PATCH] sata_nv: kill struct nv_host_desc and nv_host nv_host_desc and nv_host are used to discern different generations of nv controllers. Kill those. New EH/hotplug implementation will use standard port_info/ata_port_operations for that. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/sata_nv.c | 50 ++------------------------------------------------ 1 file changed, 2 insertions(+), 48 deletions(-) diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c index 70f81941f76..e9c4547723c 100644 --- a/drivers/scsi/sata_nv.c +++ b/drivers/scsi/sata_nv.c @@ -89,7 +89,6 @@ static irqreturn_t nv_interrupt (int irq, void *dev_instance, struct pt_regs *regs); static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg); static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); -static void nv_host_stop (struct ata_host_set *host_set); enum nv_host_type { @@ -137,30 +136,6 @@ static const struct pci_device_id nv_pci_tbl[] = { { 0, } /* terminate list */ }; -struct nv_host_desc -{ - enum nv_host_type host_type; -}; -static struct nv_host_desc nv_device_tbl[] = { - { - .host_type = GENERIC, - }, - { - .host_type = NFORCE2, - }, - { - .host_type = NFORCE3, - }, - { .host_type = CK804, - }, -}; - -struct nv_host -{ - struct nv_host_desc *host_desc; - unsigned long host_flags; -}; - static struct pci_driver nv_pci_driver = { .name = DRV_NAME, .id_table = nv_pci_tbl, @@ -208,7 +183,7 @@ static const struct ata_port_operations nv_ops = { .scr_write = nv_scr_write, .port_start = ata_port_start, .port_stop = ata_port_stop, - .host_stop = nv_host_stop, + .host_stop = ata_pci_host_stop, }; /* FIXME: The hardware provides the necessary SATA PHY controls @@ -287,19 +262,9 @@ static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val) iowrite32(val, (void __iomem *)ap->ioaddr.scr_addr + (sc_reg * 4)); } -static void nv_host_stop (struct ata_host_set *host_set) -{ - struct nv_host *host = host_set->private_data; - - kfree(host); - - ata_pci_host_stop(host_set); -} - static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { static int printed_version = 0; - struct nv_host *host; struct ata_port_info *ppi; struct ata_probe_ent *probe_ent; int pci_dev_busy = 0; @@ -341,19 +306,10 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) if (!probe_ent) goto err_out_regions; - host = kmalloc(sizeof(struct nv_host), GFP_KERNEL); - if (!host) - goto err_out_free_ent; - - memset(host, 0, sizeof(struct nv_host)); - host->host_desc = &nv_device_tbl[ent->driver_data]; - - probe_ent->private_data = host; - probe_ent->mmio_base = pci_iomap(pdev, 5, 0); if (!probe_ent->mmio_base) { rc = -EIO; - goto err_out_free_host; + goto err_out_free_ent; } base = (unsigned long)probe_ent->mmio_base; @@ -373,8 +329,6 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) err_out_iounmap: pci_iounmap(pdev, probe_ent->mmio_base); -err_out_free_host: - kfree(host); err_out_free_ent: kfree(probe_ent); err_out_regions: -- cgit v1.2.3 From 27e4b2745443cef67220da9a4f5f71b1c5f72442 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 17 Jun 2006 15:49:55 +0900 Subject: [PATCH] sata_nv: simplify constants Simplify interrupt constants and make NFORCE3 equal to NFORCE2. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/sata_nv.c | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c index e9c4547723c..1cb7b44cb66 100644 --- a/drivers/scsi/sata_nv.c +++ b/drivers/scsi/sata_nv.c @@ -54,28 +54,21 @@ enum { NV_PORT0_SCR_REG_OFFSET = 0x00, NV_PORT1_SCR_REG_OFFSET = 0x40, + /* INT_STATUS/ENABLE */ NV_INT_STATUS = 0x10, - NV_INT_STATUS_CK804 = 0x440, - NV_INT_STATUS_PDEV_INT = 0x01, - NV_INT_STATUS_PDEV_PM = 0x02, - NV_INT_STATUS_PDEV_ADDED = 0x04, - NV_INT_STATUS_PDEV_REMOVED = 0x08, - NV_INT_STATUS_SDEV_INT = 0x10, - NV_INT_STATUS_SDEV_PM = 0x20, - NV_INT_STATUS_SDEV_ADDED = 0x40, - NV_INT_STATUS_SDEV_REMOVED = 0x80, - NV_INT_ENABLE = 0x11, + NV_INT_STATUS_CK804 = 0x440, NV_INT_ENABLE_CK804 = 0x441, - NV_INT_ENABLE_PDEV_MASK = 0x01, - NV_INT_ENABLE_PDEV_PM = 0x02, - NV_INT_ENABLE_PDEV_ADDED = 0x04, - NV_INT_ENABLE_PDEV_REMOVED = 0x08, - NV_INT_ENABLE_SDEV_MASK = 0x10, - NV_INT_ENABLE_SDEV_PM = 0x20, - NV_INT_ENABLE_SDEV_ADDED = 0x40, - NV_INT_ENABLE_SDEV_REMOVED = 0x80, + /* INT_STATUS/ENABLE bits */ + NV_INT_DEV = 0x01, + NV_INT_PM = 0x02, + NV_INT_ADDED = 0x04, + NV_INT_REMOVED = 0x08, + + NV_INT_PORT_SHIFT = 4, /* each port occupies 4 bits */ + + /* INT_CONFIG */ NV_INT_CONFIG = 0x12, NV_INT_CONFIG_METHD = 0x01, // 0 = INT, 1 = SMI @@ -94,7 +87,7 @@ enum nv_host_type { GENERIC, NFORCE2, - NFORCE3, + NFORCE3 = NFORCE2, /* NF2 == NF3 as far as sata_nv is concerned */ CK804 }; -- cgit v1.2.3 From ada364e884eb7e60ee96e84cbce07b3c90234c9d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 17 Jun 2006 15:49:56 +0900 Subject: [PATCH] sata_nv: better irq handlers nf2/3 and ck804 have irq status register. Implement better irq handler for those flavors of nv. This patch makes different flavors of nv controllers use different irq handlers by using separate port_info for each flavor. This change also makes following EH and hotplug updates easier to integrate. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/sata_nv.c | 211 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 194 insertions(+), 17 deletions(-) diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c index 1cb7b44cb66..94cb17903fa 100644 --- a/drivers/scsi/sata_nv.c +++ b/drivers/scsi/sata_nv.c @@ -78,8 +78,13 @@ enum { }; static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); -static irqreturn_t nv_interrupt (int irq, void *dev_instance, - struct pt_regs *regs); +static void nv_ck804_host_stop(struct ata_host_set *host_set); +static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance, + struct pt_regs *regs); +static irqreturn_t nv_nf2_interrupt(int irq, void *dev_instance, + struct pt_regs *regs); +static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance, + struct pt_regs *regs); static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg); static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); @@ -154,7 +159,7 @@ static struct scsi_host_template nv_sht = { .bios_param = ata_std_bios_param, }; -static const struct ata_port_operations nv_ops = { +static const struct ata_port_operations nv_generic_ops = { .port_disable = ata_port_disable, .tf_load = ata_tf_load, .tf_read = ata_tf_read, @@ -170,7 +175,7 @@ static const struct ata_port_operations nv_ops = { .qc_issue = ata_qc_issue_prot, .eng_timeout = ata_eng_timeout, .data_xfer = ata_pio_data_xfer, - .irq_handler = nv_interrupt, + .irq_handler = nv_generic_interrupt, .irq_clear = ata_bmdma_irq_clear, .scr_read = nv_scr_read, .scr_write = nv_scr_write, @@ -179,6 +184,56 @@ static const struct ata_port_operations nv_ops = { .host_stop = ata_pci_host_stop, }; +static const struct ata_port_operations nv_nf2_ops = { + .port_disable = ata_port_disable, + .tf_load = ata_tf_load, + .tf_read = ata_tf_read, + .exec_command = ata_exec_command, + .check_status = ata_check_status, + .dev_select = ata_std_dev_select, + .phy_reset = sata_phy_reset, + .bmdma_setup = ata_bmdma_setup, + .bmdma_start = ata_bmdma_start, + .bmdma_stop = ata_bmdma_stop, + .bmdma_status = ata_bmdma_status, + .qc_prep = ata_qc_prep, + .qc_issue = ata_qc_issue_prot, + .eng_timeout = ata_eng_timeout, + .data_xfer = ata_pio_data_xfer, + .irq_handler = nv_nf2_interrupt, + .irq_clear = ata_bmdma_irq_clear, + .scr_read = nv_scr_read, + .scr_write = nv_scr_write, + .port_start = ata_port_start, + .port_stop = ata_port_stop, + .host_stop = ata_pci_host_stop, +}; + +static const struct ata_port_operations nv_ck804_ops = { + .port_disable = ata_port_disable, + .tf_load = ata_tf_load, + .tf_read = ata_tf_read, + .exec_command = ata_exec_command, + .check_status = ata_check_status, + .dev_select = ata_std_dev_select, + .phy_reset = sata_phy_reset, + .bmdma_setup = ata_bmdma_setup, + .bmdma_start = ata_bmdma_start, + .bmdma_stop = ata_bmdma_stop, + .bmdma_status = ata_bmdma_status, + .qc_prep = ata_qc_prep, + .qc_issue = ata_qc_issue_prot, + .eng_timeout = ata_eng_timeout, + .data_xfer = ata_pio_data_xfer, + .irq_handler = nv_ck804_interrupt, + .irq_clear = ata_bmdma_irq_clear, + .scr_read = nv_scr_read, + .scr_write = nv_scr_write, + .port_start = ata_port_start, + .port_stop = ata_port_stop, + .host_stop = nv_ck804_host_stop, +}; + /* FIXME: The hardware provides the necessary SATA PHY controls * to support ATA_FLAG_SATA_RESET. However, it is currently * necessary to disable that flag, to solve misdetection problems. @@ -187,16 +242,43 @@ static const struct ata_port_operations nv_ops = { * This problem really needs to be investigated further. But in the * meantime, we avoid ATA_FLAG_SATA_RESET to get people working. */ -static struct ata_port_info nv_port_info = { - .sht = &nv_sht, - .host_flags = ATA_FLAG_SATA | - /* ATA_FLAG_SATA_RESET | */ - ATA_FLAG_SRST | - ATA_FLAG_NO_LEGACY, - .pio_mask = NV_PIO_MASK, - .mwdma_mask = NV_MWDMA_MASK, - .udma_mask = NV_UDMA_MASK, - .port_ops = &nv_ops, +static struct ata_port_info nv_port_info[] = { + /* generic */ + { + .sht = &nv_sht, + .host_flags = ATA_FLAG_SATA | + /* ATA_FLAG_SATA_RESET | */ + ATA_FLAG_SRST | + ATA_FLAG_NO_LEGACY, + .pio_mask = NV_PIO_MASK, + .mwdma_mask = NV_MWDMA_MASK, + .udma_mask = NV_UDMA_MASK, + .port_ops = &nv_generic_ops, + }, + /* nforce2/3 */ + { + .sht = &nv_sht, + .host_flags = ATA_FLAG_SATA | + /* ATA_FLAG_SATA_RESET | */ + ATA_FLAG_SRST | + ATA_FLAG_NO_LEGACY, + .pio_mask = NV_PIO_MASK, + .mwdma_mask = NV_MWDMA_MASK, + .udma_mask = NV_UDMA_MASK, + .port_ops = &nv_nf2_ops, + }, + /* ck804 */ + { + .sht = &nv_sht, + .host_flags = ATA_FLAG_SATA | + /* ATA_FLAG_SATA_RESET | */ + ATA_FLAG_SRST | + ATA_FLAG_NO_LEGACY, + .pio_mask = NV_PIO_MASK, + .mwdma_mask = NV_MWDMA_MASK, + .udma_mask = NV_UDMA_MASK, + .port_ops = &nv_ck804_ops, + }, }; MODULE_AUTHOR("NVIDIA"); @@ -205,8 +287,8 @@ MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, nv_pci_tbl); MODULE_VERSION(DRV_VERSION); -static irqreturn_t nv_interrupt (int irq, void *dev_instance, - struct pt_regs *regs) +static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance, + struct pt_regs *regs) { struct ata_host_set *host_set = dev_instance; unsigned int i; @@ -239,6 +321,79 @@ static irqreturn_t nv_interrupt (int irq, void *dev_instance, return IRQ_RETVAL(handled); } +static int nv_host_intr(struct ata_port *ap, u8 irq_stat) +{ + struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag); + int handled; + + /* bail out if not our interrupt */ + if (!(irq_stat & NV_INT_DEV)) + return 0; + + /* DEV interrupt w/ no active qc? */ + if (unlikely(!qc || (qc->tf.flags & ATA_TFLAG_POLLING))) { + ata_check_status(ap); + return 1; + } + + /* handle interrupt */ + handled = ata_host_intr(ap, qc); + if (unlikely(!handled)) { + /* spurious, clear it */ + ata_check_status(ap); + } + + return 1; +} + +static irqreturn_t nv_do_interrupt(struct ata_host_set *host_set, u8 irq_stat) +{ + int i, handled = 0; + + for (i = 0; i < host_set->n_ports; i++) { + struct ata_port *ap = host_set->ports[i]; + + if (ap && !(ap->flags & ATA_FLAG_DISABLED)) + handled += nv_host_intr(ap, irq_stat); + + irq_stat >>= NV_INT_PORT_SHIFT; + } + + return IRQ_RETVAL(handled); +} + +static irqreturn_t nv_nf2_interrupt(int irq, void *dev_instance, + struct pt_regs *regs) +{ + struct ata_host_set *host_set = dev_instance; + unsigned long flags; + u8 irq_stat; + irqreturn_t ret; + + spin_lock_irqsave(&host_set->lock, flags); + irq_stat = inb(host_set->ports[0]->ioaddr.scr_addr + NV_INT_STATUS); + ret = nv_do_interrupt(host_set, irq_stat); + spin_unlock_irqrestore(&host_set->lock, flags); + + return ret; +} + +static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance, + struct pt_regs *regs) +{ + struct ata_host_set *host_set = dev_instance; + unsigned long flags; + u8 irq_stat; + irqreturn_t ret; + + spin_lock_irqsave(&host_set->lock, flags); + irq_stat = readb(host_set->mmio_base + NV_INT_STATUS_CK804); + ret = nv_do_interrupt(host_set, irq_stat); + spin_unlock_irqrestore(&host_set->lock, flags); + + return ret; +} + static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg) { if (sc_reg > SCR_CONTROL) @@ -294,7 +449,7 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) rc = -ENOMEM; - ppi = &nv_port_info; + ppi = &nv_port_info[ent->driver_data]; probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY); if (!probe_ent) goto err_out_regions; @@ -310,6 +465,15 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) probe_ent->port[0].scr_addr = base + NV_PORT0_SCR_REG_OFFSET; probe_ent->port[1].scr_addr = base + NV_PORT1_SCR_REG_OFFSET; + /* enable SATA space for CK804 */ + if (ent->driver_data == CK804) { + u8 regval; + + pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, ®val); + regval |= NV_MCP_SATA_CFG_20_SATA_SPACE_EN; + pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval); + } + pci_set_master(pdev); rc = ata_device_add(probe_ent); @@ -333,6 +497,19 @@ err_out: return rc; } +static void nv_ck804_host_stop(struct ata_host_set *host_set) +{ + struct pci_dev *pdev = to_pci_dev(host_set->dev); + u8 regval; + + /* disable SATA space for CK804 */ + pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, ®val); + regval &= ~NV_MCP_SATA_CFG_20_SATA_SPACE_EN; + pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval); + + ata_pci_host_stop(host_set); +} + static int __init nv_init(void) { return pci_module_init(&nv_pci_driver); -- cgit v1.2.3 From 39f8758259868a01ecad29b4379661dd3f21881f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 17 Jun 2006 15:49:56 +0900 Subject: [PATCH] sata_nv: convert to new EH Convert to new EH. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/sata_nv.c | 115 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 89 insertions(+), 26 deletions(-) diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c index 94cb17903fa..2a1bd85404e 100644 --- a/drivers/scsi/sata_nv.c +++ b/drivers/scsi/sata_nv.c @@ -68,6 +68,9 @@ enum { NV_INT_PORT_SHIFT = 4, /* each port occupies 4 bits */ + NV_INT_ALL = 0x0f, + NV_INT_MASK = NV_INT_DEV, + /* INT_CONFIG */ NV_INT_CONFIG = 0x12, NV_INT_CONFIG_METHD = 0x01, // 0 = INT, 1 = SMI @@ -88,6 +91,12 @@ static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance, static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg); static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); +static void nv_nf2_freeze(struct ata_port *ap); +static void nv_nf2_thaw(struct ata_port *ap); +static void nv_ck804_freeze(struct ata_port *ap); +static void nv_ck804_thaw(struct ata_port *ap); +static void nv_error_handler(struct ata_port *ap); + enum nv_host_type { GENERIC, @@ -166,14 +175,16 @@ static const struct ata_port_operations nv_generic_ops = { .exec_command = ata_exec_command, .check_status = ata_check_status, .dev_select = ata_std_dev_select, - .phy_reset = sata_phy_reset, .bmdma_setup = ata_bmdma_setup, .bmdma_start = ata_bmdma_start, .bmdma_stop = ata_bmdma_stop, .bmdma_status = ata_bmdma_status, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, + .freeze = ata_bmdma_freeze, + .thaw = ata_bmdma_thaw, + .error_handler = nv_error_handler, + .post_internal_cmd = ata_bmdma_post_internal_cmd, .data_xfer = ata_pio_data_xfer, .irq_handler = nv_generic_interrupt, .irq_clear = ata_bmdma_irq_clear, @@ -191,14 +202,16 @@ static const struct ata_port_operations nv_nf2_ops = { .exec_command = ata_exec_command, .check_status = ata_check_status, .dev_select = ata_std_dev_select, - .phy_reset = sata_phy_reset, .bmdma_setup = ata_bmdma_setup, .bmdma_start = ata_bmdma_start, .bmdma_stop = ata_bmdma_stop, .bmdma_status = ata_bmdma_status, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, + .freeze = nv_nf2_freeze, + .thaw = nv_nf2_thaw, + .error_handler = nv_error_handler, + .post_internal_cmd = ata_bmdma_post_internal_cmd, .data_xfer = ata_pio_data_xfer, .irq_handler = nv_nf2_interrupt, .irq_clear = ata_bmdma_irq_clear, @@ -216,14 +229,16 @@ static const struct ata_port_operations nv_ck804_ops = { .exec_command = ata_exec_command, .check_status = ata_check_status, .dev_select = ata_std_dev_select, - .phy_reset = sata_phy_reset, .bmdma_setup = ata_bmdma_setup, .bmdma_start = ata_bmdma_start, .bmdma_stop = ata_bmdma_stop, .bmdma_status = ata_bmdma_status, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, + .freeze = nv_ck804_freeze, + .thaw = nv_ck804_thaw, + .error_handler = nv_error_handler, + .post_internal_cmd = ata_bmdma_post_internal_cmd, .data_xfer = ata_pio_data_xfer, .irq_handler = nv_ck804_interrupt, .irq_clear = ata_bmdma_irq_clear, @@ -234,22 +249,11 @@ static const struct ata_port_operations nv_ck804_ops = { .host_stop = nv_ck804_host_stop, }; -/* FIXME: The hardware provides the necessary SATA PHY controls - * to support ATA_FLAG_SATA_RESET. However, it is currently - * necessary to disable that flag, to solve misdetection problems. - * See http://bugme.osdl.org/show_bug.cgi?id=3352 for more info. - * - * This problem really needs to be investigated further. But in the - * meantime, we avoid ATA_FLAG_SATA_RESET to get people working. - */ static struct ata_port_info nv_port_info[] = { /* generic */ { .sht = &nv_sht, - .host_flags = ATA_FLAG_SATA | - /* ATA_FLAG_SATA_RESET | */ - ATA_FLAG_SRST | - ATA_FLAG_NO_LEGACY, + .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, .pio_mask = NV_PIO_MASK, .mwdma_mask = NV_MWDMA_MASK, .udma_mask = NV_UDMA_MASK, @@ -258,10 +262,7 @@ static struct ata_port_info nv_port_info[] = { /* nforce2/3 */ { .sht = &nv_sht, - .host_flags = ATA_FLAG_SATA | - /* ATA_FLAG_SATA_RESET | */ - ATA_FLAG_SRST | - ATA_FLAG_NO_LEGACY, + .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, .pio_mask = NV_PIO_MASK, .mwdma_mask = NV_MWDMA_MASK, .udma_mask = NV_UDMA_MASK, @@ -270,10 +271,7 @@ static struct ata_port_info nv_port_info[] = { /* ck804 */ { .sht = &nv_sht, - .host_flags = ATA_FLAG_SATA | - /* ATA_FLAG_SATA_RESET | */ - ATA_FLAG_SRST | - ATA_FLAG_NO_LEGACY, + .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, .pio_mask = NV_PIO_MASK, .mwdma_mask = NV_MWDMA_MASK, .udma_mask = NV_UDMA_MASK, @@ -410,6 +408,71 @@ static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val) iowrite32(val, (void __iomem *)ap->ioaddr.scr_addr + (sc_reg * 4)); } +static void nv_nf2_freeze(struct ata_port *ap) +{ + unsigned long scr_addr = ap->host_set->ports[0]->ioaddr.scr_addr; + int shift = ap->port_no * NV_INT_PORT_SHIFT; + u8 mask; + + mask = inb(scr_addr + NV_INT_ENABLE); + mask &= ~(NV_INT_ALL << shift); + outb(mask, scr_addr + NV_INT_ENABLE); +} + +static void nv_nf2_thaw(struct ata_port *ap) +{ + unsigned long scr_addr = ap->host_set->ports[0]->ioaddr.scr_addr; + int shift = ap->port_no * NV_INT_PORT_SHIFT; + u8 mask; + + outb(NV_INT_ALL << shift, scr_addr + NV_INT_STATUS); + + mask = inb(scr_addr + NV_INT_ENABLE); + mask |= (NV_INT_MASK << shift); + outb(mask, scr_addr + NV_INT_ENABLE); +} + +static void nv_ck804_freeze(struct ata_port *ap) +{ + void __iomem *mmio_base = ap->host_set->mmio_base; + int shift = ap->port_no * NV_INT_PORT_SHIFT; + u8 mask; + + mask = readb(mmio_base + NV_INT_ENABLE_CK804); + mask &= ~(NV_INT_ALL << shift); + writeb(mask, mmio_base + NV_INT_ENABLE_CK804); +} + +static void nv_ck804_thaw(struct ata_port *ap) +{ + void __iomem *mmio_base = ap->host_set->mmio_base; + int shift = ap->port_no * NV_INT_PORT_SHIFT; + u8 mask; + + writeb(NV_INT_ALL << shift, mmio_base + NV_INT_STATUS_CK804); + + mask = readb(mmio_base + NV_INT_ENABLE_CK804); + mask |= (NV_INT_MASK << shift); + writeb(mask, mmio_base + NV_INT_ENABLE_CK804); +} + +static int nv_hardreset(struct ata_port *ap, unsigned int *class) +{ + unsigned int dummy; + + /* SATA hardreset fails to retrieve proper device signature on + * some controllers. Don't classify on hardreset. For more + * info, see http://bugme.osdl.org/show_bug.cgi?id=3352 + */ + return sata_std_hardreset(ap, &dummy); +} + +static void nv_error_handler(struct ata_port *ap) +{ + ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, + nv_hardreset, ata_std_postreset); +} + static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { static int printed_version = 0; -- cgit v1.2.3 From 5a44efff4f8fe8139c0c4166ad5aae5f2fa5bced Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 17 Jun 2006 15:49:56 +0900 Subject: [PATCH] sata_nv: add hotplug support Add hotplug support. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/sata_nv.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c index 2a1bd85404e..19deaa42fbf 100644 --- a/drivers/scsi/sata_nv.c +++ b/drivers/scsi/sata_nv.c @@ -69,7 +69,8 @@ enum { NV_INT_PORT_SHIFT = 4, /* each port occupies 4 bits */ NV_INT_ALL = 0x0f, - NV_INT_MASK = NV_INT_DEV, + NV_INT_MASK = NV_INT_DEV | + NV_INT_ADDED | NV_INT_REMOVED, /* INT_CONFIG */ NV_INT_CONFIG = 0x12, @@ -324,6 +325,12 @@ static int nv_host_intr(struct ata_port *ap, u8 irq_stat) struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag); int handled; + /* freeze if hotplugged */ + if (unlikely(irq_stat & (NV_INT_ADDED | NV_INT_REMOVED))) { + ata_port_freeze(ap); + return 1; + } + /* bail out if not our interrupt */ if (!(irq_stat & NV_INT_DEV)) return 0; -- cgit v1.2.3 From c5fa46e175ccd02803031ea071060cdb01521736 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Tue, 20 Jun 2006 05:08:44 -0400 Subject: [libata] sata_nv: s/spin_lock_irqsave/spin_lock/ in irq handler We don't need to use the heavier spin lock in the irq handler. It's quite possible we can do this in nv_generic_interrupt() as well, but I didn't take the time to pursue that train of thought. Signed-off-by: Jeff Garzik --- drivers/scsi/sata_nv.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c index 19deaa42fbf..be8650f1702 100644 --- a/drivers/scsi/sata_nv.c +++ b/drivers/scsi/sata_nv.c @@ -371,14 +371,13 @@ static irqreturn_t nv_nf2_interrupt(int irq, void *dev_instance, struct pt_regs *regs) { struct ata_host_set *host_set = dev_instance; - unsigned long flags; u8 irq_stat; irqreturn_t ret; - spin_lock_irqsave(&host_set->lock, flags); + spin_lock(&host_set->lock); irq_stat = inb(host_set->ports[0]->ioaddr.scr_addr + NV_INT_STATUS); ret = nv_do_interrupt(host_set, irq_stat); - spin_unlock_irqrestore(&host_set->lock, flags); + spin_unlock(&host_set->lock); return ret; } @@ -387,14 +386,13 @@ static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance, struct pt_regs *regs) { struct ata_host_set *host_set = dev_instance; - unsigned long flags; u8 irq_stat; irqreturn_t ret; - spin_lock_irqsave(&host_set->lock, flags); + spin_lock(&host_set->lock); irq_stat = readb(host_set->mmio_base + NV_INT_STATUS_CK804); ret = nv_do_interrupt(host_set, irq_stat); - spin_unlock_irqrestore(&host_set->lock, flags); + spin_unlock(&host_set->lock); return ret; } -- cgit v1.2.3 From 40ef1d8d48e364dce689342adfdc475aa53f4808 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 16 Jun 2006 15:13:53 +0900 Subject: [PATCH] sata_via: convert to new EH, take #3 Convert sata_via to new EH. vt6420 used ATA_FLAG_SRST while vt6421 used ATA_FLAG_SATA_RESET. This difference seems to be an accident rather than intended. This patch makes both flavors use ata_bmdma_error_handler() which makes use of both SRST and SATA hardreset. This behavior change is intended and if it breaks anything, it should be very easy to spot. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/sata_via.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c index c6975c5580e..322890b400a 100644 --- a/drivers/scsi/sata_via.c +++ b/drivers/scsi/sata_via.c @@ -116,8 +116,6 @@ static const struct ata_port_operations svia_sata_ops = { .exec_command = ata_exec_command, .dev_select = ata_std_dev_select, - .phy_reset = sata_phy_reset, - .bmdma_setup = ata_bmdma_setup, .bmdma_start = ata_bmdma_start, .bmdma_stop = ata_bmdma_stop, @@ -127,7 +125,10 @@ static const struct ata_port_operations svia_sata_ops = { .qc_issue = ata_qc_issue_prot, .data_xfer = ata_pio_data_xfer, - .eng_timeout = ata_eng_timeout, + .freeze = ata_bmdma_freeze, + .thaw = ata_bmdma_thaw, + .error_handler = ata_bmdma_error_handler, + .post_internal_cmd = ata_bmdma_post_internal_cmd, .irq_handler = ata_interrupt, .irq_clear = ata_bmdma_irq_clear, @@ -142,7 +143,7 @@ static const struct ata_port_operations svia_sata_ops = { static struct ata_port_info svia_port_info = { .sht = &svia_sht, - .host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST | ATA_FLAG_NO_LEGACY, + .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, .pio_mask = 0x1f, .mwdma_mask = 0x07, .udma_mask = 0x7f, @@ -237,8 +238,7 @@ static struct ata_probe_ent *vt6421_init_probe_ent(struct pci_dev *pdev) INIT_LIST_HEAD(&probe_ent->node); probe_ent->sht = &svia_sht; - probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_SATA_RESET | - ATA_FLAG_NO_LEGACY; + probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY; probe_ent->port_ops = &svia_sata_ops; probe_ent->n_ports = N_PORTS; probe_ent->irq = pdev->irq; -- cgit v1.2.3 From d7a80dad2fe19a2b8c119c8e9cba605474a75a2b Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 16 Jun 2006 15:00:18 +0900 Subject: [PATCH] libata: convert several bmdma-style controllers to new EH, take #3 Convert sata_sis, svw, uli and vsc drivers to new EH. All the drivers used to specify ATA_FLAG_SATA_RESET to tell libata to use SATA hardreset instead of SRST. This patch makes all the converted drivers use the standard bmdma error handler which uses both SRST and SATA hardreset. All the controllers should be able to perform SRST but still needs verification. If some of the controllers can't do SRST, it will be very easy to spot as it will show up during boot probing. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/sata_sis.c | 9 +++++---- drivers/scsi/sata_svw.c | 10 ++++++---- drivers/scsi/sata_uli.c | 10 +++++----- drivers/scsi/sata_vsc.c | 8 +++++--- 4 files changed, 21 insertions(+), 16 deletions(-) diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c index a07e6e52517..809d337ed64 100644 --- a/drivers/scsi/sata_sis.c +++ b/drivers/scsi/sata_sis.c @@ -107,7 +107,6 @@ static const struct ata_port_operations sis_ops = { .check_status = ata_check_status, .exec_command = ata_exec_command, .dev_select = ata_std_dev_select, - .phy_reset = sata_phy_reset, .bmdma_setup = ata_bmdma_setup, .bmdma_start = ata_bmdma_start, .bmdma_stop = ata_bmdma_stop, @@ -115,7 +114,10 @@ static const struct ata_port_operations sis_ops = { .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, .data_xfer = ata_pio_data_xfer, - .eng_timeout = ata_eng_timeout, + .freeze = ata_bmdma_freeze, + .thaw = ata_bmdma_thaw, + .error_handler = ata_bmdma_error_handler, + .post_internal_cmd = ata_bmdma_post_internal_cmd, .irq_handler = ata_interrupt, .irq_clear = ata_bmdma_irq_clear, .scr_read = sis_scr_read, @@ -127,8 +129,7 @@ static const struct ata_port_operations sis_ops = { static struct ata_port_info sis_port_info = { .sht = &sis_sht, - .host_flags = ATA_FLAG_SATA | ATA_FLAG_SATA_RESET | - ATA_FLAG_NO_LEGACY, + .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, .pio_mask = 0x1f, .mwdma_mask = 0x7, .udma_mask = 0x7f, diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c index d9b51683648..c94b870cf37 100644 --- a/drivers/scsi/sata_svw.c +++ b/drivers/scsi/sata_svw.c @@ -314,7 +314,6 @@ static const struct ata_port_operations k2_sata_ops = { .check_status = k2_stat_check_status, .exec_command = ata_exec_command, .dev_select = ata_std_dev_select, - .phy_reset = sata_phy_reset, .bmdma_setup = k2_bmdma_setup_mmio, .bmdma_start = k2_bmdma_start_mmio, .bmdma_stop = ata_bmdma_stop, @@ -322,7 +321,10 @@ static const struct ata_port_operations k2_sata_ops = { .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, .data_xfer = ata_mmio_data_xfer, - .eng_timeout = ata_eng_timeout, + .freeze = ata_bmdma_freeze, + .thaw = ata_bmdma_thaw, + .error_handler = ata_bmdma_error_handler, + .post_internal_cmd = ata_bmdma_post_internal_cmd, .irq_handler = ata_interrupt, .irq_clear = ata_bmdma_irq_clear, .scr_read = k2_sata_scr_read, @@ -422,8 +424,8 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e writel(0x0, mmio_base + K2_SATA_SIM_OFFSET); probe_ent->sht = &k2_sata_sht; - probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_SATA_RESET | - ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO; + probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | + ATA_FLAG_MMIO; probe_ent->port_ops = &k2_sata_ops; probe_ent->n_ports = 4; probe_ent->irq = pdev->irq; diff --git a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c index e69ba229adc..f668c997e9a 100644 --- a/drivers/scsi/sata_uli.c +++ b/drivers/scsi/sata_uli.c @@ -103,8 +103,6 @@ static const struct ata_port_operations uli_ops = { .exec_command = ata_exec_command, .dev_select = ata_std_dev_select, - .phy_reset = sata_phy_reset, - .bmdma_setup = ata_bmdma_setup, .bmdma_start = ata_bmdma_start, .bmdma_stop = ata_bmdma_stop, @@ -113,7 +111,10 @@ static const struct ata_port_operations uli_ops = { .qc_issue = ata_qc_issue_prot, .data_xfer = ata_pio_data_xfer, - .eng_timeout = ata_eng_timeout, + .freeze = ata_bmdma_freeze, + .thaw = ata_bmdma_thaw, + .error_handler = ata_bmdma_error_handler, + .post_internal_cmd = ata_bmdma_post_internal_cmd, .irq_handler = ata_interrupt, .irq_clear = ata_bmdma_irq_clear, @@ -128,8 +129,7 @@ static const struct ata_port_operations uli_ops = { static struct ata_port_info uli_port_info = { .sht = &uli_sht, - .host_flags = ATA_FLAG_SATA | ATA_FLAG_SATA_RESET | - ATA_FLAG_NO_LEGACY, + .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, .pio_mask = 0x1f, /* pio0-4 */ .udma_mask = 0x7f, /* udma0-6 */ .port_ops = &uli_ops, diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c index 22ca7b848cf..d92e3dd3704 100644 --- a/drivers/scsi/sata_vsc.c +++ b/drivers/scsi/sata_vsc.c @@ -291,7 +291,6 @@ static const struct ata_port_operations vsc_sata_ops = { .exec_command = ata_exec_command, .check_status = ata_check_status, .dev_select = ata_std_dev_select, - .phy_reset = sata_phy_reset, .bmdma_setup = ata_bmdma_setup, .bmdma_start = ata_bmdma_start, .bmdma_stop = ata_bmdma_stop, @@ -299,7 +298,10 @@ static const struct ata_port_operations vsc_sata_ops = { .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, .data_xfer = ata_pio_data_xfer, - .eng_timeout = ata_eng_timeout, + .freeze = ata_bmdma_freeze, + .thaw = ata_bmdma_thaw, + .error_handler = ata_bmdma_error_handler, + .post_internal_cmd = ata_bmdma_post_internal_cmd, .irq_handler = vsc_sata_interrupt, .irq_clear = ata_bmdma_irq_clear, .scr_read = vsc_sata_scr_read, @@ -394,7 +396,7 @@ static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_d probe_ent->sht = &vsc_sata_sht; probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_MMIO | ATA_FLAG_SATA_RESET; + ATA_FLAG_MMIO; probe_ent->port_ops = &vsc_sata_ops; probe_ent->n_ports = 4; probe_ent->irq = pdev->irq; -- cgit v1.2.3 From 8ca84481b69513f7bf341c7dd9897023a04d7d1d Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 20 Jun 2006 03:26:14 -0700 Subject: [SCTP]: sctp_unpack_cookie() fix sizeof(pointer) != sizeof(array)... Signed-off-by: Al Viro Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- net/sctp/sm_make_chunk.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 5e0de3c0eea..2a877369169 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -1402,14 +1402,14 @@ struct sctp_association *sctp_unpack_cookie( sg.length = bodysize; key = (char *)ep->secret_key[ep->current_key]; - memset(digest, 0x00, sizeof(digest)); + memset(digest, 0x00, SCTP_SIGNATURE_SIZE); sctp_crypto_hmac(sctp_sk(ep->base.sk)->hmac, key, &keylen, &sg, 1, digest); if (memcmp(digest, cookie->signature, SCTP_SIGNATURE_SIZE)) { /* Try the previous key. */ key = (char *)ep->secret_key[ep->last_key]; - memset(digest, 0x00, sizeof(digest)); + memset(digest, 0x00, SCTP_SIGNATURE_SIZE); sctp_crypto_hmac(sctp_sk(ep->base.sk)->hmac, key, &keylen, &sg, 1, digest); -- cgit v1.2.3 From ff7512e1a2a3504649d3716a757f43807b6d26ef Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 20 Jun 2006 03:27:27 -0700 Subject: [ATM]: fix broken uses of NIPQUAD in net/atm NIPQUAD expects an l-value of type __be32, _NOT_ a pointer to __be32. Signed-off-by: Al Viro Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- net/atm/mpc.c | 13 +++---------- net/atm/mpoa_caches.c | 12 ++++-------- 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/net/atm/mpc.c b/net/atm/mpc.c index c304ef1513b..a48a5d58040 100644 --- a/net/atm/mpc.c +++ b/net/atm/mpc.c @@ -229,20 +229,15 @@ int atm_mpoa_delete_qos(struct atm_mpoa_qos *entry) /* this is buggered - we need locking for qos_head */ void atm_mpoa_disp_qos(struct seq_file *m) { - unsigned char *ip; - char ipaddr[16]; struct atm_mpoa_qos *qos; qos = qos_head; seq_printf(m, "QoS entries for shortcuts:\n"); seq_printf(m, "IP address\n TX:max_pcr pcr min_pcr max_cdv max_sdu\n RX:max_pcr pcr min_pcr max_cdv max_sdu\n"); - ipaddr[sizeof(ipaddr)-1] = '\0'; while (qos != NULL) { - ip = (unsigned char *)&qos->ipaddr; - sprintf(ipaddr, "%u.%u.%u.%u", NIPQUAD(ip)); seq_printf(m, "%u.%u.%u.%u\n %-7d %-7d %-7d %-7d %-7d\n %-7d %-7d %-7d %-7d %-7d\n", - NIPQUAD(ipaddr), + NIPQUAD(qos->ipaddr), qos->qos.txtp.max_pcr, qos->qos.txtp.pcr, qos->qos.txtp.min_pcr, qos->qos.txtp.max_cdv, qos->qos.txtp.max_sdu, qos->qos.rxtp.max_pcr, qos->qos.rxtp.pcr, qos->qos.rxtp.min_pcr, qos->qos.rxtp.max_cdv, qos->qos.rxtp.max_sdu); qos = qos->next; @@ -1083,7 +1078,6 @@ static void MPOA_trigger_rcvd(struct k_message *msg, struct mpoa_client *mpc) static void check_qos_and_open_shortcut(struct k_message *msg, struct mpoa_client *client, in_cache_entry *entry) { uint32_t dst_ip = msg->content.in_info.in_dst_ip; - unsigned char *ip __attribute__ ((unused)) = (unsigned char *)&dst_ip; struct atm_mpoa_qos *qos = atm_mpoa_search_qos(dst_ip); eg_cache_entry *eg_entry = client->eg_ops->get_by_src_ip(dst_ip, client); @@ -1097,7 +1091,7 @@ static void check_qos_and_open_shortcut(struct k_message *msg, struct mpoa_clien entry->shortcut = eg_entry->shortcut; } if(entry->shortcut){ - dprintk("mpoa: (%s) using egress SVC to reach %u.%u.%u.%u\n",client->dev->name, NIPQUAD(ip)); + dprintk("mpoa: (%s) using egress SVC to reach %u.%u.%u.%u\n",client->dev->name, NIPQUAD(dst_ip)); client->eg_ops->put(eg_entry); return; } @@ -1123,8 +1117,7 @@ static void MPOA_res_reply_rcvd(struct k_message *msg, struct mpoa_client *mpc) uint32_t dst_ip = msg->content.in_info.in_dst_ip; in_cache_entry *entry = mpc->in_ops->get(dst_ip, mpc); - ip = (unsigned char *)&dst_ip; - dprintk("mpoa: (%s) MPOA_res_reply_rcvd: ip %u.%u.%u.%u\n", mpc->dev->name, NIPQUAD(ip)); + dprintk("mpoa: (%s) MPOA_res_reply_rcvd: ip %u.%u.%u.%u\n", mpc->dev->name, NIPQUAD(dst_ip)); ddprintk("mpoa: (%s) MPOA_res_reply_rcvd() entry = %p", mpc->dev->name, entry); if(entry == NULL){ printk("\nmpoa: (%s) ARGH, received res. reply for an entry that doesn't exist.\n", mpc->dev->name); diff --git a/net/atm/mpoa_caches.c b/net/atm/mpoa_caches.c index 64ddebb6406..781ed1b9329 100644 --- a/net/atm/mpoa_caches.c +++ b/net/atm/mpoa_caches.c @@ -223,7 +223,6 @@ static void in_cache_remove_entry(in_cache_entry *entry, but an easy one... */ static void clear_count_and_expired(struct mpoa_client *client) { - unsigned char *ip; in_cache_entry *entry, *next_entry; struct timeval now; @@ -236,8 +235,7 @@ static void clear_count_and_expired(struct mpoa_client *client) next_entry = entry->next; if((now.tv_sec - entry->tv.tv_sec) > entry->ctrl_info.holding_time){ - ip = (unsigned char*)&entry->ctrl_info.in_dst_ip; - dprintk("mpoa: mpoa_caches.c: holding time expired, ip = %u.%u.%u.%u\n", NIPQUAD(ip)); + dprintk("mpoa: mpoa_caches.c: holding time expired, ip = %u.%u.%u.%u\n", NIPQUAD(entry->ctrl_info.in_dst_ip)); client->in_ops->remove_entry(entry, client); } entry = next_entry; @@ -455,7 +453,6 @@ static void eg_cache_remove_entry(eg_cache_entry *entry, static eg_cache_entry *eg_cache_add_entry(struct k_message *msg, struct mpoa_client *client) { - unsigned char *ip; eg_cache_entry *entry = kmalloc(sizeof(eg_cache_entry), GFP_KERNEL); if (entry == NULL) { @@ -463,8 +460,7 @@ static eg_cache_entry *eg_cache_add_entry(struct k_message *msg, struct mpoa_cli return NULL; } - ip = (unsigned char *)&msg->content.eg_info.eg_dst_ip; - dprintk("mpoa: mpoa_caches.c: adding an egress entry, ip = %u.%u.%u.%u, this should be our IP\n", NIPQUAD(ip)); + dprintk("mpoa: mpoa_caches.c: adding an egress entry, ip = %u.%u.%u.%u, this should be our IP\n", NIPQUAD(msg->content.eg_info.eg_dst_ip)); memset(entry, 0, sizeof(eg_cache_entry)); atomic_set(&entry->use, 1); @@ -481,8 +477,8 @@ static eg_cache_entry *eg_cache_add_entry(struct k_message *msg, struct mpoa_cli do_gettimeofday(&(entry->tv)); entry->entry_state = EGRESS_RESOLVED; dprintk("mpoa: mpoa_caches.c: new_eg_cache_entry cache_id %lu\n", ntohl(entry->ctrl_info.cache_id)); - ip = (unsigned char *)&entry->ctrl_info.mps_ip; - dprintk("mpoa: mpoa_caches.c: mps_ip = %u.%u.%u.%u\n", NIPQUAD(ip)); + dprintk("mpoa: mpoa_caches.c: mps_ip = %u.%u.%u.%u\n", + NIPQUAD(entry->ctrl_info.mps_ip)); atomic_inc(&entry->use); write_unlock_irq(&client->egress_lock); -- cgit v1.2.3 From 4faf4e0e7d4e1935fbfc5043d3ebd8d51a3d898d Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 20 Jun 2006 19:24:07 +0100 Subject: [ARM] 3600/1: increase amba-pl010 UART_NR to 8 Patch from Lennert Buytenhek The cirrus ep93xx has 3 pl010 UARTs, while amba-pl010.c only allows for 2 by default. A while ago, I think we agreed on changing the 2 to 8, but I don't see this in 2.6.17 yet. Signed-off-by: Lennert Buytenhek Signed-off-by: Russell King --- drivers/serial/amba-pl010.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c index 1631414000a..e920d196d0b 100644 --- a/drivers/serial/amba-pl010.c +++ b/drivers/serial/amba-pl010.c @@ -52,7 +52,7 @@ #include -#define UART_NR 2 +#define UART_NR 8 #define SERIAL_AMBA_MAJOR 204 #define SERIAL_AMBA_MINOR 16 -- cgit v1.2.3 From e6fea6a5e30efef56dee2b8455fde0811922055b Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 20 Jun 2006 19:26:41 +0100 Subject: [ARM] 3602/1: ixp23xx: fix two typos Patch from Lennert Buytenhek Fix two typos in include/asm-arm/arch-ixp23xx. Signed-off-by: Lennert Buytenhek Signed-off-by: Russell King --- include/asm-arm/arch-ixp23xx/entry-macro.S | 2 +- include/asm-arm/arch-ixp23xx/ixp23xx.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/asm-arm/arch-ixp23xx/entry-macro.S b/include/asm-arm/arch-ixp23xx/entry-macro.S index 0ef4e6016ac..867761677b5 100644 --- a/include/asm-arm/arch-ixp23xx/entry-macro.S +++ b/include/asm-arm/arch-ixp23xx/entry-macro.S @@ -8,7 +8,7 @@ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp ldr \irqnr, =(IXP23XX_INTC_VIRT + IXP23XX_INTR_IRQ_ENC_ST_OFFSET) ldr \irqnr, [\irqnr] @ get interrupt number - cmp \irqnr, #0x0 @ suprious interrupt ? + cmp \irqnr, #0x0 @ spurious interrupt ? movne \irqnr, \irqnr, lsr #2 @ skip unwanted low order bits subne \irqnr, \irqnr, #1 @ convert to 0 based diff --git a/include/asm-arm/arch-ixp23xx/ixp23xx.h b/include/asm-arm/arch-ixp23xx/ixp23xx.h index e49e1ca61b1..01efdbd1180 100644 --- a/include/asm-arm/arch-ixp23xx/ixp23xx.h +++ b/include/asm-arm/arch-ixp23xx/ixp23xx.h @@ -251,7 +251,7 @@ * CAP CSRs. ****************************************************************************/ #define IXP23XX_GLOBAL_REG(x) ((volatile unsigned long *)(IXP23XX_CAP_CSR_VIRT + 0x4a00 + (x))) -#define IXP23XX_PROD_IDG IXP23XX_GLOBAL_REG(0x00) +#define IXP23XX_PRODUCT_ID IXP23XX_GLOBAL_REG(0x00) #define IXP23XX_MISC_CONTROL IXP23XX_GLOBAL_REG(0x04) #define IXP23XX_MSF_CLK_CNTRL IXP23XX_GLOBAL_REG(0x08) #define IXP23XX_RESET0 IXP23XX_GLOBAL_REG(0x0c) -- cgit v1.2.3 From c322e24b40b83bbdfa7c269bc0105e76a39e627f Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Tue, 20 Jun 2006 19:26:42 +0100 Subject: [ARM] 3606/1: PXA27x SSP Register definitions Patch from Liam Girdwood This patch adds some new PXA27x SSP port registers and also fixes the SSP slots per frame macro Changes:- o SSCR0_SlotPerFrm fixed o Added SSP port TSA, RSA, TSS and ACD registers Signed-off-by: Liam Girdwood Signed-off-by: Russell King --- include/asm-arm/arch-pxa/pxa-regs.h | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h index c8f53a71c07..7c1aefd99d5 100644 --- a/include/asm-arm/arch-pxa/pxa-regs.h +++ b/include/asm-arm/arch-pxa/pxa-regs.h @@ -1626,7 +1626,7 @@ #define SSCR0_RIM (1 << 22) /* Receive FIFO overrrun interrupt mask */ #define SSCR0_TUM (1 << 23) /* Transmit FIFO underrun interrupt mask */ #define SSCR0_FRDC (0x07000000) /* Frame rate divider control (mask) */ -#define SSCR0_SlotsPerFrm(c) ((x) - 1) /* Time slots per frame [1..8] */ +#define SSCR0_SlotsPerFrm(x) ((x) - 1) /* Time slots per frame [1..8] */ #define SSCR0_ADC (1 << 30) /* Audio clock select */ #define SSCR0_MOD (1 << 31) /* Mode (normal or network) */ #endif @@ -1707,6 +1707,10 @@ #if defined (CONFIG_PXA27x) #define SSTO_P1 __REG(0x41000028) /* SSP Port 1 Time Out Register */ #define SSPSP_P1 __REG(0x4100002C) /* SSP Port 1 Programmable Serial Protocol */ +#define SSTSA_P1 __REG(0x41000030) /* SSP Port 1 Tx Timeslot Active */ +#define SSRSA_P1 __REG(0x41000034) /* SSP Port 1 Rx Timeslot Active */ +#define SSTSS_P1 __REG(0x41000038) /* SSP Port 1 Timeslot Status */ +#define SSACD_P1 __REG(0x4100003C) /* SSP Port 1 Audio Clock Divider */ #define SSCR0_P2 __REG(0x41700000) /* SSP Port 2 Control Register 0 */ #define SSCR1_P2 __REG(0x41700004) /* SSP Port 2 Control Register 1 */ #define SSSR_P2 __REG(0x41700008) /* SSP Port 2 Status Register */ @@ -1714,6 +1718,10 @@ #define SSDR_P2 __REG(0x41700010) /* (Write / Read) SSP Port 2 Data Write Register/SSP Data Read Register */ #define SSTO_P2 __REG(0x41700028) /* SSP Port 2 Time Out Register */ #define SSPSP_P2 __REG(0x4170002C) /* SSP Port 2 Programmable Serial Protocol */ +#define SSTSA_P2 __REG(0x41700030) /* SSP Port 2 Tx Timeslot Active */ +#define SSRSA_P2 __REG(0x41700034) /* SSP Port 2 Rx Timeslot Active */ +#define SSTSS_P2 __REG(0x41700038) /* SSP Port 2 Timeslot Status */ +#define SSACD_P2 __REG(0x4170003C) /* SSP Port 2 Audio Clock Divider */ #define SSCR0_P3 __REG(0x41900000) /* SSP Port 3 Control Register 0 */ #define SSCR1_P3 __REG(0x41900004) /* SSP Port 3 Control Register 1 */ #define SSSR_P3 __REG(0x41900008) /* SSP Port 3 Status Register */ @@ -1721,6 +1729,10 @@ #define SSDR_P3 __REG(0x41900010) /* (Write / Read) SSP Port 3 Data Write Register/SSP Data Read Register */ #define SSTO_P3 __REG(0x41900028) /* SSP Port 3 Time Out Register */ #define SSPSP_P3 __REG(0x4190002C) /* SSP Port 3 Programmable Serial Protocol */ +#define SSTSA_P3 __REG(0x41900030) /* SSP Port 3 Tx Timeslot Active */ +#define SSRSA_P3 __REG(0x41900034) /* SSP Port 3 Rx Timeslot Active */ +#define SSTSS_P3 __REG(0x41900038) /* SSP Port 3 Timeslot Status */ +#define SSACD_P3 __REG(0x4190003C) /* SSP Port 3 Audio Clock Divider */ #else /* PXA255 (only port 2) and PXA26x ports*/ #define SSTO_P1 __REG(0x41000028) /* SSP Port 1 Time Out Register */ #define SSPSP_P1 __REG(0x4100002C) /* SSP Port 1 Programmable Serial Protocol */ @@ -1747,6 +1759,10 @@ #define SSDR_P(x) (*(((x) == 1) ? &SSDR_P1 : ((x) == 2) ? &SSDR_P2 : ((x) == 3) ? &SSDR_P3 : NULL)) #define SSTO_P(x) (*(((x) == 1) ? &SSTO_P1 : ((x) == 2) ? &SSTO_P2 : ((x) == 3) ? &SSTO_P3 : NULL)) #define SSPSP_P(x) (*(((x) == 1) ? &SSPSP_P1 : ((x) == 2) ? &SSPSP_P2 : ((x) == 3) ? &SSPSP_P3 : NULL)) +#define SSTSA_P(x) (*(((x) == 1) ? &SSTSA_P1 : ((x) == 2) ? &SSTSA_P2 : ((x) == 3) ? &SSTSA_P3 : NULL)) +#define SSRSA_P(x) (*(((x) == 1) ? &SSRSA_P1 : ((x) == 2) ? &SSRSA_P2 : ((x) == 3) ? &SSRSA_P3 : NULL)) +#define SSTSS_P(x) (*(((x) == 1) ? &SSTSS_P1 : ((x) == 2) ? &SSTSS_P2 : ((x) == 3) ? &SSTSS_P3 : NULL)) +#define SSACD_P(x) (*(((x) == 1) ? &SSACD_P1 : ((x) == 2) ? &SSACD_P2 : ((x) == 3) ? &SSACD_P3 : NULL)) /* * MultiMediaCard (MMC) controller -- cgit v1.2.3 From d6bdbb8ef3e4a9cafc747e1444b4908f9f2f548d Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Tue, 20 Jun 2006 19:27:34 +0100 Subject: [ARM] 3603/1: AT91RM9200 remove old files Patch from Andrew Victor This patch removes the now unnecessary include/asm-arm/arch-at91rm9200/pio.h file. The pin configuration is now handled in the platform-device setup code (arch/arm/mach-at91rm9200/devices.c). Signed-off-by: Andrew Victor Signed-off-by: Russell King --- include/asm-arm/arch-at91rm9200/pio.h | 115 ---------------------------------- 1 file changed, 115 deletions(-) delete mode 100644 include/asm-arm/arch-at91rm9200/pio.h diff --git a/include/asm-arm/arch-at91rm9200/pio.h b/include/asm-arm/arch-at91rm9200/pio.h deleted file mode 100644 index a89501b4a70..00000000000 --- a/include/asm-arm/arch-at91rm9200/pio.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * include/asm-arm/arch-at91rm9200/pio.h - * - * Copyright (C) 2003 SAN People - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -#ifndef __ASM_ARCH_PIO_H -#define __ASM_ARCH_PIO_H - -#include - -static inline void AT91_CfgPIO_USART0(void) { - at91_sys_write(AT91_PIOA + PIO_PDR, AT91_PA17_TXD0 | AT91_PA18_RXD0 | AT91_PA20_CTS0); - - /* - * Errata #39 - RTS0 is not internally connected to PA21. We need to drive - * the pin manually. Default is off (RTS is active low). - */ - at91_sys_write(AT91_PIOA + PIO_PER, AT91_PA21_RTS0); - at91_sys_write(AT91_PIOA + PIO_OER, AT91_PA21_RTS0); - at91_sys_write(AT91_PIOA + PIO_SODR, AT91_PA21_RTS0); -} - -static inline void AT91_CfgPIO_USART1(void) { - at91_sys_write(AT91_PIOB + PIO_PDR, AT91_PB18_RI1 | AT91_PB19_DTR1 - | AT91_PB20_TXD1 | AT91_PB21_RXD1 | AT91_PB23_DCD1 - | AT91_PB24_CTS1 | AT91_PB25_DSR1 | AT91_PB26_RTS1); -} - -static inline void AT91_CfgPIO_USART2(void) { - at91_sys_write(AT91_PIOA + PIO_PDR, AT91_PA22_RXD2 | AT91_PA23_TXD2); -} - -static inline void AT91_CfgPIO_USART3(void) { - at91_sys_write(AT91_PIOA + PIO_PDR, AT91_PA5_TXD3 | AT91_PA6_RXD3); - at91_sys_write(AT91_PIOA + PIO_BSR, AT91_PA5_TXD3 | AT91_PA6_RXD3); -} - -static inline void AT91_CfgPIO_DBGU(void) { - at91_sys_write(AT91_PIOA + PIO_PDR, AT91_PA31_DTXD | AT91_PA30_DRXD); -} - -/* - * Enable the Two-Wire interface. - */ -static inline void AT91_CfgPIO_TWI(void) { - at91_sys_write(AT91_PIOA + PIO_PDR, AT91_PA25_TWD | AT91_PA26_TWCK); - at91_sys_write(AT91_PIOA + PIO_ASR, AT91_PA25_TWD | AT91_PA26_TWCK); - at91_sys_write(AT91_PIOA + PIO_MDER, AT91_PA25_TWD | AT91_PA26_TWCK); /* open drain */ -} - -/* - * Enable the Serial Peripheral Interface. - */ -static inline void AT91_CfgPIO_SPI(void) { - at91_sys_write(AT91_PIOA + PIO_PDR, AT91_PA0_MISO | AT91_PA1_MOSI | AT91_PA2_SPCK); -} - -static inline void AT91_CfgPIO_SPI_CS0(void) { - at91_sys_write(AT91_PIOA + PIO_PDR, AT91_PA3_NPCS0); -} - -static inline void AT91_CfgPIO_SPI_CS1(void) { - at91_sys_write(AT91_PIOA + PIO_PDR, AT91_PA4_NPCS1); -} - -static inline void AT91_CfgPIO_SPI_CS2(void) { - at91_sys_write(AT91_PIOA + PIO_PDR, AT91_PA5_NPCS2); -} - -static inline void AT91_CfgPIO_SPI_CS3(void) { - at91_sys_write(AT91_PIOA + PIO_PDR, AT91_PA6_NPCS3); -} - -/* - * Select the DataFlash card. - */ -static inline void AT91_CfgPIO_DataFlashCard(void) { - at91_sys_write(AT91_PIOB + PIO_PER, AT91_PIO_P(7)); - at91_sys_write(AT91_PIOB + PIO_OER, AT91_PIO_P(7)); - at91_sys_write(AT91_PIOB + PIO_CODR, AT91_PIO_P(7)); -} - -/* - * Enable NAND Flash (SmartMedia) interface. - */ -static inline void AT91_CfgPIO_SmartMedia(void) { - /* enable PC0=SMCE, PC1=SMOE, PC3=SMWE, A21=CLE, A22=ALE */ - at91_sys_write(AT91_PIOC + PIO_ASR, AT91_PC0_BFCK | AT91_PC1_BFRDY_SMOE | AT91_PC3_BFBAA_SMWE); - at91_sys_write(AT91_PIOC + PIO_PDR, AT91_PC0_BFCK | AT91_PC1_BFRDY_SMOE | AT91_PC3_BFBAA_SMWE); - - /* Configure PC2 as input (signal READY of the SmartMedia) */ - at91_sys_write(AT91_PIOC + PIO_PER, AT91_PC2_BFAVD); /* enable direct output enable */ - at91_sys_write(AT91_PIOC + PIO_ODR, AT91_PC2_BFAVD); /* disable output */ - - /* Configure PB1 as input (signal Card Detect of the SmartMedia) */ - at91_sys_write(AT91_PIOB + PIO_PER, AT91_PIO_P(1)); /* enable direct output enable */ - at91_sys_write(AT91_PIOB + PIO_ODR, AT91_PIO_P(1)); /* disable output */ -} - -static inline int AT91_PIO_SmartMedia_RDY(void) { - return (at91_sys_read(AT91_PIOC + PIO_PDSR) & AT91_PIO_P(2)) ? 1 : 0; -} - -static inline int AT91_PIO_SmartMedia_CardDetect(void) { - return (at91_sys_read(AT91_PIOB + PIO_PDSR) & AT91_PIO_P(1)) ? 1 : 0; -} - -#endif -- cgit v1.2.3 From 6902f523a328bba5af036699b1352389c0746526 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Tue, 20 Jun 2006 19:30:18 +0100 Subject: [ARM] 3604/1: AT91RM9200 New boards Patch from Andrew Victor This patch adds support for an additional 4 AT91RM9200-based boards: 1. Conitec ARM&EVA [MACH_CARMEVA] (http://www.conitec.net/english/linuxboard.htm) 2. KwikByte KB920x [MACH_KB9200] (http://kwikbyte.com/KB9202_description_new.htm) 3. Embest ATEB9200 [MACH_ATEB9200] (http://www.embedinfo.com/english/product/ATEB9200.asp) 4. Sperry-Sun KAFA board [MACH_KAFA] (unknown) Signed-off-by: Andrew Victor Signed-off-by: Russell King --- arch/arm/boot/compressed/head-at91rm9200.S | 12 + arch/arm/configs/ateb9200_defconfig | 1312 ++++++++++++++++++++++++++++ arch/arm/configs/carmeva_defconfig | 723 +++++++++++++++ arch/arm/configs/kafa_defconfig | 884 +++++++++++++++++++ arch/arm/configs/kb9202_defconfig | 780 +++++++++++++++++ arch/arm/mach-at91rm9200/Kconfig | 12 + arch/arm/mach-at91rm9200/Makefile | 10 +- arch/arm/mach-at91rm9200/board-carmeva.c | 131 +++ arch/arm/mach-at91rm9200/board-eb9200.c | 130 +++ arch/arm/mach-at91rm9200/board-kafa.c | 116 +++ arch/arm/mach-at91rm9200/board-kb9202.c | 125 +++ 11 files changed, 4231 insertions(+), 4 deletions(-) create mode 100644 arch/arm/configs/ateb9200_defconfig create mode 100644 arch/arm/configs/carmeva_defconfig create mode 100644 arch/arm/configs/kafa_defconfig create mode 100644 arch/arm/configs/kb9202_defconfig create mode 100644 arch/arm/mach-at91rm9200/board-carmeva.c create mode 100644 arch/arm/mach-at91rm9200/board-eb9200.c create mode 100644 arch/arm/mach-at91rm9200/board-kafa.c create mode 100644 arch/arm/mach-at91rm9200/board-kb9202.c diff --git a/arch/arm/boot/compressed/head-at91rm9200.S b/arch/arm/boot/compressed/head-at91rm9200.S index 2119ea62b54..57a3b163b2c 100644 --- a/arch/arm/boot/compressed/head-at91rm9200.S +++ b/arch/arm/boot/compressed/head-at91rm9200.S @@ -49,6 +49,18 @@ cmp r7, r3 beq 99f + @ Embest ATEB9200 : 923 + mov r3, #(MACH_TYPE_ATEB9200 & 0xff) + orr r3, r3, #(MACH_TYPE_ATEB9200 & 0xff00) + cmp r7, r3 + beq 99f + + @ Sperry-Sun KAFA : 662 + mov r3, #(MACH_TYPE_KAFA & 0xff) + orr r3, r3, #(MACH_TYPE_KAFA & 0xff00) + cmp r7, r3 + beq 99f + @ Unknown board, use the AT91RM9200DK board @ mov r7, #MACH_TYPE_AT91RM9200 mov r7, #(MACH_TYPE_AT91RM9200DK & 0xff) diff --git a/arch/arm/configs/ateb9200_defconfig b/arch/arm/configs/ateb9200_defconfig new file mode 100644 index 00000000000..69c39e09874 --- /dev/null +++ b/arch/arm/configs/ateb9200_defconfig @@ -0,0 +1,1312 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.17-rc3 +# Sun May 7 16:53:18 2006 +# +CONFIG_ARM=y +CONFIG_MMU=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_VECTORS_BASE=0xffff0000 + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +# CONFIG_RELAY is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_UID16=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y + +# +# Block layer +# +# CONFIG_BLK_DEV_IO_TRACE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" + +# +# System Type +# +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_IOP3XX is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_AAEC2000 is not set +CONFIG_ARCH_AT91RM9200=y + +# +# AT91RM9200 Implementations +# + +# +# AT91RM9200 Board Type +# +# CONFIG_ARCH_AT91RM9200DK is not set +# CONFIG_MACH_AT91RM9200EK is not set +# CONFIG_MACH_CSB337 is not set +# CONFIG_MACH_CSB637 is not set +# CONFIG_MACH_CARMEVA is not set +# CONFIG_MACH_KB9200 is not set +CONFIG_MACH_ATEB9200=y +# CONFIG_MACH_KAFA is not set + +# +# AT91 Feature Selections +# +# CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_ARM920T=y +CONFIG_CPU_32v4=y +CONFIG_CPU_ABRT_EV4T=y +CONFIG_CPU_CACHE_V4WT=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set + +# +# Bus support +# + +# +# PCCARD (PCMCIA/CardBus) support +# +CONFIG_PCCARD=m +# CONFIG_PCMCIA_DEBUG is not set +CONFIG_PCMCIA=m +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_PCMCIA_IOCTL=y + +# +# PC-card bridges +# +CONFIG_AT91_CF=m + +# +# Kernel Features +# +CONFIG_PREEMPT=y +CONFIG_NO_IDLE_HZ=y +CONFIG_HZ=100 +# CONFIG_AEABI is not set +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4096 +# CONFIG_LEDS is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="" +# CONFIG_XIP_KERNEL is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set +# CONFIG_ARTHUR is not set + +# +# Power management options +# +CONFIG_PM=y +CONFIG_PM_LEGACY=y +# CONFIG_PM_DEBUG is not set +# CONFIG_APM is not set + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +CONFIG_NET_KEY=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +# CONFIG_DECNET is not set +CONFIG_LLC=m +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +CONFIG_IEEE80211=m +# CONFIG_IEEE80211_DEBUG is not set +CONFIG_IEEE80211_CRYPT_WEP=m +CONFIG_IEEE80211_CRYPT_CCMP=m +CONFIG_IEEE80211_CRYPT_TKIP=m +# CONFIG_IEEE80211_SOFTMAC is not set +CONFIG_WIRELESS_EXT=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +# CONFIG_MTD_BLOCK is not set +CONFIG_MTD_BLOCK_RO=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +CONFIG_MTD_AT91_DATAFLASH=y +# CONFIG_MTD_AT91_DATAFLASH_CARD is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +CONFIG_BLK_DEV_NBD=m +# CONFIG_BLK_DEV_UB is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=m +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=m +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +CONFIG_BLK_DEV_SR=m +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=m +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI Transport Attributes +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set + +# +# SCSI low-level drivers +# +# CONFIG_ISCSI_TCP is not set +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_DEBUG is not set + +# +# PCMCIA SCSI adapter support +# +# CONFIG_PCMCIA_AHA152X is not set +# CONFIG_PCMCIA_FDOMAIN is not set +# CONFIG_PCMCIA_NINJA_SCSI is not set +# CONFIG_PCMCIA_QLOGIC is not set +# CONFIG_PCMCIA_SYM53C500 is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# I2O device support +# + +# +# Network device support +# +CONFIG_NETDEVICES=y +CONFIG_DUMMY=m +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +CONFIG_TUN=m + +# +# PHY device support +# +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +CONFIG_DAVICOM_PHY=y +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +CONFIG_ARM_AT91_ETHER=y +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +CONFIG_NET_RADIO=y +# CONFIG_NET_WIRELESS_RTNETLINK is not set + +# +# Obsolete Wireless cards support (pre-802.11) +# +# CONFIG_STRIP is not set +# CONFIG_PCMCIA_WAVELAN is not set +# CONFIG_PCMCIA_NETWAVE is not set + +# +# Wireless 802.11 Frequency Hopping cards support +# +# CONFIG_PCMCIA_RAYCS is not set + +# +# Wireless 802.11b ISA/PCI cards support +# +# CONFIG_HERMES is not set +# CONFIG_ATMEL is not set + +# +# Wireless 802.11b Pcmcia/Cardbus cards support +# +# CONFIG_AIRO_CS is not set +# CONFIG_PCMCIA_WL3501 is not set +# CONFIG_HOSTAP is not set +CONFIG_NET_WIRELESS=y + +# +# PCMCIA network device support +# +# CONFIG_NET_PCMCIA is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +CONFIG_PPP=m +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m +# CONFIG_PPP_MPPE is not set +CONFIG_PPPOE=m +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_AT91=y +CONFIG_SERIAL_AT91_CONSOLE=y +# CONFIG_SERIAL_AT91_TTYAT is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set + +# +# Ftape, the floppy tape device driver +# + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +# CONFIG_CARDMAN_4000 is not set +# CONFIG_CARDMAN_4040 is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set +CONFIG_AT91_SPI=y +CONFIG_AT91_SPIDEV=y + +# +# I2C support +# +CONFIG_I2C=m +CONFIG_I2C_CHARDEV=m + +# +# I2C Algorithms +# +CONFIG_I2C_ALGOBIT=m +CONFIG_I2C_ALGOPCF=m +CONFIG_I2C_ALGOPCA=m + +# +# I2C Hardware Bus support +# +CONFIG_I2C_AT91=m +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_PCA_ISA is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ASB100 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_FSCHER is not set +# CONFIG_SENSORS_FSCPOS is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set +# CONFIG_USB_DABUSB is not set + +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +CONFIG_SOUND=y + +# +# Advanced Linux Sound Architecture +# +# CONFIG_SND is not set + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ARCH_HAS_EHCI is not set +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_SUSPEND is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_ISP116X_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_SL811_HCD is not set + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_DPCM=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=m +CONFIG_USB_HIDINPUT=y +# CONFIG_USB_HIDINPUT_POWERBOOK is not set +CONFIG_HID_FF=y +CONFIG_HID_PID=y +CONFIG_LOGITECH_FF=y +CONFIG_THRUSTMASTER_FF=y +CONFIG_USB_HIDDEV=y + +# +# USB HID Boot Protocol drivers +# +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set +# CONFIG_USB_AIPTEK is not set +# CONFIG_USB_WACOM is not set +# CONFIG_USB_ACECAD is not set +# CONFIG_USB_KBTAB is not set +# CONFIG_USB_POWERMATE is not set +# CONFIG_USB_TOUCHSCREEN is not set +# CONFIG_USB_YEALINK is not set +# CONFIG_USB_XPAD is not set +# CONFIG_USB_ATI_REMOTE is not set +# CONFIG_USB_ATI_REMOTE2 is not set +# CONFIG_USB_KEYSPAN_REMOTE is not set +# CONFIG_USB_APPLETOUCH is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +CONFIG_USB_USBNET=y +CONFIG_USB_NET_AX8817X=y +CONFIG_USB_NET_CDCETHER=y +CONFIG_USB_NET_GL620A=y +CONFIG_USB_NET_NET1080=y +CONFIG_USB_NET_PLUSB=y +CONFIG_USB_NET_RNDIS_HOST=y +CONFIG_USB_NET_CDC_SUBSET=y +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +CONFIG_USB_BELKIN=y +CONFIG_USB_ARMLINUX=y +CONFIG_USB_EPSON2888=y +CONFIG_USB_NET_ZAURUS=y +# CONFIG_USB_ZD1201 is not set +CONFIG_USB_MON=y + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +# CONFIG_USB_SERIAL_AIRPRIME is not set +# CONFIG_USB_SERIAL_ANYDATA is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +CONFIG_USB_SERIAL_CP2101=m +# CONFIG_USB_SERIAL_CYPRESS_M8 is not set +# CONFIG_USB_SERIAL_EMPEG is not set +CONFIG_USB_SERIAL_FTDI_SIO=m +# CONFIG_USB_SERIAL_FUNSOFT is not set +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_IPAQ is not set +# CONFIG_USB_SERIAL_IR is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_EDGEPORT_TI is not set +# CONFIG_USB_SERIAL_GARMIN is not set +# CONFIG_USB_SERIAL_IPW is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +# CONFIG_USB_SERIAL_KEYSPAN is not set +# CONFIG_USB_SERIAL_KLSI is not set +# CONFIG_USB_SERIAL_KOBIL_SCT is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_NAVMAN is not set +CONFIG_USB_SERIAL_PL2303=m +# CONFIG_USB_SERIAL_HP4X is not set +# CONFIG_USB_SERIAL_SAFE is not set +# CONFIG_USB_SERIAL_TI is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_XIRCOM is not set +# CONFIG_USB_SERIAL_OPTION is not set +# CONFIG_USB_SERIAL_OMNINET is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGETKIT is not set +# CONFIG_USB_PHIDGETSERVO is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TEST is not set + +# +# USB DSL modem support +# + +# +# USB Gadget Support +# +CONFIG_USB_GADGET=m +# CONFIG_USB_GADGET_DEBUG_FILES is not set +CONFIG_USB_GADGET_SELECTED=y +# CONFIG_USB_GADGET_NET2280 is not set +# CONFIG_USB_GADGET_PXA2XX is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_OMAP is not set +CONFIG_USB_GADGET_AT91=y +CONFIG_USB_AT91=m +# CONFIG_USB_GADGET_DUMMY_HCD is not set +# CONFIG_USB_GADGET_DUALSPEED is not set +# CONFIG_USB_ZERO is not set +CONFIG_USB_ETH=m +CONFIG_USB_ETH_RNDIS=y +CONFIG_USB_GADGETFS=m +CONFIG_USB_FILE_STORAGE=m +# CONFIG_USB_FILE_STORAGE_TEST is not set +CONFIG_USB_G_SERIAL=m + +# +# MMC/SD Card support +# +CONFIG_MMC=m +CONFIG_MMC_DEBUG=y +CONFIG_MMC_BLOCK=m +CONFIG_MMC_AT91RM9200=m + +# +# Real Time Clock +# +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +# CONFIG_RTC_HCTOSYS is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y + +# +# RTC drivers +# +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_M48T86 is not set +CONFIG_RTC_DRV_AT91=y +# CONFIG_RTC_DRV_TEST is not set + +# +# File systems +# +CONFIG_EXT2_FS=m +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=m +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_JBD=m +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=m +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_REISERFS_FS_XATTR is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_ZISOFS_FS=m +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +CONFIG_NTFS_FS=m +# CONFIG_NTFS_DEBUG is not set +CONFIG_NTFS_RW=y + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set +CONFIG_CRAMFS=y +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_NFS_DIRECTIO=y +CONFIG_NFSD=m +CONFIG_NFSD_V3=y +# CONFIG_NFSD_V3_ACL is not set +CONFIG_NFSD_V4=y +CONFIG_NFSD_TCP=y +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_NFS_ACL_SUPPORT=m +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +CONFIG_SUNRPC_GSS=m +CONFIG_RPCSEC_GSS_KRB5=m +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +CONFIG_MAC_PARTITION=y +CONFIG_MSDOS_PARTITION=y +CONFIG_BSD_DISKLABEL=y +CONFIG_MINIX_SUBPARTITION=y +CONFIG_SOLARIS_X86_PARTITION=y +CONFIG_UNIXWARE_DISKLABEL=y +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# +CONFIG_NLS=m +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +CONFIG_NLS_CODEPAGE_932=m +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=m +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +CONFIG_NLS_ISO8859_15=m +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +CONFIG_NLS_UTF8=m + +# +# Profiling support +# +CONFIG_PROFILING=y +CONFIG_OPROFILE=m + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_DEBUG_KERNEL is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_FS is not set +CONFIG_FRAME_POINTER=y +# CONFIG_UNWIND_INFO is not set +# CONFIG_DEBUG_USER is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +CONFIG_CRYPTO_DES=m +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +CONFIG_CRYPTO_AES=m +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +CONFIG_CRYPTO_ARC4=m +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_DEFLATE is not set +CONFIG_CRYPTO_MICHAEL_MIC=m +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Hardware crypto devices +# + +# +# Library routines +# +CONFIG_CRC_CCITT=m +CONFIG_CRC16=m +CONFIG_CRC32=y +CONFIG_LIBCRC32C=m +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m diff --git a/arch/arm/configs/carmeva_defconfig b/arch/arm/configs/carmeva_defconfig new file mode 100644 index 00000000000..5ccd29a7c1f --- /dev/null +++ b/arch/arm/configs/carmeva_defconfig @@ -0,0 +1,723 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.12-rc4 +# Tue Jun 14 12:05:24 2005 +# +CONFIG_ARM=y +CONFIG_MMU=y +CONFIG_UID16=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_IOMAP=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_SWAP=y +# CONFIG_SYSVIPC is not set +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_SYSCTL is not set +# CONFIG_AUDIT is not set +# CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_OBSOLETE_MODPARM=y +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +# CONFIG_KMOD is not set + +# +# System Type +# +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_IOP3XX is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_H720X is not set +CONFIG_ARCH_AT91RM9200=y + +# +# AT91RM9200 Implementations +# +# CONFIG_ARCH_AT91RM9200DK is not set +# CONFIG_MACH_AT91RM9200EK is not set +# CONFIG_MACH_CSB337 is not set +# CONFIG_MACH_CSB637 is not set +CONFIG_MACH_CARMEVA=y + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_ARM920T=y +CONFIG_CPU_32v4=y +CONFIG_CPU_ABRT_EV4T=y +CONFIG_CPU_CACHE_V4WT=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set + +# +# Bus support +# +CONFIG_ISA_DMA_API=y + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +# CONFIG_SMP is not set +# CONFIG_PREEMPT is not set +# CONFIG_DISCONTIGMEM is not set +# CONFIG_LEDS is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="" +# CONFIG_XIP_KERNEL is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set +# CONFIG_ARTHUR is not set + +# +# Power management options +# +# CONFIG_PM is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +CONFIG_MTD_AT91_DATAFLASH=y +# CONFIG_MTD_AT91_DATAFLASH_CARD is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_ATA_OVER_ETH is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support +# + +# +# I2O device support +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_PACKET is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_IP_TCPDIAG=y +# CONFIG_IP_TCPDIAG_IPV6 is not set +# CONFIG_IPV6 is not set +# CONFIG_NETFILTER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +CONFIG_ARM_AT91_ETHER=y +CONFIG_ARM_AT91_ETHER_RMII=y +# CONFIG_SMC91X is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=m +CONFIG_SERIO_SERPORT=m +# CONFIG_SERIO_LIBPS2 is not set +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_AT91=y +CONFIG_SERIAL_AT91_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_AT91_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +CONFIG_AT91_SPI=y +CONFIG_AT91_SPIDEV=y + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Misc devices +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +CONFIG_MMC=m +CONFIG_MMC_DEBUG=y +CONFIG_MMC_BLOCK=m +CONFIG_MMC_AT91RM9200=m + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +# CONFIG_EXT2_FS_POSIX_ACL is not set +# CONFIG_EXT2_FS_SECURITY is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set + +# +# XFS support +# +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_DNOTIFY is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_SYSFS=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS_FS=y +CONFIG_JFFS_FS_VERBOSE=0 +CONFIG_JFFS_PROC_FS=y +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_NAND=y +# CONFIG_JFFS2_FS_NOR_ECC is not set +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_JFFS2_CMODE_NONE is not set +CONFIG_JFFS2_CMODE_PRIORITY=y +# CONFIG_JFFS2_CMODE_SIZE is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +CONFIG_NFS_V4=y +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=y +# CONFIG_NFSD_V3 is not set +CONFIG_NFSD_TCP=y +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +# CONFIG_DEBUG_KERNEL is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_DEBUG_BUGVERBOSE is not set +CONFIG_FRAME_POINTER=y +# CONFIG_DEBUG_USER is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Hardware crypto devices +# + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y diff --git a/arch/arm/configs/kafa_defconfig b/arch/arm/configs/kafa_defconfig new file mode 100644 index 00000000000..51ded20e3f6 --- /dev/null +++ b/arch/arm/configs/kafa_defconfig @@ -0,0 +1,884 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.17-rc3 +# Sun May 7 16:54:53 2006 +# +CONFIG_ARM=y +CONFIG_MMU=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_VECTORS_BASE=0xffff0000 + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +# CONFIG_RELAY is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_UID16=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_EMBEDDED is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +# CONFIG_KMOD is not set + +# +# Block layer +# +# CONFIG_BLK_DEV_IO_TRACE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_IOSCHED_CFQ is not set +# CONFIG_DEFAULT_AS is not set +CONFIG_DEFAULT_DEADLINE=y +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="deadline" + +# +# System Type +# +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_IOP3XX is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_AAEC2000 is not set +CONFIG_ARCH_AT91RM9200=y + +# +# AT91RM9200 Implementations +# + +# +# AT91RM9200 Board Type +# +# CONFIG_ARCH_AT91RM9200DK is not set +# CONFIG_MACH_AT91RM9200EK is not set +# CONFIG_MACH_CSB337 is not set +# CONFIG_MACH_CSB637 is not set +# CONFIG_MACH_CARMEVA is not set +# CONFIG_MACH_KB9200 is not set +# CONFIG_MACH_ATEB9200 is not set +CONFIG_MACH_KAFA=y + +# +# AT91 Feature Selections +# +# CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_ARM920T=y +CONFIG_CPU_32v4=y +CONFIG_CPU_ABRT_EV4T=y +CONFIG_CPU_CACHE_V4WT=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y + +# +# Processor Features +# +# CONFIG_ARM_THUMB is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set + +# +# Bus support +# + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_PREEMPT=y +# CONFIG_NO_IDLE_HZ is not set +CONFIG_HZ=100 +# CONFIG_AEABI is not set +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4096 +CONFIG_LEDS=y +# CONFIG_LEDS_TIMER is not set +CONFIG_LEDS_CPU=y +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="mem=32M console=ttyS0,115200 initrd=0x20800000,10M root=/dev/ram0 rw" +# CONFIG_XIP_KERNEL is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_MISC=y +# CONFIG_ARTHUR is not set + +# +# Power management options +# +# CONFIG_PM is not set +# CONFIG_APM is not set + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_INET_DIAG is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AFS_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +# CONFIG_MTD_BLOCK is not set +CONFIG_MTD_BLOCK_RO=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +CONFIG_MTD_AT91_DATAFLASH=y +# CONFIG_MTD_AT91_DATAFLASH_CARD is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# I2O device support +# + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# PHY device support +# +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +CONFIG_DAVICOM_PHY=y +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +CONFIG_ARM_AT91_ETHER=y +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_AT91=y +CONFIG_SERIAL_AT91_CONSOLE=y +# CONFIG_SERIAL_AT91_TTYAT is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=32 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_NOWAYOUT=y + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_AT91_WATCHDOG=y +# CONFIG_NVRAM is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set +CONFIG_AT91_SPI=y +CONFIG_AT91_SPIDEV=y + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y + +# +# I2C Algorithms +# +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# +CONFIG_I2C_AT91=y +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_PCA_ISA is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +# CONFIG_HWMON is not set +# CONFIG_HWMON_VID is not set + +# +# Misc devices +# + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ARCH_HAS_EHCI is not set +# CONFIG_USB is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# Real Time Clock +# +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +# CONFIG_RTC_HCTOSYS is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y + +# +# RTC drivers +# +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_M48T86 is not set +CONFIG_RTC_DRV_AT91=y +# CONFIG_RTC_DRV_TEST is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_FS_XATTR is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_INOTIFY is not set +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set +CONFIG_CRAMFS=y +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_DEBUG_KERNEL is not set +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_FS is not set +CONFIG_FRAME_POINTER=y +# CONFIG_UNWIND_INFO is not set +# CONFIG_DEBUG_USER is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Hardware crypto devices +# + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y diff --git a/arch/arm/configs/kb9202_defconfig b/arch/arm/configs/kb9202_defconfig new file mode 100644 index 00000000000..fee4f566452 --- /dev/null +++ b/arch/arm/configs/kb9202_defconfig @@ -0,0 +1,780 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.13-rc2 +# Sun Aug 14 19:26:59 2005 +# +CONFIG_ARM=y +CONFIG_MMU=y +CONFIG_UID16=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_CALIBRATE_DELAY=y + +# +# Code maturity level options +# +# CONFIG_EXPERIMENTAL is not set +CONFIG_CLEAN_COMPILE=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_SWAP is not set +# CONFIG_SYSVIPC is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +CONFIG_HOTPLUG=y +# CONFIG_KOBJECT_UEVENT is not set +# CONFIG_IKCONFIG is not set +# CONFIG_EMBEDDED is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_OBSOLETE_MODPARM=y +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y + +# +# System Type +# +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_IOP3XX is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_AAEC2000 is not set +CONFIG_ARCH_AT91RM9200=y + +# +# AT91RM9200 Implementations +# +# CONFIG_ARCH_AT91RM9200DK is not set +# CONFIG_MACH_AT91RM9200EK is not set +# CONFIG_MACH_CSB337 is not set +# CONFIG_MACH_CSB637 is not set +# CONFIG_MACH_CARMEVA is not set +CONFIG_MACH_KB9200=y + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_ARM920T=y +CONFIG_CPU_32v4=y +CONFIG_CPU_ABRT_EV4T=y +CONFIG_CPU_CACHE_V4WT=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set + +# +# Bus support +# +CONFIG_ISA_DMA_API=y + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +# CONFIG_NO_IDLE_HZ is not set +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_LEDS is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x10000000 +CONFIG_ZBOOT_ROM_BSS=0x20040000 +CONFIG_ZBOOT_ROM=y +CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/ram rw initrd=0x20210000,654933" + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_AOUT=y +CONFIG_BINFMT_MISC=y +# CONFIG_ARTHUR is not set + +# +# Power management options +# +# CONFIG_PM is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +CONFIG_DEBUG_DRIVER=y + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +CONFIG_BLK_DEV_NBD=y +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_ATA_OVER_ETH is not set + +# +# SCSI device support +# +CONFIG_SCSI=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +CONFIG_CHR_DEV_SG=y +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI Transport Attributes +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set + +# +# SCSI low-level drivers +# +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# I2O device support +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_IP_TCPDIAG is not set +# CONFIG_IP_TCPDIAG_IPV6 is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_NETFILTER is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +CONFIG_ARM_AT91_ETHER=y +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +# CONFIG_SERIO_SERPORT is not set +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_AT91=y +CONFIG_SERIAL_AT91_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_AT91_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_AT91_SPI is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Misc devices +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB=y +CONFIG_USB_DEBUG=y + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y + +# +# USB Host Controller Drivers +# +# CONFIG_USB_ISP116X_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_SL811_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_BLUETOOTH_TTY is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=y +CONFIG_USB_STORAGE_DEBUG=y +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_DPCM is not set + +# +# USB Input Devices +# +# CONFIG_USB_HID is not set + +# +# USB HID Boot Protocol drivers +# +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set +# CONFIG_USB_AIPTEK is not set +# CONFIG_USB_WACOM is not set +# CONFIG_USB_ACECAD is not set +# CONFIG_USB_KBTAB is not set +# CONFIG_USB_POWERMATE is not set +# CONFIG_USB_MTOUCH is not set +# CONFIG_USB_ITMTOUCH is not set +# CONFIG_USB_EGALAX is not set +# CONFIG_USB_XPAD is not set +# CONFIG_USB_ATI_REMOTE is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MICROTEK is not set + +# +# USB Multimedia devices +# +# CONFIG_USB_DABUSB is not set + +# +# Video4Linux support is needed for USB Multimedia device support +# + +# +# USB Network Adapters +# +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_USBNET is not set +# CONFIG_USB_MON is not set + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGETKIT is not set +# CONFIG_USB_PHIDGETSERVO is not set +# CONFIG_USB_IDMOUSE is not set + +# +# USB DSL modem support +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +# CONFIG_EXT2_FS_POSIX_ACL is not set +# CONFIG_EXT2_FS_SECURITY is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set + +# +# XFS support +# +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +CONFIG_AUTOFS_FS=y +CONFIG_AUTOFS4_FS=y + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_SYSFS=y +CONFIG_DEVPTS_FS_XATTR=y +# CONFIG_DEVPTS_FS_SECURITY is not set +CONFIG_TMPFS=y +# CONFIG_TMPFS_XATTR is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_HFSPLUS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=y +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_MAGIC_SYSRQ is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_FS is not set +CONFIG_FRAME_POINTER=y +CONFIG_DEBUG_USER=y +# CONFIG_DEBUG_WAITQ is not set +CONFIG_DEBUG_ERRORS=y +CONFIG_DEBUG_LL=y +# CONFIG_DEBUG_ICEDCC is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Hardware crypto devices +# + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set diff --git a/arch/arm/mach-at91rm9200/Kconfig b/arch/arm/mach-at91rm9200/Kconfig index 4b7218fc3eb..1ab5b782831 100644 --- a/arch/arm/mach-at91rm9200/Kconfig +++ b/arch/arm/mach-at91rm9200/Kconfig @@ -40,6 +40,18 @@ config MACH_KB9200 help Select this if you are using KwikByte's KB920x board +config MACH_ATEB9200 + bool "Embest's ATEB9200" + depends on ARCH_AT91RM9200 + help + Select this if you are using Embest's ATEB9200 board + +config MACH_KAFA + bool "Sperry-Sun KAFA board" + depends on ARCH_AT91RM9200 + help + Select this if you are using Sperry-Sun's KAFA board + comment "AT91RM9200 Feature Selections" diff --git a/arch/arm/mach-at91rm9200/Makefile b/arch/arm/mach-at91rm9200/Makefile index ef88c4128ed..c8f544b789c 100644 --- a/arch/arm/mach-at91rm9200/Makefile +++ b/arch/arm/mach-at91rm9200/Makefile @@ -12,16 +12,18 @@ obj-$(CONFIG_ARCH_AT91RM9200DK) += board-dk.o obj-$(CONFIG_MACH_AT91RM9200EK) += board-ek.o obj-$(CONFIG_MACH_CSB337) += board-csb337.o obj-$(CONFIG_MACH_CSB637) += board-csb637.o -#obj-$(CONFIG_MACH_CARMEVA) += board-carmeva.o -#obj-$(CONFIG_MACH_KB9200) += board-kb9202.o +obj-$(CONFIG_MACH_CARMEVA) += board-carmeva.o +obj-$(CONFIG_MACH_KB9200) += board-kb9202.o +obj-$(CONFIG_MACH_ATEB9200) += board-eb9200.o +obj-$(CONFIG_MACH_KAFA) += board-kafa.o # LEDs support led-$(CONFIG_ARCH_AT91RM9200DK) += leds.o led-$(CONFIG_MACH_AT91RM9200EK) += leds.o led-$(CONFIG_MACH_CSB337) += leds.o led-$(CONFIG_MACH_CSB637) += leds.o -#led-$(CONFIG_MACH_KB9200) += leds.o -#led-$(CONFIG_MACH_KAFA) += leds.o +led-$(CONFIG_MACH_KB9200) += leds.o +led-$(CONFIG_MACH_KAFA) += leds.o obj-$(CONFIG_LEDS) += $(led-y) # VGA support diff --git a/arch/arm/mach-at91rm9200/board-carmeva.c b/arch/arm/mach-at91rm9200/board-carmeva.c new file mode 100644 index 00000000000..9183cb75ccd --- /dev/null +++ b/arch/arm/mach-at91rm9200/board-carmeva.c @@ -0,0 +1,131 @@ +/* + * linux/arch/arm/mach-at91rm9200/board-carmeva.c + * + * Copyright (c) 2005 Peer Georgi + * Conitec Datasystems + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include "generic.h" + +static void __init carmeva_init_irq(void) +{ + /* Initialize AIC controller */ + at91rm9200_init_irq(NULL); + + /* Set up the GPIO interrupts */ + at91_gpio_irq_setup(BGA_GPIO_BANKS); +} + +/* + * Serial port configuration. + * 0 .. 3 = USART0 .. USART3 + * 4 = DBGU + */ +static struct at91_uart_config __initdata carmeva_uart_config = { + .console_tty = 0, /* ttyS0 */ + .nr_tty = 2, + .tty_map = { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */ +}; + +static void __init carmeva_map_io(void) +{ + at91rm9200_map_io(); + + /* Initialize clocks: 20.000 MHz crystal */ + at91_clock_init(20000000); + + /* Setup the serial ports and console */ + at91_init_serial(&carmeva_uart_config); +} + +static struct at91_eth_data __initdata carmeva_eth_data = { + .phy_irq_pin = AT91_PIN_PC4, + .is_rmii = 1, +}; + +static struct at91_usbh_data __initdata carmeva_usbh_data = { + .ports = 2, +}; + +static struct at91_udc_data __initdata carmeva_udc_data = { + .vbus_pin = AT91_PIN_PD12, + .pullup_pin = AT91_PIN_PD9, +}; + +/* FIXME: user dependend */ +// static struct at91_cf_data __initdata carmeva_cf_data = { +// .det_pin = AT91_PIN_PB0, +// .rst_pin = AT91_PIN_PC5, + // .irq_pin = ... not connected + // .vcc_pin = ... always powered +// }; + +static struct at91_mmc_data __initdata carmeva_mmc_data = { + .is_b = 0, + .wire4 = 1, +}; + +static void __init carmeva_board_init(void) +{ + /* Serial */ + at91_add_device_serial(); + /* Ethernet */ + at91_add_device_eth(&carmeva_eth_data); + /* USB Host */ + at91_add_device_usbh(&carmeva_usbh_data); + /* USB Device */ + at91_add_device_udc(&carmeva_udc_data); + /* I2C */ + at91_add_device_i2c(); + /* Compact Flash */ +// at91_add_device_cf(&carmeva_cf_data); + /* SPI */ +// at91_add_device_spi(NULL, 0); + /* MMC */ + at91_add_device_mmc(&carmeva_mmc_data); +} + +MACHINE_START(CARMEVA, "Carmeva") + /* Maintainer: Conitec Datasystems */ + .phys_io = AT91_BASE_SYS, + .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, + .boot_params = AT91_SDRAM_BASE + 0x100, + .timer = &at91rm9200_timer, + .map_io = carmeva_map_io, + .init_irq = carmeva_init_irq, + .init_machine = carmeva_board_init, +MACHINE_END diff --git a/arch/arm/mach-at91rm9200/board-eb9200.c b/arch/arm/mach-at91rm9200/board-eb9200.c new file mode 100644 index 00000000000..c7e4546a262 --- /dev/null +++ b/arch/arm/mach-at91rm9200/board-eb9200.c @@ -0,0 +1,130 @@ +/* + * linux/arch/arm/mach-at91rm9200/board-eb9200.c + * + * Copyright (C) 2005 SAN People, adapted for ATEB9200 from Embest + * by Andrew Patrikalakis + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include "generic.h" + +static void __init eb9200_init_irq(void) +{ + /* Initialize AIC controller */ + at91rm9200_init_irq(NULL); + + /* Set up the GPIO interrupts */ + at91_gpio_irq_setup(BGA_GPIO_BANKS); +} + +/* + * Serial port configuration. + * 0 .. 3 = USART0 .. USART3 + * 4 = DBGU + */ +static struct at91_uart_config __initdata eb9200_uart_config = { + .console_tty = 0, /* ttyS0 */ + .nr_tty = 2, + .tty_map = { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */ +}; + +static void __init eb9200_map_io(void) +{ + at91rm9200_map_io(); + + /* Initialize clocks: 18.432 MHz crystal */ + at91_clock_init(18432000); + + /* Setup the serial ports and console */ + at91_init_serial(&eb9200_uart_config); +} + +static struct at91_eth_data __initdata eb9200_eth_data = { + .phy_irq_pin = AT91_PIN_PC4, + .is_rmii = 1, +}; + +static struct at91_usbh_data __initdata eb9200_usbh_data = { + .ports = 2, +}; + +static struct at91_udc_data __initdata eb9200_udc_data = { + .vbus_pin = AT91_PIN_PD4, + .pullup_pin = AT91_PIN_PD5, +}; + +static struct at91_cf_data __initdata eb9200_cf_data = { + .det_pin = AT91_PIN_PB0, + .rst_pin = AT91_PIN_PC5, + // .irq_pin = ... not connected + // .vcc_pin = ... always powered +}; + +static struct at91_mmc_data __initdata eb9200_mmc_data = { + .is_b = 0, + .wire4 = 1, +}; + +static void __init eb9200_board_init(void) +{ + /* Serial */ + at91_add_device_serial(); + /* Ethernet */ + at91_add_device_eth(&eb9200_eth_data); + /* USB Host */ + at91_add_device_usbh(&eb9200_usbh_data); + /* USB Device */ + at91_add_device_udc(&eb9200_udc_data); + /* I2C */ + at91_add_device_i2c(); + /* Compact Flash */ + at91_add_device_cf(&eb9200_cf_data); + /* SPI */ + at91_add_device_spi(NULL, 0); + /* MMC */ + /* only supports 1 or 4 bit interface, not wired through to SPI */ + at91_add_device_mmc(&eb9200_mmc_data); +} + +MACHINE_START(ATEB9200, "Embest ATEB9200") + .phys_io = AT91_BASE_SYS, + .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, + .boot_params = AT91_SDRAM_BASE + 0x100, + .timer = &at91rm9200_timer, + .map_io = eb9200_map_io, + .init_irq = eb9200_init_irq, + .init_machine = eb9200_board_init, +MACHINE_END diff --git a/arch/arm/mach-at91rm9200/board-kafa.c b/arch/arm/mach-at91rm9200/board-kafa.c new file mode 100644 index 00000000000..35d459fdfcf --- /dev/null +++ b/arch/arm/mach-at91rm9200/board-kafa.c @@ -0,0 +1,116 @@ +/* + * linux/arch/arm/mach-at91rm9200/board-kafa.c + * + * Copyright (C) 2006 Sperry-Sun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include "generic.h" + +static void __init kafa_init_irq(void) +{ + /* Initialize AIC controller */ + at91rm9200_init_irq(NULL); + + /* Set up the GPIO interrupts */ + at91_gpio_irq_setup(PQFP_GPIO_BANKS); +} + +/* + * Serial port configuration. + * 0 .. 3 = USART0 .. USART3 + * 4 = DBGU + */ +static struct at91_uart_config __initdata kafa_uart_config = { + .console_tty = 0, /* ttyS0 */ + .nr_tty = 2, + .tty_map = { 4, 0, -1, -1, -1 } /* ttyS0, ..., ttyS4 */ +}; + +static void __init kafa_map_io(void) +{ + at91rm9200_map_io(); + + /* Initialize clocks: 18.432 MHz crystal */ + at91_clock_init(18432000); + + /* Set up the LEDs */ + at91_init_leds(AT91_PIN_PB4, AT91_PIN_PB4); + + /* Setup the serial ports and console */ + at91_init_serial(&kafa_uart_config); +} + +static struct at91_eth_data __initdata kafa_eth_data = { + .phy_irq_pin = AT91_PIN_PC4, + .is_rmii = 0, +}; + +static struct at91_usbh_data __initdata kafa_usbh_data = { + .ports = 1, +}; + +static struct at91_udc_data __initdata kafa_udc_data = { + .vbus_pin = AT91_PIN_PB6, + .pullup_pin = AT91_PIN_PB7, +}; + +static void __init kafa_board_init(void) +{ + /* Serial */ + at91_add_device_serial(); + /* Ethernet */ + at91_add_device_eth(&kafa_eth_data); + /* USB Host */ + at91_add_device_usbh(&kafa_usbh_data); + /* USB Device */ + at91_add_device_udc(&kafa_udc_data); + /* I2C */ + at91_add_device_i2c(); + /* SPI */ + at91_add_device_spi(NULL, 0); +} + +MACHINE_START(KAFA, "Sperry-Sun KAFA") + /* Maintainer: Sergei Sharonov */ + .phys_io = AT91_BASE_SYS, + .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, + .boot_params = AT91_SDRAM_BASE + 0x100, + .timer = &at91rm9200_timer, + .map_io = kafa_map_io, + .init_irq = kafa_init_irq, + .init_machine = kafa_board_init, +MACHINE_END diff --git a/arch/arm/mach-at91rm9200/board-kb9202.c b/arch/arm/mach-at91rm9200/board-kb9202.c new file mode 100644 index 00000000000..6ba65ef4880 --- /dev/null +++ b/arch/arm/mach-at91rm9200/board-kb9202.c @@ -0,0 +1,125 @@ +/* + * linux/arch/arm/mach-at91rm9200/board-kb9202.c + * + * Copyright (c) 2005 kb_admin + * KwikByte, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include "generic.h" + +static void __init kb9202_init_irq(void) +{ + /* Initialize AIC controller */ + at91rm9200_init_irq(NULL); + + /* Set up the GPIO interrupts */ + at91_gpio_irq_setup(PQFP_GPIO_BANKS); +} + +/* + * Serial port configuration. + * 0 .. 3 = USART0 .. USART3 + * 4 = DBGU + */ +static struct at91_uart_config __initdata kb9202_uart_config = { + .console_tty = 0, /* ttyS0 */ + .nr_tty = 3, + .tty_map = { 4, 0, 1, -1, -1 } /* ttyS0, ..., ttyS4 */ +}; + +static void __init kb9202_map_io(void) +{ + at91rm9200_map_io(); + + /* Initialize clocks: 10 MHz crystal */ + at91_clock_init(10000000); + + /* Set up the LEDs */ + at91_init_leds(AT91_PIN_PC19, AT91_PIN_PC18); + + /* Setup the serial ports and console */ + at91_init_serial(&kb9202_uart_config); +} + +static struct at91_eth_data __initdata kb9202_eth_data = { + .phy_irq_pin = AT91_PIN_PB29, + .is_rmii = 0, +}; + +static struct at91_usbh_data __initdata kb9202_usbh_data = { + .ports = 1, +}; + +static struct at91_udc_data __initdata kb9202_udc_data = { + .vbus_pin = AT91_PIN_PB24, + .pullup_pin = AT91_PIN_PB22, +}; + +static struct at91_mmc_data __initdata kb9202_mmc_data = { + .det_pin = AT91_PIN_PB2, + .is_b = 0, + .wire4 = 1, +}; + +static void __init kb9202_board_init(void) +{ + /* Serial */ + at91_add_device_serial(); + /* Ethernet */ + at91_add_device_eth(&kb9202_eth_data); + /* USB Host */ + at91_add_device_usbh(&kb9202_usbh_data); + /* USB Device */ + at91_add_device_udc(&kb9202_udc_data); + /* MMC */ + at91_add_device_mmc(&kb9202_mmc_data); + /* I2C */ + at91_add_device_i2c(); + /* SPI */ + at91_add_device_spi(NULL, 0); +} + +MACHINE_START(KB9200, "KB920x") + /* Maintainer: KwikByte, Inc. */ + .phys_io = AT91_BASE_SYS, + .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, + .boot_params = AT91_SDRAM_BASE + 0x100, + .timer = &at91rm9200_timer, + .map_io = kb9202_map_io, + .init_irq = kb9202_init_irq, + .init_machine = kb9202_board_init, +MACHINE_END -- cgit v1.2.3 From 907d6deb625cd7ff5fea3ef4b20dfb6c1c19c3ee Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Tue, 20 Jun 2006 19:30:19 +0100 Subject: [ARM] 3605/1: AT91RM9200 Power Management Patch from Andrew Victor This patch adds the core Power Management support for the AT91RM9200 processor. It will support suspend-to-RAM and standby modes. The suspend-to-RAM functionality is not 100% complete. The code that needs to be execute from the internal SRAM to restore the system is outstanding. For now we just fall through to Standby mode. The AT91-specific at91_suspend_entering_slow_clock() function will eventually be replaced by clk_must_disable() once that functionality is added to mainline clock API. Patch from David Brownell. Signed-off-by: Andrew Victor Signed-off-by: Russell King --- arch/arm/mach-at91rm9200/generic.h | 7 + arch/arm/mach-at91rm9200/pm.c | 225 +++++++++++++++++++++++++++++++++ include/asm-arm/arch-at91rm9200/gpio.h | 5 + 3 files changed, 237 insertions(+) create mode 100644 arch/arm/mach-at91rm9200/pm.c diff --git a/arch/arm/mach-at91rm9200/generic.h b/arch/arm/mach-at91rm9200/generic.h index 9bd541eba0a..f0d969d7d87 100644 --- a/arch/arm/mach-at91rm9200/generic.h +++ b/arch/arm/mach-at91rm9200/generic.h @@ -16,3 +16,10 @@ extern struct sys_timer at91rm9200_timer; extern void __init at91rm9200_map_io(void); extern int __init at91_clock_init(unsigned long main_clock); +struct device; +extern void __init at91_clock_associate(const char *id, struct device *dev, const char *func); + + /* Power Management */ +extern void at91_irq_suspend(void); +extern void at91_irq_resume(void); + diff --git a/arch/arm/mach-at91rm9200/pm.c b/arch/arm/mach-at91rm9200/pm.c new file mode 100644 index 00000000000..47e5480feb7 --- /dev/null +++ b/arch/arm/mach-at91rm9200/pm.c @@ -0,0 +1,225 @@ +/* + * arch/arm/mach-at91rm9200/pm.c + * AT91 Power Management + * + * Copyright (C) 2005 David Brownell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "generic.h" + + +static int at91_pm_valid_state(suspend_state_t state) +{ + switch (state) { + case PM_SUSPEND_ON: + case PM_SUSPEND_STANDBY: + case PM_SUSPEND_MEM: + return 1; + + default: + return 0; + } +} + + +static suspend_state_t target_state; + +/* + * Called after processes are frozen, but before we shutdown devices. + */ +static int at91_pm_prepare(suspend_state_t state) +{ + target_state = state; + return 0; +} + +/* + * Verify that all the clocks are correct before entering + * slow-clock mode. + */ +static int at91_pm_verify_clocks(void) +{ + unsigned long scsr; + int i; + + scsr = at91_sys_read(AT91_PMC_SCSR); + + /* USB must not be using PLLB */ + if ((scsr & (AT91_PMC_UHP | AT91_PMC_UDP)) != 0) { + pr_debug("AT91: PM - Suspend-to-RAM with USB still active\n"); + return 0; + } + +#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS + /* PCK0..PCK3 must be disabled, or configured to use clk32k */ + for (i = 0; i < 4; i++) { + u32 css; + + if ((scsr & (AT91_PMC_PCK0 << i)) == 0) + continue; + + css = at91_sys_read(AT91_PMC_PCKR(i)) & AT91_PMC_CSS; + if (css != AT91_PMC_CSS_SLOW) { + pr_debug("AT91: PM - Suspend-to-RAM with PCK%d src %d\n", i, css); + return 0; + } + } +#endif + + return 1; +} + +/* + * Call this from platform driver suspend() to see how deeply to suspend. + * For example, some controllers (like OHCI) need one of the PLL clocks + * in order to act as a wakeup source, and those are not available when + * going into slow clock mode. + * + * REVISIT: generalize as clk_will_be_available(clk)? Other platforms have + * the very same problem (but not using at91 main_clk), and it'd be better + * to add one generic API rather than lots of platform-specific ones. + */ +int at91_suspend_entering_slow_clock(void) +{ + return (target_state == PM_SUSPEND_MEM); +} +EXPORT_SYMBOL(at91_suspend_entering_slow_clock); + + +static void (*slow_clock)(void); + + + +static int at91_pm_enter(suspend_state_t state) +{ + at91_gpio_suspend(); + at91_irq_suspend(); + + pr_debug("AT91: PM - wake mask %08x, pm state %d\n", + /* remember all the always-wake irqs */ + (at91_sys_read(AT91_PMC_PCSR) + | (1 << AT91_ID_FIQ) + | (1 << AT91_ID_SYS) + | (1 << AT91_ID_IRQ0) + | (1 << AT91_ID_IRQ1) + | (1 << AT91_ID_IRQ2) + | (1 << AT91_ID_IRQ3) + | (1 << AT91_ID_IRQ4) + | (1 << AT91_ID_IRQ5) + | (1 << AT91_ID_IRQ6)) + & at91_sys_read(AT91_AIC_IMR), + state); + + switch (state) { + /* + * Suspend-to-RAM is like STANDBY plus slow clock mode, so + * drivers must suspend more deeply: only the master clock + * controller may be using the main oscillator. + */ + case PM_SUSPEND_MEM: + /* + * Ensure that clocks are in a valid state. + */ + if (!at91_pm_verify_clocks()) + goto error; + + /* + * Enter slow clock mode by switching over to clk32k and + * turning off the main oscillator; reverse on wakeup. + */ + if (slow_clock) { + slow_clock(); + break; + } else { + /* DEVELOPMENT ONLY */ + pr_info("AT91: PM - no slow clock mode yet ...\n"); + /* FALLTHROUGH leaving master clock alone */ + } + + /* + * STANDBY mode has *all* drivers suspended; ignores irqs not + * marked as 'wakeup' event sources; and reduces DRAM power. + * But otherwise it's identical to PM_SUSPEND_ON: cpu idle, and + * nothing fancy done with main or cpu clocks. + */ + case PM_SUSPEND_STANDBY: + /* + * NOTE: the Wait-for-Interrupt instruction needs to be + * in icache so the SDRAM stays in self-refresh mode until + * the wakeup IRQ occurs. + */ + asm("b 1f; .align 5; 1:"); + asm("mcr p15, 0, r0, c7, c10, 4"); /* drain write buffer */ + at91_sys_write(AT91_SDRAMC_SRR, 1); /* self-refresh mode */ + /* fall though to next state */ + + case PM_SUSPEND_ON: + asm("mcr p15, 0, r0, c7, c0, 4"); /* wait for interrupt */ + break; + + default: + pr_debug("AT91: PM - bogus suspend state %d\n", state); + goto error; + } + + pr_debug("AT91: PM - wakeup %08x\n", + at91_sys_read(AT91_AIC_IPR) & at91_sys_read(AT91_AIC_IMR)); + +error: + target_state = PM_SUSPEND_ON; + at91_irq_resume(); + at91_gpio_resume(); + return 0; +} + + +static struct pm_ops at91_pm_ops ={ + .pm_disk_mode = 0, + .valid = at91_pm_valid_state, + .prepare = at91_pm_prepare, + .enter = at91_pm_enter, +}; + +static int __init at91_pm_init(void) +{ + printk("AT91: Power Management\n"); + +#ifdef CONFIG_AT91_PM_SLOW_CLOCK + /* REVISIT allocations of SRAM should be dynamically managed. + * FIQ handlers and other components will want SRAM/TCM too... + */ + slow_clock = (void *) (AT91_VA_BASE_SRAM + (3 * SZ_4K)); + memcpy(slow_clock, at91rm9200_slow_clock, at91rm9200_slow_clock_sz); +#endif + + /* Disable SDRAM low-power mode. Cannot be used with self-refresh. */ + at91_sys_write(AT91_SDRAMC_LPR, 0); + + pm_set_ops(&at91_pm_ops); + + return 0; +} +arch_initcall(at91_pm_init); diff --git a/include/asm-arm/arch-at91rm9200/gpio.h b/include/asm-arm/arch-at91rm9200/gpio.h index 6176ab2dc41..dbde1baaf25 100644 --- a/include/asm-arm/arch-at91rm9200/gpio.h +++ b/include/asm-arm/arch-at91rm9200/gpio.h @@ -13,6 +13,8 @@ #ifndef __ASM_ARCH_AT91RM9200_GPIO_H #define __ASM_ARCH_AT91RM9200_GPIO_H +#include + #define PIN_BASE NR_AIC_IRQS #define PQFP_GPIO_BANKS 3 /* PQFP package has 3 banks */ @@ -188,6 +190,9 @@ extern int at91_set_multi_drive(unsigned pin, int is_on); /* callable at any time */ extern int at91_set_gpio_value(unsigned pin, int value); extern int at91_get_gpio_value(unsigned pin); + +extern void at91_gpio_suspend(void); +extern void at91_gpio_resume(void); #endif #endif -- cgit v1.2.3 From 5c3fddced9f62f4b175ce400bb96b23f47626e50 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Tue, 20 Jun 2006 19:30:20 +0100 Subject: [ARM] 3607/1: AT91RM9200 misc fixes Patch from Andrew Victor This final patch includes some general fixes. 1. Link in pm.o if CONFIG_PM is enabled. [Should have been included in patch 3605/1]. 2. Use __raw_readl()/__raw_writel() when accessing System Peripheral registers. 3. Removed some unnecessary includes Signed-off-by: Andrew Victor Signed-off-by: Russell King --- arch/arm/mach-at91rm9200/Makefile | 7 +++++++ include/asm-arm/arch-at91rm9200/hardware.h | 4 ++-- include/asm-arm/arch-at91rm9200/io.h | 1 - include/asm-arm/arch-at91rm9200/irqs.h | 2 -- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-at91rm9200/Makefile b/arch/arm/mach-at91rm9200/Makefile index c8f544b789c..81ebc6684ad 100644 --- a/arch/arm/mach-at91rm9200/Makefile +++ b/arch/arm/mach-at91rm9200/Makefile @@ -7,6 +7,8 @@ obj-m := obj-n := obj- := +obj-$(CONFIG_PM) += pm.o + # Board-specific support obj-$(CONFIG_ARCH_AT91RM9200DK) += board-dk.o obj-$(CONFIG_MACH_AT91RM9200EK) += board-ek.o @@ -28,3 +30,8 @@ obj-$(CONFIG_LEDS) += $(led-y) # VGA support #obj-$(CONFIG_FB_S1D13XXX) += ics1523.o + + +ifeq ($(CONFIG_PM_DEBUG),y) +CFLAGS_pm.o += -DDEBUG +endif diff --git a/include/asm-arm/arch-at91rm9200/hardware.h b/include/asm-arm/arch-at91rm9200/hardware.h index 87f40df5714..235d39d9110 100644 --- a/include/asm-arm/arch-at91rm9200/hardware.h +++ b/include/asm-arm/arch-at91rm9200/hardware.h @@ -84,14 +84,14 @@ static inline unsigned int at91_sys_read(unsigned int reg_offset) { void __iomem *addr = (void __iomem *)AT91_VA_BASE_SYS; - return readl(addr + reg_offset); + return __raw_readl(addr + reg_offset); } static inline void at91_sys_write(unsigned int reg_offset, unsigned long value) { void __iomem *addr = (void __iomem *)AT91_VA_BASE_SYS; - writel(value, addr + reg_offset); + __raw_writel(value, addr + reg_offset); } #endif diff --git a/include/asm-arm/arch-at91rm9200/io.h b/include/asm-arm/arch-at91rm9200/io.h index 23e670d85c9..88fd1bebcef 100644 --- a/include/asm-arm/arch-at91rm9200/io.h +++ b/include/asm-arm/arch-at91rm9200/io.h @@ -21,7 +21,6 @@ #ifndef __ASM_ARCH_IO_H #define __ASM_ARCH_IO_H -#include #include #define IO_SPACE_LIMIT 0xFFFFFFFF diff --git a/include/asm-arm/arch-at91rm9200/irqs.h b/include/asm-arm/arch-at91rm9200/irqs.h index 27b0497f1b3..2dc93b174a8 100644 --- a/include/asm-arm/arch-at91rm9200/irqs.h +++ b/include/asm-arm/arch-at91rm9200/irqs.h @@ -37,8 +37,6 @@ * symbols in gpio.h for ones handled indirectly as GPIOs. * We make provision for 4 banks of GPIO. */ -#include - #define NR_IRQS (NR_AIC_IRQS + (4 * 32)) -- cgit v1.2.3 From ec57b709c3dc2e8b7643c51fc4c3fdae42b29be2 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 20 Jun 2006 19:31:06 +0100 Subject: [ARM] 3609/1: S3C24XX: defconfig update for s3c2410_defconfig Patch from Ben Dooks Update s3c2410_defconfig to latest kernel with the latest patches Signed-off-by: Ben Dooks Signed-off-by: Russell King --- arch/arm/configs/s3c2410_defconfig | 76 +++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 37 deletions(-) diff --git a/arch/arm/configs/s3c2410_defconfig b/arch/arm/configs/s3c2410_defconfig index 3cec29d56c8..e1766138009 100644 --- a/arch/arm/configs/s3c2410_defconfig +++ b/arch/arm/configs/s3c2410_defconfig @@ -1,12 +1,14 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.16 -# Mon Mar 20 20:36:02 2006 +# Linux kernel version: 2.6.17 +# Tue Jun 20 18:57:01 2006 # CONFIG_ARM=y CONFIG_MMU=y CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_VECTORS_BASE=0xffff0000 # # Code maturity level options @@ -27,6 +29,7 @@ CONFIG_SYSVIPC=y CONFIG_SYSCTL=y # CONFIG_AUDIT is not set # CONFIG_IKCONFIG is not set +# CONFIG_RELAY is not set CONFIG_INITRAMFS_SOURCE="" CONFIG_UID16=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y @@ -42,10 +45,6 @@ CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y CONFIG_SHMEM=y -CONFIG_CC_ALIGN_FUNCTIONS=0 -CONFIG_CC_ALIGN_LABELS=0 -CONFIG_CC_ALIGN_LOOPS=0 -CONFIG_CC_ALIGN_JUMPS=0 CONFIG_SLAB=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 @@ -57,7 +56,6 @@ CONFIG_OBSOLETE_INTERMODULE=y # CONFIG_MODULES=y # CONFIG_MODULE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y @@ -65,6 +63,7 @@ CONFIG_KMOD=y # # Block layer # +# CONFIG_BLK_DEV_IO_TRACE is not set # # IO Schedulers @@ -92,6 +91,7 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # CONFIG_ARCH_IOP3XX is not set # CONFIG_ARCH_IXP4XX is not set # CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP23XX is not set # CONFIG_ARCH_L7200 is not set # CONFIG_ARCH_PXA is not set # CONFIG_ARCH_RPC is not set @@ -106,6 +106,8 @@ CONFIG_ARCH_S3C2410=y # CONFIG_ARCH_H720X is not set # CONFIG_ARCH_AAEC2000 is not set # CONFIG_ARCH_AT91RM9200 is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_NETX is not set # # S3C24XX Implementations @@ -116,14 +118,19 @@ CONFIG_ARCH_BAST=y CONFIG_BAST_PC104_IRQ=y CONFIG_ARCH_H1940=y CONFIG_MACH_N30=y +CONFIG_MACH_SMDK=y CONFIG_ARCH_SMDK2410=y CONFIG_ARCH_S3C2440=y +CONFIG_SMDK2440_CPU2440=y +CONFIG_SMDK2440_CPU2442=y CONFIG_MACH_VR1000=y CONFIG_MACH_RX3715=y CONFIG_MACH_OTOM=y CONFIG_MACH_NEXCODER_2440=y CONFIG_CPU_S3C2410=y +CONFIG_CPU_S3C244X=y CONFIG_CPU_S3C2440=y +CONFIG_CPU_S3C2442=y # # S3C2410 Boot @@ -251,12 +258,15 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set # CONFIG_INET_TUNNEL is not set CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set CONFIG_TCP_CONG_BIC=y # CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set # CONFIG_NETFILTER is not set # @@ -360,7 +370,6 @@ CONFIG_MTD_CFI_I2=y # CONFIG_MTD_CFI_I8 is not set CONFIG_MTD_CFI_INTELEXT=y CONFIG_MTD_CFI_AMDSTD=y -CONFIG_MTD_CFI_AMDSTD_RETRY=0 # CONFIG_MTD_CFI_STAA is not set CONFIG_MTD_CFI_UTIL=y # CONFIG_MTD_RAM is not set @@ -385,7 +394,6 @@ CONFIG_MTD_BAST_MAXSIZE=4 # CONFIG_MTD_SLRAM is not set # CONFIG_MTD_PHRAM is not set # CONFIG_MTD_MTDRAM is not set -# CONFIG_MTD_BLKMTD is not set # CONFIG_MTD_BLOCK2MTD is not set # @@ -694,7 +702,6 @@ CONFIG_S3C2410_WATCHDOG=y # # CONFIG_USBPCWATCHDOG is not set # CONFIG_NVRAM is not set -# CONFIG_RTC is not set CONFIG_S3C2410_RTC=y # CONFIG_DTLK is not set # CONFIG_R3964 is not set @@ -743,9 +750,7 @@ CONFIG_SENSORS_EEPROM=m # CONFIG_SENSORS_PCF8574 is not set # CONFIG_SENSORS_PCA9539 is not set # CONFIG_SENSORS_PCF8591 is not set -# CONFIG_SENSORS_RTC8564 is not set # CONFIG_SENSORS_MAX6875 is not set -# CONFIG_RTC_X1205_I2C is not set # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set @@ -807,18 +812,29 @@ CONFIG_SENSORS_LM85=m # # -# Multimedia Capabilities Port drivers +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers # # # Multimedia devices # # CONFIG_VIDEO_DEV is not set +CONFIG_VIDEO_V4L2=y # # Digital Video Broadcasting Devices # # CONFIG_DVB is not set +# CONFIG_USB_DABUSB is not set # # Graphics support @@ -828,6 +844,7 @@ CONFIG_FB_CFB_FILLRECT=y CONFIG_FB_CFB_COPYAREA=y CONFIG_FB_CFB_IMAGEBLIT=y # CONFIG_FB_MACMODES is not set +CONFIG_FB_FIRMWARE_EDID=y CONFIG_FB_MODE_HELPERS=y # CONFIG_FB_TILEBLITTING is not set # CONFIG_FB_S1D13XXX is not set @@ -863,6 +880,7 @@ CONFIG_FONT_8x16=y # CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ARCH_HAS_EHCI is not set CONFIG_USB=y # CONFIG_USB_DEBUG is not set @@ -915,9 +933,7 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y # CONFIG_USB_ACECAD is not set # CONFIG_USB_KBTAB is not set # CONFIG_USB_POWERMATE is not set -# CONFIG_USB_MTOUCH is not set -# CONFIG_USB_ITMTOUCH is not set -# CONFIG_USB_EGALAX is not set +# CONFIG_USB_TOUCHSCREEN is not set # CONFIG_USB_YEALINK is not set # CONFIG_USB_XPAD is not set # CONFIG_USB_ATI_REMOTE is not set @@ -930,15 +946,6 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y # # CONFIG_USB_MDC800 is not set -# -# USB Multimedia devices -# -# CONFIG_USB_DABUSB is not set - -# -# Video4Linux support is needed for USB Multimedia device support -# - # # USB Network Adapters # @@ -984,23 +991,18 @@ CONFIG_USB_MON=y # USB Gadget Support # # CONFIG_USB_GADGET is not set -# CONFIG_USB_GADGET_NET2280 is not set -# CONFIG_USB_GADGET_PXA2XX is not set -# CONFIG_USB_GADGET_GOKU is not set -# CONFIG_USB_GADGET_LH7A40X is not set -# CONFIG_USB_GADGET_OMAP is not set -# CONFIG_USB_GADGET_DUMMY_HCD is not set -# CONFIG_USB_ZERO is not set -# CONFIG_USB_ETH is not set -# CONFIG_USB_GADGETFS is not set -# CONFIG_USB_FILE_STORAGE is not set -# CONFIG_USB_G_SERIAL is not set # # MMC/SD Card support # # CONFIG_MMC is not set +# +# Real Time Clock +# +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set + # # File systems # @@ -1052,7 +1054,6 @@ CONFIG_SYSFS=y # CONFIG_TMPFS is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y -# CONFIG_RELAYFS_FS is not set # CONFIG_CONFIGFS_FS is not set # @@ -1193,6 +1194,7 @@ CONFIG_DEBUG_INFO=y # CONFIG_DEBUG_FS is not set # CONFIG_DEBUG_VM is not set CONFIG_FRAME_POINTER=y +# CONFIG_UNWIND_INFO is not set CONFIG_FORCED_INLINING=y # CONFIG_RCU_TORTURE_TEST is not set CONFIG_DEBUG_USER=y -- cgit v1.2.3 From 55c20c0af7fe7d5d09af4addfafcfe3bdc500f5d Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Tue, 20 Jun 2006 19:31:39 +0100 Subject: [ARM] 3599/1: AT91RM9200 remove global variables Patch from Andrew Victor This patch removes some now unnecessary global variables - at91_master_clock, at91_serial_map, at91_console_port. Signed-off-by: Andrew Victor Signed-off-by: Russell King --- arch/arm/mach-at91rm9200/clock.c | 5 +---- arch/arm/mach-at91rm9200/common.c | 11 ----------- include/asm-arm/arch-at91rm9200/board.h | 7 ------- 3 files changed, 1 insertion(+), 22 deletions(-) diff --git a/arch/arm/mach-at91rm9200/clock.c b/arch/arm/mach-at91rm9200/clock.c index 30042d2bac5..fe71b834899 100644 --- a/arch/arm/mach-at91rm9200/clock.c +++ b/arch/arm/mach-at91rm9200/clock.c @@ -28,10 +28,10 @@ #include #include -#include /* for master clock global */ #include "generic.h" + /* * There's a lot more which can be done with clocks, including cpufreq * integration, slow clock mode support (for system suspend), letting @@ -722,9 +722,6 @@ int __init at91_clock_init(unsigned long main_clock) (unsigned) main_clock / 1000000, ((unsigned) main_clock % 1000000) / 1000); - /* FIXME get rid of master_clock global */ - at91_master_clock = mck.rate_hz; - #ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS /* establish PCK0..PCK3 parentage */ for (tmp = 0; tmp < ARRAY_SIZE(clock_list); tmp++) { diff --git a/arch/arm/mach-at91rm9200/common.c b/arch/arm/mach-at91rm9200/common.c index 40d29a73b5c..1da68966e77 100644 --- a/arch/arm/mach-at91rm9200/common.c +++ b/arch/arm/mach-at91rm9200/common.c @@ -108,14 +108,3 @@ void __init at91rm9200_map_io(void) iotable_init(at91rm9200_io_desc, ARRAY_SIZE(at91rm9200_io_desc)); } - -unsigned long at91_master_clock; - -EXPORT_SYMBOL(at91_master_clock); - - -int at91_serial_map[AT91_NR_UART]; -int at91_console_port; - -EXPORT_SYMBOL(at91_serial_map); -EXPORT_SYMBOL(at91_console_port); diff --git a/include/asm-arm/arch-at91rm9200/board.h b/include/asm-arm/arch-at91rm9200/board.h index 587948d5675..1fdd70b2380 100644 --- a/include/asm-arm/arch-at91rm9200/board.h +++ b/include/asm-arm/arch-at91rm9200/board.h @@ -31,13 +31,6 @@ #ifndef __ASM_ARCH_BOARD_H #define __ASM_ARCH_BOARD_H - /* Clocks */ -extern unsigned long at91_master_clock; - - /* Serial Port */ -extern int at91_serial_map[AT91_NR_UART]; -extern int at91_console_port; - #include #include #include -- cgit v1.2.3 From ea75ee9ab8835ece099589c729574aa8aa94c0a6 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 20 Jun 2006 19:53:16 +0100 Subject: [ARM] Include asm/hardware.h not asm/arch/hardware.h Signed-off-by: Russell King --- arch/arm/mach-at91rm9200/board-carmeva.c | 2 +- arch/arm/mach-at91rm9200/board-csb337.c | 2 +- arch/arm/mach-at91rm9200/board-csb637.c | 2 +- arch/arm/mach-at91rm9200/board-dk.c | 2 +- arch/arm/mach-at91rm9200/board-eb9200.c | 2 +- arch/arm/mach-at91rm9200/board-ek.c | 2 +- arch/arm/mach-at91rm9200/board-kafa.c | 2 +- arch/arm/mach-at91rm9200/board-kb9202.c | 2 +- arch/arm/mach-at91rm9200/clock.c | 2 +- arch/arm/mach-at91rm9200/common.c | 2 +- arch/arm/mach-at91rm9200/devices.c | 2 +- arch/arm/mach-at91rm9200/gpio.c | 2 +- arch/arm/mach-netx/fb.c | 2 +- arch/arm/mach-pnx4008/serial.c | 2 +- include/asm-arm/arch-at91rm9200/memory.h | 2 +- include/asm-arm/arch-at91rm9200/system.h | 2 +- include/asm-arm/arch-at91rm9200/timex.h | 2 +- include/asm-arm/arch-at91rm9200/uncompress.h | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/arch/arm/mach-at91rm9200/board-carmeva.c b/arch/arm/mach-at91rm9200/board-carmeva.c index 9183cb75ccd..2c138b542eb 100644 --- a/arch/arm/mach-at91rm9200/board-carmeva.c +++ b/arch/arm/mach-at91rm9200/board-carmeva.c @@ -35,7 +35,7 @@ #include #include -#include +#include #include #include diff --git a/arch/arm/mach-at91rm9200/board-csb337.c b/arch/arm/mach-at91rm9200/board-csb337.c index 3b9de181ae3..e94645d77f7 100644 --- a/arch/arm/mach-at91rm9200/board-csb337.c +++ b/arch/arm/mach-at91rm9200/board-csb337.c @@ -35,7 +35,7 @@ #include #include -#include +#include #include #include diff --git a/arch/arm/mach-at91rm9200/board-csb637.c b/arch/arm/mach-at91rm9200/board-csb637.c index 2c4470d110d..67d5f7786cd 100644 --- a/arch/arm/mach-at91rm9200/board-csb637.c +++ b/arch/arm/mach-at91rm9200/board-csb637.c @@ -34,7 +34,7 @@ #include #include -#include +#include #include #include diff --git a/arch/arm/mach-at91rm9200/board-dk.c b/arch/arm/mach-at91rm9200/board-dk.c index eb02ca95be7..48d7390fa58 100644 --- a/arch/arm/mach-at91rm9200/board-dk.c +++ b/arch/arm/mach-at91rm9200/board-dk.c @@ -38,7 +38,7 @@ #include #include -#include +#include #include #include diff --git a/arch/arm/mach-at91rm9200/board-eb9200.c b/arch/arm/mach-at91rm9200/board-eb9200.c index c7e4546a262..a3e2df968a6 100644 --- a/arch/arm/mach-at91rm9200/board-eb9200.c +++ b/arch/arm/mach-at91rm9200/board-eb9200.c @@ -35,7 +35,7 @@ #include #include -#include +#include #include #include diff --git a/arch/arm/mach-at91rm9200/board-ek.c b/arch/arm/mach-at91rm9200/board-ek.c index 4d7468e4267..72202ed830a 100644 --- a/arch/arm/mach-at91rm9200/board-ek.c +++ b/arch/arm/mach-at91rm9200/board-ek.c @@ -38,7 +38,7 @@ #include #include -#include +#include #include #include diff --git a/arch/arm/mach-at91rm9200/board-kafa.c b/arch/arm/mach-at91rm9200/board-kafa.c index 35d459fdfcf..bf760c5e0c4 100644 --- a/arch/arm/mach-at91rm9200/board-kafa.c +++ b/arch/arm/mach-at91rm9200/board-kafa.c @@ -34,7 +34,7 @@ #include #include -#include +#include #include #include diff --git a/arch/arm/mach-at91rm9200/board-kb9202.c b/arch/arm/mach-at91rm9200/board-kb9202.c index 6ba65ef4880..f06d2b54cc9 100644 --- a/arch/arm/mach-at91rm9200/board-kb9202.c +++ b/arch/arm/mach-at91rm9200/board-kb9202.c @@ -35,7 +35,7 @@ #include #include -#include +#include #include #include diff --git a/arch/arm/mach-at91rm9200/clock.c b/arch/arm/mach-at91rm9200/clock.c index fe71b834899..edc2cc837ae 100644 --- a/arch/arm/mach-at91rm9200/clock.c +++ b/arch/arm/mach-at91rm9200/clock.c @@ -27,7 +27,7 @@ #include #include -#include +#include #include "generic.h" diff --git a/arch/arm/mach-at91rm9200/common.c b/arch/arm/mach-at91rm9200/common.c index 1da68966e77..e836f8537a1 100644 --- a/arch/arm/mach-at91rm9200/common.c +++ b/arch/arm/mach-at91rm9200/common.c @@ -16,7 +16,7 @@ #include #include -#include +#include #include "generic.h" static struct map_desc at91rm9200_io_desc[] __initdata = { diff --git a/arch/arm/mach-at91rm9200/devices.c b/arch/arm/mach-at91rm9200/devices.c index bf753e306a3..1cf85d231ba 100644 --- a/arch/arm/mach-at91rm9200/devices.c +++ b/arch/arm/mach-at91rm9200/devices.c @@ -16,7 +16,7 @@ #include #include -#include +#include #include #include diff --git a/arch/arm/mach-at91rm9200/gpio.c b/arch/arm/mach-at91rm9200/gpio.c index 3430ea05466..83c34747087 100644 --- a/arch/arm/mach-at91rm9200/gpio.c +++ b/arch/arm/mach-at91rm9200/gpio.c @@ -16,7 +16,7 @@ #include #include -#include +#include #include static const u32 pio_controller_offset[4] = { diff --git a/arch/arm/mach-netx/fb.c b/arch/arm/mach-netx/fb.c index e169b683e4d..ef0ab6115c0 100644 --- a/arch/arm/mach-netx/fb.c +++ b/arch/arm/mach-netx/fb.c @@ -24,7 +24,7 @@ #include #include -#include +#include struct clk {}; diff --git a/arch/arm/mach-pnx4008/serial.c b/arch/arm/mach-pnx4008/serial.c index 2e1e04cc048..10322384e45 100644 --- a/arch/arm/mach-pnx4008/serial.c +++ b/arch/arm/mach-pnx4008/serial.c @@ -16,7 +16,7 @@ #include #include -#include +#include #include #include diff --git a/include/asm-arm/arch-at91rm9200/memory.h b/include/asm-arm/arch-at91rm9200/memory.h index 462f1f0ad67..3c327c40437 100644 --- a/include/asm-arm/arch-at91rm9200/memory.h +++ b/include/asm-arm/arch-at91rm9200/memory.h @@ -21,7 +21,7 @@ #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H -#include +#include #define PHYS_OFFSET (AT91_SDRAM_BASE) diff --git a/include/asm-arm/arch-at91rm9200/system.h b/include/asm-arm/arch-at91rm9200/system.h index 945e66507a7..8a2ff472e4c 100644 --- a/include/asm-arm/arch-at91rm9200/system.h +++ b/include/asm-arm/arch-at91rm9200/system.h @@ -21,7 +21,7 @@ #ifndef __ASM_ARCH_SYSTEM_H #define __ASM_ARCH_SYSTEM_H -#include +#include static inline void arch_idle(void) { diff --git a/include/asm-arm/arch-at91rm9200/timex.h b/include/asm-arm/arch-at91rm9200/timex.h index 3f112dd1258..88687cefe6e 100644 --- a/include/asm-arm/arch-at91rm9200/timex.h +++ b/include/asm-arm/arch-at91rm9200/timex.h @@ -21,7 +21,7 @@ #ifndef __ASM_ARCH_TIMEX_H #define __ASM_ARCH_TIMEX_H -#include +#include #define CLOCK_TICK_RATE (AT91_SLOW_CLOCK) diff --git a/include/asm-arm/arch-at91rm9200/uncompress.h b/include/asm-arm/arch-at91rm9200/uncompress.h index 7b38497c24b..ec7811ab0a5 100644 --- a/include/asm-arm/arch-at91rm9200/uncompress.h +++ b/include/asm-arm/arch-at91rm9200/uncompress.h @@ -21,7 +21,7 @@ #ifndef __ASM_ARCH_UNCOMPRESS_H #define __ASM_ARCH_UNCOMPRESS_H -#include +#include /* * The following code assumes the serial port has already been -- cgit v1.2.3 From 4af6fee18822d012a15b4c9b8992e1f2793dfe0b Mon Sep 17 00:00:00 2001 From: Deepak Saxena Date: Tue, 20 Jun 2006 21:30:44 +0100 Subject: [ARM] 3610/1: Make reboot work on Versatile Patch from Deepak Saxena This patch makes soft reboot work on the Versatile board. Thanks to Catalin Marinas @ ARM for pointing out the proper way to do this. Signed-off-by: Deepak Saxena Signed-off-by: Russell King --- arch/arm/Kconfig | 112 ++++++++++++++++---------------- include/asm-arm/arch-versatile/system.h | 16 ++--- 2 files changed, 63 insertions(+), 65 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index dfb97fe045d..1b7e5c2e90e 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -93,15 +93,49 @@ choice prompt "ARM system type" default ARCH_VERSATILE +config ARCH_AAEC2000 + bool "Agilent AAEC-2000 based" + select ARM_AMBA + help + This enables support for systems based on the Agilent AAEC-2000 + +config ARCH_INTEGRATOR + bool "ARM Ltd. Integrator family" + select ARM_AMBA + select ICST525 + help + Support for ARM's Integrator platform. + +config ARCH_REALVIEW + bool "ARM Ltd. RealView family" + select ARM_AMBA + select ICST307 + help + This enables support for ARM Ltd RealView boards. + +config ARCH_VERSATILE + bool "ARM Ltd. Versatile family" + select ARM_AMBA + select ARM_VIC + select ICST307 + help + This enables support for ARM Ltd Versatile board. + +config ARCH_AT91RM9200 + bool "Atmel AT91RM9200" + help + Say Y here if you intend to run this kernel on an Atmel + AT91RM9200-based board. + config ARCH_CLPS7500 - bool "Cirrus-CL-PS7500FE" + bool "Cirrus CL-PS7500FE" select TIMER_ACORN select ISA help Support for the Cirrus Logic PS7500FE system-on-a-chip. config ARCH_CLPS711X - bool "CLPS711x/EP721x-based" + bool "Cirrus Logic CLPS711x/EP721x-based" help Support for Cirrus Logic 711x/721x based boards. @@ -135,12 +169,22 @@ config ARCH_FOOTBRIDGE Support for systems based on the DC21285 companion chip ("FootBridge"), such as the Simtec CATS and the Rebel NetWinder. -config ARCH_INTEGRATOR - bool "Integrator" - select ARM_AMBA - select ICST525 +config ARCH_NETX + bool "Hilscher NetX based" + select ARM_VIC help - Support for ARM's Integrator platform. + This enables support for systems based on the Hilscher NetX Soc + +config ARCH_H720X + bool "Hynix HMS720x-based" + select ISA_DMA_API + help + This enables support for systems based on the Hynix HMS720x + +config ARCH_IMX + bool "IMX" + help + Support for Motorola's i.MX family of processors (MX1, MXL). config ARCH_IOP3XX bool "IOP3xx-based" @@ -178,6 +222,11 @@ config ARCH_L7200 If you have any questions or comments about the Linux kernel port to this board, send e-mail to . +config ARCH_PNX4008 + bool "Philips Nexperia PNX4008 Mobile" + help + This enables support for Philips PNX4008 mobile platform. + config ARCH_PXA bool "PXA2xx-based" select ARCH_MTD_XIP @@ -232,55 +281,6 @@ config ARCH_OMAP help Support for TI's OMAP platform (OMAP1 and OMAP2). -config ARCH_VERSATILE - bool "Versatile" - select ARM_AMBA - select ARM_VIC - select ICST307 - help - This enables support for ARM Ltd Versatile board. - -config ARCH_REALVIEW - bool "RealView" - select ARM_AMBA - select ICST307 - help - This enables support for ARM Ltd RealView boards. - -config ARCH_IMX - bool "IMX" - help - Support for Motorola's i.MX family of processors (MX1, MXL). - -config ARCH_H720X - bool "Hynix-HMS720x-based" - select ISA_DMA_API - help - This enables support for systems based on the Hynix HMS720x - -config ARCH_AAEC2000 - bool "Agilent AAEC-2000 based" - select ARM_AMBA - help - This enables support for systems based on the Agilent AAEC-2000 - -config ARCH_AT91RM9200 - bool "AT91RM9200" - help - Say Y here if you intend to run this kernel on an Atmel - AT91RM9200-based board. - -config ARCH_PNX4008 - bool "Philips Nexperia PNX4008 Mobile" - help - This enables support for Philips PNX4008 mobile platform. - -config ARCH_NETX - bool "Hilscher NetX based" - select ARM_VIC - help - This enables support for systems based on the Hilscher NetX Soc - endchoice source "arch/arm/mach-clps711x/Kconfig" diff --git a/include/asm-arm/arch-versatile/system.h b/include/asm-arm/arch-versatile/system.h index 8889a189739..71c6254c0d9 100644 --- a/include/asm-arm/arch-versatile/system.h +++ b/include/asm-arm/arch-versatile/system.h @@ -36,16 +36,14 @@ static inline void arch_idle(void) static inline void arch_reset(char mode) { - unsigned int hdr_ctrl = (IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_RESETCTL_OFFSET); - unsigned int val; + u32 val; - /* - * To reset, we hit the on-board reset register - * in the system FPGA - */ - val = __raw_readl(hdr_ctrl); - val |= VERSATILE_SYS_CTRL_RESET_CONFIGCLR; - __raw_writel(val, hdr_ctrl); + val = __raw_readl(IO_ADDRESS(VERSATILE_SYS_RESETCTL)) & ~0x7; + val |= 0x105; + + __raw_writel(0xa05f, IO_ADDRESS(VERSATILE_SYS_LOCK)); + __raw_writel(val, IO_ADDRESS(VERSATILE_SYS_RESETCTL)); + __raw_writel(0, IO_ADDRESS(VERSATILE_SYS_LOCK)); } #endif -- cgit v1.2.3 From 905f14672e6d0552bfde954d5f7adb5f2c7a7960 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 20 Jun 2006 23:27:37 +0100 Subject: [ARM] Fix tosa build error tosa.c references mdelay(), but was missing linux/delay.h Signed-off-by: Russell King --- arch/arm/mach-pxa/tosa.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index afa223b9e7a..7152bc13680 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include -- cgit v1.2.3 From 58dfd9c16e88b9d790e7df8f2c5b03b7887db54c Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Wed, 21 Jun 2006 10:53:54 +1000 Subject: [FORCEDETH] Fix xmit_lock/netif_tx_lock after merge There has been an update to the forcedeth driver that added a few new uses of xmit_lock which is no longer meant to be used directly. This patch replaces them with netif_tx_lock_bh. Signed-off-by: Herbert Xu Signed-off-by: Linus Torvalds --- drivers/net/forcedeth.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 04a53f1dfdb..62b38a4494b 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -2991,13 +2991,13 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) netif_carrier_off(dev); if (netif_running(dev)) { nv_disable_irq(dev); - spin_lock_bh(&dev->xmit_lock); + netif_tx_lock_bh(dev); spin_lock(&np->lock); /* stop engines */ nv_stop_rx(dev); nv_stop_tx(dev); spin_unlock(&np->lock); - spin_unlock_bh(&dev->xmit_lock); + netif_tx_unlock_bh(dev); } if (ecmd->autoneg == AUTONEG_ENABLE) { @@ -3131,13 +3131,13 @@ static int nv_nway_reset(struct net_device *dev) netif_carrier_off(dev); if (netif_running(dev)) { nv_disable_irq(dev); - spin_lock_bh(&dev->xmit_lock); + netif_tx_lock_bh(dev); spin_lock(&np->lock); /* stop engines */ nv_stop_rx(dev); nv_stop_tx(dev); spin_unlock(&np->lock); - spin_unlock_bh(&dev->xmit_lock); + netif_tx_unlock_bh(dev); printk(KERN_INFO "%s: link down.\n", dev->name); } @@ -3244,7 +3244,7 @@ static int nv_set_ringparam(struct net_device *dev, struct ethtool_ringparam* ri if (netif_running(dev)) { nv_disable_irq(dev); - spin_lock_bh(&dev->xmit_lock); + netif_tx_lock_bh(dev); spin_lock(&np->lock); /* stop engines */ nv_stop_rx(dev); @@ -3303,7 +3303,7 @@ static int nv_set_ringparam(struct net_device *dev, struct ethtool_ringparam* ri nv_start_rx(dev); nv_start_tx(dev); spin_unlock(&np->lock); - spin_unlock_bh(&dev->xmit_lock); + netif_tx_unlock_bh(dev); nv_enable_irq(dev); } return 0; @@ -3339,13 +3339,13 @@ static int nv_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam* netif_carrier_off(dev); if (netif_running(dev)) { nv_disable_irq(dev); - spin_lock_bh(&dev->xmit_lock); + netif_tx_lock_bh(dev); spin_lock(&np->lock); /* stop engines */ nv_stop_rx(dev); nv_stop_tx(dev); spin_unlock(&np->lock); - spin_unlock_bh(&dev->xmit_lock); + netif_tx_unlock_bh(dev); } np->pause_flags &= ~(NV_PAUSEFRAME_RX_REQ|NV_PAUSEFRAME_TX_REQ); @@ -3729,7 +3729,7 @@ static void nv_self_test(struct net_device *dev, struct ethtool_test *test, u64 if (test->flags & ETH_TEST_FL_OFFLINE) { if (netif_running(dev)) { netif_stop_queue(dev); - spin_lock_bh(&dev->xmit_lock); + netif_tx_lock_bh(dev); spin_lock_irq(&np->lock); nv_disable_hw_interrupts(dev, np->irqmask); if (!(np->msi_flags & NV_MSI_X_ENABLED)) { @@ -3745,7 +3745,7 @@ static void nv_self_test(struct net_device *dev, struct ethtool_test *test, u64 nv_drain_rx(dev); nv_drain_tx(dev); spin_unlock_irq(&np->lock); - spin_unlock_bh(&dev->xmit_lock); + netif_tx_unlock_bh(dev); } if (!nv_register_test(dev)) { -- cgit v1.2.3 From 6b41fd1785f4effe2f3bd40da864415812f5b8c9 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 20 Jun 2006 19:44:03 -0700 Subject: Fix up CFQ scheduler for recent rbtree node shrinkage The color is now in the low bits of the parent pointer, and initializing it to 0 happens as part of the whole memset above, so just remove the unnecessary RB_CLEAR_COLOR. Signed-off-by: Linus Torvalds --- block/cfq-iosched.c | 1 - 1 file changed, 1 deletion(-) diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 6200d9b9af2..e2e6ad0a158 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -1318,7 +1318,6 @@ cfq_alloc_io_context(struct cfq_data *cfqd, gfp_t gfp_mask) if (cic) { memset(cic, 0, sizeof(*cic)); - RB_CLEAR_COLOR(&cic->rb_node); cic->last_end_request = jiffies; INIT_LIST_HEAD(&cic->queue_list); cic->dtor = cfq_free_io_context; -- cgit v1.2.3 From 2eec0e0842ef747027eb9181d5f50d7157184d57 Mon Sep 17 00:00:00 2001 From: Cedric Le Goater Date: Mon, 19 Jun 2006 21:10:44 -0700 Subject: [PATCH] s390: add __raw_writeq required by __iowrite64_copy It also adds all the related quad routines. Signed-off-by: Cedric Le Goater Acked-by: Heiko Carstens Cc: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-s390/io.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/asm-s390/io.h b/include/asm-s390/io.h index b05825dd16d..d4614b35f42 100644 --- a/include/asm-s390/io.h +++ b/include/asm-s390/io.h @@ -86,20 +86,25 @@ extern void iounmap(void *addr); #define readb(addr) (*(volatile unsigned char *) __io_virt(addr)) #define readw(addr) (*(volatile unsigned short *) __io_virt(addr)) #define readl(addr) (*(volatile unsigned int *) __io_virt(addr)) +#define readq(addr) (*(volatile unsigned long long *) __io_virt(addr)) #define readb_relaxed(addr) readb(addr) #define readw_relaxed(addr) readw(addr) #define readl_relaxed(addr) readl(addr) +#define readq_relaxed(addr) readq(addr) #define __raw_readb readb #define __raw_readw readw #define __raw_readl readl +#define __raw_readq readq #define writeb(b,addr) (*(volatile unsigned char *) __io_virt(addr) = (b)) #define writew(b,addr) (*(volatile unsigned short *) __io_virt(addr) = (b)) #define writel(b,addr) (*(volatile unsigned int *) __io_virt(addr) = (b)) +#define writeq(b,addr) (*(volatile unsigned long long *) __io_virt(addr) = (b)) #define __raw_writeb writeb #define __raw_writew writew #define __raw_writel writel +#define __raw_writeq writeq #define memset_io(a,b,c) memset(__io_virt(a),(b),(c)) #define memcpy_fromio(a,b,c) memcpy((a),__io_virt(b),(c)) -- cgit v1.2.3 From 22ae813b85df7c0b0fc7c8d6f336d6a9f566ff97 Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Tue, 20 Jun 2006 20:03:02 -0700 Subject: [PATCH] add __iowrite64_copy Introduce __iowrite64_copy. It will be used by the Myri-10G Ethernet driver to post requests to the NIC. This driver will be submitted soon. __iowrite64_copy copies to I/O memory in units of 64 bits when possible (on 64 bit architectures). It reverts to __iowrite32_copy on 32 bit architectures. Signed-off-by: Brice Goglin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/io.h | 1 + lib/iomap_copy.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/include/linux/io.h b/include/linux/io.h index 85533ec5aaa..420e2fdf26f 100644 --- a/include/linux/io.h +++ b/include/linux/io.h @@ -21,5 +21,6 @@ #include void __iowrite32_copy(void __iomem *to, const void *from, size_t count); +void __iowrite64_copy(void __iomem *to, const void *from, size_t count); #endif /* _LINUX_IO_H */ diff --git a/lib/iomap_copy.c b/lib/iomap_copy.c index 351045f4f63..864fc5ea398 100644 --- a/lib/iomap_copy.c +++ b/lib/iomap_copy.c @@ -40,3 +40,31 @@ void __attribute__((weak)) __iowrite32_copy(void __iomem *to, __raw_writel(*src++, dst++); } EXPORT_SYMBOL_GPL(__iowrite32_copy); + +/** + * __iowrite64_copy - copy data to MMIO space, in 64-bit or 32-bit units + * @to: destination, in MMIO space (must be 64-bit aligned) + * @from: source (must be 64-bit aligned) + * @count: number of 64-bit quantities to copy + * + * Copy data from kernel space to MMIO space, in units of 32 or 64 bits at a + * time. Order of access is not guaranteed, nor is a memory barrier + * performed afterwards. + */ +void __attribute__((weak)) __iowrite64_copy(void __iomem *to, + const void *from, + size_t count) +{ +#ifdef CONFIG_64BIT + u64 __iomem *dst = to; + const u64 *src = from; + const u64 *end = src + count; + + while (src < end) + __raw_writeq(*src++, dst++); +#else + __iowrite32_copy(to, from, count * 2); +#endif +} + +EXPORT_SYMBOL_GPL(__iowrite64_copy); -- cgit v1.2.3 From 7932f0b82ff1db35a5ed8d5825d51cafe15fa6db Mon Sep 17 00:00:00 2001 From: John Rose Date: Thu, 15 Jun 2006 17:32:15 -0500 Subject: [POWERPC] RTAS delay, fix module build breaks Export both news RTAS delay functions, and change the scanlog module to use the new delay functions. Signed-off-by: John Rose Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/rtas.c | 1 + arch/powerpc/platforms/pseries/scanlog.c | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index fd15e3e3bb3..17dc7919851 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -797,6 +797,7 @@ EXPORT_SYMBOL(rtas_call); EXPORT_SYMBOL(rtas_data_buf); EXPORT_SYMBOL(rtas_data_buf_lock); EXPORT_SYMBOL(rtas_busy_delay_time); +EXPORT_SYMBOL(rtas_busy_delay); EXPORT_SYMBOL(rtas_get_sensor); EXPORT_SYMBOL(rtas_get_power_level); EXPORT_SYMBOL(rtas_set_power_level); diff --git a/arch/powerpc/platforms/pseries/scanlog.c b/arch/powerpc/platforms/pseries/scanlog.c index 50643496eb6..77a5bb1d9c3 100644 --- a/arch/powerpc/platforms/pseries/scanlog.c +++ b/arch/powerpc/platforms/pseries/scanlog.c @@ -107,9 +107,9 @@ static ssize_t scanlog_read(struct file *file, char __user *buf, /* Break to sleep default time */ break; default: - if (status > 9900 && status <= 9905) { - wait_time = rtas_extended_busy_delay_time(status); - } else { + /* Assume extended busy */ + wait_time = rtas_busy_delay_time(status); + if (!wait_time) { printk(KERN_ERR "scanlog: unknown error from rtas: %d\n", status); return -EIO; } -- cgit v1.2.3 From 2198c070498850c16d65c09bc587e3f5042126ef Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Sat, 17 Jun 2006 17:49:42 -0500 Subject: [POWERPC] Guard L3CR references with CPU_FTR_L3CR. Signed-off-by: Jon Loeliger Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/cpu_setup_6xx.S | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/powerpc/kernel/cpu_setup_6xx.S b/arch/powerpc/kernel/cpu_setup_6xx.S index 55ed7716636..365381fcb27 100644 --- a/arch/powerpc/kernel/cpu_setup_6xx.S +++ b/arch/powerpc/kernel/cpu_setup_6xx.S @@ -210,9 +210,11 @@ setup_745x_specifics: * the firmware. If any, we disable NAP capability as * it's known to be bogus on rev 2.1 and earlier */ +BEGIN_FTR_SECTION mfspr r11,SPRN_L3CR andis. r11,r11,L3CR_L3E@h beq 1f +END_FTR_SECTION_IFSET(CPU_FTR_L3CR) lwz r6,CPU_SPEC_FEATURES(r5) andi. r0,r6,CPU_FTR_L3_DISABLE_NAP beq 1f -- cgit v1.2.3 From 8a30088794ff426cd3e21557db8f3d2687ac6695 Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Sat, 17 Jun 2006 17:51:09 -0500 Subject: [POWERPC] Prevent duplicate lmb reservations for Device Tree blob. Signed-off-by: Jon Loeliger Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/prom.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index d77d24a89b3..629023240ec 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -1267,13 +1267,16 @@ static void __init early_reserve_mem(void) { u64 base, size; u64 *reserve_map; + unsigned long self_base; + unsigned long self_size; reserve_map = (u64 *)(((unsigned long)initial_boot_params) + initial_boot_params->off_mem_rsvmap); /* before we do anything, lets reserve the dt blob */ - lmb_reserve(__pa((unsigned long)initial_boot_params), - initial_boot_params->totalsize); + self_base = __pa((unsigned long)initial_boot_params); + self_size = initial_boot_params->totalsize; + lmb_reserve(self_base, self_size); #ifdef CONFIG_PPC32 /* @@ -1289,6 +1292,9 @@ static void __init early_reserve_mem(void) size_32 = *(reserve_map_32++); if (size_32 == 0) break; + /* skip if the reservation is for the blob */ + if (base_32 == self_base && size_32 == self_size) + continue; DBG("reserving: %x -> %x\n", base_32, size_32); lmb_reserve(base_32, size_32); } @@ -1300,6 +1306,9 @@ static void __init early_reserve_mem(void) size = *(reserve_map++); if (size == 0) break; + /* skip if the reservation is for the blob */ + if (base == self_base && size == self_size) + continue; DBG("reserving: %llx -> %llx\n", base, size); lmb_reserve(base, size); } -- cgit v1.2.3 From c9b484b5c1201321f40b04870e8b417033b6fe76 Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Sat, 17 Jun 2006 17:52:35 -0500 Subject: [POWERPC] Add the mpc8641 hpcn Kconfig and Makefiles. Signed-off-by: Xianghua Xiao Signed-off-by: Jon Loeliger Signed-off-by: Paul Mackerras --- arch/powerpc/Kconfig | 15 +++++++++++++-- arch/powerpc/platforms/86xx/Kconfig | 36 ++++++++++++++++++++++++++++++++++++ arch/powerpc/platforms/86xx/Makefile | 10 ++++++++++ arch/powerpc/platforms/Makefile | 1 + 4 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 arch/powerpc/platforms/86xx/Kconfig create mode 100644 arch/powerpc/platforms/86xx/Makefile diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 4ef2478cb84..65f4cd181bd 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -141,6 +141,15 @@ config PPC_85xx select FSL_SOC select 85xx +config PPC_86xx + bool "Freescale 86xx" + select 6xx + select FSL_SOC + select PPC_FPU + select ALTIVEC + help + The Freescale E600 SoCs have 74xx cores. + config 40x bool "AMCC 40x" @@ -549,6 +558,7 @@ source arch/powerpc/platforms/embedded6xx/Kconfig source arch/powerpc/platforms/4xx/Kconfig source arch/powerpc/platforms/83xx/Kconfig source arch/powerpc/platforms/85xx/Kconfig +source arch/powerpc/platforms/86xx/Kconfig source arch/powerpc/platforms/8xx/Kconfig source arch/powerpc/platforms/cell/Kconfig @@ -780,6 +790,7 @@ config GENERIC_ISA_DMA config PPC_I8259 bool + default y if MPC8641_HPCN default n config PPC_INDIRECT_PCI @@ -802,8 +813,8 @@ config MCA bool config PCI - bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_MPC52xx || (EMBEDDED && PPC_ISERIES) - default y if !40x && !CPM2 && !8xx && !APUS && !PPC_83xx && !PPC_85xx + bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_86xx || PPC_MPC52xx || (EMBEDDED && PPC_ISERIES) + default y if !40x && !CPM2 && !8xx && !APUS && !PPC_83xx && !PPC_85xx && !PPC_86xx default PCI_PERMEDIA if !4xx && !CPM2 && !8xx && APUS default PCI_QSPAN if !4xx && !CPM2 && 8xx help diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig new file mode 100644 index 00000000000..3a87863d287 --- /dev/null +++ b/arch/powerpc/platforms/86xx/Kconfig @@ -0,0 +1,36 @@ +menu "Platform Support" + depends on PPC_86xx + +choice + prompt "Machine Type" + default MPC8641_HPCN + +config MPC8641_HPCN + bool "Freescale MPC8641 HPCN" + help + This option enables support for the MPC8641 HPCN board. + +endchoice + + +config MPC8641 + bool + select PPC_INDIRECT_PCI + select PPC_UDBG_16550 + default y if MPC8641_HPCN + +config MPIC + bool + default y + +config PPC_INDIRECT_PCI_BE + bool + depends on PPC_86xx + default y + +config PPC_STD_MMU + bool + depends on PPC_86xx + default y + +endmenu diff --git a/arch/powerpc/platforms/86xx/Makefile b/arch/powerpc/platforms/86xx/Makefile new file mode 100644 index 00000000000..7be796c5d5c --- /dev/null +++ b/arch/powerpc/platforms/86xx/Makefile @@ -0,0 +1,10 @@ +# +# Makefile for the PowerPC 86xx linux kernel. +# + + +ifeq ($(CONFIG_PPC_86xx),y) +obj-$(CONFIG_SMP) += mpc86xx_smp.o +endif +obj-$(CONFIG_MPC8641_HPCN) += mpc86xx_hpcn.o +obj-$(CONFIG_PCI) += pci.o mpc86xx_pcie.o diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile index c4f6b0d2d14..29286369456 100644 --- a/arch/powerpc/platforms/Makefile +++ b/arch/powerpc/platforms/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_PPC_CHRP) += chrp/ obj-$(CONFIG_4xx) += 4xx/ obj-$(CONFIG_PPC_83xx) += 83xx/ obj-$(CONFIG_PPC_85xx) += 85xx/ +obj-$(CONFIG_PPC_86xx) += 86xx/ obj-$(CONFIG_PPC_PSERIES) += pseries/ obj-$(CONFIG_PPC_ISERIES) += iseries/ obj-$(CONFIG_PPC_MAPLE) += maple/ -- cgit v1.2.3 From 96abe9358becb543c21121699c711897374bcbdf Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Sat, 17 Jun 2006 17:52:37 -0500 Subject: [POWERPC] Add mpc8641_hpcn_defconfig config file. Signed-off-by: Jon Loeliger Signed-off-by: Haiying Wang Signed-off-by: Paul Mackerras --- arch/powerpc/configs/mpc8641_hpcn_defconfig | 921 ++++++++++++++++++++++++++++ 1 file changed, 921 insertions(+) create mode 100644 arch/powerpc/configs/mpc8641_hpcn_defconfig diff --git a/arch/powerpc/configs/mpc8641_hpcn_defconfig b/arch/powerpc/configs/mpc8641_hpcn_defconfig new file mode 100644 index 00000000000..d7a30f9bc53 --- /dev/null +++ b/arch/powerpc/configs/mpc8641_hpcn_defconfig @@ -0,0 +1,921 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.17-rc3 +# Fri Jun 16 10:47:09 2006 +# +# CONFIG_PPC64 is not set +CONFIG_PPC32=y +CONFIG_PPC_MERGE=y +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_PPC=y +CONFIG_EARLY_PRINTK=y +CONFIG_GENERIC_NVRAM=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_PPC_OF=y +CONFIG_PPC_UDBG_16550=y +CONFIG_GENERIC_TBSYNC=y +# CONFIG_DEFAULT_UIMAGE is not set + +# +# Processor support +# +# CONFIG_CLASSIC32 is not set +# CONFIG_PPC_52xx is not set +# CONFIG_PPC_82xx is not set +# CONFIG_PPC_83xx is not set +# CONFIG_PPC_85xx is not set +CONFIG_PPC_86xx=y +# CONFIG_40x is not set +# CONFIG_44x is not set +# CONFIG_8xx is not set +# CONFIG_E200 is not set +CONFIG_6xx=y +CONFIG_PPC_FPU=y +CONFIG_ALTIVEC=y +CONFIG_PPC_STD_MMU=y +CONFIG_PPC_STD_MMU_32=y +CONFIG_SMP=y +CONFIG_NR_CPUS=2 + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +# CONFIG_SWAP is not set +# CONFIG_SYSVIPC is not set +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +# CONFIG_CPUSETS is not set +# CONFIG_RELAY is not set +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +# CONFIG_ELF_CORE is not set +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +# CONFIG_SLAB is not set +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +CONFIG_SLOB=y + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# Block layer +# +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_IOSCHED_CFQ is not set +# CONFIG_DEFAULT_AS is not set +CONFIG_DEFAULT_DEADLINE=y +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="deadline" +CONFIG_MPIC=y +# CONFIG_WANT_EARLY_SERIAL is not set +CONFIG_PPC_INDIRECT_PCI_BE=y + +# +# Platform Support +# +CONFIG_MPC8641_HPCN=y +CONFIG_MPC8641=y + +# +# Kernel options +# +CONFIG_HIGHMEM=y +# CONFIG_HZ_100 is not set +# CONFIG_HZ_250 is not set +CONFIG_HZ_1000=y +CONFIG_HZ=1000 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_PREEMPT_BKL=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +# CONFIG_IRQ_ALL_CPUS is not set +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_PROC_DEVICETREE=y +# CONFIG_CMDLINE_BOOL is not set +# CONFIG_PM is not set +# CONFIG_SECCOMP is not set +CONFIG_ISA_DMA_API=y + +# +# Bus options +# +CONFIG_GENERIC_ISA_DMA=y +CONFIG_PPC_I8259=y +CONFIG_PPC_INDIRECT_PCI=y +CONFIG_FSL_SOC=y +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +# CONFIG_PCI_DEBUG is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# PCI Hotplug Support +# +# CONFIG_HOTPLUG_PCI is not set + +# +# Advanced setup +# +# CONFIG_ADVANCED_OPTIONS is not set + +# +# Default settings for advanced configuration options are used +# +CONFIG_HIGHMEM_START=0xfe000000 +CONFIG_LOWMEM_SIZE=0x30000000 +CONFIG_KERNEL_START=0xc0000000 +CONFIG_TASK_SIZE=0x80000000 +CONFIG_BOOT_LOAD=0x00800000 + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +CONFIG_IPV6=y +# CONFIG_IPV6_PRIVACY is not set +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_IPV6_TUNNEL is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_DEBUG_DRIVER is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=131072 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Macintosh device drivers +# +# CONFIG_WINDFARM is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +CONFIG_DUMMY=y +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +CONFIG_VITESSE_PHY=y + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_NET_PCI is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set +CONFIG_GIANFAR=y +# CONFIG_GFAR_NAPI is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_CHELSIO_T1 is not set +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_NR_UARTS=2 +CONFIG_SERIAL_8250_RUNTIME_UARTS=2 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_8250_DETECT_IRQ=y +CONFIG_SERIAL_8250_RSA=y + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +CONFIG_I2C=y +# CONFIG_I2C_CHARDEV is not set + +# +# I2C Algorithms +# +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_I810 is not set +# CONFIG_I2C_PIIX4 is not set +CONFIG_I2C_MPC=y +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_PROSAVAGE is not set +# CONFIG_I2C_SAVAGE4 is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +# CONFIG_I2C_VOODOO3 is not set +# CONFIG_I2C_PCA_ISA is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +CONFIG_SENSORS_EEPROM=y +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_M41T00 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +# CONFIG_HWMON is not set +# CONFIG_HWMON_VID is not set + +# +# Misc devices +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +# CONFIG_VGACON_SOFT_SCROLLBACK is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +# CONFIG_USB is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# InfiniBand support +# +# CONFIG_INFINIBAND is not set + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# + +# +# Real Time Clock +# +# CONFIG_RTC_CLASS is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_INOTIFY is not set +# CONFIG_QUOTA is not set +# CONFIG_DNOTIFY is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=y +# CONFIG_NFSD_V3 is not set +CONFIG_NFSD_TCP=y +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +CONFIG_LDM_PARTITION=y +# CONFIG_LDM_DEBUG is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set + +# +# Instrumentation Support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +# CONFIG_MAGIC_SYSRQ is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_HIGHMEM is not set +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_UNWIND_INFO is not set +CONFIG_FORCED_INLINING=y +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_DEBUGGER is not set +# CONFIG_BDI_SWITCH is not set +# CONFIG_BOOTX_TEXT is not set +# CONFIG_PPC_EARLY_DEBUG_LPAR is not set +# CONFIG_PPC_EARLY_DEBUG_G5 is not set +# CONFIG_PPC_EARLY_DEBUG_RTAS is not set +# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set +# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Hardware crypto devices +# -- cgit v1.2.3 From 9674ed38d8e4a9ce15c61b4306ef803cad0e1dc0 Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Sat, 17 Jun 2006 17:52:40 -0500 Subject: [POWERPC] Add 8641 CPU table entry. Signed-off-by: Wei Zhang Signed-off-by: Xianghua Xiao Signed-off-by: Jon Loeliger Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/cputable.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index abf7d42a8b0..1c114880dc0 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -722,6 +722,18 @@ struct cpu_spec cpu_specs[] = { .oprofile_type = PPC_OPROFILE_G4, .platform = "ppc7450", }, + { /* 8641 */ + .pvr_mask = 0xffffffff, + .pvr_value = 0x80040010, + .cpu_name = "8641", + .cpu_features = CPU_FTRS_7447A, + .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, + .icache_bsize = 32, + .dcache_bsize = 32, + .num_pmcs = 6, + .cpu_setup = __setup_cpu_745x + }, + { /* 82xx (8240, 8245, 8260 are all 603e cores) */ .pvr_mask = 0x7fff0000, .pvr_value = 0x00810000, -- cgit v1.2.3 From ee0339f205d60375c5ce1653c0dc318c6ec72668 Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Sat, 17 Jun 2006 17:52:44 -0500 Subject: [POWERPC] Add starting of secondary 86xx CPUs. Clear the high BATS during load_up_mmu if FTR_HAS_HIGH_BATS. Allow just a bit more time for secondary CPUs to phone home. Signed-off-by: Wei Zhang Signed-off-by: Haiying Wang Signed-off-by: Jon Loeliger Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/head_32.S | 14 +++++++++++++- arch/powerpc/kernel/smp.c | 2 +- arch/powerpc/mm/ppc_mmu_32.c | 4 ++-- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S index a0579e859b2..b25b25902d1 100644 --- a/arch/powerpc/kernel/head_32.S +++ b/arch/powerpc/kernel/head_32.S @@ -973,6 +973,13 @@ __secondary_start_gemini: b __secondary_start #endif /* CONFIG_GEMINI */ + .globl __secondary_start_mpc86xx +__secondary_start_mpc86xx: + mfspr r3, SPRN_PIR + stw r3, __secondary_hold_acknowledge@l(0) + mr r24, r3 /* cpu # */ + b __secondary_start + .globl __secondary_start_pmac_0 __secondary_start_pmac_0: /* NB the entries for cpus 0, 1, 2 must each occupy 8 bytes. */ @@ -1088,7 +1095,12 @@ load_up_mmu: LOAD_BAT(1,r3,r4,r5) LOAD_BAT(2,r3,r4,r5) LOAD_BAT(3,r3,r4,r5) - +BEGIN_FTR_SECTION + LOAD_BAT(4,r3,r4,r5) + LOAD_BAT(5,r3,r4,r5) + LOAD_BAT(6,r3,r4,r5) + LOAD_BAT(7,r3,r4,r5) +END_FTR_SECTION_IFSET(CPU_FTR_HAS_HIGH_BATS) blr /* diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 530f7dba0bd..c5d179d4f81 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -492,7 +492,7 @@ int __devinit __cpu_up(unsigned int cpu) * -- Cort */ if (system_state < SYSTEM_RUNNING) - for (c = 5000; c && !cpu_callin_map[cpu]; c--) + for (c = 50000; c && !cpu_callin_map[cpu]; c--) udelay(100); #ifdef CONFIG_HOTPLUG_CPU else diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c index ab5cd724b12..2ed43a493b3 100644 --- a/arch/powerpc/mm/ppc_mmu_32.c +++ b/arch/powerpc/mm/ppc_mmu_32.c @@ -43,13 +43,13 @@ unsigned long _SDR1; union ubat { /* BAT register values to be loaded */ BAT bat; u32 word[2]; -} BATS[4][2]; /* 4 pairs of IBAT, DBAT */ +} BATS[8][2]; /* 8 pairs of IBAT, DBAT */ struct batrange { /* stores address ranges mapped by BATs */ unsigned long start; unsigned long limit; unsigned long phys; -} bat_addrs[4]; +} bat_addrs[8]; /* * Return PA for this VA if it is mapped by a BAT, or 0 -- cgit v1.2.3 From 4ca4b6274c30d53d22014fb6974efe2b3e52cfdc Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Sat, 17 Jun 2006 17:52:45 -0500 Subject: [POWERPC] Add the MPC8641 HPCN platform files. Signed-off-by: Xianghua Xiao Signed-off-by: Haiying Wang Signed-off-by: Wei Zhang Signed-off-by: Jon Loeliger Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/86xx/mpc8641_hpcn.h | 54 +++++ arch/powerpc/platforms/86xx/mpc86xx.h | 28 +++ arch/powerpc/platforms/86xx/mpc86xx_hpcn.c | 326 +++++++++++++++++++++++++++++ arch/powerpc/platforms/86xx/mpc86xx_smp.c | 117 +++++++++++ 4 files changed, 525 insertions(+) create mode 100644 arch/powerpc/platforms/86xx/mpc8641_hpcn.h create mode 100644 arch/powerpc/platforms/86xx/mpc86xx.h create mode 100644 arch/powerpc/platforms/86xx/mpc86xx_hpcn.c create mode 100644 arch/powerpc/platforms/86xx/mpc86xx_smp.c diff --git a/arch/powerpc/platforms/86xx/mpc8641_hpcn.h b/arch/powerpc/platforms/86xx/mpc8641_hpcn.h new file mode 100644 index 00000000000..5042253758b --- /dev/null +++ b/arch/powerpc/platforms/86xx/mpc8641_hpcn.h @@ -0,0 +1,54 @@ +/* + * MPC8641 HPCN board definitions + * + * Copyright 2006 Freescale Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * Author: Xianghua Xiao + */ + +#ifndef __MPC8641_HPCN_H__ +#define __MPC8641_HPCN_H__ + +#include +#include + +/* PCI interrupt controller */ +#define PIRQA 3 +#define PIRQB 4 +#define PIRQC 5 +#define PIRQD 6 +#define PIRQ7 7 +#define PIRQE 9 +#define PIRQF 10 +#define PIRQG 11 +#define PIRQH 12 + +/* PCI-Express memory map */ +#define MPC86XX_PCIE_LOWER_IO 0x00000000 +#define MPC86XX_PCIE_UPPER_IO 0x00ffffff + +#define MPC86XX_PCIE_LOWER_MEM 0x80000000 +#define MPC86XX_PCIE_UPPER_MEM 0x9fffffff + +#define MPC86XX_PCIE_IO_BASE 0xe2000000 +#define MPC86XX_PCIE_MEM_OFFSET 0x00000000 + +#define MPC86XX_PCIE_IO_SIZE 0x01000000 + +#define PCIE1_CFG_ADDR_OFFSET (0x8000) +#define PCIE1_CFG_DATA_OFFSET (0x8004) + +#define PCIE2_CFG_ADDR_OFFSET (0x9000) +#define PCIE2_CFG_DATA_OFFSET (0x9004) + +#define MPC86xx_PCIE_OFFSET PCIE1_CFG_ADDR_OFFSET +#define MPC86xx_PCIE_SIZE (0x1000) + +#define MPC86XX_RSTCR_OFFSET (0xe00b0) /* Reset Control Register */ + +#endif /* __MPC8641_HPCN_H__ */ diff --git a/arch/powerpc/platforms/86xx/mpc86xx.h b/arch/powerpc/platforms/86xx/mpc86xx.h new file mode 100644 index 00000000000..e3c9e4f417d --- /dev/null +++ b/arch/powerpc/platforms/86xx/mpc86xx.h @@ -0,0 +1,28 @@ +/* + * Copyright 2006 Freescale Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#ifndef __MPC86XX_H__ +#define __MPC86XX_H__ + +/* + * Declaration for the various functions exported by the + * mpc86xx_* files. Mostly for use by mpc86xx_setup(). + */ + +extern int __init add_bridge(struct device_node *dev); + +extern void __init setup_indirect_pcie(struct pci_controller *hose, + u32 cfg_addr, u32 cfg_data); +extern void __init setup_indirect_pcie_nomap(struct pci_controller *hose, + void __iomem *cfg_addr, + void __iomem *cfg_data); + +extern void __init mpc86xx_smp_init(void); + +#endif /* __MPC86XX_H__ */ diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file mode 100644 index 00000000000..483c21df181 --- /dev/null +++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c @@ -0,0 +1,326 @@ +/* + * MPC86xx HPCN board specific routines + * + * Recode: ZHANG WEI + * Initial author: Xianghua Xiao + * + * Copyright 2006 Freescale Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "mpc86xx.h" + +#ifndef CONFIG_PCI +unsigned long isa_io_base = 0; +unsigned long isa_mem_base = 0; +unsigned long pci_dram_offset = 0; +#endif + + +/* + * Internal interrupts are all Level Sensitive, and Positive Polarity + */ + +static u_char mpc86xx_hpcn_openpic_initsenses[] __initdata = { + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 0: Reserved */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 1: MCM */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 2: DDR DRAM */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 3: LBIU */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 4: DMA 0 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 5: DMA 1 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 6: DMA 2 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 7: DMA 3 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 8: PCIE1 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 9: PCIE2 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 10: Reserved */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 11: Reserved */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 12: DUART2 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 13: TSEC 1 Transmit */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 14: TSEC 1 Receive */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 15: TSEC 3 transmit */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 16: TSEC 3 receive */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 17: TSEC 3 error */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 18: TSEC 1 Receive/Transmit Error */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 19: TSEC 2 Transmit */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 20: TSEC 2 Receive */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 21: TSEC 4 transmit */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 22: TSEC 4 receive */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 23: TSEC 4 error */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 24: TSEC 2 Receive/Transmit Error */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 25: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 26: DUART1 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 27: I2C */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 28: Performance Monitor */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 29: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 30: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 31: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 32: SRIO error/write-port unit */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 33: SRIO outbound doorbell */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 34: SRIO inbound doorbell */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 35: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 36: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 37: SRIO outbound message unit 1 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 38: SRIO inbound message unit 1 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 39: SRIO outbound message unit 2 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 40: SRIO inbound message unit 2 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 41: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 42: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 43: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 44: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 45: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 46: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 47: Unused */ + 0x0, /* External 0: */ + 0x0, /* External 1: */ + 0x0, /* External 2: */ + 0x0, /* External 3: */ + 0x0, /* External 4: */ + 0x0, /* External 5: */ + 0x0, /* External 6: */ + 0x0, /* External 7: */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 8: Pixis FPGA */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* External 9: ULI 8259 INTR Cascade */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 10: Quad ETH PHY */ + 0x0, /* External 11: */ + 0x0, + 0x0, + 0x0, + 0x0, +}; + + +void __init +mpc86xx_hpcn_init_irq(void) +{ + struct mpic *mpic1; + phys_addr_t openpic_paddr; + + /* Determine the Physical Address of the OpenPIC regs */ + openpic_paddr = get_immrbase() + MPC86xx_OPENPIC_OFFSET; + + /* Alloc mpic structure and per isu has 16 INT entries. */ + mpic1 = mpic_alloc(openpic_paddr, + MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, + 16, MPC86xx_OPENPIC_IRQ_OFFSET, 0, 250, + mpc86xx_hpcn_openpic_initsenses, + sizeof(mpc86xx_hpcn_openpic_initsenses), + " MPIC "); + BUG_ON(mpic1 == NULL); + + /* 48 Internal Interrupts */ + mpic_assign_isu(mpic1, 0, openpic_paddr + 0x10200); + mpic_assign_isu(mpic1, 1, openpic_paddr + 0x10400); + mpic_assign_isu(mpic1, 2, openpic_paddr + 0x10600); + + /* 16 External interrupts */ + mpic_assign_isu(mpic1, 3, openpic_paddr + 0x10000); + + mpic_init(mpic1); + +#ifdef CONFIG_PCI + mpic_setup_cascade(MPC86xx_IRQ_EXT9, i8259_irq_cascade, NULL); + i8259_init(0, I8259_OFFSET); +#endif +} + + + +#ifdef CONFIG_PCI +/* + * interrupt routing + */ + +int +mpc86xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) +{ + static char pci_irq_table[][4] = { + /* + * PCI IDSEL/INTPIN->INTLINE + * A B C D + */ + {PIRQA, PIRQB, PIRQC, PIRQD}, /* IDSEL 17 -- PCI Slot 1 */ + {PIRQB, PIRQC, PIRQD, PIRQA}, /* IDSEL 18 -- PCI Slot 2 */ + {0, 0, 0, 0}, /* IDSEL 19 */ + {0, 0, 0, 0}, /* IDSEL 20 */ + {0, 0, 0, 0}, /* IDSEL 21 */ + {0, 0, 0, 0}, /* IDSEL 22 */ + {0, 0, 0, 0}, /* IDSEL 23 */ + {0, 0, 0, 0}, /* IDSEL 24 */ + {0, 0, 0, 0}, /* IDSEL 25 */ + {PIRQD, PIRQA, PIRQB, PIRQC}, /* IDSEL 26 -- PCI Bridge*/ + {PIRQC, 0, 0, 0}, /* IDSEL 27 -- LAN */ + {PIRQE, PIRQF, PIRQH, PIRQ7}, /* IDSEL 28 -- USB 1.1 */ + {PIRQE, PIRQF, PIRQG, 0}, /* IDSEL 29 -- Audio & Modem */ + {PIRQH, 0, 0, 0}, /* IDSEL 30 -- LPC & PMU*/ + {PIRQD, 0, 0, 0}, /* IDSEL 31 -- ATA */ + }; + + const long min_idsel = 17, max_idsel = 31, irqs_per_slot = 4; + return PCI_IRQ_TABLE_LOOKUP + I8259_OFFSET; +} + + +int +mpc86xx_exclude_device(u_char bus, u_char devfn) +{ +#if !defined(CONFIG_PCI) + if (bus == 0 && PCI_SLOT(devfn) == 0) + return PCIBIOS_DEVICE_NOT_FOUND; +#endif + + return PCIBIOS_SUCCESSFUL; +} +#endif /* CONFIG_PCI */ + + +static void __init +mpc86xx_hpcn_setup_arch(void) +{ + struct device_node *np; + + if (ppc_md.progress) + ppc_md.progress("mpc86xx_hpcn_setup_arch()", 0); + + np = of_find_node_by_type(NULL, "cpu"); + if (np != 0) { + unsigned int *fp; + + fp = (int *)get_property(np, "clock-frequency", NULL); + if (fp != 0) + loops_per_jiffy = *fp / HZ; + else + loops_per_jiffy = 50000000 / HZ; + of_node_put(np); + } + +#ifdef CONFIG_PCI + for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) + add_bridge(np); + + ppc_md.pci_swizzle = common_swizzle; + ppc_md.pci_map_irq = mpc86xx_map_irq; + ppc_md.pci_exclude_device = mpc86xx_exclude_device; +#endif + + printk("MPC86xx HPCN board from Freescale Semiconductor\n"); + +#ifdef CONFIG_ROOT_NFS + ROOT_DEV = Root_NFS; +#else + ROOT_DEV = Root_HDA1; +#endif + +#ifdef CONFIG_SMP + mpc86xx_smp_init(); +#endif +} + + +void +mpc86xx_hpcn_show_cpuinfo(struct seq_file *m) +{ + struct device_node *root; + uint memsize = total_memory; + const char *model = ""; + uint svid = mfspr(SPRN_SVR); + + seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n"); + + root = of_find_node_by_path("/"); + if (root) + model = get_property(root, "model", NULL); + seq_printf(m, "Machine\t\t: %s\n", model); + of_node_put(root); + + seq_printf(m, "SVR\t\t: 0x%x\n", svid); + seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); +} + + +/* + * Called very early, device-tree isn't unflattened + */ +static int __init mpc86xx_hpcn_probe(void) +{ + unsigned long root = of_get_flat_dt_root(); + + if (of_flat_dt_is_compatible(root, "mpc86xx")) + return 1; /* Looks good */ + + return 0; +} + + +void +mpc86xx_restart(char *cmd) +{ + void __iomem *rstcr; + + rstcr = ioremap(get_immrbase() + MPC86XX_RSTCR_OFFSET, 0x100); + + local_irq_disable(); + + /* Assert reset request to Reset Control Register */ + out_be32(rstcr, 0x2); + + /* not reached */ +} + + +long __init +mpc86xx_time_init(void) +{ + unsigned int temp; + + /* Set the time base to zero */ + mtspr(SPRN_TBWL, 0); + mtspr(SPRN_TBWU, 0); + + temp = mfspr(SPRN_HID0); + temp |= HID0_TBEN; + mtspr(SPRN_HID0, temp); + asm volatile("isync"); + + return 0; +} + + +define_machine(mpc86xx_hpcn) { + .name = "MPC86xx HPCN", + .probe = mpc86xx_hpcn_probe, + .setup_arch = mpc86xx_hpcn_setup_arch, + .init_IRQ = mpc86xx_hpcn_init_irq, + .show_cpuinfo = mpc86xx_hpcn_show_cpuinfo, + .get_irq = mpic_get_irq, + .restart = mpc86xx_restart, + .time_init = mpc86xx_time_init, + .calibrate_decr = generic_calibrate_decr, + .progress = udbg_progress, +}; diff --git a/arch/powerpc/platforms/86xx/mpc86xx_smp.c b/arch/powerpc/platforms/86xx/mpc86xx_smp.c new file mode 100644 index 00000000000..944ec4b7141 --- /dev/null +++ b/arch/powerpc/platforms/86xx/mpc86xx_smp.c @@ -0,0 +1,117 @@ +/* + * Author: Xianghua Xiao + * Zhang Wei + * + * Copyright 2006 Freescale Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "mpc86xx.h" + +extern void __secondary_start_mpc86xx(void); +extern unsigned long __secondary_hold_acknowledge; + + +static void __init +smp_86xx_release_core(int nr) +{ + void *mcm_vaddr; + unsigned long vaddr, pcr; + + if (nr < 0 || nr >= NR_CPUS) + return; + + /* + * Startup Core #nr. + */ + mcm_vaddr = ioremap(get_immrbase() + MPC86xx_MCM_OFFSET, + MPC86xx_MCM_SIZE); + vaddr = (unsigned long)mcm_vaddr + MCM_PORT_CONFIG_OFFSET; + pcr = in_be32((volatile unsigned *)vaddr); + pcr |= 1 << (nr + 24); + out_be32((volatile unsigned *)vaddr, pcr); +} + + +static void __init +smp_86xx_kick_cpu(int nr) +{ + unsigned int save_vector; + unsigned long target, flags; + int n = 0; + volatile unsigned int *vector + = (volatile unsigned int *)(KERNELBASE + 0x100); + + if (nr < 0 || nr >= NR_CPUS) + return; + + pr_debug("smp_86xx_kick_cpu: kick CPU #%d\n", nr); + + local_irq_save(flags); + local_irq_disable(); + + /* Save reset vector */ + save_vector = *vector; + + /* Setup fake reset vector to call __secondary_start_mpc86xx. */ + target = (unsigned long) __secondary_start_mpc86xx; + create_branch((unsigned long)vector, target, BRANCH_SET_LINK); + + /* Kick that CPU */ + smp_86xx_release_core(nr); + + /* Wait a bit for the CPU to take the exception. */ + while ((__secondary_hold_acknowledge != nr) && (n++, n < 1000)) + mdelay(1); + + /* Restore the exception vector */ + *vector = save_vector; + flush_icache_range((unsigned long) vector, (unsigned long) vector + 4); + + local_irq_restore(flags); + + pr_debug("wait CPU #%d for %d msecs.\n", nr, n); +} + + +static void __init +smp_86xx_setup_cpu(int cpu_nr) +{ + mpic_setup_this_cpu(); +} + + +struct smp_ops_t smp_86xx_ops = { + .message_pass = smp_mpic_message_pass, + .probe = smp_mpic_probe, + .kick_cpu = smp_86xx_kick_cpu, + .setup_cpu = smp_86xx_setup_cpu, + .take_timebase = smp_generic_take_timebase, + .give_timebase = smp_generic_give_timebase, +}; + + +void __init +mpc86xx_smp_init(void) +{ + smp_ops = &smp_86xx_ops; +} -- cgit v1.2.3 From b809b3e86f39651475b30ceb1caf535071534d4d Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Sat, 17 Jun 2006 17:52:48 -0500 Subject: [POWERPC] Add mpc8641hpcn PCI/PCI-Express platform files. Signed-off-by: Xianghua Xiao Signed-off-by: Wei Zhang Signed-off-by: Haiying Wang Signed-off-by: Jon Loeliger Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/86xx/mpc86xx_pcie.c | 173 +++++++++++++++ arch/powerpc/platforms/86xx/pci.c | 325 +++++++++++++++++++++++++++++ 2 files changed, 498 insertions(+) create mode 100644 arch/powerpc/platforms/86xx/mpc86xx_pcie.c create mode 100644 arch/powerpc/platforms/86xx/pci.c diff --git a/arch/powerpc/platforms/86xx/mpc86xx_pcie.c b/arch/powerpc/platforms/86xx/mpc86xx_pcie.c new file mode 100644 index 00000000000..a2f4f730213 --- /dev/null +++ b/arch/powerpc/platforms/86xx/mpc86xx_pcie.c @@ -0,0 +1,173 @@ +/* + * Support for indirect PCI bridges. + * + * Copyright (C) 1998 Gabriel Paubert. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * "Temporary" MPC8548 Errata file - + * The standard indirect_pci code should work with future silicon versions. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "mpc86xx.h" + +#define PCI_CFG_OUT out_be32 + +/* ERRATA PCI-Ex 14 PCIE Controller timeout */ +#define PCIE_FIX out_be32(hose->cfg_addr+0x4, 0x0400ffff) + + +static int +indirect_read_config_pcie(struct pci_bus *bus, unsigned int devfn, int offset, + int len, u32 *val) +{ + struct pci_controller *hose = bus->sysdata; + volatile void __iomem *cfg_data; + u32 temp; + + if (ppc_md.pci_exclude_device) + if (ppc_md.pci_exclude_device(bus->number, devfn)) + return PCIBIOS_DEVICE_NOT_FOUND; + + /* Possible artifact of CDCpp50937 needs further investigation */ + if (devfn != 0x0 && bus->number == 0xff) + return PCIBIOS_DEVICE_NOT_FOUND; + + PCIE_FIX; + if (bus->number == 0xff) { + PCI_CFG_OUT(hose->cfg_addr, + (0x80000000 | ((offset & 0xf00) << 16) | + ((bus->number - hose->bus_offset) << 16) + | (devfn << 8) | ((offset & 0xfc) ))); + } else { + PCI_CFG_OUT(hose->cfg_addr, + (0x80000001 | ((offset & 0xf00) << 16) | + ((bus->number - hose->bus_offset) << 16) + | (devfn << 8) | ((offset & 0xfc) ))); + } + + /* + * Note: the caller has already checked that offset is + * suitably aligned and that len is 1, 2 or 4. + */ + /* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */ + cfg_data = hose->cfg_data; + PCIE_FIX; + temp = in_le32(cfg_data); + switch (len) { + case 1: + *val = (temp >> (((offset & 3))*8)) & 0xff; + break; + case 2: + *val = (temp >> (((offset & 3))*8)) & 0xffff; + break; + default: + *val = temp; + break; + } + return PCIBIOS_SUCCESSFUL; +} + +static int +indirect_write_config_pcie(struct pci_bus *bus, unsigned int devfn, int offset, + int len, u32 val) +{ + struct pci_controller *hose = bus->sysdata; + volatile void __iomem *cfg_data; + u32 temp; + + if (ppc_md.pci_exclude_device) + if (ppc_md.pci_exclude_device(bus->number, devfn)) + return PCIBIOS_DEVICE_NOT_FOUND; + + /* Possible artifact of CDCpp50937 needs further investigation */ + if (devfn != 0x0 && bus->number == 0xff) + return PCIBIOS_DEVICE_NOT_FOUND; + + PCIE_FIX; + if (bus->number == 0xff) { + PCI_CFG_OUT(hose->cfg_addr, + (0x80000000 | ((offset & 0xf00) << 16) | + ((bus->number - hose->bus_offset) << 16) + | (devfn << 8) | ((offset & 0xfc) ))); + } else { + PCI_CFG_OUT(hose->cfg_addr, + (0x80000001 | ((offset & 0xf00) << 16) | + ((bus->number - hose->bus_offset) << 16) + | (devfn << 8) | ((offset & 0xfc) ))); + } + + /* + * Note: the caller has already checked that offset is + * suitably aligned and that len is 1, 2 or 4. + */ + /* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */ + cfg_data = hose->cfg_data; + switch (len) { + case 1: + PCIE_FIX; + temp = in_le32(cfg_data); + temp = (temp & ~(0xff << ((offset & 3) * 8))) | + (val << ((offset & 3) * 8)); + PCIE_FIX; + out_le32(cfg_data, temp); + break; + case 2: + PCIE_FIX; + temp = in_le32(cfg_data); + temp = (temp & ~(0xffff << ((offset & 3) * 8))); + temp |= (val << ((offset & 3) * 8)) ; + PCIE_FIX; + out_le32(cfg_data, temp); + break; + default: + PCIE_FIX; + out_le32(cfg_data, val); + break; + } + PCIE_FIX; + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops indirect_pcie_ops = { + indirect_read_config_pcie, + indirect_write_config_pcie +}; + +void __init +setup_indirect_pcie_nomap(struct pci_controller* hose, void __iomem * cfg_addr, + void __iomem * cfg_data) +{ + hose->cfg_addr = cfg_addr; + hose->cfg_data = cfg_data; + hose->ops = &indirect_pcie_ops; +} + +void __init +setup_indirect_pcie(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data) +{ + unsigned long base = cfg_addr & PAGE_MASK; + void __iomem *mbase, *addr, *data; + + mbase = ioremap(base, PAGE_SIZE); + addr = mbase + (cfg_addr & ~PAGE_MASK); + if ((cfg_data & PAGE_MASK) != base) + mbase = ioremap(cfg_data & PAGE_MASK, PAGE_SIZE); + data = mbase + (cfg_data & ~PAGE_MASK); + setup_indirect_pcie_nomap(hose, addr, data); +} diff --git a/arch/powerpc/platforms/86xx/pci.c b/arch/powerpc/platforms/86xx/pci.c new file mode 100644 index 00000000000..5180df7c75b --- /dev/null +++ b/arch/powerpc/platforms/86xx/pci.c @@ -0,0 +1,325 @@ +/* + * MPC86XX pci setup code + * + * Recode: ZHANG WEI + * Initial author: Xianghua Xiao + * + * Copyright 2006 Freescale Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "mpc86xx.h" + +#undef DEBUG + +#ifdef DEBUG +#define DBG(fmt, args...) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ## args) +#else +#define DBG(fmt, args...) +#endif + +struct pcie_outbound_window_regs { + uint pexotar; /* 0x.0 - PCI Express outbound translation address register */ + uint pexotear; /* 0x.4 - PCI Express outbound translation extended address register */ + uint pexowbar; /* 0x.8 - PCI Express outbound window base address register */ + char res1[4]; + uint pexowar; /* 0x.10 - PCI Express outbound window attributes register */ + char res2[12]; +}; + +struct pcie_inbound_window_regs { + uint pexitar; /* 0x.0 - PCI Express inbound translation address register */ + char res1[4]; + uint pexiwbar; /* 0x.8 - PCI Express inbound window base address register */ + uint pexiwbear; /* 0x.c - PCI Express inbound window base extended address register */ + uint pexiwar; /* 0x.10 - PCI Express inbound window attributes register */ + char res2[12]; +}; + +static void __init setup_pcie_atmu(struct pci_controller *hose, struct resource *rsrc) +{ + volatile struct ccsr_pex *pcie; + volatile struct pcie_outbound_window_regs *pcieow; + volatile struct pcie_inbound_window_regs *pcieiw; + int i = 0; + + DBG("PCIE memory map start 0x%x, size 0x%x\n", rsrc->start, + rsrc->end - rsrc->start + 1); + pcie = ioremap(rsrc->start, rsrc->end - rsrc->start + 1); + + /* Disable all windows (except pexowar0 since its ignored) */ + pcie->pexowar1 = 0; + pcie->pexowar2 = 0; + pcie->pexowar3 = 0; + pcie->pexowar4 = 0; + pcie->pexiwar1 = 0; + pcie->pexiwar2 = 0; + pcie->pexiwar3 = 0; + + pcieow = (struct pcie_outbound_window_regs *)&pcie->pexotar1; + pcieiw = (struct pcie_inbound_window_regs *)&pcie->pexitar1; + + /* Setup outbound MEM window */ + for(i = 0; i < 3; i++) + if (hose->mem_resources[i].flags & IORESOURCE_MEM){ + DBG("PCIE MEM resource start 0x%08x, size 0x%08x.\n", + hose->mem_resources[i].start, + hose->mem_resources[i].end + - hose->mem_resources[i].start + 1); + pcieow->pexotar = (hose->mem_resources[i].start) >> 12 + & 0x000fffff; + pcieow->pexotear = 0; + pcieow->pexowbar = (hose->mem_resources[i].start) >> 12 + & 0x000fffff; + /* Enable, Mem R/W */ + pcieow->pexowar = 0x80044000 | + (__ilog2(hose->mem_resources[i].end + - hose->mem_resources[i].start + 1) + - 1); + pcieow++; + } + + /* Setup outbound IO window */ + if (hose->io_resource.flags & IORESOURCE_IO){ + DBG("PCIE IO resource start 0x%08x, size 0x%08x, phy base 0x%08x.\n", + hose->io_resource.start, + hose->io_resource.end - hose->io_resource.start + 1, + hose->io_base_phys); + pcieow->pexotar = (hose->io_resource.start) >> 12 & 0x000fffff; + pcieow->pexotear = 0; + pcieow->pexowbar = (hose->io_base_phys) >> 12 & 0x000fffff; + /* Enable, IO R/W */ + pcieow->pexowar = 0x80088000 | (__ilog2(hose->io_resource.end + - hose->io_resource.start + 1) - 1); + } + + /* Setup 2G inbound Memory Window @ 0 */ + pcieiw->pexitar = 0x00000000; + pcieiw->pexiwbar = 0x00000000; + /* Enable, Prefetch, Local Mem, Snoop R/W, 2G */ + pcieiw->pexiwar = 0xa0f5501e; +} + +static void __init +mpc86xx_setup_pcie(struct pci_controller *hose, u32 pcie_offset, u32 pcie_size) +{ + volatile struct ccsr_pex *pcie; + u16 cmd; + unsigned int temps; + + DBG("PCIE host controller register offset 0x%08x, size 0x%08x.\n", + pcie_offset, pcie_size); + + pcie = ioremap(pcie_offset, pcie_size); + + early_read_config_word(hose, 0, 0, PCI_COMMAND, &cmd); + cmd |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY + | PCI_COMMAND_IO; + early_write_config_word(hose, 0, 0, PCI_COMMAND, cmd); + + early_write_config_byte(hose, 0, 0, PCI_LATENCY_TIMER, 0x80); + + /* PCIE Bus, Fix the MPC8641D host bridge's location to bus 0xFF. */ + early_read_config_dword(hose, 0, 0, PCI_PRIMARY_BUS, &temps); + temps = (temps & 0xff000000) | (0xff) | (0x0 << 8) | (0xfe << 16); + early_write_config_dword(hose, 0, 0, PCI_PRIMARY_BUS, temps); +} + +int __init add_bridge(struct device_node *dev) +{ + int len; + struct pci_controller *hose; + struct resource rsrc; + int *bus_range; + int has_address = 0; + int primary = 0; + + DBG("Adding PCIE host bridge %s\n", dev->full_name); + + /* Fetch host bridge registers address */ + has_address = (of_address_to_resource(dev, 0, &rsrc) == 0); + + /* Get bus range if any */ + bus_range = (int *) get_property(dev, "bus-range", &len); + if (bus_range == NULL || len < 2 * sizeof(int)) + printk(KERN_WARNING "Can't get bus-range for %s, assume" + " bus 0\n", dev->full_name); + + hose = pcibios_alloc_controller(); + if (!hose) + return -ENOMEM; + hose->arch_data = dev; + hose->set_cfg_type = 1; + + /* last_busno = 0xfe cause by MPC8641 PCIE bug */ + hose->first_busno = bus_range ? bus_range[0] : 0x0; + hose->last_busno = bus_range ? bus_range[1] : 0xfe; + + setup_indirect_pcie(hose, rsrc.start, rsrc.start + 0x4); + + /* Setup the PCIE host controller. */ + mpc86xx_setup_pcie(hose, rsrc.start, rsrc.end - rsrc.start + 1); + + if ((rsrc.start & 0xfffff) == 0x8000) + primary = 1; + + printk(KERN_INFO "Found MPC86xx PCIE host bridge at 0x%08lx. " + "Firmware bus number: %d->%d\n", + rsrc.start, hose->first_busno, hose->last_busno); + + DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n", + hose, hose->cfg_addr, hose->cfg_data); + + /* Interpret the "ranges" property */ + /* This also maps the I/O region and sets isa_io/mem_base */ + pci_process_bridge_OF_ranges(hose, dev, primary); + + /* Setup PEX window registers */ + setup_pcie_atmu(hose, &rsrc); + + return 0; +} + +static void __devinit quirk_ali1575(struct pci_dev *dev) +{ + unsigned short temp; + + /* + * ALI1575 interrupts route table setup: + * + * IRQ pin IRQ# + * PIRQA ---- 3 + * PIRQB ---- 4 + * PIRQC ---- 5 + * PIRQD ---- 6 + * PIRQE ---- 9 + * PIRQF ---- 10 + * PIRQG ---- 11 + * PIRQH ---- 12 + * + * interrupts for PCI slot0 -- PIRQA / PIRQB / PIRQC / PIRQD + * PCI slot1 -- PIRQB / PIRQC / PIRQD / PIRQA + */ + pci_write_config_dword(dev, 0x48, 0xb9317542); + + /* USB 1.1 OHCI controller 1, interrupt: PIRQE */ + pci_write_config_byte(dev, 0x86, 0x0c); + + /* USB 1.1 OHCI controller 2, interrupt: PIRQF */ + pci_write_config_byte(dev, 0x87, 0x0d); + + /* USB 1.1 OHCI controller 3, interrupt: PIRQH */ + pci_write_config_byte(dev, 0x88, 0x0f); + + /* USB 2.0 controller, interrupt: PIRQ7 */ + pci_write_config_byte(dev, 0x74, 0x06); + + /* Audio controller, interrupt: PIRQE */ + pci_write_config_byte(dev, 0x8a, 0x0c); + + /* Modem controller, interrupt: PIRQF */ + pci_write_config_byte(dev, 0x8b, 0x0d); + + /* HD audio controller, interrupt: PIRQG */ + pci_write_config_byte(dev, 0x8c, 0x0e); + + /* Serial ATA interrupt: PIRQD */ + pci_write_config_byte(dev, 0x8d, 0x0b); + + /* SMB interrupt: PIRQH */ + pci_write_config_byte(dev, 0x8e, 0x0f); + + /* PMU ACPI SCI interrupt: PIRQH */ + pci_write_config_byte(dev, 0x8f, 0x0f); + + /* Primary PATA IDE IRQ: 14 + * Secondary PATA IDE IRQ: 15 + */ + pci_write_config_byte(dev, 0x44, 0x3d); + pci_write_config_byte(dev, 0x75, 0x0f); + + /* Set IRQ14 and IRQ15 to legacy IRQs */ + pci_read_config_word(dev, 0x46, &temp); + temp |= 0xc000; + pci_write_config_word(dev, 0x46, temp); + + /* Set i8259 interrupt trigger + * IRQ 3: Level + * IRQ 4: Level + * IRQ 5: Level + * IRQ 6: Level + * IRQ 7: Level + * IRQ 9: Level + * IRQ 10: Level + * IRQ 11: Level + * IRQ 12: Level + * IRQ 14: Edge + * IRQ 15: Edge + */ + outb(0xfa, 0x4d0); + outb(0x1e, 0x4d1); +} + +static void __devinit quirk_uli5288(struct pci_dev *dev) +{ + unsigned char c; + + pci_read_config_byte(dev,0x83,&c); + c |= 0x80; + pci_write_config_byte(dev, 0x83, c); + + pci_write_config_byte(dev, 0x09, 0x01); + pci_write_config_byte(dev, 0x0a, 0x06); + + pci_read_config_byte(dev,0x83,&c); + c &= 0x7f; + pci_write_config_byte(dev, 0x83, c); + + pci_read_config_byte(dev,0x84,&c); + c |= 0x01; + pci_write_config_byte(dev, 0x84, c); +} + +static void __devinit quirk_uli5229(struct pci_dev *dev) +{ + unsigned short temp; + pci_write_config_word(dev, 0x04, 0x0405); + pci_read_config_word(dev, 0x4a, &temp); + temp |= 0x1000; + pci_write_config_word(dev, 0x4a, temp); +} + +static void __devinit early_uli5249(struct pci_dev *dev) +{ + unsigned char temp; + pci_write_config_word(dev, 0x04, 0x0007); + pci_read_config_byte(dev, 0x7c, &temp); + pci_write_config_byte(dev, 0x7c, 0x80); + pci_write_config_byte(dev, 0x09, 0x01); + pci_write_config_byte(dev, 0x7c, temp); + dev->class |= 0x1; +} + +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x1575, quirk_ali1575); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5288, quirk_uli5288); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5229, quirk_uli5229); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_AL, 0x5249, early_uli5249); -- cgit v1.2.3 From 6b543404058a5ffdca8c48e95e0b8a69bb4bdba9 Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Sat, 17 Jun 2006 17:52:51 -0500 Subject: [POWERPC] Add 8641 Register space and IRQ definitions. Signed-off-by: Jeff Brown Signed-off-by: Xianghua Xiao Signed-off-by: Jon Loeliger Signed-off-by: Paul Mackerras --- include/asm-powerpc/immap_86xx.h | 199 +++++++++++++++++++++++++++++++++++++++ include/asm-powerpc/irq.h | 86 +++++++++++++++++ include/asm-powerpc/mpc86xx.h | 47 +++++++++ 3 files changed, 332 insertions(+) create mode 100644 include/asm-powerpc/immap_86xx.h create mode 100644 include/asm-powerpc/mpc86xx.h diff --git a/include/asm-powerpc/immap_86xx.h b/include/asm-powerpc/immap_86xx.h new file mode 100644 index 00000000000..d905b662226 --- /dev/null +++ b/include/asm-powerpc/immap_86xx.h @@ -0,0 +1,199 @@ +/* + * MPC86xx Internal Memory Map + * + * Author: Jeff Brown + * + * Copyright 2004 Freescale Semiconductor, Inc + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#ifndef __ASM_POWERPC_IMMAP_86XX_H__ +#define __ASM_POWERPC_IMMAP_86XX_H__ +#ifdef __KERNEL__ + +/* Eventually this should define all the IO block registers in 86xx */ + +/* PCI Registers */ +typedef struct ccsr_pci { + uint cfg_addr; /* 0x.000 - PCI Configuration Address Register */ + uint cfg_data; /* 0x.004 - PCI Configuration Data Register */ + uint int_ack; /* 0x.008 - PCI Interrupt Acknowledge Register */ + char res1[3060]; + uint potar0; /* 0x.c00 - PCI Outbound Transaction Address Register 0 */ + uint potear0; /* 0x.c04 - PCI Outbound Translation Extended Address Register 0 */ + uint powbar0; /* 0x.c08 - PCI Outbound Window Base Address Register 0 */ + char res2[4]; + uint powar0; /* 0x.c10 - PCI Outbound Window Attributes Register 0 */ + char res3[12]; + uint potar1; /* 0x.c20 - PCI Outbound Transaction Address Register 1 */ + uint potear1; /* 0x.c24 - PCI Outbound Translation Extended Address Register 1 */ + uint powbar1; /* 0x.c28 - PCI Outbound Window Base Address Register 1 */ + char res4[4]; + uint powar1; /* 0x.c30 - PCI Outbound Window Attributes Register 1 */ + char res5[12]; + uint potar2; /* 0x.c40 - PCI Outbound Transaction Address Register 2 */ + uint potear2; /* 0x.c44 - PCI Outbound Translation Extended Address Register 2 */ + uint powbar2; /* 0x.c48 - PCI Outbound Window Base Address Register 2 */ + char res6[4]; + uint powar2; /* 0x.c50 - PCI Outbound Window Attributes Register 2 */ + char res7[12]; + uint potar3; /* 0x.c60 - PCI Outbound Transaction Address Register 3 */ + uint potear3; /* 0x.c64 - PCI Outbound Translation Extended Address Register 3 */ + uint powbar3; /* 0x.c68 - PCI Outbound Window Base Address Register 3 */ + char res8[4]; + uint powar3; /* 0x.c70 - PCI Outbound Window Attributes Register 3 */ + char res9[12]; + uint potar4; /* 0x.c80 - PCI Outbound Transaction Address Register 4 */ + uint potear4; /* 0x.c84 - PCI Outbound Translation Extended Address Register 4 */ + uint powbar4; /* 0x.c88 - PCI Outbound Window Base Address Register 4 */ + char res10[4]; + uint powar4; /* 0x.c90 - PCI Outbound Window Attributes Register 4 */ + char res11[268]; + uint pitar3; /* 0x.da0 - PCI Inbound Translation Address Register 3 */ + char res12[4]; + uint piwbar3; /* 0x.da8 - PCI Inbound Window Base Address Register 3 */ + uint piwbear3; /* 0x.dac - PCI Inbound Window Base Extended Address Register 3 */ + uint piwar3; /* 0x.db0 - PCI Inbound Window Attributes Register 3 */ + char res13[12]; + uint pitar2; /* 0x.dc0 - PCI Inbound Translation Address Register 2 */ + char res14[4]; + uint piwbar2; /* 0x.dc8 - PCI Inbound Window Base Address Register 2 */ + uint piwbear2; /* 0x.dcc - PCI Inbound Window Base Extended Address Register 2 */ + uint piwar2; /* 0x.dd0 - PCI Inbound Window Attributes Register 2 */ + char res15[12]; + uint pitar1; /* 0x.de0 - PCI Inbound Translation Address Register 1 */ + char res16[4]; + uint piwbar1; /* 0x.de8 - PCI Inbound Window Base Address Register 1 */ + char res17[4]; + uint piwar1; /* 0x.df0 - PCI Inbound Window Attributes Register 1 */ + char res18[12]; + uint err_dr; /* 0x.e00 - PCI Error Detect Register */ + uint err_cap_dr; /* 0x.e04 - PCI Error Capture Disable Register */ + uint err_en; /* 0x.e08 - PCI Error Enable Register */ + uint err_attrib; /* 0x.e0c - PCI Error Attributes Capture Register */ + uint err_addr; /* 0x.e10 - PCI Error Address Capture Register */ + uint err_ext_addr; /* 0x.e14 - PCI Error Extended Address Capture Register */ + uint err_dl; /* 0x.e18 - PCI Error Data Low Capture Register */ + uint err_dh; /* 0x.e1c - PCI Error Data High Capture Register */ + uint gas_timr; /* 0x.e20 - PCI Gasket Timer Register */ + uint pci_timr; /* 0x.e24 - PCI Timer Register */ + char res19[472]; +} ccsr_pci_t; + +/* PCI Express Registers */ +typedef struct ccsr_pex { + uint pex_config_addr; /* 0x.000 - PCI Express Configuration Address Register */ + uint pex_config_data; /* 0x.004 - PCI Express Configuration Data Register */ + char res1[4]; + uint pex_otb_cpl_tor; /* 0x.00c - PCI Express Outbound completion timeout register */ + uint pex_conf_tor; /* 0x.010 - PCI Express configuration timeout register */ + char res2[12]; + uint pex_pme_mes_dr; /* 0x.020 - PCI Express PME and message detect register */ + uint pex_pme_mes_disr; /* 0x.024 - PCI Express PME and message disable register */ + uint pex_pme_mes_ier; /* 0x.028 - PCI Express PME and message interrupt enable register */ + uint pex_pmcr; /* 0x.02c - PCI Express power management command register */ + char res3[3024]; + uint pexotar0; /* 0x.c00 - PCI Express outbound translation address register 0 */ + uint pexotear0; /* 0x.c04 - PCI Express outbound translation extended address register 0*/ + char res4[8]; + uint pexowar0; /* 0x.c10 - PCI Express outbound window attributes register 0*/ + char res5[12]; + uint pexotar1; /* 0x.c20 - PCI Express outbound translation address register 1 */ + uint pexotear1; /* 0x.c24 - PCI Express outbound translation extended address register 1*/ + uint pexowbar1; /* 0x.c28 - PCI Express outbound window base address register 1*/ + char res6[4]; + uint pexowar1; /* 0x.c30 - PCI Express outbound window attributes register 1*/ + char res7[12]; + uint pexotar2; /* 0x.c40 - PCI Express outbound translation address register 2 */ + uint pexotear2; /* 0x.c44 - PCI Express outbound translation extended address register 2*/ + uint pexowbar2; /* 0x.c48 - PCI Express outbound window base address register 2*/ + char res8[4]; + uint pexowar2; /* 0x.c50 - PCI Express outbound window attributes register 2*/ + char res9[12]; + uint pexotar3; /* 0x.c60 - PCI Express outbound translation address register 3 */ + uint pexotear3; /* 0x.c64 - PCI Express outbound translation extended address register 3*/ + uint pexowbar3; /* 0x.c68 - PCI Express outbound window base address register 3*/ + char res10[4]; + uint pexowar3; /* 0x.c70 - PCI Express outbound window attributes register 3*/ + char res11[12]; + uint pexotar4; /* 0x.c80 - PCI Express outbound translation address register 4 */ + uint pexotear4; /* 0x.c84 - PCI Express outbound translation extended address register 4*/ + uint pexowbar4; /* 0x.c88 - PCI Express outbound window base address register 4*/ + char res12[4]; + uint pexowar4; /* 0x.c90 - PCI Express outbound window attributes register 4*/ + char res13[12]; + char res14[256]; + uint pexitar3; /* 0x.da0 - PCI Express inbound translation address register 3 */ + char res15[4]; + uint pexiwbar3; /* 0x.da8 - PCI Express inbound window base address register 3 */ + uint pexiwbear3; /* 0x.dac - PCI Express inbound window base extended address register 3 */ + uint pexiwar3; /* 0x.db0 - PCI Express inbound window attributes register 3 */ + char res16[12]; + uint pexitar2; /* 0x.dc0 - PCI Express inbound translation address register 2 */ + char res17[4]; + uint pexiwbar2; /* 0x.dc8 - PCI Express inbound window base address register 2 */ + uint pexiwbear2; /* 0x.dcc - PCI Express inbound window base extended address register 2 */ + uint pexiwar2; /* 0x.dd0 - PCI Express inbound window attributes register 2 */ + char res18[12]; + uint pexitar1; /* 0x.de0 - PCI Express inbound translation address register 2 */ + char res19[4]; + uint pexiwbar1; /* 0x.de8 - PCI Express inbound window base address register 2 */ + uint pexiwbear1; /* 0x.dec - PCI Express inbound window base extended address register 2 */ + uint pexiwar1; /* 0x.df0 - PCI Express inbound window attributes register 2 */ + char res20[12]; + uint pex_err_dr; /* 0x.e00 - PCI Express error detect register */ + char res21[4]; + uint pex_err_en; /* 0x.e08 - PCI Express error interrupt enable register */ + char res22[4]; + uint pex_err_disr; /* 0x.e10 - PCI Express error disable register */ + char res23[12]; + uint pex_err_cap_stat; /* 0x.e20 - PCI Express error capture status register */ + char res24[4]; + uint pex_err_cap_r0; /* 0x.e28 - PCI Express error capture register 0 */ + uint pex_err_cap_r1; /* 0x.e2c - PCI Express error capture register 0 */ + uint pex_err_cap_r2; /* 0x.e30 - PCI Express error capture register 0 */ + uint pex_err_cap_r3; /* 0x.e34 - PCI Express error capture register 0 */ +} ccsr_pex_t; + +/* Global Utility Registers */ +typedef struct ccsr_guts { + uint porpllsr; /* 0x.0000 - POR PLL Ratio Status Register */ + uint porbmsr; /* 0x.0004 - POR Boot Mode Status Register */ + uint porimpscr; /* 0x.0008 - POR I/O Impedance Status and Control Register */ + uint pordevsr; /* 0x.000c - POR I/O Device Status Register */ + uint pordbgmsr; /* 0x.0010 - POR Debug Mode Status Register */ + char res1[12]; + uint gpporcr; /* 0x.0020 - General-Purpose POR Configuration Register */ + char res2[12]; + uint gpiocr; /* 0x.0030 - GPIO Control Register */ + char res3[12]; + uint gpoutdr; /* 0x.0040 - General-Purpose Output Data Register */ + char res4[12]; + uint gpindr; /* 0x.0050 - General-Purpose Input Data Register */ + char res5[12]; + uint pmuxcr; /* 0x.0060 - Alternate Function Signal Multiplex Control */ + char res6[12]; + uint devdisr; /* 0x.0070 - Device Disable Control */ + char res7[12]; + uint powmgtcsr; /* 0x.0080 - Power Management Status and Control Register */ + char res8[12]; + uint mcpsumr; /* 0x.0090 - Machine Check Summary Register */ + char res9[12]; + uint pvr; /* 0x.00a0 - Processor Version Register */ + uint svr; /* 0x.00a4 - System Version Register */ + char res10[3416]; + uint clkocr; /* 0x.0e00 - Clock Out Select Register */ + char res11[12]; + uint ddrdllcr; /* 0x.0e10 - DDR DLL Control Register */ + char res12[12]; + uint lbcdllcr; /* 0x.0e20 - LBC DLL Control Register */ + char res13[61916]; +} ccsr_guts_t; + +#endif /* __ASM_POWERPC_IMMAP_86XX_H__ */ +#endif /* __KERNEL__ */ diff --git a/include/asm-powerpc/irq.h b/include/asm-powerpc/irq.h index 7bc6d73b282..7a762096f19 100644 --- a/include/asm-powerpc/irq.h +++ b/include/asm-powerpc/irq.h @@ -348,6 +348,92 @@ extern u64 ppc64_interrupt_controller; #define SIU_INT_PC1 ((uint)0x3e+CPM_IRQ_OFFSET) #define SIU_INT_PC0 ((uint)0x3f+CPM_IRQ_OFFSET) +#elif defined(CONFIG_PPC_86xx) +#include + +#define NR_EPIC_INTS 48 +#ifndef NR_8259_INTS +#define NR_8259_INTS 16 /*ULI 1575 can route 12 interrupts */ +#endif +#define NUM_8259_INTERRUPTS NR_8259_INTS + +#ifndef I8259_OFFSET +#define I8259_OFFSET 0 +#endif + +#define NR_IRQS 256 + +/* Internal IRQs on MPC86xx OpenPIC */ + +#ifndef MPC86xx_OPENPIC_IRQ_OFFSET +#define MPC86xx_OPENPIC_IRQ_OFFSET NR_8259_INTS +#endif + +/* The 48 internal sources */ +#define MPC86xx_IRQ_NULL ( 0 + MPC86xx_OPENPIC_IRQ_OFFSET) +#define MPC86xx_IRQ_MCM ( 1 + MPC86xx_OPENPIC_IRQ_OFFSET) +#define MPC86xx_IRQ_DDR ( 2 + MPC86xx_OPENPIC_IRQ_OFFSET) +#define MPC86xx_IRQ_LBC ( 3 + MPC86xx_OPENPIC_IRQ_OFFSET) +#define MPC86xx_IRQ_DMA0 ( 4 + MPC86xx_OPENPIC_IRQ_OFFSET) +#define MPC86xx_IRQ_DMA1 ( 5 + MPC86xx_OPENPIC_IRQ_OFFSET) +#define MPC86xx_IRQ_DMA2 ( 6 + MPC86xx_OPENPIC_IRQ_OFFSET) +#define MPC86xx_IRQ_DMA3 ( 7 + MPC86xx_OPENPIC_IRQ_OFFSET) + +/* no 10,11 */ +#define MPC86xx_IRQ_UART2 (12 + MPC86xx_OPENPIC_IRQ_OFFSET) +#define MPC86xx_IRQ_TSEC1_TX (13 + MPC86xx_OPENPIC_IRQ_OFFSET) +#define MPC86xx_IRQ_TSEC1_RX (14 + MPC86xx_OPENPIC_IRQ_OFFSET) +#define MPC86xx_IRQ_TSEC3_TX (15 + MPC86xx_OPENPIC_IRQ_OFFSET) +#define MPC86xx_IRQ_TSEC3_RX (16 + MPC86xx_OPENPIC_IRQ_OFFSET) +#define MPC86xx_IRQ_TSEC3_ERROR (17 + MPC86xx_OPENPIC_IRQ_OFFSET) +#define MPC86xx_IRQ_TSEC1_ERROR (18 + MPC86xx_OPENPIC_IRQ_OFFSET) +#define MPC86xx_IRQ_TSEC2_TX (19 + MPC86xx_OPENPIC_IRQ_OFFSET) +#define MPC86xx_IRQ_TSEC2_RX (20 + MPC86xx_OPENPIC_IRQ_OFFSET) +#define MPC86xx_IRQ_TSEC4_TX (21 + MPC86xx_OPENPIC_IRQ_OFFSET) +#define MPC86xx_IRQ_TSEC4_RX (22 + MPC86xx_OPENPIC_IRQ_OFFSET) +#define MPC86xx_IRQ_TSEC4_ERROR (23 + MPC86xx_OPENPIC_IRQ_OFFSET) +#define MPC86xx_IRQ_TSEC2_ERROR (24 + MPC86xx_OPENPIC_IRQ_OFFSET) +/* no 25 */ +#define MPC86xx_IRQ_UART1 (26 + MPC86xx_OPENPIC_IRQ_OFFSET) +#define MPC86xx_IRQ_IIC (27 + MPC86xx_OPENPIC_IRQ_OFFSET) +#define MPC86xx_IRQ_PERFMON (28 + MPC86xx_OPENPIC_IRQ_OFFSET) +/* no 29,30,31 */ +#define MPC86xx_IRQ_SRIO_ERROR (32 + MPC86xx_OPENPIC_IRQ_OFFSET) +#define MPC86xx_IRQ_SRIO_OUT_BELL (33 + MPC86xx_OPENPIC_IRQ_OFFSET) +#define MPC86xx_IRQ_SRIO_IN_BELL (34 + MPC86xx_OPENPIC_IRQ_OFFSET) +/* no 35,36 */ +#define MPC86xx_IRQ_SRIO_OUT_MSG1 (37 + MPC86xx_OPENPIC_IRQ_OFFSET) +#define MPC86xx_IRQ_SRIO_IN_MSG1 (38 + MPC86xx_OPENPIC_IRQ_OFFSET) +#define MPC86xx_IRQ_SRIO_OUT_MSG2 (39 + MPC86xx_OPENPIC_IRQ_OFFSET) +#define MPC86xx_IRQ_SRIO_IN_MSG2 (40 + MPC86xx_OPENPIC_IRQ_OFFSET) + +/* The 12 external interrupt lines */ +#define MPC86xx_IRQ_EXT_BASE 48 +#define MPC86xx_IRQ_EXT0 (0 + MPC86xx_IRQ_EXT_BASE \ + + MPC86xx_OPENPIC_IRQ_OFFSET) +#define MPC86xx_IRQ_EXT1 (1 + MPC86xx_IRQ_EXT_BASE \ + + MPC86xx_OPENPIC_IRQ_OFFSET) +#define MPC86xx_IRQ_EXT2 (2 + MPC86xx_IRQ_EXT_BASE \ + + MPC86xx_OPENPIC_IRQ_OFFSET) +#define MPC86xx_IRQ_EXT3 (3 + MPC86xx_IRQ_EXT_BASE \ + + MPC86xx_OPENPIC_IRQ_OFFSET) +#define MPC86xx_IRQ_EXT4 (4 + MPC86xx_IRQ_EXT_BASE \ + + MPC86xx_OPENPIC_IRQ_OFFSET) +#define MPC86xx_IRQ_EXT5 (5 + MPC86xx_IRQ_EXT_BASE \ + + MPC86xx_OPENPIC_IRQ_OFFSET) +#define MPC86xx_IRQ_EXT6 (6 + MPC86xx_IRQ_EXT_BASE \ + + MPC86xx_OPENPIC_IRQ_OFFSET) +#define MPC86xx_IRQ_EXT7 (7 + MPC86xx_IRQ_EXT_BASE \ + + MPC86xx_OPENPIC_IRQ_OFFSET) +#define MPC86xx_IRQ_EXT8 (8 + MPC86xx_IRQ_EXT_BASE \ + + MPC86xx_OPENPIC_IRQ_OFFSET) +#define MPC86xx_IRQ_EXT9 (9 + MPC86xx_IRQ_EXT_BASE \ + + MPC86xx_OPENPIC_IRQ_OFFSET) +#define MPC86xx_IRQ_EXT10 (10 + MPC86xx_IRQ_EXT_BASE \ + + MPC86xx_OPENPIC_IRQ_OFFSET) +#define MPC86xx_IRQ_EXT11 (11 + MPC86xx_IRQ_EXT_BASE \ + + MPC86xx_OPENPIC_IRQ_OFFSET) + #else /* CONFIG_40x + CONFIG_8xx */ /* * this is the # irq's for all ppc arch's (pmac/chrp/prep) diff --git a/include/asm-powerpc/mpc86xx.h b/include/asm-powerpc/mpc86xx.h new file mode 100644 index 00000000000..d0a6718d188 --- /dev/null +++ b/include/asm-powerpc/mpc86xx.h @@ -0,0 +1,47 @@ +/* + * MPC86xx definitions + * + * Author: Jeff Brown + * + * Copyright 2004 Freescale Semiconductor, Inc + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#ifdef __KERNEL__ +#ifndef __ASM_POWERPC_MPC86xx_H__ +#define __ASM_POWERPC_MPC86xx_H__ + +#include +#include + +#ifdef CONFIG_PPC_86xx + +#ifdef CONFIG_MPC8641_HPCN +#include +#endif + +#define _IO_BASE isa_io_base +#define _ISA_MEM_BASE isa_mem_base +#ifdef CONFIG_PCI +#define PCI_DRAM_OFFSET pci_dram_offset +#else +#define PCI_DRAM_OFFSET 0 +#endif + +#define CPU0_BOOT_RELEASE 0x01000000 +#define CPU1_BOOT_RELEASE 0x02000000 +#define CPU_ALL_RELEASED (CPU0_BOOT_RELEASE | CPU1_BOOT_RELEASE) +#define MCM_PORT_CONFIG_OFFSET 0x1010 + +/* Offset from CCSRBAR */ +#define MPC86xx_OPENPIC_OFFSET (0x40000) +#define MPC86xx_MCM_OFFSET (0x00000) +#define MPC86xx_MCM_SIZE (0x02000) + +#endif /* CONFIG_PPC_86xx */ +#endif /* __ASM_POWERPC_MPC86xx_H__ */ +#endif /* __KERNEL__ */ -- cgit v1.2.3 From 2097c7f04af7fb962ab8676ed8083f350ed885f7 Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Sat, 17 Jun 2006 17:52:54 -0500 Subject: [POWERPC] Document I2C_MPC option for 86xx too. The same I2C driver found on 85xx, etc., can be used for 86xx too. Signed-off-by: Jon Loeliger Signed-off-by: Paul Mackerras --- drivers/i2c/busses/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index d6d44946a28..fbeae821ffb 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -252,12 +252,12 @@ config I2C_POWERMAC will be called i2c-powermac. config I2C_MPC - tristate "MPC107/824x/85xx/52xx" + tristate "MPC107/824x/85xx/52xx/86xx" depends on I2C && PPC32 help If you say yes to this option, support will be included for the built-in I2C interface on the MPC107/Tsi107/MPC8240/MPC8245 and - MPC85xx family processors. The driver may also work on 52xx + MPC85xx/MPC8641 family processors. The driver may also work on 52xx family processors, though interrupts are known not to work. This driver can also be built as a module. If so, the module -- cgit v1.2.3 From ef82a306b46dbedaecbb154b24d05dfab937df35 Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Sat, 17 Jun 2006 17:52:55 -0500 Subject: [POWERPC] Add Vitesse 8244 PHY for MPC8641 HPCN platform. Signed-off-by: Kriston Carson Signed-off-by: Xianghua Xiao Signed-off-by: Jon Loeliger Acked-by: Jeff Garzik Signed-off-by: Paul Mackerras --- drivers/net/Kconfig | 6 +-- drivers/net/phy/Kconfig | 5 +++ drivers/net/phy/Makefile | 1 + drivers/net/phy/vitesse.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 121 insertions(+), 3 deletions(-) create mode 100644 drivers/net/phy/vitesse.c diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index bdaaad8f212..c1c275833fc 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2179,11 +2179,11 @@ config SPIDER_NET config GIANFAR tristate "Gianfar Ethernet" - depends on 85xx || 83xx + depends on 85xx || 83xx || PPC_86xx select PHYLIB help - This driver supports the Gigabit TSEC on the MPC85xx - family of chips, and the FEC on the 8540 + This driver supports the Gigabit TSEC on the MPC83xx, MPC85xx, + and MPC86xx family of chips, and the FEC on the 8540. config GFAR_NAPI bool "NAPI Support" diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index fa39b944bc4..76e51b1baf1 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -44,6 +44,11 @@ config CICADA_PHY depends on PHYLIB ---help--- Currently supports the cis8204 +config VITESSE_PHY + tristate "Drivers for the Vitesse PHYs" + depends on PHYLIB + ---help--- + Currently supports the vsc8244 endmenu diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index e4116a5fbb4..a8d066eab6a 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -8,3 +8,4 @@ obj-$(CONFIG_DAVICOM_PHY) += davicom.o obj-$(CONFIG_CICADA_PHY) += cicada.o obj-$(CONFIG_LXT_PHY) += lxt.o obj-$(CONFIG_QSEMI_PHY) += qsemi.o +obj-$(CONFIG_VITESSE_PHY) += vitesse.o diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c new file mode 100644 index 00000000000..ffd215d9a9b --- /dev/null +++ b/drivers/net/phy/vitesse.c @@ -0,0 +1,112 @@ +/* + * Driver for Vitesse PHYs + * + * Author: Kriston Carson + * + * Copyright (c) 2005 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include +#include +#include +#include +#include +#include + +/* Vitesse Extended Control Register 1 */ +#define MII_VSC8244_EXT_CON1 0x17 +#define MII_VSC8244_EXTCON1_INIT 0x0000 + +/* Vitesse Interrupt Mask Register */ +#define MII_VSC8244_IMASK 0x19 +#define MII_VSC8244_IMASK_IEN 0x8000 +#define MII_VSC8244_IMASK_SPEED 0x4000 +#define MII_VSC8244_IMASK_LINK 0x2000 +#define MII_VSC8244_IMASK_DUPLEX 0x1000 +#define MII_VSC8244_IMASK_MASK 0xf000 + +/* Vitesse Interrupt Status Register */ +#define MII_VSC8244_ISTAT 0x1a +#define MII_VSC8244_ISTAT_STATUS 0x8000 +#define MII_VSC8244_ISTAT_SPEED 0x4000 +#define MII_VSC8244_ISTAT_LINK 0x2000 +#define MII_VSC8244_ISTAT_DUPLEX 0x1000 + +/* Vitesse Auxiliary Control/Status Register */ +#define MII_VSC8244_AUX_CONSTAT 0x1c +#define MII_VSC8244_AUXCONSTAT_INIT 0x0004 +#define MII_VSC8244_AUXCONSTAT_DUPLEX 0x0020 +#define MII_VSC8244_AUXCONSTAT_SPEED 0x0018 +#define MII_VSC8244_AUXCONSTAT_GBIT 0x0010 +#define MII_VSC8244_AUXCONSTAT_100 0x0008 + +MODULE_DESCRIPTION("Vitesse PHY driver"); +MODULE_AUTHOR("Kriston Carson"); +MODULE_LICENSE("GPL"); + +static int vsc824x_config_init(struct phy_device *phydev) +{ + int err; + + err = phy_write(phydev, MII_VSC8244_AUX_CONSTAT, + MII_VSC8244_AUXCONSTAT_INIT); + if (err < 0) + return err; + + err = phy_write(phydev, MII_VSC8244_EXT_CON1, + MII_VSC8244_EXTCON1_INIT); + return err; +} + +static int vsc824x_ack_interrupt(struct phy_device *phydev) +{ + int err = phy_read(phydev, MII_VSC8244_ISTAT); + + return (err < 0) ? err : 0; +} + +static int vsc824x_config_intr(struct phy_device *phydev) +{ + int err; + + if (phydev->interrupts == PHY_INTERRUPT_ENABLED) + err = phy_write(phydev, MII_VSC8244_IMASK, + MII_VSC8244_IMASK_MASK); + else + err = phy_write(phydev, MII_VSC8244_IMASK, 0); + return err; +} + +/* Vitesse 824x */ +static struct phy_driver vsc8244_driver = { + .phy_id = 0x000fc6c2, + .name = "Vitesse VSC8244", + .phy_id_mask = 0x000fffc0, + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .config_init = &vsc824x_config_init, + .config_aneg = &genphy_config_aneg, + .read_status = &genphy_read_status, + .ack_interrupt = &vsc824x_ack_interrupt, + .config_intr = &vsc824x_config_intr, + .driver = { .owner = THIS_MODULE,}, +}; + +static int __init vsc8244_init(void) +{ + return phy_driver_register(&vsc8244_driver); +} + +static void __exit vsc8244_exit(void) +{ + phy_driver_unregister(&vsc8244_driver); +} + +module_init(vsc8244_init); +module_exit(vsc8244_exit); -- cgit v1.2.3 From acf7d76827a577059636e949079021e6af6dd702 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 19 Jun 2006 20:33:16 +0200 Subject: [POWERPC] cell: add RAS support This is a first version of support for the Cell BE "Reliability, Availability and Serviceability" features. It doesn't yet handle some of the RAS interrupts (the ones described in iic_is/iic_irr), I'm still working on a proper way to expose these. They are essentially a cascaded controller by themselves (sic !) though I may just handle them locally to the iic driver. I need also to sync with David Erb on the way he hooked in the performance monitor interrupt. So that's all for 2.6.17 and I'll do more work on that with my rework of the powerpc interrupt layer that I'm hacking on at the moment. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/configs/cell_defconfig | 1 + arch/powerpc/kernel/head_64.S | 29 +++++++ arch/powerpc/kernel/prom.c | 43 +++++++++++ arch/powerpc/platforms/cell/Kconfig | 4 + arch/powerpc/platforms/cell/Makefile | 3 +- arch/powerpc/platforms/cell/cbe_regs.c | 128 +++++++++++++++++++++++++++++++ arch/powerpc/platforms/cell/cbe_regs.h | 129 ++++++++++++++++++++++++++++++++ arch/powerpc/platforms/cell/interrupt.c | 37 +++------ arch/powerpc/platforms/cell/pervasive.c | 104 ++++++------------------- arch/powerpc/platforms/cell/pervasive.h | 37 +-------- arch/powerpc/platforms/cell/ras.c | 112 +++++++++++++++++++++++++++ arch/powerpc/platforms/cell/ras.h | 9 +++ arch/powerpc/platforms/cell/setup.c | 10 ++- include/asm-powerpc/prom.h | 3 + include/asm-powerpc/reg.h | 2 + 15 files changed, 505 insertions(+), 146 deletions(-) create mode 100644 arch/powerpc/platforms/cell/cbe_regs.c create mode 100644 arch/powerpc/platforms/cell/cbe_regs.h create mode 100644 arch/powerpc/platforms/cell/ras.c create mode 100644 arch/powerpc/platforms/cell/ras.h diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig index dbe421dc3c1..5b8599d03f1 100644 --- a/arch/powerpc/configs/cell_defconfig +++ b/arch/powerpc/configs/cell_defconfig @@ -133,6 +133,7 @@ CONFIG_CELL_IIC=y # CONFIG_SPU_FS=m CONFIG_SPUFS_MMAP=y +CONFIG_CBE_RAS=y # # Kernel options diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index b7d140430a4..831acbdf259 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -316,6 +316,21 @@ label##_pSeries: \ mtspr SPRN_SPRG1,r13; /* save r13 */ \ EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common) +#define HSTD_EXCEPTION_PSERIES(n, label) \ + . = n; \ + .globl label##_pSeries; \ +label##_pSeries: \ + HMT_MEDIUM; \ + mtspr SPRN_SPRG1,r20; /* save r20 */ \ + mfspr r20,SPRN_HSRR0; /* copy HSRR0 to SRR0 */ \ + mtspr SPRN_SRR0,r20; \ + mfspr r20,SPRN_HSRR1; /* copy HSRR0 to SRR0 */ \ + mtspr SPRN_SRR1,r20; \ + mfspr r20,SPRN_SPRG1; /* restore r20 */ \ + mtspr SPRN_SPRG1,r13; /* save r13 */ \ + EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common) + + #define STD_EXCEPTION_ISERIES(n, label, area) \ .globl label##_iSeries; \ label##_iSeries: \ @@ -544,8 +559,17 @@ system_call_pSeries: STD_EXCEPTION_PSERIES(0xf20, altivec_unavailable) +#ifdef CONFIG_CBE_RAS + HSTD_EXCEPTION_PSERIES(0x1200, cbe_system_error) +#endif /* CONFIG_CBE_RAS */ STD_EXCEPTION_PSERIES(0x1300, instruction_breakpoint) +#ifdef CONFIG_CBE_RAS + HSTD_EXCEPTION_PSERIES(0x1600, cbe_maintenance) +#endif /* CONFIG_CBE_RAS */ STD_EXCEPTION_PSERIES(0x1700, altivec_assist) +#ifdef CONFIG_CBE_RAS + HSTD_EXCEPTION_PSERIES(0x1800, cbe_thermal) +#endif /* CONFIG_CBE_RAS */ . = 0x3000 @@ -827,6 +851,11 @@ machine_check_common: #else STD_EXCEPTION_COMMON(0x1700, altivec_assist, .unknown_exception) #endif +#ifdef CONFIG_CBE_RAS + STD_EXCEPTION_COMMON(0x1200, cbe_system_error, .cbe_system_error_exception) + STD_EXCEPTION_COMMON(0x1600, cbe_maintenance, .cbe_maintenance_exception) + STD_EXCEPTION_COMMON(0x1800, cbe_thermal, .cbe_thermal_exception) +#endif /* CONFIG_CBE_RAS */ /* * Here we have detected that the kernel stack pointer is bad. diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 629023240ec..483455c5bb0 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -2105,3 +2105,46 @@ int prom_update_property(struct device_node *np, return 0; } + +/* Find the device node for a given logical cpu number, also returns the cpu + * local thread number (index in ibm,interrupt-server#s) if relevant and + * asked for (non NULL) + */ +struct device_node *of_get_cpu_node(int cpu, unsigned int *thread) +{ + int hardid; + struct device_node *np; + + hardid = get_hard_smp_processor_id(cpu); + + for_each_node_by_type(np, "cpu") { + u32 *intserv; + unsigned int plen, t; + + /* Check for ibm,ppc-interrupt-server#s. If it doesn't exist + * fallback to "reg" property and assume no threads + */ + intserv = (u32 *)get_property(np, "ibm,ppc-interrupt-server#s", + &plen); + if (intserv == NULL) { + u32 *reg = (u32 *)get_property(np, "reg", NULL); + if (reg == NULL) + continue; + if (*reg == hardid) { + if (thread) + *thread = 0; + return np; + } + } else { + plen /= sizeof(u32); + for (t = 0; t < plen; t++) { + if (hardid == intserv[t]) { + if (thread) + *thread = t; + return np; + } + } + } + } + return NULL; +} diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig index 6a02d51086c..00b83db2ce7 100644 --- a/arch/powerpc/platforms/cell/Kconfig +++ b/arch/powerpc/platforms/cell/Kconfig @@ -16,4 +16,8 @@ config SPUFS_MMAP select MEMORY_HOTPLUG default y +config CBE_RAS + bool "RAS features for bare metal Cell BE" + default y + endmenu diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile index e570bad0639..6b11f6adca0 100644 --- a/arch/powerpc/platforms/cell/Makefile +++ b/arch/powerpc/platforms/cell/Makefile @@ -1,5 +1,6 @@ obj-y += interrupt.o iommu.o setup.o spider-pic.o -obj-y += pervasive.o +obj-y += cbe_regs.o pervasive.o +obj-$(CONFIG_CBE_RAS) += ras.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_SPU_FS) += spu-base.o spufs/ diff --git a/arch/powerpc/platforms/cell/cbe_regs.c b/arch/powerpc/platforms/cell/cbe_regs.c new file mode 100644 index 00000000000..2dfde61c841 --- /dev/null +++ b/arch/powerpc/platforms/cell/cbe_regs.c @@ -0,0 +1,128 @@ +/* + * cbe_regs.c + * + * Accessor routines for the various MMIO register blocks of the CBE + * + * (c) 2006 Benjamin Herrenschmidt , IBM Corp. + */ + + +#include +#include +#include + +#include +#include +#include +#include + +#include "cbe_regs.h" + +#define MAX_CBE 2 + +/* + * Current implementation uses "cpu" nodes. We build our own mapping + * array of cpu numbers to cpu nodes locally for now to allow interrupt + * time code to have a fast path rather than call of_get_cpu_node(). If + * we implement cpu hotplug, we'll have to install an appropriate norifier + * in order to release references to the cpu going away + */ +static struct cbe_regs_map +{ + struct device_node *cpu_node; + struct cbe_pmd_regs __iomem *pmd_regs; + struct cbe_iic_regs __iomem *iic_regs; +} cbe_regs_maps[MAX_CBE]; +static int cbe_regs_map_count; + +static struct cbe_thread_map +{ + struct device_node *cpu_node; + struct cbe_regs_map *regs; +} cbe_thread_map[NR_CPUS]; + +static struct cbe_regs_map *cbe_find_map(struct device_node *np) +{ + int i; + + for (i = 0; i < cbe_regs_map_count; i++) + if (cbe_regs_maps[i].cpu_node == np) + return &cbe_regs_maps[i]; + return NULL; +} + +struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np) +{ + struct cbe_regs_map *map = cbe_find_map(np); + if (map == NULL) + return NULL; + return map->pmd_regs; +} + +struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu) +{ + struct cbe_regs_map *map = cbe_thread_map[cpu].regs; + if (map == NULL) + return NULL; + return map->pmd_regs; +} + + +struct cbe_iic_regs __iomem *cbe_get_iic_regs(struct device_node *np) +{ + struct cbe_regs_map *map = cbe_find_map(np); + if (map == NULL) + return NULL; + return map->iic_regs; +} +struct cbe_iic_regs __iomem *cbe_get_cpu_iic_regs(int cpu) +{ + struct cbe_regs_map *map = cbe_thread_map[cpu].regs; + if (map == NULL) + return NULL; + return map->iic_regs; +} + +void __init cbe_regs_init(void) +{ + int i; + struct device_node *cpu; + + /* Build local fast map of CPUs */ + for_each_cpu(i) + cbe_thread_map[i].cpu_node = of_get_cpu_node(i, NULL); + + /* Find maps for each device tree CPU */ + for_each_node_by_type(cpu, "cpu") { + struct cbe_regs_map *map = &cbe_regs_maps[cbe_regs_map_count++]; + + /* That hack must die die die ! */ + struct address_prop { + unsigned long address; + unsigned int len; + } __attribute__((packed)) *prop; + + + if (cbe_regs_map_count > MAX_CBE) { + printk(KERN_ERR "cbe_regs: More BE chips than supported" + "!\n"); + cbe_regs_map_count--; + return; + } + map->cpu_node = cpu; + for_each_cpu(i) + if (cbe_thread_map[i].cpu_node == cpu) + cbe_thread_map[i].regs = map; + + prop = (struct address_prop *)get_property(cpu, "pervasive", + NULL); + if (prop != NULL) + map->pmd_regs = ioremap(prop->address, prop->len); + + prop = (struct address_prop *)get_property(cpu, "iic", + NULL); + if (prop != NULL) + map->iic_regs = ioremap(prop->address, prop->len); + } +} + diff --git a/arch/powerpc/platforms/cell/cbe_regs.h b/arch/powerpc/platforms/cell/cbe_regs.h new file mode 100644 index 00000000000..e76e4a6af5b --- /dev/null +++ b/arch/powerpc/platforms/cell/cbe_regs.h @@ -0,0 +1,129 @@ +/* + * cbe_regs.h + * + * This file is intended to hold the various register definitions for CBE + * on-chip system devices (memory controller, IO controller, etc...) + * + * (c) 2006 Benjamin Herrenschmidt , IBM Corp. + */ + +#ifndef CBE_REGS_H +#define CBE_REGS_H + +/* + * + * Some HID register definitions + * + */ + +/* CBE specific HID0 bits */ +#define HID0_CBE_THERM_WAKEUP 0x0000020000000000ul +#define HID0_CBE_SYSERR_WAKEUP 0x0000008000000000ul +#define HID0_CBE_THERM_INT_EN 0x0000000400000000ul +#define HID0_CBE_SYSERR_INT_EN 0x0000000200000000ul + + +/* + * + * Pervasive unit register definitions + * + */ + +struct cbe_pmd_regs { + u8 pad_0x0000_0x0800[0x0800 - 0x0000]; /* 0x0000 */ + + /* Thermal Sensor Registers */ + u64 ts_ctsr1; /* 0x0800 */ + u64 ts_ctsr2; /* 0x0808 */ + u64 ts_mtsr1; /* 0x0810 */ + u64 ts_mtsr2; /* 0x0818 */ + u64 ts_itr1; /* 0x0820 */ + u64 ts_itr2; /* 0x0828 */ + u64 ts_gitr; /* 0x0830 */ + u64 ts_isr; /* 0x0838 */ + u64 ts_imr; /* 0x0840 */ + u64 tm_cr1; /* 0x0848 */ + u64 tm_cr2; /* 0x0850 */ + u64 tm_simr; /* 0x0858 */ + u64 tm_tpr; /* 0x0860 */ + u64 tm_str1; /* 0x0868 */ + u64 tm_str2; /* 0x0870 */ + u64 tm_tsr; /* 0x0878 */ + + /* Power Management */ + u64 pm_control; /* 0x0880 */ +#define CBE_PMD_PAUSE_ZERO_CONTROL 0x10000 + u64 pm_status; /* 0x0888 */ + + /* Time Base Register */ + u64 tbr; /* 0x0890 */ + + u8 pad_0x0898_0x0c00 [0x0c00 - 0x0898]; /* 0x0898 */ + + /* Fault Isolation Registers */ + u64 checkstop_fir; /* 0x0c00 */ + u64 recoverable_fir; + u64 spec_att_mchk_fir; + u64 fir_mode_reg; + u64 fir_enable_mask; + + u8 pad_0x0c28_0x1000 [0x1000 - 0x0c28]; /* 0x0c28 */ +}; + +extern struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np); +extern struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu); + +/* + * + * IIC unit register definitions + * + */ + +struct cbe_iic_pending_bits { + u32 data; + u8 flags; + u8 class; + u8 source; + u8 prio; +}; + +#define CBE_IIC_IRQ_VALID 0x80 +#define CBE_IIC_IRQ_IPI 0x40 + +struct cbe_iic_thread_regs { + struct cbe_iic_pending_bits pending; + struct cbe_iic_pending_bits pending_destr; + u64 generate; + u64 prio; +}; + +struct cbe_iic_regs { + u8 pad_0x0000_0x0400[0x0400 - 0x0000]; /* 0x0000 */ + + /* IIC interrupt registers */ + struct cbe_iic_thread_regs thread[2]; /* 0x0400 */ + u64 iic_ir; /* 0x0440 */ + u64 iic_is; /* 0x0448 */ + + u8 pad_0x0450_0x0500[0x0500 - 0x0450]; /* 0x0450 */ + + /* IOC FIR */ + u64 ioc_fir_reset; /* 0x0500 */ + u64 ioc_fir_set; + u64 ioc_checkstop_enable; + u64 ioc_fir_error_mask; + u64 ioc_syserr_enable; + u64 ioc_fir; + + u8 pad_0x0530_0x1000[0x1000 - 0x0530]; /* 0x0530 */ +}; + +extern struct cbe_iic_regs __iomem *cbe_get_iic_regs(struct device_node *np); +extern struct cbe_iic_regs __iomem *cbe_get_cpu_iic_regs(int cpu); + + +/* Init this module early */ +extern void cbe_regs_init(void); + + +#endif /* CBE_REGS_H */ diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c index 978be1c30c1..0a707bcabef 100644 --- a/arch/powerpc/platforms/cell/interrupt.c +++ b/arch/powerpc/platforms/cell/interrupt.c @@ -33,29 +33,10 @@ #include #include "interrupt.h" - -struct iic_pending_bits { - u32 data; - u8 flags; - u8 class; - u8 source; - u8 prio; -}; - -enum iic_pending_flags { - IIC_VALID = 0x80, - IIC_IPI = 0x40, -}; - -struct iic_regs { - struct iic_pending_bits pending; - struct iic_pending_bits pending_destr; - u64 generate; - u64 prio; -}; +#include "cbe_regs.h" struct iic { - struct iic_regs __iomem *regs; + struct cbe_iic_thread_regs __iomem *regs; u8 target_id; }; @@ -115,7 +96,7 @@ static struct hw_interrupt_type iic_pic = { .end = iic_end, }; -static int iic_external_get_irq(struct iic_pending_bits pending) +static int iic_external_get_irq(struct cbe_iic_pending_bits pending) { int irq; unsigned char node, unit; @@ -168,15 +149,15 @@ int iic_get_irq(struct pt_regs *regs) { struct iic *iic; int irq; - struct iic_pending_bits pending; + struct cbe_iic_pending_bits pending; iic = &__get_cpu_var(iic); *(unsigned long *) &pending = in_be64((unsigned long __iomem *) &iic->regs->pending_destr); irq = -1; - if (pending.flags & IIC_VALID) { - if (pending.flags & IIC_IPI) { + if (pending.flags & CBE_IIC_IRQ_VALID) { + if (pending.flags & CBE_IIC_IRQ_IPI) { irq = IIC_IPI_OFFSET + (pending.prio >> 4); /* if (irq > 0x80) @@ -226,7 +207,7 @@ static int setup_iic_hardcoded(void) regs += 0x20; printk(KERN_INFO "IIC for CPU %d at %lx\n", cpu, regs); - iic->regs = ioremap(regs, sizeof(struct iic_regs)); + iic->regs = ioremap(regs, sizeof(struct cbe_iic_thread_regs)); iic->target_id = (nodeid << 4) + ((cpu & 1) ? 0xf : 0xe); } @@ -267,12 +248,12 @@ static int setup_iic(void) } iic = &per_cpu(iic, np[0]); - iic->regs = ioremap(regs[0], sizeof(struct iic_regs)); + iic->regs = ioremap(regs[0], sizeof(struct cbe_iic_thread_regs)); iic->target_id = ((np[0] & 2) << 3) + ((np[0] & 1) ? 0xf : 0xe); printk("IIC for CPU %d at %lx mapped to %p\n", np[0], regs[0], iic->regs); iic = &per_cpu(iic, np[1]); - iic->regs = ioremap(regs[2], sizeof(struct iic_regs)); + iic->regs = ioremap(regs[2], sizeof(struct cbe_iic_thread_regs)); iic->target_id = ((np[1] & 2) << 3) + ((np[1] & 1) ? 0xf : 0xe); printk("IIC for CPU %d at %lx mapped to %p\n", np[1], regs[2], iic->regs); diff --git a/arch/powerpc/platforms/cell/pervasive.c b/arch/powerpc/platforms/cell/pervasive.c index 7eed8c62451..695ac4e1617 100644 --- a/arch/powerpc/platforms/cell/pervasive.c +++ b/arch/powerpc/platforms/cell/pervasive.c @@ -37,36 +37,28 @@ #include #include "pervasive.h" +#include "cbe_regs.h" static DEFINE_SPINLOCK(cbe_pervasive_lock); -struct cbe_pervasive { - struct pmd_regs __iomem *regs; - unsigned int thread; -}; - -/* can't use per_cpu from setup_arch */ -static struct cbe_pervasive cbe_pervasive[NR_CPUS]; static void __init cbe_enable_pause_zero(void) { unsigned long thread_switch_control; unsigned long temp_register; - struct cbe_pervasive *p; - int thread; + struct cbe_pmd_regs __iomem *pregs; spin_lock_irq(&cbe_pervasive_lock); - p = &cbe_pervasive[smp_processor_id()]; - - if (!cbe_pervasive->regs) + pregs = cbe_get_cpu_pmd_regs(smp_processor_id()); + if (pregs == NULL) goto out; pr_debug("Power Management: CPU %d\n", smp_processor_id()); /* Enable Pause(0) control bit */ - temp_register = in_be64(&p->regs->pm_control); + temp_register = in_be64(&pregs->pm_control); - out_be64(&p->regs->pm_control, - temp_register|PMD_PAUSE_ZERO_CONTROL); + out_be64(&pregs->pm_control, + temp_register | CBE_PMD_PAUSE_ZERO_CONTROL); /* Enable DEC and EE interrupt request */ thread_switch_control = mfspr(SPRN_TSC_CELL); @@ -75,25 +67,16 @@ static void __init cbe_enable_pause_zero(void) switch ((mfspr(SPRN_CTRLF) & CTRL_CT)) { case CTRL_CT0: thread_switch_control |= TSC_CELL_DEC_ENABLE_0; - thread = 0; break; case CTRL_CT1: thread_switch_control |= TSC_CELL_DEC_ENABLE_1; - thread = 1; break; default: printk(KERN_WARNING "%s: unknown configuration\n", __FUNCTION__); - thread = -1; break; } - if (p->thread != thread) - printk(KERN_WARNING "%s: device tree inconsistant, " - "cpu %i: %d/%d\n", __FUNCTION__, - smp_processor_id(), - p->thread, thread); - mtspr(SPRN_TSC_CELL, thread_switch_control); out: @@ -104,6 +87,11 @@ static void cbe_idle(void) { unsigned long ctrl; + /* Why do we do that on every idle ? Couldn't that be done once for + * all or do we lose the state some way ? Also, the pm_control + * register setting, that can't be set once at boot ? We really want + * to move that away in order to implement a simple powersave + */ cbe_enable_pause_zero(); while (1) { @@ -152,8 +140,15 @@ static int cbe_system_reset_exception(struct pt_regs *regs) timer_interrupt(regs); break; case SRR1_WAKEMT: - /* no action required */ break; +#ifdef CONFIG_CBE_RAS + case SRR1_WAKESYSERR: + cbe_system_error_exception(regs); + break; + case SRR1_WAKETHERM: + cbe_thermal_exception(regs); + break; +#endif /* CONFIG_CBE_RAS */ default: /* do system reset */ return 0; @@ -162,68 +157,11 @@ static int cbe_system_reset_exception(struct pt_regs *regs) return 1; } -static int __init cbe_find_pmd_mmio(int cpu, struct cbe_pervasive *p) -{ - struct device_node *node; - unsigned int *int_servers; - char *addr; - unsigned long real_address; - unsigned int size; - - struct pmd_regs __iomem *pmd_mmio_area; - int hardid, thread; - int proplen; - - pmd_mmio_area = NULL; - hardid = get_hard_smp_processor_id(cpu); - for (node = NULL; (node = of_find_node_by_type(node, "cpu"));) { - int_servers = (void *) get_property(node, - "ibm,ppc-interrupt-server#s", &proplen); - if (!int_servers) { - printk(KERN_WARNING "%s misses " - "ibm,ppc-interrupt-server#s property", - node->full_name); - continue; - } - for (thread = 0; thread < proplen / sizeof (int); thread++) { - if (hardid == int_servers[thread]) { - addr = get_property(node, "pervasive", NULL); - goto found; - } - } - } - - printk(KERN_WARNING "%s: CPU %d not found\n", __FUNCTION__, cpu); - return -EINVAL; - -found: - real_address = *(unsigned long*) addr; - addr += sizeof (unsigned long); - size = *(unsigned int*) addr; - - pr_debug("pervasive area for CPU %d at %lx, size %x\n", - cpu, real_address, size); - p->regs = ioremap(real_address, size); - p->thread = thread; - return 0; -} - -void __init cell_pervasive_init(void) +void __init cbe_pervasive_init(void) { - struct cbe_pervasive *p; - int cpu; - int ret; - if (!cpu_has_feature(CPU_FTR_PAUSE_ZERO)) return; - for_each_possible_cpu(cpu) { - p = &cbe_pervasive[cpu]; - ret = cbe_find_pmd_mmio(cpu, p); - if (ret) - return; - } - ppc_md.idle_loop = cbe_idle; ppc_md.system_reset_exception = cbe_system_reset_exception; } diff --git a/arch/powerpc/platforms/cell/pervasive.h b/arch/powerpc/platforms/cell/pervasive.h index da1fb85ca3e..7b50947f804 100644 --- a/arch/powerpc/platforms/cell/pervasive.h +++ b/arch/powerpc/platforms/cell/pervasive.h @@ -25,38 +25,9 @@ #ifndef PERVASIVE_H #define PERVASIVE_H -struct pmd_regs { - u8 pad_0x0000_0x0800[0x0800 - 0x0000]; /* 0x0000 */ - - /* Thermal Sensor Registers */ - u64 ts_ctsr1; /* 0x0800 */ - u64 ts_ctsr2; /* 0x0808 */ - u64 ts_mtsr1; /* 0x0810 */ - u64 ts_mtsr2; /* 0x0818 */ - u64 ts_itr1; /* 0x0820 */ - u64 ts_itr2; /* 0x0828 */ - u64 ts_gitr; /* 0x0830 */ - u64 ts_isr; /* 0x0838 */ - u64 ts_imr; /* 0x0840 */ - u64 tm_cr1; /* 0x0848 */ - u64 tm_cr2; /* 0x0850 */ - u64 tm_simr; /* 0x0858 */ - u64 tm_tpr; /* 0x0860 */ - u64 tm_str1; /* 0x0868 */ - u64 tm_str2; /* 0x0870 */ - u64 tm_tsr; /* 0x0878 */ - - /* Power Management */ - u64 pm_control; /* 0x0880 */ -#define PMD_PAUSE_ZERO_CONTROL 0x10000 - u64 pm_status; /* 0x0888 */ - - /* Time Base Register */ - u64 tbr; /* 0x0890 */ - - u8 pad_0x0898_0x1000 [0x1000 - 0x0898]; /* 0x0898 */ -}; - -void __init cell_pervasive_init(void); +extern void cbe_pervasive_init(void); +extern void cbe_system_error_exception(struct pt_regs *regs); +extern void cbe_maintenance_exception(struct pt_regs *regs); +extern void cbe_thermal_exception(struct pt_regs *regs); #endif diff --git a/arch/powerpc/platforms/cell/ras.c b/arch/powerpc/platforms/cell/ras.c new file mode 100644 index 00000000000..033ad6e2827 --- /dev/null +++ b/arch/powerpc/platforms/cell/ras.c @@ -0,0 +1,112 @@ +#define DEBUG + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "ras.h" +#include "cbe_regs.h" + + +static void dump_fir(int cpu) +{ + struct cbe_pmd_regs __iomem *pregs = cbe_get_cpu_pmd_regs(cpu); + struct cbe_iic_regs __iomem *iregs = cbe_get_cpu_iic_regs(cpu); + + if (pregs == NULL) + return; + + /* Todo: do some nicer parsing of bits and based on them go down + * to other sub-units FIRs and not only IIC + */ + printk(KERN_ERR "Global Checkstop FIR : 0x%016lx\n", + in_be64(&pregs->checkstop_fir)); + printk(KERN_ERR "Global Recoverable FIR : 0x%016lx\n", + in_be64(&pregs->checkstop_fir)); + printk(KERN_ERR "Global MachineCheck FIR : 0x%016lx\n", + in_be64(&pregs->spec_att_mchk_fir)); + + if (iregs == NULL) + return; + printk(KERN_ERR "IOC FIR : 0x%016lx\n", + in_be64(&iregs->ioc_fir)); + +} + +void cbe_system_error_exception(struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + + printk(KERN_ERR "System Error Interrupt on CPU %d !\n", cpu); + dump_fir(cpu); + dump_stack(); +} + +void cbe_maintenance_exception(struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + + /* + * Nothing implemented for the maintenance interrupt at this point + */ + + printk(KERN_ERR "Unhandled Maintenance interrupt on CPU %d !\n", cpu); + dump_stack(); +} + +void cbe_thermal_exception(struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + + /* + * Nothing implemented for the thermal interrupt at this point + */ + + printk(KERN_ERR "Unhandled Thermal interrupt on CPU %d !\n", cpu); + dump_stack(); +} + +static int cbe_machine_check_handler(struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + + printk(KERN_ERR "Machine Check Interrupt on CPU %d !\n", cpu); + dump_fir(cpu); + + /* No recovery from this code now, lets continue */ + return 0; +} + +void __init cbe_ras_init(void) +{ + unsigned long hid0; + + /* + * Enable System Error & thermal interrupts and wakeup conditions + */ + + hid0 = mfspr(SPRN_HID0); + hid0 |= HID0_CBE_THERM_INT_EN | HID0_CBE_THERM_WAKEUP | + HID0_CBE_SYSERR_INT_EN | HID0_CBE_SYSERR_WAKEUP; + mtspr(SPRN_HID0, hid0); + mb(); + + /* + * Install machine check handler. Leave setting of precise mode to + * what the firmware did for now + */ + ppc_md.machine_check_exception = cbe_machine_check_handler; + mb(); + + /* + * For now, we assume that IOC_FIR is already set to forward some + * error conditions to the System Error handler. If that is not true + * then it will have to be fixed up here. + */ +} diff --git a/arch/powerpc/platforms/cell/ras.h b/arch/powerpc/platforms/cell/ras.h new file mode 100644 index 00000000000..eb7ee54c82a --- /dev/null +++ b/arch/powerpc/platforms/cell/ras.h @@ -0,0 +1,9 @@ +#ifndef RAS_H +#define RAS_H + +extern void cbe_system_error_exception(struct pt_regs *regs); +extern void cbe_maintenance_exception(struct pt_regs *regs); +extern void cbe_thermal_exception(struct pt_regs *regs); +extern void cbe_ras_init(void); + +#endif /* RAS_H */ diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c index fd3e5609e3e..eb8ab9bbf74 100644 --- a/arch/powerpc/platforms/cell/setup.c +++ b/arch/powerpc/platforms/cell/setup.c @@ -52,7 +52,9 @@ #include "interrupt.h" #include "iommu.h" +#include "cbe_regs.h" #include "pervasive.h" +#include "ras.h" #ifdef DEBUG #define DBG(fmt...) udbg_printf(fmt) @@ -82,6 +84,12 @@ static void __init cell_setup_arch(void) ppc_md.init_IRQ = iic_init_IRQ; ppc_md.get_irq = iic_get_irq; + cbe_regs_init(); + +#ifdef CONFIG_CBE_RAS + cbe_ras_init(); +#endif + #ifdef CONFIG_SMP smp_init_cell(); #endif @@ -98,7 +106,7 @@ static void __init cell_setup_arch(void) init_pci_config_tokens(); find_and_init_phbs(); spider_init_IRQ(); - cell_pervasive_init(); + cbe_pervasive_init(); #ifdef CONFIG_DUMMY_CONSOLE conswitchp = &dummy_con; #endif diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h index c79d58ab744..8bdcd517830 100644 --- a/include/asm-powerpc/prom.h +++ b/include/asm-powerpc/prom.h @@ -238,5 +238,8 @@ void of_parse_dma_window(struct device_node *dn, unsigned char *dma_window_prop, extern void kdump_move_device_tree(void); +/* CPU OF node matching */ +struct device_node *of_get_cpu_node(int cpu, unsigned int *thread); + #endif /* __KERNEL__ */ #endif /* _POWERPC_PROM_H */ diff --git a/include/asm-powerpc/reg.h b/include/asm-powerpc/reg.h index f2ed7577aa3..cf73475a0c6 100644 --- a/include/asm-powerpc/reg.h +++ b/include/asm-powerpc/reg.h @@ -386,6 +386,8 @@ #define SRR1_WAKEMT 0x00280000 /* mtctrl */ #define SRR1_WAKEDEC 0x00180000 /* Decrementer interrupt */ #define SRR1_WAKETHERM 0x00100000 /* Thermal management interrupt */ +#define SPRN_HSRR0 0x13A /* Save/Restore Register 0 */ +#define SPRN_HSRR1 0x13B /* Save/Restore Register 1 */ #ifndef SPRN_SVR #define SPRN_SVR 0x11E /* System Version Register */ -- cgit v1.2.3 From b40feec8efbe609a3a38bca1f18d3ba4d590563a Mon Sep 17 00:00:00 2001 From: "arnd@arndb.de" Date: Mon, 19 Jun 2006 20:33:17 +0200 Subject: [POWERPC] cell: fix interrupt priority handling Checking the priority field to test for irq validity is completely bogus and breaks with future external interrupt controllers. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/interrupt.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c index 0a707bcabef..f4e2d8805c9 100644 --- a/arch/powerpc/platforms/cell/interrupt.c +++ b/arch/powerpc/platforms/cell/interrupt.c @@ -117,8 +117,7 @@ static int iic_external_get_irq(struct cbe_iic_pending_bits pending) * One of these units can be connected * to an external interrupt controller. */ - if (pending.prio > 0x3f || - pending.class != 2) + if (pending.class != 2) break; irq = IIC_EXT_OFFSET + spider_get_irq(node) -- cgit v1.2.3 From 0f0f90c304b42d8ce7fc5958de894bdcff3a0ca1 Mon Sep 17 00:00:00 2001 From: "arnd@arndb.de" Date: Mon, 19 Jun 2006 20:33:18 +0200 Subject: [POWERPC] cell: update defconfig Enable some of the most requested features in defconfig and refresh with the latest powerpc.git Kconfig files. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/configs/cell_defconfig | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig index 5b8599d03f1..5569befa405 100644 --- a/arch/powerpc/configs/cell_defconfig +++ b/arch/powerpc/configs/cell_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.16 -# Thu Mar 23 20:48:09 2006 +# Linux kernel version: 2.6.17 +# Mon Jun 19 17:23:03 2006 # CONFIG_PPC64=y CONFIG_64BIT=y @@ -11,6 +11,7 @@ CONFIG_GENERIC_HARDIRQS=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_PPC=y CONFIG_EARLY_PRINTK=y CONFIG_COMPAT=y @@ -55,7 +56,7 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y -# CONFIG_CPUSETS is not set +CONFIG_CPUSETS=y # CONFIG_RELAY is not set CONFIG_INITRAMFS_SOURCE="" CONFIG_CC_OPTIMIZE_FOR_SIZE=y @@ -116,6 +117,7 @@ CONFIG_PPC_MULTIPLATFORM=y # CONFIG_PPC_PMAC is not set # CONFIG_PPC_MAPLE is not set CONFIG_PPC_CELL=y +CONFIG_PPC_SYSTEMSIM=y # CONFIG_U3_DART is not set CONFIG_PPC_RTAS=y # CONFIG_RTAS_ERROR_LOGGING is not set @@ -153,20 +155,24 @@ CONFIG_FORCE_MAX_ZONEORDER=13 CONFIG_KEXEC=y # CONFIG_CRASH_DUMP is not set CONFIG_IRQ_ALL_CPUS=y -# CONFIG_NUMA is not set +CONFIG_NUMA=y +CONFIG_NODES_SHIFT=4 CONFIG_ARCH_SELECT_MEMORY_MODEL=y -CONFIG_ARCH_FLATMEM_ENABLE=y CONFIG_ARCH_SPARSEMEM_ENABLE=y CONFIG_SELECT_MEMORY_MODEL=y # CONFIG_FLATMEM_MANUAL is not set # CONFIG_DISCONTIGMEM_MANUAL is not set CONFIG_SPARSEMEM_MANUAL=y CONFIG_SPARSEMEM=y +CONFIG_NEED_MULTIPLE_NODES=y CONFIG_HAVE_MEMORY_PRESENT=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPARSEMEM_EXTREME=y -# CONFIG_MEMORY_HOTPLUG is not set +CONFIG_MEMORY_HOTPLUG=y CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_MIGRATION=y +CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y +CONFIG_ARCH_MEMORY_PROBE=y # CONFIG_PPC_64K_PAGES is not set CONFIG_SCHED_SMT=y CONFIG_PROC_DEVICETREE=y @@ -183,6 +189,7 @@ CONFIG_GENERIC_ISA_DMA=y # CONFIG_PPC_INDIRECT_PCI is not set CONFIG_PCI=y CONFIG_PCI_DOMAINS=y +CONFIG_PCIEPORTBUS=y # CONFIG_PCI_DEBUG is not set # @@ -477,7 +484,7 @@ CONFIG_DM_MULTIPATH=m # CONFIG_NETDEVICES=y # CONFIG_DUMMY is not set -# CONFIG_BONDING is not set +CONFIG_BONDING=y # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set @@ -625,6 +632,7 @@ CONFIG_SERIAL_NONSTANDARD=y # CONFIG_N_HDLC is not set # CONFIG_SPECIALIX is not set # CONFIG_SX is not set +# CONFIG_RIO is not set # CONFIG_STALDRV is not set # @@ -767,6 +775,7 @@ CONFIG_I2C_ALGOBIT=y # Multimedia devices # # CONFIG_VIDEO_DEV is not set +CONFIG_VIDEO_V4L2=y # # Digital Video Broadcasting Devices @@ -1055,11 +1064,7 @@ CONFIG_DEBUGGER=y # CONFIG_XMON is not set CONFIG_IRQSTACKS=y # CONFIG_BOOTX_TEXT is not set -# CONFIG_PPC_EARLY_DEBUG_LPAR is not set -# CONFIG_PPC_EARLY_DEBUG_G5 is not set -# CONFIG_PPC_EARLY_DEBUG_RTAS is not set -# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set -# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set +# CONFIG_PPC_EARLY_DEBUG is not set # # Security options -- cgit v1.2.3 From 1d64093f6627a7eef1ed0fe005463f0a5ea25a5f Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Mon, 19 Jun 2006 20:33:19 +0200 Subject: [POWERPC] cell: register SPUs as sysdevs SPUs are registered as system devices, exposing attributes through sysfs. Since the sysdev includes a kref, we can remove the one in struct spu (it isn't used at the moment anyway). Currently only the interrupt source and numa node attributes are added. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spu_base.c | 54 ++++++++++++++++++++++++++++++++++ include/asm-powerpc/spu.h | 5 ++-- 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index ad141fe8d52..d5877aacc3b 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -649,6 +649,46 @@ out: return ret; } +struct sysdev_class spu_sysdev_class = { + set_kset_name("spu") +}; + +static ssize_t spu_show_isrc(struct sys_device *sysdev, char *buf) +{ + struct spu *spu = container_of(sysdev, struct spu, sysdev); + return sprintf(buf, "%d\n", spu->isrc); + +} +static SYSDEV_ATTR(isrc, 0400, spu_show_isrc, NULL); + +extern int attach_sysdev_to_node(struct sys_device *dev, int nid); + +static int spu_create_sysdev(struct spu *spu) +{ + int ret; + + spu->sysdev.id = spu->number; + spu->sysdev.cls = &spu_sysdev_class; + ret = sysdev_register(&spu->sysdev); + if (ret) { + printk(KERN_ERR "Can't register SPU %d with sysfs\n", + spu->number); + return ret; + } + + sysdev_create_file(&spu->sysdev, &attr_isrc); + sysfs_add_device_to_node(&spu->sysdev, spu->nid); + + return 0; +} + +static void spu_destroy_sysdev(struct spu *spu) +{ + sysdev_remove_file(&spu->sysdev, &attr_isrc); + sysfs_remove_device_from_node(&spu->sysdev, spu->nid); + sysdev_unregister(&spu->sysdev); +} + static int __init create_spu(struct device_node *spe) { struct spu *spu; @@ -695,6 +735,10 @@ static int __init create_spu(struct device_node *spe) if (ret) goto out_unmap; + ret = spu_create_sysdev(spu); + if (ret) + goto out_free_irqs; + list_add(&spu->list, &spu_list); mutex_unlock(&spu_mutex); @@ -703,6 +747,9 @@ static int __init create_spu(struct device_node *spe) spu->problem, spu->priv1, spu->priv2, spu->number); goto out; +out_free_irqs: + spu_free_irqs(spu); + out_unmap: mutex_unlock(&spu_mutex); spu_unmap(spu); @@ -716,6 +763,7 @@ static void destroy_spu(struct spu *spu) { list_del_init(&spu->list); + spu_destroy_sysdev(spu); spu_free_irqs(spu); spu_unmap(spu); kfree(spu); @@ -728,6 +776,7 @@ static void cleanup_spu_base(void) list_for_each_entry_safe(spu, tmp, &spu_list, list) destroy_spu(spu); mutex_unlock(&spu_mutex); + sysdev_class_unregister(&spu_sysdev_class); } module_exit(cleanup_spu_base); @@ -736,6 +785,11 @@ static int __init init_spu_base(void) struct device_node *node; int ret; + /* create sysdev class for spus */ + ret = sysdev_class_register(&spu_sysdev_class); + if (ret) + return ret; + ret = -ENODEV; for (node = of_find_node_by_type(NULL, "spe"); node; node = of_find_node_by_type(node, "spe")) { diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h index 7cfcff3ef02..946489929eb 100644 --- a/include/asm-powerpc/spu.h +++ b/include/asm-powerpc/spu.h @@ -25,8 +25,8 @@ #ifdef __KERNEL__ #include -#include #include +#include #define LS_SIZE (256 * 1024) #define LS_ADDR_MASK (LS_SIZE - 1) @@ -123,7 +123,6 @@ struct spu { u64 flags; u64 dar; u64 dsisr; - struct kref kref; size_t ls_size; unsigned int slb_replace; struct mm_struct *mm; @@ -144,6 +143,8 @@ struct spu { char irq_c0[8]; char irq_c1[8]; char irq_c2[8]; + + struct sys_device sysdev; }; struct spu *spu_alloc(void); -- cgit v1.2.3 From 91edfa49b97f0b0fafac5c8d5f171fc183782ce6 Mon Sep 17 00:00:00 2001 From: "arnd@arndb.de" Date: Mon, 19 Jun 2006 20:33:20 +0200 Subject: [POWERPC] cell: always build spu base into the kernel The spu_base module is rather deeply intermixed with the core kernel, so it makes sense to have that built-in. This will let us extend the base in the future without having to export more core symbols just for it. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/Makefile | 6 +----- arch/powerpc/platforms/cell/spufs/Makefile | 4 +++- arch/powerpc/platforms/cell/spufs/switch.c | 4 ++++ 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile index 6b11f6adca0..bfaf4002463 100644 --- a/arch/powerpc/platforms/cell/Makefile +++ b/arch/powerpc/platforms/cell/Makefile @@ -3,15 +3,11 @@ obj-y += cbe_regs.o pervasive.o obj-$(CONFIG_CBE_RAS) += ras.o obj-$(CONFIG_SMP) += smp.o -obj-$(CONFIG_SPU_FS) += spu-base.o spufs/ - -spu-base-y += spu_base.o spu_priv1.o # needed only when building loadable spufs.ko spufs-modular-$(CONFIG_SPU_FS) += spu_syscalls.o obj-y += $(spufs-modular-m) # always needed in kernel -spufs-builtin-$(CONFIG_SPU_FS) += spu_callbacks.o +spufs-builtin-$(CONFIG_SPU_FS) += spu_callbacks.o spu_base.o spu_priv1.o spufs/ obj-y += $(spufs-builtin-y) $(spufs-builtin-m) - diff --git a/arch/powerpc/platforms/cell/spufs/Makefile b/arch/powerpc/platforms/cell/spufs/Makefile index a7cddf40e3d..7963d520b67 100644 --- a/arch/powerpc/platforms/cell/spufs/Makefile +++ b/arch/powerpc/platforms/cell/spufs/Makefile @@ -1,5 +1,7 @@ +obj-y += switch.o + obj-$(CONFIG_SPU_FS) += spufs.o -spufs-y += inode.o file.o context.o switch.o syscalls.o +spufs-y += inode.o file.o context.o syscalls.o spufs-y += sched.o backing_ops.o hw_ops.o run.o # Rules to build switch.o with the help of SPU tool chain diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c index 1726bfe38ee..60f8b361644 100644 --- a/arch/powerpc/platforms/cell/spufs/switch.c +++ b/arch/powerpc/platforms/cell/spufs/switch.c @@ -2074,6 +2074,7 @@ int spu_save(struct spu_state *prev, struct spu *spu) } return rc; } +EXPORT_SYMBOL_GPL(spu_save); /** * spu_restore - SPU context restore, with harvest and locking. @@ -2103,6 +2104,7 @@ int spu_restore(struct spu_state *new, struct spu *spu) } return rc; } +EXPORT_SYMBOL_GPL(spu_restore); /** * spu_harvest - SPU harvest (reset) operation @@ -2193,6 +2195,7 @@ void spu_init_csa(struct spu_state *csa) init_priv1(csa); init_priv2(csa); } +EXPORT_SYMBOL_GPL(spu_init_csa); void spu_fini_csa(struct spu_state *csa) { @@ -2203,3 +2206,4 @@ void spu_fini_csa(struct spu_state *csa) vfree(csa->lscsa); } +EXPORT_SYMBOL_GPL(spu_fini_csa); -- cgit v1.2.3 From d9379c4bcee7046182edf45eeab349334421416e Mon Sep 17 00:00:00 2001 From: "arnd@arndb.de" Date: Mon, 19 Jun 2006 20:33:21 +0200 Subject: [POWERPC] spufs: restore mapping of mssync register A recent change to the way that the mfc file gets mapped made it impossible to map the SPE Multi-Source Synchronization register into user space, but that may be needed by some applications. This restores the missing functionality. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spufs/file.c | 50 ++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index 366185e9266..3bc00913fe1 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c @@ -824,6 +824,55 @@ static u64 spufs_signal2_type_get(void *data) DEFINE_SIMPLE_ATTRIBUTE(spufs_signal2_type, spufs_signal2_type_get, spufs_signal2_type_set, "%llu"); +#ifdef CONFIG_SPUFS_MMAP +static struct page *spufs_mss_mmap_nopage(struct vm_area_struct *vma, + unsigned long address, int *type) +{ + return spufs_ps_nopage(vma, address, type, 0x0000); +} + +static struct vm_operations_struct spufs_mss_mmap_vmops = { + .nopage = spufs_mss_mmap_nopage, +}; + +/* + * mmap support for problem state MFC DMA area [0x0000 - 0x0fff]. + * Mapping this area requires that the application have CAP_SYS_RAWIO, + * as these registers require special care when read/writing. + */ +static int spufs_mss_mmap(struct file *file, struct vm_area_struct *vma) +{ + if (!(vma->vm_flags & VM_SHARED)) + return -EINVAL; + + if (!capable(CAP_SYS_RAWIO)) + return -EPERM; + + vma->vm_flags |= VM_RESERVED; + vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) + | _PAGE_NO_CACHE); + + vma->vm_ops = &spufs_mss_mmap_vmops; + return 0; +} +#endif + +static int spufs_mss_open(struct inode *inode, struct file *file) +{ + struct spufs_inode_info *i = SPUFS_I(inode); + + file->private_data = i->i_ctx; + return nonseekable_open(inode, file); +} + +static struct file_operations spufs_mss_fops = { + .open = spufs_mss_open, +#ifdef CONFIG_SPUFS_MMAP + .mmap = spufs_mss_mmap, +#endif +}; + + #ifdef CONFIG_SPUFS_MMAP static struct page *spufs_mfc_mmap_nopage(struct vm_area_struct *vma, unsigned long address, int *type) @@ -1292,6 +1341,7 @@ struct tree_descr spufs_dir_contents[] = { { "signal2", &spufs_signal2_fops, 0666, }, { "signal1_type", &spufs_signal1_type, 0666, }, { "signal2_type", &spufs_signal2_type, 0666, }, + { "mss", &spufs_mss_fops, 0666, }, { "mfc", &spufs_mfc_fops, 0666, }, { "cntl", &spufs_cntl_fops, 0666, }, { "npc", &spufs_npc_ops, 0666, }, -- cgit v1.2.3 From 0309f02d8e1b68811e513bdd06015672d0696af5 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Mon, 19 Jun 2006 20:33:22 +0200 Subject: [POWERPC] spufs: fix deadlock in spu_create error path spufs_rmdir tries to acquire the spufs root i_mutex, which is already held by spufs_create_thread. This was tracked as Bug #H9512. Signed-off-by: Michael Ellerman Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spufs/inode.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index d9554199afa..fed511a2b17 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c @@ -157,20 +157,12 @@ static void spufs_prune_dir(struct dentry *dir) mutex_unlock(&dir->d_inode->i_mutex); } +/* Caller must hold root->i_mutex */ static int spufs_rmdir(struct inode *root, struct dentry *dir_dentry) { - struct spu_context *ctx; - /* remove all entries */ - mutex_lock(&root->i_mutex); spufs_prune_dir(dir_dentry); - mutex_unlock(&root->i_mutex); - /* We have to give up the mm_struct */ - ctx = SPUFS_I(dir_dentry->d_inode)->i_ctx; - spu_forget(ctx); - - /* XXX Do we need to hold i_mutex here ? */ return simple_rmdir(root, dir_dentry); } @@ -199,16 +191,23 @@ out: static int spufs_dir_close(struct inode *inode, struct file *file) { + struct spu_context *ctx; struct inode *dir; struct dentry *dentry; int ret; dentry = file->f_dentry; dir = dentry->d_parent->d_inode; + ctx = SPUFS_I(dentry->d_inode)->i_ctx; + mutex_lock(&dir->i_mutex); ret = spufs_rmdir(dir, dentry); + mutex_unlock(&dir->i_mutex); WARN_ON(ret); + /* We have to give up the mm_struct */ + spu_forget(ctx); + return dcache_dir_close(inode, file); } @@ -324,8 +323,13 @@ long spufs_create_thread(struct nameidata *nd, * in error path of *_open(). */ ret = spufs_context_open(dget(dentry), mntget(nd->mnt)); - if (ret < 0) - spufs_rmdir(nd->dentry->d_inode, dentry); + if (ret < 0) { + WARN_ON(spufs_rmdir(nd->dentry->d_inode, dentry)); + mutex_unlock(&nd->dentry->d_inode->i_mutex); + spu_forget(SPUFS_I(dentry->d_inode)->i_ctx); + dput(dentry); + goto out; + } out_dput: dput(dentry); -- cgit v1.2.3 From 724bd80e8102ac137868b23fad2b06af65f8e168 Mon Sep 17 00:00:00 2001 From: "arnd@arndb.de" Date: Mon, 19 Jun 2006 20:33:23 +0200 Subject: [POWERPC] spufs: set up correct SLB entries for 64k pages spufs currently knows only 4k pages and 16M hugetlb pages. Make it use the regular methods for deciding on the SLB bits. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spu_base.c | 11 ++++++++--- arch/powerpc/platforms/cell/spufs/switch.c | 14 ++++++++------ 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index d5877aacc3b..fd6ea571dbd 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -71,7 +71,7 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea) { struct spu_priv2 __iomem *priv2 = spu->priv2; struct mm_struct *mm = spu->mm; - u64 esid, vsid; + u64 esid, vsid, llp; pr_debug("%s\n", __FUNCTION__); @@ -91,9 +91,14 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea) } esid = (ea & ESID_MASK) | SLB_ESID_V; - vsid = (get_vsid(mm->context.id, ea) << SLB_VSID_SHIFT) | SLB_VSID_USER; +#ifdef CONFIG_HUGETLB_PAGE if (in_hugepage_area(mm->context, ea)) - vsid |= SLB_VSID_L; + llp = mmu_psize_defs[mmu_huge_psize].sllp; + else +#endif + llp = mmu_psize_defs[mmu_virtual_psize].sllp; + vsid = (get_vsid(mm->context.id, ea) << SLB_VSID_SHIFT) | + SLB_VSID_USER | llp; out_be64(&priv2->slb_index_W, spu->slb_replace); out_be64(&priv2->slb_vsid_RW, vsid); diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c index 60f8b361644..97a0e80c7df 100644 --- a/arch/powerpc/platforms/cell/spufs/switch.c +++ b/arch/powerpc/platforms/cell/spufs/switch.c @@ -718,13 +718,15 @@ static inline void invalidate_slbs(struct spu_state *csa, struct spu *spu) static inline void get_kernel_slb(u64 ea, u64 slb[2]) { - slb[0] = (get_kernel_vsid(ea) << SLB_VSID_SHIFT) | SLB_VSID_KERNEL; + u64 llp; + + if (REGION_ID(ea) == KERNEL_REGION_ID) + llp = mmu_psize_defs[mmu_linear_psize].sllp; + else + llp = mmu_psize_defs[mmu_virtual_psize].sllp; + slb[0] = (get_kernel_vsid(ea) << SLB_VSID_SHIFT) | + SLB_VSID_KERNEL | llp; slb[1] = (ea & ESID_MASK) | SLB_ESID_V; - - /* Large pages are used for kernel text/data, but not vmalloc. */ - if (cpu_has_feature(CPU_FTR_16M_PAGE) - && REGION_ID(ea) == KERNEL_REGION_ID) - slb[0] |= SLB_VSID_L; } static inline void load_mfc_slb(struct spu *spu, u64 slb[2], int slbe) -- cgit v1.2.3 From 7b1a701480fb17b7f78b95b257bfc90a4f949d04 Mon Sep 17 00:00:00 2001 From: "arnd@arndb.de" Date: Mon, 19 Jun 2006 20:33:24 +0200 Subject: [POWERPC] spufs: add a phys-id attribute to each SPU context For performance analysis, it is often interesting to know which physical SPE a thread is currently running on, and, more importantly, if it is running at all. This patch adds a simple attribute to each SPU directory with that information. The attribute is read-only and called 'phys-id'. It contains an ascii string with the number of the physical SPU (e.g. "0x5"), or alternatively the string "0xffffffff" (32 bit -1) when it is not running at all at the time that the file is read. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spufs/file.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index 3bc00913fe1..80c02660e61 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c @@ -1328,6 +1328,22 @@ static u64 spufs_srr0_get(void *data) DEFINE_SIMPLE_ATTRIBUTE(spufs_srr0_ops, spufs_srr0_get, spufs_srr0_set, "%llx\n") +static u64 spufs_id_get(void *data) +{ + struct spu_context *ctx = data; + u64 num; + + spu_acquire(ctx); + if (ctx->state == SPU_STATE_RUNNABLE) + num = ctx->spu->number; + else + num = (unsigned int)-1; + spu_release(ctx); + + return num; +} +DEFINE_SIMPLE_ATTRIBUTE(spufs_id_ops, spufs_id_get, 0, "0x%llx\n") + struct tree_descr spufs_dir_contents[] = { { "mem", &spufs_mem_fops, 0666, }, { "regs", &spufs_regs_fops, 0666, }, @@ -1351,5 +1367,6 @@ struct tree_descr spufs_dir_contents[] = { { "spu_tag_mask", &spufs_spu_tag_mask_ops, 0666, }, { "event_mask", &spufs_event_mask_ops, 0666, }, { "srr0", &spufs_srr0_ops, 0666, }, + { "phys-id", &spufs_id_ops, 0666, }, {}, }; -- cgit v1.2.3 From 970f1baae78ff99b7536464214d4c78dde4551e2 Mon Sep 17 00:00:00 2001 From: "arnd@arndb.de" Date: Mon, 19 Jun 2006 20:33:25 +0200 Subject: [POWERPC] spufs: fix initial state of wbox file The wbox channel count of an spu is now initialized to four for the saved context. This makes it possible to write to the mailbox right away without waiting for the SPE to become scheduled first. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spufs/switch.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c index 97a0e80c7df..4210ec2cb4c 100644 --- a/arch/powerpc/platforms/cell/spufs/switch.c +++ b/arch/powerpc/platforms/cell/spufs/switch.c @@ -2129,6 +2129,7 @@ static void init_prob(struct spu_state *csa) csa->spu_chnlcnt_RW[28] = 1; csa->spu_chnlcnt_RW[30] = 1; csa->prob.spu_runcntl_RW = SPU_RUNCNTL_STOP; + csa->prob.mb_stat_R = 0x000400; } static void init_priv1(struct spu_state *csa) -- cgit v1.2.3 From ecec21770d87a5035cfd210cfdb22e1935b0c4a6 Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Mon, 19 Jun 2006 20:33:26 +0200 Subject: [POWERPC] spufs: use kzalloc in create_spu Clean up create_spu() a little by using kzalloc instead of kmalloc + assignments. Signed-off-by: Jeremy Kerr Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spu_base.c | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index fd6ea571dbd..eb367dd89a7 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -701,7 +701,7 @@ static int __init create_spu(struct device_node *spe) static int number; ret = -ENOMEM; - spu = kmalloc(sizeof (*spu), GFP_KERNEL); + spu = kzalloc(sizeof (*spu), GFP_KERNEL); if (!spu) goto out; @@ -713,28 +713,11 @@ static int __init create_spu(struct device_node *spe) spu->nid = of_node_to_nid(spe); if (spu->nid == -1) spu->nid = 0; - - spu->stop_code = 0; - spu->slb_replace = 0; - spu->mm = NULL; - spu->ctx = NULL; - spu->rq = NULL; - spu->pid = 0; - spu->class_0_pending = 0; - spu->flags = 0UL; - spu->dar = 0UL; - spu->dsisr = 0UL; spin_lock_init(&spu->register_lock); - spu_mfc_sdr_set(spu, mfspr(SPRN_SDR1)); spu_mfc_sr1_set(spu, 0x33); - - spu->ibox_callback = NULL; - spu->wbox_callback = NULL; - spu->stop_callback = NULL; - spu->mfc_callback = NULL; - mutex_lock(&spu_mutex); + spu->number = number++; ret = spu_request_irqs(spu); if (ret) -- cgit v1.2.3 From e46a0237fda640f02bc4cb3d9702b6ee91bfd6e4 Mon Sep 17 00:00:00 2001 From: "arnd@arndb.de" Date: Mon, 19 Jun 2006 20:33:27 +0200 Subject: [POWERPC] spufs: dont try to access SPE channel 1 count The save/restore sequence for SPE contexts currently attempts to save and restore the channel count for SPE channel 1 (the SPU_WriteEventMask channel. But the CBE architecture (section 9.11.2) clearly states that this channel does not have an associated count. Hardware simply ignores the attempt to write this count, but the simulator generates a warning message. WARNING: 279721590: SPE7: Attempt to write channel count for CH 1 with no associated count is ignored. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spufs/switch.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c index 4210ec2cb4c..85bea06e798 100644 --- a/arch/powerpc/platforms/cell/spufs/switch.c +++ b/arch/powerpc/platforms/cell/spufs/switch.c @@ -622,12 +622,17 @@ static inline void save_ppuint_mb(struct spu_state *csa, struct spu *spu) static inline void save_ch_part1(struct spu_state *csa, struct spu *spu) { struct spu_priv2 __iomem *priv2 = spu->priv2; - u64 idx, ch_indices[7] = { 0UL, 1UL, 3UL, 4UL, 24UL, 25UL, 27UL }; + u64 idx, ch_indices[7] = { 0UL, 3UL, 4UL, 24UL, 25UL, 27UL }; int i; /* Save, Step 42: - * Save the following CH: [0,1,3,4,24,25,27] */ + + /* Save CH 1, without channel count */ + out_be64(&priv2->spu_chnlcntptr_RW, 1); + csa->spu_chnldata_RW[1] = in_be64(&priv2->spu_chnldata_RW); + + /* Save the following CH: [0,3,4,24,25,27] */ for (i = 0; i < 7; i++) { idx = ch_indices[i]; out_be64(&priv2->spu_chnlcntptr_RW, idx); @@ -1105,13 +1110,18 @@ static inline void clear_spu_status(struct spu_state *csa, struct spu *spu) static inline void reset_ch_part1(struct spu_state *csa, struct spu *spu) { struct spu_priv2 __iomem *priv2 = spu->priv2; - u64 ch_indices[7] = { 0UL, 1UL, 3UL, 4UL, 24UL, 25UL, 27UL }; + u64 ch_indices[7] = { 0UL, 3UL, 4UL, 24UL, 25UL, 27UL }; u64 idx; int i; /* Restore, Step 20: - * Reset the following CH: [0,1,3,4,24,25,27] */ + + /* Reset CH 1 */ + out_be64(&priv2->spu_chnlcntptr_RW, 1); + out_be64(&priv2->spu_chnldata_RW, 0UL); + + /* Reset the following CH: [0,3,4,24,25,27] */ for (i = 0; i < 7; i++) { idx = ch_indices[i]; out_be64(&priv2->spu_chnlcntptr_RW, idx); @@ -1572,12 +1582,17 @@ static inline void restore_decr_wrapped(struct spu_state *csa, struct spu *spu) static inline void restore_ch_part1(struct spu_state *csa, struct spu *spu) { struct spu_priv2 __iomem *priv2 = spu->priv2; - u64 idx, ch_indices[7] = { 0UL, 1UL, 3UL, 4UL, 24UL, 25UL, 27UL }; + u64 idx, ch_indices[7] = { 0UL, 3UL, 4UL, 24UL, 25UL, 27UL }; int i; /* Restore, Step 59: - * Restore the following CH: [0,1,3,4,24,25,27] */ + + /* Restore CH 1 without count */ + out_be64(&priv2->spu_chnlcntptr_RW, 1); + out_be64(&priv2->spu_chnldata_RW, csa->spu_chnldata_RW[1]); + + /* Restore the following CH: [0,3,4,24,25,27] */ for (i = 0; i < 7; i++) { idx = ch_indices[i]; out_be64(&priv2->spu_chnlcntptr_RW, idx); -- cgit v1.2.3 From c01ea72a3b8abb7baa4291a1876b82599867035a Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Mon, 19 Jun 2006 20:33:28 +0200 Subject: [POWERPC] spufs: split the Cell BE support into generic and platform dependant parts Creates new config variables PPC_CELL_NATIVE and PPC_IBM_CELL_BLADE. The existing CONFIG_PPC_CELL is now used to denote the generic Cell processor support. PPC_CELL = make descends into platforms/cell PPC_CELL_NATIVE = add bare metal support PPC_IBM_CELL_BLADE = add blade device drivers, etc. Also renames spu_priv1.c to spu_priv1_mmio.c. Signed-off-by: Geoff Levand Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/Kconfig | 17 ++-- arch/powerpc/configs/cell_defconfig | 4 +- arch/powerpc/platforms/cell/Kconfig | 5 + arch/powerpc/platforms/cell/Makefile | 20 ++-- arch/powerpc/platforms/cell/spu_priv1.c | 133 --------------------------- arch/powerpc/platforms/cell/spu_priv1_mmio.c | 133 +++++++++++++++++++++++++++ drivers/net/Kconfig | 2 +- 7 files changed, 164 insertions(+), 150 deletions(-) delete mode 100644 arch/powerpc/platforms/cell/spu_priv1.c create mode 100644 arch/powerpc/platforms/cell/spu_priv1_mmio.c diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 65f4cd181bd..7b829c754d0 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -404,8 +404,18 @@ config PPC_MAPLE For more informations, refer to config PPC_CELL - bool "Cell Broadband Processor Architecture" + bool + default n + +config PPC_CELL_NATIVE + bool + select PPC_CELL + default n + +config PPC_IBM_CELL_BLADE + bool " IBM Cell Blade" depends on PPC_MULTIPLATFORM && PPC64 + select PPC_CELL_NATIVE select PPC_RTAS select MMIO_NVRAM select PPC_UDBG_16550 @@ -452,11 +462,6 @@ config MPIC_BROKEN_U3 depends on PPC_MAPLE default y -config CELL_IIC - depends on PPC_CELL - bool - default y - config IBMVIO depends on PPC_PSERIES || PPC_ISERIES bool diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig index 5569befa405..b8b8d4675dc 100644 --- a/arch/powerpc/configs/cell_defconfig +++ b/arch/powerpc/configs/cell_defconfig @@ -117,6 +117,8 @@ CONFIG_PPC_MULTIPLATFORM=y # CONFIG_PPC_PMAC is not set # CONFIG_PPC_MAPLE is not set CONFIG_PPC_CELL=y +CONFIG_PPC_CELL_NATIVE=y +CONFIG_PPC_IBM_CELL_BLADE=y CONFIG_PPC_SYSTEMSIM=y # CONFIG_U3_DART is not set CONFIG_PPC_RTAS=y @@ -124,7 +126,6 @@ CONFIG_PPC_RTAS=y CONFIG_RTAS_PROC=y CONFIG_RTAS_FLASH=y CONFIG_MMIO_NVRAM=y -CONFIG_CELL_IIC=y # CONFIG_PPC_MPC106 is not set # CONFIG_PPC_970_NAP is not set # CONFIG_CPU_FREQ is not set @@ -134,6 +135,7 @@ CONFIG_CELL_IIC=y # Cell Broadband Engine options # CONFIG_SPU_FS=m +CONFIG_SPU_BASE=y CONFIG_SPUFS_MMAP=y CONFIG_CBE_RAS=y diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig index 00b83db2ce7..352bbbacde9 100644 --- a/arch/powerpc/platforms/cell/Kconfig +++ b/arch/powerpc/platforms/cell/Kconfig @@ -5,11 +5,16 @@ config SPU_FS tristate "SPU file system" default m depends on PPC_CELL + select SPU_BASE help The SPU file system is used to access Synergistic Processing Units on machines implementing the Broadband Processor Architecture. +config SPU_BASE + bool + default n + config SPUFS_MMAP bool depends on SPU_FS && SPARSEMEM diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile index bfaf4002463..c89cdd67383 100644 --- a/arch/powerpc/platforms/cell/Makefile +++ b/arch/powerpc/platforms/cell/Makefile @@ -1,13 +1,15 @@ -obj-y += interrupt.o iommu.o setup.o spider-pic.o -obj-y += cbe_regs.o pervasive.o -obj-$(CONFIG_CBE_RAS) += ras.o +obj-$(CONFIG_PPC_CELL_NATIVE) += interrupt.o iommu.o setup.o \ + cbe_regs.o spider-pic.o pervasive.o +obj-$(CONFIG_CBE_RAS) += ras.o -obj-$(CONFIG_SMP) += smp.o +ifeq ($(CONFIG_SMP),y) +obj-$(CONFIG_PPC_CELL_NATIVE) += smp.o +endif # needed only when building loadable spufs.ko -spufs-modular-$(CONFIG_SPU_FS) += spu_syscalls.o -obj-y += $(spufs-modular-m) +spufs-modular-$(CONFIG_SPU_FS) += spu_syscalls.o +spu-priv1-$(CONFIG_PPC_CELL_NATIVE) += spu_priv1_mmio.o -# always needed in kernel -spufs-builtin-$(CONFIG_SPU_FS) += spu_callbacks.o spu_base.o spu_priv1.o spufs/ -obj-y += $(spufs-builtin-y) $(spufs-builtin-m) +obj-$(CONFIG_SPU_BASE) += spu_callbacks.o spu_base.o \ + $(spufs-modular-m) \ + $(spu-priv1-y) spufs/ diff --git a/arch/powerpc/platforms/cell/spu_priv1.c b/arch/powerpc/platforms/cell/spu_priv1.c deleted file mode 100644 index b2656421c7b..00000000000 --- a/arch/powerpc/platforms/cell/spu_priv1.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * access to SPU privileged registers - */ -#include - -#include -#include - -void spu_int_mask_and(struct spu *spu, int class, u64 mask) -{ - u64 old_mask; - - old_mask = in_be64(&spu->priv1->int_mask_RW[class]); - out_be64(&spu->priv1->int_mask_RW[class], old_mask & mask); -} -EXPORT_SYMBOL_GPL(spu_int_mask_and); - -void spu_int_mask_or(struct spu *spu, int class, u64 mask) -{ - u64 old_mask; - - old_mask = in_be64(&spu->priv1->int_mask_RW[class]); - out_be64(&spu->priv1->int_mask_RW[class], old_mask | mask); -} -EXPORT_SYMBOL_GPL(spu_int_mask_or); - -void spu_int_mask_set(struct spu *spu, int class, u64 mask) -{ - out_be64(&spu->priv1->int_mask_RW[class], mask); -} -EXPORT_SYMBOL_GPL(spu_int_mask_set); - -u64 spu_int_mask_get(struct spu *spu, int class) -{ - return in_be64(&spu->priv1->int_mask_RW[class]); -} -EXPORT_SYMBOL_GPL(spu_int_mask_get); - -void spu_int_stat_clear(struct spu *spu, int class, u64 stat) -{ - out_be64(&spu->priv1->int_stat_RW[class], stat); -} -EXPORT_SYMBOL_GPL(spu_int_stat_clear); - -u64 spu_int_stat_get(struct spu *spu, int class) -{ - return in_be64(&spu->priv1->int_stat_RW[class]); -} -EXPORT_SYMBOL_GPL(spu_int_stat_get); - -void spu_int_route_set(struct spu *spu, u64 route) -{ - out_be64(&spu->priv1->int_route_RW, route); -} -EXPORT_SYMBOL_GPL(spu_int_route_set); - -u64 spu_mfc_dar_get(struct spu *spu) -{ - return in_be64(&spu->priv1->mfc_dar_RW); -} -EXPORT_SYMBOL_GPL(spu_mfc_dar_get); - -u64 spu_mfc_dsisr_get(struct spu *spu) -{ - return in_be64(&spu->priv1->mfc_dsisr_RW); -} -EXPORT_SYMBOL_GPL(spu_mfc_dsisr_get); - -void spu_mfc_dsisr_set(struct spu *spu, u64 dsisr) -{ - out_be64(&spu->priv1->mfc_dsisr_RW, dsisr); -} -EXPORT_SYMBOL_GPL(spu_mfc_dsisr_set); - -void spu_mfc_sdr_set(struct spu *spu, u64 sdr) -{ - out_be64(&spu->priv1->mfc_sdr_RW, sdr); -} -EXPORT_SYMBOL_GPL(spu_mfc_sdr_set); - -void spu_mfc_sr1_set(struct spu *spu, u64 sr1) -{ - out_be64(&spu->priv1->mfc_sr1_RW, sr1); -} -EXPORT_SYMBOL_GPL(spu_mfc_sr1_set); - -u64 spu_mfc_sr1_get(struct spu *spu) -{ - return in_be64(&spu->priv1->mfc_sr1_RW); -} -EXPORT_SYMBOL_GPL(spu_mfc_sr1_get); - -void spu_mfc_tclass_id_set(struct spu *spu, u64 tclass_id) -{ - out_be64(&spu->priv1->mfc_tclass_id_RW, tclass_id); -} -EXPORT_SYMBOL_GPL(spu_mfc_tclass_id_set); - -u64 spu_mfc_tclass_id_get(struct spu *spu) -{ - return in_be64(&spu->priv1->mfc_tclass_id_RW); -} -EXPORT_SYMBOL_GPL(spu_mfc_tclass_id_get); - -void spu_tlb_invalidate(struct spu *spu) -{ - out_be64(&spu->priv1->tlb_invalidate_entry_W, 0ul); -} -EXPORT_SYMBOL_GPL(spu_tlb_invalidate); - -void spu_resource_allocation_groupID_set(struct spu *spu, u64 id) -{ - out_be64(&spu->priv1->resource_allocation_groupID_RW, id); -} -EXPORT_SYMBOL_GPL(spu_resource_allocation_groupID_set); - -u64 spu_resource_allocation_groupID_get(struct spu *spu) -{ - return in_be64(&spu->priv1->resource_allocation_groupID_RW); -} -EXPORT_SYMBOL_GPL(spu_resource_allocation_groupID_get); - -void spu_resource_allocation_enable_set(struct spu *spu, u64 enable) -{ - out_be64(&spu->priv1->resource_allocation_enable_RW, enable); -} -EXPORT_SYMBOL_GPL(spu_resource_allocation_enable_set); - -u64 spu_resource_allocation_enable_get(struct spu *spu) -{ - return in_be64(&spu->priv1->resource_allocation_enable_RW); -} -EXPORT_SYMBOL_GPL(spu_resource_allocation_enable_get); diff --git a/arch/powerpc/platforms/cell/spu_priv1_mmio.c b/arch/powerpc/platforms/cell/spu_priv1_mmio.c new file mode 100644 index 00000000000..b2656421c7b --- /dev/null +++ b/arch/powerpc/platforms/cell/spu_priv1_mmio.c @@ -0,0 +1,133 @@ +/* + * access to SPU privileged registers + */ +#include + +#include +#include + +void spu_int_mask_and(struct spu *spu, int class, u64 mask) +{ + u64 old_mask; + + old_mask = in_be64(&spu->priv1->int_mask_RW[class]); + out_be64(&spu->priv1->int_mask_RW[class], old_mask & mask); +} +EXPORT_SYMBOL_GPL(spu_int_mask_and); + +void spu_int_mask_or(struct spu *spu, int class, u64 mask) +{ + u64 old_mask; + + old_mask = in_be64(&spu->priv1->int_mask_RW[class]); + out_be64(&spu->priv1->int_mask_RW[class], old_mask | mask); +} +EXPORT_SYMBOL_GPL(spu_int_mask_or); + +void spu_int_mask_set(struct spu *spu, int class, u64 mask) +{ + out_be64(&spu->priv1->int_mask_RW[class], mask); +} +EXPORT_SYMBOL_GPL(spu_int_mask_set); + +u64 spu_int_mask_get(struct spu *spu, int class) +{ + return in_be64(&spu->priv1->int_mask_RW[class]); +} +EXPORT_SYMBOL_GPL(spu_int_mask_get); + +void spu_int_stat_clear(struct spu *spu, int class, u64 stat) +{ + out_be64(&spu->priv1->int_stat_RW[class], stat); +} +EXPORT_SYMBOL_GPL(spu_int_stat_clear); + +u64 spu_int_stat_get(struct spu *spu, int class) +{ + return in_be64(&spu->priv1->int_stat_RW[class]); +} +EXPORT_SYMBOL_GPL(spu_int_stat_get); + +void spu_int_route_set(struct spu *spu, u64 route) +{ + out_be64(&spu->priv1->int_route_RW, route); +} +EXPORT_SYMBOL_GPL(spu_int_route_set); + +u64 spu_mfc_dar_get(struct spu *spu) +{ + return in_be64(&spu->priv1->mfc_dar_RW); +} +EXPORT_SYMBOL_GPL(spu_mfc_dar_get); + +u64 spu_mfc_dsisr_get(struct spu *spu) +{ + return in_be64(&spu->priv1->mfc_dsisr_RW); +} +EXPORT_SYMBOL_GPL(spu_mfc_dsisr_get); + +void spu_mfc_dsisr_set(struct spu *spu, u64 dsisr) +{ + out_be64(&spu->priv1->mfc_dsisr_RW, dsisr); +} +EXPORT_SYMBOL_GPL(spu_mfc_dsisr_set); + +void spu_mfc_sdr_set(struct spu *spu, u64 sdr) +{ + out_be64(&spu->priv1->mfc_sdr_RW, sdr); +} +EXPORT_SYMBOL_GPL(spu_mfc_sdr_set); + +void spu_mfc_sr1_set(struct spu *spu, u64 sr1) +{ + out_be64(&spu->priv1->mfc_sr1_RW, sr1); +} +EXPORT_SYMBOL_GPL(spu_mfc_sr1_set); + +u64 spu_mfc_sr1_get(struct spu *spu) +{ + return in_be64(&spu->priv1->mfc_sr1_RW); +} +EXPORT_SYMBOL_GPL(spu_mfc_sr1_get); + +void spu_mfc_tclass_id_set(struct spu *spu, u64 tclass_id) +{ + out_be64(&spu->priv1->mfc_tclass_id_RW, tclass_id); +} +EXPORT_SYMBOL_GPL(spu_mfc_tclass_id_set); + +u64 spu_mfc_tclass_id_get(struct spu *spu) +{ + return in_be64(&spu->priv1->mfc_tclass_id_RW); +} +EXPORT_SYMBOL_GPL(spu_mfc_tclass_id_get); + +void spu_tlb_invalidate(struct spu *spu) +{ + out_be64(&spu->priv1->tlb_invalidate_entry_W, 0ul); +} +EXPORT_SYMBOL_GPL(spu_tlb_invalidate); + +void spu_resource_allocation_groupID_set(struct spu *spu, u64 id) +{ + out_be64(&spu->priv1->resource_allocation_groupID_RW, id); +} +EXPORT_SYMBOL_GPL(spu_resource_allocation_groupID_set); + +u64 spu_resource_allocation_groupID_get(struct spu *spu) +{ + return in_be64(&spu->priv1->resource_allocation_groupID_RW); +} +EXPORT_SYMBOL_GPL(spu_resource_allocation_groupID_get); + +void spu_resource_allocation_enable_set(struct spu *spu, u64 enable) +{ + out_be64(&spu->priv1->resource_allocation_enable_RW, enable); +} +EXPORT_SYMBOL_GPL(spu_resource_allocation_enable_set); + +u64 spu_resource_allocation_enable_get(struct spu *spu) +{ + return in_be64(&spu->priv1->resource_allocation_enable_RW); +} +EXPORT_SYMBOL_GPL(spu_resource_allocation_enable_get); diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index c1c275833fc..c71209b4afd 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2171,7 +2171,7 @@ config BNX2 config SPIDER_NET tristate "Spider Gigabit Ethernet driver" - depends on PCI && PPC_CELL + depends on PCI && PPC_IBM_CELL_BLADE select FW_LOADER help This driver supports the Gigabit Ethernet chips present on the -- cgit v1.2.3 From 540270d82db943855538cea5d0c790e7e669dda0 Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Mon, 19 Jun 2006 20:33:29 +0200 Subject: [POWERPC] spufs: further abstract priv1 register access To support muti-platform binaries the spu hypervisor accessor routines must have runtime binding. I removed the existing statically linked routines in spu.h and spu_priv1_mmio.c and created new accessor routines in spu_priv1.h that operate indirectly through an ops struct spu_priv1_ops. spu_priv1_mmio.c contains the instance of the accessor routines for running on raw hardware. Signed-off-by: Geoff Levand Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/setup.c | 4 + arch/powerpc/platforms/cell/spu_base.c | 5 + arch/powerpc/platforms/cell/spu_priv1_mmio.c | 104 +++++++++------ arch/powerpc/platforms/cell/spufs/hw_ops.c | 1 + arch/powerpc/platforms/cell/spufs/switch.c | 1 + include/asm-powerpc/spu.h | 23 ---- include/asm-powerpc/spu_priv1.h | 182 +++++++++++++++++++++++++++ 7 files changed, 256 insertions(+), 64 deletions(-) create mode 100644 include/asm-powerpc/spu_priv1.h diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c index eb8ab9bbf74..3d1831d331e 100644 --- a/arch/powerpc/platforms/cell/setup.c +++ b/arch/powerpc/platforms/cell/setup.c @@ -49,6 +49,7 @@ #include #include #include +#include #include "interrupt.h" #include "iommu.h" @@ -83,6 +84,9 @@ static void __init cell_setup_arch(void) { ppc_md.init_IRQ = iic_init_IRQ; ppc_md.get_irq = iic_get_irq; +#ifdef CONFIG_SPU_BASE + spu_priv1_ops = &spu_priv1_mmio_ops; +#endif cbe_regs_init(); diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index eb367dd89a7..c3bb7299c4b 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -34,10 +34,15 @@ #include #include #include +#include #include #include "interrupt.h" +const struct spu_priv1_ops *spu_priv1_ops; + +EXPORT_SYMBOL_GPL(spu_priv1_ops); + static int __spu_trap_invalid_dma(struct spu *spu) { pr_debug("%s\n", __FUNCTION__); diff --git a/arch/powerpc/platforms/cell/spu_priv1_mmio.c b/arch/powerpc/platforms/cell/spu_priv1_mmio.c index b2656421c7b..abe8a84925d 100644 --- a/arch/powerpc/platforms/cell/spu_priv1_mmio.c +++ b/arch/powerpc/platforms/cell/spu_priv1_mmio.c @@ -1,133 +1,155 @@ /* - * access to SPU privileged registers + * spu hypervisor abstraction for direct hardware access. + * + * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 + * Copyright 2006 Sony Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + #include #include #include +#include -void spu_int_mask_and(struct spu *spu, int class, u64 mask) +static void int_mask_and(struct spu *spu, int class, u64 mask) { u64 old_mask; old_mask = in_be64(&spu->priv1->int_mask_RW[class]); out_be64(&spu->priv1->int_mask_RW[class], old_mask & mask); } -EXPORT_SYMBOL_GPL(spu_int_mask_and); -void spu_int_mask_or(struct spu *spu, int class, u64 mask) +static void int_mask_or(struct spu *spu, int class, u64 mask) { u64 old_mask; old_mask = in_be64(&spu->priv1->int_mask_RW[class]); out_be64(&spu->priv1->int_mask_RW[class], old_mask | mask); } -EXPORT_SYMBOL_GPL(spu_int_mask_or); -void spu_int_mask_set(struct spu *spu, int class, u64 mask) +static void int_mask_set(struct spu *spu, int class, u64 mask) { out_be64(&spu->priv1->int_mask_RW[class], mask); } -EXPORT_SYMBOL_GPL(spu_int_mask_set); -u64 spu_int_mask_get(struct spu *spu, int class) +static u64 int_mask_get(struct spu *spu, int class) { return in_be64(&spu->priv1->int_mask_RW[class]); } -EXPORT_SYMBOL_GPL(spu_int_mask_get); -void spu_int_stat_clear(struct spu *spu, int class, u64 stat) +static void int_stat_clear(struct spu *spu, int class, u64 stat) { out_be64(&spu->priv1->int_stat_RW[class], stat); } -EXPORT_SYMBOL_GPL(spu_int_stat_clear); -u64 spu_int_stat_get(struct spu *spu, int class) +static u64 int_stat_get(struct spu *spu, int class) { return in_be64(&spu->priv1->int_stat_RW[class]); } -EXPORT_SYMBOL_GPL(spu_int_stat_get); -void spu_int_route_set(struct spu *spu, u64 route) +static void int_route_set(struct spu *spu, u64 route) { out_be64(&spu->priv1->int_route_RW, route); } -EXPORT_SYMBOL_GPL(spu_int_route_set); -u64 spu_mfc_dar_get(struct spu *spu) +static u64 mfc_dar_get(struct spu *spu) { return in_be64(&spu->priv1->mfc_dar_RW); } -EXPORT_SYMBOL_GPL(spu_mfc_dar_get); -u64 spu_mfc_dsisr_get(struct spu *spu) +static u64 mfc_dsisr_get(struct spu *spu) { return in_be64(&spu->priv1->mfc_dsisr_RW); } -EXPORT_SYMBOL_GPL(spu_mfc_dsisr_get); -void spu_mfc_dsisr_set(struct spu *spu, u64 dsisr) +static void mfc_dsisr_set(struct spu *spu, u64 dsisr) { out_be64(&spu->priv1->mfc_dsisr_RW, dsisr); } -EXPORT_SYMBOL_GPL(spu_mfc_dsisr_set); -void spu_mfc_sdr_set(struct spu *spu, u64 sdr) +static void mfc_sdr_set(struct spu *spu, u64 sdr) { out_be64(&spu->priv1->mfc_sdr_RW, sdr); } -EXPORT_SYMBOL_GPL(spu_mfc_sdr_set); -void spu_mfc_sr1_set(struct spu *spu, u64 sr1) +static void mfc_sr1_set(struct spu *spu, u64 sr1) { out_be64(&spu->priv1->mfc_sr1_RW, sr1); } -EXPORT_SYMBOL_GPL(spu_mfc_sr1_set); -u64 spu_mfc_sr1_get(struct spu *spu) +static u64 mfc_sr1_get(struct spu *spu) { return in_be64(&spu->priv1->mfc_sr1_RW); } -EXPORT_SYMBOL_GPL(spu_mfc_sr1_get); -void spu_mfc_tclass_id_set(struct spu *spu, u64 tclass_id) +static void mfc_tclass_id_set(struct spu *spu, u64 tclass_id) { out_be64(&spu->priv1->mfc_tclass_id_RW, tclass_id); } -EXPORT_SYMBOL_GPL(spu_mfc_tclass_id_set); -u64 spu_mfc_tclass_id_get(struct spu *spu) +static u64 mfc_tclass_id_get(struct spu *spu) { return in_be64(&spu->priv1->mfc_tclass_id_RW); } -EXPORT_SYMBOL_GPL(spu_mfc_tclass_id_get); -void spu_tlb_invalidate(struct spu *spu) +static void tlb_invalidate(struct spu *spu) { out_be64(&spu->priv1->tlb_invalidate_entry_W, 0ul); } -EXPORT_SYMBOL_GPL(spu_tlb_invalidate); -void spu_resource_allocation_groupID_set(struct spu *spu, u64 id) +static void resource_allocation_groupID_set(struct spu *spu, u64 id) { out_be64(&spu->priv1->resource_allocation_groupID_RW, id); } -EXPORT_SYMBOL_GPL(spu_resource_allocation_groupID_set); -u64 spu_resource_allocation_groupID_get(struct spu *spu) +static u64 resource_allocation_groupID_get(struct spu *spu) { return in_be64(&spu->priv1->resource_allocation_groupID_RW); } -EXPORT_SYMBOL_GPL(spu_resource_allocation_groupID_get); -void spu_resource_allocation_enable_set(struct spu *spu, u64 enable) +static void resource_allocation_enable_set(struct spu *spu, u64 enable) { out_be64(&spu->priv1->resource_allocation_enable_RW, enable); } -EXPORT_SYMBOL_GPL(spu_resource_allocation_enable_set); -u64 spu_resource_allocation_enable_get(struct spu *spu) +static u64 resource_allocation_enable_get(struct spu *spu) { return in_be64(&spu->priv1->resource_allocation_enable_RW); } -EXPORT_SYMBOL_GPL(spu_resource_allocation_enable_get); + +const struct spu_priv1_ops spu_priv1_mmio_ops = +{ + .int_mask_and = int_mask_and, + .int_mask_or = int_mask_or, + .int_mask_set = int_mask_set, + .int_mask_get = int_mask_get, + .int_stat_clear = int_stat_clear, + .int_stat_get = int_stat_get, + .int_route_set = int_route_set, + .mfc_dar_get = mfc_dar_get, + .mfc_dsisr_get = mfc_dsisr_get, + .mfc_dsisr_set = mfc_dsisr_set, + .mfc_sdr_set = mfc_sdr_set, + .mfc_sr1_set = mfc_sr1_set, + .mfc_sr1_get = mfc_sr1_get, + .mfc_tclass_id_set = mfc_tclass_id_set, + .mfc_tclass_id_get = mfc_tclass_id_get, + .tlb_invalidate = tlb_invalidate, + .resource_allocation_groupID_set = resource_allocation_groupID_set, + .resource_allocation_groupID_get = resource_allocation_groupID_get, + .resource_allocation_enable_set = resource_allocation_enable_set, + .resource_allocation_enable_get = resource_allocation_enable_get, +}; diff --git a/arch/powerpc/platforms/cell/spufs/hw_ops.c b/arch/powerpc/platforms/cell/spufs/hw_ops.c index a13a8b5a014..ede2cac46b6 100644 --- a/arch/powerpc/platforms/cell/spufs/hw_ops.c +++ b/arch/powerpc/platforms/cell/spufs/hw_ops.c @@ -32,6 +32,7 @@ #include #include +#include #include #include #include "spufs.h" diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c index 85bea06e798..2dae062a9ae 100644 --- a/arch/powerpc/platforms/cell/spufs/switch.c +++ b/arch/powerpc/platforms/cell/spufs/switch.c @@ -46,6 +46,7 @@ #include #include +#include #include #include diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h index 946489929eb..c7812e92f68 100644 --- a/include/asm-powerpc/spu.h +++ b/include/asm-powerpc/spu.h @@ -183,29 +183,6 @@ static inline void unregister_spu_syscalls(struct spufs_calls *calls) #endif /* MODULE */ -/* access to priv1 registers */ -void spu_int_mask_and(struct spu *spu, int class, u64 mask); -void spu_int_mask_or(struct spu *spu, int class, u64 mask); -void spu_int_mask_set(struct spu *spu, int class, u64 mask); -u64 spu_int_mask_get(struct spu *spu, int class); -void spu_int_stat_clear(struct spu *spu, int class, u64 stat); -u64 spu_int_stat_get(struct spu *spu, int class); -void spu_int_route_set(struct spu *spu, u64 route); -u64 spu_mfc_dar_get(struct spu *spu); -u64 spu_mfc_dsisr_get(struct spu *spu); -void spu_mfc_dsisr_set(struct spu *spu, u64 dsisr); -void spu_mfc_sdr_set(struct spu *spu, u64 sdr); -void spu_mfc_sr1_set(struct spu *spu, u64 sr1); -u64 spu_mfc_sr1_get(struct spu *spu); -void spu_mfc_tclass_id_set(struct spu *spu, u64 tclass_id); -u64 spu_mfc_tclass_id_get(struct spu *spu); -void spu_tlb_invalidate(struct spu *spu); -void spu_resource_allocation_groupID_set(struct spu *spu, u64 id); -u64 spu_resource_allocation_groupID_get(struct spu *spu); -void spu_resource_allocation_enable_set(struct spu *spu, u64 enable); -u64 spu_resource_allocation_enable_get(struct spu *spu); - - /* * This defines the Local Store, Problem Area and Privlege Area of an SPU. */ diff --git a/include/asm-powerpc/spu_priv1.h b/include/asm-powerpc/spu_priv1.h new file mode 100644 index 00000000000..cb87d1f7e9b --- /dev/null +++ b/include/asm-powerpc/spu_priv1.h @@ -0,0 +1,182 @@ +/* + * Defines an spu hypervisor abstraction layer. + * + * Copyright 2006 Sony Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#if !defined(_SPU_PRIV1_H) +#define _SPU_PRIV1_H +#if defined(__KERNEL__) + +struct spu; + +/* access to priv1 registers */ + +struct spu_priv1_ops +{ + void (*int_mask_and) (struct spu *spu, int class, u64 mask); + void (*int_mask_or) (struct spu *spu, int class, u64 mask); + void (*int_mask_set) (struct spu *spu, int class, u64 mask); + u64 (*int_mask_get) (struct spu *spu, int class); + void (*int_stat_clear) (struct spu *spu, int class, u64 stat); + u64 (*int_stat_get) (struct spu *spu, int class); + void (*int_route_set) (struct spu *spu, u64 route); + u64 (*mfc_dar_get) (struct spu *spu); + u64 (*mfc_dsisr_get) (struct spu *spu); + void (*mfc_dsisr_set) (struct spu *spu, u64 dsisr); + void (*mfc_sdr_set) (struct spu *spu, u64 sdr); + void (*mfc_sr1_set) (struct spu *spu, u64 sr1); + u64 (*mfc_sr1_get) (struct spu *spu); + void (*mfc_tclass_id_set) (struct spu *spu, u64 tclass_id); + u64 (*mfc_tclass_id_get) (struct spu *spu); + void (*tlb_invalidate) (struct spu *spu); + void (*resource_allocation_groupID_set) (struct spu *spu, u64 id); + u64 (*resource_allocation_groupID_get) (struct spu *spu); + void (*resource_allocation_enable_set) (struct spu *spu, u64 enable); + u64 (*resource_allocation_enable_get) (struct spu *spu); +}; + +extern const struct spu_priv1_ops* spu_priv1_ops; + +static inline void +spu_int_mask_and (struct spu *spu, int class, u64 mask) +{ + spu_priv1_ops->int_mask_and(spu, class, mask); +} + +static inline void +spu_int_mask_or (struct spu *spu, int class, u64 mask) +{ + spu_priv1_ops->int_mask_or(spu, class, mask); +} + +static inline void +spu_int_mask_set (struct spu *spu, int class, u64 mask) +{ + spu_priv1_ops->int_mask_set(spu, class, mask); +} + +static inline u64 +spu_int_mask_get (struct spu *spu, int class) +{ + return spu_priv1_ops->int_mask_get(spu, class); +} + +static inline void +spu_int_stat_clear (struct spu *spu, int class, u64 stat) +{ + spu_priv1_ops->int_stat_clear(spu, class, stat); +} + +static inline u64 +spu_int_stat_get (struct spu *spu, int class) +{ + return spu_priv1_ops->int_stat_get (spu, class); +} + +static inline void +spu_int_route_set (struct spu *spu, u64 route) +{ + spu_priv1_ops->int_stat_get(spu, route); +} + +static inline u64 +spu_mfc_dar_get (struct spu *spu) +{ + return spu_priv1_ops->mfc_dar_get(spu); +} + +static inline u64 +spu_mfc_dsisr_get (struct spu *spu) +{ + return spu_priv1_ops->mfc_dsisr_get(spu); +} + +static inline void +spu_mfc_dsisr_set (struct spu *spu, u64 dsisr) +{ + spu_priv1_ops->mfc_dsisr_set(spu, dsisr); +} + +static inline void +spu_mfc_sdr_set (struct spu *spu, u64 sdr) +{ + spu_priv1_ops->mfc_sdr_set(spu, sdr); +} + +static inline void +spu_mfc_sr1_set (struct spu *spu, u64 sr1) +{ + spu_priv1_ops->mfc_sr1_set(spu, sr1); +} + +static inline u64 +spu_mfc_sr1_get (struct spu *spu) +{ + return spu_priv1_ops->mfc_sr1_get(spu); +} + +static inline void +spu_mfc_tclass_id_set (struct spu *spu, u64 tclass_id) +{ + spu_priv1_ops->mfc_tclass_id_set(spu, tclass_id); +} + +static inline u64 +spu_mfc_tclass_id_get (struct spu *spu) +{ + return spu_priv1_ops->mfc_tclass_id_get(spu); +} + +static inline void +spu_tlb_invalidate (struct spu *spu) +{ + spu_priv1_ops->tlb_invalidate(spu); +} + +static inline void +spu_resource_allocation_groupID_set (struct spu *spu, u64 id) +{ + spu_priv1_ops->resource_allocation_groupID_set(spu, id); +} + +static inline u64 +spu_resource_allocation_groupID_get (struct spu *spu) +{ + return spu_priv1_ops->resource_allocation_groupID_get(spu); +} + +static inline void +spu_resource_allocation_enable_set (struct spu *spu, u64 enable) +{ + spu_priv1_ops->resource_allocation_enable_set(spu, enable); +} + +static inline u64 +spu_resource_allocation_enable_get (struct spu *spu) +{ + return spu_priv1_ops->resource_allocation_enable_get(spu); +} + +/* The declarations folowing are put here for convenience + * and only intended to be used by the platform setup code + * for initializing spu_priv1_ops. + */ + +extern const struct spu_priv1_ops spu_priv1_mmio_ops; + +#endif /* __KERNEL__ */ +#endif -- cgit v1.2.3 From a91942ae7ebd518006dcbeb2a1d7b147253c080e Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Mon, 19 Jun 2006 20:33:30 +0200 Subject: [POWERPC] spufs: fix spu irq affinity setting This changes the hypervisor abstraction of setting cpu affinity to a higher level to avoid platform dependent interrupt controller routines. I replaced spu_priv1_ops:spu_int_route_set() with a new routine spu_priv1_ops:spu_cpu_affinity_set(). As a by-product, this change eliminated what looked like an existing bug in the set affinity code where spu_int_route_set() mistakenly called int_stat_get(). Signed-off-by: Geoff Levand Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spu_base.c | 8 -------- arch/powerpc/platforms/cell/spu_priv1_mmio.c | 8 ++++++-- arch/powerpc/platforms/cell/spufs/sched.c | 3 ++- include/asm-powerpc/spu_priv1.h | 6 +++--- 4 files changed, 11 insertions(+), 14 deletions(-) diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index c3bb7299c4b..8ca22394e4d 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -522,14 +522,6 @@ int spu_irq_class_1_bottom(struct spu *spu) return ret; } -void spu_irq_setaffinity(struct spu *spu, int cpu) -{ - u64 target = iic_get_target_id(cpu); - u64 route = target << 48 | target << 32 | target << 16; - spu_int_route_set(spu, route); -} -EXPORT_SYMBOL_GPL(spu_irq_setaffinity); - static int __init find_spu_node_id(struct device_node *spe) { unsigned int *id; diff --git a/arch/powerpc/platforms/cell/spu_priv1_mmio.c b/arch/powerpc/platforms/cell/spu_priv1_mmio.c index abe8a84925d..71b69f0a1a4 100644 --- a/arch/powerpc/platforms/cell/spu_priv1_mmio.c +++ b/arch/powerpc/platforms/cell/spu_priv1_mmio.c @@ -24,6 +24,8 @@ #include #include +#include "interrupt.h" + static void int_mask_and(struct spu *spu, int class, u64 mask) { u64 old_mask; @@ -60,8 +62,10 @@ static u64 int_stat_get(struct spu *spu, int class) return in_be64(&spu->priv1->int_stat_RW[class]); } -static void int_route_set(struct spu *spu, u64 route) +static void cpu_affinity_set(struct spu *spu, int cpu) { + u64 target = iic_get_target_id(cpu); + u64 route = target << 48 | target << 32 | target << 16; out_be64(&spu->priv1->int_route_RW, route); } @@ -138,7 +142,7 @@ const struct spu_priv1_ops spu_priv1_mmio_ops = .int_mask_get = int_mask_get, .int_stat_clear = int_stat_clear, .int_stat_get = int_stat_get, - .int_route_set = int_route_set, + .cpu_affinity_set = cpu_affinity_set, .mfc_dar_get = mfc_dar_get, .mfc_dsisr_get = mfc_dsisr_get, .mfc_dsisr_set = mfc_dsisr_set, diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c index bf652cd7700..3dcc5d8d66b 100644 --- a/arch/powerpc/platforms/cell/spufs/sched.c +++ b/arch/powerpc/platforms/cell/spufs/sched.c @@ -43,6 +43,7 @@ #include #include #include +#include #include "spufs.h" #define SPU_MIN_TIMESLICE (100 * HZ / 1000) @@ -363,7 +364,7 @@ int spu_activate(struct spu_context *ctx, u64 flags) * We're likely to wait for interrupts on the same * CPU that we are now on, so send them here. */ - spu_irq_setaffinity(spu, raw_smp_processor_id()); + spu_cpu_affinity_set(spu, raw_smp_processor_id()); put_active_spu(spu); return 0; } diff --git a/include/asm-powerpc/spu_priv1.h b/include/asm-powerpc/spu_priv1.h index cb87d1f7e9b..300c458b6d0 100644 --- a/include/asm-powerpc/spu_priv1.h +++ b/include/asm-powerpc/spu_priv1.h @@ -33,7 +33,7 @@ struct spu_priv1_ops u64 (*int_mask_get) (struct spu *spu, int class); void (*int_stat_clear) (struct spu *spu, int class, u64 stat); u64 (*int_stat_get) (struct spu *spu, int class); - void (*int_route_set) (struct spu *spu, u64 route); + void (*cpu_affinity_set) (struct spu *spu, int cpu); u64 (*mfc_dar_get) (struct spu *spu); u64 (*mfc_dsisr_get) (struct spu *spu); void (*mfc_dsisr_set) (struct spu *spu, u64 dsisr); @@ -88,9 +88,9 @@ spu_int_stat_get (struct spu *spu, int class) } static inline void -spu_int_route_set (struct spu *spu, u64 route) +spu_cpu_affinity_set (struct spu *spu, int cpu) { - spu_priv1_ops->int_stat_get(spu, route); + spu_priv1_ops->cpu_affinity_set(spu, cpu); } static inline u64 -- cgit v1.2.3 From 2eabbbd33ec39f690005aa186c57476598edc6b3 Mon Sep 17 00:00:00 2001 From: Masato Noguchi Date: Mon, 19 Jun 2006 20:33:31 +0200 Subject: [POWERPC] spufs: remove stop_code from struct spu This patch remove 'stop_code' -- discarded member of struct spu. It is written at initialize and interrupt, but never read in current implementation. Signed-off-by: Masato Noguchi Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spu_base.c | 2 -- arch/powerpc/platforms/cell/spufs/switch.c | 1 - include/asm-powerpc/spu.h | 1 - 3 files changed, 4 deletions(-) diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index 8ca22394e4d..249a0af4cc9 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -160,7 +160,6 @@ static int __spu_trap_mailbox(struct spu *spu) static int __spu_trap_stop(struct spu *spu) { pr_debug("%s\n", __FUNCTION__); - spu->stop_code = in_be32(&spu->problem->spu_status_R); if (spu->stop_callback) spu->stop_callback(spu); return 0; @@ -169,7 +168,6 @@ static int __spu_trap_stop(struct spu *spu) static int __spu_trap_halt(struct spu *spu) { pr_debug("%s\n", __FUNCTION__); - spu->stop_code = in_be32(&spu->problem->spu_status_R); if (spu->stop_callback) spu->stop_callback(spu); return 0; diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c index 2dae062a9ae..b30e55dab83 100644 --- a/arch/powerpc/platforms/cell/spufs/switch.c +++ b/arch/powerpc/platforms/cell/spufs/switch.c @@ -2109,7 +2109,6 @@ int spu_restore(struct spu_state *new, struct spu *spu) acquire_spu_lock(spu); harvest(NULL, spu); - spu->stop_code = 0; spu->dar = 0; spu->dsisr = 0; spu->slb_replace = 0; diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h index c7812e92f68..c0290f9d20b 100644 --- a/include/asm-powerpc/spu.h +++ b/include/asm-powerpc/spu.h @@ -134,7 +134,6 @@ struct spu { int class_0_pending; spinlock_t register_lock; - u32 stop_code; void (* wbox_callback)(struct spu *spu); void (* ibox_callback)(struct spu *spu); void (* stop_callback)(struct spu *spu); -- cgit v1.2.3 From 6e18b27bd0911d4d2495c6fdeeac0c047d915300 Mon Sep 17 00:00:00 2001 From: Masato Noguchi Date: Mon, 19 Jun 2006 20:33:32 +0200 Subject: [POWERPC] spufs: fix Makefile for "make clean" added spu_{save,restore}_dump.h to target of 'make clean' Signed-off-by: Masato Noguchi Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spufs/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/powerpc/platforms/cell/spufs/Makefile b/arch/powerpc/platforms/cell/spufs/Makefile index 7963d520b67..e3c4482be3b 100644 --- a/arch/powerpc/platforms/cell/spufs/Makefile +++ b/arch/powerpc/platforms/cell/spufs/Makefile @@ -15,6 +15,7 @@ SPU_AFLAGS := -c -D__ASSEMBLY__ -I$(srctree)/include -I$(objtree)/include2 SPU_LDFLAGS := -N -Ttext=0x0 $(obj)/switch.o: $(obj)/spu_save_dump.h $(obj)/spu_restore_dump.h +clean-files := spu_save_dump.h spu_restore_dump.h # Compile SPU files cmd_spu_cc = $(SPU_CC) $(SPU_CFLAGS) -c -o $@ $< -- cgit v1.2.3 From ba723fe2b2facc8d45b53701fec39aa429596759 Mon Sep 17 00:00:00 2001 From: Masato Noguchi Date: Mon, 19 Jun 2006 20:33:33 +0200 Subject: [POWERPC] spufs: clear class2 interrupt status before wakeup SPU interrupt status must be cleared before handle it. Otherwise, kernel may drop some interrupt packet. Currently, class2 interrupt treated like: 1) call callback to wake up waiting process 2) mask raised mailbox interrupt 3) clear interrupt status I changed like: 1) mask raised mailbox interrupt 2) clear interrupt status 3) call callback to wake up waiting process Clearing status before masking will make spurious interrupt. Thus, it is necessary to hold by steps I described above, I think. Signed-off-by: Masato Noguchi Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spu_base.c | 78 +++++++++------------------------- 1 file changed, 19 insertions(+), 59 deletions(-) diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index 249a0af4cc9..db82f503ba2 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -140,55 +140,7 @@ static int __spu_trap_data_map(struct spu *spu, unsigned long ea, u64 dsisr) spu->dar = ea; spu->dsisr = dsisr; mb(); - if (spu->stop_callback) - spu->stop_callback(spu); - return 0; -} - -static int __spu_trap_mailbox(struct spu *spu) -{ - if (spu->ibox_callback) - spu->ibox_callback(spu); - - /* atomically disable SPU mailbox interrupts */ - spin_lock(&spu->register_lock); - spu_int_mask_and(spu, 2, ~0x1); - spin_unlock(&spu->register_lock); - return 0; -} - -static int __spu_trap_stop(struct spu *spu) -{ - pr_debug("%s\n", __FUNCTION__); - if (spu->stop_callback) - spu->stop_callback(spu); - return 0; -} - -static int __spu_trap_halt(struct spu *spu) -{ - pr_debug("%s\n", __FUNCTION__); - if (spu->stop_callback) - spu->stop_callback(spu); - return 0; -} - -static int __spu_trap_tag_group(struct spu *spu) -{ - pr_debug("%s\n", __FUNCTION__); - spu->mfc_callback(spu); - return 0; -} - -static int __spu_trap_spubox(struct spu *spu) -{ - if (spu->wbox_callback) - spu->wbox_callback(spu); - - /* atomically disable SPU mailbox interrupts */ - spin_lock(&spu->register_lock); - spu_int_mask_and(spu, 2, ~0x10); - spin_unlock(&spu->register_lock); + spu->stop_callback(spu); return 0; } @@ -199,8 +151,7 @@ spu_irq_class_0(int irq, void *data, struct pt_regs *regs) spu = data; spu->class_0_pending = 1; - if (spu->stop_callback) - spu->stop_callback(spu); + spu->stop_callback(spu); return IRQ_HANDLED; } @@ -278,29 +229,38 @@ spu_irq_class_2(int irq, void *data, struct pt_regs *regs) unsigned long mask; spu = data; + spin_lock(&spu->register_lock); stat = spu_int_stat_get(spu, 2); mask = spu_int_mask_get(spu, 2); + /* ignore interrupts we're not waiting for */ + stat &= mask; + /* + * mailbox interrupts (0x1 and 0x10) are level triggered. + * mask them now before acknowledging. + */ + if (stat & 0x11) + spu_int_mask_and(spu, 2, ~(stat & 0x11)); + /* acknowledge all interrupts before the callbacks */ + spu_int_stat_clear(spu, 2, stat); + spin_unlock(&spu->register_lock); pr_debug("class 2 interrupt %d, %lx, %lx\n", irq, stat, mask); - stat &= mask; - if (stat & 1) /* PPC core mailbox */ - __spu_trap_mailbox(spu); + spu->ibox_callback(spu); if (stat & 2) /* SPU stop-and-signal */ - __spu_trap_stop(spu); + spu->stop_callback(spu); if (stat & 4) /* SPU halted */ - __spu_trap_halt(spu); + spu->stop_callback(spu); if (stat & 8) /* DMA tag group complete */ - __spu_trap_tag_group(spu); + spu->mfc_callback(spu); if (stat & 0x10) /* SPU mailbox threshold */ - __spu_trap_spubox(spu); + spu->wbox_callback(spu); - spu_int_stat_clear(spu, 2, stat); return stat ? IRQ_HANDLED : IRQ_NONE; } -- cgit v1.2.3 From c983294872ebccd4aacf1b8dd694ac2170feadc3 Mon Sep 17 00:00:00 2001 From: "arnd@arndb.de" Date: Mon, 19 Jun 2006 20:33:34 +0200 Subject: [POWERPC] spufs: fail spu_create with invalid flags At this time, all flags are invalid. Since we are planning to actually add valid flags in the future, we better check if any were passed by the user. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spufs/inode.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index fed511a2b17..1987697b23a 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c @@ -304,6 +304,10 @@ long spufs_create_thread(struct nameidata *nd, nd->dentry != nd->dentry->d_sb->s_root) goto out; + /* all flags are reserved */ + if (flags) + goto out; + dentry = lookup_create(nd, 1); ret = PTR_ERR(dentry); if (IS_ERR(dentry)) -- cgit v1.2.3 From 379507181a1e330d4f5b0fabe61cd43eccf09763 Mon Sep 17 00:00:00 2001 From: "arnd@arndb.de" Date: Mon, 19 Jun 2006 20:33:35 +0200 Subject: [POWERPC] spufs: one more fix for 64k pages The SPU context save/restore code is currently built for a 4k page size and we provide a _shipped version of it since most people don't have the spu toolchain that is needed to rebuild that code. This patch hardcodes the data structures to a 64k page alignment, which also guarantees 4k alignment but unfortunately wastes 60k of memory per SPU context that is created in the running system. We will follow up on this with another patch to reduce that overhead or maybe redo the context save/restore logic to do this part entirely different, but for now it should make experimental systems work with either page size. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spufs/Makefile | 9 +- .../cell/spufs/spu_restore_dump.h_shipped | 1122 ++++++++++++++++---- .../platforms/cell/spufs/spu_save_dump.h_shipped | 922 ++++++++++++---- include/asm-powerpc/spu_csa.h | 13 +- 4 files changed, 1651 insertions(+), 415 deletions(-) diff --git a/arch/powerpc/platforms/cell/spufs/Makefile b/arch/powerpc/platforms/cell/spufs/Makefile index e3c4482be3b..bb5dc634272 100644 --- a/arch/powerpc/platforms/cell/spufs/Makefile +++ b/arch/powerpc/platforms/cell/spufs/Makefile @@ -10,8 +10,10 @@ SPU_CC := $(SPU_CROSS)gcc SPU_AS := $(SPU_CROSS)gcc SPU_LD := $(SPU_CROSS)ld SPU_OBJCOPY := $(SPU_CROSS)objcopy -SPU_CFLAGS := -O2 -Wall -I$(srctree)/include -I$(objtree)/include2 -SPU_AFLAGS := -c -D__ASSEMBLY__ -I$(srctree)/include -I$(objtree)/include2 +SPU_CFLAGS := -O2 -Wall -I$(srctree)/include \ + -I$(objtree)/include2 -D__KERNEL__ +SPU_AFLAGS := -c -D__ASSEMBLY__ -I$(srctree)/include \ + -I$(objtree)/include2 -D__KERNEL__ SPU_LDFLAGS := -N -Ttext=0x0 $(obj)/switch.o: $(obj)/spu_save_dump.h $(obj)/spu_restore_dump.h @@ -48,7 +50,8 @@ cmd_hexdump = ( \ echo " * Hex-dump auto generated from $*.c." ; \ echo " * Do not edit!" ; \ echo " */" ; \ - echo "static unsigned int $*_code[] __page_aligned = {" ; \ + echo "static unsigned int $*_code[] " \ + "__attribute__((__aligned__(128))) = {" ; \ hexdump -v -e '"0x" 4/1 "%02x" "," "\n"' $< ; \ echo "};" ; \ ) > $@ diff --git a/arch/powerpc/platforms/cell/spufs/spu_restore_dump.h_shipped b/arch/powerpc/platforms/cell/spufs/spu_restore_dump.h_shipped index 1b2355ff703..15183d209b5 100644 --- a/arch/powerpc/platforms/cell/spufs/spu_restore_dump.h_shipped +++ b/arch/powerpc/platforms/cell/spufs/spu_restore_dump.h_shipped @@ -3,229 +3,901 @@ * Hex-dump auto generated from spu_restore.c. * Do not edit! */ -static unsigned int spu_restore_code[] __page_aligned = { -0x40800000, 0x409ff801, 0x24000080, 0x24fd8081, -0x1cd80081, 0x33001180, 0x42030003, 0x33800284, -0x1c010204, 0x40200000, 0x40200000, 0x40200000, -0x34000190, 0x34004191, 0x34008192, 0x3400c193, -0x141fc205, 0x23fffd84, 0x1c100183, 0x217ffa85, -0x3080a000, 0x3080a201, 0x3080a402, 0x3080a603, -0x3080a804, 0x3080aa05, 0x3080ac06, 0x3080ae07, -0x3080b008, 0x3080b209, 0x3080b40a, 0x3080b60b, -0x3080b80c, 0x3080ba0d, 0x3080bc0e, 0x3080be0f, -0x00003ffc, 0x00000000, 0x00000000, 0x00000000, -0x01a00182, 0x3ec00083, 0xb0a14103, 0x01a00204, -0x3ec10082, 0x4202800e, 0x04000703, 0xb0a14202, -0x21a00803, 0x3fbf028d, 0x3f20068d, 0x3fbe0682, -0x3fe30102, 0x21a00882, 0x3f82028f, 0x3fe3078f, -0x3fbf0784, 0x3f200204, 0x3fbe0204, 0x3fe30204, -0x04000203, 0x21a00903, 0x40848002, 0x21a00982, -0x40800003, 0x21a00a03, 0x40802002, 0x21a00a82, -0x21a00083, 0x40800082, 0x21a00b02, 0x10002818, -0x40a80002, 0x32800007, 0x4207000c, 0x18008208, -0x40a0000b, 0x4080020a, 0x40800709, 0x00200000, -0x42070002, 0x3ac30384, 0x1cffc489, 0x00200000, -0x18008383, 0x38830382, 0x4cffc486, 0x3ac28185, -0xb0408584, 0x28830382, 0x1c020387, 0x38828182, -0xb0408405, 0x1802c408, 0x28828182, 0x217ff886, -0x04000583, 0x21a00803, 0x3fbe0682, 0x3fe30102, -0x04000106, 0x21a00886, 0x04000603, 0x21a00903, -0x40803c02, 0x21a00982, 0x40800003, 0x04000184, -0x21a00a04, 0x40802202, 0x21a00a82, 0x42028005, -0x34208702, 0x21002282, 0x21a00804, 0x21a00886, -0x3fbf0782, 0x3f200102, 0x3fbe0102, 0x3fe30102, -0x21a00902, 0x40804003, 0x21a00983, 0x21a00a04, -0x40805a02, 0x21a00a82, 0x40800083, 0x21a00b83, -0x01a00c02, 0x01a00d83, 0x3420c282, 0x21a00e02, -0x34210283, 0x21a00f03, 0x34200284, 0x77400200, -0x3421c282, 0x21a00702, 0x34218283, 0x21a00083, -0x34214282, 0x21a00b02, 0x4200480c, 0x00200000, -0x1c010286, 0x34220284, 0x34220302, 0x0f608203, -0x5c024204, 0x3b81810b, 0x42013c02, 0x00200000, -0x18008185, 0x38808183, 0x3b814182, 0x21004e84, -0x4020007f, 0x35000100, 0x000004e0, 0x000002a0, -0x000002e8, 0x00000428, 0x00000360, 0x000002e8, -0x000004a0, 0x00000468, 0x000003c8, 0x00000360, -0x409ffe02, 0x30801203, 0x40800204, 0x3ec40085, -0x10009c09, 0x3ac10606, 0xb060c105, 0x4020007f, -0x4020007f, 0x20801203, 0x38810602, 0xb0408586, -0x28810602, 0x32004180, 0x34204702, 0x21a00382, -0x4020007f, 0x327fdc80, 0x409ffe02, 0x30801203, -0x40800204, 0x3ec40087, 0x40800405, 0x00200000, -0x40800606, 0x3ac10608, 0x3ac14609, 0x3ac1860a, -0xb060c107, 0x20801203, 0x41004003, 0x38810602, -0x4020007f, 0xb0408188, 0x4020007f, 0x28810602, -0x41201002, 0x38814603, 0x10009c09, 0xb060c109, -0x4020007f, 0x28814603, 0x41193f83, 0x38818602, -0x60ffc003, 0xb040818a, 0x28818602, 0x32003080, -0x409ffe02, 0x30801203, 0x40800204, 0x3ec40087, -0x41201008, 0x10009c14, 0x40800405, 0x3ac10609, -0x40800606, 0x3ac1460a, 0xb060c107, 0x3ac1860b, -0x20801203, 0x38810602, 0xb0408409, 0x28810602, -0x38814603, 0xb060c40a, 0x4020007f, 0x28814603, -0x41193f83, 0x38818602, 0x60ffc003, 0xb040818b, -0x28818602, 0x32002380, 0x409ffe02, 0x30801204, -0x40800205, 0x3ec40083, 0x40800406, 0x3ac14607, -0x3ac18608, 0xb0810103, 0x41004002, 0x20801204, -0x4020007f, 0x38814603, 0x10009c0b, 0xb060c107, -0x4020007f, 0x4020007f, 0x28814603, 0x38818602, -0x4020007f, 0x4020007f, 0xb0408588, 0x28818602, -0x4020007f, 0x32001780, 0x409ffe02, 0x1000640e, -0x40800204, 0x30801203, 0x40800405, 0x3ec40087, -0x40800606, 0x3ac10608, 0x3ac14609, 0x3ac1860a, -0xb060c107, 0x20801203, 0x413d8003, 0x38810602, -0x4020007f, 0x327fd780, 0x409ffe02, 0x10007f0c, -0x40800205, 0x30801204, 0x40800406, 0x3ec40083, -0x3ac14607, 0x3ac18608, 0xb0810103, 0x413d8002, -0x20801204, 0x38814603, 0x4020007f, 0x327feb80, -0x409ffe02, 0x30801203, 0x40800204, 0x3ec40087, -0x40800405, 0x1000650a, 0x40800606, 0x3ac10608, -0x3ac14609, 0x3ac1860a, 0xb060c107, 0x20801203, -0x38810602, 0xb0408588, 0x4020007f, 0x327fc980, -0x00400000, 0x40800003, 0x4020007f, 0x35000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, +static unsigned int spu_restore_code[] __attribute__((__aligned__(128))) = { +0x40800000, +0x409ff801, +0x24000080, +0x24fd8081, +0x1cd80081, +0x33001180, +0x42030003, +0x33800284, +0x1c010204, +0x40200000, +0x40200000, +0x40200000, +0x34000190, +0x34004191, +0x34008192, +0x3400c193, +0x141fc205, +0x23fffd84, +0x1c100183, +0x217ffa85, +0x3080a000, +0x3080a201, +0x3080a402, +0x3080a603, +0x3080a804, +0x3080aa05, +0x3080ac06, +0x3080ae07, +0x3080b008, +0x3080b209, +0x3080b40a, +0x3080b60b, +0x3080b80c, +0x3080ba0d, +0x3080bc0e, +0x3080be0f, +0x00003ffc, +0x00000000, +0x00000000, +0x00000000, +0x01a00182, +0x3ec00083, +0xb0a14103, +0x01a00204, +0x3ec10082, +0x4202800e, +0x04000703, +0xb0a14202, +0x21a00803, +0x3fbf028d, +0x3f20068d, +0x3fbe0682, +0x3fe30102, +0x21a00882, +0x3f82028f, +0x3fe3078f, +0x3fbf0784, +0x3f200204, +0x3fbe0204, +0x3fe30204, +0x04000203, +0x21a00903, +0x40848002, +0x21a00982, +0x40800003, +0x21a00a03, +0x40802002, +0x21a00a82, +0x21a00083, +0x40800082, +0x21a00b02, +0x10002818, +0x42a00002, +0x32800007, +0x4207000c, +0x18008208, +0x40a0000b, +0x4080020a, +0x40800709, +0x00200000, +0x42070002, +0x3ac30384, +0x1cffc489, +0x00200000, +0x18008383, +0x38830382, +0x4cffc486, +0x3ac28185, +0xb0408584, +0x28830382, +0x1c020387, +0x38828182, +0xb0408405, +0x1802c408, +0x28828182, +0x217ff886, +0x04000583, +0x21a00803, +0x3fbe0682, +0x3fe30102, +0x04000106, +0x21a00886, +0x04000603, +0x21a00903, +0x40803c02, +0x21a00982, +0x40800003, +0x04000184, +0x21a00a04, +0x40802202, +0x21a00a82, +0x42028005, +0x34208702, +0x21002282, +0x21a00804, +0x21a00886, +0x3fbf0782, +0x3f200102, +0x3fbe0102, +0x3fe30102, +0x21a00902, +0x40804003, +0x21a00983, +0x21a00a04, +0x40805a02, +0x21a00a82, +0x40800083, +0x21a00b83, +0x01a00c02, +0x01a00d83, +0x3420c282, +0x21a00e02, +0x34210283, +0x21a00f03, +0x34200284, +0x77400200, +0x3421c282, +0x21a00702, +0x34218283, +0x21a00083, +0x34214282, +0x21a00b02, +0x4200480c, +0x00200000, +0x1c010286, +0x34220284, +0x34220302, +0x0f608203, +0x5c024204, +0x3b81810b, +0x42013c02, +0x00200000, +0x18008185, +0x38808183, +0x3b814182, +0x21004e84, +0x4020007f, +0x35000100, +0x000004e0, +0x000002a0, +0x000002e8, +0x00000428, +0x00000360, +0x000002e8, +0x000004a0, +0x00000468, +0x000003c8, +0x00000360, +0x409ffe02, +0x30801203, +0x40800204, +0x3ec40085, +0x10009c09, +0x3ac10606, +0xb060c105, +0x4020007f, +0x4020007f, +0x20801203, +0x38810602, +0xb0408586, +0x28810602, +0x32004180, +0x34204702, +0x21a00382, +0x4020007f, +0x327fdc80, +0x409ffe02, +0x30801203, +0x40800204, +0x3ec40087, +0x40800405, +0x00200000, +0x40800606, +0x3ac10608, +0x3ac14609, +0x3ac1860a, +0xb060c107, +0x20801203, +0x41004003, +0x38810602, +0x4020007f, +0xb0408188, +0x4020007f, +0x28810602, +0x41201002, +0x38814603, +0x10009c09, +0xb060c109, +0x4020007f, +0x28814603, +0x41193f83, +0x38818602, +0x60ffc003, +0xb040818a, +0x28818602, +0x32003080, +0x409ffe02, +0x30801203, +0x40800204, +0x3ec40087, +0x41201008, +0x10009c14, +0x40800405, +0x3ac10609, +0x40800606, +0x3ac1460a, +0xb060c107, +0x3ac1860b, +0x20801203, +0x38810602, +0xb0408409, +0x28810602, +0x38814603, +0xb060c40a, +0x4020007f, +0x28814603, +0x41193f83, +0x38818602, +0x60ffc003, +0xb040818b, +0x28818602, +0x32002380, +0x409ffe02, +0x30801204, +0x40800205, +0x3ec40083, +0x40800406, +0x3ac14607, +0x3ac18608, +0xb0810103, +0x41004002, +0x20801204, +0x4020007f, +0x38814603, +0x10009c0b, +0xb060c107, +0x4020007f, +0x4020007f, +0x28814603, +0x38818602, +0x4020007f, +0x4020007f, +0xb0408588, +0x28818602, +0x4020007f, +0x32001780, +0x409ffe02, +0x1000640e, +0x40800204, +0x30801203, +0x40800405, +0x3ec40087, +0x40800606, +0x3ac10608, +0x3ac14609, +0x3ac1860a, +0xb060c107, +0x20801203, +0x413d8003, +0x38810602, +0x4020007f, +0x327fd780, +0x409ffe02, +0x10007f0c, +0x40800205, +0x30801204, +0x40800406, +0x3ec40083, +0x3ac14607, +0x3ac18608, +0xb0810103, +0x413d8002, +0x20801204, +0x38814603, +0x4020007f, +0x327feb80, +0x409ffe02, +0x30801203, +0x40800204, +0x3ec40087, +0x40800405, +0x1000650a, +0x40800606, +0x3ac10608, +0x3ac14609, +0x3ac1860a, +0xb060c107, +0x20801203, +0x38810602, +0xb0408588, +0x4020007f, +0x327fc980, +0x00400000, +0x40800003, +0x4020007f, +0x35000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, }; diff --git a/arch/powerpc/platforms/cell/spufs/spu_save_dump.h_shipped b/arch/powerpc/platforms/cell/spufs/spu_save_dump.h_shipped index 39e54003f1d..b9f81ac8a63 100644 --- a/arch/powerpc/platforms/cell/spufs/spu_save_dump.h_shipped +++ b/arch/powerpc/platforms/cell/spufs/spu_save_dump.h_shipped @@ -3,189 +3,741 @@ * Hex-dump auto generated from spu_save.c. * Do not edit! */ -static unsigned int spu_save_code[] __page_aligned = { -0x20805000, 0x20805201, 0x20805402, 0x20805603, -0x20805804, 0x20805a05, 0x20805c06, 0x20805e07, -0x20806008, 0x20806209, 0x2080640a, 0x2080660b, -0x2080680c, 0x20806a0d, 0x20806c0e, 0x20806e0f, -0x4201c003, 0x33800184, 0x1c010204, 0x40200000, -0x24000190, 0x24004191, 0x24008192, 0x2400c193, -0x141fc205, 0x23fffd84, 0x1c100183, 0x217ffb85, -0x40800000, 0x409ff801, 0x24000080, 0x24fd8081, -0x1cd80081, 0x33000180, 0x00000000, 0x00000000, -0x01a00182, 0x3ec00083, 0xb1c38103, 0x01a00204, -0x3ec10082, 0x4201400d, 0xb1c38202, 0x01a00583, -0x34218682, 0x3ed80684, 0xb0408184, 0x24218682, -0x01a00603, 0x00200000, 0x34214682, 0x3ed40684, -0xb0408184, 0x40800003, 0x24214682, 0x21a00083, -0x40800082, 0x21a00b02, 0x4020007f, 0x1000251e, -0x40a80002, 0x32800008, 0x4205c00c, 0x00200000, -0x40a0000b, 0x3f82070f, 0x4080020a, 0x40800709, -0x3fe3078f, 0x3fbf0783, 0x3f200183, 0x3fbe0183, -0x3fe30187, 0x18008387, 0x4205c002, 0x3ac30404, -0x1cffc489, 0x00200000, 0x18008403, 0x38830402, -0x4cffc486, 0x3ac28185, 0xb0408584, 0x28830402, -0x1c020408, 0x38828182, 0xb0408385, 0x1802c387, -0x28828182, 0x217ff886, 0x04000582, 0x32800007, -0x21a00802, 0x3fbf0705, 0x3f200285, 0x3fbe0285, -0x3fe30285, 0x21a00885, 0x04000603, 0x21a00903, -0x40803c02, 0x21a00982, 0x04000386, 0x21a00a06, -0x40801202, 0x21a00a82, 0x73000003, 0x24200683, -0x01a00404, 0x00200000, 0x34204682, 0x3ec40683, -0xb0408203, 0x24204682, 0x01a00783, 0x00200000, -0x3421c682, 0x3edc0684, 0xb0408184, 0x2421c682, -0x21a00806, 0x21a00885, 0x3fbf0784, 0x3f200204, -0x3fbe0204, 0x3fe30204, 0x21a00904, 0x40804002, -0x21a00982, 0x21a00a06, 0x40805a02, 0x21a00a82, -0x04000683, 0x21a00803, 0x21a00885, 0x21a00904, -0x40848002, 0x21a00982, 0x21a00a06, 0x40801002, -0x21a00a82, 0x21a00a06, 0x40806602, 0x00200000, -0x35800009, 0x21a00a82, 0x40800083, 0x21a00b83, -0x01a00c02, 0x01a00d83, 0x00003ffb, 0x40800003, -0x4020007f, 0x35000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, +static unsigned int spu_save_code[] __attribute__((__aligned__(128))) = { +0x20805000, +0x20805201, +0x20805402, +0x20805603, +0x20805804, +0x20805a05, +0x20805c06, +0x20805e07, +0x20806008, +0x20806209, +0x2080640a, +0x2080660b, +0x2080680c, +0x20806a0d, +0x20806c0e, +0x20806e0f, +0x4201c003, +0x33800184, +0x1c010204, +0x40200000, +0x24000190, +0x24004191, +0x24008192, +0x2400c193, +0x141fc205, +0x23fffd84, +0x1c100183, +0x217ffb85, +0x40800000, +0x409ff801, +0x24000080, +0x24fd8081, +0x1cd80081, +0x33000180, +0x00000000, +0x00000000, +0x01a00182, +0x3ec00083, +0xb1c38103, +0x01a00204, +0x3ec10082, +0x4201400d, +0xb1c38202, +0x01a00583, +0x34218682, +0x3ed80684, +0xb0408184, +0x24218682, +0x01a00603, +0x00200000, +0x34214682, +0x3ed40684, +0xb0408184, +0x40800003, +0x24214682, +0x21a00083, +0x40800082, +0x21a00b02, +0x4020007f, +0x1000251e, +0x42a00002, +0x32800008, +0x4205c00c, +0x00200000, +0x40a0000b, +0x3f82070f, +0x4080020a, +0x40800709, +0x3fe3078f, +0x3fbf0783, +0x3f200183, +0x3fbe0183, +0x3fe30187, +0x18008387, +0x4205c002, +0x3ac30404, +0x1cffc489, +0x00200000, +0x18008403, +0x38830402, +0x4cffc486, +0x3ac28185, +0xb0408584, +0x28830402, +0x1c020408, +0x38828182, +0xb0408385, +0x1802c387, +0x28828182, +0x217ff886, +0x04000582, +0x32800007, +0x21a00802, +0x3fbf0705, +0x3f200285, +0x3fbe0285, +0x3fe30285, +0x21a00885, +0x04000603, +0x21a00903, +0x40803c02, +0x21a00982, +0x04000386, +0x21a00a06, +0x40801202, +0x21a00a82, +0x73000003, +0x24200683, +0x01a00404, +0x00200000, +0x34204682, +0x3ec40683, +0xb0408203, +0x24204682, +0x01a00783, +0x00200000, +0x3421c682, +0x3edc0684, +0xb0408184, +0x2421c682, +0x21a00806, +0x21a00885, +0x3fbf0784, +0x3f200204, +0x3fbe0204, +0x3fe30204, +0x21a00904, +0x40804002, +0x21a00982, +0x21a00a06, +0x40805a02, +0x21a00a82, +0x04000683, +0x21a00803, +0x21a00885, +0x21a00904, +0x40848002, +0x21a00982, +0x21a00a06, +0x40801002, +0x21a00a82, +0x21a00a06, +0x40806602, +0x00200000, +0x35800009, +0x21a00a82, +0x40800083, +0x21a00b83, +0x01a00c02, +0x01a00d83, +0x00003ffb, +0x40800003, +0x4020007f, +0x35000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, }; diff --git a/include/asm-powerpc/spu_csa.h b/include/asm-powerpc/spu_csa.h index ba18d7d4dde..964c2d38ccb 100644 --- a/include/asm-powerpc/spu_csa.h +++ b/include/asm-powerpc/spu_csa.h @@ -86,10 +86,18 @@ struct spu_lscsa { struct spu_reg128 event_mask; struct spu_reg128 srr0; struct spu_reg128 stopped_status; - struct spu_reg128 pad[119]; /* 'ls' must be page-aligned. */ - unsigned char ls[LS_SIZE]; + + /* + * 'ls' must be page-aligned on all configurations. + * Since we don't want to rely on having the spu-gcc + * installed to build the kernel and this structure + * is used in the SPU-side code, make it 64k-page + * aligned for now. + */ + unsigned char ls[LS_SIZE] __attribute__((aligned(65536))); }; +#ifndef __SPU__ /* * struct spu_problem_collapsed - condensed problem state area, w/o pads. */ @@ -250,6 +258,7 @@ extern int spu_restore(struct spu_state *new, struct spu *spu); extern int spu_switch(struct spu_state *prev, struct spu_state *new, struct spu *spu); +#endif /* !__SPU__ */ #endif /* __KERNEL__ */ #endif /* !__ASSEMBLY__ */ #endif /* _SPU_CSA_H_ */ -- cgit v1.2.3 From 0aa8d15b01881ccaab5f2fb31eef33ced97ccb5f Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Mon, 19 Jun 2006 15:07:40 -0500 Subject: [POWERPC] pseries: Print PCI slot location code on failure The PCI error recovery code will printk diagnostic info when a PCI error event occurs. Change the messages to include the slot location code, which is how most sysadmins will know the device. Signed-off-by: Linas Vepstas Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/pseries/eeh_driver.c | 35 ++++++++++++++++++----------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c index 4d45347afab..0ec9a5445b9 100644 --- a/arch/powerpc/platforms/pseries/eeh_driver.c +++ b/arch/powerpc/platforms/pseries/eeh_driver.c @@ -261,16 +261,22 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event) struct pci_bus *frozen_bus; int rc = 0; enum pci_ers_result result = PCI_ERS_RESULT_NONE; - const char *pci_str, *drv_str; + const char *location, *pci_str, *drv_str; frozen_dn = find_device_pe(event->dn); frozen_bus = pcibios_find_pci_bus(frozen_dn); if (!frozen_dn) { - printk(KERN_ERR "EEH: Error: Cannot find partition endpoint for %s\n", - pci_name(event->dev)); + + location = (char *) get_property(event->dn, "ibm,loc-code", NULL); + location = location ? location : "unknown"; + printk(KERN_ERR "EEH: Error: Cannot find partition endpoint " + "for location=%s pci addr=%s\n", + location, pci_name(event->dev)); return NULL; } + location = (char *) get_property(frozen_dn, "ibm,loc-code", NULL); + location = location ? location : "unknown"; /* There are two different styles for coming up with the PE. * In the old style, it was the highest EEH-capable device @@ -282,8 +288,9 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event) frozen_bus = pcibios_find_pci_bus (frozen_dn->parent); if (!frozen_bus) { - printk(KERN_ERR "EEH: Cannot find PCI bus for %s\n", - frozen_dn->full_name); + printk(KERN_ERR "EEH: Cannot find PCI bus " + "for location=%s dn=%s\n", + location, frozen_dn->full_name); return NULL; } @@ -318,8 +325,9 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event) eeh_slot_error_detail(frozen_pdn, 1 /* Temporary Error */); printk(KERN_WARNING - "EEH: This PCI device has failed %d times since last reboot: %s - %s\n", - frozen_pdn->eeh_freeze_count, drv_str, pci_str); + "EEH: This PCI device has failed %d times since last reboot: " + "location=%s driver=%s pci addr=%s\n", + frozen_pdn->eeh_freeze_count, location, drv_str, pci_str); /* Walk the various device drivers attached to this slot through * a reset sequence, giving each an opportunity to do what it needs @@ -368,17 +376,18 @@ excess_failures: * due to actual, failed cards. */ printk(KERN_ERR - "EEH: PCI device %s - %s has failed %d times \n" - "and has been permanently disabled. Please try reseating\n" - "this device or replacing it.\n", - drv_str, pci_str, frozen_pdn->eeh_freeze_count); + "EEH: PCI device at location=%s driver=%s pci addr=%s \n" + "has failed %d times and has been permanently disabled. \n" + "Please try reseating this device or replacing it.\n", + location, drv_str, pci_str, frozen_pdn->eeh_freeze_count); goto perm_error; hard_fail: printk(KERN_ERR - "EEH: Unable to recover from failure of PCI device %s - %s\n" + "EEH: Unable to recover from failure of PCI device " + "at location=%s driver=%s pci addr=%s \n" "Please try reseating this device or replacing it.\n", - drv_str, pci_str); + location, drv_str, pci_str); perm_error: eeh_slot_error_detail(frozen_pdn, 2 /* Permanent Error */); -- cgit v1.2.3 From 868ea0c9256b658b14603e1ad7361b81b92ccacd Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Tue, 20 Jun 2006 14:15:36 -0700 Subject: [POWERPC] mpic: add support for serial mode interrupts On Tue, Jun 20, 2006 at 02:01:26PM +1000, Benjamin Herrenschmidt wrote: > On Mon, 2006-06-19 at 13:08 -0700, Mark A. Greer wrote: > > MPC10x-style interrupt controllers have a serial mode that allows > > several interrupts to be clocked in through one INT signal. > > > > This patch adds the software support for that mode. > > You hard code the clock ratio... why not add a separate call to be > called after mpic_init, > something like mpic_set_serial_int(int mpic, int enable, int > clock_ratio) ? How's this? -- MPC10x-style interrupt controllers have a serial mode that allows several interrupts to be clocked in through one INT signal. This patch adds the software support for that mode. Signed-off-by: Mark A. Greer -- arch/powerpc/sysdev/mpic.c | 20 ++++++++++++++++++++ include/asm-powerpc/mpic.h | 10 ++++++++++ 2 files changed, 30 insertions(+) -- Signed-off-by: Paul Mackerras --- arch/powerpc/sysdev/mpic.c | 20 ++++++++++++++++++++ include/asm-powerpc/mpic.h | 10 ++++++++++ 2 files changed, 30 insertions(+) diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 7dcdfcb3c98..bffe50d02c9 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -829,7 +829,27 @@ void __init mpic_init(struct mpic *mpic) mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0); } +void __init mpic_set_clk_ratio(struct mpic *mpic, u32 clock_ratio) +{ + u32 v; + + v = mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1); + v &= ~MPIC_GREG_GLOBAL_CONF_1_CLK_RATIO_MASK; + v |= MPIC_GREG_GLOBAL_CONF_1_CLK_RATIO(clock_ratio); + mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1, v); +} +void __init mpic_set_serial_int(struct mpic *mpic, int enable) +{ + u32 v; + + v = mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1); + if (enable) + v |= MPIC_GREG_GLOBAL_CONF_1_SIE; + else + v &= ~MPIC_GREG_GLOBAL_CONF_1_SIE; + mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1, v); +} void mpic_irq_set_priority(unsigned int irq, unsigned int pri) { diff --git a/include/asm-powerpc/mpic.h b/include/asm-powerpc/mpic.h index 6b9e78142f4..f0d22ac34b9 100644 --- a/include/asm-powerpc/mpic.h +++ b/include/asm-powerpc/mpic.h @@ -22,6 +22,10 @@ #define MPIC_GREG_GCONF_8259_PTHROU_DIS 0x20000000 #define MPIC_GREG_GCONF_BASE_MASK 0x000fffff #define MPIC_GREG_GLOBAL_CONF_1 0x00030 +#define MPIC_GREG_GLOBAL_CONF_1_SIE 0x08000000 +#define MPIC_GREG_GLOBAL_CONF_1_CLK_RATIO_MASK 0x70000000 +#define MPIC_GREG_GLOBAL_CONF_1_CLK_RATIO(r) \ + (((r) << 28) & MPIC_GREG_GLOBAL_CONF_1_CLK_RATIO_MASK) #define MPIC_GREG_VENDOR_0 0x00040 #define MPIC_GREG_VENDOR_1 0x00050 #define MPIC_GREG_VENDOR_2 0x00060 @@ -284,6 +288,12 @@ extern int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs); /* This one gets to the primary mpic */ extern int mpic_get_irq(struct pt_regs *regs); +/* Set the EPIC clock ratio */ +void mpic_set_clk_ratio(struct mpic *mpic, u32 clock_ratio); + +/* Enable/Disable EPIC serial interrupt mode */ +void mpic_set_serial_int(struct mpic *mpic, int enable); + /* global mpic for pSeries */ extern struct mpic *pSeries_mpic; -- cgit v1.2.3 From 72abd54035a3d71fd8f02596e659257e8bba16ca Mon Sep 17 00:00:00 2001 From: Andreas Schwab Date: Mon, 19 Jun 2006 22:45:04 +0200 Subject: [POWERPC] Unify ppc syscall tables Avoid duplication of the syscall table for the cell platform. Based on an idea from David Woodhouse. Signed-off-by: Andreas Schwab Acked-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/systbl.S | 311 +-------------------------- arch/powerpc/platforms/cell/spu_callbacks.c | 314 ++-------------------------- include/asm-powerpc/systbl.h | 306 +++++++++++++++++++++++++++ 3 files changed, 324 insertions(+), 607 deletions(-) create mode 100644 include/asm-powerpc/systbl.h diff --git a/arch/powerpc/kernel/systbl.S b/arch/powerpc/kernel/systbl.S index 26ed1f5ef16..ee75ccf1a80 100644 --- a/arch/powerpc/kernel/systbl.S +++ b/arch/powerpc/kernel/systbl.S @@ -32,6 +32,10 @@ #define SYS32ONLY(func) .long sys_##func #define SYSX(f, f3264, f32) .long f32 #endif +#define SYSCALL_SPU(func) SYSCALL(func) +#define COMPAT_SYS_SPU(func) COMPAT_SYS(func) +#define PPC_SYS_SPU(func) PPC_SYS(func) +#define SYSX_SPU(f, f3264, f32) SYSX(f, f3264, f32) #ifdef CONFIG_PPC64 #define sys_sigpending sys_ni_syscall @@ -39,309 +43,4 @@ #endif _GLOBAL(sys_call_table) -SYSCALL(restart_syscall) -SYSCALL(exit) -PPC_SYS(fork) -SYSCALL(read) -SYSCALL(write) -COMPAT_SYS(open) -SYSCALL(close) -COMPAT_SYS(waitpid) -COMPAT_SYS(creat) -SYSCALL(link) -SYSCALL(unlink) -COMPAT_SYS(execve) -SYSCALL(chdir) -COMPAT_SYS(time) -SYSCALL(mknod) -SYSCALL(chmod) -SYSCALL(lchown) -SYSCALL(ni_syscall) -OLDSYS(stat) -SYSX(sys_lseek,ppc32_lseek,sys_lseek) -SYSCALL(getpid) -COMPAT_SYS(mount) -SYSX(sys_ni_syscall,sys_oldumount,sys_oldumount) -SYSCALL(setuid) -SYSCALL(getuid) -COMPAT_SYS(stime) -COMPAT_SYS(ptrace) -SYSCALL(alarm) -OLDSYS(fstat) -COMPAT_SYS(pause) -COMPAT_SYS(utime) -SYSCALL(ni_syscall) -SYSCALL(ni_syscall) -COMPAT_SYS(access) -COMPAT_SYS(nice) -SYSCALL(ni_syscall) -SYSCALL(sync) -COMPAT_SYS(kill) -SYSCALL(rename) -COMPAT_SYS(mkdir) -SYSCALL(rmdir) -SYSCALL(dup) -SYSCALL(pipe) -COMPAT_SYS(times) -SYSCALL(ni_syscall) -SYSCALL(brk) -SYSCALL(setgid) -SYSCALL(getgid) -SYSCALL(signal) -SYSCALL(geteuid) -SYSCALL(getegid) -SYSCALL(acct) -SYSCALL(umount) -SYSCALL(ni_syscall) -COMPAT_SYS(ioctl) -COMPAT_SYS(fcntl) -SYSCALL(ni_syscall) -COMPAT_SYS(setpgid) -SYSCALL(ni_syscall) -SYSX(sys_ni_syscall,sys_olduname, sys_olduname) -COMPAT_SYS(umask) -SYSCALL(chroot) -SYSCALL(ustat) -SYSCALL(dup2) -SYSCALL(getppid) -SYSCALL(getpgrp) -SYSCALL(setsid) -SYS32ONLY(sigaction) -SYSCALL(sgetmask) -COMPAT_SYS(ssetmask) -SYSCALL(setreuid) -SYSCALL(setregid) -SYS32ONLY(sigsuspend) -COMPAT_SYS(sigpending) -COMPAT_SYS(sethostname) -COMPAT_SYS(setrlimit) -COMPAT_SYS(old_getrlimit) -COMPAT_SYS(getrusage) -COMPAT_SYS(gettimeofday) -COMPAT_SYS(settimeofday) -COMPAT_SYS(getgroups) -COMPAT_SYS(setgroups) -SYSX(sys_ni_syscall,sys_ni_syscall,ppc_select) -SYSCALL(symlink) -OLDSYS(lstat) -COMPAT_SYS(readlink) -SYSCALL(uselib) -SYSCALL(swapon) -SYSCALL(reboot) -SYSX(sys_ni_syscall,old32_readdir,old_readdir) -SYSCALL(mmap) -SYSCALL(munmap) -SYSCALL(truncate) -SYSCALL(ftruncate) -SYSCALL(fchmod) -SYSCALL(fchown) -COMPAT_SYS(getpriority) -COMPAT_SYS(setpriority) -SYSCALL(ni_syscall) -COMPAT_SYS(statfs) -COMPAT_SYS(fstatfs) -SYSCALL(ni_syscall) -COMPAT_SYS(socketcall) -COMPAT_SYS(syslog) -COMPAT_SYS(setitimer) -COMPAT_SYS(getitimer) -COMPAT_SYS(newstat) -COMPAT_SYS(newlstat) -COMPAT_SYS(newfstat) -SYSX(sys_ni_syscall,sys_uname,sys_uname) -SYSCALL(ni_syscall) -SYSCALL(vhangup) -SYSCALL(ni_syscall) -SYSCALL(ni_syscall) -COMPAT_SYS(wait4) -SYSCALL(swapoff) -COMPAT_SYS(sysinfo) -COMPAT_SYS(ipc) -SYSCALL(fsync) -SYS32ONLY(sigreturn) -PPC_SYS(clone) -COMPAT_SYS(setdomainname) -PPC_SYS(newuname) -SYSCALL(ni_syscall) -COMPAT_SYS(adjtimex) -SYSCALL(mprotect) -SYSX(sys_ni_syscall,compat_sys_sigprocmask,sys_sigprocmask) -SYSCALL(ni_syscall) -SYSCALL(init_module) -SYSCALL(delete_module) -SYSCALL(ni_syscall) -SYSCALL(quotactl) -COMPAT_SYS(getpgid) -SYSCALL(fchdir) -SYSCALL(bdflush) -COMPAT_SYS(sysfs) -SYSX(ppc64_personality,ppc64_personality,sys_personality) -SYSCALL(ni_syscall) -SYSCALL(setfsuid) -SYSCALL(setfsgid) -SYSCALL(llseek) -COMPAT_SYS(getdents) -SYSX(sys_select,ppc32_select,ppc_select) -SYSCALL(flock) -SYSCALL(msync) -COMPAT_SYS(readv) -COMPAT_SYS(writev) -COMPAT_SYS(getsid) -SYSCALL(fdatasync) -COMPAT_SYS(sysctl) -SYSCALL(mlock) -SYSCALL(munlock) -SYSCALL(mlockall) -SYSCALL(munlockall) -COMPAT_SYS(sched_setparam) -COMPAT_SYS(sched_getparam) -COMPAT_SYS(sched_setscheduler) -COMPAT_SYS(sched_getscheduler) -SYSCALL(sched_yield) -COMPAT_SYS(sched_get_priority_max) -COMPAT_SYS(sched_get_priority_min) -COMPAT_SYS(sched_rr_get_interval) -COMPAT_SYS(nanosleep) -SYSCALL(mremap) -SYSCALL(setresuid) -SYSCALL(getresuid) -SYSCALL(ni_syscall) -SYSCALL(poll) -COMPAT_SYS(nfsservctl) -SYSCALL(setresgid) -SYSCALL(getresgid) -COMPAT_SYS(prctl) -COMPAT_SYS(rt_sigreturn) -COMPAT_SYS(rt_sigaction) -COMPAT_SYS(rt_sigprocmask) -COMPAT_SYS(rt_sigpending) -COMPAT_SYS(rt_sigtimedwait) -COMPAT_SYS(rt_sigqueueinfo) -COMPAT_SYS(rt_sigsuspend) -COMPAT_SYS(pread64) -COMPAT_SYS(pwrite64) -SYSCALL(chown) -SYSCALL(getcwd) -SYSCALL(capget) -SYSCALL(capset) -COMPAT_SYS(sigaltstack) -SYSX(sys_sendfile64,compat_sys_sendfile,sys_sendfile) -SYSCALL(ni_syscall) -SYSCALL(ni_syscall) -PPC_SYS(vfork) -COMPAT_SYS(getrlimit) -COMPAT_SYS(readahead) -SYS32ONLY(mmap2) -SYS32ONLY(truncate64) -SYS32ONLY(ftruncate64) -SYSX(sys_ni_syscall,sys_stat64,sys_stat64) -SYSX(sys_ni_syscall,sys_lstat64,sys_lstat64) -SYSX(sys_ni_syscall,sys_fstat64,sys_fstat64) -SYSCALL(pciconfig_read) -SYSCALL(pciconfig_write) -SYSCALL(pciconfig_iobase) -SYSCALL(ni_syscall) -SYSCALL(getdents64) -SYSCALL(pivot_root) -SYSX(sys_ni_syscall,compat_sys_fcntl64,sys_fcntl64) -SYSCALL(madvise) -SYSCALL(mincore) -SYSCALL(gettid) -SYSCALL(tkill) -SYSCALL(setxattr) -SYSCALL(lsetxattr) -SYSCALL(fsetxattr) -SYSCALL(getxattr) -SYSCALL(lgetxattr) -SYSCALL(fgetxattr) -SYSCALL(listxattr) -SYSCALL(llistxattr) -SYSCALL(flistxattr) -SYSCALL(removexattr) -SYSCALL(lremovexattr) -SYSCALL(fremovexattr) -COMPAT_SYS(futex) -COMPAT_SYS(sched_setaffinity) -COMPAT_SYS(sched_getaffinity) -SYSCALL(ni_syscall) -SYSCALL(ni_syscall) -SYS32ONLY(sendfile64) -COMPAT_SYS(io_setup) -SYSCALL(io_destroy) -COMPAT_SYS(io_getevents) -COMPAT_SYS(io_submit) -SYSCALL(io_cancel) -SYSCALL(set_tid_address) -SYSX(sys_fadvise64,ppc32_fadvise64,sys_fadvise64) -SYSCALL(exit_group) -SYSX(sys_lookup_dcookie,ppc32_lookup_dcookie,sys_lookup_dcookie) -SYSCALL(epoll_create) -SYSCALL(epoll_ctl) -SYSCALL(epoll_wait) -SYSCALL(remap_file_pages) -SYSX(sys_timer_create,compat_sys_timer_create,sys_timer_create) -COMPAT_SYS(timer_settime) -COMPAT_SYS(timer_gettime) -SYSCALL(timer_getoverrun) -SYSCALL(timer_delete) -COMPAT_SYS(clock_settime) -COMPAT_SYS(clock_gettime) -COMPAT_SYS(clock_getres) -COMPAT_SYS(clock_nanosleep) -SYSX(ppc64_swapcontext,ppc32_swapcontext,ppc_swapcontext) -COMPAT_SYS(tgkill) -COMPAT_SYS(utimes) -COMPAT_SYS(statfs64) -COMPAT_SYS(fstatfs64) -SYSX(sys_ni_syscall, ppc_fadvise64_64, ppc_fadvise64_64) -PPC_SYS(rtas) -OLDSYS(debug_setcontext) -SYSCALL(ni_syscall) -SYSCALL(ni_syscall) -COMPAT_SYS(mbind) -COMPAT_SYS(get_mempolicy) -COMPAT_SYS(set_mempolicy) -COMPAT_SYS(mq_open) -SYSCALL(mq_unlink) -COMPAT_SYS(mq_timedsend) -COMPAT_SYS(mq_timedreceive) -COMPAT_SYS(mq_notify) -COMPAT_SYS(mq_getsetattr) -COMPAT_SYS(kexec_load) -COMPAT_SYS(add_key) -COMPAT_SYS(request_key) -COMPAT_SYS(keyctl) -COMPAT_SYS(waitid) -COMPAT_SYS(ioprio_set) -COMPAT_SYS(ioprio_get) -SYSCALL(inotify_init) -SYSCALL(inotify_add_watch) -SYSCALL(inotify_rm_watch) -SYSCALL(spu_run) -SYSCALL(spu_create) -COMPAT_SYS(pselect6) -COMPAT_SYS(ppoll) -SYSCALL(unshare) -SYSCALL(splice) -SYSCALL(tee) -SYSCALL(vmsplice) -COMPAT_SYS(openat) -SYSCALL(mkdirat) -SYSCALL(mknodat) -SYSCALL(fchownat) -COMPAT_SYS(futimesat) -SYSX(sys_newfstatat, sys_fstatat64, sys_fstatat64) -SYSCALL(unlinkat) -SYSCALL(renameat) -SYSCALL(linkat) -SYSCALL(symlinkat) -SYSCALL(readlinkat) -SYSCALL(fchmodat) -SYSCALL(faccessat) -COMPAT_SYS(get_robust_list) -COMPAT_SYS(set_robust_list) - -/* - * please add new calls to arch/powerpc/platforms/cell/spu_callbacks.c - * as well when appropriate. - */ +#include diff --git a/arch/powerpc/platforms/cell/spu_callbacks.c b/arch/powerpc/platforms/cell/spu_callbacks.c index b47fcc5ddb7..47ec3be3edc 100644 --- a/arch/powerpc/platforms/cell/spu_callbacks.c +++ b/arch/powerpc/platforms/cell/spu_callbacks.c @@ -34,307 +34,19 @@ */ void *spu_syscall_table[] = { - [__NR_restart_syscall] sys_ni_syscall, /* sys_restart_syscall */ - [__NR_exit] sys_ni_syscall, /* sys_exit */ - [__NR_fork] sys_ni_syscall, /* ppc_fork */ - [__NR_read] sys_read, - [__NR_write] sys_write, - [__NR_open] sys_open, - [__NR_close] sys_close, - [__NR_waitpid] sys_waitpid, - [__NR_creat] sys_creat, - [__NR_link] sys_link, - [__NR_unlink] sys_unlink, - [__NR_execve] sys_ni_syscall, /* sys_execve */ - [__NR_chdir] sys_chdir, - [__NR_time] sys_time, - [__NR_mknod] sys_mknod, - [__NR_chmod] sys_chmod, - [__NR_lchown] sys_lchown, - [__NR_break] sys_ni_syscall, - [__NR_oldstat] sys_ni_syscall, - [__NR_lseek] sys_lseek, - [__NR_getpid] sys_getpid, - [__NR_mount] sys_ni_syscall, /* sys_mount */ - [__NR_umount] sys_ni_syscall, - [__NR_setuid] sys_setuid, - [__NR_getuid] sys_getuid, - [__NR_stime] sys_stime, - [__NR_ptrace] sys_ni_syscall, /* sys_ptrace */ - [__NR_alarm] sys_alarm, - [__NR_oldfstat] sys_ni_syscall, - [__NR_pause] sys_ni_syscall, /* sys_pause */ - [__NR_utime] sys_ni_syscall, /* sys_utime */ - [__NR_stty] sys_ni_syscall, - [__NR_gtty] sys_ni_syscall, - [__NR_access] sys_access, - [__NR_nice] sys_nice, - [__NR_ftime] sys_ni_syscall, - [__NR_sync] sys_sync, - [__NR_kill] sys_kill, - [__NR_rename] sys_rename, - [__NR_mkdir] sys_mkdir, - [__NR_rmdir] sys_rmdir, - [__NR_dup] sys_dup, - [__NR_pipe] sys_pipe, - [__NR_times] sys_times, - [__NR_prof] sys_ni_syscall, - [__NR_brk] sys_brk, - [__NR_setgid] sys_setgid, - [__NR_getgid] sys_getgid, - [__NR_signal] sys_ni_syscall, /* sys_signal */ - [__NR_geteuid] sys_geteuid, - [__NR_getegid] sys_getegid, - [__NR_acct] sys_ni_syscall, /* sys_acct */ - [__NR_umount2] sys_ni_syscall, /* sys_umount */ - [__NR_lock] sys_ni_syscall, - [__NR_ioctl] sys_ioctl, - [__NR_fcntl] sys_fcntl, - [__NR_mpx] sys_ni_syscall, - [__NR_setpgid] sys_setpgid, - [__NR_ulimit] sys_ni_syscall, - [__NR_oldolduname] sys_ni_syscall, - [__NR_umask] sys_umask, - [__NR_chroot] sys_chroot, - [__NR_ustat] sys_ni_syscall, /* sys_ustat */ - [__NR_dup2] sys_dup2, - [__NR_getppid] sys_getppid, - [__NR_getpgrp] sys_getpgrp, - [__NR_setsid] sys_setsid, - [__NR_sigaction] sys_ni_syscall, - [__NR_sgetmask] sys_sgetmask, - [__NR_ssetmask] sys_ssetmask, - [__NR_setreuid] sys_setreuid, - [__NR_setregid] sys_setregid, - [__NR_sigsuspend] sys_ni_syscall, - [__NR_sigpending] sys_ni_syscall, - [__NR_sethostname] sys_sethostname, - [__NR_setrlimit] sys_setrlimit, - [__NR_getrlimit] sys_ni_syscall, - [__NR_getrusage] sys_getrusage, - [__NR_gettimeofday] sys_gettimeofday, - [__NR_settimeofday] sys_settimeofday, - [__NR_getgroups] sys_getgroups, - [__NR_setgroups] sys_setgroups, - [__NR_select] sys_ni_syscall, - [__NR_symlink] sys_symlink, - [__NR_oldlstat] sys_ni_syscall, - [__NR_readlink] sys_readlink, - [__NR_uselib] sys_ni_syscall, /* sys_uselib */ - [__NR_swapon] sys_ni_syscall, /* sys_swapon */ - [__NR_reboot] sys_ni_syscall, /* sys_reboot */ - [__NR_readdir] sys_ni_syscall, - [__NR_mmap] sys_mmap, - [__NR_munmap] sys_munmap, - [__NR_truncate] sys_truncate, - [__NR_ftruncate] sys_ftruncate, - [__NR_fchmod] sys_fchmod, - [__NR_fchown] sys_fchown, - [__NR_getpriority] sys_getpriority, - [__NR_setpriority] sys_setpriority, - [__NR_profil] sys_ni_syscall, - [__NR_statfs] sys_ni_syscall, /* sys_statfs */ - [__NR_fstatfs] sys_ni_syscall, /* sys_fstatfs */ - [__NR_ioperm] sys_ni_syscall, - [__NR_socketcall] sys_socketcall, - [__NR_syslog] sys_syslog, - [__NR_setitimer] sys_setitimer, - [__NR_getitimer] sys_getitimer, - [__NR_stat] sys_newstat, - [__NR_lstat] sys_newlstat, - [__NR_fstat] sys_newfstat, - [__NR_olduname] sys_ni_syscall, - [__NR_iopl] sys_ni_syscall, - [__NR_vhangup] sys_vhangup, - [__NR_idle] sys_ni_syscall, - [__NR_vm86] sys_ni_syscall, - [__NR_wait4] sys_wait4, - [__NR_swapoff] sys_ni_syscall, /* sys_swapoff */ - [__NR_sysinfo] sys_sysinfo, - [__NR_ipc] sys_ni_syscall, /* sys_ipc */ - [__NR_fsync] sys_fsync, - [__NR_sigreturn] sys_ni_syscall, - [__NR_clone] sys_ni_syscall, /* ppc_clone */ - [__NR_setdomainname] sys_setdomainname, - [__NR_uname] ppc_newuname, - [__NR_modify_ldt] sys_ni_syscall, - [__NR_adjtimex] sys_adjtimex, - [__NR_mprotect] sys_mprotect, - [__NR_sigprocmask] sys_ni_syscall, - [__NR_create_module] sys_ni_syscall, - [__NR_init_module] sys_ni_syscall, /* sys_init_module */ - [__NR_delete_module] sys_ni_syscall, /* sys_delete_module */ - [__NR_get_kernel_syms] sys_ni_syscall, - [__NR_quotactl] sys_ni_syscall, /* sys_quotactl */ - [__NR_getpgid] sys_getpgid, - [__NR_fchdir] sys_fchdir, - [__NR_bdflush] sys_bdflush, - [__NR_sysfs] sys_ni_syscall, /* sys_sysfs */ - [__NR_personality] ppc64_personality, - [__NR_afs_syscall] sys_ni_syscall, - [__NR_setfsuid] sys_setfsuid, - [__NR_setfsgid] sys_setfsgid, - [__NR__llseek] sys_llseek, - [__NR_getdents] sys_getdents, - [__NR__newselect] sys_select, - [__NR_flock] sys_flock, - [__NR_msync] sys_msync, - [__NR_readv] sys_readv, - [__NR_writev] sys_writev, - [__NR_getsid] sys_getsid, - [__NR_fdatasync] sys_fdatasync, - [__NR__sysctl] sys_ni_syscall, /* sys_sysctl */ - [__NR_mlock] sys_mlock, - [__NR_munlock] sys_munlock, - [__NR_mlockall] sys_mlockall, - [__NR_munlockall] sys_munlockall, - [__NR_sched_setparam] sys_sched_setparam, - [__NR_sched_getparam] sys_sched_getparam, - [__NR_sched_setscheduler] sys_sched_setscheduler, - [__NR_sched_getscheduler] sys_sched_getscheduler, - [__NR_sched_yield] sys_sched_yield, - [__NR_sched_get_priority_max] sys_sched_get_priority_max, - [__NR_sched_get_priority_min] sys_sched_get_priority_min, - [__NR_sched_rr_get_interval] sys_sched_rr_get_interval, - [__NR_nanosleep] sys_nanosleep, - [__NR_mremap] sys_mremap, - [__NR_setresuid] sys_setresuid, - [__NR_getresuid] sys_getresuid, - [__NR_query_module] sys_ni_syscall, - [__NR_poll] sys_poll, - [__NR_nfsservctl] sys_ni_syscall, /* sys_nfsservctl */ - [__NR_setresgid] sys_setresgid, - [__NR_getresgid] sys_getresgid, - [__NR_prctl] sys_prctl, - [__NR_rt_sigreturn] sys_ni_syscall, /* ppc64_rt_sigreturn */ - [__NR_rt_sigaction] sys_ni_syscall, /* sys_rt_sigaction */ - [__NR_rt_sigprocmask] sys_ni_syscall, /* sys_rt_sigprocmask */ - [__NR_rt_sigpending] sys_ni_syscall, /* sys_rt_sigpending */ - [__NR_rt_sigtimedwait] sys_ni_syscall, /* sys_rt_sigtimedwait */ - [__NR_rt_sigqueueinfo] sys_ni_syscall, /* sys_rt_sigqueueinfo */ - [__NR_rt_sigsuspend] sys_ni_syscall, /* sys_rt_sigsuspend */ - [__NR_pread64] sys_pread64, - [__NR_pwrite64] sys_pwrite64, - [__NR_chown] sys_chown, - [__NR_getcwd] sys_getcwd, - [__NR_capget] sys_capget, - [__NR_capset] sys_capset, - [__NR_sigaltstack] sys_ni_syscall, /* sys_sigaltstack */ - [__NR_sendfile] sys_sendfile64, - [__NR_getpmsg] sys_ni_syscall, - [__NR_putpmsg] sys_ni_syscall, - [__NR_vfork] sys_ni_syscall, /* ppc_vfork */ - [__NR_ugetrlimit] sys_getrlimit, - [__NR_readahead] sys_readahead, - [192] sys_ni_syscall, - [193] sys_ni_syscall, - [194] sys_ni_syscall, - [195] sys_ni_syscall, - [196] sys_ni_syscall, - [197] sys_ni_syscall, - [__NR_pciconfig_read] sys_ni_syscall, /* sys_pciconfig_read */ - [__NR_pciconfig_write] sys_ni_syscall, /* sys_pciconfig_write */ - [__NR_pciconfig_iobase] sys_ni_syscall, /* sys_pciconfig_iobase */ - [__NR_multiplexer] sys_ni_syscall, - [__NR_getdents64] sys_getdents64, - [__NR_pivot_root] sys_pivot_root, - [204] sys_ni_syscall, - [__NR_madvise] sys_madvise, - [__NR_mincore] sys_mincore, - [__NR_gettid] sys_gettid, - [__NR_tkill] sys_tkill, - [__NR_setxattr] sys_setxattr, - [__NR_lsetxattr] sys_lsetxattr, - [__NR_fsetxattr] sys_fsetxattr, - [__NR_getxattr] sys_getxattr, - [__NR_lgetxattr] sys_lgetxattr, - [__NR_fgetxattr] sys_fgetxattr, - [__NR_listxattr] sys_listxattr, - [__NR_llistxattr] sys_llistxattr, - [__NR_flistxattr] sys_flistxattr, - [__NR_removexattr] sys_removexattr, - [__NR_lremovexattr] sys_lremovexattr, - [__NR_fremovexattr] sys_fremovexattr, - [__NR_futex] sys_futex, - [__NR_sched_setaffinity] sys_sched_setaffinity, - [__NR_sched_getaffinity] sys_sched_getaffinity, - [224] sys_ni_syscall, - [__NR_tuxcall] sys_ni_syscall, - [226] sys_ni_syscall, - [__NR_io_setup] sys_io_setup, - [__NR_io_destroy] sys_io_destroy, - [__NR_io_getevents] sys_io_getevents, - [__NR_io_submit] sys_io_submit, - [__NR_io_cancel] sys_io_cancel, - [__NR_set_tid_address] sys_ni_syscall, /* sys_set_tid_address */ - [__NR_fadvise64] sys_fadvise64, - [__NR_exit_group] sys_ni_syscall, /* sys_exit_group */ - [__NR_lookup_dcookie] sys_ni_syscall, /* sys_lookup_dcookie */ - [__NR_epoll_create] sys_epoll_create, - [__NR_epoll_ctl] sys_epoll_ctl, - [__NR_epoll_wait] sys_epoll_wait, - [__NR_remap_file_pages] sys_remap_file_pages, - [__NR_timer_create] sys_timer_create, - [__NR_timer_settime] sys_timer_settime, - [__NR_timer_gettime] sys_timer_gettime, - [__NR_timer_getoverrun] sys_timer_getoverrun, - [__NR_timer_delete] sys_timer_delete, - [__NR_clock_settime] sys_clock_settime, - [__NR_clock_gettime] sys_clock_gettime, - [__NR_clock_getres] sys_clock_getres, - [__NR_clock_nanosleep] sys_clock_nanosleep, - [__NR_swapcontext] sys_ni_syscall, /* ppc64_swapcontext */ - [__NR_tgkill] sys_tgkill, - [__NR_utimes] sys_utimes, - [__NR_statfs64] sys_statfs64, - [__NR_fstatfs64] sys_fstatfs64, - [254] sys_ni_syscall, - [__NR_rtas] ppc_rtas, - [256] sys_ni_syscall, - [257] sys_ni_syscall, - [258] sys_ni_syscall, - [__NR_mbind] sys_ni_syscall, /* sys_mbind */ - [__NR_get_mempolicy] sys_ni_syscall, /* sys_get_mempolicy */ - [__NR_set_mempolicy] sys_ni_syscall, /* sys_set_mempolicy */ - [__NR_mq_open] sys_ni_syscall, /* sys_mq_open */ - [__NR_mq_unlink] sys_ni_syscall, /* sys_mq_unlink */ - [__NR_mq_timedsend] sys_ni_syscall, /* sys_mq_timedsend */ - [__NR_mq_timedreceive] sys_ni_syscall, /* sys_mq_timedreceive */ - [__NR_mq_notify] sys_ni_syscall, /* sys_mq_notify */ - [__NR_mq_getsetattr] sys_ni_syscall, /* sys_mq_getsetattr */ - [__NR_kexec_load] sys_ni_syscall, /* sys_kexec_load */ - [__NR_add_key] sys_ni_syscall, /* sys_add_key */ - [__NR_request_key] sys_ni_syscall, /* sys_request_key */ - [__NR_keyctl] sys_ni_syscall, /* sys_keyctl */ - [__NR_waitid] sys_ni_syscall, /* sys_waitid */ - [__NR_ioprio_set] sys_ni_syscall, /* sys_ioprio_set */ - [__NR_ioprio_get] sys_ni_syscall, /* sys_ioprio_get */ - [__NR_inotify_init] sys_ni_syscall, /* sys_inotify_init */ - [__NR_inotify_add_watch] sys_ni_syscall, /* sys_inotify_add_watch */ - [__NR_inotify_rm_watch] sys_ni_syscall, /* sys_inotify_rm_watch */ - [__NR_spu_run] sys_ni_syscall, /* sys_spu_run */ - [__NR_spu_create] sys_ni_syscall, /* sys_spu_create */ - [__NR_pselect6] sys_ni_syscall, /* sys_pselect */ - [__NR_ppoll] sys_ni_syscall, /* sys_ppoll */ - [__NR_unshare] sys_unshare, - [__NR_splice] sys_splice, - [__NR_tee] sys_tee, - [__NR_vmsplice] sys_vmsplice, - [__NR_openat] sys_openat, - [__NR_mkdirat] sys_mkdirat, - [__NR_mknodat] sys_mknodat, - [__NR_fchownat] sys_fchownat, - [__NR_futimesat] sys_futimesat, - [__NR_newfstatat] sys_newfstatat, - [__NR_unlinkat] sys_unlinkat, - [__NR_renameat] sys_renameat, - [__NR_linkat] sys_linkat, - [__NR_symlinkat] sys_symlinkat, - [__NR_readlinkat] sys_readlinkat, - [__NR_fchmodat] sys_fchmodat, - [__NR_faccessat] sys_faccessat, - [__NR_get_robust_list] sys_get_robust_list, - [__NR_set_robust_list] sys_set_robust_list, +#define SYSCALL(func) sys_ni_syscall, +#define COMPAT_SYS(func) sys_ni_syscall, +#define PPC_SYS(func) sys_ni_syscall, +#define OLDSYS(func) sys_ni_syscall, +#define SYS32ONLY(func) sys_ni_syscall, +#define SYSX(f, f3264, f32) sys_ni_syscall, + +#define SYSCALL_SPU(func) sys_##func, +#define COMPAT_SYS_SPU(func) sys_##func, +#define PPC_SYS_SPU(func) ppc_##func, +#define SYSX_SPU(f, f3264, f32) f, + +#include }; long spu_sys_callback(struct spu_syscall_block *s) diff --git a/include/asm-powerpc/systbl.h b/include/asm-powerpc/systbl.h new file mode 100644 index 00000000000..eac85ce101b --- /dev/null +++ b/include/asm-powerpc/systbl.h @@ -0,0 +1,306 @@ +/* + * List of powerpc syscalls. For the meaning of the _SPU suffix see + * arch/powerpc/platforms/cell/spu_callbacks.c + */ + +SYSCALL(restart_syscall) +SYSCALL(exit) +PPC_SYS(fork) +SYSCALL_SPU(read) +SYSCALL_SPU(write) +COMPAT_SYS_SPU(open) +SYSCALL_SPU(close) +COMPAT_SYS_SPU(waitpid) +COMPAT_SYS_SPU(creat) +SYSCALL_SPU(link) +SYSCALL_SPU(unlink) +COMPAT_SYS(execve) +SYSCALL_SPU(chdir) +COMPAT_SYS_SPU(time) +SYSCALL_SPU(mknod) +SYSCALL_SPU(chmod) +SYSCALL_SPU(lchown) +SYSCALL(ni_syscall) +OLDSYS(stat) +SYSX_SPU(sys_lseek,ppc32_lseek,sys_lseek) +SYSCALL_SPU(getpid) +COMPAT_SYS(mount) +SYSX(sys_ni_syscall,sys_oldumount,sys_oldumount) +SYSCALL_SPU(setuid) +SYSCALL_SPU(getuid) +COMPAT_SYS_SPU(stime) +COMPAT_SYS(ptrace) +SYSCALL_SPU(alarm) +OLDSYS(fstat) +COMPAT_SYS(pause) +COMPAT_SYS(utime) +SYSCALL(ni_syscall) +SYSCALL(ni_syscall) +COMPAT_SYS_SPU(access) +COMPAT_SYS_SPU(nice) +SYSCALL(ni_syscall) +SYSCALL_SPU(sync) +COMPAT_SYS_SPU(kill) +SYSCALL_SPU(rename) +COMPAT_SYS_SPU(mkdir) +SYSCALL_SPU(rmdir) +SYSCALL_SPU(dup) +SYSCALL_SPU(pipe) +COMPAT_SYS_SPU(times) +SYSCALL(ni_syscall) +SYSCALL_SPU(brk) +SYSCALL_SPU(setgid) +SYSCALL_SPU(getgid) +SYSCALL(signal) +SYSCALL_SPU(geteuid) +SYSCALL_SPU(getegid) +SYSCALL(acct) +SYSCALL(umount) +SYSCALL(ni_syscall) +COMPAT_SYS_SPU(ioctl) +COMPAT_SYS_SPU(fcntl) +SYSCALL(ni_syscall) +COMPAT_SYS_SPU(setpgid) +SYSCALL(ni_syscall) +SYSX(sys_ni_syscall,sys_olduname, sys_olduname) +COMPAT_SYS_SPU(umask) +SYSCALL_SPU(chroot) +SYSCALL(ustat) +SYSCALL_SPU(dup2) +SYSCALL_SPU(getppid) +SYSCALL_SPU(getpgrp) +SYSCALL_SPU(setsid) +SYS32ONLY(sigaction) +SYSCALL_SPU(sgetmask) +COMPAT_SYS_SPU(ssetmask) +SYSCALL_SPU(setreuid) +SYSCALL_SPU(setregid) +SYS32ONLY(sigsuspend) +COMPAT_SYS(sigpending) +COMPAT_SYS_SPU(sethostname) +COMPAT_SYS_SPU(setrlimit) +COMPAT_SYS(old_getrlimit) +COMPAT_SYS_SPU(getrusage) +COMPAT_SYS_SPU(gettimeofday) +COMPAT_SYS_SPU(settimeofday) +COMPAT_SYS_SPU(getgroups) +COMPAT_SYS_SPU(setgroups) +SYSX(sys_ni_syscall,sys_ni_syscall,ppc_select) +SYSCALL_SPU(symlink) +OLDSYS(lstat) +COMPAT_SYS_SPU(readlink) +SYSCALL(uselib) +SYSCALL(swapon) +SYSCALL(reboot) +SYSX(sys_ni_syscall,old32_readdir,old_readdir) +SYSCALL_SPU(mmap) +SYSCALL_SPU(munmap) +SYSCALL_SPU(truncate) +SYSCALL_SPU(ftruncate) +SYSCALL_SPU(fchmod) +SYSCALL_SPU(fchown) +COMPAT_SYS_SPU(getpriority) +COMPAT_SYS_SPU(setpriority) +SYSCALL(ni_syscall) +COMPAT_SYS(statfs) +COMPAT_SYS(fstatfs) +SYSCALL(ni_syscall) +COMPAT_SYS_SPU(socketcall) +COMPAT_SYS_SPU(syslog) +COMPAT_SYS_SPU(setitimer) +COMPAT_SYS_SPU(getitimer) +COMPAT_SYS_SPU(newstat) +COMPAT_SYS_SPU(newlstat) +COMPAT_SYS_SPU(newfstat) +SYSX(sys_ni_syscall,sys_uname,sys_uname) +SYSCALL(ni_syscall) +SYSCALL_SPU(vhangup) +SYSCALL(ni_syscall) +SYSCALL(ni_syscall) +COMPAT_SYS_SPU(wait4) +SYSCALL(swapoff) +COMPAT_SYS_SPU(sysinfo) +COMPAT_SYS(ipc) +SYSCALL_SPU(fsync) +SYS32ONLY(sigreturn) +PPC_SYS(clone) +COMPAT_SYS_SPU(setdomainname) +PPC_SYS_SPU(newuname) +SYSCALL(ni_syscall) +COMPAT_SYS_SPU(adjtimex) +SYSCALL_SPU(mprotect) +SYSX(sys_ni_syscall,compat_sys_sigprocmask,sys_sigprocmask) +SYSCALL(ni_syscall) +SYSCALL(init_module) +SYSCALL(delete_module) +SYSCALL(ni_syscall) +SYSCALL(quotactl) +COMPAT_SYS_SPU(getpgid) +SYSCALL_SPU(fchdir) +SYSCALL_SPU(bdflush) +COMPAT_SYS(sysfs) +SYSX_SPU(ppc64_personality,ppc64_personality,sys_personality) +SYSCALL(ni_syscall) +SYSCALL_SPU(setfsuid) +SYSCALL_SPU(setfsgid) +SYSCALL_SPU(llseek) +COMPAT_SYS_SPU(getdents) +SYSX_SPU(sys_select,ppc32_select,ppc_select) +SYSCALL_SPU(flock) +SYSCALL_SPU(msync) +COMPAT_SYS_SPU(readv) +COMPAT_SYS_SPU(writev) +COMPAT_SYS_SPU(getsid) +SYSCALL_SPU(fdatasync) +COMPAT_SYS(sysctl) +SYSCALL_SPU(mlock) +SYSCALL_SPU(munlock) +SYSCALL_SPU(mlockall) +SYSCALL_SPU(munlockall) +COMPAT_SYS_SPU(sched_setparam) +COMPAT_SYS_SPU(sched_getparam) +COMPAT_SYS_SPU(sched_setscheduler) +COMPAT_SYS_SPU(sched_getscheduler) +SYSCALL_SPU(sched_yield) +COMPAT_SYS_SPU(sched_get_priority_max) +COMPAT_SYS_SPU(sched_get_priority_min) +COMPAT_SYS_SPU(sched_rr_get_interval) +COMPAT_SYS_SPU(nanosleep) +SYSCALL_SPU(mremap) +SYSCALL_SPU(setresuid) +SYSCALL_SPU(getresuid) +SYSCALL(ni_syscall) +SYSCALL_SPU(poll) +COMPAT_SYS(nfsservctl) +SYSCALL_SPU(setresgid) +SYSCALL_SPU(getresgid) +COMPAT_SYS_SPU(prctl) +COMPAT_SYS(rt_sigreturn) +COMPAT_SYS(rt_sigaction) +COMPAT_SYS(rt_sigprocmask) +COMPAT_SYS(rt_sigpending) +COMPAT_SYS(rt_sigtimedwait) +COMPAT_SYS(rt_sigqueueinfo) +COMPAT_SYS(rt_sigsuspend) +COMPAT_SYS_SPU(pread64) +COMPAT_SYS_SPU(pwrite64) +SYSCALL_SPU(chown) +SYSCALL_SPU(getcwd) +SYSCALL_SPU(capget) +SYSCALL_SPU(capset) +COMPAT_SYS(sigaltstack) +SYSX_SPU(sys_sendfile64,compat_sys_sendfile,sys_sendfile) +SYSCALL(ni_syscall) +SYSCALL(ni_syscall) +PPC_SYS(vfork) +COMPAT_SYS_SPU(getrlimit) +COMPAT_SYS_SPU(readahead) +SYS32ONLY(mmap2) +SYS32ONLY(truncate64) +SYS32ONLY(ftruncate64) +SYSX(sys_ni_syscall,sys_stat64,sys_stat64) +SYSX(sys_ni_syscall,sys_lstat64,sys_lstat64) +SYSX(sys_ni_syscall,sys_fstat64,sys_fstat64) +SYSCALL(pciconfig_read) +SYSCALL(pciconfig_write) +SYSCALL(pciconfig_iobase) +SYSCALL(ni_syscall) +SYSCALL_SPU(getdents64) +SYSCALL_SPU(pivot_root) +SYSX(sys_ni_syscall,compat_sys_fcntl64,sys_fcntl64) +SYSCALL_SPU(madvise) +SYSCALL_SPU(mincore) +SYSCALL_SPU(gettid) +SYSCALL_SPU(tkill) +SYSCALL_SPU(setxattr) +SYSCALL_SPU(lsetxattr) +SYSCALL_SPU(fsetxattr) +SYSCALL_SPU(getxattr) +SYSCALL_SPU(lgetxattr) +SYSCALL_SPU(fgetxattr) +SYSCALL_SPU(listxattr) +SYSCALL_SPU(llistxattr) +SYSCALL_SPU(flistxattr) +SYSCALL_SPU(removexattr) +SYSCALL_SPU(lremovexattr) +SYSCALL_SPU(fremovexattr) +COMPAT_SYS_SPU(futex) +COMPAT_SYS_SPU(sched_setaffinity) +COMPAT_SYS_SPU(sched_getaffinity) +SYSCALL(ni_syscall) +SYSCALL(ni_syscall) +SYS32ONLY(sendfile64) +COMPAT_SYS_SPU(io_setup) +SYSCALL_SPU(io_destroy) +COMPAT_SYS_SPU(io_getevents) +COMPAT_SYS_SPU(io_submit) +SYSCALL_SPU(io_cancel) +SYSCALL(set_tid_address) +SYSX_SPU(sys_fadvise64,ppc32_fadvise64,sys_fadvise64) +SYSCALL(exit_group) +SYSX(sys_lookup_dcookie,ppc32_lookup_dcookie,sys_lookup_dcookie) +SYSCALL_SPU(epoll_create) +SYSCALL_SPU(epoll_ctl) +SYSCALL_SPU(epoll_wait) +SYSCALL_SPU(remap_file_pages) +SYSX_SPU(sys_timer_create,compat_sys_timer_create,sys_timer_create) +COMPAT_SYS_SPU(timer_settime) +COMPAT_SYS_SPU(timer_gettime) +SYSCALL_SPU(timer_getoverrun) +SYSCALL_SPU(timer_delete) +COMPAT_SYS_SPU(clock_settime) +COMPAT_SYS_SPU(clock_gettime) +COMPAT_SYS_SPU(clock_getres) +COMPAT_SYS_SPU(clock_nanosleep) +SYSX(ppc64_swapcontext,ppc32_swapcontext,ppc_swapcontext) +COMPAT_SYS_SPU(tgkill) +COMPAT_SYS_SPU(utimes) +COMPAT_SYS_SPU(statfs64) +COMPAT_SYS_SPU(fstatfs64) +SYSX(sys_ni_syscall, ppc_fadvise64_64, ppc_fadvise64_64) +PPC_SYS_SPU(rtas) +OLDSYS(debug_setcontext) +SYSCALL(ni_syscall) +SYSCALL(ni_syscall) +COMPAT_SYS(mbind) +COMPAT_SYS(get_mempolicy) +COMPAT_SYS(set_mempolicy) +COMPAT_SYS(mq_open) +SYSCALL(mq_unlink) +COMPAT_SYS(mq_timedsend) +COMPAT_SYS(mq_timedreceive) +COMPAT_SYS(mq_notify) +COMPAT_SYS(mq_getsetattr) +COMPAT_SYS(kexec_load) +COMPAT_SYS(add_key) +COMPAT_SYS(request_key) +COMPAT_SYS(keyctl) +COMPAT_SYS(waitid) +COMPAT_SYS(ioprio_set) +COMPAT_SYS(ioprio_get) +SYSCALL(inotify_init) +SYSCALL(inotify_add_watch) +SYSCALL(inotify_rm_watch) +SYSCALL(spu_run) +SYSCALL(spu_create) +COMPAT_SYS(pselect6) +COMPAT_SYS(ppoll) +SYSCALL_SPU(unshare) +SYSCALL_SPU(splice) +SYSCALL_SPU(tee) +SYSCALL_SPU(vmsplice) +COMPAT_SYS_SPU(openat) +SYSCALL_SPU(mkdirat) +SYSCALL_SPU(mknodat) +SYSCALL_SPU(fchownat) +COMPAT_SYS_SPU(futimesat) +SYSX_SPU(sys_newfstatat, sys_fstatat64, sys_fstatat64) +SYSCALL_SPU(unlinkat) +SYSCALL_SPU(renameat) +SYSCALL_SPU(linkat) +SYSCALL_SPU(symlinkat) +SYSCALL_SPU(readlinkat) +SYSCALL_SPU(fchmodat) +SYSCALL_SPU(faccessat) +COMPAT_SYS_SPU(get_robust_list) +COMPAT_SYS_SPU(set_robust_list) -- cgit v1.2.3 From ddf5f75a16b3e7460ffee881795aa168dffcd0cf Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 20 Jun 2006 02:30:33 +0200 Subject: [POWERPC] disable floating point exceptions for init Floating point exceptions should not be enabled by default, as this setting impacts the performance on some CPUs, in particular the Cell BE. Since the bits are inherited from parent processes, the place to change the default is the thread struct used for init. glibc sets this up correctly per thread in its fesetenv function, so user space should not be impacted by this setting. None of the other common libc implementations (uClibc, dietlibc, newlib, klibc) has support for fp exceptions, so they are unlikely to be hit by this either. There is a small risk that somebody wrote their own application that manually sets the fpscr bits instead of calling fesetenv, without changing the MSR bits as well. Those programs will break with this change. It probably makes sense to change glibc in the future to be more clever about FE bits, so that when running on a CPU where this is expensive, it disables exceptions ASAP, while it keeps them enabled on CPUs where running with exceptions on is cheaper than changing the state often. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- include/asm-powerpc/processor.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/asm-powerpc/processor.h b/include/asm-powerpc/processor.h index d2c2c95f913..22e54a2a660 100644 --- a/include/asm-powerpc/processor.h +++ b/include/asm-powerpc/processor.h @@ -190,7 +190,7 @@ struct thread_struct { .fs = KERNEL_DS, \ .fpr = {0}, \ .fpscr = { .val = 0, }, \ - .fpexc_mode = MSR_FE0|MSR_FE1, \ + .fpexc_mode = 0, \ } #endif -- cgit v1.2.3 From 1e92a550e80fef01ebcc0bcd0896109cdb986c72 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Thu, 15 Jun 2006 14:11:22 +1000 Subject: [POWERPC] Fix mdelay badness on shared processor partitions On partitioned PPC64 systems where a partition is given 1/10 of a processor, we have seen mdelay() delaying for 10 times longer than it should. The reason is that the generic mdelay(n) does n delays of 1 millisecond each. However, with 1/10 of a processor, we only get a one-millisecond timeslice every 10ms. Thus each 1 millisecond delay loop ends up taking 10ms elapsed time. The solution is just to use the PPC64 udelay function, which uses the timebase to ensure that the delay is based on elapsed time rather than how much processing time the partition has been given. (Yes, the generic mdelay uses the PPC64 udelay, but the problem is that the start time gets reset every millisecond, and each time it gets reset we lose another 9ms.) Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras Acked-by: Andrew Morton --- include/asm-powerpc/delay.h | 13 +++++++++++++ include/linux/delay.h | 5 +---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/include/asm-powerpc/delay.h b/include/asm-powerpc/delay.h index 057a6095547..f9200a65c63 100644 --- a/include/asm-powerpc/delay.h +++ b/include/asm-powerpc/delay.h @@ -17,5 +17,18 @@ extern void __delay(unsigned long loops); extern void udelay(unsigned long usecs); +/* + * On shared processor machines the generic implementation of mdelay can + * result in large errors. While each iteration of the loop inside mdelay + * is supposed to take 1ms, the hypervisor could sleep our partition for + * longer (eg 10ms). With the right timing these errors can add up. + * + * Since there is no 32bit overflow issue on 64bit kernels, just call + * udelay directly. + */ +#ifdef CONFIG_PPC64 +#define mdelay(n) udelay((n) * 1000) +#endif + #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_DELAY_H */ diff --git a/include/linux/delay.h b/include/linux/delay.h index acb74865b97..17ddb55430a 100644 --- a/include/linux/delay.h +++ b/include/linux/delay.h @@ -25,10 +25,7 @@ extern unsigned long loops_per_jiffy; #define MAX_UDELAY_MS 5 #endif -#ifdef notdef -#define mdelay(n) (\ - {unsigned long __ms=(n); while (__ms--) udelay(1000);}) -#else +#ifndef mdelay #define mdelay(n) (\ (__builtin_constant_p(n) && (n)<=MAX_UDELAY_MS) ? udelay((n)*1000) : \ ({unsigned long __ms=(n); while (__ms--) udelay(1000);})) -- cgit v1.2.3 From d3c58fb177dc957af5cdac5ad1638d713fdb8765 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Tue, 20 Jun 2006 18:00:30 +1000 Subject: [POWERPC] Dont look for class-code in pci children Looking for class-code in PCI children breaks with direct slots. Lets just count all children. Signed-off-by: Anton Blanchard Acked-by: Olof Johansson Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/pseries/iommu.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 2f66dc6503f..d03a8b078f9 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -331,13 +331,9 @@ static void iommu_bus_setup_pSeries(struct pci_bus *bus) if (isa_dn_orig) of_node_put(isa_dn_orig); - /* Count number of direct PCI children of the PHB. - * All PCI device nodes have class-code property, so it's - * an easy way to find them. - */ + /* Count number of direct PCI children of the PHB. */ for (children = 0, tmp = dn->child; tmp; tmp = tmp->sibling) - if (get_property(tmp, "class-code", NULL)) - children++; + children++; DBG("Children: %d\n", children); -- cgit v1.2.3 From ccba051c373e342de240ba00d542dac67ae0eb7e Mon Sep 17 00:00:00 2001 From: Nathan Lynch Date: Tue, 20 Jun 2006 18:01:58 +1000 Subject: [POWERPC] Extra sanity check in EEH code Don't dereference a device node that isn't there. A "shouldn't happen" case, but someone ran into it with a possibly misconfigured device tree. Signed-off-by: Nathan Lynch Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/pseries/eeh_cache.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/powerpc/platforms/pseries/eeh_cache.c b/arch/powerpc/platforms/pseries/eeh_cache.c index d4a402c5866..98c23aec85b 100644 --- a/arch/powerpc/platforms/pseries/eeh_cache.c +++ b/arch/powerpc/platforms/pseries/eeh_cache.c @@ -304,6 +304,8 @@ void __init pci_addr_cache_build(void) pci_addr_cache_insert_device(dev); dn = pci_device_to_OF_node(dev); + if (!dn) + continue; pci_dev_get (dev); /* matching put is in eeh_remove_device() */ PCI_DN(dn)->pcidev = dev; } -- cgit v1.2.3 From 0bb474a48e5d1ceb8e4005c7664b548c9834a784 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Tue, 20 Jun 2006 18:47:26 +1000 Subject: [POWERPC] support ibm,extended-*-frequency properties Support the ibm,extended-*-frequency properties found in recent POWER5 firmware: cpus/PowerPC,POWER5@0/clock-frequency 59aa5880 (1504336000) cpus/PowerPC,POWER5@0/ibm,extended-clock-frequency 00000000 59aa5880 cpus/PowerPC,POWER5@0/timebase-frequency 0b354b10 (188042000) cpus/PowerPC,POWER5@0/ibm,extended-timebase-frequency 00000000 0b354b10 Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/time.c | 57 ++++++++++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 528e7f84cb6..d20907561f4 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -857,42 +857,50 @@ int do_settimeofday(struct timespec *tv) EXPORT_SYMBOL(do_settimeofday); -void __init generic_calibrate_decr(void) +static int __init get_freq(char *name, int cells, unsigned long *val) { struct device_node *cpu; unsigned int *fp; - int node_found; + int found = 0; - /* - * The cpu node should have a timebase-frequency property - * to tell us the rate at which the decrementer counts. - */ + /* The cpu node should have timebase and clock frequency properties */ cpu = of_find_node_by_type(NULL, "cpu"); - ppc_tb_freq = DEFAULT_TB_FREQ; /* hardcoded default */ - node_found = 0; if (cpu) { - fp = (unsigned int *)get_property(cpu, "timebase-frequency", - NULL); + fp = (unsigned int *)get_property(cpu, name, NULL); if (fp) { - node_found = 1; - ppc_tb_freq = *fp; + found = 1; + *val = 0; + while (cells--) + *val = (*val << 32) | *fp++; } + + of_node_put(cpu); } - if (!node_found) + + return found; +} + +void __init generic_calibrate_decr(void) +{ + ppc_tb_freq = DEFAULT_TB_FREQ; /* hardcoded default */ + + if (!get_freq("ibm,extended-timebase-frequency", 2, &ppc_tb_freq) && + !get_freq("timebase-frequency", 1, &ppc_tb_freq)) { + printk(KERN_ERR "WARNING: Estimating decrementer frequency " "(not found)\n"); + } - ppc_proc_freq = DEFAULT_PROC_FREQ; - node_found = 0; - if (cpu) { - fp = (unsigned int *)get_property(cpu, "clock-frequency", - NULL); - if (fp) { - node_found = 1; - ppc_proc_freq = *fp; - } + ppc_proc_freq = DEFAULT_PROC_FREQ; /* hardcoded default */ + + if (!get_freq("ibm,extended-clock-frequency", 2, &ppc_proc_freq) && + !get_freq("clock-frequency", 1, &ppc_proc_freq)) { + + printk(KERN_ERR "WARNING: Estimating processor frequency " + "(not found)\n"); } + #ifdef CONFIG_BOOKE /* Set the time base to zero */ mtspr(SPRN_TBWL, 0); @@ -904,11 +912,6 @@ void __init generic_calibrate_decr(void) /* Enable decrementer interrupt */ mtspr(SPRN_TCR, TCR_DIE); #endif - if (!node_found) - printk(KERN_ERR "WARNING: Estimating processor frequency " - "(not found)\n"); - - of_node_put(cpu); } unsigned long get_boot_time(void) -- cgit v1.2.3 From 2191fe3e39159e3375f4b7ec1420df149f154101 Mon Sep 17 00:00:00 2001 From: Kelly Daly Date: Wed, 21 Jun 2006 13:52:55 +1000 Subject: [POWERPC] re-enable OProfile for iSeries, using timer interrupt This patch removes the changes from an earlier patch that disables oProfile for iSeries within the oProfile KConfig (submitted Feb 23, 2006). Checks within the arch init for iSeries, still allowing profiling for timer interrupts (using firmware_has_feature). Signed-off-by: Kelly Daly Acked-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/oprofile/Kconfig | 1 - arch/powerpc/oprofile/common.c | 4 ++++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/oprofile/Kconfig b/arch/powerpc/oprofile/Kconfig index d03c0e5ca87..eb2dece76a5 100644 --- a/arch/powerpc/oprofile/Kconfig +++ b/arch/powerpc/oprofile/Kconfig @@ -1,5 +1,4 @@ config PROFILING - depends on !PPC_ISERIES bool "Profiling support (EXPERIMENTAL)" help Say Y here to enable the extended profiling support mechanisms used diff --git a/arch/powerpc/oprofile/common.c b/arch/powerpc/oprofile/common.c index 38a2f9c1718..27ad56bd227 100644 --- a/arch/powerpc/oprofile/common.c +++ b/arch/powerpc/oprofile/common.c @@ -22,6 +22,7 @@ #include #include #include +#include static struct op_powerpc_model *model; @@ -130,6 +131,9 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) if (!cur_cpu_spec->oprofile_cpu_type) return -ENODEV; + if (firmware_has_feature(FW_FEATURE_ISERIES)) + return -ENODEV; + switch (cur_cpu_spec->oprofile_type) { #ifdef CONFIG_PPC64 case PPC_OPROFILE_RS64: -- cgit v1.2.3 From c34b4c734482dda750deb6089521f7c891b48736 Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Tue, 9 May 2006 10:52:09 -0700 Subject: [PATCH] PCI: Add PCI_CAP_ID_VNDR Add the vendor-specific extended capability PCI_CAP_ID_VNDR. It will be used by the Myri-10G Ethernet driver (will be submitted soon). Signed-off-by: Brice Goglin Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- include/linux/pci_regs.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h index d27a78b7129..6bce4a24036 100644 --- a/include/linux/pci_regs.h +++ b/include/linux/pci_regs.h @@ -197,6 +197,7 @@ #define PCI_CAP_ID_CHSWP 0x06 /* CompactPCI HotSwap */ #define PCI_CAP_ID_PCIX 0x07 /* PCI-X */ #define PCI_CAP_ID_HT_IRQCONF 0x08 /* HyperTransport IRQ Configuration */ +#define PCI_CAP_ID_VNDR 0x09 /* Vendor specific capability */ #define PCI_CAP_ID_SHPC 0x0C /* PCI Standard Hot-Plug Controller */ #define PCI_CAP_ID_EXP 0x10 /* PCI Express */ #define PCI_CAP_ID_MSIX 0x11 /* MSI-X */ -- cgit v1.2.3 From fd58e55fcf5568e51da2ed54d7acd049c3fdb184 Mon Sep 17 00:00:00 2001 From: Mark Maule Date: Mon, 10 Apr 2006 21:17:48 -0500 Subject: [PATCH] PCI: msi abstractions and support for altix Abstract portions of the MSI core for platforms that do not use standard APIC interrupt controllers. This is implemented through a new arch-specific msi setup routine, and a set of msi ops which can be set on a per platform basis. Signed-off-by: Mark Maule Signed-off-by: Greg Kroah-Hartman --- drivers/pci/Makefile | 6 +- drivers/pci/msi-altix.c | 18 ++++ drivers/pci/msi-apic.c | 100 +++++++++++++++++++ drivers/pci/msi.c | 212 +++++++++++++++++++++++++---------------- drivers/pci/msi.h | 133 ++++++++++++++------------ include/asm-i386/msi.h | 8 ++ include/asm-ia64/machvec.h | 7 ++ include/asm-ia64/machvec_sn2.h | 7 ++ include/asm-ia64/msi.h | 12 +++ include/asm-x86_64/msi.h | 8 ++ 10 files changed, 367 insertions(+), 144 deletions(-) create mode 100644 drivers/pci/msi-altix.c create mode 100644 drivers/pci/msi-apic.c diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 6707df96893..f2d152b818f 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -26,7 +26,11 @@ obj-$(CONFIG_PPC32) += setup-irq.o obj-$(CONFIG_PPC64) += setup-bus.o obj-$(CONFIG_MIPS) += setup-bus.o setup-irq.o obj-$(CONFIG_X86_VISWS) += setup-irq.o -obj-$(CONFIG_PCI_MSI) += msi.o + +msiobj-y := msi.o msi-apic.o +msiobj-$(CONFIG_IA64_GENERIC) += msi-altix.o +msiobj-$(CONFIG_IA64_SGI_SN2) += msi-altix.o +obj-$(CONFIG_PCI_MSI) += $(msiobj-y) # # ACPI Related PCI FW Functions diff --git a/drivers/pci/msi-altix.c b/drivers/pci/msi-altix.c new file mode 100644 index 00000000000..9bd240602c1 --- /dev/null +++ b/drivers/pci/msi-altix.c @@ -0,0 +1,18 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2006 Silicon Graphics, Inc. All Rights Reserved. + */ + +#include + +int +sn_msi_init(void) +{ + /* + * return error until MSI is supported on altix platforms + */ + return -EINVAL; +} diff --git a/drivers/pci/msi-apic.c b/drivers/pci/msi-apic.c new file mode 100644 index 00000000000..0eb5fe9003a --- /dev/null +++ b/drivers/pci/msi-apic.c @@ -0,0 +1,100 @@ +/* + * MSI hooks for standard x86 apic + */ + +#include +#include + +#include "msi.h" + +/* + * Shifts for APIC-based data + */ + +#define MSI_DATA_VECTOR_SHIFT 0 +#define MSI_DATA_VECTOR(v) (((u8)v) << MSI_DATA_VECTOR_SHIFT) + +#define MSI_DATA_DELIVERY_SHIFT 8 +#define MSI_DATA_DELIVERY_FIXED (0 << MSI_DATA_DELIVERY_SHIFT) +#define MSI_DATA_DELIVERY_LOWPRI (1 << MSI_DATA_DELIVERY_SHIFT) + +#define MSI_DATA_LEVEL_SHIFT 14 +#define MSI_DATA_LEVEL_DEASSERT (0 << MSI_DATA_LEVEL_SHIFT) +#define MSI_DATA_LEVEL_ASSERT (1 << MSI_DATA_LEVEL_SHIFT) + +#define MSI_DATA_TRIGGER_SHIFT 15 +#define MSI_DATA_TRIGGER_EDGE (0 << MSI_DATA_TRIGGER_SHIFT) +#define MSI_DATA_TRIGGER_LEVEL (1 << MSI_DATA_TRIGGER_SHIFT) + +/* + * Shift/mask fields for APIC-based bus address + */ + +#define MSI_ADDR_HEADER 0xfee00000 + +#define MSI_ADDR_DESTID_MASK 0xfff0000f +#define MSI_ADDR_DESTID_CPU(cpu) ((cpu) << MSI_TARGET_CPU_SHIFT) + +#define MSI_ADDR_DESTMODE_SHIFT 2 +#define MSI_ADDR_DESTMODE_PHYS (0 << MSI_ADDR_DESTMODE_SHIFT) +#define MSI_ADDR_DESTMODE_LOGIC (1 << MSI_ADDR_DESTMODE_SHIFT) + +#define MSI_ADDR_REDIRECTION_SHIFT 3 +#define MSI_ADDR_REDIRECTION_CPU (0 << MSI_ADDR_REDIRECTION_SHIFT) +#define MSI_ADDR_REDIRECTION_LOWPRI (1 << MSI_ADDR_REDIRECTION_SHIFT) + + +static void +msi_target_apic(unsigned int vector, + unsigned int dest_cpu, + u32 *address_hi, /* in/out */ + u32 *address_lo) /* in/out */ +{ + u32 addr = *address_lo; + + addr &= MSI_ADDR_DESTID_MASK; + addr |= MSI_ADDR_DESTID_CPU(cpu_physical_id(dest_cpu)); + + *address_lo = addr; +} + +static int +msi_setup_apic(struct pci_dev *pdev, /* unused in generic */ + unsigned int vector, + u32 *address_hi, + u32 *address_lo, + u32 *data) +{ + unsigned long dest_phys_id; + + dest_phys_id = cpu_physical_id(first_cpu(cpu_online_map)); + + *address_hi = 0; + *address_lo = MSI_ADDR_HEADER | + MSI_ADDR_DESTMODE_PHYS | + MSI_ADDR_REDIRECTION_CPU | + MSI_ADDR_DESTID_CPU(dest_phys_id); + + *data = MSI_DATA_TRIGGER_EDGE | + MSI_DATA_LEVEL_ASSERT | + MSI_DATA_DELIVERY_FIXED | + MSI_DATA_VECTOR(vector); + + return 0; +} + +static void +msi_teardown_apic(unsigned int vector) +{ + return; /* no-op */ +} + +/* + * Generic ops used on most IA archs/platforms. Set with msi_register() + */ + +struct msi_ops msi_apic_ops = { + .setup = msi_setup_apic, + .teardown = msi_teardown_apic, + .target = msi_target_apic, +}; diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 9855c4c920b..55ff52df5fe 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -23,8 +23,6 @@ #include "pci.h" #include "msi.h" -#define MSI_TARGET_CPU first_cpu(cpu_online_map) - static DEFINE_SPINLOCK(msi_lock); static struct msi_desc* msi_desc[NR_IRQS] = { [0 ... NR_IRQS-1] = NULL }; static kmem_cache_t* msi_cachep; @@ -40,6 +38,15 @@ int vector_irq[NR_VECTORS] = { [0 ... NR_VECTORS - 1] = -1}; u8 irq_vector[NR_IRQ_VECTORS] = { FIRST_DEVICE_VECTOR , 0 }; #endif +static struct msi_ops *msi_ops; + +int +msi_register(struct msi_ops *ops) +{ + msi_ops = ops; + return 0; +} + static void msi_cache_ctor(void *p, kmem_cache_t *cache, unsigned long flags) { memset(p, 0, NR_IRQS * sizeof(struct msi_desc)); @@ -92,7 +99,7 @@ static void msi_set_mask_bit(unsigned int vector, int flag) static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask) { struct msi_desc *entry; - struct msg_address address; + u32 address_hi, address_lo; unsigned int irq = vector; unsigned int dest_cpu = first_cpu(cpu_mask); @@ -108,28 +115,36 @@ static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask) if (!pos) return; + pci_read_config_dword(entry->dev, msi_upper_address_reg(pos), + &address_hi); pci_read_config_dword(entry->dev, msi_lower_address_reg(pos), - &address.lo_address.value); - address.lo_address.value &= MSI_ADDRESS_DEST_ID_MASK; - address.lo_address.value |= (cpu_physical_id(dest_cpu) << - MSI_TARGET_CPU_SHIFT); - entry->msi_attrib.current_cpu = cpu_physical_id(dest_cpu); + &address_lo); + + msi_ops->target(vector, dest_cpu, &address_hi, &address_lo); + + pci_write_config_dword(entry->dev, msi_upper_address_reg(pos), + address_hi); pci_write_config_dword(entry->dev, msi_lower_address_reg(pos), - address.lo_address.value); + address_lo); set_native_irq_info(irq, cpu_mask); break; } case PCI_CAP_ID_MSIX: { - int offset = entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + - PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET; - - address.lo_address.value = readl(entry->mask_base + offset); - address.lo_address.value &= MSI_ADDRESS_DEST_ID_MASK; - address.lo_address.value |= (cpu_physical_id(dest_cpu) << - MSI_TARGET_CPU_SHIFT); - entry->msi_attrib.current_cpu = cpu_physical_id(dest_cpu); - writel(address.lo_address.value, entry->mask_base + offset); + int offset_hi = + entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET; + int offset_lo = + entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET; + + address_hi = readl(entry->mask_base + offset_hi); + address_lo = readl(entry->mask_base + offset_lo); + + msi_ops->target(vector, dest_cpu, &address_hi, &address_lo); + + writel(address_hi, entry->mask_base + offset_hi); + writel(address_lo, entry->mask_base + offset_lo); set_native_irq_info(irq, cpu_mask); break; } @@ -251,30 +266,6 @@ static struct hw_interrupt_type msi_irq_wo_maskbit_type = { .set_affinity = set_msi_affinity }; -static void msi_data_init(struct msg_data *msi_data, - unsigned int vector) -{ - memset(msi_data, 0, sizeof(struct msg_data)); - msi_data->vector = (u8)vector; - msi_data->delivery_mode = MSI_DELIVERY_MODE; - msi_data->level = MSI_LEVEL_MODE; - msi_data->trigger = MSI_TRIGGER_MODE; -} - -static void msi_address_init(struct msg_address *msi_address) -{ - unsigned int dest_id; - unsigned long dest_phys_id = cpu_physical_id(MSI_TARGET_CPU); - - memset(msi_address, 0, sizeof(struct msg_address)); - msi_address->hi_address = (u32)0; - dest_id = (MSI_ADDRESS_HEADER << MSI_ADDRESS_HEADER_SHIFT); - msi_address->lo_address.u.dest_mode = MSI_PHYSICAL_MODE; - msi_address->lo_address.u.redirection_hint = MSI_REDIRECTION_HINT_MODE; - msi_address->lo_address.u.dest_id = dest_id; - msi_address->lo_address.value |= (dest_phys_id << MSI_TARGET_CPU_SHIFT); -} - static int msi_free_vector(struct pci_dev* dev, int vector, int reassign); static int assign_msi_vector(void) { @@ -369,13 +360,29 @@ static int msi_init(void) return status; } + status = msi_arch_init(); + if (status < 0) { + pci_msi_enable = 0; + printk(KERN_WARNING + "PCI: MSI arch init failed. MSI disabled.\n"); + return status; + } + + if (! msi_ops) { + printk(KERN_WARNING + "PCI: MSI ops not registered. MSI disabled.\n"); + status = -EINVAL; + return status; + } + + last_alloc_vector = assign_irq_vector(AUTO_ASSIGN); status = msi_cache_init(); if (status < 0) { pci_msi_enable = 0; printk(KERN_WARNING "PCI: MSI cache init failed\n"); return status; } - last_alloc_vector = assign_irq_vector(AUTO_ASSIGN); + if (last_alloc_vector < 0) { pci_msi_enable = 0; printk(KERN_WARNING "PCI: No interrupt vectors available for MSI\n"); @@ -575,6 +582,8 @@ void pci_restore_msi_state(struct pci_dev *dev) int pci_save_msix_state(struct pci_dev *dev) { int pos; + int temp; + int vector, head, tail = 0; u16 control; struct pci_cap_saved_state *save_state; @@ -582,6 +591,7 @@ int pci_save_msix_state(struct pci_dev *dev) if (pos <= 0 || dev->no_msi) return 0; + /* save the capability */ pci_read_config_word(dev, msi_control_reg(pos), &control); if (!(control & PCI_MSIX_FLAGS_ENABLE)) return 0; @@ -593,6 +603,38 @@ int pci_save_msix_state(struct pci_dev *dev) } *((u16 *)&save_state->data[0]) = control; + /* save the table */ + temp = dev->irq; + if (msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) { + kfree(save_state); + return -EINVAL; + } + + vector = head = dev->irq; + while (head != tail) { + int j; + void __iomem *base; + struct msi_desc *entry; + + entry = msi_desc[vector]; + base = entry->mask_base; + j = entry->msi_attrib.entry_nr; + + entry->address_lo_save = + readl(base + j * PCI_MSIX_ENTRY_SIZE + + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET); + entry->address_hi_save = + readl(base + j * PCI_MSIX_ENTRY_SIZE + + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET); + entry->data_save = + readl(base + j * PCI_MSIX_ENTRY_SIZE + + PCI_MSIX_ENTRY_DATA_OFFSET); + + tail = msi_desc[vector]->link.tail; + vector = tail; + } + dev->irq = temp; + disable_msi_mode(dev, pos, PCI_CAP_ID_MSIX); save_state->cap_nr = PCI_CAP_ID_MSIX; pci_add_saved_cap(dev, save_state); @@ -606,8 +648,6 @@ void pci_restore_msix_state(struct pci_dev *dev) int vector, head, tail = 0; void __iomem *base; int j; - struct msg_address address; - struct msg_data data; struct msi_desc *entry; int temp; struct pci_cap_saved_state *save_state; @@ -633,20 +673,13 @@ void pci_restore_msix_state(struct pci_dev *dev) base = entry->mask_base; j = entry->msi_attrib.entry_nr; - msi_address_init(&address); - msi_data_init(&data, vector); - - address.lo_address.value &= MSI_ADDRESS_DEST_ID_MASK; - address.lo_address.value |= entry->msi_attrib.current_cpu << - MSI_TARGET_CPU_SHIFT; - - writel(address.lo_address.value, + writel(entry->address_lo_save, base + j * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET); - writel(address.hi_address, + writel(entry->address_hi_save, base + j * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET); - writel(*(u32*)&data, + writel(entry->data_save, base + j * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_DATA_OFFSET); @@ -660,30 +693,32 @@ void pci_restore_msix_state(struct pci_dev *dev) } #endif -static void msi_register_init(struct pci_dev *dev, struct msi_desc *entry) +static int msi_register_init(struct pci_dev *dev, struct msi_desc *entry) { - struct msg_address address; - struct msg_data data; + int status; + u32 address_hi; + u32 address_lo; + u32 data; int pos, vector = dev->irq; u16 control; pos = pci_find_capability(dev, PCI_CAP_ID_MSI); pci_read_config_word(dev, msi_control_reg(pos), &control); + /* Configure MSI capability structure */ - msi_address_init(&address); - msi_data_init(&data, vector); - entry->msi_attrib.current_cpu = ((address.lo_address.u.dest_id >> - MSI_TARGET_CPU_SHIFT) & MSI_TARGET_CPU_MASK); - pci_write_config_dword(dev, msi_lower_address_reg(pos), - address.lo_address.value); + status = msi_ops->setup(dev, vector, &address_hi, &address_lo, &data); + if (status < 0) + return status; + + pci_write_config_dword(dev, msi_lower_address_reg(pos), address_lo); if (is_64bit_address(control)) { pci_write_config_dword(dev, - msi_upper_address_reg(pos), address.hi_address); + msi_upper_address_reg(pos), address_hi); pci_write_config_word(dev, - msi_data_reg(pos, 1), *((u32*)&data)); + msi_data_reg(pos, 1), data); } else pci_write_config_word(dev, - msi_data_reg(pos, 0), *((u32*)&data)); + msi_data_reg(pos, 0), data); if (entry->msi_attrib.maskbit) { unsigned int maskbits, temp; /* All MSIs are unmasked by default, Mask them all */ @@ -697,6 +732,8 @@ static void msi_register_init(struct pci_dev *dev, struct msi_desc *entry) msi_mask_bits_reg(pos, is_64bit_address(control)), maskbits); } + + return 0; } /** @@ -710,6 +747,7 @@ static void msi_register_init(struct pci_dev *dev, struct msi_desc *entry) **/ static int msi_capability_init(struct pci_dev *dev) { + int status; struct msi_desc *entry; int pos, vector; u16 control; @@ -742,7 +780,12 @@ static int msi_capability_init(struct pci_dev *dev) /* Replace with MSI handler */ irq_handler_init(PCI_CAP_ID_MSI, vector, entry->msi_attrib.maskbit); /* Configure MSI capability structure */ - msi_register_init(dev, entry); + status = msi_register_init(dev, entry); + if (status != 0) { + dev->irq = entry->msi_attrib.default_vector; + kmem_cache_free(msi_cachep, entry); + return status; + } attach_msi_entry(entry, vector); /* Set MSI enabled bits */ @@ -765,8 +808,10 @@ static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries, int nvec) { struct msi_desc *head = NULL, *tail = NULL, *entry = NULL; - struct msg_address address; - struct msg_data data; + u32 address_hi; + u32 address_lo; + u32 data; + int status; int vector, pos, i, j, nr_entries, temp = 0; unsigned long phys_addr; u32 table_offset; @@ -822,18 +867,20 @@ static int msix_capability_init(struct pci_dev *dev, /* Replace with MSI-X handler */ irq_handler_init(PCI_CAP_ID_MSIX, vector, 1); /* Configure MSI-X capability structure */ - msi_address_init(&address); - msi_data_init(&data, vector); - entry->msi_attrib.current_cpu = - ((address.lo_address.u.dest_id >> - MSI_TARGET_CPU_SHIFT) & MSI_TARGET_CPU_MASK); - writel(address.lo_address.value, + status = msi_ops->setup(dev, vector, + &address_hi, + &address_lo, + &data); + if (status < 0) + break; + + writel(address_lo, base + j * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET); - writel(address.hi_address, + writel(address_hi, base + j * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET); - writel(*(u32*)&data, + writel(data, base + j * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_DATA_OFFSET); attach_msi_entry(entry, vector); @@ -901,9 +948,10 @@ int pci_enable_msi(struct pci_dev* dev) vector_irq[dev->irq] = -1; nr_released_vectors--; spin_unlock_irqrestore(&msi_lock, flags); - msi_register_init(dev, msi_desc[dev->irq]); - enable_msi_mode(dev, pos, PCI_CAP_ID_MSI); - return 0; + status = msi_register_init(dev, msi_desc[dev->irq]); + if (status == 0) + enable_msi_mode(dev, pos, PCI_CAP_ID_MSI); + return status; } spin_unlock_irqrestore(&msi_lock, flags); dev->irq = temp; @@ -980,6 +1028,8 @@ static int msi_free_vector(struct pci_dev* dev, int vector, int reassign) void __iomem *base; unsigned long flags; + msi_ops->teardown(vector); + spin_lock_irqsave(&msi_lock, flags); entry = msi_desc[vector]; if (!entry || entry->dev != dev) { diff --git a/drivers/pci/msi.h b/drivers/pci/msi.h index 4ac52d441e4..56951c39d3a 100644 --- a/drivers/pci/msi.h +++ b/drivers/pci/msi.h @@ -6,6 +6,68 @@ #ifndef MSI_H #define MSI_H +/* + * MSI operation vector. Used by the msi core code (drivers/pci/msi.c) + * to abstract platform-specific tasks relating to MSI address generation + * and resource management. + */ +struct msi_ops { + /** + * setup - generate an MSI bus address and data for a given vector + * @pdev: PCI device context (in) + * @vector: vector allocated by the msi core (in) + * @addr_hi: upper 32 bits of PCI bus MSI address (out) + * @addr_lo: lower 32 bits of PCI bus MSI address (out) + * @data: MSI data payload (out) + * + * Description: The setup op is used to generate a PCI bus addres and + * data which the msi core will program into the card MSI capability + * registers. The setup routine is responsible for picking an initial + * cpu to target the MSI at. The setup routine is responsible for + * examining pdev to determine the MSI capabilities of the card and + * generating a suitable address/data. The setup routine is + * responsible for allocating and tracking any system resources it + * needs to route the MSI to the cpu it picks, and for associating + * those resources with the passed in vector. + * + * Returns 0 if the MSI address/data was successfully setup. + **/ + + int (*setup) (struct pci_dev *pdev, unsigned int vector, + u32 *addr_hi, u32 *addr_lo, u32 *data); + + /** + * teardown - release resources allocated by setup + * @vector: vector context for resources (in) + * + * Description: The teardown op is used to release any resources + * that were allocated in the setup routine associated with the passed + * in vector. + **/ + + void (*teardown) (unsigned int vector); + + /** + * target - retarget an MSI at a different cpu + * @vector: vector context for resources (in) + * @cpu: new cpu to direct vector at (in) + * @addr_hi: new value of PCI bus upper 32 bits (in/out) + * @addr_lo: new value of PCI bus lower 32 bits (in/out) + * + * Description: The target op is used to redirect an MSI vector + * at a different cpu. addr_hi/addr_lo coming in are the existing + * values that the MSI core has programmed into the card. The + * target code is responsible for freeing any resources (if any) + * associated with the old address, and generating a new PCI bus + * addr_hi/addr_lo that will redirect the vector at the indicated cpu. + **/ + + void (*target) (unsigned int vector, unsigned int cpu, + u32 *addr_hi, u32 *addr_lo); +}; + +extern int msi_register(struct msi_ops *ops); + #include /* @@ -63,67 +125,6 @@ extern int pci_vector_resources(int last, int nr_released); #define msix_mask(address) (address | PCI_MSIX_FLAGS_BITMASK) #define msix_is_pending(address) (address & PCI_MSIX_FLAGS_PENDMASK) -/* - * MSI Defined Data Structures - */ -#define MSI_ADDRESS_HEADER 0xfee -#define MSI_ADDRESS_HEADER_SHIFT 12 -#define MSI_ADDRESS_HEADER_MASK 0xfff000 -#define MSI_ADDRESS_DEST_ID_MASK 0xfff0000f -#define MSI_TARGET_CPU_MASK 0xff -#define MSI_DELIVERY_MODE 0 -#define MSI_LEVEL_MODE 1 /* Edge always assert */ -#define MSI_TRIGGER_MODE 0 /* MSI is edge sensitive */ -#define MSI_PHYSICAL_MODE 0 -#define MSI_LOGICAL_MODE 1 -#define MSI_REDIRECTION_HINT_MODE 0 - -struct msg_data { -#if defined(__LITTLE_ENDIAN_BITFIELD) - __u32 vector : 8; - __u32 delivery_mode : 3; /* 000b: FIXED | 001b: lowest prior */ - __u32 reserved_1 : 3; - __u32 level : 1; /* 0: deassert | 1: assert */ - __u32 trigger : 1; /* 0: edge | 1: level */ - __u32 reserved_2 : 16; -#elif defined(__BIG_ENDIAN_BITFIELD) - __u32 reserved_2 : 16; - __u32 trigger : 1; /* 0: edge | 1: level */ - __u32 level : 1; /* 0: deassert | 1: assert */ - __u32 reserved_1 : 3; - __u32 delivery_mode : 3; /* 000b: FIXED | 001b: lowest prior */ - __u32 vector : 8; -#else -#error "Bitfield endianness not defined! Check your byteorder.h" -#endif -} __attribute__ ((packed)); - -struct msg_address { - union { - struct { -#if defined(__LITTLE_ENDIAN_BITFIELD) - __u32 reserved_1 : 2; - __u32 dest_mode : 1; /*0:physic | 1:logic */ - __u32 redirection_hint: 1; /*0: dedicated CPU - 1: lowest priority */ - __u32 reserved_2 : 4; - __u32 dest_id : 24; /* Destination ID */ -#elif defined(__BIG_ENDIAN_BITFIELD) - __u32 dest_id : 24; /* Destination ID */ - __u32 reserved_2 : 4; - __u32 redirection_hint: 1; /*0: dedicated CPU - 1: lowest priority */ - __u32 dest_mode : 1; /*0:physic | 1:logic */ - __u32 reserved_1 : 2; -#else -#error "Bitfield endianness not defined! Check your byteorder.h" -#endif - }u; - __u32 value; - }lo_address; - __u32 hi_address; -} __attribute__ ((packed)); - struct msi_desc { struct { __u8 type : 5; /* {0: unused, 5h:MSI, 11h:MSI-X} */ @@ -132,7 +133,7 @@ struct msi_desc { __u8 reserved: 1; /* reserved */ __u8 entry_nr; /* specific enabled entry */ __u8 default_vector; /* default pre-assigned vector */ - __u8 current_cpu; /* current destination cpu */ + __u8 unused; /* formerly unused destination cpu*/ }msi_attrib; struct { @@ -142,6 +143,14 @@ struct msi_desc { void __iomem *mask_base; struct pci_dev *dev; + +#ifdef CONFIG_PM + /* PM save area for MSIX address/data */ + + u32 address_hi_save; + u32 address_lo_save; + u32 data_save; +#endif }; #endif /* MSI_H */ diff --git a/include/asm-i386/msi.h b/include/asm-i386/msi.h index f041d4495fa..ed1014235e9 100644 --- a/include/asm-i386/msi.h +++ b/include/asm-i386/msi.h @@ -12,4 +12,12 @@ #define LAST_DEVICE_VECTOR 232 #define MSI_TARGET_CPU_SHIFT 12 +extern struct msi_ops msi_apic_ops; + +static inline int msi_arch_init(void) +{ + msi_register(&msi_apic_ops); + return 0; +} + #endif /* ASM_MSI_H */ diff --git a/include/asm-ia64/machvec.h b/include/asm-ia64/machvec.h index 0df72a134c8..15b545a897a 100644 --- a/include/asm-ia64/machvec.h +++ b/include/asm-ia64/machvec.h @@ -75,6 +75,7 @@ typedef unsigned char ia64_mv_readb_relaxed_t (const volatile void __iomem *); typedef unsigned short ia64_mv_readw_relaxed_t (const volatile void __iomem *); typedef unsigned int ia64_mv_readl_relaxed_t (const volatile void __iomem *); typedef unsigned long ia64_mv_readq_relaxed_t (const volatile void __iomem *); +typedef int ia64_mv_msi_init_t (void); static inline void machvec_noop (void) @@ -153,6 +154,7 @@ extern void machvec_tlb_migrate_finish (struct mm_struct *); # define platform_readl_relaxed ia64_mv.readl_relaxed # define platform_readq_relaxed ia64_mv.readq_relaxed # define platform_migrate ia64_mv.migrate +# define platform_msi_init ia64_mv.msi_init # endif /* __attribute__((__aligned__(16))) is required to make size of the @@ -202,6 +204,7 @@ struct ia64_machine_vector { ia64_mv_readl_relaxed_t *readl_relaxed; ia64_mv_readq_relaxed_t *readq_relaxed; ia64_mv_migrate_t *migrate; + ia64_mv_msi_init_t *msi_init; } __attribute__((__aligned__(16))); /* align attrib? see above comment */ #define MACHVEC_INIT(name) \ @@ -247,6 +250,7 @@ struct ia64_machine_vector { platform_readl_relaxed, \ platform_readq_relaxed, \ platform_migrate, \ + platform_msi_init, \ } extern struct ia64_machine_vector ia64_mv; @@ -400,5 +404,8 @@ extern int ia64_pci_legacy_write(struct pci_bus *bus, u16 port, u32 val, u8 size #ifndef platform_migrate # define platform_migrate machvec_noop_task #endif +#ifndef platform_msi_init +# define platform_msi_init ((ia64_mv_msi_init_t*)NULL) +#endif #endif /* _ASM_IA64_MACHVEC_H */ diff --git a/include/asm-ia64/machvec_sn2.h b/include/asm-ia64/machvec_sn2.h index da1d43755af..cf724dc79d8 100644 --- a/include/asm-ia64/machvec_sn2.h +++ b/include/asm-ia64/machvec_sn2.h @@ -67,6 +67,8 @@ extern ia64_mv_dma_sync_sg_for_device sn_dma_sync_sg_for_device; extern ia64_mv_dma_mapping_error sn_dma_mapping_error; extern ia64_mv_dma_supported sn_dma_supported; extern ia64_mv_migrate_t sn_migrate; +extern ia64_mv_msi_init_t sn_msi_init; + /* * This stuff has dual use! @@ -117,6 +119,11 @@ extern ia64_mv_migrate_t sn_migrate; #define platform_dma_mapping_error sn_dma_mapping_error #define platform_dma_supported sn_dma_supported #define platform_migrate sn_migrate +#ifdef CONFIG_PCI_MSI +#define platform_msi_init sn_msi_init +#else +#define platform_msi_init ((ia64_mv_msi_init_t*)NULL) +#endif #include diff --git a/include/asm-ia64/msi.h b/include/asm-ia64/msi.h index 97890f7762b..bb92b0dbde2 100644 --- a/include/asm-ia64/msi.h +++ b/include/asm-ia64/msi.h @@ -14,4 +14,16 @@ static inline void set_intr_gate (int nr, void *func) {} #define ack_APIC_irq ia64_eoi #define MSI_TARGET_CPU_SHIFT 4 +extern struct msi_ops msi_apic_ops; + +static inline int msi_arch_init(void) +{ + if (platform_msi_init) + return platform_msi_init(); + + /* default ops for most ia64 platforms */ + msi_register(&msi_apic_ops); + return 0; +} + #endif /* ASM_MSI_H */ diff --git a/include/asm-x86_64/msi.h b/include/asm-x86_64/msi.h index 356e0e82f50..8d6d6bf8fad 100644 --- a/include/asm-x86_64/msi.h +++ b/include/asm-x86_64/msi.h @@ -13,4 +13,12 @@ #define LAST_DEVICE_VECTOR 232 #define MSI_TARGET_CPU_SHIFT 12 +extern struct msi_ops msi_apic_ops; + +static inline int msi_arch_init(void) +{ + msi_register(&msi_apic_ops); + return 0; +} + #endif /* ASM_MSI_H */ -- cgit v1.2.3 From 10083072bfabc40bc47306e512c158c57cf55c2e Mon Sep 17 00:00:00 2001 From: Mark Maule Date: Fri, 14 Apr 2006 16:03:49 -0500 Subject: [PATCH] PCI: per-platform IA64_{FIRST,LAST}_DEVICE_VECTOR definitions Abstract IA64_FIRST_DEVICE_VECTOR/IA64_LAST_DEVICE_VECTOR since SN platforms use a subset of the IA64 range. Implement this by making the above macros global variables which the platform can override in it setup code. Also add a reserve_irq_vector() routine used by SN to mark a vector's as in-use when that weren't allocated through assign_irq_vector(). Signed-off-by: Mark Maule Signed-off-by: Greg Kroah-Hartman --- arch/ia64/kernel/irq_ia64.c | 19 ++++++++++++++++++- arch/ia64/sn/kernel/irq.c | 7 +++++++ drivers/pci/msi.c | 6 +++++- include/asm-ia64/hw_irq.h | 15 +++++++++++++-- 4 files changed, 43 insertions(+), 4 deletions(-) diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c index 6c4d59fd036..ef9a2b49307 100644 --- a/arch/ia64/kernel/irq_ia64.c +++ b/arch/ia64/kernel/irq_ia64.c @@ -46,6 +46,10 @@ #define IRQ_DEBUG 0 +/* These can be overridden in platform_irq_init */ +int ia64_first_device_vector = IA64_DEF_FIRST_DEVICE_VECTOR; +int ia64_last_device_vector = IA64_DEF_LAST_DEVICE_VECTOR; + /* default base addr of IPI table */ void __iomem *ipi_base_addr = ((void __iomem *) (__IA64_UNCACHED_OFFSET | IA64_IPI_DEFAULT_BASE_ADDR)); @@ -60,7 +64,7 @@ __u8 isa_irq_to_vector_map[16] = { }; EXPORT_SYMBOL(isa_irq_to_vector_map); -static unsigned long ia64_vector_mask[BITS_TO_LONGS(IA64_NUM_DEVICE_VECTORS)]; +static unsigned long ia64_vector_mask[BITS_TO_LONGS(IA64_MAX_DEVICE_VECTORS)]; int assign_irq_vector (int irq) @@ -89,6 +93,19 @@ free_irq_vector (int vector) printk(KERN_WARNING "%s: double free!\n", __FUNCTION__); } +int +reserve_irq_vector (int vector) +{ + int pos; + + if (vector < IA64_FIRST_DEVICE_VECTOR || + vector > IA64_LAST_DEVICE_VECTOR) + return -EINVAL; + + pos = vector - IA64_FIRST_DEVICE_VECTOR; + return test_and_set_bit(pos, ia64_vector_mask); +} + #ifdef CONFIG_SMP # define IS_RESCHEDULE(vec) (vec == IA64_IPI_RESCHEDULE) #else diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c index c265e02f503..db187f5cdae 100644 --- a/arch/ia64/sn/kernel/irq.c +++ b/arch/ia64/sn/kernel/irq.c @@ -202,6 +202,9 @@ void sn_irq_init(void) int i; irq_desc_t *base_desc = irq_desc; + ia64_first_device_vector = IA64_SN2_FIRST_DEVICE_VECTOR; + ia64_last_device_vector = IA64_SN2_LAST_DEVICE_VECTOR; + for (i = 0; i < NR_IRQS; i++) { if (base_desc[i].handler == &no_irq_type) { base_desc[i].handler = &irq_type_sn; @@ -285,6 +288,7 @@ void sn_irq_fixup(struct pci_dev *pci_dev, struct sn_irq_info *sn_irq_info) /* link it into the sn_irq[irq] list */ spin_lock(&sn_irq_info_lock); list_add_rcu(&sn_irq_info->list, sn_irq_lh[sn_irq_info->irq_irq]); + reserve_irq_vector(sn_irq_info->irq_irq); spin_unlock(&sn_irq_info_lock); register_intr_pda(sn_irq_info); @@ -310,8 +314,11 @@ void sn_irq_unfixup(struct pci_dev *pci_dev) spin_lock(&sn_irq_info_lock); list_del_rcu(&sn_irq_info->list); spin_unlock(&sn_irq_info_lock); + if (list_empty(sn_irq_lh[sn_irq_info->irq_irq])) + free_irq_vector(sn_irq_info->irq_irq); call_rcu(&sn_irq_info->rcu, sn_irq_info_free); pci_dev_put(pci_dev); + } static inline void diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 55ff52df5fe..f8105783da2 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -35,7 +35,7 @@ static int nr_msix_devices; #ifndef CONFIG_X86_IO_APIC int vector_irq[NR_VECTORS] = { [0 ... NR_VECTORS - 1] = -1}; -u8 irq_vector[NR_IRQ_VECTORS] = { FIRST_DEVICE_VECTOR , 0 }; +u8 irq_vector[NR_IRQ_VECTORS]; #endif static struct msi_ops *msi_ops; @@ -383,6 +383,10 @@ static int msi_init(void) return status; } +#ifndef CONFIG_X86_IO_APIC + irq_vector[0] = FIRST_DEVICE_VECTOR; +#endif + if (last_alloc_vector < 0) { pci_msi_enable = 0; printk(KERN_WARNING "PCI: No interrupt vectors available for MSI\n"); diff --git a/include/asm-ia64/hw_irq.h b/include/asm-ia64/hw_irq.h index 0cf119b42f7..ea8b8c407ab 100644 --- a/include/asm-ia64/hw_irq.h +++ b/include/asm-ia64/hw_irq.h @@ -47,9 +47,19 @@ typedef u8 ia64_vector; #define IA64_CMC_VECTOR 0x1f /* corrected machine-check interrupt vector */ /* * Vectors 0x20-0x2f are reserved for legacy ISA IRQs. + * Use vectors 0x30-0xe7 as the default device vector range for ia64. + * Platforms may choose to reduce this range in platform_irq_setup, but the + * platform range must fall within + * [IA64_DEF_FIRST_DEVICE_VECTOR..IA64_DEF_LAST_DEVICE_VECTOR] */ -#define IA64_FIRST_DEVICE_VECTOR 0x30 -#define IA64_LAST_DEVICE_VECTOR 0xe7 +extern int ia64_first_device_vector; +extern int ia64_last_device_vector; + +#define IA64_DEF_FIRST_DEVICE_VECTOR 0x30 +#define IA64_DEF_LAST_DEVICE_VECTOR 0xe7 +#define IA64_FIRST_DEVICE_VECTOR ia64_first_device_vector +#define IA64_LAST_DEVICE_VECTOR ia64_last_device_vector +#define IA64_MAX_DEVICE_VECTORS (IA64_DEF_LAST_DEVICE_VECTOR - IA64_DEF_FIRST_DEVICE_VECTOR + 1) #define IA64_NUM_DEVICE_VECTORS (IA64_LAST_DEVICE_VECTOR - IA64_FIRST_DEVICE_VECTOR + 1) #define IA64_MCA_RENDEZ_VECTOR 0xe8 /* MCA rendez interrupt */ @@ -83,6 +93,7 @@ extern struct hw_interrupt_type irq_type_ia64_lsapic; /* CPU-internal interrupt extern int assign_irq_vector (int irq); /* allocate a free vector */ extern void free_irq_vector (int vector); +extern int reserve_irq_vector (int vector); extern void ia64_send_ipi (int cpu, int vector, int delivery_mode, int redirect); extern void register_percpu_irq (ia64_vector vec, struct irqaction *action); -- cgit v1.2.3 From 83821d3f558dc651e555d62182ed0c95651f41a6 Mon Sep 17 00:00:00 2001 From: Mark Maule Date: Fri, 14 Apr 2006 16:03:54 -0500 Subject: [PATCH] PCI: altix: msi support MSI callouts for altix. Involves a fair amount of code reorg in sn irq.c code as well as adding some extensions to the altix PCI provider abstaction. Signed-off-by: Mark Maule Signed-off-by: Greg Kroah-Hartman --- arch/ia64/sn/kernel/io_init.c | 9 +- arch/ia64/sn/kernel/irq.c | 135 ++++++++++--------- arch/ia64/sn/pci/pci_dma.c | 10 +- arch/ia64/sn/pci/pcibr/pcibr_dma.c | 62 ++++++--- arch/ia64/sn/pci/tioca_provider.c | 8 +- arch/ia64/sn/pci/tioce_provider.c | 65 ++++++---- drivers/pci/msi-altix.c | 200 ++++++++++++++++++++++++++++- include/asm-ia64/sn/intr.h | 8 ++ include/asm-ia64/sn/pcibr_provider.h | 5 +- include/asm-ia64/sn/pcibus_provider_defs.h | 17 ++- include/asm-ia64/sn/tiocp.h | 3 +- 11 files changed, 401 insertions(+), 121 deletions(-) diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c index 5101ac46264..dc09a6a28a3 100644 --- a/arch/ia64/sn/kernel/io_init.c +++ b/arch/ia64/sn/kernel/io_init.c @@ -58,7 +58,7 @@ static int max_pcibus_number = 255; /* Default highest pci bus number */ */ static dma_addr_t -sn_default_pci_map(struct pci_dev *pdev, unsigned long paddr, size_t size) +sn_default_pci_map(struct pci_dev *pdev, unsigned long paddr, size_t size, int type) { return 0; } @@ -457,13 +457,6 @@ void sn_pci_fixup_slot(struct pci_dev *dev) pcidev_info->pdi_sn_irq_info = NULL; kfree(sn_irq_info); } - - /* - * MSI currently not supported on altix. Remove this when - * the MSI abstraction patches are integrated into the kernel - * (sometime after 2.6.16 releases) - */ - dev->no_msi = 1; } /* diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c index db187f5cdae..dc8e2b69671 100644 --- a/arch/ia64/sn/kernel/irq.c +++ b/arch/ia64/sn/kernel/irq.c @@ -26,11 +26,11 @@ static void unregister_intr_pda(struct sn_irq_info *sn_irq_info); int sn_force_interrupt_flag = 1; extern int sn_ioif_inited; -static struct list_head **sn_irq_lh; +struct list_head **sn_irq_lh; static spinlock_t sn_irq_info_lock = SPIN_LOCK_UNLOCKED; /* non-IRQ lock */ -static inline u64 sn_intr_alloc(nasid_t local_nasid, int local_widget, - u64 sn_irq_info, +u64 sn_intr_alloc(nasid_t local_nasid, int local_widget, + struct sn_irq_info *sn_irq_info, int req_irq, nasid_t req_nasid, int req_slice) { @@ -40,12 +40,13 @@ static inline u64 sn_intr_alloc(nasid_t local_nasid, int local_widget, SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_INTERRUPT, (u64) SAL_INTR_ALLOC, (u64) local_nasid, - (u64) local_widget, (u64) sn_irq_info, (u64) req_irq, + (u64) local_widget, __pa(sn_irq_info), (u64) req_irq, (u64) req_nasid, (u64) req_slice); + return ret_stuff.status; } -static inline void sn_intr_free(nasid_t local_nasid, int local_widget, +void sn_intr_free(nasid_t local_nasid, int local_widget, struct sn_irq_info *sn_irq_info) { struct ia64_sal_retval ret_stuff; @@ -112,73 +113,91 @@ static void sn_end_irq(unsigned int irq) static void sn_irq_info_free(struct rcu_head *head); -static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask) +struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info, + nasid_t nasid, int slice) { - struct sn_irq_info *sn_irq_info, *sn_irq_info_safe; - int cpuid, cpuphys; + int vector; + int cpuphys; + int64_t bridge; + int local_widget, status; + nasid_t local_nasid; + struct sn_irq_info *new_irq_info; + struct sn_pcibus_provider *pci_provider; - cpuid = first_cpu(mask); - cpuphys = cpu_physical_id(cpuid); + new_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_ATOMIC); + if (new_irq_info == NULL) + return NULL; - list_for_each_entry_safe(sn_irq_info, sn_irq_info_safe, - sn_irq_lh[irq], list) { - u64 bridge; - int local_widget, status; - nasid_t local_nasid; - struct sn_irq_info *new_irq_info; - struct sn_pcibus_provider *pci_provider; - - new_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_ATOMIC); - if (new_irq_info == NULL) - break; - memcpy(new_irq_info, sn_irq_info, sizeof(struct sn_irq_info)); - - bridge = (u64) new_irq_info->irq_bridge; - if (!bridge) { - kfree(new_irq_info); - break; /* irq is not a device interrupt */ - } + memcpy(new_irq_info, sn_irq_info, sizeof(struct sn_irq_info)); - local_nasid = NASID_GET(bridge); + bridge = (u64) new_irq_info->irq_bridge; + if (!bridge) { + kfree(new_irq_info); + return NULL; /* irq is not a device interrupt */ + } - if (local_nasid & 1) - local_widget = TIO_SWIN_WIDGETNUM(bridge); - else - local_widget = SWIN_WIDGETNUM(bridge); + local_nasid = NASID_GET(bridge); - /* Free the old PROM new_irq_info structure */ - sn_intr_free(local_nasid, local_widget, new_irq_info); - /* Update kernels new_irq_info with new target info */ - unregister_intr_pda(new_irq_info); + if (local_nasid & 1) + local_widget = TIO_SWIN_WIDGETNUM(bridge); + else + local_widget = SWIN_WIDGETNUM(bridge); - /* allocate a new PROM new_irq_info struct */ - status = sn_intr_alloc(local_nasid, local_widget, - __pa(new_irq_info), irq, - cpuid_to_nasid(cpuid), - cpuid_to_slice(cpuid)); + vector = sn_irq_info->irq_irq; + /* Free the old PROM new_irq_info structure */ + sn_intr_free(local_nasid, local_widget, new_irq_info); + /* Update kernels new_irq_info with new target info */ + unregister_intr_pda(new_irq_info); - /* SAL call failed */ - if (status) { - kfree(new_irq_info); - break; - } + /* allocate a new PROM new_irq_info struct */ + status = sn_intr_alloc(local_nasid, local_widget, + new_irq_info, vector, + nasid, slice); + + /* SAL call failed */ + if (status) { + kfree(new_irq_info); + return NULL; + } - new_irq_info->irq_cpuid = cpuid; - register_intr_pda(new_irq_info); + cpuphys = nasid_slice_to_cpuid(nasid, slice); + new_irq_info->irq_cpuid = cpuphys; + register_intr_pda(new_irq_info); - pci_provider = sn_pci_provider[new_irq_info->irq_bridge_type]; - if (pci_provider && pci_provider->target_interrupt) - (pci_provider->target_interrupt)(new_irq_info); + pci_provider = sn_pci_provider[new_irq_info->irq_bridge_type]; + + /* + * If this represents a line interrupt, target it. If it's + * an msi (irq_int_bit < 0), it's already targeted. + */ + if (new_irq_info->irq_int_bit >= 0 && + pci_provider && pci_provider->target_interrupt) + (pci_provider->target_interrupt)(new_irq_info); - spin_lock(&sn_irq_info_lock); - list_replace_rcu(&sn_irq_info->list, &new_irq_info->list); - spin_unlock(&sn_irq_info_lock); - call_rcu(&sn_irq_info->rcu, sn_irq_info_free); + spin_lock(&sn_irq_info_lock); + list_replace_rcu(&sn_irq_info->list, &new_irq_info->list); + spin_unlock(&sn_irq_info_lock); + call_rcu(&sn_irq_info->rcu, sn_irq_info_free); #ifdef CONFIG_SMP - set_irq_affinity_info((irq & 0xff), cpuphys, 0); + set_irq_affinity_info((vector & 0xff), cpuphys, 0); #endif - } + + return new_irq_info; +} + +static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask) +{ + struct sn_irq_info *sn_irq_info, *sn_irq_info_safe; + nasid_t nasid; + int slice; + + nasid = cpuid_to_nasid(first_cpu(mask)); + slice = cpuid_to_slice(first_cpu(mask)); + + list_for_each_entry_safe(sn_irq_info, sn_irq_info_safe, + sn_irq_lh[irq], list) + (void)sn_retarget_vector(sn_irq_info, nasid, slice); } struct hw_interrupt_type irq_type_sn = { diff --git a/arch/ia64/sn/pci/pci_dma.c b/arch/ia64/sn/pci/pci_dma.c index b4b84c26921..7a291a27151 100644 --- a/arch/ia64/sn/pci/pci_dma.c +++ b/arch/ia64/sn/pci/pci_dma.c @@ -11,7 +11,7 @@ #include #include -#include +#include #include #include #include @@ -113,7 +113,8 @@ void *sn_dma_alloc_coherent(struct device *dev, size_t size, * resources. */ - *dma_handle = provider->dma_map_consistent(pdev, phys_addr, size); + *dma_handle = provider->dma_map_consistent(pdev, phys_addr, size, + SN_DMA_ADDR_PHYS); if (!*dma_handle) { printk(KERN_ERR "%s: out of ATEs\n", __FUNCTION__); free_pages((unsigned long)cpuaddr, get_order(size)); @@ -176,7 +177,7 @@ dma_addr_t sn_dma_map_single(struct device *dev, void *cpu_addr, size_t size, BUG_ON(dev->bus != &pci_bus_type); phys_addr = __pa(cpu_addr); - dma_addr = provider->dma_map(pdev, phys_addr, size); + dma_addr = provider->dma_map(pdev, phys_addr, size, SN_DMA_ADDR_PHYS); if (!dma_addr) { printk(KERN_ERR "%s: out of ATEs\n", __FUNCTION__); return 0; @@ -260,7 +261,8 @@ int sn_dma_map_sg(struct device *dev, struct scatterlist *sg, int nhwentries, for (i = 0; i < nhwentries; i++, sg++) { phys_addr = SG_ENT_PHYS_ADDRESS(sg); sg->dma_address = provider->dma_map(pdev, - phys_addr, sg->length); + phys_addr, sg->length, + SN_DMA_ADDR_PHYS); if (!sg->dma_address) { printk(KERN_ERR "%s: out of ATEs\n", __FUNCTION__); diff --git a/arch/ia64/sn/pci/pcibr/pcibr_dma.c b/arch/ia64/sn/pci/pcibr/pcibr_dma.c index 9f86bb6519a..a86c7b94596 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_dma.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_dma.c @@ -41,7 +41,7 @@ extern int sn_ioif_inited; static dma_addr_t pcibr_dmamap_ate32(struct pcidev_info *info, - u64 paddr, size_t req_size, u64 flags) + u64 paddr, size_t req_size, u64 flags, int dma_flags) { struct pcidev_info *pcidev_info = info->pdi_host_pcidev_info; @@ -81,9 +81,12 @@ pcibr_dmamap_ate32(struct pcidev_info *info, if (IS_PCIX(pcibus_info)) ate_flags &= ~(PCI32_ATE_PREF); - xio_addr = - IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) : - PHYS_TO_TIODMA(paddr); + if (SN_DMA_ADDRTYPE(dma_flags == SN_DMA_ADDR_PHYS)) + xio_addr = IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) : + PHYS_TO_TIODMA(paddr); + else + xio_addr = paddr; + offset = IOPGOFF(xio_addr); ate = ate_flags | (xio_addr - offset); @@ -91,6 +94,13 @@ pcibr_dmamap_ate32(struct pcidev_info *info, if (IS_PIC_SOFT(pcibus_info)) { ate |= (pcibus_info->pbi_hub_xid << PIC_ATE_TARGETID_SHFT); } + + /* + * If we're mapping for MSI, set the MSI bit in the ATE + */ + if (dma_flags & SN_DMA_MSI) + ate |= PCI32_ATE_MSI; + ate_write(pcibus_info, ate_index, ate_count, ate); /* @@ -105,20 +115,27 @@ pcibr_dmamap_ate32(struct pcidev_info *info, if (pcibus_info->pbi_devreg[internal_device] & PCIBR_DEV_SWAP_DIR) ATE_SWAP_ON(pci_addr); + return pci_addr; } static dma_addr_t pcibr_dmatrans_direct64(struct pcidev_info * info, u64 paddr, - u64 dma_attributes) + u64 dma_attributes, int dma_flags) { struct pcibus_info *pcibus_info = (struct pcibus_info *) ((info->pdi_host_pcidev_info)->pdi_pcibus_info); u64 pci_addr; /* Translate to Crosstalk View of Physical Address */ - pci_addr = (IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) : - PHYS_TO_TIODMA(paddr)) | dma_attributes; + if (SN_DMA_ADDRTYPE(dma_flags) == SN_DMA_ADDR_PHYS) + pci_addr = IS_PIC_SOFT(pcibus_info) ? + PHYS_TO_DMA(paddr) : + PHYS_TO_TIODMA(paddr) | dma_attributes; + else + pci_addr = IS_PIC_SOFT(pcibus_info) ? + paddr : + paddr | dma_attributes; /* Handle Bus mode */ if (IS_PCIX(pcibus_info)) @@ -130,7 +147,9 @@ pcibr_dmatrans_direct64(struct pcidev_info * info, u64 paddr, ((u64) pcibus_info-> pbi_hub_xid << PIC_PCI64_ATTR_TARG_SHFT); } else - pci_addr |= TIOCP_PCI64_CMDTYPE_MEM; + pci_addr |= (dma_flags & SN_DMA_MSI) ? + TIOCP_PCI64_CMDTYPE_MSI : + TIOCP_PCI64_CMDTYPE_MEM; /* If PCI mode, func zero uses VCHAN0, every other func uses VCHAN1 */ if (!IS_PCIX(pcibus_info) && PCI_FUNC(info->pdi_linux_pcidev->devfn)) @@ -141,7 +160,7 @@ pcibr_dmatrans_direct64(struct pcidev_info * info, u64 paddr, static dma_addr_t pcibr_dmatrans_direct32(struct pcidev_info * info, - u64 paddr, size_t req_size, u64 flags) + u64 paddr, size_t req_size, u64 flags, int dma_flags) { struct pcidev_info *pcidev_info = info->pdi_host_pcidev_info; struct pcibus_info *pcibus_info = (struct pcibus_info *)pcidev_info-> @@ -156,8 +175,14 @@ pcibr_dmatrans_direct32(struct pcidev_info * info, return 0; } - xio_addr = IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) : - PHYS_TO_TIODMA(paddr); + if (dma_flags & SN_DMA_MSI) + return 0; + + if (SN_DMA_ADDRTYPE(dma_flags) == SN_DMA_ADDR_PHYS) + xio_addr = IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) : + PHYS_TO_TIODMA(paddr); + else + xio_addr = paddr; xio_base = pcibus_info->pbi_dir_xbase; offset = xio_addr - xio_base; @@ -327,7 +352,7 @@ void sn_dma_flush(u64 addr) */ dma_addr_t -pcibr_dma_map(struct pci_dev * hwdev, unsigned long phys_addr, size_t size) +pcibr_dma_map(struct pci_dev * hwdev, unsigned long phys_addr, size_t size, int dma_flags) { dma_addr_t dma_handle; struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(hwdev); @@ -344,11 +369,11 @@ pcibr_dma_map(struct pci_dev * hwdev, unsigned long phys_addr, size_t size) */ dma_handle = pcibr_dmatrans_direct64(pcidev_info, phys_addr, - PCI64_ATTR_PREF); + PCI64_ATTR_PREF, dma_flags); } else { /* Handle 32-63 bit cards via direct mapping */ dma_handle = pcibr_dmatrans_direct32(pcidev_info, phys_addr, - size, 0); + size, 0, dma_flags); if (!dma_handle) { /* * It is a 32 bit card and we cannot do direct mapping, @@ -356,7 +381,8 @@ pcibr_dma_map(struct pci_dev * hwdev, unsigned long phys_addr, size_t size) */ dma_handle = pcibr_dmamap_ate32(pcidev_info, phys_addr, - size, PCI32_ATE_PREF); + size, PCI32_ATE_PREF, + dma_flags); } } @@ -365,18 +391,18 @@ pcibr_dma_map(struct pci_dev * hwdev, unsigned long phys_addr, size_t size) dma_addr_t pcibr_dma_map_consistent(struct pci_dev * hwdev, unsigned long phys_addr, - size_t size) + size_t size, int dma_flags) { dma_addr_t dma_handle; struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(hwdev); if (hwdev->dev.coherent_dma_mask == ~0UL) { dma_handle = pcibr_dmatrans_direct64(pcidev_info, phys_addr, - PCI64_ATTR_BAR); + PCI64_ATTR_BAR, dma_flags); } else { dma_handle = (dma_addr_t) pcibr_dmamap_ate32(pcidev_info, phys_addr, size, - PCI32_ATE_BAR); + PCI32_ATE_BAR, dma_flags); } return dma_handle; diff --git a/arch/ia64/sn/pci/tioca_provider.c b/arch/ia64/sn/pci/tioca_provider.c index be017691296..20de72791b9 100644 --- a/arch/ia64/sn/pci/tioca_provider.c +++ b/arch/ia64/sn/pci/tioca_provider.c @@ -515,10 +515,16 @@ tioca_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir) * use the GART mapped mode. */ static u64 -tioca_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count) +tioca_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count, int dma_flags) { u64 mapaddr; + /* + * Not supported for now ... + */ + if (dma_flags & SN_DMA_MSI) + return 0; + /* * If card is 64 or 48 bit addresable, use a direct mapping. 32 * bit direct is so restrictive w.r.t. where the memory resides that diff --git a/arch/ia64/sn/pci/tioce_provider.c b/arch/ia64/sn/pci/tioce_provider.c index 833295624e5..4cac7bdc7c7 100644 --- a/arch/ia64/sn/pci/tioce_provider.c +++ b/arch/ia64/sn/pci/tioce_provider.c @@ -170,7 +170,8 @@ tioce_mmr_war_post(struct tioce_kernel *kern, void *mmr_addr) (ATE_PAGE((start)+(len)-1, pagesize) - ATE_PAGE(start, pagesize) + 1) #define ATE_VALID(ate) ((ate) & (1UL << 63)) -#define ATE_MAKE(addr, ps) (((addr) & ~ATE_PAGEMASK(ps)) | (1UL << 63)) +#define ATE_MAKE(addr, ps, msi) \ + (((addr) & ~ATE_PAGEMASK(ps)) | (1UL << 63) | ((msi)?(1UL << 62):0)) /* * Flavors of ate-based mapping supported by tioce_alloc_map() @@ -196,15 +197,17 @@ tioce_mmr_war_post(struct tioce_kernel *kern, void *mmr_addr) * * 63 - must be 1 to indicate d64 mode to CE hardware * 62 - barrier bit ... controlled with tioce_dma_barrier() - * 61 - 0 since this is not an MSI transaction + * 61 - msi bit ... specified through dma_flags * 60:54 - reserved, MBZ */ static u64 -tioce_dma_d64(unsigned long ct_addr) +tioce_dma_d64(unsigned long ct_addr, int dma_flags) { u64 bus_addr; bus_addr = ct_addr | (1UL << 63); + if (dma_flags & SN_DMA_MSI) + bus_addr |= (1UL << 61); return bus_addr; } @@ -261,7 +264,7 @@ pcidev_to_tioce(struct pci_dev *pdev, struct tioce **base, */ static u64 tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port, - u64 ct_addr, int len) + u64 ct_addr, int len, int dma_flags) { int i; int j; @@ -270,6 +273,7 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port, int entries; int nates; u64 pagesize; + int msi_capable, msi_wanted; u64 *ate_shadow; u64 *ate_reg; u64 addr; @@ -291,6 +295,7 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port, ate_reg = ce_mmr->ce_ure_ate3240; pagesize = ce_kern->ce_ate3240_pagesize; bus_base = TIOCE_M32_MIN; + msi_capable = 1; break; case TIOCE_ATE_M40: first = 0; @@ -299,6 +304,7 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port, ate_reg = ce_mmr->ce_ure_ate40; pagesize = MB(64); bus_base = TIOCE_M40_MIN; + msi_capable = 0; break; case TIOCE_ATE_M40S: /* @@ -311,11 +317,16 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port, ate_reg = ce_mmr->ce_ure_ate3240; pagesize = GB(16); bus_base = TIOCE_M40S_MIN; + msi_capable = 0; break; default: return 0; } + msi_wanted = dma_flags & SN_DMA_MSI; + if (msi_wanted && !msi_capable) + return 0; + nates = ATE_NPAGES(ct_addr, len, pagesize); if (nates > entries) return 0; @@ -344,7 +355,7 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port, for (j = 0; j < nates; j++) { u64 ate; - ate = ATE_MAKE(addr, pagesize); + ate = ATE_MAKE(addr, pagesize, msi_wanted); ate_shadow[i + j] = ate; tioce_mmr_storei(ce_kern, &ate_reg[i + j], ate); addr += pagesize; @@ -371,7 +382,7 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port, * Map @paddr into 32-bit bus space of the CE associated with @pcidev_info. */ static u64 -tioce_dma_d32(struct pci_dev *pdev, u64 ct_addr) +tioce_dma_d32(struct pci_dev *pdev, u64 ct_addr, int dma_flags) { int dma_ok; int port; @@ -381,6 +392,9 @@ tioce_dma_d32(struct pci_dev *pdev, u64 ct_addr) u64 ct_lower; dma_addr_t bus_addr; + if (dma_flags & SN_DMA_MSI) + return 0; + ct_upper = ct_addr & ~0x3fffffffUL; ct_lower = ct_addr & 0x3fffffffUL; @@ -507,7 +521,7 @@ tioce_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir) */ static u64 tioce_do_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count, - int barrier) + int barrier, int dma_flags) { unsigned long flags; u64 ct_addr; @@ -523,15 +537,18 @@ tioce_do_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count, if (dma_mask < 0x7fffffffUL) return 0; - ct_addr = PHYS_TO_TIODMA(paddr); + if (SN_DMA_ADDRTYPE(dma_flags) == SN_DMA_ADDR_PHYS) + ct_addr = PHYS_TO_TIODMA(paddr); + else + ct_addr = paddr; /* * If the device can generate 64 bit addresses, create a D64 map. - * Since this should never fail, bypass the rest of the checks. */ if (dma_mask == ~0UL) { - mapaddr = tioce_dma_d64(ct_addr); - goto dma_map_done; + mapaddr = tioce_dma_d64(ct_addr, dma_flags); + if (mapaddr) + goto dma_map_done; } pcidev_to_tioce(pdev, NULL, &ce_kern, &port); @@ -574,18 +591,22 @@ tioce_do_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count, if (byte_count > MB(64)) { mapaddr = tioce_alloc_map(ce_kern, TIOCE_ATE_M40S, - port, ct_addr, byte_count); + port, ct_addr, byte_count, + dma_flags); if (!mapaddr) mapaddr = tioce_alloc_map(ce_kern, TIOCE_ATE_M40, -1, - ct_addr, byte_count); + ct_addr, byte_count, + dma_flags); } else { mapaddr = tioce_alloc_map(ce_kern, TIOCE_ATE_M40, -1, - ct_addr, byte_count); + ct_addr, byte_count, + dma_flags); if (!mapaddr) mapaddr = tioce_alloc_map(ce_kern, TIOCE_ATE_M40S, - port, ct_addr, byte_count); + port, ct_addr, byte_count, + dma_flags); } } @@ -593,7 +614,7 @@ tioce_do_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count, * 32-bit direct is the next mode to try */ if (!mapaddr && dma_mask >= 0xffffffffUL) - mapaddr = tioce_dma_d32(pdev, ct_addr); + mapaddr = tioce_dma_d32(pdev, ct_addr, dma_flags); /* * Last resort, try 32-bit ATE-based map. @@ -601,7 +622,7 @@ tioce_do_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count, if (!mapaddr) mapaddr = tioce_alloc_map(ce_kern, TIOCE_ATE_M32, -1, ct_addr, - byte_count); + byte_count, dma_flags); spin_unlock_irqrestore(&ce_kern->ce_lock, flags); @@ -622,9 +643,9 @@ dma_map_done: * in the address. */ static u64 -tioce_dma(struct pci_dev *pdev, u64 paddr, size_t byte_count) +tioce_dma(struct pci_dev *pdev, u64 paddr, size_t byte_count, int dma_flags) { - return tioce_do_dma_map(pdev, paddr, byte_count, 0); + return tioce_do_dma_map(pdev, paddr, byte_count, 0, dma_flags); } /** @@ -636,9 +657,9 @@ tioce_dma(struct pci_dev *pdev, u64 paddr, size_t byte_count) * Simply call tioce_do_dma_map() to create a map with the barrier bit set * in the address. */ static u64 -tioce_dma_consistent(struct pci_dev *pdev, u64 paddr, size_t byte_count) +tioce_dma_consistent(struct pci_dev *pdev, u64 paddr, size_t byte_count, int dma_flags) { - return tioce_do_dma_map(pdev, paddr, byte_count, 1); + return tioce_do_dma_map(pdev, paddr, byte_count, 1, dma_flags); } /** @@ -696,7 +717,7 @@ tioce_reserve_m32(struct tioce_kernel *ce_kern, u64 base, u64 limit) while (ate_index <= last_ate) { u64 ate; - ate = ATE_MAKE(0xdeadbeef, ps); + ate = ATE_MAKE(0xdeadbeef, ps, 0); ce_kern->ce_ate3240_shadow[ate_index] = ate; tioce_mmr_storei(ce_kern, &ce_mmr->ce_ure_ate3240[ate_index], ate); diff --git a/drivers/pci/msi-altix.c b/drivers/pci/msi-altix.c index 9bd240602c1..bed4183a5e3 100644 --- a/drivers/pci/msi-altix.c +++ b/drivers/pci/msi-altix.c @@ -6,13 +6,205 @@ * Copyright (C) 2006 Silicon Graphics, Inc. All Rights Reserved. */ -#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "msi.h" + +struct sn_msi_info { + u64 pci_addr; + struct sn_irq_info *sn_irq_info; +}; + +static struct sn_msi_info *sn_msi_info; + +static void +sn_msi_teardown(unsigned int vector) +{ + nasid_t nasid; + int widget; + struct pci_dev *pdev; + struct pcidev_info *sn_pdev; + struct sn_irq_info *sn_irq_info; + struct pcibus_bussoft *bussoft; + struct sn_pcibus_provider *provider; + + sn_irq_info = sn_msi_info[vector].sn_irq_info; + if (sn_irq_info == NULL || sn_irq_info->irq_int_bit >= 0) + return; + + sn_pdev = (struct pcidev_info *)sn_irq_info->irq_pciioinfo; + pdev = sn_pdev->pdi_linux_pcidev; + provider = SN_PCIDEV_BUSPROVIDER(pdev); + + (*provider->dma_unmap)(pdev, + sn_msi_info[vector].pci_addr, + PCI_DMA_FROMDEVICE); + sn_msi_info[vector].pci_addr = 0; + + bussoft = SN_PCIDEV_BUSSOFT(pdev); + nasid = NASID_GET(bussoft->bs_base); + widget = (nasid & 1) ? + TIO_SWIN_WIDGETNUM(bussoft->bs_base) : + SWIN_WIDGETNUM(bussoft->bs_base); + + sn_intr_free(nasid, widget, sn_irq_info); + sn_msi_info[vector].sn_irq_info = NULL; + + return; +} int -sn_msi_init(void) +sn_msi_setup(struct pci_dev *pdev, unsigned int vector, + u32 *addr_hi, u32 *addr_lo, u32 *data) { + int widget; + int status; + nasid_t nasid; + u64 bus_addr; + struct sn_irq_info *sn_irq_info; + struct pcibus_bussoft *bussoft = SN_PCIDEV_BUSSOFT(pdev); + struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev); + + if (bussoft == NULL) + return -EINVAL; + + if (provider == NULL || provider->dma_map_consistent == NULL) + return -EINVAL; + + /* + * Set up the vector plumbing. Let the prom (via sn_intr_alloc) + * decide which cpu to direct this msi at by default. + */ + + nasid = NASID_GET(bussoft->bs_base); + widget = (nasid & 1) ? + TIO_SWIN_WIDGETNUM(bussoft->bs_base) : + SWIN_WIDGETNUM(bussoft->bs_base); + + sn_irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL); + if (! sn_irq_info) + return -ENOMEM; + + status = sn_intr_alloc(nasid, widget, sn_irq_info, vector, -1, -1); + if (status) { + kfree(sn_irq_info); + return -ENOMEM; + } + + sn_irq_info->irq_int_bit = -1; /* mark this as an MSI irq */ + sn_irq_fixup(pdev, sn_irq_info); + + /* Prom probably should fill these in, but doesn't ... */ + sn_irq_info->irq_bridge_type = bussoft->bs_asic_type; + sn_irq_info->irq_bridge = (void *)bussoft->bs_base; + /* - * return error until MSI is supported on altix platforms + * Map the xio address into bus space */ - return -EINVAL; + bus_addr = (*provider->dma_map_consistent)(pdev, + sn_irq_info->irq_xtalkaddr, + sizeof(sn_irq_info->irq_xtalkaddr), + SN_DMA_MSI|SN_DMA_ADDR_XIO); + if (! bus_addr) { + sn_intr_free(nasid, widget, sn_irq_info); + kfree(sn_irq_info); + return -ENOMEM; + } + + sn_msi_info[vector].sn_irq_info = sn_irq_info; + sn_msi_info[vector].pci_addr = bus_addr; + + *addr_hi = (u32)(bus_addr >> 32); + *addr_lo = (u32)(bus_addr & 0x00000000ffffffff); + + /* + * In the SN platform, bit 16 is a "send vector" bit which + * must be present in order to move the vector through the system. + */ + *data = 0x100 + (unsigned int)vector; + +#ifdef CONFIG_SMP + set_irq_affinity_info((vector & 0xff), sn_irq_info->irq_cpuid, 0); +#endif + + return 0; +} + +static void +sn_msi_target(unsigned int vector, unsigned int cpu, + u32 *addr_hi, u32 *addr_lo) +{ + int slice; + nasid_t nasid; + u64 bus_addr; + struct pci_dev *pdev; + struct pcidev_info *sn_pdev; + struct sn_irq_info *sn_irq_info; + struct sn_irq_info *new_irq_info; + struct sn_pcibus_provider *provider; + + sn_irq_info = sn_msi_info[vector].sn_irq_info; + if (sn_irq_info == NULL || sn_irq_info->irq_int_bit >= 0) + return; + + /* + * Release XIO resources for the old MSI PCI address + */ + + sn_pdev = (struct pcidev_info *)sn_irq_info->irq_pciioinfo; + pdev = sn_pdev->pdi_linux_pcidev; + provider = SN_PCIDEV_BUSPROVIDER(pdev); + + bus_addr = (u64)(*addr_hi) << 32 | (u64)(*addr_lo); + (*provider->dma_unmap)(pdev, bus_addr, PCI_DMA_FROMDEVICE); + sn_msi_info[vector].pci_addr = 0; + + nasid = cpuid_to_nasid(cpu); + slice = cpuid_to_slice(cpu); + + new_irq_info = sn_retarget_vector(sn_irq_info, nasid, slice); + sn_msi_info[vector].sn_irq_info = new_irq_info; + if (new_irq_info == NULL) + return; + + /* + * Map the xio address into bus space + */ + + bus_addr = (*provider->dma_map_consistent)(pdev, + new_irq_info->irq_xtalkaddr, + sizeof(new_irq_info->irq_xtalkaddr), + SN_DMA_MSI|SN_DMA_ADDR_XIO); + + sn_msi_info[vector].pci_addr = bus_addr; + *addr_hi = (u32)(bus_addr >> 32); + *addr_lo = (u32)(bus_addr & 0x00000000ffffffff); +} + +struct msi_ops sn_msi_ops = { + .setup = sn_msi_setup, + .teardown = sn_msi_teardown, +#ifdef CONFIG_SMP + .target = sn_msi_target, +#endif +}; + +int +sn_msi_init(void) +{ + sn_msi_info = + kzalloc(sizeof(struct sn_msi_info) * NR_VECTORS, GFP_KERNEL); + if (! sn_msi_info) + return -ENOMEM; + + msi_register(&sn_msi_ops); + return 0; } diff --git a/include/asm-ia64/sn/intr.h b/include/asm-ia64/sn/intr.h index 60a51a406ee..12b54ddb06b 100644 --- a/include/asm-ia64/sn/intr.h +++ b/include/asm-ia64/sn/intr.h @@ -10,6 +10,7 @@ #define _ASM_IA64_SN_INTR_H #include +#include #define SGI_UART_VECTOR 0xe9 @@ -40,6 +41,7 @@ struct sn_irq_info { int irq_cpuid; /* kernel logical cpuid */ int irq_irq; /* the IRQ number */ int irq_int_bit; /* Bridge interrupt pin */ + /* <0 means MSI */ u64 irq_xtalkaddr; /* xtalkaddr IRQ is sent to */ int irq_bridge_type;/* pciio asic type (pciio.h) */ void *irq_bridge; /* bridge generating irq */ @@ -53,6 +55,12 @@ struct sn_irq_info { }; extern void sn_send_IPI_phys(int, long, int, int); +extern u64 sn_intr_alloc(nasid_t, int, + struct sn_irq_info *, + int, nasid_t, int); +extern void sn_intr_free(nasid_t, int, struct sn_irq_info *); +extern struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *, nasid_t, int); +extern struct list_head **sn_irq_lh; #define CPU_VECTOR_TO_IRQ(cpuid,vector) (vector) diff --git a/include/asm-ia64/sn/pcibr_provider.h b/include/asm-ia64/sn/pcibr_provider.h index 51260ab70d9..e3b0c3fe5ee 100644 --- a/include/asm-ia64/sn/pcibr_provider.h +++ b/include/asm-ia64/sn/pcibr_provider.h @@ -55,6 +55,7 @@ #define PCI32_ATE_V (0x1 << 0) #define PCI32_ATE_CO (0x1 << 1) #define PCI32_ATE_PREC (0x1 << 2) +#define PCI32_ATE_MSI (0x1 << 2) #define PCI32_ATE_PREF (0x1 << 3) #define PCI32_ATE_BAR (0x1 << 4) #define PCI32_ATE_ADDR_SHFT 12 @@ -117,8 +118,8 @@ struct pcibus_info { extern int pcibr_init_provider(void); extern void *pcibr_bus_fixup(struct pcibus_bussoft *, struct pci_controller *); -extern dma_addr_t pcibr_dma_map(struct pci_dev *, unsigned long, size_t); -extern dma_addr_t pcibr_dma_map_consistent(struct pci_dev *, unsigned long, size_t); +extern dma_addr_t pcibr_dma_map(struct pci_dev *, unsigned long, size_t, int type); +extern dma_addr_t pcibr_dma_map_consistent(struct pci_dev *, unsigned long, size_t, int type); extern void pcibr_dma_unmap(struct pci_dev *, dma_addr_t, int); /* diff --git a/include/asm-ia64/sn/pcibus_provider_defs.h b/include/asm-ia64/sn/pcibus_provider_defs.h index ce3f6c32824..8f7c83d0f6d 100644 --- a/include/asm-ia64/sn/pcibus_provider_defs.h +++ b/include/asm-ia64/sn/pcibus_provider_defs.h @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1992 - 1997, 2000-2004 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 1992 - 1997, 2000-2005 Silicon Graphics, Inc. All rights reserved. */ #ifndef _ASM_IA64_SN_PCI_PCIBUS_PROVIDER_H #define _ASM_IA64_SN_PCI_PCIBUS_PROVIDER_H @@ -45,13 +45,24 @@ struct pci_controller; */ struct sn_pcibus_provider { - dma_addr_t (*dma_map)(struct pci_dev *, unsigned long, size_t); - dma_addr_t (*dma_map_consistent)(struct pci_dev *, unsigned long, size_t); + dma_addr_t (*dma_map)(struct pci_dev *, unsigned long, size_t, int flags); + dma_addr_t (*dma_map_consistent)(struct pci_dev *, unsigned long, size_t, int flags); void (*dma_unmap)(struct pci_dev *, dma_addr_t, int); void * (*bus_fixup)(struct pcibus_bussoft *, struct pci_controller *); void (*force_interrupt)(struct sn_irq_info *); void (*target_interrupt)(struct sn_irq_info *); }; +/* + * Flags used by the map interfaces + * bits 3:0 specifies format of passed in address + * bit 4 specifies that address is to be used for MSI + */ + +#define SN_DMA_ADDRTYPE(x) ((x) & 0xf) +#define SN_DMA_ADDR_PHYS 1 /* address is an xio address. */ +#define SN_DMA_ADDR_XIO 2 /* address is phys memory */ +#define SN_DMA_MSI 0x10 /* Bus address is to be used for MSI */ + extern struct sn_pcibus_provider *sn_pci_provider[]; #endif /* _ASM_IA64_SN_PCI_PCIBUS_PROVIDER_H */ diff --git a/include/asm-ia64/sn/tiocp.h b/include/asm-ia64/sn/tiocp.h index f47c08ab483..e8ad0bb5b6c 100644 --- a/include/asm-ia64/sn/tiocp.h +++ b/include/asm-ia64/sn/tiocp.h @@ -3,13 +3,14 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2003-2004 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2003-2005 Silicon Graphics, Inc. All rights reserved. */ #ifndef _ASM_IA64_SN_PCI_TIOCP_H #define _ASM_IA64_SN_PCI_TIOCP_H #define TIOCP_HOST_INTR_ADDR 0x003FFFFFFFFFFFFFUL #define TIOCP_PCI64_CMDTYPE_MEM (0x1ull << 60) +#define TIOCP_PCI64_CMDTYPE_MSI (0x3ull << 60) /***************************************************************************** -- cgit v1.2.3 From 17d6dc8ff098cc8c57941c82f7702804302b1ea1 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 18 Apr 2006 17:19:52 -0700 Subject: [PATCH] PCI: Ignore pre-set 64-bit BARs on 32-bit platforms [pci] Ignore pre-set 64-bit BARs on 32-bit platforms Currently, Linux always rejects a device which has a pre-set 64-bit address on a 32-bit platform. On systems which do not do PCI initialization in firmware, this causes some devices which don't correctly power up with all BARs zero to fail. This patch makes the kernel automatically zero out such an address (thus treating it as if it had not been set at all, meaning it will assign an address if necessary). I have done this only for devices, not bridges. It seems potentially hazardous to do for bridges. Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- drivers/pci/probe.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index a10ed9dab2c..5c4924c27f0 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -180,25 +180,31 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) res->flags |= pci_calc_resource_flags(l); if ((l & (PCI_BASE_ADDRESS_SPACE | PCI_BASE_ADDRESS_MEM_TYPE_MASK)) == (PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64)) { - pci_read_config_dword(dev, reg+4, &l); + u32 szhi, lhi; + pci_read_config_dword(dev, reg+4, &lhi); + pci_write_config_dword(dev, reg+4, ~0); + pci_read_config_dword(dev, reg+4, &szhi); + pci_write_config_dword(dev, reg+4, lhi); + szhi = pci_size(lhi, szhi, 0xffffffff); next++; #if BITS_PER_LONG == 64 - res->start |= ((unsigned long) l) << 32; + res->start |= ((unsigned long) lhi) << 32; res->end = res->start + sz; - pci_write_config_dword(dev, reg+4, ~0); - pci_read_config_dword(dev, reg+4, &sz); - pci_write_config_dword(dev, reg+4, l); - sz = pci_size(l, sz, 0xffffffff); - if (sz) { + if (szhi) { /* This BAR needs > 4GB? Wow. */ - res->end |= (unsigned long)sz<<32; + res->end |= (unsigned long)szhi<<32; } #else - if (l) { - printk(KERN_ERR "PCI: Unable to handle 64-bit address for device %s\n", pci_name(dev)); + if (szhi) { + printk(KERN_ERR "PCI: Unable to handle 64-bit BAR for device %s\n", pci_name(dev)); res->start = 0; res->flags = 0; - continue; + } else if (l) { + /* 64-bit wide address, treat as disabled */ + pci_write_config_dword(dev, reg, l & ~(u32)PCI_BASE_ADDRESS_MEM_MASK); + pci_write_config_dword(dev, reg+4, 0); + res->start = 0; + res->end = sz; } #endif } -- cgit v1.2.3 From ea28502d5d0fc624777a8a6b4d6865d282055b05 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 9 Jun 2006 11:28:29 -0700 Subject: [PATCH] PCI: fix to pci ignore pre-set 64-bit bars on 32-bit platforms When we detect a 64-bit pre-set address in a BAR on a 32-bit platform, we disable it and treat it as if it had been unset, thus allowing the general address assignment code to assign a new address to it when the device is enabled. This can happen either if the firmware assigns 64-bit addresses; additionally, some cards have been found "in the wild" which do not come out of reset with all the BAR registers set to zero. Unfortunately, the patch that implemented this tested the low part of the address instead of the high part of the address. This patch fixes that. Signed-off-by: Bjorn Helgaas Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- drivers/pci/probe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 5c4924c27f0..27148db06ba 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -199,7 +199,7 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) printk(KERN_ERR "PCI: Unable to handle 64-bit BAR for device %s\n", pci_name(dev)); res->start = 0; res->flags = 0; - } else if (l) { + } else if (lhi) { /* 64-bit wide address, treat as disabled */ pci_write_config_dword(dev, reg, l & ~(u32)PCI_BASE_ADDRESS_MEM_MASK); pci_write_config_dword(dev, reg+4, 0); -- cgit v1.2.3 From 75acfecaa031c0e1bc412cee4fe58ba49ff3406c Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Mon, 1 May 2006 10:43:46 -0500 Subject: [PATCH] PCI: Add pci_assign_resource_fixed -- allow fixed address assignments PCI: Add pci_assign_resource_fixed -- allow fixed address assignments On some embedded systems the PCI address for hotplug devices are not only known a priori but are required to be at a given PCI address for other master in the system to be able to access. An example of such a system would be an FPGA which is setup from user space after the system has booted. The FPGA may be access by DSPs in the system and those DSPs expect the FPGA at a fixed PCI address. Added pci_assign_resource_fixed() as a way to allow assignment of the PCI devices's BARs at fixed PCI addresses. Signed-off-by: Kumar Gala Signed-off-by: Greg Kroah-Hartman --- drivers/pci/setup-res.c | 40 ++++++++++++++++++++++++++++++++++++++++ include/linux/pci.h | 1 + 2 files changed, 41 insertions(+) diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index ea9277b7f89..577f4b55c46 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c @@ -155,6 +155,46 @@ int pci_assign_resource(struct pci_dev *dev, int resno) return ret; } +#ifdef CONFIG_EMBEDDED +int pci_assign_resource_fixed(struct pci_dev *dev, int resno) +{ + struct pci_bus *bus = dev->bus; + struct resource *res = dev->resource + resno; + unsigned int type_mask; + int i, ret = -EBUSY; + + type_mask = IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_PREFETCH; + + for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { + struct resource *r = bus->resource[i]; + if (!r) + continue; + + /* type_mask must match */ + if ((res->flags ^ r->flags) & type_mask) + continue; + + ret = request_resource(r, res); + + if (ret == 0) + break; + } + + if (ret) { + printk(KERN_ERR "PCI: Failed to allocate %s resource " + "#%d:%llx@%llx for %s\n", + res->flags & IORESOURCE_IO ? "I/O" : "mem", + resno, (unsigned long long)(res->end - res->start + 1), + (unsigned long long)res->start, pci_name(dev)); + } else if (resno < PCI_BRIDGE_RESOURCES) { + pci_update_resource(dev, res, resno); + } + + return ret; +} +EXPORT_SYMBOL_GPL(pci_assign_resource_fixed); +#endif + /* Sort resources by alignment */ void __devinit pdev_sort_resources(struct pci_dev *dev, struct resource_list *head) diff --git a/include/linux/pci.h b/include/linux/pci.h index 6c4bc773f7b..b9eb9b021d6 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -496,6 +496,7 @@ int pci_set_dma_mask(struct pci_dev *dev, u64 mask); int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask); void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno); int pci_assign_resource(struct pci_dev *dev, int i); +int pci_assign_resource_fixed(struct pci_dev *dev, int i); void pci_restore_bars(struct pci_dev *dev); /* ROM control related routines */ -- cgit v1.2.3 From 9f125d30487cea72542a84b4835c037163c7f3d5 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Sat, 29 Apr 2006 10:59:08 +0200 Subject: [PATCH] PCI: Add a "enable" sysfs attribute to the pci devices to allow userspace (Xorg) to enable devices without doing foul direct access This patch adds an "enable" sysfs attribute to each PCI device. When read it shows the "enabled-ness" of the device, but you can write a "0" into it to disable a device, and a "1" to enable it. This later is needed for X and other cases where userspace wants to enable the BARs on a device (typical example: to run the video bios on a secundary head). Right now X does all this "by hand" via bitbanging, that's just evil. This allows X to no longer do that but to just let the kernel do this. Signed-off-by: Arjan van de Ven CC: Peter Jones Acked-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pci-sysfs.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 56ac2bc003c..37897a8c95e 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -43,6 +43,7 @@ pci_config_attr(subsystem_vendor, "0x%04x\n"); pci_config_attr(subsystem_device, "0x%04x\n"); pci_config_attr(class, "0x%06x\n"); pci_config_attr(irq, "%u\n"); +pci_config_attr(is_enabled, "%u\n"); static ssize_t local_cpus_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -90,6 +91,25 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, (u8)(pci_dev->class >> 16), (u8)(pci_dev->class >> 8), (u8)(pci_dev->class)); } +static ssize_t +is_enabled_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct pci_dev *pdev = to_pci_dev(dev); + + /* this can crash the machine when done on the "wrong" device */ + if (!capable(CAP_SYS_ADMIN)) + return count; + + if (*buf == '0') + pci_disable_device(pdev); + + if (*buf == '1') + pci_enable_device(pdev); + + return count; +} + struct device_attribute pci_dev_attrs[] = { __ATTR_RO(resource), @@ -101,6 +121,7 @@ struct device_attribute pci_dev_attrs[] = { __ATTR_RO(irq), __ATTR_RO(local_cpus), __ATTR_RO(modalias), + __ATTR(enable, 0600, is_enabled_show, is_enabled_store), __ATTR_NULL, }; -- cgit v1.2.3 From a1e022b3aeacf633a6c8e8f0eb04d9c9e44b4fcd Mon Sep 17 00:00:00 2001 From: Kristen Accardi Date: Fri, 28 Apr 2006 11:37:38 -0700 Subject: [PATCH] PCI: don't enable device if already enabled If a device is already enabled, don't bother reenabling it. Signed-off-by: Kristen Carlson Accardi Acked-By: Arjan van de Ven Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pci.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index fde41cc1473..aa480370ef1 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -517,7 +517,12 @@ pci_enable_device_bars(struct pci_dev *dev, int bars) int pci_enable_device(struct pci_dev *dev) { - int err = pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1); + int err; + + if (dev->is_enabled) + return 0; + + err = pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1); if (err) return err; pci_fixup_device(pci_fixup_enable, dev); -- cgit v1.2.3 From 9c273b95808c270149e9be9e172e4ef19f5d5c98 Mon Sep 17 00:00:00 2001 From: Muthu Kumar Date: Fri, 28 Apr 2006 00:42:21 -0700 Subject: [PATCH] PCI ACPI: Rename the functions to avoid multiple instances. There were two instances of pci_acpi_init(), one in drivers/pci/pci-acpi.c and another in arch/i386/pci/acpi.c. Rename the one in pci-acpi.c and make it consistent with other names in the same file. Signed-off-by: Muthukumar R Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pci-acpi.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index c2ecae5ff0c..bb7456c1dba 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -267,7 +267,7 @@ static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state) /* ACPI bus type */ -static int pci_acpi_find_device(struct device *dev, acpi_handle *handle) +static int acpi_pci_find_device(struct device *dev, acpi_handle *handle) { struct pci_dev * pci_dev; acpi_integer addr; @@ -281,7 +281,7 @@ static int pci_acpi_find_device(struct device *dev, acpi_handle *handle) return 0; } -static int pci_acpi_find_root_bridge(struct device *dev, acpi_handle *handle) +static int acpi_pci_find_root_bridge(struct device *dev, acpi_handle *handle) { int num; unsigned int seg, bus; @@ -299,21 +299,21 @@ static int pci_acpi_find_root_bridge(struct device *dev, acpi_handle *handle) return 0; } -static struct acpi_bus_type pci_acpi_bus = { +static struct acpi_bus_type acpi_pci_bus = { .bus = &pci_bus_type, - .find_device = pci_acpi_find_device, - .find_bridge = pci_acpi_find_root_bridge, + .find_device = acpi_pci_find_device, + .find_bridge = acpi_pci_find_root_bridge, }; -static int __init pci_acpi_init(void) +static int __init acpi_pci_init(void) { int ret; - ret = register_acpi_bus_type(&pci_acpi_bus); + ret = register_acpi_bus_type(&acpi_pci_bus); if (ret) return 0; platform_pci_choose_state = acpi_pci_choose_state; platform_pci_set_power_state = acpi_pci_set_power_state; return 0; } -arch_initcall(pci_acpi_init); +arch_initcall(acpi_pci_init); -- cgit v1.2.3 From 53e4d30dd666d7f83598957ee4a415eefb47c9a6 Mon Sep 17 00:00:00 2001 From: Rajesh Shah Date: Wed, 3 May 2006 15:27:47 -0700 Subject: [PATCH] PCI: i386/x86_84: disable PCI resource decode on device disable When a PCI device is disabled via pci_disable_device(), it's still left decoding its BAR resource ranges even though its driver will have likely released those regions (and may even have unloaded). pci_enable_device() already explicitly enables BAR resource decode for the device being enabled. This patch disables resource decode for the PCI device being disabled, making it symmetric with the enable call. I saw this while doing something else, not because of a problem report. Still, seems to be the correct thing to do. Signed-off-by: Rajesh Shah Signed-off-by: Greg Kroah-Hartman --- arch/i386/pci/common.c | 1 + arch/i386/pci/i386.c | 9 +++++++++ arch/i386/pci/pci.h | 1 + 3 files changed, 11 insertions(+) diff --git a/arch/i386/pci/common.c b/arch/i386/pci/common.c index dbece776c5b..c624b61e110 100644 --- a/arch/i386/pci/common.c +++ b/arch/i386/pci/common.c @@ -288,6 +288,7 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) void pcibios_disable_device (struct pci_dev *dev) { + pcibios_disable_resources(dev); if (pcibios_disable_irq) pcibios_disable_irq(dev); } diff --git a/arch/i386/pci/i386.c b/arch/i386/pci/i386.c index ed2c8c899bd..7852827a599 100644 --- a/arch/i386/pci/i386.c +++ b/arch/i386/pci/i386.c @@ -242,6 +242,15 @@ int pcibios_enable_resources(struct pci_dev *dev, int mask) return 0; } +void pcibios_disable_resources(struct pci_dev *dev) +{ + u16 cmd; + + pci_read_config_word(dev, PCI_COMMAND, &cmd); + cmd &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY); + pci_write_config_word(dev, PCI_COMMAND, cmd); +} + /* * If we set up a device for bus mastering, we need to check the latency * timer as certain crappy BIOSes forget to set it properly. diff --git a/arch/i386/pci/pci.h b/arch/i386/pci/pci.h index 12035e29108..12bf3d8dda2 100644 --- a/arch/i386/pci/pci.h +++ b/arch/i386/pci/pci.h @@ -35,6 +35,7 @@ extern unsigned int pcibios_max_latency; void pcibios_resource_survey(void); int pcibios_enable_resources(struct pci_dev *, int); +void pcibios_disable_resources(struct pci_dev *); /* pci-pc.c */ -- cgit v1.2.3 From bd8481e1646d7649fa101ee57a5139b9da3c2436 Mon Sep 17 00:00:00 2001 From: Doug Thompson Date: Mon, 8 May 2006 17:06:09 -0700 Subject: [PATCH] PCI Bus Parity Status-broken hardware attribute, EDAC foundation Currently, the EDAC (error detection and correction) modules that are in the kernel contain some features that need to be moved. After some good feedback on the PCI Parity detection code and interface (http://www.ussg.iu.edu/hypermail/linux/kernel/0603.1/0897.html) this patch ADDs an new attribute to the pci_dev structure: Namely the 'broken_parity_status' bit. When set this indicates that the respective hardware generates false positives of Parity errors. The EDAC "blacklist" solution was inferior and will be removed in a future patch. Also in this patch is a PCI quirk.c entry for an Infiniband PCI-X card which generates false positive parity errors. I am requesting comments on this AND on the possibility of a exposing this 'broken_parity_status' bit to userland via the PCI device sysfs directory for devices. This access would allow for enabling of this feature on new devices and for old devices that have their drivers updated. (SLES 9 SP3 did this on an ATI motherboard video device). There is a need to update such a PCI attribute between kernel releases. This patch just adds a storage place for the attribute and a quirk entry for a known bad PCI device. PCI Parity reaper/harvestor operations are in EDAC itself and will be refactored to use this PCI attribute instead of its own mechanisms (which are currently disabled) in the future. Signed-off-by: Doug Thompson Signed-off-by: Greg Kroah-Hartman --- drivers/pci/quirks.c | 11 +++++++++++ include/linux/pci.h | 1 + include/linux/pci_ids.h | 1 + 3 files changed, 13 insertions(+) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index d378478612f..ea48e969a12 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -24,6 +24,17 @@ #include #include "pci.h" +/* The Mellanox Tavor device gives false positive parity errors + * Mark this device with a broken_parity_status, to allow + * PCI scanning code to "skip" this now blacklisted device. + */ +static void __devinit quirk_mellanox_tavor(struct pci_dev *dev) +{ + dev->broken_parity_status = 1; /* This device gives false positives */ +} +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MELLANOX,PCI_DEVICE_ID_MELLANOX_TAVOR,quirk_mellanox_tavor); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MELLANOX,PCI_DEVICE_ID_MELLANOX_TAVOR_BRIDGE,quirk_mellanox_tavor); + /* Deal with broken BIOS'es that neglect to enable passive release, which can cause problems in combination with the 82441FX/PPro MTRRs */ static void __devinit quirk_passive_release(struct pci_dev *dev) diff --git a/include/linux/pci.h b/include/linux/pci.h index b9eb9b021d6..91c37750cd3 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -162,6 +162,7 @@ struct pci_dev { unsigned int is_busmaster:1; /* device is busmaster */ unsigned int no_msi:1; /* device may not use msi */ unsigned int block_ucfg_access:1; /* userspace config space access is blocked */ + unsigned int broken_parity_status:1; /* Device generates false positive parity */ u32 saved_config_space[16]; /* config space saved at suspend time */ struct hlist_head saved_cap_space; diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index bcfe9d4f56a..3d197cdcfa3 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1946,6 +1946,7 @@ #define PCI_VENDOR_ID_MELLANOX 0x15b3 #define PCI_DEVICE_ID_MELLANOX_TAVOR 0x5a44 +#define PCI_DEVICE_ID_MELLANOX_TAVOR_BRIDGE 0x5a46 #define PCI_DEVICE_ID_MELLANOX_ARBEL_COMPAT 0x6278 #define PCI_DEVICE_ID_MELLANOX_ARBEL 0x6282 #define PCI_DEVICE_ID_MELLANOX_SINAI_OLD 0x5e8c -- cgit v1.2.3 From 74d0a988d3aa359b6b8a8536c8cb92cce02ca5d5 Mon Sep 17 00:00:00 2001 From: Brent Casavant Date: Wed, 10 May 2006 01:49:14 -0700 Subject: [PATCH] PCI: Move various PCI IDs to header file Move various QLogic, Vitesse, and Intel storage controller PCI IDs to the main header file. Signed-off-by: Brent Casavant Acked-by: Jes Sorensen Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/qla1280.c | 24 ------------------------ drivers/scsi/sata_vsc.c | 11 ++++++----- include/linux/pci_ids.h | 9 +++++++++ 3 files changed, 15 insertions(+), 29 deletions(-) diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c index 77bb2351500..680f6063954 100644 --- a/drivers/scsi/qla1280.c +++ b/drivers/scsi/qla1280.c @@ -397,30 +397,6 @@ #include "ql1280_fw.h" #include "ql1040_fw.h" - -/* - * Missing PCI ID's - */ -#ifndef PCI_DEVICE_ID_QLOGIC_ISP1080 -#define PCI_DEVICE_ID_QLOGIC_ISP1080 0x1080 -#endif -#ifndef PCI_DEVICE_ID_QLOGIC_ISP1240 -#define PCI_DEVICE_ID_QLOGIC_ISP1240 0x1240 -#endif -#ifndef PCI_DEVICE_ID_QLOGIC_ISP1280 -#define PCI_DEVICE_ID_QLOGIC_ISP1280 0x1280 -#endif -#ifndef PCI_DEVICE_ID_QLOGIC_ISP10160 -#define PCI_DEVICE_ID_QLOGIC_ISP10160 0x1016 -#endif -#ifndef PCI_DEVICE_ID_QLOGIC_ISP12160 -#define PCI_DEVICE_ID_QLOGIC_ISP12160 0x1216 -#endif - -#ifndef PCI_VENDOR_ID_AMI -#define PCI_VENDOR_ID_AMI 0x101e -#endif - #ifndef BITS_PER_LONG #error "BITS_PER_LONG not defined!" #endif diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c index 8a29ce340b4..27d658704cf 100644 --- a/drivers/scsi/sata_vsc.c +++ b/drivers/scsi/sata_vsc.c @@ -433,13 +433,14 @@ err_out: /* - * 0x1725/0x7174 is the Vitesse VSC-7174 - * 0x8086/0x3200 is the Intel 31244, which is supposed to be identical - * compatibility is untested as of yet + * Intel 31244 is supposed to be identical. + * Compatibility is untested as of yet. */ static const struct pci_device_id vsc_sata_pci_tbl[] = { - { 0x1725, 0x7174, PCI_ANY_ID, PCI_ANY_ID, 0x10600, 0xFFFFFF, 0 }, - { 0x8086, 0x3200, PCI_ANY_ID, PCI_ANY_ID, 0x10600, 0xFFFFFF, 0 }, + { PCI_VENDOR_ID_VITESSE, PCI_DEVICE_ID_VITESSE_VSC7174, + PCI_ANY_ID, PCI_ANY_ID, 0x10600, 0xFFFFFF, 0 }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_GD31244, + PCI_ANY_ID, PCI_ANY_ID, 0x10600, 0xFFFFFF, 0 }, { } }; diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 3d197cdcfa3..e526e7b5ea4 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -848,7 +848,12 @@ #define PCI_VENDOR_ID_QLOGIC 0x1077 +#define PCI_DEVICE_ID_QLOGIC_ISP10160 0x1016 #define PCI_DEVICE_ID_QLOGIC_ISP1020 0x1020 +#define PCI_DEVICE_ID_QLOGIC_ISP1080 0x1080 +#define PCI_DEVICE_ID_QLOGIC_ISP12160 0x1216 +#define PCI_DEVICE_ID_QLOGIC_ISP1240 0x1240 +#define PCI_DEVICE_ID_QLOGIC_ISP1280 0x1280 #define PCI_DEVICE_ID_QLOGIC_ISP2100 0x2100 #define PCI_DEVICE_ID_QLOGIC_ISP2200 0x2200 #define PCI_DEVICE_ID_QLOGIC_ISP2300 0x2300 @@ -1970,6 +1975,9 @@ #define PCI_VENDOR_ID_NETCELL 0x169c #define PCI_DEVICE_ID_REVOLUTION 0x0044 +#define PCI_VENDOR_ID_VITESSE 0x1725 +#define PCI_DEVICE_ID_VITESSE_VSC7174 0x7174 + #define PCI_VENDOR_ID_LINKSYS 0x1737 #define PCI_DEVICE_ID_LINKSYS_EG1064 0x1064 @@ -2149,6 +2157,7 @@ #define PCI_DEVICE_ID_INTEL_ICH8_4 0x2815 #define PCI_DEVICE_ID_INTEL_ICH8_5 0x283e #define PCI_DEVICE_ID_INTEL_ICH8_6 0x2850 +#define PCI_DEVICE_ID_INTEL_GD31244 0x3200 #define PCI_DEVICE_ID_INTEL_82855PM_HB 0x3340 #define PCI_DEVICE_ID_INTEL_82830_HB 0x3575 #define PCI_DEVICE_ID_INTEL_82830_CGC 0x3577 -- cgit v1.2.3 From 1edab4a164b229807853682f7ff7858c11dd3481 Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Tue, 23 May 2006 03:05:27 -0400 Subject: [PATCH] PCI: AMD 8131 MSI quirk called too late, bus_flags not inherited ? The PCI_BUS_FLAGS_NO_MSI bus flags does not appear do be inherited correctly from the amd8131 MSI quirk to its parent busses. It makes devices behind a bridge behind amd8131 try to enable MSI while the amd8131 does not support it. We fix this by looking at flags of all parent busses in pci_enable_msi() and pci_enable_msix(). By the way, also add the missing dev->no_msi check in pci_enable_msix() Signed-off-by: Brice Goglin Signed-off-by: Greg Kroah-Hartman --- drivers/pci/msi.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index f8105783da2..4aea563bda6 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -916,6 +916,7 @@ static int msix_capability_init(struct pci_dev *dev, **/ int pci_enable_msi(struct pci_dev* dev) { + struct pci_bus *bus; int pos, temp, status = -EINVAL; u16 control; @@ -925,8 +926,9 @@ int pci_enable_msi(struct pci_dev* dev) if (dev->no_msi) return status; - if (dev->bus->bus_flags & PCI_BUS_FLAGS_NO_MSI) - return -EINVAL; + for (bus = dev->bus; bus; bus = bus->parent) + if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI) + return -EINVAL; temp = dev->irq; @@ -1162,6 +1164,7 @@ static int reroute_msix_table(int head, struct msix_entry *entries, int *nvec) **/ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) { + struct pci_bus *bus; int status, pos, nr_entries, free_vectors; int i, j, temp; u16 control; @@ -1170,6 +1173,13 @@ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) if (!pci_msi_enable || !dev || !entries) return -EINVAL; + if (dev->no_msi) + return -EINVAL; + + for (bus = dev->bus; bus; bus = bus->parent) + if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI) + return -EINVAL; + status = msi_init(); if (status < 0) return status; -- cgit v1.2.3 From 020d502488bebdbc1b2c2828d996f04e563f082a Mon Sep 17 00:00:00 2001 From: Rajesh Shah Date: Tue, 23 May 2006 10:14:36 -0700 Subject: [PATCH] PCI: Allow MSI to work on kexec kernel We recently ran into a problem where the e1000 device failed to work properly on the kexec kernel. MSI was enabled for the device in the main kernel when it crashed. The e1000 driver tried to enable MSI on the kexec kernel, but the code bailed early when it found that MSI was already enabled in the hardware, even though the software state was not properly set up in the kexec'd kernel. This patch fixes the problem by moving the early return to after making sure that the software state is properly initialized. Signed-off-by: Rajesh Shah Signed-off-by: Greg Kroah-Hartman --- drivers/pci/msi.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 4aea563bda6..9c69b6966e7 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -940,14 +940,13 @@ int pci_enable_msi(struct pci_dev* dev) if (!pos) return -EINVAL; - pci_read_config_word(dev, msi_control_reg(pos), &control); - if (control & PCI_MSI_FLAGS_ENABLE) - return 0; /* Already in MSI mode */ - if (!msi_lookup_vector(dev, PCI_CAP_ID_MSI)) { /* Lookup Sucess */ unsigned long flags; + pci_read_config_word(dev, msi_control_reg(pos), &control); + if (control & PCI_MSI_FLAGS_ENABLE) + return 0; /* Already in MSI mode */ spin_lock_irqsave(&msi_lock, flags); if (!vector_irq[dev->irq]) { msi_desc[dev->irq]->msi_attrib.state = 0; -- cgit v1.2.3 From 99dc804d9bcc2c53f4c20c291bf4e185312a1a0c Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Fri, 26 May 2006 10:58:27 +0800 Subject: [PATCH] PCI: disable msi mode in pci_disable_device Brice said the pci_save_msi_state breaks his driver in his special usage (not in suspend/resume), as pci_save_msi_state will disable msi mode. In his usage, pci_save_state will be called at runtime, and later (after the device operates for some time and has an error) pci_restore_state will be called. In another hand, suspend/resume needs disable msi mode, as device should stop working completely. This patch try to workaround this issue. Drivers are expected call pci_disable_device in suspend time after pci_save_state. Signed-off-by: Shaohua Li Signed-off-by: Greg Kroah-Hartman --- drivers/pci/msi.c | 6 ++++-- drivers/pci/pci.c | 9 ++++++++- include/linux/pci.h | 2 ++ 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 9c69b6966e7..3ec558dc652 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -453,9 +453,11 @@ static void enable_msi_mode(struct pci_dev *dev, int pos, int type) /* Set enabled bits to single MSI & enable MSI_enable bit */ msi_enable(control, 1); pci_write_config_word(dev, msi_control_reg(pos), control); + dev->msi_enabled = 1; } else { msix_enable(control); pci_write_config_word(dev, msi_control_reg(pos), control); + dev->msix_enabled = 1; } if (pci_find_capability(dev, PCI_CAP_ID_EXP)) { /* PCI Express Endpoint device detected */ @@ -472,9 +474,11 @@ void disable_msi_mode(struct pci_dev *dev, int pos, int type) /* Set enabled bits to single MSI & enable MSI_enable bit */ msi_disable(control); pci_write_config_word(dev, msi_control_reg(pos), control); + dev->msi_enabled = 0; } else { msix_disable(control); pci_write_config_word(dev, msi_control_reg(pos), control); + dev->msix_enabled = 0; } if (pci_find_capability(dev, PCI_CAP_ID_EXP)) { /* PCI Express Endpoint device detected */ @@ -549,7 +553,6 @@ int pci_save_msi_state(struct pci_dev *dev) pci_read_config_dword(dev, pos + PCI_MSI_DATA_32, &cap[i++]); if (control & PCI_MSI_FLAGS_MASKBIT) pci_read_config_dword(dev, pos + PCI_MSI_MASK_BIT, &cap[i++]); - disable_msi_mode(dev, pos, PCI_CAP_ID_MSI); save_state->cap_nr = PCI_CAP_ID_MSI; pci_add_saved_cap(dev, save_state); return 0; @@ -639,7 +642,6 @@ int pci_save_msix_state(struct pci_dev *dev) } dev->irq = temp; - disable_msi_mode(dev, pos, PCI_CAP_ID_MSIX); save_state->cap_nr = PCI_CAP_ID_MSIX; pci_add_saved_cap(dev, save_state); return 0; diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index aa480370ef1..d408a3c3042 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -551,7 +551,14 @@ void pci_disable_device(struct pci_dev *dev) { u16 pci_command; - + + if (dev->msi_enabled) + disable_msi_mode(dev, pci_find_capability(dev, PCI_CAP_ID_MSI), + PCI_CAP_ID_MSI); + if (dev->msix_enabled) + disable_msi_mode(dev, pci_find_capability(dev, PCI_CAP_ID_MSI), + PCI_CAP_ID_MSIX); + pci_read_config_word(dev, PCI_COMMAND, &pci_command); if (pci_command & PCI_COMMAND_MASTER) { pci_command &= ~PCI_COMMAND_MASTER; diff --git a/include/linux/pci.h b/include/linux/pci.h index 91c37750cd3..62a8c22f5f6 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -163,6 +163,8 @@ struct pci_dev { unsigned int no_msi:1; /* device may not use msi */ unsigned int block_ucfg_access:1; /* userspace config space access is blocked */ unsigned int broken_parity_status:1; /* Device generates false positive parity */ + unsigned int msi_enabled:1; + unsigned int msix_enabled:1; u32 saved_config_space[16]; /* config space saved at suspend time */ struct hlist_head saved_cap_space; -- cgit v1.2.3 From b209a6ee49099b7500abf024f7b6b9648b5a3eac Mon Sep 17 00:00:00 2001 From: "bibo,mao" Date: Wed, 31 May 2006 18:17:33 +0800 Subject: [PATCH] PCI: cleanup unused variable about msi driver In IA64 platform, msi driver does not use irq_vector variable, and in x86 platform LAST_DEVICE_VECTOR should one before FIRST_SYSTEM_VECTOR, this patch modify this. Signed-off-by: bibo, mao Signed-off-by: Greg Kroah-Hartman --- drivers/pci/msi.c | 5 ----- include/asm-i386/msi.h | 2 +- include/asm-x86_64/msi.h | 2 +- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 3ec558dc652..a81c5b99daf 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -35,7 +35,6 @@ static int nr_msix_devices; #ifndef CONFIG_X86_IO_APIC int vector_irq[NR_VECTORS] = { [0 ... NR_VECTORS - 1] = -1}; -u8 irq_vector[NR_IRQ_VECTORS]; #endif static struct msi_ops *msi_ops; @@ -383,10 +382,6 @@ static int msi_init(void) return status; } -#ifndef CONFIG_X86_IO_APIC - irq_vector[0] = FIRST_DEVICE_VECTOR; -#endif - if (last_alloc_vector < 0) { pci_msi_enable = 0; printk(KERN_WARNING "PCI: No interrupt vectors available for MSI\n"); diff --git a/include/asm-i386/msi.h b/include/asm-i386/msi.h index ed1014235e9..b11c4b7dfae 100644 --- a/include/asm-i386/msi.h +++ b/include/asm-i386/msi.h @@ -9,7 +9,7 @@ #include #include -#define LAST_DEVICE_VECTOR 232 +#define LAST_DEVICE_VECTOR (FIRST_SYSTEM_VECTOR - 1) #define MSI_TARGET_CPU_SHIFT 12 extern struct msi_ops msi_apic_ops; diff --git a/include/asm-x86_64/msi.h b/include/asm-x86_64/msi.h index 8d6d6bf8fad..3ad2346624b 100644 --- a/include/asm-x86_64/msi.h +++ b/include/asm-x86_64/msi.h @@ -10,7 +10,7 @@ #include #include -#define LAST_DEVICE_VECTOR 232 +#define LAST_DEVICE_VECTOR (FIRST_SYSTEM_VECTOR - 1) #define MSI_TARGET_CPU_SHIFT 12 extern struct msi_ops msi_apic_ops; -- cgit v1.2.3 From c0da3ba0a29d70c95ed39366a1c9b849f3439fbe Mon Sep 17 00:00:00 2001 From: Kimball Murray Date: Wed, 31 May 2006 14:20:04 -0400 Subject: [PATCH] PCI: don't move ioapics below PCI bridge A recent Stratus x86_64 platform uses a system ioapic that is a PCI device located below a PCI bridge. Other platforms like this may exist. This patch fixes a problem wherein the kernel's PCI setup code moves the ioapic to an address other than that assigned by the BIOS. It simply adds another exclusion (which already includes classless devices and host bridges) to the function pbus_assign_resources_sorted so that it will not move the ioapic. If the ioapic is moved, the fixmap mapping to it is broken, so the OS should leave it alone. From: Kimball Murray Signed-off-by: Greg Kroah-Hartman --- drivers/pci/setup-bus.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 28ce3a7ee43..35086e80faa 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -55,9 +55,10 @@ pbus_assign_resources_sorted(struct pci_bus *bus) list_for_each_entry(dev, &bus->devices, bus_list) { u16 class = dev->class >> 8; - /* Don't touch classless devices and host bridges. */ + /* Don't touch classless devices or host bridges or ioapics. */ if (class == PCI_CLASS_NOT_DEFINED || - class == PCI_CLASS_BRIDGE_HOST) + class == PCI_CLASS_BRIDGE_HOST || + class == PCI_CLASS_SYSTEM_PIC) continue; pdev_sort_resources(dev, &head); -- cgit v1.2.3 From f7e6600d762bf7c04b48c8d9bd0ab26d04a8d11f Mon Sep 17 00:00:00 2001 From: Grant Grundler Date: Wed, 31 May 2006 23:35:47 -0700 Subject: [PATCH] PCI: remove unneeded msi code The code is really not needed. Roland Dreier/Greg KH removed the release_mem_region() calls that were the only consumers of phys_addr: http://www.ussg.iu.edu/hypermail/linux/kernel/0503.0/1540.html patch below deletes the "dead" code. Signed-off-by: Grant Grundler Signed-off-by: Greg Kroah-Hartman --- drivers/pci/msi.c | 45 +-------------------------------------------- 1 file changed, 1 insertion(+), 44 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index a81c5b99daf..7f8429284fa 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -1060,33 +1060,8 @@ static int msi_free_vector(struct pci_dev* dev, int vector, int reassign) entry_nr * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET); - if (head == vector) { - /* - * Detect last MSI-X vector to be released. - * Release the MSI-X memory-mapped table. - */ -#if 0 - int pos, nr_entries; - unsigned long phys_addr; - u32 table_offset; - u16 control; - u8 bir; - - pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); - pci_read_config_word(dev, msi_control_reg(pos), - &control); - nr_entries = multi_msix_capable(control); - pci_read_config_dword(dev, msix_table_offset_reg(pos), - &table_offset); - bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK); - table_offset &= ~PCI_MSIX_FLAGS_BIRMASK; - phys_addr = pci_resource_start(dev, bir) + table_offset; -/* - * FIXME! and what did you want to do with phys_addr? - */ -#endif + if (head == vector) iounmap(base); - } } return 0; @@ -1360,24 +1335,6 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev) } msi_free_vector(dev, vector, 0); if (warning) { - /* Force to release the MSI-X memory-mapped table */ -#if 0 - unsigned long phys_addr; - u32 table_offset; - u16 control; - u8 bir; - - pci_read_config_word(dev, msi_control_reg(pos), - &control); - pci_read_config_dword(dev, msix_table_offset_reg(pos), - &table_offset); - bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK); - table_offset &= ~PCI_MSIX_FLAGS_BIRMASK; - phys_addr = pci_resource_start(dev, bir) + table_offset; -/* - * FIXME! and what did you want to do with phys_addr? - */ -#endif iounmap(base); printk(KERN_WARNING "PCI: %s: msi_remove_pci_irq_vectors() " "called without free_irq() on all MSI-X vectors\n", -- cgit v1.2.3 From 733a7fe12248072e1bca729c88a26298666f1956 Mon Sep 17 00:00:00 2001 From: Grant Grundler Date: Thu, 1 Jun 2006 11:15:59 -0600 Subject: [PATCH] PCI: clean up pci documentation to be more specific On Thu, Jun 01, 2006 at 02:46:11AM -0700, Rajesh Shah wrote: > This patch assumes that pci_request_region() will always be called > after pci_enable_device() and pci_release_region() will always > be called before pci_disable_device(). We cannot make this > assumption,since it's perfectly legal to disable a device > first and then release it's regions. So, I think that patch > needs to change. Patch below clarifies comments in Documentation/pci.txt. Signed-off-by: Grant Grundler Signed-off-by: Greg Kroah-Hartman --- Documentation/pci.txt | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/Documentation/pci.txt b/Documentation/pci.txt index 66bbbf1d1ef..3242e5c1ee9 100644 --- a/Documentation/pci.txt +++ b/Documentation/pci.txt @@ -213,9 +213,17 @@ have been remapped by the kernel. See Documentation/IO-mapping.txt for how to access device memory. - You still need to call request_region() for I/O regions and -request_mem_region() for memory regions to make sure nobody else is using the -same device. + The device driver needs to call pci_request_region() to make sure +no other device is already using the same resource. The driver is expected +to determine MMIO and IO Port resource availability _before_ calling +pci_enable_device(). Conversely, drivers should call pci_release_region() +_after_ calling pci_disable_device(). The idea is to prevent two devices +colliding on the same address range. + +Generic flavors of pci_request_region() are request_mem_region() +(for MMIO ranges) and request_region() (for IO Port ranges). +Use these for address resources that are not described by "normal" PCI +interfaces (e.g. BAR). All interrupt handlers should be registered with SA_SHIRQ and use the devid to map IRQs to devices (remember that all PCI interrupts are shared). -- cgit v1.2.3 From d71374dafbba7ec3f67371d3b7e9f6310a588808 Mon Sep 17 00:00:00 2001 From: Zhang Yanmin Date: Fri, 2 Jun 2006 12:35:43 +0800 Subject: [PATCH] PCI: fix race with pci_walk_bus and pci_destroy_dev pci_walk_bus has a race with pci_destroy_dev. When cb is called in pci_walk_bus, pci_destroy_dev might unlink the dev pointed by next. Later on in the next loop, pointer next becomes NULL and cause kernel panic. Below patch against 2.6.17-rc4 fixes it by changing pci_bus_lock (spin_lock) to pci_bus_sem (rw_semaphore). Signed-off-by: Zhang Yanmin Signed-off-by: Greg Kroah-Hartman --- drivers/pci/bus.c | 21 +++++++++------------ drivers/pci/pci.h | 2 +- drivers/pci/probe.c | 17 +++++++++-------- drivers/pci/remove.c | 12 ++++++------ drivers/pci/search.c | 32 ++++++++++++++++---------------- 5 files changed, 41 insertions(+), 43 deletions(-) diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index eed67d9e73b..72309268202 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -81,9 +81,9 @@ void __devinit pci_bus_add_device(struct pci_dev *dev) { device_add(&dev->dev); - spin_lock(&pci_bus_lock); + down_write(&pci_bus_sem); list_add_tail(&dev->global_list, &pci_devices); - spin_unlock(&pci_bus_lock); + up_write(&pci_bus_sem); pci_proc_attach_device(dev); pci_create_sysfs_dev_files(dev); @@ -125,10 +125,10 @@ void __devinit pci_bus_add_devices(struct pci_bus *bus) */ if (dev->subordinate) { if (list_empty(&dev->subordinate->node)) { - spin_lock(&pci_bus_lock); + down_write(&pci_bus_sem); list_add_tail(&dev->subordinate->node, &dev->bus->children); - spin_unlock(&pci_bus_lock); + up_write(&pci_bus_sem); } pci_bus_add_devices(dev->subordinate); @@ -168,7 +168,7 @@ void pci_walk_bus(struct pci_bus *top, void (*cb)(struct pci_dev *, void *), struct list_head *next; bus = top; - spin_lock(&pci_bus_lock); + down_read(&pci_bus_sem); next = top->devices.next; for (;;) { if (next == &bus->devices) { @@ -180,22 +180,19 @@ void pci_walk_bus(struct pci_bus *top, void (*cb)(struct pci_dev *, void *), continue; } dev = list_entry(next, struct pci_dev, bus_list); - pci_dev_get(dev); if (dev->subordinate) { /* this is a pci-pci bridge, do its devices next */ next = dev->subordinate->devices.next; bus = dev->subordinate; } else next = dev->bus_list.next; - spin_unlock(&pci_bus_lock); - /* Run device routines with the bus unlocked */ + /* Run device routines with the device locked */ + down(&dev->dev.sem); cb(dev, userdata); - - spin_lock(&pci_bus_lock); - pci_dev_put(dev); + up(&dev->dev.sem); } - spin_unlock(&pci_bus_lock); + up_read(&pci_bus_sem); } EXPORT_SYMBOL_GPL(pci_walk_bus); diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 30630cbe2fe..29bdeca031a 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -40,7 +40,7 @@ extern int pci_bus_find_capability (struct pci_bus *bus, unsigned int devfn, int extern void pci_remove_legacy_files(struct pci_bus *bus); /* Lock for read/write access to pci device and bus lists */ -extern spinlock_t pci_bus_lock; +extern struct rw_semaphore pci_bus_sem; #ifdef CONFIG_X86_IO_APIC extern int pci_msi_quirk; diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 27148db06ba..f89dbc3738b 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -383,9 +383,9 @@ struct pci_bus * __devinit pci_add_new_bus(struct pci_bus *parent, struct pci_de child = pci_alloc_child_bus(parent, dev, busnr); if (child) { - spin_lock(&pci_bus_lock); + down_write(&pci_bus_sem); list_add_tail(&child->node, &parent->children); - spin_unlock(&pci_bus_lock); + up_write(&pci_bus_sem); } return child; } @@ -844,9 +844,9 @@ void __devinit pci_device_add(struct pci_dev *dev, struct pci_bus *bus) * and the bus list for fixup functions, etc. */ INIT_LIST_HEAD(&dev->global_list); - spin_lock(&pci_bus_lock); + down_write(&pci_bus_sem); list_add_tail(&dev->bus_list, &bus->devices); - spin_unlock(&pci_bus_lock); + up_write(&pci_bus_sem); } struct pci_dev * __devinit @@ -981,9 +981,10 @@ struct pci_bus * __devinit pci_create_bus(struct device *parent, pr_debug("PCI: Bus %04x:%02x already known\n", pci_domain_nr(b), bus); goto err_out; } - spin_lock(&pci_bus_lock); + + down_write(&pci_bus_sem); list_add_tail(&b->node, &pci_root_buses); - spin_unlock(&pci_bus_lock); + up_write(&pci_bus_sem); memset(dev, 0, sizeof(*dev)); dev->parent = parent; @@ -1023,9 +1024,9 @@ class_dev_create_file_err: class_dev_reg_err: device_unregister(dev); dev_reg_err: - spin_lock(&pci_bus_lock); + down_write(&pci_bus_sem); list_del(&b->node); - spin_unlock(&pci_bus_lock); + up_write(&pci_bus_sem); err_out: kfree(dev); kfree(b); diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c index 1a6bf9de166..99ffbd478b2 100644 --- a/drivers/pci/remove.c +++ b/drivers/pci/remove.c @@ -22,18 +22,18 @@ static void pci_destroy_dev(struct pci_dev *dev) pci_proc_detach_device(dev); pci_remove_sysfs_dev_files(dev); device_unregister(&dev->dev); - spin_lock(&pci_bus_lock); + down_write(&pci_bus_sem); list_del(&dev->global_list); dev->global_list.next = dev->global_list.prev = NULL; - spin_unlock(&pci_bus_lock); + up_write(&pci_bus_sem); } /* Remove the device from the device lists, and prevent any further * list accesses from this device */ - spin_lock(&pci_bus_lock); + down_write(&pci_bus_sem); list_del(&dev->bus_list); dev->bus_list.next = dev->bus_list.prev = NULL; - spin_unlock(&pci_bus_lock); + up_write(&pci_bus_sem); pci_free_resources(dev); pci_dev_put(dev); @@ -62,9 +62,9 @@ void pci_remove_bus(struct pci_bus *pci_bus) { pci_proc_detach_bus(pci_bus); - spin_lock(&pci_bus_lock); + down_write(&pci_bus_sem); list_del(&pci_bus->node); - spin_unlock(&pci_bus_lock); + up_write(&pci_bus_sem); pci_remove_legacy_files(pci_bus); class_device_remove_file(&pci_bus->class_dev, &class_device_attr_cpuaffinity); diff --git a/drivers/pci/search.c b/drivers/pci/search.c index ce7dd6e7be6..622b3f8ba82 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c @@ -13,7 +13,7 @@ #include #include "pci.h" -DEFINE_SPINLOCK(pci_bus_lock); +DECLARE_RWSEM(pci_bus_sem); static struct pci_bus * __devinit pci_do_find_bus(struct pci_bus* bus, unsigned char busnr) @@ -72,11 +72,11 @@ pci_find_next_bus(const struct pci_bus *from) struct pci_bus *b = NULL; WARN_ON(in_interrupt()); - spin_lock(&pci_bus_lock); + down_read(&pci_bus_sem); n = from ? from->node.next : pci_root_buses.next; if (n != &pci_root_buses) b = pci_bus_b(n); - spin_unlock(&pci_bus_lock); + up_read(&pci_bus_sem); return b; } @@ -124,7 +124,7 @@ struct pci_dev * pci_get_slot(struct pci_bus *bus, unsigned int devfn) struct pci_dev *dev; WARN_ON(in_interrupt()); - spin_lock(&pci_bus_lock); + down_read(&pci_bus_sem); list_for_each(tmp, &bus->devices) { dev = pci_dev_b(tmp); @@ -135,7 +135,7 @@ struct pci_dev * pci_get_slot(struct pci_bus *bus, unsigned int devfn) dev = NULL; out: pci_dev_get(dev); - spin_unlock(&pci_bus_lock); + up_read(&pci_bus_sem); return dev; } @@ -167,7 +167,7 @@ static struct pci_dev * pci_find_subsys(unsigned int vendor, struct pci_dev *dev; WARN_ON(in_interrupt()); - spin_lock(&pci_bus_lock); + down_read(&pci_bus_sem); n = from ? from->global_list.next : pci_devices.next; while (n && (n != &pci_devices)) { @@ -181,7 +181,7 @@ static struct pci_dev * pci_find_subsys(unsigned int vendor, } dev = NULL; exit: - spin_unlock(&pci_bus_lock); + up_read(&pci_bus_sem); return dev; } @@ -232,7 +232,7 @@ pci_get_subsys(unsigned int vendor, unsigned int device, struct pci_dev *dev; WARN_ON(in_interrupt()); - spin_lock(&pci_bus_lock); + down_read(&pci_bus_sem); n = from ? from->global_list.next : pci_devices.next; while (n && (n != &pci_devices)) { @@ -247,7 +247,7 @@ pci_get_subsys(unsigned int vendor, unsigned int device, dev = NULL; exit: dev = pci_dev_get(dev); - spin_unlock(&pci_bus_lock); + up_read(&pci_bus_sem); pci_dev_put(from); return dev; } @@ -292,7 +292,7 @@ pci_find_device_reverse(unsigned int vendor, unsigned int device, const struct p struct pci_dev *dev; WARN_ON(in_interrupt()); - spin_lock(&pci_bus_lock); + down_read(&pci_bus_sem); n = from ? from->global_list.prev : pci_devices.prev; while (n && (n != &pci_devices)) { @@ -304,7 +304,7 @@ pci_find_device_reverse(unsigned int vendor, unsigned int device, const struct p } dev = NULL; exit: - spin_unlock(&pci_bus_lock); + up_read(&pci_bus_sem); return dev; } @@ -328,7 +328,7 @@ struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from) struct pci_dev *dev; WARN_ON(in_interrupt()); - spin_lock(&pci_bus_lock); + down_read(&pci_bus_sem); n = from ? from->global_list.next : pci_devices.next; while (n && (n != &pci_devices)) { @@ -340,7 +340,7 @@ struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from) dev = NULL; exit: dev = pci_dev_get(dev); - spin_unlock(&pci_bus_lock); + up_read(&pci_bus_sem); pci_dev_put(from); return dev; } @@ -362,7 +362,7 @@ int pci_dev_present(const struct pci_device_id *ids) int found = 0; WARN_ON(in_interrupt()); - spin_lock(&pci_bus_lock); + down_read(&pci_bus_sem); while (ids->vendor || ids->subvendor || ids->class_mask) { list_for_each_entry(dev, &pci_devices, global_list) { if (pci_match_one_device(ids, dev)) { @@ -372,8 +372,8 @@ int pci_dev_present(const struct pci_device_id *ids) } ids++; } -exit: - spin_unlock(&pci_bus_lock); +exit: + up_read(&pci_bus_sem); return found; } EXPORT_SYMBOL(pci_dev_present); -- cgit v1.2.3 From bd91fde952b0aa80c820857241ff1923537d2bde Mon Sep 17 00:00:00 2001 From: Chris Wedgwood Date: Mon, 5 Jun 2006 00:13:21 -0700 Subject: [PATCH] PCI: MSI-K8T-Neo2-Fir: run only where needed Be more selective when running the MSI-K8T-Neo2Fir soundcard PCI quirk so as not to run this on hardware where it's probably not needed. Signed-off-by: Chris Wedgwood Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/pci/quirks.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index ea48e969a12..aea4d49bcce 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -889,27 +889,30 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82375, quirk_e * when a PCI-Soundcard is added. The BIOS only gives Options * "Disabled" and "AUTO". This Quirk Sets the corresponding * Register-Value to enable the Soundcard. + * + * FIXME: Presently this quirk will run on anything that has an 8237 + * which isn't correct, we need to check DMI tables or something in + * order to make sure it only runs on the MSI-K8T-Neo2Fir. Because it + * runs everywhere at present we suppress the printk output in most + * irrelevant cases. */ static void __init k8t_sound_hostbridge(struct pci_dev *dev) { unsigned char val; - printk(KERN_INFO "PCI: Quirk-MSI-K8T Soundcard On\n"); pci_read_config_byte(dev, 0x50, &val); if (val == 0x88 || val == 0xc8) { + /* Assume it's probably a MSI-K8T-Neo2Fir */ + printk(KERN_INFO "PCI: MSI-K8T-Neo2Fir, attempting to turn soundcard ON\n"); pci_write_config_byte(dev, 0x50, val & (~0x40)); /* Verify the Change for Status output */ pci_read_config_byte(dev, 0x50, &val); if (val & 0x40) - printk(KERN_INFO "PCI: MSI-K8T soundcard still off\n"); + printk(KERN_INFO "PCI: MSI-K8T-Neo2Fir, soundcard still off\n"); else - printk(KERN_INFO "PCI: MSI-K8T soundcard on\n"); - } else { - printk(KERN_INFO "PCI: Unexpected Value in PCI-Register: " - "no Change!\n"); + printk(KERN_INFO "PCI: MSI-K8T-Neo2Fir, soundcard on\n"); } - } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, k8t_sound_hostbridge); -- cgit v1.2.3 From 4d15a1779dfdf7e7a111022697d3a43da1745d31 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 6 Jun 2006 16:58:25 -0400 Subject: [PATCH] PCI: fix error with pci_get_device() call in the mpc85xx driver Signed-off-by: Greg Kroah-Hartman --- arch/ppc/platforms/85xx/mpc85xx_cds_common.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c index c9e0aeeca3d..4368dc3f3c3 100644 --- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c +++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c @@ -379,13 +379,12 @@ mpc85xx_cds_pcibios_fixup(void) PCI_DEVICE_ID_VIA_82C586_2, NULL))) { dev->irq = 10; pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 10); - pci_dev_put(dev); - } - if ((dev = pci_get_device(PCI_VENDOR_ID_VIA, + if ((dev = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2, dev))) { - dev->irq = 11; - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11); + dev->irq = 11; + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11); + } pci_dev_put(dev); } } -- cgit v1.2.3 From acc7c2e0b73a46122ec370bf8a3aa9f19065d331 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Date: Thu, 15 Jun 2006 12:08:30 -0400 Subject: [PATCH] PCI: fix memory leak in MMCONFIG error path This a bit late (yours patch was posted about a year ago), but a co-worker of spotted part of the code that looks like a memory leak. Looking at the code it seems that pci_mmcfg_config should be free-ed if MMCONFIG is above 4GB. From: Konrad Rzeszutek Signed-off-by: Greg Kroah-Hartman --- arch/i386/kernel/acpi/boot.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c index 40e5aba3ad3..fbe93084244 100644 --- a/arch/i386/kernel/acpi/boot.c +++ b/arch/i386/kernel/acpi/boot.c @@ -202,6 +202,8 @@ int __init acpi_parse_mcfg(unsigned long phys_addr, unsigned long size) if (mcfg->config[i].base_reserved) { printk(KERN_ERR PREFIX "MMCONFIG not in low 4GB of memory\n"); + kfree(pci_mmcfg_config); + pci_mmcfg_config_num = 0; return -ENODEV; } } -- cgit v1.2.3 From bdee9d98d281d84718eaff6bf0dd2b6ad418b36f Mon Sep 17 00:00:00 2001 From: Doug Thompson Date: Wed, 14 Jun 2006 16:59:48 -0700 Subject: [PATCH] PCI: Bus Parity Status sysfs interface From: Doug Thompson This patch adds the 'broken_parity_status' sysfs attribute file to a PCI device. Reading this attribute a userland program can determine if PCI device provides false positives (value of 1) in its generation of PCI Parity status, or not (value of 0). As PCI devices are found to be 'bad' in this regard, userland programs can also set the appropriate value (root access only) of a faulty device. This per device information will be used in the EDAC PCI Parity scanner code in a future patch once this interface becomes available. Signed-off-by: Doug Thompson Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pci-sysfs.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 37897a8c95e..bc405c035ce 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -45,6 +45,28 @@ pci_config_attr(class, "0x%06x\n"); pci_config_attr(irq, "%u\n"); pci_config_attr(is_enabled, "%u\n"); +static ssize_t broken_parity_status_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct pci_dev *pdev = to_pci_dev(dev); + return sprintf (buf, "%u\n", pdev->broken_parity_status); +} + +static ssize_t broken_parity_status_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct pci_dev *pdev = to_pci_dev(dev); + ssize_t consumed = -EINVAL; + + if ((count > 0) && (*buf == '0' || *buf == '1')) { + pdev->broken_parity_status = *buf == '1' ? 1 : 0; + consumed = count; + } + return consumed; +} + static ssize_t local_cpus_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -122,6 +144,8 @@ struct device_attribute pci_dev_attrs[] = { __ATTR_RO(local_cpus), __ATTR_RO(modalias), __ATTR(enable, 0600, is_enabled_show, is_enabled_store), + __ATTR(broken_parity_status,(S_IRUGO|S_IWUSR), + broken_parity_status_show,broken_parity_status_store), __ATTR_NULL, }; -- cgit v1.2.3 From ead2bfeb7f739d2ad6e09dc1343f0da51feb7f51 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert <76306.1226@compuserve.com> Date: Thu, 15 Jun 2006 04:41:52 -0400 Subject: [PATCH] PCI: fix issues with extended conf space when MMCONFIG disabled because of e820 On 15 Jun 2006 03:45:10 +0200, Andi Kleen wrote: > Anyways I would say that if the BIOS can't get MCFG right then > it's likely not been validated on that board and shouldn't be used. According to Petr Vandrovec: ... "What is important (and checked) is address of MMCONFIG reported by MCFG table... Unfortunately code does not bother with printing that address :-( "Another problem is that code has hardcoded that MMCONFIG area is 256MB large. Unfortunately for the code PCI specification allows any power of two between 2MB and 256MB if vendor knows that such amount of busses (from 2 to 128) will be sufficient for system. With notebook it is quite possible that not full 8 bits are implemented for MMCONFIG bus number." So here is a patch. Unfortunately my system still fails the test because it doesn't reserve any part of the MMCONFIG area, but this may fix others. Booted on x86_64, only compiled on i386. x86_64 still remaps the max area (256MB) even though only 2MB is checked... but 2.6.16 had no check at all so it is still better. PCI: reduce size of x86 MMCONFIG reserved area check 1. Print the address of the MMCONFIG area when the test for that area being reserved fails. 2. Only check if the first 2MB is reserved, as that is the minimum. Signed-off-by: Chuck Ebbert <76306.1226@compuserve.com> Acked-by: Arjan van de Ven Signed-off-by: Greg Kroah-Hartman --- arch/i386/pci/mmconfig.c | 9 ++++++--- arch/x86_64/pci/mmconfig.c | 13 +++++++++---- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c index 6b1ea0c9a57..e545b0992c4 100644 --- a/arch/i386/pci/mmconfig.c +++ b/arch/i386/pci/mmconfig.c @@ -15,7 +15,9 @@ #include #include "pci.h" -#define MMCONFIG_APER_SIZE (256*1024*1024) +/* aperture is up to 256MB but BIOS may reserve less */ +#define MMCONFIG_APER_MIN (2 * 1024*1024) +#define MMCONFIG_APER_MAX (256 * 1024*1024) /* Assume systems with more busses have correct MCFG */ #define MAX_CHECK_BUS 16 @@ -197,9 +199,10 @@ void __init pci_mmcfg_init(void) return; if (!e820_all_mapped(pci_mmcfg_config[0].base_address, - pci_mmcfg_config[0].base_address + MMCONFIG_APER_SIZE, + pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN, E820_RESERVED)) { - printk(KERN_ERR "PCI: BIOS Bug: MCFG area is not E820-reserved\n"); + printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n", + pci_mmcfg_config[0].base_address); printk(KERN_ERR "PCI: Not using MMCONFIG.\n"); return; } diff --git a/arch/x86_64/pci/mmconfig.c b/arch/x86_64/pci/mmconfig.c index a2060e4d5de..3c55c76c6fd 100644 --- a/arch/x86_64/pci/mmconfig.c +++ b/arch/x86_64/pci/mmconfig.c @@ -13,7 +13,10 @@ #include "pci.h" -#define MMCONFIG_APER_SIZE (256*1024*1024) +/* aperture is up to 256MB but BIOS may reserve less */ +#define MMCONFIG_APER_MIN (2 * 1024*1024) +#define MMCONFIG_APER_MAX (256 * 1024*1024) + /* Verify the first 16 busses. We assume that systems with more busses get MCFG right. */ #define MAX_CHECK_BUS 16 @@ -175,9 +178,10 @@ void __init pci_mmcfg_init(void) return; if (!e820_all_mapped(pci_mmcfg_config[0].base_address, - pci_mmcfg_config[0].base_address + MMCONFIG_APER_SIZE, + pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN, E820_RESERVED)) { - printk(KERN_ERR "PCI: BIOS Bug: MCFG area is not E820-reserved\n"); + printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n", + pci_mmcfg_config[0].base_address); printk(KERN_ERR "PCI: Not using MMCONFIG.\n"); return; } @@ -190,7 +194,8 @@ void __init pci_mmcfg_init(void) } for (i = 0; i < pci_mmcfg_config_num; ++i) { pci_mmcfg_virt[i].cfg = &pci_mmcfg_config[i]; - pci_mmcfg_virt[i].virt = ioremap_nocache(pci_mmcfg_config[i].base_address, MMCONFIG_APER_SIZE); + pci_mmcfg_virt[i].virt = ioremap_nocache(pci_mmcfg_config[i].base_address, + MMCONFIG_APER_MAX); if (!pci_mmcfg_virt[i].virt) { printk("PCI: Cannot map mmconfig aperture for segment %d\n", pci_mmcfg_config[i].pci_segment_group_number); -- cgit v1.2.3 From cf34a8e07f02c76f3f1232eecb681301a3d7b10b Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Tue, 13 Jun 2006 14:35:42 -0400 Subject: [PATCH] PCI: nVidia quirk to make AER PCI-E extended capability visible The nVidia CK804 PCI-E chipset supports the AER extended capability but sometimes fails to link it (with some BIOS or after a warm reboot). It makes the AER cap invisible to pci_find_ext_capability(). The patch adds a quirk to set the missing bit that controls the linking of the capability. By the way, it removes the corresponding code in the myri10ge driver. Signed-off-by: Brice Goglin Signed-off-by: Loic Prylli Signed-off-by: Greg Kroah-Hartman --- drivers/pci/quirks.c | 19 +++++++++++++++++++ include/linux/pci_ids.h | 1 + 2 files changed, 20 insertions(+) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index aea4d49bcce..4364d793f73 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -1499,6 +1499,25 @@ static void __devinit quirk_p64h2_1k_io(struct pci_dev *dev) } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1460, quirk_p64h2_1k_io); +/* Under some circumstances, AER is not linked with extended capabilities. + * Force it to be linked by setting the corresponding control bit in the + * config space. + */ +static void __devinit quirk_nvidia_ck804_pcie_aer_ext_cap(struct pci_dev *dev) +{ + uint8_t b; + if (pci_read_config_byte(dev, 0xf41, &b) == 0) { + if (!(b & 0x20)) { + pci_write_config_byte(dev, 0xf41, b | 0x20); + printk(KERN_INFO + "PCI: Linking AER extended capability on %s\n", + pci_name(dev)); + } + } +} +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE, + quirk_nvidia_ck804_pcie_aer_ext_cap); + EXPORT_SYMBOL(pcie_mch_quirk); #ifdef CONFIG_HOTPLUG EXPORT_SYMBOL(pci_fixup_device); diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index e526e7b5ea4..fd54a9d4c3d 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1023,6 +1023,7 @@ #define PCI_DEVICE_ID_NVIDIA_NVENET_8 0x0056 #define PCI_DEVICE_ID_NVIDIA_NVENET_9 0x0057 #define PCI_DEVICE_ID_NVIDIA_CK804_AUDIO 0x0059 +#define PCI_DEVICE_ID_NVIDIA_CK804_PCIE 0x005d #define PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS 0x0064 #define PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE 0x0065 #define PCI_DEVICE_ID_NVIDIA_NVENET_2 0x0066 -- cgit v1.2.3 From 183bd5b3da82b80920c30c4772222df8027fc364 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 18 May 2006 10:39:21 -0700 Subject: [PATCH] kobject: make people pay attention to kobject_add errors These really need to be fixed, shout it out to the world. Signed-off-by: Greg Kroah-Hartman --- lib/kobject.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/kobject.c b/lib/kobject.c index 687ab418d29..8e7c7199348 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -198,14 +198,14 @@ int kobject_add(struct kobject * kobj) /* be noisy on error issues */ if (error == -EEXIST) - pr_debug("kobject_add failed for %s with -EEXIST, " + printk("kobject_add failed for %s with -EEXIST, " "don't try to register things with the " "same name in the same directory.\n", kobject_name(kobj)); else - pr_debug("kobject_add failed for %s (%d)\n", + printk("kobject_add failed for %s (%d)\n", kobject_name(kobj), error); - /* dump_stack(); */ + dump_stack(); } return error; -- cgit v1.2.3 From c18f6365fdbaf30611a8822afcd7097865dcaa32 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 27 Apr 2006 14:10:12 -0700 Subject: [PATCH] Add kernel<->userspace ABI stability documentation Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- Documentation/ABI/README | 77 +++++++++++++++++++++++++++++++++ Documentation/ABI/obsolete/devfs | 13 ++++++ Documentation/ABI/stable/syscalls | 10 +++++ Documentation/ABI/stable/sysfs-module | 30 +++++++++++++ Documentation/ABI/testing/sysfs-class | 16 +++++++ Documentation/ABI/testing/sysfs-devices | 25 +++++++++++ 6 files changed, 171 insertions(+) create mode 100644 Documentation/ABI/README create mode 100644 Documentation/ABI/obsolete/devfs create mode 100644 Documentation/ABI/stable/syscalls create mode 100644 Documentation/ABI/stable/sysfs-module create mode 100644 Documentation/ABI/testing/sysfs-class create mode 100644 Documentation/ABI/testing/sysfs-devices diff --git a/Documentation/ABI/README b/Documentation/ABI/README new file mode 100644 index 00000000000..9feaf16f161 --- /dev/null +++ b/Documentation/ABI/README @@ -0,0 +1,77 @@ +This directory attempts to document the ABI between the Linux kernel and +userspace, and the relative stability of these interfaces. Due to the +everchanging nature of Linux, and the differing maturity levels, these +interfaces should be used by userspace programs in different ways. + +We have four different levels of ABI stability, as shown by the four +different subdirectories in this location. Interfaces may change levels +of stability according to the rules described below. + +The different levels of stability are: + + stable/ + This directory documents the interfaces that the developer has + defined to be stable. Userspace programs are free to use these + interfaces with no restrictions, and backward compatibility for + them will be guaranteed for at least 2 years. Most interfaces + (like syscalls) are expected to never change and always be + available. + + testing/ + This directory documents interfaces that are felt to be stable, + as the main development of this interface has been completed. + The interface can be changed to add new features, but the + current interface will not break by doing this, unless grave + errors or security problems are found in them. Userspace + programs can start to rely on these interfaces, but they must be + aware of changes that can occur before these interfaces move to + be marked stable. Programs that use these interfaces are + strongly encouraged to add their name to the description of + these interfaces, so that the kernel developers can easily + notify them if any changes occur (see the description of the + layout of the files below for details on how to do this.) + + obsolete/ + This directory documents interfaces that are still remaining in + the kernel, but are marked to be removed at some later point in + time. The description of the interface will document the reason + why it is obsolete and when it can be expected to be removed. + The file Documentation/feature-removal-schedule.txt may describe + some of these interfaces, giving a schedule for when they will + be removed. + + removed/ + This directory contains a list of the old interfaces that have + been removed from the kernel. + +Every file in these directories will contain the following information: + +What: Short description of the interface +Date: Date created +KernelVersion: Kernel version this feature first showed up in. +Contact: Primary contact for this interface (may be a mailing list) +Description: Long description of the interface and how to use it. +Users: All users of this interface who wish to be notified when + it changes. This is very important for interfaces in + the "testing" stage, so that kernel developers can work + with userspace developers to ensure that things do not + break in ways that are unacceptable. It is also + important to get feedback for these interfaces to make + sure they are working in a proper way and do not need to + be changed further. + + +How things move between levels: + +Interfaces in stable may move to obsolete, as long as the proper +notification is given. + +Interfaces may be removed from obsolete and the kernel as long as the +documented amount of time has gone by. + +Interfaces in the testing state can move to the stable state when the +developers feel they are finished. They cannot be removed from the +kernel tree without going through the obsolete state first. + +It's up to the developer to place their interfaces in the category they +wish for it to start out in. diff --git a/Documentation/ABI/obsolete/devfs b/Documentation/ABI/obsolete/devfs new file mode 100644 index 00000000000..b8b87399bc8 --- /dev/null +++ b/Documentation/ABI/obsolete/devfs @@ -0,0 +1,13 @@ +What: devfs +Date: July 2005 +Contact: Greg Kroah-Hartman +Description: + devfs has been unmaintained for a number of years, has unfixable + races, contains a naming policy within the kernel that is + against the LSB, and can be replaced by using udev. + The files fs/devfs/*, include/linux/devfs_fs*.h will be removed, + along with the the assorted devfs function calls throughout the + kernel tree. + +Users: + diff --git a/Documentation/ABI/stable/syscalls b/Documentation/ABI/stable/syscalls new file mode 100644 index 00000000000..c3ae3e7d6a0 --- /dev/null +++ b/Documentation/ABI/stable/syscalls @@ -0,0 +1,10 @@ +What: The kernel syscall interface +Description: + This interface matches much of the POSIX interface and is based + on it and other Unix based interfaces. It will only be added to + over time, and not have things removed from it. + + Note that this interface is different for every architecture + that Linux supports. Please see the architecture-specific + documentation for details on the syscall numbers that are to be + mapped to each syscall. diff --git a/Documentation/ABI/stable/sysfs-module b/Documentation/ABI/stable/sysfs-module new file mode 100644 index 00000000000..75be4311833 --- /dev/null +++ b/Documentation/ABI/stable/sysfs-module @@ -0,0 +1,30 @@ +What: /sys/module +Description: + The /sys/module tree consists of the following structure: + + /sys/module/MODULENAME + The name of the module that is in the kernel. This + module name will show up either if the module is built + directly into the kernel, or if it is loaded as a + dyanmic module. + + /sys/module/MODULENAME/parameters + This directory contains individual files that are each + individual parameters of the module that are able to be + changed at runtime. See the individual module + documentation as to the contents of these parameters and + what they accomplish. + + Note: The individual parameter names and values are not + considered stable, only the fact that they will be + placed in this location within sysfs. See the + individual driver documentation for details as to the + stability of the different parameters. + + /sys/module/MODULENAME/refcnt + If the module is able to be unloaded from the kernel, this file + will contain the current reference count of the module. + + Note: If the module is built into the kernel, or if the + CONFIG_MODULE_UNLOAD kernel configuration value is not enabled, + this file will not be present. diff --git a/Documentation/ABI/testing/sysfs-class b/Documentation/ABI/testing/sysfs-class new file mode 100644 index 00000000000..4b0cb891e46 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-class @@ -0,0 +1,16 @@ +What: /sys/class/ +Date: Febuary 2006 +Contact: Greg Kroah-Hartman +Description: + The /sys/class directory will consist of a group of + subdirectories describing individual classes of devices + in the kernel. The individual directories will consist + of either subdirectories, or symlinks to other + directories. + + All programs that use this directory tree must be able + to handle both subdirectories or symlinks in order to + work properly. + +Users: + udev diff --git a/Documentation/ABI/testing/sysfs-devices b/Documentation/ABI/testing/sysfs-devices new file mode 100644 index 00000000000..6a25671ee5f --- /dev/null +++ b/Documentation/ABI/testing/sysfs-devices @@ -0,0 +1,25 @@ +What: /sys/devices +Date: February 2006 +Contact: Greg Kroah-Hartman +Description: + The /sys/devices tree contains a snapshot of the + internal state of the kernel device tree. Devices will + be added and removed dynamically as the machine runs, + and between different kernel versions, the layout of the + devices within this tree will change. + + Please do not rely on the format of this tree because of + this. If a program wishes to find different things in + the tree, please use the /sys/class structure and rely + on the symlinks there to point to the proper location + within the /sys/devices tree of the individual devices. + Or rely on the uevent messages to notify programs of + devices being added and removed from this tree to find + the location of those devices. + + Note that sometimes not all devices along the directory + chain will have emitted uevent messages, so userspace + programs must be able to handle such occurrences. + +Users: + udev -- cgit v1.2.3 From 27c0ff868f2ad3c9732ce45abbb8dd7e1723931f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 27 Apr 2006 15:46:39 -0700 Subject: [PATCH] CCISS: add device symlink to the block cciss block devices in sysfs Signed-off-by: Greg Kroah-Hartman --- drivers/block/cciss.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 1319d8f2064..25c3c4a5da8 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -3237,6 +3237,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, disk->fops = &cciss_fops; disk->queue = q; disk->private_data = drv; + disk->driverfs_dev = &pdev->dev; /* we must register the controller even if no disks exist */ /* this is for the online array utilities */ if(!drv->heads && j) -- cgit v1.2.3 From 53877d06d53a412d901bb323f080296c363d8b51 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 4 Apr 2006 20:42:26 +0200 Subject: [PATCH] Driver core: bus device event delay split bus_add_device() and send device uevents after sysfs population Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/base/base.h | 1 + drivers/base/bus.c | 22 ++++++++++++++++++---- drivers/base/core.c | 3 ++- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/drivers/base/base.h b/drivers/base/base.h index 5735b38582d..bbbc2acd921 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -11,6 +11,7 @@ extern int cpu_dev_init(void); extern int attribute_container_init(void); extern int bus_add_device(struct device * dev); +extern void bus_attach_device(struct device * dev); extern void bus_remove_device(struct device * dev); extern int bus_add_driver(struct device_driver *); diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 76656acd00d..b27a6067e5a 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -362,8 +362,7 @@ static void device_remove_attrs(struct bus_type * bus, struct device * dev) * @dev: device being added * * - Add the device to its bus's list of devices. - * - Try to attach to driver. - * - Create link to device's physical location. + * - Create link to device's bus. */ int bus_add_device(struct device * dev) { @@ -372,8 +371,6 @@ int bus_add_device(struct device * dev) if (bus) { pr_debug("bus %s: add device %s\n", bus->name, dev->bus_id); - device_attach(dev); - klist_add_tail(&dev->knode_bus, &bus->klist_devices); error = device_add_attrs(bus, dev); if (!error) { sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id); @@ -383,6 +380,22 @@ int bus_add_device(struct device * dev) return error; } +/** + * bus_attach_device - add device to bus + * @dev: device tried to attach to a driver + * + * - Try to attach to driver. + */ +void bus_attach_device(struct device * dev) +{ + struct bus_type * bus = dev->bus; + + if (bus) { + device_attach(dev); + klist_add_tail(&dev->knode_bus, &bus->klist_devices); + } +} + /** * bus_remove_device - remove device from bus * @dev: device to be removed @@ -733,6 +746,7 @@ EXPORT_SYMBOL_GPL(bus_find_device); EXPORT_SYMBOL_GPL(bus_for_each_drv); EXPORT_SYMBOL_GPL(bus_add_device); +EXPORT_SYMBOL_GPL(bus_attach_device); EXPORT_SYMBOL_GPL(bus_remove_device); EXPORT_SYMBOL_GPL(bus_register); EXPORT_SYMBOL_GPL(bus_unregister); diff --git a/drivers/base/core.c b/drivers/base/core.c index 6b355bd7816..d5e15a03584 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -274,11 +274,12 @@ int device_add(struct device *dev) dev->uevent_attr.store = store_uevent; device_create_file(dev, &dev->uevent_attr); - kobject_uevent(&dev->kobj, KOBJ_ADD); if ((error = device_pm_add(dev))) goto PMError; if ((error = bus_add_device(dev))) goto BusError; + kobject_uevent(&dev->kobj, KOBJ_ADD); + bus_attach_device(dev); if (parent) klist_add_tail(&dev->knode_parent, &parent->klist_children); -- cgit v1.2.3 From 1cdcb6b43fda7424b7435dac8f80b2b5d8a48899 Mon Sep 17 00:00:00 2001 From: Hansjoerg Lipp Date: Sat, 22 Apr 2006 18:36:53 +0200 Subject: [PATCH] TTY: return class device pointer from tty_register_device() Let tty_register_device() return a pointer to the class device it creates. This allows registrants to add their own sysfs files under the class device node. Signed-off-by: Hansjoerg Lipp Signed-off-by: Tilman Schmidt Signed-off-by: Greg Kroah-Hartman --- drivers/char/tty_io.c | 11 +++++++---- include/linux/tty.h | 4 +++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index a88b94a82b1..8b2a5996986 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -2961,12 +2961,14 @@ static struct class *tty_class; * This field is optional, if there is no known struct device for this * tty device it can be set to NULL safely. * + * Returns a pointer to the class device (or ERR_PTR(-EFOO) on error). + * * This call is required to be made to register an individual tty device if * the tty driver's flags have the TTY_DRIVER_NO_DEVFS bit set. If that * bit is not set, this function should not be called. */ -void tty_register_device(struct tty_driver *driver, unsigned index, - struct device *device) +struct class_device *tty_register_device(struct tty_driver *driver, + unsigned index, struct device *device) { char name[64]; dev_t dev = MKDEV(driver->major, driver->minor_start) + index; @@ -2974,7 +2976,7 @@ void tty_register_device(struct tty_driver *driver, unsigned index, if (index >= driver->num) { printk(KERN_ERR "Attempt to register invalid tty line number " " (%d).\n", index); - return; + return ERR_PTR(-EINVAL); } devfs_mk_cdev(dev, S_IFCHR | S_IRUSR | S_IWUSR, @@ -2984,7 +2986,8 @@ void tty_register_device(struct tty_driver *driver, unsigned index, pty_line_name(driver, index, name); else tty_line_name(driver, index, name); - class_device_create(tty_class, NULL, dev, device, "%s", name); + + return class_device_create(tty_class, NULL, dev, device, "%s", name); } /** diff --git a/include/linux/tty.h b/include/linux/tty.h index e898eeb9416..cb35ca50a0a 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -290,7 +290,9 @@ extern int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc); extern int tty_unregister_ldisc(int disc); extern int tty_register_driver(struct tty_driver *driver); extern int tty_unregister_driver(struct tty_driver *driver); -extern void tty_register_device(struct tty_driver *driver, unsigned index, struct device *dev); +extern struct class_device *tty_register_device(struct tty_driver *driver, + unsigned index, + struct device *dev); extern void tty_unregister_device(struct tty_driver *driver, unsigned index); extern int tty_read_raw_data(struct tty_struct *tty, unsigned char *bufp, int buflen); -- cgit v1.2.3 From 3dda4e373c7474cfe280f4270b70c1563f92a2a7 Mon Sep 17 00:00:00 2001 From: Hansjoerg Lipp Date: Sat, 22 Apr 2006 18:43:00 +0200 Subject: [PATCH] i4l gigaset: move sysfs entry to tty class device Using the class device pointer returned by tty_register_device() with part 1 of the patch, attach the Gigaset drivers' "cidmode" sysfs entry to its tty class device, where it can be found more easily by users who do not know nor care which USB port the device is attached to. Signed-off-by: Hansjoerg Lipp Signed-off-by: Tilman Schmidt Signed-off-by: Greg Kroah-Hartman --- Documentation/isdn/README.gigaset | 7 ++++--- drivers/isdn/gigaset/common.c | 13 +++++++------ drivers/isdn/gigaset/gigaset.h | 1 + drivers/isdn/gigaset/interface.c | 10 +++++++++- drivers/isdn/gigaset/proc.c | 21 +++++++++++++-------- 5 files changed, 34 insertions(+), 18 deletions(-) diff --git a/Documentation/isdn/README.gigaset b/Documentation/isdn/README.gigaset index 85a64defd38..fa0d4cca964 100644 --- a/Documentation/isdn/README.gigaset +++ b/Documentation/isdn/README.gigaset @@ -124,7 +124,8 @@ GigaSet 307x Device Driver You can use some configuration tool of your distribution to configure this "modem" or configure pppd/wvdial manually. There are some example ppp - configuration files and chat scripts in the gigaset-VERSION/ppp directory. + configuration files and chat scripts in the gigaset-VERSION/ppp directory + in the driver packages from http://sourceforge.net/projects/gigaset307x/. Please note that the USB drivers are not able to change the state of the control lines (the M105 driver can be configured to use some undocumented control requests, if you really need the control lines, though). This means @@ -164,8 +165,8 @@ GigaSet 307x Device Driver If you want both of these at once, you are out of luck. - You can also use /sys/module//parameters/cidmode for changing - the CID mode setting ( is usb_gigaset or bas_gigaset). + You can also use /sys/class/tty/ttyGxy/cidmode for changing the CID mode + setting (ttyGxy is ttyGU0 or ttyGB0). 3. Troubleshooting diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index e55767b2ccd..acb7e265678 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c @@ -460,6 +460,9 @@ void gigaset_freecs(struct cardstate *cs) switch (cs->cs_init) { default: + /* clear device sysfs */ + gigaset_free_dev_sysfs(cs); + gigaset_if_free(cs); gig_dbg(DEBUG_INIT, "clearing hw"); @@ -699,6 +702,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, cs->open_count = 0; cs->dev = NULL; cs->tty = NULL; + cs->class = NULL; cs->cidmode = cidmode != 0; //if(onechannel) { //FIXME @@ -760,6 +764,9 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, gigaset_if_init(cs); + /* set up device sysfs */ + gigaset_init_dev_sysfs(cs); + spin_lock_irqsave(&cs->lock, flags); cs->running = 1; spin_unlock_irqrestore(&cs->lock, flags); @@ -902,9 +909,6 @@ int gigaset_start(struct cardstate *cs) wait_event(cs->waitqueue, !cs->waiting); - /* set up device sysfs */ - gigaset_init_dev_sysfs(cs); - mutex_unlock(&cs->mutex); return 1; @@ -969,9 +973,6 @@ void gigaset_stop(struct cardstate *cs) //FIXME } - /* clear device sysfs */ - gigaset_free_dev_sysfs(cs); - cleanup_cs(cs); exit: diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h index 22b9693f7c0..8d63d822104 100644 --- a/drivers/isdn/gigaset/gigaset.h +++ b/drivers/isdn/gigaset/gigaset.h @@ -445,6 +445,7 @@ struct cardstate { struct gigaset_driver *driver; unsigned minor_index; struct device *dev; + struct class_device *class; const struct gigaset_ops *ops; diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c index 08e4c4eea14..74fd234956c 100644 --- a/drivers/isdn/gigaset/interface.c +++ b/drivers/isdn/gigaset/interface.c @@ -625,7 +625,14 @@ void gigaset_if_init(struct cardstate *cs) return; tasklet_init(&cs->if_wake_tasklet, &if_wake, (unsigned long) cs); - tty_register_device(drv->tty, cs->minor_index, NULL); + cs->class = tty_register_device(drv->tty, cs->minor_index, NULL); + + if (!IS_ERR(cs->class)) + class_set_devdata(cs->class, cs); + else { + warn("could not register device to the tty subsystem"); + cs->class = NULL; + } } void gigaset_if_free(struct cardstate *cs) @@ -638,6 +645,7 @@ void gigaset_if_free(struct cardstate *cs) tasklet_disable(&cs->if_wake_tasklet); tasklet_kill(&cs->if_wake_tasklet); + cs->class = NULL; tty_unregister_device(drv->tty, cs->minor_index); } diff --git a/drivers/isdn/gigaset/proc.c b/drivers/isdn/gigaset/proc.c index d267a636b53..9ae3a7f3e7b 100644 --- a/drivers/isdn/gigaset/proc.c +++ b/drivers/isdn/gigaset/proc.c @@ -16,12 +16,11 @@ #include "gigaset.h" #include -static ssize_t show_cidmode(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t show_cidmode(struct class_device *class, char *buf) { int ret; unsigned long flags; - struct cardstate *cs = dev_get_drvdata(dev); + struct cardstate *cs = class_get_devdata(class); spin_lock_irqsave(&cs->lock, flags); ret = sprintf(buf, "%u\n", cs->cidmode); @@ -30,10 +29,10 @@ static ssize_t show_cidmode(struct device *dev, struct device_attribute *attr, return ret; } -static ssize_t set_cidmode(struct device *dev, struct device_attribute *attr, +static ssize_t set_cidmode(struct class_device *class, const char *buf, size_t count) { - struct cardstate *cs = dev_get_drvdata(dev); + struct cardstate *cs = class_get_devdata(class); long int value; char *end; @@ -65,18 +64,24 @@ static ssize_t set_cidmode(struct device *dev, struct device_attribute *attr, return count; } -static DEVICE_ATTR(cidmode, S_IRUGO|S_IWUSR, show_cidmode, set_cidmode); +static CLASS_DEVICE_ATTR(cidmode, S_IRUGO|S_IWUSR, show_cidmode, set_cidmode); /* free sysfs for device */ void gigaset_free_dev_sysfs(struct cardstate *cs) { + if (!cs->class) + return; + gig_dbg(DEBUG_INIT, "removing sysfs entries"); - device_remove_file(cs->dev, &dev_attr_cidmode); + class_device_remove_file(cs->class, &class_device_attr_cidmode); } /* initialize sysfs for device */ void gigaset_init_dev_sysfs(struct cardstate *cs) { + if (!cs->class) + return; + gig_dbg(DEBUG_INIT, "setting up sysfs"); - device_create_file(cs->dev, &dev_attr_cidmode); + class_device_create_file(cs->class, &class_device_attr_cidmode); } -- cgit v1.2.3 From b7fe4a60f3a5a428832bf5dd9388e80f0d02fc2e Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 26 Apr 2006 09:53:14 -0700 Subject: [PATCH] Driver core: class_device_add needs error checks class_device_add needs to check the return value of all the setup it does. It doesn't handle out of memory well. This is not complete, probably more needs to be done. Signed-off-by: Stephen Hemminger Signed-off-by: Greg Kroah-Hartman --- drivers/base/class.c | 72 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 54 insertions(+), 18 deletions(-) diff --git a/drivers/base/class.c b/drivers/base/class.c index b1ea4df85c7..48ad5df7281 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -535,18 +535,22 @@ int class_device_add(struct class_device *class_dev) return -EINVAL; if (!strlen(class_dev->class_id)) - goto register_done; + goto out1; parent_class = class_get(class_dev->class); if (!parent_class) - goto register_done; + goto out1; + parent_class_dev = class_device_get(class_dev->parent); pr_debug("CLASS: registering class device: ID = '%s'\n", class_dev->class_id); /* first, register with generic layer. */ - kobject_set_name(&class_dev->kobj, "%s", class_dev->class_id); + error = kobject_set_name(&class_dev->kobj, "%s", class_dev->class_id); + if (error) + goto out2; + if (parent_class_dev) class_dev->kobj.parent = &parent_class_dev->kobj; else @@ -554,41 +558,56 @@ int class_device_add(struct class_device *class_dev) error = kobject_add(&class_dev->kobj); if (error) - goto register_done; + goto out2; /* add the needed attributes to this device */ class_dev->uevent_attr.attr.name = "uevent"; class_dev->uevent_attr.attr.mode = S_IWUSR; class_dev->uevent_attr.attr.owner = parent_class->owner; class_dev->uevent_attr.store = store_uevent; - class_device_create_file(class_dev, &class_dev->uevent_attr); + error = class_device_create_file(class_dev, &class_dev->uevent_attr); + if (error) + goto out3; if (MAJOR(class_dev->devt)) { struct class_device_attribute *attr; attr = kzalloc(sizeof(*attr), GFP_KERNEL); if (!attr) { error = -ENOMEM; - kobject_del(&class_dev->kobj); - goto register_done; + goto out4; } attr->attr.name = "dev"; attr->attr.mode = S_IRUGO; attr->attr.owner = parent_class->owner; attr->show = show_dev; - class_device_create_file(class_dev, attr); + error = class_device_create_file(class_dev, attr); + if (error) { + kfree(attr); + goto out4; + } + class_dev->devt_attr = attr; } - class_device_add_attrs(class_dev); + error = class_device_add_attrs(class_dev); + if (error) + goto out5; + if (class_dev->dev) { class_name = make_class_name(class_dev); - sysfs_create_link(&class_dev->kobj, - &class_dev->dev->kobj, "device"); - sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj, - class_name); + error = sysfs_create_link(&class_dev->kobj, + &class_dev->dev->kobj, "device"); + if (error) + goto out6; + error = sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj, + class_name); + if (error) + goto out7; } - class_device_add_groups(class_dev); + error = class_device_add_groups(class_dev); + if (error) + goto out8; kobject_uevent(&class_dev->kobj, KOBJ_ADD); @@ -601,11 +620,28 @@ int class_device_add(struct class_device *class_dev) } up(&parent_class->sem); - register_done: - if (error) { - class_put(parent_class); + goto out1; + + out8: + if (class_dev->dev) + sysfs_remove_link(&class_dev->kobj, class_name); + out7: + if (class_dev->dev) + sysfs_remove_link(&class_dev->kobj, "device"); + out6: + class_device_remove_attrs(class_dev); + out5: + if (class_dev->devt_attr) + class_device_remove_file(class_dev, class_dev->devt_attr); + out4: + class_device_remove_file(class_dev, &class_dev->uevent_attr); + out3: + kobject_del(&class_dev->kobj); + out2: + if(parent_class_dev) class_device_put(parent_class_dev); - } + class_put(parent_class); + out1: class_device_put(class_dev); kfree(class_name); return error; -- cgit v1.2.3 From 05967118a6c354eaa5950429c70ad4c8daca94bf Mon Sep 17 00:00:00 2001 From: David Brownell Date: Mon, 1 May 2006 13:58:33 -0700 Subject: [PATCH] Driver Core: CONFIG_DEBUG_PM covers drivers/base/power too The drivers/base/power PM debug messages should appear when either PM or driver model debug are enabled. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/base/power/Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/base/power/Makefile b/drivers/base/power/Makefile index c0219ad94ac..ceeeba2c56c 100644 --- a/drivers/base/power/Makefile +++ b/drivers/base/power/Makefile @@ -4,3 +4,6 @@ obj-$(CONFIG_PM) += main.o suspend.o resume.o runtime.o sysfs.o ifeq ($(CONFIG_DEBUG_DRIVER),y) EXTRA_CFLAGS += -DDEBUG endif +ifeq ($(CONFIG_PM_DEBUG),y) +EXTRA_CFLAGS += -DDEBUG +endif -- cgit v1.2.3 From a0245f7ad5214cb00131d7cd176446e067c913dc Mon Sep 17 00:00:00 2001 From: David Brownell Date: Mon, 29 May 2006 10:37:33 -0700 Subject: [PATCH] platform_bus learns about modalias This patch adds modalias support to platform devices, for simpler hotplug/coldplug driven driver setup. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 83f5c5984d1..f8071976fe0 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -452,6 +452,37 @@ void platform_driver_unregister(struct platform_driver *drv) EXPORT_SYMBOL_GPL(platform_driver_unregister); +/* modalias support enables more hands-off userspace setup: + * (a) environment variable lets new-style hotplug events work once system is + * fully running: "modprobe $MODALIAS" + * (b) sysfs attribute lets new-style coldplug recover from hotplug events + * mishandled before system is fully running: "modprobe $(cat modalias)" + */ +static ssize_t +modalias_show(struct device *dev, struct device_attribute *a, char *buf) +{ + struct platform_device *pdev = to_platform_device(dev); + int len = snprintf(buf, PAGE_SIZE, "%s\n", pdev->name); + + return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len; +} + +static struct device_attribute platform_dev_attrs[] = { + __ATTR_RO(modalias), + __ATTR_NULL, +}; + +static int platform_uevent(struct device *dev, char **envp, int num_envp, + char *buffer, int buffer_size) +{ + struct platform_device *pdev = to_platform_device(dev); + + envp[0] = buffer; + snprintf(buffer, buffer_size, "MODALIAS=%s", pdev->name); + return 0; +} + + /** * platform_match - bind platform device to platform driver. * @dev: device. @@ -496,7 +527,9 @@ static int platform_resume(struct device * dev) struct bus_type platform_bus_type = { .name = "platform", + .dev_attrs = platform_dev_attrs, .match = platform_match, + .uevent = platform_uevent, .suspend = platform_suspend, .resume = platform_resume, }; -- cgit v1.2.3 From 1740757e8f94c6899705eb6f5434de9404992778 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 2 May 2006 16:59:59 +0200 Subject: [PATCH] Driver Core: remove unused exports Cc: Arjan van de Ven Signed-off-by: Greg Kroah-Hartman --- drivers/base/attribute_container.c | 8 -------- drivers/base/base.h | 2 ++ drivers/base/bus.c | 6 ------ drivers/base/class.c | 6 ++---- include/linux/device.h | 8 -------- 5 files changed, 4 insertions(+), 26 deletions(-) diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c index 2a7d7ae83e1..22220733f76 100644 --- a/drivers/base/attribute_container.c +++ b/drivers/base/attribute_container.c @@ -236,7 +236,6 @@ attribute_container_remove_device(struct device *dev, } up(&attribute_container_mutex); } -EXPORT_SYMBOL_GPL(attribute_container_remove_device); /** * attribute_container_device_trigger - execute a trigger for each matching classdev @@ -276,7 +275,6 @@ attribute_container_device_trigger(struct device *dev, } up(&attribute_container_mutex); } -EXPORT_SYMBOL_GPL(attribute_container_device_trigger); /** * attribute_container_trigger - trigger a function for each matching container @@ -304,7 +302,6 @@ attribute_container_trigger(struct device *dev, } up(&attribute_container_mutex); } -EXPORT_SYMBOL_GPL(attribute_container_trigger); /** * attribute_container_add_attrs - add attributes @@ -333,7 +330,6 @@ attribute_container_add_attrs(struct class_device *classdev) return 0; } -EXPORT_SYMBOL_GPL(attribute_container_add_attrs); /** * attribute_container_add_class_device - same function as class_device_add @@ -352,7 +348,6 @@ attribute_container_add_class_device(struct class_device *classdev) return error; return attribute_container_add_attrs(classdev); } -EXPORT_SYMBOL_GPL(attribute_container_add_class_device); /** * attribute_container_add_class_device_adapter - simple adapter for triggers @@ -367,7 +362,6 @@ attribute_container_add_class_device_adapter(struct attribute_container *cont, { return attribute_container_add_class_device(classdev); } -EXPORT_SYMBOL_GPL(attribute_container_add_class_device_adapter); /** * attribute_container_remove_attrs - remove any attribute files @@ -389,7 +383,6 @@ attribute_container_remove_attrs(struct class_device *classdev) for (i = 0; attrs[i]; i++) class_device_remove_file(classdev, attrs[i]); } -EXPORT_SYMBOL_GPL(attribute_container_remove_attrs); /** * attribute_container_class_device_del - equivalent of class_device_del @@ -405,7 +398,6 @@ attribute_container_class_device_del(struct class_device *classdev) attribute_container_remove_attrs(classdev); class_device_del(classdev); } -EXPORT_SYMBOL_GPL(attribute_container_class_device_del); /** * attribute_container_find_class_device - find the corresponding class_device diff --git a/drivers/base/base.h b/drivers/base/base.h index bbbc2acd921..122498aef50 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -13,6 +13,8 @@ extern int attribute_container_init(void); extern int bus_add_device(struct device * dev); extern void bus_attach_device(struct device * dev); extern void bus_remove_device(struct device * dev); +extern struct bus_type *get_bus(struct bus_type * bus); +extern void put_bus(struct bus_type * bus); extern int bus_add_driver(struct device_driver *); extern void bus_remove_driver(struct device_driver *); diff --git a/drivers/base/bus.c b/drivers/base/bus.c index b27a6067e5a..64ba9011d1a 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -745,15 +745,9 @@ EXPORT_SYMBOL_GPL(bus_for_each_dev); EXPORT_SYMBOL_GPL(bus_find_device); EXPORT_SYMBOL_GPL(bus_for_each_drv); -EXPORT_SYMBOL_GPL(bus_add_device); -EXPORT_SYMBOL_GPL(bus_attach_device); -EXPORT_SYMBOL_GPL(bus_remove_device); EXPORT_SYMBOL_GPL(bus_register); EXPORT_SYMBOL_GPL(bus_unregister); EXPORT_SYMBOL_GPL(bus_rescan_devices); -EXPORT_SYMBOL_GPL(get_bus); -EXPORT_SYMBOL_GPL(put_bus); -EXPORT_SYMBOL_GPL(find_bus); EXPORT_SYMBOL_GPL(bus_create_file); EXPORT_SYMBOL_GPL(bus_remove_file); diff --git a/drivers/base/class.c b/drivers/base/class.c index 48ad5df7281..4b598be0e4b 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -91,14 +91,14 @@ void class_remove_file(struct class * cls, const struct class_attribute * attr) sysfs_remove_file(&cls->subsys.kset.kobj, &attr->attr); } -struct class * class_get(struct class * cls) +static struct class *class_get(struct class *cls) { if (cls) return container_of(subsys_get(&cls->subsys), struct class, subsys); return NULL; } -void class_put(struct class * cls) +static void class_put(struct class * cls) { if (cls) subsys_put(&cls->subsys); @@ -894,8 +894,6 @@ EXPORT_SYMBOL_GPL(class_create_file); EXPORT_SYMBOL_GPL(class_remove_file); EXPORT_SYMBOL_GPL(class_register); EXPORT_SYMBOL_GPL(class_unregister); -EXPORT_SYMBOL_GPL(class_get); -EXPORT_SYMBOL_GPL(class_put); EXPORT_SYMBOL_GPL(class_create); EXPORT_SYMBOL_GPL(class_destroy); diff --git a/include/linux/device.h b/include/linux/device.h index b2e5da2b637..ade10dd6b77 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -60,11 +60,6 @@ extern void bus_unregister(struct bus_type * bus); extern void bus_rescan_devices(struct bus_type * bus); -extern struct bus_type * get_bus(struct bus_type * bus); -extern void put_bus(struct bus_type * bus); - -extern struct bus_type * find_bus(char * name); - /* iterator helpers for buses */ int bus_for_each_dev(struct bus_type * bus, struct device * start, void * data, @@ -163,9 +158,6 @@ struct class { extern int class_register(struct class *); extern void class_unregister(struct class *); -extern struct class * class_get(struct class *); -extern void class_put(struct class *); - struct class_attribute { struct attribute attr; -- cgit v1.2.3 From 670dd90d81f60ef429cbba54ad235e9207f4d444 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Mon, 8 May 2006 13:45:57 +0800 Subject: [PATCH] Driver Core: Allow sysdev_class have attributes allow sysdev_class adding attribute. Next patch will use the new API to add an attribute under /sys/device/system/cpu/. Signed-off-by: Shaohua Li Signed-off-by: Greg Kroah-Hartman --- drivers/base/sys.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++- include/linux/sysdev.h | 18 +++++++++++++++++- 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/drivers/base/sys.c b/drivers/base/sys.c index 6fc23ab127b..6858178b3af 100644 --- a/drivers/base/sys.c +++ b/drivers/base/sys.c @@ -80,10 +80,59 @@ void sysdev_remove_file(struct sys_device * s, struct sysdev_attribute * a) EXPORT_SYMBOL_GPL(sysdev_create_file); EXPORT_SYMBOL_GPL(sysdev_remove_file); +#define to_sysdev_class(k) container_of(k, struct sysdev_class, kset.kobj) +#define to_sysdev_class_attr(a) container_of(a, \ + struct sysdev_class_attribute, attr) + +static ssize_t sysdev_class_show(struct kobject *kobj, struct attribute *attr, + char *buffer) +{ + struct sysdev_class * class = to_sysdev_class(kobj); + struct sysdev_class_attribute *class_attr = to_sysdev_class_attr(attr); + + if (class_attr->show) + return class_attr->show(class, buffer); + return -EIO; +} + +static ssize_t sysdev_class_store(struct kobject *kobj, struct attribute *attr, + const char *buffer, size_t count) +{ + struct sysdev_class * class = to_sysdev_class(kobj); + struct sysdev_class_attribute * class_attr = to_sysdev_class_attr(attr); + + if (class_attr->store) + return class_attr->store(class, buffer, count); + return -EIO; +} + +static struct sysfs_ops sysfs_class_ops = { + .show = sysdev_class_show, + .store = sysdev_class_store, +}; + +static struct kobj_type ktype_sysdev_class = { + .sysfs_ops = &sysfs_class_ops, +}; + +int sysdev_class_create_file(struct sysdev_class *c, + struct sysdev_class_attribute *a) +{ + return sysfs_create_file(&c->kset.kobj, &a->attr); +} +EXPORT_SYMBOL_GPL(sysdev_class_create_file); + +void sysdev_class_remove_file(struct sysdev_class *c, + struct sysdev_class_attribute *a) +{ + sysfs_remove_file(&c->kset.kobj, &a->attr); +} +EXPORT_SYMBOL_GPL(sysdev_class_remove_file); + /* * declare system_subsys */ -static decl_subsys(system, &ktype_sysdev, NULL); +static decl_subsys(system, &ktype_sysdev_class, NULL); int sysdev_class_register(struct sysdev_class * cls) { diff --git a/include/linux/sysdev.h b/include/linux/sysdev.h index 2a4b432e117..166a2e58c28 100644 --- a/include/linux/sysdev.h +++ b/include/linux/sysdev.h @@ -37,11 +37,27 @@ struct sysdev_class { struct kset kset; }; +struct sysdev_class_attribute { + struct attribute attr; + ssize_t (*show)(struct sysdev_class *, char *); + ssize_t (*store)(struct sysdev_class *, const char *, size_t); +}; + +#define SYSDEV_CLASS_ATTR(_name,_mode,_show,_store) \ +struct sysdev_class_attribute attr_##_name = { \ + .attr = {.name = __stringify(_name), .mode = _mode }, \ + .show = _show, \ + .store = _store, \ +}; + extern int sysdev_class_register(struct sysdev_class *); extern void sysdev_class_unregister(struct sysdev_class *); - +extern int sysdev_class_create_file(struct sysdev_class *, + struct sysdev_class_attribute *); +extern void sysdev_class_remove_file(struct sysdev_class *, + struct sysdev_class_attribute *); /** * Auxillary system device drivers. */ -- cgit v1.2.3 From e391553222211e07dfbe2f01c413b4e6d0ae32aa Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 6 May 2006 08:15:26 +0100 Subject: [PATCH] Driver Core: Fix platform_device_add to use device_add platform_device_add() should be using device_add() rather than device_register() - any platform device passed to platform_device_add() should have already been initialised, either by platform_device_alloc() or platform_device_register(). Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/platform.c b/drivers/base/platform.c index f8071976fe0..2b8755db76c 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -275,7 +275,7 @@ int platform_device_add(struct platform_device *pdev) pr_debug("Registering platform device '%s'. Parent at %s\n", pdev->dev.bus_id, pdev->dev.parent->bus_id); - ret = device_register(&pdev->dev); + ret = device_add(&pdev->dev); if (ret == 0) return ret; -- cgit v1.2.3 From 4039483fd3065920f035eed39ec59085421c0a4f Mon Sep 17 00:00:00 2001 From: Michael Holzheu Date: Tue, 9 May 2006 12:53:49 +0200 Subject: [PATCH] Driver Core: Add /sys/hypervisor when needed To have a home for all hypervisors, this patch creates /sys/hypervisor. A new config option SYS_HYPERVISOR is introduced, which should to be set by architecture dependent hypervisors (e.g. s390 or Xen). Acked-by: Martin Schwidefsky Signed-off-by: Michael Holzheu Signed-off-by: Greg Kroah-Hartman --- drivers/base/Kconfig | 4 ++++ drivers/base/Makefile | 1 + drivers/base/base.h | 5 +++++ drivers/base/hypervisor.c | 19 +++++++++++++++++++ drivers/base/init.c | 1 + include/linux/kobject.h | 2 ++ 6 files changed, 32 insertions(+) create mode 100644 drivers/base/hypervisor.c diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index f0eff3dac58..80502dc6ed6 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig @@ -38,3 +38,7 @@ config DEBUG_DRIVER If you are unsure about this, say N here. endmenu + +config SYS_HYPERVISOR + bool + default n diff --git a/drivers/base/Makefile b/drivers/base/Makefile index e99471d3232..659cde6c2fb 100644 --- a/drivers/base/Makefile +++ b/drivers/base/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_FW_LOADER) += firmware_class.o obj-$(CONFIG_NUMA) += node.o obj-$(CONFIG_MEMORY_HOTPLUG) += memory.o obj-$(CONFIG_SMP) += topology.o +obj-$(CONFIG_SYS_HYPERVISOR) += hypervisor.o ifeq ($(CONFIG_DEBUG_DRIVER),y) EXTRA_CFLAGS += -DDEBUG diff --git a/drivers/base/base.h b/drivers/base/base.h index 122498aef50..79115eff6e9 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -5,6 +5,11 @@ extern int devices_init(void); extern int buses_init(void); extern int classes_init(void); extern int firmware_init(void); +#ifdef CONFIG_SYS_HYPERVISOR +extern int hypervisor_init(void); +#else +static inline int hypervisor_init(void) { return 0; } +#endif extern int platform_bus_init(void); extern int system_bus_init(void); extern int cpu_dev_init(void); diff --git a/drivers/base/hypervisor.c b/drivers/base/hypervisor.c new file mode 100644 index 00000000000..0c85e9d6a44 --- /dev/null +++ b/drivers/base/hypervisor.c @@ -0,0 +1,19 @@ +/* + * hypervisor.c - /sys/hypervisor subsystem. + * + * This file is released under the GPLv2 + * + */ + +#include +#include + +#include "base.h" + +decl_subsys(hypervisor, NULL, NULL); +EXPORT_SYMBOL_GPL(hypervisor_subsys); + +int __init hypervisor_init(void) +{ + return subsystem_register(&hypervisor_subsys); +} diff --git a/drivers/base/init.c b/drivers/base/init.c index c648914b9cd..37138154f9e 100644 --- a/drivers/base/init.c +++ b/drivers/base/init.c @@ -27,6 +27,7 @@ void __init driver_init(void) buses_init(); classes_init(); firmware_init(); + hypervisor_init(); /* These are also core pieces, but must come after the * core core pieces. diff --git a/include/linux/kobject.h b/include/linux/kobject.h index c187c53cecd..2d229327959 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h @@ -190,6 +190,8 @@ struct subsystem _varname##_subsys = { \ /* The global /sys/kernel/ subsystem for people to chain off of */ extern struct subsystem kernel_subsys; +/* The global /sys/hypervisor/ subsystem */ +extern struct subsystem hypervisor_subsys; /** * Helpers for setting the kset of registered objects. -- cgit v1.2.3 From 1e724845034eb898c97dc6636207f0a231af9432 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Tue, 16 May 2006 17:00:08 -0700 Subject: [PATCH] remove duplication from Documentation/power/devices.txt Remove a chunk of duplicated documentation text. Signed-off-by: Greg Kroah-Hartman --- Documentation/power/devices.txt | 90 ----------------------------------------- 1 file changed, 90 deletions(-) diff --git a/Documentation/power/devices.txt b/Documentation/power/devices.txt index f987afe43e2..fba1e05c47c 100644 --- a/Documentation/power/devices.txt +++ b/Documentation/power/devices.txt @@ -118,96 +118,6 @@ will fail. There is currently no way to know what states a device or driver supports a priori. This will change in the future. -pm_message_t meaning - -pm_message_t has two fields. event ("major"), and flags. If driver -does not know event code, it aborts the request, returning error. Some -drivers may need to deal with special cases based on the actual type -of suspend operation being done at the system level. This is why -there are flags. - -Event codes are: - -ON -- no need to do anything except special cases like broken -HW. - -# NOTIFICATION -- pretty much same as ON? - -FREEZE -- stop DMA and interrupts, and be prepared to reinit HW from -scratch. That probably means stop accepting upstream requests, the -actual policy of what to do with them beeing specific to a given -driver. It's acceptable for a network driver to just drop packets -while a block driver is expected to block the queue so no request is -lost. (Use IDE as an example on how to do that). FREEZE requires no -power state change, and it's expected for drivers to be able to -quickly transition back to operating state. - -SUSPEND -- like FREEZE, but also put hardware into low-power state. If -there's need to distinguish several levels of sleep, additional flag -is probably best way to do that. - -Transitions are only from a resumed state to a suspended state, never -between 2 suspended states. (ON -> FREEZE or ON -> SUSPEND can happen, -FREEZE -> SUSPEND or SUSPEND -> FREEZE can not). - -All events are: - -[NOTE NOTE NOTE: If you are driver author, you should not care; you -should only look at event, and ignore flags.] - -#Prepare for suspend -- userland is still running but we are going to -#enter suspend state. This gives drivers chance to load firmware from -#disk and store it in memory, or do other activities taht require -#operating userland, ability to kmalloc GFP_KERNEL, etc... All of these -#are forbiden once the suspend dance is started.. event = ON, flags = -#PREPARE_TO_SUSPEND - -Apm standby -- prepare for APM event. Quiesce devices to make life -easier for APM BIOS. event = FREEZE, flags = APM_STANDBY - -Apm suspend -- same as APM_STANDBY, but it we should probably avoid -spinning down disks. event = FREEZE, flags = APM_SUSPEND - -System halt, reboot -- quiesce devices to make life easier for BIOS. event -= FREEZE, flags = SYSTEM_HALT or SYSTEM_REBOOT - -System shutdown -- at least disks need to be spun down, or data may be -lost. Quiesce devices, just to make life easier for BIOS. event = -FREEZE, flags = SYSTEM_SHUTDOWN - -Kexec -- turn off DMAs and put hardware into some state where new -kernel can take over. event = FREEZE, flags = KEXEC - -Powerdown at end of swsusp -- very similar to SYSTEM_SHUTDOWN, except wake -may need to be enabled on some devices. This actually has at least 3 -subtypes, system can reboot, enter S4 and enter S5 at the end of -swsusp. event = FREEZE, flags = SWSUSP and one of SYSTEM_REBOOT, -SYSTEM_SHUTDOWN, SYSTEM_S4 - -Suspend to ram -- put devices into low power state. event = SUSPEND, -flags = SUSPEND_TO_RAM - -Freeze for swsusp snapshot -- stop DMA and interrupts. No need to put -devices into low power mode, but you must be able to reinitialize -device from scratch in resume method. This has two flavors, its done -once on suspending kernel, once on resuming kernel. event = FREEZE, -flags = DURING_SUSPEND or DURING_RESUME - -Device detach requested from /sys -- deinitialize device; proably same as -SYSTEM_SHUTDOWN, I do not understand this one too much. probably event -= FREEZE, flags = DEV_DETACH. - -#These are not really events sent: -# -#System fully on -- device is working normally; this is probably never -#passed to suspend() method... event = ON, flags = 0 -# -#Ready after resume -- userland is now running, again. Time to free any -#memory you ate during prepare to suspend... event = ON, flags = -#READY_AFTER_RESUME -# - - pm_message_t meaning pm_message_t has two fields. event ("major"), and flags. If driver -- cgit v1.2.3 From fd869db6eb1ea0ffe251e53a113dbf259400f4f6 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Tue, 16 May 2006 17:03:25 -0700 Subject: [PATCH] Driver core: PM_DEBUG device suspend() messages become informative This makes the driver model PM suspend debug messages more useful, by (a) explaining what event is being sent, since not all suspend() requests mean the same thing; (b) reporting when a PM_EVENT_SUSPEND call is allowing the device to issue wakeup events. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/base/power/suspend.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c index 2a769cc6f5f..1a1fe43a305 100644 --- a/drivers/base/power/suspend.c +++ b/drivers/base/power/suspend.c @@ -29,6 +29,15 @@ * lists. This way, the ancestors will be accessed before their descendents. */ +static inline char *suspend_verb(u32 event) +{ + switch (event) { + case PM_EVENT_SUSPEND: return "suspend"; + case PM_EVENT_FREEZE: return "freeze"; + default: return "(unknown suspend event)"; + } +} + /** * suspend_device - Save state of one device. @@ -57,7 +66,13 @@ int suspend_device(struct device * dev, pm_message_t state) dev->power.prev_state = dev->power.power_state; if (dev->bus && dev->bus->suspend && !dev->power.power_state.event) { - dev_dbg(dev, "suspending\n"); + dev_dbg(dev, "%s%s\n", + suspend_verb(state.event), + ((state.event == PM_EVENT_SUSPEND) + && device_may_wakeup(dev)) + ? ", may wakeup" + : "" + ); error = dev->bus->suspend(dev, state); suspend_report_result(dev->bus->suspend, error); } -- cgit v1.2.3 From cad1e55d4d19a49c2b82b74562a6e4e555b05f38 Mon Sep 17 00:00:00 2001 From: Laura Garcia Date: Tue, 23 May 2006 23:22:38 +0200 Subject: [PATCH] firmware_class: s/semaphores/mutexes Hi, this patch converts semaphores to mutexes for Randy's firmware_class. Signed-off-by: Laura Garcia Liebana Signed-off-by: Greg Kroah-Hartman --- drivers/base/firmware_class.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 0c99ae6a340..5d6c011183f 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include "base.h" @@ -36,7 +36,7 @@ static int loading_timeout = 10; /* In seconds */ /* fw_lock could be moved to 'struct firmware_priv' but since it is just * guarding for corner cases a global lock should be OK */ -static DECLARE_MUTEX(fw_lock); +static DEFINE_MUTEX(fw_lock); struct firmware_priv { char fw_id[FIRMWARE_NAME_MAX]; @@ -142,9 +142,9 @@ firmware_loading_store(struct class_device *class_dev, switch (loading) { case 1: - down(&fw_lock); + mutex_lock(&fw_lock); if (!fw_priv->fw) { - up(&fw_lock); + mutex_unlock(&fw_lock); break; } vfree(fw_priv->fw->data); @@ -152,7 +152,7 @@ firmware_loading_store(struct class_device *class_dev, fw_priv->fw->size = 0; fw_priv->alloc_size = 0; set_bit(FW_STATUS_LOADING, &fw_priv->status); - up(&fw_lock); + mutex_unlock(&fw_lock); break; case 0: if (test_bit(FW_STATUS_LOADING, &fw_priv->status)) { @@ -185,7 +185,7 @@ firmware_data_read(struct kobject *kobj, struct firmware *fw; ssize_t ret_count = count; - down(&fw_lock); + mutex_lock(&fw_lock); fw = fw_priv->fw; if (!fw || test_bit(FW_STATUS_DONE, &fw_priv->status)) { ret_count = -ENODEV; @@ -200,7 +200,7 @@ firmware_data_read(struct kobject *kobj, memcpy(buffer, fw->data + offset, ret_count); out: - up(&fw_lock); + mutex_unlock(&fw_lock); return ret_count; } @@ -253,7 +253,7 @@ firmware_data_write(struct kobject *kobj, if (!capable(CAP_SYS_RAWIO)) return -EPERM; - down(&fw_lock); + mutex_lock(&fw_lock); fw = fw_priv->fw; if (!fw || test_bit(FW_STATUS_DONE, &fw_priv->status)) { retval = -ENODEV; @@ -268,7 +268,7 @@ firmware_data_write(struct kobject *kobj, fw->size = max_t(size_t, offset + count, fw->size); retval = count; out: - up(&fw_lock); + mutex_unlock(&fw_lock); return retval; } @@ -436,14 +436,14 @@ _request_firmware(const struct firmware **firmware_p, const char *name, } else wait_for_completion(&fw_priv->completion); - down(&fw_lock); + mutex_lock(&fw_lock); if (!fw_priv->fw->size || test_bit(FW_STATUS_ABORT, &fw_priv->status)) { retval = -ENOENT; release_firmware(fw_priv->fw); *firmware_p = NULL; } fw_priv->fw = NULL; - up(&fw_lock); + mutex_unlock(&fw_lock); class_device_unregister(class_dev); goto out; -- cgit v1.2.3 From aa49b9136e3d44cc264811d77eef4ded88456717 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 20 Jun 2006 13:59:20 -0700 Subject: [PATCH] Driver core: change make_class_name() to take kobjects This is needed for a future patch for the device code to create the proper symlinks for devices that are "class devices". Signed-off-by: Greg Kroah-Hartman --- drivers/base/base.h | 1 + drivers/base/class.c | 31 +++++++++++++++++-------------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/drivers/base/base.h b/drivers/base/base.h index 79115eff6e9..c3b8dc98b8a 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -42,4 +42,5 @@ struct class_device_attribute *to_class_dev_attr(struct attribute *_attr) return container_of(_attr, struct class_device_attribute, attr); } +extern char *make_class_name(const char *name, struct kobject *kobj); diff --git a/drivers/base/class.c b/drivers/base/class.c index 4b598be0e4b..41a8e0934e3 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -504,22 +504,21 @@ void class_device_initialize(struct class_device *class_dev) INIT_LIST_HEAD(&class_dev->node); } -static char *make_class_name(struct class_device *class_dev) +char *make_class_name(const char *name, struct kobject *kobj) { - char *name; + char *class_name; int size; - size = strlen(class_dev->class->name) + - strlen(kobject_name(&class_dev->kobj)) + 2; + size = strlen(name) + strlen(kobject_name(kobj)) + 2; - name = kmalloc(size, GFP_KERNEL); - if (!name) + class_name = kmalloc(size, GFP_KERNEL); + if (!class_name) return ERR_PTR(-ENOMEM); - strcpy(name, class_dev->class->name); - strcat(name, ":"); - strcat(name, kobject_name(&class_dev->kobj)); - return name; + strcpy(class_name, name); + strcat(class_name, ":"); + strcat(class_name, kobject_name(kobj)); + return class_name; } int class_device_add(struct class_device *class_dev) @@ -594,7 +593,8 @@ int class_device_add(struct class_device *class_dev) goto out5; if (class_dev->dev) { - class_name = make_class_name(class_dev); + class_name = make_class_name(class_dev->class->name, + &class_dev->kobj); error = sysfs_create_link(&class_dev->kobj, &class_dev->dev->kobj, "device"); if (error) @@ -731,7 +731,8 @@ void class_device_del(struct class_device *class_dev) } if (class_dev->dev) { - class_name = make_class_name(class_dev); + class_name = make_class_name(class_dev->class->name, + &class_dev->kobj); sysfs_remove_link(&class_dev->kobj, "device"); sysfs_remove_link(&class_dev->dev->kobj, class_name); } @@ -796,14 +797,16 @@ int class_device_rename(struct class_device *class_dev, char *new_name) new_name); if (class_dev->dev) - old_class_name = make_class_name(class_dev); + old_class_name = make_class_name(class_dev->class->name, + &class_dev->kobj); strlcpy(class_dev->class_id, new_name, KOBJ_NAME_LEN); error = kobject_rename(&class_dev->kobj, new_name); if (class_dev->dev) { - new_class_name = make_class_name(class_dev); + new_class_name = make_class_name(class_dev->class->name, + &class_dev->kobj); sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj, new_class_name); sysfs_remove_link(&class_dev->dev->kobj, old_class_name); -- cgit v1.2.3 From 23681e479129854305da1da32f7f1eaf635ef22c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 14 Jun 2006 12:14:34 -0700 Subject: [PATCH] Driver core: allow struct device to have a dev_t This is the first step in moving class_device to being replaced by struct device. It allows struct device to export a dev_t and makes it easy to dynamically create and destroy struct device as long as they are associated with a specific class. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/base/class.c | 1 + drivers/base/core.c | 162 ++++++++++++++++++++++++++++++++++++++++++++++++- include/linux/device.h | 14 +++++ 3 files changed, 176 insertions(+), 1 deletion(-) diff --git a/drivers/base/class.c b/drivers/base/class.c index 41a8e0934e3..50e841a33af 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -142,6 +142,7 @@ int class_register(struct class * cls) pr_debug("device class '%s': registering\n", cls->name); INIT_LIST_HEAD(&cls->children); + INIT_LIST_HEAD(&cls->devices); INIT_LIST_HEAD(&cls->interfaces); init_MUTEX(&cls->sem); error = kobject_set_name(&cls->subsys.kset.kobj, "%s", cls->name); diff --git a/drivers/base/core.c b/drivers/base/core.c index d5e15a03584..252cf403f89 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -15,6 +15,7 @@ #include #include #include +#include #include @@ -98,6 +99,8 @@ static int dev_uevent_filter(struct kset *kset, struct kobject *kobj) struct device *dev = to_dev(kobj); if (dev->bus) return 1; + if (dev->class) + return 1; } return 0; } @@ -106,7 +109,11 @@ static const char *dev_uevent_name(struct kset *kset, struct kobject *kobj) { struct device *dev = to_dev(kobj); - return dev->bus->name; + if (dev->bus) + return dev->bus->name; + if (dev->class) + return dev->class->name; + return NULL; } static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp, @@ -117,6 +124,16 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp, int length = 0; int retval = 0; + /* add the major/minor if present */ + if (MAJOR(dev->devt)) { + add_uevent_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "MAJOR=%u", MAJOR(dev->devt)); + add_uevent_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "MINOR=%u", MINOR(dev->devt)); + } + /* add bus name of physical device */ if (dev->bus) add_uevent_var(envp, num_envp, &i, @@ -161,6 +178,12 @@ static ssize_t store_uevent(struct device *dev, struct device_attribute *attr, return count; } +static ssize_t show_dev(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return print_dev_t(buf, dev->devt); +} + /* * devices_subsys - structure to be registered with kobject core. */ @@ -231,6 +254,7 @@ void device_initialize(struct device *dev) klist_init(&dev->klist_children, klist_children_get, klist_children_put); INIT_LIST_HEAD(&dev->dma_pools); + INIT_LIST_HEAD(&dev->node); init_MUTEX(&dev->sem); device_init_wakeup(dev, 0); } @@ -274,6 +298,31 @@ int device_add(struct device *dev) dev->uevent_attr.store = store_uevent; device_create_file(dev, &dev->uevent_attr); + if (MAJOR(dev->devt)) { + struct device_attribute *attr; + attr = kzalloc(sizeof(*attr), GFP_KERNEL); + if (!attr) { + error = -ENOMEM; + goto PMError; + } + attr->attr.name = "dev"; + attr->attr.mode = S_IRUGO; + if (dev->driver) + attr->attr.owner = dev->driver->owner; + attr->show = show_dev; + error = device_create_file(dev, attr); + if (error) { + kfree(attr); + goto attrError; + } + + dev->devt_attr = attr; + } + + if (dev->class) + sysfs_create_link(&dev->class->subsys.kset.kobj, &dev->kobj, + dev->bus_id); + if ((error = device_pm_add(dev))) goto PMError; if ((error = bus_add_device(dev))) @@ -292,6 +341,11 @@ int device_add(struct device *dev) BusError: device_pm_remove(dev); PMError: + if (dev->devt_attr) { + device_remove_file(dev, dev->devt_attr); + kfree(dev->devt_attr); + } + attrError: kobject_uevent(&dev->kobj, KOBJ_REMOVE); kobject_del(&dev->kobj); Error: @@ -366,6 +420,10 @@ void device_del(struct device * dev) if (parent) klist_del(&dev->knode_parent); + if (dev->devt_attr) + device_remove_file(dev, dev->devt_attr); + if (dev->class) + sysfs_remove_link(&dev->class->subsys.kset.kobj, dev->bus_id); device_remove_file(dev, &dev->uevent_attr); /* Notify the platform of the removal, in case they @@ -450,3 +508,105 @@ EXPORT_SYMBOL_GPL(put_device); EXPORT_SYMBOL_GPL(device_create_file); EXPORT_SYMBOL_GPL(device_remove_file); + + +static void device_create_release(struct device *dev) +{ + pr_debug("%s called for %s\n", __FUNCTION__, dev->bus_id); + kfree(dev); +} + +/** + * device_create - creates a device and registers it with sysfs + * @cs: pointer to the struct class that this device should be registered to. + * @parent: pointer to the parent struct device of this new device, if any. + * @dev: the dev_t for the char device to be added. + * @fmt: string for the class device's name + * + * This function can be used by char device classes. A struct + * device will be created in sysfs, registered to the specified + * class. + * A "dev" file will be created, showing the dev_t for the device, if + * the dev_t is not 0,0. + * If a pointer to a parent struct device is passed in, the newly + * created struct device will be a child of that device in sysfs. The + * pointer to the struct device will be returned from the call. Any + * further sysfs files that might be required can be created using this + * pointer. + * + * Note: the struct class passed to this function must have previously + * been created with a call to class_create(). + */ +struct device *device_create(struct class *class, struct device *parent, + dev_t devt, char *fmt, ...) +{ + va_list args; + struct device *dev = NULL; + int retval = -ENODEV; + + if (class == NULL || IS_ERR(class)) + goto error; + if (parent == NULL) { + printk(KERN_WARNING "%s does not work yet for NULL parents\n", __FUNCTION__); + goto error; + } + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) { + retval = -ENOMEM; + goto error; + } + + dev->devt = devt; + dev->class = class; + dev->parent = parent; + dev->release = device_create_release; + + va_start(args, fmt); + vsnprintf(dev->bus_id, BUS_ID_SIZE, fmt, args); + va_end(args); + retval = device_register(dev); + if (retval) + goto error; + + /* tie the class to the device */ + down(&class->sem); + list_add_tail(&dev->node, &class->devices); + up(&class->sem); + + return dev; + +error: + kfree(dev); + return ERR_PTR(retval); +} +EXPORT_SYMBOL_GPL(device_create); + +/** + * device_destroy - removes a device that was created with device_create() + * @class: the pointer to the struct class that this device was registered * with. + * @dev: the dev_t of the device that was previously registered. + * + * This call unregisters and cleans up a class device that was created with a + * call to class_device_create() + */ +void device_destroy(struct class *class, dev_t devt) +{ + struct device *dev = NULL; + struct device *dev_tmp; + + down(&class->sem); + list_for_each_entry(dev_tmp, &class->devices, node) { + if (dev_tmp->devt == devt) { + dev = dev_tmp; + break; + } + } + up(&class->sem); + + if (dev) { + list_del_init(&dev->node); + device_unregister(dev); + } +} +EXPORT_SYMBOL_GPL(device_destroy); diff --git a/include/linux/device.h b/include/linux/device.h index ade10dd6b77..b473f427891 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -142,6 +142,7 @@ struct class { struct subsystem subsys; struct list_head children; + struct list_head devices; struct list_head interfaces; struct semaphore sem; /* locks both the children and interfaces lists */ @@ -305,6 +306,7 @@ struct device { struct kobject kobj; char bus_id[BUS_ID_SIZE]; /* position on parent bus */ struct device_attribute uevent_attr; + struct device_attribute *devt_attr; struct semaphore sem; /* semaphore to synchronize calls to * its driver. @@ -332,6 +334,11 @@ struct device { struct dma_coherent_mem *dma_mem; /* internal for coherent mem override */ + /* class_device migration path */ + struct list_head node; + struct class *class; /* optional*/ + dev_t devt; /* dev_t, creates the sysfs "dev" */ + void (*release)(struct device * dev); }; @@ -373,6 +380,13 @@ extern int device_attach(struct device * dev); extern void driver_attach(struct device_driver * drv); extern void device_reprobe(struct device *dev); +/* + * Easy functions for dynamically creating devices on the fly + */ +extern struct device *device_create(struct class *cls, struct device *parent, + dev_t devt, char *fmt, ...) + __attribute__((format(printf,4,5))); +extern void device_destroy(struct class *cls, dev_t devt); /* * Platform "fixup" functions - allow the platform to have their say -- cgit v1.2.3 From b9d9c82b4d081feb464f62dfc786c8621d09ecd2 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Thu, 15 Jun 2006 15:31:56 +0200 Subject: [PATCH] Driver core: add generic "subsystem" link to all devices Like the SUBSYTEM= key we find in the environment of the uevent, this creates a generic "subsystem" link in sysfs for every device. Userspace usually doesn't care at all if its a "class" or a "bus" device. This provides an unified way to determine the subsytem of a device, regardless of the way the driver core has created it. Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- block/genhd.c | 7 ++----- drivers/base/bus.c | 2 ++ drivers/base/class.c | 2 ++ drivers/base/core.c | 9 +++++++-- fs/partitions/check.c | 4 ++++ 5 files changed, 17 insertions(+), 7 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index 5a8d3bf02f1..8d7339511e5 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -17,8 +17,7 @@ #include #include -static struct subsystem block_subsys; - +struct subsystem block_subsys; static DEFINE_MUTEX(block_subsys_lock); /* @@ -511,9 +510,7 @@ static struct kset_uevent_ops block_uevent_ops = { .uevent = block_uevent, }; -/* declare block_subsys. */ -static decl_subsys(block, &ktype_block, &block_uevent_ops); - +decl_subsys(block, &ktype_block, &block_uevent_ops); /* * aggregate disk stat collector. Uses the same stats that the sysfs diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 64ba9011d1a..050d86d0b87 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -374,6 +374,7 @@ int bus_add_device(struct device * dev) error = device_add_attrs(bus, dev); if (!error) { sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id); + sysfs_create_link(&dev->kobj, &dev->bus->subsys.kset.kobj, "subsystem"); sysfs_create_link(&dev->kobj, &dev->bus->subsys.kset.kobj, "bus"); } } @@ -408,6 +409,7 @@ void bus_attach_device(struct device * dev) void bus_remove_device(struct device * dev) { if (dev->bus) { + sysfs_remove_link(&dev->kobj, "subsystem"); sysfs_remove_link(&dev->kobj, "bus"); sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id); device_remove_attrs(dev->bus, dev); diff --git a/drivers/base/class.c b/drivers/base/class.c index 50e841a33af..9aa12746026 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -561,6 +561,7 @@ int class_device_add(struct class_device *class_dev) goto out2; /* add the needed attributes to this device */ + sysfs_create_link(&class_dev->kobj, &parent_class->subsys.kset.kobj, "subsystem"); class_dev->uevent_attr.attr.name = "uevent"; class_dev->uevent_attr.attr.mode = S_IWUSR; class_dev->uevent_attr.attr.owner = parent_class->owner; @@ -737,6 +738,7 @@ void class_device_del(struct class_device *class_dev) sysfs_remove_link(&class_dev->kobj, "device"); sysfs_remove_link(&class_dev->dev->kobj, class_name); } + sysfs_remove_link(&class_dev->kobj, "subsystem"); class_device_remove_file(class_dev, &class_dev->uevent_attr); if (class_dev->devt_attr) class_device_remove_file(class_dev, class_dev->devt_attr); diff --git a/drivers/base/core.c b/drivers/base/core.c index 252cf403f89..cc8bb97427d 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -319,9 +319,12 @@ int device_add(struct device *dev) dev->devt_attr = attr; } - if (dev->class) + if (dev->class) { + sysfs_create_link(&dev->kobj, &dev->class->subsys.kset.kobj, + "subsystem"); sysfs_create_link(&dev->class->subsys.kset.kobj, &dev->kobj, dev->bus_id); + } if ((error = device_pm_add(dev))) goto PMError; @@ -422,8 +425,10 @@ void device_del(struct device * dev) klist_del(&dev->knode_parent); if (dev->devt_attr) device_remove_file(dev, dev->devt_attr); - if (dev->class) + if (dev->class) { + sysfs_remove_link(&dev->kobj, "subsystem"); sysfs_remove_link(&dev->class->subsys.kset.kobj, dev->bus_id); + } device_remove_file(dev, &dev->uevent_attr); /* Notify the platform of the removal, in case they diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 7ef1f094de9..8851b81e7c5 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -329,6 +329,7 @@ void delete_partition(struct gendisk *disk, int part) p->ios[0] = p->ios[1] = 0; p->sectors[0] = p->sectors[1] = 0; devfs_remove("%s/part%d", disk->devfs_name, part); + sysfs_remove_link(&p->kobj, "subsystem"); if (p->holder_dir) kobject_unregister(p->holder_dir); kobject_uevent(&p->kobj, KOBJ_REMOVE); @@ -363,6 +364,7 @@ void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len) kobject_add(&p->kobj); if (!disk->part_uevent_suppress) kobject_uevent(&p->kobj, KOBJ_ADD); + sysfs_create_link(&p->kobj, &block_subsys.kset.kobj, "subsystem"); partition_sysfs_add_subdir(p); disk->part[part-1] = p; } @@ -398,6 +400,7 @@ static void disk_sysfs_symlinks(struct gendisk *disk) kfree(disk_name); } } + sysfs_create_link(&disk->kobj, &block_subsys.kset.kobj, "subsystem"); } /* Not exported, helper to add_disk(). */ @@ -548,5 +551,6 @@ void del_gendisk(struct gendisk *disk) put_device(disk->driverfs_dev); disk->driverfs_dev = NULL; } + sysfs_remove_link(&disk->kobj, "subsystem"); kobject_del(&disk->kobj); } -- cgit v1.2.3 From e9a7d305faec364ba973d6c22c9b1e802ef79204 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 20 Jun 2006 13:59:20 -0700 Subject: [PATCH] Driver core: add proper symlinks for devices We need to create the "compatible" symlinks that class_devices used to create when they were in the class directories so that userspace does not know anything changed at all. Yeah, we have a lot of symlinks now, but we should be able to get rid of them in a year or two... (wishful thinking...) Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/base/core.c b/drivers/base/core.c index cc8bb97427d..a979bc3f49a 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -273,6 +273,7 @@ void device_initialize(struct device *dev) int device_add(struct device *dev) { struct device *parent = NULL; + char *class_name = NULL; int error = -EINVAL; dev = get_device(dev); @@ -324,6 +325,10 @@ int device_add(struct device *dev) "subsystem"); sysfs_create_link(&dev->class->subsys.kset.kobj, &dev->kobj, dev->bus_id); + + sysfs_create_link(&dev->kobj, &dev->parent->kobj, "device"); + class_name = make_class_name(dev->class->name, &dev->kobj); + sysfs_create_link(&dev->parent->kobj, &dev->kobj, class_name); } if ((error = device_pm_add(dev))) @@ -339,6 +344,7 @@ int device_add(struct device *dev) if (platform_notify) platform_notify(dev); Done: + kfree(class_name); put_device(dev); return error; BusError: @@ -420,6 +426,7 @@ void put_device(struct device * dev) void device_del(struct device * dev) { struct device * parent = dev->parent; + char *class_name = NULL; if (parent) klist_del(&dev->knode_parent); @@ -428,6 +435,10 @@ void device_del(struct device * dev) if (dev->class) { sysfs_remove_link(&dev->kobj, "subsystem"); sysfs_remove_link(&dev->class->subsys.kset.kobj, dev->bus_id); + class_name = make_class_name(dev->class->name, &dev->kobj); + sysfs_remove_link(&dev->kobj, "device"); + sysfs_remove_link(&dev->parent->kobj, class_name); + kfree(class_name); } device_remove_file(dev, &dev->uevent_attr); -- cgit v1.2.3 From 3e95637a48820ff8bedb33e6439def96ccff1de5 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 16 Jun 2006 17:10:48 -0400 Subject: [PATCH] Driver Core: Make dev_info and friends print the bus name if there is no driver This patch (as721) makes dev_info and related macros print the device's bus name if the device doesn't have a driver, instead of printing just a blank. If the device isn't on a bus either... well, then it does leave a blank space. But it will be easier for someone else to change if they want. Cc: Matthew Wilcox Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 16 ++++++++++++++++ include/linux/device.h | 3 ++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index a979bc3f49a..d0f84ff7877 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -29,6 +29,22 @@ int (*platform_notify_remove)(struct device * dev) = NULL; * sysfs bindings for devices. */ +/** + * dev_driver_string - Return a device's driver name, if at all possible + * @dev: struct device to get the name of + * + * Will return the device's driver's name if it is bound to a device. If + * the device is not bound to a device, it will return the name of the bus + * it is attached to. If it is not attached to a bus either, an empty + * string will be returned. + */ +const char *dev_driver_string(struct device *dev) +{ + return dev->driver ? dev->driver->name : + (dev->bus ? dev->bus->name : ""); +} +EXPORT_SYMBOL_GPL(dev_driver_string); + #define to_dev(obj) container_of(obj, struct device, kobj) #define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr) diff --git a/include/linux/device.h b/include/linux/device.h index b473f427891..1e5f30da98b 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -416,8 +416,9 @@ extern int firmware_register(struct subsystem *); extern void firmware_unregister(struct subsystem *); /* debugging and troubleshooting/diagnostic helpers. */ +extern const char *dev_driver_string(struct device *dev); #define dev_printk(level, dev, format, arg...) \ - printk(level "%s %s: " format , (dev)->driver ? (dev)->driver->name : "" , (dev)->bus_id , ## arg) + printk(level "%s %s: " format , dev_driver_string(dev) , (dev)->bus_id , ## arg) #ifdef DEBUG #define dev_dbg(dev, format, arg...) \ -- cgit v1.2.3 From a5117ba7da37deb09df5eb802dace229b3fb1e9f Mon Sep 17 00:00:00 2001 From: Rene Herman Date: Tue, 6 Jun 2006 23:54:02 +0200 Subject: [PATCH] Driver model: add ISA bus During the recent "isa drivers using platform devices" discussion it was pointed out that (ALSA) ISA drivers ran into the problem of not having the option to fail driver load (device registration rather) upon not finding their hardware due to a probe() error not being passed up through the driver model. In the course of that, I suggested a seperate ISA bus might be best; Russell King agreed and suggested this bus could use the .match() method for the actual device discovery. The attached does this. For this old non (generically) discoverable ISA hardware only the driver itself can do discovery so as a difference with the platform_bus, this isa_bus also distributes match() up to the driver. As another difference: these devices only exist in the driver model due to the driver creating them because it might want to drive them, meaning that all device creation has been made internal as well. The usage model this provides is nice, and has been acked from the ALSA side by Takashi Iwai and Jaroslav Kysela. The ALSA driver module_init's now (for oldisa-only drivers) become: static int __init alsa_card_foo_init(void) { return isa_register_driver(&snd_foo_isa_driver, SNDRV_CARDS); } static void __exit alsa_card_foo_exit(void) { isa_unregister_driver(&snd_foo_isa_driver); } Quite like the other bus models therefore. This removes a lot of duplicated init code from the ALSA ISA drivers. The passed in isa_driver struct is the regular driver struct embedding a struct device_driver, the normal probe/remove/shutdown/suspend/resume callbacks, and as indicated that .match callback. The "SNDRV_CARDS" you see being passed in is a "unsigned int ndev" parameter, indicating how many devices to create and call our methods with. The platform_driver callbacks are called with a platform_device param; the isa_driver callbacks are being called with a "struct device *dev, unsigned int id" pair directly -- with the device creation completely internal to the bus it's much cleaner to not leak isa_dev's by passing them in at all. The id is the only thing we ever want other then the struct device * anyways, and it makes for nicer code in the callbacks as well. With this additional .match() callback ISA drivers have all options. If ALSA would want to keep the old non-load behaviour, it could stick all of the old .probe in .match, which would only keep them registered after everything was found to be present and accounted for. If it wanted the behaviour of always loading as it inadvertently did for a bit after the changeover to platform devices, it could just not provide a .match() and do everything in .probe() as before. If it, as Takashi Iwai already suggested earlier as a way of following the model from saner buses more closely, wants to load when a later bind could conceivably succeed, it could use .match() for the prerequisites (such as checking the user wants the card enabled and that port/irq/dma values have been passed in) and .probe() for everything else. This is the nicest model. To the code... This exports only two functions; isa_{,un}register_driver(). isa_register_driver() register's the struct device_driver, and then loops over the passed in ndev creating devices and registering them. This causes the bus match method to be called for them, which is: int isa_bus_match(struct device *dev, struct device_driver *driver) { struct isa_driver *isa_driver = to_isa_driver(driver); if (dev->platform_data == isa_driver) { if (!isa_driver->match || isa_driver->match(dev, to_isa_dev(dev)->id)) return 1; dev->platform_data = NULL; } return 0; } The first thing this does is check if this device is in fact one of this driver's devices by seeing if the device's platform_data pointer is set to this driver. Platform devices compare strings, but we don't need to do that with everything being internal, so isa_register_driver() abuses dev->platform_data as a isa_driver pointer which we can then check here. I believe platform_data is available for this, but if rather not, moving the isa_driver pointer to the private struct isa_dev is ofcourse fine as well. Then, if the the driver did not provide a .match, it matches. If it did, the driver match() method is called to determine a match. If it did _not_ match, dev->platform_data is reset to indicate this to isa_register_driver which can then unregister the device again. If during all this, there's any error, or no devices matched at all everything is backed out again and the error, or -ENODEV, is returned. isa_unregister_driver() just unregisters the matched devices and the driver itself. More global points/questions... - I'm introducing include/linux/isa.h. It was available but is ofcourse a somewhat generic name. Moving more isa stuff over to it in time is ofcourse fine, so can I have it please? :) - I'm using device_initcall() and added the isa.o (dependent on CONFIG_ISA) after the base driver model things in the Makefile. Will this do, or I really need to stick it in drivers/base/init.c, inside #ifdef CONFIG_ISA? It's working fine. Lastly -- I also looked, a bit, into integrating with PnP. "Old ISA" could be another pnp_protocol, but this does not seem to be a good match, largely due to the same reason platform_devices weren't -- the devices do not have a life of their own outside the driver, meaning the pnp_protocol {get,set}_resources callbacks would need to callback into driver -- which again means you first need to _have_ that driver. Even if there's clean way around that, you only end up inventing fake but valid-form PnP IDs and generally catering to the PnP layer without any practical advantages over this very simple isa_bus. The thing I also suggested earlier about the user echoing values into /sys to set up the hardware from userspace first is... well, cute, but a horrible idea from a user standpoint. Comments ofcourse appreciated. Hope it's okay. As said, the usage model is nice at least. Signed-off-by: Rene Herman --- drivers/base/Makefile | 1 + drivers/base/isa.c | 180 ++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/isa.h | 28 ++++++++ 3 files changed, 209 insertions(+) create mode 100644 drivers/base/isa.c create mode 100644 include/linux/isa.h diff --git a/drivers/base/Makefile b/drivers/base/Makefile index 659cde6c2fb..b539e5e75b5 100644 --- a/drivers/base/Makefile +++ b/drivers/base/Makefile @@ -5,6 +5,7 @@ obj-y := core.o sys.o bus.o dd.o \ cpu.o firmware.o init.o map.o dmapool.o \ attribute_container.o transport_class.o obj-y += power/ +obj-$(CONFIG_ISA) += isa.o obj-$(CONFIG_FW_LOADER) += firmware_class.o obj-$(CONFIG_NUMA) += node.o obj-$(CONFIG_MEMORY_HOTPLUG) += memory.o diff --git a/drivers/base/isa.c b/drivers/base/isa.c new file mode 100644 index 00000000000..d2222397a40 --- /dev/null +++ b/drivers/base/isa.c @@ -0,0 +1,180 @@ +/* + * ISA bus. + */ + +#include +#include +#include +#include +#include +#include + +static struct device isa_bus = { + .bus_id = "isa" +}; + +struct isa_dev { + struct device dev; + struct device *next; + unsigned int id; +}; + +#define to_isa_dev(x) container_of((x), struct isa_dev, dev) + +static int isa_bus_match(struct device *dev, struct device_driver *driver) +{ + struct isa_driver *isa_driver = to_isa_driver(driver); + + if (dev->platform_data == isa_driver) { + if (!isa_driver->match || + isa_driver->match(dev, to_isa_dev(dev)->id)) + return 1; + dev->platform_data = NULL; + } + return 0; +} + +static int isa_bus_probe(struct device *dev) +{ + struct isa_driver *isa_driver = dev->platform_data; + + if (isa_driver->probe) + return isa_driver->probe(dev, to_isa_dev(dev)->id); + + return 0; +} + +static int isa_bus_remove(struct device *dev) +{ + struct isa_driver *isa_driver = dev->platform_data; + + if (isa_driver->remove) + return isa_driver->remove(dev, to_isa_dev(dev)->id); + + return 0; +} + +static void isa_bus_shutdown(struct device *dev) +{ + struct isa_driver *isa_driver = dev->platform_data; + + if (isa_driver->shutdown) + isa_driver->shutdown(dev, to_isa_dev(dev)->id); +} + +static int isa_bus_suspend(struct device *dev, pm_message_t state) +{ + struct isa_driver *isa_driver = dev->platform_data; + + if (isa_driver->suspend) + return isa_driver->suspend(dev, to_isa_dev(dev)->id, state); + + return 0; +} + +static int isa_bus_resume(struct device *dev) +{ + struct isa_driver *isa_driver = dev->platform_data; + + if (isa_driver->resume) + return isa_driver->resume(dev, to_isa_dev(dev)->id); + + return 0; +} + +static struct bus_type isa_bus_type = { + .name = "isa", + .match = isa_bus_match, + .probe = isa_bus_probe, + .remove = isa_bus_remove, + .shutdown = isa_bus_shutdown, + .suspend = isa_bus_suspend, + .resume = isa_bus_resume +}; + +static void isa_dev_release(struct device *dev) +{ + kfree(to_isa_dev(dev)); +} + +void isa_unregister_driver(struct isa_driver *isa_driver) +{ + struct device *dev = isa_driver->devices; + + while (dev) { + struct device *tmp = to_isa_dev(dev)->next; + device_unregister(dev); + dev = tmp; + } + driver_unregister(&isa_driver->driver); +} +EXPORT_SYMBOL_GPL(isa_unregister_driver); + +int isa_register_driver(struct isa_driver *isa_driver, unsigned int ndev) +{ + int error; + unsigned int id; + + isa_driver->driver.bus = &isa_bus_type; + isa_driver->devices = NULL; + + error = driver_register(&isa_driver->driver); + if (error) + return error; + + for (id = 0; id < ndev; id++) { + struct isa_dev *isa_dev; + + isa_dev = kzalloc(sizeof *isa_dev, GFP_KERNEL); + if (!isa_dev) { + error = -ENOMEM; + break; + } + + isa_dev->dev.parent = &isa_bus; + isa_dev->dev.bus = &isa_bus_type; + + snprintf(isa_dev->dev.bus_id, BUS_ID_SIZE, "%s.%u", + isa_driver->driver.name, id); + + isa_dev->dev.platform_data = isa_driver; + isa_dev->dev.release = isa_dev_release; + isa_dev->id = id; + + error = device_register(&isa_dev->dev); + if (error) { + put_device(&isa_dev->dev); + break; + } + + if (isa_dev->dev.platform_data) { + isa_dev->next = isa_driver->devices; + isa_driver->devices = &isa_dev->dev; + } else + device_unregister(&isa_dev->dev); + } + + if (!error && !isa_driver->devices) + error = -ENODEV; + + if (error) + isa_unregister_driver(isa_driver); + + return error; +} +EXPORT_SYMBOL_GPL(isa_register_driver); + +static int __init isa_bus_init(void) +{ + int error; + + error = bus_register(&isa_bus_type); + if (!error) { + error = device_register(&isa_bus); + if (error) + bus_unregister(&isa_bus_type); + } + return error; +} + +device_initcall(isa_bus_init); diff --git a/include/linux/isa.h b/include/linux/isa.h new file mode 100644 index 00000000000..1b855335cb1 --- /dev/null +++ b/include/linux/isa.h @@ -0,0 +1,28 @@ +/* + * ISA bus. + */ + +#ifndef __LINUX_ISA_H +#define __LINUX_ISA_H + +#include +#include + +struct isa_driver { + int (*match)(struct device *, unsigned int); + int (*probe)(struct device *, unsigned int); + int (*remove)(struct device *, unsigned int); + void (*shutdown)(struct device *, unsigned int); + int (*suspend)(struct device *, unsigned int, pm_message_t); + int (*resume)(struct device *, unsigned int); + + struct device_driver driver; + struct device *devices; +}; + +#define to_isa_driver(x) container_of((x), struct isa_driver, driver) + +int isa_register_driver(struct isa_driver *, unsigned int); +void isa_unregister_driver(struct isa_driver *); + +#endif /* __LINUX_ISA_H */ -- cgit v1.2.3 From 120b286d3c94a4e59fdb8069d42e8d49ea468ffd Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Tue, 6 Jun 2006 10:23:34 -0600 Subject: [IA64] add vmlinuz target This is a trivial stand-alone patch out of the Xen/ia64 patches. Add a vmlinuz build target to be more compatible with x86-ish targets. Signed-off-by: Alex Williamson Signed-off-by: Tony Luck --- arch/ia64/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile index 80ea7506fa1..21033ed8330 100644 --- a/arch/ia64/Makefile +++ b/arch/ia64/Makefile @@ -71,6 +71,8 @@ all: compressed unwcheck compressed: vmlinux.gz +vmlinuz: vmlinux.gz + vmlinux.gz: vmlinux $(Q)$(MAKE) $(build)=$(boot) $@ -- cgit v1.2.3 From 5eb1d63f5fc8455269c2756223b3cf3779fd2f7a Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Tue, 6 Jun 2006 10:36:27 -0600 Subject: [IA64] sanity check reserved region usage One more trivial, stand-alone patch from the Xen/ia64 review. Sanity check usage of the reserved region numbers. Signed-off-by: Alex Williamson Signed-off-by: Tony Luck --- arch/ia64/kernel/setup.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index e4dfda1eb7d..6dba2d63f24 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -260,6 +260,7 @@ reserve_memory (void) n++; num_rsvd_regions = n; + BUG_ON(IA64_MAX_RSVD_REGIONS + 1 < n); sort_regions(rsvd_region, num_rsvd_regions); } -- cgit v1.2.3 From a1d7057727bc9e20a0a417812f538fe6b8a02c03 Mon Sep 17 00:00:00 2001 From: Jack Steiner Date: Wed, 31 May 2006 08:58:08 -0500 Subject: [IA64-SGI] SN topology fix for large systems There is an SN bug in sn_hwperf.c that affects systems with 1024n or 1024p. The bug manifests itself 2 ways: IO interrupts are not always targeted to the nearest node, and 2) the "cat /proc/sgi_sn/sn_topology" commands fails with "cannot allocate memory". The code is using the wrong macros for validating node numbers. Signed-off-by: Jack Steiner Signed-off-by: Tony Luck --- arch/ia64/sn/kernel/sn2/sn_hwperf.c | 50 ++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c index 739c948dc50..9a8a29339d2 100644 --- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c +++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c @@ -51,6 +51,8 @@ static nasid_t sn_hwperf_master_nasid = INVALID_NASID; static int sn_hwperf_init(void); static DECLARE_MUTEX(sn_hwperf_init_mutex); +#define cnode_possible(n) ((n) < num_cnodes) + static int sn_hwperf_enum_objects(int *nobj, struct sn_hwperf_object_info **ret) { int e; @@ -127,14 +129,14 @@ static int sn_hwperf_geoid_to_cnode(char *location) } } - return node_possible(cnode) ? cnode : -1; + return cnode_possible(cnode) ? cnode : -1; } static int sn_hwperf_obj_to_cnode(struct sn_hwperf_object_info * obj) { if (!SN_HWPERF_IS_NODE(obj) && !SN_HWPERF_IS_IONODE(obj)) BUG(); - if (!obj->sn_hwp_this_part) + if (SN_HWPERF_FOREIGN(obj)) return -1; return sn_hwperf_geoid_to_cnode(obj->location); } @@ -199,12 +201,12 @@ static void print_pci_topology(struct seq_file *s) static inline int sn_hwperf_has_cpus(cnodeid_t node) { - return node_online(node) && nr_cpus_node(node); + return node < MAX_NUMNODES && node_online(node) && nr_cpus_node(node); } static inline int sn_hwperf_has_mem(cnodeid_t node) { - return node_online(node) && NODE_DATA(node)->node_present_pages; + return node < MAX_NUMNODES && node_online(node) && NODE_DATA(node)->node_present_pages; } static struct sn_hwperf_object_info * @@ -237,7 +239,7 @@ static int sn_hwperf_get_nearest_node_objdata(struct sn_hwperf_object_info *objb int found_mem = 0; int found_cpu = 0; - if (!node_possible(node)) + if (!cnode_possible(node)) return -EINVAL; if (sn_hwperf_has_cpus(node)) { @@ -442,7 +444,7 @@ static int sn_topology_show(struct seq_file *s, void *d) seq_printf(s, "%s %d %s %s asic %s", slabname, ordinal, obj->location, obj->sn_hwp_this_part ? "local" : "shared", obj->name); - if (!SN_HWPERF_IS_NODE(obj) && !SN_HWPERF_IS_IONODE(obj)) + if (ordinal < 0 || (!SN_HWPERF_IS_NODE(obj) && !SN_HWPERF_IS_IONODE(obj))) seq_putc(s, '\n'); else { cnodeid_t near_mem = -1; @@ -468,22 +470,24 @@ static int sn_topology_show(struct seq_file *s, void *d) /* * CPUs on this node, if any */ - cpumask = node_to_cpumask(ordinal); - for_each_online_cpu(i) { - if (cpu_isset(i, cpumask)) { - slice = 'a' + cpuid_to_slice(i); - c = cpu_data(i); - seq_printf(s, "cpu %d %s%c local" - " freq %luMHz, arch ia64", - i, obj->location, slice, - c->proc_freq / 1000000); - for_each_online_cpu(j) { - seq_printf(s, j ? ":%d" : ", dist %d", - node_distance( - cpu_to_node(i), - cpu_to_node(j))); + if (!SN_HWPERF_IS_IONODE(obj)) { + cpumask = node_to_cpumask(ordinal); + for_each_online_cpu(i) { + if (cpu_isset(i, cpumask)) { + slice = 'a' + cpuid_to_slice(i); + c = cpu_data(i); + seq_printf(s, "cpu %d %s%c local" + " freq %luMHz, arch ia64", + i, obj->location, slice, + c->proc_freq / 1000000); + for_each_online_cpu(j) { + seq_printf(s, j ? ":%d" : ", dist %d", + node_distance( + cpu_to_node(i), + cpu_to_node(j))); + } + seq_putc(s, '\n'); } - seq_putc(s, '\n'); } } } @@ -523,7 +527,7 @@ static int sn_topology_show(struct seq_file *s, void *d) if (obj->sn_hwp_this_part && p->sn_hwp_this_part) /* both ends local to this partition */ seq_puts(s, " local"); - else if (!obj->sn_hwp_this_part && !p->sn_hwp_this_part) + else if (SN_HWPERF_FOREIGN(p)) /* both ends of the link in foreign partiton */ seq_puts(s, " foreign"); else @@ -776,7 +780,7 @@ sn_hwperf_ioctl(struct inode *in, struct file *fp, u32 op, u64 arg) case SN_HWPERF_GET_NODE_NASID: if (a.sz != sizeof(u64) || - (node = a.arg) < 0 || !node_possible(node)) { + (node = a.arg) < 0 || !cnode_possible(node)) { r = -EINVAL; goto error; } -- cgit v1.2.3 From 491b07c98f2ac75f1a4370af76ae2403a4c579f5 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Wed, 21 Jun 2006 13:15:48 -0700 Subject: [PATCH] redirect speedstep-centrino maintainer mail to cpufreq list I haven't really maintained this driver for a while, and I'm not keeping up with the latest in Intel power management. I get a steady stream of mail which I don't really do anything useful with; the cpufreq list seems like a better destination, unless someone wants to get the mail directly. Also clean up a couple of ancient comments which don't really apply anymore (as far as I know, nobody has ever damaged a CPU with this driver). Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Dave Jones --- arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c index ce54ff12c15..f1a82c5de1b 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c @@ -2,19 +2,15 @@ * cpufreq driver for Enhanced SpeedStep, as found in Intel's Pentium * M (part of the Centrino chipset). * + * Since the original Pentium M, most new Intel CPUs support Enhanced + * SpeedStep. + * * Despite the "SpeedStep" in the name, this is almost entirely unlike * traditional SpeedStep. * * Modelled on speedstep.c * * Copyright (C) 2003 Jeremy Fitzhardinge - * - * WARNING WARNING WARNING - * - * This driver manipulates the PERF_CTL MSR, which is only somewhat - * documented. While it seems to work on my laptop, it has not been - * tested anywhere else, and it may not work for you, do strange - * things or simply crash. */ #include @@ -36,7 +32,7 @@ #include #define PFX "speedstep-centrino: " -#define MAINTAINER "Jeremy Fitzhardinge " +#define MAINTAINER "cpufreq@lists.linux.org.uk" #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "speedstep-centrino", msg) -- cgit v1.2.3 From 9ed059e1551bf36092215b965838502ac21f42e4 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 20 Jun 2006 22:32:56 -0700 Subject: [CPUFREQ] Fix powernow-k8 SMP kernel on UP hardware bug. Fix powernow-k8 doesn't load bug. Reference: https://launchpad.net/distros/ubuntu/+source/linux-source-2.6.15/+bug/35145 Signed-off-by: Ben Collins Signed-off-by: Dave Jones --- arch/i386/kernel/cpu/cpufreq/powernow-k8.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c index 756d0a333ed..2d649167255 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c @@ -1163,7 +1163,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol) * Use the PSB BIOS structure. This is only availabe on * an UP version, and is deprecated by AMD. */ - if ((num_online_cpus() != 1) || (num_possible_cpus() != 1)) { + if (num_online_cpus() != 1) { printk(KERN_ERR PFX "MP systems not supported by PSB BIOS structure\n"); kfree(data); return -ENODEV; -- cgit v1.2.3 From 65884734902c8f0b4d83293985678ab83b24ef72 Mon Sep 17 00:00:00 2001 From: David Mosberger-Tang Date: Wed, 24 May 2006 22:16:03 -0600 Subject: [IA64] make efi_stub.S fit in 80 cols Just a trivial cleanup patch Signed-off-by: Tony Luck --- arch/ia64/kernel/efi_stub.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/ia64/kernel/efi_stub.S b/arch/ia64/kernel/efi_stub.S index 5a7fe70212a..a56e161d751 100644 --- a/arch/ia64/kernel/efi_stub.S +++ b/arch/ia64/kernel/efi_stub.S @@ -61,7 +61,7 @@ GLOBAL_ENTRY(efi_call_phys) or loc3=loc3,r17 mov b6=r2 ;; - andcm r16=loc3,r16 // get psr with IT, DT, and RT bits cleared + andcm r16=loc3,r16 // get psr with IT, DT, and RT bits cleared br.call.sptk.many rp=ia64_switch_mode_phys .ret0: mov out4=in5 mov out0=in1 -- cgit v1.2.3 From ea95972f18481089e73368f9e62f6d70087bf4de Mon Sep 17 00:00:00 2001 From: Russ Anderson Date: Wed, 10 May 2006 11:09:01 -0500 Subject: [IA64-SGI] Remove SN SAL error handling feature bit that is no longer needed Due to improvements in linux & SAL MCA handling, the SAL_ERR_FEAT_MCA_SLV_TO_OS_INIT_SLV error handling features bit is no longer needed. Signed-off-by: Russ Anderson (rja@sgi.com) Signed-off-by: Tony Luck --- include/asm-ia64/sn/sn_sal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h index 8c865e43f60..cd490b20d59 100644 --- a/include/asm-ia64/sn/sn_sal.h +++ b/include/asm-ia64/sn/sn_sal.h @@ -345,7 +345,7 @@ ia64_sn_plat_set_error_handling_features(void) ret_stuff.v1 = 0; ret_stuff.v2 = 0; SAL_CALL_REENTRANT(ret_stuff, SN_SAL_SET_ERROR_HANDLING_FEATURES, - (SAL_ERR_FEAT_MCA_SLV_TO_OS_INIT_SLV | SAL_ERR_FEAT_LOG_SBES), + SAL_ERR_FEAT_LOG_SBES, 0, 0, 0, 0, 0, 0); return ret_stuff.status; -- cgit v1.2.3 From b7bb575c3fa3694811a072109f4e9c2f4705d8f5 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Fri, 28 Apr 2006 11:50:43 +0900 Subject: [IA64] Make PCI Express support selectable When I tried to use PCI Express Hotplug driver on my ia64 box, I noticed that "PCI Express support" is not even selectable on ia64. This patch makes PCI Express support selectable. Signed-off-by: Kenji Kaneshige Signed-off-by: Tony Luck --- arch/ia64/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 0f3076a820c..cd2051f5c9c 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -449,6 +449,8 @@ config PCI_DOMAINS bool default PCI +source "drivers/pci/pcie/Kconfig" + source "drivers/pci/Kconfig" source "drivers/pci/hotplug/Kconfig" -- cgit v1.2.3 From d270acbc24f0ce451c773c214ac0e92e95396b2f Mon Sep 17 00:00:00 2001 From: Keith Owens Date: Fri, 7 Apr 2006 18:08:11 +1000 Subject: [IA64] Sanitize assembler code for ia64_sal_os_state struct ia64_sal_os_state has three semi-independent sections. The code in mca_asm.S assumes that these three sections are contiguous, which makes it very awkward to add new data to this structure. Remove the assumption that the sections are contiguous. Define a macro to shorten references to offsets in ia64_sal_os_state. This patch does not change the way that the code behaves. It just makes it easier to update the code in future and to add fields to ia64_sal_os_state when debugging the MCA/INIT handlers. Signed-off-by: Keith Owens Signed-off-by: Tony Luck --- arch/ia64/kernel/asm-offsets.c | 16 ++++++++++++---- arch/ia64/kernel/entry.h | 1 + arch/ia64/kernel/mca_asm.S | 28 +++++++++++++++++----------- include/asm-ia64/mca.h | 9 ++++++--- 4 files changed, 36 insertions(+), 18 deletions(-) diff --git a/arch/ia64/kernel/asm-offsets.c b/arch/ia64/kernel/asm-offsets.c index 77225659e96..16e7b6600ae 100644 --- a/arch/ia64/kernel/asm-offsets.c +++ b/arch/ia64/kernel/asm-offsets.c @@ -217,16 +217,24 @@ void foo(void) DEFINE(IA64_MCA_CPU_INIT_STACK_OFFSET, offsetof (struct ia64_mca_cpu, init_stack)); BLANK(); - DEFINE(IA64_SAL_OS_STATE_COMMON_OFFSET, - offsetof (struct ia64_sal_os_state, sal_ra)); DEFINE(IA64_SAL_OS_STATE_OS_GP_OFFSET, offsetof (struct ia64_sal_os_state, os_gp)); - DEFINE(IA64_SAL_OS_STATE_PAL_MIN_STATE_OFFSET, - offsetof (struct ia64_sal_os_state, pal_min_state)); DEFINE(IA64_SAL_OS_STATE_PROC_STATE_PARAM_OFFSET, offsetof (struct ia64_sal_os_state, proc_state_param)); + DEFINE(IA64_SAL_OS_STATE_SAL_RA_OFFSET, + offsetof (struct ia64_sal_os_state, sal_ra)); + DEFINE(IA64_SAL_OS_STATE_SAL_GP_OFFSET, + offsetof (struct ia64_sal_os_state, sal_gp)); + DEFINE(IA64_SAL_OS_STATE_PAL_MIN_STATE_OFFSET, + offsetof (struct ia64_sal_os_state, pal_min_state)); + DEFINE(IA64_SAL_OS_STATE_OS_STATUS_OFFSET, + offsetof (struct ia64_sal_os_state, os_status)); + DEFINE(IA64_SAL_OS_STATE_CONTEXT_OFFSET, + offsetof (struct ia64_sal_os_state, context)); DEFINE(IA64_SAL_OS_STATE_SIZE, sizeof (struct ia64_sal_os_state)); + BLANK(); + DEFINE(IA64_PMSA_GR_OFFSET, offsetof (struct pal_min_state_area_s, pmsa_gr)); DEFINE(IA64_PMSA_BANK1_GR_OFFSET, diff --git a/arch/ia64/kernel/entry.h b/arch/ia64/kernel/entry.h index 78eeb079341..ebc3dfb8882 100644 --- a/arch/ia64/kernel/entry.h +++ b/arch/ia64/kernel/entry.h @@ -23,6 +23,7 @@ #define PT(f) (IA64_PT_REGS_##f##_OFFSET) #define SW(f) (IA64_SWITCH_STACK_##f##_OFFSET) +#define SOS(f) (IA64_SAL_OS_STATE_##f##_OFFSET) #define PT_REGS_SAVES(off) \ .unwabi 3, 'i'; \ diff --git a/arch/ia64/kernel/mca_asm.S b/arch/ia64/kernel/mca_asm.S index 6dff024cd62..c1bd1feffab 100644 --- a/arch/ia64/kernel/mca_asm.S +++ b/arch/ia64/kernel/mca_asm.S @@ -159,7 +159,7 @@ ia64_os_mca_spin: GET_IA64_MCA_DATA(r2) // Using MCA stack, struct ia64_sal_os_state, variable proc_state_param ;; - add r3=IA64_MCA_CPU_MCA_STACK_OFFSET+MCA_SOS_OFFSET+IA64_SAL_OS_STATE_PROC_STATE_PARAM_OFFSET, r2 + add r3=IA64_MCA_CPU_MCA_STACK_OFFSET+MCA_SOS_OFFSET+SOS(PROC_STATE_PARAM), r2 ;; ld8 r18=[r3] // Get processor state parameter on existing PALE_CHECK. ;; @@ -479,9 +479,11 @@ ia64_state_save: st8 [temp2]=r11,16 // rv_rc mov r11=cr.iipa ;; - st8 [temp1]=r18,16 // proc_state_param - st8 [temp2]=r19,16 // monarch + st8 [temp1]=r18 // proc_state_param + st8 [temp2]=r19 // monarch mov r6=IA64_KR(CURRENT) + add temp1=SOS(SAL_RA), regs + add temp2=SOS(SAL_GP), regs ;; st8 [temp1]=r12,16 // sal_ra st8 [temp2]=r10,16 // sal_gp @@ -503,12 +505,14 @@ ia64_state_save: st8 [temp2]=r11,16 // cr.iipa mov r12=cr.iim ;; - st8 [temp1]=r12,16 // cr.iim + st8 [temp1]=r12 // cr.iim (p1) mov r12=IA64_MCA_COLD_BOOT (p2) mov r12=IA64_INIT_WARM_BOOT mov r6=cr.iha + add temp1=SOS(OS_STATUS), regs ;; - st8 [temp2]=r6,16 // cr.iha + st8 [temp2]=r6 // cr.iha + add temp2=SOS(CONTEXT), regs st8 [temp1]=r12 // os_status, default is cold boot mov r6=IA64_MCA_SAME_CONTEXT ;; @@ -820,8 +824,8 @@ ia64_state_restore: // Restore the SAL to OS state. The previous code left regs at pt_regs. add regs=MCA_SOS_OFFSET-MCA_PT_REGS_OFFSET, regs ;; - add temp1=IA64_SAL_OS_STATE_COMMON_OFFSET, regs - add temp2=IA64_SAL_OS_STATE_COMMON_OFFSET+8, regs + add temp1=SOS(SAL_RA), regs + add temp2=SOS(SAL_GP), regs ;; ld8 r12=[temp1],16 // sal_ra ld8 r9=[temp2],16 // sal_gp @@ -842,8 +846,10 @@ ia64_state_restore: ;; mov cr.itir=temp3 mov cr.iipa=temp4 - ld8 temp3=[temp1],16 // cr.iim - ld8 temp4=[temp2],16 // cr.iha + ld8 temp3=[temp1] // cr.iim + ld8 temp4=[temp2] // cr.iha + add temp1=SOS(OS_STATUS), regs + add temp2=SOS(CONTEXT), regs ;; mov cr.iim=temp3 mov cr.iha=temp4 @@ -916,7 +922,7 @@ ia64_state_restore: ia64_new_stack: add regs=MCA_PT_REGS_OFFSET, r3 - add temp2=MCA_SOS_OFFSET+IA64_SAL_OS_STATE_PAL_MIN_STATE_OFFSET, r3 + add temp2=MCA_SOS_OFFSET+SOS(PAL_MIN_STATE), r3 mov b0=r2 // save return address GET_IA64_MCA_DATA(temp1) invala @@ -1020,7 +1026,7 @@ ia64_old_stack: ia64_set_kernel_registers: add temp3=MCA_SP_OFFSET, r3 - add temp4=MCA_SOS_OFFSET+IA64_SAL_OS_STATE_OS_GP_OFFSET, r3 + add temp4=MCA_SOS_OFFSET+SOS(OS_GP), r3 mov b0=r2 // save return address GET_IA64_MCA_DATA(temp1) ;; diff --git a/include/asm-ia64/mca.h b/include/asm-ia64/mca.h index 9c5389b7e62..ee97f7c2d46 100644 --- a/include/asm-ia64/mca.h +++ b/include/asm-ia64/mca.h @@ -69,14 +69,16 @@ typedef struct ia64_mc_info_s { */ struct ia64_sal_os_state { - /* SAL to OS, must be at offset 0 */ + + /* SAL to OS */ u64 os_gp; /* GP of the os registered with the SAL, physical */ u64 pal_proc; /* PAL_PROC entry point, physical */ u64 sal_proc; /* SAL_PROC entry point, physical */ u64 rv_rc; /* MCA - Rendezvous state, INIT - reason code */ u64 proc_state_param; /* from R18 */ u64 monarch; /* 1 for a monarch event, 0 for a slave */ - /* common, must follow SAL to OS */ + + /* common */ u64 sal_ra; /* Return address in SAL, physical */ u64 sal_gp; /* GP of the SAL - physical */ pal_min_state_area_t *pal_min_state; /* from R17. physical in asm, virtual in C */ @@ -98,7 +100,8 @@ struct ia64_sal_os_state { u64 iipa; u64 iim; u64 iha; - /* OS to SAL, must follow common */ + + /* OS to SAL */ u64 os_status; /* OS status to SAL, enum below */ u64 context; /* 0 if return to same context 1 if return to new context */ -- cgit v1.2.3 From f640f94ec4f39e8a4d91d58354d3e09b28769edf Mon Sep 17 00:00:00 2001 From: Mike Habeck Date: Mon, 19 Jun 2006 15:38:10 -0500 Subject: [IA64-SGI] fix SGI Altix tioce_bus_fixup() bug The following patch fixes a bug in the SGI Altix tioce_bus_fixup() code. ce_dre_comp_err_addr needs to be zero'd out not ~0ULL. As a result completion errors weren't being captured. Signed-off-by: Mike Habeck Signed-off-by: Tony Luck --- arch/ia64/sn/pci/tioce_provider.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/ia64/sn/pci/tioce_provider.c b/arch/ia64/sn/pci/tioce_provider.c index 833295624e5..85f3b3d4c60 100644 --- a/arch/ia64/sn/pci/tioce_provider.c +++ b/arch/ia64/sn/pci/tioce_provider.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2003-2005 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (C) 2003-2006 Silicon Graphics, Inc. All Rights Reserved. */ #include @@ -1002,7 +1002,7 @@ tioce_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont tioce_mmr_seti(tioce_kern, &tioce_mmr->ce_adm_int_status_alias, ~0ULL); tioce_mmr_seti(tioce_kern, &tioce_mmr->ce_adm_error_summary_alias, ~0ULL); - tioce_mmr_seti(tioce_kern, &tioce_mmr->ce_dre_comp_err_addr, ~0ULL); + tioce_mmr_seti(tioce_kern, &tioce_mmr->ce_dre_comp_err_addr, 0ULL); if (request_irq(SGI_PCIASIC_ERROR, tioce_error_intr_handler, -- cgit v1.2.3 From 9ba89334552b96e2127dcafb1c46ce255ecf2667 Mon Sep 17 00:00:00 2001 From: Ian Wienand Date: Wed, 21 Jun 2006 10:33:04 +1000 Subject: [IA64] SKI Simulator boot Sorry I didn't notice earlier, but that BUG_ON triggers for me on the simulator. AFAICS the mask for itv is set in cpu_init(), which comes after sal_init(). Consequently on the simulator the itv still has its start value of zero. I've probably missed something, but I wonder why at this stage of the boot you even need to save and restore the itv? Signed-Off-By: Ian Wienand Signed-off-by: Tony Luck --- arch/ia64/kernel/sal.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/arch/ia64/kernel/sal.c b/arch/ia64/kernel/sal.c index 056f7a6eedc..77fa65903d9 100644 --- a/arch/ia64/kernel/sal.c +++ b/arch/ia64/kernel/sal.c @@ -227,7 +227,7 @@ static int sal_cache_flush_drops_interrupts; static void __init check_sal_cache_flush (void) { - unsigned long flags, itv; + unsigned long flags; int cpu; u64 vector; @@ -238,9 +238,6 @@ check_sal_cache_flush (void) * Schedule a timer interrupt, wait until it's reported, and see if * SAL_CACHE_FLUSH drops it. */ - itv = ia64_get_itv(); - BUG_ON((itv & (1 << 16)) == 0); - ia64_set_itv(IA64_TIMER_VECTOR); ia64_set_itm(ia64_get_itc() + 1000); @@ -260,7 +257,6 @@ check_sal_cache_flush (void) ia64_eoi(); } - ia64_set_itv(itv); local_irq_restore(flags); put_cpu(); } -- cgit v1.2.3 From c32ba30f76eb18b3d4449072fe9c345a9574796b Mon Sep 17 00:00:00 2001 From: Paul Serice Date: Wed, 7 Jun 2006 10:23:38 -0700 Subject: [PATCH] USB: EHCI works again on NVidia controllers with >2GB RAM From: Paul Serice The workaround in commit f7201c3dcd7799f2aa3d6ec427b194225360ecee broke. The work around requires memory for DMA transfers for some NVidia EHCI controllers to be below 2GB, but recent changes have caused some DMA memory to be allocated before the DMA mask is set. Signed-off-by: Paul Serice Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-pci.c | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index a1bd2bea6de..648ddb52d57 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -76,6 +76,30 @@ static int ehci_pci_setup(struct usb_hcd *hcd) dbg_hcs_params(ehci, "reset"); dbg_hcc_params(ehci, "reset"); + /* ehci_init() causes memory for DMA transfers to be + * allocated. Thus, any vendor-specific workarounds based on + * limiting the type of memory used for DMA transfers must + * happen before ehci_init() is called. */ + switch (pdev->vendor) { + case PCI_VENDOR_ID_NVIDIA: + /* NVidia reports that certain chips don't handle + * QH, ITD, or SITD addresses above 2GB. (But TD, + * data buffer, and periodic schedule are normal.) + */ + switch (pdev->device) { + case 0x003c: /* MCP04 */ + case 0x005b: /* CK804 */ + case 0x00d8: /* CK8 */ + case 0x00e8: /* CK8S */ + if (pci_set_consistent_dma_mask(pdev, + DMA_31BIT_MASK) < 0) + ehci_warn(ehci, "can't enable NVidia " + "workaround for >2GB RAM\n"); + break; + } + break; + } + /* cache this readonly data; minimize chip reads */ ehci->hcs_params = readl(&ehci->caps->hcs_params); @@ -88,8 +112,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd) if (retval) return retval; - /* NOTE: only the parts below this line are PCI-specific */ - switch (pdev->vendor) { case PCI_VENDOR_ID_TDI: if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) { @@ -107,19 +129,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd) break; case PCI_VENDOR_ID_NVIDIA: switch (pdev->device) { - /* NVidia reports that certain chips don't handle - * QH, ITD, or SITD addresses above 2GB. (But TD, - * data buffer, and periodic schedule are normal.) - */ - case 0x003c: /* MCP04 */ - case 0x005b: /* CK804 */ - case 0x00d8: /* CK8 */ - case 0x00e8: /* CK8S */ - if (pci_set_consistent_dma_mask(pdev, - DMA_31BIT_MASK) < 0) - ehci_warn(ehci, "can't enable NVidia " - "workaround for >2GB RAM\n"); - break; /* Some NForce2 chips have problems with selective suspend; * fixed in newer silicon. */ -- cgit v1.2.3 From 5cd330f4f30eb154e7af9210bed42dfcd447997f Mon Sep 17 00:00:00 2001 From: Henk Vergonet Date: Mon, 15 May 2006 12:34:43 +0200 Subject: [PATCH] USB: add YEALINK phones to the HID_QUIRK_IGNORE blacklist Keys on Yealink based phones will not function properly when using the generic HID driver. This patch prevents the generic HID code from grabbing the device before the regular yealink driver can get a grip on it. Signed-off-by: Henk Vergonet Signed-off-by: Vojtech Pavlik Signed-off-by: Greg Kroah-Hartman --- drivers/usb/input/hid-core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 435273e7c85..4f7e9214de0 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -1563,6 +1563,8 @@ void hid_init_reports(struct hid_device *hid) #define USB_VENDOR_ID_CREATIVELABS 0x062a #define USB_DEVICE_ID_CREATIVELABS_SILVERCREST 0x0201 +#define USB_VENDOR_ID_YEALINK 0x6993 +#define USB_DEVICE_ID_YEALINK_P1K_P4K_B2K 0xb001 /* * Alphabetically sorted blacklist by quirk type. */ @@ -1671,6 +1673,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_DTF + 3, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_YEALINK, USB_DEVICE_ID_YEALINK_P1K_P4K_B2K, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_302, HID_QUIRK_IGNORE }, -- cgit v1.2.3 From 86478944eba887f149e151bacc023ae4b2d23ea6 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Sat, 13 May 2006 22:50:47 +0200 Subject: [PATCH] USB: cdc-acm: add a new special case for modems with buggy firmware this fixes the "duplicated text" bug. There's a modem that cannot cope with large transfers and more than one urb in flight. This patch adds a special case to the driver. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 82 +++++++++++++++++++++++++++------------------ drivers/usb/class/cdc-acm.h | 16 +++++---- 2 files changed, 59 insertions(+), 39 deletions(-) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 6dd339f4c0f..506aff60dac 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -127,8 +127,8 @@ static int acm_wb_alloc(struct acm *acm) wb->use = 1; return wbn; } - wbn = (wbn + 1) % ACM_NWB; - if (++i >= ACM_NWB) + wbn = (wbn + 1) % ACM_NW; + if (++i >= ACM_NW) return -1; } } @@ -142,10 +142,9 @@ static int acm_wb_is_avail(struct acm *acm) { int i, n; - n = 0; - for (i = 0; i < ACM_NWB; i++) { - if (!acm->wb[i].use) - n++; + n = ACM_NW; + for (i = 0; i < ACM_NW; i++) { + n -= acm->wb[i].use; } return n; } @@ -167,7 +166,7 @@ static void acm_write_done(struct acm *acm) acm->write_ready = 1; wbn = acm->write_current; acm_wb_free(acm, wbn); - acm->write_current = (wbn + 1) % ACM_NWB; + acm->write_current = (wbn + 1) % ACM_NW; spin_unlock_irqrestore(&acm->write_lock, flags); } @@ -291,22 +290,32 @@ static void acm_read_bulk(struct urb *urb, struct pt_regs *regs) struct acm_rb *buf; struct acm_ru *rcv = urb->context; struct acm *acm = rcv->instance; + int status = urb->status; dbg("Entering acm_read_bulk with status %d\n", urb->status); if (!ACM_READY(acm)) return; - if (urb->status) - dev_dbg(&acm->data->dev, "bulk rx status %d\n", urb->status); + if (status) + dev_dbg(&acm->data->dev, "bulk rx status %d\n", status); buf = rcv->buffer; buf->size = urb->actual_length; - spin_lock(&acm->read_lock); - list_add_tail(&rcv->list, &acm->spare_read_urbs); - list_add_tail(&buf->list, &acm->filled_read_bufs); - spin_unlock(&acm->read_lock); - + if (likely(status == 0)) { + spin_lock(&acm->read_lock); + list_add_tail(&rcv->list, &acm->spare_read_urbs); + list_add_tail(&buf->list, &acm->filled_read_bufs); + spin_unlock(&acm->read_lock); + } else { + /* we drop the buffer due to an error */ + spin_lock(&acm->read_lock); + list_add_tail(&rcv->list, &acm->spare_read_urbs); + list_add(&buf->list, &acm->spare_read_bufs); + spin_unlock(&acm->read_lock); + /* nevertheless the tasklet must be kicked unconditionally + so the queue cannot dry up */ + } tasklet_schedule(&acm->urb_task); } @@ -464,10 +473,10 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) INIT_LIST_HEAD(&acm->spare_read_urbs); INIT_LIST_HEAD(&acm->spare_read_bufs); INIT_LIST_HEAD(&acm->filled_read_bufs); - for (i = 0; i < ACM_NRU; i++) { + for (i = 0; i < acm->rx_buflimit; i++) { list_add(&(acm->ru[i].list), &acm->spare_read_urbs); } - for (i = 0; i < ACM_NRB; i++) { + for (i = 0; i < acm->rx_buflimit; i++) { list_add(&(acm->rb[i].list), &acm->spare_read_bufs); } @@ -488,14 +497,15 @@ bail_out: static void acm_tty_unregister(struct acm *acm) { - int i; + int i,nr; + nr = acm->rx_buflimit; tty_unregister_device(acm_tty_driver, acm->minor); usb_put_intf(acm->control); acm_table[acm->minor] = NULL; usb_free_urb(acm->ctrlurb); usb_free_urb(acm->writeurb); - for (i = 0; i < ACM_NRU; i++) + for (i = 0; i < nr; i++) usb_free_urb(acm->ru[i].urb); kfree(acm); } @@ -503,18 +513,19 @@ static void acm_tty_unregister(struct acm *acm) static void acm_tty_close(struct tty_struct *tty, struct file *filp) { struct acm *acm = tty->driver_data; - int i; + int i,nr; if (!acm || !acm->used) return; + nr = acm->rx_buflimit; mutex_lock(&open_mutex); if (!--acm->used) { if (acm->dev) { acm_set_control(acm, acm->ctrlout = 0); usb_kill_urb(acm->ctrlurb); usb_kill_urb(acm->writeurb); - for (i = 0; i < ACM_NRU; i++) + for (i = 0; i < nr; i++) usb_kill_urb(acm->ru[i].urb); } else acm_tty_unregister(acm); @@ -576,7 +587,7 @@ static int acm_tty_chars_in_buffer(struct tty_struct *tty) /* * This is inaccurate (overcounts), but it works. */ - return (ACM_NWB - acm_wb_is_avail(acm)) * acm->writesize; + return (ACM_NW - acm_wb_is_avail(acm)) * acm->writesize; } static void acm_tty_throttle(struct tty_struct *tty) @@ -712,7 +723,7 @@ static void acm_write_buffers_free(struct acm *acm) int i; struct acm_wb *wb; - for (wb = &acm->wb[0], i = 0; i < ACM_NWB; i++, wb++) { + for (wb = &acm->wb[0], i = 0; i < ACM_NW; i++, wb++) { usb_buffer_free(acm->dev, acm->writesize, wb->buf, wb->dmah); } } @@ -723,7 +734,7 @@ static int acm_write_buffers_alloc(struct acm *acm) int i; struct acm_wb *wb; - for (wb = &acm->wb[0], i = 0; i < ACM_NWB; i++, wb++) { + for (wb = &acm->wb[0], i = 0; i < ACM_NW; i++, wb++) { wb->buf = usb_buffer_alloc(acm->dev, acm->writesize, GFP_KERNEL, &wb->dmah); if (!wb->buf) { @@ -760,10 +771,14 @@ static int acm_probe (struct usb_interface *intf, int call_interface_num = -1; int data_interface_num; unsigned long quirks; + int num_rx_buf; int i; - /* handle quirks deadly to normal probing*/ + /* normal quirks */ quirks = (unsigned long)id->driver_info; + num_rx_buf = (quirks == SINGLE_RX_URB) ? 1 : ACM_NR; + + /* handle quirks deadly to normal probing*/ if (quirks == NO_UNION_NORMAL) { data_interface = usb_ifnum_to_if(usb_dev, 1); control_interface = usb_ifnum_to_if(usb_dev, 0); @@ -900,7 +915,7 @@ skip_normal_probe: } ctrlsize = le16_to_cpu(epctrl->wMaxPacketSize); - readsize = le16_to_cpu(epread->wMaxPacketSize)*2; + readsize = le16_to_cpu(epread->wMaxPacketSize)* ( quirks == SINGLE_RX_URB ? 1 : 2); acm->writesize = le16_to_cpu(epwrite->wMaxPacketSize); acm->control = control_interface; acm->data = data_interface; @@ -909,6 +924,7 @@ skip_normal_probe: acm->ctrl_caps = ac_management_function; acm->ctrlsize = ctrlsize; acm->readsize = readsize; + acm->rx_buflimit = num_rx_buf; acm->urb_task.func = acm_rx_tasklet; acm->urb_task.data = (unsigned long) acm; INIT_WORK(&acm->work, acm_softint, acm); @@ -935,7 +951,7 @@ skip_normal_probe: dev_dbg(&intf->dev, "out of memory (ctrlurb kmalloc)\n"); goto alloc_fail5; } - for (i = 0; i < ACM_NRU; i++) { + for (i = 0; i < num_rx_buf; i++) { struct acm_ru *rcv = &(acm->ru[i]); if (!(rcv->urb = usb_alloc_urb(0, GFP_KERNEL))) { @@ -946,10 +962,9 @@ skip_normal_probe: rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; rcv->instance = acm; } - for (i = 0; i < ACM_NRB; i++) { + for (i = 0; i < num_rx_buf; i++) { struct acm_rb *buf = &(acm->rb[i]); - // Using usb_buffer_alloc instead of kmalloc as Oliver suggested if (!(buf->base = usb_buffer_alloc(acm->dev, readsize, GFP_KERNEL, &buf->dma))) { dev_dbg(&intf->dev, "out of memory (read bufs usb_buffer_alloc)\n"); goto alloc_fail7; @@ -988,9 +1003,9 @@ skip_normal_probe: return 0; alloc_fail7: - for (i = 0; i < ACM_NRB; i++) + for (i = 0; i < num_rx_buf; i++) usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma); - for (i = 0; i < ACM_NRU; i++) + for (i = 0; i < num_rx_buf; i++) usb_free_urb(acm->ru[i].urb); usb_free_urb(acm->ctrlurb); alloc_fail5: @@ -1027,7 +1042,7 @@ static void acm_disconnect(struct usb_interface *intf) usb_kill_urb(acm->ctrlurb); usb_kill_urb(acm->writeurb); - for (i = 0; i < ACM_NRU; i++) + for (i = 0; i < acm->rx_buflimit; i++) usb_kill_urb(acm->ru[i].urb); INIT_LIST_HEAD(&acm->filled_read_bufs); @@ -1039,7 +1054,7 @@ static void acm_disconnect(struct usb_interface *intf) acm_write_buffers_free(acm); usb_buffer_free(usb_dev, acm->ctrlsize, acm->ctrl_buffer, acm->ctrl_dma); - for (i = 0; i < ACM_NRB; i++) + for (i = 0; i < acm->rx_buflimit; i++) usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma); usb_driver_release_interface(&acm_driver, intf == acm->control ? acm->data : intf); @@ -1068,6 +1083,9 @@ static struct usb_device_id acm_ids[] = { { USB_DEVICE(0x0482, 0x0203), /* KYOCERA AH-K3001V */ .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ }, + { USB_DEVICE(0x0ace, 0x1608), /* ZyDAS 56K USB MODEM */ + .driver_info = SINGLE_RX_URB, /* firmware bug */ + }, /* control interfaces with various AT-command sets */ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, USB_CDC_ACM_PROTO_AT_V25TER) }, diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h index fd2aaccdcba..1bcaea32cfc 100644 --- a/drivers/usb/class/cdc-acm.h +++ b/drivers/usb/class/cdc-acm.h @@ -56,11 +56,11 @@ * in line disciplines. They ask for empty space amount, receive our URB size, * and proceed to issue several 1-character writes, assuming they will fit. * The very first write takes a complete URB. Fortunately, this only happens - * when processing onlcr, so we only need 2 buffers. + * when processing onlcr, so we only need 2 buffers. These values must be + * powers of 2. */ -#define ACM_NWB 2 -#define ACM_NRU 16 -#define ACM_NRB 16 +#define ACM_NW 2 +#define ACM_NR 16 struct acm_wb { unsigned char *buf; @@ -91,9 +91,10 @@ struct acm { struct urb *ctrlurb, *writeurb; /* urbs */ u8 *ctrl_buffer; /* buffers of urbs */ dma_addr_t ctrl_dma; /* dma handles of buffers */ - struct acm_wb wb[ACM_NWB]; - struct acm_ru ru[ACM_NRU]; - struct acm_rb rb[ACM_NRB]; + struct acm_wb wb[ACM_NW]; + struct acm_ru ru[ACM_NR]; + struct acm_rb rb[ACM_NR]; + int rx_buflimit; int rx_endpoint; spinlock_t read_lock; struct list_head spare_read_urbs; @@ -122,3 +123,4 @@ struct acm { /* constants describing various quirks and errors */ #define NO_UNION_NORMAL 1 +#define SINGLE_RX_URB 2 -- cgit v1.2.3 From f44f725f7d635e8b9786eef13f836dc1a2851495 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Fri, 12 May 2006 19:24:34 -0700 Subject: [PATCH] USB: usbnet, zaurus mtu fixup This includes an MTU fixup which could affect larger packets with newer Zaurii, described as http://bugzilla.kernel.org/show_bug.cgi?id=6286; plus minor whitespace cleanup. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/net/zaurus.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/usb/net/zaurus.c b/drivers/usb/net/zaurus.c index f7ac9d6b985..bf2035d329f 100644 --- a/drivers/usb/net/zaurus.c +++ b/drivers/usb/net/zaurus.c @@ -109,7 +109,7 @@ static const struct driver_info zaurus_sl5x00_info = { .check_connect = always_connected, .bind = zaurus_bind, .unbind = usbnet_cdc_unbind, - .tx_fixup = zaurus_tx_fixup, + .tx_fixup = zaurus_tx_fixup, }; #define ZAURUS_STRONGARM_INFO ((unsigned long)&zaurus_sl5x00_info) @@ -119,7 +119,7 @@ static const struct driver_info zaurus_pxa_info = { .check_connect = always_connected, .bind = zaurus_bind, .unbind = usbnet_cdc_unbind, - .tx_fixup = zaurus_tx_fixup, + .tx_fixup = zaurus_tx_fixup, }; #define ZAURUS_PXA_INFO ((unsigned long)&zaurus_pxa_info) @@ -129,7 +129,7 @@ static const struct driver_info olympus_mxl_info = { .check_connect = always_connected, .bind = zaurus_bind, .unbind = usbnet_cdc_unbind, - .tx_fixup = zaurus_tx_fixup, + .tx_fixup = zaurus_tx_fixup, }; #define OLYMPUS_MXL_INFO ((unsigned long)&olympus_mxl_info) @@ -228,6 +228,11 @@ bad_detail: detail->bDetailData[2]); goto bad_desc; } + + /* same extra framing as for non-BLAN mode */ + dev->net->hard_header_len += 6; + dev->rx_urb_size = dev->net->hard_header_len + + dev->net->mtu; break; } next_desc: @@ -258,7 +263,7 @@ static const struct driver_info bogus_mdlm_info = { .description = "pseudo-MDLM (BLAN) device", .flags = FLAG_FRAMING_Z, .check_connect = always_connected, - .tx_fixup = zaurus_tx_fixup, + .tx_fixup = zaurus_tx_fixup, .bind = blan_mdlm_bind, }; @@ -367,13 +372,13 @@ static struct usb_driver zaurus_driver = { static int __init zaurus_init(void) { - return usb_register(&zaurus_driver); + return usb_register(&zaurus_driver); } module_init(zaurus_init); static void __exit zaurus_exit(void) { - usb_deregister(&zaurus_driver); + usb_deregister(&zaurus_driver); } module_exit(zaurus_exit); -- cgit v1.2.3 From 7327413c745c2f8e8d4b92f76759821263b095c1 Mon Sep 17 00:00:00 2001 From: Eduard Warkentin Date: Thu, 18 May 2006 01:13:17 -0700 Subject: [PATCH] USB: added support for ASIX 88178 chipset USB Gigabit Ethernet adaptor Add support for detection and dworking with a ASIX 88178 based USB-Gigabit adaptor. With the patch, it is detected and handled correctly by the asix module. Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/net/asix.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/usb/net/asix.c b/drivers/usb/net/asix.c index 12b599a0b53..37111acec87 100644 --- a/drivers/usb/net/asix.c +++ b/drivers/usb/net/asix.c @@ -911,6 +911,10 @@ static const struct usb_device_id products [] = { // ASIX AX88772 10/100 USB_DEVICE (0x0b95, 0x7720), .driver_info = (unsigned long) &ax88772_info, +}, { + // ASIX AX88178 10/100/1000 + USB_DEVICE (0x0b95, 0x1780), + .driver_info = (unsigned long) &ax88772_info, }, { // Linksys USB200M Rev 2 USB_DEVICE (0x13b1, 0x0018), -- cgit v1.2.3 From 2682d27c5884550857cd96231db5b22b3acced53 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Tue, 28 Mar 2006 01:00:21 -0800 Subject: [PATCH] USB: convert the semaphores in the sisusb driver to mutexes From: Arjan van de Ven Convert the semaphores-used-as-mutex to mutexes in the sisusb video driver; this required manual checking due to the "return as locked" stuff in this driver, but the ->lock semaphore is still used as mutex in the end. Signed-off-by: Arjan van de Ven Cc: Thomas Winischhofer Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/sisusbvga/sisusb.c | 77 +++++++++---------- drivers/usb/misc/sisusbvga/sisusb.h | 6 +- drivers/usb/misc/sisusbvga/sisusb_con.c | 129 ++++++++++++++++---------------- 3 files changed, 107 insertions(+), 105 deletions(-) diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index 196c8794a73..19aedbc85ea 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c @@ -37,6 +37,7 @@ */ #include +#include #include #include #include @@ -102,7 +103,7 @@ MODULE_PARM_DESC(last, "Number of last console to take over (1 - MAX_NR_CONSOLES static struct usb_driver sisusb_driver; -DECLARE_MUTEX(disconnect_sem); +DEFINE_MUTEX(disconnect_mutex); static void sisusb_free_buffers(struct sisusb_usb_data *sisusb) @@ -2552,39 +2553,39 @@ sisusb_open(struct inode *inode, struct file *file) struct usb_interface *interface; int subminor = iminor(inode); - down(&disconnect_sem); + mutex_lock(&disconnect_mutex); if (!(interface = usb_find_interface(&sisusb_driver, subminor))) { printk(KERN_ERR "sisusb[%d]: Failed to find interface\n", subminor); - up(&disconnect_sem); + mutex_unlock(&disconnect_mutex); return -ENODEV; } if (!(sisusb = usb_get_intfdata(interface))) { - up(&disconnect_sem); + mutex_unlock(&disconnect_mutex); return -ENODEV; } - down(&sisusb->lock); + mutex_lock(&sisusb->lock); if (!sisusb->present || !sisusb->ready) { - up(&sisusb->lock); - up(&disconnect_sem); + mutex_unlock(&sisusb->lock); + mutex_unlock(&disconnect_mutex); return -ENODEV; } if (sisusb->isopen) { - up(&sisusb->lock); - up(&disconnect_sem); + mutex_unlock(&sisusb->lock); + mutex_unlock(&disconnect_mutex); return -EBUSY; } if (!sisusb->devinit) { if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH) { if (sisusb_init_gfxdevice(sisusb, 0)) { - up(&sisusb->lock); - up(&disconnect_sem); + mutex_unlock(&sisusb->lock); + mutex_unlock(&disconnect_mutex); printk(KERN_ERR "sisusbvga[%d]: Failed to initialize " "device\n", @@ -2592,8 +2593,8 @@ sisusb_open(struct inode *inode, struct file *file) return -EIO; } } else { - up(&sisusb->lock); - up(&disconnect_sem); + mutex_unlock(&sisusb->lock); + mutex_unlock(&disconnect_mutex); printk(KERN_ERR "sisusbvga[%d]: Device not attached to " "USB 2.0 hub\n", @@ -2609,9 +2610,9 @@ sisusb_open(struct inode *inode, struct file *file) file->private_data = sisusb; - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); - up(&disconnect_sem); + mutex_unlock(&disconnect_mutex); return 0; } @@ -2642,14 +2643,14 @@ sisusb_release(struct inode *inode, struct file *file) struct sisusb_usb_data *sisusb; int myminor; - down(&disconnect_sem); + mutex_lock(&disconnect_mutex); if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) { - up(&disconnect_sem); + mutex_unlock(&disconnect_mutex); return -ENODEV; } - down(&sisusb->lock); + mutex_lock(&sisusb->lock); if (sisusb->present) { /* Wait for all URBs to finish if device still present */ @@ -2662,12 +2663,12 @@ sisusb_release(struct inode *inode, struct file *file) sisusb->isopen = 0; file->private_data = NULL; - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); /* decrement the usage count on our device */ kref_put(&sisusb->kref, sisusb_delete); - up(&disconnect_sem); + mutex_unlock(&disconnect_mutex); return 0; } @@ -2685,11 +2686,11 @@ sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) return -ENODEV; - down(&sisusb->lock); + mutex_lock(&sisusb->lock); /* Sanity check */ if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) { - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return -ENODEV; } @@ -2784,7 +2785,7 @@ sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + 0x5c) { if (count != 4) { - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return -EINVAL; } @@ -2808,7 +2809,7 @@ sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) (*ppos) += bytes_read; - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return errno ? errno : bytes_read; } @@ -2827,11 +2828,11 @@ sisusb_write(struct file *file, const char __user *buffer, size_t count, if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) return -ENODEV; - down(&sisusb->lock); + mutex_lock(&sisusb->lock); /* Sanity check */ if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) { - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return -ENODEV; } @@ -2930,7 +2931,7 @@ sisusb_write(struct file *file, const char __user *buffer, size_t count, (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + SISUSB_PCI_PCONFSIZE) { if (count != 4) { - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return -EINVAL; } @@ -2956,7 +2957,7 @@ sisusb_write(struct file *file, const char __user *buffer, size_t count, (*ppos) += bytes_written; - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return errno ? errno : bytes_written; } @@ -2970,11 +2971,11 @@ sisusb_lseek(struct file *file, loff_t offset, int orig) if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) return -ENODEV; - down(&sisusb->lock); + mutex_lock(&sisusb->lock); /* Sanity check */ if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) { - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return -ENODEV; } @@ -2994,7 +2995,7 @@ sisusb_lseek(struct file *file, loff_t offset, int orig) ret = -EINVAL; } - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return ret; } @@ -3136,7 +3137,7 @@ sisusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) return -ENODEV; - down(&sisusb->lock); + mutex_lock(&sisusb->lock); /* Sanity check */ if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) { @@ -3193,7 +3194,7 @@ sisusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, } err_out: - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return retval; } @@ -3258,7 +3259,7 @@ static int sisusb_probe(struct usb_interface *intf, } kref_init(&sisusb->kref); - init_MUTEX(&(sisusb->lock)); + mutex_init(&(sisusb->lock)); /* Register device */ if ((retval = usb_register_dev(intf, &usb_sisusb_class))) { @@ -3429,9 +3430,9 @@ static void sisusb_disconnect(struct usb_interface *intf) * protect all other routines from the disconnect * case, not the other way round. */ - down(&disconnect_sem); + mutex_lock(&disconnect_mutex); - down(&sisusb->lock); + mutex_lock(&sisusb->lock); /* Wait for all URBs to complete and kill them in case (MUST do) */ if (!sisusb_wait_all_out_complete(sisusb)) @@ -3462,12 +3463,12 @@ static void sisusb_disconnect(struct usb_interface *intf) sisusb->present = 0; sisusb->ready = 0; - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); /* decrement our usage count */ kref_put(&sisusb->kref, sisusb_delete); - up(&disconnect_sem); + mutex_unlock(&disconnect_mutex); printk(KERN_INFO "sisusbvga[%d]: Disconnected\n", minor); } diff --git a/drivers/usb/misc/sisusbvga/sisusb.h b/drivers/usb/misc/sisusbvga/sisusb.h index a716825d1f9..8e1120a6480 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.h +++ b/drivers/usb/misc/sisusbvga/sisusb.h @@ -41,6 +41,8 @@ #define SISUSB_NEW_CONFIG_COMPAT #endif +#include + /* For older kernels, support for text consoles is by default * off. To ensable text console support, change the following: */ @@ -60,11 +62,9 @@ #define INCL_SISUSB_CON 1 #endif -#ifdef INCL_SISUSB_CON #include #include #include "sisusb_struct.h" -#endif /* USB related */ @@ -116,7 +116,7 @@ struct sisusb_usb_data { struct usb_interface *interface; struct kref kref; wait_queue_head_t wait_q; /* for syncind and timeouts */ - struct semaphore lock; /* general race avoidance */ + struct mutex lock; /* general race avoidance */ unsigned int ifnum; /* interface number of the USB device */ int minor; /* minor (for logging clarity) */ int isopen; /* !=0 if open */ diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c index be5c1a25ae2..092281c172a 100644 --- a/drivers/usb/misc/sisusbvga/sisusb_con.c +++ b/drivers/usb/misc/sisusbvga/sisusb_con.c @@ -48,6 +48,7 @@ */ #include +#include #include #include #include @@ -102,7 +103,7 @@ static struct sisusb_usb_data *mysisusbs[MAX_NR_CONSOLES]; /* Forward declaration */ static const struct consw sisusb_con; -extern struct semaphore disconnect_sem; +extern struct mutex disconnect_mutex; static inline void sisusbcon_memsetw(u16 *s, u16 c, unsigned int count) @@ -194,11 +195,11 @@ sisusb_get_sisusb_lock_and_check(unsigned short console) if (!(sisusb = sisusb_get_sisusb(console))) return NULL; - down(&sisusb->lock); + mutex_lock(&sisusb->lock); if (!sisusb_sisusb_valid(sisusb) || !sisusb->havethisconsole[console]) { - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return NULL; } @@ -236,18 +237,18 @@ sisusbcon_init(struct vc_data *c, int init) * are set up/restored. */ - down(&disconnect_sem); + mutex_lock(&disconnect_mutex); if (!(sisusb = sisusb_get_sisusb(c->vc_num))) { - up(&disconnect_sem); + mutex_unlock(&disconnect_mutex); return; } - down(&sisusb->lock); + mutex_lock(&sisusb->lock); if (!sisusb_sisusb_valid(sisusb)) { - up(&sisusb->lock); - up(&disconnect_sem); + mutex_unlock(&sisusb->lock); + mutex_unlock(&disconnect_mutex); return; } @@ -284,9 +285,9 @@ sisusbcon_init(struct vc_data *c, int init) if (!*c->vc_uni_pagedir_loc) con_set_default_unimap(c); - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); - up(&disconnect_sem); + mutex_unlock(&disconnect_mutex); if (init) { c->vc_cols = cols; @@ -306,14 +307,14 @@ sisusbcon_deinit(struct vc_data *c) * and others, ie not under our control. */ - down(&disconnect_sem); + mutex_lock(&disconnect_mutex); if (!(sisusb = sisusb_get_sisusb(c->vc_num))) { - up(&disconnect_sem); + mutex_unlock(&disconnect_mutex); return; } - down(&sisusb->lock); + mutex_lock(&sisusb->lock); /* Clear ourselves in mysisusbs */ mysisusbs[c->vc_num] = NULL; @@ -332,12 +333,12 @@ sisusbcon_deinit(struct vc_data *c) } } - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); /* decrement the usage count on our sisusb */ kref_put(&sisusb->kref, sisusb_delete); - up(&disconnect_sem); + mutex_unlock(&disconnect_mutex); } /* interface routine */ @@ -417,7 +418,7 @@ sisusbcon_putc(struct vc_data *c, int ch, int y, int x) #endif if (sisusb_is_inactive(c, sisusb)) { - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return; } @@ -425,7 +426,7 @@ sisusbcon_putc(struct vc_data *c, int ch, int y, int x) sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(x, y), (u32)SISUSB_HADDR(x, y), 2, &written); - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); } /* Interface routine */ @@ -453,14 +454,14 @@ sisusbcon_putcs(struct vc_data *c, const unsigned short *s, sisusbcon_writew(sisusbcon_readw(s++), dest++); if (sisusb_is_inactive(c, sisusb)) { - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return; } sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(x, y), (u32)SISUSB_HADDR(x, y), count * 2, &written); - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); } /* Interface routine */ @@ -504,7 +505,7 @@ sisusbcon_clear(struct vc_data *c, int y, int x, int height, int width) } if (sisusb_is_inactive(c, sisusb)) { - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return; } @@ -514,7 +515,7 @@ sisusbcon_clear(struct vc_data *c, int y, int x, int height, int width) sisusb_copy_memory(sisusb, (unsigned char *)SISUSB_VADDR(x, y), (u32)SISUSB_HADDR(x, y), length, &written); - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); } /* Interface routine */ @@ -576,7 +577,7 @@ sisusbcon_bmove(struct vc_data *c, int sy, int sx, #endif if (sisusb_is_inactive(c, sisusb)) { - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return; } @@ -586,7 +587,7 @@ sisusbcon_bmove(struct vc_data *c, int sy, int sx, sisusb_copy_memory(sisusb, (unsigned char *)SISUSB_VADDR(dx, dy), (u32)SISUSB_HADDR(dx, dy), length, &written); - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); } /* interface routine */ @@ -609,7 +610,7 @@ sisusbcon_switch(struct vc_data *c) /* Don't write to screen if in gfx mode */ if (sisusb_is_inactive(c, sisusb)) { - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return 0; } @@ -618,7 +619,7 @@ sisusbcon_switch(struct vc_data *c) * as origin. */ if (c->vc_origin == (unsigned long)c->vc_screenbuf) { - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); printk(KERN_DEBUG "sisusb: ASSERT ORIGIN != SCREENBUF!\n"); return 0; } @@ -635,7 +636,7 @@ sisusbcon_switch(struct vc_data *c) (u32)SISUSB_HADDR(0, 0), length, &written); - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return 0; } @@ -657,7 +658,7 @@ sisusbcon_save_screen(struct vc_data *c) /* sisusb->lock is down */ if (sisusb_is_inactive(c, sisusb)) { - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return; } @@ -669,7 +670,7 @@ sisusbcon_save_screen(struct vc_data *c) sisusbcon_memcpyw((u16 *)c->vc_screenbuf, (u16 *)c->vc_origin, length); - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); } /* interface routine */ @@ -690,7 +691,7 @@ sisusbcon_set_palette(struct vc_data *c, unsigned char *table) /* sisusb->lock is down */ if (sisusb_is_inactive(c, sisusb)) { - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return -EINVAL; } @@ -705,7 +706,7 @@ sisusbcon_set_palette(struct vc_data *c, unsigned char *table) break; } - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return 0; } @@ -728,7 +729,7 @@ sisusbcon_blank(struct vc_data *c, int blank, int mode_switch) sisusb->is_gfx = blank ? 1 : 0; if (sisusb_is_inactive(c, sisusb)) { - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return 0; } @@ -777,7 +778,7 @@ sisusbcon_blank(struct vc_data *c, int blank, int mode_switch) cr63 = 0x40; break; default: - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return -EINVAL; } @@ -788,7 +789,7 @@ sisusbcon_blank(struct vc_data *c, int blank, int mode_switch) } - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return ret; } @@ -809,7 +810,7 @@ sisusbcon_scrolldelta(struct vc_data *c, int lines) /* sisusb->lock is down */ if (sisusb_is_inactive(c, sisusb)) { - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return 0; } @@ -849,7 +850,7 @@ sisusbcon_scrolldelta(struct vc_data *c, int lines) sisusbcon_set_start_address(sisusb, c); - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return 1; } @@ -867,7 +868,7 @@ sisusbcon_cursor(struct vc_data *c, int mode) /* sisusb->lock is down */ if (sisusb_is_inactive(c, sisusb)) { - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return; } @@ -879,7 +880,7 @@ sisusbcon_cursor(struct vc_data *c, int mode) if (mode == CM_ERASE) { sisusb_setidxregor(sisusb, SISCR, 0x0a, 0x20); sisusb->sisusb_cursor_size_to = -1; - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return; } @@ -919,7 +920,7 @@ sisusbcon_cursor(struct vc_data *c, int mode) sisusb->sisusb_cursor_size_to = to; } - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); } static int @@ -961,7 +962,7 @@ sisusbcon_scroll_area(struct vc_data *c, struct sisusb_usb_data *sisusb, sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(0, t), (u32)SISUSB_HADDR(0, t), length, &written); - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return 1; } @@ -994,7 +995,7 @@ sisusbcon_scroll(struct vc_data *c, int t, int b, int dir, int lines) /* sisusb->lock is down */ if (sisusb_is_inactive(c, sisusb)) { - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return 0; } @@ -1084,7 +1085,7 @@ sisusbcon_scroll(struct vc_data *c, int t, int b, int dir, int lines) c->vc_pos = c->vc_pos - oldorigin + c->vc_origin; - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return 1; } @@ -1106,7 +1107,7 @@ sisusbcon_set_origin(struct vc_data *c) /* sisusb->lock is down */ if (sisusb_is_inactive(c, sisusb) || sisusb->con_blanked) { - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return 0; } @@ -1116,7 +1117,7 @@ sisusbcon_set_origin(struct vc_data *c) sisusb->con_rolled_over = 0; - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return 1; } @@ -1133,7 +1134,7 @@ sisusbcon_resize(struct vc_data *c, unsigned int newcols, unsigned int newrows) fh = sisusb->current_font_height; - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); /* We are quite unflexible as regards resizing. The vt code * handles sizes where the line length isn't equal the pitch @@ -1167,7 +1168,7 @@ sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot, if ((slot != 0 && slot != 2) || !fh) { if (uplock) - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return -EINVAL; } @@ -1327,7 +1328,7 @@ sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot, } if (uplock) - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); if (dorecalc && c) { int i, rows = c->vc_scan_lines / fh; @@ -1351,7 +1352,7 @@ sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot, font_op_error: if (uplock) - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return -EIO; } @@ -1417,19 +1418,19 @@ sisusbcon_font_get(struct vc_data *c, struct console_font *font) font->charcount = 256; if (!font->data) { - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return 0; } if (!sisusb->font_backup) { - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return -ENODEV; } /* Copy 256 chars only, like vgacon */ memcpy(font->data, sisusb->font_backup, 256 * 32); - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return 0; } @@ -1512,14 +1513,14 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last) { int i, ret, minor = sisusb->minor; - down(&disconnect_sem); + mutex_lock(&disconnect_mutex); - down(&sisusb->lock); + mutex_lock(&sisusb->lock); /* Erm.. that should not happen */ if (sisusb->haveconsole || !sisusb->SiS_Pr) { - up(&sisusb->lock); - up(&disconnect_sem); + mutex_unlock(&sisusb->lock); + mutex_unlock(&disconnect_mutex); return 1; } @@ -1529,15 +1530,15 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last) if (first > last || first > MAX_NR_CONSOLES || last > MAX_NR_CONSOLES) { - up(&sisusb->lock); - up(&disconnect_sem); + mutex_unlock(&sisusb->lock); + mutex_unlock(&disconnect_mutex); return 1; } /* If gfxcore not initialized or no consoles given, quit graciously */ if (!sisusb->gfxinit || first < 1 || last < 1) { - up(&sisusb->lock); - up(&disconnect_sem); + mutex_unlock(&sisusb->lock); + mutex_unlock(&disconnect_mutex); return 0; } @@ -1547,8 +1548,8 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last) /* Set up text mode (and upload default font) */ if (sisusb_reset_text_mode(sisusb, 1)) { - up(&sisusb->lock); - up(&disconnect_sem); + mutex_unlock(&sisusb->lock); + mutex_unlock(&disconnect_mutex); printk(KERN_ERR "sisusbvga[%d]: Failed to set up text mode\n", minor); @@ -1571,16 +1572,16 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last) /* Allocate screen buffer */ if (!(sisusb->scrbuf = (unsigned long)vmalloc(sisusb->scrbuf_size))) { - up(&sisusb->lock); - up(&disconnect_sem); + mutex_unlock(&sisusb->lock); + mutex_unlock(&disconnect_mutex); printk(KERN_ERR "sisusbvga[%d]: Failed to allocate screen buffer\n", minor); return 1; } - up(&sisusb->lock); - up(&disconnect_sem); + mutex_unlock(&sisusb->lock); + mutex_unlock(&disconnect_mutex); /* Now grab the desired console(s) */ ret = take_over_console(&sisusb_con, first - 1, last - 1, 0); -- cgit v1.2.3 From df47e5330b0f5decb0a5736e9a81fff49d46d151 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sat, 15 Apr 2006 11:17:27 +0200 Subject: [PATCH] USB: sisusbvga: possible cleanups This patch contains the following possible cleanups: - make needlessly global functions static - function and struct declarations belong into header files - make SiS_VCLKData const - #if 0 the following unused global functions: - sisusb.c: sisusb_writew() - sisusb.c: sisusb_readw() - sisusb_init.c: SiSUSB_GetModeID() Signed-off-by: Adrian Bunk Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/sisusbvga/sisusb.c | 50 +++--------------------------- drivers/usb/misc/sisusbvga/sisusb_con.c | 24 ++------------ drivers/usb/misc/sisusbvga/sisusb_init.c | 4 ++- drivers/usb/misc/sisusbvga/sisusb_init.h | 20 ++++++++++-- drivers/usb/misc/sisusbvga/sisusb_struct.h | 2 +- 5 files changed, 28 insertions(+), 72 deletions(-) diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index 19aedbc85ea..738bd7c7451 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c @@ -53,6 +53,7 @@ #include #include "sisusb.h" +#include "sisusb_init.h" #ifdef INCL_SISUSB_CON #include @@ -63,36 +64,6 @@ /* Forward declarations / clean-up routines */ #ifdef INCL_SISUSB_CON -int sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data); -int sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data); -int sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data); -int sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data); -int sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand, u8 myor); -int sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor); -int sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand); - -int sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data); -int sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data); -int sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data); -int sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data); -int sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src, - u32 dest, int length, size_t *bytes_written); - -int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init); - -extern int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo); -extern int SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo); - -extern void sisusb_init_concode(void); -extern int sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last); -extern void sisusb_console_exit(struct sisusb_usb_data *sisusb); - -extern void sisusb_set_cursor(struct sisusb_usb_data *sisusb, unsigned int location); - -extern int sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot, - u8 *arg, int cmapsz, int ch512, int dorecalc, - struct vc_data *c, int fh, int uplock); - static int sisusb_first_vc = 0; static int sisusb_last_vc = 0; module_param_named(first, sisusb_first_vc, int, 0); @@ -1360,9 +1331,6 @@ sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data) } #endif -#ifndef INCL_SISUSB_CON -static -#endif int sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data) { @@ -1372,9 +1340,6 @@ sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data) return ret; } -#ifndef INCL_SISUSB_CON -static -#endif int sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data) { @@ -1384,9 +1349,6 @@ sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data) return ret; } -#ifndef INCL_SISUSB_CON -static -#endif int sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand, u8 myor) @@ -1416,18 +1378,12 @@ sisusb_setidxregmask(struct sisusb_usb_data *sisusb, int port, u8 idx, return ret; } -#ifndef INCL_SISUSB_CON -static -#endif int sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor) { return(sisusb_setidxregandor(sisusb, port, index, 0xff, myor)); } -#ifndef INCL_SISUSB_CON -static -#endif int sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand) { @@ -1449,6 +1405,8 @@ sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data) return(sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data)); } +#if 0 + int sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data) { @@ -1461,6 +1419,8 @@ sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data) return(sisusb_read_memio_word(sisusb, SISUSB_TYPE_MEM, adr, data)); } +#endif /* 0 */ + int sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src, u32 dest, int length, size_t *bytes_written) diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c index 092281c172a..fb48feca835 100644 --- a/drivers/usb/misc/sisusbvga/sisusb_con.c +++ b/drivers/usb/misc/sisusbvga/sisusb_con.c @@ -70,27 +70,9 @@ #include #include "sisusb.h" +#include "sisusb_init.h" #ifdef INCL_SISUSB_CON -extern int sisusb_setreg(struct sisusb_usb_data *, int, u8); -extern int sisusb_getreg(struct sisusb_usb_data *, int, u8 *); -extern int sisusb_setidxreg(struct sisusb_usb_data *, int, u8, u8); -extern int sisusb_getidxreg(struct sisusb_usb_data *, int, u8, u8 *); -extern int sisusb_setidxregor(struct sisusb_usb_data *, int, u8, u8); -extern int sisusb_setidxregand(struct sisusb_usb_data *, int, u8, u8); -extern int sisusb_setidxregandor(struct sisusb_usb_data *, int, u8, u8, u8); - -extern int sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data); -extern int sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data); -extern int sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data); -extern int sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data); -extern int sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src, - u32 dest, int length, size_t *bytes_written); - -extern void sisusb_delete(struct kref *kref); -extern int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init); - -extern int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo); #define sisusbcon_writew(val, addr) (*(addr) = (val)) #define sisusbcon_readw(addr) (*(addr)) @@ -103,8 +85,6 @@ static struct sisusb_usb_data *mysisusbs[MAX_NR_CONSOLES]; /* Forward declaration */ static const struct consw sisusb_con; -extern struct mutex disconnect_mutex; - static inline void sisusbcon_memsetw(u16 *s, u16 c, unsigned int count) { @@ -1487,7 +1467,7 @@ static int sisusbdummycon_dummy(void) #define SISUSBCONDUMMY (void *)sisusbdummycon_dummy -const struct consw sisusb_dummy_con = { +static const struct consw sisusb_dummy_con = { .owner = THIS_MODULE, .con_startup = sisusbdummycon_startup, .con_init = sisusbdummycon_init, diff --git a/drivers/usb/misc/sisusbvga/sisusb_init.c b/drivers/usb/misc/sisusbvga/sisusb_init.c index 044fa4482f9..968f0d38cff 100644 --- a/drivers/usb/misc/sisusbvga/sisusb_init.c +++ b/drivers/usb/misc/sisusbvga/sisusb_init.c @@ -74,6 +74,7 @@ SiSUSB_InitPtr(struct SiS_Private *SiS_Pr) /* HELPER: Get ModeID */ /*********************************************/ +#if 0 unsigned short SiSUSB_GetModeID(int HDisplay, int VDisplay, int Depth) { @@ -157,6 +158,7 @@ SiSUSB_GetModeID(int HDisplay, int VDisplay, int Depth) return ModeIndex; } +#endif /* 0 */ /*********************************************/ /* HELPER: SetReg, GetReg */ @@ -233,7 +235,7 @@ SiS_DisplayOn(struct SiS_Private *SiS_Pr) /* HELPER: Init Port Addresses */ /*********************************************/ -void +static void SiSUSBRegInit(struct SiS_Private *SiS_Pr, unsigned long BaseAddr) { SiS_Pr->SiS_P3c4 = BaseAddr + 0x14; diff --git a/drivers/usb/misc/sisusbvga/sisusb_init.h b/drivers/usb/misc/sisusbvga/sisusb_init.h index 5b11577835c..f05f83268af 100644 --- a/drivers/usb/misc/sisusbvga/sisusb_init.h +++ b/drivers/usb/misc/sisusbvga/sisusb_init.h @@ -690,7 +690,7 @@ static const struct SiS_CRT1Table SiSUSB_CRT1Table[] = 0x41}} /* 0x54 */ }; -static struct SiS_VCLKData SiSUSB_VCLKData[] = +static const struct SiS_VCLKData SiSUSB_VCLKData[] = { { 0x1b,0xe1, 25}, /* 0x00 */ { 0x4e,0xe4, 28}, /* 0x01 */ @@ -808,8 +808,8 @@ static struct SiS_VCLKData SiSUSB_VCLKData[] = { 0x2b,0xc2, 35} /* 0x71 768@576@60 */ }; -void SiSUSBRegInit(struct SiS_Private *SiS_Pr, unsigned long BaseAddr); -unsigned short SiSUSB_GetModeID(int HDisplay, int VDisplay, int Depth); +extern struct mutex disconnect_mutex; + int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo); int SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo); @@ -826,5 +826,19 @@ extern int sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, extern int sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand); +void sisusb_delete(struct kref *kref); +int sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data); +int sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data); +int sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src, + u32 dest, int length, size_t *bytes_written); +int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init); +int sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot, + u8 *arg, int cmapsz, int ch512, int dorecalc, + struct vc_data *c, int fh, int uplock); +void sisusb_set_cursor(struct sisusb_usb_data *sisusb, unsigned int location); +int sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last); +void sisusb_console_exit(struct sisusb_usb_data *sisusb); +void sisusb_init_concode(void); + #endif diff --git a/drivers/usb/misc/sisusbvga/sisusb_struct.h b/drivers/usb/misc/sisusbvga/sisusb_struct.h index 94edd4726c4..f325ecb29a6 100644 --- a/drivers/usb/misc/sisusbvga/sisusb_struct.h +++ b/drivers/usb/misc/sisusbvga/sisusb_struct.h @@ -161,7 +161,7 @@ struct SiS_Private const struct SiS_Ext *SiS_EModeIDTable; const struct SiS_Ext2 *SiS_RefIndex; const struct SiS_CRT1Table *SiS_CRT1Table; - struct SiS_VCLKData *SiS_VCLKData; + const struct SiS_VCLKData *SiS_VCLKData; const struct SiS_ModeResInfo *SiS_ModeResInfo; }; -- cgit v1.2.3 From 01cced250722d22d99c2342979490f93ca886521 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Tue, 11 Apr 2006 10:07:16 -0500 Subject: [PATCH] USB: allow multiple types of EHCI controllers to be built as modules In some systems we may have both a platform EHCI controller and PCI EHCI controller. Previously we couldn't build the EHCI support as a module due to conflicting module_init() calls in the code. Signed-off-by: Kumar Gala Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/sysdev/fsl_soc.c | 66 +++++++++++++++------------------------ arch/ppc/syslib/mpc83xx_devices.c | 6 ++-- drivers/usb/host/ehci-au1xxx.c | 17 ++-------- drivers/usb/host/ehci-fsl.c | 37 ++-------------------- drivers/usb/host/ehci-hcd.c | 48 +++++++++++++++++++++++++--- drivers/usb/host/ehci-pci.c | 20 ------------ 6 files changed, 78 insertions(+), 116 deletions(-) diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c index ceb584682fa..71a3275935e 100644 --- a/arch/powerpc/sysdev/fsl_soc.c +++ b/arch/powerpc/sysdev/fsl_soc.c @@ -372,7 +372,7 @@ static int __init fsl_usb_of_init(void) { struct device_node *np; unsigned int i; - struct platform_device *usb_dev; + struct platform_device *usb_dev_mph = NULL, *usb_dev_dr = NULL; int ret; for (np = NULL, i = 0; @@ -393,15 +393,15 @@ static int __init fsl_usb_of_init(void) r[1].end = np->intrs[0].line; r[1].flags = IORESOURCE_IRQ; - usb_dev = - platform_device_register_simple("fsl-usb2-mph", i, r, 2); - if (IS_ERR(usb_dev)) { - ret = PTR_ERR(usb_dev); + usb_dev_mph = + platform_device_register_simple("fsl-ehci", i, r, 2); + if (IS_ERR(usb_dev_mph)) { + ret = PTR_ERR(usb_dev_mph); goto err; } - usb_dev->dev.coherent_dma_mask = 0xffffffffUL; - usb_dev->dev.dma_mask = &usb_dev->dev.coherent_dma_mask; + usb_dev_mph->dev.coherent_dma_mask = 0xffffffffUL; + usb_dev_mph->dev.dma_mask = &usb_dev_mph->dev.coherent_dma_mask; usb_data.operating_mode = FSL_USB2_MPH_HOST; @@ -417,31 +417,14 @@ static int __init fsl_usb_of_init(void) usb_data.phy_mode = determine_usb_phy(prop); ret = - platform_device_add_data(usb_dev, &usb_data, + platform_device_add_data(usb_dev_mph, &usb_data, sizeof(struct fsl_usb2_platform_data)); if (ret) - goto unreg; + goto unreg_mph; } - return 0; - -unreg: - platform_device_unregister(usb_dev); -err: - return ret; -} - -arch_initcall(fsl_usb_of_init); - -static int __init fsl_usb_dr_of_init(void) -{ - struct device_node *np; - unsigned int i; - struct platform_device *usb_dev; - int ret; - - for (np = NULL, i = 0; + for (np = NULL; (np = of_find_compatible_node(np, "usb", "fsl-usb2-dr")) != NULL; i++) { struct resource r[2]; @@ -453,21 +436,21 @@ static int __init fsl_usb_dr_of_init(void) ret = of_address_to_resource(np, 0, &r[0]); if (ret) - goto err; + goto unreg_mph; r[1].start = np->intrs[0].line; r[1].end = np->intrs[0].line; r[1].flags = IORESOURCE_IRQ; - usb_dev = - platform_device_register_simple("fsl-usb2-dr", i, r, 2); - if (IS_ERR(usb_dev)) { - ret = PTR_ERR(usb_dev); + usb_dev_dr = + platform_device_register_simple("fsl-ehci", i, r, 2); + if (IS_ERR(usb_dev_dr)) { + ret = PTR_ERR(usb_dev_dr); goto err; } - usb_dev->dev.coherent_dma_mask = 0xffffffffUL; - usb_dev->dev.dma_mask = &usb_dev->dev.coherent_dma_mask; + usb_dev_dr->dev.coherent_dma_mask = 0xffffffffUL; + usb_dev_dr->dev.dma_mask = &usb_dev_dr->dev.coherent_dma_mask; usb_data.operating_mode = FSL_USB2_DR_HOST; @@ -475,19 +458,22 @@ static int __init fsl_usb_dr_of_init(void) usb_data.phy_mode = determine_usb_phy(prop); ret = - platform_device_add_data(usb_dev, &usb_data, + platform_device_add_data(usb_dev_dr, &usb_data, sizeof(struct fsl_usb2_platform_data)); if (ret) - goto unreg; + goto unreg_dr; } - return 0; -unreg: - platform_device_unregister(usb_dev); +unreg_dr: + if (usb_dev_dr) + platform_device_unregister(usb_dev_dr); +unreg_mph: + if (usb_dev_mph) + platform_device_unregister(usb_dev_mph); err: return ret; } -arch_initcall(fsl_usb_dr_of_init); +arch_initcall(fsl_usb_of_init); diff --git a/arch/ppc/syslib/mpc83xx_devices.c b/arch/ppc/syslib/mpc83xx_devices.c index 1af2c000fcf..5c4932ca8e9 100644 --- a/arch/ppc/syslib/mpc83xx_devices.c +++ b/arch/ppc/syslib/mpc83xx_devices.c @@ -186,7 +186,7 @@ struct platform_device ppc_sys_platform_devices[] = { }, }, [MPC83xx_USB2_DR] = { - .name = "fsl-usb2-dr", + .name = "fsl-ehci", .id = 1, .num_resources = 2, .resource = (struct resource[]) { @@ -203,8 +203,8 @@ struct platform_device ppc_sys_platform_devices[] = { }, }, [MPC83xx_USB2_MPH] = { - .name = "fsl-usb2-mph", - .id = 1, + .name = "fsl-ehci", + .id = 2, .num_resources = 2, .resource = (struct resource[]) { { diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c index 63eadeec132..0e444ab1930 100644 --- a/drivers/usb/host/ehci-au1xxx.c +++ b/drivers/usb/host/ehci-au1xxx.c @@ -272,6 +272,8 @@ static int ehci_hcd_au1xxx_drv_resume(struct device *dev) return 0; } */ +MODULE_ALIAS("au1xxx-ehci"); +/* FIXME use "struct platform_driver" */ static struct device_driver ehci_hcd_au1xxx_driver = { .name = "au1xxx-ehci", .bus = &platform_bus_type, @@ -280,18 +282,3 @@ static struct device_driver ehci_hcd_au1xxx_driver = { /*.suspend = ehci_hcd_au1xxx_drv_suspend, */ /*.resume = ehci_hcd_au1xxx_drv_resume, */ }; - -static int __init ehci_hcd_au1xxx_init(void) -{ - pr_debug(DRIVER_INFO " (Au1xxx)\n"); - - return driver_register(&ehci_hcd_au1xxx_driver); -} - -static void __exit ehci_hcd_au1xxx_cleanup(void) -{ - driver_unregister(&ehci_hcd_au1xxx_driver); -} - -module_init(ehci_hcd_au1xxx_init); -module_exit(ehci_hcd_au1xxx_cleanup); diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index f985f121a24..a49a689bf42 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -324,43 +324,12 @@ static int ehci_fsl_drv_remove(struct platform_device *pdev) return 0; } -static struct platform_driver ehci_fsl_dr_driver = { - .probe = ehci_fsl_drv_probe, - .remove = ehci_fsl_drv_remove, - .driver = { - .name = "fsl-usb2-dr", - }, -}; +MODULE_ALIAS("fsl-ehci"); -static struct platform_driver ehci_fsl_mph_driver = { +static struct platform_driver ehci_fsl_driver = { .probe = ehci_fsl_drv_probe, .remove = ehci_fsl_drv_remove, .driver = { - .name = "fsl-usb2-mph", + .name = "fsl-ehci", }, }; - -static int __init ehci_fsl_init(void) -{ - int retval; - - pr_debug("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n", - hcd_name, - sizeof(struct ehci_qh), sizeof(struct ehci_qtd), - sizeof(struct ehci_itd), sizeof(struct ehci_sitd)); - - retval = platform_driver_register(&ehci_fsl_dr_driver); - if (retval) - return retval; - - return platform_driver_register(&ehci_fsl_mph_driver); -} - -static void __exit ehci_fsl_cleanup(void) -{ - platform_driver_unregister(&ehci_fsl_mph_driver); - platform_driver_unregister(&ehci_fsl_dr_driver); -} - -module_init(ehci_fsl_init); -module_exit(ehci_fsl_cleanup); diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 79f2d8b9bfb..7d7c97cf9b2 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -889,19 +889,59 @@ MODULE_LICENSE ("GPL"); #ifdef CONFIG_PCI #include "ehci-pci.c" -#define EHCI_BUS_GLUED +#define PCI_DRIVER ehci_pci_driver #endif #ifdef CONFIG_PPC_83xx #include "ehci-fsl.c" -#define EHCI_BUS_GLUED +#define PLATFORM_DRIVER ehci_fsl_driver #endif #ifdef CONFIG_SOC_AU1X00 #include "ehci-au1xxx.c" -#define EHCI_BUS_GLUED +#define PLATFORM_DRIVER ehci_hcd_au1xxx_driver #endif -#ifndef EHCI_BUS_GLUED +#if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) #error "missing bus glue for ehci-hcd" #endif + +static int __init ehci_hcd_init(void) +{ + int retval = 0; + + pr_debug("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n", + hcd_name, + sizeof(struct ehci_qh), sizeof(struct ehci_qtd), + sizeof(struct ehci_itd), sizeof(struct ehci_sitd)); + +#ifdef PLATFORM_DRIVER + retval = platform_driver_register(&PLATFORM_DRIVER); + if (retval < 0) + return retval; +#endif + +#ifdef PCI_DRIVER + retval = pci_register_driver(&PCI_DRIVER); + if (retval < 0) { +#ifdef PLATFORM_DRIVER + platform_driver_unregister(&PLATFORM_DRIVER); +#endif + } +#endif + + return retval; +} +module_init(ehci_hcd_init); + +static void __exit ehci_hcd_cleanup(void) +{ +#ifdef PLATFORM_DRIVER + platform_driver_unregister(&PLATFORM_DRIVER); +#endif +#ifdef PCI_DRIVER + pci_unregister_driver(&PCI_DRIVER); +#endif +} +module_exit(ehci_hcd_cleanup); + diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 648ddb52d57..cadffacd945 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -379,23 +379,3 @@ static struct pci_driver ehci_pci_driver = { .resume = usb_hcd_pci_resume, #endif }; - -static int __init ehci_hcd_pci_init(void) -{ - if (usb_disabled()) - return -ENODEV; - - pr_debug("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n", - hcd_name, - sizeof(struct ehci_qh), sizeof(struct ehci_qtd), - sizeof(struct ehci_itd), sizeof(struct ehci_sitd)); - - return pci_register_driver(&ehci_pci_driver); -} -module_init(ehci_hcd_pci_init); - -static void __exit ehci_hcd_pci_cleanup(void) -{ - pci_unregister_driver(&ehci_pci_driver); -} -module_exit(ehci_hcd_pci_cleanup); -- cgit v1.2.3 From c10746dbb39d41e5fc27badfebe61448210c426d Mon Sep 17 00:00:00 2001 From: Paul Fulghum Date: Thu, 13 Apr 2006 22:26:35 +0200 Subject: [PATCH] USB: console: fix cr/lf issues Append Carriage-Returns after Line-Feeds, analogous to the serial driver. From: Paul Fulghum Signed-off-by: Guennadi Liakhovetski Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/console.c | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index 8023bb7279b..fc4a0f731d9 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c @@ -213,17 +213,38 @@ static void usb_console_write(struct console *co, const char *buf, unsigned coun if (!port->open_count) { dbg ("%s - port not opened", __FUNCTION__); - goto exit; + return; } - /* pass on to the driver specific version of this function if it is available */ - if (serial->type->write) - retval = serial->type->write(port, buf, count); - else - retval = usb_serial_generic_write(port, buf, count); - -exit: - dbg("%s - return value (if we had one): %d", __FUNCTION__, retval); + while (count) { + unsigned int i; + unsigned int lf; + /* search for LF so we can insert CR if necessary */ + for (i=0, lf=0 ; i < count ; i++) { + if (*(buf + i) == 10) { + lf = 1; + i++; + break; + } + } + /* pass on to the driver specific version of this function if it is available */ + if (serial->type->write) + retval = serial->type->write(port, buf, i); + else + retval = usb_serial_generic_write(port, buf, i); + dbg("%s - return value : %d", __FUNCTION__, retval); + if (lf) { + /* append CR after LF */ + unsigned char cr = 13; + if (serial->type->write) + retval = serial->type->write(port, &cr, 1); + else + retval = usb_serial_generic_write(port, &cr, 1); + dbg("%s - return value : %d", __FUNCTION__, retval); + } + buf += i; + count -= i; + } } static struct console usbcons = { -- cgit v1.2.3 From 57845bd104233cb75b9ab3624f7ea7662298bc27 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 13 Apr 2006 22:27:12 +0200 Subject: [PATCH] USB: console: fix oops Prevent NULL dereference when used as a USB-serial console. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 986d7622273..1122a0da41c 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1261,7 +1261,6 @@ static void ftdi_shutdown (struct usb_serial *serial) static int ftdi_open (struct usb_serial_port *port, struct file *filp) { /* ftdi_open */ - struct termios tmp_termios; struct usb_device *dev = port->serial->dev; struct ftdi_private *priv = usb_get_serial_port_data(port); unsigned long flags; @@ -1271,8 +1270,8 @@ static int ftdi_open (struct usb_serial_port *port, struct file *filp) dbg("%s", __FUNCTION__); - - port->tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0; + if (port->tty) + port->tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0; /* No error checking for this (will get errors later anyway) */ /* See ftdi_sio.h for description of what is reset */ @@ -1286,7 +1285,8 @@ static int ftdi_open (struct usb_serial_port *port, struct file *filp) This is same behaviour as serial.c/rs_open() - Kuba */ /* ftdi_set_termios will send usb control messages */ - ftdi_set_termios(port, &tmp_termios); + if (port->tty) + ftdi_set_termios(port, NULL); /* FIXME: Flow control might be enabled, so it should be checked - we have no control of defaults! */ @@ -1867,7 +1867,7 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct termios *old_ err("%s urb failed to set baudrate", __FUNCTION__); } /* Ensure RTS and DTR are raised when baudrate changed from 0 */ - if ((old_termios->c_cflag & CBAUD) == B0) { + if (!old_termios || (old_termios->c_cflag & CBAUD) == B0) { set_mctrl(port, TIOCM_DTR | TIOCM_RTS); } } -- cgit v1.2.3 From ca85485c1f482e6625f36aceb85eaaeff4b22d79 Mon Sep 17 00:00:00 2001 From: Paul Fulghum Date: Thu, 13 Apr 2006 22:28:17 +0200 Subject: [PATCH] USB: console: prevent ENODEV on node Prevent ENODEV on a /dev/ttyUSBx, used as a USB-serial console. From: Paul Fulghum Signed-off-by: Guennadi Liakhovetski Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb-serial.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 9c36f0ece20..de9111d97a5 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -201,12 +201,12 @@ static int serial_open (struct tty_struct *tty, struct file * filp) ++port->open_count; - if (port->open_count == 1) { + /* set up our port structure making the tty driver + * remember our port object, and us it */ + tty->driver_data = port; + port->tty = tty; - /* set up our port structure making the tty driver - * remember our port object, and us it */ - tty->driver_data = port; - port->tty = tty; + if (port->open_count == 1) { /* lock this module before we call it * this may fail, which means we must bail out, -- cgit v1.2.3 From 73e487fdb75f8abf230968dbf73a3dc3b16808d3 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Apr 2006 07:46:17 +0200 Subject: [PATCH] USB console: fix disconnection issues Prevent sending further output to a USB-serial console after the dongle is disconnected, take care not to leak kref. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/console.c | 17 +++++++++++++++-- drivers/usb/serial/usb-serial.c | 16 +++++++++++----- drivers/usb/serial/usb-serial.h | 3 +++ 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index fc4a0f731d9..f3404e10afb 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c @@ -202,7 +202,7 @@ static void usb_console_write(struct console *co, const char *buf, unsigned coun struct usb_serial *serial; int retval = -ENODEV; - if (!port) + if (!port || port->serial->dev->state == USB_STATE_NOTATTACHED) return; serial = port->serial; @@ -255,6 +255,14 @@ static struct console usbcons = { .index = -1, }; +void usb_serial_console_disconnect(struct usb_serial *serial) +{ + if (serial && serial->port && serial->port[0] && serial->port[0] == usbcons_info.port) { + usb_serial_console_exit(); + usb_serial_put(serial); + } +} + void usb_serial_console_init (int serial_debug, int minor) { debug = serial_debug; @@ -280,6 +288,11 @@ void usb_serial_console_init (int serial_debug, int minor) void usb_serial_console_exit (void) { - unregister_console(&usbcons); + if (usbcons_info.port) { + unregister_console(&usbcons); + if (usbcons_info.port->open_count) + usbcons_info.port->open_count--; + usbcons_info.port = NULL; + } } diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index de9111d97a5..92200f05b53 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -168,6 +168,11 @@ static void destroy_serial(struct kref *kref) kfree (serial); } +void usb_serial_put(struct usb_serial *serial) +{ + kref_put(&serial->kref, destroy_serial); +} + /***************************************************************************** * Driver tty interface functions *****************************************************************************/ @@ -232,7 +237,7 @@ bailout_mutex_unlock: port->open_count = 0; mutex_unlock(&port->mutex); bailout_kref_put: - kref_put(&serial->kref, destroy_serial); + usb_serial_put(serial); return retval; } @@ -268,7 +273,7 @@ static void serial_close(struct tty_struct *tty, struct file * filp) } mutex_unlock(&port->mutex); - kref_put(&port->serial->kref, destroy_serial); + usb_serial_put(port->serial); } static int serial_write (struct tty_struct * tty, const unsigned char *buf, int count) @@ -276,7 +281,7 @@ static int serial_write (struct tty_struct * tty, const unsigned char *buf, int struct usb_serial_port *port = tty->driver_data; int retval = -EINVAL; - if (!port) + if (!port || port->serial->dev->state == USB_STATE_NOTATTACHED) goto exit; dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count); @@ -473,7 +478,7 @@ static int serial_read_proc (char *page, char **start, off_t off, int count, int begin += length; length = 0; } - kref_put(&serial->kref, destroy_serial); + usb_serial_put(serial); } *eof = 1; done: @@ -985,6 +990,7 @@ void usb_serial_disconnect(struct usb_interface *interface) struct device *dev = &interface->dev; struct usb_serial_port *port; + usb_serial_console_disconnect(serial); dbg ("%s", __FUNCTION__); usb_set_intfdata (interface, NULL); @@ -996,7 +1002,7 @@ void usb_serial_disconnect(struct usb_interface *interface) } /* let the last holder of this object * cause it to be cleaned up */ - kref_put(&serial->kref, destroy_serial); + usb_serial_put(serial); } dev_info(dev, "device disconnected\n"); } diff --git a/drivers/usb/serial/usb-serial.h b/drivers/usb/serial/usb-serial.h index dc89d871046..c07ece3fef1 100644 --- a/drivers/usb/serial/usb-serial.h +++ b/drivers/usb/serial/usb-serial.h @@ -248,13 +248,16 @@ extern int ezusb_set_reset (struct usb_serial *serial, unsigned char reset_bit); #ifdef CONFIG_USB_SERIAL_CONSOLE extern void usb_serial_console_init (int debug, int minor); extern void usb_serial_console_exit (void); +extern void usb_serial_console_disconnect(struct usb_serial *serial); #else static inline void usb_serial_console_init (int debug, int minor) { } static inline void usb_serial_console_exit (void) { } +static inline void usb_serial_console_disconnect(struct usb_serial *serial) {} #endif /* Functions needed by other parts of the usbserial core */ extern struct usb_serial *usb_serial_get_by_index (unsigned int minor); +extern void usb_serial_put(struct usb_serial *serial); extern int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp); extern int usb_serial_generic_write (struct usb_serial_port *port, const unsigned char *buf, int count); extern void usb_serial_generic_close (struct usb_serial_port *port, struct file *filp); -- cgit v1.2.3 From 9effa978f1d51f6d0426ebabcf6cb32336bb3153 Mon Sep 17 00:00:00 2001 From: Nicolas Boichat Date: Wed, 19 Apr 2006 23:36:40 +0200 Subject: [PATCH] USB: MacBook Pro touchpad support Add support for MacBook touchpad in appletouch driver. Thanks to Alex Harper for the informations. Use u16 instead of int16_t in atp_is_geyser* functions. Acked-by: Johannes Berg Acked-by: Stelian Pop Signed-off-by: Nicolas Boichat Signed-off-by: Greg Kroah-Hartman --- drivers/usb/input/appletouch.c | 113 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 107 insertions(+), 6 deletions(-) diff --git a/drivers/usb/input/appletouch.c b/drivers/usb/input/appletouch.c index c222ed13dea..4eff8d7a79d 100644 --- a/drivers/usb/input/appletouch.c +++ b/drivers/usb/input/appletouch.c @@ -1,5 +1,5 @@ /* - * Apple USB Touchpad (for post-February 2005 PowerBooks) driver + * Apple USB Touchpad (for post-February 2005 PowerBooks and MacBooks) driver * * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com) * Copyright (C) 2005 Johannes Berg (johannes@sipsolutions.net) @@ -7,6 +7,7 @@ * Copyright (C) 2005 Frank Arnold (frank@scirocco-5v-turbo.de) * Copyright (C) 2005 Peter Osterlund (petero2@telia.com) * Copyright (C) 2005 Michael Hanselmann (linux-kernel@hansmi.ch) + * Copyright (C) 2006 Nicolas Boichat (nicolas@boichat.ch) * * Thanks to Alex Harper for his inputs. * @@ -44,6 +45,11 @@ #define GEYSER_ISO_PRODUCT_ID 0x0215 #define GEYSER_JIS_PRODUCT_ID 0x0216 +/* MacBook devices */ +#define GEYSER3_ANSI_PRODUCT_ID 0x0217 +#define GEYSER3_ISO_PRODUCT_ID 0x0218 +#define GEYSER3_JIS_PRODUCT_ID 0x0219 + #define ATP_DEVICE(prod) \ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ USB_DEVICE_ID_MATCH_INT_CLASS | \ @@ -65,6 +71,10 @@ static struct usb_device_id atp_table [] = { { ATP_DEVICE(GEYSER_ISO_PRODUCT_ID) }, { ATP_DEVICE(GEYSER_JIS_PRODUCT_ID) }, + { ATP_DEVICE(GEYSER3_ANSI_PRODUCT_ID) }, + { ATP_DEVICE(GEYSER3_ISO_PRODUCT_ID) }, + { ATP_DEVICE(GEYSER3_JIS_PRODUCT_ID) }, + /* Terminating entry */ { } }; @@ -101,6 +111,13 @@ MODULE_DEVICE_TABLE (usb, atp_table); */ #define ATP_THRESHOLD 5 +/* MacBook Pro (Geyser 3) initialization constants */ +#define ATP_GEYSER3_MODE_READ_REQUEST_ID 1 +#define ATP_GEYSER3_MODE_WRITE_REQUEST_ID 9 +#define ATP_GEYSER3_MODE_REQUEST_VALUE 0x300 +#define ATP_GEYSER3_MODE_REQUEST_INDEX 0 +#define ATP_GEYSER3_MODE_VENDOR_VALUE 0x04 + /* Structure to hold all of our device specific stuff */ struct atp { char phys[64]; @@ -147,13 +164,22 @@ MODULE_PARM_DESC(debug, "Activate debugging output"); /* Checks if the device a Geyser 2 (ANSI, ISO, JIS) */ static inline int atp_is_geyser_2(struct atp *dev) { - int16_t productId = le16_to_cpu(dev->udev->descriptor.idProduct); + u16 productId = le16_to_cpu(dev->udev->descriptor.idProduct); return (productId == GEYSER_ANSI_PRODUCT_ID) || (productId == GEYSER_ISO_PRODUCT_ID) || (productId == GEYSER_JIS_PRODUCT_ID); } +static inline int atp_is_geyser_3(struct atp *dev) +{ + u16 productId = le16_to_cpu(dev->udev->descriptor.idProduct); + + return (productId == GEYSER3_ANSI_PRODUCT_ID) || + (productId == GEYSER3_ISO_PRODUCT_ID) || + (productId == GEYSER3_JIS_PRODUCT_ID); +} + static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact, int *z, int *fingers) { @@ -219,12 +245,33 @@ static void atp_complete(struct urb* urb, struct pt_regs* regs) /* drop incomplete datasets */ if (dev->urb->actual_length != dev->datalen) { - dprintk("appletouch: incomplete data package.\n"); + dprintk("appletouch: incomplete data package" + " (first byte: %d, length: %d).\n", + dev->data[0], dev->urb->actual_length); goto exit; } /* reorder the sensors values */ - if (atp_is_geyser_2(dev)) { + if (atp_is_geyser_3(dev)) { + memset(dev->xy_cur, 0, sizeof(dev->xy_cur)); + + /* + * The values are laid out like this: + * -, Y1, Y2, -, Y3, Y4, -, ..., -, X1, X2, -, X3, X4, ... + * '-' is an unused value. + */ + + /* read X values */ + for (i = 0, j = 19; i < 20; i += 2, j += 3) { + dev->xy_cur[i] = dev->data[j + 1]; + dev->xy_cur[i + 1] = dev->data[j + 2]; + } + /* read Y values */ + for (i = 0, j = 1; i < 9; i += 2, j += 3) { + dev->xy_cur[ATP_XSENSORS + i] = dev->data[j + 1]; + dev->xy_cur[ATP_XSENSORS + i + 1] = dev->data[j + 2]; + } + } else if (atp_is_geyser_2(dev)) { memset(dev->xy_cur, 0, sizeof(dev->xy_cur)); /* @@ -267,6 +314,9 @@ static void atp_complete(struct urb* urb, struct pt_regs* regs) dev->x_old = dev->y_old = -1; memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old)); + if (atp_is_geyser_3(dev)) /* No 17" Macbooks (yet) */ + goto exit; + /* 17" Powerbooks have extra X sensors */ for (i = (atp_is_geyser_2(dev)?15:16); i < ATP_XSENSORS; i++) { if (!dev->xy_cur[i]) continue; @@ -414,7 +464,50 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id dev->udev = udev; dev->input = input_dev; dev->overflowwarn = 0; - dev->datalen = (atp_is_geyser_2(dev)?64:81); + if (atp_is_geyser_3(dev)) + dev->datalen = 64; + else if (atp_is_geyser_2(dev)) + dev->datalen = 64; + else + dev->datalen = 81; + + if (atp_is_geyser_3(dev)) { + /* + * By default Geyser 3 device sends standard USB HID mouse + * packets (Report ID 2). This code changes device mode, so it + * sends raw sensor reports (Report ID 5). + */ + char data[8]; + int size; + + size = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + ATP_GEYSER3_MODE_READ_REQUEST_ID, + USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, + ATP_GEYSER3_MODE_REQUEST_VALUE, + ATP_GEYSER3_MODE_REQUEST_INDEX, &data, 8, 5000); + + if (size != 8) { + err("Could not do mode read request from device" + " (Geyser 3 mode)"); + goto err_free_devs; + } + + /* Apply the mode switch */ + data[0] = ATP_GEYSER3_MODE_VENDOR_VALUE; + + size = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + ATP_GEYSER3_MODE_WRITE_REQUEST_ID, + USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, + ATP_GEYSER3_MODE_REQUEST_VALUE, + ATP_GEYSER3_MODE_REQUEST_INDEX, &data, 8, 5000); + + if (size != 8) { + err("Could not do mode write request to device" + " (Geyser 3 mode)"); + goto err_free_devs; + } + printk("appletouch Geyser 3 inited.\n"); + } dev->urb = usb_alloc_urb(0, GFP_KERNEL); if (!dev->urb) { @@ -447,7 +540,15 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id set_bit(EV_ABS, input_dev->evbit); - if (atp_is_geyser_2(dev)) { + if (atp_is_geyser_3(dev)) { + /* + * MacBook have 20 X sensors, 10 Y sensors + */ + input_set_abs_params(input_dev, ABS_X, 0, + ((20 - 1) * ATP_XFACT) - 1, ATP_FUZZ, 0); + input_set_abs_params(input_dev, ABS_Y, 0, + ((10 - 1) * ATP_YFACT) - 1, ATP_FUZZ, 0); + } else if (atp_is_geyser_2(dev)) { /* * Oct 2005 15" PowerBooks have 15 X sensors, 17" are detected * later. -- cgit v1.2.3 From 4489a5712b086621a6c3f669057d2996245cd3fb Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 27 Apr 2006 15:54:22 -0400 Subject: [PATCH] USB: usbcore: always turn on hub port power Some hubs claim not to support port-power switching, and right now the hub driver believes them and does not enable power to their ports. However it turns out that even though they don't actually switch power, they do ignore all events on a port until told to turn on the power! This problem has been reported by several users. This revised patch (as672b) makes the hub driver always try to turn on port power to all hubs, regardless of what the hub descriptor says. It also adds a comment explaining the need for this. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 90b8d43c6b3..1b1846e6473 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -432,15 +432,22 @@ static void hub_power_on(struct usb_hub *hub) { int port1; unsigned pgood_delay = hub->descriptor->bPwrOn2PwrGood * 2; - u16 wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics); - - /* if hub supports power switching, enable power on each port */ - if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2) { + u16 wHubCharacteristics = + le16_to_cpu(hub->descriptor->wHubCharacteristics); + + /* Enable power on each port. Some hubs have reserved values + * of LPSM (> 2) in their descriptors, even though they are + * USB 2.0 hubs. Some hubs do not implement port-power switching + * but only emulate it. In all cases, the ports won't work + * unless we send these messages to the hub. + */ + if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2) dev_dbg(hub->intfdev, "enabling power on all ports\n"); - for (port1 = 1; port1 <= hub->descriptor->bNbrPorts; port1++) - set_port_feature(hub->hdev, port1, - USB_PORT_FEAT_POWER); - } + else + dev_dbg(hub->intfdev, "trying to enable port power on " + "non-switchable hub\n"); + for (port1 = 1; port1 <= hub->descriptor->bNbrPorts; port1++) + set_port_feature(hub->hdev, port1, USB_PORT_FEAT_POWER); /* Wait at least 100 msec for power to become stable */ msleep(max(pgood_delay, (unsigned) 100)); -- cgit v1.2.3 From 41fea55e0382b7d59d694d8055b39aa69c793b1f Mon Sep 17 00:00:00 2001 From: Pete Zaitcev Date: Fri, 28 Apr 2006 20:45:49 -0700 Subject: [PATCH] USB: clean out an unnecessary NULL check from ub Remove the check for NULL which makes no sense. Suggested by Al. Signed-off-by: Pete Zaitcev Signed-off-by: Greg Kroah-Hartman --- drivers/block/ub.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/block/ub.c b/drivers/block/ub.c index c688c25992e..8eb44a55b9b 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c @@ -1651,15 +1651,11 @@ static void ub_revalidate(struct ub_dev *sc, struct ub_lun *lun) static int ub_bd_open(struct inode *inode, struct file *filp) { struct gendisk *disk = inode->i_bdev->bd_disk; - struct ub_lun *lun; - struct ub_dev *sc; + struct ub_lun *lun = disk->private_data; + struct ub_dev *sc = lun->udev; unsigned long flags; int rc; - if ((lun = disk->private_data) == NULL) - return -ENXIO; - sc = lun->udev; - spin_lock_irqsave(&ub_lock, flags); if (atomic_read(&sc->poison)) { spin_unlock_irqrestore(&ub_lock, flags); -- cgit v1.2.3 From fcf4830a525d37b9bd3ba60430b5729b8621062d Mon Sep 17 00:00:00 2001 From: Duncan Sands Date: Fri, 28 Apr 2006 18:53:45 +0200 Subject: [PATCH] USBATM: remove pointless inline Remove pointless inline. Signed-off-by: Duncan Sands Signed-off-by: Greg Kroah-Hartman --- drivers/usb/atm/usbatm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c index 546249843b8..a38701c742c 100644 --- a/drivers/usb/atm/usbatm.c +++ b/drivers/usb/atm/usbatm.c @@ -1039,7 +1039,7 @@ static void usbatm_tasklet_schedule(unsigned long data) tasklet_schedule((struct tasklet_struct *) data); } -static inline void usbatm_init_channel(struct usbatm_channel *channel) +static void usbatm_init_channel(struct usbatm_channel *channel) { spin_lock_init(&channel->lock); INIT_LIST_HEAD(&channel->list); -- cgit v1.2.3 From a01c4ef1cc9622fcce5c10ddb8e9e7f76206959e Mon Sep 17 00:00:00 2001 From: Duncan Sands Date: Fri, 28 Apr 2006 18:58:57 +0200 Subject: [PATCH] USBATM: remove no-longer needed #include We #include only because needed it, but didn't #include it itself. But that's been fixed now. Signed-off-by: Duncan Sands Signed-off-by: Greg Kroah-Hartman --- drivers/usb/atm/xusbatm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/atm/xusbatm.c b/drivers/usb/atm/xusbatm.c index 42d6823b82b..70125c6d3be 100644 --- a/drivers/usb/atm/xusbatm.c +++ b/drivers/usb/atm/xusbatm.c @@ -20,7 +20,6 @@ ******************************************************************************/ #include -#include /* FIXME: required by linux/etherdevice.h */ #include /* for random_ether_addr() */ #include "usbatm.h" -- cgit v1.2.3 From 69165c29bb4db9bafead7c6574c73ce245965f3a Mon Sep 17 00:00:00 2001 From: Sean Young Date: Tue, 2 May 2006 11:44:43 +0000 Subject: [PATCH] USB Phidget InterfaceKit: make inputs pollable and new device support Make inputs pollable using sysfs_notify and add support for the Phidget InterfaceKit 0/16/16. Various cleanups. Signed-off-by: Sean Young Signed-off-by: Daniel Saakes Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/phidgetkit.c | 303 ++++++++++++++++++++++++++++++------------ 1 file changed, 218 insertions(+), 85 deletions(-) diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c index 997db5d8e35..13aeea2026c 100644 --- a/drivers/usb/misc/phidgetkit.c +++ b/drivers/usb/misc/phidgetkit.c @@ -1,7 +1,8 @@ /* * USB PhidgetInterfaceKit driver 1.0 * - * Copyright (C) 2004 Sean Young + * Copyright (C) 2004, 2006 Sean Young + * Copyright (C) 2005 Daniel Saakes * Copyright (C) 2004 Greg Kroah-Hartman * * This program is free software; you can redistribute it and/or modify @@ -25,6 +26,7 @@ #define USB_VENDOR_ID_GLAB 0x06c2 #define USB_DEVICE_ID_INTERFACEKIT004 0x0040 +#define USB_DEVICE_ID_INTERFACEKIT01616 0x0044 #define USB_DEVICE_ID_INTERFACEKIT888 0x0045 #define USB_DEVICE_ID_INTERFACEKIT047 0x0051 #define USB_DEVICE_ID_INTERFACEKIT088 0x0053 @@ -32,7 +34,9 @@ #define USB_VENDOR_ID_WISEGROUP 0x0925 #define USB_DEVICE_ID_INTERFACEKIT884 0x8201 -#define MAX_INTERFACES 8 +#define MAX_INTERFACES 16 + +#define URB_INT_SIZE 8 struct driver_interfacekit { int sensors; @@ -52,19 +56,24 @@ ifkit(8, 8, 8, 0); ifkit(0, 4, 7, 1); ifkit(8, 8, 4, 0); ifkit(0, 8, 8, 1); +ifkit(0, 16, 16, 0); -struct phidget_interfacekit { +struct interfacekit { struct usb_device *udev; struct usb_interface *intf; struct driver_interfacekit *ifkit; - int outputs[MAX_INTERFACES]; - int inputs[MAX_INTERFACES]; - int sensors[MAX_INTERFACES]; + unsigned long outputs; + u8 inputs[MAX_INTERFACES]; + u16 sensors[MAX_INTERFACES]; u8 lcd_files_on; struct urb *irq; unsigned char *data; dma_addr_t data_dma; + + struct work_struct do_notify; + unsigned long input_events; + unsigned long sensor_events; }; static struct usb_device_id id_table[] = { @@ -76,33 +85,33 @@ static struct usb_device_id id_table[] = { .driver_info = (kernel_ulong_t)&ph_047}, {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT088), .driver_info = (kernel_ulong_t)&ph_088}, + {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT01616), + .driver_info = (kernel_ulong_t)&ph_01616}, {USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_INTERFACEKIT884), .driver_info = (kernel_ulong_t)&ph_884}, {} }; MODULE_DEVICE_TABLE(usb, id_table); -static int change_outputs(struct phidget_interfacekit *kit, int output_num, int enable) +static int change_outputs(struct interfacekit *kit, int output_num, int enable) { - unsigned char *buffer; + u8 *buffer; int retval; - int n; + + if (enable) + set_bit(output_num, &kit->outputs); + else + clear_bit(output_num, &kit->outputs); buffer = kzalloc(4, GFP_KERNEL); if (!buffer) { - dev_err(&kit->udev->dev, "%s - out of memory\n", - __FUNCTION__); + dev_err(&kit->udev->dev, "%s - out of memory\n", __FUNCTION__); return -ENOMEM; } + buffer[0] = (u8)kit->outputs; + buffer[1] = (u8)(kit->outputs >> 8); - kit->outputs[output_num] = enable; - for (n=0; n<8; n++) { - if (kit->outputs[n]) { - buffer[0] |= 1 << n; - } - } - - dev_dbg(&kit->udev->dev, "sending data: %02x\n", buffer[0]); + dev_dbg(&kit->udev->dev, "sending data: 0x%04x\n", (u16)kit->outputs); retval = usb_control_msg(kit->udev, usb_sndctrlpipe(kit->udev, 0), @@ -116,10 +125,10 @@ static int change_outputs(struct phidget_interfacekit *kit, int output_num, int return retval < 0 ? retval : 0; } -static int change_string(struct phidget_interfacekit *kit, const char *display, unsigned char row) +static int change_string(struct interfacekit *kit, const char *display, unsigned char row) { unsigned char *buffer; - unsigned char *form_buffer; + unsigned char *form_buffer; int retval = -ENOMEM; int i,j, len, buf_ptr; @@ -175,7 +184,7 @@ exit: static ssize_t lcd_line_##number(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ { \ struct usb_interface *intf = to_usb_interface(dev); \ - struct phidget_interfacekit *kit = usb_get_intfdata(intf); \ + struct interfacekit *kit = usb_get_intfdata(intf); \ change_string(kit, buf, number - 1); \ return count; \ } \ @@ -186,7 +195,7 @@ set_lcd_line(2); static ssize_t set_backlight(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct usb_interface *intf = to_usb_interface(dev); - struct phidget_interfacekit *kit = usb_get_intfdata(intf); + struct interfacekit *kit = usb_get_intfdata(intf); int enabled; unsigned char *buffer; int retval = -ENOMEM; @@ -220,7 +229,7 @@ exit: } static DEVICE_ATTR(backlight, S_IWUGO, NULL, set_backlight); -static void remove_lcd_files(struct phidget_interfacekit *kit) +static void remove_lcd_files(struct interfacekit *kit) { if (kit->lcd_files_on) { dev_dbg(&kit->udev->dev, "Removing lcd files\n"); @@ -233,7 +242,7 @@ static void remove_lcd_files(struct phidget_interfacekit *kit) static ssize_t enable_lcd_files(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct usb_interface *intf = to_usb_interface(dev); - struct phidget_interfacekit *kit = usb_get_intfdata(intf); + struct interfacekit *kit = usb_get_intfdata(intf); int enable; if (kit->ifkit->has_lcd == 0) @@ -263,10 +272,10 @@ static DEVICE_ATTR(lcd, S_IWUGO, NULL, enable_lcd_files); static void interfacekit_irq(struct urb *urb, struct pt_regs *regs) { - struct phidget_interfacekit *kit = urb->context; + struct interfacekit *kit = urb->context; unsigned char *buffer = kit->data; + int i, level, sensor; int status; - int n; switch (urb->status) { case 0: /* success */ @@ -280,22 +289,63 @@ static void interfacekit_irq(struct urb *urb, struct pt_regs *regs) goto resubmit; } - for (n=0; n<8; n++) { - kit->inputs[n] = buffer[1] & (1 << n) ? 1 : 0; + /* digital inputs */ + if (kit->ifkit->inputs == 16) { + for (i=0; i < 8; i++) { + level = (buffer[0] >> i) & 1; + if (kit->inputs[i] != level) { + kit->inputs[i] = level; + set_bit(i, &kit->input_events); + } + level = (buffer[1] >> i) & 1; + if (kit->inputs[8 + i] != level) { + kit->inputs[8 + i] = level; + set_bit(8 + i, &kit->input_events); + } + } + } + else if (kit->ifkit->inputs == 8) { + for (i=0; i < 8; i++) { + level = (buffer[1] >> i) & 1; + if (kit->inputs[i] != level) { + kit->inputs[i] = level; + set_bit(i, &kit->input_events); + } + } } - if (buffer[0] & 1) { - kit->sensors[4] = buffer[2] + (buffer[3] & 0x0f) * 256; - kit->sensors[5] = buffer[4] + (buffer[3] & 0xf0) * 16; - kit->sensors[6] = buffer[5] + (buffer[6] & 0x0f) * 256; - kit->sensors[7] = buffer[7] + (buffer[6] & 0xf0) * 16; - } else { - kit->sensors[0] = buffer[2] + (buffer[3] & 0x0f) * 256; - kit->sensors[1] = buffer[4] + (buffer[3] & 0xf0) * 16; - kit->sensors[2] = buffer[5] + (buffer[6] & 0x0f) * 256; - kit->sensors[3] = buffer[7] + (buffer[6] & 0xf0) * 16; + /* analog inputs */ + if (kit->ifkit->sensors) { + sensor = (buffer[0] & 1) ? 4 : 0; + + level = buffer[2] + (buffer[3] & 0x0f) * 256; + if (level != kit->sensors[sensor]) { + kit->sensors[sensor] = level; + set_bit(sensor, &kit->sensor_events); + } + sensor++; + level = buffer[4] + (buffer[3] & 0xf0) * 16; + if (level != kit->sensors[sensor]) { + kit->sensors[sensor] = level; + set_bit(sensor, &kit->sensor_events); + } + sensor++; + level = buffer[5] + (buffer[6] & 0x0f) * 256; + if (level != kit->sensors[sensor]) { + kit->sensors[sensor] = level; + set_bit(sensor, &kit->sensor_events); + } + sensor++; + level = buffer[7] + (buffer[6] & 0xf0) * 16; + if (level != kit->sensors[sensor]) { + kit->sensors[sensor] = level; + set_bit(sensor, &kit->sensor_events); + } } + if (kit->input_events || kit->sensor_events) + schedule_work(&kit->do_notify); + resubmit: status = usb_submit_urb(urb, SLAB_ATOMIC); if (status) @@ -304,20 +354,40 @@ resubmit: kit->udev->devpath, status); } +static void do_notify(void *data) +{ + struct interfacekit *kit = data; + int i; + char sysfs_file[8]; + + for (i=0; iifkit->inputs; i++) { + if (test_and_clear_bit(i, &kit->input_events)) { + sprintf(sysfs_file, "input%d", i + 1); + sysfs_notify(&kit->intf->dev.kobj, NULL, sysfs_file); + } + } + + for (i=0; iifkit->sensors; i++) { + if (test_and_clear_bit(i, &kit->sensor_events)) { + sprintf(sysfs_file, "sensor%d", i + 1); + sysfs_notify(&kit->intf->dev.kobj, NULL, sysfs_file); + } + } +} + #define show_set_output(value) \ -static ssize_t set_output##value(struct device *dev, struct device_attribute *attr, const char *buf, \ +static ssize_t set_output##value(struct device *dev, struct device_attribute *attr, const char *buf, \ size_t count) \ { \ struct usb_interface *intf = to_usb_interface(dev); \ - struct phidget_interfacekit *kit = usb_get_intfdata(intf); \ + struct interfacekit *kit = usb_get_intfdata(intf); \ int enabled; \ int retval; \ \ - if (sscanf(buf, "%d", &enabled) < 1) { \ + if (sscanf(buf, "%d", &enabled) < 1) \ return -EINVAL; \ - } \ \ - retval = change_outputs(kit, value - 1, enabled ? 1 : 0); \ + retval = change_outputs(kit, value - 1, enabled); \ \ return retval ? retval : count; \ } \ @@ -325,9 +395,9 @@ static ssize_t set_output##value(struct device *dev, struct device_attribute *at static ssize_t show_output##value(struct device *dev, struct device_attribute *attr, char *buf) \ { \ struct usb_interface *intf = to_usb_interface(dev); \ - struct phidget_interfacekit *kit = usb_get_intfdata(intf); \ + struct interfacekit *kit = usb_get_intfdata(intf); \ \ - return sprintf(buf, "%d\n", kit->outputs[value - 1]); \ + return sprintf(buf, "%d\n", !!test_bit(value - 1, &kit->outputs));\ } \ static DEVICE_ATTR(output##value, S_IWUGO | S_IRUGO, \ show_output##value, set_output##value); @@ -338,15 +408,23 @@ show_set_output(4); show_set_output(5); show_set_output(6); show_set_output(7); -show_set_output(8); /* should be MAX_INTERFACES - 1 */ +show_set_output(8); +show_set_output(9); +show_set_output(10); +show_set_output(11); +show_set_output(12); +show_set_output(13); +show_set_output(14); +show_set_output(15); +show_set_output(16); #define show_input(value) \ static ssize_t show_input##value(struct device *dev, struct device_attribute *attr, char *buf) \ { \ struct usb_interface *intf = to_usb_interface(dev); \ - struct phidget_interfacekit *kit = usb_get_intfdata(intf); \ + struct interfacekit *kit = usb_get_intfdata(intf); \ \ - return sprintf(buf, "%d\n", kit->inputs[value - 1]); \ + return sprintf(buf, "%d\n", (int)kit->inputs[value - 1]); \ } \ static DEVICE_ATTR(input##value, S_IRUGO, show_input##value, NULL); @@ -357,15 +435,23 @@ show_input(4); show_input(5); show_input(6); show_input(7); -show_input(8); /* should be MAX_INTERFACES - 1 */ +show_input(8); +show_input(9); +show_input(10); +show_input(11); +show_input(12); +show_input(13); +show_input(14); +show_input(15); +show_input(16); #define show_sensor(value) \ static ssize_t show_sensor##value(struct device *dev, struct device_attribute *attr, char *buf) \ { \ struct usb_interface *intf = to_usb_interface(dev); \ - struct phidget_interfacekit *kit = usb_get_intfdata(intf); \ + struct interfacekit *kit = usb_get_intfdata(intf); \ \ - return sprintf(buf, "%d\n", kit->sensors[value - 1]); \ + return sprintf(buf, "%d\n", (int)kit->sensors[value - 1]); \ } \ static DEVICE_ATTR(sensor##value, S_IRUGO, show_sensor##value, NULL); @@ -376,16 +462,16 @@ show_sensor(4); show_sensor(5); show_sensor(6); show_sensor(7); -show_sensor(8); /* should be MAX_INTERFACES - 1 */ +show_sensor(8); static int interfacekit_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *dev = interface_to_usbdev(intf); struct usb_host_interface *interface; struct usb_endpoint_descriptor *endpoint; - struct phidget_interfacekit *kit; + struct interfacekit *kit; struct driver_interfacekit *ifkit; - int pipe, maxp; + int pipe, maxp, rc = -ENOMEM; ifkit = (struct driver_interfacekit *)id->driver_info; if (!ifkit) @@ -405,29 +491,23 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); kit = kzalloc(sizeof(*kit), GFP_KERNEL); - if (kit == NULL) { - dev_err(&intf->dev, "%s - out of memory\n", __FUNCTION__); - return -ENOMEM; - } - kit->ifkit = ifkit; + if (!kit) + goto out; - kit->data = usb_buffer_alloc(dev, 8, SLAB_ATOMIC, &kit->data_dma); - if (!kit->data) { - kfree(kit); - return -ENOMEM; - } + kit->ifkit = ifkit; + kit->data = usb_buffer_alloc(dev, URB_INT_SIZE, SLAB_ATOMIC, &kit->data_dma); + if (!kit->data) + goto out; kit->irq = usb_alloc_urb(0, GFP_KERNEL); - if (!kit->irq) { - usb_buffer_free(dev, 8, kit->data, kit->data_dma); - kfree(kit); - return -ENOMEM; - } + if (!kit->irq) + goto out; kit->udev = usb_get_dev(dev); kit->intf = intf; + INIT_WORK(&kit->do_notify, do_notify, kit); usb_fill_int_urb(kit->irq, kit->udev, pipe, kit->data, - (maxp > 8 ? 8 : maxp), + maxp > URB_INT_SIZE ? URB_INT_SIZE : maxp, interfacekit_irq, kit, endpoint->bInterval); kit->irq->transfer_dma = kit->data_dma; kit->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; @@ -435,7 +515,8 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic usb_set_intfdata(intf, kit); if (usb_submit_urb(kit->irq, GFP_KERNEL)) { - return -EIO; + rc = -EIO; + goto out; } if (ifkit->outputs >= 4) { @@ -444,12 +525,22 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic device_create_file(&intf->dev, &dev_attr_output3); device_create_file(&intf->dev, &dev_attr_output4); } - if (ifkit->outputs == 8) { + if (ifkit->outputs >= 8) { device_create_file(&intf->dev, &dev_attr_output5); device_create_file(&intf->dev, &dev_attr_output6); device_create_file(&intf->dev, &dev_attr_output7); device_create_file(&intf->dev, &dev_attr_output8); } + if (ifkit->outputs == 16) { + device_create_file(&intf->dev, &dev_attr_output9); + device_create_file(&intf->dev, &dev_attr_output10); + device_create_file(&intf->dev, &dev_attr_output11); + device_create_file(&intf->dev, &dev_attr_output12); + device_create_file(&intf->dev, &dev_attr_output13); + device_create_file(&intf->dev, &dev_attr_output14); + device_create_file(&intf->dev, &dev_attr_output15); + device_create_file(&intf->dev, &dev_attr_output16); + } if (ifkit->inputs >= 4) { device_create_file(&intf->dev, &dev_attr_input1); @@ -457,12 +548,22 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic device_create_file(&intf->dev, &dev_attr_input3); device_create_file(&intf->dev, &dev_attr_input4); } - if (ifkit->inputs == 8) { + if (ifkit->inputs >= 8) { device_create_file(&intf->dev, &dev_attr_input5); device_create_file(&intf->dev, &dev_attr_input6); device_create_file(&intf->dev, &dev_attr_input7); device_create_file(&intf->dev, &dev_attr_input8); } + if (ifkit->inputs == 16) { + device_create_file(&intf->dev, &dev_attr_input9); + device_create_file(&intf->dev, &dev_attr_input10); + device_create_file(&intf->dev, &dev_attr_input11); + device_create_file(&intf->dev, &dev_attr_input12); + device_create_file(&intf->dev, &dev_attr_input13); + device_create_file(&intf->dev, &dev_attr_input14); + device_create_file(&intf->dev, &dev_attr_input15); + device_create_file(&intf->dev, &dev_attr_input16); + } if (ifkit->sensors >= 4) { device_create_file(&intf->dev, &dev_attr_sensor1); @@ -475,9 +576,8 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic device_create_file(&intf->dev, &dev_attr_sensor6); device_create_file(&intf->dev, &dev_attr_sensor7); } - if (ifkit->sensors == 8) { + if (ifkit->sensors == 8) device_create_file(&intf->dev, &dev_attr_sensor8); - } if (ifkit->has_lcd) device_create_file(&intf->dev, &dev_attr_lcd); @@ -486,29 +586,56 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic ifkit->sensors, ifkit->inputs, ifkit->outputs); return 0; + +out: + if (kit) { + if (kit->irq) + usb_free_urb(kit->irq); + if (kit->data) + usb_buffer_free(dev, URB_INT_SIZE, kit->data, kit->data_dma); + kfree(kit); + } + + return rc; } static void interfacekit_disconnect(struct usb_interface *interface) { - struct phidget_interfacekit *kit; + struct interfacekit *kit; kit = usb_get_intfdata(interface); usb_set_intfdata(interface, NULL); if (!kit) return; + usb_kill_urb(kit->irq); + usb_free_urb(kit->irq); + usb_buffer_free(kit->udev, URB_INT_SIZE, kit->data, kit->data_dma); + + cancel_delayed_work(&kit->do_notify); + if (kit->ifkit->outputs >= 4) { device_remove_file(&interface->dev, &dev_attr_output1); device_remove_file(&interface->dev, &dev_attr_output2); device_remove_file(&interface->dev, &dev_attr_output3); device_remove_file(&interface->dev, &dev_attr_output4); } - if (kit->ifkit->outputs == 8) { + if (kit->ifkit->outputs >= 8) { device_remove_file(&interface->dev, &dev_attr_output5); device_remove_file(&interface->dev, &dev_attr_output6); device_remove_file(&interface->dev, &dev_attr_output7); device_remove_file(&interface->dev, &dev_attr_output8); } + if (kit->ifkit->outputs == 16) { + device_remove_file(&interface->dev, &dev_attr_output9); + device_remove_file(&interface->dev, &dev_attr_output10); + device_remove_file(&interface->dev, &dev_attr_output11); + device_remove_file(&interface->dev, &dev_attr_output12); + device_remove_file(&interface->dev, &dev_attr_output13); + device_remove_file(&interface->dev, &dev_attr_output14); + device_remove_file(&interface->dev, &dev_attr_output15); + device_remove_file(&interface->dev, &dev_attr_output16); + } if (kit->ifkit->inputs >= 4) { device_remove_file(&interface->dev, &dev_attr_input1); @@ -516,12 +643,22 @@ static void interfacekit_disconnect(struct usb_interface *interface) device_remove_file(&interface->dev, &dev_attr_input3); device_remove_file(&interface->dev, &dev_attr_input4); } - if (kit->ifkit->inputs == 8) { + if (kit->ifkit->inputs >= 8) { device_remove_file(&interface->dev, &dev_attr_input5); device_remove_file(&interface->dev, &dev_attr_input6); device_remove_file(&interface->dev, &dev_attr_input7); device_remove_file(&interface->dev, &dev_attr_input8); } + if (kit->ifkit->inputs == 16) { + device_remove_file(&interface->dev, &dev_attr_input9); + device_remove_file(&interface->dev, &dev_attr_input10); + device_remove_file(&interface->dev, &dev_attr_input11); + device_remove_file(&interface->dev, &dev_attr_input12); + device_remove_file(&interface->dev, &dev_attr_input13); + device_remove_file(&interface->dev, &dev_attr_input14); + device_remove_file(&interface->dev, &dev_attr_input15); + device_remove_file(&interface->dev, &dev_attr_input16); + } if (kit->ifkit->sensors >= 4) { device_remove_file(&interface->dev, &dev_attr_sensor1); @@ -534,19 +671,15 @@ static void interfacekit_disconnect(struct usb_interface *interface) device_remove_file(&interface->dev, &dev_attr_sensor6); device_remove_file(&interface->dev, &dev_attr_sensor7); } - if (kit->ifkit->sensors == 8) { + if (kit->ifkit->sensors == 8) device_remove_file(&interface->dev, &dev_attr_sensor8); - } + if (kit->ifkit->has_lcd) device_remove_file(&interface->dev, &dev_attr_lcd); dev_info(&interface->dev, "USB PhidgetInterfaceKit %d/%d/%d detached\n", kit->ifkit->sensors, kit->ifkit->inputs, kit->ifkit->outputs); - usb_kill_urb(kit->irq); - usb_free_urb(kit->irq); - usb_buffer_free(kit->udev, 8, kit->data, kit->data_dma); - usb_put_dev(kit->udev); kfree(kit); } -- cgit v1.2.3 From 141804d401631f0384feabfa5fc3e2ce1321c0f0 Mon Sep 17 00:00:00 2001 From: Peter Chubb Date: Tue, 2 May 2006 18:30:12 +0100 Subject: [PATCH] USB: shuttle_usbat: Fix handling of scatter-gather buffers I've worked out what's going wrong. The scsi layer is now much more likely to pass down scatterlists instead of plain buffers. So you have to make sure that they're handled correctly. In one of the changes along the way, usbat_write_block and friends stopped obeying the srb->use_sg flag. Anyway, with the appended patch, and the one I'm putting in the next email, it all seems to work for the HP cd4e. Of course, someone's going to have to test it with the flash drives as well.... This patch teaches the usbat_{read,write}_block functions to obey the use_sg flag in the scsi-request. Signed-off-by: Peter Chubb Signed-off-by: Daniel Drake Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/shuttle_usbat.c | 54 ++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c index f2bc5c9e23d..92095b858eb 100644 --- a/drivers/usb/storage/shuttle_usbat.c +++ b/drivers/usb/storage/shuttle_usbat.c @@ -131,28 +131,30 @@ static int usbat_write(struct us_data *us, * Convenience function to perform a bulk read */ static int usbat_bulk_read(struct us_data *us, - unsigned char *data, - unsigned int len) + unsigned char *data, + unsigned int len, + int use_sg) { if (len == 0) return USB_STOR_XFER_GOOD; US_DEBUGP("usbat_bulk_read: len = %d\n", len); - return usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, data, len, NULL); + return usb_stor_bulk_transfer_sg(us, us->recv_bulk_pipe, data, len, use_sg, NULL); } /* * Convenience function to perform a bulk write */ static int usbat_bulk_write(struct us_data *us, - unsigned char *data, - unsigned int len) + unsigned char *data, + unsigned int len, + int use_sg) { if (len == 0) return USB_STOR_XFER_GOOD; US_DEBUGP("usbat_bulk_write: len = %d\n", len); - return usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, data, len, NULL); + return usb_stor_bulk_transfer_sg(us, us->send_bulk_pipe, data, len, use_sg, NULL); } /* @@ -317,7 +319,8 @@ static int usbat_wait_not_busy(struct us_data *us, int minutes) */ static int usbat_read_block(struct us_data *us, unsigned char *content, - unsigned short len) + unsigned short len, + int use_sg) { int result; unsigned char *command = us->iobuf; @@ -338,7 +341,7 @@ static int usbat_read_block(struct us_data *us, if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; - result = usbat_bulk_read(us, content, len); + result = usbat_bulk_read(us, content, len, use_sg); return (result == USB_STOR_XFER_GOOD ? USB_STOR_TRANSPORT_GOOD : USB_STOR_TRANSPORT_ERROR); } @@ -350,7 +353,8 @@ static int usbat_write_block(struct us_data *us, unsigned char access, unsigned char *content, unsigned short len, - int minutes) + int minutes, + int use_sg) { int result; unsigned char *command = us->iobuf; @@ -372,7 +376,7 @@ static int usbat_write_block(struct us_data *us, if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; - result = usbat_bulk_write(us, content, len); + result = usbat_bulk_write(us, content, len, use_sg); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; @@ -465,7 +469,7 @@ static int usbat_hp8200e_rw_block_test(struct us_data *us, data[1+(j<<1)] = data_out[j]; } - result = usbat_bulk_write(us, data, num_registers*2); + result = usbat_bulk_write(us, data, num_registers*2, 0); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; @@ -583,7 +587,7 @@ static int usbat_multiple_write(struct us_data *us, } /* Send the data */ - result = usbat_bulk_write(us, data, num_registers*2); + result = usbat_bulk_write(us, data, num_registers*2, 0); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; @@ -606,8 +610,9 @@ static int usbat_multiple_write(struct us_data *us, * other related details) are defined beforehand with _set_shuttle_features(). */ static int usbat_read_blocks(struct us_data *us, - unsigned char *buffer, - int len) + unsigned char *buffer, + int len, + int use_sg) { int result; unsigned char *command = us->iobuf; @@ -627,7 +632,7 @@ static int usbat_read_blocks(struct us_data *us, return USB_STOR_TRANSPORT_FAILED; /* Read the blocks we just asked for */ - result = usbat_bulk_read(us, buffer, len); + result = usbat_bulk_read(us, buffer, len, use_sg); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_FAILED; @@ -648,7 +653,8 @@ static int usbat_read_blocks(struct us_data *us, */ static int usbat_write_blocks(struct us_data *us, unsigned char *buffer, - int len) + int len, + int use_sg) { int result; unsigned char *command = us->iobuf; @@ -668,7 +674,7 @@ static int usbat_write_blocks(struct us_data *us, return USB_STOR_TRANSPORT_FAILED; /* Write the data */ - result = usbat_bulk_write(us, buffer, len); + result = usbat_bulk_write(us, buffer, len, use_sg); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_FAILED; @@ -947,7 +953,7 @@ static int usbat_flash_get_sector_count(struct us_data *us, msleep(100); /* Read the device identification data */ - rc = usbat_read_block(us, reply, 512); + rc = usbat_read_block(us, reply, 512, 0); if (rc != USB_STOR_TRANSPORT_GOOD) goto leave; @@ -1031,7 +1037,7 @@ static int usbat_flash_read_data(struct us_data *us, goto leave; /* Read the data we just requested */ - result = usbat_read_blocks(us, buffer, len); + result = usbat_read_blocks(us, buffer, len, 0); if (result != USB_STOR_TRANSPORT_GOOD) goto leave; @@ -1125,7 +1131,7 @@ static int usbat_flash_write_data(struct us_data *us, goto leave; /* Write the data */ - result = usbat_write_blocks(us, buffer, len); + result = usbat_write_blocks(us, buffer, len, 0); if (result != USB_STOR_TRANSPORT_GOOD) goto leave; @@ -1503,10 +1509,10 @@ static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us) * AT SPEED 4 IS UNRELIABLE!!! */ - if ( (result = usbat_write_block(us, + if ((result = usbat_write_block(us, USBAT_ATA, srb->cmnd, 12, - srb->cmnd[0]==GPCMD_BLANK ? 75 : 10)) != - USB_STOR_TRANSPORT_GOOD) { + (srb->cmnd[0]==GPCMD_BLANK ? 75 : 10), 0) != + USB_STOR_TRANSPORT_GOOD)) { return result; } @@ -1533,7 +1539,7 @@ static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us) len = *status; - result = usbat_read_block(us, srb->request_buffer, len); + result = usbat_read_block(us, srb->request_buffer, len, srb->use_sg); /* Debug-print the first 32 bytes of the transfer */ -- cgit v1.2.3 From bdcfd9e349eff9398a1d85eaa517294f493bb3c8 Mon Sep 17 00:00:00 2001 From: Peter Chubb Date: Tue, 2 May 2006 18:29:34 +0100 Subject: [PATCH] USB: shuttle_usbat: Hardcode detection of HP CDRW devices Use USB vendor and product IDs to determine whether the attached device is a CDROM or a Flash device. Daniel Drake says that the *same* vendor and product IDs for non-HP vendor ID could be either flash or cdrom, so try to probe for them. Signed-off-by: Peter Chubb Signed-off-by: Daniel Drake Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/shuttle_usbat.c | 51 ++++++++++++++++++++++++++----------- drivers/usb/storage/shuttle_usbat.h | 4 ++- drivers/usb/storage/unusual_devs.h | 8 +++--- 3 files changed, 43 insertions(+), 20 deletions(-) diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c index 92095b858eb..8fcec01dc62 100644 --- a/drivers/usb/storage/shuttle_usbat.c +++ b/drivers/usb/storage/shuttle_usbat.c @@ -893,22 +893,28 @@ static int usbat_identify_device(struct us_data *us, * Set the transport function based on the device type */ static int usbat_set_transport(struct us_data *us, - struct usbat_info *info) + struct usbat_info *info, + int devicetype) { - int rc; - if (!info->devicetype) { - rc = usbat_identify_device(us, info); - if (rc != USB_STOR_TRANSPORT_GOOD) { - US_DEBUGP("usbat_set_transport: Could not identify device\n"); - return 1; - } - } + if (!info->devicetype) + info->devicetype = devicetype; - if (usbat_get_device_type(us) == USBAT_DEV_HP8200) + if (!info->devicetype) + usbat_identify_device(us, info); + + switch (info->devicetype) { + default: + return USB_STOR_TRANSPORT_ERROR; + + case USBAT_DEV_HP8200: us->transport = usbat_hp8200e_transport; - else if (usbat_get_device_type(us) == USBAT_DEV_FLASH) + break; + + case USBAT_DEV_FLASH: us->transport = usbat_flash_transport; + break; + } return 0; } @@ -1316,7 +1322,7 @@ static int usbat_select_and_test_registers(struct us_data *us) /* * Initialize the USBAT processor and the storage device */ -int init_usbat(struct us_data *us) +static int init_usbat(struct us_data *us, int devicetype) { int rc; struct usbat_info *info; @@ -1398,7 +1404,7 @@ int init_usbat(struct us_data *us) US_DEBUGP("INIT 9\n"); /* At this point, we need to detect which device we are using */ - if (usbat_set_transport(us, info)) + if (usbat_set_transport(us, info, devicetype)) return USB_STOR_TRANSPORT_ERROR; US_DEBUGP("INIT 10\n"); @@ -1701,6 +1707,22 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us) return USB_STOR_TRANSPORT_FAILED; } +int init_usbat_cd(struct us_data *us) +{ + return init_usbat(us, USBAT_DEV_HP8200); +} + + +int init_usbat_flash(struct us_data *us) +{ + return init_usbat(us, USBAT_DEV_FLASH); +} + +int init_usbat_probe(struct us_data *us) +{ + return init_usbat(us, 0); +} + /* * Default transport function. Attempts to detect which transport function * should be called, makes it the new default, and calls it. @@ -1714,9 +1736,8 @@ int usbat_transport(struct scsi_cmnd *srb, struct us_data *us) { struct usbat_info *info = (struct usbat_info*) (us->extra); - if (usbat_set_transport(us, info)) + if (usbat_set_transport(us, info, 0)) return USB_STOR_TRANSPORT_ERROR; return us->transport(srb, us); } - diff --git a/drivers/usb/storage/shuttle_usbat.h b/drivers/usb/storage/shuttle_usbat.h index 25e7d8b340b..3ddf143a1de 100644 --- a/drivers/usb/storage/shuttle_usbat.h +++ b/drivers/usb/storage/shuttle_usbat.h @@ -106,7 +106,9 @@ #define USBAT_FEAT_ET2 0x01 extern int usbat_transport(struct scsi_cmnd *srb, struct us_data *us); -extern int init_usbat(struct us_data *us); +extern int init_usbat_cd(struct us_data *us); +extern int init_usbat_flash(struct us_data *us); +extern int init_usbat_probe(struct us_data *us); struct usbat_info { int devicetype; diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index aec5ea8682d..f24fa12eaed 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -78,12 +78,12 @@ UNUSUAL_DEV( 0x03f0, 0x0107, 0x0200, 0x0200, UNUSUAL_DEV( 0x03f0, 0x0207, 0x0001, 0x0001, "HP", "CD-Writer+ 8200e", - US_SC_8070, US_PR_USBAT, init_usbat, 0), + US_SC_8070, US_PR_USBAT, init_usbat_cd, 0), UNUSUAL_DEV( 0x03f0, 0x0307, 0x0001, 0x0001, "HP", "CD-Writer+ CD-4e", - US_SC_8070, US_PR_USBAT, init_usbat, 0), + US_SC_8070, US_PR_USBAT, init_usbat_cd, 0), #endif /* Reported by Sebastian Kapfer @@ -393,7 +393,7 @@ UNUSUAL_DEV( 0x04fc, 0x80c2, 0x0100, 0x0100, UNUSUAL_DEV( 0x04e6, 0x1010, 0x0000, 0x9999, "Shuttle/SCM", "USBAT-02", - US_SC_SCSI, US_PR_USBAT, init_usbat, + US_SC_SCSI, US_PR_USBAT, init_usbat_probe, US_FL_SINGLE_LUN), #endif @@ -797,7 +797,7 @@ UNUSUAL_DEV( 0x0781, 0x0002, 0x0009, 0x0009, UNUSUAL_DEV( 0x0781, 0x0005, 0x0005, 0x0005, "Sandisk", "ImageMate SDDR-05b", - US_SC_SCSI, US_PR_USBAT, init_usbat, + US_SC_SCSI, US_PR_USBAT, init_usbat_flash, US_FL_SINGLE_LUN ), #endif -- cgit v1.2.3 From f9347c52347f24244c550871eab8ecb0fb5704d6 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Mon, 8 May 2006 23:43:02 +0100 Subject: [PATCH] USB shuttle_usbat: hardcode flash detection for now After some further testing with my flash device I realised that our current probe doesn't always work (e.g. when no media is inserted). Now that Peter Chubb's patch has simplified the detection of 99% of the HP CD writers out there, we have a much smaller range of hardware to work with on the shared device ID, so it should be possible to try some of the previous probe options again: we just need to find another tester with a USBAT2-based HP CD writer. This patch hardcodes the flash detection until someone comes along with one of these obscure CD drives. Note that these devices are extremely rare, so even if we can't ever find a decent probe method, at least we will be supporting almost all of the USBAT-based hardware out there. Signed-off-by: Daniel Drake Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index f24fa12eaed..9f72000a006 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -393,7 +393,7 @@ UNUSUAL_DEV( 0x04fc, 0x80c2, 0x0100, 0x0100, UNUSUAL_DEV( 0x04e6, 0x1010, 0x0000, 0x9999, "Shuttle/SCM", "USBAT-02", - US_SC_SCSI, US_PR_USBAT, init_usbat_probe, + US_SC_SCSI, US_PR_USBAT, init_usbat_flash, US_FL_SINGLE_LUN), #endif -- cgit v1.2.3 From b383539e04c413e040d998aedcc120c49aa670da Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Tue, 9 May 2006 01:45:27 +0100 Subject: [PATCH] USB: usb-storage alauda: Fix transport info mismerge Unfortunately it looks like the transport entry for this subdriver was merged into the protocol section, making this driver unusable :( Signed-off-by: Daniel Drake Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/usb.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index dd108634348..0142fe82f6b 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -593,6 +593,15 @@ static int get_transport(struct us_data *us) break; #endif +#ifdef CONFIG_USB_STORAGE_ALAUDA + case US_PR_ALAUDA: + us->transport_name = "Alauda Control/Bulk"; + us->transport = alauda_transport; + us->transport_reset = usb_stor_Bulk_reset; + us->max_lun = 1; + break; +#endif + default: return -EIO; } @@ -648,15 +657,6 @@ static int get_protocol(struct us_data *us) break; #endif -#ifdef CONFIG_USB_STORAGE_ALAUDA - case US_PR_ALAUDA: - us->transport_name = "Alauda Control/Bulk"; - us->transport = alauda_transport; - us->transport_reset = usb_stor_Bulk_reset; - us->max_lun = 1; - break; -#endif - default: return -EIO; } -- cgit v1.2.3 From 2d61bde7a0e630e1906e6478b6b2a7aeaaa8f8da Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 5 May 2006 16:23:42 -0400 Subject: [PATCH] USB: net2280: add a shutdown routine The net2280 board has an annoying habit of surviving soft reboots with interrupts enabled. This patch (as674) adds a shutdown routine to the driver so that the board can be put in a quiescent state. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/net2280.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index 020d3c42b1a..1facdea56a8 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c @@ -2966,6 +2966,22 @@ done: return retval; } +/* make sure the board is quiescent; otherwise it will continue + * generating IRQs across the upcoming reboot. + */ + +static void net2280_shutdown (struct pci_dev *pdev) +{ + struct net2280 *dev = pci_get_drvdata (pdev); + + /* disable IRQs */ + writel (0, &dev->regs->pciirqenb0); + writel (0, &dev->regs->pciirqenb1); + + /* disable the pullup so the host will think we're gone */ + writel (0, &dev->usb->usbctl); +} + /*-------------------------------------------------------------------------*/ @@ -2995,6 +3011,7 @@ static struct pci_driver net2280_pci_driver = { .probe = net2280_probe, .remove = net2280_remove, + .shutdown = net2280_shutdown, /* FIXME add power management support */ }; -- cgit v1.2.3 From 4de7d2c231a8624a47417977be0768c5b5257c4f Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 5 May 2006 16:26:58 -0400 Subject: [PATCH] USB: UHCI: store the endpoint type in the QH structure This patch (as675) simplifies uhci-hcd slightly by storing each endpoint's type in the corresponding Queue Header structure. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/uhci-debug.c | 26 +++++++++++++++++++------- drivers/usb/host/uhci-hcd.h | 1 + drivers/usb/host/uhci-q.c | 34 ++++++++++++++++++---------------- 3 files changed, 38 insertions(+), 23 deletions(-) diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c index e1239319655..28c1c51ec47 100644 --- a/drivers/usb/host/uhci-debug.c +++ b/drivers/usb/host/uhci-debug.c @@ -98,6 +98,7 @@ static int uhci_show_urbp(struct urb_priv *urbp, char *buf, int len, int space) char *out = buf; struct uhci_td *td; int i, nactive, ninactive; + char *ptype; if (len < 200) return 0; @@ -110,13 +111,14 @@ static int uhci_show_urbp(struct urb_priv *urbp, char *buf, int len, int space) (usb_pipein(urbp->urb->pipe) ? "IN" : "OUT")); switch (usb_pipetype(urbp->urb->pipe)) { - case PIPE_ISOCHRONOUS: out += sprintf(out, "ISO"); break; - case PIPE_INTERRUPT: out += sprintf(out, "INT"); break; - case PIPE_BULK: out += sprintf(out, "BLK"); break; - case PIPE_CONTROL: out += sprintf(out, "CTL"); break; + case PIPE_ISOCHRONOUS: ptype = "ISO"; break; + case PIPE_INTERRUPT: ptype = "INT"; break; + case PIPE_BULK: ptype = "BLK"; break; + default: + case PIPE_CONTROL: ptype = "CTL"; break; } - out += sprintf(out, "%s", (urbp->fsbr ? " FSBR" : "")); + out += sprintf(out, "%s%s", ptype, (urbp->fsbr ? " FSBR" : "")); if (urbp->urb->status != -EINPROGRESS) out += sprintf(out, " Status=%d", urbp->urb->status); @@ -147,13 +149,23 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space) char *out = buf; int i, nurbs; __le32 element = qh_element(qh); + char *qtype; /* Try to make sure there's enough memory */ if (len < 80 * 6) return 0; - out += sprintf(out, "%*s[%p] link (%08x) element (%08x)\n", space, "", - qh, le32_to_cpu(qh->link), le32_to_cpu(element)); + switch (qh->type) { + case USB_ENDPOINT_XFER_ISOC: qtype = "ISO"; break; + case USB_ENDPOINT_XFER_INT: qtype = "INT"; break; + case USB_ENDPOINT_XFER_BULK: qtype = "BLK"; break; + case USB_ENDPOINT_XFER_CONTROL: qtype = "CTL"; break; + default: qtype = "Skel" ; break; + } + + out += sprintf(out, "%*s[%p] %s QH link (%08x) element (%08x)\n", + space, "", qh, qtype, + le32_to_cpu(qh->link), le32_to_cpu(element)); if (element & UHCI_PTR_QH) out += sprintf(out, "%*s Element points to QH (bug?)\n", space, ""); diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h index d5c8f4d9282..8e577865049 100644 --- a/drivers/usb/host/uhci-hcd.h +++ b/drivers/usb/host/uhci-hcd.h @@ -132,6 +132,7 @@ struct uhci_qh { unsigned int unlink_frame; /* When the QH was unlinked */ int state; /* QH_STATE_xxx; see above */ + int type; /* Queue type (control, bulk, etc) */ unsigned int initial_toggle:1; /* Endpoint's current toggle value */ unsigned int needs_fixup:1; /* Must fix the TD toggle values */ diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index a06d84c19e1..8639e903593 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -179,10 +179,12 @@ static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, qh->hep = hep; qh->udev = udev; hep->hcpriv = qh; + qh->type = hep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; } else { /* Skeleton QH */ qh->state = QH_STATE_ACTIVE; qh->udev = NULL; + qh->type = -1; } return qh; } @@ -217,8 +219,8 @@ static void uhci_save_toggle(struct uhci_qh *qh, struct urb *urb) qh->element = UHCI_PTR_TERM; /* Only bulk and interrupt pipes have to worry about toggles */ - if (!(usb_pipetype(urb->pipe) == PIPE_BULK || - usb_pipetype(urb->pipe) == PIPE_INTERRUPT)) + if (!(qh->type == USB_ENDPOINT_XFER_BULK || + qh->type == USB_ENDPOINT_XFER_INT)) return; /* Find the first active TD; that's the device's toggle state */ @@ -1099,14 +1101,14 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd, } urbp->qh = qh; - switch (usb_pipetype(urb->pipe)) { - case PIPE_CONTROL: + switch (qh->type) { + case USB_ENDPOINT_XFER_CONTROL: ret = uhci_submit_control(uhci, urb, qh); break; - case PIPE_BULK: + case USB_ENDPOINT_XFER_BULK: ret = uhci_submit_bulk(uhci, urb, qh); break; - case PIPE_INTERRUPT: + case USB_ENDPOINT_XFER_INT: if (list_empty(&qh->queue)) { bustime = usb_check_bandwidth(urb->dev, urb); if (bustime < 0) @@ -1125,7 +1127,7 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd, ret = uhci_submit_interrupt(uhci, urb, qh); } break; - case PIPE_ISOCHRONOUS: + case USB_ENDPOINT_XFER_ISOC: bustime = usb_check_bandwidth(urb->dev, urb); if (bustime < 0) { ret = bustime; @@ -1175,7 +1177,7 @@ static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) goto done; /* Remove Isochronous TDs from the frame list ASAP */ - if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) + if (urbp->qh->type == USB_ENDPOINT_XFER_ISOC) uhci_unlink_isochronous_tds(uhci, urb); uhci_unlink_qh(uhci, urbp->qh); @@ -1195,7 +1197,7 @@ __acquires(uhci->lock) struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; /* Isochronous TDs get unlinked directly from the frame list */ - if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) + if (qh->type == USB_ENDPOINT_XFER_ISOC) uhci_unlink_isochronous_tds(uhci, urb); /* If the URB isn't first on its queue, adjust the link pointer @@ -1224,13 +1226,13 @@ __acquires(uhci->lock) uhci_dec_fsbr(uhci, urb); /* Safe since it checks */ uhci_free_urb_priv(uhci, urbp); - switch (usb_pipetype(urb->pipe)) { - case PIPE_ISOCHRONOUS: + switch (qh->type) { + case USB_ENDPOINT_XFER_ISOC: /* Release bandwidth for Interrupt or Isoc. transfers */ if (urb->bandwidth) usb_release_bandwidth(urb->dev, urb, 1); break; - case PIPE_INTERRUPT: + case USB_ENDPOINT_XFER_INT: /* Release bandwidth for Interrupt or Isoc. transfers */ /* Make sure we don't release if we have a queued URB */ if (list_empty(&qh->queue) && urb->bandwidth) @@ -1273,14 +1275,14 @@ static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh, urbp = list_entry(qh->queue.next, struct urb_priv, node); urb = urbp->urb; - switch (usb_pipetype(urb->pipe)) { - case PIPE_CONTROL: + switch (qh->type) { + case USB_ENDPOINT_XFER_CONTROL: status = uhci_result_control(uhci, urb); break; - case PIPE_ISOCHRONOUS: + case USB_ENDPOINT_XFER_ISOC: status = uhci_result_isochronous(uhci, urb); break; - default: /* PIPE_BULK or PIPE_INTERRUPT */ + default: /* USB_ENDPOINT_XFER_BULK or _INT */ status = uhci_result_common(uhci, urb); break; } -- cgit v1.2.3 From 2775562ad2af2fc131ef7987166db6e42217528f Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 5 May 2006 16:32:02 -0400 Subject: [PATCH] USB: UHCI: fix obscure bug in enqueue() This patch (as676) fixes a small bug in uhci-hcd's enqueue routine. When an URB is unlinked or gets an error and the completion handler queues another URB for the same endpoint, the queue shouldn't be allowed to start up again until the handler returns. Not even if the new URB is the only one on its queue. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/uhci-q.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index 8639e903593..693e92c1bd9 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -1148,8 +1148,9 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd, /* If the new URB is the first and only one on this QH then either * the QH is new and idle or else it's unlinked and waiting to - * become idle, so we can activate it right away. */ - if (qh->queue.next == &urbp->node) + * become idle, so we can activate it right away. But only if the + * queue isn't stopped. */ + if (qh->queue.next == &urbp->node && !qh->is_stopped) uhci_activate_qh(uhci, qh); goto done; @@ -1293,27 +1294,32 @@ static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh, if (urb->status == -EINPROGRESS) /* Not dequeued */ urb->status = status; else - status = -ECONNRESET; + status = ECONNRESET; /* Not -ECONNRESET */ spin_unlock(&urb->lock); /* Dequeued but completed URBs can't be given back unless * the QH is stopped or has finished unlinking. */ - if (status == -ECONNRESET && - !(qh->is_stopped || QH_FINISHED_UNLINKING(qh))) - return; + if (status == ECONNRESET) { + if (QH_FINISHED_UNLINKING(qh)) + qh->is_stopped = 1; + else if (!qh->is_stopped) + return; + } uhci_giveback_urb(uhci, qh, urb, regs); - if (qh->is_stopped) + if (status < 0) break; } /* If the QH is neither stopped nor finished unlinking (normal case), * our work here is done. */ - restart: - if (!(qh->is_stopped || QH_FINISHED_UNLINKING(qh))) + if (QH_FINISHED_UNLINKING(qh)) + qh->is_stopped = 1; + else if (!qh->is_stopped) return; /* Otherwise give back each of the dequeued URBs */ +restart: list_for_each_entry(urbp, &qh->queue, node) { urb = urbp->urb; if (urb->status != -EINPROGRESS) { -- cgit v1.2.3 From a82e49b8aeb9f8dafdf6cf2e617c8b95bf056257 Mon Sep 17 00:00:00 2001 From: Bart Massey Date: Mon, 8 May 2006 14:40:13 -0700 Subject: [PATCH] USB HID/HIDBP, INPUT DRIVERS: fix various usb/input/hid-input.c bugs that make Apple Mighty Mouse work poorly Transposed lines of code in drivers/usb/input/hid-input.c causes the capability bits for a new HID device to be set before quirks are applied at configuration time. When an HID event is then sent up to the input layer, it may then be discarded as irrelevant because the wrong capability bit is set. Further, the quirks for the Apple Mighty Mouse are not quite right: the horizontal scrolling needs its axis reversed, and the left and center buttons are transposed. Also, the mouse is labeled in the kernel with its earlier name (I think) of Apple PowerMouse. Steps to reproduce problem: Plug in an Apple Mighty Mouse. Note that horizontal scrolling doesn't work at all, and in fact doesn't generate any input events on /dev/input/eventN. Note also that pushing the middle button performs the right button action, and vice versa. Once you have the horizontal scrolling working, note that it is backward WRT both to vertical scrolling and to common sense. This patch maybe should be broken up, as it does address two problems. The transposed code in hidinput_configure_usage() probably creates bugs beyond just the Mighty Mouse. The rest of the patch renames POWERMOUSE to MIGHTYMOUSE everywhere (which I *believe* is correct), fixes the MIGHTYMOUSE quirk to swap the center and right mouse buttons, and adds a new quirk HID_QUIRK_INVERT_HWHEEL also assigned to the MIGHTYMOUSE with code in hidinput_hid_event() to implement it. Signed-off-by: Bart Massey Signed-off-by: Greg Kroah-Hartman --- drivers/usb/input/hid-core.c | 4 ++-- drivers/usb/input/hid-input.c | 32 ++++++++++++++++++++++---------- drivers/usb/input/hid.h | 3 ++- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 4f7e9214de0..bb1f5211ff9 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -1549,7 +1549,7 @@ void hid_init_reports(struct hid_device *hid) #define USB_DEVICE_ID_LD_MACHINETEST 0x2040 #define USB_VENDOR_ID_APPLE 0x05ac -#define USB_DEVICE_ID_APPLE_POWERMOUSE 0x0304 +#define USB_DEVICE_ID_APPLE_MIGHTYMOUSE 0x0304 #define USB_VENDOR_ID_CHERRY 0x046a #define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023 @@ -1692,7 +1692,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_SILVERCREST, USB_DEVICE_ID_SILVERCREST_KB, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_POWERMOUSE, HID_QUIRK_2WHEEL_POWERMOUSE }, + { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE, HID_QUIRK_MIGHTYMOUSE | HID_QUIRK_INVERT_HWHEEL }, { USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK_7 }, { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE, HID_QUIRK_2WHEEL_MOUSE_HACK_5 }, diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c index 25bc85f8ce3..2f665195f4a 100644 --- a/drivers/usb/input/hid-input.c +++ b/drivers/usb/input/hid-input.c @@ -567,16 +567,14 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel break; } - set_bit(usage->type, input->evbit); - - while (usage->code <= max && test_and_set_bit(usage->code, bit)) - usage->code = find_next_zero_bit(bit, max + 1, usage->code); - - if (usage->code > max) - goto ignore; - - if (((device->quirks & (HID_QUIRK_2WHEEL_POWERMOUSE)) && (usage->hid == 0x00010032))) - map_rel(REL_HWHEEL); + if (device->quirks & HID_QUIRK_MIGHTYMOUSE) { + if (usage->hid == HID_GD_Z) + map_rel(REL_HWHEEL); + else if (usage->code == BTN_1) + map_key(BTN_2); + else if (usage->code == BTN_2) + map_key(BTN_1); + } if ((device->quirks & (HID_QUIRK_2WHEEL_MOUSE_HACK_7 | HID_QUIRK_2WHEEL_MOUSE_HACK_5)) && (usage->type == EV_REL) && (usage->code == REL_WHEEL)) @@ -586,6 +584,15 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel || ((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) && (usage->hid == 0x00090007))) goto ignore; + set_bit(usage->type, input->evbit); + + while (usage->code <= max && test_and_set_bit(usage->code, bit)) + usage->code = find_next_zero_bit(bit, max + 1, usage->code); + + if (usage->code > max) + goto ignore; + + if (usage->type == EV_ABS) { int a = field->logical_minimum; @@ -647,6 +654,11 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct return; } + if ((hid->quirks & HID_QUIRK_INVERT_HWHEEL) && (usage->code == REL_HWHEEL)) { + input_event(input, usage->type, usage->code, -value); + return; + } + if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_ON) && (usage->code == REL_WHEEL)) { input_event(input, usage->type, REL_HWHEEL, value); return; diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h index 9c62837b5b8..7efbfff8add 100644 --- a/drivers/usb/input/hid.h +++ b/drivers/usb/input/hid.h @@ -247,10 +247,11 @@ struct hid_item { #define HID_QUIRK_2WHEEL_MOUSE_HACK_7 0x00000080 #define HID_QUIRK_2WHEEL_MOUSE_HACK_5 0x00000100 #define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x00000200 -#define HID_QUIRK_2WHEEL_POWERMOUSE 0x00000400 +#define HID_QUIRK_MIGHTYMOUSE 0x00000400 #define HID_QUIRK_CYMOTION 0x00000800 #define HID_QUIRK_POWERBOOK_HAS_FN 0x00001000 #define HID_QUIRK_POWERBOOK_FN_ON 0x00002000 +#define HID_QUIRK_INVERT_HWHEEL 0x00004000 /* * This is the global environment of the parser. This information is -- cgit v1.2.3 From 0f28b55db543001d360e4319bfc3f2c4e28ba05f Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 15 May 2006 14:49:04 -0400 Subject: [PATCH] usbhid: automatically set HID_QUIRK_NOGET for keyboards and mice It seems to be relatively common for USB keyboards and mice to dislike being polled for reports. Since there's no need to poll a keyboard or a mouse, this patch (as685) automatically sets the HID_QUIRK_NOGET flag for devices that advertise themselves as either sort of device with boot protocol support. This won't cure all the problems since some devices don't support the boot protocol, but it's simple and easy and it should fix quite a few problems. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/input/hid-core.c | 8 ++++++++ drivers/usb/input/hid.h | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index bb1f5211ff9..061002fc66f 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -1797,6 +1797,14 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) (hid_blacklist[n].idProduct == le16_to_cpu(dev->descriptor.idProduct))) quirks = hid_blacklist[n].quirks; + /* Many keyboards and mice don't like to be polled for reports, + * so we will always set the HID_QUIRK_NOGET flag for them. */ + if (interface->desc.bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT) { + if (interface->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_KEYBOARD || + interface->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE) + quirks |= HID_QUIRK_NOGET; + } + if (quirks & HID_QUIRK_IGNORE) return NULL; diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h index 7efbfff8add..778e575de35 100644 --- a/drivers/usb/input/hid.h +++ b/drivers/usb/input/hid.h @@ -40,6 +40,14 @@ #define USB_INTERFACE_CLASS_HID 3 +/* + * USB HID interface subclass and protocol codes + */ + +#define USB_INTERFACE_SUBCLASS_BOOT 1 +#define USB_INTERFACE_PROTOCOL_KEYBOARD 1 +#define USB_INTERFACE_PROTOCOL_MOUSE 2 + /* * HID class requests */ -- cgit v1.2.3 From b1869000a60b0c72022811f24110a52d3e300b1e Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 12 May 2006 11:14:25 -0400 Subject: [PATCH] UHCI: Common result routine for Control/Bulk/Interrupt This patch (as679) combines the result routine for Control URBs with the routine for Bulk/Interrupt URBs. Along the way I eliminated the debugging printouts for Control transfers unless the debugging level is set higher than 1. I also eliminated a long-unused (#ifdef'ed-out) section that works around some buggy old APC BackUPS devices. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/uhci-q.c | 342 +++++++++++++++++----------------------------- 1 file changed, 125 insertions(+), 217 deletions(-) diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index 693e92c1bd9..30e36031fe2 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -618,134 +618,6 @@ nomem: return -ENOMEM; } -/* - * If control-IN transfer was short, the status packet wasn't sent. - * This routine changes the element pointer in the QH to point at the - * status TD. It's safe to do this even while the QH is live, because - * the hardware only updates the element pointer following a successful - * transfer. The inactive TD for the short packet won't cause an update, - * so the pointer won't get overwritten. The next time the controller - * sees this QH, it will send the status packet. - */ -static int usb_control_retrigger_status(struct uhci_hcd *uhci, struct urb *urb) -{ - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - struct uhci_td *td; - - urbp->short_transfer = 1; - - td = list_entry(urbp->td_list.prev, struct uhci_td, list); - urbp->qh->element = cpu_to_le32(td->dma_handle); - - return -EINPROGRESS; -} - - -static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb) -{ - struct list_head *tmp, *head; - struct urb_priv *urbp = urb->hcpriv; - struct uhci_td *td; - unsigned int status; - int ret = 0; - - head = &urbp->td_list; - if (urbp->short_transfer) { - tmp = head->prev; - goto status_stage; - } - - urb->actual_length = 0; - - tmp = head->next; - td = list_entry(tmp, struct uhci_td, list); - - /* The first TD is the SETUP stage, check the status, but skip */ - /* the count */ - status = uhci_status_bits(td_status(td)); - if (status & TD_CTRL_ACTIVE) - return -EINPROGRESS; - - if (status) - goto td_error; - - /* The rest of the TDs (but the last) are data */ - tmp = tmp->next; - while (tmp != head && tmp->next != head) { - unsigned int ctrlstat; - - td = list_entry(tmp, struct uhci_td, list); - tmp = tmp->next; - - ctrlstat = td_status(td); - status = uhci_status_bits(ctrlstat); - if (status & TD_CTRL_ACTIVE) - return -EINPROGRESS; - - urb->actual_length += uhci_actual_length(ctrlstat); - - if (status) - goto td_error; - - /* Check to see if we received a short packet */ - if (uhci_actual_length(ctrlstat) < - uhci_expected_length(td_token(td))) { - if (urb->transfer_flags & URB_SHORT_NOT_OK) { - ret = -EREMOTEIO; - goto err; - } - - return usb_control_retrigger_status(uhci, urb); - } - } - -status_stage: - td = list_entry(tmp, struct uhci_td, list); - - /* Control status stage */ - status = td_status(td); - -#ifdef I_HAVE_BUGGY_APC_BACKUPS - /* APC BackUPS Pro kludge */ - /* It tries to send all of the descriptor instead of the amount */ - /* we requested */ - if (status & TD_CTRL_IOC && /* IOC is masked out by uhci_status_bits */ - status & TD_CTRL_ACTIVE && - status & TD_CTRL_NAK) - return 0; -#endif - - status = uhci_status_bits(status); - if (status & TD_CTRL_ACTIVE) - return -EINPROGRESS; - - if (status) - goto td_error; - - return 0; - -td_error: - ret = uhci_map_status(status, uhci_packetout(td_token(td))); - -err: - if ((debug == 1 && ret != -EPIPE) || debug > 1) { - /* Some debugging code */ - dev_dbg(uhci_dev(uhci), "%s: failed with status %x\n", - __FUNCTION__, status); - - if (errbuf) { - /* Print the chain for debugging purposes */ - uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0); - lprintk(errbuf); - } - } - - /* Note that the queue has stopped */ - urbp->qh->element = UHCI_PTR_TERM; - urbp->qh->is_stopped = 1; - return ret; -} - /* * Common submit for bulk and interrupt */ @@ -864,86 +736,6 @@ nomem: return -ENOMEM; } -/* - * Common result for bulk and interrupt - */ -static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb) -{ - struct urb_priv *urbp = urb->hcpriv; - struct uhci_td *td; - unsigned int status = 0; - int ret = 0; - - urb->actual_length = 0; - - list_for_each_entry(td, &urbp->td_list, list) { - unsigned int ctrlstat = td_status(td); - - status = uhci_status_bits(ctrlstat); - if (status & TD_CTRL_ACTIVE) - return -EINPROGRESS; - - urb->actual_length += uhci_actual_length(ctrlstat); - - if (status) - goto td_error; - - if (uhci_actual_length(ctrlstat) < - uhci_expected_length(td_token(td))) { - if (urb->transfer_flags & URB_SHORT_NOT_OK) { - ret = -EREMOTEIO; - goto err; - } - - /* - * This URB stopped short of its end. We have to - * fix up the toggles of the following URBs on the - * queue and restart the queue. - * - * Do this only the first time we encounter the - * short URB. - */ - if (!urbp->short_transfer) { - urbp->short_transfer = 1; - urbp->qh->initial_toggle = - uhci_toggle(td_token(td)) ^ 1; - uhci_fixup_toggles(urbp->qh, 1); - - td = list_entry(urbp->td_list.prev, - struct uhci_td, list); - urbp->qh->element = td->link; - } - break; - } - } - - return 0; - -td_error: - ret = uhci_map_status(status, uhci_packetout(td_token(td))); - - if ((debug == 1 && ret != -EPIPE) || debug > 1) { - /* Some debugging code */ - dev_dbg(uhci_dev(uhci), "%s: failed with status %x\n", - __FUNCTION__, status); - - if (debug > 1 && errbuf) { - /* Print the chain for debugging purposes */ - uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0); - lprintk(errbuf); - } - } -err: - - /* Note that the queue has stopped and save the next toggle value */ - urbp->qh->element = UHCI_PTR_TERM; - urbp->qh->is_stopped = 1; - urbp->qh->needs_fixup = 1; - urbp->qh->initial_toggle = uhci_toggle(td_token(td)) ^ - (ret == -EREMOTEIO); - return ret; -} - static inline int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb, struct uhci_qh *qh) { @@ -971,6 +763,129 @@ static inline int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb, return uhci_submit_common(uhci, urb, qh); } +/* + * Fix up the data structures following a short transfer + */ +static int uhci_fixup_short_transfer(struct uhci_hcd *uhci, + struct uhci_qh *qh, struct urb_priv *urbp, + struct uhci_td *short_td) +{ + struct uhci_td *td; + int ret = 0; + + td = list_entry(urbp->td_list.prev, struct uhci_td, list); + if (qh->type == USB_ENDPOINT_XFER_CONTROL) { + urbp->short_transfer = 1; + + /* When a control transfer is short, we have to restart + * the queue at the status stage transaction, which is + * the last TD. */ + qh->element = cpu_to_le32(td->dma_handle); + ret = -EINPROGRESS; + + } else if (!urbp->short_transfer) { + urbp->short_transfer = 1; + + /* When a bulk/interrupt transfer is short, we have to + * fix up the toggles of the following URBs on the queue + * before restarting the queue at the next URB. */ + qh->initial_toggle = uhci_toggle(td_token(short_td)) ^ 1; + uhci_fixup_toggles(qh, 1); + + qh->element = td->link; + } + + return ret; +} + +/* + * Common result for control, bulk, and interrupt + */ +static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb) +{ + struct urb_priv *urbp = urb->hcpriv; + struct uhci_qh *qh = urbp->qh; + struct uhci_td *td; + struct list_head *tmp; + unsigned status; + int ret = 0; + + tmp = urbp->td_list.next; + + if (qh->type == USB_ENDPOINT_XFER_CONTROL) { + if (urbp->short_transfer) + tmp = urbp->td_list.prev; + else + urb->actual_length = -8; /* SETUP packet */ + } else + urb->actual_length = 0; + + + while (tmp != &urbp->td_list) { + unsigned int ctrlstat; + int len; + + td = list_entry(tmp, struct uhci_td, list); + tmp = tmp->next; + + ctrlstat = td_status(td); + status = uhci_status_bits(ctrlstat); + if (status & TD_CTRL_ACTIVE) + return -EINPROGRESS; + + len = uhci_actual_length(ctrlstat); + urb->actual_length += len; + + if (status) { + ret = uhci_map_status(status, + uhci_packetout(td_token(td))); + if ((debug == 1 && ret != -EPIPE) || debug > 1) { + /* Some debugging code */ + dev_dbg(uhci_dev(uhci), + "%s: failed with status %x\n", + __FUNCTION__, status); + + if (debug > 1 && errbuf) { + /* Print the chain for debugging */ + uhci_show_qh(urbp->qh, errbuf, + ERRBUF_LEN, 0); + lprintk(errbuf); + } + } + + } else if (len < uhci_expected_length(td_token(td))) { + + /* We received a short packet */ + if (urb->transfer_flags & URB_SHORT_NOT_OK) + ret = -EREMOTEIO; + else if (ctrlstat & TD_CTRL_SPD) + ret = 1; + } + + if (ret != 0) + goto err; + } + return ret; + +err: + if (ret < 0) { + /* In case a control transfer gets an error + * during the setup stage */ + urb->actual_length = max(urb->actual_length, 0); + + /* Note that the queue has stopped and save + * the next toggle value */ + qh->element = UHCI_PTR_TERM; + qh->is_stopped = 1; + qh->needs_fixup = (qh->type != USB_ENDPOINT_XFER_CONTROL); + qh->initial_toggle = uhci_toggle(td_token(td)) ^ + (ret == -EREMOTEIO); + + } else /* Short packet received */ + ret = uhci_fixup_short_transfer(uhci, qh, urbp, td); + return ret; +} + /* * Isochronous transfers */ @@ -1276,17 +1191,10 @@ static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh, urbp = list_entry(qh->queue.next, struct urb_priv, node); urb = urbp->urb; - switch (qh->type) { - case USB_ENDPOINT_XFER_CONTROL: - status = uhci_result_control(uhci, urb); - break; - case USB_ENDPOINT_XFER_ISOC: + if (qh->type == USB_ENDPOINT_XFER_ISOC) status = uhci_result_isochronous(uhci, urb); - break; - default: /* USB_ENDPOINT_XFER_BULK or _INT */ + else status = uhci_result_common(uhci, urb); - break; - } if (status == -EINPROGRESS) break; -- cgit v1.2.3 From 59e29ed91cff90b27d393c7a3d3ac9c3fcaea7dd Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 12 May 2006 11:19:19 -0400 Subject: [PATCH] UHCI: Remove non-iso TDs as they are used This patch (as680) frees non-isochronous TDs as they are used, rather than all at once when an URB is complete. Although not a terribly important change in itself, it opens the door to a later enhancement that will reduce storage requirements by allocating only a limited number of TDs at any time for each endpoint queue. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/uhci-debug.c | 1 + drivers/usb/host/uhci-hcd.h | 5 ++- drivers/usb/host/uhci-q.c | 78 +++++++++++++++++++++++-------------------- 3 files changed, 45 insertions(+), 39 deletions(-) diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c index 28c1c51ec47..6bbd33db935 100644 --- a/drivers/usb/host/uhci-debug.c +++ b/drivers/usb/host/uhci-debug.c @@ -119,6 +119,7 @@ static int uhci_show_urbp(struct urb_priv *urbp, char *buf, int len, int space) } out += sprintf(out, "%s%s", ptype, (urbp->fsbr ? " FSBR" : "")); + out += sprintf(out, " Actlen=%d", urbp->urb->actual_length); if (urbp->urb->status != -EINPROGRESS) out += sprintf(out, " Status=%d", urbp->urb->status); diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h index 8e577865049..3093ca25094 100644 --- a/drivers/usb/host/uhci-hcd.h +++ b/drivers/usb/host/uhci-hcd.h @@ -129,6 +129,7 @@ struct uhci_qh { struct list_head queue; /* Queue of urbps for this QH */ struct uhci_qh *skel; /* Skeleton for this QH */ struct uhci_td *dummy_td; /* Dummy TD to end the queue */ + struct uhci_td *post_td; /* Last TD completed */ unsigned int unlink_frame; /* When the QH was unlinked */ int state; /* QH_STATE_xxx; see above */ @@ -136,7 +137,7 @@ struct uhci_qh { unsigned int initial_toggle:1; /* Endpoint's current toggle value */ unsigned int needs_fixup:1; /* Must fix the TD toggle values */ - unsigned int is_stopped:1; /* Queue was stopped by an error */ + unsigned int is_stopped:1; /* Queue was stopped by error/unlink */ } __attribute__((aligned(16))); /* @@ -456,8 +457,6 @@ struct urb_priv { struct list_head td_list; unsigned fsbr : 1; /* URB turned on FSBR */ - unsigned short_transfer : 1; /* URB got a short transfer, no - * need to rescan */ }; diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index 30e36031fe2..888938d7823 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -161,6 +161,7 @@ static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, if (!qh) return NULL; + memset(qh, 0, sizeof(*qh)); qh->dma_handle = dma_handle; qh->element = UHCI_PTR_TERM; @@ -183,7 +184,6 @@ static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, } else { /* Skeleton QH */ qh->state = QH_STATE_ACTIVE; - qh->udev = NULL; qh->type = -1; } return qh; @@ -223,16 +223,10 @@ static void uhci_save_toggle(struct uhci_qh *qh, struct urb *urb) qh->type == USB_ENDPOINT_XFER_INT)) return; - /* Find the first active TD; that's the device's toggle state */ - list_for_each_entry(td, &urbp->td_list, list) { - if (td_status(td) & TD_CTRL_ACTIVE) { - qh->needs_fixup = 1; - qh->initial_toggle = uhci_toggle(td_token(td)); - return; - } - } - - WARN_ON(1); + WARN_ON(list_empty(&urbp->td_list)); + td = list_entry(urbp->td_list.next, struct uhci_td, list); + qh->needs_fixup = 1; + qh->initial_toggle = uhci_toggle(td_token(td)); } /* @@ -372,6 +366,12 @@ static void uhci_make_qh_idle(struct uhci_hcd *uhci, struct uhci_qh *qh) list_move(&qh->node, &uhci->idle_qh_list); qh->state = QH_STATE_IDLE; + /* Now that the QH is idle, its post_td isn't being used */ + if (qh->post_td) { + uhci_free_td(uhci, qh->post_td); + qh->post_td = NULL; + } + /* If anyone is waiting for a QH to become idle, wake them up */ if (uhci->num_waiting) wake_up_all(&uhci->waitqh); @@ -610,6 +610,8 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, qh->skel = uhci->skel_fs_control_qh; uhci_inc_fsbr(uhci, urb); } + + urb->actual_length = -8; /* Account for the SETUP packet */ return 0; nomem: @@ -767,34 +769,46 @@ static inline int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb, * Fix up the data structures following a short transfer */ static int uhci_fixup_short_transfer(struct uhci_hcd *uhci, - struct uhci_qh *qh, struct urb_priv *urbp, - struct uhci_td *short_td) + struct uhci_qh *qh, struct urb_priv *urbp) { struct uhci_td *td; - int ret = 0; + struct list_head *tmp; + int ret; td = list_entry(urbp->td_list.prev, struct uhci_td, list); if (qh->type == USB_ENDPOINT_XFER_CONTROL) { - urbp->short_transfer = 1; /* When a control transfer is short, we have to restart * the queue at the status stage transaction, which is * the last TD. */ + WARN_ON(list_empty(&urbp->td_list)); qh->element = cpu_to_le32(td->dma_handle); + tmp = td->list.prev; ret = -EINPROGRESS; - } else if (!urbp->short_transfer) { - urbp->short_transfer = 1; + } else { /* When a bulk/interrupt transfer is short, we have to * fix up the toggles of the following URBs on the queue * before restarting the queue at the next URB. */ - qh->initial_toggle = uhci_toggle(td_token(short_td)) ^ 1; + qh->initial_toggle = uhci_toggle(td_token(qh->post_td)) ^ 1; uhci_fixup_toggles(qh, 1); + if (list_empty(&urbp->td_list)) + td = qh->post_td; qh->element = td->link; + tmp = urbp->td_list.prev; + ret = 0; } + /* Remove all the TDs we skipped over, from tmp back to the start */ + while (tmp != &urbp->td_list) { + td = list_entry(tmp, struct uhci_td, list); + tmp = tmp->prev; + + uhci_remove_td_from_urb(td); + list_add(&td->remove_list, &uhci->td_remove_list); + } return ret; } @@ -805,29 +819,14 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb) { struct urb_priv *urbp = urb->hcpriv; struct uhci_qh *qh = urbp->qh; - struct uhci_td *td; - struct list_head *tmp; + struct uhci_td *td, *tmp; unsigned status; int ret = 0; - tmp = urbp->td_list.next; - - if (qh->type == USB_ENDPOINT_XFER_CONTROL) { - if (urbp->short_transfer) - tmp = urbp->td_list.prev; - else - urb->actual_length = -8; /* SETUP packet */ - } else - urb->actual_length = 0; - - - while (tmp != &urbp->td_list) { + list_for_each_entry_safe(td, tmp, &urbp->td_list, list) { unsigned int ctrlstat; int len; - td = list_entry(tmp, struct uhci_td, list); - tmp = tmp->next; - ctrlstat = td_status(td); status = uhci_status_bits(ctrlstat); if (status & TD_CTRL_ACTIVE) @@ -862,6 +861,12 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb) ret = 1; } + uhci_remove_td_from_urb(td); + if (qh->post_td) + list_add(&qh->post_td->remove_list, + &uhci->td_remove_list); + qh->post_td = td; + if (ret != 0) goto err; } @@ -882,7 +887,7 @@ err: (ret == -EREMOTEIO); } else /* Short packet received */ - ret = uhci_fixup_short_transfer(uhci, qh, urbp, td); + ret = uhci_fixup_short_transfer(uhci, qh, urbp); return ret; } @@ -1123,6 +1128,7 @@ __acquires(uhci->lock) struct uhci_td *ptd, *ltd; purbp = list_entry(urbp->node.prev, struct urb_priv, node); + WARN_ON(list_empty(&purbp->td_list)); ptd = list_entry(purbp->td_list.prev, struct uhci_td, list); ltd = list_entry(urbp->td_list.prev, struct uhci_td, -- cgit v1.2.3 From a0b458b64b2a3a4cb806dd5cd889bbf6c7e9d686 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 12 May 2006 11:23:19 -0400 Subject: [PATCH] UHCI: Move code for cleaning up unlinked URBs This patch (as681) moves some code for cleaning up after unlinked URBs out of the general completion pathway into the unlinking pathway. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/uhci-q.c | 57 +++++++++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index 888938d7823..64b6c74789f 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -204,25 +204,49 @@ static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) } /* - * When the currently executing URB is dequeued, save its current toggle value + * When a queue is stopped and a dequeued URB is given back, adjust + * the previous TD link (if the URB isn't first on the queue) or + * save its toggle value (if it is first and is currently executing). */ -static void uhci_save_toggle(struct uhci_qh *qh, struct urb *urb) +static void uhci_cleanup_queue(struct uhci_qh *qh, + struct urb *urb) { - struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; + struct urb_priv *urbp = urb->hcpriv; struct uhci_td *td; + /* Isochronous pipes don't use toggles and their TD link pointers + * get adjusted during uhci_urb_dequeue(). */ + if (qh->type == USB_ENDPOINT_XFER_ISOC) + return; + + /* If the URB isn't first on its queue, adjust the link pointer + * of the last TD in the previous URB. The toggle doesn't need + * to be saved since this URB can't be executing yet. */ + if (qh->queue.next != &urbp->node) { + struct urb_priv *purbp; + struct uhci_td *ptd; + + purbp = list_entry(urbp->node.prev, struct urb_priv, node); + WARN_ON(list_empty(&purbp->td_list)); + ptd = list_entry(purbp->td_list.prev, struct uhci_td, + list); + td = list_entry(urbp->td_list.prev, struct uhci_td, + list); + ptd->link = td->link; + return; + } + /* If the QH element pointer is UHCI_PTR_TERM then then currently * executing URB has already been unlinked, so this one isn't it. */ - if (qh_element(qh) == UHCI_PTR_TERM || - qh->queue.next != &urbp->node) + if (qh_element(qh) == UHCI_PTR_TERM) return; qh->element = UHCI_PTR_TERM; - /* Only bulk and interrupt pipes have to worry about toggles */ - if (!(qh->type == USB_ENDPOINT_XFER_BULK || - qh->type == USB_ENDPOINT_XFER_INT)) + /* Control pipes have to worry about toggles */ + if (qh->type == USB_ENDPOINT_XFER_CONTROL) return; + /* Save the next toggle value */ WARN_ON(list_empty(&urbp->td_list)); td = list_entry(urbp->td_list.next, struct uhci_td, list); qh->needs_fixup = 1; @@ -1121,21 +1145,6 @@ __acquires(uhci->lock) if (qh->type == USB_ENDPOINT_XFER_ISOC) uhci_unlink_isochronous_tds(uhci, urb); - /* If the URB isn't first on its queue, adjust the link pointer - * of the last TD in the previous URB. */ - else if (qh->queue.next != &urbp->node) { - struct urb_priv *purbp; - struct uhci_td *ptd, *ltd; - - purbp = list_entry(urbp->node.prev, struct urb_priv, node); - WARN_ON(list_empty(&purbp->td_list)); - ptd = list_entry(purbp->td_list.prev, struct uhci_td, - list); - ltd = list_entry(urbp->td_list.prev, struct uhci_td, - list); - ptd->link = ltd->link; - } - /* Take the URB off the QH's queue. If the queue is now empty, * this is a perfect time for a toggle fixup. */ list_del_init(&urbp->node); @@ -1237,7 +1246,7 @@ restart: list_for_each_entry(urbp, &qh->queue, node) { urb = urbp->urb; if (urb->status != -EINPROGRESS) { - uhci_save_toggle(qh, urb); + uhci_cleanup_queue(qh, urb); uhci_giveback_urb(uhci, qh, urb, regs); goto restart; } -- cgit v1.2.3 From 04538a255ac8b404c20cbf15867c9829254c470f Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 12 May 2006 11:29:04 -0400 Subject: [PATCH] UHCI: Eliminate the TD-removal list This patch (as682) gets rid of the TD-removal list in uhci-hcd. It is no longer needed because now TDs are not freed until we know the hardware isn't using them. It also simplifies the code for adding and removing TDs to/from URBs. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/uhci-hcd.c | 1 - drivers/usb/host/uhci-hcd.h | 5 --- drivers/usb/host/uhci-q.c | 92 +++++++++++++-------------------------------- 3 files changed, 27 insertions(+), 71 deletions(-) diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index d225e11f405..fb4c1a8cadf 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -492,7 +492,6 @@ static int uhci_start(struct usb_hcd *hcd) spin_lock_init(&uhci->lock); - INIT_LIST_HEAD(&uhci->td_remove_list); INIT_LIST_HEAD(&uhci->idle_qh_list); init_waitqueue_head(&uhci->waitqh); diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h index 3093ca25094..90ef7fbbf2f 100644 --- a/drivers/usb/host/uhci-hcd.h +++ b/drivers/usb/host/uhci-hcd.h @@ -228,7 +228,6 @@ struct uhci_td { dma_addr_t dma_handle; struct list_head list; - struct list_head remove_list; int frame; /* for iso: what frame? */ struct list_head fl_list; @@ -420,10 +419,6 @@ struct uhci_hcd { unsigned long resuming_ports; unsigned long ports_timeout; /* Time to stop signalling */ - /* List of TDs that are done, but waiting to be freed (race) */ - struct list_head td_remove_list; - unsigned int td_remove_age; /* Age in frames */ - struct list_head idle_qh_list; /* Where the idle QHs live */ int rh_numports; /* Number of root-hub ports */ diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index 64b6c74789f..12af6fb05a3 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -16,7 +16,6 @@ * (C) Copyright 2004-2005 Alan Stern, stern@rowland.harvard.edu */ -static void uhci_free_pending_tds(struct uhci_hcd *uhci); /* * Technically, updating td->status here is a race, but it's not really a @@ -51,7 +50,6 @@ static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci) td->frame = -1; INIT_LIST_HEAD(&td->list); - INIT_LIST_HEAD(&td->remove_list); INIT_LIST_HEAD(&td->fl_list); return td; @@ -61,8 +59,6 @@ static void uhci_free_td(struct uhci_hcd *uhci, struct uhci_td *td) { if (!list_empty(&td->list)) dev_warn(uhci_dev(uhci), "td %p still in list!\n", td); - if (!list_empty(&td->remove_list)) - dev_warn(uhci_dev(uhci), "td %p still in remove_list!\n", td); if (!list_empty(&td->fl_list)) dev_warn(uhci_dev(uhci), "td %p still in fl_list!\n", td); @@ -77,6 +73,16 @@ static inline void uhci_fill_td(struct uhci_td *td, u32 status, td->buffer = cpu_to_le32(buffer); } +static void uhci_add_td_to_urbp(struct uhci_td *td, struct urb_priv *urbp) +{ + list_add_tail(&td->list, &urbp->td_list); +} + +static void uhci_remove_td_from_urbp(struct uhci_td *td) +{ + list_del_init(&td->list); +} + /* * We insert Isochronous URBs directly into the frame list at the beginning */ @@ -421,21 +427,6 @@ static inline struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci, return urbp; } -static void uhci_add_td_to_urb(struct urb *urb, struct uhci_td *td) -{ - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - - list_add_tail(&td->list, &urbp->td_list); -} - -static void uhci_remove_td_from_urb(struct uhci_td *td) -{ - if (list_empty(&td->list)) - return; - - list_del_init(&td->list); -} - static void uhci_free_urb_priv(struct uhci_hcd *uhci, struct urb_priv *urbp) { @@ -445,20 +436,9 @@ static void uhci_free_urb_priv(struct uhci_hcd *uhci, dev_warn(uhci_dev(uhci), "urb %p still on QH's list!\n", urbp->urb); - uhci_get_current_frame_number(uhci); - if (uhci->frame_number + uhci->is_stopped != uhci->td_remove_age) { - uhci_free_pending_tds(uhci); - uhci->td_remove_age = uhci->frame_number; - } - - /* Check to see if the remove list is empty. Set the IOC bit */ - /* to force an interrupt so we can remove the TDs. */ - if (list_empty(&uhci->td_remove_list)) - uhci_set_next_interrupt(uhci); - list_for_each_entry_safe(td, tmp, &urbp->td_list, list) { - uhci_remove_td_from_urb(td); - list_add(&td->remove_list, &uhci->td_remove_list); + uhci_remove_td_from_urbp(td); + uhci_free_td(uhci, td); } urbp->urb->hcpriv = NULL; @@ -529,6 +509,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, int len = urb->transfer_buffer_length; dma_addr_t data = urb->transfer_dma; __le32 *plink; + struct urb_priv *urbp = urb->hcpriv; /* The "pipe" thing contains the destination in bits 8--18 */ destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP; @@ -542,7 +523,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, * Build the TD for the control request setup packet */ td = qh->dummy_td; - uhci_add_td_to_urb(urb, td); + uhci_add_td_to_urbp(td, urbp); uhci_fill_td(td, status, destination | uhci_explen(8), urb->setup_dma); plink = &td->link; @@ -574,7 +555,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, /* Alternate Data0/1 (start with Data1) */ destination ^= TD_TOKEN_TOGGLE; - uhci_add_td_to_urb(urb, td); + uhci_add_td_to_urbp(td, urbp); uhci_fill_td(td, status, destination | uhci_explen(pktsze), data); plink = &td->link; @@ -605,7 +586,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, status &= ~TD_CTRL_SPD; - uhci_add_td_to_urb(urb, td); + uhci_add_td_to_urbp(td, urbp); uhci_fill_td(td, status | TD_CTRL_IOC, destination | uhci_explen(0), 0); plink = &td->link; @@ -640,7 +621,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, nomem: /* Remove the dummy TD from the td_list so it doesn't get freed */ - uhci_remove_td_from_urb(qh->dummy_td); + uhci_remove_td_from_urbp(qh->dummy_td); return -ENOMEM; } @@ -656,6 +637,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, int len = urb->transfer_buffer_length; dma_addr_t data = urb->transfer_dma; __le32 *plink; + struct urb_priv *urbp = urb->hcpriv; unsigned int toggle; if (len < 0) @@ -693,7 +675,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, goto nomem; *plink = cpu_to_le32(td->dma_handle); } - uhci_add_td_to_urb(urb, td); + uhci_add_td_to_urbp(td, urbp); uhci_fill_td(td, status, destination | uhci_explen(pktsze) | (toggle << TD_TOKEN_TOGGLE_SHIFT), @@ -721,7 +703,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, goto nomem; *plink = cpu_to_le32(td->dma_handle); - uhci_add_td_to_urb(urb, td); + uhci_add_td_to_urbp(td, urbp); uhci_fill_td(td, status, destination | uhci_explen(0) | (toggle << TD_TOKEN_TOGGLE_SHIFT), @@ -758,7 +740,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, nomem: /* Remove the dummy TD from the td_list so it doesn't get freed */ - uhci_remove_td_from_urb(qh->dummy_td); + uhci_remove_td_from_urbp(qh->dummy_td); return -ENOMEM; } @@ -830,8 +812,8 @@ static int uhci_fixup_short_transfer(struct uhci_hcd *uhci, td = list_entry(tmp, struct uhci_td, list); tmp = tmp->prev; - uhci_remove_td_from_urb(td); - list_add(&td->remove_list, &uhci->td_remove_list); + uhci_remove_td_from_urbp(td); + uhci_free_td(uhci, td); } return ret; } @@ -885,10 +867,9 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb) ret = 1; } - uhci_remove_td_from_urb(td); + uhci_remove_td_from_urbp(td); if (qh->post_td) - list_add(&qh->post_td->remove_list, - &uhci->td_remove_list); + uhci_free_td(uhci, qh->post_td); qh->post_td = td; if (ret != 0) @@ -957,7 +938,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, if (!td) return -ENOMEM; - uhci_add_td_to_urb(urb, td); + uhci_add_td_to_urbp(td, urbp); uhci_fill_td(td, status, destination | uhci_explen(urb->iso_frame_desc[i].length), urb->transfer_dma + @@ -1267,17 +1248,6 @@ restart: uhci_make_qh_idle(uhci, qh); } -static void uhci_free_pending_tds(struct uhci_hcd *uhci) -{ - struct uhci_td *td, *tmp; - - list_for_each_entry_safe(td, tmp, &uhci->td_remove_list, remove_list) { - list_del_init(&td->remove_list); - - uhci_free_td(uhci, td); - } -} - /* * Process events in the schedule, but only in one thread at a time */ @@ -1298,9 +1268,6 @@ static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs) uhci_clear_next_interrupt(uhci); uhci_get_current_frame_number(uhci); - if (uhci->frame_number + uhci->is_stopped != uhci->td_remove_age) - uhci_free_pending_tds(uhci); - /* Go through all the QH queues and process the URBs in each one */ for (i = 0; i < UHCI_NUM_SKELQH - 1; ++i) { uhci->next_qh = list_entry(uhci->skelqh[i]->node.next, @@ -1316,12 +1283,7 @@ static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs) goto rescan; uhci->scan_in_progress = 0; - /* If the controller is stopped, we can finish these off right now */ - if (uhci->is_stopped) - uhci_free_pending_tds(uhci); - - if (list_empty(&uhci->td_remove_list) && - list_empty(&uhci->skel_unlink_qh->node)) + if (list_empty(&uhci->skel_unlink_qh->node)) uhci_clear_next_interrupt(uhci); else uhci_set_next_interrupt(uhci); -- cgit v1.2.3 From 84afddd7ac58adad00cb0e50d0af25fcf825668b Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 12 May 2006 11:35:45 -0400 Subject: [PATCH] UHCI: Reimplement FSBR This patch (as683) re-implements Full-Speed Bandwidth Reclamation (FSBR) properly. It keeps track of which endpoint queues have advanced, and when none have advanced for a sufficiently long time, FSBR is turned off. The next TD on each of the non-moving queues is modified to generate an interrupt on completion, so that FSBR can be re-enabled as soon as the hardware starts to make some progress. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/uhci-debug.c | 3 +- drivers/usb/host/uhci-hcd.c | 13 +--- drivers/usb/host/uhci-hcd.h | 15 +++- drivers/usb/host/uhci-hub.c | 1 - drivers/usb/host/uhci-q.c | 168 ++++++++++++++++++++++++++++++++---------- 5 files changed, 143 insertions(+), 57 deletions(-) diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c index 6bbd33db935..081c592fe8b 100644 --- a/drivers/usb/host/uhci-debug.c +++ b/drivers/usb/host/uhci-debug.c @@ -274,7 +274,8 @@ static int uhci_show_root_hub_state(struct uhci_hcd *uhci, char *buf, int len) default: rh_state = "?"; break; } - out += sprintf(out, "Root-hub state: %s\n", rh_state); + out += sprintf(out, "Root-hub state: %s FSBR: %d\n", + rh_state, uhci->fsbr_is_on); return out - buf; } diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index fb4c1a8cadf..395402eec5e 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -88,15 +88,6 @@ static void suspend_rh(struct uhci_hcd *uhci, enum uhci_rh_state new_state); static void wakeup_rh(struct uhci_hcd *uhci); static void uhci_get_current_frame_number(struct uhci_hcd *uhci); -/* If a transfer is still active after this much time, turn off FSBR */ -#define IDLE_TIMEOUT msecs_to_jiffies(50) -#define FSBR_DELAY msecs_to_jiffies(50) - -/* When we timeout an idle transfer for FSBR, we'll switch it over to */ -/* depth first traversal. We'll do it in groups of this number of TDs */ -/* to make sure it doesn't hog all of the bandwidth */ -#define DEPTH_INTERVAL 5 - #include "uhci-debug.c" #include "uhci-q.c" #include "uhci-hub.c" @@ -255,6 +246,7 @@ __acquires(uhci->lock) uhci_to_hcd(uhci)->poll_rh = !int_enable; uhci_scan_schedule(uhci, NULL); + uhci_fsbr_off(uhci); } static void start_rh(struct uhci_hcd *uhci) @@ -487,9 +479,6 @@ static int uhci_start(struct usb_hcd *hcd) hcd->uses_new_polling = 1; - uhci->fsbr = 0; - uhci->fsbrtimeout = 0; - spin_lock_init(&uhci->lock); INIT_LIST_HEAD(&uhci->idle_qh_list); diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h index 90ef7fbbf2f..04938e64799 100644 --- a/drivers/usb/host/uhci-hcd.h +++ b/drivers/usb/host/uhci-hcd.h @@ -84,6 +84,13 @@ #define CAN_SCHEDULE_FRAMES 1000 /* how far in the future frames * can be scheduled */ +/* When no queues need Full-Speed Bandwidth Reclamation, + * delay this long before turning FSBR off */ +#define FSBR_OFF_DELAY msecs_to_jiffies(400) + +/* If a queue hasn't advanced after this much time, assume it is stuck */ +#define QH_WAIT_TIMEOUT msecs_to_jiffies(200) + /* * Queue Headers @@ -131,6 +138,7 @@ struct uhci_qh { struct uhci_td *dummy_td; /* Dummy TD to end the queue */ struct uhci_td *post_td; /* Last TD completed */ + unsigned long advance_jiffies; /* Time of last queue advance */ unsigned int unlink_frame; /* When the QH was unlinked */ int state; /* QH_STATE_xxx; see above */ int type; /* Queue type (control, bulk, etc) */ @@ -138,6 +146,7 @@ struct uhci_qh { unsigned int initial_toggle:1; /* Endpoint's current toggle value */ unsigned int needs_fixup:1; /* Must fix the TD toggle values */ unsigned int is_stopped:1; /* Queue was stopped by error/unlink */ + unsigned int wait_expired:1; /* QH_WAIT_TIMEOUT has expired */ } __attribute__((aligned(16))); /* @@ -397,8 +406,7 @@ struct uhci_hcd { __le32 *frame; void **frame_cpu; /* CPU's frame list */ - int fsbr; /* Full-speed bandwidth reclamation */ - unsigned long fsbrtimeout; /* FSBR delay */ + unsigned long fsbr_jiffies; /* Time when FSBR was last wanted */ enum uhci_rh_state rh_state; unsigned long auto_stop_time; /* When to AUTO_STOP */ @@ -413,6 +421,7 @@ struct uhci_hcd { unsigned int working_RD:1; /* Suspended root hub doesn't need to be polled */ unsigned int is_initialized:1; /* Data structure is usable */ + unsigned int fsbr_is_on:1; /* FSBR is turned on */ /* Support for port suspend/resume/reset */ unsigned long port_c_suspend; /* Bit-arrays of ports */ @@ -451,7 +460,7 @@ struct urb_priv { struct uhci_qh *qh; /* QH for this URB */ struct list_head td_list; - unsigned fsbr : 1; /* URB turned on FSBR */ + unsigned fsbr:1; /* URB wants FSBR */ }; diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c index c8451d9578f..f53c116e0df 100644 --- a/drivers/usb/host/uhci-hub.c +++ b/drivers/usb/host/uhci-hub.c @@ -173,7 +173,6 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf) uhci_scan_schedule(uhci, NULL); if (uhci->hc_inaccessible) goto done; - check_fsbr(uhci); uhci_check_ports(uhci); status = get_hub_status_data(uhci, buf); diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index 12af6fb05a3..2be84b3b40f 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -37,6 +37,46 @@ static inline void uhci_clear_next_interrupt(struct uhci_hcd *uhci) uhci->term_td->status &= ~cpu_to_le32(TD_CTRL_IOC); } + +/* + * Full-Speed Bandwidth Reclamation (FSBR). + * We turn on FSBR whenever a queue that wants it is advancing, + * and leave it on for a short time thereafter. + */ +static void uhci_fsbr_on(struct uhci_hcd *uhci) +{ + uhci->fsbr_is_on = 1; + uhci->skel_term_qh->link = cpu_to_le32( + uhci->skel_fs_control_qh->dma_handle) | UHCI_PTR_QH; +} + +static void uhci_fsbr_off(struct uhci_hcd *uhci) +{ + uhci->fsbr_is_on = 0; + uhci->skel_term_qh->link = UHCI_PTR_TERM; +} + +static void uhci_add_fsbr(struct uhci_hcd *uhci, struct urb *urb) +{ + struct urb_priv *urbp = urb->hcpriv; + + if (!(urb->transfer_flags & URB_NO_FSBR)) + urbp->fsbr = 1; +} + +static void uhci_qh_wants_fsbr(struct uhci_hcd *uhci, struct uhci_qh *qh) +{ + struct urb_priv *urbp = + list_entry(qh->queue.next, struct urb_priv, node); + + if (urbp->fsbr) { + uhci->fsbr_jiffies = jiffies; + if (!uhci->fsbr_is_on) + uhci_fsbr_on(uhci); + } +} + + static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci) { dma_addr_t dma_handle; @@ -331,6 +371,10 @@ static void uhci_activate_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) qh->element = cpu_to_le32(td->dma_handle); } + /* Treat the queue as if it has just advanced */ + qh->wait_expired = 0; + qh->advance_jiffies = jiffies; + if (qh->state == QH_STATE_ACTIVE) return; qh->state = QH_STATE_ACTIVE; @@ -445,28 +489,6 @@ static void uhci_free_urb_priv(struct uhci_hcd *uhci, kmem_cache_free(uhci_up_cachep, urbp); } -static void uhci_inc_fsbr(struct uhci_hcd *uhci, struct urb *urb) -{ - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - - if ((!(urb->transfer_flags & URB_NO_FSBR)) && !urbp->fsbr) { - urbp->fsbr = 1; - if (!uhci->fsbr++ && !uhci->fsbrtimeout) - uhci->skel_term_qh->link = cpu_to_le32(uhci->skel_fs_control_qh->dma_handle) | UHCI_PTR_QH; - } -} - -static void uhci_dec_fsbr(struct uhci_hcd *uhci, struct urb *urb) -{ - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - - if ((!(urb->transfer_flags & URB_NO_FSBR)) && urbp->fsbr) { - urbp->fsbr = 0; - if (!--uhci->fsbr) - uhci->fsbrtimeout = jiffies + FSBR_DELAY; - } -} - /* * Map status to standard result codes * @@ -613,7 +635,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, qh->skel = uhci->skel_ls_control_qh; else { qh->skel = uhci->skel_fs_control_qh; - uhci_inc_fsbr(uhci, urb); + uhci_add_fsbr(uhci, urb); } urb->actual_length = -8; /* Account for the SETUP packet */ @@ -756,7 +778,7 @@ static inline int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb, qh->skel = uhci->skel_bulk_qh; ret = uhci_submit_common(uhci, urb, qh); if (ret == 0) - uhci_inc_fsbr(uhci, urb); + uhci_add_fsbr(uhci, urb); return ret; } @@ -1075,8 +1097,10 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd, * the QH is new and idle or else it's unlinked and waiting to * become idle, so we can activate it right away. But only if the * queue isn't stopped. */ - if (qh->queue.next == &urbp->node && !qh->is_stopped) + if (qh->queue.next == &urbp->node && !qh->is_stopped) { uhci_activate_qh(uhci, qh); + uhci_qh_wants_fsbr(uhci, qh); + } goto done; err_submit_failed: @@ -1135,7 +1159,6 @@ __acquires(uhci->lock) qh->needs_fixup = 0; } - uhci_dec_fsbr(uhci, urb); /* Safe since it checks */ uhci_free_urb_priv(uhci, urbp); switch (qh->type) { @@ -1239,6 +1262,18 @@ restart: if (!list_empty(&qh->queue)) { if (qh->needs_fixup) uhci_fixup_toggles(qh, 0); + + /* If the first URB on the queue wants FSBR but its time + * limit has expired, set the next TD to interrupt on + * completion before reactivating the QH. */ + urbp = list_entry(qh->queue.next, struct urb_priv, node); + if (urbp->fsbr && qh->wait_expired) { + struct uhci_td *td = list_entry(urbp->td_list.next, + struct uhci_td, list); + + td->status |= __cpu_to_le32(TD_CTRL_IOC); + } + uhci_activate_qh(uhci, qh); } @@ -1248,6 +1283,62 @@ restart: uhci_make_qh_idle(uhci, qh); } +/* + * Check for queues that have made some forward progress. + * Returns 0 if the queue is not Isochronous, is ACTIVE, and + * has not advanced since last examined; 1 otherwise. + */ +static int uhci_advance_check(struct uhci_hcd *uhci, struct uhci_qh *qh) +{ + struct urb_priv *urbp = NULL; + struct uhci_td *td; + int ret = 1; + unsigned status; + + if (qh->type == USB_ENDPOINT_XFER_ISOC) + return ret; + + /* Treat an UNLINKING queue as though it hasn't advanced. + * This is okay because reactivation will treat it as though + * it has advanced, and if it is going to become IDLE then + * this doesn't matter anyway. Furthermore it's possible + * for an UNLINKING queue not to have any URBs at all, or + * for its first URB not to have any TDs (if it was dequeued + * just as it completed). So it's not easy in any case to + * test whether such queues have advanced. */ + if (qh->state != QH_STATE_ACTIVE) { + urbp = NULL; + status = 0; + + } else { + urbp = list_entry(qh->queue.next, struct urb_priv, node); + td = list_entry(urbp->td_list.next, struct uhci_td, list); + status = td_status(td); + if (!(status & TD_CTRL_ACTIVE)) { + + /* We're okay, the queue has advanced */ + qh->wait_expired = 0; + qh->advance_jiffies = jiffies; + return ret; + } + ret = 0; + } + + /* The queue hasn't advanced; check for timeout */ + if (!qh->wait_expired && time_after(jiffies, + qh->advance_jiffies + QH_WAIT_TIMEOUT)) { + qh->wait_expired = 1; + + /* If the current URB wants FSBR, unlink it temporarily + * so that we can safely set the next TD to interrupt on + * completion. That way we'll know as soon as the queue + * starts moving again. */ + if (urbp && urbp->fsbr && !(status & TD_CTRL_IOC)) + uhci_unlink_qh(uhci, qh); + } + return ret; +} + /* * Process events in the schedule, but only in one thread at a time */ @@ -1262,7 +1353,7 @@ static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs) return; } uhci->scan_in_progress = 1; - rescan: +rescan: uhci->need_rescan = 0; uhci_clear_next_interrupt(uhci); @@ -1275,7 +1366,12 @@ static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs) while ((qh = uhci->next_qh) != uhci->skelqh[i]) { uhci->next_qh = list_entry(qh->node.next, struct uhci_qh, node); - uhci_scan_qh(uhci, qh, regs); + + if (uhci_advance_check(uhci, qh)) { + uhci_scan_qh(uhci, qh, regs); + if (qh->state == QH_STATE_ACTIVE) + uhci_qh_wants_fsbr(uhci, qh); + } } } @@ -1283,20 +1379,12 @@ static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs) goto rescan; uhci->scan_in_progress = 0; + if (uhci->fsbr_is_on && time_after(jiffies, + uhci->fsbr_jiffies + FSBR_OFF_DELAY)) + uhci_fsbr_off(uhci); + if (list_empty(&uhci->skel_unlink_qh->node)) uhci_clear_next_interrupt(uhci); else uhci_set_next_interrupt(uhci); } - -static void check_fsbr(struct uhci_hcd *uhci) -{ - /* For now, don't scan URBs for FSBR timeouts. - * Add it back in later... */ - - /* Really disable FSBR */ - if (!uhci->fsbr && uhci->fsbrtimeout && time_after_eq(jiffies, uhci->fsbrtimeout)) { - uhci->fsbrtimeout = 0; - uhci->skel_term_qh->link = UHCI_PTR_TERM; - } -} -- cgit v1.2.3 From b761d9d867bcc29e8de3e62d1d72b27e75078ca6 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 12 May 2006 11:41:59 -0400 Subject: [PATCH] UHCI: Work around old Intel bug Some old Intel UHCI controllers have a bug that has shown up in a few systems (the PIIX3 "Neptune" chip set). Until now there has not been any simple way to work around the bug, but the lastest changes in uhci-hcd have made it easy. This patch (as684) adds the work-around. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/uhci-q.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index 2be84b3b40f..76b0a9e95a7 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -13,7 +13,7 @@ * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface * support from usb-ohci.c by Adam Richter, adam@yggdrasil.com). * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c) - * (C) Copyright 2004-2005 Alan Stern, stern@rowland.harvard.edu + * (C) Copyright 2004-2006 Alan Stern, stern@rowland.harvard.edu */ @@ -1287,6 +1287,11 @@ restart: * Check for queues that have made some forward progress. * Returns 0 if the queue is not Isochronous, is ACTIVE, and * has not advanced since last examined; 1 otherwise. + * + * Early Intel controllers have a bug which causes qh->element sometimes + * not to advance when a TD completes successfully. The queue remains + * stuck on the inactive completed TD. We detect such cases and advance + * the element pointer by hand. */ static int uhci_advance_check(struct uhci_hcd *uhci, struct uhci_qh *qh) { @@ -1327,6 +1332,15 @@ static int uhci_advance_check(struct uhci_hcd *uhci, struct uhci_qh *qh) /* The queue hasn't advanced; check for timeout */ if (!qh->wait_expired && time_after(jiffies, qh->advance_jiffies + QH_WAIT_TIMEOUT)) { + + /* Detect the Intel bug and work around it */ + if (qh->post_td && qh_element(qh) == + cpu_to_le32(qh->post_td->dma_handle)) { + qh->element = qh->post_td->link; + qh->advance_jiffies = jiffies; + return 1; + } + qh->wait_expired = 1; /* If the current URB wants FSBR, unlink it temporarily -- cgit v1.2.3 From b9827e4b29edb4af1481b75efdf9ea2d8a7ffc96 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Tue, 16 May 2006 17:33:14 -0700 Subject: [PATCH] USB: correct the USB info in Documentation/power/swsusp.txt The swsusp.txt documentation harshes confusingly on USB, and this patch addresses the issue. It's harsh because it blames USB for some issues that are generic to all drivers -- especially those supporting removable media -- and it's confusing since it says that USB has the issue with "suspend" not just swsusp ... while in reality, USB doesn't have the issue when real system suspend states are used. Signed-off-by: David Brownell Acked-by: Pavel Machek Signed-off-by: Greg Kroah-Hartman --- Documentation/power/swsusp.txt | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/Documentation/power/swsusp.txt b/Documentation/power/swsusp.txt index d7814a113ee..516c5019013 100644 --- a/Documentation/power/swsusp.txt +++ b/Documentation/power/swsusp.txt @@ -18,10 +18,11 @@ Some warnings, first. * * (*) suspend/resume support is needed to make it safe. * - * If you have any filesystems on USB devices mounted before suspend, + * If you have any filesystems on USB devices mounted before software suspend, * they won't be accessible after resume and you may lose data, as though - * you have unplugged the USB devices with mounted filesystems on them - * (see the FAQ below for details). + * you have unplugged the USB devices with mounted filesystems on them; + * see the FAQ below for details. (This is not true for more traditional + * power states like "standby", which normally don't turn USB off.) You need to append resume=/dev/your_swap_partition to kernel command line. Then you suspend by @@ -204,7 +205,7 @@ Q: There don't seem to be any generally useful behavioral distinctions between SUSPEND and FREEZE. A: Doing SUSPEND when you are asked to do FREEZE is always correct, -but it may be unneccessarily slow. If you want USB to stay simple, +but it may be unneccessarily slow. If you want your driver to stay simple, slowness may not matter to you. It can always be fixed later. For devices like disk it does matter, you do not want to spindown for @@ -357,17 +358,25 @@ Q: Is this true that if I have a mounted filesystem on a USB device and I suspend to disk, I can lose data unless the filesystem has been mounted with "sync"? -A: That's right. It depends on your hardware, and it could be true even for -suspend-to-RAM. In fact, even with "-o sync" you can lose data if your -programs have information in buffers they haven't written out to disk. +A: That's right ... if you disconnect that device, you may lose data. +In fact, even with "-o sync" you can lose data if your programs have +information in buffers they haven't written out to a disk you disconnect, +or if you disconnect before the device finished saving data you wrote. -If you're lucky, your hardware will support low-power modes for USB -controllers while the system is asleep. Lots of hardware doesn't, -however. Shutting off the power to a USB controller is equivalent to -unplugging all the attached devices. +Software suspend normally powers down USB controllers, which is equivalent +to disconnecting all USB devices attached to your system. + +Your system might well support low-power modes for its USB controllers +while the system is asleep, maintaining the connection, using true sleep +modes like "suspend-to-RAM" or "standby". (Don't write "disk" to the +/sys/power/state file; write "standby" or "mem".) We've not seen any +hardware that can use these modes through software suspend, although in +theory some systems might support "platform" or "firmware" modes that +won't break the USB connections. Remember that it's always a bad idea to unplug a disk drive containing a -mounted filesystem. With USB that's true even when your system is asleep! -The safest thing is to unmount all USB-based filesystems before suspending -and remount them after resuming. +mounted filesystem. That's true even when your system is asleep! The +safest thing is to unmount all filesystems on removable media (such USB, +Firewire, CompactFlash, MMC, external SATA, or even IDE hotplug bays) +before suspending; then remount them after resuming. -- cgit v1.2.3 From e016683d595aacde78b9385aabd0b98c8915d885 Mon Sep 17 00:00:00 2001 From: Micah Dowty Date: Fri, 19 May 2006 11:20:11 -0700 Subject: [PATCH] USB: Remove 4088-byte limit on usbfs control URBs This patch removes the artificial 4088-byte limit that usbfs currently places on Control transfers. The USB spec does not specify a strict limit on the size of an entire control transfer. It does, however, state that the data stage "follows the same protocol rules as bulk transfers." (USB 2, 8.5.3) The level of support for large control transfers in real host controllers varies, but it's important to support at least 4K transfers. Windows enforces a maximum control transfer size of 4K, so there exists some hardware that requires a full 4096 byte data stage. Without this patch, we fall short of that by 8 bytes on architectures with a 4K page size, and it becomes impossible to support such hardware with a user-space driver. Since any limit placed on control transfers by usbfs would be arbitrary, this patch replaces the PAGE_SIZE limit with the same arbitrary limit used by bulk transfers. Signed-off-by: Micah Dowty Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 545da37afca..04f7504e098 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -923,8 +923,8 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_CONTROL) return -EINVAL; - /* min 8 byte setup packet, max arbitrary */ - if (uurb->buffer_length < 8 || uurb->buffer_length > PAGE_SIZE) + /* min 8 byte setup packet, max 8 byte setup plus an arbitrary data stage */ + if (uurb->buffer_length < 8 || uurb->buffer_length > (8 + MAX_USBFS_BUFFER_SIZE)) return -EINVAL; if (!(dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL))) return -ENOMEM; -- cgit v1.2.3 From 3612242e527eb47ee4756b5350f8bdf791aa5ede Mon Sep 17 00:00:00 2001 From: Micah Dowty Date: Fri, 19 May 2006 11:26:24 -0700 Subject: [PATCH] USB: Allow high-bandwidth isochronous packets via usbfs This patch increases an arbitrary limit on the size of individual isochronous packets submitted via usbfs. The limit is still arbitrary, but it's now large enough to support the maximum packet size used by high-bandwidth isochronous transfers. Signed-off-by: Micah Dowty Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 04f7504e098..b04ede772f2 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -982,7 +982,8 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, return -EFAULT; } for (totlen = u = 0; u < uurb->number_of_packets; u++) { - if (isopkt[u].length > 1023) { + /* arbitrary limit, sufficient for USB 2.0 high-bandwidth iso */ + if (isopkt[u].length > 8192) { kfree(isopkt); return -EINVAL; } -- cgit v1.2.3 From c433472658b4df11bd3590a59be79194a1ff43ae Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 19 May 2006 16:34:57 -0400 Subject: [PATCH] UHCI: use integer-sized frame numbers This patch (as687) changes uhci-hcd to keep track of frame numbers as full-sized integers rather than 11-bit values. This makes them a lot easier to handle and makes it possible to schedule beyond a 2-second window, should anyone ever want to do so. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/uhci-debug.c | 4 +++- drivers/usb/host/uhci-hcd.c | 40 ++++++++++++++++++++++------------------ drivers/usb/host/uhci-hcd.h | 3 +++ 3 files changed, 28 insertions(+), 19 deletions(-) diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c index 081c592fe8b..ecef5880cfd 100644 --- a/drivers/usb/host/uhci-debug.c +++ b/drivers/usb/host/uhci-debug.c @@ -289,7 +289,7 @@ static int uhci_show_status(struct uhci_hcd *uhci, char *buf, int len) unsigned short portsc1, portsc2; /* Try to make sure there's enough memory */ - if (len < 80 * 6) + if (len < 80 * 9) return 0; usbcmd = inw(io_addr + 0); @@ -328,6 +328,8 @@ static int uhci_show_status(struct uhci_hcd *uhci, char *buf, int len) out += sprintf(out, " sof = %02x\n", sof); out += uhci_show_sc(1, portsc1, out, len - (out - buf)); out += uhci_show_sc(2, portsc2, out, len - (out - buf)); + out += sprintf(out, "Most recent frame: %x\n", + uhci->frame_number); return out - buf; } diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 395402eec5e..5e75ad6dc29 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -13,7 +13,7 @@ * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface * support from usb-ohci.c by Adam Richter, adam@yggdrasil.com). * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c) - * (C) Copyright 2004-2005 Alan Stern, stern@rowland.harvard.edu + * (C) Copyright 2004-2006 Alan Stern, stern@rowland.harvard.edu * * Intel documents this fairly well, and as far as I know there * are no royalties or anything like that, but even so there are @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -146,7 +145,8 @@ static void configure_hc(struct uhci_hcd *uhci) outl(uhci->frame_dma_handle, uhci->io_addr + USBFLBASEADD); /* Set the current frame number */ - outw(uhci->frame_number, uhci->io_addr + USBFRNUM); + outw(uhci->frame_number & UHCI_MAX_SOF_NUMBER, + uhci->io_addr + USBFRNUM); /* Mark controller as not halted before we enable interrupts */ uhci_to_hcd(uhci)->state = HC_STATE_SUSPENDED; @@ -239,7 +239,6 @@ __acquires(uhci->lock) dev_warn(uhci_dev(uhci), "Controller not stopped yet!\n"); uhci_get_current_frame_number(uhci); - smp_wmb(); uhci->rh_state = new_state; uhci->is_stopped = UHCI_IS_STOPPED; @@ -253,7 +252,6 @@ static void start_rh(struct uhci_hcd *uhci) { uhci_to_hcd(uhci)->state = HC_STATE_RUNNING; uhci->is_stopped = 0; - smp_wmb(); /* Mark it configured and running with a 64-byte max packet. * All interrupts are enabled, even though RESUME won't do anything. @@ -360,12 +358,21 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs) /* * Store the current frame number in uhci->frame_number if the controller - * is runnning + * is runnning. Expand from 11 bits (of which we use only 10) to a + * full-sized integer. + * + * Like many other parts of the driver, this code relies on being polled + * more than once per second as long as the controller is running. */ static void uhci_get_current_frame_number(struct uhci_hcd *uhci) { - if (!uhci->is_stopped) - uhci->frame_number = inw(uhci->io_addr + USBFRNUM); + if (!uhci->is_stopped) { + unsigned delta; + + delta = (inw(uhci->io_addr + USBFRNUM) - uhci->frame_number) & + (UHCI_NUMFRAMES - 1); + uhci->frame_number += delta; + } } /* @@ -798,18 +805,15 @@ done: static int uhci_hcd_get_frame_number(struct usb_hcd *hcd) { struct uhci_hcd *uhci = hcd_to_uhci(hcd); - unsigned long flags; - int is_stopped; - int frame_number; + unsigned frame_number; + unsigned delta; /* Minimize latency by avoiding the spinlock */ - local_irq_save(flags); - is_stopped = uhci->is_stopped; - smp_rmb(); - frame_number = (is_stopped ? uhci->frame_number : - inw(uhci->io_addr + USBFRNUM)); - local_irq_restore(flags); - return frame_number; + frame_number = uhci->frame_number; + barrier(); + delta = (inw(uhci->io_addr + USBFRNUM) - frame_number) & + (UHCI_NUMFRAMES - 1); + return frame_number + delta; } static const char hcd_name[] = "uhci_hcd"; diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h index 04938e64799..c87ceaa178b 100644 --- a/drivers/usb/host/uhci-hcd.h +++ b/drivers/usb/host/uhci-hcd.h @@ -448,6 +448,9 @@ static inline struct usb_hcd *uhci_to_hcd(struct uhci_hcd *uhci) #define uhci_dev(u) (uhci_to_hcd(u)->self.controller) +/* Utility macro for comparing frame numbers */ +#define uhci_frame_before_eq(f1, f2) (0 <= (int) ((f2) - (f1))) + /* * Private per-URB data -- cgit v1.2.3 From 10b8e47d6b32bfba22874354c62770cb4e42aa6c Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 19 May 2006 16:39:52 -0400 Subject: [PATCH] UHCI: fix race in ISO dequeuing This patch (as688) fixes a small race in uhci-hcd. Because ISO queues aren't controlled by queue headers, they can't be unlinked. Only individual URBs can. So whenever multiple ISO URBs are dequeued, it's necessary to make sure the hardware is done with each one. We can't assume that dequeuing the first URB will suffice to unlink the entire queue. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/uhci-q.c | 48 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index 76b0a9e95a7..96ce4c87c87 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -194,7 +194,6 @@ static void uhci_unlink_isochronous_tds(struct uhci_hcd *uhci, struct urb *urb) list_for_each_entry(td, &urbp->td_list, list) uhci_remove_td_from_frame_list(uhci, td); - wmb(); } static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, @@ -253,17 +252,25 @@ static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) * When a queue is stopped and a dequeued URB is given back, adjust * the previous TD link (if the URB isn't first on the queue) or * save its toggle value (if it is first and is currently executing). + * + * Returns 0 if the URB should not yet be given back, 1 otherwise. */ -static void uhci_cleanup_queue(struct uhci_qh *qh, +static int uhci_cleanup_queue(struct uhci_hcd *uhci, struct uhci_qh *qh, struct urb *urb) { struct urb_priv *urbp = urb->hcpriv; struct uhci_td *td; + int ret = 1; /* Isochronous pipes don't use toggles and their TD link pointers - * get adjusted during uhci_urb_dequeue(). */ - if (qh->type == USB_ENDPOINT_XFER_ISOC) - return; + * get adjusted during uhci_urb_dequeue(). But since their queues + * cannot truly be stopped, we have to watch out for dequeues + * occurring after the nominal unlink frame. */ + if (qh->type == USB_ENDPOINT_XFER_ISOC) { + ret = (uhci->frame_number + uhci->is_stopped != + qh->unlink_frame); + return ret; + } /* If the URB isn't first on its queue, adjust the link pointer * of the last TD in the previous URB. The toggle doesn't need @@ -279,24 +286,25 @@ static void uhci_cleanup_queue(struct uhci_qh *qh, td = list_entry(urbp->td_list.prev, struct uhci_td, list); ptd->link = td->link; - return; + return ret; } /* If the QH element pointer is UHCI_PTR_TERM then then currently * executing URB has already been unlinked, so this one isn't it. */ if (qh_element(qh) == UHCI_PTR_TERM) - return; + return ret; qh->element = UHCI_PTR_TERM; /* Control pipes have to worry about toggles */ if (qh->type == USB_ENDPOINT_XFER_CONTROL) - return; + return ret; /* Save the next toggle value */ WARN_ON(list_empty(&urbp->td_list)); td = list_entry(urbp->td_list.next, struct uhci_td, list); qh->needs_fixup = 1; qh->initial_toggle = uhci_toggle(td_token(td)); + return ret; } /* @@ -953,7 +961,6 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, } else { /* FIXME: Sanity check */ } - urb->start_frame &= (UHCI_NUMFRAMES - 1); for (i = 0; i < urb->number_of_packets; i++) { td = uhci_alloc_td(uhci); @@ -1120,16 +1127,26 @@ static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) struct uhci_hcd *uhci = hcd_to_uhci(hcd); unsigned long flags; struct urb_priv *urbp; + struct uhci_qh *qh; spin_lock_irqsave(&uhci->lock, flags); urbp = urb->hcpriv; if (!urbp) /* URB was never linked! */ goto done; + qh = urbp->qh; /* Remove Isochronous TDs from the frame list ASAP */ - if (urbp->qh->type == USB_ENDPOINT_XFER_ISOC) + if (qh->type == USB_ENDPOINT_XFER_ISOC) { uhci_unlink_isochronous_tds(uhci, urb); - uhci_unlink_qh(uhci, urbp->qh); + mb(); + + /* If the URB has already started, update the QH unlink time */ + uhci_get_current_frame_number(uhci); + if (uhci_frame_before_eq(urb->start_frame, uhci->frame_number)) + qh->unlink_frame = uhci->frame_number; + } + + uhci_unlink_qh(uhci, qh); done: spin_unlock_irqrestore(&uhci->lock, flags); @@ -1250,7 +1267,14 @@ restart: list_for_each_entry(urbp, &qh->queue, node) { urb = urbp->urb; if (urb->status != -EINPROGRESS) { - uhci_cleanup_queue(qh, urb); + + /* Fix up the TD links and save the toggles for + * non-Isochronous queues. For Isochronous queues, + * test for too-recent dequeues. */ + if (!uhci_cleanup_queue(uhci, qh, urb)) { + qh->is_stopped = 0; + return; + } uhci_giveback_urb(uhci, qh, urb, regs); goto restart; } -- cgit v1.2.3 From caf3827a65af476c71eaeb79636869a4ab128d48 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 19 May 2006 16:44:55 -0400 Subject: [PATCH] UHCI: store the period in the queue header This patch (as689) stores the period for periodic transfers (interrupt and ISO) in the queue header. This is necessary for proper bandwidth tracking (not yet implemented). It also makes the scheduling of ISO transfers a bit more rigorous, with checks for out-of-bounds frame numbers. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/uhci-debug.c | 5 ++- drivers/usb/host/uhci-hcd.h | 36 +++------------------- drivers/usb/host/uhci-q.c | 72 +++++++++++++++++++++++++++++++++---------- 3 files changed, 63 insertions(+), 50 deletions(-) diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c index ecef5880cfd..ab8ba8220ad 100644 --- a/drivers/usb/host/uhci-debug.c +++ b/drivers/usb/host/uhci-debug.c @@ -153,7 +153,7 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space) char *qtype; /* Try to make sure there's enough memory */ - if (len < 80 * 6) + if (len < 80 * 7) return 0; switch (qh->type) { @@ -167,6 +167,9 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space) out += sprintf(out, "%*s[%p] %s QH link (%08x) element (%08x)\n", space, "", qh, qtype, le32_to_cpu(qh->link), le32_to_cpu(element)); + if (qh->type == USB_ENDPOINT_XFER_ISOC) + out += sprintf(out, "%*s period %d\n", + space, "", qh->period); if (element & UHCI_PTR_QH) out += sprintf(out, "%*s Element points to QH (bug?)\n", space, ""); diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h index c87ceaa178b..eaac6ddf03a 100644 --- a/drivers/usb/host/uhci-hcd.h +++ b/drivers/usb/host/uhci-hcd.h @@ -140,6 +140,8 @@ struct uhci_qh { unsigned long advance_jiffies; /* Time of last queue advance */ unsigned int unlink_frame; /* When the QH was unlinked */ + unsigned int period; /* For Interrupt and Isochronous QHs */ + int state; /* QH_STATE_xxx; see above */ int type; /* Queue type (control, bulk, etc) */ @@ -315,38 +317,8 @@ static inline u32 td_status(struct uhci_td *td) { #define skel_bulk_qh skelqh[12] #define skel_term_qh skelqh[13] -/* - * Search tree for determining where fits in the skelqh[] - * skeleton. - * - * An interrupt request should be placed into the slowest skelqh[] - * which meets the interval/period/frequency requirement. - * An interrupt request is allowed to be faster than but not slower. - * - * For a given , this function returns the appropriate/matching - * skelqh[] index value. - */ -static inline int __interval_to_skel(int interval) -{ - if (interval < 16) { - if (interval < 4) { - if (interval < 2) - return 9; /* int1 for 0-1 ms */ - return 8; /* int2 for 2-3 ms */ - } - if (interval < 8) - return 7; /* int4 for 4-7 ms */ - return 6; /* int8 for 8-15 ms */ - } - if (interval < 64) { - if (interval < 32) - return 5; /* int16 for 16-31 ms */ - return 4; /* int32 for 32-63 ms */ - } - if (interval < 128) - return 3; /* int64 for 64-127 ms */ - return 2; /* int128 for 128-255 ms (Max.) */ -} +/* Find the skelqh entry corresponding to an interval exponent */ +#define UHCI_SKEL_INDEX(exponent) (9 - exponent) /* diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index 96ce4c87c87..7acc23473c6 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -763,6 +763,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, wmb(); qh->dummy_td->status |= __constant_cpu_to_le32(TD_CTRL_ACTIVE); qh->dummy_td = td; + qh->period = urb->interval; usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), toggle); @@ -790,14 +791,30 @@ static inline int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb, return ret; } -static inline int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb, +static int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb, struct uhci_qh *qh) { + int exponent; + /* USB 1.1 interrupt transfers only involve one packet per interval. * Drivers can submit URBs of any length, but longer ones will need * multiple intervals to complete. */ - qh->skel = uhci->skelqh[__interval_to_skel(urb->interval)]; + + /* Figure out which power-of-two queue to use */ + for (exponent = 7; exponent >= 0; --exponent) { + if ((1 << exponent) <= urb->interval) + break; + } + if (exponent < 0) + return -EINVAL; + urb->interval = 1 << exponent; + + if (qh->period == 0) + qh->skel = uhci->skelqh[UHCI_SKEL_INDEX(exponent)]; + else if (qh->period != urb->interval) + return -EINVAL; /* Can't change the period */ + return uhci_submit_common(uhci, urb, qh); } @@ -937,31 +954,50 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, unsigned long destination, status; struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; - if (urb->number_of_packets > 900) /* 900? Why? */ + /* Values must not be too big (could overflow below) */ + if (urb->interval >= UHCI_NUMFRAMES || + urb->number_of_packets >= UHCI_NUMFRAMES) return -EFBIG; - status = TD_CTRL_ACTIVE | TD_CTRL_IOS; - destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe); + /* Check the period and figure out the starting frame number */ + uhci_get_current_frame_number(uhci); + if (qh->period == 0) { + if (urb->transfer_flags & URB_ISO_ASAP) { + urb->start_frame = uhci->frame_number + 10; + } else { + i = urb->start_frame - uhci->frame_number; + if (i <= 0 || i >= UHCI_NUMFRAMES) + return -EINVAL; + } + } else if (qh->period != urb->interval) { + return -EINVAL; /* Can't change the period */ - /* Figure out the starting frame number */ - if (urb->transfer_flags & URB_ISO_ASAP) { + } else { /* Pick up where the last URB leaves off */ if (list_empty(&qh->queue)) { - uhci_get_current_frame_number(uhci); - urb->start_frame = (uhci->frame_number + 10); - - } else { /* Go right after the last one */ - struct urb *last_urb; + frame = uhci->frame_number + 10; + } else { + struct urb *lurb; - last_urb = list_entry(qh->queue.prev, + lurb = list_entry(qh->queue.prev, struct urb_priv, node)->urb; - urb->start_frame = (last_urb->start_frame + - last_urb->number_of_packets * - last_urb->interval); + frame = lurb->start_frame + + lurb->number_of_packets * + lurb->interval; } - } else { + if (urb->transfer_flags & URB_ISO_ASAP) + urb->start_frame = frame; /* FIXME: Sanity check */ } + /* Make sure we won't have to go too far into the future */ + if (uhci_frame_before_eq(uhci->frame_number + UHCI_NUMFRAMES, + urb->start_frame + urb->number_of_packets * + urb->interval)) + return -EFBIG; + + status = TD_CTRL_ACTIVE | TD_CTRL_IOS; + destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe); + for (i = 0; i < urb->number_of_packets; i++) { td = uhci_alloc_td(uhci); if (!td) @@ -978,6 +1014,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, td->status |= __constant_cpu_to_le32(TD_CTRL_IOC); qh->skel = uhci->skel_iso_qh; + qh->period = urb->interval; /* Add the TDs to the frame list */ frame = urb->start_frame; @@ -1206,6 +1243,7 @@ __acquires(uhci->lock) uhci_unlink_qh(uhci, qh); /* Bandwidth stuff not yet implemented */ + qh->period = 0; } } -- cgit v1.2.3 From c8155cc5d839838f8425dbea568fc537337176a7 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 19 May 2006 16:52:35 -0400 Subject: [PATCH] UHCI: remove ISO TDs as they are used This patch (as690) does the same thing for ISO TDs as as680 did for non-ISO TDs: free them as they are used rather than all at once when an URB is complete. At the same time it fixes a minor buglet (I'm not aware of it ever affecting anyone): An ISO TD should be retired when its frame is over, regardless of whether or not the hardware has marked it inactive. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/uhci-debug.c | 14 ++++-- drivers/usb/host/uhci-hcd.h | 10 +++- drivers/usb/host/uhci-q.c | 103 ++++++++++++++++++++++++++++++------------ 3 files changed, 90 insertions(+), 37 deletions(-) diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c index ab8ba8220ad..6637a0e4997 100644 --- a/drivers/usb/host/uhci-debug.c +++ b/drivers/usb/host/uhci-debug.c @@ -127,7 +127,8 @@ static int uhci_show_urbp(struct urb_priv *urbp, char *buf, int len, int space) i = nactive = ninactive = 0; list_for_each_entry(td, &urbp->td_list, list) { - if (++i <= 10 || debug > 2) { + if (urbp->qh->type != USB_ENDPOINT_XFER_ISOC && + (++i <= 10 || debug > 2)) { out += sprintf(out, "%*s%d: ", space + 2, "", i); out += uhci_show_td(td, out, len - (out - buf), 0); } else { @@ -168,8 +169,9 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space) space, "", qh, qtype, le32_to_cpu(qh->link), le32_to_cpu(element)); if (qh->type == USB_ENDPOINT_XFER_ISOC) - out += sprintf(out, "%*s period %d\n", - space, "", qh->period); + out += sprintf(out, "%*s period %d frame %x desc [%p]\n", + space, "", qh->period, qh->iso_frame, + qh->iso_packet_desc); if (element & UHCI_PTR_QH) out += sprintf(out, "%*s Element points to QH (bug?)\n", space, ""); @@ -331,8 +333,10 @@ static int uhci_show_status(struct uhci_hcd *uhci, char *buf, int len) out += sprintf(out, " sof = %02x\n", sof); out += uhci_show_sc(1, portsc1, out, len - (out - buf)); out += uhci_show_sc(2, portsc2, out, len - (out - buf)); - out += sprintf(out, "Most recent frame: %x\n", - uhci->frame_number); + out += sprintf(out, "Most recent frame: %x (%d) " + "Last ISO frame: %x (%d)\n", + uhci->frame_number, uhci->frame_number & 1023, + uhci->last_iso_frame, uhci->last_iso_frame & 1023); return out - buf; } diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h index eaac6ddf03a..469b4268b85 100644 --- a/drivers/usb/host/uhci-hcd.h +++ b/drivers/usb/host/uhci-hcd.h @@ -128,8 +128,6 @@ struct uhci_qh { __le32 element; /* Queue element (TD) pointer */ /* Software fields */ - dma_addr_t dma_handle; - struct list_head node; /* Node in the list of QHs */ struct usb_host_endpoint *hep; /* Endpoint information */ struct usb_device *udev; @@ -138,13 +136,19 @@ struct uhci_qh { struct uhci_td *dummy_td; /* Dummy TD to end the queue */ struct uhci_td *post_td; /* Last TD completed */ + struct usb_iso_packet_descriptor *iso_packet_desc; + /* Next urb->iso_frame_desc entry */ unsigned long advance_jiffies; /* Time of last queue advance */ unsigned int unlink_frame; /* When the QH was unlinked */ unsigned int period; /* For Interrupt and Isochronous QHs */ + unsigned int iso_frame; /* Frame # for iso_packet_desc */ + int iso_status; /* Status for Isochronous URBs */ int state; /* QH_STATE_xxx; see above */ int type; /* Queue type (control, bulk, etc) */ + dma_addr_t dma_handle; + unsigned int initial_toggle:1; /* Endpoint's current toggle value */ unsigned int needs_fixup:1; /* Must fix the TD toggle values */ unsigned int is_stopped:1; /* Queue was stopped by error/unlink */ @@ -386,6 +390,8 @@ struct uhci_hcd { unsigned int frame_number; /* As of last check */ unsigned int is_stopped; #define UHCI_IS_STOPPED 9999 /* Larger than a frame # */ + unsigned int last_iso_frame; /* Frame of last scan */ + unsigned int cur_iso_frame; /* Frame for current scan */ unsigned int scan_in_progress:1; /* Schedule scan is running */ unsigned int need_rescan:1; /* Redo the schedule scan */ diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index 7acc23473c6..cbbaa4c1740 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -184,6 +184,24 @@ static inline void uhci_remove_td_from_frame_list(struct uhci_hcd *uhci, td->frame = -1; } +static inline void uhci_remove_tds_from_frame(struct uhci_hcd *uhci, + unsigned int framenum) +{ + struct uhci_td *ftd, *ltd; + + framenum &= (UHCI_NUMFRAMES - 1); + + ftd = uhci->frame_cpu[framenum]; + if (ftd) { + ltd = list_entry(ftd->fl_list.prev, struct uhci_td, fl_list); + uhci->frame[framenum] = ltd->link; + uhci->frame_cpu[framenum] = NULL; + + while (!list_empty(&ftd->fl_list)) + list_del_init(ftd->fl_list.prev); + } +} + /* * Remove all the TDs for an Isochronous URB from the frame list */ @@ -523,7 +541,6 @@ static int uhci_map_status(int status, int dir_out) return -ENOSR; if (status & TD_CTRL_STALLED) /* Stalled */ return -EPIPE; - WARN_ON(status & TD_CTRL_ACTIVE); /* Active */ return 0; } @@ -960,12 +977,12 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, return -EFBIG; /* Check the period and figure out the starting frame number */ - uhci_get_current_frame_number(uhci); if (qh->period == 0) { if (urb->transfer_flags & URB_ISO_ASAP) { + uhci_get_current_frame_number(uhci); urb->start_frame = uhci->frame_number + 10; } else { - i = urb->start_frame - uhci->frame_number; + i = urb->start_frame - uhci->last_iso_frame; if (i <= 0 || i >= UHCI_NUMFRAMES) return -EINVAL; } @@ -974,7 +991,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, } else { /* Pick up where the last URB leaves off */ if (list_empty(&qh->queue)) { - frame = uhci->frame_number + 10; + frame = qh->iso_frame; } else { struct urb *lurb; @@ -986,11 +1003,12 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, } if (urb->transfer_flags & URB_ISO_ASAP) urb->start_frame = frame; - /* FIXME: Sanity check */ + else if (urb->start_frame != frame) + return -EINVAL; } /* Make sure we won't have to go too far into the future */ - if (uhci_frame_before_eq(uhci->frame_number + UHCI_NUMFRAMES, + if (uhci_frame_before_eq(uhci->last_iso_frame + UHCI_NUMFRAMES, urb->start_frame + urb->number_of_packets * urb->interval)) return -EFBIG; @@ -1020,7 +1038,13 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, frame = urb->start_frame; list_for_each_entry(td, &urbp->td_list, list) { uhci_insert_td_in_frame_list(uhci, td, frame); - frame += urb->interval; + frame += qh->period; + } + + if (list_empty(&qh->queue)) { + qh->iso_packet_desc = &urb->iso_frame_desc[0]; + qh->iso_frame = urb->start_frame; + qh->iso_status = 0; } return 0; @@ -1028,37 +1052,44 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb) { - struct uhci_td *td; - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - int status; - int i, ret = 0; - - urb->actual_length = urb->error_count = 0; + struct uhci_td *td, *tmp; + struct urb_priv *urbp = urb->hcpriv; + struct uhci_qh *qh = urbp->qh; - i = 0; - list_for_each_entry(td, &urbp->td_list, list) { + list_for_each_entry_safe(td, tmp, &urbp->td_list, list) { + unsigned int ctrlstat; + int status; int actlength; - unsigned int ctrlstat = td_status(td); - if (ctrlstat & TD_CTRL_ACTIVE) + if (uhci_frame_before_eq(uhci->cur_iso_frame, qh->iso_frame)) return -EINPROGRESS; - actlength = uhci_actual_length(ctrlstat); - urb->iso_frame_desc[i].actual_length = actlength; - urb->actual_length += actlength; + uhci_remove_tds_from_frame(uhci, qh->iso_frame); + + ctrlstat = td_status(td); + if (ctrlstat & TD_CTRL_ACTIVE) { + status = -EXDEV; /* TD was added too late? */ + } else { + status = uhci_map_status(uhci_status_bits(ctrlstat), + usb_pipeout(urb->pipe)); + actlength = uhci_actual_length(ctrlstat); + + urb->actual_length += actlength; + qh->iso_packet_desc->actual_length = actlength; + qh->iso_packet_desc->status = status; + } - status = uhci_map_status(uhci_status_bits(ctrlstat), - usb_pipeout(urb->pipe)); - urb->iso_frame_desc[i].status = status; if (status) { urb->error_count++; - ret = status; + qh->iso_status = status; } - i++; + uhci_remove_td_from_urbp(td); + uhci_free_td(uhci, td); + qh->iso_frame += qh->period; + ++qh->iso_packet_desc; } - - return ret; + return qh->iso_status; } static int uhci_urb_enqueue(struct usb_hcd *hcd, @@ -1119,6 +1150,7 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd, } break; case USB_ENDPOINT_XFER_ISOC: + urb->error_count = 0; bustime = usb_check_bandwidth(urb->dev, urb); if (bustime < 0) { ret = bustime; @@ -1200,9 +1232,18 @@ __acquires(uhci->lock) { struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; - /* Isochronous TDs get unlinked directly from the frame list */ - if (qh->type == USB_ENDPOINT_XFER_ISOC) - uhci_unlink_isochronous_tds(uhci, urb); + /* When giving back the first URB in an Isochronous queue, + * reinitialize the QH's iso-related members for the next URB. */ + if (qh->type == USB_ENDPOINT_XFER_ISOC && + urbp->node.prev == &qh->queue && + urbp->node.next != &qh->queue) { + struct urb *nurb = list_entry(urbp->node.next, + struct urb_priv, node)->urb; + + qh->iso_packet_desc = &nurb->iso_frame_desc[0]; + qh->iso_frame = nurb->start_frame; + qh->iso_status = 0; + } /* Take the URB off the QH's queue. If the queue is now empty, * this is a perfect time for a toggle fixup. */ @@ -1434,6 +1475,7 @@ rescan: uhci_clear_next_interrupt(uhci); uhci_get_current_frame_number(uhci); + uhci->cur_iso_frame = uhci->frame_number; /* Go through all the QH queues and process the URBs in each one */ for (i = 0; i < UHCI_NUM_SKELQH - 1; ++i) { @@ -1451,6 +1493,7 @@ rescan: } } + uhci->last_iso_frame = uhci->cur_iso_frame; if (uhci->need_rescan) goto rescan; uhci->scan_in_progress = 0; -- cgit v1.2.3 From caa2a1226741e023a103e091a7f6dce7c42e82ee Mon Sep 17 00:00:00 2001 From: Franck Bui-Huu Date: Mon, 15 May 2006 19:23:53 +0200 Subject: [PATCH] Fix a deadlock in usbtest ctrl_complete functions acquires ctx->lock and tries to unlink all queued urbs in case of errors through usb_unlink_urb func. In its turn usb_unlink_urb calls, through the hcd driver, usb_hcd_giveback_urb which calls ctrl_complete again. At this time, ctx->lock is already taken by the same function. Signed-off-by: Franck Bui-Huu Cc: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/usbtest.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index ccc5e8238bd..b42ae6bfb12 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -802,7 +802,9 @@ error: if (u == urb || !u->dev) continue; + spin_unlock(&ctx->lock); status = usb_unlink_urb (u); + spin_lock(&ctx->lock); switch (status) { case -EINPROGRESS: case -EBUSY: -- cgit v1.2.3 From 782a7a632e4b0581ade665e3d89ee97c8db0f441 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 19 May 2006 13:20:20 -0700 Subject: [PATCH] USB: add usb_interrupt_msg() function for api completeness. Really just a wrapper around usb_bulk_msg() but now it's documented much better. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/message.c | 31 +++++++++++++++++++++++++++++++ include/linux/usb.h | 2 ++ 2 files changed, 33 insertions(+) diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 08fb20f06f3..b2f608b0538 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -157,6 +157,37 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u } +/** + * usb_interrupt_msg - Builds an interrupt urb, sends it off and waits for completion + * @usb_dev: pointer to the usb device to send the message to + * @pipe: endpoint "pipe" to send the message to + * @data: pointer to the data to send + * @len: length in bytes of the data to send + * @actual_length: pointer to a location to put the actual length transferred in bytes + * @timeout: time in msecs to wait for the message to complete before + * timing out (if 0 the wait is forever) + * Context: !in_interrupt () + * + * This function sends a simple interrupt message to a specified endpoint and + * waits for the message to complete, or timeout. + * + * If successful, it returns 0, otherwise a negative error number. The number + * of actual bytes transferred will be stored in the actual_length paramater. + * + * Don't use this function from within an interrupt context, like a bottom half + * handler. If you need an asynchronous message, or need to send a message + * from within interrupt context, use usb_submit_urb() If a thread in your + * driver uses this call, make sure your disconnect() method can wait for it to + * complete. Since you don't have a handle on the URB used, you can't cancel + * the request. + */ +int usb_interrupt_msg(struct usb_device *usb_dev, unsigned int pipe, + void *data, int len, int *actual_length, int timeout) +{ + return usb_bulk_msg(usb_dev, pipe, data, len, actual_length, timeout); +} +EXPORT_SYMBOL_GPL(usb_interrupt_msg); + /** * usb_bulk_msg - Builds a bulk urb, sends it off and waits for completion * @usb_dev: pointer to the usb device to send the message to diff --git a/include/linux/usb.h b/include/linux/usb.h index 1f492c0c704..317ec9f28bc 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -1008,6 +1008,8 @@ void usb_buffer_unmap_sg (struct usb_device *dev, unsigned pipe, extern int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, __u16 value, __u16 index, void *data, __u16 size, int timeout); +extern int usb_interrupt_msg(struct usb_device *usb_dev, unsigned int pipe, + void *data, int len, int *actual_length, int timeout); extern int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, void *data, int len, int *actual_length, int timeout); -- cgit v1.2.3 From 212a4b4ed1ea9a969f3f967b3e3a8075ad1cb4de Mon Sep 17 00:00:00 2001 From: Vitja Makarov Date: Wed, 31 May 2006 00:40:06 +0400 Subject: [PATCH] USB: new cp2101 device By the way I have to ask you to add new (vid,pid) pair to cp2101 driver. This device is argussoft's avr in-system programmer AS3M, http://atmel.argussoft.ru/hard.htm it's based on cp2101 chip and works pretty well with the linux driver. It could be used with argussoft's `asisp1109.exe' (http://atmel.argussoft.ru/download/software/as-tools.soft/asisp.zip) tool run under wine. Signed-off-by: Vitja Makarov Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp2101.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c index e0c2acdb3f0..f8c0cb28773 100644 --- a/drivers/usb/serial/cp2101.c +++ b/drivers/usb/serial/cp2101.c @@ -59,6 +59,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */ { USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */ { USB_DEVICE(0x10C4, 0x803B) }, /* Pololu USB-serial converter */ + { USB_DEVICE(0x10C4, 0x8066) }, /* Argussoft In-System Programmer */ { USB_DEVICE(0x10C4, 0x807A) }, /* Crumb128 board */ { USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */ { USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */ -- cgit v1.2.3 From 83196b52053068f0240371ad2efd9d6ad685bbeb Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 22 May 2006 12:26:31 -0400 Subject: [PATCH] gadgetfs: fix AIO interface bugs This patch (as691) fixes a few errors in the AIO interface for the gadgetfs driver. Now requests will complete properly instead of hanging. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/inode.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index 0eb010a3f5b..57bf24810f9 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c @@ -528,7 +528,7 @@ struct kiocb_priv { struct usb_request *req; struct ep_data *epdata; void *buf; - char __user *ubuf; + char __user *ubuf; /* NULL for writes */ unsigned actual; }; @@ -566,7 +566,6 @@ static ssize_t ep_aio_read_retry(struct kiocb *iocb) status = priv->actual; kfree(priv->buf); kfree(priv); - aio_put_req(iocb); return status; } @@ -580,8 +579,8 @@ static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req) spin_lock(&epdata->dev->lock); priv->req = NULL; priv->epdata = NULL; - if (NULL == iocb->ki_retry - || unlikely(0 == req->actual) + if (priv->ubuf == NULL + || unlikely(req->actual == 0) || unlikely(kiocbIsCancelled(iocb))) { kfree(req->buf); kfree(priv); @@ -618,7 +617,7 @@ ep_aio_rwtail( char __user *ubuf ) { - struct kiocb_priv *priv = (void *) &iocb->private; + struct kiocb_priv *priv; struct usb_request *req; ssize_t value; @@ -670,7 +669,7 @@ fail: kfree(priv); put_ep(epdata); } else - value = -EIOCBQUEUED; + value = (ubuf ? -EIOCBRETRY : -EIOCBQUEUED); return value; } -- cgit v1.2.3 From 0ae4ea8092e1277cfca07cade7eaba5f594076c1 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 22 May 2006 12:27:38 -0400 Subject: [PATCH] gadgetfs: fix memory leaks This patch (as692) fixes a few memory leaks in some unimportant error pathways of the gadgetfs driver. Signed-off-by: Alan Stern Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/inode.c | 51 ++++++++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index 57bf24810f9..aef0722b8f1 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c @@ -1038,7 +1038,7 @@ scan: /* ep0 can't deliver events when STATE_SETUP */ for (i = 0; i < n; i++) { if (dev->event [i].type == GADGETFS_SETUP) { - len = n = i + 1; + len = i + 1; len *= sizeof (struct usb_gadgetfs_event); n = 0; break; @@ -1586,13 +1586,13 @@ gadgetfs_create_file (struct super_block *sb, char const *name, static int activate_ep_files (struct dev_data *dev) { struct usb_ep *ep; + struct ep_data *data; gadget_for_each_ep (ep, dev->gadget) { - struct ep_data *data; data = kzalloc(sizeof(*data), GFP_KERNEL); if (!data) - goto enomem; + goto enomem0; data->state = STATE_EP_DISABLED; init_MUTEX (&data->lock); init_waitqueue_head (&data->wait); @@ -1607,21 +1607,23 @@ static int activate_ep_files (struct dev_data *dev) data->req = usb_ep_alloc_request (ep, GFP_KERNEL); if (!data->req) - goto enomem; + goto enomem1; data->inode = gadgetfs_create_file (dev->sb, data->name, data, &ep_config_operations, &data->dentry); - if (!data->inode) { - usb_ep_free_request(ep, data->req); - kfree (data); - goto enomem; - } + if (!data->inode) + goto enomem2; list_add_tail (&data->epfiles, &dev->epfiles); } return 0; -enomem: +enomem2: + usb_ep_free_request (ep, data->req); +enomem1: + put_dev (dev); + kfree (data); +enomem0: DBG (dev, "%s enomem\n", __FUNCTION__); destroy_ep_files (dev); return -ENOMEM; @@ -1792,7 +1794,7 @@ static struct usb_gadget_driver probe_driver = { * * After initialization, the device stays active for as long as that * $CHIP file is open. Events may then be read from that descriptor, - * such configuration notifications. More complex drivers will handle + * such as configuration notifications. More complex drivers will handle * some control requests in user space. */ @@ -2032,12 +2034,10 @@ gadgetfs_fill_super (struct super_block *sb, void *opts, int silent) NULL, &simple_dir_operations, S_IFDIR | S_IRUGO | S_IXUGO); if (!inode) - return -ENOMEM; + goto enomem0; inode->i_op = &simple_dir_inode_operations; - if (!(d = d_alloc_root (inode))) { - iput (inode); - return -ENOMEM; - } + if (!(d = d_alloc_root (inode))) + goto enomem1; sb->s_root = d; /* the ep0 file is named after the controller we expect; @@ -2045,21 +2045,28 @@ gadgetfs_fill_super (struct super_block *sb, void *opts, int silent) */ dev = dev_new (); if (!dev) - return -ENOMEM; + goto enomem2; dev->sb = sb; - if (!(inode = gadgetfs_create_file (sb, CHIP, + if (!gadgetfs_create_file (sb, CHIP, dev, &dev_init_operations, - &dev->dentry))) { - put_dev(dev); - return -ENOMEM; - } + &dev->dentry)) + goto enomem3; /* other endpoint files are available after hardware setup, * from binding to a controller. */ the_device = dev; return 0; + +enomem3: + put_dev (dev); +enomem2: + dput (d); +enomem1: + iput (inode); +enomem0: + return -ENOMEM; } /* "mount -t gadgetfs path /dev/gadget" ends up here */ -- cgit v1.2.3 From 9da2150f59e885d88b9eabe0a677f0fa4962f7b4 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 22 May 2006 16:47:13 -0400 Subject: [PATCH] usbtest: report errors in iso tests This patch (as693b) makes the usbtest driver report errors in the isochronous bulk transfer tests instead of always returning 0. As an arbitrary cutoff, an error is returned if more than 10% of the packet transfers fail. It also stops a test immediately upon receiving an URB submission error. For a test harness, it's especially important to report when errors occur! Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/usbtest.c | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index b42ae6bfb12..81ba14c73dc 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -1337,7 +1337,9 @@ struct iso_context { unsigned pending; spinlock_t lock; struct completion done; + int submit_error; unsigned long errors; + unsigned long packet_count; struct usbtest_dev *dev; }; @@ -1348,10 +1350,14 @@ static void iso_callback (struct urb *urb, struct pt_regs *regs) spin_lock(&ctx->lock); ctx->count--; + ctx->packet_count += urb->number_of_packets; if (urb->error_count > 0) ctx->errors += urb->error_count; + else if (urb->status != 0) + ctx->errors += urb->number_of_packets; - if (urb->status == 0 && ctx->count > (ctx->pending - 1)) { + if (urb->status == 0 && ctx->count > (ctx->pending - 1) + && !ctx->submit_error) { int status = usb_submit_urb (urb, GFP_ATOMIC); switch (status) { case 0: @@ -1362,6 +1368,8 @@ static void iso_callback (struct urb *urb, struct pt_regs *regs) status); /* FALLTHROUGH */ case -ENODEV: /* disconnected */ + case -ESHUTDOWN: /* endpoint disabled */ + ctx->submit_error = 1; break; } } @@ -1371,8 +1379,8 @@ static void iso_callback (struct urb *urb, struct pt_regs *regs) if (ctx->pending == 0) { if (ctx->errors) dev_dbg (&ctx->dev->intf->dev, - "iso test, %lu errors\n", - ctx->errors); + "iso test, %lu errors out of %lu\n", + ctx->errors, ctx->packet_count); complete (&ctx->done); } done: @@ -1433,15 +1441,14 @@ test_iso_queue (struct usbtest_dev *dev, struct usbtest_param *param, struct usb_device *udev; unsigned i; unsigned long packets = 0; - int status; + int status = 0; struct urb *urbs[10]; /* FIXME no limit */ if (param->sglen > 10) return -EDOM; + memset(&context, 0, sizeof context); context.count = param->iterations * param->sglen; - context.pending = param->sglen; - context.errors = 0; context.dev = dev; init_completion (&context.done); spin_lock_init (&context.lock); @@ -1473,6 +1480,7 @@ test_iso_queue (struct usbtest_dev *dev, struct usbtest_param *param, spin_lock_irq (&context.lock); for (i = 0; i < param->sglen; i++) { + ++context.pending; status = usb_submit_urb (urbs [i], SLAB_ATOMIC); if (status < 0) { ERROR (dev, "submit iso[%d], error %d\n", i, status); @@ -1483,12 +1491,26 @@ test_iso_queue (struct usbtest_dev *dev, struct usbtest_param *param, simple_free_urb (urbs [i]); context.pending--; + context.submit_error = 1; + break; } } spin_unlock_irq (&context.lock); wait_for_completion (&context.done); - return 0; + + /* + * Isochronous transfers are expected to fail sometimes. As an + * arbitrary limit, we will report an error if any submissions + * fail or if the transfer failure rate is > 10%. + */ + if (status != 0) + ; + else if (context.submit_error) + status = -EACCES; + else if (context.errors > context.packet_count / 10) + status = -EIO; + return status; fail: for (i = 0; i < param->sglen; i++) { -- cgit v1.2.3 From ad93375a30334cd97a61f7076d242e1cfdb66abc Mon Sep 17 00:00:00 2001 From: Pete Zaitcev Date: Mon, 22 May 2006 21:49:44 -0700 Subject: [PATCH] usb: io_edgeport, cleanup to unicode handling Clean up the unicode handling in io_edgeport. Make get_string size-limited. Signed-off-by: Pete Zaitcev Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/io_edgeport.c | 42 +++++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index b606c596810..c28f1f6902c 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -142,7 +142,7 @@ struct edgeport_port { /* This structure holds all of the individual device information */ struct edgeport_serial { - char name[MAX_NAME_LEN+1]; /* string name of this device */ + char name[MAX_NAME_LEN+2]; /* string name of this device */ struct edge_manuf_descriptor manuf_descriptor; /* the manufacturer descriptor */ struct edge_boot_descriptor boot_descriptor; /* the boot firmware descriptor */ @@ -270,7 +270,7 @@ static void get_manufacturing_desc (struct edgeport_serial *edge_serial); static void get_boot_desc (struct edgeport_serial *edge_serial); static void load_application_firmware (struct edgeport_serial *edge_serial); -static void unicode_to_ascii (char *string, __le16 *unicode, int unicode_size); +static void unicode_to_ascii(char *string, int buflen, __le16 *unicode, int unicode_size); // ************************************************************************ @@ -373,7 +373,7 @@ static void update_edgeport_E2PROM (struct edgeport_serial *edge_serial) * Get string descriptor from device * * * ************************************************************************/ -static int get_string (struct usb_device *dev, int Id, char *string) +static int get_string (struct usb_device *dev, int Id, char *string, int buflen) { struct usb_string_descriptor StringDesc; struct usb_string_descriptor *pStringDesc; @@ -395,7 +395,7 @@ static int get_string (struct usb_device *dev, int Id, char *string) return 0; } - unicode_to_ascii(string, pStringDesc->wData, pStringDesc->bLength/2-1); + unicode_to_ascii(string, buflen, pStringDesc->wData, pStringDesc->bLength/2); kfree(pStringDesc); return strlen(string); @@ -2564,16 +2564,20 @@ static void change_port_settings (struct edgeport_port *edge_port, struct termio * ASCII range, but it's only for debugging... * NOTE: expects the unicode in LE format ****************************************************************************/ -static void unicode_to_ascii (char *string, __le16 *unicode, int unicode_size) +static void unicode_to_ascii(char *string, int buflen, __le16 *unicode, int unicode_size) { int i; - if (unicode_size <= 0) + if (buflen <= 0) /* never happens, but... */ return; + --buflen; /* space for nul */ - for (i = 0; i < unicode_size; ++i) + for (i = 0; i < unicode_size; i++) { + if (i >= buflen) + break; string[i] = (char)(le16_to_cpu(unicode[i])); - string[unicode_size] = 0x00; + } + string[i] = 0x00; } @@ -2603,11 +2607,17 @@ static void get_manufacturing_desc (struct edgeport_serial *edge_serial) dbg(" BoardRev: %d", edge_serial->manuf_descriptor.BoardRev); dbg(" NumPorts: %d", edge_serial->manuf_descriptor.NumPorts); dbg(" DescDate: %d/%d/%d", edge_serial->manuf_descriptor.DescDate[0], edge_serial->manuf_descriptor.DescDate[1], edge_serial->manuf_descriptor.DescDate[2]+1900); - unicode_to_ascii (string, edge_serial->manuf_descriptor.SerialNumber, edge_serial->manuf_descriptor.SerNumLength/2-1); + unicode_to_ascii(string, 30, + edge_serial->manuf_descriptor.SerialNumber, + edge_serial->manuf_descriptor.SerNumLength/2); dbg(" SerialNumber: %s", string); - unicode_to_ascii (string, edge_serial->manuf_descriptor.AssemblyNumber, edge_serial->manuf_descriptor.AssemblyNumLength/2-1); + unicode_to_ascii(string, 30, + edge_serial->manuf_descriptor.AssemblyNumber, + edge_serial->manuf_descriptor.AssemblyNumLength/2); dbg(" AssemblyNumber: %s", string); - unicode_to_ascii (string, edge_serial->manuf_descriptor.OemAssyNumber, edge_serial->manuf_descriptor.OemAssyNumLength/2-1); + unicode_to_ascii(string, 30, + edge_serial->manuf_descriptor.OemAssyNumber, + edge_serial->manuf_descriptor.OemAssyNumLength/2); dbg(" OemAssyNumber: %s", string); dbg(" UartType: %d", edge_serial->manuf_descriptor.UartType); dbg(" IonPid: %d", edge_serial->manuf_descriptor.IonPid); @@ -2735,11 +2745,11 @@ static int edge_startup (struct usb_serial *serial) usb_set_serial_data(serial, edge_serial); /* get the name for the device from the device */ - if ( (i = get_string(dev, dev->descriptor.iManufacturer, &edge_serial->name[0])) != 0) { - edge_serial->name[i-1] = ' '; - } - - get_string(dev, dev->descriptor.iProduct, &edge_serial->name[i]); + i = get_string(dev, dev->descriptor.iManufacturer, + &edge_serial->name[0], MAX_NAME_LEN+1); + edge_serial->name[i++] = ' '; + get_string(dev, dev->descriptor.iProduct, + &edge_serial->name[i], MAX_NAME_LEN+2 - i); dev_info(&serial->dev->dev, "%s detected\n", edge_serial->name); -- cgit v1.2.3 From cf2c7481d2ff7f0c266de873b2fe93883e9782f9 Mon Sep 17 00:00:00 2001 From: Pete Zaitcev Date: Mon, 22 May 2006 21:58:49 -0700 Subject: [PATCH] USB serial: encapsulate schedule_work, remove double-calling I'm going to throw schedule_work away, it's retarded. But for starters, let's have it encapsulated. Also, generic and whiteheat were both calling usb_serial_port_softint and scheduled work. Only one was necessary. Signed-off-by: Pete Zaitcev Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cyberjack.c | 2 +- drivers/usb/serial/cypress_m8.c | 2 +- drivers/usb/serial/empeg.c | 2 +- drivers/usb/serial/ftdi_sio.c | 2 +- drivers/usb/serial/garmin_gps.c | 2 +- drivers/usb/serial/generic.c | 4 +--- drivers/usb/serial/ipaq.c | 2 +- drivers/usb/serial/ipw.c | 2 +- drivers/usb/serial/ir-usb.c | 2 +- drivers/usb/serial/keyspan.c | 2 +- drivers/usb/serial/kl5kusb105.c | 3 +-- drivers/usb/serial/omninet.c | 2 +- drivers/usb/serial/option.c | 3 +-- drivers/usb/serial/pl2303.c | 2 +- drivers/usb/serial/usb-serial.c | 14 ++++++++++++-- drivers/usb/serial/usb-serial.h | 2 +- drivers/usb/serial/visor.c | 2 +- drivers/usb/serial/whiteheat.c | 4 +--- 18 files changed, 29 insertions(+), 25 deletions(-) diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c index 2357b1d102d..1fd5c5a9f2e 100644 --- a/drivers/usb/serial/cyberjack.c +++ b/drivers/usb/serial/cyberjack.c @@ -469,7 +469,7 @@ static void cyberjack_write_bulk_callback (struct urb *urb, struct pt_regs *regs exit: spin_unlock(&priv->lock); - schedule_work(&port->work); + usb_serial_port_softint(port); } static int __init cyberjack_init (void) diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index 7212fbe3b6f..5de76efe1b3 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -824,7 +824,7 @@ send: priv->bytes_out += count; /* do not count the line control and size bytes */ spin_unlock_irqrestore(&priv->lock, flags); - schedule_work(&port->work); + usb_serial_port_softint(port); } /* cypress_send */ diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c index 63f7c78a115..afca1eae5fb 100644 --- a/drivers/usb/serial/empeg.c +++ b/drivers/usb/serial/empeg.c @@ -335,7 +335,7 @@ static void empeg_write_bulk_callback (struct urb *urb, struct pt_regs *regs) return; } - schedule_work(&port->work); + usb_serial_port_softint(port); } diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 1122a0da41c..590c7ec851d 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1472,7 +1472,7 @@ static void ftdi_write_bulk_callback (struct urb *urb, struct pt_regs *regs) return; } - schedule_work(&port->work); + usb_serial_port_softint(port); } /* ftdi_write_bulk_callback */ diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index 5ec9bf5bac8..04767759cf8 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c @@ -1012,7 +1012,7 @@ static void garmin_write_bulk_callback (struct urb *urb, struct pt_regs *regs) garmin_data_p->flags |= CLEAR_HALT_REQUIRED; } - schedule_work(&port->work); + usb_serial_port_softint(port); } diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index c62cc287651..07a478c59fb 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -299,9 +299,7 @@ void usb_serial_generic_write_bulk_callback (struct urb *urb, struct pt_regs *re return; } - usb_serial_port_softint((void *)port); - - schedule_work(&port->work); + usb_serial_port_softint(port); } EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback); diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c index 9a5c9798956..9da6d2a8f2b 100644 --- a/drivers/usb/serial/ipaq.c +++ b/drivers/usb/serial/ipaq.c @@ -870,7 +870,7 @@ static void ipaq_write_bulk_callback(struct urb *urb, struct pt_regs *regs) spin_unlock_irqrestore(&write_list_lock, flags); } - schedule_work(&port->work); + usb_serial_port_softint(port); } static int ipaq_write_room(struct usb_serial_port *port) diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c index e760a70242c..a4a0bfeaab0 100644 --- a/drivers/usb/serial/ipw.c +++ b/drivers/usb/serial/ipw.c @@ -376,7 +376,7 @@ static void ipw_write_bulk_callback(struct urb *urb, struct pt_regs *regs) if (urb->status) dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); - schedule_work(&port->work); + usb_serial_port_softint(port); } static int ipw_write(struct usb_serial_port *port, const unsigned char *buf, int count) diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c index 426182ddc42..9432c730227 100644 --- a/drivers/usb/serial/ir-usb.c +++ b/drivers/usb/serial/ir-usb.c @@ -408,7 +408,7 @@ static void ir_write_bulk_callback (struct urb *urb, struct pt_regs *regs) urb->actual_length, urb->transfer_buffer); - schedule_work(&port->work); + usb_serial_port_softint(port); } static void ir_read_bulk_callback (struct urb *urb, struct pt_regs *regs) diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 052b735c4fb..2cf6ade704e 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -481,7 +481,7 @@ static void usa2x_outdat_callback(struct urb *urb, struct pt_regs *regs) dbg ("%s - urb %d", __FUNCTION__, urb == p_priv->out_urbs[1]); if (port->open_count) - schedule_work(&port->work); + usb_serial_port_softint(port); } static void usa26_inack_callback(struct urb *urb, struct pt_regs *regs) diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c index 78335a5f774..65d79f630fa 100644 --- a/drivers/usb/serial/kl5kusb105.c +++ b/drivers/usb/serial/kl5kusb105.c @@ -569,8 +569,7 @@ static void klsi_105_write_bulk_callback ( struct urb *urb, struct pt_regs *regs return; } - /* from generic_write_bulk_callback */ - schedule_work(&port->work); + usb_serial_port_softint(port); } /* klsi_105_write_bulk_completion_callback */ diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index 238033a8709..6dcdb5f598b 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -320,7 +320,7 @@ static void omninet_write_bulk_callback (struct urb *urb, struct pt_regs *regs) return; } - schedule_work(&port->work); + usb_serial_port_softint(port); } diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 5cf2b80add7..759d3608718 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -365,8 +365,7 @@ static void option_outdat_callback(struct urb *urb, struct pt_regs *regs) port = (struct usb_serial_port *) urb->context; - if (port->open_count) - schedule_work(&port->work); + usb_serial_port_softint(port); } static void option_instat_callback(struct urb *urb, struct pt_regs *regs) diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index c96714bb1cb..2ca6dd94796 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -314,7 +314,7 @@ static void pl2303_send(struct usb_serial_port *port) // TODO: reschedule pl2303_send } - schedule_work(&port->work); + usb_serial_port_softint(port); } static int pl2303_write_room(struct usb_serial_port *port) diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 92200f05b53..7a1cc1b0497 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -531,7 +531,17 @@ exit: return -EINVAL; } -void usb_serial_port_softint(void *private) +/* + * We would be calling tty_wakeup here, but unfortunately some line + * disciplines have an annoying habit of calling tty->write from + * the write wakeup callback (e.g. n_hdlc.c). + */ +void usb_serial_port_softint(struct usb_serial_port *port) +{ + schedule_work(&port->work); +} + +static void usb_serial_port_work(void *private) { struct usb_serial_port *port = private; struct tty_struct *tty; @@ -794,7 +804,7 @@ int usb_serial_probe(struct usb_interface *interface, port->serial = serial; spin_lock_init(&port->lock); mutex_init(&port->mutex); - INIT_WORK(&port->work, usb_serial_port_softint, port); + INIT_WORK(&port->work, usb_serial_port_work, port); serial->port[i] = port; } diff --git a/drivers/usb/serial/usb-serial.h b/drivers/usb/serial/usb-serial.h index c07ece3fef1..d53ea9b11e8 100644 --- a/drivers/usb/serial/usb-serial.h +++ b/drivers/usb/serial/usb-serial.h @@ -236,7 +236,7 @@ struct usb_serial_driver { extern int usb_serial_register(struct usb_serial_driver *driver); extern void usb_serial_deregister(struct usb_serial_driver *driver); -extern void usb_serial_port_softint(void *private); +extern void usb_serial_port_softint(struct usb_serial_port *port); extern int usb_serial_probe(struct usb_interface *iface, const struct usb_device_id *id); extern void usb_serial_disconnect(struct usb_interface *iface); diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index f5c3841d484..9e89b8d54f7 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c @@ -480,7 +480,7 @@ static void visor_write_bulk_callback (struct urb *urb, struct pt_regs *regs) --priv->outstanding_urbs; spin_unlock_irqrestore(&priv->lock, flags); - schedule_work(&port->work); + usb_serial_port_softint(port); } diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index f806553cd9a..582860ac876 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -1089,9 +1089,7 @@ static void whiteheat_write_callback(struct urb *urb, struct pt_regs *regs) return; } - usb_serial_port_softint((void *)port); - - schedule_work(&port->work); + usb_serial_port_softint(port); } -- cgit v1.2.3 From 6f065f70c0c1bfb0b8212438cee21e68aa155887 Mon Sep 17 00:00:00 2001 From: Pete Zaitcev Date: Mon, 22 May 2006 22:02:32 -0700 Subject: [PATCH] USB: Improve Kconfig comment for mct_u232 Add a couple of supported devices into the help message. It's a long story... I promised this comment changed to a user long ago, so I'd like to have that promise kept. In reality though, nobody is likely to read this anyway. Signed-off-by: Pete Zaitcev Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index 5c60be52156..12ad6f0897e 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig @@ -417,7 +417,7 @@ config USB_SERIAL_MCT_U232 Magic Control Technology Corp. (U232 is one of the model numbers). This driver also works with Sitecom U232-P25 and D-Link DU-H3SP USB - BAY devices. + BAY, Belkin F5U109, and Belkin F5U409 devices. To compile this driver as a module, choose M here: the module will be called mct_u232. -- cgit v1.2.3 From 80b47853b19114dd53e83e15bf1db3e183a66824 Mon Sep 17 00:00:00 2001 From: Pete Zaitcev Date: Mon, 22 May 2006 22:05:17 -0700 Subject: [PATCH] USB: Syntax cleanup for pl2303 (trailing backslash) Remove the silly trailing backslash. Signed-off-by: Pete Zaitcev Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/pl2303.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 2ca6dd94796..d8870438720 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -600,7 +600,7 @@ static void pl2303_close (struct usb_serial_port *port, struct file *filp) unsigned int c_cflag; int bps; long timeout; - wait_queue_t wait; \ + wait_queue_t wait; dbg("%s - port %d", __FUNCTION__, port->number); -- cgit v1.2.3 From 3428cc43d23f125dcb31c981aa91535dd3c4cb0d Mon Sep 17 00:00:00 2001 From: Franck Bui-Huu Date: Wed, 24 May 2006 16:57:28 +0200 Subject: [PATCH] usb-storage: get rid of the timer during URB submission This patch uses completion timeout instead of a timer to implement a timeout when submitting an URB. It also put the task in interruptible state instead of an uninterruptible one while waiting for the completion. Signed-off-by: Franck Bui-Huu Signed-off-by: Matthew Dharm Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/transport.c | 38 ++++++++++---------------------------- 1 file changed, 10 insertions(+), 28 deletions(-) diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index 7ca896a342e..038f4582ca0 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c @@ -115,19 +115,6 @@ static void usb_stor_blocking_completion(struct urb *urb, struct pt_regs *regs) complete(urb_done_ptr); } - -/* This is the timeout handler which will cancel an URB when its timeout - * expires. - */ -static void timeout_handler(unsigned long us_) -{ - struct us_data *us = (struct us_data *) us_; - - if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->flags)) { - US_DEBUGP("Timeout -- cancelling URB\n"); - usb_unlink_urb(us->current_urb); - } -} /* This is the common part of the URB message submission code * @@ -138,7 +125,7 @@ static void timeout_handler(unsigned long us_) static int usb_stor_msg_common(struct us_data *us, int timeout) { struct completion urb_done; - struct timer_list to_timer; + long timeleft; int status; /* don't submit URBs during abort/disconnect processing */ @@ -185,22 +172,17 @@ static int usb_stor_msg_common(struct us_data *us, int timeout) } } - /* submit the timeout timer, if a timeout was requested */ - if (timeout > 0) { - init_timer(&to_timer); - to_timer.expires = jiffies + timeout; - to_timer.function = timeout_handler; - to_timer.data = (unsigned long) us; - add_timer(&to_timer); - } - /* wait for the completion of the URB */ - wait_for_completion(&urb_done); - clear_bit(US_FLIDX_URB_ACTIVE, &us->flags); + timeleft = wait_for_completion_interruptible_timeout( + &urb_done, timeout ? : MAX_SCHEDULE_TIMEOUT); - /* clean up the timeout timer */ - if (timeout > 0) - del_timer_sync(&to_timer); + clear_bit(US_FLIDX_URB_ACTIVE, &us->flags); + + if (timeleft <= 0) { + US_DEBUGP("%s -- cancelling URB\n", + timeleft == 0 ? "Timeout" : "Signal"); + usb_unlink_urb(us->current_urb); + } /* return the URB status */ return us->current_urb->status; -- cgit v1.2.3 From ba47f66bd9fc451e9ce88f291e057b2f4910d01c Mon Sep 17 00:00:00 2001 From: Dan Streetman Date: Wed, 24 May 2006 09:39:16 -0700 Subject: [PATCH] improved TT scheduling for EHCI This updates the EHCI driver by adding an improved scheduler for the transaction translators, found in USB 2.0 hubs and used for low and full speed devices. - adds periodic_tt_usecs() and some helper functions, which does the same thing that "periodic_usecs" does, except on the other side of the TT, i.e. it calculates the low/fullspeed bandwidth usage instead of highspeed. - adds a tt_available() function which is the new implementation of what tt_no_collision() does ... while tt_no_collision() ensures that each TT handles only 1 periodic transfer at a time (a very pessimistic approach) this version instead tracks bandwidth and allows each TT to handle as many transfers as will fit on each TT's downstream bus (closer to best-case). The new scheduler is selected by a config option, marked as EXPERIMENTAL so it can be tested (and more broadly reviewed) for a while until it seems safe to remove the original scheduler. Signed-off-by: Dan Streetman Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/Kconfig | 20 +++- drivers/usb/host/ehci-sched.c | 216 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 234 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index e27b79a3c05..c060eb9b3b1 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -47,7 +47,25 @@ config USB_EHCI_ROOT_HUB_TT controller is needed. It's safe to say "y" even if your controller doesn't support this feature. - This supports the EHCI implementation from TransDimension Inc. + This supports the EHCI implementation that's originally + from ARC, and has since changed hands a few times. + +config USB_EHCI_TT_NEWSCHED + bool "Improved Transaction Translator scheduling (EXPERIMENTAL)" + depends on USB_EHCI_HCD && EXPERIMENTAL + ---help--- + This changes the periodic scheduling code to fill more of the low + and full speed bandwidth available from the Transaction Translator + (TT) in USB 2.0 hubs. Without this, only one transfer will be + issued in each microframe, significantly reducing the number of + periodic low/fullspeed transfers possible. + + If you have multiple periodic low/fullspeed devices connected to a + highspeed USB hub which is connected to a highspeed USB Host + Controller, and some of those devices will not work correctly + (possibly due to "ENOSPC" or "-28" errors), say Y. + + If unsure, say N. config USB_ISP116X_HCD tristate "ISP116X HCD support" diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 5871944e614..4859900bd13 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -163,6 +163,190 @@ static int same_tt (struct usb_device *dev1, struct usb_device *dev2) return 1; } +#ifdef CONFIG_USB_EHCI_TT_NEWSCHED + +/* Which uframe does the low/fullspeed transfer start in? + * + * The parameter is the mask of ssplits in "H-frame" terms + * and this returns the transfer start uframe in "B-frame" terms, + * which allows both to match, e.g. a ssplit in "H-frame" uframe 0 + * will cause a transfer in "B-frame" uframe 0. "B-frames" lag + * "H-frames" by 1 uframe. See the EHCI spec sec 4.5 and figure 4.7. + */ +static inline unsigned char tt_start_uframe(struct ehci_hcd *ehci, __le32 mask) +{ + unsigned char smask = QH_SMASK & le32_to_cpu(mask); + if (!smask) { + ehci_err(ehci, "invalid empty smask!\n"); + /* uframe 7 can't have bw so this will indicate failure */ + return 7; + } + return ffs(smask) - 1; +} + +static const unsigned char +max_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 30, 0 }; + +/* carryover low/fullspeed bandwidth that crosses uframe boundries */ +static inline void carryover_tt_bandwidth(unsigned short tt_usecs[8]) +{ + int i; + for (i=0; i<7; i++) { + if (max_tt_usecs[i] < tt_usecs[i]) { + tt_usecs[i+1] += tt_usecs[i] - max_tt_usecs[i]; + tt_usecs[i] = max_tt_usecs[i]; + } + } +} + +/* How many of the tt's periodic downstream 1000 usecs are allocated? + * + * While this measures the bandwidth in terms of usecs/uframe, + * the low/fullspeed bus has no notion of uframes, so any particular + * low/fullspeed transfer can "carry over" from one uframe to the next, + * since the TT just performs downstream transfers in sequence. + * + * For example two seperate 100 usec transfers can start in the same uframe, + * and the second one would "carry over" 75 usecs into the next uframe. + */ +static void +periodic_tt_usecs ( + struct ehci_hcd *ehci, + struct usb_device *dev, + unsigned frame, + unsigned short tt_usecs[8] +) +{ + __le32 *hw_p = &ehci->periodic [frame]; + union ehci_shadow *q = &ehci->pshadow [frame]; + unsigned char uf; + + memset(tt_usecs, 0, 16); + + while (q->ptr) { + switch (Q_NEXT_TYPE(*hw_p)) { + case Q_TYPE_ITD: + hw_p = &q->itd->hw_next; + q = &q->itd->itd_next; + continue; + case Q_TYPE_QH: + if (same_tt(dev, q->qh->dev)) { + uf = tt_start_uframe(ehci, q->qh->hw_info2); + tt_usecs[uf] += q->qh->tt_usecs; + } + hw_p = &q->qh->hw_next; + q = &q->qh->qh_next; + continue; + case Q_TYPE_SITD: + if (same_tt(dev, q->sitd->urb->dev)) { + uf = tt_start_uframe(ehci, q->sitd->hw_uframe); + tt_usecs[uf] += q->sitd->stream->tt_usecs; + } + hw_p = &q->sitd->hw_next; + q = &q->sitd->sitd_next; + continue; + // case Q_TYPE_FSTN: + default: + ehci_dbg(ehci, + "ignoring periodic frame %d FSTN\n", frame); + hw_p = &q->fstn->hw_next; + q = &q->fstn->fstn_next; + } + } + + carryover_tt_bandwidth(tt_usecs); + + if (max_tt_usecs[7] < tt_usecs[7]) + ehci_err(ehci, "frame %d tt sched overrun: %d usecs\n", + frame, tt_usecs[7] - max_tt_usecs[7]); +} + +/* + * Return true if the device's tt's downstream bus is available for a + * periodic transfer of the specified length (usecs), starting at the + * specified frame/uframe. Note that (as summarized in section 11.19 + * of the usb 2.0 spec) TTs can buffer multiple transactions for each + * uframe. + * + * The uframe parameter is when the fullspeed/lowspeed transfer + * should be executed in "B-frame" terms, which is the same as the + * highspeed ssplit's uframe (which is in "H-frame" terms). For example + * a ssplit in "H-frame" 0 causes a transfer in "B-frame" 0. + * See the EHCI spec sec 4.5 and fig 4.7. + * + * This checks if the full/lowspeed bus, at the specified starting uframe, + * has the specified bandwidth available, according to rules listed + * in USB 2.0 spec section 11.18.1 fig 11-60. + * + * This does not check if the transfer would exceed the max ssplit + * limit of 16, specified in USB 2.0 spec section 11.18.4 requirement #4, + * since proper scheduling limits ssplits to less than 16 per uframe. + */ +static int tt_available ( + struct ehci_hcd *ehci, + unsigned period, + struct usb_device *dev, + unsigned frame, + unsigned uframe, + u16 usecs +) +{ + if ((period == 0) || (uframe >= 7)) /* error */ + return 0; + + for (; frame < ehci->periodic_size; frame += period) { + unsigned short tt_usecs[8]; + + periodic_tt_usecs (ehci, dev, frame, tt_usecs); + + ehci_vdbg(ehci, "tt frame %d check %d usecs start uframe %d in" + " schedule %d/%d/%d/%d/%d/%d/%d/%d\n", + frame, usecs, uframe, + tt_usecs[0], tt_usecs[1], tt_usecs[2], tt_usecs[3], + tt_usecs[4], tt_usecs[5], tt_usecs[6], tt_usecs[7]); + + if (max_tt_usecs[uframe] <= tt_usecs[uframe]) { + ehci_vdbg(ehci, "frame %d uframe %d fully scheduled\n", + frame, uframe); + return 0; + } + + /* special case for isoc transfers larger than 125us: + * the first and each subsequent fully used uframe + * must be empty, so as to not illegally delay + * already scheduled transactions + */ + if (125 < usecs) { + int ufs = (usecs / 125) - 1; + int i; + for (i = uframe; i < (uframe + ufs) && i < 8; i++) + if (0 < tt_usecs[i]) { + ehci_vdbg(ehci, + "multi-uframe xfer can't fit " + "in frame %d uframe %d\n", + frame, i); + return 0; + } + } + + tt_usecs[uframe] += usecs; + + carryover_tt_bandwidth(tt_usecs); + + /* fail if the carryover pushed bw past the last uframe's limit */ + if (max_tt_usecs[7] < tt_usecs[7]) { + ehci_vdbg(ehci, + "tt unavailable usecs %d frame %d uframe %d\n", + usecs, frame, uframe); + return 0; + } + } + + return 1; +} + +#else + /* return true iff the device's transaction translator is available * for a periodic transfer starting at the specified frame, using * all the uframes in the mask. @@ -237,6 +421,8 @@ static int tt_no_collision ( return 1; } +#endif /* CONFIG_USB_EHCI_TT_NEWSCHED */ + /*-------------------------------------------------------------------------*/ static int enable_periodic (struct ehci_hcd *ehci) @@ -481,7 +667,7 @@ static int check_intr_schedule ( ) { int retval = -ENOSPC; - u8 mask; + u8 mask = 0; if (qh->c_usecs && uframe >= 6) /* FSTN territory? */ goto done; @@ -494,6 +680,24 @@ static int check_intr_schedule ( goto done; } +#ifdef CONFIG_USB_EHCI_TT_NEWSCHED + if (tt_available (ehci, qh->period, qh->dev, frame, uframe, + qh->tt_usecs)) { + unsigned i; + + /* TODO : this may need FSTN for SSPLIT in uframe 5. */ + for (i=uframe+1; i<8 && iperiod, qh->c_usecs)) + goto done; + else + mask |= 1 << i; + + retval = 0; + + *c_maskp = cpu_to_le32 (mask << 8); + } +#else /* Make sure this tt's buffer is also available for CSPLITs. * We pessimize a bit; probably the typical full speed case * doesn't need the second CSPLIT. @@ -514,6 +718,7 @@ static int check_intr_schedule ( goto done; retval = 0; } +#endif done: return retval; } @@ -1047,12 +1252,21 @@ sitd_slot_ok ( frame = uframe >> 3; uf = uframe & 7; +#ifdef CONFIG_USB_EHCI_TT_NEWSCHED + /* The tt's fullspeed bus bandwidth must be available. + * tt_available scheduling guarantees 10+% for control/bulk. + */ + if (!tt_available (ehci, period_uframes << 3, + stream->udev, frame, uf, stream->tt_usecs)) + return 0; +#else /* tt must be idle for start(s), any gap, and csplit. * assume scheduling slop leaves 10+% for control/bulk. */ if (!tt_no_collision (ehci, period_uframes << 3, stream->udev, frame, mask)) return 0; +#endif /* check starts (OUT uses more than one) */ max_used = 100 - stream->usecs; -- cgit v1.2.3 From 2f8ad9a1b91bc6856860a2fea8b07e0c82c0ad0a Mon Sep 17 00:00:00 2001 From: Pete Zaitcev Date: Wed, 24 May 2006 11:04:04 -0700 Subject: [PATCH] USB: rmmod pl2303 after -28 Wait for the scheduled work to finish before freeing memory, prevent oops. http://bugzilla.kernel.org/show_bug.cgi?id=6596 Signed-off-by: Pete Zaitcev Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb-serial.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 7a1cc1b0497..cbca3402d6c 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -162,6 +162,8 @@ static void destroy_serial(struct kref *kref) } } + flush_scheduled_work(); /* port->work */ + usb_put_dev(serial->dev); /* free up any memory that we allocated */ -- cgit v1.2.3 From 688e9fb1bbdd4e5a51b5030b7f9b1c811fd5e5e3 Mon Sep 17 00:00:00 2001 From: Pete Zaitcev Date: Thu, 25 May 2006 20:04:54 -0700 Subject: [PATCH] ub: atomic add_disk I am taling about this: "if (disk->flags & GENHD_FL_UP) del_gendisk(disk);" If del_gendisk() undoes add_disk() like viro just said, why is it conditional? huh? add_disk() sets the damn flag So, I should not need to check ever so the above is "if I've called add_disk(), call gendisk()" which might be what you want, of course but usually you know if you'd done add_disk() on that puppy anyway In ub, nobody upstream should ever see half-constructed disks before they were passed to add_disk. To that end, only add the struct lun to the list on the path of no return. With that fix in place, we do not need to test GENHD_FL_UP. Signed-off-by: Pete Zaitcev Signed-off-by: Greg Kroah-Hartman --- drivers/block/ub.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/block/ub.c b/drivers/block/ub.c index 8eb44a55b9b..cfb824d90c8 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c @@ -2314,7 +2314,6 @@ static int ub_probe_lun(struct ub_dev *sc, int lnum) goto err_id; lun->udev = sc; - list_add(&lun->link, &sc->luns); snprintf(lun->name, 16, DRV_NAME "%c(%d.%d.%d)", lun->id + 'a', sc->dev->bus->busnum, sc->dev->devnum, lun->num); @@ -2327,7 +2326,6 @@ static int ub_probe_lun(struct ub_dev *sc, int lnum) if ((disk = alloc_disk(UB_PARTS_PER_LUN)) == NULL) goto err_diskalloc; - lun->disk = disk; sprintf(disk->disk_name, DRV_NAME "%c", lun->id + 'a'); sprintf(disk->devfs_name, DEVFS_NAME "/%c", lun->id + 'a'); disk->major = UB_MAJOR; @@ -2349,7 +2347,9 @@ static int ub_probe_lun(struct ub_dev *sc, int lnum) blk_queue_max_sectors(q, UB_MAX_SECTORS); blk_queue_hardsect_size(q, lun->capacity.bsize); + lun->disk = disk; q->queuedata = lun; + list_add(&lun->link, &sc->luns); set_capacity(disk, lun->capacity.nsec); if (lun->removable) @@ -2362,7 +2362,6 @@ static int ub_probe_lun(struct ub_dev *sc, int lnum) err_blkqinit: put_disk(disk); err_diskalloc: - list_del(&lun->link); ub_id_put(lun->id); err_id: kfree(lun); @@ -2375,7 +2374,6 @@ static void ub_disconnect(struct usb_interface *intf) struct ub_dev *sc = usb_get_intfdata(intf); struct list_head *p; struct ub_lun *lun; - struct gendisk *disk; unsigned long flags; /* @@ -2431,9 +2429,7 @@ static void ub_disconnect(struct usb_interface *intf) */ list_for_each (p, &sc->luns) { lun = list_entry(p, struct ub_lun, link); - disk = lun->disk; - if (disk->flags & GENHD_FL_UP) - del_gendisk(disk); + del_gendisk(lun->disk); /* * I wish I could do: * set_bit(QUEUE_FLAG_DEAD, &q->queue_flags); -- cgit v1.2.3 From b5600339cd37472455d99b39963f3106411070b6 Mon Sep 17 00:00:00 2001 From: Pete Zaitcev Date: Thu, 25 May 2006 20:08:50 -0700 Subject: [PATCH] ub: random cleanups Remove some silly messages and cast in stone "temporary" messages which we keep around. Also, I am hesitant to remove the initialization retries without having the hardware to test (anyone who was at KS04 has a spare?) Signed-off-by: Pete Zaitcev Signed-off-by: Greg Kroah-Hartman --- drivers/block/ub.c | 60 +++++++++++------------------------------------------- 1 file changed, 12 insertions(+), 48 deletions(-) diff --git a/drivers/block/ub.c b/drivers/block/ub.c index cfb824d90c8..60e9a9457c6 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c @@ -10,17 +10,13 @@ * TODO (sorted by decreasing priority) * -- set readonly flag for CDs, set removable flag for CF readers * -- do inquiry and verify we got a disk and not a tape (for LUN mismatch) - * -- special case some senses, e.g. 3a/0 -> no media present, reduce retries * -- verify the 13 conditions and do bulk resets - * -- kill last_pipe and simply do two-state clearing on both pipes * -- highmem * -- move top_sense and work_bcs into separate allocations (if they survive) * for cache purists and esoteric architectures. * -- Allocate structure for LUN 0 before the first ub_sync_tur, avoid NULL. ? * -- prune comments, they are too volumnous - * -- Exterminate P3 printks * -- Resove XXX's - * -- Redo "benh's retries", perhaps have spin-up code to handle them. V:D=? * -- CLEAR, CLR2STS, CLRRS seem to be ripe for refactoring. */ #include @@ -180,7 +176,6 @@ struct ub_dev; #define UB_DIR_ILLEGAL2 2 #define UB_DIR_WRITE 3 -/* P3 */ #define UB_DIR_CHAR(c) (((c)==UB_DIR_WRITE)? 'w': \ (((c)==UB_DIR_READ)? 'r': 'n')) @@ -669,8 +664,9 @@ static int ub_request_fn_1(struct ub_lun *lun, struct request *rq) */ n_elem = blk_rq_map_sg(lun->disk->queue, rq, &urq->sgv[0]); if (n_elem < 0) { + /* Impossible, because blk_rq_map_sg should not hit ENOMEM. */ printk(KERN_INFO "%s: failed request map (%d)\n", - lun->name, n_elem); /* P3 */ + lun->name, n_elem); goto drop; } if (n_elem > UB_MAX_REQ_SG) { /* Paranoia */ @@ -824,7 +820,9 @@ static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun, if (urq->current_try >= 3) return -EIO; urq->current_try++; - /* P3 */ printk("%s: dir %c len/act %d/%d " + + /* Remove this if anyone complains of flooding. */ + printk(KERN_DEBUG "%s: dir %c len/act %d/%d " "[sense %x %02x %02x] retry %d\n", sc->name, UB_DIR_CHAR(cmd->dir), cmd->len, cmd->act_len, cmd->key, cmd->asc, cmd->ascq, urq->current_try); @@ -1241,8 +1239,6 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) * to check. But it's not all right if the device * counts disagree with our counts. */ - /* P3 */ printk("%s: resid %d len %d act %d\n", - sc->name, len, cmd->len, cmd->act_len); goto Bad_End; } @@ -1253,7 +1249,6 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) ub_state_sense(sc, cmd); return; case US_BULK_STAT_PHASE: - /* P3 */ printk("%s: status PHASE\n", sc->name); goto Bad_End; default: printk(KERN_INFO "%s: unknown CSW status 0x%x\n", @@ -1568,16 +1563,14 @@ static void ub_reset_task(void *arg) } if (atomic_read(&sc->poison)) { - printk(KERN_NOTICE "%s: Not resetting disconnected device\n", - sc->name); /* P3 This floods. Remove soon. XXX */ + ; } else if ((sc->reset & 1) == 0) { ub_sync_reset(sc); msleep(700); /* usb-storage sleeps 6s (!) */ ub_probe_clear_stall(sc, sc->recv_bulk_pipe); ub_probe_clear_stall(sc, sc->send_bulk_pipe); } else if (sc->dev->actconfig->desc.bNumInterfaces != 1) { - printk(KERN_NOTICE "%s: Not resetting multi-interface device\n", - sc->name); /* P3 This floods. Remove soon. XXX */ + ; } else { if ((lkr = usb_lock_device_for_reset(sc->dev, sc->intf)) < 0) { printk(KERN_NOTICE @@ -1819,10 +1812,8 @@ static int ub_sync_tur(struct ub_dev *sc, struct ub_lun *lun) rc = ub_submit_scsi(sc, cmd); spin_unlock_irqrestore(sc->lock, flags); - if (rc != 0) { - printk("ub: testing ready: submit error (%d)\n", rc); /* P3 */ + if (rc != 0) goto err_submit; - } wait_for_completion(&compl); @@ -1880,20 +1871,16 @@ static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun, rc = ub_submit_scsi(sc, cmd); spin_unlock_irqrestore(sc->lock, flags); - if (rc != 0) { - printk("ub: reading capacity: submit error (%d)\n", rc); /* P3 */ + if (rc != 0) goto err_submit; - } wait_for_completion(&compl); if (cmd->error != 0) { - printk("ub: reading capacity: error %d\n", cmd->error); /* P3 */ rc = -EIO; goto err_read; } if (cmd->act_len != 8) { - printk("ub: reading capacity: size %d\n", cmd->act_len); /* P3 */ rc = -EIO; goto err_read; } @@ -1907,7 +1894,6 @@ static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun, case 2048: shift = 2; break; case 4096: shift = 3; break; default: - printk("ub: Bad sector size %u\n", bsize); /* P3 */ rc = -EDOM; goto err_inv_bsize; } @@ -2019,17 +2005,8 @@ static int ub_sync_getmaxlun(struct ub_dev *sc) sc->work_urb.error_count = 0; sc->work_urb.status = 0; - if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) { - if (rc == -EPIPE) { - printk("%s: Stall submitting GetMaxLUN, using 1 LUN\n", - sc->name); /* P3 */ - } else { - printk(KERN_NOTICE - "%s: Unable to submit GetMaxLUN (%d)\n", - sc->name, rc); - } + if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) goto err_submit; - } init_timer(&timer); timer.function = ub_probe_timeout; @@ -2042,21 +2019,10 @@ static int ub_sync_getmaxlun(struct ub_dev *sc) del_timer_sync(&timer); usb_kill_urb(&sc->work_urb); - if ((rc = sc->work_urb.status) < 0) { - if (rc == -EPIPE) { - printk("%s: Stall at GetMaxLUN, using 1 LUN\n", - sc->name); /* P3 */ - } else { - printk(KERN_NOTICE - "%s: Error at GetMaxLUN (%d)\n", - sc->name, rc); - } + if ((rc = sc->work_urb.status) < 0) goto err_io; - } if (sc->work_urb.actual_length != 1) { - printk("%s: GetMaxLUN returned %d bytes\n", sc->name, - sc->work_urb.actual_length); /* P3 */ nluns = 0; } else { if ((nluns = *p) == 55) { @@ -2067,8 +2033,6 @@ static int ub_sync_getmaxlun(struct ub_dev *sc) if (nluns > UB_MAX_LUNS) nluns = UB_MAX_LUNS; } - printk("%s: GetMaxLUN returned %d, using %d LUNs\n", sc->name, - *p, nluns); /* P3 */ } kfree(p); @@ -2266,7 +2230,7 @@ static int ub_probe(struct usb_interface *intf, * has to succeed, so we clear checks with an additional one here. * In any case it's not our business how revaliadation is implemented. */ - for (i = 0; i < 3; i++) { /* Retries for benh's key */ + for (i = 0; i < 3; i++) { /* Retries for the schwag key from KS'04 */ if ((rc = ub_sync_tur(sc, NULL)) <= 0) break; if (rc != 0x6) break; msleep(10); -- cgit v1.2.3 From 955a260829b5848fa90721678bab003234c93356 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Fri, 26 May 2006 10:17:03 -0700 Subject: [PATCH] USB: more pegasus log spamming removed Remove more log spamming from pegasus: stop talking to the device once we see ENODEV reported. It may take a while before khubd notifies us. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/net/pegasus.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c index 7683926a1b6..ab21f960d25 100644 --- a/drivers/usb/net/pegasus.c +++ b/drivers/usb/net/pegasus.c @@ -163,6 +163,8 @@ static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size, /* using ATOMIC, we'd never wake up if we slept */ if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) { + if (ret == -ENODEV) + netif_device_detach(pegasus->net); if (netif_msg_drv(pegasus)) dev_err(&pegasus->intf->dev, "%s, status %d\n", __FUNCTION__, ret); @@ -217,6 +219,8 @@ static int set_registers(pegasus_t * pegasus, __u16 indx, __u16 size, set_current_state(TASK_UNINTERRUPTIBLE); if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) { + if (ret == -ENODEV) + netif_device_detach(pegasus->net); if (netif_msg_drv(pegasus)) dev_err(&pegasus->intf->dev, "%s, status %d\n", __FUNCTION__, ret); @@ -268,6 +272,8 @@ static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data) set_current_state(TASK_UNINTERRUPTIBLE); if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) { + if (ret == -ENODEV) + netif_device_detach(pegasus->net); if (netif_msg_drv(pegasus)) dev_err(&pegasus->intf->dev, "%s, status %d\n", __FUNCTION__, ret); @@ -298,10 +304,13 @@ static int update_eth_regs_async(pegasus_t * pegasus) (char *) &pegasus->dr, pegasus->eth_regs, 3, ctrl_callback, pegasus); - if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) + if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) { + if (ret == -ENODEV) + netif_device_detach(pegasus->net); if (netif_msg_drv(pegasus)) dev_err(&pegasus->intf->dev, "%s, status %d\n", __FUNCTION__, ret); + } return ret; } @@ -692,7 +701,10 @@ goon: usb_rcvbulkpipe(pegasus->usb, 1), pegasus->rx_skb->data, PEGASUS_MTU + 8, read_bulk_callback, pegasus); - if (usb_submit_urb(pegasus->rx_urb, GFP_ATOMIC)) { + rx_status = usb_submit_urb(pegasus->rx_urb, GFP_ATOMIC); + if (rx_status == -ENODEV) + netif_device_detach(pegasus->net); + else if (rx_status) { pegasus->flags |= PEGASUS_RX_URB_FAIL; goto tl_sched; } else { @@ -709,6 +721,7 @@ static void rx_fixup(unsigned long data) { pegasus_t *pegasus; unsigned long flags; + int status; pegasus = (pegasus_t *) data; if (pegasus->flags & PEGASUS_UNPLUG) @@ -734,7 +747,10 @@ static void rx_fixup(unsigned long data) pegasus->rx_skb->data, PEGASUS_MTU + 8, read_bulk_callback, pegasus); try_again: - if (usb_submit_urb(pegasus->rx_urb, GFP_ATOMIC)) { + status = usb_submit_urb(pegasus->rx_urb, GFP_ATOMIC); + if (status == -ENODEV) + netif_device_detach(pegasus->net); + else if (status) { pegasus->flags |= PEGASUS_RX_URB_FAIL; tasklet_schedule(&pegasus->rx_tl); } else { @@ -836,6 +852,8 @@ static void intr_callback(struct urb *urb, struct pt_regs *regs) } status = usb_submit_urb(urb, SLAB_ATOMIC); + if (status == -ENODEV) + netif_device_detach(pegasus->net); if (status && netif_msg_timer(pegasus)) printk(KERN_ERR "%s: can't resubmit interrupt urb, %d\n", net->name, status); @@ -874,6 +892,7 @@ static int pegasus_start_xmit(struct sk_buff *skb, struct net_device *net) /* cleanup should already have been scheduled */ break; case -ENODEV: /* disconnect() upcoming */ + netif_device_detach(pegasus->net); break; default: pegasus->stats.tx_errors++; @@ -999,6 +1018,8 @@ static int pegasus_open(struct net_device *net) pegasus->rx_skb->data, PEGASUS_MTU + 8, read_bulk_callback, pegasus); if ((res = usb_submit_urb(pegasus->rx_urb, GFP_KERNEL))) { + if (res == -ENODEV) + netif_device_detach(pegasus->net); if (netif_msg_ifup(pegasus)) pr_debug("%s: failed rx_urb, %d", net->name, res); goto exit; @@ -1009,6 +1030,8 @@ static int pegasus_open(struct net_device *net) pegasus->intr_buff, sizeof (pegasus->intr_buff), intr_callback, pegasus, pegasus->intr_interval); if ((res = usb_submit_urb(pegasus->intr_urb, GFP_KERNEL))) { + if (res == -ENODEV) + netif_device_detach(pegasus->net); if (netif_msg_ifup(pegasus)) pr_debug("%s: failed intr_urb, %d\n", net->name, res); usb_kill_urb(pegasus->rx_urb); -- cgit v1.2.3 From 1fbe75e12f0dd567c86533e13ba2605f3ecad2e1 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Fri, 26 May 2006 21:36:28 +0100 Subject: [PATCH] USB: print message when device is rejected due to insufficient power 2.6.16 introduces USB power budgeting in the Linux kernel, and since then, a fair number of users have observed that some of their devices no longer work in unpowered hubs (this is not a bug, the devices claim that they need more than 100mA). The very least we can do is print an informational message to the kernel log when this happens, otherwise it is not at all clear why the device was not accepted. Signed-off-by: Daniel Drake Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 1b1846e6473..89ebe6a23a9 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1176,6 +1176,7 @@ static int choose_configuration(struct usb_device *udev) { int i; int num_configs; + int insufficient_power = 0; struct usb_host_config *c, *best; best = NULL; @@ -1228,8 +1229,10 @@ static int choose_configuration(struct usb_device *udev) */ /* Rule out configs that draw too much bus current */ - if (c->desc.bMaxPower * 2 > udev->bus_mA) + if (c->desc.bMaxPower * 2 > udev->bus_mA) { + insufficient_power++; continue; + } /* If the first config's first interface is COMM/2/0xff * (MSFT RNDIS), rule it out unless Linux has host-side @@ -1263,6 +1266,11 @@ static int choose_configuration(struct usb_device *udev) best = c; } + if (insufficient_power > 0) + dev_info(&udev->dev, "rejected %d configuration%s " + "due to insufficient available bus power\n", + insufficient_power, plural(insufficient_power)); + if (best) { i = best->desc.bConfigurationValue; dev_info(&udev->dev, -- cgit v1.2.3 From 3f8f4a18f4f76a67fe5b80da1d3a3940e41a14a8 Mon Sep 17 00:00:00 2001 From: Giridhar Pemmasani Date: Tue, 30 May 2006 10:12:30 -0400 Subject: [PATCH] usbcore: Fix broken RNDIS config selection RNDIS devices don't get configured owing to a typo in choose_configuration(). This patch from Giridhar Pemmasani fixes the typo. From: Giridhar Pemmasani Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 89ebe6a23a9..f41c08946a5 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1241,7 +1241,7 @@ static int choose_configuration(struct usb_device *udev) && desc->bInterfaceClass == USB_CLASS_COMM && desc->bInterfaceSubClass == 2 && desc->bInterfaceProtocol == 0xff) { -#ifndef CONFIG_USB_NET_RNDIS +#ifndef CONFIG_USB_NET_RNDIS_HOST continue; #else best = c; -- cgit v1.2.3 From 633a7ecf89587879161179ac4f5a03722626866f Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 30 May 2006 10:21:14 -0400 Subject: [PATCH] usbhid: Remove unneeded blacklist entries Now that usbhid automatically applies HID_QUIRK_NOGET to keyboards and mice, we no longer need the blacklist entries that were present for no other purpose. This patch (as698) removes them. Signed-off-by: Alan Stern Acked-by: Vojtech Pavlik Signed-off-by: Greg Kroah-Hartman --- drivers/usb/input/hid-core.c | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 061002fc66f..c6051beeabd 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -1374,9 +1374,6 @@ void hid_close(struct hid_device *hid) #define USB_VENDOR_ID_PANJIT 0x134c -#define USB_VENDOR_ID_SILVERCREST 0x062a -#define USB_DEVICE_ID_SILVERCREST_KB 0x0201 - /* * Initialize all reports */ @@ -1461,9 +1458,6 @@ void hid_init_reports(struct hid_device *hid) #define USB_VENDOR_ID_ONTRAK 0x0a07 #define USB_DEVICE_ID_ONTRAK_ADU100 0x0064 -#define USB_VENDOR_ID_TANGTOP 0x0d3d -#define USB_DEVICE_ID_TANGTOP_USBPS2 0x0001 - #define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f #define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100 @@ -1520,12 +1514,6 @@ void hid_init_reports(struct hid_device *hid) #define USB_DEVICE_ID_MCC_PMD1024LS 0x0076 #define USB_DEVICE_ID_MCC_PMD1208LS 0x007a -#define USB_VENDOR_ID_CHICONY 0x04f2 -#define USB_DEVICE_ID_CHICONY_USBHUB_KB 0x0100 - -#define USB_VENDOR_ID_BTC 0x046e -#define USB_DEVICE_ID_BTC_KEYBOARD 0x5303 - #define USB_VENDOR_ID_VERNIER 0x08f7 #define USB_DEVICE_ID_VERNIER_LABPRO 0x0001 #define USB_DEVICE_ID_VERNIER_GOTEMP 0x0002 @@ -1554,15 +1542,6 @@ void hid_init_reports(struct hid_device *hid) #define USB_VENDOR_ID_CHERRY 0x046a #define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023 -#define USB_VENDOR_ID_HP 0x03f0 -#define USB_DEVICE_ID_HP_USBHUB_KB 0x020c - -#define USB_VENDOR_ID_IBM 0x04b3 -#define USB_DEVICE_ID_IBM_USBHUB_KB 0x3005 - -#define USB_VENDOR_ID_CREATIVELABS 0x062a -#define USB_DEVICE_ID_CREATIVELABS_SILVERCREST 0x0201 - #define USB_VENDOR_ID_YEALINK 0x6993 #define USB_DEVICE_ID_YEALINK_P1K_P4K_B2K 0xb001 /* @@ -1683,14 +1662,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_KEYBOARD, HID_QUIRK_NOGET}, - { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_USBHUB_KB, HID_QUIRK_NOGET}, - { USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_CREATIVELABS_SILVERCREST, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_HP, USB_DEVICE_ID_HP_USBHUB_KB, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_IBM, USB_DEVICE_ID_IBM_USBHUB_KB, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_TANGTOP, USB_DEVICE_ID_TANGTOP_USBPS2, HID_QUIRK_NOGET }, { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_SILVERCREST, USB_DEVICE_ID_SILVERCREST_KB, HID_QUIRK_NOGET }, { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE, HID_QUIRK_MIGHTYMOUSE | HID_QUIRK_INVERT_HWHEEL }, { USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK_7 }, -- cgit v1.2.3 From eb79b4fda4654eaa7e6421ad41b0a75c7b4f0608 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 30 May 2006 12:36:30 +0100 Subject: [PATCH] USB: ftdi_sio: add support for Yost Engineering ServoCenter3.1 This patch adds support for Yost Engineering Inc's ServoCenter 3.1 USB product to the ftdi_sio driver's device ID table. The PID was supplied by Aaron Prose of Yost Engineering on the ftdi-usb-sio-devel list. The PID 0xE050 matches the Windows INF files for this device. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio.h | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 590c7ec851d..b2bfea7c815 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -500,6 +500,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(ICOM_ID1_VID, ICOM_ID1_PID) }, { USB_DEVICE(PAPOUCH_VID, PAPOUCH_TMU_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ACG_HFDUAL_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_YEI_SERVOCENTER31_PID) }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index d69a917e768..6ab2ac845bd 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -436,6 +436,12 @@ */ #define FTDI_ACG_HFDUAL_PID 0xDD20 /* HF Dual ISO Reader (RFID) */ +/* + * Yost Engineering, Inc. products (www.yostengineering.com). + * PID 0xE050 submitted by Aaron Prose. + */ +#define FTDI_YEI_SERVOCENTER31_PID 0xE050 /* YEI ServoCenter3.1 USB */ + /* Commands */ #define FTDI_SIO_RESET 0 /* Reset the port */ #define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ -- cgit v1.2.3 From 069e8a65cd7970b15672825541be59218d9a8a0f Mon Sep 17 00:00:00 2001 From: "akpm@osdl.org" Date: Fri, 26 May 2006 13:17:09 -0700 Subject: [PATCH] Driver for Apple Cinema Display This is a driver to control the brightness of an Apple Cinema Display over USB. It updates the local brightness value if the user presses a button on the display. Signed-off-by: Michael Hanselmann Cc: Oliver Neukum Cc: Paul Mackerras Cc: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/Makefile | 1 + drivers/usb/misc/Kconfig | 9 + drivers/usb/misc/Makefile | 1 + drivers/usb/misc/appledisplay.c | 383 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 394 insertions(+) create mode 100644 drivers/usb/misc/appledisplay.c diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index 9b7d9769fdc..b2999656190 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -61,6 +61,7 @@ obj-$(CONFIG_USB_TEST) += misc/ obj-$(CONFIG_USB_USS720) += misc/ obj-$(CONFIG_USB_PHIDGETSERVO) += misc/ obj-$(CONFIG_USB_SISUSBVGA) += misc/ +obj-$(CONFIG_USB_APPLEDISPLAY) += misc/ obj-$(CONFIG_USB_ATM) += atm/ obj-$(CONFIG_USB_SPEEDTOUCH) += atm/ diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index 8ba6a701e9c..af79d0447bb 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig @@ -137,6 +137,15 @@ config USB_IDMOUSE See also . +config USB_APPLEDISPLAY + tristate "Apple Cinema Display support" + depends on USB + select BACKLIGHT_LCD_SUPPORT + select BACKLIGHT_CLASS_DEVICE + help + Say Y here if you want to control the backlight of Apple Cinema + Displays over USB. This driver provides a sysfs interface. + source "drivers/usb/misc/sisusbvga/Kconfig" config USB_LD diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile index 6c693bc68e2..946537d31d9 100644 --- a/drivers/usb/misc/Makefile +++ b/drivers/usb/misc/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_USB_PHIDGETSERVO) += phidgetservo.o obj-$(CONFIG_USB_RIO500) += rio500.o obj-$(CONFIG_USB_TEST) += usbtest.o obj-$(CONFIG_USB_USS720) += uss720.o +obj-$(CONFIG_USB_APPLEDISPLAY) += appledisplay.o obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga/ diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c new file mode 100644 index 00000000000..bfde82f5d18 --- /dev/null +++ b/drivers/usb/misc/appledisplay.c @@ -0,0 +1,383 @@ +/* + * Apple Cinema Display driver + * + * Copyright (C) 2006 Michael Hanselmann (linux-kernel@hansmi.ch) + * + * Thanks to Caskey L. Dickson for his work with acdctl. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define APPLE_VENDOR_ID 0x05AC + +#define USB_REQ_GET_REPORT 0x01 +#define USB_REQ_SET_REPORT 0x09 + +#define ACD_USB_TIMEOUT 250 + +#define ACD_USB_EDID 0x0302 +#define ACD_USB_BRIGHTNESS 0x0310 + +#define ACD_BTN_NONE 0 +#define ACD_BTN_BRIGHT_UP 3 +#define ACD_BTN_BRIGHT_DOWN 4 + +#define ACD_URB_BUFFER_LEN 2 +#define ACD_MSG_BUFFER_LEN 2 + +#define APPLEDISPLAY_DEVICE(prod) \ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ + USB_DEVICE_ID_MATCH_INT_CLASS | \ + USB_DEVICE_ID_MATCH_INT_PROTOCOL, \ + .idVendor = APPLE_VENDOR_ID, \ + .idProduct = (prod), \ + .bInterfaceClass = USB_CLASS_HID, \ + .bInterfaceProtocol = 0x00 + +/* table of devices that work with this driver */ +static struct usb_device_id appledisplay_table [] = { + { APPLEDISPLAY_DEVICE(0x9218) }, + { APPLEDISPLAY_DEVICE(0x9219) }, + { APPLEDISPLAY_DEVICE(0x921d) }, + + /* Terminating entry */ + { } +}; +MODULE_DEVICE_TABLE(usb, appledisplay_table); + +/* Structure to hold all of our device specific stuff */ +struct appledisplay { + struct usb_device *udev; /* usb device */ + struct urb *urb; /* usb request block */ + struct backlight_device *bd; /* backlight device */ + char *urbdata; /* interrupt URB data buffer */ + char *msgdata; /* control message data buffer */ + + struct work_struct work; + int button_pressed; + spinlock_t lock; +}; + +static atomic_t count_displays = ATOMIC_INIT(0); +static struct workqueue_struct *wq; + +static void appledisplay_complete(struct urb *urb, struct pt_regs *regs) +{ + struct appledisplay *pdata = urb->context; + unsigned long flags; + int retval; + + switch (urb->status) { + case 0: + /* success */ + break; + case -EOVERFLOW: + printk(KERN_ERR "appletouch: OVERFLOW with data " + "length %d, actual length is %d\n", + ACD_URB_BUFFER_LEN, pdata->urb->actual_length); + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* This urb is terminated, clean up */ + dbg("%s - urb shutting down with status: %d", + __FUNCTION__, urb->status); + return; + default: + dbg("%s - nonzero urb status received: %d", + __FUNCTION__, urb->status); + goto exit; + } + + spin_lock_irqsave(&pdata->lock, flags); + + switch(pdata->urbdata[1]) { + case ACD_BTN_BRIGHT_UP: + case ACD_BTN_BRIGHT_DOWN: + pdata->button_pressed = 1; + queue_work(wq, &pdata->work); + break; + case ACD_BTN_NONE: + default: + pdata->button_pressed = 0; + break; + } + + spin_unlock_irqrestore(&pdata->lock, flags); + +exit: + retval = usb_submit_urb(pdata->urb, GFP_ATOMIC); + if (retval) { + err("%s - usb_submit_urb failed with result %d", + __FUNCTION__, retval); + } +} + +static int appledisplay_bl_update_status(struct backlight_device *bd) +{ + struct appledisplay *pdata = class_get_devdata(&bd->class_dev); + int retval; + + pdata->msgdata[0] = 0x10; + pdata->msgdata[1] = bd->props->brightness; + + retval = usb_control_msg( + pdata->udev, + usb_sndctrlpipe(pdata->udev, 0), + USB_REQ_SET_REPORT, + USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, + ACD_USB_BRIGHTNESS, + 0, + pdata->msgdata, 2, + ACD_USB_TIMEOUT); + + return retval; +} + +static int appledisplay_bl_get_brightness(struct backlight_device *bd) +{ + struct appledisplay *pdata = class_get_devdata(&bd->class_dev); + int retval; + + retval = usb_control_msg( + pdata->udev, + usb_rcvctrlpipe(pdata->udev, 0), + USB_REQ_GET_REPORT, + USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, + ACD_USB_BRIGHTNESS, + 0, + pdata->msgdata, 2, + ACD_USB_TIMEOUT); + + if (retval < 0) + return retval; + else + return pdata->msgdata[1]; +} + +static struct backlight_properties appledisplay_bl_data = { + .owner = THIS_MODULE, + .get_brightness = appledisplay_bl_get_brightness, + .update_status = appledisplay_bl_update_status, + .max_brightness = 0xFF +}; + +static void appledisplay_work(void *private) +{ + struct appledisplay *pdata = private; + int retval; + + up(&pdata->bd->sem); + retval = appledisplay_bl_get_brightness(pdata->bd); + if (retval >= 0) + pdata->bd->props->brightness = retval; + down(&pdata->bd->sem); + + /* Poll again in about 125ms if there's still a button pressed */ + if (pdata->button_pressed) + schedule_delayed_work(&pdata->work, HZ / 8); +} + +static int appledisplay_probe(struct usb_interface *iface, + const struct usb_device_id *id) +{ + struct appledisplay *pdata; + struct usb_device *udev = interface_to_usbdev(iface); + struct usb_host_interface *iface_desc; + struct usb_endpoint_descriptor *endpoint; + int int_in_endpointAddr = 0; + int i, retval = -ENOMEM, brightness; + char bl_name[20]; + + /* set up the endpoint information */ + /* use only the first interrupt-in endpoint */ + iface_desc = iface->cur_altsetting; + for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { + endpoint = &iface_desc->endpoint[i].desc; + if (!int_in_endpointAddr && + (endpoint->bEndpointAddress & USB_DIR_IN) && + ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_INT)) { + /* we found an interrupt in endpoint */ + int_in_endpointAddr = endpoint->bEndpointAddress; + break; + } + } + if (!int_in_endpointAddr) { + err("Could not find int-in endpoint"); + return -EIO; + } + + /* allocate memory for our device state and initialize it */ + pdata = kzalloc(sizeof(struct appledisplay), GFP_KERNEL); + if (!pdata) { + retval = -ENOMEM; + err("Out of memory"); + goto error; + } + + pdata->udev = udev; + + spin_lock_init(&pdata->lock); + INIT_WORK(&pdata->work, appledisplay_work, pdata); + + /* Allocate buffer for control messages */ + pdata->msgdata = kmalloc(ACD_MSG_BUFFER_LEN, GFP_KERNEL); + if (!pdata->msgdata) { + retval = -ENOMEM; + err("appledisplay: Allocating buffer for control messages " + "failed"); + goto error; + } + + /* Allocate interrupt URB */ + pdata->urb = usb_alloc_urb(0, GFP_KERNEL); + if (!pdata->urb) { + retval = -ENOMEM; + err("appledisplay: Allocating URB failed"); + goto error; + } + + /* Allocate buffer for interrupt data */ + pdata->urbdata = usb_buffer_alloc(pdata->udev, ACD_URB_BUFFER_LEN, + GFP_KERNEL, &pdata->urb->transfer_dma); + if (!pdata->urbdata) { + retval = -ENOMEM; + err("appledisplay: Allocating URB buffer failed"); + goto error; + } + + /* Configure interrupt URB */ + usb_fill_int_urb(pdata->urb, udev, + usb_rcvintpipe(udev, int_in_endpointAddr), + pdata->urbdata, ACD_URB_BUFFER_LEN, appledisplay_complete, + pdata, 1); + if (usb_submit_urb(pdata->urb, GFP_KERNEL)) { + retval = -EIO; + err("appledisplay: Submitting URB failed"); + goto error; + } + + /* Register backlight device */ + snprintf(bl_name, sizeof(bl_name), "appledisplay%d", + atomic_inc_return(&count_displays) - 1); + pdata->bd = backlight_device_register(bl_name, pdata, + &appledisplay_bl_data); + if (IS_ERR(pdata->bd)) { + err("appledisplay: Backlight registration failed"); + goto error; + } + + /* Try to get brightness */ + up(&pdata->bd->sem); + brightness = appledisplay_bl_get_brightness(pdata->bd); + down(&pdata->bd->sem); + + if (brightness < 0) { + retval = brightness; + err("appledisplay: Error while getting initial brightness: %d", retval); + goto error; + } + + /* Set brightness in backlight device */ + up(&pdata->bd->sem); + pdata->bd->props->brightness = brightness; + down(&pdata->bd->sem); + + /* save our data pointer in the interface device */ + usb_set_intfdata(iface, pdata); + + printk(KERN_INFO "appledisplay: Apple Cinema Display connected\n"); + + return 0; + +error: + if (pdata) { + if (pdata->urb) { + usb_kill_urb(pdata->urb); + if (pdata->urbdata) + usb_buffer_free(pdata->udev, ACD_URB_BUFFER_LEN, + pdata->urbdata, pdata->urb->transfer_dma); + usb_free_urb(pdata->urb); + } + if (pdata->bd) + backlight_device_unregister(pdata->bd); + kfree(pdata->msgdata); + } + usb_set_intfdata(iface, NULL); + kfree(pdata); + return retval; +} + +static void appledisplay_disconnect(struct usb_interface *iface) +{ + struct appledisplay *pdata = usb_get_intfdata(iface); + + if (pdata) { + usb_kill_urb(pdata->urb); + cancel_delayed_work(&pdata->work); + backlight_device_unregister(pdata->bd); + usb_buffer_free(pdata->udev, ACD_URB_BUFFER_LEN, + pdata->urbdata, pdata->urb->transfer_dma); + usb_free_urb(pdata->urb); + kfree(pdata->msgdata); + kfree(pdata); + } + + printk(KERN_INFO "appledisplay: Apple Cinema Display disconnected\n"); +} + +static struct usb_driver appledisplay_driver = { + .name = "appledisplay", + .probe = appledisplay_probe, + .disconnect = appledisplay_disconnect, + .id_table = appledisplay_table, +}; + +static int __init appledisplay_init(void) +{ + wq = create_singlethread_workqueue("appledisplay"); + if (!wq) { + err("Could not create work queue\n"); + return -ENOMEM; + } + + return usb_register(&appledisplay_driver); +} + +static void __exit appledisplay_exit(void) +{ + flush_workqueue(wq); + destroy_workqueue(wq); + usb_deregister(&appledisplay_driver); +} + +MODULE_AUTHOR("Michael Hanselmann"); +MODULE_DESCRIPTION("Apple Cinema Display driver"); +MODULE_LICENSE("GPL"); + +module_init(appledisplay_init); +module_exit(appledisplay_exit); -- cgit v1.2.3 From 09fd6bc8b453c9215e81911cbb6882556aa03639 Mon Sep 17 00:00:00 2001 From: Stuart MacDonald Date: Wed, 31 May 2006 13:28:40 -0400 Subject: [PATCH] USB: Whiteheat: fix firmware spurious errors Attached patch fixes spurious errors during firmware load. Signed-off-by: Stuart MacDonald Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/whiteheat.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index 582860ac876..5b06fa36609 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -388,7 +388,7 @@ static int whiteheat_attach (struct usb_serial *serial) if (ret) { err("%s: Couldn't send command [%d]", serial->type->description, ret); goto no_firmware; - } else if (alen != sizeof(command)) { + } else if (alen != 2) { err("%s: Send command incomplete [%d]", serial->type->description, alen); goto no_firmware; } @@ -400,7 +400,7 @@ static int whiteheat_attach (struct usb_serial *serial) if (ret) { err("%s: Couldn't get results [%d]", serial->type->description, ret); goto no_firmware; - } else if (alen != sizeof(result)) { + } else if (alen != sizeof(*hw_info) + 1) { err("%s: Get results incomplete [%d]", serial->type->description, alen); goto no_firmware; } else if (result[0] != command[0]) { -- cgit v1.2.3 From b10cee9d035db54d0bf5a9f9fa622dcfc3f740c6 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Wed, 31 May 2006 11:21:52 -0700 Subject: [PATCH] USB: Add Sierra Wireless MC5720 ID to airprime.c Recognize the Sierra Wireless MC5720. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/airprime.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c index 694b205f9b7..8ef488849f7 100644 --- a/drivers/usb/serial/airprime.c +++ b/drivers/usb/serial/airprime.c @@ -19,6 +19,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0xf3d, 0x0112) }, /* AirPrime CDMA Wireless PC Card */ { USB_DEVICE(0x1410, 0x1110) }, /* Novatel Wireless Merlin CDMA */ { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless Aircard 580 */ + { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */ { }, }; MODULE_DEVICE_TABLE(usb, id_table); -- cgit v1.2.3 From d5ce1379be9c79d4bcf201c20c5cc87bb2bc973c Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Thu, 1 Jun 2006 20:48:45 -0700 Subject: [PATCH] USB: negative index in drivers/usb/host/isp116x-hcd.c From: Eric Sesterhenn This fixes coverity Bug #390. With the following code ret = ep->branch = balance(isp116x, ep->period, ep->load); if (ret < 0) goto fail; the problem is that ret and balance are of the type int, and ep->branch is u16. so the int balance() returns gets reduced to u16 and then converted to an int again, which removes the sign. Maybe the following little c program can explain it better: --- drivers/usb/host/isp116x-hcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index e99210b7909..c5e224048ef 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c @@ -781,7 +781,7 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd, if (ep->branch < PERIODIC_SIZE) break; - ret = ep->branch = balance(isp116x, ep->period, ep->load); + ep->branch = ret = balance(isp116x, ep->period, ep->load); if (ret < 0) goto fail; ret = 0; -- cgit v1.2.3 From efcaa20525fde82bbb4fb8cd9e9016f6fabc6509 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Tue, 30 May 2006 20:49:29 -0700 Subject: [PATCH] USB: cdc_ether: recognize olympus r1000 (fix regression) Earlier work splitting the "usbnet" driver out into a core plus driver modules was missing a blacklist entry for the Olympus R-1000; it must not use the CDC Ethernet driver, only the "zaurus" support works with it. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/net/cdc_ether.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/usb/net/cdc_ether.c b/drivers/usb/net/cdc_ether.c index 63f1f3ba8e0..9c6c5b0b01a 100644 --- a/drivers/usb/net/cdc_ether.c +++ b/drivers/usb/net/cdc_ether.c @@ -455,6 +455,18 @@ static const struct usb_device_id products [] = { .driver_info = 0, }, +/* Olympus has some models with a Zaurus-compatible option. + * R-1000 uses a FreeScale i.MXL cpu (ARMv4T) + */ +{ + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO + | USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = 0x07B4, + .idProduct = 0x0F02, /* R-1000 */ + ZAURUS_MASTER_INTERFACE, + .driver_info = 0, +}, + /* * WHITELIST!!! * -- cgit v1.2.3 From 79efa097e75018a2918155f343f0e08e61ee8a8c Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 1 Jun 2006 13:33:42 -0400 Subject: [PATCH] usbcore: port reset for composite devices This patch (as699) adds usb_reset_composite_device(), a routine for sending a USB port reset to a device with multiple interfaces owned by different drivers. Drivers are notified about impending and completed resets through two new methods in the usb_driver structure. The patch modifieds the usbfs ioctl code to make it use the new routine instead of usb_reset_device(). Follow-up patches will modify the hub, usb-storage, and usbhid drivers so they can utilize this new API. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 3 +- drivers/usb/core/hub.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++-- drivers/usb/core/usb.c | 1 + include/linux/usb.h | 9 ++++++ 4 files changed, 92 insertions(+), 5 deletions(-) diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index b04ede772f2..df3fb57d71e 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -823,8 +823,7 @@ static int proc_connectinfo(struct dev_state *ps, void __user *arg) static int proc_resetdevice(struct dev_state *ps) { - return usb_reset_device(ps->dev); - + return usb_reset_composite_device(ps->dev, NULL); } static int proc_setintf(struct dev_state *ps, void __user *arg) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index f41c08946a5..37c67d7e8b8 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -3007,9 +3007,9 @@ static int config_descriptors_changed(struct usb_device *udev) * usb_reset_device - perform a USB port reset to reinitialize a device * @udev: device to reset (not in SUSPENDED or NOTATTACHED state) * - * WARNING - don't reset any device unless drivers for all of its - * interfaces are expecting that reset! Maybe some driver->reset() - * method should eventually help ensure sufficient cooperation. + * WARNING - don't use this routine to reset a composite device + * (one with multiple interfaces owned by separate drivers)! + * Use usb_reset_composite_device() instead. * * Do a port reset, reassign the device's address, and establish its * former operating configuration. If the reset fails, or the device's @@ -3125,3 +3125,81 @@ re_enumerate: hub_port_logical_disconnect(parent_hub, port1); return -ENODEV; } + +/** + * usb_reset_composite_device - warn interface drivers and perform a USB port reset + * @udev: device to reset (not in SUSPENDED or NOTATTACHED state) + * @iface: interface bound to the driver making the request (optional) + * + * Warns all drivers bound to registered interfaces (using their pre_reset + * method), performs the port reset, and then lets the drivers know that + * the reset is over (using their post_reset method). + * + * Return value is the same as for usb_reset_device(). + * + * The caller must own the device lock. For example, it's safe to use + * this from a driver probe() routine after downloading new firmware. + * For calls that might not occur during probe(), drivers should lock + * the device using usb_lock_device_for_reset(). + * + * The interface locks are acquired during the pre_reset stage and released + * during the post_reset stage. However if iface is not NULL and is + * currently being probed, we assume that the caller already owns its + * lock. + */ +int usb_reset_composite_device(struct usb_device *udev, + struct usb_interface *iface) +{ + int ret; + struct usb_host_config *config = udev->actconfig; + + if (udev->state == USB_STATE_NOTATTACHED || + udev->state == USB_STATE_SUSPENDED) { + dev_dbg(&udev->dev, "device reset not allowed in state %d\n", + udev->state); + return -EINVAL; + } + + if (iface && iface->condition != USB_INTERFACE_BINDING) + iface = NULL; + + if (config) { + int i; + struct usb_interface *cintf; + struct usb_driver *drv; + + for (i = 0; i < config->desc.bNumInterfaces; ++i) { + cintf = config->interface[i]; + if (cintf != iface) + down(&cintf->dev.sem); + if (device_is_registered(&cintf->dev) && + cintf->dev.driver) { + drv = to_usb_driver(cintf->dev.driver); + if (drv->pre_reset) + (drv->pre_reset)(cintf); + } + } + } + + ret = usb_reset_device(udev); + + if (config) { + int i; + struct usb_interface *cintf; + struct usb_driver *drv; + + for (i = config->desc.bNumInterfaces - 1; i >= 0; --i) { + cintf = config->interface[i]; + if (device_is_registered(&cintf->dev) && + cintf->dev.driver) { + drv = to_usb_driver(cintf->dev.driver); + if (drv->post_reset) + (drv->post_reset)(cintf); + } + if (cintf != iface) + up(&cintf->dev.sem); + } + } + + return ret; +} diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index b7fdc1cd134..51531075130 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -1207,6 +1207,7 @@ EXPORT_SYMBOL(usb_ifnum_to_if); EXPORT_SYMBOL(usb_altnum_to_altsetting); EXPORT_SYMBOL(usb_reset_device); +EXPORT_SYMBOL(usb_reset_composite_device); EXPORT_SYMBOL(__usb_get_extra_descriptor); diff --git a/include/linux/usb.h b/include/linux/usb.h index 317ec9f28bc..5ad30cefe7b 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -386,6 +386,8 @@ extern int usb_lock_device_for_reset(struct usb_device *udev, /* USB port reset for device reinitialization */ extern int usb_reset_device(struct usb_device *dev); +extern int usb_reset_composite_device(struct usb_device *dev, + struct usb_interface *iface); extern struct usb_device *usb_find_device(u16 vendor_id, u16 product_id); @@ -554,6 +556,10 @@ struct usb_dynids { * do (or don't) show up otherwise in the filesystem. * @suspend: Called when the device is going to be suspended by the system. * @resume: Called when the device is being resumed by the system. + * @pre_reset: Called by usb_reset_composite_device() when the device + * is about to be reset. + * @post_reset: Called by usb_reset_composite_device() after the device + * has been reset. * @id_table: USB drivers use ID table to support hotplugging. * Export this with MODULE_DEVICE_TABLE(usb,...). This must be set * or your driver's probe function will never get called. @@ -592,6 +598,9 @@ struct usb_driver { int (*suspend) (struct usb_interface *intf, pm_message_t message); int (*resume) (struct usb_interface *intf); + void (*pre_reset) (struct usb_interface *intf); + void (*post_reset) (struct usb_interface *intf); + const struct usb_device_id *id_table; struct usb_dynids dynids; -- cgit v1.2.3 From 7de18d8bf4b470752e799e219b38b6dff4b49993 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 1 Jun 2006 13:37:24 -0400 Subject: [PATCH] USB hub: use usb_reset_composite_device This patch (as700) modifies the hub driver to take advantage of the new usb_reset_composite_device API. The existing code had special-case calls stuck into usb_reset_device, just before and after the reset. With the new version there's no need for special-case stuff; it all happens naturally in the form of pre_reset and post_reset notifications. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 37c67d7e8b8..e1731ff8af4 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -525,15 +525,16 @@ static int hub_port_disable(struct usb_hub *hub, int port1, int set_state) /* caller has locked the hub device */ -static void hub_pre_reset(struct usb_hub *hub, int disable_ports) +static void hub_pre_reset(struct usb_interface *intf) { + struct usb_hub *hub = usb_get_intfdata(intf); struct usb_device *hdev = hub->hdev; int port1; for (port1 = 1; port1 <= hdev->maxchild; ++port1) { if (hdev->children[port1 - 1]) { usb_disconnect(&hdev->children[port1 - 1]); - if (disable_ports) + if (hub->error == 0) hub_port_disable(hub, port1, 0); } } @@ -541,8 +542,10 @@ static void hub_pre_reset(struct usb_hub *hub, int disable_ports) } /* caller has locked the hub device */ -static void hub_post_reset(struct usb_hub *hub) +static void hub_post_reset(struct usb_interface *intf) { + struct usb_hub *hub = usb_get_intfdata(intf); + hub_activate(hub); hub_power_on(hub); } @@ -802,15 +805,16 @@ static void hub_disconnect(struct usb_interface *intf) struct usb_hub *hub = usb_get_intfdata (intf); struct usb_device *hdev; + /* Disconnect all children and quiesce the hub */ + hub->error = 0; + hub_pre_reset(intf); + usb_set_intfdata (intf, NULL); hdev = hub->hdev; if (hdev->speed == USB_SPEED_HIGH) highspeed_hubs--; - /* Disconnect all children and quiesce the hub */ - hub_pre_reset(hub, 1); - usb_free_urb(hub->urb); hub->urb = NULL; @@ -2747,7 +2751,8 @@ static void hub_events(void) /* If the hub has died, clean up after it */ if (hdev->state == USB_STATE_NOTATTACHED) { - hub_pre_reset(hub, 0); + hub->error = -ENODEV; + hub_pre_reset(intf); goto loop; } @@ -2759,7 +2764,7 @@ static void hub_events(void) dev_dbg (hub_dev, "resetting for error %d\n", hub->error); - ret = usb_reset_device(hdev); + ret = usb_reset_composite_device(hdev, intf); if (ret) { dev_dbg (hub_dev, "error resetting hub: %d\n", ret); @@ -2928,6 +2933,8 @@ static struct usb_driver hub_driver = { .disconnect = hub_disconnect, .suspend = hub_suspend, .resume = hub_resume, + .pre_reset = hub_pre_reset, + .post_reset = hub_post_reset, .ioctl = hub_ioctl, .id_table = hub_id_table, }; @@ -3033,7 +3040,6 @@ int usb_reset_device(struct usb_device *udev) struct usb_device *parent_hdev = udev->parent; struct usb_hub *parent_hub; struct usb_device_descriptor descriptor = udev->descriptor; - struct usb_hub *hub = NULL; int i, ret = 0; int port1 = udev->portnum; @@ -3051,14 +3057,6 @@ int usb_reset_device(struct usb_device *udev) } parent_hub = hdev_to_hub(parent_hdev); - /* If we're resetting an active hub, take some special actions */ - if (udev->actconfig && udev->actconfig->desc.bNumInterfaces > 0 && - udev->actconfig->interface[0]->dev.driver == - &hub_driver.driver && - (hub = hdev_to_hub(udev)) != NULL) { - hub_pre_reset(hub, 0); - } - set_bit(port1, parent_hub->busy_bits); for (i = 0; i < SET_CONFIG_TRIES; ++i) { @@ -3117,8 +3115,6 @@ int usb_reset_device(struct usb_device *udev) } done: - if (hub) - hub_post_reset(hub); return 0; re_enumerate: -- cgit v1.2.3 From 47104b0dd32cec467574822b0dc3517b3de3f0ad Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 1 Jun 2006 13:52:56 -0400 Subject: [PATCH] usb-storage: use usb_reset_composite_device This patch (as701) modifies usb-storage to take advantage of the new usb_reset_composite_device() API. Now we will be able to safely request port resets even if other drivers are bound to a mass-storage device. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/scsiglue.c | 4 ---- drivers/usb/storage/transport.c | 50 +++++++++++++++++++++-------------------- drivers/usb/storage/usb.c | 33 +++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 28 deletions(-) diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index 5f11e19eaae..5715291ba54 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -286,11 +286,7 @@ static int bus_reset(struct scsi_cmnd *srb) int result; US_DEBUGP("%s called\n", __FUNCTION__); - - mutex_lock(&(us->dev_mutex)); result = usb_stor_port_reset(us); - mutex_unlock(&us->dev_mutex); - return result < 0 ? FAILED : SUCCESS; } diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index 038f4582ca0..19b25c5cafd 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c @@ -703,16 +703,19 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) * device reset. */ Handle_Errors: - /* Let the SCSI layer know we are doing a reset, set the - * RESETTING bit, and clear the ABORTING bit so that the reset - * may proceed. */ + /* Set the RESETTING bit, and clear the ABORTING bit so that + * the reset may proceed. */ scsi_lock(us_to_host(us)); - usb_stor_report_bus_reset(us); set_bit(US_FLIDX_RESETTING, &us->flags); clear_bit(US_FLIDX_ABORTING, &us->flags); scsi_unlock(us_to_host(us)); + /* We must release the device lock because the pre_reset routine + * will want to acquire it. */ + mutex_unlock(&us->dev_mutex); result = usb_stor_port_reset(us); + mutex_lock(&us->dev_mutex); + if (result < 0) { scsi_lock(us_to_host(us)); usb_stor_report_device_reset(us); @@ -1196,31 +1199,30 @@ int usb_stor_Bulk_reset(struct us_data *us) 0, us->ifnum, NULL, 0); } -/* Issue a USB port reset to the device. But don't do anything if - * there's more than one interface in the device, so that other users - * are not affected. */ +/* Issue a USB port reset to the device. The caller must not hold + * us->dev_mutex. + */ int usb_stor_port_reset(struct us_data *us) { - int result, rc; + int result, rc_lock; - if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { - result = -EIO; - US_DEBUGP("No reset during disconnect\n"); - } else if (us->pusb_dev->actconfig->desc.bNumInterfaces != 1) { - result = -EBUSY; - US_DEBUGP("Refusing to reset a multi-interface device\n"); - } else { - result = rc = - usb_lock_device_for_reset(us->pusb_dev, us->pusb_intf); - if (result < 0) { - US_DEBUGP("unable to lock device for reset: %d\n", - result); + result = rc_lock = + usb_lock_device_for_reset(us->pusb_dev, us->pusb_intf); + if (result < 0) + US_DEBUGP("unable to lock device for reset: %d\n", result); + else { + /* Were we disconnected while waiting for the lock? */ + if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { + result = -EIO; + US_DEBUGP("No reset during disconnect\n"); } else { - result = usb_reset_device(us->pusb_dev); - if (rc) - usb_unlock_device(us->pusb_dev); - US_DEBUGP("usb_reset_device returns %d\n", result); + result = usb_reset_composite_device( + us->pusb_dev, us->pusb_intf); + US_DEBUGP("usb_reset_composite_device returns %d\n", + result); } + if (rc_lock) + usb_unlock_device(us->pusb_dev); } return result; } diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 0142fe82f6b..e232c7c8990 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -220,6 +220,37 @@ static int storage_resume(struct usb_interface *iface) #endif /* CONFIG_PM */ +/* + * The next two routines get called just before and just after + * a USB port reset, whether from this driver or a different one. + */ + +static void storage_pre_reset(struct usb_interface *iface) +{ + struct us_data *us = usb_get_intfdata(iface); + + US_DEBUGP("%s\n", __FUNCTION__); + + /* Make sure no command runs during the reset */ + mutex_lock(&us->dev_mutex); +} + +static void storage_post_reset(struct usb_interface *iface) +{ + struct us_data *us = usb_get_intfdata(iface); + + US_DEBUGP("%s\n", __FUNCTION__); + + /* Report the reset to the SCSI core */ + scsi_lock(us_to_host(us)); + usb_stor_report_bus_reset(us); + scsi_unlock(us_to_host(us)); + + /* FIXME: Notify the subdrivers that they need to reinitialize + * the device */ + mutex_unlock(&us->dev_mutex); +} + /* * fill_inquiry_response takes an unsigned char array (which must * be at least 36 characters) and populates the vendor name, @@ -1002,6 +1033,8 @@ static struct usb_driver usb_storage_driver = { .suspend = storage_suspend, .resume = storage_resume, #endif + .pre_reset = storage_pre_reset, + .post_reset = storage_post_reset, .id_table = storage_usb_ids, }; -- cgit v1.2.3 From df9a1f482d1252045210f50048911e2efba61e62 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 1 Jun 2006 13:55:28 -0400 Subject: [PATCH] usbhid: use usb_reset_composite_device This patch (as702) makes usbhid use the new usb_reset_composite_device API. Now HID interfaces can coexist with other interfaces on the same device, and a reset can safely be requested by any of the drivers. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/input/hid-core.c | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index c6051beeabd..17b6e6ab370 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -944,21 +944,28 @@ static void hid_reset(void *_hid) dev_dbg(&hid->intf->dev, "resetting device\n"); rc = rc_lock = usb_lock_device_for_reset(hid->dev, hid->intf); if (rc_lock >= 0) { - rc = usb_reset_device(hid->dev); + rc = usb_reset_composite_device(hid->dev, hid->intf); if (rc_lock) usb_unlock_device(hid->dev); } clear_bit(HID_RESET_PENDING, &hid->iofl); - if (rc == 0) { - hid->retry_delay = 0; - if (hid_start_in(hid)) + switch (rc) { + case 0: + if (!test_bit(HID_IN_RUNNING, &hid->iofl)) hid_io_error(hid); - } else if (!(rc == -ENODEV || rc == -EHOSTUNREACH || rc == -EINTR)) + break; + default: err("can't reset device, %s-%s/input%d, status %d", hid->dev->bus->bus_name, hid->dev->devpath, hid->ifnum, rc); + /* FALLTHROUGH */ + case -EHOSTUNREACH: + case -ENODEV: + case -EINTR: + break; + } } /* Main I/O error handler */ @@ -2063,11 +2070,29 @@ static int hid_resume(struct usb_interface *intf) int status; clear_bit(HID_SUSPENDED, &hid->iofl); + hid->retry_delay = 0; status = hid_start_in(hid); dev_dbg(&intf->dev, "resume status %d\n", status); return status; } +/* Treat USB reset pretty much the same as suspend/resume */ +static void hid_pre_reset(struct usb_interface *intf) +{ + /* FIXME: What if the interface is already suspended? */ + hid_suspend(intf, PMSG_ON); +} + +static void hid_post_reset(struct usb_interface *intf) +{ + struct usb_device *dev = interface_to_usbdev (intf); + + hid_set_idle(dev, intf->cur_altsetting->desc.bInterfaceNumber, 0, 0); + /* FIXME: Any more reinitialization needed? */ + + hid_resume(intf); +} + static struct usb_device_id hid_usb_ids [] = { { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS, .bInterfaceClass = USB_INTERFACE_CLASS_HID }, @@ -2082,6 +2107,8 @@ static struct usb_driver hid_driver = { .disconnect = hid_disconnect, .suspend = hid_suspend, .resume = hid_resume, + .pre_reset = hid_pre_reset, + .post_reset = hid_post_reset, .id_table = hid_usb_ids, }; -- cgit v1.2.3 From 6ad07129a8ed2e13dcd7e6313c201c32bcf7cc32 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 1 Jun 2006 13:59:16 -0400 Subject: [PATCH] usbcore: recovery from Set-Configuration failure This patch (as703) improves the error handling when a Set-Configuration request fails. The old interfaces are all unregistered before the request is sent, and if the request fails then we don't know what config the device is using. So it makes no sense to leave actconfig pointing to the old configuration with its invalid interfaces. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/message.c | 151 ++++++++++++++++++++++----------------------- 1 file changed, 75 insertions(+), 76 deletions(-) diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index b2f608b0538..8569600f313 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1411,15 +1411,7 @@ free_interfaces: return ret; } } - } - /* if it's already configured, clear out old state first. - * getting rid of old interfaces means unbinding their drivers. - */ - if (dev->state != USB_STATE_ADDRESS) - usb_disable_device (dev, 1); // Skip ep0 - - if (cp) { i = dev->bus_mA - cp->desc.bMaxPower * 2; if (i < 0) dev_warn(&dev->dev, "new config #%d exceeds power " @@ -1427,84 +1419,91 @@ free_interfaces: configuration, -i); } + /* if it's already configured, clear out old state first. + * getting rid of old interfaces means unbinding their drivers. + */ + if (dev->state != USB_STATE_ADDRESS) + usb_disable_device (dev, 1); // Skip ep0 + if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_CONFIGURATION, 0, configuration, 0, - NULL, 0, USB_CTRL_SET_TIMEOUT)) < 0) - goto free_interfaces; + NULL, 0, USB_CTRL_SET_TIMEOUT)) < 0) { + + /* All the old state is gone, so what else can we do? + * The device is probably useless now anyway. + */ + cp = NULL; + } dev->actconfig = cp; - if (!cp) + if (!cp) { usb_set_device_state(dev, USB_STATE_ADDRESS); - else { - usb_set_device_state(dev, USB_STATE_CONFIGURED); + goto free_interfaces; + } + usb_set_device_state(dev, USB_STATE_CONFIGURED); - /* Initialize the new interface structures and the - * hc/hcd/usbcore interface/endpoint state. - */ - for (i = 0; i < nintf; ++i) { - struct usb_interface_cache *intfc; - struct usb_interface *intf; - struct usb_host_interface *alt; - - cp->interface[i] = intf = new_interfaces[i]; - intfc = cp->intf_cache[i]; - intf->altsetting = intfc->altsetting; - intf->num_altsetting = intfc->num_altsetting; - kref_get(&intfc->ref); - - alt = usb_altnum_to_altsetting(intf, 0); - - /* No altsetting 0? We'll assume the first altsetting. - * We could use a GetInterface call, but if a device is - * so non-compliant that it doesn't have altsetting 0 - * then I wouldn't trust its reply anyway. - */ - if (!alt) - alt = &intf->altsetting[0]; - - intf->cur_altsetting = alt; - usb_enable_interface(dev, intf); - intf->dev.parent = &dev->dev; - intf->dev.driver = NULL; - intf->dev.bus = &usb_bus_type; - intf->dev.dma_mask = dev->dev.dma_mask; - intf->dev.release = release_interface; - device_initialize (&intf->dev); - mark_quiesced(intf); - sprintf (&intf->dev.bus_id[0], "%d-%s:%d.%d", - dev->bus->busnum, dev->devpath, - configuration, - alt->desc.bInterfaceNumber); - } - kfree(new_interfaces); + /* Initialize the new interface structures and the + * hc/hcd/usbcore interface/endpoint state. + */ + for (i = 0; i < nintf; ++i) { + struct usb_interface_cache *intfc; + struct usb_interface *intf; + struct usb_host_interface *alt; - if (cp->string == NULL) - cp->string = usb_cache_string(dev, - cp->desc.iConfiguration); + cp->interface[i] = intf = new_interfaces[i]; + intfc = cp->intf_cache[i]; + intf->altsetting = intfc->altsetting; + intf->num_altsetting = intfc->num_altsetting; + kref_get(&intfc->ref); - /* Now that all the interfaces are set up, register them - * to trigger binding of drivers to interfaces. probe() - * routines may install different altsettings and may - * claim() any interfaces not yet bound. Many class drivers - * need that: CDC, audio, video, etc. + alt = usb_altnum_to_altsetting(intf, 0); + + /* No altsetting 0? We'll assume the first altsetting. + * We could use a GetInterface call, but if a device is + * so non-compliant that it doesn't have altsetting 0 + * then I wouldn't trust its reply anyway. */ - for (i = 0; i < nintf; ++i) { - struct usb_interface *intf = cp->interface[i]; - - dev_dbg (&dev->dev, - "adding %s (config #%d, interface %d)\n", - intf->dev.bus_id, configuration, - intf->cur_altsetting->desc.bInterfaceNumber); - ret = device_add (&intf->dev); - if (ret != 0) { - dev_err(&dev->dev, - "device_add(%s) --> %d\n", - intf->dev.bus_id, - ret); - continue; - } - usb_create_sysfs_intf_files (intf); + if (!alt) + alt = &intf->altsetting[0]; + + intf->cur_altsetting = alt; + usb_enable_interface(dev, intf); + intf->dev.parent = &dev->dev; + intf->dev.driver = NULL; + intf->dev.bus = &usb_bus_type; + intf->dev.dma_mask = dev->dev.dma_mask; + intf->dev.release = release_interface; + device_initialize (&intf->dev); + mark_quiesced(intf); + sprintf (&intf->dev.bus_id[0], "%d-%s:%d.%d", + dev->bus->busnum, dev->devpath, + configuration, alt->desc.bInterfaceNumber); + } + kfree(new_interfaces); + + if (cp->string == NULL) + cp->string = usb_cache_string(dev, cp->desc.iConfiguration); + + /* Now that all the interfaces are set up, register them + * to trigger binding of drivers to interfaces. probe() + * routines may install different altsettings and may + * claim() any interfaces not yet bound. Many class drivers + * need that: CDC, audio, video, etc. + */ + for (i = 0; i < nintf; ++i) { + struct usb_interface *intf = cp->interface[i]; + + dev_dbg (&dev->dev, + "adding %s (config #%d, interface %d)\n", + intf->dev.bus_id, configuration, + intf->cur_altsetting->desc.bInterfaceNumber); + ret = device_add (&intf->dev); + if (ret != 0) { + dev_err(&dev->dev, "device_add(%s) --> %d\n", + intf->dev.bus_id, ret); + continue; } + usb_create_sysfs_intf_files (intf); } return 0; -- cgit v1.2.3 From 786dc1d3d7333f269e17d742886eac2188a2d9cc Mon Sep 17 00:00:00 2001 From: Philippe Retornaz Date: Thu, 1 Jun 2006 20:48:46 -0700 Subject: [PATCH] usb: drivers/usb/core/devio.c dereferences a userspace pointer See http://bugzilla.kernel.org/show_bug.cgi?id=6617. This function dereference a __user pointer. Signed-off-by: Philippe Retornaz Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index df3fb57d71e..2eda52fc1eb 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -1078,7 +1078,9 @@ static int proc_submiturb(struct dev_state *ps, void __user *arg) if (copy_from_user(&uurb, arg, sizeof(uurb))) return -EFAULT; - return proc_do_submiturb(ps, &uurb, (((struct usbdevfs_urb __user *)arg)->iso_frame_desc), arg); + return proc_do_submiturb(ps, &uurb, + (struct usbdevfs_iso_packet_desc __user *)uurb.iso_frame_desc, + arg); } static int proc_unlinkurb(struct dev_state *ps, void __user *arg) @@ -1203,7 +1205,9 @@ static int proc_submiturb_compat(struct dev_state *ps, void __user *arg) if (get_urb32(&uurb,(struct usbdevfs_urb32 *)arg)) return -EFAULT; - return proc_do_submiturb(ps, &uurb, ((struct usbdevfs_urb32 __user *)arg)->iso_frame_desc, arg); + return proc_do_submiturb(ps, &uurb, + (struct usbdevfs_iso_packet_desc __user *)uurb.iso_frame_desc, + arg); } static int processcompl_compat(struct async *as, void __user * __user *arg) -- cgit v1.2.3 From 14f76cc7ab75b1c9db036dcd6b247e0dcc8952be Mon Sep 17 00:00:00 2001 From: Matthias Urlichs Date: Fri, 2 Jun 2006 11:48:56 +0200 Subject: [PATCH] USB: new devices for the Option driver This patch extends the "option" driver with a few more devices, some of which are actually connected to USB the "right" way -- as opposed to doing it via PCMCIA and OHCI. Signed-Off-By: Matthias Urlichs Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/Kconfig | 16 ++++-- drivers/usb/serial/option.c | 136 ++++++++++++++++++++++++++++++++++---------- 2 files changed, 118 insertions(+), 34 deletions(-) diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index 12ad6f0897e..8bd44fda5ea 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig @@ -491,16 +491,22 @@ config USB_SERIAL_XIRCOM module will be called keyspan_pda. config USB_SERIAL_OPTION - tristate "USB Option PCMCIA serial driver" - depends on USB_SERIAL && USB_OHCI_HCD && PCCARD + tristate "USB driver for GSM modems" + depends on USB_SERIAL help - Say Y here if you want to use an Option card. This is a - GSM card, controlled by three serial ports which are connected - via an OHCI adapter located on a PC card. + Say Y here if you have an "Option" GSM PCMCIA card + (or an OEM version: branded Huawei, Audiovox, or Novatel). + + These cards feature a built-in OHCI-USB adapter and an + internally-connected GSM modem. The USB bus is not + accessible externally. To compile this driver as a module, choose M here: the module will be called option. + If this driver doesn't recognize your device, + it might be accessible via the FTDI_SIO driver. + config USB_SERIAL_OMNINET tristate "USB ZyXEL omni.net LCD Plus Driver (EXPERIMENTAL)" depends on USB_SERIAL && EXPERIMENTAL diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 759d3608718..b0861b61bba 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -1,5 +1,5 @@ /* - Option Card (PCMCIA to) USB to Serial Driver + USB Driver for GSM modems Copyright (C) 2005 Matthias Urlichs @@ -28,15 +28,34 @@ 2005-09-10 v0.4.3 added HUAWEI E600 card and Audiovox AirCard 2005-09-20 v0.4.4 increased recv buffer size: the card sometimes wants to send >2000 bytes. - 2006-04-10 v0.4.2 fixed two array overrun errors :-/ + 2006-04-10 v0.5 fixed two array overrun errors :-/ + 2006-04-21 v0.5.1 added support for Sierra Wireless MC8755 + 2006-05-15 v0.6 re-enable multi-port support + 2006-06-01 v0.6.1 add COBRA + 2006-06-01 v0.6.2 add backwards-compatibility stuff + 2006-06-01 v0.6.3 add Novatel Wireless + 2006-06-01 v0.7 Option => GSM Work sponsored by: Sigos GmbH, Germany + This driver exists because the "normal" serial driver doesn't work too well + with GSM modems. Issues: + - data loss -- one single Receive URB is not nearly enough + - nonstandard flow (Option devices) and multiplex (Sierra) control + - controlling the baud rate doesn't make sense + + This driver is named "option" because the most common device it's + used for is a PC-Card (with an internal OHCI-USB interface, behind + which the GSM interface sits), made by Option Inc. + + Some of the "one port" devices actually exhibit multiple USB instances + on the USB bus. This is not a bug, these ports are used for different + device features. */ -#define DRIVER_VERSION "v0.4" +#define DRIVER_VERSION "v0.7.0" #define DRIVER_AUTHOR "Matthias Urlichs " -#define DRIVER_DESC "Option Card (PC-Card to) USB to Serial Driver" +#define DRIVER_DESC "USB Driver for GSM modems" #include #include @@ -74,22 +93,45 @@ static int option_tiocmset(struct usb_serial_port *port, struct file *file, static int option_send_setup(struct usb_serial_port *port); /* Vendor and product IDs */ -#define OPTION_VENDOR_ID 0x0AF0 -#define HUAWEI_VENDOR_ID 0x12D1 -#define AUDIOVOX_VENDOR_ID 0x0F3D - -#define OPTION_PRODUCT_OLD 0x5000 -#define OPTION_PRODUCT_FUSION 0x6000 -#define OPTION_PRODUCT_FUSION2 0x6300 -#define HUAWEI_PRODUCT_E600 0x1001 -#define AUDIOVOX_PRODUCT_AIRCARD 0x0112 +#define OPTION_VENDOR_ID 0x0AF0 +#define HUAWEI_VENDOR_ID 0x12D1 +#define AUDIOVOX_VENDOR_ID 0x0F3D +#define SIERRAWIRELESS_VENDOR_ID 0x1199 +#define NOVATELWIRELESS_VENDOR_ID 0x1410 + +#define OPTION_PRODUCT_OLD 0x5000 +#define OPTION_PRODUCT_FUSION 0x6000 +#define OPTION_PRODUCT_FUSION2 0x6300 +#define OPTION_PRODUCT_COBRA 0x6500 +#define HUAWEI_PRODUCT_E600 0x1001 +#define AUDIOVOX_PRODUCT_AIRCARD 0x0112 +#define SIERRAWIRELESS_PRODUCT_MC8755 0x6802 +#define NOVATELWIRELESS_PRODUCT_U740 0x1400 static struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) }, + { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) }, { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) }, { USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) }, + { USB_DEVICE(SIERRAWIRELESS_VENDOR_ID, SIERRAWIRELESS_PRODUCT_MC8755) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) }, + { } /* Terminating entry */ +}; + +static struct usb_device_id option_ids1[] = { + { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) }, + { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION) }, + { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) }, + { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) }, + { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) }, + { USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) }, + { } /* Terminating entry */ +}; +static struct usb_device_id option_ids3[] = { + { USB_DEVICE(SIERRAWIRELESS_VENDOR_ID, SIERRAWIRELESS_PRODUCT_MC8755) }, { } /* Terminating entry */ }; @@ -111,12 +153,39 @@ static struct usb_serial_driver option_3port_device = { .owner = THIS_MODULE, .name = "option", }, - .description = "Option 3G data card", - .id_table = option_ids, + .description = "GSM modem (3-port)", + .id_table = option_ids3, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = NUM_DONT_CARE, .num_bulk_out = NUM_DONT_CARE, - .num_ports = 1, /* 3, but the card reports its ports separately */ + .num_ports = 3, + .open = option_open, + .close = option_close, + .write = option_write, + .write_room = option_write_room, + .chars_in_buffer = option_chars_in_buffer, + .throttle = option_rx_throttle, + .unthrottle = option_rx_unthrottle, + .set_termios = option_set_termios, + .break_ctl = option_break_ctl, + .tiocmget = option_tiocmget, + .tiocmset = option_tiocmset, + .attach = option_startup, + .shutdown = option_shutdown, + .read_int_callback = option_instat_callback, +}; + +static struct usb_serial_driver option_1port_device = { + .driver = { + .owner = THIS_MODULE, + .name = "option", + }, + .description = "GSM modem (1-port)", + .id_table = option_ids1, + .num_interrupt_in = NUM_DONT_CARE, + .num_bulk_in = NUM_DONT_CARE, + .num_bulk_out = NUM_DONT_CARE, + .num_ports = 1, .open = option_open, .close = option_close, .write = option_write, @@ -170,6 +239,9 @@ struct option_port_private { static int __init option_init(void) { int retval; + retval = usb_serial_register(&option_1port_device); + if (retval) + goto failed_1port_device_register; retval = usb_serial_register(&option_3port_device); if (retval) goto failed_3port_device_register; @@ -184,6 +256,8 @@ static int __init option_init(void) failed_driver_register: usb_serial_deregister (&option_3port_device); failed_3port_device_register: + usb_serial_deregister (&option_1port_device); +failed_1port_device_register: return retval; } @@ -191,6 +265,7 @@ static void __exit option_exit(void) { usb_deregister (&option_driver); usb_serial_deregister (&option_3port_device); + usb_serial_deregister (&option_1port_device); } module_init(option_init); @@ -572,27 +647,30 @@ static struct urb *option_setup_urb(struct usb_serial *serial, int endpoint, /* Setup urbs */ static void option_setup_urbs(struct usb_serial *serial) { - int j; + int i,j; struct usb_serial_port *port; struct option_port_private *portdata; dbg("%s", __FUNCTION__); - port = serial->port[0]; - portdata = usb_get_serial_port_data(port); + + for (i = 0; i < serial->num_ports; i++) { + port = serial->port[i]; + portdata = usb_get_serial_port_data(port); /* Do indat endpoints first */ - for (j = 0; j < N_IN_URB; ++j) { - portdata->in_urbs[j] = option_setup_urb (serial, - port->bulk_in_endpointAddress, USB_DIR_IN, port, - portdata->in_buffer[j], IN_BUFLEN, option_indat_callback); - } + for (j = 0; j < N_IN_URB; ++j) { + portdata->in_urbs[j] = option_setup_urb (serial, + port->bulk_in_endpointAddress, USB_DIR_IN, port, + portdata->in_buffer[j], IN_BUFLEN, option_indat_callback); + } - /* outdat endpoints */ - for (j = 0; j < N_OUT_URB; ++j) { - portdata->out_urbs[j] = option_setup_urb (serial, - port->bulk_out_endpointAddress, USB_DIR_OUT, port, - portdata->out_buffer[j], OUT_BUFLEN, option_outdat_callback); + /* outdat endpoints */ + for (j = 0; j < N_OUT_URB; ++j) { + portdata->out_urbs[j] = option_setup_urb (serial, + port->bulk_out_endpointAddress, USB_DIR_OUT, port, + portdata->out_buffer[j], OUT_BUFLEN, option_outdat_callback); + } } } -- cgit v1.2.3 From bfd5df3c0cf65bdf10a3a00baff036cb096140f6 Mon Sep 17 00:00:00 2001 From: Chris Lund Date: Sat, 3 Jun 2006 13:58:19 -0700 Subject: [PATCH] USB: free allocated memory on io_edgeport startup memory failure While an Edgeport is allocating individual port structures, if kmalloc returns NULL, the serial structure is freed and -ENOMEM, but the ports allocated before the failure are not freed. This patch addresses that condition. Signed-off-by: Christopher Lund Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/io_edgeport.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index c28f1f6902c..ed976ab5668 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -2730,7 +2730,7 @@ static int edge_startup (struct usb_serial *serial) struct edgeport_serial *edge_serial; struct edgeport_port *edge_port; struct usb_device *dev; - int i; + int i, j; dev = serial->dev; @@ -2794,6 +2794,10 @@ static int edge_startup (struct usb_serial *serial) edge_port = kmalloc (sizeof(struct edgeport_port), GFP_KERNEL); if (edge_port == NULL) { dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__); + for (j = 0; j < i; ++j) { + kfree (usb_get_serial_port_data(serial->port[j])); + usb_set_serial_port_data(serial->port[j], NULL); + } usb_set_serial_data(serial, NULL); kfree(edge_serial); return -ENOMEM; -- cgit v1.2.3 From dfbaa7d8a4056436b6a170625d64986ebb648486 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sat, 3 Jun 2006 23:58:55 +0100 Subject: [PATCH] USB: EHCI on non-Au1200 build fix Including ehci-au1xxx.c on a non-Au1200 Alchemy only to have it throw an error is stupid. From: Ralf Baechle Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-au1xxx.c | 4 ---- drivers/usb/host/ehci-hcd.c | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c index 0e444ab1930..9b4697add31 100644 --- a/drivers/usb/host/ehci-au1xxx.c +++ b/drivers/usb/host/ehci-au1xxx.c @@ -16,10 +16,6 @@ #include #include -#ifndef CONFIG_SOC_AU1200 -#error "this Alchemy chip doesn't have EHCI" -#else /* Au1200 */ - #define USB_HOST_CONFIG (USB_MSR_BASE + USB_MSR_MCFG) #define USB_MCFG_PFEN (1<<31) #define USB_MCFG_RDCOMB (1<<30) diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 7d7c97cf9b2..9b37e508ada 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -897,7 +897,7 @@ MODULE_LICENSE ("GPL"); #define PLATFORM_DRIVER ehci_fsl_driver #endif -#ifdef CONFIG_SOC_AU1X00 +#ifdef CONFIG_SOC_AU1200 #include "ehci-au1xxx.c" #define PLATFORM_DRIVER ehci_hcd_au1xxx_driver #endif -- cgit v1.2.3 From 5c218e3b86510f9685bfae5b0d2d7cc8468056c1 Mon Sep 17 00:00:00 2001 From: Rene Rebe Date: Sun, 4 Jun 2006 11:39:09 +0200 Subject: [PATCH] USB: Add Apple MacBook product IDs to usbhid This adds the Apple MacBook product IDs for the Fn translation to the usbhid. Signed-off-by: Rene Rebe Signed-off-by: Greg Kroah-Hartman --- drivers/usb/input/hid-core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 17b6e6ab370..b9fb9687f92 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -1693,6 +1693,9 @@ static const struct hid_blacklist { { USB_VENDOR_ID_APPLE, 0x0214, HID_QUIRK_POWERBOOK_HAS_FN }, { USB_VENDOR_ID_APPLE, 0x0215, HID_QUIRK_POWERBOOK_HAS_FN }, { USB_VENDOR_ID_APPLE, 0x0216, HID_QUIRK_POWERBOOK_HAS_FN }, + { USB_VENDOR_ID_APPLE, 0x0217, HID_QUIRK_POWERBOOK_HAS_FN }, + { USB_VENDOR_ID_APPLE, 0x0218, HID_QUIRK_POWERBOOK_HAS_FN }, + { USB_VENDOR_ID_APPLE, 0x0219, HID_QUIRK_POWERBOOK_HAS_FN }, { USB_VENDOR_ID_APPLE, 0x030A, HID_QUIRK_POWERBOOK_HAS_FN }, { USB_VENDOR_ID_APPLE, 0x030B, HID_QUIRK_POWERBOOK_HAS_FN }, -- cgit v1.2.3 From ae671813affd947d2f21ff8e3cd329e466ee85b2 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 6 Jun 2006 15:19:17 -0400 Subject: [PATCH] usb-storage: unusual_devs entry for Nikon DSC D70s This patch (as704) adds an unusual_devs entry for the Nikon DSC D70s, which uses a different Product ID from the D70. It also moves the entry for the DSC E2000 up in the list, to preserve the numerical ordering. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 9f72000a006..3ec17689b81 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -216,6 +216,14 @@ UNUSUAL_DEV( 0x04a4, 0x0004, 0x0001, 0x0001, "DVD-CAM DZ-MV100A Camcorder", US_SC_SCSI, US_PR_CB, NULL, US_FL_SINGLE_LUN), +/* Patch for Nikon coolpix 2000 + * Submitted by Fabien Cosse */ +UNUSUAL_DEV( 0x04b0, 0x0301, 0x0010, 0x0010, + "NIKON", + "NIKON DSC E2000", + US_SC_DEVICE, US_PR_DEVICE,NULL, + US_FL_NOT_LOCKABLE ), + /* Reported by Andreas Bockhold */ UNUSUAL_DEV( 0x04b0, 0x0405, 0x0100, 0x0100, "NIKON", @@ -223,13 +231,12 @@ UNUSUAL_DEV( 0x04b0, 0x0405, 0x0100, 0x0100, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY), -/* Patch for Nikon coolpix 2000 - * Submitted by Fabien Cosse */ -UNUSUAL_DEV( 0x04b0, 0x0301, 0x0010, 0x0010, +/* Reported by Jamie Kitson */ +UNUSUAL_DEV( 0x04b0, 0x040d, 0x0100, 0x0100, "NIKON", - "NIKON DSC E2000", - US_SC_DEVICE, US_PR_DEVICE,NULL, - US_FL_NOT_LOCKABLE ), + "NIKON DSC D70s", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_CAPACITY), /* BENQ DC5330 * Reported by Manuel Fombuena and -- cgit v1.2.3 From be3cbc5f87d4b1fbd714644b6824ce4eb229f372 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Mon, 5 Jun 2006 12:16:39 -0400 Subject: [PATCH] UHCI: various updates This patch (as705) contains a small set of updates for uhci-hcd written mostly by Dave Brownell: * Root hub suspend messages come out labeled as root hub messages; PCI messages should only come out when the pci device suspends. * Rename the reset() method to better match its init() role * Behave more like the other HCDs by returning -ESHUTDOWN for root-hub suspend/resume errors. * When an URB fails, associate the message with the usb device not the host controller (it still hides endpoint and direction) From: David Brownell Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/uhci-hcd.c | 37 +++++++++++++++++++++---------------- drivers/usb/host/uhci-q.c | 2 +- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 5e75ad6dc29..dc9ed29c617 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -124,8 +124,9 @@ static void hc_died(struct uhci_hcd *uhci) } /* - * Initialize a controller that was newly discovered or has just been - * resumed. In either case we can't be sure of its previous state. + * Initialize a controller that was newly discovered or has lost power + * or otherwise been reset while it was suspended. In none of these cases + * can we be sure of its previous state. */ static void check_and_reset_hc(struct uhci_hcd *uhci) { @@ -198,7 +199,8 @@ __acquires(uhci->lock) int int_enable; auto_stop = (new_state == UHCI_RH_AUTO_STOPPED); - dev_dbg(uhci_dev(uhci), "%s%s\n", __FUNCTION__, + dev_dbg(&uhci_to_hcd(uhci)->self.root_hub->dev, + "%s%s\n", __FUNCTION__, (auto_stop ? " (auto-stop)" : "")); /* If we get a suspend request when we're already auto-stopped @@ -236,7 +238,8 @@ __acquires(uhci->lock) return; } if (!(inw(uhci->io_addr + USBSTS) & USBSTS_HCH)) - dev_warn(uhci_dev(uhci), "Controller not stopped yet!\n"); + dev_warn(&uhci_to_hcd(uhci)->self.root_hub->dev, + "Controller not stopped yet!\n"); uhci_get_current_frame_number(uhci); @@ -268,7 +271,8 @@ static void wakeup_rh(struct uhci_hcd *uhci) __releases(uhci->lock) __acquires(uhci->lock) { - dev_dbg(uhci_dev(uhci), "%s%s\n", __FUNCTION__, + dev_dbg(&uhci_to_hcd(uhci)->self.root_hub->dev, + "%s%s\n", __FUNCTION__, uhci->rh_state == UHCI_RH_AUTO_STOPPED ? " (auto-start)" : ""); @@ -406,7 +410,7 @@ static void release_uhci(struct uhci_hcd *uhci) uhci->frame, uhci->frame_dma_handle); } -static int uhci_reset(struct usb_hcd *hcd) +static int uhci_init(struct usb_hcd *hcd) { struct uhci_hcd *uhci = hcd_to_uhci(hcd); unsigned io_size = (unsigned) hcd->rsrc_len; @@ -672,12 +676,15 @@ static void uhci_stop(struct usb_hcd *hcd) static int uhci_rh_suspend(struct usb_hcd *hcd) { struct uhci_hcd *uhci = hcd_to_uhci(hcd); + int rc = 0; spin_lock_irq(&uhci->lock); - if (!uhci->hc_inaccessible) /* Not dead */ + if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) + rc = -ESHUTDOWN; + else if (!uhci->hc_inaccessible) suspend_rh(uhci, UHCI_RH_SUSPENDED); spin_unlock_irq(&uhci->lock); - return 0; + return rc; } static int uhci_rh_resume(struct usb_hcd *hcd) @@ -686,13 +693,10 @@ static int uhci_rh_resume(struct usb_hcd *hcd) int rc = 0; spin_lock_irq(&uhci->lock); - if (uhci->hc_inaccessible) { - if (uhci->rh_state == UHCI_RH_SUSPENDED) { - dev_warn(uhci_dev(uhci), "HC isn't running!\n"); - rc = -ENODEV; - } - /* Otherwise the HC is dead */ - } else + if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { + dev_warn(&hcd->self.root_hub->dev, "HC isn't running!\n"); + rc = -ESHUTDOWN; + } else if (!uhci->hc_inaccessible) wakeup_rh(uhci); spin_unlock_irq(&uhci->lock); return rc; @@ -746,6 +750,7 @@ static int uhci_resume(struct usb_hcd *hcd) if (uhci->rh_state == UHCI_RH_RESET) /* Dead */ return 0; + spin_lock_irq(&uhci->lock); /* FIXME: Disable non-PME# remote wakeup? */ @@ -828,7 +833,7 @@ static const struct hc_driver uhci_driver = { .flags = HCD_USB11, /* Basic lifecycle operations */ - .reset = uhci_reset, + .reset = uhci_init, .start = uhci_start, #ifdef CONFIG_PM .suspend = uhci_suspend, diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index cbbaa4c1740..b173d914d74 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -910,7 +910,7 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb) uhci_packetout(td_token(td))); if ((debug == 1 && ret != -EPIPE) || debug > 1) { /* Some debugging code */ - dev_dbg(uhci_dev(uhci), + dev_dbg(&urb->dev->dev, "%s: failed with status %x\n", __FUNCTION__, status); -- cgit v1.2.3 From e323de46e83b6df2f330651907ac823f8d53308a Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 5 Jun 2006 12:21:30 -0400 Subject: [PATCH] UHCI: remove hc_inaccessible flag This patch (as706) removes the private hc_inaccessible flag from uhci-hcd. It's not needed because it conveys exactly the same information as the generic HCD_FLAG_HW_ACCESSIBLE bit. In its place goes a new flag recording whether the controller is dead. The new code allows a complete device reset to resurrect a dead controller (although usbcore doesn't yet implement such a facility). Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/uhci-hcd.c | 49 ++++++++++++++++++++++++--------------------- drivers/usb/host/uhci-hcd.h | 2 +- drivers/usb/host/uhci-hub.c | 4 ++-- 3 files changed, 29 insertions(+), 26 deletions(-) diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index dc9ed29c617..025b969f95e 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -110,17 +110,23 @@ static void finish_reset(struct uhci_hcd *uhci) uhci->is_stopped = UHCI_IS_STOPPED; uhci_to_hcd(uhci)->state = HC_STATE_HALT; uhci_to_hcd(uhci)->poll_rh = 0; + + uhci->dead = 0; /* Full reset resurrects the controller */ } /* * Last rites for a defunct/nonfunctional controller * or one we don't want to use any more. */ -static void hc_died(struct uhci_hcd *uhci) +static void uhci_hc_died(struct uhci_hcd *uhci) { + uhci_get_current_frame_number(uhci); uhci_reset_hc(to_pci_dev(uhci_dev(uhci)), uhci->io_addr); finish_reset(uhci); - uhci->hc_inaccessible = 1; + uhci->dead = 1; + + /* The current frame may already be partway finished */ + ++uhci->frame_number; } /* @@ -234,7 +240,7 @@ __acquires(uhci->lock) spin_unlock_irq(&uhci->lock); msleep(1); spin_lock_irq(&uhci->lock); - if (uhci->hc_inaccessible) /* Died */ + if (uhci->dead) return; } if (!(inw(uhci->io_addr + USBSTS) & USBSTS_HCH)) @@ -287,7 +293,7 @@ __acquires(uhci->lock) spin_unlock_irq(&uhci->lock); msleep(20); spin_lock_irq(&uhci->lock); - if (uhci->hc_inaccessible) /* Died */ + if (uhci->dead) return; /* End Global Resume and wait for EOP to be sent */ @@ -339,7 +345,7 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs) errbuf, ERRBUF_LEN); lprintk(errbuf); } - hc_died(uhci); + uhci_hc_died(uhci); /* Force a callback in case there are * pending unlinks */ @@ -462,7 +468,7 @@ static void uhci_shutdown(struct pci_dev *pdev) { struct usb_hcd *hcd = (struct usb_hcd *) pci_get_drvdata(pdev); - hc_died(hcd_to_uhci(hcd)); + uhci_hc_died(hcd_to_uhci(hcd)); } /* @@ -664,8 +670,8 @@ static void uhci_stop(struct usb_hcd *hcd) struct uhci_hcd *uhci = hcd_to_uhci(hcd); spin_lock_irq(&uhci->lock); - if (!uhci->hc_inaccessible) - hc_died(uhci); + if (test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) && !uhci->dead) + uhci_hc_died(uhci); uhci_scan_schedule(uhci, NULL); spin_unlock_irq(&uhci->lock); @@ -681,7 +687,7 @@ static int uhci_rh_suspend(struct usb_hcd *hcd) spin_lock_irq(&uhci->lock); if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) rc = -ESHUTDOWN; - else if (!uhci->hc_inaccessible) + else if (!uhci->dead) suspend_rh(uhci, UHCI_RH_SUSPENDED); spin_unlock_irq(&uhci->lock); return rc; @@ -696,7 +702,7 @@ static int uhci_rh_resume(struct usb_hcd *hcd) if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { dev_warn(&hcd->self.root_hub->dev, "HC isn't running!\n"); rc = -ESHUTDOWN; - } else if (!uhci->hc_inaccessible) + } else if (!uhci->dead) wakeup_rh(uhci); spin_unlock_irq(&uhci->lock); return rc; @@ -710,8 +716,8 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message) dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__); spin_lock_irq(&uhci->lock); - if (uhci->hc_inaccessible) /* Dead or already suspended */ - goto done; + if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead) + goto done_okay; /* Already suspended or dead */ if (uhci->rh_state > UHCI_RH_SUSPENDED) { dev_warn(uhci_dev(uhci), "Root hub isn't suspended!\n"); @@ -724,12 +730,12 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message) */ pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0); mb(); - clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - uhci->hc_inaccessible = 1; hcd->poll_rh = 0; /* FIXME: Enable non-PME# remote wakeup? */ +done_okay: + clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); done: spin_unlock_irq(&uhci->lock); return rc; @@ -742,25 +748,22 @@ static int uhci_resume(struct usb_hcd *hcd) dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__); /* Since we aren't in D3 any more, it's safe to set this flag - * even if the controller was dead. It might not even be dead - * any more, if the firmware or quirks code has reset it. + * even if the controller was dead. */ set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); mb(); - if (uhci->rh_state == UHCI_RH_RESET) /* Dead */ - return 0; - spin_lock_irq(&uhci->lock); /* FIXME: Disable non-PME# remote wakeup? */ - uhci->hc_inaccessible = 0; - - /* The BIOS may have changed the controller settings during a - * system wakeup. Check it and reconfigure to avoid problems. + /* The firmware or a boot kernel may have changed the controller + * settings during a system wakeup. Check it and reconfigure + * to avoid problems. */ check_and_reset_hc(uhci); + + /* If the controller was dead before, it's back alive now */ configure_hc(uhci); if (uhci->rh_state == UHCI_RH_RESET) { diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h index 469b4268b85..619d704f4e8 100644 --- a/drivers/usb/host/uhci-hcd.h +++ b/drivers/usb/host/uhci-hcd.h @@ -395,7 +395,7 @@ struct uhci_hcd { unsigned int scan_in_progress:1; /* Schedule scan is running */ unsigned int need_rescan:1; /* Redo the schedule scan */ - unsigned int hc_inaccessible:1; /* HC is suspended or dead */ + unsigned int dead:1; /* Controller has died */ unsigned int working_RD:1; /* Suspended root hub doesn't need to be polled */ unsigned int is_initialized:1; /* Data structure is usable */ diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c index f53c116e0df..c545ef92fe2 100644 --- a/drivers/usb/host/uhci-hub.c +++ b/drivers/usb/host/uhci-hub.c @@ -171,7 +171,7 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf) spin_lock_irqsave(&uhci->lock, flags); uhci_scan_schedule(uhci, NULL); - if (uhci->hc_inaccessible) + if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead) goto done; uhci_check_ports(uhci); @@ -227,7 +227,7 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wPortChange, wPortStatus; unsigned long flags; - if (uhci->hc_inaccessible) + if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead) return -ETIMEDOUT; spin_lock_irqsave(&uhci->lock, flags); -- cgit v1.2.3 From c5e3b741a3fec6077a480aa65ded29d79ded8898 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 5 Jun 2006 12:28:57 -0400 Subject: [PATCH] UHCI: Improve FSBR-off timing This patch (as707) improves the FSBR operation in uhci-hcd by turning it off more quickly when it isn't needed. FSBR puts a noticeable load on a computer's PCI bus, so it should be disabled as soon as possible when it isn't in use. The patch leaves it running for only 10 ms after the last URB stops using it, on the theory that this should be long enough for a driver to submit another URB if it wants keep FSBR going. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/uhci-hcd.c | 5 ++-- drivers/usb/host/uhci-hcd.h | 8 +++-- drivers/usb/host/uhci-q.c | 71 ++++++++++++++++++++++++++++++++------------- 3 files changed, 59 insertions(+), 25 deletions(-) diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 025b969f95e..7b48567622e 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -497,9 +497,9 @@ static int uhci_start(struct usb_hcd *hcd) hcd->uses_new_polling = 1; spin_lock_init(&uhci->lock); - + setup_timer(&uhci->fsbr_timer, uhci_fsbr_timeout, + (unsigned long) uhci); INIT_LIST_HEAD(&uhci->idle_qh_list); - init_waitqueue_head(&uhci->waitqh); if (DEBUG_CONFIGURED) { @@ -675,6 +675,7 @@ static void uhci_stop(struct usb_hcd *hcd) uhci_scan_schedule(uhci, NULL); spin_unlock_irq(&uhci->lock); + del_timer_sync(&uhci->fsbr_timer); release_uhci(uhci); } diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h index 619d704f4e8..108e3de2dc2 100644 --- a/drivers/usb/host/uhci-hcd.h +++ b/drivers/usb/host/uhci-hcd.h @@ -86,7 +86,7 @@ /* When no queues need Full-Speed Bandwidth Reclamation, * delay this long before turning FSBR off */ -#define FSBR_OFF_DELAY msecs_to_jiffies(400) +#define FSBR_OFF_DELAY msecs_to_jiffies(10) /* If a queue hasn't advanced after this much time, assume it is stuck */ #define QH_WAIT_TIMEOUT msecs_to_jiffies(200) @@ -382,8 +382,6 @@ struct uhci_hcd { __le32 *frame; void **frame_cpu; /* CPU's frame list */ - unsigned long fsbr_jiffies; /* Time when FSBR was last wanted */ - enum uhci_rh_state rh_state; unsigned long auto_stop_time; /* When to AUTO_STOP */ @@ -400,6 +398,10 @@ struct uhci_hcd { need to be polled */ unsigned int is_initialized:1; /* Data structure is usable */ unsigned int fsbr_is_on:1; /* FSBR is turned on */ + unsigned int fsbr_is_wanted:1; /* Does any URB want FSBR? */ + unsigned int fsbr_expiring:1; /* FSBR is timing out */ + + struct timer_list fsbr_timer; /* For turning off FBSR */ /* Support for port suspend/resume/reset */ unsigned long port_c_suspend; /* Bit-arrays of ports */ diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index b173d914d74..c9d72ac0a1d 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -64,16 +64,30 @@ static void uhci_add_fsbr(struct uhci_hcd *uhci, struct urb *urb) urbp->fsbr = 1; } -static void uhci_qh_wants_fsbr(struct uhci_hcd *uhci, struct uhci_qh *qh) +static void uhci_urbp_wants_fsbr(struct uhci_hcd *uhci, struct urb_priv *urbp) { - struct urb_priv *urbp = - list_entry(qh->queue.next, struct urb_priv, node); - if (urbp->fsbr) { - uhci->fsbr_jiffies = jiffies; + uhci->fsbr_is_wanted = 1; if (!uhci->fsbr_is_on) uhci_fsbr_on(uhci); + else if (uhci->fsbr_expiring) { + uhci->fsbr_expiring = 0; + del_timer(&uhci->fsbr_timer); + } + } +} + +static void uhci_fsbr_timeout(unsigned long _uhci) +{ + struct uhci_hcd *uhci = (struct uhci_hcd *) _uhci; + unsigned long flags; + + spin_lock_irqsave(&uhci->lock, flags); + if (uhci->fsbr_expiring) { + uhci->fsbr_expiring = 0; + uhci_fsbr_off(uhci); } + spin_unlock_irqrestore(&uhci->lock, flags); } @@ -287,7 +301,7 @@ static int uhci_cleanup_queue(struct uhci_hcd *uhci, struct uhci_qh *qh, if (qh->type == USB_ENDPOINT_XFER_ISOC) { ret = (uhci->frame_number + uhci->is_stopped != qh->unlink_frame); - return ret; + goto done; } /* If the URB isn't first on its queue, adjust the link pointer @@ -304,24 +318,26 @@ static int uhci_cleanup_queue(struct uhci_hcd *uhci, struct uhci_qh *qh, td = list_entry(urbp->td_list.prev, struct uhci_td, list); ptd->link = td->link; - return ret; + goto done; } /* If the QH element pointer is UHCI_PTR_TERM then then currently * executing URB has already been unlinked, so this one isn't it. */ if (qh_element(qh) == UHCI_PTR_TERM) - return ret; + goto done; qh->element = UHCI_PTR_TERM; /* Control pipes have to worry about toggles */ if (qh->type == USB_ENDPOINT_XFER_CONTROL) - return ret; + goto done; /* Save the next toggle value */ WARN_ON(list_empty(&urbp->td_list)); td = list_entry(urbp->td_list.next, struct uhci_td, list); qh->needs_fixup = 1; qh->initial_toggle = uhci_toggle(td_token(td)); + +done: return ret; } @@ -1175,7 +1191,7 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd, * queue isn't stopped. */ if (qh->queue.next == &urbp->node && !qh->is_stopped) { uhci_activate_qh(uhci, qh); - uhci_qh_wants_fsbr(uhci, qh); + uhci_urbp_wants_fsbr(uhci, urbp); } goto done; @@ -1404,7 +1420,7 @@ static int uhci_advance_check(struct uhci_hcd *uhci, struct uhci_qh *qh) unsigned status; if (qh->type == USB_ENDPOINT_XFER_ISOC) - return ret; + goto done; /* Treat an UNLINKING queue as though it hasn't advanced. * This is okay because reactivation will treat it as though @@ -1427,21 +1443,24 @@ static int uhci_advance_check(struct uhci_hcd *uhci, struct uhci_qh *qh) /* We're okay, the queue has advanced */ qh->wait_expired = 0; qh->advance_jiffies = jiffies; - return ret; + goto done; } ret = 0; } /* The queue hasn't advanced; check for timeout */ - if (!qh->wait_expired && time_after(jiffies, - qh->advance_jiffies + QH_WAIT_TIMEOUT)) { + if (qh->wait_expired) + goto done; + + if (time_after(jiffies, qh->advance_jiffies + QH_WAIT_TIMEOUT)) { /* Detect the Intel bug and work around it */ if (qh->post_td && qh_element(qh) == cpu_to_le32(qh->post_td->dma_handle)) { qh->element = qh->post_td->link; qh->advance_jiffies = jiffies; - return 1; + ret = 1; + goto done; } qh->wait_expired = 1; @@ -1452,7 +1471,14 @@ static int uhci_advance_check(struct uhci_hcd *uhci, struct uhci_qh *qh) * starts moving again. */ if (urbp && urbp->fsbr && !(status & TD_CTRL_IOC)) uhci_unlink_qh(uhci, qh); + + } else { + /* Unmoving but not-yet-expired queues keep FSBR alive */ + if (urbp) + uhci_urbp_wants_fsbr(uhci, urbp); } + +done: return ret; } @@ -1472,6 +1498,7 @@ static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs) uhci->scan_in_progress = 1; rescan: uhci->need_rescan = 0; + uhci->fsbr_is_wanted = 0; uhci_clear_next_interrupt(uhci); uhci_get_current_frame_number(uhci); @@ -1487,8 +1514,10 @@ rescan: if (uhci_advance_check(uhci, qh)) { uhci_scan_qh(uhci, qh, regs); - if (qh->state == QH_STATE_ACTIVE) - uhci_qh_wants_fsbr(uhci, qh); + if (qh->state == QH_STATE_ACTIVE) { + uhci_urbp_wants_fsbr(uhci, + list_entry(qh->queue.next, struct urb_priv, node)); + } } } } @@ -1498,9 +1527,11 @@ rescan: goto rescan; uhci->scan_in_progress = 0; - if (uhci->fsbr_is_on && time_after(jiffies, - uhci->fsbr_jiffies + FSBR_OFF_DELAY)) - uhci_fsbr_off(uhci); + if (uhci->fsbr_is_on && !uhci->fsbr_is_wanted && + !uhci->fsbr_expiring) { + uhci->fsbr_expiring = 1; + mod_timer(&uhci->fsbr_timer, jiffies + FSBR_OFF_DELAY); + } if (list_empty(&uhci->skel_unlink_qh->node)) uhci_clear_next_interrupt(uhci); -- cgit v1.2.3 From 34ab86e140e9810d6c5162971b6dcf01fcc0f11c Mon Sep 17 00:00:00 2001 From: Timothy Sipples Date: Fri, 16 Jun 2006 20:42:59 +0900 Subject: [PATCH] airprime.c: add Kyocera Wireless KPC650/Passport support Adds vendor & product IDs to drivers/usb/serial/airprime.c for Kyocera Wireless KPC650/Passport EV-DO/1xRTT PC Cards. Signed-off-by: Timothy Sipples Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/airprime.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c index 8ef488849f7..94b9ba0ff87 100644 --- a/drivers/usb/serial/airprime.c +++ b/drivers/usb/serial/airprime.c @@ -16,6 +16,7 @@ #include "usb-serial.h" static struct usb_device_id id_table [] = { + { USB_DEVICE(0x0c88, 0x17da) }, /* Kyocera Wireless KPC650/Passport */ { USB_DEVICE(0xf3d, 0x0112) }, /* AirPrime CDMA Wireless PC Card */ { USB_DEVICE(0x1410, 0x1110) }, /* Novatel Wireless Merlin CDMA */ { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless Aircard 580 */ -- cgit v1.2.3 From 4bc203d997c0dc1eada4cc9681372c2f7a456c46 Mon Sep 17 00:00:00 2001 From: Pete Zaitcev Date: Tue, 6 Jun 2006 18:18:33 -0700 Subject: [PATCH] USB: io_edgeport touch-up Al Borchers suggested to do this in his review of my previous patch. I guess that I skipped this initially because of my visceral dislike of sizeof(data). But in this case it seems well localized. Signed-off-by: Pete Zaitcev Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/io_edgeport.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index ed976ab5668..b85d2156dfd 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -2607,15 +2607,15 @@ static void get_manufacturing_desc (struct edgeport_serial *edge_serial) dbg(" BoardRev: %d", edge_serial->manuf_descriptor.BoardRev); dbg(" NumPorts: %d", edge_serial->manuf_descriptor.NumPorts); dbg(" DescDate: %d/%d/%d", edge_serial->manuf_descriptor.DescDate[0], edge_serial->manuf_descriptor.DescDate[1], edge_serial->manuf_descriptor.DescDate[2]+1900); - unicode_to_ascii(string, 30, + unicode_to_ascii(string, sizeof(string), edge_serial->manuf_descriptor.SerialNumber, edge_serial->manuf_descriptor.SerNumLength/2); dbg(" SerialNumber: %s", string); - unicode_to_ascii(string, 30, + unicode_to_ascii(string, sizeof(string), edge_serial->manuf_descriptor.AssemblyNumber, edge_serial->manuf_descriptor.AssemblyNumLength/2); dbg(" AssemblyNumber: %s", string); - unicode_to_ascii(string, 30, + unicode_to_ascii(string, sizeof(string), edge_serial->manuf_descriptor.OemAssyNumber, edge_serial->manuf_descriptor.OemAssyNumLength/2); dbg(" OemAssyNumber: %s", string); -- cgit v1.2.3 From 5b1c674d223eef6c6494be8be91e9e3a3054817e Mon Sep 17 00:00:00 2001 From: Pete Zaitcev Date: Fri, 9 Jun 2006 20:10:10 -0700 Subject: [PATCH] USB: update usbmon, fix glued lines This update contains one bug fix: some lines can come out truncated, because of the safety cutoff. This happened because I forgot to update the size when status packets began to be printed. The rest is: - Comments updates - Allow snooping with pkmap on x86_64, which is cache-coherent - Enlarge event buffers (certainly we can have a couple of pages) - Add event counter First touch upon usbmon for 2.6.18. Signed-off-by: Pete Zaitcev Signed-off-by: Greg Kroah-Hartman --- drivers/usb/mon/mon_dma.c | 5 ++++- drivers/usb/mon/mon_main.c | 3 ++- drivers/usb/mon/mon_stat.c | 4 ++-- drivers/usb/mon/mon_text.c | 9 ++++++--- drivers/usb/mon/usb_mon.h | 1 + 5 files changed, 15 insertions(+), 7 deletions(-) diff --git a/drivers/usb/mon/mon_dma.c b/drivers/usb/mon/mon_dma.c index 0a1367b760a..ddcfc01e77a 100644 --- a/drivers/usb/mon/mon_dma.c +++ b/drivers/usb/mon/mon_dma.c @@ -13,7 +13,10 @@ #include /* Only needed for declarations in usb_mon.h */ #include "usb_mon.h" -#ifdef __i386__ /* CONFIG_ARCH_I386 does not exit */ +/* + * PC-compatibles, are, fortunately, sufficiently cache-coherent for this. + */ +#if defined(__i386__) || defined(__x86_64__) /* CONFIG_ARCH_I386 doesn't exit */ #define MON_HAS_UNMAP 1 #define phys_to_page(phys) pfn_to_page((phys) >> PAGE_SHIFT) diff --git a/drivers/usb/mon/mon_main.c b/drivers/usb/mon/mon_main.c index 6ecc2730221..86db92b4915 100644 --- a/drivers/usb/mon/mon_main.c +++ b/drivers/usb/mon/mon_main.c @@ -97,6 +97,7 @@ static void mon_submit(struct usb_bus *ubus, struct urb *urb) if (mbus->nreaders == 0) goto out_locked; + mbus->cnt_events++; list_for_each (pos, &mbus->r_list) { r = list_entry(pos, struct mon_reader, r_link); r->rnf_submit(r->r_data, urb); @@ -152,6 +153,7 @@ static void mon_complete(struct usb_bus *ubus, struct urb *urb) } spin_lock_irqsave(&mbus->lock, flags); + mbus->cnt_events++; list_for_each (pos, &mbus->r_list) { r = list_entry(pos, struct mon_reader, r_link); r->rnf_complete(r->r_data, urb); @@ -163,7 +165,6 @@ static void mon_complete(struct usb_bus *ubus, struct urb *urb) /* * Stop monitoring. - * Obviously this must be well locked, so no need to play with mb's. */ static void mon_stop(struct mon_bus *mbus) { diff --git a/drivers/usb/mon/mon_stat.c b/drivers/usb/mon/mon_stat.c index 6e4b165d070..1fe01d994a7 100644 --- a/drivers/usb/mon/mon_stat.c +++ b/drivers/usb/mon/mon_stat.c @@ -31,8 +31,8 @@ static int mon_stat_open(struct inode *inode, struct file *file) mbus = inode->u.generic_ip; sp->slen = snprintf(sp->str, STAT_BUF_SIZE, - "nreaders %d text_lost %u\n", - mbus->nreaders, mbus->cnt_text_lost); + "nreaders %d events %u text_lost %u\n", + mbus->nreaders, mbus->cnt_events, mbus->cnt_text_lost); file->private_data = sp; return 0; diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c index ac043ec2b8d..9f9236bf62d 100644 --- a/drivers/usb/mon/mon_text.c +++ b/drivers/usb/mon/mon_text.c @@ -26,10 +26,13 @@ /* * This limit exists to prevent OOMs when the user process stops reading. + * If usbmon were available to unprivileged processes, it might be open + * to a local DoS. But we have to keep to root in order to prevent + * password sniffing from HID devices. */ -#define EVENT_MAX 25 +#define EVENT_MAX (2*PAGE_SIZE / sizeof(struct mon_event_text)) -#define PRINTF_DFL 130 +#define PRINTF_DFL 160 struct mon_event_text { struct list_head e_link; @@ -111,7 +114,7 @@ static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb, * number of corner cases, but it seems that the following is * more or less safe. * - * We do not even try to look transfer_buffer, because it can + * We do not even try to look at transfer_buffer, because it can * contain non-NULL garbage in case the upper level promised to * set DMA for the HCD. */ diff --git a/drivers/usb/mon/usb_mon.h b/drivers/usb/mon/usb_mon.h index 8e0613c350c..92702835b1e 100644 --- a/drivers/usb/mon/usb_mon.h +++ b/drivers/usb/mon/usb_mon.h @@ -27,6 +27,7 @@ struct mon_bus { struct kref ref; /* Under mon_lock */ /* Stats */ + unsigned int cnt_events; unsigned int cnt_text_lost; }; -- cgit v1.2.3 From 12e72feab5d9a23107f245b0f241a2484cbb5a4e Mon Sep 17 00:00:00 2001 From: Pete Zaitcev Date: Fri, 9 Jun 2006 22:03:32 -0700 Subject: [PATCH] USB: implement error event in usbmon Implement the "error" event in usbmon. Signed-off-by: Pete Zaitcev Signed-off-by: Greg Kroah-Hartman --- drivers/usb/mon/mon_main.c | 20 ++++++++++++++++---- drivers/usb/mon/mon_text.c | 27 +++++++++++++++++++++++++++ drivers/usb/mon/usb_mon.h | 1 + 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/drivers/usb/mon/mon_main.c b/drivers/usb/mon/mon_main.c index 86db92b4915..275a66f8305 100644 --- a/drivers/usb/mon/mon_main.c +++ b/drivers/usb/mon/mon_main.c @@ -114,20 +114,32 @@ out_unlocked: /* */ -static void mon_submit_error(struct usb_bus *ubus, struct urb *urb, int err) +static void mon_submit_error(struct usb_bus *ubus, struct urb *urb, int error) { struct mon_bus *mbus; + unsigned long flags; + struct list_head *pos; + struct mon_reader *r; mbus = ubus->mon_bus; if (mbus == NULL) goto out_unlocked; - /* - * XXX Capture the error code and the 'E' event. - */ + spin_lock_irqsave(&mbus->lock, flags); + if (mbus->nreaders == 0) + goto out_locked; + mbus->cnt_events++; + list_for_each (pos, &mbus->r_list) { + r = list_entry(pos, struct mon_reader, r_link); + r->rnf_error(r->r_data, urb, error); + } + + spin_unlock_irqrestore(&mbus->lock, flags); return; +out_locked: + spin_unlock_irqrestore(&mbus->lock, flags); out_unlocked: return; } diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c index 9f9236bf62d..e02c1a30c4c 100644 --- a/drivers/usb/mon/mon_text.c +++ b/drivers/usb/mon/mon_text.c @@ -182,6 +182,32 @@ static void mon_text_complete(void *data, struct urb *urb) mon_text_event(rp, urb, 'C'); } +static void mon_text_error(void *data, struct urb *urb, int error) +{ + struct mon_reader_text *rp = data; + struct mon_event_text *ep; + + if (rp->nevents >= EVENT_MAX || + (ep = kmem_cache_alloc(rp->e_slab, SLAB_ATOMIC)) == NULL) { + rp->r.m_bus->cnt_text_lost++; + return; + } + + ep->type = 'E'; + ep->pipe = urb->pipe; + ep->id = (unsigned long) urb; + ep->tstamp = 0; + ep->length = 0; + ep->status = error; + + ep->setup_flag = '-'; + ep->data_flag = 'E'; + + rp->nevents++; + list_add_tail(&ep->e_link, &rp->e_list); + wake_up(&rp->wait); +} + /* * Fetch next event from the circular buffer. */ @@ -235,6 +261,7 @@ static int mon_text_open(struct inode *inode, struct file *file) rp->r.m_bus = mbus; rp->r.r_data = rp; rp->r.rnf_submit = mon_text_submit; + rp->r.rnf_error = mon_text_error; rp->r.rnf_complete = mon_text_complete; snprintf(rp->slab_name, SLAB_NAME_SZ, "mon%dt_%lx", ubus->busnum, diff --git a/drivers/usb/mon/usb_mon.h b/drivers/usb/mon/usb_mon.h index 92702835b1e..33678c24ebe 100644 --- a/drivers/usb/mon/usb_mon.h +++ b/drivers/usb/mon/usb_mon.h @@ -40,6 +40,7 @@ struct mon_reader { void *r_data; /* Use container_of instead? */ void (*rnf_submit)(void *data, struct urb *urb); + void (*rnf_error)(void *data, struct urb *urb, int error); void (*rnf_complete)(void *data, struct urb *urb); }; -- cgit v1.2.3 From d9ac2cfc3aaf3bc37da4192d3edfa11d2ad2e96f Mon Sep 17 00:00:00 2001 From: Pete Zaitcev Date: Mon, 12 Jun 2006 20:09:39 -0700 Subject: [PATCH] USB: update usbmon.txt Fix up the documentation. Apparently, I left unedited copy-paste results in examples. Also, Alan helped me to improve the most confusing parts. Signed-off-by: Pete Zaitcev Signed-off-by: Greg Kroah-Hartman --- Documentation/usb/usbmon.txt | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/Documentation/usb/usbmon.txt b/Documentation/usb/usbmon.txt index 63cb7edd177..e65ec828d7a 100644 --- a/Documentation/usb/usbmon.txt +++ b/Documentation/usb/usbmon.txt @@ -29,14 +29,13 @@ if usbmon is built into the kernel. # mount -t debugfs none_debugs /sys/kernel/debug # modprobe usbmon +# Verify that bus sockets are present. -[root@lembas zaitcev]# ls /sys/kernel/debug/usbmon +# ls /sys/kernel/debug/usbmon 1s 1t 2s 2t 3s 3t 4s 4t -[root@lembas zaitcev]# - -# ls /sys/kernel +# 2. Find which bus connects to the desired device @@ -76,7 +75,7 @@ that the file size is not excessive for your favourite editor. * Raw text data format -The '0t' type data consists of a stream of events, such as URB submission, +The '1t' type data consists of a stream of events, such as URB submission, URB callback, submission error. Every event is a text line, which consists of whitespace separated words. The number of position of words may depend on the event type, but there is a set of words, common for all types. @@ -97,20 +96,25 @@ Here is the list of words, from left to right: Zi Zo Isochronous input and output Ii Io Interrupt input and output Bi Bo Bulk input and output - Device address and Endpoint number are decimal numbers with leading zeroes - or 3 and 2 positions, correspondingly. -- URB Status. This field makes no sense for submissions, but is present - to help scripts with parsing. In error case, it contains the error code. - In case of a setup packet, it contains a Setup Tag. If scripts read a number - in this field, they proceed to read Data Length. Otherwise, they read - the setup packet before reading the Data Length. + Device address and Endpoint number are 3-digit and 2-digit (respectively) + decimal numbers, with leading zeroes. +- URB Status. In most cases, this field contains a number, sometimes negative, + which represents a "status" field of the URB. This field makes no sense for + submissions, but is present anyway to help scripts with parsing. When an + error occurs, the field contains the error code. In case of a submission of + a Control packet, this field contains a Setup Tag instead of an error code. + It is easy to tell whether the Setup Tag is present because it is never a + number. Thus if scripts find a number in this field, they proceed to read + Data Length. If they find something else, like a letter, they read the setup + packet before reading the Data Length. - Setup packet, if present, consists of 5 words: one of each for bmRequestType, bRequest, wValue, wIndex, wLength, as specified by the USB Specification 2.0. These words are safe to decode if Setup Tag was 's'. Otherwise, the setup packet was present, but not captured, and the fields contain filler. -- Data Length. This is the actual length in the URB. +- Data Length. For submissions, this is the requested length. For callbacks, + this is the actual length. - Data tag. The usbmon may not always capture data, even if length is nonzero. - Only if tag is '=', the data words are present. + The data words are present only if this tag is '='. - Data words follow, in big endian hexadecimal format. Notice that they are not machine words, but really just a byte stream split into words to make it easier to read. Thus, the last word may contain from one to four bytes. -- cgit v1.2.3 From 4255e6f6d98ad092c27fa2b83ac314cbe8a0c56f Mon Sep 17 00:00:00 2001 From: Oliver Bock Date: Sat, 10 Jun 2006 00:42:19 +0200 Subject: [PATCH] USB: new driver for Cypress CY7C63xxx mirco controllers This is a new driver for the Cypress CY7C63xxx mirco controller series. It currently supports the pre-programmed CYC63001A-PC by AK Modul-Bus GmbH. It's based on a kernel 2.4 driver (cyport) by Marcus Maul which I ported to kernel 2.6 using sysfs. I intend to support more controllers of this family (and more features) as soon as I get hold of the required IDs etc. Please see the source code's header for more information. Signed-off-by: Oliver Bock Signed-off-by: Greg Kroah-Hartman --- drivers/usb/Makefile | 1 + drivers/usb/misc/Kconfig | 14 +++ drivers/usb/misc/Makefile | 1 + drivers/usb/misc/cy7c63.c | 244 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 260 insertions(+) create mode 100644 drivers/usb/misc/cy7c63.c diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index b2999656190..c7123bf71c5 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -48,6 +48,7 @@ obj-$(CONFIG_USB_MICROTEK) += image/ obj-$(CONFIG_USB_SERIAL) += serial/ obj-$(CONFIG_USB_AUERSWALD) += misc/ +obj-$(CONFIG_USB_CY7C63) += misc/ obj-$(CONFIG_USB_CYTHERM) += misc/ obj-$(CONFIG_USB_EMI26) += misc/ obj-$(CONFIG_USB_EMI62) += misc/ diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index af79d0447bb..daa486dde8c 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig @@ -88,6 +88,20 @@ config USB_LED To compile this driver as a module, choose M here: the module will be called usbled. +config USB_CY7C63 + tristate "Cypress CY7C63xxx USB driver support" + depends on USB + help + Say Y here if you want to connect a Cypress CY7C63xxx + micro controller to your computer's USB port. This driver + supports the pre-programmed devices (incl. firmware) by + AK Modul-Bus Computer GmbH. + + Please see: http://www.ak-modul-bus.de/stat/mikrocontroller.html + + To compile this driver as a module, choose M here: the + module will be called cy7c63. + config USB_CYTHERM tristate "Cypress USB thermometer driver support" depends on USB diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile index 946537d31d9..f25a9722729 100644 --- a/drivers/usb/misc/Makefile +++ b/drivers/usb/misc/Makefile @@ -4,6 +4,7 @@ # obj-$(CONFIG_USB_AUERSWALD) += auerswald.o +obj-$(CONFIG_USB_CY7C63) += cy7c63.o obj-$(CONFIG_USB_CYTHERM) += cytherm.o obj-$(CONFIG_USB_EMI26) += emi26.o obj-$(CONFIG_USB_EMI62) += emi62.o diff --git a/drivers/usb/misc/cy7c63.c b/drivers/usb/misc/cy7c63.c new file mode 100644 index 00000000000..8a1c10b89b7 --- /dev/null +++ b/drivers/usb/misc/cy7c63.c @@ -0,0 +1,244 @@ +/* +* cy7c63.c +* +* Copyright (c) 2006 Oliver Bock (bock@fh-wolfenbuettel.de) +* +* This driver is based on the Cypress Thermometer USB Driver by +* Marcus Maul and the 2.0 version of Greg Kroah-Hartman's +* USB Skeleton driver. +* +* Is is a generic driver for the Cypress CY7C63000 family. +* For the time being it enables you to toggle the single I/O ports +* of the device. +* +* Supported vendors: AK Modul-Bus Computer GmbH +* Supported devices: CY7C63001A-PC (to be continued...) +* Supported functions: Read/Write Ports (to be continued...) +* +* Chipsets families: CY7C63000, CY7C63001, CY7C63100, CY7C63101 +* +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation, version 2. +*/ + +#include +#include +#include +#include + +#define DRIVER_AUTHOR "Oliver Bock (bock@fh-wolfenbuettel.de)" +#define DRIVER_DESC "Cypress CY7C63xxx USB driver" + +#define CY7C63_VENDOR_ID 0xa2c +#define CY7C63_PRODUCT_ID 0x8 + +#define CY7C63_READ_PORT 0x4 +#define CY7C63_WRITE_PORT 0x5 +#define CY7C63_READ_RAM 0x2 +#define CY7C63_WRITE_RAM 0x3 +#define CY7C63_READ_ROM 0x1 + +#define CY7C63_READ_PORT_ID0 0 +#define CY7C63_WRITE_PORT_ID0 0 +#define CY7C63_READ_PORT_ID1 0x2 +#define CY7C63_WRITE_PORT_ID1 1 + +#define CY7C63_MAX_REQSIZE 8 + + +/* table of devices that work with this driver */ +static struct usb_device_id cy7c63_table [] = { + { USB_DEVICE(CY7C63_VENDOR_ID, CY7C63_PRODUCT_ID) }, + { } +}; +MODULE_DEVICE_TABLE(usb, cy7c63_table); + +/* structure to hold all of our device specific stuff */ +struct cy7c63 { + struct usb_device * udev; + char port0; + char port1; +}; + +/* used to send usb control messages to device */ +int vendor_command(struct cy7c63 *dev, unsigned char request, + unsigned char address, unsigned char data) { + + int retval = 0; + unsigned int pipe; + unsigned char *iobuf; + + /* allocate some memory for the i/o buffer*/ + iobuf = kzalloc(CY7C63_MAX_REQSIZE, GFP_KERNEL); + if (!iobuf) { + dev_err(&dev->udev->dev, "Out of memory!\n"); + retval = -ENOMEM; + goto error; + } + + dev_dbg(&dev->udev->dev, "Sending usb_control_msg (data: %d)\n", data); + + /* prepare usb control message and send it upstream */ + pipe = usb_rcvctrlpipe(dev->udev, 0); + retval = usb_control_msg(dev->udev, pipe, request, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER, + address, data, iobuf, CY7C63_MAX_REQSIZE, + USB_CTRL_GET_TIMEOUT); + + /* store returned data (more READs to be added!) */ + switch (request) { + case CY7C63_READ_PORT: + if (address == CY7C63_READ_PORT_ID0) { + dev->port0 = iobuf[1]; + dev_dbg(&dev->udev->dev, + "READ_PORT0 returned: %d\n",dev->port0); + } + else if (address == CY7C63_READ_PORT_ID1) { + dev->port1 = iobuf[1]; + dev_dbg(&dev->udev->dev, + "READ_PORT1 returned: %d\n",dev->port1); + } + break; + } + + kfree(iobuf); +error: + return retval; +} + +#define get_set_port(num,read_id,write_id) \ +static ssize_t set_port##num(struct device *dev, struct device_attribute *attr, \ + const char *buf, size_t count) { \ + \ + int value; \ + int result = 0; \ + \ + struct usb_interface *intf = to_usb_interface(dev); \ + struct cy7c63 *cyp = usb_get_intfdata(intf); \ + \ + dev_dbg(&cyp->udev->dev, "WRITE_PORT%d called\n", num); \ + \ + /* validate input data */ \ + if (sscanf(buf, "%d", &value) < 1) { \ + result = -EINVAL; \ + goto error; \ + } \ + if (value>255 || value<0) { \ + result = -EINVAL; \ + goto error; \ + } \ + \ + result = vendor_command(cyp, CY7C63_WRITE_PORT, write_id, \ + (unsigned char)value); \ + \ + dev_dbg(&cyp->udev->dev, "Result of vendor_command: %d\n\n",result); \ +error: \ + return result < 0 ? result : count; \ +} \ + \ +static ssize_t get_port##num(struct device *dev, \ + struct device_attribute *attr, char *buf) { \ + \ + int result = 0; \ + \ + struct usb_interface *intf = to_usb_interface(dev); \ + struct cy7c63 *cyp = usb_get_intfdata(intf); \ + \ + dev_dbg(&cyp->udev->dev, "READ_PORT%d called\n", num); \ + \ + result = vendor_command(cyp, CY7C63_READ_PORT, read_id, 0); \ + \ + dev_dbg(&cyp->udev->dev, "Result of vendor_command: %d\n\n", result); \ + \ + return sprintf(buf, "%d", cyp->port##num); \ +} \ +static DEVICE_ATTR(port##num, S_IWUGO | S_IRUGO, get_port##num, set_port##num); + +get_set_port(0, CY7C63_READ_PORT_ID0, CY7C63_WRITE_PORT_ID0); +get_set_port(1, CY7C63_READ_PORT_ID1, CY7C63_WRITE_PORT_ID1); + +static int cy7c63_probe(struct usb_interface *interface, + const struct usb_device_id *id) { + + struct cy7c63 *dev = NULL; + int retval = -ENOMEM; + + /* allocate memory for our device state and initialize it */ + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (dev == NULL) { + dev_err(&dev->udev->dev, "Out of memory!\n"); + goto error; + } + + dev->udev = usb_get_dev(interface_to_usbdev(interface)); + + /* save our data pointer in this interface device */ + usb_set_intfdata(interface, dev); + + /* create device attribute files */ + device_create_file(&interface->dev, &dev_attr_port0); + device_create_file(&interface->dev, &dev_attr_port1); + + /* let the user know what node this device is now attached to */ + dev_info(&interface->dev, + "Cypress CY7C63xxx device now attached\n"); + + retval = 0; +error: + return retval; +} + +static void cy7c63_disconnect(struct usb_interface *interface) { + + struct cy7c63 *dev; + + dev = usb_get_intfdata(interface); + usb_set_intfdata(interface, NULL); + + /* remove device attribute files */ + device_remove_file(&interface->dev, &dev_attr_port0); + device_remove_file(&interface->dev, &dev_attr_port1); + + usb_put_dev(dev->udev); + + dev_info(&interface->dev, + "Cypress CY7C63xxx device now disconnected\n"); + + kfree(dev); +} + +static struct usb_driver cy7c63_driver = { + .name = "cy7c63", + .probe = cy7c63_probe, + .disconnect = cy7c63_disconnect, + .id_table = cy7c63_table, +}; + +static int __init cy7c63_init(void) { + + int result; + + /* register this driver with the USB subsystem */ + result = usb_register(&cy7c63_driver); + if (result) { + err("Function usb_register failed! Error number: %d\n", result); + } + + return result; +} + +static void __exit cy7c63_exit(void) { + + /* deregister this driver with the USB subsystem */ + usb_deregister(&cy7c63_driver); +} + +module_init(cy7c63_init); +module_exit(cy7c63_exit); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); + +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 4186c29ca199063facdda49851b4c863699687b1 Mon Sep 17 00:00:00 2001 From: Matt Reimer Date: Wed, 7 Jun 2006 11:46:13 -0700 Subject: [PATCH] USB: trivial DEBUG message correction in gadget ether driver Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/ether.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 9c4422ac9de..bd60c816e90 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -1010,7 +1010,7 @@ set_ether_config (struct eth_dev *dev, gfp_t gfp_flags) result = usb_ep_enable (dev->out_ep, dev->out); if (result != 0) { DEBUG (dev, "enable %s --> %d\n", - dev->in_ep->name, result); + dev->out_ep->name, result); goto done; } } -- cgit v1.2.3 From b059c81af7a1759a911cfc20ce8a4bf47c435830 Mon Sep 17 00:00:00 2001 From: Frank Gevaerts Date: Wed, 14 Jun 2006 15:52:05 +0200 Subject: [PATCH] USB Serial: clean tty fields on failed device open If either the driver's open() method or try_module_get() fails, we need to set 'tty->driver_data' and 'port->tty' to NULL in serial_open(), otherwise we'll get an OOPS in usb_device_disconnect() when the device is disconnected. Signed-off-by: Frank Gevaerts Acked-by: Luiz Fernando N. Capitulino Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb-serial.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index cbca3402d6c..92c213fa931 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -237,6 +237,8 @@ bailout_module_put: module_put(serial->type->driver.owner); bailout_mutex_unlock: port->open_count = 0; + tty->driver_data = NULL; + port->tty = NULL; mutex_unlock(&port->mutex); bailout_kref_put: usb_serial_put(serial); -- cgit v1.2.3 From 943e1b4d60dc7acfabe2ebad31189bcb3b853688 Mon Sep 17 00:00:00 2001 From: Franck Bui-Huu Date: Wed, 14 Jun 2006 10:29:21 +0200 Subject: [PATCH] USB: gadget-serial: fix a deadlock when closing the serial device When closing the device, the driver acquires/release twice the port lock before/after waiting for the data to be completely sent. Therefore it will dead lock. This patch fixes it and also uses the generic scheduler services for waiting for an event. Signed-off-by: Franck Bui-Huu Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/serial.c | 95 ++++++++------------------------------------- 1 file changed, 17 insertions(+), 78 deletions(-) diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index b992546c394..b58f015554b 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -51,82 +51,10 @@ #include "gadget_chips.h" -/* Wait Cond */ - -#define __wait_cond_interruptible(wq, condition, lock, flags, ret) \ -do { \ - wait_queue_t __wait; \ - init_waitqueue_entry(&__wait, current); \ - \ - add_wait_queue(&wq, &__wait); \ - for (;;) { \ - set_current_state(TASK_INTERRUPTIBLE); \ - if (condition) \ - break; \ - if (!signal_pending(current)) { \ - spin_unlock_irqrestore(lock, flags); \ - schedule(); \ - spin_lock_irqsave(lock, flags); \ - continue; \ - } \ - ret = -ERESTARTSYS; \ - break; \ - } \ - current->state = TASK_RUNNING; \ - remove_wait_queue(&wq, &__wait); \ -} while (0) - -#define wait_cond_interruptible(wq, condition, lock, flags) \ -({ \ - int __ret = 0; \ - if (!(condition)) \ - __wait_cond_interruptible(wq, condition, lock, flags, \ - __ret); \ - __ret; \ -}) - -#define __wait_cond_interruptible_timeout(wq, condition, lock, flags, \ - timeout, ret) \ -do { \ - signed long __timeout = timeout; \ - wait_queue_t __wait; \ - init_waitqueue_entry(&__wait, current); \ - \ - add_wait_queue(&wq, &__wait); \ - for (;;) { \ - set_current_state(TASK_INTERRUPTIBLE); \ - if (__timeout == 0) \ - break; \ - if (condition) \ - break; \ - if (!signal_pending(current)) { \ - spin_unlock_irqrestore(lock, flags); \ - __timeout = schedule_timeout(__timeout); \ - spin_lock_irqsave(lock, flags); \ - continue; \ - } \ - ret = -ERESTARTSYS; \ - break; \ - } \ - current->state = TASK_RUNNING; \ - remove_wait_queue(&wq, &__wait); \ -} while (0) - -#define wait_cond_interruptible_timeout(wq, condition, lock, flags, \ - timeout) \ -({ \ - int __ret = 0; \ - if (!(condition)) \ - __wait_cond_interruptible_timeout(wq, condition, lock, \ - flags, timeout, __ret); \ - __ret; \ -}) - - /* Defines */ -#define GS_VERSION_STR "v2.0" -#define GS_VERSION_NUM 0x0200 +#define GS_VERSION_STR "v2.1" +#define GS_VERSION_NUM 0x0201 #define GS_LONG_NAME "Gadget Serial" #define GS_SHORT_NAME "g_serial" @@ -843,6 +771,18 @@ exit_unlock_dev: /* * gs_close */ + +#define GS_WRITE_FINISHED_EVENT_SAFELY(p) \ +({ \ + unsigned long flags; \ + int cond; \ + \ + spin_lock_irqsave(&(p)->port_lock, flags); \ + cond = !(p)->port_dev || !gs_buf_data_avail((p)->port_write_buf); \ + spin_unlock_irqrestore(&(p)->port_lock, flags); \ + cond; \ +}) + static void gs_close(struct tty_struct *tty, struct file *file) { unsigned long flags; @@ -888,10 +828,9 @@ static void gs_close(struct tty_struct *tty, struct file *file) /* at most GS_CLOSE_TIMEOUT seconds */ if (gs_buf_data_avail(port->port_write_buf) > 0) { spin_unlock_irqrestore(&port->port_lock, flags); - wait_cond_interruptible_timeout(port->port_write_wait, - port->port_dev == NULL - || gs_buf_data_avail(port->port_write_buf) == 0, - &port->port_lock, flags, GS_CLOSE_TIMEOUT * HZ); + wait_event_interruptible_timeout(port->port_write_wait, + GS_WRITE_FINISHED_EVENT_SAFELY(port), + GS_CLOSE_TIMEOUT * HZ); spin_lock_irqsave(&port->port_lock, flags); } -- cgit v1.2.3 From ca094f1186ef50ef8983325072cdc4f051830f13 Mon Sep 17 00:00:00 2001 From: Franck Bui-Huu Date: Wed, 14 Jun 2006 10:47:18 +0200 Subject: [PATCH] USB: gadget-serial: do not save/restore IRQ flags in gs_close() As pointed out by David Brownell, we know that IRQs are never blocked when calling gs_close function. So the save/restore IRQ flags are pointless. Signed-off-by: Franck Bui-Huu Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/serial.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index b58f015554b..e477edd681d 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -53,8 +53,8 @@ /* Defines */ -#define GS_VERSION_STR "v2.1" -#define GS_VERSION_NUM 0x0201 +#define GS_VERSION_STR "v2.2" +#define GS_VERSION_NUM 0x0202 #define GS_LONG_NAME "Gadget Serial" #define GS_SHORT_NAME "g_serial" @@ -774,18 +774,16 @@ exit_unlock_dev: #define GS_WRITE_FINISHED_EVENT_SAFELY(p) \ ({ \ - unsigned long flags; \ int cond; \ \ - spin_lock_irqsave(&(p)->port_lock, flags); \ + spin_lock_irq(&(p)->port_lock); \ cond = !(p)->port_dev || !gs_buf_data_avail((p)->port_write_buf); \ - spin_unlock_irqrestore(&(p)->port_lock, flags); \ + spin_unlock_irq(&(p)->port_lock); \ cond; \ }) static void gs_close(struct tty_struct *tty, struct file *file) { - unsigned long flags; struct gs_port *port = tty->driver_data; struct semaphore *sem; @@ -799,7 +797,7 @@ static void gs_close(struct tty_struct *tty, struct file *file) sem = &gs_open_close_sem[port->port_num]; down(sem); - spin_lock_irqsave(&port->port_lock, flags); + spin_lock_irq(&port->port_lock); if (port->port_open_count == 0) { printk(KERN_ERR @@ -827,11 +825,11 @@ static void gs_close(struct tty_struct *tty, struct file *file) /* wait for write buffer to drain, or */ /* at most GS_CLOSE_TIMEOUT seconds */ if (gs_buf_data_avail(port->port_write_buf) > 0) { - spin_unlock_irqrestore(&port->port_lock, flags); + spin_unlock_irq(&port->port_lock); wait_event_interruptible_timeout(port->port_write_wait, GS_WRITE_FINISHED_EVENT_SAFELY(port), GS_CLOSE_TIMEOUT * HZ); - spin_lock_irqsave(&port->port_lock, flags); + spin_lock_irq(&port->port_lock); } /* free disconnected port on final close */ @@ -851,7 +849,7 @@ static void gs_close(struct tty_struct *tty, struct file *file) port->port_num, tty, file); exit: - spin_unlock_irqrestore(&port->port_lock, flags); + spin_unlock_irq(&port->port_lock); up(sem); } -- cgit v1.2.3 From 7c0642c196beb41b7770571b8a61151bdd418bbe Mon Sep 17 00:00:00 2001 From: Milan Svoboda Date: Mon, 29 May 2006 03:34:00 -0700 Subject: [PATCH] usb gadget: allow drivers support speeds higher than full speed This patch removes limitation which prevents use of drivers that support speeds different that full speed. Signed-off-by: Milan Svoboda Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/pxa2xx_udc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c index 680f7fc5b17..0a609e3dfba 100644 --- a/drivers/usb/gadget/pxa2xx_udc.c +++ b/drivers/usb/gadget/pxa2xx_udc.c @@ -1585,7 +1585,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) int retval; if (!driver - || driver->speed != USB_SPEED_FULL + || driver->speed < USB_SPEED_FULL || !driver->bind || !driver->unbind || !driver->disconnect -- cgit v1.2.3 From 44df45a09c7c20bbd641b1c30b6406d54ba7e2c8 Mon Sep 17 00:00:00 2001 From: Milan Svoboda Date: Mon, 29 May 2006 03:34:00 -0700 Subject: [PATCH] usb gadget: fix compile errors This patch fixes compile errors when pxa2xx_udc is to be compiled for ixp4xx platform. Signed-off-by: Milan Svoboda Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/pxa2xx_udc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c index 0a609e3dfba..af63d8236f4 100644 --- a/drivers/usb/gadget/pxa2xx_udc.c +++ b/drivers/usb/gadget/pxa2xx_udc.c @@ -53,7 +53,9 @@ #include #include #include +#ifdef CONFIG_ARCH_PXA #include +#endif #include #include @@ -2575,10 +2577,12 @@ static int __exit pxa2xx_udc_remove(struct platform_device *pdev) free_irq(IRQ_USB, dev); dev->got_irq = 0; } +#ifdef CONFIG_ARCH_LUBBOCK if (machine_is_lubbock()) { free_irq(LUBBOCK_USB_DISC_IRQ, dev); free_irq(LUBBOCK_USB_IRQ, dev); } +#endif platform_set_drvdata(pdev, NULL); the_controller = NULL; return 0; -- cgit v1.2.3 From 043ea18b2e145c4c9cb3c30757a65fe0f1678a35 Mon Sep 17 00:00:00 2001 From: Milan Svoboda Date: Mon, 29 May 2006 03:34:00 -0700 Subject: [PATCH] usb gadget: update pxa2xx_udc.c driver to fully support IXP4xx platform This patch adds IXP465 into the list of known devices and adds IXP425 and IXP465 to the list of devices that have cfr. This is not described in the hardware documentation, but without it driver won't work. Workaround (#if 1) that seemed to get rid of lost status irqs is disabled for IXP4XX as it caused freezes during testing of control messages. No lost irqs are visible on IXP4XX. Driver survived tests running over night without any visible problems. Signed-off-by: Milan Svoboda Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/pxa2xx_udc.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c index af63d8236f4..269ce7f4ad6 100644 --- a/drivers/usb/gadget/pxa2xx_udc.c +++ b/drivers/usb/gadget/pxa2xx_udc.c @@ -60,7 +60,7 @@ #include #include -#include +#include /* @@ -547,6 +547,7 @@ write_ep0_fifo (struct pxa2xx_ep *ep, struct pxa2xx_request *req) count = req->req.length; done (ep, req, 0); ep0_idle(ep->dev); +#ifndef CONFIG_ARCH_IXP4XX #if 1 /* This seems to get rid of lost status irqs in some cases: * host responds quickly, or next request involves config @@ -566,6 +567,7 @@ write_ep0_fifo (struct pxa2xx_ep *ep, struct pxa2xx_request *req) udelay(1); } while (count); } +#endif #endif } else if (ep->dev->req_pending) ep0start(ep->dev, 0, "IN"); @@ -2429,6 +2431,7 @@ static struct pxa2xx_udc memory = { #define PXA210_B1 0x00000123 #define PXA210_B0 0x00000122 #define IXP425_A0 0x000001c1 +#define IXP465_AD 0x00000200 /* * probe - binds to the platform device @@ -2465,6 +2468,8 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev) break; #elif defined(CONFIG_ARCH_IXP4XX) case IXP425_A0: + case IXP465_AD: + dev->has_cfr = 1; out_dma = 0; break; #endif -- cgit v1.2.3 From db54a53d26322e978e66482208afabaab9cd0752 Mon Sep 17 00:00:00 2001 From: "Luiz Fernando N. Capitulino" Date: Mon, 12 Jun 2006 22:46:20 -0300 Subject: [PATCH] usbserial: Fixes wrong return values. Some usbserial functions returns -EINVAL if the port doesn't exist or if it's not opened. However, the right error code for such situations is -ENODEV. Signed-off-by: Luiz Fernando N. Capitulino Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb-serial.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 92c213fa931..a30135c7cfe 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -305,7 +305,7 @@ exit: static int serial_write_room (struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; - int retval = -EINVAL; + int retval = -ENODEV; if (!port) goto exit; @@ -327,7 +327,7 @@ exit: static int serial_chars_in_buffer (struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; - int retval = -EINVAL; + int retval = -ENODEV; if (!port) goto exit; @@ -497,19 +497,18 @@ static int serial_tiocmget (struct tty_struct *tty, struct file *file) struct usb_serial_port *port = tty->driver_data; if (!port) - goto exit; + return -ENODEV; dbg("%s - port %d", __FUNCTION__, port->number); if (!port->open_count) { dbg("%s - port not open", __FUNCTION__); - goto exit; + return -ENODEV; } if (port->serial->type->tiocmget) return port->serial->type->tiocmget(port, file); -exit: return -EINVAL; } @@ -519,19 +518,18 @@ static int serial_tiocmset (struct tty_struct *tty, struct file *file, struct usb_serial_port *port = tty->driver_data; if (!port) - goto exit; + return -ENODEV; dbg("%s - port %d", __FUNCTION__, port->number); if (!port->open_count) { dbg("%s - port not open", __FUNCTION__); - goto exit; + return -ENODEV; } if (port->serial->type->tiocmset) return port->serial->type->tiocmset(port, file, set, clear); -exit: return -EINVAL; } -- cgit v1.2.3 From d5681fe8110e1169902df37a8fd8bd01c2b7810e Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 13 Jun 2006 09:59:32 -0400 Subject: [PATCH] USB: unusual_devs entry for Nokia N80 Here is a patch (as720) adding an unusual_devs entry for the Nokia N80 mobile phone. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 3ec17689b81..543244d421c 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -133,6 +133,14 @@ UNUSUAL_DEV( 0x0420, 0x0001, 0x0100, 0x0100, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), +/* Reported by Jiri Slaby and + * Rene C. Castberg */ +UNUSUAL_DEV( 0x0421, 0x0446, 0x0100, 0x0100, + "Nokia", + "N80", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ), + /* Reported by Olaf Hering from novell bug #105878 */ UNUSUAL_DEV( 0x0424, 0x0fdc, 0x0210, 0x0210, "SMSC", -- cgit v1.2.3 From 7e27f18c8a37ffb95f677e4e9c3cca818a3e9eb1 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Tue, 13 Jun 2006 09:54:40 -0700 Subject: [PATCH] USB: whitespace removal from usb/gadget/ether This removes extraneous whitespace from the Ethernet/RNDIS gadget driver. It's all space-at-EOL, spaces-before-tabs, or tabs-then-spaces. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/ether.c | 86 +++++----- drivers/usb/gadget/rndis.c | 389 +++++++++++++++++++++++---------------------- drivers/usb/gadget/rndis.h | 26 +-- 3 files changed, 251 insertions(+), 250 deletions(-) diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index bd60c816e90..fc4684096fc 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -101,9 +101,9 @@ static const char driver_desc [] = DRIVER_DESC; /* CDC and RNDIS support the same host-chosen outgoing packet filters. */ #define DEFAULT_FILTER (USB_CDC_PACKET_TYPE_BROADCAST \ - |USB_CDC_PACKET_TYPE_ALL_MULTICAST \ - |USB_CDC_PACKET_TYPE_PROMISCUOUS \ - |USB_CDC_PACKET_TYPE_DIRECTED) + |USB_CDC_PACKET_TYPE_ALL_MULTICAST \ + |USB_CDC_PACKET_TYPE_PROMISCUOUS \ + |USB_CDC_PACKET_TYPE_DIRECTED) /*-------------------------------------------------------------------------*/ @@ -318,7 +318,7 @@ static inline int rndis_active(struct eth_dev *dev) #define DEFAULT_QLEN 2 /* double buffering by default */ /* peak bulk transfer bits-per-second */ -#define HS_BPS (13 * 512 * 8 * 1000 * 8) +#define HS_BPS (13 * 512 * 8 * 1000 * 8) #define FS_BPS (19 * 64 * 1 * 1000 * 8) #ifdef CONFIG_USB_GADGET_DUALSPEED @@ -466,7 +466,7 @@ eth_config = { }; #ifdef CONFIG_USB_ETH_RNDIS -static struct usb_config_descriptor +static struct usb_config_descriptor rndis_config = { .bLength = sizeof rndis_config, .bDescriptorType = USB_DT_CONFIG, @@ -511,7 +511,7 @@ static const struct usb_interface_descriptor rndis_control_intf = { .bLength = sizeof rndis_control_intf, .bDescriptorType = USB_DT_INTERFACE, - + .bInterfaceNumber = 0, .bNumEndpoints = 1, .bInterfaceClass = USB_CLASS_COMM, @@ -545,20 +545,20 @@ static const struct usb_cdc_union_desc union_desc = { #ifdef CONFIG_USB_ETH_RNDIS static const struct usb_cdc_call_mgmt_descriptor call_mgmt_descriptor = { - .bLength = sizeof call_mgmt_descriptor, - .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = USB_CDC_CALL_MANAGEMENT_TYPE, + .bLength = sizeof call_mgmt_descriptor, + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = USB_CDC_CALL_MANAGEMENT_TYPE, - .bmCapabilities = 0x00, - .bDataInterface = 0x01, + .bmCapabilities = 0x00, + .bDataInterface = 0x01, }; static const struct usb_cdc_acm_descriptor acm_descriptor = { - .bLength = sizeof acm_descriptor, - .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = USB_CDC_ACM_TYPE, + .bLength = sizeof acm_descriptor, + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = USB_CDC_ACM_TYPE, - .bmCapabilities = 0x00, + .bmCapabilities = 0x00, }; #endif @@ -595,7 +595,7 @@ static const struct usb_cdc_ether_desc ether_desc = { * RNDIS requires the status endpoint, since it uses that encapsulation * mechanism for its funky RPC scheme. */ - + #define LOG2_STATUS_INTERVAL_MSEC 5 /* 1 << 5 == 32 msec */ #define STATUS_BYTECOUNT 16 /* 8 byte header + data */ @@ -978,7 +978,7 @@ set_ether_config (struct eth_dev *dev, gfp_t gfp_flags) result = usb_ep_enable (dev->status_ep, dev->status); if (result != 0) { - DEBUG (dev, "enable %s --> %d\n", + DEBUG (dev, "enable %s --> %d\n", dev->status_ep->name, result); goto done; } @@ -1002,14 +1002,14 @@ set_ether_config (struct eth_dev *dev, gfp_t gfp_flags) if (!cdc_active(dev)) { result = usb_ep_enable (dev->in_ep, dev->in); if (result != 0) { - DEBUG(dev, "enable %s --> %d\n", + DEBUG(dev, "enable %s --> %d\n", dev->in_ep->name, result); goto done; } result = usb_ep_enable (dev->out_ep, dev->out); if (result != 0) { - DEBUG (dev, "enable %s --> %d\n", + DEBUG (dev, "enable %s --> %d\n", dev->out_ep->name, result); goto done; } @@ -1144,7 +1144,7 @@ eth_set_config (struct eth_dev *dev, unsigned number, gfp_t gfp_flags) #ifdef CONFIG_USB_GADGET_DUALSPEED case USB_SPEED_HIGH: speed = "high"; break; #endif - default: speed = "?"; break; + default: speed = "?"; break; } dev->config = number; @@ -1206,7 +1206,7 @@ static void issue_start_status (struct eth_dev *dev) struct usb_request *req = dev->stat_req; struct usb_cdc_notification *event; int value; - + DEBUG (dev, "%s, flush old status first\n", __FUNCTION__); /* flush old status @@ -1268,7 +1268,7 @@ static void rndis_command_complete (struct usb_ep *ep, struct usb_request *req) { struct eth_dev *dev = ep->driver_data; int status; - + /* received RNDIS command from USB_CDC_SEND_ENCAPSULATED_COMMAND */ spin_lock(&dev->lock); status = rndis_msg_parser (dev->rndis_config, (u8 *) req->buf); @@ -1472,7 +1472,7 @@ done_set_intf: #endif /* DEV_CONFIG_CDC */ -#ifdef CONFIG_USB_ETH_RNDIS +#ifdef CONFIG_USB_ETH_RNDIS /* RNDIS uses the CDC command encapsulation mechanism to implement * an RPC scheme, with much getting/setting of attributes by OID. */ @@ -1489,7 +1489,7 @@ done_set_intf: req->complete = rndis_command_complete; /* later, rndis_control_ack () sends a notification */ break; - + case USB_CDC_GET_ENCAPSULATED_RESPONSE: if ((USB_DIR_IN|USB_TYPE_CLASS|USB_RECIP_INTERFACE) == ctrl->bRequestType @@ -1641,7 +1641,7 @@ rx_submit (struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags) DEBUG (dev, "no rx skb\n"); goto enomem; } - + /* Some platforms perform better when IP packets are aligned, * but on at least one, checksumming fails otherwise. Note: * RNDIS headers involve variable numbers of LE32 values. @@ -1720,7 +1720,7 @@ quiesce: case -EOVERFLOW: dev->stats.rx_over_errors++; // FALLTHROUGH - + default: dev->stats.rx_errors++; DEBUG (dev, "rx status %d\n", status); @@ -1915,7 +1915,7 @@ static int eth_start_xmit (struct sk_buff *skb, struct net_device *net) sizeof (struct rndis_packet_msg_type)); if (!skb_rndis) goto drop; - + dev_kfree_skb_any (skb); skb = skb_rndis; rndis_add_hdr (skb); @@ -2001,7 +2001,7 @@ static int rndis_control_ack (struct net_device *net) struct eth_dev *dev = netdev_priv(net); u32 length; struct usb_request *resp = dev->stat_req; - + /* in case RNDIS calls this after disconnect */ if (!dev->status) { DEBUG (dev, "status ENODEV\n"); @@ -2021,16 +2021,16 @@ static int rndis_control_ack (struct net_device *net) resp->length = 8; resp->complete = rndis_control_ack_complete; resp->context = dev; - + *((__le32 *) resp->buf) = __constant_cpu_to_le32 (1); *((__le32 *) resp->buf + 1) = __constant_cpu_to_le32 (0); - + length = usb_ep_queue (dev->status_ep, resp, GFP_ATOMIC); if (length < 0) { resp->status = 0; rndis_control_ack_complete (dev->status_ep, resp); } - + return 0; } @@ -2047,7 +2047,7 @@ static void eth_start (struct eth_dev *dev, gfp_t gfp_flags) /* fill the rx queue */ rx_fill (dev, gfp_flags); - /* and open the tx floodgates */ + /* and open the tx floodgates */ atomic_set (&dev->tx_qlen, 0); netif_wake_queue (dev->net); if (rndis_active(dev)) { @@ -2076,7 +2076,7 @@ static int eth_stop (struct net_device *net) netif_stop_queue (net); DEBUG (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld\n", - dev->stats.rx_packets, dev->stats.tx_packets, + dev->stats.rx_packets, dev->stats.tx_packets, dev->stats.rx_errors, dev->stats.tx_errors ); @@ -2095,7 +2095,7 @@ static int eth_stop (struct net_device *net) usb_ep_enable (dev->status_ep, dev->status); } } - + if (rndis_active(dev)) { rndis_set_param_medium (dev->rndis_config, NDIS_MEDIUM_802_3, 0); @@ -2301,7 +2301,7 @@ autoconf_fail: return -ENODEV; } in_ep->driver_data = in_ep; /* claim */ - + out_ep = usb_ep_autoconfig (gadget, &fs_sink_desc); if (!out_ep) goto autoconf_fail; @@ -2374,8 +2374,8 @@ autoconf_fail: #endif } - net = alloc_etherdev (sizeof *dev); - if (!net) + net = alloc_etherdev (sizeof *dev); + if (!net) return status; dev = netdev_priv(net); spin_lock_init (&dev->lock); @@ -2454,7 +2454,7 @@ autoconf_fail: dev->gadget = gadget; set_gadget_data (gadget, dev); gadget->ep0->driver_data = dev; - + /* two kinds of host-initiated state changes: * - iff DATA transfer is active, carrier is "on" * - tx queueing enabled if open *and* carrier is "on" @@ -2462,8 +2462,8 @@ autoconf_fail: netif_stop_queue (dev->net); netif_carrier_off (dev->net); - SET_NETDEV_DEV (dev->net, &gadget->dev); - status = register_netdev (dev->net); + SET_NETDEV_DEV (dev->net, &gadget->dev); + status = register_netdev (dev->net); if (status < 0) goto fail1; @@ -2488,7 +2488,7 @@ autoconf_fail: u32 vendorID = 0; /* FIXME RNDIS vendor id == "vendor NIC code" == ? */ - + dev->rndis_config = rndis_register (rndis_control_ack); if (dev->rndis_config < 0) { fail0: @@ -2496,7 +2496,7 @@ fail0: status = -ENODEV; goto fail; } - + /* these set up a lot of the OIDs that RNDIS needs */ rndis_set_host_mac (dev->rndis_config, dev->host_mac); if (rndis_set_param_dev (dev->rndis_config, dev->net, @@ -2556,7 +2556,7 @@ static struct usb_gadget_driver eth_driver = { .suspend = eth_suspend, .resume = eth_resume, - .driver = { + .driver = { .name = (char *) shortname, .owner = THIS_MODULE, }, diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c index 6d6eaad7396..3ff6db7828a 100644 --- a/drivers/usb/gadget/rndis.c +++ b/drivers/usb/gadget/rndis.c @@ -1,23 +1,23 @@ -/* +/* * RNDIS MSG parser - * + * * Version: $Id: rndis.c,v 1.19 2004/03/25 21:33:46 robert Exp $ - * + * * Authors: Benedikt Spranger, Pengutronix - * Robert Schwebel, Pengutronix - * + * Robert Schwebel, Pengutronix + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License - * version 2, as published by the Free Software Foundation. - * + * version 2, as published by the Free Software Foundation. + * * This software was originally developed in conformance with * Microsoft's Remote NDIS Specification License Agreement. - * + * * 03/12/2004 Kai-Uwe Bloem * Fixed message length bug in init_response - * + * * 03/25/2004 Kai-Uwe Bloem - * Fixed rndis_rm_hdr length bug. + * Fixed rndis_rm_hdr length bug. * * Copyright (C) 2004 by David Brownell * updates to merge with Linux 2.6, better match RNDIS spec @@ -82,7 +82,7 @@ static rndis_resp_t *rndis_add_response (int configNr, u32 length); /* supported OIDs */ -static const u32 oid_supported_list [] = +static const u32 oid_supported_list [] = { /* the general stuff */ OID_GEN_SUPPORTED_LIST, @@ -103,7 +103,7 @@ static const u32 oid_supported_list [] = #if 0 OID_GEN_RNDIS_CONFIG_PARAMETER, #endif - + /* the statistical stuff */ OID_GEN_XMIT_OK, OID_GEN_RCV_OK, @@ -127,14 +127,14 @@ static const u32 oid_supported_list [] = OID_GEN_TRANSMIT_QUEUE_LENGTH, #endif /* RNDIS_OPTIONAL_STATS */ - /* mandatory 802.3 */ + /* mandatory 802.3 */ /* the general stuff */ OID_802_3_PERMANENT_ADDRESS, OID_802_3_CURRENT_ADDRESS, OID_802_3_MULTICAST_LIST, OID_802_3_MAC_OPTIONS, OID_802_3_MAXIMUM_LIST_SIZE, - + /* the statistical stuff */ OID_802_3_RCV_ERROR_ALIGNMENT, OID_802_3_XMIT_ONE_COLLISION, @@ -172,8 +172,8 @@ static int gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, rndis_resp_t *r) { - int retval = -ENOTSUPP; - u32 length = 4; /* usually */ + int retval = -ENOTSUPP; + u32 length = 4; /* usually */ __le32 *outbuf; int i, count; rndis_query_cmplt_type *resp; @@ -211,27 +211,27 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, outbuf[i] = cpu_to_le32 (oid_supported_list[i]); retval = 0; break; - + /* mandatory */ case OID_GEN_HARDWARE_STATUS: DEBUG("%s: OID_GEN_HARDWARE_STATUS\n", __FUNCTION__); - /* Bogus question! + /* Bogus question! * Hardware must be ready to receive high level protocols. - * BTW: + * BTW: * reddite ergo quae sunt Caesaris Caesari * et quae sunt Dei Deo! */ *outbuf = __constant_cpu_to_le32 (0); retval = 0; break; - + /* mandatory */ case OID_GEN_MEDIA_SUPPORTED: DEBUG("%s: OID_GEN_MEDIA_SUPPORTED\n", __FUNCTION__); *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium); retval = 0; break; - + /* mandatory */ case OID_GEN_MEDIA_IN_USE: DEBUG("%s: OID_GEN_MEDIA_IN_USE\n", __FUNCTION__); @@ -239,7 +239,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium); retval = 0; break; - + /* mandatory */ case OID_GEN_MAXIMUM_FRAME_SIZE: DEBUG("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __FUNCTION__); @@ -249,7 +249,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, retval = 0; } break; - + /* mandatory */ case OID_GEN_LINK_SPEED: if (rndis_debug > 1) @@ -272,7 +272,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, retval = 0; } break; - + /* mandatory */ case OID_GEN_RECEIVE_BLOCK_SIZE: DEBUG("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __FUNCTION__); @@ -282,7 +282,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, retval = 0; } break; - + /* mandatory */ case OID_GEN_VENDOR_ID: DEBUG("%s: OID_GEN_VENDOR_ID\n", __FUNCTION__); @@ -290,7 +290,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, rndis_per_dev_params [configNr].vendorID); retval = 0; break; - + /* mandatory */ case OID_GEN_VENDOR_DESCRIPTION: DEBUG("%s: OID_GEN_VENDOR_DESCRIPTION\n", __FUNCTION__); @@ -356,7 +356,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, DEBUG("%s: OID_GEN_XMIT_OK\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { *outbuf = cpu_to_le32 ( - rndis_per_dev_params [configNr].stats->tx_packets - + rndis_per_dev_params [configNr].stats->tx_packets - rndis_per_dev_params [configNr].stats->tx_errors - rndis_per_dev_params [configNr].stats->tx_dropped); retval = 0; @@ -369,13 +369,13 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, DEBUG("%s: OID_GEN_RCV_OK\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { *outbuf = cpu_to_le32 ( - rndis_per_dev_params [configNr].stats->rx_packets - + rndis_per_dev_params [configNr].stats->rx_packets - rndis_per_dev_params [configNr].stats->rx_errors - rndis_per_dev_params [configNr].stats->rx_dropped); retval = 0; } break; - + /* mandatory */ case OID_GEN_XMIT_ERROR: if (rndis_debug > 1) @@ -386,7 +386,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, retval = 0; } break; - + /* mandatory */ case OID_GEN_RCV_ERROR: if (rndis_debug > 1) @@ -397,7 +397,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, retval = 0; } break; - + /* mandatory */ case OID_GEN_RCV_NO_BUFFER: DEBUG("%s: OID_GEN_RCV_NO_BUFFER\n", __FUNCTION__); @@ -411,7 +411,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, #ifdef RNDIS_OPTIONAL_STATS case OID_GEN_DIRECTED_BYTES_XMIT: DEBUG("%s: OID_GEN_DIRECTED_BYTES_XMIT\n", __FUNCTION__); - /* + /* * Aunt Tilly's size of shoes * minus antarctica count of penguins * divided by weight of Alpha Centauri @@ -419,7 +419,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, if (rndis_per_dev_params [configNr].stats) { *outbuf = cpu_to_le32 ( (rndis_per_dev_params [configNr] - .stats->tx_packets - + .stats->tx_packets - rndis_per_dev_params [configNr] .stats->tx_errors - rndis_per_dev_params [configNr] @@ -428,14 +428,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, retval = 0; } break; - + case OID_GEN_DIRECTED_FRAMES_XMIT: DEBUG("%s: OID_GEN_DIRECTED_FRAMES_XMIT\n", __FUNCTION__); /* dito */ if (rndis_per_dev_params [configNr].stats) { *outbuf = cpu_to_le32 ( (rndis_per_dev_params [configNr] - .stats->tx_packets - + .stats->tx_packets - rndis_per_dev_params [configNr] .stats->tx_errors - rndis_per_dev_params [configNr] @@ -444,7 +444,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, retval = 0; } break; - + case OID_GEN_MULTICAST_BYTES_XMIT: DEBUG("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { @@ -453,7 +453,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, retval = 0; } break; - + case OID_GEN_MULTICAST_FRAMES_XMIT: DEBUG("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { @@ -462,7 +462,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, retval = 0; } break; - + case OID_GEN_BROADCAST_BYTES_XMIT: DEBUG("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { @@ -471,7 +471,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, retval = 0; } break; - + case OID_GEN_BROADCAST_FRAMES_XMIT: DEBUG("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { @@ -480,19 +480,19 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, retval = 0; } break; - + case OID_GEN_DIRECTED_BYTES_RCV: DEBUG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __FUNCTION__); *outbuf = __constant_cpu_to_le32 (0); retval = 0; break; - + case OID_GEN_DIRECTED_FRAMES_RCV: DEBUG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __FUNCTION__); *outbuf = __constant_cpu_to_le32 (0); retval = 0; break; - + case OID_GEN_MULTICAST_BYTES_RCV: DEBUG("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { @@ -501,7 +501,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, retval = 0; } break; - + case OID_GEN_MULTICAST_FRAMES_RCV: DEBUG("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { @@ -510,7 +510,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, retval = 0; } break; - + case OID_GEN_BROADCAST_BYTES_RCV: DEBUG("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { @@ -519,7 +519,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, retval = 0; } break; - + case OID_GEN_BROADCAST_FRAMES_RCV: DEBUG("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { @@ -528,7 +528,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, retval = 0; } break; - + case OID_GEN_RCV_CRC_ERROR: DEBUG("%s: OID_GEN_RCV_CRC_ERROR\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { @@ -537,7 +537,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, retval = 0; } break; - + case OID_GEN_TRANSMIT_QUEUE_LENGTH: DEBUG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __FUNCTION__); *outbuf = __constant_cpu_to_le32 (0); @@ -558,7 +558,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, retval = 0; } break; - + /* mandatory */ case OID_802_3_CURRENT_ADDRESS: DEBUG("%s: OID_802_3_CURRENT_ADDRESS\n", __FUNCTION__); @@ -570,7 +570,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, retval = 0; } break; - + /* mandatory */ case OID_802_3_MULTICAST_LIST: DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__); @@ -578,7 +578,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, *outbuf = __constant_cpu_to_le32 (0xE0000000); retval = 0; break; - + /* mandatory */ case OID_802_3_MAXIMUM_LIST_SIZE: DEBUG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __FUNCTION__); @@ -586,7 +586,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, *outbuf = __constant_cpu_to_le32 (1); retval = 0; break; - + case OID_802_3_MAC_OPTIONS: DEBUG("%s: OID_802_3_MAC_OPTIONS\n", __FUNCTION__); break; @@ -602,56 +602,56 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, retval = 0; } break; - + /* mandatory */ case OID_802_3_XMIT_ONE_COLLISION: DEBUG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __FUNCTION__); *outbuf = __constant_cpu_to_le32 (0); retval = 0; break; - + /* mandatory */ case OID_802_3_XMIT_MORE_COLLISIONS: DEBUG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __FUNCTION__); *outbuf = __constant_cpu_to_le32 (0); retval = 0; break; - + #ifdef RNDIS_OPTIONAL_STATS case OID_802_3_XMIT_DEFERRED: DEBUG("%s: OID_802_3_XMIT_DEFERRED\n", __FUNCTION__); /* TODO */ break; - + case OID_802_3_XMIT_MAX_COLLISIONS: DEBUG("%s: OID_802_3_XMIT_MAX_COLLISIONS\n", __FUNCTION__); /* TODO */ break; - + case OID_802_3_RCV_OVERRUN: DEBUG("%s: OID_802_3_RCV_OVERRUN\n", __FUNCTION__); /* TODO */ break; - + case OID_802_3_XMIT_UNDERRUN: DEBUG("%s: OID_802_3_XMIT_UNDERRUN\n", __FUNCTION__); /* TODO */ break; - + case OID_802_3_XMIT_HEARTBEAT_FAILURE: DEBUG("%s: OID_802_3_XMIT_HEARTBEAT_FAILURE\n", __FUNCTION__); /* TODO */ break; - + case OID_802_3_XMIT_TIMES_CRS_LOST: DEBUG("%s: OID_802_3_XMIT_TIMES_CRS_LOST\n", __FUNCTION__); /* TODO */ break; - + case OID_802_3_XMIT_LATE_COLLISIONS: DEBUG("%s: OID_802_3_XMIT_LATE_COLLISIONS\n", __FUNCTION__); /* TODO */ - break; + break; #endif /* RNDIS_OPTIONAL_STATS */ #ifdef RNDIS_PM @@ -676,23 +676,23 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, #endif default: - printk (KERN_WARNING "%s: query unknown OID 0x%08X\n", + printk (KERN_WARNING "%s: query unknown OID 0x%08X\n", __FUNCTION__, OID); } if (retval < 0) length = 0; - + resp->InformationBufferLength = cpu_to_le32 (length); r->length = length + sizeof *resp; resp->MessageLength = cpu_to_le32 (r->length); return retval; } -static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len, - rndis_resp_t *r) +static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len, + rndis_resp_t *r) { rndis_set_cmplt_type *resp; - int i, retval = -ENOTSUPP; + int i, retval = -ENOTSUPP; struct rndis_params *params; if (!r) @@ -745,9 +745,9 @@ update_linkstate: netif_stop_queue (params->dev); } break; - + case OID_802_3_MULTICAST_LIST: - /* I think we can ignore this */ + /* I think we can ignore this */ DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__); retval = 0; break; @@ -796,29 +796,29 @@ update_linkstate: #endif /* RNDIS_PM */ default: - printk (KERN_WARNING "%s: set unknown OID 0x%08X, size %d\n", + printk (KERN_WARNING "%s: set unknown OID 0x%08X, size %d\n", __FUNCTION__, OID, buf_len); } - + return retval; } -/* - * Response Functions +/* + * Response Functions */ static int rndis_init_response (int configNr, rndis_init_msg_type *buf) { - rndis_init_cmplt_type *resp; + rndis_init_cmplt_type *resp; rndis_resp_t *r; - + if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP; - + r = rndis_add_response (configNr, sizeof (rndis_init_cmplt_type)); if (!r) return -ENOMEM; resp = (rndis_init_cmplt_type *) r->buf; - + resp->MessageType = __constant_cpu_to_le32 ( REMOTE_NDIS_INITIALIZE_CMPLT); resp->MessageLength = __constant_cpu_to_le32 (52); @@ -837,11 +837,11 @@ static int rndis_init_response (int configNr, rndis_init_msg_type *buf) resp->PacketAlignmentFactor = __constant_cpu_to_le32 (0); resp->AFListOffset = __constant_cpu_to_le32 (0); resp->AFListSize = __constant_cpu_to_le32 (0); - + if (rndis_per_dev_params [configNr].ack) - rndis_per_dev_params [configNr].ack ( - rndis_per_dev_params [configNr].dev); - + rndis_per_dev_params [configNr].ack ( + rndis_per_dev_params [configNr].dev); + return 0; } @@ -849,10 +849,10 @@ static int rndis_query_response (int configNr, rndis_query_msg_type *buf) { rndis_query_cmplt_type *resp; rndis_resp_t *r; - + // DEBUG("%s: OID = %08X\n", __FUNCTION__, cpu_to_le32(buf->OID)); if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP; - + /* * we need more memory: * gen_ndis_query_resp expects enough space for @@ -864,10 +864,10 @@ static int rndis_query_response (int configNr, rndis_query_msg_type *buf) if (!r) return -ENOMEM; resp = (rndis_query_cmplt_type *) r->buf; - + resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_QUERY_CMPLT); resp->RequestID = buf->RequestID; /* Still LE in msg buffer */ - + if (gen_ndis_query_resp (configNr, le32_to_cpu (buf->OID), le32_to_cpu(buf->InformationBufferOffset) + 8 + (u8 *) buf, @@ -881,10 +881,10 @@ static int rndis_query_response (int configNr, rndis_query_msg_type *buf) resp->InformationBufferOffset = __constant_cpu_to_le32 (0); } else resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS); - + if (rndis_per_dev_params [configNr].ack) - rndis_per_dev_params [configNr].ack ( - rndis_per_dev_params [configNr].dev); + rndis_per_dev_params [configNr].ack ( + rndis_per_dev_params [configNr].dev); return 0; } @@ -893,7 +893,7 @@ static int rndis_set_response (int configNr, rndis_set_msg_type *buf) u32 BufLength, BufOffset; rndis_set_cmplt_type *resp; rndis_resp_t *r; - + r = rndis_add_response (configNr, sizeof (rndis_set_cmplt_type)); if (!r) return -ENOMEM; @@ -906,26 +906,27 @@ static int rndis_set_response (int configNr, rndis_set_msg_type *buf) DEBUG("%s: Length: %d\n", __FUNCTION__, BufLength); DEBUG("%s: Offset: %d\n", __FUNCTION__, BufOffset); DEBUG("%s: InfoBuffer: ", __FUNCTION__); - + for (i = 0; i < BufLength; i++) { DEBUG ("%02x ", *(((u8 *) buf) + i + 8 + BufOffset)); } - + DEBUG ("\n"); #endif - + resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_SET_CMPLT); resp->MessageLength = __constant_cpu_to_le32 (16); resp->RequestID = buf->RequestID; /* Still LE in msg buffer */ - if (gen_ndis_set_resp (configNr, le32_to_cpu (buf->OID), - ((u8 *) buf) + 8 + BufOffset, BufLength, r)) - resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_NOT_SUPPORTED); - else resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS); - + if (gen_ndis_set_resp (configNr, le32_to_cpu (buf->OID), + ((u8 *) buf) + 8 + BufOffset, BufLength, r)) + resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_NOT_SUPPORTED); + else + resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS); + if (rndis_per_dev_params [configNr].ack) - rndis_per_dev_params [configNr].ack ( - rndis_per_dev_params [configNr].dev); - + rndis_per_dev_params [configNr].ack ( + rndis_per_dev_params [configNr].dev); + return 0; } @@ -933,27 +934,27 @@ static int rndis_reset_response (int configNr, rndis_reset_msg_type *buf) { rndis_reset_cmplt_type *resp; rndis_resp_t *r; - + r = rndis_add_response (configNr, sizeof (rndis_reset_cmplt_type)); if (!r) return -ENOMEM; resp = (rndis_reset_cmplt_type *) r->buf; - + resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_RESET_CMPLT); resp->MessageLength = __constant_cpu_to_le32 (16); resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS); /* resent information */ resp->AddressingReset = __constant_cpu_to_le32 (1); - + if (rndis_per_dev_params [configNr].ack) - rndis_per_dev_params [configNr].ack ( - rndis_per_dev_params [configNr].dev); + rndis_per_dev_params [configNr].ack ( + rndis_per_dev_params [configNr].dev); return 0; } static int rndis_keepalive_response (int configNr, - rndis_keepalive_msg_type *buf) + rndis_keepalive_msg_type *buf) { rndis_keepalive_cmplt_type *resp; rndis_resp_t *r; @@ -964,48 +965,48 @@ static int rndis_keepalive_response (int configNr, if (!r) return -ENOMEM; resp = (rndis_keepalive_cmplt_type *) r->buf; - + resp->MessageType = __constant_cpu_to_le32 ( REMOTE_NDIS_KEEPALIVE_CMPLT); resp->MessageLength = __constant_cpu_to_le32 (16); resp->RequestID = buf->RequestID; /* Still LE in msg buffer */ resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS); - + if (rndis_per_dev_params [configNr].ack) - rndis_per_dev_params [configNr].ack ( - rndis_per_dev_params [configNr].dev); - + rndis_per_dev_params [configNr].ack ( + rndis_per_dev_params [configNr].dev); + return 0; } -/* - * Device to Host Comunication +/* + * Device to Host Comunication */ static int rndis_indicate_status_msg (int configNr, u32 status) { - rndis_indicate_status_msg_type *resp; + rndis_indicate_status_msg_type *resp; rndis_resp_t *r; - + if (rndis_per_dev_params [configNr].state == RNDIS_UNINITIALIZED) - return -ENOTSUPP; - - r = rndis_add_response (configNr, + return -ENOTSUPP; + + r = rndis_add_response (configNr, sizeof (rndis_indicate_status_msg_type)); if (!r) return -ENOMEM; resp = (rndis_indicate_status_msg_type *) r->buf; - + resp->MessageType = __constant_cpu_to_le32 ( REMOTE_NDIS_INDICATE_STATUS_MSG); resp->MessageLength = __constant_cpu_to_le32 (20); resp->Status = cpu_to_le32 (status); resp->StatusBufferLength = __constant_cpu_to_le32 (0); resp->StatusBufferOffset = __constant_cpu_to_le32 (0); - - if (rndis_per_dev_params [configNr].ack) - rndis_per_dev_params [configNr].ack ( - rndis_per_dev_params [configNr].dev); + + if (rndis_per_dev_params [configNr].ack) + rndis_per_dev_params [configNr].ack ( + rndis_per_dev_params [configNr].dev); return 0; } @@ -1013,7 +1014,7 @@ int rndis_signal_connect (int configNr) { rndis_per_dev_params [configNr].media_state = NDIS_MEDIA_STATE_CONNECTED; - return rndis_indicate_status_msg (configNr, + return rndis_indicate_status_msg (configNr, RNDIS_STATUS_MEDIA_CONNECT); } @@ -1045,26 +1046,26 @@ void rndis_set_host_mac (int configNr, const u8 *addr) rndis_per_dev_params [configNr].host_mac = addr; } -/* - * Message Parser +/* + * Message Parser */ int rndis_msg_parser (u8 configNr, u8 *buf) { u32 MsgType, MsgLength; __le32 *tmp; struct rndis_params *params; - + if (!buf) return -ENOMEM; - - tmp = (__le32 *) buf; + + tmp = (__le32 *) buf; MsgType = le32_to_cpup(tmp++); MsgLength = le32_to_cpup(tmp++); - + if (configNr >= RNDIS_MAX_CONFIGS) return -ENOTSUPP; params = &rndis_per_dev_params [configNr]; - + /* NOTE: RNDIS is *EXTREMELY* chatty ... Windows constantly polls for * rx/tx statistics and link status, in addition to KEEPALIVE traffic * and normal HC level polling to see if there's any IN traffic. @@ -1073,12 +1074,12 @@ int rndis_msg_parser (u8 configNr, u8 *buf) /* For USB: responses may take up to 10 seconds */ switch (MsgType) { case REMOTE_NDIS_INITIALIZE_MSG: - DEBUG("%s: REMOTE_NDIS_INITIALIZE_MSG\n", + DEBUG("%s: REMOTE_NDIS_INITIALIZE_MSG\n", __FUNCTION__ ); params->state = RNDIS_INITIALIZED; return rndis_init_response (configNr, - (rndis_init_msg_type *) buf); - + (rndis_init_msg_type *) buf); + case REMOTE_NDIS_HALT_MSG: DEBUG("%s: REMOTE_NDIS_HALT_MSG\n", __FUNCTION__ ); @@ -1088,37 +1089,37 @@ int rndis_msg_parser (u8 configNr, u8 *buf) netif_stop_queue (params->dev); } return 0; - + case REMOTE_NDIS_QUERY_MSG: - return rndis_query_response (configNr, - (rndis_query_msg_type *) buf); - + return rndis_query_response (configNr, + (rndis_query_msg_type *) buf); + case REMOTE_NDIS_SET_MSG: - return rndis_set_response (configNr, - (rndis_set_msg_type *) buf); - + return rndis_set_response (configNr, + (rndis_set_msg_type *) buf); + case REMOTE_NDIS_RESET_MSG: - DEBUG("%s: REMOTE_NDIS_RESET_MSG\n", + DEBUG("%s: REMOTE_NDIS_RESET_MSG\n", __FUNCTION__ ); return rndis_reset_response (configNr, - (rndis_reset_msg_type *) buf); + (rndis_reset_msg_type *) buf); case REMOTE_NDIS_KEEPALIVE_MSG: /* For USB: host does this every 5 seconds */ if (rndis_debug > 1) - DEBUG("%s: REMOTE_NDIS_KEEPALIVE_MSG\n", + DEBUG("%s: REMOTE_NDIS_KEEPALIVE_MSG\n", __FUNCTION__ ); return rndis_keepalive_response (configNr, - (rndis_keepalive_msg_type *) + (rndis_keepalive_msg_type *) buf); - - default: + + default: /* At least Windows XP emits some undefined RNDIS messages. * In one case those messages seemed to relate to the host * suspending itself. */ printk (KERN_WARNING - "%s: unknown RNDIS message 0x%08X len %d\n", + "%s: unknown RNDIS message 0x%08X len %d\n", __FUNCTION__ , MsgType, MsgLength); { unsigned i; @@ -1142,14 +1143,14 @@ int rndis_msg_parser (u8 configNr, u8 *buf) } break; } - + return -ENOTSUPP; } int rndis_register (int (* rndis_control_ack) (struct net_device *)) { u8 i; - + for (i = 0; i < RNDIS_MAX_CONFIGS; i++) { if (!rndis_per_dev_params [i].used) { rndis_per_dev_params [i].used = 1; @@ -1159,32 +1160,32 @@ int rndis_register (int (* rndis_control_ack) (struct net_device *)) } } DEBUG("failed\n"); - + return -1; } void rndis_deregister (int configNr) { DEBUG("%s: \n", __FUNCTION__ ); - + if (configNr >= RNDIS_MAX_CONFIGS) return; rndis_per_dev_params [configNr].used = 0; - + return; } -int rndis_set_param_dev (u8 configNr, struct net_device *dev, +int rndis_set_param_dev (u8 configNr, struct net_device *dev, struct net_device_stats *stats, u16 *cdc_filter) { DEBUG("%s:\n", __FUNCTION__ ); if (!dev || !stats) return -1; if (configNr >= RNDIS_MAX_CONFIGS) return -1; - + rndis_per_dev_params [configNr].dev = dev; rndis_per_dev_params [configNr].stats = stats; rndis_per_dev_params [configNr].filter = cdc_filter; - + return 0; } @@ -1193,10 +1194,10 @@ int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr) DEBUG("%s:\n", __FUNCTION__ ); if (!vendorDescr) return -1; if (configNr >= RNDIS_MAX_CONFIGS) return -1; - + rndis_per_dev_params [configNr].vendorID = vendorID; rndis_per_dev_params [configNr].vendorDescr = vendorDescr; - + return 0; } @@ -1204,10 +1205,10 @@ int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed) { DEBUG("%s: %u %u\n", __FUNCTION__, medium, speed); if (configNr >= RNDIS_MAX_CONFIGS) return -1; - + rndis_per_dev_params [configNr].medium = medium; rndis_per_dev_params [configNr].speed = speed; - + return 0; } @@ -1229,9 +1230,9 @@ void rndis_free_response (int configNr, u8 *buf) { rndis_resp_t *r; struct list_head *act, *tmp; - - list_for_each_safe (act, tmp, - &(rndis_per_dev_params [configNr].resp_queue)) + + list_for_each_safe (act, tmp, + &(rndis_per_dev_params [configNr].resp_queue)) { r = list_entry (act, rndis_resp_t, list); if (r && r->buf == buf) { @@ -1244,12 +1245,12 @@ void rndis_free_response (int configNr, u8 *buf) u8 *rndis_get_next_response (int configNr, u32 *length) { rndis_resp_t *r; - struct list_head *act, *tmp; - + struct list_head *act, *tmp; + if (!length) return NULL; - - list_for_each_safe (act, tmp, - &(rndis_per_dev_params [configNr].resp_queue)) + + list_for_each_safe (act, tmp, + &(rndis_per_dev_params [configNr].resp_queue)) { r = list_entry (act, rndis_resp_t, list); if (!r->send) { @@ -1258,24 +1259,24 @@ u8 *rndis_get_next_response (int configNr, u32 *length) return r->buf; } } - + return NULL; } static rndis_resp_t *rndis_add_response (int configNr, u32 length) { rndis_resp_t *r; - + /* NOTE: this gets copied into ether.c USB_BUFSIZ bytes ... */ r = kmalloc (sizeof (rndis_resp_t) + length, GFP_ATOMIC); if (!r) return NULL; - + r->buf = (u8 *) (r + 1); r->length = length; r->send = 0; - - list_add_tail (&r->list, - &(rndis_per_dev_params [configNr].resp_queue)); + + list_add_tail (&r->list, + &(rndis_per_dev_params [configNr].resp_queue)); return r; } @@ -1301,14 +1302,14 @@ int rndis_rm_hdr(struct sk_buff *skb) #ifdef CONFIG_USB_GADGET_DEBUG_FILES -static int rndis_proc_read (char *page, char **start, off_t off, int count, int *eof, - void *data) +static int rndis_proc_read (char *page, char **start, off_t off, int count, int *eof, + void *data) { char *out = page; int len; rndis_params *param = (rndis_params *) data; - - out += snprintf (out, count, + + out += snprintf (out, count, "Config Nr. %d\n" "used : %s\n" "state : %s\n" @@ -1316,8 +1317,8 @@ static int rndis_proc_read (char *page, char **start, off_t off, int count, int "speed : %d\n" "cable : %s\n" "vendor ID : 0x%08X\n" - "vendor : %s\n", - param->confignr, (param->used) ? "y" : "n", + "vendor : %s\n", + param->confignr, (param->used) ? "y" : "n", ({ char *s = "?"; switch (param->state) { case RNDIS_UNINITIALIZED: @@ -1327,32 +1328,32 @@ static int rndis_proc_read (char *page, char **start, off_t off, int count, int case RNDIS_DATA_INITIALIZED: s = "RNDIS_DATA_INITIALIZED"; break; }; s; }), - param->medium, - (param->media_state) ? 0 : param->speed*100, + param->medium, + (param->media_state) ? 0 : param->speed*100, (param->media_state) ? "disconnected" : "connected", - param->vendorID, param->vendorDescr); - + param->vendorID, param->vendorDescr); + len = out - page; len -= off; - + if (len < count) { *eof = 1; if (len <= 0) return 0; } else len = count; - + *start = page + off; return len; } -static int rndis_proc_write (struct file *file, const char __user *buffer, - unsigned long count, void *data) +static int rndis_proc_write (struct file *file, const char __user *buffer, + unsigned long count, void *data) { rndis_params *p = data; u32 speed = 0; int i, fl_speed = 0; - + for (i = 0; i < count; i++) { char c; if (get_user(c, buffer)) @@ -1379,15 +1380,15 @@ static int rndis_proc_write (struct file *file, const char __user *buffer, case 'd': rndis_signal_disconnect(p->confignr); break; - default: + default: if (fl_speed) p->speed = speed; else DEBUG ("%c is not valid\n", c); break; } - + buffer++; } - + return count; } @@ -1408,7 +1409,7 @@ int __init rndis_init (void) sprintf (name, NAME_TEMPLATE, i); if (!(rndis_connect_state [i] - = create_proc_entry (name, 0660, NULL))) + = create_proc_entry (name, 0660, NULL))) { DEBUG ("%s :remove entries", __FUNCTION__); while (i) { @@ -1432,7 +1433,7 @@ int __init rndis_init (void) = NDIS_MEDIA_STATE_DISCONNECTED; INIT_LIST_HEAD (&(rndis_per_dev_params [i].resp_queue)); } - + return 0; } @@ -1441,7 +1442,7 @@ void rndis_exit (void) #ifdef CONFIG_USB_GADGET_DEBUG_FILES u8 i; char name [20]; - + for (i = 0; i < RNDIS_MAX_CONFIGS; i++) { sprintf (name, NAME_TEMPLATE, i); remove_proc_entry (name, NULL); diff --git a/drivers/usb/gadget/rndis.h b/drivers/usb/gadget/rndis.h index 95b4c632610..2956608be75 100644 --- a/drivers/usb/gadget/rndis.h +++ b/drivers/usb/gadget/rndis.h @@ -1,15 +1,15 @@ -/* +/* * RNDIS Definitions for Remote NDIS - * + * * Version: $Id: rndis.h,v 1.15 2004/03/25 21:33:46 robert Exp $ - * + * * Authors: Benedikt Spranger, Pengutronix - * Robert Schwebel, Pengutronix - * - * This program is free software; you can redistribute it and/or + * Robert Schwebel, Pengutronix + * + * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License - * version 2, as published by the Free Software Foundation. - * + * version 2, as published by the Free Software Foundation. + * * This software was originally developed in conformance with * Microsoft's Remote NDIS Specification License Agreement. */ @@ -34,7 +34,7 @@ #define RNDIS_STATUS_MEDIA_CONNECT 0x4001000BU /* Device connected */ #define RNDIS_STATUS_MEDIA_DISCONNECT 0x4001000CU /* Device disconnected */ /* For all not specified status messages: - * RNDIS_STATUS_Xxx -> NDIS_STATUS_Xxx + * RNDIS_STATUS_Xxx -> NDIS_STATUS_Xxx */ /* Message Set for Connectionless (802.3) Devices */ @@ -69,7 +69,7 @@ #define OID_PNP_ENABLE_WAKE_UP 0xFD010106 -typedef struct rndis_init_msg_type +typedef struct rndis_init_msg_type { __le32 MessageType; __le32 MessageLength; @@ -234,12 +234,12 @@ typedef struct rndis_params const u8 *host_mac; u16 *filter; - struct net_device *dev; + struct net_device *dev; struct net_device_stats *stats; u32 vendorID; const char *vendorDescr; - int (*ack) (struct net_device *); + int (*ack) (struct net_device *); struct list_head resp_queue; } rndis_params; @@ -250,7 +250,7 @@ void rndis_deregister (int configNr); int rndis_set_param_dev (u8 configNr, struct net_device *dev, struct net_device_stats *stats, u16 *cdc_filter); -int rndis_set_param_vendor (u8 configNr, u32 vendorID, +int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr); int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed); void rndis_add_hdr (struct sk_buff *skb); -- cgit v1.2.3 From a8c28f2389942bab376e39351d27525499630248 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Tue, 13 Jun 2006 09:57:47 -0700 Subject: [PATCH] USB: move to This moves to to reduce some of the clutter of usb header files. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 2 +- drivers/usb/gadget/ether.c | 2 +- drivers/usb/gadget/serial.c | 2 +- drivers/usb/net/cdc_ether.c | 2 +- drivers/usb/net/rndis_host.c | 2 +- drivers/usb/net/zaurus.c | 2 +- include/linux/usb/cdc.h | 205 +++++++++++++++++++++++++++++++++++++++++++ include/linux/usb_cdc.h | 205 ------------------------------------------- 8 files changed, 211 insertions(+), 211 deletions(-) create mode 100644 include/linux/usb/cdc.h delete mode 100644 include/linux/usb_cdc.h diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 506aff60dac..d41dc67ba4c 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -63,7 +63,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index fc4684096fc..078daa02671 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -49,7 +49,7 @@ #include #include -#include +#include #include #include diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index e477edd681d..9d6e1d29552 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -45,7 +45,7 @@ #include #include -#include +#include #include #include "gadget_chips.h" diff --git a/drivers/usb/net/cdc_ether.c b/drivers/usb/net/cdc_ether.c index 9c6c5b0b01a..efd195b5912 100644 --- a/drivers/usb/net/cdc_ether.c +++ b/drivers/usb/net/cdc_ether.c @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include "usbnet.h" diff --git a/drivers/usb/net/rndis_host.c b/drivers/usb/net/rndis_host.c index 94ddfe16fdd..f551546d752 100644 --- a/drivers/usb/net/rndis_host.c +++ b/drivers/usb/net/rndis_host.c @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include "usbnet.h" diff --git a/drivers/usb/net/zaurus.c b/drivers/usb/net/zaurus.c index bf2035d329f..813e470d060 100644 --- a/drivers/usb/net/zaurus.c +++ b/drivers/usb/net/zaurus.c @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include "usbnet.h" diff --git a/include/linux/usb/cdc.h b/include/linux/usb/cdc.h new file mode 100644 index 00000000000..ba617c37245 --- /dev/null +++ b/include/linux/usb/cdc.h @@ -0,0 +1,205 @@ +/* + * USB Communications Device Class (CDC) definitions + * + * CDC says how to talk to lots of different types of network adapters, + * notably ethernet adapters and various modems. It's used mostly with + * firmware based USB peripherals. + */ + +#define USB_CDC_SUBCLASS_ACM 0x02 +#define USB_CDC_SUBCLASS_ETHERNET 0x06 +#define USB_CDC_SUBCLASS_WHCM 0x08 +#define USB_CDC_SUBCLASS_DMM 0x09 +#define USB_CDC_SUBCLASS_MDLM 0x0a +#define USB_CDC_SUBCLASS_OBEX 0x0b + +#define USB_CDC_PROTO_NONE 0 + +#define USB_CDC_ACM_PROTO_AT_V25TER 1 +#define USB_CDC_ACM_PROTO_AT_PCCA101 2 +#define USB_CDC_ACM_PROTO_AT_PCCA101_WAKE 3 +#define USB_CDC_ACM_PROTO_AT_GSM 4 +#define USB_CDC_ACM_PROTO_AT_3G 5 +#define USB_CDC_ACM_PROTO_AT_CDMA 6 +#define USB_CDC_ACM_PROTO_VENDOR 0xff + +/*-------------------------------------------------------------------------*/ + +/* + * Class-Specific descriptors ... there are a couple dozen of them + */ + +#define USB_CDC_HEADER_TYPE 0x00 /* header_desc */ +#define USB_CDC_CALL_MANAGEMENT_TYPE 0x01 /* call_mgmt_descriptor */ +#define USB_CDC_ACM_TYPE 0x02 /* acm_descriptor */ +#define USB_CDC_UNION_TYPE 0x06 /* union_desc */ +#define USB_CDC_COUNTRY_TYPE 0x07 +#define USB_CDC_NETWORK_TERMINAL_TYPE 0x0a /* network_terminal_desc */ +#define USB_CDC_ETHERNET_TYPE 0x0f /* ether_desc */ +#define USB_CDC_WHCM_TYPE 0x11 +#define USB_CDC_MDLM_TYPE 0x12 /* mdlm_desc */ +#define USB_CDC_MDLM_DETAIL_TYPE 0x13 /* mdlm_detail_desc */ +#define USB_CDC_DMM_TYPE 0x14 +#define USB_CDC_OBEX_TYPE 0x15 + +/* "Header Functional Descriptor" from CDC spec 5.2.3.1 */ +struct usb_cdc_header_desc { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubType; + + __le16 bcdCDC; +} __attribute__ ((packed)); + +/* "Call Management Descriptor" from CDC spec 5.2.3.2 */ +struct usb_cdc_call_mgmt_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubType; + + __u8 bmCapabilities; +#define USB_CDC_CALL_MGMT_CAP_CALL_MGMT 0x01 +#define USB_CDC_CALL_MGMT_CAP_DATA_INTF 0x02 + + __u8 bDataInterface; +} __attribute__ ((packed)); + +/* "Abstract Control Management Descriptor" from CDC spec 5.2.3.3 */ +struct usb_cdc_acm_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubType; + + __u8 bmCapabilities; +} __attribute__ ((packed)); + +/* "Union Functional Descriptor" from CDC spec 5.2.3.8 */ +struct usb_cdc_union_desc { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubType; + + __u8 bMasterInterface0; + __u8 bSlaveInterface0; + /* ... and there could be other slave interfaces */ +} __attribute__ ((packed)); + +/* "Network Channel Terminal Functional Descriptor" from CDC spec 5.2.3.11 */ +struct usb_cdc_network_terminal_desc { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubType; + + __u8 bEntityId; + __u8 iName; + __u8 bChannelIndex; + __u8 bPhysicalInterface; +} __attribute__ ((packed)); + +/* "Ethernet Networking Functional Descriptor" from CDC spec 5.2.3.16 */ +struct usb_cdc_ether_desc { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubType; + + __u8 iMACAddress; + __le32 bmEthernetStatistics; + __le16 wMaxSegmentSize; + __le16 wNumberMCFilters; + __u8 bNumberPowerFilters; +} __attribute__ ((packed)); + +/* "MDLM Functional Descriptor" from CDC WMC spec 6.7.2.3 */ +struct usb_cdc_mdlm_desc { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubType; + + __le16 bcdVersion; + __u8 bGUID[16]; +} __attribute__ ((packed)); + +/* "MDLM Detail Functional Descriptor" from CDC WMC spec 6.7.2.4 */ +struct usb_cdc_mdlm_detail_desc { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubType; + + /* type is associated with mdlm_desc.bGUID */ + __u8 bGuidDescriptorType; + __u8 bDetailData[0]; +} __attribute__ ((packed)); + +/*-------------------------------------------------------------------------*/ + +/* + * Class-Specific Control Requests (6.2) + * + * section 3.6.2.1 table 4 has the ACM profile, for modems. + * section 3.8.2 table 10 has the ethernet profile. + * + * Microsoft's RNDIS stack for Ethernet is a vendor-specific CDC ACM variant, + * heavily dependent on the encapsulated (proprietary) command mechanism. + */ + +#define USB_CDC_SEND_ENCAPSULATED_COMMAND 0x00 +#define USB_CDC_GET_ENCAPSULATED_RESPONSE 0x01 +#define USB_CDC_REQ_SET_LINE_CODING 0x20 +#define USB_CDC_REQ_GET_LINE_CODING 0x21 +#define USB_CDC_REQ_SET_CONTROL_LINE_STATE 0x22 +#define USB_CDC_REQ_SEND_BREAK 0x23 +#define USB_CDC_SET_ETHERNET_MULTICAST_FILTERS 0x40 +#define USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER 0x41 +#define USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER 0x42 +#define USB_CDC_SET_ETHERNET_PACKET_FILTER 0x43 +#define USB_CDC_GET_ETHERNET_STATISTIC 0x44 + +/* Line Coding Structure from CDC spec 6.2.13 */ +struct usb_cdc_line_coding { + __le32 dwDTERate; + __u8 bCharFormat; +#define USB_CDC_1_STOP_BITS 0 +#define USB_CDC_1_5_STOP_BITS 1 +#define USB_CDC_2_STOP_BITS 2 + + __u8 bParityType; +#define USB_CDC_NO_PARITY 0 +#define USB_CDC_ODD_PARITY 1 +#define USB_CDC_EVEN_PARITY 2 +#define USB_CDC_MARK_PARITY 3 +#define USB_CDC_SPACE_PARITY 4 + + __u8 bDataBits; +} __attribute__ ((packed)); + +/* table 62; bits in multicast filter */ +#define USB_CDC_PACKET_TYPE_PROMISCUOUS (1 << 0) +#define USB_CDC_PACKET_TYPE_ALL_MULTICAST (1 << 1) /* no filter */ +#define USB_CDC_PACKET_TYPE_DIRECTED (1 << 2) +#define USB_CDC_PACKET_TYPE_BROADCAST (1 << 3) +#define USB_CDC_PACKET_TYPE_MULTICAST (1 << 4) /* filtered */ + + +/*-------------------------------------------------------------------------*/ + +/* + * Class-Specific Notifications (6.3) sent by interrupt transfers + * + * section 3.8.2 table 11 of the CDC spec lists Ethernet notifications + * section 3.6.2.1 table 5 specifies ACM notifications, accepted by RNDIS + * RNDIS also defines its own bit-incompatible notifications + */ + +#define USB_CDC_NOTIFY_NETWORK_CONNECTION 0x00 +#define USB_CDC_NOTIFY_RESPONSE_AVAILABLE 0x01 +#define USB_CDC_NOTIFY_SERIAL_STATE 0x20 +#define USB_CDC_NOTIFY_SPEED_CHANGE 0x2a + +struct usb_cdc_notification { + __u8 bmRequestType; + __u8 bNotificationType; + __le16 wValue; + __le16 wIndex; + __le16 wLength; +} __attribute__ ((packed)); + diff --git a/include/linux/usb_cdc.h b/include/linux/usb_cdc.h deleted file mode 100644 index ba617c37245..00000000000 --- a/include/linux/usb_cdc.h +++ /dev/null @@ -1,205 +0,0 @@ -/* - * USB Communications Device Class (CDC) definitions - * - * CDC says how to talk to lots of different types of network adapters, - * notably ethernet adapters and various modems. It's used mostly with - * firmware based USB peripherals. - */ - -#define USB_CDC_SUBCLASS_ACM 0x02 -#define USB_CDC_SUBCLASS_ETHERNET 0x06 -#define USB_CDC_SUBCLASS_WHCM 0x08 -#define USB_CDC_SUBCLASS_DMM 0x09 -#define USB_CDC_SUBCLASS_MDLM 0x0a -#define USB_CDC_SUBCLASS_OBEX 0x0b - -#define USB_CDC_PROTO_NONE 0 - -#define USB_CDC_ACM_PROTO_AT_V25TER 1 -#define USB_CDC_ACM_PROTO_AT_PCCA101 2 -#define USB_CDC_ACM_PROTO_AT_PCCA101_WAKE 3 -#define USB_CDC_ACM_PROTO_AT_GSM 4 -#define USB_CDC_ACM_PROTO_AT_3G 5 -#define USB_CDC_ACM_PROTO_AT_CDMA 6 -#define USB_CDC_ACM_PROTO_VENDOR 0xff - -/*-------------------------------------------------------------------------*/ - -/* - * Class-Specific descriptors ... there are a couple dozen of them - */ - -#define USB_CDC_HEADER_TYPE 0x00 /* header_desc */ -#define USB_CDC_CALL_MANAGEMENT_TYPE 0x01 /* call_mgmt_descriptor */ -#define USB_CDC_ACM_TYPE 0x02 /* acm_descriptor */ -#define USB_CDC_UNION_TYPE 0x06 /* union_desc */ -#define USB_CDC_COUNTRY_TYPE 0x07 -#define USB_CDC_NETWORK_TERMINAL_TYPE 0x0a /* network_terminal_desc */ -#define USB_CDC_ETHERNET_TYPE 0x0f /* ether_desc */ -#define USB_CDC_WHCM_TYPE 0x11 -#define USB_CDC_MDLM_TYPE 0x12 /* mdlm_desc */ -#define USB_CDC_MDLM_DETAIL_TYPE 0x13 /* mdlm_detail_desc */ -#define USB_CDC_DMM_TYPE 0x14 -#define USB_CDC_OBEX_TYPE 0x15 - -/* "Header Functional Descriptor" from CDC spec 5.2.3.1 */ -struct usb_cdc_header_desc { - __u8 bLength; - __u8 bDescriptorType; - __u8 bDescriptorSubType; - - __le16 bcdCDC; -} __attribute__ ((packed)); - -/* "Call Management Descriptor" from CDC spec 5.2.3.2 */ -struct usb_cdc_call_mgmt_descriptor { - __u8 bLength; - __u8 bDescriptorType; - __u8 bDescriptorSubType; - - __u8 bmCapabilities; -#define USB_CDC_CALL_MGMT_CAP_CALL_MGMT 0x01 -#define USB_CDC_CALL_MGMT_CAP_DATA_INTF 0x02 - - __u8 bDataInterface; -} __attribute__ ((packed)); - -/* "Abstract Control Management Descriptor" from CDC spec 5.2.3.3 */ -struct usb_cdc_acm_descriptor { - __u8 bLength; - __u8 bDescriptorType; - __u8 bDescriptorSubType; - - __u8 bmCapabilities; -} __attribute__ ((packed)); - -/* "Union Functional Descriptor" from CDC spec 5.2.3.8 */ -struct usb_cdc_union_desc { - __u8 bLength; - __u8 bDescriptorType; - __u8 bDescriptorSubType; - - __u8 bMasterInterface0; - __u8 bSlaveInterface0; - /* ... and there could be other slave interfaces */ -} __attribute__ ((packed)); - -/* "Network Channel Terminal Functional Descriptor" from CDC spec 5.2.3.11 */ -struct usb_cdc_network_terminal_desc { - __u8 bLength; - __u8 bDescriptorType; - __u8 bDescriptorSubType; - - __u8 bEntityId; - __u8 iName; - __u8 bChannelIndex; - __u8 bPhysicalInterface; -} __attribute__ ((packed)); - -/* "Ethernet Networking Functional Descriptor" from CDC spec 5.2.3.16 */ -struct usb_cdc_ether_desc { - __u8 bLength; - __u8 bDescriptorType; - __u8 bDescriptorSubType; - - __u8 iMACAddress; - __le32 bmEthernetStatistics; - __le16 wMaxSegmentSize; - __le16 wNumberMCFilters; - __u8 bNumberPowerFilters; -} __attribute__ ((packed)); - -/* "MDLM Functional Descriptor" from CDC WMC spec 6.7.2.3 */ -struct usb_cdc_mdlm_desc { - __u8 bLength; - __u8 bDescriptorType; - __u8 bDescriptorSubType; - - __le16 bcdVersion; - __u8 bGUID[16]; -} __attribute__ ((packed)); - -/* "MDLM Detail Functional Descriptor" from CDC WMC spec 6.7.2.4 */ -struct usb_cdc_mdlm_detail_desc { - __u8 bLength; - __u8 bDescriptorType; - __u8 bDescriptorSubType; - - /* type is associated with mdlm_desc.bGUID */ - __u8 bGuidDescriptorType; - __u8 bDetailData[0]; -} __attribute__ ((packed)); - -/*-------------------------------------------------------------------------*/ - -/* - * Class-Specific Control Requests (6.2) - * - * section 3.6.2.1 table 4 has the ACM profile, for modems. - * section 3.8.2 table 10 has the ethernet profile. - * - * Microsoft's RNDIS stack for Ethernet is a vendor-specific CDC ACM variant, - * heavily dependent on the encapsulated (proprietary) command mechanism. - */ - -#define USB_CDC_SEND_ENCAPSULATED_COMMAND 0x00 -#define USB_CDC_GET_ENCAPSULATED_RESPONSE 0x01 -#define USB_CDC_REQ_SET_LINE_CODING 0x20 -#define USB_CDC_REQ_GET_LINE_CODING 0x21 -#define USB_CDC_REQ_SET_CONTROL_LINE_STATE 0x22 -#define USB_CDC_REQ_SEND_BREAK 0x23 -#define USB_CDC_SET_ETHERNET_MULTICAST_FILTERS 0x40 -#define USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER 0x41 -#define USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER 0x42 -#define USB_CDC_SET_ETHERNET_PACKET_FILTER 0x43 -#define USB_CDC_GET_ETHERNET_STATISTIC 0x44 - -/* Line Coding Structure from CDC spec 6.2.13 */ -struct usb_cdc_line_coding { - __le32 dwDTERate; - __u8 bCharFormat; -#define USB_CDC_1_STOP_BITS 0 -#define USB_CDC_1_5_STOP_BITS 1 -#define USB_CDC_2_STOP_BITS 2 - - __u8 bParityType; -#define USB_CDC_NO_PARITY 0 -#define USB_CDC_ODD_PARITY 1 -#define USB_CDC_EVEN_PARITY 2 -#define USB_CDC_MARK_PARITY 3 -#define USB_CDC_SPACE_PARITY 4 - - __u8 bDataBits; -} __attribute__ ((packed)); - -/* table 62; bits in multicast filter */ -#define USB_CDC_PACKET_TYPE_PROMISCUOUS (1 << 0) -#define USB_CDC_PACKET_TYPE_ALL_MULTICAST (1 << 1) /* no filter */ -#define USB_CDC_PACKET_TYPE_DIRECTED (1 << 2) -#define USB_CDC_PACKET_TYPE_BROADCAST (1 << 3) -#define USB_CDC_PACKET_TYPE_MULTICAST (1 << 4) /* filtered */ - - -/*-------------------------------------------------------------------------*/ - -/* - * Class-Specific Notifications (6.3) sent by interrupt transfers - * - * section 3.8.2 table 11 of the CDC spec lists Ethernet notifications - * section 3.6.2.1 table 5 specifies ACM notifications, accepted by RNDIS - * RNDIS also defines its own bit-incompatible notifications - */ - -#define USB_CDC_NOTIFY_NETWORK_CONNECTION 0x00 -#define USB_CDC_NOTIFY_RESPONSE_AVAILABLE 0x01 -#define USB_CDC_NOTIFY_SERIAL_STATE 0x20 -#define USB_CDC_NOTIFY_SPEED_CHANGE 0x2a - -struct usb_cdc_notification { - __u8 bmRequestType; - __u8 bNotificationType; - __le16 wValue; - __le16 wIndex; - __le16 wLength; -} __attribute__ ((packed)); - -- cgit v1.2.3 From 325a4af60dc945bf2da9cbcdbabb276e312b297c Mon Sep 17 00:00:00 2001 From: David Brownell Date: Tue, 13 Jun 2006 09:59:32 -0700 Subject: [PATCH] USB: move hardware-specific to This moves header files for controller-specific platform data from to to start reducing some clutter. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/isp116x-hcd.c | 2 +- drivers/usb/host/sl811-hcd.c | 2 +- drivers/usb/host/sl811_cs.c | 2 +- include/linux/usb/isp116x.h | 29 +++++++++++++++++++++++++++++ include/linux/usb/sl811.h | 26 ++++++++++++++++++++++++++ include/linux/usb_isp116x.h | 29 ----------------------------- include/linux/usb_sl811.h | 26 -------------------------- 7 files changed, 58 insertions(+), 58 deletions(-) create mode 100644 include/linux/usb/isp116x.h create mode 100644 include/linux/usb/sl811.h delete mode 100644 include/linux/usb_isp116x.h delete mode 100644 include/linux/usb_sl811.h diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index c5e224048ef..14386254c87 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c @@ -63,7 +63,7 @@ #include #include #include -#include +#include #include #include diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index a9234305275..6b4bc3f2bd8 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c @@ -46,7 +46,7 @@ #include #include #include -#include +#include #include #include diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c index 302aa1ec312..54f554e0f0a 100644 --- a/drivers/usb/host/sl811_cs.c +++ b/drivers/usb/host/sl811_cs.c @@ -27,7 +27,7 @@ #include #include -#include +#include MODULE_AUTHOR("Botond Botyanszki"); MODULE_DESCRIPTION("REX-CFU1U PCMCIA driver for 2.6"); diff --git a/include/linux/usb/isp116x.h b/include/linux/usb/isp116x.h new file mode 100644 index 00000000000..436dd8a2b64 --- /dev/null +++ b/include/linux/usb/isp116x.h @@ -0,0 +1,29 @@ + +/* + * Board initialization code should put one of these into dev->platform_data + * and place the isp116x onto platform_bus. + */ + +struct isp116x_platform_data { + /* Enable internal resistors on downstream ports */ + unsigned sel15Kres:1; + /* On-chip overcurrent detection */ + unsigned oc_enable:1; + /* INT output polarity */ + unsigned int_act_high:1; + /* INT edge or level triggered */ + unsigned int_edge_triggered:1; + /* Enable wakeup by devices on usb bus (e.g. wakeup + by attachment/detachment or by device activity + such as moving a mouse). When chosen, this option + prevents stopping internal clock, increasing + thereby power consumption in suspended state. */ + unsigned remote_wakeup_enable:1; + /* Inter-io delay (ns). The chip is picky about access timings; it + expects at least: + 150ns delay between consecutive accesses to DATA_REG, + 300ns delay between access to ADDR_REG and DATA_REG + OE, WE MUST NOT be changed during these intervals + */ + void (*delay) (struct device * dev, int delay); +}; diff --git a/include/linux/usb/sl811.h b/include/linux/usb/sl811.h new file mode 100644 index 00000000000..397ee3b3d7f --- /dev/null +++ b/include/linux/usb/sl811.h @@ -0,0 +1,26 @@ + +/* + * board initialization should put one of these into dev->platform_data + * and place the sl811hs onto platform_bus named "sl811-hcd". + */ + +struct sl811_platform_data { + unsigned can_wakeup:1; + + /* given port_power, msec/2 after power on till power good */ + u8 potpg; + + /* mA/2 power supplied on this port (max = default = 250) */ + u8 power; + + /* sl811 relies on an external source of VBUS current */ + void (*port_power)(struct device *dev, int is_on); + + /* pulse sl811 nRST (probably with a GPIO) */ + void (*reset)(struct device *dev); + + // some boards need something like these: + // int (*check_overcurrent)(struct device *dev); + // void (*clock_enable)(struct device *dev, int is_on); +}; + diff --git a/include/linux/usb_isp116x.h b/include/linux/usb_isp116x.h deleted file mode 100644 index 436dd8a2b64..00000000000 --- a/include/linux/usb_isp116x.h +++ /dev/null @@ -1,29 +0,0 @@ - -/* - * Board initialization code should put one of these into dev->platform_data - * and place the isp116x onto platform_bus. - */ - -struct isp116x_platform_data { - /* Enable internal resistors on downstream ports */ - unsigned sel15Kres:1; - /* On-chip overcurrent detection */ - unsigned oc_enable:1; - /* INT output polarity */ - unsigned int_act_high:1; - /* INT edge or level triggered */ - unsigned int_edge_triggered:1; - /* Enable wakeup by devices on usb bus (e.g. wakeup - by attachment/detachment or by device activity - such as moving a mouse). When chosen, this option - prevents stopping internal clock, increasing - thereby power consumption in suspended state. */ - unsigned remote_wakeup_enable:1; - /* Inter-io delay (ns). The chip is picky about access timings; it - expects at least: - 150ns delay between consecutive accesses to DATA_REG, - 300ns delay between access to ADDR_REG and DATA_REG - OE, WE MUST NOT be changed during these intervals - */ - void (*delay) (struct device * dev, int delay); -}; diff --git a/include/linux/usb_sl811.h b/include/linux/usb_sl811.h deleted file mode 100644 index 4f2d012d730..00000000000 --- a/include/linux/usb_sl811.h +++ /dev/null @@ -1,26 +0,0 @@ - -/* - * board initialization should put one of these into dev->platform_data - * and place the sl811hs onto platform_bus named "sl811-hcd". - */ - -struct sl811_platform_data { - unsigned can_wakeup:1; - - /* given port_power, msec/2 after power on till power good */ - u8 potpg; - - /* mA/2 power supplied on this port (max = default = 250) */ - u8 power; - - /* sl811 relies on an external source of VBUS current */ - void (*port_power)(struct device *dev, int is_on); - - /* pulse sl811 nRST (probably with a GPIO) */ - void (*reset)(struct device *dev); - - // some boards need something like these: - // int (*check_overcurrent)(struct device *dev); - // void (*clock_enable)(struct device *dev, int is_on); -}; - -- cgit v1.2.3 From ae0dadcf0f912cbab2ac84caa437454620bf71b2 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Tue, 13 Jun 2006 10:04:34 -0700 Subject: [PATCH] USB: move to Move to and remove some redundant includes. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/media/video/usbvideo/konicawc.c | 3 +-- drivers/usb/input/acecad.c | 4 +--- drivers/usb/input/aiptek.c | 4 +--- drivers/usb/input/appletouch.c | 4 +--- drivers/usb/input/ati_remote.c | 4 +--- drivers/usb/input/ati_remote2.c | 2 +- drivers/usb/input/hid-input.c | 4 +--- drivers/usb/input/itmtouch.c | 4 +--- drivers/usb/input/kbtab.c | 5 +---- drivers/usb/input/keyspan_remote.c | 4 +--- drivers/usb/input/mtouchusb.c | 4 +--- drivers/usb/input/powermate.c | 4 +--- drivers/usb/input/touchkitusb.c | 4 +--- drivers/usb/input/usbkbd.c | 4 +--- drivers/usb/input/usbmouse.c | 4 +--- drivers/usb/input/usbtouchscreen.c | 2 +- drivers/usb/input/wacom.c | 5 +---- drivers/usb/input/xpad.c | 4 +--- drivers/usb/input/yealink.c | 4 +--- drivers/usb/storage/onetouch.c | 3 +-- include/linux/usb/input.h | 25 +++++++++++++++++++++++++ include/linux/usb_input.h | 25 ------------------------- 22 files changed, 45 insertions(+), 81 deletions(-) create mode 100644 include/linux/usb/input.h delete mode 100644 include/linux/usb_input.h diff --git a/drivers/media/video/usbvideo/konicawc.c b/drivers/media/video/usbvideo/konicawc.c index c11f5d46b11..6f31ecc8884 100644 --- a/drivers/media/video/usbvideo/konicawc.c +++ b/drivers/media/video/usbvideo/konicawc.c @@ -15,8 +15,7 @@ #include #include #include -#include -#include +#include #include "usbvideo.h" diff --git a/drivers/usb/input/acecad.c b/drivers/usb/input/acecad.c index df29b8078b5..18c10e150ef 100644 --- a/drivers/usb/input/acecad.c +++ b/drivers/usb/input/acecad.c @@ -27,11 +27,9 @@ #include #include -#include #include #include -#include -#include +#include /* * Version Information diff --git a/drivers/usb/input/aiptek.c b/drivers/usb/input/aiptek.c index a6693b0d1c4..b138dae2b05 100644 --- a/drivers/usb/input/aiptek.c +++ b/drivers/usb/input/aiptek.c @@ -73,11 +73,9 @@ #include #include #include -#include #include #include -#include -#include +#include #include #include #include diff --git a/drivers/usb/input/appletouch.c b/drivers/usb/input/appletouch.c index 4eff8d7a79d..36855062eac 100644 --- a/drivers/usb/input/appletouch.c +++ b/drivers/usb/input/appletouch.c @@ -33,9 +33,7 @@ #include #include #include -#include -#include -#include +#include /* Apple has powerbooks which have the keyboard with different Product IDs */ #define APPLE_VENDOR_ID 0x05AC diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c index 99f986cb6e9..07c8c0e665d 100644 --- a/drivers/usb/input/ati_remote.c +++ b/drivers/usb/input/ati_remote.c @@ -92,9 +92,7 @@ #include #include #include -#include -#include -#include +#include #include #include diff --git a/drivers/usb/input/ati_remote2.c b/drivers/usb/input/ati_remote2.c index ab1a1ae24be..ea71de81ca6 100644 --- a/drivers/usb/input/ati_remote2.c +++ b/drivers/usb/input/ati_remote2.c @@ -8,7 +8,7 @@ * as published by the Free Software Foundation. */ -#include +#include #define DRIVER_DESC "ATI/Philips USB RF remote driver" #define DRIVER_VERSION "0.1" diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c index 2f665195f4a..028e1ad89f5 100644 --- a/drivers/usb/input/hid-input.c +++ b/drivers/usb/input/hid-input.c @@ -29,9 +29,7 @@ #include #include #include -#include -#include -#include +#include #undef DEBUG diff --git a/drivers/usb/input/itmtouch.c b/drivers/usb/input/itmtouch.c index 7618ae5c104..5c570cc703f 100644 --- a/drivers/usb/input/itmtouch.c +++ b/drivers/usb/input/itmtouch.c @@ -42,11 +42,9 @@ #include #include #include -#include #include #include -#include -#include +#include /* only an 8 byte buffer necessary for a single packet */ #define ITM_BUFSIZE 8 diff --git a/drivers/usb/input/kbtab.c b/drivers/usb/input/kbtab.c index f6d5cead542..604ade356ea 100644 --- a/drivers/usb/input/kbtab.c +++ b/drivers/usb/input/kbtab.c @@ -1,12 +1,9 @@ #include #include -#include #include #include -#include -#include +#include #include -#include /* * Version Information diff --git a/drivers/usb/input/keyspan_remote.c b/drivers/usb/input/keyspan_remote.c index 3d911976f37..70af985b5db 100644 --- a/drivers/usb/input/keyspan_remote.c +++ b/drivers/usb/input/keyspan_remote.c @@ -18,9 +18,7 @@ #include #include #include -#include -#include -#include +#include #define DRIVER_VERSION "v0.1" #define DRIVER_AUTHOR "Michael Downey " diff --git a/drivers/usb/input/mtouchusb.c b/drivers/usb/input/mtouchusb.c index f018953a548..4fdee4db072 100644 --- a/drivers/usb/input/mtouchusb.c +++ b/drivers/usb/input/mtouchusb.c @@ -42,11 +42,9 @@ #include #include #include -#include #include #include -#include -#include +#include #define MTOUCHUSB_MIN_XC 0x0 #define MTOUCHUSB_MAX_RAW_XC 0x4000 diff --git a/drivers/usb/input/powermate.c b/drivers/usb/input/powermate.c index fdf0f788062..b3c0d0c3eae 100644 --- a/drivers/usb/input/powermate.c +++ b/drivers/usb/input/powermate.c @@ -30,12 +30,10 @@ #include #include -#include #include #include #include -#include -#include +#include #define POWERMATE_VENDOR 0x077d /* Griffin Technology, Inc. */ #define POWERMATE_PRODUCT_NEW 0x0410 /* Griffin PowerMate */ diff --git a/drivers/usb/input/touchkitusb.c b/drivers/usb/input/touchkitusb.c index 697c5e573a1..da7b0bf51af 100644 --- a/drivers/usb/input/touchkitusb.c +++ b/drivers/usb/input/touchkitusb.c @@ -27,11 +27,9 @@ #include #include #include -#include #include #include -#include -#include +#include #define TOUCHKIT_MIN_XC 0x0 #define TOUCHKIT_MAX_XC 0x07ff diff --git a/drivers/usb/input/usbkbd.c b/drivers/usb/input/usbkbd.c index 2f3edc26cb5..5067a6ae650 100644 --- a/drivers/usb/input/usbkbd.c +++ b/drivers/usb/input/usbkbd.c @@ -29,10 +29,8 @@ #include #include #include -#include #include -#include -#include +#include /* * Version Information diff --git a/drivers/usb/input/usbmouse.c b/drivers/usb/input/usbmouse.c index af526135d21..446935b671d 100644 --- a/drivers/usb/input/usbmouse.c +++ b/drivers/usb/input/usbmouse.c @@ -28,11 +28,9 @@ #include #include -#include #include #include -#include -#include +#include /* * Version Information diff --git a/drivers/usb/input/usbtouchscreen.c b/drivers/usb/input/usbtouchscreen.c index e9a07c1e905..3b175aa482c 100644 --- a/drivers/usb/input/usbtouchscreen.c +++ b/drivers/usb/input/usbtouchscreen.c @@ -39,7 +39,7 @@ #include #include #include -#include +#include #define DRIVER_VERSION "v0.3" diff --git a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c index cf84c6096f2..369461a70b7 100644 --- a/drivers/usb/input/wacom.c +++ b/drivers/usb/input/wacom.c @@ -69,13 +69,10 @@ #include #include -#include #include #include -#include -#include +#include #include -#include /* * Version Information diff --git a/drivers/usb/input/xpad.c b/drivers/usb/input/xpad.c index e278489a80c..cfd4a4e0433 100644 --- a/drivers/usb/input/xpad.c +++ b/drivers/usb/input/xpad.c @@ -56,13 +56,11 @@ #include #include -#include #include #include #include #include -#include -#include +#include #define DRIVER_VERSION "v0.0.5" #define DRIVER_AUTHOR "Marko Friedemann " diff --git a/drivers/usb/input/yealink.c b/drivers/usb/input/yealink.c index 37d2f0ba031..24aedbb20f0 100644 --- a/drivers/usb/input/yealink.c +++ b/drivers/usb/input/yealink.c @@ -48,13 +48,11 @@ #include #include -#include #include #include #include #include -#include -#include +#include #include "map_to_7segment.h" #include "yealink.h" diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c index 55ee2d36d58..026a587eb8d 100644 --- a/drivers/usb/storage/onetouch.c +++ b/drivers/usb/storage/onetouch.c @@ -34,9 +34,8 @@ #include #include #include -#include #include -#include +#include #include "usb.h" #include "onetouch.h" #include "debug.h" diff --git a/include/linux/usb/input.h b/include/linux/usb/input.h new file mode 100644 index 00000000000..716e0cc1604 --- /dev/null +++ b/include/linux/usb/input.h @@ -0,0 +1,25 @@ +#ifndef __USB_INPUT_H +#define __USB_INPUT_H + +/* + * Copyright (C) 2005 Dmitry Torokhov + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +#include +#include +#include + +static inline void +usb_to_input_id(const struct usb_device *dev, struct input_id *id) +{ + id->bustype = BUS_USB; + id->vendor = le16_to_cpu(dev->descriptor.idVendor); + id->product = le16_to_cpu(dev->descriptor.idProduct); + id->version = le16_to_cpu(dev->descriptor.bcdDevice); +} + +#endif diff --git a/include/linux/usb_input.h b/include/linux/usb_input.h deleted file mode 100644 index 716e0cc1604..00000000000 --- a/include/linux/usb_input.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef __USB_INPUT_H -#define __USB_INPUT_H - -/* - * Copyright (C) 2005 Dmitry Torokhov - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - */ - -#include -#include -#include - -static inline void -usb_to_input_id(const struct usb_device *dev, struct input_id *id) -{ - id->bustype = BUS_USB; - id->vendor = le16_to_cpu(dev->descriptor.idVendor); - id->product = le16_to_cpu(dev->descriptor.idProduct); - id->version = le16_to_cpu(dev->descriptor.bcdDevice); -} - -#endif -- cgit v1.2.3 From 84412f6291b50690febd81899e46f0f0ef7a13e0 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 14 Jun 2006 12:14:34 -0700 Subject: [PATCH] USB: move the endpoint specific sysfs code to it's own file This makes it easier to modify in the future without touching anything else. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/Makefile | 3 +- drivers/usb/core/endpoint.c | 213 ++++++++++++++++++++++++++++++++++++++++++++ drivers/usb/core/sysfs.c | 197 ---------------------------------------- drivers/usb/core/usb.h | 3 + 4 files changed, 218 insertions(+), 198 deletions(-) create mode 100644 drivers/usb/core/endpoint.c diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile index 28329ddf187..ec510922af6 100644 --- a/drivers/usb/core/Makefile +++ b/drivers/usb/core/Makefile @@ -3,7 +3,8 @@ # usbcore-objs := usb.o hub.o hcd.o urb.o message.o driver.o \ - config.o file.o buffer.o sysfs.o devio.o notify.o + config.o file.o buffer.o sysfs.o endpoint.o \ + devio.o notify.o ifeq ($(CONFIG_PCI),y) usbcore-objs += hcd-pci.o diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c new file mode 100644 index 00000000000..2b1697715e8 --- /dev/null +++ b/drivers/usb/core/endpoint.c @@ -0,0 +1,213 @@ +/* + * drivers/usb/core/endpoint.c + * + * (C) Copyright 2002,2004,2006 Greg Kroah-Hartman + * (C) Copyright 2002,2004 IBM Corp. + * (C) Copyright 2006 Novell Inc. + * + * Endpoint sysfs stuff + * + */ + +#include +#include +#include "usb.h" + +/* endpoint stuff */ +struct ep_object { + struct usb_endpoint_descriptor *desc; + struct usb_device *udev; + struct kobject kobj; +}; +#define to_ep_object(_kobj) \ + container_of(_kobj, struct ep_object, kobj) + +struct ep_attribute { + struct attribute attr; + ssize_t (*show)(struct usb_device *, + struct usb_endpoint_descriptor *, char *); +}; +#define to_ep_attribute(_attr) \ + container_of(_attr, struct ep_attribute, attr) + +#define EP_ATTR(_name) \ +struct ep_attribute ep_##_name = { \ + .attr = {.name = #_name, .owner = THIS_MODULE, \ + .mode = S_IRUGO}, \ + .show = show_ep_##_name} + +#define usb_ep_attr(field, format_string) \ +static ssize_t show_ep_##field(struct usb_device *udev, \ + struct usb_endpoint_descriptor *desc, \ + char *buf) \ +{ \ + return sprintf(buf, format_string, desc->field); \ +} \ +static EP_ATTR(field); + +usb_ep_attr(bLength, "%02x\n") +usb_ep_attr(bEndpointAddress, "%02x\n") +usb_ep_attr(bmAttributes, "%02x\n") +usb_ep_attr(bInterval, "%02x\n") + +static ssize_t show_ep_wMaxPacketSize(struct usb_device *udev, + struct usb_endpoint_descriptor *desc, char *buf) +{ + return sprintf(buf, "%04x\n", + le16_to_cpu(desc->wMaxPacketSize) & 0x07ff); +} +static EP_ATTR(wMaxPacketSize); + +static ssize_t show_ep_type(struct usb_device *udev, + struct usb_endpoint_descriptor *desc, char *buf) +{ + char *type = "unknown"; + + switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { + case USB_ENDPOINT_XFER_CONTROL: + type = "Control"; + break; + case USB_ENDPOINT_XFER_ISOC: + type = "Isoc"; + break; + case USB_ENDPOINT_XFER_BULK: + type = "Bulk"; + break; + case USB_ENDPOINT_XFER_INT: + type = "Interrupt"; + break; + } + return sprintf(buf, "%s\n", type); +} +static EP_ATTR(type); + +static ssize_t show_ep_interval(struct usb_device *udev, + struct usb_endpoint_descriptor *desc, char *buf) +{ + char unit; + unsigned interval = 0; + unsigned in; + + in = (desc->bEndpointAddress & USB_DIR_IN); + + switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { + case USB_ENDPOINT_XFER_CONTROL: + if (udev->speed == USB_SPEED_HIGH) /* uframes per NAK */ + interval = desc->bInterval; + break; + case USB_ENDPOINT_XFER_ISOC: + interval = 1 << (desc->bInterval - 1); + break; + case USB_ENDPOINT_XFER_BULK: + if (udev->speed == USB_SPEED_HIGH && !in) /* uframes per NAK */ + interval = desc->bInterval; + break; + case USB_ENDPOINT_XFER_INT: + if (udev->speed == USB_SPEED_HIGH) + interval = 1 << (desc->bInterval - 1); + else + interval = desc->bInterval; + break; + } + interval *= (udev->speed == USB_SPEED_HIGH) ? 125 : 1000; + if (interval % 1000) + unit = 'u'; + else { + unit = 'm'; + interval /= 1000; + } + + return sprintf(buf, "%d%cs\n", interval, unit); +} +static EP_ATTR(interval); + +static ssize_t show_ep_direction(struct usb_device *udev, + struct usb_endpoint_descriptor *desc, char *buf) +{ + char *direction; + + if ((desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_CONTROL) + direction = "both"; + else if (desc->bEndpointAddress & USB_DIR_IN) + direction = "in"; + else + direction = "out"; + return sprintf(buf, "%s\n", direction); +} +static EP_ATTR(direction); + +static struct attribute *ep_attrs[] = { + &ep_bLength.attr, + &ep_bEndpointAddress.attr, + &ep_bmAttributes.attr, + &ep_bInterval.attr, + &ep_wMaxPacketSize.attr, + &ep_type.attr, + &ep_interval.attr, + &ep_direction.attr, + NULL, +}; + +static void ep_object_release(struct kobject *kobj) +{ + kfree(to_ep_object(kobj)); +} + +static ssize_t ep_object_show(struct kobject *kobj, struct attribute *attr, + char *buf) +{ + struct ep_object *ep_obj = to_ep_object(kobj); + struct ep_attribute *ep_attr = to_ep_attribute(attr); + + return (ep_attr->show)(ep_obj->udev, ep_obj->desc, buf); +} + +static struct sysfs_ops ep_object_sysfs_ops = { + .show = ep_object_show, +}; + +static struct kobj_type ep_object_ktype = { + .release = ep_object_release, + .sysfs_ops = &ep_object_sysfs_ops, + .default_attrs = ep_attrs, +}; + +void usb_create_ep_files(struct kobject *parent, + struct usb_host_endpoint *endpoint, + struct usb_device *udev) +{ + struct ep_object *ep_obj; + struct kobject *kobj; + + ep_obj = kzalloc(sizeof(struct ep_object), GFP_KERNEL); + if (!ep_obj) + return; + + ep_obj->desc = &endpoint->desc; + ep_obj->udev = udev; + + kobj = &ep_obj->kobj; + kobject_set_name(kobj, "ep_%02x", endpoint->desc.bEndpointAddress); + kobj->parent = parent; + kobj->ktype = &ep_object_ktype; + + /* Don't use kobject_register, because it generates a hotplug event */ + kobject_init(kobj); + if (kobject_add(kobj) == 0) + endpoint->kobj = kobj; + else + kobject_put(kobj); +} + +void usb_remove_ep_files(struct usb_host_endpoint *endpoint) +{ + + if (endpoint->kobj) { + kobject_del(endpoint->kobj); + kobject_put(endpoint->kobj); + endpoint->kobj = NULL; + } +} + + diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 71d881327e8..cc18a05e577 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -15,203 +15,6 @@ #include #include "usb.h" -/* endpoint stuff */ -struct ep_object { - struct usb_endpoint_descriptor *desc; - struct usb_device *udev; - struct kobject kobj; -}; -#define to_ep_object(_kobj) \ - container_of(_kobj, struct ep_object, kobj) - -struct ep_attribute { - struct attribute attr; - ssize_t (*show)(struct usb_device *, - struct usb_endpoint_descriptor *, char *); -}; -#define to_ep_attribute(_attr) \ - container_of(_attr, struct ep_attribute, attr) - -#define EP_ATTR(_name) \ -struct ep_attribute ep_##_name = { \ - .attr = {.name = #_name, .owner = THIS_MODULE, \ - .mode = S_IRUGO}, \ - .show = show_ep_##_name} - -#define usb_ep_attr(field, format_string) \ -static ssize_t show_ep_##field(struct usb_device *udev, \ - struct usb_endpoint_descriptor *desc, \ - char *buf) \ -{ \ - return sprintf(buf, format_string, desc->field); \ -} \ -static EP_ATTR(field); - -usb_ep_attr(bLength, "%02x\n") -usb_ep_attr(bEndpointAddress, "%02x\n") -usb_ep_attr(bmAttributes, "%02x\n") -usb_ep_attr(bInterval, "%02x\n") - -static ssize_t show_ep_wMaxPacketSize(struct usb_device *udev, - struct usb_endpoint_descriptor *desc, char *buf) -{ - return sprintf(buf, "%04x\n", - le16_to_cpu(desc->wMaxPacketSize) & 0x07ff); -} -static EP_ATTR(wMaxPacketSize); - -static ssize_t show_ep_type(struct usb_device *udev, - struct usb_endpoint_descriptor *desc, char *buf) -{ - char *type = "unknown"; - - switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { - case USB_ENDPOINT_XFER_CONTROL: - type = "Control"; - break; - case USB_ENDPOINT_XFER_ISOC: - type = "Isoc"; - break; - case USB_ENDPOINT_XFER_BULK: - type = "Bulk"; - break; - case USB_ENDPOINT_XFER_INT: - type = "Interrupt"; - break; - } - return sprintf(buf, "%s\n", type); -} -static EP_ATTR(type); - -static ssize_t show_ep_interval(struct usb_device *udev, - struct usb_endpoint_descriptor *desc, char *buf) -{ - char unit; - unsigned interval = 0; - unsigned in; - - in = (desc->bEndpointAddress & USB_DIR_IN); - - switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { - case USB_ENDPOINT_XFER_CONTROL: - if (udev->speed == USB_SPEED_HIGH) /* uframes per NAK */ - interval = desc->bInterval; - break; - case USB_ENDPOINT_XFER_ISOC: - interval = 1 << (desc->bInterval - 1); - break; - case USB_ENDPOINT_XFER_BULK: - if (udev->speed == USB_SPEED_HIGH && !in) /* uframes per NAK */ - interval = desc->bInterval; - break; - case USB_ENDPOINT_XFER_INT: - if (udev->speed == USB_SPEED_HIGH) - interval = 1 << (desc->bInterval - 1); - else - interval = desc->bInterval; - break; - } - interval *= (udev->speed == USB_SPEED_HIGH) ? 125 : 1000; - if (interval % 1000) - unit = 'u'; - else { - unit = 'm'; - interval /= 1000; - } - - return sprintf(buf, "%d%cs\n", interval, unit); -} -static EP_ATTR(interval); - -static ssize_t show_ep_direction(struct usb_device *udev, - struct usb_endpoint_descriptor *desc, char *buf) -{ - char *direction; - - if ((desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == - USB_ENDPOINT_XFER_CONTROL) - direction = "both"; - else if (desc->bEndpointAddress & USB_DIR_IN) - direction = "in"; - else - direction = "out"; - return sprintf(buf, "%s\n", direction); -} -static EP_ATTR(direction); - -static struct attribute *ep_attrs[] = { - &ep_bLength.attr, - &ep_bEndpointAddress.attr, - &ep_bmAttributes.attr, - &ep_bInterval.attr, - &ep_wMaxPacketSize.attr, - &ep_type.attr, - &ep_interval.attr, - &ep_direction.attr, - NULL, -}; - -static void ep_object_release(struct kobject *kobj) -{ - kfree(to_ep_object(kobj)); -} - -static ssize_t ep_object_show(struct kobject *kobj, struct attribute *attr, - char *buf) -{ - struct ep_object *ep_obj = to_ep_object(kobj); - struct ep_attribute *ep_attr = to_ep_attribute(attr); - - return (ep_attr->show)(ep_obj->udev, ep_obj->desc, buf); -} - -static struct sysfs_ops ep_object_sysfs_ops = { - .show = ep_object_show, -}; - -static struct kobj_type ep_object_ktype = { - .release = ep_object_release, - .sysfs_ops = &ep_object_sysfs_ops, - .default_attrs = ep_attrs, -}; - -static void usb_create_ep_files(struct kobject *parent, - struct usb_host_endpoint *endpoint, - struct usb_device *udev) -{ - struct ep_object *ep_obj; - struct kobject *kobj; - - ep_obj = kzalloc(sizeof(struct ep_object), GFP_KERNEL); - if (!ep_obj) - return; - - ep_obj->desc = &endpoint->desc; - ep_obj->udev = udev; - - kobj = &ep_obj->kobj; - kobject_set_name(kobj, "ep_%02x", endpoint->desc.bEndpointAddress); - kobj->parent = parent; - kobj->ktype = &ep_object_ktype; - - /* Don't use kobject_register, because it generates a hotplug event */ - kobject_init(kobj); - if (kobject_add(kobj) == 0) - endpoint->kobj = kobj; - else - kobject_put(kobj); -} - -static void usb_remove_ep_files(struct usb_host_endpoint *endpoint) -{ - - if (endpoint->kobj) { - kobject_del(endpoint->kobj); - kobject_put(endpoint->kobj); - endpoint->kobj = NULL; - } -} - /* Active configuration fields */ #define usb_actconfig_show(field, multiplier, format_string) \ static ssize_t show_##field (struct device *dev, \ diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 4647e1ebc68..941cb397ba0 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -4,6 +4,9 @@ extern void usb_create_sysfs_dev_files (struct usb_device *dev); extern void usb_remove_sysfs_dev_files (struct usb_device *dev); extern void usb_create_sysfs_intf_files (struct usb_interface *intf); extern void usb_remove_sysfs_intf_files (struct usb_interface *intf); +extern void usb_create_ep_files(struct kobject *parent, struct usb_host_endpoint *endpoint, + struct usb_device *udev); +extern void usb_remove_ep_files(struct usb_host_endpoint *endpoint); extern void usb_disable_endpoint (struct usb_device *dev, unsigned int epaddr); extern void usb_disable_interface (struct usb_device *dev, -- cgit v1.2.3 From 36679ea59846d8f34a48f71ca1a37671ca0ad3c5 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 14 Jun 2006 12:14:34 -0700 Subject: [PATCH] USB: make usb_create_ep_files take a struct device Instead of a kobject, will make things easier in the future (don't know what I was thinking when I did this originally...) Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/endpoint.c | 4 ++-- drivers/usb/core/sysfs.c | 4 ++-- drivers/usb/core/usb.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c index 2b1697715e8..4c2fe8f723e 100644 --- a/drivers/usb/core/endpoint.c +++ b/drivers/usb/core/endpoint.c @@ -173,7 +173,7 @@ static struct kobj_type ep_object_ktype = { .default_attrs = ep_attrs, }; -void usb_create_ep_files(struct kobject *parent, +void usb_create_ep_files(struct device *parent, struct usb_host_endpoint *endpoint, struct usb_device *udev) { @@ -189,7 +189,7 @@ void usb_create_ep_files(struct kobject *parent, kobj = &ep_obj->kobj; kobject_set_name(kobj, "ep_%02x", endpoint->desc.bEndpointAddress); - kobj->parent = parent; + kobj->parent = &parent->kobj; kobj->ktype = &ep_object_ktype; /* Don't use kobject_register, because it generates a hotplug event */ diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index cc18a05e577..3f49bf51cff 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -223,7 +223,7 @@ void usb_create_sysfs_dev_files (struct usb_device *udev) if (udev->serial) device_create_file (dev, &dev_attr_serial); device_create_file (dev, &dev_attr_configuration); - usb_create_ep_files(&dev->kobj, &udev->ep0, udev); + usb_create_ep_files(dev, &udev->ep0, udev); } void usb_remove_sysfs_dev_files (struct usb_device *udev) @@ -327,7 +327,7 @@ static inline void usb_create_intf_ep_files(struct usb_interface *intf, iface_desc = intf->cur_altsetting; for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) - usb_create_ep_files(&intf->dev.kobj, &iface_desc->endpoint[i], + usb_create_ep_files(&intf->dev, &iface_desc->endpoint[i], udev); } diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 941cb397ba0..7a650c763a6 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -4,7 +4,7 @@ extern void usb_create_sysfs_dev_files (struct usb_device *dev); extern void usb_remove_sysfs_dev_files (struct usb_device *dev); extern void usb_create_sysfs_intf_files (struct usb_interface *intf); extern void usb_remove_sysfs_intf_files (struct usb_interface *intf); -extern void usb_create_ep_files(struct kobject *parent, struct usb_host_endpoint *endpoint, +extern void usb_create_ep_files(struct device *parent, struct usb_host_endpoint *endpoint, struct usb_device *udev); extern void usb_remove_ep_files(struct usb_host_endpoint *endpoint); -- cgit v1.2.3 From 9bde7497e0b54178c317fac47a18be7f948dd471 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 14 Jun 2006 12:14:34 -0700 Subject: [PATCH] USB: make endpoints real struct devices This will allow for us to give endpoints a major/minor to create a "usbfs2-like" way to access endpoints directly from userspace in an easier manner than the current usbfs provides us. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/endpoint.c | 238 ++++++++++++++++++++++++++++---------------- include/linux/usb.h | 4 +- 2 files changed, 153 insertions(+), 89 deletions(-) diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c index 4c2fe8f723e..247b5a4913a 100644 --- a/drivers/usb/core/endpoint.c +++ b/drivers/usb/core/endpoint.c @@ -14,13 +14,14 @@ #include "usb.h" /* endpoint stuff */ -struct ep_object { + +struct ep_device { struct usb_endpoint_descriptor *desc; struct usb_device *udev; - struct kobject kobj; + struct device dev; }; -#define to_ep_object(_kobj) \ - container_of(_kobj, struct ep_object, kobj) +#define to_ep_device(_dev) \ + container_of(_dev, struct ep_device, dev) struct ep_attribute { struct attribute attr; @@ -30,40 +31,37 @@ struct ep_attribute { #define to_ep_attribute(_attr) \ container_of(_attr, struct ep_attribute, attr) -#define EP_ATTR(_name) \ -struct ep_attribute ep_##_name = { \ - .attr = {.name = #_name, .owner = THIS_MODULE, \ - .mode = S_IRUGO}, \ - .show = show_ep_##_name} - #define usb_ep_attr(field, format_string) \ -static ssize_t show_ep_##field(struct usb_device *udev, \ - struct usb_endpoint_descriptor *desc, \ - char *buf) \ +static ssize_t show_ep_##field(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ { \ - return sprintf(buf, format_string, desc->field); \ + struct ep_device *ep = to_ep_device(dev); \ + return sprintf(buf, format_string, ep->desc->field); \ } \ -static EP_ATTR(field); +static DEVICE_ATTR(field, S_IRUGO, show_ep_##field, NULL); usb_ep_attr(bLength, "%02x\n") usb_ep_attr(bEndpointAddress, "%02x\n") usb_ep_attr(bmAttributes, "%02x\n") usb_ep_attr(bInterval, "%02x\n") -static ssize_t show_ep_wMaxPacketSize(struct usb_device *udev, - struct usb_endpoint_descriptor *desc, char *buf) +static ssize_t show_ep_wMaxPacketSize(struct device *dev, + struct device_attribute *attr, char *buf) { + struct ep_device *ep = to_ep_device(dev); return sprintf(buf, "%04x\n", - le16_to_cpu(desc->wMaxPacketSize) & 0x07ff); + le16_to_cpu(ep->desc->wMaxPacketSize) & 0x07ff); } -static EP_ATTR(wMaxPacketSize); +static DEVICE_ATTR(wMaxPacketSize, S_IRUGO, show_ep_wMaxPacketSize, NULL); -static ssize_t show_ep_type(struct usb_device *udev, - struct usb_endpoint_descriptor *desc, char *buf) +static ssize_t show_ep_type(struct device *dev, struct device_attribute *attr, + char *buf) { + struct ep_device *ep = to_ep_device(dev); char *type = "unknown"; - switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { + switch (ep->desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { case USB_ENDPOINT_XFER_CONTROL: type = "Control"; break; @@ -79,37 +77,38 @@ static ssize_t show_ep_type(struct usb_device *udev, } return sprintf(buf, "%s\n", type); } -static EP_ATTR(type); +static DEVICE_ATTR(type, S_IRUGO, show_ep_type, NULL); -static ssize_t show_ep_interval(struct usb_device *udev, - struct usb_endpoint_descriptor *desc, char *buf) +static ssize_t show_ep_interval(struct device *dev, + struct device_attribute *attr, char *buf) { + struct ep_device *ep = to_ep_device(dev); char unit; unsigned interval = 0; unsigned in; - in = (desc->bEndpointAddress & USB_DIR_IN); + in = (ep->desc->bEndpointAddress & USB_DIR_IN); - switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { + switch (ep->desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { case USB_ENDPOINT_XFER_CONTROL: - if (udev->speed == USB_SPEED_HIGH) /* uframes per NAK */ - interval = desc->bInterval; + if (ep->udev->speed == USB_SPEED_HIGH) /* uframes per NAK */ + interval = ep->desc->bInterval; break; case USB_ENDPOINT_XFER_ISOC: - interval = 1 << (desc->bInterval - 1); + interval = 1 << (ep->desc->bInterval - 1); break; case USB_ENDPOINT_XFER_BULK: - if (udev->speed == USB_SPEED_HIGH && !in) /* uframes per NAK */ - interval = desc->bInterval; + if (ep->udev->speed == USB_SPEED_HIGH && !in) /* uframes per NAK */ + interval = ep->desc->bInterval; break; case USB_ENDPOINT_XFER_INT: - if (udev->speed == USB_SPEED_HIGH) - interval = 1 << (desc->bInterval - 1); + if (ep->udev->speed == USB_SPEED_HIGH) + interval = 1 << (ep->desc->bInterval - 1); else - interval = desc->bInterval; + interval = ep->desc->bInterval; break; } - interval *= (udev->speed == USB_SPEED_HIGH) ? 125 : 1000; + interval *= (ep->udev->speed == USB_SPEED_HIGH) ? 125 : 1000; if (interval % 1000) unit = 'u'; else { @@ -119,95 +118,158 @@ static ssize_t show_ep_interval(struct usb_device *udev, return sprintf(buf, "%d%cs\n", interval, unit); } -static EP_ATTR(interval); +static DEVICE_ATTR(interval, S_IRUGO, show_ep_interval, NULL); -static ssize_t show_ep_direction(struct usb_device *udev, - struct usb_endpoint_descriptor *desc, char *buf) +static ssize_t show_ep_direction(struct device *dev, + struct device_attribute *attr, char *buf) { + struct ep_device *ep = to_ep_device(dev); char *direction; - if ((desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + if ((ep->desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_CONTROL) direction = "both"; - else if (desc->bEndpointAddress & USB_DIR_IN) + else if (ep->desc->bEndpointAddress & USB_DIR_IN) direction = "in"; else direction = "out"; return sprintf(buf, "%s\n", direction); } -static EP_ATTR(direction); - -static struct attribute *ep_attrs[] = { - &ep_bLength.attr, - &ep_bEndpointAddress.attr, - &ep_bmAttributes.attr, - &ep_bInterval.attr, - &ep_wMaxPacketSize.attr, - &ep_type.attr, - &ep_interval.attr, - &ep_direction.attr, +static DEVICE_ATTR(direction, S_IRUGO, show_ep_direction, NULL); + +static struct attribute *ep_dev_attrs[] = { + &dev_attr_bLength.attr, + &dev_attr_bEndpointAddress.attr, + &dev_attr_bmAttributes.attr, + &dev_attr_bInterval.attr, + &dev_attr_wMaxPacketSize.attr, + &dev_attr_interval.attr, + &dev_attr_type.attr, + &dev_attr_direction.attr, NULL, }; +static struct attribute_group ep_dev_attr_grp = { + .attrs = ep_dev_attrs, +}; -static void ep_object_release(struct kobject *kobj) +static struct endpoint_class { + struct kref kref; + struct class *class; +} *ep_class; + +static int init_endpoint_class(void) { - kfree(to_ep_object(kobj)); + int result = 0; + + if (ep_class != NULL) { + kref_get(&ep_class->kref); + goto exit; + } + + ep_class = kmalloc(sizeof(*ep_class), GFP_KERNEL); + if (!ep_class) { + result = -ENOMEM; + goto exit; + } + + kref_init(&ep_class->kref); + ep_class->class = class_create(THIS_MODULE, "usb_endpoint"); + if (IS_ERR(ep_class->class)) { + result = IS_ERR(ep_class->class); + kfree(ep_class); + ep_class = NULL; + goto exit; + } + +exit: + return result; } -static ssize_t ep_object_show(struct kobject *kobj, struct attribute *attr, - char *buf) +static void release_endpoint_class(struct kref *kref) { - struct ep_object *ep_obj = to_ep_object(kobj); - struct ep_attribute *ep_attr = to_ep_attribute(attr); + /* Ok, we cheat as we know we only have one ep_class */ + class_destroy(ep_class->class); + kfree(ep_class); + ep_class = NULL; +} - return (ep_attr->show)(ep_obj->udev, ep_obj->desc, buf); +static void destroy_endpoint_class(void) +{ + if (ep_class) + kref_put(&ep_class->kref, release_endpoint_class); } -static struct sysfs_ops ep_object_sysfs_ops = { - .show = ep_object_show, -}; +static void ep_device_release(struct device *dev) +{ + struct ep_device *ep_dev = to_ep_device(dev); -static struct kobj_type ep_object_ktype = { - .release = ep_object_release, - .sysfs_ops = &ep_object_sysfs_ops, - .default_attrs = ep_attrs, -}; + dev_dbg(dev, "%s called for %s\n", __FUNCTION__, dev->bus_id); + kfree(ep_dev); +} void usb_create_ep_files(struct device *parent, struct usb_host_endpoint *endpoint, struct usb_device *udev) { - struct ep_object *ep_obj; - struct kobject *kobj; + char name[8]; + struct ep_device *ep_dev; + int minor; + int retval; + + retval = init_endpoint_class(); + if (retval) + goto exit; - ep_obj = kzalloc(sizeof(struct ep_object), GFP_KERNEL); - if (!ep_obj) - return; + ep_dev = kzalloc(sizeof(*ep_dev), GFP_KERNEL); + if (!ep_dev) { + retval = -ENOMEM; + goto exit; + } - ep_obj->desc = &endpoint->desc; - ep_obj->udev = udev; + /* fun calculation to determine the minor of this endpoint */ + minor = (((udev->bus->busnum - 1) * 128) * 16) + (udev->devnum - 1); - kobj = &ep_obj->kobj; - kobject_set_name(kobj, "ep_%02x", endpoint->desc.bEndpointAddress); - kobj->parent = &parent->kobj; - kobj->ktype = &ep_object_ktype; + ep_dev->desc = &endpoint->desc; + ep_dev->udev = udev; + ep_dev->dev.devt = MKDEV(442, minor); // FIXME fake number... + ep_dev->dev.class = ep_class->class; + ep_dev->dev.parent = parent; + ep_dev->dev.release = ep_device_release; + snprintf(ep_dev->dev.bus_id, BUS_ID_SIZE, "usbdev%d.%d_ep%02x", + udev->bus->busnum, udev->devnum, + endpoint->desc.bEndpointAddress); - /* Don't use kobject_register, because it generates a hotplug event */ - kobject_init(kobj); - if (kobject_add(kobj) == 0) - endpoint->kobj = kobj; - else - kobject_put(kobj); + retval = device_register(&ep_dev->dev); + if (retval) + goto error; + sysfs_create_group(&ep_dev->dev.kobj, &ep_dev_attr_grp); + + endpoint->ep_dev = ep_dev; + + /* create the symlink to the old-style "ep_XX" directory */ + sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress); + sysfs_create_link(&parent->kobj, &endpoint->ep_dev->dev.kobj, name); + +exit: + return; +error: + kfree(ep_dev); + return; } void usb_remove_ep_files(struct usb_host_endpoint *endpoint) { - if (endpoint->kobj) { - kobject_del(endpoint->kobj); - kobject_put(endpoint->kobj); - endpoint->kobj = NULL; + if (endpoint->ep_dev) { + char name[8]; + + sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress); + sysfs_remove_link(&endpoint->ep_dev->dev.parent->kobj, name); + sysfs_remove_group(&endpoint->ep_dev->dev.kobj, &ep_dev_attr_grp); + device_unregister(&endpoint->ep_dev->dev); + endpoint->ep_dev = NULL; } + destroy_endpoint_class(); } diff --git a/include/linux/usb.h b/include/linux/usb.h index 5ad30cefe7b..46956a72de5 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -40,6 +40,8 @@ struct usb_driver; * Devices may also have class-specific or vendor-specific descriptors. */ +struct ep_device; + /** * struct usb_host_endpoint - host-side endpoint descriptor and queue * @desc: descriptor for this endpoint, wMaxPacketSize in native byteorder @@ -57,7 +59,7 @@ struct usb_host_endpoint { struct usb_endpoint_descriptor desc; struct list_head urb_list; void *hcpriv; - struct kobject *kobj; /* For sysfs info */ + struct ep_device *ep_dev; /* For sysfs info */ unsigned char *extra; /* Extra descriptors */ int extralen; -- cgit v1.2.3 From c182274ffe1277f4e7c564719a696a37cacf74ea Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 19 Jun 2006 23:59:31 -0700 Subject: [PATCH] USB: move usb_device_class class devices to be real devices This moves the usb class devices that control the usbfs nodes to show up in the proper place in the larger device tree. No userspace changes is needed, this is compatible due to the symlinks generated by the driver core. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 20 ++++++++++---------- include/linux/usb.h | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 2eda52fc1eb..3f8e06279c9 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -515,19 +515,19 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, unsig static struct usb_device *usbdev_lookup_minor(int minor) { - struct class_device *class_dev; - struct usb_device *dev = NULL; + struct device *device; + struct usb_device *udev = NULL; down(&usb_device_class->sem); - list_for_each_entry(class_dev, &usb_device_class->children, node) { - if (class_dev->devt == MKDEV(USB_DEVICE_MAJOR, minor)) { - dev = class_dev->class_data; + list_for_each_entry(device, &usb_device_class->devices, node) { + if (device->devt == MKDEV(USB_DEVICE_MAJOR, minor)) { + udev = device->platform_data; break; } } up(&usb_device_class->sem); - return dev; + return udev; }; /* @@ -1580,16 +1580,16 @@ static void usbdev_add(struct usb_device *dev) { int minor = ((dev->bus->busnum-1) * 128) + (dev->devnum-1); - dev->class_dev = class_device_create(usb_device_class, NULL, - MKDEV(USB_DEVICE_MAJOR, minor), &dev->dev, + dev->usbfs_dev = device_create(usb_device_class, &dev->dev, + MKDEV(USB_DEVICE_MAJOR, minor), "usbdev%d.%d", dev->bus->busnum, dev->devnum); - dev->class_dev->class_data = dev; + dev->usbfs_dev->platform_data = dev; } static void usbdev_remove(struct usb_device *dev) { - class_device_unregister(dev->class_dev); + device_unregister(dev->usbfs_dev); } static int usbdev_notify(struct notifier_block *self, unsigned long action, diff --git a/include/linux/usb.h b/include/linux/usb.h index 46956a72de5..b69b6cfb0bd 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -360,7 +360,7 @@ struct usb_device { char *serial; /* iSerialNumber string, if present */ struct list_head filelist; - struct class_device *class_dev; + struct device *usbfs_dev; struct dentry *usbfs_dentry; /* usbfs dentry entry for the device */ /* -- cgit v1.2.3 From bd00949647ddcea47ce4ea8bb2cfcfc98ebf9f2a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 20 Jun 2006 13:09:50 -0700 Subject: [PATCH] USB: convert usb class devices to real devices Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/file.c | 13 ++++++------- include/linux/usb.h | 5 +++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c index b263a54a13c..70898716dd9 100644 --- a/drivers/usb/core/file.c +++ b/drivers/usb/core/file.c @@ -158,14 +158,13 @@ int usb_register_dev(struct usb_interface *intf, ++temp; else temp = name; - intf->class_dev = class_device_create(usb_class, NULL, - MKDEV(USB_MAJOR, minor), - &intf->dev, "%s", temp); - if (IS_ERR(intf->class_dev)) { + intf->usb_dev = device_create(usb_class, &intf->dev, + MKDEV(USB_MAJOR, minor), "%s", temp); + if (IS_ERR(intf->usb_dev)) { spin_lock (&minor_lock); usb_minors[intf->minor] = NULL; spin_unlock (&minor_lock); - retval = PTR_ERR(intf->class_dev); + retval = PTR_ERR(intf->usb_dev); } exit: return retval; @@ -206,8 +205,8 @@ void usb_deregister_dev(struct usb_interface *intf, spin_unlock (&minor_lock); snprintf(name, BUS_ID_SIZE, class_driver->name, intf->minor - minor_base); - class_device_destroy(usb_class, MKDEV(USB_MAJOR, intf->minor)); - intf->class_dev = NULL; + device_destroy(usb_class, MKDEV(USB_MAJOR, intf->minor)); + intf->usb_dev = NULL; intf->minor = -1; } EXPORT_SYMBOL(usb_deregister_dev); diff --git a/include/linux/usb.h b/include/linux/usb.h index b69b6cfb0bd..8dead32e7eb 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -103,7 +103,8 @@ enum usb_interface_condition { * @condition: binding state of the interface: not bound, binding * (in probe()), bound to a driver, or unbinding (in disconnect()) * @dev: driver model's view of this device - * @class_dev: driver model's class view of this device. + * @usb_dev: if an interface is bound to the USB major, this will point + * to the sysfs representation for that device. * * USB device drivers attach to interfaces on a physical device. Each * interface encapsulates a single high level function, such as feeding @@ -143,7 +144,7 @@ struct usb_interface { * bound to */ enum usb_interface_condition condition; /* state of binding */ struct device dev; /* interface specific device info */ - struct class_device *class_dev; + struct device *usb_dev; /* pointer to the usb class's device, if any */ }; #define to_usb_interface(d) container_of(d, struct usb_interface, dev) #define interface_to_usbdev(intf) \ -- cgit v1.2.3 From 43104f1da88f5335e9a45695df92a735ad550dda Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 20 Jun 2006 15:14:07 -0700 Subject: [PATCH] USB: only make /sys/class/usb show up when there is something in it Now /sys/class/usb is dynamically created when we have something to put in it, and removed when all devices go away. Just trying to cut down on the clutter in sysfs... Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/file.c | 70 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 54 insertions(+), 16 deletions(-) diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c index 70898716dd9..f65b193cde3 100644 --- a/drivers/usb/core/file.c +++ b/drivers/usb/core/file.c @@ -61,33 +61,66 @@ static struct file_operations usb_fops = { .open = usb_open, }; -static struct class *usb_class; +static struct usb_class { + struct kref kref; + struct class *class; +} *usb_class; -int usb_major_init(void) +static int init_usb_class(void) { - int error; + int result = 0; - error = register_chrdev(USB_MAJOR, "usb", &usb_fops); - if (error) { - err("unable to get major %d for usb devices", USB_MAJOR); - goto out; + if (usb_class != NULL) { + kref_get(&usb_class->kref); + goto exit; + } + + usb_class = kmalloc(sizeof(*usb_class), GFP_KERNEL); + if (!usb_class) { + result = -ENOMEM; + goto exit; } - usb_class = class_create(THIS_MODULE, "usb"); - if (IS_ERR(usb_class)) { - error = PTR_ERR(usb_class); + kref_init(&usb_class->kref); + usb_class->class = class_create(THIS_MODULE, "usb"); + if (IS_ERR(usb_class->class)) { + result = IS_ERR(usb_class->class); err("class_create failed for usb devices"); - unregister_chrdev(USB_MAJOR, "usb"); - goto out; + kfree(usb_class); + usb_class = NULL; } -out: +exit: + return result; +} + +static void release_usb_class(struct kref *kref) +{ + /* Ok, we cheat as we know we only have one usb_class */ + class_destroy(usb_class->class); + kfree(usb_class); + usb_class = NULL; +} + +static void destroy_usb_class(void) +{ + if (usb_class) + kref_put(&usb_class->kref, release_usb_class); +} + +int usb_major_init(void) +{ + int error; + + error = register_chrdev(USB_MAJOR, "usb", &usb_fops); + if (error) + err("unable to get major %d for usb devices", USB_MAJOR); + return error; } void usb_major_cleanup(void) { - class_destroy(usb_class); unregister_chrdev(USB_MAJOR, "usb"); } @@ -146,6 +179,10 @@ int usb_register_dev(struct usb_interface *intf, } spin_unlock (&minor_lock); + if (retval) + goto exit; + + retval = init_usb_class(); if (retval) goto exit; @@ -158,7 +195,7 @@ int usb_register_dev(struct usb_interface *intf, ++temp; else temp = name; - intf->usb_dev = device_create(usb_class, &intf->dev, + intf->usb_dev = device_create(usb_class->class, &intf->dev, MKDEV(USB_MAJOR, minor), "%s", temp); if (IS_ERR(intf->usb_dev)) { spin_lock (&minor_lock); @@ -205,9 +242,10 @@ void usb_deregister_dev(struct usb_interface *intf, spin_unlock (&minor_lock); snprintf(name, BUS_ID_SIZE, class_driver->name, intf->minor - minor_base); - device_destroy(usb_class, MKDEV(USB_MAJOR, intf->minor)); + device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor)); intf->usb_dev = NULL; intf->minor = -1; + destroy_usb_class(); } EXPORT_SYMBOL(usb_deregister_dev); -- cgit v1.2.3 From 4ec223d02f4d5f5a3129edc0e3d22550d6ac8a32 Mon Sep 17 00:00:00 2001 From: Venkatesh Pallipadi Date: Wed, 21 Jun 2006 15:18:34 -0700 Subject: [CPUFREQ] Fix ondemand vs suspend deadlock Rootcaused the bug to a deadlock in cpufreq and ondemand. Due to non-existent ordering between cpu_hotplug lock and dbs_mutex. Basically a race condition between cpu_down() and do_dbs_timer(). cpu_down() flow: * cpu_down() call for CPU 1 * Takes hot plug lock * Calls pre down notifier * cpufreq notifier handler calls cpufreq_driver_target() which takes cpu_hotplug lock again. OK as cpu_hotplug lock is recursive in same process context * CPU 1 goes down * Calls post down notifier * cpufreq notifier handler calls ondemand event stop which takes dbs_mutex So, cpu_hotplug lock is taken before dbs_mutex in this flow. do_dbs_timer is triggerred by a periodic timer event. It first takes dbs_mutex and then takes cpu_hotplug lock in cpufreq_driver_target(). Note the reverse order here compared to above. So, if this timer event happens at right moment during cpu_down, system will deadlok. Attached patch fixes the issue for both ondemand and conservative. Signed-off-by: Venkatesh Pallipadi Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq_conservative.c | 12 ++++++++++++ drivers/cpufreq/cpufreq_ondemand.c | 12 ++++++++++++ 2 files changed, 24 insertions(+) diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index e07a35487bd..8878a154ed4 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -72,6 +72,14 @@ static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info); static unsigned int dbs_enable; /* number of CPUs using this policy */ +/* + * DEADLOCK ALERT! There is a ordering requirement between cpu_hotplug + * lock and dbs_mutex. cpu_hotplug lock should always be held before + * dbs_mutex. If any function that can potentially take cpu_hotplug lock + * (like __cpufreq_driver_target()) is being called with dbs_mutex taken, then + * cpu_hotplug lock should be taken before that. Note that cpu_hotplug lock + * is recursive for the same process. -Venki + */ static DEFINE_MUTEX (dbs_mutex); static DECLARE_WORK (dbs_work, do_dbs_timer, NULL); @@ -414,12 +422,14 @@ static void dbs_check_cpu(int cpu) static void do_dbs_timer(void *data) { int i; + lock_cpu_hotplug(); mutex_lock(&dbs_mutex); for_each_online_cpu(i) dbs_check_cpu(i); schedule_delayed_work(&dbs_work, usecs_to_jiffies(dbs_tuners_ins.sampling_rate)); mutex_unlock(&dbs_mutex); + unlock_cpu_hotplug(); } static inline void dbs_timer_init(void) @@ -514,6 +524,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, break; case CPUFREQ_GOV_LIMITS: + lock_cpu_hotplug(); mutex_lock(&dbs_mutex); if (policy->max < this_dbs_info->cur_policy->cur) __cpufreq_driver_target( @@ -524,6 +535,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, this_dbs_info->cur_policy, policy->min, CPUFREQ_RELATION_L); mutex_unlock(&dbs_mutex); + unlock_cpu_hotplug(); break; } return 0; diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 3e6ffcaa5af..4d308410b60 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -71,6 +71,14 @@ static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info); static unsigned int dbs_enable; /* number of CPUs using this policy */ +/* + * DEADLOCK ALERT! There is a ordering requirement between cpu_hotplug + * lock and dbs_mutex. cpu_hotplug lock should always be held before + * dbs_mutex. If any function that can potentially take cpu_hotplug lock + * (like __cpufreq_driver_target()) is being called with dbs_mutex taken, then + * cpu_hotplug lock should be taken before that. Note that cpu_hotplug lock + * is recursive for the same process. -Venki + */ static DEFINE_MUTEX (dbs_mutex); static DECLARE_WORK (dbs_work, do_dbs_timer, NULL); @@ -363,12 +371,14 @@ static void dbs_check_cpu(int cpu) static void do_dbs_timer(void *data) { int i; + lock_cpu_hotplug(); mutex_lock(&dbs_mutex); for_each_online_cpu(i) dbs_check_cpu(i); queue_delayed_work(dbs_workq, &dbs_work, usecs_to_jiffies(dbs_tuners_ins.sampling_rate)); mutex_unlock(&dbs_mutex); + unlock_cpu_hotplug(); } static inline void dbs_timer_init(void) @@ -469,6 +479,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, break; case CPUFREQ_GOV_LIMITS: + lock_cpu_hotplug(); mutex_lock(&dbs_mutex); if (policy->max < this_dbs_info->cur_policy->cur) __cpufreq_driver_target( @@ -479,6 +490,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, this_dbs_info->cur_policy, policy->min, CPUFREQ_RELATION_L); mutex_unlock(&dbs_mutex); + unlock_cpu_hotplug(); break; } return 0; -- cgit v1.2.3 From d6551e884cf66de072b81f8b6d23259462c40baf Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 21 Jun 2006 13:31:52 +0100 Subject: [ARM] Add thread_notify infrastructure Some machine classes need to allow VFP support to be built into the kernel, but still allow the kernel to run even though VFP isn't present. Unfortunately, the kernel hard-codes VFP instructions into the thread switch, which prevents this being run-time selectable. Solve this by introducing a notifier which things such as VFP can hook into to be informed of events which affect the VFP subsystem (eg, creation and destruction of threads, switches between threads.) Signed-off-by: Russell King --- arch/arm/kernel/entry-armv.S | 24 +++++++------- arch/arm/kernel/iwmmxt.S | 2 +- arch/arm/kernel/process.c | 24 ++++++-------- arch/arm/nwfpe/fpmodule.c | 25 +++++++++++---- arch/arm/vfp/vfpmodule.c | 71 ++++++++++++++++++++++++++--------------- include/asm-arm/thread_notify.h | 48 ++++++++++++++++++++++++++++ 6 files changed, 135 insertions(+), 59 deletions(-) create mode 100644 include/asm-arm/thread_notify.h diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index ab8e600c18c..86c92523a34 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -20,6 +20,7 @@ #include #include #include +#include #include "entry-header.S" @@ -560,10 +561,8 @@ ENTRY(__switch_to) add ip, r1, #TI_CPU_SAVE ldr r3, [r2, #TI_TP_VALUE] stmia ip!, {r4 - sl, fp, sp, lr} @ Store most regs on stack -#ifndef CONFIG_MMU - add r2, r2, #TI_CPU_DOMAIN -#else - ldr r6, [r2, #TI_CPU_DOMAIN]! +#ifdef CONFIG_MMU + ldr r6, [r2, #TI_CPU_DOMAIN] #endif #if __LINUX_ARM_ARCH__ >= 6 #ifdef CONFIG_CPU_32v6K @@ -585,21 +584,20 @@ ENTRY(__switch_to) #ifdef CONFIG_MMU mcr p15, 0, r6, c3, c0, 0 @ Set domain register #endif -#ifdef CONFIG_VFP - @ Always disable VFP so we can lazily save/restore the old - @ state. This occurs in the context of the previous thread. - VFPFMRX r4, FPEXC - bic r4, r4, #FPEXC_ENABLE - VFPFMXR FPEXC, r4 -#endif #if defined(CONFIG_IWMMXT) bl iwmmxt_task_switch #elif defined(CONFIG_CPU_XSCALE) - add r4, r2, #40 @ cpu_context_save->extra + add r4, r2, #TI_CPU_DOMAIN + 40 @ cpu_context_save->extra ldmib r4, {r4, r5} mar acc0, r4, r5 #endif - ldmib r2, {r4 - sl, fp, sp, pc} @ Load all regs saved previously + mov r5, r0 + add r4, r2, #TI_CPU_SAVE + ldr r0, =thread_notify_head + mov r1, #THREAD_NOTIFY_SWITCH + bl atomic_notifier_call_chain + mov r0, r5 + ldmia r4, {r4 - sl, fp, sp, pc} @ Load all regs saved previously __INIT diff --git a/arch/arm/kernel/iwmmxt.S b/arch/arm/kernel/iwmmxt.S index 24c7b0477a0..af9e0ae952d 100644 --- a/arch/arm/kernel/iwmmxt.S +++ b/arch/arm/kernel/iwmmxt.S @@ -285,7 +285,7 @@ ENTRY(iwmmxt_task_switch) bne 1f @ yes: block them for next task ldr r5, =concan_owner - add r6, r2, #(TI_IWMMXT_STATE - TI_CPU_DOMAIN) @ get next task Concan save area + add r6, r2, #TI_IWMMXT_STATE @ get next task Concan save area ldr r5, [r5] @ get current Concan owner teq r5, r6 @ next task owns it? movne pc, lr @ no: leave Concan disabled diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 17c38dbf2f3..e1c77ee885a 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -338,13 +339,9 @@ void exit_thread(void) { } -static void default_fp_init(union fp_state *fp) -{ - memset(fp, 0, sizeof(union fp_state)); -} +ATOMIC_NOTIFIER_HEAD(thread_notify_head); -void (*fp_init)(union fp_state *) = default_fp_init; -EXPORT_SYMBOL(fp_init); +EXPORT_SYMBOL_GPL(thread_notify_head); void flush_thread(void) { @@ -353,22 +350,21 @@ void flush_thread(void) memset(thread->used_cp, 0, sizeof(thread->used_cp)); memset(&tsk->thread.debug, 0, sizeof(struct debug_info)); + memset(&thread->fpstate, 0, sizeof(union fp_state)); + + thread_notify(THREAD_NOTIFY_FLUSH, thread); #if defined(CONFIG_IWMMXT) iwmmxt_task_release(thread); -#endif - fp_init(&thread->fpstate); -#if defined(CONFIG_VFP) - vfp_flush_thread(&thread->vfpstate); #endif } void release_thread(struct task_struct *dead_task) { -#if defined(CONFIG_VFP) - vfp_release_thread(&task_thread_info(dead_task)->vfpstate); -#endif + struct thread_info *thread = task_thread_info(dead_task); + + thread_notify(THREAD_NOTIFY_RELEASE, thread); #if defined(CONFIG_IWMMXT) - iwmmxt_task_release(task_thread_info(dead_task)); + iwmmxt_task_release(thread); #endif } diff --git a/arch/arm/nwfpe/fpmodule.c b/arch/arm/nwfpe/fpmodule.c index 2dfe1ac42ee..7d977d23f02 100644 --- a/arch/arm/nwfpe/fpmodule.c +++ b/arch/arm/nwfpe/fpmodule.c @@ -33,7 +33,8 @@ #include #include #include -/* XXX */ + +#include #include "softfloat.h" #include "fpopcode.h" @@ -56,16 +57,28 @@ void fp_send_sig(unsigned long sig, struct task_struct *p, int priv); extern char fpe_type[]; #endif +static int nwfpe_notify(struct notifier_block *self, unsigned long cmd, void *v) +{ + struct thread_info *thread = v; + + if (cmd == THREAD_NOTIFY_FLUSH) + nwfpe_init_fpa(&thread->fpstate); + + return NOTIFY_DONE; +} + +static struct notifier_block nwfpe_notifier_block = { + .notifier_call = nwfpe_notify, +}; + /* kernel function prototypes required */ void fp_setup(void); /* external declarations for saved kernel symbols */ extern void (*kern_fp_enter)(void); -extern void (*fp_init)(union fp_state *); /* Original value of fp_enter from kernel before patched by fpe_init. */ static void (*orig_fp_enter)(void); -static void (*orig_fp_init)(union fp_state *); /* forward declarations */ extern void nwfpe_enter(void); @@ -88,20 +101,20 @@ static int __init fpe_init(void) printk(KERN_WARNING "NetWinder Floating Point Emulator V0.97 (" NWFPE_BITS " precision)\n"); + thread_register_notifier(&nwfpe_notifier_block); + /* Save pointer to the old FP handler and then patch ourselves in */ orig_fp_enter = kern_fp_enter; - orig_fp_init = fp_init; kern_fp_enter = nwfpe_enter; - fp_init = nwfpe_init_fpa; return 0; } static void __exit fpe_exit(void) { + thread_unregister_notifier(&nwfpe_notifier_block); /* Restore the values we saved earlier. */ kern_fp_enter = orig_fp_enter; - fp_init = orig_fp_init; } /* diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index 03486be0419..2476f4c2e76 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c @@ -15,6 +15,8 @@ #include #include #include + +#include #include #include "vfpinstr.h" @@ -36,38 +38,55 @@ union vfp_state *last_VFP_context; */ unsigned int VFP_arch; -/* - * Per-thread VFP initialisation. - */ -void vfp_flush_thread(union vfp_state *vfp) +static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v) { - memset(vfp, 0, sizeof(union vfp_state)); + struct thread_info *thread = v; + union vfp_state *vfp = &thread->vfpstate; - vfp->hard.fpexc = FPEXC_ENABLE; - vfp->hard.fpscr = FPSCR_ROUND_NEAREST; + switch (cmd) { + case THREAD_NOTIFY_FLUSH: + /* + * Per-thread VFP initialisation. + */ + memset(vfp, 0, sizeof(union vfp_state)); - /* - * Disable VFP to ensure we initialise it first. - */ - fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_ENABLE); + vfp->hard.fpexc = FPEXC_ENABLE; + vfp->hard.fpscr = FPSCR_ROUND_NEAREST; - /* - * Ensure we don't try to overwrite our newly initialised - * state information on the first fault. - */ - if (last_VFP_context == vfp) - last_VFP_context = NULL; -} + /* + * Disable VFP to ensure we initialise it first. + */ + fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_ENABLE); -/* - * Per-thread VFP cleanup. - */ -void vfp_release_thread(union vfp_state *vfp) -{ - if (last_VFP_context == vfp) - last_VFP_context = NULL; + /* + * FALLTHROUGH: Ensure we don't try to overwrite our newly + * initialised state information on the first fault. + */ + + case THREAD_NOTIFY_RELEASE: + /* + * Per-thread VFP cleanup. + */ + if (last_VFP_context == vfp) + last_VFP_context = NULL; + break; + + case THREAD_NOTIFY_SWITCH: + /* + * Always disable VFP so we can lazily save/restore the + * old state. + */ + fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_ENABLE); + break; + } + + return NOTIFY_DONE; } +static struct notifier_block vfp_notifier_block = { + .notifier_call = vfp_notifier, +}; + /* * Raise a SIGFPE for the current process. * sicode describes the signal being raised. @@ -281,6 +300,8 @@ static int __init vfp_init(void) (vfpsid & FPSID_VARIANT_MASK) >> FPSID_VARIANT_BIT, (vfpsid & FPSID_REV_MASK) >> FPSID_REV_BIT); vfp_vector = vfp_support_entry; + + thread_register_notifier(&vfp_notifier_block); } return 0; } diff --git a/include/asm-arm/thread_notify.h b/include/asm-arm/thread_notify.h new file mode 100644 index 00000000000..8866e521684 --- /dev/null +++ b/include/asm-arm/thread_notify.h @@ -0,0 +1,48 @@ +/* + * linux/include/asm-arm/thread_notify.h + * + * Copyright (C) 2006 Russell King. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef ASMARM_THREAD_NOTIFY_H +#define ASMARM_THREAD_NOTIFY_H + +#ifdef __KERNEL__ + +#ifndef __ASSEMBLY__ + +#include +#include + +static inline int thread_register_notifier(struct notifier_block *n) +{ + extern struct atomic_notifier_head thread_notify_head; + return atomic_notifier_chain_register(&thread_notify_head, n); +} + +static inline void thread_unregister_notifier(struct notifier_block *n) +{ + extern struct atomic_notifier_head thread_notify_head; + atomic_notifier_chain_unregister(&thread_notify_head, n); +} + +static inline void thread_notify(unsigned long rc, struct thread_info *thread) +{ + extern struct atomic_notifier_head thread_notify_head; + atomic_notifier_call_chain(&thread_notify_head, rc, thread); +} + +#endif + +/* + * These are the reason codes for the thread notifier. + */ +#define THREAD_NOTIFY_FLUSH 0 +#define THREAD_NOTIFY_RELEASE 1 +#define THREAD_NOTIFY_SWITCH 2 + +#endif +#endif -- cgit v1.2.3 From 1a6be26d5b1a86f66ef60e5b73bae64d50873724 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 21 Jun 2006 13:51:41 +0100 Subject: [ARM] Enable VFP to be built when non-VFP capable CPUs are selected Since we pass flags to the compiler to control code generation based on the least capable selected CPU, if we want to include VFP support, we must tweak the assembler flags to allow the VFP instructions. Moreover, we must not use the mrrc/mcrr versions since these will not be recognised by the assembler. We do not convert all instructions to the VFP-equivalent (yet) since binutils appears to barf on "fmrx rn, fpinst" and doesn't provide any other way (other than using the mrc equivalent) to encode this instruction - which is rather a problem when you have a VFP implementation which requires these instructions. Signed-off-by: Russell King --- arch/arm/vfp/Makefile | 5 ++++- arch/arm/vfp/vfphw.S | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/arch/arm/vfp/Makefile b/arch/arm/vfp/Makefile index afabac31dd1..7e136e77971 100644 --- a/arch/arm/vfp/Makefile +++ b/arch/arm/vfp/Makefile @@ -7,6 +7,9 @@ # EXTRA_CFLAGS := -DDEBUG # EXTRA_AFLAGS := -DDEBUG +AFLAGS :=$(AFLAGS:-msoft-float=-Wa,-mfpu=softvfp+vfp) +LDFLAGS +=--no-warn-mismatch + obj-y += vfp.o -vfp-$(CONFIG_VFP) += entry.o vfpmodule.o vfphw.o vfpsingle.o vfpdouble.o +vfp-$(CONFIG_VFP) += vfpmodule.o entry.o vfphw.o vfpsingle.o vfpdouble.o diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S index a3f65b47aea..eb683cd7716 100644 --- a/arch/arm/vfp/vfphw.S +++ b/arch/arm/vfp/vfphw.S @@ -192,7 +192,7 @@ vfp_get_double: add pc, pc, r0, lsl #3 mov r0, r0 .irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 - mrrc p11, 1, r0, r1, c\dr @ fmrrd r0, r1, d\dr + fmrrd r0, r1, d\dr mov pc, lr .endr @@ -206,6 +206,6 @@ vfp_put_double: add pc, pc, r0, lsl #3 mov r0, r0 .irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 - mcrr p11, 1, r1, r2, c\dr @ fmdrr r1, r2, d\dr + fmdrr d\dr, r1, r2 mov pc, lr .endr -- cgit v1.2.3 From e9931b5da6247c18cbf4db8e9e924c980758f41a Mon Sep 17 00:00:00 2001 From: Vitaly Wool Date: Thu, 22 Jun 2006 10:26:20 +0100 Subject: [ARM] 3622/1: pnx4008: remove clk_use/clk_unuse Patch from Vitaly Wool clk_use/clk_unuse functions are no longer needed, so removing those from arch/arm/mach-pnx4008/clock.c. Also, the order of functions is rearranged a bit, to avoid forward declarations. Signed-off-by: Vitaly Wool Signed-off-by: Russell King --- arch/arm/mach-pnx4008/clock.c | 129 +++++++++++++++++------------------------- 1 file changed, 51 insertions(+), 78 deletions(-) diff --git a/arch/arm/mach-pnx4008/clock.c b/arch/arm/mach-pnx4008/clock.c index 285b22f631e..f582ed2ec43 100644 --- a/arch/arm/mach-pnx4008/clock.c +++ b/arch/arm/mach-pnx4008/clock.c @@ -767,6 +767,54 @@ static struct clk *onchip_clks[] = { &uart6_ck, }; +static int local_clk_enable(struct clk *clk) +{ + int ret = 0; + + if (!(clk->flags & FIXED_RATE) && !clk->rate && clk->set_rate + && clk->user_rate) + ret = clk->set_rate(clk, clk->user_rate); + return ret; +} + +static void local_clk_disable(struct clk *clk) +{ + if (!(clk->flags & FIXED_RATE) && clk->rate && clk->set_rate) + clk->set_rate(clk, 0); +} + +static void local_clk_unuse(struct clk *clk) +{ + if (clk->usecount > 0 && !(--clk->usecount)) { + local_clk_disable(clk); + if (clk->parent) + local_clk_unuse(clk->parent); + } +} + +static int local_clk_use(struct clk *clk) +{ + int ret = 0; + if (clk->usecount++ == 0) { + if (clk->parent) + ret = local_clk_use(clk->parent); + + if (ret != 0) { + clk->usecount--; + goto out; + } + + ret = local_clk_enable(clk); + + if (ret != 0 && clk->parent) { + local_clk_unuse(clk->parent); + clk->usecount--; + } + } +out: + return ret; +} + static int local_set_rate(struct clk *clk, u32 rate) { int ret = -EINVAL; @@ -847,28 +895,12 @@ unsigned long clk_get_rate(struct clk *clk) } EXPORT_SYMBOL(clk_get_rate); -static int local_clk_enable(struct clk *clk) -{ - int ret = 0; - - if (!(clk->flags & FIXED_RATE) && !clk->rate && clk->set_rate - && clk->user_rate) - ret = clk->set_rate(clk, clk->user_rate); - return ret; -} - -static void local_clk_disable(struct clk *clk) -{ - if (!(clk->flags & FIXED_RATE) && clk->rate && clk->set_rate) - clk->set_rate(clk, 0); -} - int clk_enable(struct clk *clk) { int ret = 0; clock_lock(); - ret = local_clk_enable(clk); + ret = local_clk_use(clk); clock_unlock(); return ret; } @@ -877,71 +909,12 @@ EXPORT_SYMBOL(clk_enable); void clk_disable(struct clk *clk) { - clock_lock(); - local_clk_disable(clk); - clock_unlock(); -} - -EXPORT_SYMBOL(clk_disable); - -static void local_clk_unuse(struct clk *clk) -{ - if (clk->usecount > 0 && !(--clk->usecount)) { - local_clk_disable(clk); - if (clk->parent) - local_clk_unuse(clk->parent); - } -} - -static int local_clk_use(struct clk *clk) -{ - int ret = 0; - if (clk->usecount++ == 0) { - if (clk->parent) - ret = local_clk_use(clk->parent); - - if (ret != 0) { - clk->usecount--; - goto out; - } - - ret = local_clk_enable(clk); - - if (ret != 0 && clk->parent) { - local_clk_unuse(clk->parent); - clk->usecount--; - } - } -out: - return ret; -} - -/* The main purpose of clk_use ans clk_unuse functions - * is to control switching 13MHz oscillator and PLL1 (13'MHz), - * so that they are disabled whenever none of PLL2-5 is using them. - * Although in theory these functions should work with any clock, - * please use them only on PLL2 - PLL5 to avoid confusion. - */ -int clk_use(struct clk *clk) -{ - int ret = 0; - - clock_lock(); - ret = local_clk_use(clk); - clock_unlock(); - return ret; -} -EXPORT_SYMBOL(clk_use); - -void clk_unuse(struct clk *clk) -{ - clock_lock(); local_clk_unuse(clk); clock_unlock(); } -EXPORT_SYMBOL(clk_unuse); +EXPORT_SYMBOL(clk_disable); long clk_round_rate(struct clk *clk, unsigned long rate) { @@ -995,7 +968,7 @@ static int __init clk_init(void) __FUNCTION__, (*clkp)->name, (*clkp)->rate); } - clk_use(&ck_pll4); + local_clk_use(&ck_pll4); /* if ck_13MHz is not used, disable it. */ if (ck_13MHz.usecount == 0) -- cgit v1.2.3 From b741483d7d8d86d215daf2a1f77bc3d3770746a6 Mon Sep 17 00:00:00 2001 From: Vitaly Wool Date: Thu, 22 Jun 2006 10:26:21 +0100 Subject: [ARM] 3623/1: pnx4008: move GPIO-related defines to gpio.h Patch from Vitaly Wool This patch moves GPIO-related defines and static inline funcs from include/asm-arm/arch-pnx4008/pm.h to include/asm-arm/arch-pnx4008/gpio.h. Also, some more GPIO-related defines are added to include/asm-arm/arch-pnx4008/gpio.h as they are needed for the USB host driver (coming soon...) Signed-off-by: Vitaly Wool Signed-off-by: Russell King --- arch/arm/mach-pnx4008/serial.c | 2 +- include/asm-arm/arch-pnx4008/gpio.h | 102 ++++++++++++++++++++++++++++++++++++ include/asm-arm/arch-pnx4008/pm.h | 29 ---------- 3 files changed, 103 insertions(+), 30 deletions(-) diff --git a/arch/arm/mach-pnx4008/serial.c b/arch/arm/mach-pnx4008/serial.c index 10322384e45..95a1b3f964a 100644 --- a/arch/arm/mach-pnx4008/serial.c +++ b/arch/arm/mach-pnx4008/serial.c @@ -20,7 +20,7 @@ #include #include -#include +#include #include diff --git a/include/asm-arm/arch-pnx4008/gpio.h b/include/asm-arm/arch-pnx4008/gpio.h index 1fa5a77c301..d01bf83d55c 100644 --- a/include/asm-arm/arch-pnx4008/gpio.h +++ b/include/asm-arm/arch-pnx4008/gpio.h @@ -127,6 +127,79 @@ #define GPIO_ISOUT(K) ((GPIO_TYPE_MASK(K) == GPIO_OUT) && (GPIO_BIT(K) & GPIO_OUT_MASK)) #define GPIO_ISIN(K) ((GPIO_TYPE_MASK(K) == GPIO_IN) && (GPIO_BIT(K) & GPIO_IN_MASK)) +/* Start Enable Pin Interrupts - table 58 page 66 */ + +#define SE_PIN_BASE_INT 32 + +#define SE_U7_RX_INT 63 +#define SE_U7_HCTS_INT 62 +#define SE_BT_CLKREQ_INT 61 +#define SE_U6_IRRX_INT 60 +/*59 unused*/ +#define SE_U5_RX_INT 58 +#define SE_GPI_11_INT 57 +#define SE_U3_RX_INT 56 +#define SE_U2_HCTS_INT 55 +#define SE_U2_RX_INT 54 +#define SE_U1_RX_INT 53 +#define SE_DISP_SYNC_INT 52 +/*51 unused*/ +#define SE_SDIO_INT_N 50 +#define SE_MSDIO_START_INT 49 +#define SE_GPI_06_INT 48 +#define SE_GPI_05_INT 47 +#define SE_GPI_04_INT 46 +#define SE_GPI_03_INT 45 +#define SE_GPI_02_INT 44 +#define SE_GPI_01_INT 43 +#define SE_GPI_00_INT 42 +#define SE_SYSCLKEN_PIN_INT 41 +#define SE_SPI1_DATAIN_INT 40 +#define SE_GPI_07_INT 39 +#define SE_SPI2_DATAIN_INT 38 +#define SE_GPI_10_INT 37 +#define SE_GPI_09_INT 36 +#define SE_GPI_08_INT 35 +/*34-32 unused*/ + +/* Start Enable Internal Interrupts - table 57 page 65 */ + +#define SE_INT_BASE_INT 0 + +#define SE_TS_IRQ 31 +#define SE_TS_P_INT 30 +#define SE_TS_AUX_INT 29 +/*27-28 unused*/ +#define SE_USB_AHB_NEED_CLK_INT 26 +#define SE_MSTIMER_INT 25 +#define SE_RTC_INT 24 +#define SE_USB_NEED_CLK_INT 23 +#define SE_USB_INT 22 +#define SE_USB_I2C_INT 21 +#define SE_USB_OTG_TIMER_INT 20 +#define SE_USB_OTG_ATX_INT_N 19 +/*18 unused*/ +#define SE_DSP_GPIO4_INT 17 +#define SE_KEY_IRQ 16 +#define SE_DSP_SLAVEPORT_INT 15 +#define SE_DSP_GPIO1_INT 14 +#define SE_DSP_GPIO0_INT 13 +#define SE_DSP_AHB_INT 12 +/*11-6 unused*/ +#define SE_GPIO_05_INT 5 +#define SE_GPIO_04_INT 4 +#define SE_GPIO_03_INT 3 +#define SE_GPIO_02_INT 2 +#define SE_GPIO_01_INT 1 +#define SE_GPIO_00_INT 0 + +#define START_INT_REG_BIT(irq) (1<<((irq)&0x1F)) + +#define START_INT_ER_REG(irq) IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x20 + (((irq)&(0x1<<5))>>1))) +#define START_INT_RSR_REG(irq) IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x24 + (((irq)&(0x1<<5))>>1))) +#define START_INT_SR_REG(irq) IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x28 + (((irq)&(0x1<<5))>>1))) +#define START_INT_APR_REG(irq) IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x2C + (((irq)&(0x1<<5))>>1))) + extern int pnx4008_gpio_register_pin(unsigned short pin); extern int pnx4008_gpio_unregister_pin(unsigned short pin); extern unsigned long pnx4008_gpio_read_pin(unsigned short pin); @@ -136,4 +209,33 @@ extern int pnx4008_gpio_read_pin_direction(unsigned short pin); extern int pnx4008_gpio_set_pin_mux(unsigned short pin, int output); extern int pnx4008_gpio_read_pin_mux(unsigned short pin); +static inline void start_int_umask(u8 irq) +{ + __raw_writel(__raw_readl(START_INT_ER_REG(irq)) | + START_INT_REG_BIT(irq), START_INT_ER_REG(irq)); +} + +static inline void start_int_mask(u8 irq) +{ + __raw_writel(__raw_readl(START_INT_ER_REG(irq)) & + ~START_INT_REG_BIT(irq), START_INT_ER_REG(irq)); +} + +static inline void start_int_ack(u8 irq) +{ + __raw_writel(START_INT_REG_BIT(irq), START_INT_RSR_REG(irq)); +} + +static inline void start_int_set_falling_edge(u8 irq) +{ + __raw_writel(__raw_readl(START_INT_APR_REG(irq)) & + ~START_INT_REG_BIT(irq), START_INT_APR_REG(irq)); +} + +static inline void start_int_set_rising_edge(u8 irq) +{ + __raw_writel(__raw_readl(START_INT_APR_REG(irq)) | + START_INT_REG_BIT(irq), START_INT_APR_REG(irq)); +} + #endif /* _PNX4008_GPIO_H_ */ diff --git a/include/asm-arm/arch-pnx4008/pm.h b/include/asm-arm/arch-pnx4008/pm.h index c660486670f..bac1634cb3e 100644 --- a/include/asm-arm/arch-pnx4008/pm.h +++ b/include/asm-arm/arch-pnx4008/pm.h @@ -29,34 +29,5 @@ extern void pnx4008_cpu_standby(void); extern int pnx4008_startup_pll(struct clk *); extern int pnx4008_shutdown_pll(struct clk *); -static inline void start_int_umask(u8 irq) -{ - __raw_writel(__raw_readl(START_INT_ER_REG(irq)) | - START_INT_REG_BIT(irq), START_INT_ER_REG(irq)); -} - -static inline void start_int_mask(u8 irq) -{ - __raw_writel(__raw_readl(START_INT_ER_REG(irq)) & - ~START_INT_REG_BIT(irq), START_INT_ER_REG(irq)); -} - -static inline void start_int_ack(u8 irq) -{ - __raw_writel(START_INT_REG_BIT(irq), START_INT_RSR_REG(irq)); -} - -static inline void start_int_set_falling_edge(u8 irq) -{ - __raw_writel(__raw_readl(START_INT_APR_REG(irq)) & - ~START_INT_REG_BIT(irq), START_INT_APR_REG(irq)); -} - -static inline void start_int_set_rising_edge(u8 irq) -{ - __raw_writel(__raw_readl(START_INT_APR_REG(irq)) | - START_INT_REG_BIT(irq), START_INT_APR_REG(irq)); -} - #endif /* ASSEMBLER */ #endif /* __ASM_ARCH_PNX4008_PM_H */ -- cgit v1.2.3 From ae2a120ce50e9dc8092f9bd4d76d8c8150a12c48 Mon Sep 17 00:00:00 2001 From: Vitaly Wool Date: Thu, 22 Jun 2006 10:27:15 +0100 Subject: [ARM] 3621/1: fix compilation breakage for pnx4008 Patch from Vitaly Wool pnx4008_defconfig fails to build: include/asm/hardware/debug-8250.S: Assembler messages: include/asm/hardware/debug-8250.S:12: Error: Macro with this name was already defined. This is due to senduart macro erroneously defined in include/asm-arm/arch-pnx4008/debug-macro.S. This patch removes it from that file. Signed-off-by: Vitaly Wool Signed-off-by: Russell King --- include/asm-arm/arch-pnx4008/debug-macro.S | 4 ---- 1 file changed, 4 deletions(-) diff --git a/include/asm-arm/arch-pnx4008/debug-macro.S b/include/asm-arm/arch-pnx4008/debug-macro.S index eb3839de389..67d18a203d2 100644 --- a/include/asm-arm/arch-pnx4008/debug-macro.S +++ b/include/asm-arm/arch-pnx4008/debug-macro.S @@ -19,9 +19,5 @@ addne \rx, \rx, #0xf4000000 .endm - .macro senduart,rd,rx - strb \rd, [\rx, #0x0] - .endm - #define UART_SHIFT 2 #include -- cgit v1.2.3 From 0967b5f0790cff737c86e9797cbbbdf420eb00f3 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Thu, 22 Jun 2006 10:30:51 +0100 Subject: [ARM] 3614/1: ep93xx: use platform devices for physmap flash Patch from Lennert Buytenhek Now that the physmap platform device rewrite is in, make the ep93xx boards use platform devices for physmap flash. Signed-off-by: Lennert Buytenhek Signed-off-by: Russell King --- arch/arm/mach-ep93xx/gesbc9312.c | 24 +++++++++++++++++++++++- arch/arm/mach-ep93xx/ts72xx.c | 23 ++++++++++++++++++++++- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-ep93xx/gesbc9312.c b/arch/arm/mach-ep93xx/gesbc9312.c index d18fcb1a2f1..47cc6c8b7c7 100644 --- a/arch/arm/mach-ep93xx/gesbc9312.c +++ b/arch/arm/mach-ep93xx/gesbc9312.c @@ -16,16 +16,38 @@ #include #include #include +#include #include +#include #include #include #include #include +static struct physmap_flash_data gesbc9312_flash_data = { + .width = 4, +}; + +static struct resource gesbc9312_flash_resource = { + .start = 0x60000000, + .end = 0x60800000, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device gesbc9312_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &gesbc9312_flash_data, + }, + .num_resources = 1, + .resource = &gesbc9312_flash_resource, +}; + static void __init gesbc9312_init_machine(void) { ep93xx_init_devices(); - physmap_configure(0x60000000, 0x00800000, 4, NULL); + platform_device_register(&gesbc9312_flash); } MACHINE_START(GESBC9312, "Glomation GESBC-9312-sx") diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c index e24566b88a7..6e5a56cd5ae 100644 --- a/arch/arm/mach-ep93xx/ts72xx.c +++ b/arch/arm/mach-ep93xx/ts72xx.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -111,6 +112,26 @@ static void __init ts72xx_map_io(void) } } +static struct physmap_flash_data ts72xx_flash_data = { + .width = 1, +}; + +static struct resource ts72xx_flash_resource = { + .start = TS72XX_NOR_PHYS_BASE, + .end = TS72XX_NOR_PHYS_BASE + 0x01000000, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device ts72xx_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &ts72xx_flash_data, + }, + .num_resources = 1, + .resource = &ts72xx_flash_resource, +}; + static unsigned char ts72xx_rtc_readbyte(unsigned long addr) { __raw_writeb(addr, TS72XX_RTC_INDEX_VIRT_BASE); @@ -141,7 +162,7 @@ static void __init ts72xx_init_machine(void) { ep93xx_init_devices(); if (board_is_ts7200()) - physmap_configure(TS72XX_NOR_PHYS_BASE, 0x01000000, 1, NULL); + platform_device_register(&ts72xx_flash); platform_device_register(&ts72xx_rtc_device); } -- cgit v1.2.3 From 84b61f6d3ad8a5761e61d83076588f64a289a574 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Thu, 22 Jun 2006 10:30:52 +0100 Subject: [ARM] 3615/1: ixp23xx: use platform devices for physmap flash Patch from Lennert Buytenhek Now that the physmap platform device rewrite is in, make the ixp23xx boards use platform devices for physmap flash. Signed-off-by: Lennert Buytenhek Signed-off-by: Russell King --- arch/arm/mach-ixp23xx/espresso.c | 22 +++++++++++++++++++++- arch/arm/mach-ixp23xx/ixdp2351.c | 22 +++++++++++++++++++++- arch/arm/mach-ixp23xx/roadrunner.c | 22 +++++++++++++++++++++- 3 files changed, 63 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-ixp23xx/espresso.c b/arch/arm/mach-ixp23xx/espresso.c index bf688c12863..dc5e489c70b 100644 --- a/arch/arm/mach-ixp23xx/espresso.c +++ b/arch/arm/mach-ixp23xx/espresso.c @@ -53,9 +53,29 @@ static int __init espresso_pci_init(void) }; subsys_initcall(espresso_pci_init); +static struct physmap_flash_data espresso_flash_data = { + .width = 2, +}; + +static struct resource espresso_flash_resource = { + .start = 0x90000000, + .end = 0x92000000, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device espresso_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &espresso_flash_data, + }, + .num_resources = 1, + .resource = &espresso_flash_resource, +}; + static void __init espresso_init(void) { - physmap_configure(0x90000000, 0x02000000, 2, NULL); + platform_device_register(&espresso_flash); /* * Mark flash as writeable. diff --git a/arch/arm/mach-ixp23xx/ixdp2351.c b/arch/arm/mach-ixp23xx/ixdp2351.c index 00146c35daa..535b334ee04 100644 --- a/arch/arm/mach-ixp23xx/ixdp2351.c +++ b/arch/arm/mach-ixp23xx/ixdp2351.c @@ -298,9 +298,29 @@ static void __init ixdp2351_map_io(void) iotable_init(ixdp2351_io_desc, ARRAY_SIZE(ixdp2351_io_desc)); } +static struct physmap_flash_data ixdp2351_flash_data = { + .width = 1, +}; + +static struct resource ixdp2351_flash_resource = { + .start = 0x90000000, + .end = 0x94000000, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device ixdp2351_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &ixdp2351_flash_data, + }, + .num_resources = 1, + .resource = &ixdp2351_flash_resource, +}; + static void __init ixdp2351_init(void) { - physmap_configure(0x90000000, 0x04000000, 1, NULL); + platform_device_register(&ixdp2351_flash); /* * Mark flash as writeable diff --git a/arch/arm/mach-ixp23xx/roadrunner.c b/arch/arm/mach-ixp23xx/roadrunner.c index 43c14e74079..b9f5d13fcfe 100644 --- a/arch/arm/mach-ixp23xx/roadrunner.c +++ b/arch/arm/mach-ixp23xx/roadrunner.c @@ -137,9 +137,29 @@ static int __init roadrunner_pci_init(void) subsys_initcall(roadrunner_pci_init); +static struct physmap_flash_data roadrunner_flash_data = { + .width = 2, +}; + +static struct resource roadrunner_flash_resource = { + .start = 0x90000000, + .end = 0x94000000, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device roadrunner_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &roadrunner_flash_data, + }, + .num_resources = 1, + .resource = &roadrunner_flash_resource, +}; + static void __init roadrunner_init(void) { - physmap_configure(0x90000000, 0x04000000, 2, NULL); + platform_device_register(&roadrunner_flash); /* * Mark flash as writeable -- cgit v1.2.3 From f869afab8f36c5f8561557f74b4b9846719092da Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Thu, 22 Jun 2006 10:30:53 +0100 Subject: [ARM] 3616/1: fix timer handler wrap logic for a number of platforms Patch from Lennert Buytenhek A couple of platforms aren't using the right comparison type in their timer interrupt handlers (as we're comparing two wrapping timestamps, we need a bmi/bpl-type comparison, not an unsigned comparison) -- this patch fixes them up. Signed-off-by: Lennert Buytenhek Signed-off-by: Russell King --- arch/arm/mach-ep93xx/core.c | 3 ++- arch/arm/mach-ixp2000/core.c | 3 ++- arch/arm/mach-ixp23xx/core.c | 4 ++-- arch/arm/mach-ixp4xx/common.c | 2 +- arch/arm/plat-omap/timer32k.c | 3 ++- 5 files changed, 9 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index dcd41762538..d0eb364fc01 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -103,7 +103,8 @@ static int ep93xx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) write_seqlock(&xtime_lock); __raw_writel(1, EP93XX_TIMER1_CLEAR); - while (__raw_readl(EP93XX_TIMER4_VALUE_LOW) - last_jiffy_time + while ((signed long) + (__raw_readl(EP93XX_TIMER4_VALUE_LOW) - last_jiffy_time) >= TIMER4_TICKS_PER_JIFFY) { last_jiffy_time += TIMER4_TICKS_PER_JIFFY; timer_tick(regs); diff --git a/arch/arm/mach-ixp2000/core.c b/arch/arm/mach-ixp2000/core.c index 6e8d504aca5..186f632035b 100644 --- a/arch/arm/mach-ixp2000/core.c +++ b/arch/arm/mach-ixp2000/core.c @@ -211,7 +211,8 @@ static int ixp2000_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) /* clear timer 1 */ ixp2000_reg_wrb(IXP2000_T1_CLR, 1); - while ((next_jiffy_time - *missing_jiffy_timer_csr) > ticks_per_jiffy) { + while ((signed long)(next_jiffy_time - *missing_jiffy_timer_csr) + >= ticks_per_jiffy) { timer_tick(regs); next_jiffy_time -= ticks_per_jiffy; } diff --git a/arch/arm/mach-ixp23xx/core.c b/arch/arm/mach-ixp23xx/core.c index affd1d5d744..e2aad734080 100644 --- a/arch/arm/mach-ixp23xx/core.c +++ b/arch/arm/mach-ixp23xx/core.c @@ -334,7 +334,7 @@ void __init ixp23xx_init_irq(void) /************************************************************************* * Timer-tick functions for IXP23xx *************************************************************************/ -#define CLOCK_TICKS_PER_USEC CLOCK_TICK_RATE / (USEC_PER_SEC) +#define CLOCK_TICKS_PER_USEC (CLOCK_TICK_RATE / USEC_PER_SEC) static unsigned long next_jiffy_time; @@ -353,7 +353,7 @@ ixp23xx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { /* Clear Pending Interrupt by writing '1' to it */ *IXP23XX_TIMER_STATUS = IXP23XX_TIMER1_INT_PEND; - while ((*IXP23XX_TIMER_CONT - next_jiffy_time) > LATCH) { + while ((signed long)(*IXP23XX_TIMER_CONT - next_jiffy_time) >= LATCH) { timer_tick(regs); next_jiffy_time += LATCH; } diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c index 00b761ff0f9..bf25a76e9bd 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c @@ -276,7 +276,7 @@ static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id, struct pt_regs /* * Catch up with the real idea of time */ - while ((*IXP4XX_OSTS - last_jiffy_time) > LATCH) { + while ((signed long)(*IXP4XX_OSTS - last_jiffy_time) >= LATCH) { timer_tick(regs); last_jiffy_time += LATCH; } diff --git a/arch/arm/plat-omap/timer32k.c b/arch/arm/plat-omap/timer32k.c index b2a943bf11e..3461a6c9665 100644 --- a/arch/arm/plat-omap/timer32k.c +++ b/arch/arm/plat-omap/timer32k.c @@ -210,7 +210,8 @@ static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id, now = omap_32k_sync_timer_read(); - while (now - omap_32k_last_tick >= OMAP_32K_TICKS_PER_HZ) { + while ((signed long)(now - omap_32k_last_tick) + >= OMAP_32K_TICKS_PER_HZ) { omap_32k_last_tick += OMAP_32K_TICKS_PER_HZ; timer_tick(regs); } -- cgit v1.2.3 From a059e33ce67cec5e990fdec43f242d3b06c60d1a Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Thu, 22 Jun 2006 10:30:54 +0100 Subject: [ARM] 3617/1: ep93xx: fix slightly incorrect timer tick rate Patch from Lennert Buytenhek The tick rate of timers 1-3 isn't exactly 508 kHz as some parts of the relevant documentation claim, but more like 508.469 kHz (14.7456 MHz divided by 29.) Signed-off-by: Lennert Buytenhek Signed-off-by: Russell King --- arch/arm/mach-ep93xx/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index d0eb364fc01..bf6bd71bdd0 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -125,7 +125,7 @@ static void __init ep93xx_timer_init(void) { /* Enable periodic HZ timer. */ __raw_writel(0x48, EP93XX_TIMER1_CONTROL); - __raw_writel((508000 / HZ) - 1, EP93XX_TIMER1_LOAD); + __raw_writel((508469 / HZ) - 1, EP93XX_TIMER1_LOAD); __raw_writel(0xc8, EP93XX_TIMER1_CONTROL); /* Enable lost jiffy timer. */ -- cgit v1.2.3 From 744da2cb598639767ddcc90ca855771bc524fe76 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Thu, 22 Jun 2006 10:30:55 +0100 Subject: [ARM] 3618/1: add defconfig for logicpd pxa270 card engine Patch from Lennert Buytenhek As it's slightly nontrivial to make it possible to build a single kernel image for both the mainstone and the logicpd pxa270 card engine, add a separate defconfig for the logicpd pxa270 card engine for now. Signed-off-by: Lennert Buytenhek Signed-off-by: Russell King --- arch/arm/configs/lpd270_defconfig | 963 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 963 insertions(+) create mode 100644 arch/arm/configs/lpd270_defconfig diff --git a/arch/arm/configs/lpd270_defconfig b/arch/arm/configs/lpd270_defconfig new file mode 100644 index 00000000000..d08bbe59483 --- /dev/null +++ b/arch/arm/configs/lpd270_defconfig @@ -0,0 +1,963 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.17-git2 +# Wed Jun 21 22:20:18 2006 +# +CONFIG_ARM=y +CONFIG_MMU=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_ARCH_MTD_XIP=y +CONFIG_VECTORS_BASE=0xffff0000 + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +# CONFIG_RELAY is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_UID16=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_EMBEDDED is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODULE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +# CONFIG_KMOD is not set + +# +# Block layer +# +# CONFIG_BLK_DEV_IO_TRACE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" + +# +# System Type +# +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91RM9200 is not set +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_IOP3XX is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_PNX4008 is not set +CONFIG_ARCH_PXA=y +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_OMAP is not set + +# +# Intel PXA2xx Implementations +# +# CONFIG_ARCH_LUBBOCK is not set +CONFIG_MACH_LOGICPD_PXA270=y +# CONFIG_MACH_MAINSTONE is not set +# CONFIG_ARCH_PXA_IDP is not set +# CONFIG_PXA_SHARPSL is not set +CONFIG_PXA27x=y +CONFIG_IWMMXT=y + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_XSCALE=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5T=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_TLB_V4WBI=y + +# +# Processor Features +# +# CONFIG_ARM_THUMB is not set +CONFIG_XSCALE_PMU=y + +# +# Bus support +# + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +# CONFIG_PREEMPT is not set +# CONFIG_NO_IDLE_HZ is not set +CONFIG_HZ=100 +# CONFIG_AEABI is not set +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4096 +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="root=/dev/nfs ip=bootp console=ttyS0,115200 mem=64M" +# CONFIG_XIP_KERNEL is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set +# CONFIG_ARTHUR is not set + +# +# Power management options +# +# CONFIG_PM is not set +# CONFIG_PM_LEGACY is not set +# CONFIG_PM_DEBUG is not set +# CONFIG_APM is not set + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +# CONFIG_PACKET is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_DEBUG_DRIVER is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_REDBOOT_PARTS=y +CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 +# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set +# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AFS_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +CONFIG_MTD_CFI_GEOMETRY=y +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +# CONFIG_MTD_CFI_I1 is not set +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_OTP is not set +CONFIG_MTD_CFI_INTELEXT=y +# CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set +# CONFIG_MTD_XIP is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_SHARP_SL is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_IDE_TASK_IOCTL is not set + +# +# IDE chipset support/bugfixes +# +# CONFIG_IDE_GENERIC is not set +# CONFIG_IDE_ARM is not set +# CONFIG_BLK_DEV_IDEDMA is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# I2O device support +# + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# PHY device support +# +# CONFIG_PHYLIB is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +CONFIG_SMC91X=y +# CONFIG_DM9000 is not set +# CONFIG_SMC911X is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +# CONFIG_SERIO_SERPORT is not set +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_PXA=y +CONFIG_SERIAL_PXA_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set +CONFIG_VIDEO_V4L2=y + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_MACMODES is not set +CONFIG_FB_FIRMWARE_EDID=y +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set +# CONFIG_FB_S1D13XXX is not set +CONFIG_FB_PXA=y +# CONFIG_FB_PXA_PARAMETERS is not set +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Logo configuration +# +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y +CONFIG_LOGO_LINUX_CLUT224=y +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Sound +# +CONFIG_SOUND=y + +# +# Advanced Linux Sound Architecture +# +CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +# CONFIG_SND_SEQUENCER is not set +# CONFIG_SND_MIXER_OSS is not set +# CONFIG_SND_PCM_OSS is not set +# CONFIG_SND_DYNAMIC_MINORS is not set +# CONFIG_SND_SUPPORT_OLD_API is not set +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set + +# +# Generic devices +# +CONFIG_SND_AC97_CODEC=y +CONFIG_SND_AC97_BUS=y +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set + +# +# ALSA ARM devices +# +CONFIG_SND_PXA2XX_PCM=y +CONFIG_SND_PXA2XX_AC97=y + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ARCH_HAS_EHCI is not set +# CONFIG_USB is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# Real Time Clock +# +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +# CONFIG_EXT3_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +# CONFIG_VFAT_FS is not set +CONFIG_FAT_DEFAULT_CODEPAGE=437 +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_SYSFS=y +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_FS is not set +# CONFIG_DEBUG_VM is not set +CONFIG_FRAME_POINTER=y +# CONFIG_UNWIND_INFO is not set +CONFIG_FORCED_INLINING=y +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_DEBUG_USER=y +# CONFIG_DEBUG_WAITQ is not set +CONFIG_DEBUG_ERRORS=y +CONFIG_DEBUG_LL=y +# CONFIG_DEBUG_ICEDCC is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Hardware crypto devices +# + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y -- cgit v1.2.3 From 8b76a68c6caafef5a91cdc80958aecaca76a8896 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Thu, 22 Jun 2006 10:30:56 +0100 Subject: [ARM] 3620/2: ixp23xx: add uengine loader support Patch from Lennert Buytenhek This patch allows the ixp2000 uengine loader that is already in the tree to also be used on the ixp23xx. Signed-off-by: Lennert Buytenhek Signed-off-by: Russell King --- arch/arm/common/Makefile | 1 + arch/arm/common/uengine.c | 58 +++++++++++++++++++++++++++------ arch/arm/mach-ixp23xx/core.c | 1 + include/asm-arm/arch-ixp23xx/ixp23xx.h | 3 ++ include/asm-arm/arch-ixp23xx/platform.h | 15 +++++++++ 5 files changed, 68 insertions(+), 10 deletions(-) diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile index 847e3e6356c..e1289a256ce 100644 --- a/arch/arm/common/Makefile +++ b/arch/arm/common/Makefile @@ -16,3 +16,4 @@ obj-$(CONFIG_SHARP_PARAM) += sharpsl_param.o obj-$(CONFIG_SHARPSL_PM) += sharpsl_pm.o obj-$(CONFIG_SHARP_SCOOP) += scoop.o obj-$(CONFIG_ARCH_IXP2000) += uengine.o +obj-$(CONFIG_ARCH_IXP23XX) += uengine.o diff --git a/arch/arm/common/uengine.c b/arch/arm/common/uengine.c index a1310b71004..dfca596a9a2 100644 --- a/arch/arm/common/uengine.c +++ b/arch/arm/common/uengine.c @@ -18,10 +18,26 @@ #include #include #include -#include +#include #include #include +#if defined(CONFIG_ARCH_IXP2000) +#define IXP_UENGINE_CSR_VIRT_BASE IXP2000_UENGINE_CSR_VIRT_BASE +#define IXP_PRODUCT_ID IXP2000_PRODUCT_ID +#define IXP_MISC_CONTROL IXP2000_MISC_CONTROL +#define IXP_RESET1 IXP2000_RESET1 +#else +#if defined(CONFIG_ARCH_IXP23XX) +#define IXP_UENGINE_CSR_VIRT_BASE IXP23XX_UENGINE_CSR_VIRT_BASE +#define IXP_PRODUCT_ID IXP23XX_PRODUCT_ID +#define IXP_MISC_CONTROL IXP23XX_MISC_CONTROL +#define IXP_RESET1 IXP23XX_RESET1 +#else +#error unknown platform +#endif +#endif + #define USTORE_ADDRESS 0x000 #define USTORE_DATA_LOWER 0x004 #define USTORE_DATA_UPPER 0x008 @@ -43,7 +59,7 @@ u32 ixp2000_uengine_mask; static void *ixp2000_uengine_csr_area(int uengine) { - return ((void *)IXP2000_UENGINE_CSR_VIRT_BASE) + (uengine << 10); + return ((void *)IXP_UENGINE_CSR_VIRT_BASE) + (uengine << 10); } /* @@ -91,8 +107,13 @@ EXPORT_SYMBOL(ixp2000_uengine_csr_write); void ixp2000_uengine_reset(u32 uengine_mask) { - ixp2000_reg_wrb(IXP2000_RESET1, uengine_mask & ixp2000_uengine_mask); - ixp2000_reg_wrb(IXP2000_RESET1, 0); + u32 value; + + value = ixp2000_reg_read(IXP_RESET1) & ~ixp2000_uengine_mask; + + uengine_mask &= ixp2000_uengine_mask; + ixp2000_reg_wrb(IXP_RESET1, value | uengine_mask); + ixp2000_reg_wrb(IXP_RESET1, value); } EXPORT_SYMBOL(ixp2000_uengine_reset); @@ -235,11 +256,12 @@ static int check_ixp_type(struct ixp2000_uengine_code *c) u32 product_id; u32 rev; - product_id = ixp2000_reg_read(IXP2000_PRODUCT_ID); + product_id = ixp2000_reg_read(IXP_PRODUCT_ID); if (((product_id >> 16) & 0x1f) != 0) return 0; switch ((product_id >> 8) & 0xff) { +#ifdef CONFIG_ARCH_IXP2000 case 0: /* IXP2800 */ if (!(c->cpu_model_bitmask & 4)) return 0; @@ -254,6 +276,14 @@ static int check_ixp_type(struct ixp2000_uengine_code *c) if (!(c->cpu_model_bitmask & 2)) return 0; break; +#endif + +#ifdef CONFIG_ARCH_IXP23XX + case 4: /* IXP23xx */ + if (!(c->cpu_model_bitmask & 0x3f0)) + return 0; + break; +#endif default: return 0; @@ -432,7 +462,8 @@ static int __init ixp2000_uengine_init(void) /* * Determine number of microengines present. */ - switch ((ixp2000_reg_read(IXP2000_PRODUCT_ID) >> 8) & 0x1fff) { + switch ((ixp2000_reg_read(IXP_PRODUCT_ID) >> 8) & 0x1fff) { +#ifdef CONFIG_ARCH_IXP2000 case 0: /* IXP2800 */ case 1: /* IXP2850 */ ixp2000_uengine_mask = 0x00ff00ff; @@ -441,10 +472,17 @@ static int __init ixp2000_uengine_init(void) case 2: /* IXP2400 */ ixp2000_uengine_mask = 0x000f000f; break; +#endif + +#ifdef CONFIG_ARCH_IXP23XX + case 4: /* IXP23xx */ + ixp2000_uengine_mask = (*IXP23XX_EXP_CFG_FUSE >> 8) & 0xf; + break; +#endif default: printk(KERN_INFO "Detected unknown IXP2000 model (%.8x)\n", - (unsigned int)ixp2000_reg_read(IXP2000_PRODUCT_ID)); + (unsigned int)ixp2000_reg_read(IXP_PRODUCT_ID)); ixp2000_uengine_mask = 0x00000000; break; } @@ -457,15 +495,15 @@ static int __init ixp2000_uengine_init(void) /* * Synchronise timestamp counters across all microengines. */ - value = ixp2000_reg_read(IXP2000_MISC_CONTROL); - ixp2000_reg_wrb(IXP2000_MISC_CONTROL, value & ~0x80); + value = ixp2000_reg_read(IXP_MISC_CONTROL); + ixp2000_reg_wrb(IXP_MISC_CONTROL, value & ~0x80); for (uengine = 0; uengine < 32; uengine++) { if (ixp2000_uengine_mask & (1 << uengine)) { ixp2000_uengine_csr_write(uengine, TIMESTAMP_LOW, 0); ixp2000_uengine_csr_write(uengine, TIMESTAMP_HIGH, 0); } } - ixp2000_reg_wrb(IXP2000_MISC_CONTROL, value | 0x80); + ixp2000_reg_wrb(IXP_MISC_CONTROL, value | 0x80); return 0; } diff --git a/arch/arm/mach-ixp23xx/core.c b/arch/arm/mach-ixp23xx/core.c index e2aad734080..051e3d70026 100644 --- a/arch/arm/mach-ixp23xx/core.c +++ b/arch/arm/mach-ixp23xx/core.c @@ -439,5 +439,6 @@ static struct platform_device *ixp23xx_devices[] __initdata = { void __init ixp23xx_sys_init(void) { + *IXP23XX_EXP_UNIT_FUSE |= 0xf; platform_add_devices(ixp23xx_devices, ARRAY_SIZE(ixp23xx_devices)); } diff --git a/include/asm-arm/arch-ixp23xx/ixp23xx.h b/include/asm-arm/arch-ixp23xx/ixp23xx.h index 01efdbd1180..d0a72201ee9 100644 --- a/include/asm-arm/arch-ixp23xx/ixp23xx.h +++ b/include/asm-arm/arch-ixp23xx/ixp23xx.h @@ -124,6 +124,7 @@ #define IXP23XX_EXP_UNIT_FUSE IXP23XX_EXP_CFG_REG(0x28) #define IXP23XX_EXP_MSF_MUX IXP23XX_EXP_CFG_REG(0x30) +#define IXP23XX_EXP_CFG_FUSE IXP23XX_EXP_CFG_REG(0x34) #define IXP23XX_EXP_BUS_PHYS 0x90000000 #define IXP23XX_EXP_BUS_WINDOW_SIZE 0x01000000 @@ -265,6 +266,8 @@ #define IXP23XX_PCI_UNIT_RESET (1 << 1) #define IXP23XX_XSCALE_RESET (1 << 0) +#define IXP23XX_UENGINE_CSR_VIRT_BASE (IXP23XX_CAP_CSR_VIRT + 0x18000) + /**************************************************************************** * PCI CSRs. diff --git a/include/asm-arm/arch-ixp23xx/platform.h b/include/asm-arm/arch-ixp23xx/platform.h index e4d99060a04..19a73b39c86 100644 --- a/include/asm-arm/arch-ixp23xx/platform.h +++ b/include/asm-arm/arch-ixp23xx/platform.h @@ -14,6 +14,21 @@ #ifndef __ASSEMBLY__ +extern inline unsigned long ixp2000_reg_read(volatile void *reg) +{ + return *((volatile unsigned long *)reg); +} + +extern inline void ixp2000_reg_write(volatile void *reg, unsigned long val) +{ + *((volatile unsigned long *)reg) = val; +} + +extern inline void ixp2000_reg_wrb(volatile void *reg, unsigned long val) +{ + *((volatile unsigned long *)reg) = val; +} + struct pci_sys_data; void ixp23xx_map_io(void); -- cgit v1.2.3 From 005b5e4d0c7795d2ec298c34c96cbe2c1e1902b0 Mon Sep 17 00:00:00 2001 From: Uli Luckas Date: Thu, 22 Jun 2006 16:49:54 +0100 Subject: [ARM] 3624/1: Report true modem control line states Patch from Uli Luckas This patch removes the fake return from serial_pxa_get_mctrl. Signed-off-by: Uli Luckas I just can't remember why this return was there. Being in the first column clearly indicates it was meant to be removed. Signed-off-by: Nicolas Pitre Signed-off-by: Russell King --- drivers/serial/pxa.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c index 77d4568ccc3..ae364956854 100644 --- a/drivers/serial/pxa.c +++ b/drivers/serial/pxa.c @@ -269,7 +269,6 @@ static unsigned int serial_pxa_get_mctrl(struct uart_port *port) unsigned char status; unsigned int ret; -return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; status = serial_in(up, UART_MSR); ret = 0; -- cgit v1.2.3 From 43cb7ebee2f478d3f987ad773d4e6b07fc23c631 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Thu, 23 Mar 2006 16:19:49 +0100 Subject: [PATCH] lm83: Add LM82 support Add LM82 temperature sensor support (similar to the LM83, but less featureful). Signed-off-by: Jordan Crouse Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- Documentation/hwmon/lm83 | 16 ++++++++++++---- drivers/hwmon/Kconfig | 4 ++-- drivers/hwmon/lm83.c | 50 +++++++++++++++++++++++++++++++++++------------- 3 files changed, 51 insertions(+), 19 deletions(-) diff --git a/Documentation/hwmon/lm83 b/Documentation/hwmon/lm83 index 061d9ed8ff4..74aa7ee1a35 100644 --- a/Documentation/hwmon/lm83 +++ b/Documentation/hwmon/lm83 @@ -7,6 +7,10 @@ Supported chips: Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e Datasheet: Publicly available at the National Semiconductor website http://www.national.com/pf/LM/LM83.html + * National Semiconductor LM82 + Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e + Datasheet: Publicly available at the National Semiconductor website + http://www.national.com/pf/LM/LM82.html Author: Jean Delvare @@ -15,10 +19,11 @@ Description ----------- The LM83 is a digital temperature sensor. It senses its own temperature as -well as the temperature of up to three external diodes. It is compatible -with many other devices such as the LM84 and all other ADM1021 clones. -The main difference between the LM83 and the LM84 in that the later can -only sense the temperature of one external diode. +well as the temperature of up to three external diodes. The LM82 is +a stripped down version of the LM83 that only supports one external diode. +Both are compatible with many other devices such as the LM84 and all +other ADM1021 clones. The main difference between the LM83 and the LM84 +in that the later can only sense the temperature of one external diode. Using the adm1021 driver for a LM83 should work, but only two temperatures will be reported instead of four. @@ -36,6 +41,9 @@ Unconfirmed motherboards: Iwill MPX2 Soltek SL-75DRV5 +The LM82 is confirmed to have been found on most AMD Geode reference +designs and test platforms. + The driver has been successfully tested by Magnus Forsström, who I'd like to thank here. More testers will be of course welcome. diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 99cdc612d2c..a6a8d66129b 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -236,11 +236,11 @@ config SENSORS_LM80 will be called lm80. config SENSORS_LM83 - tristate "National Semiconductor LM83" + tristate "National Semiconductor LM83 and compatibles" depends on HWMON && I2C help If you say yes here you get support for National Semiconductor - LM83 sensor chips. + LM82 and LM83 sensor chips. This driver can also be built as a module. If so, the module will be called lm83. diff --git a/drivers/hwmon/lm83.c b/drivers/hwmon/lm83.c index aac4ec2bf69..2137d7879df 100644 --- a/drivers/hwmon/lm83.c +++ b/drivers/hwmon/lm83.c @@ -12,6 +12,10 @@ * Since the datasheet omits to give the chip stepping code, I give it * here: 0x03 (at register 0xff). * + * Also supports the LM82 temp sensor, which is basically a stripped down + * model of the LM83. Datasheet is here: + * http://www.national.com/pf/LM/LM82.html + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -52,7 +56,7 @@ static unsigned short normal_i2c[] = { 0x18, 0x19, 0x1a, * Insmod parameters */ -I2C_CLIENT_INSMOD_1(lm83); +I2C_CLIENT_INSMOD_2(lm83, lm82); /* * The LM83 registers @@ -283,6 +287,9 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind) if (man_id == 0x01) { /* National Semiconductor */ if (chip_id == 0x03) { kind = lm83; + } else + if (chip_id == 0x01) { + kind = lm82; } } @@ -296,6 +303,9 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind) if (kind == lm83) { name = "lm83"; + } else + if (kind == lm82) { + name = "lm82"; } /* We can fill in the remaining client fields */ @@ -319,32 +329,46 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind) goto exit_detach; } + /* + * The LM82 can only monitor one external diode which is + * at the same register as the LM83 temp3 entry - so we + * declare 1 and 3 common, and then 2 and 4 only for the LM83. + */ + device_create_file(&new_client->dev, &sensor_dev_attr_temp1_input.dev_attr); - device_create_file(&new_client->dev, - &sensor_dev_attr_temp2_input.dev_attr); device_create_file(&new_client->dev, &sensor_dev_attr_temp3_input.dev_attr); - device_create_file(&new_client->dev, - &sensor_dev_attr_temp4_input.dev_attr); + device_create_file(&new_client->dev, &sensor_dev_attr_temp1_max.dev_attr); - device_create_file(&new_client->dev, - &sensor_dev_attr_temp2_max.dev_attr); device_create_file(&new_client->dev, &sensor_dev_attr_temp3_max.dev_attr); - device_create_file(&new_client->dev, - &sensor_dev_attr_temp4_max.dev_attr); + device_create_file(&new_client->dev, &sensor_dev_attr_temp1_crit.dev_attr); - device_create_file(&new_client->dev, - &sensor_dev_attr_temp2_crit.dev_attr); device_create_file(&new_client->dev, &sensor_dev_attr_temp3_crit.dev_attr); - device_create_file(&new_client->dev, - &sensor_dev_attr_temp4_crit.dev_attr); + device_create_file(&new_client->dev, &dev_attr_alarms); + if (kind == lm83) { + device_create_file(&new_client->dev, + &sensor_dev_attr_temp2_input.dev_attr); + device_create_file(&new_client->dev, + &sensor_dev_attr_temp4_input.dev_attr); + + device_create_file(&new_client->dev, + &sensor_dev_attr_temp2_max.dev_attr); + device_create_file(&new_client->dev, + &sensor_dev_attr_temp4_max.dev_attr); + + device_create_file(&new_client->dev, + &sensor_dev_attr_temp2_crit.dev_attr); + device_create_file(&new_client->dev, + &sensor_dev_attr_temp4_crit.dev_attr); + } + return 0; exit_detach: -- cgit v1.2.3 From cf0676fe42c8e14c4c7ed5895e2fe5d17f779b43 Mon Sep 17 00:00:00 2001 From: Rudolf Marek Date: Thu, 23 Mar 2006 16:25:22 +0100 Subject: [PATCH] w83627ehf: Add voltage inputs support Add the voltage measuring support to W83627EHF. The code is based on the patch provided by Yuan Mu from Winbond. Signed-off-by: Yuan Mu Signed-off-by: Rudolf Marek Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/w83627ehf.c | 124 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 120 insertions(+), 4 deletions(-) diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index b6bd5685fd3..08bbeaf64e9 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c @@ -30,10 +30,7 @@ Supports the following chips: Chip #vin #fan #pwm #temp chip_id man_id - w83627ehf - 5 - 3 0x88 0x5ca3 - - This is a preliminary version of the driver, only supporting the - fan and temperature inputs. The chip does much more than that. + w83627ehf 10 5 - 3 0x88 0x5ca3 */ #include @@ -121,6 +118,14 @@ superio_exit(void) static const u16 W83627EHF_REG_FAN[] = { 0x28, 0x29, 0x2a, 0x3f, 0x553 }; static const u16 W83627EHF_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d, 0x3e, 0x55c }; +/* The W83627EHF registers for nr=7,8,9 are in bank 5 */ +#define W83627EHF_REG_IN_MAX(nr) ((nr < 7) ? (0x2b + (nr) * 2) : \ + (0x554 + (((nr) - 7) * 2))) +#define W83627EHF_REG_IN_MIN(nr) ((nr < 7) ? (0x2c + (nr) * 2) : \ + (0x555 + (((nr) - 7) * 2))) +#define W83627EHF_REG_IN(nr) ((nr < 7) ? (0x20 + (nr)) : \ + (0x550 + (nr) - 7)) + #define W83627EHF_REG_TEMP1 0x27 #define W83627EHF_REG_TEMP1_HYST 0x3a #define W83627EHF_REG_TEMP1_OVER 0x39 @@ -172,6 +177,20 @@ temp1_to_reg(int temp) return (temp + 500) / 1000; } +/* Some of analog inputs have internal scaling (2x), 8mV is ADC LSB */ + +static u8 scale_in[10] = { 8, 8, 16, 16, 8, 8, 8, 16, 16, 8 }; + +static inline long in_from_reg(u8 reg, u8 nr) +{ + return reg * scale_in[nr]; +} + +static inline u8 in_to_reg(u32 val, u8 nr) +{ + return SENSORS_LIMIT(((val + (scale_in[nr] / 2)) / scale_in[nr]), 0, 255); +} + /* * Data structures and manipulation thereof */ @@ -186,6 +205,9 @@ struct w83627ehf_data { unsigned long last_updated; /* In jiffies */ /* Register values */ + u8 in[10]; /* Register value */ + u8 in_max[10]; /* Register value */ + u8 in_min[10]; /* Register value */ u8 fan[5]; u8 fan_min[5]; u8 fan_div[5]; @@ -349,6 +371,16 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev) data->fan_div[3] |= (i >> 5) & 0x04; } + /* Measured voltages and limits */ + for (i = 0; i < 10; i++) { + data->in[i] = w83627ehf_read_value(client, + W83627EHF_REG_IN(i)); + data->in_min[i] = w83627ehf_read_value(client, + W83627EHF_REG_IN_MIN(i)); + data->in_max[i] = w83627ehf_read_value(client, + W83627EHF_REG_IN_MAX(i)); + } + /* Measured fan speeds and limits */ for (i = 0; i < 5; i++) { if (!(data->has_fan & (1 << i))) @@ -406,6 +438,87 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev) /* * Sysfs callback functions */ +#define show_in_reg(reg) \ +static ssize_t \ +show_##reg(struct device *dev, struct device_attribute *attr, \ + char *buf) \ +{ \ + struct w83627ehf_data *data = w83627ehf_update_device(dev); \ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \ + int nr = sensor_attr->index; \ + return sprintf(buf, "%ld\n", in_from_reg(data->reg[nr], nr)); \ +} +show_in_reg(in) +show_in_reg(in_min) +show_in_reg(in_max) + +#define store_in_reg(REG, reg) \ +static ssize_t \ +store_in_##reg (struct device *dev, struct device_attribute *attr, \ + const char *buf, size_t count) \ +{ \ + struct i2c_client *client = to_i2c_client(dev); \ + struct w83627ehf_data *data = i2c_get_clientdata(client); \ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \ + int nr = sensor_attr->index; \ + u32 val = simple_strtoul(buf, NULL, 10); \ + \ + mutex_lock(&data->update_lock); \ + data->in_##reg[nr] = in_to_reg(val, nr); \ + w83627ehf_write_value(client, W83627EHF_REG_IN_##REG(nr), \ + data->in_##reg[nr]); \ + mutex_unlock(&data->update_lock); \ + return count; \ +} + +store_in_reg(MIN, min) +store_in_reg(MAX, max) + +static struct sensor_device_attribute sda_in_input[] = { + SENSOR_ATTR(in0_input, S_IRUGO, show_in, NULL, 0), + SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1), + SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2), + SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3), + SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4), + SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5), + SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6), + SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7), + SENSOR_ATTR(in8_input, S_IRUGO, show_in, NULL, 8), + SENSOR_ATTR(in9_input, S_IRUGO, show_in, NULL, 9), +}; + +static struct sensor_device_attribute sda_in_min[] = { + SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 0), + SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 1), + SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 2), + SENSOR_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 3), + SENSOR_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 4), + SENSOR_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 5), + SENSOR_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 6), + SENSOR_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 7), + SENSOR_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 8), + SENSOR_ATTR(in9_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 9), +}; + +static struct sensor_device_attribute sda_in_max[] = { + SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 0), + SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 1), + SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 2), + SENSOR_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 3), + SENSOR_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 4), + SENSOR_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 5), + SENSOR_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 6), + SENSOR_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 7), + SENSOR_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 8), + SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 9), +}; + +static void device_create_file_in(struct device *dev, int i) +{ + device_create_file(dev, &sda_in_input[i].dev_attr); + device_create_file(dev, &sda_in_min[i].dev_attr); + device_create_file(dev, &sda_in_max[i].dev_attr); +} #define show_fan_reg(reg) \ static ssize_t \ @@ -705,6 +818,9 @@ static int w83627ehf_detect(struct i2c_adapter *adapter) goto exit_detach; } + for (i = 0; i < 10; i++) + device_create_file_in(dev, i); + for (i = 0; i < 5; i++) { if (data->has_fan & (1 << i)) device_create_file_fan(dev, i); -- cgit v1.2.3 From a4589dbb4e2dc758d1aadb8b5d7e5a598ccb0341 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 23 Mar 2006 16:30:29 +0100 Subject: [PATCH] w83627ehf: Add alarms support Add alarms support for the W83627EHF/EHG hardware monitoring chip. This is based on an earlier patch from Rudolf Marek. Signed-off-by: Rudolf Marek Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/w83627ehf.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index 08bbeaf64e9..40301bc6ce1 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c @@ -141,6 +141,10 @@ static const u16 W83627EHF_REG_TEMP_CONFIG[] = { 0x152, 0x252 }; #define W83627EHF_REG_DIODE 0x59 #define W83627EHF_REG_SMI_OVT 0x4C +#define W83627EHF_REG_ALARM1 0x459 +#define W83627EHF_REG_ALARM2 0x45A +#define W83627EHF_REG_ALARM3 0x45B + /* * Conversions */ @@ -218,6 +222,7 @@ struct w83627ehf_data { s16 temp[2]; s16 temp_max[2]; s16 temp_max_hyst[2]; + u32 alarms; }; static inline int is_word_sized(u16 reg) @@ -427,6 +432,13 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev) W83627EHF_REG_TEMP_HYST[i]); } + data->alarms = w83627ehf_read_value(client, + W83627EHF_REG_ALARM1) | + (w83627ehf_read_value(client, + W83627EHF_REG_ALARM2) << 8) | + (w83627ehf_read_value(client, + W83627EHF_REG_ALARM3) << 16); + data->last_updated = jiffies; data->valid = 1; } @@ -474,6 +486,14 @@ store_in_##reg (struct device *dev, struct device_attribute *attr, \ store_in_reg(MIN, min) store_in_reg(MAX, max) +static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct w83627ehf_data *data = w83627ehf_update_device(dev); + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + return sprintf(buf, "%u\n", (data->alarms >> nr) & 0x01); +} + static struct sensor_device_attribute sda_in_input[] = { SENSOR_ATTR(in0_input, S_IRUGO, show_in, NULL, 0), SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1), @@ -487,6 +507,19 @@ static struct sensor_device_attribute sda_in_input[] = { SENSOR_ATTR(in9_input, S_IRUGO, show_in, NULL, 9), }; +static struct sensor_device_attribute sda_in_alarm[] = { + SENSOR_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0), + SENSOR_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1), + SENSOR_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2), + SENSOR_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3), + SENSOR_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8), + SENSOR_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 21), + SENSOR_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 20), + SENSOR_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 16), + SENSOR_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 17), + SENSOR_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, 19), +}; + static struct sensor_device_attribute sda_in_min[] = { SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 0), SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 1), @@ -516,6 +549,7 @@ static struct sensor_device_attribute sda_in_max[] = { static void device_create_file_in(struct device *dev, int i) { device_create_file(dev, &sda_in_input[i].dev_attr); + device_create_file(dev, &sda_in_alarm[i].dev_attr); device_create_file(dev, &sda_in_min[i].dev_attr); device_create_file(dev, &sda_in_max[i].dev_attr); } @@ -618,6 +652,14 @@ static struct sensor_device_attribute sda_fan_input[] = { SENSOR_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4), }; +static struct sensor_device_attribute sda_fan_alarm[] = { + SENSOR_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6), + SENSOR_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7), + SENSOR_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11), + SENSOR_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, 10), + SENSOR_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 23), +}; + static struct sensor_device_attribute sda_fan_min[] = { SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 0), @@ -642,6 +684,7 @@ static struct sensor_device_attribute sda_fan_div[] = { static void device_create_file_fan(struct device *dev, int i) { device_create_file(dev, &sda_fan_input[i].dev_attr); + device_create_file(dev, &sda_fan_alarm[i].dev_attr); device_create_file(dev, &sda_fan_div[i].dev_attr); device_create_file(dev, &sda_fan_min[i].dev_attr); } @@ -729,6 +772,9 @@ static struct sensor_device_attribute sda_temp[] = { store_temp_max_hyst, 0), SENSOR_ATTR(temp3_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst, store_temp_max_hyst, 1), + SENSOR_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4), + SENSOR_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5), + SENSOR_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13), }; /* -- cgit v1.2.3 From 59ac83677f72ea2cc25b5426e7df9589aa7a5384 Mon Sep 17 00:00:00 2001 From: Hartmut Rick Date: Thu, 23 Mar 2006 16:37:23 +0100 Subject: [PATCH] smsc47m192: New hwmon driver for SMSC LPC47M192/997 New driver (smsc47m192) which supports voltage and temperature measurement features of SMSC LPC47M192 and LPC47M997 chips. Signed-off-by: Hartmut Rick Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- Documentation/hwmon/smsc47m192 | 102 ++++++ Documentation/hwmon/sysfs-interface | 6 + drivers/hwmon/Kconfig | 23 +- drivers/hwmon/Makefile | 1 + drivers/hwmon/smsc47m192.c | 648 ++++++++++++++++++++++++++++++++++++ 5 files changed, 779 insertions(+), 1 deletion(-) create mode 100644 Documentation/hwmon/smsc47m192 create mode 100644 drivers/hwmon/smsc47m192.c diff --git a/Documentation/hwmon/smsc47m192 b/Documentation/hwmon/smsc47m192 new file mode 100644 index 00000000000..45d6453cd43 --- /dev/null +++ b/Documentation/hwmon/smsc47m192 @@ -0,0 +1,102 @@ +Kernel driver smsc47m192 +======================== + +Supported chips: + * SMSC LPC47M192 and LPC47M997 + Prefix: 'smsc47m192' + Addresses scanned: I2C 0x2c - 0x2d + Datasheet: The datasheet for LPC47M192 is publicly available from + http://www.smsc.com/ + The LPC47M997 is compatible for hardware monitoring. + +Author: Hartmut Rick + Special thanks to Jean Delvare for careful checking + of the code and many helpful comments and suggestions. + + +Description +----------- + +This driver implements support for the hardware sensor capabilities +of the SMSC LPC47M192 and LPC47M997 Super-I/O chips. + +These chips support 3 temperature channels and 8 voltage inputs +as well as CPU voltage VID input. + +They do also have fan monitoring and control capabilities, but the +these features are accessed via ISA bus and are not supported by this +driver. Use the 'smsc47m1' driver for fan monitoring and control. + +Voltages and temperatures are measured by an 8-bit ADC, the resolution +of the temperatures is 1 bit per degree C. +Voltages are scaled such that the nominal voltage corresponds to +192 counts, i.e. 3/4 of the full range. Thus the available range for +each voltage channel is 0V ... 255/192*(nominal voltage), the resolution +is 1 bit per (nominal voltage)/192. +Both voltage and temperature values are scaled by 1000, the sys files +show voltages in mV and temperatures in units of 0.001 degC. + +The +12V analog voltage input channel (in4_input) is multiplexed with +bit 4 of the encoded CPU voltage. This means that you either get +a +12V voltage measurement or a 5 bit CPU VID, but not both. +The default setting is to use the pin as 12V input, and use only 4 bit VID. +This driver assumes that the information in the configuration register +is correct, i.e. that the BIOS has updated the configuration if +the motherboard has this input wired to VID4. + +The temperature and voltage readings are updated once every 1.5 seconds. +Reading them more often repeats the same values. + + +sysfs interface +--------------- + +in0_input - +2.5V voltage input +in1_input - CPU voltage input (nominal 2.25V) +in2_input - +3.3V voltage input +in3_input - +5V voltage input +in4_input - +12V voltage input (may be missing if used as VID4) +in5_input - Vcc voltage input (nominal 3.3V) + This is the supply voltage of the sensor chip itself. +in6_input - +1.5V voltage input +in7_input - +1.8V voltage input + +in[0-7]_min, +in[0-7]_max - lower and upper alarm thresholds for in[0-7]_input reading + + All voltages are read and written in mV. + +in[0-7]_alarm - alarm flags for voltage inputs + These files read '1' in case of alarm, '0' otherwise. + +temp1_input - chip temperature measured by on-chip diode +temp[2-3]_input - temperature measured by external diodes (one of these would + typically be wired to the diode inside the CPU) + +temp[1-3]_min, +temp[1-3]_max - lower and upper alarm thresholds for temperatures + +temp[1-3]_offset - temperature offset registers + The chip adds the offsets stored in these registers to + the corresponding temperature readings. + Note that temp1 and temp2 offsets share the same register, + they cannot both be different from zero at the same time. + Writing a non-zero number to one of them will reset the other + offset to zero. + + All temperatures and offsets are read and written in + units of 0.001 degC. + +temp[1-3]_alarm - alarm flags for temperature inputs, '1' in case of alarm, + '0' otherwise. +temp[2-3]_input_fault - diode fault flags for temperature inputs 2 and 3. + A fault is detected if the two pins for the corresponding + sensor are open or shorted, or any of the two is shorted + to ground or Vcc. '1' indicates a diode fault. + +cpu0_vid - CPU voltage as received from the CPU + +vrm - CPU VID standard used for decoding CPU voltage + + The *_min, *_max, *_offset and vrm files can be read and + written, all others are read-only. diff --git a/Documentation/hwmon/sysfs-interface b/Documentation/hwmon/sysfs-interface index a0d0ab24288..2d16e1e4017 100644 --- a/Documentation/hwmon/sysfs-interface +++ b/Documentation/hwmon/sysfs-interface @@ -218,6 +218,12 @@ temp[1-2]_crit_hyst from the critical value. Read/Write value. +temp[1-4]_offset + Temperature offset which is added to the temperature reading + by the chip. + Unit: millidegree Celsius + Read/Write value. + If there are multiple temperature sensors, temp1_* is generally the sensor inside the chip itself, reported as "motherboard temperature". temp2_* to diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index a6a8d66129b..9cf3d9c5962 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -333,11 +333,32 @@ config SENSORS_SMSC47M1 help If you say yes here you get support for the integrated fan monitoring and control capabilities of the SMSC LPC47B27x, - LPC47M10x, LPC47M13x, LPC47M14x, LPC47M15x and LPC47M192 chips. + LPC47M10x, LPC47M13x, LPC47M14x, LPC47M15x, LPC47M192 and + LPC47M997 chips. + + The temperature and voltage sensor features of the LPC47M192 + and LPC47M997 are supported by another driver, select also + "SMSC LPC47M192 and compatibles" below for those. This driver can also be built as a module. If so, the module will be called smsc47m1. +config SENSORS_SMSC47M192 + tristate "SMSC LPC47M192 and compatibles" + depends on HWMON && I2C && EXPERIMENTAL + select HWMON_VID + help + If you say yes here you get support for the temperature and + voltage sensors of the SMSC LPC47M192 and LPC47M997 chips. + + The fan monitoring and control capabilities of these chips + are supported by another driver, select + "SMSC LPC47M10x and compatibles" above. You need both drivers + if you want fan control and voltage/temperature sensor support. + + This driver can also be built as a module. If so, the module + will be called smsc47m192. + config SENSORS_SMSC47B397 tristate "SMSC LPC47B397-NC" depends on HWMON && I2C && EXPERIMENTAL diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index fbdb8d911a7..d0904593c9e 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -40,6 +40,7 @@ obj-$(CONFIG_SENSORS_PC87360) += pc87360.o obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o +obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o obj-$(CONFIG_SENSORS_VIA686A) += via686a.o obj-$(CONFIG_SENSORS_VT8231) += vt8231.o obj-$(CONFIG_SENSORS_W83627EHF) += w83627ehf.o diff --git a/drivers/hwmon/smsc47m192.c b/drivers/hwmon/smsc47m192.c new file mode 100644 index 00000000000..bdc4570acf9 --- /dev/null +++ b/drivers/hwmon/smsc47m192.c @@ -0,0 +1,648 @@ +/* + smsc47m192.c - Support for hardware monitoring block of + SMSC LPC47M192 and LPC47M997 Super I/O chips + + Copyright (C) 2006 Hartmut Rick + + Derived from lm78.c and other chip drivers. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Addresses to scan */ +static unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END }; + +/* Insmod parameters */ +I2C_CLIENT_INSMOD_1(smsc47m192); + +/* SMSC47M192 registers */ +#define SMSC47M192_REG_IN(nr) ((nr)<6 ? (0x20 + (nr)) : \ + (0x50 + (nr) - 6)) +#define SMSC47M192_REG_IN_MAX(nr) ((nr)<6 ? (0x2b + (nr) * 2) : \ + (0x54 + (((nr) - 6) * 2))) +#define SMSC47M192_REG_IN_MIN(nr) ((nr)<6 ? (0x2c + (nr) * 2) : \ + (0x55 + (((nr) - 6) * 2))) +static u8 SMSC47M192_REG_TEMP[3] = { 0x27, 0x26, 0x52 }; +static u8 SMSC47M192_REG_TEMP_MAX[3] = { 0x39, 0x37, 0x58 }; +static u8 SMSC47M192_REG_TEMP_MIN[3] = { 0x3A, 0x38, 0x59 }; +#define SMSC47M192_REG_TEMP_OFFSET(nr) ((nr)==2 ? 0x1e : 0x1f) +#define SMSC47M192_REG_ALARM1 0x41 +#define SMSC47M192_REG_ALARM2 0x42 +#define SMSC47M192_REG_VID 0x47 +#define SMSC47M192_REG_VID4 0x49 +#define SMSC47M192_REG_CONFIG 0x40 +#define SMSC47M192_REG_SFR 0x4f +#define SMSC47M192_REG_COMPANY_ID 0x3e +#define SMSC47M192_REG_VERSION 0x3f + +/* generalised scaling with integer rounding */ +static inline int SCALE(long val, int mul, int div) +{ + if (val < 0) + return (val * mul - div / 2) / div; + else + return (val * mul + div / 2) / div; +} + +/* Conversions */ + +/* smsc47m192 internally scales voltage measurements */ +static const u16 nom_mv[] = { 2500, 2250, 3300, 5000, 12000, 3300, 1500, 1800 }; + +static inline unsigned int IN_FROM_REG(u8 reg, int n) +{ + return SCALE(reg, nom_mv[n], 192); +} + +static inline u8 IN_TO_REG(unsigned long val, int n) +{ + return SENSORS_LIMIT(SCALE(val, 192, nom_mv[n]), 0, 255); +} + +/* TEMP: 0.001 degC units (-128C to +127C) + REG: 1C/bit, two's complement */ +static inline s8 TEMP_TO_REG(int val) +{ + return SENSORS_LIMIT(SCALE(val, 1, 1000), -128000, 127000); +} + +static inline int TEMP_FROM_REG(s8 val) +{ + return val * 1000; +} + +struct smsc47m192_data { + struct i2c_client client; + struct class_device *class_dev; + struct semaphore update_lock; + char valid; /* !=0 if following fields are valid */ + unsigned long last_updated; /* In jiffies */ + + u8 in[8]; /* Register value */ + u8 in_max[8]; /* Register value */ + u8 in_min[8]; /* Register value */ + s8 temp[3]; /* Register value */ + s8 temp_max[3]; /* Register value */ + s8 temp_min[3]; /* Register value */ + s8 temp_offset[3]; /* Register value */ + u16 alarms; /* Register encoding, combined */ + u8 vid; /* Register encoding, combined */ + u8 vrm; +}; + +static int smsc47m192_attach_adapter(struct i2c_adapter *adapter); +static int smsc47m192_detect(struct i2c_adapter *adapter, int address, + int kind); +static int smsc47m192_detach_client(struct i2c_client *client); +static struct smsc47m192_data *smsc47m192_update_device(struct device *dev); + +static struct i2c_driver smsc47m192_driver = { + .driver = { + .name = "smsc47m192", + }, + .attach_adapter = smsc47m192_attach_adapter, + .detach_client = smsc47m192_detach_client, +}; + +/* Voltages */ +static ssize_t show_in(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + struct smsc47m192_data *data = smsc47m192_update_device(dev); + return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr], nr)); +} + +static ssize_t show_in_min(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + struct smsc47m192_data *data = smsc47m192_update_device(dev); + return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[nr], nr)); +} + +static ssize_t show_in_max(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + struct smsc47m192_data *data = smsc47m192_update_device(dev); + return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[nr], nr)); +} + +static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + struct i2c_client *client = to_i2c_client(dev); + struct smsc47m192_data *data = i2c_get_clientdata(client); + unsigned long val = simple_strtoul(buf, NULL, 10); + + down(&data->update_lock); + data->in_min[nr] = IN_TO_REG(val, nr); + i2c_smbus_write_byte_data(client, SMSC47M192_REG_IN_MIN(nr), + data->in_min[nr]); + up(&data->update_lock); + return count; +} + +static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + struct i2c_client *client = to_i2c_client(dev); + struct smsc47m192_data *data = i2c_get_clientdata(client); + unsigned long val = simple_strtoul(buf, NULL, 10); + + down(&data->update_lock); + data->in_max[nr] = IN_TO_REG(val, nr); + i2c_smbus_write_byte_data(client, SMSC47M192_REG_IN_MAX(nr), + data->in_max[nr]); + up(&data->update_lock); + return count; +} + +#define show_in_offset(offset) \ +static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ + show_in, NULL, offset); \ +static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ + show_in_min, set_in_min, offset); \ +static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ + show_in_max, set_in_max, offset); + +show_in_offset(0) +show_in_offset(1) +show_in_offset(2) +show_in_offset(3) +show_in_offset(4) +show_in_offset(5) +show_in_offset(6) +show_in_offset(7) + +/* Temperatures */ +static ssize_t show_temp(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + struct smsc47m192_data *data = smsc47m192_update_device(dev); + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr])); +} + +static ssize_t show_temp_min(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + struct smsc47m192_data *data = smsc47m192_update_device(dev); + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[nr])); +} + +static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + struct smsc47m192_data *data = smsc47m192_update_device(dev); + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[nr])); +} + +static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + struct i2c_client *client = to_i2c_client(dev); + struct smsc47m192_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + + down(&data->update_lock); + data->temp_min[nr] = TEMP_TO_REG(val); + i2c_smbus_write_byte_data(client, SMSC47M192_REG_TEMP_MIN[nr], + data->temp_min[nr]); + up(&data->update_lock); + return count; +} + +static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + struct i2c_client *client = to_i2c_client(dev); + struct smsc47m192_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + + down(&data->update_lock); + data->temp_max[nr] = TEMP_TO_REG(val); + i2c_smbus_write_byte_data(client, SMSC47M192_REG_TEMP_MAX[nr], + data->temp_max[nr]); + up(&data->update_lock); + return count; +} + +static ssize_t show_temp_offset(struct device *dev, struct device_attribute + *attr, char *buf) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + struct smsc47m192_data *data = smsc47m192_update_device(dev); + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_offset[nr])); +} + +static ssize_t set_temp_offset(struct device *dev, struct device_attribute + *attr, const char *buf, size_t count) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + struct i2c_client *client = to_i2c_client(dev); + struct smsc47m192_data *data = i2c_get_clientdata(client); + u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR); + long val = simple_strtol(buf, NULL, 10); + + down(&data->update_lock); + data->temp_offset[nr] = TEMP_TO_REG(val); + if (nr>1) + i2c_smbus_write_byte_data(client, + SMSC47M192_REG_TEMP_OFFSET(nr), data->temp_offset[nr]); + else if (data->temp_offset[nr] != 0) { + /* offset[0] and offset[1] share the same register, + SFR bit 4 activates offset[0] */ + i2c_smbus_write_byte_data(client, SMSC47M192_REG_SFR, + (sfr & 0xef) | (nr==0 ? 0x10 : 0)); + data->temp_offset[1-nr] = 0; + i2c_smbus_write_byte_data(client, + SMSC47M192_REG_TEMP_OFFSET(nr), data->temp_offset[nr]); + } else if ((sfr & 0x10) == (nr==0 ? 0x10 : 0)) + i2c_smbus_write_byte_data(client, + SMSC47M192_REG_TEMP_OFFSET(nr), 0); + up(&data->update_lock); + return count; +} + +#define show_temp_index(index) \ +static SENSOR_DEVICE_ATTR(temp##index##_input, S_IRUGO, \ + show_temp, NULL, index-1); \ +static SENSOR_DEVICE_ATTR(temp##index##_min, S_IRUGO | S_IWUSR, \ + show_temp_min, set_temp_min, index-1); \ +static SENSOR_DEVICE_ATTR(temp##index##_max, S_IRUGO | S_IWUSR, \ + show_temp_max, set_temp_max, index-1); \ +static SENSOR_DEVICE_ATTR(temp##index##_offset, S_IRUGO | S_IWUSR, \ + show_temp_offset, set_temp_offset, index-1); + +show_temp_index(1) +show_temp_index(2) +show_temp_index(3) + +/* VID */ +static ssize_t show_vid(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct smsc47m192_data *data = smsc47m192_update_device(dev); + return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm)); +} +static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); + +static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct smsc47m192_data *data = smsc47m192_update_device(dev); + return sprintf(buf, "%d\n", data->vrm); +} + +static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct smsc47m192_data *data = i2c_get_clientdata(client); + data->vrm = simple_strtoul(buf, NULL, 10); + return count; +} +static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm); + +/* Alarms */ +static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + struct smsc47m192_data *data = smsc47m192_update_device(dev); + return sprintf(buf, "%u\n", (data->alarms & nr) ? 1 : 0); +} + +static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 0x0010); +static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 0x0020); +static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 0x0040); +static SENSOR_DEVICE_ATTR(temp2_input_fault, S_IRUGO, show_alarm, NULL, 0x4000); +static SENSOR_DEVICE_ATTR(temp3_input_fault, S_IRUGO, show_alarm, NULL, 0x8000); +static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0x0001); +static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 0x0002); +static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 0x0004); +static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 0x0008); +static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 0x0100); +static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 0x0200); +static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 0x0400); +static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 0x0800); + +/* This function is called when: + * smsc47m192_driver is inserted (when this module is loaded), for each + available adapter + * when a new adapter is inserted (and smsc47m192_driver is still present) */ +static int smsc47m192_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, smsc47m192_detect); +} + +static void smsc47m192_init_client(struct i2c_client *client) +{ + int i; + u8 config = i2c_smbus_read_byte_data(client, SMSC47M192_REG_CONFIG); + u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR); + + /* select cycle mode (pause 1 sec between updates) */ + i2c_smbus_write_byte_data(client, SMSC47M192_REG_SFR, + (sfr & 0xfd) | 0x02); + if (!(config & 0x01)) { + /* initialize alarm limits */ + for (i=0; i<8; i++) { + i2c_smbus_write_byte_data(client, + SMSC47M192_REG_IN_MIN(i), 0); + i2c_smbus_write_byte_data(client, + SMSC47M192_REG_IN_MAX(i), 0xff); + } + for (i=0; i<3; i++) { + i2c_smbus_write_byte_data(client, + SMSC47M192_REG_TEMP_MIN[i], 0x80); + i2c_smbus_write_byte_data(client, + SMSC47M192_REG_TEMP_MAX[i], 0x7f); + } + + /* start monitoring */ + i2c_smbus_write_byte_data(client, SMSC47M192_REG_CONFIG, + (config & 0xf7) | 0x01); + } +} + +/* This function is called by i2c_probe */ +static int smsc47m192_detect(struct i2c_adapter *adapter, int address, + int kind) +{ + struct i2c_client *client; + struct smsc47m192_data *data; + int err = 0; + int version, config; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + goto exit; + + if (!(data = kzalloc(sizeof(struct smsc47m192_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + client = &data->client; + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &smsc47m192_driver; + + if (kind == 0) + kind = smsc47m192; + + /* Detection criteria from sensors_detect script */ + if (kind < 0) { + if (i2c_smbus_read_byte_data(client, + SMSC47M192_REG_COMPANY_ID) == 0x55 + && ((version = i2c_smbus_read_byte_data(client, + SMSC47M192_REG_VERSION)) & 0xf0) == 0x20 + && (i2c_smbus_read_byte_data(client, + SMSC47M192_REG_VID) & 0x70) == 0x00 + && (i2c_smbus_read_byte_data(client, + SMSC47M192_REG_VID4) & 0xfe) == 0x80) { + dev_info(&adapter->dev, + "found SMSC47M192 or SMSC47M997, " + "version 2, stepping A%d\n", version & 0x0f); + } else { + dev_dbg(&adapter->dev, + "SMSC47M192 detection failed at 0x%02x\n", + address); + goto exit_free; + } + } + + /* Fill in the remaining client fields and put into the global list */ + strlcpy(client->name, "smsc47m192", I2C_NAME_SIZE); + data->vrm = vid_which_vrm(); + init_MUTEX(&data->update_lock); + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(client))) + goto exit_free; + + /* Initialize the SMSC47M192 chip */ + smsc47m192_init_client(client); + + /* Register sysfs hooks */ + data->class_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->class_dev)) { + err = PTR_ERR(data->class_dev); + goto exit_detach; + } + + device_create_file(&client->dev, &sensor_dev_attr_in0_input.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in0_min.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in0_max.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in0_alarm.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in1_input.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in1_min.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in1_max.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in1_alarm.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in2_input.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in2_min.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in2_max.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in2_alarm.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in3_input.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in3_min.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in3_max.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in3_alarm.dev_attr); + + /* Pin 110 is either in4 (+12V) or VID4 */ + config = i2c_smbus_read_byte_data(client, SMSC47M192_REG_CONFIG); + if (!(config & 0x20)) { + device_create_file(&client->dev, + &sensor_dev_attr_in4_input.dev_attr); + device_create_file(&client->dev, + &sensor_dev_attr_in4_min.dev_attr); + device_create_file(&client->dev, + &sensor_dev_attr_in4_max.dev_attr); + device_create_file(&client->dev, + &sensor_dev_attr_in4_alarm.dev_attr); + } + device_create_file(&client->dev, &sensor_dev_attr_in5_input.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in5_min.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in5_max.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in5_alarm.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in6_input.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in6_min.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in6_max.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in6_alarm.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in7_input.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in7_min.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in7_max.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in7_alarm.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_temp1_input.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_temp1_max.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_temp1_min.dev_attr); + device_create_file(&client->dev, + &sensor_dev_attr_temp1_offset.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_temp1_alarm.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_temp2_input.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_temp2_max.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_temp2_min.dev_attr); + device_create_file(&client->dev, + &sensor_dev_attr_temp2_offset.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_temp2_alarm.dev_attr); + device_create_file(&client->dev, + &sensor_dev_attr_temp2_input_fault.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_temp3_input.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_temp3_max.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_temp3_min.dev_attr); + device_create_file(&client->dev, + &sensor_dev_attr_temp3_offset.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_temp3_alarm.dev_attr); + device_create_file(&client->dev, + &sensor_dev_attr_temp3_input_fault.dev_attr); + device_create_file(&client->dev, &dev_attr_cpu0_vid); + device_create_file(&client->dev, &dev_attr_vrm); + + return 0; + +exit_detach: + i2c_detach_client(client); +exit_free: + kfree(data); +exit: + return err; +} + +static int smsc47m192_detach_client(struct i2c_client *client) +{ + struct smsc47m192_data *data = i2c_get_clientdata(client); + int err; + + hwmon_device_unregister(data->class_dev); + + if ((err = i2c_detach_client(client))) + return err; + + kfree(data); + + return 0; +} + +static struct smsc47m192_data *smsc47m192_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct smsc47m192_data *data = i2c_get_clientdata(client); + int i, config; + + down(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR); + + dev_dbg(&client->dev, "Starting smsc47m192 update\n"); + + for (i = 0; i <= 7; i++) { + data->in[i] = i2c_smbus_read_byte_data(client, + SMSC47M192_REG_IN(i)); + data->in_min[i] = i2c_smbus_read_byte_data(client, + SMSC47M192_REG_IN_MIN(i)); + data->in_max[i] = i2c_smbus_read_byte_data(client, + SMSC47M192_REG_IN_MAX(i)); + } + for (i = 0; i < 3; i++) { + data->temp[i] = i2c_smbus_read_byte_data(client, + SMSC47M192_REG_TEMP[i]); + data->temp_max[i] = i2c_smbus_read_byte_data(client, + SMSC47M192_REG_TEMP_MAX[i]); + data->temp_min[i] = i2c_smbus_read_byte_data(client, + SMSC47M192_REG_TEMP_MIN[i]); + } + for (i = 1; i < 3; i++) + data->temp_offset[i] = i2c_smbus_read_byte_data(client, + SMSC47M192_REG_TEMP_OFFSET(i)); + /* first offset is temp_offset[0] if SFR bit 4 is set, + temp_offset[1] otherwise */ + if (sfr & 0x10) { + data->temp_offset[0] = data->temp_offset[1]; + data->temp_offset[1] = 0; + } else + data->temp_offset[0] = 0; + + data->vid = i2c_smbus_read_byte_data(client, SMSC47M192_REG_VID) + & 0x0f; + config = i2c_smbus_read_byte_data(client, + SMSC47M192_REG_CONFIG); + if (config & 0x20) + data->vid |= (i2c_smbus_read_byte_data(client, + SMSC47M192_REG_VID4) & 0x01) << 4; + data->alarms = i2c_smbus_read_byte_data(client, + SMSC47M192_REG_ALARM1) | + (i2c_smbus_read_byte_data(client, + SMSC47M192_REG_ALARM2) << 8); + + data->last_updated = jiffies; + data->valid = 1; + } + + up(&data->update_lock); + + return data; +} + +static int __init smsc47m192_init(void) +{ + return i2c_add_driver(&smsc47m192_driver); +} + +static void __exit smsc47m192_exit(void) +{ + i2c_del_driver(&smsc47m192_driver); +} + +MODULE_AUTHOR("Hartmut Rick "); +MODULE_DESCRIPTION("SMSC47M192 driver"); +MODULE_LICENSE("GPL"); + +module_init(smsc47m192_init); +module_exit(smsc47m192_exit); -- cgit v1.2.3 From 568825c8ed3c902981ce908ed5693abb3c9ddf59 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 23 Mar 2006 16:40:23 +0100 Subject: [PATCH] f71805f: Resource needs not be global The F71805F I/O resource structure needs not be a global variable, as the platform core allocs its own copy of it anyway. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/f71805f.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c index 885465df6e6..fd72440faf7 100644 --- a/drivers/hwmon/f71805f.c +++ b/drivers/hwmon/f71805f.c @@ -99,10 +99,6 @@ superio_exit(int base) #define ADDR_REG_OFFSET 0 #define DATA_REG_OFFSET 1 -static struct resource f71805f_resource __initdata = { - .flags = IORESOURCE_IO, -}; - /* * Registers */ @@ -782,6 +778,11 @@ static struct platform_driver f71805f_driver = { static int __init f71805f_device_add(unsigned short address) { + struct resource res = { + .start = address, + .end = address + REGION_LENGTH - 1, + .flags = IORESOURCE_IO, + }; int err; pdev = platform_device_alloc(DRVNAME, address); @@ -791,10 +792,8 @@ static int __init f71805f_device_add(unsigned short address) goto exit; } - f71805f_resource.start = address; - f71805f_resource.end = address + REGION_LENGTH - 1; - f71805f_resource.name = pdev->name; - err = platform_device_add_resources(pdev, &f71805f_resource, 1); + res.name = pdev->name; + err = platform_device_add_resources(pdev, &res, 1); if (err) { printk(KERN_ERR DRVNAME ": Device resource addition failed " "(%d)\n", err); -- cgit v1.2.3 From 400b48ecd95a7fac6b126042d37b7efe0202b582 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 23 Mar 2006 16:46:47 +0100 Subject: [PATCH] hwmon: Add sysfs interface for individual alarm files Extend the sysfs interface of hardware monitoring chips, by adding individual alarm and beep files. Contrary to the old aggregated "alarms" and "beeps" files, individual files constitute a standard way to access the status information, making it finally possible to implement a chip-independant hardware monitoring chip access library (once all drivers have been added this new interface, that is.) If future drivers need more individual files, the interface will be extended as needed at the same time these drivers are merged into the kernel tree. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- Documentation/hwmon/sysfs-interface | 98 +++++++++++++++++++++++++++---------- 1 file changed, 73 insertions(+), 25 deletions(-) diff --git a/Documentation/hwmon/sysfs-interface b/Documentation/hwmon/sysfs-interface index 2d16e1e4017..eeb912254db 100644 --- a/Documentation/hwmon/sysfs-interface +++ b/Documentation/hwmon/sysfs-interface @@ -252,9 +252,68 @@ curr[1-n]_input Current input value Read only. -********* -* Other * -********* +********** +* Alarms * +********** + +Each channel or limit may have an associated alarm file, containing a +boolean value. 1 means than an alarm condition exists, 0 means no alarm. + +Usually a given chip will either use channel-related alarms, or +limit-related alarms, not both. The driver should just reflect the hardware +implementation. + +in[0-n]_alarm +fan[1-n]_alarm +temp[1-n]_alarm + Channel alarm + Boolean + Read-only + +OR + +in[0-n]_min_alarm +in[0-n]_max_alarm +fan[1-n]_min_alarm +temp[1-n]_min_alarm +temp[1-n]_max_alarm +temp[1-n]_crit_alarm + Limit alarm + Boolean + Read-only + +Each input channel may have an associated fault file. This can be used +to notify open diodes, unconnected fans etc. where the hardware +supports it. When this boolean has value 1, the measurement for that +channel should not be trusted. + +in[0-n]_input_fault +fan[1-n]_input_fault +temp[1-n]_input_fault + Input fault condition + Boolean + Read-only + +Some chips also offer the possibility to get beeped when an alarm occurs: + +beep_enable Master beep enable + Boolean + Read/Write + +in[0-n]_beep +fan[1-n]_beep +temp[1-n]_beep + Channel beep + 0 to disable. + 1 to enable. + Read/write + +In theory, a chip could provide per-limit beep masking, but no such chip +was seen so far. + +Old drivers provided a different, non-standard interface to alarms and +beeps. These interface files are deprecated, but will be kept around +for compatibility reasons: alarms Alarm bitmask. Read only. @@ -265,33 +324,22 @@ alarms Alarm bitmask. if it is still valid. Generally a direct representation of a chip's internal alarm registers; there is no standard for the position - of individual bits. + of individual bits. For this reason, the use of this + interface file for new drivers is discouraged. Use + individual *_alarm and *_fault files instead. Bits are defined in kernel/include/sensors.h. -alarms_in Alarm bitmask relative to in (voltage) channels - Read only - A '1' bit means an alarm, LSB corresponds to in0 and so on - Prefered to 'alarms' for newer chips - -alarms_fan Alarm bitmask relative to fan channels - Read only - A '1' bit means an alarm, LSB corresponds to fan1 and so on - Prefered to 'alarms' for newer chips - -alarms_temp Alarm bitmask relative to temp (temperature) channels - Read only - A '1' bit means an alarm, LSB corresponds to temp1 and so on - Prefered to 'alarms' for newer chips - -beep_enable Beep/interrupt enable - 0 to disable. - 1 to enable. - Read/Write - beep_mask Bitmask for beep. - Same format as 'alarms' with the same bit locations. + Same format as 'alarms' with the same bit locations, + use discouraged for the same reason. Use individual + *_beep files instead. Read/Write + +********* +* Other * +********* + eeprom Raw EEPROM data in binary form. Read only. -- cgit v1.2.3 From 02e0c5d5c2e00374b6808a42f8eea4ea9baaa216 Mon Sep 17 00:00:00 2001 From: Rudolf Marek Date: Thu, 23 Mar 2006 16:48:09 +0100 Subject: [PATCH] i2c-piix4: Add ATI IXP200/300/400 support This patch adds the ATI IXP southbridges support to i2c-piix4, as it turned out those chips are compatible with it. Signed-off-by: Rudolf Marek Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- Documentation/i2c/busses/i2c-piix4 | 2 ++ drivers/i2c/busses/Kconfig | 5 ++++- drivers/i2c/busses/i2c-piix4.c | 6 ++++++ include/linux/pci_ids.h | 3 +++ 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/Documentation/i2c/busses/i2c-piix4 b/Documentation/i2c/busses/i2c-piix4 index a1c8f581afe..6e6c905143a 100644 --- a/Documentation/i2c/busses/i2c-piix4 +++ b/Documentation/i2c/busses/i2c-piix4 @@ -6,6 +6,8 @@ Supported adapters: Datasheet: Publicly available at the Intel website * ServerWorks OSB4, CSB5, CSB6 and HT-1000 southbridges Datasheet: Only available via NDA from ServerWorks + * ATI IXP southbridges IXP200, IXP300, IXP400 + Datasheet: Not publicly available * Standard Microsystems (SMSC) SLC90E66 (Victory66) southbridge Datasheet: Publicly available at the SMSC website http://www.smsc.com diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index d6d44946a28..e3450d16d8a 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -163,7 +163,7 @@ config I2C_PXA_SLAVE I2C bus. config I2C_PIIX4 - tristate "Intel PIIX4" + tristate "Intel PIIX4 and compatible (ATI/Serverworks/Broadcom/SMSC)" depends on I2C && PCI help If you say yes to this option, support will be included for the Intel @@ -172,6 +172,9 @@ config I2C_PIIX4 of Broadcom): Intel PIIX4 Intel 440MX + ATI IXP200 + ATI IXP300 + ATI IXP400 Serverworks OSB4 Serverworks CSB5 Serverworks CSB6 diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index d9c7c00e71f..5f06e81a208 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c @@ -413,6 +413,12 @@ static struct i2c_adapter piix4_adapter = { static struct pci_device_id piix4_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3), .driver_data = 3 }, + { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP200_SMBUS), + .driver_data = 0 }, + { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP300_SMBUS), + .driver_data = 0 }, + { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_SMBUS), + .driver_data = 0 }, { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4), .driver_data = 0 }, { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5), diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index bcfe9d4f56a..489af9d3ce1 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -352,8 +352,11 @@ #define PCI_DEVICE_ID_ATI_RS480 0x5950 /* ATI IXP Chipset */ #define PCI_DEVICE_ID_ATI_IXP200_IDE 0x4349 +#define PCI_DEVICE_ID_ATI_IXP200_SMBUS 0x4353 +#define PCI_DEVICE_ID_ATI_IXP300_SMBUS 0x4363 #define PCI_DEVICE_ID_ATI_IXP300_IDE 0x4369 #define PCI_DEVICE_ID_ATI_IXP300_SATA 0x436e +#define PCI_DEVICE_ID_ATI_IXP400_SMBUS 0x4372 #define PCI_DEVICE_ID_ATI_IXP400_IDE 0x4376 #define PCI_DEVICE_ID_ATI_IXP400_SATA 0x4379 #define PCI_DEVICE_ID_ATI_IXP400_SATA2 0x437a -- cgit v1.2.3 From e931b8d8a428f87e6ea488d2fd80007bb66b3ea8 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Fri, 31 Mar 2006 23:06:46 +0200 Subject: [PATCH] i2c: cleanup m41t00 This patch does some cleanup to the m41t00 i2c/rtc driver including: - use BCD2BIN/BIN2BCD instead of BCD_TO_BIN/BIN_TO_BCD - use strlcpy instead of strncpy - some whitespace cleanup Signed-off-by: Mark A. Greer Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/chips/m41t00.c | 49 ++++++++++++++++++++-------------------------- 1 file changed, 21 insertions(+), 28 deletions(-) diff --git a/drivers/i2c/chips/m41t00.c b/drivers/i2c/chips/m41t00.c index 99ab4ec3439..eb2be3e4416 100644 --- a/drivers/i2c/chips/m41t00.c +++ b/drivers/i2c/chips/m41t00.c @@ -1,6 +1,4 @@ /* - * drivers/i2c/chips/m41t00.c - * * I2C client/driver for the ST M41T00 Real-Time Clock chip. * * Author: Mark A. Greer @@ -13,9 +11,6 @@ /* * This i2c client/driver wedges between the drivers/char/genrtc.c RTC * interface and the SMBus interface of the i2c subsystem. - * It would be more efficient to use i2c msgs/i2c_transfer directly but, as - * recommened in .../Documentation/i2c/writing-clients section - * "Sending and receiving", using SMBus level communication is preferred. */ #include @@ -41,17 +36,17 @@ static unsigned short ignore[] = { I2C_CLIENT_END }; static unsigned short normal_addr[] = { 0x68, I2C_CLIENT_END }; static struct i2c_client_address_data addr_data = { - .normal_i2c = normal_addr, - .probe = ignore, - .ignore = ignore, + .normal_i2c = normal_addr, + .probe = ignore, + .ignore = ignore, }; ulong m41t00_get_rtc_time(void) { - s32 sec, min, hour, day, mon, year; - s32 sec1, min1, hour1, day1, mon1, year1; - ulong limit = 10; + s32 sec, min, hour, day, mon, year; + s32 sec1, min1, hour1, day1, mon1, year1; + ulong limit = 10; sec = min = hour = day = mon = year = 0; sec1 = min1 = hour1 = day1 = mon1 = year1 = 0; @@ -97,12 +92,12 @@ m41t00_get_rtc_time(void) mon &= 0x1f; year &= 0xff; - BCD_TO_BIN(sec); - BCD_TO_BIN(min); - BCD_TO_BIN(hour); - BCD_TO_BIN(day); - BCD_TO_BIN(mon); - BCD_TO_BIN(year); + sec = BCD2BIN(sec); + min = BCD2BIN(min); + hour = BCD2BIN(hour); + day = BCD2BIN(day); + mon = BCD2BIN(mon); + year = BCD2BIN(year); year += 1900; if (year < 1970) @@ -115,17 +110,17 @@ static void m41t00_set(void *arg) { struct rtc_time tm; - ulong nowtime = *(ulong *)arg; + ulong nowtime = *(ulong *)arg; to_tm(nowtime, &tm); tm.tm_year = (tm.tm_year - 1900) % 100; - BIN_TO_BCD(tm.tm_sec); - BIN_TO_BCD(tm.tm_min); - BIN_TO_BCD(tm.tm_hour); - BIN_TO_BCD(tm.tm_mon); - BIN_TO_BCD(tm.tm_mday); - BIN_TO_BCD(tm.tm_year); + tm.tm_sec = BIN2BCD(tm.tm_sec); + tm.tm_min = BIN2BCD(tm.tm_min); + tm.tm_hour = BIN2BCD(tm.tm_hour); + tm.tm_mon = BIN2BCD(tm.tm_mon); + tm.tm_mday = BIN2BCD(tm.tm_mday); + tm.tm_year = BIN2BCD(tm.tm_year); mutex_lock(&m41t00_mutex); if ((i2c_smbus_write_byte_data(save_client, 0, tm.tm_sec & 0x7f) < 0) @@ -143,7 +138,6 @@ m41t00_set(void *arg) dev_warn(&save_client->dev,"m41t00: can't write to rtc chip\n"); mutex_unlock(&m41t00_mutex); - return; } static ulong new_time; @@ -180,7 +174,7 @@ m41t00_probe(struct i2c_adapter *adap, int addr, int kind) if (!client) return -ENOMEM; - strncpy(client->name, M41T00_DRV_NAME, I2C_NAME_SIZE); + strlcpy(client->name, M41T00_DRV_NAME, I2C_NAME_SIZE); client->addr = addr; client->adapter = adap; client->driver = &m41t00_driver; @@ -204,7 +198,7 @@ m41t00_attach(struct i2c_adapter *adap) static int m41t00_detach(struct i2c_client *client) { - int rc; + int rc; if ((rc = i2c_detach_client(client)) == 0) { kfree(client); @@ -232,7 +226,6 @@ static void __exit m41t00_exit(void) { i2c_del_driver(&m41t00_driver); - return; } module_init(m41t00_init); -- cgit v1.2.3 From 5e9f4f2e5a02bb6908278a819952aa31fffefaa2 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Tue, 25 Apr 2006 13:04:54 +0200 Subject: [PATCH] I2C: m41t00: Add support for the ST M41T81 and M41T85 This patch adds support for the ST m41t81 and m41t85 i2c rtc chips to the existing m41t00 driver. Since there is no way to reliably determine what type of rtc chip is in use, the chip type is passed in via platform_data. The i2c address and square wave frequency are passed in via platform_data as well. To accommodate the use of platform_data, a new header file include/linux/m41t00.h has been added. The m41t81 and m41t85 chips halt the updating of their time registers while they are being accessed. They resume when a stop condition exists on the i2c bus or when non-time related regs are accessed. To make the best use of that facility and to make more efficient use of the i2c bus, this patch replaces multiple i2c_smbus_xxx calls with a single i2c_transfer call. Signed-off-by: Mark A. Greer Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/chips/m41t00.c | 313 ++++++++++++++++++++++++++++++++++----------- include/linux/m41t00.h | 50 ++++++++ 2 files changed, 291 insertions(+), 72 deletions(-) create mode 100644 include/linux/m41t00.h diff --git a/drivers/i2c/chips/m41t00.c b/drivers/i2c/chips/m41t00.c index eb2be3e4416..2dd0a34d947 100644 --- a/drivers/i2c/chips/m41t00.c +++ b/drivers/i2c/chips/m41t00.c @@ -1,9 +1,9 @@ /* - * I2C client/driver for the ST M41T00 Real-Time Clock chip. + * I2C client/driver for the ST M41T00 family of i2c rtc chips. * * Author: Mark A. Greer * - * 2005 (c) MontaVista Software, Inc. This file is licensed under + * 2005, 2006 (c) MontaVista Software, Inc. This file is licensed under * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. @@ -19,21 +19,17 @@ #include #include #include -#include #include - +#include +#include #include #include -#define M41T00_DRV_NAME "m41t00" - -static DEFINE_MUTEX(m41t00_mutex); - static struct i2c_driver m41t00_driver; static struct i2c_client *save_client; static unsigned short ignore[] = { I2C_CLIENT_END }; -static unsigned short normal_addr[] = { 0x68, I2C_CLIENT_END }; +static unsigned short normal_addr[] = { I2C_CLIENT_END, I2C_CLIENT_END }; static struct i2c_client_address_data addr_data = { .normal_i2c = normal_addr, @@ -41,34 +37,92 @@ static struct i2c_client_address_data addr_data = { .ignore = ignore, }; +struct m41t00_chip_info { + u8 type; + char *name; + u8 read_limit; + u8 sec; /* Offsets for chip regs */ + u8 min; + u8 hour; + u8 day; + u8 mon; + u8 year; + u8 alarm_mon; + u8 alarm_hour; + u8 sqw; + u8 sqw_freq; +}; + +static struct m41t00_chip_info m41t00_chip_info_tbl[] = { + { + .type = M41T00_TYPE_M41T00, + .name = "m41t00", + .read_limit = 5, + .sec = 0, + .min = 1, + .hour = 2, + .day = 4, + .mon = 5, + .year = 6, + }, + { + .type = M41T00_TYPE_M41T81, + .name = "m41t81", + .read_limit = 1, + .sec = 1, + .min = 2, + .hour = 3, + .day = 5, + .mon = 6, + .year = 7, + .alarm_mon = 0xa, + .alarm_hour = 0xc, + .sqw = 0x13, + }, + { + .type = M41T00_TYPE_M41T85, + .name = "m41t85", + .read_limit = 1, + .sec = 1, + .min = 2, + .hour = 3, + .day = 5, + .mon = 6, + .year = 7, + .alarm_mon = 0xa, + .alarm_hour = 0xc, + .sqw = 0x13, + }, +}; +static struct m41t00_chip_info *m41t00_chip; + ulong m41t00_get_rtc_time(void) { s32 sec, min, hour, day, mon, year; s32 sec1, min1, hour1, day1, mon1, year1; - ulong limit = 10; + u8 reads = 0; + u8 buf[8], msgbuf[1] = { 0 }; /* offset into rtc's regs */ + struct i2c_msg msgs[] = { + { + .addr = save_client->addr, + .flags = 0, + .len = 1, + .buf = msgbuf, + }, + { + .addr = save_client->addr, + .flags = I2C_M_RD, + .len = 8, + .buf = buf, + }, + }; sec = min = hour = day = mon = year = 0; - sec1 = min1 = hour1 = day1 = mon1 = year1 = 0; - mutex_lock(&m41t00_mutex); do { - if (((sec = i2c_smbus_read_byte_data(save_client, 0)) >= 0) - && ((min = i2c_smbus_read_byte_data(save_client, 1)) - >= 0) - && ((hour = i2c_smbus_read_byte_data(save_client, 2)) - >= 0) - && ((day = i2c_smbus_read_byte_data(save_client, 4)) - >= 0) - && ((mon = i2c_smbus_read_byte_data(save_client, 5)) - >= 0) - && ((year = i2c_smbus_read_byte_data(save_client, 6)) - >= 0) - && ((sec == sec1) && (min == min1) && (hour == hour1) - && (day == day1) && (mon == mon1) - && (year == year1))) - - break; + if (i2c_transfer(save_client->adapter, msgs, 2) < 0) + goto read_err; sec1 = sec; min1 = min; @@ -76,21 +130,21 @@ m41t00_get_rtc_time(void) day1 = day; mon1 = mon; year1 = year; - } while (--limit > 0); - mutex_unlock(&m41t00_mutex); - - if (limit == 0) { - dev_warn(&save_client->dev, - "m41t00: can't read rtc chip\n"); - sec = min = hour = day = mon = year = 0; - } - sec &= 0x7f; - min &= 0x7f; - hour &= 0x3f; - day &= 0x3f; - mon &= 0x1f; - year &= 0xff; + sec = buf[m41t00_chip->sec] & 0x7f; + min = buf[m41t00_chip->min] & 0x7f; + hour = buf[m41t00_chip->hour] & 0x3f; + day = buf[m41t00_chip->day] & 0x3f; + mon = buf[m41t00_chip->mon] & 0x1f; + year = buf[m41t00_chip->year]; + } while ((++reads < m41t00_chip->read_limit) && ((sec != sec1) + || (min != min1) || (hour != hour1) || (day != day1) + || (mon != mon1) || (year != year1))); + + if ((m41t00_chip->read_limit > 1) && ((sec != sec1) || (min != min1) + || (hour != hour1) || (day != day1) || (mon != mon1) + || (year != year1))) + goto read_err; sec = BCD2BIN(sec); min = BCD2BIN(min); @@ -104,40 +158,60 @@ m41t00_get_rtc_time(void) year += 100; return mktime(year, mon, day, hour, min, sec); + +read_err: + dev_err(&save_client->dev, "m41t00_get_rtc_time: Read error\n"); + return 0; } +EXPORT_SYMBOL_GPL(m41t00_get_rtc_time); static void m41t00_set(void *arg) { struct rtc_time tm; - ulong nowtime = *(ulong *)arg; + int nowtime = *(int *)arg; + s32 sec, min, hour, day, mon, year; + u8 wbuf[9], *buf = &wbuf[1], msgbuf[1] = { 0 }; + struct i2c_msg msgs[] = { + { + .addr = save_client->addr, + .flags = 0, + .len = 1, + .buf = msgbuf, + }, + { + .addr = save_client->addr, + .flags = I2C_M_RD, + .len = 8, + .buf = buf, + }, + }; to_tm(nowtime, &tm); tm.tm_year = (tm.tm_year - 1900) % 100; - tm.tm_sec = BIN2BCD(tm.tm_sec); - tm.tm_min = BIN2BCD(tm.tm_min); - tm.tm_hour = BIN2BCD(tm.tm_hour); - tm.tm_mon = BIN2BCD(tm.tm_mon); - tm.tm_mday = BIN2BCD(tm.tm_mday); - tm.tm_year = BIN2BCD(tm.tm_year); - - mutex_lock(&m41t00_mutex); - if ((i2c_smbus_write_byte_data(save_client, 0, tm.tm_sec & 0x7f) < 0) - || (i2c_smbus_write_byte_data(save_client, 1, tm.tm_min & 0x7f) - < 0) - || (i2c_smbus_write_byte_data(save_client, 2, tm.tm_hour & 0x3f) - < 0) - || (i2c_smbus_write_byte_data(save_client, 4, tm.tm_mday & 0x3f) - < 0) - || (i2c_smbus_write_byte_data(save_client, 5, tm.tm_mon & 0x1f) - < 0) - || (i2c_smbus_write_byte_data(save_client, 6, tm.tm_year & 0xff) - < 0)) - - dev_warn(&save_client->dev,"m41t00: can't write to rtc chip\n"); - - mutex_unlock(&m41t00_mutex); + sec = BIN2BCD(tm.tm_sec); + min = BIN2BCD(tm.tm_min); + hour = BIN2BCD(tm.tm_hour); + day = BIN2BCD(tm.tm_mday); + mon = BIN2BCD(tm.tm_mon); + year = BIN2BCD(tm.tm_year); + + /* Read reg values into buf[0..7]/wbuf[1..8] */ + if (i2c_transfer(save_client->adapter, msgs, 2) < 0) { + dev_err(&save_client->dev, "m41t00_set: Read error\n"); + return; + } + + wbuf[0] = 0; /* offset into rtc's regs */ + buf[m41t00_chip->sec] = (buf[m41t00_chip->sec] & ~0x7f) | (sec & 0x7f); + buf[m41t00_chip->min] = (buf[m41t00_chip->min] & ~0x7f) | (min & 0x7f); + buf[m41t00_chip->hour] = (buf[m41t00_chip->hour] & ~0x3f) | (hour& 0x3f); + buf[m41t00_chip->day] = (buf[m41t00_chip->day] & ~0x3f) | (day & 0x3f); + buf[m41t00_chip->mon] = (buf[m41t00_chip->mon] & ~0x1f) | (mon & 0x1f); + + if (i2c_master_send(save_client, wbuf, 9) < 0) + dev_err(&save_client->dev, "m41t00_set: Write error\n"); } static ulong new_time; @@ -156,6 +230,48 @@ m41t00_set_rtc_time(ulong nowtime) return 0; } +EXPORT_SYMBOL_GPL(m41t00_set_rtc_time); + +/* + ***************************************************************************** + * + * platform_data Driver Interface + * + ***************************************************************************** + */ +static int __init +m41t00_platform_probe(struct platform_device *pdev) +{ + struct m41t00_platform_data *pdata; + int i; + + if (pdev && (pdata = pdev->dev.platform_data)) { + normal_addr[0] = pdata->i2c_addr; + + for (i=0; itype) { + m41t00_chip = &m41t00_chip_info_tbl[i]; + m41t00_chip->sqw_freq = pdata->sqw_freq; + return 0; + } + } + return -ENODEV; +} + +static int __exit +m41t00_platform_remove(struct platform_device *pdev) +{ + return 0; +} + +static struct platform_driver m41t00_platform_driver = { + .probe = m41t00_platform_probe, + .remove = m41t00_platform_remove, + .driver = { + .owner = THIS_MODULE, + .name = M41T00_DRV_NAME, + }, +}; /* ***************************************************************************** @@ -170,23 +286,71 @@ m41t00_probe(struct i2c_adapter *adap, int addr, int kind) struct i2c_client *client; int rc; + if (!i2c_check_functionality(adap, I2C_FUNC_I2C + | I2C_FUNC_SMBUS_BYTE_DATA)) + return 0; + client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); if (!client) return -ENOMEM; - strlcpy(client->name, M41T00_DRV_NAME, I2C_NAME_SIZE); + strlcpy(client->name, m41t00_chip->name, I2C_NAME_SIZE); client->addr = addr; client->adapter = adap; client->driver = &m41t00_driver; - if ((rc = i2c_attach_client(client)) != 0) { - kfree(client); - return rc; + if ((rc = i2c_attach_client(client))) + goto attach_err; + + if (m41t00_chip->type != M41T00_TYPE_M41T00) { + /* If asked, disable SQW, set SQW frequency & re-enable */ + if (m41t00_chip->sqw_freq) + if (((rc = i2c_smbus_read_byte_data(client, + m41t00_chip->alarm_mon)) < 0) + || ((rc = i2c_smbus_write_byte_data(client, + m41t00_chip->alarm_mon, rc & ~0x40)) <0) + || ((rc = i2c_smbus_write_byte_data(client, + m41t00_chip->sqw, + m41t00_chip->sqw_freq)) < 0) + || ((rc = i2c_smbus_write_byte_data(client, + m41t00_chip->alarm_mon, rc | 0x40)) <0)) + goto sqw_err; + + /* Make sure HT (Halt Update) bit is cleared */ + if ((rc = i2c_smbus_read_byte_data(client, + m41t00_chip->alarm_hour)) < 0) + goto ht_err; + + if (rc & 0x40) + if ((rc = i2c_smbus_write_byte_data(client, + m41t00_chip->alarm_hour, rc & ~0x40))<0) + goto ht_err; } - m41t00_wq = create_singlethread_workqueue("m41t00"); + /* Make sure ST (stop) bit is cleared */ + if ((rc = i2c_smbus_read_byte_data(client, m41t00_chip->sec)) < 0) + goto st_err; + + if (rc & 0x80) + if ((rc = i2c_smbus_write_byte_data(client, m41t00_chip->sec, + rc & ~0x80)) < 0) + goto st_err; + + m41t00_wq = create_singlethread_workqueue(m41t00_chip->name); save_client = client; return 0; + +st_err: + dev_err(&client->dev, "m41t00_probe: Can't clear ST bit\n"); + goto attach_err; +ht_err: + dev_err(&client->dev, "m41t00_probe: Can't clear HT bit\n"); + goto attach_err; +sqw_err: + dev_err(&client->dev, "m41t00_probe: Can't set SQW Frequency\n"); +attach_err: + kfree(client); + return rc; } static int @@ -219,13 +383,18 @@ static struct i2c_driver m41t00_driver = { static int __init m41t00_init(void) { - return i2c_add_driver(&m41t00_driver); + int rc; + + if (!(rc = platform_driver_register(&m41t00_platform_driver))) + rc = i2c_add_driver(&m41t00_driver); + return rc; } static void __exit m41t00_exit(void) { i2c_del_driver(&m41t00_driver); + platform_driver_unregister(&m41t00_platform_driver); } module_init(m41t00_init); diff --git a/include/linux/m41t00.h b/include/linux/m41t00.h new file mode 100644 index 00000000000..b423360ca38 --- /dev/null +++ b/include/linux/m41t00.h @@ -0,0 +1,50 @@ +/* + * Definitions for the ST M41T00 family of i2c rtc chips. + * + * Author: Mark A. Greer + * + * 2005, 2006 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#ifndef _M41T00_H +#define _M41T00_H + +#define M41T00_DRV_NAME "m41t00" +#define M41T00_I2C_ADDR 0x68 + +#define M41T00_TYPE_M41T00 0 +#define M41T00_TYPE_M41T81 81 +#define M41T00_TYPE_M41T85 85 + +struct m41t00_platform_data { + u8 type; + u8 i2c_addr; + u8 sqw_freq; +}; + +/* SQW output disabled, this is default value by power on */ +#define M41T00_SQW_DISABLE (0) + +#define M41T00_SQW_32KHZ (1<<4) /* 32.768 KHz */ +#define M41T00_SQW_8KHZ (2<<4) /* 8.192 KHz */ +#define M41T00_SQW_4KHZ (3<<4) /* 4.096 KHz */ +#define M41T00_SQW_2KHZ (4<<4) /* 2.048 KHz */ +#define M41T00_SQW_1KHZ (5<<4) /* 1.024 KHz */ +#define M41T00_SQW_512HZ (6<<4) /* 512 Hz */ +#define M41T00_SQW_256HZ (7<<4) /* 256 Hz */ +#define M41T00_SQW_128HZ (8<<4) /* 128 Hz */ +#define M41T00_SQW_64HZ (9<<4) /* 64 Hz */ +#define M41T00_SQW_32HZ (10<<4) /* 32 Hz */ +#define M41T00_SQW_16HZ (11<<4) /* 16 Hz */ +#define M41T00_SQW_8HZ (12<<4) /* 8 Hz */ +#define M41T00_SQW_4HZ (13<<4) /* 4 Hz */ +#define M41T00_SQW_2HZ (14<<4) /* 2 Hz */ +#define M41T00_SQW_1HZ (15<<4) /* 1 Hz */ + +extern ulong m41t00_get_rtc_time(void); +extern int m41t00_set_rtc_time(ulong nowtime); + +#endif /* _M41T00_H */ -- cgit v1.2.3 From 54aaa1ca1022d95d854315743241bb6bf59f531f Mon Sep 17 00:00:00 2001 From: Rudolf Marek Date: Tue, 25 Apr 2006 13:06:41 +0200 Subject: [PATCH] I2C: i2c-piix4: Remove the fix_hstcfg parameter This patch removes the fix_hstcfg option from the driver and related SMBus Interrupt Select register magic because now we know what are valid values for this register. This patch updates the documentation and adds new IRQ mode check so we are sure not to miss any new "unusual" value. The PCI quirk for users of fix_hstcfg was not developed because the chipset lacks of subsystem ID registers and DMI is stated "To be filled". Impact to existing systems is minimal because the problem showed up on motherboards like 10 years back. On the other hand users of newer Serverworks and HT1000 systems won't be misleaded by the message suggesting to try the fix_hstcfg any more. Signed-off-by: Rudolf Marek Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- Documentation/i2c/busses/i2c-piix4 | 22 ++++++++++++++++------ drivers/i2c/busses/i2c-piix4.c | 25 +------------------------ 2 files changed, 17 insertions(+), 30 deletions(-) diff --git a/Documentation/i2c/busses/i2c-piix4 b/Documentation/i2c/busses/i2c-piix4 index 6e6c905143a..10957bee7f6 100644 --- a/Documentation/i2c/busses/i2c-piix4 +++ b/Documentation/i2c/busses/i2c-piix4 @@ -23,8 +23,6 @@ Module Parameters Forcibly enable the PIIX4. DANGEROUS! * force_addr: int Forcibly enable the PIIX4 at the given address. EXTREMELY DANGEROUS! -* fix_hstcfg: int - Fix config register. Needed on some boards (Force CPCI735). Description @@ -68,7 +66,19 @@ this driver on those mainboards. The ServerWorks Southbridges, the Intel 440MX, and the Victory766 are identical to the PIIX4 in I2C/SMBus support. -A few OSB4 southbridges are known to be misconfigured by the BIOS. In this -case, you have you use the fix_hstcfg module parameter. Do not use it -unless you know you have to, because in some cases it also breaks -configuration on southbridges that don't need it. +If you own Force CPCI735 motherboard or other OSB4 based systems you may need +to change the SMBus Interrupt Select register so the SMBus controller uses +the SMI mode. + +1) Use lspci command and locate the PCI device with the SMBus controller: + 00:0f.0 ISA bridge: ServerWorks OSB4 South Bridge (rev 4f) + The line may vary for different chipsets. Please consult the driver source + for all possible PCI ids (and lspci -n to match them). Lets assume the + device is located at 00:0f.0. +2) Now you just need to change the value in 0xD2 register. Get it first with + command: lspci -xxx -s 00:0f.0 + If the value is 0x3 then you need to change it to 0x1 + setpci -s 00:0f.0 d2.b=1 + +Please note that you don't need to do that in all cases, just when the SMBus is +not working properly. diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index 5f06e81a208..05af7b0292f 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c @@ -102,13 +102,6 @@ MODULE_PARM_DESC(force_addr, "Forcibly enable the PIIX4 at the given address. " "EXTREMELY DANGEROUS!"); -/* If fix_hstcfg is set to anything different from 0, we reset one of the - registers to be a valid value. */ -static int fix_hstcfg; -module_param (fix_hstcfg, int, 0); -MODULE_PARM_DESC(fix_hstcfg, - "Fix config register. Needed on some boards (Force CPCI735)."); - static int piix4_transaction(void); static unsigned short piix4_smba; @@ -166,22 +159,6 @@ static int __devinit piix4_setup(struct pci_dev *PIIX4_dev, pci_read_config_byte(PIIX4_dev, SMBHSTCFG, &temp); - /* Some BIOS will set up the chipset incorrectly and leave a register - in an undefined state (causing I2C to act very strangely). */ - if (temp & 0x02) { - if (fix_hstcfg) { - dev_info(&PIIX4_dev->dev, "Working around buggy BIOS " - "(I2C)\n"); - temp &= 0xfd; - pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp); - } else { - dev_info(&PIIX4_dev->dev, "Unusual config register " - "value\n"); - dev_info(&PIIX4_dev->dev, "Try using fix_hstcfg=1 if " - "you experience problems\n"); - } - } - /* If force_addr is set, we program the new address here. Just to make sure, we disable the PIIX4 first. */ if (force_addr) { @@ -214,7 +191,7 @@ static int __devinit piix4_setup(struct pci_dev *PIIX4_dev, } } - if ((temp & 0x0E) == 8) + if (((temp & 0x0E) == 8) || ((temp & 0x0E) == 2)) dev_dbg(&PIIX4_dev->dev, "Using Interrupt 9 for SMBus.\n"); else if ((temp & 0x0E) == 0) dev_dbg(&PIIX4_dev->dev, "Using Interrupt SMI# for SMBus.\n"); -- cgit v1.2.3 From 7aadb8f943f6f8fb48962099cfba05ad0518b0ac Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 25 Apr 2006 13:29:26 +0200 Subject: [PATCH] I2C: i2c-piix4: Fix typo in documentation Fix i2c-piix4 documentation typo. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- Documentation/i2c/busses/i2c-piix4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/i2c/busses/i2c-piix4 b/Documentation/i2c/busses/i2c-piix4 index 10957bee7f6..a706ae6a1b4 100644 --- a/Documentation/i2c/busses/i2c-piix4 +++ b/Documentation/i2c/busses/i2c-piix4 @@ -63,7 +63,7 @@ The PIIX4E is just an new version of the PIIX4; it is supported as well. The PIIX/PIIX3 does not implement an SMBus or I2C bus, so you can't use this driver on those mainboards. -The ServerWorks Southbridges, the Intel 440MX, and the Victory766 are +The ServerWorks Southbridges, the Intel 440MX, and the Victory66 are identical to the PIIX4 in I2C/SMBus support. If you own Force CPCI735 motherboard or other OSB4 based systems you may need -- cgit v1.2.3 From f9ba6c04ef1dcf16f7179b7883e9751baaac218e Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 25 Apr 2006 13:37:25 +0200 Subject: [PATCH] I2C: i2c-piix4: Document the IBM problem more clearly Properly document on which systems the i2c-piix4 SMBus driver will refuse to load. Hopefully this will make it clearer for users, which were often wondering why their destop or server systems were detected as laptops. Closes bug #6429. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- Documentation/i2c/busses/i2c-piix4 | 14 ++++++++++++++ drivers/i2c/busses/i2c-piix4.c | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/Documentation/i2c/busses/i2c-piix4 b/Documentation/i2c/busses/i2c-piix4 index a706ae6a1b4..92147633323 100644 --- a/Documentation/i2c/busses/i2c-piix4 +++ b/Documentation/i2c/busses/i2c-piix4 @@ -82,3 +82,17 @@ the SMI mode. Please note that you don't need to do that in all cases, just when the SMBus is not working properly. + + +Hardware-specific issues +------------------------ + +This driver will refuse to load on IBM systems with an Intel PIIX4 SMBus. +Some of these machines have an RFID EEPROM (24RF08) connected to the SMBus, +which can easily get corrupted due to a state machine bug. These are mostly +Thinkpad laptops, but desktop systems may also be affected. We have no list +of all affected systems, so the only safe solution was to prevent access to +the SMBus on all IBM systems (detected using DMI data.) + +For additional information, read: +http://www2.lm-sensors.nu/~lm78/cvs/lm_sensors2/README.thinkpad diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index 05af7b0292f..8f2f65b793b 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c @@ -130,7 +130,7 @@ static int __devinit piix4_setup(struct pci_dev *PIIX4_dev, /* Don't access SMBus on IBM systems which get corrupted eeproms */ if (dmi_check_system(piix4_dmi_table) && PIIX4_dev->vendor == PCI_VENDOR_ID_INTEL) { - dev_err(&PIIX4_dev->dev, "IBM Laptop detected; this module " + dev_err(&PIIX4_dev->dev, "IBM system detected; this module " "may corrupt your serial eeprom! Refusing to load " "module!\n"); return -EPERM; -- cgit v1.2.3 From 5c7ae65899a4c5b05b6277f856018d1eeeb98907 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 25 Apr 2006 14:18:16 +0200 Subject: [PATCH] I2C: i2c-nforce2: Add support for the nForce4 MCP51 and MCP55 Add support for the new nForce4 MCP51 (also known as nForce 410 or 430) and nForce4 MCP55 to the i2c-nforce2 driver. Some code changes were required because the base I/O address registers have changed in these versions. Standard BARs are now being used, while the original nForce2 chips used non-standard ones. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- Documentation/i2c/busses/i2c-nforce2 | 2 ++ drivers/i2c/busses/i2c-nforce2.c | 38 +++++++++++++++++++++++++----------- include/linux/pci_ids.h | 2 ++ 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/Documentation/i2c/busses/i2c-nforce2 b/Documentation/i2c/busses/i2c-nforce2 index d751282d9b2..cd49c428a3a 100644 --- a/Documentation/i2c/busses/i2c-nforce2 +++ b/Documentation/i2c/busses/i2c-nforce2 @@ -7,6 +7,8 @@ Supported adapters: * nForce3 250Gb MCP 10de:00E4 * nForce4 MCP 10de:0052 * nForce4 MCP-04 10de:0034 + * nForce4 MCP51 10de:0264 + * nForce4 MCP55 10de:0368 Datasheet: not publically available, but seems to be similar to the AMD-8111 SMBus 2.0 adapter. diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c index 2d80eb26f68..604b49e22df 100644 --- a/drivers/i2c/busses/i2c-nforce2.c +++ b/drivers/i2c/busses/i2c-nforce2.c @@ -31,6 +31,8 @@ nForce3 250Gb MCP 00E4 nForce4 MCP 0052 nForce4 MCP-04 0034 + nForce4 MCP51 0264 + nForce4 MCP55 0368 This driver supports the 2 SMBuses that are included in the MCP of the nForce2/3/4 chipsets. @@ -64,6 +66,7 @@ struct nforce2_smbus { /* * nVidia nForce2 SMBus control register definitions + * (Newer incarnations use standard BARs 4 and 5 instead) */ #define NFORCE_PCI_SMB1 0x50 #define NFORCE_PCI_SMB2 0x54 @@ -259,6 +262,8 @@ static struct pci_device_id nforce2_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE4_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SMBUS) }, + { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS) }, + { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS) }, { 0 } }; @@ -266,19 +271,29 @@ static struct pci_device_id nforce2_ids[] = { MODULE_DEVICE_TABLE (pci, nforce2_ids); -static int __devinit nforce2_probe_smb (struct pci_dev *dev, int reg, - struct nforce2_smbus *smbus, char *name) +static int __devinit nforce2_probe_smb (struct pci_dev *dev, int bar, + int alt_reg, struct nforce2_smbus *smbus, const char *name) { - u16 iobase; int error; - if (pci_read_config_word(dev, reg, &iobase) != PCIBIOS_SUCCESSFUL) { - dev_err(&smbus->adapter.dev, "Error reading PCI config for %s\n", name); - return -1; + smbus->base = pci_resource_start(dev, bar); + if (smbus->base) { + smbus->size = pci_resource_len(dev, bar); + } else { + /* Older incarnations of the device used non-standard BARs */ + u16 iobase; + + if (pci_read_config_word(dev, alt_reg, &iobase) + != PCIBIOS_SUCCESSFUL) { + dev_err(&dev->dev, "Error reading PCI config for %s\n", + name); + return -1; + } + + smbus->base = iobase & PCI_BASE_ADDRESS_IO_MASK; + smbus->size = 8; } - smbus->dev = dev; - smbus->base = iobase & 0xfffc; - smbus->size = 8; + smbus->dev = dev; if (!request_region(smbus->base, smbus->size, nforce2_driver.name)) { dev_err(&smbus->adapter.dev, "Error requesting region %02x .. %02X for %s\n", @@ -313,12 +328,13 @@ static int __devinit nforce2_probe(struct pci_dev *dev, const struct pci_device_ pci_set_drvdata(dev, smbuses); /* SMBus adapter 1 */ - res1 = nforce2_probe_smb (dev, NFORCE_PCI_SMB1, &smbuses[0], "SMB1"); + res1 = nforce2_probe_smb(dev, 4, NFORCE_PCI_SMB1, &smbuses[0], "SMB1"); if (res1 < 0) { dev_err(&dev->dev, "Error probing SMB1.\n"); smbuses[0].base = 0; /* to have a check value */ } - res2 = nforce2_probe_smb (dev, NFORCE_PCI_SMB2, &smbuses[1], "SMB2"); + /* SMBus adapter 2 */ + res2 = nforce2_probe_smb(dev, 5, NFORCE_PCI_SMB2, &smbuses[1], "SMB2"); if (res2 < 0) { dev_err(&dev->dev, "Error probing SMB2.\n"); smbuses[1].base = 0; /* to have a check value */ diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 489af9d3ce1..d33436097e1 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1130,9 +1130,11 @@ #define PCI_DEVICE_ID_NVIDIA_QUADRO4_900XGL 0x0258 #define PCI_DEVICE_ID_NVIDIA_QUADRO4_750XGL 0x0259 #define PCI_DEVICE_ID_NVIDIA_QUADRO4_700XGL 0x025B +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS 0x0264 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE 0x0265 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA 0x0266 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2 0x0267 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS 0x0368 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE 0x036E #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA 0x037E #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2 0x037F -- cgit v1.2.3 From 4f507ea1560805b16cf4a4359e304ae0db0c2dcb Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 25 Apr 2006 14:20:11 +0200 Subject: [PATCH] HWMON: hdaps: Update the list of supported systems Update the list of systems supported by the hdaps driver: * Add the "ThinkPad Z60m" entry, reported by Arkadiusz Miskiewicz. * Add the "ThinkPad H" entry, reported by Frank Gevaerts for some ThinkPad R52 models (1846AQG). * Drop the "ThinkPad X41 Tablet" entry, which looks redundant to me. And a comment update for good measure. Signed-off-by: Jean Delvare Cc: Arkadiusz Miskiewicz Cc: Frank Gevaerts Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/hdaps.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c index 1659f6c4145..7841fa07025 100644 --- a/drivers/hwmon/hdaps.c +++ b/drivers/hwmon/hdaps.c @@ -522,13 +522,15 @@ static int __init hdaps_init(void) { int ret; - /* Note that DMI_MATCH(...,"ThinkPad T42") will match "ThinkPad T42p" */ + /* Note that HDAPS_DMI_MATCH_NORMAL("ThinkPad T42") would match + "ThinkPad T42p", so the order of the entries matters */ struct dmi_system_id hdaps_whitelist[] = { HDAPS_DMI_MATCH_NORMAL("ThinkPad H"), HDAPS_DMI_MATCH_INVERT("ThinkPad R50p"), HDAPS_DMI_MATCH_NORMAL("ThinkPad R50"), HDAPS_DMI_MATCH_NORMAL("ThinkPad R51"), HDAPS_DMI_MATCH_NORMAL("ThinkPad R52"), + HDAPS_DMI_MATCH_NORMAL("ThinkPad H"), /* R52 (1846AQG) */ HDAPS_DMI_MATCH_INVERT("ThinkPad T41p"), HDAPS_DMI_MATCH_NORMAL("ThinkPad T41"), HDAPS_DMI_MATCH_INVERT("ThinkPad T42p"), @@ -536,9 +538,9 @@ static int __init hdaps_init(void) HDAPS_DMI_MATCH_NORMAL("ThinkPad T43"), HDAPS_DMI_MATCH_LENOVO("ThinkPad T60p"), HDAPS_DMI_MATCH_NORMAL("ThinkPad X40"), - HDAPS_DMI_MATCH_NORMAL("ThinkPad X41 Tablet"), HDAPS_DMI_MATCH_NORMAL("ThinkPad X41"), HDAPS_DMI_MATCH_LENOVO("ThinkPad X60"), + HDAPS_DMI_MATCH_NORMAL("ThinkPad Z60m"), { .ident = NULL } }; -- cgit v1.2.3 From 9873964d6eb24bd0205394f9b791de9eddbcb855 Mon Sep 17 00:00:00 2001 From: Charles Spirakis Date: Tue, 25 Apr 2006 14:21:03 +0200 Subject: [PATCH] HWMON: w83791d: New hardware monitoring driver for the Winbond W83791D Add support for the w83791d sensor chip. The w83791d hardware is somewhere between the w83781d and the w83792d and this driver code is derived from the code that supports those chips. Signed-off-by: Charles Spirakis Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- Documentation/hwmon/w83791d | 113 ++++ drivers/hwmon/Kconfig | 10 + drivers/hwmon/Makefile | 1 + drivers/hwmon/w83791d.c | 1255 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 1379 insertions(+) create mode 100644 Documentation/hwmon/w83791d create mode 100644 drivers/hwmon/w83791d.c diff --git a/Documentation/hwmon/w83791d b/Documentation/hwmon/w83791d new file mode 100644 index 00000000000..83a3836289c --- /dev/null +++ b/Documentation/hwmon/w83791d @@ -0,0 +1,113 @@ +Kernel driver w83791d +===================== + +Supported chips: + * Winbond W83791D + Prefix: 'w83791d' + Addresses scanned: I2C 0x2c - 0x2f + Datasheet: http://www.winbond-usa.com/products/winbond_products/pdfs/PCIC/W83791Da.pdf + +Author: Charles Spirakis + +This driver was derived from the w83781d.c and w83792d.c source files. + +Credits: + w83781d.c: + Frodo Looijaard , + Philip Edelbrock , + and Mark Studebaker + w83792d.c: + Chunhao Huang , + Rudolf Marek + +Module Parameters +----------------- + +* init boolean + (default 0) + Use 'init=1' to have the driver do extra software initializations. + The default behavior is to do the minimum initialization possible + and depend on the BIOS to properly setup the chip. If you know you + have a w83791d and you're having problems, try init=1 before trying + reset=1. + +* reset boolean + (default 0) + Use 'reset=1' to reset the chip (via index 0x40, bit 7). The default + behavior is no chip reset to preserve BIOS settings. + +* force_subclients=bus,caddr,saddr,saddr + This is used to force the i2c addresses for subclients of + a certain chip. Example usage is `force_subclients=0,0x2f,0x4a,0x4b' + to force the subclients of chip 0x2f on bus 0 to i2c addresses + 0x4a and 0x4b. + + +Description +----------- + +This driver implements support for the Winbond W83791D chip. + +Detection of the chip can sometimes be foiled because it can be in an +internal state that allows no clean access (Bank with ID register is not +currently selected). If you know the address of the chip, use a 'force' +parameter; this will put it into a more well-behaved state first. + +The driver implements three temperature sensors, five fan rotation speed +sensors, and ten voltage sensors. + +Temperatures are measured in degrees Celsius and measurement resolution is 1 +degC for temp1 and 0.5 degC for temp2 and temp3. An alarm is triggered when +the temperature gets higher than the Overtemperature Shutdown value; it stays +on until the temperature falls below the Hysteresis value. + +Fan rotation speeds are reported in RPM (rotations per minute). An alarm is +triggered if the rotation speed has dropped below a programmable limit. Fan +readings can be divided by a programmable divider (1, 2, 4, 8 for fan 1/2/3 +and 1, 2, 4, 8, 16, 32, 64 or 128 for fan 4/5) to give the readings more +range or accuracy. + +Voltage sensors (also known as IN sensors) report their values in millivolts. +An alarm is triggered if the voltage has crossed a programmable minimum +or maximum limit. + +Alarms are provided as output from a "realtime status register". The +following bits are defined: + +bit - alarm on: +0 - Vcore +1 - VINR0 +2 - +3.3VIN +3 - 5VDD +4 - temp1 +5 - temp2 +6 - fan1 +7 - fan2 +8 - +12VIN +9 - -12VIN +10 - -5VIN +11 - fan3 +12 - chassis +13 - temp3 +14 - VINR1 +15 - reserved +16 - tart1 +17 - tart2 +18 - tart3 +19 - VSB +20 - VBAT +21 - fan4 +22 - fan5 +23 - reserved + +When an alarm goes off, you can be warned by a beeping signal through your +computer speaker. It is possible to enable all beeping globally, or only +the beeping for some alarms. + +The driver only reads the chip values each 3 seconds; reading them more +often will do no harm, but will return 'old' values. + +W83791D TODO: +--------------- +Provide a patch for per-file alarms as discussed on the mailing list +Provide a patch for smart-fan control (still need appropriate motherboard/fans) diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 9cf3d9c5962..9384b85b893 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -406,6 +406,16 @@ config SENSORS_W83781D This driver can also be built as a module. If so, the module will be called w83781d. +config SENSORS_W83791D + tristate "Winbond W83791D" + depends on HWMON && I2C && EXPERIMENTAL + select HWMON_VID + help + If you say yes here you get support for the Winbond W83791D chip. + + This driver can also be built as a module. If so, the module + will be called w83791d. + config SENSORS_W83792D tristate "Winbond W83792D" depends on HWMON && I2C && EXPERIMENTAL diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index d0904593c9e..db72b1415e7 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_SENSORS_ASB100) += asb100.o obj-$(CONFIG_SENSORS_W83627HF) += w83627hf.o obj-$(CONFIG_SENSORS_W83792D) += w83792d.o obj-$(CONFIG_SENSORS_W83781D) += w83781d.o +obj-$(CONFIG_SENSORS_W83791D) += w83791d.o obj-$(CONFIG_SENSORS_ADM1021) += adm1021.o obj-$(CONFIG_SENSORS_ADM1025) += adm1025.o diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c new file mode 100644 index 00000000000..eec43abd57f --- /dev/null +++ b/drivers/hwmon/w83791d.c @@ -0,0 +1,1255 @@ +/* + w83791d.c - Part of lm_sensors, Linux kernel modules for hardware + monitoring + + Copyright (C) 2006 Charles Spirakis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + Supports following chips: + + Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA + w83791d 10 5 3 3 0x71 0x5ca3 yes no + + The w83791d chip appears to be part way between the 83781d and the + 83792d. Thus, this file is derived from both the w83792d.c and + w83781d.c files, but its output is more along the lines of the + 83781d (which means there are no changes to the user-mode sensors + program which treats the 83791d as an 83781d). +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NUMBER_OF_VIN 10 +#define NUMBER_OF_FANIN 5 +#define NUMBER_OF_TEMPIN 3 + +/* Addresses to scan */ +static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, I2C_CLIENT_END }; + +/* Insmod parameters */ +I2C_CLIENT_INSMOD_1(w83791d); +I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: " + "{bus, clientaddr, subclientaddr1, subclientaddr2}"); + +static int reset; +module_param(reset, bool, 0); +MODULE_PARM_DESC(reset, "Set to one to force a hardware chip reset"); + +static int init; +module_param(init, bool, 0); +MODULE_PARM_DESC(init, "Set to one to force extra software initialization"); + +/* The W83791D registers */ +static const u8 W83791D_REG_IN[NUMBER_OF_VIN] = { + 0x20, /* VCOREA in DataSheet */ + 0x21, /* VINR0 in DataSheet */ + 0x22, /* +3.3VIN in DataSheet */ + 0x23, /* VDD5V in DataSheet */ + 0x24, /* +12VIN in DataSheet */ + 0x25, /* -12VIN in DataSheet */ + 0x26, /* -5VIN in DataSheet */ + 0xB0, /* 5VSB in DataSheet */ + 0xB1, /* VBAT in DataSheet */ + 0xB2 /* VINR1 in DataSheet */ +}; + +static const u8 W83791D_REG_IN_MAX[NUMBER_OF_VIN] = { + 0x2B, /* VCOREA High Limit in DataSheet */ + 0x2D, /* VINR0 High Limit in DataSheet */ + 0x2F, /* +3.3VIN High Limit in DataSheet */ + 0x31, /* VDD5V High Limit in DataSheet */ + 0x33, /* +12VIN High Limit in DataSheet */ + 0x35, /* -12VIN High Limit in DataSheet */ + 0x37, /* -5VIN High Limit in DataSheet */ + 0xB4, /* 5VSB High Limit in DataSheet */ + 0xB6, /* VBAT High Limit in DataSheet */ + 0xB8 /* VINR1 High Limit in DataSheet */ +}; +static const u8 W83791D_REG_IN_MIN[NUMBER_OF_VIN] = { + 0x2C, /* VCOREA Low Limit in DataSheet */ + 0x2E, /* VINR0 Low Limit in DataSheet */ + 0x30, /* +3.3VIN Low Limit in DataSheet */ + 0x32, /* VDD5V Low Limit in DataSheet */ + 0x34, /* +12VIN Low Limit in DataSheet */ + 0x36, /* -12VIN Low Limit in DataSheet */ + 0x38, /* -5VIN Low Limit in DataSheet */ + 0xB5, /* 5VSB Low Limit in DataSheet */ + 0xB7, /* VBAT Low Limit in DataSheet */ + 0xB9 /* VINR1 Low Limit in DataSheet */ +}; +static const u8 W83791D_REG_FAN[NUMBER_OF_FANIN] = { + 0x28, /* FAN 1 Count in DataSheet */ + 0x29, /* FAN 2 Count in DataSheet */ + 0x2A, /* FAN 3 Count in DataSheet */ + 0xBA, /* FAN 4 Count in DataSheet */ + 0xBB, /* FAN 5 Count in DataSheet */ +}; +static const u8 W83791D_REG_FAN_MIN[NUMBER_OF_FANIN] = { + 0x3B, /* FAN 1 Count Low Limit in DataSheet */ + 0x3C, /* FAN 2 Count Low Limit in DataSheet */ + 0x3D, /* FAN 3 Count Low Limit in DataSheet */ + 0xBC, /* FAN 4 Count Low Limit in DataSheet */ + 0xBD, /* FAN 5 Count Low Limit in DataSheet */ +}; + +static const u8 W83791D_REG_FAN_CFG[2] = { + 0x84, /* FAN 1/2 configuration */ + 0x95, /* FAN 3 configuration */ +}; + +static const u8 W83791D_REG_FAN_DIV[3] = { + 0x47, /* contains FAN1 and FAN2 Divisor */ + 0x4b, /* contains FAN3 Divisor */ + 0x5C, /* contains FAN4 and FAN5 Divisor */ +}; + +#define W83791D_REG_BANK 0x4E +#define W83791D_REG_TEMP2_CONFIG 0xC2 +#define W83791D_REG_TEMP3_CONFIG 0xCA + +static const u8 W83791D_REG_TEMP1[3] = { + 0x27, /* TEMP 1 in DataSheet */ + 0x39, /* TEMP 1 Over in DataSheet */ + 0x3A, /* TEMP 1 Hyst in DataSheet */ +}; + +static const u8 W83791D_REG_TEMP_ADD[2][6] = { + {0xC0, /* TEMP 2 in DataSheet */ + 0xC1, /* TEMP 2(0.5 deg) in DataSheet */ + 0xC5, /* TEMP 2 Over High part in DataSheet */ + 0xC6, /* TEMP 2 Over Low part in DataSheet */ + 0xC3, /* TEMP 2 Thyst High part in DataSheet */ + 0xC4}, /* TEMP 2 Thyst Low part in DataSheet */ + {0xC8, /* TEMP 3 in DataSheet */ + 0xC9, /* TEMP 3(0.5 deg) in DataSheet */ + 0xCD, /* TEMP 3 Over High part in DataSheet */ + 0xCE, /* TEMP 3 Over Low part in DataSheet */ + 0xCB, /* TEMP 3 Thyst High part in DataSheet */ + 0xCC} /* TEMP 3 Thyst Low part in DataSheet */ +}; + +#define W83791D_REG_BEEP_CONFIG 0x4D + +static const u8 W83791D_REG_BEEP_CTRL[3] = { + 0x56, /* BEEP Control Register 1 */ + 0x57, /* BEEP Control Register 2 */ + 0xA3, /* BEEP Control Register 3 */ +}; + +#define W83791D_REG_CONFIG 0x40 +#define W83791D_REG_VID_FANDIV 0x47 +#define W83791D_REG_DID_VID4 0x49 +#define W83791D_REG_WCHIPID 0x58 +#define W83791D_REG_CHIPMAN 0x4F +#define W83791D_REG_PIN 0x4B +#define W83791D_REG_I2C_SUBADDR 0x4A + +#define W83791D_REG_ALARM1 0xA9 /* realtime status register1 */ +#define W83791D_REG_ALARM2 0xAA /* realtime status register2 */ +#define W83791D_REG_ALARM3 0xAB /* realtime status register3 */ + +#define W83791D_REG_VBAT 0x5D +#define W83791D_REG_I2C_ADDR 0x48 + +/* The SMBus locks itself. The Winbond W83791D has a bank select register + (index 0x4e), but the driver only accesses registers in bank 0. Since + we don't switch banks, we don't need any special code to handle + locking access between bank switches */ +static inline int w83791d_read(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static inline int w83791d_write(struct i2c_client *client, u8 reg, u8 value) +{ + return i2c_smbus_write_byte_data(client, reg, value); +} + +/* The analog voltage inputs have 16mV LSB. Since the sysfs output is + in mV as would be measured on the chip input pin, need to just + multiply/divide by 16 to translate from/to register values. */ +#define IN_TO_REG(val) (SENSORS_LIMIT((((val) + 8) / 16), 0, 255)) +#define IN_FROM_REG(val) ((val) * 16) + +static u8 fan_to_reg(long rpm, int div) +{ + if (rpm == 0) + return 255; + rpm = SENSORS_LIMIT(rpm, 1, 1000000); + return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254); +} + +#define FAN_FROM_REG(val,div) ((val) == 0 ? -1 : \ + ((val) == 255 ? 0 : \ + 1350000 / ((val) * (div)))) + +/* for temp1 which is 8-bit resolution, LSB = 1 degree Celsius */ +#define TEMP1_FROM_REG(val) ((val) * 1000) +#define TEMP1_TO_REG(val) ((val) <= -128000 ? -128 : \ + (val) >= 127000 ? 127 : \ + (val) < 0 ? ((val) - 500) / 1000 : \ + ((val) + 500) / 1000) + +/* for temp2 and temp3 which are 9-bit resolution, LSB = 0.5 degree Celsius + Assumes the top 8 bits are the integral amount and the bottom 8 bits + are the fractional amount. Since we only have 0.5 degree resolution, + the bottom 7 bits will always be zero */ +#define TEMP23_FROM_REG(val) ((val) / 128 * 500) +#define TEMP23_TO_REG(val) ((val) <= -128000 ? 0x8000 : \ + (val) >= 127500 ? 0x7F80 : \ + (val) < 0 ? ((val) - 250) / 500 * 128 : \ + ((val) + 250) / 500 * 128) + + +#define BEEP_MASK_TO_REG(val) ((val) & 0xffffff) +#define BEEP_MASK_FROM_REG(val) ((val) & 0xffffff) + +#define DIV_FROM_REG(val) (1 << (val)) + +static u8 div_to_reg(int nr, long val) +{ + int i; + int max; + + /* first three fan's divisor max out at 8, rest max out at 128 */ + max = (nr < 3) ? 8 : 128; + val = SENSORS_LIMIT(val, 1, max) >> 1; + for (i = 0; i < 7; i++) { + if (val == 0) + break; + val >>= 1; + } + return (u8) i; +} + +struct w83791d_data { + struct i2c_client client; + struct class_device *class_dev; + struct mutex update_lock; + + char valid; /* !=0 if following fields are valid */ + unsigned long last_updated; /* In jiffies */ + + /* array of 2 pointers to subclients */ + struct i2c_client *lm75[2]; + + /* volts */ + u8 in[NUMBER_OF_VIN]; /* Register value */ + u8 in_max[NUMBER_OF_VIN]; /* Register value */ + u8 in_min[NUMBER_OF_VIN]; /* Register value */ + + /* fans */ + u8 fan[NUMBER_OF_FANIN]; /* Register value */ + u8 fan_min[NUMBER_OF_FANIN]; /* Register value */ + u8 fan_div[NUMBER_OF_FANIN]; /* Register encoding, shifted right */ + + /* Temperature sensors */ + + s8 temp1[3]; /* current, over, thyst */ + s16 temp_add[2][3]; /* fixed point value. Top 8 bits are the + integral part, bottom 8 bits are the + fractional part. We only use the top + 9 bits as the resolution is only + to the 0.5 degree C... + two sensors with three values + (cur, over, hyst) */ + + /* Misc */ + u32 alarms; /* realtime status register encoding,combined */ + u8 beep_enable; /* Global beep enable */ + u32 beep_mask; /* Mask off specific beeps */ + u8 vid; /* Register encoding, combined */ + u8 vrm; /* hwmon-vid */ +}; + +static int w83791d_attach_adapter(struct i2c_adapter *adapter); +static int w83791d_detect(struct i2c_adapter *adapter, int address, int kind); +static int w83791d_detach_client(struct i2c_client *client); + +static int w83791d_read(struct i2c_client *client, u8 register); +static int w83791d_write(struct i2c_client *client, u8 register, u8 value); +static struct w83791d_data *w83791d_update_device(struct device *dev); + +#ifdef DEBUG +static void w83791d_print_debug(struct w83791d_data *data, struct device *dev); +#endif + +static void w83791d_init_client(struct i2c_client *client); + +static struct i2c_driver w83791d_driver = { + .driver = { + .name = "w83791d", + }, + .attach_adapter = w83791d_attach_adapter, + .detach_client = w83791d_detach_client, +}; + +/* following are the sysfs callback functions */ +#define show_in_reg(reg) \ +static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \ + char *buf) \ +{ \ + struct sensor_device_attribute *sensor_attr = \ + to_sensor_dev_attr(attr); \ + struct w83791d_data *data = w83791d_update_device(dev); \ + int nr = sensor_attr->index; \ + return sprintf(buf,"%d\n", IN_FROM_REG(data->reg[nr])); \ +} + +show_in_reg(in); +show_in_reg(in_min); +show_in_reg(in_max); + +#define store_in_reg(REG, reg) \ +static ssize_t store_in_##reg(struct device *dev, \ + struct device_attribute *attr, \ + const char *buf, size_t count) \ +{ \ + struct sensor_device_attribute *sensor_attr = \ + to_sensor_dev_attr(attr); \ + struct i2c_client *client = to_i2c_client(dev); \ + struct w83791d_data *data = i2c_get_clientdata(client); \ + unsigned long val = simple_strtoul(buf, NULL, 10); \ + int nr = sensor_attr->index; \ + \ + mutex_lock(&data->update_lock); \ + data->in_##reg[nr] = IN_TO_REG(val); \ + w83791d_write(client, W83791D_REG_IN_##REG[nr], data->in_##reg[nr]); \ + mutex_unlock(&data->update_lock); \ + \ + return count; \ +} +store_in_reg(MIN, min); +store_in_reg(MAX, max); + +static struct sensor_device_attribute sda_in_input[] = { + SENSOR_ATTR(in0_input, S_IRUGO, show_in, NULL, 0), + SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1), + SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2), + SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3), + SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4), + SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5), + SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6), + SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7), + SENSOR_ATTR(in8_input, S_IRUGO, show_in, NULL, 8), + SENSOR_ATTR(in9_input, S_IRUGO, show_in, NULL, 9), +}; + +static struct sensor_device_attribute sda_in_min[] = { + SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 0), + SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 1), + SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 2), + SENSOR_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 3), + SENSOR_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 4), + SENSOR_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 5), + SENSOR_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 6), + SENSOR_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 7), + SENSOR_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 8), + SENSOR_ATTR(in9_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 9), +}; + +static struct sensor_device_attribute sda_in_max[] = { + SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 0), + SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 1), + SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 2), + SENSOR_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 3), + SENSOR_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 4), + SENSOR_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 5), + SENSOR_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 6), + SENSOR_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 7), + SENSOR_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 8), + SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 9), +}; + +#define show_fan_reg(reg) \ +static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \ + char *buf) \ +{ \ + struct sensor_device_attribute *sensor_attr = \ + to_sensor_dev_attr(attr); \ + struct w83791d_data *data = w83791d_update_device(dev); \ + int nr = sensor_attr->index; \ + return sprintf(buf,"%d\n", \ + FAN_FROM_REG(data->reg[nr], DIV_FROM_REG(data->fan_div[nr]))); \ +} + +show_fan_reg(fan); +show_fan_reg(fan_min); + +static ssize_t store_fan_min(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + struct i2c_client *client = to_i2c_client(dev); + struct w83791d_data *data = i2c_get_clientdata(client); + unsigned long val = simple_strtoul(buf, NULL, 10); + int nr = sensor_attr->index; + + mutex_lock(&data->update_lock); + data->fan_min[nr] = fan_to_reg(val, DIV_FROM_REG(data->fan_div[nr])); + w83791d_write(client, W83791D_REG_FAN_MIN[nr], data->fan_min[nr]); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + struct w83791d_data *data = w83791d_update_device(dev); + return sprintf(buf, "%u\n", DIV_FROM_REG(data->fan_div[nr])); +} + +/* Note: we save and restore the fan minimum here, because its value is + determined in part by the fan divisor. This follows the principle of + least suprise; the user doesn't expect the fan minimum to change just + because the divisor changed. */ +static ssize_t store_fan_div(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + struct i2c_client *client = to_i2c_client(dev); + struct w83791d_data *data = i2c_get_clientdata(client); + int nr = sensor_attr->index; + unsigned long min; + u8 tmp_fan_div; + u8 fan_div_reg; + int indx = 0; + u8 keep_mask = 0; + u8 new_shift = 0; + + /* Save fan_min */ + min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])); + + mutex_lock(&data->update_lock); + data->fan_div[nr] = div_to_reg(nr, simple_strtoul(buf, NULL, 10)); + + switch (nr) { + case 0: + indx = 0; + keep_mask = 0xcf; + new_shift = 4; + break; + case 1: + indx = 0; + keep_mask = 0x3f; + new_shift = 6; + break; + case 2: + indx = 1; + keep_mask = 0x3f; + new_shift = 6; + break; + case 3: + indx = 2; + keep_mask = 0xf8; + new_shift = 0; + break; + case 4: + indx = 2; + keep_mask = 0x8f; + new_shift = 4; + break; +#ifdef DEBUG + default: + dev_warn(dev, "store_fan_div: Unexpected nr seen: %d\n", nr); + count = -EINVAL; + goto err_exit; +#endif + } + + fan_div_reg = w83791d_read(client, W83791D_REG_FAN_DIV[indx]) + & keep_mask; + tmp_fan_div = (data->fan_div[nr] << new_shift) & ~keep_mask; + + w83791d_write(client, W83791D_REG_FAN_DIV[indx], + fan_div_reg | tmp_fan_div); + + /* Restore fan_min */ + data->fan_min[nr] = fan_to_reg(min, DIV_FROM_REG(data->fan_div[nr])); + w83791d_write(client, W83791D_REG_FAN_MIN[nr], data->fan_min[nr]); + +#ifdef DEBUG +err_exit: +#endif + mutex_unlock(&data->update_lock); + + return count; +} + +static struct sensor_device_attribute sda_fan_input[] = { + SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0), + SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1), + SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2), + SENSOR_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3), + SENSOR_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4), +}; + +static struct sensor_device_attribute sda_fan_min[] = { + SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, + show_fan_min, store_fan_min, 0), + SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO, + show_fan_min, store_fan_min, 1), + SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, + show_fan_min, store_fan_min, 2), + SENSOR_ATTR(fan4_min, S_IWUSR | S_IRUGO, + show_fan_min, store_fan_min, 3), + SENSOR_ATTR(fan5_min, S_IWUSR | S_IRUGO, + show_fan_min, store_fan_min, 4), +}; + +static struct sensor_device_attribute sda_fan_div[] = { + SENSOR_ATTR(fan1_div, S_IWUSR | S_IRUGO, + show_fan_div, store_fan_div, 0), + SENSOR_ATTR(fan2_div, S_IWUSR | S_IRUGO, + show_fan_div, store_fan_div, 1), + SENSOR_ATTR(fan3_div, S_IWUSR | S_IRUGO, + show_fan_div, store_fan_div, 2), + SENSOR_ATTR(fan4_div, S_IWUSR | S_IRUGO, + show_fan_div, store_fan_div, 3), + SENSOR_ATTR(fan5_div, S_IWUSR | S_IRUGO, + show_fan_div, store_fan_div, 4), +}; + +/* read/write the temperature1, includes measured value and limits */ +static ssize_t show_temp1(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct w83791d_data *data = w83791d_update_device(dev); + return sprintf(buf, "%d\n", TEMP1_FROM_REG(data->temp1[attr->index])); +} + +static ssize_t store_temp1(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct w83791d_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + int nr = attr->index; + + mutex_lock(&data->update_lock); + data->temp1[nr] = TEMP1_TO_REG(val); + w83791d_write(client, W83791D_REG_TEMP1[nr], data->temp1[nr]); + mutex_unlock(&data->update_lock); + return count; +} + +/* read/write temperature2-3, includes measured value and limits */ +static ssize_t show_temp23(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct w83791d_data *data = w83791d_update_device(dev); + int nr = attr->nr; + int index = attr->index; + return sprintf(buf, "%d\n", TEMP23_FROM_REG(data->temp_add[nr][index])); +} + +static ssize_t store_temp23(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct w83791d_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + int nr = attr->nr; + int index = attr->index; + + mutex_lock(&data->update_lock); + data->temp_add[nr][index] = TEMP23_TO_REG(val); + w83791d_write(client, W83791D_REG_TEMP_ADD[nr][index * 2], + data->temp_add[nr][index] >> 8); + w83791d_write(client, W83791D_REG_TEMP_ADD[nr][index * 2 + 1], + data->temp_add[nr][index] & 0x80); + mutex_unlock(&data->update_lock); + + return count; +} + +static struct sensor_device_attribute_2 sda_temp_input[] = { + SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp1, NULL, 0, 0), + SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp23, NULL, 0, 0), + SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp23, NULL, 1, 0), +}; + +static struct sensor_device_attribute_2 sda_temp_max[] = { + SENSOR_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, + show_temp1, store_temp1, 0, 1), + SENSOR_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, + show_temp23, store_temp23, 0, 1), + SENSOR_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, + show_temp23, store_temp23, 1, 1), +}; + +static struct sensor_device_attribute_2 sda_temp_max_hyst[] = { + SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO | S_IWUSR, + show_temp1, store_temp1, 0, 2), + SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO | S_IWUSR, + show_temp23, store_temp23, 0, 2), + SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO | S_IWUSR, + show_temp23, store_temp23, 1, 2), +}; + + +/* get reatime status of all sensors items: voltage, temp, fan */ +static ssize_t show_alarms_reg(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct w83791d_data *data = w83791d_update_device(dev); + return sprintf(buf, "%u\n", data->alarms); +} + +static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL); + +/* Beep control */ + +#define GLOBAL_BEEP_ENABLE_SHIFT 15 +#define GLOBAL_BEEP_ENABLE_MASK (1 << GLOBAL_BEEP_ENABLE_SHIFT) + +static ssize_t show_beep_enable(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct w83791d_data *data = w83791d_update_device(dev); + return sprintf(buf, "%d\n", data->beep_enable); +} + +static ssize_t show_beep_mask(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct w83791d_data *data = w83791d_update_device(dev); + return sprintf(buf, "%d\n", BEEP_MASK_FROM_REG(data->beep_mask)); +} + + +static ssize_t store_beep_mask(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct w83791d_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + int i; + + mutex_lock(&data->update_lock); + + /* The beep_enable state overrides any enabling request from + the masks */ + data->beep_mask = BEEP_MASK_TO_REG(val) & ~GLOBAL_BEEP_ENABLE_MASK; + data->beep_mask |= (data->beep_enable << GLOBAL_BEEP_ENABLE_SHIFT); + + val = data->beep_mask; + + for (i = 0; i < 3; i++) { + w83791d_write(client, W83791D_REG_BEEP_CTRL[i], (val & 0xff)); + val >>= 8; + } + + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t store_beep_enable(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct w83791d_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + + mutex_lock(&data->update_lock); + + data->beep_enable = val ? 1 : 0; + + /* Keep the full mask value in sync with the current enable */ + data->beep_mask &= ~GLOBAL_BEEP_ENABLE_MASK; + data->beep_mask |= (data->beep_enable << GLOBAL_BEEP_ENABLE_SHIFT); + + /* The global control is in the second beep control register + so only need to update that register */ + val = (data->beep_mask >> 8) & 0xff; + + w83791d_write(client, W83791D_REG_BEEP_CTRL[1], val); + + mutex_unlock(&data->update_lock); + + return count; +} + +static struct sensor_device_attribute sda_beep_ctrl[] = { + SENSOR_ATTR(beep_enable, S_IRUGO | S_IWUSR, + show_beep_enable, store_beep_enable, 0), + SENSOR_ATTR(beep_mask, S_IRUGO | S_IWUSR, + show_beep_mask, store_beep_mask, 1) +}; + +/* cpu voltage regulation information */ +static ssize_t show_vid_reg(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct w83791d_data *data = w83791d_update_device(dev); + return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm)); +} + +static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL); + +static ssize_t show_vrm_reg(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct w83791d_data *data = w83791d_update_device(dev); + return sprintf(buf, "%d\n", data->vrm); +} + +static ssize_t store_vrm_reg(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct w83791d_data *data = i2c_get_clientdata(client); + unsigned long val = simple_strtoul(buf, NULL, 10); + + /* No lock needed as vrm is internal to the driver + (not read from a chip register) and so is not + updated in w83791d_update_device() */ + data->vrm = val; + + return count; +} + +static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg); + +/* This function is called when: + * w83791d_driver is inserted (when this module is loaded), for each + available adapter + * when a new adapter is inserted (and w83791d_driver is still present) */ +static int w83791d_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, w83791d_detect); +} + + +static int w83791d_create_subclient(struct i2c_adapter *adapter, + struct i2c_client *client, int addr, + struct i2c_client **sub_cli) +{ + int err; + struct i2c_client *sub_client; + + (*sub_cli) = sub_client = + kzalloc(sizeof(struct i2c_client), GFP_KERNEL); + if (!(sub_client)) { + return -ENOMEM; + } + sub_client->addr = 0x48 + addr; + i2c_set_clientdata(sub_client, NULL); + sub_client->adapter = adapter; + sub_client->driver = &w83791d_driver; + strlcpy(sub_client->name, "w83791d subclient", I2C_NAME_SIZE); + if ((err = i2c_attach_client(sub_client))) { + dev_err(&client->dev, "subclient registration " + "at address 0x%x failed\n", sub_client->addr); + kfree(sub_client); + return err; + } + return 0; +} + + +static int w83791d_detect_subclients(struct i2c_adapter *adapter, int address, + int kind, struct i2c_client *client) +{ + struct w83791d_data *data = i2c_get_clientdata(client); + int i, id, err; + u8 val; + + id = i2c_adapter_id(adapter); + if (force_subclients[0] == id && force_subclients[1] == address) { + for (i = 2; i <= 3; i++) { + if (force_subclients[i] < 0x48 || + force_subclients[i] > 0x4f) { + dev_err(&client->dev, + "invalid subclient " + "address %d; must be 0x48-0x4f\n", + force_subclients[i]); + err = -ENODEV; + goto error_sc_0; + } + } + w83791d_write(client, W83791D_REG_I2C_SUBADDR, + (force_subclients[2] & 0x07) | + ((force_subclients[3] & 0x07) << 4)); + } + + val = w83791d_read(client, W83791D_REG_I2C_SUBADDR); + if (!(val & 0x08)) { + err = w83791d_create_subclient(adapter, client, + val & 0x7, &data->lm75[0]); + if (err < 0) + goto error_sc_0; + } + if (!(val & 0x80)) { + if ((data->lm75[0] != NULL) && + ((val & 0x7) == ((val >> 4) & 0x7))) { + dev_err(&client->dev, + "duplicate addresses 0x%x, " + "use force_subclient\n", + data->lm75[0]->addr); + err = -ENODEV; + goto error_sc_1; + } + err = w83791d_create_subclient(adapter, client, + (val >> 4) & 0x7, &data->lm75[1]); + if (err < 0) + goto error_sc_1; + } + + return 0; + +/* Undo inits in case of errors */ + +error_sc_1: + if (data->lm75[0] != NULL) { + i2c_detach_client(data->lm75[0]); + kfree(data->lm75[0]); + } +error_sc_0: + return err; +} + + +static int w83791d_detect(struct i2c_adapter *adapter, int address, int kind) +{ + struct i2c_client *client; + struct device *dev; + struct w83791d_data *data; + int i, val1, val2; + int err = 0; + const char *client_name = ""; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + goto error0; + } + + /* OK. For now, we presume we have a valid client. We now create the + client structure, even though we cannot fill it completely yet. + But it allows us to access w83791d_{read,write}_value. */ + if (!(data = kzalloc(sizeof(struct w83791d_data), GFP_KERNEL))) { + err = -ENOMEM; + goto error0; + } + + client = &data->client; + dev = &client->dev; + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &w83791d_driver; + mutex_init(&data->update_lock); + + /* Now, we do the remaining detection. */ + + /* The w83791d may be stuck in some other bank than bank 0. This may + make reading other information impossible. Specify a force=... + parameter, and the Winbond will be reset to the right bank. */ + if (kind < 0) { + if (w83791d_read(client, W83791D_REG_CONFIG) & 0x80) { + dev_dbg(dev, "Detection failed at step 1\n"); + goto error1; + } + val1 = w83791d_read(client, W83791D_REG_BANK); + val2 = w83791d_read(client, W83791D_REG_CHIPMAN); + /* Check for Winbond ID if in bank 0 */ + if (!(val1 & 0x07)) { + /* yes it is Bank0 */ + if (((!(val1 & 0x80)) && (val2 != 0xa3)) || + ((val1 & 0x80) && (val2 != 0x5c))) { + dev_dbg(dev, "Detection failed at step 2\n"); + goto error1; + } + } + /* If Winbond chip, address of chip and W83791D_REG_I2C_ADDR + should match */ + if (w83791d_read(client, W83791D_REG_I2C_ADDR) != address) { + dev_dbg(dev, "Detection failed at step 3\n"); + goto error1; + } + } + + /* We either have a force parameter or we have reason to + believe it is a Winbond chip. Either way, we want bank 0 and + Vendor ID high byte */ + val1 = w83791d_read(client, W83791D_REG_BANK) & 0x78; + w83791d_write(client, W83791D_REG_BANK, val1 | 0x80); + + /* Verify it is a Winbond w83791d */ + if (kind <= 0) { + /* get vendor ID */ + val2 = w83791d_read(client, W83791D_REG_CHIPMAN); + if (val2 != 0x5c) { /* the vendor is NOT Winbond */ + dev_dbg(dev, "Detection failed at step 4\n"); + goto error1; + } + val1 = w83791d_read(client, W83791D_REG_WCHIPID); + if (val1 == 0x71) { + kind = w83791d; + } else { + if (kind == 0) + dev_warn(dev, + "w83791d: Ignoring 'force' parameter " + "for unknown chip at adapter %d, " + "address 0x%02x\n", + i2c_adapter_id(adapter), address); + goto error1; + } + } + + if (kind == w83791d) { + client_name = "w83791d"; + } else { + dev_err(dev, "w83791d: Internal error: unknown kind (%d)?!?", + kind); + goto error1; + } + +#ifdef DEBUG + val1 = w83791d_read(client, W83791D_REG_DID_VID4); + dev_dbg(dev, "Device ID version: %d.%d (0x%02x)\n", + (val1 >> 5) & 0x07, (val1 >> 1) & 0x0f, val1); +#endif + + /* Fill in the remaining client fields and put into the global list */ + strlcpy(client->name, client_name, I2C_NAME_SIZE); + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(client))) + goto error1; + + if ((err = w83791d_detect_subclients(adapter, address, kind, client))) + goto error2; + + /* Initialize the chip */ + w83791d_init_client(client); + + /* If the fan_div is changed, make sure there is a rational + fan_min in place */ + for (i = 0; i < NUMBER_OF_FANIN; i++) { + data->fan_min[i] = w83791d_read(client, W83791D_REG_FAN_MIN[i]); + } + + /* Register sysfs hooks */ + data->class_dev = hwmon_device_register(dev); + if (IS_ERR(data->class_dev)) { + err = PTR_ERR(data->class_dev); + goto error3; + } + + for (i = 0; i < NUMBER_OF_VIN; i++) { + device_create_file(dev, &sda_in_input[i].dev_attr); + device_create_file(dev, &sda_in_min[i].dev_attr); + device_create_file(dev, &sda_in_max[i].dev_attr); + } + + for (i = 0; i < NUMBER_OF_FANIN; i++) { + device_create_file(dev, &sda_fan_input[i].dev_attr); + device_create_file(dev, &sda_fan_div[i].dev_attr); + device_create_file(dev, &sda_fan_min[i].dev_attr); + } + + for (i = 0; i < NUMBER_OF_TEMPIN; i++) { + device_create_file(dev, &sda_temp_input[i].dev_attr); + device_create_file(dev, &sda_temp_max[i].dev_attr); + device_create_file(dev, &sda_temp_max_hyst[i].dev_attr); + } + + device_create_file(dev, &dev_attr_alarms); + + for (i = 0; i < ARRAY_SIZE(sda_beep_ctrl); i++) { + device_create_file(dev, &sda_beep_ctrl[i].dev_attr); + } + + device_create_file(dev, &dev_attr_cpu0_vid); + device_create_file(dev, &dev_attr_vrm); + + return 0; + +error3: + if (data->lm75[0] != NULL) { + i2c_detach_client(data->lm75[0]); + kfree(data->lm75[0]); + } + if (data->lm75[1] != NULL) { + i2c_detach_client(data->lm75[1]); + kfree(data->lm75[1]); + } +error2: + i2c_detach_client(client); +error1: + kfree(data); +error0: + return err; +} + +static int w83791d_detach_client(struct i2c_client *client) +{ + struct w83791d_data *data = i2c_get_clientdata(client); + int err; + + /* main client */ + if (data) + hwmon_device_unregister(data->class_dev); + + if ((err = i2c_detach_client(client))) + return err; + + /* main client */ + if (data) + kfree(data); + /* subclient */ + else + kfree(client); + + return 0; +} + +static void w83791d_init_client(struct i2c_client *client) +{ + struct w83791d_data *data = i2c_get_clientdata(client); + u8 tmp; + u8 old_beep; + + /* The difference between reset and init is that reset + does a hard reset of the chip via index 0x40, bit 7, + but init simply forces certain registers to have "sane" + values. The hope is that the BIOS has done the right + thing (which is why the default is reset=0, init=0), + but if not, reset is the hard hammer and init + is the soft mallet both of which are trying to whack + things into place... + NOTE: The data sheet makes a distinction between + "power on defaults" and "reset by MR". As far as I can tell, + the hard reset puts everything into a power-on state so I'm + not sure what "reset by MR" means or how it can happen. + */ + if (reset || init) { + /* keep some BIOS settings when we... */ + old_beep = w83791d_read(client, W83791D_REG_BEEP_CONFIG); + + if (reset) { + /* ... reset the chip and ... */ + w83791d_write(client, W83791D_REG_CONFIG, 0x80); + } + + /* ... disable power-on abnormal beep */ + w83791d_write(client, W83791D_REG_BEEP_CONFIG, old_beep | 0x80); + + /* disable the global beep (not done by hard reset) */ + tmp = w83791d_read(client, W83791D_REG_BEEP_CTRL[1]); + w83791d_write(client, W83791D_REG_BEEP_CTRL[1], tmp & 0xef); + + if (init) { + /* Make sure monitoring is turned on for add-ons */ + tmp = w83791d_read(client, W83791D_REG_TEMP2_CONFIG); + if (tmp & 1) { + w83791d_write(client, W83791D_REG_TEMP2_CONFIG, + tmp & 0xfe); + } + + tmp = w83791d_read(client, W83791D_REG_TEMP3_CONFIG); + if (tmp & 1) { + w83791d_write(client, W83791D_REG_TEMP3_CONFIG, + tmp & 0xfe); + } + + /* Start monitoring */ + tmp = w83791d_read(client, W83791D_REG_CONFIG) & 0xf7; + w83791d_write(client, W83791D_REG_CONFIG, tmp | 0x01); + } + } + + data->vrm = vid_which_vrm(); +} + +static struct w83791d_data *w83791d_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct w83791d_data *data = i2c_get_clientdata(client); + int i, j; + u8 reg_array_tmp[3]; + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + (HZ * 3)) + || !data->valid) { + dev_dbg(dev, "Starting w83791d device update\n"); + + /* Update the voltages measured value and limits */ + for (i = 0; i < NUMBER_OF_VIN; i++) { + data->in[i] = w83791d_read(client, + W83791D_REG_IN[i]); + data->in_max[i] = w83791d_read(client, + W83791D_REG_IN_MAX[i]); + data->in_min[i] = w83791d_read(client, + W83791D_REG_IN_MIN[i]); + } + + /* Update the fan counts and limits */ + for (i = 0; i < NUMBER_OF_FANIN; i++) { + /* Update the Fan measured value and limits */ + data->fan[i] = w83791d_read(client, + W83791D_REG_FAN[i]); + data->fan_min[i] = w83791d_read(client, + W83791D_REG_FAN_MIN[i]); + } + + /* Update the fan divisor */ + for (i = 0; i < 3; i++) { + reg_array_tmp[i] = w83791d_read(client, + W83791D_REG_FAN_DIV[i]); + } + data->fan_div[0] = (reg_array_tmp[0] >> 4) & 0x03; + data->fan_div[1] = (reg_array_tmp[0] >> 6) & 0x03; + data->fan_div[2] = (reg_array_tmp[1] >> 6) & 0x03; + data->fan_div[3] = reg_array_tmp[2] & 0x07; + data->fan_div[4] = (reg_array_tmp[2] >> 4) & 0x07; + + /* Update the first temperature sensor */ + for (i = 0; i < 3; i++) { + data->temp1[i] = w83791d_read(client, + W83791D_REG_TEMP1[i]); + } + + /* Update the rest of the temperature sensors */ + for (i = 0; i < 2; i++) { + for (j = 0; j < 3; j++) { + data->temp_add[i][j] = + (w83791d_read(client, + W83791D_REG_TEMP_ADD[i][j * 2]) << 8) | + w83791d_read(client, + W83791D_REG_TEMP_ADD[i][j * 2 + 1]); + } + } + + /* Update the realtime status */ + data->alarms = + w83791d_read(client, W83791D_REG_ALARM1) + + (w83791d_read(client, W83791D_REG_ALARM2) << 8) + + (w83791d_read(client, W83791D_REG_ALARM3) << 16); + + /* Update the beep configuration information */ + data->beep_mask = + w83791d_read(client, W83791D_REG_BEEP_CTRL[0]) + + (w83791d_read(client, W83791D_REG_BEEP_CTRL[1]) << 8) + + (w83791d_read(client, W83791D_REG_BEEP_CTRL[2]) << 16); + + data->beep_enable = + (data->beep_mask >> GLOBAL_BEEP_ENABLE_SHIFT) & 0x01; + + /* Update the cpu voltage information */ + i = w83791d_read(client, W83791D_REG_VID_FANDIV); + data->vid = i & 0x0f; + data->vid |= (w83791d_read(client, W83791D_REG_DID_VID4) & 0x01) + << 4; + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + +#ifdef DEBUG + w83791d_print_debug(data, dev); +#endif + + return data; +} + +#ifdef DEBUG +static void w83791d_print_debug(struct w83791d_data *data, struct device *dev) +{ + int i = 0, j = 0; + + dev_dbg(dev, "======Start of w83791d debug values======\n"); + dev_dbg(dev, "%d set of Voltages: ===>\n", NUMBER_OF_VIN); + for (i = 0; i < NUMBER_OF_VIN; i++) { + dev_dbg(dev, "vin[%d] is: 0x%02x\n", i, data->in[i]); + dev_dbg(dev, "vin[%d] min is: 0x%02x\n", i, data->in_min[i]); + dev_dbg(dev, "vin[%d] max is: 0x%02x\n", i, data->in_max[i]); + } + dev_dbg(dev, "%d set of Fan Counts/Divisors: ===>\n", NUMBER_OF_FANIN); + for (i = 0; i < NUMBER_OF_FANIN; i++) { + dev_dbg(dev, "fan[%d] is: 0x%02x\n", i, data->fan[i]); + dev_dbg(dev, "fan[%d] min is: 0x%02x\n", i, data->fan_min[i]); + dev_dbg(dev, "fan_div[%d] is: 0x%02x\n", i, data->fan_div[i]); + } + + /* temperature math is signed, but only print out the + bits that matter */ + dev_dbg(dev, "%d set of Temperatures: ===>\n", NUMBER_OF_TEMPIN); + for (i = 0; i < 3; i++) { + dev_dbg(dev, "temp1[%d] is: 0x%02x\n", i, (u8) data->temp1[i]); + } + for (i = 0; i < 2; i++) { + for (j = 0; j < 3; j++) { + dev_dbg(dev, "temp_add[%d][%d] is: 0x%04x\n", i, j, + (u16) data->temp_add[i][j]); + } + } + + dev_dbg(dev, "Misc Information: ===>\n"); + dev_dbg(dev, "alarm is: 0x%08x\n", data->alarms); + dev_dbg(dev, "beep_mask is: 0x%08x\n", data->beep_mask); + dev_dbg(dev, "beep_enable is: %d\n", data->beep_enable); + dev_dbg(dev, "vid is: 0x%02x\n", data->vid); + dev_dbg(dev, "vrm is: 0x%02x\n", data->vrm); + dev_dbg(dev, "=======End of w83791d debug values========\n"); + dev_dbg(dev, "\n"); +} +#endif + +static int __init sensors_w83791d_init(void) +{ + return i2c_add_driver(&w83791d_driver); +} + +static void __exit sensors_w83791d_exit(void) +{ + i2c_del_driver(&w83791d_driver); +} + +MODULE_AUTHOR("Charles Spirakis "); +MODULE_DESCRIPTION("W83791D driver"); +MODULE_LICENSE("GPL"); + +module_init(sensors_w83791d_init); +module_exit(sensors_w83791d_exit); -- cgit v1.2.3 From 114cc0c0c1e98f0b8e205f91ae7b2471e0ad5325 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 25 Apr 2006 14:22:14 +0200 Subject: [PATCH] HWMON: lm83: Documentation update One more motherboard confirmed to have an LM83 temperature sensor chip. Thanks to Steven Hardy for reporting. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- Documentation/hwmon/lm83 | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/hwmon/lm83 b/Documentation/hwmon/lm83 index 74aa7ee1a35..f7aad1489cb 100644 --- a/Documentation/hwmon/lm83 +++ b/Documentation/hwmon/lm83 @@ -35,6 +35,7 @@ contact us. Note that the LM90 can easily be misdetected as a LM83. Confirmed motherboards: SBS P014 + SBS PSL09 Unconfirmed motherboards: Gigabyte GA-8IK1100 -- cgit v1.2.3 From 0d0001dd956d4ae2c8739c2877fa660eec68ed5f Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 25 Apr 2006 14:23:01 +0200 Subject: [PATCH] HWMON: Improve the help text for CONFIG_HWMON Improve the help text for CONFIG_HWMON to let the users know how they pick the right hardware monitoring driver(s) for their system. Also fix a couple typos in the related documentation file and improve some parts a bit. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- Documentation/hwmon/userspace-tools | 17 +++++++++-------- drivers/hwmon/Kconfig | 4 ++++ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/Documentation/hwmon/userspace-tools b/Documentation/hwmon/userspace-tools index 2622aac6542..19900a8fe67 100644 --- a/Documentation/hwmon/userspace-tools +++ b/Documentation/hwmon/userspace-tools @@ -6,31 +6,32 @@ voltages, fans speed). They are often connected through an I2C bus, but some are also connected directly through the ISA bus. The kernel drivers make the data from the sensor chips available in the /sys -virtual filesystem. Userspace tools are then used to display or set or the -data in a more friendly manner. +virtual filesystem. Userspace tools are then used to display the measured +values or configure the chips in a more friendly manner. Lm-sensors ---------- -Core set of utilites that will allow you to obtain health information, +Core set of utilities that will allow you to obtain health information, setup monitoring limits etc. You can get them on their homepage http://www.lm-sensors.nu/ or as a package from your Linux distribution. If from website: -Get lmsensors from project web site. Please note, you need only userspace -part, so compile with "make user_install" target. +Get lm-sensors from project web site. Please note, you need only userspace +part, so compile with "make user" and install with "make user_install". General hints to get things working: 0) get lm-sensors userspace utils -1) compile all drivers in I2C section as modules in your kernel +1) compile all drivers in I2C and Hardware Monitoring sections as modules + in your kernel 2) run sensors-detect script, it will tell you what modules you need to load. 3) load them and run "sensors" command, you should see some results. 4) fix sensors.conf, labels, limits, fan divisors 5) if any more problems consult FAQ, or documentation -Other utilites --------------- +Other utilities +--------------- If you want some graphical indicators of system health look for applications like: gkrellm, ksensors, xsensors, wmtemp, wmsensors, wmgtemp, ksysguardd, diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 9384b85b893..164760df123 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -16,6 +16,10 @@ config HWMON should say Y here and also to the specific driver(s) for your sensors chip(s) below. + To find out which specific driver(s) you need, use the + sensors-detect script from the lm_sensors package. Read + for details. + This support can also be built as a module. If so, the module will be called hwmon. -- cgit v1.2.3 From 177d165d7c2ec424007d6241a93d0cb83d953c51 Mon Sep 17 00:00:00 2001 From: Rudolf Marek Date: Tue, 25 Apr 2006 14:24:46 +0200 Subject: [PATCH] HWMON: Trim VID values to correct number of bits Following patch trims the VID value to correct number of bits for each VRM. Signed-off-by: Rudolf Marek Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/hwmon-vid.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/hwmon/hwmon-vid.c b/drivers/hwmon/hwmon-vid.c index a74a44f16f5..b0fd267635b 100644 --- a/drivers/hwmon/hwmon-vid.c +++ b/drivers/hwmon/hwmon-vid.c @@ -70,6 +70,7 @@ int vid_from_reg(int val, u8 vrm) switch(vrm) { case 100: /* VRD 10.0 */ + val &= 0x3f; if((val & 0x1f) == 0x1f) return 0; if((val & 0x1f) <= 0x09 || val == 0x0a) @@ -82,14 +83,17 @@ int vid_from_reg(int val, u8 vrm) return vid; case 24: /* Opteron processor */ + val &= 0x1f; return(val == 0x1f ? 0 : 1550 - val * 25); case 91: /* VRM 9.1 */ case 90: /* VRM 9.0 */ + val &= 0x1f; return(val == 0x1f ? 0 : 1850 - val * 25); case 85: /* VRM 8.5 */ + val &= 0x1f; return((val & 0x10 ? 25 : 0) + ((val & 0x0f) > 0x04 ? 2050 : 1250) - ((val & 0x0f) * 50)); @@ -98,14 +102,17 @@ int vid_from_reg(int val, u8 vrm) val &= 0x0f; /* fall through */ case 82: /* VRM 8.2 */ + val &= 0x1f; return(val == 0x1f ? 0 : val & 0x10 ? 5100 - (val) * 100 : 2050 - (val) * 50); case 17: /* Intel IMVP-II */ + val &= 0x1f; return(val & 0x10 ? 975 - (val & 0xF) * 25 : 1750 - val * 50); case 13: - return(1708 - (val & 0x3f) * 16); + val &= 0x3f; + return(1708 - val * 16); default: /* report 0 for unknown */ printk(KERN_INFO "hwmon-vid: requested unknown VRM version\n"); return 0; -- cgit v1.2.3 From aee62305345863430a937af289b9bd080a100dac Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 4 Jun 2006 19:59:57 +0200 Subject: [PATCH] i2c: Suggest N for rare devices in Kconfig Improve the Kconfig help text of the follwing i2c drivers: * busses/i2c-pca-isa.c * chips/pcf8574.c * chips/pcf8591.c These are hard to detect and building them into the kernel results in long delays at boot. March 2006, thread "I2C_PCA_ISA causes boot delays" http://marc.theaimsgroup.com/?l=linux-kernel&m=114360399415744&w=2 April 2006, thread "i2c-related 1-minute hang during bootup" http://marc.theaimsgroup.com/?l=linux-kernel&m=114640992330721&w=2 Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/Kconfig | 6 ++++++ drivers/i2c/chips/Kconfig | 8 ++++++++ 2 files changed, 14 insertions(+) diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index e3450d16d8a..d25a8cbbec0 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -503,6 +503,7 @@ config I2C_PCA_ISA tristate "PCA9564 on an ISA bus" depends on I2C select I2C_ALGOPCA + default n help This driver supports ISA boards using the Philips PCA 9564 Parallel bus to I2C bus controller @@ -510,6 +511,11 @@ config I2C_PCA_ISA This driver can also be built as a module. If so, the module will be called i2c-pca-isa. + This device is almost undetectable and using this driver on a + system which doesn't have this device will result in long + delays when I2C/SMBus chip drivers are loaded (e.g. at boot + time). If unsure, say N. + config I2C_MV64XXX tristate "Marvell mv64xxx I2C Controller" depends on I2C && MV64X60 && EXPERIMENTAL diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig index 7aa5c38f085..87ee3ce5861 100644 --- a/drivers/i2c/chips/Kconfig +++ b/drivers/i2c/chips/Kconfig @@ -39,6 +39,7 @@ config SENSORS_EEPROM config SENSORS_PCF8574 tristate "Philips PCF8574 and PCF8574A" depends on I2C && EXPERIMENTAL + default n help If you say yes here you get support for Philips PCF8574 and PCF8574A chips. @@ -46,6 +47,9 @@ config SENSORS_PCF8574 This driver can also be built as a module. If so, the module will be called pcf8574. + These devices are hard to detect and rarely found on mainstream + hardware. If unsure, say N. + config SENSORS_PCA9539 tristate "Philips PCA9539 16-bit I/O port" depends on I2C && EXPERIMENTAL @@ -59,12 +63,16 @@ config SENSORS_PCA9539 config SENSORS_PCF8591 tristate "Philips PCF8591" depends on I2C && EXPERIMENTAL + default n help If you say yes here you get support for Philips PCF8591 chips. This driver can also be built as a module. If so, the module will be called pcf8591. + These devices are hard to detect and rarely found on mainstream + hardware. If unsure, say N. + config ISP1301_OMAP tristate "Philips ISP1301 with OMAP OTG" depends on I2C && ARCH_OMAP_OTG -- cgit v1.2.3 From 18f98b1e3147afdb51e545cc6ff2b016c7d088a7 Mon Sep 17 00:00:00 2001 From: Peter Korsgaard Date: Sun, 4 Jun 2006 20:01:08 +0200 Subject: [PATCH] i2c: New bus driver for the OpenCores I2C controller The following patch adds support for the OpenCores I2C controller IP core (See http://www.opencores.org/projects.cgi/web/i2c/overview). Signed-off-by: Peter Korsgaard Signed-off-by: Andrew Morton Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- Documentation/i2c/busses/i2c-ocores | 51 ++++++ drivers/i2c/busses/Kconfig | 11 ++ drivers/i2c/busses/Makefile | 1 + drivers/i2c/busses/i2c-ocores.c | 343 ++++++++++++++++++++++++++++++++++++ include/linux/i2c-ocores.h | 19 ++ 5 files changed, 425 insertions(+) create mode 100644 Documentation/i2c/busses/i2c-ocores create mode 100644 drivers/i2c/busses/i2c-ocores.c create mode 100644 include/linux/i2c-ocores.h diff --git a/Documentation/i2c/busses/i2c-ocores b/Documentation/i2c/busses/i2c-ocores new file mode 100644 index 00000000000..cfcebb10d14 --- /dev/null +++ b/Documentation/i2c/busses/i2c-ocores @@ -0,0 +1,51 @@ +Kernel driver i2c-ocores + +Supported adapters: + * OpenCores.org I2C controller by Richard Herveille (see datasheet link) + Datasheet: http://www.opencores.org/projects.cgi/web/i2c/overview + +Author: Peter Korsgaard + +Description +----------- + +i2c-ocores is an i2c bus driver for the OpenCores.org I2C controller +IP core by Richard Herveille. + +Usage +----- + +i2c-ocores uses the platform bus, so you need to provide a struct +platform_device with the base address and interrupt number. The +dev.platform_data of the device should also point to a struct +ocores_i2c_platform_data (see linux/i2c-ocores.h) describing the +distance between registers and the input clock speed. + +E.G. something like: + +static struct resource ocores_resources[] = { + [0] = { + .start = MYI2C_BASEADDR, + .end = MYI2C_BASEADDR + 8, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = MYI2C_IRQ, + .end = MYI2C_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct ocores_i2c_platform_data myi2c_data = { + .regstep = 2, /* two bytes between registers */ + .clock_khz = 50000, /* input clock of 50MHz */ +}; + +static struct platform_device myi2c = { + .name = "ocores-i2c", + .dev = { + .platform_data = &myi2c_data, + }, + .num_resources = ARRAY_SIZE(ocores_resources), + .resource = ocores_resources, +}; diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index d25a8cbbec0..f7af7e9bb7d 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -276,6 +276,17 @@ config I2C_NFORCE2 This driver can also be built as a module. If so, the module will be called i2c-nforce2. +config I2C_OCORES + tristate "OpenCores I2C Controller" + depends on I2C && EXPERIMENTAL + help + If you say yes to this option, support will be included for the + OpenCores I2C controller. For details see + http://www.opencores.org/projects.cgi/web/i2c/overview + + This driver can also be built as a module. If so, the module + will be called i2c-ocores. + config I2C_PARPORT tristate "Parallel port adapter" depends on I2C && PARPORT diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index b44831dff68..ac56df53155 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -23,6 +23,7 @@ obj-$(CONFIG_I2C_POWERMAC) += i2c-powermac.o obj-$(CONFIG_I2C_MPC) += i2c-mpc.o obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o obj-$(CONFIG_I2C_NFORCE2) += i2c-nforce2.o +obj-$(CONFIG_I2C_OCORES) += i2c-ocores.o obj-$(CONFIG_I2C_PARPORT) += i2c-parport.o obj-$(CONFIG_I2C_PARPORT_LIGHT) += i2c-parport-light.o obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c new file mode 100644 index 00000000000..d5c0610bfe6 --- /dev/null +++ b/drivers/i2c/busses/i2c-ocores.c @@ -0,0 +1,343 @@ +/* + * i2c-ocores.c: I2C bus driver for OpenCores I2C controller + * (http://www.opencores.org/projects.cgi/web/i2c/overview). + * + * Peter Korsgaard + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct ocores_i2c { + void __iomem *base; + int regstep; + wait_queue_head_t wait; + struct i2c_adapter adap; + struct i2c_msg *msg; + int pos; + int nmsgs; + int state; /* see STATE_ */ +}; + +/* registers */ +#define OCI2C_PRELOW 0 +#define OCI2C_PREHIGH 1 +#define OCI2C_CONTROL 2 +#define OCI2C_DATA 3 +#define OCI2C_CMD 4 +#define OCI2C_STATUS 4 + +#define OCI2C_CTRL_IEN 0x40 +#define OCI2C_CTRL_EN 0x80 + +#define OCI2C_CMD_START 0x91 +#define OCI2C_CMD_STOP 0x41 +#define OCI2C_CMD_READ 0x21 +#define OCI2C_CMD_WRITE 0x11 +#define OCI2C_CMD_READ_ACK 0x21 +#define OCI2C_CMD_READ_NACK 0x29 +#define OCI2C_CMD_IACK 0x01 + +#define OCI2C_STAT_IF 0x01 +#define OCI2C_STAT_TIP 0x02 +#define OCI2C_STAT_ARBLOST 0x20 +#define OCI2C_STAT_BUSY 0x40 +#define OCI2C_STAT_NACK 0x80 + +#define STATE_DONE 0 +#define STATE_START 1 +#define STATE_WRITE 2 +#define STATE_READ 3 +#define STATE_ERROR 4 + +static inline void oc_setreg(struct ocores_i2c *i2c, int reg, u8 value) +{ + iowrite8(value, i2c->base + reg * i2c->regstep); +} + +static inline u8 oc_getreg(struct ocores_i2c *i2c, int reg) +{ + return ioread8(i2c->base + reg * i2c->regstep); +} + +static void ocores_process(struct ocores_i2c *i2c) +{ + struct i2c_msg *msg = i2c->msg; + u8 stat = oc_getreg(i2c, OCI2C_STATUS); + + if ((i2c->state == STATE_DONE) || (i2c->state == STATE_ERROR)) { + /* stop has been sent */ + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK); + wake_up(&i2c->wait); + return; + } + + /* error? */ + if (stat & OCI2C_STAT_ARBLOST) { + i2c->state = STATE_ERROR; + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP); + return; + } + + if ((i2c->state == STATE_START) || (i2c->state == STATE_WRITE)) { + i2c->state = + (msg->flags & I2C_M_RD) ? STATE_READ : STATE_WRITE; + + if (stat & OCI2C_STAT_NACK) { + i2c->state = STATE_ERROR; + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP); + return; + } + } else + msg->buf[i2c->pos++] = oc_getreg(i2c, OCI2C_DATA); + + /* end of msg? */ + if (i2c->pos == msg->len) { + i2c->nmsgs--; + i2c->msg++; + i2c->pos = 0; + msg = i2c->msg; + + if (i2c->nmsgs) { /* end? */ + /* send start? */ + if (!(msg->flags & I2C_M_NOSTART)) { + u8 addr = (msg->addr << 1); + + if (msg->flags & I2C_M_RD) + addr |= 1; + + i2c->state = STATE_START; + + oc_setreg(i2c, OCI2C_DATA, addr); + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_START); + return; + } else + i2c->state = (msg->flags & I2C_M_RD) + ? STATE_READ : STATE_WRITE; + } else { + i2c->state = STATE_DONE; + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP); + return; + } + } + + if (i2c->state == STATE_READ) { + oc_setreg(i2c, OCI2C_CMD, i2c->pos == (msg->len-1) ? + OCI2C_CMD_READ_NACK : OCI2C_CMD_READ_ACK); + } else { + oc_setreg(i2c, OCI2C_DATA, msg->buf[i2c->pos++]); + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_WRITE); + } +} + +static irqreturn_t ocores_isr(int irq, void *dev_id, struct pt_regs *regs) +{ + struct ocores_i2c *i2c = dev_id; + + ocores_process(i2c); + + return IRQ_HANDLED; +} + +static int ocores_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) +{ + struct ocores_i2c *i2c = i2c_get_adapdata(adap); + + i2c->msg = msgs; + i2c->pos = 0; + i2c->nmsgs = num; + i2c->state = STATE_START; + + oc_setreg(i2c, OCI2C_DATA, + (i2c->msg->addr << 1) | + ((i2c->msg->flags & I2C_M_RD) ? 1:0)); + + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_START); + + if (wait_event_timeout(i2c->wait, (i2c->state == STATE_ERROR) || + (i2c->state == STATE_DONE), HZ)) + return (i2c->state == STATE_DONE) ? num : -EIO; + else + return -ETIMEDOUT; +} + +static void ocores_init(struct ocores_i2c *i2c, + struct ocores_i2c_platform_data *pdata) +{ + int prescale; + u8 ctrl = oc_getreg(i2c, OCI2C_CONTROL); + + /* make sure the device is disabled */ + oc_setreg(i2c, OCI2C_CONTROL, ctrl & ~(OCI2C_CTRL_EN|OCI2C_CTRL_IEN)); + + prescale = (pdata->clock_khz / (5*100)) - 1; + oc_setreg(i2c, OCI2C_PRELOW, prescale & 0xff); + oc_setreg(i2c, OCI2C_PREHIGH, prescale >> 8); + + /* Init the device */ + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK); + oc_setreg(i2c, OCI2C_CONTROL, ctrl | OCI2C_CTRL_IEN | OCI2C_CTRL_EN); +} + + +static u32 ocores_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +static struct i2c_algorithm ocores_algorithm = { + .master_xfer = ocores_xfer, + .functionality = ocores_func, +}; + +static struct i2c_adapter ocores_adapter = { + .owner = THIS_MODULE, + .name = "i2c-ocores", + .class = I2C_CLASS_HWMON, + .algo = &ocores_algorithm, + .timeout = 2, + .retries = 1, +}; + + +static int __devinit ocores_i2c_probe(struct platform_device *pdev) +{ + struct ocores_i2c *i2c; + struct ocores_i2c_platform_data *pdata; + struct resource *res, *res2; + int ret; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + + res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!res2) + return -ENODEV; + + pdata = (struct ocores_i2c_platform_data*) pdev->dev.platform_data; + if (!pdata) + return -ENODEV; + + i2c = kzalloc(sizeof(*i2c), GFP_KERNEL); + if (!i2c) + return -ENOMEM; + + if (!request_mem_region(res->start, res->end - res->start + 1, + pdev->name)) { + dev_err(&pdev->dev, "Memory region busy\n"); + ret = -EBUSY; + goto request_mem_failed; + } + + i2c->base = ioremap(res->start, res->end - res->start + 1); + if (!i2c->base) { + dev_err(&pdev->dev, "Unable to map registers\n"); + ret = -EIO; + goto map_failed; + } + + i2c->regstep = pdata->regstep; + ocores_init(i2c, pdata); + + init_waitqueue_head(&i2c->wait); + ret = request_irq(res2->start, ocores_isr, 0, pdev->name, i2c); + if (ret) { + dev_err(&pdev->dev, "Cannot claim IRQ\n"); + goto request_irq_failed; + } + + /* hook up driver to tree */ + platform_set_drvdata(pdev, i2c); + i2c->adap = ocores_adapter; + i2c_set_adapdata(&i2c->adap, i2c); + i2c->adap.dev.parent = &pdev->dev; + + /* add i2c adapter to i2c tree */ + ret = i2c_add_adapter(&i2c->adap); + if (ret) { + dev_err(&pdev->dev, "Failed to add adapter\n"); + goto add_adapter_failed; + } + + return 0; + +add_adapter_failed: + free_irq(res2->start, i2c); +request_irq_failed: + iounmap(i2c->base); +map_failed: + release_mem_region(res->start, res->end - res->start + 1); +request_mem_failed: + kfree(i2c); + + return ret; +} + +static int __devexit ocores_i2c_remove(struct platform_device* pdev) +{ + struct ocores_i2c *i2c = platform_get_drvdata(pdev); + struct resource *res; + + /* disable i2c logic */ + oc_setreg(i2c, OCI2C_CONTROL, oc_getreg(i2c, OCI2C_CONTROL) + & ~(OCI2C_CTRL_EN|OCI2C_CTRL_IEN)); + + /* remove adapter & data */ + i2c_del_adapter(&i2c->adap); + platform_set_drvdata(pdev, NULL); + + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (res) + free_irq(res->start, i2c); + + iounmap(i2c->base); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res) + release_mem_region(res->start, res->end - res->start + 1); + + kfree(i2c); + + return 0; +} + +static struct platform_driver ocores_i2c_driver = { + .probe = ocores_i2c_probe, + .remove = __devexit_p(ocores_i2c_remove), + .driver = { + .owner = THIS_MODULE, + .name = "ocores-i2c", + }, +}; + +static int __init ocores_i2c_init(void) +{ + return platform_driver_register(&ocores_i2c_driver); +} + +static void __exit ocores_i2c_exit(void) +{ + platform_driver_unregister(&ocores_i2c_driver); +} + +module_init(ocores_i2c_init); +module_exit(ocores_i2c_exit); + +MODULE_AUTHOR("Peter Korsgaard "); +MODULE_DESCRIPTION("OpenCores I2C bus driver"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/i2c-ocores.h b/include/linux/i2c-ocores.h new file mode 100644 index 00000000000..8ed591b0887 --- /dev/null +++ b/include/linux/i2c-ocores.h @@ -0,0 +1,19 @@ +/* + * i2c-ocores.h - definitions for the i2c-ocores interface + * + * Peter Korsgaard + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#ifndef _LINUX_I2C_OCORES_H +#define _LINUX_I2C_OCORES_H + +struct ocores_i2c_platform_data { + u32 regstep; /* distance between registers */ + u32 clock_khz; /* input clock in kHz */ +}; + +#endif /* _LINUX_I2C_OCORES_H */ -- cgit v1.2.3 From 057bc350992fa2ac31fcd2ff80add269bdf32a80 Mon Sep 17 00:00:00 2001 From: Rudolf Marek Date: Sun, 4 Jun 2006 20:03:39 +0200 Subject: [PATCH] hwmon: Sysfs interface documentation update, 1 of 2 This patch cleans up hwmon sysfs documentation file, plus introduces the description of DC/PWM selection for fan speed control. Signed-off-by: Rudolf Marek Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- Documentation/hwmon/sysfs-interface | 181 +++++++++++++++++++++--------------- 1 file changed, 107 insertions(+), 74 deletions(-) diff --git a/Documentation/hwmon/sysfs-interface b/Documentation/hwmon/sysfs-interface index eeb912254db..bc59a5113d1 100644 --- a/Documentation/hwmon/sysfs-interface +++ b/Documentation/hwmon/sysfs-interface @@ -69,28 +69,37 @@ to cause an alarm) is chip-dependent. ------------------------------------------------------------------------- +[0-*] denotes any positive number starting from 0 +[1-*] denotes any positive number starting from 1 +RO read only value +RW read/write value + +Read/write values may be read-only for some chips, depending on the +hardware implementation. + ************ * Voltages * ************ -in[0-8]_min Voltage min value. +in[0-*]_min Voltage min value. Unit: millivolt - Read/Write + RW -in[0-8]_max Voltage max value. +in[0-*]_max Voltage max value. Unit: millivolt - Read/Write + RW -in[0-8]_input Voltage input value. +in[0-*]_input Voltage input value. Unit: millivolt - Read only + RO + Voltage measured on the chip pin. Actual voltage depends on the scaling resistors on the motherboard, as recommended in the chip datasheet. This varies by chip and by motherboard. Because of this variation, values are generally NOT scaled by the chip driver, and must be done by the application. However, some drivers (notably lm87 and via686a) - do scale, with various degrees of success. + do scale, because of internal resistors built into a chip. These drivers will output the actual voltage. Typical usage: @@ -104,58 +113,72 @@ in[0-8]_input Voltage input value. in7_* varies in8_* varies -cpu[0-1]_vid CPU core reference voltage. +cpu[0-*]_vid CPU core reference voltage. Unit: millivolt - Read only. + RO Not always correct. vrm Voltage Regulator Module version number. - Read only. - Two digit number, first is major version, second is - minor version. + RW (but changing it should no more be necessary) + Originally the VRM standard version multiplied by 10, but now + an arbitrary number, as not all standards have a version + number. Affects the way the driver calculates the CPU core reference voltage from the vid pins. +Also see the Alarms section for status flags associated with voltages. + ******** * Fans * ******** -fan[1-3]_min Fan minimum value +fan[1-*]_min Fan minimum value Unit: revolution/min (RPM) - Read/Write. + RW -fan[1-3]_input Fan input value. +fan[1-*]_input Fan input value. Unit: revolution/min (RPM) - Read only. + RO -fan[1-3]_div Fan divisor. +fan[1-*]_div Fan divisor. Integer value in powers of two (1, 2, 4, 8, 16, 32, 64, 128). + RW Some chips only support values 1, 2, 4 and 8. Note that this is actually an internal clock divisor, which affects the measurable speed range, not the read value. +Also see the Alarms section for status flags associated with fans. + + ******* * PWM * ******* -pwm[1-3] Pulse width modulation fan control. +pwm[1-*] Pulse width modulation fan control. Integer value in the range 0 to 255 - Read/Write + RW 255 is max or 100%. -pwm[1-3]_enable +pwm[1-*]_enable Switch PWM on and off. Not always present even if fan*_pwm is. - 0 to turn off - 1 to turn on in manual mode - 2 to turn on in automatic mode - Read/Write + 0: turn off + 1: turn on in manual mode + 2+: turn on in automatic mode + Check individual chip documentation files for automatic mode details. + RW + +pwm[1-*]_mode + 0: DC mode + 1: PWM mode + RW pwm[1-*]_auto_channels_temp Select which temperature channels affect this PWM output in auto mode. Bitfield, 1 is temp1, 2 is temp2, 4 is temp3 etc... Which values are possible depend on the chip used. + RW pwm[1-*]_auto_point[1-*]_pwm pwm[1-*]_auto_point[1-*]_temp @@ -163,6 +186,7 @@ pwm[1-*]_auto_point[1-*]_temp_hyst Define the PWM vs temperature curve. Number of trip points is chip-dependent. Use this for chips which associate trip points to PWM output channels. + RW OR @@ -172,51 +196,52 @@ temp[1-*]_auto_point[1-*]_temp_hyst Define the PWM vs temperature curve. Number of trip points is chip-dependent. Use this for chips which associate trip points to temperature channels. + RW **************** * Temperatures * **************** -temp[1-3]_type Sensor type selection. +temp[1-*]_type Sensor type selection. Integers 1 to 4 or thermistor Beta value (typically 3435) - Read/Write. + RW 1: PII/Celeron Diode 2: 3904 transistor 3: thermal diode 4: thermistor (default/unknown Beta) Not all types are supported by all chips -temp[1-4]_max Temperature max value. +temp[1-*]_max Temperature max value. Unit: millidegree Celcius - Read/Write value. + RW -temp[1-3]_min Temperature min value. +temp[1-*]_min Temperature min value. Unit: millidegree Celcius - Read/Write value. + RW -temp[1-3]_max_hyst +temp[1-*]_max_hyst Temperature hysteresis value for max limit. Unit: millidegree Celcius Must be reported as an absolute temperature, NOT a delta from the max value. - Read/Write value. + RW -temp[1-4]_input Temperature input value. +temp[1-*]_input Temperature input value. Unit: millidegree Celcius - Read only value. + RO -temp[1-4]_crit Temperature critical value, typically greater than +temp[1-*]_crit Temperature critical value, typically greater than corresponding temp_max values. Unit: millidegree Celcius - Read/Write value. + RW -temp[1-2]_crit_hyst +temp[1-*]_crit_hyst Temperature hysteresis value for critical limit. Unit: millidegree Celcius Must be reported as an absolute temperature, NOT a delta from the critical value. - Read/Write value. + RW temp[1-4]_offset Temperature offset which is added to the temperature reading @@ -231,6 +256,8 @@ temp[1-4]_offset itself, for example the thermal diode inside the CPU or a thermistor nearby. +Also see the Alarms section for status flags associated with temperatures. + ************ * Currents * @@ -239,17 +266,17 @@ temp[1-4]_offset Note that no known chip provides current measurements as of writing, so this part is theoretical, so to say. -curr[1-n]_max Current max value +curr[1-*]_max Current max value Unit: milliampere - Read/Write. + RW -curr[1-n]_min Current min value. +curr[1-*]_min Current min value. Unit: milliampere - Read/Write. + RW -curr[1-n]_input Current input value +curr[1-*]_input Current input value Unit: milliampere - Read only. + RO ********** @@ -263,50 +290,54 @@ Usually a given chip will either use channel-related alarms, or limit-related alarms, not both. The driver should just reflect the hardware implementation. -in[0-n]_alarm -fan[1-n]_alarm -temp[1-n]_alarm +in[0-*]_alarm +fan[1-*]_alarm +temp[1-*]_alarm Channel alarm - Boolean - Read-only + 0: no alarm + 1: alarm + RO OR -in[0-n]_min_alarm -in[0-n]_max_alarm -fan[1-n]_min_alarm -temp[1-n]_min_alarm -temp[1-n]_max_alarm -temp[1-n]_crit_alarm +in[0-*]_min_alarm +in[0-*]_max_alarm +fan[1-*]_min_alarm +temp[1-*]_min_alarm +temp[1-*]_max_alarm +temp[1-*]_crit_alarm Limit alarm - Boolean - Read-only + 0: no alarm + 1: alarm + RO Each input channel may have an associated fault file. This can be used to notify open diodes, unconnected fans etc. where the hardware supports it. When this boolean has value 1, the measurement for that channel should not be trusted. -in[0-n]_input_fault -fan[1-n]_input_fault -temp[1-n]_input_fault +in[0-*]_input_fault +fan[1-*]_input_fault +temp[1-*]_input_fault Input fault condition - Boolean - Read-only + 0: no fault occured + 1: fault condition + RO Some chips also offer the possibility to get beeped when an alarm occurs: beep_enable Master beep enable - Boolean - Read/Write + 0: no beeps + 1: beeps + RW -in[0-n]_beep -fan[1-n]_beep -temp[1-n]_beep +in[0-*]_beep +fan[1-*]_beep +temp[1-*]_beep Channel beep - 0 to disable. - 1 to enable. - Read/write + 0: disable + 1: enable + RW In theory, a chip could provide per-limit beep masking, but no such chip was seen so far. @@ -316,7 +347,7 @@ beeps. These interface files are deprecated, but will be kept around for compatibility reasons: alarms Alarm bitmask. - Read only. + RO Integer representation of one to four bytes. A '1' bit means an alarm. Chips should be programmed for 'comparator' mode so that @@ -333,7 +364,7 @@ beep_mask Bitmask for beep. Same format as 'alarms' with the same bit locations, use discouraged for the same reason. Use individual *_beep files instead. - Read/Write + RW ********* @@ -341,7 +372,9 @@ beep_mask Bitmask for beep. ********* eeprom Raw EEPROM data in binary form. - Read only. + RO pec Enable or disable PEC (SMBus only) - Read/Write + 0: disable + 1: enable + RW -- cgit v1.2.3 From 740e06a89fb905ee1979c57442c544afe51ed21c Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 5 Jun 2006 20:31:20 +0200 Subject: [PATCH] hwmon: Sysfs interface documentation update, 2 of 2, take 2 Reword and complete certain parts of the hwmon sysfs-interface documentation file. Hopefully this will make things clearer for new driver authors. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- Documentation/hwmon/sysfs-interface | 45 ++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/Documentation/hwmon/sysfs-interface b/Documentation/hwmon/sysfs-interface index bc59a5113d1..d1d390aaf62 100644 --- a/Documentation/hwmon/sysfs-interface +++ b/Documentation/hwmon/sysfs-interface @@ -3,15 +3,15 @@ Naming and data format standards for sysfs files The libsensors library offers an interface to the raw sensors data through the sysfs interface. See libsensors documentation and source for -more further information. As of writing this document, libsensors -(from lm_sensors 2.8.3) is heavily chip-dependant. Adding or updating +further information. As of writing this document, libsensors +(from lm_sensors 2.8.3) is heavily chip-dependent. Adding or updating support for any given chip requires modifying the library's code. This is because libsensors was written for the procfs interface older kernel modules were using, which wasn't standardized enough. Recent versions of libsensors (from lm_sensors 2.8.2 and later) have support for the sysfs interface, though. -The new sysfs interface was designed to be as chip-independant as +The new sysfs interface was designed to be as chip-independent as possible. Note that motherboards vary widely in the connections to sensor chips. @@ -24,7 +24,7 @@ range using external resistors. Since the values of these resistors can change from motherboard to motherboard, the conversions cannot be hard coded into the driver and have to be done in user space. -For this reason, even if we aim at a chip-independant libsensors, it will +For this reason, even if we aim at a chip-independent libsensors, it will still require a configuration file (e.g. /etc/sensors.conf) for proper values conversion, labeling of inputs and hiding of unused inputs. @@ -39,15 +39,16 @@ If you are developing a userspace application please send us feedback on this standard. Note that this standard isn't completely established yet, so it is subject -to changes, even important ones. One more reason to use the library instead -of accessing sysfs files directly. +to changes. If you are writing a new hardware monitoring driver those +features can't seem to fit in this interface, please contact us with your +extension proposal. Keep in mind that backward compatibility must be +preserved. Each chip gets its own directory in the sysfs /sys/devices tree. To -find all sensor chips, it is easier to follow the symlinks from -/sys/i2c/devices/ +find all sensor chips, it is easier to follow the device symlinks from +/sys/class/hwmon/hwmon*. -All sysfs values are fixed point numbers. To get the true value of some -of the values, you should divide by the specified value. +All sysfs values are fixed point numbers. There is only one value per file, unlike the older /proc specification. The common scheme for files naming is: _. Usual @@ -77,6 +78,9 @@ RW read/write value Read/write values may be read-only for some chips, depending on the hardware implementation. +All entries are optional, and should only be created in a given driver +if the chip has the feature. + ************ * Voltages * ************ @@ -213,32 +217,32 @@ temp[1-*]_type Sensor type selection. Not all types are supported by all chips temp[1-*]_max Temperature max value. - Unit: millidegree Celcius + Unit: millidegree Celsius (or millivolt, see below) RW temp[1-*]_min Temperature min value. - Unit: millidegree Celcius + Unit: millidegree Celsius RW temp[1-*]_max_hyst Temperature hysteresis value for max limit. - Unit: millidegree Celcius + Unit: millidegree Celsius Must be reported as an absolute temperature, NOT a delta from the max value. RW temp[1-*]_input Temperature input value. - Unit: millidegree Celcius + Unit: millidegree Celsius RO temp[1-*]_crit Temperature critical value, typically greater than corresponding temp_max values. - Unit: millidegree Celcius + Unit: millidegree Celsius RW temp[1-*]_crit_hyst Temperature hysteresis value for critical limit. - Unit: millidegree Celcius + Unit: millidegree Celsius Must be reported as an absolute temperature, NOT a delta from the critical value. RW @@ -256,6 +260,15 @@ temp[1-4]_offset itself, for example the thermal diode inside the CPU or a thermistor nearby. +Some chips measure temperature using external thermistors and an ADC, and +report the temperature measurement as a voltage. Converting this voltage +back to a temperature (or the other way around for limits) requires +mathematical functions not available in the kernel, so the conversion +must occur in user space. For these chips, all temp* files described +above should contain values expressed in millivolt instead of millidegree +Celsius. In other words, such temperature channels are handled as voltage +channels by the driver. + Also see the Alarms section for status flags associated with temperatures. -- cgit v1.2.3 From 0a704681f37f8cd84fa10312728a39e9fcf2c2c5 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 4 Jun 2006 20:10:55 +0200 Subject: [PATCH] hwmon: Fix a typo in the hdaps driver Fix a typo in the hdaps driver. Signed-off-by: Jean Delvare Acked-by: Robert Love Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/hdaps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c index 7841fa07025..42b632889dd 100644 --- a/drivers/hwmon/hdaps.c +++ b/drivers/hwmon/hdaps.c @@ -41,7 +41,7 @@ #define HDAPS_PORT_STATE 0x1611 /* device state */ #define HDAPS_PORT_YPOS 0x1612 /* y-axis position */ #define HDAPS_PORT_XPOS 0x1614 /* x-axis position */ -#define HDAPS_PORT_TEMP1 0x1616 /* device temperature, in celcius */ +#define HDAPS_PORT_TEMP1 0x1616 /* device temperature, in Celsius */ #define HDAPS_PORT_YVAR 0x1617 /* y-axis variance (what is this?) */ #define HDAPS_PORT_XVAR 0x1619 /* x-axis variance (what is this?) */ #define HDAPS_PORT_TEMP2 0x161b /* device temperature (again?) */ -- cgit v1.2.3 From 3dc26c600cbae8e8e7566136148aef5667e8342b Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 4 Jun 2006 20:13:01 +0200 Subject: [PATCH] hwmon: Drop some maintainers entries I no more wish to be listed as the maintainer for the smsc47m1 and w83l785ts drivers. I have no test device, and people will fallback to me as the general hardware monitoring maintainer anyway. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index d10e629db56..58d181d050c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2528,12 +2528,6 @@ M: thomas@winischhofer.net W: http://www.winischhofer.at/linuxsisusbvga.shtml S: Maintained -SMSC47M1 HARDWARE MONITOR DRIVER -P: Jean Delvare -M: khali@linux-fr.org -L: lm-sensors@lm-sensors.org -S: Odd Fixes - SMB FILESYSTEM P: Urban Widmark M: urban@teststation.com @@ -3146,12 +3140,6 @@ L: wbsd-devel@list.drzeus.cx W: http://projects.drzeus.cx/wbsd S: Maintained -W83L785TS HARDWARE MONITOR DRIVER -P: Jean Delvare -M: khali@linux-fr.org -L: lm-sensors@lm-sensors.org -S: Odd Fixes - WATCHDOG DEVICE DRIVERS P: Wim Van Sebroeck M: wim@iguana.be -- cgit v1.2.3 From 53e2761bb2e4ed58913c266ad13e8c10692aec1e Mon Sep 17 00:00:00 2001 From: Yuan Mu Date: Sun, 4 Jun 2006 20:18:05 +0200 Subject: [PATCH] w83792d: Fix setting the PWM value W83792D use pwm register low 4 bits to store PWM/DC value, bit 7 is used to store fan PWM/DC mode. The store_pwm function did not convert the pwm input correctly, so it may change the fan mode when new value is set. This fix the problem. Change the "index" value of pwm*_mode and pwm* SENSOR_ATTR to simplify code. Signed-off-by: Yuan Mu Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/w83792d.c | 56 +++++++++++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c index 958602e2841..6cdef18b1b2 100644 --- a/drivers/hwmon/w83792d.c +++ b/drivers/hwmon/w83792d.c @@ -250,8 +250,6 @@ FAN_TO_REG(long rpm, int div) : (val)) / 1000, 0, 0xff)) #define TEMP_ADD_TO_REG_LOW(val) ((val%1000) ? 0x80 : 0x00) -#define PWM_FROM_REG(val) (val) -#define PWM_TO_REG(val) (SENSORS_LIMIT((val),0,255)) #define DIV_FROM_REG(val) (1 << (val)) static inline u8 @@ -291,7 +289,6 @@ struct w83792d_data { u8 pwm[7]; /* We only consider the first 3 set of pwm, although 792 chip has 7 set of pwm. */ u8 pwmenable[3]; - u8 pwm_mode[7]; /* indicates PWM or DC mode: 1->PWM; 0->DC */ u32 alarms; /* realtime status register encoding,combined */ u8 chassis; /* Chassis status */ u8 chassis_clear; /* CLR_CHS, clear chassis intrusion detection */ @@ -627,7 +624,7 @@ show_pwm(struct device *dev, struct device_attribute *attr, struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; struct w83792d_data *data = w83792d_update_device(dev); - return sprintf(buf, "%ld\n", (long) PWM_FROM_REG(data->pwm[nr-1])); + return sprintf(buf, "%d\n", (data->pwm[nr] & 0x0f) << 4); } static ssize_t @@ -659,14 +656,16 @@ store_pwm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index - 1; + int nr = sensor_attr->index; struct i2c_client *client = to_i2c_client(dev); struct w83792d_data *data = i2c_get_clientdata(client); - u32 val; + u8 val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 0, 255) >> 4; - val = simple_strtoul(buf, NULL, 10); - data->pwm[nr] = PWM_TO_REG(val); + mutex_lock(&data->update_lock); + val |= w83792d_read_value(client, W83792D_REG_PWM[nr]) & 0xf0; + data->pwm[nr] = val; w83792d_write_value(client, W83792D_REG_PWM[nr], data->pwm[nr]); + mutex_unlock(&data->update_lock); return count; } @@ -707,9 +706,9 @@ store_pwmenable(struct device *dev, struct device_attribute *attr, } static struct sensor_device_attribute sda_pwm[] = { - SENSOR_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1), - SENSOR_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2), - SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 3), + SENSOR_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0), + SENSOR_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1), + SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2), }; static struct sensor_device_attribute sda_pwm_enable[] = { SENSOR_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, @@ -728,7 +727,7 @@ show_pwm_mode(struct device *dev, struct device_attribute *attr, struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; struct w83792d_data *data = w83792d_update_device(dev); - return sprintf(buf, "%d\n", data->pwm_mode[nr-1]); + return sprintf(buf, "%d\n", data->pwm[nr] >> 7); } static ssize_t @@ -736,29 +735,35 @@ store_pwm_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index - 1; + int nr = sensor_attr->index; struct i2c_client *client = to_i2c_client(dev); struct w83792d_data *data = i2c_get_clientdata(client); u32 val; - u8 pwm_mode_mask = 0; val = simple_strtoul(buf, NULL, 10); - data->pwm_mode[nr] = SENSORS_LIMIT(val, 0, 1); - pwm_mode_mask = w83792d_read_value(client, - W83792D_REG_PWM[nr]) & 0x7f; - w83792d_write_value(client, W83792D_REG_PWM[nr], - ((data->pwm_mode[nr]) << 7) | pwm_mode_mask); + if (val != 0 && val != 1) + return -EINVAL; + + mutex_lock(&data->update_lock); + data->pwm[nr] = w83792d_read_value(client, W83792D_REG_PWM[nr]); + if (val) { /* PWM mode */ + data->pwm[nr] |= 0x80; + } else { /* DC mode */ + data->pwm[nr] &= 0x7f; + } + w83792d_write_value(client, W83792D_REG_PWM[nr], data->pwm[nr]); + mutex_unlock(&data->update_lock); return count; } static struct sensor_device_attribute sda_pwm_mode[] = { SENSOR_ATTR(pwm1_mode, S_IWUSR | S_IRUGO, - show_pwm_mode, store_pwm_mode, 1), + show_pwm_mode, store_pwm_mode, 0), SENSOR_ATTR(pwm2_mode, S_IWUSR | S_IRUGO, - show_pwm_mode, store_pwm_mode, 2), + show_pwm_mode, store_pwm_mode, 1), SENSOR_ATTR(pwm3_mode, S_IWUSR | S_IRUGO, - show_pwm_mode, store_pwm_mode, 3), + show_pwm_mode, store_pwm_mode, 2), }; @@ -1373,7 +1378,7 @@ static struct w83792d_data *w83792d_update_device(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct w83792d_data *data = i2c_get_clientdata(client); int i, j; - u8 reg_array_tmp[4], pwm_array_tmp[7], reg_tmp; + u8 reg_array_tmp[4], reg_tmp; mutex_lock(&data->update_lock); @@ -1402,10 +1407,8 @@ static struct w83792d_data *w83792d_update_device(struct device *dev) data->fan_min[i] = w83792d_read_value(client, W83792D_REG_FAN_MIN[i]); /* Update the PWM/DC Value and PWM/DC flag */ - pwm_array_tmp[i] = w83792d_read_value(client, + data->pwm[i] = w83792d_read_value(client, W83792D_REG_PWM[i]); - data->pwm[i] = pwm_array_tmp[i] & 0x0f; - data->pwm_mode[i] = pwm_array_tmp[i] >> 7; } reg_tmp = w83792d_read_value(client, W83792D_REG_FAN_CFG); @@ -1513,7 +1516,6 @@ static void w83792d_print_debug(struct w83792d_data *data, struct device *dev) dev_dbg(dev, "fan[%d] is: 0x%x\n", i, data->fan[i]); dev_dbg(dev, "fan[%d] min is: 0x%x\n", i, data->fan_min[i]); dev_dbg(dev, "pwm[%d] is: 0x%x\n", i, data->pwm[i]); - dev_dbg(dev, "pwm_mode[%d] is: 0x%x\n", i, data->pwm_mode[i]); } dev_dbg(dev, "3 set of Temperatures: =====>\n"); for (i=0; i<3; i++) { -- cgit v1.2.3 From bed730821b74be4c7d135098842219473f7c8f2c Mon Sep 17 00:00:00 2001 From: Yuan Mu Date: Sun, 4 Jun 2006 20:18:45 +0200 Subject: [PATCH] w83792d: Add missing data access locks Add missing data lock in w83792d driver to avoid unexpected data change. Signed-off-by: Yuan Mu Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/w83792d.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c index 6cdef18b1b2..4ef884c216e 100644 --- a/drivers/hwmon/w83792d.c +++ b/drivers/hwmon/w83792d.c @@ -372,8 +372,10 @@ static ssize_t store_in_##reg (struct device *dev, \ u32 val; \ \ val = simple_strtoul(buf, NULL, 10); \ + mutex_lock(&data->update_lock); \ data->in_##reg[nr] = SENSORS_LIMIT(IN_TO_REG(nr, val)/4, 0, 255); \ w83792d_write_value(client, W83792D_REG_IN_##REG[nr], data->in_##reg[nr]); \ + mutex_unlock(&data->update_lock); \ \ return count; \ } @@ -440,9 +442,11 @@ store_fan_min(struct device *dev, struct device_attribute *attr, u32 val; val = simple_strtoul(buf, NULL, 10); + mutex_lock(&data->update_lock); data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); w83792d_write_value(client, W83792D_REG_FAN_MIN[nr], data->fan_min[nr]); + mutex_unlock(&data->update_lock); return count; } @@ -475,6 +479,7 @@ store_fan_div(struct device *dev, struct device_attribute *attr, u8 tmp_fan_div; /* Save fan_min */ + mutex_lock(&data->update_lock); min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])); @@ -490,6 +495,7 @@ store_fan_div(struct device *dev, struct device_attribute *attr, /* Restore fan_min */ data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); w83792d_write_value(client, W83792D_REG_FAN_MIN[nr], data->fan_min[nr]); + mutex_unlock(&data->update_lock); return count; } @@ -544,10 +550,11 @@ static ssize_t store_temp1(struct device *dev, struct device_attribute *attr, s32 val; val = simple_strtol(buf, NULL, 10); - + mutex_lock(&data->update_lock); data->temp1[nr] = TEMP1_TO_REG(val); w83792d_write_value(client, W83792D_REG_TEMP1[nr], data->temp1[nr]); + mutex_unlock(&data->update_lock); return count; } @@ -577,13 +584,14 @@ static ssize_t store_temp23(struct device *dev, struct device_attribute *attr, s32 val; val = simple_strtol(buf, NULL, 10); - + mutex_lock(&data->update_lock); data->temp_add[nr][index] = TEMP_ADD_TO_REG_HIGH(val); data->temp_add[nr][index+1] = TEMP_ADD_TO_REG_LOW(val); w83792d_write_value(client, W83792D_REG_TEMP_ADD[nr][index], data->temp_add[nr][index]); w83792d_write_value(client, W83792D_REG_TEMP_ADD[nr][index+1], data->temp_add[nr][index+1]); + mutex_unlock(&data->update_lock); return count; } @@ -682,6 +690,10 @@ store_pwmenable(struct device *dev, struct device_attribute *attr, u8 fan_cfg_tmp, cfg1_tmp, cfg2_tmp, cfg3_tmp, cfg4_tmp; val = simple_strtoul(buf, NULL, 10); + if (val < 1 || val > 3) + return -EINVAL; + + mutex_lock(&data->update_lock); switch (val) { case 1: data->pwmenable[nr] = 0; /* manual mode */ @@ -692,8 +704,6 @@ store_pwmenable(struct device *dev, struct device_attribute *attr, case 3: data->pwmenable[nr] = 1; /* thermal cruise/Smart Fan I */ break; - default: - return -EINVAL; } cfg1_tmp = data->pwmenable[0]; cfg2_tmp = (data->pwmenable[1]) << 2; @@ -701,6 +711,7 @@ store_pwmenable(struct device *dev, struct device_attribute *attr, cfg4_tmp = w83792d_read_value(client,W83792D_REG_FAN_CFG) & 0xc0; fan_cfg_tmp = ((cfg4_tmp | cfg3_tmp) | cfg2_tmp) | cfg1_tmp; w83792d_write_value(client, W83792D_REG_FAN_CFG, fan_cfg_tmp); + mutex_unlock(&data->update_lock); return count; } @@ -794,12 +805,13 @@ store_chassis_clear(struct device *dev, struct device_attribute *attr, u8 temp1 = 0, temp2 = 0; val = simple_strtoul(buf, NULL, 10); - + mutex_lock(&data->update_lock); data->chassis_clear = SENSORS_LIMIT(val, 0 ,1); temp1 = ((data->chassis_clear) << 7) & 0x80; temp2 = w83792d_read_value(client, W83792D_REG_CHASSIS_CLR) & 0x7f; w83792d_write_value(client, W83792D_REG_CHASSIS_CLR, temp1 | temp2); + mutex_unlock(&data->update_lock); return count; } @@ -832,10 +844,12 @@ store_thermal_cruise(struct device *dev, struct device_attribute *attr, val = simple_strtoul(buf, NULL, 10); target_tmp = val; target_tmp = target_tmp & 0x7f; + mutex_lock(&data->update_lock); target_mask = w83792d_read_value(client, W83792D_REG_THERMAL[nr]) & 0x80; data->thermal_cruise[nr] = SENSORS_LIMIT(target_tmp, 0, 255); w83792d_write_value(client, W83792D_REG_THERMAL[nr], (data->thermal_cruise[nr]) | target_mask); + mutex_unlock(&data->update_lock); return count; } @@ -872,6 +886,7 @@ store_tolerance(struct device *dev, struct device_attribute *attr, u8 tol_tmp, tol_mask; val = simple_strtoul(buf, NULL, 10); + mutex_lock(&data->update_lock); tol_mask = w83792d_read_value(client, W83792D_REG_TOLERANCE[nr]) & ((nr == 1) ? 0x0f : 0xf0); tol_tmp = SENSORS_LIMIT(val, 0, 15); @@ -882,6 +897,7 @@ store_tolerance(struct device *dev, struct device_attribute *attr, } w83792d_write_value(client, W83792D_REG_TOLERANCE[nr], tol_mask | tol_tmp); + mutex_unlock(&data->update_lock); return count; } @@ -920,11 +936,13 @@ store_sf2_point(struct device *dev, struct device_attribute *attr, u8 mask_tmp = 0; val = simple_strtoul(buf, NULL, 10); + mutex_lock(&data->update_lock); data->sf2_points[index][nr] = SENSORS_LIMIT(val, 0, 127); mask_tmp = w83792d_read_value(client, W83792D_REG_POINTS[index][nr]) & 0x80; w83792d_write_value(client, W83792D_REG_POINTS[index][nr], mask_tmp|data->sf2_points[index][nr]); + mutex_unlock(&data->update_lock); return count; } @@ -984,6 +1002,7 @@ store_sf2_level(struct device *dev, struct device_attribute *attr, u8 mask_tmp=0, level_tmp=0; val = simple_strtoul(buf, NULL, 10); + mutex_lock(&data->update_lock); data->sf2_levels[index][nr] = SENSORS_LIMIT((val * 15) / 100, 0, 15); mask_tmp = w83792d_read_value(client, W83792D_REG_LEVELS[index][nr]) & ((nr==3) ? 0xf0 : 0x0f); @@ -993,6 +1012,7 @@ store_sf2_level(struct device *dev, struct device_attribute *attr, level_tmp = data->sf2_levels[index][nr] << 4; } w83792d_write_value(client, W83792D_REG_LEVELS[index][nr], level_tmp | mask_tmp); + mutex_unlock(&data->update_lock); return count; } -- cgit v1.2.3 From f2b84bbcebfdbe4855bab532909eef6621999f9f Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 4 Jun 2006 20:22:24 +0200 Subject: [PATCH] abituguru: New hardware monitoring driver New hardware monitoring driver for the Abit uGuru Signed-off-by: Hans de Goede Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- Documentation/hwmon/abituguru | 59 ++ Documentation/hwmon/abituguru-datasheet | 312 +++++++ MAINTAINERS | 6 + drivers/hwmon/Kconfig | 12 + drivers/hwmon/Makefile | 1 + drivers/hwmon/abituguru.c | 1391 +++++++++++++++++++++++++++++++ 6 files changed, 1781 insertions(+) create mode 100644 Documentation/hwmon/abituguru create mode 100644 Documentation/hwmon/abituguru-datasheet create mode 100644 drivers/hwmon/abituguru.c diff --git a/Documentation/hwmon/abituguru b/Documentation/hwmon/abituguru new file mode 100644 index 00000000000..69cdb527d58 --- /dev/null +++ b/Documentation/hwmon/abituguru @@ -0,0 +1,59 @@ +Kernel driver abituguru +======================= + +Supported chips: + * Abit uGuru (Hardware Monitor part only) + Prefix: 'abituguru' + Addresses scanned: ISA 0x0E0 + Datasheet: Not available, this driver is based on reverse engineering. + A "Datasheet" has been written based on the reverse engineering it + should be available in the same dir as this file under the name + abituguru-datasheet. + +Authors: + Hans de Goede , + (Initial reverse engineering done by Olle Sandberg + ) + + +Module Parameters +----------------- + +* force: bool Force detection. Note this parameter only causes the + detection to be skipped, if the uGuru can't be read + the module initialization (insmod) will still fail. +* fan_sensors: int Tell the driver how many fan speed sensors there are + on your motherboard. Default: 0 (autodetect). +* pwms: int Tell the driver how many fan speed controls (fan + pwms) your motherboard has. Default: 0 (autodetect). +* verbose: int How verbose should the driver be? (0-3): + 0 normal output + 1 + verbose error reporting + 2 + sensors type probing info\n" + 3 + retryable error reporting + Default: 2 (the driver is still in the testing phase) + +Notice if you need any of the first three options above please insmod the +driver with verbose set to 3 and mail me the output of: +dmesg | grep abituguru + + +Description +----------- + +This driver supports the hardware monitoring features of the Abit uGuru chip +found on Abit uGuru featuring motherboards (most modern Abit motherboards). + +The uGuru chip in reality is a Winbond W83L950D in disguise (despite Abit +claiming it is "a new microprocessor designed by the ABIT Engineers"). +Unfortunatly this doesn't help since the W83L950D is a generic +microcontroller with a custom Abit application running on it. + +Despite Abit not releasing any information regarding the uGuru, Olle +Sandberg has managed to reverse engineer the sensor part +of the uGuru. Without his work this driver would not have been possible. + +Known Issues +------------ + +The voltage and frequency control parts of the Abit uGuru are not supported. diff --git a/Documentation/hwmon/abituguru-datasheet b/Documentation/hwmon/abituguru-datasheet new file mode 100644 index 00000000000..aef5a9b3684 --- /dev/null +++ b/Documentation/hwmon/abituguru-datasheet @@ -0,0 +1,312 @@ +uGuru datasheet +=============== + +First of all, what I know about uGuru is no fact based on any help, hints or +datasheet from Abit. The data I have got on uGuru have I assembled through +my weak knowledge in "backwards engineering". +And just for the record, you may have noticed uGuru isn't a chip developed by +Abit, as they claim it to be. It's realy just an microprocessor (uC) created by +Winbond (W83L950D). And no, reading the manual for this specific uC or +mailing Windbond for help won't give any usefull data about uGuru, as it is +the program inside the uC that is responding to calls. + +Olle Sandberg , 2005-05-25 + + +Original version by Olle Sandberg who did the heavy lifting of the initial +reverse engineering. This version has been almost fully rewritten for clarity +and extended with write support and info on more databanks, the write support +is once again reverse engineered by Olle the additional databanks have been +reverse engineered by me. I would like to express my thanks to Olle, this +document and the Linux driver could not have been written without his efforts. + +Note: because of the lack of specs only the sensors part of the uGuru is +described here and not the CPU / RAM / etc voltage & frequency control. + +Hans de Goede , 28-01-2006 + + +Detection +========= + +As far as known the uGuru is always placed at and using the (ISA) I/O-ports +0xE0 and 0xE4, so we don't have to scan any port-range, just check what the two +ports are holding for detection. We will refer to 0xE0 as CMD (command-port) +and 0xE4 as DATA because Abit refers to them with these names. + +If DATA holds 0x00 or 0x08 and CMD holds 0x00 or 0xAC an uGuru could be +present. We have to check for two different values at data-port, because +after a reboot uGuru will hold 0x00 here, but if the driver is removed and +later on attached again data-port will hold 0x08, more about this later. + +After wider testing of the Linux kernel driver some variants of the uGuru have +turned up which will hold 0x00 instead of 0xAC at the CMD port, thus we also +have to test CMD for two different values. On these uGuru's DATA will initally +hold 0x09 and will only hold 0x08 after reading CMD first, so CMD must be read +first! + +To be really sure an uGuru is present a test read of one or more register +sets should be done. + + +Reading / Writing +================= + +Addressing +---------- + +The uGuru has a number of different addressing levels. The first addressing +level we will call banks. A bank holds data for one or more sensors. The data +in a bank for a sensor is one or more bytes large. + +The number of bytes is fixed for a given bank, you should always read or write +that many bytes, reading / writing more will fail, the results when writing +less then the number of bytes for a given bank are undetermined. + +See below for all known bank addresses, numbers of sensors in that bank, +number of bytes data per sensor and contents/meaning of those bytes. + +Although both this document and the kernel driver have kept the sensor +terminoligy for the addressing within a bank this is not 100% correct, in +bank 0x24 for example the addressing within the bank selects a PWM output not +a sensor. + +Notice that some banks have both a read and a write address this is how the +uGuru determines if a read from or a write to the bank is taking place, thus +when reading you should always use the read address and when writing the +write address. The write address is always one (1) more then the read address. + + +uGuru ready +----------- + +Before you can read from or write to the uGuru you must first put the uGuru +in "ready" mode. + +To put the uGuru in ready mode first write 0x00 to DATA and then wait for DATA +to hold 0x09, DATA should read 0x09 within 250 read cycles. + +Next CMD _must_ be read and should hold 0xAC, usually CMD will hold 0xAC the +first read but sometimes it takes a while before CMD holds 0xAC and thus it +has to be read a number of times (max 50). + +After reading CMD, DATA should hold 0x08 which means that the uGuru is ready +for input. As above DATA will usually hold 0x08 the first read but not always. +This step can be skipped, but it is undetermined what happens if the uGuru has +not yet reported 0x08 at DATA and you proceed with writing a bank address. + + +Sending bank and sensor addresses to the uGuru +---------------------------------------------- + +First the uGuru must be in "ready" mode as described above, DATA should hold +0x08 indicating that the uGuru wants input, in this case the bank address. + +Next write the bank address to DATA. After the bank address has been written +wait for to DATA to hold 0x08 again indicating that it wants / is ready for +more input (max 250 reads). + +Once DATA holds 0x08 again write the sensor address to CMD. + + +Reading +------- + +First send the bank and sensor addresses as described above. +Then for each byte of data you want to read wait for DATA to hold 0x01 +which indicates that the uGuru is ready to be read (max 250 reads) and once +DATA holds 0x01 read the byte from CMD. + +Once all bytes have been read data will hold 0x09, but there is no reason to +test for this. Notice that the number of bytes is bank address dependent see +above and below. + +After completing a successfull read it is advised to put the uGuru back in +ready mode, so that it is ready for the next read / write cycle. This way +if your program / driver is unloaded and later loaded again the detection +algorithm described above will still work. + + + +Writing +------- + +First send the bank and sensor addresses as described above. +Then for each byte of data you want to write wait for DATA to hold 0x00 +which indicates that the uGuru is ready to be written (max 250 reads) and +once DATA holds 0x00 write the byte to CMD. + +Once all bytes have been written wait for DATA to hold 0x01 (max 250 reads) +don't ask why this is the way it is. + +Once DATA holds 0x01 read CMD it should hold 0xAC now. + +After completing a successfull write it is advised to put the uGuru back in +ready mode, so that it is ready for the next read / write cycle. This way +if your program / driver is unloaded and later loaded again the detection +algorithm described above will still work. + + +Gotchas +------- + +After wider testing of the Linux kernel driver some variants of the uGuru have +turned up which do not hold 0x08 at DATA within 250 reads after writing the +bank address. With these versions this happens quite frequent, using larger +timeouts doesn't help, they just go offline for a second or 2, doing some +internal callibration or whatever. Your code should be prepared to handle +this and in case of no response in this specific case just goto sleep for a +while and then retry. + + +Address Map +=========== + +Bank 0x20 Alarms (R) +-------------------- +This bank contains 0 sensors, iow the sensor address is ignored (but must be +written) just use 0. Bank 0x20 contains 3 bytes: + +Byte 0: +This byte holds the alarm flags for sensor 0-7 of Sensor Bank1, with bit 0 +corresponding to sensor 0, 1 to 1, etc. + +Byte 1: +This byte holds the alarm flags for sensor 8-15 of Sensor Bank1, with bit 0 +corresponding to sensor 8, 1 to 9, etc. + +Byte 2: +This byte holds the alarm flags for sensor 0-5 of Sensor Bank2, with bit 0 +corresponding to sensor 0, 1 to 1, etc. + + +Bank 0x21 Sensor Bank1 Values / Readings (R) +-------------------------------------------- +This bank contains 16 sensors, for each sensor it contains 1 byte. +So far the following sensors are known to be available on all motherboards: +Sensor 0 CPU temp +Sensor 1 SYS temp +Sensor 3 CPU core volt +Sensor 4 DDR volt +Sensor 10 DDR Vtt volt +Sensor 15 PWM temp + +Byte 0: +This byte holds the reading from the sensor. Sensors in Bank1 can be both +volt and temp sensors, this is motherboard specific. The uGuru however does +seem to know (be programmed with) what kindoff sensor is attached see Sensor +Bank1 Settings description. + +Volt sensors use a linear scale, a reading 0 corresponds with 0 volt and a +reading of 255 with 3494 mV. The sensors for higher voltages however are +connected through a division circuit. The currently known division circuits +in use result in ranges of: 0-4361mV, 0-6248mV or 0-14510mV. 3.3 volt sources +use the 0-4361mV range, 5 volt the 0-6248mV and 12 volt the 0-14510mV . + +Temp sensors also use a linear scale, a reading of 0 corresponds with 0 degree +Celsius and a reading of 255 with a reading of 255 degrees Celsius. + + +Bank 0x22 Sensor Bank1 Settings (R) +Bank 0x23 Sensor Bank1 Settings (W) +----------------------------------- + +This bank contains 16 sensors, for each sensor it contains 3 bytes. Each +set of 3 bytes contains the settings for the sensor with the same sensor +address in Bank 0x21 . + +Byte 0: +Alarm behaviour for the selected sensor. A 1 enables the described behaviour. +Bit 0: Give an alarm if measured temp is over the warning threshold (RW) * +Bit 1: Give an alarm if measured volt is over the max threshold (RW) ** +Bit 2: Give an alarm if measured volt is under the min threshold (RW) ** +Bit 3: Beep if alarm (RW) +Bit 4: 1 if alarm cause measured temp is over the warning threshold (R) +Bit 5: 1 if alarm cause measured volt is over the max threshold (R) +Bit 6: 1 if alarm cause measured volt is under the min threshold (R) +Bit 7: Volt sensor: Shutdown if alarm persist for more then 4 seconds (RW) + Temp sensor: Shutdown if temp is over the shutdown threshold (RW) + +* This bit is only honored/used by the uGuru if a temp sensor is connected +** This bit is only honored/used by the uGuru if a volt sensor is connected +Note with some trickery this can be used to find out what kinda sensor is +detected see the Linux kernel driver for an example with many comments on +how todo this. + +Byte 1: +Temp sensor: warning threshold (scale as bank 0x21) +Volt sensor: min threshold (scale as bank 0x21) + +Byte 2: +Temp sensor: shutdown threshold (scale as bank 0x21) +Volt sensor: max threshold (scale as bank 0x21) + + +Bank 0x24 PWM outputs for FAN's (R) +Bank 0x25 PWM outputs for FAN's (W) +----------------------------------- + +This bank contains 3 "sensors", for each sensor it contains 5 bytes. +Sensor 0 usually controls the CPU fan +Sensor 1 usually controls the NB (or chipset for single chip) fan +Sensor 2 usually controls the System fan + +Byte 0: +Flag 0x80 to enable control, Fan runs at 100% when disabled. +low nibble (temp)sensor address at bank 0x21 used for control. + +Byte 1: +0-255 = 0-12v (linear), specify voltage at which fan will rotate when under +low threshold temp (specified in byte 3) + +Byte 2: +0-255 = 0-12v (linear), specify voltage at which fan will rotate when above +high threshold temp (specified in byte 4) + +Byte 3: +Low threshold temp (scale as bank 0x21) + +byte 4: +High threshold temp (scale as bank 0x21) + + +Bank 0x26 Sensors Bank2 Values / Readings (R) +--------------------------------------------- + +This bank contains 6 sensors (AFAIK), for each sensor it contains 1 byte. +So far the following sensors are known to be available on all motherboards: +Sensor 0: CPU fan speed +Sensor 1: NB (or chipset for single chip) fan speed +Sensor 2: SYS fan speed + +Byte 0: +This byte holds the reading from the sensor. 0-255 = 0-15300 (linear) + + +Bank 0x27 Sensors Bank2 Settings (R) +Bank 0x28 Sensors Bank2 Settings (W) +------------------------------------ + +This bank contains 6 sensors (AFAIK), for each sensor it contains 2 bytes. + +Byte 0: +Alarm behaviour for the selected sensor. A 1 enables the described behaviour. +Bit 0: Give an alarm if measured rpm is under the min threshold (RW) +Bit 3: Beep if alarm (RW) +Bit 7: Shutdown if alarm persist for more then 4 seconds (RW) + +Byte 1: +min threshold (scale as bank 0x26) + + +Warning for the adventerous +=========================== + +A word of caution to those who want to experiment and see if they can figure +the voltage / clock programming out, I tried reading and only reading banks +0-0x30 with the reading code used for the sensor banks (0x20-0x28) and this +resulted in a _permanent_ reprogramming of the voltages, luckily I had the +sensors part configured so that it would shutdown my system on any out of spec +voltages which proprably safed my computer (after a reboot I managed to +immediatly enter the bios and reload the defaults). This probably means that +the read/write cycle for the non sensor part is different from the sensor part. diff --git a/MAINTAINERS b/MAINTAINERS index 58d181d050c..7e3a38eeccb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -181,6 +181,12 @@ M: bcrl@kvack.org L: linux-aio@kvack.org S: Supported +ABIT UGURU HARDWARE MONITOR DRIVER +P: Hans de Goede +M: j.w.r.degoede@hhs.nl +L: lm-sensors@lm-sensors.org +S: Maintained + ACENIC DRIVER P: Jes Sorensen M: jes@trained-monkey.org diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 164760df123..6fb93d63bd8 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -27,6 +27,18 @@ config HWMON_VID tristate default n +config SENSORS_ABITUGURU + tristate "Abit uGuru" + depends on HWMON && EXPERIMENTAL + help + If you say yes here you get support for the Abit uGuru chips + sensor part. The voltage and frequency control parts of the Abit + uGuru are not supported. The Abit uGuru chip can be found on Abit + uGuru featuring motherboards (most modern Abit motherboards). + + This driver can also be built as a module. If so, the module + will be called abituguru. + config SENSORS_ADM1021 tristate "Analog Devices ADM1021 and compatibles" depends on HWMON && I2C diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index db72b1415e7..5092999deb7 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_SENSORS_W83792D) += w83792d.o obj-$(CONFIG_SENSORS_W83781D) += w83781d.o obj-$(CONFIG_SENSORS_W83791D) += w83791d.o +obj-$(CONFIG_SENSORS_ABITUGURU) += abituguru.o obj-$(CONFIG_SENSORS_ADM1021) += adm1021.o obj-$(CONFIG_SENSORS_ADM1025) += adm1025.o obj-$(CONFIG_SENSORS_ADM1026) += adm1026.o diff --git a/drivers/hwmon/abituguru.c b/drivers/hwmon/abituguru.c new file mode 100644 index 00000000000..bf2cb0aa69b --- /dev/null +++ b/drivers/hwmon/abituguru.c @@ -0,0 +1,1391 @@ +/* + abituguru.c Copyright (c) 2005-2006 Hans de Goede + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +/* + This driver supports the sensor part of the custom Abit uGuru chip found + on Abit uGuru motherboards. Note: because of lack of specs the CPU / RAM / + etc voltage & frequency control is not supported! +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Banks */ +#define ABIT_UGURU_ALARM_BANK 0x20 /* 1x 3 bytes */ +#define ABIT_UGURU_SENSOR_BANK1 0x21 /* 16x volt and temp */ +#define ABIT_UGURU_FAN_PWM 0x24 /* 3x 5 bytes */ +#define ABIT_UGURU_SENSOR_BANK2 0x26 /* fans */ +/* max nr of sensors in bank2, currently mb's with max 6 fans are known */ +#define ABIT_UGURU_MAX_BANK2_SENSORS 6 +/* max nr of pwm outputs, currently mb's with max 5 pwm outputs are known */ +#define ABIT_UGURU_MAX_PWMS 5 +/* uGuru sensor bank 1 flags */ /* Alarm if: */ +#define ABIT_UGURU_TEMP_HIGH_ALARM_ENABLE 0x01 /* temp over warn */ +#define ABIT_UGURU_VOLT_HIGH_ALARM_ENABLE 0x02 /* volt over max */ +#define ABIT_UGURU_VOLT_LOW_ALARM_ENABLE 0x04 /* volt under min */ +#define ABIT_UGURU_TEMP_HIGH_ALARM_FLAG 0x10 /* temp is over warn */ +#define ABIT_UGURU_VOLT_HIGH_ALARM_FLAG 0x20 /* volt is over max */ +#define ABIT_UGURU_VOLT_LOW_ALARM_FLAG 0x40 /* volt is under min */ +/* uGuru sensor bank 2 flags */ /* Alarm if: */ +#define ABIT_UGURU_FAN_LOW_ALARM_ENABLE 0x01 /* fan under min */ +/* uGuru sensor bank common flags */ +#define ABIT_UGURU_BEEP_ENABLE 0x08 /* beep if alarm */ +#define ABIT_UGURU_SHUTDOWN_ENABLE 0x80 /* shutdown if alarm */ +/* uGuru fan PWM (speed control) flags */ +#define ABIT_UGURU_FAN_PWM_ENABLE 0x80 /* enable speed control */ +/* Values used for conversion */ +#define ABIT_UGURU_FAN_MAX 15300 /* RPM */ +/* Bank1 sensor types */ +#define ABIT_UGURU_IN_SENSOR 0 +#define ABIT_UGURU_TEMP_SENSOR 1 +#define ABIT_UGURU_NC 2 +/* Timeouts / Retries, if these turn out to need a lot of fiddling we could + convert them to params. */ +/* 250 was determined by trial and error, 200 works most of the time, but not + always. I assume this is cpu-speed independent, since the ISA-bus and not + the CPU should be the bottleneck. Note that 250 sometimes is still not + enough (only reported on AN7 mb) this is handled by a higher layer. */ +#define ABIT_UGURU_WAIT_TIMEOUT 250 +/* Normally all expected status in abituguru_ready, are reported after the + first read, but sometimes not and we need to poll, 5 polls was not enough + 50 sofar is. */ +#define ABIT_UGURU_READY_TIMEOUT 50 +/* Maximum 3 retries on timedout reads/writes, delay 200 ms before retrying */ +#define ABIT_UGURU_MAX_RETRIES 3 +#define ABIT_UGURU_RETRY_DELAY (HZ/5) +/* Maximum 2 timeouts in abituguru_update_device, iow 3 in a row is a error */ +#define ABIT_UGURU_MAX_TIMEOUTS 2 + +/* All the variables below are named identical to the oguru and oguru2 programs + reverse engineered by Olle Sandberg, hence the names might not be 100% + logical. I could come up with better names, but I prefer keeping the names + identical so that this driver can be compared with his work more easily. */ +/* Two i/o-ports are used by uGuru */ +#define ABIT_UGURU_BASE 0x00E0 +/* Used to tell uGuru what to read and to read the actual data */ +#define ABIT_UGURU_CMD 0x00 +/* Mostly used to check if uGuru is busy */ +#define ABIT_UGURU_DATA 0x04 +#define ABIT_UGURU_REGION_LENGTH 5 +/* uGuru status' */ +#define ABIT_UGURU_STATUS_WRITE 0x00 /* Ready to be written */ +#define ABIT_UGURU_STATUS_READ 0x01 /* Ready to be read */ +#define ABIT_UGURU_STATUS_INPUT 0x08 /* More input */ +#define ABIT_UGURU_STATUS_READY 0x09 /* Ready to be written */ +/* utility macros */ +#define ABIT_UGURU_NAME "abituguru" +#define ABIT_UGURU_DEBUG(level, format, arg...) \ + if (level <= verbose) \ + printk(KERN_DEBUG ABIT_UGURU_NAME ": " format , ## arg) + +/* Constants */ +/* in (Volt) sensors go up to 3494 mV, temp to 255000 millidegrees Celsius */ +static const int abituguru_bank1_max_value[2] = { 3494, 255000 }; +/* Min / Max allowed values for sensor2 (fan) alarm threshold, these values + correspond to 300-3000 RPM */ +static const u8 abituguru_bank2_min_threshold = 5; +static const u8 abituguru_bank2_max_threshold = 50; +/* Register 0 is a bitfield, 1 and 2 are pwm settings (255 = 100%), 3 and 4 + are temperature trip points. */ +static const int abituguru_pwm_settings_multiplier[5] = { 0, 1, 1, 1000, 1000 }; +/* Min / Max allowed values for pwm_settings. Note: pwm1 (CPU fan) is a + special case the minium allowed pwm% setting for this is 30% (77) on + some MB's this special case is handled in the code! */ +static const u8 abituguru_pwm_min[5] = { 0, 170, 170, 25, 25 }; +static const u8 abituguru_pwm_max[5] = { 0, 255, 255, 75, 75 }; + + +/* Insmod parameters */ +static int force; +module_param(force, bool, 0); +MODULE_PARM_DESC(force, "Set to one to force detection."); +static int fan_sensors; +module_param(fan_sensors, int, 0); +MODULE_PARM_DESC(fan_sensors, "Number of fan sensors on the uGuru " + "(0 = autodetect)"); +static int pwms; +module_param(pwms, int, 0); +MODULE_PARM_DESC(pwms, "Number of PWMs on the uGuru " + "(0 = autodetect)"); + +/* Default verbose is 2, since this driver is still in the testing phase */ +static int verbose = 2; +module_param(verbose, int, 0644); +MODULE_PARM_DESC(verbose, "How verbose should the driver be? (0-3):\n" + " 0 normal output\n" + " 1 + verbose error reporting\n" + " 2 + sensors type probing info\n" + " 3 + retryable error reporting"); + + +/* For the Abit uGuru, we need to keep some data in memory. + The structure is dynamically allocated, at the same time when a new + abituguru device is allocated. */ +struct abituguru_data { + struct class_device *class_dev; /* hwmon registered device */ + struct mutex update_lock; /* protect access to data and uGuru */ + unsigned long last_updated; /* In jiffies */ + unsigned short addr; /* uguru base address */ + char uguru_ready; /* is the uguru in ready state? */ + unsigned char update_timeouts; /* number of update timeouts since last + successful update */ + + /* The sysfs attr and their names are generated automatically, for bank1 + we cannot use a predefined array because we don't know beforehand + of a sensor is a volt or a temp sensor, for bank2 and the pwms its + easier todo things the same way. For in sensors we have 9 (temp 7) + sysfs entries per sensor, for bank2 and pwms 6. */ + struct sensor_device_attribute_2 sysfs_attr[16 * 9 + + ABIT_UGURU_MAX_BANK2_SENSORS * 6 + ABIT_UGURU_MAX_PWMS * 6]; + /* Buffer to store the dynamically generated sysfs names, we need 2120 + bytes for bank1 (worst case scenario of 16 in sensors), 444 bytes + for fan1-6 and 738 bytes for pwm1-6 + some room to spare in case I + miscounted :) */ + char bank1_names[3400]; + + /* Bank 1 data */ + u8 bank1_sensors[2]; /* number of [0] in, [1] temp sensors */ + u8 bank1_address[2][16];/* addresses of [0] in, [1] temp sensors */ + u8 bank1_value[16]; + /* This array holds 16 x 3 entries for all the bank 1 sensor settings + (flags, min, max for voltage / flags, warn, shutdown for temp). */ + u8 bank1_settings[16][3]; + /* Maximum value for each sensor used for scaling in mV/millidegrees + Celsius. */ + int bank1_max_value[16]; + + /* Bank 2 data, ABIT_UGURU_MAX_BANK2_SENSORS entries for bank2 */ + u8 bank2_sensors; /* actual number of bank2 sensors found */ + u8 bank2_value[ABIT_UGURU_MAX_BANK2_SENSORS]; + u8 bank2_settings[ABIT_UGURU_MAX_BANK2_SENSORS][2]; /* flags, min */ + + /* Alarms 2 bytes for bank1, 1 byte for bank2 */ + u8 alarms[3]; + + /* Fan PWM (speed control) 5 bytes per PWM */ + u8 pwms; /* actual number of pwms found */ + u8 pwm_settings[ABIT_UGURU_MAX_PWMS][5]; +}; + +/* wait till the uguru is in the specified state */ +static int abituguru_wait(struct abituguru_data *data, u8 state) +{ + int timeout = ABIT_UGURU_WAIT_TIMEOUT; + + while (inb_p(data->addr + ABIT_UGURU_DATA) != state) { + timeout--; + if (timeout == 0) + return -EBUSY; + } + return 0; +} + +/* Put the uguru in ready for input state */ +static int abituguru_ready(struct abituguru_data *data) +{ + int timeout = ABIT_UGURU_READY_TIMEOUT; + + if (data->uguru_ready) + return 0; + + /* Reset? / Prepare for next read/write cycle */ + outb(0x00, data->addr + ABIT_UGURU_DATA); + + /* Wait till the uguru is ready */ + if (abituguru_wait(data, ABIT_UGURU_STATUS_READY)) { + ABIT_UGURU_DEBUG(1, + "timeout exceeded waiting for ready state\n"); + return -EIO; + } + + /* Cmd port MUST be read now and should contain 0xAC */ + while (inb_p(data->addr + ABIT_UGURU_CMD) != 0xAC) { + timeout--; + if (timeout == 0) { + ABIT_UGURU_DEBUG(1, + "CMD reg does not hold 0xAC after ready command\n"); + return -EIO; + } + } + + /* After this the ABIT_UGURU_DATA port should contain + ABIT_UGURU_STATUS_INPUT */ + timeout = ABIT_UGURU_READY_TIMEOUT; + while (inb_p(data->addr + ABIT_UGURU_DATA) != ABIT_UGURU_STATUS_INPUT) { + timeout--; + if (timeout == 0) { + ABIT_UGURU_DEBUG(1, + "state != more input after ready command\n"); + return -EIO; + } + } + + data->uguru_ready = 1; + return 0; +} + +/* Send the bank and then sensor address to the uGuru for the next read/write + cycle. This function gets called as the first part of a read/write by + abituguru_read and abituguru_write. This function should never be + called by any other function. */ +static int abituguru_send_address(struct abituguru_data *data, + u8 bank_addr, u8 sensor_addr, int retries) +{ + /* assume the caller does error handling itself if it has not requested + any retries, and thus be quiet. */ + int report_errors = retries; + + for (;;) { + /* Make sure the uguru is ready and then send the bank address, + after this the uguru is no longer "ready". */ + if (abituguru_ready(data) != 0) + return -EIO; + outb(bank_addr, data->addr + ABIT_UGURU_DATA); + data->uguru_ready = 0; + + /* Wait till the uguru is ABIT_UGURU_STATUS_INPUT state again + and send the sensor addr */ + if (abituguru_wait(data, ABIT_UGURU_STATUS_INPUT)) { + if (retries) { + ABIT_UGURU_DEBUG(3, "timeout exceeded " + "waiting for more input state, %d " + "tries remaining\n", retries); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(ABIT_UGURU_RETRY_DELAY); + retries--; + continue; + } + if (report_errors) + ABIT_UGURU_DEBUG(1, "timeout exceeded " + "waiting for more input state " + "(bank: %d)\n", (int)bank_addr); + return -EBUSY; + } + outb(sensor_addr, data->addr + ABIT_UGURU_CMD); + return 0; + } +} + +/* Read count bytes from sensor sensor_addr in bank bank_addr and store the + result in buf, retry the send address part of the read retries times. */ +static int abituguru_read(struct abituguru_data *data, + u8 bank_addr, u8 sensor_addr, u8 *buf, int count, int retries) +{ + int i; + + /* Send the address */ + i = abituguru_send_address(data, bank_addr, sensor_addr, retries); + if (i) + return i; + + /* And read the data */ + for (i = 0; i < count; i++) { + if (abituguru_wait(data, ABIT_UGURU_STATUS_READ)) { + ABIT_UGURU_DEBUG(1, "timeout exceeded waiting for " + "read state (bank: %d, sensor: %d)\n", + (int)bank_addr, (int)sensor_addr); + break; + } + buf[i] = inb(data->addr + ABIT_UGURU_CMD); + } + + /* Last put the chip back in ready state */ + abituguru_ready(data); + + return i; +} + +/* Write count bytes from buf to sensor sensor_addr in bank bank_addr, the send + address part of the write is always retried ABIT_UGURU_MAX_RETRIES times. */ +static int abituguru_write(struct abituguru_data *data, + u8 bank_addr, u8 sensor_addr, u8 *buf, int count) +{ + int i; + + /* Send the address */ + i = abituguru_send_address(data, bank_addr, sensor_addr, + ABIT_UGURU_MAX_RETRIES); + if (i) + return i; + + /* And write the data */ + for (i = 0; i < count; i++) { + if (abituguru_wait(data, ABIT_UGURU_STATUS_WRITE)) { + ABIT_UGURU_DEBUG(1, "timeout exceeded waiting for " + "write state (bank: %d, sensor: %d)\n", + (int)bank_addr, (int)sensor_addr); + break; + } + outb(buf[i], data->addr + ABIT_UGURU_CMD); + } + + /* Now we need to wait till the chip is ready to be read again, + don't ask why */ + if (abituguru_wait(data, ABIT_UGURU_STATUS_READ)) { + ABIT_UGURU_DEBUG(1, "timeout exceeded waiting for read state " + "after write (bank: %d, sensor: %d)\n", (int)bank_addr, + (int)sensor_addr); + return -EIO; + } + + /* Cmd port MUST be read now and should contain 0xAC */ + if (inb_p(data->addr + ABIT_UGURU_CMD) != 0xAC) { + ABIT_UGURU_DEBUG(1, "CMD reg does not hold 0xAC after write " + "(bank: %d, sensor: %d)\n", (int)bank_addr, + (int)sensor_addr); + return -EIO; + } + + /* Last put the chip back in ready state */ + abituguru_ready(data); + + return i; +} + +/* Detect sensor type. Temp and Volt sensors are enabled with + different masks and will ignore enable masks not meant for them. + This enables us to test what kind of sensor we're dealing with. + By setting the alarm thresholds so that we will always get an + alarm for sensor type X and then enabling the sensor as sensor type + X, if we then get an alarm it is a sensor of type X. */ +static int __devinit +abituguru_detect_bank1_sensor_type(struct abituguru_data *data, + u8 sensor_addr) +{ + u8 val, buf[3]; + int ret = ABIT_UGURU_NC; + + /* First read the sensor and the current settings */ + if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1, sensor_addr, &val, + 1, ABIT_UGURU_MAX_RETRIES) != 1) + return -EIO; + + /* Test val is sane / usable for sensor type detection. */ + if ((val < 10u) || (val > 240u)) { + printk(KERN_WARNING ABIT_UGURU_NAME + ": bank1-sensor: %d reading (%d) too close to limits, " + "unable to determine sensor type, skipping sensor\n", + (int)sensor_addr, (int)val); + /* assume no sensor is there for sensors for which we can't + determine the sensor type because their reading is too close + to their limits, this usually means no sensor is there. */ + return ABIT_UGURU_NC; + } + + ABIT_UGURU_DEBUG(2, "testing bank1 sensor %d\n", (int)sensor_addr); + /* Volt sensor test, enable volt low alarm, set min value ridicously + high. If its a volt sensor this should always give us an alarm. */ + buf[0] = ABIT_UGURU_VOLT_LOW_ALARM_ENABLE; + buf[1] = 245; + buf[2] = 250; + if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, sensor_addr, + buf, 3) != 3) + return -EIO; + /* Now we need 20 ms to give the uguru time to read the sensors + and raise a voltage alarm */ + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ/50); + /* Check for alarm and check the alarm is a volt low alarm. */ + if (abituguru_read(data, ABIT_UGURU_ALARM_BANK, 0, buf, 3, + ABIT_UGURU_MAX_RETRIES) != 3) + return -EIO; + if (buf[sensor_addr/8] & (0x01 << (sensor_addr % 8))) { + if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1 + 1, + sensor_addr, buf, 3, + ABIT_UGURU_MAX_RETRIES) != 3) + return -EIO; + if (buf[0] & ABIT_UGURU_VOLT_LOW_ALARM_FLAG) { + /* Restore original settings */ + if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, + sensor_addr, + data->bank1_settings[sensor_addr], + 3) != 3) + return -EIO; + ABIT_UGURU_DEBUG(2, " found volt sensor\n"); + return ABIT_UGURU_IN_SENSOR; + } else + ABIT_UGURU_DEBUG(2, " alarm raised during volt " + "sensor test, but volt low flag not set\n"); + } else + ABIT_UGURU_DEBUG(2, " alarm not raised during volt sensor " + "test\n"); + + /* Temp sensor test, enable sensor as a temp sensor, set beep value + ridicously low (but not too low, otherwise uguru ignores it). + If its a temp sensor this should always give us an alarm. */ + buf[0] = ABIT_UGURU_TEMP_HIGH_ALARM_ENABLE; + buf[1] = 5; + buf[2] = 10; + if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, sensor_addr, + buf, 3) != 3) + return -EIO; + /* Now we need 50 ms to give the uguru time to read the sensors + and raise a temp alarm */ + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ/20); + /* Check for alarm and check the alarm is a temp high alarm. */ + if (abituguru_read(data, ABIT_UGURU_ALARM_BANK, 0, buf, 3, + ABIT_UGURU_MAX_RETRIES) != 3) + return -EIO; + if (buf[sensor_addr/8] & (0x01 << (sensor_addr % 8))) { + if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1 + 1, + sensor_addr, buf, 3, + ABIT_UGURU_MAX_RETRIES) != 3) + return -EIO; + if (buf[0] & ABIT_UGURU_TEMP_HIGH_ALARM_FLAG) { + ret = ABIT_UGURU_TEMP_SENSOR; + ABIT_UGURU_DEBUG(2, " found temp sensor\n"); + } else + ABIT_UGURU_DEBUG(2, " alarm raised during temp " + "sensor test, but temp high flag not set\n"); + } else + ABIT_UGURU_DEBUG(2, " alarm not raised during temp sensor " + "test\n"); + + /* Restore original settings */ + if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, sensor_addr, + data->bank1_settings[sensor_addr], 3) != 3) + return -EIO; + + return ret; +} + +/* These functions try to find out how many sensors there are in bank2 and how + many pwms there are. The purpose of this is to make sure that we don't give + the user the possibility to change settings for non-existent sensors / pwm. + The uGuru will happily read / write whatever memory happens to be after the + memory storing the PWM settings when reading/writing to a PWM which is not + there. Notice even if we detect a PWM which doesn't exist we normally won't + write to it, unless the user tries to change the settings. + + Although the uGuru allows reading (settings) from non existing bank2 + sensors, my version of the uGuru does seem to stop writing to them, the + write function above aborts in this case with: + "CMD reg does not hold 0xAC after write" + + Notice these 2 tests are non destructive iow read-only tests, otherwise + they would defeat their purpose. Although for the bank2_sensors detection a + read/write test would be feasible because of the reaction above, I've + however opted to stay on the safe side. */ +static void __devinit +abituguru_detect_no_bank2_sensors(struct abituguru_data *data) +{ + int i; + + if (fan_sensors) { + data->bank2_sensors = fan_sensors; + ABIT_UGURU_DEBUG(2, "assuming %d fan sensors because of " + "\"fan_sensors\" module param\n", + (int)data->bank2_sensors); + return; + } + + ABIT_UGURU_DEBUG(2, "detecting number of fan sensors\n"); + for (i = 0; i < ABIT_UGURU_MAX_BANK2_SENSORS; i++) { + /* 0x89 are the known used bits: + -0x80 enable shutdown + -0x08 enable beep + -0x01 enable alarm + All other bits should be 0, but on some motherboards + 0x40 (bit 6) is also high, at least for fan1 */ + if ((!i && (data->bank2_settings[i][0] & ~0xC9)) || + (i && (data->bank2_settings[i][0] & ~0x89))) { + ABIT_UGURU_DEBUG(2, " bank2 sensor %d does not seem " + "to be a fan sensor: settings[0] = %02X\n", + i, (unsigned int)data->bank2_settings[i][0]); + break; + } + + /* check if the threshold is within the allowed range */ + if (data->bank2_settings[i][1] < + abituguru_bank2_min_threshold) { + ABIT_UGURU_DEBUG(2, " bank2 sensor %d does not seem " + "to be a fan sensor: the threshold (%d) is " + "below the minimum (%d)\n", i, + (int)data->bank2_settings[i][1], + (int)abituguru_bank2_min_threshold); + break; + } + if (data->bank2_settings[i][1] > + abituguru_bank2_max_threshold) { + ABIT_UGURU_DEBUG(2, " bank2 sensor %d does not seem " + "to be a fan sensor: the threshold (%d) is " + "above the maximum (%d)\n", i, + (int)data->bank2_settings[i][1], + (int)abituguru_bank2_max_threshold); + break; + } + } + + data->bank2_sensors = i; + ABIT_UGURU_DEBUG(2, " found: %d fan sensors\n", + (int)data->bank2_sensors); +} + +static void __devinit +abituguru_detect_no_pwms(struct abituguru_data *data) +{ + int i, j; + + if (pwms) { + data->pwms = pwms; + ABIT_UGURU_DEBUG(2, "assuming %d PWM outputs because of " + "\"pwms\" module param\n", (int)data->pwms); + return; + } + + ABIT_UGURU_DEBUG(2, "detecting number of PWM outputs\n"); + for (i = 0; i < ABIT_UGURU_MAX_PWMS; i++) { + /* 0x80 is the enable bit and the low + nibble is which temp sensor to use, + the other bits should be 0 */ + if (data->pwm_settings[i][0] & ~0x8F) { + ABIT_UGURU_DEBUG(2, " pwm channel %d does not seem " + "to be a pwm channel: settings[0] = %02X\n", + i, (unsigned int)data->pwm_settings[i][0]); + break; + } + + /* the low nibble must correspond to one of the temp sensors + we've found */ + for (j = 0; j < data->bank1_sensors[ABIT_UGURU_TEMP_SENSOR]; + j++) { + if (data->bank1_address[ABIT_UGURU_TEMP_SENSOR][j] == + (data->pwm_settings[i][0] & 0x0F)) + break; + } + if (j == data->bank1_sensors[ABIT_UGURU_TEMP_SENSOR]) { + ABIT_UGURU_DEBUG(2, " pwm channel %d does not seem " + "to be a pwm channel: %d is not a valid temp " + "sensor address\n", i, + data->pwm_settings[i][0] & 0x0F); + break; + } + + /* check if all other settings are within the allowed range */ + for (j = 1; j < 5; j++) { + u8 min; + /* special case pwm1 min pwm% */ + if ((i == 0) && ((j == 1) || (j == 2))) + min = 77; + else + min = abituguru_pwm_min[j]; + if (data->pwm_settings[i][j] < min) { + ABIT_UGURU_DEBUG(2, " pwm channel %d does " + "not seem to be a pwm channel: " + "setting %d (%d) is below the minimum " + "value (%d)\n", i, j, + (int)data->pwm_settings[i][j], + (int)min); + goto abituguru_detect_no_pwms_exit; + } + if (data->pwm_settings[i][j] > abituguru_pwm_max[j]) { + ABIT_UGURU_DEBUG(2, " pwm channel %d does " + "not seem to be a pwm channel: " + "setting %d (%d) is above the maximum " + "value (%d)\n", i, j, + (int)data->pwm_settings[i][j], + (int)abituguru_pwm_max[j]); + goto abituguru_detect_no_pwms_exit; + } + } + + /* check that min temp < max temp and min pwm < max pwm */ + if (data->pwm_settings[i][1] >= data->pwm_settings[i][2]) { + ABIT_UGURU_DEBUG(2, " pwm channel %d does not seem " + "to be a pwm channel: min pwm (%d) >= " + "max pwm (%d)\n", i, + (int)data->pwm_settings[i][1], + (int)data->pwm_settings[i][2]); + break; + } + if (data->pwm_settings[i][3] >= data->pwm_settings[i][4]) { + ABIT_UGURU_DEBUG(2, " pwm channel %d does not seem " + "to be a pwm channel: min temp (%d) >= " + "max temp (%d)\n", i, + (int)data->pwm_settings[i][3], + (int)data->pwm_settings[i][4]); + break; + } + } + +abituguru_detect_no_pwms_exit: + data->pwms = i; + ABIT_UGURU_DEBUG(2, " found: %d PWM outputs\n", (int)data->pwms); +} + +/* Following are the sysfs callback functions. These functions expect: + sensor_device_attribute_2->index: sensor address/offset in the bank + sensor_device_attribute_2->nr: register offset, bitmask or NA. */ +static struct abituguru_data *abituguru_update_device(struct device *dev); + +static ssize_t show_bank1_value(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = abituguru_update_device(dev); + if (!data) + return -EIO; + return sprintf(buf, "%d\n", (data->bank1_value[attr->index] * + data->bank1_max_value[attr->index] + 128) / 255); +} + +static ssize_t show_bank1_setting(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = dev_get_drvdata(dev); + return sprintf(buf, "%d\n", + (data->bank1_settings[attr->index][attr->nr] * + data->bank1_max_value[attr->index] + 128) / 255); +} + +static ssize_t show_bank2_value(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = abituguru_update_device(dev); + if (!data) + return -EIO; + return sprintf(buf, "%d\n", (data->bank2_value[attr->index] * + ABIT_UGURU_FAN_MAX + 128) / 255); +} + +static ssize_t show_bank2_setting(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = dev_get_drvdata(dev); + return sprintf(buf, "%d\n", + (data->bank2_settings[attr->index][attr->nr] * + ABIT_UGURU_FAN_MAX + 128) / 255); +} + +static ssize_t store_bank1_setting(struct device *dev, struct device_attribute + *devattr, const char *buf, size_t count) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = dev_get_drvdata(dev); + u8 val = (simple_strtoul(buf, NULL, 10) * 255 + + data->bank1_max_value[attr->index]/2) / + data->bank1_max_value[attr->index]; + ssize_t ret = count; + + mutex_lock(&data->update_lock); + if (data->bank1_settings[attr->index][attr->nr] != val) { + u8 orig_val = data->bank1_settings[attr->index][attr->nr]; + data->bank1_settings[attr->index][attr->nr] = val; + if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, + attr->index, data->bank1_settings[attr->index], + 3) <= attr->nr) { + data->bank1_settings[attr->index][attr->nr] = orig_val; + ret = -EIO; + } + } + mutex_unlock(&data->update_lock); + return ret; +} + +static ssize_t store_bank2_setting(struct device *dev, struct device_attribute + *devattr, const char *buf, size_t count) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = dev_get_drvdata(dev); + u8 val = (simple_strtoul(buf, NULL, 10)*255 + ABIT_UGURU_FAN_MAX/2) / + ABIT_UGURU_FAN_MAX; + ssize_t ret = count; + + /* this check can be done before taking the lock */ + if ((val < abituguru_bank2_min_threshold) || + (val > abituguru_bank2_max_threshold)) + return -EINVAL; + + mutex_lock(&data->update_lock); + if (data->bank2_settings[attr->index][attr->nr] != val) { + u8 orig_val = data->bank2_settings[attr->index][attr->nr]; + data->bank2_settings[attr->index][attr->nr] = val; + if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK2 + 2, + attr->index, data->bank2_settings[attr->index], + 2) <= attr->nr) { + data->bank2_settings[attr->index][attr->nr] = orig_val; + ret = -EIO; + } + } + mutex_unlock(&data->update_lock); + return ret; +} + +static ssize_t show_bank1_alarm(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = abituguru_update_device(dev); + if (!data) + return -EIO; + /* See if the alarm bit for this sensor is set, and if the + alarm matches the type of alarm we're looking for (for volt + it can be either low or high). The type is stored in a few + readonly bits in the settings part of the relevant sensor. + The bitmask of the type is passed to us in attr->nr. */ + if ((data->alarms[attr->index / 8] & (0x01 << (attr->index % 8))) && + (data->bank1_settings[attr->index][0] & attr->nr)) + return sprintf(buf, "1\n"); + else + return sprintf(buf, "0\n"); +} + +static ssize_t show_bank2_alarm(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = abituguru_update_device(dev); + if (!data) + return -EIO; + if (data->alarms[2] & (0x01 << attr->index)) + return sprintf(buf, "1\n"); + else + return sprintf(buf, "0\n"); +} + +static ssize_t show_bank1_mask(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = dev_get_drvdata(dev); + if (data->bank1_settings[attr->index][0] & attr->nr) + return sprintf(buf, "1\n"); + else + return sprintf(buf, "0\n"); +} + +static ssize_t show_bank2_mask(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = dev_get_drvdata(dev); + if (data->bank2_settings[attr->index][0] & attr->nr) + return sprintf(buf, "1\n"); + else + return sprintf(buf, "0\n"); +} + +static ssize_t store_bank1_mask(struct device *dev, + struct device_attribute *devattr, const char *buf, size_t count) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = dev_get_drvdata(dev); + int mask = simple_strtoul(buf, NULL, 10); + ssize_t ret = count; + u8 orig_val; + + mutex_lock(&data->update_lock); + orig_val = data->bank1_settings[attr->index][0]; + + if (mask) + data->bank1_settings[attr->index][0] |= attr->nr; + else + data->bank1_settings[attr->index][0] &= ~attr->nr; + + if ((data->bank1_settings[attr->index][0] != orig_val) && + (abituguru_write(data, + ABIT_UGURU_SENSOR_BANK1 + 2, attr->index, + data->bank1_settings[attr->index], 3) < 1)) { + data->bank1_settings[attr->index][0] = orig_val; + ret = -EIO; + } + mutex_unlock(&data->update_lock); + return ret; +} + +static ssize_t store_bank2_mask(struct device *dev, + struct device_attribute *devattr, const char *buf, size_t count) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = dev_get_drvdata(dev); + int mask = simple_strtoul(buf, NULL, 10); + ssize_t ret = count; + u8 orig_val; + + mutex_lock(&data->update_lock); + orig_val = data->bank2_settings[attr->index][0]; + + if (mask) + data->bank2_settings[attr->index][0] |= attr->nr; + else + data->bank2_settings[attr->index][0] &= ~attr->nr; + + if ((data->bank2_settings[attr->index][0] != orig_val) && + (abituguru_write(data, + ABIT_UGURU_SENSOR_BANK2 + 2, attr->index, + data->bank2_settings[attr->index], 2) < 1)) { + data->bank2_settings[attr->index][0] = orig_val; + ret = -EIO; + } + mutex_unlock(&data->update_lock); + return ret; +} + +/* Fan PWM (speed control) */ +static ssize_t show_pwm_setting(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = dev_get_drvdata(dev); + return sprintf(buf, "%d\n", data->pwm_settings[attr->index][attr->nr] * + abituguru_pwm_settings_multiplier[attr->nr]); +} + +static ssize_t store_pwm_setting(struct device *dev, struct device_attribute + *devattr, const char *buf, size_t count) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = dev_get_drvdata(dev); + u8 min, val = (simple_strtoul(buf, NULL, 10) + + abituguru_pwm_settings_multiplier[attr->nr]/2) / + abituguru_pwm_settings_multiplier[attr->nr]; + ssize_t ret = count; + + /* special case pwm1 min pwm% */ + if ((attr->index == 0) && ((attr->nr == 1) || (attr->nr == 2))) + min = 77; + else + min = abituguru_pwm_min[attr->nr]; + + /* this check can be done before taking the lock */ + if ((val < min) || (val > abituguru_pwm_max[attr->nr])) + return -EINVAL; + + mutex_lock(&data->update_lock); + /* this check needs to be done after taking the lock */ + if ((attr->nr & 1) && + (val >= data->pwm_settings[attr->index][attr->nr + 1])) + ret = -EINVAL; + else if (!(attr->nr & 1) && + (val <= data->pwm_settings[attr->index][attr->nr - 1])) + ret = -EINVAL; + else if (data->pwm_settings[attr->index][attr->nr] != val) { + u8 orig_val = data->pwm_settings[attr->index][attr->nr]; + data->pwm_settings[attr->index][attr->nr] = val; + if (abituguru_write(data, ABIT_UGURU_FAN_PWM + 1, + attr->index, data->pwm_settings[attr->index], + 5) <= attr->nr) { + data->pwm_settings[attr->index][attr->nr] = + orig_val; + ret = -EIO; + } + } + mutex_unlock(&data->update_lock); + return ret; +} + +static ssize_t show_pwm_sensor(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = dev_get_drvdata(dev); + int i; + /* We need to walk to the temp sensor addresses to find what + the userspace id of the configured temp sensor is. */ + for (i = 0; i < data->bank1_sensors[ABIT_UGURU_TEMP_SENSOR]; i++) + if (data->bank1_address[ABIT_UGURU_TEMP_SENSOR][i] == + (data->pwm_settings[attr->index][0] & 0x0F)) + return sprintf(buf, "%d\n", i+1); + + return -ENXIO; +} + +static ssize_t store_pwm_sensor(struct device *dev, struct device_attribute + *devattr, const char *buf, size_t count) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = dev_get_drvdata(dev); + unsigned long val = simple_strtoul(buf, NULL, 10) - 1; + ssize_t ret = count; + + mutex_lock(&data->update_lock); + if (val < data->bank1_sensors[ABIT_UGURU_TEMP_SENSOR]) { + u8 orig_val = data->pwm_settings[attr->index][0]; + u8 address = data->bank1_address[ABIT_UGURU_TEMP_SENSOR][val]; + data->pwm_settings[attr->index][0] &= 0xF0; + data->pwm_settings[attr->index][0] |= address; + if (data->pwm_settings[attr->index][0] != orig_val) { + if (abituguru_write(data, ABIT_UGURU_FAN_PWM + 1, + attr->index, + data->pwm_settings[attr->index], + 5) < 1) { + data->pwm_settings[attr->index][0] = orig_val; + ret = -EIO; + } + } + } + else + ret = -EINVAL; + mutex_unlock(&data->update_lock); + return ret; +} + +static ssize_t show_pwm_enable(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = dev_get_drvdata(dev); + int res = 0; + if (data->pwm_settings[attr->index][0] & ABIT_UGURU_FAN_PWM_ENABLE) + res = 2; + return sprintf(buf, "%d\n", res); +} + +static ssize_t store_pwm_enable(struct device *dev, struct device_attribute + *devattr, const char *buf, size_t count) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = dev_get_drvdata(dev); + u8 orig_val, user_val = simple_strtoul(buf, NULL, 10); + ssize_t ret = count; + + mutex_lock(&data->update_lock); + orig_val = data->pwm_settings[attr->index][0]; + switch (user_val) { + case 0: + data->pwm_settings[attr->index][0] &= + ~ABIT_UGURU_FAN_PWM_ENABLE; + break; + case 2: + data->pwm_settings[attr->index][0] |= + ABIT_UGURU_FAN_PWM_ENABLE; + break; + default: + ret = -EINVAL; + } + if ((data->pwm_settings[attr->index][0] != orig_val) && + (abituguru_write(data, ABIT_UGURU_FAN_PWM + 1, + attr->index, data->pwm_settings[attr->index], + 5) < 1)) { + data->pwm_settings[attr->index][0] = orig_val; + ret = -EIO; + } + mutex_unlock(&data->update_lock); + return ret; +} + +static ssize_t show_name(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + return sprintf(buf, "%s\n", ABIT_UGURU_NAME); +} + +/* Sysfs attr templates, the real entries are generated automatically. */ +static const +struct sensor_device_attribute_2 abituguru_sysfs_bank1_templ[2][9] = { + { + SENSOR_ATTR_2(in%d_input, 0444, show_bank1_value, NULL, 0, 0), + SENSOR_ATTR_2(in%d_min, 0644, show_bank1_setting, + store_bank1_setting, 1, 0), + SENSOR_ATTR_2(in%d_min_alarm, 0444, show_bank1_alarm, NULL, + ABIT_UGURU_VOLT_LOW_ALARM_FLAG, 0), + SENSOR_ATTR_2(in%d_max, 0644, show_bank1_setting, + store_bank1_setting, 2, 0), + SENSOR_ATTR_2(in%d_max_alarm, 0444, show_bank1_alarm, NULL, + ABIT_UGURU_VOLT_HIGH_ALARM_FLAG, 0), + SENSOR_ATTR_2(in%d_beep, 0644, show_bank1_mask, + store_bank1_mask, ABIT_UGURU_BEEP_ENABLE, 0), + SENSOR_ATTR_2(in%d_shutdown, 0644, show_bank1_mask, + store_bank1_mask, ABIT_UGURU_SHUTDOWN_ENABLE, 0), + SENSOR_ATTR_2(in%d_min_alarm_enable, 0644, show_bank1_mask, + store_bank1_mask, ABIT_UGURU_VOLT_LOW_ALARM_ENABLE, 0), + SENSOR_ATTR_2(in%d_max_alarm_enable, 0644, show_bank1_mask, + store_bank1_mask, ABIT_UGURU_VOLT_HIGH_ALARM_ENABLE, 0), + }, { + SENSOR_ATTR_2(temp%d_input, 0444, show_bank1_value, NULL, 0, 0), + SENSOR_ATTR_2(temp%d_alarm, 0444, show_bank1_alarm, NULL, + ABIT_UGURU_TEMP_HIGH_ALARM_FLAG, 0), + SENSOR_ATTR_2(temp%d_max, 0644, show_bank1_setting, + store_bank1_setting, 1, 0), + SENSOR_ATTR_2(temp%d_crit, 0644, show_bank1_setting, + store_bank1_setting, 2, 0), + SENSOR_ATTR_2(temp%d_beep, 0644, show_bank1_mask, + store_bank1_mask, ABIT_UGURU_BEEP_ENABLE, 0), + SENSOR_ATTR_2(temp%d_shutdown, 0644, show_bank1_mask, + store_bank1_mask, ABIT_UGURU_SHUTDOWN_ENABLE, 0), + SENSOR_ATTR_2(temp%d_alarm_enable, 0644, show_bank1_mask, + store_bank1_mask, ABIT_UGURU_TEMP_HIGH_ALARM_ENABLE, 0), + } +}; + +static const struct sensor_device_attribute_2 abituguru_sysfs_fan_templ[6] = { + SENSOR_ATTR_2(fan%d_input, 0444, show_bank2_value, NULL, 0, 0), + SENSOR_ATTR_2(fan%d_alarm, 0444, show_bank2_alarm, NULL, 0, 0), + SENSOR_ATTR_2(fan%d_min, 0644, show_bank2_setting, + store_bank2_setting, 1, 0), + SENSOR_ATTR_2(fan%d_beep, 0644, show_bank2_mask, + store_bank2_mask, ABIT_UGURU_BEEP_ENABLE, 0), + SENSOR_ATTR_2(fan%d_shutdown, 0644, show_bank2_mask, + store_bank2_mask, ABIT_UGURU_SHUTDOWN_ENABLE, 0), + SENSOR_ATTR_2(fan%d_alarm_enable, 0644, show_bank2_mask, + store_bank2_mask, ABIT_UGURU_FAN_LOW_ALARM_ENABLE, 0), +}; + +static const struct sensor_device_attribute_2 abituguru_sysfs_pwm_templ[6] = { + SENSOR_ATTR_2(pwm%d_enable, 0644, show_pwm_enable, + store_pwm_enable, 0, 0), + SENSOR_ATTR_2(pwm%d_auto_channels_temp, 0644, show_pwm_sensor, + store_pwm_sensor, 0, 0), + SENSOR_ATTR_2(pwm%d_auto_point1_pwm, 0644, show_pwm_setting, + store_pwm_setting, 1, 0), + SENSOR_ATTR_2(pwm%d_auto_point2_pwm, 0644, show_pwm_setting, + store_pwm_setting, 2, 0), + SENSOR_ATTR_2(pwm%d_auto_point1_temp, 0644, show_pwm_setting, + store_pwm_setting, 3, 0), + SENSOR_ATTR_2(pwm%d_auto_point2_temp, 0644, show_pwm_setting, + store_pwm_setting, 4, 0), +}; + +static const struct sensor_device_attribute_2 abituguru_sysfs_attr[] = { + SENSOR_ATTR_2(name, 0444, show_name, NULL, 0, 0), +}; + +static int __devinit abituguru_probe(struct platform_device *pdev) +{ + struct abituguru_data *data; + int i, j, res; + char *sysfs_filename; + int sysfs_attr_i = 0; + + /* El weirdo probe order, to keep the sysfs order identical to the + BIOS and window-appliction listing order. */ + const u8 probe_order[16] = { 0x00, 0x01, 0x03, 0x04, 0x0A, 0x08, 0x0E, + 0x02, 0x09, 0x06, 0x05, 0x0B, 0x0F, 0x0D, 0x07, 0x0C }; + + if (!(data = kzalloc(sizeof(struct abituguru_data), GFP_KERNEL))) + return -ENOMEM; + + data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start; + mutex_init(&data->update_lock); + platform_set_drvdata(pdev, data); + + /* See if the uGuru is ready */ + if (inb_p(data->addr + ABIT_UGURU_DATA) == ABIT_UGURU_STATUS_INPUT) + data->uguru_ready = 1; + + /* Completely read the uGuru this has 2 purposes: + - testread / see if one really is there. + - make an in memory copy of all the uguru settings for future use. */ + if (abituguru_read(data, ABIT_UGURU_ALARM_BANK, 0, + data->alarms, 3, ABIT_UGURU_MAX_RETRIES) != 3) { + kfree(data); + return -ENODEV; + } + + for (i = 0; i < 16; i++) { + if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1, i, + &data->bank1_value[i], 1, + ABIT_UGURU_MAX_RETRIES) != 1) { + kfree(data); + return -ENODEV; + } + if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1+1, i, + data->bank1_settings[i], 3, + ABIT_UGURU_MAX_RETRIES) != 3) { + kfree(data); + return -ENODEV; + } + } + /* Note: We don't know how many bank2 sensors / pwms there really are, + but in order to "detect" this we need to read the maximum amount + anyways. If we read sensors/pwms not there we'll just read crap + this can't hurt. We need the detection because we don't want + unwanted writes, which will hurt! */ + for (i = 0; i < ABIT_UGURU_MAX_BANK2_SENSORS; i++) { + if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK2, i, + &data->bank2_value[i], 1, + ABIT_UGURU_MAX_RETRIES) != 1) { + kfree(data); + return -ENODEV; + } + if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK2+1, i, + data->bank2_settings[i], 2, + ABIT_UGURU_MAX_RETRIES) != 2) { + kfree(data); + return -ENODEV; + } + } + for (i = 0; i < ABIT_UGURU_MAX_PWMS; i++) { + if (abituguru_read(data, ABIT_UGURU_FAN_PWM, i, + data->pwm_settings[i], 5, + ABIT_UGURU_MAX_RETRIES) != 5) { + kfree(data); + return -ENODEV; + } + } + data->last_updated = jiffies; + + /* Detect sensor types and fill the sysfs attr for bank1 */ + sysfs_filename = data->bank1_names; + for (i = 0; i < 16; i++) { + res = abituguru_detect_bank1_sensor_type(data, probe_order[i]); + if (res < 0) { + kfree(data); + return -ENODEV; + } + if (res == ABIT_UGURU_NC) + continue; + + for (j = 0; j < (res ? 7 : 9); j++) { + const char *name_templ = abituguru_sysfs_bank1_templ[ + res][j].dev_attr.attr.name; + data->sysfs_attr[sysfs_attr_i] = + abituguru_sysfs_bank1_templ[res][j]; + data->sysfs_attr[sysfs_attr_i].dev_attr.attr.name = + sysfs_filename; + sysfs_filename += sprintf(sysfs_filename, name_templ, + data->bank1_sensors[res] + res) + 1; + data->sysfs_attr[sysfs_attr_i].index = probe_order[i]; + sysfs_attr_i++; + } + data->bank1_max_value[probe_order[i]] = + abituguru_bank1_max_value[res]; + data->bank1_address[res][data->bank1_sensors[res]] = + probe_order[i]; + data->bank1_sensors[res]++; + } + /* Detect number of sensors and fill the sysfs attr for bank2 (fans) */ + abituguru_detect_no_bank2_sensors(data); + for (i = 0; i < data->bank2_sensors; i++) { + for (j = 0; j < 6; j++) { + const char *name_templ = abituguru_sysfs_fan_templ[j]. + dev_attr.attr.name; + data->sysfs_attr[sysfs_attr_i] = + abituguru_sysfs_fan_templ[j]; + data->sysfs_attr[sysfs_attr_i].dev_attr.attr.name = + sysfs_filename; + sysfs_filename += sprintf(sysfs_filename, name_templ, + i + 1) + 1; + data->sysfs_attr[sysfs_attr_i].index = i; + sysfs_attr_i++; + } + } + /* Detect number of sensors and fill the sysfs attr for pwms */ + abituguru_detect_no_pwms(data); + for (i = 0; i < data->pwms; i++) { + for (j = 0; j < 6; j++) { + const char *name_templ = abituguru_sysfs_pwm_templ[j]. + dev_attr.attr.name; + data->sysfs_attr[sysfs_attr_i] = + abituguru_sysfs_pwm_templ[j]; + data->sysfs_attr[sysfs_attr_i].dev_attr.attr.name = + sysfs_filename; + sysfs_filename += sprintf(sysfs_filename, name_templ, + i + 1) + 1; + data->sysfs_attr[sysfs_attr_i].index = i; + sysfs_attr_i++; + } + } + /* Last add any "generic" entries to sysfs */ + for (i = 0; i < ARRAY_SIZE(abituguru_sysfs_attr); i++) { + data->sysfs_attr[sysfs_attr_i] = abituguru_sysfs_attr[i]; + sysfs_attr_i++; + } + printk(KERN_INFO ABIT_UGURU_NAME ": found Abit uGuru\n"); + + /* Register sysfs hooks */ + data->class_dev = hwmon_device_register(&pdev->dev); + if (IS_ERR(data->class_dev)) { + kfree(data); + return PTR_ERR(data->class_dev); + } + for (i = 0; i < sysfs_attr_i; i++) + device_create_file(&pdev->dev, &data->sysfs_attr[i].dev_attr); + + return 0; +} + +static int __devexit abituguru_remove(struct platform_device *pdev) +{ + struct abituguru_data *data = platform_get_drvdata(pdev); + + platform_set_drvdata(pdev, NULL); + hwmon_device_unregister(data->class_dev); + kfree(data); + + return 0; +} + +static struct abituguru_data *abituguru_update_device(struct device *dev) +{ + int i, err; + struct abituguru_data *data = dev_get_drvdata(dev); + /* fake a complete successful read if no update necessary. */ + char success = 1; + + mutex_lock(&data->update_lock); + if (time_after(jiffies, data->last_updated + HZ)) { + success = 0; + if ((err = abituguru_read(data, ABIT_UGURU_ALARM_BANK, 0, + data->alarms, 3, 0)) != 3) + goto LEAVE_UPDATE; + for (i = 0; i < 16; i++) { + if ((err = abituguru_read(data, + ABIT_UGURU_SENSOR_BANK1, i, + &data->bank1_value[i], 1, 0)) != 1) + goto LEAVE_UPDATE; + if ((err = abituguru_read(data, + ABIT_UGURU_SENSOR_BANK1 + 1, i, + data->bank1_settings[i], 3, 0)) != 3) + goto LEAVE_UPDATE; + } + for (i = 0; i < data->bank2_sensors; i++) + if ((err = abituguru_read(data, + ABIT_UGURU_SENSOR_BANK2, i, + &data->bank2_value[i], 1, 0)) != 1) + goto LEAVE_UPDATE; + /* success! */ + success = 1; + data->update_timeouts = 0; +LEAVE_UPDATE: + /* handle timeout condition */ + if (err == -EBUSY) { + /* No overflow please */ + if (data->update_timeouts < 255u) + data->update_timeouts++; + if (data->update_timeouts <= ABIT_UGURU_MAX_TIMEOUTS) { + ABIT_UGURU_DEBUG(3, "timeout exceeded, will " + "try again next update\n"); + /* Just a timeout, fake a successful read */ + success = 1; + } else + ABIT_UGURU_DEBUG(1, "timeout exceeded %d " + "times waiting for more input state\n", + (int)data->update_timeouts); + } + /* On success set last_updated */ + if (success) + data->last_updated = jiffies; + } + mutex_unlock(&data->update_lock); + + if (success) + return data; + else + return NULL; +} + +static struct platform_driver abituguru_driver = { + .driver = { + .owner = THIS_MODULE, + .name = ABIT_UGURU_NAME, + }, + .probe = abituguru_probe, + .remove = __devexit_p(abituguru_remove), +}; + +static int __init abituguru_detect(void) +{ + /* See if there is an uguru there. After a reboot uGuru will hold 0x00 + at DATA and 0xAC, when this driver has already been loaded once + DATA will hold 0x08. For most uGuru's CMD will hold 0xAC in either + scenario but some will hold 0x00. + Some uGuru's initally hold 0x09 at DATA and will only hold 0x08 + after reading CMD first, so CMD must be read first! */ + u8 cmd_val = inb_p(ABIT_UGURU_BASE + ABIT_UGURU_CMD); + u8 data_val = inb_p(ABIT_UGURU_BASE + ABIT_UGURU_DATA); + if (((data_val == 0x00) || (data_val == 0x08)) && + ((cmd_val == 0x00) || (cmd_val == 0xAC))) + return ABIT_UGURU_BASE; + + ABIT_UGURU_DEBUG(2, "no Abit uGuru found, data = 0x%02X, cmd = " + "0x%02X\n", (unsigned int)data_val, (unsigned int)cmd_val); + + if (force) { + printk(KERN_INFO ABIT_UGURU_NAME ": Assuming Abit uGuru is " + "present because of \"force\" parameter\n"); + return ABIT_UGURU_BASE; + } + + /* No uGuru found */ + return -ENODEV; +} + +static struct platform_device *abituguru_pdev; + +static int __init abituguru_init(void) +{ + int address, err; + struct resource res = { .flags = IORESOURCE_IO }; + + address = abituguru_detect(); + if (address < 0) + return address; + + err = platform_driver_register(&abituguru_driver); + if (err) + goto exit; + + abituguru_pdev = platform_device_alloc(ABIT_UGURU_NAME, address); + if (!abituguru_pdev) { + printk(KERN_ERR ABIT_UGURU_NAME + ": Device allocation failed\n"); + err = -ENOMEM; + goto exit_driver_unregister; + } + + res.start = address; + res.end = address + ABIT_UGURU_REGION_LENGTH - 1; + res.name = ABIT_UGURU_NAME; + + err = platform_device_add_resources(abituguru_pdev, &res, 1); + if (err) { + printk(KERN_ERR ABIT_UGURU_NAME + ": Device resource addition failed (%d)\n", err); + goto exit_device_put; + } + + err = platform_device_add(abituguru_pdev); + if (err) { + printk(KERN_ERR ABIT_UGURU_NAME + ": Device addition failed (%d)\n", err); + goto exit_device_put; + } + + return 0; + +exit_device_put: + platform_device_put(abituguru_pdev); +exit_driver_unregister: + platform_driver_unregister(&abituguru_driver); +exit: + return err; +} + +static void __exit abituguru_exit(void) +{ + platform_device_unregister(abituguru_pdev); + platform_driver_unregister(&abituguru_driver); +} + +MODULE_AUTHOR("Hans de Goede "); +MODULE_DESCRIPTION("Abit uGuru Sensor device"); +MODULE_LICENSE("GPL"); + +module_init(abituguru_init); +module_exit(abituguru_exit); -- cgit v1.2.3 From a2392e0b907b9633c31be14ee75bb39fce348b01 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 4 Jun 2006 20:23:01 +0200 Subject: [PATCH] abituguru: Review fixes Fixes to the Abit uGuru driver as requested in review by Jean Delvare: - exactly calculate the sysfs_names array length using macro - use snprintf when generating names to double check that the sysfs_names array does not overflow. - use ARRAY_SIZE and / or defines to determine number of loops in for loops instead of using hardcoded values. - In abituguru_probe(), refactor the error path leaving a single call to kfree Signed-off-by: Hans de Goede Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/abituguru.c | 197 ++++++++++++++++++++++++++-------------------- 1 file changed, 111 insertions(+), 86 deletions(-) diff --git a/drivers/hwmon/abituguru.c b/drivers/hwmon/abituguru.c index bf2cb0aa69b..ab80b418bd6 100644 --- a/drivers/hwmon/abituguru.c +++ b/drivers/hwmon/abituguru.c @@ -36,6 +36,10 @@ #define ABIT_UGURU_SENSOR_BANK1 0x21 /* 16x volt and temp */ #define ABIT_UGURU_FAN_PWM 0x24 /* 3x 5 bytes */ #define ABIT_UGURU_SENSOR_BANK2 0x26 /* fans */ +/* max nr of sensors in bank1, a bank1 sensor can be in, temp or nc */ +#define ABIT_UGURU_MAX_BANK1_SENSORS 16 +/* Warning if you increase one of the 2 MAX defines below to 10 or higher you + should adjust the belonging _NAMES_LENGTH macro for the 2 digit number! */ /* max nr of sensors in bank2, currently mb's with max 6 fans are known */ #define ABIT_UGURU_MAX_BANK2_SENSORS 6 /* max nr of pwm outputs, currently mb's with max 5 pwm outputs are known */ @@ -74,10 +78,33 @@ /* Maximum 3 retries on timedout reads/writes, delay 200 ms before retrying */ #define ABIT_UGURU_MAX_RETRIES 3 #define ABIT_UGURU_RETRY_DELAY (HZ/5) -/* Maximum 2 timeouts in abituguru_update_device, iow 3 in a row is a error */ +/* Maximum 2 timeouts in abituguru_update_device, iow 3 in a row is an error */ #define ABIT_UGURU_MAX_TIMEOUTS 2 - -/* All the variables below are named identical to the oguru and oguru2 programs +/* utility macros */ +#define ABIT_UGURU_NAME "abituguru" +#define ABIT_UGURU_DEBUG(level, format, arg...) \ + if (level <= verbose) \ + printk(KERN_DEBUG ABIT_UGURU_NAME ": " format , ## arg) +/* Macros to help calculate the sysfs_names array length */ +/* sum of strlen of: in??_input\0, in??_{min,max}\0, in??_{min,max}_alarm\0, + in??_{min,max}_alarm_enable\0, in??_beep\0, in??_shutdown\0 */ +#define ABITUGURU_IN_NAMES_LENGTH (11 + 2 * 9 + 2 * 15 + 2 * 22 + 10 + 14) +/* sum of strlen of: temp??_input\0, temp??_max\0, temp??_crit\0, + temp??_alarm\0, temp??_alarm_enable\0, temp??_beep\0, temp??_shutdown\0 */ +#define ABITUGURU_TEMP_NAMES_LENGTH (13 + 11 + 12 + 13 + 20 + 12 + 16) +/* sum of strlen of: fan?_input\0, fan?_min\0, fan?_alarm\0, + fan?_alarm_enable\0, fan?_beep\0, fan?_shutdown\0 */ +#define ABITUGURU_FAN_NAMES_LENGTH (11 + 9 + 11 + 18 + 10 + 14) +/* sum of strlen of: pwm?_enable\0, pwm?_auto_channels_temp\0, + pwm?_auto_point{1,2}_pwm\0, pwm?_auto_point{1,2}_temp\0 */ +#define ABITUGURU_PWM_NAMES_LENGTH (12 + 24 + 2 * 21 + 2 * 22) +/* IN_NAMES_LENGTH > TEMP_NAMES_LENGTH so assume all bank1 sensors are in */ +#define ABITUGURU_SYSFS_NAMES_LENGTH ( \ + ABIT_UGURU_MAX_BANK1_SENSORS * ABITUGURU_IN_NAMES_LENGTH + \ + ABIT_UGURU_MAX_BANK2_SENSORS * ABITUGURU_FAN_NAMES_LENGTH + \ + ABIT_UGURU_MAX_PWMS * ABITUGURU_PWM_NAMES_LENGTH) + +/* All the macros below are named identical to the oguru and oguru2 programs reverse engineered by Olle Sandberg, hence the names might not be 100% logical. I could come up with better names, but I prefer keeping the names identical so that this driver can be compared with his work more easily. */ @@ -93,11 +120,6 @@ #define ABIT_UGURU_STATUS_READ 0x01 /* Ready to be read */ #define ABIT_UGURU_STATUS_INPUT 0x08 /* More input */ #define ABIT_UGURU_STATUS_READY 0x09 /* Ready to be written */ -/* utility macros */ -#define ABIT_UGURU_NAME "abituguru" -#define ABIT_UGURU_DEBUG(level, format, arg...) \ - if (level <= verbose) \ - printk(KERN_DEBUG ABIT_UGURU_NAME ": " format , ## arg) /* Constants */ /* in (Volt) sensors go up to 3494 mV, temp to 255000 millidegrees Celsius */ @@ -156,24 +178,23 @@ struct abituguru_data { of a sensor is a volt or a temp sensor, for bank2 and the pwms its easier todo things the same way. For in sensors we have 9 (temp 7) sysfs entries per sensor, for bank2 and pwms 6. */ - struct sensor_device_attribute_2 sysfs_attr[16 * 9 + + struct sensor_device_attribute_2 sysfs_attr[ + ABIT_UGURU_MAX_BANK1_SENSORS * 9 + ABIT_UGURU_MAX_BANK2_SENSORS * 6 + ABIT_UGURU_MAX_PWMS * 6]; - /* Buffer to store the dynamically generated sysfs names, we need 2120 - bytes for bank1 (worst case scenario of 16 in sensors), 444 bytes - for fan1-6 and 738 bytes for pwm1-6 + some room to spare in case I - miscounted :) */ - char bank1_names[3400]; + /* Buffer to store the dynamically generated sysfs names */ + char sysfs_names[ABITUGURU_SYSFS_NAMES_LENGTH]; /* Bank 1 data */ - u8 bank1_sensors[2]; /* number of [0] in, [1] temp sensors */ - u8 bank1_address[2][16];/* addresses of [0] in, [1] temp sensors */ - u8 bank1_value[16]; - /* This array holds 16 x 3 entries for all the bank 1 sensor settings + /* number of and addresses of [0] in, [1] temp sensors */ + u8 bank1_sensors[2]; + u8 bank1_address[2][ABIT_UGURU_MAX_BANK1_SENSORS]; + u8 bank1_value[ABIT_UGURU_MAX_BANK1_SENSORS]; + /* This array holds 3 entries per sensor for the bank 1 sensor settings (flags, min, max for voltage / flags, warn, shutdown for temp). */ - u8 bank1_settings[16][3]; + u8 bank1_settings[ABIT_UGURU_MAX_BANK1_SENSORS][3]; /* Maximum value for each sensor used for scaling in mV/millidegrees Celsius. */ - int bank1_max_value[16]; + int bank1_max_value[ABIT_UGURU_MAX_BANK1_SENSORS]; /* Bank 2 data, ABIT_UGURU_MAX_BANK2_SENSORS entries for bank2 */ u8 bank2_sensors; /* actual number of bank2 sensors found */ @@ -379,7 +400,7 @@ abituguru_detect_bank1_sensor_type(struct abituguru_data *data, /* First read the sensor and the current settings */ if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1, sensor_addr, &val, 1, ABIT_UGURU_MAX_RETRIES) != 1) - return -EIO; + return -ENODEV; /* Test val is sane / usable for sensor type detection. */ if ((val < 10u) || (val > 240u)) { @@ -401,7 +422,7 @@ abituguru_detect_bank1_sensor_type(struct abituguru_data *data, buf[2] = 250; if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, sensor_addr, buf, 3) != 3) - return -EIO; + return -ENODEV; /* Now we need 20 ms to give the uguru time to read the sensors and raise a voltage alarm */ set_current_state(TASK_UNINTERRUPTIBLE); @@ -409,19 +430,19 @@ abituguru_detect_bank1_sensor_type(struct abituguru_data *data, /* Check for alarm and check the alarm is a volt low alarm. */ if (abituguru_read(data, ABIT_UGURU_ALARM_BANK, 0, buf, 3, ABIT_UGURU_MAX_RETRIES) != 3) - return -EIO; + return -ENODEV; if (buf[sensor_addr/8] & (0x01 << (sensor_addr % 8))) { if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1 + 1, sensor_addr, buf, 3, ABIT_UGURU_MAX_RETRIES) != 3) - return -EIO; + return -ENODEV; if (buf[0] & ABIT_UGURU_VOLT_LOW_ALARM_FLAG) { /* Restore original settings */ if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, sensor_addr, data->bank1_settings[sensor_addr], 3) != 3) - return -EIO; + return -ENODEV; ABIT_UGURU_DEBUG(2, " found volt sensor\n"); return ABIT_UGURU_IN_SENSOR; } else @@ -439,7 +460,7 @@ abituguru_detect_bank1_sensor_type(struct abituguru_data *data, buf[2] = 10; if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, sensor_addr, buf, 3) != 3) - return -EIO; + return -ENODEV; /* Now we need 50 ms to give the uguru time to read the sensors and raise a temp alarm */ set_current_state(TASK_UNINTERRUPTIBLE); @@ -447,12 +468,12 @@ abituguru_detect_bank1_sensor_type(struct abituguru_data *data, /* Check for alarm and check the alarm is a temp high alarm. */ if (abituguru_read(data, ABIT_UGURU_ALARM_BANK, 0, buf, 3, ABIT_UGURU_MAX_RETRIES) != 3) - return -EIO; + return -ENODEV; if (buf[sensor_addr/8] & (0x01 << (sensor_addr % 8))) { if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1 + 1, sensor_addr, buf, 3, ABIT_UGURU_MAX_RETRIES) != 3) - return -EIO; + return -ENODEV; if (buf[0] & ABIT_UGURU_TEMP_HIGH_ALARM_FLAG) { ret = ABIT_UGURU_TEMP_SENSOR; ABIT_UGURU_DEBUG(2, " found temp sensor\n"); @@ -466,7 +487,7 @@ abituguru_detect_bank1_sensor_type(struct abituguru_data *data, /* Restore original settings */ if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, sensor_addr, data->bank1_settings[sensor_addr], 3) != 3) - return -EIO; + return -ENODEV; return ret; } @@ -1061,21 +1082,21 @@ static const struct sensor_device_attribute_2 abituguru_sysfs_pwm_templ[6] = { store_pwm_setting, 4, 0), }; -static const struct sensor_device_attribute_2 abituguru_sysfs_attr[] = { +static struct sensor_device_attribute_2 abituguru_sysfs_attr[] = { SENSOR_ATTR_2(name, 0444, show_name, NULL, 0, 0), }; static int __devinit abituguru_probe(struct platform_device *pdev) { struct abituguru_data *data; - int i, j, res; + int i, j, used, sysfs_names_free, sysfs_attr_i, res = -ENODEV; char *sysfs_filename; - int sysfs_attr_i = 0; /* El weirdo probe order, to keep the sysfs order identical to the BIOS and window-appliction listing order. */ - const u8 probe_order[16] = { 0x00, 0x01, 0x03, 0x04, 0x0A, 0x08, 0x0E, - 0x02, 0x09, 0x06, 0x05, 0x0B, 0x0F, 0x0D, 0x07, 0x0C }; + const u8 probe_order[ABIT_UGURU_MAX_BANK1_SENSORS] = { + 0x00, 0x01, 0x03, 0x04, 0x0A, 0x08, 0x0E, 0x02, + 0x09, 0x06, 0x05, 0x0B, 0x0F, 0x0D, 0x07, 0x0C }; if (!(data = kzalloc(sizeof(struct abituguru_data), GFP_KERNEL))) return -ENOMEM; @@ -1092,24 +1113,18 @@ static int __devinit abituguru_probe(struct platform_device *pdev) - testread / see if one really is there. - make an in memory copy of all the uguru settings for future use. */ if (abituguru_read(data, ABIT_UGURU_ALARM_BANK, 0, - data->alarms, 3, ABIT_UGURU_MAX_RETRIES) != 3) { - kfree(data); - return -ENODEV; - } + data->alarms, 3, ABIT_UGURU_MAX_RETRIES) != 3) + goto abituguru_probe_error; - for (i = 0; i < 16; i++) { + for (i = 0; i < ABIT_UGURU_MAX_BANK1_SENSORS; i++) { if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1, i, &data->bank1_value[i], 1, - ABIT_UGURU_MAX_RETRIES) != 1) { - kfree(data); - return -ENODEV; - } + ABIT_UGURU_MAX_RETRIES) != 1) + goto abituguru_probe_error; if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1+1, i, data->bank1_settings[i], 3, - ABIT_UGURU_MAX_RETRIES) != 3) { - kfree(data); - return -ENODEV; - } + ABIT_UGURU_MAX_RETRIES) != 3) + goto abituguru_probe_error; } /* Note: We don't know how many bank2 sensors / pwms there really are, but in order to "detect" this we need to read the maximum amount @@ -1119,48 +1134,45 @@ static int __devinit abituguru_probe(struct platform_device *pdev) for (i = 0; i < ABIT_UGURU_MAX_BANK2_SENSORS; i++) { if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK2, i, &data->bank2_value[i], 1, - ABIT_UGURU_MAX_RETRIES) != 1) { - kfree(data); - return -ENODEV; - } + ABIT_UGURU_MAX_RETRIES) != 1) + goto abituguru_probe_error; if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK2+1, i, data->bank2_settings[i], 2, - ABIT_UGURU_MAX_RETRIES) != 2) { - kfree(data); - return -ENODEV; - } + ABIT_UGURU_MAX_RETRIES) != 2) + goto abituguru_probe_error; } for (i = 0; i < ABIT_UGURU_MAX_PWMS; i++) { if (abituguru_read(data, ABIT_UGURU_FAN_PWM, i, data->pwm_settings[i], 5, - ABIT_UGURU_MAX_RETRIES) != 5) { - kfree(data); - return -ENODEV; - } + ABIT_UGURU_MAX_RETRIES) != 5) + goto abituguru_probe_error; } data->last_updated = jiffies; /* Detect sensor types and fill the sysfs attr for bank1 */ - sysfs_filename = data->bank1_names; - for (i = 0; i < 16; i++) { + sysfs_attr_i = 0; + sysfs_filename = data->sysfs_names; + sysfs_names_free = ABITUGURU_SYSFS_NAMES_LENGTH; + for (i = 0; i < ABIT_UGURU_MAX_BANK1_SENSORS; i++) { res = abituguru_detect_bank1_sensor_type(data, probe_order[i]); - if (res < 0) { - kfree(data); - return -ENODEV; - } + if (res < 0) + goto abituguru_probe_error; if (res == ABIT_UGURU_NC) continue; + /* res 1 (temp) sensors have 7 sysfs entries, 0 (in) 9 */ for (j = 0; j < (res ? 7 : 9); j++) { - const char *name_templ = abituguru_sysfs_bank1_templ[ - res][j].dev_attr.attr.name; + used = snprintf(sysfs_filename, sysfs_names_free, + abituguru_sysfs_bank1_templ[res][j].dev_attr. + attr.name, data->bank1_sensors[res] + res) + + 1; data->sysfs_attr[sysfs_attr_i] = abituguru_sysfs_bank1_templ[res][j]; data->sysfs_attr[sysfs_attr_i].dev_attr.attr.name = sysfs_filename; - sysfs_filename += sprintf(sysfs_filename, name_templ, - data->bank1_sensors[res] + res) + 1; data->sysfs_attr[sysfs_attr_i].index = probe_order[i]; + sysfs_filename += used; + sysfs_names_free -= used; sysfs_attr_i++; } data->bank1_max_value[probe_order[i]] = @@ -1172,52 +1184,65 @@ static int __devinit abituguru_probe(struct platform_device *pdev) /* Detect number of sensors and fill the sysfs attr for bank2 (fans) */ abituguru_detect_no_bank2_sensors(data); for (i = 0; i < data->bank2_sensors; i++) { - for (j = 0; j < 6; j++) { - const char *name_templ = abituguru_sysfs_fan_templ[j]. - dev_attr.attr.name; + for (j = 0; j < ARRAY_SIZE(abituguru_sysfs_fan_templ); j++) { + used = snprintf(sysfs_filename, sysfs_names_free, + abituguru_sysfs_fan_templ[j].dev_attr.attr.name, + i + 1) + 1; data->sysfs_attr[sysfs_attr_i] = abituguru_sysfs_fan_templ[j]; data->sysfs_attr[sysfs_attr_i].dev_attr.attr.name = sysfs_filename; - sysfs_filename += sprintf(sysfs_filename, name_templ, - i + 1) + 1; data->sysfs_attr[sysfs_attr_i].index = i; + sysfs_filename += used; + sysfs_names_free -= used; sysfs_attr_i++; } } /* Detect number of sensors and fill the sysfs attr for pwms */ abituguru_detect_no_pwms(data); for (i = 0; i < data->pwms; i++) { - for (j = 0; j < 6; j++) { - const char *name_templ = abituguru_sysfs_pwm_templ[j]. - dev_attr.attr.name; + for (j = 0; j < ARRAY_SIZE(abituguru_sysfs_pwm_templ); j++) { + used = snprintf(sysfs_filename, sysfs_names_free, + abituguru_sysfs_pwm_templ[j].dev_attr.attr.name, + i + 1) + 1; data->sysfs_attr[sysfs_attr_i] = abituguru_sysfs_pwm_templ[j]; data->sysfs_attr[sysfs_attr_i].dev_attr.attr.name = sysfs_filename; - sysfs_filename += sprintf(sysfs_filename, name_templ, - i + 1) + 1; data->sysfs_attr[sysfs_attr_i].index = i; + sysfs_filename += used; + sysfs_names_free -= used; sysfs_attr_i++; } } - /* Last add any "generic" entries to sysfs */ - for (i = 0; i < ARRAY_SIZE(abituguru_sysfs_attr); i++) { - data->sysfs_attr[sysfs_attr_i] = abituguru_sysfs_attr[i]; - sysfs_attr_i++; + /* Fail safe check, this should never happen! */ + if (sysfs_names_free < 0) { + printk(KERN_ERR ABIT_UGURU_NAME ": Fatal error ran out of " + "space for sysfs attr names. This should never " + "happen please report to the abituguru maintainer " + "(see MAINTAINERS)\n"); + res = -ENAMETOOLONG; + goto abituguru_probe_error; } printk(KERN_INFO ABIT_UGURU_NAME ": found Abit uGuru\n"); /* Register sysfs hooks */ data->class_dev = hwmon_device_register(&pdev->dev); if (IS_ERR(data->class_dev)) { - kfree(data); - return PTR_ERR(data->class_dev); + res = PTR_ERR(data->class_dev); + goto abituguru_probe_error; } for (i = 0; i < sysfs_attr_i; i++) device_create_file(&pdev->dev, &data->sysfs_attr[i].dev_attr); + for (i = 0; i < ARRAY_SIZE(abituguru_sysfs_attr); i++) + device_create_file(&pdev->dev, + &abituguru_sysfs_attr[i].dev_attr); return 0; + +abituguru_probe_error: + kfree(data); + return res; } static int __devexit abituguru_remove(struct platform_device *pdev) @@ -1244,7 +1269,7 @@ static struct abituguru_data *abituguru_update_device(struct device *dev) if ((err = abituguru_read(data, ABIT_UGURU_ALARM_BANK, 0, data->alarms, 3, 0)) != 3) goto LEAVE_UPDATE; - for (i = 0; i < 16; i++) { + for (i = 0; i < ABIT_UGURU_MAX_BANK1_SENSORS; i++) { if ((err = abituguru_read(data, ABIT_UGURU_SENSOR_BANK1, i, &data->bank1_value[i], 1, 0)) != 1) -- cgit v1.2.3 From b7c066044f4355d9fbe1ac45e03303b78d21e8d4 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 4 Jun 2006 20:24:11 +0200 Subject: [PATCH] abituguru: Fix fan detection One of my testers had a problem where the driver only saw 2 of the 4 fan sensors his uGuru has, this fixes this. -accept 0x40 (bit 6) being high as a valid fan sensor setting for all fans not just fan 1, I have a feeling this bit indicates whether or not a fan is actually connected . Signed-off-by: Hans de Goede Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/abituguru.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/hwmon/abituguru.c b/drivers/hwmon/abituguru.c index ab80b418bd6..59122cc0a50 100644 --- a/drivers/hwmon/abituguru.c +++ b/drivers/hwmon/abituguru.c @@ -529,9 +529,8 @@ abituguru_detect_no_bank2_sensors(struct abituguru_data *data) -0x08 enable beep -0x01 enable alarm All other bits should be 0, but on some motherboards - 0x40 (bit 6) is also high, at least for fan1 */ - if ((!i && (data->bank2_settings[i][0] & ~0xC9)) || - (i && (data->bank2_settings[i][0] & ~0x89))) { + 0x40 (bit 6) is also high for some of the fans?? */ + if (data->bank2_settings[i][0] & ~0xC9) { ABIT_UGURU_DEBUG(2, " bank2 sensor %d does not seem " "to be a fan sensor: settings[0] = %02X\n", i, (unsigned int)data->bank2_settings[i][0]); -- cgit v1.2.3 From 1ded969fb97fba33e7310ef95f0b3e3123d4d92a Mon Sep 17 00:00:00 2001 From: Peter Korsgaard Date: Mon, 12 Jun 2006 21:40:53 +0200 Subject: [PATCH] i2c-ocores: Minor cleanups Minor cleanup to the i2c-ocores driver. Peter Korsgaard will maintain the i2c-ocores driver. Signed-off-by: Peter Korsgaard Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 6 ++++++ drivers/i2c/busses/i2c-ocores.c | 6 ++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 7e3a38eeccb..f4cf0148c90 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2063,6 +2063,12 @@ M: adaplas@pol.net L: linux-fbdev-devel@lists.sourceforge.net S: Maintained +OPENCORES I2C BUS DRIVER +P: Peter Korsgaard +M: jacmet@sunsite.dk +L: lm-sensors@lm-sensors.org +S: Maintained + ORACLE CLUSTER FILESYSTEM 2 (OCFS2) P: Mark Fasheh M: mark.fasheh@oracle.com diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c index d5c0610bfe6..592824087c4 100644 --- a/drivers/i2c/busses/i2c-ocores.c +++ b/drivers/i2c/busses/i2c-ocores.c @@ -38,8 +38,8 @@ struct ocores_i2c { #define OCI2C_PREHIGH 1 #define OCI2C_CONTROL 2 #define OCI2C_DATA 3 -#define OCI2C_CMD 4 -#define OCI2C_STATUS 4 +#define OCI2C_CMD 4 /* write only */ +#define OCI2C_STATUS 4 /* read only, same address as OCI2C_CMD */ #define OCI2C_CTRL_IEN 0x40 #define OCI2C_CTRL_EN 0x80 @@ -209,8 +209,6 @@ static struct i2c_adapter ocores_adapter = { .name = "i2c-ocores", .class = I2C_CLASS_HWMON, .algo = &ocores_algorithm, - .timeout = 2, - .retries = 1, }; -- cgit v1.2.3 From 46f5ed753fac512f73069bd07455555b41a8a06e Mon Sep 17 00:00:00 2001 From: Krzysztof Halasa Date: Mon, 12 Jun 2006 21:42:20 +0200 Subject: [PATCH] i2c: Mark block write buffers as const The attached patch marks i2c_smbus_write_block_data() and i2c_smbus_write_i2c_block_data() buffers as const. Signed-off-by: Krzysztof Halasa Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/i2c-core.c | 4 ++-- include/linux/i2c.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 45e2cdf5473..a45155f799d 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -916,7 +916,7 @@ s32 i2c_smbus_write_word_data(struct i2c_client *client, u8 command, u16 value) } s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command, - u8 length, u8 *values) + u8 length, const u8 *values) { union i2c_smbus_data data; @@ -944,7 +944,7 @@ s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, u8 *val } s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client, u8 command, - u8 length, u8 *values) + u8 length, const u8 *values) { union i2c_smbus_data data; diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 0510430e00d..526ddc8eecf 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -97,13 +97,13 @@ extern s32 i2c_smbus_write_word_data(struct i2c_client * client, u8 command, u16 value); extern s32 i2c_smbus_write_block_data(struct i2c_client * client, u8 command, u8 length, - u8 *values); + const u8 *values); /* Returns the number of read bytes */ extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client, u8 command, u8 *values); extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client * client, u8 command, u8 length, - u8 *values); + const u8 *values); /* * A driver is capable of handling one or more physical devices present on -- cgit v1.2.3 From 80cd3a8769c66203d55cdf635390bdcebd742091 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Mon, 12 Jun 2006 21:44:28 +0200 Subject: [PATCH] scx200_acb: Use PCI I/O resource when appropriate On the CS5535 and CS5536, the I/O resource is allocated through PCI, so use that instead of using the MSR backdoor. Signed-off-by: Jordan Crouse Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/scx200_acb.c | 200 +++++++++++++++++++++++++++++----------- 1 file changed, 147 insertions(+), 53 deletions(-) diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c index 766cc969c4d..09b4586f3bd 100644 --- a/drivers/i2c/busses/scx200_acb.c +++ b/drivers/i2c/busses/scx200_acb.c @@ -33,7 +33,6 @@ #include #include #include -#include #include @@ -85,6 +84,10 @@ struct scx200_acb_iface { u8 *ptr; char needs_reset; unsigned len; + + /* PCI device info */ + struct pci_dev *pdev; + int bar; }; /* Register Definitions */ @@ -417,17 +420,16 @@ static int scx200_acb_probe(struct scx200_acb_iface *iface) return 0; } -static int __init scx200_acb_create(const char *text, int base, int index) +static __init struct scx200_acb_iface *scx200_create_iface(const char *text, + int index) { struct scx200_acb_iface *iface; struct i2c_adapter *adapter; - int rc; iface = kzalloc(sizeof(*iface), GFP_KERNEL); if (!iface) { printk(KERN_ERR NAME ": can't allocate memory\n"); - rc = -ENOMEM; - goto errout; + return NULL; } adapter = &iface->adapter; @@ -440,26 +442,27 @@ static int __init scx200_acb_create(const char *text, int base, int index) mutex_init(&iface->mutex); - if (!request_region(base, 8, adapter->name)) { - printk(KERN_ERR NAME ": can't allocate io 0x%x-0x%x\n", - base, base + 8-1); - rc = -EBUSY; - goto errout_free; - } - iface->base = base; + return iface; +} + +static int __init scx200_acb_create(struct scx200_acb_iface *iface) +{ + struct i2c_adapter *adapter; + int rc; + + adapter = &iface->adapter; rc = scx200_acb_probe(iface); if (rc) { printk(KERN_WARNING NAME ": probe failed\n"); - goto errout_release; + return rc; } scx200_acb_reset(iface); if (i2c_add_adapter(adapter) < 0) { printk(KERN_ERR NAME ": failed to register\n"); - rc = -ENODEV; - goto errout_release; + return -ENODEV; } down(&scx200_acb_list_mutex); @@ -468,64 +471,148 @@ static int __init scx200_acb_create(const char *text, int base, int index) up(&scx200_acb_list_mutex); return 0; +} - errout_release: - release_region(iface->base, 8); +static __init int scx200_create_pci(const char *text, struct pci_dev *pdev, + int bar) +{ + struct scx200_acb_iface *iface; + int rc; + + iface = scx200_create_iface(text, 0); + + if (iface == NULL) + return -ENOMEM; + + iface->pdev = pdev; + iface->bar = bar; + + pci_enable_device_bars(iface->pdev, 1 << iface->bar); + + rc = pci_request_region(iface->pdev, iface->bar, iface->adapter.name); + + if (rc != 0) { + printk(KERN_ERR NAME ": can't allocate PCI BAR %d\n", + iface->bar); + goto errout_free; + } + + iface->base = pci_resource_start(iface->pdev, iface->bar); + rc = scx200_acb_create(iface); + + if (rc == 0) + return 0; + + pci_release_region(iface->pdev, iface->bar); + pci_dev_put(iface->pdev); errout_free: kfree(iface); - errout: return rc; } -static struct pci_device_id scx200[] = { - { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_BRIDGE) }, - { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_BRIDGE) }, - { }, -}; +static int __init scx200_create_isa(const char *text, unsigned long base, + int index) +{ + struct scx200_acb_iface *iface; + int rc; + + iface = scx200_create_iface(text, index); + + if (iface == NULL) + return -ENOMEM; + + if (request_region(base, 8, iface->adapter.name) == 0) { + printk(KERN_ERR NAME ": can't allocate io 0x%lx-0x%lx\n", + base, base + 8 - 1); + rc = -EBUSY; + goto errout_free; + } + + iface->base = base; + rc = scx200_acb_create(iface); + + if (rc == 0) + return 0; -static struct pci_device_id divil_pci[] = { - { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_ISA) }, - { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA) }, - { } /* NULL entry */ + release_region(base, 8); + errout_free: + kfree(iface); + return rc; +} + +/* Driver data is an index into the scx200_data array that indicates + * the name and the BAR where the I/O address resource is located. ISA + * devices are flagged with a bar value of -1 */ + +static struct pci_device_id scx200_pci[] = { + { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_BRIDGE), + .driver_data = 0 }, + { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_BRIDGE), + .driver_data = 0 }, + { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_ISA), + .driver_data = 1 }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA), + .driver_data = 2 } }; -#define MSR_LBAR_SMB 0x5140000B +static struct { + const char *name; + int bar; +} scx200_data[] = { + { "SCx200", -1 }, + { "CS5535", 0 }, + { "CS5536", 0 } +}; -static __init int scx200_add_cs553x(void) +static __init int scx200_scan_pci(void) { - u32 low, hi; - u32 smb_base; - - /* Grab & reserve the SMB I/O range */ - rdmsr(MSR_LBAR_SMB, low, hi); + int data, dev; + int rc = -ENODEV; + struct pci_dev *pdev; + + for(dev = 0; dev < ARRAY_SIZE(scx200_pci); dev++) { + pdev = pci_get_device(scx200_pci[dev].vendor, + scx200_pci[dev].device, NULL); + + if (pdev == NULL) + continue; + + data = scx200_pci[dev].driver_data; + + /* if .bar is greater or equal to zero, this is a + * PCI device - otherwise, we assume + that the ports are ISA based + */ + + if (scx200_data[data].bar >= 0) + rc = scx200_create_pci(scx200_data[data].name, pdev, + scx200_data[data].bar); + else { + int i; + + for (i = 0; i < MAX_DEVICES; ++i) { + if (base[i] == 0) + continue; + + rc = scx200_create_isa(scx200_data[data].name, + base[i], + i); + } + } - /* Check the IO mask and whether SMB is enabled */ - if (hi != 0x0000F001) { - printk(KERN_WARNING NAME ": SMBus not enabled\n"); - return -ENODEV; + break; } - /* SMBus IO size is 8 bytes */ - smb_base = low & 0x0000FFF8; - - return scx200_acb_create("CS5535", smb_base, 0); + return rc; } static int __init scx200_acb_init(void) { - int i; - int rc = -ENODEV; + int rc; pr_debug(NAME ": NatSemi SCx200 ACCESS.bus Driver\n"); - /* Verify that this really is a SCx200 processor */ - if (pci_dev_present(scx200)) { - for (i = 0; i < MAX_DEVICES; ++i) { - if (base[i] > 0) - rc = scx200_acb_create("SCx200", base[i], i); - } - } else if (pci_dev_present(divil_pci)) - rc = scx200_add_cs553x(); + rc = scx200_scan_pci(); /* If at least one bus was created, init must succeed */ if (scx200_acb_list) @@ -543,7 +630,14 @@ static void __exit scx200_acb_cleanup(void) up(&scx200_acb_list_mutex); i2c_del_adapter(&iface->adapter); - release_region(iface->base, 8); + + if (iface->pdev) { + pci_release_region(iface->pdev, iface->bar); + pci_dev_put(iface->pdev); + } + else + release_region(iface->base, 8); + kfree(iface); down(&scx200_acb_list_mutex); } -- cgit v1.2.3 From 9917392608c6d8b8952bce9f7b5867b1e9149235 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 12 Jun 2006 21:46:04 +0200 Subject: [PATCH] scx200_acb: Mark scx200_acb_probe __init In i2c bus driver scx200_acb, function scx200_acb_probe can be tagged __init. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/scx200_acb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c index 09b4586f3bd..22a3eda0416 100644 --- a/drivers/i2c/busses/scx200_acb.c +++ b/drivers/i2c/busses/scx200_acb.c @@ -384,7 +384,7 @@ static struct i2c_algorithm scx200_acb_algorithm = { static struct scx200_acb_iface *scx200_acb_list; static DECLARE_MUTEX(scx200_acb_list_mutex); -static int scx200_acb_probe(struct scx200_acb_iface *iface) +static __init int scx200_acb_probe(struct scx200_acb_iface *iface) { u8 val; -- cgit v1.2.3 From 62aaa288ab0425b058fd337c5135a32e8c1aeace Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 12 Jun 2006 21:48:08 +0200 Subject: [PATCH] scx200_acb: Documentation update Documentation update for the scx200_acb driver. Hopefully this will help future users. References: [lm-sensors] Support of i2c-nscacb (April, May 2005) http://lists.lm-sensors.org/pipermail/lm-sensors/2005-April/011756.html http://lists.lm-sensors.org/pipermail/lm-sensors/2005-May/012043.html [lm-sensors] making a geode i2c slave driver (April 2006) http://lists.lm-sensors.org/pipermail/lm-sensors/2006-April/015998.html Kernel bug #6445 http://bugzilla.kernel.org/show_bug.cgi?id=6445 Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- Documentation/i2c/busses/scx200_acb | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/Documentation/i2c/busses/scx200_acb b/Documentation/i2c/busses/scx200_acb index f50e69981ec..7c07883d4df 100644 --- a/Documentation/i2c/busses/scx200_acb +++ b/Documentation/i2c/busses/scx200_acb @@ -2,14 +2,31 @@ Kernel driver scx200_acb Author: Christer Weinigel +The driver supersedes the older, never merged driver named i2c-nscacb. + Module Parameters ----------------- -* base: int +* base: up to 4 ints Base addresses for the ACCESS.bus controllers on SCx200 and SC1100 devices + By default the driver uses two base addresses 0x820 and 0x840. + If you want only one base address, specify the second as 0 so as to + override this default. + Description ----------- Enable the use of the ACCESS.bus controller on the Geode SCx200 and SC1100 processors and the CS5535 and CS5536 Geode companion devices. + +Device-specific notes +--------------------- + +The SC1100 WRAP boards are known to use base addresses 0x810 and 0x820. +If the scx200_acb driver is built into the kernel, add the following +parameter to your boot command line: + scx200_acb.base=0x810,0x820 +If the scx200_acb driver is built as a module, add the following line to +the file /etc/modprobe.conf instead: + options scx200_acb base=0x810,0x820 -- cgit v1.2.3 From 397e2f66a23469e2b8a13b764cb2d9ff2444ad5a Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 12 Jun 2006 21:49:36 +0200 Subject: [PATCH] i2c-i801: Fix block transaction poll loops i2c-i801: Fix block transaction poll loops Two of the three poll loops have the poll and sleep swapped, causing an extra sleep to occur after the polled condition is fulfilled. In practice, this doubles the amount of sleep time for every block transaction. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/i2c-i801.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index dfca7493362..4396dc91d5f 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -334,8 +334,8 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write, /* We will always wait for a fraction of a second! */ timeout = 0; do { - temp = inb_p(SMBHSTSTS); msleep(1); + temp = inb_p(SMBHSTSTS); } while ((!(temp & 0x80)) && (timeout++ < MAX_TIMEOUT)); @@ -393,8 +393,8 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write, /* wait for INTR bit as advised by Intel */ timeout = 0; do { - temp = inb_p(SMBHSTSTS); msleep(1); + temp = inb_p(SMBHSTSTS); } while ((!(temp & 0x02)) && (timeout++ < MAX_TIMEOUT)); -- cgit v1.2.3 From d8db8f98562c1e358e42503bb920f75f15a5c6d2 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 12 Jun 2006 21:50:11 +0200 Subject: [PATCH] i2c-i801: Remove force_addr parameter i2c-i801: Remove force_addr parameter Remove the force_addr module parameter. It doesn't appear to ever have been needed, and PCI resources shouldn't be arbitrarily changed anyway. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- Documentation/i2c/busses/i2c-i801 | 3 +-- drivers/i2c/busses/i2c-i801.c | 35 +++++++---------------------------- 2 files changed, 8 insertions(+), 30 deletions(-) diff --git a/Documentation/i2c/busses/i2c-i801 b/Documentation/i2c/busses/i2c-i801 index fd4b2712d57..e46c2345824 100644 --- a/Documentation/i2c/busses/i2c-i801 +++ b/Documentation/i2c/busses/i2c-i801 @@ -21,8 +21,7 @@ Authors: Module Parameters ----------------- -* force_addr: int - Forcibly enable the ICH at the given address. EXTREMELY DANGEROUS! +None. Description diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 4396dc91d5f..0d5374cce9c 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -92,15 +92,6 @@ #define I801_START 0x40 #define I801_PEC_EN 0x80 /* ICH4 only */ -/* insmod parameters */ - -/* If force_addr is set to anything different from 0, we forcibly enable - the I801 at the given address. VERY DANGEROUS! */ -static u16 force_addr; -module_param(force_addr, ushort, 0); -MODULE_PARM_DESC(force_addr, - "Forcibly enable the I801 at the given address. " - "EXTREMELY DANGEROUS!"); static int i801_transaction(void); static int i801_block_transaction(union i2c_smbus_data *data, char read_write, @@ -129,16 +120,12 @@ static int i801_setup(struct pci_dev *dev) isich4 = 0; /* Determine the address of the SMBus areas */ - if (force_addr) { - i801_smba = force_addr & 0xfff0; - } else { - pci_read_config_word(I801_dev, SMBBA, &i801_smba); - i801_smba &= 0xfff0; - if(i801_smba == 0) { - dev_err(&dev->dev, "SMB base address uninitialized " - "- upgrade BIOS or use force_addr=0xaddr\n"); - return -ENODEV; - } + pci_read_config_word(I801_dev, SMBBA, &i801_smba); + i801_smba &= 0xfff0; + if (!i801_smba) { + dev_err(&dev->dev, "SMBus base address uninitialized, " + "upgrade BIOS\n"); + return -ENODEV; } if (!request_region(i801_smba, (isich4 ? 16 : 8), i801_driver.name)) { @@ -152,15 +139,7 @@ static int i801_setup(struct pci_dev *dev) temp &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */ pci_write_config_byte(I801_dev, SMBHSTCFG, temp); - /* If force_addr is set, we program the new address here. Just to make - sure, we disable the device first. */ - if (force_addr) { - pci_write_config_byte(I801_dev, SMBHSTCFG, temp & 0xfe); - pci_write_config_word(I801_dev, SMBBA, i801_smba); - pci_write_config_byte(I801_dev, SMBHSTCFG, temp | 0x01); - dev_warn(&dev->dev, "WARNING: I801 SMBus interface set to " - "new address %04x!\n", i801_smba); - } else if ((temp & 1) == 0) { + if (!(temp & 1)) { pci_write_config_byte(I801_dev, SMBHSTCFG, temp | 1); dev_warn(&dev->dev, "enabling SMBus device\n"); } -- cgit v1.2.3 From 520e64d5c081c76b77b4ee87d241cd3e40edc43a Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 12 Jun 2006 21:51:20 +0200 Subject: [PATCH] i2c-i801: Remove PCI function check i2c-i801: Remove PCI function check Remove the PCI function number check when probing devices. This check is redundant, each function has a separate PCI device ID, so checking for that ID is sufficient. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/i2c-i801.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 0d5374cce9c..b651493375c 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -107,10 +107,6 @@ static int i801_setup(struct pci_dev *dev) int error_return = 0; unsigned char temp; - /* Note: we keep on searching until we have found 'function 3' */ - if(PCI_FUNC(dev->devfn) != 3) - return -ENODEV; - I801_dev = dev; if ((dev->device == PCI_DEVICE_ID_INTEL_82801DB_3) || (dev->device == PCI_DEVICE_ID_INTEL_82801EB_3) || -- cgit v1.2.3 From 455f332323a17446fb66ea7b2f65f2751f1a3f06 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 12 Jun 2006 21:52:02 +0200 Subject: [PATCH] i2c-i801: Cleanups i2c-i801: Cleanups Various cleanups to the i2c-i801 driver: * Fix documentation file and self file name references. * i801_setup can be marked __devinit. * Drop useless error local variable and label in i801_setup. * Avoid a double PCI configuration register write in some cases. * Use symbolic names for SMBHSTCFG bits. * Transmit the error code returned by i801_setup instead of forcing it to an arbitrary value. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/i2c-i801.c | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index b651493375c..b9e6fac8142 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -1,5 +1,5 @@ /* - i801.c - Part of lm_sensors, Linux kernel modules for hardware + i2c-i801.c - Part of lm_sensors, Linux kernel modules for hardware monitoring Copyright (c) 1998 - 2002 Frodo Looijaard , Philip Edelbrock , and Mark D. Studebaker @@ -36,7 +36,7 @@ This driver supports several versions of Intel's I/O Controller Hubs (ICH). For SMBus support, they are similar to the PIIX4 and are part of Intel's '810' and other chipsets. - See the doc/busses/i2c-i801 file for details. + See the file Documentation/i2c/busses/i2c-i801 for details. I2C Block Read and Process Call are not supported. */ @@ -102,9 +102,8 @@ static struct pci_driver i801_driver; static struct pci_dev *I801_dev; static int isich4; -static int i801_setup(struct pci_dev *dev) +static int __devinit i801_setup(struct pci_dev *dev) { - int error_return = 0; unsigned char temp; I801_dev = dev; @@ -115,7 +114,7 @@ static int i801_setup(struct pci_dev *dev) else isich4 = 0; - /* Determine the address of the SMBus areas */ + /* Determine the address of the SMBus area */ pci_read_config_word(I801_dev, SMBBA, &i801_smba); i801_smba &= 0xfff0; if (!i801_smba) { @@ -127,20 +126,18 @@ static int i801_setup(struct pci_dev *dev) if (!request_region(i801_smba, (isich4 ? 16 : 8), i801_driver.name)) { dev_err(&dev->dev, "I801_smb region 0x%x already in use!\n", i801_smba); - error_return = -EBUSY; - goto END; + return -EBUSY; } pci_read_config_byte(I801_dev, SMBHSTCFG, &temp); temp &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */ - pci_write_config_byte(I801_dev, SMBHSTCFG, temp); - - if (!(temp & 1)) { - pci_write_config_byte(I801_dev, SMBHSTCFG, temp | 1); + if (!(temp & SMBHSTCFG_HST_EN)) { dev_warn(&dev->dev, "enabling SMBus device\n"); + temp |= SMBHSTCFG_HST_EN; } + pci_write_config_byte(I801_dev, SMBHSTCFG, temp); - if (temp & 0x02) + if (temp & SMBHSTCFG_SMB_SMI_EN) dev_dbg(&dev->dev, "I801 using Interrupt SMI# for SMBus.\n"); else dev_dbg(&dev->dev, "I801 using PCI Interrupt for SMBus.\n"); @@ -149,8 +146,7 @@ static int i801_setup(struct pci_dev *dev) dev_dbg(&dev->dev, "SMBREV = 0x%X\n", temp); dev_dbg(&dev->dev, "I801_smba = 0x%X\n", i801_smba); -END: - return error_return; + return 0; } static int i801_transaction(void) @@ -516,12 +512,10 @@ MODULE_DEVICE_TABLE (pci, i801_ids); static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id) { + int err; - if (i801_setup(dev)) { - dev_warn(&dev->dev, - "I801 not detected, module not inserted.\n"); - return -ENODEV; - } + if ((err = i801_setup(dev))) + return err; /* set up the driverfs linkage to our parent device */ i801_adapter.dev.parent = &dev->dev; -- cgit v1.2.3 From 6dcc19dfbc84b2ea5428711b7a47146b5b1788bb Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 12 Jun 2006 21:53:02 +0200 Subject: [PATCH] i2c-i801: Better pci subsystem integration i2c-i801: Better pci subsystem integration Integrate the i2c-i801 driver better with the pci subsystem, by calling pci_{enable,disable}_device and requesting the I/O region by BAR rather than direct configuration space access. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/i2c-i801.c | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index b9e6fac8142..94a30f5de77 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -66,7 +66,7 @@ #define SMBAUXCTL (13 + i801_smba) /* ICH4 only */ /* PCI Address Constants */ -#define SMBBA 0x020 +#define SMBBAR 4 #define SMBHSTCFG 0x040 #define SMBREV 0x008 @@ -97,7 +97,7 @@ static int i801_transaction(void); static int i801_block_transaction(union i2c_smbus_data *data, char read_write, int command, int hwpec); -static unsigned short i801_smba; +static unsigned long i801_smba; static struct pci_driver i801_driver; static struct pci_dev *I801_dev; static int isich4; @@ -105,6 +105,7 @@ static int isich4; static int __devinit i801_setup(struct pci_dev *dev) { unsigned char temp; + int err; I801_dev = dev; if ((dev->device == PCI_DEVICE_ID_INTEL_82801DB_3) || @@ -114,19 +115,28 @@ static int __devinit i801_setup(struct pci_dev *dev) else isich4 = 0; + err = pci_enable_device(dev); + if (err) { + dev_err(&dev->dev, "Failed to enable SMBus device (%d)\n", + err); + goto exit; + } + /* Determine the address of the SMBus area */ - pci_read_config_word(I801_dev, SMBBA, &i801_smba); - i801_smba &= 0xfff0; + i801_smba = pci_resource_start(dev, SMBBAR); if (!i801_smba) { dev_err(&dev->dev, "SMBus base address uninitialized, " "upgrade BIOS\n"); - return -ENODEV; + err = -ENODEV; + goto exit_disable; } - if (!request_region(i801_smba, (isich4 ? 16 : 8), i801_driver.name)) { - dev_err(&dev->dev, "I801_smb region 0x%x already in use!\n", - i801_smba); - return -EBUSY; + err = pci_request_region(dev, SMBBAR, i801_driver.name); + if (err) { + dev_err(&dev->dev, "Failed to request SMBus region " + "0x%lx-0x%lx\n", i801_smba, + pci_resource_end(dev, SMBBAR)); + goto exit_disable; } pci_read_config_byte(I801_dev, SMBHSTCFG, &temp); @@ -147,6 +157,11 @@ static int __devinit i801_setup(struct pci_dev *dev) dev_dbg(&dev->dev, "I801_smba = 0x%X\n", i801_smba); return 0; + +exit_disable: + pci_disable_device(dev); +exit: + return err; } static int i801_transaction(void) @@ -521,14 +536,15 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id i801_adapter.dev.parent = &dev->dev; snprintf(i801_adapter.name, I2C_NAME_SIZE, - "SMBus I801 adapter at %04x", i801_smba); + "SMBus I801 adapter at %04lx", i801_smba); return i2c_add_adapter(&i801_adapter); } static void __devexit i801_remove(struct pci_dev *dev) { i2c_del_adapter(&i801_adapter); - release_region(i801_smba, (isich4 ? 16 : 8)); + pci_release_region(dev, SMBBAR); + pci_disable_device(dev); } static struct pci_driver i801_driver = { -- cgit v1.2.3 From 02dd7ae2892e5ceff111d032769c78d3377df970 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 12 Jun 2006 21:53:41 +0200 Subject: [PATCH] i2c-i801: Merge setup function i2c-i801: Merge setup function Merge i801_setup into i801_probe, as it doesn't make much sense to have them split. This lets us handle errors better. Christopher Hellwig had been suggesting this back in March 2003 when the driver was merged. Also drop two useless debug messages (revision and base address can be obtained from lspci, procfs or sysfs.) Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/i2c-i801.c | 121 +++++++++++++++++++----------------------- 1 file changed, 55 insertions(+), 66 deletions(-) diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 94a30f5de77..3e0d04d5a80 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -68,7 +68,6 @@ /* PCI Address Constants */ #define SMBBAR 4 #define SMBHSTCFG 0x040 -#define SMBREV 0x008 /* Host configuration bits for SMBHSTCFG */ #define SMBHSTCFG_HST_EN 1 @@ -102,68 +101,6 @@ static struct pci_driver i801_driver; static struct pci_dev *I801_dev; static int isich4; -static int __devinit i801_setup(struct pci_dev *dev) -{ - unsigned char temp; - int err; - - I801_dev = dev; - if ((dev->device == PCI_DEVICE_ID_INTEL_82801DB_3) || - (dev->device == PCI_DEVICE_ID_INTEL_82801EB_3) || - (dev->device == PCI_DEVICE_ID_INTEL_ESB_4)) - isich4 = 1; - else - isich4 = 0; - - err = pci_enable_device(dev); - if (err) { - dev_err(&dev->dev, "Failed to enable SMBus device (%d)\n", - err); - goto exit; - } - - /* Determine the address of the SMBus area */ - i801_smba = pci_resource_start(dev, SMBBAR); - if (!i801_smba) { - dev_err(&dev->dev, "SMBus base address uninitialized, " - "upgrade BIOS\n"); - err = -ENODEV; - goto exit_disable; - } - - err = pci_request_region(dev, SMBBAR, i801_driver.name); - if (err) { - dev_err(&dev->dev, "Failed to request SMBus region " - "0x%lx-0x%lx\n", i801_smba, - pci_resource_end(dev, SMBBAR)); - goto exit_disable; - } - - pci_read_config_byte(I801_dev, SMBHSTCFG, &temp); - temp &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */ - if (!(temp & SMBHSTCFG_HST_EN)) { - dev_warn(&dev->dev, "enabling SMBus device\n"); - temp |= SMBHSTCFG_HST_EN; - } - pci_write_config_byte(I801_dev, SMBHSTCFG, temp); - - if (temp & SMBHSTCFG_SMB_SMI_EN) - dev_dbg(&dev->dev, "I801 using Interrupt SMI# for SMBus.\n"); - else - dev_dbg(&dev->dev, "I801 using PCI Interrupt for SMBus.\n"); - - pci_read_config_byte(I801_dev, SMBREV, &temp); - dev_dbg(&dev->dev, "SMBREV = 0x%X\n", temp); - dev_dbg(&dev->dev, "I801_smba = 0x%X\n", i801_smba); - - return 0; - -exit_disable: - pci_disable_device(dev); -exit: - return err; -} - static int i801_transaction(void) { int temp; @@ -527,17 +464,69 @@ MODULE_DEVICE_TABLE (pci, i801_ids); static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id) { + unsigned char temp; int err; - if ((err = i801_setup(dev))) - return err; + I801_dev = dev; + if ((dev->device == PCI_DEVICE_ID_INTEL_82801DB_3) || + (dev->device == PCI_DEVICE_ID_INTEL_82801EB_3) || + (dev->device == PCI_DEVICE_ID_INTEL_ESB_4)) + isich4 = 1; + else + isich4 = 0; + + err = pci_enable_device(dev); + if (err) { + dev_err(&dev->dev, "Failed to enable SMBus PCI device (%d)\n", + err); + goto exit; + } + + /* Determine the address of the SMBus area */ + i801_smba = pci_resource_start(dev, SMBBAR); + if (!i801_smba) { + dev_err(&dev->dev, "SMBus base address uninitialized, " + "upgrade BIOS\n"); + err = -ENODEV; + goto exit_disable; + } + + err = pci_request_region(dev, SMBBAR, i801_driver.name); + if (err) { + dev_err(&dev->dev, "Failed to request SMBus region " + "0x%lx-0x%lx\n", i801_smba, + pci_resource_end(dev, SMBBAR)); + goto exit_disable; + } + + pci_read_config_byte(I801_dev, SMBHSTCFG, &temp); + temp &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */ + if (!(temp & SMBHSTCFG_HST_EN)) { + dev_info(&dev->dev, "Enabling SMBus device\n"); + temp |= SMBHSTCFG_HST_EN; + } + pci_write_config_byte(I801_dev, SMBHSTCFG, temp); + + if (temp & SMBHSTCFG_SMB_SMI_EN) + dev_dbg(&dev->dev, "SMBus using interrupt SMI#\n"); + else + dev_dbg(&dev->dev, "SMBus using PCI Interrupt\n"); /* set up the driverfs linkage to our parent device */ i801_adapter.dev.parent = &dev->dev; snprintf(i801_adapter.name, I2C_NAME_SIZE, "SMBus I801 adapter at %04lx", i801_smba); - return i2c_add_adapter(&i801_adapter); + err = i2c_add_adapter(&i801_adapter); + if (err) { + dev_err(&dev->dev, "Failed to add SMBus adapter\n"); + goto exit_disable; + } + +exit_disable: + pci_disable_device(dev); +exit: + return err; } static void __devexit i801_remove(struct pci_dev *dev) -- cgit v1.2.3 From 060b2f5584bf3bbb0268c83c24d5a506780fb702 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 12 Jun 2006 21:55:28 +0200 Subject: [PATCH] hwmon: Fix the Kconfig header Hardware monitoring chips don't have to be on the I2C bus. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 6fb93d63bd8..43e1f082f7b 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -1,5 +1,5 @@ # -# I2C Sensor chip drivers configuration +# Hardware monitoring chip drivers configuration # menu "Hardware Monitoring support" -- cgit v1.2.3 From e1a8e913f97e36cc5a23a24a8b4717e84998f13c Mon Sep 17 00:00:00 2001 From: Kaiwan N Billimoria Date: Mon, 12 Jun 2006 22:00:05 +0200 Subject: [PATCH] lm70: New hardware monitoring driver This driver implements support for the National Semiconductor LM70 temperature sensor. The LM70 temperature sensor chip supports a single temperature sensor. It communicates with a host processor (or microcontroller) via an SPI/Microwire Bus interface. Communication with the LM70 is simple: when the temperature is to be sensed, the driver accesses the LM70 using SPI communication: 16 SCLK cycles comprise the MOSI/MISO loop. At the end of the transfer, the 11-bit 2's complement digital temperature (sent via the SIO line), is available in the driver for interpretation. This driver makes use of the kernel's in-core SPI support. Signed-off-by: Kaiwan N Billimoria Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- Documentation/hwmon/lm70 | 31 +++++++++ drivers/hwmon/Kconfig | 10 +++ drivers/hwmon/Makefile | 1 + drivers/hwmon/lm70.c | 165 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 207 insertions(+) create mode 100644 Documentation/hwmon/lm70 create mode 100644 drivers/hwmon/lm70.c diff --git a/Documentation/hwmon/lm70 b/Documentation/hwmon/lm70 new file mode 100644 index 00000000000..2bdd3feebf5 --- /dev/null +++ b/Documentation/hwmon/lm70 @@ -0,0 +1,31 @@ +Kernel driver lm70 +================== + +Supported chip: + * National Semiconductor LM70 + Datasheet: http://www.national.com/pf/LM/LM70.html + +Author: + Kaiwan N Billimoria + +Description +----------- + +This driver implements support for the National Semiconductor LM70 +temperature sensor. + +The LM70 temperature sensor chip supports a single temperature sensor. +It communicates with a host processor (or microcontroller) via an +SPI/Microwire Bus interface. + +Communication with the LM70 is simple: when the temperature is to be sensed, +the driver accesses the LM70 using SPI communication: 16 SCLK cycles +comprise the MOSI/MISO loop. At the end of the transfer, the 11-bit 2's +complement digital temperature (sent via the SIO line), is available in the +driver for interpretation. This driver makes use of the kernel's in-core +SPI support. + +Thanks to +--------- +Jean Delvare for mentoring the hwmon-side driver +development. diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 43e1f082f7b..0e31a0c496e 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -204,6 +204,16 @@ config SENSORS_LM63 This driver can also be built as a module. If so, the module will be called lm63. +config SENSORS_LM70 + tristate "National Semiconductor LM70" + depends on HWMON && SPI_MASTER && EXPERIMENTAL + help + If you say yes here you get support for the National Semiconductor + LM70 digital temperature sensor chip. + + This driver can also be built as a module. If so, the module + will be called lm70. + config SENSORS_LM75 tristate "National Semiconductor LM75 and compatibles" depends on HWMON && I2C diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 5092999deb7..31415843a91 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -28,6 +28,7 @@ obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o obj-$(CONFIG_SENSORS_IT87) += it87.o obj-$(CONFIG_SENSORS_LM63) += lm63.o +obj-$(CONFIG_SENSORS_LM70) += lm70.o obj-$(CONFIG_SENSORS_LM75) += lm75.o obj-$(CONFIG_SENSORS_LM77) += lm77.o obj-$(CONFIG_SENSORS_LM78) += lm78.o diff --git a/drivers/hwmon/lm70.c b/drivers/hwmon/lm70.c new file mode 100644 index 00000000000..6ba84731b9c --- /dev/null +++ b/drivers/hwmon/lm70.c @@ -0,0 +1,165 @@ +/* + * lm70.c + * + * The LM70 is a temperature sensor chip from National Semiconductor (NS). + * Copyright (C) 2006 Kaiwan N Billimoria + * + * The LM70 communicates with a host processor via an SPI/Microwire Bus + * interface. The complete datasheet is available at National's website + * here: + * http://www.national.com/pf/LM/LM70.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "lm70" + +struct lm70 { + struct class_device *cdev; + struct semaphore sem; +}; + +/* sysfs hook function */ +static ssize_t lm70_sense_temp(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct spi_device *spi = to_spi_device(dev); + int status, val; + u8 rxbuf[2]; + s16 raw=0; + struct lm70 *p_lm70 = dev_get_drvdata(&spi->dev); + + if (down_interruptible(&p_lm70->sem)) + return -ERESTARTSYS; + + /* + * spi_read() requires a DMA-safe buffer; so we use + * spi_write_then_read(), transmitting 0 bytes. + */ + status = spi_write_then_read(spi, NULL, 0, &rxbuf[0], 2); + if (status < 0) { + printk(KERN_WARNING + "spi_write_then_read failed with status %d\n", status); + goto out; + } + dev_dbg(dev, "rxbuf[1] : 0x%x rxbuf[0] : 0x%x\n", rxbuf[1], rxbuf[0]); + + raw = (rxbuf[1] << 8) + rxbuf[0]; + dev_dbg(dev, "raw=0x%x\n", raw); + + /* + * The "raw" temperature read into rxbuf[] is a 16-bit signed 2's + * complement value. Only the MSB 11 bits (1 sign + 10 temperature + * bits) are meaningful; the LSB 5 bits are to be discarded. + * See the datasheet. + * + * Further, each bit represents 0.25 degrees Celsius; so, multiply + * by 0.25. Also multiply by 1000 to represent in millidegrees + * Celsius. + * So it's equivalent to multiplying by 0.25 * 1000 = 250. + */ + val = ((int)raw/32) * 250; + status = sprintf(buf, "%+d\n", val); /* millidegrees Celsius */ +out: + up(&p_lm70->sem); + return status; +} + +static DEVICE_ATTR(temp1_input, S_IRUGO, lm70_sense_temp, NULL); + +/*----------------------------------------------------------------------*/ + +static int __devinit lm70_probe(struct spi_device *spi) +{ + struct lm70 *p_lm70; + int status; + + p_lm70 = kzalloc(sizeof *p_lm70, GFP_KERNEL); + if (!p_lm70) + return -ENOMEM; + + init_MUTEX(&p_lm70->sem); + + /* sysfs hook */ + p_lm70->cdev = hwmon_device_register(&spi->dev); + if (IS_ERR(p_lm70->cdev)) { + dev_dbg(&spi->dev, "hwmon_device_register failed.\n"); + status = PTR_ERR(p_lm70->cdev); + goto out_dev_reg_failed; + } + dev_set_drvdata(&spi->dev, p_lm70); + + if ((status = device_create_file(&spi->dev, &dev_attr_temp1_input))) { + dev_dbg(&spi->dev, "device_create_file failure.\n"); + goto out_dev_create_file_failed; + } + + return 0; + +out_dev_create_file_failed: + hwmon_device_unregister(p_lm70->cdev); +out_dev_reg_failed: + dev_set_drvdata(&spi->dev, NULL); + kfree(p_lm70); + return status; +} + +static int __exit lm70_remove(struct spi_device *spi) +{ + struct lm70 *p_lm70 = dev_get_drvdata(&spi->dev); + + device_remove_file(&spi->dev, &dev_attr_temp1_input); + hwmon_device_unregister(p_lm70->cdev); + dev_set_drvdata(&spi->dev, NULL); + kfree(p_lm70); + + return 0; +} + +static struct spi_driver lm70_driver = { + .driver = { + .name = "lm70", + .owner = THIS_MODULE, + }, + .probe = lm70_probe, + .remove = __devexit_p(lm70_remove), +}; + +static int __init init_lm70(void) +{ + return spi_register_driver(&lm70_driver); +} + +static void __exit cleanup_lm70(void) +{ + spi_unregister_driver(&lm70_driver); +} + +module_init(init_lm70); +module_exit(cleanup_lm70); + +MODULE_AUTHOR("Kaiwan N Billimoria"); +MODULE_DESCRIPTION("National Semiconductor LM70 Linux driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 6af586dc58820d052aa538abef4d4d15c2a9e33e Mon Sep 17 00:00:00 2001 From: Rudolf Marek Date: Mon, 12 Jun 2006 22:00:53 +0200 Subject: [PATCH] hwmon-vid: Add support for Intel Core and Conroe This patch adds support for two new VID codes, supporting Intel mobile Core processors and new Conroe based platforms. Signed-off-by: Rudolf Marek Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/hwmon-vid.c | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/drivers/hwmon/hwmon-vid.c b/drivers/hwmon/hwmon-vid.c index b0fd267635b..a6764ff0080 100644 --- a/drivers/hwmon/hwmon-vid.c +++ b/drivers/hwmon/hwmon-vid.c @@ -58,11 +58,20 @@ doesn't seem to be any named specification for these. The conversion tables are detailed directly in the various Pentium M datasheets: http://www.intel.com/design/intarch/pentiumm/docs_pentiumm.htm + + The 14 specification corresponds to Intel Core series. There + doesn't seem to be any named specification for these. The conversion + tables are detailed directly in the various Pentium Core datasheets: + http://www.intel.com/design/mobile/datashts/309221.htm + + The 110 (VRM 11) specification corresponds to Intel Conroe based series. + http://www.intel.com/design/processor/applnots/313214.htm */ /* vrm is the VRM/VRD document version multiplied by 10. - val is the 4-, 5- or 6-bit VID code. - Returned value is in mV to avoid floating point in the kernel. */ + val is the 4-bit or more VID code. + Returned value is in mV to avoid floating point in the kernel. + Some VID have some bits in uV scale, this is rounded to mV */ int vid_from_reg(int val, u8 vrm) { int vid; @@ -70,18 +79,24 @@ int vid_from_reg(int val, u8 vrm) switch(vrm) { case 100: /* VRD 10.0 */ + /* compute in uV, round to mV */ val &= 0x3f; if((val & 0x1f) == 0x1f) return 0; if((val & 0x1f) <= 0x09 || val == 0x0a) - vid = 10875 - (val & 0x1f) * 250; + vid = 1087500 - (val & 0x1f) * 25000; else - vid = 18625 - (val & 0x1f) * 250; + vid = 1862500 - (val & 0x1f) * 25000; if(val & 0x20) - vid -= 125; - vid /= 10; /* only return 3 dec. places for now */ - return vid; + vid -= 12500; + return((vid + 500) / 1000); + case 110: /* Intel Conroe */ + /* compute in uV, round to mV */ + val &= 0xff; + if(((val & 0x7e) == 0xfe) || (!(val & 0x7e))) + return 0; + return((1600000 - (val - 2) * 6250 + 500) / 1000); case 24: /* Opteron processor */ val &= 0x1f; return(val == 0x1f ? 0 : 1550 - val * 25); @@ -113,6 +128,10 @@ int vid_from_reg(int val, u8 vrm) case 13: val &= 0x3f; return(1708 - val * 16); + case 14: /* Intel Core */ + /* compute in uV, round to mV */ + val &= 0x7f; + return(val > 0x77 ? 0 : (1500000 - (val * 12500) + 500) / 1000); default: /* report 0 for unknown */ printk(KERN_INFO "hwmon-vid: requested unknown VRM version\n"); return 0; @@ -145,6 +164,8 @@ static struct vrm_model vrm_models[] = { {X86_VENDOR_INTEL, 0x6, 0x9, ANY, 13}, /* Pentium M (130 nm) */ {X86_VENDOR_INTEL, 0x6, 0xB, ANY, 85}, /* Tualatin */ {X86_VENDOR_INTEL, 0x6, 0xD, ANY, 13}, /* Pentium M (90 nm) */ + {X86_VENDOR_INTEL, 0x6, 0xE, ANY, 14}, /* Intel Core (65 nm) */ + {X86_VENDOR_INTEL, 0x6, 0xF, ANY, 110}, /* Intel Conroe */ {X86_VENDOR_INTEL, 0x6, ANY, ANY, 82}, /* any P6 */ {X86_VENDOR_INTEL, 0x7, ANY, ANY, 0}, /* Itanium */ {X86_VENDOR_INTEL, 0xF, 0x0, ANY, 90}, /* P4 */ -- cgit v1.2.3 From 4941b395b3c2635a8c16d88791a789fb6ac6be43 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Tue, 13 Jun 2006 09:47:27 -0700 Subject: [PATCH] I2C: I2C controllers go into right place on sysfs I2C creates some sysfs nodes in the wrong places: not as children of parent controllers, but as their peers (!). This puts them into the right place always, instead of just when the adapter is on the platform bus. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/i2c-dev.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index ed7eed388ba..58ccddd5c23 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c @@ -426,10 +426,7 @@ static int i2cdev_attach_adapter(struct i2c_adapter *adap) /* register this i2c device with the driver core */ i2c_dev->adap = adap; - if (adap->dev.parent == &platform_bus) - dev = &adap->dev; - else - dev = adap->dev.parent; + dev = &adap->dev; i2c_dev->class_dev = class_device_create(i2c_dev_class, NULL, MKDEV(I2C_MAJOR, i2c_dev->minor), dev, "i2c-%d", i2c_dev->minor); -- cgit v1.2.3 From f522d2396138e68bcb9cc5650aa368a81d7f7ff0 Mon Sep 17 00:00:00 2001 From: Evgeniy Polyakov Date: Thu, 23 Mar 2006 19:11:58 +0300 Subject: [PATCH] w1: Added default generic read/write operations. Special file in each w1 slave device's directory called "rw" is created each time new slave and no appropriate w1 family is registered. "rw" file supports read and write operations, which allows to perform almost any kind of operations. Each logical operation is a transaction in nature, which can contain several (two or one) low-level operations. Let's see how one can read EEPROM context: 1. one must write control buffer, i.e. buffer containing command byte and two byte address. At this step bus is reset and appropriate device is selected using either W1_SKIP_ROM or W1_MATCH_ROM command. Then provided control buffer is being written to the wire. 2. reading. This will issue reading eeprom response. It is possible that between 1. and 2. w1 master thread will reset bus for searching and slave device will be even removed, but in this case 0xff will be read, since no device was selected. Signed-off-by: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman --- Documentation/w1/w1.generic | 18 ++++++++++-- drivers/w1/w1.c | 69 ++++++++++++++++++++++++++++++++++++++++++++- drivers/w1/w1.h | 2 +- 3 files changed, 84 insertions(+), 5 deletions(-) diff --git a/Documentation/w1/w1.generic b/Documentation/w1/w1.generic index f937fbe1cac..4c6509dd478 100644 --- a/Documentation/w1/w1.generic +++ b/Documentation/w1/w1.generic @@ -27,8 +27,19 @@ When a w1 master driver registers with the w1 subsystem, the following occurs: When a device is found on the bus, w1 core checks if driver for it's family is loaded. If so, the family driver is attached to the slave. -If there is no driver for the family, a simple sysfs entry is created -for the slave device. +If there is no driver for the family, default one is assigned, which allows to perform +almost any kind of operations. Each logical operation is a transaction +in nature, which can contain several (two or one) low-level operations. +Let's see how one can read EEPROM context: +1. one must write control buffer, i.e. buffer containing command byte +and two byte address. At this step bus is reset and appropriate device +is selected using either W1_SKIP_ROM or W1_MATCH_ROM command. +Then provided control buffer is being written to the wire. +2. reading. This will issue reading eeprom response. + +It is possible that between 1. and 2. w1 master thread will reset bus for searching +and slave device will be even removed, but in this case 0xff will +be read, since no device was selected. W1 device families @@ -89,4 +100,5 @@ driver - (standard) symlink to the w1 driver name - the device name, usually the same as the directory name w1_slave - (optional) a binary file whose meaning depends on the family driver - +rw - (optional) created for slave devices which do not have + appropriate family driver. Allows to read/write binary data. diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index a698b517e86..c9486c16850 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c @@ -139,7 +139,74 @@ static struct bin_attribute w1_slave_attr_bin_id = { }; /* Default family */ -static struct w1_family w1_default_family; + +static ssize_t w1_default_write(struct kobject *kobj, char *buf, loff_t off, size_t count) +{ + struct w1_slave *sl = kobj_to_w1_slave(kobj); + + if (down_interruptible(&sl->master->mutex)) { + count = 0; + goto out; + } + + if (w1_reset_select_slave(sl)) { + count = 0; + goto out_up; + } + + w1_write_block(sl->master, buf, count); + +out_up: + up(&sl->master->mutex); +out: + return count; +} + +static ssize_t w1_default_read(struct kobject *kobj, char *buf, loff_t off, size_t count) +{ + struct w1_slave *sl = kobj_to_w1_slave(kobj); + + if (down_interruptible(&sl->master->mutex)) { + count = 0; + goto out; + } + + w1_read_block(sl->master, buf, count); + + up(&sl->master->mutex); +out: + return count; +} + +static struct bin_attribute w1_default_attr = { + .attr = { + .name = "rw", + .mode = S_IRUGO | S_IWUSR, + .owner = THIS_MODULE, + }, + .size = PAGE_SIZE, + .read = w1_default_read, + .write = w1_default_write, +}; + +static int w1_default_add_slave(struct w1_slave *sl) +{ + return sysfs_create_bin_file(&sl->dev.kobj, &w1_default_attr); +} + +static void w1_default_remove_slave(struct w1_slave *sl) +{ + sysfs_remove_bin_file(&sl->dev.kobj, &w1_default_attr); +} + +static struct w1_family_ops w1_default_fops = { + .add_slave = w1_default_add_slave, + .remove_slave = w1_default_remove_slave, +}; + +static struct w1_family w1_default_family = { + .fops = &w1_default_fops, +}; static int w1_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size); diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h index 56980505e6c..02e8caddfb3 100644 --- a/drivers/w1/w1.h +++ b/drivers/w1/w1.h @@ -60,7 +60,7 @@ struct w1_reg_num #define W1_READ_PSUPPLY 0xB4 #define W1_MATCH_ROM 0x55 -#define W1_SLAVE_ACTIVE (1<<0) +#define W1_SLAVE_ACTIVE 0 struct w1_slave { -- cgit v1.2.3 From 81f6075ebcf3b0800321b7d81e4845d6ad9566d8 Mon Sep 17 00:00:00 2001 From: Evgeniy Polyakov Date: Thu, 23 Mar 2006 19:11:58 +0300 Subject: [PATCH] w1: Replace dscore and ds_w1_bridge with ds2490 driver. --- Documentation/w1/masters/ds2490 | 18 + drivers/w1/masters/Kconfig | 27 +- drivers/w1/masters/Makefile | 7 +- drivers/w1/masters/ds2490.c | 947 ++++++++++++++++++++++++++++++++++++++ drivers/w1/masters/ds_w1_bridge.c | 174 ------- drivers/w1/masters/dscore.c | 795 -------------------------------- drivers/w1/masters/dscore.h | 166 ------- 7 files changed, 975 insertions(+), 1159 deletions(-) create mode 100644 Documentation/w1/masters/ds2490 create mode 100644 drivers/w1/masters/ds2490.c delete mode 100644 drivers/w1/masters/ds_w1_bridge.c delete mode 100644 drivers/w1/masters/dscore.c delete mode 100644 drivers/w1/masters/dscore.h diff --git a/Documentation/w1/masters/ds2490 b/Documentation/w1/masters/ds2490 new file mode 100644 index 00000000000..44a4918bd7f --- /dev/null +++ b/Documentation/w1/masters/ds2490 @@ -0,0 +1,18 @@ +Kernel driver ds2490 +==================== + +Supported chips: + * Maxim DS2490 based + +Author: Evgeniy Polyakov + + +Description +----------- + +The Maixm/Dallas Semiconductor DS2490 is a chip +which allows to build USB <-> W1 bridges. + +DS9490(R) is a USB <-> W1 bus master device +which has 0x81 family ID integrated chip and DS2490 +low-level operational chip. diff --git a/drivers/w1/masters/Kconfig b/drivers/w1/masters/Kconfig index c6bad4dbdc6..2fb425536ea 100644 --- a/drivers/w1/masters/Kconfig +++ b/drivers/w1/masters/Kconfig @@ -15,24 +15,15 @@ config W1_MASTER_MATROX This support is also available as a module. If so, the module will be called matrox_w1.ko. -config W1_MASTER_DS9490 - tristate "DS9490R transport layer driver" - depends on W1 && USB - help - Say Y here if you want to have a driver for DS9490R UWB <-> W1 bridge. - - This support is also available as a module. If so, the module - will be called ds9490r.ko. - -config W1_MASTER_DS9490_BRIDGE - tristate "DS9490R USB <-> W1 transport layer for 1-wire" - depends on W1_MASTER_DS9490 - help - Say Y here if you want to communicate with your 1-wire devices - using DS9490R USB bridge. - - This support is also available as a module. If so, the module - will be called ds_w1_bridge.ko. +config W1_MASTER_DS2490 + tristate "DS2490 USB <-> W1 transport layer for 1-wire" + depends on W1 && USB + help + Say Y here if you want to have a driver for DS2490 based USB <-> W1 bridges, + for example DS9490*. + + This support is also available as a module. If so, the module + will be called ds2490.ko. config W1_MASTER_DS2482 tristate "Maxim DS2482 I2C to 1-Wire bridge" diff --git a/drivers/w1/masters/Makefile b/drivers/w1/masters/Makefile index 1f3c8b983dc..4cee256a813 100644 --- a/drivers/w1/masters/Makefile +++ b/drivers/w1/masters/Makefile @@ -3,11 +3,6 @@ # obj-$(CONFIG_W1_MASTER_MATROX) += matrox_w1.o - -obj-$(CONFIG_W1_MASTER_DS9490) += ds9490r.o -ds9490r-objs := dscore.o - -obj-$(CONFIG_W1_MASTER_DS9490_BRIDGE) += ds_w1_bridge.o - +obj-$(CONFIG_W1_MASTER_DS2490) += ds2490.o obj-$(CONFIG_W1_MASTER_DS2482) += ds2482.o diff --git a/drivers/w1/masters/ds2490.c b/drivers/w1/masters/ds2490.c new file mode 100644 index 00000000000..637677833da --- /dev/null +++ b/drivers/w1/masters/ds2490.c @@ -0,0 +1,947 @@ +/* + * dscore.c + * + * Copyright (c) 2004 Evgeniy Polyakov + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "../w1_int.h" +#include "../w1.h" + +/* COMMAND TYPE CODES */ +#define CONTROL_CMD 0x00 +#define COMM_CMD 0x01 +#define MODE_CMD 0x02 + +/* CONTROL COMMAND CODES */ +#define CTL_RESET_DEVICE 0x0000 +#define CTL_START_EXE 0x0001 +#define CTL_RESUME_EXE 0x0002 +#define CTL_HALT_EXE_IDLE 0x0003 +#define CTL_HALT_EXE_DONE 0x0004 +#define CTL_FLUSH_COMM_CMDS 0x0007 +#define CTL_FLUSH_RCV_BUFFER 0x0008 +#define CTL_FLUSH_XMT_BUFFER 0x0009 +#define CTL_GET_COMM_CMDS 0x000A + +/* MODE COMMAND CODES */ +#define MOD_PULSE_EN 0x0000 +#define MOD_SPEED_CHANGE_EN 0x0001 +#define MOD_1WIRE_SPEED 0x0002 +#define MOD_STRONG_PU_DURATION 0x0003 +#define MOD_PULLDOWN_SLEWRATE 0x0004 +#define MOD_PROG_PULSE_DURATION 0x0005 +#define MOD_WRITE1_LOWTIME 0x0006 +#define MOD_DSOW0_TREC 0x0007 + +/* COMMUNICATION COMMAND CODES */ +#define COMM_ERROR_ESCAPE 0x0601 +#define COMM_SET_DURATION 0x0012 +#define COMM_BIT_IO 0x0020 +#define COMM_PULSE 0x0030 +#define COMM_1_WIRE_RESET 0x0042 +#define COMM_BYTE_IO 0x0052 +#define COMM_MATCH_ACCESS 0x0064 +#define COMM_BLOCK_IO 0x0074 +#define COMM_READ_STRAIGHT 0x0080 +#define COMM_DO_RELEASE 0x6092 +#define COMM_SET_PATH 0x00A2 +#define COMM_WRITE_SRAM_PAGE 0x00B2 +#define COMM_WRITE_EPROM 0x00C4 +#define COMM_READ_CRC_PROT_PAGE 0x00D4 +#define COMM_READ_REDIRECT_PAGE_CRC 0x21E4 +#define COMM_SEARCH_ACCESS 0x00F4 + +/* Communication command bits */ +#define COMM_TYPE 0x0008 +#define COMM_SE 0x0008 +#define COMM_D 0x0008 +#define COMM_Z 0x0008 +#define COMM_CH 0x0008 +#define COMM_SM 0x0008 +#define COMM_R 0x0008 +#define COMM_IM 0x0001 + +#define COMM_PS 0x4000 +#define COMM_PST 0x4000 +#define COMM_CIB 0x4000 +#define COMM_RTS 0x4000 +#define COMM_DT 0x2000 +#define COMM_SPU 0x1000 +#define COMM_F 0x0800 +#define COMM_NTP 0x0400 +#define COMM_ICP 0x0200 +#define COMM_RST 0x0100 + +#define PULSE_PROG 0x01 +#define PULSE_SPUE 0x02 + +#define BRANCH_MAIN 0xCC +#define BRANCH_AUX 0x33 + +/* + * Duration of the strong pull-up pulse in milliseconds. + */ +#define PULLUP_PULSE_DURATION 750 + +/* Status flags */ +#define ST_SPUA 0x01 /* Strong Pull-up is active */ +#define ST_PRGA 0x02 /* 12V programming pulse is being generated */ +#define ST_12VP 0x04 /* external 12V programming voltage is present */ +#define ST_PMOD 0x08 /* DS2490 powered from USB and external sources */ +#define ST_HALT 0x10 /* DS2490 is currently halted */ +#define ST_IDLE 0x20 /* DS2490 is currently idle */ +#define ST_EPOF 0x80 + +#define SPEED_NORMAL 0x00 +#define SPEED_FLEXIBLE 0x01 +#define SPEED_OVERDRIVE 0x02 + +#define NUM_EP 4 +#define EP_CONTROL 0 +#define EP_STATUS 1 +#define EP_DATA_OUT 2 +#define EP_DATA_IN 3 + +struct ds_device +{ + struct list_head ds_entry; + + struct usb_device *udev; + struct usb_interface *intf; + + int ep[NUM_EP]; + + struct w1_bus_master master; +}; + +struct ds_status +{ + u8 enable; + u8 speed; + u8 pullup_dur; + u8 ppuls_dur; + u8 pulldown_slew; + u8 write1_time; + u8 write0_time; + u8 reserved0; + u8 status; + u8 command0; + u8 command1; + u8 command_buffer_status; + u8 data_out_buffer_status; + u8 data_in_buffer_status; + u8 reserved1; + u8 reserved2; + +}; + +static struct usb_device_id ds_id_table [] = { + { USB_DEVICE(0x04fa, 0x2490) }, + { }, +}; +MODULE_DEVICE_TABLE(usb, ds_id_table); + +static int ds_probe(struct usb_interface *, const struct usb_device_id *); +static void ds_disconnect(struct usb_interface *); + +static inline void ds_dump_status(unsigned char *, unsigned char *, int); +static int ds_send_control(struct ds_device *, u16, u16); +static int ds_send_control_cmd(struct ds_device *, u16, u16); + +static LIST_HEAD(ds_devices); +static DECLARE_MUTEX(ds_mutex); + +static struct usb_driver ds_driver = { + .name = "DS9490R", + .probe = ds_probe, + .disconnect = ds_disconnect, + .id_table = ds_id_table, +}; + +static int ds_send_control_cmd(struct ds_device *dev, u16 value, u16 index) +{ + int err; + + err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]), + CONTROL_CMD, 0x40, value, index, NULL, 0, 1000); + if (err < 0) { + printk(KERN_ERR "Failed to send command control message %x.%x: err=%d.\n", + value, index, err); + return err; + } + + return err; +} +#if 0 +static int ds_send_control_mode(struct ds_device *dev, u16 value, u16 index) +{ + int err; + + err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]), + MODE_CMD, 0x40, value, index, NULL, 0, 1000); + if (err < 0) { + printk(KERN_ERR "Failed to send mode control message %x.%x: err=%d.\n", + value, index, err); + return err; + } + + return err; +} +#endif +static int ds_send_control(struct ds_device *dev, u16 value, u16 index) +{ + int err; + + err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]), + COMM_CMD, 0x40, value, index, NULL, 0, 1000); + if (err < 0) { + printk(KERN_ERR "Failed to send control message %x.%x: err=%d.\n", + value, index, err); + return err; + } + + return err; +} + +static inline void ds_dump_status(unsigned char *buf, unsigned char *str, int off) +{ + printk("%45s: %8x\n", str, buf[off]); +} + +static int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st, + unsigned char *buf, int size) +{ + int count, err; + + memset(st, 0, sizeof(st)); + + count = 0; + err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_STATUS]), buf, size, &count, 100); + if (err < 0) { + printk(KERN_ERR "Failed to read 1-wire data from 0x%x: err=%d.\n", dev->ep[EP_STATUS], err); + return err; + } + + if (count >= sizeof(*st)) + memcpy(st, buf, sizeof(*st)); + + return count; +} + +static int ds_recv_status(struct ds_device *dev, struct ds_status *st) +{ + unsigned char buf[64]; + int count, err = 0, i; + + memcpy(st, buf, sizeof(*st)); + + count = ds_recv_status_nodump(dev, st, buf, sizeof(buf)); + if (count < 0) + return err; + + printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], count); + for (i=0; i= 16) { + ds_dump_status(buf, "enable flag", 0); + ds_dump_status(buf, "1-wire speed", 1); + ds_dump_status(buf, "strong pullup duration", 2); + ds_dump_status(buf, "programming pulse duration", 3); + ds_dump_status(buf, "pulldown slew rate control", 4); + ds_dump_status(buf, "write-1 low time", 5); + ds_dump_status(buf, "data sample offset/write-0 recovery time", 6); + ds_dump_status(buf, "reserved (test register)", 7); + ds_dump_status(buf, "device status flags", 8); + ds_dump_status(buf, "communication command byte 1", 9); + ds_dump_status(buf, "communication command byte 2", 10); + ds_dump_status(buf, "communication command buffer status", 11); + ds_dump_status(buf, "1-wire data output buffer status", 12); + ds_dump_status(buf, "1-wire data input buffer status", 13); + ds_dump_status(buf, "reserved", 14); + ds_dump_status(buf, "reserved", 15); + } + + memcpy(st, buf, sizeof(*st)); + + if (st->status & ST_EPOF) { + printk(KERN_INFO "Resetting device after ST_EPOF.\n"); + err = ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0); + if (err) + return err; + count = ds_recv_status_nodump(dev, st, buf, sizeof(buf)); + if (count < 0) + return err; + } +#if 0 + if (st->status & ST_IDLE) { + printk(KERN_INFO "Resetting pulse after ST_IDLE.\n"); + err = ds_start_pulse(dev, PULLUP_PULSE_DURATION); + if (err) + return err; + } +#endif + + return err; +} + +static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size) +{ + int count, err; + struct ds_status st; + + count = 0; + err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]), + buf, size, &count, 1000); + if (err < 0) { + printk(KERN_INFO "Clearing ep0x%x.\n", dev->ep[EP_DATA_IN]); + usb_clear_halt(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN])); + ds_recv_status(dev, &st); + return err; + } + +#if 0 + { + int i; + + printk("%s: count=%d: ", __func__, count); + for (i=0; iudev, usb_sndbulkpipe(dev->udev, dev->ep[EP_DATA_OUT]), buf, len, &count, 1000); + if (err < 0) { + printk(KERN_ERR "Failed to read 1-wire data from 0x02: err=%d.\n", err); + return err; + } + + return err; +} + +#if 0 + +int ds_stop_pulse(struct ds_device *dev, int limit) +{ + struct ds_status st; + int count = 0, err = 0; + u8 buf[0x20]; + + do { + err = ds_send_control(dev, CTL_HALT_EXE_IDLE, 0); + if (err) + break; + err = ds_send_control(dev, CTL_RESUME_EXE, 0); + if (err) + break; + err = ds_recv_status_nodump(dev, &st, buf, sizeof(buf)); + if (err) + break; + + if ((st.status & ST_SPUA) == 0) { + err = ds_send_control_mode(dev, MOD_PULSE_EN, 0); + if (err) + break; + } + } while(++count < limit); + + return err; +} + +int ds_detect(struct ds_device *dev, struct ds_status *st) +{ + int err; + + err = ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0); + if (err) + return err; + + err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, 0); + if (err) + return err; + + err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM | COMM_TYPE, 0x40); + if (err) + return err; + + err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_PROG); + if (err) + return err; + + err = ds_recv_status(dev, st); + + return err; +} + +#endif /* 0 */ + +static int ds_wait_status(struct ds_device *dev, struct ds_status *st) +{ + u8 buf[0x20]; + int err, count = 0; + + do { + err = ds_recv_status_nodump(dev, st, buf, sizeof(buf)); +#if 0 + if (err >= 0) { + int i; + printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], err); + for (i=0; i 16) && (buf[0x10] & 0x01)) || count >= 100 || err < 0) { + ds_recv_status(dev, st); + return -1; + } else + return 0; +} + +static int ds_reset(struct ds_device *dev, struct ds_status *st) +{ + int err; + + //err = ds_send_control(dev, COMM_1_WIRE_RESET | COMM_F | COMM_IM | COMM_SE, SPEED_FLEXIBLE); + err = ds_send_control(dev, 0x43, SPEED_NORMAL); + if (err) + return err; + + ds_wait_status(dev, st); +#if 0 + if (st->command_buffer_status) { + printk(KERN_INFO "Short circuit.\n"); + return -EIO; + } +#endif + + return 0; +} + +#if 0 +static int ds_set_speed(struct ds_device *dev, int speed) +{ + int err; + + if (speed != SPEED_NORMAL && speed != SPEED_FLEXIBLE && speed != SPEED_OVERDRIVE) + return -EINVAL; + + if (speed != SPEED_OVERDRIVE) + speed = SPEED_FLEXIBLE; + + speed &= 0xff; + + err = ds_send_control_mode(dev, MOD_1WIRE_SPEED, speed); + if (err) + return err; + + return err; +} +#endif /* 0 */ + +static int ds_start_pulse(struct ds_device *dev, int delay) +{ + int err; + u8 del = 1 + (u8)(delay >> 4); + struct ds_status st; + +#if 0 + err = ds_stop_pulse(dev, 10); + if (err) + return err; + + err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_SPUE); + if (err) + return err; +#endif + err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, del); + if (err) + return err; + + err = ds_send_control(dev, COMM_PULSE | COMM_IM | COMM_F, 0); + if (err) + return err; + + mdelay(delay); + + ds_wait_status(dev, &st); + + return err; +} + +static int ds_touch_bit(struct ds_device *dev, u8 bit, u8 *tbit) +{ + int err, count; + struct ds_status st; + u16 value = (COMM_BIT_IO | COMM_IM) | ((bit) ? COMM_D : 0); + u16 cmd; + + err = ds_send_control(dev, value, 0); + if (err) + return err; + + count = 0; + do { + err = ds_wait_status(dev, &st); + if (err) + return err; + + cmd = st.command0 | (st.command1 << 8); + } while (cmd != value && ++count < 10); + + if (err < 0 || count >= 10) { + printk(KERN_ERR "Failed to obtain status.\n"); + return -EINVAL; + } + + err = ds_recv_data(dev, tbit, sizeof(*tbit)); + if (err < 0) + return err; + + return 0; +} + +static int ds_write_bit(struct ds_device *dev, u8 bit) +{ + int err; + struct ds_status st; + + err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | (bit) ? COMM_D : 0, 0); + if (err) + return err; + + ds_wait_status(dev, &st); + + return 0; +} + +static int ds_write_byte(struct ds_device *dev, u8 byte) +{ + int err; + struct ds_status st; + u8 rbyte; + + err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM | COMM_SPU, byte); + if (err) + return err; + + err = ds_wait_status(dev, &st); + if (err) + return err; + + err = ds_recv_data(dev, &rbyte, sizeof(rbyte)); + if (err < 0) + return err; + + ds_start_pulse(dev, PULLUP_PULSE_DURATION); + + return !(byte == rbyte); +} + +static int ds_read_byte(struct ds_device *dev, u8 *byte) +{ + int err; + struct ds_status st; + + err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM , 0xff); + if (err) + return err; + + ds_wait_status(dev, &st); + + err = ds_recv_data(dev, byte, sizeof(*byte)); + if (err < 0) + return err; + + return 0; +} + +static int ds_read_block(struct ds_device *dev, u8 *buf, int len) +{ + struct ds_status st; + int err; + + if (len > 64*1024) + return -E2BIG; + + memset(buf, 0xFF, len); + + err = ds_send_data(dev, buf, len); + if (err < 0) + return err; + + err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len); + if (err) + return err; + + ds_wait_status(dev, &st); + + memset(buf, 0x00, len); + err = ds_recv_data(dev, buf, len); + + return err; +} + +static int ds_write_block(struct ds_device *dev, u8 *buf, int len) +{ + int err; + struct ds_status st; + + err = ds_send_data(dev, buf, len); + if (err < 0) + return err; + + ds_wait_status(dev, &st); + + err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len); + if (err) + return err; + + ds_wait_status(dev, &st); + + err = ds_recv_data(dev, buf, len); + if (err < 0) + return err; + + ds_start_pulse(dev, PULLUP_PULSE_DURATION); + + return !(err == len); +} + +#if 0 + +static int ds_search(struct ds_device *dev, u64 init, u64 *buf, u8 id_number, int conditional_search) +{ + int err; + u16 value, index; + struct ds_status st; + + memset(buf, 0, sizeof(buf)); + + err = ds_send_data(ds_dev, (unsigned char *)&init, 8); + if (err) + return err; + + ds_wait_status(ds_dev, &st); + + value = COMM_SEARCH_ACCESS | COMM_IM | COMM_SM | COMM_F | COMM_RTS; + index = (conditional_search ? 0xEC : 0xF0) | (id_number << 8); + err = ds_send_control(ds_dev, value, index); + if (err) + return err; + + ds_wait_status(ds_dev, &st); + + err = ds_recv_data(ds_dev, (unsigned char *)buf, 8*id_number); + if (err < 0) + return err; + + return err/8; +} + +static int ds_match_access(struct ds_device *dev, u64 init) +{ + int err; + struct ds_status st; + + err = ds_send_data(dev, (unsigned char *)&init, sizeof(init)); + if (err) + return err; + + ds_wait_status(dev, &st); + + err = ds_send_control(dev, COMM_MATCH_ACCESS | COMM_IM | COMM_RST, 0x0055); + if (err) + return err; + + ds_wait_status(dev, &st); + + return 0; +} + +static int ds_set_path(struct ds_device *dev, u64 init) +{ + int err; + struct ds_status st; + u8 buf[9]; + + memcpy(buf, &init, 8); + buf[8] = BRANCH_MAIN; + + err = ds_send_data(dev, buf, sizeof(buf)); + if (err) + return err; + + ds_wait_status(dev, &st); + + err = ds_send_control(dev, COMM_SET_PATH | COMM_IM | COMM_RST, 0); + if (err) + return err; + + ds_wait_status(dev, &st); + + return 0; +} + +#endif /* 0 */ + +static u8 ds9490r_touch_bit(void *data, u8 bit) +{ + u8 ret; + struct ds_device *dev = data; + + if (ds_touch_bit(dev, bit, &ret)) + return 0; + + return ret; +} + +static void ds9490r_write_bit(void *data, u8 bit) +{ + struct ds_device *dev = data; + + ds_write_bit(dev, bit); +} + +static void ds9490r_write_byte(void *data, u8 byte) +{ + struct ds_device *dev = data; + + ds_write_byte(dev, byte); +} + +static u8 ds9490r_read_bit(void *data) +{ + struct ds_device *dev = data; + int err; + u8 bit = 0; + + err = ds_touch_bit(dev, 1, &bit); + if (err) + return 0; + + return bit & 1; +} + +static u8 ds9490r_read_byte(void *data) +{ + struct ds_device *dev = data; + int err; + u8 byte = 0; + + err = ds_read_byte(dev, &byte); + if (err) + return 0; + + return byte; +} + +static void ds9490r_write_block(void *data, const u8 *buf, int len) +{ + struct ds_device *dev = data; + + ds_write_block(dev, (u8 *)buf, len); +} + +static u8 ds9490r_read_block(void *data, u8 *buf, int len) +{ + struct ds_device *dev = data; + int err; + + err = ds_read_block(dev, buf, len); + if (err < 0) + return 0; + + return len; +} + +static u8 ds9490r_reset(void *data) +{ + struct ds_device *dev = data; + struct ds_status st; + int err; + + memset(&st, 0, sizeof(st)); + + err = ds_reset(dev, &st); + if (err) + return 1; + + return 0; +} + +static int ds_w1_init(struct ds_device *dev) +{ + memset(&dev->master, 0, sizeof(struct w1_bus_master)); + + dev->master.data = dev; + dev->master.touch_bit = &ds9490r_touch_bit; + dev->master.read_bit = &ds9490r_read_bit; + dev->master.write_bit = &ds9490r_write_bit; + dev->master.read_byte = &ds9490r_read_byte; + dev->master.write_byte = &ds9490r_write_byte; + dev->master.read_block = &ds9490r_read_block; + dev->master.write_block = &ds9490r_write_block; + dev->master.reset_bus = &ds9490r_reset; + + return w1_add_master_device(&dev->master); +} + +static void ds_w1_fini(struct ds_device *dev) +{ + w1_remove_master_device(&dev->master); +} + +static int ds_probe(struct usb_interface *intf, + const struct usb_device_id *udev_id) +{ + struct usb_device *udev = interface_to_usbdev(intf); + struct usb_endpoint_descriptor *endpoint; + struct usb_host_interface *iface_desc; + struct ds_device *dev; + int i, err; + + dev = kmalloc(sizeof(struct ds_device), GFP_KERNEL); + if (!dev) { + printk(KERN_INFO "Failed to allocate new DS9490R structure.\n"); + return -ENOMEM; + } + dev->udev = usb_get_dev(udev); + if (!dev->udev) { + err = -ENOMEM; + goto err_out_free; + } + memset(dev->ep, 0, sizeof(dev->ep)); + + usb_set_intfdata(intf, dev); + + err = usb_set_interface(dev->udev, intf->altsetting[0].desc.bInterfaceNumber, 3); + if (err) { + printk(KERN_ERR "Failed to set alternative setting 3 for %d interface: err=%d.\n", + intf->altsetting[0].desc.bInterfaceNumber, err); + goto err_out_clear; + } + + err = usb_reset_configuration(dev->udev); + if (err) { + printk(KERN_ERR "Failed to reset configuration: err=%d.\n", err); + goto err_out_clear; + } + + iface_desc = &intf->altsetting[0]; + if (iface_desc->desc.bNumEndpoints != NUM_EP-1) { + printk(KERN_INFO "Num endpoints=%d. It is not DS9490R.\n", iface_desc->desc.bNumEndpoints); + err = -EINVAL; + goto err_out_clear; + } + + /* + * This loop doesn'd show control 0 endpoint, + * so we will fill only 1-3 endpoints entry. + */ + for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { + endpoint = &iface_desc->endpoint[i].desc; + + dev->ep[i+1] = endpoint->bEndpointAddress; +#if 0 + printk("%d: addr=%x, size=%d, dir=%s, type=%x\n", + i, endpoint->bEndpointAddress, le16_to_cpu(endpoint->wMaxPacketSize), + (endpoint->bEndpointAddress & USB_DIR_IN)?"IN":"OUT", + endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK); +#endif + } + + err = ds_w1_init(dev); + if (err) + goto err_out_clear; + + down(&ds_mutex); + list_add_tail(&dev->ds_entry, &ds_devices); + up(&ds_mutex); + + return 0; + +err_out_clear: + usb_set_intfdata(intf, NULL); + usb_put_dev(dev->udev); +err_out_free: + kfree(dev); + return err; +} + +static void ds_disconnect(struct usb_interface *intf) +{ + struct ds_device *dev; + + dev = usb_get_intfdata(intf); + if (!dev) + return; + + down(&ds_mutex); + list_del(&dev->ds_entry); + up(&ds_mutex); + + ds_w1_fini(dev); + + usb_set_intfdata(intf, NULL); + + usb_put_dev(dev->udev); + kfree(dev); +} + +static int ds_init(void) +{ + int err; + + err = usb_register(&ds_driver); + if (err) { + printk(KERN_INFO "Failed to register DS9490R USB device: err=%d.\n", err); + return err; + } + + return 0; +} + +static void ds_fini(void) +{ + usb_deregister(&ds_driver); +} + +module_init(ds_init); +module_exit(ds_fini); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Evgeniy Polyakov "); +MODULE_DESCRIPTION("DS2490 USB <-> W1 bus master driver (DS9490*)"); diff --git a/drivers/w1/masters/ds_w1_bridge.c b/drivers/w1/masters/ds_w1_bridge.c deleted file mode 100644 index 5d30783a3eb..00000000000 --- a/drivers/w1/masters/ds_w1_bridge.c +++ /dev/null @@ -1,174 +0,0 @@ -/* - * ds_w1_bridge.c - * - * Copyright (c) 2004 Evgeniy Polyakov - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include - -#include "../w1.h" -#include "../w1_int.h" -#include "dscore.h" - -static struct ds_device *ds_dev; -static struct w1_bus_master *ds_bus_master; - -static u8 ds9490r_touch_bit(void *data, u8 bit) -{ - u8 ret; - struct ds_device *dev = data; - - if (ds_touch_bit(dev, bit, &ret)) - return 0; - - return ret; -} - -static void ds9490r_write_bit(void *data, u8 bit) -{ - struct ds_device *dev = data; - - ds_write_bit(dev, bit); -} - -static void ds9490r_write_byte(void *data, u8 byte) -{ - struct ds_device *dev = data; - - ds_write_byte(dev, byte); -} - -static u8 ds9490r_read_bit(void *data) -{ - struct ds_device *dev = data; - int err; - u8 bit = 0; - - err = ds_touch_bit(dev, 1, &bit); - if (err) - return 0; - //err = ds_read_bit(dev, &bit); - //if (err) - // return 0; - - return bit & 1; -} - -static u8 ds9490r_read_byte(void *data) -{ - struct ds_device *dev = data; - int err; - u8 byte = 0; - - err = ds_read_byte(dev, &byte); - if (err) - return 0; - - return byte; -} - -static void ds9490r_write_block(void *data, const u8 *buf, int len) -{ - struct ds_device *dev = data; - - ds_write_block(dev, (u8 *)buf, len); -} - -static u8 ds9490r_read_block(void *data, u8 *buf, int len) -{ - struct ds_device *dev = data; - int err; - - err = ds_read_block(dev, buf, len); - if (err < 0) - return 0; - - return len; -} - -static u8 ds9490r_reset(void *data) -{ - struct ds_device *dev = data; - struct ds_status st; - int err; - - memset(&st, 0, sizeof(st)); - - err = ds_reset(dev, &st); - if (err) - return 1; - - return 0; -} - -static int __devinit ds_w1_init(void) -{ - int err; - - ds_bus_master = kmalloc(sizeof(*ds_bus_master), GFP_KERNEL); - if (!ds_bus_master) { - printk(KERN_ERR "Failed to allocate DS9490R USB<->W1 bus_master structure.\n"); - return -ENOMEM; - } - - ds_dev = ds_get_device(); - if (!ds_dev) { - printk(KERN_ERR "DS9490R is not registered.\n"); - err = -ENODEV; - goto err_out_free_bus_master; - } - - memset(ds_bus_master, 0, sizeof(*ds_bus_master)); - - ds_bus_master->data = ds_dev; - ds_bus_master->touch_bit = &ds9490r_touch_bit; - ds_bus_master->read_bit = &ds9490r_read_bit; - ds_bus_master->write_bit = &ds9490r_write_bit; - ds_bus_master->read_byte = &ds9490r_read_byte; - ds_bus_master->write_byte = &ds9490r_write_byte; - ds_bus_master->read_block = &ds9490r_read_block; - ds_bus_master->write_block = &ds9490r_write_block; - ds_bus_master->reset_bus = &ds9490r_reset; - - err = w1_add_master_device(ds_bus_master); - if (err) - goto err_out_put_device; - - return 0; - -err_out_put_device: - ds_put_device(ds_dev); -err_out_free_bus_master: - kfree(ds_bus_master); - - return err; -} - -static void __devexit ds_w1_fini(void) -{ - w1_remove_master_device(ds_bus_master); - ds_put_device(ds_dev); - kfree(ds_bus_master); -} - -module_init(ds_w1_init); -module_exit(ds_w1_fini); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Evgeniy Polyakov "); diff --git a/drivers/w1/masters/dscore.c b/drivers/w1/masters/dscore.c deleted file mode 100644 index 2cf7776a708..00000000000 --- a/drivers/w1/masters/dscore.c +++ /dev/null @@ -1,795 +0,0 @@ -/* - * dscore.c - * - * Copyright (c) 2004 Evgeniy Polyakov - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include - -#include "dscore.h" - -static struct usb_device_id ds_id_table [] = { - { USB_DEVICE(0x04fa, 0x2490) }, - { }, -}; -MODULE_DEVICE_TABLE(usb, ds_id_table); - -static int ds_probe(struct usb_interface *, const struct usb_device_id *); -static void ds_disconnect(struct usb_interface *); - -int ds_touch_bit(struct ds_device *, u8, u8 *); -int ds_read_byte(struct ds_device *, u8 *); -int ds_read_bit(struct ds_device *, u8 *); -int ds_write_byte(struct ds_device *, u8); -int ds_write_bit(struct ds_device *, u8); -static int ds_start_pulse(struct ds_device *, int); -int ds_reset(struct ds_device *, struct ds_status *); -struct ds_device * ds_get_device(void); -void ds_put_device(struct ds_device *); - -static inline void ds_dump_status(unsigned char *, unsigned char *, int); -static int ds_send_control(struct ds_device *, u16, u16); -static int ds_send_control_mode(struct ds_device *, u16, u16); -static int ds_send_control_cmd(struct ds_device *, u16, u16); - - -static struct usb_driver ds_driver = { - .name = "DS9490R", - .probe = ds_probe, - .disconnect = ds_disconnect, - .id_table = ds_id_table, -}; - -static struct ds_device *ds_dev; - -struct ds_device * ds_get_device(void) -{ - if (ds_dev) - atomic_inc(&ds_dev->refcnt); - return ds_dev; -} - -void ds_put_device(struct ds_device *dev) -{ - atomic_dec(&dev->refcnt); -} - -static int ds_send_control_cmd(struct ds_device *dev, u16 value, u16 index) -{ - int err; - - err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]), - CONTROL_CMD, 0x40, value, index, NULL, 0, 1000); - if (err < 0) { - printk(KERN_ERR "Failed to send command control message %x.%x: err=%d.\n", - value, index, err); - return err; - } - - return err; -} - -static int ds_send_control_mode(struct ds_device *dev, u16 value, u16 index) -{ - int err; - - err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]), - MODE_CMD, 0x40, value, index, NULL, 0, 1000); - if (err < 0) { - printk(KERN_ERR "Failed to send mode control message %x.%x: err=%d.\n", - value, index, err); - return err; - } - - return err; -} - -static int ds_send_control(struct ds_device *dev, u16 value, u16 index) -{ - int err; - - err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]), - COMM_CMD, 0x40, value, index, NULL, 0, 1000); - if (err < 0) { - printk(KERN_ERR "Failed to send control message %x.%x: err=%d.\n", - value, index, err); - return err; - } - - return err; -} - -static inline void ds_dump_status(unsigned char *buf, unsigned char *str, int off) -{ - printk("%45s: %8x\n", str, buf[off]); -} - -static int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st, - unsigned char *buf, int size) -{ - int count, err; - - memset(st, 0, sizeof(st)); - - count = 0; - err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_STATUS]), buf, size, &count, 100); - if (err < 0) { - printk(KERN_ERR "Failed to read 1-wire data from 0x%x: err=%d.\n", dev->ep[EP_STATUS], err); - return err; - } - - if (count >= sizeof(*st)) - memcpy(st, buf, sizeof(*st)); - - return count; -} - -static int ds_recv_status(struct ds_device *dev, struct ds_status *st) -{ - unsigned char buf[64]; - int count, err = 0, i; - - memcpy(st, buf, sizeof(*st)); - - count = ds_recv_status_nodump(dev, st, buf, sizeof(buf)); - if (count < 0) - return err; - - printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], count); - for (i=0; i= 16) { - ds_dump_status(buf, "enable flag", 0); - ds_dump_status(buf, "1-wire speed", 1); - ds_dump_status(buf, "strong pullup duration", 2); - ds_dump_status(buf, "programming pulse duration", 3); - ds_dump_status(buf, "pulldown slew rate control", 4); - ds_dump_status(buf, "write-1 low time", 5); - ds_dump_status(buf, "data sample offset/write-0 recovery time", 6); - ds_dump_status(buf, "reserved (test register)", 7); - ds_dump_status(buf, "device status flags", 8); - ds_dump_status(buf, "communication command byte 1", 9); - ds_dump_status(buf, "communication command byte 2", 10); - ds_dump_status(buf, "communication command buffer status", 11); - ds_dump_status(buf, "1-wire data output buffer status", 12); - ds_dump_status(buf, "1-wire data input buffer status", 13); - ds_dump_status(buf, "reserved", 14); - ds_dump_status(buf, "reserved", 15); - } - - memcpy(st, buf, sizeof(*st)); - - if (st->status & ST_EPOF) { - printk(KERN_INFO "Resetting device after ST_EPOF.\n"); - err = ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0); - if (err) - return err; - count = ds_recv_status_nodump(dev, st, buf, sizeof(buf)); - if (count < 0) - return err; - } -#if 0 - if (st->status & ST_IDLE) { - printk(KERN_INFO "Resetting pulse after ST_IDLE.\n"); - err = ds_start_pulse(dev, PULLUP_PULSE_DURATION); - if (err) - return err; - } -#endif - - return err; -} - -static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size) -{ - int count, err; - struct ds_status st; - - count = 0; - err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]), - buf, size, &count, 1000); - if (err < 0) { - printk(KERN_INFO "Clearing ep0x%x.\n", dev->ep[EP_DATA_IN]); - usb_clear_halt(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN])); - ds_recv_status(dev, &st); - return err; - } - -#if 0 - { - int i; - - printk("%s: count=%d: ", __func__, count); - for (i=0; iudev, usb_sndbulkpipe(dev->udev, dev->ep[EP_DATA_OUT]), buf, len, &count, 1000); - if (err < 0) { - printk(KERN_ERR "Failed to read 1-wire data from 0x02: err=%d.\n", err); - return err; - } - - return err; -} - -#if 0 - -int ds_stop_pulse(struct ds_device *dev, int limit) -{ - struct ds_status st; - int count = 0, err = 0; - u8 buf[0x20]; - - do { - err = ds_send_control(dev, CTL_HALT_EXE_IDLE, 0); - if (err) - break; - err = ds_send_control(dev, CTL_RESUME_EXE, 0); - if (err) - break; - err = ds_recv_status_nodump(dev, &st, buf, sizeof(buf)); - if (err) - break; - - if ((st.status & ST_SPUA) == 0) { - err = ds_send_control_mode(dev, MOD_PULSE_EN, 0); - if (err) - break; - } - } while(++count < limit); - - return err; -} - -int ds_detect(struct ds_device *dev, struct ds_status *st) -{ - int err; - - err = ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0); - if (err) - return err; - - err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, 0); - if (err) - return err; - - err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM | COMM_TYPE, 0x40); - if (err) - return err; - - err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_PROG); - if (err) - return err; - - err = ds_recv_status(dev, st); - - return err; -} - -#endif /* 0 */ - -static int ds_wait_status(struct ds_device *dev, struct ds_status *st) -{ - u8 buf[0x20]; - int err, count = 0; - - do { - err = ds_recv_status_nodump(dev, st, buf, sizeof(buf)); -#if 0 - if (err >= 0) { - int i; - printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], err); - for (i=0; i 16) && (buf[0x10] & 0x01)) || count >= 100 || err < 0) { - ds_recv_status(dev, st); - return -1; - } else - return 0; -} - -int ds_reset(struct ds_device *dev, struct ds_status *st) -{ - int err; - - //err = ds_send_control(dev, COMM_1_WIRE_RESET | COMM_F | COMM_IM | COMM_SE, SPEED_FLEXIBLE); - err = ds_send_control(dev, 0x43, SPEED_NORMAL); - if (err) - return err; - - ds_wait_status(dev, st); -#if 0 - if (st->command_buffer_status) { - printk(KERN_INFO "Short circuit.\n"); - return -EIO; - } -#endif - - return 0; -} - -#if 0 -int ds_set_speed(struct ds_device *dev, int speed) -{ - int err; - - if (speed != SPEED_NORMAL && speed != SPEED_FLEXIBLE && speed != SPEED_OVERDRIVE) - return -EINVAL; - - if (speed != SPEED_OVERDRIVE) - speed = SPEED_FLEXIBLE; - - speed &= 0xff; - - err = ds_send_control_mode(dev, MOD_1WIRE_SPEED, speed); - if (err) - return err; - - return err; -} -#endif /* 0 */ - -static int ds_start_pulse(struct ds_device *dev, int delay) -{ - int err; - u8 del = 1 + (u8)(delay >> 4); - struct ds_status st; - -#if 0 - err = ds_stop_pulse(dev, 10); - if (err) - return err; - - err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_SPUE); - if (err) - return err; -#endif - err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, del); - if (err) - return err; - - err = ds_send_control(dev, COMM_PULSE | COMM_IM | COMM_F, 0); - if (err) - return err; - - mdelay(delay); - - ds_wait_status(dev, &st); - - return err; -} - -int ds_touch_bit(struct ds_device *dev, u8 bit, u8 *tbit) -{ - int err, count; - struct ds_status st; - u16 value = (COMM_BIT_IO | COMM_IM) | ((bit) ? COMM_D : 0); - u16 cmd; - - err = ds_send_control(dev, value, 0); - if (err) - return err; - - count = 0; - do { - err = ds_wait_status(dev, &st); - if (err) - return err; - - cmd = st.command0 | (st.command1 << 8); - } while (cmd != value && ++count < 10); - - if (err < 0 || count >= 10) { - printk(KERN_ERR "Failed to obtain status.\n"); - return -EINVAL; - } - - err = ds_recv_data(dev, tbit, sizeof(*tbit)); - if (err < 0) - return err; - - return 0; -} - -int ds_write_bit(struct ds_device *dev, u8 bit) -{ - int err; - struct ds_status st; - - err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | (bit) ? COMM_D : 0, 0); - if (err) - return err; - - ds_wait_status(dev, &st); - - return 0; -} - -int ds_write_byte(struct ds_device *dev, u8 byte) -{ - int err; - struct ds_status st; - u8 rbyte; - - err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM | COMM_SPU, byte); - if (err) - return err; - - err = ds_wait_status(dev, &st); - if (err) - return err; - - err = ds_recv_data(dev, &rbyte, sizeof(rbyte)); - if (err < 0) - return err; - - ds_start_pulse(dev, PULLUP_PULSE_DURATION); - - return !(byte == rbyte); -} - -int ds_read_bit(struct ds_device *dev, u8 *bit) -{ - int err; - - err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_SPUE); - if (err) - return err; - - err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | COMM_SPU | COMM_D, 0); - if (err) - return err; - - err = ds_recv_data(dev, bit, sizeof(*bit)); - if (err < 0) - return err; - - return 0; -} - -int ds_read_byte(struct ds_device *dev, u8 *byte) -{ - int err; - struct ds_status st; - - err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM , 0xff); - if (err) - return err; - - ds_wait_status(dev, &st); - - err = ds_recv_data(dev, byte, sizeof(*byte)); - if (err < 0) - return err; - - return 0; -} - -int ds_read_block(struct ds_device *dev, u8 *buf, int len) -{ - struct ds_status st; - int err; - - if (len > 64*1024) - return -E2BIG; - - memset(buf, 0xFF, len); - - err = ds_send_data(dev, buf, len); - if (err < 0) - return err; - - err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len); - if (err) - return err; - - ds_wait_status(dev, &st); - - memset(buf, 0x00, len); - err = ds_recv_data(dev, buf, len); - - return err; -} - -int ds_write_block(struct ds_device *dev, u8 *buf, int len) -{ - int err; - struct ds_status st; - - err = ds_send_data(dev, buf, len); - if (err < 0) - return err; - - ds_wait_status(dev, &st); - - err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len); - if (err) - return err; - - ds_wait_status(dev, &st); - - err = ds_recv_data(dev, buf, len); - if (err < 0) - return err; - - ds_start_pulse(dev, PULLUP_PULSE_DURATION); - - return !(err == len); -} - -#if 0 - -int ds_search(struct ds_device *dev, u64 init, u64 *buf, u8 id_number, int conditional_search) -{ - int err; - u16 value, index; - struct ds_status st; - - memset(buf, 0, sizeof(buf)); - - err = ds_send_data(ds_dev, (unsigned char *)&init, 8); - if (err) - return err; - - ds_wait_status(ds_dev, &st); - - value = COMM_SEARCH_ACCESS | COMM_IM | COMM_SM | COMM_F | COMM_RTS; - index = (conditional_search ? 0xEC : 0xF0) | (id_number << 8); - err = ds_send_control(ds_dev, value, index); - if (err) - return err; - - ds_wait_status(ds_dev, &st); - - err = ds_recv_data(ds_dev, (unsigned char *)buf, 8*id_number); - if (err < 0) - return err; - - return err/8; -} - -int ds_match_access(struct ds_device *dev, u64 init) -{ - int err; - struct ds_status st; - - err = ds_send_data(dev, (unsigned char *)&init, sizeof(init)); - if (err) - return err; - - ds_wait_status(dev, &st); - - err = ds_send_control(dev, COMM_MATCH_ACCESS | COMM_IM | COMM_RST, 0x0055); - if (err) - return err; - - ds_wait_status(dev, &st); - - return 0; -} - -int ds_set_path(struct ds_device *dev, u64 init) -{ - int err; - struct ds_status st; - u8 buf[9]; - - memcpy(buf, &init, 8); - buf[8] = BRANCH_MAIN; - - err = ds_send_data(dev, buf, sizeof(buf)); - if (err) - return err; - - ds_wait_status(dev, &st); - - err = ds_send_control(dev, COMM_SET_PATH | COMM_IM | COMM_RST, 0); - if (err) - return err; - - ds_wait_status(dev, &st); - - return 0; -} - -#endif /* 0 */ - -static int ds_probe(struct usb_interface *intf, - const struct usb_device_id *udev_id) -{ - struct usb_device *udev = interface_to_usbdev(intf); - struct usb_endpoint_descriptor *endpoint; - struct usb_host_interface *iface_desc; - int i, err; - - ds_dev = kmalloc(sizeof(struct ds_device), GFP_KERNEL); - if (!ds_dev) { - printk(KERN_INFO "Failed to allocate new DS9490R structure.\n"); - return -ENOMEM; - } - - ds_dev->udev = usb_get_dev(udev); - usb_set_intfdata(intf, ds_dev); - - err = usb_set_interface(ds_dev->udev, intf->altsetting[0].desc.bInterfaceNumber, 3); - if (err) { - printk(KERN_ERR "Failed to set alternative setting 3 for %d interface: err=%d.\n", - intf->altsetting[0].desc.bInterfaceNumber, err); - return err; - } - - err = usb_reset_configuration(ds_dev->udev); - if (err) { - printk(KERN_ERR "Failed to reset configuration: err=%d.\n", err); - return err; - } - - iface_desc = &intf->altsetting[0]; - if (iface_desc->desc.bNumEndpoints != NUM_EP-1) { - printk(KERN_INFO "Num endpoints=%d. It is not DS9490R.\n", iface_desc->desc.bNumEndpoints); - return -ENODEV; - } - - atomic_set(&ds_dev->refcnt, 0); - memset(ds_dev->ep, 0, sizeof(ds_dev->ep)); - - /* - * This loop doesn'd show control 0 endpoint, - * so we will fill only 1-3 endpoints entry. - */ - for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { - endpoint = &iface_desc->endpoint[i].desc; - - ds_dev->ep[i+1] = endpoint->bEndpointAddress; - - printk("%d: addr=%x, size=%d, dir=%s, type=%x\n", - i, endpoint->bEndpointAddress, le16_to_cpu(endpoint->wMaxPacketSize), - (endpoint->bEndpointAddress & USB_DIR_IN)?"IN":"OUT", - endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK); - } - -#if 0 - { - int err, i; - u64 buf[3]; - u64 init=0xb30000002078ee81ull; - struct ds_status st; - - ds_reset(ds_dev, &st); - err = ds_search(ds_dev, init, buf, 3, 0); - if (err < 0) - return err; - for (i=0; irefcnt)) { - printk(KERN_INFO "Waiting for DS to become free: refcnt=%d.\n", - atomic_read(&dev->refcnt)); - - if (msleep_interruptible(1000)) - flush_signals(current); - } - - usb_put_dev(dev->udev); - kfree(dev); - ds_dev = NULL; -} - -static int ds_init(void) -{ - int err; - - err = usb_register(&ds_driver); - if (err) { - printk(KERN_INFO "Failed to register DS9490R USB device: err=%d.\n", err); - return err; - } - - return 0; -} - -static void ds_fini(void) -{ - usb_deregister(&ds_driver); -} - -module_init(ds_init); -module_exit(ds_fini); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Evgeniy Polyakov "); - -EXPORT_SYMBOL(ds_touch_bit); -EXPORT_SYMBOL(ds_read_byte); -EXPORT_SYMBOL(ds_read_bit); -EXPORT_SYMBOL(ds_read_block); -EXPORT_SYMBOL(ds_write_byte); -EXPORT_SYMBOL(ds_write_bit); -EXPORT_SYMBOL(ds_write_block); -EXPORT_SYMBOL(ds_reset); -EXPORT_SYMBOL(ds_get_device); -EXPORT_SYMBOL(ds_put_device); - -/* - * This functions can be used for EEPROM programming, - * when driver will be included into mainline this will - * require uncommenting. - */ -#if 0 -EXPORT_SYMBOL(ds_start_pulse); -EXPORT_SYMBOL(ds_set_speed); -EXPORT_SYMBOL(ds_detect); -EXPORT_SYMBOL(ds_stop_pulse); -EXPORT_SYMBOL(ds_search); -#endif diff --git a/drivers/w1/masters/dscore.h b/drivers/w1/masters/dscore.h deleted file mode 100644 index 6cf5671d6eb..00000000000 --- a/drivers/w1/masters/dscore.h +++ /dev/null @@ -1,166 +0,0 @@ -/* - * dscore.h - * - * Copyright (c) 2004 Evgeniy Polyakov - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __DSCORE_H -#define __DSCORE_H - -#include -#include - -/* COMMAND TYPE CODES */ -#define CONTROL_CMD 0x00 -#define COMM_CMD 0x01 -#define MODE_CMD 0x02 - -/* CONTROL COMMAND CODES */ -#define CTL_RESET_DEVICE 0x0000 -#define CTL_START_EXE 0x0001 -#define CTL_RESUME_EXE 0x0002 -#define CTL_HALT_EXE_IDLE 0x0003 -#define CTL_HALT_EXE_DONE 0x0004 -#define CTL_FLUSH_COMM_CMDS 0x0007 -#define CTL_FLUSH_RCV_BUFFER 0x0008 -#define CTL_FLUSH_XMT_BUFFER 0x0009 -#define CTL_GET_COMM_CMDS 0x000A - -/* MODE COMMAND CODES */ -#define MOD_PULSE_EN 0x0000 -#define MOD_SPEED_CHANGE_EN 0x0001 -#define MOD_1WIRE_SPEED 0x0002 -#define MOD_STRONG_PU_DURATION 0x0003 -#define MOD_PULLDOWN_SLEWRATE 0x0004 -#define MOD_PROG_PULSE_DURATION 0x0005 -#define MOD_WRITE1_LOWTIME 0x0006 -#define MOD_DSOW0_TREC 0x0007 - -/* COMMUNICATION COMMAND CODES */ -#define COMM_ERROR_ESCAPE 0x0601 -#define COMM_SET_DURATION 0x0012 -#define COMM_BIT_IO 0x0020 -#define COMM_PULSE 0x0030 -#define COMM_1_WIRE_RESET 0x0042 -#define COMM_BYTE_IO 0x0052 -#define COMM_MATCH_ACCESS 0x0064 -#define COMM_BLOCK_IO 0x0074 -#define COMM_READ_STRAIGHT 0x0080 -#define COMM_DO_RELEASE 0x6092 -#define COMM_SET_PATH 0x00A2 -#define COMM_WRITE_SRAM_PAGE 0x00B2 -#define COMM_WRITE_EPROM 0x00C4 -#define COMM_READ_CRC_PROT_PAGE 0x00D4 -#define COMM_READ_REDIRECT_PAGE_CRC 0x21E4 -#define COMM_SEARCH_ACCESS 0x00F4 - -/* Communication command bits */ -#define COMM_TYPE 0x0008 -#define COMM_SE 0x0008 -#define COMM_D 0x0008 -#define COMM_Z 0x0008 -#define COMM_CH 0x0008 -#define COMM_SM 0x0008 -#define COMM_R 0x0008 -#define COMM_IM 0x0001 - -#define COMM_PS 0x4000 -#define COMM_PST 0x4000 -#define COMM_CIB 0x4000 -#define COMM_RTS 0x4000 -#define COMM_DT 0x2000 -#define COMM_SPU 0x1000 -#define COMM_F 0x0800 -#define COMM_NTP 0x0400 -#define COMM_ICP 0x0200 -#define COMM_RST 0x0100 - -#define PULSE_PROG 0x01 -#define PULSE_SPUE 0x02 - -#define BRANCH_MAIN 0xCC -#define BRANCH_AUX 0x33 - -/* - * Duration of the strong pull-up pulse in milliseconds. - */ -#define PULLUP_PULSE_DURATION 750 - -/* Status flags */ -#define ST_SPUA 0x01 /* Strong Pull-up is active */ -#define ST_PRGA 0x02 /* 12V programming pulse is being generated */ -#define ST_12VP 0x04 /* external 12V programming voltage is present */ -#define ST_PMOD 0x08 /* DS2490 powered from USB and external sources */ -#define ST_HALT 0x10 /* DS2490 is currently halted */ -#define ST_IDLE 0x20 /* DS2490 is currently idle */ -#define ST_EPOF 0x80 - -#define SPEED_NORMAL 0x00 -#define SPEED_FLEXIBLE 0x01 -#define SPEED_OVERDRIVE 0x02 - -#define NUM_EP 4 -#define EP_CONTROL 0 -#define EP_STATUS 1 -#define EP_DATA_OUT 2 -#define EP_DATA_IN 3 - -struct ds_device -{ - struct usb_device *udev; - struct usb_interface *intf; - - int ep[NUM_EP]; - - atomic_t refcnt; -}; - -struct ds_status -{ - u8 enable; - u8 speed; - u8 pullup_dur; - u8 ppuls_dur; - u8 pulldown_slew; - u8 write1_time; - u8 write0_time; - u8 reserved0; - u8 status; - u8 command0; - u8 command1; - u8 command_buffer_status; - u8 data_out_buffer_status; - u8 data_in_buffer_status; - u8 reserved1; - u8 reserved2; - -}; - -int ds_touch_bit(struct ds_device *, u8, u8 *); -int ds_read_byte(struct ds_device *, u8 *); -int ds_read_bit(struct ds_device *, u8 *); -int ds_write_byte(struct ds_device *, u8); -int ds_write_bit(struct ds_device *, u8); -int ds_reset(struct ds_device *, struct ds_status *); -struct ds_device * ds_get_device(void); -void ds_put_device(struct ds_device *); -int ds_write_block(struct ds_device *, u8 *, int); -int ds_read_block(struct ds_device *, u8 *, int); - -#endif /* __DSCORE_H */ - -- cgit v1.2.3 From 12003375acd879e498c6c511faf27531296f9640 Mon Sep 17 00:00:00 2001 From: Evgeniy Polyakov Date: Thu, 23 Mar 2006 19:11:58 +0300 Subject: [PATCH] w1: Userspace communication protocol over connector. There are three types of messages between w1 core and userspace: 1. Events. They are generated each time new master or slave device found either due to automatic or requested search. 2. Userspace commands. Includes read/write and search/alarm search comamnds. 3. Replies to userspace commands. From: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman --- Documentation/w1/w1.netlink | 98 +++++++++++++++++++ drivers/w1/Makefile | 2 +- drivers/w1/slaves/w1_ds2433.c | 1 - drivers/w1/slaves/w1_smem.c | 1 - drivers/w1/slaves/w1_therm.c | 1 - drivers/w1/w1.c | 137 ++++++++++++++++++--------- drivers/w1/w1.h | 38 ++++---- drivers/w1/w1_family.h | 1 + drivers/w1/w1_int.c | 27 +++--- drivers/w1/w1_io.c | 18 +--- drivers/w1/w1_netlink.c | 215 ++++++++++++++++++++++++++++++++++++------ drivers/w1/w1_netlink.h | 38 ++++++-- 12 files changed, 445 insertions(+), 132 deletions(-) create mode 100644 Documentation/w1/w1.netlink diff --git a/Documentation/w1/w1.netlink b/Documentation/w1/w1.netlink new file mode 100644 index 00000000000..3640c7c87d4 --- /dev/null +++ b/Documentation/w1/w1.netlink @@ -0,0 +1,98 @@ +Userspace communication protocol over connector [1]. + + +Message types. +============= + +There are three types of messages between w1 core and userspace: +1. Events. They are generated each time new master or slave device found + either due to automatic or requested search. +2. Userspace commands. Includes read/write and search/alarm search comamnds. +3. Replies to userspace commands. + + +Protocol. +======== + +[struct cn_msg] - connector header. It's length field is equal to size of the attached data. +[struct w1_netlink_msg] - w1 netlink header. + __u8 type - message type. + W1_SLAVE_ADD/W1_SLAVE_REMOVE - slave add/remove events. + W1_MASTER_ADD/W1_MASTER_REMOVE - master add/remove events. + W1_MASTER_CMD - userspace command for bus master device (search/alarm search). + W1_SLAVE_CMD - userspace command for slave device (read/write/ search/alarm search + for bus master device where given slave device found). + __u8 res - reserved + __u16 len - size of attached to this header data. + union { + __u8 id; - slave unique device id + struct w1_mst { + __u32 id; - master's id. + __u32 res; - reserved + } mst; + } id; + +[strucrt w1_netlink_cmd] - command for gived master or slave device. + __u8 cmd - command opcode. + W1_CMD_READ - read command. + W1_CMD_WRITE - write command. + W1_CMD_SEARCH - search command. + W1_CMD_ALARM_SEARCH - alarm search command. + __u8 res - reserved + __u16 len - length of data for this command. + For read command data must be allocated like for write command. + __u8 data[0] - data for this command. + + +Each connector message can include one or more w1_netlink_msg with zero of more attached w1_netlink_cmd messages. + +For event messages there are no w1_netlink_cmd embedded structures, only connector header +and w1_netlink_msg strucutre with "len" field being zero and filled type (one of event types) +and id - either 8 bytes of slave unique id in host order, or master's id, which is assigned +to bus master device when it is added to w1 core. + +Currently replies to userspace commands are only generated for read command request. +One reply is generated exactly for one w1_netlink_cmd read request. +Replies are not combined when sent - i.e. typical reply messages looks like the following: +[cn_msg][w1_netlink_msg][w1_netlink_cmd] +cn_msg.len = sizeof(struct w1_netlink_msg) + sizeof(struct w1_netlink_cmd) + cmd->len; +w1_netlink_msg.len = sizeof(struct w1_netlink_cmd) + cmd->len; +w1_netlink_cmd.len = cmd->len; + + +Operation steps in w1 core when new command is received. +======================================================= + +When new message (w1_netlink_msg) is received w1 core detects if it is master of slave request, +according to w1_netlink_msg.type field. +Then master or slave device is searched for. +When found, master device (requested or those one on where slave device is found) is locked. +If slave command is requested, then reset/select procedure is started to select given device. + +Then all requested in w1_netlink_msg operations are performed one by one. +If command requires reply (like read command) it is sent on command completion. + +When all commands (w1_netlink_cmd) are processed muster device is unlocked +and next w1_netlink_msg header processing started. + + +Connector [1] specific documentation. +==================================== + +Each connector message includes two u32 fields as "address". +w1 uses CN_W1_IDX and CN_W1_VAL defined in include/linux/connector.h header. +Each message also includes sequence and acknowledge numbers. +Sequence number for event messages is appropriate bus master sequence number increased with +each event message sent "through" this master. +Sequence number for userspace requests is set by userspace application. +Sequence number for reply is the same as was in request, and +acknowledge number is set to seq+1. + + +Additional documantion, source code examples. +============================================ + +1. Documentation/connector +2. http://tservice.net.ru/~s0mbre/archive/w1 +This archive includes userspace application w1d.c which +uses read/write/search commands for all master/slave devices found on the bus. diff --git a/drivers/w1/Makefile b/drivers/w1/Makefile index 0c2aa22d8c0..f0465c20a67 100644 --- a/drivers/w1/Makefile +++ b/drivers/w1/Makefile @@ -2,7 +2,7 @@ # Makefile for the Dallas's 1-wire bus. # -ifneq ($(CONFIG_NET), y) +ifeq ($(CONFIG_CONNECTOR), n) EXTRA_CFLAGS += -DNETLINK_DISABLED endif diff --git a/drivers/w1/slaves/w1_ds2433.c b/drivers/w1/slaves/w1_ds2433.c index fb118be789e..ddd01e6fc2c 100644 --- a/drivers/w1/slaves/w1_ds2433.c +++ b/drivers/w1/slaves/w1_ds2433.c @@ -22,7 +22,6 @@ #endif #include "../w1.h" -#include "../w1_io.h" #include "../w1_int.h" #include "../w1_family.h" diff --git a/drivers/w1/slaves/w1_smem.c b/drivers/w1/slaves/w1_smem.c index c6d3be54f94..cc8c02e9259 100644 --- a/drivers/w1/slaves/w1_smem.c +++ b/drivers/w1/slaves/w1_smem.c @@ -28,7 +28,6 @@ #include #include "../w1.h" -#include "../w1_io.h" #include "../w1_int.h" #include "../w1_family.h" diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c index 536d16d78de..44afdffe3c8 100644 --- a/drivers/w1/slaves/w1_therm.c +++ b/drivers/w1/slaves/w1_therm.c @@ -29,7 +29,6 @@ #include #include "../w1.h" -#include "../w1_io.h" #include "../w1_int.h" #include "../w1_family.h" diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index c9486c16850..32d8de881f1 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c @@ -35,7 +35,6 @@ #include #include "w1.h" -#include "w1_io.h" #include "w1_log.h" #include "w1_int.h" #include "w1_family.h" @@ -55,7 +54,7 @@ module_param_named(control_timeout, w1_control_timeout, int, 0); module_param_named(max_slave_count, w1_max_slave_count, int, 0); module_param_named(slave_ttl, w1_max_slave_ttl, int, 0); -DEFINE_SPINLOCK(w1_mlock); +DECLARE_MUTEX(w1_mlock); LIST_HEAD(w1_masters); static struct task_struct *w1_control_thread; @@ -75,8 +74,6 @@ static void w1_master_release(struct device *dev) struct w1_master *md = dev_to_w1_master(dev); dev_dbg(dev, "%s: Releasing %s.\n", __func__, md->name); - - dev_fini_netlink(md); memset(md, 0, sizeof(struct w1_master) + sizeof(struct w1_bus_master)); kfree(md); } @@ -85,10 +82,10 @@ static void w1_slave_release(struct device *dev) { struct w1_slave *sl = dev_to_w1_slave(dev); - dev_dbg(dev, "%s: Releasing %s.\n", __func__, sl->name); + printk("%s: Releasing %s.\n", __func__, sl->name); while (atomic_read(&sl->refcnt)) { - dev_dbg(dev, "Waiting for %s to become free: refcnt=%d.\n", + printk("Waiting for %s to become free: refcnt=%d.\n", sl->name, atomic_read(&sl->refcnt)); if (msleep_interruptible(1000)) flush_signals(current); @@ -111,7 +108,6 @@ static ssize_t w1_slave_read_id(struct kobject *kobj, char *buf, loff_t off, siz { struct w1_slave *sl = kobj_to_w1_slave(kobj); - atomic_inc(&sl->refcnt); if (off > 8) { count = 0; } else { @@ -120,7 +116,6 @@ static ssize_t w1_slave_read_id(struct kobject *kobj, char *buf, loff_t off, siz memcpy(buf, (u8 *)&sl->reg_num, count); } - atomic_dec(&sl->refcnt); return count; } @@ -230,12 +225,11 @@ struct device w1_master_device = { .release = &w1_master_release }; -static struct device_driver w1_slave_driver = { +struct device_driver w1_slave_driver = { .name = "w1_slave_driver", .bus = &w1_bus_type, }; -#if 0 struct device w1_slave_device = { .parent = NULL, .bus = &w1_bus_type, @@ -243,7 +237,6 @@ struct device w1_slave_device = { .driver = &w1_slave_driver, .release = &w1_slave_release }; -#endif /* 0 */ static ssize_t w1_master_attribute_show_name(struct device *dev, struct device_attribute *attr, char *buf) { @@ -423,7 +416,7 @@ int w1_create_master_attributes(struct w1_master *master) return sysfs_create_group(&master->dev.kobj, &w1_master_defattr_group); } -static void w1_destroy_master_attributes(struct w1_master *master) +void w1_destroy_master_attributes(struct w1_master *master) { sysfs_remove_group(&master->dev.kobj, &w1_master_defattr_group); } @@ -454,14 +447,11 @@ static int w1_uevent(struct device *dev, char **envp, int num_envp, char *buffer if (dev->driver != &w1_slave_driver || !sl) return 0; - err = add_uevent_var(envp, num_envp, &cur_index, buffer, buffer_size, - &cur_len, "W1_FID=%02X", sl->reg_num.family); + err = add_uevent_var(envp, num_envp, &cur_index, buffer, buffer_size, &cur_len, "W1_FID=%02X", sl->reg_num.family); if (err) return err; - err = add_uevent_var(envp, num_envp, &cur_index, buffer, buffer_size, - &cur_len, "W1_SLAVE_ID=%024LX", - (unsigned long long)sl->reg_num.id); + err = add_uevent_var(envp, num_envp, &cur_index, buffer, buffer_size, &cur_len, "W1_SLAVE_ID=%024LX", (u64)sl->reg_num.id); if (err) return err; @@ -563,6 +553,7 @@ static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn) sl->master = dev; set_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags); + memset(&msg, 0, sizeof(msg)); memcpy(&sl->reg_num, rn, sizeof(sl->reg_num)); atomic_set(&sl->refcnt, 0); init_completion(&sl->released); @@ -593,7 +584,7 @@ static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn) sl->ttl = dev->slave_ttl; dev->slave_count++; - memcpy(&msg.id.id, rn, sizeof(msg.id.id)); + memcpy(msg.id.id, rn, sizeof(msg.id)); msg.type = W1_SLAVE_ADD; w1_netlink_send(dev, &msg); @@ -611,7 +602,8 @@ static void w1_slave_detach(struct w1_slave *sl) if (sl->family->fops && sl->family->fops->remove_slave) sl->family->fops->remove_slave(sl); - memcpy(&msg.id.id, &sl->reg_num, sizeof(msg.id.id)); + memset(&msg, 0, sizeof(msg)); + memcpy(msg.id.id, &sl->reg_num, sizeof(msg.id)); msg.type = W1_SLAVE_REMOVE; w1_netlink_send(sl->master, &msg); @@ -628,7 +620,7 @@ static struct w1_master *w1_search_master(void *data) struct w1_master *dev; int found = 0; - spin_lock_bh(&w1_mlock); + down(&w1_mlock); list_for_each_entry(dev, &w1_masters, w1_master_entry) { if (dev->bus_master->data == data) { found = 1; @@ -636,22 +628,69 @@ static struct w1_master *w1_search_master(void *data) break; } } - spin_unlock_bh(&w1_mlock); + up(&w1_mlock); return (found)?dev:NULL; } +struct w1_master *w1_search_master_id(u32 id) +{ + struct w1_master *dev; + int found = 0; + + down(&w1_mlock); + list_for_each_entry(dev, &w1_masters, w1_master_entry) { + if (dev->id == id) { + found = 1; + atomic_inc(&dev->refcnt); + break; + } + } + up(&w1_mlock); + + return (found)?dev:NULL; +} + +struct w1_slave *w1_search_slave(struct w1_reg_num *id) +{ + struct w1_master *dev; + struct w1_slave *sl = NULL; + int found = 0; + + down(&w1_mlock); + list_for_each_entry(dev, &w1_masters, w1_master_entry) { + down(&dev->mutex); + list_for_each_entry(sl, &dev->slist, w1_slave_entry) { + if (sl->reg_num.family == id->family && + sl->reg_num.id == id->id && + sl->reg_num.crc == id->crc) { + found = 1; + atomic_inc(&dev->refcnt); + atomic_inc(&sl->refcnt); + break; + } + } + up(&dev->mutex); + + if (found) + break; + } + up(&w1_mlock); + + return (found)?sl:NULL; +} + void w1_reconnect_slaves(struct w1_family *f) { struct w1_master *dev; - spin_lock_bh(&w1_mlock); + down(&w1_mlock); list_for_each_entry(dev, &w1_masters, w1_master_entry) { dev_dbg(&dev->dev, "Reconnecting slaves in %s into new family %02x.\n", dev->name, f->fid); set_bit(W1_MASTER_NEED_RECONNECT, &dev->flags); } - spin_unlock_bh(&w1_mlock); + up(&w1_mlock); } static void w1_slave_found(void *data, u64 rn) @@ -713,7 +752,7 @@ static void w1_slave_found(void *data, u64 rn) * @dev The master device to search * @cb Function to call when a device is found */ -void w1_search(struct w1_master *dev, w1_slave_found_callback cb) +void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb) { u64 last_rn, rn, tmp64; int i, slave_count = 0; @@ -744,7 +783,7 @@ void w1_search(struct w1_master *dev, w1_slave_found_callback cb) } /* Start the search */ - w1_write_8(dev, W1_SEARCH); + w1_write_8(dev, search_type); for (i = 0; i < 64; ++i) { /* Determine the direction/search bit */ if (i == desc_bit) @@ -806,9 +845,9 @@ static int w1_control(void *data) if (kthread_should_stop() || test_bit(W1_MASTER_NEED_EXIT, &dev->flags)) { set_bit(W1_MASTER_NEED_EXIT, &dev->flags); - spin_lock(&w1_mlock); + down(&w1_mlock); list_del(&dev->w1_master_entry); - spin_unlock(&w1_mlock); + up(&w1_mlock); down(&dev->mutex); list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) { @@ -843,10 +882,31 @@ static int w1_control(void *data) return 0; } +void w1_search_process(struct w1_master *dev, u8 search_type) +{ + struct w1_slave *sl, *sln; + + list_for_each_entry(sl, &dev->slist, w1_slave_entry) + clear_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags); + + w1_search_devices(dev, search_type, w1_slave_found); + + list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) { + if (!test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags) && !--sl->ttl) { + w1_slave_detach(sl); + + dev->slave_count--; + } else if (test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags)) + sl->ttl = dev->slave_ttl; + } + + if (dev->search_count > 0) + dev->search_count--; +} + int w1_process(void *data) { struct w1_master *dev = (struct w1_master *) data; - struct w1_slave *sl, *sln; while (!kthread_should_stop() && !test_bit(W1_MASTER_NEED_EXIT, &dev->flags)) { try_to_freeze(); @@ -864,22 +924,7 @@ int w1_process(void *data) if (down_interruptible(&dev->mutex)) continue; - list_for_each_entry(sl, &dev->slist, w1_slave_entry) - clear_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags); - - w1_search_devices(dev, w1_slave_found); - - list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) { - if (!test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags) && !--sl->ttl) { - w1_slave_detach(sl); - - dev->slave_count--; - } else if (test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags)) - sl->ttl = dev->slave_ttl; - } - - if (dev->search_count > 0) - dev->search_count--; + w1_search_process(dev, W1_SEARCH); up(&dev->mutex); } @@ -895,6 +940,8 @@ static int w1_init(void) printk(KERN_INFO "Driver for 1-wire Dallas network protocol.\n"); + w1_init_netlink(); + retval = bus_register(&w1_bus_type); if (retval) { printk(KERN_ERR "Failed to register bus. err=%d.\n", retval); @@ -947,6 +994,8 @@ static void w1_fini(void) list_for_each_entry(dev, &w1_masters, w1_master_entry) __w1_remove_master_device(dev); + w1_fini_netlink(); + kthread_stop(w1_control_thread); driver_unregister(&w1_slave_driver); diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h index 02e8caddfb3..e8c96e6e741 100644 --- a/drivers/w1/w1.h +++ b/drivers/w1/w1.h @@ -42,8 +42,6 @@ struct w1_reg_num #include #include -#include - #include #include "w1_family.h" @@ -52,7 +50,7 @@ struct w1_reg_num #define W1_SLAVE_DATA_SIZE 128 #define W1_SEARCH 0xF0 -#define W1_CONDITIONAL_SEARCH 0xEC +#define W1_ALARM_SEARCH 0xEC #define W1_CONVERT_TEMP 0x44 #define W1_SKIP_ROM 0xCC #define W1_READ_SCRATCHPAD 0xBE @@ -145,8 +143,8 @@ struct w1_bus_master */ u8 (*reset_bus)(void *); - /** Really nice hardware can handles the ROM searches */ - void (*search)(void *, w1_slave_found_callback); + /** Really nice hardware can handles the different types of ROM search */ + void (*search)(void *, u8, w1_slave_found_callback); }; #define W1_MASTER_NEED_EXIT 0 @@ -180,12 +178,26 @@ struct w1_master struct w1_bus_master *bus_master; - u32 seq, groups; - struct sock *nls; + u32 seq; }; int w1_create_master_attributes(struct w1_master *); -void w1_search(struct w1_master *dev, w1_slave_found_callback cb); +void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb); +void w1_search_devices(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb); +struct w1_slave *w1_search_slave(struct w1_reg_num *id); +void w1_search_process(struct w1_master *dev, u8 search_type); +struct w1_master *w1_search_master_id(u32 id); + +void w1_delay(unsigned long); +u8 w1_touch_bit(struct w1_master *, int); +u8 w1_triplet(struct w1_master *dev, int bdir); +void w1_write_8(struct w1_master *, u8); +u8 w1_read_8(struct w1_master *); +int w1_reset_bus(struct w1_master *); +u8 w1_calc_crc8(u8 *, int); +void w1_write_block(struct w1_master *, const u8 *, int); +u8 w1_read_block(struct w1_master *, u8 *, int); +int w1_reset_select_slave(struct w1_slave *sl); static inline struct w1_slave* dev_to_w1_slave(struct device *dev) { @@ -202,16 +214,6 @@ static inline struct w1_master* dev_to_w1_master(struct device *dev) return container_of(dev, struct w1_master, dev); } -extern int w1_max_slave_count; -extern int w1_max_slave_ttl; -extern spinlock_t w1_mlock; -extern struct list_head w1_masters; -extern struct device_driver w1_master_driver; -extern struct device w1_master_device; - -int w1_process(void *data); -void w1_reconnect_slaves(struct w1_family *f); - #endif /* __KERNEL__ */ #endif /* __W1_H */ diff --git a/drivers/w1/w1_family.h b/drivers/w1/w1_family.h index 2ca0489c716..22a9d52c94f 100644 --- a/drivers/w1/w1_family.h +++ b/drivers/w1/w1_family.h @@ -64,5 +64,6 @@ void __w1_family_put(struct w1_family *); struct w1_family * w1_family_registered(u8); void w1_unregister_family(struct w1_family *); int w1_register_family(struct w1_family *); +void w1_reconnect_slaves(struct w1_family *f); #endif /* __W1_FAMILY_H */ diff --git a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c index 68565aacec7..ae78473d11f 100644 --- a/drivers/w1/w1_int.c +++ b/drivers/w1/w1_int.c @@ -27,10 +27,19 @@ #include "w1.h" #include "w1_log.h" #include "w1_netlink.h" -#include "w1_int.h" static u32 w1_ids = 1; +extern struct device_driver w1_master_driver; +extern struct bus_type w1_bus_type; +extern struct device w1_master_device; +extern int w1_max_slave_count; +extern int w1_max_slave_ttl; +extern struct list_head w1_masters; +extern struct semaphore w1_mlock; + +extern int w1_process(void *); + static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl, struct device_driver *driver, struct device *device) @@ -74,16 +83,11 @@ static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl, dev->driver = driver; - dev->groups = 1; dev->seq = 1; - dev_init_netlink(dev); err = device_register(&dev->dev); if (err) { printk(KERN_ERR "Failed to register master device. err=%d\n", err); - - dev_fini_netlink(dev); - memset(dev, 0, sizeof(struct w1_master)); kfree(dev); dev = NULL; @@ -92,7 +96,7 @@ static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl, return dev; } -static void w1_free_dev(struct w1_master *dev) +void w1_free_dev(struct w1_master *dev) { device_unregister(&dev->dev); } @@ -131,12 +135,12 @@ int w1_add_master_device(struct w1_bus_master *master) dev->initialized = 1; - spin_lock(&w1_mlock); + down(&w1_mlock); list_add(&dev->w1_master_entry, &w1_masters); - spin_unlock(&w1_mlock); + up(&w1_mlock); + memset(&msg, 0, sizeof(msg)); msg.id.mst.id = dev->id; - msg.id.mst.pid = dev->thread->pid; msg.type = W1_MASTER_ADD; w1_netlink_send(dev, &msg); @@ -153,7 +157,6 @@ err_out_free_dev: void __w1_remove_master_device(struct w1_master *dev) { struct w1_netlink_msg msg; - pid_t pid = dev->thread->pid; set_bit(W1_MASTER_NEED_EXIT, &dev->flags); kthread_stop(dev->thread); @@ -166,8 +169,8 @@ void __w1_remove_master_device(struct w1_master *dev) flush_signals(current); } + memset(&msg, 0, sizeof(msg)); msg.id.mst.id = dev->id; - msg.id.mst.pid = pid; msg.type = W1_MASTER_REMOVE; w1_netlink_send(dev, &msg); diff --git a/drivers/w1/w1_io.c b/drivers/w1/w1_io.c index f7f7e8bec30..a6eb9db7359 100644 --- a/drivers/w1/w1_io.c +++ b/drivers/w1/w1_io.c @@ -26,7 +26,6 @@ #include "w1.h" #include "w1_log.h" -#include "w1_io.h" static int w1_delay_parm = 1; module_param_named(delay_coef, w1_delay_parm, int, 0); @@ -268,13 +267,13 @@ u8 w1_calc_crc8(u8 * data, int len) return crc; } -void w1_search_devices(struct w1_master *dev, w1_slave_found_callback cb) +void w1_search_devices(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb) { dev->attempts++; if (dev->bus_master->search) - dev->bus_master->search(dev->bus_master->data, cb); + dev->bus_master->search(dev->bus_master->data, search_type, cb); else - w1_search(dev, cb); + w1_search(dev, search_type, cb); } /** @@ -300,13 +299,4 @@ int w1_reset_select_slave(struct w1_slave *sl) return 0; } -EXPORT_SYMBOL(w1_touch_bit); -EXPORT_SYMBOL(w1_write_8); -EXPORT_SYMBOL(w1_read_8); -EXPORT_SYMBOL(w1_reset_bus); -EXPORT_SYMBOL(w1_calc_crc8); -EXPORT_SYMBOL(w1_delay); -EXPORT_SYMBOL(w1_read_block); -EXPORT_SYMBOL(w1_write_block); -EXPORT_SYMBOL(w1_search_devices); -EXPORT_SYMBOL(w1_reset_select_slave); +EXPORT_SYMBOL_GPL(w1_calc_crc8); diff --git a/drivers/w1/w1_netlink.c b/drivers/w1/w1_netlink.c index 328645da797..d48f3acdb8a 100644 --- a/drivers/w1/w1_netlink.c +++ b/drivers/w1/w1_netlink.c @@ -21,6 +21,7 @@ #include #include +#include #include "w1.h" #include "w1_log.h" @@ -29,50 +30,204 @@ #ifndef NETLINK_DISABLED void w1_netlink_send(struct w1_master *dev, struct w1_netlink_msg *msg) { - unsigned int size; - struct sk_buff *skb; - struct w1_netlink_msg *data; - struct nlmsghdr *nlh; + char buf[sizeof(struct cn_msg) + sizeof(struct w1_netlink_msg)]; + struct cn_msg *m = (struct cn_msg *)buf; + struct w1_netlink_msg *w = (struct w1_netlink_msg *)(m+1); - if (!dev->nls) - return; + memset(buf, 0, sizeof(buf)); - size = NLMSG_SPACE(sizeof(struct w1_netlink_msg)); + m->id.idx = CN_W1_IDX; + m->id.val = CN_W1_VAL; - skb = alloc_skb(size, GFP_ATOMIC); - if (!skb) { - dev_err(&dev->dev, "skb_alloc() failed.\n"); - return; - } + m->seq = dev->seq++; + m->len = sizeof(struct w1_netlink_msg); - nlh = NLMSG_PUT(skb, 0, dev->seq++, NLMSG_DONE, size - sizeof(*nlh)); + memcpy(w, msg, sizeof(struct w1_netlink_msg)); - data = (struct w1_netlink_msg *)NLMSG_DATA(nlh); + cn_netlink_send(m, 0, GFP_KERNEL); +} - memcpy(data, msg, sizeof(struct w1_netlink_msg)); +static int w1_process_command_master(struct w1_master *dev, struct cn_msg *msg, + struct w1_netlink_msg *hdr, struct w1_netlink_cmd *cmd) +{ + dev_dbg(&dev->dev, "%s: %s: cmd=%02x, len=%u.\n", + __func__, dev->name, cmd->cmd, cmd->len); - NETLINK_CB(skb).dst_group = dev->groups; - netlink_broadcast(dev->nls, skb, 0, dev->groups, GFP_ATOMIC); + if (cmd->cmd != W1_CMD_SEARCH && cmd->cmd != W1_CMD_ALARM_SEARCH) + return -EINVAL; -nlmsg_failure: - return; + w1_search_process(dev, (cmd->cmd == W1_CMD_ALARM_SEARCH)?W1_ALARM_SEARCH:W1_SEARCH); + return 0; } -int dev_init_netlink(struct w1_master *dev) +static int w1_send_read_reply(struct w1_slave *sl, struct cn_msg *msg, + struct w1_netlink_msg *hdr, struct w1_netlink_cmd *cmd) { - dev->nls = netlink_kernel_create(NETLINK_W1, 1, NULL, THIS_MODULE); - if (!dev->nls) { - printk(KERN_ERR "Failed to create new netlink socket(%u) for w1 master %s.\n", - NETLINK_W1, dev->dev.bus_id); + void *data; + struct w1_netlink_msg *h; + struct w1_netlink_cmd *c; + struct cn_msg *cm; + int err; + + data = kzalloc(sizeof(struct cn_msg) + + sizeof(struct w1_netlink_msg) + + sizeof(struct w1_netlink_cmd) + + cmd->len, GFP_KERNEL); + if (!data) + return -ENOMEM; + + cm = (struct cn_msg *)(data); + h = (struct w1_netlink_msg *)(cm + 1); + c = (struct w1_netlink_cmd *)(h + 1); + + memcpy(cm, msg, sizeof(struct cn_msg)); + memcpy(h, hdr, sizeof(struct w1_netlink_msg)); + memcpy(c, cmd, sizeof(struct w1_netlink_cmd)); + + cm->ack = msg->seq+1; + cm->len = sizeof(struct w1_netlink_msg) + sizeof(struct w1_netlink_cmd) + cmd->len; + + h->len = sizeof(struct w1_netlink_cmd) + cmd->len; + + memcpy(c->data, cmd->data, c->len); + + err = cn_netlink_send(cm, 0, GFP_KERNEL); + + kfree(data); + + return err; +} + +static int w1_process_command_slave(struct w1_slave *sl, struct cn_msg *msg, + struct w1_netlink_msg *hdr, struct w1_netlink_cmd *cmd) +{ + int err = 0; + + dev_dbg(&sl->master->dev, "%s: %02x.%012llx.%02x: cmd=%02x, len=%u.\n", + __func__, sl->reg_num.family, (unsigned long long)sl->reg_num.id, sl->reg_num.crc, + cmd->cmd, cmd->len); + + switch (cmd->cmd) { + case W1_CMD_READ: + w1_read_block(sl->master, cmd->data, cmd->len); + w1_send_read_reply(sl, msg, hdr, cmd); + break; + case W1_CMD_WRITE: + w1_write_block(sl->master, cmd->data, cmd->len); + break; + case W1_CMD_SEARCH: + case W1_CMD_ALARM_SEARCH: + w1_search_process(sl->master, + (cmd->cmd == W1_CMD_ALARM_SEARCH)?W1_ALARM_SEARCH:W1_SEARCH); + break; + default: + err = -1; + break; } - return 0; + return err; +} + +static void w1_cn_callback(void *data) +{ + struct cn_msg *msg = data; + struct w1_netlink_msg *m = (struct w1_netlink_msg *)(msg + 1); + struct w1_netlink_cmd *cmd; + struct w1_slave *sl; + struct w1_master *dev; + int err = 0; + + while (msg->len && !err) { + struct w1_reg_num id; + u16 mlen = m->len; + u8 *cmd_data = m->data; + + dev = NULL; + sl = NULL; + + memcpy(&id, m->id.id, sizeof(id)); +#if 0 + printk("%s: %02x.%012llx.%02x: type=%02x, len=%u.\n", + __func__, id.family, (unsigned long long)id.id, id.crc, m->type, m->len); +#endif + if (m->len + sizeof(struct w1_netlink_msg) > msg->len) { + err = -E2BIG; + break; + } + + if (!mlen) + goto out_cont; + + if (m->type == W1_MASTER_CMD) { + dev = w1_search_master_id(m->id.mst.id); + } else if (m->type == W1_SLAVE_CMD) { + sl = w1_search_slave(&id); + if (sl) + dev = sl->master; + } + + if (!dev) { + err = -ENODEV; + goto out_cont; + } + + down(&dev->mutex); + + if (sl && w1_reset_select_slave(sl)) { + err = -ENODEV; + goto out_up; + } + + while (mlen) { + cmd = (struct w1_netlink_cmd *)cmd_data; + + if (cmd->len + sizeof(struct w1_netlink_cmd) > mlen) { + err = -E2BIG; + break; + } + + if (sl) + w1_process_command_slave(sl, msg, m, cmd); + else + w1_process_command_master(dev, msg, m, cmd); + + cmd_data += cmd->len + sizeof(struct w1_netlink_cmd); + mlen -= cmd->len + sizeof(struct w1_netlink_cmd); + } +out_up: + atomic_dec(&dev->refcnt); + if (sl) + atomic_dec(&sl->refcnt); + up(&dev->mutex); +out_cont: + msg->len -= sizeof(struct w1_netlink_msg) + m->len; + m = (struct w1_netlink_msg *)(((u8 *)m) + sizeof(struct w1_netlink_msg) + m->len); + + /* + * Let's allow requests for nonexisting devices. + */ + if (err == -ENODEV) + err = 0; + } +#if 0 + if (err) { + printk("%s: malformed message. Dropping.\n", __func__); + } +#endif } -void dev_fini_netlink(struct w1_master *dev) +int w1_init_netlink(void) { - if (dev->nls && dev->nls->sk_socket) - sock_release(dev->nls->sk_socket); + struct cb_id w1_id = {.idx = CN_W1_IDX, .val = CN_W1_VAL}; + + return cn_add_callback(&w1_id, "w1", &w1_cn_callback); +} + +void w1_fini_netlink(void) +{ + struct cb_id w1_id = {.idx = CN_W1_IDX, .val = CN_W1_VAL}; + + cn_del_callback(&w1_id); } #else #warning Netlink support is disabled. Please compile with NET support enabled. @@ -81,12 +236,12 @@ void w1_netlink_send(struct w1_master *dev, struct w1_netlink_msg *msg) { } -int dev_init_netlink(struct w1_master *dev) +int w1_init_netlink(void) { return 0; } -void dev_fini_netlink(struct w1_master *dev) +void w1_fini_netlink(void) { } #endif diff --git a/drivers/w1/w1_netlink.h b/drivers/w1/w1_netlink.h index eb0c8b3152c..5644221f9a4 100644 --- a/drivers/w1/w1_netlink.h +++ b/drivers/w1/w1_netlink.h @@ -23,37 +23,55 @@ #define __W1_NETLINK_H #include +#include #include "w1.h" +#define CN_W1_IDX 3 +#define CN_W1_VAL 1 + enum w1_netlink_message_types { W1_SLAVE_ADD = 0, W1_SLAVE_REMOVE, W1_MASTER_ADD, W1_MASTER_REMOVE, + W1_MASTER_CMD, + W1_SLAVE_CMD, }; struct w1_netlink_msg { __u8 type; - __u8 reserved[3]; - union - { - struct w1_reg_num id; - __u64 w1_id; - struct - { + __u8 reserved; + __u16 len; + union { + __u8 id[8]; + struct w1_mst { __u32 id; - __u32 pid; + __u32 res; } mst; } id; + __u8 data[0]; +}; + +#define W1_CMD_READ 0x0 +#define W1_CMD_WRITE 0x1 +#define W1_CMD_SEARCH 0x2 +#define W1_CMD_ALARM_SEARCH 0x3 + +struct w1_netlink_cmd +{ + __u8 cmd; + __u8 res; + __u16 len; + __u8 data[0]; }; #ifdef __KERNEL__ void w1_netlink_send(struct w1_master *, struct w1_netlink_msg *); -int dev_init_netlink(struct w1_master *dev); -void dev_fini_netlink(struct w1_master *dev); +int w1_init_netlink(void); +void w1_fini_netlink(void); #endif /* __KERNEL__ */ #endif /* __W1_NETLINK_H */ -- cgit v1.2.3 From b6043fcab4b2b06b9fcde4c783ab253cdc2c1129 Mon Sep 17 00:00:00 2001 From: Evgeniy Polyakov Date: Thu, 23 Mar 2006 19:11:58 +0300 Subject: [PATCH] w1: Move w1-connector definitions into linux/include/connector.h Signed-off-by: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman --- drivers/w1/w1_netlink.h | 3 --- include/linux/connector.h | 5 ++++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/w1/w1_netlink.h b/drivers/w1/w1_netlink.h index 5644221f9a4..56122b9e929 100644 --- a/drivers/w1/w1_netlink.h +++ b/drivers/w1/w1_netlink.h @@ -27,9 +27,6 @@ #include "w1.h" -#define CN_W1_IDX 3 -#define CN_W1_VAL 1 - enum w1_netlink_message_types { W1_SLAVE_ADD = 0, W1_SLAVE_REMOVE, diff --git a/include/linux/connector.h b/include/linux/connector.h index ad1a22c1c42..4c02119c6ab 100644 --- a/include/linux/connector.h +++ b/include/linux/connector.h @@ -34,8 +34,11 @@ #define CN_VAL_PROC 0x1 #define CN_IDX_CIFS 0x2 #define CN_VAL_CIFS 0x1 +#define CN_W1_IDX 0x3 /* w1 communication */ +#define CN_W1_VAL 0x1 -#define CN_NETLINK_USERS 1 + +#define CN_NETLINK_USERS 4 /* * Maximum connector's message size. -- cgit v1.2.3 From bb5427b5466782ba0bbf56a4ed752e08b65a5d08 Mon Sep 17 00:00:00 2001 From: Evgeniy Polyakov Date: Thu, 23 Mar 2006 19:11:58 +0300 Subject: [PATCH] w1: netlink: Mark netlink group 1 as unused. netlink_w1 was moved to connector. Signed-off-by: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman --- include/linux/netlink.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/netlink.h b/include/linux/netlink.h index 87b8a5703eb..855b44668ca 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h @@ -5,7 +5,7 @@ #include #define NETLINK_ROUTE 0 /* Routing/device hook */ -#define NETLINK_W1 1 /* 1-wire subsystem */ +#define NETLINK_UNUSED 1 /* Unused number */ #define NETLINK_USERSOCK 2 /* Reserved for user mode socket protocols */ #define NETLINK_FIREWALL 3 /* Firewalling hook */ #define NETLINK_INET_DIAG 4 /* INET socket monitoring */ -- cgit v1.2.3 From 46e07f6e5eb0e465e086b8f485f4238bd453e3e9 Mon Sep 17 00:00:00 2001 From: Evgeniy Polyakov Date: Mon, 3 Apr 2006 12:01:12 +0400 Subject: [PATCH] w1: Make w1 connector notifications depend on connector. Make w1 connector notifications depend on connector. Signed-off-by: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman --- drivers/w1/Kconfig | 14 +++++++++++++- drivers/w1/Makefile | 4 ---- drivers/w1/w1_netlink.c | 4 +--- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/drivers/w1/Kconfig b/drivers/w1/Kconfig index 5e61ed59a41..0c6c4359bf7 100644 --- a/drivers/w1/Kconfig +++ b/drivers/w1/Kconfig @@ -3,7 +3,7 @@ menu "Dallas's 1-wire bus" config W1 tristate "Dallas's 1-wire support" ---help--- - Dallas's 1-wire bus is useful to connect slow 1-pin devices + Dallas' 1-wire bus is useful to connect slow 1-pin devices such as iButtons and thermal sensors. If you want W1 support, you should say Y here. @@ -11,6 +11,18 @@ config W1 This W1 support can also be built as a module. If so, the module will be called wire.ko. +config W1_CON + depends on CONNECTOR + bool "Userspace communication over connector" + default y + --- help --- + This allows to communicate with userspace using connector [Documentation/connector]. + There are three types of messages between w1 core and userspace: + 1. Events. They are generated each time new master or slave device found + either due to automatic or requested search. + 2. Userspace commands. Includes read/write and search/alarm search comamnds. + 3. Replies to userspace commands. + source drivers/w1/masters/Kconfig source drivers/w1/slaves/Kconfig diff --git a/drivers/w1/Makefile b/drivers/w1/Makefile index f0465c20a67..93845a2c7c2 100644 --- a/drivers/w1/Makefile +++ b/drivers/w1/Makefile @@ -2,10 +2,6 @@ # Makefile for the Dallas's 1-wire bus. # -ifeq ($(CONFIG_CONNECTOR), n) -EXTRA_CFLAGS += -DNETLINK_DISABLED -endif - ifeq ($(CONFIG_W1_DS2433_CRC), y) EXTRA_CFLAGS += -DCONFIG_W1_F23_CRC endif diff --git a/drivers/w1/w1_netlink.c b/drivers/w1/w1_netlink.c index d48f3acdb8a..d539e09aad3 100644 --- a/drivers/w1/w1_netlink.c +++ b/drivers/w1/w1_netlink.c @@ -27,7 +27,7 @@ #include "w1_log.h" #include "w1_netlink.h" -#ifndef NETLINK_DISABLED +#if defined(CONFIG_W1_CON) && (defined(CONFIG_CONNECTOR) || (defined(CONFIG_CONNECTOR_MODULE) && defined(CONFIG_W1_MODULE))) void w1_netlink_send(struct w1_master *dev, struct w1_netlink_msg *msg) { char buf[sizeof(struct cn_msg) + sizeof(struct w1_netlink_msg)]; @@ -230,8 +230,6 @@ void w1_fini_netlink(void) cn_del_callback(&w1_id); } #else -#warning Netlink support is disabled. Please compile with NET support enabled. - void w1_netlink_send(struct w1_master *dev, struct w1_netlink_msg *msg) { } -- cgit v1.2.3 From abd52a13206e02537ca1dc08fc5438c7d27bdbf1 Mon Sep 17 00:00:00 2001 From: Evgeniy Polyakov Date: Mon, 3 Apr 2006 12:04:27 +0400 Subject: [PATCH] w1: Use mutexes instead of semaphores. Use mutexes instead of semaphores. Patch tested on x86_64 and i386 with test bus master driver. Signed-off-by: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman --- drivers/w1/masters/ds2482.c | 24 ++++----- drivers/w1/masters/ds2490.c | 10 ++-- drivers/w1/slaves/w1_ds2433.c | 20 ++------ drivers/w1/slaves/w1_therm.c | 12 +---- drivers/w1/w1.c | 114 +++++++++++++++--------------------------- drivers/w1/w1.h | 5 +- drivers/w1/w1_int.c | 8 +-- drivers/w1/w1_netlink.c | 4 +- 8 files changed, 70 insertions(+), 127 deletions(-) diff --git a/drivers/w1/masters/ds2482.c b/drivers/w1/masters/ds2482.c index d1cacd23576..af492cc48db 100644 --- a/drivers/w1/masters/ds2482.c +++ b/drivers/w1/masters/ds2482.c @@ -125,7 +125,7 @@ struct ds2482_w1_chan { struct ds2482_data { struct i2c_client client; - struct semaphore access_lock; + struct mutex access_lock; /* 1-wire interface(s) */ int w1_count; /* 1 or 8 */ @@ -265,7 +265,7 @@ static u8 ds2482_w1_touch_bit(void *data, u8 bit) struct ds2482_data *pdev = pchan->pdev; int status = -1; - down(&pdev->access_lock); + mutex_lock(&pdev->access_lock); /* Select the channel */ ds2482_wait_1wire_idle(pdev); @@ -277,7 +277,7 @@ static u8 ds2482_w1_touch_bit(void *data, u8 bit) bit ? 0xFF : 0)) status = ds2482_wait_1wire_idle(pdev); - up(&pdev->access_lock); + mutex_unlock(&pdev->access_lock); return (status & DS2482_REG_STS_SBR) ? 1 : 0; } @@ -297,7 +297,7 @@ static u8 ds2482_w1_triplet(void *data, u8 dbit) struct ds2482_data *pdev = pchan->pdev; int status = (3 << 5); - down(&pdev->access_lock); + mutex_lock(&pdev->access_lock); /* Select the channel */ ds2482_wait_1wire_idle(pdev); @@ -309,7 +309,7 @@ static u8 ds2482_w1_triplet(void *data, u8 dbit) dbit ? 0xFF : 0)) status = ds2482_wait_1wire_idle(pdev); - up(&pdev->access_lock); + mutex_unlock(&pdev->access_lock); /* Decode the status */ return (status >> 5); @@ -326,7 +326,7 @@ static void ds2482_w1_write_byte(void *data, u8 byte) struct ds2482_w1_chan *pchan = data; struct ds2482_data *pdev = pchan->pdev; - down(&pdev->access_lock); + mutex_lock(&pdev->access_lock); /* Select the channel */ ds2482_wait_1wire_idle(pdev); @@ -336,7 +336,7 @@ static void ds2482_w1_write_byte(void *data, u8 byte) /* Send the write byte command */ ds2482_send_cmd_data(pdev, DS2482_CMD_1WIRE_WRITE_BYTE, byte); - up(&pdev->access_lock); + mutex_unlock(&pdev->access_lock); } /** @@ -351,7 +351,7 @@ static u8 ds2482_w1_read_byte(void *data) struct ds2482_data *pdev = pchan->pdev; int result; - down(&pdev->access_lock); + mutex_lock(&pdev->access_lock); /* Select the channel */ ds2482_wait_1wire_idle(pdev); @@ -370,7 +370,7 @@ static u8 ds2482_w1_read_byte(void *data) /* Read the data byte */ result = i2c_smbus_read_byte(&pdev->client); - up(&pdev->access_lock); + mutex_unlock(&pdev->access_lock); return result; } @@ -389,7 +389,7 @@ static u8 ds2482_w1_reset_bus(void *data) int err; u8 retval = 1; - down(&pdev->access_lock); + mutex_lock(&pdev->access_lock); /* Select the channel */ ds2482_wait_1wire_idle(pdev); @@ -409,7 +409,7 @@ static u8 ds2482_w1_reset_bus(void *data) 0xF0); } - up(&pdev->access_lock); + mutex_unlock(&pdev->access_lock); return retval; } @@ -482,7 +482,7 @@ static int ds2482_detect(struct i2c_adapter *adapter, int address, int kind) snprintf(new_client->name, sizeof(new_client->name), "ds2482-%d00", data->w1_count); - init_MUTEX(&data->access_lock); + mutex_init(&data->access_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) diff --git a/drivers/w1/masters/ds2490.c b/drivers/w1/masters/ds2490.c index 637677833da..299e274d241 100644 --- a/drivers/w1/masters/ds2490.c +++ b/drivers/w1/masters/ds2490.c @@ -169,7 +169,7 @@ static int ds_send_control(struct ds_device *, u16, u16); static int ds_send_control_cmd(struct ds_device *, u16, u16); static LIST_HEAD(ds_devices); -static DECLARE_MUTEX(ds_mutex); +static DEFINE_MUTEX(ds_mutex); static struct usb_driver ds_driver = { .name = "DS9490R", @@ -887,9 +887,9 @@ static int ds_probe(struct usb_interface *intf, if (err) goto err_out_clear; - down(&ds_mutex); + mutex_lock(&ds_mutex); list_add_tail(&dev->ds_entry, &ds_devices); - up(&ds_mutex); + mutex_unlock(&ds_mutex); return 0; @@ -909,9 +909,9 @@ static void ds_disconnect(struct usb_interface *intf) if (!dev) return; - down(&ds_mutex); + mutex_lock(&ds_mutex); list_del(&dev->ds_entry); - up(&ds_mutex); + mutex_unlock(&ds_mutex); ds_w1_fini(dev); diff --git a/drivers/w1/slaves/w1_ds2433.c b/drivers/w1/slaves/w1_ds2433.c index ddd01e6fc2c..2ac238f1480 100644 --- a/drivers/w1/slaves/w1_ds2433.c +++ b/drivers/w1/slaves/w1_ds2433.c @@ -105,11 +105,7 @@ static ssize_t w1_f23_read_bin(struct kobject *kobj, char *buf, loff_t off, if ((count = w1_f23_fix_count(off, count, W1_EEPROM_SIZE)) == 0) return 0; - atomic_inc(&sl->refcnt); - if (down_interruptible(&sl->master->mutex)) { - count = 0; - goto out_dec; - } + mutex_lock(&sl->master->mutex); #ifdef CONFIG_W1_F23_CRC @@ -140,9 +136,7 @@ static ssize_t w1_f23_read_bin(struct kobject *kobj, char *buf, loff_t off, #endif /* CONFIG_W1_F23_CRC */ out_up: - up(&sl->master->mutex); -out_dec: - atomic_dec(&sl->refcnt); + mutex_unlock(&sl->master->mutex); return count; } @@ -231,11 +225,7 @@ static ssize_t w1_f23_write_bin(struct kobject *kobj, char *buf, loff_t off, } #endif /* CONFIG_W1_F23_CRC */ - atomic_inc(&sl->refcnt); - if (down_interruptible(&sl->master->mutex)) { - count = 0; - goto out_dec; - } + mutex_lock(&sl->master->mutex); /* Can only write data to one page at a time */ idx = 0; @@ -253,9 +243,7 @@ static ssize_t w1_f23_write_bin(struct kobject *kobj, char *buf, loff_t off, } out_up: - up(&sl->master->mutex); -out_dec: - atomic_dec(&sl->refcnt); + mutex_unlock(&sl->master->mutex); return count; } diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c index 44afdffe3c8..5372cfcbd05 100644 --- a/drivers/w1/slaves/w1_therm.c +++ b/drivers/w1/slaves/w1_therm.c @@ -165,12 +165,7 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si u8 rom[9], crc, verdict; int i, max_trying = 10; - atomic_inc(&sl->refcnt); - smp_mb__after_atomic_inc(); - if (down_interruptible(&sl->master->mutex)) { - count = 0; - goto out_dec; - } + mutex_lock(&sl->master->mutex); if (off > W1_SLAVE_DATA_SIZE) { count = 0; @@ -233,10 +228,7 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si count += sprintf(buf + count, "t=%d\n", w1_convert_temp(rom, sl->family->fid)); out: - up(&dev->mutex); -out_dec: - smp_mb__before_atomic_inc(); - atomic_dec(&sl->refcnt); + mutex_unlock(&dev->mutex); return count; } diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index 32d8de881f1..420be14c2f8 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c @@ -54,7 +54,7 @@ module_param_named(control_timeout, w1_control_timeout, int, 0); module_param_named(max_slave_count, w1_max_slave_count, int, 0); module_param_named(slave_ttl, w1_max_slave_ttl, int, 0); -DECLARE_MUTEX(w1_mlock); +DEFINE_MUTEX(w1_mlock); LIST_HEAD(w1_masters); static struct task_struct *w1_control_thread; @@ -139,11 +139,7 @@ static ssize_t w1_default_write(struct kobject *kobj, char *buf, loff_t off, siz { struct w1_slave *sl = kobj_to_w1_slave(kobj); - if (down_interruptible(&sl->master->mutex)) { - count = 0; - goto out; - } - + mutex_lock(&sl->master->mutex); if (w1_reset_select_slave(sl)) { count = 0; goto out_up; @@ -152,8 +148,7 @@ static ssize_t w1_default_write(struct kobject *kobj, char *buf, loff_t off, siz w1_write_block(sl->master, buf, count); out_up: - up(&sl->master->mutex); -out: + mutex_unlock(&sl->master->mutex); return count; } @@ -161,15 +156,9 @@ static ssize_t w1_default_read(struct kobject *kobj, char *buf, loff_t off, size { struct w1_slave *sl = kobj_to_w1_slave(kobj); - if (down_interruptible(&sl->master->mutex)) { - count = 0; - goto out; - } - + mutex_lock(&sl->master->mutex); w1_read_block(sl->master, buf, count); - - up(&sl->master->mutex); -out: + mutex_unlock(&sl->master->mutex); return count; } @@ -243,12 +232,9 @@ static ssize_t w1_master_attribute_show_name(struct device *dev, struct device_a struct w1_master *md = dev_to_w1_master(dev); ssize_t count; - if (down_interruptible (&md->mutex)) - return -EBUSY; - + mutex_lock(&md->mutex); count = sprintf(buf, "%s\n", md->name); - - up(&md->mutex); + mutex_unlock(&md->mutex); return count; } @@ -259,12 +245,9 @@ static ssize_t w1_master_attribute_store_search(struct device * dev, { struct w1_master *md = dev_to_w1_master(dev); - if (down_interruptible (&md->mutex)) - return -EBUSY; - + mutex_lock(&md->mutex); md->search_count = simple_strtol(buf, NULL, 0); - - up(&md->mutex); + mutex_unlock(&md->mutex); return count; } @@ -276,12 +259,9 @@ static ssize_t w1_master_attribute_show_search(struct device *dev, struct w1_master *md = dev_to_w1_master(dev); ssize_t count; - if (down_interruptible (&md->mutex)) - return -EBUSY; - + mutex_lock(&md->mutex); count = sprintf(buf, "%d\n", md->search_count); - - up(&md->mutex); + mutex_unlock(&md->mutex); return count; } @@ -291,12 +271,9 @@ static ssize_t w1_master_attribute_show_pointer(struct device *dev, struct devic struct w1_master *md = dev_to_w1_master(dev); ssize_t count; - if (down_interruptible(&md->mutex)) - return -EBUSY; - + mutex_lock(&md->mutex); count = sprintf(buf, "0x%p\n", md->bus_master); - - up(&md->mutex); + mutex_unlock(&md->mutex); return count; } @@ -312,12 +289,9 @@ static ssize_t w1_master_attribute_show_max_slave_count(struct device *dev, stru struct w1_master *md = dev_to_w1_master(dev); ssize_t count; - if (down_interruptible(&md->mutex)) - return -EBUSY; - + mutex_lock(&md->mutex); count = sprintf(buf, "%d\n", md->max_slave_count); - - up(&md->mutex); + mutex_unlock(&md->mutex); return count; } @@ -326,12 +300,9 @@ static ssize_t w1_master_attribute_show_attempts(struct device *dev, struct devi struct w1_master *md = dev_to_w1_master(dev); ssize_t count; - if (down_interruptible(&md->mutex)) - return -EBUSY; - + mutex_lock(&md->mutex); count = sprintf(buf, "%lu\n", md->attempts); - - up(&md->mutex); + mutex_unlock(&md->mutex); return count; } @@ -340,12 +311,9 @@ static ssize_t w1_master_attribute_show_slave_count(struct device *dev, struct d struct w1_master *md = dev_to_w1_master(dev); ssize_t count; - if (down_interruptible(&md->mutex)) - return -EBUSY; - + mutex_lock(&md->mutex); count = sprintf(buf, "%d\n", md->slave_count); - - up(&md->mutex); + mutex_unlock(&md->mutex); return count; } @@ -354,8 +322,7 @@ static ssize_t w1_master_attribute_show_slaves(struct device *dev, struct device struct w1_master *md = dev_to_w1_master(dev); int c = PAGE_SIZE; - if (down_interruptible(&md->mutex)) - return -EBUSY; + mutex_lock(&md->mutex); if (md->slave_count == 0) c -= snprintf(buf + PAGE_SIZE - c, c, "not found.\n"); @@ -370,7 +337,7 @@ static ssize_t w1_master_attribute_show_slaves(struct device *dev, struct device } } - up(&md->mutex); + mutex_unlock(&md->mutex); return PAGE_SIZE - c; } @@ -620,7 +587,7 @@ static struct w1_master *w1_search_master(void *data) struct w1_master *dev; int found = 0; - down(&w1_mlock); + mutex_lock(&w1_mlock); list_for_each_entry(dev, &w1_masters, w1_master_entry) { if (dev->bus_master->data == data) { found = 1; @@ -628,7 +595,7 @@ static struct w1_master *w1_search_master(void *data) break; } } - up(&w1_mlock); + mutex_unlock(&w1_mlock); return (found)?dev:NULL; } @@ -638,7 +605,7 @@ struct w1_master *w1_search_master_id(u32 id) struct w1_master *dev; int found = 0; - down(&w1_mlock); + mutex_lock(&w1_mlock); list_for_each_entry(dev, &w1_masters, w1_master_entry) { if (dev->id == id) { found = 1; @@ -646,7 +613,7 @@ struct w1_master *w1_search_master_id(u32 id) break; } } - up(&w1_mlock); + mutex_unlock(&w1_mlock); return (found)?dev:NULL; } @@ -657,9 +624,9 @@ struct w1_slave *w1_search_slave(struct w1_reg_num *id) struct w1_slave *sl = NULL; int found = 0; - down(&w1_mlock); + mutex_lock(&w1_mlock); list_for_each_entry(dev, &w1_masters, w1_master_entry) { - down(&dev->mutex); + mutex_lock(&dev->mutex); list_for_each_entry(sl, &dev->slist, w1_slave_entry) { if (sl->reg_num.family == id->family && sl->reg_num.id == id->id && @@ -670,12 +637,12 @@ struct w1_slave *w1_search_slave(struct w1_reg_num *id) break; } } - up(&dev->mutex); + mutex_unlock(&dev->mutex); if (found) break; } - up(&w1_mlock); + mutex_unlock(&w1_mlock); return (found)?sl:NULL; } @@ -684,13 +651,13 @@ void w1_reconnect_slaves(struct w1_family *f) { struct w1_master *dev; - down(&w1_mlock); + mutex_lock(&w1_mlock); list_for_each_entry(dev, &w1_masters, w1_master_entry) { dev_dbg(&dev->dev, "Reconnecting slaves in %s into new family %02x.\n", dev->name, f->fid); set_bit(W1_MASTER_NEED_RECONNECT, &dev->flags); } - up(&w1_mlock); + mutex_unlock(&w1_mlock); } static void w1_slave_found(void *data, u64 rn) @@ -845,23 +812,23 @@ static int w1_control(void *data) if (kthread_should_stop() || test_bit(W1_MASTER_NEED_EXIT, &dev->flags)) { set_bit(W1_MASTER_NEED_EXIT, &dev->flags); - down(&w1_mlock); + mutex_lock(&w1_mlock); list_del(&dev->w1_master_entry); - up(&w1_mlock); + mutex_unlock(&w1_mlock); - down(&dev->mutex); + mutex_lock(&dev->mutex); list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) { w1_slave_detach(sl); } w1_destroy_master_attributes(dev); - up(&dev->mutex); + mutex_unlock(&dev->mutex); atomic_dec(&dev->refcnt); continue; } if (test_bit(W1_MASTER_NEED_RECONNECT, &dev->flags)) { dev_dbg(&dev->dev, "Reconnecting slaves in device %s.\n", dev->name); - down(&dev->mutex); + mutex_lock(&dev->mutex); list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) { if (sl->family->fid == W1_FAMILY_DEFAULT) { struct w1_reg_num rn; @@ -874,7 +841,7 @@ static int w1_control(void *data) } dev_dbg(&dev->dev, "Reconnecting slaves in device %s has been finished.\n", dev->name); clear_bit(W1_MASTER_NEED_RECONNECT, &dev->flags); - up(&dev->mutex); + mutex_unlock(&dev->mutex); } } } @@ -921,12 +888,9 @@ int w1_process(void *data) if (dev->search_count == 0) continue; - if (down_interruptible(&dev->mutex)) - continue; - + mutex_lock(&dev->mutex); w1_search_process(dev, W1_SEARCH); - - up(&dev->mutex); + mutex_unlock(&dev->mutex); } atomic_dec(&dev->refcnt); diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h index e8c96e6e741..6caccfc97cd 100644 --- a/drivers/w1/w1.h +++ b/drivers/w1/w1.h @@ -41,8 +41,7 @@ struct w1_reg_num #include #include - -#include +#include #include "w1_family.h" @@ -171,7 +170,7 @@ struct w1_master long flags; struct task_struct *thread; - struct semaphore mutex; + struct mutex mutex; struct device_driver *driver; struct device dev; diff --git a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c index ae78473d11f..24e7c102fa7 100644 --- a/drivers/w1/w1_int.c +++ b/drivers/w1/w1_int.c @@ -36,7 +36,7 @@ extern struct device w1_master_device; extern int w1_max_slave_count; extern int w1_max_slave_ttl; extern struct list_head w1_masters; -extern struct semaphore w1_mlock; +extern struct mutex w1_mlock; extern int w1_process(void *); @@ -74,7 +74,7 @@ static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl, atomic_set(&dev->refcnt, 2); INIT_LIST_HEAD(&dev->slist); - init_MUTEX(&dev->mutex); + mutex_init(&dev->mutex); memcpy(&dev->dev, device, sizeof(struct device)); snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id), @@ -135,9 +135,9 @@ int w1_add_master_device(struct w1_bus_master *master) dev->initialized = 1; - down(&w1_mlock); + mutex_lock(&w1_mlock); list_add(&dev->w1_master_entry, &w1_masters); - up(&w1_mlock); + mutex_unlock(&w1_mlock); memset(&msg, 0, sizeof(msg)); msg.id.mst.id = dev->id; diff --git a/drivers/w1/w1_netlink.c b/drivers/w1/w1_netlink.c index d539e09aad3..65c5ebd0787 100644 --- a/drivers/w1/w1_netlink.c +++ b/drivers/w1/w1_netlink.c @@ -171,7 +171,7 @@ static void w1_cn_callback(void *data) goto out_cont; } - down(&dev->mutex); + mutex_lock(&dev->mutex); if (sl && w1_reset_select_slave(sl)) { err = -ENODEV; @@ -198,7 +198,7 @@ out_up: atomic_dec(&dev->refcnt); if (sl) atomic_dec(&sl->refcnt); - up(&dev->mutex); + mutex_unlock(&dev->mutex); out_cont: msg->len -= sizeof(struct w1_netlink_msg) + m->len; m = (struct w1_netlink_msg *)(((u8 *)m) + sizeof(struct w1_netlink_msg) + m->len); -- cgit v1.2.3 From 339f07236b481371ffb4993cf309dd1f1b3382ab Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 3 Apr 2006 22:51:17 -0700 Subject: [PATCH] w1 exports From: Andrew Morton WARNING: "w1_read_block" [drivers/w1/slaves/w1_therm.ko] undefined! WARNING: "w1_write_8" [drivers/w1/slaves/w1_therm.ko] undefined! WARNING: "w1_reset_select_slave" [drivers/w1/slaves/w1_therm.ko] undefined! WARNING: "w1_reset_bus" [drivers/w1/slaves/w1_ds2433.ko] undefined! WARNING: "w1_write_8" [drivers/w1/slaves/w1_ds2433.ko] undefined! WARNING: "w1_read_block" [drivers/w1/slaves/w1_ds2433.ko] undefined! WARNING: "w1_write_block" [drivers/w1/slaves/w1_ds2433.ko] undefined! WARNING: "w1_reset_select_slave" [drivers/w1/slaves/w1_ds2433.ko] undefined! Cc: Evgeniy Polyakov Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/w1/w1_io.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/w1/w1_io.c b/drivers/w1/w1_io.c index a6eb9db7359..3253bb0d082 100644 --- a/drivers/w1/w1_io.c +++ b/drivers/w1/w1_io.c @@ -23,6 +23,7 @@ #include #include +#include #include "w1.h" #include "w1_log.h" @@ -107,6 +108,7 @@ void w1_write_8(struct w1_master *dev, u8 byte) for (i = 0; i < 8; ++i) w1_touch_bit(dev, (byte >> i) & 0x1); } +EXPORT_SYMBOL_GPL(w1_write_8); /** @@ -207,6 +209,7 @@ void w1_write_block(struct w1_master *dev, const u8 *buf, int len) for (i = 0; i < len; ++i) w1_write_8(dev, buf[i]); } +EXPORT_SYMBOL_GPL(w1_write_block); /** * Reads a series of bytes. @@ -231,6 +234,7 @@ u8 w1_read_block(struct w1_master *dev, u8 *buf, int len) return ret; } +EXPORT_SYMBOL_GPL(w1_read_block); /** * Issues a reset bus sequence. @@ -256,6 +260,7 @@ int w1_reset_bus(struct w1_master *dev) return result; } +EXPORT_SYMBOL_GPL(w1_reset_bus); u8 w1_calc_crc8(u8 * data, int len) { @@ -266,6 +271,7 @@ u8 w1_calc_crc8(u8 * data, int len) return crc; } +EXPORT_SYMBOL_GPL(w1_calc_crc8); void w1_search_devices(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb) { @@ -298,5 +304,4 @@ int w1_reset_select_slave(struct w1_slave *sl) } return 0; } - -EXPORT_SYMBOL_GPL(w1_calc_crc8); +EXPORT_SYMBOL_GPL(w1_reset_select_slave); -- cgit v1.2.3 From 2c5bfdac33607a618d8cf1532ef235ca9eccd49e Mon Sep 17 00:00:00 2001 From: Evgeniy Polyakov Date: Tue, 4 Apr 2006 20:35:22 +0400 Subject: [PATCH] W1: cleanups Nice cleanup spotted by Adrian Bunk, which was lost due to moving to the completely new functionality. Shame-shame-shame on me. Signed-off-by: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman --- drivers/w1/w1.c | 6 ++++-- drivers/w1/w1.h | 10 ++++++++++ drivers/w1/w1_int.c | 12 +----------- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index 420be14c2f8..b41366a0784 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c @@ -214,11 +214,12 @@ struct device w1_master_device = { .release = &w1_master_release }; -struct device_driver w1_slave_driver = { +static struct device_driver w1_slave_driver = { .name = "w1_slave_driver", .bus = &w1_bus_type, }; +#if 0 struct device w1_slave_device = { .parent = NULL, .bus = &w1_bus_type, @@ -226,6 +227,7 @@ struct device w1_slave_device = { .driver = &w1_slave_driver, .release = &w1_slave_release }; +#endif /* 0 */ static ssize_t w1_master_attribute_show_name(struct device *dev, struct device_attribute *attr, char *buf) { @@ -383,7 +385,7 @@ int w1_create_master_attributes(struct w1_master *master) return sysfs_create_group(&master->dev.kobj, &w1_master_defattr_group); } -void w1_destroy_master_attributes(struct w1_master *master) +static void w1_destroy_master_attributes(struct w1_master *master) { sysfs_remove_group(&master->dev.kobj, &w1_master_defattr_group); } diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h index 6caccfc97cd..3828f39b22e 100644 --- a/drivers/w1/w1.h +++ b/drivers/w1/w1.h @@ -213,6 +213,16 @@ static inline struct w1_master* dev_to_w1_master(struct device *dev) return container_of(dev, struct w1_master, dev); } +extern struct device_driver w1_master_driver; +extern struct bus_type w1_bus_type; +extern struct device w1_master_device; +extern int w1_max_slave_count; +extern int w1_max_slave_ttl; +extern struct list_head w1_masters; +extern struct mutex w1_mlock; + +extern int w1_process(void *); + #endif /* __KERNEL__ */ #endif /* __W1_H */ diff --git a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c index 24e7c102fa7..475996cd1b7 100644 --- a/drivers/w1/w1_int.c +++ b/drivers/w1/w1_int.c @@ -30,16 +30,6 @@ static u32 w1_ids = 1; -extern struct device_driver w1_master_driver; -extern struct bus_type w1_bus_type; -extern struct device w1_master_device; -extern int w1_max_slave_count; -extern int w1_max_slave_ttl; -extern struct list_head w1_masters; -extern struct mutex w1_mlock; - -extern int w1_process(void *); - static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl, struct device_driver *driver, struct device *device) @@ -96,7 +86,7 @@ static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl, return dev; } -void w1_free_dev(struct w1_master *dev) +static void w1_free_dev(struct w1_master *dev) { device_unregister(&dev->dev); } -- cgit v1.2.3 From 70d484bff43013e9b08f5d970b1c5941e9d98e16 Mon Sep 17 00:00:00 2001 From: Evgeniy Polyakov Date: Mon, 24 Apr 2006 10:46:14 +0400 Subject: [PATCH] W1: possible cleanups This patch contains the following possible cleanups: - the following file did't #include the header with the prototypes for it's global functions: - w1_int.c - #if 0 the following unused global function: - w1_family.c: w1_family_get() - make the following needlessly global functions static: - w1_family.c: __w1_family_put() - w1_io.c: w1_delay() - w1_io.c: w1_touch_bit() - w1_io.c: w1_read_8() - remove the following unused EXPORT_SYMBOL's: - w1_family.c: w1_family_put - w1_family.c: w1_family_registered Signed-off-by: Adrian Bunk Signed-off-by: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman --- drivers/w1/w1.h | 3 --- drivers/w1/w1_family.c | 18 ++++++++---------- drivers/w1/w1_family.h | 2 -- drivers/w1/w1_int.c | 1 + drivers/w1/w1_io.c | 6 +++--- drivers/w1/w1_io.h | 3 --- 6 files changed, 12 insertions(+), 21 deletions(-) diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h index 3828f39b22e..c90a92879bc 100644 --- a/drivers/w1/w1.h +++ b/drivers/w1/w1.h @@ -187,11 +187,8 @@ struct w1_slave *w1_search_slave(struct w1_reg_num *id); void w1_search_process(struct w1_master *dev, u8 search_type); struct w1_master *w1_search_master_id(u32 id); -void w1_delay(unsigned long); -u8 w1_touch_bit(struct w1_master *, int); u8 w1_triplet(struct w1_master *dev, int bdir); void w1_write_8(struct w1_master *, u8); -u8 w1_read_8(struct w1_master *); int w1_reset_bus(struct w1_master *); u8 w1_calc_crc8(u8 *, int); void w1_write_block(struct w1_master *, const u8 *, int); diff --git a/drivers/w1/w1_family.c b/drivers/w1/w1_family.c index 0e32c114f90..a3c95bd6890 100644 --- a/drivers/w1/w1_family.c +++ b/drivers/w1/w1_family.c @@ -107,6 +107,12 @@ struct w1_family * w1_family_registered(u8 fid) return (ret) ? f : NULL; } +static void __w1_family_put(struct w1_family *f) +{ + if (atomic_dec_and_test(&f->refcnt)) + f->need_exit = 1; +} + void w1_family_put(struct w1_family *f) { spin_lock(&w1_flock); @@ -114,19 +120,14 @@ void w1_family_put(struct w1_family *f) spin_unlock(&w1_flock); } -void __w1_family_put(struct w1_family *f) -{ - if (atomic_dec_and_test(&f->refcnt)) - f->need_exit = 1; -} - +#if 0 void w1_family_get(struct w1_family *f) { spin_lock(&w1_flock); __w1_family_get(f); spin_unlock(&w1_flock); - } +#endif /* 0 */ void __w1_family_get(struct w1_family *f) { @@ -135,8 +136,5 @@ void __w1_family_get(struct w1_family *f) smp_mb__after_atomic_inc(); } -EXPORT_SYMBOL(w1_family_get); -EXPORT_SYMBOL(w1_family_put); -EXPORT_SYMBOL(w1_family_registered); EXPORT_SYMBOL(w1_unregister_family); EXPORT_SYMBOL(w1_register_family); diff --git a/drivers/w1/w1_family.h b/drivers/w1/w1_family.h index 22a9d52c94f..1e2ac40c2c1 100644 --- a/drivers/w1/w1_family.h +++ b/drivers/w1/w1_family.h @@ -57,10 +57,8 @@ struct w1_family extern spinlock_t w1_flock; -void w1_family_get(struct w1_family *); void w1_family_put(struct w1_family *); void __w1_family_get(struct w1_family *); -void __w1_family_put(struct w1_family *); struct w1_family * w1_family_registered(u8); void w1_unregister_family(struct w1_family *); int w1_register_family(struct w1_family *); diff --git a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c index 475996cd1b7..357a2e0f637 100644 --- a/drivers/w1/w1_int.c +++ b/drivers/w1/w1_int.c @@ -27,6 +27,7 @@ #include "w1.h" #include "w1_log.h" #include "w1_netlink.h" +#include "w1_int.h" static u32 w1_ids = 1; diff --git a/drivers/w1/w1_io.c b/drivers/w1/w1_io.c index 3253bb0d082..30b6fbf83bd 100644 --- a/drivers/w1/w1_io.c +++ b/drivers/w1/w1_io.c @@ -50,7 +50,7 @@ static u8 w1_crc8_table[] = { 116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53 }; -void w1_delay(unsigned long tm) +static void w1_delay(unsigned long tm) { udelay(tm * w1_delay_parm); } @@ -61,7 +61,7 @@ static u8 w1_read_bit(struct w1_master *dev); /** * Generates a write-0 or write-1 cycle and samples the level. */ -u8 w1_touch_bit(struct w1_master *dev, int bit) +static u8 w1_touch_bit(struct w1_master *dev, int bit) { if (dev->bus_master->touch_bit) return dev->bus_master->touch_bit(dev->bus_master->data, bit); @@ -177,7 +177,7 @@ u8 w1_triplet(struct w1_master *dev, int bdir) * @param dev the master device * @return the byte read */ -u8 w1_read_8(struct w1_master * dev) +static u8 w1_read_8(struct w1_master * dev) { int i; u8 res = 0; diff --git a/drivers/w1/w1_io.h b/drivers/w1/w1_io.h index 232860184a2..9a76d2ad69c 100644 --- a/drivers/w1/w1_io.h +++ b/drivers/w1/w1_io.h @@ -24,11 +24,8 @@ #include "w1.h" -void w1_delay(unsigned long); -u8 w1_touch_bit(struct w1_master *, int); u8 w1_triplet(struct w1_master *dev, int bdir); void w1_write_8(struct w1_master *, u8); -u8 w1_read_8(struct w1_master *); int w1_reset_bus(struct w1_master *); u8 w1_calc_crc8(u8 *, int); void w1_write_block(struct w1_master *, const u8 *, int); -- cgit v1.2.3 From f621e1c78134f7cea0d2cf2c2822c917bedec516 Mon Sep 17 00:00:00 2001 From: Jean-Luc Leger Date: Tue, 18 Apr 2006 21:18:20 -0700 Subject: [PATCH] W1: fix dependencies of W1_SLAVE_DS2433_CRC From: Jean-Luc Leger Default values for boolean and tristate options can only be 'y', 'm' or 'n'. This patch fixes dependencies of W1_SLAVE_DS2433_CRC. Signed-off-by: Jean-Luc Leger Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/w1/slaves/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/w1/slaves/Kconfig b/drivers/w1/slaves/Kconfig index f9d4c91fc53..d18d6424cd2 100644 --- a/drivers/w1/slaves/Kconfig +++ b/drivers/w1/slaves/Kconfig @@ -28,7 +28,7 @@ config W1_SLAVE_DS2433 config W1_SLAVE_DS2433_CRC bool "Protect DS2433 data with a CRC16" - depends on W1_DS2433 + depends on W1_SLAVE_DS2433 select CRC16 help Say Y here to protect DS2433 data with a CRC16. -- cgit v1.2.3 From 6a873403d387c34c4466cc81649acc8acd66874d Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Thu, 27 Apr 2006 02:29:18 -0700 Subject: [PATCH] drivers/w1/w1.c: fix a compile error From: Adrian Bunk drivers/w1/w1.c:197: error: static declaration of 'w1_bus_type' follows non-static declaration drivers/w1/w1.h:217: error: previous declaration of 'w1_bus_type' was here Signed-off-by: Adrian Bunk Cc: Evgeniy Polyakov Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/w1/w1.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h index c90a92879bc..f1df5343f4a 100644 --- a/drivers/w1/w1.h +++ b/drivers/w1/w1.h @@ -211,7 +211,6 @@ static inline struct w1_master* dev_to_w1_master(struct device *dev) } extern struct device_driver w1_master_driver; -extern struct bus_type w1_bus_type; extern struct device w1_master_device; extern int w1_max_slave_count; extern int w1_max_slave_ttl; -- cgit v1.2.3 From 30841711c88dc2d9ce31bfa3fa5479aa823804cf Mon Sep 17 00:00:00 2001 From: Evgeniy Polyakov Date: Thu, 27 Apr 2006 19:40:27 +0400 Subject: [PATCH] w1: clean up W1_CON dependency. If w1 is not enabled, w1_con should not appear in configuration, even if no logic is turned on without w1. W1_CON should depend on W1 also. Signed-off-by: Randy Dunlap Signed-off-by: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman --- drivers/w1/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/w1/Kconfig b/drivers/w1/Kconfig index 0c6c4359bf7..f2d9a08e89a 100644 --- a/drivers/w1/Kconfig +++ b/drivers/w1/Kconfig @@ -12,7 +12,7 @@ config W1 will be called wire.ko. config W1_CON - depends on CONNECTOR + depends on CONNECTOR && W1 bool "Userspace communication over connector" default y --- help --- -- cgit v1.2.3 From c6976a4eb3c9ead165de950899b45db0840b8e30 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 14 May 2006 21:43:50 -0700 Subject: [PATCH] w1: warning fix drivers/w1/w1.c:423: warning: long long unsigned int format, __u64 arg (arg 8) u64 is not, never has been and never will be "unsigned long long"! While we're there, fix up some code layout - it looks awful in an 80-col display. Cc: Evgeniy Polyakov Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/w1/w1.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index b41366a0784..de3e9791f80 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c @@ -391,7 +391,8 @@ static void w1_destroy_master_attributes(struct w1_master *master) } #ifdef CONFIG_HOTPLUG -static int w1_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size) +static int w1_uevent(struct device *dev, char **envp, int num_envp, + char *buffer, int buffer_size) { struct w1_master *md = NULL; struct w1_slave *sl = NULL; @@ -411,23 +412,28 @@ static int w1_uevent(struct device *dev, char **envp, int num_envp, char *buffer return -EINVAL; } - dev_dbg(dev, "Hotplug event for %s %s, bus_id=%s.\n", event_owner, name, dev->bus_id); + dev_dbg(dev, "Hotplug event for %s %s, bus_id=%s.\n", + event_owner, name, dev->bus_id); if (dev->driver != &w1_slave_driver || !sl) return 0; - err = add_uevent_var(envp, num_envp, &cur_index, buffer, buffer_size, &cur_len, "W1_FID=%02X", sl->reg_num.family); + err = add_uevent_var(envp, num_envp, &cur_index, buffer, buffer_size, + &cur_len, "W1_FID=%02X", sl->reg_num.family); if (err) return err; - err = add_uevent_var(envp, num_envp, &cur_index, buffer, buffer_size, &cur_len, "W1_SLAVE_ID=%024LX", (u64)sl->reg_num.id); + err = add_uevent_var(envp, num_envp, &cur_index, buffer, buffer_size, + &cur_len, "W1_SLAVE_ID=%024LX", + (unsigned long long)sl->reg_num.id); if (err) return err; return 0; }; #else -static int w1_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size) +static int w1_uevent(struct device *dev, char **envp, int num_envp, + char *buffer, int buffer_size) { return 0; } @@ -451,7 +457,8 @@ static int __w1_attach_slave_device(struct w1_slave *sl) (unsigned int) sl->reg_num.family, (unsigned long long) sl->reg_num.id); - dev_dbg(&sl->dev, "%s: registering %s as %p.\n", __func__, &sl->dev.bus_id[0]); + dev_dbg(&sl->dev, "%s: registering %s as %p.\n", __func__, + &sl->dev.bus_id[0]); err = device_register(&sl->dev); if (err < 0) { -- cgit v1.2.3 From 6129daaa0d2b84c0e376b6b17b3d3740c4d1d1ca Mon Sep 17 00:00:00 2001 From: James Courtier-Dutton Date: Sun, 9 Apr 2006 13:01:34 +0100 Subject: [ALSA] ca0106: Add analog capture controls. Signed-off-by: James Courtier-Dutton --- sound/pci/ca0106/ca0106.h | 4 +- sound/pci/ca0106/ca0106_main.c | 44 ++++++++++-- sound/pci/ca0106/ca0106_mixer.c | 152 +++++++++++++++++++++++++++++++++++++--- 3 files changed, 186 insertions(+), 14 deletions(-) diff --git a/sound/pci/ca0106/ca0106.h b/sound/pci/ca0106/ca0106.h index c8131ea92ed..9cb66c59f52 100644 --- a/sound/pci/ca0106/ca0106.h +++ b/sound/pci/ca0106/ca0106.h @@ -537,9 +537,9 @@ #endif #define ADC_MUX_MASK 0x0000000f //Mask for ADC Mux +#define ADC_MUX_PHONE 0x00000001 //Value to select TAD at ADC Mux (Not used) #define ADC_MUX_MIC 0x00000002 //Value to select Mic at ADC Mux #define ADC_MUX_LINEIN 0x00000004 //Value to select LineIn at ADC Mux -#define ADC_MUX_PHONE 0x00000001 //Value to select TAD at ADC Mux (Not used) #define ADC_MUX_AUX 0x00000008 //Value to select Aux at ADC Mux #define SET_CHANNEL 0 /* Testing channel outputs 0=Front, 1=Center/LFE, 2=Unknown, 3=Rear */ @@ -604,6 +604,8 @@ struct snd_ca0106 { u32 spdif_bits[4]; /* s/pdif out setup */ int spdif_enable; int capture_source; + int i2c_capture_source; + u8 i2c_capture_volume[4][2]; int capture_mic_line_in; struct snd_dma_buffer buffer; diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index fd8bfebfbd5..3762f58384e 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c @@ -326,6 +326,7 @@ int snd_ca0106_spi_write(struct snd_ca0106 * emu, return 0; } +/* The ADC does not support i2c read, so only write is implemented */ int snd_ca0106_i2c_write(struct snd_ca0106 *emu, u32 reg, u32 value) @@ -340,6 +341,7 @@ int snd_ca0106_i2c_write(struct snd_ca0106 *emu, } tmp = reg << 25 | value << 16; + // snd_printk("I2C-write:reg=0x%x, value=0x%x\n", reg, value); /* Not sure what this I2C channel controls. */ /* snd_ca0106_ptr_write(emu, I2C_D0, 0, tmp); */ @@ -348,8 +350,9 @@ int snd_ca0106_i2c_write(struct snd_ca0106 *emu, for (retry = 0; retry < 10; retry++) { /* Send the data to i2c */ - tmp = snd_ca0106_ptr_read(emu, I2C_A, 0); - tmp = tmp & ~(I2C_A_ADC_READ|I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD_MASK); + //tmp = snd_ca0106_ptr_read(emu, I2C_A, 0); + //tmp = tmp & ~(I2C_A_ADC_READ|I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD_MASK); + tmp = 0; tmp = tmp | (I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD); snd_ca0106_ptr_write(emu, I2C_A, 0, tmp); @@ -1200,6 +1203,22 @@ static unsigned int spi_dac_init[] = { 0x1400, }; +static unsigned int i2c_adc_init[][2] = { + { 0x17, 0x00 }, /* Reset */ + { 0x07, 0x00 }, /* Timeout */ + { 0x0b, 0x22 }, /* Interface control */ + { 0x0c, 0x22 }, /* Master mode control */ + { 0x0d, 0x08 }, /* Powerdown control */ + { 0x0e, 0xcf }, /* Attenuation Left 0x01 = -103dB, 0xff = 24dB */ + { 0x0f, 0xcf }, /* Attenuation Right 0.5dB steps */ + { 0x10, 0x7b }, /* ALC Control 1 */ + { 0x11, 0x00 }, /* ALC Control 2 */ + { 0x12, 0x32 }, /* ALC Control 3 */ + { 0x13, 0x00 }, /* Noise gate control */ + { 0x14, 0xa6 }, /* Limiter control */ + { 0x15, ADC_MUX_LINEIN }, /* ADC Mixer control */ +}; + static int __devinit snd_ca0106_create(struct snd_card *card, struct pci_dev *pci, struct snd_ca0106 **rchip) @@ -1361,7 +1380,12 @@ static int __devinit snd_ca0106_create(struct snd_card *card, snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4); /* Select MIC, Line in, TAD in, AUX in */ chip->capture_source = 3; /* Set CAPTURE_SOURCE */ - if (chip->details->gpio_type == 1) { /* The SB0410 and SB0413 use GPIO differently. */ + if (chip->details->gpio_type == 2) { /* The SB0410 and SB0413 use GPIO differently. */ + /* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */ + outl(0x0, chip->port+GPIO); + //outl(0x00f0e000, chip->port+GPIO); /* Analog */ + outl(0x005f5301, chip->port+GPIO); /* Analog */ + } else if (chip->details->gpio_type == 1) { /* The SB0410 and SB0413 use GPIO differently. */ /* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */ outl(0x0, chip->port+GPIO); //outl(0x00f0e000, chip->port+GPIO); /* Analog */ @@ -1379,7 +1403,19 @@ static int __devinit snd_ca0106_create(struct snd_card *card, outl(HCFG_AC97 | HCFG_AUDIOENABLE, chip->port+HCFG); /* AC97 2.0, Enable outputs. */ if (chip->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */ - snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); /* Enable Line-in capture. MIC in currently untested. */ + int size, n; + + size = ARRAY_SIZE(i2c_adc_init); + //snd_printk("I2C:array size=0x%x\n", size); + for (n=0; n < size; n++) { + snd_ca0106_i2c_write(chip, i2c_adc_init[n][0], i2c_adc_init[n][1]); + } + for (n=0; n < 4; n++) { + chip->i2c_capture_volume[n][0]= 0xcf; + chip->i2c_capture_volume[n][1]= 0xcf; + } + chip->i2c_capture_source=2; /* Line in */ + //snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); /* Enable Line-in capture. MIC in currently untested. */ } if (chip->details->spi_dac == 1) { /* The SB0570 use SPI to control DAC. */ int size, n; diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c index 06fe055674f..8a5833317b0 100644 --- a/sound/pci/ca0106/ca0106_mixer.c +++ b/sound/pci/ca0106/ca0106_mixer.c @@ -171,6 +171,62 @@ static int snd_ca0106_capture_source_put(struct snd_kcontrol *kcontrol, return change; } +static int snd_ca0106_i2c_capture_source_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + static char *texts[6] = { + "Phone", "Mic", "Line in", "Aux" + }; + + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; + uinfo->count = 1; + uinfo->value.enumerated.items = 4; + if (uinfo->value.enumerated.item > 3) + uinfo->value.enumerated.item = 3; + strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); + return 0; +} + +static int snd_ca0106_i2c_capture_source_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); + + ucontrol->value.enumerated.item[0] = emu->i2c_capture_source; + return 0; +} + +static int snd_ca0106_i2c_capture_source_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); + unsigned int source_id; + unsigned int ngain, ogain; + int change = 0; + u32 source; + /* If the capture source has changed, + * update the capture volume from the cached value + * for the particular source. + */ + source_id = ucontrol->value.enumerated.item[0] ; + change = (emu->i2c_capture_source != source_id); + if (change) { + snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */ + ngain = emu->i2c_capture_volume[source_id][0]; /* Left */ + ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */ + if (ngain != ogain) + snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff)); + ngain = emu->i2c_capture_volume[source_id][1]; /* Left */ + ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Left */ + if (ngain != ogain) + snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff)); + source = 1 << source_id; + snd_ca0106_i2c_write(emu, ADC_MUX, source); /* Set source */ + emu->i2c_capture_source = source_id; + } + return change; +} + static int snd_ca0106_capture_mic_line_in_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { @@ -207,16 +263,16 @@ static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol, if (change) { emu->capture_mic_line_in = val; if (val) { - snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_PHONE); /* Mute input */ + //snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */ tmp = inl(emu->port+GPIO) & ~0x400; tmp = tmp | 0x400; outl(tmp, emu->port+GPIO); - snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC); + //snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC); } else { - snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_PHONE); /* Mute input */ + //snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */ tmp = inl(emu->port+GPIO) & ~0x400; outl(tmp, emu->port+GPIO); - snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_LINEIN); + //snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_LINEIN); } } return change; @@ -225,7 +281,7 @@ static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol, static struct snd_kcontrol_new snd_ca0106_capture_mic_line_in __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Mic/Line in Capture", + .name = "Shared Mic/Line in Capture Switch", .info = snd_ca0106_capture_mic_line_in_info, .get = snd_ca0106_capture_mic_line_in_get, .put = snd_ca0106_capture_mic_line_in_put @@ -329,15 +385,81 @@ static int snd_ca0106_volume_put(struct snd_kcontrol *kcontrol, return 1; } +static int snd_ca0106_i2c_volume_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 2; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 255; + return 0; +} + +static int snd_ca0106_i2c_volume_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); + int source_id; + + source_id = kcontrol->private_value; + + ucontrol->value.integer.value[0] = emu->i2c_capture_volume[source_id][0]; + ucontrol->value.integer.value[1] = emu->i2c_capture_volume[source_id][1]; + return 0; +} + +static int snd_ca0106_i2c_volume_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); + unsigned int ogain; + unsigned int ngain; + int source_id; + int change = 0; + + source_id = kcontrol->private_value; + ogain = emu->i2c_capture_volume[source_id][0]; /* Left */ + ngain = ucontrol->value.integer.value[0]; + if (ngain > 0xff) + return 0; + if (ogain != ngain) { + if (emu->i2c_capture_source == source_id) + snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff) ); + emu->i2c_capture_volume[source_id][0] = ucontrol->value.integer.value[0]; + change = 1; + } + ogain = emu->i2c_capture_volume[source_id][1]; /* Right */ + ngain = ucontrol->value.integer.value[1]; + if (ngain > 0xff) + return 0; + if (ogain != ngain) { + if (emu->i2c_capture_source == source_id) + snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff)); + emu->i2c_capture_volume[source_id][1] = ucontrol->value.integer.value[1]; + change = 1; + } + + return change; +} + #define CA_VOLUME(xname,chid,reg) \ { \ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_ca0106_volume_info, \ - .get = snd_ca0106_volume_get, \ - .put = snd_ca0106_volume_put, \ + .info = snd_ca0106_volume_info, \ + .get = snd_ca0106_volume_get, \ + .put = snd_ca0106_volume_put, \ .private_value = ((chid) << 8) | (reg) \ } +#define I2C_VOLUME(xname,chid) \ +{ \ + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ + .info = snd_ca0106_i2c_volume_info, \ + .get = snd_ca0106_i2c_volume_get, \ + .put = snd_ca0106_i2c_volume_put, \ + .private_value = chid \ +} + static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = { CA_VOLUME("Analog Front Playback Volume", @@ -361,6 +483,11 @@ static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = { CA_VOLUME("CAPTURE feedback Playback Volume", 1, CAPTURE_CONTROL), + I2C_VOLUME("Phone Capture Volume", 0), + I2C_VOLUME("Mic Capture Volume", 1), + I2C_VOLUME("Line in Capture Volume", 2), + I2C_VOLUME("Aux Capture Volume", 3), + { .access = SNDRV_CTL_ELEM_ACCESS_READ, .iface = SNDRV_CTL_ELEM_IFACE_PCM, @@ -378,11 +505,18 @@ static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = { }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", + .name = "Digital Capture Source", .info = snd_ca0106_capture_source_info, .get = snd_ca0106_capture_source_get, .put = snd_ca0106_capture_source_put }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Capture Source", + .info = snd_ca0106_i2c_capture_source_info, + .get = snd_ca0106_i2c_capture_source_get, + .put = snd_ca0106_i2c_capture_source_put + }, { .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), -- cgit v1.2.3 From 21fdddea8e4cc54341d389916d0c17db8c1ca452 Mon Sep 17 00:00:00 2001 From: James Courtier-Dutton Date: Sun, 9 Apr 2006 17:36:39 +0100 Subject: [ALSA] emu10k1: Add support for Audigy4 (not Pro) Signed-off-by: James Courtier-Dutton --- include/sound/emu10k1.h | 2 ++ sound/pci/ac97/ac97_codec.c | 4 +-- sound/pci/ac97/ac97_patch.c | 4 +-- sound/pci/emu10k1/emu10k1_main.c | 56 +++++++++++++++++++++++++++++++++------- sound/pci/emu10k1/emumixer.c | 54 ++++++++++++++++++++++++++++++++++++-- sound/pci/emu10k1/tina2.h | 8 ++---- 6 files changed, 107 insertions(+), 21 deletions(-) diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h index 186e00ad9e7..884bbf54cd3 100644 --- a/include/sound/emu10k1.h +++ b/include/sound/emu10k1.h @@ -245,6 +245,7 @@ #define A_IOCFG_GPOUT0 0x0044 /* analog/digital */ #define A_IOCFG_DISABLE_ANALOG 0x0040 /* = 'enable' for Audigy2 (chiprev=4) */ #define A_IOCFG_ENABLE_DIGITAL 0x0004 +#define A_IOCFG_ENABLE_DIGITAL_AUDIGY4 0x0080 #define A_IOCFG_UNKNOWN_20 0x0020 #define A_IOCFG_DISABLE_AC97_FRONT 0x0080 /* turn off ac97 front -> front (10k2.1) */ #define A_IOCFG_GPOUT1 0x0002 /* IR? drive's internal bypass (?) */ @@ -1065,6 +1066,7 @@ struct snd_emu_chip_details { unsigned char emu1212m; /* EMU 1212m card */ unsigned char spi_dac; /* SPI interface for DAC */ unsigned char i2c_adc; /* I2C interface for ADC */ + unsigned char adc_1361t; /* Use Philips 1361T ADC */ const char *driver; const char *name; const char *id; /* for backward compatibility - can be NULL if not needed */ diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index d05200741ac..4544f6aa089 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -563,7 +563,7 @@ AC97_SINGLE("PC Speaker Playback Volume", AC97_PC_BEEP, 1, 15, 1) }; static const struct snd_kcontrol_new snd_ac97_controls_mic_boost = - AC97_SINGLE("Mic Boost (+20dB)", AC97_MIC, 6, 1, 0); + AC97_SINGLE("Mic Boost (+20dB) Capture Switch", AC97_MIC, 6, 1, 0); static const char* std_rec_sel[] = {"Mic", "CD", "Video", "Aux", "Line", "Mix", "Mix Mono", "Phone"}; @@ -605,7 +605,7 @@ AC97_SINGLE("Simulated Stereo Enhancement", AC97_GENERAL_PURPOSE, 14, 1, 0), AC97_SINGLE("3D Control - Switch", AC97_GENERAL_PURPOSE, 13, 1, 0), AC97_SINGLE("Loudness (bass boost)", AC97_GENERAL_PURPOSE, 12, 1, 0), AC97_ENUM("Mono Output Select", std_enum[2]), -AC97_ENUM("Mic Select", std_enum[3]), +AC97_ENUM("Mic Select Capture Switch", std_enum[3]), AC97_SINGLE("ADC/DAC Loopback", AC97_GENERAL_PURPOSE, 7, 1, 0) }; diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index 4d9cf37300f..7ae7bc6524e 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c @@ -563,7 +563,7 @@ AC97_SINGLE("Mic 1 to Phone Switch", AC97_MIC, 14, 1, 1), AC97_SINGLE("Mic 2 to Phone Switch", AC97_MIC, 13, 1, 1), AC97_ENUM("Mic Select Source", wm9711_enum[7]), AC97_SINGLE("Mic 1 Volume", AC97_MIC, 8, 32, 1), -AC97_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 7, 1, 0), +AC97_SINGLE("Mic 20dB Boost Capture Switch", AC97_MIC, 7, 1, 0), AC97_SINGLE("Master ZC Switch", AC97_MASTER, 7, 1, 0), AC97_SINGLE("Headphone ZC Switch", AC97_HEADPHONE, 7, 1, 0), @@ -653,7 +653,7 @@ AC97_SINGLE("Mic 1 Volume", AC97_MIC, 8, 31, 1), AC97_SINGLE("Mic 2 Volume", AC97_MIC, 0, 31, 1), AC97_SINGLE("Mic 1 to Mono Switch", AC97_LINE, 7, 1, 1), AC97_SINGLE("Mic 2 to Mono Switch", AC97_LINE, 6, 1, 1), -AC97_SINGLE("Mic Boost (+20dB) Switch", AC97_LINE, 5, 1, 0), +AC97_SINGLE("Mic Boost (+20dB) Capture Switch", AC97_LINE, 5, 1, 0), AC97_ENUM("Mic to Headphone Mux", wm9713_enum[0]), AC97_SINGLE("Mic Headphone Mixer Volume", AC97_LINE, 0, 7, 1), diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index 6bfa08436ef..e71485c23cc 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c @@ -777,14 +777,6 @@ static int snd_emu10k1_dev_free(struct snd_device *device) static struct snd_emu_chip_details emu_chip_details[] = { /* Audigy 2 Value AC3 out does not work yet. Need to find out how to turn off interpolators.*/ - /* Audigy4 SB0400 */ - {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10211102, - .driver = "Audigy2", .name = "Audigy 4 [SB0400]", - .id = "Audigy2", - .emu10k2_chip = 1, - .ca0108_chip = 1, - .spk71 = 1, - .ac97_chip = 1} , /* Tested by James@superbug.co.uk 3rd July 2005 */ /* DSP: CA0108-IAT * DAC: CS4382-KQ @@ -799,13 +791,59 @@ static struct snd_emu_chip_details emu_chip_details[] = { .ca0108_chip = 1, .spk71 = 1, .ac97_chip = 1} , + /* Audigy4 (Not PRO) SB0610 */ + /* Tested by James@superbug.co.uk 4th April 2006 */ + /* A_IOCFG bits + * Output + * 0: ? + * 1: ? + * 2: ? + * 3: 0 - Digital Out, 1 - Line in + * 4: ? + * 5: ? + * 6: ? + * 7: ? + * Input + * 8: ? + * 9: ? + * A: Green jack sense (Front) + * B: ? + * C: Black jack sense (Rear/Side Right) + * D: Yellow jack sense (Center/LFE/Side Left) + * E: ? + * F: ? + * + * Digital Out/Line in switch using A_IOCFG bit 3 (0x08) + * 0 - Digital Out + * 1 - Line in + */ + /* Mic input not tested. + * Analog CD input not tested + * Digital Out not tested. + * Line in working. + * Audio output 5.1 working. Side outputs not working. + */ + /* DSP: CA10300-IAT LF + * DAC: Cirrus Logic CS4382-KQZ + * ADC: Philips 1361T + * AC97: Sigmatel STAC9750 + * CA0151: None + */ + {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10211102, + .driver = "Audigy2", .name = "Audigy 4 [SB0610]", + .id = "Audigy2", + .emu10k2_chip = 1, + .ca0108_chip = 1, + .spk71 = 1, + .adc_1361t = 1, /* 24 bit capture instead of 16bit */ + .ac97_chip = 1} , /* Audigy 2 ZS Notebook Cardbus card.*/ /* Tested by James@superbug.co.uk 22th December 2005 */ /* Audio output 7.1/Headphones working. * Digital output working. (AC3 not checked, only PCM) * Audio inputs not tested. */ - /* DSP: Tiny2 + /* DSP: Tina2 * DAC: Wolfson WM8768/WM8568 * ADC: Wolfson WM8775 * AC97: None diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c index 2a9d12d1068..c31f3d0877f 100644 --- a/sound/pci/emu10k1/emumixer.c +++ b/sound/pci/emu10k1/emumixer.c @@ -777,6 +777,8 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu, }; static char *audigy_remove_ctls[] = { /* Master/PCM controls on ac97 of Audigy has no effect */ + /* On the Audigy2 the AC97 playback is piped into + * the Philips ADC for 24bit capture */ "PCM Playback Switch", "PCM Playback Volume", "Master Mono Playback Switch", @@ -804,6 +806,47 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu, "AMic Playback Volume", "Mic Playback Volume", NULL }; + static char *audigy_remove_ctls_1361t_adc[] = { + /* On the Audigy2 the AC97 playback is piped into + * the Philips ADC for 24bit capture */ + "PCM Playback Switch", + "PCM Playback Volume", + "Master Mono Playback Switch", + "Master Mono Playback Volume", + "Capture Source", + "Capture Switch", + "Capture Volume", + "Mic Capture Volume", + "Headphone Playback Switch", + "Headphone Playback Volume", + "3D Control - Center", + "3D Control - Depth", + "3D Control - Switch", + "Line2 Playback Volume", + "Line2 Capture Volume", + NULL + }; + static char *audigy_rename_ctls_1361t_adc[] = { + "Master Playback Switch", "Master Capture Switch", + "Master Playback Volume", "Master Capture Volume", + "Wave Master Playback Volume", "Master Playback Volume", + "PC Speaker Playback Switch", "PC Speaker Capture Switch", + "PC Speaker Playback Volume", "PC Speaker Capture Volume", + "Phone Playback Switch", "Phone Capture Switch", + "Phone Playback Volume", "Phone Capture Volume", + "Mic Playback Switch", "Mic Capture Switch", + "Mic Playback Volume", "Mic Capture Volume", + "Line Playback Switch", "Line Capture Switch", + "Line Playback Volume", "Line Capture Volume", + "CD Playback Switch", "CD Capture Switch", + "CD Playback Volume", "CD Capture Volume", + "Aux Playback Switch", "Aux Capture Switch", + "Aux Playback Volume", "Aux Capture Volume", + "Video Playback Switch", "Video Capture Switch", + "Video Playback Volume", "Video Capture Volume", + + NULL + }; if (emu->card_capabilities->ac97_chip) { struct snd_ac97_bus *pbus; @@ -834,7 +877,10 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu, snd_ac97_write_cache(emu->ac97, AC97_MASTER, 0x0000); /* set capture source to mic */ snd_ac97_write_cache(emu->ac97, AC97_REC_SEL, 0x0000); - c = audigy_remove_ctls; + if (emu->card_capabilities->adc_1361t) + c = audigy_remove_ctls_1361t_adc; + else + c = audigy_remove_ctls; } else { /* * Credits for cards based on STAC9758: @@ -863,11 +909,15 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu, } if (emu->audigy) - c = audigy_rename_ctls; + if (emu->card_capabilities->adc_1361t) + c = audigy_rename_ctls_1361t_adc; + else + c = audigy_rename_ctls; else c = emu10k1_rename_ctls; for (; *c; c += 2) rename_ctl(card, c[0], c[1]); + if (emu->card_capabilities->subsystem == 0x20071102) { /* Audigy 4 Pro */ rename_ctl(card, "Line2 Capture Volume", "Line1/Mic Capture Volume"); rename_ctl(card, "Analog Mix Capture Volume", "Line2 Capture Volume"); diff --git a/sound/pci/emu10k1/tina2.h b/sound/pci/emu10k1/tina2.h index 5c43abf03e8..f2d8eb6c89e 100644 --- a/sound/pci/emu10k1/tina2.h +++ b/sound/pci/emu10k1/tina2.h @@ -1,11 +1,7 @@ /* * Copyright (c) by James Courtier-Dutton - * Driver p16v chips - * Version: 0.21 - * - * - * This code was initally based on code from ALSA's emu10k1x.c which is: - * Copyright (c) by Francisco Moraes + * Driver tina2 chips + * Version: 0.1 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by -- cgit v1.2.3 From 3969f6178b86613fd443e70d11b8848451552bdd Mon Sep 17 00:00:00 2001 From: James Courtier-Dutton Date: Sun, 9 Apr 2006 17:44:13 +0100 Subject: [ALSA] Add p17v.h file. Signed-off-by: James Courtier-Dutton --- sound/pci/emu10k1/p17v.h | 111 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 sound/pci/emu10k1/p17v.h diff --git a/sound/pci/emu10k1/p17v.h b/sound/pci/emu10k1/p17v.h new file mode 100644 index 00000000000..7ddb5be632c --- /dev/null +++ b/sound/pci/emu10k1/p17v.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) by James Courtier-Dutton + * Driver p17v chips + * Version: 0.01 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/******************************************************************************/ +/* Audigy2Value Tina (P17V) pointer-offset register set, + * accessed through the PTR20 and DATA24 registers */ +/******************************************************************************/ + +/* 00 - 07: Not used */ +#define P17V_PLAYBACK_FIFO_PTR 0x08 /* Current playback fifo pointer + * and number of sound samples in cache. + */ +/* 09 - 12: Not used */ +#define P17V_CAPTURE_FIFO_PTR 0x13 /* Current capture fifo pointer + * and number of sound samples in cache. + */ +/* 14 - 17: Not used */ +#define P17V_PB_CHN_SEL 0x18 /* P17v playback channel select */ +#define P17V_SE_SLOT_SEL_L 0x19 /* Sound Engine slot select low */ +#define P17V_SE_SLOT_SEL_H 0x1a /* Sound Engine slot select high */ +/* 1b - 1f: Not used */ +/* 20 - 2f: Not used */ +/* 30 - 3b: Not used */ +#define P17V_SPI 0x3c /* SPI interface register */ +#define P17V_I2C_ADDR 0x3d /* I2C Address */ +#define P17V_I2C_0 0x3e /* I2C Data */ +#define P17V_I2C_1 0x3f /* I2C Data */ + +#define P17V_START_AUDIO 0x40 /* Start Audio bit */ +/* 41 - 47: Reserved */ +#define P17V_START_CAPTURE 0x48 /* Start Capture bit */ +#define P17V_CAPTURE_FIFO_BASE 0x49 /* Record FIFO base address */ +#define P17V_CAPTURE_FIFO_SIZE 0x4a /* Record FIFO buffer size */ +#define P17V_CAPTURE_FIFO_INDEX 0x4b /* Record FIFO capture index */ +#define P17V_CAPTURE_VOL_H 0x4c /* P17v capture volume control */ +#define P17V_CAPTURE_VOL_L 0x4d /* P17v capture volume control */ +/* 4e - 4f: Not used */ +/* 50 - 5f: Not used */ +#define P17V_SRCSel 0x60 /* SRC48 and SRCMulti sample rate select + * and output select + */ +#define P17V_MIXER_AC97_10K1_VOL_L 0x61 /* 10K to Mixer_AC97 input volume control */ +#define P17V_MIXER_AC97_10K1_VOL_H 0x62 /* 10K to Mixer_AC97 input volume control */ +#define P17V_MIXER_AC97_P17V_VOL_L 0x63 /* P17V to Mixer_AC97 input volume control */ +#define P17V_MIXER_AC97_P17V_VOL_H 0x64 /* P17V to Mixer_AC97 input volume control */ +#define P17V_MIXER_AC97_SRP_REC_VOL_L 0x65 /* SRP Record to Mixer_AC97 input volume control */ +#define P17V_MIXER_AC97_SRP_REC_VOL_H 0x66 /* SRP Record to Mixer_AC97 input volume control */ +/* 67 - 68: Reserved */ +#define P17V_MIXER_Spdif_10K1_VOL_L 0x69 /* 10K to Mixer_Spdif input volume control */ +#define P17V_MIXER_Spdif_10K1_VOL_H 0x6A /* 10K to Mixer_Spdif input volume control */ +#define P17V_MIXER_Spdif_P17V_VOL_L 0x6B /* P17V to Mixer_Spdif input volume control */ +#define P17V_MIXER_Spdif_P17V_VOL_H 0x6C /* P17V to Mixer_Spdif input volume control */ +#define P17V_MIXER_Spdif_SRP_REC_VOL_L 0x6D /* SRP Record to Mixer_Spdif input volume control */ +#define P17V_MIXER_Spdif_SRP_REC_VOL_H 0x6E /* SRP Record to Mixer_Spdif input volume control */ +/* 6f - 70: Reserved */ +#define P17V_MIXER_I2S_10K1_VOL_L 0x71 /* 10K to Mixer_I2S input volume control */ +#define P17V_MIXER_I2S_10K1_VOL_H 0x72 /* 10K to Mixer_I2S input volume control */ +#define P17V_MIXER_I2S_P17V_VOL_L 0x73 /* P17V to Mixer_I2S input volume control */ +#define P17V_MIXER_I2S_P17V_VOL_H 0x74 /* P17V to Mixer_I2S input volume control */ +#define P17V_MIXER_I2S_SRP_REC_VOL_L 0x75 /* SRP Record to Mixer_I2S input volume control */ +#define P17V_MIXER_I2S_SRP_REC_VOL_H 0x76 /* SRP Record to Mixer_I2S input volume control */ +/* 77 - 78: Reserved */ +#define P17V_MIXER_AC97_ENABLE 0x79 /* Mixer AC97 input audio enable */ +#define P17V_MIXER_SPDIF_ENABLE 0x7A /* Mixer SPDIF input audio enable */ +#define P17V_MIXER_I2S_ENABLE 0x7B /* Mixer I2S input audio enable */ +#define P17V_AUDIO_OUT_ENABLE 0x7C /* Audio out enable */ +#define P17V_MIXER_ATT 0x7D /* SRP Mixer Attenuation Select */ +#define P17V_SRP_RECORD_SRR 0x7E /* SRP Record channel source Select */ +#define P17V_SOFT_RESET_SRP_MIXER 0x7F /* SRP and mixer soft reset */ + +#define P17V_AC97_OUT_MASTER_VOL_L 0x80 /* AC97 Output master volume control */ +#define P17V_AC97_OUT_MASTER_VOL_H 0x81 /* AC97 Output master volume control */ +#define P17V_SPDIF_OUT_MASTER_VOL_L 0x82 /* SPDIF Output master volume control */ +#define P17V_SPDIF_OUT_MASTER_VOL_H 0x83 /* SPDIF Output master volume control */ +#define P17V_I2S_OUT_MASTER_VOL_L 0x84 /* I2S Output master volume control */ +#define P17V_I2S_OUT_MASTER_VOL_H 0x85 /* I2S Output master volume control */ +/* 86 - 87: Not used */ +#define P17V_I2S_CHANNEL_SWAP_PHASE_INVERSE 0x88 /* I2S out mono channel swap + * and phase inverse */ +#define P17V_SPDIF_CHANNEL_SWAP_PHASE_INVERSE 0x89 /* SPDIF out mono channel swap + * and phase inverse */ +/* 8A: Not used */ +#define P17V_SRP_P17V_ESR 0x8B /* SRP_P17V estimated sample rate and rate lock */ +#define P17V_SRP_REC_ESR 0x8C /* SRP_REC estimated sample rate and rate lock */ +#define P17V_SRP_BYPASS 0x8D /* srps channel bypass and srps bypass */ +/* 8E - 92: Not used */ +#define P17V_I2S_SRC_SEL 0x93 /* I2SIN mode sel */ + + + + + + -- cgit v1.2.3 From be0b7b0113300c324034e94a12244c4ac3f4b354 Mon Sep 17 00:00:00 2001 From: James Courtier-Dutton Date: Sun, 9 Apr 2006 20:48:44 +0100 Subject: [ALSA] ca0106: Fixes MSI K8N's SB Live 24 bit, no sound from line-in. Fixed bug#1331 Signed-off-by: James Courtier-Dutton --- sound/pci/ca0106/ca0106_main.c | 9 +++++++-- sound/pci/ca0106/ca0106_mixer.c | 29 ++++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index 3762f58384e..b605d7045cc 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c @@ -195,9 +195,14 @@ static struct snd_ca0106_details ca0106_chip_details[] = { .i2c_adc = 1, .spi_dac = 1 } , /* MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97 */ + /* SB0438 + * CTRL:CA0106-DAT + * ADC: WM8775SEDS + * DAC: CS4382-KQZ + */ { .serial = 0x10091462, .name = "MSI K8N Diamond MB [SB0438]", - .gpio_type = 1, + .gpio_type = 2, .i2c_adc = 1 } , /* Shuttle XPC SD31P which has an onboard Creative Labs * Sound Blaster Live! 24-bit EAX @@ -1380,7 +1385,7 @@ static int __devinit snd_ca0106_create(struct snd_card *card, snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4); /* Select MIC, Line in, TAD in, AUX in */ chip->capture_source = 3; /* Set CAPTURE_SOURCE */ - if (chip->details->gpio_type == 2) { /* The SB0410 and SB0413 use GPIO differently. */ + if (chip->details->gpio_type == 2) { /* The SB0438 use GPIO differently. */ /* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */ outl(0x0, chip->port+GPIO); //outl(0x00f0e000, chip->port+GPIO); /* Analog */ diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c index 8a5833317b0..146eed70dce 100644 --- a/sound/pci/ca0106/ca0106_mixer.c +++ b/sound/pci/ca0106/ca0106_mixer.c @@ -227,6 +227,20 @@ static int snd_ca0106_i2c_capture_source_put(struct snd_kcontrol *kcontrol, return change; } +static int snd_ca0106_capture_line_in_side_out_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + static char *texts[2] = { "Side out", "Line in" }; + + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; + uinfo->count = 1; + uinfo->value.enumerated.items = 2; + if (uinfo->value.enumerated.item > 1) + uinfo->value.enumerated.item = 1; + strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); + return 0; +} + static int snd_ca0106_capture_mic_line_in_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { @@ -287,6 +301,16 @@ static struct snd_kcontrol_new snd_ca0106_capture_mic_line_in __devinitdata = .put = snd_ca0106_capture_mic_line_in_put }; +static struct snd_kcontrol_new snd_ca0106_capture_line_in_side_out __devinitdata = +{ + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Shared Line in/Side out Capture Switch", + .info = snd_ca0106_capture_line_in_side_out_info, + .get = snd_ca0106_capture_mic_line_in_get, + .put = snd_ca0106_capture_mic_line_in_put +}; + + static int snd_ca0106_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { @@ -611,7 +635,10 @@ int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu) return err; } if (emu->details->i2c_adc == 1) { - err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_mic_line_in, emu)); + if (emu->details->gpio_type == 1) + err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_mic_line_in, emu)); + else /* gpio_type == 2 */ + err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_line_in_side_out, emu)); if (err < 0) return err; } -- cgit v1.2.3 From d7f6f1157f73dffe0a6afd12b90557e484b7fb35 Mon Sep 17 00:00:00 2001 From: James Courtier-Dutton Date: Tue, 11 Apr 2006 21:47:27 +0100 Subject: [ALSA] AC97: Correct Mic Boost label. Signed-off-by: James Courtier-Dutton --- sound/pci/ac97/ac97_codec.c | 2 +- sound/pci/ac97/ac97_patch.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index 4544f6aa089..6c1937ff0d5 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -563,7 +563,7 @@ AC97_SINGLE("PC Speaker Playback Volume", AC97_PC_BEEP, 1, 15, 1) }; static const struct snd_kcontrol_new snd_ac97_controls_mic_boost = - AC97_SINGLE("Mic Boost (+20dB) Capture Switch", AC97_MIC, 6, 1, 0); + AC97_SINGLE("Mic Boost (+20dB) Switch", AC97_MIC, 6, 1, 0); static const char* std_rec_sel[] = {"Mic", "CD", "Video", "Aux", "Line", "Mix", "Mix Mono", "Phone"}; diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index 7ae7bc6524e..4d9cf37300f 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c @@ -563,7 +563,7 @@ AC97_SINGLE("Mic 1 to Phone Switch", AC97_MIC, 14, 1, 1), AC97_SINGLE("Mic 2 to Phone Switch", AC97_MIC, 13, 1, 1), AC97_ENUM("Mic Select Source", wm9711_enum[7]), AC97_SINGLE("Mic 1 Volume", AC97_MIC, 8, 32, 1), -AC97_SINGLE("Mic 20dB Boost Capture Switch", AC97_MIC, 7, 1, 0), +AC97_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 7, 1, 0), AC97_SINGLE("Master ZC Switch", AC97_MASTER, 7, 1, 0), AC97_SINGLE("Headphone ZC Switch", AC97_HEADPHONE, 7, 1, 0), @@ -653,7 +653,7 @@ AC97_SINGLE("Mic 1 Volume", AC97_MIC, 8, 31, 1), AC97_SINGLE("Mic 2 Volume", AC97_MIC, 0, 31, 1), AC97_SINGLE("Mic 1 to Mono Switch", AC97_LINE, 7, 1, 1), AC97_SINGLE("Mic 2 to Mono Switch", AC97_LINE, 6, 1, 1), -AC97_SINGLE("Mic Boost (+20dB) Capture Switch", AC97_LINE, 5, 1, 0), +AC97_SINGLE("Mic Boost (+20dB) Switch", AC97_LINE, 5, 1, 0), AC97_ENUM("Mic to Headphone Mux", wm9713_enum[0]), AC97_SINGLE("Mic Headphone Mixer Volume", AC97_LINE, 0, 7, 1), -- cgit v1.2.3 From 79ca4f3f625e14212310f953b096e2e45110ac6b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 12 Apr 2006 12:54:55 +0200 Subject: [ALSA] vxpocket - Fix a typo Fix a typo of return value from vxpocket_config(). Signed-off-by: Takashi Iwai --- sound/pcmcia/vx/vxpocket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c index 7e0cda2b6ef..cafe6640cc1 100644 --- a/sound/pcmcia/vx/vxpocket.c +++ b/sound/pcmcia/vx/vxpocket.c @@ -261,7 +261,7 @@ static int vxpocket_config(struct pcmcia_device *link) link->dev_node = &vxp->node; kfree(parse); - return 9; + return 0; cs_failed: cs_error(link, last_fn, last_ret); -- cgit v1.2.3 From 7152447df98b3981d621224be947a2c8d77aed06 Mon Sep 17 00:00:00 2001 From: Rene Herman Date: Thu, 13 Apr 2006 12:58:06 +0200 Subject: [ALSA] unregister platform device again if probe was unsuccessful This second one unregisters the platform device again when the probe is unsuccesful for sound/drivers, sound/arm/sa11xx-uda1341.c and sound/ppc/powermac.c. This gets them all. Signed-off-by: Rene Herman Signed-off-by: Takashi Iwai --- sound/arm/sa11xx-uda1341.c | 14 +++++++++----- sound/drivers/dummy.c | 4 ++++ sound/drivers/mpu401/mpu401.c | 4 ++++ sound/drivers/mtpav.c | 14 +++++++++----- sound/drivers/serial-u16550.c | 4 ++++ sound/drivers/virmidi.c | 4 ++++ sound/ppc/powermac.c | 14 +++++++++----- 7 files changed, 43 insertions(+), 15 deletions(-) diff --git a/sound/arm/sa11xx-uda1341.c b/sound/arm/sa11xx-uda1341.c index 13057d92f08..9211348824a 100644 --- a/sound/arm/sa11xx-uda1341.c +++ b/sound/arm/sa11xx-uda1341.c @@ -984,11 +984,15 @@ static int __init sa11xx_uda1341_init(void) if ((err = platform_driver_register(&sa11xx_uda1341_driver)) < 0) return err; device = platform_device_register_simple(SA11XX_UDA1341_DRIVER, -1, NULL, 0); - if (IS_ERR(device)) { - platform_driver_unregister(&sa11xx_uda1341_driver); - return PTR_ERR(device); - } - return 0; + if (!IS_ERR(device)) { + if (platform_get_drvdata(device)) + return 0; + platform_device_unregister(device); + err = -ENODEV + } else + err = PTR_ERR(device); + platform_driver_unregister(&sa11xx_uda1341_driver); + return err; } static void __exit sa11xx_uda1341_exit(void) diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c index ae0df549fac..ffeafaf2ecc 100644 --- a/sound/drivers/dummy.c +++ b/sound/drivers/dummy.c @@ -677,6 +677,10 @@ static int __init alsa_card_dummy_init(void) i, NULL, 0); if (IS_ERR(device)) continue; + if (!platform_get_drvdata(device)) { + platform_device_unregister(device); + continue; + } devices[i] = device; cards++; } diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c index 77b06009735..d3cbbb04758 100644 --- a/sound/drivers/mpu401/mpu401.c +++ b/sound/drivers/mpu401/mpu401.c @@ -253,6 +253,10 @@ static int __init alsa_card_mpu401_init(void) i, NULL, 0); if (IS_ERR(device)) continue; + if (!platform_get_drvdata(device)) { + platform_device_unregister(device); + continue; + } platform_devices[i] = device; snd_mpu401_devices++; } diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c index b7a0b42813e..474eed06e70 100644 --- a/sound/drivers/mtpav.c +++ b/sound/drivers/mtpav.c @@ -770,11 +770,15 @@ static int __init alsa_card_mtpav_init(void) return err; device = platform_device_register_simple(SND_MTPAV_DRIVER, -1, NULL, 0); - if (IS_ERR(device)) { - platform_driver_unregister(&snd_mtpav_driver); - return PTR_ERR(device); - } - return 0; + if (!IS_ERR(device)) { + if (platform_get_drvdata(device)) + return 0; + platform_device_unregister(device); + err = -ENODEV; + } else + err = PTR_ERR(device); + platform_driver_unregister(&snd_mtpav_driver); + return err; } static void __exit alsa_card_mtpav_exit(void) diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c index c01b4c5118b..2330fec505d 100644 --- a/sound/drivers/serial-u16550.c +++ b/sound/drivers/serial-u16550.c @@ -998,6 +998,10 @@ static int __init alsa_card_serial_init(void) i, NULL, 0); if (IS_ERR(device)) continue; + if (!platform_get_drvdata(device)) { + platform_device_unregister(device); + continue; + } devices[i] = device; cards++; } diff --git a/sound/drivers/virmidi.c b/sound/drivers/virmidi.c index 26eb2499d44..59171f8200d 100644 --- a/sound/drivers/virmidi.c +++ b/sound/drivers/virmidi.c @@ -171,6 +171,10 @@ static int __init alsa_card_virmidi_init(void) i, NULL, 0); if (IS_ERR(device)) continue; + if (!platform_get_drvdata(device)) { + platform_device_unregister(device); + continue; + } devices[i] = device; cards++; } diff --git a/sound/ppc/powermac.c b/sound/ppc/powermac.c index f4902a219e5..875f1f7bdc5 100644 --- a/sound/ppc/powermac.c +++ b/sound/ppc/powermac.c @@ -188,11 +188,15 @@ static int __init alsa_card_pmac_init(void) if ((err = platform_driver_register(&snd_pmac_driver)) < 0) return err; device = platform_device_register_simple(SND_PMAC_DRIVER, -1, NULL, 0); - if (IS_ERR(device)) { - platform_driver_unregister(&snd_pmac_driver); - return PTR_ERR(device); - } - return 0; + if (!IS_ERR(device)) { + if (platform_get_drvdata(device)) + return 0; + platform_device_unregister(device); + err = -ENODEV; + } else + err = PTR_ERR(device); + platform_driver_unregister(&snd_pmac_driver); + return err; } -- cgit v1.2.3 From 01686c5fce4682350849f9f2c262fcaf67ec73c3 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Apr 2006 12:54:11 +0200 Subject: [ALSA] hda-codec - Add Thinkpad X60/T60/Z60 support Added the support for Thinkpad X60/T60/Z60 laptops with AD1981HD codec. Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/ALSA-Configuration.txt | 1 + sound/pci/hda/patch_analog.c | 44 ++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 0ee2c7dfc48..3c09d9b8cd3 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -778,6 +778,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. AD1981 basic 3-jack (default) hp HP nx6320 + thinkpad Lenovo Thinkpad T60/X60/Z60 AD1986A 6stack 6-jack, separate surrounds (default) diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 40f000ba136..8ddae0a25ea 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -1329,13 +1329,50 @@ static int ad1981_hp_init(struct hda_codec *codec) return 0; } +/* configuration for Lenovo Thinkpad T60 */ +static struct snd_kcontrol_new ad1981_thinkpad_mixers[] = { + HDA_CODEC_VOLUME("Master Playback Volume", 0x05, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Master Playback Switch", 0x05, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("Mic Boost", 0x08, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT), + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Capture Source", + .info = ad198x_mux_enum_info, + .get = ad198x_mux_enum_get, + .put = ad198x_mux_enum_put, + }, + { } /* end */ +}; + +static struct hda_input_mux ad1981_thinkpad_capture_source = { + .num_items = 3, + .items = { + { "Mic", 0x0 }, + { "Mix", 0x2 }, + { "CD", 0x4 }, + }, +}; + /* models */ -enum { AD1981_BASIC, AD1981_HP }; +enum { AD1981_BASIC, AD1981_HP, AD1981_THINKPAD }; static struct hda_board_config ad1981_cfg_tbl[] = { { .modelname = "hp", .config = AD1981_HP }, /* All HP models */ { .pci_subvendor = 0x103c, .config = AD1981_HP }, + { .modelname = "thinkpad", .config = AD1981_THINKPAD }, + /* Lenovo Thinkpad T60/X60/Z6xx */ + { .pci_subvendor = 0x17aa, .config = AD1981_THINKPAD }, + { .pci_subvendor = 0x1014, .pci_subsystem = 0x0597, + .config = AD1981_THINKPAD }, /* Z60m/t */ { .modelname = "basic", .config = AD1981_BASIC }, {} }; @@ -1381,6 +1418,11 @@ static int patch_ad1981(struct hda_codec *codec) codec->patch_ops.init = ad1981_hp_init; codec->patch_ops.unsol_event = ad1981_hp_unsol_event; break; + case AD1981_THINKPAD: + spec->mixers[0] = ad1981_thinkpad_mixers; + spec->multiout.dig_out_nid = 0; + spec->input_mux = &ad1981_thinkpad_capture_source; + break; } return 0; -- cgit v1.2.3 From 887709be9063d233eb5abef25aafcd94615b03f9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Apr 2006 13:27:31 +0200 Subject: [ALSA] hda-codec - Fix a typo Fixed a typo of 'pci_subsystem' in the last changeset. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_analog.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 8ddae0a25ea..3a9b800db83 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -1371,7 +1371,7 @@ static struct hda_board_config ad1981_cfg_tbl[] = { { .modelname = "thinkpad", .config = AD1981_THINKPAD }, /* Lenovo Thinkpad T60/X60/Z6xx */ { .pci_subvendor = 0x17aa, .config = AD1981_THINKPAD }, - { .pci_subvendor = 0x1014, .pci_subsystem = 0x0597, + { .pci_subvendor = 0x1014, .pci_subdevice = 0x0597, .config = AD1981_THINKPAD }, /* Z60m/t */ { .modelname = "basic", .config = AD1981_BASIC }, {} -- cgit v1.2.3 From 78fc030bdbbeebdea436f2b02a616d67e5f9bd9b Mon Sep 17 00:00:00 2001 From: Alan Horstmann Date: Fri, 21 Apr 2006 08:39:20 +0200 Subject: [ALSA] Change seq_midi.c so client name is card, rather than port, specific Change snd_seq_midisynth_register_port() in seq_midi.c so that if a new client is created, the client name string is based on card->shortname not (port-specific) info->name. Signed-off-by: Alan Horstmann Signed-off-by: Clemens Ladisch --- sound/core/seq/seq_midi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c index 9caa1372bec..3b316da25ef 100644 --- a/sound/core/seq/seq_midi.c +++ b/sound/core/seq/seq_midi.c @@ -320,8 +320,8 @@ snd_seq_midisynth_register_port(struct snd_seq_device *dev) } client->seq_client = snd_seq_create_kernel_client( - card, 0, "%s", info->name[0] ? - (const char *)info->name : "External MIDI"); + card, 0, "%s", card->shortname[0] ? + (const char *)card->shortname : "External MIDI"); if (client->seq_client < 0) { kfree(client); mutex_unlock(®ister_mutex); -- cgit v1.2.3 From 3bef229e4f13790402b1387ea8147906f217a766 Mon Sep 17 00:00:00 2001 From: Alan Horstmann Date: Wed, 26 Apr 2006 18:13:59 +0200 Subject: [ALSA] ice1712 - Provides specified midi port names instead of defaults Patch provides for the ice1712 card driver to overwrite the midi port name string given by default in mpu401_uart, with one specified in snd_ice1712_card_info. Signed-off-by: Alan Horstmann Signed-off-by: Takashi Iwai --- sound/pci/ice1712/ews.c | 2 ++ sound/pci/ice1712/ice1712.c | 17 +++++++++++++++-- sound/pci/ice1712/ice1712.h | 2 ++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/sound/pci/ice1712/ews.c b/sound/pci/ice1712/ews.c index 2c529e74138..2e1cf112058 100644 --- a/sound/pci/ice1712/ews.c +++ b/sound/pci/ice1712/ews.c @@ -1031,6 +1031,8 @@ struct snd_ice1712_card_info snd_ice1712_ews_cards[] __devinitdata = { .model = "dmx6fire", .chip_init = snd_ice1712_ews_init, .build_controls = snd_ice1712_ews_add_controls, + .mpu401_1_name = "MIDI-Front DMX6fire", + .mpu401_2_name = "Wavetable DMX6fire", }, { } /* terminator */ }; diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index c56793b381e..2821014b26e 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c @@ -2743,8 +2743,14 @@ static int __devinit snd_ice1712_probe(struct pci_dev *pci, snd_card_free(card); return err; } - - if (ice->eeprom.data[ICE_EEP1_CODEC] & ICE1712_CFG_2xMPU401) + if (c->mpu401_1_name) + /* Prefered name available in card_info */ + snprintf(ice->rmidi[0]->name, + sizeof(ice->rmidi[0]->name), + "%s %d", c->mpu401_1_name, card->number); + + if (ice->eeprom.data[ICE_EEP1_CODEC] & ICE1712_CFG_2xMPU401) { + /* 2nd port used */ if ((err = snd_mpu401_uart_new(card, 1, MPU401_HW_ICE1712, ICEREG(ice, MPU2_CTRL), 1, ice->irq, 0, @@ -2752,6 +2758,13 @@ static int __devinit snd_ice1712_probe(struct pci_dev *pci, snd_card_free(card); return err; } + if (c->mpu401_2_name) + /* Prefered name available in card_info */ + snprintf(ice->rmidi[1]->name, + sizeof(ice->rmidi[1]->name), + "%s %d", c->mpu401_2_name, + card->number); + } } snd_ice1712_set_input_clock_source(ice, 0); diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h index 053f8e56fd6..d4776319a0c 100644 --- a/sound/pci/ice1712/ice1712.h +++ b/sound/pci/ice1712/ice1712.h @@ -495,6 +495,8 @@ struct snd_ice1712_card_info { int (*chip_init)(struct snd_ice1712 *); int (*build_controls)(struct snd_ice1712 *); unsigned int no_mpu401: 1; + const char *mpu401_1_name; + const char *mpu401_2_name; unsigned int eeprom_size; unsigned char *eeprom_data; }; -- cgit v1.2.3 From 5e1b1518a53fc62d9f39a13819c849336c6d8dd4 Mon Sep 17 00:00:00 2001 From: Kenneth Crudup Date: Fri, 28 Apr 2006 13:03:48 +0200 Subject: [ALSA] hda-codec - Add support for Sony Vaio VGN-A790 laptop Added the model entry for Sony Vaio VGN-A790 laptop with ALC260 codec. From: Kenneth Crudup Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index f0e9a9c9078..cf6c100940d 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -3822,6 +3822,8 @@ static struct hda_board_config alc260_cfg_tbl[] = { { .modelname = "basic", .config = ALC260_BASIC }, { .pci_subvendor = 0x104d, .pci_subdevice = 0x81bb, .config = ALC260_BASIC }, /* Sony VAIO */ + { .pci_subvendor = 0x104d, .pci_subdevice = 0x81cd, + .config = ALC260_BASIC }, /* Sony VAIO */ { .pci_subvendor = 0x152d, .pci_subdevice = 0x0729, .config = ALC260_BASIC }, /* CTL Travel Master U553W */ { .modelname = "hp", .config = ALC260_HP }, -- cgit v1.2.3 From 9ac25594e68a4b61516e7c1140d8c0f7ef449e20 Mon Sep 17 00:00:00 2001 From: Jaya Kumar Date: Fri, 28 Apr 2006 14:34:49 +0200 Subject: [ALSA] PM support for cs5535audio Appended is my patch adding PM support to the cs5535audio driver. I also added the ac97 quirk but it's not yet confirmed which boards need to be in the quirk list. The patch also includes some Kconfig and misc cleanup. Signed-off-by: Jaya Kumar Signed-off-by: Takashi Iwai --- sound/pci/Kconfig | 9 ++- sound/pci/cs5535audio/Makefile | 4 ++ sound/pci/cs5535audio/cs5535audio.c | 31 ++++++-- sound/pci/cs5535audio/cs5535audio.h | 8 +++ sound/pci/cs5535audio/cs5535audio_pcm.c | 24 ++++++- sound/pci/cs5535audio/cs5535audio_pm.c | 123 ++++++++++++++++++++++++++++++++ 6 files changed, 191 insertions(+), 8 deletions(-) create mode 100644 sound/pci/cs5535audio/cs5535audio_pm.c diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig index a2081803a82..d37346b12dc 100644 --- a/sound/pci/Kconfig +++ b/sound/pci/Kconfig @@ -216,14 +216,19 @@ config SND_CS46XX_NEW_DSP This works better than the old code, so say Y. config SND_CS5535AUDIO - tristate "CS5535 Audio" + tristate "CS5535/CS5536 Audio" depends on SND && X86 && !X86_64 select SND_PCM select SND_AC97_CODEC help Say Y here to include support for audio on CS5535 chips. It is referred to as NS CS5535 IO or AMD CS5535 IO companion in - various literature. + various literature. This driver also supports the CS5536 audio + device. However, for both chips, on certain boards, you may + need to use ac97_quirk=hp_only if your board has physically + mapped headphone out to master output. If that works for you, + send lspci -vvv output to the mailing list so that your board + can be identified in the quirks list. To compile this driver as a module, choose M here: the module will be called snd-cs5535audio. diff --git a/sound/pci/cs5535audio/Makefile b/sound/pci/cs5535audio/Makefile index 08d8ee6547d..2911a8adc1f 100644 --- a/sound/pci/cs5535audio/Makefile +++ b/sound/pci/cs5535audio/Makefile @@ -4,5 +4,9 @@ snd-cs5535audio-objs := cs5535audio.o cs5535audio_pcm.o +ifdef CONFIG_PM +snd-cs5535audio-objs += cs5535audio_pm.o +endif + # Toplevel Module Dependency obj-$(CONFIG_SND_CS5535AUDIO) += snd-cs5535audio.o diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c index 2c1213a35dc..41f02f05dfd 100644 --- a/sound/pci/cs5535audio/cs5535audio.c +++ b/sound/pci/cs5535audio/cs5535audio.c @@ -1,5 +1,5 @@ /* - * Driver for audio on multifunction CS5535 companion device + * Driver for audio on multifunction CS5535/6 companion device * Copyright (C) Jaya Kumar * * Based on Jaroslav Kysela and Takashi Iwai's examples. @@ -40,16 +40,29 @@ #define DRIVER_NAME "cs5535audio" +static char *ac97_quirk; +module_param(ac97_quirk, charp, 0444); +MODULE_PARM_DESC(ac97_quirk, "AC'97 board specific workarounds."); + +static struct ac97_quirk ac97_quirks[] __devinitdata = { +#if 0 /* Not yet confirmed if all 5536 boards are HP only */ + { + .subvendor = PCI_VENDOR_ID_AMD, + .subdevice = PCI_DEVICE_ID_AMD_CS5536_AUDIO, + .name = "AMD RDK", + .type = AC97_TUNE_HP_ONLY + }, +#endif + {} +}; static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; static struct pci_device_id snd_cs5535audio_ids[] __devinitdata = { - { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_AUDIO, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, - { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_AUDIO, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, + { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_AUDIO) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_AUDIO) }, {} }; @@ -148,6 +161,8 @@ static int snd_cs5535audio_mixer(struct cs5535audio *cs5535au) return err; } + snd_ac97_tune_hardware(cs5535au->ac97, ac97_quirks, ac97_quirk); + return 0; } @@ -347,6 +362,8 @@ static int __devinit snd_cs5535audio_probe(struct pci_dev *pci, if ((err = snd_cs5535audio_create(card, pci, &cs5535au)) < 0) goto probefail_out; + card->private_data = cs5535au; + if ((err = snd_cs5535audio_mixer(cs5535au)) < 0) goto probefail_out; @@ -383,6 +400,10 @@ static struct pci_driver driver = { .id_table = snd_cs5535audio_ids, .probe = snd_cs5535audio_probe, .remove = __devexit_p(snd_cs5535audio_remove), +#ifdef CONFIG_PM + .suspend = snd_cs5535audio_suspend, + .resume = snd_cs5535audio_resume, +#endif }; static int __init alsa_card_cs5535audio_init(void) diff --git a/sound/pci/cs5535audio/cs5535audio.h b/sound/pci/cs5535audio/cs5535audio.h index 5e55a1a1ed6..4fd1f31a6cf 100644 --- a/sound/pci/cs5535audio/cs5535audio.h +++ b/sound/pci/cs5535audio/cs5535audio.h @@ -74,6 +74,8 @@ #define PRM_RDY_STS 0x00800000 #define ACC_CODEC_CNTL_WR_CMD (~0x80000000) #define ACC_CODEC_CNTL_RD_CMD 0x80000000 +#define ACC_CODEC_CNTL_LNK_SHUTDOWN 0x00040000 +#define ACC_CODEC_CNTL_LNK_WRM_RST 0x00020000 #define PRD_JMP 0x2000 #define PRD_EOP 0x4000 #define PRD_EOT 0x8000 @@ -88,6 +90,7 @@ struct cs5535audio_dma_ops { void (*disable_dma)(struct cs5535audio *cs5535au); void (*pause_dma)(struct cs5535audio *cs5535au); void (*setup_prd)(struct cs5535audio *cs5535au, u32 prd_addr); + u32 (*read_prd)(struct cs5535audio *cs5535au); u32 (*read_dma_pntr)(struct cs5535audio *cs5535au); }; @@ -103,11 +106,14 @@ struct cs5535audio_dma { struct snd_pcm_substream *substream; unsigned int buf_addr, buf_bytes; unsigned int period_bytes, periods; + int suspended; + u32 saved_prd; }; struct cs5535audio { struct snd_card *card; struct snd_ac97 *ac97; + struct snd_pcm *pcm; int irq; struct pci_dev *pci; unsigned long port; @@ -117,6 +123,8 @@ struct cs5535audio { struct cs5535audio_dma dmas[NUM_CS5535AUDIO_DMAS]; }; +int snd_cs5535audio_suspend(struct pci_dev *pci, pm_message_t state); +int snd_cs5535audio_resume(struct pci_dev *pci); int __devinit snd_cs5535audio_pcm(struct cs5535audio *cs5535audio); #endif /* __SOUND_CS5535AUDIO_H */ diff --git a/sound/pci/cs5535audio/cs5535audio_pcm.c b/sound/pci/cs5535audio/cs5535audio_pcm.c index 60bb82b2ff4..f0a48693d68 100644 --- a/sound/pci/cs5535audio/cs5535audio_pcm.c +++ b/sound/pci/cs5535audio/cs5535audio_pcm.c @@ -43,7 +43,8 @@ static struct snd_pcm_hardware snd_cs5535audio_playback = SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_SYNC_START + SNDRV_PCM_INFO_SYNC_START | + SNDRV_PCM_INFO_RESUME ), .formats = ( SNDRV_PCM_FMTBIT_S16_LE @@ -193,6 +194,11 @@ static void cs5535audio_playback_setup_prd(struct cs5535audio *cs5535au, cs_writel(cs5535au, ACC_BM0_PRD, prd_addr); } +static u32 cs5535audio_playback_read_prd(struct cs5535audio *cs5535au) +{ + return cs_readl(cs5535au, ACC_BM0_PRD); +} + static u32 cs5535audio_playback_read_dma_pntr(struct cs5535audio *cs5535au) { return cs_readl(cs5535au, ACC_BM0_PNTR); @@ -219,6 +225,11 @@ static void cs5535audio_capture_setup_prd(struct cs5535audio *cs5535au, cs_writel(cs5535au, ACC_BM1_PRD, prd_addr); } +static u32 cs5535audio_capture_read_prd(struct cs5535audio *cs5535au) +{ + return cs_readl(cs5535au, ACC_BM1_PRD); +} + static u32 cs5535audio_capture_read_dma_pntr(struct cs5535audio *cs5535au) { return cs_readl(cs5535au, ACC_BM1_PNTR); @@ -285,9 +296,17 @@ static int snd_cs5535audio_trigger(struct snd_pcm_substream *substream, int cmd) case SNDRV_PCM_TRIGGER_START: dma->ops->enable_dma(cs5535au); break; + case SNDRV_PCM_TRIGGER_RESUME: + dma->ops->enable_dma(cs5535au); + dma->suspended = 0; + break; case SNDRV_PCM_TRIGGER_STOP: dma->ops->disable_dma(cs5535au); break; + case SNDRV_PCM_TRIGGER_SUSPEND: + dma->ops->disable_dma(cs5535au); + dma->suspended = 1; + break; default: snd_printk(KERN_ERR "unhandled trigger\n"); err = -EINVAL; @@ -375,6 +394,7 @@ static struct cs5535audio_dma_ops snd_cs5535audio_playback_dma_ops = { .enable_dma = cs5535audio_playback_enable_dma, .disable_dma = cs5535audio_playback_disable_dma, .setup_prd = cs5535audio_playback_setup_prd, + .read_prd = cs5535audio_playback_read_prd, .pause_dma = cs5535audio_playback_pause_dma, .read_dma_pntr = cs5535audio_playback_read_dma_pntr, }; @@ -384,6 +404,7 @@ static struct cs5535audio_dma_ops snd_cs5535audio_capture_dma_ops = { .enable_dma = cs5535audio_capture_enable_dma, .disable_dma = cs5535audio_capture_disable_dma, .setup_prd = cs5535audio_capture_setup_prd, + .read_prd = cs5535audio_capture_read_prd, .pause_dma = cs5535audio_capture_pause_dma, .read_dma_pntr = cs5535audio_capture_read_dma_pntr, }; @@ -413,6 +434,7 @@ int __devinit snd_cs5535audio_pcm(struct cs5535audio *cs5535au) snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(cs5535au->pci), 64*1024, 128*1024); + cs5535au->pcm = pcm; return 0; } diff --git a/sound/pci/cs5535audio/cs5535audio_pm.c b/sound/pci/cs5535audio/cs5535audio_pm.c new file mode 100644 index 00000000000..aad0e69db9c --- /dev/null +++ b/sound/pci/cs5535audio/cs5535audio_pm.c @@ -0,0 +1,123 @@ +/* + * Power management for audio on multifunction CS5535 companion device + * Copyright (C) Jaya Kumar + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cs5535audio.h" + +static void snd_cs5535audio_stop_hardware(struct cs5535audio *cs5535au) +{ + /* + we depend on snd_ac97_suspend to tell the + AC97 codec to shutdown. the amd spec suggests + that the LNK_SHUTDOWN be done at the same time + that the codec power-down is issued. instead, + we do it just after rather than at the same + time. excluding codec specific build_ops->suspend + ac97 powerdown hits: + 0x8000 EAPD + 0x4000 Headphone amplifier + 0x0300 ADC & DAC + 0x0400 Analog Mixer powerdown (Vref on) + I am not sure if this is the best that we can do. + The remainder to be investigated are: + - analog mixer (vref off) 0x0800 + - AC-link powerdown 0x1000 + - codec internal clock 0x2000 + */ + + /* set LNK_SHUTDOWN to shutdown AC link */ + cs_writel(cs5535au, ACC_CODEC_CNTL, ACC_CODEC_CNTL_LNK_SHUTDOWN); + +} + +int snd_cs5535audio_suspend(struct pci_dev *pci, pm_message_t state) +{ + struct snd_card *card = pci_get_drvdata(pci); + struct cs5535audio *cs5535au = card->private_data; + int i; + + snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); + for (i = 0; i < NUM_CS5535AUDIO_DMAS; i++) { + struct cs5535audio_dma *dma = &cs5535au->dmas[i]; + if (dma && dma->substream && !dma->suspended) + dma->saved_prd = dma->ops->read_prd(cs5535au); + } + snd_pcm_suspend_all(cs5535au->pcm); + snd_ac97_suspend(cs5535au->ac97); + /* save important regs, then disable aclink in hw */ + snd_cs5535audio_stop_hardware(cs5535au); + pci_disable_device(pci); + pci_save_state(pci); + + return 0; +} + +int snd_cs5535audio_resume(struct pci_dev *pci) +{ + struct snd_card *card = pci_get_drvdata(pci); + struct cs5535audio *cs5535au = card->private_data; + u32 tmp; + int timeout; + int i; + + pci_restore_state(pci); + pci_enable_device(pci); + pci_set_master(pci); + + /* set LNK_WRM_RST to reset AC link */ + cs_writel(cs5535au, ACC_CODEC_CNTL, ACC_CODEC_CNTL_LNK_WRM_RST); + + timeout = 50; + do { + tmp = cs_readl(cs5535au, ACC_CODEC_STATUS); + if (tmp & PRM_RDY_STS) + break; + udelay(1); + } while (--timeout); + + if (!timeout) + snd_printk(KERN_ERR "Failure getting AC Link ready\n"); + + /* we depend on ac97 to perform the codec power up */ + snd_ac97_resume(cs5535au->ac97); + /* set up rate regs, dma. actual initiation is done in trig */ + for (i = 0; i < NUM_CS5535AUDIO_DMAS; i++) { + struct cs5535audio_dma *dma = &cs5535au->dmas[i]; + if (dma && dma->substream && dma->suspended) { + dma->substream->ops->prepare(dma->substream); + dma->ops->setup_prd(cs5535au, dma->saved_prd); + } + } + + snd_power_change_state(card, SNDRV_CTL_POWER_D0); + + return 0; +} + -- cgit v1.2.3 From 9bb22e215c28204faee73dd7ac0ad98c075d6f7b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 28 Apr 2006 15:13:39 +0200 Subject: [ALSA] Clean up ugly hacks in pcm_params.h Clean up ugly hacks for sync with alsa-lib in pcm_params.h. Signed-off-by: Takashi Iwai --- include/sound/pcm_params.h | 105 ++++++++++++++++++--------------------------- 1 file changed, 42 insertions(+), 63 deletions(-) diff --git a/include/sound/pcm_params.h b/include/sound/pcm_params.h index fb18aef7734..e3bebd98e1c 100644 --- a/include/sound/pcm_params.h +++ b/include/sound/pcm_params.h @@ -35,16 +35,12 @@ extern int _snd_pcm_hw_param_setinteger(struct snd_pcm_hw_params *params, extern int _snd_pcm_hw_param_set(struct snd_pcm_hw_params *params, snd_pcm_hw_param_t var, unsigned int val, int dir); -/* To share the same code we have alsa-lib */ -#define INLINE static inline -#define assert(a) (void)(a) - #define SNDRV_MASK_BITS 64 /* we use so far 64bits only */ #define SNDRV_MASK_SIZE (SNDRV_MASK_BITS / 32) #define MASK_OFS(i) ((i) >> 5) #define MASK_BIT(i) (1U << ((i) & 31)) -INLINE unsigned int ld2(u_int32_t v) +static inline unsigned int ld2(u_int32_t v) { unsigned r = 0; @@ -69,22 +65,22 @@ INLINE unsigned int ld2(u_int32_t v) return r; } -INLINE size_t snd_mask_sizeof(void) +static inline size_t snd_mask_sizeof(void) { return sizeof(struct snd_mask); } -INLINE void snd_mask_none(struct snd_mask *mask) +static inline void snd_mask_none(struct snd_mask *mask) { memset(mask, 0, sizeof(*mask)); } -INLINE void snd_mask_any(struct snd_mask *mask) +static inline void snd_mask_any(struct snd_mask *mask) { memset(mask, 0xff, SNDRV_MASK_SIZE * sizeof(u_int32_t)); } -INLINE int snd_mask_empty(const struct snd_mask *mask) +static inline int snd_mask_empty(const struct snd_mask *mask) { int i; for (i = 0; i < SNDRV_MASK_SIZE; i++) @@ -93,10 +89,9 @@ INLINE int snd_mask_empty(const struct snd_mask *mask) return 1; } -INLINE unsigned int snd_mask_min(const struct snd_mask *mask) +static inline unsigned int snd_mask_min(const struct snd_mask *mask) { int i; - assert(!snd_mask_empty(mask)); for (i = 0; i < SNDRV_MASK_SIZE; i++) { if (mask->bits[i]) return ffs(mask->bits[i]) - 1 + (i << 5); @@ -104,10 +99,9 @@ INLINE unsigned int snd_mask_min(const struct snd_mask *mask) return 0; } -INLINE unsigned int snd_mask_max(const struct snd_mask *mask) +static inline unsigned int snd_mask_max(const struct snd_mask *mask) { int i; - assert(!snd_mask_empty(mask)); for (i = SNDRV_MASK_SIZE - 1; i >= 0; i--) { if (mask->bits[i]) return ld2(mask->bits[i]) + (i << 5); @@ -115,70 +109,68 @@ INLINE unsigned int snd_mask_max(const struct snd_mask *mask) return 0; } -INLINE void snd_mask_set(struct snd_mask *mask, unsigned int val) +static inline void snd_mask_set(struct snd_mask *mask, unsigned int val) { - assert(val <= SNDRV_MASK_BITS); mask->bits[MASK_OFS(val)] |= MASK_BIT(val); } -INLINE void snd_mask_reset(struct snd_mask *mask, unsigned int val) +static inline void snd_mask_reset(struct snd_mask *mask, unsigned int val) { - assert(val <= SNDRV_MASK_BITS); mask->bits[MASK_OFS(val)] &= ~MASK_BIT(val); } -INLINE void snd_mask_set_range(struct snd_mask *mask, unsigned int from, unsigned int to) +static inline void snd_mask_set_range(struct snd_mask *mask, + unsigned int from, unsigned int to) { unsigned int i; - assert(to <= SNDRV_MASK_BITS && from <= to); for (i = from; i <= to; i++) mask->bits[MASK_OFS(i)] |= MASK_BIT(i); } -INLINE void snd_mask_reset_range(struct snd_mask *mask, unsigned int from, unsigned int to) +static inline void snd_mask_reset_range(struct snd_mask *mask, + unsigned int from, unsigned int to) { unsigned int i; - assert(to <= SNDRV_MASK_BITS && from <= to); for (i = from; i <= to; i++) mask->bits[MASK_OFS(i)] &= ~MASK_BIT(i); } -INLINE void snd_mask_leave(struct snd_mask *mask, unsigned int val) +static inline void snd_mask_leave(struct snd_mask *mask, unsigned int val) { unsigned int v; - assert(val <= SNDRV_MASK_BITS); v = mask->bits[MASK_OFS(val)] & MASK_BIT(val); snd_mask_none(mask); mask->bits[MASK_OFS(val)] = v; } -INLINE void snd_mask_intersect(struct snd_mask *mask, const struct snd_mask *v) +static inline void snd_mask_intersect(struct snd_mask *mask, + const struct snd_mask *v) { int i; for (i = 0; i < SNDRV_MASK_SIZE; i++) mask->bits[i] &= v->bits[i]; } -INLINE int snd_mask_eq(const struct snd_mask *mask, const struct snd_mask *v) +static inline int snd_mask_eq(const struct snd_mask *mask, + const struct snd_mask *v) { return ! memcmp(mask, v, SNDRV_MASK_SIZE * sizeof(u_int32_t)); } -INLINE void snd_mask_copy(struct snd_mask *mask, const struct snd_mask *v) +static inline void snd_mask_copy(struct snd_mask *mask, + const struct snd_mask *v) { *mask = *v; } -INLINE int snd_mask_test(const struct snd_mask *mask, unsigned int val) +static inline int snd_mask_test(const struct snd_mask *mask, unsigned int val) { - assert(val <= SNDRV_MASK_BITS); return mask->bits[MASK_OFS(val)] & MASK_BIT(val); } -INLINE int snd_mask_single(const struct snd_mask *mask) +static inline int snd_mask_single(const struct snd_mask *mask) { int i, c = 0; - assert(!snd_mask_empty(mask)); for (i = 0; i < SNDRV_MASK_SIZE; i++) { if (! mask->bits[i]) continue; @@ -191,10 +183,10 @@ INLINE int snd_mask_single(const struct snd_mask *mask) return 1; } -INLINE int snd_mask_refine(struct snd_mask *mask, const struct snd_mask *v) +static inline int snd_mask_refine(struct snd_mask *mask, + const struct snd_mask *v) { struct snd_mask old; - assert(!snd_mask_empty(mask)); snd_mask_copy(&old, mask); snd_mask_intersect(mask, v); if (snd_mask_empty(mask)) @@ -202,27 +194,24 @@ INLINE int snd_mask_refine(struct snd_mask *mask, const struct snd_mask *v) return !snd_mask_eq(mask, &old); } -INLINE int snd_mask_refine_first(struct snd_mask *mask) +static inline int snd_mask_refine_first(struct snd_mask *mask) { - assert(!snd_mask_empty(mask)); if (snd_mask_single(mask)) return 0; snd_mask_leave(mask, snd_mask_min(mask)); return 1; } -INLINE int snd_mask_refine_last(struct snd_mask *mask) +static inline int snd_mask_refine_last(struct snd_mask *mask) { - assert(!snd_mask_empty(mask)); if (snd_mask_single(mask)) return 0; snd_mask_leave(mask, snd_mask_max(mask)); return 1; } -INLINE int snd_mask_refine_min(struct snd_mask *mask, unsigned int val) +static inline int snd_mask_refine_min(struct snd_mask *mask, unsigned int val) { - assert(!snd_mask_empty(mask)); if (snd_mask_min(mask) >= val) return 0; snd_mask_reset_range(mask, 0, val - 1); @@ -231,9 +220,8 @@ INLINE int snd_mask_refine_min(struct snd_mask *mask, unsigned int val) return 1; } -INLINE int snd_mask_refine_max(struct snd_mask *mask, unsigned int val) +static inline int snd_mask_refine_max(struct snd_mask *mask, unsigned int val) { - assert(!snd_mask_empty(mask)); if (snd_mask_max(mask) <= val) return 0; snd_mask_reset_range(mask, val + 1, SNDRV_MASK_BITS); @@ -242,10 +230,9 @@ INLINE int snd_mask_refine_max(struct snd_mask *mask, unsigned int val) return 1; } -INLINE int snd_mask_refine_set(struct snd_mask *mask, unsigned int val) +static inline int snd_mask_refine_set(struct snd_mask *mask, unsigned int val) { int changed; - assert(!snd_mask_empty(mask)); changed = !snd_mask_single(mask); snd_mask_leave(mask, val); if (snd_mask_empty(mask)) @@ -253,13 +240,12 @@ INLINE int snd_mask_refine_set(struct snd_mask *mask, unsigned int val) return changed; } -INLINE int snd_mask_value(const struct snd_mask *mask) +static inline int snd_mask_value(const struct snd_mask *mask) { - assert(!snd_mask_empty(mask)); return snd_mask_min(mask); } -INLINE void snd_interval_any(struct snd_interval *i) +static inline void snd_interval_any(struct snd_interval *i) { i->min = 0; i->openmin = 0; @@ -269,63 +255,59 @@ INLINE void snd_interval_any(struct snd_interval *i) i->empty = 0; } -INLINE void snd_interval_none(struct snd_interval *i) +static inline void snd_interval_none(struct snd_interval *i) { i->empty = 1; } -INLINE int snd_interval_checkempty(const struct snd_interval *i) +static inline int snd_interval_checkempty(const struct snd_interval *i) { return (i->min > i->max || (i->min == i->max && (i->openmin || i->openmax))); } -INLINE int snd_interval_empty(const struct snd_interval *i) +static inline int snd_interval_empty(const struct snd_interval *i) { return i->empty; } -INLINE int snd_interval_single(const struct snd_interval *i) +static inline int snd_interval_single(const struct snd_interval *i) { - assert(!snd_interval_empty(i)); return (i->min == i->max || (i->min + 1 == i->max && i->openmax)); } -INLINE int snd_interval_value(const struct snd_interval *i) +static inline int snd_interval_value(const struct snd_interval *i) { - assert(snd_interval_single(i)); return i->min; } -INLINE int snd_interval_min(const struct snd_interval *i) +static inline int snd_interval_min(const struct snd_interval *i) { - assert(!snd_interval_empty(i)); return i->min; } -INLINE int snd_interval_max(const struct snd_interval *i) +static inline int snd_interval_max(const struct snd_interval *i) { unsigned int v; - assert(!snd_interval_empty(i)); v = i->max; if (i->openmax) v--; return v; } -INLINE int snd_interval_test(const struct snd_interval *i, unsigned int val) +static inline int snd_interval_test(const struct snd_interval *i, unsigned int val) { return !((i->min > val || (i->min == val && i->openmin) || i->max < val || (i->max == val && i->openmax))); } -INLINE void snd_interval_copy(struct snd_interval *d, const struct snd_interval *s) +static inline void snd_interval_copy(struct snd_interval *d, const struct snd_interval *s) { *d = *s; } -INLINE int snd_interval_setinteger(struct snd_interval *i) +static inline int snd_interval_setinteger(struct snd_interval *i) { if (i->integer) return 0; @@ -335,7 +317,7 @@ INLINE int snd_interval_setinteger(struct snd_interval *i) return 1; } -INLINE int snd_interval_eq(const struct snd_interval *i1, const struct snd_interval *i2) +static inline int snd_interval_eq(const struct snd_interval *i1, const struct snd_interval *i2) { if (i1->empty) return i2->empty; @@ -359,8 +341,5 @@ static inline unsigned int sub(unsigned int a, unsigned int b) return 0; } -#undef INLINE -#undef assert - #endif /* __SOUND_PCM_PARAMS_H */ -- cgit v1.2.3 From c0d3fb39e9511c6fad17d059a3a50d1be33add24 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 28 Apr 2006 15:13:39 +0200 Subject: [ALSA] Clean up EXPORT_SYMBOL()s in snd module Move EXPORT_SYMBOL()s to places adjacent to functions/variables. Signed-off-by: Takashi Iwai --- sound/core/control.c | 31 ++++++++++++++++ sound/core/device.c | 6 +++ sound/core/info.c | 20 ++++++++++ sound/core/info_oss.c | 2 + sound/core/init.c | 20 ++++++++++ sound/core/isadma.c | 6 +++ sound/core/memory.c | 5 +++ sound/core/misc.c | 6 +++ sound/core/sound.c | 99 ++++++-------------------------------------------- sound/core/sound_oss.c | 6 +++ 10 files changed, 113 insertions(+), 88 deletions(-) diff --git a/sound/core/control.c b/sound/core/control.c index 22565c9b960..bb397eaa718 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -176,6 +176,8 @@ void snd_ctl_notify(struct snd_card *card, unsigned int mask, read_unlock(&card->ctl_files_rwlock); } +EXPORT_SYMBOL(snd_ctl_notify); + /** * snd_ctl_new - create a control instance from the template * @control: the control template @@ -204,6 +206,8 @@ struct snd_kcontrol *snd_ctl_new(struct snd_kcontrol *control, unsigned int acce return kctl; } +EXPORT_SYMBOL(snd_ctl_new); + /** * snd_ctl_new1 - create a control instance from the template * @ncontrol: the initialization record @@ -242,6 +246,8 @@ struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new *ncontrol, return snd_ctl_new(&kctl, access); } +EXPORT_SYMBOL(snd_ctl_new1); + /** * snd_ctl_free_one - release the control instance * @kcontrol: the control instance @@ -259,6 +265,8 @@ void snd_ctl_free_one(struct snd_kcontrol *kcontrol) } } +EXPORT_SYMBOL(snd_ctl_free_one); + static unsigned int snd_ctl_hole_check(struct snd_card *card, unsigned int count) { @@ -347,6 +355,8 @@ int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol) return err; } +EXPORT_SYMBOL(snd_ctl_add); + /** * snd_ctl_remove - remove the control from the card and release it * @card: the card instance @@ -373,6 +383,8 @@ int snd_ctl_remove(struct snd_card *card, struct snd_kcontrol *kcontrol) return 0; } +EXPORT_SYMBOL(snd_ctl_remove); + /** * snd_ctl_remove_id - remove the control of the given id and release it * @card: the card instance @@ -399,6 +411,8 @@ int snd_ctl_remove_id(struct snd_card *card, struct snd_ctl_elem_id *id) return ret; } +EXPORT_SYMBOL(snd_ctl_remove_id); + /** * snd_ctl_remove_unlocked_id - remove the unlocked control of the given id and release it * @file: active control handle @@ -461,6 +475,8 @@ int snd_ctl_rename_id(struct snd_card *card, struct snd_ctl_elem_id *src_id, return 0; } +EXPORT_SYMBOL(snd_ctl_rename_id); + /** * snd_ctl_find_numid - find the control instance with the given number-id * @card: the card instance @@ -487,6 +503,8 @@ struct snd_kcontrol *snd_ctl_find_numid(struct snd_card *card, unsigned int numi return NULL; } +EXPORT_SYMBOL(snd_ctl_find_numid); + /** * snd_ctl_find_id - find the control instance with the given id * @card: the card instance @@ -527,6 +545,8 @@ struct snd_kcontrol *snd_ctl_find_id(struct snd_card *card, return NULL; } +EXPORT_SYMBOL(snd_ctl_find_id); + static int snd_ctl_card_info(struct snd_card *card, struct snd_ctl_file * ctl, unsigned int cmd, void __user *arg) { @@ -704,6 +724,8 @@ int snd_ctl_elem_read(struct snd_card *card, struct snd_ctl_elem_value *control) return result; } +EXPORT_SYMBOL(snd_ctl_elem_read); + static int snd_ctl_elem_read_user(struct snd_card *card, struct snd_ctl_elem_value __user *_control) { @@ -767,6 +789,8 @@ int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file, return result; } +EXPORT_SYMBOL(snd_ctl_elem_write); + static int snd_ctl_elem_write_user(struct snd_ctl_file *file, struct snd_ctl_elem_value __user *_control) { @@ -1199,11 +1223,15 @@ int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn) return _snd_ctl_register_ioctl(fcn, &snd_control_ioctls); } +EXPORT_SYMBOL(snd_ctl_register_ioctl); + #ifdef CONFIG_COMPAT int snd_ctl_register_ioctl_compat(snd_kctl_ioctl_func_t fcn) { return _snd_ctl_register_ioctl(fcn, &snd_control_compat_ioctls); } + +EXPORT_SYMBOL(snd_ctl_register_ioctl_compat); #endif /* @@ -1236,12 +1264,15 @@ int snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn) return _snd_ctl_unregister_ioctl(fcn, &snd_control_ioctls); } +EXPORT_SYMBOL(snd_ctl_unregister_ioctl); + #ifdef CONFIG_COMPAT int snd_ctl_unregister_ioctl_compat(snd_kctl_ioctl_func_t fcn) { return _snd_ctl_unregister_ioctl(fcn, &snd_control_compat_ioctls); } +EXPORT_SYMBOL(snd_ctl_unregister_ioctl_compat); #endif static int snd_ctl_fasync(int fd, struct file * file, int on) diff --git a/sound/core/device.c b/sound/core/device.c index b1cf6ec5678..6ce4da4a108 100644 --- a/sound/core/device.c +++ b/sound/core/device.c @@ -63,6 +63,8 @@ int snd_device_new(struct snd_card *card, snd_device_type_t type, return 0; } +EXPORT_SYMBOL(snd_device_new); + /** * snd_device_free - release the device from the card * @card: the card instance @@ -107,6 +109,8 @@ int snd_device_free(struct snd_card *card, void *device_data) return -ENXIO; } +EXPORT_SYMBOL(snd_device_free); + /** * snd_device_disconnect - disconnect the device * @card: the card instance @@ -182,6 +186,8 @@ int snd_device_register(struct snd_card *card, void *device_data) return -ENXIO; } +EXPORT_SYMBOL(snd_device_register); + /* * register all the devices on the card. * called from init.c diff --git a/sound/core/info.c b/sound/core/info.c index 2582b74d319..9c288539e99 100644 --- a/sound/core/info.c +++ b/sound/core/info.c @@ -111,12 +111,16 @@ int snd_iprintf(struct snd_info_buffer *buffer, char *fmt,...) return res; } +EXPORT_SYMBOL(snd_iprintf); + /* */ static struct proc_dir_entry *snd_proc_root = NULL; struct snd_info_entry *snd_seq_root = NULL; +EXPORT_SYMBOL(snd_seq_root); + #ifdef CONFIG_SND_OSSEMUL struct snd_info_entry *snd_oss_root = NULL; #endif @@ -687,6 +691,8 @@ int snd_info_get_line(struct snd_info_buffer *buffer, char *line, int len) return 0; } +EXPORT_SYMBOL(snd_info_get_line); + /** * snd_info_get_str - parse a string token * @dest: the buffer to store the string token @@ -723,6 +729,8 @@ char *snd_info_get_str(char *dest, char *src, int len) return src; } +EXPORT_SYMBOL(snd_info_get_str); + /** * snd_info_create_entry - create an info entry * @name: the proc file name @@ -774,6 +782,8 @@ struct snd_info_entry *snd_info_create_module_entry(struct module * module, return entry; } +EXPORT_SYMBOL(snd_info_create_module_entry); + /** * snd_info_create_card_entry - create an info entry for the given card * @card: the card instance @@ -797,6 +807,8 @@ struct snd_info_entry *snd_info_create_card_entry(struct snd_card *card, return entry; } +EXPORT_SYMBOL(snd_info_create_card_entry); + static int snd_info_dev_free_entry(struct snd_device *device) { struct snd_info_entry *entry = device->device_data; @@ -867,6 +879,8 @@ int snd_card_proc_new(struct snd_card *card, const char *name, return 0; } +EXPORT_SYMBOL(snd_card_proc_new); + /** * snd_info_free_entry - release the info entry * @entry: the info entry @@ -883,6 +897,8 @@ void snd_info_free_entry(struct snd_info_entry * entry) kfree(entry); } +EXPORT_SYMBOL(snd_info_free_entry); + /** * snd_info_register - register the info entry * @entry: the info entry @@ -913,6 +929,8 @@ int snd_info_register(struct snd_info_entry * entry) return 0; } +EXPORT_SYMBOL(snd_info_register); + /** * snd_info_unregister - de-register the info entry * @entry: the info entry @@ -937,6 +955,8 @@ int snd_info_unregister(struct snd_info_entry * entry) return 0; } +EXPORT_SYMBOL(snd_info_unregister); + /* */ diff --git a/sound/core/info_oss.c b/sound/core/info_oss.c index f9ce854b3d1..f2efca18728 100644 --- a/sound/core/info_oss.c +++ b/sound/core/info_oss.c @@ -64,6 +64,8 @@ int snd_oss_info_register(int dev, int num, char *string) return 0; } +EXPORT_SYMBOL(snd_oss_info_register); + extern void snd_card_info_read_oss(struct snd_info_buffer *buffer); static int snd_sndstat_show_strings(struct snd_info_buffer *buf, char *id, int dev) diff --git a/sound/core/init.c b/sound/core/init.c index 39ed2e5bb0a..b145d17ba3b 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -40,10 +40,13 @@ struct snd_shutdown_f_ops { unsigned int snd_cards_lock = 0; /* locked for registering/using */ struct snd_card *snd_cards[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = NULL}; +EXPORT_SYMBOL(snd_cards); + DEFINE_RWLOCK(snd_card_rwlock); #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) int (*snd_mixer_oss_notify_callback)(struct snd_card *card, int free_flag); +EXPORT_SYMBOL(snd_mixer_oss_notify_callback); #endif #ifdef CONFIG_PROC_FS @@ -169,6 +172,8 @@ struct snd_card *snd_card_new(int idx, const char *xid, return NULL; } +EXPORT_SYMBOL(snd_card_new); + static loff_t snd_disconnect_llseek(struct file *file, loff_t offset, int orig) { return -ENODEV; @@ -298,6 +303,8 @@ int snd_card_disconnect(struct snd_card *card) return 0; } +EXPORT_SYMBOL(snd_card_disconnect); + /** * snd_card_free - frees given soundcard structure * @card: soundcard structure @@ -360,6 +367,8 @@ int snd_card_free(struct snd_card *card) return 0; } +EXPORT_SYMBOL(snd_card_free); + static void snd_card_free_thread(void * __card) { struct snd_card *card = __card; @@ -405,6 +414,8 @@ int snd_card_free_in_thread(struct snd_card *card) return -EFAULT; } +EXPORT_SYMBOL(snd_card_free_in_thread); + static void choose_default_id(struct snd_card *card) { int i, len, idx_flag = 0, loops = SNDRV_CARDS; @@ -505,6 +516,8 @@ int snd_card_register(struct snd_card *card) return 0; } +EXPORT_SYMBOL(snd_card_register); + #ifdef CONFIG_PROC_FS static struct snd_info_entry *snd_card_info_entry = NULL; @@ -644,6 +657,8 @@ int snd_component_add(struct snd_card *card, const char *component) return 0; } +EXPORT_SYMBOL(snd_component_add); + /** * snd_card_file_add - add the file to the file list of the card * @card: soundcard structure @@ -676,6 +691,8 @@ int snd_card_file_add(struct snd_card *card, struct file *file) return 0; } +EXPORT_SYMBOL(snd_card_file_add); + /** * snd_card_file_remove - remove the file from the file list * @card: soundcard structure @@ -717,6 +734,8 @@ int snd_card_file_remove(struct snd_card *card, struct file *file) return 0; } +EXPORT_SYMBOL(snd_card_file_remove); + #ifdef CONFIG_PM /** * snd_power_wait - wait until the power-state is changed. @@ -753,4 +772,5 @@ int snd_power_wait(struct snd_card *card, unsigned int power_state) return result; } +EXPORT_SYMBOL(snd_power_wait); #endif /* CONFIG_PM */ diff --git a/sound/core/isadma.c b/sound/core/isadma.c index 1a378951da5..d52398727f0 100644 --- a/sound/core/isadma.c +++ b/sound/core/isadma.c @@ -56,6 +56,8 @@ void snd_dma_program(unsigned long dma, release_dma_lock(flags); } +EXPORT_SYMBOL(snd_dma_program); + /** * snd_dma_disable - stop the ISA DMA transfer * @dma: the dma number @@ -72,6 +74,8 @@ void snd_dma_disable(unsigned long dma) release_dma_lock(flags); } +EXPORT_SYMBOL(snd_dma_disable); + /** * snd_dma_pointer - return the current pointer to DMA transfer buffer in bytes * @dma: the dma number @@ -101,3 +105,5 @@ unsigned int snd_dma_pointer(unsigned long dma, unsigned int size) else return size - result; } + +EXPORT_SYMBOL(snd_dma_pointer); diff --git a/sound/core/memory.c b/sound/core/memory.c index 862d62d2e14..fe59850be86 100644 --- a/sound/core/memory.c +++ b/sound/core/memory.c @@ -21,6 +21,7 @@ */ #include +#include #include #include @@ -55,6 +56,8 @@ int copy_to_user_fromio(void __user *dst, const volatile void __iomem *src, size #endif } +EXPORT_SYMBOL(copy_to_user_fromio); + /** * copy_from_user_toio - copy data from user-space to mmio-space * @dst: the destination pointer on mmio-space @@ -85,3 +88,5 @@ int copy_from_user_toio(volatile void __iomem *dst, const void __user *src, size return 0; #endif } + +EXPORT_SYMBOL(copy_from_user_toio); diff --git a/sound/core/misc.c b/sound/core/misc.c index b53e563c09e..03fc711f412 100644 --- a/sound/core/misc.c +++ b/sound/core/misc.c @@ -34,6 +34,8 @@ void release_and_free_resource(struct resource *res) } } +EXPORT_SYMBOL(release_and_free_resource); + #ifdef CONFIG_SND_VERBOSE_PRINTK void snd_verbose_printk(const char *file, int line, const char *format, ...) { @@ -51,6 +53,8 @@ void snd_verbose_printk(const char *file, int line, const char *format, ...) vprintk(format, args); va_end(args); } + +EXPORT_SYMBOL(snd_verbose_printk); #endif #if defined(CONFIG_SND_DEBUG) && defined(CONFIG_SND_VERBOSE_PRINTK) @@ -71,4 +75,6 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...) va_end(args); } + +EXPORT_SYMBOL(snd_verbose_printd); #endif diff --git a/sound/core/sound.c b/sound/core/sound.c index 108e430b503..67cfa06062b 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c @@ -39,6 +39,8 @@ static int major = CONFIG_SND_MAJOR; int snd_major; +EXPORT_SYMBOL(snd_major); + static int cards_limit = 1; static int device_mode = S_IFCHR | S_IRUGO | S_IWUGO; @@ -60,6 +62,7 @@ MODULE_ALIAS_CHARDEV_MAJOR(CONFIG_SND_MAJOR); * modules are loaded manually, this limit number increases, too. */ int snd_ecards_limit; +EXPORT_SYMBOL(snd_ecards_limit); static struct snd_minor *snd_minors[SNDRV_OS_MINORS]; static DEFINE_MUTEX(sound_mutex); @@ -92,6 +95,8 @@ void snd_request_card(int card) request_module("snd-card-%i", card); } +EXPORT_SYMBOL(snd_request_card); + static void snd_request_other(int minor) { char *str; @@ -133,6 +138,8 @@ void *snd_lookup_minor_data(unsigned int minor, int type) return private_data; } +EXPORT_SYMBOL(snd_lookup_minor_data); + static int snd_open(struct inode *inode, struct file *file) { unsigned int minor = iminor(inode); @@ -281,6 +288,8 @@ int snd_register_device(int type, struct snd_card *card, int dev, return 0; } +EXPORT_SYMBOL(snd_register_device); + /** * snd_unregister_device - unregister the device on the given card * @type: the device type, SNDRV_DEVICE_TYPE_XXX @@ -321,6 +330,8 @@ int snd_unregister_device(int type, struct snd_card *card, int dev) return 0; } +EXPORT_SYMBOL(snd_unregister_device); + #ifdef CONFIG_PROC_FS /* * INFO PART @@ -446,91 +457,3 @@ static void __exit alsa_sound_exit(void) module_init(alsa_sound_init) module_exit(alsa_sound_exit) - - /* sound.c */ -EXPORT_SYMBOL(snd_major); -EXPORT_SYMBOL(snd_ecards_limit); -#if defined(CONFIG_KMOD) -EXPORT_SYMBOL(snd_request_card); -#endif -EXPORT_SYMBOL(snd_register_device); -EXPORT_SYMBOL(snd_unregister_device); -EXPORT_SYMBOL(snd_lookup_minor_data); -#if defined(CONFIG_SND_OSSEMUL) -EXPORT_SYMBOL(snd_register_oss_device); -EXPORT_SYMBOL(snd_unregister_oss_device); -EXPORT_SYMBOL(snd_lookup_oss_minor_data); -#endif - /* memory.c */ -EXPORT_SYMBOL(copy_to_user_fromio); -EXPORT_SYMBOL(copy_from_user_toio); - /* init.c */ -EXPORT_SYMBOL(snd_cards); -#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) -EXPORT_SYMBOL(snd_mixer_oss_notify_callback); -#endif -EXPORT_SYMBOL(snd_card_new); -EXPORT_SYMBOL(snd_card_disconnect); -EXPORT_SYMBOL(snd_card_free); -EXPORT_SYMBOL(snd_card_free_in_thread); -EXPORT_SYMBOL(snd_card_register); -EXPORT_SYMBOL(snd_component_add); -EXPORT_SYMBOL(snd_card_file_add); -EXPORT_SYMBOL(snd_card_file_remove); -#ifdef CONFIG_PM -EXPORT_SYMBOL(snd_power_wait); -#endif - /* device.c */ -EXPORT_SYMBOL(snd_device_new); -EXPORT_SYMBOL(snd_device_register); -EXPORT_SYMBOL(snd_device_free); - /* isadma.c */ -#ifdef CONFIG_ISA_DMA_API -EXPORT_SYMBOL(snd_dma_program); -EXPORT_SYMBOL(snd_dma_disable); -EXPORT_SYMBOL(snd_dma_pointer); -#endif - /* info.c */ -#ifdef CONFIG_PROC_FS -EXPORT_SYMBOL(snd_seq_root); -EXPORT_SYMBOL(snd_iprintf); -EXPORT_SYMBOL(snd_info_get_line); -EXPORT_SYMBOL(snd_info_get_str); -EXPORT_SYMBOL(snd_info_create_module_entry); -EXPORT_SYMBOL(snd_info_create_card_entry); -EXPORT_SYMBOL(snd_info_free_entry); -EXPORT_SYMBOL(snd_info_register); -EXPORT_SYMBOL(snd_info_unregister); -EXPORT_SYMBOL(snd_card_proc_new); -#endif - /* info_oss.c */ -#if defined(CONFIG_SND_OSSEMUL) && defined(CONFIG_PROC_FS) -EXPORT_SYMBOL(snd_oss_info_register); -#endif - /* control.c */ -EXPORT_SYMBOL(snd_ctl_new); -EXPORT_SYMBOL(snd_ctl_new1); -EXPORT_SYMBOL(snd_ctl_free_one); -EXPORT_SYMBOL(snd_ctl_add); -EXPORT_SYMBOL(snd_ctl_remove); -EXPORT_SYMBOL(snd_ctl_remove_id); -EXPORT_SYMBOL(snd_ctl_rename_id); -EXPORT_SYMBOL(snd_ctl_find_numid); -EXPORT_SYMBOL(snd_ctl_find_id); -EXPORT_SYMBOL(snd_ctl_notify); -EXPORT_SYMBOL(snd_ctl_register_ioctl); -EXPORT_SYMBOL(snd_ctl_unregister_ioctl); -#ifdef CONFIG_COMPAT -EXPORT_SYMBOL(snd_ctl_register_ioctl_compat); -EXPORT_SYMBOL(snd_ctl_unregister_ioctl_compat); -#endif -EXPORT_SYMBOL(snd_ctl_elem_read); -EXPORT_SYMBOL(snd_ctl_elem_write); - /* misc.c */ -EXPORT_SYMBOL(release_and_free_resource); -#ifdef CONFIG_SND_VERBOSE_PRINTK -EXPORT_SYMBOL(snd_verbose_printk); -#endif -#if defined(CONFIG_SND_DEBUG) && defined(CONFIG_SND_VERBOSE_PRINTK) -EXPORT_SYMBOL(snd_verbose_printd); -#endif diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c index 9055c6de958..c18f6a45e4d 100644 --- a/sound/core/sound_oss.c +++ b/sound/core/sound_oss.c @@ -58,6 +58,8 @@ void *snd_lookup_oss_minor_data(unsigned int minor, int type) return private_data; } +EXPORT_SYMBOL(snd_lookup_oss_minor_data); + static int snd_oss_kernel_minor(int type, struct snd_card *card, int dev) { int minor; @@ -158,6 +160,8 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev, return -EBUSY; } +EXPORT_SYMBOL(snd_register_oss_device); + int snd_unregister_oss_device(int type, struct snd_card *card, int dev) { int minor = snd_oss_kernel_minor(type, card, dev); @@ -197,6 +201,8 @@ int snd_unregister_oss_device(int type, struct snd_card *card, int dev) return 0; } +EXPORT_SYMBOL(snd_unregister_oss_device); + /* * INFO PART */ -- cgit v1.2.3 From 91715ed934fb645948ff17b6c20c6f7fd7688a70 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 28 Apr 2006 15:13:39 +0200 Subject: [ALSA] Clean up EXPORT_SYMBOL()s in snd-seq module Move EXPORT_SYMBOL()s to places adjacent to functions/variables. Signed-off-by: Takashi Iwai --- sound/core/seq/seq.c | 22 ---------------------- sound/core/seq/seq_clientmgr.c | 12 ++++++++++++ sound/core/seq/seq_lock.c | 2 ++ sound/core/seq/seq_memory.c | 3 +++ sound/core/seq/seq_ports.c | 3 +++ 5 files changed, 20 insertions(+), 22 deletions(-) diff --git a/sound/core/seq/seq.c b/sound/core/seq/seq.c index 20f954bc7aa..2f0d8773ac6 100644 --- a/sound/core/seq/seq.c +++ b/sound/core/seq/seq.c @@ -129,25 +129,3 @@ static void __exit alsa_seq_exit(void) module_init(alsa_seq_init) module_exit(alsa_seq_exit) - - /* seq_clientmgr.c */ -EXPORT_SYMBOL(snd_seq_create_kernel_client); -EXPORT_SYMBOL(snd_seq_delete_kernel_client); -EXPORT_SYMBOL(snd_seq_kernel_client_enqueue); -EXPORT_SYMBOL(snd_seq_kernel_client_enqueue_blocking); -EXPORT_SYMBOL(snd_seq_kernel_client_dispatch); -EXPORT_SYMBOL(snd_seq_kernel_client_ctl); -EXPORT_SYMBOL(snd_seq_kernel_client_write_poll); -EXPORT_SYMBOL(snd_seq_set_queue_tempo); - /* seq_memory.c */ -EXPORT_SYMBOL(snd_seq_expand_var_event); -EXPORT_SYMBOL(snd_seq_dump_var_event); - /* seq_ports.c */ -EXPORT_SYMBOL(snd_seq_event_port_attach); -EXPORT_SYMBOL(snd_seq_event_port_detach); - /* seq_lock.c */ -#if defined(CONFIG_SMP) || defined(CONFIG_SND_DEBUG) -/*EXPORT_SYMBOL(snd_seq_sleep_in_lock);*/ -/*EXPORT_SYMBOL(snd_seq_sleep_timeout_in_lock);*/ -EXPORT_SYMBOL(snd_use_lock_sync_helper); -#endif diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index bb15d9ee884..532a660df51 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -1714,6 +1714,8 @@ int snd_seq_set_queue_tempo(int client, struct snd_seq_queue_tempo *tempo) return snd_seq_queue_timer_set_tempo(tempo->queue, client, tempo); } +EXPORT_SYMBOL(snd_seq_set_queue_tempo); + static int snd_seq_ioctl_set_queue_tempo(struct snd_seq_client *client, void __user *arg) { @@ -2264,6 +2266,8 @@ int snd_seq_create_kernel_client(struct snd_card *card, int client_index, return client->number; } +EXPORT_SYMBOL(snd_seq_create_kernel_client); + /* exported to kernel modules */ int snd_seq_delete_kernel_client(int client) { @@ -2280,6 +2284,7 @@ int snd_seq_delete_kernel_client(int client) return 0; } +EXPORT_SYMBOL(snd_seq_delete_kernel_client); /* skeleton to enqueue event, called from snd_seq_kernel_client_enqueue * and snd_seq_kernel_client_enqueue_blocking @@ -2328,6 +2333,8 @@ int snd_seq_kernel_client_enqueue(int client, struct snd_seq_event * ev, return kernel_client_enqueue(client, ev, NULL, 0, atomic, hop); } +EXPORT_SYMBOL(snd_seq_kernel_client_enqueue); + /* * exported, called by kernel clients to enqueue events (with blocking) * @@ -2340,6 +2347,7 @@ int snd_seq_kernel_client_enqueue_blocking(int client, struct snd_seq_event * ev return kernel_client_enqueue(client, ev, file, 1, atomic, hop); } +EXPORT_SYMBOL(snd_seq_kernel_client_enqueue_blocking); /* * exported, called by kernel clients to dispatch events directly to other @@ -2376,6 +2384,7 @@ int snd_seq_kernel_client_dispatch(int client, struct snd_seq_event * ev, return result; } +EXPORT_SYMBOL(snd_seq_kernel_client_dispatch); /* * exported, called by kernel clients to perform same functions as with @@ -2396,6 +2405,7 @@ int snd_seq_kernel_client_ctl(int clientid, unsigned int cmd, void *arg) return result; } +EXPORT_SYMBOL(snd_seq_kernel_client_ctl); /* exported (for OSS emulator) */ int snd_seq_kernel_client_write_poll(int clientid, struct file *file, poll_table *wait) @@ -2413,6 +2423,8 @@ int snd_seq_kernel_client_write_poll(int clientid, struct file *file, poll_table return 0; } +EXPORT_SYMBOL(snd_seq_kernel_client_write_poll); + /*---------------------------------------------------------------------------*/ #ifdef CONFIG_PROC_FS diff --git a/sound/core/seq/seq_lock.c b/sound/core/seq/seq_lock.c index a837a94b2d2..1a34941d421 100644 --- a/sound/core/seq/seq_lock.c +++ b/sound/core/seq/seq_lock.c @@ -44,4 +44,6 @@ void snd_use_lock_sync_helper(snd_use_lock_t *lockp, const char *file, int line) } } +EXPORT_SYMBOL(snd_use_lock_sync_helper); + #endif diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c index 40b4f679c80..4bffe509f71 100644 --- a/sound/core/seq/seq_memory.c +++ b/sound/core/seq/seq_memory.c @@ -118,6 +118,8 @@ int snd_seq_dump_var_event(const struct snd_seq_event *event, return 0; } +EXPORT_SYMBOL(snd_seq_dump_var_event); + /* * exported: @@ -167,6 +169,7 @@ int snd_seq_expand_var_event(const struct snd_seq_event *event, int count, char return err < 0 ? err : newlen; } +EXPORT_SYMBOL(snd_seq_expand_var_event); /* * release this cell, free extended data if available diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c index 41e078c938c..5f46ee9e217 100644 --- a/sound/core/seq/seq_ports.c +++ b/sound/core/seq/seq_ports.c @@ -677,6 +677,7 @@ int snd_seq_event_port_attach(int client, return ret; } +EXPORT_SYMBOL(snd_seq_event_port_attach); /* * Detach the driver from a port. @@ -696,3 +697,5 @@ int snd_seq_event_port_detach(int client, int port) return err; } + +EXPORT_SYMBOL(snd_seq_event_port_detach); -- cgit v1.2.3 From 7b09679c431ba91551a90203f7e7dadbb4c26d1b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 28 Apr 2006 15:13:39 +0200 Subject: [ALSA] ac97 - Move EXPORT_SYMBOL() to adjacent to each function Move EXPORT_SYMBOL() to adjacent to each exported function/variable. Signed-off-by: Takashi Iwai --- sound/pci/ac97/ac97_codec.c | 40 ++++++++++++++++++---------------------- sound/pci/ac97/ac97_pcm.c | 10 ++++++++++ 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index 6c1937ff0d5..72e33b9532f 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -253,6 +253,8 @@ void snd_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short va ac97->bus->ops->write(ac97, reg, value); } +EXPORT_SYMBOL(snd_ac97_write); + /** * snd_ac97_read - read a value from the given register * @@ -281,6 +283,8 @@ static inline unsigned short snd_ac97_read_cache(struct snd_ac97 *ac97, unsigned return ac97->regs[reg]; } +EXPORT_SYMBOL(snd_ac97_read); + /** * snd_ac97_write_cache - write a value on the given register and update the cache * @ac97: the ac97 instance @@ -302,6 +306,8 @@ void snd_ac97_write_cache(struct snd_ac97 *ac97, unsigned short reg, unsigned sh mutex_unlock(&ac97->reg_mutex); } +EXPORT_SYMBOL(snd_ac97_write_cache); + /** * snd_ac97_update - update the value on the given register * @ac97: the ac97 instance @@ -331,6 +337,8 @@ int snd_ac97_update(struct snd_ac97 *ac97, unsigned short reg, unsigned short va return change; } +EXPORT_SYMBOL(snd_ac97_update); + /** * snd_ac97_update_bits - update the bits on the given register * @ac97: the ac97 instance @@ -356,6 +364,8 @@ int snd_ac97_update_bits(struct snd_ac97 *ac97, unsigned short reg, unsigned sho return change; } +EXPORT_SYMBOL(snd_ac97_update_bits); + /* no lock version - see snd_ac97_updat_bits() */ int snd_ac97_update_bits_nolock(struct snd_ac97 *ac97, unsigned short reg, unsigned short mask, unsigned short value) @@ -1682,6 +1692,7 @@ const char *snd_ac97_get_short_name(struct snd_ac97 *ac97) return "unknown codec"; } +EXPORT_SYMBOL(snd_ac97_get_short_name); /* wait for a while until registers are accessible after RESET * return 0 if ok, negative not ready @@ -1774,6 +1785,8 @@ int snd_ac97_bus(struct snd_card *card, int num, struct snd_ac97_bus_ops *ops, return 0; } +EXPORT_SYMBOL(snd_ac97_bus); + /* stop no dev release warning */ static void ac97_device_release(struct device * dev) { @@ -2117,6 +2130,7 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, return 0; } +EXPORT_SYMBOL(snd_ac97_mixer); /* * Power down the chip. @@ -2166,6 +2180,8 @@ void snd_ac97_suspend(struct snd_ac97 *ac97) snd_ac97_powerdown(ac97); } +EXPORT_SYMBOL(snd_ac97_suspend); + /* * restore ac97 status */ @@ -2267,6 +2283,8 @@ __reset_ready: snd_ac97_restore_iec958(ac97); } } + +EXPORT_SYMBOL(snd_ac97_resume); #endif @@ -2590,29 +2608,7 @@ int snd_ac97_tune_hardware(struct snd_ac97 *ac97, struct ac97_quirk *quirk, cons return 0; } - -/* - * Exported symbols - */ - -EXPORT_SYMBOL(snd_ac97_write); -EXPORT_SYMBOL(snd_ac97_read); -EXPORT_SYMBOL(snd_ac97_write_cache); -EXPORT_SYMBOL(snd_ac97_update); -EXPORT_SYMBOL(snd_ac97_update_bits); -EXPORT_SYMBOL(snd_ac97_get_short_name); -EXPORT_SYMBOL(snd_ac97_bus); -EXPORT_SYMBOL(snd_ac97_mixer); -EXPORT_SYMBOL(snd_ac97_pcm_assign); -EXPORT_SYMBOL(snd_ac97_pcm_open); -EXPORT_SYMBOL(snd_ac97_pcm_close); -EXPORT_SYMBOL(snd_ac97_pcm_double_rate_rules); EXPORT_SYMBOL(snd_ac97_tune_hardware); -EXPORT_SYMBOL(snd_ac97_set_rate); -#ifdef CONFIG_PM -EXPORT_SYMBOL(snd_ac97_resume); -EXPORT_SYMBOL(snd_ac97_suspend); -#endif /* * INIT part diff --git a/sound/pci/ac97/ac97_pcm.c b/sound/pci/ac97/ac97_pcm.c index 512a3583b0c..f684aa2c006 100644 --- a/sound/pci/ac97/ac97_pcm.c +++ b/sound/pci/ac97/ac97_pcm.c @@ -317,6 +317,8 @@ int snd_ac97_set_rate(struct snd_ac97 *ac97, int reg, unsigned int rate) return 0; } +EXPORT_SYMBOL(snd_ac97_set_rate); + static unsigned short get_pslots(struct snd_ac97 *ac97, unsigned char *rate_table, unsigned short *spdif_slots) { if (!ac97_is_audio(ac97)) @@ -550,6 +552,8 @@ int snd_ac97_pcm_assign(struct snd_ac97_bus *bus, return 0; } +EXPORT_SYMBOL(snd_ac97_pcm_assign); + /** * snd_ac97_pcm_open - opens the given AC97 pcm * @pcm: the ac97 pcm instance @@ -633,6 +637,8 @@ int snd_ac97_pcm_open(struct ac97_pcm *pcm, unsigned int rate, return err; } +EXPORT_SYMBOL(snd_ac97_pcm_open); + /** * snd_ac97_pcm_close - closes the given AC97 pcm * @pcm: the ac97 pcm instance @@ -658,6 +664,8 @@ int snd_ac97_pcm_close(struct ac97_pcm *pcm) return 0; } +EXPORT_SYMBOL(snd_ac97_pcm_close); + static int double_rate_hw_constraint_rate(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) { @@ -709,3 +717,5 @@ int snd_ac97_pcm_double_rate_rules(struct snd_pcm_runtime *runtime) SNDRV_PCM_HW_PARAM_RATE, -1); return err; } + +EXPORT_SYMBOL(snd_ac97_pcm_double_rate_rules); -- cgit v1.2.3 From ac19e19b3664feda8040fb9fb7885183a9eb7a80 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 28 Apr 2006 15:13:39 +0200 Subject: [ALSA] opl3 - Move EXPORT_SYMBOL() to adjacent to each function Move EXPORT_SYMBOL() to adjacent to each exported function/variable. Signed-off-by: Takashi Iwai --- sound/drivers/opl3/opl3_lib.c | 19 ++++++++++--------- sound/drivers/opl3/opl3_synth.c | 4 ++++ 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/sound/drivers/opl3/opl3_lib.c b/sound/drivers/opl3/opl3_lib.c index 4f855697677..87fe376f38f 100644 --- a/sound/drivers/opl3/opl3_lib.c +++ b/sound/drivers/opl3/opl3_lib.c @@ -316,6 +316,8 @@ void snd_opl3_interrupt(struct snd_hwdep * hw) } } +EXPORT_SYMBOL(snd_opl3_interrupt); + /* */ @@ -369,6 +371,8 @@ int snd_opl3_new(struct snd_card *card, return 0; } +EXPORT_SYMBOL(snd_opl3_new); + int snd_opl3_init(struct snd_opl3 *opl3) { if (! opl3->command) { @@ -393,6 +397,8 @@ int snd_opl3_init(struct snd_opl3 *opl3) return 0; } +EXPORT_SYMBOL(snd_opl3_init); + int snd_opl3_create(struct snd_card *card, unsigned long l_port, unsigned long r_port, @@ -451,6 +457,8 @@ int snd_opl3_create(struct snd_card *card, return 0; } +EXPORT_SYMBOL(snd_opl3_create); + int snd_opl3_timer_new(struct snd_opl3 * opl3, int timer1_dev, int timer2_dev) { int err; @@ -468,6 +476,8 @@ int snd_opl3_timer_new(struct snd_opl3 * opl3, int timer1_dev, int timer2_dev) return 0; } +EXPORT_SYMBOL(snd_opl3_timer_new); + int snd_opl3_hwdep_new(struct snd_opl3 * opl3, int device, int seq_device, struct snd_hwdep ** rhwdep) @@ -526,17 +536,8 @@ int snd_opl3_hwdep_new(struct snd_opl3 * opl3, return 0; } -EXPORT_SYMBOL(snd_opl3_interrupt); -EXPORT_SYMBOL(snd_opl3_new); -EXPORT_SYMBOL(snd_opl3_init); -EXPORT_SYMBOL(snd_opl3_create); -EXPORT_SYMBOL(snd_opl3_timer_new); EXPORT_SYMBOL(snd_opl3_hwdep_new); -/* opl3_synth.c */ -EXPORT_SYMBOL(snd_opl3_regmap); -EXPORT_SYMBOL(snd_opl3_reset); - /* * INIT part */ diff --git a/sound/drivers/opl3/opl3_synth.c b/sound/drivers/opl3/opl3_synth.c index 6db503f025b..a4b3543a711 100644 --- a/sound/drivers/opl3/opl3_synth.c +++ b/sound/drivers/opl3/opl3_synth.c @@ -58,6 +58,8 @@ char snd_opl3_regmap[MAX_OPL2_VOICES][4] = { 0x12, 0x15, 0x00, 0x00 } /* is selected (only left reg block) */ }; +EXPORT_SYMBOL(snd_opl3_regmap); + /* * prototypes */ @@ -228,6 +230,7 @@ void snd_opl3_reset(struct snd_opl3 * opl3) opl3->rhythm = 0; } +EXPORT_SYMBOL(snd_opl3_reset); static int snd_opl3_play_note(struct snd_opl3 * opl3, struct snd_dm_fm_note * note) { @@ -445,3 +448,4 @@ static int snd_opl3_set_connection(struct snd_opl3 * opl3, int connection) return 0; } + -- cgit v1.2.3 From 4181e5fe4b27b0a049402a359a4a5d8b80308528 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 28 Apr 2006 15:13:39 +0200 Subject: [ALSA] opl4 - Move EXPORT_SYMBOL() to adjacent to each function Move EXPORT_SYMBOL() to adjacent to each exported function/variable. Signed-off-by: Takashi Iwai --- sound/drivers/opl4/opl4_lib.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/sound/drivers/opl4/opl4_lib.c b/sound/drivers/opl4/opl4_lib.c index 4bc860ae02d..01997f24c89 100644 --- a/sound/drivers/opl4/opl4_lib.c +++ b/sound/drivers/opl4/opl4_lib.c @@ -43,6 +43,8 @@ void snd_opl4_write(struct snd_opl4 *opl4, u8 reg, u8 value) outb(value, opl4->pcm_port + 1); } +EXPORT_SYMBOL(snd_opl4_write); + u8 snd_opl4_read(struct snd_opl4 *opl4, u8 reg) { snd_opl4_wait(opl4); @@ -52,6 +54,8 @@ u8 snd_opl4_read(struct snd_opl4 *opl4, u8 reg) return inb(opl4->pcm_port + 1); } +EXPORT_SYMBOL(snd_opl4_read); + void snd_opl4_read_memory(struct snd_opl4 *opl4, char *buf, int offset, int size) { unsigned long flags; @@ -76,6 +80,8 @@ void snd_opl4_read_memory(struct snd_opl4 *opl4, char *buf, int offset, int size spin_unlock_irqrestore(&opl4->reg_lock, flags); } +EXPORT_SYMBOL(snd_opl4_read_memory); + void snd_opl4_write_memory(struct snd_opl4 *opl4, const char *buf, int offset, int size) { unsigned long flags; @@ -100,6 +106,8 @@ void snd_opl4_write_memory(struct snd_opl4 *opl4, const char *buf, int offset, i spin_unlock_irqrestore(&opl4->reg_lock, flags); } +EXPORT_SYMBOL(snd_opl4_write_memory); + static void snd_opl4_enable_opl4(struct snd_opl4 *opl4) { outb(OPL3_REG_MODE, opl4->fm_port + 2); @@ -256,10 +264,6 @@ int snd_opl4_create(struct snd_card *card, return 0; } -EXPORT_SYMBOL(snd_opl4_write); -EXPORT_SYMBOL(snd_opl4_read); -EXPORT_SYMBOL(snd_opl4_write_memory); -EXPORT_SYMBOL(snd_opl4_read_memory); EXPORT_SYMBOL(snd_opl4_create); static int __init alsa_opl4_init(void) -- cgit v1.2.3 From 2dd31deeeb238a4f40c9fc9e219dc210fcbf8765 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 28 Apr 2006 15:13:39 +0200 Subject: [ALSA] emu10k1 - Move EXPORT_SYMBOL() to adjacent to each function Move EXPORT_SYMBOL() to adjacent to each exported function/variable. Signed-off-by: Takashi Iwai --- sound/pci/emu10k1/emu10k1_main.c | 13 ------------- sound/pci/emu10k1/io.c | 4 ++++ sound/pci/emu10k1/memory.c | 8 ++++++++ sound/pci/emu10k1/voice.c | 4 ++++ 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index e71485c23cc..42a358f989c 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c @@ -1459,16 +1459,3 @@ void snd_emu10k1_resume_regs(struct snd_emu10k1 *emu) } } #endif - -/* memory.c */ -EXPORT_SYMBOL(snd_emu10k1_synth_alloc); -EXPORT_SYMBOL(snd_emu10k1_synth_free); -EXPORT_SYMBOL(snd_emu10k1_synth_bzero); -EXPORT_SYMBOL(snd_emu10k1_synth_copy_from_user); -EXPORT_SYMBOL(snd_emu10k1_memblk_map); -/* voice.c */ -EXPORT_SYMBOL(snd_emu10k1_voice_alloc); -EXPORT_SYMBOL(snd_emu10k1_voice_free); -/* io.c */ -EXPORT_SYMBOL(snd_emu10k1_ptr_read); -EXPORT_SYMBOL(snd_emu10k1_ptr_write); diff --git a/sound/pci/emu10k1/io.c b/sound/pci/emu10k1/io.c index ef5304df8c1..029e7856c43 100644 --- a/sound/pci/emu10k1/io.c +++ b/sound/pci/emu10k1/io.c @@ -62,6 +62,8 @@ unsigned int snd_emu10k1_ptr_read(struct snd_emu10k1 * emu, unsigned int reg, un } } +EXPORT_SYMBOL(snd_emu10k1_ptr_read); + void snd_emu10k1_ptr_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned int chn, unsigned int data) { unsigned int regptr; @@ -92,6 +94,8 @@ void snd_emu10k1_ptr_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned i } } +EXPORT_SYMBOL(snd_emu10k1_ptr_write); + unsigned int snd_emu10k1_ptr20_read(struct snd_emu10k1 * emu, unsigned int reg, unsigned int chn) diff --git a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c index e7ec98649f0..4fcaefe5a3c 100644 --- a/sound/pci/emu10k1/memory.c +++ b/sound/pci/emu10k1/memory.c @@ -287,6 +287,8 @@ int snd_emu10k1_memblk_map(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *b return err; } +EXPORT_SYMBOL(snd_emu10k1_memblk_map); + /* * page allocation for DMA */ @@ -387,6 +389,7 @@ snd_emu10k1_synth_alloc(struct snd_emu10k1 *hw, unsigned int size) return (struct snd_util_memblk *)blk; } +EXPORT_SYMBOL(snd_emu10k1_synth_alloc); /* * free a synth sample area @@ -409,6 +412,7 @@ snd_emu10k1_synth_free(struct snd_emu10k1 *emu, struct snd_util_memblk *memblk) return 0; } +EXPORT_SYMBOL(snd_emu10k1_synth_free); /* check new allocation range */ static void get_single_page_range(struct snd_util_memhdr *hdr, @@ -540,6 +544,8 @@ int snd_emu10k1_synth_bzero(struct snd_emu10k1 *emu, struct snd_util_memblk *blk return 0; } +EXPORT_SYMBOL(snd_emu10k1_synth_bzero); + /* * copy_from_user(blk + offset, data, size) */ @@ -568,3 +574,5 @@ int snd_emu10k1_synth_copy_from_user(struct snd_emu10k1 *emu, struct snd_util_me } while (offset < end_offset); return 0; } + +EXPORT_SYMBOL(snd_emu10k1_synth_copy_from_user); diff --git a/sound/pci/emu10k1/voice.c b/sound/pci/emu10k1/voice.c index 56ffb7dc3ee..94eca82dd4f 100644 --- a/sound/pci/emu10k1/voice.c +++ b/sound/pci/emu10k1/voice.c @@ -139,6 +139,8 @@ int snd_emu10k1_voice_alloc(struct snd_emu10k1 *emu, int type, int number, return result; } +EXPORT_SYMBOL(snd_emu10k1_voice_alloc); + int snd_emu10k1_voice_free(struct snd_emu10k1 *emu, struct snd_emu10k1_voice *pvoice) { @@ -153,3 +155,5 @@ int snd_emu10k1_voice_free(struct snd_emu10k1 *emu, spin_unlock_irqrestore(&emu->voice_lock, flags); return 0; } + +EXPORT_SYMBOL(snd_emu10k1_voice_free); -- cgit v1.2.3 From cbef55f3d8e4e7efef4703c82302a0021d781483 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 28 Apr 2006 15:13:40 +0200 Subject: [ALSA] trident - Move EXPORT_SYMBOL() to adjacent to each function Move EXPORT_SYMBOL() to adjacent to each exported function/variable. Signed-off-by: Takashi Iwai --- sound/pci/trident/trident_main.c | 20 ++++++++++---------- sound/pci/trident/trident_memory.c | 3 +++ 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c index 52178b8ad49..850579208e4 100644 --- a/sound/pci/trident/trident_main.c +++ b/sound/pci/trident/trident_main.c @@ -306,6 +306,8 @@ void snd_trident_start_voice(struct snd_trident * trident, unsigned int voice) outl(mask, TRID_REG(trident, reg)); } +EXPORT_SYMBOL(snd_trident_start_voice); + /*--------------------------------------------------------------------------- void snd_trident_stop_voice(struct snd_trident * trident, unsigned int voice) @@ -328,6 +330,8 @@ void snd_trident_stop_voice(struct snd_trident * trident, unsigned int voice) outl(mask, TRID_REG(trident, reg)); } +EXPORT_SYMBOL(snd_trident_stop_voice); + /*--------------------------------------------------------------------------- int snd_trident_allocate_pcm_channel(struct snd_trident *trident) @@ -502,6 +506,8 @@ void snd_trident_write_voice_regs(struct snd_trident * trident, #endif } +EXPORT_SYMBOL(snd_trident_write_voice_regs); + /*--------------------------------------------------------------------------- snd_trident_write_cso_reg @@ -3884,6 +3890,8 @@ struct snd_trident_voice *snd_trident_alloc_voice(struct snd_trident * trident, return NULL; } +EXPORT_SYMBOL(snd_trident_alloc_voice); + void snd_trident_free_voice(struct snd_trident * trident, struct snd_trident_voice *voice) { unsigned long flags; @@ -3912,6 +3920,8 @@ void snd_trident_free_voice(struct snd_trident * trident, struct snd_trident_voi private_free(voice); } +EXPORT_SYMBOL(snd_trident_free_voice); + static void snd_trident_clear_voices(struct snd_trident * trident, unsigned short v_min, unsigned short v_max) { unsigned int i, val, mask[2] = { 0, 0 }; @@ -3993,13 +4003,3 @@ int snd_trident_resume(struct pci_dev *pci) return 0; } #endif /* CONFIG_PM */ - -EXPORT_SYMBOL(snd_trident_alloc_voice); -EXPORT_SYMBOL(snd_trident_free_voice); -EXPORT_SYMBOL(snd_trident_start_voice); -EXPORT_SYMBOL(snd_trident_stop_voice); -EXPORT_SYMBOL(snd_trident_write_voice_regs); -/* trident_memory.c symbols */ -EXPORT_SYMBOL(snd_trident_synth_alloc); -EXPORT_SYMBOL(snd_trident_synth_free); -EXPORT_SYMBOL(snd_trident_synth_copy_from_user); diff --git a/sound/pci/trident/trident_memory.c b/sound/pci/trident/trident_memory.c index 46c6982c9e8..aff3f874131 100644 --- a/sound/pci/trident/trident_memory.c +++ b/sound/pci/trident/trident_memory.c @@ -349,6 +349,7 @@ snd_trident_synth_alloc(struct snd_trident *hw, unsigned int size) return blk; } +EXPORT_SYMBOL(snd_trident_synth_alloc); /* * free a synth sample area @@ -365,6 +366,7 @@ snd_trident_synth_free(struct snd_trident *hw, struct snd_util_memblk *blk) return 0; } +EXPORT_SYMBOL(snd_trident_synth_free); /* * reset TLB entry and free kernel page @@ -486,3 +488,4 @@ int snd_trident_synth_copy_from_user(struct snd_trident *trident, return 0; } +EXPORT_SYMBOL(snd_trident_synth_copy_from_user); -- cgit v1.2.3 From 95ff17564b6db34cad0cd67678fb79174e77531e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 28 Apr 2006 15:13:40 +0200 Subject: [ALSA] emux - Move EXPORT_SYMBOL() to adjacent to each function Move EXPORT_SYMBOL() to adjacent to each exported function/variable. Signed-off-by: Takashi Iwai --- sound/synth/emux/emux.c | 12 ++---------- sound/synth/emux/emux_synth.c | 5 +++++ sound/synth/emux/soundfont.c | 4 +++- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/sound/synth/emux/emux.c b/sound/synth/emux/emux.c index fc733bbf448..573e3701c14 100644 --- a/sound/synth/emux/emux.c +++ b/sound/synth/emux/emux.c @@ -63,6 +63,7 @@ int snd_emux_new(struct snd_emux **remu) return 0; } +EXPORT_SYMBOL(snd_emux_new); /* */ @@ -136,6 +137,7 @@ int snd_emux_register(struct snd_emux *emu, struct snd_card *card, int index, ch return 0; } +EXPORT_SYMBOL(snd_emux_register); /* */ @@ -171,18 +173,8 @@ int snd_emux_free(struct snd_emux *emu) return 0; } - -EXPORT_SYMBOL(snd_emux_new); -EXPORT_SYMBOL(snd_emux_register); EXPORT_SYMBOL(snd_emux_free); -EXPORT_SYMBOL(snd_emux_terminate_all); -EXPORT_SYMBOL(snd_emux_lock_voice); -EXPORT_SYMBOL(snd_emux_unlock_voice); - -/* soundfont.c */ -EXPORT_SYMBOL(snd_sf_linear_to_log); - /* * INIT part diff --git a/sound/synth/emux/emux_synth.c b/sound/synth/emux/emux_synth.c index 24705d15ebd..3733118d39b 100644 --- a/sound/synth/emux/emux_synth.c +++ b/sound/synth/emux/emux_synth.c @@ -434,6 +434,7 @@ snd_emux_terminate_all(struct snd_emux *emu) spin_unlock_irqrestore(&emu->voice_lock, flags); } +EXPORT_SYMBOL(snd_emux_terminate_all); /* * Terminate all voices associated with the given port @@ -951,6 +952,8 @@ void snd_emux_lock_voice(struct snd_emux *emu, int voice) spin_unlock_irqrestore(&emu->voice_lock, flags); } +EXPORT_SYMBOL(snd_emux_lock_voice); + /* */ void snd_emux_unlock_voice(struct snd_emux *emu, int voice) @@ -965,3 +968,5 @@ void snd_emux_unlock_voice(struct snd_emux *emu, int voice) voice, emu->voices[voice].state); spin_unlock_irqrestore(&emu->voice_lock, flags); } + +EXPORT_SYMBOL(snd_emux_unlock_voice); diff --git a/sound/synth/emux/soundfont.c b/sound/synth/emux/soundfont.c index 32c27162dfb..7f0bdea0dfd 100644 --- a/sound/synth/emux/soundfont.c +++ b/sound/synth/emux/soundfont.c @@ -810,6 +810,9 @@ snd_sf_linear_to_log(unsigned int amount, int offset, int ratio) return v; } +EXPORT_SYMBOL(snd_sf_linear_to_log); + + #define OFFSET_MSEC 653117 /* base = 1000 */ #define OFFSET_ABSCENT 851781 /* base = 8176 */ #define OFFSET_SAMPLERATE 1011119 /* base = 44100 */ @@ -1485,4 +1488,3 @@ snd_soundfont_remove_unlocked(struct snd_sf_list *sflist) unlock_preset(sflist); return 0; } - -- cgit v1.2.3 From fa325eb3afc3cdaf7fba6ee3eaf05b243f5614a3 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 28 Apr 2006 15:13:40 +0200 Subject: [ALSA] vx - Move EXPORT_SYMBOL() to adjacent to each function Move EXPORT_SYMBOL() to adjacent to each exported function/variable. Signed-off-by: Takashi Iwai --- sound/drivers/vx/vx_core.c | 30 ++++++++++++++---------------- sound/drivers/vx/vx_hwdep.c | 3 +++ 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c index fa4a2b5c2d8..e1c3dda1577 100644 --- a/sound/drivers/vx/vx_core.c +++ b/sound/drivers/vx/vx_core.c @@ -70,6 +70,8 @@ int snd_vx_check_reg_bit(struct vx_core *chip, int reg, int mask, int bit, int t return -EIO; } +EXPORT_SYMBOL(snd_vx_check_reg_bit); + /* * vx_send_irq_dsp - set command irq bit * @num: the requested IRQ type, IRQ_XXX @@ -465,6 +467,8 @@ int snd_vx_load_boot_image(struct vx_core *chip, const struct firmware *boot) return 0; } +EXPORT_SYMBOL(snd_vx_load_boot_image); + /* * vx_test_irq_src - query the source of interrupts * @@ -545,6 +549,7 @@ irqreturn_t snd_vx_irq_handler(int irq, void *dev, struct pt_regs *regs) return IRQ_HANDLED; } +EXPORT_SYMBOL(snd_vx_irq_handler); /* */ @@ -657,6 +662,8 @@ int snd_vx_dsp_boot(struct vx_core *chip, const struct firmware *boot) return 0; } +EXPORT_SYMBOL(snd_vx_dsp_boot); + /** * snd_vx_dsp_load - load the DSP image */ @@ -705,6 +712,8 @@ int snd_vx_dsp_load(struct vx_core *chip, const struct firmware *dsp) return 0; } +EXPORT_SYMBOL(snd_vx_dsp_load); + #ifdef CONFIG_PM /* * suspend @@ -721,6 +730,8 @@ int snd_vx_suspend(struct vx_core *chip, pm_message_t state) return 0; } +EXPORT_SYMBOL(snd_vx_suspend); + /* * resume */ @@ -747,6 +758,7 @@ int snd_vx_resume(struct vx_core *chip) return 0; } +EXPORT_SYMBOL(snd_vx_resume); #endif /** @@ -790,6 +802,8 @@ struct vx_core *snd_vx_create(struct snd_card *card, struct snd_vx_hardware *hw, return chip; } +EXPORT_SYMBOL(snd_vx_create); + /* * module entries */ @@ -804,19 +818,3 @@ static void __exit alsa_vx_core_exit(void) module_init(alsa_vx_core_init) module_exit(alsa_vx_core_exit) - -/* - * exports - */ -EXPORT_SYMBOL(snd_vx_check_reg_bit); -EXPORT_SYMBOL(snd_vx_create); -EXPORT_SYMBOL(snd_vx_setup_firmware); -EXPORT_SYMBOL(snd_vx_free_firmware); -EXPORT_SYMBOL(snd_vx_irq_handler); -EXPORT_SYMBOL(snd_vx_dsp_boot); -EXPORT_SYMBOL(snd_vx_dsp_load); -EXPORT_SYMBOL(snd_vx_load_boot_image); -#ifdef CONFIG_PM -EXPORT_SYMBOL(snd_vx_suspend); -EXPORT_SYMBOL(snd_vx_resume); -#endif diff --git a/sound/drivers/vx/vx_hwdep.c b/sound/drivers/vx/vx_hwdep.c index d837783fb53..e1920af4501 100644 --- a/sound/drivers/vx/vx_hwdep.c +++ b/sound/drivers/vx/vx_hwdep.c @@ -250,3 +250,6 @@ void snd_vx_free_firmware(struct vx_core *chip) } #endif /* SND_VX_FW_LOADER */ + +EXPORT_SYMBOL(snd_vx_setup_firmware); +EXPORT_SYMBOL(snd_vx_free_firmware); -- cgit v1.2.3 From 57c65c116e1c03c54ac7c4bf38f2b4086d2c1a17 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 28 Apr 2006 15:13:40 +0200 Subject: [ALSA] i2c - Move EXPORT_SYMBOL() to adjacent to each function Move EXPORT_SYMBOL() to adjacent to each exported function/variable. Signed-off-by: Takashi Iwai --- sound/i2c/i2c.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/sound/i2c/i2c.c b/sound/i2c/i2c.c index edfe76fb007..b60fb189282 100644 --- a/sound/i2c/i2c.c +++ b/sound/i2c/i2c.c @@ -106,6 +106,8 @@ int snd_i2c_bus_create(struct snd_card *card, const char *name, return 0; } +EXPORT_SYMBOL(snd_i2c_bus_create); + int snd_i2c_device_create(struct snd_i2c_bus *bus, const char *name, unsigned char addr, struct snd_i2c_device **rdevice) { @@ -124,6 +126,8 @@ int snd_i2c_device_create(struct snd_i2c_bus *bus, const char *name, return 0; } +EXPORT_SYMBOL(snd_i2c_device_create); + int snd_i2c_device_free(struct snd_i2c_device *device) { if (device->bus) @@ -134,22 +138,29 @@ int snd_i2c_device_free(struct snd_i2c_device *device) return 0; } +EXPORT_SYMBOL(snd_i2c_device_free); + int snd_i2c_sendbytes(struct snd_i2c_device *device, unsigned char *bytes, int count) { return device->bus->ops->sendbytes(device, bytes, count); } +EXPORT_SYMBOL(snd_i2c_sendbytes); int snd_i2c_readbytes(struct snd_i2c_device *device, unsigned char *bytes, int count) { return device->bus->ops->readbytes(device, bytes, count); } +EXPORT_SYMBOL(snd_i2c_readbytes); + int snd_i2c_probeaddr(struct snd_i2c_bus *bus, unsigned short addr) { return bus->ops->probeaddr(bus, addr); } +EXPORT_SYMBOL(snd_i2c_probeaddr); + /* * bit-operations */ @@ -320,12 +331,6 @@ static int snd_i2c_bit_probeaddr(struct snd_i2c_bus *bus, unsigned short addr) return err; } -EXPORT_SYMBOL(snd_i2c_bus_create); -EXPORT_SYMBOL(snd_i2c_device_create); -EXPORT_SYMBOL(snd_i2c_device_free); -EXPORT_SYMBOL(snd_i2c_sendbytes); -EXPORT_SYMBOL(snd_i2c_readbytes); -EXPORT_SYMBOL(snd_i2c_probeaddr); static int __init alsa_i2c_init(void) { -- cgit v1.2.3 From e5e8a1d4618595ea406336da3cdbd0c6eb6f260d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 28 Apr 2006 15:13:40 +0200 Subject: [ALSA] hda-codec - Move EXPORT_SYMBOL() to adjacent to each function Move EXPORT_SYMBOL() to adjacent to each exported function/variable. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 5bee3b53647..8c2a8174ece 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -86,6 +86,8 @@ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, int dire return res; } +EXPORT_SYMBOL(snd_hda_codec_read); + /** * snd_hda_codec_write - send a single command without waiting for response * @codec: the HDA codec @@ -108,6 +110,8 @@ int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct, return err; } +EXPORT_SYMBOL(snd_hda_codec_write); + /** * snd_hda_sequence_write - sequence writes * @codec: the HDA codec @@ -122,6 +126,8 @@ void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq) snd_hda_codec_write(codec, seq->nid, 0, seq->verb, seq->param); } +EXPORT_SYMBOL(snd_hda_sequence_write); + /** * snd_hda_get_sub_nodes - get the range of sub nodes * @codec: the HDA codec @@ -140,6 +146,8 @@ int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid, hda_nid_t *sta return (int)(parm & 0x7fff); } +EXPORT_SYMBOL(snd_hda_get_sub_nodes); + /** * snd_hda_get_connections - get connection list * @codec: the HDA codec @@ -256,6 +264,8 @@ int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex) return 0; } +EXPORT_SYMBOL(snd_hda_queue_unsol_event); + /* * process queueud unsolicited events */ @@ -384,6 +394,7 @@ int snd_hda_bus_new(struct snd_card *card, const struct hda_bus_template *temp, return 0; } +EXPORT_SYMBOL(snd_hda_bus_new); /* * find a matching codec preset @@ -587,6 +598,8 @@ int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, return 0; } +EXPORT_SYMBOL(snd_hda_codec_new); + /** * snd_hda_codec_setup_stream - set up the codec for streaming * @codec: the CODEC to set up @@ -609,6 +622,7 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, u32 stre snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, format); } +EXPORT_SYMBOL(snd_hda_codec_setup_stream); /* * amp access functions @@ -1294,6 +1308,7 @@ int snd_hda_build_controls(struct hda_bus *bus) return 0; } +EXPORT_SYMBOL(snd_hda_build_controls); /* * stream formats @@ -1382,6 +1397,8 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate, return val; } +EXPORT_SYMBOL(snd_hda_calc_stream_format); + /** * snd_hda_query_supported_pcm - query the supported PCM rates and formats * @codec: the HDA codec @@ -1663,6 +1680,7 @@ int snd_hda_build_pcms(struct hda_bus *bus) return 0; } +EXPORT_SYMBOL(snd_hda_build_pcms); /** * snd_hda_check_board_config - compare the current codec with the config table @@ -2165,6 +2183,8 @@ int snd_hda_suspend(struct hda_bus *bus, pm_message_t state) return 0; } +EXPORT_SYMBOL(snd_hda_suspend); + /** * snd_hda_resume - resume the codecs * @bus: the HDA bus @@ -2187,6 +2207,8 @@ int snd_hda_resume(struct hda_bus *bus) return 0; } +EXPORT_SYMBOL(snd_hda_resume); + /** * snd_hda_resume_ctls - resume controls in the new control list * @codec: the HDA codec @@ -2246,25 +2268,6 @@ int snd_hda_resume_spdif_in(struct hda_codec *codec) } #endif -/* - * symbols exported for controller modules - */ -EXPORT_SYMBOL(snd_hda_codec_read); -EXPORT_SYMBOL(snd_hda_codec_write); -EXPORT_SYMBOL(snd_hda_sequence_write); -EXPORT_SYMBOL(snd_hda_get_sub_nodes); -EXPORT_SYMBOL(snd_hda_queue_unsol_event); -EXPORT_SYMBOL(snd_hda_bus_new); -EXPORT_SYMBOL(snd_hda_codec_new); -EXPORT_SYMBOL(snd_hda_codec_setup_stream); -EXPORT_SYMBOL(snd_hda_calc_stream_format); -EXPORT_SYMBOL(snd_hda_build_pcms); -EXPORT_SYMBOL(snd_hda_build_controls); -#ifdef CONFIG_PM -EXPORT_SYMBOL(snd_hda_suspend); -EXPORT_SYMBOL(snd_hda_resume); -#endif - /* * INIT part */ -- cgit v1.2.3 From e88e8ae639a4908b903d9406c54e99a729b01a28 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 28 Apr 2006 15:13:40 +0200 Subject: [ALSA] Move OSS-specific hw_params helper to snd-pcm-oss module Move EXPORT_SYMBOL()s to places adjacent to functions/variables. Also move OSS-specific hw_params helper functions to pcm_oss.c. Signed-off-by: Takashi Iwai --- include/sound/pcm.h | 8 - include/sound/pcm_params.h | 20 +- sound/core/oss/pcm_oss.c | 481 +++++++++++++++++++++++++++++++++ sound/core/pcm.c | 36 +-- sound/core/pcm_lib.c | 649 ++++----------------------------------------- sound/core/pcm_memory.c | 12 + sound/core/pcm_misc.c | 24 ++ sound/core/pcm_native.c | 21 +- 8 files changed, 605 insertions(+), 646 deletions(-) diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 373425895fa..998bacefc8f 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -825,14 +825,6 @@ int snd_interval_ratnum(struct snd_interval *i, void _snd_pcm_hw_params_any(struct snd_pcm_hw_params *params); void _snd_pcm_hw_param_setempty(struct snd_pcm_hw_params *params, snd_pcm_hw_param_t var); -int snd_pcm_hw_param_near(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var, - unsigned int val, int *dir); -int snd_pcm_hw_param_set(struct snd_pcm_substream *pcm, - struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var, - unsigned int val, int dir); int snd_pcm_hw_params_choose(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params); int snd_pcm_hw_refine(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params); diff --git a/include/sound/pcm_params.h b/include/sound/pcm_params.h index e3bebd98e1c..85cf1cf4f31 100644 --- a/include/sound/pcm_params.h +++ b/include/sound/pcm_params.h @@ -22,18 +22,14 @@ * */ -extern int snd_pcm_hw_param_mask(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var, const struct snd_mask *val); -extern unsigned int snd_pcm_hw_param_value_min(const struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var, int *dir); -extern unsigned int snd_pcm_hw_param_value_max(const struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var, int *dir); -extern int _snd_pcm_hw_param_min(struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var, unsigned int val, int dir); -extern int _snd_pcm_hw_param_setinteger(struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var); -extern int _snd_pcm_hw_param_set(struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var, unsigned int val, int dir); +int snd_pcm_hw_param_first(struct snd_pcm_substream *pcm, + struct snd_pcm_hw_params *params, + snd_pcm_hw_param_t var, int *dir); +int snd_pcm_hw_param_last(struct snd_pcm_substream *pcm, + struct snd_pcm_hw_params *params, + snd_pcm_hw_param_t var, int *dir); +int snd_pcm_hw_param_value(const struct snd_pcm_hw_params *params, + snd_pcm_hw_param_t var, int *dir); #define SNDRV_MASK_BITS 64 /* we use so far 64bits only */ #define SNDRV_MASK_SIZE (SNDRV_MASK_BITS / 32) diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index ac990bf0b48..0d2e232afe6 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -78,6 +78,487 @@ static inline void snd_leave_user(mm_segment_t fs) set_fs(fs); } +/* + * helper functions to process hw_params + */ +static int snd_interval_refine_min(struct snd_interval *i, unsigned int min, int openmin) +{ + int changed = 0; + if (i->min < min) { + i->min = min; + i->openmin = openmin; + changed = 1; + } else if (i->min == min && !i->openmin && openmin) { + i->openmin = 1; + changed = 1; + } + if (i->integer) { + if (i->openmin) { + i->min++; + i->openmin = 0; + } + } + if (snd_interval_checkempty(i)) { + snd_interval_none(i); + return -EINVAL; + } + return changed; +} + +static int snd_interval_refine_max(struct snd_interval *i, unsigned int max, int openmax) +{ + int changed = 0; + if (i->max > max) { + i->max = max; + i->openmax = openmax; + changed = 1; + } else if (i->max == max && !i->openmax && openmax) { + i->openmax = 1; + changed = 1; + } + if (i->integer) { + if (i->openmax) { + i->max--; + i->openmax = 0; + } + } + if (snd_interval_checkempty(i)) { + snd_interval_none(i); + return -EINVAL; + } + return changed; +} + +static int snd_interval_refine_set(struct snd_interval *i, unsigned int val) +{ + struct snd_interval t; + t.empty = 0; + t.min = t.max = val; + t.openmin = t.openmax = 0; + t.integer = 1; + return snd_interval_refine(i, &t); +} + +/** + * snd_pcm_hw_param_value_min + * @params: the hw_params instance + * @var: parameter to retrieve + * @dir: pointer to the direction (-1,0,1) or NULL + * + * Return the minimum value for field PAR. + */ +static unsigned int +snd_pcm_hw_param_value_min(const struct snd_pcm_hw_params *params, + snd_pcm_hw_param_t var, int *dir) +{ + if (hw_is_mask(var)) { + if (dir) + *dir = 0; + return snd_mask_min(hw_param_mask_c(params, var)); + } + if (hw_is_interval(var)) { + const struct snd_interval *i = hw_param_interval_c(params, var); + if (dir) + *dir = i->openmin; + return snd_interval_min(i); + } + return -EINVAL; +} + +/** + * snd_pcm_hw_param_value_max + * @params: the hw_params instance + * @var: parameter to retrieve + * @dir: pointer to the direction (-1,0,1) or NULL + * + * Return the maximum value for field PAR. + */ +static unsigned int +snd_pcm_hw_param_value_max(const struct snd_pcm_hw_params *params, + snd_pcm_hw_param_t var, int *dir) +{ + if (hw_is_mask(var)) { + if (dir) + *dir = 0; + return snd_mask_max(hw_param_mask_c(params, var)); + } + if (hw_is_interval(var)) { + const struct snd_interval *i = hw_param_interval_c(params, var); + if (dir) + *dir = - (int) i->openmax; + return snd_interval_max(i); + } + return -EINVAL; +} + +static int _snd_pcm_hw_param_mask(struct snd_pcm_hw_params *params, + snd_pcm_hw_param_t var, + const struct snd_mask *val) +{ + int changed; + changed = snd_mask_refine(hw_param_mask(params, var), val); + if (changed) { + params->cmask |= 1 << var; + params->rmask |= 1 << var; + } + return changed; +} + +static int snd_pcm_hw_param_mask(struct snd_pcm_substream *pcm, + struct snd_pcm_hw_params *params, + snd_pcm_hw_param_t var, + const struct snd_mask *val) +{ + int changed = _snd_pcm_hw_param_mask(params, var, val); + if (changed < 0) + return changed; + if (params->rmask) { + int err = snd_pcm_hw_refine(pcm, params); + if (err < 0) + return err; + } + return 0; +} + +static int _snd_pcm_hw_param_min(struct snd_pcm_hw_params *params, + snd_pcm_hw_param_t var, unsigned int val, + int dir) +{ + int changed; + int open = 0; + if (dir) { + if (dir > 0) { + open = 1; + } else if (dir < 0) { + if (val > 0) { + open = 1; + val--; + } + } + } + if (hw_is_mask(var)) + changed = snd_mask_refine_min(hw_param_mask(params, var), + val + !!open); + else if (hw_is_interval(var)) + changed = snd_interval_refine_min(hw_param_interval(params, var), + val, open); + else + return -EINVAL; + if (changed) { + params->cmask |= 1 << var; + params->rmask |= 1 << var; + } + return changed; +} + +/** + * snd_pcm_hw_param_min + * @pcm: PCM instance + * @params: the hw_params instance + * @var: parameter to retrieve + * @val: minimal value + * @dir: pointer to the direction (-1,0,1) or NULL + * + * Inside configuration space defined by PARAMS remove from PAR all + * values < VAL. Reduce configuration space accordingly. + * Return new minimum or -EINVAL if the configuration space is empty + */ +static int snd_pcm_hw_param_min(struct snd_pcm_substream *pcm, + struct snd_pcm_hw_params *params, + snd_pcm_hw_param_t var, unsigned int val, + int *dir) +{ + int changed = _snd_pcm_hw_param_min(params, var, val, dir ? *dir : 0); + if (changed < 0) + return changed; + if (params->rmask) { + int err = snd_pcm_hw_refine(pcm, params); + if (err < 0) + return err; + } + return snd_pcm_hw_param_value_min(params, var, dir); +} + +static int _snd_pcm_hw_param_max(struct snd_pcm_hw_params *params, + snd_pcm_hw_param_t var, unsigned int val, + int dir) +{ + int changed; + int open = 0; + if (dir) { + if (dir < 0) { + open = 1; + } else if (dir > 0) { + open = 1; + val++; + } + } + if (hw_is_mask(var)) { + if (val == 0 && open) { + snd_mask_none(hw_param_mask(params, var)); + changed = -EINVAL; + } else + changed = snd_mask_refine_max(hw_param_mask(params, var), + val - !!open); + } else if (hw_is_interval(var)) + changed = snd_interval_refine_max(hw_param_interval(params, var), + val, open); + else + return -EINVAL; + if (changed) { + params->cmask |= 1 << var; + params->rmask |= 1 << var; + } + return changed; +} + +/** + * snd_pcm_hw_param_max + * @pcm: PCM instance + * @params: the hw_params instance + * @var: parameter to retrieve + * @val: maximal value + * @dir: pointer to the direction (-1,0,1) or NULL + * + * Inside configuration space defined by PARAMS remove from PAR all + * values >= VAL + 1. Reduce configuration space accordingly. + * Return new maximum or -EINVAL if the configuration space is empty + */ +static int snd_pcm_hw_param_max(struct snd_pcm_substream *pcm, + struct snd_pcm_hw_params *params, + snd_pcm_hw_param_t var, unsigned int val, + int *dir) +{ + int changed = _snd_pcm_hw_param_max(params, var, val, dir ? *dir : 0); + if (changed < 0) + return changed; + if (params->rmask) { + int err = snd_pcm_hw_refine(pcm, params); + if (err < 0) + return err; + } + return snd_pcm_hw_param_value_max(params, var, dir); +} + +static int boundary_sub(int a, int adir, + int b, int bdir, + int *c, int *cdir) +{ + adir = adir < 0 ? -1 : (adir > 0 ? 1 : 0); + bdir = bdir < 0 ? -1 : (bdir > 0 ? 1 : 0); + *c = a - b; + *cdir = adir - bdir; + if (*cdir == -2) { + (*c)--; + } else if (*cdir == 2) { + (*c)++; + } + return 0; +} + +static int boundary_lt(unsigned int a, int adir, + unsigned int b, int bdir) +{ + if (adir < 0) { + a--; + adir = 1; + } else if (adir > 0) + adir = 1; + if (bdir < 0) { + b--; + bdir = 1; + } else if (bdir > 0) + bdir = 1; + return a < b || (a == b && adir < bdir); +} + +/* Return 1 if min is nearer to best than max */ +static int boundary_nearer(int min, int mindir, + int best, int bestdir, + int max, int maxdir) +{ + int dmin, dmindir; + int dmax, dmaxdir; + boundary_sub(best, bestdir, min, mindir, &dmin, &dmindir); + boundary_sub(max, maxdir, best, bestdir, &dmax, &dmaxdir); + return boundary_lt(dmin, dmindir, dmax, dmaxdir); +} + +/** + * snd_pcm_hw_param_near + * @pcm: PCM instance + * @params: the hw_params instance + * @var: parameter to retrieve + * @best: value to set + * @dir: pointer to the direction (-1,0,1) or NULL + * + * Inside configuration space defined by PARAMS set PAR to the available value + * nearest to VAL. Reduce configuration space accordingly. + * This function cannot be called for SNDRV_PCM_HW_PARAM_ACCESS, + * SNDRV_PCM_HW_PARAM_FORMAT, SNDRV_PCM_HW_PARAM_SUBFORMAT. + * Return the value found. + */ +static int snd_pcm_hw_param_near(struct snd_pcm_substream *pcm, + struct snd_pcm_hw_params *params, + snd_pcm_hw_param_t var, unsigned int best, + int *dir) +{ + struct snd_pcm_hw_params *save = NULL; + int v; + unsigned int saved_min; + int last = 0; + int min, max; + int mindir, maxdir; + int valdir = dir ? *dir : 0; + /* FIXME */ + if (best > INT_MAX) + best = INT_MAX; + min = max = best; + mindir = maxdir = valdir; + if (maxdir > 0) + maxdir = 0; + else if (maxdir == 0) + maxdir = -1; + else { + maxdir = 1; + max--; + } + save = kmalloc(sizeof(*save), GFP_KERNEL); + if (save == NULL) + return -ENOMEM; + *save = *params; + saved_min = min; + min = snd_pcm_hw_param_min(pcm, params, var, min, &mindir); + if (min >= 0) { + struct snd_pcm_hw_params *params1; + if (max < 0) + goto _end; + if ((unsigned int)min == saved_min && mindir == valdir) + goto _end; + params1 = kmalloc(sizeof(*params1), GFP_KERNEL); + if (params1 == NULL) { + kfree(save); + return -ENOMEM; + } + *params1 = *save; + max = snd_pcm_hw_param_max(pcm, params1, var, max, &maxdir); + if (max < 0) { + kfree(params1); + goto _end; + } + if (boundary_nearer(max, maxdir, best, valdir, min, mindir)) { + *params = *params1; + last = 1; + } + kfree(params1); + } else { + *params = *save; + max = snd_pcm_hw_param_max(pcm, params, var, max, &maxdir); + snd_assert(max >= 0, return -EINVAL); + last = 1; + } + _end: + kfree(save); + if (last) + v = snd_pcm_hw_param_last(pcm, params, var, dir); + else + v = snd_pcm_hw_param_first(pcm, params, var, dir); + snd_assert(v >= 0, return -EINVAL); + return v; +} + +static int _snd_pcm_hw_param_set(struct snd_pcm_hw_params *params, + snd_pcm_hw_param_t var, unsigned int val, + int dir) +{ + int changed; + if (hw_is_mask(var)) { + struct snd_mask *m = hw_param_mask(params, var); + if (val == 0 && dir < 0) { + changed = -EINVAL; + snd_mask_none(m); + } else { + if (dir > 0) + val++; + else if (dir < 0) + val--; + changed = snd_mask_refine_set(hw_param_mask(params, var), val); + } + } else if (hw_is_interval(var)) { + struct snd_interval *i = hw_param_interval(params, var); + if (val == 0 && dir < 0) { + changed = -EINVAL; + snd_interval_none(i); + } else if (dir == 0) + changed = snd_interval_refine_set(i, val); + else { + struct snd_interval t; + t.openmin = 1; + t.openmax = 1; + t.empty = 0; + t.integer = 0; + if (dir < 0) { + t.min = val - 1; + t.max = val; + } else { + t.min = val; + t.max = val+1; + } + changed = snd_interval_refine(i, &t); + } + } else + return -EINVAL; + if (changed) { + params->cmask |= 1 << var; + params->rmask |= 1 << var; + } + return changed; +} + +/** + * snd_pcm_hw_param_set + * @pcm: PCM instance + * @params: the hw_params instance + * @var: parameter to retrieve + * @val: value to set + * @dir: pointer to the direction (-1,0,1) or NULL + * + * Inside configuration space defined by PARAMS remove from PAR all + * values != VAL. Reduce configuration space accordingly. + * Return VAL or -EINVAL if the configuration space is empty + */ +static int snd_pcm_hw_param_set(struct snd_pcm_substream *pcm, + struct snd_pcm_hw_params *params, + snd_pcm_hw_param_t var, unsigned int val, + int dir) +{ + int changed = _snd_pcm_hw_param_set(params, var, val, dir); + if (changed < 0) + return changed; + if (params->rmask) { + int err = snd_pcm_hw_refine(pcm, params); + if (err < 0) + return err; + } + return snd_pcm_hw_param_value(params, var, NULL); +} + +static int _snd_pcm_hw_param_setinteger(struct snd_pcm_hw_params *params, + snd_pcm_hw_param_t var) +{ + int changed; + changed = snd_interval_setinteger(hw_param_interval(params, var)); + if (changed) { + params->cmask |= 1 << var; + params->rmask |= 1 << var; + } + return changed; +} + +/* + * plugin + */ + #ifdef CONFIG_SND_PCM_OSS_PLUGINS static int snd_pcm_oss_plugin_clear(struct snd_pcm_substream *substream) { diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 84b00038236..8c15c01907f 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -671,6 +671,8 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count) return 0; } +EXPORT_SYMBOL(snd_pcm_new_stream); + /** * snd_pcm_new - create a new PCM instance * @card: the card instance @@ -730,6 +732,8 @@ int snd_pcm_new(struct snd_card *card, char *id, int device, return 0; } +EXPORT_SYMBOL(snd_pcm_new); + static void snd_pcm_free_stream(struct snd_pcm_str * pstr) { struct snd_pcm_substream *substream, *substream_next; @@ -1022,6 +1026,8 @@ int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree) return 0; } +EXPORT_SYMBOL(snd_pcm_notify); + #ifdef CONFIG_PROC_FS /* * Info interface @@ -1099,33 +1105,3 @@ static void __exit alsa_pcm_exit(void) module_init(alsa_pcm_init) module_exit(alsa_pcm_exit) - -EXPORT_SYMBOL(snd_pcm_new); -EXPORT_SYMBOL(snd_pcm_new_stream); -EXPORT_SYMBOL(snd_pcm_notify); -EXPORT_SYMBOL(snd_pcm_open_substream); -EXPORT_SYMBOL(snd_pcm_release_substream); - /* pcm_native.c */ -EXPORT_SYMBOL(snd_pcm_link_rwlock); -#ifdef CONFIG_PM -EXPORT_SYMBOL(snd_pcm_suspend); -EXPORT_SYMBOL(snd_pcm_suspend_all); -#endif -EXPORT_SYMBOL(snd_pcm_kernel_ioctl); -EXPORT_SYMBOL(snd_pcm_mmap_data); -#if SNDRV_PCM_INFO_MMAP_IOMEM -EXPORT_SYMBOL(snd_pcm_lib_mmap_iomem); -#endif - /* pcm_misc.c */ -EXPORT_SYMBOL(snd_pcm_format_signed); -EXPORT_SYMBOL(snd_pcm_format_unsigned); -EXPORT_SYMBOL(snd_pcm_format_linear); -EXPORT_SYMBOL(snd_pcm_format_little_endian); -EXPORT_SYMBOL(snd_pcm_format_big_endian); -EXPORT_SYMBOL(snd_pcm_format_width); -EXPORT_SYMBOL(snd_pcm_format_physical_width); -EXPORT_SYMBOL(snd_pcm_format_size); -EXPORT_SYMBOL(snd_pcm_format_silence_64); -EXPORT_SYMBOL(snd_pcm_format_set_silence); -EXPORT_SYMBOL(snd_pcm_build_linear_format); -EXPORT_SYMBOL(snd_pcm_limit_hw_rates); diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index eedc6cb038b..786f88145ee 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -289,6 +289,7 @@ void snd_pcm_set_ops(struct snd_pcm *pcm, int direction, struct snd_pcm_ops *ops substream->ops = ops; } +EXPORT_SYMBOL(snd_pcm_set_ops); /** * snd_pcm_sync - set the PCM sync id @@ -306,13 +307,12 @@ void snd_pcm_set_sync(struct snd_pcm_substream *substream) runtime->sync.id32[3] = -1; } +EXPORT_SYMBOL(snd_pcm_set_sync); + /* * Standard ioctl routine */ -/* Code taken from alsa-lib */ -#define assert(a) snd_assert((a), return -EINVAL) - static inline unsigned int div32(unsigned int a, unsigned int b, unsigned int *r) { @@ -369,56 +369,6 @@ static inline unsigned int muldiv32(unsigned int a, unsigned int b, return n; } -static int snd_interval_refine_min(struct snd_interval *i, unsigned int min, int openmin) -{ - int changed = 0; - assert(!snd_interval_empty(i)); - if (i->min < min) { - i->min = min; - i->openmin = openmin; - changed = 1; - } else if (i->min == min && !i->openmin && openmin) { - i->openmin = 1; - changed = 1; - } - if (i->integer) { - if (i->openmin) { - i->min++; - i->openmin = 0; - } - } - if (snd_interval_checkempty(i)) { - snd_interval_none(i); - return -EINVAL; - } - return changed; -} - -static int snd_interval_refine_max(struct snd_interval *i, unsigned int max, int openmax) -{ - int changed = 0; - assert(!snd_interval_empty(i)); - if (i->max > max) { - i->max = max; - i->openmax = openmax; - changed = 1; - } else if (i->max == max && !i->openmax && openmax) { - i->openmax = 1; - changed = 1; - } - if (i->integer) { - if (i->openmax) { - i->max--; - i->openmax = 0; - } - } - if (snd_interval_checkempty(i)) { - snd_interval_none(i); - return -EINVAL; - } - return changed; -} - /** * snd_interval_refine - refine the interval value of configurator * @i: the interval value to refine @@ -433,7 +383,7 @@ static int snd_interval_refine_max(struct snd_interval *i, unsigned int max, int int snd_interval_refine(struct snd_interval *i, const struct snd_interval *v) { int changed = 0; - assert(!snd_interval_empty(i)); + snd_assert(!snd_interval_empty(i), return -EINVAL); if (i->min < v->min) { i->min = v->min; i->openmin = v->openmin; @@ -472,9 +422,11 @@ int snd_interval_refine(struct snd_interval *i, const struct snd_interval *v) return changed; } +EXPORT_SYMBOL(snd_interval_refine); + static int snd_interval_refine_first(struct snd_interval *i) { - assert(!snd_interval_empty(i)); + snd_assert(!snd_interval_empty(i), return -EINVAL); if (snd_interval_single(i)) return 0; i->max = i->min; @@ -486,7 +438,7 @@ static int snd_interval_refine_first(struct snd_interval *i) static int snd_interval_refine_last(struct snd_interval *i) { - assert(!snd_interval_empty(i)); + snd_assert(!snd_interval_empty(i), return -EINVAL); if (snd_interval_single(i)) return 0; i->min = i->max; @@ -496,16 +448,6 @@ static int snd_interval_refine_last(struct snd_interval *i) return 1; } -static int snd_interval_refine_set(struct snd_interval *i, unsigned int val) -{ - struct snd_interval t; - t.empty = 0; - t.min = t.max = val; - t.openmin = t.openmax = 0; - t.integer = 1; - return snd_interval_refine(i, &t); -} - void snd_interval_mul(const struct snd_interval *a, const struct snd_interval *b, struct snd_interval *c) { if (a->empty || b->empty) { @@ -621,7 +563,6 @@ void snd_interval_mulkdiv(const struct snd_interval *a, unsigned int k, c->integer = 0; } -#undef assert /* ---- */ @@ -727,6 +668,8 @@ int snd_interval_ratnum(struct snd_interval *i, return err; } +EXPORT_SYMBOL(snd_interval_ratnum); + /** * snd_interval_ratden - refine the interval value * @i: interval to refine @@ -877,6 +820,8 @@ int snd_interval_list(struct snd_interval *i, unsigned int count, unsigned int * return changed; } +EXPORT_SYMBOL(snd_interval_list); + static int snd_interval_step(struct snd_interval *i, unsigned int min, unsigned int step) { unsigned int n; @@ -953,6 +898,8 @@ int snd_pcm_hw_rule_add(struct snd_pcm_runtime *runtime, unsigned int cond, return 0; } +EXPORT_SYMBOL(snd_pcm_hw_rule_add); + /** * snd_pcm_hw_constraint_mask * @runtime: PCM runtime instance @@ -1007,6 +954,8 @@ int snd_pcm_hw_constraint_integer(struct snd_pcm_runtime *runtime, snd_pcm_hw_pa return snd_interval_setinteger(constrs_interval(constrs, var)); } +EXPORT_SYMBOL(snd_pcm_hw_constraint_integer); + /** * snd_pcm_hw_constraint_minmax * @runtime: PCM runtime instance @@ -1028,6 +977,8 @@ int snd_pcm_hw_constraint_minmax(struct snd_pcm_runtime *runtime, snd_pcm_hw_par return snd_interval_refine(constrs_interval(constrs, var), &t); } +EXPORT_SYMBOL(snd_pcm_hw_constraint_minmax); + static int snd_pcm_hw_rule_list(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) { @@ -1055,6 +1006,8 @@ int snd_pcm_hw_constraint_list(struct snd_pcm_runtime *runtime, var, -1); } +EXPORT_SYMBOL(snd_pcm_hw_constraint_list); + static int snd_pcm_hw_rule_ratnums(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) { @@ -1087,6 +1040,8 @@ int snd_pcm_hw_constraint_ratnums(struct snd_pcm_runtime *runtime, var, -1); } +EXPORT_SYMBOL(snd_pcm_hw_constraint_ratnums); + static int snd_pcm_hw_rule_ratdens(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) { @@ -1118,6 +1073,8 @@ int snd_pcm_hw_constraint_ratdens(struct snd_pcm_runtime *runtime, var, -1); } +EXPORT_SYMBOL(snd_pcm_hw_constraint_ratdens); + static int snd_pcm_hw_rule_msbits(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) { @@ -1149,6 +1106,8 @@ int snd_pcm_hw_constraint_msbits(struct snd_pcm_runtime *runtime, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1); } +EXPORT_SYMBOL(snd_pcm_hw_constraint_msbits); + static int snd_pcm_hw_rule_step(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) { @@ -1173,6 +1132,8 @@ int snd_pcm_hw_constraint_step(struct snd_pcm_runtime *runtime, var, -1); } +EXPORT_SYMBOL(snd_pcm_hw_constraint_step); + static int snd_pcm_hw_rule_pow2(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) { static int pow2_sizes[] = { @@ -1200,6 +1161,8 @@ int snd_pcm_hw_constraint_pow2(struct snd_pcm_runtime *runtime, var, -1); } +EXPORT_SYMBOL(snd_pcm_hw_constraint_pow2); + /* To use the same code we have in alsa-lib */ #define assert(i) snd_assert((i), return -EINVAL) #ifndef INT_MIN @@ -1224,18 +1187,6 @@ static void _snd_pcm_hw_param_any(struct snd_pcm_hw_params *params, snd_BUG(); } -#if 0 -/* - * snd_pcm_hw_param_any - */ -int snd_pcm_hw_param_any(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var) -{ - _snd_pcm_hw_param_any(params, var); - return snd_pcm_hw_refine(pcm, params); -} -#endif /* 0 */ - void _snd_pcm_hw_params_any(struct snd_pcm_hw_params *params) { unsigned int k; @@ -1247,18 +1198,7 @@ void _snd_pcm_hw_params_any(struct snd_pcm_hw_params *params) params->info = ~0U; } -#if 0 -/* - * snd_pcm_hw_params_any - * - * Fill PARAMS with full configuration space boundaries - */ -int snd_pcm_hw_params_any(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params) -{ - _snd_pcm_hw_params_any(params); - return snd_pcm_hw_refine(pcm, params); -} -#endif /* 0 */ +EXPORT_SYMBOL(_snd_pcm_hw_params_any); /** * snd_pcm_hw_param_value @@ -1269,8 +1209,8 @@ int snd_pcm_hw_params_any(struct snd_pcm_substream *pcm, struct snd_pcm_hw_param * Return the value for field PAR if it's fixed in configuration space * defined by PARAMS. Return -EINVAL otherwise */ -static int snd_pcm_hw_param_value(const struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var, int *dir) +int snd_pcm_hw_param_value(const struct snd_pcm_hw_params *params, + snd_pcm_hw_param_t var, int *dir) { if (hw_is_mask(var)) { const struct snd_mask *mask = hw_param_mask_c(params, var); @@ -1292,57 +1232,7 @@ static int snd_pcm_hw_param_value(const struct snd_pcm_hw_params *params, return -EINVAL; } -/** - * snd_pcm_hw_param_value_min - * @params: the hw_params instance - * @var: parameter to retrieve - * @dir: pointer to the direction (-1,0,1) or NULL - * - * Return the minimum value for field PAR. - */ -unsigned int snd_pcm_hw_param_value_min(const struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var, int *dir) -{ - if (hw_is_mask(var)) { - if (dir) - *dir = 0; - return snd_mask_min(hw_param_mask_c(params, var)); - } - if (hw_is_interval(var)) { - const struct snd_interval *i = hw_param_interval_c(params, var); - if (dir) - *dir = i->openmin; - return snd_interval_min(i); - } - assert(0); - return -EINVAL; -} - -/** - * snd_pcm_hw_param_value_max - * @params: the hw_params instance - * @var: parameter to retrieve - * @dir: pointer to the direction (-1,0,1) or NULL - * - * Return the maximum value for field PAR. - */ -unsigned int snd_pcm_hw_param_value_max(const struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var, int *dir) -{ - if (hw_is_mask(var)) { - if (dir) - *dir = 0; - return snd_mask_max(hw_param_mask_c(params, var)); - } - if (hw_is_interval(var)) { - const struct snd_interval *i = hw_param_interval_c(params, var); - if (dir) - *dir = - (int) i->openmax; - return snd_interval_max(i); - } - assert(0); - return -EINVAL; -} +EXPORT_SYMBOL(snd_pcm_hw_param_value); void _snd_pcm_hw_param_setempty(struct snd_pcm_hw_params *params, snd_pcm_hw_param_t var) @@ -1360,42 +1250,7 @@ void _snd_pcm_hw_param_setempty(struct snd_pcm_hw_params *params, } } -int _snd_pcm_hw_param_setinteger(struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var) -{ - int changed; - assert(hw_is_interval(var)); - changed = snd_interval_setinteger(hw_param_interval(params, var)); - if (changed) { - params->cmask |= 1 << var; - params->rmask |= 1 << var; - } - return changed; -} - -#if 0 -/* - * snd_pcm_hw_param_setinteger - * - * Inside configuration space defined by PARAMS remove from PAR all - * non integer values. Reduce configuration space accordingly. - * Return -EINVAL if the configuration space is empty - */ -int snd_pcm_hw_param_setinteger(struct snd_pcm_substream *pcm, - struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var) -{ - int changed = _snd_pcm_hw_param_setinteger(params, var); - if (changed < 0) - return changed; - if (params->rmask) { - int err = snd_pcm_hw_refine(pcm, params); - if (err < 0) - return err; - } - return 0; -} -#endif /* 0 */ +EXPORT_SYMBOL(_snd_pcm_hw_param_setempty); static int _snd_pcm_hw_param_first(struct snd_pcm_hw_params *params, snd_pcm_hw_param_t var) @@ -1428,9 +1283,9 @@ static int _snd_pcm_hw_param_first(struct snd_pcm_hw_params *params, * values > minimum. Reduce configuration space accordingly. * Return the minimum. */ -static int snd_pcm_hw_param_first(struct snd_pcm_substream *pcm, - struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var, int *dir) +int snd_pcm_hw_param_first(struct snd_pcm_substream *pcm, + struct snd_pcm_hw_params *params, + snd_pcm_hw_param_t var, int *dir) { int changed = _snd_pcm_hw_param_first(params, var); if (changed < 0) @@ -1442,6 +1297,8 @@ static int snd_pcm_hw_param_first(struct snd_pcm_substream *pcm, return snd_pcm_hw_param_value(params, var, dir); } +EXPORT_SYMBOL(snd_pcm_hw_param_first); + static int _snd_pcm_hw_param_last(struct snd_pcm_hw_params *params, snd_pcm_hw_param_t var) { @@ -1473,9 +1330,9 @@ static int _snd_pcm_hw_param_last(struct snd_pcm_hw_params *params, * values < maximum. Reduce configuration space accordingly. * Return the maximum. */ -static int snd_pcm_hw_param_last(struct snd_pcm_substream *pcm, - struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var, int *dir) +int snd_pcm_hw_param_last(struct snd_pcm_substream *pcm, + struct snd_pcm_hw_params *params, + snd_pcm_hw_param_t var, int *dir) { int changed = _snd_pcm_hw_param_last(params, var); if (changed < 0) @@ -1487,367 +1344,7 @@ static int snd_pcm_hw_param_last(struct snd_pcm_substream *pcm, return snd_pcm_hw_param_value(params, var, dir); } -int _snd_pcm_hw_param_min(struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var, unsigned int val, int dir) -{ - int changed; - int open = 0; - if (dir) { - if (dir > 0) { - open = 1; - } else if (dir < 0) { - if (val > 0) { - open = 1; - val--; - } - } - } - if (hw_is_mask(var)) - changed = snd_mask_refine_min(hw_param_mask(params, var), val + !!open); - else if (hw_is_interval(var)) - changed = snd_interval_refine_min(hw_param_interval(params, var), val, open); - else { - assert(0); - return -EINVAL; - } - if (changed) { - params->cmask |= 1 << var; - params->rmask |= 1 << var; - } - return changed; -} - -/** - * snd_pcm_hw_param_min - * @pcm: PCM instance - * @params: the hw_params instance - * @var: parameter to retrieve - * @val: minimal value - * @dir: pointer to the direction (-1,0,1) or NULL - * - * Inside configuration space defined by PARAMS remove from PAR all - * values < VAL. Reduce configuration space accordingly. - * Return new minimum or -EINVAL if the configuration space is empty - */ -static int snd_pcm_hw_param_min(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var, unsigned int val, - int *dir) -{ - int changed = _snd_pcm_hw_param_min(params, var, val, dir ? *dir : 0); - if (changed < 0) - return changed; - if (params->rmask) { - int err = snd_pcm_hw_refine(pcm, params); - if (err < 0) - return err; - } - return snd_pcm_hw_param_value_min(params, var, dir); -} - -static int _snd_pcm_hw_param_max(struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var, unsigned int val, - int dir) -{ - int changed; - int open = 0; - if (dir) { - if (dir < 0) { - open = 1; - } else if (dir > 0) { - open = 1; - val++; - } - } - if (hw_is_mask(var)) { - if (val == 0 && open) { - snd_mask_none(hw_param_mask(params, var)); - changed = -EINVAL; - } else - changed = snd_mask_refine_max(hw_param_mask(params, var), val - !!open); - } else if (hw_is_interval(var)) - changed = snd_interval_refine_max(hw_param_interval(params, var), val, open); - else { - assert(0); - return -EINVAL; - } - if (changed) { - params->cmask |= 1 << var; - params->rmask |= 1 << var; - } - return changed; -} - -/** - * snd_pcm_hw_param_max - * @pcm: PCM instance - * @params: the hw_params instance - * @var: parameter to retrieve - * @val: maximal value - * @dir: pointer to the direction (-1,0,1) or NULL - * - * Inside configuration space defined by PARAMS remove from PAR all - * values >= VAL + 1. Reduce configuration space accordingly. - * Return new maximum or -EINVAL if the configuration space is empty - */ -static int snd_pcm_hw_param_max(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var, unsigned int val, - int *dir) -{ - int changed = _snd_pcm_hw_param_max(params, var, val, dir ? *dir : 0); - if (changed < 0) - return changed; - if (params->rmask) { - int err = snd_pcm_hw_refine(pcm, params); - if (err < 0) - return err; - } - return snd_pcm_hw_param_value_max(params, var, dir); -} - -int _snd_pcm_hw_param_set(struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var, unsigned int val, int dir) -{ - int changed; - if (hw_is_mask(var)) { - struct snd_mask *m = hw_param_mask(params, var); - if (val == 0 && dir < 0) { - changed = -EINVAL; - snd_mask_none(m); - } else { - if (dir > 0) - val++; - else if (dir < 0) - val--; - changed = snd_mask_refine_set(hw_param_mask(params, var), val); - } - } else if (hw_is_interval(var)) { - struct snd_interval *i = hw_param_interval(params, var); - if (val == 0 && dir < 0) { - changed = -EINVAL; - snd_interval_none(i); - } else if (dir == 0) - changed = snd_interval_refine_set(i, val); - else { - struct snd_interval t; - t.openmin = 1; - t.openmax = 1; - t.empty = 0; - t.integer = 0; - if (dir < 0) { - t.min = val - 1; - t.max = val; - } else { - t.min = val; - t.max = val+1; - } - changed = snd_interval_refine(i, &t); - } - } else { - assert(0); - return -EINVAL; - } - if (changed) { - params->cmask |= 1 << var; - params->rmask |= 1 << var; - } - return changed; -} - -/** - * snd_pcm_hw_param_set - * @pcm: PCM instance - * @params: the hw_params instance - * @var: parameter to retrieve - * @val: value to set - * @dir: pointer to the direction (-1,0,1) or NULL - * - * Inside configuration space defined by PARAMS remove from PAR all - * values != VAL. Reduce configuration space accordingly. - * Return VAL or -EINVAL if the configuration space is empty - */ -int snd_pcm_hw_param_set(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var, unsigned int val, int dir) -{ - int changed = _snd_pcm_hw_param_set(params, var, val, dir); - if (changed < 0) - return changed; - if (params->rmask) { - int err = snd_pcm_hw_refine(pcm, params); - if (err < 0) - return err; - } - return snd_pcm_hw_param_value(params, var, NULL); -} - -static int _snd_pcm_hw_param_mask(struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var, const struct snd_mask *val) -{ - int changed; - assert(hw_is_mask(var)); - changed = snd_mask_refine(hw_param_mask(params, var), val); - if (changed) { - params->cmask |= 1 << var; - params->rmask |= 1 << var; - } - return changed; -} - -/** - * snd_pcm_hw_param_mask - * @pcm: PCM instance - * @params: the hw_params instance - * @var: parameter to retrieve - * @val: mask to apply - * - * Inside configuration space defined by PARAMS remove from PAR all values - * not contained in MASK. Reduce configuration space accordingly. - * This function can be called only for SNDRV_PCM_HW_PARAM_ACCESS, - * SNDRV_PCM_HW_PARAM_FORMAT, SNDRV_PCM_HW_PARAM_SUBFORMAT. - * Return 0 on success or -EINVAL - * if the configuration space is empty - */ -int snd_pcm_hw_param_mask(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var, const struct snd_mask *val) -{ - int changed = _snd_pcm_hw_param_mask(params, var, val); - if (changed < 0) - return changed; - if (params->rmask) { - int err = snd_pcm_hw_refine(pcm, params); - if (err < 0) - return err; - } - return 0; -} - -static int boundary_sub(int a, int adir, - int b, int bdir, - int *c, int *cdir) -{ - adir = adir < 0 ? -1 : (adir > 0 ? 1 : 0); - bdir = bdir < 0 ? -1 : (bdir > 0 ? 1 : 0); - *c = a - b; - *cdir = adir - bdir; - if (*cdir == -2) { - assert(*c > INT_MIN); - (*c)--; - } else if (*cdir == 2) { - assert(*c < INT_MAX); - (*c)++; - } - return 0; -} - -static int boundary_lt(unsigned int a, int adir, - unsigned int b, int bdir) -{ - assert(a > 0 || adir >= 0); - assert(b > 0 || bdir >= 0); - if (adir < 0) { - a--; - adir = 1; - } else if (adir > 0) - adir = 1; - if (bdir < 0) { - b--; - bdir = 1; - } else if (bdir > 0) - bdir = 1; - return a < b || (a == b && adir < bdir); -} - -/* Return 1 if min is nearer to best than max */ -static int boundary_nearer(int min, int mindir, - int best, int bestdir, - int max, int maxdir) -{ - int dmin, dmindir; - int dmax, dmaxdir; - boundary_sub(best, bestdir, min, mindir, &dmin, &dmindir); - boundary_sub(max, maxdir, best, bestdir, &dmax, &dmaxdir); - return boundary_lt(dmin, dmindir, dmax, dmaxdir); -} - -/** - * snd_pcm_hw_param_near - * @pcm: PCM instance - * @params: the hw_params instance - * @var: parameter to retrieve - * @best: value to set - * @dir: pointer to the direction (-1,0,1) or NULL - * - * Inside configuration space defined by PARAMS set PAR to the available value - * nearest to VAL. Reduce configuration space accordingly. - * This function cannot be called for SNDRV_PCM_HW_PARAM_ACCESS, - * SNDRV_PCM_HW_PARAM_FORMAT, SNDRV_PCM_HW_PARAM_SUBFORMAT. - * Return the value found. - */ -int snd_pcm_hw_param_near(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var, unsigned int best, int *dir) -{ - struct snd_pcm_hw_params *save = NULL; - int v; - unsigned int saved_min; - int last = 0; - int min, max; - int mindir, maxdir; - int valdir = dir ? *dir : 0; - /* FIXME */ - if (best > INT_MAX) - best = INT_MAX; - min = max = best; - mindir = maxdir = valdir; - if (maxdir > 0) - maxdir = 0; - else if (maxdir == 0) - maxdir = -1; - else { - maxdir = 1; - max--; - } - save = kmalloc(sizeof(*save), GFP_KERNEL); - if (save == NULL) - return -ENOMEM; - *save = *params; - saved_min = min; - min = snd_pcm_hw_param_min(pcm, params, var, min, &mindir); - if (min >= 0) { - struct snd_pcm_hw_params *params1; - if (max < 0) - goto _end; - if ((unsigned int)min == saved_min && mindir == valdir) - goto _end; - params1 = kmalloc(sizeof(*params1), GFP_KERNEL); - if (params1 == NULL) { - kfree(save); - return -ENOMEM; - } - *params1 = *save; - max = snd_pcm_hw_param_max(pcm, params1, var, max, &maxdir); - if (max < 0) { - kfree(params1); - goto _end; - } - if (boundary_nearer(max, maxdir, best, valdir, min, mindir)) { - *params = *params1; - last = 1; - } - kfree(params1); - } else { - *params = *save; - max = snd_pcm_hw_param_max(pcm, params, var, max, &maxdir); - assert(max >= 0); - last = 1; - } - _end: - kfree(save); - if (last) - v = snd_pcm_hw_param_last(pcm, params, var, dir); - else - v = snd_pcm_hw_param_first(pcm, params, var, dir); - assert(v >= 0); - return v; -} +EXPORT_SYMBOL(snd_pcm_hw_param_last); /** * snd_pcm_hw_param_choose @@ -1967,6 +1464,8 @@ int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream, return -ENXIO; } +EXPORT_SYMBOL(snd_pcm_lib_ioctl); + /* * Conditions */ @@ -2101,6 +1600,8 @@ void snd_pcm_period_elapsed(struct snd_pcm_substream *substream) kill_fasync(&runtime->fasync, SIGIO, POLL_IN); } +EXPORT_SYMBOL(snd_pcm_period_elapsed); + static int snd_pcm_lib_write_transfer(struct snd_pcm_substream *substream, unsigned int hwoff, unsigned long data, unsigned int off, @@ -2308,6 +1809,8 @@ snd_pcm_sframes_t snd_pcm_lib_write(struct snd_pcm_substream *substream, const v snd_pcm_lib_write_transfer); } +EXPORT_SYMBOL(snd_pcm_lib_write); + static int snd_pcm_lib_writev_transfer(struct snd_pcm_substream *substream, unsigned int hwoff, unsigned long data, unsigned int off, @@ -2370,6 +1873,8 @@ snd_pcm_sframes_t snd_pcm_lib_writev(struct snd_pcm_substream *substream, nonblock, snd_pcm_lib_writev_transfer); } +EXPORT_SYMBOL(snd_pcm_lib_writev); + static int snd_pcm_lib_read_transfer(struct snd_pcm_substream *substream, unsigned int hwoff, unsigned long data, unsigned int off, @@ -2578,6 +2083,8 @@ snd_pcm_sframes_t snd_pcm_lib_read(struct snd_pcm_substream *substream, void __u return snd_pcm_lib_read1(substream, (unsigned long)buf, size, nonblock, snd_pcm_lib_read_transfer); } +EXPORT_SYMBOL(snd_pcm_lib_read); + static int snd_pcm_lib_readv_transfer(struct snd_pcm_substream *substream, unsigned int hwoff, unsigned long data, unsigned int off, @@ -2635,52 +2142,4 @@ snd_pcm_sframes_t snd_pcm_lib_readv(struct snd_pcm_substream *substream, return snd_pcm_lib_read1(substream, (unsigned long)bufs, frames, nonblock, snd_pcm_lib_readv_transfer); } -/* - * Exported symbols - */ - -EXPORT_SYMBOL(snd_interval_refine); -EXPORT_SYMBOL(snd_interval_list); -EXPORT_SYMBOL(snd_interval_ratnum); -EXPORT_SYMBOL(_snd_pcm_hw_params_any); -EXPORT_SYMBOL(_snd_pcm_hw_param_min); -EXPORT_SYMBOL(_snd_pcm_hw_param_set); -EXPORT_SYMBOL(_snd_pcm_hw_param_setempty); -EXPORT_SYMBOL(_snd_pcm_hw_param_setinteger); -EXPORT_SYMBOL(snd_pcm_hw_param_value_min); -EXPORT_SYMBOL(snd_pcm_hw_param_value_max); -EXPORT_SYMBOL(snd_pcm_hw_param_mask); -EXPORT_SYMBOL(snd_pcm_hw_param_first); -EXPORT_SYMBOL(snd_pcm_hw_param_last); -EXPORT_SYMBOL(snd_pcm_hw_param_near); -EXPORT_SYMBOL(snd_pcm_hw_param_set); -EXPORT_SYMBOL(snd_pcm_hw_refine); -EXPORT_SYMBOL(snd_pcm_hw_constraints_init); -EXPORT_SYMBOL(snd_pcm_hw_constraints_complete); -EXPORT_SYMBOL(snd_pcm_hw_constraint_list); -EXPORT_SYMBOL(snd_pcm_hw_constraint_step); -EXPORT_SYMBOL(snd_pcm_hw_constraint_ratnums); -EXPORT_SYMBOL(snd_pcm_hw_constraint_ratdens); -EXPORT_SYMBOL(snd_pcm_hw_constraint_msbits); -EXPORT_SYMBOL(snd_pcm_hw_constraint_minmax); -EXPORT_SYMBOL(snd_pcm_hw_constraint_integer); -EXPORT_SYMBOL(snd_pcm_hw_constraint_pow2); -EXPORT_SYMBOL(snd_pcm_hw_rule_add); -EXPORT_SYMBOL(snd_pcm_set_ops); -EXPORT_SYMBOL(snd_pcm_set_sync); -EXPORT_SYMBOL(snd_pcm_lib_ioctl); -EXPORT_SYMBOL(snd_pcm_stop); -EXPORT_SYMBOL(snd_pcm_period_elapsed); -EXPORT_SYMBOL(snd_pcm_lib_write); -EXPORT_SYMBOL(snd_pcm_lib_read); -EXPORT_SYMBOL(snd_pcm_lib_writev); EXPORT_SYMBOL(snd_pcm_lib_readv); -EXPORT_SYMBOL(snd_pcm_lib_buffer_bytes); -EXPORT_SYMBOL(snd_pcm_lib_period_bytes); -/* pcm_memory.c */ -EXPORT_SYMBOL(snd_pcm_lib_preallocate_free_for_all); -EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages); -EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages_for_all); -EXPORT_SYMBOL(snd_pcm_sgbuf_ops_page); -EXPORT_SYMBOL(snd_pcm_lib_malloc_pages); -EXPORT_SYMBOL(snd_pcm_lib_free_pages); diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c index 428f8c169ee..eb56167d3bb 100644 --- a/sound/core/pcm_memory.c +++ b/sound/core/pcm_memory.c @@ -126,6 +126,8 @@ int snd_pcm_lib_preallocate_free_for_all(struct snd_pcm *pcm) return 0; } +EXPORT_SYMBOL(snd_pcm_lib_preallocate_free_for_all); + #ifdef CONFIG_SND_VERBOSE_PROCFS /* * read callback for prealloc proc file @@ -253,6 +255,8 @@ int snd_pcm_lib_preallocate_pages(struct snd_pcm_substream *substream, return snd_pcm_lib_preallocate_pages1(substream, size, max); } +EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages); + /** * snd_pcm_lib_preallocate_pages_for_all - pre-allocation for continous memory type (all substreams) * @pcm: the pcm instance @@ -280,6 +284,8 @@ int snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm, return 0; } +EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages_for_all); + /** * snd_pcm_sgbuf_ops_page - get the page struct at the given offset * @substream: the pcm substream instance @@ -298,6 +304,8 @@ struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, unsigne return sgbuf->page_table[idx]; } +EXPORT_SYMBOL(snd_pcm_sgbuf_ops_page); + /** * snd_pcm_lib_malloc_pages - allocate the DMA buffer * @substream: the substream to allocate the DMA buffer to @@ -349,6 +357,8 @@ int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size) return 1; /* area was changed */ } +EXPORT_SYMBOL(snd_pcm_lib_malloc_pages); + /** * snd_pcm_lib_free_pages - release the allocated DMA buffer. * @substream: the substream to release the DMA buffer @@ -374,3 +384,5 @@ int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream) snd_pcm_set_runtime_buffer(substream, NULL); return 0; } + +EXPORT_SYMBOL(snd_pcm_lib_free_pages); diff --git a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c index 593c77f4d18..0019c59a779 100644 --- a/sound/core/pcm_misc.c +++ b/sound/core/pcm_misc.c @@ -207,6 +207,8 @@ int snd_pcm_format_signed(snd_pcm_format_t format) return val; } +EXPORT_SYMBOL(snd_pcm_format_signed); + /** * snd_pcm_format_unsigned - Check the PCM format is unsigned linear * @format: the format to check @@ -224,6 +226,8 @@ int snd_pcm_format_unsigned(snd_pcm_format_t format) return !val; } +EXPORT_SYMBOL(snd_pcm_format_unsigned); + /** * snd_pcm_format_linear - Check the PCM format is linear * @format: the format to check @@ -235,6 +239,8 @@ int snd_pcm_format_linear(snd_pcm_format_t format) return snd_pcm_format_signed(format) >= 0; } +EXPORT_SYMBOL(snd_pcm_format_linear); + /** * snd_pcm_format_little_endian - Check the PCM format is little-endian * @format: the format to check @@ -252,6 +258,8 @@ int snd_pcm_format_little_endian(snd_pcm_format_t format) return val; } +EXPORT_SYMBOL(snd_pcm_format_little_endian); + /** * snd_pcm_format_big_endian - Check the PCM format is big-endian * @format: the format to check @@ -269,6 +277,8 @@ int snd_pcm_format_big_endian(snd_pcm_format_t format) return !val; } +EXPORT_SYMBOL(snd_pcm_format_big_endian); + /** * snd_pcm_format_width - return the bit-width of the format * @format: the format to check @@ -286,6 +296,8 @@ int snd_pcm_format_width(snd_pcm_format_t format) return val; } +EXPORT_SYMBOL(snd_pcm_format_width); + /** * snd_pcm_format_physical_width - return the physical bit-width of the format * @format: the format to check @@ -303,6 +315,8 @@ int snd_pcm_format_physical_width(snd_pcm_format_t format) return val; } +EXPORT_SYMBOL(snd_pcm_format_physical_width); + /** * snd_pcm_format_size - return the byte size of samples on the given format * @format: the format to check @@ -318,6 +332,8 @@ ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples) return samples * phys_width / 8; } +EXPORT_SYMBOL(snd_pcm_format_size); + /** * snd_pcm_format_silence_64 - return the silent data in 8 bytes array * @format: the format to check @@ -333,6 +349,8 @@ const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format) return pcm_formats[format].silence; } +EXPORT_SYMBOL(snd_pcm_format_silence_64); + /** * snd_pcm_format_set_silence - set the silence data on the buffer * @format: the PCM format @@ -402,6 +420,8 @@ int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int return 0; } +EXPORT_SYMBOL(snd_pcm_format_set_silence); + /* [width][unsigned][bigendian] */ static int linear_formats[4][2][2] = { {{ SNDRV_PCM_FORMAT_S8, SNDRV_PCM_FORMAT_S8}, @@ -432,6 +452,8 @@ snd_pcm_format_t snd_pcm_build_linear_format(int width, int unsignd, int big_end return linear_formats[width][!!unsignd][!!big_endian]; } +EXPORT_SYMBOL(snd_pcm_build_linear_format); + /** * snd_pcm_limit_hw_rates - determine rate_min/rate_max fields * @runtime: the runtime instance @@ -463,3 +485,5 @@ int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime) } return 0; } + +EXPORT_SYMBOL(snd_pcm_limit_hw_rates); diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 0860c5a8450..7b5729c4b21 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -71,8 +71,9 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream); */ DEFINE_RWLOCK(snd_pcm_link_rwlock); -static DECLARE_RWSEM(snd_pcm_link_rwsem); +EXPORT_SYMBOL(snd_pcm_link_rwlock); +static DECLARE_RWSEM(snd_pcm_link_rwsem); static inline mm_segment_t snd_enter_user(void) { @@ -319,6 +320,8 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream, return 0; } +EXPORT_SYMBOL(snd_pcm_hw_refine); + static int snd_pcm_hw_refine_user(struct snd_pcm_substream *substream, struct snd_pcm_hw_params __user * _params) { @@ -936,6 +939,8 @@ int snd_pcm_stop(struct snd_pcm_substream *substream, int state) return snd_pcm_action(&snd_pcm_action_stop, substream, state); } +EXPORT_SYMBOL(snd_pcm_stop); + /** * snd_pcm_drain_done * @substream: the PCM substream @@ -1085,6 +1090,8 @@ int snd_pcm_suspend(struct snd_pcm_substream *substream) return err; } +EXPORT_SYMBOL(snd_pcm_suspend); + /** * snd_pcm_suspend_all * @pcm: the PCM instance @@ -1114,6 +1121,8 @@ int snd_pcm_suspend_all(struct snd_pcm *pcm) return 0; } +EXPORT_SYMBOL(snd_pcm_suspend_all); + /* resume */ static int snd_pcm_pre_resume(struct snd_pcm_substream *substream, int state) @@ -2020,6 +2029,8 @@ void snd_pcm_release_substream(struct snd_pcm_substream *substream) snd_pcm_detach_substream(substream); } +EXPORT_SYMBOL(snd_pcm_release_substream); + int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, struct file *file, struct snd_pcm_substream **rsubstream) @@ -2056,6 +2067,8 @@ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, return err; } +EXPORT_SYMBOL(snd_pcm_open_substream); + static int snd_pcm_open_file(struct file *file, struct snd_pcm *pcm, int stream, @@ -2768,6 +2781,8 @@ int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, return result; } +EXPORT_SYMBOL(snd_pcm_kernel_ioctl); + static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count, loff_t * offset) { @@ -3169,6 +3184,8 @@ int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream, atomic_inc(&substream->runtime->mmap_count); return 0; } + +EXPORT_SYMBOL(snd_pcm_lib_mmap_iomem); #endif /* SNDRV_PCM_INFO_MMAP */ /* @@ -3212,6 +3229,8 @@ int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file, return snd_pcm_default_mmap(substream, area); } +EXPORT_SYMBOL(snd_pcm_mmap_data); + static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area) { struct snd_pcm_file * pcm_file; -- cgit v1.2.3 From 2f4ca8e5c7cf6a6f7935483d8ee4aa8b039bdd7d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 28 Apr 2006 15:13:40 +0200 Subject: [ALSA] Clean up ugly hacks in pcm_lib.c Clean up ugly hacks for sync with alsa-lib code in pcm_lib.c. Also, optimize snd_pcm_hw_params_choose() with a loop. Signed-off-by: Takashi Iwai --- sound/core/pcm_lib.c | 70 +++++++++++++++++++--------------------------------- 1 file changed, 26 insertions(+), 44 deletions(-) diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 786f88145ee..a21aa0050e4 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -1163,12 +1163,6 @@ int snd_pcm_hw_constraint_pow2(struct snd_pcm_runtime *runtime, EXPORT_SYMBOL(snd_pcm_hw_constraint_pow2); -/* To use the same code we have in alsa-lib */ -#define assert(i) snd_assert((i), return -EINVAL) -#ifndef INT_MIN -#define INT_MIN ((int)((unsigned int)INT_MAX+1)) -#endif - static void _snd_pcm_hw_param_any(struct snd_pcm_hw_params *params, snd_pcm_hw_param_t var) { @@ -1228,7 +1222,6 @@ int snd_pcm_hw_param_value(const struct snd_pcm_hw_params *params, *dir = i->openmin; return snd_interval_value(i); } - assert(0); return -EINVAL; } @@ -1260,10 +1253,8 @@ static int _snd_pcm_hw_param_first(struct snd_pcm_hw_params *params, changed = snd_mask_refine_first(hw_param_mask(params, var)); else if (hw_is_interval(var)) changed = snd_interval_refine_first(hw_param_interval(params, var)); - else { - assert(0); + else return -EINVAL; - } if (changed) { params->cmask |= 1 << var; params->rmask |= 1 << var; @@ -1292,7 +1283,7 @@ int snd_pcm_hw_param_first(struct snd_pcm_substream *pcm, return changed; if (params->rmask) { int err = snd_pcm_hw_refine(pcm, params); - assert(err >= 0); + snd_assert(err >= 0, return err); } return snd_pcm_hw_param_value(params, var, dir); } @@ -1307,10 +1298,8 @@ static int _snd_pcm_hw_param_last(struct snd_pcm_hw_params *params, changed = snd_mask_refine_last(hw_param_mask(params, var)); else if (hw_is_interval(var)) changed = snd_interval_refine_last(hw_param_interval(params, var)); - else { - assert(0); + else return -EINVAL; - } if (changed) { params->cmask |= 1 << var; params->rmask |= 1 << var; @@ -1339,7 +1328,7 @@ int snd_pcm_hw_param_last(struct snd_pcm_substream *pcm, return changed; if (params->rmask) { int err = snd_pcm_hw_refine(pcm, params); - assert(err >= 0); + snd_assert(err >= 0, return err); } return snd_pcm_hw_param_value(params, var, dir); } @@ -1356,39 +1345,32 @@ EXPORT_SYMBOL(snd_pcm_hw_param_last); * first access, first format, first subformat, min channels, * min rate, min period time, max buffer size, min tick time */ -int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params) -{ - int err; - - err = snd_pcm_hw_param_first(pcm, params, SNDRV_PCM_HW_PARAM_ACCESS, NULL); - assert(err >= 0); - - err = snd_pcm_hw_param_first(pcm, params, SNDRV_PCM_HW_PARAM_FORMAT, NULL); - assert(err >= 0); - - err = snd_pcm_hw_param_first(pcm, params, SNDRV_PCM_HW_PARAM_SUBFORMAT, NULL); - assert(err >= 0); - - err = snd_pcm_hw_param_first(pcm, params, SNDRV_PCM_HW_PARAM_CHANNELS, NULL); - assert(err >= 0); - - err = snd_pcm_hw_param_first(pcm, params, SNDRV_PCM_HW_PARAM_RATE, NULL); - assert(err >= 0); - - err = snd_pcm_hw_param_first(pcm, params, SNDRV_PCM_HW_PARAM_PERIOD_TIME, NULL); - assert(err >= 0); - - err = snd_pcm_hw_param_last(pcm, params, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, NULL); - assert(err >= 0); - - err = snd_pcm_hw_param_first(pcm, params, SNDRV_PCM_HW_PARAM_TICK_TIME, NULL); - assert(err >= 0); +int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm, + struct snd_pcm_hw_params *params) +{ + static int vars[] = { + SNDRV_PCM_HW_PARAM_ACCESS, + SNDRV_PCM_HW_PARAM_FORMAT, + SNDRV_PCM_HW_PARAM_SUBFORMAT, + SNDRV_PCM_HW_PARAM_CHANNELS, + SNDRV_PCM_HW_PARAM_RATE, + SNDRV_PCM_HW_PARAM_PERIOD_TIME, + SNDRV_PCM_HW_PARAM_BUFFER_SIZE, + SNDRV_PCM_HW_PARAM_TICK_TIME, + -1 + }; + int err, *v; + for (v = vars; *v != -1; v++) { + if (*v != SNDRV_PCM_HW_PARAM_BUFFER_SIZE) + err = snd_pcm_hw_param_first(pcm, params, *v, NULL); + else + err = snd_pcm_hw_param_last(pcm, params, *v, NULL); + snd_assert(err >= 0, return err); + } return 0; } -#undef assert - static int snd_pcm_lib_ioctl_reset(struct snd_pcm_substream *substream, void *arg) { -- cgit v1.2.3 From 7e4eeec8a30fa9e00cac67a37ca9ddf6cbdb79c4 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 28 Apr 2006 15:13:40 +0200 Subject: [ALSA] Make buffer size of proc text interface variable Make the read/write buffer size of proc text interface variable. Signed-off-by: Takashi Iwai --- include/sound/info.h | 6 +-- sound/core/info.c | 149 +++++++++++++++++++++++++++------------------------ 2 files changed, 82 insertions(+), 73 deletions(-) diff --git a/include/sound/info.h b/include/sound/info.h index f23d8381c21..48128438985 100644 --- a/include/sound/info.h +++ b/include/sound/info.h @@ -27,9 +27,9 @@ /* buffer for information */ struct snd_info_buffer { char *buffer; /* pointer to begin of buffer */ - char *curr; /* current position in buffer */ - unsigned long size; /* current size */ - unsigned long len; /* total length of buffer */ + unsigned int curr; /* current position in buffer */ + unsigned int size; /* current size */ + unsigned int len; /* total length of buffer */ int stop; /* stop flag */ int error; /* error code */ }; diff --git a/sound/core/info.c b/sound/core/info.c index 9c288539e99..86366839c4b 100644 --- a/sound/core/info.c +++ b/sound/core/info.c @@ -21,7 +21,6 @@ #include #include -#include #include #include #include @@ -82,6 +81,24 @@ static int snd_info_version_init(void); static int snd_info_version_done(void); +/* resize the proc r/w buffer */ +static int resize_info_buffer(struct snd_info_buffer *buffer, + unsigned int nsize) +{ + char *nbuf; + + nsize = PAGE_ALIGN(nsize); + nbuf = kmalloc(nsize, GFP_KERNEL); + if (! nbuf) + return -ENOMEM; + + memcpy(nbuf, buffer->buffer, buffer->len); + kfree(buffer->buffer); + buffer->buffer = nbuf; + buffer->len = nsize; + return 0; +} + /** * snd_iprintf - printf on the procfs buffer * @buffer: the procfs buffer @@ -95,17 +112,25 @@ int snd_iprintf(struct snd_info_buffer *buffer, char *fmt,...) { va_list args; int len, res; + int err = 0; if (buffer->stop || buffer->error) return 0; len = buffer->len - buffer->size; va_start(args, fmt); - res = vsnprintf(buffer->curr, len, fmt, args); - va_end(args); - if (res >= len) { - buffer->stop = 1; - return 0; + for (;;) { + res = vsnprintf(buffer->buffer + buffer->curr, len, fmt, args); + if (res < len) + break; + err = resize_info_buffer(buffer, buffer->len + PAGE_SIZE); + if (err < 0) + break; + len = buffer->len - buffer->size; } + va_end(args); + + if (err < 0) + return err; buffer->curr += res; buffer->size += res; return res; @@ -225,7 +250,7 @@ static ssize_t snd_info_entry_write(struct file *file, const char __user *buffer struct snd_info_private_data *data; struct snd_info_entry *entry; struct snd_info_buffer *buf; - size_t size = 0; + ssize_t size = 0; loff_t pos; data = file->private_data; @@ -241,14 +266,20 @@ static ssize_t snd_info_entry_write(struct file *file, const char __user *buffer buf = data->wbuffer; if (buf == NULL) return -EIO; - if (pos >= buf->len) - return -ENOMEM; - size = buf->len - pos; - size = min(count, size); - if (copy_from_user(buf->buffer + pos, buffer, size)) + mutex_unlock(&entry->access); + if (pos + count >= buf->len) { + if (resize_info_buffer(buf, pos + count)) { + mutex_unlock(&entry->access); + return -ENOMEM; + } + } + if (copy_from_user(buf->buffer + pos, buffer, count)) { + mutex_unlock(&entry->access); return -EFAULT; - if ((long)buf->size < pos + size) - buf->size = pos + size; + } + buf->size = pos + count; + mutex_unlock(&entry->access); + size = count; break; case SNDRV_INFO_CONTENT_DATA: if (entry->c.ops->write) @@ -283,18 +314,14 @@ static int snd_info_entry_open(struct inode *inode, struct file *file) } mode = file->f_flags & O_ACCMODE; if (mode == O_RDONLY || mode == O_RDWR) { - if ((entry->content == SNDRV_INFO_CONTENT_TEXT && - !entry->c.text.read_size) || - (entry->content == SNDRV_INFO_CONTENT_DATA && + if ((entry->content == SNDRV_INFO_CONTENT_DATA && entry->c.ops->read == NULL)) { err = -ENODEV; goto __error; } } if (mode == O_WRONLY || mode == O_RDWR) { - if ((entry->content == SNDRV_INFO_CONTENT_TEXT && - !entry->c.text.write_size) || - (entry->content == SNDRV_INFO_CONTENT_DATA && + if ((entry->content == SNDRV_INFO_CONTENT_DATA && entry->c.ops->write == NULL)) { err = -ENODEV; goto __error; @@ -310,49 +337,23 @@ static int snd_info_entry_open(struct inode *inode, struct file *file) case SNDRV_INFO_CONTENT_TEXT: if (mode == O_RDONLY || mode == O_RDWR) { buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); - if (buffer == NULL) { - kfree(data); - err = -ENOMEM; - goto __error; - } - buffer->len = (entry->c.text.read_size + - (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); - buffer->buffer = vmalloc(buffer->len); - if (buffer->buffer == NULL) { - kfree(buffer); - kfree(data); - err = -ENOMEM; - goto __error; - } - buffer->curr = buffer->buffer; + if (buffer == NULL) + goto __nomem; data->rbuffer = buffer; + buffer->len = PAGE_SIZE; + buffer->buffer = kmalloc(buffer->len, GFP_KERNEL); + if (buffer->buffer == NULL) + goto __nomem; } if (mode == O_WRONLY || mode == O_RDWR) { buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); - if (buffer == NULL) { - if (mode == O_RDWR) { - vfree(data->rbuffer->buffer); - kfree(data->rbuffer); - } - kfree(data); - err = -ENOMEM; - goto __error; - } - buffer->len = (entry->c.text.write_size + - (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); - buffer->buffer = vmalloc(buffer->len); - if (buffer->buffer == NULL) { - if (mode == O_RDWR) { - vfree(data->rbuffer->buffer); - kfree(data->rbuffer); - } - kfree(buffer); - kfree(data); - err = -ENOMEM; - goto __error; - } - buffer->curr = buffer->buffer; + if (buffer == NULL) + goto __nomem; data->wbuffer = buffer; + buffer->len = PAGE_SIZE; + buffer->buffer = kmalloc(buffer->len, GFP_KERNEL); + if (buffer->buffer == NULL) + goto __nomem; } break; case SNDRV_INFO_CONTENT_DATA: /* data */ @@ -377,6 +378,17 @@ static int snd_info_entry_open(struct inode *inode, struct file *file) } return 0; + __nomem: + if (data->rbuffer) { + kfree(data->rbuffer->buffer); + kfree(data->rbuffer); + } + if (data->wbuffer) { + kfree(data->wbuffer->buffer); + kfree(data->wbuffer); + } + kfree(data); + err = -ENOMEM; __error: module_put(entry->module); __error1: @@ -395,11 +407,11 @@ static int snd_info_entry_release(struct inode *inode, struct file *file) entry = data->entry; switch (entry->content) { case SNDRV_INFO_CONTENT_TEXT: - if (mode == O_RDONLY || mode == O_RDWR) { - vfree(data->rbuffer->buffer); + if (data->rbuffer) { + kfree(data->rbuffer->buffer); kfree(data->rbuffer); } - if (mode == O_WRONLY || mode == O_RDWR) { + if (data->wbuffer) { if (entry->c.text.write) { entry->c.text.write(entry, data->wbuffer); if (data->wbuffer->error) { @@ -408,7 +420,7 @@ static int snd_info_entry_release(struct inode *inode, struct file *file) data->wbuffer->error); } } - vfree(data->wbuffer->buffer); + kfree(data->wbuffer->buffer); kfree(data->wbuffer); } break; @@ -668,24 +680,22 @@ int snd_info_get_line(struct snd_info_buffer *buffer, char *line, int len) if (len <= 0 || buffer->stop || buffer->error) return 1; while (--len > 0) { - c = *buffer->curr++; + c = buffer->buffer[buffer->curr++]; if (c == '\n') { - if ((buffer->curr - buffer->buffer) >= (long)buffer->size) { + if (buffer->curr >= buffer->size) buffer->stop = 1; - } break; } *line++ = c; - if ((buffer->curr - buffer->buffer) >= (long)buffer->size) { + if (buffer->curr >= buffer->size) { buffer->stop = 1; break; } } while (c != '\n' && !buffer->stop) { - c = *buffer->curr++; - if ((buffer->curr - buffer->buffer) >= (long)buffer->size) { + c = buffer->buffer[buffer->curr++]; + if (buffer->curr >= buffer->size) buffer->stop = 1; - } } *line = '\0'; return 0; @@ -978,7 +988,6 @@ static int __init snd_info_version_init(void) entry = snd_info_create_module_entry(THIS_MODULE, "version", NULL); if (entry == NULL) return -ENOMEM; - entry->c.text.read_size = 256; entry->c.text.read = snd_info_version_read; if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); -- cgit v1.2.3 From bf850204a71a97eb5a6afaf27263bb667f9cab0a Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 28 Apr 2006 15:13:41 +0200 Subject: [ALSA] Remove unneeded read/write_size fields in proc text ops Remove unneeded read/write_size fields in proc text ops. snd_info_set_text_ops() is fixed, too. Signed-off-by: Takashi Iwai --- .../sound/alsa/DocBook/writing-an-alsa-driver.tmpl | 19 +-------------- include/sound/info.h | 5 ---- sound/core/hwdep.c | 1 - sound/core/info_oss.c | 1 - sound/core/init.c | 3 --- sound/core/oss/mixer_oss.c | 2 -- sound/core/oss/pcm_oss.c | 2 -- sound/core/pcm.c | 19 +++++++-------- sound/core/pcm_memory.c | 2 -- sound/core/rawmidi.c | 1 - sound/core/seq/oss/seq_oss.c | 1 - sound/core/seq/seq_device.c | 1 - sound/core/seq/seq_info.c | 11 ++++----- sound/core/sound.c | 1 - sound/core/sound_oss.c | 1 - sound/core/timer.c | 1 - sound/drivers/vx/vx_core.c | 2 +- sound/i2c/l3/uda1341.c | 4 ++-- sound/isa/gus/gus_irq.c | 2 +- sound/isa/gus/gus_mem.c | 6 ++--- sound/isa/opti9xx/miro.c | 2 +- sound/isa/sb/sb16_csp.c | 2 +- sound/pci/ac97/ac97_proc.c | 5 ++-- sound/pci/ac97/ak4531_codec.c | 2 +- sound/pci/ad1889.c | 2 +- sound/pci/ali5451/ali5451.c | 2 +- sound/pci/atiixp.c | 2 +- sound/pci/atiixp_modem.c | 2 +- sound/pci/ca0106/ca0106_proc.c | 17 ++++++-------- sound/pci/cmipci.c | 2 +- sound/pci/cs4281.c | 2 +- sound/pci/cs46xx/dsp_spos.c | 7 ------ sound/pci/cs46xx/dsp_spos_scb_lib.c | 1 - sound/pci/emu10k1/emu10k1x.c | 3 +-- sound/pci/emu10k1/emuproc.c | 27 ++++++++-------------- sound/pci/ens1370.c | 2 +- sound/pci/hda/hda_proc.c | 2 +- sound/pci/ice1712/ice1712.c | 2 +- sound/pci/ice1712/ice1724.c | 2 +- sound/pci/ice1712/pontis.c | 8 +++---- sound/pci/intel8x0.c | 2 +- sound/pci/intel8x0m.c | 2 +- sound/pci/korg1212/korg1212.c | 2 +- sound/pci/mixart/mixart.c | 1 - sound/pci/pcxhr/pcxhr.c | 4 ++-- sound/pci/riptide/riptide.c | 2 +- sound/pci/rme32.c | 2 +- sound/pci/rme96.c | 2 +- sound/pci/rme9652/hdsp.c | 2 +- sound/pci/rme9652/hdspm.c | 2 +- sound/pci/rme9652/rme9652.c | 2 +- sound/pci/sonicvibes.c | 2 +- sound/pci/trident/trident_main.c | 2 +- sound/pci/via82xx.c | 2 +- sound/pci/via82xx_modem.c | 2 +- sound/pci/ymfpci/ymfpci_main.c | 2 +- sound/pcmcia/pdaudiocf/pdaudiocf_core.c | 2 +- sound/sparc/dbri.c | 4 ++-- sound/synth/emux/emux_proc.c | 1 - sound/usb/usbaudio.c | 6 ++--- sound/usb/usbmixer.c | 2 +- 61 files changed, 81 insertions(+), 146 deletions(-) diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl index 1faf76383ba..db557f91ab7 100644 --- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl +++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl @@ -5333,7 +5333,7 @@ struct _snd_pcm_runtime { @@ -5394,29 +5394,12 @@ struct _snd_pcm_runtime { c.text.write_size = 256; entry->c.text.write = my_proc_write; ]]> - - The buffer size for read is set to 1024 implicitly by - snd_info_set_text_ops(). It should suffice - in most cases (the size will be aligned to - PAGE_SIZE anyway), but if you need to handle - very large text files, you can set it explicitly, too. - - - -c.text.read_size = 65536; -]]> - - - - For the write callback, you can use snd_info_get_line() to get a text line, and diff --git a/include/sound/info.h b/include/sound/info.h index 48128438985..74f6996769c 100644 --- a/include/sound/info.h +++ b/include/sound/info.h @@ -40,8 +40,6 @@ struct snd_info_buffer { struct snd_info_entry; struct snd_info_entry_text { - unsigned long read_size; - unsigned long write_size; void (*read) (struct snd_info_entry *entry, struct snd_info_buffer *buffer); void (*write) (struct snd_info_entry *entry, struct snd_info_buffer *buffer); }; @@ -132,11 +130,9 @@ int snd_card_proc_new(struct snd_card *card, const char *name, struct snd_info_e static inline void snd_info_set_text_ops(struct snd_info_entry *entry, void *private_data, - long read_size, void (*read)(struct snd_info_entry *, struct snd_info_buffer *)) { entry->private_data = private_data; - entry->c.text.read_size = read_size; entry->c.text.read = read; } @@ -167,7 +163,6 @@ static inline int snd_card_proc_new(struct snd_card *card, const char *name, struct snd_info_entry **entryp) { return -EINVAL; } static inline void snd_info_set_text_ops(struct snd_info_entry *entry __attribute__((unused)), void *private_data, - long read_size, void (*read)(struct snd_info_entry *, struct snd_info_buffer *)) {} static inline int snd_info_check_reserved_words(const char *str) { return 1; } diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c index 2524e66eccd..8bd0dcc93eb 100644 --- a/sound/core/hwdep.c +++ b/sound/core/hwdep.c @@ -486,7 +486,6 @@ static void __init snd_hwdep_proc_init(void) struct snd_info_entry *entry; if ((entry = snd_info_create_module_entry(THIS_MODULE, "hwdep", NULL)) != NULL) { - entry->c.text.read_size = PAGE_SIZE; entry->c.text.read = snd_hwdep_proc_read; if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); diff --git a/sound/core/info_oss.c b/sound/core/info_oss.c index f2efca18728..bb2c40d0ab6 100644 --- a/sound/core/info_oss.c +++ b/sound/core/info_oss.c @@ -119,7 +119,6 @@ int snd_info_minor_register(void) memset(snd_sndstat_strings, 0, sizeof(snd_sndstat_strings)); if ((entry = snd_info_create_module_entry(THIS_MODULE, "sndstat", snd_oss_root)) != NULL) { - entry->c.text.read_size = 2048; entry->c.text.read = snd_sndstat_proc_read; if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); diff --git a/sound/core/init.c b/sound/core/init.c index b145d17ba3b..2ff0e5e9086 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -69,7 +69,6 @@ static inline int init_info_for_card(struct snd_card *card) snd_printd("unable to create card entry\n"); return err; } - entry->c.text.read_size = PAGE_SIZE; entry->c.text.read = snd_card_id_read; if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); @@ -592,7 +591,6 @@ int __init snd_card_info_init(void) entry = snd_info_create_module_entry(THIS_MODULE, "cards", NULL); if (! entry) return -ENOMEM; - entry->c.text.read_size = PAGE_SIZE; entry->c.text.read = snd_card_info_read; if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); @@ -603,7 +601,6 @@ int __init snd_card_info_init(void) #ifdef MODULE entry = snd_info_create_module_entry(THIS_MODULE, "modules", NULL); if (entry) { - entry->c.text.read_size = PAGE_SIZE; entry->c.text.read = snd_card_module_info_read; if (snd_info_register(entry) < 0) snd_info_free_entry(entry); diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c index 9c68bc3f97a..71b5080fa66 100644 --- a/sound/core/oss/mixer_oss.c +++ b/sound/core/oss/mixer_oss.c @@ -1182,9 +1182,7 @@ static void snd_mixer_oss_proc_init(struct snd_mixer_oss *mixer) return; entry->content = SNDRV_INFO_CONTENT_TEXT; entry->mode = S_IFREG | S_IRUGO | S_IWUSR; - entry->c.text.read_size = 8192; entry->c.text.read = snd_mixer_oss_proc_read; - entry->c.text.write_size = 8192; entry->c.text.write = snd_mixer_oss_proc_write; entry->private_data = mixer; if (snd_info_register(entry) < 0) { diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 0d2e232afe6..d8b7416ee00 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -2823,9 +2823,7 @@ static void snd_pcm_oss_proc_init(struct snd_pcm *pcm) if ((entry = snd_info_create_card_entry(pcm->card, "oss", pstr->proc_root)) != NULL) { entry->content = SNDRV_INFO_CONTENT_TEXT; entry->mode = S_IFREG | S_IRUGO | S_IWUSR; - entry->c.text.read_size = 8192; entry->c.text.read = snd_pcm_oss_proc_read; - entry->c.text.write_size = 8192; entry->c.text.write = snd_pcm_oss_proc_write; entry->private_data = pstr; if (snd_info_register(entry) < 0) { diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 8c15c01907f..08223783cfa 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -472,7 +472,7 @@ static int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr) pstr->proc_root = entry; if ((entry = snd_info_create_card_entry(pcm->card, "info", pstr->proc_root)) != NULL) { - snd_info_set_text_ops(entry, pstr, 256, snd_pcm_stream_proc_info_read); + snd_info_set_text_ops(entry, pstr, snd_pcm_stream_proc_info_read); if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); entry = NULL; @@ -483,9 +483,7 @@ static int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr) #ifdef CONFIG_SND_PCM_XRUN_DEBUG if ((entry = snd_info_create_card_entry(pcm->card, "xrun_debug", pstr->proc_root)) != NULL) { - entry->c.text.read_size = 64; entry->c.text.read = snd_pcm_xrun_debug_read; - entry->c.text.write_size = 64; entry->c.text.write = snd_pcm_xrun_debug_write; entry->mode |= S_IWUSR; entry->private_data = pstr; @@ -537,7 +535,8 @@ static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream) substream->proc_root = entry; if ((entry = snd_info_create_card_entry(card, "info", substream->proc_root)) != NULL) { - snd_info_set_text_ops(entry, substream, 256, snd_pcm_substream_proc_info_read); + snd_info_set_text_ops(entry, substream, + snd_pcm_substream_proc_info_read); if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); entry = NULL; @@ -546,7 +545,8 @@ static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream) substream->proc_info_entry = entry; if ((entry = snd_info_create_card_entry(card, "hw_params", substream->proc_root)) != NULL) { - snd_info_set_text_ops(entry, substream, 256, snd_pcm_substream_proc_hw_params_read); + snd_info_set_text_ops(entry, substream, + snd_pcm_substream_proc_hw_params_read); if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); entry = NULL; @@ -555,7 +555,8 @@ static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream) substream->proc_hw_params_entry = entry; if ((entry = snd_info_create_card_entry(card, "sw_params", substream->proc_root)) != NULL) { - snd_info_set_text_ops(entry, substream, 256, snd_pcm_substream_proc_sw_params_read); + snd_info_set_text_ops(entry, substream, + snd_pcm_substream_proc_sw_params_read); if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); entry = NULL; @@ -564,7 +565,8 @@ static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream) substream->proc_sw_params_entry = entry; if ((entry = snd_info_create_card_entry(card, "status", substream->proc_root)) != NULL) { - snd_info_set_text_ops(entry, substream, 256, snd_pcm_substream_proc_status_read); + snd_info_set_text_ops(entry, substream, + snd_pcm_substream_proc_status_read); if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); entry = NULL; @@ -1062,8 +1064,7 @@ static void snd_pcm_proc_init(void) struct snd_info_entry *entry; if ((entry = snd_info_create_module_entry(THIS_MODULE, "pcm", NULL)) != NULL) { - snd_info_set_text_ops(entry, NULL, SNDRV_CARDS * SNDRV_PCM_DEVICES * 128, - snd_pcm_proc_read); + snd_info_set_text_ops(entry, NULL, snd_pcm_proc_read); if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); entry = NULL; diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c index eb56167d3bb..067d2056db9 100644 --- a/sound/core/pcm_memory.c +++ b/sound/core/pcm_memory.c @@ -193,9 +193,7 @@ static inline void preallocate_info_init(struct snd_pcm_substream *substream) struct snd_info_entry *entry; if ((entry = snd_info_create_card_entry(substream->pcm->card, "prealloc", substream->proc_root)) != NULL) { - entry->c.text.read_size = 64; entry->c.text.read = snd_pcm_lib_preallocate_proc_read; - entry->c.text.write_size = 64; entry->c.text.write = snd_pcm_lib_preallocate_proc_write; entry->mode |= S_IWUSR; entry->private_data = substream; diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 87b47c9564f..08a41e5023c 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -1561,7 +1561,6 @@ static int snd_rawmidi_dev_register(struct snd_device *device) entry = snd_info_create_card_entry(rmidi->card, name, rmidi->card->proc_root); if (entry) { entry->private_data = rmidi; - entry->c.text.read_size = 1024; entry->c.text.read = snd_rawmidi_proc_info_read; if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); diff --git a/sound/core/seq/oss/seq_oss.c b/sound/core/seq/oss/seq_oss.c index b9919785180..e7234135641 100644 --- a/sound/core/seq/oss/seq_oss.c +++ b/sound/core/seq/oss/seq_oss.c @@ -291,7 +291,6 @@ register_proc(void) entry->content = SNDRV_INFO_CONTENT_TEXT; entry->private_data = NULL; - entry->c.text.read_size = 1024; entry->c.text.read = info_read; if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); diff --git a/sound/core/seq/seq_device.c b/sound/core/seq/seq_device.c index d9a3e5a18d6..1e4bc402f00 100644 --- a/sound/core/seq/seq_device.c +++ b/sound/core/seq/seq_device.c @@ -555,7 +555,6 @@ static int __init alsa_seq_device_init(void) if (info_entry == NULL) return -ENOMEM; info_entry->content = SNDRV_INFO_CONTENT_TEXT; - info_entry->c.text.read_size = 2048; info_entry->c.text.read = snd_seq_device_info; if (snd_info_register(info_entry) < 0) { snd_info_free_entry(info_entry); diff --git a/sound/core/seq/seq_info.c b/sound/core/seq/seq_info.c index acce21afdaa..142e9e6882c 100644 --- a/sound/core/seq/seq_info.c +++ b/sound/core/seq/seq_info.c @@ -34,8 +34,8 @@ static struct snd_info_entry *timer_entry; static struct snd_info_entry * __init -create_info_entry(char *name, int size, void (*read)(struct snd_info_entry *, - struct snd_info_buffer *)) +create_info_entry(char *name, void (*read)(struct snd_info_entry *, + struct snd_info_buffer *)) { struct snd_info_entry *entry; @@ -43,7 +43,6 @@ create_info_entry(char *name, int size, void (*read)(struct snd_info_entry *, if (entry == NULL) return NULL; entry->content = SNDRV_INFO_CONTENT_TEXT; - entry->c.text.read_size = size; entry->c.text.read = read; if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); @@ -55,11 +54,11 @@ create_info_entry(char *name, int size, void (*read)(struct snd_info_entry *, /* create all our /proc entries */ int __init snd_seq_info_init(void) { - queues_entry = create_info_entry("queues", 512 + (256 * SNDRV_SEQ_MAX_QUEUES), + queues_entry = create_info_entry("queues", snd_seq_info_queues_read); - clients_entry = create_info_entry("clients", 512 + (256 * SNDRV_SEQ_MAX_CLIENTS), + clients_entry = create_info_entry("clients", snd_seq_info_clients_read); - timer_entry = create_info_entry("timer", 1024, snd_seq_info_timer_read); + timer_entry = create_info_entry("timer", snd_seq_info_timer_read); return 0; } diff --git a/sound/core/sound.c b/sound/core/sound.c index 67cfa06062b..8313f97907d 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c @@ -392,7 +392,6 @@ int __init snd_minor_info_init(void) entry = snd_info_create_module_entry(THIS_MODULE, "devices", NULL); if (entry) { - entry->c.text.read_size = PAGE_SIZE; entry->c.text.read = snd_minor_info_read; if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c index c18f6a45e4d..0043c9a97de 100644 --- a/sound/core/sound_oss.c +++ b/sound/core/sound_oss.c @@ -258,7 +258,6 @@ int __init snd_minor_info_oss_init(void) entry = snd_info_create_module_entry(THIS_MODULE, "devices", snd_oss_root); if (entry) { - entry->c.text.read_size = PAGE_SIZE; entry->c.text.read = snd_minor_info_oss_read; if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); diff --git a/sound/core/timer.c b/sound/core/timer.c index cdeeb639b67..9a1e51c7c23 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -1117,7 +1117,6 @@ static void __init snd_timer_proc_init(void) entry = snd_info_create_module_entry(THIS_MODULE, "timers", NULL); if (entry != NULL) { - entry->c.text.read_size = SNDRV_TIMER_DEVICES * 128; entry->c.text.read = snd_timer_proc_read; if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); diff --git a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c index e1c3dda1577..a60168268dd 100644 --- a/sound/drivers/vx/vx_core.c +++ b/sound/drivers/vx/vx_core.c @@ -640,7 +640,7 @@ static void vx_proc_init(struct vx_core *chip) struct snd_info_entry *entry; if (! snd_card_proc_new(chip->card, "vx-status", &entry)) - snd_info_set_text_ops(entry, chip, 1024, vx_proc_read); + snd_info_set_text_ops(entry, chip, vx_proc_read); } diff --git a/sound/i2c/l3/uda1341.c b/sound/i2c/l3/uda1341.c index 746500e0695..b074fdddea5 100644 --- a/sound/i2c/l3/uda1341.c +++ b/sound/i2c/l3/uda1341.c @@ -517,9 +517,9 @@ static void __devinit snd_uda1341_proc_init(struct snd_card *card, struct l3_cli struct snd_info_entry *entry; if (! snd_card_proc_new(card, "uda1341", &entry)) - snd_info_set_text_ops(entry, clnt, 1024, snd_uda1341_proc_read); + snd_info_set_text_ops(entry, clnt, snd_uda1341_proc_read); if (! snd_card_proc_new(card, "uda1341-regs", &entry)) - snd_info_set_text_ops(entry, clnt, 1024, snd_uda1341_proc_regs_read); + snd_info_set_text_ops(entry, clnt, snd_uda1341_proc_regs_read); } /* }}} */ diff --git a/sound/isa/gus/gus_irq.c b/sound/isa/gus/gus_irq.c index c19ba2910b7..42db37552ef 100644 --- a/sound/isa/gus/gus_irq.c +++ b/sound/isa/gus/gus_irq.c @@ -136,7 +136,7 @@ void snd_gus_irq_profile_init(struct snd_gus_card *gus) struct snd_info_entry *entry; if (! snd_card_proc_new(gus->card, "gusirq", &entry)) - snd_info_set_text_ops(entry, gus, 1024, snd_gus_irq_info_read); + snd_info_set_text_ops(entry, gus, snd_gus_irq_info_read); } #endif diff --git a/sound/isa/gus/gus_mem.c b/sound/isa/gus/gus_mem.c index 3c0d27aa08b..f50c276caee 100644 --- a/sound/isa/gus/gus_mem.c +++ b/sound/isa/gus/gus_mem.c @@ -264,10 +264,8 @@ int snd_gf1_mem_init(struct snd_gus_card * gus) if (snd_gf1_mem_xalloc(alloc, &block) == NULL) return -ENOMEM; #ifdef CONFIG_SND_DEBUG - if (! snd_card_proc_new(gus->card, "gusmem", &entry)) { - snd_info_set_text_ops(entry, gus, 1024, snd_gf1_mem_info_read); - entry->c.text.read_size = 256 * 1024; - } + if (! snd_card_proc_new(gus->card, "gusmem", &entry)) + snd_info_set_text_ops(entry, gus, snd_gf1_mem_info_read); #endif return 0; } diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c index e6bfcf74c1c..283817f2de7 100644 --- a/sound/isa/opti9xx/miro.c +++ b/sound/isa/opti9xx/miro.c @@ -967,7 +967,7 @@ static void __init snd_miro_proc_init(struct snd_miro * miro) struct snd_info_entry *entry; if (! snd_card_proc_new(miro->card, "miro", &entry)) - snd_info_set_text_ops(entry, miro, 1024, snd_miro_proc_read); + snd_info_set_text_ops(entry, miro, snd_miro_proc_read); } /* diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c index 9703c68e4e0..fcd638090a9 100644 --- a/sound/isa/sb/sb16_csp.c +++ b/sound/isa/sb/sb16_csp.c @@ -1101,7 +1101,7 @@ static int init_proc_entry(struct snd_sb_csp * p, int device) struct snd_info_entry *entry; sprintf(name, "cspD%d", device); if (! snd_card_proc_new(p->chip->card, name, &entry)) - snd_info_set_text_ops(entry, p, 1024, info_read); + snd_info_set_text_ops(entry, p, info_read); return 0; } diff --git a/sound/pci/ac97/ac97_proc.c b/sound/pci/ac97/ac97_proc.c index 4d523df79cc..2118df50b9d 100644 --- a/sound/pci/ac97/ac97_proc.c +++ b/sound/pci/ac97/ac97_proc.c @@ -433,7 +433,7 @@ void snd_ac97_proc_init(struct snd_ac97 * ac97) prefix = ac97_is_audio(ac97) ? "ac97" : "mc97"; sprintf(name, "%s#%d-%d", prefix, ac97->addr, ac97->num); if ((entry = snd_info_create_card_entry(ac97->bus->card, name, ac97->bus->proc)) != NULL) { - snd_info_set_text_ops(entry, ac97, 1024, snd_ac97_proc_read); + snd_info_set_text_ops(entry, ac97, snd_ac97_proc_read); if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); entry = NULL; @@ -442,10 +442,9 @@ void snd_ac97_proc_init(struct snd_ac97 * ac97) ac97->proc = entry; sprintf(name, "%s#%d-%d+regs", prefix, ac97->addr, ac97->num); if ((entry = snd_info_create_card_entry(ac97->bus->card, name, ac97->bus->proc)) != NULL) { - snd_info_set_text_ops(entry, ac97, 1024, snd_ac97_proc_regs_read); + snd_info_set_text_ops(entry, ac97, snd_ac97_proc_regs_read); #ifdef CONFIG_SND_DEBUG entry->mode |= S_IWUSR; - entry->c.text.write_size = 1024; entry->c.text.write = snd_ac97_proc_regs_write; #endif if (snd_info_register(entry) < 0) { diff --git a/sound/pci/ac97/ak4531_codec.c b/sound/pci/ac97/ak4531_codec.c index 0fb7b340731..94c26ec0588 100644 --- a/sound/pci/ac97/ak4531_codec.c +++ b/sound/pci/ac97/ak4531_codec.c @@ -453,7 +453,7 @@ static void snd_ak4531_proc_init(struct snd_card *card, struct snd_ak4531 *ak453 struct snd_info_entry *entry; if (! snd_card_proc_new(card, "ak4531", &entry)) - snd_info_set_text_ops(entry, ak4531, 1024, snd_ak4531_proc_read); + snd_info_set_text_ops(entry, ak4531, snd_ak4531_proc_read); } #endif diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c index eece1c7e55a..d42bf457036 100644 --- a/sound/pci/ad1889.c +++ b/sound/pci/ad1889.c @@ -753,7 +753,7 @@ snd_ad1889_proc_init(struct snd_ad1889 *chip) struct snd_info_entry *entry; if (!snd_card_proc_new(chip->card, chip->card->driver, &entry)) - snd_info_set_text_ops(entry, chip, 1024, snd_ad1889_proc_read); + snd_info_set_text_ops(entry, chip, snd_ad1889_proc_read); } static struct ac97_quirk ac97_quirks[] = { diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index e2dbc211890..4f01ef10fac 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c @@ -2173,7 +2173,7 @@ static void __devinit snd_ali_proc_init(struct snd_ali *codec) { struct snd_info_entry *entry; if(!snd_card_proc_new(codec->card, "ali5451", &entry)) - snd_info_set_text_ops(entry, codec, 1024, snd_ali_proc_read); + snd_info_set_text_ops(entry, codec, snd_ali_proc_read); } static int __devinit snd_ali_resources(struct snd_ali *codec) diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index d0f759d86d3..f18a8c0e468 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c @@ -1504,7 +1504,7 @@ static void __devinit snd_atiixp_proc_init(struct atiixp *chip) struct snd_info_entry *entry; if (! snd_card_proc_new(chip->card, "atiixp", &entry)) - snd_info_set_text_ops(entry, chip, 1024, snd_atiixp_proc_read); + snd_info_set_text_ops(entry, chip, snd_atiixp_proc_read); } #else /* !CONFIG_PROC_FS */ #define snd_atiixp_proc_init(chip) diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c index 12a34c39caa..40739057076 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c @@ -1177,7 +1177,7 @@ static void __devinit snd_atiixp_proc_init(struct atiixp_modem *chip) struct snd_info_entry *entry; if (! snd_card_proc_new(chip->card, "atiixp-modem", &entry)) - snd_info_set_text_ops(entry, chip, 1024, snd_atiixp_proc_read); + snd_info_set_text_ops(entry, chip, snd_atiixp_proc_read); } #else #define snd_atiixp_proc_init(chip) diff --git a/sound/pci/ca0106/ca0106_proc.c b/sound/pci/ca0106/ca0106_proc.c index 63757273bfb..75ca421eb3a 100644 --- a/sound/pci/ca0106/ca0106_proc.c +++ b/sound/pci/ca0106/ca0106_proc.c @@ -431,33 +431,30 @@ int __devinit snd_ca0106_proc_init(struct snd_ca0106 * emu) struct snd_info_entry *entry; if(! snd_card_proc_new(emu->card, "iec958", &entry)) - snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_iec958); + snd_info_set_text_ops(entry, emu, snd_ca0106_proc_iec958); if(! snd_card_proc_new(emu->card, "ca0106_reg32", &entry)) { - snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read32); - entry->c.text.write_size = 64; + snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read32); entry->c.text.write = snd_ca0106_proc_reg_write32; entry->mode |= S_IWUSR; } if(! snd_card_proc_new(emu->card, "ca0106_reg16", &entry)) - snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read16); + snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read16); if(! snd_card_proc_new(emu->card, "ca0106_reg8", &entry)) - snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read8); + snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read8); if(! snd_card_proc_new(emu->card, "ca0106_regs1", &entry)) { - snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read1); - entry->c.text.write_size = 64; + snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read1); entry->c.text.write = snd_ca0106_proc_reg_write; entry->mode |= S_IWUSR; // entry->private_data = emu; } if(! snd_card_proc_new(emu->card, "ca0106_i2c", &entry)) { - snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_i2c_write); - entry->c.text.write_size = 64; + snd_info_set_text_ops(entry, emu, snd_ca0106_proc_i2c_write); entry->c.text.write = snd_ca0106_proc_i2c_write; entry->mode |= S_IWUSR; // entry->private_data = emu; } if(! snd_card_proc_new(emu->card, "ca0106_regs2", &entry)) - snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read2); + snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read2); return 0; } diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index e5ce2dabd08..42ca92be18f 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c @@ -2602,7 +2602,7 @@ static void __devinit snd_cmipci_proc_init(struct cmipci *cm) struct snd_info_entry *entry; if (! snd_card_proc_new(cm->card, "cmipci", &entry)) - snd_info_set_text_ops(entry, cm, 1024, snd_cmipci_proc_read); + snd_info_set_text_ops(entry, cm, snd_cmipci_proc_read); } #else /* !CONFIG_PROC_FS */ static inline void snd_cmipci_proc_init(struct cmipci *cm) {} diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index b3c94d83450..8c150eab45b 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c @@ -1184,7 +1184,7 @@ static void __devinit snd_cs4281_proc_init(struct cs4281 * chip) struct snd_info_entry *entry; if (! snd_card_proc_new(chip->card, "cs4281", &entry)) - snd_info_set_text_ops(entry, chip, 1024, snd_cs4281_proc_read); + snd_info_set_text_ops(entry, chip, snd_cs4281_proc_read); if (! snd_card_proc_new(chip->card, "cs4281_BA0", &entry)) { entry->content = SNDRV_INFO_CONTENT_DATA; entry->private_data = chip; diff --git a/sound/pci/cs46xx/dsp_spos.c b/sound/pci/cs46xx/dsp_spos.c index f407d2a5ce3..5c9711c0265 100644 --- a/sound/pci/cs46xx/dsp_spos.c +++ b/sound/pci/cs46xx/dsp_spos.c @@ -767,7 +767,6 @@ int cs46xx_dsp_proc_init (struct snd_card *card, struct snd_cs46xx *chip) if ((entry = snd_info_create_card_entry(card, "dsp", card->proc_root)) != NULL) { entry->content = SNDRV_INFO_CONTENT_TEXT; entry->mode = S_IFDIR | S_IRUGO | S_IXUGO; - entry->c.text.read_size = 512; if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); @@ -784,7 +783,6 @@ int cs46xx_dsp_proc_init (struct snd_card *card, struct snd_cs46xx *chip) entry->content = SNDRV_INFO_CONTENT_TEXT; entry->private_data = chip; entry->mode = S_IFREG | S_IRUGO | S_IWUSR; - entry->c.text.read_size = 512; entry->c.text.read = cs46xx_dsp_proc_symbol_table_read; if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); @@ -797,7 +795,6 @@ int cs46xx_dsp_proc_init (struct snd_card *card, struct snd_cs46xx *chip) entry->content = SNDRV_INFO_CONTENT_TEXT; entry->private_data = chip; entry->mode = S_IFREG | S_IRUGO | S_IWUSR; - entry->c.text.read_size = 512; entry->c.text.read = cs46xx_dsp_proc_modules_read; if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); @@ -810,7 +807,6 @@ int cs46xx_dsp_proc_init (struct snd_card *card, struct snd_cs46xx *chip) entry->content = SNDRV_INFO_CONTENT_TEXT; entry->private_data = chip; entry->mode = S_IFREG | S_IRUGO | S_IWUSR; - entry->c.text.read_size = 512; entry->c.text.read = cs46xx_dsp_proc_parameter_dump_read; if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); @@ -823,7 +819,6 @@ int cs46xx_dsp_proc_init (struct snd_card *card, struct snd_cs46xx *chip) entry->content = SNDRV_INFO_CONTENT_TEXT; entry->private_data = chip; entry->mode = S_IFREG | S_IRUGO | S_IWUSR; - entry->c.text.read_size = 512; entry->c.text.read = cs46xx_dsp_proc_sample_dump_read; if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); @@ -836,7 +831,6 @@ int cs46xx_dsp_proc_init (struct snd_card *card, struct snd_cs46xx *chip) entry->content = SNDRV_INFO_CONTENT_TEXT; entry->private_data = chip; entry->mode = S_IFREG | S_IRUGO | S_IWUSR; - entry->c.text.read_size = 512; entry->c.text.read = cs46xx_dsp_proc_task_tree_read; if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); @@ -849,7 +843,6 @@ int cs46xx_dsp_proc_init (struct snd_card *card, struct snd_cs46xx *chip) entry->content = SNDRV_INFO_CONTENT_TEXT; entry->private_data = chip; entry->mode = S_IFREG | S_IRUGO | S_IWUSR; - entry->c.text.read_size = 1024; entry->c.text.read = cs46xx_dsp_proc_scb_read; if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); diff --git a/sound/pci/cs46xx/dsp_spos_scb_lib.c b/sound/pci/cs46xx/dsp_spos_scb_lib.c index 2c4ee45fe10..3844d18af19 100644 --- a/sound/pci/cs46xx/dsp_spos_scb_lib.c +++ b/sound/pci/cs46xx/dsp_spos_scb_lib.c @@ -267,7 +267,6 @@ void cs46xx_dsp_proc_register_scb_desc (struct snd_cs46xx *chip, entry->private_data = scb_info; entry->mode = S_IFREG | S_IRUGO | S_IWUSR; - entry->c.text.read_size = 512; entry->c.text.read = cs46xx_dsp_proc_scb_info_read; if (snd_info_register(entry) < 0) { diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c index d51290c1816..0fb27e4be07 100644 --- a/sound/pci/emu10k1/emu10k1x.c +++ b/sound/pci/emu10k1/emu10k1x.c @@ -1055,8 +1055,7 @@ static int __devinit snd_emu10k1x_proc_init(struct emu10k1x * emu) struct snd_info_entry *entry; if(! snd_card_proc_new(emu->card, "emu10k1x_regs", &entry)) { - snd_info_set_text_ops(entry, emu, 1024, snd_emu10k1x_proc_reg_read); - entry->c.text.write_size = 64; + snd_info_set_text_ops(entry, emu, snd_emu10k1x_proc_reg_read); entry->c.text.write = snd_emu10k1x_proc_reg_write; entry->mode |= S_IWUSR; entry->private_data = emu; diff --git a/sound/pci/emu10k1/emuproc.c b/sound/pci/emu10k1/emuproc.c index 90f1c52703a..b939e03aaed 100644 --- a/sound/pci/emu10k1/emuproc.c +++ b/sound/pci/emu10k1/emuproc.c @@ -532,57 +532,51 @@ int __devinit snd_emu10k1_proc_init(struct snd_emu10k1 * emu) struct snd_info_entry *entry; #ifdef CONFIG_SND_DEBUG if (! snd_card_proc_new(emu->card, "io_regs", &entry)) { - snd_info_set_text_ops(entry, emu, 1024, snd_emu_proc_io_reg_read); - entry->c.text.write_size = 64; + snd_info_set_text_ops(entry, emu, snd_emu_proc_io_reg_read); entry->c.text.write = snd_emu_proc_io_reg_write; entry->mode |= S_IWUSR; } if (! snd_card_proc_new(emu->card, "ptr_regs00a", &entry)) { - snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read00a); - entry->c.text.write_size = 64; + snd_info_set_text_ops(entry, emu, snd_emu_proc_ptr_reg_read00a); entry->c.text.write = snd_emu_proc_ptr_reg_write00; entry->mode |= S_IWUSR; } if (! snd_card_proc_new(emu->card, "ptr_regs00b", &entry)) { - snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read00b); - entry->c.text.write_size = 64; + snd_info_set_text_ops(entry, emu, snd_emu_proc_ptr_reg_read00b); entry->c.text.write = snd_emu_proc_ptr_reg_write00; entry->mode |= S_IWUSR; } if (! snd_card_proc_new(emu->card, "ptr_regs20a", &entry)) { - snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read20a); - entry->c.text.write_size = 64; + snd_info_set_text_ops(entry, emu, snd_emu_proc_ptr_reg_read20a); entry->c.text.write = snd_emu_proc_ptr_reg_write20; entry->mode |= S_IWUSR; } if (! snd_card_proc_new(emu->card, "ptr_regs20b", &entry)) { - snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read20b); - entry->c.text.write_size = 64; + snd_info_set_text_ops(entry, emu, snd_emu_proc_ptr_reg_read20b); entry->c.text.write = snd_emu_proc_ptr_reg_write20; entry->mode |= S_IWUSR; } if (! snd_card_proc_new(emu->card, "ptr_regs20c", &entry)) { - snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read20c); - entry->c.text.write_size = 64; + snd_info_set_text_ops(entry, emu, snd_emu_proc_ptr_reg_read20c); entry->c.text.write = snd_emu_proc_ptr_reg_write20; entry->mode |= S_IWUSR; } #endif if (! snd_card_proc_new(emu->card, "emu10k1", &entry)) - snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_read); + snd_info_set_text_ops(entry, emu, snd_emu10k1_proc_read); if (emu->card_capabilities->emu10k2_chip) { if (! snd_card_proc_new(emu->card, "spdif-in", &entry)) - snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_spdif_read); + snd_info_set_text_ops(entry, emu, snd_emu10k1_proc_spdif_read); } if (emu->card_capabilities->ca0151_chip) { if (! snd_card_proc_new(emu->card, "capture-rates", &entry)) - snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_rates_read); + snd_info_set_text_ops(entry, emu, snd_emu10k1_proc_rates_read); } if (! snd_card_proc_new(emu->card, "voices", &entry)) - snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_voices_read); + snd_info_set_text_ops(entry, emu, snd_emu10k1_proc_voices_read); if (! snd_card_proc_new(emu->card, "fx8010_gpr", &entry)) { entry->content = SNDRV_INFO_CONTENT_DATA; @@ -616,7 +610,6 @@ int __devinit snd_emu10k1_proc_init(struct snd_emu10k1 * emu) entry->content = SNDRV_INFO_CONTENT_TEXT; entry->private_data = emu; entry->mode = S_IFREG | S_IRUGO /*| S_IWUSR*/; - entry->c.text.read_size = 128*1024; entry->c.text.read = snd_emu10k1_proc_acode_read; } return 0; diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index ca9e34e88f6..9d46bbee2a4 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c @@ -1915,7 +1915,7 @@ static void __devinit snd_ensoniq_proc_init(struct ensoniq * ensoniq) struct snd_info_entry *entry; if (! snd_card_proc_new(ensoniq->card, "audiopci", &entry)) - snd_info_set_text_ops(entry, ensoniq, 1024, snd_ensoniq_proc_read); + snd_info_set_text_ops(entry, ensoniq, snd_ensoniq_proc_read); } /* diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index ca514a6a587..3db009990c5 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c @@ -318,7 +318,7 @@ int snd_hda_codec_proc_new(struct hda_codec *codec) if (err < 0) return err; - snd_info_set_text_ops(entry, codec, 32 * 1024, print_codec_info); + snd_info_set_text_ops(entry, codec, print_codec_info); return 0; } diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index 2821014b26e..52de85e21b9 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c @@ -1596,7 +1596,7 @@ static void __devinit snd_ice1712_proc_init(struct snd_ice1712 * ice) struct snd_info_entry *entry; if (! snd_card_proc_new(ice->card, "ice1712", &entry)) - snd_info_set_text_ops(entry, ice, 1024, snd_ice1712_proc_read); + snd_info_set_text_ops(entry, ice, snd_ice1712_proc_read); } /* diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index b1c007e022d..1031bcbf706 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c @@ -1293,7 +1293,7 @@ static void __devinit snd_vt1724_proc_init(struct snd_ice1712 * ice) struct snd_info_entry *entry; if (! snd_card_proc_new(ice->card, "ice1724", &entry)) - snd_info_set_text_ops(entry, ice, 1024, snd_vt1724_proc_read); + snd_info_set_text_ops(entry, ice, snd_vt1724_proc_read); } /* diff --git a/sound/pci/ice1712/pontis.c b/sound/pci/ice1712/pontis.c index d23fb3fc213..0efcad9260a 100644 --- a/sound/pci/ice1712/pontis.c +++ b/sound/pci/ice1712/pontis.c @@ -680,9 +680,8 @@ static void wm_proc_init(struct snd_ice1712 *ice) { struct snd_info_entry *entry; if (! snd_card_proc_new(ice->card, "wm_codec", &entry)) { - snd_info_set_text_ops(entry, ice, 1024, wm_proc_regs_read); + snd_info_set_text_ops(entry, ice, wm_proc_regs_read); entry->mode |= S_IWUSR; - entry->c.text.write_size = 1024; entry->c.text.write = wm_proc_regs_write; } } @@ -705,9 +704,8 @@ static void cs_proc_regs_read(struct snd_info_entry *entry, struct snd_info_buff static void cs_proc_init(struct snd_ice1712 *ice) { struct snd_info_entry *entry; - if (! snd_card_proc_new(ice->card, "cs_codec", &entry)) { - snd_info_set_text_ops(entry, ice, 1024, cs_proc_regs_read); - } + if (! snd_card_proc_new(ice->card, "cs_codec", &entry)) + snd_info_set_text_ops(entry, ice, cs_proc_regs_read); } diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 0df7602568e..a4e5b8115a6 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -2645,7 +2645,7 @@ static void __devinit snd_intel8x0_proc_init(struct intel8x0 * chip) struct snd_info_entry *entry; if (! snd_card_proc_new(chip->card, "intel8x0", &entry)) - snd_info_set_text_ops(entry, chip, 1024, snd_intel8x0_proc_read); + snd_info_set_text_ops(entry, chip, snd_intel8x0_proc_read); } #else #define snd_intel8x0_proc_init(x) diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index 720635f0cb8..20acb1a7e92 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c @@ -1092,7 +1092,7 @@ static void __devinit snd_intel8x0m_proc_init(struct intel8x0m * chip) struct snd_info_entry *entry; if (! snd_card_proc_new(chip->card, "intel8x0m", &entry)) - snd_info_set_text_ops(entry, chip, 1024, snd_intel8x0m_proc_read); + snd_info_set_text_ops(entry, chip, snd_intel8x0m_proc_read); } #else /* !CONFIG_PROC_FS */ #define snd_intel8x0m_proc_init(chip) diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c index e39fad1a420..6e97932de34 100644 --- a/sound/pci/korg1212/korg1212.c +++ b/sound/pci/korg1212/korg1212.c @@ -2085,7 +2085,7 @@ static void __devinit snd_korg1212_proc_init(struct snd_korg1212 *korg1212) struct snd_info_entry *entry; if (! snd_card_proc_new(korg1212->card, "korg1212", &entry)) - snd_info_set_text_ops(entry, korg1212, 1024, snd_korg1212_proc_read); + snd_info_set_text_ops(entry, korg1212, snd_korg1212_proc_read); } static int diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index 09cc0786495..366c4a7e65c 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c @@ -1244,7 +1244,6 @@ static void __devinit snd_mixart_proc_init(struct snd_mixart *chip) /* text interface to read perf and temp meters */ if (! snd_card_proc_new(chip->card, "board_info", &entry)) { entry->private_data = chip; - entry->c.text.read_size = 1024; entry->c.text.read = snd_mixart_proc_read; } diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c index dafa2235aba..8198884b51e 100644 --- a/sound/pci/pcxhr/pcxhr.c +++ b/sound/pci/pcxhr/pcxhr.c @@ -1150,9 +1150,9 @@ static void __devinit pcxhr_proc_init(struct snd_pcxhr *chip) struct snd_info_entry *entry; if (! snd_card_proc_new(chip->card, "info", &entry)) - snd_info_set_text_ops(entry, chip, 1024, pcxhr_proc_info); + snd_info_set_text_ops(entry, chip, pcxhr_proc_info); if (! snd_card_proc_new(chip->card, "sync", &entry)) - snd_info_set_text_ops(entry, chip, 1024, pcxhr_proc_sync); + snd_info_set_text_ops(entry, chip, pcxhr_proc_sync); } /* end of proc interface */ diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c index d8cc985d724..c27cd499977 100644 --- a/sound/pci/riptide/riptide.c +++ b/sound/pci/riptide/riptide.c @@ -1992,7 +1992,7 @@ static void __devinit snd_riptide_proc_init(struct snd_riptide *chip) struct snd_info_entry *entry; if (!snd_card_proc_new(chip->card, "riptide", &entry)) - snd_info_set_text_ops(entry, chip, 4096, snd_riptide_proc_read); + snd_info_set_text_ops(entry, chip, snd_riptide_proc_read); } static int __devinit snd_riptide_mixer(struct snd_riptide *chip) diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c index 55b1d4838d9..4dd53bfe030 100644 --- a/sound/pci/rme32.c +++ b/sound/pci/rme32.c @@ -1578,7 +1578,7 @@ static void __devinit snd_rme32_proc_init(struct rme32 * rme32) struct snd_info_entry *entry; if (! snd_card_proc_new(rme32->card, "rme32", &entry)) - snd_info_set_text_ops(entry, rme32, 1024, snd_rme32_proc_read); + snd_info_set_text_ops(entry, rme32, snd_rme32_proc_read); } /* diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c index 3c1bc533d51..75a8b754ef2 100644 --- a/sound/pci/rme96.c +++ b/sound/pci/rme96.c @@ -1805,7 +1805,7 @@ snd_rme96_proc_init(struct rme96 *rme96) struct snd_info_entry *entry; if (! snd_card_proc_new(rme96->card, "rme96", &entry)) - snd_info_set_text_ops(entry, rme96, 1024, snd_rme96_proc_read); + snd_info_set_text_ops(entry, rme96, snd_rme96_proc_read); } /* diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index 61f82f0d5cc..da63a1a1995 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c @@ -3470,7 +3470,7 @@ static void __devinit snd_hdsp_proc_init(struct hdsp *hdsp) struct snd_info_entry *entry; if (! snd_card_proc_new(hdsp->card, "hdsp", &entry)) - snd_info_set_text_ops(entry, hdsp, 1024, snd_hdsp_proc_read); + snd_info_set_text_ops(entry, hdsp, snd_hdsp_proc_read); } static void snd_hdsp_free_buffers(struct hdsp *hdsp) diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 722b9e6ce54..bba1615504d 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -2489,7 +2489,7 @@ static void __devinit snd_hdspm_proc_init(struct hdspm * hdspm) struct snd_info_entry *entry; if (!snd_card_proc_new(hdspm->card, "hdspm", &entry)) - snd_info_set_text_ops(entry, hdspm, 1024, + snd_info_set_text_ops(entry, hdspm, snd_hdspm_proc_read); } diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c index 75d6406303d..ac14b2733f7 100644 --- a/sound/pci/rme9652/rme9652.c +++ b/sound/pci/rme9652/rme9652.c @@ -1787,7 +1787,7 @@ static void __devinit snd_rme9652_proc_init(struct snd_rme9652 *rme9652) struct snd_info_entry *entry; if (! snd_card_proc_new(rme9652->card, "rme9652", &entry)) - snd_info_set_text_ops(entry, rme9652, 1024, snd_rme9652_proc_read); + snd_info_set_text_ops(entry, rme9652, snd_rme9652_proc_read); } static void snd_rme9652_free_buffers(struct snd_rme9652 *rme9652) diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c index 91f8bf3ae9f..a7830417292 100644 --- a/sound/pci/sonicvibes.c +++ b/sound/pci/sonicvibes.c @@ -1144,7 +1144,7 @@ static void __devinit snd_sonicvibes_proc_init(struct sonicvibes * sonic) struct snd_info_entry *entry; if (! snd_card_proc_new(sonic->card, "sonicvibes", &entry)) - snd_info_set_text_ops(entry, sonic, 1024, snd_sonicvibes_proc_read); + snd_info_set_text_ops(entry, sonic, snd_sonicvibes_proc_read); } /* diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c index 850579208e4..d99ed723775 100644 --- a/sound/pci/trident/trident_main.c +++ b/sound/pci/trident/trident_main.c @@ -3338,7 +3338,7 @@ static void __devinit snd_trident_proc_init(struct snd_trident * trident) if (trident->device == TRIDENT_DEVICE_ID_SI7018) s = "sis7018"; if (! snd_card_proc_new(trident->card, s, &entry)) - snd_info_set_text_ops(entry, trident, 1024, snd_trident_proc_read); + snd_info_set_text_ops(entry, trident, snd_trident_proc_read); } static int snd_trident_dev_free(struct snd_device *device) diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 39daf62d2ba..a1b777e79c5 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -2015,7 +2015,7 @@ static void __devinit snd_via82xx_proc_init(struct via82xx *chip) struct snd_info_entry *entry; if (! snd_card_proc_new(chip->card, "via82xx", &entry)) - snd_info_set_text_ops(entry, chip, 1024, snd_via82xx_proc_read); + snd_info_set_text_ops(entry, chip, snd_via82xx_proc_read); } /* diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index ef97e50cd6c..577a2b03759 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c @@ -929,7 +929,7 @@ static void __devinit snd_via82xx_proc_init(struct via82xx_modem *chip) struct snd_info_entry *entry; if (! snd_card_proc_new(chip->card, "via82xx", &entry)) - snd_info_set_text_ops(entry, chip, 1024, snd_via82xx_proc_read); + snd_info_set_text_ops(entry, chip, snd_via82xx_proc_read); } /* diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index 8ac5ab50b5c..f894752523b 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c @@ -1919,7 +1919,7 @@ static int __devinit snd_ymfpci_proc_init(struct snd_card *card, struct snd_ymfp struct snd_info_entry *entry; if (! snd_card_proc_new(card, "ymfpci", &entry)) - snd_info_set_text_ops(entry, chip, 1024, snd_ymfpci_proc_read); + snd_info_set_text_ops(entry, chip, snd_ymfpci_proc_read); return 0; } diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c index bd0d70ff301..1dfe29b863d 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c @@ -144,7 +144,7 @@ static void pdacf_proc_init(struct snd_pdacf *chip) struct snd_info_entry *entry; if (! snd_card_proc_new(chip->card, "pdaudiocf", &entry)) - snd_info_set_text_ops(entry, chip, 1024, pdacf_proc_read); + snd_info_set_text_ops(entry, chip, pdacf_proc_read); } struct snd_pdacf *snd_pdacf_create(struct snd_card *card) diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c index e622d08215c..db6539126d2 100644 --- a/sound/sparc/dbri.c +++ b/sound/sparc/dbri.c @@ -2521,11 +2521,11 @@ void snd_dbri_proc(struct snd_dbri * dbri) struct snd_info_entry *entry; if (! snd_card_proc_new(dbri->card, "regs", &entry)) - snd_info_set_text_ops(entry, dbri, 1024, dbri_regs_read); + snd_info_set_text_ops(entry, dbri, dbri_regs_read); #ifdef DBRI_DEBUG if (! snd_card_proc_new(dbri->card, "debug", &entry)) { - snd_info_set_text_ops(entry, dbri, 4096, dbri_debug_read); + snd_info_set_text_ops(entry, dbri, dbri_debug_read); entry->mode = S_IFREG | S_IRUGO; /* Readable only. */ } #endif diff --git a/sound/synth/emux/emux_proc.c b/sound/synth/emux/emux_proc.c index 1ba68ce3027..58b9601f3ad 100644 --- a/sound/synth/emux/emux_proc.c +++ b/sound/synth/emux/emux_proc.c @@ -119,7 +119,6 @@ void snd_emux_proc_init(struct snd_emux *emu, struct snd_card *card, int device) entry->content = SNDRV_INFO_CONTENT_TEXT; entry->private_data = emu; - entry->c.text.read_size = 1024; entry->c.text.read = snd_emux_proc_info_read; if (snd_info_register(entry) < 0) snd_info_free_entry(entry); diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 4e614ac39f2..8100516e1f7 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -2138,7 +2138,7 @@ static void proc_pcm_format_add(struct snd_usb_stream *stream) sprintf(name, "stream%d", stream->pcm_index); if (! snd_card_proc_new(card, name, &entry)) - snd_info_set_text_ops(entry, stream, 1024, proc_pcm_format_read); + snd_info_set_text_ops(entry, stream, proc_pcm_format_read); } #else @@ -3197,9 +3197,9 @@ static void snd_usb_audio_create_proc(struct snd_usb_audio *chip) { struct snd_info_entry *entry; if (! snd_card_proc_new(chip->card, "usbbus", &entry)) - snd_info_set_text_ops(entry, chip, 1024, proc_audio_usbbus_read); + snd_info_set_text_ops(entry, chip, proc_audio_usbbus_read); if (! snd_card_proc_new(chip->card, "usbid", &entry)) - snd_info_set_text_ops(entry, chip, 1024, proc_audio_usbid_read); + snd_info_set_text_ops(entry, chip, proc_audio_usbid_read); } /* diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c index ce86283ee0f..ab921aa9d77 100644 --- a/sound/usb/usbmixer.c +++ b/sound/usb/usbmixer.c @@ -1998,7 +1998,7 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif) if ((err = snd_audigy2nx_controls_create(mixer)) < 0) goto _error; if (!snd_card_proc_new(chip->card, "audigy2nx", &entry)) - snd_info_set_text_ops(entry, mixer, 1024, + snd_info_set_text_ops(entry, mixer, snd_audigy2nx_proc_read); } -- cgit v1.2.3 From d689e34b524b69c111db0b7c844d71c8e1a53b15 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 28 Apr 2006 15:13:41 +0200 Subject: [ALSA] Remove spinlocks around proc prints Don't lock during showing proc read. snd_iprintf() might sleep. Signed-off-by: Takashi Iwai --- sound/core/pcm.c | 6 ------ sound/core/timer.c | 2 -- 2 files changed, 8 deletions(-) diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 08223783cfa..4f5204175d3 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -351,10 +351,8 @@ static void snd_pcm_substream_proc_hw_params_read(struct snd_info_entry *entry, snd_iprintf(buffer, "closed\n"); return; } - snd_pcm_stream_lock_irq(substream); if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { snd_iprintf(buffer, "no setup\n"); - snd_pcm_stream_unlock_irq(substream); return; } snd_iprintf(buffer, "access: %s\n", snd_pcm_access_name(runtime->access)); @@ -375,7 +373,6 @@ static void snd_pcm_substream_proc_hw_params_read(struct snd_info_entry *entry, snd_iprintf(buffer, "OSS period frames: %lu\n", (unsigned long)runtime->oss.period_frames); } #endif - snd_pcm_stream_unlock_irq(substream); } static void snd_pcm_substream_proc_sw_params_read(struct snd_info_entry *entry, @@ -387,10 +384,8 @@ static void snd_pcm_substream_proc_sw_params_read(struct snd_info_entry *entry, snd_iprintf(buffer, "closed\n"); return; } - snd_pcm_stream_lock_irq(substream); if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { snd_iprintf(buffer, "no setup\n"); - snd_pcm_stream_unlock_irq(substream); return; } snd_iprintf(buffer, "tstamp_mode: %s\n", snd_pcm_tstamp_mode_name(runtime->tstamp_mode)); @@ -403,7 +398,6 @@ static void snd_pcm_substream_proc_sw_params_read(struct snd_info_entry *entry, snd_iprintf(buffer, "silence_threshold: %lu\n", runtime->silence_threshold); snd_iprintf(buffer, "silence_size: %lu\n", runtime->silence_size); snd_iprintf(buffer, "boundary: %lu\n", runtime->boundary); - snd_pcm_stream_unlock_irq(substream); } static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry, diff --git a/sound/core/timer.c b/sound/core/timer.c index 9a1e51c7c23..e37eab74572 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -1095,7 +1095,6 @@ static void snd_timer_proc_read(struct snd_info_entry *entry, if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE) snd_iprintf(buffer, " SLAVE"); snd_iprintf(buffer, "\n"); - spin_lock_irqsave(&timer->lock, flags); list_for_each(q, &timer->open_list_head) { ti = list_entry(q, struct snd_timer_instance, open_list); snd_iprintf(buffer, " Client %s : %s\n", @@ -1104,7 +1103,6 @@ static void snd_timer_proc_read(struct snd_info_entry *entry, SNDRV_TIMER_IFLG_RUNNING) ? "running" : "stopped"); } - spin_unlock_irqrestore(&timer->lock, flags); } mutex_unlock(®ister_mutex); } -- cgit v1.2.3 From f001c3acf64b8ca18fe40af592629abb261b321e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 28 Apr 2006 15:13:41 +0200 Subject: [ALSA] Insert might_sleep() in snd_iprintf() Inserted might_sleep() in snd_iprintf() for sanity check. Signed-off-by: Takashi Iwai --- sound/core/info.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/core/info.c b/sound/core/info.c index 86366839c4b..4188f76add7 100644 --- a/sound/core/info.c +++ b/sound/core/info.c @@ -114,6 +114,7 @@ int snd_iprintf(struct snd_info_buffer *buffer, char *fmt,...) int len, res; int err = 0; + might_sleep(); if (buffer->stop || buffer->error) return 0; len = buffer->len - buffer->size; -- cgit v1.2.3 From 0df63e44c3e315ec0fe427ae62558231864108bd Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 28 Apr 2006 15:13:41 +0200 Subject: [ALSA] Add O_APPEND flag support to PCM Added O_APPEND flag support to PCM to enable shared substreams among multiple processes. This mechanism is used by dmix and dsnoop plugins. Signed-off-by: Takashi Iwai --- include/sound/asound.h | 2 +- include/sound/pcm.h | 5 ++- sound/core/oss/pcm_oss.c | 17 +++++---- sound/core/pcm.c | 25 ++++++++++++- sound/core/pcm_compat.c | 4 +- sound/core/pcm_lib.c | 8 ++-- sound/core/pcm_native.c | 81 ++++++++++++++++++++++++++++------------- sound/usb/usx2y/usx2yhwdeppcm.c | 2 +- 8 files changed, 99 insertions(+), 45 deletions(-) diff --git a/include/sound/asound.h b/include/sound/asound.h index 9cc021c7ee1..41885f48ad9 100644 --- a/include/sound/asound.h +++ b/include/sound/asound.h @@ -137,7 +137,7 @@ enum { * * *****************************************************************************/ -#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 7) +#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 8) typedef unsigned long snd_pcm_uframes_t; typedef signed long snd_pcm_sframes_t; diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 998bacefc8f..cebf0310a8d 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -368,7 +368,8 @@ struct snd_pcm_substream { struct snd_pcm_group *group; /* pointer to current group */ /* -- assigned files -- */ void *file; - struct file *ffile; + int ref_count; + unsigned int f_flags; void (*pcm_release)(struct snd_pcm_substream *); #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) /* -- OSS things -- */ @@ -387,7 +388,7 @@ struct snd_pcm_substream { unsigned int hw_opened: 1; }; -#define SUBSTREAM_BUSY(substream) ((substream)->file != NULL) +#define SUBSTREAM_BUSY(substream) ((substream)->ref_count > 0) struct snd_pcm_str { diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index d8b7416ee00..9803a6ce3d4 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -1331,7 +1331,7 @@ static ssize_t snd_pcm_oss_write1(struct snd_pcm_substream *substream, const cha if (runtime->oss.period_ptr == 0 || runtime->oss.period_ptr == runtime->oss.buffer_used) runtime->oss.buffer_used = 0; - else if ((substream->ffile->f_flags & O_NONBLOCK) != 0) + else if ((substream->f_flags & O_NONBLOCK) != 0) return xfer > 0 ? xfer : -EAGAIN; } } else { @@ -1344,7 +1344,7 @@ static ssize_t snd_pcm_oss_write1(struct snd_pcm_substream *substream, const cha buf += tmp; bytes -= tmp; xfer += tmp; - if ((substream->ffile->f_flags & O_NONBLOCK) != 0 && + if ((substream->f_flags & O_NONBLOCK) != 0 && tmp != runtime->oss.period_bytes) break; } @@ -1582,10 +1582,10 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file) * finish sync: drain the buffer */ __direct: - saved_f_flags = substream->ffile->f_flags; - substream->ffile->f_flags &= ~O_NONBLOCK; + saved_f_flags = substream->f_flags; + substream->f_flags &= ~O_NONBLOCK; err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL); - substream->ffile->f_flags = saved_f_flags; + substream->f_flags = saved_f_flags; if (err < 0) return err; runtime->oss.prepare = 1; @@ -2164,9 +2164,9 @@ static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream, substream->oss.oss = 1; substream->oss.setup = *setup; if (setup->nonblock) - substream->ffile->f_flags |= O_NONBLOCK; + substream->f_flags |= O_NONBLOCK; else if (setup->block) - substream->ffile->f_flags &= ~O_NONBLOCK; + substream->f_flags &= ~O_NONBLOCK; runtime = substream->runtime; runtime->oss.params = 1; runtime->oss.trigger = 1; @@ -2223,6 +2223,7 @@ static int snd_pcm_oss_open_file(struct file *file, (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX)) f_mode = FMODE_WRITE; + file->f_flags &= ~O_APPEND; for (idx = 0; idx < 2; idx++) { if (setup[idx].disable) continue; @@ -2540,6 +2541,7 @@ static ssize_t snd_pcm_oss_read(struct file *file, char __user *buf, size_t coun substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; if (substream == NULL) return -ENXIO; + substream->f_flags = file->f_flags & O_NONBLOCK; #ifndef OSS_DEBUG return snd_pcm_oss_read1(substream, buf, count); #else @@ -2561,6 +2563,7 @@ static ssize_t snd_pcm_oss_write(struct file *file, const char __user *buf, size substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; if (substream == NULL) return -ENXIO; + substream->f_flags = file->f_flags & O_NONBLOCK; result = snd_pcm_oss_write1(substream, buf, count); #ifdef OSS_DEBUG printk("pcm_oss: write %li bytes (wrote %li bytes)\n", (long)count, (long)result); diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 4f5204175d3..8136be2e606 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -829,6 +829,26 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, return -EINVAL; } + if (file->f_flags & O_APPEND) { + if (prefer_subdevice < 0) { + if (pstr->substream_count > 1) + return -EINVAL; /* must be unique */ + substream = pstr->substream; + } else { + for (substream = pstr->substream; substream; + substream = substream->next) + if (substream->number == prefer_subdevice) + break; + } + if (! substream) + return -ENODEV; + if (! SUBSTREAM_BUSY(substream)) + return -EBADFD; + substream->ref_count++; + *rsubstream = substream; + return 0; + } + if (prefer_subdevice >= 0) { for (substream = pstr->substream; substream; substream = substream->next) if (!SUBSTREAM_BUSY(substream) && substream->number == prefer_subdevice) @@ -873,7 +893,8 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, substream->runtime = runtime; substream->private_data = pcm->private_data; - substream->ffile = file; + substream->ref_count = 1; + substream->f_flags = file->f_flags; pstr->substream_opened++; *rsubstream = substream; return 0; @@ -882,7 +903,7 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, void snd_pcm_detach_substream(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime; - substream->file = NULL; + runtime = substream->runtime; snd_assert(runtime != NULL, return); if (runtime->private_free != NULL) diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c index e5133033de5..2b8aab6fd6c 100644 --- a/sound/core/pcm_compat.c +++ b/sound/core/pcm_compat.c @@ -497,9 +497,9 @@ static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned l case SNDRV_PCM_IOCTL_LINK: case SNDRV_PCM_IOCTL_UNLINK: if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - return snd_pcm_playback_ioctl1(substream, cmd, argp); + return snd_pcm_playback_ioctl1(file, substream, cmd, argp); else - return snd_pcm_capture_ioctl1(substream, cmd, argp); + return snd_pcm_capture_ioctl1(file, substream, cmd, argp); case SNDRV_PCM_IOCTL_HW_REFINE32: return snd_pcm_ioctl_hw_params_compat(substream, 1, argp); case SNDRV_PCM_IOCTL_HW_PARAMS32: diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index a21aa0050e4..0bb142a2853 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -1782,7 +1782,7 @@ snd_pcm_sframes_t snd_pcm_lib_write(struct snd_pcm_substream *substream, const v if (runtime->status->state == SNDRV_PCM_STATE_OPEN) return -EBADFD; - nonblock = !!(substream->ffile->f_flags & O_NONBLOCK); + nonblock = !!(substream->f_flags & O_NONBLOCK); if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED && runtime->channels > 1) @@ -1847,7 +1847,7 @@ snd_pcm_sframes_t snd_pcm_lib_writev(struct snd_pcm_substream *substream, if (runtime->status->state == SNDRV_PCM_STATE_OPEN) return -EBADFD; - nonblock = !!(substream->ffile->f_flags & O_NONBLOCK); + nonblock = !!(substream->f_flags & O_NONBLOCK); if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) return -EINVAL; @@ -2059,7 +2059,7 @@ snd_pcm_sframes_t snd_pcm_lib_read(struct snd_pcm_substream *substream, void __u if (runtime->status->state == SNDRV_PCM_STATE_OPEN) return -EBADFD; - nonblock = !!(substream->ffile->f_flags & O_NONBLOCK); + nonblock = !!(substream->f_flags & O_NONBLOCK); if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED) return -EINVAL; return snd_pcm_lib_read1(substream, (unsigned long)buf, size, nonblock, snd_pcm_lib_read_transfer); @@ -2118,7 +2118,7 @@ snd_pcm_sframes_t snd_pcm_lib_readv(struct snd_pcm_substream *substream, if (runtime->status->state == SNDRV_PCM_STATE_OPEN) return -EBADFD; - nonblock = !!(substream->ffile->f_flags & O_NONBLOCK); + nonblock = !!(substream->f_flags & O_NONBLOCK); if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) return -EINVAL; return snd_pcm_lib_read1(substream, (unsigned long)bufs, frames, nonblock, snd_pcm_lib_readv_transfer); diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 7b5729c4b21..36d6765618a 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -1284,13 +1284,16 @@ static int snd_pcm_reset(struct snd_pcm_substream *substream) /* * prepare ioctl */ -static int snd_pcm_pre_prepare(struct snd_pcm_substream *substream, int state) +/* we use the second argument for updating f_flags */ +static int snd_pcm_pre_prepare(struct snd_pcm_substream *substream, + int f_flags) { struct snd_pcm_runtime *runtime = substream->runtime; if (runtime->status->state == SNDRV_PCM_STATE_OPEN) return -EBADFD; if (snd_pcm_running(substream)) return -EBUSY; + substream->f_flags = f_flags; return 0; } @@ -1319,17 +1322,26 @@ static struct action_ops snd_pcm_action_prepare = { /** * snd_pcm_prepare * @substream: the PCM substream instance + * @file: file to refer f_flags * * Prepare the PCM substream to be triggerable. */ -static int snd_pcm_prepare(struct snd_pcm_substream *substream) +static int snd_pcm_prepare(struct snd_pcm_substream *substream, + struct file *file) { int res; struct snd_card *card = substream->pcm->card; + int f_flags; + + if (file) + f_flags = file->f_flags; + else + f_flags = substream->f_flags; snd_power_lock(card); if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0)) >= 0) - res = snd_pcm_action_nonatomic(&snd_pcm_action_prepare, substream, 0); + res = snd_pcm_action_nonatomic(&snd_pcm_action_prepare, + substream, f_flags); snd_power_unlock(card); return res; } @@ -1340,7 +1352,7 @@ static int snd_pcm_prepare(struct snd_pcm_substream *substream) static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream, int state) { - if (substream->ffile->f_flags & O_NONBLOCK) + if (substream->f_flags & O_NONBLOCK) return -EAGAIN; substream->runtime->trigger_master = substream; return 0; @@ -2015,6 +2027,10 @@ static void pcm_release_private(struct snd_pcm_substream *substream) void snd_pcm_release_substream(struct snd_pcm_substream *substream) { + substream->ref_count--; + if (substream->ref_count > 0) + return; + snd_pcm_drop(substream); if (substream->hw_opened) { if (substream->ops->hw_free != NULL) @@ -2041,6 +2057,11 @@ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, err = snd_pcm_attach_substream(pcm, stream, file, &substream); if (err < 0) return err; + if (substream->ref_count > 1) { + *rsubstream = substream; + return 0; + } + substream->no_mmap_ctrl = 0; err = snd_pcm_hw_constraints_init(substream); if (err < 0) { @@ -2086,17 +2107,20 @@ static int snd_pcm_open_file(struct file *file, if (err < 0) return err; - pcm_file = kzalloc(sizeof(*pcm_file), GFP_KERNEL); - if (pcm_file == NULL) { - snd_pcm_release_substream(substream); - return -ENOMEM; + if (substream->ref_count > 1) + pcm_file = substream->file; + else { + pcm_file = kzalloc(sizeof(*pcm_file), GFP_KERNEL); + if (pcm_file == NULL) { + snd_pcm_release_substream(substream); + return -ENOMEM; + } + str = substream->pstr; + substream->file = pcm_file; + substream->pcm_release = pcm_release_private; + pcm_file->substream = substream; + snd_pcm_add_file(str, pcm_file); } - str = substream->pstr; - substream->file = pcm_file; - substream->pcm_release = pcm_release_private; - pcm_file->substream = substream; - snd_pcm_add_file(str, pcm_file); - file->private_data = pcm_file; *rpcm_file = pcm_file; return 0; @@ -2506,7 +2530,8 @@ static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream, return 0; } -static int snd_pcm_common_ioctl1(struct snd_pcm_substream *substream, +static int snd_pcm_common_ioctl1(struct file *file, + struct snd_pcm_substream *substream, unsigned int cmd, void __user *arg) { snd_assert(substream != NULL, return -ENXIO); @@ -2531,7 +2556,7 @@ static int snd_pcm_common_ioctl1(struct snd_pcm_substream *substream, case SNDRV_PCM_IOCTL_CHANNEL_INFO: return snd_pcm_channel_info_user(substream, arg); case SNDRV_PCM_IOCTL_PREPARE: - return snd_pcm_prepare(substream); + return snd_pcm_prepare(substream, file); case SNDRV_PCM_IOCTL_RESET: return snd_pcm_reset(substream); case SNDRV_PCM_IOCTL_START: @@ -2573,7 +2598,8 @@ static int snd_pcm_common_ioctl1(struct snd_pcm_substream *substream, return -ENOTTY; } -static int snd_pcm_playback_ioctl1(struct snd_pcm_substream *substream, +static int snd_pcm_playback_ioctl1(struct file *file, + struct snd_pcm_substream *substream, unsigned int cmd, void __user *arg) { snd_assert(substream != NULL, return -ENXIO); @@ -2649,10 +2675,11 @@ static int snd_pcm_playback_ioctl1(struct snd_pcm_substream *substream, return result < 0 ? result : 0; } } - return snd_pcm_common_ioctl1(substream, cmd, arg); + return snd_pcm_common_ioctl1(file, substream, cmd, arg); } -static int snd_pcm_capture_ioctl1(struct snd_pcm_substream *substream, +static int snd_pcm_capture_ioctl1(struct file *file, + struct snd_pcm_substream *substream, unsigned int cmd, void __user *arg) { snd_assert(substream != NULL, return -ENXIO); @@ -2728,7 +2755,7 @@ static int snd_pcm_capture_ioctl1(struct snd_pcm_substream *substream, return result < 0 ? result : 0; } } - return snd_pcm_common_ioctl1(substream, cmd, arg); + return snd_pcm_common_ioctl1(file, substream, cmd, arg); } static long snd_pcm_playback_ioctl(struct file *file, unsigned int cmd, @@ -2741,7 +2768,8 @@ static long snd_pcm_playback_ioctl(struct file *file, unsigned int cmd, if (((cmd >> 8) & 0xff) != 'A') return -ENOTTY; - return snd_pcm_playback_ioctl1(pcm_file->substream, cmd, (void __user *)arg); + return snd_pcm_playback_ioctl1(file, pcm_file->substream, cmd, + (void __user *)arg); } static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd, @@ -2754,7 +2782,8 @@ static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd, if (((cmd >> 8) & 0xff) != 'A') return -ENOTTY; - return snd_pcm_capture_ioctl1(pcm_file->substream, cmd, (void __user *)arg); + return snd_pcm_capture_ioctl1(file, pcm_file->substream, cmd, + (void __user *)arg); } int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, @@ -2766,12 +2795,12 @@ int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, fs = snd_enter_user(); switch (substream->stream) { case SNDRV_PCM_STREAM_PLAYBACK: - result = snd_pcm_playback_ioctl1(substream, - cmd, (void __user *)arg); + result = snd_pcm_playback_ioctl1(NULL, substream, cmd, + (void __user *)arg); break; case SNDRV_PCM_STREAM_CAPTURE: - result = snd_pcm_capture_ioctl1(substream, - cmd, (void __user *)arg); + result = snd_pcm_capture_ioctl1(NULL, substream, cmd, + (void __user *)arg); break; default: result = -EINVAL; diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c index fe67a92e2a1..88b72b52590 100644 --- a/sound/usb/usx2y/usx2yhwdeppcm.c +++ b/sound/usb/usx2y/usx2yhwdeppcm.c @@ -632,7 +632,7 @@ static int usX2Y_pcms_lock_check(struct snd_card *card) for (s = 0; s < 2; ++s) { struct snd_pcm_substream *substream; substream = pcm->streams[s].substream; - if (substream && substream->ffile != NULL) + if (SUBSTREAM_BUSY(substream)) err = -EBUSY; } } -- cgit v1.2.3 From 9c323fcbc51493f79f9700cb20830d0857c72d99 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 28 Apr 2006 15:13:41 +0200 Subject: [ALSA] Fix mmap_count with O_APPEND opened streams Move mmap_count to snd_pcm_substream instead of runtime struct so that multiplly opened substreams via O_APPEND can be handled correctly. Signed-off-by: Takashi Iwai --- include/sound/pcm.h | 6 +++--- sound/core/oss/pcm_oss.c | 27 ++++++++++++++------------- sound/core/pcm.c | 2 +- sound/core/pcm_native.c | 10 +++++----- 4 files changed, 23 insertions(+), 22 deletions(-) diff --git a/include/sound/pcm.h b/include/sound/pcm.h index cebf0310a8d..f84d84993a3 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -300,7 +300,6 @@ struct snd_pcm_runtime { /* -- mmap -- */ volatile struct snd_pcm_mmap_status *status; volatile struct snd_pcm_mmap_control *control; - atomic_t mmap_count; /* -- locking / scheduling -- */ wait_queue_head_t sleep; @@ -369,6 +368,7 @@ struct snd_pcm_substream { /* -- assigned files -- */ void *file; int ref_count; + atomic_t mmap_count; unsigned int f_flags; void (*pcm_release)(struct snd_pcm_substream *); #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) @@ -972,13 +972,13 @@ struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, unsigne static inline void snd_pcm_mmap_data_open(struct vm_area_struct *area) { struct snd_pcm_substream *substream = (struct snd_pcm_substream *)area->vm_private_data; - atomic_inc(&substream->runtime->mmap_count); + atomic_inc(&substream->mmap_count); } static inline void snd_pcm_mmap_data_close(struct vm_area_struct *area) { struct snd_pcm_substream *substream = (struct snd_pcm_substream *)area->vm_private_data; - atomic_dec(&substream->runtime->mmap_count); + atomic_dec(&substream->mmap_count); } /* mmap for io-memory area */ diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 9803a6ce3d4..4395285aa6a 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -684,7 +684,7 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream, oss_buffer_size = snd_pcm_plug_client_size(substream, snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, NULL)) * oss_frame_size; oss_buffer_size = 1 << ld2(oss_buffer_size); - if (atomic_read(&runtime->mmap_count)) { + if (atomic_read(&substream->mmap_count)) { if (oss_buffer_size > runtime->oss.mmap_bytes) oss_buffer_size = runtime->oss.mmap_bytes; } @@ -819,7 +819,7 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) goto failure; } - if (atomic_read(&runtime->mmap_count)) + if (atomic_read(&substream->mmap_count)) direct = 1; else direct = substream->oss.setup.direct; @@ -828,7 +828,7 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) _snd_pcm_hw_param_setinteger(sparams, SNDRV_PCM_HW_PARAM_PERIODS); _snd_pcm_hw_param_min(sparams, SNDRV_PCM_HW_PARAM_PERIODS, 2, 0); snd_mask_none(&mask); - if (atomic_read(&runtime->mmap_count)) + if (atomic_read(&substream->mmap_count)) snd_mask_set(&mask, SNDRV_PCM_ACCESS_MMAP_INTERLEAVED); else { snd_mask_set(&mask, SNDRV_PCM_ACCESS_RW_INTERLEAVED); @@ -947,7 +947,8 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) } else { sw_params->start_threshold = runtime->boundary; } - if (atomic_read(&runtime->mmap_count) || substream->stream == SNDRV_PCM_STREAM_CAPTURE) + if (atomic_read(&substream->mmap_count) || + substream->stream == SNDRV_PCM_STREAM_CAPTURE) sw_params->stop_threshold = runtime->boundary; else sw_params->stop_threshold = runtime->buffer_size; @@ -957,7 +958,7 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) sw_params->avail_min = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 1 : runtime->period_size; sw_params->xfer_align = 1; - if (atomic_read(&runtime->mmap_count) || + if (atomic_read(&substream->mmap_count) || substream->oss.setup.nosilence) { sw_params->silence_threshold = 0; sw_params->silence_size = 0; @@ -1301,7 +1302,7 @@ static ssize_t snd_pcm_oss_write1(struct snd_pcm_substream *substream, const cha ssize_t tmp; struct snd_pcm_runtime *runtime = substream->runtime; - if (atomic_read(&runtime->mmap_count)) + if (atomic_read(&substream->mmap_count)) return -ENXIO; if ((tmp = snd_pcm_oss_make_ready(substream)) < 0) @@ -1391,7 +1392,7 @@ static ssize_t snd_pcm_oss_read1(struct snd_pcm_substream *substream, char __use ssize_t tmp; struct snd_pcm_runtime *runtime = substream->runtime; - if (atomic_read(&runtime->mmap_count)) + if (atomic_read(&substream->mmap_count)) return -ENXIO; if ((tmp = snd_pcm_oss_make_ready(substream)) < 0) @@ -1521,7 +1522,7 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file) substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; if (substream != NULL) { runtime = substream->runtime; - if (atomic_read(&runtime->mmap_count)) + if (atomic_read(&substream->mmap_count)) goto __direct; if ((err = snd_pcm_oss_make_ready(substream)) < 0) return err; @@ -1690,7 +1691,7 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file) if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) return err; - if (atomic_read(&substream->runtime->mmap_count)) + if (atomic_read(&substream->mmap_count)) direct = 1; else direct = substream->oss.setup.direct; @@ -1900,7 +1901,7 @@ static int snd_pcm_oss_set_trigger(struct snd_pcm_oss_file *pcm_oss_file, int tr if (trigger & PCM_ENABLE_OUTPUT) { if (runtime->oss.trigger) goto _skip1; - if (atomic_read(&psubstream->runtime->mmap_count)) + if (atomic_read(&psubstream->mmap_count)) snd_pcm_oss_simulate_fill(psubstream, runtime->hw_ptr_interrupt); runtime->oss.trigger = 1; runtime->start_threshold = 1; @@ -2018,7 +2019,7 @@ static int snd_pcm_oss_get_ptr(struct snd_pcm_oss_file *pcm_oss_file, int stream if (err < 0) return err; info.ptr = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr % runtime->buffer_size); - if (atomic_read(&runtime->mmap_count)) { + if (atomic_read(&substream->mmap_count)) { snd_pcm_sframes_t n; n = (delay = runtime->hw_ptr_interrupt) - runtime->oss.prev_hw_ptr_interrupt; if (n < 0) @@ -2574,7 +2575,7 @@ static ssize_t snd_pcm_oss_write(struct file *file, const char __user *buf, size static int snd_pcm_oss_playback_ready(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - if (atomic_read(&runtime->mmap_count)) + if (atomic_read(&substream->mmap_count)) return runtime->oss.prev_hw_ptr_interrupt != runtime->hw_ptr_interrupt; else return snd_pcm_playback_avail(runtime) >= runtime->oss.period_frames; @@ -2583,7 +2584,7 @@ static int snd_pcm_oss_playback_ready(struct snd_pcm_substream *substream) static int snd_pcm_oss_capture_ready(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - if (atomic_read(&runtime->mmap_count)) + if (atomic_read(&substream->mmap_count)) return runtime->oss.prev_hw_ptr_interrupt != runtime->hw_ptr_interrupt; else return snd_pcm_capture_avail(runtime) >= runtime->oss.period_frames; diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 8136be2e606..bc00f9b00cb 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -662,6 +662,7 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count) INIT_LIST_HEAD(&substream->self_group.substreams); list_add_tail(&substream->link_list, &substream->self_group.substreams); spin_lock_init(&substream->timer_lock); + atomic_set(&substream->mmap_count, 0); prev = substream; } return 0; @@ -884,7 +885,6 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, memset((void*)runtime->control, 0, size); init_waitqueue_head(&runtime->sleep); - atomic_set(&runtime->mmap_count, 0); init_timer(&runtime->tick_timer); runtime->tick_timer.function = snd_pcm_tick_timer_func; runtime->tick_timer.data = (unsigned long) substream; diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 36d6765618a..a998f88e3f3 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -372,7 +372,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream, #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) if (!substream->oss.oss) #endif - if (atomic_read(&runtime->mmap_count)) + if (atomic_read(&substream->mmap_count)) return -EBADFD; params->rmask = ~0U; @@ -485,7 +485,7 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream) return -EBADFD; } snd_pcm_stream_unlock_irq(substream); - if (atomic_read(&runtime->mmap_count)) + if (atomic_read(&substream->mmap_count)) return -EBADFD; if (substream->ops->hw_free) result = substream->ops->hw_free(substream); @@ -2207,7 +2207,7 @@ static int snd_pcm_release(struct inode *inode, struct file *file) pcm_file = file->private_data; substream = pcm_file->substream; snd_assert(substream != NULL, return -ENXIO); - snd_assert(!atomic_read(&substream->runtime->mmap_count), ); + snd_assert(!atomic_read(&substream->mmap_count), ); pcm = substream->pcm; fasync_helper(-1, file, 0, &substream->runtime->fasync); mutex_lock(&pcm->open_mutex); @@ -3178,7 +3178,7 @@ static int snd_pcm_default_mmap(struct snd_pcm_substream *substream, area->vm_ops = &snd_pcm_vm_ops_data; area->vm_private_data = substream; area->vm_flags |= VM_RESERVED; - atomic_inc(&substream->runtime->mmap_count); + atomic_inc(&substream->mmap_count); return 0; } @@ -3210,7 +3210,7 @@ int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream, (substream->runtime->dma_addr + offset) >> PAGE_SHIFT, size, area->vm_page_prot)) return -EAGAIN; - atomic_inc(&substream->runtime->mmap_count); + atomic_inc(&substream->mmap_count); return 0; } -- cgit v1.2.3 From 170a34605c14a90df5f4a78e0b4ca643be6ef8ba Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 28 Apr 2006 15:29:15 +0200 Subject: [ALSA] Fix compile warning in timer.c Fix a compile warning in timer.c due to unused variables. Signed-off-by: Takashi Iwai --- sound/core/timer.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/core/timer.c b/sound/core/timer.c index e37eab74572..d92f73c2c6b 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -1061,7 +1061,6 @@ static int snd_timer_register_system(void) static void snd_timer_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) { - unsigned long flags; struct snd_timer *timer; struct snd_timer_instance *ti; struct list_head *p, *q; -- cgit v1.2.3 From f4a747f155fe375231196ec3d26fcb6e3675d82f Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Tue, 2 May 2006 15:33:25 +0200 Subject: [ALSA] fix a wrong lock fix a typo in the info locking code Signed-off-by: Clemens Ladisch --- sound/core/info.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/core/info.c b/sound/core/info.c index 4188f76add7..c8eeaea9d69 100644 --- a/sound/core/info.c +++ b/sound/core/info.c @@ -267,7 +267,7 @@ static ssize_t snd_info_entry_write(struct file *file, const char __user *buffer buf = data->wbuffer; if (buf == NULL) return -EIO; - mutex_unlock(&entry->access); + mutex_lock(&entry->access); if (pos + count >= buf->len) { if (resize_info_buffer(buf, pos + count)) { mutex_unlock(&entry->access); -- cgit v1.2.3 From c97f3dd85490e51ba48782dd0c063cdade352c0d Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Tue, 2 May 2006 15:50:05 +0200 Subject: [ALSA] fix port type bits Fix the port information about non-MIDI messages that had wrong values for some OPL3 and EmuX ports. Signed-off-by: Clemens Ladisch --- sound/drivers/opl3/opl3_oss.c | 3 +-- sound/drivers/opl3/opl3_seq.c | 2 +- sound/synth/emux/emux_seq.c | 3 +-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/sound/drivers/opl3/opl3_oss.c b/sound/drivers/opl3/opl3_oss.c index fccf019a6d8..d48f8dee2d9 100644 --- a/sound/drivers/opl3/opl3_oss.c +++ b/sound/drivers/opl3/opl3_oss.c @@ -99,8 +99,7 @@ static int snd_opl3_oss_create_port(struct snd_opl3 * opl3) opl3->oss_chset->port = snd_seq_event_port_attach(opl3->seq_client, &callbacks, SNDRV_SEQ_PORT_CAP_WRITE, SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | - SNDRV_SEQ_PORT_TYPE_MIDI_GM | - SNDRV_SEQ_PORT_TYPE_SYNTH, + SNDRV_SEQ_PORT_TYPE_MIDI_GM, voices, voices, name); if (opl3->oss_chset->port < 0) { diff --git a/sound/drivers/opl3/opl3_seq.c b/sound/drivers/opl3/opl3_seq.c index 57becf34f43..2aece1b1866 100644 --- a/sound/drivers/opl3/opl3_seq.c +++ b/sound/drivers/opl3/opl3_seq.c @@ -203,7 +203,7 @@ static int snd_opl3_synth_create_port(struct snd_opl3 * opl3) SNDRV_SEQ_PORT_CAP_SUBS_WRITE, SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | SNDRV_SEQ_PORT_TYPE_MIDI_GM | - SNDRV_SEQ_PORT_TYPE_SYNTH, + SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE, 16, voices, name); if (opl3->chset->port < 0) { diff --git a/sound/synth/emux/emux_seq.c b/sound/synth/emux/emux_seq.c index 8f00f07701c..58838f7c95f 100644 --- a/sound/synth/emux/emux_seq.c +++ b/sound/synth/emux/emux_seq.c @@ -54,8 +54,7 @@ static struct snd_midi_op emux_ops = { #define DEFAULT_MIDI_TYPE (SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC |\ SNDRV_SEQ_PORT_TYPE_MIDI_GM |\ SNDRV_SEQ_PORT_TYPE_MIDI_GS |\ - SNDRV_SEQ_PORT_TYPE_MIDI_XG |\ - SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE) + SNDRV_SEQ_PORT_TYPE_MIDI_XG) /* * Initialise the EMUX Synth by creating a client and registering -- cgit v1.2.3 From 450047a78f3c35a905576e121abfbee2ccd45993 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Tue, 2 May 2006 16:08:41 +0200 Subject: [ALSA] add more sequencer port type information bits Add four new information flags SNDRV_SEQ_PORT_TYPE_HARDWARE, _SOFTWARE, _SYNTHESIZER, _PORT for sequencer ports. This makes it easier for apps like Rosegarden to make policy decisions based on the port type. Signed-off-by: Clemens Ladisch --- include/sound/asequencer.h | 4 ++++ sound/core/seq/seq_dummy.c | 4 +++- sound/core/seq/seq_midi.c | 4 +++- sound/core/seq/seq_virmidi.c | 4 +++- sound/drivers/opl3/opl3_oss.c | 4 +++- sound/drivers/opl3/opl3_seq.c | 4 +++- sound/drivers/opl4/opl4_seq.c | 4 +++- sound/isa/gus/gus_synth.c | 4 +++- sound/pci/trident/trident_synth.c | 4 +++- sound/synth/emux/emux_seq.c | 4 +++- 10 files changed, 31 insertions(+), 9 deletions(-) diff --git a/include/sound/asequencer.h b/include/sound/asequencer.h index 6691e4aa4ea..3f2f4042a20 100644 --- a/include/sound/asequencer.h +++ b/include/sound/asequencer.h @@ -605,6 +605,10 @@ struct snd_seq_remove_events { #define SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE (1<<11) /* Sampling device (support sample download) */ #define SNDRV_SEQ_PORT_TYPE_SAMPLE (1<<12) /* Sampling device (sample can be downloaded at any time) */ /*...*/ +#define SNDRV_SEQ_PORT_TYPE_HARDWARE (1<<16) /* driver for a hardware device */ +#define SNDRV_SEQ_PORT_TYPE_SOFTWARE (1<<17) /* implemented in software */ +#define SNDRV_SEQ_PORT_TYPE_SYNTHESIZER (1<<18) /* generates sound */ +#define SNDRV_SEQ_PORT_TYPE_PORT (1<<19) /* connects to other device(s) */ #define SNDRV_SEQ_PORT_TYPE_APPLICATION (1<<20) /* application (sequencer/editor) */ /* misc. conditioning flags */ diff --git a/sound/core/seq/seq_dummy.c b/sound/core/seq/seq_dummy.c index 2a283a59ea4..9eb1c744f77 100644 --- a/sound/core/seq/seq_dummy.c +++ b/sound/core/seq/seq_dummy.c @@ -171,7 +171,9 @@ create_port(int idx, int type) pinfo.capability |= SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE; if (duplex) pinfo.capability |= SNDRV_SEQ_PORT_CAP_DUPLEX; - pinfo.type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC; + pinfo.type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC + | SNDRV_SEQ_PORT_TYPE_SOFTWARE + | SNDRV_SEQ_PORT_TYPE_PORT; memset(&pcb, 0, sizeof(pcb)); pcb.owner = THIS_MODULE; pcb.unuse = dummy_unuse; diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c index 3b316da25ef..f873742c653 100644 --- a/sound/core/seq/seq_midi.c +++ b/sound/core/seq/seq_midi.c @@ -376,7 +376,9 @@ snd_seq_midisynth_register_port(struct snd_seq_device *dev) if ((port->capability & (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_READ)) == (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_READ) && info->flags & SNDRV_RAWMIDI_INFO_DUPLEX) port->capability |= SNDRV_SEQ_PORT_CAP_DUPLEX; - port->type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC; + port->type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC + | SNDRV_SEQ_PORT_TYPE_HARDWARE + | SNDRV_SEQ_PORT_TYPE_PORT; port->midi_channels = 16; memset(&pcallbacks, 0, sizeof(pcallbacks)); pcallbacks.owner = THIS_MODULE; diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c index f4edec603b8..0cfa06c6b81 100644 --- a/sound/core/seq/seq_virmidi.c +++ b/sound/core/seq/seq_virmidi.c @@ -390,7 +390,9 @@ static int snd_virmidi_dev_attach_seq(struct snd_virmidi_dev *rdev) pinfo->capability |= SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SYNC_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE; pinfo->capability |= SNDRV_SEQ_PORT_CAP_READ | SNDRV_SEQ_PORT_CAP_SYNC_READ | SNDRV_SEQ_PORT_CAP_SUBS_READ; pinfo->capability |= SNDRV_SEQ_PORT_CAP_DUPLEX; - pinfo->type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC; + pinfo->type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC + | SNDRV_SEQ_PORT_TYPE_SOFTWARE + | SNDRV_SEQ_PORT_TYPE_PORT; pinfo->midi_channels = 16; memset(&pcallbacks, 0, sizeof(pcallbacks)); pcallbacks.owner = THIS_MODULE; diff --git a/sound/drivers/opl3/opl3_oss.c b/sound/drivers/opl3/opl3_oss.c index d48f8dee2d9..5fd3a4c9562 100644 --- a/sound/drivers/opl3/opl3_oss.c +++ b/sound/drivers/opl3/opl3_oss.c @@ -99,7 +99,9 @@ static int snd_opl3_oss_create_port(struct snd_opl3 * opl3) opl3->oss_chset->port = snd_seq_event_port_attach(opl3->seq_client, &callbacks, SNDRV_SEQ_PORT_CAP_WRITE, SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | - SNDRV_SEQ_PORT_TYPE_MIDI_GM, + SNDRV_SEQ_PORT_TYPE_MIDI_GM | + SNDRV_SEQ_PORT_TYPE_HARDWARE | + SNDRV_SEQ_PORT_TYPE_SYNTHESIZER, voices, voices, name); if (opl3->oss_chset->port < 0) { diff --git a/sound/drivers/opl3/opl3_seq.c b/sound/drivers/opl3/opl3_seq.c index 2aece1b1866..96762c9d485 100644 --- a/sound/drivers/opl3/opl3_seq.c +++ b/sound/drivers/opl3/opl3_seq.c @@ -203,7 +203,9 @@ static int snd_opl3_synth_create_port(struct snd_opl3 * opl3) SNDRV_SEQ_PORT_CAP_SUBS_WRITE, SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | SNDRV_SEQ_PORT_TYPE_MIDI_GM | - SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE, + SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE | + SNDRV_SEQ_PORT_TYPE_HARDWARE | + SNDRV_SEQ_PORT_TYPE_SYNTHESIZER, 16, voices, name); if (opl3->chset->port < 0) { diff --git a/sound/drivers/opl4/opl4_seq.c b/sound/drivers/opl4/opl4_seq.c index dc0dcdc6c31..43d8a2bdd28 100644 --- a/sound/drivers/opl4/opl4_seq.c +++ b/sound/drivers/opl4/opl4_seq.c @@ -164,7 +164,9 @@ static int snd_opl4_seq_new_device(struct snd_seq_device *dev) SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE, SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | - SNDRV_SEQ_PORT_TYPE_MIDI_GM, + SNDRV_SEQ_PORT_TYPE_MIDI_GM | + SNDRV_SEQ_PORT_TYPE_HARDWARE | + SNDRV_SEQ_PORT_TYPE_SYNTHESIZER, 16, 24, "OPL4 Wavetable Port"); if (opl4->chset->port < 0) { diff --git a/sound/isa/gus/gus_synth.c b/sound/isa/gus/gus_synth.c index 2767cc187ae..3e4d4d6edd8 100644 --- a/sound/isa/gus/gus_synth.c +++ b/sound/isa/gus/gus_synth.c @@ -194,7 +194,9 @@ static int snd_gus_synth_create_port(struct snd_gus_card * gus, int idx) &callbacks, SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE, SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE | - SNDRV_SEQ_PORT_TYPE_SYNTH, + SNDRV_SEQ_PORT_TYPE_SYNTH | + SNDRV_SEQ_PORT_TYPE_HARDWARE | + SNDRV_SEQ_PORT_TYPE_SYNTHESIZER, 16, 0, name); if (p->chset->port < 0) { diff --git a/sound/pci/trident/trident_synth.c b/sound/pci/trident/trident_synth.c index cc7af8bc55a..9b7dee84743 100644 --- a/sound/pci/trident/trident_synth.c +++ b/sound/pci/trident/trident_synth.c @@ -914,7 +914,9 @@ static int snd_trident_synth_create_port(struct snd_trident * trident, int idx) &callbacks, SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE, SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE | - SNDRV_SEQ_PORT_TYPE_SYNTH, + SNDRV_SEQ_PORT_TYPE_SYNTH | + SNDRV_SEQ_PORT_TYPE_HARDWARE | + SNDRV_SEQ_PORT_TYPE_SYNTHESIZER, 16, 0, name); if (p->chset->port < 0) { diff --git a/sound/synth/emux/emux_seq.c b/sound/synth/emux/emux_seq.c index 58838f7c95f..d176cc01742 100644 --- a/sound/synth/emux/emux_seq.c +++ b/sound/synth/emux/emux_seq.c @@ -54,7 +54,9 @@ static struct snd_midi_op emux_ops = { #define DEFAULT_MIDI_TYPE (SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC |\ SNDRV_SEQ_PORT_TYPE_MIDI_GM |\ SNDRV_SEQ_PORT_TYPE_MIDI_GS |\ - SNDRV_SEQ_PORT_TYPE_MIDI_XG) + SNDRV_SEQ_PORT_TYPE_MIDI_XG |\ + SNDRV_SEQ_PORT_TYPE_HARDWARE |\ + SNDRV_SEQ_PORT_TYPE_SYNTHESIZER) /* * Initialise the EMUX Synth by creating a client and registering -- cgit v1.2.3 From a7b928ac5fcd8e1b5c7c69926d8845b1d0500af3 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Tue, 2 May 2006 16:22:12 +0200 Subject: [ALSA] rawmidi: add get_port_info callback for sequencer information flags Add a get_port_info callback to the snd_rawmidi_global_ops structure to allow the USB MIDI driver to supply information flags for the sequencer ports created by seq_midi. Signed-off-by: Clemens Ladisch --- include/sound/rawmidi.h | 3 + sound/core/seq/seq_midi.c | 3 + sound/usb/usbmidi.c | 200 ++++++++++++++++++++++++++++++---------------- 3 files changed, 136 insertions(+), 70 deletions(-) diff --git a/include/sound/rawmidi.h b/include/sound/rawmidi.h index 584e73dd479..7dbcd10fa21 100644 --- a/include/sound/rawmidi.h +++ b/include/sound/rawmidi.h @@ -46,6 +46,7 @@ struct snd_rawmidi; struct snd_rawmidi_substream; +struct snd_seq_port_info; struct snd_rawmidi_ops { int (*open) (struct snd_rawmidi_substream * substream); @@ -57,6 +58,8 @@ struct snd_rawmidi_ops { struct snd_rawmidi_global_ops { int (*dev_register) (struct snd_rawmidi * rmidi); int (*dev_unregister) (struct snd_rawmidi * rmidi); + void (*get_port_info)(struct snd_rawmidi *rmidi, int number, + struct snd_seq_port_info *info); }; struct snd_rawmidi_runtime { diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c index f873742c653..1daa5b069c7 100644 --- a/sound/core/seq/seq_midi.c +++ b/sound/core/seq/seq_midi.c @@ -278,6 +278,7 @@ snd_seq_midisynth_register_port(struct snd_seq_device *dev) struct seq_midisynth *msynth, *ms; struct snd_seq_port_info *port; struct snd_rawmidi_info *info; + struct snd_rawmidi *rmidi = dev->private_data; int newclient = 0; unsigned int p, ports; struct snd_seq_port_callback pcallbacks; @@ -389,6 +390,8 @@ snd_seq_midisynth_register_port(struct snd_seq_device *dev) pcallbacks.unuse = midisynth_unuse; pcallbacks.event_input = event_process_midi; port->kernel = &pcallbacks; + if (rmidi->ops && rmidi->ops->get_port_info) + rmidi->ops->get_port_info(rmidi, p, port); if (snd_seq_kernel_client_ctl(client->seq_client, SNDRV_SEQ_IOCTL_CREATE_PORT, port)<0) goto __nomem; ms->seq_client = client->seq_client; diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c index 2b9d940c806..5c53ec8a13b 100644 --- a/sound/usb/usbmidi.c +++ b/sound/usb/usbmidi.c @@ -48,6 +48,7 @@ #include #include #include +#include #include "usbaudio.h" @@ -1010,97 +1011,157 @@ static struct snd_rawmidi_substream *snd_usbmidi_find_substream(struct snd_usb_m * "(product) MIDI (n)" schema because they aren't external MIDI ports, * such as internal control or synthesizer ports. */ -static struct { +static struct port_info { u32 id; - int port; - const char *name_format; -} snd_usbmidi_port_names[] = { + short int port; + short int voices; + const char *name; + unsigned int seq_flags; +} snd_usbmidi_port_info[] = { +#define PORT_INFO(vendor, product, num, name_, voices_, flags) \ + { .id = USB_ID(vendor, product), \ + .port = num, .voices = voices_, \ + .name = name_, .seq_flags = flags } +#define EXTERNAL_PORT(vendor, product, num, name) \ + PORT_INFO(vendor, product, num, name, 0, \ + SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | \ + SNDRV_SEQ_PORT_TYPE_HARDWARE | \ + SNDRV_SEQ_PORT_TYPE_PORT) +#define CONTROL_PORT(vendor, product, num, name) \ + PORT_INFO(vendor, product, num, name, 0, \ + SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | \ + SNDRV_SEQ_PORT_TYPE_HARDWARE) +#define ROLAND_SYNTH_PORT(vendor, product, num, name, voices) \ + PORT_INFO(vendor, product, num, name, voices, \ + SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | \ + SNDRV_SEQ_PORT_TYPE_MIDI_GM | \ + SNDRV_SEQ_PORT_TYPE_MIDI_GM2 | \ + SNDRV_SEQ_PORT_TYPE_MIDI_GS | \ + SNDRV_SEQ_PORT_TYPE_MIDI_XG | \ + SNDRV_SEQ_PORT_TYPE_HARDWARE | \ + SNDRV_SEQ_PORT_TYPE_SYNTHESIZER) +#define SOUNDCANVAS_PORT(vendor, product, num, name, voices) \ + PORT_INFO(vendor, product, num, name, voices, \ + SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | \ + SNDRV_SEQ_PORT_TYPE_MIDI_GM | \ + SNDRV_SEQ_PORT_TYPE_MIDI_GM2 | \ + SNDRV_SEQ_PORT_TYPE_MIDI_GS | \ + SNDRV_SEQ_PORT_TYPE_MIDI_XG | \ + SNDRV_SEQ_PORT_TYPE_MIDI_MT32 | \ + SNDRV_SEQ_PORT_TYPE_HARDWARE | \ + SNDRV_SEQ_PORT_TYPE_SYNTHESIZER) /* Roland UA-100 */ - { USB_ID(0x0582, 0x0000), 2, "%s Control" }, + CONTROL_PORT(0x0582, 0x0000, 2, "%s Control"), /* Roland SC-8850 */ - { USB_ID(0x0582, 0x0003), 0, "%s Part A" }, - { USB_ID(0x0582, 0x0003), 1, "%s Part B" }, - { USB_ID(0x0582, 0x0003), 2, "%s Part C" }, - { USB_ID(0x0582, 0x0003), 3, "%s Part D" }, - { USB_ID(0x0582, 0x0003), 4, "%s MIDI 1" }, - { USB_ID(0x0582, 0x0003), 5, "%s MIDI 2" }, + SOUNDCANVAS_PORT(0x0582, 0x0003, 0, "%s Part A", 128), + SOUNDCANVAS_PORT(0x0582, 0x0003, 1, "%s Part B", 128), + SOUNDCANVAS_PORT(0x0582, 0x0003, 2, "%s Part C", 128), + SOUNDCANVAS_PORT(0x0582, 0x0003, 3, "%s Part D", 128), + EXTERNAL_PORT(0x0582, 0x0003, 4, "%s MIDI 1"), + EXTERNAL_PORT(0x0582, 0x0003, 5, "%s MIDI 2"), /* Roland U-8 */ - { USB_ID(0x0582, 0x0004), 0, "%s MIDI" }, - { USB_ID(0x0582, 0x0004), 1, "%s Control" }, + EXTERNAL_PORT(0x0582, 0x0004, 0, "%s MIDI"), + CONTROL_PORT(0x0582, 0x0004, 1, "%s Control"), /* Roland SC-8820 */ - { USB_ID(0x0582, 0x0007), 0, "%s Part A" }, - { USB_ID(0x0582, 0x0007), 1, "%s Part B" }, - { USB_ID(0x0582, 0x0007), 2, "%s MIDI" }, + SOUNDCANVAS_PORT(0x0582, 0x0007, 0, "%s Part A", 64), + SOUNDCANVAS_PORT(0x0582, 0x0007, 1, "%s Part B", 64), + EXTERNAL_PORT(0x0582, 0x0007, 2, "%s MIDI"), /* Roland SK-500 */ - { USB_ID(0x0582, 0x000b), 0, "%s Part A" }, - { USB_ID(0x0582, 0x000b), 1, "%s Part B" }, - { USB_ID(0x0582, 0x000b), 2, "%s MIDI" }, + SOUNDCANVAS_PORT(0x0582, 0x000b, 0, "%s Part A", 64), + SOUNDCANVAS_PORT(0x0582, 0x000b, 1, "%s Part B", 64), + EXTERNAL_PORT(0x0582, 0x000b, 2, "%s MIDI"), /* Roland SC-D70 */ - { USB_ID(0x0582, 0x000c), 0, "%s Part A" }, - { USB_ID(0x0582, 0x000c), 1, "%s Part B" }, - { USB_ID(0x0582, 0x000c), 2, "%s MIDI" }, + SOUNDCANVAS_PORT(0x0582, 0x000c, 0, "%s Part A", 64), + SOUNDCANVAS_PORT(0x0582, 0x000c, 1, "%s Part B", 64), + EXTERNAL_PORT(0x0582, 0x000c, 2, "%s MIDI"), /* Edirol UM-880 */ - { USB_ID(0x0582, 0x0014), 8, "%s Control" }, + CONTROL_PORT(0x0582, 0x0014, 8, "%s Control"), /* Edirol SD-90 */ - { USB_ID(0x0582, 0x0016), 0, "%s Part A" }, - { USB_ID(0x0582, 0x0016), 1, "%s Part B" }, - { USB_ID(0x0582, 0x0016), 2, "%s MIDI 1" }, - { USB_ID(0x0582, 0x0016), 3, "%s MIDI 2" }, + ROLAND_SYNTH_PORT(0x0582, 0x0016, 0, "%s Part A", 128), + ROLAND_SYNTH_PORT(0x0582, 0x0016, 1, "%s Part B", 128), + EXTERNAL_PORT(0x0582, 0x0016, 2, "%s MIDI 1"), + EXTERNAL_PORT(0x0582, 0x0016, 3, "%s MIDI 2"), /* Edirol UM-550 */ - { USB_ID(0x0582, 0x0023), 5, "%s Control" }, + CONTROL_PORT(0x0582, 0x0023, 5, "%s Control"), /* Edirol SD-20 */ - { USB_ID(0x0582, 0x0027), 0, "%s Part A" }, - { USB_ID(0x0582, 0x0027), 1, "%s Part B" }, - { USB_ID(0x0582, 0x0027), 2, "%s MIDI" }, + ROLAND_SYNTH_PORT(0x0582, 0x0027, 0, "%s Part A", 64), + ROLAND_SYNTH_PORT(0x0582, 0x0027, 1, "%s Part B", 64), + EXTERNAL_PORT(0x0582, 0x0027, 2, "%s MIDI"), /* Edirol SD-80 */ - { USB_ID(0x0582, 0x0029), 0, "%s Part A" }, - { USB_ID(0x0582, 0x0029), 1, "%s Part B" }, - { USB_ID(0x0582, 0x0029), 2, "%s MIDI 1" }, - { USB_ID(0x0582, 0x0029), 3, "%s MIDI 2" }, + ROLAND_SYNTH_PORT(0x0582, 0x0029, 0, "%s Part A", 128), + ROLAND_SYNTH_PORT(0x0582, 0x0029, 1, "%s Part B", 128), + EXTERNAL_PORT(0x0582, 0x0029, 2, "%s MIDI 1"), + EXTERNAL_PORT(0x0582, 0x0029, 3, "%s MIDI 2"), /* Edirol UA-700 */ - { USB_ID(0x0582, 0x002b), 0, "%s MIDI" }, - { USB_ID(0x0582, 0x002b), 1, "%s Control" }, + EXTERNAL_PORT(0x0582, 0x002b, 0, "%s MIDI"), + CONTROL_PORT(0x0582, 0x002b, 1, "%s Control"), /* Roland VariOS */ - { USB_ID(0x0582, 0x002f), 0, "%s MIDI" }, - { USB_ID(0x0582, 0x002f), 1, "%s External MIDI" }, - { USB_ID(0x0582, 0x002f), 2, "%s Sync" }, + EXTERNAL_PORT(0x0582, 0x002f, 0, "%s MIDI"), + EXTERNAL_PORT(0x0582, 0x002f, 1, "%s External MIDI"), + EXTERNAL_PORT(0x0582, 0x002f, 2, "%s Sync"), /* Edirol PCR */ - { USB_ID(0x0582, 0x0033), 0, "%s MIDI" }, - { USB_ID(0x0582, 0x0033), 1, "%s 1" }, - { USB_ID(0x0582, 0x0033), 2, "%s 2" }, + EXTERNAL_PORT(0x0582, 0x0033, 0, "%s MIDI"), + EXTERNAL_PORT(0x0582, 0x0033, 1, "%s 1"), + EXTERNAL_PORT(0x0582, 0x0033, 2, "%s 2"), /* BOSS GS-10 */ - { USB_ID(0x0582, 0x003b), 0, "%s MIDI" }, - { USB_ID(0x0582, 0x003b), 1, "%s Control" }, + EXTERNAL_PORT(0x0582, 0x003b, 0, "%s MIDI"), + CONTROL_PORT(0x0582, 0x003b, 1, "%s Control"), /* Edirol UA-1000 */ - { USB_ID(0x0582, 0x0044), 0, "%s MIDI" }, - { USB_ID(0x0582, 0x0044), 1, "%s Control" }, + EXTERNAL_PORT(0x0582, 0x0044, 0, "%s MIDI"), + CONTROL_PORT(0x0582, 0x0044, 1, "%s Control"), /* Edirol UR-80 */ - { USB_ID(0x0582, 0x0048), 0, "%s MIDI" }, - { USB_ID(0x0582, 0x0048), 1, "%s 1" }, - { USB_ID(0x0582, 0x0048), 2, "%s 2" }, + EXTERNAL_PORT(0x0582, 0x0048, 0, "%s MIDI"), + EXTERNAL_PORT(0x0582, 0x0048, 1, "%s 1"), + EXTERNAL_PORT(0x0582, 0x0048, 2, "%s 2"), /* Edirol PCR-A */ - { USB_ID(0x0582, 0x004d), 0, "%s MIDI" }, - { USB_ID(0x0582, 0x004d), 1, "%s 1" }, - { USB_ID(0x0582, 0x004d), 2, "%s 2" }, + EXTERNAL_PORT(0x0582, 0x004d, 0, "%s MIDI"), + EXTERNAL_PORT(0x0582, 0x004d, 1, "%s 1"), + EXTERNAL_PORT(0x0582, 0x004d, 2, "%s 2"), /* Edirol UM-3EX */ - { USB_ID(0x0582, 0x009a), 3, "%s Control" }, + CONTROL_PORT(0x0582, 0x009a, 3, "%s Control"), /* M-Audio MidiSport 8x8 */ - { USB_ID(0x0763, 0x1031), 8, "%s Control" }, - { USB_ID(0x0763, 0x1033), 8, "%s Control" }, + CONTROL_PORT(0x0763, 0x1031, 8, "%s Control"), + CONTROL_PORT(0x0763, 0x1033, 8, "%s Control"), /* MOTU Fastlane */ - { USB_ID(0x07fd, 0x0001), 0, "%s MIDI A" }, - { USB_ID(0x07fd, 0x0001), 1, "%s MIDI B" }, + EXTERNAL_PORT(0x07fd, 0x0001, 0, "%s MIDI A"), + EXTERNAL_PORT(0x07fd, 0x0001, 1, "%s MIDI B"), /* Emagic Unitor8/AMT8/MT4 */ - { USB_ID(0x086a, 0x0001), 8, "%s Broadcast" }, - { USB_ID(0x086a, 0x0002), 8, "%s Broadcast" }, - { USB_ID(0x086a, 0x0003), 4, "%s Broadcast" }, + EXTERNAL_PORT(0x086a, 0x0001, 8, "%s Broadcast"), + EXTERNAL_PORT(0x086a, 0x0002, 8, "%s Broadcast"), + EXTERNAL_PORT(0x086a, 0x0003, 4, "%s Broadcast"), }; +static struct port_info *find_port_info(struct snd_usb_midi* umidi, int number) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(snd_usbmidi_port_info); ++i) { + if (snd_usbmidi_port_info[i].id == umidi->chip->usb_id && + snd_usbmidi_port_info[i].port == number) + return &snd_usbmidi_port_info[i]; + } + return NULL; +} + +static void snd_usbmidi_get_port_info(struct snd_rawmidi *rmidi, int number, + struct snd_seq_port_info *seq_port_info) +{ + struct snd_usb_midi *umidi = rmidi->private_data; + struct port_info *port_info; + + /* TODO: read port flags from descriptors */ + port_info = find_port_info(umidi, number); + if (port_info) { + seq_port_info->type = port_info->seq_flags; + seq_port_info->midi_voices = port_info->voices; + } +} + static void snd_usbmidi_init_substream(struct snd_usb_midi* umidi, int stream, int number, struct snd_rawmidi_substream ** rsubstream) { - int i; + struct port_info *port_info; const char *name_format; struct snd_rawmidi_substream *substream = snd_usbmidi_find_substream(umidi, stream, number); @@ -1110,14 +1171,8 @@ static void snd_usbmidi_init_substream(struct snd_usb_midi* umidi, } /* TODO: read port name from jack descriptor */ - name_format = "%s MIDI %d"; - for (i = 0; i < ARRAY_SIZE(snd_usbmidi_port_names); ++i) { - if (snd_usbmidi_port_names[i].id == umidi->chip->usb_id && - snd_usbmidi_port_names[i].port == number) { - name_format = snd_usbmidi_port_names[i].name_format; - break; - } - } + port_info = find_port_info(umidi, number); + name_format = port_info ? port_info->name : "%s MIDI %d"; snprintf(substream->name, sizeof(substream->name), name_format, umidi->chip->card->shortname, number + 1); @@ -1457,6 +1512,10 @@ static int snd_usbmidi_create_endpoints_midiman(struct snd_usb_midi* umidi, return 0; } +static struct snd_rawmidi_global_ops snd_usbmidi_ops = { + .get_port_info = snd_usbmidi_get_port_info, +}; + static int snd_usbmidi_create_rawmidi(struct snd_usb_midi* umidi, int out_ports, int in_ports) { @@ -1472,6 +1531,7 @@ static int snd_usbmidi_create_rawmidi(struct snd_usb_midi* umidi, rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX; + rmidi->ops = &snd_usbmidi_ops; rmidi->private_data = umidi; rmidi->private_free = snd_usbmidi_rawmidi_free; snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_usbmidi_output_ops); -- cgit v1.2.3 From 886da8677d2e4e942fc8984b22bfb8da45e810ec Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 2 May 2006 18:17:57 +0200 Subject: [ALSA] hda-codec - Add support for LG S1 laptop Added the model entry for LG S1 laptop. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index cf6c100940d..6876094c911 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -2174,6 +2174,7 @@ static struct hda_board_config alc880_cfg_tbl[] = { { .modelname = "lg", .config = ALC880_LG }, { .pci_subvendor = 0x1854, .pci_subdevice = 0x003b, .config = ALC880_LG }, + { .pci_subvendor = 0x1854, .pci_subdevice = 0x0068, .config = ALC880_LG }, { .modelname = "lg-lw", .config = ALC880_LG_LW }, { .pci_subvendor = 0x1854, .pci_subdevice = 0x0018, .config = ALC880_LG_LW }, -- cgit v1.2.3 From eed656493a459bbc0fdf687fa8f43f87946d8d3a Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 2 May 2006 18:22:06 +0200 Subject: [ALSA] Add a workaround for ASUS A6KM Added a workaround for ASUS A6KM board that requires EAPD rather than SPDIF-in. Signed-off-by: Takashi Iwai --- sound/pci/ac97/ac97_patch.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index 4d9cf37300f..720b419e0c6 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c @@ -2048,7 +2048,10 @@ int patch_alc650(struct snd_ac97 * ac97) /* Enable SPDIF-IN only on Rev.E and above */ val = snd_ac97_read(ac97, AC97_ALC650_CLOCK); /* SPDIF IN with pin 47 */ - if (ac97->spec.dev_flags) + if (ac97->spec.dev_flags && + /* ASUS A6KM requires EAPD */ + ! (ac97->subsystem_vendor == 0x1043 && + ac97->subsystem_device == 0x1103)) val |= 0x03; /* enable */ else val &= ~0x03; /* disable */ -- cgit v1.2.3 From 1dbfd8c56bd7366d86e58b3e510a75de93e1978b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 2 May 2006 18:31:31 +0200 Subject: [ALSA] cs5535audio - Add missing module_param*() and MODULE_PARM_DESC() Added missing module_param*() and MODULE_PARM_DESC() for cs5535audio driver. Signed-off-by: Takashi Iwai --- sound/pci/cs5535audio/cs5535audio.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c index 41f02f05dfd..f61c4fa4ed6 100644 --- a/sound/pci/cs5535audio/cs5535audio.c +++ b/sound/pci/cs5535audio/cs5535audio.c @@ -60,6 +60,13 @@ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; +module_param_array(index, int, NULL, 0444); +MODULE_PARM_DESC(index, "Index value for " DRIVER_NAME); +module_param_array(id, charp, NULL, 0444); +MODULE_PARM_DESC(id, "ID string for " DRIVER_NAME); +module_param_array(enable, bool, NULL, 0444); +MODULE_PARM_DESC(enable, "Enable " DRIVER_NAME); + static struct pci_device_id snd_cs5535audio_ids[] __devinitdata = { { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_AUDIO) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_AUDIO) }, -- cgit v1.2.3 From a9393d70e564e4afe0333b1e26dda48af8b9305e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 3 May 2006 11:59:03 +0200 Subject: [ALSA] hda-codec - Fix mute switch on VAIO laptops with STAC7661 Fixed the master mute switch on VAIO laptops with STAC7661 codec chip. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 8c440fb9860..d8622951c3d 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -1262,13 +1262,13 @@ static int vaio_master_sw_put(struct snd_kcontrol *kcontrol, int change; change = snd_hda_codec_amp_update(codec, 0x02, 0, HDA_OUTPUT, 0, - 0x80, valp[0] & 0x80); + 0x80, (valp[0] ? 0 : 0x80)); change |= snd_hda_codec_amp_update(codec, 0x02, 1, HDA_OUTPUT, 0, - 0x80, valp[1] & 0x80); + 0x80, (valp[1] ? 0 : 0x80)); snd_hda_codec_amp_update(codec, 0x05, 0, HDA_OUTPUT, 0, - 0x80, valp[0] & 0x80); + 0x80, (valp[0] ? 0 : 0x80)); snd_hda_codec_amp_update(codec, 0x05, 1, HDA_OUTPUT, 0, - 0x80, valp[1] & 0x80); + 0x80, (valp[1] ? 0 : 0x80)); return change; } -- cgit v1.2.3 From a59524faf3a2050e14a1c9038eb006ce96025394 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Wed, 3 May 2006 14:08:33 +0200 Subject: [ALSA] hda: add sigmatel 9227/9228/9229 ids Adds support for the 9227/9228/9229 sigmatel hda codecs. Signed-off-by: Matt Porter Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index d8622951c3d..6d8224dc033 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -1370,6 +1370,12 @@ struct hda_codec_preset snd_hda_preset_sigmatel[] = { { .id = 0x83847681, .name = "STAC9220D/9223D A2", .patch = patch_stac922x }, { .id = 0x83847682, .name = "STAC9221 A2", .patch = patch_stac922x }, { .id = 0x83847683, .name = "STAC9221D A2", .patch = patch_stac922x }, + { .id = 0x83847618, .name = "STAC9227", .patch = patch_stac922x }, + { .id = 0x83847619, .name = "STAC9227", .patch = patch_stac922x }, + { .id = 0x83847616, .name = "STAC9228", .patch = patch_stac922x }, + { .id = 0x83847617, .name = "STAC9228", .patch = patch_stac922x }, + { .id = 0x83847614, .name = "STAC9229", .patch = patch_stac922x }, + { .id = 0x83847615, .name = "STAC9229", .patch = patch_stac922x }, { .id = 0x83847620, .name = "STAC9274", .patch = patch_stac927x }, { .id = 0x83847621, .name = "STAC9274D", .patch = patch_stac927x }, { .id = 0x83847622, .name = "STAC9273X", .patch = patch_stac927x }, -- cgit v1.2.3 From 520290e43f9880da34e542185838816c6d79a340 Mon Sep 17 00:00:00 2001 From: Alan Horstmann Date: Wed, 3 May 2006 17:07:29 +0200 Subject: [ALSA] au88x0 - Init before create components Change the order in vortex_probe to set the card details before creating the components, meaning for example that card->shortname is available when registering the midi port. I have also added extra to card->shortname, and a line to overwrite the midi name following snd_mpu401_uart_new. Signed-off-by: Alan Horstmann Signed-off-by: Takashi Iwai --- sound/pci/au88x0/au88x0.c | 12 +++++++----- sound/pci/au88x0/au88x0_mpu401.c | 3 +++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c index 126870ec063..8a3b118989b 100644 --- a/sound/pci/au88x0/au88x0.c +++ b/sound/pci/au88x0/au88x0.c @@ -261,6 +261,13 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) return err; } snd_vortex_workaround(pci, pcifix[dev]); + + // Card details needed in snd_vortex_midi + strcpy(card->driver, CARD_NAME_SHORT); + sprintf(card->shortname, "Aureal Vortex %s", CARD_NAME_SHORT); + sprintf(card->longname, "%s at 0x%lx irq %i", + card->shortname, chip->io, chip->irq); + // (4) Alloc components. // ADB pcm. if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_ADB, NR_ADB)) < 0) { @@ -323,11 +330,6 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) #endif // (5) - strcpy(card->driver, CARD_NAME_SHORT); - strcpy(card->shortname, CARD_NAME_SHORT); - sprintf(card->longname, "%s at 0x%lx irq %i", - card->shortname, chip->io, chip->irq); - if ((err = pci_read_config_word(pci, PCI_DEVICE_ID, &(chip->device))) < 0) { snd_card_free(card); diff --git a/sound/pci/au88x0/au88x0_mpu401.c b/sound/pci/au88x0/au88x0_mpu401.c index 873f486b07b..814bc2db9f0 100644 --- a/sound/pci/au88x0/au88x0_mpu401.c +++ b/sound/pci/au88x0/au88x0_mpu401.c @@ -107,6 +107,9 @@ static int __devinit snd_vortex_midi(vortex_t * vortex) mpu = rmidi->private_data; mpu->cport = (unsigned long)(vortex->mmio + VORTEX_MIDI_CMD); #endif + /* Overwrite MIDI name */ + snprintf(rmidi->name, sizeof(rmidi->name), "%s MIDI %d", CARD_NAME_SHORT , vortex->card->number); + vortex->rmidi = rmidi; return 0; } -- cgit v1.2.3 From a7306336e818fe83f08a476c91ae2616e7fb209f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 4 May 2006 11:58:43 +0200 Subject: [ALSA] Fix a typo in writing-an-alsa-driver document Fixed a typo in writing-an-alsa-driver document. Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl index db557f91ab7..23c6c7cde4e 100644 --- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl +++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl @@ -5545,7 +5545,7 @@ struct _snd_pcm_runtime { power status. Call snd_pcm_suspend_all() to suspend the running PCM streams. If AC97 codecs are used, call - snd_ac97_resume() for each codec. + snd_ac97_suspend() for each codec. Save the register values if necessary. Stop the hardware if necessary. Disable the PCI device by calling -- cgit v1.2.3 From cab5c4c97a98e46359faa52e86787c1f0ccd773c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 4 May 2006 14:36:08 +0200 Subject: [ALSA] cmipci - Disable integrated mpu401 as default Enable the support of mpu401 PCI port only when mpu_port=1 module option is given, i.e. disabled as default. It turned out that the check of integrated midi port isn't perfect and caused hang-ups on some boards. Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/ALSA-Configuration.txt | 4 +++- sound/pci/cmipci.c | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 3c09d9b8cd3..e5bfb0f7ff3 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -366,7 +366,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. Module for C-Media CMI8338 and 8738 PCI sound cards. - mpu_port - 0x300,0x310,0x320,0x330, 0 = disable (default) + mpu_port - 0x300,0x310,0x320,0x330 = legacy port, + 1 = integrated PCI port, + 0 = disable (default) fm_port - 0x388 (default), 0 = disable (default) soft_ac3 - Software-conversion of raw SPDIF packets (model 033 only) (default = 1) diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index 42ca92be18f..cb475ada2ef 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c @@ -2932,7 +2932,7 @@ static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pc } integrated_midi = snd_cmipci_read_b(cm, CM_REG_MPU_PCI) != 0xff; - if (integrated_midi) + if (integrated_midi && mpu_port[dev] == 1) iomidi = cm->iobase + CM_REG_MPU_PCI; else { iomidi = mpu_port[dev]; -- cgit v1.2.3 From 4d1a70dad0e1c44dc0725de6de25aceead48599e Mon Sep 17 00:00:00 2001 From: Raimonds Cicans Date: Fri, 5 May 2006 09:49:53 +0200 Subject: [ALSA] add support for SB Live! 24-Bit External remote control This patch rewrites the remote control code to use a table for the peculiarities of the various SB models, and adds support for a third model. Signed-off-by: Raimonds Cicans Signed-off-by: Clemens Ladisch --- sound/usb/usbmixer.c | 68 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 28 deletions(-) diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c index ab921aa9d77..491e975a0c8 100644 --- a/sound/usb/usbmixer.c +++ b/sound/usb/usbmixer.c @@ -46,6 +46,27 @@ /* ignore error from controls - for debugging */ /* #define IGNORE_CTL_ERROR */ +/* + * Sound Blaster remote control configuration + * + * format of remote control data: + * Extigy: xx 00 + * Audigy 2 NX: 06 80 xx 00 00 00 + * Live! 24-bit: 06 80 xx yy 22 83 + */ +static const struct rc_config { + u32 usb_id; + u8 offset; + u8 length; + u8 packet_length; + u8 mute_mixer_id; + u32 mute_code; +} rc_configs[] = { + { USB_ID(0x041e, 0x3000), 0, 1, 2, 18, 0x0013 }, /* Extigy */ + { USB_ID(0x041e, 0x3020), 2, 1, 6, 18, 0x0013 }, /* Audigy 2 NX */ + { USB_ID(0x041e, 0x3040), 2, 2, 6, 2, 0x6e91 }, /* Live! 24-bit */ +}; + struct usb_mixer_interface { struct snd_usb_audio *chip; unsigned int ctrlif; @@ -55,11 +76,7 @@ struct usb_mixer_interface { struct usb_mixer_elem_info **id_elems; /* array[256], indexed by unit id */ /* Sound Blaster remote control stuff */ - enum { - RC_NONE, - RC_EXTIGY, - RC_AUDIGY2NX, - } rc_type; + const struct rc_config *rc_cfg; unsigned long rc_hwdep_open; u32 rc_code; wait_queue_head_t rc_waitq; @@ -1647,7 +1664,7 @@ static void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, static void snd_usb_mixer_memory_change(struct usb_mixer_interface *mixer, int unitid) { - if (mixer->rc_type == RC_NONE) + if (!mixer->rc_cfg) return; /* unit ids specific to Extigy/Audigy 2 NX: */ switch (unitid) { @@ -1732,20 +1749,19 @@ static void snd_usb_soundblaster_remote_complete(struct urb *urb, struct pt_regs *regs) { struct usb_mixer_interface *mixer = urb->context; - /* - * format of remote control data: - * Extigy: xx 00 - * Audigy 2 NX: 06 80 xx 00 00 00 - */ - int offset = mixer->rc_type == RC_EXTIGY ? 0 : 2; + const struct rc_config *rc = mixer->rc_cfg; u32 code; - if (urb->status < 0 || urb->actual_length <= offset) + if (urb->status < 0 || urb->actual_length < rc->packet_length) return; - code = mixer->rc_buffer[offset]; + + code = mixer->rc_buffer[rc->offset]; + if (rc->length == 2) + code |= mixer->rc_buffer[rc->offset + 1] << 8; + /* the Mute button actually changes the mixer control */ - if (code == 13) - snd_usb_mixer_notify_id(mixer, 18); + if (code == rc->mute_code) + snd_usb_mixer_notify_id(mixer, rc->mute_mixer_id); mixer->rc_code = code; wmb(); wake_up(&mixer->rc_waitq); @@ -1801,21 +1817,17 @@ static unsigned int snd_usb_sbrc_hwdep_poll(struct snd_hwdep *hw, struct file *f static int snd_usb_soundblaster_remote_init(struct usb_mixer_interface *mixer) { struct snd_hwdep *hwdep; - int err, len; + int err, len, i; - switch (mixer->chip->usb_id) { - case USB_ID(0x041e, 0x3000): - mixer->rc_type = RC_EXTIGY; - len = 2; - break; - case USB_ID(0x041e, 0x3020): - mixer->rc_type = RC_AUDIGY2NX; - len = 6; - break; - default: + for (i = 0; i < ARRAY_SIZE(rc_configs); ++i) + if (rc_configs[i].usb_id == mixer->chip->usb_id) + break; + if (i >= ARRAY_SIZE(rc_configs)) return 0; - } + mixer->rc_cfg = &rc_configs[i]; + len = mixer->rc_cfg->packet_length; + init_waitqueue_head(&mixer->rc_waitq); err = snd_hwdep_new(mixer->chip->card, "SB remote control", 0, &hwdep); if (err < 0) -- cgit v1.2.3 From 62fe78e90dc25b269362034487dc450cd8453e8c Mon Sep 17 00:00:00 2001 From: Sam Revitch Date: Wed, 10 May 2006 15:09:17 +0200 Subject: [ALSA] hda-codec - Add support for Apple Mac Mini (early 2006) Add support for some audio quirks of the Apple Mac Mini (early 2006) Signed-off-by: Sam Revitch Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 68 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 67 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 6d8224dc033..36f199442fd 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -41,6 +41,7 @@ #define STAC_REF 0 #define STAC_D945GTP3 1 #define STAC_D945GTP5 2 +#define STAC_MACMINI 3 struct sigmatel_spec { struct snd_kcontrol_new *mixers[4]; @@ -52,6 +53,7 @@ struct sigmatel_spec { unsigned int mic_switch: 1; unsigned int alt_switch: 1; unsigned int hp_detect: 1; + unsigned int gpio_mute: 1; /* playback */ struct hda_multi_out multiout; @@ -293,6 +295,7 @@ static unsigned int *stac922x_brd_tbl[] = { ref922x_pin_configs, d945gtp3_pin_configs, d945gtp5_pin_configs, + NULL, /* STAC_MACMINI */ }; static struct hda_board_config stac922x_cfg_tbl[] = { @@ -324,6 +327,9 @@ static struct hda_board_config stac922x_cfg_tbl[] = { { .pci_subvendor = PCI_VENDOR_ID_INTEL, .pci_subdevice = 0x0417, .config = STAC_D945GTP5 }, /* Intel D975XBK - 5 Stack */ + { .pci_subvendor = 0x8384, + .pci_subdevice = 0x7680, + .config = STAC_MACMINI }, /* Apple Mac Mini (early 2006) */ {} /* terminator */ }; @@ -841,6 +847,19 @@ static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const } } + if (imux->num_items == 1) { + /* + * Set the current input for the muxes. + * The STAC9221 has two input muxes with identical source + * NID lists. Hopefully this won't get confused. + */ + for (i = 0; i < spec->num_muxes; i++) { + snd_hda_codec_write(codec, spec->mux_nids[i], 0, + AC_VERB_SET_CONNECT_SEL, + imux->items[0].index); + } + } + return 0; } @@ -946,6 +965,45 @@ static int stac9200_parse_auto_config(struct hda_codec *codec) return 1; } +/* + * Early 2006 Intel Macintoshes with STAC9220X5 codecs seem to have a + * funky external mute control using GPIO pins. + */ + +static void stac922x_gpio_mute(struct hda_codec *codec, int pin, int muted) +{ + unsigned int gpiostate, gpiomask, gpiodir; + + gpiostate = snd_hda_codec_read(codec, codec->afg, 0, + AC_VERB_GET_GPIO_DATA, 0); + + if (!muted) + gpiostate |= (1 << pin); + else + gpiostate &= ~(1 << pin); + + gpiomask = snd_hda_codec_read(codec, codec->afg, 0, + AC_VERB_GET_GPIO_MASK, 0); + gpiomask |= (1 << pin); + + gpiodir = snd_hda_codec_read(codec, codec->afg, 0, + AC_VERB_GET_GPIO_DIRECTION, 0); + gpiodir |= (1 << pin); + + /* AppleHDA seems to do this -- WTF is this verb?? */ + snd_hda_codec_write(codec, codec->afg, 0, 0x7e7, 0); + + snd_hda_codec_write(codec, codec->afg, 0, + AC_VERB_SET_GPIO_MASK, gpiomask); + snd_hda_codec_write(codec, codec->afg, 0, + AC_VERB_SET_GPIO_DIRECTION, gpiodir); + + msleep(1); + + snd_hda_codec_write(codec, codec->afg, 0, + AC_VERB_SET_GPIO_DATA, gpiostate); +} + static int stac92xx_init(struct hda_codec *codec) { struct sigmatel_spec *spec = codec->spec; @@ -982,6 +1040,11 @@ static int stac92xx_init(struct hda_codec *codec) stac92xx_auto_set_pinctl(codec, cfg->dig_in_pin, AC_PINCTL_IN_EN); + if (spec->gpio_mute) { + stac922x_gpio_mute(codec, 0, 0); + stac922x_gpio_mute(codec, 1, 0); + } + return 0; } @@ -1132,7 +1195,7 @@ static int patch_stac922x(struct hda_codec *codec) spec->board_config = snd_hda_check_board_config(codec, stac922x_cfg_tbl); if (spec->board_config < 0) snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC922x, using BIOS defaults\n"); - else { + else if (stac922x_brd_tbl[spec->board_config] != NULL) { spec->num_pins = 10; spec->pin_nids = stac922x_pin_nids; spec->pin_configs = stac922x_brd_tbl[spec->board_config]; @@ -1154,6 +1217,9 @@ static int patch_stac922x(struct hda_codec *codec) return err; } + if (spec->board_config == STAC_MACMINI) + spec->gpio_mute = 1; + codec->patch_ops = stac92xx_patch_ops; return 0; -- cgit v1.2.3 From 2ce7fb579f842f76a0216618c105bffd334d9233 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 10 May 2006 16:24:42 +0200 Subject: [ALSA] rme96 - Fix OSS full-duplex Fixed a bug in rme96 driver that the full-duplex on OSS emulation doesn't work due to the invalid period size parameter. Signed-off-by: Takashi Iwai --- sound/pci/rme96.c | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c index 75a8b754ef2..65611a7d366 100644 --- a/sound/pci/rme96.c +++ b/sound/pci/rme96.c @@ -1151,6 +1151,25 @@ static struct snd_pcm_hw_constraint_list hw_constraints_period_bytes = { .mask = 0 }; +static void +rme96_set_buffer_size_constraint(struct rme96 *rme96, + struct snd_pcm_runtime *runtime) +{ + unsigned int size; + + snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, + RME96_BUFFER_SIZE, RME96_BUFFER_SIZE); + if ((size = rme96->playback_periodsize) != 0 || + (size = rme96->capture_periodsize) != 0) + snd_pcm_hw_constraint_minmax(runtime, + SNDRV_PCM_HW_PARAM_PERIOD_BYTES, + size, size); + else + snd_pcm_hw_constraint_list(runtime, 0, + SNDRV_PCM_HW_PARAM_PERIOD_BYTES, + &hw_constraints_period_bytes); +} + static int snd_rme96_playback_spdif_open(struct snd_pcm_substream *substream) { @@ -1180,8 +1199,7 @@ snd_rme96_playback_spdif_open(struct snd_pcm_substream *substream) runtime->hw.rate_min = rate; runtime->hw.rate_max = rate; } - snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, RME96_BUFFER_SIZE, RME96_BUFFER_SIZE); - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_period_bytes); + rme96_set_buffer_size_constraint(rme96, runtime); rme96->wcreg_spdif_stream = rme96->wcreg_spdif; rme96->spdif_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; @@ -1219,9 +1237,7 @@ snd_rme96_capture_spdif_open(struct snd_pcm_substream *substream) rme96->capture_substream = substream; spin_unlock_irq(&rme96->lock); - snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, RME96_BUFFER_SIZE, RME96_BUFFER_SIZE); - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_period_bytes); - + rme96_set_buffer_size_constraint(rme96, runtime); return 0; } @@ -1254,8 +1270,7 @@ snd_rme96_playback_adat_open(struct snd_pcm_substream *substream) runtime->hw.rate_min = rate; runtime->hw.rate_max = rate; } - snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, RME96_BUFFER_SIZE, RME96_BUFFER_SIZE); - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_period_bytes); + rme96_set_buffer_size_constraint(rme96, runtime); return 0; } @@ -1291,8 +1306,7 @@ snd_rme96_capture_adat_open(struct snd_pcm_substream *substream) rme96->capture_substream = substream; spin_unlock_irq(&rme96->lock); - snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, RME96_BUFFER_SIZE, RME96_BUFFER_SIZE); - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_period_bytes); + rme96_set_buffer_size_constraint(rme96, runtime); return 0; } -- cgit v1.2.3 From 3206b9ca9fba8dc8d6ddd371a3ff455c67ad137f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 10 May 2006 16:33:11 +0200 Subject: [ALSA] hda-codec - Add support for Sony Vaio VGN-S3HP Added the missing support for Sony Vaio VGN-S3HP with ALC260 codec. The patch taken from ALSA bug#2101. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 6876094c911..f6bccd66d14 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -3823,6 +3823,8 @@ static struct hda_board_config alc260_cfg_tbl[] = { { .modelname = "basic", .config = ALC260_BASIC }, { .pci_subvendor = 0x104d, .pci_subdevice = 0x81bb, .config = ALC260_BASIC }, /* Sony VAIO */ + { .pci_subvendor = 0x104d, .pci_subdevice = 0x81cc, + .config = ALC260_BASIC }, /* Sony VAIO VGN-S3HP */ { .pci_subvendor = 0x104d, .pci_subdevice = 0x81cd, .config = ALC260_BASIC }, /* Sony VAIO */ { .pci_subvendor = 0x152d, .pci_subdevice = 0x0729, -- cgit v1.2.3 From ed7cbe3e4175e5fe9386793fbffee786840d7e9c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 11 May 2006 11:30:10 +0200 Subject: [ALSA] Remove obsolete description from ALSA-Configuration.txt Remove obsolete descriptions about the dependency on CONFIG_ISA for vxpocket and pdaudiocf drivers. Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/ALSA-Configuration.txt | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index e5bfb0f7ff3..89a12a64385 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -1636,9 +1636,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. About capture IBL, see the description of snd-vx222 module. - Note: the driver is build only when CONFIG_ISA is set. - - Note2: snd-vxp440 driver is merged to snd-vxpocket driver since + Note: snd-vxp440 driver is merged to snd-vxpocket driver since ALSA 1.0.10. The power-management is supported. @@ -1665,8 +1663,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. Module for Sound Core PDAudioCF sound card. - Note: the driver is build only when CONFIG_ISA is set. - The power-management is supported. -- cgit v1.2.3 From 0defb2672d7cde8d048eec35c183da7b88adbd9e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 11 May 2006 18:12:23 +0200 Subject: [ALSA] hda-codec - Fix handling of capture controls on ALC882 3/6-stack models Fixed the handling of capture controls on ALC882 3/6-stack models. Now the driver checks the availability of NID 07h. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index f6bccd66d14..0fc2f77dce2 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4099,21 +4099,6 @@ static struct snd_kcontrol_new alc882_base_mixer[] = { HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), - HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT), - HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT), - HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - /* .name = "Capture Source", */ - .name = "Input Source", - .count = 3, - .info = alc882_mux_enum_info, - .get = alc882_mux_enum_get, - .put = alc882_mux_enum_put, - }, { } /* end */ }; @@ -4347,8 +4332,6 @@ static struct alc_config_preset alc882_presets[] = { .num_dacs = ARRAY_SIZE(alc882_dac_nids), .dac_nids = alc882_dac_nids, .dig_out_nid = ALC882_DIGOUT_NID, - .num_adc_nids = ARRAY_SIZE(alc882_adc_nids), - .adc_nids = alc882_adc_nids, .dig_in_nid = ALC882_DIGIN_NID, .num_channel_mode = ARRAY_SIZE(alc882_ch_modes), .channel_mode = alc882_ch_modes, @@ -4360,8 +4343,6 @@ static struct alc_config_preset alc882_presets[] = { .num_dacs = ARRAY_SIZE(alc882_dac_nids), .dac_nids = alc882_dac_nids, .dig_out_nid = ALC882_DIGOUT_NID, - .num_adc_nids = ARRAY_SIZE(alc882_adc_nids), - .adc_nids = alc882_adc_nids, .dig_in_nid = ALC882_DIGIN_NID, .num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes), .channel_mode = alc882_sixstack_modes, -- cgit v1.2.3 From 746df94898554b3d8e91d855e934852e626c701c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 15 May 2006 19:49:05 +0200 Subject: [ALSA] Fix rwlock around snd_iprintf() in sound core Fixed rwlock around snd_iprintf() in sound core part. Replaced with mutex. Also, make mutex and flags static variables with addition of snd_card_locked() function (just for sound.c). Signed-off-by: Takashi Iwai --- include/sound/core.h | 3 +-- sound/core/init.c | 51 +++++++++++++++++++++++++++++++-------------------- sound/core/sound.c | 7 +------ 3 files changed, 33 insertions(+), 28 deletions(-) diff --git a/include/sound/core.h b/include/sound/core.h index 5135147f20e..5d184be0ff7 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -233,9 +233,8 @@ int copy_from_user_toio(volatile void __iomem *dst, const void __user *src, size /* init.c */ -extern unsigned int snd_cards_lock; extern struct snd_card *snd_cards[SNDRV_CARDS]; -extern rwlock_t snd_card_rwlock; +int snd_card_locked(int card); #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) #define SND_MIXER_OSS_NOTIFY_REGISTER 0 #define SND_MIXER_OSS_NOTIFY_DISCONNECT 1 diff --git a/sound/core/init.c b/sound/core/init.c index 2ff0e5e9086..38b2d4a9d67 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -38,11 +38,11 @@ struct snd_shutdown_f_ops { struct snd_shutdown_f_ops *next; }; -unsigned int snd_cards_lock = 0; /* locked for registering/using */ +static unsigned int snd_cards_lock = 0; /* locked for registering/using */ struct snd_card *snd_cards[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = NULL}; EXPORT_SYMBOL(snd_cards); -DEFINE_RWLOCK(snd_card_rwlock); +static DEFINE_MUTEX(snd_card_mutex); #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) int (*snd_mixer_oss_notify_callback)(struct snd_card *card, int free_flag); @@ -112,7 +112,7 @@ struct snd_card *snd_card_new(int idx, const char *xid, strlcpy(card->id, xid, sizeof(card->id)); } err = 0; - write_lock(&snd_card_rwlock); + mutex_lock(&snd_card_mutex); if (idx < 0) { int idx2; for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++) @@ -130,12 +130,12 @@ struct snd_card *snd_card_new(int idx, const char *xid, else err = -ENODEV; if (idx < 0 || err < 0) { - write_unlock(&snd_card_rwlock); + mutex_unlock(&snd_card_mutex); snd_printk(KERN_ERR "cannot find the slot for index %d (range 0-%i)\n", idx, snd_ecards_limit - 1); goto __error; } snd_cards_lock |= 1 << idx; /* lock it */ - write_unlock(&snd_card_rwlock); + mutex_unlock(&snd_card_mutex); card->number = idx; card->module = module; INIT_LIST_HEAD(&card->devices); @@ -173,6 +173,17 @@ struct snd_card *snd_card_new(int idx, const char *xid, EXPORT_SYMBOL(snd_card_new); +/* return non-zero if a card is already locked */ +int snd_card_locked(int card) +{ + int locked; + + mutex_lock(&snd_card_mutex); + locked = snd_cards_lock & (1 << card); + mutex_unlock(&snd_card_mutex); + return locked; +} + static loff_t snd_disconnect_llseek(struct file *file, loff_t offset, int orig) { return -ENODEV; @@ -240,9 +251,9 @@ int snd_card_disconnect(struct snd_card *card) spin_unlock(&card->files_lock); /* phase 1: disable fops (user space) operations for ALSA API */ - write_lock(&snd_card_rwlock); + mutex_lock(&snd_card_mutex); snd_cards[card->number] = NULL; - write_unlock(&snd_card_rwlock); + mutex_unlock(&snd_card_mutex); /* phase 2: replace file->f_op with special dummy operations */ @@ -321,9 +332,9 @@ int snd_card_free(struct snd_card *card) if (card == NULL) return -EINVAL; - write_lock(&snd_card_rwlock); + mutex_lock(&snd_card_mutex); snd_cards[card->number] = NULL; - write_unlock(&snd_card_rwlock); + mutex_unlock(&snd_card_mutex); #ifdef CONFIG_PM wake_up(&card->power_sleep); @@ -359,9 +370,9 @@ int snd_card_free(struct snd_card *card) card->s_f_ops = s_f_ops->next; kfree(s_f_ops); } - write_lock(&snd_card_rwlock); + mutex_lock(&snd_card_mutex); snd_cards_lock &= ~(1 << card->number); - write_unlock(&snd_card_rwlock); + mutex_unlock(&snd_card_mutex); kfree(card); return 0; } @@ -497,16 +508,16 @@ int snd_card_register(struct snd_card *card) snd_assert(card != NULL, return -EINVAL); if ((err = snd_device_register_all(card)) < 0) return err; - write_lock(&snd_card_rwlock); + mutex_lock(&snd_card_mutex); if (snd_cards[card->number]) { /* already registered */ - write_unlock(&snd_card_rwlock); + mutex_unlock(&snd_card_mutex); return 0; } if (card->id[0] == '\0') choose_default_id(card); snd_cards[card->number] = card; - write_unlock(&snd_card_rwlock); + mutex_unlock(&snd_card_mutex); init_info_for_card(card); #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) if (snd_mixer_oss_notify_callback) @@ -527,7 +538,7 @@ static void snd_card_info_read(struct snd_info_entry *entry, struct snd_card *card; for (idx = count = 0; idx < SNDRV_CARDS; idx++) { - read_lock(&snd_card_rwlock); + mutex_lock(&snd_card_mutex); if ((card = snd_cards[idx]) != NULL) { count++; snd_iprintf(buffer, "%2i [%-15s]: %s - %s\n", @@ -538,7 +549,7 @@ static void snd_card_info_read(struct snd_info_entry *entry, snd_iprintf(buffer, " %s\n", card->longname); } - read_unlock(&snd_card_rwlock); + mutex_unlock(&snd_card_mutex); } if (!count) snd_iprintf(buffer, "--- no soundcards ---\n"); @@ -552,12 +563,12 @@ void snd_card_info_read_oss(struct snd_info_buffer *buffer) struct snd_card *card; for (idx = count = 0; idx < SNDRV_CARDS; idx++) { - read_lock(&snd_card_rwlock); + mutex_lock(&snd_card_mutex); if ((card = snd_cards[idx]) != NULL) { count++; snd_iprintf(buffer, "%s\n", card->longname); } - read_unlock(&snd_card_rwlock); + mutex_unlock(&snd_card_mutex); } if (!count) { snd_iprintf(buffer, "--- no soundcards ---\n"); @@ -575,11 +586,11 @@ static void snd_card_module_info_read(struct snd_info_entry *entry, struct snd_card *card; for (idx = 0; idx < SNDRV_CARDS; idx++) { - read_lock(&snd_card_rwlock); + mutex_lock(&snd_card_mutex); if ((card = snd_cards[idx]) != NULL) snd_iprintf(buffer, "%2i %s\n", idx, card->module->name); - read_unlock(&snd_card_rwlock); + mutex_unlock(&snd_card_mutex); } } #endif diff --git a/sound/core/sound.c b/sound/core/sound.c index 8313f97907d..02c8cc4ebff 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c @@ -81,14 +81,9 @@ extern struct class *sound_class; */ void snd_request_card(int card) { - int locked; - if (! current->fs->root) return; - read_lock(&snd_card_rwlock); - locked = snd_cards_lock & (1 << card); - read_unlock(&snd_card_rwlock); - if (locked) + if (snd_card_locked(card)) return; if (card < 0 || card >= cards_limit) return; -- cgit v1.2.3 From ca54bde3634360afecd0dada9c59399bbe88bd32 Mon Sep 17 00:00:00 2001 From: Andreas Mohr Date: Wed, 17 May 2006 11:02:24 +0200 Subject: [ALSA] azt3328.c: add suspend/resume support - add suspend/resume handlers - fix problem (private_data members not set) Playing a file while suspending will resume correctly with this patch, so I assume the hardware to get fully correctly reinitialized with this patch. Signed-off-by: Andreas Mohr Signed-off-by: Takashi Iwai --- sound/pci/azt3328.c | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++-- sound/pci/azt3328.h | 20 +++++++-- 2 files changed, 133 insertions(+), 6 deletions(-) diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index 52a36452426..f197fbac10a 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c @@ -90,9 +90,11 @@ * * TODO * - test MPU401 MIDI playback etc. - * - power management. See e.g. intel8x0 or cs4281. - * This would be nice since the chip runs a bit hot, and it's *required* - * anyway for proper ACPI power management. + * - add some power micro-management (disable various units of the card + * as long as they're unused). However this requires I/O ports which I + * haven't figured out yet and which thus might not even exist... + * The standard suspend/resume functionality could probably make use of + * some improvement, too... * - figure out what all unknown port bits are responsible for */ @@ -214,6 +216,16 @@ struct snd_azf3328 { struct pci_dev *pci; int irq; + +#ifdef CONFIG_PM + /* register value containers for power management + * Note: not always full I/O range preserved (just like Win driver!) */ + u16 saved_regs_codec [AZF_IO_SIZE_CODEC_PM / 2]; + u16 saved_regs_io2 [AZF_IO_SIZE_IO2_PM / 2]; + u16 saved_regs_mpu [AZF_IO_SIZE_MPU_PM / 2]; + u16 saved_regs_synth[AZF_IO_SIZE_SYNTH_PM / 2]; + u16 saved_regs_mixer[AZF_IO_SIZE_MIXER_PM / 2]; +#endif }; static const struct pci_device_id snd_azf3328_ids[] __devinitdata = { @@ -961,6 +973,13 @@ snd_azf3328_playback_trigger(struct snd_pcm_substream *substream, int cmd) chip->is_playing = 1; snd_azf3328_dbgplay("STARTED PLAYBACK\n"); break; + case SNDRV_PCM_TRIGGER_RESUME: + snd_azf3328_dbgplay("RESUME PLAYBACK\n"); + /* resume playback if we were active */ + if (chip->is_playing) + snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, + snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS) | DMA_RESUME); + break; case SNDRV_PCM_TRIGGER_STOP: snd_azf3328_dbgplay("STOP PLAYBACK\n"); @@ -988,6 +1007,12 @@ snd_azf3328_playback_trigger(struct snd_pcm_substream *substream, int cmd) chip->is_playing = 0; snd_azf3328_dbgplay("STOPPED PLAYBACK\n"); break; + case SNDRV_PCM_TRIGGER_SUSPEND: + snd_azf3328_dbgplay("SUSPEND PLAYBACK\n"); + /* make sure playback is stopped */ + snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, + snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS) & ~DMA_RESUME); + break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_PUSH NIY!\n"); break; @@ -995,6 +1020,7 @@ snd_azf3328_playback_trigger(struct snd_pcm_substream *substream, int cmd) snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_RELEASE NIY!\n"); break; default: + printk(KERN_ERR "FIXME: unknown trigger mode!\n"); return -EINVAL; } @@ -1068,6 +1094,13 @@ snd_azf3328_capture_trigger(struct snd_pcm_substream *substream, int cmd) chip->is_recording = 1; snd_azf3328_dbgplay("STARTED CAPTURE\n"); break; + case SNDRV_PCM_TRIGGER_RESUME: + snd_azf3328_dbgplay("RESUME CAPTURE\n"); + /* resume recording if we were active */ + if (chip->is_recording) + snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, + snd_azf3328_codec_inw(chip, IDX_IO_REC_FLAGS) | DMA_RESUME); + break; case SNDRV_PCM_TRIGGER_STOP: snd_azf3328_dbgplay("STOP CAPTURE\n"); @@ -1088,6 +1121,12 @@ snd_azf3328_capture_trigger(struct snd_pcm_substream *substream, int cmd) chip->is_recording = 0; snd_azf3328_dbgplay("STOPPED CAPTURE\n"); break; + case SNDRV_PCM_TRIGGER_SUSPEND: + snd_azf3328_dbgplay("SUSPEND CAPTURE\n"); + /* make sure recording is stopped */ + snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, + snd_azf3328_codec_inw(chip, IDX_IO_REC_FLAGS) & ~DMA_RESUME); + break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_PUSH NIY!\n"); break; @@ -1095,6 +1134,7 @@ snd_azf3328_capture_trigger(struct snd_pcm_substream *substream, int cmd) snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_RELEASE NIY!\n"); break; default: + printk(KERN_ERR "FIXME: unknown trigger mode!\n"); return -EINVAL; } @@ -1766,6 +1806,8 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) goto out_err; } + card->private_data = chip; + if ((err = snd_mpu401_uart_new( card, 0, MPU401_HW_MPU401, chip->mpu_port, 1, pci->irq, 0, &chip->rmidi)) < 0) { @@ -1791,6 +1833,8 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) } } + opl3->private_data = chip; + sprintf(card->longname, "%s at 0x%lx, irq %i", card->shortname, chip->codec_port, chip->irq); @@ -1834,11 +1878,80 @@ snd_azf3328_remove(struct pci_dev *pci) snd_azf3328_dbgcallleave(); } +#ifdef CONFIG_PM +static int +snd_azf3328_suspend(struct pci_dev *pci, pm_message_t state) +{ + struct snd_card *card = pci_get_drvdata(pci); + struct snd_azf3328 *chip = card->private_data; + int reg; + + snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); + + snd_pcm_suspend_all(chip->pcm); + + for (reg = 0; reg < AZF_IO_SIZE_MIXER_PM / 2; reg++) + chip->saved_regs_mixer[reg] = inw(chip->mixer_port + reg * 2); + + /* make sure to disable master volume etc. to prevent looping sound */ + snd_azf3328_mixer_set_mute(chip, IDX_MIXER_PLAY_MASTER, 1); + snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 1); + + for (reg = 0; reg < AZF_IO_SIZE_CODEC_PM / 2; reg++) + chip->saved_regs_codec[reg] = inw(chip->codec_port + reg * 2); + for (reg = 0; reg < AZF_IO_SIZE_IO2_PM / 2; reg++) + chip->saved_regs_io2[reg] = inw(chip->io2_port + reg * 2); + for (reg = 0; reg < AZF_IO_SIZE_MPU_PM / 2; reg++) + chip->saved_regs_mpu[reg] = inw(chip->mpu_port + reg * 2); + for (reg = 0; reg < AZF_IO_SIZE_SYNTH_PM / 2; reg++) + chip->saved_regs_synth[reg] = inw(chip->synth_port + reg * 2); + + pci_set_power_state(pci, PCI_D3hot); + pci_disable_device(pci); + pci_save_state(pci); + return 0; +} + +static int +snd_azf3328_resume(struct pci_dev *pci) +{ + struct snd_card *card = pci_get_drvdata(pci); + struct snd_azf3328 *chip = card->private_data; + int reg; + + pci_restore_state(pci); + pci_enable_device(pci); + pci_set_power_state(pci, PCI_D0); + pci_set_master(pci); + + for (reg = 0; reg < AZF_IO_SIZE_IO2_PM / 2; reg++) + outw(chip->saved_regs_io2[reg], chip->io2_port + reg * 2); + for (reg = 0; reg < AZF_IO_SIZE_MPU_PM / 2; reg++) + outw(chip->saved_regs_mpu[reg], chip->mpu_port + reg * 2); + for (reg = 0; reg < AZF_IO_SIZE_SYNTH_PM / 2; reg++) + outw(chip->saved_regs_synth[reg], chip->synth_port + reg * 2); + for (reg = 0; reg < AZF_IO_SIZE_MIXER_PM / 2; reg++) + outw(chip->saved_regs_mixer[reg], chip->mixer_port + reg * 2); + for (reg = 0; reg < AZF_IO_SIZE_CODEC_PM / 2; reg++) + outw(chip->saved_regs_codec[reg], chip->codec_port + reg * 2); + + snd_power_change_state(card, SNDRV_CTL_POWER_D0); + return 0; +} +#endif + + + + static struct pci_driver driver = { .name = "AZF3328", .id_table = snd_azf3328_ids, .probe = snd_azf3328_probe, .remove = __devexit_p(snd_azf3328_remove), +#ifdef CONFIG_PM + .suspend = snd_azf3328_suspend, + .resume = snd_azf3328_resume, +#endif }; static int __init diff --git a/sound/pci/azt3328.h b/sound/pci/azt3328.h index f489bdaf6d4..560a4653c0b 100644 --- a/sound/pci/azt3328.h +++ b/sound/pci/azt3328.h @@ -5,6 +5,9 @@ /*** main I/O area port indices ***/ /* (only 0x70 of 0x80 bytes saved/restored by Windows driver) */ +#define AZF_IO_SIZE_CODEC 0x80 +#define AZF_IO_SIZE_CODEC_PM 0x70 + /* the driver initialisation suggests a layout of 4 main areas: * from 0x00 (playback), from 0x20 (recording) and from 0x40 (maybe MPU401??). * And another area from 0x60 to 0x6f (DirectX timer, IRQ management, @@ -107,7 +110,8 @@ #define IRQ_UNKNOWN2 0x0080 /* probably unused */ #define IDX_IO_66H 0x66 /* writing 0xffff returns 0x0000 */ #define IDX_IO_SOME_VALUE 0x68 /* this is set to e.g. 0x3ff or 0x300, and writable; maybe some buffer limit, but I couldn't find out more, PU:0x00ff */ -#define IDX_IO_6AH 0x6A /* this WORD can be set to have bits 0x0028 activated; actually inhibits PCM playback!!! maybe power management?? */ +#define IDX_IO_6AH 0x6A /* this WORD can be set to have bits 0x0028 activated (FIXME: correct??); actually inhibits PCM playback!!! maybe power management?? */ + #define IO_6A_PAUSE_PLAYBACK 0x0200 /* bit 9; sure, this pauses playback, but what the heck is this really about?? */ #define IDX_IO_6CH 0x6C #define IDX_IO_6EH 0x6E /* writing 0xffff returns 0x83fe */ /* further I/O indices not saved/restored, so probably not used */ @@ -115,15 +119,25 @@ /*** I/O 2 area port indices ***/ /* (only 0x06 of 0x08 bytes saved/restored by Windows driver) */ +#define AZF_IO_SIZE_IO2 0x08 +#define AZF_IO_SIZE_IO2_PM 0x06 + #define IDX_IO2_LEGACY_ADDR 0x04 #define LEGACY_SOMETHING 0x01 /* OPL3?? */ #define LEGACY_JOY 0x08 +#define AZF_IO_SIZE_MPU 0x04 +#define AZF_IO_SIZE_MPU_PM 0x04 + +#define AZF_IO_SIZE_SYNTH 0x08 +#define AZF_IO_SIZE_SYNTH_PM 0x06 /*** mixer I/O area port indices ***/ /* (only 0x22 of 0x40 bytes saved/restored by Windows driver) - * generally spoken: AC97 register index = AZF3328 mixer reg index + 2 - * (in other words: AZF3328 NOT fully AC97 compliant) */ + * UNFORTUNATELY azf3328 is NOT truly AC97 compliant: see main file intro */ +#define AZF_IO_SIZE_MIXER 0x40 +#define AZF_IO_SIZE_MIXER_PM 0x22 + #define MIXER_VOLUME_RIGHT_MASK 0x001f #define MIXER_VOLUME_LEFT_MASK 0x1f00 #define MIXER_MUTE_MASK 0x8000 -- cgit v1.2.3 From 13769e3f21d6e9c59999c9bf6908278b878d05c5 Mon Sep 17 00:00:00 2001 From: Andreas Mohr Date: Wed, 17 May 2006 11:03:16 +0200 Subject: [ALSA] azt3328.c: add 3D sound mixer switch/rename controls - add 3D sound pre-3D/post-3D switch, as seen in standard AC-97 - rename controls to shorter and more accurate strings Signed-off-by: Andreas Mohr Signed-off-by: Takashi Iwai --- sound/pci/azt3328.c | 41 +++++++++++++++++++++++++++++++---------- sound/pci/azt3328.h | 16 ++++++++-------- 2 files changed, 39 insertions(+), 18 deletions(-) diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index f197fbac10a..c9af04ed200 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c @@ -39,8 +39,15 @@ * for compatibility reasons) has the following features: * * - builtin AC97 conformant codec (SNR over 80dB) - * (really AC97 compliant?? I really doubt it when looking - * at the mixer register layout) + * Note that "conformant" != "compliant"!! this chip's mixer register layout + * *differs* from the standard AC97 layout: + * they chose to not implement the headphone register (which is not a + * problem since it's merely optional), yet when doing this, they committed + * the grave sin of letting other registers follow immediately instead of + * keeping a headphone dummy register, thereby shifting the mixer register + * addresses illegally. So far unfortunately it looks like the very flexible + * ALSA AC97 support is still not enough to easily compensate for such a + * grave layout violation despite all tweaks and quirks mechanisms it offers. * - builtin genuine OPL3 * - full duplex 16bit playback/record at independent sampling rate * - MPU401 (+ legacy address support) FIXME: how to enable legacy addr?? @@ -96,6 +103,9 @@ * The standard suspend/resume functionality could probably make use of * some improvement, too... * - figure out what all unknown port bits are responsible for + * - figure out some cleverly evil scheme to possibly make ALSA AC97 code + * fully accept our quite incompatible ""AC97"" mixer and thus save some + * code (but I'm not too optimistic that doing this is possible at all) */ #include @@ -526,15 +536,18 @@ snd_azf3328_info_mixer_enum(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { static const char * const texts1[] = { - "ModemOut1", "ModemOut2" + "Mic1", "Mic2" }; static const char * const texts2[] = { - "MonoSelectSource1", "MonoSelectSource2" + "Mix", "Mic" }; static const char * const texts3[] = { "Mic", "CD", "Video", "Aux", "Line", "Mix", "Mix Mono", "Phone" }; + static const char * const texts4[] = { + "pre 3D", "post 3D" + }; struct azf3328_mixer_reg reg; snd_azf3328_mixer_reg_decode(®, kcontrol->private_value); @@ -545,10 +558,17 @@ snd_azf3328_info_mixer_enum(struct snd_kcontrol *kcontrol, uinfo->value.enumerated.item = reg.enum_c - 1U; if (reg.reg == IDX_MIXER_ADVCTL2) { - if (reg.lchan_shift == 8) /* modem out sel */ + switch(reg.lchan_shift) { + case 8: /* modem out sel */ strcpy(uinfo->value.enumerated.name, texts1[uinfo->value.enumerated.item]); - else /* mono sel source */ + break; + case 9: /* mono sel source */ strcpy(uinfo->value.enumerated.name, texts2[uinfo->value.enumerated.item]); + break; + case 15: /* PCM Out Path */ + strcpy(uinfo->value.enumerated.name, texts4[uinfo->value.enumerated.item]); + break; + } } else strcpy(uinfo->value.enumerated.name, texts3[uinfo->value.enumerated.item] @@ -641,13 +661,14 @@ static const struct snd_kcontrol_new snd_azf3328_mixer_controls[] __devinitdata AZF3328_MIXER_VOL_MONO("Modem Playback Volume", IDX_MIXER_MODEMOUT, 0x1f, 1), AZF3328_MIXER_SWITCH("Modem Capture Switch", IDX_MIXER_MODEMIN, 15, 1), AZF3328_MIXER_VOL_MONO("Modem Capture Volume", IDX_MIXER_MODEMIN, 0x1f, 1), - AZF3328_MIXER_ENUM("Modem Out Select", IDX_MIXER_ADVCTL2, 2, 8), - AZF3328_MIXER_ENUM("Mono Select Source", IDX_MIXER_ADVCTL2, 2, 9), + AZF3328_MIXER_ENUM("Mic Select", IDX_MIXER_ADVCTL2, 2, 8), + AZF3328_MIXER_ENUM("Mono Output Select", IDX_MIXER_ADVCTL2, 2, 9), + AZF3328_MIXER_ENUM("PCM", IDX_MIXER_ADVCTL2, 2, 15), /* PCM Out Path, place in front since it controls *both* 3D and Bass/Treble! */ AZF3328_MIXER_VOL_SPECIAL("Tone Control - Treble", IDX_MIXER_BASSTREBLE, 0x07, 1, 0), AZF3328_MIXER_VOL_SPECIAL("Tone Control - Bass", IDX_MIXER_BASSTREBLE, 0x07, 9, 0), AZF3328_MIXER_SWITCH("3D Control - Switch", IDX_MIXER_ADVCTL2, 13, 0), - AZF3328_MIXER_VOL_SPECIAL("3D Control - Wide", IDX_MIXER_ADVCTL1, 0x07, 1, 0), /* "3D Width" */ - AZF3328_MIXER_VOL_SPECIAL("3D Control - Space", IDX_MIXER_ADVCTL1, 0x03, 8, 0), /* "Hifi 3D" */ + AZF3328_MIXER_VOL_SPECIAL("3D Control - Width", IDX_MIXER_ADVCTL1, 0x07, 1, 0), /* "3D Width" */ + AZF3328_MIXER_VOL_SPECIAL("3D Control - Depth", IDX_MIXER_ADVCTL1, 0x03, 8, 0), /* "Hifi 3D" */ #if MIXER_TESTING AZF3328_MIXER_SWITCH("0", IDX_MIXER_ADVCTL2, 0, 0), AZF3328_MIXER_SWITCH("1", IDX_MIXER_ADVCTL2, 1, 0), diff --git a/sound/pci/azt3328.h b/sound/pci/azt3328.h index 560a4653c0b..b4f3e3cd006 100644 --- a/sound/pci/azt3328.h +++ b/sound/pci/azt3328.h @@ -90,7 +90,7 @@ #define IDX_IO_REC_DMA_CURROFS 0x34 /* PU:0x00000000 */ #define IDX_IO_REC_SOUNDFORMAT 0x36 /* PU:0x0000 */ -/** hmm, what is this I/O area for? MPU401?? (after playback, recording, ???, timer) **/ +/** hmm, what is this I/O area for? MPU401?? or external DAC via I2S?? (after playback, recording, ???, timer) **/ #define IDX_IO_SOMETHING_FLAGS 0x40 /* gets set to 0x34 just like port 0x0 and 0x20 on card init, PU:0x0000 */ /* general */ #define IDX_IO_42H 0x42 /* PU:0x0001 */ @@ -170,14 +170,14 @@ #define IDX_MIXER_ADVCTL1 0x1e /* unlisted bits are unmodifiable */ #define MIXER_ADVCTL1_3DWIDTH_MASK 0x000e - #define MIXER_ADVCTL1_HIFI3D_MASK 0x0300 -#define IDX_MIXER_ADVCTL2 0x20 /* resembles AC97_GENERAL_PURPOSE reg! */ + #define MIXER_ADVCTL1_HIFI3D_MASK 0x0300 /* yup, this is missing the high bit that official AC97 contains, plus it doesn't have linear bit value range behaviour but instead acts weirdly (possibly we're dealing with two *different* 3D settings here??) */ +#define IDX_MIXER_ADVCTL2 0x20 /* subset of AC97_GENERAL_PURPOSE reg! */ /* unlisted bits are unmodifiable */ - #define MIXER_ADVCTL2_BIT7 0x0080 /* WaveOut 3D Bypass? mutes WaveOut at LineOut */ - #define MIXER_ADVCTL2_BIT8 0x0100 /* is this Modem Out Select? */ - #define MIXER_ADVCTL2_BIT9 0x0200 /* Mono Select Source? */ - #define MIXER_ADVCTL2_BIT13 0x2000 /* 3D enable? */ - #define MIXER_ADVCTL2_BIT15 0x8000 /* unknown */ + #define MIXER_ADVCTL2_LPBK 0x0080 /* Loopback mode -- Win driver: "WaveOut3DBypass"? mutes WaveOut at LineOut */ + #define MIXER_ADVCTL2_MS 0x0100 /* Mic Select 0=Mic1, 1=Mic2 -- Win driver: "ModemOutSelect"?? */ + #define MIXER_ADVCTL2_MIX 0x0200 /* Mono output select 0=Mix, 1=Mic; Win driver: "MonoSelectSource"?? */ + #define MIXER_ADVCTL2_3D 0x2000 /* 3D Enhancement 1=on */ + #define MIXER_ADVCTL2_POP 0x8000 /* Pcm Out Path, 0=pre 3D, 1=post 3D */ #define IDX_MIXER_SOMETHING30H 0x30 /* used, but unknown??? */ -- cgit v1.2.3 From e2f872608af7f3c00beaa61ff6037e3cc5a66cf1 Mon Sep 17 00:00:00 2001 From: Andreas Mohr Date: Wed, 17 May 2006 11:04:19 +0200 Subject: [ALSA] azt3328.c: use kernel coding style Scope braces were not done the One True Kernel Way. Signed-off-by: Andreas Mohr Signed-off-by: Takashi Iwai --- sound/pci/azt3328.c | 70 ++++++++++++++++++----------------------------------- 1 file changed, 23 insertions(+), 47 deletions(-) diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index c9af04ed200..e68056c8158 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c @@ -33,7 +33,7 @@ * in the first place >:-P}), * I was forced to base this driver on reverse engineering * (3 weeks' worth of evenings filled with driver work). - * (and no, I did NOT go the easy way: to pick up a PCI128 for 9 Euros) + * (and no, I did NOT go the easy way: to pick up a SB PCI128 for 9 Euros) * * The AZF3328 chip (note: AZF3328, *not* AZT3328, that's just the driver name * for compatibility reasons) has the following features: @@ -339,10 +339,8 @@ snd_azf3328_mixer_write_volume_gradually(const struct snd_azf3328 *chip, int reg else dst_vol_left &= ~0x80; - do - { - if (!left_done) - { + do { + if (!left_done) { if (curr_vol_left > dst_vol_left) curr_vol_left--; else @@ -352,8 +350,7 @@ snd_azf3328_mixer_write_volume_gradually(const struct snd_azf3328 *chip, int reg left_done = 1; outb(curr_vol_left, portbase + 1); } - if (!right_done) - { + if (!right_done) { if (curr_vol_right > dst_vol_right) curr_vol_right--; else @@ -368,8 +365,7 @@ snd_azf3328_mixer_write_volume_gradually(const struct snd_azf3328 *chip, int reg } if (delay) mdelay(delay); - } - while ((!left_done) || (!right_done)); + } while ((!left_done) || (!right_done)); snd_azf3328_dbgcallleave(); } @@ -556,8 +552,7 @@ snd_azf3328_info_mixer_enum(struct snd_kcontrol *kcontrol, uinfo->value.enumerated.items = reg.enum_c; if (uinfo->value.enumerated.item > reg.enum_c - 1U) uinfo->value.enumerated.item = reg.enum_c - 1U; - if (reg.reg == IDX_MIXER_ADVCTL2) - { + if (reg.reg == IDX_MIXER_ADVCTL2) { switch(reg.lchan_shift) { case 8: /* modem out sel */ strcpy(uinfo->value.enumerated.name, texts1[uinfo->value.enumerated.item]); @@ -569,8 +564,7 @@ snd_azf3328_info_mixer_enum(struct snd_kcontrol *kcontrol, strcpy(uinfo->value.enumerated.name, texts4[uinfo->value.enumerated.item]); break; } - } - else + } else strcpy(uinfo->value.enumerated.name, texts3[uinfo->value.enumerated.item] ); return 0; @@ -586,12 +580,10 @@ snd_azf3328_get_mixer_enum(struct snd_kcontrol *kcontrol, snd_azf3328_mixer_reg_decode(®, kcontrol->private_value); val = snd_azf3328_mixer_inw(chip, reg.reg); - if (reg.reg == IDX_MIXER_REC_SELECT) - { + if (reg.reg == IDX_MIXER_REC_SELECT) { ucontrol->value.enumerated.item[0] = (val >> 8) & (reg.enum_c - 1); ucontrol->value.enumerated.item[1] = (val >> 0) & (reg.enum_c - 1); - } - else + } else ucontrol->value.enumerated.item[0] = (val >> reg.lchan_shift) & (reg.enum_c - 1); snd_azf3328_dbgmixer("get_enum: %02x is %04x -> %d|%d (shift %02d, enum_c %d)\n", @@ -611,16 +603,13 @@ snd_azf3328_put_mixer_enum(struct snd_kcontrol *kcontrol, snd_azf3328_mixer_reg_decode(®, kcontrol->private_value); oreg = snd_azf3328_mixer_inw(chip, reg.reg); val = oreg; - if (reg.reg == IDX_MIXER_REC_SELECT) - { + if (reg.reg == IDX_MIXER_REC_SELECT) { if (ucontrol->value.enumerated.item[0] > reg.enum_c - 1U || ucontrol->value.enumerated.item[1] > reg.enum_c - 1U) return -EINVAL; val = (ucontrol->value.enumerated.item[0] << 8) | (ucontrol->value.enumerated.item[1] << 0); - } - else - { + } else { if (ucontrol->value.enumerated.item[0] > reg.enum_c - 1U) return -EINVAL; val &= ~((reg.enum_c - 1) << reg.lchan_shift); @@ -846,22 +835,18 @@ snd_azf3328_setdmaa(struct snd_azf3328 *chip, unsigned int is_running; snd_azf3328_dbgcallenter(); - if (do_recording) - { + if (do_recording) { /* access capture registers, i.e. skip playback reg section */ portbase = chip->codec_port + 0x20; is_running = chip->is_recording; - } - else - { + } else { /* access the playback register section */ portbase = chip->codec_port + 0x00; is_running = chip->is_playing; } /* AZF3328 uses a two buffer pointer DMA playback approach */ - if (!is_running) - { + if (!is_running) { unsigned long addr_area2; unsigned long count_areas, count_tmp; /* width 32bit -- overflow!! */ count_areas = size/2; @@ -1224,8 +1209,7 @@ snd_azf3328_interrupt(int irq, void *dev_id, struct pt_regs *regs) snd_azf3328_codec_inw(chip, IDX_IO_PLAY_IRQTYPE), status); - if (status & IRQ_TIMER) - { + if (status & IRQ_TIMER) { /* snd_azf3328_dbgplay("timer %ld\n", inl(chip->codec_port+IDX_IO_TIMER_VALUE) & TIMER_VALUE_MASK); */ if (chip->timer) snd_timer_interrupt(chip->timer, chip->timer->sticks); @@ -1235,50 +1219,43 @@ snd_azf3328_interrupt(int irq, void *dev_id, struct pt_regs *regs) spin_unlock(&chip->reg_lock); snd_azf3328_dbgplay("azt3328: timer IRQ\n"); } - if (status & IRQ_PLAYBACK) - { + if (status & IRQ_PLAYBACK) { spin_lock(&chip->reg_lock); which = snd_azf3328_codec_inb(chip, IDX_IO_PLAY_IRQTYPE); /* ack all IRQ types immediately */ snd_azf3328_codec_outb(chip, IDX_IO_PLAY_IRQTYPE, which); spin_unlock(&chip->reg_lock); - if (chip->pcm && chip->playback_substream) - { + if (chip->pcm && chip->playback_substream) { snd_pcm_period_elapsed(chip->playback_substream); snd_azf3328_dbgplay("PLAY period done (#%x), @ %x\n", which, inl(chip->codec_port+IDX_IO_PLAY_DMA_CURRPOS)); - } - else + } else snd_azf3328_dbgplay("azt3328: ouch, irq handler problem!\n"); if (which & IRQ_PLAY_SOMETHING) snd_azf3328_dbgplay("azt3328: unknown play IRQ type occurred, please report!\n"); } - if (status & IRQ_RECORDING) - { + if (status & IRQ_RECORDING) { spin_lock(&chip->reg_lock); which = snd_azf3328_codec_inb(chip, IDX_IO_REC_IRQTYPE); /* ack all IRQ types immediately */ snd_azf3328_codec_outb(chip, IDX_IO_REC_IRQTYPE, which); spin_unlock(&chip->reg_lock); - if (chip->pcm && chip->capture_substream) - { + if (chip->pcm && chip->capture_substream) { snd_pcm_period_elapsed(chip->capture_substream); snd_azf3328_dbgplay("REC period done (#%x), @ %x\n", which, inl(chip->codec_port+IDX_IO_REC_DMA_CURRPOS)); - } - else + } else snd_azf3328_dbgplay("azt3328: ouch, irq handler problem!\n"); if (which & IRQ_REC_SOMETHING) snd_azf3328_dbgplay("azt3328: unknown rec IRQ type occurred, please report!\n"); } /* MPU401 has less critical IRQ requirements * than timer and playback/recording, right? */ - if (status & IRQ_MPU401) - { + if (status & IRQ_MPU401) { snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data, regs); /* hmm, do we have to ack the IRQ here somehow? @@ -1572,8 +1549,7 @@ snd_azf3328_timer_start(struct snd_timer *timer) snd_azf3328_dbgcallenter(); chip = snd_timer_chip(timer); delay = ((timer->sticks * seqtimer_scaling) - 1) & TIMER_VALUE_MASK; - if (delay < 49) - { + if (delay < 49) { /* uhoh, that's not good, since user-space won't know about * this timing tweak * (we need to do it to avoid a lockup, though) */ -- cgit v1.2.3 From 778b6e1b2da260adf3d3254aaa35bffd1eb05b42 Mon Sep 17 00:00:00 2001 From: Felix Kuehling Date: Wed, 17 May 2006 11:22:21 +0200 Subject: [ALSA] hda - Add support for the ATI RS600 HDMI audio device Add support for the ATI RS600 HDMI audio device. It has a one-stream pure digital stereo codec that isn't handled by the generic codec support. Signed-off-by: Felix Kuehling Signed-off-by: Takashi Iwai --- sound/pci/hda/Makefile | 2 +- sound/pci/hda/hda_intel.c | 16 ++++ sound/pci/hda/hda_patch.h | 3 + sound/pci/hda/patch_atihdmi.c | 165 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 185 insertions(+), 1 deletion(-) create mode 100644 sound/pci/hda/patch_atihdmi.c diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile index ddfb5ff7fb8..dbacba6177d 100644 --- a/sound/pci/hda/Makefile +++ b/sound/pci/hda/Makefile @@ -1,5 +1,5 @@ snd-hda-intel-objs := hda_intel.o -snd-hda-codec-objs := hda_codec.o hda_generic.o patch_realtek.o patch_cmedia.o patch_analog.o patch_sigmatel.o patch_si3054.o +snd-hda-codec-objs := hda_codec.o hda_generic.o patch_realtek.o patch_cmedia.o patch_analog.o patch_sigmatel.o patch_si3054.o patch_atihdmi.o ifdef CONFIG_PROC_FS snd-hda-codec-objs += hda_proc.o endif diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index e821d65afa1..0154389bf95 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -82,6 +82,7 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6}," "{Intel, ICH8}," "{ATI, SB450}," "{ATI, SB600}," + "{ATI, RS600}," "{VIA, VT8251}," "{VIA, VT8237A}," "{SiS, SIS966}," @@ -167,6 +168,12 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; #define ULI_PLAYBACK_INDEX 5 #define ULI_NUM_PLAYBACK 6 +/* ATI HDMI has 1 playback and 0 capture */ +#define ATIHDMI_CAPTURE_INDEX 0 +#define ATIHDMI_NUM_CAPTURE 0 +#define ATIHDMI_PLAYBACK_INDEX 0 +#define ATIHDMI_NUM_PLAYBACK 1 + /* this number is statically defined for simplicity */ #define MAX_AZX_DEV 16 @@ -331,6 +338,7 @@ struct azx { enum { AZX_DRIVER_ICH, AZX_DRIVER_ATI, + AZX_DRIVER_ATIHDMI, AZX_DRIVER_VIA, AZX_DRIVER_SIS, AZX_DRIVER_ULI, @@ -340,6 +348,7 @@ enum { static char *driver_short_names[] __devinitdata = { [AZX_DRIVER_ICH] = "HDA Intel", [AZX_DRIVER_ATI] = "HDA ATI SB", + [AZX_DRIVER_ATIHDMI] = "HDA ATI HDMI", [AZX_DRIVER_VIA] = "HDA VIA VT82xx", [AZX_DRIVER_SIS] = "HDA SIS966", [AZX_DRIVER_ULI] = "HDA ULI M5461", @@ -1495,6 +1504,12 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, chip->playback_index_offset = ULI_PLAYBACK_INDEX; chip->capture_index_offset = ULI_CAPTURE_INDEX; break; + case AZX_DRIVER_ATIHDMI: + chip->playback_streams = ATIHDMI_NUM_PLAYBACK; + chip->capture_streams = ATIHDMI_NUM_CAPTURE; + chip->playback_index_offset = ATIHDMI_PLAYBACK_INDEX; + chip->capture_index_offset = ATIHDMI_CAPTURE_INDEX; + break; default: chip->playback_streams = ICH6_NUM_PLAYBACK; chip->capture_streams = ICH6_NUM_CAPTURE; @@ -1621,6 +1636,7 @@ static struct pci_device_id azx_ids[] __devinitdata = { { 0x8086, 0x284b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH8 */ { 0x1002, 0x437b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB450 */ { 0x1002, 0x4383, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB600 */ + { 0x1002, 0x793b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RS600 HDMI */ { 0x1106, 0x3288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_VIA }, /* VIA VT8251/VT8237A */ { 0x1039, 0x7502, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_SIS }, /* SIS966 */ { 0x10b9, 0x5461, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ULI }, /* ULI M5461 */ diff --git a/sound/pci/hda/hda_patch.h b/sound/pci/hda/hda_patch.h index acaef3c811b..0b668793fac 100644 --- a/sound/pci/hda/hda_patch.h +++ b/sound/pci/hda/hda_patch.h @@ -12,6 +12,8 @@ extern struct hda_codec_preset snd_hda_preset_analog[]; extern struct hda_codec_preset snd_hda_preset_sigmatel[]; /* SiLabs 3054/3055 modem codecs */ extern struct hda_codec_preset snd_hda_preset_si3054[]; +/* ATI HDMI codecs */ +extern struct hda_codec_preset snd_hda_preset_atihdmi[]; static const struct hda_codec_preset *hda_preset_tables[] = { snd_hda_preset_realtek, @@ -19,5 +21,6 @@ static const struct hda_codec_preset *hda_preset_tables[] = { snd_hda_preset_analog, snd_hda_preset_sigmatel, snd_hda_preset_si3054, + snd_hda_preset_atihdmi, NULL }; diff --git a/sound/pci/hda/patch_atihdmi.c b/sound/pci/hda/patch_atihdmi.c new file mode 100644 index 00000000000..a27440ffd1c --- /dev/null +++ b/sound/pci/hda/patch_atihdmi.c @@ -0,0 +1,165 @@ +/* + * Universal Interface for Intel High Definition Audio Codec + * + * HD audio interface patch for ATI HDMI codecs + * + * Copyright (c) 2006 ATI Technologies Inc. + * + * + * This driver is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This driver is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include "hda_codec.h" +#include "hda_local.h" + +struct atihdmi_spec { + struct hda_multi_out multiout; + + struct hda_pcm pcm_rec; +}; + +static struct hda_verb atihdmi_basic_init[] = { + /* enable digital output on pin widget */ + { 0x03, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + {} /* terminator */ +}; + +/* + * Controls + */ +static int atihdmi_build_controls(struct hda_codec *codec) +{ + struct atihdmi_spec *spec = codec->spec; + int err; + + err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid); + if (err < 0) + return err; + + return 0; +} + +static int atihdmi_init(struct hda_codec *codec) +{ + snd_hda_sequence_write(codec, atihdmi_basic_init); + return 0; +} + +#ifdef CONFIG_PM +/* + * resume + */ +static int atihdmi_resume(struct hda_codec *codec) +{ + atihdmi_init(codec); + snd_hda_resume_spdif_out(codec); + + return 0; +} +#endif + +/* + * Digital out + */ +static int atihdmi_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + struct snd_pcm_substream *substream) +{ + struct atihdmi_spec *spec = codec->spec; + return snd_hda_multi_out_dig_open(codec, &spec->multiout); +} + +static int atihdmi_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + struct snd_pcm_substream *substream) +{ + struct atihdmi_spec *spec = codec->spec; + return snd_hda_multi_out_dig_close(codec, &spec->multiout); +} + +static struct hda_pcm_stream atihdmi_pcm_digital_playback = { + .substreams = 1, + .channels_min = 2, + .channels_max = 2, + .nid = 0x2, /* NID to query formats and rates and setup streams */ + .ops = { + .open = atihdmi_dig_playback_pcm_open, + .close = atihdmi_dig_playback_pcm_close + }, +}; + +static int atihdmi_build_pcms(struct hda_codec *codec) +{ + struct atihdmi_spec *spec = codec->spec; + struct hda_pcm *info = &spec->pcm_rec; + + codec->num_pcms = 1; + codec->pcm_info = info; + + info->name = "ATI HDMI"; + info->stream[SNDRV_PCM_STREAM_PLAYBACK] = atihdmi_pcm_digital_playback; + + return 0; +} + +static void atihdmi_free(struct hda_codec *codec) +{ + kfree(codec->spec); +} + +static struct hda_codec_ops atihdmi_patch_ops = { + .build_controls = atihdmi_build_controls, + .build_pcms = atihdmi_build_pcms, + .init = atihdmi_init, + .free = atihdmi_free, +#ifdef CONFIG_PM + .resume = atihdmi_resume, +#endif +}; + +static int patch_atihdmi(struct hda_codec *codec) +{ + struct atihdmi_spec *spec; + + spec = kzalloc(sizeof(*spec), GFP_KERNEL); + if (spec == NULL) + return -ENOMEM; + + codec->spec = spec; + + spec->multiout.num_dacs = 0; /* no analog */ + spec->multiout.max_channels = 2; + spec->multiout.dig_out_nid = 0x2; /* NID for copying analog to digital, + * seems to be unused in pure-digital + * case. */ + + codec->patch_ops = atihdmi_patch_ops; + + return 0; +} + +/* + * patch entries + */ +struct hda_codec_preset snd_hda_preset_atihdmi[] = { + { .id = 0x1002793c, .name = "ATI RS600 HDMI", .patch = patch_atihdmi }, + {} /* terminator */ +}; -- cgit v1.2.3 From 9b87819b61060a3d32d5982f5ee998c22ab8ca27 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 17 May 2006 11:26:39 +0200 Subject: [ALSA] Fix description of snd-hda-intel driver in document Fixed the description of snd-hda-intel driver in ALSA-Configuration.txt document. Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/ALSA-Configuration.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 89a12a64385..017e930fa05 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -709,8 +709,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. Module snd-hda-intel -------------------- - Module for Intel HD Audio (ICH6, ICH6M, ICH7), ATI SB450, - VIA VT8251/VT8237A + Module for Intel HD Audio (ICH6, ICH6M, ESB2, ICH7, ICH8), + ATI SB450, SB600, RS600, + VIA VT8251/VT8237A, + SIS966, ULI M5461 model - force the model name position_fix - Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size) -- cgit v1.2.3 From 0fbf405c583e6ee6d7227eb938a096d0998f7e78 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 17 May 2006 17:10:35 +0200 Subject: [ALSA] Fix pcm-draining of capture stream in PCM middle layer Fix the draining of PCM capture stream in the PCM middle layer. snd_pcm_drain() ignored capture streams, but it should change the state to SNDRV_PCM_DRAINING. Signed-off-by: Takashi Iwai --- sound/core/pcm_native.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index a998f88e3f3..9e495244eee 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -1469,8 +1469,6 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream) } } up_read(&snd_pcm_link_rwsem); - if (! num_drecs) - goto _error; snd_pcm_stream_lock_irq(substream); /* resume pause */ -- cgit v1.2.3 From 6581f4e74d8541dd7d579f64e94822622cbb1654 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 17 May 2006 17:14:51 +0200 Subject: [ALSA] Remove zero-initialization of static variables Removed zero-initializations of static variables. A tiny optimization. Signed-off-by: Takashi Iwai --- sound/arm/sa11xx-uda1341.c | 2 +- sound/core/info.c | 8 ++++---- sound/core/init.c | 6 +++--- sound/core/oss/pcm_oss.c | 2 +- sound/core/pcm.c | 2 +- sound/core/rawmidi.c | 2 +- sound/core/seq/seq_device.c | 2 +- sound/core/seq/seq_dummy.c | 2 +- sound/core/sound.c | 2 +- sound/core/sound_oss.c | 2 +- sound/core/timer.c | 2 +- sound/drivers/virmidi.c | 2 +- sound/isa/gus/interwave.c | 4 ++-- sound/isa/opl3sa2.c | 2 +- sound/isa/sb/emu8000_patch.c | 2 +- sound/isa/sb/sb16.c | 2 +- sound/isa/wavefront/wavefront.c | 2 +- sound/pci/ali5451/ali5451.c | 2 +- sound/pci/au88x0/au88x0_xtalk.c | 29 ++++++----------------------- sound/pci/bt87x.c | 2 +- sound/pci/cs46xx/cs46xx.c | 4 ++-- sound/pci/emu10k1/emu10k1.c | 8 ++++---- sound/pci/es1968.c | 2 +- sound/pci/fm801.c | 2 +- sound/pci/intel8x0.c | 2 +- sound/pci/intel8x0m.c | 2 +- sound/pci/rme9652/rme9652.c | 2 +- sound/pci/sonicvibes.c | 4 ++-- sound/sparc/dbri.c | 4 ++-- 29 files changed, 46 insertions(+), 63 deletions(-) diff --git a/sound/arm/sa11xx-uda1341.c b/sound/arm/sa11xx-uda1341.c index 9211348824a..b88fb0c5a68 100644 --- a/sound/arm/sa11xx-uda1341.c +++ b/sound/arm/sa11xx-uda1341.c @@ -112,7 +112,7 @@ MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("SA1100/SA1111 + UDA1341TS driver for ALSA"); MODULE_SUPPORTED_DEVICE("{{UDA1341,iPAQ H3600 UDA1341TS}}"); -static char *id = NULL; /* ID for this card */ +static char *id; /* ID for this card */ module_param(id, charp, 0444); MODULE_PARM_DESC(id, "ID string for SA1100/SA1111 + UDA1341TS soundcard."); diff --git a/sound/core/info.c b/sound/core/info.c index c8eeaea9d69..10c1772bf3e 100644 --- a/sound/core/info.c +++ b/sound/core/info.c @@ -143,12 +143,12 @@ EXPORT_SYMBOL(snd_iprintf); */ -static struct proc_dir_entry *snd_proc_root = NULL; -struct snd_info_entry *snd_seq_root = NULL; +static struct proc_dir_entry *snd_proc_root; +struct snd_info_entry *snd_seq_root; EXPORT_SYMBOL(snd_seq_root); #ifdef CONFIG_SND_OSSEMUL -struct snd_info_entry *snd_oss_root = NULL; +struct snd_info_entry *snd_oss_root; #endif static inline void snd_info_entry_prepare(struct proc_dir_entry *de) @@ -972,7 +972,7 @@ EXPORT_SYMBOL(snd_info_unregister); */ -static struct snd_info_entry *snd_info_version_entry = NULL; +static struct snd_info_entry *snd_info_version_entry; static void snd_info_version_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) { diff --git a/sound/core/init.c b/sound/core/init.c index 38b2d4a9d67..4d9258884e4 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -38,8 +38,8 @@ struct snd_shutdown_f_ops { struct snd_shutdown_f_ops *next; }; -static unsigned int snd_cards_lock = 0; /* locked for registering/using */ -struct snd_card *snd_cards[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = NULL}; +static unsigned int snd_cards_lock; /* locked for registering/using */ +struct snd_card *snd_cards[SNDRV_CARDS]; EXPORT_SYMBOL(snd_cards); static DEFINE_MUTEX(snd_card_mutex); @@ -529,7 +529,7 @@ int snd_card_register(struct snd_card *card) EXPORT_SYMBOL(snd_card_register); #ifdef CONFIG_PROC_FS -static struct snd_info_entry *snd_card_info_entry = NULL; +static struct snd_info_entry *snd_card_info_entry; static void snd_card_info_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 4395285aa6a..f5ff4f4a16e 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -45,7 +45,7 @@ #define OSS_ALSAEMULVER _SIOR ('M', 249, int) -static int dsp_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 0}; +static int dsp_map[SNDRV_CARDS]; static int adsp_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1}; static int nonblock_open = 1; diff --git a/sound/core/pcm.c b/sound/core/pcm.c index bc00f9b00cb..7581edd7b9f 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -1072,7 +1072,7 @@ static void snd_pcm_proc_read(struct snd_info_entry *entry, mutex_unlock(®ister_mutex); } -static struct snd_info_entry *snd_pcm_proc_entry = NULL; +static struct snd_info_entry *snd_pcm_proc_entry; static void snd_pcm_proc_init(void) { diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 08a41e5023c..8c15c66eb4a 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -43,7 +43,7 @@ MODULE_DESCRIPTION("Midlevel RawMidi code for ALSA."); MODULE_LICENSE("GPL"); #ifdef CONFIG_SND_OSSEMUL -static int midi_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 0}; +static int midi_map[SNDRV_CARDS]; static int amidi_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1}; module_param_array(midi_map, int, NULL, 0444); MODULE_PARM_DESC(midi_map, "Raw MIDI device number assigned to 1st OSS device."); diff --git a/sound/core/seq/seq_device.c b/sound/core/seq/seq_device.c index 1e4bc402f00..d812dc88636 100644 --- a/sound/core/seq/seq_device.c +++ b/sound/core/seq/seq_device.c @@ -80,7 +80,7 @@ static LIST_HEAD(opslist); static int num_ops; static DEFINE_MUTEX(ops_mutex); #ifdef CONFIG_PROC_FS -static struct snd_info_entry *info_entry = NULL; +static struct snd_info_entry *info_entry; #endif /* diff --git a/sound/core/seq/seq_dummy.c b/sound/core/seq/seq_dummy.c index 9eb1c744f77..e55488d1237 100644 --- a/sound/core/seq/seq_dummy.c +++ b/sound/core/seq/seq_dummy.c @@ -66,7 +66,7 @@ MODULE_LICENSE("GPL"); MODULE_ALIAS("snd-seq-client-" __stringify(SNDRV_SEQ_CLIENT_DUMMY)); static int ports = 1; -static int duplex = 0; +static int duplex; module_param(ports, int, 0444); MODULE_PARM_DESC(ports, "number of ports to be created"); diff --git a/sound/core/sound.c b/sound/core/sound.c index 02c8cc4ebff..cd862728346 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c @@ -332,7 +332,7 @@ EXPORT_SYMBOL(snd_unregister_device); * INFO PART */ -static struct snd_info_entry *snd_minor_info_entry = NULL; +static struct snd_info_entry *snd_minor_info_entry; static const char *snd_device_type_name(int type) { diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c index 0043c9a97de..74f0fe5a1ba 100644 --- a/sound/core/sound_oss.c +++ b/sound/core/sound_oss.c @@ -209,7 +209,7 @@ EXPORT_SYMBOL(snd_unregister_oss_device); #ifdef CONFIG_PROC_FS -static struct snd_info_entry *snd_minor_info_oss_entry = NULL; +static struct snd_info_entry *snd_minor_info_oss_entry; static const char *snd_oss_device_type_name(int type) { diff --git a/sound/core/timer.c b/sound/core/timer.c index d92f73c2c6b..78199f58b93 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -1106,7 +1106,7 @@ static void snd_timer_proc_read(struct snd_info_entry *entry, mutex_unlock(®ister_mutex); } -static struct snd_info_entry *snd_timer_proc_entry = NULL; +static struct snd_info_entry *snd_timer_proc_entry; static void __init snd_timer_proc_init(void) { diff --git a/sound/drivers/virmidi.c b/sound/drivers/virmidi.c index 59171f8200d..72d09b304db 100644 --- a/sound/drivers/virmidi.c +++ b/sound/drivers/virmidi.c @@ -65,7 +65,7 @@ MODULE_SUPPORTED_DEVICE("{{ALSA,Virtual rawmidi device}}"); static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0}; +static int enable[SNDRV_CARDS]; static int midi_devs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 4}; module_param_array(index, int, NULL, 0444); diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c index 4298d339e78..866300f2acb 100644 --- a/sound/isa/gus/interwave.c +++ b/sound/isa/gus/interwave.c @@ -70,9 +70,9 @@ static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */ static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */ static int joystick_dac[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 29}; /* 0 to 31, (0.59V-4.52V or 0.389V-2.98V) */ -static int midi[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; +static int midi[SNDRV_CARDS]; static int pcm_channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; -static int effect[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; +static int effect[SNDRV_CARDS]; #ifdef SNDRV_STB #define PFX "interwave-stb: " diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c index 6d889052c32..931ff75e543 100644 --- a/sound/isa/opl3sa2.c +++ b/sound/isa/opl3sa2.c @@ -59,7 +59,7 @@ static long midi_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;/* 0x330,0x300 */ static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 0,1,3,5,9,11,12,15 */ static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 1,3,5,6,7 */ static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 1,3,5,6,7 */ -static int opl3sa3_ymode[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 0 }; /* 0,1,2,3 */ /*SL Added*/ +static int opl3sa3_ymode[SNDRV_CARDS]; /* 0,1,2,3 */ /*SL Added*/ module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for OPL3-SA soundcard."); diff --git a/sound/isa/sb/emu8000_patch.c b/sound/isa/sb/emu8000_patch.c index 80b1cf84a1a..1be16c9700f 100644 --- a/sound/isa/sb/emu8000_patch.c +++ b/sound/isa/sb/emu8000_patch.c @@ -23,7 +23,7 @@ #include #include -static int emu8000_reset_addr = 0; +static int emu8000_reset_addr; module_param(emu8000_reset_addr, int, 0444); MODULE_PARM_DESC(emu8000_reset_addr, "reset write address at each time (makes slowdown)"); diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c index 6333f900eae..7f7f05fa518 100644 --- a/sound/isa/sb/sb16.c +++ b/sound/isa/sb/sb16.c @@ -85,7 +85,7 @@ static int dma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3 */ static int dma16[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 5,6,7 */ static int mic_agc[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; #ifdef CONFIG_SND_SB16_CSP -static int csp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; +static int csp[SNDRV_CARDS]; #endif #ifdef SNDRV_SBAWE_EMU8000 static int seq_ports[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 4}; diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c index 7ae86f82c3f..9eb27082c65 100644 --- a/sound/isa/wavefront/wavefront.c +++ b/sound/isa/wavefront/wavefront.c @@ -50,7 +50,7 @@ static int ics2115_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 2,9,11,12,15 */ static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */ static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */ -static int use_cs4232_midi[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; +static int use_cs4232_midi[SNDRV_CARDS]; module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for WaveFront soundcard."); diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index 4f01ef10fac..5dfdbf6657f 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c @@ -49,7 +49,7 @@ MODULE_SUPPORTED_DEVICE("{{ALI,M5451,pci},{ALI,M5451}}"); static int index = SNDRV_DEFAULT_IDX1; /* Index */ static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ static int pcm_channels = 32; -static int spdif = 0; +static int spdif; module_param(index, int, 0444); MODULE_PARM_DESC(index, "Index value for ALI M5451 PCI Audio."); diff --git a/sound/pci/au88x0/au88x0_xtalk.c b/sound/pci/au88x0/au88x0_xtalk.c index 4534e1882ad..b4151e208b7 100644 --- a/sound/pci/au88x0/au88x0_xtalk.c +++ b/sound/pci/au88x0/au88x0_xtalk.c @@ -66,31 +66,20 @@ static xtalk_gains_t const asXtalkGainsAllChan = { 0 //0x7FFF,0x7FFF,0x7FFF,0x7FFF,0x7fff,0x7FFF,0x7FFF,0x7FFF,0x7FFF,0x7fff }; -static xtalk_gains_t const asXtalkGainsZeros = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; +static xtalk_gains_t const asXtalkGainsZeros; -static xtalk_dline_t const alXtalkDlineZeros = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0 -}; +static xtalk_dline_t const alXtalkDlineZeros; static xtalk_dline_t const alXtalkDlineTest = { 0xFC18, 0x03E8FFFF, 0x186A0, 0x7960FFFE, 1, 0xFFFFFFFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -static xtalk_instate_t const asXtalkInStateZeros = { 0, 0, 0, 0 }; +static xtalk_instate_t const asXtalkInStateZeros; static xtalk_instate_t const asXtalkInStateTest = { 0xFF80, 0x0080, 0xFFFF, 0x0001 }; -static xtalk_state_t const asXtalkOutStateZeros = { - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0} -}; +static xtalk_state_t const asXtalkOutStateZeros; + static short const sDiamondKLeftEq = 0x401d; static short const sDiamondKRightEq = 0x401d; static short const sDiamondKLeftXt = 0xF90E; @@ -162,13 +151,7 @@ static xtalk_coefs_t const asXtalkNarrowCoefsRightXt = { {0, 0, 0, 0, 0} }; -static xtalk_coefs_t const asXtalkCoefsZeros = { - {0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0} -}; +static xtalk_coefs_t const asXtalkCoefsZeros; static xtalk_coefs_t const asXtalkCoefsPipe = { {0, 0, 0x0FA0, 0, 0}, {0, 0, 0x0FA0, 0, 0}, diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c index 9ee07d4aac1..aa21cc74a85 100644 --- a/sound/pci/bt87x.c +++ b/sound/pci/bt87x.c @@ -44,7 +44,7 @@ MODULE_SUPPORTED_DEVICE("{{Brooktree,Bt878}," static int index[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -2}; /* Exclude the first card */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ -static int digital_rate[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 0 }; /* digital input rate */ +static int digital_rate[SNDRV_CARDS]; /* digital input rate */ static int load_all; /* allow to load the non-whitelisted cards */ module_param_array(index, int, NULL, 0444); diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c index 848d772ae3c..772dc52bfeb 100644 --- a/sound/pci/cs46xx/cs46xx.c +++ b/sound/pci/cs46xx/cs46xx.c @@ -48,8 +48,8 @@ MODULE_SUPPORTED_DEVICE("{{Cirrus Logic,Sound Fusion (CS4280)}," static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ -static int external_amp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; -static int thinkpad[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; +static int external_amp[SNDRV_CARDS]; +static int thinkpad[SNDRV_CARDS]; static int mmap_valid[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; module_param_array(index, int, NULL, 0444); diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c index 42b11ba1d21..549673ea14a 100644 --- a/sound/pci/emu10k1/emu10k1.c +++ b/sound/pci/emu10k1/emu10k1.c @@ -46,13 +46,13 @@ MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB Live!/PCI512/E-mu APS}," static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ -static int extin[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; -static int extout[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; +static int extin[SNDRV_CARDS]; +static int extout[SNDRV_CARDS]; static int seq_ports[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 4}; static int max_synth_voices[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 64}; static int max_buffer_size[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 128}; -static int enable_ir[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; -static uint subsystem[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; /* Force card subsystem model */ +static int enable_ir[SNDRV_CARDS]; +static uint subsystem[SNDRV_CARDS]; /* Force card subsystem model */ module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for the EMU10K1 soundcard."); diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index 5ff4175c7b6..f43bd380ac2 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c @@ -132,7 +132,7 @@ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card * static int total_bufsize[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1024 }; static int pcm_substreams_p[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 4 }; static int pcm_substreams_c[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1 }; -static int clock[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; +static int clock[SNDRV_CARDS]; static int use_pm[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; static int enable_mpu[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; #ifdef SUPPORT_JOYSTICK diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index d72fc28c580..0ec90f37731 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c @@ -56,7 +56,7 @@ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card * * 3 = MediaForte 64-PCR * High 16-bits are video (radio) device number + 1 */ -static int tea575x_tuner[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 0 }; +static int tea575x_tuner[SNDRV_CARDS]; module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for the FM801 soundcard."); diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index a4e5b8115a6..e09fb7f9e77 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -66,7 +66,7 @@ MODULE_SUPPORTED_DEVICE("{{Intel,82801AA-ICH}," static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ -static int ac97_clock = 0; +static int ac97_clock; static char *ac97_quirk; static int buggy_semaphore; static int buggy_irq = -1; /* auto-check */ diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index 20acb1a7e92..24703d75b65 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c @@ -59,7 +59,7 @@ MODULE_SUPPORTED_DEVICE("{{Intel,82801AA-ICH}," static int index = -2; /* Exclude the first card */ static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ -static int ac97_clock = 0; +static int ac97_clock; module_param(index, int, 0444); MODULE_PARM_DESC(index, "Index value for Intel i8x0 modemcard."); diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c index ac14b2733f7..3b945e8c1b1 100644 --- a/sound/pci/rme9652/rme9652.c +++ b/sound/pci/rme9652/rme9652.c @@ -41,7 +41,7 @@ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ -static int precise_ptr[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 0 }; /* Enable precise pointer */ +static int precise_ptr[SNDRV_CARDS]; /* Enable precise pointer */ module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for RME Digi9652 (Hammerfall) soundcard."); diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c index a7830417292..51775706c84 100644 --- a/sound/pci/sonicvibes.c +++ b/sound/pci/sonicvibes.c @@ -54,8 +54,8 @@ MODULE_SUPPORTED_DEVICE("{{S3,SonicVibes PCI}}"); static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ -static int reverb[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; -static int mge[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; +static int reverb[SNDRV_CARDS]; +static int mge[SNDRV_CARDS]; static unsigned int dmaio = 0x7a00; /* DDMA i/o address */ module_param_array(index, int, NULL, 0444); diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c index db6539126d2..5eecdd09a79 100644 --- a/sound/sparc/dbri.c +++ b/sound/sparc/dbri.c @@ -92,7 +92,7 @@ MODULE_PARM_DESC(enable, "Enable Sun DBRI soundcard."); #define D_USR (1<<4) #define D_DESC (1<<5) -static int dbri_debug = 0; +static int dbri_debug; module_param(dbri_debug, int, 0644); MODULE_PARM_DESC(dbri_debug, "Debug value for Sun DBRI soundcard."); @@ -593,7 +593,7 @@ struct snd_dbri { /* Return a pointer to dbri_streaminfo */ #define DBRI_STREAM(dbri, substream) &dbri->stream_info[DBRI_STREAMNO(substream)] -static struct snd_dbri *dbri_list = NULL; /* All DBRI devices */ +static struct snd_dbri *dbri_list; /* All DBRI devices */ /* * Short data pipes transmit LSB first. The CS4215 receives MSB first. Grrr. -- cgit v1.2.3 From 474167d646cb2147b9fcd7bacf5cdf8177ed43c4 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 17 May 2006 17:17:43 +0200 Subject: [ALSA] hda-codec - Fix init verbs for ALC260 hp model Use the basic init verbs for ALC260 instead of hp init verbs since hp init verbs seem incomplete and not working on some machines. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 0fc2f77dce2..ceb103b93b0 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -3106,6 +3106,7 @@ static struct hda_verb alc260_init_verbs[] = { { } }; +#if 0 /* should be identical with alc260_init_verbs? */ static struct hda_verb alc260_hp_init_verbs[] = { /* Headphone and output */ {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0}, @@ -3152,6 +3153,7 @@ static struct hda_verb alc260_hp_init_verbs[] = { {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, { } }; +#endif static struct hda_verb alc260_hp_3013_init_verbs[] = { /* Line out and output */ @@ -3867,7 +3869,7 @@ static struct alc_config_preset alc260_presets[] = { .mixers = { alc260_base_output_mixer, alc260_input_mixer, alc260_capture_alt_mixer }, - .init_verbs = { alc260_hp_init_verbs }, + .init_verbs = { alc260_init_verbs }, .num_dacs = ARRAY_SIZE(alc260_dac_nids), .dac_nids = alc260_dac_nids, .num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids), -- cgit v1.2.3 From faf8d11743961c720c85be191f8a08c00e5c5d60 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Thu, 18 May 2006 09:35:15 +0200 Subject: [ALSA] usb-audio: add workaround for CSR Bluetooth Headphones (Saitek A-250) Some devices don't have the required class-specific endpoint descriptors. Instead of making this case an error, this patch makes the driver guess the endpoint attributes. Signed-off-by: Clemens Ladisch --- sound/usb/usbaudio.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 8100516e1f7..770642a5953 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -2627,9 +2627,10 @@ static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) if (!csep && altsd->bNumEndpoints >= 2) csep = snd_usb_find_desc(alts->endpoint[1].extra, alts->endpoint[1].extralen, NULL, USB_DT_CS_ENDPOINT); if (!csep || csep[0] < 7 || csep[2] != EP_GENERAL) { - snd_printk(KERN_ERR "%d:%u:%d : no or invalid class specific endpoint descriptor\n", + snd_printk(KERN_WARN "%d:%u:%d : no or invalid" + " class specific endpoint descriptor\n", dev->devnum, iface_no, altno); - continue; + csep = NULL; } fp = kmalloc(sizeof(*fp), GFP_KERNEL); @@ -2648,7 +2649,7 @@ static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) if (snd_usb_get_speed(dev) == USB_SPEED_HIGH) fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1) * (fp->maxpacksize & 0x7ff); - fp->attributes = csep[3]; + fp->attributes = csep ? csep[3] : 0; /* some quirks for attributes here */ -- cgit v1.2.3 From c77a03551b3fd8ef6434153dfadff83ae404e526 Mon Sep 17 00:00:00 2001 From: Alan Horstmann Date: Thu, 18 May 2006 14:24:30 +0200 Subject: [ALSA] Remove ENTER_UART from au88x0 init Remove an unnecessary ENTER_UART instruction during au88x0 init as it makes the first/subsequent midi open to fail. Signed-off-by: Alan Horstmann Signed-off-by: Takashi Iwai --- sound/pci/au88x0/au88x0_mpu401.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/sound/pci/au88x0/au88x0_mpu401.c b/sound/pci/au88x0/au88x0_mpu401.c index 814bc2db9f0..1e128a3c8d8 100644 --- a/sound/pci/au88x0/au88x0_mpu401.c +++ b/sound/pci/au88x0/au88x0_mpu401.c @@ -70,9 +70,6 @@ static int __devinit snd_vortex_midi(vortex_t * vortex) temp |= (MIDI_CLOCK_DIV << 8) | ((mode >> 24) & 0xff) << 4; hwwrite(vortex->mmio, VORTEX_CTRL2, temp); hwwrite(vortex->mmio, VORTEX_MIDI_CMD, MPU401_RESET); - /* Set some kind of mode */ - if (mode) - hwwrite(vortex->mmio, VORTEX_MIDI_CMD, MPU401_ENTER_UART); /* Check if anything is OK. */ temp = hwread(vortex->mmio, VORTEX_MIDI_DATA); -- cgit v1.2.3 From f8c7579051763d6be275bf88a430ffb1c5234bad Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 18 May 2006 14:47:03 +0200 Subject: [ALSA] usbaudio - Fix a typo Fix a typo introduced by the last fix. Signed-off-by: Takashi Iwai --- sound/usb/usbaudio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 770642a5953..30cadec9a34 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -2627,7 +2627,7 @@ static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) if (!csep && altsd->bNumEndpoints >= 2) csep = snd_usb_find_desc(alts->endpoint[1].extra, alts->endpoint[1].extralen, NULL, USB_DT_CS_ENDPOINT); if (!csep || csep[0] < 7 || csep[2] != EP_GENERAL) { - snd_printk(KERN_WARN "%d:%u:%d : no or invalid" + snd_printk(KERN_WARNING "%d:%u:%d : no or invalid" " class specific endpoint descriptor\n", dev->devnum, iface_no, altno); csep = NULL; -- cgit v1.2.3 From 2851d963e0038c53d2175970daac4217abed7af2 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 18 May 2006 14:48:26 +0200 Subject: [ALSA] mpu401_uart - Fix coding style and code clean up - fold lines and fix spaces to follow the standard style - added some comments - moved EXPORT_SYMBOL() near the definition - some code clean up Signed-off-by: Takashi Iwai --- sound/drivers/mpu401/mpu401_uart.c | 108 ++++++++++++++++++++++--------------- 1 file changed, 66 insertions(+), 42 deletions(-) diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c index b49a45cbf67..cd64d3eb9ec 100644 --- a/sound/drivers/mpu401/mpu401_uart.c +++ b/sound/drivers/mpu401/mpu401_uart.c @@ -58,22 +58,26 @@ static void snd_mpu401_uart_output_write(struct snd_mpu401 * mpu); #define MPU401_ACK 0xfe /* Build in lowlevel io */ -static void mpu401_write_port(struct snd_mpu401 *mpu, unsigned char data, unsigned long addr) +static void mpu401_write_port(struct snd_mpu401 *mpu, unsigned char data, + unsigned long addr) { outb(data, addr); } -static unsigned char mpu401_read_port(struct snd_mpu401 *mpu, unsigned long addr) +static unsigned char mpu401_read_port(struct snd_mpu401 *mpu, + unsigned long addr) { return inb(addr); } -static void mpu401_write_mmio(struct snd_mpu401 *mpu, unsigned char data, unsigned long addr) +static void mpu401_write_mmio(struct snd_mpu401 *mpu, unsigned char data, + unsigned long addr) { writeb(data, (void __iomem *)addr); } -static unsigned char mpu401_read_mmio(struct snd_mpu401 *mpu, unsigned long addr) +static unsigned char mpu401_read_mmio(struct snd_mpu401 *mpu, + unsigned long addr) { return readb((void __iomem *)addr); } @@ -86,20 +90,22 @@ static void snd_mpu401_uart_clear_rx(struct snd_mpu401 *mpu) mpu->read(mpu, MPU401D(mpu)); #ifdef CONFIG_SND_DEBUG if (timeout <= 0) - snd_printk("cmd: clear rx timeout (status = 0x%x)\n", mpu->read(mpu, MPU401C(mpu))); + snd_printk(KERN_ERR "cmd: clear rx timeout (status = 0x%x)\n", + mpu->read(mpu, MPU401C(mpu))); #endif } static void _snd_mpu401_uart_interrupt(struct snd_mpu401 *mpu) { spin_lock(&mpu->input_lock); - if (test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) { + if (test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) snd_mpu401_uart_input_read(mpu); - } else { + else snd_mpu401_uart_clear_rx(mpu); - } spin_unlock(&mpu->input_lock); - /* ok. for better Tx performance try do some output when input is done */ + /* ok. for better Tx performance try do some output when + * input is done + */ if (test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode) && test_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode)) { spin_lock(&mpu->output_lock); @@ -116,7 +122,8 @@ static void _snd_mpu401_uart_interrupt(struct snd_mpu401 *mpu) * * Processes the interrupt for MPU401-UART i/o. */ -irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id, struct pt_regs *regs) +irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id, + struct pt_regs *regs) { struct snd_mpu401 *mpu = dev_id; @@ -126,6 +133,8 @@ irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id, struct pt_regs *reg return IRQ_HANDLED; } +EXPORT_SYMBOL(snd_mpu401_uart_interrupt); + /* * timer callback * reprogram the timer and call the interrupt job @@ -159,7 +168,8 @@ static void snd_mpu401_uart_add_timer (struct snd_mpu401 *mpu, int input) mpu->timer.expires = 1 + jiffies; add_timer(&mpu->timer); } - mpu->timer_invoked |= input ? MPU401_MODE_INPUT_TIMER : MPU401_MODE_OUTPUT_TIMER; + mpu->timer_invoked |= input ? MPU401_MODE_INPUT_TIMER : + MPU401_MODE_OUTPUT_TIMER; spin_unlock_irqrestore (&mpu->timer_lock, flags); } @@ -172,7 +182,8 @@ static void snd_mpu401_uart_remove_timer (struct snd_mpu401 *mpu, int input) spin_lock_irqsave (&mpu->timer_lock, flags); if (mpu->timer_invoked) { - mpu->timer_invoked &= input ? ~MPU401_MODE_INPUT_TIMER : ~MPU401_MODE_OUTPUT_TIMER; + mpu->timer_invoked &= input ? ~MPU401_MODE_INPUT_TIMER : + ~MPU401_MODE_OUTPUT_TIMER; if (! mpu->timer_invoked) del_timer(&mpu->timer); } @@ -180,11 +191,12 @@ static void snd_mpu401_uart_remove_timer (struct snd_mpu401 *mpu, int input) } /* - + * send a UART command + * return zero if successful, non-zero for some errors */ static int snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd, - int ack) + int ack) { unsigned long flags; int timeout, ok; @@ -196,11 +208,13 @@ static int snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd, } /* ok. standard MPU-401 initialization */ if (mpu->hardware != MPU401_HW_SB) { - for (timeout = 1000; timeout > 0 && !snd_mpu401_output_ready(mpu); timeout--) + for (timeout = 1000; timeout > 0 && + !snd_mpu401_output_ready(mpu); timeout--) udelay(10); #ifdef CONFIG_SND_DEBUG if (!timeout) - snd_printk("cmd: tx timeout (status = 0x%x)\n", mpu->read(mpu, MPU401C(mpu))); + snd_printk(KERN_ERR "cmd: tx timeout (status = 0x%x)\n", + mpu->read(mpu, MPU401C(mpu))); #endif } mpu->write(mpu, cmd, MPU401C(mpu)); @@ -215,12 +229,14 @@ static int snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd, } if (!ok && mpu->read(mpu, MPU401D(mpu)) == MPU401_ACK) ok = 1; - } else { + } else ok = 1; - } spin_unlock_irqrestore(&mpu->input_lock, flags); if (!ok) { - snd_printk("cmd: 0x%x failed at 0x%lx (status = 0x%x, data = 0x%x)\n", cmd, mpu->port, mpu->read(mpu, MPU401C(mpu)), mpu->read(mpu, MPU401D(mpu))); + snd_printk(KERN_ERR "cmd: 0x%x failed at 0x%lx " + "(status = 0x%x, data = 0x%x)\n", cmd, mpu->port, + mpu->read(mpu, MPU401C(mpu)), + mpu->read(mpu, MPU401D(mpu))); return 1; } return 0; @@ -314,7 +330,8 @@ static int snd_mpu401_uart_output_close(struct snd_rawmidi_substream *substream) /* * trigger input callback */ -static void snd_mpu401_uart_input_trigger(struct snd_rawmidi_substream *substream, int up) +static void +snd_mpu401_uart_input_trigger(struct snd_rawmidi_substream *substream, int up) { unsigned long flags; struct snd_mpu401 *mpu; @@ -322,7 +339,8 @@ static void snd_mpu401_uart_input_trigger(struct snd_rawmidi_substream *substrea mpu = substream->rmidi->private_data; if (up) { - if (! test_and_set_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode)) { + if (! test_and_set_bit(MPU401_MODE_BIT_INPUT_TRIGGER, + &mpu->mode)) { /* first time - flush FIFO */ while (max-- > 0) mpu->read(mpu, MPU401D(mpu)); @@ -352,13 +370,11 @@ static void snd_mpu401_uart_input_read(struct snd_mpu401 * mpu) unsigned char byte; while (max-- > 0) { - if (snd_mpu401_input_avail(mpu)) { - byte = mpu->read(mpu, MPU401D(mpu)); - if (test_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode)) - snd_rawmidi_receive(mpu->substream_input, &byte, 1); - } else { + if (! snd_mpu401_input_avail(mpu)) break; /* input not available */ - } + byte = mpu->read(mpu, MPU401D(mpu)); + if (test_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode)) + snd_rawmidi_receive(mpu->substream_input, &byte, 1); } } @@ -380,16 +396,16 @@ static void snd_mpu401_uart_output_write(struct snd_mpu401 * mpu) int max = 256, timeout; do { - if (snd_rawmidi_transmit_peek(mpu->substream_output, &byte, 1) == 1) { + if (snd_rawmidi_transmit_peek(mpu->substream_output, + &byte, 1) == 1) { for (timeout = 100; timeout > 0; timeout--) { - if (snd_mpu401_output_ready(mpu)) { - mpu->write(mpu, byte, MPU401D(mpu)); - snd_rawmidi_transmit_ack(mpu->substream_output, 1); + if (snd_mpu401_output_ready(mpu)) break; - } } if (timeout == 0) break; /* Tx FIFO full - try again later */ + mpu->write(mpu, byte, MPU401D(mpu)); + snd_rawmidi_transmit_ack(mpu->substream_output, 1); } else { snd_mpu401_uart_remove_timer (mpu, 0); break; /* no other data - leave the tx loop */ @@ -400,7 +416,8 @@ static void snd_mpu401_uart_output_write(struct snd_mpu401 * mpu) /* * output trigger callback */ -static void snd_mpu401_uart_output_trigger(struct snd_rawmidi_substream *substream, int up) +static void +snd_mpu401_uart_output_trigger(struct snd_rawmidi_substream *substream, int up) { unsigned long flags; struct snd_mpu401 *mpu; @@ -499,8 +516,11 @@ int snd_mpu401_uart_new(struct snd_card *card, int device, mpu->hardware = hardware; if (!integrated) { int res_size = hardware == MPU401_HW_PC98II ? 4 : 2; - if ((mpu->res = request_region(port, res_size, "MPU401 UART")) == NULL) { - snd_printk(KERN_ERR "mpu401_uart: unable to grab port 0x%lx size %d\n", port, res_size); + mpu->res = request_region(port, res_size, "MPU401 UART"); + if (mpu->res == NULL) { + snd_printk(KERN_ERR "mpu401_uart: " + "unable to grab port 0x%lx size %d\n", + port, res_size); snd_device_free(card, rmidi); return -EBUSY; } @@ -521,8 +541,10 @@ int snd_mpu401_uart_new(struct snd_card *card, int device, else mpu->cport = port + 1; if (irq >= 0 && irq_flags) { - if (request_irq(irq, snd_mpu401_uart_interrupt, irq_flags, "MPU401 UART", (void *) mpu)) { - snd_printk(KERN_ERR "mpu401_uart: unable to grab IRQ %d\n", irq); + if (request_irq(irq, snd_mpu401_uart_interrupt, irq_flags, + "MPU401 UART", (void *) mpu)) { + snd_printk(KERN_ERR "mpu401_uart: " + "unable to grab IRQ %d\n", irq); snd_device_free(card, rmidi); return -EBUSY; } @@ -530,11 +552,14 @@ int snd_mpu401_uart_new(struct snd_card *card, int device, mpu->irq = irq; mpu->irq_flags = irq_flags; if (card->shortname[0]) - snprintf(rmidi->name, sizeof(rmidi->name), "%s MIDI", card->shortname); + snprintf(rmidi->name, sizeof(rmidi->name), "%s MIDI", + card->shortname); else - sprintf(rmidi->name, "MPU-401 MIDI %d-%d", card->number, device); - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_mpu401_uart_output); - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_mpu401_uart_input); + sprintf(rmidi->name, "MPU-401 MIDI %d-%d",card->number, device); + snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, + &snd_mpu401_uart_output); + snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, + &snd_mpu401_uart_input); rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX; @@ -544,7 +569,6 @@ int snd_mpu401_uart_new(struct snd_card *card, int device, return 0; } -EXPORT_SYMBOL(snd_mpu401_uart_interrupt); EXPORT_SYMBOL(snd_mpu401_uart_new); /* -- cgit v1.2.3 From 77389b432344c811832962ca7f8181b8b3da3449 Mon Sep 17 00:00:00 2001 From: Jaya Kumar Date: Fri, 19 May 2006 12:04:22 +0200 Subject: [ALSA] Single variables for cs5535audio As per Takashi's feedback, this is a cleanup to make cs5535audio be single device per system. The diff is against 2.6.17-rc4 with Takashi's patch adding the module_params for index, id and enable. Signed-off-by: Jaya Kumar Signed-off-by: Takashi Iwai --- sound/pci/cs5535audio/cs5535audio.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c index f61c4fa4ed6..8f46190f24a 100644 --- a/sound/pci/cs5535audio/cs5535audio.c +++ b/sound/pci/cs5535audio/cs5535audio.c @@ -56,16 +56,17 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { {} }; -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; +static int index = SNDRV_DEFAULT_IDX1; +static char *id = SNDRV_DEFAULT_STR1; +/* for backward compatibility */ +static int enable; -module_param_array(index, int, NULL, 0444); +module_param(index, int, 0444); MODULE_PARM_DESC(index, "Index value for " DRIVER_NAME); -module_param_array(id, charp, NULL, 0444); +module_param(id, charp, 0444); MODULE_PARM_DESC(id, "ID string for " DRIVER_NAME); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable " DRIVER_NAME); +module_param(enable, bool, 0444); +MODULE_PARM_DESC(enable, "Enable for " DRIVER_NAME); static struct pci_device_id snd_cs5535audio_ids[] __devinitdata = { { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_AUDIO) }, @@ -357,12 +358,8 @@ static int __devinit snd_cs5535audio_probe(struct pci_dev *pci, if (dev >= SNDRV_CARDS) return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); + card = snd_card_new(index, id, THIS_MODULE, 0); if (card == NULL) return -ENOMEM; -- cgit v1.2.3 From c00bd74a0dd69c4b39e4d95a20253e735616bdb9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 19 May 2006 19:22:34 +0200 Subject: [ALSA] Fix description of cs5535audio driver in ALSA-Configuration.txt Fix the description of cs5535audio driver in ALSA-Configuraiton.txt. Now it supports only single device. Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/ALSA-Configuration.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 017e930fa05..87d76a5c73d 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -470,7 +470,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. Module for multifunction CS5535 companion PCI device - This module supports multiple cards. + The power-management is supported. Module snd-dt019x ----------------- -- cgit v1.2.3 From 140432fd2fbe68d59fe6fcddbcd4bcd0f84e951a Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 22 May 2006 14:31:57 +0200 Subject: [ALSA] hdsp - Fix compilation with hdsp driver built in kernel Fixed the compilation with hdsp driver built in kernel. The traditional hwdep loader is used in this case. Signed-off-by: Takashi Iwai --- sound/pci/rme9652/hdsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index da63a1a1995..bf89ab9e313 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c @@ -389,7 +389,7 @@ MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP}," /* use hotplug firmeare loader? */ #if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE) -#ifndef HDSP_USE_HWDEP_LOADER +#if !defined(HDSP_USE_HWDEP_LOADER) && !defined(CONFIG_SND_HDSP) #define HDSP_FW_LOADER #endif #endif -- cgit v1.2.3 From 302e4c2f9e2b9f07c69649782330a61c60001ac4 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 23 May 2006 13:24:30 +0200 Subject: [ALSA] Change an arugment of snd_mpu401_uart_new() to bit flags Change the 5th argument of snd_mpu401_uart_new() to bit flags instead of a boolean. The argument takes bits that consist of MPU401_INFO_XXX flags. The callers that used the value 1 there are replaced with MPU401_INFO_INTEGRATED. Signed-off-by: Takashi Iwai --- .../sound/alsa/DocBook/writing-an-alsa-driver.tmpl | 29 ++++++- include/sound/mpu401.h | 14 +++- sound/drivers/mpu401/mpu401_uart.c | 96 +++++++++++++++------- sound/isa/sscape.c | 3 +- sound/pci/als4000.c | 4 +- sound/pci/au88x0/au88x0_mpu401.c | 3 +- sound/pci/azt3328.c | 4 +- sound/pci/cmipci.c | 4 +- sound/pci/cs5535audio/cs5535audio.c | 21 +++-- sound/pci/es1938.c | 3 +- sound/pci/es1968.c | 3 +- sound/pci/fm801.c | 3 +- sound/pci/ice1712/ice1712.c | 6 +- sound/pci/ice1712/ice1724.c | 3 +- sound/pci/maestro3.c | 3 +- sound/pci/sonicvibes.c | 2 +- sound/pci/trident/trident.c | 3 +- sound/pci/via82xx.c | 2 +- sound/pci/ymfpci/ymfpci.c | 3 +- 19 files changed, 147 insertions(+), 62 deletions(-) diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl index 23c6c7cde4e..635cbb94357 100644 --- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl +++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl @@ -4215,7 +4215,7 @@ struct _snd_pcm_runtime { @@ -4242,15 +4242,36 @@ struct _snd_pcm_runtime { + The 5th argument is bitflags for additional information. When the i/o port address above is a part of the PCI i/o region, the MPU401 i/o port might have been already allocated - (reserved) by the driver itself. In such a case, pass non-zero - to the 5th argument - (integrated). Otherwise, pass 0 to it, + (reserved) by the driver itself. In such a case, pass a bit flag + MPU401_INFO_INTEGRATED, and the mpu401-uart layer will allocate the i/o ports by itself. + + When the controller supports only the input or output MIDI stream, + pass MPU401_INFO_INPUT or + MPU401_INFO_OUTPUT bitflag, respectively. + Then the rawmidi instance is created as a single stream. + + + + MPU401_INFO_MMIO bitflag is used to change + the access method to MMIO (via readb and writeb) instead of + iob and outb. In this case, you have to pass the iomapped address + to snd_mpu401_uart_new(). + + + + When MPU401_INFO_TX_IRQ is set, the output + stream isn't checked in the default interrupt handler. The driver + needs to call snd_mpu401_uart_interrupt_tx() + by itself to start processing the output stream in irq handler. + + Usually, the port address corresponds to the command port and port + 1 corresponds to the data port. If not, you may change diff --git a/include/sound/mpu401.h b/include/sound/mpu401.h index 8e97ace78f1..ac504321ea5 100644 --- a/include/sound/mpu401.h +++ b/include/sound/mpu401.h @@ -45,6 +45,12 @@ #define MPU401_HW_PC98II 18 /* Roland PC98II */ #define MPU401_HW_AUREAL 19 /* Aureal Vortex */ +#define MPU401_INFO_INPUT (1 << 0) /* input stream */ +#define MPU401_INFO_OUTPUT (1 << 1) /* output stream */ +#define MPU401_INFO_INTEGRATED (1 << 2) /* integrated h/w port */ +#define MPU401_INFO_MMIO (1 << 3) /* MMIO access */ +#define MPU401_INFO_TX_IRQ (1 << 4) /* independent TX irq */ + #define MPU401_MODE_BIT_INPUT 0 #define MPU401_MODE_BIT_OUTPUT 1 #define MPU401_MODE_BIT_INPUT_TRIGGER 2 @@ -62,6 +68,7 @@ struct snd_mpu401 { struct snd_rawmidi *rmidi; unsigned short hardware; /* MPU401_HW_XXXX */ + unsigned int info_flags; /* MPU401_INFO_XXX */ unsigned long port; /* base port of MPU-401 chip */ unsigned long cport; /* port + 1 (usually) */ struct resource *res; /* port resource */ @@ -99,13 +106,16 @@ struct snd_mpu401 { */ -irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id, struct pt_regs *regs); +irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id, + struct pt_regs *regs); +irqreturn_t snd_mpu401_uart_interrupt_tx(int irq, void *dev_id, + struct pt_regs *regs); int snd_mpu401_uart_new(struct snd_card *card, int device, unsigned short hardware, unsigned long port, - int integrated, + unsigned int info_flags, int irq, int irq_flags, struct snd_rawmidi ** rrawmidi); diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c index cd64d3eb9ec..4bf07ca9b17 100644 --- a/sound/drivers/mpu401/mpu401_uart.c +++ b/sound/drivers/mpu401/mpu401_uart.c @@ -95,17 +95,8 @@ static void snd_mpu401_uart_clear_rx(struct snd_mpu401 *mpu) #endif } -static void _snd_mpu401_uart_interrupt(struct snd_mpu401 *mpu) +static void uart_interrupt_tx(struct snd_mpu401 *mpu) { - spin_lock(&mpu->input_lock); - if (test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) - snd_mpu401_uart_input_read(mpu); - else - snd_mpu401_uart_clear_rx(mpu); - spin_unlock(&mpu->input_lock); - /* ok. for better Tx performance try do some output when - * input is done - */ if (test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode) && test_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode)) { spin_lock(&mpu->output_lock); @@ -114,6 +105,22 @@ static void _snd_mpu401_uart_interrupt(struct snd_mpu401 *mpu) } } +static void _snd_mpu401_uart_interrupt(struct snd_mpu401 *mpu) +{ + if (mpu->info_flags & MPU401_INFO_INPUT) { + spin_lock(&mpu->input_lock); + if (test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) + snd_mpu401_uart_input_read(mpu); + else + snd_mpu401_uart_clear_rx(mpu); + spin_unlock(&mpu->input_lock); + } + if (! (mpu->info_flags & MPU401_INFO_TX_IRQ)) + /* ok. for better Tx performance try do some output + when input is done */ + uart_interrupt_tx(mpu); +} + /** * snd_mpu401_uart_interrupt - generic MPU401-UART interrupt handler * @irq: the irq number @@ -135,6 +142,27 @@ irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id, EXPORT_SYMBOL(snd_mpu401_uart_interrupt); +/** + * snd_mpu401_uart_interrupt_tx - generic MPU401-UART transmit irq handler + * @irq: the irq number + * @dev_id: mpu401 instance + * @regs: the reigster + * + * Processes the interrupt for MPU401-UART output. + */ +irqreturn_t snd_mpu401_uart_interrupt_tx(int irq, void *dev_id, + struct pt_regs *regs) +{ + struct snd_mpu401 *mpu = dev_id; + + if (mpu == NULL) + return IRQ_NONE; + uart_interrupt_tx(mpu); + return IRQ_HANDLED; +} + +EXPORT_SYMBOL(snd_mpu401_uart_interrupt_tx); + /* * timer callback * reprogram the timer and call the interrupt job @@ -430,14 +458,16 @@ snd_mpu401_uart_output_trigger(struct snd_rawmidi_substream *substream, int up) * since the output timer might have been removed in * snd_mpu401_uart_output_write(). */ - snd_mpu401_uart_add_timer(mpu, 0); + if (! (mpu->info_flags & MPU401_INFO_TX_IRQ)) + snd_mpu401_uart_add_timer(mpu, 0); /* output pending data */ spin_lock_irqsave(&mpu->output_lock, flags); snd_mpu401_uart_output_write(mpu); spin_unlock_irqrestore(&mpu->output_lock, flags); } else { - snd_mpu401_uart_remove_timer(mpu, 0); + if (! (mpu->info_flags & MPU401_INFO_TX_IRQ)) + snd_mpu401_uart_remove_timer(mpu, 0); clear_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode); } } @@ -475,7 +505,7 @@ static void snd_mpu401_uart_free(struct snd_rawmidi *rmidi) * @device: the device index, zero-based * @hardware: the hardware type, MPU401_HW_XXXX * @port: the base address of MPU401 port - * @integrated: non-zero if the port was already reserved by the chip + * @info_flags: bitflags MPU401_INFO_XXX * @irq: the irq number, -1 if no interrupt for mpu * @irq_flags: the irq request flags (SA_XXX), 0 if irq was already reserved. * @rrawmidi: the pointer to store the new rawmidi instance @@ -490,17 +520,24 @@ static void snd_mpu401_uart_free(struct snd_rawmidi *rmidi) */ int snd_mpu401_uart_new(struct snd_card *card, int device, unsigned short hardware, - unsigned long port, int integrated, + unsigned long port, + unsigned int info_flags, int irq, int irq_flags, struct snd_rawmidi ** rrawmidi) { struct snd_mpu401 *mpu; struct snd_rawmidi *rmidi; + int in_enable, out_enable; int err; if (rrawmidi) *rrawmidi = NULL; - if ((err = snd_rawmidi_new(card, "MPU-401U", device, 1, 1, &rmidi)) < 0) + if (! (info_flags & (MPU401_INFO_INPUT | MPU401_INFO_OUTPUT))) + info_flags |= MPU401_INFO_INPUT | MPU401_INFO_OUTPUT; + in_enable = (info_flags & MPU401_INFO_INPUT) ? 1 : 0; + out_enable = (info_flags & MPU401_INFO_OUTPUT) ? 1 : 0; + if ((err = snd_rawmidi_new(card, "MPU-401U", device, + out_enable, in_enable, &rmidi)) < 0) return err; mpu = kzalloc(sizeof(*mpu), GFP_KERNEL); if (mpu == NULL) { @@ -514,7 +551,7 @@ int snd_mpu401_uart_new(struct snd_card *card, int device, spin_lock_init(&mpu->output_lock); spin_lock_init(&mpu->timer_lock); mpu->hardware = hardware; - if (!integrated) { + if (! (info_flags & MPU401_INFO_INTEGRATED)) { int res_size = hardware == MPU401_HW_PC98II ? 4 : 2; mpu->res = request_region(port, res_size, "MPU401 UART"); if (mpu->res == NULL) { @@ -525,15 +562,12 @@ int snd_mpu401_uart_new(struct snd_card *card, int device, return -EBUSY; } } - switch (hardware) { - case MPU401_HW_AUREAL: + if (info_flags & MPU401_INFO_MMIO) { mpu->write = mpu401_write_mmio; mpu->read = mpu401_read_mmio; - break; - default: + } else { mpu->write = mpu401_write_port; mpu->read = mpu401_read_port; - break; } mpu->port = port; if (hardware == MPU401_HW_PC98II) @@ -549,6 +583,7 @@ int snd_mpu401_uart_new(struct snd_card *card, int device, return -EBUSY; } } + mpu->info_flags = info_flags; mpu->irq = irq; mpu->irq_flags = irq_flags; if (card->shortname[0]) @@ -556,13 +591,18 @@ int snd_mpu401_uart_new(struct snd_card *card, int device, card->shortname); else sprintf(rmidi->name, "MPU-401 MIDI %d-%d",card->number, device); - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, - &snd_mpu401_uart_output); - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, - &snd_mpu401_uart_input); - rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | - SNDRV_RAWMIDI_INFO_INPUT | - SNDRV_RAWMIDI_INFO_DUPLEX; + if (out_enable) { + snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, + &snd_mpu401_uart_output); + rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT; + } + if (in_enable) { + snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, + &snd_mpu401_uart_input); + rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT; + if (out_enable) + rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX; + } mpu->rmidi = rmidi; if (rrawmidi) *rrawmidi = rmidi; diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c index d2a856f0fde..27271c9446d 100644 --- a/sound/isa/sscape.c +++ b/sound/isa/sscape.c @@ -897,10 +897,9 @@ static int __devinit create_mpu401(struct snd_card *card, int devnum, unsigned l struct snd_rawmidi *rawmidi; int err; -#define MPU401_SHARE_HARDWARE 1 if ((err = snd_mpu401_uart_new(card, devnum, MPU401_HW_MPU401, - port, MPU401_SHARE_HARDWARE, + port, MPU401_INFO_INTEGRATED, irq, SA_INTERRUPT, &rawmidi)) == 0) { struct snd_mpu401 *mpu = (struct snd_mpu401 *) rawmidi->private_data; diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c index 60423b1c678..a9f08066459 100644 --- a/sound/pci/als4000.c +++ b/sound/pci/als4000.c @@ -746,8 +746,8 @@ static int __devinit snd_card_als4000_probe(struct pci_dev *pci, card->shortname, chip->alt_port, chip->irq); if ((err = snd_mpu401_uart_new( card, 0, MPU401_HW_ALS4000, - gcr+0x30, 1, pci->irq, 0, - &chip->rmidi)) < 0) { + gcr+0x30, MPU401_INFO_INTEGRATED, + pci->irq, 0, &chip->rmidi)) < 0) { printk(KERN_ERR "als4000: no MPU-401 device at 0x%lx?\n", gcr+0x30); goto out_err; } diff --git a/sound/pci/au88x0/au88x0_mpu401.c b/sound/pci/au88x0/au88x0_mpu401.c index 1e128a3c8d8..5a0c53530fa 100644 --- a/sound/pci/au88x0/au88x0_mpu401.c +++ b/sound/pci/au88x0/au88x0_mpu401.c @@ -95,7 +95,8 @@ static int __devinit snd_vortex_midi(vortex_t * vortex) port = (unsigned long)(vortex->mmio + VORTEX_MIDI_DATA); if ((temp = snd_mpu401_uart_new(vortex->card, 0, MPU401_HW_AUREAL, port, - 1, 0, 0, &rmidi)) != 0) { + MPU401_INFO_INTEGRATED | MPU401_INFO_MMIO, + 0, 0, &rmidi)) != 0) { hwwrite(vortex->mmio, VORTEX_CTRL, (hwread(vortex->mmio, VORTEX_CTRL) & ~CTRL_MIDI_PORT) & ~CTRL_MIDI_EN); diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index e68056c8158..6e62dafb66c 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c @@ -1806,8 +1806,8 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) card->private_data = chip; if ((err = snd_mpu401_uart_new( card, 0, MPU401_HW_MPU401, - chip->mpu_port, 1, pci->irq, 0, - &chip->rmidi)) < 0) { + chip->mpu_port, MPU401_INFO_INTEGRATED, + pci->irq, 0, &chip->rmidi)) < 0) { snd_printk(KERN_ERR "azf3328: no MPU-401 device at 0x%lx?\n", chip->mpu_port); goto out_err; } diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index cb475ada2ef..79bc60a5204 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c @@ -2981,7 +2981,9 @@ static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pc if (iomidi > 0) { if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_CMIPCI, - iomidi, integrated_midi, + iomidi, + (integrated_midi ? + MPU401_INFO_INTEGRATED : 0), cm->irq, 0, &cm->rmidi)) < 0) { printk(KERN_ERR "cmipci: no UART401 device at 0x%lx\n", iomidi); } diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c index 8f46190f24a..f61c4fa4ed6 100644 --- a/sound/pci/cs5535audio/cs5535audio.c +++ b/sound/pci/cs5535audio/cs5535audio.c @@ -56,17 +56,16 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { {} }; -static int index = SNDRV_DEFAULT_IDX1; -static char *id = SNDRV_DEFAULT_STR1; -/* for backward compatibility */ -static int enable; +static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; +static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; +static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; -module_param(index, int, 0444); +module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for " DRIVER_NAME); -module_param(id, charp, 0444); +module_param_array(id, charp, NULL, 0444); MODULE_PARM_DESC(id, "ID string for " DRIVER_NAME); -module_param(enable, bool, 0444); -MODULE_PARM_DESC(enable, "Enable for " DRIVER_NAME); +module_param_array(enable, bool, NULL, 0444); +MODULE_PARM_DESC(enable, "Enable " DRIVER_NAME); static struct pci_device_id snd_cs5535audio_ids[] __devinitdata = { { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_AUDIO) }, @@ -358,8 +357,12 @@ static int __devinit snd_cs5535audio_probe(struct pci_dev *pci, if (dev >= SNDRV_CARDS) return -ENODEV; + if (!enable[dev]) { + dev++; + return -ENOENT; + } - card = snd_card_new(index, id, THIS_MODULE, 0); + card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); if (card == NULL) return -ENOMEM; diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c index 6f9094ca4fb..ca6603fe0b1 100644 --- a/sound/pci/es1938.c +++ b/sound/pci/es1938.c @@ -1756,7 +1756,8 @@ static int __devinit snd_es1938_probe(struct pci_dev *pci, } } if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, - chip->mpu_port, 1, chip->irq, 0, &chip->rmidi) < 0) { + chip->mpu_port, MPU401_INFO_INTEGRATED, + chip->irq, 0, &chip->rmidi) < 0) { printk(KERN_ERR "es1938: unable to initialize MPU-401\n"); } else { // this line is vital for MIDI interrupt handling on ess-solo1 diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index f43bd380ac2..bfa0876e715 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c @@ -2727,7 +2727,8 @@ static int __devinit snd_es1968_probe(struct pci_dev *pci, } if (enable_mpu[dev]) { if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, - chip->io_port + ESM_MPU401_PORT, 1, + chip->io_port + ESM_MPU401_PORT, + MPU401_INFO_INTEGRATED, chip->irq, 0, &chip->rmidi)) < 0) { printk(KERN_WARNING "es1968: skipping MPU-401 MIDI support..\n"); } diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index 0ec90f37731..0afa573dd24 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c @@ -1448,7 +1448,8 @@ static int __devinit snd_card_fm801_probe(struct pci_dev *pci, return err; } if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_FM801, - FM801_REG(chip, MPU401_DATA), 1, + FM801_REG(chip, MPU401_DATA), + MPU401_INFO_INTEGRATED, chip->irq, 0, &chip->rmidi)) < 0) { snd_card_free(card); return err; diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index 52de85e21b9..00e565e1db3 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c @@ -2737,7 +2737,8 @@ static int __devinit snd_ice1712_probe(struct pci_dev *pci, if (! c->no_mpu401) { if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_ICE1712, - ICEREG(ice, MPU1_CTRL), 1, + ICEREG(ice, MPU1_CTRL), + MPU401_INFO_INTEGRATED, ice->irq, 0, &ice->rmidi[0])) < 0) { snd_card_free(card); @@ -2752,7 +2753,8 @@ static int __devinit snd_ice1712_probe(struct pci_dev *pci, if (ice->eeprom.data[ICE_EEP1_CODEC] & ICE1712_CFG_2xMPU401) { /* 2nd port used */ if ((err = snd_mpu401_uart_new(card, 1, MPU401_HW_ICE1712, - ICEREG(ice, MPU2_CTRL), 1, + ICEREG(ice, MPU2_CTRL), + MPU401_INFO_INTEGRATED, ice->irq, 0, &ice->rmidi[1])) < 0) { snd_card_free(card); diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index 1031bcbf706..34a58c629f4 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c @@ -2388,7 +2388,8 @@ static int __devinit snd_vt1724_probe(struct pci_dev *pci, if (! c->no_mpu401) { if (ice->eeprom.data[ICE_EEP2_SYSCONF] & VT1724_CFG_MPU401) { if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_ICE1712, - ICEREG1724(ice, MPU_CTRL), 1, + ICEREG1724(ice, MPU_CTRL), + MPU401_INFO_INTEGRATED, ice->irq, 0, &ice->rmidi[0])) < 0) { snd_card_free(card); diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index 1928e06b6d8..1c344fbd964 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c @@ -2861,7 +2861,8 @@ snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) #if 0 /* TODO: not supported yet */ /* TODO enable MIDI IRQ and I/O */ err = snd_mpu401_uart_new(chip->card, 0, MPU401_HW_MPU401, - chip->iobase + MPU401_DATA_PORT, 1, + chip->iobase + MPU401_DATA_PORT, + MPU401_INFO_INTEGRATED, chip->irq, 0, &chip->rmidi); if (err < 0) printk(KERN_WARNING "maestro3: no MIDI support.\n"); diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c index 51775706c84..dcf40294834 100644 --- a/sound/pci/sonicvibes.c +++ b/sound/pci/sonicvibes.c @@ -1456,7 +1456,7 @@ static int __devinit snd_sonic_probe(struct pci_dev *pci, return err; } if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_SONICVIBES, - sonic->midi_port, 1, + sonic->midi_port, MPU401_INFO_INTEGRATED, sonic->irq, 0, &midi_uart)) < 0) { snd_card_free(card); diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c index 9624a5f2b87..5629b7eba96 100644 --- a/sound/pci/trident/trident.c +++ b/sound/pci/trident/trident.c @@ -148,7 +148,8 @@ static int __devinit snd_trident_probe(struct pci_dev *pci, } if (trident->device != TRIDENT_DEVICE_ID_SI7018 && (err = snd_mpu401_uart_new(card, 0, MPU401_HW_TRID4DWAVE, - trident->midi_port, 1, + trident->midi_port, + MPU401_INFO_INTEGRATED, trident->irq, 0, &trident->rmidi)) < 0) { snd_card_free(card); return err; diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index a1b777e79c5..12ce22ef16e 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -1973,7 +1973,7 @@ static int __devinit snd_via686_init_misc(struct via82xx *chip) pci_write_config_byte(chip->pci, VIA_PNP_CONTROL, legacy_cfg); if (chip->mpu_res) { if (snd_mpu401_uart_new(chip->card, 0, MPU401_HW_VIA686A, - mpu_port, 1, + mpu_port, MPU401_INFO_INTEGRATED, chip->irq, 0, &chip->rmidi) < 0) { printk(KERN_WARNING "unable to initialize MPU-401" " at 0x%lx, skipping\n", mpu_port); diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c index 65ebf5f1933..26aa775b7b6 100644 --- a/sound/pci/ymfpci/ymfpci.c +++ b/sound/pci/ymfpci/ymfpci.c @@ -308,7 +308,8 @@ static int __devinit snd_card_ymfpci_probe(struct pci_dev *pci, } if (chip->mpu_res) { if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_YMFPCI, - mpu_port[dev], 1, + mpu_port[dev], + MPU401_INFO_INTEGRATED, pci->irq, 0, &chip->rawmidi)) < 0) { printk(KERN_WARNING "ymfpci: cannot initialize MPU401 at 0x%lx, skipping...\n", mpu_port[dev]); legacy_ctrl &= ~YMFPCI_LEGACY_MIEN; /* disable MPU401 irq */ -- cgit v1.2.3 From 721b8a297279276699900a662fa8299232ebc0e8 Mon Sep 17 00:00:00 2001 From: Alan Horstmann Date: Tue, 23 May 2006 13:29:51 +0200 Subject: [ALSA] ice1712 - Disable AC97 for DMX6fire Consumer AC97 is not used by the Terratec DMX6fire, but eeprom bit indicates it is; change the stored value to disable failing consumer mode. Signed-off-by: Alan Horstmann Signed-off-by: Takashi Iwai --- sound/pci/ice1712/ice1712.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index 00e565e1db3..aa5a41fecb0 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c @@ -2398,13 +2398,14 @@ static int __devinit snd_ice1712_chip_init(struct snd_ice1712 *ice) udelay(200); outb(ICE1712_NATIVE, ICEREG(ice, CONTROL)); udelay(200); - if (ice->eeprom.subvendor == ICE1712_SUBDEVICE_DMX6FIRE && !ice->dxr_enable) { - /* Limit active ADCs and DACs to 6; */ - /* Note: DXR extension not supported */ - pci_write_config_byte(ice->pci, 0x60, 0x2a); - } else { - pci_write_config_byte(ice->pci, 0x60, ice->eeprom.data[ICE_EEP1_CODEC]); - } + if (ice->eeprom.subvendor == ICE1712_SUBDEVICE_DMX6FIRE && + !ice->dxr_enable) + /* Set eeprom value to limit active ADCs and DACs to 6; + * Also disable AC97 as no hardware in standard 6fire card/box + * Note: DXR extensions are not currently supported + */ + ice->eeprom.data[ICE_EEP1_CODEC] = 0x3a; + pci_write_config_byte(ice->pci, 0x60, ice->eeprom.data[ICE_EEP1_CODEC]); pci_write_config_byte(ice->pci, 0x61, ice->eeprom.data[ICE_EEP1_ACLINK]); pci_write_config_byte(ice->pci, 0x62, ice->eeprom.data[ICE_EEP1_I2SID]); pci_write_config_byte(ice->pci, 0x63, ice->eeprom.data[ICE_EEP1_SPDIF]); -- cgit v1.2.3 From d5a31b8b6e79145c832d530743ca80bf5f58a965 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 23 May 2006 13:30:59 +0200 Subject: [ALSA] au88x0 - Fix 64bit address of MPU401 MMIO port Fix 64bit address of MPU401 MMIO port on au88x0 chip. Signed-off-by: Takashi Iwai --- sound/pci/au88x0/au88x0_mpu401.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/au88x0/au88x0_mpu401.c b/sound/pci/au88x0/au88x0_mpu401.c index 5a0c53530fa..c75d368ea08 100644 --- a/sound/pci/au88x0/au88x0_mpu401.c +++ b/sound/pci/au88x0/au88x0_mpu401.c @@ -47,7 +47,7 @@ static int __devinit snd_vortex_midi(vortex_t * vortex) struct snd_rawmidi *rmidi; int temp, mode; struct snd_mpu401 *mpu; - int port; + unsigned long port; #ifdef VORTEX_MPU401_LEGACY /* EnableHardCodedMPU401Port() */ -- cgit v1.2.3 From c51302710546f075e65b1e70487707e8324abf2f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 23 May 2006 15:46:10 +0200 Subject: [ALSA] ice1724 - Add functionality for Audiotrak Prodigy 7.1 LT This patch adds support for useable front audio channels, user controllable headphone channel and optical output. From: Anho Ki Signed-off-by: Matt Taylor Signed-off-by: Takashi Iwai --- sound/pci/ice1712/aureon.c | 26 ++++++++++++++++---------- sound/pci/ice1712/aureon.h | 1 + 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c index 336dc489aee..ca74f5b85f4 100644 --- a/sound/pci/ice1712/aureon.c +++ b/sound/pci/ice1712/aureon.c @@ -1281,9 +1281,15 @@ static int aureon_set_headphone_amp(struct snd_ice1712 *ice, int enable) tmp2 = tmp = snd_ice1712_gpio_read(ice); if (enable) - tmp |= AUREON_HP_SEL; + if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT) + tmp |= AUREON_HP_SEL; + else + tmp |= PRODIGY_HP_SEL; else - tmp &= ~ AUREON_HP_SEL; + if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT) + tmp &= ~ AUREON_HP_SEL; + else + tmp &= ~ PRODIGY_HP_SEL; if (tmp != tmp2) { snd_ice1712_gpio_write(ice, tmp); return 1; @@ -2079,16 +2085,16 @@ static unsigned char prodigy71_eeprom[] __devinitdata = { }; static unsigned char prodigy71lt_eeprom[] __devinitdata = { - 0x0b, /* SYSCINF: clock 512, spdif-in/ADC, 4DACs */ + 0x4b, /* SYSCINF: clock 512, spdif-in/ADC, 4DACs */ 0x80, /* ACLINK: I2S */ 0xfc, /* I2S: vol, 96k, 24bit, 192k */ - 0xc3, /* SPDUF: out-en, out-int */ - 0x00, /* GPIO_DIR */ - 0x07, /* GPIO_DIR1 */ - 0x00, /* GPIO_DIR2 */ - 0xff, /* GPIO_MASK */ - 0xf8, /* GPIO_MASK1 */ - 0xff, /* GPIO_MASK2 */ + 0xc3, /* SPDIF: out-en, out-int, spdif-in */ + 0xff, /* GPIO_DIR */ + 0xff, /* GPIO_DIR1 */ + 0x5f, /* GPIO_DIR2 */ + 0x00, /* GPIO_MASK */ + 0x00, /* GPIO_MASK1 */ + 0x00, /* GPIO_MASK2 */ 0x00, /* GPIO_STATE */ 0x00, /* GPIO_STATE1 */ 0x00, /* GPIO_STATE2 */ diff --git a/sound/pci/ice1712/aureon.h b/sound/pci/ice1712/aureon.h index 98a6752280f..3b7bea656c5 100644 --- a/sound/pci/ice1712/aureon.h +++ b/sound/pci/ice1712/aureon.h @@ -58,5 +58,6 @@ extern struct snd_ice1712_card_info snd_vt1724_aureon_cards[]; #define PRODIGY_WM_CS (1 << 8) #define PRODIGY_SPI_MOSI (1 << 10) #define PRODIGY_SPI_CLK (1 << 9) +#define PRODIGY_HP_SEL (1 << 5) #endif /* __SOUND_AUREON_H */ -- cgit v1.2.3 From 766a6c36f3a0b12e1c55dddc1df6673db6b22bfb Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 26 May 2006 14:58:29 +0200 Subject: [ALSA] hda-codec - Fix model for HP dc7600 Changed the assigned model for HP dc7600 with ALC260 codec to match better with the actual I/O assignment. Patch taken from ALSA bug#2157. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index ceb103b93b0..98b9f16c26f 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -3834,7 +3834,7 @@ static struct hda_board_config alc260_cfg_tbl[] = { { .modelname = "hp", .config = ALC260_HP }, { .pci_subvendor = 0x103c, .pci_subdevice = 0x3010, .config = ALC260_HP }, { .pci_subvendor = 0x103c, .pci_subdevice = 0x3011, .config = ALC260_HP }, - { .pci_subvendor = 0x103c, .pci_subdevice = 0x3012, .config = ALC260_HP }, + { .pci_subvendor = 0x103c, .pci_subdevice = 0x3012, .config = ALC260_HP_3013 }, { .pci_subvendor = 0x103c, .pci_subdevice = 0x3013, .config = ALC260_HP_3013 }, { .pci_subvendor = 0x103c, .pci_subdevice = 0x3014, .config = ALC260_HP }, { .pci_subvendor = 0x103c, .pci_subdevice = 0x3015, .config = ALC260_HP }, -- cgit v1.2.3 From cf78ee2ccc96d59e602188e0e6e3fe3522b6d3f6 Mon Sep 17 00:00:00 2001 From: Alan Horstmann Date: Fri, 26 May 2006 17:19:34 +0200 Subject: [ALSA] ice1712 - Set mpu401 info flags from _card_info MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To permit use, in ice1712, of the mpu401 info flags recently added to mpu401_uart, adds info_flags in snd_ice1712_card_info so that additional flags can be set, if desired.  'MPU401_INFO_INTEGRATED' is always set with the ice1712.  The flags are passed on to snd_mpu401_uart_new(). _INFO_OUTPUT is set for DMX6fire mpu2. Signed-off-by: Alan Horstmann Signed-off-by: Takashi Iwai --- sound/pci/ice1712/ews.c | 1 + sound/pci/ice1712/ice1712.c | 7 ++++--- sound/pci/ice1712/ice1712.h | 3 +++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/sound/pci/ice1712/ews.c b/sound/pci/ice1712/ews.c index 2e1cf112058..b135389fec6 100644 --- a/sound/pci/ice1712/ews.c +++ b/sound/pci/ice1712/ews.c @@ -1033,6 +1033,7 @@ struct snd_ice1712_card_info snd_ice1712_ews_cards[] __devinitdata = { .build_controls = snd_ice1712_ews_add_controls, .mpu401_1_name = "MIDI-Front DMX6fire", .mpu401_2_name = "Wavetable DMX6fire", + .mpu401_2_info_flags = MPU401_INFO_OUTPUT, }, { } /* terminator */ }; diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index aa5a41fecb0..845907159b7 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c @@ -61,7 +61,6 @@ #include #include #include -#include #include #include @@ -2739,7 +2738,8 @@ static int __devinit snd_ice1712_probe(struct pci_dev *pci, if (! c->no_mpu401) { if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_ICE1712, ICEREG(ice, MPU1_CTRL), - MPU401_INFO_INTEGRATED, + (c->mpu401_1_info_flags | + MPU401_INFO_INTEGRATED), ice->irq, 0, &ice->rmidi[0])) < 0) { snd_card_free(card); @@ -2755,7 +2755,8 @@ static int __devinit snd_ice1712_probe(struct pci_dev *pci, /* 2nd port used */ if ((err = snd_mpu401_uart_new(card, 1, MPU401_HW_ICE1712, ICEREG(ice, MPU2_CTRL), - MPU401_INFO_INTEGRATED, + (c->mpu401_2_info_flags | + MPU401_INFO_INTEGRATED), ice->irq, 0, &ice->rmidi[1])) < 0) { snd_card_free(card); diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h index d4776319a0c..ce27eac40d4 100644 --- a/sound/pci/ice1712/ice1712.h +++ b/sound/pci/ice1712/ice1712.h @@ -29,6 +29,7 @@ #include #include #include +#include /* @@ -495,6 +496,8 @@ struct snd_ice1712_card_info { int (*chip_init)(struct snd_ice1712 *); int (*build_controls)(struct snd_ice1712 *); unsigned int no_mpu401: 1; + unsigned int mpu401_1_info_flags; + unsigned int mpu401_2_info_flags; const char *mpu401_1_name; const char *mpu401_2_name; unsigned int eeprom_size; -- cgit v1.2.3 From f26eb78fcfb5b76fbe6d3e740b6fedda611f8395 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 29 May 2006 19:05:28 +0200 Subject: [ALSA] cmipci - Fix a typo in 'PC Speaker Playback Switch' control Fixed a typo in 'PC Speaker Playback Switch' control name. Signed-off-by: Takashi Iwai --- sound/pci/cmipci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index 79bc60a5204..0938c158b5c 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c @@ -2121,7 +2121,7 @@ static struct snd_kcontrol_new snd_cmipci_mixers[] __devinitdata = { CMIPCI_MIXER_VOL_MONO("Mic Capture Volume", CM_REG_MIXER2, CM_VADMIC_SHIFT, 7), CMIPCI_SB_VOL_MONO("Phone Playback Volume", CM_REG_EXTENT_IND, 5, 7), CMIPCI_DOUBLE("Phone Playback Switch", CM_REG_EXTENT_IND, CM_REG_EXTENT_IND, 4, 4, 1, 0, 0), - CMIPCI_DOUBLE("PC Speaker Playnack Switch", CM_REG_EXTENT_IND, CM_REG_EXTENT_IND, 3, 3, 1, 0, 0), + CMIPCI_DOUBLE("PC Speaker Playback Switch", CM_REG_EXTENT_IND, CM_REG_EXTENT_IND, 3, 3, 1, 0, 0), CMIPCI_DOUBLE("Mic Boost Capture Switch", CM_REG_EXTENT_IND, CM_REG_EXTENT_IND, 0, 0, 1, 0, 0), }; -- cgit v1.2.3 From d20cad602fc3d92902dc3b4ed252359ab05eae0f Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Wed, 31 May 2006 11:55:17 +0200 Subject: [ALSA] NULL pointer dereference in sound/synth/emux/soundfont.c this is about coverity id #100. It seems the if statement is negated, since the else branch calls remove_info() with sflist->currsf as a parameter where it gets dereferenced. Signed-off-by: Eric Sesterhenn Signed-off-by: Takashi Iwai --- sound/synth/emux/soundfont.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/synth/emux/soundfont.c b/sound/synth/emux/soundfont.c index 7f0bdea0dfd..455e535933e 100644 --- a/sound/synth/emux/soundfont.c +++ b/sound/synth/emux/soundfont.c @@ -195,7 +195,7 @@ snd_soundfont_load(struct snd_sf_list *sflist, const void __user *data, break; case SNDRV_SFNT_REMOVE_INFO: /* patch must be opened */ - if (sflist->currsf) { + if (!sflist->currsf) { snd_printk("soundfont: remove_info: patch not opened\n"); rc = -EINVAL; } else { -- cgit v1.2.3 From 29463dfea754b8b360f638244f002c751aaad1b0 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Thu, 1 Jun 2006 08:33:48 +0200 Subject: [ALSA] bt87x: add Voodoo TV 200 whitelist entry This adds a whitelist entry for the digital audio input of the Voodoo TV 200. Signed-off-by: Clemens Ladisch --- sound/pci/bt87x.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c index aa21cc74a85..c33642d8d9a 100644 --- a/sound/pci/bt87x.c +++ b/sound/pci/bt87x.c @@ -781,10 +781,12 @@ static struct pci_device_id snd_bt87x_ids[] __devinitdata = { BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_879, 0x0070, 0x13eb, 32000), /* Viewcast Osprey 200 */ BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0xff01, 44100), - /* AVerMedia Studio No. 103, 203, ...? */ - BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1461, 0x0003, 48000), /* Leadtek Winfast tv 2000xp delux */ BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x107d, 0x6606, 32000), + /* Voodoo TV 200 */ + BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x121a, 0x3000, 32000), + /* AVerMedia Studio No. 103, 203, ...? */ + BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1461, 0x0003, 48000), { } }; MODULE_DEVICE_TABLE(pci, snd_bt87x_ids); -- cgit v1.2.3 From f079c25ab8a7d223875c5bac9b23b484e4a18f88 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 1 Jun 2006 11:42:14 +0200 Subject: [ALSA] hda-intel - Fix race in remove Call iounmap after free_irq to avoid invalid accesses in the shared irq. The patch is taken from https://bugzilla.novell.com/show_bug.cgi?id=167869 Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 0154389bf95..4070b5cd9b6 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1402,10 +1402,10 @@ static int azx_free(struct azx *chip) msleep(1); } - if (chip->remap_addr) - iounmap(chip->remap_addr); if (chip->irq >= 0) free_irq(chip->irq, (void*)chip); + if (chip->remap_addr) + iounmap(chip->remap_addr); if (chip->bdl.area) snd_dma_free_pages(&chip->bdl); -- cgit v1.2.3 From 0a50d2b2951cb7ae12726814f9a198e1c699aa0b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 1 Jun 2006 14:47:29 +0200 Subject: [ALSA] Fix possible races in PCI driver removal Call free_irq() before releasing others to avoid races when shared irq is issued. Signed-off-by: Takashi Iwai --- sound/pci/cs46xx/cs46xx_lib.c | 5 +++-- sound/pci/riptide/riptide.c | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index 69dbf542a6d..5c211443920 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c @@ -2877,14 +2877,15 @@ static int snd_cs46xx_free(struct snd_cs46xx *chip) if (chip->region.idx[0].resource) snd_cs46xx_hw_stop(chip); + if (chip->irq >= 0) + free_irq(chip->irq, chip); + for (idx = 0; idx < 5; idx++) { struct snd_cs46xx_region *region = &chip->region.idx[idx]; if (region->remap_addr) iounmap(region->remap_addr); release_and_free_resource(region->resource); } - if (chip->irq >= 0) - free_irq(chip->irq, chip); if (chip->active_ctrl) chip->active_ctrl(chip, -chip->amplifier); diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c index c27cd499977..5618ec9740b 100644 --- a/sound/pci/riptide/riptide.c +++ b/sound/pci/riptide/riptide.c @@ -1836,11 +1836,11 @@ static int snd_riptide_free(struct snd_riptide *chip) UNSET_GRESET(cif->hwport); kfree(chip->cif); } + if (chip->irq >= 0) + free_irq(chip->irq, chip); if (chip->fw_entry) release_firmware(chip->fw_entry); release_and_free_resource(chip->res_port); - if (chip->irq >= 0) - free_irq(chip->irq, chip); kfree(chip); return 0; } -- cgit v1.2.3 From a43c4d4d7326c2894be9fd04519b109c438ee78b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 1 Jun 2006 17:16:41 +0200 Subject: [ALSA] ac97 - Add Thinkpad T41p to AD1981 jack-sense blacklist Added Thinkpad T41p to the blacklist to disable HP/line jack-sensing with AD1981B. The jack-sensing is just harmful on this laptop. Signed-off-by: Takashi Iwai --- sound/pci/ac97/ac97_patch.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index 720b419e0c6..1c47ee3d7ef 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c @@ -1627,6 +1627,7 @@ static const struct snd_kcontrol_new snd_ac97_ad1981x_jack_sense[] = { * (SS vendor << 16 | device) */ static unsigned int ad1981_jacks_blacklist[] = { + 0x10140537, /* Thinkpad T41p */ 0x10140554, /* Thinkpad T42p/R50p */ 0 /* end */ }; -- cgit v1.2.3 From f8e9f340da753c021c071f318f97ac9046c1316a Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 1 Jun 2006 21:08:53 +0200 Subject: [ALSA] hda-codec - Add model entry for HP nx6320 Added a model entry for HP nx6320 with AD1981HD codec. It wasn't covered by the generic HP entry because of a hardware bug (the SSID is reversed). Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_analog.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 3a9b800db83..e83c7b01cbb 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -1368,6 +1368,8 @@ static struct hda_board_config ad1981_cfg_tbl[] = { { .modelname = "hp", .config = AD1981_HP }, /* All HP models */ { .pci_subvendor = 0x103c, .config = AD1981_HP }, + { .pci_subvendor = 0x30b0, .pci_subdevice = 0x103c, + .config = AD1981_HP }, /* HP nx6320 (reversed SSID, H/W bug) */ { .modelname = "thinkpad", .config = AD1981_THINKPAD }, /* Lenovo Thinkpad T60/X60/Z6xx */ { .pci_subvendor = 0x17aa, .config = AD1981_THINKPAD }, -- cgit v1.2.3 From c5533bf36b4a6629dab0e08c4951247050928853 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Fri, 2 Jun 2006 09:15:44 +0200 Subject: [ALSA] virmidi: revert erroneous removal of zero initialization The last patch that tried to remove zero initializations of static variables accidentally removed a not-quite-zero initialization too. Signed-off-by: Clemens Ladisch --- sound/drivers/virmidi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/drivers/virmidi.c b/sound/drivers/virmidi.c index 72d09b304db..59171f8200d 100644 --- a/sound/drivers/virmidi.c +++ b/sound/drivers/virmidi.c @@ -65,7 +65,7 @@ MODULE_SUPPORTED_DEVICE("{{ALSA,Virtual rawmidi device}}"); static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static int enable[SNDRV_CARDS]; +static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0}; static int midi_devs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 4}; module_param_array(index, int, NULL, 0444); -- cgit v1.2.3 From 688956f23bdbfb1c3551bfafc819f989b36bb8ae Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 6 Jun 2006 15:44:34 +0200 Subject: [ALSA] Fix races in irq handler and ioremap Call ioremap before request_irq for avoiding possible races in the irq handler. Signed-off-by: Takashi Iwai Signed-off-by: Takashi Iwai --- sound/pci/cs4281.c | 14 +++++++------- sound/pci/rme32.c | 12 ++++++------ sound/pci/rme96.c | 10 +++++----- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index 8c150eab45b..e77a4ce314b 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c @@ -1379,6 +1379,13 @@ static int __devinit snd_cs4281_create(struct snd_card *card, chip->ba0_addr = pci_resource_start(pci, 0); chip->ba1_addr = pci_resource_start(pci, 1); + chip->ba0 = ioremap_nocache(chip->ba0_addr, pci_resource_len(pci, 0)); + chip->ba1 = ioremap_nocache(chip->ba1_addr, pci_resource_len(pci, 1)); + if (!chip->ba0 || !chip->ba1) { + snd_cs4281_free(chip); + return -ENOMEM; + } + if (request_irq(pci->irq, snd_cs4281_interrupt, SA_INTERRUPT|SA_SHIRQ, "CS4281", chip)) { snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); @@ -1387,13 +1394,6 @@ static int __devinit snd_cs4281_create(struct snd_card *card, } chip->irq = pci->irq; - chip->ba0 = ioremap_nocache(chip->ba0_addr, pci_resource_len(pci, 0)); - chip->ba1 = ioremap_nocache(chip->ba1_addr, pci_resource_len(pci, 1)); - if (!chip->ba0 || !chip->ba1) { - snd_cs4281_free(chip); - return -ENOMEM; - } - tmp = snd_cs4281_chip_init(chip); if (tmp) { snd_cs4281_free(chip); diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c index 4dd53bfe030..2cb9fe98db2 100644 --- a/sound/pci/rme32.c +++ b/sound/pci/rme32.c @@ -1368,18 +1368,18 @@ static int __devinit snd_rme32_create(struct rme32 * rme32) return err; rme32->port = pci_resource_start(rme32->pci, 0); - if (request_irq(pci->irq, snd_rme32_interrupt, SA_INTERRUPT | SA_SHIRQ, "RME32", (void *) rme32)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); - return -EBUSY; - } - rme32->irq = pci->irq; - if ((rme32->iobase = ioremap_nocache(rme32->port, RME32_IO_SIZE)) == 0) { snd_printk(KERN_ERR "unable to remap memory region 0x%lx-0x%lx\n", rme32->port, rme32->port + RME32_IO_SIZE - 1); return -ENOMEM; } + if (request_irq(pci->irq, snd_rme32_interrupt, SA_INTERRUPT | SA_SHIRQ, "RME32", (void *) rme32)) { + snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); + return -EBUSY; + } + rme32->irq = pci->irq; + /* read the card's revision number */ pci_read_config_byte(pci, 8, &rme32->rev); diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c index 65611a7d366..991cb18c14f 100644 --- a/sound/pci/rme96.c +++ b/sound/pci/rme96.c @@ -1583,17 +1583,17 @@ snd_rme96_create(struct rme96 *rme96) return err; rme96->port = pci_resource_start(rme96->pci, 0); + if ((rme96->iobase = ioremap_nocache(rme96->port, RME96_IO_SIZE)) == 0) { + snd_printk(KERN_ERR "unable to remap memory region 0x%lx-0x%lx\n", rme96->port, rme96->port + RME96_IO_SIZE - 1); + return -ENOMEM; + } + if (request_irq(pci->irq, snd_rme96_interrupt, SA_INTERRUPT|SA_SHIRQ, "RME96", (void *)rme96)) { snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); return -EBUSY; } rme96->irq = pci->irq; - if ((rme96->iobase = ioremap_nocache(rme96->port, RME96_IO_SIZE)) == 0) { - snd_printk(KERN_ERR "unable to remap memory region 0x%lx-0x%lx\n", rme96->port, rme96->port + RME96_IO_SIZE - 1); - return -ENOMEM; - } - /* read the card's revision number */ pci_read_config_byte(pci, 8, &rme96->rev); -- cgit v1.2.3 From 3758d4e601552a3d9066913a31ccb8dc6a25ee69 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 7 Jun 2006 18:12:31 +0200 Subject: [ALSA] Remove bogus check of mmap_count in snd_pcm_release() Removed a bogus check of mmap_count in snd_pcm_release(). This is no longer true for the shared streams. Signed-off-by: Takashi Iwai --- sound/core/pcm_native.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 9e495244eee..439f047929e 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -2205,7 +2205,6 @@ static int snd_pcm_release(struct inode *inode, struct file *file) pcm_file = file->private_data; substream = pcm_file->substream; snd_assert(substream != NULL, return -ENXIO); - snd_assert(!atomic_read(&substream->mmap_count), ); pcm = substream->pcm; fasync_helper(-1, file, 0, &substream->runtime->fasync); mutex_lock(&pcm->open_mutex); -- cgit v1.2.3 From 3f3488b84c261ab3cb64b9f0b9f40b61e33edb98 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 8 Jun 2006 12:01:44 +0200 Subject: [ALSA] sound/vxpocket: fix printk warning Fix printk format warning: sound/pcmcia/vx/vxp_ops.c:205: warning: format '%x' expects type 'unsigned int', but argument 5 has type 'size_t' Signed-off-by: Randy Dunlap Signed-off-by: Takashi Iwai --- sound/pcmcia/vx/vxp_ops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pcmcia/vx/vxp_ops.c b/sound/pcmcia/vx/vxp_ops.c index 7f82f619f9f..1ee0918c3b9 100644 --- a/sound/pcmcia/vx/vxp_ops.c +++ b/sound/pcmcia/vx/vxp_ops.c @@ -202,7 +202,7 @@ static int vxp_load_xilinx_binary(struct vx_core *_chip, const struct firmware * c |= (int)vx_inb(chip, RXM) << 8; c |= vx_inb(chip, RXL); - snd_printdd(KERN_DEBUG "xilinx: dsp size received 0x%x, orig 0x%x\n", c, fw->size); + snd_printdd(KERN_DEBUG "xilinx: dsp size received 0x%x, orig 0x%Zx\n", c, fw->size); vx_outb(chip, ICR, ICR_HF0); -- cgit v1.2.3 From 2e74eba3e2f000184ade92833c80e799af41c180 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 9 Jun 2006 15:28:07 +0200 Subject: [ALSA] Fix invalid __init in ALSA ISA drivers Replaced invalid __init with __devinit in snd-sbawe and snd-opl3sa2 drivers. Signed-off-by: Takashi Iwai --- sound/isa/opl3sa2.c | 10 +++++----- sound/isa/sb/emu8000.c | 22 +++++++++++----------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c index 931ff75e543..647a996791e 100644 --- a/sound/isa/opl3sa2.c +++ b/sound/isa/opl3sa2.c @@ -221,7 +221,7 @@ static void snd_opl3sa2_write(struct snd_opl3sa2 *chip, unsigned char reg, unsig spin_unlock_irqrestore(&chip->reg_lock, flags); } -static int __init snd_opl3sa2_detect(struct snd_opl3sa2 *chip) +static int __devinit snd_opl3sa2_detect(struct snd_opl3sa2 *chip) { struct snd_card *card; unsigned long port; @@ -489,7 +489,7 @@ static void snd_opl3sa2_master_free(struct snd_kcontrol *kcontrol) chip->master_volume = NULL; } -static int __init snd_opl3sa2_mixer(struct snd_opl3sa2 *chip) +static int __devinit snd_opl3sa2_mixer(struct snd_opl3sa2 *chip) { struct snd_card *card = chip->card; struct snd_ctl_elem_id id1, id2; @@ -583,8 +583,8 @@ static int snd_opl3sa2_resume(struct snd_card *card) #endif /* CONFIG_PM */ #ifdef CONFIG_PNP -static int __init snd_opl3sa2_pnp(int dev, struct snd_opl3sa2 *chip, - struct pnp_dev *pdev) +static int __devinit snd_opl3sa2_pnp(int dev, struct snd_opl3sa2 *chip, + struct pnp_dev *pdev) { struct pnp_resource_table * cfg; int err; @@ -862,7 +862,7 @@ static struct pnp_card_driver opl3sa2_pnpc_driver = { }; #endif /* CONFIG_PNP */ -static int __init snd_opl3sa2_nonpnp_probe(struct platform_device *pdev) +static int __devinit snd_opl3sa2_nonpnp_probe(struct platform_device *pdev) { struct snd_card *card; int err; diff --git a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c index c0b8d61b75e..658179e8614 100644 --- a/sound/isa/sb/emu8000.c +++ b/sound/isa/sb/emu8000.c @@ -131,7 +131,7 @@ snd_emu8000_dma_chan(struct snd_emu8000 *emu, int ch, int mode) /* */ -static void __init +static void __devinit snd_emu8000_read_wait(struct snd_emu8000 *emu) { while ((EMU8000_SMALR_READ(emu) & 0x80000000) != 0) { @@ -143,7 +143,7 @@ snd_emu8000_read_wait(struct snd_emu8000 *emu) /* */ -static void __init +static void __devinit snd_emu8000_write_wait(struct snd_emu8000 *emu) { while ((EMU8000_SMALW_READ(emu) & 0x80000000) != 0) { @@ -156,7 +156,7 @@ snd_emu8000_write_wait(struct snd_emu8000 *emu) /* * detect a card at the given port */ -static int __init +static int __devinit snd_emu8000_detect(struct snd_emu8000 *emu) { /* Initialise */ @@ -182,7 +182,7 @@ snd_emu8000_detect(struct snd_emu8000 *emu) /* * intiailize audio channels */ -static void __init +static void __devinit init_audio(struct snd_emu8000 *emu) { int ch; @@ -223,7 +223,7 @@ init_audio(struct snd_emu8000 *emu) /* * initialize DMA address */ -static void __init +static void __devinit init_dma(struct snd_emu8000 *emu) { EMU8000_SMALR_WRITE(emu, 0); @@ -327,7 +327,7 @@ static unsigned short init4[128] /*__devinitdata*/ = { * Taken from the oss driver, not obvious from the doc how this * is meant to work */ -static void __init +static void __devinit send_array(struct snd_emu8000 *emu, unsigned short *data, int size) { int i; @@ -349,7 +349,7 @@ send_array(struct snd_emu8000 *emu, unsigned short *data, int size) * Send initialization arrays to start up, this just follows the * initialisation sequence in the adip. */ -static void __init +static void __devinit init_arrays(struct snd_emu8000 *emu) { send_array(emu, init1, ARRAY_SIZE(init1)/4); @@ -375,7 +375,7 @@ init_arrays(struct snd_emu8000 *emu) * seems that the only way to do this is to use the one channel and keep * reallocating between read and write. */ -static void __init +static void __devinit size_dram(struct snd_emu8000 *emu) { int i, size; @@ -500,7 +500,7 @@ snd_emu8000_init_fm(struct snd_emu8000 *emu) /* * The main initialization routine. */ -static void __init +static void __devinit snd_emu8000_init_hw(struct snd_emu8000 *emu) { int i; @@ -1019,7 +1019,7 @@ static struct snd_kcontrol_new *mixer_defs[EMU8000_NUM_CONTROLS] = { /* * create and attach mixer elements for WaveTable treble/bass controls */ -static int __init +static int __devinit snd_emu8000_create_mixer(struct snd_card *card, struct snd_emu8000 *emu) { int i, err = 0; @@ -1069,7 +1069,7 @@ static int snd_emu8000_dev_free(struct snd_device *device) /* * initialize and register emu8000 synth device. */ -int __init +int __devinit snd_emu8000_new(struct snd_card *card, int index, long port, int seq_ports, struct snd_seq_device **awe_ret) { -- cgit v1.2.3 From 58398895663f855aa32b440b164c426cfae4450c Mon Sep 17 00:00:00 2001 From: James Courtier-Dutton Date: Sat, 10 Jun 2006 09:16:49 +0100 Subject: [ALSA] snd-ca0106: Update playback to 24bit. Fix typo is comment. Signed-off-by: James Courtier-Dutton --- sound/pci/ca0106/ca0106_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index b605d7045cc..59bf9bd0253 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c @@ -186,8 +186,8 @@ static struct snd_ca0106_details ca0106_chip_details[] = { /* New Audigy SE. Has a different DAC. */ /* SB0570: * CTRL:CA0106-DAT - * ADC: WM8768GEDS - * DAC: WM8775EDS + * ADC: WM8775EDS + * DAC: WM8768GEDS */ { .serial = 0x100a1102, .name = "Audigy SE [SB0570]", @@ -1189,7 +1189,7 @@ static unsigned int spi_dac_init[] = { 0x02ff, 0x0400, 0x0520, - 0x0600, + 0x0620, /* Set 24 bit. Was 0x0600 */ 0x08ff, 0x0aff, 0x0cff, -- cgit v1.2.3 From ecb594e66e740dc390a301768d89662777f1fde2 Mon Sep 17 00:00:00 2001 From: Remy Bruno Date: Mon, 12 Jun 2006 09:25:22 +0200 Subject: [ALSA] RME HDSP - fixed proc interface (missing {}) From: Remy Bruno Signed-off-by: Jaroslav Kysela --- sound/pci/rme9652/hdsp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index bf89ab9e313..eaf3c22449a 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c @@ -3169,9 +3169,10 @@ snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) char *clock_source; int x; - if (hdsp_check_for_iobox (hdsp)) + if (hdsp_check_for_iobox (hdsp)) { snd_iprintf(buffer, "No I/O box connected.\nPlease connect one and upload firmware.\n"); return; + } if (hdsp_check_for_firmware(hdsp, 0)) { if (hdsp->state & HDSP_FirmwareCached) { -- cgit v1.2.3 From 70c5acbdcc7bb1651bb166f9e4b2345759a9fb18 Mon Sep 17 00:00:00 2001 From: Jaya Kumar Date: Mon, 12 Jun 2006 10:08:02 +0200 Subject: [ALSA] ac97_codec - fix duplicate control creation in AC97 This patch conditions AC97 control creation by whether or not the codec is an AD18xx codec. This fixes the case where the default control would get created and then snd_ac97_mixer_build fails out when creation of ad18xx specific control would get attempted. This problem was found and debuged by Marcelo Tosatti. Signed-off-by: Jaya Kumar Signed-off-by: Jaroslav Kysela --- sound/pci/ac97/ac97_codec.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index 72e33b9532f..f8389c2d3e6 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -1236,7 +1236,8 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) ac97->regs[AC97_CENTER_LFE_MASTER] = 0x8080; /* build center controls */ - if (snd_ac97_try_volume_mix(ac97, AC97_CENTER_LFE_MASTER)) { + if ((snd_ac97_try_volume_mix(ac97, AC97_CENTER_LFE_MASTER)) + && !(ac97->flags & AC97_AD_MULTI)) { if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_center[0], ac97))) < 0) return err; if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_center[1], ac97))) < 0) @@ -1248,7 +1249,8 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) } /* build LFE controls */ - if (snd_ac97_try_volume_mix(ac97, AC97_CENTER_LFE_MASTER+1)) { + if ((snd_ac97_try_volume_mix(ac97, AC97_CENTER_LFE_MASTER+1)) + && !(ac97->flags & AC97_AD_MULTI)) { if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_lfe[0], ac97))) < 0) return err; if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_lfe[1], ac97))) < 0) @@ -1260,7 +1262,8 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) } /* build surround controls */ - if (snd_ac97_try_volume_mix(ac97, AC97_SURROUND_MASTER)) { + if ((snd_ac97_try_volume_mix(ac97, AC97_SURROUND_MASTER)) + && !(ac97->flags & AC97_AD_MULTI)) { /* Surround Master (0x38) is with stereo mutes */ if ((err = snd_ac97_cmix_new_stereo(card, "Surround Playback", AC97_SURROUND_MASTER, 1, ac97)) < 0) return err; -- cgit v1.2.3 From 6540dffa6ecfe0d99fb263548dcc4b35ccefe784 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 13 Jun 2006 11:57:22 +0200 Subject: [ALSA] hda-codec - Add SPDIF support to Thinkpad T/X/Z60 Added IEC958 (SPDIF) output support to Thinkpad T/X/Z60 with AD1981HD codec. The spdif jack is on docking station. Also, renamed 'IEC958 Playback Route' to 'IEC958 Playback Source' to avoid the mixer name confliction with IEC958 switch. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_analog.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index e83c7b01cbb..e13e36aefbb 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -963,7 +963,7 @@ static struct snd_kcontrol_new ad1983_mixers[] = { }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Route", + .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", .info = ad1983_spdif_route_info, .get = ad1983_spdif_route_get, .put = ad1983_spdif_route_put, @@ -1103,7 +1103,7 @@ static struct snd_kcontrol_new ad1981_mixers[] = { /* identical with AD1983 */ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Route", + .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", .info = ad1983_spdif_route_info, .get = ad1983_spdif_route_get, .put = ad1983_spdif_route_put, @@ -1349,6 +1349,14 @@ static struct snd_kcontrol_new ad1981_thinkpad_mixers[] = { .get = ad198x_mux_enum_get, .put = ad198x_mux_enum_put, }, + /* identical with AD1983 */ + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", + .info = ad1983_spdif_route_info, + .get = ad1983_spdif_route_get, + .put = ad1983_spdif_route_put, + }, { } /* end */ }; @@ -1422,7 +1430,6 @@ static int patch_ad1981(struct hda_codec *codec) break; case AD1981_THINKPAD: spec->mixers[0] = ad1981_thinkpad_mixers; - spec->multiout.dig_out_nid = 0; spec->input_mux = &ad1981_thinkpad_capture_source; break; } -- cgit v1.2.3 From 63eb1e4bd2975f1d1102c1f44e4fd6fcd76f7792 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Tue, 13 Jun 2006 11:58:12 +0200 Subject: [ALSA] fix potential NULL pointer deref in snd_sb8dsp_midi_interrupt() First testing if a pointer is NULL and if it is (or might be), proceeding with code that dereferences that same pointer is clearly a mistake. This happens in sound/isa/sb/sb8_midi.c::snd_sb8dsp_midi_interrupt() The patch below reworks the code so this unfortunate case doesn't happen. Also remove some blank comments. Found by the Coverity checker as bug #367 Patch is compile testted only due to lack of hardware. Signed-off-by: Jesper Juhl Signed-off-by: Takashi Iwai --- sound/isa/sb/sb8_midi.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/sound/isa/sb/sb8_midi.c b/sound/isa/sb/sb8_midi.c index c549aceea29..0b67edd7ac6 100644 --- a/sound/isa/sb/sb8_midi.c +++ b/sound/isa/sb/sb8_midi.c @@ -32,20 +32,22 @@ #include #include -/* - - */ -irqreturn_t snd_sb8dsp_midi_interrupt(struct snd_sb * chip) +irqreturn_t snd_sb8dsp_midi_interrupt(struct snd_sb *chip) { struct snd_rawmidi *rmidi; int max = 64; char byte; - if (chip == NULL || (rmidi = chip->rmidi) == NULL) { + if (!chip) + return IRQ_NONE; + + rmidi = chip->rmidi; + if (!rmidi) { inb(SBP(chip, DATA_AVAIL)); /* ack interrupt */ return IRQ_NONE; } + spin_lock(&chip->midi_input_lock); while (max-- > 0) { if (inb(SBP(chip, DATA_AVAIL)) & 0x80) { @@ -59,10 +61,6 @@ irqreturn_t snd_sb8dsp_midi_interrupt(struct snd_sb * chip) return IRQ_HANDLED; } -/* - - */ - static int snd_sb8dsp_midi_input_open(struct snd_rawmidi_substream *substream) { unsigned long flags; @@ -252,10 +250,6 @@ static void snd_sb8dsp_midi_output_trigger(struct snd_rawmidi_substream *substre snd_sb8dsp_midi_output_write(substream); } -/* - - */ - static struct snd_rawmidi_ops snd_sb8dsp_midi_output = { .open = snd_sb8dsp_midi_output_open, -- cgit v1.2.3 From 40a4f7a014339712a9f81b5fad99558611e99ca1 Mon Sep 17 00:00:00 2001 From: Jaya Kumar Date: Tue, 13 Jun 2006 12:01:14 +0200 Subject: [ALSA] cs5535audio - trivial debug printk Following is a trivial patch to get more info for boards where the AC97_VENDOR_ID2 register (or others) time out. Signed-off-by: Jaya Kumar Signed-off-by: Takashi Iwai --- sound/pci/cs5535audio/cs5535audio.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c index f61c4fa4ed6..91c18a11fe8 100644 --- a/sound/pci/cs5535audio/cs5535audio.c +++ b/sound/pci/cs5535audio/cs5535audio.c @@ -110,7 +110,8 @@ static unsigned short snd_cs5535audio_codec_read(struct cs5535audio *cs5535au, udelay(1); } while (--timeout); if (!timeout) - snd_printk(KERN_ERR "Failure reading cs5535 codec\n"); + snd_printk(KERN_ERR "Failure reading codec reg 0x%x," + "Last value=0x%x\n", reg, val); return (unsigned short) val; } -- cgit v1.2.3 From 1781a9af1d95256ed45abac4b0b87f48f64b9b87 Mon Sep 17 00:00:00 2001 From: Daniel T Chen Date: Fri, 16 Jun 2006 12:13:00 +0200 Subject: [ALSA] sound/pci/: Add hp_only quirk for Dell D800 laptops http://www.kernel.org/git/?p=linux/kernel/git/bcollins/ubuntu-dapper.git;a=commitdiff;h=9ad787cd9670c3f3b8f3db235e84baf00a2ea526 Anders Ostling comments in Malone #41015 that his Dell D800 laptop's volume control works correctly when the hp_only quirk is passed to modprobe. This commit adds his hardware's sub{vendor,device} ids to the quirk list for the intel8x0 driver. Signed-off-by: Daniel T Chen Signed-off-by: Ben Collins Signed-off-by: Takashi Iwai --- sound/pci/intel8x0.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index e09fb7f9e77..edc14475ef8 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -1805,6 +1805,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { .name = "Dell Optiplex GX270", /* AD1981B */ .type = AC97_TUNE_HP_ONLY }, + { + .subvendor = 0x1028, + .subdevice = 0x014e, + .name = "Dell D800", /* STAC9750/51 */ + .type = AC97_TUNE_HP_ONLY + }, { .subvendor = 0x1028, .subdevice = 0x0163, -- cgit v1.2.3 From d4199f01750f3fa6a5b8bacdac9bd0051fee95ef Mon Sep 17 00:00:00 2001 From: Daniel T Chen Date: Fri, 16 Jun 2006 16:21:54 +0200 Subject: [ALSA] Add hp_only quirk for pci id [161f:2032] to via82xx http://www.kernel.org/git/?p=linux/kernel/git/bcollins/ubuntu-dapper.git;a=commitdiff;h=eae2cc78de39502595f67b7fc1f821f5963bb8ae UpstreamStatus: Not merged Christian Bjalevik reports in LP#38546 that his sound chipset requires the 'hp_only' quirk to allow him to control sound volume correctly when headphones are inserted. This patch adds the appropriate pci id to the via82xx ALSA driver so that the quirk is applied automatically, thereby removing the need for users to modify /etc/modprobe.d/alsa-base (or to unload and reload snd-via82xx with ac97_quirk=hp_only). This patch closes LP#38546. Signed-off-by: Daniel T Chen Signed-off-by: Ben Collins Signed-off-by: Takashi Iwai --- sound/pci/via82xx.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 12ce22ef16e..cbad9b22f00 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -1775,6 +1775,12 @@ static struct ac97_quirk ac97_quirks[] = { .name = "Targa Traveller 811", .type = AC97_TUNE_HP_ONLY, }, + { + .subvendor = 0x161f, + .subdevice = 0x2032, + .name = "m680x", + .type = AC97_TUNE_HP_ONLY, /* http://launchpad.net/bugs/38546 */ + }, { } /* terminator */ }; -- cgit v1.2.3 From 396f739e21f3b7ea9ece08bf0abf0a45693c3047 Mon Sep 17 00:00:00 2001 From: Karsten Wiese Date: Mon, 19 Jun 2006 13:22:52 +0200 Subject: [ALSA] via82xx - Default to variable samplerate enabled for MSI K8T Neo2-FI Default to variable samplerate enabled for MSI K8T Neo2-FI No crackles here with 44100. Signed-off-by: Karsten Wiese Signed-off-by: Takashi Iwai --- sound/pci/via82xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index cbad9b22f00..2527bbd958c 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -2371,7 +2371,7 @@ static int __devinit check_dxs_list(struct pci_dev *pci, int revision) { .subvendor = 0x1462, .subdevice = 0x0470, .action = VIA_DXS_SRC }, /* MSI KT880 Delta-FSR */ { .subvendor = 0x1462, .subdevice = 0x3800, .action = VIA_DXS_ENABLE }, /* MSI KT266 */ { .subvendor = 0x1462, .subdevice = 0x5901, .action = VIA_DXS_NO_VRA }, /* MSI KT6 Delta-SR */ - { .subvendor = 0x1462, .subdevice = 0x7023, .action = VIA_DXS_NO_VRA }, /* MSI K8T Neo2-FI */ + { .subvendor = 0x1462, .subdevice = 0x7023, .action = VIA_DXS_SRC }, /* MSI K8T Neo2-FI */ { .subvendor = 0x1462, .subdevice = 0x7120, .action = VIA_DXS_ENABLE }, /* MSI KT4V */ { .subvendor = 0x1462, .subdevice = 0x7142, .action = VIA_DXS_ENABLE }, /* MSI K8MM-V */ { .subvendor = 0x1462, .subdevice = 0xb012, .action = VIA_DXS_SRC }, /* P4M800/VIA8237R */ -- cgit v1.2.3 From 1459c7849ea24fd71e4d2e678caa1cc3fef754e2 Mon Sep 17 00:00:00 2001 From: Rodolfo Giometti Date: Mon, 19 Jun 2006 15:04:54 +0200 Subject: [ALSA] Disable AC97 AUX and VIDEO controls for WM9705 touchscreen This patch by Rodolfo Giometti disables the AC97 AUX and VIDEO controls on the WM9705 when the touchscreen is selected as the AUX and VIDEO lines are shared with the touch controller. Changes:- o Added AC97_HAS_NO_AUX flag o Test for AC97_HAS_NO_AUX flag in snd_ac97_mixer_build() o Sets AC97_HAS_NO_VIDEO and AC97_HAS_NO_AUX in patch_wolfson05() when WM9705 touch driver is selected. Signed-off-by: Rodolfo Giometti Signed-off-by: Liam Girdwood Signed-off-by: Takashi Iwai --- include/sound/ac97_codec.h | 1 + sound/pci/ac97/ac97_codec.c | 8 +++++--- sound/pci/ac97/ac97_patch.c | 4 ++++ 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h index b45a7371274..446afc3ea27 100644 --- a/include/sound/ac97_codec.h +++ b/include/sound/ac97_codec.h @@ -378,6 +378,7 @@ #define AC97_HAS_NO_MIC (1<<15) /* no MIC volume */ #define AC97_HAS_NO_TONE (1<<16) /* no Tone volume */ #define AC97_HAS_NO_STD_PCM (1<<17) /* no standard AC97 PCM volume and mute */ +#define AC97_HAS_NO_AUX (1<<18) /* no standard AC97 AUX volume and mute */ /* rates indexes */ #define AC97_RATES_FRONT_DAC 0 diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index f8389c2d3e6..0abf2808d59 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -1348,9 +1348,11 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) } /* build Aux controls */ - if (snd_ac97_try_volume_mix(ac97, AC97_AUX)) { - if ((err = snd_ac97_cmix_new(card, "Aux Playback", AC97_AUX, ac97)) < 0) - return err; + if (!(ac97->flags & AC97_HAS_NO_AUX)) { + if (snd_ac97_try_volume_mix(ac97, AC97_AUX)) { + if ((err = snd_ac97_cmix_new(card, "Aux Playback", AC97_AUX, ac97)) < 0) + return err; + } } /* build PCM controls */ diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index 1c47ee3d7ef..cc93ee61908 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c @@ -464,6 +464,10 @@ int patch_wolfson05(struct snd_ac97 * ac97) { /* WM9705, WM9710 */ ac97->build_ops = &patch_wolfson_wm9705_ops; +#ifdef CONFIG_TOUCHSCREEN_WM9705 + /* WM9705 touchscreen uses AUX and VIDEO for touch */ + ac97->flags |=3D AC97_HAS_NO_VIDEO | AC97_HAS_NO_AUX; +#endif return 0; } -- cgit v1.2.3 From 1561f09a2f91bc258a72225f919807c9e51c8290 Mon Sep 17 00:00:00 2001 From: Jaya Kumar Date: Mon, 19 Jun 2006 15:06:14 +0200 Subject: [ALSA] AD1888 suspend/resume fix This patch adds a write to an undocumented register, 0x60 Extended Codec Register Page in the AD1888 codec. It is neccessary in order to make suspend/resume work with the AD1888. Signed-off-by: Jaya Kumar Signed-off-by: Takashi Iwai --- sound/pci/ac97/ac97_patch.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index cc93ee61908..7f197c78081 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c @@ -1371,6 +1371,13 @@ static void ad18xx_resume(struct snd_ac97 *ac97) snd_ac97_restore_iec958(ac97); } + +static void ad1888_resume(struct snd_ac97 *ac97) +{ + ad18xx_resume(ac97); + snd_ac97_write_cache(ac97, AC97_CODEC_CLASS_REV, 0x8080); +} + #endif int patch_ad1819(struct snd_ac97 * ac97) @@ -1844,7 +1851,7 @@ static struct snd_ac97_build_ops patch_ad1888_build_ops = { .build_post_spdif = patch_ad198x_post_spdif, .build_specific = patch_ad1888_specific, #ifdef CONFIG_PM - .resume = ad18xx_resume, + .resume = ad1888_resume, #endif .update_jacks = ad1888_update_jacks, }; -- cgit v1.2.3 From c4a87ef4de9860d00460dce30776f7cc17e77459 Mon Sep 17 00:00:00 2001 From: Ben Williamson Date: Mon, 19 Jun 2006 17:20:09 +0200 Subject: [ALSA] USB midi: Remove duplicate CS_AUDIO_* #defines Removed the CS_AUDIO_* #defines, which were duplicates of the class-specific USB_DT_CS_* #defines in . Signed-off-by: Ben Williamson Signed-off-by: Takashi Iwai --- sound/usb/usbaudio.c | 2 +- sound/usb/usbaudio.h | 7 ------- sound/usb/usbmidi.c | 2 +- 3 files changed, 2 insertions(+), 9 deletions(-) diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 30cadec9a34..627de9525a3 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -2981,7 +2981,7 @@ static int create_ua1000_quirk(struct snd_usb_audio *chip, return -ENXIO; alts = &iface->altsetting[1]; altsd = get_iface_desc(alts); - if (alts->extralen != 11 || alts->extra[1] != CS_AUDIO_INTERFACE || + if (alts->extralen != 11 || alts->extra[1] != USB_DT_CS_INTERFACE || altsd->bNumEndpoints != 1) return -ENXIO; diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index 88733524d0f..0f4b2b8541d 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -30,13 +30,6 @@ #define USB_SUBCLASS_MIDI_STREAMING 0x03 #define USB_SUBCLASS_VENDOR_SPEC 0xff -#define CS_AUDIO_UNDEFINED 0x20 -#define CS_AUDIO_DEVICE 0x21 -#define CS_AUDIO_CONFIGURATION 0x22 -#define CS_AUDIO_STRING 0x23 -#define CS_AUDIO_INTERFACE 0x24 -#define CS_AUDIO_ENDPOINT 0x25 - #define HEADER 0x01 #define INPUT_TERMINAL 0x02 #define OUTPUT_TERMINAL 0x03 diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c index 5c53ec8a13b..5105b6b0574 100644 --- a/sound/usb/usbmidi.c +++ b/sound/usb/usbmidi.c @@ -1413,7 +1413,7 @@ static int snd_usbmidi_detect_yamaha(struct snd_usb_midi* umidi, for (cs_desc = hostif->extra; cs_desc < hostif->extra + hostif->extralen && cs_desc[0] >= 2; cs_desc += cs_desc[0]) { - if (cs_desc[1] == CS_AUDIO_INTERFACE) { + if (cs_desc[1] == USB_DT_CS_INTERFACE) { if (cs_desc[2] == MIDI_IN_JACK) endpoint->in_cables = (endpoint->in_cables << 1) | 1; else if (cs_desc[2] == MIDI_OUT_JACK) -- cgit v1.2.3 From 6dac9a65f05600bc29316e3cf3365236efe69041 Mon Sep 17 00:00:00 2001 From: Daniel T Chen Date: Wed, 21 Jun 2006 08:51:07 +0200 Subject: [ALSA] HDA - Lenovo 3000 N100-07684JU - enable laptop-eapd by default Justin Sunseri reports that sound is audible on his Lenovo 3000 N100-07684JU by passing 'model=laptop-eapd' to modprobe, so this patch adds the pci ids for his sound device to patch_analog.c . This commit closes LP#39517. Alexey Parshin also confirmed the fix at http://bugs.gentoo.org/137245 TODO: Mute onboard speakers when device is plugged into the headphone jack. Muting the 'External Amplifier' mixer element while a device is plugged into the headphone jack allows sound to be played only from the headphone jack. From: Daniel T Chen Signed-off-by: Daniel T Chen Signed-off-by: Daniel Drake Signed-off-by: Jaroslav Kysela --- sound/pci/hda/patch_analog.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index e13e36aefbb..9a6015ad618 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -809,6 +809,8 @@ static struct hda_board_config ad1986a_cfg_tbl[] = { .config = AD1986A_LAPTOP_EAPD }, /* ASUS Z62F */ { .pci_subvendor = 0x103c, .pci_subdevice = 0x30af, .config = AD1986A_LAPTOP_EAPD }, /* HP Compaq Presario B2800 */ + { .pci_subvendor = 0x17aa, .pci_subdevice = 0x2066, + .config = AD1986A_LAPTOP_EAPD }, /* Lenovo 3000 N100-07684JU */ {} }; -- cgit v1.2.3 From 41f0cd3a0c4c6547860cf3b1c2d7968008e6c071 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 21 Jun 2006 12:14:40 +0200 Subject: [ALSA] hda-codec - Use 3stack model for ASUS P5RD2-VM / P5GPL-X SE Use 3stack model as default for ASUS P5RD2-VM and P5GPL-X SE boards with AD1986A codec (ALSA bug#2103). Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_analog.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 9a6015ad618..dd4e00a82b5 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -789,6 +789,8 @@ static struct hda_board_config ad1986a_cfg_tbl[] = { { .modelname = "3stack", .config = AD1986A_3STACK }, { .pci_subvendor = 0x10de, .pci_subdevice = 0xcb84, .config = AD1986A_3STACK }, /* ASUS A8N-VM CSM */ + { .pci_subvendor = 0x1043, .pci_subdevice = 0x81b3, + .config = AD1986A_3STACK }, /* ASUS P5RD2-VM / P5GPL-X SE */ { .modelname = "laptop", .config = AD1986A_LAPTOP }, { .pci_subvendor = 0x144d, .pci_subdevice = 0xc01e, .config = AD1986A_LAPTOP }, /* FSC V2060 */ -- cgit v1.2.3 From f3d9478b2ce468c3115b02ecae7e975990697f15 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 21 Jun 2006 15:42:43 +0200 Subject: [ALSA] snd-aoa: add snd-aoa This large patch adds all of snd-aoa. Consisting of many modules, it currently replaces snd-powermac for all layout-id based machines and handles many more (for example new powerbooks and powermacs with digital output that previously couldn't be used at all). It also has support for all layout-IDs that Apple has (judging from their Info.plist file) but not all are tested. The driver currently has 2 known regressions over snd-powermac: * it doesn't handle powermac 7,2 and 7,3 * it doesn't have a DRC control on snapper-based machines I will fix those during the 2.6.18 development cycle. Signed-off-by: Johannes Berg Signed-off-by: Takashi Iwai --- sound/Kconfig | 2 + sound/Makefile | 2 +- sound/aoa/Kconfig | 17 + sound/aoa/Makefile | 4 + sound/aoa/aoa-gpio.h | 81 ++ sound/aoa/aoa.h | 131 +++ sound/aoa/codecs/Kconfig | 32 + sound/aoa/codecs/Makefile | 3 + sound/aoa/codecs/snd-aoa-codec-onyx.c | 1113 +++++++++++++++++++++++ sound/aoa/codecs/snd-aoa-codec-onyx.h | 76 ++ sound/aoa/codecs/snd-aoa-codec-tas-gain-table.h | 209 +++++ sound/aoa/codecs/snd-aoa-codec-tas.c | 654 +++++++++++++ sound/aoa/codecs/snd-aoa-codec-tas.h | 47 + sound/aoa/codecs/snd-aoa-codec-toonie.c | 141 +++ sound/aoa/core/Makefile | 5 + sound/aoa/core/snd-aoa-alsa.c | 98 ++ sound/aoa/core/snd-aoa-alsa.h | 16 + sound/aoa/core/snd-aoa-core.c | 162 ++++ sound/aoa/core/snd-aoa-gpio-feature.c | 399 ++++++++ sound/aoa/core/snd-aoa-gpio-pmf.c | 246 +++++ sound/aoa/fabrics/Kconfig | 12 + sound/aoa/fabrics/Makefile | 1 + sound/aoa/fabrics/snd-aoa-fabric-layout.c | 1109 ++++++++++++++++++++++ sound/aoa/soundbus/Kconfig | 14 + sound/aoa/soundbus/Makefile | 3 + sound/aoa/soundbus/core.c | 250 +++++ sound/aoa/soundbus/i2sbus/Makefile | 2 + sound/aoa/soundbus/i2sbus/i2sbus-control.c | 192 ++++ sound/aoa/soundbus/i2sbus/i2sbus-control.h | 37 + sound/aoa/soundbus/i2sbus/i2sbus-core.c | 387 ++++++++ sound/aoa/soundbus/i2sbus/i2sbus-interface.h | 187 ++++ sound/aoa/soundbus/i2sbus/i2sbus-pcm.c | 1021 +++++++++++++++++++++ sound/aoa/soundbus/i2sbus/i2sbus.h | 112 +++ sound/aoa/soundbus/soundbus.h | 202 ++++ sound/aoa/soundbus/sysfs.c | 43 + 35 files changed, 7009 insertions(+), 1 deletion(-) create mode 100644 sound/aoa/Kconfig create mode 100644 sound/aoa/Makefile create mode 100644 sound/aoa/aoa-gpio.h create mode 100644 sound/aoa/aoa.h create mode 100644 sound/aoa/codecs/Kconfig create mode 100644 sound/aoa/codecs/Makefile create mode 100644 sound/aoa/codecs/snd-aoa-codec-onyx.c create mode 100644 sound/aoa/codecs/snd-aoa-codec-onyx.h create mode 100644 sound/aoa/codecs/snd-aoa-codec-tas-gain-table.h create mode 100644 sound/aoa/codecs/snd-aoa-codec-tas.c create mode 100644 sound/aoa/codecs/snd-aoa-codec-tas.h create mode 100644 sound/aoa/codecs/snd-aoa-codec-toonie.c create mode 100644 sound/aoa/core/Makefile create mode 100644 sound/aoa/core/snd-aoa-alsa.c create mode 100644 sound/aoa/core/snd-aoa-alsa.h create mode 100644 sound/aoa/core/snd-aoa-core.c create mode 100644 sound/aoa/core/snd-aoa-gpio-feature.c create mode 100644 sound/aoa/core/snd-aoa-gpio-pmf.c create mode 100644 sound/aoa/fabrics/Kconfig create mode 100644 sound/aoa/fabrics/Makefile create mode 100644 sound/aoa/fabrics/snd-aoa-fabric-layout.c create mode 100644 sound/aoa/soundbus/Kconfig create mode 100644 sound/aoa/soundbus/Makefile create mode 100644 sound/aoa/soundbus/core.c create mode 100644 sound/aoa/soundbus/i2sbus/Makefile create mode 100644 sound/aoa/soundbus/i2sbus/i2sbus-control.c create mode 100644 sound/aoa/soundbus/i2sbus/i2sbus-control.h create mode 100644 sound/aoa/soundbus/i2sbus/i2sbus-core.c create mode 100644 sound/aoa/soundbus/i2sbus/i2sbus-interface.h create mode 100644 sound/aoa/soundbus/i2sbus/i2sbus-pcm.c create mode 100644 sound/aoa/soundbus/i2sbus/i2sbus.h create mode 100644 sound/aoa/soundbus/soundbus.h create mode 100644 sound/aoa/soundbus/sysfs.c diff --git a/sound/Kconfig b/sound/Kconfig index b65ee4701f9..e0d791a9845 100644 --- a/sound/Kconfig +++ b/sound/Kconfig @@ -58,6 +58,8 @@ source "sound/pci/Kconfig" source "sound/ppc/Kconfig" +source "sound/aoa/Kconfig" + source "sound/arm/Kconfig" source "sound/mips/Kconfig" diff --git a/sound/Makefile b/sound/Makefile index f352bb23596..a682ea30f0c 100644 --- a/sound/Makefile +++ b/sound/Makefile @@ -4,7 +4,7 @@ obj-$(CONFIG_SOUND) += soundcore.o obj-$(CONFIG_SOUND_PRIME) += oss/ obj-$(CONFIG_DMASOUND) += oss/ -obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ synth/ usb/ sparc/ parisc/ pcmcia/ mips/ +obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ synth/ usb/ sparc/ parisc/ pcmcia/ mips/ aoa/ ifeq ($(CONFIG_SND),y) obj-y += last.o diff --git a/sound/aoa/Kconfig b/sound/aoa/Kconfig new file mode 100644 index 00000000000..b11ccf6dbab --- /dev/null +++ b/sound/aoa/Kconfig @@ -0,0 +1,17 @@ +menu "Apple Onboard Audio driver" + depends on SND != n && PPC + +config SND_AOA + tristate "Apple Onboard Audio driver" + depends on SOUND && SND_PCM + ---help--- + This option enables the new driver for the various + Apple Onboard Audio components. + +source "sound/aoa/fabrics/Kconfig" + +source "sound/aoa/codecs/Kconfig" + +source "sound/aoa/soundbus/Kconfig" + +endmenu diff --git a/sound/aoa/Makefile b/sound/aoa/Makefile new file mode 100644 index 00000000000..d8de3e7df48 --- /dev/null +++ b/sound/aoa/Makefile @@ -0,0 +1,4 @@ +obj-$(CONFIG_SND_AOA) += core/ +obj-$(CONFIG_SND_AOA) += codecs/ +obj-$(CONFIG_SND_AOA) += fabrics/ +obj-$(CONFIG_SND_AOA_SOUNDBUS) += soundbus/ diff --git a/sound/aoa/aoa-gpio.h b/sound/aoa/aoa-gpio.h new file mode 100644 index 00000000000..3a61f311557 --- /dev/null +++ b/sound/aoa/aoa-gpio.h @@ -0,0 +1,81 @@ +/* + * Apple Onboard Audio GPIO definitions + * + * Copyright 2006 Johannes Berg + * + * GPL v2, can be found in COPYING. + */ + +#ifndef __AOA_GPIO_H +#define __AOA_GPIO_H +#include +#include +#include + +typedef void (*notify_func_t)(void *data); + +enum notify_type { + AOA_NOTIFY_HEADPHONE, + AOA_NOTIFY_LINE_IN, + AOA_NOTIFY_LINE_OUT, +}; + +struct gpio_runtime; +struct gpio_methods { + /* for initialisation/de-initialisation of the GPIO layer */ + void (*init)(struct gpio_runtime *rt); + void (*exit)(struct gpio_runtime *rt); + + /* turn off headphone, speakers, lineout */ + void (*all_amps_off)(struct gpio_runtime *rt); + /* turn headphone, speakers, lineout back to previous setting */ + void (*all_amps_restore)(struct gpio_runtime *rt); + + void (*set_headphone)(struct gpio_runtime *rt, int on); + void (*set_speakers)(struct gpio_runtime *rt, int on); + void (*set_lineout)(struct gpio_runtime *rt, int on); + + int (*get_headphone)(struct gpio_runtime *rt); + int (*get_speakers)(struct gpio_runtime *rt); + int (*get_lineout)(struct gpio_runtime *rt); + + void (*set_hw_reset)(struct gpio_runtime *rt, int on); + + /* use this to be notified of any events. The notification + * function is passed the data, and is called in process + * context by the use of schedule_work. + * The interface for it is that setting a function to NULL + * removes it, and they return 0 if the operation succeeded, + * and -EBUSY if the notification is already assigned by + * someone else. */ + int (*set_notify)(struct gpio_runtime *rt, + enum notify_type type, + notify_func_t notify, + void *data); + /* returns 0 if not plugged in, 1 if plugged in + * or a negative error code */ + int (*get_detect)(struct gpio_runtime *rt, + enum notify_type type); +}; + +struct gpio_notification { + notify_func_t notify; + void *data; + void *gpio_private; + struct work_struct work; + struct mutex mutex; +}; + +struct gpio_runtime { + /* to be assigned by fabric */ + struct device_node *node; + /* since everyone needs this pointer anyway... */ + struct gpio_methods *methods; + /* to be used by the gpio implementation */ + int implementation_private; + struct gpio_notification headphone_notify; + struct gpio_notification line_in_notify; + struct gpio_notification line_out_notify; +}; + +#endif /* __AOA_GPIO_H */ diff --git a/sound/aoa/aoa.h b/sound/aoa/aoa.h new file mode 100644 index 00000000000..378ef1e9879 --- /dev/null +++ b/sound/aoa/aoa.h @@ -0,0 +1,131 @@ +/* + * Apple Onboard Audio definitions + * + * Copyright 2006 Johannes Berg + * + * GPL v2, can be found in COPYING. + */ + +#ifndef __AOA_H +#define __AOA_H +#include +#include +/* So apparently there's a reason for requiring driver.h to be included first! */ +#include +#include +#include +#include +#include "aoa-gpio.h" +#include "soundbus/soundbus.h" + +#define MAX_CODEC_NAME_LEN 32 + +struct aoa_codec { + char name[MAX_CODEC_NAME_LEN]; + + struct module *owner; + + /* called when the fabric wants to init this codec. + * Do alsa card manipulations from here. */ + int (*init)(struct aoa_codec *codec); + + /* called when the fabric is done with the codec. + * The alsa card will be cleaned up so don't bother. */ + void (*exit)(struct aoa_codec *codec); + + /* May be NULL, but can be used by the fabric. + * Refcounting is the codec driver's responsibility */ + struct device_node *node; + + /* assigned by fabric before init() is called, points + * to the soundbus device. Cannot be NULL. */ + struct soundbus_dev *soundbus_dev; + + /* assigned by the fabric before init() is called, points + * to the fabric's gpio runtime record for the relevant + * device. */ + struct gpio_runtime *gpio; + + /* assigned by the fabric before init() is called, contains + * a codec specific bitmask of what outputs and inputs are + * actually connected */ + u32 connected; + + /* data the fabric can associate with this structure */ + void *fabric_data; + + /* private! */ + struct list_head list; + struct aoa_fabric *fabric; +}; + +/* return 0 on success */ +extern int +aoa_codec_register(struct aoa_codec *codec); +extern void +aoa_codec_unregister(struct aoa_codec *codec); + +#define MAX_LAYOUT_NAME_LEN 32 + +struct aoa_fabric { + char name[MAX_LAYOUT_NAME_LEN]; + + struct module *owner; + + /* once codecs register, they are passed here after. + * They are of course not initialised, since the + * fabric is responsible for initialising some fields + * in the codec structure! */ + int (*found_codec)(struct aoa_codec *codec); + /* called for each codec when it is removed, + * also in the case that aoa_fabric_unregister + * is called and all codecs are removed + * from this fabric. + * Also called if found_codec returned 0 but + * the codec couldn't initialise. */ + void (*remove_codec)(struct aoa_codec *codec); + /* If found_codec returned 0, and the codec + * could be initialised, this is called. */ + void (*attached_codec)(struct aoa_codec *codec); +}; + +/* return 0 on success, -EEXIST if another fabric is + * registered, -EALREADY if the same fabric is registered. + * Passing NULL can be used to test for the presence + * of another fabric, if -EALREADY is returned there is + * no other fabric present. + * In the case that the function returns -EALREADY + * and the fabric passed is not NULL, all codecs + * that are not assigned yet are passed to the fabric + * again for reconsideration. */ +extern int +aoa_fabric_register(struct aoa_fabric *fabric); + +/* it is vital to call this when the fabric exits! + * When calling, the remove_codec will be called + * for all codecs, unless it is NULL. */ +extern void +aoa_fabric_unregister(struct aoa_fabric *fabric); + +/* if for some reason you want to get rid of a codec + * before the fabric is removed, use this. + * Note that remove_codec is called for it! */ +extern void +aoa_fabric_unlink_codec(struct aoa_codec *codec); + +/* alsa help methods */ +struct aoa_card { + struct snd_card *alsa_card; +}; + +extern int aoa_snd_device_new(snd_device_type_t type, + void * device_data, struct snd_device_ops * ops); +extern struct snd_card *aoa_get_card(void); +extern int aoa_snd_ctl_add(struct snd_kcontrol* control); + +/* GPIO stuff */ +extern struct gpio_methods *pmf_gpio_methods; +extern struct gpio_methods *ftr_gpio_methods; +/* extern struct gpio_methods *map_gpio_methods; */ + +#endif /* __AOA_H */ diff --git a/sound/aoa/codecs/Kconfig b/sound/aoa/codecs/Kconfig new file mode 100644 index 00000000000..90cf58f6863 --- /dev/null +++ b/sound/aoa/codecs/Kconfig @@ -0,0 +1,32 @@ +config SND_AOA_ONYX + tristate "support Onyx chip" + depends on SND_AOA + ---help--- + This option enables support for the Onyx (pcm3052) + codec chip found in the latest Apple machines + (most of those with digital audio output). + +#config SND_AOA_TOPAZ +# tristate "support Topaz chips" +# depends on SND_AOA +# ---help--- +# This option enables support for the Topaz (CS84xx) +# codec chips found in the latest Apple machines, +# these chips do the digital input and output on +# some PowerMacs. + +config SND_AOA_TAS + tristate "support TAS chips" + depends on SND_AOA + ---help--- + This option enables support for the tas chips + found in a lot of Apple Machines, especially + iBooks and PowerBooks without digital. + +config SND_AOA_TOONIE + tristate "support Toonie chip" + depends on SND_AOA + ---help--- + This option enables support for the toonie codec + found in the Mac Mini. If you have a Mac Mini and + want to hear sound, select this option. diff --git a/sound/aoa/codecs/Makefile b/sound/aoa/codecs/Makefile new file mode 100644 index 00000000000..31cbe68fd42 --- /dev/null +++ b/sound/aoa/codecs/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_SND_AOA_ONYX) += snd-aoa-codec-onyx.o +obj-$(CONFIG_SND_AOA_TAS) += snd-aoa-codec-tas.o +obj-$(CONFIG_SND_AOA_TOONIE) += snd-aoa-codec-toonie.o diff --git a/sound/aoa/codecs/snd-aoa-codec-onyx.c b/sound/aoa/codecs/snd-aoa-codec-onyx.c new file mode 100644 index 00000000000..0b7650788f1 --- /dev/null +++ b/sound/aoa/codecs/snd-aoa-codec-onyx.c @@ -0,0 +1,1113 @@ +/* + * Apple Onboard Audio driver for Onyx codec + * + * Copyright 2006 Johannes Berg + * + * GPL v2, can be found in COPYING. + * + * + * This is a driver for the pcm3052 codec chip (codenamed Onyx) + * that is present in newer Apple hardware (with digital output). + * + * The Onyx codec has the following connections (listed by the bit + * to be used in aoa_codec.connected): + * 0: analog output + * 1: digital output + * 2: line input + * 3: microphone input + * Note that even though I know of no machine that has for example + * the digital output connected but not the analog, I have handled + * all the different cases in the code so that this driver may serve + * as a good example of what to do. + * + * NOTE: This driver assumes that there's at most one chip to be + * used with one alsa card, in form of creating all kinds + * of mixer elements without regard for their existence. + * But snd-aoa assumes that there's at most one card, so + * this means you can only have one onyx on a system. This + * should probably be fixed by changing the assumption of + * having just a single card on a system, and making the + * 'card' pointer accessible to anyone who needs it instead + * of hiding it in the aoa_snd_* functions... + * + */ +#include +#include +MODULE_AUTHOR("Johannes Berg "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("pcm3052 (onyx) codec driver for snd-aoa"); + +#include "snd-aoa-codec-onyx.h" +#include "../aoa.h" +#include "../soundbus/soundbus.h" + + +#define PFX "snd-aoa-codec-onyx: " + +struct onyx { + /* cache registers 65 to 80, they are write-only! */ + u8 cache[16]; + struct i2c_client i2c; + struct aoa_codec codec; + u32 initialised:1, + spdif_locked:1, + analog_locked:1, + original_mute:2; + int open_count; + struct codec_info *codec_info; + + /* mutex serializes concurrent access to the device + * and this structure. + */ + struct mutex mutex; +}; +#define codec_to_onyx(c) container_of(c, struct onyx, codec) + +/* both return 0 if all ok, else on error */ +static int onyx_read_register(struct onyx *onyx, u8 reg, u8 *value) +{ + s32 v; + + if (reg != ONYX_REG_CONTROL) { + *value = onyx->cache[reg-FIRSTREGISTER]; + return 0; + } + v = i2c_smbus_read_byte_data(&onyx->i2c, reg); + if (v < 0) + return -1; + *value = (u8)v; + onyx->cache[ONYX_REG_CONTROL-FIRSTREGISTER] = *value; + return 0; +} + +static int onyx_write_register(struct onyx *onyx, u8 reg, u8 value) +{ + int result; + + result = i2c_smbus_write_byte_data(&onyx->i2c, reg, value); + if (!result) + onyx->cache[reg-FIRSTREGISTER] = value; + return result; +} + +/* alsa stuff */ + +static int onyx_dev_register(struct snd_device *dev) +{ + return 0; +} + +static struct snd_device_ops ops = { + .dev_register = onyx_dev_register, +}; + +/* this is necessary because most alsa mixer programs + * can't properly handle the negative range */ +#define VOLUME_RANGE_SHIFT 128 + +static int onyx_snd_vol_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 2; + uinfo->value.integer.min = -128 + VOLUME_RANGE_SHIFT; + uinfo->value.integer.max = -1 + VOLUME_RANGE_SHIFT; + return 0; +} + +static int onyx_snd_vol_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct onyx *onyx = snd_kcontrol_chip(kcontrol); + s8 l, r; + + mutex_lock(&onyx->mutex); + onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_LEFT, &l); + onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT, &r); + mutex_unlock(&onyx->mutex); + + ucontrol->value.integer.value[0] = l + VOLUME_RANGE_SHIFT; + ucontrol->value.integer.value[1] = r + VOLUME_RANGE_SHIFT; + + return 0; +} + +static int onyx_snd_vol_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct onyx *onyx = snd_kcontrol_chip(kcontrol); + s8 l, r; + + mutex_lock(&onyx->mutex); + onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_LEFT, &l); + onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT, &r); + + if (l + VOLUME_RANGE_SHIFT == ucontrol->value.integer.value[0] && + r + VOLUME_RANGE_SHIFT == ucontrol->value.integer.value[1]) { + mutex_unlock(&onyx->mutex); + return 0; + } + + onyx_write_register(onyx, ONYX_REG_DAC_ATTEN_LEFT, + ucontrol->value.integer.value[0] + - VOLUME_RANGE_SHIFT); + onyx_write_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT, + ucontrol->value.integer.value[1] + - VOLUME_RANGE_SHIFT); + mutex_unlock(&onyx->mutex); + + return 1; +} + +static struct snd_kcontrol_new volume_control = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Master Playback Volume", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .info = onyx_snd_vol_info, + .get = onyx_snd_vol_get, + .put = onyx_snd_vol_put, +}; + +/* like above, this is necessary because a lot + * of alsa mixer programs don't handle ranges + * that don't start at 0 properly. + * even alsamixer is one of them... */ +#define INPUTGAIN_RANGE_SHIFT (-3) + +static int onyx_snd_inputgain_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = 3 + INPUTGAIN_RANGE_SHIFT; + uinfo->value.integer.max = 28 + INPUTGAIN_RANGE_SHIFT; + return 0; +} + +static int onyx_snd_inputgain_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct onyx *onyx = snd_kcontrol_chip(kcontrol); + u8 ig; + + mutex_lock(&onyx->mutex); + onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &ig); + mutex_unlock(&onyx->mutex); + + ucontrol->value.integer.value[0] = + (ig & ONYX_ADC_PGA_GAIN_MASK) + INPUTGAIN_RANGE_SHIFT; + + return 0; +} + +static int onyx_snd_inputgain_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct onyx *onyx = snd_kcontrol_chip(kcontrol); + u8 v, n; + + mutex_lock(&onyx->mutex); + onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v); + n = v; + n &= ~ONYX_ADC_PGA_GAIN_MASK; + n |= (ucontrol->value.integer.value[0] - INPUTGAIN_RANGE_SHIFT) + & ONYX_ADC_PGA_GAIN_MASK; + onyx_write_register(onyx, ONYX_REG_ADC_CONTROL, n); + mutex_unlock(&onyx->mutex); + + return n != v; +} + +static struct snd_kcontrol_new inputgain_control = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Master Capture Volume", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .info = onyx_snd_inputgain_info, + .get = onyx_snd_inputgain_get, + .put = onyx_snd_inputgain_put, +}; + +static int onyx_snd_capture_source_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + static char *texts[] = { "Line-In", "Microphone" }; + + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; + uinfo->count = 1; + uinfo->value.enumerated.items = 2; + if (uinfo->value.enumerated.item > 1) + uinfo->value.enumerated.item = 1; + strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); + return 0; +} + +static int onyx_snd_capture_source_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct onyx *onyx = snd_kcontrol_chip(kcontrol); + s8 v; + + mutex_lock(&onyx->mutex); + onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v); + mutex_unlock(&onyx->mutex); + + ucontrol->value.enumerated.item[0] = !!(v&ONYX_ADC_INPUT_MIC); + + return 0; +} + +static void onyx_set_capture_source(struct onyx *onyx, int mic) +{ + s8 v; + + mutex_lock(&onyx->mutex); + onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v); + v &= ~ONYX_ADC_INPUT_MIC; + if (mic) + v |= ONYX_ADC_INPUT_MIC; + onyx_write_register(onyx, ONYX_REG_ADC_CONTROL, v); + mutex_unlock(&onyx->mutex); +} + +static int onyx_snd_capture_source_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + onyx_set_capture_source(snd_kcontrol_chip(kcontrol), + ucontrol->value.enumerated.item[0]); + return 1; +} + +static struct snd_kcontrol_new capture_source_control = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + /* If we name this 'Input Source', it properly shows up in + * alsamixer as a selection, * but it's shown under the + * 'Playback' category. + * If I name it 'Capture Source', it shows up in strange + * ways (two bools of which one can be selected at a + * time) but at least it's shown in the 'Capture' + * category. + * I was told that this was due to backward compatibility, + * but I don't understand then why the mangling is *not* + * done when I name it "Input Source"..... + */ + .name = "Capture Source", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .info = onyx_snd_capture_source_info, + .get = onyx_snd_capture_source_get, + .put = onyx_snd_capture_source_put, +}; + +static int onyx_snd_mute_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + uinfo->count = 2; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + return 0; +} + +static int onyx_snd_mute_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct onyx *onyx = snd_kcontrol_chip(kcontrol); + u8 c; + + mutex_lock(&onyx->mutex); + onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &c); + mutex_unlock(&onyx->mutex); + + ucontrol->value.integer.value[0] = !(c & ONYX_MUTE_LEFT); + ucontrol->value.integer.value[1] = !(c & ONYX_MUTE_RIGHT); + + return 0; +} + +static int onyx_snd_mute_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct onyx *onyx = snd_kcontrol_chip(kcontrol); + u8 v = 0, c = 0; + int err = -EBUSY; + + mutex_lock(&onyx->mutex); + if (onyx->analog_locked) + goto out_unlock; + + onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v); + c = v; + c &= ~(ONYX_MUTE_RIGHT | ONYX_MUTE_LEFT); + if (!ucontrol->value.integer.value[0]) + c |= ONYX_MUTE_LEFT; + if (!ucontrol->value.integer.value[1]) + c |= ONYX_MUTE_RIGHT; + err = onyx_write_register(onyx, ONYX_REG_DAC_CONTROL, c); + + out_unlock: + mutex_unlock(&onyx->mutex); + + return !err ? (v != c) : err; +} + +static struct snd_kcontrol_new mute_control = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Master Playback Switch", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .info = onyx_snd_mute_info, + .get = onyx_snd_mute_get, + .put = onyx_snd_mute_put, +}; + + +static int onyx_snd_single_bit_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + return 0; +} + +#define FLAG_POLARITY_INVERT 1 +#define FLAG_SPDIFLOCK 2 + +static int onyx_snd_single_bit_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct onyx *onyx = snd_kcontrol_chip(kcontrol); + u8 c; + long int pv = kcontrol->private_value; + u8 polarity = (pv >> 16) & FLAG_POLARITY_INVERT; + u8 address = (pv >> 8) & 0xff; + u8 mask = pv & 0xff; + + mutex_lock(&onyx->mutex); + onyx_read_register(onyx, address, &c); + mutex_unlock(&onyx->mutex); + + ucontrol->value.integer.value[0] = !!(c & mask) ^ polarity; + + return 0; +} + +static int onyx_snd_single_bit_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct onyx *onyx = snd_kcontrol_chip(kcontrol); + u8 v = 0, c = 0; + int err; + long int pv = kcontrol->private_value; + u8 polarity = (pv >> 16) & FLAG_POLARITY_INVERT; + u8 spdiflock = (pv >> 16) & FLAG_SPDIFLOCK; + u8 address = (pv >> 8) & 0xff; + u8 mask = pv & 0xff; + + mutex_lock(&onyx->mutex); + if (spdiflock && onyx->spdif_locked) { + /* even if alsamixer doesn't care.. */ + err = -EBUSY; + goto out_unlock; + } + onyx_read_register(onyx, address, &v); + c = v; + c &= ~(mask); + if (!!ucontrol->value.integer.value[0] ^ polarity) + c |= mask; + err = onyx_write_register(onyx, address, c); + + out_unlock: + mutex_unlock(&onyx->mutex); + + return !err ? (v != c) : err; +} + +#define SINGLE_BIT(n, type, description, address, mask, flags) \ +static struct snd_kcontrol_new n##_control = { \ + .iface = SNDRV_CTL_ELEM_IFACE_##type, \ + .name = description, \ + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ + .info = onyx_snd_single_bit_info, \ + .get = onyx_snd_single_bit_get, \ + .put = onyx_snd_single_bit_put, \ + .private_value = (flags << 16) | (address << 8) | mask \ +} + +SINGLE_BIT(spdif, + MIXER, + SNDRV_CTL_NAME_IEC958("", PLAYBACK, SWITCH), + ONYX_REG_DIG_INFO4, + ONYX_SPDIF_ENABLE, + FLAG_SPDIFLOCK); +SINGLE_BIT(ovr1, + MIXER, + "Oversampling Rate", + ONYX_REG_DAC_CONTROL, + ONYX_OVR1, + 0); +SINGLE_BIT(flt0, + MIXER, + "Fast Digital Filter Rolloff", + ONYX_REG_DAC_FILTER, + ONYX_ROLLOFF_FAST, + FLAG_POLARITY_INVERT); +SINGLE_BIT(hpf, + MIXER, + "Highpass Filter", + ONYX_REG_ADC_HPF_BYPASS, + ONYX_HPF_DISABLE, + FLAG_POLARITY_INVERT); +SINGLE_BIT(dm12, + MIXER, + "Digital De-Emphasis", + ONYX_REG_DAC_DEEMPH, + ONYX_DIGDEEMPH_CTRL, + 0); + +static int onyx_spdif_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; + uinfo->count = 1; + return 0; +} + +static int onyx_spdif_mask_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + /* datasheet page 30, all others are 0 */ + ucontrol->value.iec958.status[0] = 0x3e; + ucontrol->value.iec958.status[1] = 0xff; + + ucontrol->value.iec958.status[3] = 0x3f; + ucontrol->value.iec958.status[4] = 0x0f; + + return 0; +} + +static struct snd_kcontrol_new onyx_spdif_mask = { + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK), + .info = onyx_spdif_info, + .get = onyx_spdif_mask_get, +}; + +static int onyx_spdif_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct onyx *onyx = snd_kcontrol_chip(kcontrol); + u8 v; + + mutex_lock(&onyx->mutex); + onyx_read_register(onyx, ONYX_REG_DIG_INFO1, &v); + ucontrol->value.iec958.status[0] = v & 0x3e; + + onyx_read_register(onyx, ONYX_REG_DIG_INFO2, &v); + ucontrol->value.iec958.status[1] = v; + + onyx_read_register(onyx, ONYX_REG_DIG_INFO3, &v); + ucontrol->value.iec958.status[3] = v & 0x3f; + + onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v); + ucontrol->value.iec958.status[4] = v & 0x0f; + mutex_unlock(&onyx->mutex); + + return 0; +} + +static int onyx_spdif_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct onyx *onyx = snd_kcontrol_chip(kcontrol); + u8 v; + + mutex_lock(&onyx->mutex); + onyx_read_register(onyx, ONYX_REG_DIG_INFO1, &v); + v = (v & ~0x3e) | (ucontrol->value.iec958.status[0] & 0x3e); + onyx_write_register(onyx, ONYX_REG_DIG_INFO1, v); + + v = ucontrol->value.iec958.status[1]; + onyx_write_register(onyx, ONYX_REG_DIG_INFO2, v); + + onyx_read_register(onyx, ONYX_REG_DIG_INFO3, &v); + v = (v & ~0x3f) | (ucontrol->value.iec958.status[3] & 0x3f); + onyx_write_register(onyx, ONYX_REG_DIG_INFO3, v); + + onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v); + v = (v & ~0x0f) | (ucontrol->value.iec958.status[4] & 0x0f); + onyx_write_register(onyx, ONYX_REG_DIG_INFO4, v); + mutex_unlock(&onyx->mutex); + + return 1; +} + +static struct snd_kcontrol_new onyx_spdif_ctrl = { + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), + .info = onyx_spdif_info, + .get = onyx_spdif_get, + .put = onyx_spdif_put, +}; + +/* our registers */ + +static u8 register_map[] = { + ONYX_REG_DAC_ATTEN_LEFT, + ONYX_REG_DAC_ATTEN_RIGHT, + ONYX_REG_CONTROL, + ONYX_REG_DAC_CONTROL, + ONYX_REG_DAC_DEEMPH, + ONYX_REG_DAC_FILTER, + ONYX_REG_DAC_OUTPHASE, + ONYX_REG_ADC_CONTROL, + ONYX_REG_ADC_HPF_BYPASS, + ONYX_REG_DIG_INFO1, + ONYX_REG_DIG_INFO2, + ONYX_REG_DIG_INFO3, + ONYX_REG_DIG_INFO4 +}; + +static u8 initial_values[ARRAY_SIZE(register_map)] = { + 0x80, 0x80, /* muted */ + ONYX_MRST | ONYX_SRST, /* but handled specially! */ + ONYX_MUTE_LEFT | ONYX_MUTE_RIGHT, + 0, /* no deemphasis */ + ONYX_DAC_FILTER_ALWAYS, + ONYX_OUTPHASE_INVERTED, + (-1 /*dB*/ + 8) & 0xF, /* line in selected, -1 dB gain*/ + ONYX_ADC_HPF_ALWAYS, + (1<<2), /* pcm audio */ + 2, /* category: pcm coder */ + 0, /* sampling frequency 44.1 kHz, clock accuracy level II */ + 1 /* 24 bit depth */ +}; + +/* reset registers of chip, either to initial or to previous values */ +static int onyx_register_init(struct onyx *onyx) +{ + int i; + u8 val; + u8 regs[sizeof(initial_values)]; + + if (!onyx->initialised) { + memcpy(regs, initial_values, sizeof(initial_values)); + if (onyx_read_register(onyx, ONYX_REG_CONTROL, &val)) + return -1; + val &= ~ONYX_SILICONVERSION; + val |= initial_values[3]; + regs[3] = val; + } else { + for (i=0; icache[register_map[i]-FIRSTREGISTER]; + } + + for (i=0; iinitialised = 1; + return 0; +} + +static struct transfer_info onyx_transfers[] = { + /* this is first so we can skip it if no input is present... + * No hardware exists with that, but it's here as an example + * of what to do :) */ + { + /* analog input */ + .formats = SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_S16_BE | + SNDRV_PCM_FMTBIT_S24_BE, + .rates = SNDRV_PCM_RATE_8000_96000, + .transfer_in = 1, + .must_be_clock_source = 0, + .tag = 0, + }, + { + /* if analog and digital are currently off, anything should go, + * so this entry describes everything we can do... */ + .formats = SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_S16_BE | + SNDRV_PCM_FMTBIT_S24_BE +#ifdef SNDRV_PCM_FMTBIT_COMPRESSED_16BE + | SNDRV_PCM_FMTBIT_COMPRESSED_16BE +#endif + , + .rates = SNDRV_PCM_RATE_8000_96000, + .tag = 0, + }, + { + /* analog output */ + .formats = SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_S16_BE | + SNDRV_PCM_FMTBIT_S24_BE, + .rates = SNDRV_PCM_RATE_8000_96000, + .transfer_in = 0, + .must_be_clock_source = 0, + .tag = 1, + }, + { + /* digital pcm output, also possible for analog out */ + .formats = SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_S16_BE | + SNDRV_PCM_FMTBIT_S24_BE, + .rates = SNDRV_PCM_RATE_32000 | + SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000, + .transfer_in = 0, + .must_be_clock_source = 0, + .tag = 2, + }, +#ifdef SNDRV_PCM_FMTBIT_COMPRESSED_16BE +Once alsa gets supports for this kind of thing we can add it... + { + /* digital compressed output */ + .formats = SNDRV_PCM_FMTBIT_COMPRESSED_16BE, + .rates = SNDRV_PCM_RATE_32000 | + SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000, + .tag = 2, + }, +#endif + {} +}; + +static int onyx_usable(struct codec_info_item *cii, + struct transfer_info *ti, + struct transfer_info *out) +{ + u8 v; + struct onyx *onyx = cii->codec_data; + int spdif_enabled, analog_enabled; + + mutex_lock(&onyx->mutex); + onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v); + spdif_enabled = !!(v & ONYX_SPDIF_ENABLE); + onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v); + analog_enabled = + (v & (ONYX_MUTE_RIGHT|ONYX_MUTE_LEFT)) + != (ONYX_MUTE_RIGHT|ONYX_MUTE_LEFT); + mutex_unlock(&onyx->mutex); + + switch (ti->tag) { + case 0: return 1; + case 1: return analog_enabled; + case 2: return spdif_enabled; + } + return 1; +} + +static int onyx_prepare(struct codec_info_item *cii, + struct bus_info *bi, + struct snd_pcm_substream *substream) +{ + u8 v; + struct onyx *onyx = cii->codec_data; + int err = -EBUSY; + + mutex_lock(&onyx->mutex); + +#ifdef SNDRV_PCM_FMTBIT_COMPRESSED_16BE + if (substream->runtime->format == SNDRV_PCM_FMTBIT_COMPRESSED_16BE) { + /* mute and lock analog output */ + onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v); + if (onyx_write_register(onyx + ONYX_REG_DAC_CONTROL, + v | ONYX_MUTE_RIGHT | ONYX_MUTE_LEFT)) + goto out_unlock; + onyx->analog_locked = 1; + err = 0; + goto out_unlock; + } +#endif + switch (substream->runtime->rate) { + case 32000: + case 44100: + case 48000: + /* these rates are ok for all outputs */ + /* FIXME: program spdif channel control bits here so that + * userspace doesn't have to if it only plays pcm! */ + err = 0; + goto out_unlock; + default: + /* got some rate that the digital output can't do, + * so disable and lock it */ + onyx_read_register(cii->codec_data, ONYX_REG_DIG_INFO4, &v); + if (onyx_write_register(onyx, + ONYX_REG_DIG_INFO4, + v & ~ONYX_SPDIF_ENABLE)) + goto out_unlock; + onyx->spdif_locked = 1; + err = 0; + goto out_unlock; + } + + out_unlock: + mutex_unlock(&onyx->mutex); + + return err; +} + +static int onyx_open(struct codec_info_item *cii, + struct snd_pcm_substream *substream) +{ + struct onyx *onyx = cii->codec_data; + + mutex_lock(&onyx->mutex); + onyx->open_count++; + mutex_unlock(&onyx->mutex); + + return 0; +} + +static int onyx_close(struct codec_info_item *cii, + struct snd_pcm_substream *substream) +{ + struct onyx *onyx = cii->codec_data; + + mutex_lock(&onyx->mutex); + onyx->open_count--; + if (!onyx->open_count) + onyx->spdif_locked = onyx->analog_locked = 0; + mutex_unlock(&onyx->mutex); + + return 0; +} + +static int onyx_switch_clock(struct codec_info_item *cii, + enum clock_switch what) +{ + struct onyx *onyx = cii->codec_data; + + mutex_lock(&onyx->mutex); + /* this *MUST* be more elaborate later... */ + switch (what) { + case CLOCK_SWITCH_PREPARE_SLAVE: + onyx->codec.gpio->methods->all_amps_off(onyx->codec.gpio); + break; + case CLOCK_SWITCH_SLAVE: + onyx->codec.gpio->methods->all_amps_restore(onyx->codec.gpio); + break; + default: /* silence warning */ + break; + } + mutex_unlock(&onyx->mutex); + + return 0; +} + +#ifdef CONFIG_PM + +static int onyx_suspend(struct codec_info_item *cii, pm_message_t state) +{ + struct onyx *onyx = cii->codec_data; + u8 v; + int err = -ENXIO; + + mutex_lock(&onyx->mutex); + if (onyx_read_register(onyx, ONYX_REG_CONTROL, &v)) + goto out_unlock; + onyx_write_register(onyx, ONYX_REG_CONTROL, v | ONYX_ADPSV | ONYX_DAPSV); + /* Apple does a sleep here but the datasheet says to do it on resume */ + err = 0; + out_unlock: + mutex_unlock(&onyx->mutex); + + return err; +} + +static int onyx_resume(struct codec_info_item *cii) +{ + struct onyx *onyx = cii->codec_data; + u8 v; + int err = -ENXIO; + + mutex_lock(&onyx->mutex); + /* take codec out of suspend */ + if (onyx_read_register(onyx, ONYX_REG_CONTROL, &v)) + goto out_unlock; + onyx_write_register(onyx, ONYX_REG_CONTROL, v & ~(ONYX_ADPSV | ONYX_DAPSV)); + /* FIXME: should divide by sample rate, but 8k is the lowest we go */ + msleep(2205000/8000); + /* reset all values */ + onyx_register_init(onyx); + err = 0; + out_unlock: + mutex_unlock(&onyx->mutex); + + return err; +} + +#endif /* CONFIG_PM */ + +static struct codec_info onyx_codec_info = { + .transfers = onyx_transfers, + .sysclock_factor = 256, + .bus_factor = 64, + .owner = THIS_MODULE, + .usable = onyx_usable, + .prepare = onyx_prepare, + .open = onyx_open, + .close = onyx_close, + .switch_clock = onyx_switch_clock, +#ifdef CONFIG_PM + .suspend = onyx_suspend, + .resume = onyx_resume, +#endif +}; + +static int onyx_init_codec(struct aoa_codec *codec) +{ + struct onyx *onyx = codec_to_onyx(codec); + struct snd_kcontrol *ctl; + struct codec_info *ci = &onyx_codec_info; + u8 v; + int err; + + if (!onyx->codec.gpio || !onyx->codec.gpio->methods) { + printk(KERN_ERR PFX "gpios not assigned!!\n"); + return -EINVAL; + } + + onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0); + msleep(1); + onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 1); + msleep(1); + onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0); + msleep(1); + + if (onyx_register_init(onyx)) { + printk(KERN_ERR PFX "failed to initialise onyx registers\n"); + return -ENODEV; + } + + if (aoa_snd_device_new(SNDRV_DEV_LOWLEVEL, onyx, &ops)) { + printk(KERN_ERR PFX "failed to create onyx snd device!\n"); + return -ENODEV; + } + + /* nothing connected? what a joke! */ + if ((onyx->codec.connected & 0xF) == 0) + return -ENOTCONN; + + /* if no inputs are present... */ + if ((onyx->codec.connected & 0xC) == 0) { + if (!onyx->codec_info) + onyx->codec_info = kmalloc(sizeof(struct codec_info), GFP_KERNEL); + if (!onyx->codec_info) + return -ENOMEM; + ci = onyx->codec_info; + *ci = onyx_codec_info; + ci->transfers++; + } + + /* if no outputs are present... */ + if ((onyx->codec.connected & 3) == 0) { + if (!onyx->codec_info) + onyx->codec_info = kmalloc(sizeof(struct codec_info), GFP_KERNEL); + if (!onyx->codec_info) + return -ENOMEM; + ci = onyx->codec_info; + /* this is fine as there have to be inputs + * if we end up in this part of the code */ + *ci = onyx_codec_info; + ci->transfers[1].formats = 0; + } + + if (onyx->codec.soundbus_dev->attach_codec(onyx->codec.soundbus_dev, + aoa_get_card(), + ci, onyx)) { + printk(KERN_ERR PFX "error creating onyx pcm\n"); + return -ENODEV; + } +#define ADDCTL(n) \ + do { \ + ctl = snd_ctl_new1(&n, onyx); \ + if (ctl) { \ + ctl->id.device = \ + onyx->codec.soundbus_dev->pcm->device; \ + err = aoa_snd_ctl_add(ctl); \ + if (err) \ + goto error; \ + } \ + } while (0) + + if (onyx->codec.soundbus_dev->pcm) { + /* give the user appropriate controls + * depending on what inputs are connected */ + if ((onyx->codec.connected & 0xC) == 0xC) + ADDCTL(capture_source_control); + else if (onyx->codec.connected & 4) + onyx_set_capture_source(onyx, 0); + else + onyx_set_capture_source(onyx, 1); + if (onyx->codec.connected & 0xC) + ADDCTL(inputgain_control); + + /* depending on what output is connected, + * give the user appropriate controls */ + if (onyx->codec.connected & 1) { + ADDCTL(volume_control); + ADDCTL(mute_control); + ADDCTL(ovr1_control); + ADDCTL(flt0_control); + ADDCTL(hpf_control); + ADDCTL(dm12_control); + /* spdif control defaults to off */ + } + if (onyx->codec.connected & 2) { + ADDCTL(onyx_spdif_mask); + ADDCTL(onyx_spdif_ctrl); + } + if ((onyx->codec.connected & 3) == 3) + ADDCTL(spdif_control); + /* if only S/PDIF is connected, enable it unconditionally */ + if ((onyx->codec.connected & 3) == 2) { + onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v); + v |= ONYX_SPDIF_ENABLE; + onyx_write_register(onyx, ONYX_REG_DIG_INFO4, v); + } + } +#undef ADDCTL + printk(KERN_INFO PFX "attached to onyx codec via i2c\n"); + + return 0; + error: + onyx->codec.soundbus_dev->detach_codec(onyx->codec.soundbus_dev, onyx); + snd_device_free(aoa_get_card(), onyx); + return err; +} + +static void onyx_exit_codec(struct aoa_codec *codec) +{ + struct onyx *onyx = codec_to_onyx(codec); + + if (!onyx->codec.soundbus_dev) { + printk(KERN_ERR PFX "onyx_exit_codec called without soundbus_dev!\n"); + return; + } + onyx->codec.soundbus_dev->detach_codec(onyx->codec.soundbus_dev, onyx); +} + +static struct i2c_driver onyx_driver; + +static int onyx_create(struct i2c_adapter *adapter, + struct device_node *node, + int addr) +{ + struct onyx *onyx; + u8 dummy; + + onyx = kzalloc(sizeof(struct onyx), GFP_KERNEL); + + if (!onyx) + return -ENOMEM; + + mutex_init(&onyx->mutex); + onyx->i2c.driver = &onyx_driver; + onyx->i2c.adapter = adapter; + onyx->i2c.addr = addr & 0x7f; + strlcpy(onyx->i2c.name, "onyx audio codec", I2C_NAME_SIZE-1); + + if (i2c_attach_client(&onyx->i2c)) { + printk(KERN_ERR PFX "failed to attach to i2c\n"); + goto fail; + } + + /* we try to read from register ONYX_REG_CONTROL + * to check if the codec is present */ + if (onyx_read_register(onyx, ONYX_REG_CONTROL, &dummy) != 0) { + i2c_detach_client(&onyx->i2c); + printk(KERN_ERR PFX "failed to read control register\n"); + goto fail; + } + + strlcpy(onyx->codec.name, "onyx", MAX_CODEC_NAME_LEN-1); + onyx->codec.owner = THIS_MODULE; + onyx->codec.init = onyx_init_codec; + onyx->codec.exit = onyx_exit_codec; + onyx->codec.node = of_node_get(node); + + if (aoa_codec_register(&onyx->codec)) { + i2c_detach_client(&onyx->i2c); + goto fail; + } + printk(KERN_DEBUG PFX "created and attached onyx instance\n"); + return 0; + fail: + kfree(onyx); + return -EINVAL; +} + +static int onyx_i2c_attach(struct i2c_adapter *adapter) +{ + struct device_node *busnode, *dev = NULL; + struct pmac_i2c_bus *bus; + + bus = pmac_i2c_adapter_to_bus(adapter); + if (bus == NULL) + return -ENODEV; + busnode = pmac_i2c_get_bus_node(bus); + + while ((dev = of_get_next_child(busnode, dev)) != NULL) { + if (device_is_compatible(dev, "pcm3052")) { + u32 *addr; + printk(KERN_DEBUG PFX "found pcm3052\n"); + addr = (u32 *) get_property(dev, "reg", NULL); + if (!addr) + return -ENODEV; + return onyx_create(adapter, dev, (*addr)>>1); + } + } + + /* if that didn't work, try desperate mode for older + * machines that have stuff missing from the device tree */ + + if (!device_is_compatible(busnode, "k2-i2c")) + return -ENODEV; + + printk(KERN_DEBUG PFX "found k2-i2c, checking if onyx chip is on it\n"); + /* probe both possible addresses for the onyx chip */ + if (onyx_create(adapter, NULL, 0x46) == 0) + return 0; + return onyx_create(adapter, NULL, 0x47); +} + +static int onyx_i2c_detach(struct i2c_client *client) +{ + struct onyx *onyx = container_of(client, struct onyx, i2c); + int err; + + if ((err = i2c_detach_client(client))) + return err; + aoa_codec_unregister(&onyx->codec); + of_node_put(onyx->codec.node); + if (onyx->codec_info) + kfree(onyx->codec_info); + kfree(onyx); + return 0; +} + +static struct i2c_driver onyx_driver = { + .driver = { + .name = "aoa_codec_onyx", + .owner = THIS_MODULE, + }, + .attach_adapter = onyx_i2c_attach, + .detach_client = onyx_i2c_detach, +}; + +static int __init onyx_init(void) +{ + return i2c_add_driver(&onyx_driver); +} + +static void __exit onyx_exit(void) +{ + i2c_del_driver(&onyx_driver); +} + +module_init(onyx_init); +module_exit(onyx_exit); diff --git a/sound/aoa/codecs/snd-aoa-codec-onyx.h b/sound/aoa/codecs/snd-aoa-codec-onyx.h new file mode 100644 index 00000000000..aeedda77369 --- /dev/null +++ b/sound/aoa/codecs/snd-aoa-codec-onyx.h @@ -0,0 +1,76 @@ +/* + * Apple Onboard Audio driver for Onyx codec (header) + * + * Copyright 2006 Johannes Berg + * + * GPL v2, can be found in COPYING. + */ +#ifndef __SND_AOA_CODEC_ONYX_H +#define __SND_AOA_CODEC_ONYX_H +#include +#include +#include +#include +#include + +/* PCM3052 register definitions */ + +/* the attenuation registers take values from + * -1 (0dB) to -127 (-63.0 dB) or others (muted) */ +#define ONYX_REG_DAC_ATTEN_LEFT 65 +#define FIRSTREGISTER ONYX_REG_DAC_ATTEN_LEFT +#define ONYX_REG_DAC_ATTEN_RIGHT 66 + +#define ONYX_REG_CONTROL 67 +# define ONYX_MRST (1<<7) +# define ONYX_SRST (1<<6) +# define ONYX_ADPSV (1<<5) +# define ONYX_DAPSV (1<<4) +# define ONYX_SILICONVERSION (1<<0) +/* all others reserved */ + +#define ONYX_REG_DAC_CONTROL 68 +# define ONYX_OVR1 (1<<6) +# define ONYX_MUTE_RIGHT (1<<1) +# define ONYX_MUTE_LEFT (1<<0) + +#define ONYX_REG_DAC_DEEMPH 69 +# define ONYX_DIGDEEMPH_SHIFT 5 +# define ONYX_DIGDEEMPH_MASK (3< +#include +int main() { + int dB2; + printf("/" "* This file is only included exactly once!\n"); + printf(" *\n"); + printf(" * If they'd only tell us that generating this table was\n"); + printf(" * as easy as calculating\n"); + printf(" * hwvalue = 1048576.0*exp(0.057564628*dB*2)\n"); + printf(" * :) *" "/\n"); + printf("static int tas_gaintable[] = {\n"); + printf(" 0x000000, /" "* -infinity dB *" "/\n"); + for (dB2=-140;dB2<=36;dB2++) + printf(" 0x%.6x, /" "* %-02.1f dB *" "/\n", (int)(1048576.0*exp(0.057564628*dB2)), dB2/2.0); + printf("};\n\n"); +} + +*/ + +/* This file is only included exactly once! + * + * If they'd only tell us that generating this table was + * as easy as calculating + * hwvalue = 1048576.0*exp(0.057564628*dB*2) + * :) */ +static int tas_gaintable[] = { + 0x000000, /* -infinity dB */ + 0x00014b, /* -70.0 dB */ + 0x00015f, /* -69.5 dB */ + 0x000174, /* -69.0 dB */ + 0x00018a, /* -68.5 dB */ + 0x0001a1, /* -68.0 dB */ + 0x0001ba, /* -67.5 dB */ + 0x0001d4, /* -67.0 dB */ + 0x0001f0, /* -66.5 dB */ + 0x00020d, /* -66.0 dB */ + 0x00022c, /* -65.5 dB */ + 0x00024d, /* -65.0 dB */ + 0x000270, /* -64.5 dB */ + 0x000295, /* -64.0 dB */ + 0x0002bc, /* -63.5 dB */ + 0x0002e6, /* -63.0 dB */ + 0x000312, /* -62.5 dB */ + 0x000340, /* -62.0 dB */ + 0x000372, /* -61.5 dB */ + 0x0003a6, /* -61.0 dB */ + 0x0003dd, /* -60.5 dB */ + 0x000418, /* -60.0 dB */ + 0x000456, /* -59.5 dB */ + 0x000498, /* -59.0 dB */ + 0x0004de, /* -58.5 dB */ + 0x000528, /* -58.0 dB */ + 0x000576, /* -57.5 dB */ + 0x0005c9, /* -57.0 dB */ + 0x000620, /* -56.5 dB */ + 0x00067d, /* -56.0 dB */ + 0x0006e0, /* -55.5 dB */ + 0x000748, /* -55.0 dB */ + 0x0007b7, /* -54.5 dB */ + 0x00082c, /* -54.0 dB */ + 0x0008a8, /* -53.5 dB */ + 0x00092b, /* -53.0 dB */ + 0x0009b6, /* -52.5 dB */ + 0x000a49, /* -52.0 dB */ + 0x000ae5, /* -51.5 dB */ + 0x000b8b, /* -51.0 dB */ + 0x000c3a, /* -50.5 dB */ + 0x000cf3, /* -50.0 dB */ + 0x000db8, /* -49.5 dB */ + 0x000e88, /* -49.0 dB */ + 0x000f64, /* -48.5 dB */ + 0x00104e, /* -48.0 dB */ + 0x001145, /* -47.5 dB */ + 0x00124b, /* -47.0 dB */ + 0x001361, /* -46.5 dB */ + 0x001487, /* -46.0 dB */ + 0x0015be, /* -45.5 dB */ + 0x001708, /* -45.0 dB */ + 0x001865, /* -44.5 dB */ + 0x0019d8, /* -44.0 dB */ + 0x001b60, /* -43.5 dB */ + 0x001cff, /* -43.0 dB */ + 0x001eb7, /* -42.5 dB */ + 0x002089, /* -42.0 dB */ + 0x002276, /* -41.5 dB */ + 0x002481, /* -41.0 dB */ + 0x0026ab, /* -40.5 dB */ + 0x0028f5, /* -40.0 dB */ + 0x002b63, /* -39.5 dB */ + 0x002df5, /* -39.0 dB */ + 0x0030ae, /* -38.5 dB */ + 0x003390, /* -38.0 dB */ + 0x00369e, /* -37.5 dB */ + 0x0039db, /* -37.0 dB */ + 0x003d49, /* -36.5 dB */ + 0x0040ea, /* -36.0 dB */ + 0x0044c3, /* -35.5 dB */ + 0x0048d6, /* -35.0 dB */ + 0x004d27, /* -34.5 dB */ + 0x0051b9, /* -34.0 dB */ + 0x005691, /* -33.5 dB */ + 0x005bb2, /* -33.0 dB */ + 0x006121, /* -32.5 dB */ + 0x0066e3, /* -32.0 dB */ + 0x006cfb, /* -31.5 dB */ + 0x007370, /* -31.0 dB */ + 0x007a48, /* -30.5 dB */ + 0x008186, /* -30.0 dB */ + 0x008933, /* -29.5 dB */ + 0x009154, /* -29.0 dB */ + 0x0099f1, /* -28.5 dB */ + 0x00a310, /* -28.0 dB */ + 0x00acba, /* -27.5 dB */ + 0x00b6f6, /* -27.0 dB */ + 0x00c1cd, /* -26.5 dB */ + 0x00cd49, /* -26.0 dB */ + 0x00d973, /* -25.5 dB */ + 0x00e655, /* -25.0 dB */ + 0x00f3fb, /* -24.5 dB */ + 0x010270, /* -24.0 dB */ + 0x0111c0, /* -23.5 dB */ + 0x0121f9, /* -23.0 dB */ + 0x013328, /* -22.5 dB */ + 0x01455b, /* -22.0 dB */ + 0x0158a2, /* -21.5 dB */ + 0x016d0e, /* -21.0 dB */ + 0x0182af, /* -20.5 dB */ + 0x019999, /* -20.0 dB */ + 0x01b1de, /* -19.5 dB */ + 0x01cb94, /* -19.0 dB */ + 0x01e6cf, /* -18.5 dB */ + 0x0203a7, /* -18.0 dB */ + 0x022235, /* -17.5 dB */ + 0x024293, /* -17.0 dB */ + 0x0264db, /* -16.5 dB */ + 0x02892c, /* -16.0 dB */ + 0x02afa3, /* -15.5 dB */ + 0x02d862, /* -15.0 dB */ + 0x03038a, /* -14.5 dB */ + 0x033142, /* -14.0 dB */ + 0x0361af, /* -13.5 dB */ + 0x0394fa, /* -13.0 dB */ + 0x03cb50, /* -12.5 dB */ + 0x0404de, /* -12.0 dB */ + 0x0441d5, /* -11.5 dB */ + 0x048268, /* -11.0 dB */ + 0x04c6d0, /* -10.5 dB */ + 0x050f44, /* -10.0 dB */ + 0x055c04, /* -9.5 dB */ + 0x05ad50, /* -9.0 dB */ + 0x06036e, /* -8.5 dB */ + 0x065ea5, /* -8.0 dB */ + 0x06bf44, /* -7.5 dB */ + 0x07259d, /* -7.0 dB */ + 0x079207, /* -6.5 dB */ + 0x0804dc, /* -6.0 dB */ + 0x087e80, /* -5.5 dB */ + 0x08ff59, /* -5.0 dB */ + 0x0987d5, /* -4.5 dB */ + 0x0a1866, /* -4.0 dB */ + 0x0ab189, /* -3.5 dB */ + 0x0b53be, /* -3.0 dB */ + 0x0bff91, /* -2.5 dB */ + 0x0cb591, /* -2.0 dB */ + 0x0d765a, /* -1.5 dB */ + 0x0e4290, /* -1.0 dB */ + 0x0f1adf, /* -0.5 dB */ + 0x100000, /* 0.0 dB */ + 0x10f2b4, /* 0.5 dB */ + 0x11f3c9, /* 1.0 dB */ + 0x13041a, /* 1.5 dB */ + 0x14248e, /* 2.0 dB */ + 0x15561a, /* 2.5 dB */ + 0x1699c0, /* 3.0 dB */ + 0x17f094, /* 3.5 dB */ + 0x195bb8, /* 4.0 dB */ + 0x1adc61, /* 4.5 dB */ + 0x1c73d5, /* 5.0 dB */ + 0x1e236d, /* 5.5 dB */ + 0x1fec98, /* 6.0 dB */ + 0x21d0d9, /* 6.5 dB */ + 0x23d1cd, /* 7.0 dB */ + 0x25f125, /* 7.5 dB */ + 0x2830af, /* 8.0 dB */ + 0x2a9254, /* 8.5 dB */ + 0x2d1818, /* 9.0 dB */ + 0x2fc420, /* 9.5 dB */ + 0x3298b0, /* 10.0 dB */ + 0x35982f, /* 10.5 dB */ + 0x38c528, /* 11.0 dB */ + 0x3c224c, /* 11.5 dB */ + 0x3fb278, /* 12.0 dB */ + 0x4378b0, /* 12.5 dB */ + 0x477829, /* 13.0 dB */ + 0x4bb446, /* 13.5 dB */ + 0x5030a1, /* 14.0 dB */ + 0x54f106, /* 14.5 dB */ + 0x59f980, /* 15.0 dB */ + 0x5f4e52, /* 15.5 dB */ + 0x64f403, /* 16.0 dB */ + 0x6aef5e, /* 16.5 dB */ + 0x714575, /* 17.0 dB */ + 0x77fbaa, /* 17.5 dB */ + 0x7f17af, /* 18.0 dB */ +}; + diff --git a/sound/aoa/codecs/snd-aoa-codec-tas.c b/sound/aoa/codecs/snd-aoa-codec-tas.c new file mode 100644 index 00000000000..2e39ff6ee34 --- /dev/null +++ b/sound/aoa/codecs/snd-aoa-codec-tas.c @@ -0,0 +1,654 @@ +/* + * Apple Onboard Audio driver for tas codec + * + * Copyright 2006 Johannes Berg + * + * GPL v2, can be found in COPYING. + * + * Open questions: + * - How to distinguish between 3004 and versions? + * + * FIXMEs: + * - This codec driver doesn't honour the 'connected' + * property of the aoa_codec struct, hence if + * it is used in machines where not everything is + * connected it will display wrong mixer elements. + * - Driver assumes that the microphone is always + * monaureal and connected to the right channel of + * the input. This should also be a codec-dependent + * flag, maybe the codec should have 3 different + * bits for the three different possibilities how + * it can be hooked up... + * But as long as I don't see any hardware hooked + * up that way... + * - As Apple notes in their code, the tas3004 seems + * to delay the right channel by one sample. You can + * see this when for example recording stereo in + * audacity, or recording the tas output via cable + * on another machine (use a sinus generator or so). + * I tried programming the BiQuads but couldn't + * make the delay work, maybe someone can read the + * datasheet and fix it. The relevant Apple comment + * is in AppleTAS3004Audio.cpp lines 1637 ff. Note + * that their comment describing how they program + * the filters sucks... + * + * Other things: + * - this should actually register *two* aoa_codec + * structs since it has two inputs. Then it must + * use the prepare callback to forbid running the + * secondary output on a different clock. + * Also, whatever bus knows how to do this must + * provide two soundbus_dev devices and the fabric + * must be able to link them correctly. + * + * I don't even know if Apple ever uses the second + * port on the tas3004 though, I don't think their + * i2s controllers can even do it. OTOH, they all + * derive the clocks from common clocks, so it + * might just be possible. The framework allows the + * codec to refine the transfer_info items in the + * usable callback, so we can simply remove the + * rates the second instance is not using when it + * actually is in use. + * Maybe we'll need to make the sound busses have + * a 'clock group id' value so the codec can + * determine if the two outputs can be driven at + * the same time. But that is likely overkill, up + * to the fabric to not link them up incorrectly, + * and up to the hardware designer to not wire + * them up in some weird unusable way. + */ +#include +#include +#include +#include +#include +#include +#include +MODULE_AUTHOR("Johannes Berg "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("tas codec driver for snd-aoa"); + +#include "snd-aoa-codec-tas.h" +#include "snd-aoa-codec-tas-gain-table.h" +#include "../aoa.h" +#include "../soundbus/soundbus.h" + + +#define PFX "snd-aoa-codec-tas: " + +struct tas { + struct aoa_codec codec; + struct i2c_client i2c; + u32 muted_l:1, muted_r:1, + controls_created:1; + u8 cached_volume_l, cached_volume_r; + u8 mixer_l[3], mixer_r[3]; + u8 acr; +}; + +static struct tas *codec_to_tas(struct aoa_codec *codec) +{ + return container_of(codec, struct tas, codec); +} + +static inline int tas_write_reg(struct tas *tas, u8 reg, u8 len, u8 *data) +{ + if (len == 1) + return i2c_smbus_write_byte_data(&tas->i2c, reg, *data); + else + return i2c_smbus_write_i2c_block_data(&tas->i2c, reg, len, data); +} + +static void tas_set_volume(struct tas *tas) +{ + u8 block[6]; + int tmp; + u8 left, right; + + left = tas->cached_volume_l; + right = tas->cached_volume_r; + + if (left > 177) left = 177; + if (right > 177) right = 177; + + if (tas->muted_l) left = 0; + if (tas->muted_r) right = 0; + + /* analysing the volume and mixer tables shows + * that they are similar enough when we shift + * the mixer table down by 4 bits. The error + * is miniscule, in just one item the error + * is 1, at a value of 0x07f17b (mixer table + * value is 0x07f17a) */ + tmp = tas_gaintable[left]; + block[0] = tmp>>20; + block[1] = tmp>>12; + block[2] = tmp>>4; + tmp = tas_gaintable[right]; + block[3] = tmp>>20; + block[4] = tmp>>12; + block[5] = tmp>>4; + tas_write_reg(tas, TAS_REG_VOL, 6, block); +} + +static void tas_set_mixer(struct tas *tas) +{ + u8 block[9]; + int tmp, i; + u8 val; + + for (i=0;i<3;i++) { + val = tas->mixer_l[i]; + if (val > 177) val = 177; + tmp = tas_gaintable[val]; + block[3*i+0] = tmp>>16; + block[3*i+1] = tmp>>8; + block[3*i+2] = tmp; + } + tas_write_reg(tas, TAS_REG_LMIX, 9, block); + + for (i=0;i<3;i++) { + val = tas->mixer_r[i]; + if (val > 177) val = 177; + tmp = tas_gaintable[val]; + block[3*i+0] = tmp>>16; + block[3*i+1] = tmp>>8; + block[3*i+2] = tmp; + } + tas_write_reg(tas, TAS_REG_RMIX, 9, block); +} + +/* alsa stuff */ + +static int tas_dev_register(struct snd_device *dev) +{ + return 0; +} + +static struct snd_device_ops ops = { + .dev_register = tas_dev_register, +}; + +static int tas_snd_vol_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 2; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 177; + return 0; +} + +static int tas_snd_vol_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct tas *tas = snd_kcontrol_chip(kcontrol); + + ucontrol->value.integer.value[0] = tas->cached_volume_l; + ucontrol->value.integer.value[1] = tas->cached_volume_r; + return 0; +} + +static int tas_snd_vol_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct tas *tas = snd_kcontrol_chip(kcontrol); + + if (tas->cached_volume_l == ucontrol->value.integer.value[0] + && tas->cached_volume_r == ucontrol->value.integer.value[1]) + return 0; + + tas->cached_volume_l = ucontrol->value.integer.value[0]; + tas->cached_volume_r = ucontrol->value.integer.value[1]; + tas_set_volume(tas); + return 1; +} + +static struct snd_kcontrol_new volume_control = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Master Playback Volume", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .info = tas_snd_vol_info, + .get = tas_snd_vol_get, + .put = tas_snd_vol_put, +}; + +static int tas_snd_mute_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + uinfo->count = 2; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + return 0; +} + +static int tas_snd_mute_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct tas *tas = snd_kcontrol_chip(kcontrol); + + ucontrol->value.integer.value[0] = !tas->muted_l; + ucontrol->value.integer.value[1] = !tas->muted_r; + return 0; +} + +static int tas_snd_mute_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct tas *tas = snd_kcontrol_chip(kcontrol); + + if (tas->muted_l == !ucontrol->value.integer.value[0] + && tas->muted_r == !ucontrol->value.integer.value[1]) + return 0; + + tas->muted_l = !ucontrol->value.integer.value[0]; + tas->muted_r = !ucontrol->value.integer.value[1]; + tas_set_volume(tas); + return 1; +} + +static struct snd_kcontrol_new mute_control = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Master Playback Switch", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .info = tas_snd_mute_info, + .get = tas_snd_mute_get, + .put = tas_snd_mute_put, +}; + +static int tas_snd_mixer_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 2; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 177; + return 0; +} + +static int tas_snd_mixer_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct tas *tas = snd_kcontrol_chip(kcontrol); + int idx = kcontrol->private_value; + + ucontrol->value.integer.value[0] = tas->mixer_l[idx]; + ucontrol->value.integer.value[1] = tas->mixer_r[idx]; + + return 0; +} + +static int tas_snd_mixer_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct tas *tas = snd_kcontrol_chip(kcontrol); + int idx = kcontrol->private_value; + + if (tas->mixer_l[idx] == ucontrol->value.integer.value[0] + && tas->mixer_r[idx] == ucontrol->value.integer.value[1]) + return 0; + + tas->mixer_l[idx] = ucontrol->value.integer.value[0]; + tas->mixer_r[idx] = ucontrol->value.integer.value[1]; + + tas_set_mixer(tas); + return 1; +} + +#define MIXER_CONTROL(n,descr,idx) \ +static struct snd_kcontrol_new n##_control = { \ + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ + .name = descr " Playback Volume", \ + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ + .info = tas_snd_mixer_info, \ + .get = tas_snd_mixer_get, \ + .put = tas_snd_mixer_put, \ + .private_value = idx, \ +} + +MIXER_CONTROL(pcm1, "PCM1", 0); +MIXER_CONTROL(monitor, "Monitor", 2); + +static int tas_snd_capture_source_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + static char *texts[] = { "Line-In", "Microphone" }; + + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; + uinfo->count = 1; + uinfo->value.enumerated.items = 2; + if (uinfo->value.enumerated.item > 1) + uinfo->value.enumerated.item = 1; + strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); + return 0; +} + +static int tas_snd_capture_source_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct tas *tas = snd_kcontrol_chip(kcontrol); + + ucontrol->value.enumerated.item[0] = !!(tas->acr & TAS_ACR_INPUT_B); + return 0; +} + +static int tas_snd_capture_source_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct tas *tas = snd_kcontrol_chip(kcontrol); + int oldacr = tas->acr; + + tas->acr &= ~TAS_ACR_INPUT_B; + if (ucontrol->value.enumerated.item[0]) + tas->acr |= TAS_ACR_INPUT_B; + if (oldacr == tas->acr) + return 0; + tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr); + return 1; +} + +static struct snd_kcontrol_new capture_source_control = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + /* If we name this 'Input Source', it properly shows up in + * alsamixer as a selection, * but it's shown under the + * 'Playback' category. + * If I name it 'Capture Source', it shows up in strange + * ways (two bools of which one can be selected at a + * time) but at least it's shown in the 'Capture' + * category. + * I was told that this was due to backward compatibility, + * but I don't understand then why the mangling is *not* + * done when I name it "Input Source"..... + */ + .name = "Capture Source", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .info = tas_snd_capture_source_info, + .get = tas_snd_capture_source_get, + .put = tas_snd_capture_source_put, +}; + + +static struct transfer_info tas_transfers[] = { + { + /* input */ + .formats = SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_S16_BE | + SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S24_BE, + .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, + .transfer_in = 1, + }, + { + /* output */ + .formats = SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_S16_BE | + SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S24_BE, + .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, + .transfer_in = 0, + }, + {} +}; + +static int tas_usable(struct codec_info_item *cii, + struct transfer_info *ti, + struct transfer_info *out) +{ + return 1; +} + +static int tas_reset_init(struct tas *tas) +{ + u8 tmp; + tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 0); + msleep(1); + tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 1); + msleep(1); + tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 0); + msleep(1); + + tas->acr &= ~TAS_ACR_ANALOG_PDOWN; + tas->acr |= TAS_ACR_B_MONAUREAL | TAS_ACR_B_MON_SEL_RIGHT; + if (tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr)) + return -ENODEV; + + tmp = TAS_MCS_SCLK64 | TAS_MCS_SPORT_MODE_I2S | TAS_MCS_SPORT_WL_24BIT; + if (tas_write_reg(tas, TAS_REG_MCS, 1, &tmp)) + return -ENODEV; + + tmp = 0; + if (tas_write_reg(tas, TAS_REG_MCS2, 1, &tmp)) + return -ENODEV; + + return 0; +} + +/* we are controlled via i2c and assume that is always up + * If that wasn't the case, we'd have to suspend once + * our i2c device is suspended, and then take note of that! */ +static int tas_suspend(struct tas *tas) +{ + tas->acr |= TAS_ACR_ANALOG_PDOWN; + tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr); + return 0; +} + +static int tas_resume(struct tas *tas) +{ + /* reset codec */ + tas_reset_init(tas); + tas_set_volume(tas); + tas_set_mixer(tas); + return 0; +} + +#ifdef CONFIG_PM +static int _tas_suspend(struct codec_info_item *cii, pm_message_t state) +{ + return tas_suspend(cii->codec_data); +} + +static int _tas_resume(struct codec_info_item *cii) +{ + return tas_resume(cii->codec_data); +} +#endif + +static struct codec_info tas_codec_info = { + .transfers = tas_transfers, + /* in theory, we can drive it at 512 too... + * but so far the framework doesn't allow + * for that and I don't see much point in it. */ + .sysclock_factor = 256, + /* same here, could be 32 for just one 16 bit format */ + .bus_factor = 64, + .owner = THIS_MODULE, + .usable = tas_usable, +#ifdef CONFIG_PM + .suspend = _tas_suspend, + .resume = _tas_resume, +#endif +}; + +static int tas_init_codec(struct aoa_codec *codec) +{ + struct tas *tas = codec_to_tas(codec); + int err; + + if (!tas->codec.gpio || !tas->codec.gpio->methods) { + printk(KERN_ERR PFX "gpios not assigned!!\n"); + return -EINVAL; + } + + if (tas_reset_init(tas)) { + printk(KERN_ERR PFX "tas failed to initialise\n"); + return -ENXIO; + } + + if (tas->codec.soundbus_dev->attach_codec(tas->codec.soundbus_dev, + aoa_get_card(), + &tas_codec_info, tas)) { + printk(KERN_ERR PFX "error attaching tas to soundbus\n"); + return -ENODEV; + } + + if (aoa_snd_device_new(SNDRV_DEV_LOWLEVEL, tas, &ops)) { + printk(KERN_ERR PFX "failed to create tas snd device!\n"); + return -ENODEV; + } + err = aoa_snd_ctl_add(snd_ctl_new1(&volume_control, tas)); + if (err) + goto error; + + err = aoa_snd_ctl_add(snd_ctl_new1(&mute_control, tas)); + if (err) + goto error; + + err = aoa_snd_ctl_add(snd_ctl_new1(&pcm1_control, tas)); + if (err) + goto error; + + err = aoa_snd_ctl_add(snd_ctl_new1(&monitor_control, tas)); + if (err) + goto error; + + err = aoa_snd_ctl_add(snd_ctl_new1(&capture_source_control, tas)); + if (err) + goto error; + + return 0; + error: + tas->codec.soundbus_dev->detach_codec(tas->codec.soundbus_dev, tas); + snd_device_free(aoa_get_card(), tas); + return err; +} + +static void tas_exit_codec(struct aoa_codec *codec) +{ + struct tas *tas = codec_to_tas(codec); + + if (!tas->codec.soundbus_dev) + return; + tas->codec.soundbus_dev->detach_codec(tas->codec.soundbus_dev, tas); +} + + +static struct i2c_driver tas_driver; + +static int tas_create(struct i2c_adapter *adapter, + struct device_node *node, + int addr) +{ + struct tas *tas; + + tas = kzalloc(sizeof(struct tas), GFP_KERNEL); + + if (!tas) + return -ENOMEM; + + tas->i2c.driver = &tas_driver; + tas->i2c.adapter = adapter; + tas->i2c.addr = addr; + strlcpy(tas->i2c.name, "tas audio codec", I2C_NAME_SIZE-1); + + if (i2c_attach_client(&tas->i2c)) { + printk(KERN_ERR PFX "failed to attach to i2c\n"); + goto fail; + } + + strlcpy(tas->codec.name, "tas", MAX_CODEC_NAME_LEN-1); + tas->codec.owner = THIS_MODULE; + tas->codec.init = tas_init_codec; + tas->codec.exit = tas_exit_codec; + tas->codec.node = of_node_get(node); + + if (aoa_codec_register(&tas->codec)) { + goto detach; + } + printk(KERN_DEBUG "snd-aoa-codec-tas: created and attached tas instance\n"); + return 0; + detach: + i2c_detach_client(&tas->i2c); + fail: + kfree(tas); + return -EINVAL; +} + +static int tas_i2c_attach(struct i2c_adapter *adapter) +{ + struct device_node *busnode, *dev = NULL; + struct pmac_i2c_bus *bus; + + bus = pmac_i2c_adapter_to_bus(adapter); + if (bus == NULL) + return -ENODEV; + busnode = pmac_i2c_get_bus_node(bus); + + while ((dev = of_get_next_child(busnode, dev)) != NULL) { + if (device_is_compatible(dev, "tas3004")) { + u32 *addr; + printk(KERN_DEBUG PFX "found tas3004\n"); + addr = (u32 *) get_property(dev, "reg", NULL); + if (!addr) + continue; + return tas_create(adapter, dev, ((*addr) >> 1) & 0x7f); + } + /* older machines have no 'codec' node with a 'compatible' + * property that says 'tas3004', they just have a 'deq' + * node without any such property... */ + if (strcmp(dev->name, "deq") == 0) { + u32 *_addr, addr; + printk(KERN_DEBUG PFX "found 'deq' node\n"); + _addr = (u32 *) get_property(dev, "i2c-address", NULL); + if (!_addr) + continue; + addr = ((*_addr) >> 1) & 0x7f; + /* now, if the address doesn't match any of the two + * that a tas3004 can have, we cannot handle this. + * I doubt it ever happens but hey. */ + if (addr != 0x34 && addr != 0x35) + continue; + return tas_create(adapter, dev, addr); + } + } + return -ENODEV; +} + +static int tas_i2c_detach(struct i2c_client *client) +{ + struct tas *tas = container_of(client, struct tas, i2c); + int err; + u8 tmp = TAS_ACR_ANALOG_PDOWN; + + if ((err = i2c_detach_client(client))) + return err; + aoa_codec_unregister(&tas->codec); + of_node_put(tas->codec.node); + + /* power down codec chip */ + tas_write_reg(tas, TAS_REG_ACR, 1, &tmp); + + kfree(tas); + return 0; +} + +static struct i2c_driver tas_driver = { + .driver = { + .name = "aoa_codec_tas", + .owner = THIS_MODULE, + }, + .attach_adapter = tas_i2c_attach, + .detach_client = tas_i2c_detach, +}; + +static int __init tas_init(void) +{ + return i2c_add_driver(&tas_driver); +} + +static void __exit tas_exit(void) +{ + i2c_del_driver(&tas_driver); +} + +module_init(tas_init); +module_exit(tas_exit); diff --git a/sound/aoa/codecs/snd-aoa-codec-tas.h b/sound/aoa/codecs/snd-aoa-codec-tas.h new file mode 100644 index 00000000000..daf81f45d83 --- /dev/null +++ b/sound/aoa/codecs/snd-aoa-codec-tas.h @@ -0,0 +1,47 @@ +/* + * Apple Onboard Audio driver for tas codec (header) + * + * Copyright 2006 Johannes Berg + * + * GPL v2, can be found in COPYING. + */ +#ifndef __SND_AOA_CODECTASH +#define __SND_AOA_CODECTASH + +#define TAS_REG_MCS 0x01 /* main control */ +# define TAS_MCS_FASTLOAD (1<<7) +# define TAS_MCS_SCLK64 (1<<6) +# define TAS_MCS_SPORT_MODE_MASK (3<<4) +# define TAS_MCS_SPORT_MODE_I2S (2<<4) +# define TAS_MCS_SPORT_MODE_RJ (1<<4) +# define TAS_MCS_SPORT_MODE_LJ (0<<4) +# define TAS_MCS_SPORT_WL_MASK (3<<0) +# define TAS_MCS_SPORT_WL_16BIT (0<<0) +# define TAS_MCS_SPORT_WL_18BIT (1<<0) +# define TAS_MCS_SPORT_WL_20BIT (2<<0) +# define TAS_MCS_SPORT_WL_24BIT (3<<0) + +#define TAS_REG_DRC 0x02 +#define TAS_REG_VOL 0x04 +#define TAS_REG_TREBLE 0x05 +#define TAS_REG_BASS 0x06 +#define TAS_REG_LMIX 0x07 +#define TAS_REG_RMIX 0x08 + +#define TAS_REG_ACR 0x40 /* analog control */ +# define TAS_ACR_B_MONAUREAL (1<<7) +# define TAS_ACR_B_MON_SEL_RIGHT (1<<6) +# define TAS_ACR_DEEMPH_MASK (3<<2) +# define TAS_ACR_DEEMPH_OFF (0<<2) +# define TAS_ACR_DEEMPH_48KHz (1<<2) +# define TAS_ACR_DEEMPH_44KHz (2<<2) +# define TAS_ACR_INPUT_B (1<<1) +# define TAS_ACR_ANALOG_PDOWN (1<<0) + +#define TAS_REG_MCS2 0x43 /* main control 2 */ +# define TAS_MCS2_ALLPASS (1<<1) + +#define TAS_REG_LEFT_BIQUAD6 0x10 +#define TAS_REG_RIGHT_BIQUAD6 0x19 + +#endif /* __SND_AOA_CODECTASH */ diff --git a/sound/aoa/codecs/snd-aoa-codec-toonie.c b/sound/aoa/codecs/snd-aoa-codec-toonie.c new file mode 100644 index 00000000000..bcc555647e7 --- /dev/null +++ b/sound/aoa/codecs/snd-aoa-codec-toonie.c @@ -0,0 +1,141 @@ +/* + * Apple Onboard Audio driver for Toonie codec + * + * Copyright 2006 Johannes Berg + * + * GPL v2, can be found in COPYING. + * + * + * This is a driver for the toonie codec chip. This chip is present + * on the Mac Mini and is nothing but a DAC. + */ +#include +#include +MODULE_AUTHOR("Johannes Berg "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("toonie codec driver for snd-aoa"); + +#include "../aoa.h" +#include "../soundbus/soundbus.h" + + +#define PFX "snd-aoa-codec-toonie: " + +struct toonie { + struct aoa_codec codec; +}; +#define codec_to_toonie(c) container_of(c, struct toonie, codec) + +static int toonie_dev_register(struct snd_device *dev) +{ + return 0; +} + +static struct snd_device_ops ops = { + .dev_register = toonie_dev_register, +}; + +static struct transfer_info toonie_transfers[] = { + /* This thing *only* has analog output, + * the rates are taken from Info.plist + * from Darwin. */ + { + .formats = SNDRV_PCM_FMTBIT_S16_BE | + SNDRV_PCM_FMTBIT_S24_BE, + .rates = SNDRV_PCM_RATE_32000 | + SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_88200 | + SNDRV_PCM_RATE_96000, + }, + {} +}; + +#ifdef CONFIG_PM +static int toonie_suspend(struct codec_info_item *cii, pm_message_t state) +{ + /* can we turn it off somehow? */ + return 0; +} + +static int toonie_resume(struct codec_info_item *cii) +{ + return 0; +} +#endif /* CONFIG_PM */ + +static struct codec_info toonie_codec_info = { + .transfers = toonie_transfers, + .sysclock_factor = 256, + .bus_factor = 64, + .owner = THIS_MODULE, +#ifdef CONFIG_PM + .suspend = toonie_suspend, + .resume = toonie_resume, +#endif +}; + +static int toonie_init_codec(struct aoa_codec *codec) +{ + struct toonie *toonie = codec_to_toonie(codec); + + if (aoa_snd_device_new(SNDRV_DEV_LOWLEVEL, toonie, &ops)) { + printk(KERN_ERR PFX "failed to create toonie snd device!\n"); + return -ENODEV; + } + + /* nothing connected? what a joke! */ + if (toonie->codec.connected != 1) + return -ENOTCONN; + + if (toonie->codec.soundbus_dev->attach_codec(toonie->codec.soundbus_dev, + aoa_get_card(), + &toonie_codec_info, toonie)) { + printk(KERN_ERR PFX "error creating toonie pcm\n"); + return -ENODEV; + } + + return 0; +} + +static void toonie_exit_codec(struct aoa_codec *codec) +{ + struct toonie *toonie = codec_to_toonie(codec); + + if (!toonie->codec.soundbus_dev) { + printk(KERN_ERR PFX "toonie_exit_codec called without soundbus_dev!\n"); + return; + } + toonie->codec.soundbus_dev->detach_codec(toonie->codec.soundbus_dev, toonie); +} + +static struct toonie *toonie; + +static int __init toonie_init(void) +{ + toonie = kzalloc(sizeof(struct toonie), GFP_KERNEL); + + if (!toonie) + return -ENOMEM; + + strlcpy(toonie->codec.name, "toonie", sizeof(toonie->codec.name)); + toonie->codec.owner = THIS_MODULE; + toonie->codec.init = toonie_init_codec; + toonie->codec.exit = toonie_exit_codec; + + if (aoa_codec_register(&toonie->codec)) { + kfree(toonie); + return -EINVAL; + } + + return 0; +} + +static void __exit toonie_exit(void) +{ + aoa_codec_unregister(&toonie->codec); + kfree(toonie); +} + +module_init(toonie_init); +module_exit(toonie_exit); diff --git a/sound/aoa/core/Makefile b/sound/aoa/core/Makefile new file mode 100644 index 00000000000..62dc7287f66 --- /dev/null +++ b/sound/aoa/core/Makefile @@ -0,0 +1,5 @@ +obj-$(CONFIG_SND_AOA) += snd-aoa.o +snd-aoa-objs := snd-aoa-core.o \ + snd-aoa-alsa.o \ + snd-aoa-gpio-pmf.o \ + snd-aoa-gpio-feature.o diff --git a/sound/aoa/core/snd-aoa-alsa.c b/sound/aoa/core/snd-aoa-alsa.c new file mode 100644 index 00000000000..b42fdea77ed --- /dev/null +++ b/sound/aoa/core/snd-aoa-alsa.c @@ -0,0 +1,98 @@ +/* + * Apple Onboard Audio Alsa helpers + * + * Copyright 2006 Johannes Berg + * + * GPL v2, can be found in COPYING. + */ +#include +#include "snd-aoa-alsa.h" + +static int index = -1; +module_param(index, int, 0444); +MODULE_PARM_DESC(index, "index for AOA sound card."); + +static struct aoa_card *aoa_card; + +int aoa_alsa_init(char *name, struct module *mod) +{ + struct snd_card *alsa_card; + int err; + + if (aoa_card) + /* cannot be EEXIST due to usage in aoa_fabric_register */ + return -EBUSY; + + alsa_card = snd_card_new(index, name, mod, sizeof(struct aoa_card)); + if (!alsa_card) + return -ENOMEM; + aoa_card = alsa_card->private_data; + aoa_card->alsa_card = alsa_card; + strlcpy(alsa_card->driver, "AppleOnbdAudio", sizeof(alsa_card->driver)); + strlcpy(alsa_card->shortname, name, sizeof(alsa_card->shortname)); + strlcpy(alsa_card->longname, name, sizeof(alsa_card->longname)); + strlcpy(alsa_card->mixername, name, sizeof(alsa_card->mixername)); + err = snd_card_register(aoa_card->alsa_card); + if (err < 0) { + printk(KERN_ERR "snd-aoa: couldn't register alsa card\n"); + snd_card_free(aoa_card->alsa_card); + aoa_card = NULL; + return err; + } + return 0; +} + +struct snd_card *aoa_get_card(void) +{ + if (aoa_card) + return aoa_card->alsa_card; + return NULL; +} +EXPORT_SYMBOL_GPL(aoa_get_card); + +void aoa_alsa_cleanup(void) +{ + if (aoa_card) { + snd_card_free(aoa_card->alsa_card); + aoa_card = NULL; + } +} + +int aoa_snd_device_new(snd_device_type_t type, + void * device_data, struct snd_device_ops * ops) +{ + struct snd_card *card = aoa_get_card(); + int err; + + if (!card) return -ENOMEM; + + err = snd_device_new(card, type, device_data, ops); + if (err) { + printk(KERN_ERR "snd-aoa: failed to create snd device (%d)\n", err); + return err; + } + err = snd_device_register(card, device_data); + if (err) { + printk(KERN_ERR "snd-aoa: failed to register " + "snd device (%d)\n", err); + printk(KERN_ERR "snd-aoa: have you forgotten the " + "dev_register callback?\n"); + snd_device_free(card, device_data); + } + return err; +} +EXPORT_SYMBOL_GPL(aoa_snd_device_new); + +int aoa_snd_ctl_add(struct snd_kcontrol* control) +{ + int err; + + if (!aoa_card) return -ENODEV; + + err = snd_ctl_add(aoa_card->alsa_card, control); + if (err) + printk(KERN_ERR "snd-aoa: failed to add alsa control (%d)\n", + err); + return err; +} +EXPORT_SYMBOL_GPL(aoa_snd_ctl_add); diff --git a/sound/aoa/core/snd-aoa-alsa.h b/sound/aoa/core/snd-aoa-alsa.h new file mode 100644 index 00000000000..660d2f1793b --- /dev/null +++ b/sound/aoa/core/snd-aoa-alsa.h @@ -0,0 +1,16 @@ +/* + * Apple Onboard Audio Alsa private helpers + * + * Copyright 2006 Johannes Berg + * + * GPL v2, can be found in COPYING. + */ + +#ifndef __SND_AOA_ALSA_H +#define __SND_AOA_ALSA_H +#include "../aoa.h" + +extern int aoa_alsa_init(char *name, struct module *mod); +extern void aoa_alsa_cleanup(void); + +#endif /* __SND_AOA_ALSA_H */ diff --git a/sound/aoa/core/snd-aoa-core.c b/sound/aoa/core/snd-aoa-core.c new file mode 100644 index 00000000000..ecd2d8263f2 --- /dev/null +++ b/sound/aoa/core/snd-aoa-core.c @@ -0,0 +1,162 @@ +/* + * Apple Onboard Audio driver core + * + * Copyright 2006 Johannes Berg + * + * GPL v2, can be found in COPYING. + */ + +#include +#include +#include +#include "../aoa.h" +#include "snd-aoa-alsa.h" + +MODULE_DESCRIPTION("Apple Onboard Audio Sound Driver"); +MODULE_AUTHOR("Johannes Berg "); +MODULE_LICENSE("GPL"); + +/* We allow only one fabric. This simplifies things, + * and more don't really make that much sense */ +static struct aoa_fabric *fabric; +static LIST_HEAD(codec_list); + +static int attach_codec_to_fabric(struct aoa_codec *c) +{ + int err; + + if (!try_module_get(c->owner)) + return -EBUSY; + /* found_codec has to be assigned */ + err = -ENOENT; + if (fabric->found_codec) + err = fabric->found_codec(c); + if (err) { + module_put(c->owner); + printk(KERN_ERR "snd-aoa: fabric didn't like codec %s\n", + c->name); + return err; + } + c->fabric = fabric; + + err = 0; + if (c->init) + err = c->init(c); + if (err) { + printk(KERN_ERR "snd-aoa: codec %s didn't init\n", c->name); + c->fabric = NULL; + if (fabric->remove_codec) + fabric->remove_codec(c); + module_put(c->owner); + return err; + } + if (fabric->attached_codec) + fabric->attached_codec(c); + return 0; +} + +int aoa_codec_register(struct aoa_codec *codec) +{ + int err = 0; + + /* if there's a fabric already, we can tell if we + * will want to have this codec, so propagate error + * through. Otherwise, this will happen later... */ + if (fabric) + err = attach_codec_to_fabric(codec); + if (!err) + list_add(&codec->list, &codec_list); + return err; +} +EXPORT_SYMBOL_GPL(aoa_codec_register); + +void aoa_codec_unregister(struct aoa_codec *codec) +{ + list_del(&codec->list); + if (codec->fabric && codec->exit) + codec->exit(codec); + if (fabric && fabric->remove_codec) + fabric->remove_codec(codec); + codec->fabric = NULL; + module_put(codec->owner); +} +EXPORT_SYMBOL_GPL(aoa_codec_unregister); + +int aoa_fabric_register(struct aoa_fabric *new_fabric) +{ + struct aoa_codec *c; + int err; + + /* allow querying for presence of fabric + * (i.e. do this test first!) */ + if (new_fabric == fabric) { + err = -EALREADY; + goto attach; + } + if (fabric) + return -EEXIST; + if (!new_fabric) + return -EINVAL; + + err = aoa_alsa_init(new_fabric->name, new_fabric->owner); + if (err) + return err; + + fabric = new_fabric; + + attach: + list_for_each_entry(c, &codec_list, list) { + if (c->fabric != fabric) + attach_codec_to_fabric(c); + } + return err; +} +EXPORT_SYMBOL_GPL(aoa_fabric_register); + +void aoa_fabric_unregister(struct aoa_fabric *old_fabric) +{ + struct aoa_codec *c; + + if (fabric != old_fabric) + return; + + list_for_each_entry(c, &codec_list, list) { + if (c->fabric) + aoa_fabric_unlink_codec(c); + } + + aoa_alsa_cleanup(); + + fabric = NULL; +} +EXPORT_SYMBOL_GPL(aoa_fabric_unregister); + +void aoa_fabric_unlink_codec(struct aoa_codec *codec) +{ + if (!codec->fabric) { + printk(KERN_ERR "snd-aoa: fabric unassigned " + "in aoa_fabric_unlink_codec\n"); + dump_stack(); + return; + } + if (codec->exit) + codec->exit(codec); + if (codec->fabric->remove_codec) + codec->fabric->remove_codec(codec); + codec->fabric = NULL; + module_put(codec->owner); +} +EXPORT_SYMBOL_GPL(aoa_fabric_unlink_codec); + +static int __init aoa_init(void) +{ + return 0; +} + +static void __exit aoa_exit(void) +{ + aoa_alsa_cleanup(); +} + +module_init(aoa_init); +module_exit(aoa_exit); diff --git a/sound/aoa/core/snd-aoa-gpio-feature.c b/sound/aoa/core/snd-aoa-gpio-feature.c new file mode 100644 index 00000000000..2c6eb7784cc --- /dev/null +++ b/sound/aoa/core/snd-aoa-gpio-feature.c @@ -0,0 +1,399 @@ +/* + * Apple Onboard Audio feature call GPIO control + * + * Copyright 2006 Johannes Berg + * + * GPL v2, can be found in COPYING. + * + * This file contains the GPIO control routines for + * direct (through feature calls) access to the GPIO + * registers. + */ + +#include +#include +#include "../aoa.h" + +/* TODO: these are 20 global variables + * that aren't used on most machines... + * Move them into a dynamically allocated + * structure and use that. + */ + +/* these are the GPIO numbers (register addresses as offsets into + * the GPIO space) */ +static int headphone_mute_gpio; +static int amp_mute_gpio; +static int lineout_mute_gpio; +static int hw_reset_gpio; +static int lineout_detect_gpio; +static int headphone_detect_gpio; +static int linein_detect_gpio; + +/* see the SWITCH_GPIO macro */ +static int headphone_mute_gpio_activestate; +static int amp_mute_gpio_activestate; +static int lineout_mute_gpio_activestate; +static int hw_reset_gpio_activestate; +static int lineout_detect_gpio_activestate; +static int headphone_detect_gpio_activestate; +static int linein_detect_gpio_activestate; + +/* node pointers that we save when getting the GPIO number + * to get the interrupt later */ +static struct device_node *lineout_detect_node; +static struct device_node *linein_detect_node; +static struct device_node *headphone_detect_node; + +static int lineout_detect_irq; +static int linein_detect_irq; +static int headphone_detect_irq; + +static struct device_node *get_gpio(char *name, + char *altname, + int *gpioptr, + int *gpioactiveptr) +{ + struct device_node *np, *gpio; + u32 *reg; + char *audio_gpio; + + *gpioptr = -1; + + /* check if we can get it the easy way ... */ + np = of_find_node_by_name(NULL, name); + if (!np) { + /* some machines have only gpioX/extint-gpioX nodes, + * and an audio-gpio property saying what it is ... + * So what we have to do is enumerate all children + * of the gpio node and check them all. */ + gpio = of_find_node_by_name(NULL, "gpio"); + if (!gpio) + return NULL; + while ((np = of_get_next_child(gpio, np))) { + audio_gpio = get_property(np, "audio-gpio", NULL); + if (!audio_gpio) + continue; + if (strcmp(audio_gpio, name) == 0) + break; + if (altname && (strcmp(audio_gpio, altname) == 0)) + break; + } + /* still not found, assume not there */ + if (!np) + return NULL; + } + + reg = (u32 *)get_property(np, "reg", NULL); + if (!reg) + return NULL; + + *gpioptr = *reg; + + /* this is a hack, usually the GPIOs 'reg' property + * should have the offset based from the GPIO space + * which is at 0x50, but apparently not always... */ + if (*gpioptr < 0x50) + *gpioptr += 0x50; + + reg = (u32 *)get_property(np, "audio-gpio-active-state", NULL); + if (!reg) + /* Apple seems to default to 1, but + * that doesn't seem right at least on most + * machines. So until proven that the opposite + * is necessary, we default to 0 + * (which, incidentally, snd-powermac also does...) */ + *gpioactiveptr = 0; + else + *gpioactiveptr = *reg; + + return np; +} + +static void get_irq(struct device_node * np, int *irqptr) +{ + *irqptr = -1; + if (!np) + return; + if (np->n_intrs != 1) + return; + *irqptr = np->intrs[0].line; +} + +/* 0x4 is outenable, 0x1 is out, thus 4 or 5 */ +#define SWITCH_GPIO(name, v, on) \ + (((v)&~1) | ((on)? \ + (name##_gpio_activestate==0?4:5): \ + (name##_gpio_activestate==0?5:4))) + +#define FTR_GPIO(name, bit) \ +static void ftr_gpio_set_##name(struct gpio_runtime *rt, int on)\ +{ \ + int v; \ + \ + if (unlikely(!rt)) return; \ + \ + if (name##_mute_gpio < 0) \ + return; \ + \ + v = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, \ + name##_mute_gpio, \ + 0); \ + \ + /* muted = !on... */ \ + v = SWITCH_GPIO(name##_mute, v, !on); \ + \ + pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, \ + name##_mute_gpio, v); \ + \ + rt->implementation_private &= ~(1<implementation_private |= (!!on << bit); \ +} \ +static int ftr_gpio_get_##name(struct gpio_runtime *rt) \ +{ \ + if (unlikely(!rt)) return 0; \ + return (rt->implementation_private>>bit)&1; \ +} + +FTR_GPIO(headphone, 0); +FTR_GPIO(amp, 1); +FTR_GPIO(lineout, 2); + +static void ftr_gpio_set_hw_reset(struct gpio_runtime *rt, int on) +{ + int v; + + if (unlikely(!rt)) return; + if (hw_reset_gpio < 0) + return; + + v = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, + hw_reset_gpio, 0); + v = SWITCH_GPIO(hw_reset, v, on); + pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, + hw_reset_gpio, v); +} + +static void ftr_gpio_all_amps_off(struct gpio_runtime *rt) +{ + int saved; + + if (unlikely(!rt)) return; + saved = rt->implementation_private; + ftr_gpio_set_headphone(rt, 0); + ftr_gpio_set_amp(rt, 0); + ftr_gpio_set_lineout(rt, 0); + rt->implementation_private = saved; +} + +static void ftr_gpio_all_amps_restore(struct gpio_runtime *rt) +{ + int s; + + if (unlikely(!rt)) return; + s = rt->implementation_private; + ftr_gpio_set_headphone(rt, (s>>0)&1); + ftr_gpio_set_amp(rt, (s>>1)&1); + ftr_gpio_set_lineout(rt, (s>>2)&1); +} + +static void ftr_handle_notify(void *data) +{ + struct gpio_notification *notif = data; + + mutex_lock(¬if->mutex); + if (notif->notify) + notif->notify(notif->data); + mutex_unlock(¬if->mutex); +} + +static void ftr_gpio_init(struct gpio_runtime *rt) +{ + get_gpio("headphone-mute", NULL, + &headphone_mute_gpio, + &headphone_mute_gpio_activestate); + get_gpio("amp-mute", NULL, + &_mute_gpio, + &_mute_gpio_activestate); + get_gpio("lineout-mute", NULL, + &lineout_mute_gpio, + &lineout_mute_gpio_activestate); + get_gpio("hw-reset", "audio-hw-reset", + &hw_reset_gpio, + &hw_reset_gpio_activestate); + + headphone_detect_node = get_gpio("headphone-detect", NULL, + &headphone_detect_gpio, + &headphone_detect_gpio_activestate); + /* go Apple, and thanks for giving these different names + * across the board... */ + lineout_detect_node = get_gpio("lineout-detect", "line-output-detect", + &lineout_detect_gpio, + &lineout_detect_gpio_activestate); + linein_detect_node = get_gpio("linein-detect", "line-input-detect", + &linein_detect_gpio, + &linein_detect_gpio_activestate); + + get_irq(headphone_detect_node, &headphone_detect_irq); + get_irq(lineout_detect_node, &lineout_detect_irq); + get_irq(linein_detect_node, &linein_detect_irq); + + ftr_gpio_all_amps_off(rt); + rt->implementation_private = 0; + INIT_WORK(&rt->headphone_notify.work, ftr_handle_notify, + &rt->headphone_notify); + INIT_WORK(&rt->line_in_notify.work, ftr_handle_notify, + &rt->line_in_notify); + INIT_WORK(&rt->line_out_notify.work, ftr_handle_notify, + &rt->line_out_notify); + mutex_init(&rt->headphone_notify.mutex); + mutex_init(&rt->line_in_notify.mutex); + mutex_init(&rt->line_out_notify.mutex); +} + +static void ftr_gpio_exit(struct gpio_runtime *rt) +{ + ftr_gpio_all_amps_off(rt); + rt->implementation_private = 0; + if (rt->headphone_notify.notify) + free_irq(headphone_detect_irq, &rt->headphone_notify); + if (rt->line_in_notify.gpio_private) + free_irq(linein_detect_irq, &rt->line_in_notify); + if (rt->line_out_notify.gpio_private) + free_irq(lineout_detect_irq, &rt->line_out_notify); + cancel_delayed_work(&rt->headphone_notify.work); + cancel_delayed_work(&rt->line_in_notify.work); + cancel_delayed_work(&rt->line_out_notify.work); + flush_scheduled_work(); + mutex_destroy(&rt->headphone_notify.mutex); + mutex_destroy(&rt->line_in_notify.mutex); + mutex_destroy(&rt->line_out_notify.mutex); +} + +static irqreturn_t ftr_handle_notify_irq(int xx, + void *data, + struct pt_regs *regs) +{ + struct gpio_notification *notif = data; + + schedule_work(¬if->work); + + return IRQ_HANDLED; +} + +static int ftr_set_notify(struct gpio_runtime *rt, + enum notify_type type, + notify_func_t notify, + void *data) +{ + struct gpio_notification *notif; + notify_func_t old; + int irq; + char *name; + int err = -EBUSY; + + switch (type) { + case AOA_NOTIFY_HEADPHONE: + notif = &rt->headphone_notify; + name = "headphone-detect"; + irq = headphone_detect_irq; + break; + case AOA_NOTIFY_LINE_IN: + notif = &rt->line_in_notify; + name = "linein-detect"; + irq = linein_detect_irq; + break; + case AOA_NOTIFY_LINE_OUT: + notif = &rt->line_out_notify; + name = "lineout-detect"; + irq = lineout_detect_irq; + break; + default: + return -EINVAL; + } + + if (irq == -1) + return -ENODEV; + + mutex_lock(¬if->mutex); + + old = notif->notify; + + if (!old && !notify) { + err = 0; + goto out_unlock; + } + + if (old && notify) { + if (old == notify && notif->data == data) + err = 0; + goto out_unlock; + } + + if (old && !notify) + free_irq(irq, notif); + + if (!old && notify) { + err = request_irq(irq, ftr_handle_notify_irq, 0, name, notif); + if (err) + goto out_unlock; + } + + notif->notify = notify; + notif->data = data; + + err = 0; + out_unlock: + mutex_unlock(¬if->mutex); + return err; +} + +static int ftr_get_detect(struct gpio_runtime *rt, + enum notify_type type) +{ + int gpio, ret, active; + + switch (type) { + case AOA_NOTIFY_HEADPHONE: + gpio = headphone_detect_gpio; + active = headphone_detect_gpio_activestate; + break; + case AOA_NOTIFY_LINE_IN: + gpio = linein_detect_gpio; + active = linein_detect_gpio_activestate; + break; + case AOA_NOTIFY_LINE_OUT: + gpio = lineout_detect_gpio; + active = lineout_detect_gpio_activestate; + break; + default: + return -EINVAL; + } + + if (gpio == -1) + return -ENODEV; + + ret = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, gpio, 0); + if (ret < 0) + return ret; + return ((ret >> 1) & 1) == active; +} + +static struct gpio_methods methods = { + .init = ftr_gpio_init, + .exit = ftr_gpio_exit, + .all_amps_off = ftr_gpio_all_amps_off, + .all_amps_restore = ftr_gpio_all_amps_restore, + .set_headphone = ftr_gpio_set_headphone, + .set_speakers = ftr_gpio_set_amp, + .set_lineout = ftr_gpio_set_lineout, + .set_hw_reset = ftr_gpio_set_hw_reset, + .get_headphone = ftr_gpio_get_headphone, + .get_speakers = ftr_gpio_get_amp, + .get_lineout = ftr_gpio_get_lineout, + .set_notify = ftr_set_notify, + .get_detect = ftr_get_detect, +}; + +struct gpio_methods *ftr_gpio_methods = &methods; +EXPORT_SYMBOL_GPL(ftr_gpio_methods); diff --git a/sound/aoa/core/snd-aoa-gpio-pmf.c b/sound/aoa/core/snd-aoa-gpio-pmf.c new file mode 100644 index 00000000000..0e9b9bb2a6d --- /dev/null +++ b/sound/aoa/core/snd-aoa-gpio-pmf.c @@ -0,0 +1,246 @@ +/* + * Apple Onboard Audio pmf GPIOs + * + * Copyright 2006 Johannes Berg + * + * GPL v2, can be found in COPYING. + */ + +#include +#include +#include "../aoa.h" + +#define PMF_GPIO(name, bit) \ +static void pmf_gpio_set_##name(struct gpio_runtime *rt, int on)\ +{ \ + struct pmf_args args = { .count = 1, .u[0].v = !on }; \ + \ + if (unlikely(!rt)) return; \ + pmf_call_function(rt->node, #name "-mute", &args); \ + rt->implementation_private &= ~(1<implementation_private |= (!!on << bit); \ +} \ +static int pmf_gpio_get_##name(struct gpio_runtime *rt) \ +{ \ + if (unlikely(!rt)) return 0; \ + return (rt->implementation_private>>bit)&1; \ +} + +PMF_GPIO(headphone, 0); +PMF_GPIO(amp, 1); +PMF_GPIO(lineout, 2); + +static void pmf_gpio_set_hw_reset(struct gpio_runtime *rt, int on) +{ + struct pmf_args args = { .count = 1, .u[0].v = !!on }; + + if (unlikely(!rt)) return; + pmf_call_function(rt->node, "hw-reset", &args); +} + +static void pmf_gpio_all_amps_off(struct gpio_runtime *rt) +{ + int saved; + + if (unlikely(!rt)) return; + saved = rt->implementation_private; + pmf_gpio_set_headphone(rt, 0); + pmf_gpio_set_amp(rt, 0); + pmf_gpio_set_lineout(rt, 0); + rt->implementation_private = saved; +} + +static void pmf_gpio_all_amps_restore(struct gpio_runtime *rt) +{ + int s; + + if (unlikely(!rt)) return; + s = rt->implementation_private; + pmf_gpio_set_headphone(rt, (s>>0)&1); + pmf_gpio_set_amp(rt, (s>>1)&1); + pmf_gpio_set_lineout(rt, (s>>2)&1); +} + +static void pmf_handle_notify(void *data) +{ + struct gpio_notification *notif = data; + + mutex_lock(¬if->mutex); + if (notif->notify) + notif->notify(notif->data); + mutex_unlock(¬if->mutex); +} + +static void pmf_gpio_init(struct gpio_runtime *rt) +{ + pmf_gpio_all_amps_off(rt); + rt->implementation_private = 0; + INIT_WORK(&rt->headphone_notify.work, pmf_handle_notify, + &rt->headphone_notify); + INIT_WORK(&rt->line_in_notify.work, pmf_handle_notify, + &rt->line_in_notify); + INIT_WORK(&rt->line_out_notify.work, pmf_handle_notify, + &rt->line_out_notify); + mutex_init(&rt->headphone_notify.mutex); + mutex_init(&rt->line_in_notify.mutex); + mutex_init(&rt->line_out_notify.mutex); +} + +static void pmf_gpio_exit(struct gpio_runtime *rt) +{ + pmf_gpio_all_amps_off(rt); + rt->implementation_private = 0; + + if (rt->headphone_notify.gpio_private) + pmf_unregister_irq_client(rt->headphone_notify.gpio_private); + if (rt->line_in_notify.gpio_private) + pmf_unregister_irq_client(rt->line_in_notify.gpio_private); + if (rt->line_out_notify.gpio_private) + pmf_unregister_irq_client(rt->line_out_notify.gpio_private); + + /* make sure no work is pending before freeing + * all things */ + cancel_delayed_work(&rt->headphone_notify.work); + cancel_delayed_work(&rt->line_in_notify.work); + cancel_delayed_work(&rt->line_out_notify.work); + flush_scheduled_work(); + + mutex_destroy(&rt->headphone_notify.mutex); + mutex_destroy(&rt->line_in_notify.mutex); + mutex_destroy(&rt->line_out_notify.mutex); + + if (rt->headphone_notify.gpio_private) + kfree(rt->headphone_notify.gpio_private); + if (rt->line_in_notify.gpio_private) + kfree(rt->line_in_notify.gpio_private); + if (rt->line_out_notify.gpio_private) + kfree(rt->line_out_notify.gpio_private); +} + +static void pmf_handle_notify_irq(void *data) +{ + struct gpio_notification *notif = data; + + schedule_work(¬if->work); +} + +static int pmf_set_notify(struct gpio_runtime *rt, + enum notify_type type, + notify_func_t notify, + void *data) +{ + struct gpio_notification *notif; + notify_func_t old; + struct pmf_irq_client *irq_client; + char *name; + int err = -EBUSY; + + switch (type) { + case AOA_NOTIFY_HEADPHONE: + notif = &rt->headphone_notify; + name = "headphone-detect"; + break; + case AOA_NOTIFY_LINE_IN: + notif = &rt->line_in_notify; + name = "linein-detect"; + break; + case AOA_NOTIFY_LINE_OUT: + notif = &rt->line_out_notify; + name = "lineout-detect"; + break; + default: + return -EINVAL; + } + + mutex_lock(¬if->mutex); + + old = notif->notify; + + if (!old && !notify) { + err = 0; + goto out_unlock; + } + + if (old && notify) { + if (old == notify && notif->data == data) + err = 0; + goto out_unlock; + } + + if (old && !notify) { + irq_client = notif->gpio_private; + pmf_unregister_irq_client(irq_client); + kfree(irq_client); + notif->gpio_private = NULL; + } + if (!old && notify) { + irq_client = kzalloc(sizeof(struct pmf_irq_client), + GFP_KERNEL); + irq_client->data = notif; + irq_client->handler = pmf_handle_notify_irq; + irq_client->owner = THIS_MODULE; + err = pmf_register_irq_client(rt->node, + name, + irq_client); + if (err) { + printk(KERN_ERR "snd-aoa: gpio layer failed to" + " register %s irq (%d)\n", name, err); + kfree(irq_client); + goto out_unlock; + } + notif->gpio_private = irq_client; + } + notif->notify = notify; + notif->data = data; + + err = 0; + out_unlock: + mutex_unlock(¬if->mutex); + return err; +} + +static int pmf_get_detect(struct gpio_runtime *rt, + enum notify_type type) +{ + char *name; + int err = -EBUSY, ret; + struct pmf_args args = { .count = 1, .u[0].p = &ret }; + + switch (type) { + case AOA_NOTIFY_HEADPHONE: + name = "headphone-detect"; + break; + case AOA_NOTIFY_LINE_IN: + name = "linein-detect"; + break; + case AOA_NOTIFY_LINE_OUT: + name = "lineout-detect"; + break; + default: + return -EINVAL; + } + + err = pmf_call_function(rt->node, name, &args); + if (err) + return err; + return ret; +} + +static struct gpio_methods methods = { + .init = pmf_gpio_init, + .exit = pmf_gpio_exit, + .all_amps_off = pmf_gpio_all_amps_off, + .all_amps_restore = pmf_gpio_all_amps_restore, + .set_headphone = pmf_gpio_set_headphone, + .set_speakers = pmf_gpio_set_amp, + .set_lineout = pmf_gpio_set_lineout, + .set_hw_reset = pmf_gpio_set_hw_reset, + .get_headphone = pmf_gpio_get_headphone, + .get_speakers = pmf_gpio_get_amp, + .get_lineout = pmf_gpio_get_lineout, + .set_notify = pmf_set_notify, + .get_detect = pmf_get_detect, +}; + +struct gpio_methods *pmf_gpio_methods = &methods; +EXPORT_SYMBOL_GPL(pmf_gpio_methods); diff --git a/sound/aoa/fabrics/Kconfig b/sound/aoa/fabrics/Kconfig new file mode 100644 index 00000000000..c3bc7705c86 --- /dev/null +++ b/sound/aoa/fabrics/Kconfig @@ -0,0 +1,12 @@ +config SND_AOA_FABRIC_LAYOUT + tristate "layout-id fabric" + depends SND_AOA + select SND_AOA_SOUNDBUS + select SND_AOA_SOUNDBUS_I2S + ---help--- + This enables the layout-id fabric for the Apple Onboard + Audio driver, the module holding it all together + based on the device-tree's layout-id property. + + If you are unsure and have a later Apple machine, + compile it as a module. diff --git a/sound/aoa/fabrics/Makefile b/sound/aoa/fabrics/Makefile new file mode 100644 index 00000000000..55fc5e7e52c --- /dev/null +++ b/sound/aoa/fabrics/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_SND_AOA_FABRIC_LAYOUT) += snd-aoa-fabric-layout.o diff --git a/sound/aoa/fabrics/snd-aoa-fabric-layout.c b/sound/aoa/fabrics/snd-aoa-fabric-layout.c new file mode 100644 index 00000000000..04a7238e949 --- /dev/null +++ b/sound/aoa/fabrics/snd-aoa-fabric-layout.c @@ -0,0 +1,1109 @@ +/* + * Apple Onboard Audio driver -- layout fabric + * + * Copyright 2006 Johannes Berg + * + * GPL v2, can be found in COPYING. + * + * + * This fabric module looks for sound codecs + * based on the layout-id property in the device tree. + * + */ + +#include +#include +#include +#include "../aoa.h" +#include "../soundbus/soundbus.h" + +MODULE_AUTHOR("Johannes Berg "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Layout-ID fabric for snd-aoa"); + +#define MAX_CODECS_PER_BUS 2 + +/* These are the connections the layout fabric + * knows about. It doesn't really care about the + * input ones, but I thought I'd separate them + * to give them proper names. The thing is that + * Apple usually will distinguish the active output + * by GPIOs, while the active input is set directly + * on the codec. Hence we here tell the codec what + * we think is connected. This information is hard- + * coded below ... */ +#define CC_SPEAKERS (1<<0) +#define CC_HEADPHONE (1<<1) +#define CC_LINEOUT (1<<2) +#define CC_DIGITALOUT (1<<3) +#define CC_LINEIN (1<<4) +#define CC_MICROPHONE (1<<5) +#define CC_DIGITALIN (1<<6) +/* pretty bogus but users complain... + * This is a flag saying that the LINEOUT + * should be renamed to HEADPHONE. + * be careful with input detection! */ +#define CC_LINEOUT_LABELLED_HEADPHONE (1<<7) + +struct codec_connection { + /* CC_ flags from above */ + int connected; + /* codec dependent bit to be set in the aoa_codec.connected field. + * This intentionally doesn't have any generic flags because the + * fabric has to know the codec anyway and all codecs might have + * different connectors */ + int codec_bit; +}; + +struct codec_connect_info { + char *name; + struct codec_connection *connections; +}; + +#define LAYOUT_FLAG_COMBO_LINEOUT_SPDIF (1<<0) + +struct layout { + unsigned int layout_id; + struct codec_connect_info codecs[MAX_CODECS_PER_BUS]; + int flags; + + /* if busname is not assigned, we use 'Master' below, + * so that our layout table doesn't need to be filled + * too much. + * We only assign these two if we expect to find more + * than one soundbus, i.e. on those machines with + * multiple layout-ids */ + char *busname; + int pcmid; +}; + +MODULE_ALIAS("sound-layout-41"); +MODULE_ALIAS("sound-layout-45"); +MODULE_ALIAS("sound-layout-51"); +MODULE_ALIAS("sound-layout-58"); +MODULE_ALIAS("sound-layout-60"); +MODULE_ALIAS("sound-layout-61"); +MODULE_ALIAS("sound-layout-64"); +MODULE_ALIAS("sound-layout-65"); +MODULE_ALIAS("sound-layout-68"); +MODULE_ALIAS("sound-layout-69"); +MODULE_ALIAS("sound-layout-70"); +MODULE_ALIAS("sound-layout-72"); +MODULE_ALIAS("sound-layout-80"); +MODULE_ALIAS("sound-layout-82"); +MODULE_ALIAS("sound-layout-84"); +MODULE_ALIAS("sound-layout-86"); +MODULE_ALIAS("sound-layout-92"); + +/* onyx with all but microphone connected */ +static struct codec_connection onyx_connections_nomic[] = { + { + .connected = CC_SPEAKERS | CC_HEADPHONE | CC_LINEOUT, + .codec_bit = 0, + }, + { + .connected = CC_DIGITALOUT, + .codec_bit = 1, + }, + { + .connected = CC_LINEIN, + .codec_bit = 2, + }, + {} /* terminate array by .connected == 0 */ +}; + +/* onyx on machines without headphone */ +static struct codec_connection onyx_connections_noheadphones[] = { + { + .connected = CC_SPEAKERS | CC_LINEOUT | + CC_LINEOUT_LABELLED_HEADPHONE, + .codec_bit = 0, + }, + { + .connected = CC_DIGITALOUT, + .codec_bit = 1, + }, + /* FIXME: are these correct? probably not for all the machines + * below ... If not this will need separating. */ + { + .connected = CC_LINEIN, + .codec_bit = 2, + }, + { + .connected = CC_MICROPHONE, + .codec_bit = 3, + }, + {} /* terminate array by .connected == 0 */ +}; + +/* onyx on machines with real line-out */ +static struct codec_connection onyx_connections_reallineout[] = { + { + .connected = CC_SPEAKERS | CC_LINEOUT | CC_HEADPHONE, + .codec_bit = 0, + }, + { + .connected = CC_DIGITALOUT, + .codec_bit = 1, + }, + { + .connected = CC_LINEIN, + .codec_bit = 2, + }, + {} /* terminate array by .connected == 0 */ +}; + +/* tas on machines without line out */ +static struct codec_connection tas_connections_nolineout[] = { + { + .connected = CC_SPEAKERS | CC_HEADPHONE, + .codec_bit = 0, + }, + { + .connected = CC_LINEIN, + .codec_bit = 2, + }, + { + .connected = CC_MICROPHONE, + .codec_bit = 3, + }, + {} /* terminate array by .connected == 0 */ +}; + +/* tas on machines with neither line out nor line in */ +static struct codec_connection tas_connections_noline[] = { + { + .connected = CC_SPEAKERS | CC_HEADPHONE, + .codec_bit = 0, + }, + { + .connected = CC_MICROPHONE, + .codec_bit = 3, + }, + {} /* terminate array by .connected == 0 */ +}; + +/* tas on machines without microphone */ +static struct codec_connection tas_connections_nomic[] = { + { + .connected = CC_SPEAKERS | CC_HEADPHONE | CC_LINEOUT, + .codec_bit = 0, + }, + { + .connected = CC_LINEIN, + .codec_bit = 2, + }, + {} /* terminate array by .connected == 0 */ +}; + +/* tas on machines with everything connected */ +static struct codec_connection tas_connections_all[] = { + { + .connected = CC_SPEAKERS | CC_HEADPHONE | CC_LINEOUT, + .codec_bit = 0, + }, + { + .connected = CC_LINEIN, + .codec_bit = 2, + }, + { + .connected = CC_MICROPHONE, + .codec_bit = 3, + }, + {} /* terminate array by .connected == 0 */ +}; + +static struct codec_connection toonie_connections[] = { + { + .connected = CC_SPEAKERS | CC_HEADPHONE, + .codec_bit = 0, + }, + {} /* terminate array by .connected == 0 */ +}; + +static struct codec_connection topaz_input[] = { + { + .connected = CC_DIGITALIN, + .codec_bit = 0, + }, + {} /* terminate array by .connected == 0 */ +}; + +static struct codec_connection topaz_output[] = { + { + .connected = CC_DIGITALOUT, + .codec_bit = 1, + }, + {} /* terminate array by .connected == 0 */ +}; + +static struct codec_connection topaz_inout[] = { + { + .connected = CC_DIGITALIN, + .codec_bit = 0, + }, + { + .connected = CC_DIGITALOUT, + .codec_bit = 1, + }, + {} /* terminate array by .connected == 0 */ +}; + +static struct layout layouts[] = { + /* last PowerBooks (15" Oct 2005) */ + { .layout_id = 82, + .flags = LAYOUT_FLAG_COMBO_LINEOUT_SPDIF, + .codecs[0] = { + .name = "onyx", + .connections = onyx_connections_noheadphones, + }, + .codecs[1] = { + .name = "topaz", + .connections = topaz_input, + }, + }, + /* PowerMac9,1 */ + { .layout_id = 60, + .codecs[0] = { + .name = "onyx", + .connections = onyx_connections_reallineout, + }, + }, + /* PowerMac9,1 */ + { .layout_id = 61, + .codecs[0] = { + .name = "topaz", + .connections = topaz_input, + }, + }, + /* PowerBook5,7 */ + { .layout_id = 64, + .flags = LAYOUT_FLAG_COMBO_LINEOUT_SPDIF, + .codecs[0] = { + .name = "onyx", + .connections = onyx_connections_noheadphones, + }, + }, + /* PowerBook5,7 */ + { .layout_id = 65, + .codecs[0] = { + .name = "topaz", + .connections = topaz_input, + }, + }, + /* PowerBook5,9 [17" Oct 2005] */ + { .layout_id = 84, + .flags = LAYOUT_FLAG_COMBO_LINEOUT_SPDIF, + .codecs[0] = { + .name = "onyx", + .connections = onyx_connections_noheadphones, + }, + .codecs[1] = { + .name = "topaz", + .connections = topaz_input, + }, + }, + /* PowerMac8,1 */ + { .layout_id = 45, + .codecs[0] = { + .name = "onyx", + .connections = onyx_connections_noheadphones, + }, + .codecs[1] = { + .name = "topaz", + .connections = topaz_input, + }, + }, + /* Quad PowerMac (analog in, analog/digital out) */ + { .layout_id = 68, + .codecs[0] = { + .name = "onyx", + .connections = onyx_connections_nomic, + }, + }, + /* Quad PowerMac (digital in) */ + { .layout_id = 69, + .codecs[0] = { + .name = "topaz", + .connections = topaz_input, + }, + .busname = "digital in", .pcmid = 1 }, + /* Early 2005 PowerBook (PowerBook 5,6) */ + { .layout_id = 70, + .codecs[0] = { + .name = "tas", + .connections = tas_connections_nolineout, + }, + }, + /* PowerBook 5,4 */ + { .layout_id = 51, + .codecs[0] = { + .name = "tas", + .connections = tas_connections_nolineout, + }, + }, + /* PowerBook6,7 */ + { .layout_id = 80, + .codecs[0] = { + .name = "tas", + .connections = tas_connections_noline, + }, + }, + /* PowerBook6,8 */ + { .layout_id = 72, + .codecs[0] = { + .name = "tas", + .connections = tas_connections_nolineout, + }, + }, + /* PowerMac8,2 */ + { .layout_id = 86, + .codecs[0] = { + .name = "onyx", + .connections = onyx_connections_nomic, + }, + .codecs[1] = { + .name = "topaz", + .connections = topaz_input, + }, + }, + /* PowerBook6,7 */ + { .layout_id = 92, + .codecs[0] = { + .name = "tas", + .connections = tas_connections_nolineout, + }, + }, + /* PowerMac10,1 (Mac Mini) */ + { .layout_id = 58, + .codecs[0] = { + .name = "toonie", + .connections = toonie_connections, + }, + }, + /* unknown, untested, but this comes from Apple */ + { .layout_id = 41, + .codecs[0] = { + .name = "tas", + .connections = tas_connections_all, + }, + }, + { .layout_id = 36, + .codecs[0] = { + .name = "tas", + .connections = tas_connections_nomic, + }, + .codecs[1] = { + .name = "topaz", + .connections = topaz_inout, + }, + }, + { .layout_id = 47, + .codecs[0] = { + .name = "onyx", + .connections = onyx_connections_noheadphones, + }, + }, + { .layout_id = 48, + .codecs[0] = { + .name = "topaz", + .connections = topaz_input, + }, + }, + { .layout_id = 49, + .codecs[0] = { + .name = "onyx", + .connections = onyx_connections_nomic, + }, + }, + { .layout_id = 50, + .codecs[0] = { + .name = "topaz", + .connections = topaz_input, + }, + }, + { .layout_id = 56, + .codecs[0] = { + .name = "onyx", + .connections = onyx_connections_noheadphones, + }, + }, + { .layout_id = 57, + .codecs[0] = { + .name = "topaz", + .connections = topaz_input, + }, + }, + { .layout_id = 62, + .codecs[0] = { + .name = "onyx", + .connections = onyx_connections_noheadphones, + }, + .codecs[1] = { + .name = "topaz", + .connections = topaz_output, + }, + }, + { .layout_id = 66, + .codecs[0] = { + .name = "onyx", + .connections = onyx_connections_noheadphones, + }, + }, + { .layout_id = 67, + .codecs[0] = { + .name = "topaz", + .connections = topaz_input, + }, + }, + { .layout_id = 76, + .codecs[0] = { + .name = "tas", + .connections = tas_connections_nomic, + }, + .codecs[1] = { + .name = "topaz", + .connections = topaz_inout, + }, + }, + { .layout_id = 90, + .codecs[0] = { + .name = "tas", + .connections = tas_connections_noline, + }, + }, + { .layout_id = 94, + .codecs[0] = { + .name = "onyx", + /* but it has an external mic?? how to select? */ + .connections = onyx_connections_noheadphones, + }, + }, + { .layout_id = 96, + .codecs[0] = { + .name = "onyx", + .connections = onyx_connections_noheadphones, + }, + }, + { .layout_id = 98, + .codecs[0] = { + .name = "toonie", + .connections = toonie_connections, + }, + }, + { .layout_id = 100, + .codecs[0] = { + .name = "topaz", + .connections = topaz_input, + }, + .codecs[1] = { + .name = "onyx", + .connections = onyx_connections_noheadphones, + }, + }, + {} +}; + +static struct layout *find_layout_by_id(unsigned int id) +{ + struct layout *l; + + l = layouts; + while (l->layout_id) { + if (l->layout_id == id) + return l; + l++; + } + return NULL; +} + +static void use_layout(struct layout *l) +{ + int i; + + for (i=0; icodecs[i].name) { + request_module("snd-aoa-codec-%s", l->codecs[i].name); + } + } + /* now we wait for the codecs to call us back */ +} + +struct layout_dev; + +struct layout_dev_ptr { + struct layout_dev *ptr; +}; + +struct layout_dev { + struct list_head list; + struct soundbus_dev *sdev; + struct device_node *sound; + struct aoa_codec *codecs[MAX_CODECS_PER_BUS]; + struct layout *layout; + struct gpio_runtime gpio; + + /* we need these for headphone/lineout detection */ + struct snd_kcontrol *headphone_ctrl; + struct snd_kcontrol *lineout_ctrl; + struct snd_kcontrol *speaker_ctrl; + struct snd_kcontrol *headphone_detected_ctrl; + struct snd_kcontrol *lineout_detected_ctrl; + + struct layout_dev_ptr selfptr_headphone; + struct layout_dev_ptr selfptr_lineout; + + u32 have_lineout_detect:1, + have_headphone_detect:1, + switch_on_headphone:1, + switch_on_lineout:1; +}; + +static LIST_HEAD(layouts_list); +static int layouts_list_items; +/* this can go away but only if we allow multiple cards, + * make the fabric handle all the card stuff, etc... */ +static struct layout_dev *layout_device; + +static int control_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + return 0; +} + +#define AMP_CONTROL(n, description) \ +static int n##_control_get(struct snd_kcontrol *kcontrol, \ + struct snd_ctl_elem_value *ucontrol) \ +{ \ + struct gpio_runtime *gpio = snd_kcontrol_chip(kcontrol); \ + if (gpio->methods && gpio->methods->get_##n) \ + ucontrol->value.integer.value[0] = \ + gpio->methods->get_##n(gpio); \ + return 0; \ +} \ +static int n##_control_put(struct snd_kcontrol *kcontrol, \ + struct snd_ctl_elem_value *ucontrol) \ +{ \ + struct gpio_runtime *gpio = snd_kcontrol_chip(kcontrol); \ + if (gpio->methods && gpio->methods->get_##n) \ + gpio->methods->set_##n(gpio, \ + ucontrol->value.integer.value[0]); \ + return 1; \ +} \ +static struct snd_kcontrol_new n##_ctl = { \ + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ + .name = description, \ + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ + .info = control_info, \ + .get = n##_control_get, \ + .put = n##_control_put, \ +} + +AMP_CONTROL(headphone, "Headphone Switch"); +AMP_CONTROL(speakers, "Speakers Switch"); +AMP_CONTROL(lineout, "Line-Out Switch"); + +static int detect_choice_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct layout_dev *ldev = snd_kcontrol_chip(kcontrol); + + switch (kcontrol->private_value) { + case 0: + ucontrol->value.integer.value[0] = ldev->switch_on_headphone; + break; + case 1: + ucontrol->value.integer.value[0] = ldev->switch_on_lineout; + break; + default: + return -ENODEV; + } + return 0; +} + +static int detect_choice_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct layout_dev *ldev = snd_kcontrol_chip(kcontrol); + + switch (kcontrol->private_value) { + case 0: + ldev->switch_on_headphone = !!ucontrol->value.integer.value[0]; + break; + case 1: + ldev->switch_on_lineout = !!ucontrol->value.integer.value[0]; + break; + default: + return -ENODEV; + } + return 1; +} + +static struct snd_kcontrol_new headphone_detect_choice = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Headphone Detect Autoswitch", + .info = control_info, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .get = detect_choice_get, + .put = detect_choice_put, + .private_value = 0, +}; + +static struct snd_kcontrol_new lineout_detect_choice = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Line-Out Detect Autoswitch", + .info = control_info, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .get = detect_choice_get, + .put = detect_choice_put, + .private_value = 1, +}; + +static int detected_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct layout_dev *ldev = snd_kcontrol_chip(kcontrol); + int v; + + switch (kcontrol->private_value) { + case 0: + v = ldev->gpio.methods->get_detect(&ldev->gpio, + AOA_NOTIFY_HEADPHONE); + break; + case 1: + v = ldev->gpio.methods->get_detect(&ldev->gpio, + AOA_NOTIFY_LINE_OUT); + break; + default: + return -ENODEV; + } + ucontrol->value.integer.value[0] = v; + return 0; +} + +static struct snd_kcontrol_new headphone_detected = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Headphone Detected", + .info = control_info, + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .get = detected_get, + .private_value = 0, +}; + +static struct snd_kcontrol_new lineout_detected = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Line-Out Detected", + .info = control_info, + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .get = detected_get, + .private_value = 1, +}; + +static int check_codec(struct aoa_codec *codec, + struct layout_dev *ldev, + struct codec_connect_info *cci) +{ + u32 *ref; + char propname[32]; + struct codec_connection *cc; + + /* if the codec has a 'codec' node, we require a reference */ + if (codec->node && (strcmp(codec->node->name, "codec") == 0)) { + snprintf(propname, sizeof(propname), + "platform-%s-codec-ref", codec->name); + ref = (u32*)get_property(ldev->sound, propname, NULL); + if (!ref) { + printk(KERN_INFO "snd-aoa-fabric-layout: " + "required property %s not present\n", propname); + return -ENODEV; + } + if (*ref != codec->node->linux_phandle) { + printk(KERN_INFO "snd-aoa-fabric-layout: " + "%s doesn't match!\n", propname); + return -ENODEV; + } + } else { + if (layouts_list_items != 1) { + printk(KERN_INFO "snd-aoa-fabric-layout: " + "more than one soundbus, but no references.\n"); + return -ENODEV; + } + } + codec->soundbus_dev = ldev->sdev; + codec->gpio = &ldev->gpio; + + cc = cci->connections; + if (!cc) + return -EINVAL; + + printk(KERN_INFO "snd-aoa-fabric-layout: can use this codec\n"); + + codec->connected = 0; + codec->fabric_data = cc; + + while (cc->connected) { + codec->connected |= 1<codec_bit; + cc++; + } + + return 0; +} + +static int layout_found_codec(struct aoa_codec *codec) +{ + struct layout_dev *ldev; + int i; + + list_for_each_entry(ldev, &layouts_list, list) { + for (i=0; ilayout->codecs[i].name) + continue; + if (strcmp(ldev->layout->codecs[i].name, codec->name) == 0) { + if (check_codec(codec, + ldev, + &ldev->layout->codecs[i]) == 0) + return 0; + } + } + } + return -ENODEV; +} + +static void layout_remove_codec(struct aoa_codec *codec) +{ + int i; + /* here remove the codec from the layout dev's + * codec reference */ + + codec->soundbus_dev = NULL; + codec->gpio = NULL; + for (i=0; iptr; + if (data == &ldev->selfptr_headphone) { + v = ldev->gpio.methods->get_detect(&ldev->gpio, AOA_NOTIFY_HEADPHONE); + detected = ldev->headphone_detected_ctrl; + update = ldev->switch_on_headphone; + if (update) { + ldev->gpio.methods->set_speakers(&ldev->gpio, !v); + ldev->gpio.methods->set_headphone(&ldev->gpio, v); + ldev->gpio.methods->set_lineout(&ldev->gpio, 0); + } + } else if (data == &ldev->selfptr_lineout) { + v = ldev->gpio.methods->get_detect(&ldev->gpio, AOA_NOTIFY_LINE_OUT); + detected = ldev->lineout_detected_ctrl; + update = ldev->switch_on_lineout; + if (update) { + ldev->gpio.methods->set_speakers(&ldev->gpio, !v); + ldev->gpio.methods->set_headphone(&ldev->gpio, 0); + ldev->gpio.methods->set_lineout(&ldev->gpio, v); + } + } else + return; + + if (detected) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &detected->id); + if (update) { + c = ldev->headphone_ctrl; + if (c) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &c->id); + c = ldev->speaker_ctrl; + if (c) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &c->id); + c = ldev->lineout_ctrl; + if (c) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &c->id); + } +} + +static void layout_attached_codec(struct aoa_codec *codec) +{ + struct codec_connection *cc; + struct snd_kcontrol *ctl; + int headphones, lineout; + struct layout_dev *ldev = layout_device; + + /* need to add this codec to our codec array! */ + + cc = codec->fabric_data; + + headphones = codec->gpio->methods->get_detect(codec->gpio, + AOA_NOTIFY_HEADPHONE); + lineout = codec->gpio->methods->get_detect(codec->gpio, + AOA_NOTIFY_LINE_OUT); + + while (cc->connected) { + if (cc->connected & CC_SPEAKERS) { + if (headphones <= 0 && lineout <= 0) + ldev->gpio.methods->set_speakers(codec->gpio, 1); + ctl = snd_ctl_new1(&speakers_ctl, codec->gpio); + ldev->speaker_ctrl = ctl; + aoa_snd_ctl_add(ctl); + } + if (cc->connected & CC_HEADPHONE) { + if (headphones == 1) + ldev->gpio.methods->set_headphone(codec->gpio, 1); + ctl = snd_ctl_new1(&headphone_ctl, codec->gpio); + ldev->headphone_ctrl = ctl; + aoa_snd_ctl_add(ctl); + ldev->have_headphone_detect = + !ldev->gpio.methods + ->set_notify(&ldev->gpio, + AOA_NOTIFY_HEADPHONE, + layout_notify, + &ldev->selfptr_headphone); + if (ldev->have_headphone_detect) { + ctl = snd_ctl_new1(&headphone_detect_choice, + ldev); + aoa_snd_ctl_add(ctl); + ctl = snd_ctl_new1(&headphone_detected, + ldev); + ldev->headphone_detected_ctrl = ctl; + aoa_snd_ctl_add(ctl); + } + } + if (cc->connected & CC_LINEOUT) { + if (lineout == 1) + ldev->gpio.methods->set_lineout(codec->gpio, 1); + ctl = snd_ctl_new1(&lineout_ctl, codec->gpio); + if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE) + strlcpy(ctl->id.name, + "Headphone Switch", sizeof(ctl->id.name)); + ldev->lineout_ctrl = ctl; + aoa_snd_ctl_add(ctl); + ldev->have_lineout_detect = + !ldev->gpio.methods + ->set_notify(&ldev->gpio, + AOA_NOTIFY_LINE_OUT, + layout_notify, + &ldev->selfptr_lineout); + if (ldev->have_lineout_detect) { + ctl = snd_ctl_new1(&lineout_detect_choice, + ldev); + if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE) + strlcpy(ctl->id.name, + "Headphone Detect Autoswitch", + sizeof(ctl->id.name)); + aoa_snd_ctl_add(ctl); + ctl = snd_ctl_new1(&lineout_detected, + ldev); + if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE) + strlcpy(ctl->id.name, + "Headphone Detected", + sizeof(ctl->id.name)); + ldev->lineout_detected_ctrl = ctl; + aoa_snd_ctl_add(ctl); + } + } + cc++; + } + /* now update initial state */ + if (ldev->have_headphone_detect) + layout_notify(&ldev->selfptr_headphone); + if (ldev->have_lineout_detect) + layout_notify(&ldev->selfptr_lineout); +} + +static struct aoa_fabric layout_fabric = { + .name = "SoundByLayout", + .owner = THIS_MODULE, + .found_codec = layout_found_codec, + .remove_codec = layout_remove_codec, + .attached_codec = layout_attached_codec, +}; + +static int aoa_fabric_layout_probe(struct soundbus_dev *sdev) +{ + struct device_node *sound = NULL; + unsigned int *layout_id; + struct layout *layout; + struct layout_dev *ldev = NULL; + int err; + + /* hm, currently we can only have one ... */ + if (layout_device) + return -ENODEV; + + /* by breaking out we keep a reference */ + while ((sound = of_get_next_child(sdev->ofdev.node, sound))) { + if (sound->type && strcasecmp(sound->type, "soundchip") == 0) + break; + } + if (!sound) return -ENODEV; + + layout_id = (unsigned int *) get_property(sound, "layout-id", NULL); + if (!layout_id) + goto outnodev; + printk(KERN_INFO "snd-aoa-fabric-layout: found bus with layout %d ", *layout_id); + + layout = find_layout_by_id(*layout_id); + if (!layout) { + printk("(no idea how to handle)\n"); + goto outnodev; + } + + ldev = kzalloc(sizeof(struct layout_dev), GFP_KERNEL); + if (!ldev) + goto outnodev; + + layout_device = ldev; + ldev->sdev = sdev; + ldev->sound = sound; + ldev->layout = layout; + ldev->gpio.node = sound->parent; + switch (layout->layout_id) { + case 41: /* that unknown machine no one seems to have */ + case 51: /* PowerBook5,4 */ + case 58: /* Mac Mini */ + ldev->gpio.methods = ftr_gpio_methods; + break; + default: + ldev->gpio.methods = pmf_gpio_methods; + } + ldev->selfptr_headphone.ptr = ldev; + ldev->selfptr_lineout.ptr = ldev; + sdev->ofdev.dev.driver_data = ldev; + + printk("(using)\n"); + list_add(&ldev->list, &layouts_list); + layouts_list_items++; + + /* assign these before registering ourselves, so + * callbacks that are done during registration + * already have the values */ + sdev->pcmid = ldev->layout->pcmid; + if (ldev->layout->busname) { + sdev->pcmname = ldev->layout->busname; + } else { + sdev->pcmname = "Master"; + } + + ldev->gpio.methods->init(&ldev->gpio); + + err = aoa_fabric_register(&layout_fabric); + if (err && err != -EALREADY) { + printk(KERN_INFO "snd-aoa-fabric-layout: can't use," + " another fabric is active!\n"); + goto outlistdel; + } + + use_layout(layout); + ldev->switch_on_headphone = 1; + ldev->switch_on_lineout = 1; + return 0; + outlistdel: + /* we won't be using these then... */ + ldev->gpio.methods->exit(&ldev->gpio); + /* reset if we didn't use it */ + sdev->pcmname = NULL; + sdev->pcmid = -1; + list_del(&ldev->list); + layouts_list_items--; + outnodev: + if (sound) of_node_put(sound); + layout_device = NULL; + if (ldev) kfree(ldev); + return -ENODEV; +} + +static int aoa_fabric_layout_remove(struct soundbus_dev *sdev) +{ + struct layout_dev *ldev = sdev->ofdev.dev.driver_data; + int i; + + for (i=0; icodecs[i]) { + aoa_fabric_unlink_codec(ldev->codecs[i]); + } + ldev->codecs[i] = NULL; + } + list_del(&ldev->list); + layouts_list_items--; + of_node_put(ldev->sound); + + ldev->gpio.methods->set_notify(&ldev->gpio, + AOA_NOTIFY_HEADPHONE, + NULL, + NULL); + ldev->gpio.methods->set_notify(&ldev->gpio, + AOA_NOTIFY_LINE_OUT, + NULL, + NULL); + + ldev->gpio.methods->exit(&ldev->gpio); + layout_device = NULL; + kfree(ldev); + sdev->pcmid = -1; + sdev->pcmname = NULL; + return 0; +} + +#ifdef CONFIG_PM +static int aoa_fabric_layout_suspend(struct soundbus_dev *sdev, pm_message_t state) +{ + struct layout_dev *ldev = sdev->ofdev.dev.driver_data; + + printk("aoa_fabric_layout_suspend()\n"); + + if (ldev->gpio.methods && ldev->gpio.methods->all_amps_off) + ldev->gpio.methods->all_amps_off(&ldev->gpio); + + return 0; +} + +static int aoa_fabric_layout_resume(struct soundbus_dev *sdev) +{ + struct layout_dev *ldev = sdev->ofdev.dev.driver_data; + + printk("aoa_fabric_layout_resume()\n"); + + if (ldev->gpio.methods && ldev->gpio.methods->all_amps_off) + ldev->gpio.methods->all_amps_restore(&ldev->gpio); + + return 0; +} +#endif + +static struct soundbus_driver aoa_soundbus_driver = { + .name = "snd_aoa_soundbus_drv", + .owner = THIS_MODULE, + .probe = aoa_fabric_layout_probe, + .remove = aoa_fabric_layout_remove, +#ifdef CONFIG_PM + .suspend = aoa_fabric_layout_suspend, + .resume = aoa_fabric_layout_resume, +#endif +}; + +static int __init aoa_fabric_layout_init(void) +{ + int err; + + err = soundbus_register_driver(&aoa_soundbus_driver); + if (err) + return err; + return 0; +} + +static void __exit aoa_fabric_layout_exit(void) +{ + soundbus_unregister_driver(&aoa_soundbus_driver); + aoa_fabric_unregister(&layout_fabric); +} + +module_init(aoa_fabric_layout_init); +module_exit(aoa_fabric_layout_exit); diff --git a/sound/aoa/soundbus/Kconfig b/sound/aoa/soundbus/Kconfig new file mode 100644 index 00000000000..d532d27a9f5 --- /dev/null +++ b/sound/aoa/soundbus/Kconfig @@ -0,0 +1,14 @@ +config SND_AOA_SOUNDBUS + tristate "Apple Soundbus support" + depends on SOUND && SND_PCM && EXPERIMENTAL + ---help--- + This option enables the generic driver for the soundbus + support on Apple machines. + + It is required for the sound bus implementations. + +config SND_AOA_SOUNDBUS_I2S + tristate "I2S bus support" + depends on SND_AOA_SOUNDBUS && PCI + ---help--- + This option enables support for Apple I2S busses. diff --git a/sound/aoa/soundbus/Makefile b/sound/aoa/soundbus/Makefile new file mode 100644 index 00000000000..0e61f5aa06b --- /dev/null +++ b/sound/aoa/soundbus/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_SND_AOA_SOUNDBUS) += snd-aoa-soundbus.o +snd-aoa-soundbus-objs := core.o sysfs.o +obj-$(CONFIG_SND_AOA_SOUNDBUS_I2S) += i2sbus/ diff --git a/sound/aoa/soundbus/core.c b/sound/aoa/soundbus/core.c new file mode 100644 index 00000000000..abe84a76c83 --- /dev/null +++ b/sound/aoa/soundbus/core.c @@ -0,0 +1,250 @@ +/* + * soundbus + * + * Copyright 2006 Johannes Berg + * + * GPL v2, can be found in COPYING. + */ + +#include +#include "soundbus.h" + +MODULE_AUTHOR("Johannes Berg "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Apple Soundbus"); + +struct soundbus_dev *soundbus_dev_get(struct soundbus_dev *dev) +{ + struct device *tmp; + + if (!dev) + return NULL; + tmp = get_device(&dev->ofdev.dev); + if (tmp) + return to_soundbus_device(tmp); + else + return NULL; +} +EXPORT_SYMBOL_GPL(soundbus_dev_get); + +void soundbus_dev_put(struct soundbus_dev *dev) +{ + if (dev) + put_device(&dev->ofdev.dev); +} +EXPORT_SYMBOL_GPL(soundbus_dev_put); + +static int soundbus_probe(struct device *dev) +{ + int error = -ENODEV; + struct soundbus_driver *drv; + struct soundbus_dev *soundbus_dev; + + drv = to_soundbus_driver(dev->driver); + soundbus_dev = to_soundbus_device(dev); + + if (!drv->probe) + return error; + + soundbus_dev_get(soundbus_dev); + + error = drv->probe(soundbus_dev); + if (error) + soundbus_dev_put(soundbus_dev); + + return error; +} + + +static int soundbus_uevent(struct device *dev, char **envp, int num_envp, + char *buffer, int buffer_size) +{ + struct soundbus_dev * soundbus_dev; + struct of_device * of; + char *scratch, *compat, *compat2; + int i = 0; + int length, cplen, cplen2, seen = 0; + + if (!dev) + return -ENODEV; + + soundbus_dev = to_soundbus_device(dev); + if (!soundbus_dev) + return -ENODEV; + + of = &soundbus_dev->ofdev; + + /* stuff we want to pass to /sbin/hotplug */ + envp[i++] = scratch = buffer; + length = scnprintf (scratch, buffer_size, "OF_NAME=%s", of->node->name); + ++length; + buffer_size -= length; + if ((buffer_size <= 0) || (i >= num_envp)) + return -ENOMEM; + scratch += length; + + envp[i++] = scratch; + length = scnprintf (scratch, buffer_size, "OF_TYPE=%s", of->node->type); + ++length; + buffer_size -= length; + if ((buffer_size <= 0) || (i >= num_envp)) + return -ENOMEM; + scratch += length; + + /* Since the compatible field can contain pretty much anything + * it's not really legal to split it out with commas. We split it + * up using a number of environment variables instead. */ + + compat = (char *) get_property(of->node, "compatible", &cplen); + compat2 = compat; + cplen2= cplen; + while (compat && cplen > 0) { + envp[i++] = scratch; + length = scnprintf (scratch, buffer_size, + "OF_COMPATIBLE_%d=%s", seen, compat); + ++length; + buffer_size -= length; + if ((buffer_size <= 0) || (i >= num_envp)) + return -ENOMEM; + scratch += length; + length = strlen (compat) + 1; + compat += length; + cplen -= length; + seen++; + } + + envp[i++] = scratch; + length = scnprintf (scratch, buffer_size, "OF_COMPATIBLE_N=%d", seen); + ++length; + buffer_size -= length; + if ((buffer_size <= 0) || (i >= num_envp)) + return -ENOMEM; + scratch += length; + + envp[i++] = scratch; + length = scnprintf (scratch, buffer_size, "MODALIAS=%s", + soundbus_dev->modalias); + + buffer_size -= length; + if ((buffer_size <= 0) || (i >= num_envp)) + return -ENOMEM; + + envp[i] = NULL; + + return 0; +} + +static int soundbus_device_remove(struct device *dev) +{ + struct soundbus_dev * soundbus_dev = to_soundbus_device(dev); + struct soundbus_driver * drv = to_soundbus_driver(dev->driver); + + if (dev->driver && drv->remove) + drv->remove(soundbus_dev); + soundbus_dev_put(soundbus_dev); + + return 0; +} + +static void soundbus_device_shutdown(struct device *dev) +{ + struct soundbus_dev * soundbus_dev = to_soundbus_device(dev); + struct soundbus_driver * drv = to_soundbus_driver(dev->driver); + + if (dev->driver && drv->shutdown) + drv->shutdown(soundbus_dev); +} + +#ifdef CONFIG_PM + +static int soundbus_device_suspend(struct device *dev, pm_message_t state) +{ + struct soundbus_dev * soundbus_dev = to_soundbus_device(dev); + struct soundbus_driver * drv = to_soundbus_driver(dev->driver); + + if (dev->driver && drv->suspend) + return drv->suspend(soundbus_dev, state); + return 0; +} + +static int soundbus_device_resume(struct device * dev) +{ + struct soundbus_dev * soundbus_dev = to_soundbus_device(dev); + struct soundbus_driver * drv = to_soundbus_driver(dev->driver); + + if (dev->driver && drv->resume) + return drv->resume(soundbus_dev); + return 0; +} + +#endif /* CONFIG_PM */ + +extern struct device_attribute soundbus_dev_attrs[]; + +static struct bus_type soundbus_bus_type = { + .name = "aoa-soundbus", + .probe = soundbus_probe, + .uevent = soundbus_uevent, + .remove = soundbus_device_remove, + .shutdown = soundbus_device_shutdown, +#ifdef CONFIG_PM + .suspend = soundbus_device_suspend, + .resume = soundbus_device_resume, +#endif + .dev_attrs = soundbus_dev_attrs, +}; + +static int __init soundbus_init(void) +{ + return bus_register(&soundbus_bus_type); +} + +static void __exit soundbus_exit(void) +{ + bus_unregister(&soundbus_bus_type); +} + +int soundbus_add_one(struct soundbus_dev *dev) +{ + static int devcount; + + /* sanity checks */ + if (!dev->attach_codec || + !dev->ofdev.node || + dev->pcmname || + dev->pcmid != -1) { + printk(KERN_ERR "soundbus: adding device failed sanity check!\n"); + return -EINVAL; + } + + snprintf(dev->ofdev.dev.bus_id, BUS_ID_SIZE, "soundbus:%x", ++devcount); + dev->ofdev.dev.bus = &soundbus_bus_type; + return of_device_register(&dev->ofdev); +} +EXPORT_SYMBOL_GPL(soundbus_add_one); + +void soundbus_remove_one(struct soundbus_dev *dev) +{ + of_device_unregister(&dev->ofdev); +} +EXPORT_SYMBOL_GPL(soundbus_remove_one); + +int soundbus_register_driver(struct soundbus_driver *drv) +{ + /* initialize common driver fields */ + drv->driver.name = drv->name; + drv->driver.bus = &soundbus_bus_type; + + /* register with core */ + return driver_register(&drv->driver); +} +EXPORT_SYMBOL_GPL(soundbus_register_driver); + +void soundbus_unregister_driver(struct soundbus_driver *drv) +{ + driver_unregister(&drv->driver); +} +EXPORT_SYMBOL_GPL(soundbus_unregister_driver); + +module_init(soundbus_init); +module_exit(soundbus_exit); diff --git a/sound/aoa/soundbus/i2sbus/Makefile b/sound/aoa/soundbus/i2sbus/Makefile new file mode 100644 index 00000000000..e57a5cf6565 --- /dev/null +++ b/sound/aoa/soundbus/i2sbus/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_SND_AOA_SOUNDBUS_I2S) += snd-aoa-i2sbus.o +snd-aoa-i2sbus-objs := i2sbus-core.o i2sbus-pcm.o i2sbus-control.o diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-control.c b/sound/aoa/soundbus/i2sbus/i2sbus-control.c new file mode 100644 index 00000000000..f50407952d3 --- /dev/null +++ b/sound/aoa/soundbus/i2sbus/i2sbus-control.c @@ -0,0 +1,192 @@ +/* + * i2sbus driver -- bus control routines + * + * Copyright 2006 Johannes Berg + * + * GPL v2, can be found in COPYING. + */ + +#include +#include +#include +#include +#include +#include +#include "i2sbus.h" + +int i2sbus_control_init(struct macio_dev* dev, struct i2sbus_control **c) +{ + *c = kzalloc(sizeof(struct i2sbus_control), GFP_KERNEL); + if (!*c) + return -ENOMEM; + + INIT_LIST_HEAD(&(*c)->list); + + if (of_address_to_resource(dev->ofdev.node, 0, &(*c)->rsrc)) + goto err; + /* we really should be using feature calls instead of mapping + * these registers. It's safe for now since no one else is + * touching them... */ + (*c)->controlregs = ioremap((*c)->rsrc.start, + sizeof(struct i2s_control_regs)); + if (!(*c)->controlregs) + goto err; + + return 0; + err: + kfree(*c); + *c = NULL; + return -ENODEV; +} + +void i2sbus_control_destroy(struct i2sbus_control *c) +{ + iounmap(c->controlregs); + kfree(c); +} + +/* this is serialised externally */ +int i2sbus_control_add_dev(struct i2sbus_control *c, + struct i2sbus_dev *i2sdev) +{ + struct device_node *np; + + np = i2sdev->sound.ofdev.node; + i2sdev->enable = pmf_find_function(np, "enable"); + i2sdev->cell_enable = pmf_find_function(np, "cell-enable"); + i2sdev->clock_enable = pmf_find_function(np, "clock-enable"); + i2sdev->cell_disable = pmf_find_function(np, "cell-disable"); + i2sdev->clock_disable = pmf_find_function(np, "clock-disable"); + + /* if the bus number is not 0 or 1 we absolutely need to use + * the platform functions -- there's nothing in Darwin that + * would allow seeing a system behind what the FCRs are then, + * and I don't want to go parsing a bunch of platform functions + * by hand to try finding a system... */ + if (i2sdev->bus_number != 0 && i2sdev->bus_number != 1 && + (!i2sdev->enable || + !i2sdev->cell_enable || !i2sdev->clock_enable || + !i2sdev->cell_disable || !i2sdev->clock_disable)) { + pmf_put_function(i2sdev->enable); + pmf_put_function(i2sdev->cell_enable); + pmf_put_function(i2sdev->clock_enable); + pmf_put_function(i2sdev->cell_disable); + pmf_put_function(i2sdev->clock_disable); + return -ENODEV; + } + + list_add(&i2sdev->item, &c->list); + + return 0; +} + +void i2sbus_control_remove_dev(struct i2sbus_control *c, + struct i2sbus_dev *i2sdev) +{ + /* this is serialised externally */ + list_del(&i2sdev->item); + if (list_empty(&c->list)) + i2sbus_control_destroy(c); +} + +int i2sbus_control_enable(struct i2sbus_control *c, + struct i2sbus_dev *i2sdev) +{ + struct pmf_args args = { .count = 0 }; + int cc; + + if (i2sdev->enable) + return pmf_call_one(i2sdev->enable, &args); + + switch (i2sdev->bus_number) { + case 0: + cc = in_le32(&c->controlregs->cell_control); + out_le32(&c->controlregs->cell_control, cc | CTRL_CLOCK_INTF_0_ENABLE); + break; + case 1: + cc = in_le32(&c->controlregs->cell_control); + out_le32(&c->controlregs->cell_control, cc | CTRL_CLOCK_INTF_1_ENABLE); + break; + default: + return -ENODEV; + } + return 0; +} + +int i2sbus_control_cell(struct i2sbus_control *c, + struct i2sbus_dev *i2sdev, + int enable) +{ + struct pmf_args args = { .count = 0 }; + int cc; + + switch (enable) { + case 0: + if (i2sdev->cell_disable) + return pmf_call_one(i2sdev->cell_disable, &args); + break; + case 1: + if (i2sdev->cell_enable) + return pmf_call_one(i2sdev->cell_enable, &args); + break; + default: + printk(KERN_ERR "i2sbus: INVALID CELL ENABLE VALUE\n"); + return -ENODEV; + } + switch (i2sdev->bus_number) { + case 0: + cc = in_le32(&c->controlregs->cell_control); + cc &= ~CTRL_CLOCK_CELL_0_ENABLE; + cc |= enable * CTRL_CLOCK_CELL_0_ENABLE; + out_le32(&c->controlregs->cell_control, cc); + break; + case 1: + cc = in_le32(&c->controlregs->cell_control); + cc &= ~CTRL_CLOCK_CELL_1_ENABLE; + cc |= enable * CTRL_CLOCK_CELL_1_ENABLE; + out_le32(&c->controlregs->cell_control, cc); + break; + default: + return -ENODEV; + } + return 0; +} + +int i2sbus_control_clock(struct i2sbus_control *c, + struct i2sbus_dev *i2sdev, + int enable) +{ + struct pmf_args args = { .count = 0 }; + int cc; + + switch (enable) { + case 0: + if (i2sdev->clock_disable) + return pmf_call_one(i2sdev->clock_disable, &args); + break; + case 1: + if (i2sdev->clock_enable) + return pmf_call_one(i2sdev->clock_enable, &args); + break; + default: + printk(KERN_ERR "i2sbus: INVALID CLOCK ENABLE VALUE\n"); + return -ENODEV; + } + switch (i2sdev->bus_number) { + case 0: + cc = in_le32(&c->controlregs->cell_control); + cc &= ~CTRL_CLOCK_CLOCK_0_ENABLE; + cc |= enable * CTRL_CLOCK_CLOCK_0_ENABLE; + out_le32(&c->controlregs->cell_control, cc); + break; + case 1: + cc = in_le32(&c->controlregs->cell_control); + cc &= ~CTRL_CLOCK_CLOCK_1_ENABLE; + cc |= enable * CTRL_CLOCK_CLOCK_1_ENABLE; + out_le32(&c->controlregs->cell_control, cc); + break; + default: + return -ENODEV; + } + return 0; +} diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-control.h b/sound/aoa/soundbus/i2sbus/i2sbus-control.h new file mode 100644 index 00000000000..bb05550f730 --- /dev/null +++ b/sound/aoa/soundbus/i2sbus/i2sbus-control.h @@ -0,0 +1,37 @@ +/* + * i2sbus driver -- bus register definitions + * + * Copyright 2006 Johannes Berg + * + * GPL v2, can be found in COPYING. + */ +#ifndef __I2SBUS_CONTROLREGS_H +#define __I2SBUS_CONTROLREGS_H + +/* i2s control registers, at least what we know about them */ + +#define __PAD(m,n) u8 __pad##m[n] +#define _PAD(line, n) __PAD(line, n) +#define PAD(n) _PAD(__LINE__, (n)) +struct i2s_control_regs { + PAD(0x38); + __le32 fcr0; /* 0x38 (unknown) */ + __le32 cell_control; /* 0x3c (fcr1) */ + __le32 fcr2; /* 0x40 (unknown) */ + __le32 fcr3; /* 0x44 (fcr3) */ + __le32 clock_control; /* 0x48 (unknown) */ + PAD(4); + /* total size: 0x50 bytes */ +} __attribute__((__packed__)); + +#define CTRL_CLOCK_CELL_0_ENABLE (1<<10) +#define CTRL_CLOCK_CLOCK_0_ENABLE (1<<12) +#define CTRL_CLOCK_SWRESET_0 (1<<11) +#define CTRL_CLOCK_INTF_0_ENABLE (1<<13) + +#define CTRL_CLOCK_CELL_1_ENABLE (1<<17) +#define CTRL_CLOCK_CLOCK_1_ENABLE (1<<18) +#define CTRL_CLOCK_SWRESET_1 (1<<19) +#define CTRL_CLOCK_INTF_1_ENABLE (1<<20) + +#endif /* __I2SBUS_CONTROLREGS_H */ diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-core.c b/sound/aoa/soundbus/i2sbus/i2sbus-core.c new file mode 100644 index 00000000000..f268dacdaa0 --- /dev/null +++ b/sound/aoa/soundbus/i2sbus/i2sbus-core.c @@ -0,0 +1,387 @@ +/* + * i2sbus driver + * + * Copyright 2006 Johannes Berg + * + * GPL v2, can be found in COPYING. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "../soundbus.h" +#include "i2sbus.h" + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Johannes Berg "); +MODULE_DESCRIPTION("Apple Soundbus: I2S support"); +/* for auto-loading, declare that we handle this weird + * string that macio puts into the relevant device */ +MODULE_ALIAS("of:Ni2sTi2sC"); + +static struct of_device_id i2sbus_match[] = { + { .name = "i2s" }, + { } +}; + +static int alloc_dbdma_descriptor_ring(struct i2sbus_dev *i2sdev, + struct dbdma_command_mem *r, + int numcmds) +{ + /* one more for rounding */ + r->size = (numcmds+1) * sizeof(struct dbdma_cmd); + /* We use the PCI APIs for now until the generic one gets fixed + * enough or until we get some macio-specific versions + */ + r->space = dma_alloc_coherent( + &macio_get_pci_dev(i2sdev->macio)->dev, + r->size, + &r->bus_addr, + GFP_KERNEL); + + if (!r->space) return -ENOMEM; + + memset(r->space, 0, r->size); + r->cmds = (void*)DBDMA_ALIGN(r->space); + r->bus_cmd_start = r->bus_addr + + (dma_addr_t)((char*)r->cmds - (char*)r->space); + + return 0; +} + +static void free_dbdma_descriptor_ring(struct i2sbus_dev *i2sdev, + struct dbdma_command_mem *r) +{ + if (!r->space) return; + + dma_free_coherent(&macio_get_pci_dev(i2sdev->macio)->dev, + r->size, r->space, r->bus_addr); +} + +static void i2sbus_release_dev(struct device *dev) +{ + struct i2sbus_dev *i2sdev; + int i; + + i2sdev = container_of(dev, struct i2sbus_dev, sound.ofdev.dev); + + if (i2sdev->intfregs) iounmap(i2sdev->intfregs); + if (i2sdev->out.dbdma) iounmap(i2sdev->out.dbdma); + if (i2sdev->in.dbdma) iounmap(i2sdev->in.dbdma); + for (i=0;i<3;i++) + if (i2sdev->allocated_resource[i]) + release_and_free_resource(i2sdev->allocated_resource[i]); + free_dbdma_descriptor_ring(i2sdev, &i2sdev->out.dbdma_ring); + free_dbdma_descriptor_ring(i2sdev, &i2sdev->in.dbdma_ring); + for (i=0;i<3;i++) + free_irq(i2sdev->interrupts[i], i2sdev); + i2sbus_control_remove_dev(i2sdev->control, i2sdev); + mutex_destroy(&i2sdev->lock); + kfree(i2sdev); +} + +static irqreturn_t i2sbus_bus_intr(int irq, void *devid, struct pt_regs *regs) +{ + struct i2sbus_dev *dev = devid; + u32 intreg; + + spin_lock(&dev->low_lock); + intreg = in_le32(&dev->intfregs->intr_ctl); + + /* acknowledge interrupt reasons */ + out_le32(&dev->intfregs->intr_ctl, intreg); + + spin_unlock(&dev->low_lock); + + return IRQ_HANDLED; +} + +static int force; +module_param(force, int, 0444); +MODULE_PARM_DESC(force, "Force loading i2sbus even when" + " no layout-id property is present"); + +/* FIXME: look at device node refcounting */ +static int i2sbus_add_dev(struct macio_dev *macio, + struct i2sbus_control *control, + struct device_node *np) +{ + struct i2sbus_dev *dev; + struct device_node *child = NULL, *sound = NULL; + int i; + static const char *rnames[] = { "i2sbus: %s (control)", + "i2sbus: %s (tx)", + "i2sbus: %s (rx)" }; + static irqreturn_t (*ints[])(int irq, void *devid, + struct pt_regs *regs) = { + i2sbus_bus_intr, + i2sbus_tx_intr, + i2sbus_rx_intr + }; + + if (strlen(np->name) != 5) + return 0; + if (strncmp(np->name, "i2s-", 4)) + return 0; + + if (np->n_intrs != 3) + return 0; + + dev = kzalloc(sizeof(struct i2sbus_dev), GFP_KERNEL); + if (!dev) + return 0; + + i = 0; + while ((child = of_get_next_child(np, child))) { + if (strcmp(child->name, "sound") == 0) { + i++; + sound = child; + } + } + if (i == 1) { + u32 *layout_id; + layout_id = (u32*) get_property(sound, "layout-id", NULL); + if (layout_id) { + snprintf(dev->sound.modalias, 32, + "sound-layout-%d", *layout_id); + force = 1; + } + } + /* for the time being, until we can handle non-layout-id + * things in some fabric, refuse to attach if there is no + * layout-id property or we haven't been forced to attach. + * When there are two i2s busses and only one has a layout-id, + * then this depends on the order, but that isn't important + * either as the second one in that case is just a modem. */ + if (!force) { + kfree(dev); + return -ENODEV; + } + + mutex_init(&dev->lock); + spin_lock_init(&dev->low_lock); + dev->sound.ofdev.node = np; + dev->sound.ofdev.dma_mask = macio->ofdev.dma_mask; + dev->sound.ofdev.dev.dma_mask = &dev->sound.ofdev.dma_mask; + dev->sound.ofdev.dev.parent = &macio->ofdev.dev; + dev->sound.ofdev.dev.release = i2sbus_release_dev; + dev->sound.attach_codec = i2sbus_attach_codec; + dev->sound.detach_codec = i2sbus_detach_codec; + dev->sound.pcmid = -1; + dev->macio = macio; + dev->control = control; + dev->bus_number = np->name[4] - 'a'; + INIT_LIST_HEAD(&dev->sound.codec_list); + + for (i=0;i<3;i++) { + dev->interrupts[i] = -1; + snprintf(dev->rnames[i], sizeof(dev->rnames[i]), rnames[i], np->name); + } + for (i=0;i<3;i++) { + if (request_irq(np->intrs[i].line, ints[i], 0, dev->rnames[i], dev)) + goto err; + dev->interrupts[i] = np->intrs[i].line; + } + + for (i=0;i<3;i++) { + if (of_address_to_resource(np, i, &dev->resources[i])) + goto err; + /* if only we could use our resource dev->resources[i]... + * but request_resource doesn't know about parents and + * contained resources... */ + dev->allocated_resource[i] = + request_mem_region(dev->resources[i].start, + dev->resources[i].end - + dev->resources[i].start + 1, + dev->rnames[i]); + if (!dev->allocated_resource[i]) { + printk(KERN_ERR "i2sbus: failed to claim resource %d!\n", i); + goto err; + } + } + /* should do sanity checking here about length of them */ + dev->intfregs = ioremap(dev->resources[0].start, + dev->resources[0].end-dev->resources[0].start+1); + dev->out.dbdma = ioremap(dev->resources[1].start, + dev->resources[1].end-dev->resources[1].start+1); + dev->in.dbdma = ioremap(dev->resources[2].start, + dev->resources[2].end-dev->resources[2].start+1); + if (!dev->intfregs || !dev->out.dbdma || !dev->in.dbdma) + goto err; + + if (alloc_dbdma_descriptor_ring(dev, &dev->out.dbdma_ring, + MAX_DBDMA_COMMANDS)) + goto err; + if (alloc_dbdma_descriptor_ring(dev, &dev->in.dbdma_ring, + MAX_DBDMA_COMMANDS)) + goto err; + + if (i2sbus_control_add_dev(dev->control, dev)) { + printk(KERN_ERR "i2sbus: control layer didn't like bus\n"); + goto err; + } + + if (soundbus_add_one(&dev->sound)) { + printk(KERN_DEBUG "i2sbus: device registration error!\n"); + goto err; + } + + /* enable this cell */ + i2sbus_control_cell(dev->control, dev, 1); + i2sbus_control_enable(dev->control, dev); + i2sbus_control_clock(dev->control, dev, 1); + + return 1; + err: + for (i=0;i<3;i++) + if (dev->interrupts[i] != -1) + free_irq(dev->interrupts[i], dev); + free_dbdma_descriptor_ring(dev, &dev->out.dbdma_ring); + free_dbdma_descriptor_ring(dev, &dev->in.dbdma_ring); + if (dev->intfregs) iounmap(dev->intfregs); + if (dev->out.dbdma) iounmap(dev->out.dbdma); + if (dev->in.dbdma) iounmap(dev->in.dbdma); + for (i=0;i<3;i++) + if (dev->allocated_resource[i]) + release_and_free_resource(dev->allocated_resource[i]); + mutex_destroy(&dev->lock); + kfree(dev); + return 0; +} + +static int i2sbus_probe(struct macio_dev* dev, const struct of_device_id *match) +{ + struct device_node *np = NULL; + int got = 0, err; + struct i2sbus_control *control = NULL; + + err = i2sbus_control_init(dev, &control); + if (err) + return err; + if (!control) { + printk(KERN_ERR "i2sbus_control_init API breakage\n"); + return -ENODEV; + } + + while ((np = of_get_next_child(dev->ofdev.node, np))) { + if (device_is_compatible(np, "i2sbus") || + device_is_compatible(np, "i2s-modem")) { + got += i2sbus_add_dev(dev, control, np); + } + } + + if (!got) { + /* found none, clean up */ + i2sbus_control_destroy(control); + return -ENODEV; + } + + dev->ofdev.dev.driver_data = control; + + return 0; +} + +static int i2sbus_remove(struct macio_dev* dev) +{ + struct i2sbus_control *control = dev->ofdev.dev.driver_data; + struct i2sbus_dev *i2sdev, *tmp; + + list_for_each_entry_safe(i2sdev, tmp, &control->list, item) + soundbus_remove_one(&i2sdev->sound); + + return 0; +} + +#ifdef CONFIG_PM +static int i2sbus_suspend(struct macio_dev* dev, pm_message_t state) +{ + struct i2sbus_control *control = dev->ofdev.dev.driver_data; + struct codec_info_item *cii; + struct i2sbus_dev* i2sdev; + int err, ret = 0; + + list_for_each_entry(i2sdev, &control->list, item) { + /* Notify Alsa */ + if (i2sdev->sound.pcm) { + /* Suspend PCM streams */ + snd_pcm_suspend_all(i2sdev->sound.pcm); + /* Probably useless as we handle + * power transitions ourselves */ + snd_power_change_state(i2sdev->sound.pcm->card, + SNDRV_CTL_POWER_D3hot); + } + /* Notify codecs */ + list_for_each_entry(cii, &i2sdev->sound.codec_list, list) { + err = 0; + if (cii->codec->suspend) + err = cii->codec->suspend(cii, state); + if (err) + ret = err; + } + } + return ret; +} + +static int i2sbus_resume(struct macio_dev* dev) +{ + struct i2sbus_control *control = dev->ofdev.dev.driver_data; + struct codec_info_item *cii; + struct i2sbus_dev* i2sdev; + int err, ret = 0; + + list_for_each_entry(i2sdev, &control->list, item) { + /* Notify codecs so they can re-initialize */ + list_for_each_entry(cii, &i2sdev->sound.codec_list, list) { + err = 0; + if (cii->codec->resume) + err = cii->codec->resume(cii); + if (err) + ret = err; + } + /* Notify Alsa */ + if (i2sdev->sound.pcm) { + /* Same comment as above, probably useless */ + snd_power_change_state(i2sdev->sound.pcm->card, + SNDRV_CTL_POWER_D0); + } + } + + return ret; +} +#endif /* CONFIG_PM */ + +static int i2sbus_shutdown(struct macio_dev* dev) +{ + return 0; +} + +static struct macio_driver i2sbus_drv = { + .name = "soundbus-i2s", + .owner = THIS_MODULE, + .match_table = i2sbus_match, + .probe = i2sbus_probe, + .remove = i2sbus_remove, +#ifdef CONFIG_PM + .suspend = i2sbus_suspend, + .resume = i2sbus_resume, +#endif + .shutdown = i2sbus_shutdown, +}; + +static int __init soundbus_i2sbus_init(void) +{ + return macio_register_driver(&i2sbus_drv); +} + +static void __exit soundbus_i2sbus_exit(void) +{ + macio_unregister_driver(&i2sbus_drv); +} + +module_init(soundbus_i2sbus_init); +module_exit(soundbus_i2sbus_exit); diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-interface.h b/sound/aoa/soundbus/i2sbus/i2sbus-interface.h new file mode 100644 index 00000000000..c6b5f5452d2 --- /dev/null +++ b/sound/aoa/soundbus/i2sbus/i2sbus-interface.h @@ -0,0 +1,187 @@ +/* + * i2sbus driver -- interface register definitions + * + * Copyright 2006 Johannes Berg + * + * GPL v2, can be found in COPYING. + */ +#ifndef __I2SBUS_INTERFACE_H +#define __I2SBUS_INTERFACE_H + +/* i2s bus control registers, at least what we know about them */ + +#define __PAD(m,n) u8 __pad##m[n] +#define _PAD(line, n) __PAD(line, n) +#define PAD(n) _PAD(__LINE__, (n)) +struct i2s_interface_regs { + __le32 intr_ctl; /* 0x00 */ + PAD(12); + __le32 serial_format; /* 0x10 */ + PAD(12); + __le32 codec_msg_out; /* 0x20 */ + PAD(12); + __le32 codec_msg_in; /* 0x30 */ + PAD(12); + __le32 frame_count; /* 0x40 */ + PAD(12); + __le32 frame_match; /* 0x50 */ + PAD(12); + __le32 data_word_sizes; /* 0x60 */ + PAD(12); + __le32 peak_level_sel; /* 0x70 */ + PAD(12); + __le32 peak_level_in0; /* 0x80 */ + PAD(12); + __le32 peak_level_in1; /* 0x90 */ + PAD(12); + /* total size: 0x100 bytes */ +} __attribute__((__packed__)); + +/* interrupt register is just a bitfield with + * interrupt enable and pending bits */ +#define I2S_REG_INTR_CTL 0x00 +# define I2S_INT_FRAME_COUNT (1<<31) +# define I2S_PENDING_FRAME_COUNT (1<<30) +# define I2S_INT_MESSAGE_FLAG (1<<29) +# define I2S_PENDING_MESSAGE_FLAG (1<<28) +# define I2S_INT_NEW_PEAK (1<<27) +# define I2S_PENDING_NEW_PEAK (1<<26) +# define I2S_INT_CLOCKS_STOPPED (1<<25) +# define I2S_PENDING_CLOCKS_STOPPED (1<<24) +# define I2S_INT_EXTERNAL_SYNC_ERROR (1<<23) +# define I2S_PENDING_EXTERNAL_SYNC_ERROR (1<<22) +# define I2S_INT_EXTERNAL_SYNC_OK (1<<21) +# define I2S_PENDING_EXTERNAL_SYNC_OK (1<<20) +# define I2S_INT_NEW_SAMPLE_RATE (1<<19) +# define I2S_PENDING_NEW_SAMPLE_RATE (1<<18) +# define I2S_INT_STATUS_FLAG (1<<17) +# define I2S_PENDING_STATUS_FLAG (1<<16) + +/* serial format register is more interesting :) + * It contains: + * - clock source + * - MClk divisor + * - SClk divisor + * - SClk master flag + * - serial format (sony, i2s 64x, i2s 32x, dav, silabs) + * - external sample frequency interrupt (don't understand) + * - external sample frequency + */ +#define I2S_REG_SERIAL_FORMAT 0x10 +/* clock source. You get either 18.432, 45.1584 or 49.1520 MHz */ +# define I2S_SF_CLOCK_SOURCE_SHIFT 30 +# define I2S_SF_CLOCK_SOURCE_MASK (3< + * + * GPL v2, can be found in COPYING. + */ + +#include +#include +/* So apparently there's a reason for requiring driver.h + * to be included first, even if I don't know it... */ +#include +#include +#include +#include +#include "../soundbus.h" +#include "i2sbus.h" + +static inline void get_pcm_info(struct i2sbus_dev *i2sdev, int in, + struct pcm_info **pi, struct pcm_info **other) +{ + if (in) { + if (pi) + *pi = &i2sdev->in; + if (other) + *other = &i2sdev->out; + } else { + if (pi) + *pi = &i2sdev->out; + if (other) + *other = &i2sdev->in; + } +} + +static int clock_and_divisors(int mclk, int sclk, int rate, int *out) +{ + /* sclk must be derived from mclk! */ + if (mclk % sclk) + return -1; + /* derive sclk register value */ + if (i2s_sf_sclkdiv(mclk / sclk, out)) + return -1; + + if (I2S_CLOCK_SPEED_18MHz % (rate * mclk) == 0) { + if (!i2s_sf_mclkdiv(I2S_CLOCK_SPEED_18MHz / (rate * mclk), out)) { + *out |= I2S_SF_CLOCK_SOURCE_18MHz; + return 0; + } + } + if (I2S_CLOCK_SPEED_45MHz % (rate * mclk) == 0) { + if (!i2s_sf_mclkdiv(I2S_CLOCK_SPEED_45MHz / (rate * mclk), out)) { + *out |= I2S_SF_CLOCK_SOURCE_45MHz; + return 0; + } + } + if (I2S_CLOCK_SPEED_49MHz % (rate * mclk) == 0) { + if (!i2s_sf_mclkdiv(I2S_CLOCK_SPEED_49MHz / (rate * mclk), out)) { + *out |= I2S_SF_CLOCK_SOURCE_49MHz; + return 0; + } + } + return -1; +} + +#define CHECK_RATE(rate) \ + do { if (rates & SNDRV_PCM_RATE_ ##rate) { \ + int dummy; \ + if (clock_and_divisors(sysclock_factor, \ + bus_factor, rate, &dummy)) \ + rates &= ~SNDRV_PCM_RATE_ ##rate; \ + } } while (0) + +static int i2sbus_pcm_open(struct i2sbus_dev *i2sdev, int in) +{ + struct pcm_info *pi, *other; + struct soundbus_dev *sdev; + int masks_inited = 0, err; + struct codec_info_item *cii, *rev; + struct snd_pcm_hardware *hw; + u64 formats = 0; + unsigned int rates = 0; + struct transfer_info v; + int result = 0; + int bus_factor = 0, sysclock_factor = 0; + int found_this; + + mutex_lock(&i2sdev->lock); + + get_pcm_info(i2sdev, in, &pi, &other); + + hw = &pi->substream->runtime->hw; + sdev = &i2sdev->sound; + + if (pi->active) { + /* alsa messed up */ + result = -EBUSY; + goto out_unlock; + } + + /* we now need to assign the hw */ + list_for_each_entry(cii, &sdev->codec_list, list) { + struct transfer_info *ti = cii->codec->transfers; + bus_factor = cii->codec->bus_factor; + sysclock_factor = cii->codec->sysclock_factor; + while (ti->formats && ti->rates) { + v = *ti; + if (ti->transfer_in == in + && cii->codec->usable(cii, ti, &v)) { + if (masks_inited) { + formats &= v.formats; + rates &= v.rates; + } else { + formats = v.formats; + rates = v.rates; + masks_inited = 1; + } + } + ti++; + } + } + if (!masks_inited || !bus_factor || !sysclock_factor) { + result = -ENODEV; + goto out_unlock; + } + /* bus dependent stuff */ + hw->info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_RESUME; + + CHECK_RATE(5512); + CHECK_RATE(8000); + CHECK_RATE(11025); + CHECK_RATE(16000); + CHECK_RATE(22050); + CHECK_RATE(32000); + CHECK_RATE(44100); + CHECK_RATE(48000); + CHECK_RATE(64000); + CHECK_RATE(88200); + CHECK_RATE(96000); + CHECK_RATE(176400); + CHECK_RATE(192000); + hw->rates = rates; + + /* well. the codec might want 24 bits only, and we'll + * ever only transfer 24 bits, but they are top-aligned! + * So for alsa, we claim that we're doing full 32 bit + * while in reality we'll ignore the lower 8 bits of + * that when doing playback (they're transferred as 0 + * as far as I know, no codecs we have are 32-bit capable + * so I can't really test) and when doing recording we'll + * always have those lower 8 bits recorded as 0 */ + if (formats & SNDRV_PCM_FMTBIT_S24_BE) + formats |= SNDRV_PCM_FMTBIT_S32_BE; + if (formats & SNDRV_PCM_FMTBIT_U24_BE) + formats |= SNDRV_PCM_FMTBIT_U32_BE; + /* now mask off what we can support. I suppose we could + * also support S24_3LE and some similar formats, but I + * doubt there's a codec that would be able to use that, + * so we don't support it here. */ + hw->formats = formats & (SNDRV_PCM_FMTBIT_S16_BE | + SNDRV_PCM_FMTBIT_U16_BE | + SNDRV_PCM_FMTBIT_S32_BE | + SNDRV_PCM_FMTBIT_U32_BE); + + /* we need to set the highest and lowest rate possible. + * These are the highest and lowest rates alsa can + * support properly in its bitfield. + * Below, we'll use that to restrict to the rate + * currently in use (if any). */ + hw->rate_min = 5512; + hw->rate_max = 192000; + /* if the other stream is active, then we can only + * support what it is currently using. + * FIXME: I lied. This comment is wrong. We can support + * anything that works with the same serial format, ie. + * when recording 24 bit sound we can well play 16 bit + * sound at the same time iff using the same transfer mode. + */ + if (other->active) { + /* FIXME: is this guaranteed by the alsa api? */ + hw->formats &= (1ULL << i2sdev->format); + /* see above, restrict rates to the one we already have */ + hw->rate_min = i2sdev->rate; + hw->rate_max = i2sdev->rate; + } + + hw->channels_min = 2; + hw->channels_max = 2; + /* these are somewhat arbitrary */ + hw->buffer_bytes_max = 131072; + hw->period_bytes_min = 256; + hw->period_bytes_max = 16384; + hw->periods_min = 3; + hw->periods_max = MAX_DBDMA_COMMANDS; + list_for_each_entry(cii, &sdev->codec_list, list) { + if (cii->codec->open) { + err = cii->codec->open(cii, pi->substream); + if (err) { + result = err; + /* unwind */ + found_this = 0; + list_for_each_entry_reverse(rev, + &sdev->codec_list, list) { + if (found_this && rev->codec->close) { + rev->codec->close(rev, + pi->substream); + } + if (rev == cii) + found_this = 1; + } + goto out_unlock; + } + } + } + + out_unlock: + mutex_unlock(&i2sdev->lock); + return result; +} + +#undef CHECK_RATE + +static int i2sbus_pcm_close(struct i2sbus_dev *i2sdev, int in) +{ + struct codec_info_item *cii; + struct pcm_info *pi; + int err = 0, tmp; + + mutex_lock(&i2sdev->lock); + + get_pcm_info(i2sdev, in, &pi, NULL); + + list_for_each_entry(cii, &i2sdev->sound.codec_list, list) { + if (cii->codec->close) { + tmp = cii->codec->close(cii, pi->substream); + if (tmp) + err = tmp; + } + } + + pi->substream = NULL; + pi->active = 0; + mutex_unlock(&i2sdev->lock); + return err; +} + +static int i2sbus_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); +} + +static int i2sbus_hw_free(struct snd_pcm_substream *substream) +{ + snd_pcm_lib_free_pages(substream); + return 0; +} + +static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in) +{ + /* whee. Hard work now. The user has selected a bitrate + * and bit format, so now we have to program our + * I2S controller appropriately. */ + struct snd_pcm_runtime *runtime; + struct dbdma_cmd *command; + int i, periodsize; + dma_addr_t offset; + struct bus_info bi; + struct codec_info_item *cii; + int sfr = 0; /* serial format register */ + int dws = 0; /* data word sizes reg */ + int input_16bit; + struct pcm_info *pi, *other; + int cnt; + int result = 0; + + mutex_lock(&i2sdev->lock); + + get_pcm_info(i2sdev, in, &pi, &other); + + if (pi->dbdma_ring.running) { + result = -EBUSY; + goto out_unlock; + } + + runtime = pi->substream->runtime; + pi->active = 1; + if (other->active && + ((i2sdev->format != runtime->format) + || (i2sdev->rate != runtime->rate))) { + result = -EINVAL; + goto out_unlock; + } + + i2sdev->format = runtime->format; + i2sdev->rate = runtime->rate; + + periodsize = snd_pcm_lib_period_bytes(pi->substream); + pi->current_period = 0; + + /* generate dbdma command ring first */ + command = pi->dbdma_ring.cmds; + offset = runtime->dma_addr; + for (i = 0; i < pi->substream->runtime->periods; + i++, command++, offset += periodsize) { + memset(command, 0, sizeof(struct dbdma_cmd)); + command->command = + cpu_to_le16((in ? INPUT_MORE : OUTPUT_MORE) | INTR_ALWAYS); + command->phy_addr = cpu_to_le32(offset); + command->req_count = cpu_to_le16(periodsize); + command->xfer_status = cpu_to_le16(0); + } + /* last one branches back to first */ + command--; + command->command |= cpu_to_le16(BR_ALWAYS); + command->cmd_dep = cpu_to_le32(pi->dbdma_ring.bus_cmd_start); + + /* ok, let's set the serial format and stuff */ + switch (runtime->format) { + /* 16 bit formats */ + case SNDRV_PCM_FORMAT_S16_BE: + case SNDRV_PCM_FORMAT_U16_BE: + /* FIXME: if we add different bus factors we need to + * do more here!! */ + bi.bus_factor = 0; + list_for_each_entry(cii, &i2sdev->sound.codec_list, list) { + bi.bus_factor = cii->codec->bus_factor; + break; + } + if (!bi.bus_factor) { + result = -ENODEV; + goto out_unlock; + } + input_16bit = 1; + break; + case SNDRV_PCM_FORMAT_S32_BE: + case SNDRV_PCM_FORMAT_U32_BE: + /* force 64x bus speed, otherwise the data cannot be + * transferred quickly enough! */ + bi.bus_factor = 64; + input_16bit = 0; + break; + default: + result = -EINVAL; + goto out_unlock; + } + /* we assume all sysclocks are the same! */ + list_for_each_entry(cii, &i2sdev->sound.codec_list, list) { + bi.sysclock_factor = cii->codec->sysclock_factor; + break; + } + + if (clock_and_divisors(bi.sysclock_factor, + bi.bus_factor, + runtime->rate, + &sfr) < 0) { + result = -EINVAL; + goto out_unlock; + } + switch (bi.bus_factor) { + case 32: + sfr |= I2S_SF_SERIAL_FORMAT_I2S_32X; + break; + case 64: + sfr |= I2S_SF_SERIAL_FORMAT_I2S_64X; + break; + } + /* FIXME: THIS ASSUMES MASTER ALL THE TIME */ + sfr |= I2S_SF_SCLK_MASTER; + + list_for_each_entry(cii, &i2sdev->sound.codec_list, list) { + int err = 0; + if (cii->codec->prepare) + err = cii->codec->prepare(cii, &bi, pi->substream); + if (err) { + result = err; + goto out_unlock; + } + } + /* codecs are fine with it, so set our clocks */ + if (input_16bit) + dws = (2 << I2S_DWS_NUM_CHANNELS_IN_SHIFT) | + (2 << I2S_DWS_NUM_CHANNELS_OUT_SHIFT) | + I2S_DWS_DATA_IN_16BIT | I2S_DWS_DATA_OUT_16BIT; + else + dws = (2 << I2S_DWS_NUM_CHANNELS_IN_SHIFT) | + (2 << I2S_DWS_NUM_CHANNELS_OUT_SHIFT) | + I2S_DWS_DATA_IN_24BIT | I2S_DWS_DATA_OUT_24BIT; + + /* early exit if already programmed correctly */ + /* not locking these is fine since we touch them only in this function */ + if (in_le32(&i2sdev->intfregs->serial_format) == sfr + && in_le32(&i2sdev->intfregs->data_word_sizes) == dws) + goto out_unlock; + + /* let's notify the codecs about clocks going away. + * For now we only do mastering on the i2s cell... */ + list_for_each_entry(cii, &i2sdev->sound.codec_list, list) + if (cii->codec->switch_clock) + cii->codec->switch_clock(cii, CLOCK_SWITCH_PREPARE_SLAVE); + + i2sbus_control_enable(i2sdev->control, i2sdev); + i2sbus_control_cell(i2sdev->control, i2sdev, 1); + + out_le32(&i2sdev->intfregs->intr_ctl, I2S_PENDING_CLOCKS_STOPPED); + + i2sbus_control_clock(i2sdev->control, i2sdev, 0); + + msleep(1); + + /* wait for clock stopped. This can apparently take a while... */ + cnt = 100; + while (cnt-- && + !(in_le32(&i2sdev->intfregs->intr_ctl) & I2S_PENDING_CLOCKS_STOPPED)) { + msleep(5); + } + out_le32(&i2sdev->intfregs->intr_ctl, I2S_PENDING_CLOCKS_STOPPED); + + /* not locking these is fine since we touch them only in this function */ + out_le32(&i2sdev->intfregs->serial_format, sfr); + out_le32(&i2sdev->intfregs->data_word_sizes, dws); + + i2sbus_control_enable(i2sdev->control, i2sdev); + i2sbus_control_cell(i2sdev->control, i2sdev, 1); + i2sbus_control_clock(i2sdev->control, i2sdev, 1); + msleep(1); + + list_for_each_entry(cii, &i2sdev->sound.codec_list, list) + if (cii->codec->switch_clock) + cii->codec->switch_clock(cii, CLOCK_SWITCH_SLAVE); + + out_unlock: + mutex_unlock(&i2sdev->lock); + return result; +} + +static struct dbdma_cmd STOP_CMD = { + .command = __constant_cpu_to_le16(DBDMA_STOP), +}; + +static int i2sbus_pcm_trigger(struct i2sbus_dev *i2sdev, int in, int cmd) +{ + struct codec_info_item *cii; + struct pcm_info *pi; + int timeout; + struct dbdma_cmd tmp; + int result = 0; + unsigned long flags; + + spin_lock_irqsave(&i2sdev->low_lock, flags); + + get_pcm_info(i2sdev, in, &pi, NULL); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + if (pi->dbdma_ring.running) { + result = -EALREADY; + goto out_unlock; + } + list_for_each_entry(cii, &i2sdev->sound.codec_list, list) + if (cii->codec->start) + cii->codec->start(cii, pi->substream); + pi->dbdma_ring.running = 1; + + /* reset dma engine */ + out_le32(&pi->dbdma->control, + 0 | (RUN | PAUSE | FLUSH | WAKE) << 16); + timeout = 100; + while (in_le32(&pi->dbdma->status) & RUN && timeout--) + udelay(1); + if (timeout <= 0) { + printk(KERN_ERR + "i2sbus: error waiting for dma reset\n"); + result = -ENXIO; + goto out_unlock; + } + + /* write dma command buffer address to the dbdma chip */ + out_le32(&pi->dbdma->cmdptr, pi->dbdma_ring.bus_cmd_start); + /* post PCI write */ + mb(); + (void)in_le32(&pi->dbdma->status); + + /* change first command to STOP */ + tmp = *pi->dbdma_ring.cmds; + *pi->dbdma_ring.cmds = STOP_CMD; + + /* set running state, remember that the first command is STOP */ + out_le32(&pi->dbdma->control, RUN | (RUN << 16)); + timeout = 100; + /* wait for STOP to be executed */ + while (in_le32(&pi->dbdma->status) & ACTIVE && timeout--) + udelay(1); + if (timeout <= 0) { + printk(KERN_ERR "i2sbus: error waiting for dma stop\n"); + result = -ENXIO; + goto out_unlock; + } + /* again, write dma command buffer address to the dbdma chip, + * this time of the first real command */ + *pi->dbdma_ring.cmds = tmp; + out_le32(&pi->dbdma->cmdptr, pi->dbdma_ring.bus_cmd_start); + /* post write */ + mb(); + (void)in_le32(&pi->dbdma->status); + + /* reset dma engine again */ + out_le32(&pi->dbdma->control, + 0 | (RUN | PAUSE | FLUSH | WAKE) << 16); + timeout = 100; + while (in_le32(&pi->dbdma->status) & RUN && timeout--) + udelay(1); + if (timeout <= 0) { + printk(KERN_ERR + "i2sbus: error waiting for dma reset\n"); + result = -ENXIO; + goto out_unlock; + } + + /* wake up the chip with the next descriptor */ + out_le32(&pi->dbdma->control, + (RUN | WAKE) | ((RUN | WAKE) << 16)); + /* get the frame count */ + pi->frame_count = in_le32(&i2sdev->intfregs->frame_count); + + /* off you go! */ + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + if (!pi->dbdma_ring.running) { + result = -EALREADY; + goto out_unlock; + } + + /* turn off all relevant bits */ + out_le32(&pi->dbdma->control, + (RUN | WAKE | FLUSH | PAUSE) << 16); + { + /* FIXME: move to own function */ + int timeout = 5000; + while ((in_le32(&pi->dbdma->status) & RUN) + && --timeout > 0) + udelay(1); + if (!timeout) + printk(KERN_ERR + "i2sbus: timed out turning " + "off dbdma engine!\n"); + } + + pi->dbdma_ring.running = 0; + list_for_each_entry(cii, &i2sdev->sound.codec_list, list) + if (cii->codec->stop) + cii->codec->stop(cii, pi->substream); + break; + default: + result = -EINVAL; + goto out_unlock; + } + + out_unlock: + spin_unlock_irqrestore(&i2sdev->low_lock, flags); + return result; +} + +static snd_pcm_uframes_t i2sbus_pcm_pointer(struct i2sbus_dev *i2sdev, int in) +{ + struct pcm_info *pi; + u32 fc; + + get_pcm_info(i2sdev, in, &pi, NULL); + + fc = in_le32(&i2sdev->intfregs->frame_count); + fc = fc - pi->frame_count; + + return (bytes_to_frames(pi->substream->runtime, + pi->current_period * + snd_pcm_lib_period_bytes(pi->substream)) + + fc) % pi->substream->runtime->buffer_size; +} + +static inline void handle_interrupt(struct i2sbus_dev *i2sdev, int in) +{ + struct pcm_info *pi; + u32 fc; + u32 delta; + + spin_lock(&i2sdev->low_lock); + get_pcm_info(i2sdev, in, &pi, NULL); + + if (!pi->dbdma_ring.running) { + /* there was still an interrupt pending + * while we stopped. or maybe another + * processor (not the one that was stopping + * the DMA engine) was spinning above + * waiting for the lock. */ + goto out_unlock; + } + + fc = in_le32(&i2sdev->intfregs->frame_count); + /* a counter overflow does not change the calculation. */ + delta = fc - pi->frame_count; + + /* update current_period */ + while (delta >= pi->substream->runtime->period_size) { + pi->current_period++; + delta = delta - pi->substream->runtime->period_size; + } + + if (unlikely(delta)) { + /* Some interrupt came late, so check the dbdma. + * This special case exists to syncronize the frame_count with + * the dbdma transfer, but is hit every once in a while. */ + int period; + + period = (in_le32(&pi->dbdma->cmdptr) + - pi->dbdma_ring.bus_cmd_start) + / sizeof(struct dbdma_cmd); + pi->current_period = pi->current_period + % pi->substream->runtime->periods; + + while (pi->current_period != period) { + pi->current_period++; + pi->current_period %= pi->substream->runtime->periods; + /* Set delta to zero, as the frame_count value is too + * high (otherwise the code path will not be executed). + * This corrects the fact that the frame_count is too + * low at the beginning due to buffering. */ + delta = 0; + } + } + + pi->frame_count = fc - delta; + pi->current_period %= pi->substream->runtime->periods; + + spin_unlock(&i2sdev->low_lock); + /* may call _trigger again, hence needs to be unlocked */ + snd_pcm_period_elapsed(pi->substream); + return; + out_unlock: + spin_unlock(&i2sdev->low_lock); +} + +irqreturn_t i2sbus_tx_intr(int irq, void *devid, struct pt_regs *regs) +{ + handle_interrupt((struct i2sbus_dev *)devid, 0); + return IRQ_HANDLED; +} + +irqreturn_t i2sbus_rx_intr(int irq, void *devid, struct pt_regs * regs) +{ + handle_interrupt((struct i2sbus_dev *)devid, 1); + return IRQ_HANDLED; +} + +static int i2sbus_playback_open(struct snd_pcm_substream *substream) +{ + struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); + + if (!i2sdev) + return -EINVAL; + i2sdev->out.substream = substream; + return i2sbus_pcm_open(i2sdev, 0); +} + +static int i2sbus_playback_close(struct snd_pcm_substream *substream) +{ + struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); + int err; + + if (!i2sdev) + return -EINVAL; + if (i2sdev->out.substream != substream) + return -EINVAL; + err = i2sbus_pcm_close(i2sdev, 0); + if (!err) + i2sdev->out.substream = NULL; + return err; +} + +static int i2sbus_playback_prepare(struct snd_pcm_substream *substream) +{ + struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); + + if (!i2sdev) + return -EINVAL; + if (i2sdev->out.substream != substream) + return -EINVAL; + return i2sbus_pcm_prepare(i2sdev, 0); +} + +static int i2sbus_playback_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); + + if (!i2sdev) + return -EINVAL; + if (i2sdev->out.substream != substream) + return -EINVAL; + return i2sbus_pcm_trigger(i2sdev, 0, cmd); +} + +static snd_pcm_uframes_t i2sbus_playback_pointer(struct snd_pcm_substream + *substream) +{ + struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); + + if (!i2sdev) + return -EINVAL; + if (i2sdev->out.substream != substream) + return 0; + return i2sbus_pcm_pointer(i2sdev, 0); +} + +static struct snd_pcm_ops i2sbus_playback_ops = { + .open = i2sbus_playback_open, + .close = i2sbus_playback_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = i2sbus_hw_params, + .hw_free = i2sbus_hw_free, + .prepare = i2sbus_playback_prepare, + .trigger = i2sbus_playback_trigger, + .pointer = i2sbus_playback_pointer, +}; + +static int i2sbus_record_open(struct snd_pcm_substream *substream) +{ + struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); + + if (!i2sdev) + return -EINVAL; + i2sdev->in.substream = substream; + return i2sbus_pcm_open(i2sdev, 1); +} + +static int i2sbus_record_close(struct snd_pcm_substream *substream) +{ + struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); + int err; + + if (!i2sdev) + return -EINVAL; + if (i2sdev->in.substream != substream) + return -EINVAL; + err = i2sbus_pcm_close(i2sdev, 1); + if (!err) + i2sdev->in.substream = NULL; + return err; +} + +static int i2sbus_record_prepare(struct snd_pcm_substream *substream) +{ + struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); + + if (!i2sdev) + return -EINVAL; + if (i2sdev->in.substream != substream) + return -EINVAL; + return i2sbus_pcm_prepare(i2sdev, 1); +} + +static int i2sbus_record_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); + + if (!i2sdev) + return -EINVAL; + if (i2sdev->in.substream != substream) + return -EINVAL; + return i2sbus_pcm_trigger(i2sdev, 1, cmd); +} + +static snd_pcm_uframes_t i2sbus_record_pointer(struct snd_pcm_substream + *substream) +{ + struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); + + if (!i2sdev) + return -EINVAL; + if (i2sdev->in.substream != substream) + return 0; + return i2sbus_pcm_pointer(i2sdev, 1); +} + +static struct snd_pcm_ops i2sbus_record_ops = { + .open = i2sbus_record_open, + .close = i2sbus_record_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = i2sbus_hw_params, + .hw_free = i2sbus_hw_free, + .prepare = i2sbus_record_prepare, + .trigger = i2sbus_record_trigger, + .pointer = i2sbus_record_pointer, +}; + +static void i2sbus_private_free(struct snd_pcm *pcm) +{ + struct i2sbus_dev *i2sdev = snd_pcm_chip(pcm); + struct codec_info_item *p, *tmp; + + i2sdev->sound.pcm = NULL; + i2sdev->out.created = 0; + i2sdev->in.created = 0; + list_for_each_entry_safe(p, tmp, &i2sdev->sound.codec_list, list) { + printk(KERN_ERR "i2sbus: a codec didn't unregister!\n"); + list_del(&p->list); + module_put(p->codec->owner); + kfree(p); + } + soundbus_dev_put(&i2sdev->sound); + module_put(THIS_MODULE); +} + +/* FIXME: this function needs an error handling strategy with labels */ +int +i2sbus_attach_codec(struct soundbus_dev *dev, struct snd_card *card, + struct codec_info *ci, void *data) +{ + int err, in = 0, out = 0; + struct transfer_info *tmp; + struct i2sbus_dev *i2sdev = soundbus_dev_to_i2sbus_dev(dev); + struct codec_info_item *cii; + + if (!dev->pcmname || dev->pcmid == -1) { + printk(KERN_ERR "i2sbus: pcm name and id must be set!\n"); + return -EINVAL; + } + + list_for_each_entry(cii, &dev->codec_list, list) { + if (cii->codec_data == data) + return -EALREADY; + } + + if (!ci->transfers || !ci->transfers->formats + || !ci->transfers->rates || !ci->usable) + return -EINVAL; + + /* we currently code the i2s transfer on the clock, and support only + * 32 and 64 */ + if (ci->bus_factor != 32 && ci->bus_factor != 64) + return -EINVAL; + + /* If you want to fix this, you need to keep track of what transport infos + * are to be used, which codecs they belong to, and then fix all the + * sysclock/busclock stuff above to depend on which is usable */ + list_for_each_entry(cii, &dev->codec_list, list) { + if (cii->codec->sysclock_factor != ci->sysclock_factor) { + printk(KERN_DEBUG + "cannot yet handle multiple different sysclocks!\n"); + return -EINVAL; + } + if (cii->codec->bus_factor != ci->bus_factor) { + printk(KERN_DEBUG + "cannot yet handle multiple different bus clocks!\n"); + return -EINVAL; + } + } + + tmp = ci->transfers; + while (tmp->formats && tmp->rates) { + if (tmp->transfer_in) + in = 1; + else + out = 1; + tmp++; + } + + cii = kzalloc(sizeof(struct codec_info_item), GFP_KERNEL); + if (!cii) { + printk(KERN_DEBUG "i2sbus: failed to allocate cii\n"); + return -ENOMEM; + } + + /* use the private data to point to the codec info */ + cii->sdev = soundbus_dev_get(dev); + cii->codec = ci; + cii->codec_data = data; + + if (!cii->sdev) { + printk(KERN_DEBUG + "i2sbus: failed to get soundbus dev reference\n"); + kfree(cii); + return -ENODEV; + } + + if (!try_module_get(THIS_MODULE)) { + printk(KERN_DEBUG "i2sbus: failed to get module reference!\n"); + soundbus_dev_put(dev); + kfree(cii); + return -EBUSY; + } + + if (!try_module_get(ci->owner)) { + printk(KERN_DEBUG + "i2sbus: failed to get module reference to codec owner!\n"); + module_put(THIS_MODULE); + soundbus_dev_put(dev); + kfree(cii); + return -EBUSY; + } + + if (!dev->pcm) { + err = snd_pcm_new(card, + dev->pcmname, + dev->pcmid, + 0, + 0, + &dev->pcm); + if (err) { + printk(KERN_DEBUG "i2sbus: failed to create pcm\n"); + kfree(cii); + module_put(ci->owner); + soundbus_dev_put(dev); + module_put(THIS_MODULE); + return err; + } + } + + /* ALSA yet again sucks. + * If it is ever fixed, remove this line. See below. */ + out = in = 1; + + if (!i2sdev->out.created && out) { + if (dev->pcm->card != card) { + /* eh? */ + printk(KERN_ERR + "Can't attach same bus to different cards!\n"); + module_put(ci->owner); + kfree(cii); + soundbus_dev_put(dev); + module_put(THIS_MODULE); + return -EINVAL; + } + if ((err = + snd_pcm_new_stream(dev->pcm, SNDRV_PCM_STREAM_PLAYBACK, 1))) { + module_put(ci->owner); + kfree(cii); + soundbus_dev_put(dev); + module_put(THIS_MODULE); + return err; + } + snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_PLAYBACK, + &i2sbus_playback_ops); + i2sdev->out.created = 1; + } + + if (!i2sdev->in.created && in) { + if (dev->pcm->card != card) { + printk(KERN_ERR + "Can't attach same bus to different cards!\n"); + module_put(ci->owner); + kfree(cii); + soundbus_dev_put(dev); + module_put(THIS_MODULE); + return -EINVAL; + } + if ((err = + snd_pcm_new_stream(dev->pcm, SNDRV_PCM_STREAM_CAPTURE, 1))) { + module_put(ci->owner); + kfree(cii); + soundbus_dev_put(dev); + module_put(THIS_MODULE); + return err; + } + snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_CAPTURE, + &i2sbus_record_ops); + i2sdev->in.created = 1; + } + + /* so we have to register the pcm after adding any substream + * to it because alsa doesn't create the devices for the + * substreams when we add them later. + * Therefore, force in and out on both busses (above) and + * register the pcm now instead of just after creating it. + */ + err = snd_device_register(card, dev->pcm); + if (err) { + printk(KERN_ERR "i2sbus: error registering new pcm\n"); + module_put(ci->owner); + kfree(cii); + soundbus_dev_put(dev); + module_put(THIS_MODULE); + return err; + } + /* no errors any more, so let's add this to our list */ + list_add(&cii->list, &dev->codec_list); + + dev->pcm->private_data = i2sdev; + dev->pcm->private_free = i2sbus_private_free; + + /* well, we really should support scatter/gather DMA */ + snd_pcm_lib_preallocate_pages_for_all( + dev->pcm, SNDRV_DMA_TYPE_DEV, + snd_dma_pci_data(macio_get_pci_dev(i2sdev->macio)), + 64 * 1024, 64 * 1024); + + return 0; +} + +void i2sbus_detach_codec(struct soundbus_dev *dev, void *data) +{ + struct codec_info_item *cii = NULL, *i; + + list_for_each_entry(i, &dev->codec_list, list) { + if (i->codec_data == data) { + cii = i; + break; + } + } + if (cii) { + list_del(&cii->list); + module_put(cii->codec->owner); + kfree(cii); + } + /* no more codecs, but still a pcm? */ + if (list_empty(&dev->codec_list) && dev->pcm) { + /* the actual cleanup is done by the callback above! */ + snd_device_free(dev->pcm->card, dev->pcm); + } +} diff --git a/sound/aoa/soundbus/i2sbus/i2sbus.h b/sound/aoa/soundbus/i2sbus/i2sbus.h new file mode 100644 index 00000000000..cfa5162e3b0 --- /dev/null +++ b/sound/aoa/soundbus/i2sbus/i2sbus.h @@ -0,0 +1,112 @@ +/* + * i2sbus driver -- private definitions + * + * Copyright 2006 Johannes Berg + * + * GPL v2, can be found in COPYING. + */ +#ifndef __I2SBUS_H +#define __I2SBUS_H +#include +#include +#include +#include +#include +#include +#include "i2sbus-interface.h" +#include "i2sbus-control.h" +#include "../soundbus.h" + +struct i2sbus_control { + volatile struct i2s_control_regs __iomem *controlregs; + struct resource rsrc; + struct list_head list; +}; + +#define MAX_DBDMA_COMMANDS 32 + +struct dbdma_command_mem { + dma_addr_t bus_addr; + dma_addr_t bus_cmd_start; + struct dbdma_cmd *cmds; + void *space; + int size; + u32 running:1; +}; + +struct pcm_info { + u32 created:1, /* has this direction been created with alsa? */ + active:1; /* is this stream active? */ + /* runtime information */ + struct snd_pcm_substream *substream; + int current_period; + u32 frame_count; + struct dbdma_command_mem dbdma_ring; + volatile struct dbdma_regs __iomem *dbdma; +}; + +struct i2sbus_dev { + struct soundbus_dev sound; + struct macio_dev *macio; + struct i2sbus_control *control; + volatile struct i2s_interface_regs __iomem *intfregs; + + struct resource resources[3]; + struct resource *allocated_resource[3]; + int interrupts[3]; + char rnames[3][32]; + + /* info about currently active substreams */ + struct pcm_info out, in; + snd_pcm_format_t format; + unsigned int rate; + + /* list for a single controller */ + struct list_head item; + /* number of bus on controller */ + int bus_number; + /* for use by control layer */ + struct pmf_function *enable, + *cell_enable, + *cell_disable, + *clock_enable, + *clock_disable; + + /* locks */ + /* spinlock for low-level interrupt locking */ + spinlock_t low_lock; + /* mutex for high-level consistency */ + struct mutex lock; +}; + +#define soundbus_dev_to_i2sbus_dev(sdev) \ + container_of(sdev, struct i2sbus_dev, sound) + +/* pcm specific functions */ +extern int +i2sbus_attach_codec(struct soundbus_dev *dev, struct snd_card *card, + struct codec_info *ci, void *data); +extern void +i2sbus_detach_codec(struct soundbus_dev *dev, void *data); +extern irqreturn_t +i2sbus_tx_intr(int irq, void *devid, struct pt_regs *regs); +extern irqreturn_t +i2sbus_rx_intr(int irq, void *devid, struct pt_regs *regs); + +/* control specific functions */ +extern int i2sbus_control_init(struct macio_dev* dev, + struct i2sbus_control **c); +extern void i2sbus_control_destroy(struct i2sbus_control *c); +extern int i2sbus_control_add_dev(struct i2sbus_control *c, + struct i2sbus_dev *i2sdev); +extern void i2sbus_control_remove_dev(struct i2sbus_control *c, + struct i2sbus_dev *i2sdev); +extern int i2sbus_control_enable(struct i2sbus_control *c, + struct i2sbus_dev *i2sdev); +extern int i2sbus_control_cell(struct i2sbus_control *c, + struct i2sbus_dev *i2sdev, + int enable); +extern int i2sbus_control_clock(struct i2sbus_control *c, + struct i2sbus_dev *i2sdev, + int enable); +#endif /* __I2SBUS_H */ diff --git a/sound/aoa/soundbus/soundbus.h b/sound/aoa/soundbus/soundbus.h new file mode 100644 index 00000000000..5c27297835d --- /dev/null +++ b/sound/aoa/soundbus/soundbus.h @@ -0,0 +1,202 @@ +/* + * soundbus generic definitions + * + * Copyright 2006 Johannes Berg + * + * GPL v2, can be found in COPYING. + */ +#ifndef __SOUNDBUS_H +#define __SOUNDBUS_H + +#include +#include +#include + + +/* When switching from master to slave or the other way around, + * you don't want to have the codec chip acting as clock source + * while the bus still is. + * More importantly, while switch from slave to master, you need + * to turn off the chip's master function first, but then there's + * no clock for a while and other chips might reset, so we notify + * their drivers after having switched. + * The constants here are codec-point of view, so when we switch + * the soundbus to master we tell the codec we're going to switch + * and give it CLOCK_SWITCH_PREPARE_SLAVE! + */ +enum clock_switch { + CLOCK_SWITCH_PREPARE_SLAVE, + CLOCK_SWITCH_PREPARE_MASTER, + CLOCK_SWITCH_SLAVE, + CLOCK_SWITCH_MASTER, + CLOCK_SWITCH_NOTIFY, +}; + +/* information on a transfer the codec can take */ +struct transfer_info { + u64 formats; /* SNDRV_PCM_FMTBIT_* */ + unsigned int rates; /* SNDRV_PCM_RATE_* */ + /* flags */ + u32 transfer_in:1, /* input = 1, output = 0 */ + must_be_clock_source:1; + /* for codecs to distinguish among their TIs */ + int tag; +}; + +struct codec_info_item { + struct codec_info *codec; + void *codec_data; + struct soundbus_dev *sdev; + /* internal, to be used by the soundbus provider */ + struct list_head list; +}; + +/* for prepare, where the codecs need to know + * what we're going to drive the bus with */ +struct bus_info { + /* see below */ + int sysclock_factor; + int bus_factor; +}; + +/* information on the codec itself, plus function pointers */ +struct codec_info { + /* the module this lives in */ + struct module *owner; + + /* supported transfer possibilities, array terminated by + * formats or rates being 0. */ + struct transfer_info *transfers; + + /* Master clock speed factor + * to be used (master clock speed = sysclock_factor * sampling freq) + * Unused if the soundbus provider has no such notion. + */ + int sysclock_factor; + + /* Bus factor, bus clock speed = bus_factor * sampling freq) + * Unused if the soundbus provider has no such notion. + */ + int bus_factor; + + /* operations */ + /* clock switching, see above */ + int (*switch_clock)(struct codec_info_item *cii, + enum clock_switch clock); + + /* called for each transfer_info when the user + * opens the pcm device to determine what the + * hardware can support at this point in time. + * That can depend on other user-switchable controls. + * Return 1 if usable, 0 if not. + * out points to another instance of a transfer_info + * which is initialised to the values in *ti, and + * it's format and rate values can be modified by + * the callback if it is necessary to further restrict + * the formats that can be used at the moment, for + * example when one codec has multiple logical codec + * info structs for multiple inputs. + */ + int (*usable)(struct codec_info_item *cii, + struct transfer_info *ti, + struct transfer_info *out); + + /* called when pcm stream is opened, probably not implemented + * most of the time since it isn't too useful */ + int (*open)(struct codec_info_item *cii, + struct snd_pcm_substream *substream); + + /* called when the pcm stream is closed, at this point + * the user choices can all be unlocked (see below) */ + int (*close)(struct codec_info_item *cii, + struct snd_pcm_substream *substream); + + /* if the codec must forbid some user choices because + * they are not valid with the substream/transfer info, + * it must do so here. Example: no digital output for + * incompatible framerate, say 8KHz, on Onyx. + * If the selected stuff in the substream is NOT + * compatible, you have to reject this call! */ + int (*prepare)(struct codec_info_item *cii, + struct bus_info *bi, + struct snd_pcm_substream *substream); + + /* start() is called before data is pushed to the codec. + * Note that start() must be atomic! */ + int (*start)(struct codec_info_item *cii, + struct snd_pcm_substream *substream); + + /* stop() is called after data is no longer pushed to the codec. + * Note that stop() must be atomic! */ + int (*stop)(struct codec_info_item *cii, + struct snd_pcm_substream *substream); + + int (*suspend)(struct codec_info_item *cii, pm_message_t state); + int (*resume)(struct codec_info_item *cii); +}; + +/* information on a soundbus device */ +struct soundbus_dev { + /* the bus it belongs to */ + struct list_head onbuslist; + + /* the of device it represents */ + struct of_device ofdev; + + /* what modules go by */ + char modalias[32]; + + /* These fields must be before attach_codec can be called. + * They should be set by the owner of the alsa card object + * that is needed, and whoever sets them must make sure + * that they are unique within that alsa card object. */ + char *pcmname; + int pcmid; + + /* this is assigned by the soundbus provider in attach_codec */ + struct snd_pcm *pcm; + + /* operations */ + /* attach a codec to this soundbus, give the alsa + * card object the PCMs for this soundbus should be in. + * The 'data' pointer must be unique, it is used as the + * key for detach_codec(). */ + int (*attach_codec)(struct soundbus_dev *dev, struct snd_card *card, + struct codec_info *ci, void *data); + void (*detach_codec)(struct soundbus_dev *dev, void *data); + /* TODO: suspend/resume */ + + /* private for the soundbus provider */ + struct list_head codec_list; + u32 have_out:1, have_in:1; +}; +#define to_soundbus_device(d) container_of(d, struct soundbus_dev, ofdev.dev) +#define of_to_soundbus_device(d) container_of(d, struct soundbus_dev, ofdev) + +extern int soundbus_add_one(struct soundbus_dev *dev); +extern void soundbus_remove_one(struct soundbus_dev *dev); + +extern struct soundbus_dev *soundbus_dev_get(struct soundbus_dev *dev); +extern void soundbus_dev_put(struct soundbus_dev *dev); + +struct soundbus_driver { + char *name; + struct module *owner; + + /* we don't implement any matching at all */ + + int (*probe)(struct soundbus_dev* dev); + int (*remove)(struct soundbus_dev* dev); + + int (*suspend)(struct soundbus_dev* dev, pm_message_t state); + int (*resume)(struct soundbus_dev* dev); + int (*shutdown)(struct soundbus_dev* dev); + + struct device_driver driver; +}; +#define to_soundbus_driver(drv) container_of(drv,struct soundbus_driver, driver) + +extern int soundbus_register_driver(struct soundbus_driver *drv); +extern void soundbus_unregister_driver(struct soundbus_driver *drv); + +#endif /* __SOUNDBUS_H */ diff --git a/sound/aoa/soundbus/sysfs.c b/sound/aoa/soundbus/sysfs.c new file mode 100644 index 00000000000..d31f8146952 --- /dev/null +++ b/sound/aoa/soundbus/sysfs.c @@ -0,0 +1,43 @@ +#include +#include +#include +/* FIX UP */ +#include "soundbus.h" + +#define soundbus_config_of_attr(field, format_string) \ +static ssize_t \ +field##_show (struct device *dev, struct device_attribute *attr, \ + char *buf) \ +{ \ + struct soundbus_dev *mdev = to_soundbus_device (dev); \ + return sprintf (buf, format_string, mdev->ofdev.node->field); \ +} + +static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct soundbus_dev *sdev = to_soundbus_device(dev); + struct of_device *of = &sdev->ofdev; + int length; + + if (*sdev->modalias) { + strlcpy(buf, sdev->modalias, sizeof(sdev->modalias) + 1); + strcat(buf, "\n"); + length = strlen(buf); + } else { + length = sprintf(buf, "of:N%sT%s\n", + of->node->name, of->node->type); + } + + return length; +} + +soundbus_config_of_attr (name, "%s\n"); +soundbus_config_of_attr (type, "%s\n"); + +struct device_attribute soundbus_dev_attrs[] = { + __ATTR_RO(name), + __ATTR_RO(type), + __ATTR_RO(modalias), + __ATTR_NULL +}; -- cgit v1.2.3 From 55c385ad5e1f3cda887cd6a8ad69a6d74b4b9125 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 21 Jun 2006 15:43:44 +0200 Subject: [ALSA] snd-powermac: no longer handle anything with a layout-id property This patch removes from snd-powermac the code that check for the layout-id and instead adds code that makes it refuse loading when a layout-id property is present, nothing that snd-aoa should be used. It also removes the 'toonie' codec from snd-powermac which was only ever used on the mac mini which has a layout-id property. Signed-off-by: Johannes Berg Signed-off-by: Takashi Iwai --- sound/ppc/Makefile | 2 +- sound/ppc/pmac.c | 44 ++++++++------------------------------------ sound/ppc/pmac.h | 3 +-- sound/ppc/powermac.c | 7 ------- 4 files changed, 10 insertions(+), 46 deletions(-) diff --git a/sound/ppc/Makefile b/sound/ppc/Makefile index d6ba9959097..4d95c652c8c 100644 --- a/sound/ppc/Makefile +++ b/sound/ppc/Makefile @@ -3,7 +3,7 @@ # Copyright (c) 2001 by Jaroslav Kysela # -snd-powermac-objs := powermac.o pmac.o awacs.o burgundy.o daca.o tumbler.o toonie.o keywest.o beep.o +snd-powermac-objs := powermac.o pmac.o awacs.o burgundy.o daca.o tumbler.o keywest.o beep.o # Toplevel Module Dependency obj-$(CONFIG_SND_POWERMAC) += snd-powermac.o diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c index f0794ef9d1a..b678814975c 100644 --- a/sound/ppc/pmac.c +++ b/sound/ppc/pmac.c @@ -867,8 +867,6 @@ static int __init snd_pmac_detect(struct snd_pmac *chip) unsigned int *prop, l; struct macio_chip* macio; - u32 layout_id = 0; - if (!machine_is(powermac)) return -ENODEV; @@ -929,8 +927,14 @@ static int __init snd_pmac_detect(struct snd_pmac *chip) if (prop && *prop < 16) chip->subframe = *prop; prop = (unsigned int *) get_property(sound, "layout-id", NULL); - if (prop) - layout_id = *prop; + if (prop) { + /* partly deprecate snd-powermac, for those machines + * that have a layout-id property for now */ + printk(KERN_INFO "snd-powermac no longer handles any " + "machines with a layout-id property " + "in the device-tree, use snd-aoa.\n"); + return -ENODEV; + } /* This should be verified on older screamers */ if (device_is_compatible(sound, "screamer")) { chip->model = PMAC_SCREAMER; @@ -963,38 +967,6 @@ static int __init snd_pmac_detect(struct snd_pmac *chip) chip->freq_table = tumbler_freqs; chip->control_mask = MASK_IEPC | 0x11; /* disable IEE */ } - if (device_is_compatible(sound, "AOAKeylargo") || - device_is_compatible(sound, "AOAbase") || - device_is_compatible(sound, "AOAK2")) { - /* For now, only support very basic TAS3004 based machines with - * single frequency until proper i2s control is implemented - */ - switch(layout_id) { - case 0x24: - case 0x29: - case 0x33: - case 0x46: - case 0x48: - case 0x50: - case 0x5c: - chip->num_freqs = ARRAY_SIZE(tumbler_freqs); - chip->model = PMAC_SNAPPER; - chip->can_byte_swap = 0; /* FIXME: check this */ - chip->control_mask = MASK_IEPC | 0x11;/* disable IEE */ - break; - case 0x3a: - chip->num_freqs = ARRAY_SIZE(tumbler_freqs); - chip->model = PMAC_TOONIE; - chip->can_byte_swap = 0; /* FIXME: check this */ - chip->control_mask = MASK_IEPC | 0x11;/* disable IEE */ - break; - default: - printk(KERN_ERR "snd: Unknown layout ID 0x%x\n", - layout_id); - return -ENODEV; - - } - } prop = (unsigned int *)get_property(sound, "device-id", NULL); if (prop) chip->device_id = *prop; diff --git a/sound/ppc/pmac.h b/sound/ppc/pmac.h index 3a9bd4dbb9a..8394e66ceb0 100644 --- a/sound/ppc/pmac.h +++ b/sound/ppc/pmac.h @@ -85,7 +85,7 @@ struct pmac_stream { enum snd_pmac_model { PMAC_AWACS, PMAC_SCREAMER, PMAC_BURGUNDY, PMAC_DACA, PMAC_TUMBLER, - PMAC_SNAPPER, PMAC_TOONIE + PMAC_SNAPPER }; struct snd_pmac { @@ -188,7 +188,6 @@ int snd_pmac_burgundy_init(struct snd_pmac *chip); int snd_pmac_daca_init(struct snd_pmac *chip); int snd_pmac_tumbler_init(struct snd_pmac *chip); int snd_pmac_tumbler_post_init(void); -int snd_pmac_toonie_init(struct snd_pmac *chip); /* i2c functions */ struct pmac_keywest { diff --git a/sound/ppc/powermac.c b/sound/ppc/powermac.c index 875f1f7bdc5..fa9a44ab487 100644 --- a/sound/ppc/powermac.c +++ b/sound/ppc/powermac.c @@ -94,13 +94,6 @@ static int __init snd_pmac_probe(struct platform_device *devptr) if ( snd_pmac_tumbler_init(chip) < 0 || snd_pmac_tumbler_post_init() < 0) goto __error; break; - case PMAC_TOONIE: - strcpy(card->driver, "PMac Toonie"); - strcpy(card->shortname, "PowerMac Toonie"); - strcpy(card->longname, card->shortname); - if ((err = snd_pmac_toonie_init(chip)) < 0) - goto __error; - break; case PMAC_AWACS: case PMAC_SCREAMER: name_ext = chip->model == PMAC_SCREAMER ? "Screamer" : "AWACS"; -- cgit v1.2.3 From 555fdc2e9fb2071fdd10ff1d86b8d63265d80241 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 21 Jun 2006 16:23:31 +0200 Subject: [ALSA] Remove ppc/toonie.c Remove obsoleted ppc/toonie.c. The function is replaced with new snd-aoa driver. Signed-off-by: Takashi Iwai --- sound/ppc/toonie.c | 378 ----------------------------------------------------- 1 file changed, 378 deletions(-) diff --git a/sound/ppc/toonie.c b/sound/ppc/toonie.c index 1ac7c8552f5..e69de29bb2d 100644 --- a/sound/ppc/toonie.c +++ b/sound/ppc/toonie.c @@ -1,378 +0,0 @@ -/* - * Mac Mini "toonie" mixer control - * - * Copyright (c) 2005 by Benjamin Herrenschmidt - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "pmac.h" - -#undef DEBUG - -#ifdef DEBUG -#define DBG(fmt...) printk(fmt) -#else -#define DBG(fmt...) -#endif - -struct pmac_gpio { - unsigned int addr; - u8 active_val; - u8 inactive_val; - u8 active_state; -}; - -struct pmac_toonie -{ - struct pmac_gpio hp_detect_gpio; - struct pmac_gpio hp_mute_gpio; - struct pmac_gpio amp_mute_gpio; - int hp_detect_irq; - int auto_mute_notify; - struct work_struct detect_work; -}; - - -/* - * gpio access - */ -#define do_gpio_write(gp, val) \ - pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, (gp)->addr, val) -#define do_gpio_read(gp) \ - pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, (gp)->addr, 0) -#define tumbler_gpio_free(gp) /* NOP */ - -static void write_audio_gpio(struct pmac_gpio *gp, int active) -{ - if (! gp->addr) - return; - active = active ? gp->active_val : gp->inactive_val; - do_gpio_write(gp, active); - DBG("(I) gpio %x write %d\n", gp->addr, active); -} - -static int check_audio_gpio(struct pmac_gpio *gp) -{ - int ret; - - if (! gp->addr) - return 0; - - ret = do_gpio_read(gp); - - return (ret & 0xd) == (gp->active_val & 0xd); -} - -static int read_audio_gpio(struct pmac_gpio *gp) -{ - int ret; - if (! gp->addr) - return 0; - ret = ((do_gpio_read(gp) & 0x02) !=0); - return ret == gp->active_state; -} - - -enum { TOONIE_MUTE_HP, TOONIE_MUTE_AMP }; - -static int toonie_get_mute_switch(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_toonie *mix = chip->mixer_data; - struct pmac_gpio *gp; - - if (mix == NULL) - return -ENODEV; - switch(kcontrol->private_value) { - case TOONIE_MUTE_HP: - gp = &mix->hp_mute_gpio; - break; - case TOONIE_MUTE_AMP: - gp = &mix->amp_mute_gpio; - break; - default: - return -EINVAL; - } - ucontrol->value.integer.value[0] = !check_audio_gpio(gp); - return 0; -} - -static int toonie_put_mute_switch(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_toonie *mix = chip->mixer_data; - struct pmac_gpio *gp; - int val; - - if (chip->update_automute && chip->auto_mute) - return 0; /* don't touch in the auto-mute mode */ - - if (mix == NULL) - return -ENODEV; - - switch(kcontrol->private_value) { - case TOONIE_MUTE_HP: - gp = &mix->hp_mute_gpio; - break; - case TOONIE_MUTE_AMP: - gp = &mix->amp_mute_gpio; - break; - default: - return -EINVAL; - } - val = ! check_audio_gpio(gp); - if (val != ucontrol->value.integer.value[0]) { - write_audio_gpio(gp, ! ucontrol->value.integer.value[0]); - return 1; - } - return 0; -} - -static struct snd_kcontrol_new toonie_hp_sw __initdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Headphone Playback Switch", - .info = snd_pmac_boolean_mono_info, - .get = toonie_get_mute_switch, - .put = toonie_put_mute_switch, - .private_value = TOONIE_MUTE_HP, -}; -static struct snd_kcontrol_new toonie_speaker_sw __initdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "PC Speaker Playback Switch", - .info = snd_pmac_boolean_mono_info, - .get = toonie_get_mute_switch, - .put = toonie_put_mute_switch, - .private_value = TOONIE_MUTE_AMP, -}; - -/* - * auto-mute stuffs - */ -static int toonie_detect_headphone(struct snd_pmac *chip) -{ - struct pmac_toonie *mix = chip->mixer_data; - int detect = 0; - - if (mix->hp_detect_gpio.addr) - detect |= read_audio_gpio(&mix->hp_detect_gpio); - return detect; -} - -static void toonie_check_mute(struct snd_pmac *chip, struct pmac_gpio *gp, int val, - int do_notify, struct snd_kcontrol *sw) -{ - if (check_audio_gpio(gp) != val) { - write_audio_gpio(gp, val); - if (do_notify) - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &sw->id); - } -} - -static void toonie_detect_handler(void *self) -{ - struct snd_pmac *chip = (struct snd_pmac *) self; - struct pmac_toonie *mix; - int headphone; - - if (!chip) - return; - - mix = chip->mixer_data; - snd_assert(mix, return); - - headphone = toonie_detect_headphone(chip); - - DBG("headphone: %d, lineout: %d\n", headphone, lineout); - - if (headphone) { - /* unmute headphone/lineout & mute speaker */ - toonie_check_mute(chip, &mix->hp_mute_gpio, 0, - mix->auto_mute_notify, chip->master_sw_ctl); - toonie_check_mute(chip, &mix->amp_mute_gpio, 1, - mix->auto_mute_notify, chip->speaker_sw_ctl); - } else { - /* unmute speaker, mute others */ - toonie_check_mute(chip, &mix->amp_mute_gpio, 0, - mix->auto_mute_notify, chip->speaker_sw_ctl); - toonie_check_mute(chip, &mix->hp_mute_gpio, 1, - mix->auto_mute_notify, chip->master_sw_ctl); - } - if (mix->auto_mute_notify) { - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->hp_detect_ctl->id); - } -} - -static void toonie_update_automute(struct snd_pmac *chip, int do_notify) -{ - if (chip->auto_mute) { - struct pmac_toonie *mix; - mix = chip->mixer_data; - snd_assert(mix, return); - mix->auto_mute_notify = do_notify; - schedule_work(&mix->detect_work); - } -} - -/* interrupt - headphone plug changed */ -static irqreturn_t toonie_hp_intr(int irq, void *devid, struct pt_regs *regs) -{ - struct snd_pmac *chip = devid; - - if (chip->update_automute && chip->initialized) { - chip->update_automute(chip, 1); - return IRQ_HANDLED; - } - return IRQ_NONE; -} - -/* look for audio gpio device */ -static int find_audio_gpio(const char *name, const char *platform, - struct pmac_gpio *gp) -{ - struct device_node *np; - u32 *base, addr; - - if (! (np = find_devices("gpio"))) - return -ENODEV; - - for (np = np->child; np; np = np->sibling) { - char *property = get_property(np, "audio-gpio", NULL); - if (property && strcmp(property, name) == 0) - break; - if (device_is_compatible(np, name)) - break; - } - if (np == NULL) - return -ENODEV; - - base = (u32 *)get_property(np, "AAPL,address", NULL); - if (! base) { - base = (u32 *)get_property(np, "reg", NULL); - if (!base) { - DBG("(E) cannot find address for device %s !\n", name); - return -ENODEV; - } - addr = *base; - if (addr < 0x50) - addr += 0x50; - } else - addr = *base; - - gp->addr = addr & 0x0000ffff; - - /* Try to find the active state, default to 0 ! */ - base = (u32 *)get_property(np, "audio-gpio-active-state", NULL); - if (base) { - gp->active_state = *base; - gp->active_val = (*base) ? 0x5 : 0x4; - gp->inactive_val = (*base) ? 0x4 : 0x5; - } else { - u32 *prop = NULL; - gp->active_state = 0; - gp->active_val = 0x4; - gp->inactive_val = 0x5; - /* Here are some crude hacks to extract the GPIO polarity and - * open collector informations out of the do-platform script - * as we don't yet have an interpreter for these things - */ - if (platform) - prop = (u32 *)get_property(np, platform, NULL); - if (prop) { - if (prop[3] == 0x9 && prop[4] == 0x9) { - gp->active_val = 0xd; - gp->inactive_val = 0xc; - } - if (prop[3] == 0x1 && prop[4] == 0x1) { - gp->active_val = 0x5; - gp->inactive_val = 0x4; - } - } - } - - DBG("(I) GPIO device %s found, offset: %x, active state: %d !\n", - name, gp->addr, gp->active_state); - - return (np->n_intrs > 0) ? np->intrs[0].line : 0; -} - -static void toonie_cleanup(struct snd_pmac *chip) -{ - struct pmac_toonie *mix = chip->mixer_data; - if (! mix) - return; - if (mix->hp_detect_irq >= 0) - free_irq(mix->hp_detect_irq, chip); - kfree(mix); - chip->mixer_data = NULL; -} - -int __init snd_pmac_toonie_init(struct snd_pmac *chip) -{ - struct pmac_toonie *mix; - - mix = kmalloc(sizeof(*mix), GFP_KERNEL); - if (! mix) - return -ENOMEM; - - chip->mixer_data = mix; - chip->mixer_free = toonie_cleanup; - - find_audio_gpio("headphone-mute", NULL, &mix->hp_mute_gpio); - find_audio_gpio("amp-mute", NULL, &mix->amp_mute_gpio); - mix->hp_detect_irq = find_audio_gpio("headphone-detect", - NULL, &mix->hp_detect_gpio); - - strcpy(chip->card->mixername, "PowerMac Toonie"); - - chip->master_sw_ctl = snd_ctl_new1(&toonie_hp_sw, chip); - snd_ctl_add(chip->card, chip->master_sw_ctl); - - chip->speaker_sw_ctl = snd_ctl_new1(&toonie_speaker_sw, chip); - snd_ctl_add(chip->card, chip->speaker_sw_ctl); - - INIT_WORK(&mix->detect_work, toonie_detect_handler, (void *)chip); - - if (mix->hp_detect_irq >= 0) { - snd_pmac_add_automute(chip); - - chip->detect_headphone = toonie_detect_headphone; - chip->update_automute = toonie_update_automute; - toonie_update_automute(chip, 0); - - if (request_irq(mix->hp_detect_irq, toonie_hp_intr, 0, - "Sound Headphone Detection", chip) < 0) - mix->hp_detect_irq = -1; - } - - return 0; -} - -- cgit v1.2.3 From 45df379798b5c3b2ea937735ef04c58ce0f532a7 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 21 Jun 2006 16:37:54 +0200 Subject: [ALSA] Remove nested mutexes in seq_ports.c Removed nested mutexes in the removal routine of port connections. The port is guaranteed to be offline before calling it, so no mutex is needed. Signed-off-by: Takashi Iwai --- sound/core/seq/seq_ports.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c index 5f46ee9e217..334579a9f26 100644 --- a/sound/core/seq/seq_ports.c +++ b/sound/core/seq/seq_ports.c @@ -221,7 +221,6 @@ static void clear_subscriber_list(struct snd_seq_client *client, { struct list_head *p, *n; - down_write(&grp->list_mutex); list_for_each_safe(p, n, &grp->list_head) { struct snd_seq_subscribers *subs; struct snd_seq_client *c; @@ -259,7 +258,6 @@ static void clear_subscriber_list(struct snd_seq_client *client, snd_seq_client_unlock(c); } } - up_write(&grp->list_mutex); } /* delete port data */ -- cgit v1.2.3 From 5885492ab4fb18c155000d12f920754f7f35fbab Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 21 Jun 2006 19:19:25 +0200 Subject: [ALSA] hda-codec - Show EAPD and pin-detection capabilities in proc Show EAPD and pin-detection capabilities in proc files. They are often required to support the proper audio functionality. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_proc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index 3db009990c5..c2f0fe85bf3 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c @@ -182,6 +182,10 @@ static void print_pin_caps(struct snd_info_buffer *buffer, snd_iprintf(buffer, " OUT"); if (caps & AC_PINCAP_HP_DRV) snd_iprintf(buffer, " HP"); + if (caps & AC_PINCAP_EAPD) + snd_iprintf(buffer, " EAPD"); + if (caps & AC_PINCAP_PRES_DETECT) + snd_iprintf(buffer, " Detect"); snd_iprintf(buffer, "\n"); caps = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); snd_iprintf(buffer, " Pin Default 0x%08x: [%s] %s at %s %s\n", caps, -- cgit v1.2.3 From 607c0fbee7272be4d5455d6b29f6ffb092573eff Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Thu, 22 Jun 2006 17:49:58 +0200 Subject: [ALSA] aoa driver - Kconfig - remove spaces for SND!=n Signed-off-by: Jaroslav Kysela --- sound/aoa/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/aoa/Kconfig b/sound/aoa/Kconfig index b11ccf6dbab..a85194fe0b0 100644 --- a/sound/aoa/Kconfig +++ b/sound/aoa/Kconfig @@ -1,5 +1,5 @@ menu "Apple Onboard Audio driver" - depends on SND != n && PPC + depends on SND!=n && PPC config SND_AOA tristate "Apple Onboard Audio driver" -- cgit v1.2.3 From 0dad31d2da706ef114bc5c21123123be2f405d5b Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Thu, 22 Jun 2006 21:35:11 +0200 Subject: [ALSA] version 1.0.12rc1 --- include/sound/version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/sound/version.h b/include/sound/version.h index 4f0e65808cf..2ee849d0e19 100644 --- a/include/sound/version.h +++ b/include/sound/version.h @@ -1,3 +1,3 @@ /* include/version.h. Generated by configure. */ -#define CONFIG_SND_VERSION "1.0.11rc4" -#define CONFIG_SND_DATE " (Wed Mar 22 10:27:24 2006 UTC)" +#define CONFIG_SND_VERSION "1.0.12rc1" +#define CONFIG_SND_DATE " (Thu Jun 22 13:55:50 2006 UTC)" -- cgit v1.2.3 From a341305e94982c66a2e94125a24b860605da9066 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 22 Jun 2006 22:18:13 +0100 Subject: [ARM] 3613/1: S3C2410: Add sysdev and sysclass Patch from Ben Dooks The S3C2440 and S3C2442 both have their own sysdev and sysclass for differentiating them from the currently default S3C2410. Add a sysdev for the S3C2410 as part of the work to make the code be non-dependant on the S3C2410. Signed-off-by: Ben Dooks Signed-off-by: Russell King --- arch/arm/mach-s3c2410/cpu.h | 1 + arch/arm/mach-s3c2410/s3c2410.c | 24 +++++++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-s3c2410/cpu.h b/arch/arm/mach-s3c2410/cpu.h index 40862899b2f..21c62dc29bb 100644 --- a/arch/arm/mach-s3c2410/cpu.h +++ b/arch/arm/mach-s3c2410/cpu.h @@ -73,5 +73,6 @@ extern struct sys_timer s3c24xx_timer; /* system device classes */ +extern struct sysdev_class s3c2410_sysclass; extern struct sysdev_class s3c2440_sysclass; extern struct sysdev_class s3c2442_sysclass; diff --git a/arch/arm/mach-s3c2410/s3c2410.c b/arch/arm/mach-s3c2410/s3c2410.c index 0852e87a79c..cb252ddf3c7 100644 --- a/arch/arm/mach-s3c2410/s3c2410.c +++ b/arch/arm/mach-s3c2410/s3c2410.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -110,9 +111,30 @@ void __init s3c2410_init_clocks(int xtal) s3c24xx_setup_clocks(xtal, fclk, hclk, pclk); } +struct sysdev_class s3c2410_sysclass = { + set_kset_name("s3c2410-core"), +}; + +static struct sys_device s3c2410_sysdev = { + .cls = &s3c2410_sysclass, +}; + +/* need to register class before we actually register the device, and + * we also need to ensure that it has been initialised before any of the + * drivers even try to use it (even if not on an s3c2440 based system) + * as a driver which may support both 2410 and 2440 may try and use it. +*/ + +static int __init s3c2410_core_init(void) +{ + return sysdev_class_register(&s3c2410_sysclass); +} + +core_initcall(s3c2410_core_init); + int __init s3c2410_init(void) { printk("S3C2410: Initialising architecture\n"); - return 0; + return sysdev_register(&s3c2410_sysdev); } -- cgit v1.2.3 From 99c13853ffa26dd6527995b3f47548e075f201fb Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 22 Jun 2006 22:18:20 +0100 Subject: [ARM] 3627/1: S3C24XX: split s3c2410 clocks from core clocks Patch from Ben Dooks Split the s3c2410 specific clocks from the core clock code, as part of the work to support more of the Samsung line of SoCs. The patch does not use the sysdev mechanism as the clocks are needed for the timer init, which is very early in the kernel init sequence. Signed-off-by: Ben Dooks Signed-off-by: Russell King --- arch/arm/mach-s3c2410/Kconfig | 8 ++ arch/arm/mach-s3c2410/Makefile | 4 + arch/arm/mach-s3c2410/clock.c | 221 +--------------------------- arch/arm/mach-s3c2410/clock.h | 10 +- arch/arm/mach-s3c2410/s3c2410-clock.c | 263 ++++++++++++++++++++++++++++++++++ arch/arm/mach-s3c2410/s3c2410.c | 1 + arch/arm/mach-s3c2410/s3c2410.h | 2 + arch/arm/mach-s3c2410/s3c2440-clock.c | 4 +- arch/arm/mach-s3c2410/s3c2442-clock.c | 2 +- arch/arm/mach-s3c2410/s3c244x.c | 2 + 10 files changed, 299 insertions(+), 218 deletions(-) create mode 100644 arch/arm/mach-s3c2410/s3c2410-clock.c diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig index 0c334136db7..7b786d72563 100644 --- a/arch/arm/mach-s3c2410/Kconfig +++ b/arch/arm/mach-s3c2410/Kconfig @@ -114,9 +114,15 @@ config MACH_NEXCODER_2440 endmenu +config S3C2410_CLOCK + bool + help + Clock code for the S3C2410, and similar processors + config CPU_S3C2410 bool depends on ARCH_S3C2410 + select S3C2410_CLOCK help Support for S3C2410 and S3C2410A family from the S3C24XX line of Samsung Mobile CPUs. @@ -130,6 +136,7 @@ config CPU_S3C244X config CPU_S3C2440 bool depends on ARCH_S3C2410 + select S3C2410_CLOCK select CPU_S3C244X help Support for S3C2440 Samsung Mobile CPU based systems. @@ -137,6 +144,7 @@ config CPU_S3C2440 config CPU_S3C2442 bool depends on ARCH_S3C2420 + select S3C2410_CLOCK select CPU_S3C244X help Support for S3C2442 Samsung Mobile CPU based systems. diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile index 5e09355cd4f..372dbcea143 100644 --- a/arch/arm/mach-s3c2410/Makefile +++ b/arch/arm/mach-s3c2410/Makefile @@ -29,6 +29,10 @@ obj-$(CONFIG_PM_SIMTEC) += pm-simtec.o obj-$(CONFIG_CPU_S3C244X) += s3c244x.o obj-$(CONFIG_CPU_S3C244X) += s3c244x-irq.o +# Clock control + +obj-$(CONFIG_S3C2410_CLOCK) += s3c2410-clock.o + # S3C2440 support obj-$(CONFIG_CPU_S3C2440) += s3c2440.o s3c2440-dsc.o diff --git a/arch/arm/mach-s3c2410/clock.c b/arch/arm/mach-s3c2410/clock.c index 99d174612b5..f553e5ee747 100644 --- a/arch/arm/mach-s3c2410/clock.c +++ b/arch/arm/mach-s3c2410/clock.c @@ -3,7 +3,7 @@ * Copyright (c) 2004-2005 Simtec Electronics * Ben Dooks * - * S3C2410 Clock control support + * S3C24XX Core clock control support * * Based on, and code from linux/arch/arm/mach-versatile/clock.c ** @@ -56,25 +56,6 @@ static LIST_HEAD(clocks); DEFINE_MUTEX(clocks_mutex); -/* old functions */ - -void inline s3c24xx_clk_enable(unsigned int clocks, unsigned int enable) -{ - unsigned long clkcon; - - clkcon = __raw_readl(S3C2410_CLKCON); - - if (enable) - clkcon |= clocks; - else - clkcon &= ~clocks; - - /* ensure none of the special function bits set */ - clkcon &= ~(S3C2410_CLKCON_IDLE|S3C2410_CLKCON_POWER | 3); - - __raw_writel(clkcon, S3C2410_CLKCON); -} - /* enable and disable calls for use with the clk struct */ static int clk_null_enable(struct clk *clk, int enable) @@ -82,12 +63,6 @@ static int clk_null_enable(struct clk *clk, int enable) return 0; } -int s3c24xx_clkcon_enable(struct clk *clk, int enable) -{ - s3c24xx_clk_enable(clk->ctrlbit, enable); - return 0; -} - /* Clock API calls */ struct clk *clk_get(struct device *dev, const char *id) @@ -233,28 +208,6 @@ EXPORT_SYMBOL(clk_set_rate); EXPORT_SYMBOL(clk_get_parent); EXPORT_SYMBOL(clk_set_parent); -/* base clock enable */ - -static int s3c24xx_upll_enable(struct clk *clk, int enable) -{ - unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW); - unsigned long orig = clkslow; - - if (enable) - clkslow &= ~S3C2410_CLKSLOW_UCLK_OFF; - else - clkslow |= S3C2410_CLKSLOW_UCLK_OFF; - - __raw_writel(clkslow, S3C2410_CLKSLOW); - - /* if we started the UPLL, then allow to settle */ - - if (enable && (orig & S3C2410_CLKSLOW_UCLK_OFF)) - udelay(200); - - return 0; -} - /* base clocks */ static struct clk clk_xtal = { @@ -265,15 +218,14 @@ static struct clk clk_xtal = { .ctrlbit = 0, }; -static struct clk clk_upll = { +struct clk clk_upll = { .name = "upll", .id = -1, .parent = NULL, - .enable = s3c24xx_upll_enable, .ctrlbit = 0, }; -static struct clk clk_f = { +struct clk clk_f = { .name = "fclk", .id = -1, .rate = 0, @@ -281,7 +233,7 @@ static struct clk clk_f = { .ctrlbit = 0, }; -static struct clk clk_h = { +struct clk clk_h = { .name = "hclk", .id = -1, .rate = 0, @@ -289,7 +241,7 @@ static struct clk clk_h = { .ctrlbit = 0, }; -static struct clk clk_p = { +struct clk clk_p = { .name = "pclk", .id = -1, .rate = 0, @@ -426,108 +378,6 @@ struct clk s3c24xx_uclk = { .id = -1, }; - -/* standard clock definitions */ - -static struct clk init_clocks[] = { - { - .name = "nand", - .id = -1, - .parent = &clk_h, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_NAND, - }, { - .name = "lcd", - .id = -1, - .parent = &clk_h, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_LCDC, - }, { - .name = "usb-host", - .id = -1, - .parent = &clk_h, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_USBH, - }, { - .name = "usb-device", - .id = -1, - .parent = &clk_h, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_USBD, - }, { - .name = "timers", - .id = -1, - .parent = &clk_p, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_PWMT, - }, { - .name = "sdi", - .id = -1, - .parent = &clk_p, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_SDI, - }, { - .name = "uart", - .id = 0, - .parent = &clk_p, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_UART0, - }, { - .name = "uart", - .id = 1, - .parent = &clk_p, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_UART1, - }, { - .name = "uart", - .id = 2, - .parent = &clk_p, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_UART2, - }, { - .name = "gpio", - .id = -1, - .parent = &clk_p, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_GPIO, - }, { - .name = "rtc", - .id = -1, - .parent = &clk_p, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_RTC, - }, { - .name = "adc", - .id = -1, - .parent = &clk_p, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_ADC, - }, { - .name = "i2c", - .id = -1, - .parent = &clk_p, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_IIC, - }, { - .name = "iis", - .id = -1, - .parent = &clk_p, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_IIS, - }, { - .name = "spi", - .id = -1, - .parent = &clk_p, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_SPI, - }, { - .name = "watchdog", - .id = -1, - .parent = &clk_p, - .ctrlbit = 0, - } -}; - /* initialise the clock system */ int s3c24xx_register_clock(struct clk *clk) @@ -537,14 +387,6 @@ int s3c24xx_register_clock(struct clk *clk) if (clk->enable == NULL) clk->enable = clk_null_enable; - /* if this is a standard clock, set the usage state */ - - if (clk->ctrlbit && clk->enable == s3c24xx_clkcon_enable) { - unsigned long clkcon = __raw_readl(S3C2410_CLKCON); - - clk->usage = (clkcon & clk->ctrlbit) ? 1 : 0; - } - /* add to the list of available clocks */ mutex_lock(&clocks_mutex); @@ -561,44 +403,17 @@ int __init s3c24xx_setup_clocks(unsigned long xtal, unsigned long hclk, unsigned long pclk) { - unsigned long upllcon = __raw_readl(S3C2410_UPLLCON); - unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW); - struct clk *clkp = init_clocks; - int ptr; - int ret; - - printk(KERN_INFO "S3C2410 Clocks, (c) 2004 Simtec Electronics\n"); + printk(KERN_INFO "S3C24XX Clocks, (c) 2004 Simtec Electronics\n"); /* initialise the main system clocks */ clk_xtal.rate = xtal; - clk_upll.rate = s3c2410_get_pll(upllcon, xtal); + clk_upll.rate = s3c2410_get_pll(__raw_readl(S3C2410_UPLLCON), xtal); clk_h.rate = hclk; clk_p.rate = pclk; clk_f.rate = fclk; - /* We must be careful disabling the clocks we are not intending to - * be using at boot time, as subsytems such as the LCD which do - * their own DMA requests to the bus can cause the system to lockup - * if they where in the middle of requesting bus access. - * - * Disabling the LCD clock if the LCD is active is very dangerous, - * and therefore the bootloader should be careful to not enable - * the LCD clock if it is not needed. - */ - - mutex_lock(&clocks_mutex); - - s3c24xx_clk_enable(S3C2410_CLKCON_NAND, 0); - s3c24xx_clk_enable(S3C2410_CLKCON_USBH, 0); - s3c24xx_clk_enable(S3C2410_CLKCON_USBD, 0); - s3c24xx_clk_enable(S3C2410_CLKCON_ADC, 0); - s3c24xx_clk_enable(S3C2410_CLKCON_IIC, 0); - s3c24xx_clk_enable(S3C2410_CLKCON_SPI, 0); - - mutex_unlock(&clocks_mutex); - /* assume uart clocks are correctly setup */ /* register our clocks */ @@ -618,27 +433,5 @@ int __init s3c24xx_setup_clocks(unsigned long xtal, if (s3c24xx_register_clock(&clk_p) < 0) printk(KERN_ERR "failed to register cpu pclk\n"); - - if (s3c24xx_register_clock(&clk_usb_bus) < 0) - printk(KERN_ERR "failed to register usb bus clock\n"); - - /* register clocks from clock array */ - - for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) { - ret = s3c24xx_register_clock(clkp); - if (ret < 0) { - printk(KERN_ERR "Failed to register clock %s (%d)\n", - clkp->name, ret); - } - } - - /* show the clock-slow value */ - - printk("CLOCK: Slow mode (%ld.%ld MHz), %s, MPLL %s, UPLL %s\n", - print_mhz(xtal / ( 2 * S3C2410_CLKSLOW_GET_SLOWVAL(clkslow))), - (clkslow & S3C2410_CLKSLOW_SLOW) ? "slow" : "fast", - (clkslow & S3C2410_CLKSLOW_MPLL_OFF) ? "off" : "on", - (clkslow & S3C2410_CLKSLOW_UCLK_OFF) ? "off" : "on"); - return 0; } diff --git a/arch/arm/mach-s3c2410/clock.h b/arch/arm/mach-s3c2410/clock.h index 01bb458bf8e..1bee5708c35 100644 --- a/arch/arm/mach-s3c2410/clock.h +++ b/arch/arm/mach-s3c2410/clock.h @@ -36,6 +36,13 @@ extern struct clk s3c24xx_uclk; extern struct clk clk_usb_bus; +/* core clock support */ + +extern struct clk clk_f; +extern struct clk clk_h; +extern struct clk clk_p; +extern struct clk clk_upll; + /* exports for arch/arm/mach-s3c2410 * * Please DO NOT use these outside of arch/arm/mach-s3c2410 @@ -43,7 +50,8 @@ extern struct clk clk_usb_bus; extern struct mutex clocks_mutex; -extern int s3c24xx_clkcon_enable(struct clk *clk, int enable); +extern int s3c2410_clkcon_enable(struct clk *clk, int enable); + extern int s3c24xx_register_clock(struct clk *clk); extern int s3c24xx_setup_clocks(unsigned long xtal, diff --git a/arch/arm/mach-s3c2410/s3c2410-clock.c b/arch/arm/mach-s3c2410/s3c2410-clock.c new file mode 100644 index 00000000000..fd17c60e113 --- /dev/null +++ b/arch/arm/mach-s3c2410/s3c2410-clock.c @@ -0,0 +1,263 @@ +/* linux/arch/arm/mach-s3c2410/clock.c + * + * Copyright (c) 2006 Simtec Electronics + * Ben Dooks + * + * S3C2410,S3C2440,S3C2442 Clock control support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "clock.h" +#include "cpu.h" + +int s3c2410_clkcon_enable(struct clk *clk, int enable) +{ + unsigned int clocks = clk->ctrlbit; + unsigned long clkcon; + + clkcon = __raw_readl(S3C2410_CLKCON); + + if (enable) + clkcon |= clocks; + else + clkcon &= ~clocks; + + /* ensure none of the special function bits set */ + clkcon &= ~(S3C2410_CLKCON_IDLE|S3C2410_CLKCON_POWER); + + __raw_writel(clkcon, S3C2410_CLKCON); + + return 0; +} + +static int s3c2410_upll_enable(struct clk *clk, int enable) +{ + unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW); + unsigned long orig = clkslow; + + if (enable) + clkslow &= ~S3C2410_CLKSLOW_UCLK_OFF; + else + clkslow |= S3C2410_CLKSLOW_UCLK_OFF; + + __raw_writel(clkslow, S3C2410_CLKSLOW); + + /* if we started the UPLL, then allow to settle */ + + if (enable && (orig & S3C2410_CLKSLOW_UCLK_OFF)) + udelay(200); + + return 0; +} + +/* standard clock definitions */ + +static struct clk init_clocks_disable[] = { + { + .name = "nand", + .id = -1, + .parent = &clk_h, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_NAND, + }, { + .name = "sdi", + .id = -1, + .parent = &clk_p, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_SDI, + }, { + .name = "adc", + .id = -1, + .parent = &clk_p, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_ADC, + }, { + .name = "i2c", + .id = -1, + .parent = &clk_p, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_IIC, + }, { + .name = "iis", + .id = -1, + .parent = &clk_p, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_IIS, + }, { + .name = "spi", + .id = -1, + .parent = &clk_p, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_SPI, + } +}; + +static struct clk init_clocks[] = { + { + .name = "lcd", + .id = -1, + .parent = &clk_h, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_LCDC, + }, { + .name = "gpio", + .id = -1, + .parent = &clk_p, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_GPIO, + }, { + .name = "usb-host", + .id = -1, + .parent = &clk_h, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_USBH, + }, { + .name = "usb-device", + .id = -1, + .parent = &clk_h, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_USBD, + }, { + .name = "timers", + .id = -1, + .parent = &clk_p, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_PWMT, + }, { + .name = "uart", + .id = 0, + .parent = &clk_p, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_UART0, + }, { + .name = "uart", + .id = 1, + .parent = &clk_p, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_UART1, + }, { + .name = "uart", + .id = 2, + .parent = &clk_p, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_UART2, + }, { + .name = "rtc", + .id = -1, + .parent = &clk_p, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_RTC, + }, { + .name = "watchdog", + .id = -1, + .parent = &clk_p, + .ctrlbit = 0, + } +}; + +/* s3c2410_baseclk_add() + * + * Add all the clocks used by the s3c2410 or compatible CPUs + * such as the S3C2440 and S3C2442. + * + * We cannot use a system device as we are needed before any + * of the init-calls that initialise the devices are actually + * done. +*/ + +int __init s3c2410_baseclk_add(void) +{ + unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW); + unsigned long clkcon = __raw_readl(S3C2410_CLKCON); + struct clk *clkp; + struct clk *xtal; + int ret; + int ptr; + + clk_upll.enable = s3c2410_upll_enable; + + if (s3c24xx_register_clock(&clk_usb_bus) < 0) + printk(KERN_ERR "failed to register usb bus clock\n"); + + /* register clocks from clock array */ + + clkp = init_clocks; + for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) { + /* ensure that we note the clock state */ + + clkp->usage = clkcon & clkp->ctrlbit ? 1 : 0; + + ret = s3c24xx_register_clock(clkp); + if (ret < 0) { + printk(KERN_ERR "Failed to register clock %s (%d)\n", + clkp->name, ret); + } + } + + /* We must be careful disabling the clocks we are not intending to + * be using at boot time, as subsytems such as the LCD which do + * their own DMA requests to the bus can cause the system to lockup + * if they where in the middle of requesting bus access. + * + * Disabling the LCD clock if the LCD is active is very dangerous, + * and therefore the bootloader should be careful to not enable + * the LCD clock if it is not needed. + */ + + /* install (and disable) the clocks we do not need immediately */ + + clkp = init_clocks_disable; + for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) { + + ret = s3c24xx_register_clock(clkp); + if (ret < 0) { + printk(KERN_ERR "Failed to register clock %s (%d)\n", + clkp->name, ret); + } + + s3c2410_clkcon_enable(clkp, 0); + } + + /* show the clock-slow value */ + + xtal = clk_get(NULL, "xtal"); + + printk("CLOCK: Slow mode (%ld.%ld MHz), %s, MPLL %s, UPLL %s\n", + print_mhz(clk_get_rate(xtal) / + ( 2 * S3C2410_CLKSLOW_GET_SLOWVAL(clkslow))), + (clkslow & S3C2410_CLKSLOW_SLOW) ? "slow" : "fast", + (clkslow & S3C2410_CLKSLOW_MPLL_OFF) ? "off" : "on", + (clkslow & S3C2410_CLKSLOW_UCLK_OFF) ? "off" : "on"); + + return 0; +} diff --git a/arch/arm/mach-s3c2410/s3c2410.c b/arch/arm/mach-s3c2410/s3c2410.c index cb252ddf3c7..a110cff9cf6 100644 --- a/arch/arm/mach-s3c2410/s3c2410.c +++ b/arch/arm/mach-s3c2410/s3c2410.c @@ -109,6 +109,7 @@ void __init s3c2410_init_clocks(int xtal) */ s3c24xx_setup_clocks(xtal, fclk, hclk, pclk); + s3c2410_baseclk_add(); } struct sysdev_class s3c2410_sysclass = { diff --git a/arch/arm/mach-s3c2410/s3c2410.h b/arch/arm/mach-s3c2410/s3c2410.h index 4d5312a4820..73f1a2474a6 100644 --- a/arch/arm/mach-s3c2410/s3c2410.h +++ b/arch/arm/mach-s3c2410/s3c2410.h @@ -29,6 +29,8 @@ extern void s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no); extern void s3c2410_init_clocks(int xtal); +extern int s3c2410_baseclk_add(void); + #else #define s3c2410_init_clocks NULL #define s3c2410_init_uarts NULL diff --git a/arch/arm/mach-s3c2410/s3c2440-clock.c b/arch/arm/mach-s3c2410/s3c2440-clock.c index d7a30ed6c32..15796864d01 100644 --- a/arch/arm/mach-s3c2410/s3c2440-clock.c +++ b/arch/arm/mach-s3c2410/s3c2440-clock.c @@ -91,7 +91,7 @@ static int s3c2440_camif_upll_setrate(struct clk *clk, unsigned long rate) static struct clk s3c2440_clk_cam = { .name = "camif", .id = -1, - .enable = s3c24xx_clkcon_enable, + .enable = s3c2410_clkcon_enable, .ctrlbit = S3C2440_CLKCON_CAMERA, }; @@ -105,7 +105,7 @@ static struct clk s3c2440_clk_cam_upll = { static struct clk s3c2440_clk_ac97 = { .name = "ac97", .id = -1, - .enable = s3c24xx_clkcon_enable, + .enable = s3c2410_clkcon_enable, .ctrlbit = S3C2440_CLKCON_CAMERA, }; diff --git a/arch/arm/mach-s3c2410/s3c2442-clock.c b/arch/arm/mach-s3c2410/s3c2442-clock.c index 5b7b301eb52..d9f54b5cab7 100644 --- a/arch/arm/mach-s3c2410/s3c2442-clock.c +++ b/arch/arm/mach-s3c2410/s3c2442-clock.c @@ -102,7 +102,7 @@ static int s3c2442_camif_upll_setrate(struct clk *clk, unsigned long rate) static struct clk s3c2442_clk_cam = { .name = "camif", .id = -1, - .enable = s3c24xx_clkcon_enable, + .enable = s3c2410_clkcon_enable, .ctrlbit = S3C2440_CLKCON_CAMERA, }; diff --git a/arch/arm/mach-s3c2410/s3c244x.c b/arch/arm/mach-s3c2410/s3c244x.c index 96852a7000d..838bc525e83 100644 --- a/arch/arm/mach-s3c2410/s3c244x.c +++ b/arch/arm/mach-s3c2410/s3c244x.c @@ -34,6 +34,7 @@ #include #include +#include "s3c2410.h" #include "s3c2440.h" #include "s3c244x.h" #include "clock.h" @@ -118,6 +119,7 @@ void __init s3c244x_init_clocks(int xtal) */ s3c24xx_setup_clocks(xtal, fclk, hclk, pclk); + s3c2410_baseclk_add(); } #ifdef CONFIG_PM -- cgit v1.2.3 From 92b7eb8ffc0741f1fd5fbd5458a466d608310442 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 22 Jun 2006 22:18:21 +0100 Subject: [ARM] 3628/1: S3C24XX: add get_rate call to struct clk Patch from Ben Dooks Add a get_rate call to allow an given clock to over-ride the clk_get_rate() call. This provides support for clocks which rely on division of their parent to correctly report their frequency when the parent can also change. Signed-off-by: Ben Dooks Signed-off-by: Russell King --- arch/arm/mach-s3c2410/clock.c | 7 +++++-- arch/arm/mach-s3c2410/clock.h | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-s3c2410/clock.c b/arch/arm/mach-s3c2410/clock.c index f553e5ee747..c5c93c333ac 100644 --- a/arch/arm/mach-s3c2410/clock.c +++ b/arch/arm/mach-s3c2410/clock.c @@ -148,8 +148,11 @@ unsigned long clk_get_rate(struct clk *clk) if (clk->rate != 0) return clk->rate; - while (clk->parent != NULL && clk->rate == 0) - clk = clk->parent; + if (clk->get_rate != NULL) + return (clk->get_rate)(clk); + + if (clk->parent != NULL) + return clk_get_rate(clk->parent); return clk->rate; } diff --git a/arch/arm/mach-s3c2410/clock.h b/arch/arm/mach-s3c2410/clock.h index 1bee5708c35..9456c81eb5d 100644 --- a/arch/arm/mach-s3c2410/clock.h +++ b/arch/arm/mach-s3c2410/clock.h @@ -22,6 +22,7 @@ struct clk { int (*enable)(struct clk *, int enable); int (*set_rate)(struct clk *c, unsigned long rate); + unsigned long (*get_rate)(struct clk *c); unsigned long (*round_rate)(struct clk *c, unsigned long rate); int (*set_parent)(struct clk *c, struct clk *parent); }; -- cgit v1.2.3 From f606a6ff222dc7dceeb4d0e214ce4f55d9c6b0e6 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Thu, 22 Jun 2006 22:18:45 +0100 Subject: [ARM] 3626/1: ARM EABI: fix syscall restarting Patch from Nicolas Pitre The RESTARTBLOCK case currently store some code on the stack to invoke sys_restart_syscall. However this is ABI dependent and there is a mismatch with the way __NR_restart_syscall gets defined when the kernel is compiled for EABI. There is also a long standing bug in the thumb case since with OABI the __NR_restart_syscall value includes __NR_SYSCALL_BASE which should not be the case for Thumb syscalls. Credits to Yauheni Kaliuta for finding the EABI bug. Signed-off-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/kernel/signal.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index a0cd0a90a10..e9fe7803336 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c @@ -665,17 +665,33 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall) if (syscall) { if (regs->ARM_r0 == -ERESTART_RESTARTBLOCK) { if (thumb_mode(regs)) { - regs->ARM_r7 = __NR_restart_syscall; + regs->ARM_r7 = __NR_restart_syscall - __NR_SYSCALL_BASE; regs->ARM_pc -= 2; } else { +#if defined(CONFIG_AEABI) && !defined(CONFIG_OABI_COMPAT) + regs->ARM_r7 = __NR_restart_syscall; + regs->ARM_pc -= 4; +#else u32 __user *usp; + u32 swival = __NR_restart_syscall; regs->ARM_sp -= 12; usp = (u32 __user *)regs->ARM_sp; + /* + * Either we supports OABI only, or we have + * EABI with the OABI compat layer enabled. + * In the later case we don't know if user + * space is EABI or not, and if not we must + * not clobber r7. Always using the OABI + * syscall solves that issue and works for + * all those cases. + */ + swival = swival - __NR_SYSCAll_BASE + __NR_OABI_SYSCALL_BASE; + put_user(regs->ARM_pc, &usp[0]); /* swi __NR_restart_syscall */ - put_user(0xef000000 | __NR_restart_syscall, &usp[1]); + put_user(0xef000000 | swival, &usp[1]); /* ldr pc, [sp], #12 */ put_user(0xe49df00c, &usp[2]); @@ -683,6 +699,7 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall) (unsigned long)(usp + 3)); regs->ARM_pc = regs->ARM_sp + 4; +#endif } } if (regs->ARM_r0 == -ERESTARTNOHAND || -- cgit v1.2.3 From df6934b33c43a3ad517244935fe9c19715d9dc15 Mon Sep 17 00:00:00 2001 From: Rod Whitby Date: Thu, 22 Jun 2006 22:21:01 +0100 Subject: [ARM] 3595/1: ixp4xx/nas100d: Board support for new LED subsystem Patch from Rod Whitby This patch implements NEW_LEDS support for the IOMega NAS100d. The NAS100d has three LED indicators, which are the only form of output for an unmodified device - there is no keyboard or display on an NAS100d. For an NAS100d which has been modified to bring out the serial port console, it is important to register that device first separately, to enable debugging of other device support. Signed-off-by: John Bowler Signed-off-by: Rod Whitby Signed-off-by: Deepak Saxena Signed-off-by: Russell King --- arch/arm/mach-ixp4xx/nas100d-setup.c | 41 +++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-ixp4xx/nas100d-setup.c b/arch/arm/mach-ixp4xx/nas100d-setup.c index a3b4c6ac570..9a31444d921 100644 --- a/arch/arm/mach-ixp4xx/nas100d-setup.c +++ b/arch/arm/mach-ixp4xx/nas100d-setup.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -37,6 +38,36 @@ static struct platform_device nas100d_flash = { .resource = &nas100d_flash_resource, }; +#ifdef CONFIG_LEDS_IXP4XX +static struct resource nas100d_led_resources[] = { + { + .name = "wlan", /* green led */ + .start = 0, + .end = 0, + .flags = IXP4XX_GPIO_LOW, + }, + { + .name = "ready", /* blue power led (off is flashing!) */ + .start = 15, + .end = 15, + .flags = IXP4XX_GPIO_LOW, + }, + { + .name = "disk", /* yellow led */ + .start = 3, + .end = 3, + .flags = IXP4XX_GPIO_LOW, + }, +}; + +static struct platform_device nas100d_leds = { + .name = "IXP4XX-GPIO-LED", + .id = -1, + .num_resources = ARRAY_SIZE(nas100d_led_resources), + .resource = nas100d_led_resources, +}; +#endif + static struct ixp4xx_i2c_pins nas100d_i2c_gpio_pins = { .sda_pin = NAS100D_SDA_PIN, .scl_pin = NAS100D_SCL_PIN, @@ -95,7 +126,9 @@ static struct platform_device nas100d_uart = { static struct platform_device *nas100d_devices[] __initdata = { &nas100d_i2c_controller, &nas100d_flash, - &nas100d_uart, +#ifdef CONFIG_LEDS_IXP4XX + &nas100d_leds, +#endif }; static void nas100d_power_off(void) @@ -122,6 +155,12 @@ static void __init nas100d_init(void) pm_power_off = nas100d_power_off; + /* This is only useful on a modified machine, but it is valuable + * to have it first in order to see debug messages, and so that + * it does *not* get removed if platform_add_devices fails! + */ + (void)platform_device_register(&nas100d_uart); + platform_add_devices(nas100d_devices, ARRAY_SIZE(nas100d_devices)); } -- cgit v1.2.3 From e22b04fb6b1689aee208b65966fa9fb19e098006 Mon Sep 17 00:00:00 2001 From: Rod Whitby Date: Thu, 22 Jun 2006 22:21:02 +0100 Subject: [ARM] 3597/1: ixp4xx/nslu2: Board support for new LED subsystem Patch from Rod Whitby This patch implements NEW_LEDS support for the Linksys NSLU2. The NSLU2 has four LED indicators, which are the only form of output for an unmodified device - there is no keyboard or display on an NSLU2. For an NSLU2 which has been modified to bring out the serial port console, it is important to register that device first separately, to enable debugging of other device support. Signed-off-by: John Bowler Signed-off-by: Rod Whitby Signed-off-by: Deepak Saxena Signed-off-by: Russell King --- arch/arm/mach-ixp4xx/nslu2-setup.c | 48 +++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-ixp4xx/nslu2-setup.c b/arch/arm/mach-ixp4xx/nslu2-setup.c index 55411f21d83..749a337494d 100644 --- a/arch/arm/mach-ixp4xx/nslu2-setup.c +++ b/arch/arm/mach-ixp4xx/nslu2-setup.c @@ -7,6 +7,7 @@ * Copyright (C) 2003-2004 MontaVista Software, Inc. * * Author: Mark Rakes + * Author: Rod Whitby * Maintainers: http://www.nslu2-linux.org/ * * Fixed missing init_time in MACHINE_START kas11 10/22/04 @@ -16,6 +17,7 @@ #include #include #include +#include #include #include @@ -43,6 +45,42 @@ static struct ixp4xx_i2c_pins nslu2_i2c_gpio_pins = { .scl_pin = NSLU2_SCL_PIN, }; +#ifdef CONFIG_LEDS_IXP4XX +static struct resource nslu2_led_resources[] = { + { + .name = "ready", /* green led */ + .start = NSLU2_LED_GRN, + .end = NSLU2_LED_GRN, + .flags = IXP4XX_GPIO_HIGH, + }, + { + .name = "status", /* red led */ + .start = NSLU2_LED_RED, + .end = NSLU2_LED_RED, + .flags = IXP4XX_GPIO_HIGH, + }, + { + .name = "disk-1", + .start = NSLU2_LED_DISK1, + .end = NSLU2_LED_DISK1, + .flags = IXP4XX_GPIO_LOW, + }, + { + .name = "disk-2", + .start = NSLU2_LED_DISK2, + .end = NSLU2_LED_DISK2, + .flags = IXP4XX_GPIO_LOW, + }, +}; + +static struct platform_device nslu2_leds = { + .name = "IXP4XX-GPIO-LED", + .id = -1, + .num_resources = ARRAY_SIZE(nslu2_led_resources), + .resource = nslu2_led_resources, +}; +#endif + static struct platform_device nslu2_i2c_controller = { .name = "IXP4XX-I2C", .id = 0, @@ -102,8 +140,10 @@ static struct platform_device nslu2_uart = { static struct platform_device *nslu2_devices[] __initdata = { &nslu2_i2c_controller, &nslu2_flash, - &nslu2_uart, &nslu2_beeper, +#ifdef CONFIG_LEDS_IXP4XX + &nslu2_leds, +#endif }; static void nslu2_power_off(void) @@ -127,6 +167,12 @@ static void __init nslu2_init(void) pm_power_off = nslu2_power_off; + /* This is only useful on a modified machine, but it is valuable + * to have it first in order to see debug messages, and so that + * it does *not* get removed if platform_add_devices fails! + */ + (void)platform_device_register(&nslu2_uart); + platform_add_devices(nslu2_devices, ARRAY_SIZE(nslu2_devices)); } -- cgit v1.2.3 From fa3e686a34f4c33de31a128cc36def0b466bfe1a Mon Sep 17 00:00:00 2001 From: Pavel Pisa Date: Thu, 22 Jun 2006 22:21:03 +0100 Subject: [ARM] 3601/1: i.MX/MX1 DMA error handling for signaled channels only Patch from Pavel Pisa There has been bug, that dma_err_handler() touches even channels not signaling error condition. Problem noticed by Andrea Paterniani. Signed-off-by: Pavel Pisa Signed-off-by: Russell King --- arch/arm/mach-imx/dma.c | 65 +++++++++++++++++++++++--------------- include/asm-arm/arch-imx/imx-dma.h | 8 +++-- 2 files changed, 45 insertions(+), 28 deletions(-) diff --git a/arch/arm/mach-imx/dma.c b/arch/arm/mach-imx/dma.c index 4ca51dcf13a..36578871ecc 100644 --- a/arch/arm/mach-imx/dma.c +++ b/arch/arm/mach-imx/dma.c @@ -15,6 +15,9 @@ * Changed to support scatter gather DMA * by taking Russell's code from RiscPC * + * 2006-05-31 Pavel Pisa + * Corrected error handling code. + * */ #undef DEBUG @@ -277,7 +280,7 @@ imx_dma_setup_sg(imx_dmach_t dma_ch, int imx_dma_setup_handlers(imx_dmach_t dma_ch, void (*irq_handler) (int, void *, struct pt_regs *), - void (*err_handler) (int, void *, struct pt_regs *), + void (*err_handler) (int, void *, struct pt_regs *, int), void *data) { struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch]; @@ -463,43 +466,53 @@ static irqreturn_t dma_err_handler(int irq, void *dev_id, struct pt_regs *regs) int i, disr = DISR; struct imx_dma_channel *channel; unsigned int err_mask = DBTOSR | DRTOSR | DSESR | DBOSR; + int errcode; - DISR = disr; + DISR = disr & err_mask; for (i = 0; i < IMX_DMA_CHANNELS; i++) { - channel = &imx_dma_channels[i]; - - if ((err_mask & 1 << i) && channel->name - && channel->err_handler) { - channel->err_handler(i, channel->data, regs); + if(!(err_mask & (1 << i))) continue; - } - - imx_dma_channels[i].sg = NULL; + channel = &imx_dma_channels[i]; + errcode = 0; if (DBTOSR & (1 << i)) { - printk(KERN_WARNING - "Burst timeout on channel %d (%s)\n", - i, channel->name); - DBTOSR |= (1 << i); + DBTOSR = (1 << i); + errcode |= IMX_DMA_ERR_BURST; } if (DRTOSR & (1 << i)) { - printk(KERN_WARNING - "Request timeout on channel %d (%s)\n", - i, channel->name); - DRTOSR |= (1 << i); + DRTOSR = (1 << i); + errcode |= IMX_DMA_ERR_REQUEST; } if (DSESR & (1 << i)) { - printk(KERN_WARNING - "Transfer timeout on channel %d (%s)\n", - i, channel->name); - DSESR |= (1 << i); + DSESR = (1 << i); + errcode |= IMX_DMA_ERR_TRANSFER; } if (DBOSR & (1 << i)) { - printk(KERN_WARNING - "Buffer overflow timeout on channel %d (%s)\n", - i, channel->name); - DBOSR |= (1 << i); + DBOSR = (1 << i); + errcode |= IMX_DMA_ERR_BUFFER; } + + /* + * The cleaning of @sg field would be questionable + * there, because its value can help to compute + * remaining/transfered bytes count in the handler + */ + /*imx_dma_channels[i].sg = NULL;*/ + + if (channel->name && channel->err_handler) { + channel->err_handler(i, channel->data, regs, errcode); + continue; + } + + imx_dma_channels[i].sg = NULL; + + printk(KERN_WARNING + "DMA timeout on channel %d (%s) -%s%s%s%s\n", + i, channel->name, + errcode&IMX_DMA_ERR_BURST? " burst":"", + errcode&IMX_DMA_ERR_REQUEST? " request":"", + errcode&IMX_DMA_ERR_TRANSFER? " transfer":"", + errcode&IMX_DMA_ERR_BUFFER? " buffer":""); } return IRQ_HANDLED; } diff --git a/include/asm-arm/arch-imx/imx-dma.h b/include/asm-arm/arch-imx/imx-dma.h index f2063c1d610..599f03e5a9e 100644 --- a/include/asm-arm/arch-imx/imx-dma.h +++ b/include/asm-arm/arch-imx/imx-dma.h @@ -46,7 +46,7 @@ struct imx_dma_channel { const char *name; void (*irq_handler) (int, void *, struct pt_regs *); - void (*err_handler) (int, void *, struct pt_regs *); + void (*err_handler) (int, void *, struct pt_regs *, int errcode); void *data; dmamode_t dma_mode; struct scatterlist *sg; @@ -58,6 +58,10 @@ struct imx_dma_channel { extern struct imx_dma_channel imx_dma_channels[IMX_DMA_CHANNELS]; +#define IMX_DMA_ERR_BURST 1 +#define IMX_DMA_ERR_REQUEST 2 +#define IMX_DMA_ERR_TRANSFER 4 +#define IMX_DMA_ERR_BUFFER 8 /* The type to distinguish channel numbers parameter from ordinal int type */ typedef int imx_dmach_t; @@ -74,7 +78,7 @@ imx_dma_setup_sg(imx_dmach_t dma_ch, int imx_dma_setup_handlers(imx_dmach_t dma_ch, void (*irq_handler) (int, void *, struct pt_regs *), - void (*err_handler) (int, void *, struct pt_regs *), void *data); + void (*err_handler) (int, void *, struct pt_regs *, int), void *data); void imx_dma_enable(imx_dmach_t dma_ch); -- cgit v1.2.3 From 823588c18689ddd49d4643eda7654302f18a275f Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Thu, 22 Jun 2006 22:27:14 +0100 Subject: [ARM] 3537/1: Rework DMA-bounce locking for finer granularity Patch from Kevin Hilman This time with IRQ versions of locks. Rework also enables compatability with realtime-preemption patch. With the current locking via interrupt disabling, under RT, potentially sleeping functions can be called with interrupts disabled. Signed-off-by: Kevin Hilman Signed-off-by: Deepak Saxena Signed-off-by: Russell King --- arch/arm/common/dmabounce.c | 67 ++++++++++++++------------------------------- 1 file changed, 21 insertions(+), 46 deletions(-) diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c index 7971d0dc689..5b7c26395b4 100644 --- a/arch/arm/common/dmabounce.c +++ b/arch/arm/common/dmabounce.c @@ -77,6 +77,8 @@ struct dmabounce_device_info { #endif struct dmabounce_pool small; struct dmabounce_pool large; + + rwlock_t lock; }; static LIST_HEAD(dmabounce_devs); @@ -116,6 +118,7 @@ alloc_safe_buffer(struct dmabounce_device_info *device_info, void *ptr, struct safe_buffer *buf; struct dmabounce_pool *pool; struct device *dev = device_info->dev; + unsigned long flags; dev_dbg(dev, "%s(ptr=%p, size=%d, dir=%d)\n", __func__, ptr, size, dir); @@ -163,8 +166,12 @@ alloc_safe_buffer(struct dmabounce_device_info *device_info, void *ptr, print_alloc_stats(device_info); #endif + write_lock_irqsave(&device_info->lock, flags); + list_add(&buf->node, &device_info->safe_buffers); + write_unlock_irqrestore(&device_info->lock, flags); + return buf; } @@ -172,22 +179,32 @@ alloc_safe_buffer(struct dmabounce_device_info *device_info, void *ptr, static inline struct safe_buffer * find_safe_buffer(struct dmabounce_device_info *device_info, dma_addr_t safe_dma_addr) { - struct safe_buffer *b; + struct safe_buffer *b = NULL; + unsigned long flags; + + read_lock_irqsave(&device_info->lock, flags); list_for_each_entry(b, &device_info->safe_buffers, node) if (b->safe_dma_addr == safe_dma_addr) - return b; + break; - return NULL; + read_unlock_irqrestore(&device_info->lock, flags); + return b; } static inline void free_safe_buffer(struct dmabounce_device_info *device_info, struct safe_buffer *buf) { + unsigned long flags; + dev_dbg(device_info->dev, "%s(buf=%p)\n", __func__, buf); + write_lock_irqsave(&device_info->lock, flags); + list_del(&buf->node); + write_unlock_irqrestore(&device_info->lock, flags); + if (buf->pool) dma_pool_free(buf->pool->pool, buf->safe, buf->safe_dma_addr); else @@ -396,7 +413,6 @@ dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, enum dma_data_direction dir) { - unsigned long flags; dma_addr_t dma_addr; dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n", @@ -404,12 +420,8 @@ dma_map_single(struct device *dev, void *ptr, size_t size, BUG_ON(dir == DMA_NONE); - local_irq_save(flags); - dma_addr = map_single(dev, ptr, size, dir); - local_irq_restore(flags); - return dma_addr; } @@ -424,25 +436,18 @@ void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, enum dma_data_direction dir) { - unsigned long flags; - dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n", __func__, (void *) dma_addr, size, dir); BUG_ON(dir == DMA_NONE); - local_irq_save(flags); - unmap_single(dev, dma_addr, size, dir); - - local_irq_restore(flags); } int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, enum dma_data_direction dir) { - unsigned long flags; int i; dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n", @@ -450,8 +455,6 @@ dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, BUG_ON(dir == DMA_NONE); - local_irq_save(flags); - for (i = 0; i < nents; i++, sg++) { struct page *page = sg->page; unsigned int offset = sg->offset; @@ -462,8 +465,6 @@ dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, map_single(dev, ptr, length, dir); } - local_irq_restore(flags); - return nents; } @@ -471,7 +472,6 @@ void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents, enum dma_data_direction dir) { - unsigned long flags; int i; dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n", @@ -479,55 +479,38 @@ dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents, BUG_ON(dir == DMA_NONE); - local_irq_save(flags); - for (i = 0; i < nents; i++, sg++) { dma_addr_t dma_addr = sg->dma_address; unsigned int length = sg->length; unmap_single(dev, dma_addr, length, dir); } - - local_irq_restore(flags); } void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_addr, size_t size, enum dma_data_direction dir) { - unsigned long flags; - dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n", __func__, (void *) dma_addr, size, dir); - local_irq_save(flags); - sync_single(dev, dma_addr, size, dir); - - local_irq_restore(flags); } void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_addr, size_t size, enum dma_data_direction dir) { - unsigned long flags; - dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n", __func__, (void *) dma_addr, size, dir); - local_irq_save(flags); - sync_single(dev, dma_addr, size, dir); - - local_irq_restore(flags); } void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nents, enum dma_data_direction dir) { - unsigned long flags; int i; dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n", @@ -535,23 +518,18 @@ dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nents, BUG_ON(dir == DMA_NONE); - local_irq_save(flags); - for (i = 0; i < nents; i++, sg++) { dma_addr_t dma_addr = sg->dma_address; unsigned int length = sg->length; sync_single(dev, dma_addr, length, dir); } - - local_irq_restore(flags); } void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents, enum dma_data_direction dir) { - unsigned long flags; int i; dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n", @@ -559,16 +537,12 @@ dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents, BUG_ON(dir == DMA_NONE); - local_irq_save(flags); - for (i = 0; i < nents; i++, sg++) { dma_addr_t dma_addr = sg->dma_address; unsigned int length = sg->length; sync_single(dev, dma_addr, length, dir); } - - local_irq_restore(flags); } static int @@ -622,6 +596,7 @@ dmabounce_register_dev(struct device *dev, unsigned long small_buffer_size, device_info->dev = dev; INIT_LIST_HEAD(&device_info->safe_buffers); + rwlock_init(&device_info->lock); #ifdef STATS device_info->total_allocs = 0; -- cgit v1.2.3 From 02916526133aebc0b3b6c486d1b0af95221033bd Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 22 Jun 2006 22:57:54 +0100 Subject: [ARM] 3629/1: S3C24XX: fix missing bracket in regs-dsc.h Patch from Ben Dooks Fix missing bracket in include/asm-arm/arch-s3c2410/regs-dsc.h Signed-off-by: Ben Dooks Signed-off-by: Russell King --- include/asm-arm/arch-s3c2410/regs-dsc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/asm-arm/arch-s3c2410/regs-dsc.h b/include/asm-arm/arch-s3c2410/regs-dsc.h index a023b0434ef..ba13a2c9e54 100644 --- a/include/asm-arm/arch-s3c2410/regs-dsc.h +++ b/include/asm-arm/arch-s3c2410/regs-dsc.h @@ -170,7 +170,7 @@ #define S3C2440_DSC1_CS1_4mA (3<<2) #define S3C2440_DSC1_CS1_MASK (3<<2) -#define S3C2440_DSC1_CS0 (S3C2440_SELECT_DSC1 | 0 +#define S3C2440_DSC1_CS0 (S3C2440_SELECT_DSC1 | 0) #define S3C2440_DSC1_CS0_10mA (0<<0) #define S3C2440_DSC1_CS0_8mA (1<<0) #define S3C2440_DSC1_CS0_6mA (2<<0) -- cgit v1.2.3 From 7f98a44b9d09580036da7e7f8b33e66f411cf374 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Thu, 22 Jun 2006 14:47:09 -0700 Subject: [PATCH] UML: fix wall_to_monotonic initialization Change a variable from unsigned to signed in order to get sign-extension when the thing is negated. Without this, uptime is horribly confused. Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/kernel/time_kern.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/um/kernel/time_kern.c b/arch/um/kernel/time_kern.c index 86f51d04c98..87cdbc560d3 100644 --- a/arch/um/kernel/time_kern.c +++ b/arch/um/kernel/time_kern.c @@ -87,7 +87,7 @@ void timer_irq(union uml_pt_regs *regs) void time_init_kern(void) { - unsigned long long nsecs; + long long nsecs; nsecs = os_nsecs(); set_normalized_timespec(&wall_to_monotonic, -nsecs / BILLION, -- cgit v1.2.3 From 5d2170ad1092b2940138dc3ae4a944d7bf87ae9e Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 22 Jun 2006 14:47:14 -0700 Subject: [PATCH] sparc build breakage rd_prompt et.al. depend on CONFIG_BLK_DEV_RAM, not CONFIG_BLK_INITRD; now that those are independent, setup.c blows with INITRD on and BLK_DEV_RAM off. Signed-off-by: Al Viro Cc: "David S. Miller" Cc: William Lee Irwin III Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/sparc/kernel/setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c index 2cbf282f0d0..a893a9cc953 100644 --- a/arch/sparc/kernel/setup.c +++ b/arch/sparc/kernel/setup.c @@ -332,7 +332,7 @@ void __init setup_arch(char **cmdline_p) if (!root_flags) root_mountflags &= ~MS_RDONLY; ROOT_DEV = old_decode_dev(root_dev); -#ifdef CONFIG_BLK_DEV_INITRD +#ifdef CONFIG_BLK_DEV_RAM rd_image_start = ram_flags & RAMDISK_IMAGE_START_MASK; rd_prompt = ((ram_flags & RAMDISK_PROMPT_FLAG) != 0); rd_doload = ((ram_flags & RAMDISK_LOAD_FLAG) != 0); -- cgit v1.2.3 From f893afbe1262e27e91234506f72e17716190dd2f Mon Sep 17 00:00:00 2001 From: Anton Altaparmakov Date: Thu, 22 Jun 2006 14:47:15 -0700 Subject: [PATCH] NTFS: Critical bug fix (affects MIPS and possibly others) Many thanks to Pauline Ng for the detailed bug report and analysis! Signed-off-by: Anton Altaparmakov Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ntfs/file.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c index c63a83e8da9..36e1e136bb0 100644 --- a/fs/ntfs/file.c +++ b/fs/ntfs/file.c @@ -1484,14 +1484,15 @@ static inline void ntfs_flush_dcache_pages(struct page **pages, unsigned nr_pages) { BUG_ON(!nr_pages); + /* + * Warning: Do not do the decrement at the same time as the call to + * flush_dcache_page() because it is a NULL macro on i386 and hence the + * decrement never happens so the loop never terminates. + */ do { - /* - * Warning: Do not do the decrement at the same time as the - * call because flush_dcache_page() is a NULL macro on i386 - * and hence the decrement never happens. - */ + --nr_pages; flush_dcache_page(pages[nr_pages]); - } while (--nr_pages > 0); + } while (nr_pages > 0); } /** -- cgit v1.2.3 From d720024e94de4e8b7f10ee83c532926f3ad5d708 Mon Sep 17 00:00:00 2001 From: Michael LeMay Date: Thu, 22 Jun 2006 14:47:17 -0700 Subject: [PATCH] selinux: add hooks for key subsystem Introduce SELinux hooks to support the access key retention subsystem within the kernel. Incorporate new flask headers from a modified version of the SELinux reference policy, with support for the new security class representing retained keys. Extend the "key_alloc" security hook with a task parameter representing the intended ownership context for the key being allocated. Attach security information to root's default keyrings within the SELinux initialization routine. Has passed David's testsuite. Signed-off-by: Michael LeMay Signed-off-by: David Howells Signed-off-by: James Morris Acked-by: Chris Wright Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/keys.txt | 29 +++++++++++++ include/linux/key.h | 18 +++++--- include/linux/security.h | 10 +++-- kernel/user.c | 2 +- security/dummy.c | 2 +- security/keys/key.c | 8 ++-- security/keys/keyring.c | 5 ++- security/keys/process_keys.c | 15 ++++--- security/keys/request_key.c | 6 ++- security/keys/request_key_auth.c | 2 +- security/selinux/hooks.c | 64 ++++++++++++++++++++++++++++ security/selinux/include/av_perm_to_string.h | 6 +++ security/selinux/include/av_permissions.h | 8 ++++ security/selinux/include/class_to_string.h | 1 + security/selinux/include/flask.h | 1 + security/selinux/include/objsec.h | 5 +++ 16 files changed, 155 insertions(+), 27 deletions(-) diff --git a/Documentation/keys.txt b/Documentation/keys.txt index aaa01b0e3ee..70302001270 100644 --- a/Documentation/keys.txt +++ b/Documentation/keys.txt @@ -19,6 +19,7 @@ This document has the following sections: - Key overview - Key service overview - Key access permissions + - SELinux support - New procfs files - Userspace system call interface - Kernel services @@ -232,6 +233,34 @@ For changing the ownership, group ID or permissions mask, being the owner of the key or having the sysadmin capability is sufficient. +=============== +SELINUX SUPPORT +=============== + +The security class "key" has been added to SELinux so that mandatory access +controls can be applied to keys created within various contexts. This support +is preliminary, and is likely to change quite significantly in the near future. +Currently, all of the basic permissions explained above are provided in SELinux +as well; SE Linux is simply invoked after all basic permission checks have been +performed. + +Each key is labeled with the same context as the task to which it belongs. +Typically, this is the same task that was running when the key was created. +The default keyrings are handled differently, but in a way that is very +intuitive: + + (*) The user and user session keyrings that are created when the user logs in + are currently labeled with the context of the login manager. + + (*) The keyrings associated with new threads are each labeled with the context + of their associated thread, and both session and process keyrings are + handled similarly. + +Note, however, that the default keyrings associated with the root user are +labeled with the default kernel context, since they are created early in the +boot process, before root has a chance to log in. + + ================ NEW PROCFS FILES ================ diff --git a/include/linux/key.h b/include/linux/key.h index cbf464ad958..8c275d12ef6 100644 --- a/include/linux/key.h +++ b/include/linux/key.h @@ -241,8 +241,9 @@ extern void unregister_key_type(struct key_type *ktype); extern struct key *key_alloc(struct key_type *type, const char *desc, - uid_t uid, gid_t gid, key_perm_t perm, - int not_in_quota); + uid_t uid, gid_t gid, + struct task_struct *ctx, + key_perm_t perm, int not_in_quota); extern int key_payload_reserve(struct key *key, size_t datalen); extern int key_instantiate_and_link(struct key *key, const void *data, @@ -292,7 +293,9 @@ extern int key_unlink(struct key *keyring, struct key *key); extern struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, - int not_in_quota, struct key *dest); + struct task_struct *ctx, + int not_in_quota, + struct key *dest); extern int keyring_clear(struct key *keyring); @@ -313,7 +316,8 @@ extern void keyring_replace_payload(struct key *key, void *replacement); * the userspace interface */ extern struct key root_user_keyring, root_session_keyring; -extern int alloc_uid_keyring(struct user_struct *user); +extern int alloc_uid_keyring(struct user_struct *user, + struct task_struct *ctx); extern void switch_uid_keyring(struct user_struct *new_user); extern int copy_keys(unsigned long clone_flags, struct task_struct *tsk); extern int copy_thread_group_keys(struct task_struct *tsk); @@ -342,7 +346,7 @@ extern void key_init(void); #define make_key_ref(k) ({ NULL; }) #define key_ref_to_ptr(k) ({ NULL; }) #define is_key_possessed(k) 0 -#define alloc_uid_keyring(u) 0 +#define alloc_uid_keyring(u,c) 0 #define switch_uid_keyring(u) do { } while(0) #define __install_session_keyring(t, k) ({ NULL; }) #define copy_keys(f,t) 0 @@ -355,6 +359,10 @@ extern void key_init(void); #define key_fsgid_changed(t) do { } while(0) #define key_init() do { } while(0) +/* Initial keyrings */ +extern struct key root_user_keyring; +extern struct key root_session_keyring; + #endif /* CONFIG_KEYS */ #endif /* __KERNEL__ */ #endif /* _LINUX_KEY_H */ diff --git a/include/linux/security.h b/include/linux/security.h index 4dfb1b84a9b..47722d35553 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -1313,7 +1313,7 @@ struct security_operations { /* key management security hooks */ #ifdef CONFIG_KEYS - int (*key_alloc)(struct key *key); + int (*key_alloc)(struct key *key, struct task_struct *tsk); void (*key_free)(struct key *key); int (*key_permission)(key_ref_t key_ref, struct task_struct *context, @@ -3008,9 +3008,10 @@ static inline int security_xfrm_policy_lookup(struct xfrm_policy *xp, u32 sk_sid #ifdef CONFIG_KEYS #ifdef CONFIG_SECURITY -static inline int security_key_alloc(struct key *key) +static inline int security_key_alloc(struct key *key, + struct task_struct *tsk) { - return security_ops->key_alloc(key); + return security_ops->key_alloc(key, tsk); } static inline void security_key_free(struct key *key) @@ -3027,7 +3028,8 @@ static inline int security_key_permission(key_ref_t key_ref, #else -static inline int security_key_alloc(struct key *key) +static inline int security_key_alloc(struct key *key, + struct task_struct *tsk) { return 0; } diff --git a/kernel/user.c b/kernel/user.c index 4b1eb745afa..6408c042429 100644 --- a/kernel/user.c +++ b/kernel/user.c @@ -148,7 +148,7 @@ struct user_struct * alloc_uid(uid_t uid) new->mq_bytes = 0; new->locked_shm = 0; - if (alloc_uid_keyring(new) < 0) { + if (alloc_uid_keyring(new, current) < 0) { kmem_cache_free(uid_cachep, new); return NULL; } diff --git a/security/dummy.c b/security/dummy.c index 64f6da0f422..6de4a4a5eb1 100644 --- a/security/dummy.c +++ b/security/dummy.c @@ -860,7 +860,7 @@ static int dummy_setprocattr(struct task_struct *p, char *name, void *value, siz } #ifdef CONFIG_KEYS -static inline int dummy_key_alloc(struct key *key) +static inline int dummy_key_alloc(struct key *key, struct task_struct *ctx) { return 0; } diff --git a/security/keys/key.c b/security/keys/key.c index 3fdc49c6a02..14a15abb773 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -247,8 +247,8 @@ static inline void key_alloc_serial(struct key *key) * instantiate the key or discard it before returning */ struct key *key_alloc(struct key_type *type, const char *desc, - uid_t uid, gid_t gid, key_perm_t perm, - int not_in_quota) + uid_t uid, gid_t gid, struct task_struct *ctx, + key_perm_t perm, int not_in_quota) { struct key_user *user = NULL; struct key *key; @@ -318,7 +318,7 @@ struct key *key_alloc(struct key_type *type, const char *desc, #endif /* let the security module know about the key */ - ret = security_key_alloc(key); + ret = security_key_alloc(key, ctx); if (ret < 0) goto security_error; @@ -822,7 +822,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, /* allocate a new key */ key = key_alloc(ktype, description, current->fsuid, current->fsgid, - perm, not_in_quota); + current, perm, not_in_quota); if (IS_ERR(key)) { key_ref = ERR_PTR(PTR_ERR(key)); goto error_3; diff --git a/security/keys/keyring.c b/security/keys/keyring.c index bffa924c1f8..1357207fc9d 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c @@ -240,13 +240,14 @@ static long keyring_read(const struct key *keyring, * allocate a keyring and link into the destination keyring */ struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, - int not_in_quota, struct key *dest) + struct task_struct *ctx, int not_in_quota, + struct key *dest) { struct key *keyring; int ret; keyring = key_alloc(&key_type_keyring, description, - uid, gid, + uid, gid, ctx, (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL, not_in_quota); diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 217a0bef3c8..a50a91332fe 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c @@ -67,7 +67,8 @@ struct key root_session_keyring = { /* * allocate the keyrings to be associated with a UID */ -int alloc_uid_keyring(struct user_struct *user) +int alloc_uid_keyring(struct user_struct *user, + struct task_struct *ctx) { struct key *uid_keyring, *session_keyring; char buf[20]; @@ -76,7 +77,7 @@ int alloc_uid_keyring(struct user_struct *user) /* concoct a default session keyring */ sprintf(buf, "_uid_ses.%u", user->uid); - session_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, 0, NULL); + session_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx, 0, NULL); if (IS_ERR(session_keyring)) { ret = PTR_ERR(session_keyring); goto error; @@ -86,7 +87,7 @@ int alloc_uid_keyring(struct user_struct *user) * keyring */ sprintf(buf, "_uid.%u", user->uid); - uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, 0, + uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx, 0, session_keyring); if (IS_ERR(uid_keyring)) { key_put(session_keyring); @@ -143,7 +144,7 @@ int install_thread_keyring(struct task_struct *tsk) sprintf(buf, "_tid.%u", tsk->pid); - keyring = keyring_alloc(buf, tsk->uid, tsk->gid, 1, NULL); + keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, 1, NULL); if (IS_ERR(keyring)) { ret = PTR_ERR(keyring); goto error; @@ -177,7 +178,7 @@ int install_process_keyring(struct task_struct *tsk) if (!tsk->signal->process_keyring) { sprintf(buf, "_pid.%u", tsk->tgid); - keyring = keyring_alloc(buf, tsk->uid, tsk->gid, 1, NULL); + keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, 1, NULL); if (IS_ERR(keyring)) { ret = PTR_ERR(keyring); goto error; @@ -217,7 +218,7 @@ static int install_session_keyring(struct task_struct *tsk, if (!keyring) { sprintf(buf, "_ses.%u", tsk->tgid); - keyring = keyring_alloc(buf, tsk->uid, tsk->gid, 1, NULL); + keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, 1, NULL); if (IS_ERR(keyring)) return PTR_ERR(keyring); } @@ -717,7 +718,7 @@ long join_session_keyring(const char *name) keyring = find_keyring_by_name(name, 0); if (PTR_ERR(keyring) == -ENOKEY) { /* not found - try and create a new one */ - keyring = keyring_alloc(name, tsk->uid, tsk->gid, 0, NULL); + keyring = keyring_alloc(name, tsk->uid, tsk->gid, tsk, 0, NULL); if (IS_ERR(keyring)) { ret = PTR_ERR(keyring); goto error2; diff --git a/security/keys/request_key.c b/security/keys/request_key.c index f030a0ccbb9..eab66a06ca5 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c @@ -48,7 +48,8 @@ static int call_sbin_request_key(struct key *key, /* allocate a new session keyring */ sprintf(desc, "_req.%u", key->serial); - keyring = keyring_alloc(desc, current->fsuid, current->fsgid, 1, NULL); + keyring = keyring_alloc(desc, current->fsuid, current->fsgid, + current, 1, NULL); if (IS_ERR(keyring)) { ret = PTR_ERR(keyring); goto error_alloc; @@ -137,7 +138,8 @@ static struct key *__request_key_construction(struct key_type *type, /* create a key and add it to the queue */ key = key_alloc(type, description, - current->fsuid, current->fsgid, KEY_POS_ALL, 0); + current->fsuid, current->fsgid, + current, KEY_POS_ALL, 0); if (IS_ERR(key)) goto alloc_failed; diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c index cce6ba6b032..0ecc2e8d2bd 100644 --- a/security/keys/request_key_auth.c +++ b/security/keys/request_key_auth.c @@ -148,7 +148,7 @@ struct key *request_key_auth_new(struct key *target, const char *callout_info) sprintf(desc, "%x", target->serial); authkey = key_alloc(&key_type_request_key_auth, desc, - current->fsuid, current->fsgid, + current->fsuid, current->fsgid, current, KEY_POS_VIEW | KEY_POS_READ | KEY_POS_SEARCH | KEY_USR_VIEW, 1); if (IS_ERR(authkey)) { diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 54adc9d31e9..524915dfda6 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -4252,6 +4252,57 @@ static int selinux_setprocattr(struct task_struct *p, return size; } +#ifdef CONFIG_KEYS + +static int selinux_key_alloc(struct key *k, struct task_struct *tsk) +{ + struct task_security_struct *tsec = tsk->security; + struct key_security_struct *ksec; + + ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL); + if (!ksec) + return -ENOMEM; + + ksec->obj = k; + ksec->sid = tsec->sid; + k->security = ksec; + + return 0; +} + +static void selinux_key_free(struct key *k) +{ + struct key_security_struct *ksec = k->security; + + k->security = NULL; + kfree(ksec); +} + +static int selinux_key_permission(key_ref_t key_ref, + struct task_struct *ctx, + key_perm_t perm) +{ + struct key *key; + struct task_security_struct *tsec; + struct key_security_struct *ksec; + + key = key_ref_to_ptr(key_ref); + + tsec = ctx->security; + ksec = key->security; + + /* if no specific permissions are requested, we skip the + permission check. No serious, additional covert channels + appear to be created. */ + if (perm == 0) + return 0; + + return avc_has_perm(tsec->sid, ksec->sid, + SECCLASS_KEY, perm, NULL); +} + +#endif + static struct security_operations selinux_ops = { .ptrace = selinux_ptrace, .capget = selinux_capget, @@ -4406,6 +4457,12 @@ static struct security_operations selinux_ops = { .xfrm_state_delete_security = selinux_xfrm_state_delete, .xfrm_policy_lookup = selinux_xfrm_policy_lookup, #endif + +#ifdef CONFIG_KEYS + .key_alloc = selinux_key_alloc, + .key_free = selinux_key_free, + .key_permission = selinux_key_permission, +#endif }; static __init int selinux_init(void) @@ -4441,6 +4498,13 @@ static __init int selinux_init(void) } else { printk(KERN_INFO "SELinux: Starting in permissive mode\n"); } + +#ifdef CONFIG_KEYS + /* Add security information to initial keyrings */ + security_key_alloc(&root_user_keyring, current); + security_key_alloc(&root_session_keyring, current); +#endif + return 0; } diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h index 70ee65a5881..bc020bde6c8 100644 --- a/security/selinux/include/av_perm_to_string.h +++ b/security/selinux/include/av_perm_to_string.h @@ -242,3 +242,9 @@ S_(SECCLASS_PACKET, PACKET__SEND, "send") S_(SECCLASS_PACKET, PACKET__RECV, "recv") S_(SECCLASS_PACKET, PACKET__RELABELTO, "relabelto") + S_(SECCLASS_KEY, KEY__VIEW, "view") + S_(SECCLASS_KEY, KEY__READ, "read") + S_(SECCLASS_KEY, KEY__WRITE, "write") + S_(SECCLASS_KEY, KEY__SEARCH, "search") + S_(SECCLASS_KEY, KEY__LINK, "link") + S_(SECCLASS_KEY, KEY__SETATTR, "setattr") diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h index 1d9cf3d306b..1205227a3a3 100644 --- a/security/selinux/include/av_permissions.h +++ b/security/selinux/include/av_permissions.h @@ -959,3 +959,11 @@ #define PACKET__SEND 0x00000001UL #define PACKET__RECV 0x00000002UL #define PACKET__RELABELTO 0x00000004UL + +#define KEY__VIEW 0x00000001UL +#define KEY__READ 0x00000002UL +#define KEY__WRITE 0x00000004UL +#define KEY__SEARCH 0x00000008UL +#define KEY__LINK 0x00000010UL +#define KEY__SETATTR 0x00000020UL + diff --git a/security/selinux/include/class_to_string.h b/security/selinux/include/class_to_string.h index 3aec75fee4f..24303b61309 100644 --- a/security/selinux/include/class_to_string.h +++ b/security/selinux/include/class_to_string.h @@ -60,3 +60,4 @@ S_("netlink_kobject_uevent_socket") S_("appletalk_socket") S_("packet") + S_("key") diff --git a/security/selinux/include/flask.h b/security/selinux/include/flask.h index a0eb9e281d1..95887aed2a6 100644 --- a/security/selinux/include/flask.h +++ b/security/selinux/include/flask.h @@ -62,6 +62,7 @@ #define SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET 55 #define SECCLASS_APPLETALK_SOCKET 56 #define SECCLASS_PACKET 57 +#define SECCLASS_KEY 58 /* * Security identifier indices for initial entities diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index 54c03077888..8f5547ad185 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h @@ -99,6 +99,11 @@ struct sk_security_struct { u32 peer_sid; /* SID of peer */ }; +struct key_security_struct { + struct key *obj; /* back pointer */ + u32 sid; /* SID of key */ +}; + extern unsigned int selinux_checkreqprot; #endif /* _SELINUX_OBJSEC_H_ */ -- cgit v1.2.3 From 04c567d9313e4927b9835361d8ac0318ce65af6b Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 22 Jun 2006 14:47:18 -0700 Subject: [PATCH] Keys: Fix race between two instantiators of a key Add a revocation notification method to the key type and calls it whilst the key's semaphore is still write-locked after setting the revocation flag. The patch then uses this to maintain a reference on the task_struct of the process that calls request_key() for as long as the authorisation key remains unrevoked. This fixes a potential race between two processes both of which have assumed the authority to instantiate a key (one may have forked the other for example). The problem is that there's no locking around the check for revocation of the auth key and the use of the task_struct it points to, nor does the auth key keep a reference on the task_struct. Access to the "context" pointer in the auth key must thenceforth be done with the auth key semaphore held. The revocation method is called with the target key semaphore held write-locked and the search of the context process's keyrings is done with the auth key semaphore read-locked. The check for the revocation state of the auth key just prior to searching it is done after the auth key is read-locked for the search. This ensures that the auth key can't be revoked between the check and the search. The revocation notification method is added so that the context task_struct can be released as soon as instantiation happens rather than waiting for the auth key to be destroyed, thus avoiding the unnecessary pinning of the requesting process. Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/keys.txt | 10 +++++++++ include/linux/key.h | 5 +++++ security/keys/key.c | 4 ++++ security/keys/process_keys.c | 42 +++++++++++++++++++++++-------------- security/keys/request_key_auth.c | 45 +++++++++++++++++++++++++++++++++++++++- 5 files changed, 89 insertions(+), 17 deletions(-) diff --git a/Documentation/keys.txt b/Documentation/keys.txt index 70302001270..3bbe157b45e 100644 --- a/Documentation/keys.txt +++ b/Documentation/keys.txt @@ -964,6 +964,16 @@ The structure has a number of fields, some of which are mandatory: It is not safe to sleep in this method; the caller may hold spinlocks. + (*) void (*revoke)(struct key *key); + + This method is optional. It is called to discard part of the payload + data upon a key being revoked. The caller will have the key semaphore + write-locked. + + It is safe to sleep in this method, though care should be taken to avoid + a deadlock against the key semaphore. + + (*) void (*destroy)(struct key *key); This method is optional. It is called to discard the payload data on a key diff --git a/include/linux/key.h b/include/linux/key.h index 8c275d12ef6..e81ebf910d0 100644 --- a/include/linux/key.h +++ b/include/linux/key.h @@ -205,6 +205,11 @@ struct key_type { /* match a key against a description */ int (*match)(const struct key *key, const void *desc); + /* clear some of the data from a key on revokation (optional) + * - the key's semaphore will be write-locked by the caller + */ + void (*revoke)(struct key *key); + /* clear the data from a key (optional) */ void (*destroy)(struct key *key); diff --git a/security/keys/key.c b/security/keys/key.c index 14a15abb773..51f85155738 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -907,6 +907,10 @@ void key_revoke(struct key *key) * it */ down_write(&key->sem); set_bit(KEY_FLAG_REVOKED, &key->flags); + + if (key->type->revoke) + key->type->revoke(key); + up_write(&key->sem); } /* end key_revoke() */ diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index a50a91332fe..4d9825f9962 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c @@ -391,6 +391,8 @@ key_ref_t search_process_keyrings(struct key_type *type, struct request_key_auth *rka; key_ref_t key_ref, ret, err; + might_sleep(); + /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were * searchable, but we failed to find a key or we found a negative key; * otherwise we want to return a sample error (probably -EACCES) if @@ -496,27 +498,35 @@ key_ref_t search_process_keyrings(struct key_type *type, */ if (context->request_key_auth && context == current && - type != &key_type_request_key_auth && - key_validate(context->request_key_auth) == 0 + type != &key_type_request_key_auth ) { - rka = context->request_key_auth->payload.data; + /* defend against the auth key being revoked */ + down_read(&context->request_key_auth->sem); - key_ref = search_process_keyrings(type, description, match, - rka->context); + if (key_validate(context->request_key_auth) == 0) { + rka = context->request_key_auth->payload.data; - if (!IS_ERR(key_ref)) - goto found; + key_ref = search_process_keyrings(type, description, + match, rka->context); - switch (PTR_ERR(key_ref)) { - case -EAGAIN: /* no key */ - if (ret) + up_read(&context->request_key_auth->sem); + + if (!IS_ERR(key_ref)) + goto found; + + switch (PTR_ERR(key_ref)) { + case -EAGAIN: /* no key */ + if (ret) + break; + case -ENOKEY: /* negative key */ + ret = key_ref; break; - case -ENOKEY: /* negative key */ - ret = key_ref; - break; - default: - err = key_ref; - break; + default: + err = key_ref; + break; + } + } else { + up_read(&context->request_key_auth->sem); } } diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c index 0ecc2e8d2bd..cb9817ced3f 100644 --- a/security/keys/request_key_auth.c +++ b/security/keys/request_key_auth.c @@ -20,6 +20,7 @@ static int request_key_auth_instantiate(struct key *, const void *, size_t); static void request_key_auth_describe(const struct key *, struct seq_file *); +static void request_key_auth_revoke(struct key *); static void request_key_auth_destroy(struct key *); static long request_key_auth_read(const struct key *, char __user *, size_t); @@ -31,6 +32,7 @@ struct key_type key_type_request_key_auth = { .def_datalen = sizeof(struct request_key_auth), .instantiate = request_key_auth_instantiate, .describe = request_key_auth_describe, + .revoke = request_key_auth_revoke, .destroy = request_key_auth_destroy, .read = request_key_auth_read, }; @@ -91,6 +93,24 @@ static long request_key_auth_read(const struct key *key, } /* end request_key_auth_read() */ +/*****************************************************************************/ +/* + * handle revocation of an authorisation token key + * - called with the key sem write-locked + */ +static void request_key_auth_revoke(struct key *key) +{ + struct request_key_auth *rka = key->payload.data; + + kenter("{%d}", key->serial); + + if (rka->context) { + put_task_struct(rka->context); + rka->context = NULL; + } + +} /* end request_key_auth_revoke() */ + /*****************************************************************************/ /* * destroy an instantiation authorisation token key @@ -101,6 +121,11 @@ static void request_key_auth_destroy(struct key *key) kenter("{%d}", key->serial); + if (rka->context) { + put_task_struct(rka->context); + rka->context = NULL; + } + key_put(rka->target_key); kfree(rka); @@ -131,14 +156,26 @@ struct key *request_key_auth_new(struct key *target, const char *callout_info) * another process */ if (current->request_key_auth) { /* it is - use that instantiation context here too */ + down_read(¤t->request_key_auth->sem); + + /* if the auth key has been revoked, then the key we're + * servicing is already instantiated */ + if (test_bit(KEY_FLAG_REVOKED, + ¤t->request_key_auth->flags)) + goto auth_key_revoked; + irka = current->request_key_auth->payload.data; rka->context = irka->context; rka->pid = irka->pid; + get_task_struct(rka->context); + + up_read(¤t->request_key_auth->sem); } else { /* it isn't - use this process as the context */ rka->context = current; rka->pid = current->pid; + get_task_struct(rka->context); } rka->target_key = key_get(target); @@ -161,9 +198,15 @@ struct key *request_key_auth_new(struct key *target, const char *callout_info) if (ret < 0) goto error_inst; - kleave(" = {%d})", authkey->serial); + kleave(" = {%d}", authkey->serial); return authkey; +auth_key_revoked: + up_read(¤t->request_key_auth->sem); + kfree(rka); + kleave("= -EKEYREVOKED"); + return ERR_PTR(-EKEYREVOKED); + error_inst: key_revoke(authkey); key_put(authkey); -- cgit v1.2.3 From 6cc0719181a7aa8883855140541e7892250e66af Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 22 Jun 2006 14:47:18 -0700 Subject: [PATCH] suspend_console() warning fix kernel/power/main.c: In function 'suspend_prepare': kernel/power/main.c:89: warning: implicit declaration of function 'suspend_console' kernel/power/main.c: In function 'suspend_finish': kernel/power/main.c:137: warning: implicit declaration of function 'resume_console' Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/power/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/power/main.c b/kernel/power/main.c index 0a907f0dc56..cdf0f07af92 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c @@ -15,7 +15,7 @@ #include #include #include - +#include #include "power.h" -- cgit v1.2.3 From bec0e85910b95c325a008ead7c3bbe047cc39672 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 22 Jun 2006 14:47:19 -0700 Subject: [PATCH] myri10ge build fix Someone changed skb_linearize(). Cc: Brice Goglin Cc: "David S. Miller" Cc: Jeff Garzik Cc: Herbert Xu Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/myri10ge/myri10ge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index e1feb58bd66..1a2b9785e99 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -2120,7 +2120,7 @@ abort_linearize: goto drop; } - if (skb_linearize(skb, GFP_ATOMIC)) + if (skb_linearize(skb)) goto drop; mgp->tx_linearized++; -- cgit v1.2.3 From 0e5b3781591cc954037c08ef78edf7f1192d38c5 Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Thu, 22 Jun 2006 14:47:20 -0700 Subject: [PATCH] PCI: Add PCI_CAP_ID_VNDR Add the vendor-specific extended capability PCI_CAP_ID_VNDR. It is required by the Myri-10G Ethernet driver. Signed-off-by: Brice Goglin Signed-off-by: Greg Kroah-Hartman Cc: Jeff Garzik Cc: "David S. Miller" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/pci_regs.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h index d27a78b7129..6bce4a24036 100644 --- a/include/linux/pci_regs.h +++ b/include/linux/pci_regs.h @@ -197,6 +197,7 @@ #define PCI_CAP_ID_CHSWP 0x06 /* CompactPCI HotSwap */ #define PCI_CAP_ID_PCIX 0x07 /* PCI-X */ #define PCI_CAP_ID_HT_IRQCONF 0x08 /* HyperTransport IRQ Configuration */ +#define PCI_CAP_ID_VNDR 0x09 /* Vendor specific capability */ #define PCI_CAP_ID_SHPC 0x0C /* PCI Standard Hot-Plug Controller */ #define PCI_CAP_ID_EXP 0x10 /* PCI Express */ #define PCI_CAP_ID_MSIX 0x11 /* MSI-X */ -- cgit v1.2.3 From 09d967c6f32b35eab15b45862ae16e4f06259d8e Mon Sep 17 00:00:00 2001 From: OGAWA Hirofumi Date: Thu, 22 Jun 2006 14:47:21 -0700 Subject: [PATCH] Fix a race condition between ->i_mapping and iput() This race became a cause of oops, and can reproduce by the following. while true; do dd if=/dev/zero of=/dev/.static/dev/hdg1 bs=512 count=1000 & sync done This race condition was between __sync_single_inode() and iput(). cpu0 (fs's inode) cpu1 (bdev's inode) ----------------- ------------------- close("/dev/hda2") [...] __sync_single_inode() /* copy the bdev's ->i_mapping */ mapping = inode->i_mapping; generic_forget_inode() bdev_clear_inode() /* restre the fs's ->i_mapping */ inode->i_mapping = &inode->i_data; /* bdev's inode was freed */ destroy_inode(inode); if (wait) { /* dereference a freed bdev's mapping->host */ filemap_fdatawait(mapping); /* Oops */ Since __sync_single_inode() is only taking a ref-count of fs's inode, the another process can be close() and freeing the bdev's inode while writing fs's inode. So, __sync_signle_inode() accesses the freed ->i_mapping, oops. This patch takes a ref-count on the bdev's inode for the fs's inode before setting a ->i_mapping, and the clear_inode() of the fs's inode does iput() on the bdev's inode. So if the fs's inode is still living, bdev's inode shouldn't be freed. Signed-off-by: OGAWA Hirofumi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/block_dev.c | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/fs/block_dev.c b/fs/block_dev.c index f5958f413bd..44aaba202f7 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -414,21 +414,31 @@ EXPORT_SYMBOL(bdput); static struct block_device *bd_acquire(struct inode *inode) { struct block_device *bdev; + spin_lock(&bdev_lock); bdev = inode->i_bdev; - if (bdev && igrab(bdev->bd_inode)) { + if (bdev) { + atomic_inc(&bdev->bd_inode->i_count); spin_unlock(&bdev_lock); return bdev; } spin_unlock(&bdev_lock); + bdev = bdget(inode->i_rdev); if (bdev) { spin_lock(&bdev_lock); - if (inode->i_bdev) - __bd_forget(inode); - inode->i_bdev = bdev; - inode->i_mapping = bdev->bd_inode->i_mapping; - list_add(&inode->i_devices, &bdev->bd_inodes); + if (!inode->i_bdev) { + /* + * We take an additional bd_inode->i_count for inode, + * and it's released in clear_inode() of inode. + * So, we can access it via ->i_mapping always + * without igrab(). + */ + atomic_inc(&bdev->bd_inode->i_count); + inode->i_bdev = bdev; + inode->i_mapping = bdev->bd_inode->i_mapping; + list_add(&inode->i_devices, &bdev->bd_inodes); + } spin_unlock(&bdev_lock); } return bdev; @@ -438,10 +448,18 @@ static struct block_device *bd_acquire(struct inode *inode) void bd_forget(struct inode *inode) { + struct block_device *bdev = NULL; + spin_lock(&bdev_lock); - if (inode->i_bdev) + if (inode->i_bdev) { + if (inode->i_sb != blockdev_superblock) + bdev = inode->i_bdev; __bd_forget(inode); + } spin_unlock(&bdev_lock); + + if (bdev) + iput(bdev->bd_inode); } int bd_claim(struct block_device *bdev, void *holder) -- cgit v1.2.3 From c89681ed7d0e4a61d35bdc12c06c6733b718b2cb Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Thu, 22 Jun 2006 14:47:22 -0700 Subject: [PATCH] remove steal_locks() This patch removes the steal_locks() function. steal_locks() doesn't work correctly with any filesystem that does it's own lock management, including NFS, CIFS, etc. In addition it has weird semantics on local filesystems in case tasks sharing file-descriptor tables are doing POSIX locking operations in parallel to execve(). The steal_locks() function has an effect on applications doing: clone(CLONE_FILES) /* in child */ lock execve lock POSIX locks acquired before execve (by "child", "parent" or any further task sharing files_struct) will after the execve be owned exclusively by "child". According to Chris Wright some LSB/LTP kind of suite triggers without the stealing behavior, but there's no known real-world application that would also fail. Apps using NPTL are not affected, since all other threads are killed before execve. Apps using LinuxThreads are only affected if they - have multiple threads during exec (LinuxThreads doesn't kill other threads, the app may do it with pthread_kill_other_threads_np()) - rely on POSIX locks being inherited across exec Both conditions are documented, but not their interaction. Apps using clone() natively are affected if they - use clone(CLONE_FILES) - rely on POSIX locks being inherited across exec The above scenarios are unlikely, but possible. If the patch is vetoed, there's a plan B, that involves mostly keeping the weird stealing semantics, but changing the way lock ownership is handled so that network and local filesystems work consistently. That would add more complexity though, so this solution seems to be preferred by most people. Signed-off-by: Miklos Szeredi Cc: Trond Myklebust Cc: Matthew Wilcox Cc: Chris Wright Cc: Christoph Hellwig Cc: Steven French Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/binfmt_elf.c | 1 - fs/binfmt_misc.c | 1 - fs/exec.c | 1 - fs/locks.c | 57 ------------------------------------------------------ include/linux/fs.h | 1 - 5 files changed, 61 deletions(-) diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 537893a1601..8a04216e8b4 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -759,7 +759,6 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) /* Discard our unneeded old files struct */ if (files) { - steal_locks(files); put_files_struct(files); files = NULL; } diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index d73d75591a3..599f36fd0f6 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c @@ -203,7 +203,6 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs) goto _error; if (files) { - steal_locks(files); put_files_struct(files); files = NULL; } diff --git a/fs/exec.c b/fs/exec.c index d07858c0b7c..0b88bf64614 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -866,7 +866,6 @@ int flush_old_exec(struct linux_binprm * bprm) bprm->mm = NULL; /* We're using it now */ /* This is the point of no return */ - steal_locks(files); put_files_struct(files); current->sas_ss_sp = current->sas_ss_size = 0; diff --git a/fs/locks.c b/fs/locks.c index ab61a8b5482..69435c68c1e 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -2206,63 +2206,6 @@ int lock_may_write(struct inode *inode, loff_t start, unsigned long len) EXPORT_SYMBOL(lock_may_write); -static inline void __steal_locks(struct file *file, fl_owner_t from) -{ - struct inode *inode = file->f_dentry->d_inode; - struct file_lock *fl = inode->i_flock; - - while (fl) { - if (fl->fl_file == file && fl->fl_owner == from) - fl->fl_owner = current->files; - fl = fl->fl_next; - } -} - -/* When getting ready for executing a binary, we make sure that current - * has a files_struct on its own. Before dropping the old files_struct, - * we take over ownership of all locks for all file descriptors we own. - * Note that we may accidentally steal a lock for a file that a sibling - * has created since the unshare_files() call. - */ -void steal_locks(fl_owner_t from) -{ - struct files_struct *files = current->files; - int i, j; - struct fdtable *fdt; - - if (from == files) - return; - - lock_kernel(); - j = 0; - - /* - * We are not taking a ref to the file structures, so - * we need to acquire ->file_lock. - */ - spin_lock(&files->file_lock); - fdt = files_fdtable(files); - for (;;) { - unsigned long set; - i = j * __NFDBITS; - if (i >= fdt->max_fdset || i >= fdt->max_fds) - break; - set = fdt->open_fds->fds_bits[j++]; - while (set) { - if (set & 1) { - struct file *file = fdt->fd[i]; - if (file) - __steal_locks(file, from); - } - i++; - set >>= 1; - } - } - spin_unlock(&files->file_lock); - unlock_kernel(); -} -EXPORT_SYMBOL(steal_locks); - static int __init filelock_init(void) { filelock_cache = kmem_cache_create("file_lock_cache", diff --git a/include/linux/fs.h b/include/linux/fs.h index ecc8c2c3d8c..73c7d6f04b3 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -782,7 +782,6 @@ extern int setlease(struct file *, long, struct file_lock **); extern int lease_modify(struct file_lock **, int); extern int lock_may_read(struct inode *, loff_t start, unsigned long count); extern int lock_may_write(struct inode *, loff_t start, unsigned long count); -extern void steal_locks(fl_owner_t from); struct fasync_struct { int magic; -- cgit v1.2.3 From de047c1bcd7f7bcfbdc29eb5b439fb332594da3f Mon Sep 17 00:00:00 2001 From: Ravikiran G Thirumalai Date: Thu, 22 Jun 2006 14:47:26 -0700 Subject: [PATCH] avoid tasklist_lock at getrusage for multithreaded case too Avoid taking tasklist_lock for at getrusage for the multithreaded case too. We don't need to take the tasklist lock for thread traversal of a process since Oleg's do-__unhash_process-under-siglock.patch and related work. Signed-off-by: Ravikiran Thirumalai Cc: Oleg Nesterov Cc: "Eric W. Biederman" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/sys.c | 56 ++++++++++++++++++++++---------------------------------- 1 file changed, 22 insertions(+), 34 deletions(-) diff --git a/kernel/sys.c b/kernel/sys.c index 0b6ec0e7936..fc9ebbbaba0 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -1860,23 +1860,20 @@ out: * fields when reaping, so a sample either gets all the additions of a * given child after it's reaped, or none so this sample is before reaping. * - * tasklist_lock locking optimisation: - * If we are current and single threaded, we do not need to take the tasklist - * lock or the siglock. No one else can take our signal_struct away, - * no one else can reap the children to update signal->c* counters, and - * no one else can race with the signal-> fields. - * If we do not take the tasklist_lock, the signal-> fields could be read - * out of order while another thread was just exiting. So we place a - * read memory barrier when we avoid the lock. On the writer side, - * write memory barrier is implied in __exit_signal as __exit_signal releases - * the siglock spinlock after updating the signal-> fields. - * - * We don't really need the siglock when we access the non c* fields - * of the signal_struct (for RUSAGE_SELF) even in multithreaded - * case, since we take the tasklist lock for read and the non c* signal-> - * fields are updated only in __exit_signal, which is called with - * tasklist_lock taken for write, hence these two threads cannot execute - * concurrently. + * Locking: + * We need to take the siglock for CHILDEREN, SELF and BOTH + * for the cases current multithreaded, non-current single threaded + * non-current multithreaded. Thread traversal is now safe with + * the siglock held. + * Strictly speaking, we donot need to take the siglock if we are current and + * single threaded, as no one else can take our signal_struct away, no one + * else can reap the children to update signal->c* counters, and no one else + * can race with the signal-> fields. If we do not take any lock, the + * signal-> fields could be read out of order while another thread was just + * exiting. So we should place a read memory barrier when we avoid the lock. + * On the writer side, write memory barrier is implied in __exit_signal + * as __exit_signal releases the siglock spinlock after updating the signal-> + * fields. But we don't do this yet to keep things simple. * */ @@ -1885,35 +1882,25 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r) struct task_struct *t; unsigned long flags; cputime_t utime, stime; - int need_lock = 0; memset((char *) r, 0, sizeof *r); utime = stime = cputime_zero; - if (p != current || !thread_group_empty(p)) - need_lock = 1; - - if (need_lock) { - read_lock(&tasklist_lock); - if (unlikely(!p->signal)) { - read_unlock(&tasklist_lock); - return; - } - } else - /* See locking comments above */ - smp_rmb(); + rcu_read_lock(); + if (!lock_task_sighand(p, &flags)) { + rcu_read_unlock(); + return; + } switch (who) { case RUSAGE_BOTH: case RUSAGE_CHILDREN: - spin_lock_irqsave(&p->sighand->siglock, flags); utime = p->signal->cutime; stime = p->signal->cstime; r->ru_nvcsw = p->signal->cnvcsw; r->ru_nivcsw = p->signal->cnivcsw; r->ru_minflt = p->signal->cmin_flt; r->ru_majflt = p->signal->cmaj_flt; - spin_unlock_irqrestore(&p->sighand->siglock, flags); if (who == RUSAGE_CHILDREN) break; @@ -1941,8 +1928,9 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r) BUG(); } - if (need_lock) - read_unlock(&tasklist_lock); + unlock_task_sighand(p, &flags); + rcu_read_unlock(); + cputime_to_timeval(utime, &r->ru_utime); cputime_to_timeval(stime, &r->ru_stime); } -- cgit v1.2.3 From 0feae5c47aabdde59cbbec32d150e17102de37f0 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 22 Jun 2006 14:47:28 -0700 Subject: [PATCH] Fix dcache race during umount The race is that the shrink_dcache_memory shrinker could get called while a filesystem is being unmounted, and could try to prune a dentry belonging to that filesystem. If it does, then it will call in to iput on the inode while the dentry is no longer able to be found by the umounting process. If iput takes a while, generic_shutdown_super could get all the way though shrink_dcache_parent and shrink_dcache_anon and invalidate_inodes without ever waiting on this particular inode. Eventually the superblock gets freed anyway and if the iput tried to touch it (which some filesystems certainly do), it will lose. The promised "Self-destruct in 5 seconds" doesn't lead to a nice day. The race is closed by holding s_umount while calling prune_one_dentry on someone else's dentry. As a down_read_trylock is used, shrink_dcache_memory will no longer try to prune the dentry of a filesystem that is being unmounted, and unmount will not be able to start until any such active prune_one_dentry completes. This requires that prune_dcache *knows* which filesystem (if any) it is doing the prune on behalf of so that it can be careful of other filesystems. shrink_dcache_memory isn't called it on behalf of any filesystem, and so is careful of everything. shrink_dcache_anon is now passed a super_block rather than the s_anon list out of the superblock, so it can get the s_anon list itself, and can pass the superblock down to prune_dcache. If prune_dcache finds a dentry that it cannot free, it leaves it where it is (at the tail of the list) and exits, on the assumption that some other thread will be removing that dentry soon. To try to make sure that some work gets done, a limited number of dnetries which are untouchable are skipped over while choosing the dentry to work on. I believe this race was first found by Kirill Korotaev. Cc: Jan Blunck Acked-by: Kirill Korotaev Cc: Olaf Hering Acked-by: Balbir Singh Signed-off-by: Neil Brown Signed-off-by: Balbir Singh Acked-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/dcache.c | 66 +++++++++++++++++++++++++++++++++++++++++++++----- fs/super.c | 2 +- include/linux/dcache.h | 2 +- 3 files changed, 62 insertions(+), 8 deletions(-) diff --git a/fs/dcache.c b/fs/dcache.c index 940d188e5d1..385f5dbc4b0 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -382,6 +382,8 @@ static inline void prune_one_dentry(struct dentry * dentry) /** * prune_dcache - shrink the dcache * @count: number of entries to try and free + * @sb: if given, ignore dentries for other superblocks + * which are being unmounted. * * Shrink the dcache. This is done when we need * more memory, or simply when we need to unmount @@ -392,16 +394,29 @@ static inline void prune_one_dentry(struct dentry * dentry) * all the dentries are in use. */ -static void prune_dcache(int count) +static void prune_dcache(int count, struct super_block *sb) { spin_lock(&dcache_lock); for (; count ; count--) { struct dentry *dentry; struct list_head *tmp; + struct rw_semaphore *s_umount; cond_resched_lock(&dcache_lock); tmp = dentry_unused.prev; + if (unlikely(sb)) { + /* Try to find a dentry for this sb, but don't try + * too hard, if they aren't near the tail they will + * be moved down again soon + */ + int skip = count; + while (skip && tmp != &dentry_unused && + list_entry(tmp, struct dentry, d_lru)->d_sb != sb) { + skip--; + tmp = tmp->prev; + } + } if (tmp == &dentry_unused) break; list_del_init(tmp); @@ -427,7 +442,45 @@ static void prune_dcache(int count) spin_unlock(&dentry->d_lock); continue; } - prune_one_dentry(dentry); + /* + * If the dentry is not DCACHED_REFERENCED, it is time + * to remove it from the dcache, provided the super block is + * NULL (which means we are trying to reclaim memory) + * or this dentry belongs to the same super block that + * we want to shrink. + */ + /* + * If this dentry is for "my" filesystem, then I can prune it + * without taking the s_umount lock (I already hold it). + */ + if (sb && dentry->d_sb == sb) { + prune_one_dentry(dentry); + continue; + } + /* + * ...otherwise we need to be sure this filesystem isn't being + * unmounted, otherwise we could race with + * generic_shutdown_super(), and end up holding a reference to + * an inode while the filesystem is unmounted. + * So we try to get s_umount, and make sure s_root isn't NULL. + * (Take a local copy of s_umount to avoid a use-after-free of + * `dentry'). + */ + s_umount = &dentry->d_sb->s_umount; + if (down_read_trylock(s_umount)) { + if (dentry->d_sb->s_root != NULL) { + prune_one_dentry(dentry); + up_read(s_umount); + continue; + } + up_read(s_umount); + } + spin_unlock(&dentry->d_lock); + /* Cannot remove the first dentry, and it isn't appropriate + * to move it to the head of the list, so give up, and try + * later + */ + break; } spin_unlock(&dcache_lock); } @@ -630,7 +683,7 @@ void shrink_dcache_parent(struct dentry * parent) int found; while ((found = select_parent(parent)) != 0) - prune_dcache(found); + prune_dcache(found, parent->d_sb); } /** @@ -643,9 +696,10 @@ void shrink_dcache_parent(struct dentry * parent) * done under dcache_lock. * */ -void shrink_dcache_anon(struct hlist_head *head) +void shrink_dcache_anon(struct super_block *sb) { struct hlist_node *lp; + struct hlist_head *head = &sb->s_anon; int found; do { found = 0; @@ -668,7 +722,7 @@ void shrink_dcache_anon(struct hlist_head *head) } } spin_unlock(&dcache_lock); - prune_dcache(found); + prune_dcache(found, sb); } while(found); } @@ -689,7 +743,7 @@ static int shrink_dcache_memory(int nr, gfp_t gfp_mask) if (nr) { if (!(gfp_mask & __GFP_FS)) return -1; - prune_dcache(nr); + prune_dcache(nr, NULL); } return (dentry_stat.nr_unused / 100) * sysctl_vfs_cache_pressure; } diff --git a/fs/super.c b/fs/super.c index a66f66bb804..9d5c2add722 100644 --- a/fs/super.c +++ b/fs/super.c @@ -231,7 +231,7 @@ void generic_shutdown_super(struct super_block *sb) if (root) { sb->s_root = NULL; shrink_dcache_parent(root); - shrink_dcache_anon(&sb->s_anon); + shrink_dcache_anon(sb); dput(root); fsync_super(sb); lock_super(sb); diff --git a/include/linux/dcache.h b/include/linux/dcache.h index 836325ee093..46d0e079735 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -217,7 +217,7 @@ extern struct dentry * d_alloc_anon(struct inode *); extern struct dentry * d_splice_alias(struct inode *, struct dentry *); extern void shrink_dcache_sb(struct super_block *); extern void shrink_dcache_parent(struct dentry *); -extern void shrink_dcache_anon(struct hlist_head *); +extern void shrink_dcache_anon(struct super_block *); extern int d_invalidate(struct dentry *); /* only used at mount-time */ -- cgit v1.2.3 From d702ccb342e49f7591df5a87c3857c698183b0fa Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 22 Jun 2006 14:47:31 -0700 Subject: [PATCH] prune_one_dentry() tweaks - Add description of d_lock handling to comments over prune_one_dentry(). - It has three callsites - uninline it, saving 200 bytes of text. Cc: Jan Blunck Cc: Kirill Korotaev Cc: Olaf Hering Cc: Balbir Singh Cc: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/dcache.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/fs/dcache.c b/fs/dcache.c index 385f5dbc4b0..59dbc92c207 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -359,12 +359,13 @@ restart: } /* - * Throw away a dentry - free the inode, dput the parent. - * This requires that the LRU list has already been - * removed. + * Throw away a dentry - free the inode, dput the parent. This requires that + * the LRU list has already been removed. + * * Called with dcache_lock, drops it and then regains. + * Called with dentry->d_lock held, drops it. */ -static inline void prune_one_dentry(struct dentry * dentry) +static void prune_one_dentry(struct dentry * dentry) { struct dentry * parent; -- cgit v1.2.3 From 4f1bcaf094ccc512c23e10104c05a6f8e5b7a9e4 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 22 Jun 2006 14:47:32 -0700 Subject: [PATCH] vgacon: make VGA_MAP_MEM take size, remove extra use VGA_MAP_MEM translates to ioremap() on some architectures. It makes sense to do this to vga_vram_base, because we're going to access memory between vga_vram_base and vga_vram_end. But it doesn't really make sense to map starting at vga_vram_end, because we aren't going to access memory starting there. On ia64, which always has to be different, ioremapping vga_vram_end gives you something completely incompatible with ioremapped vga_vram_start, so vga_vram_size ends up being nonsense. As a bonus, we often know the size up front, so we can use ioremap() correctly, rather than giving it a zero size. Signed-off-by: Bjorn Helgaas Cc: "Antonino A. Daplas" Cc: "Luck, Tony" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/console/mdacon.c | 2 +- drivers/video/console/vgacon.c | 19 +++++++++---------- drivers/video/vga16fb.c | 2 +- include/asm-alpha/vga.h | 2 +- include/asm-arm/vga.h | 2 +- include/asm-i386/vga.h | 2 +- include/asm-ia64/vga.h | 2 +- include/asm-m32r/vga.h | 2 +- include/asm-mips/vga.h | 2 +- include/asm-powerpc/vga.h | 4 ++-- include/asm-sparc64/vga.h | 2 +- include/asm-x86_64/vga.h | 2 +- include/asm-xtensa/vga.h | 2 +- 13 files changed, 22 insertions(+), 23 deletions(-) diff --git a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c index 989e4d49e5b..7f939d066a5 100644 --- a/drivers/video/console/mdacon.c +++ b/drivers/video/console/mdacon.c @@ -313,8 +313,8 @@ static const char __init *mdacon_startup(void) mda_num_columns = 80; mda_num_lines = 25; - mda_vram_base = VGA_MAP_MEM(0xb0000); mda_vram_len = 0x01000; + mda_vram_base = VGA_MAP_MEM(0xb0000, mda_vram_len); mda_index_port = 0x3b4; mda_value_port = 0x3b5; diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index d5a04b68c4d..e64d42e2449 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -391,7 +391,7 @@ static const char __init *vgacon_startup(void) static struct resource ega_console_resource = { "ega", 0x3B0, 0x3BF }; vga_video_type = VIDEO_TYPE_EGAM; - vga_vram_end = 0xb8000; + vga_vram_size = 0x8000; display_desc = "EGA+"; request_resource(&ioport_resource, &ega_console_resource); @@ -401,7 +401,7 @@ static const char __init *vgacon_startup(void) static struct resource mda2_console_resource = { "mda", 0x3BF, 0x3BF }; vga_video_type = VIDEO_TYPE_MDA; - vga_vram_end = 0xb2000; + vga_vram_size = 0x2000; display_desc = "*MDA"; request_resource(&ioport_resource, &mda1_console_resource); @@ -418,7 +418,7 @@ static const char __init *vgacon_startup(void) if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10) { int i; - vga_vram_end = 0xc0000; + vga_vram_size = 0x8000; if (!ORIG_VIDEO_ISVGA) { static struct resource ega_console_resource @@ -443,7 +443,7 @@ static const char __init *vgacon_startup(void) * and COE=1 isn't necessarily a good idea) */ vga_vram_base = 0xa0000; - vga_vram_end = 0xb0000; + vga_vram_size = 0x10000; outb_p(6, VGA_GFX_I); outb_p(6, VGA_GFX_D); #endif @@ -475,7 +475,7 @@ static const char __init *vgacon_startup(void) static struct resource cga_console_resource = { "cga", 0x3D4, 0x3D5 }; vga_video_type = VIDEO_TYPE_CGA; - vga_vram_end = 0xba000; + vga_vram_size = 0x2000; display_desc = "*CGA"; request_resource(&ioport_resource, &cga_console_resource); @@ -483,9 +483,8 @@ static const char __init *vgacon_startup(void) } } - vga_vram_base = VGA_MAP_MEM(vga_vram_base); - vga_vram_end = VGA_MAP_MEM(vga_vram_end); - vga_vram_size = vga_vram_end - vga_vram_base; + vga_vram_base = VGA_MAP_MEM(vga_vram_base, vga_vram_size); + vga_vram_end = vga_vram_base + vga_vram_size; /* * Find out if there is a graphics card present. @@ -1020,14 +1019,14 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512) char *charmap; if (vga_video_type != VIDEO_TYPE_EGAM) { - charmap = (char *) VGA_MAP_MEM(colourmap); + charmap = (char *) VGA_MAP_MEM(colourmap, 0); beg = 0x0e; #ifdef VGA_CAN_DO_64KB if (vga_video_type == VIDEO_TYPE_VGAC) beg = 0x06; #endif } else { - charmap = (char *) VGA_MAP_MEM(blackwmap); + charmap = (char *) VGA_MAP_MEM(blackwmap, 0); beg = 0x0a; } diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c index f3f16fd9f23..4fd2a272e03 100644 --- a/drivers/video/vga16fb.c +++ b/drivers/video/vga16fb.c @@ -1351,7 +1351,7 @@ static int __init vga16fb_probe(struct device *device) } /* XXX share VGA_FB_PHYS and I/O region with vgacon and others */ - info->screen_base = (void __iomem *)VGA_MAP_MEM(VGA_FB_PHYS); + info->screen_base = (void __iomem *)VGA_MAP_MEM(VGA_FB_PHYS, 0); if (!info->screen_base) { printk(KERN_ERR "vga16fb: unable to map device\n"); diff --git a/include/asm-alpha/vga.h b/include/asm-alpha/vga.h index 8ca4f6b2da1..ed06f59b544 100644 --- a/include/asm-alpha/vga.h +++ b/include/asm-alpha/vga.h @@ -46,6 +46,6 @@ extern void scr_memcpyw(u16 *d, const u16 *s, unsigned int count); #define vga_readb(a) readb((u8 __iomem *)(a)) #define vga_writeb(v,a) writeb(v, (u8 __iomem *)(a)) -#define VGA_MAP_MEM(x) ((unsigned long) ioremap(x, 0)) +#define VGA_MAP_MEM(x,s) ((unsigned long) ioremap(x, s)) #endif diff --git a/include/asm-arm/vga.h b/include/asm-arm/vga.h index 926e5ee128e..1e0b913c3d7 100644 --- a/include/asm-arm/vga.h +++ b/include/asm-arm/vga.h @@ -4,7 +4,7 @@ #include #include -#define VGA_MAP_MEM(x) (PCIMEM_BASE + (x)) +#define VGA_MAP_MEM(x,s) (PCIMEM_BASE + (x)) #define vga_readb(x) (*((volatile unsigned char *)x)) #define vga_writeb(x,y) (*((volatile unsigned char *)y) = (x)) diff --git a/include/asm-i386/vga.h b/include/asm-i386/vga.h index ef0c0e50cc9..0ecf68ac03a 100644 --- a/include/asm-i386/vga.h +++ b/include/asm-i386/vga.h @@ -12,7 +12,7 @@ * access the videoram directly without any black magic. */ -#define VGA_MAP_MEM(x) (unsigned long)phys_to_virt(x) +#define VGA_MAP_MEM(x,s) (unsigned long)phys_to_virt(x) #define vga_readb(x) (*(x)) #define vga_writeb(x,y) (*(y) = (x)) diff --git a/include/asm-ia64/vga.h b/include/asm-ia64/vga.h index 091177cda22..02184ecd820 100644 --- a/include/asm-ia64/vga.h +++ b/include/asm-ia64/vga.h @@ -17,7 +17,7 @@ extern unsigned long vga_console_iobase; extern unsigned long vga_console_membase; -#define VGA_MAP_MEM(x) ((unsigned long) ioremap_nocache(vga_console_membase + (x), 0)) +#define VGA_MAP_MEM(x,s) ((unsigned long) ioremap_nocache(vga_console_membase + (x), s)) #define vga_readb(x) (*(x)) #define vga_writeb(x,y) (*(y) = (x)) diff --git a/include/asm-m32r/vga.h b/include/asm-m32r/vga.h index d0f4b6eed7a..533163447cc 100644 --- a/include/asm-m32r/vga.h +++ b/include/asm-m32r/vga.h @@ -14,7 +14,7 @@ * access the videoram directly without any black magic. */ -#define VGA_MAP_MEM(x) (unsigned long)phys_to_virt(x) +#define VGA_MAP_MEM(x,s) (unsigned long)phys_to_virt(x) #define vga_readb(x) (*(x)) #define vga_writeb(x,y) (*(y) = (x)) diff --git a/include/asm-mips/vga.h b/include/asm-mips/vga.h index 34755c0a639..c1dd0b10bc2 100644 --- a/include/asm-mips/vga.h +++ b/include/asm-mips/vga.h @@ -13,7 +13,7 @@ * access the videoram directly without any black magic. */ -#define VGA_MAP_MEM(x) (0xb0000000L + (unsigned long)(x)) +#define VGA_MAP_MEM(x,s) (0xb0000000L + (unsigned long)(x)) #define vga_readb(x) (*(x)) #define vga_writeb(x,y) (*(y) = (x)) diff --git a/include/asm-powerpc/vga.h b/include/asm-powerpc/vga.h index eadaf2f3d03..a2eac409c1e 100644 --- a/include/asm-powerpc/vga.h +++ b/include/asm-powerpc/vga.h @@ -41,9 +41,9 @@ static inline u16 scr_readw(volatile const u16 *addr) extern unsigned long vgacon_remap_base; #ifdef __powerpc64__ -#define VGA_MAP_MEM(x) ((unsigned long) ioremap((x), 0)) +#define VGA_MAP_MEM(x,s) ((unsigned long) ioremap((x), s)) #else -#define VGA_MAP_MEM(x) (x + vgacon_remap_base) +#define VGA_MAP_MEM(x,s) (x + vgacon_remap_base) #endif #define vga_readb(x) (*(x)) diff --git a/include/asm-sparc64/vga.h b/include/asm-sparc64/vga.h index 9c57eb363b4..c69d5b2ba19 100644 --- a/include/asm-sparc64/vga.h +++ b/include/asm-sparc64/vga.h @@ -28,6 +28,6 @@ static inline u16 scr_readw(const u16 *addr) return *addr; } -#define VGA_MAP_MEM(x) (x) +#define VGA_MAP_MEM(x,s) (x) #endif diff --git a/include/asm-x86_64/vga.h b/include/asm-x86_64/vga.h index ef0c0e50cc9..0ecf68ac03a 100644 --- a/include/asm-x86_64/vga.h +++ b/include/asm-x86_64/vga.h @@ -12,7 +12,7 @@ * access the videoram directly without any black magic. */ -#define VGA_MAP_MEM(x) (unsigned long)phys_to_virt(x) +#define VGA_MAP_MEM(x,s) (unsigned long)phys_to_virt(x) #define vga_readb(x) (*(x)) #define vga_writeb(x,y) (*(y) = (x)) diff --git a/include/asm-xtensa/vga.h b/include/asm-xtensa/vga.h index 23d82f6acb5..1fd8cab3a29 100644 --- a/include/asm-xtensa/vga.h +++ b/include/asm-xtensa/vga.h @@ -11,7 +11,7 @@ #ifndef _XTENSA_VGA_H #define _XTENSA_VGA_H -#define VGA_MAP_MEM(x) (unsigned long)phys_to_virt(x) +#define VGA_MAP_MEM(x,s) (unsigned long)phys_to_virt(x) #define vga_readb(x) (*(x)) #define vga_writeb(x,y) (*(y) = (x)) -- cgit v1.2.3 From 4f3865fb57a04db7cca068fed1c15badc064a302 Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Thu, 22 Jun 2006 14:47:34 -0700 Subject: [PATCH] zlib_inflate: Upgrade library code to a recent version Upgrade the zlib_inflate implementation in the kernel from a patched version 1.1.3/4 to a patched 1.2.3. The code in the kernel is about seven years old and I noticed that the external zlib library's inflate performance was significantly faster (~50%) than the code in the kernel on ARM (and faster again on x86_32). For comparison the newer deflate code is 20% slower on ARM and 50% slower on x86_32 but gives an approx 1% compression ratio improvement. I don't consider this to be an improvement for kernel use so have no plans to change the zlib_deflate code. Various changes have been made to the zlib code in the kernel, the most significant being the extra functions/flush option used by ppp_deflate. This update reimplements the features PPP needs to ensure it continues to work. This code has been tested on ARM under both JFFS2 (with zlib compression enabled) and ppp_deflate and on x86_32. JFFS2 sees an approx. 10% real world file read speed improvement. This patch also removes ZLIB_VERSION as it no longer has a correct value. We don't need version checks anyway as the kernel's module handling will take care of that for us. This removal is also more in keeping with the zlib author's wishes (http://www.zlib.net/zlib_faq.html#faq24) and I've added something to the zlib.h header to note its a modified version. Signed-off-by: Richard Purdie Acked-by: Joern Engel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/boot/Makefile | 4 +- arch/ppc/boot/lib/Makefile | 2 +- arch/xtensa/boot/lib/Makefile | 2 +- include/linux/zconf.h | 12 + include/linux/zlib.h | 209 +++++--- include/linux/zutil.h | 12 - lib/zlib_deflate/deflate.c | 25 +- lib/zlib_deflate/deflate_syms.c | 3 +- lib/zlib_inflate/Makefile | 4 +- lib/zlib_inflate/infblock.c | 365 ------------- lib/zlib_inflate/infblock.h | 48 -- lib/zlib_inflate/infcodes.c | 202 -------- lib/zlib_inflate/infcodes.h | 33 -- lib/zlib_inflate/inffast.c | 462 +++++++++++------ lib/zlib_inflate/inffast.h | 12 +- lib/zlib_inflate/inffixed.h | 94 ++++ lib/zlib_inflate/inflate.c | 1086 +++++++++++++++++++++++++++++++-------- lib/zlib_inflate/inflate.h | 107 ++++ lib/zlib_inflate/inflate_syms.c | 3 +- lib/zlib_inflate/inflate_sync.c | 152 ------ lib/zlib_inflate/inftrees.c | 683 +++++++++++------------- lib/zlib_inflate/inftrees.h | 99 ++-- lib/zlib_inflate/infutil.c | 88 ---- lib/zlib_inflate/infutil.h | 176 +------ 24 files changed, 1877 insertions(+), 2006 deletions(-) delete mode 100644 lib/zlib_inflate/infblock.c delete mode 100644 lib/zlib_inflate/infblock.h delete mode 100644 lib/zlib_inflate/infcodes.c delete mode 100644 lib/zlib_inflate/infcodes.h create mode 100644 lib/zlib_inflate/inffixed.h create mode 100644 lib/zlib_inflate/inflate.h delete mode 100644 lib/zlib_inflate/inflate_sync.c delete mode 100644 lib/zlib_inflate/infutil.c diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index 840ae595a61..d961bfeed05 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile @@ -29,8 +29,8 @@ OBJCOPYFLAGS := contents,alloc,load,readonly,data OBJCOPY_COFF_ARGS := -O aixcoff-rs6000 --set-start 0x500000 OBJCOPY_MIB_ARGS := -O aixcoff-rs6000 -R .stab -R .stabstr -R .comment -zlib := infblock.c infcodes.c inffast.c inflate.c inftrees.c infutil.c -zlibheader := infblock.h infcodes.h inffast.h inftrees.h infutil.h +zlib := inffast.c inflate.c inftrees.c +zlibheader := inffast.h inffixed.h inflate.h inftrees.h infutil.h zliblinuxheader := zlib.h zconf.h zutil.h $(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader)) diff --git a/arch/ppc/boot/lib/Makefile b/arch/ppc/boot/lib/Makefile index 80c84d562fa..2f995f712ec 100644 --- a/arch/ppc/boot/lib/Makefile +++ b/arch/ppc/boot/lib/Makefile @@ -5,7 +5,7 @@ CFLAGS_kbd.o := -Idrivers/char CFLAGS_vreset.o := -Iarch/ppc/boot/include -zlib := infblock.c infcodes.c inffast.c inflate.c inftrees.c infutil.c +zlib := inffast.c inflate.c inftrees.c lib-y += $(zlib:.c=.o) div64.o lib-$(CONFIG_VGA_CONSOLE) += vreset.o kbd.o diff --git a/arch/xtensa/boot/lib/Makefile b/arch/xtensa/boot/lib/Makefile index 9e73bb8aeb7..d3d2aa2d883 100644 --- a/arch/xtensa/boot/lib/Makefile +++ b/arch/xtensa/boot/lib/Makefile @@ -2,7 +2,7 @@ # Makefile for some libs needed by zImage. # -zlib := infblock.c infcodes.c inffast.c inflate.c inftrees.c infutil.c +zlib := inffast.c inflate.c inftrees.c lib-y += $(zlib:.c=.o) zmem.o diff --git a/include/linux/zconf.h b/include/linux/zconf.h index f1cfd66b955..0beb75e38ca 100644 --- a/include/linux/zconf.h +++ b/include/linux/zconf.h @@ -33,6 +33,18 @@ */ #ifndef MAX_WBITS # define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* default windowBits for decompression. MAX_WBITS is for compression only */ +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif + +/* default memLevel */ +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL #endif /* Type declarations */ diff --git a/include/linux/zlib.h b/include/linux/zlib.h index 4fa32f0d4df..9e3192a7dc6 100644 --- a/include/linux/zlib.h +++ b/include/linux/zlib.h @@ -1,7 +1,6 @@ /* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.1.3, July 9th, 1998 - Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler + Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -24,7 +23,7 @@ The data format used by the zlib library is described by RFCs (Request for - Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt + Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). */ @@ -33,7 +32,22 @@ #include -#define ZLIB_VERSION "1.1.3" +/* zlib deflate based on ZLIB_VERSION "1.1.3" */ +/* zlib inflate based on ZLIB_VERSION "1.2.3" */ + +/* + This is a modified version of zlib for use inside the Linux kernel. + The main changes are to perform all memory allocation in advance. + + Inflation Changes: + * Z_PACKET_FLUSH is added and used by ppp_deflate. Before returning + this checks there is no more input data available and the next data + is a STORED block. It also resets the mode to be read for the next + data, all as per PPP requirements. + * Addition of zlib_inflateIncomp which copies incompressible data into + the history window and adjusts the accoutning without calling + zlib_inflate itself to inflate the data. +*/ /* The 'zlib' compression library provides in-memory compression and @@ -48,9 +62,18 @@ application must provide more input and/or consume the output (providing more output space) before each call. + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + The library also supports reading and writing files in gzip (.gz) format with an interface similar to that of stdio. + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + The library does not install any signal handler. The decoder checks the consistency of the compressed data, so the library should never crash even in case of corrupted input. @@ -119,7 +142,8 @@ typedef z_stream *z_streamp; #define Z_SYNC_FLUSH 3 #define Z_FULL_FLUSH 4 #define Z_FINISH 5 -/* Allowed flush values; see deflate() below for details */ +#define Z_BLOCK 6 /* Only for inflate at present */ +/* Allowed flush values; see deflate() and inflate() below for details */ #define Z_OK 0 #define Z_STREAM_END 1 @@ -155,13 +179,6 @@ typedef z_stream *z_streamp; /* basic functions */ -extern const char * zlib_zlibVersion (void); -/* The application can compare zlibVersion and ZLIB_VERSION for consistency. - If the first character differs, the library code actually used is - not compatible with the zlib.h header file used by the application. - This check is automatically made by deflateInit and inflateInit. - */ - extern int zlib_deflate_workspacesize (void); /* Returns the number of bytes that needs to be allocated for a per- @@ -315,9 +332,9 @@ extern int zlib_inflateInit (z_streamp strm); extern int zlib_inflate (z_streamp strm, int flush); /* inflate decompresses as much data as possible, and stops when the input - buffer becomes empty or the output buffer becomes full. It may some - introduce some output latency (reading input without producing any output) - except when forced to flush. + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. The detailed semantics are as follows. inflate performs one or both of the following actions: @@ -341,11 +358,26 @@ extern int zlib_inflate (z_streamp strm, int flush); must be called again after making room in the output buffer because there might be more output pending. - If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much - output as possible to the output buffer. The flushing behavior of inflate is - not specified for values of the flush parameter other than Z_SYNC_FLUSH - and Z_FINISH, but the current implementation actually flushes as much output - as possible anyway. + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, + Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() stop + if and when it gets to the next deflate block boundary. When decoding the + zlib or gzip format, this will cause inflate() to return immediately after + the header and before the first block. When doing a raw inflate, inflate() + will go ahead and process the first block, and will return when it gets to + the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + Also to assist in this, on return inflate() will set strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 + if inflate() is currently decoding the last block in the deflate stream, + plus 128 if inflate() returned immediately after decoding an end-of-block + code or decoding the complete header up to just before the first byte of the + deflate stream. The end-of-block will not be indicated until all of the + uncompressed data from that block has been written to strm->next_out. The + number of unused bits may in general be greater than seven, except when + bit 7 of data_type is set, in which case the number of unused bits will be + less than eight. inflate() should normally be called until it returns Z_STREAM_END or an error. However if all decompression is to be performed in a single step @@ -355,29 +387,44 @@ extern int zlib_inflate (z_streamp strm, int flush); uncompressed data. (The size of the uncompressed data may have been saved by the compressor for this purpose.) The next operation on this stream must be inflateEnd to deallocate the decompression state. The use of Z_FINISH - is never required, but can be used to inform inflate that a faster routine + is never required, but can be used to inform inflate that a faster approach may be used for the single inflate() call. - If a preset dictionary is needed at this point (see inflateSetDictionary - below), inflate sets strm-adler to the adler32 checksum of the - dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise - it sets strm->adler to the adler32 checksum of all output produced - so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or - an error code as described below. At the end of the stream, inflate() - checks that its computed adler32 checksum is equal to that saved by the - compressor and returns Z_STREAM_END only if the checksum is correct. + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the only effect of the flush parameter in this implementation + is on the return value of inflate(), as noted below, or when it returns early + because Z_BLOCK is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the adler32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the adler32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() will decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically. Any information + contained in the gzip header is not retained, so applications that need that + information should instead use raw inflate, see inflateInit2() below, or + inflateBack() and perform their own processing of the gzip header and + trailer. inflate() returns Z_OK if some progress has been made (more input processed or more output produced), Z_STREAM_END if the end of the compressed data has been reached and all uncompressed output has been produced, Z_NEED_DICT if a preset dictionary is needed at this point, Z_DATA_ERROR if the input data was - corrupted (input stream not conforming to the zlib format or incorrect - adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent - (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if no progress is possible or if there was not - enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR - case, the application may then call inflateSync to look for a good - compression block. + corrupted (input stream not conforming to the zlib format or incorrect check + value), Z_STREAM_ERROR if the stream structure was inconsistent (for example + if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is possible or if there was not enough room in the + output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may then + call inflateSync() to look for a good compression block if a partial recovery + of the data is desired. */ @@ -547,16 +594,36 @@ extern int inflateInit2 (z_streamp strm, int windowBits); The windowBits parameter is the base two logarithm of the maximum window size (the size of the history buffer). It should be in the range 8..15 for this version of the library. The default value is 15 if inflateInit is used - instead. If a compressed stream with a larger window size is given as - input, inflate() will return with the error code Z_DATA_ERROR instead of - trying to allocate a larger window. - - inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative - memLevel). msg is set to null if there is no error message. inflateInit2 - does not perform any decompression apart from reading the zlib header if - present: this will be done by inflate(). (So next_in and avail_in may be - modified, but next_out and avail_out are unchanged.) + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an adler32 or a crc32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is + a crc32 instead of an adler32. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a null strm). msg + is set to null if there is no error message. inflateInit2 does not perform + any decompression apart from reading the zlib header if present: this will + be done by inflate(). (So next_in and avail_in may be modified, but next_out + and avail_out are unchanged.) */ extern int zlib_inflateSetDictionary (z_streamp strm, @@ -564,16 +631,19 @@ extern int zlib_inflateSetDictionary (z_streamp strm, uInt dictLength); /* Initializes the decompression dictionary from the given uncompressed byte - sequence. This function must be called immediately after a call of inflate - if this call returned Z_NEED_DICT. The dictionary chosen by the compressor - can be determined from the Adler32 value returned by this call of - inflate. The compressor and decompressor must use exactly the same - dictionary (see deflateSetDictionary). + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called + immediately after inflateInit2() or inflateReset() and before any call of + inflate() to set the dictionary. The application must insure that the + dictionary that was used for compression is provided. inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a parameter is invalid (such as NULL dictionary) or the stream state is inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the - expected one (incorrect Adler32 value). inflateSetDictionary does not + expected one (incorrect adler32 value). inflateSetDictionary does not perform any decompression: this will be done by subsequent calls of inflate(). */ @@ -614,40 +684,19 @@ extern int zlib_inflateIncomp (z_stream *strm); containing the data at next_in (except that the data is not output). */ - /* various hacks, don't look :) */ - -/* deflateInit and inflateInit are macros to allow checking the zlib version - * and the compiler's view of z_stream: - */ -extern int zlib_deflateInit_ (z_streamp strm, int level, - const char *version, int stream_size); -extern int zlib_inflateInit_ (z_streamp strm, - const char *version, int stream_size); -extern int zlib_deflateInit2_ (z_streamp strm, int level, int method, - int windowBits, int memLevel, - int strategy, const char *version, - int stream_size); -extern int zlib_inflateInit2_ (z_streamp strm, int windowBits, - const char *version, int stream_size); #define zlib_deflateInit(strm, level) \ - zlib_deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) + zlib_deflateInit2((strm), (level), Z_DEFLATED, MAX_WBITS, \ + DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY) #define zlib_inflateInit(strm) \ - zlib_inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) -#define zlib_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ - zlib_deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ - (strategy), ZLIB_VERSION, sizeof(z_stream)) -#define zlib_inflateInit2(strm, windowBits) \ - zlib_inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) + zlib_inflateInit2((strm), DEF_WBITS) +extern int zlib_deflateInit2(z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy); +extern int zlib_inflateInit2(z_streamp strm, int windowBits); #if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL) struct internal_state {int dummy;}; /* hack for buggy compilers */ #endif -extern const char * zlib_zError (int err); -#if 0 -extern int zlib_inflateSyncPoint (z_streamp z); -#endif -extern const uLong * zlib_get_crc_table (void); - #endif /* _ZLIB_H */ diff --git a/include/linux/zutil.h b/include/linux/zutil.h index ee0c59cf213..6adfa9a6ffe 100644 --- a/include/linux/zutil.h +++ b/include/linux/zutil.h @@ -23,18 +23,6 @@ typedef unsigned long ulg; /* common constants */ -#ifndef DEF_WBITS -# define DEF_WBITS MAX_WBITS -#endif -/* default windowBits for decompression. MAX_WBITS is for compression only */ - -#if MAX_MEM_LEVEL >= 8 -# define DEF_MEM_LEVEL 8 -#else -# define DEF_MEM_LEVEL MAX_MEM_LEVEL -#endif -/* default memLevel */ - #define STORED_BLOCK 0 #define STATIC_TREES 1 #define DYN_TREES 2 diff --git a/lib/zlib_deflate/deflate.c b/lib/zlib_deflate/deflate.c index 1653dd9bb01..c3e4a2baf83 100644 --- a/lib/zlib_deflate/deflate.c +++ b/lib/zlib_deflate/deflate.c @@ -164,34 +164,17 @@ static const config configuration_table[10] = { memset((char *)s->head, 0, (unsigned)(s->hash_size-1)*sizeof(*s->head)); /* ========================================================================= */ -int zlib_deflateInit_( - z_streamp strm, - int level, - const char *version, - int stream_size -) -{ - return zlib_deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, - DEF_MEM_LEVEL, - Z_DEFAULT_STRATEGY, version, stream_size); - /* To do: ignore strm->next_in if we use it as window */ -} - -/* ========================================================================= */ -int zlib_deflateInit2_( +int zlib_deflateInit2( z_streamp strm, int level, int method, int windowBits, int memLevel, - int strategy, - const char *version, - int stream_size + int strategy ) { deflate_state *s; int noheader = 0; - static char* my_version = ZLIB_VERSION; deflate_workspace *mem; ush *overlay; @@ -199,10 +182,6 @@ int zlib_deflateInit2_( * output size for (length,distance) codes is <= 24 bits. */ - if (version == NULL || version[0] != my_version[0] || - stream_size != sizeof(z_stream)) { - return Z_VERSION_ERROR; - } if (strm == NULL) return Z_STREAM_ERROR; strm->msg = NULL; diff --git a/lib/zlib_deflate/deflate_syms.c b/lib/zlib_deflate/deflate_syms.c index 767b573d1ef..ccfe25f3920 100644 --- a/lib/zlib_deflate/deflate_syms.c +++ b/lib/zlib_deflate/deflate_syms.c @@ -12,8 +12,7 @@ EXPORT_SYMBOL(zlib_deflate_workspacesize); EXPORT_SYMBOL(zlib_deflate); -EXPORT_SYMBOL(zlib_deflateInit_); -EXPORT_SYMBOL(zlib_deflateInit2_); +EXPORT_SYMBOL(zlib_deflateInit2); EXPORT_SYMBOL(zlib_deflateEnd); EXPORT_SYMBOL(zlib_deflateReset); MODULE_LICENSE("GPL"); diff --git a/lib/zlib_inflate/Makefile b/lib/zlib_inflate/Makefile index 221c139e0df..bf065482fa6 100644 --- a/lib/zlib_inflate/Makefile +++ b/lib/zlib_inflate/Makefile @@ -15,5 +15,5 @@ obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate.o -zlib_inflate-objs := infblock.o infcodes.o inffast.o inflate.o \ - inflate_sync.o inftrees.o infutil.o inflate_syms.o +zlib_inflate-objs := inffast.o inflate.o \ + inftrees.o inflate_syms.o diff --git a/lib/zlib_inflate/infblock.c b/lib/zlib_inflate/infblock.c deleted file mode 100644 index c16cdeff51a..00000000000 --- a/lib/zlib_inflate/infblock.c +++ /dev/null @@ -1,365 +0,0 @@ -/* infblock.c -- interpret and process block types to last block - * Copyright (C) 1995-1998 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include -#include "infblock.h" -#include "inftrees.h" -#include "infcodes.h" -#include "infutil.h" - -struct inflate_codes_state; - -/* simplify the use of the inflate_huft type with some defines */ -#define exop word.what.Exop -#define bits word.what.Bits - -/* Table for deflate from PKZIP's appnote.txt. */ -static const uInt border[] = { /* Order of the bit length code lengths */ - 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - -/* - Notes beyond the 1.93a appnote.txt: - - 1. Distance pointers never point before the beginning of the output - stream. - 2. Distance pointers can point back across blocks, up to 32k away. - 3. There is an implied maximum of 7 bits for the bit length table and - 15 bits for the actual data. - 4. If only one code exists, then it is encoded using one bit. (Zero - would be more efficient, but perhaps a little confusing.) If two - codes exist, they are coded using one bit each (0 and 1). - 5. There is no way of sending zero distance codes--a dummy must be - sent if there are none. (History: a pre 2.0 version of PKZIP would - store blocks with no distance codes, but this was discovered to be - too harsh a criterion.) Valid only for 1.93a. 2.04c does allow - zero distance codes, which is sent as one code of zero bits in - length. - 6. There are up to 286 literal/length codes. Code 256 represents the - end-of-block. Note however that the static length tree defines - 288 codes just to fill out the Huffman codes. Codes 286 and 287 - cannot be used though, since there is no length base or extra bits - defined for them. Similarily, there are up to 30 distance codes. - However, static trees define 32 codes (all 5 bits) to fill out the - Huffman codes, but the last two had better not show up in the data. - 7. Unzip can check dynamic Huffman blocks for complete code sets. - The exception is that a single code would not be complete (see #4). - 8. The five bits following the block type is really the number of - literal codes sent minus 257. - 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits - (1+6+6). Therefore, to output three times the length, you output - three codes (1+1+1), whereas to output four times the same length, - you only need two codes (1+3). Hmm. - 10. In the tree reconstruction algorithm, Code = Code + Increment - only if BitLength(i) is not zero. (Pretty obvious.) - 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19) - 12. Note: length code 284 can represent 227-258, but length code 285 - really is 258. The last length deserves its own, short code - since it gets used a lot in very redundant files. The length - 258 is special since 258 - 3 (the min match length) is 255. - 13. The literal/length and distance code bit lengths are read as a - single stream of lengths. It is possible (and advantageous) for - a repeat code (16, 17, or 18) to go across the boundary between - the two sets of lengths. - */ - - -void zlib_inflate_blocks_reset( - inflate_blocks_statef *s, - z_streamp z, - uLong *c -) -{ - if (c != NULL) - *c = s->check; - if (s->mode == CODES) - zlib_inflate_codes_free(s->sub.decode.codes, z); - s->mode = TYPE; - s->bitk = 0; - s->bitb = 0; - s->read = s->write = s->window; - if (s->checkfn != NULL) - z->adler = s->check = (*s->checkfn)(0L, NULL, 0); -} - -inflate_blocks_statef *zlib_inflate_blocks_new( - z_streamp z, - check_func c, - uInt w -) -{ - inflate_blocks_statef *s; - - s = &WS(z)->working_blocks_state; - s->hufts = WS(z)->working_hufts; - s->window = WS(z)->working_window; - s->end = s->window + w; - s->checkfn = c; - s->mode = TYPE; - zlib_inflate_blocks_reset(s, z, NULL); - return s; -} - - -int zlib_inflate_blocks( - inflate_blocks_statef *s, - z_streamp z, - int r -) -{ - uInt t; /* temporary storage */ - uLong b; /* bit buffer */ - uInt k; /* bits in bit buffer */ - Byte *p; /* input data pointer */ - uInt n; /* bytes available there */ - Byte *q; /* output window write pointer */ - uInt m; /* bytes to end of window or read pointer */ - - /* copy input/output information to locals (UPDATE macro restores) */ - LOAD - - /* process input based on current state */ - while (1) switch (s->mode) - { - case TYPE: - NEEDBITS(3) - t = (uInt)b & 7; - s->last = t & 1; - switch (t >> 1) - { - case 0: /* stored */ - DUMPBITS(3) - t = k & 7; /* go to byte boundary */ - DUMPBITS(t) - s->mode = LENS; /* get length of stored block */ - break; - case 1: /* fixed */ - { - uInt bl, bd; - inflate_huft *tl, *td; - - zlib_inflate_trees_fixed(&bl, &bd, &tl, &td, s->hufts, z); - s->sub.decode.codes = zlib_inflate_codes_new(bl, bd, tl, td, z); - if (s->sub.decode.codes == NULL) - { - r = Z_MEM_ERROR; - LEAVE - } - } - DUMPBITS(3) - s->mode = CODES; - break; - case 2: /* dynamic */ - DUMPBITS(3) - s->mode = TABLE; - break; - case 3: /* illegal */ - DUMPBITS(3) - s->mode = B_BAD; - z->msg = (char*)"invalid block type"; - r = Z_DATA_ERROR; - LEAVE - } - break; - case LENS: - NEEDBITS(32) - if ((((~b) >> 16) & 0xffff) != (b & 0xffff)) - { - s->mode = B_BAD; - z->msg = (char*)"invalid stored block lengths"; - r = Z_DATA_ERROR; - LEAVE - } - s->sub.left = (uInt)b & 0xffff; - b = k = 0; /* dump bits */ - s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE); - break; - case STORED: - if (n == 0) - LEAVE - NEEDOUT - t = s->sub.left; - if (t > n) t = n; - if (t > m) t = m; - memcpy(q, p, t); - p += t; n -= t; - q += t; m -= t; - if ((s->sub.left -= t) != 0) - break; - s->mode = s->last ? DRY : TYPE; - break; - case TABLE: - NEEDBITS(14) - s->sub.trees.table = t = (uInt)b & 0x3fff; -#ifndef PKZIP_BUG_WORKAROUND - if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) - { - s->mode = B_BAD; - z->msg = (char*)"too many length or distance symbols"; - r = Z_DATA_ERROR; - LEAVE - } -#endif - { - s->sub.trees.blens = WS(z)->working_blens; - } - DUMPBITS(14) - s->sub.trees.index = 0; - s->mode = BTREE; - case BTREE: - while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10)) - { - NEEDBITS(3) - s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7; - DUMPBITS(3) - } - while (s->sub.trees.index < 19) - s->sub.trees.blens[border[s->sub.trees.index++]] = 0; - s->sub.trees.bb = 7; - t = zlib_inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb, - &s->sub.trees.tb, s->hufts, z); - if (t != Z_OK) - { - r = t; - if (r == Z_DATA_ERROR) - s->mode = B_BAD; - LEAVE - } - s->sub.trees.index = 0; - s->mode = DTREE; - case DTREE: - while (t = s->sub.trees.table, - s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f)) - { - inflate_huft *h; - uInt i, j, c; - - t = s->sub.trees.bb; - NEEDBITS(t) - h = s->sub.trees.tb + ((uInt)b & zlib_inflate_mask[t]); - t = h->bits; - c = h->base; - if (c < 16) - { - DUMPBITS(t) - s->sub.trees.blens[s->sub.trees.index++] = c; - } - else /* c == 16..18 */ - { - i = c == 18 ? 7 : c - 14; - j = c == 18 ? 11 : 3; - NEEDBITS(t + i) - DUMPBITS(t) - j += (uInt)b & zlib_inflate_mask[i]; - DUMPBITS(i) - i = s->sub.trees.index; - t = s->sub.trees.table; - if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || - (c == 16 && i < 1)) - { - s->mode = B_BAD; - z->msg = (char*)"invalid bit length repeat"; - r = Z_DATA_ERROR; - LEAVE - } - c = c == 16 ? s->sub.trees.blens[i - 1] : 0; - do { - s->sub.trees.blens[i++] = c; - } while (--j); - s->sub.trees.index = i; - } - } - s->sub.trees.tb = NULL; - { - uInt bl, bd; - inflate_huft *tl, *td; - inflate_codes_statef *c; - - bl = 9; /* must be <= 9 for lookahead assumptions */ - bd = 6; /* must be <= 9 for lookahead assumptions */ - t = s->sub.trees.table; - t = zlib_inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), - s->sub.trees.blens, &bl, &bd, &tl, &td, - s->hufts, z); - if (t != Z_OK) - { - if (t == (uInt)Z_DATA_ERROR) - s->mode = B_BAD; - r = t; - LEAVE - } - if ((c = zlib_inflate_codes_new(bl, bd, tl, td, z)) == NULL) - { - r = Z_MEM_ERROR; - LEAVE - } - s->sub.decode.codes = c; - } - s->mode = CODES; - case CODES: - UPDATE - if ((r = zlib_inflate_codes(s, z, r)) != Z_STREAM_END) - return zlib_inflate_flush(s, z, r); - r = Z_OK; - zlib_inflate_codes_free(s->sub.decode.codes, z); - LOAD - if (!s->last) - { - s->mode = TYPE; - break; - } - s->mode = DRY; - case DRY: - FLUSH - if (s->read != s->write) - LEAVE - s->mode = B_DONE; - case B_DONE: - r = Z_STREAM_END; - LEAVE - case B_BAD: - r = Z_DATA_ERROR; - LEAVE - default: - r = Z_STREAM_ERROR; - LEAVE - } -} - - -int zlib_inflate_blocks_free( - inflate_blocks_statef *s, - z_streamp z -) -{ - zlib_inflate_blocks_reset(s, z, NULL); - return Z_OK; -} - - -#if 0 -void zlib_inflate_set_dictionary( - inflate_blocks_statef *s, - const Byte *d, - uInt n -) -{ - memcpy(s->window, d, n); - s->read = s->write = s->window + n; -} -#endif /* 0 */ - - -/* Returns true if inflate is currently at the end of a block generated - * by Z_SYNC_FLUSH or Z_FULL_FLUSH. - * IN assertion: s != NULL - */ -#if 0 -int zlib_inflate_blocks_sync_point( - inflate_blocks_statef *s -) -{ - return s->mode == LENS; -} -#endif /* 0 */ diff --git a/lib/zlib_inflate/infblock.h b/lib/zlib_inflate/infblock.h deleted file mode 100644 index ceee60b5107..00000000000 --- a/lib/zlib_inflate/infblock.h +++ /dev/null @@ -1,48 +0,0 @@ -/* infblock.h -- header to use infblock.c - * Copyright (C) 1995-1998 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -#ifndef _INFBLOCK_H -#define _INFBLOCK_H - -struct inflate_blocks_state; -typedef struct inflate_blocks_state inflate_blocks_statef; - -extern inflate_blocks_statef * zlib_inflate_blocks_new ( - z_streamp z, - check_func c, /* check function */ - uInt w); /* window size */ - -extern int zlib_inflate_blocks ( - inflate_blocks_statef *, - z_streamp , - int); /* initial return code */ - -extern void zlib_inflate_blocks_reset ( - inflate_blocks_statef *, - z_streamp , - uLong *); /* check value on output */ - -extern int zlib_inflate_blocks_free ( - inflate_blocks_statef *, - z_streamp); - -#if 0 -extern void zlib_inflate_set_dictionary ( - inflate_blocks_statef *s, - const Byte *d, /* dictionary */ - uInt n); /* dictionary length */ -#endif /* 0 */ - -#if 0 -extern int zlib_inflate_blocks_sync_point ( - inflate_blocks_statef *s); -#endif /* 0 */ - -#endif /* _INFBLOCK_H */ diff --git a/lib/zlib_inflate/infcodes.c b/lib/zlib_inflate/infcodes.c deleted file mode 100644 index 07cd7591cbb..00000000000 --- a/lib/zlib_inflate/infcodes.c +++ /dev/null @@ -1,202 +0,0 @@ -/* infcodes.c -- process literals and length/distance pairs - * Copyright (C) 1995-1998 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include -#include "inftrees.h" -#include "infblock.h" -#include "infcodes.h" -#include "infutil.h" -#include "inffast.h" - -/* simplify the use of the inflate_huft type with some defines */ -#define exop word.what.Exop -#define bits word.what.Bits - -inflate_codes_statef *zlib_inflate_codes_new( - uInt bl, - uInt bd, - inflate_huft *tl, - inflate_huft *td, /* need separate declaration for Borland C++ */ - z_streamp z -) -{ - inflate_codes_statef *c; - - c = &WS(z)->working_state; - { - c->mode = START; - c->lbits = (Byte)bl; - c->dbits = (Byte)bd; - c->ltree = tl; - c->dtree = td; - } - return c; -} - - -int zlib_inflate_codes( - inflate_blocks_statef *s, - z_streamp z, - int r -) -{ - uInt j; /* temporary storage */ - inflate_huft *t; /* temporary pointer */ - uInt e; /* extra bits or operation */ - uLong b; /* bit buffer */ - uInt k; /* bits in bit buffer */ - Byte *p; /* input data pointer */ - uInt n; /* bytes available there */ - Byte *q; /* output window write pointer */ - uInt m; /* bytes to end of window or read pointer */ - Byte *f; /* pointer to copy strings from */ - inflate_codes_statef *c = s->sub.decode.codes; /* codes state */ - - /* copy input/output information to locals (UPDATE macro restores) */ - LOAD - - /* process input and output based on current state */ - while (1) switch (c->mode) - { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ - case START: /* x: set up for LEN */ -#ifndef SLOW - if (m >= 258 && n >= 10) - { - UPDATE - r = zlib_inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z); - LOAD - if (r != Z_OK) - { - c->mode = r == Z_STREAM_END ? WASH : BADCODE; - break; - } - } -#endif /* !SLOW */ - c->sub.code.need = c->lbits; - c->sub.code.tree = c->ltree; - c->mode = LEN; - case LEN: /* i: get length/literal/eob next */ - j = c->sub.code.need; - NEEDBITS(j) - t = c->sub.code.tree + ((uInt)b & zlib_inflate_mask[j]); - DUMPBITS(t->bits) - e = (uInt)(t->exop); - if (e == 0) /* literal */ - { - c->sub.lit = t->base; - c->mode = LIT; - break; - } - if (e & 16) /* length */ - { - c->sub.copy.get = e & 15; - c->len = t->base; - c->mode = LENEXT; - break; - } - if ((e & 64) == 0) /* next table */ - { - c->sub.code.need = e; - c->sub.code.tree = t + t->base; - break; - } - if (e & 32) /* end of block */ - { - c->mode = WASH; - break; - } - c->mode = BADCODE; /* invalid code */ - z->msg = (char*)"invalid literal/length code"; - r = Z_DATA_ERROR; - LEAVE - case LENEXT: /* i: getting length extra (have base) */ - j = c->sub.copy.get; - NEEDBITS(j) - c->len += (uInt)b & zlib_inflate_mask[j]; - DUMPBITS(j) - c->sub.code.need = c->dbits; - c->sub.code.tree = c->dtree; - c->mode = DIST; - case DIST: /* i: get distance next */ - j = c->sub.code.need; - NEEDBITS(j) - t = c->sub.code.tree + ((uInt)b & zlib_inflate_mask[j]); - DUMPBITS(t->bits) - e = (uInt)(t->exop); - if (e & 16) /* distance */ - { - c->sub.copy.get = e & 15; - c->sub.copy.dist = t->base; - c->mode = DISTEXT; - break; - } - if ((e & 64) == 0) /* next table */ - { - c->sub.code.need = e; - c->sub.code.tree = t + t->base; - break; - } - c->mode = BADCODE; /* invalid code */ - z->msg = (char*)"invalid distance code"; - r = Z_DATA_ERROR; - LEAVE - case DISTEXT: /* i: getting distance extra */ - j = c->sub.copy.get; - NEEDBITS(j) - c->sub.copy.dist += (uInt)b & zlib_inflate_mask[j]; - DUMPBITS(j) - c->mode = COPY; - case COPY: /* o: copying bytes in window, waiting for space */ - f = q - c->sub.copy.dist; - while (f < s->window) /* modulo window size-"while" instead */ - f += s->end - s->window; /* of "if" handles invalid distances */ - while (c->len) - { - NEEDOUT - OUTBYTE(*f++) - if (f == s->end) - f = s->window; - c->len--; - } - c->mode = START; - break; - case LIT: /* o: got literal, waiting for output space */ - NEEDOUT - OUTBYTE(c->sub.lit) - c->mode = START; - break; - case WASH: /* o: got eob, possibly more output */ - if (k > 7) /* return unused byte, if any */ - { - k -= 8; - n++; - p--; /* can always return one */ - } - FLUSH - if (s->read != s->write) - LEAVE - c->mode = END; - case END: - r = Z_STREAM_END; - LEAVE - case BADCODE: /* x: got error */ - r = Z_DATA_ERROR; - LEAVE - default: - r = Z_STREAM_ERROR; - LEAVE - } -#ifdef NEED_DUMMY_RETURN - return Z_STREAM_ERROR; /* Some dumb compilers complain without this */ -#endif -} - - -void zlib_inflate_codes_free( - inflate_codes_statef *c, - z_streamp z -) -{ -} diff --git a/lib/zlib_inflate/infcodes.h b/lib/zlib_inflate/infcodes.h deleted file mode 100644 index 5cff417523b..00000000000 --- a/lib/zlib_inflate/infcodes.h +++ /dev/null @@ -1,33 +0,0 @@ -/* infcodes.h -- header to use infcodes.c - * Copyright (C) 1995-1998 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -#ifndef _INFCODES_H -#define _INFCODES_H - -#include "infblock.h" - -struct inflate_codes_state; -typedef struct inflate_codes_state inflate_codes_statef; - -extern inflate_codes_statef *zlib_inflate_codes_new ( - uInt, uInt, - inflate_huft *, inflate_huft *, - z_streamp ); - -extern int zlib_inflate_codes ( - inflate_blocks_statef *, - z_streamp , - int); - -extern void zlib_inflate_codes_free ( - inflate_codes_statef *, - z_streamp ); - -#endif /* _INFCODES_H */ diff --git a/lib/zlib_inflate/inffast.c b/lib/zlib_inflate/inffast.c index 0bd7623fc85..02a16eacb72 100644 --- a/lib/zlib_inflate/inffast.c +++ b/lib/zlib_inflate/inffast.c @@ -1,176 +1,312 @@ -/* inffast.c -- process literals and length/distance pairs fast - * Copyright (C) 1995-1998 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h +/* inffast.c -- fast decoding + * Copyright (C) 1995-2004 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h */ #include #include "inftrees.h" -#include "infblock.h" -#include "infcodes.h" -#include "infutil.h" +#include "inflate.h" #include "inffast.h" -struct inflate_codes_state; - -/* simplify the use of the inflate_huft type with some defines */ -#define exop word.what.Exop -#define bits word.what.Bits - -/* macros for bit input with no checking and for returning unused bytes */ -#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<avail_in-n;c=(k>>3)>3:c;n+=c;p-=c;k-=c<<3;} - -/* Called with number of bytes left to write in window at least 258 - (the maximum string length) and number of input bytes available - at least ten. The ten bytes are six bytes for the longest length/ - distance pair plus four bytes for overloading the bit buffer. */ - -int zlib_inflate_fast( - uInt bl, - uInt bd, - inflate_huft *tl, - inflate_huft *td, /* need separate declaration for Borland C++ */ - inflate_blocks_statef *s, - z_streamp z -) +#ifndef ASMINF + +/* Allow machine dependent optimization for post-increment or pre-increment. + Based on testing to date, + Pre-increment preferred for: + - PowerPC G3 (Adler) + - MIPS R5000 (Randers-Pehrson) + Post-increment preferred for: + - none + No measurable difference: + - Pentium III (Anderson) + - M68060 (Nikl) + */ +#ifdef POSTINC +# define OFF 0 +# define PUP(a) *(a)++ +#else +# define OFF 1 +# define PUP(a) *++(a) +#endif + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ +void inflate_fast(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ { - inflate_huft *t; /* temporary pointer */ - uInt e; /* extra bits or operation */ - uLong b; /* bit buffer */ - uInt k; /* bits in bit buffer */ - Byte *p; /* input data pointer */ - uInt n; /* bytes available there */ - Byte *q; /* output window write pointer */ - uInt m; /* bytes to end of window or read pointer */ - uInt ml; /* mask for literal/length tree */ - uInt md; /* mask for distance tree */ - uInt c; /* bytes to copy */ - uInt d; /* distance back to copy from */ - Byte *r; /* copy source pointer */ - - /* load input, output, bit values */ - LOAD - - /* initialize masks */ - ml = zlib_inflate_mask[bl]; - md = zlib_inflate_mask[bd]; - - /* do until not enough input or output space for fast loop */ - do { /* assume called with m >= 258 && n >= 10 */ - /* get literal/length code */ - GRABBITS(20) /* max bits for literal/length code */ - if ((e = (t = tl + ((uInt)b & ml))->exop) == 0) - { - DUMPBITS(t->bits) - *q++ = (Byte)t->base; - m--; - continue; - } + struct inflate_state *state; + unsigned char *in; /* local strm->next_in */ + unsigned char *last; /* while in < last, enough input available */ + unsigned char *out; /* local strm->next_out */ + unsigned char *beg; /* inflate()'s initial strm->next_out */ + unsigned char *end; /* while out < end, enough space available */ +#ifdef INFLATE_STRICT + unsigned dmax; /* maximum distance from zlib header */ +#endif + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char *window; /* allocated sliding window, if wsize != 0 */ + unsigned long hold; /* local strm->hold */ + unsigned bits; /* local strm->bits */ + code const *lcode; /* local strm->lencode */ + code const *dcode; /* local strm->distcode */ + unsigned lmask; /* mask for first level of length codes */ + unsigned dmask; /* mask for first level of distance codes */ + code this; /* retrieved table entry */ + unsigned op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + unsigned len; /* match length, unused bytes */ + unsigned dist; /* match distance */ + unsigned char *from; /* where to copy match from */ + + /* copy state to local variables */ + state = (struct inflate_state *)strm->state; + in = strm->next_in - OFF; + last = in + (strm->avail_in - 5); + out = strm->next_out - OFF; + beg = out - (start - strm->avail_out); + end = out + (strm->avail_out - 257); +#ifdef INFLATE_STRICT + dmax = state->dmax; +#endif + wsize = state->wsize; + whave = state->whave; + write = state->write; + window = state->window; + hold = state->hold; + bits = state->bits; + lcode = state->lencode; + dcode = state->distcode; + lmask = (1U << state->lenbits) - 1; + dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ do { - DUMPBITS(t->bits) - if (e & 16) - { - /* get extra bits for length */ - e &= 15; - c = t->base + ((uInt)b & zlib_inflate_mask[e]); - DUMPBITS(e) - - /* decode distance base of block to copy */ - GRABBITS(15); /* max bits for distance code */ - e = (t = td + ((uInt)b & md))->exop; - do { - DUMPBITS(t->bits) - if (e & 16) - { - /* get extra bits to add to distance base */ - e &= 15; - GRABBITS(e) /* get extra bits (up to 13) */ - d = t->base + ((uInt)b & zlib_inflate_mask[e]); - DUMPBITS(e) - - /* do the copy */ - m -= c; - r = q - d; - if (r < s->window) /* wrap if needed */ - { - do { - r += s->end - s->window; /* force pointer in window */ - } while (r < s->window); /* covers invalid distances */ - e = s->end - r; - if (c > e) - { - c -= e; /* wrapped copy */ - do { - *q++ = *r++; - } while (--e); - r = s->window; - do { - *q++ = *r++; - } while (--c); - } - else /* normal copy */ - { - *q++ = *r++; c--; - *q++ = *r++; c--; - do { - *q++ = *r++; - } while (--c); - } + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + this = lcode[hold & lmask]; + dolen: + op = (unsigned)(this.bits); + hold >>= op; + bits -= op; + op = (unsigned)(this.op); + if (op == 0) { /* literal */ + PUP(out) = (unsigned char)(this.val); + } + else if (op & 16) { /* length base */ + len = (unsigned)(this.val); + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + len += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + } + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + this = dcode[hold & dmask]; + dodist: + op = (unsigned)(this.bits); + hold >>= op; + bits -= op; + op = (unsigned)(this.op); + if (op & 16) { /* distance base */ + dist = (unsigned)(this.val); + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + } + dist += (unsigned)hold & ((1U << op) - 1); +#ifdef INFLATE_STRICT + if (dist > dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + hold >>= op; + bits -= op; + op = (unsigned)(out - beg); /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + from = window - OFF; + if (write == 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + else if (write < op) { /* wrap around window */ + from += wsize + write - op; + op -= write; + if (op < len) { /* some from end of window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = window - OFF; + if (write < len) { /* some from start of window */ + op = write; + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + } + else { /* contiguous in window */ + from += write - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + while (len > 2) { + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + else { + from = out - dist; /* copy direct from output */ + do { /* minimum length is three */ + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } while (len > 2); + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + } + else if ((op & 64) == 0) { /* 2nd level distance code */ + this = dcode[this.val + (hold & ((1U << op) - 1))]; + goto dodist; } - else /* normal copy */ - { - *q++ = *r++; c--; - *q++ = *r++; c--; - do { - *q++ = *r++; - } while (--c); + else { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; } + } + else if ((op & 64) == 0) { /* 2nd level length code */ + this = lcode[this.val + (hold & ((1U << op) - 1))]; + goto dolen; + } + else if (op & 32) { /* end-of-block */ + state->mode = TYPE; break; - } - else if ((e & 64) == 0) - { - t += t->base; - e = (t += ((uInt)b & zlib_inflate_mask[e]))->exop; - } - else - { - z->msg = (char*)"invalid distance code"; - UNGRAB - UPDATE - return Z_DATA_ERROR; - } - } while (1); - break; - } - if ((e & 64) == 0) - { - t += t->base; - if ((e = (t += ((uInt)b & zlib_inflate_mask[e]))->exop) == 0) - { - DUMPBITS(t->bits) - *q++ = (Byte)t->base; - m--; - break; } - } - else if (e & 32) - { - UNGRAB - UPDATE - return Z_STREAM_END; - } - else - { - z->msg = (char*)"invalid literal/length code"; - UNGRAB - UPDATE - return Z_DATA_ERROR; - } - } while (1); - } while (m >= 258 && n >= 10); - - /* not enough input or output--restore pointers and return */ - UNGRAB - UPDATE - return Z_OK; + else { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + } while (in < last && out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + in -= len; + bits -= len << 3; + hold &= (1U << bits) - 1; + + /* update state and return */ + strm->next_in = in + OFF; + strm->next_out = out + OFF; + strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); + strm->avail_out = (unsigned)(out < end ? + 257 + (end - out) : 257 - (out - end)); + state->hold = hold; + state->bits = bits; + return; } + +/* + inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): + - Using bit fields for code structure + - Different op definition to avoid & for extra bits (do & for table bits) + - Three separate decoding do-loops for direct, window, and write == 0 + - Special case for distance > 1 copies to do overlapped load and store copy + - Explicit branch predictions (based on measured branch probabilities) + - Deferring match copy and interspersed it with decoding subsequent codes + - Swapping literal/length else + - Swapping window/direct else + - Larger unrolled copy loops (three is about right) + - Moving len -= 3 statement into middle of loop + */ + +#endif /* !ASMINF */ diff --git a/lib/zlib_inflate/inffast.h b/lib/zlib_inflate/inffast.h index fc720f0fa7f..40315d9fddc 100644 --- a/lib/zlib_inflate/inffast.h +++ b/lib/zlib_inflate/inffast.h @@ -1,6 +1,6 @@ /* inffast.h -- header to use inffast.c - * Copyright (C) 1995-1998 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is @@ -8,10 +8,4 @@ subject to change. Applications should only use zlib.h. */ -extern int zlib_inflate_fast ( - uInt, - uInt, - inflate_huft *, - inflate_huft *, - inflate_blocks_statef *, - z_streamp ); +void inflate_fast (z_streamp strm, unsigned start); diff --git a/lib/zlib_inflate/inffixed.h b/lib/zlib_inflate/inffixed.h new file mode 100644 index 00000000000..75ed4b5978d --- /dev/null +++ b/lib/zlib_inflate/inffixed.h @@ -0,0 +1,94 @@ + /* inffixed.h -- table for decoding fixed codes + * Generated automatically by makefixed(). + */ + + /* WARNING: this file should *not* be used by applications. It + is part of the implementation of the compression library and + is subject to change. Applications should only use zlib.h. + */ + + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} + }; + + static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} + }; diff --git a/lib/zlib_inflate/inflate.c b/lib/zlib_inflate/inflate.c index 31b9e9054bf..7f922dccf1a 100644 --- a/lib/zlib_inflate/inflate.c +++ b/lib/zlib_inflate/inflate.c @@ -1,89 +1,148 @@ -/* inflate.c -- zlib interface to inflate modules - * Copyright (C) 1995-1998 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h +/* inflate.c -- zlib decompression + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Based on zlib 1.2.3 but modified for the Linux Kernel by + * Richard Purdie + * + * Changes mainly for static instead of dynamic memory allocation + * */ #include -#include "infblock.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" #include "infutil.h" int zlib_inflate_workspacesize(void) { - return sizeof(struct inflate_workspace); + return sizeof(struct inflate_workspace); } +int zlib_inflateReset(z_streamp strm) +{ + struct inflate_state *state; + + if (strm == NULL || strm->state == NULL) return Z_STREAM_ERROR; + state = (struct inflate_state *)strm->state; + strm->total_in = strm->total_out = state->total = 0; + strm->msg = NULL; + strm->adler = 1; /* to support ill-conceived Java test suite */ + state->mode = HEAD; + state->last = 0; + state->havedict = 0; + state->dmax = 32768U; + state->hold = 0; + state->bits = 0; + state->lencode = state->distcode = state->next = state->codes; -int zlib_inflateReset( - z_streamp z -) + /* Initialise Window */ + state->wsize = 1U << state->wbits; + state->write = 0; + state->whave = 0; + + return Z_OK; +} + +#if 0 +int zlib_inflatePrime(z_streamp strm, int bits, int value) { - if (z == NULL || z->state == NULL || z->workspace == NULL) - return Z_STREAM_ERROR; - z->total_in = z->total_out = 0; - z->msg = NULL; - z->state->mode = z->state->nowrap ? BLOCKS : METHOD; - zlib_inflate_blocks_reset(z->state->blocks, z, NULL); - return Z_OK; + struct inflate_state *state; + + if (strm == NULL || strm->state == NULL) return Z_STREAM_ERROR; + state = (struct inflate_state *)strm->state; + if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR; + value &= (1L << bits) - 1; + state->hold += value << state->bits; + state->bits += bits; + return Z_OK; } +#endif + +int zlib_inflateInit2(z_streamp strm, int windowBits) +{ + struct inflate_state *state; + + if (strm == NULL) return Z_STREAM_ERROR; + strm->msg = NULL; /* in case we return an error */ + + state = &WS(strm)->inflate_state; + strm->state = (struct internal_state *)state; + + if (windowBits < 0) { + state->wrap = 0; + windowBits = -windowBits; + } + else { + state->wrap = (windowBits >> 4) + 1; + } + if (windowBits < 8 || windowBits > 15) { + return Z_STREAM_ERROR; + } + state->wbits = (unsigned)windowBits; + state->window = &WS(strm)->working_window[0]; + return zlib_inflateReset(strm); +} -int zlib_inflateEnd( - z_streamp z -) +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. This returns fixed tables from inffixed.h. + */ +static void zlib_fixedtables(struct inflate_state *state) { - if (z == NULL || z->state == NULL || z->workspace == NULL) - return Z_STREAM_ERROR; - if (z->state->blocks != NULL) - zlib_inflate_blocks_free(z->state->blocks, z); - z->state = NULL; - return Z_OK; +# include "inffixed.h" + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; } -int zlib_inflateInit2_( - z_streamp z, - int w, - const char *version, - int stream_size -) +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. This is only called when a window is already in use, or when + output has been written during this inflate call, but the end of the deflate + stream has not been reached yet. It is also called to window dictionary data + when a dictionary is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +static void zlib_updatewindow(z_streamp strm, unsigned out) { - if (version == NULL || version[0] != ZLIB_VERSION[0] || - stream_size != sizeof(z_stream) || z->workspace == NULL) - return Z_VERSION_ERROR; - - /* initialize state */ - z->msg = NULL; - z->state = &WS(z)->internal_state; - z->state->blocks = NULL; - - /* handle undocumented nowrap option (no zlib header or check) */ - z->state->nowrap = 0; - if (w < 0) - { - w = - w; - z->state->nowrap = 1; - } - - /* set window size */ - if (w < 8 || w > 15) - { - zlib_inflateEnd(z); - return Z_STREAM_ERROR; - } - z->state->wbits = (uInt)w; - - /* create inflate_blocks state */ - if ((z->state->blocks = - zlib_inflate_blocks_new(z, z->state->nowrap ? NULL : zlib_adler32, (uInt)1 << w)) - == NULL) - { - zlib_inflateEnd(z); - return Z_MEM_ERROR; - } - - /* reset state */ - zlib_inflateReset(z); - return Z_OK; + struct inflate_state *state; + unsigned copy, dist; + + state = (struct inflate_state *)strm->state; + + /* copy state->wsize or less output bytes into the circular window */ + copy = out - strm->avail_out; + if (copy >= state->wsize) { + memcpy(state->window, strm->next_out - state->wsize, state->wsize); + state->write = 0; + state->whave = state->wsize; + } + else { + dist = state->wsize - state->write; + if (dist > copy) dist = copy; + memcpy(state->window + state->write, strm->next_out - copy, dist); + copy -= dist; + if (copy) { + memcpy(state->window, strm->next_out - copy, copy); + state->write = copy; + state->whave = state->wsize; + } + else { + state->write += dist; + if (state->write == state->wsize) state->write = 0; + if (state->whave < state->wsize) state->whave += dist; + } + } } @@ -91,157 +150,764 @@ int zlib_inflateInit2_( * At the end of a Deflate-compressed PPP packet, we expect to have seen * a `stored' block type value but not the (zero) length bytes. */ -static int zlib_inflate_packet_flush(inflate_blocks_statef *s) +/* + Returns true if inflate is currently at the end of a block generated by + Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + implementation to provide an additional safety check. PPP uses + Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored + block. When decompressing, PPP checks that at the end of input packet, + inflate is waiting for these length bytes. + */ +static int zlib_inflateSyncPacket(z_streamp strm) { - if (s->mode != LENS) - return Z_DATA_ERROR; - s->mode = TYPE; + struct inflate_state *state; + + if (strm == NULL || strm->state == NULL) return Z_STREAM_ERROR; + state = (struct inflate_state *)strm->state; + + if (state->mode == STORED && state->bits == 0) { + state->mode = TYPE; + return Z_OK; + } + return Z_DATA_ERROR; +} + +/* Macros for inflate(): */ + +/* check function to use adler32() for zlib or crc32() for gzip */ +#define UPDATE(check, buf, len) zlib_adler32(check, buf, len) + +/* Load registers with state in inflate() for speed */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Restore state from registers in inflate() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflate() + if there is no input available. */ +#define PULLBYTE() \ + do { \ + if (have == 0) goto inf_leave; \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflate(). */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Reverse the bytes in a 32-bit value */ +#define REVERSE(q) \ + ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) + +/* + inflate() uses a state machine to process as much input data and generate as + much output data as possible before returning. The state machine is + structured roughly as follows: + + for (;;) switch (state) { + ... + case STATEn: + if (not enough input data or output space to make progress) + return; + ... make progress ... + state = STATEm; + break; + ... + } + + so when inflate() is called again, the same case is attempted again, and + if the appropriate resources are provided, the machine proceeds to the + next state. The NEEDBITS() macro is usually the way the state evaluates + whether it can proceed or should return. NEEDBITS() does the return if + the requested bits are not available. The typical use of the BITS macros + is: + + NEEDBITS(n); + ... do something with BITS(n) ... + DROPBITS(n); + + where NEEDBITS(n) either returns from inflate() if there isn't enough + input left to load n bits into the accumulator, or it continues. BITS(n) + gives the low n bits in the accumulator. When done, DROPBITS(n) drops + the low n bits off the accumulator. INITBITS() clears the accumulator + and sets the number of available bits to zero. BYTEBITS() discards just + enough bits to put the accumulator on a byte boundary. After BYTEBITS() + and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. + + NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return + if there is no input available. The decoding of variable length codes uses + PULLBYTE() directly in order to pull just enough bytes to decode the next + code, and no more. + + Some states loop until they get enough input, making sure that enough + state information is maintained to continue the loop where it left off + if NEEDBITS() returns in the loop. For example, want, need, and keep + would all have to actually be part of the saved state in case NEEDBITS() + returns: + + case STATEw: + while (want < need) { + NEEDBITS(n); + keep[want++] = BITS(n); + DROPBITS(n); + } + state = STATEx; + case STATEx: + + As shown above, if the next state is also the next case, then the break + is omitted. + + A state may also return if there is not enough output space available to + complete that state. Those states are copying stored data, writing a + literal byte, and copying a matching string. + + When returning, a "goto inf_leave" is used to update the total counters, + update the check value, and determine whether any progress has been made + during that inflate() call in order to return the proper return code. + Progress is defined as a change in either strm->avail_in or strm->avail_out. + When there is a window, goto inf_leave will update the window with the last + output written. If a goto inf_leave occurs in the middle of decompression + and there is no window currently, goto inf_leave will create one and copy + output to the window for the next call of inflate(). + + In this implementation, the flush parameter of inflate() only affects the + return code (per zlib.h). inflate() always writes as much as possible to + strm->next_out, given the space available and the provided input--the effect + documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers + the allocation of and copying into a sliding window until necessary, which + provides the effect documented in zlib.h for Z_FINISH when the entire input + stream available. So the only thing the flush parameter actually does is: + when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it + will return Z_BUF_ERROR if it has not reached the end of the stream. + */ + +int zlib_inflate(z_streamp strm, int flush) +{ + struct inflate_state *state; + unsigned char *next; /* next input */ + unsigned char *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned in, out; /* save starting available input and output */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char *from; /* where to copy match bytes from */ + code this; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + if (strm == NULL || strm->state == NULL || strm->next_out == NULL || + (strm->next_in == NULL && strm->avail_in != 0)) + return Z_STREAM_ERROR; + + state = (struct inflate_state *)strm->state; + + if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ + LOAD(); + in = have; + out = left; + ret = Z_OK; + for (;;) + switch (state->mode) { + case HEAD: + if (state->wrap == 0) { + state->mode = TYPEDO; + break; + } + NEEDBITS(16); + if ( + ((BITS(8) << 8) + (hold >> 8)) % 31) { + strm->msg = (char *)"incorrect header check"; + state->mode = BAD; + break; + } + if (BITS(4) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + DROPBITS(4); + len = BITS(4) + 8; + if (len > state->wbits) { + strm->msg = (char *)"invalid window size"; + state->mode = BAD; + break; + } + state->dmax = 1U << len; + strm->adler = state->check = zlib_adler32(0L, NULL, 0); + state->mode = hold & 0x200 ? DICTID : TYPE; + INITBITS(); + break; + case DICTID: + NEEDBITS(32); + strm->adler = state->check = REVERSE(hold); + INITBITS(); + state->mode = DICT; + case DICT: + if (state->havedict == 0) { + RESTORE(); + return Z_NEED_DICT; + } + strm->adler = state->check = zlib_adler32(0L, NULL, 0); + state->mode = TYPE; + case TYPE: + if (flush == Z_BLOCK) goto inf_leave; + case TYPEDO: + if (state->last) { + BYTEBITS(); + state->mode = CHECK; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + state->mode = STORED; + break; + case 1: /* fixed block */ + zlib_fixedtables(state); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + case STORED: + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + INITBITS(); + state->mode = COPY; + case COPY: + copy = state->length; + if (copy) { + if (copy > have) copy = have; + if (copy > left) copy = left; + if (copy == 0) goto inf_leave; + memcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + break; + } + state->mode = TYPE; + break; + case TABLE: + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + state->have = 0; + state->mode = LENLENS; + case LENLENS: + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const *)(state->next); + state->lenbits = 7; + ret = zlib_inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + state->have = 0; + state->mode = CODELENS; + case CODELENS: + while (state->have < state->nlen + state->ndist) { + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.val < 16) { + NEEDBITS(this.bits); + DROPBITS(this.bits); + state->lens[state->have++] = this.val; + } + else { + if (this.val == 16) { + NEEDBITS(this.bits + 2); + DROPBITS(this.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = state->lens[state->have - 1]; + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (this.val == 17) { + NEEDBITS(this.bits + 3); + DROPBITS(this.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(this.bits + 7); + DROPBITS(this.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* build code tables */ + state->next = state->codes; + state->lencode = (code const *)(state->next); + state->lenbits = 9; + ret = zlib_inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const *)(state->next); + state->distbits = 6; + ret = zlib_inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + state->mode = LEN; + case LEN: + if (have >= 6 && left >= 258) { + RESTORE(); + inflate_fast(strm, out); + LOAD(); + break; + } + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.op && (this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + state->length = (unsigned)this.val; + if ((int)(this.op) == 0) { + state->mode = LIT; + break; + } + if (this.op & 32) { + state->mode = TYPE; + break; + } + if (this.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + state->extra = (unsigned)(this.op) & 15; + state->mode = LENEXT; + case LENEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + state->mode = DIST; + case DIST: + for (;;) { + this = state->distcode[BITS(state->distbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if ((this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + if (this.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)this.val; + state->extra = (unsigned)(this.op) & 15; + state->mode = DISTEXT; + case DISTEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } +#ifdef INFLATE_STRICT + if (state->offset > state->dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + if (state->offset > state->whave + out - left) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + state->mode = MATCH; + case MATCH: + if (left == 0) goto inf_leave; + copy = out - left; + if (state->offset > copy) { /* copy from window */ + copy = state->offset - copy; + if (copy > state->write) { + copy -= state->write; + from = state->window + (state->wsize - copy); + } + else + from = state->window + (state->write - copy); + if (copy > state->length) copy = state->length; + } + else { /* copy from output */ + from = put - state->offset; + copy = state->length; + } + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = *from++; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; + case LIT: + if (left == 0) goto inf_leave; + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + case CHECK: + if (state->wrap) { + NEEDBITS(32); + out -= left; + strm->total_out += out; + state->total += out; + if (out) + strm->adler = state->check = + UPDATE(state->check, put - out, out); + out = left; + if (( + REVERSE(hold)) != state->check) { + strm->msg = (char *)"incorrect data check"; + state->mode = BAD; + break; + } + INITBITS(); + } + state->mode = DONE; + case DONE: + ret = Z_STREAM_END; + goto inf_leave; + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + default: + return Z_STREAM_ERROR; + } + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call zlib_updatewindow() to create and/or update the window state. + */ + inf_leave: + RESTORE(); + if (state->wsize || (state->mode < CHECK && out != strm->avail_out)) + zlib_updatewindow(strm, out); + + in -= strm->avail_in; + out -= strm->avail_out; + strm->total_in += in; + strm->total_out += out; + state->total += out; + if (state->wrap && out) + strm->adler = state->check = + UPDATE(state->check, strm->next_out - out, out); + + strm->data_type = state->bits + (state->last ? 64 : 0) + + (state->mode == TYPE ? 128 : 0); + if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) + ret = Z_BUF_ERROR; + + if (flush == Z_PACKET_FLUSH && ret == Z_OK && + (strm->avail_out != 0 || strm->avail_in == 0)) + return zlib_inflateSyncPacket(strm); + return ret; +} + +int zlib_inflateEnd(z_streamp strm) +{ + if (strm == NULL || strm->state == NULL) + return Z_STREAM_ERROR; return Z_OK; } +#if 0 +int zlib_inflateSetDictionary(z_streamp strm, const Byte *dictionary, + uInt dictLength) +{ + struct inflate_state *state; + unsigned long id; + + /* check state */ + if (strm == NULL || strm->state == NULL) return Z_STREAM_ERROR; + state = (struct inflate_state *)strm->state; + if (state->wrap != 0 && state->mode != DICT) + return Z_STREAM_ERROR; + + /* check for correct dictionary id */ + if (state->mode == DICT) { + id = zlib_adler32(0L, NULL, 0); + id = zlib_adler32(id, dictionary, dictLength); + if (id != state->check) + return Z_DATA_ERROR; + } + + /* copy dictionary to window */ + zlib_updatewindow(strm, strm->avail_out); -int zlib_inflateInit_( - z_streamp z, - const char *version, - int stream_size -) + if (dictLength > state->wsize) { + memcpy(state->window, dictionary + dictLength - state->wsize, + state->wsize); + state->whave = state->wsize; + } + else { + memcpy(state->window + state->wsize - dictLength, dictionary, + dictLength); + state->whave = dictLength; + } + state->havedict = 1; + return Z_OK; +} +#endif + +#if 0 +/* + Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found + or when out of input. When called, *have is the number of pattern bytes + found in order so far, in 0..3. On return *have is updated to the new + state. If on return *have equals four, then the pattern was found and the + return value is how many bytes were read including the last byte of the + pattern. If *have is less than four, then the pattern has not been found + yet and the return value is len. In the latter case, zlib_syncsearch() can be + called again with more data and the *have state. *have is initialized to + zero for the first call. + */ +static unsigned zlib_syncsearch(unsigned *have, unsigned char *buf, + unsigned len) { - return zlib_inflateInit2_(z, DEF_WBITS, version, stream_size); + unsigned got; + unsigned next; + + got = *have; + next = 0; + while (next < len && got < 4) { + if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) + got++; + else if (buf[next]) + got = 0; + else + got = 4 - got; + next++; + } + *have = got; + return next; } +#endif -#undef NEEDBYTE -#undef NEXTBYTE -#define NEEDBYTE {if(z->avail_in==0)goto empty;r=trv;} -#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++) +#if 0 +int zlib_inflateSync(z_streamp strm) +{ + unsigned len; /* number of bytes to look at or looked at */ + unsigned long in, out; /* temporary to save total_in and total_out */ + unsigned char buf[4]; /* to restore bit buffer to byte string */ + struct inflate_state *state; + + /* check parameters */ + if (strm == NULL || strm->state == NULL) return Z_STREAM_ERROR; + state = (struct inflate_state *)strm->state; + if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; + + /* if first time, start search in bit buffer */ + if (state->mode != SYNC) { + state->mode = SYNC; + state->hold <<= state->bits & 7; + state->bits -= state->bits & 7; + len = 0; + while (state->bits >= 8) { + buf[len++] = (unsigned char)(state->hold); + state->hold >>= 8; + state->bits -= 8; + } + state->have = 0; + zlib_syncsearch(&(state->have), buf, len); + } + + /* search available input */ + len = zlib_syncsearch(&(state->have), strm->next_in, strm->avail_in); + strm->avail_in -= len; + strm->next_in += len; + strm->total_in += len; + + /* return no joy or set up to restart inflate() on a new block */ + if (state->have != 4) return Z_DATA_ERROR; + in = strm->total_in; out = strm->total_out; + zlib_inflateReset(strm); + strm->total_in = in; strm->total_out = out; + state->mode = TYPE; + return Z_OK; +} +#endif -int zlib_inflate( - z_streamp z, - int f -) +/* + * This subroutine adds the data at next_in/avail_in to the output history + * without performing any output. The output buffer must be "caught up"; + * i.e. no pending output but this should always be the case. The state must + * be waiting on the start of a block (i.e. mode == TYPE or HEAD). On exit, + * the output will also be caught up, and the checksum will have been updated + * if need be. + */ +int zlib_inflateIncomp(z_stream *z) { - int r, trv; - uInt b; - - if (z == NULL || z->state == NULL || z->next_in == NULL) - return Z_STREAM_ERROR; - trv = f == Z_FINISH ? Z_BUF_ERROR : Z_OK; - r = Z_BUF_ERROR; - while (1) switch (z->state->mode) - { - case METHOD: - NEEDBYTE - if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED) - { - z->state->mode = I_BAD; - z->msg = (char*)"unknown compression method"; - z->state->sub.marker = 5; /* can't try inflateSync */ - break; - } - if ((z->state->sub.method >> 4) + 8 > z->state->wbits) - { - z->state->mode = I_BAD; - z->msg = (char*)"invalid window size"; - z->state->sub.marker = 5; /* can't try inflateSync */ - break; - } - z->state->mode = FLAG; - case FLAG: - NEEDBYTE - b = NEXTBYTE; - if (((z->state->sub.method << 8) + b) % 31) - { - z->state->mode = I_BAD; - z->msg = (char*)"incorrect header check"; - z->state->sub.marker = 5; /* can't try inflateSync */ - break; - } - if (!(b & PRESET_DICT)) - { - z->state->mode = BLOCKS; - break; - } - z->state->mode = DICT4; - case DICT4: - NEEDBYTE - z->state->sub.check.need = (uLong)NEXTBYTE << 24; - z->state->mode = DICT3; - case DICT3: - NEEDBYTE - z->state->sub.check.need += (uLong)NEXTBYTE << 16; - z->state->mode = DICT2; - case DICT2: - NEEDBYTE - z->state->sub.check.need += (uLong)NEXTBYTE << 8; - z->state->mode = DICT1; - case DICT1: - NEEDBYTE - z->state->sub.check.need += (uLong)NEXTBYTE; - z->adler = z->state->sub.check.need; - z->state->mode = DICT0; - return Z_NEED_DICT; - case DICT0: - z->state->mode = I_BAD; - z->msg = (char*)"need dictionary"; - z->state->sub.marker = 0; /* can try inflateSync */ - return Z_STREAM_ERROR; - case BLOCKS: - r = zlib_inflate_blocks(z->state->blocks, z, r); - if (f == Z_PACKET_FLUSH && z->avail_in == 0 && z->avail_out != 0) - r = zlib_inflate_packet_flush(z->state->blocks); - if (r == Z_DATA_ERROR) - { - z->state->mode = I_BAD; - z->state->sub.marker = 0; /* can try inflateSync */ - break; - } - if (r == Z_OK) - r = trv; - if (r != Z_STREAM_END) - return r; - r = trv; - zlib_inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was); - if (z->state->nowrap) - { - z->state->mode = I_DONE; - break; - } - z->state->mode = CHECK4; - case CHECK4: - NEEDBYTE - z->state->sub.check.need = (uLong)NEXTBYTE << 24; - z->state->mode = CHECK3; - case CHECK3: - NEEDBYTE - z->state->sub.check.need += (uLong)NEXTBYTE << 16; - z->state->mode = CHECK2; - case CHECK2: - NEEDBYTE - z->state->sub.check.need += (uLong)NEXTBYTE << 8; - z->state->mode = CHECK1; - case CHECK1: - NEEDBYTE - z->state->sub.check.need += (uLong)NEXTBYTE; - - if (z->state->sub.check.was != z->state->sub.check.need) - { - z->state->mode = I_BAD; - z->msg = (char*)"incorrect data check"; - z->state->sub.marker = 5; /* can't try inflateSync */ - break; - } - z->state->mode = I_DONE; - case I_DONE: - return Z_STREAM_END; - case I_BAD: - return Z_DATA_ERROR; - default: - return Z_STREAM_ERROR; - } - empty: - if (f != Z_PACKET_FLUSH) - return r; - z->state->mode = I_BAD; - z->msg = (char *)"need more for packet flush"; - z->state->sub.marker = 0; /* can try inflateSync */ - return Z_DATA_ERROR; + struct inflate_state *state = (struct inflate_state *)z->state; + Byte *saved_no = z->next_out; + uInt saved_ao = z->avail_out; + + if (state->mode != TYPE && state->mode != HEAD) + return Z_DATA_ERROR; + + /* Setup some variables to allow misuse of updateWindow */ + z->avail_out = 0; + z->next_out = z->next_in + z->avail_in; + + zlib_updatewindow(z, z->avail_in); + + /* Restore saved variables */ + z->avail_out = saved_ao; + z->next_out = saved_no; + + z->adler = state->check = + UPDATE(state->check, z->next_in, z->avail_in); + + z->total_out += z->avail_in; + z->total_in += z->avail_in; + z->next_in += z->avail_in; + state->total += z->avail_in; + z->avail_in = 0; + + return Z_OK; } diff --git a/lib/zlib_inflate/inflate.h b/lib/zlib_inflate/inflate.h new file mode 100644 index 00000000000..df8a6c92052 --- /dev/null +++ b/lib/zlib_inflate/inflate.h @@ -0,0 +1,107 @@ +/* inflate.h -- internal inflate state definition + * Copyright (C) 1995-2004 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Possible inflate modes between inflate() calls */ +typedef enum { + HEAD, /* i: waiting for magic header */ + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN, /* i: waiting for length/lit code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ + LENGTH, /* i: waiting for 32-bit length (gzip) */ + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to the BAD or MEM mode -- not shown for clarity) + + Process header: + HEAD -> (gzip) or (zlib) + (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME + NAME -> COMMENT -> HCRC -> TYPE + (zlib) -> DICTID or TYPE + DICTID -> DICT -> TYPE + Read deflate blocks: + TYPE -> STORED or TABLE or LEN or CHECK + STORED -> COPY -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN + Read deflate codes: + LEN -> LENEXT or LIT or TYPE + LENEXT -> DIST -> DISTEXT -> MATCH -> LEN + LIT -> LEN + Process trailer: + CHECK -> LENGTH -> DONE + */ + +/* state maintained between inflate() calls. Approximately 7K bytes. */ +struct inflate_state { + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags (0 if zlib) */ + unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + /* gz_headerp head; */ /* where to save gzip header information */ + /* sliding window */ + unsigned wbits; /* log base 2 of requested window size */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char *window; /* allocated sliding window, if needed */ + /* bit accumulator */ + unsigned long hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + /* for string and stored block copying */ + unsigned length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + /* for table and code decoding */ + unsigned extra; /* extra bits needed */ + /* fixed and dynamic code tables */ + code const *lencode; /* starting table for length/literal codes */ + code const *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ +}; diff --git a/lib/zlib_inflate/inflate_syms.c b/lib/zlib_inflate/inflate_syms.c index ef49738f57e..2061d4f0676 100644 --- a/lib/zlib_inflate/inflate_syms.c +++ b/lib/zlib_inflate/inflate_syms.c @@ -12,8 +12,7 @@ EXPORT_SYMBOL(zlib_inflate_workspacesize); EXPORT_SYMBOL(zlib_inflate); -EXPORT_SYMBOL(zlib_inflateInit_); -EXPORT_SYMBOL(zlib_inflateInit2_); +EXPORT_SYMBOL(zlib_inflateInit2); EXPORT_SYMBOL(zlib_inflateEnd); EXPORT_SYMBOL(zlib_inflateReset); EXPORT_SYMBOL(zlib_inflateIncomp); diff --git a/lib/zlib_inflate/inflate_sync.c b/lib/zlib_inflate/inflate_sync.c deleted file mode 100644 index 61411ff89d6..00000000000 --- a/lib/zlib_inflate/inflate_sync.c +++ /dev/null @@ -1,152 +0,0 @@ -/* inflate.c -- zlib interface to inflate modules - * Copyright (C) 1995-1998 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include -#include "infblock.h" -#include "infutil.h" - -#if 0 -int zlib_inflateSync( - z_streamp z -) -{ - uInt n; /* number of bytes to look at */ - Byte *p; /* pointer to bytes */ - uInt m; /* number of marker bytes found in a row */ - uLong r, w; /* temporaries to save total_in and total_out */ - - /* set up */ - if (z == NULL || z->state == NULL) - return Z_STREAM_ERROR; - if (z->state->mode != I_BAD) - { - z->state->mode = I_BAD; - z->state->sub.marker = 0; - } - if ((n = z->avail_in) == 0) - return Z_BUF_ERROR; - p = z->next_in; - m = z->state->sub.marker; - - /* search */ - while (n && m < 4) - { - static const Byte mark[4] = {0, 0, 0xff, 0xff}; - if (*p == mark[m]) - m++; - else if (*p) - m = 0; - else - m = 4 - m; - p++, n--; - } - - /* restore */ - z->total_in += p - z->next_in; - z->next_in = p; - z->avail_in = n; - z->state->sub.marker = m; - - /* return no joy or set up to restart on a new block */ - if (m != 4) - return Z_DATA_ERROR; - r = z->total_in; w = z->total_out; - zlib_inflateReset(z); - z->total_in = r; z->total_out = w; - z->state->mode = BLOCKS; - return Z_OK; -} -#endif /* 0 */ - - -/* Returns true if inflate is currently at the end of a block generated - * by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP - * implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH - * but removes the length bytes of the resulting empty stored block. When - * decompressing, PPP checks that at the end of input packet, inflate is - * waiting for these length bytes. - */ -#if 0 -int zlib_inflateSyncPoint( - z_streamp z -) -{ - if (z == NULL || z->state == NULL || z->state->blocks == NULL) - return Z_STREAM_ERROR; - return zlib_inflate_blocks_sync_point(z->state->blocks); -} -#endif /* 0 */ - -/* - * This subroutine adds the data at next_in/avail_in to the output history - * without performing any output. The output buffer must be "caught up"; - * i.e. no pending output (hence s->read equals s->write), and the state must - * be BLOCKS (i.e. we should be willing to see the start of a series of - * BLOCKS). On exit, the output will also be caught up, and the checksum - * will have been updated if need be. - */ -static int zlib_inflate_addhistory(inflate_blocks_statef *s, - z_stream *z) -{ - uLong b; /* bit buffer */ /* NOT USED HERE */ - uInt k; /* bits in bit buffer */ /* NOT USED HERE */ - uInt t; /* temporary storage */ - Byte *p; /* input data pointer */ - uInt n; /* bytes available there */ - Byte *q; /* output window write pointer */ - uInt m; /* bytes to end of window or read pointer */ - - if (s->read != s->write) - return Z_STREAM_ERROR; - if (s->mode != TYPE) - return Z_DATA_ERROR; - - /* we're ready to rock */ - LOAD - /* while there is input ready, copy to output buffer, moving - * pointers as needed. - */ - while (n) { - t = n; /* how many to do */ - /* is there room until end of buffer? */ - if (t > m) t = m; - /* update check information */ - if (s->checkfn != NULL) - s->check = (*s->checkfn)(s->check, q, t); - memcpy(q, p, t); - q += t; - p += t; - n -= t; - z->total_out += t; - s->read = q; /* drag read pointer forward */ -/* WWRAP */ /* expand WWRAP macro by hand to handle s->read */ - if (q == s->end) { - s->read = q = s->window; - m = WAVAIL; - } - } - UPDATE - return Z_OK; -} - - -/* - * This subroutine adds the data at next_in/avail_in to the output history - * without performing any output. The output buffer must be "caught up"; - * i.e. no pending output (hence s->read equals s->write), and the state must - * be BLOCKS (i.e. we should be willing to see the start of a series of - * BLOCKS). On exit, the output will also be caught up, and the checksum - * will have been updated if need be. - */ - -int zlib_inflateIncomp( - z_stream *z - -) -{ - if (z->state->mode != BLOCKS) - return Z_DATA_ERROR; - return zlib_inflate_addhistory(z->state->blocks, z); -} diff --git a/lib/zlib_inflate/inftrees.c b/lib/zlib_inflate/inftrees.c index 874950ec485..62343c53bf7 100644 --- a/lib/zlib_inflate/inftrees.c +++ b/lib/zlib_inflate/inftrees.c @@ -1,412 +1,329 @@ /* inftrees.c -- generate Huffman trees for efficient decoding - * Copyright (C) 1995-1998 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h */ #include #include "inftrees.h" -#include "infutil.h" -static const char inflate_copyright[] __attribute_used__ = - " inflate 1.1.3 Copyright 1995-1998 Mark Adler "; +#define MAXBITS 15 + +const char inflate_copyright[] = + " inflate 1.2.3 Copyright 1995-2005 Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot include such an acknowledgment, I would appreciate that you keep this copyright string in the executable of your product. */ -struct internal_state; - -/* simplify the use of the inflate_huft type with some defines */ -#define exop word.what.Exop -#define bits word.what.Bits - - -static int huft_build ( - uInt *, /* code lengths in bits */ - uInt, /* number of codes */ - uInt, /* number of "simple" codes */ - const uInt *, /* list of base values for non-simple codes */ - const uInt *, /* list of extra bits for non-simple codes */ - inflate_huft **, /* result: starting table */ - uInt *, /* maximum lookup bits (returns actual) */ - inflate_huft *, /* space for trees */ - uInt *, /* hufts used in space */ - uInt * ); /* space for values */ - -/* Tables for deflate from PKZIP's appnote.txt. */ -static const uInt cplens[31] = { /* Copy lengths for literal codes 257..285 */ - 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, - 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; - /* see note #13 above about 258 */ -static const uInt cplext[31] = { /* Extra bits for literal codes 257..285 */ - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, - 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; /* 112==invalid */ -static const uInt cpdist[30] = { /* Copy offsets for distance codes 0..29 */ - 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, - 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, - 8193, 12289, 16385, 24577}; -static const uInt cpdext[30] = { /* Extra bits for distance codes */ - 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, - 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, - 12, 12, 13, 13}; /* - Huffman code decoding is performed using a multi-level table lookup. - The fastest way to decode is to simply build a lookup table whose - size is determined by the longest code. However, the time it takes - to build this table can also be a factor if the data being decoded - is not very long. The most common codes are necessarily the - shortest codes, so those codes dominate the decoding time, and hence - the speed. The idea is you can have a shorter table that decodes the - shorter, more probable codes, and then point to subsidiary tables for - the longer codes. The time it costs to decode the longer codes is - then traded against the time it takes to make longer tables. - - This results of this trade are in the variables lbits and dbits - below. lbits is the number of bits the first level table for literal/ - length codes can decode in one step, and dbits is the same thing for - the distance codes. Subsequent tables are also less than or equal to - those sizes. These values may be adjusted either when all of the - codes are shorter than that, in which case the longest code length in - bits is used, or when the shortest code is *longer* than the requested - table size, in which case the length of the shortest code in bits is - used. - - There are two different values for the two tables, since they code a - different number of possibilities each. The literal/length table - codes 286 possible values, or in a flat code, a little over eight - bits. The distance table codes 30 possible values, or a little less - than five bits, flat. The optimum values for speed end up being - about one bit more than those, so lbits is 8+1 and dbits is 5+1. - The optimum values may differ though from machine to machine, and - possibly even between compilers. Your mileage may vary. + Build a set of tables to decode the provided canonical Huffman code. + The code lengths are lens[0..codes-1]. The result starts at *table, + whose indices are 0..2^bits-1. work is a writable array of at least + lens shorts, which is used as a work area. type is the type of code + to be generated, CODES, LENS, or DISTS. On return, zero is success, + -1 is an invalid code, and +1 means that ENOUGH isn't enough. table + on return points to the next available entry's address. bits is the + requested root table index bits, and on return it is the actual root + table index bits. It will differ if the request is greater than the + longest code or if it is less than the shortest code. */ - - -/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */ -#define BMAX 15 /* maximum bit length of any code */ - -static int huft_build( - uInt *b, /* code lengths in bits (all assumed <= BMAX) */ - uInt n, /* number of codes (assumed <= 288) */ - uInt s, /* number of simple-valued codes (0..s-1) */ - const uInt *d, /* list of base values for non-simple codes */ - const uInt *e, /* list of extra bits for non-simple codes */ - inflate_huft **t, /* result: starting table */ - uInt *m, /* maximum lookup bits, returns actual */ - inflate_huft *hp, /* space for trees */ - uInt *hn, /* hufts used in space */ - uInt *v /* working area: values in order of bit length */ -) -/* Given a list of code lengths and a maximum table size, make a set of - tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR - if the given code set is incomplete (the tables are still built in this - case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of - lengths), or Z_MEM_ERROR if not enough memory. */ +int zlib_inflate_table(type, lens, codes, table, bits, work) +codetype type; +unsigned short *lens; +unsigned codes; +code **table; +unsigned *bits; +unsigned short *work; { + unsigned len; /* a code's length in bits */ + unsigned sym; /* index of code symbols */ + unsigned min, max; /* minimum and maximum code lengths */ + unsigned root; /* number of index bits for root table */ + unsigned curr; /* number of index bits for current table */ + unsigned drop; /* code bits to drop for sub-table */ + int left; /* number of prefix codes available */ + unsigned used; /* code entries in table used */ + unsigned huff; /* Huffman code */ + unsigned incr; /* for incrementing code, index */ + unsigned fill; /* index for replicating entries */ + unsigned low; /* low bits for current root entry */ + unsigned mask; /* mask for low root bits */ + code this; /* table entry for duplication */ + code *next; /* next available space in table */ + const unsigned short *base; /* base value table to use */ + const unsigned short *extra; /* extra bits table to use */ + int end; /* use base and extra for symbol > end */ + unsigned short count[MAXBITS+1]; /* number of codes of each length */ + unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ + static const unsigned short lbase[31] = { /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + static const unsigned short lext[31] = { /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 201, 196}; + static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0}; + static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64}; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) + count[len] = 0; + for (sym = 0; sym < codes; sym++) + count[lens[sym]]++; + + /* bound code lengths, force root to be within code lengths */ + root = *bits; + for (max = MAXBITS; max >= 1; max--) + if (count[max] != 0) break; + if (root > max) root = max; + if (max == 0) { /* no symbols to code at all */ + this.op = (unsigned char)64; /* invalid code marker */ + this.bits = (unsigned char)1; + this.val = (unsigned short)0; + *(*table)++ = this; /* make a table to force an error */ + *(*table)++ = this; + *bits = 1; + return 0; /* no symbols, but wait for decoding to report error */ + } + for (min = 1; min <= MAXBITS; min++) + if (count[min] != 0) break; + if (root < min) root = min; + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) return -1; /* over-subscribed */ + } + if (left > 0 && (type == CODES || max != 1)) + return -1; /* incomplete set */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + count[len]; + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) + if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked when a LENS table is being made + against the space in *table, ENOUGH, minus the maximum space needed by + the worst case distance code, MAXD. This should never happen, but the + sufficiency of ENOUGH has not been proven exhaustively, hence the check. + This assumes that when type == LENS, bits == 9. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ + end = 19; + break; + case LENS: + base = lbase; + base -= 257; + extra = lext; + extra -= 257; + end = 256; + break; + default: /* DISTS */ + base = dbase; + extra = dext; + end = -1; + } - uInt a; /* counter for codes of length k */ - uInt c[BMAX+1]; /* bit length count table */ - uInt f; /* i repeats in table every f entries */ - int g; /* maximum code length */ - int h; /* table level */ - register uInt i; /* counter, current code */ - register uInt j; /* counter */ - register int k; /* number of bits in current code */ - int l; /* bits per table (returned in m) */ - uInt mask; /* (1 << w) - 1, to avoid cc -O bug on HP */ - register uInt *p; /* pointer into c[], b[], or v[] */ - inflate_huft *q; /* points to current table */ - struct inflate_huft_s r; /* table entry for structure assignment */ - inflate_huft *u[BMAX]; /* table stack */ - register int w; /* bits before this table == (l * h) */ - uInt x[BMAX+1]; /* bit offsets, then code stack */ - uInt *xp; /* pointer into x */ - int y; /* number of dummy codes added */ - uInt z; /* number of entries in current table */ - - - /* Generate counts for each bit length */ - p = c; -#define C0 *p++ = 0; -#define C2 C0 C0 C0 C0 -#define C4 C2 C2 C2 C2 - C4 /* clear c[]--assume BMAX+1 is 16 */ - p = b; i = n; - do { - c[*p++]++; /* assume all entries <= BMAX */ - } while (--i); - if (c[0] == n) /* null input--all zero length codes */ - { - *t = NULL; - *m = 0; - return Z_OK; - } - - - /* Find minimum and maximum length, bound *m by those */ - l = *m; - for (j = 1; j <= BMAX; j++) - if (c[j]) - break; - k = j; /* minimum code length */ - if ((uInt)l < j) - l = j; - for (i = BMAX; i; i--) - if (c[i]) - break; - g = i; /* maximum code length */ - if ((uInt)l > i) - l = i; - *m = l; - - - /* Adjust last length count to fill out codes, if needed */ - for (y = 1 << j; j < i; j++, y <<= 1) - if ((y -= c[j]) < 0) - return Z_DATA_ERROR; - if ((y -= c[i]) < 0) - return Z_DATA_ERROR; - c[i] += y; - - - /* Generate starting offsets into the value table for each length */ - x[1] = j = 0; - p = c + 1; xp = x + 2; - while (--i) { /* note that i == g from above */ - *xp++ = (j += *p++); - } - - - /* Make a table of values in order of bit lengths */ - p = b; i = 0; - do { - if ((j = *p++) != 0) - v[x[j]++] = i; - } while (++i < n); - n = x[g]; /* set n to length of v */ - - - /* Generate the Huffman codes and for each, make the table entries */ - x[0] = i = 0; /* first Huffman code is zero */ - p = v; /* grab values in bit order */ - h = -1; /* no tables yet--level -1 */ - w = -l; /* bits decoded == (l * h) */ - u[0] = NULL; /* just to keep compilers happy */ - q = NULL; /* ditto */ - z = 0; /* ditto */ - - /* go through the bit lengths (k already is bits in shortest code) */ - for (; k <= g; k++) - { - a = c[k]; - while (a--) - { - /* here i is the Huffman code of length k bits for value *p */ - /* make tables up to required level */ - while (k > w + l) - { - h++; - w += l; /* previous table always l bits */ - - /* compute minimum size table less than or equal to l bits */ - z = g - w; - z = z > (uInt)l ? l : z; /* table size upper limit */ - if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ - { /* too few codes for k-w bit table */ - f -= a + 1; /* deduct codes from patterns left */ - xp = c + k; - if (j < z) - while (++j < z) /* try smaller tables up to z bits */ - { - if ((f <<= 1) <= *++xp) - break; /* enough codes to use up j bits */ - f -= *xp; /* else deduct codes from patterns */ - } + /* initialize state for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = *table; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = (unsigned)(-1); /* trigger new sub-table when len > root */ + used = 1U << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if (type == LENS && used >= ENOUGH - MAXD) + return 1; + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + this.bits = (unsigned char)(len - drop); + if ((int)(work[sym]) < end) { + this.op = (unsigned char)0; + this.val = work[sym]; } - z = 1 << j; /* table entries for j-bit table */ - - /* allocate new table */ - if (*hn + z > MANY) /* (note: doesn't matter for fixed) */ - return Z_DATA_ERROR; /* overflow of MANY */ - u[h] = q = hp + *hn; - *hn += z; - - /* connect to last table, if there is one */ - if (h) - { - x[h] = i; /* save pattern for backing up */ - r.bits = (Byte)l; /* bits to dump before this table */ - r.exop = (Byte)j; /* bits in this table */ - j = i >> (w - l); - r.base = (uInt)(q - u[h-1] - j); /* offset to this table */ - u[h-1][j] = r; /* connect to last table */ + else if ((int)(work[sym]) > end) { + this.op = (unsigned char)(extra[work[sym]]); + this.val = base[work[sym]]; + } + else { + this.op = (unsigned char)(32 + 64); /* end of block */ + this.val = 0; } - else - *t = q; /* first table is returned result */ - } - - /* set up table entry in r */ - r.bits = (Byte)(k - w); - if (p >= v + n) - r.exop = 128 + 64; /* out of values--invalid code */ - else if (*p < s) - { - r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); /* 256 is end-of-block */ - r.base = *p++; /* simple code is just the value */ - } - else - { - r.exop = (Byte)(e[*p - s] + 16 + 64);/* non-simple--look up in lists */ - r.base = d[*p++ - s]; - } - - /* fill code-like entries with r */ - f = 1 << (k - w); - for (j = i >> w; j < z; j += f) - q[j] = r; - - /* backwards increment the k-bit code i */ - for (j = 1 << (k - 1); i & j; j >>= 1) - i ^= j; - i ^= j; - - /* backup over finished tables */ - mask = (1 << w) - 1; /* needed on HP, cc -O bug */ - while ((i & mask) != x[h]) - { - h--; /* don't need to update q */ - w -= l; - mask = (1 << w) - 1; - } - } - } + /* replicate for those indices with low len bits equal to huff */ + incr = 1U << (len - drop); + fill = 1U << curr; + min = fill; /* save offset to next table */ + do { + fill -= incr; + next[(huff >> drop) + fill] = this; + } while (fill != 0); + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; - /* Return Z_BUF_ERROR if we were given an incomplete table */ - return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK; -} + /* go to next symbol, update count, len */ + sym++; + if (--(count[len]) == 0) { + if (len == max) break; + len = lens[work[sym]]; + } + /* create new sub-table if needed */ + if (len > root && (huff & mask) != low) { + /* if first time, transition to sub-tables */ + if (drop == 0) + drop = root; + + /* increment past last table */ + next += min; /* here min is 1 << curr */ + + /* determine length of next table */ + curr = len - drop; + left = (int)(1 << curr); + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) break; + curr++; + left <<= 1; + } -int zlib_inflate_trees_bits( - uInt *c, /* 19 code lengths */ - uInt *bb, /* bits tree desired/actual depth */ - inflate_huft **tb, /* bits tree result */ - inflate_huft *hp, /* space for trees */ - z_streamp z /* for messages */ -) -{ - int r; - uInt hn = 0; /* hufts used in space */ - uInt *v; /* work area for huft_build */ - - v = WS(z)->tree_work_area_1; - r = huft_build(c, 19, 19, NULL, NULL, tb, bb, hp, &hn, v); - if (r == Z_DATA_ERROR) - z->msg = (char*)"oversubscribed dynamic bit lengths tree"; - else if (r == Z_BUF_ERROR || *bb == 0) - { - z->msg = (char*)"incomplete dynamic bit lengths tree"; - r = Z_DATA_ERROR; - } - return r; -} + /* check for enough space */ + used += 1U << curr; + if (type == LENS && used >= ENOUGH - MAXD) + return 1; -int zlib_inflate_trees_dynamic( - uInt nl, /* number of literal/length codes */ - uInt nd, /* number of distance codes */ - uInt *c, /* that many (total) code lengths */ - uInt *bl, /* literal desired/actual bit depth */ - uInt *bd, /* distance desired/actual bit depth */ - inflate_huft **tl, /* literal/length tree result */ - inflate_huft **td, /* distance tree result */ - inflate_huft *hp, /* space for trees */ - z_streamp z /* for messages */ -) -{ - int r; - uInt hn = 0; /* hufts used in space */ - uInt *v; /* work area for huft_build */ - - /* allocate work area */ - v = WS(z)->tree_work_area_2; - - /* build literal/length tree */ - r = huft_build(c, nl, 257, cplens, cplext, tl, bl, hp, &hn, v); - if (r != Z_OK || *bl == 0) - { - if (r == Z_DATA_ERROR) - z->msg = (char*)"oversubscribed literal/length tree"; - else if (r != Z_MEM_ERROR) - { - z->msg = (char*)"incomplete literal/length tree"; - r = Z_DATA_ERROR; - } - return r; - } - - /* build distance tree */ - r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, hp, &hn, v); - if (r != Z_OK || (*bd == 0 && nl > 257)) - { - if (r == Z_DATA_ERROR) - z->msg = (char*)"oversubscribed distance tree"; - else if (r == Z_BUF_ERROR) { -#ifdef PKZIP_BUG_WORKAROUND - r = Z_OK; - } -#else - z->msg = (char*)"incomplete distance tree"; - r = Z_DATA_ERROR; - } - else if (r != Z_MEM_ERROR) - { - z->msg = (char*)"empty distance tree with lengths"; - r = Z_DATA_ERROR; + /* point entry in root table to sub-table */ + low = huff & mask; + (*table)[low].op = (unsigned char)curr; + (*table)[low].bits = (unsigned char)root; + (*table)[low].val = (unsigned short)(next - *table); + } } - return r; -#endif - } - /* done */ - return Z_OK; -} + /* + Fill in rest of table for incomplete codes. This loop is similar to the + loop above in incrementing huff for table indices. It is assumed that + len is equal to curr + drop, so there is no loop needed to increment + through high index bits. When the current sub-table is filled, the loop + drops back to the root table to fill in any remaining entries there. + */ + this.op = (unsigned char)64; /* invalid code marker */ + this.bits = (unsigned char)(len - drop); + this.val = (unsigned short)0; + while (huff != 0) { + /* when done with sub-table, drop back to root table */ + if (drop != 0 && (huff & mask) != low) { + drop = 0; + len = root; + next = *table; + this.bits = (unsigned char)len; + } + /* put invalid code marker in table */ + next[huff >> drop] = this; -int zlib_inflate_trees_fixed( - uInt *bl, /* literal desired/actual bit depth */ - uInt *bd, /* distance desired/actual bit depth */ - inflate_huft **tl, /* literal/length tree result */ - inflate_huft **td, /* distance tree result */ - inflate_huft *hp, /* space for trees */ - z_streamp z /* for memory allocation */ -) -{ - int i; /* temporary variable */ - unsigned l[288]; /* length list for huft_build */ - uInt *v; /* work area for huft_build */ - - /* set up literal table */ - for (i = 0; i < 144; i++) - l[i] = 8; - for (; i < 256; i++) - l[i] = 9; - for (; i < 280; i++) - l[i] = 7; - for (; i < 288; i++) /* make a complete, but wrong code set */ - l[i] = 8; - *bl = 9; - v = WS(z)->tree_work_area_1; - if ((i = huft_build(l, 288, 257, cplens, cplext, tl, bl, hp, &i, v)) != 0) - return i; - - /* set up distance table */ - for (i = 0; i < 30; i++) /* make an incomplete code set */ - l[i] = 5; - *bd = 5; - if ((i = huft_build(l, 30, 0, cpdist, cpdext, td, bd, hp, &i, v)) > 1) - return i; - - return Z_OK; + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + } + + /* set return parameters */ + *table += used; + *bits = root; + return 0; } diff --git a/lib/zlib_inflate/inftrees.h b/lib/zlib_inflate/inftrees.h index e37705adc00..5f5219b1240 100644 --- a/lib/zlib_inflate/inftrees.h +++ b/lib/zlib_inflate/inftrees.h @@ -1,6 +1,6 @@ /* inftrees.h -- header to use inftrees.c - * Copyright (C) 1995-1998 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is @@ -8,57 +8,48 @@ subject to change. Applications should only use zlib.h. */ -/* Huffman code lookup table entry--this entry is four bytes for machines - that have 16-bit pointers (e.g. PC's in the small or medium model). */ - -#ifndef _INFTREES_H -#define _INFTREES_H - -typedef struct inflate_huft_s inflate_huft; - -struct inflate_huft_s { - union { - struct { - Byte Exop; /* number of extra bits or operation */ - Byte Bits; /* number of bits in this code or subcode */ - } what; - uInt pad; /* pad structure to a power of 2 (4 bytes for */ - } word; /* 16-bit, 8 bytes for 32-bit int's) */ - uInt base; /* literal, length base, distance base, - or table offset */ -}; +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ +} code; + +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 0001eeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ /* Maximum size of dynamic tree. The maximum found in a long but non- - exhaustive search was 1004 huft structures (850 for length/literals - and 154 for distances, the latter actually the result of an - exhaustive search). The actual maximum is not known, but the - value below is more than safe. */ -#define MANY 1440 - -extern int zlib_inflate_trees_bits ( - uInt *, /* 19 code lengths */ - uInt *, /* bits tree desired/actual depth */ - inflate_huft **, /* bits tree result */ - inflate_huft *, /* space for trees */ - z_streamp); /* for messages */ - -extern int zlib_inflate_trees_dynamic ( - uInt, /* number of literal/length codes */ - uInt, /* number of distance codes */ - uInt *, /* that many (total) code lengths */ - uInt *, /* literal desired/actual bit depth */ - uInt *, /* distance desired/actual bit depth */ - inflate_huft **, /* literal/length tree result */ - inflate_huft **, /* distance tree result */ - inflate_huft *, /* space for trees */ - z_streamp); /* for messages */ - -extern int zlib_inflate_trees_fixed ( - uInt *, /* literal desired/actual bit depth */ - uInt *, /* distance desired/actual bit depth */ - inflate_huft **, /* literal/length tree result */ - inflate_huft **, /* distance tree result */ - inflate_huft *, /* space for trees */ - z_streamp); /* for memory allocation */ - -#endif /* _INFTREES_H */ + exhaustive search was 1444 code structures (852 for length/literals + and 592 for distances, the latter actually the result of an + exhaustive search). The true maximum is not known, but the value + below is more than safe. */ +#define ENOUGH 2048 +#define MAXD 592 + +/* Type of code to build for inftable() */ +typedef enum { + CODES, + LENS, + DISTS +} codetype; + +extern int zlib_inflate_table (codetype type, unsigned short *lens, + unsigned codes, code **table, + unsigned *bits, unsigned short *work); diff --git a/lib/zlib_inflate/infutil.c b/lib/zlib_inflate/infutil.c deleted file mode 100644 index 00202b3438e..00000000000 --- a/lib/zlib_inflate/infutil.c +++ /dev/null @@ -1,88 +0,0 @@ -/* inflate_util.c -- data and routines common to blocks and codes - * Copyright (C) 1995-1998 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include -#include "infblock.h" -#include "inftrees.h" -#include "infcodes.h" -#include "infutil.h" - -struct inflate_codes_state; - -/* And'ing with mask[n] masks the lower n bits */ -uInt zlib_inflate_mask[17] = { - 0x0000, - 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, - 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff -}; - - -/* copy as much as possible from the sliding window to the output area */ -int zlib_inflate_flush( - inflate_blocks_statef *s, - z_streamp z, - int r -) -{ - uInt n; - Byte *p; - Byte *q; - - /* local copies of source and destination pointers */ - p = z->next_out; - q = s->read; - - /* compute number of bytes to copy as far as end of window */ - n = (uInt)((q <= s->write ? s->write : s->end) - q); - if (n > z->avail_out) n = z->avail_out; - if (n && r == Z_BUF_ERROR) r = Z_OK; - - /* update counters */ - z->avail_out -= n; - z->total_out += n; - - /* update check information */ - if (s->checkfn != NULL) - z->adler = s->check = (*s->checkfn)(s->check, q, n); - - /* copy as far as end of window */ - memcpy(p, q, n); - p += n; - q += n; - - /* see if more to copy at beginning of window */ - if (q == s->end) - { - /* wrap pointers */ - q = s->window; - if (s->write == s->end) - s->write = s->window; - - /* compute bytes to copy */ - n = (uInt)(s->write - q); - if (n > z->avail_out) n = z->avail_out; - if (n && r == Z_BUF_ERROR) r = Z_OK; - - /* update counters */ - z->avail_out -= n; - z->total_out += n; - - /* update check information */ - if (s->checkfn != NULL) - z->adler = s->check = (*s->checkfn)(s->check, q, n); - - /* copy */ - memcpy(p, q, n); - p += n; - q += n; - } - - /* update pointers */ - z->next_out = p; - s->read = q; - - /* done */ - return r; -} diff --git a/lib/zlib_inflate/infutil.h b/lib/zlib_inflate/infutil.h index a15875fc5f7..eb1a9007bd8 100644 --- a/lib/zlib_inflate/infutil.h +++ b/lib/zlib_inflate/infutil.h @@ -11,184 +11,12 @@ #ifndef _INFUTIL_H #define _INFUTIL_H -#include -#include "inftrees.h" -#include "infcodes.h" - -typedef enum { - TYPE, /* get type bits (3, including end bit) */ - LENS, /* get lengths for stored */ - STORED, /* processing stored block */ - TABLE, /* get table lengths */ - BTREE, /* get bit lengths tree for a dynamic block */ - DTREE, /* get length, distance trees for a dynamic block */ - CODES, /* processing fixed or dynamic block */ - DRY, /* output remaining window bytes */ - B_DONE, /* finished last block, done */ - B_BAD} /* got a data error--stuck here */ -inflate_block_mode; - -/* inflate blocks semi-private state */ -struct inflate_blocks_state { - - /* mode */ - inflate_block_mode mode; /* current inflate_block mode */ - - /* mode dependent information */ - union { - uInt left; /* if STORED, bytes left to copy */ - struct { - uInt table; /* table lengths (14 bits) */ - uInt index; /* index into blens (or border) */ - uInt *blens; /* bit lengths of codes */ - uInt bb; /* bit length tree depth */ - inflate_huft *tb; /* bit length decoding tree */ - } trees; /* if DTREE, decoding info for trees */ - struct { - inflate_codes_statef - *codes; - } decode; /* if CODES, current state */ - } sub; /* submode */ - uInt last; /* true if this block is the last block */ - - /* mode independent information */ - uInt bitk; /* bits in bit buffer */ - uLong bitb; /* bit buffer */ - inflate_huft *hufts; /* single malloc for tree space */ - Byte *window; /* sliding window */ - Byte *end; /* one byte after sliding window */ - Byte *read; /* window read pointer */ - Byte *write; /* window write pointer */ - check_func checkfn; /* check function */ - uLong check; /* check on output */ - -}; - - -/* defines for inflate input/output */ -/* update pointers and return */ -#define UPDBITS {s->bitb=b;s->bitk=k;} -#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;} -#define UPDOUT {s->write=q;} -#define UPDATE {UPDBITS UPDIN UPDOUT} -#define LEAVE {UPDATE return zlib_inflate_flush(s,z,r);} -/* get bytes and bits */ -#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;} -#define NEEDBYTE {if(n)r=Z_OK;else LEAVE} -#define NEXTBYTE (n--,*p++) -#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<>=(j);k-=(j);} -/* output bytes */ -#define WAVAIL (uInt)(qread?s->read-q-1:s->end-q) -#define LOADOUT {q=s->write;m=(uInt)WAVAIL;} -#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}} -#define FLUSH {UPDOUT r=zlib_inflate_flush(s,z,r); LOADOUT} -#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;} -#define OUTBYTE(a) {*q++=(Byte)(a);m--;} -/* load local pointers */ -#define LOAD {LOADIN LOADOUT} - -/* masks for lower bits (size given to avoid silly warnings with Visual C++) */ -extern uInt zlib_inflate_mask[17]; - -/* copy as much as possible from the sliding window to the output area */ -extern int zlib_inflate_flush ( - inflate_blocks_statef *, - z_streamp , - int); - -/* inflate private state */ -typedef enum { - METHOD, /* waiting for method byte */ - FLAG, /* waiting for flag byte */ - DICT4, /* four dictionary check bytes to go */ - DICT3, /* three dictionary check bytes to go */ - DICT2, /* two dictionary check bytes to go */ - DICT1, /* one dictionary check byte to go */ - DICT0, /* waiting for inflateSetDictionary */ - BLOCKS, /* decompressing blocks */ - CHECK4, /* four check bytes to go */ - CHECK3, /* three check bytes to go */ - CHECK2, /* two check bytes to go */ - CHECK1, /* one check byte to go */ - I_DONE, /* finished check, done */ - I_BAD} /* got an error--stay here */ -inflate_mode; - -struct internal_state { - - /* mode */ - inflate_mode mode; /* current inflate mode */ - - /* mode dependent information */ - union { - uInt method; /* if FLAGS, method byte */ - struct { - uLong was; /* computed check value */ - uLong need; /* stream check value */ - } check; /* if CHECK, check values to compare */ - uInt marker; /* if BAD, inflateSync's marker bytes count */ - } sub; /* submode */ - - /* mode independent information */ - int nowrap; /* flag for no wrapper */ - uInt wbits; /* log2(window size) (8..15, defaults to 15) */ - inflate_blocks_statef - *blocks; /* current inflate_blocks state */ - -}; - -/* inflate codes private state */ -typedef enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ - START, /* x: set up for LEN */ - LEN, /* i: get length/literal/eob next */ - LENEXT, /* i: getting length extra (have base) */ - DIST, /* i: get distance next */ - DISTEXT, /* i: getting distance extra */ - COPY, /* o: copying bytes in window, waiting for space */ - LIT, /* o: got literal, waiting for output space */ - WASH, /* o: got eob, possibly still output waiting */ - END, /* x: got eob and all data flushed */ - BADCODE} /* x: got error */ -inflate_codes_mode; - -struct inflate_codes_state { - - /* mode */ - inflate_codes_mode mode; /* current inflate_codes mode */ - - /* mode dependent information */ - uInt len; - union { - struct { - inflate_huft *tree; /* pointer into tree */ - uInt need; /* bits needed */ - } code; /* if LEN or DIST, where in tree */ - uInt lit; /* if LIT, literal */ - struct { - uInt get; /* bits to get for extra */ - uInt dist; /* distance back to copy from */ - } copy; /* if EXT or COPY, where and how much */ - } sub; /* submode */ - - /* mode independent information */ - Byte lbits; /* ltree bits decoded per branch */ - Byte dbits; /* dtree bits decoder per branch */ - inflate_huft *ltree; /* literal/length/eob tree */ - inflate_huft *dtree; /* distance tree */ - -}; +#include /* memory allocation for inflation */ struct inflate_workspace { - inflate_codes_statef working_state; - struct inflate_blocks_state working_blocks_state; - struct internal_state internal_state; - unsigned int tree_work_area_1[19]; - unsigned int tree_work_area_2[288]; - unsigned working_blens[258 + 0x1f + 0x1f]; - inflate_huft working_hufts[MANY]; + struct inflate_state inflate_state; unsigned char working_window[1 << MAX_WBITS]; }; -- cgit v1.2.3 From dcc1a66a09420ccc5a22671bddc5a842f92d67e5 Mon Sep 17 00:00:00 2001 From: Roman Zippel Date: Thu, 22 Jun 2006 14:47:35 -0700 Subject: [PATCH] x86_64: use select for GART_IOMMU to enable AGP The AGP default doesn't work well with other selects, so use a select for GART_IOMMU as well. Remove a redundant default for SWIOTLB as well. Signed-off-by: Roman Zippel Signed-off-by: Andi Kleen Cc: Andi Kleen Cc: Dave Jones Cc: Dave Airlie Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/x86_64/Kconfig | 5 ++--- drivers/char/agp/Kconfig | 3 +-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index 408d44a5975..7d3bc5ac5db 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig @@ -389,6 +389,7 @@ config GART_IOMMU bool "K8 GART IOMMU support" default y select SWIOTLB + select AGP depends on PCI help Support for hardware IOMMU in AMD's Opteron/Athlon64 Processors @@ -401,11 +402,9 @@ config GART_IOMMU northbridge and a software emulation used on other systems without hardware IOMMU. If unsure, say Y. -# need this always enabled with GART_IOMMU for the VIA workaround +# need this always selected by GART_IOMMU for the VIA workaround config SWIOTLB bool - default y - depends on GART_IOMMU config X86_MCE bool "Machine check support" if EMBEDDED diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig index 7c88c060a9e..46685a54077 100644 --- a/drivers/char/agp/Kconfig +++ b/drivers/char/agp/Kconfig @@ -1,7 +1,6 @@ config AGP - tristate "/dev/agpgart (AGP Support)" if !GART_IOMMU + tristate "/dev/agpgart (AGP Support)" depends on ALPHA || IA64 || PPC || X86 - default y if GART_IOMMU ---help--- AGP (Accelerated Graphics Port) is a bus system mainly used to connect graphics cards to the rest of the system. -- cgit v1.2.3 From 8a22dddb2a5b5834577afd9e25b5392218715611 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Fri, 23 Jun 2006 00:47:06 +0200 Subject: via-velocity: the link is not correctly detected when the device starts The patch fixes http://bugzilla.kernel.org/show_bug.cgi?id=6711 Signed-off-by: Roy Marples Signed-off-by: Francois Romieu --- drivers/net/via-velocity.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index 2eb6b5f9ba0..09e05fe40c3 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -248,6 +248,7 @@ static void velocity_free_rd_ring(struct velocity_info *vptr); static void velocity_free_tx_buf(struct velocity_info *vptr, struct velocity_td_info *); static int velocity_soft_reset(struct velocity_info *vptr); static void mii_init(struct velocity_info *vptr, u32 mii_status); +static u32 velocity_get_link(struct net_device *dev); static u32 velocity_get_opt_media_mode(struct velocity_info *vptr); static void velocity_print_link_status(struct velocity_info *vptr); static void safe_disable_mii_autopoll(struct mac_regs __iomem * regs); @@ -798,6 +799,9 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi if (ret < 0) goto err_iounmap; + if (velocity_get_link(dev)) + netif_carrier_off(dev); + velocity_print_info(vptr); pci_set_drvdata(pdev, dev); @@ -1653,8 +1657,10 @@ static void velocity_error(struct velocity_info *vptr, int status) if (linked) { vptr->mii_status &= ~VELOCITY_LINK_FAIL; + netif_carrier_on(vptr->dev); } else { vptr->mii_status |= VELOCITY_LINK_FAIL; + netif_carrier_off(vptr->dev); } velocity_print_link_status(vptr); -- cgit v1.2.3 From d955d90b90db4b3ac2a3e56d271f372c41fb00d6 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sat, 17 Jun 2006 18:57:39 +0100 Subject: [PATCH] IP27: Really set PCI64_ATTR_VIRTUAL, not PCI64_ATTR_PREC. IOC3's homegrown DMA mapping functions that are used to optimize things a little on IP27 set the wrong bit. Signed-off-by: Ralf Baechle Signed-off-by: Jeff Garzik --- drivers/net/ioc3-eth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c index ae71ed57c12..e76e6e7be0b 100644 --- a/drivers/net/ioc3-eth.c +++ b/drivers/net/ioc3-eth.c @@ -145,7 +145,7 @@ static inline struct sk_buff * ioc3_alloc_skb(unsigned long length, static inline unsigned long ioc3_map(void *ptr, unsigned long vdev) { #ifdef CONFIG_SGI_IP27 - vdev <<= 58; /* Shift to PCI64_ATTR_VIRTUAL */ + vdev <<= 57; /* Shift to PCI64_ATTR_VIRTUAL */ return vdev | (0xaUL << PCI64_ATTR_TARG_SHFT) | PCI64_ATTR_PREF | ((unsigned long)ptr & TO_PHYS_MASK); -- cgit v1.2.3 From 775637df0caccc204628ebacca2b07f35c88b96b Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Tue, 20 Jun 2006 11:50:23 +0200 Subject: [PATCH] AT91RM9200 Ethernet #1: Link poll For Ethernet PHYs that don't have an IRQ pin or boards that don't connect the IRQ pin to the processor, we enable a timer to poll the PHY's link state. Patch originally supplied by Eric Benard and Roman Kolesnikov. Signed-off-by: Andrew Victor Signed-off-by: Jeff Garzik --- drivers/net/arm/at91_ether.c | 61 +++++++++++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 18 deletions(-) diff --git a/drivers/net/arm/at91_ether.c b/drivers/net/arm/at91_ether.c index 5503dc8a66e..5b5095629a9 100644 --- a/drivers/net/arm/at91_ether.c +++ b/drivers/net/arm/at91_ether.c @@ -45,6 +45,9 @@ static struct net_device *at91_dev; static struct clk *ether_clk; +static struct timer_list check_timer; +#define LINK_POLL_INTERVAL (HZ) + /* ..................................................................... */ /* @@ -143,7 +146,7 @@ static void read_phy(unsigned char phy_addr, unsigned char address, unsigned int * MAC accordingly. * If no link or auto-negotiation is busy, then no changes are made. */ -static void update_linkspeed(struct net_device *dev) +static void update_linkspeed(struct net_device *dev, int silent) { struct at91_private *lp = (struct at91_private *) dev->priv; unsigned int bmsr, bmcr, lpa, mac_cfg; @@ -151,7 +154,8 @@ static void update_linkspeed(struct net_device *dev) if (!mii_link_ok(&lp->mii)) { /* no link */ netif_carrier_off(dev); - printk(KERN_INFO "%s: Link down.\n", dev->name); + if (!silent) + printk(KERN_INFO "%s: Link down.\n", dev->name); return; } @@ -186,7 +190,8 @@ static void update_linkspeed(struct net_device *dev) } at91_emac_write(AT91_EMAC_CFG, mac_cfg); - printk(KERN_INFO "%s: Link now %i-%s\n", dev->name, speed, (duplex == DUPLEX_FULL) ? "FullDuplex" : "HalfDuplex"); + if (!silent) + printk(KERN_INFO "%s: Link now %i-%s\n", dev->name, speed, (duplex == DUPLEX_FULL) ? "FullDuplex" : "HalfDuplex"); netif_carrier_on(dev); } @@ -226,7 +231,7 @@ static irqreturn_t at91ether_phy_interrupt(int irq, void *dev_id, struct pt_regs goto done; } - update_linkspeed(dev); + update_linkspeed(dev, 0); done: disable_mdi(); @@ -243,14 +248,17 @@ static void enable_phyirq(struct net_device *dev) unsigned int dsintr, irq_number; int status; - if (lp->phy_type == MII_RTL8201_ID) /* RTL8201 does not have an interrupt */ - return; - if (lp->phy_type == MII_DP83847_ID) /* DP83847 does not have an interrupt */ - return; - if (lp->phy_type == MII_AC101L_ID) /* AC101L interrupt not supported yet */ + irq_number = lp->board_data.phy_irq_pin; + if (!irq_number) { + /* + * PHY doesn't have an IRQ pin (RTL8201, DP83847, AC101L), + * or board does not have it connected. + */ + check_timer.expires = jiffies + LINK_POLL_INTERVAL; + add_timer(&check_timer); return; + } - irq_number = lp->board_data.phy_irq_pin; status = request_irq(irq_number, at91ether_phy_interrupt, 0, dev->name, dev); if (status) { printk(KERN_ERR "at91_ether: PHY IRQ %d request failed - status %d!\n", irq_number, status); @@ -292,12 +300,11 @@ static void disable_phyirq(struct net_device *dev) unsigned int dsintr; unsigned int irq_number; - if (lp->phy_type == MII_RTL8201_ID) /* RTL8201 does not have an interrupt */ - return; - if (lp->phy_type == MII_DP83847_ID) /* DP83847 does not have an interrupt */ - return; - if (lp->phy_type == MII_AC101L_ID) /* AC101L interrupt not supported yet */ + irq_number = lp->board_data.phy_irq_pin; + if (!irq_number) { + del_timer_sync(&check_timer); return; + } spin_lock_irq(&lp->lock); enable_mdi(); @@ -326,7 +333,6 @@ static void disable_phyirq(struct net_device *dev) disable_mdi(); spin_unlock_irq(&lp->lock); - irq_number = lp->board_data.phy_irq_pin; free_irq(irq_number, dev); /* Free interrupt handler */ } @@ -355,6 +361,18 @@ static void reset_phy(struct net_device *dev) } #endif +static void at91ether_check_link(unsigned long dev_id) +{ + struct net_device *dev = (struct net_device *) dev_id; + + enable_mdi(); + update_linkspeed(dev, 1); + disable_mdi(); + + check_timer.expires = jiffies + LINK_POLL_INTERVAL; + add_timer(&check_timer); +} + /* ......................... ADDRESS MANAGEMENT ........................ */ /* @@ -708,7 +726,7 @@ static int at91ether_open(struct net_device *dev) /* Determine current link speed */ spin_lock_irq(&lp->lock); enable_mdi(); - update_linkspeed(dev); + update_linkspeed(dev, 0); disable_mdi(); spin_unlock_irq(&lp->lock); @@ -992,11 +1010,18 @@ static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_add /* Determine current link speed */ spin_lock_irq(&lp->lock); enable_mdi(); - update_linkspeed(dev); + update_linkspeed(dev, 0); disable_mdi(); spin_unlock_irq(&lp->lock); netif_carrier_off(dev); /* will be enabled in open() */ + /* If board has no PHY IRQ, use a timer to poll the PHY */ + if (!lp->board_data.phy_irq_pin) { + init_timer(&check_timer); + check_timer.data = (unsigned long)dev; + check_timer.function = at91ether_check_link; + } + /* Display ethernet banner */ printk(KERN_INFO "%s: AT91 ethernet at 0x%08x int=%d %s%s (%02x:%02x:%02x:%02x:%02x:%02x)\n", dev->name, (uint) dev->base_addr, dev->irq, -- cgit v1.2.3 From ca5585ed248dc01ce918002ee9a9c9c41ae4f7c0 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Tue, 20 Jun 2006 11:59:05 +0200 Subject: [PATCH] AT91RM9200 Ethernet #2: MII interface Adds support for the MII ioctls via generic_mii_ioctl(). Patch from Brian Stafford. Set the mii.phy_id to the detected PHY address, otherwise ethtool cannot access PHYs other than 0. Patch from Roman Kolesnikov. Signed-off-by: Andrew Victor Signed-off-by: Jeff Garzik --- drivers/net/arm/at91_ether.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/net/arm/at91_ether.c b/drivers/net/arm/at91_ether.c index 5b5095629a9..cc773662d9f 100644 --- a/drivers/net/arm/at91_ether.c +++ b/drivers/net/arm/at91_ether.c @@ -660,6 +660,22 @@ static struct ethtool_ops at91ether_ethtool_ops = { .get_link = ethtool_op_get_link, }; +static int at91ether_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + struct at91_private *lp = (struct at91_private *) dev->priv; + int res; + + if (!netif_running(dev)) + return -EINVAL; + + spin_lock_irq(&lp->lock); + enable_mdi(); + res = generic_mii_ioctl(&lp->mii, if_mii(rq), cmd, NULL); + disable_mdi(); + spin_unlock_irq(&lp->lock); + + return res; +} /* ................................ MAC ................................ */ @@ -963,6 +979,7 @@ static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_add dev->set_multicast_list = at91ether_set_rx_mode; dev->set_mac_address = set_mac_address; dev->ethtool_ops = &at91ether_ethtool_ops; + dev->do_ioctl = at91ether_ioctl; SET_NETDEV_DEV(dev, &pdev->dev); @@ -993,6 +1010,9 @@ static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_add lp->mii.dev = dev; /* Support for ethtool */ lp->mii.mdio_read = mdio_read; lp->mii.mdio_write = mdio_write; + lp->mii.phy_id = phy_address; + lp->mii.phy_id_mask = 0x1f; + lp->mii.reg_num_mask = 0x1f; lp->phy_type = phy_type; /* Type of PHY connected */ lp->phy_address = phy_address; /* MDI address of PHY */ -- cgit v1.2.3 From 427d269f17fd02d192e9ae3bd93bdc07790fa02c Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Tue, 20 Jun 2006 12:10:57 +0200 Subject: [PATCH] AT91RM9200 Ethernet #3: Cleanup Moved global ether_clk variable into controller data structure. Patch from David Brownell. Davicom 9161 PHY was being incorrectly displayed as "9196". Patch from Brian Stafford. clk_get() doesn't return NULL on error, so the return value needs to be tested with IS_ERR(). Whitespace cleanup. Signed-off-by: Andrew Victor Signed-off-by: Jeff Garzik --- drivers/net/arm/at91_ether.c | 29 +++++++++++++++-------------- drivers/net/arm/at91_ether.h | 1 + 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/drivers/net/arm/at91_ether.c b/drivers/net/arm/at91_ether.c index cc773662d9f..d081241f613 100644 --- a/drivers/net/arm/at91_ether.c +++ b/drivers/net/arm/at91_ether.c @@ -43,7 +43,6 @@ #define DRV_VERSION "1.0" static struct net_device *at91_dev; -static struct clk *ether_clk; static struct timer_list check_timer; #define LINK_POLL_INTERVAL (HZ) @@ -519,7 +518,7 @@ static int hash_get_index(__u8 *addr) hash_index |= (bitval << j); } - return hash_index; + return hash_index; } /* @@ -575,10 +574,8 @@ static void at91ether_set_rx_mode(struct net_device *dev) at91_emac_write(AT91_EMAC_CFG, cfg); } - /* ......................... ETHTOOL SUPPORT ........................... */ - static int mdio_read(struct net_device *dev, int phy_id, int location) { unsigned int value; @@ -719,10 +716,10 @@ static int at91ether_open(struct net_device *dev) struct at91_private *lp = (struct at91_private *) dev->priv; unsigned long ctl; - if (!is_valid_ether_addr(dev->dev_addr)) - return -EADDRNOTAVAIL; + if (!is_valid_ether_addr(dev->dev_addr)) + return -EADDRNOTAVAIL; - clk_enable(ether_clk); /* Re-enable Peripheral clock */ + clk_enable(lp->ether_clk); /* Re-enable Peripheral clock */ /* Clear internal statistics */ ctl = at91_emac_read(AT91_EMAC_CTL); @@ -756,6 +753,7 @@ static int at91ether_open(struct net_device *dev) */ static int at91ether_close(struct net_device *dev) { + struct at91_private *lp = (struct at91_private *) dev->priv; unsigned long ctl; /* Disable Receiver and Transmitter */ @@ -772,7 +770,7 @@ static int at91ether_close(struct net_device *dev) netif_stop_queue(dev); - clk_disable(ether_clk); /* Disable Peripheral clock */ + clk_disable(lp->ether_clk); /* Disable Peripheral clock */ return 0; } @@ -904,7 +902,7 @@ static irqreturn_t at91ether_interrupt(int irq, void *dev_id, struct pt_regs *re if (intstatus & AT91_EMAC_RCOM) /* Receive complete */ at91ether_rx(dev); - if (intstatus & AT91_EMAC_TCOM) { /* Transmit complete */ + if (intstatus & AT91_EMAC_TCOM) { /* Transmit complete */ /* The TCOM bit is set even if the transmission failed. */ if (intstatus & (AT91_EMAC_TUND | AT91_EMAC_RTRY)) lp->stats.tx_errors += 1; @@ -933,7 +931,8 @@ static irqreturn_t at91ether_interrupt(int irq, void *dev_id, struct pt_regs *re /* * Initialize the ethernet interface */ -static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_address, struct platform_device *pdev) +static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_address, + struct platform_device *pdev, struct clk *ether_clk) { struct at91_eth_data *board_data = pdev->dev.platform_data; struct net_device *dev; @@ -967,6 +966,7 @@ static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_add return -ENOMEM; } lp->board_data = *board_data; + lp->ether_clk = ether_clk; platform_set_drvdata(pdev, dev); spin_lock_init(&lp->lock); @@ -1050,7 +1050,7 @@ static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_add dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); if ((phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) - printk(KERN_INFO "%s: Davicom 9196 PHY %s\n", dev->name, (lp->phy_media == PORT_FIBRE) ? "(Fiber)" : "(Copper)"); + printk(KERN_INFO "%s: Davicom 9161 PHY %s\n", dev->name, (lp->phy_media == PORT_FIBRE) ? "(Fiber)" : "(Copper)"); else if (phy_type == MII_LXT971A_ID) printk(KERN_INFO "%s: Intel LXT971A PHY\n", dev->name); else if (phy_type == MII_RTL8201_ID) @@ -1076,9 +1076,10 @@ static int __init at91ether_probe(struct platform_device *pdev) int detected = -1; unsigned long phy_id; unsigned short phy_address = 0; + struct clk *ether_clk; ether_clk = clk_get(&pdev->dev, "ether_clk"); - if (!ether_clk) { + if (IS_ERR(ether_clk)) { printk(KERN_ERR "at91_ether: no clock defined\n"); return -ENODEV; } @@ -1101,7 +1102,7 @@ static int __init at91ether_probe(struct platform_device *pdev) case MII_DP83847_ID: /* National Semiconductor DP83847: */ case MII_AC101L_ID: /* Altima AC101L: PHY_ID1 = 0x22, PHY_ID2 = 0x5520 */ case MII_KS8721_ID: /* Micrel KS8721: PHY_ID1 = 0x22, PHY_ID2 = 0x1610 */ - detected = at91ether_setup(phy_id, phy_address, pdev); + detected = at91ether_setup(phy_id, phy_address, pdev, ether_clk); break; } @@ -1120,7 +1121,7 @@ static int __devexit at91ether_remove(struct platform_device *pdev) unregister_netdev(at91_dev); free_irq(at91_dev->irq, at91_dev); dma_free_coherent(NULL, sizeof(struct recv_desc_bufs), lp->dlist, (dma_addr_t)lp->dlist_phys); - clk_put(ether_clk); + clk_put(lp->ether_clk); free_netdev(at91_dev); at91_dev = NULL; diff --git a/drivers/net/arm/at91_ether.h b/drivers/net/arm/at91_ether.h index 9885735c9c8..d1e72e02be3 100644 --- a/drivers/net/arm/at91_ether.h +++ b/drivers/net/arm/at91_ether.h @@ -80,6 +80,7 @@ struct at91_private struct net_device_stats stats; struct mii_if_info mii; /* ethtool support */ struct at91_eth_data board_data; /* board-specific configuration */ + struct clk *ether_clk; /* clock */ /* PHY */ unsigned long phy_type; /* type of PHY (PHY_ID) */ -- cgit v1.2.3 From 00e5edcbfdb7030f6cbb8d5d89fdc2848133a182 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Tue, 20 Jun 2006 12:19:13 +0200 Subject: [PATCH] AT91RM9200 Ethernet #4: Suspend/Resume Adds power-management (suspend/resume) support to the AT91RM9200 Ethernet driver. Patch from David Brownell. Signed-off-by: Andrew Victor Signed-off-by: Jeff Garzik --- drivers/net/arm/at91_ether.c | 46 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/drivers/net/arm/at91_ether.c b/drivers/net/arm/at91_ether.c index d081241f613..613005a0285 100644 --- a/drivers/net/arm/at91_ether.c +++ b/drivers/net/arm/at91_ether.c @@ -1128,10 +1128,54 @@ static int __devexit at91ether_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM + +static int at91ether_suspend(struct platform_device *pdev, pm_message_t mesg) +{ + struct at91_private *lp = (struct at91_private *) at91_dev->priv; + struct net_device *net_dev = platform_get_drvdata(pdev); + int phy_irq = lp->board_data.phy_irq_pin; + + if (netif_running(net_dev)) { + if (phy_irq) + disable_irq(phy_irq); + + netif_stop_queue(net_dev); + netif_device_detach(net_dev); + + clk_disable(lp->ether_clk); + } + return 0; +} + +static int at91ether_resume(struct platform_device *pdev) +{ + struct at91_private *lp = (struct at91_private *) at91_dev->priv; + struct net_device *net_dev = platform_get_drvdata(pdev); + int phy_irq = lp->board_data.phy_irq_pin; + + if (netif_running(net_dev)) { + clk_enable(lp->ether_clk); + + netif_device_attach(net_dev); + netif_start_queue(net_dev); + + if (phy_irq) + enable_irq(phy_irq); + } + return 0; +} + +#else +#define at91ether_suspend NULL +#define at91ether_resume NULL +#endif + static struct platform_driver at91ether_driver = { .probe = at91ether_probe, .remove = __devexit_p(at91ether_remove), - /* FIXME: support suspend and resume */ + .suspend = at91ether_suspend, + .resume = at91ether_resume, .driver = { .name = DRV_NAME, .owner = THIS_MODULE, -- cgit v1.2.3 From fe7fa31aa0749d7d247d21e1880f0c5aea15b158 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Thu, 22 Jun 2006 23:05:36 -0400 Subject: [libata] ahci: Add NVIDIA PCI IDs. Based on a patch by Andrew Chew @ NVIDIA. Signed-off-by: Jeff Garzik --- drivers/scsi/ahci.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index e261b37c2e4..82ecdef0c48 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -285,6 +285,7 @@ static const struct ata_port_info ahci_port_info[] = { }; static const struct pci_device_id ahci_pci_tbl[] = { + /* Intel */ { PCI_VENDOR_ID_INTEL, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_ahci }, /* ICH6 */ { PCI_VENDOR_ID_INTEL, 0x2653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, @@ -315,16 +316,33 @@ static const struct pci_device_id ahci_pci_tbl[] = { board_ahci }, /* ICH8M */ { PCI_VENDOR_ID_INTEL, 0x282a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_ahci }, /* ICH8M */ + + /* JMicron */ { 0x197b, 0x2360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_ahci }, /* JMicron JMB360 */ { 0x197b, 0x2363, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_ahci }, /* JMicron JMB363 */ + + /* ATI */ { PCI_VENDOR_ID_ATI, 0x4380, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_ahci }, /* ATI SB600 non-raid */ { PCI_VENDOR_ID_ATI, 0x4381, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_ahci }, /* ATI SB600 raid */ + + /* VIA */ { PCI_VENDOR_ID_VIA, 0x3349, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_ahci_vt8251 }, /* VIA VT8251 */ + + /* NVIDIA */ + { PCI_VENDOR_ID_NVIDIA, 0x044c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_ahci }, /* MCP65 */ + { PCI_VENDOR_ID_NVIDIA, 0x044d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_ahci }, /* MCP65 */ + { PCI_VENDOR_ID_NVIDIA, 0x044e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_ahci }, /* MCP65 */ + { PCI_VENDOR_ID_NVIDIA, 0x044f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_ahci }, /* MCP65 */ + { } /* terminate list */ }; -- cgit v1.2.3 From c57c064994f1544a5ed2e9b319ebd0bc087ea540 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Thu, 22 Jun 2006 23:12:24 -0400 Subject: [libata] sata_nv: add PCI IDs Based on a patch contributed by Andrew Chew @ NVIDIA. Signed-off-by: Jeff Garzik --- drivers/scsi/sata_nv.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c index be8650f1702..d18e7e0932e 100644 --- a/drivers/scsi/sata_nv.c +++ b/drivers/scsi/sata_nv.c @@ -135,6 +135,10 @@ static const struct pci_device_id nv_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC }, { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC }, + { PCI_VENDOR_ID_NVIDIA, 0x045c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC }, + { PCI_VENDOR_ID_NVIDIA, 0x045d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC }, + { PCI_VENDOR_ID_NVIDIA, 0x045e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC }, + { PCI_VENDOR_ID_NVIDIA, 0x045f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC }, { PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE<<8, 0xffff00, GENERIC }, -- cgit v1.2.3 From 47b9c3b1e6afa3c40e3ac1822cd13946567b5955 Mon Sep 17 00:00:00 2001 From: Gary Zambrano Date: Tue, 20 Jun 2006 15:34:15 -0700 Subject: [PATCH] b44: fix manual speed/duplex/autoneg settings Fixes for speed/duplex/autoneg settings and driver settings info. This is a redo of a previous patch thanks to feedback from Jeff Garzik. Signed-off-by: Gary Zambrano Signed-off-by: Jeff Garzik --- drivers/net/b44.c | 44 ++++++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/drivers/net/b44.c b/drivers/net/b44.c index d8233e0b789..41b1618573c 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -1620,8 +1620,6 @@ static int b44_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct b44 *bp = netdev_priv(dev); - if (!netif_running(dev)) - return -EAGAIN; cmd->supported = (SUPPORTED_Autoneg); cmd->supported |= (SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | @@ -1649,6 +1647,12 @@ static int b44_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) XCVR_INTERNAL : XCVR_EXTERNAL; cmd->autoneg = (bp->flags & B44_FLAG_FORCE_LINK) ? AUTONEG_DISABLE : AUTONEG_ENABLE; + if (cmd->autoneg == AUTONEG_ENABLE) + cmd->advertising |= ADVERTISED_Autoneg; + if (!netif_running(dev)){ + cmd->speed = 0; + cmd->duplex = 0xff; + } cmd->maxtxpkt = 0; cmd->maxrxpkt = 0; return 0; @@ -1658,9 +1662,6 @@ static int b44_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct b44 *bp = netdev_priv(dev); - if (!netif_running(dev)) - return -EAGAIN; - /* We do not support gigabit. */ if (cmd->autoneg == AUTONEG_ENABLE) { if (cmd->advertising & @@ -1677,28 +1678,39 @@ static int b44_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) spin_lock_irq(&bp->lock); if (cmd->autoneg == AUTONEG_ENABLE) { - bp->flags &= ~B44_FLAG_FORCE_LINK; - bp->flags &= ~(B44_FLAG_ADV_10HALF | + bp->flags &= ~(B44_FLAG_FORCE_LINK | + B44_FLAG_100_BASE_T | + B44_FLAG_FULL_DUPLEX | + B44_FLAG_ADV_10HALF | B44_FLAG_ADV_10FULL | B44_FLAG_ADV_100HALF | B44_FLAG_ADV_100FULL); - if (cmd->advertising & ADVERTISE_10HALF) - bp->flags |= B44_FLAG_ADV_10HALF; - if (cmd->advertising & ADVERTISE_10FULL) - bp->flags |= B44_FLAG_ADV_10FULL; - if (cmd->advertising & ADVERTISE_100HALF) - bp->flags |= B44_FLAG_ADV_100HALF; - if (cmd->advertising & ADVERTISE_100FULL) - bp->flags |= B44_FLAG_ADV_100FULL; + if (cmd->advertising == 0) { + bp->flags |= (B44_FLAG_ADV_10HALF | + B44_FLAG_ADV_10FULL | + B44_FLAG_ADV_100HALF | + B44_FLAG_ADV_100FULL); + } else { + if (cmd->advertising & ADVERTISED_10baseT_Half) + bp->flags |= B44_FLAG_ADV_10HALF; + if (cmd->advertising & ADVERTISED_10baseT_Full) + bp->flags |= B44_FLAG_ADV_10FULL; + if (cmd->advertising & ADVERTISED_100baseT_Half) + bp->flags |= B44_FLAG_ADV_100HALF; + if (cmd->advertising & ADVERTISED_100baseT_Full) + bp->flags |= B44_FLAG_ADV_100FULL; + } } else { bp->flags |= B44_FLAG_FORCE_LINK; + bp->flags &= ~(B44_FLAG_100_BASE_T | B44_FLAG_FULL_DUPLEX); if (cmd->speed == SPEED_100) bp->flags |= B44_FLAG_100_BASE_T; if (cmd->duplex == DUPLEX_FULL) bp->flags |= B44_FLAG_FULL_DUPLEX; } - b44_setup_phy(bp); + if (netif_running(dev)) + b44_setup_phy(bp); spin_unlock_irq(&bp->lock); -- cgit v1.2.3 From 52cafd965507b7a7bb962486539f6d7422552692 Mon Sep 17 00:00:00 2001 From: Gary Zambrano Date: Tue, 20 Jun 2006 15:34:23 -0700 Subject: [PATCH] b44: add wol Adds wol to the driver. This is a redo of a previous patch thanks to feedback from Francois Romieu. Signed-off-by Gary Zambrano Signed-off-by: Jeff Garzik --- drivers/net/b44.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/net/b44.h | 4 +++ 2 files changed, 80 insertions(+) diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 41b1618573c..73ca729e4cd 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -1450,6 +1450,41 @@ static void b44_poll_controller(struct net_device *dev) } #endif + +static void b44_setup_wol(struct b44 *bp) +{ + u32 val; + u16 pmval; + + bw32(bp, B44_RXCONFIG, RXCONFIG_ALLMULTI); + + if (bp->flags & B44_FLAG_B0_ANDLATER) { + + bw32(bp, B44_WKUP_LEN, WKUP_LEN_DISABLE); + + val = bp->dev->dev_addr[2] << 24 | + bp->dev->dev_addr[3] << 16 | + bp->dev->dev_addr[4] << 8 | + bp->dev->dev_addr[5]; + bw32(bp, B44_ADDR_LO, val); + + val = bp->dev->dev_addr[0] << 8 | + bp->dev->dev_addr[1]; + bw32(bp, B44_ADDR_HI, val); + + val = br32(bp, B44_DEVCTRL); + bw32(bp, B44_DEVCTRL, val | DEVCTRL_MPM | DEVCTRL_PFE); + + } + + val = br32(bp, B44_SBTMSLOW); + bw32(bp, B44_SBTMSLOW, val | SBTMSLOW_PE); + + pci_read_config_word(bp->pdev, SSB_PMCSR, &pmval); + pci_write_config_word(bp->pdev, SSB_PMCSR, pmval | SSB_PE); + +} + static int b44_close(struct net_device *dev) { struct b44 *bp = netdev_priv(dev); @@ -1475,6 +1510,11 @@ static int b44_close(struct net_device *dev) netif_poll_enable(dev); + if (bp->flags & B44_FLAG_WOL_ENABLE) { + b44_init_hw(bp); + b44_setup_wol(bp); + } + b44_free_consistent(bp); return 0; @@ -1831,12 +1871,40 @@ static void b44_get_ethtool_stats(struct net_device *dev, spin_unlock_irq(&bp->lock); } +static void b44_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) +{ + struct b44 *bp = netdev_priv(dev); + + wol->supported = WAKE_MAGIC; + if (bp->flags & B44_FLAG_WOL_ENABLE) + wol->wolopts = WAKE_MAGIC; + else + wol->wolopts = 0; + memset(&wol->sopass, 0, sizeof(wol->sopass)); +} + +static int b44_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) +{ + struct b44 *bp = netdev_priv(dev); + + spin_lock_irq(&bp->lock); + if (wol->wolopts & WAKE_MAGIC) + bp->flags |= B44_FLAG_WOL_ENABLE; + else + bp->flags &= ~B44_FLAG_WOL_ENABLE; + spin_unlock_irq(&bp->lock); + + return 0; +} + static struct ethtool_ops b44_ethtool_ops = { .get_drvinfo = b44_get_drvinfo, .get_settings = b44_get_settings, .set_settings = b44_set_settings, .nway_reset = b44_nway_reset, .get_link = ethtool_op_get_link, + .get_wol = b44_get_wol, + .set_wol = b44_set_wol, .get_ringparam = b44_get_ringparam, .set_ringparam = b44_set_ringparam, .get_pauseparam = b44_get_pauseparam, @@ -1915,6 +1983,10 @@ static int __devinit b44_get_invariants(struct b44 *bp) /* XXX - really required? bp->flags |= B44_FLAG_BUGGY_TXPTR; */ + + if (ssb_get_core_rev(bp) >= 7) + bp->flags |= B44_FLAG_B0_ANDLATER; + out: return err; } @@ -2115,6 +2187,10 @@ static int b44_suspend(struct pci_dev *pdev, pm_message_t state) spin_unlock_irq(&bp->lock); free_irq(dev->irq, dev); + if (bp->flags & B44_FLAG_WOL_ENABLE) { + b44_init_hw(bp); + b44_setup_wol(bp); + } pci_disable_device(pdev); return 0; } diff --git a/drivers/net/b44.h b/drivers/net/b44.h index b178662978f..1f47777b848 100644 --- a/drivers/net/b44.h +++ b/drivers/net/b44.h @@ -264,6 +264,8 @@ #define SBIDHIGH_VC_SHIFT 16 /* SSB PCI config space registers. */ +#define SSB_PMCSR 0x44 +#define SSB_PE 0x100 #define SSB_BAR0_WIN 0x80 #define SSB_BAR1_WIN 0x84 #define SSB_SPROM_CONTROL 0x88 @@ -420,6 +422,7 @@ struct b44 { u32 dma_offset; u32 flags; +#define B44_FLAG_B0_ANDLATER 0x00000001 #define B44_FLAG_BUGGY_TXPTR 0x00000002 #define B44_FLAG_REORDER_BUG 0x00000004 #define B44_FLAG_PAUSE_AUTO 0x00008000 @@ -435,6 +438,7 @@ struct b44 { #define B44_FLAG_INTERNAL_PHY 0x10000000 #define B44_FLAG_RX_RING_HACK 0x20000000 #define B44_FLAG_TX_RING_HACK 0x40000000 +#define B44_FLAG_WOL_ENABLE 0x80000000 u32 rx_offset; -- cgit v1.2.3 From 00e8b3aa1cfd7577fd4019a24f7c3980506f83f3 Mon Sep 17 00:00:00 2001 From: Gary Zambrano Date: Tue, 20 Jun 2006 15:34:26 -0700 Subject: [PATCH] b44: add parameter This patch adds a parameter to init_hw() to not completely initialize the nic for wol. Signed-off-by: Gary Zambrano Signed-off-by: Jeff Garzik --- drivers/net/b44.c | 49 ++++++++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 73ca729e4cd..12fc67a740e 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -101,7 +101,7 @@ MODULE_DEVICE_TABLE(pci, b44_pci_tbl); static void b44_halt(struct b44 *); static void b44_init_rings(struct b44 *); -static void b44_init_hw(struct b44 *); +static void b44_init_hw(struct b44 *, int); static int dma_desc_align_mask; static int dma_desc_sync_size; @@ -873,7 +873,7 @@ static int b44_poll(struct net_device *netdev, int *budget) spin_lock_irq(&bp->lock); b44_halt(bp); b44_init_rings(bp); - b44_init_hw(bp); + b44_init_hw(bp, 1); netif_wake_queue(bp->dev); spin_unlock_irq(&bp->lock); done = 1; @@ -942,7 +942,7 @@ static void b44_tx_timeout(struct net_device *dev) b44_halt(bp); b44_init_rings(bp); - b44_init_hw(bp); + b44_init_hw(bp, 1); spin_unlock_irq(&bp->lock); @@ -1059,7 +1059,7 @@ static int b44_change_mtu(struct net_device *dev, int new_mtu) b44_halt(bp); dev->mtu = new_mtu; b44_init_rings(bp); - b44_init_hw(bp); + b44_init_hw(bp, 1); spin_unlock_irq(&bp->lock); b44_enable_ints(bp); @@ -1356,13 +1356,15 @@ static int b44_set_mac_addr(struct net_device *dev, void *p) * packet processing. Invoked with bp->lock held. */ static void __b44_set_rx_mode(struct net_device *); -static void b44_init_hw(struct b44 *bp) +static void b44_init_hw(struct b44 *bp, int full_reset) { u32 val; b44_chip_reset(bp); - b44_phy_reset(bp); - b44_setup_phy(bp); + if (full_reset) { + b44_phy_reset(bp); + b44_setup_phy(bp); + } /* Enable CRC32, set proper LED modes and power on PHY */ bw32(bp, B44_MAC_CTRL, MAC_CTRL_CRC32_ENAB | MAC_CTRL_PHY_LEDCTRL); @@ -1376,16 +1378,21 @@ static void b44_init_hw(struct b44 *bp) bw32(bp, B44_TXMAXLEN, bp->dev->mtu + ETH_HLEN + 8 + RX_HEADER_LEN); bw32(bp, B44_TX_WMARK, 56); /* XXX magic */ - bw32(bp, B44_DMATX_CTRL, DMATX_CTRL_ENABLE); - bw32(bp, B44_DMATX_ADDR, bp->tx_ring_dma + bp->dma_offset); - bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE | - (bp->rx_offset << DMARX_CTRL_ROSHIFT))); - bw32(bp, B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset); + if (full_reset) { + bw32(bp, B44_DMATX_CTRL, DMATX_CTRL_ENABLE); + bw32(bp, B44_DMATX_ADDR, bp->tx_ring_dma + bp->dma_offset); + bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE | + (bp->rx_offset << DMARX_CTRL_ROSHIFT))); + bw32(bp, B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset); - bw32(bp, B44_DMARX_PTR, bp->rx_pending); - bp->rx_prod = bp->rx_pending; + bw32(bp, B44_DMARX_PTR, bp->rx_pending); + bp->rx_prod = bp->rx_pending; - bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ); + bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ); + } else { + bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE | + (bp->rx_offset << DMARX_CTRL_ROSHIFT))); + } val = br32(bp, B44_ENET_CTRL); bw32(bp, B44_ENET_CTRL, (val | ENET_CTRL_ENABLE)); @@ -1401,7 +1408,7 @@ static int b44_open(struct net_device *dev) goto out; b44_init_rings(bp); - b44_init_hw(bp); + b44_init_hw(bp, 1); b44_check_phy(bp); @@ -1511,7 +1518,7 @@ static int b44_close(struct net_device *dev) netif_poll_enable(dev); if (bp->flags & B44_FLAG_WOL_ENABLE) { - b44_init_hw(bp); + b44_init_hw(bp, 0); b44_setup_wol(bp); } @@ -1786,7 +1793,7 @@ static int b44_set_ringparam(struct net_device *dev, b44_halt(bp); b44_init_rings(bp); - b44_init_hw(bp); + b44_init_hw(bp, 1); netif_wake_queue(bp->dev); spin_unlock_irq(&bp->lock); @@ -1829,7 +1836,7 @@ static int b44_set_pauseparam(struct net_device *dev, if (bp->flags & B44_FLAG_PAUSE_AUTO) { b44_halt(bp); b44_init_rings(bp); - b44_init_hw(bp); + b44_init_hw(bp, 1); } else { __b44_set_flow_ctrl(bp, bp->flags); } @@ -2188,7 +2195,7 @@ static int b44_suspend(struct pci_dev *pdev, pm_message_t state) free_irq(dev->irq, dev); if (bp->flags & B44_FLAG_WOL_ENABLE) { - b44_init_hw(bp); + b44_init_hw(bp, 0); b44_setup_wol(bp); } pci_disable_device(pdev); @@ -2213,7 +2220,7 @@ static int b44_resume(struct pci_dev *pdev) spin_lock_irq(&bp->lock); b44_init_rings(bp); - b44_init_hw(bp); + b44_init_hw(bp, 1); netif_device_attach(bp->dev); spin_unlock_irq(&bp->lock); -- cgit v1.2.3 From 725ad800b73a71fe91bfd8859f928852de688ea0 Mon Sep 17 00:00:00 2001 From: Gary Zambrano Date: Tue, 20 Jun 2006 15:34:36 -0700 Subject: [PATCH] b44: add wol for old nic This patch adds wol support for the older 440x nics that use pattern matching. This patch is a redo thanks to feedback from Michael Chan and Francois Romieu. Signed-off-by: Gary Zambrano Signed-off-by: Jeff Garzik --- drivers/net/b44.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++++- drivers/net/b44.h | 3 ++ 2 files changed, 112 insertions(+), 1 deletion(-) diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 12fc67a740e..98c06752f7e 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -75,6 +75,15 @@ /* minimum number of free TX descriptors required to wake up TX process */ #define B44_TX_WAKEUP_THRESH (B44_TX_RING_SIZE / 4) +/* b44 internal pattern match filter info */ +#define B44_PATTERN_BASE 0x400 +#define B44_PATTERN_SIZE 0x80 +#define B44_PMASK_BASE 0x600 +#define B44_PMASK_SIZE 0x10 +#define B44_MAX_PATTERNS 16 +#define B44_ETHIPV6UDP_HLEN 62 +#define B44_ETHIPV4UDP_HLEN 42 + static char version[] __devinitdata = DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; @@ -1457,6 +1466,103 @@ static void b44_poll_controller(struct net_device *dev) } #endif +static void bwfilter_table(struct b44 *bp, u8 *pp, u32 bytes, u32 table_offset) +{ + u32 i; + u32 *pattern = (u32 *) pp; + + for (i = 0; i < bytes; i += sizeof(u32)) { + bw32(bp, B44_FILT_ADDR, table_offset + i); + bw32(bp, B44_FILT_DATA, pattern[i / sizeof(u32)]); + } +} + +static int b44_magic_pattern(u8 *macaddr, u8 *ppattern, u8 *pmask, int offset) +{ + int magicsync = 6; + int k, j, len = offset; + int ethaddr_bytes = ETH_ALEN; + + memset(ppattern + offset, 0xff, magicsync); + for (j = 0; j < magicsync; j++) + set_bit(len++, (unsigned long *) pmask); + + for (j = 0; j < B44_MAX_PATTERNS; j++) { + if ((B44_PATTERN_SIZE - len) >= ETH_ALEN) + ethaddr_bytes = ETH_ALEN; + else + ethaddr_bytes = B44_PATTERN_SIZE - len; + if (ethaddr_bytes <=0) + break; + for (k = 0; k< ethaddr_bytes; k++) { + ppattern[offset + magicsync + + (j * ETH_ALEN) + k] = macaddr[k]; + len++; + set_bit(len, (unsigned long *) pmask); + } + } + return len - 1; +} + +/* Setup magic packet patterns in the b44 WOL + * pattern matching filter. + */ +static void b44_setup_pseudo_magicp(struct b44 *bp) +{ + + u32 val; + int plen0, plen1, plen2; + u8 *pwol_pattern; + u8 pwol_mask[B44_PMASK_SIZE]; + + pwol_pattern = kmalloc(B44_PATTERN_SIZE, GFP_KERNEL); + if (!pwol_pattern) { + printk(KERN_ERR PFX "Memory not available for WOL\n"); + return; + } + + /* Ipv4 magic packet pattern - pattern 0.*/ + memset(pwol_pattern, 0, B44_PATTERN_SIZE); + memset(pwol_mask, 0, B44_PMASK_SIZE); + plen0 = b44_magic_pattern(bp->dev->dev_addr, pwol_pattern, pwol_mask, + B44_ETHIPV4UDP_HLEN); + + bwfilter_table(bp, pwol_pattern, B44_PATTERN_SIZE, B44_PATTERN_BASE); + bwfilter_table(bp, pwol_mask, B44_PMASK_SIZE, B44_PMASK_BASE); + + /* Raw ethernet II magic packet pattern - pattern 1 */ + memset(pwol_pattern, 0, B44_PATTERN_SIZE); + memset(pwol_mask, 0, B44_PMASK_SIZE); + plen1 = b44_magic_pattern(bp->dev->dev_addr, pwol_pattern, pwol_mask, + ETH_HLEN); + + bwfilter_table(bp, pwol_pattern, B44_PATTERN_SIZE, + B44_PATTERN_BASE + B44_PATTERN_SIZE); + bwfilter_table(bp, pwol_mask, B44_PMASK_SIZE, + B44_PMASK_BASE + B44_PMASK_SIZE); + + /* Ipv6 magic packet pattern - pattern 2 */ + memset(pwol_pattern, 0, B44_PATTERN_SIZE); + memset(pwol_mask, 0, B44_PMASK_SIZE); + plen2 = b44_magic_pattern(bp->dev->dev_addr, pwol_pattern, pwol_mask, + B44_ETHIPV6UDP_HLEN); + + bwfilter_table(bp, pwol_pattern, B44_PATTERN_SIZE, + B44_PATTERN_BASE + B44_PATTERN_SIZE + B44_PATTERN_SIZE); + bwfilter_table(bp, pwol_mask, B44_PMASK_SIZE, + B44_PMASK_BASE + B44_PMASK_SIZE + B44_PMASK_SIZE); + + kfree(pwol_pattern); + + /* set these pattern's lengths: one less than each real length */ + val = plen0 | (plen1 << 8) | (plen2 << 16) | WKUP_LEN_ENABLE_THREE; + bw32(bp, B44_WKUP_LEN, val); + + /* enable wakeup pattern matching */ + val = br32(bp, B44_DEVCTRL); + bw32(bp, B44_DEVCTRL, val | DEVCTRL_PFE); + +} static void b44_setup_wol(struct b44 *bp) { @@ -1482,7 +1588,9 @@ static void b44_setup_wol(struct b44 *bp) val = br32(bp, B44_DEVCTRL); bw32(bp, B44_DEVCTRL, val | DEVCTRL_MPM | DEVCTRL_PFE); - } + } else { + b44_setup_pseudo_magicp(bp); + } val = br32(bp, B44_SBTMSLOW); bw32(bp, B44_SBTMSLOW, val | SBTMSLOW_PE); diff --git a/drivers/net/b44.h b/drivers/net/b44.h index 1f47777b848..4944507fad2 100644 --- a/drivers/net/b44.h +++ b/drivers/net/b44.h @@ -24,6 +24,9 @@ #define WKUP_LEN_P3_MASK 0x7f000000 /* Pattern 3 */ #define WKUP_LEN_P3_SHIFT 24 #define WKUP_LEN_D3 0x80000000 +#define WKUP_LEN_DISABLE 0x80808080 +#define WKUP_LEN_ENABLE_TWO 0x80800000 +#define WKUP_LEN_ENABLE_THREE 0x80000000 #define B44_ISTAT 0x0020UL /* Interrupt Status */ #define ISTAT_LS 0x00000020 /* Link Change (B0 only) */ #define ISTAT_PME 0x00000040 /* Power Management Event */ -- cgit v1.2.3 From 4d1dabdb52ee49f24cf874b6af2cd2c9efd9444a Mon Sep 17 00:00:00 2001 From: Gary Zambrano Date: Tue, 20 Jun 2006 15:34:40 -0700 Subject: [PATCH] b44: update version to 1.01 Update the driver version to 1.01 Signed-off-by: Gary Zambrano Signed-off-by: Jeff Garzik --- drivers/net/b44.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 98c06752f7e..a7e4ba5a580 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -29,8 +29,8 @@ #define DRV_MODULE_NAME "b44" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "1.00" -#define DRV_MODULE_RELDATE "Apr 7, 2006" +#define DRV_MODULE_VERSION "1.01" +#define DRV_MODULE_RELDATE "Jun 16, 2006" #define B44_DEF_MSG_ENABLE \ (NETIF_MSG_DRV | \ -- cgit v1.2.3 From fc13dcae24bfd877aeff07774c035b2b896e05ca Mon Sep 17 00:00:00 2001 From: Gary Zambrano Date: Tue, 20 Jun 2006 15:34:46 -0700 Subject: [PATCH] b44: update b44 Kconfig entry Deleted "EXPERIMENTAL" from b44 entry in Kconfig. Signed-off-by: Gary Zambrano Signed-off-by: Jeff Garzik --- drivers/net/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 0c6b45a11d1..67e812642c8 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1376,8 +1376,8 @@ config APRICOT called apricot. config B44 - tristate "Broadcom 4400 ethernet support (EXPERIMENTAL)" - depends on NET_PCI && PCI && EXPERIMENTAL + tristate "Broadcom 4400 ethernet support" + depends on NET_PCI && PCI select MII help If you have a network (Ethernet) controller of this type, say Y and -- cgit v1.2.3 From 8fa29b23d9e0ef976dc578aab98297d4f24f70da Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Thu, 22 Jun 2006 23:19:15 -0400 Subject: [libata] ahci: add JMicron PCI IDs Originally contributed by Justin @ JMicron. Signed-off-by: Jeff Garzik --- drivers/scsi/ahci.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 82ecdef0c48..df779ba8749 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -320,8 +320,14 @@ static const struct pci_device_id ahci_pci_tbl[] = { /* JMicron */ { 0x197b, 0x2360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_ahci }, /* JMicron JMB360 */ + { 0x197b, 0x2361, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_ahci }, /* JMicron JMB361 */ { 0x197b, 0x2363, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_ahci }, /* JMicron JMB363 */ + { 0x197b, 0x2365, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_ahci }, /* JMicron JMB365 */ + { 0x197b, 0x2366, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_ahci }, /* JMicron JMB366 */ /* ATI */ { PCI_VENDOR_ID_ATI, 0x4380, PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- cgit v1.2.3 From d73f1e3c3b0703e25728ce5bdda9806d6f2c576f Mon Sep 17 00:00:00 2001 From: Philip Craig Date: Wed, 21 Jun 2006 11:33:26 +1000 Subject: [PATCH] 8139cp: fix eeprom read command length The read command for the 93C46/93C56 EEPROMS should be 3 bits plus the address. This doesn't appear to affect the operation of the read command, but similar errors for write commands do cause failures. Signed-off-by: Philip Craig Signed-off-by: Jeff Garzik --- drivers/net/8139cp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index 46d8c01437e..b49be8f2c10 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c @@ -1628,7 +1628,7 @@ static int read_eeprom (void __iomem *ioaddr, int location, int addr_len) eeprom_delay (); /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { + for (i = 3 + addr_len - 1; i >= 0; i--) { int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; writeb (EE_ENB | dataval, ee_addr); eeprom_delay (); -- cgit v1.2.3 From 722fdb33591bc7308a661913fb2f829128236b6f Mon Sep 17 00:00:00 2001 From: Philip Craig Date: Wed, 21 Jun 2006 11:33:27 +1000 Subject: [PATCH] 8139cp: add ethtool eeprom support Implement the ethtool eeprom operations for the 8139cp driver. Tested on x86 and big-endian ARM. Signed-off-by: Philip Craig Signed-off-by: Jeff Garzik --- drivers/net/8139cp.c | 179 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 167 insertions(+), 12 deletions(-) diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index b49be8f2c10..a26077a175a 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c @@ -401,6 +401,11 @@ static void cp_clean_rings (struct cp_private *cp); #ifdef CONFIG_NET_POLL_CONTROLLER static void cp_poll_controller(struct net_device *dev); #endif +static int cp_get_eeprom_len(struct net_device *dev); +static int cp_get_eeprom(struct net_device *dev, + struct ethtool_eeprom *eeprom, u8 *data); +static int cp_set_eeprom(struct net_device *dev, + struct ethtool_eeprom *eeprom, u8 *data); static struct pci_device_id cp_pci_tbl[] = { { PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139, @@ -1577,6 +1582,9 @@ static struct ethtool_ops cp_ethtool_ops = { .get_strings = cp_get_strings, .get_ethtool_stats = cp_get_ethtool_stats, .get_perm_addr = ethtool_op_get_perm_addr, + .get_eeprom_len = cp_get_eeprom_len, + .get_eeprom = cp_get_eeprom, + .set_eeprom = cp_set_eeprom, }; static int cp_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) @@ -1612,24 +1620,32 @@ static int cp_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) #define eeprom_delay() readl(ee_addr) /* The EEPROM commands include the alway-set leading bit. */ +#define EE_EXTEND_CMD (4) #define EE_WRITE_CMD (5) #define EE_READ_CMD (6) #define EE_ERASE_CMD (7) -static int read_eeprom (void __iomem *ioaddr, int location, int addr_len) -{ - int i; - unsigned retval = 0; - void __iomem *ee_addr = ioaddr + Cfg9346; - int read_cmd = location | (EE_READ_CMD << addr_len); +#define EE_EWDS_ADDR (0) +#define EE_WRAL_ADDR (1) +#define EE_ERAL_ADDR (2) +#define EE_EWEN_ADDR (3) + +#define CP_EEPROM_MAGIC PCI_DEVICE_ID_REALTEK_8139 +static void eeprom_cmd_start(void __iomem *ee_addr) +{ writeb (EE_ENB & ~EE_CS, ee_addr); writeb (EE_ENB, ee_addr); eeprom_delay (); +} - /* Shift the read command bits out. */ - for (i = 3 + addr_len - 1; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; +static void eeprom_cmd(void __iomem *ee_addr, int cmd, int cmd_len) +{ + int i; + + /* Shift the command bits out. */ + for (i = cmd_len - 1; i >= 0; i--) { + int dataval = (cmd & (1 << i)) ? EE_DATA_WRITE : 0; writeb (EE_ENB | dataval, ee_addr); eeprom_delay (); writeb (EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); @@ -1637,6 +1653,33 @@ static int read_eeprom (void __iomem *ioaddr, int location, int addr_len) } writeb (EE_ENB, ee_addr); eeprom_delay (); +} + +static void eeprom_cmd_end(void __iomem *ee_addr) +{ + writeb (~EE_CS, ee_addr); + eeprom_delay (); +} + +static void eeprom_extend_cmd(void __iomem *ee_addr, int extend_cmd, + int addr_len) +{ + int cmd = (EE_EXTEND_CMD << addr_len) | (extend_cmd << (addr_len - 2)); + + eeprom_cmd_start(ee_addr); + eeprom_cmd(ee_addr, cmd, 3 + addr_len); + eeprom_cmd_end(ee_addr); +} + +static u16 read_eeprom (void __iomem *ioaddr, int location, int addr_len) +{ + int i; + u16 retval = 0; + void __iomem *ee_addr = ioaddr + Cfg9346; + int read_cmd = location | (EE_READ_CMD << addr_len); + + eeprom_cmd_start(ee_addr); + eeprom_cmd(ee_addr, read_cmd, 3 + addr_len); for (i = 16; i > 0; i--) { writeb (EE_ENB | EE_SHIFT_CLK, ee_addr); @@ -1648,13 +1691,125 @@ static int read_eeprom (void __iomem *ioaddr, int location, int addr_len) eeprom_delay (); } - /* Terminate the EEPROM access. */ - writeb (~EE_CS, ee_addr); - eeprom_delay (); + eeprom_cmd_end(ee_addr); return retval; } +static void write_eeprom(void __iomem *ioaddr, int location, u16 val, + int addr_len) +{ + int i; + void __iomem *ee_addr = ioaddr + Cfg9346; + int write_cmd = location | (EE_WRITE_CMD << addr_len); + + eeprom_extend_cmd(ee_addr, EE_EWEN_ADDR, addr_len); + + eeprom_cmd_start(ee_addr); + eeprom_cmd(ee_addr, write_cmd, 3 + addr_len); + eeprom_cmd(ee_addr, val, 16); + eeprom_cmd_end(ee_addr); + + eeprom_cmd_start(ee_addr); + for (i = 0; i < 20000; i++) + if (readb(ee_addr) & EE_DATA_READ) + break; + eeprom_cmd_end(ee_addr); + + eeprom_extend_cmd(ee_addr, EE_EWDS_ADDR, addr_len); +} + +static int cp_get_eeprom_len(struct net_device *dev) +{ + struct cp_private *cp = netdev_priv(dev); + int size; + + spin_lock_irq(&cp->lock); + size = read_eeprom(cp->regs, 0, 8) == 0x8129 ? 256 : 128; + spin_unlock_irq(&cp->lock); + + return size; +} + +static int cp_get_eeprom(struct net_device *dev, + struct ethtool_eeprom *eeprom, u8 *data) +{ + struct cp_private *cp = netdev_priv(dev); + unsigned int addr_len; + u16 val; + u32 offset = eeprom->offset >> 1; + u32 len = eeprom->len; + u32 i = 0; + + eeprom->magic = CP_EEPROM_MAGIC; + + spin_lock_irq(&cp->lock); + + addr_len = read_eeprom(cp->regs, 0, 8) == 0x8129 ? 8 : 6; + + if (eeprom->offset & 1) { + val = read_eeprom(cp->regs, offset, addr_len); + data[i++] = (u8)(val >> 8); + offset++; + } + + while (i < len - 1) { + val = read_eeprom(cp->regs, offset, addr_len); + data[i++] = (u8)val; + data[i++] = (u8)(val >> 8); + offset++; + } + + if (i < len) { + val = read_eeprom(cp->regs, offset, addr_len); + data[i] = (u8)val; + } + + spin_unlock_irq(&cp->lock); + return 0; +} + +static int cp_set_eeprom(struct net_device *dev, + struct ethtool_eeprom *eeprom, u8 *data) +{ + struct cp_private *cp = netdev_priv(dev); + unsigned int addr_len; + u16 val; + u32 offset = eeprom->offset >> 1; + u32 len = eeprom->len; + u32 i = 0; + + if (eeprom->magic != CP_EEPROM_MAGIC) + return -EINVAL; + + spin_lock_irq(&cp->lock); + + addr_len = read_eeprom(cp->regs, 0, 8) == 0x8129 ? 8 : 6; + + if (eeprom->offset & 1) { + val = read_eeprom(cp->regs, offset, addr_len) & 0xff; + val |= (u16)data[i++] << 8; + write_eeprom(cp->regs, offset, val, addr_len); + offset++; + } + + while (i < len - 1) { + val = (u16)data[i++]; + val |= (u16)data[i++] << 8; + write_eeprom(cp->regs, offset, val, addr_len); + offset++; + } + + if (i < len) { + val = read_eeprom(cp->regs, offset, addr_len) & 0xff00; + val |= (u16)data[i]; + write_eeprom(cp->regs, offset, val, addr_len); + } + + spin_unlock_irq(&cp->lock); + return 0; +} + /* Put the board into D3cold state and wait for WakeUp signal */ static void cp_set_d3_state (struct cp_private *cp) { -- cgit v1.2.3 From da4f5ccf6040b998b64c60db8fa5f4ee03fdaf95 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Wed, 21 Jun 2006 16:10:48 +0200 Subject: [PATCH] Remove useless check in drivers/net/pcmcia/xirc2ps_cs.c hi, coverity choked at this check (id #223), assuming that skb might be NULL and used anyways later. Since start_hard_xmit() always gets called with a valid skb, the check is useless and this patch removes it. Signed-off-by: Eric Sesterhenn Signed-off-by: Jeff Garzik --- drivers/net/pcmcia/xirc2ps_cs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index 71f45056a70..e80d1e3aec6 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -1359,7 +1359,7 @@ do_start_xmit(struct sk_buff *skb, struct net_device *dev) kio_addr_t ioaddr = dev->base_addr; int okay; unsigned freespace; - unsigned pktlen = skb? skb->len : 0; + unsigned pktlen = skb->len; DEBUG(1, "do_start_xmit(skb=%p, dev=%p) len=%u\n", skb, dev, pktlen); -- cgit v1.2.3 From 71f0737b2889b86f774a94afaf1342c2c0d61cb5 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 21 Jun 2006 23:12:48 +0900 Subject: [PATCH] ahci: disable NCQ support on vt8251 vt8251 chokes on NCQ commands. Two different disks from different vendors are showing the same symptom and it seems that the windows driver from via doesn't support NCQ either. Disable NCQ support on this controller for the time being. Signed-off-by: Tejun Heo Cc: Aalderd Bouwman Cc: Bastiaan Jacques Signed-off-by: Jeff Garzik --- drivers/scsi/ahci.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index df779ba8749..4bb77f62b3b 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -164,6 +164,7 @@ enum { /* ap->flags bits */ AHCI_FLAG_RESET_NEEDS_CLO = (1 << 24), + AHCI_FLAG_NO_NCQ = (1 << 25), }; struct ahci_cmd_hdr { @@ -277,7 +278,7 @@ static const struct ata_port_info ahci_port_info[] = { .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | ATA_FLAG_SKIP_D2H_BSY | - AHCI_FLAG_RESET_NEEDS_CLO, + AHCI_FLAG_RESET_NEEDS_CLO | AHCI_FLAG_NO_NCQ, .pio_mask = 0x1f, /* pio0-4 */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */ .port_ops = &ahci_ops, @@ -1386,7 +1387,8 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) if (rc) goto err_out_hpriv; - if (hpriv->cap & HOST_CAP_NCQ) + if (!(probe_ent->host_flags & AHCI_FLAG_NO_NCQ) && + (hpriv->cap & HOST_CAP_NCQ)) probe_ent->host_flags |= ATA_FLAG_NCQ; ahci_print_info(probe_ent); -- cgit v1.2.3 From a192491ad58098f2c57d2d1efe721ea0634dc0aa Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Wed, 21 Jun 2006 16:40:24 +0200 Subject: [PATCH] Array overrun in drivers/net/wireless/wavelan.c hi, this is another array overrun spotted by coverity (#id 507) we should check the index against array size before using it. Not sure why the driver doesnt use ARRAY_SIZE instead of its own macro. Signed-off-by: Eric Sesterhenn Signed-off-by: Jeff Garzik --- drivers/net/wireless/wavelan.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/wavelan.c b/drivers/net/wireless/wavelan.c index dade4b90357..b327b640823 100644 --- a/drivers/net/wireless/wavelan.c +++ b/drivers/net/wireless/wavelan.c @@ -1695,8 +1695,8 @@ static int wv_frequency_list(unsigned long ioaddr, /* I/O port of the card */ /* Look in the table if the frequency is allowed */ if (table[9 - (freq / 16)] & (1 << (freq % 16))) { /* Compute approximate channel number */ - while ((((channel_bands[c] >> 1) - 24) < freq) && - (c < NELS(channel_bands))) + while ((c < NELS(channel_bands)) && + (((channel_bands[c] >> 1) - 24) < freq)) c++; list[i].i = c; /* Set the list index */ -- cgit v1.2.3 From 6d56ab936237b429366ade0d2a1540c7e41beb87 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Wed, 21 Jun 2006 16:17:17 +0200 Subject: [PATCH] Dereference in tokenring/olympic.c hi, coverity found (bug id #225) that we might call free_netdev() with NULL argument, when alloc_trdev() fails. This patch changes the goto, so we dont call free_netdev() for dev == NULL. Signed-off-by: Eric Sesterhenn Signed-off-by: Jeff Garzik --- drivers/net/tokenring/olympic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c index 23032a7bc0a..c3cb8d26cfe 100644 --- a/drivers/net/tokenring/olympic.c +++ b/drivers/net/tokenring/olympic.c @@ -217,7 +217,7 @@ static int __devinit olympic_probe(struct pci_dev *pdev, const struct pci_device dev = alloc_trdev(sizeof(struct olympic_private)) ; if (!dev) { i = -ENOMEM; - goto op_free_dev; + goto op_release_dev; } olympic_priv = dev->priv ; @@ -282,8 +282,8 @@ op_free_iomap: if (olympic_priv->olympic_lap) iounmap(olympic_priv->olympic_lap); -op_free_dev: free_netdev(dev); +op_release_dev: pci_release_regions(pdev); op_disable_dev: -- cgit v1.2.3 From 3a778275626c0eb97674e92875efeba01189ce0e Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Thu, 22 Jun 2006 13:00:25 +0800 Subject: [PATCH] libata-dev: move the CDB-intr DMA blacklisting Move the DMA blacklisting of the CDB-intr devices from ata_check_atapi_dma() to ata_dma_blacklisted(), where it makes more sense. Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index df483adc3f7..425ab1493fd 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2943,6 +2943,14 @@ static int ata_dma_blacklisted(const struct ata_device *dev) unsigned int nlen, rlen; int i; + /* We don't support polling DMA. + * DMA blacklist those ATAPI devices with CDB-intr (and use PIO) + * if the LLDD handles only interrupts in the HSM_ST_LAST state. + */ + if ((dev->ap->flags & ATA_FLAG_PIO_POLLING) && + (dev->flags & ATA_DFLAG_CDB_INTR)) + return 1; + ata_id_string(dev->id, model_num, ATA_ID_PROD_OFS, sizeof(model_num)); ata_id_string(dev->id, model_rev, ATA_ID_FW_REV_OFS, @@ -3235,15 +3243,6 @@ int ata_check_atapi_dma(struct ata_queued_cmd *qc) if (ap->ops->check_atapi_dma) rc = ap->ops->check_atapi_dma(qc); - /* We don't support polling DMA. - * Use PIO if the LLDD handles only interrupts in - * the HSM_ST_LAST state and the ATAPI device - * generates CDB interrupts. - */ - if ((ap->flags & ATA_FLAG_PIO_POLLING) && - (qc->dev->flags & ATA_DFLAG_CDB_INTR)) - rc = 1; - return rc; } /** @@ -4551,7 +4550,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc) break; case ATA_PROT_ATAPI_DMA: if (qc->dev->flags & ATA_DFLAG_CDB_INTR) - /* see ata_check_atapi_dma() */ + /* see ata_dma_blacklisted() */ BUG(); break; default: -- cgit v1.2.3 From 92aa674d721d089c440301ab95cb6be19c78727e Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 22 Jun 2006 07:11:13 +0200 Subject: [PATCH] network driver for Hilscher netx This is a patch for the Hilscher netx builtin ethernet ports. The netx board support was merged into 2.6.17-git2. The netx is a arm926 based SoC. Signed-off-by: Robert Schwebel Signed-off-by: Sascha Hauer -- drivers/net/Kconfig | 11 drivers/net/Makefile | 1 drivers/net/netx-eth.c | 516 ++++++++++++++++++++++++++++++++++++++++ include/asm-arm/arch-netx/eth.h | 27 ++ 4 files changed, 555 insertions(+) Signed-off-by: Jeff Garzik --- drivers/net/Kconfig | 11 + drivers/net/Makefile | 1 + drivers/net/netx-eth.c | 516 ++++++++++++++++++++++++++++++++++++++++ include/asm-arm/arch-netx/eth.h | 27 +++ 4 files changed, 555 insertions(+) create mode 100644 drivers/net/netx-eth.c create mode 100644 include/asm-arm/arch-netx/eth.h diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 67e812642c8..7fa24c51e40 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -854,6 +854,17 @@ config SMC9194 . The module will be called smc9194. +config NET_NETX + tristate "NetX Ethernet support" + select MII + depends on NET_ETHERNET && ARCH_NETX + help + This is support for the Hilscher netX builtin Ethernet ports + + To compile this driver as a module, choose M here and read + . The module + will be called netx-eth. + config DM9000 tristate "DM9000 support" depends on (ARM || MIPS) && NET_ETHERNET diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 1eced328750..c91e95126f7 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -187,6 +187,7 @@ obj-$(CONFIG_MACSONIC) += macsonic.o obj-$(CONFIG_MACMACE) += macmace.o obj-$(CONFIG_MAC89x0) += mac89x0.o obj-$(CONFIG_TUN) += tun.o +obj-$(CONFIG_NET_NETX) += netx-eth.o obj-$(CONFIG_DL2K) += dl2k.o obj-$(CONFIG_R8169) += r8169.o obj-$(CONFIG_AMD8111_ETH) += amd8111e.o diff --git a/drivers/net/netx-eth.c b/drivers/net/netx-eth.c new file mode 100644 index 00000000000..b92430c4e3a --- /dev/null +++ b/drivers/net/netx-eth.c @@ -0,0 +1,516 @@ +/* + * drivers/net/netx-eth.c + * + * Copyright (c) 2005 Sascha Hauer , Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/* XC Fifo Offsets */ +#define EMPTY_PTR_FIFO(xcno) (0 + ((xcno) << 3)) /* Index of the empty pointer FIFO */ +#define IND_FIFO_PORT_HI(xcno) (1 + ((xcno) << 3)) /* Index of the FIFO where received */ + /* Data packages are indicated by XC */ +#define IND_FIFO_PORT_LO(xcno) (2 + ((xcno) << 3)) /* Index of the FIFO where received */ + /* Data packages are indicated by XC */ +#define REQ_FIFO_PORT_HI(xcno) (3 + ((xcno) << 3)) /* Index of the FIFO where Data packages */ + /* have to be indicated by ARM which */ + /* shall be sent */ +#define REQ_FIFO_PORT_LO(xcno) (4 + ((xcno) << 3)) /* Index of the FIFO where Data packages */ + /* have to be indicated by ARM which shall */ + /* be sent */ +#define CON_FIFO_PORT_HI(xcno) (5 + ((xcno) << 3)) /* Index of the FIFO where sent Data packages */ + /* are confirmed */ +#define CON_FIFO_PORT_LO(xcno) (6 + ((xcno) << 3)) /* Index of the FIFO where sent Data */ + /* packages are confirmed */ +#define PFIFO_MASK(xcno) (0x7f << (xcno*8)) + +#define FIFO_PTR_FRAMELEN_SHIFT 0 +#define FIFO_PTR_FRAMELEN_MASK (0x7ff << 0) +#define FIFO_PTR_FRAMELEN(len) (((len) << 0) & FIFO_PTR_FRAMELEN_MASK) +#define FIFO_PTR_TIMETRIG (1<<11) +#define FIFO_PTR_MULTI_REQ +#define FIFO_PTR_ORIGIN (1<<14) +#define FIFO_PTR_VLAN (1<<15) +#define FIFO_PTR_FRAMENO_SHIFT 16 +#define FIFO_PTR_FRAMENO_MASK (0x3f << 16) +#define FIFO_PTR_FRAMENO(no) (((no) << 16) & FIFO_PTR_FRAMENO_MASK) +#define FIFO_PTR_SEGMENT_SHIFT 22 +#define FIFO_PTR_SEGMENT_MASK (0xf << 22) +#define FIFO_PTR_SEGMENT(seg) (((seg) & 0xf) << 22) +#define FIFO_PTR_ERROR_SHIFT 28 +#define FIFO_PTR_ERROR_MASK (0xf << 28) + +#define ISR_LINK_STATUS_CHANGE (1<<4) +#define ISR_IND_LO (1<<3) +#define ISR_CON_LO (1<<2) +#define ISR_IND_HI (1<<1) +#define ISR_CON_HI (1<<0) + +#define ETH_MAC_LOCAL_CONFIG 0x1560 +#define ETH_MAC_4321 0x1564 +#define ETH_MAC_65 0x1568 + +#define MAC_TRAFFIC_CLASS_ARRANGEMENT_SHIFT 16 +#define MAC_TRAFFIC_CLASS_ARRANGEMENT_MASK (0xf<data; + unsigned int len = skb->len; + + spin_lock_irq(&priv->lock); + memcpy_toio(priv->sram_base + 1560, (void *)buf, len); + if (len < 60) { + memset_io(priv->sram_base + 1560 + len, 0, 60 - len); + len = 60; + } + + pfifo_push(REQ_FIFO_PORT_LO(priv->id), + FIFO_PTR_SEGMENT(priv->id) | + FIFO_PTR_FRAMENO(1) | + FIFO_PTR_FRAMELEN(len)); + + ndev->trans_start = jiffies; + priv->stats.tx_packets++; + priv->stats.tx_bytes += skb->len; + + netif_stop_queue(ndev); + spin_unlock_irq(&priv->lock); + dev_kfree_skb(skb); + + return 0; +} + +static void netx_eth_receive(struct net_device *ndev) +{ + struct netx_eth_priv *priv = netdev_priv(ndev); + unsigned int val, frameno, seg, len; + unsigned char *data; + struct sk_buff *skb; + + val = pfifo_pop(IND_FIFO_PORT_LO(priv->id)); + + frameno = (val & FIFO_PTR_FRAMENO_MASK) >> FIFO_PTR_FRAMENO_SHIFT; + seg = (val & FIFO_PTR_SEGMENT_MASK) >> FIFO_PTR_SEGMENT_SHIFT; + len = (val & FIFO_PTR_FRAMELEN_MASK) >> FIFO_PTR_FRAMELEN_SHIFT; + + skb = dev_alloc_skb(len); + if (unlikely(skb == NULL)) { + printk(KERN_NOTICE "%s: Low memory, packet dropped.\n", + ndev->name); + priv->stats.rx_dropped++; + return; + } + + data = skb_put(skb, len); + + memcpy_fromio(data, priv->sram_base + frameno * 1560, len); + + pfifo_push(EMPTY_PTR_FIFO(priv->id), + FIFO_PTR_SEGMENT(seg) | FIFO_PTR_FRAMENO(frameno)); + + ndev->last_rx = jiffies; + skb->dev = ndev; + skb->protocol = eth_type_trans(skb, ndev); + netif_rx(skb); + priv->stats.rx_packets++; + priv->stats.rx_bytes += len; +} + +static irqreturn_t +netx_eth_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct net_device *ndev = dev_id; + struct netx_eth_priv *priv = netdev_priv(ndev); + int status; + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + + status = readl(NETX_PFIFO_XPEC_ISR(priv->id)); + while (status) { + int fill_level; + writel(status, NETX_PFIFO_XPEC_ISR(priv->id)); + + if ((status & ISR_CON_HI) || (status & ISR_IND_HI)) + printk("%s: unexpected status: 0x%08x\n", + __FUNCTION__, status); + + fill_level = + readl(NETX_PFIFO_FILL_LEVEL(IND_FIFO_PORT_LO(priv->id))); + while (fill_level--) + netx_eth_receive(ndev); + + if (status & ISR_CON_LO) + netif_wake_queue(ndev); + + if (status & ISR_LINK_STATUS_CHANGE) + mii_check_media(&priv->mii, netif_msg_link(priv), 1); + + status = readl(NETX_PFIFO_XPEC_ISR(priv->id)); + } + spin_unlock_irqrestore(&priv->lock, flags); + return IRQ_HANDLED; +} + +static struct net_device_stats *netx_eth_query_statistics(struct net_device *ndev) +{ + struct netx_eth_priv *priv = netdev_priv(ndev); + return &priv->stats; +} + +static int netx_eth_open(struct net_device *ndev) +{ + struct netx_eth_priv *priv = netdev_priv(ndev); + + if (request_irq + (ndev->irq, &netx_eth_interrupt, SA_SHIRQ, ndev->name, ndev)) + return -EAGAIN; + + writel(ndev->dev_addr[0] | + ndev->dev_addr[1]<<8 | + ndev->dev_addr[2]<<16 | + ndev->dev_addr[3]<<24, + priv->xpec_base + NETX_XPEC_RAM_START_OFS + ETH_MAC_4321); + writel(ndev->dev_addr[4] | + ndev->dev_addr[5]<<8, + priv->xpec_base + NETX_XPEC_RAM_START_OFS + ETH_MAC_65); + + writel(LOCAL_CONFIG_LINK_STATUS_IRQ_EN | + LOCAL_CONFIG_CON_LO_IRQ_EN | + LOCAL_CONFIG_CON_HI_IRQ_EN | + LOCAL_CONFIG_IND_LO_IRQ_EN | + LOCAL_CONFIG_IND_HI_IRQ_EN, + priv->xpec_base + NETX_XPEC_RAM_START_OFS + + ETH_MAC_LOCAL_CONFIG); + + mii_check_media(&priv->mii, netif_msg_link(priv), 1); + netif_start_queue(ndev); + + return 0; +} + +static int netx_eth_close(struct net_device *ndev) +{ + struct netx_eth_priv *priv = netdev_priv(ndev); + + netif_stop_queue(ndev); + + writel(0, + priv->xpec_base + NETX_XPEC_RAM_START_OFS + ETH_MAC_LOCAL_CONFIG); + + free_irq(ndev->irq, ndev); + + return 0; +} + +static void netx_eth_timeout(struct net_device *ndev) +{ + struct netx_eth_priv *priv = netdev_priv(ndev); + int i; + + printk(KERN_ERR "%s: transmit timed out, resetting\n", ndev->name); + + spin_lock_irq(&priv->lock); + + xc_reset(priv->xc); + xc_start(priv->xc); + + for (i=2; i<=18; i++) + pfifo_push(EMPTY_PTR_FIFO(priv->id), + FIFO_PTR_FRAMENO(i) | FIFO_PTR_SEGMENT(priv->id)); + + spin_unlock_irq(&priv->lock); + + netif_wake_queue(ndev); +} + +static int +netx_eth_phy_read(struct net_device *ndev, int phy_id, int reg) +{ + unsigned int val; + + val = MIIMU_SNRDY | MIIMU_PREAMBLE | MIIMU_PHYADDR(phy_id) | + MIIMU_REGADDR(reg) | MIIMU_PHY_NRES; + + writel(val, NETX_MIIMU); + while (readl(NETX_MIIMU) & MIIMU_SNRDY); + + return readl(NETX_MIIMU) >> 16; + +} + +static void +netx_eth_phy_write(struct net_device *ndev, int phy_id, int reg, int value) +{ + unsigned int val; + + val = MIIMU_SNRDY | MIIMU_PREAMBLE | MIIMU_PHYADDR(phy_id) | + MIIMU_REGADDR(reg) | MIIMU_PHY_NRES | MIIMU_OPMODE_WRITE | + MIIMU_DATA(value); + + writel(val, NETX_MIIMU); + while (readl(NETX_MIIMU) & MIIMU_SNRDY); +} + +static int netx_eth_enable(struct net_device *ndev) +{ + struct netx_eth_priv *priv = netdev_priv(ndev); + unsigned int mac4321, mac65; + int running, i; + + ether_setup(ndev); + + ndev->open = netx_eth_open; + ndev->stop = netx_eth_close; + ndev->hard_start_xmit = netx_eth_hard_start_xmit; + ndev->tx_timeout = netx_eth_timeout; + ndev->watchdog_timeo = msecs_to_jiffies(5000); + ndev->get_stats = netx_eth_query_statistics; + ndev->set_multicast_list = netx_eth_set_multicast_list; + + priv->msg_enable = NETIF_MSG_LINK; + priv->mii.phy_id_mask = 0x1f; + priv->mii.reg_num_mask = 0x1f; + priv->mii.force_media = 0; + priv->mii.full_duplex = 0; + priv->mii.dev = ndev; + priv->mii.mdio_read = netx_eth_phy_read; + priv->mii.mdio_write = netx_eth_phy_write; + priv->mii.phy_id = INTERNAL_PHY_ADR + priv->id; + + running = xc_running(priv->xc); + xc_stop(priv->xc); + + /* if the xc engine is already running, assume the bootloader has + * loaded the firmware for us + */ + if (running) { + /* get Node Address from hardware */ + mac4321 = readl(priv->xpec_base + + NETX_XPEC_RAM_START_OFS + ETH_MAC_4321); + mac65 = readl(priv->xpec_base + + NETX_XPEC_RAM_START_OFS + ETH_MAC_65); + + ndev->dev_addr[0] = mac4321 & 0xff; + ndev->dev_addr[1] = (mac4321 >> 8) & 0xff; + ndev->dev_addr[2] = (mac4321 >> 16) & 0xff; + ndev->dev_addr[3] = (mac4321 >> 24) & 0xff; + ndev->dev_addr[4] = mac65 & 0xff; + ndev->dev_addr[5] = (mac65 >> 8) & 0xff; + } else { + if (xc_request_firmware(priv->xc)) { + printk(CARDNAME ": requesting firmware failed\n"); + return -ENODEV; + } + } + + xc_reset(priv->xc); + xc_start(priv->xc); + + if (!is_valid_ether_addr(ndev->dev_addr)) + printk("%s: Invalid ethernet MAC address. Please " + "set using ifconfig\n", ndev->name); + + for (i=2; i<=18; i++) + pfifo_push(EMPTY_PTR_FIFO(priv->id), + FIFO_PTR_FRAMENO(i) | FIFO_PTR_SEGMENT(priv->id)); + + return register_netdev(ndev); + +} + +static int netx_eth_drv_probe(struct platform_device *pdev) +{ + struct netx_eth_priv *priv; + struct net_device *ndev; + struct netxeth_platform_data *pdata; + int ret; + + ndev = alloc_etherdev(sizeof (struct netx_eth_priv)); + if (!ndev) { + printk("%s: could not allocate device.\n", CARDNAME); + ret = -ENOMEM; + goto exit; + } + SET_MODULE_OWNER(ndev); + SET_NETDEV_DEV(ndev, &pdev->dev); + + platform_set_drvdata(pdev, ndev); + + priv = netdev_priv(ndev); + + pdata = (struct netxeth_platform_data *)pdev->dev.platform_data; + priv->xc = request_xc(pdata->xcno, &pdev->dev); + if (!priv->xc) { + dev_err(&pdev->dev, "unable to request xc engine\n"); + ret = -ENODEV; + goto exit_free_netdev; + } + + ndev->irq = priv->xc->irq; + priv->id = pdev->id; + priv->xpec_base = priv->xc->xpec_base; + priv->xmac_base = priv->xc->xmac_base; + priv->sram_base = priv->xc->sram_base; + + ret = pfifo_request(PFIFO_MASK(priv->id)); + if (ret) { + printk("unable to request PFIFO\n"); + goto exit_free_xc; + } + + ret = netx_eth_enable(ndev); + if (ret) + goto exit_free_pfifo; + + return 0; +exit_free_pfifo: + pfifo_free(PFIFO_MASK(priv->id)); +exit_free_xc: + free_xc(priv->xc); +exit_free_netdev: + platform_set_drvdata(pdev, NULL); + free_netdev(ndev); +exit: + return ret; +} + +static int netx_eth_drv_remove(struct platform_device *pdev) +{ + struct net_device *ndev = dev_get_drvdata(&pdev->dev); + struct netx_eth_priv *priv = netdev_priv(ndev); + + platform_set_drvdata(pdev, NULL); + + unregister_netdev(ndev); + xc_stop(priv->xc); + free_xc(priv->xc); + free_netdev(ndev); + pfifo_free(PFIFO_MASK(priv->id)); + + return 0; +} + +static int netx_eth_drv_suspend(struct platform_device *pdev, pm_message_t state) +{ + dev_err(&pdev->dev, "suspend not implemented\n"); + return 0; +} + +static int netx_eth_drv_resume(struct platform_device *pdev) +{ + dev_err(&pdev->dev, "resume not implemented\n"); + return 0; +} + +static struct platform_driver netx_eth_driver = { + .probe = netx_eth_drv_probe, + .remove = netx_eth_drv_remove, + .suspend = netx_eth_drv_suspend, + .resume = netx_eth_drv_resume, + .driver = { + .name = CARDNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init netx_eth_init(void) +{ + unsigned int phy_control, val; + + printk("NetX Ethernet driver\n"); + + phy_control = PHY_CONTROL_PHY_ADDRESS(INTERNAL_PHY_ADR>>1) | + PHY_CONTROL_PHY1_MODE(PHY_MODE_ALL) | + PHY_CONTROL_PHY1_AUTOMDIX | + PHY_CONTROL_PHY1_EN | + PHY_CONTROL_PHY0_MODE(PHY_MODE_ALL) | + PHY_CONTROL_PHY0_AUTOMDIX | + PHY_CONTROL_PHY0_EN | + PHY_CONTROL_CLK_XLATIN; + + val = readl(NETX_SYSTEM_IOC_ACCESS_KEY); + writel(val, NETX_SYSTEM_IOC_ACCESS_KEY); + + writel(phy_control | PHY_CONTROL_RESET, NETX_SYSTEM_PHY_CONTROL); + udelay(100); + + val = readl(NETX_SYSTEM_IOC_ACCESS_KEY); + writel(val, NETX_SYSTEM_IOC_ACCESS_KEY); + + writel(phy_control, NETX_SYSTEM_PHY_CONTROL); + + return platform_driver_register(&netx_eth_driver); +} + +static void __exit netx_eth_cleanup(void) +{ + platform_driver_unregister(&netx_eth_driver); +} + +module_init(netx_eth_init); +module_exit(netx_eth_cleanup); + +MODULE_AUTHOR("Sascha Hauer, Pengutronix"); +MODULE_LICENSE("GPL"); + diff --git a/include/asm-arm/arch-netx/eth.h b/include/asm-arm/arch-netx/eth.h new file mode 100644 index 00000000000..643c90ef8b7 --- /dev/null +++ b/include/asm-arm/arch-netx/eth.h @@ -0,0 +1,27 @@ +/* + * include/asm-arm/arch-netx/eth.h + * + * Copyright (c) 2005 Sascha Hauer , Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef ASMARM_ARCH_ETH_H +#define ASMARM_ARCH_ETH_H + +struct netxeth_platform_data { + unsigned int xcno; /* number of xmac/xpec engine this eth uses */ +}; + +#endif -- cgit v1.2.3 From c7985051dec26dc5ae2562a975a0b37b70621f3f Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Thu, 22 Jun 2006 12:03:29 +0200 Subject: [PATCH] make drivers/net/forcedeth.c:nv_update_pause() static This patch makes the needlessly global nv_update_pause() static. Signed-off-by: Adrian Bunk Signed-off-by: Jeff Garzik --- drivers/net/forcedeth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 62b38a4494b..191383d461d 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -2076,7 +2076,7 @@ static void nv_set_multicast(struct net_device *dev) spin_unlock_irq(&np->lock); } -void nv_update_pause(struct net_device *dev, u32 pause_flags) +static void nv_update_pause(struct net_device *dev, u32 pause_flags) { struct fe_priv *np = netdev_priv(dev); u8 __iomem *base = get_hwbase(dev); -- cgit v1.2.3 From aa95abefccc25efea5c8654bc3475e8161319b94 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Thu, 22 Jun 2006 14:25:34 +0100 Subject: [PATCH] skb_padto()-area fixes in 8390, wavelan Ar Iau, 2006-06-22 am 21:29 +1000, ysgrifennodd Herbert Xu: > Alan Cox wrote: > > > > The 8390 change (corrected version) also makes 8390.c faster so should > > be applied anyway, and the orinoco one fixes some code that isn't even > > needed and someone forgot to remove long ago. Otherwise the skb_padto > > Yeah I agree totally. However, I haven't actually seen the fixed 8390 > version being posted yet or at least not to netdev :) Ah the resounding clang of a subtle hint ;) Signed-off-by: Alan Cox - Return 8390.c to the old way of handling short packets (which is also faster) - Remove the skb_padto from orinoco. This got left in when the padding bad write patch was added and is actually not needed. This is fixing a merge error way back when. - Wavelan can also use the stack based buffer trick if you want Signed-off-by: Jeff Garzik --- drivers/net/8390.c | 10 ++++++---- drivers/net/wireless/wavelan.c | 14 ++++++++------ 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/drivers/net/8390.c b/drivers/net/8390.c index f8702742008..86be96af9c8 100644 --- a/drivers/net/8390.c +++ b/drivers/net/8390.c @@ -275,12 +275,14 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev) struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); int send_length = skb->len, output_page; unsigned long flags; + char buf[ETH_ZLEN]; + char *data = skb->data; if (skb->len < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) - return 0; + memset(buf, 0, ETH_ZLEN); /* more efficient than doing just the needed bits */ + memcpy(buf, data, skb->len); send_length = ETH_ZLEN; + data = buf; } /* Mask interrupts from the ethercard. @@ -347,7 +349,7 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev) * trigger the send later, upon receiving a Tx done interrupt. */ - ei_block_output(dev, send_length, skb->data, output_page); + ei_block_output(dev, send_length, data, output_page); if (! ei_local->txing) { diff --git a/drivers/net/wireless/wavelan.c b/drivers/net/wireless/wavelan.c index b327b640823..5b69befdab7 100644 --- a/drivers/net/wireless/wavelan.c +++ b/drivers/net/wireless/wavelan.c @@ -2903,6 +2903,7 @@ static int wavelan_packet_xmit(struct sk_buff *skb, struct net_device * dev) { net_local *lp = (net_local *) dev->priv; unsigned long flags; + char data[ETH_ZLEN]; #ifdef DEBUG_TX_TRACE printk(KERN_DEBUG "%s: ->wavelan_packet_xmit(0x%X)\n", dev->name, @@ -2937,15 +2938,16 @@ static int wavelan_packet_xmit(struct sk_buff *skb, struct net_device * dev) * able to detect collisions, therefore in theory we don't really * need to pad. Jean II */ if (skb->len < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) - return 0; + memset(data, 0, ETH_ZLEN); + memcpy(data, skb->data, skb->len); + /* Write packet on the card */ + if(wv_packet_write(dev, data, ETH_ZLEN)) + return 1; /* We failed */ } - - /* Write packet on the card */ - if(wv_packet_write(dev, skb->data, skb->len)) + else if(wv_packet_write(dev, skb->data, skb->len)) return 1; /* We failed */ + dev_kfree_skb(skb); #ifdef DEBUG_TX_TRACE -- cgit v1.2.3 From 4a31e348e3ecaf54c50240109ac4574b180f8840 Mon Sep 17 00:00:00 2001 From: Krzysztof Halasa Date: Thu, 22 Jun 2006 22:20:19 +0200 Subject: [PATCH] WAN: register_hdlc_device() doesn't need dev_alloc_name() David Boggs noticed that register_hdlc_device() no longer needs to call dev_alloc_name() as it's called by register_netdev(). register_hdlc_device() is currently equivalent to register_netdev(). hdlc_setup() is now EXPORTed as per David's request. Signed-off-by: Krzysztof Halasa Signed-off-by: Jeff Garzik --- drivers/net/wan/hdlc_generic.c | 24 ++---------------------- include/linux/hdlc.h | 2 +- 2 files changed, 3 insertions(+), 23 deletions(-) diff --git a/drivers/net/wan/hdlc_generic.c b/drivers/net/wan/hdlc_generic.c index 46cef8f9213..57f9538b8fb 100644 --- a/drivers/net/wan/hdlc_generic.c +++ b/drivers/net/wan/hdlc_generic.c @@ -259,7 +259,7 @@ int hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) } } -static void hdlc_setup(struct net_device *dev) +void hdlc_setup(struct net_device *dev) { hdlc_device *hdlc = dev_to_hdlc(dev); @@ -288,26 +288,6 @@ struct net_device *alloc_hdlcdev(void *priv) return dev; } -int register_hdlc_device(struct net_device *dev) -{ - int result = dev_alloc_name(dev, "hdlc%d"); - if (result < 0) - return result; - - result = register_netdev(dev); - if (result != 0) - return -EIO; - -#if 0 - if (netif_carrier_ok(dev)) - netif_carrier_off(dev); /* no carrier until DCD goes up */ -#endif - - return 0; -} - - - void unregister_hdlc_device(struct net_device *dev) { rtnl_lock(); @@ -326,8 +306,8 @@ EXPORT_SYMBOL(hdlc_open); EXPORT_SYMBOL(hdlc_close); EXPORT_SYMBOL(hdlc_set_carrier); EXPORT_SYMBOL(hdlc_ioctl); +EXPORT_SYMBOL(hdlc_setup); EXPORT_SYMBOL(alloc_hdlcdev); -EXPORT_SYMBOL(register_hdlc_device); EXPORT_SYMBOL(unregister_hdlc_device); static struct packet_type hdlc_packet_type = { diff --git a/include/linux/hdlc.h b/include/linux/hdlc.h index df695e9ae32..4513f9e4093 100644 --- a/include/linux/hdlc.h +++ b/include/linux/hdlc.h @@ -188,7 +188,7 @@ int hdlc_x25_ioctl(struct net_device *dev, struct ifreq *ifr); int hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); /* Must be used by hardware driver on module startup/exit */ -int register_hdlc_device(struct net_device *dev); +#define register_hdlc_device(dev) register_netdev(dev) void unregister_hdlc_device(struct net_device *dev); struct net_device *alloc_hdlcdev(void *priv); -- cgit v1.2.3 From 4446065a2c9b65398ceb115f4d8c256eb1bb9647 Mon Sep 17 00:00:00 2001 From: Krzysztof Halasa Date: Thu, 22 Jun 2006 22:29:28 +0200 Subject: [PATCH] WAN: ioremap() failure checks in drivers Eric Sesterhenn found that pci200syn initialization lacks return statement in ioremap() error path (coverity bug id #195). It looks like more WAN drivers have problems with ioremap(). Signed-off-by: Krzysztof Halasa Signed-off-by: Jeff Garzik --- drivers/net/wan/c101.c | 6 +++--- drivers/net/wan/n2.c | 5 +++++ drivers/net/wan/pci200syn.c | 1 + drivers/net/wan/wanxl.c | 12 ++++++++++++ 4 files changed, 21 insertions(+), 3 deletions(-) diff --git a/drivers/net/wan/c101.c b/drivers/net/wan/c101.c index 43d854ace23..b60ef02db7b 100644 --- a/drivers/net/wan/c101.c +++ b/drivers/net/wan/c101.c @@ -326,21 +326,21 @@ static int __init c101_run(unsigned long irq, unsigned long winbase) if (request_irq(irq, sca_intr, 0, devname, card)) { printk(KERN_ERR "c101: could not allocate IRQ\n"); c101_destroy_card(card); - return(-EBUSY); + return -EBUSY; } card->irq = irq; if (!request_mem_region(winbase, C101_MAPPED_RAM_SIZE, devname)) { printk(KERN_ERR "c101: could not request RAM window\n"); c101_destroy_card(card); - return(-EBUSY); + return -EBUSY; } card->phy_winbase = winbase; card->win0base = ioremap(winbase, C101_MAPPED_RAM_SIZE); if (!card->win0base) { printk(KERN_ERR "c101: could not map I/O address\n"); c101_destroy_card(card); - return -EBUSY; + return -EFAULT; } card->tx_ring_buffers = TX_RING_BUFFERS; diff --git a/drivers/net/wan/n2.c b/drivers/net/wan/n2.c index cd32751b64e..b7d88db89a5 100644 --- a/drivers/net/wan/n2.c +++ b/drivers/net/wan/n2.c @@ -387,6 +387,11 @@ static int __init n2_run(unsigned long io, unsigned long irq, } card->phy_winbase = winbase; card->winbase = ioremap(winbase, USE_WINDOWSIZE); + if (!card->winbase) { + printk(KERN_ERR "n2: ioremap() failed\n"); + n2_destroy_card(card); + return -EFAULT; + } outb(0, io + N2_PCR); outb(winbase >> 12, io + N2_BAR); diff --git a/drivers/net/wan/pci200syn.c b/drivers/net/wan/pci200syn.c index f485a97844c..670e8bd2245 100644 --- a/drivers/net/wan/pci200syn.c +++ b/drivers/net/wan/pci200syn.c @@ -354,6 +354,7 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev, card->rambase == NULL) { printk(KERN_ERR "pci200syn: ioremap() failed\n"); pci200_pci_remove_one(pdev); + return -EFAULT; } /* Reset PLX */ diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c index 29a756dd979..437e0e938e3 100644 --- a/drivers/net/wan/wanxl.c +++ b/drivers/net/wan/wanxl.c @@ -634,7 +634,13 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev, /* set up PLX mapping */ plx_phy = pci_resource_start(pdev, 0); + card->plx = ioremap_nocache(plx_phy, 0x70); + if (!card->plx) { + printk(KERN_ERR "wanxl: ioremap() failed\n"); + wanxl_pci_remove_one(pdev); + return -EFAULT; + } #if RESET_WHILE_LOADING wanxl_reset(card); @@ -700,6 +706,12 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev, } mem = ioremap_nocache(mem_phy, PDM_OFFSET + sizeof(firmware)); + if (!mem) { + printk(KERN_ERR "wanxl: ioremap() failed\n"); + wanxl_pci_remove_one(pdev); + return -EFAULT; + } + for (i = 0; i < sizeof(firmware); i += 4) writel(htonl(*(u32*)(firmware + i)), mem + PDM_OFFSET + i); -- cgit v1.2.3 From 39105890516b06319ffcf5ef0d0cea6c7f65bc96 Mon Sep 17 00:00:00 2001 From: Gary Zambrano Date: Thu, 22 Jun 2006 17:26:20 -0700 Subject: [PATCH] add b44 to maintainers Add b44 to the MAINTAINERS file. Signed-off-by: Gary Zambrano Signed-off-by: Jeff Garzik --- MAINTAINERS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index f4cf0148c90..4dcd2f1f14d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -574,6 +574,12 @@ L: linuxppc-dev@ozlabs.org W: http://www.penguinppc.org/ppc64/ S: Supported +BROADCOM B44 10/100 ETHERNET DRIVER +P: Gary Zambrano +M: zambrano@broadcom.com +L: netdev@vger.kernel.org +S: Supported + BROADCOM BNX2 GIGABIT ETHERNET DRIVER P: Michael Chan M: mchan@broadcom.com -- cgit v1.2.3 From 69eb887b0c2380791d33f7c07bfba88d7c5cef15 Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Thu, 22 Jun 2006 21:11:59 -0400 Subject: [PATCH] myri10ge - drop workaround for the missing AER ext cap on nVidia CK804 We don't need to hardcode the AER capability of the nVidia CK804 chipset anymore since commit cf34a8e07f02c76f3f1232eecb681301a3d7b10b (PCI: nVidia quirk to make AER PCI-E extended capability visible) now makes sure that this cap will be available to pci_find_ext_capability(). Signed-off-by: Brice Goglin Signed-off-by: Jeff Garzik --- drivers/net/myri10ge/myri10ge.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 1a2b9785e99..5058def3b62 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -2251,12 +2251,6 @@ static void myri10ge_enable_ecrc(struct myri10ge_priv *mgp) } cap = pci_find_ext_capability(bridge, PCI_EXT_CAP_ID_ERR); - /* nvidia ext cap is not always linked in ext cap chain */ - if (!cap - && bridge->vendor == PCI_VENDOR_ID_NVIDIA - && bridge->device == PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_PCIE) - cap = 0x160; - if (!cap) return; -- cgit v1.2.3 From bfcbb00855db21dacd3c154ea13ec3fdd98e747b Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Thu, 22 Jun 2006 21:12:36 -0400 Subject: [PATCH] myri10ge - drop workaround pci_save_state() disabling MSI We don't need to restore the state right after saving it for later recovery since commit 99dc804d9bcc2c53f4c20c291bf4e185312a1a0c (PCI: disable msi mode in pci_disable_device) now prevents pci_save_state() from disabling MSI. Signed-off-by: Brice Goglin Signed-off-by: Jeff Garzik --- drivers/net/myri10ge/myri10ge.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 5058def3b62..5a74f63618b 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -2726,8 +2726,6 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* Save configuration space to be restored if the * nic resets due to a parity error */ myri10ge_save_state(mgp); - /* Restore state immediately since pci_save_msi_state disables MSI */ - myri10ge_restore_state(mgp); /* Setup the watchdog timer */ setup_timer(&mgp->watchdog_timer, myri10ge_watchdog_timer, -- cgit v1.2.3 From 47005f255ed126a4b48a1a2f63164fb1d83bcb0a Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 19 Jun 2006 18:27:23 +0900 Subject: [PATCH] libata: implement per-dev EH action mask eh_info->dev_action[] Currently, the only per-dev EH action is REVALIDATE. EH used to exploit ehi->dev to do selective revalidation on a ATA bus. However, this is a bit hacky and makes it impossible to request selective revalidation from outside of EH or add another per-dev EH action. This patch adds per-dev EH action mask eh_info->dev_action[] and update EH to use this field for REVALIDATE. Note that per-dev actions can still be specified at port-level and it has the same effect of specifying the action for all devices on the port. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-eh.c | 85 +++++++++++++++++++++++++++++++++++++++--------- include/linux/libata.h | 2 ++ 2 files changed, 71 insertions(+), 16 deletions(-) diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c index 531a4e11c07..70b623988a9 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/scsi/libata-eh.c @@ -706,9 +706,35 @@ static void ata_eh_detach_dev(struct ata_device *dev) spin_unlock_irqrestore(&ap->host_set->lock, flags); } +static void ata_eh_clear_action(struct ata_device *dev, + struct ata_eh_info *ehi, unsigned int action) +{ + int i; + + if (!dev) { + ehi->action &= ~action; + for (i = 0; i < ATA_MAX_DEVICES; i++) + ehi->dev_action[i] &= ~action; + } else { + /* doesn't make sense for port-wide EH actions */ + WARN_ON(!(action & ATA_EH_PERDEV_MASK)); + + /* break ehi->action into ehi->dev_action */ + if (ehi->action & action) { + for (i = 0; i < ATA_MAX_DEVICES; i++) + ehi->dev_action[i] |= ehi->action & action; + ehi->action &= ~action; + } + + /* turn off the specified per-dev action */ + ehi->dev_action[dev->devno] &= ~action; + } +} + /** * ata_eh_about_to_do - about to perform eh_action * @ap: target ATA port + * @dev: target ATA dev for per-dev action (can be NULL) * @action: action about to be performed * * Called just before performing EH actions to clear related bits @@ -718,16 +744,35 @@ static void ata_eh_detach_dev(struct ata_device *dev) * LOCKING: * None. */ -static void ata_eh_about_to_do(struct ata_port *ap, unsigned int action) +static void ata_eh_about_to_do(struct ata_port *ap, struct ata_device *dev, + unsigned int action) { unsigned long flags; spin_lock_irqsave(&ap->host_set->lock, flags); - ap->eh_info.action &= ~action; + ata_eh_clear_action(dev, &ap->eh_info, action); ap->flags |= ATA_FLAG_RECOVERED; spin_unlock_irqrestore(&ap->host_set->lock, flags); } +/** + * ata_eh_done - EH action complete + * @ap: target ATA port + * @dev: target ATA dev for per-dev action (can be NULL) + * @action: action just completed + * + * Called right after performing EH actions to clear related bits + * in @ap->eh_context. + * + * LOCKING: + * None. + */ +static void ata_eh_done(struct ata_port *ap, struct ata_device *dev, + unsigned int action) +{ + ata_eh_clear_action(dev, &ap->eh_context.i, action); +} + /** * ata_err_string - convert err_mask to descriptive string * @err_mask: error mask to convert to string @@ -1271,10 +1316,6 @@ static void ata_eh_autopsy(struct ata_port *ap) is_io = 1; } - /* speed down iff command was in progress */ - if (failed_dev) - action |= ata_eh_speed_down(failed_dev, is_io, all_err_mask); - /* enforce default EH actions */ if (ap->flags & ATA_FLAG_FROZEN || all_err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT)) @@ -1282,6 +1323,17 @@ static void ata_eh_autopsy(struct ata_port *ap) else if (all_err_mask) action |= ATA_EH_REVALIDATE; + /* if we have offending qcs and the associated failed device */ + if (failed_dev) { + /* speed down */ + action |= ata_eh_speed_down(failed_dev, is_io, all_err_mask); + + /* perform per-dev EH action only on the offending device */ + ehc->i.dev_action[failed_dev->devno] |= + action & ATA_EH_PERDEV_MASK; + action &= ~ATA_EH_PERDEV_MASK; + } + /* record autopsy result */ ehc->i.dev = failed_dev; ehc->i.action = action; @@ -1457,7 +1509,7 @@ static int ata_eh_reset(struct ata_port *ap, int classify, reset == softreset ? "soft" : "hard"); /* reset */ - ata_eh_about_to_do(ap, ATA_EH_RESET_MASK); + ata_eh_about_to_do(ap, NULL, ATA_EH_RESET_MASK); ehc->i.flags |= ATA_EHI_DID_RESET; rc = ata_do_reset(ap, reset, classes); @@ -1476,7 +1528,7 @@ static int ata_eh_reset(struct ata_port *ap, int classify, return -EINVAL; } - ata_eh_about_to_do(ap, ATA_EH_RESET_MASK); + ata_eh_about_to_do(ap, NULL, ATA_EH_RESET_MASK); rc = ata_do_reset(ap, reset, classes); if (rc == 0 && classify && @@ -1520,8 +1572,7 @@ static int ata_eh_reset(struct ata_port *ap, int classify, postreset(ap, classes); /* reset successful, schedule revalidation */ - ehc->i.dev = NULL; - ehc->i.action &= ~ATA_EH_RESET_MASK; + ata_eh_done(ap, NULL, ATA_EH_RESET_MASK); ehc->i.action |= ATA_EH_REVALIDATE; } @@ -1539,21 +1590,25 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap, DPRINTK("ENTER\n"); for (i = 0; i < ATA_MAX_DEVICES; i++) { + unsigned int action; + dev = &ap->device[i]; + action = ehc->i.action | ehc->i.dev_action[dev->devno]; - if (ehc->i.action & ATA_EH_REVALIDATE && ata_dev_enabled(dev) && - (!ehc->i.dev || ehc->i.dev == dev)) { + if (action & ATA_EH_REVALIDATE && ata_dev_enabled(dev)) { if (ata_port_offline(ap)) { rc = -EIO; break; } - ata_eh_about_to_do(ap, ATA_EH_REVALIDATE); + ata_eh_about_to_do(ap, dev, ATA_EH_REVALIDATE); rc = ata_dev_revalidate(dev, ehc->i.flags & ATA_EHI_DID_RESET); if (rc) break; + ata_eh_done(ap, dev, ATA_EH_REVALIDATE); + /* schedule the scsi_rescan_device() here */ queue_work(ata_aux_wq, &(ap->scsi_rescan_task)); } else if (dev->class == ATA_DEV_UNKNOWN && @@ -1576,9 +1631,7 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap, } } - if (rc == 0) - ehc->i.action &= ~ATA_EH_REVALIDATE; - else + if (rc) *r_failed_dev = dev; DPRINTK("EXIT\n"); diff --git a/include/linux/libata.h b/include/linux/libata.h index f03b8664af1..6b3c3af2c75 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -249,6 +249,7 @@ enum { ATA_EH_HARDRESET = (1 << 2), ATA_EH_RESET_MASK = ATA_EH_SOFTRESET | ATA_EH_HARDRESET, + ATA_EH_PERDEV_MASK = ATA_EH_REVALIDATE, /* ata_eh_info->flags */ ATA_EHI_HOTPLUGGED = (1 << 0), /* could have been hotplugged */ @@ -462,6 +463,7 @@ struct ata_eh_info { u32 serror; /* SError from LLDD */ unsigned int err_mask; /* port-wide err_mask */ unsigned int action; /* ATA_EH_* action mask */ + unsigned int dev_action[ATA_MAX_DEVICES]; /* dev EH action */ unsigned int flags; /* ATA_EHI_* flags */ unsigned long hotplug_timestamp; -- cgit v1.2.3 From ba6a13083c1b720a47c05bee7bedbb6ef06c4611 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Thu, 22 Jun 2006 23:46:10 -0400 Subject: [libata] Add host lock to struct ata_port Prepare for changes required to support SATA devices attached to SAS HBAs. For these devices we don't want to use host_set at all, since libata will not be the owner of struct scsi_host. Signed-off-by: Brian King (with slight merge modifications made by...) Signed-off-by: Jeff Garzik --- drivers/scsi/libata-bmdma.c | 5 ++-- drivers/scsi/libata-core.c | 55 +++++++++++++++++++------------------- drivers/scsi/libata-eh.c | 65 ++++++++++++++++++++++----------------------- drivers/scsi/libata-scsi.c | 20 +++++++------- include/linux/libata.h | 1 + 5 files changed, 73 insertions(+), 73 deletions(-) diff --git a/drivers/scsi/libata-bmdma.c b/drivers/scsi/libata-bmdma.c index 13fab97c840..004e1a0d8b7 100644 --- a/drivers/scsi/libata-bmdma.c +++ b/drivers/scsi/libata-bmdma.c @@ -715,7 +715,6 @@ void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset, ata_reset_fn_t softreset, ata_reset_fn_t hardreset, ata_postreset_fn_t postreset) { - struct ata_host_set *host_set = ap->host_set; struct ata_eh_context *ehc = &ap->eh_context; struct ata_queued_cmd *qc; unsigned long flags; @@ -726,7 +725,7 @@ void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset, qc = NULL; /* reset PIO HSM and stop DMA engine */ - spin_lock_irqsave(&host_set->lock, flags); + spin_lock_irqsave(ap->lock, flags); ap->hsm_task_state = HSM_ST_IDLE; @@ -755,7 +754,7 @@ void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset, ata_chk_status(ap); ap->ops->irq_clear(ap); - spin_unlock_irqrestore(&host_set->lock, flags); + spin_unlock_irqrestore(ap->lock, flags); if (thaw) ata_eh_thaw_port(ap); diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 425ab1493fd..24d340aeb51 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -933,9 +933,9 @@ void ata_port_flush_task(struct ata_port *ap) DPRINTK("ENTER\n"); - spin_lock_irqsave(&ap->host_set->lock, flags); + spin_lock_irqsave(ap->lock, flags); ap->flags |= ATA_FLAG_FLUSH_PORT_TASK; - spin_unlock_irqrestore(&ap->host_set->lock, flags); + spin_unlock_irqrestore(ap->lock, flags); DPRINTK("flush #1\n"); flush_workqueue(ata_wq); @@ -950,9 +950,9 @@ void ata_port_flush_task(struct ata_port *ap) flush_workqueue(ata_wq); } - spin_lock_irqsave(&ap->host_set->lock, flags); + spin_lock_irqsave(ap->lock, flags); ap->flags &= ~ATA_FLAG_FLUSH_PORT_TASK; - spin_unlock_irqrestore(&ap->host_set->lock, flags); + spin_unlock_irqrestore(ap->lock, flags); DPRINTK("EXIT\n"); } @@ -999,11 +999,11 @@ unsigned ata_exec_internal(struct ata_device *dev, unsigned int err_mask; int rc; - spin_lock_irqsave(&ap->host_set->lock, flags); + spin_lock_irqsave(ap->lock, flags); /* no internal command while frozen */ if (ap->flags & ATA_FLAG_FROZEN) { - spin_unlock_irqrestore(&ap->host_set->lock, flags); + spin_unlock_irqrestore(ap->lock, flags); return AC_ERR_SYSTEM; } @@ -1052,14 +1052,14 @@ unsigned ata_exec_internal(struct ata_device *dev, ata_qc_issue(qc); - spin_unlock_irqrestore(&ap->host_set->lock, flags); + spin_unlock_irqrestore(ap->lock, flags); rc = wait_for_completion_timeout(&wait, ATA_TMOUT_INTERNAL); ata_port_flush_task(ap); if (!rc) { - spin_lock_irqsave(&ap->host_set->lock, flags); + spin_lock_irqsave(ap->lock, flags); /* We're racing with irq here. If we lose, the * following test prevents us from completing the qc @@ -1078,7 +1078,7 @@ unsigned ata_exec_internal(struct ata_device *dev, "qc timeout (cmd 0x%x)\n", command); } - spin_unlock_irqrestore(&ap->host_set->lock, flags); + spin_unlock_irqrestore(ap->lock, flags); } /* do post_internal_cmd */ @@ -1092,7 +1092,7 @@ unsigned ata_exec_internal(struct ata_device *dev, } /* finish up */ - spin_lock_irqsave(&ap->host_set->lock, flags); + spin_lock_irqsave(ap->lock, flags); *tf = qc->result_tf; err_mask = qc->err_mask; @@ -1118,7 +1118,7 @@ unsigned ata_exec_internal(struct ata_device *dev, ata_port_probe(ap); } - spin_unlock_irqrestore(&ap->host_set->lock, flags); + spin_unlock_irqrestore(ap->lock, flags); return err_mask; } @@ -3912,7 +3912,7 @@ static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq) if (ap->ops->error_handler) { if (in_wq) { - spin_lock_irqsave(&ap->host_set->lock, flags); + spin_lock_irqsave(ap->lock, flags); /* EH might have kicked in while host_set lock * is released. @@ -3926,7 +3926,7 @@ static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq) ata_port_freeze(ap); } - spin_unlock_irqrestore(&ap->host_set->lock, flags); + spin_unlock_irqrestore(ap->lock, flags); } else { if (likely(!(qc->err_mask & AC_ERR_HSM))) ata_qc_complete(qc); @@ -3935,10 +3935,10 @@ static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq) } } else { if (in_wq) { - spin_lock_irqsave(&ap->host_set->lock, flags); + spin_lock_irqsave(ap->lock, flags); ata_irq_on(ap); ata_qc_complete(qc); - spin_unlock_irqrestore(&ap->host_set->lock, flags); + spin_unlock_irqrestore(ap->lock, flags); } else ata_qc_complete(qc); } @@ -4018,7 +4018,7 @@ fsm_start: * hsm_task_state is changed. Hence, the following locking. */ if (in_wq) - spin_lock_irqsave(&ap->host_set->lock, flags); + spin_lock_irqsave(ap->lock, flags); if (qc->tf.protocol == ATA_PROT_PIO) { /* PIO data out protocol. @@ -4037,7 +4037,7 @@ fsm_start: atapi_send_cdb(ap, qc); if (in_wq) - spin_unlock_irqrestore(&ap->host_set->lock, flags); + spin_unlock_irqrestore(ap->lock, flags); /* if polling, ata_pio_task() handles the rest. * otherwise, interrupt handler takes over from here. @@ -5130,9 +5130,9 @@ void ata_dev_init(struct ata_device *dev) * requests which occur asynchronously. Synchronize using * host_set lock. */ - spin_lock_irqsave(&ap->host_set->lock, flags); + spin_lock_irqsave(ap->lock, flags); dev->flags &= ~ATA_DFLAG_INIT_MASK; - spin_unlock_irqrestore(&ap->host_set->lock, flags); + spin_unlock_irqrestore(ap->lock, flags); memset((void *)dev + ATA_DEVICE_CLEAR_OFFSET, 0, sizeof(*dev) - ATA_DEVICE_CLEAR_OFFSET); @@ -5167,6 +5167,7 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host, host->unique_id = ata_unique_id++; host->max_cmd_len = 12; + ap->lock = &host_set->lock; ap->flags = ATA_FLAG_DISABLED; ap->id = host->unique_id; ap->host = host; @@ -5388,7 +5389,7 @@ int ata_device_add(const struct ata_probe_ent *ent) ata_port_probe(ap); /* kick EH for boot probing */ - spin_lock_irqsave(&ap->host_set->lock, flags); + spin_lock_irqsave(ap->lock, flags); ap->eh_info.probe_mask = (1 << ATA_MAX_DEVICES) - 1; ap->eh_info.action |= ATA_EH_SOFTRESET; @@ -5396,7 +5397,7 @@ int ata_device_add(const struct ata_probe_ent *ent) ap->flags |= ATA_FLAG_LOADING; ata_port_schedule_eh(ap); - spin_unlock_irqrestore(&ap->host_set->lock, flags); + spin_unlock_irqrestore(ap->lock, flags); /* wait for EH to finish */ ata_port_wait_eh(ap); @@ -5460,29 +5461,29 @@ void ata_port_detach(struct ata_port *ap) return; /* tell EH we're leaving & flush EH */ - spin_lock_irqsave(&ap->host_set->lock, flags); + spin_lock_irqsave(ap->lock, flags); ap->flags |= ATA_FLAG_UNLOADING; - spin_unlock_irqrestore(&ap->host_set->lock, flags); + spin_unlock_irqrestore(ap->lock, flags); ata_port_wait_eh(ap); /* EH is now guaranteed to see UNLOADING, so no new device * will be attached. Disable all existing devices. */ - spin_lock_irqsave(&ap->host_set->lock, flags); + spin_lock_irqsave(ap->lock, flags); for (i = 0; i < ATA_MAX_DEVICES; i++) ata_dev_disable(&ap->device[i]); - spin_unlock_irqrestore(&ap->host_set->lock, flags); + spin_unlock_irqrestore(ap->lock, flags); /* Final freeze & EH. All in-flight commands are aborted. EH * will be skipped and retrials will be terminated with bad * target. */ - spin_lock_irqsave(&ap->host_set->lock, flags); + spin_lock_irqsave(ap->lock, flags); ata_port_freeze(ap); /* won't be thawed */ - spin_unlock_irqrestore(&ap->host_set->lock, flags); + spin_unlock_irqrestore(ap->lock, flags); ata_port_wait_eh(ap); diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c index 70b623988a9..823385981a7 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/scsi/libata-eh.c @@ -128,7 +128,7 @@ enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd) } ret = EH_HANDLED; - spin_lock_irqsave(&ap->host_set->lock, flags); + spin_lock_irqsave(ap->lock, flags); qc = ata_qc_from_tag(ap, ap->active_tag); if (qc) { WARN_ON(qc->scsicmd != cmd); @@ -136,7 +136,7 @@ enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd) qc->err_mask |= AC_ERR_TIMEOUT; ret = EH_NOT_HANDLED; } - spin_unlock_irqrestore(&ap->host_set->lock, flags); + spin_unlock_irqrestore(ap->lock, flags); out: DPRINTK("EXIT, ret=%d\n", ret); @@ -158,7 +158,7 @@ enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd) void ata_scsi_error(struct Scsi_Host *host) { struct ata_port *ap = ata_shost_to_port(host); - spinlock_t *hs_lock = &ap->host_set->lock; + spinlock_t *ap_lock = ap->lock; int i, repeat_cnt = ATA_EH_MAX_REPEAT; unsigned long flags; @@ -185,7 +185,7 @@ void ata_scsi_error(struct Scsi_Host *host) struct scsi_cmnd *scmd, *tmp; int nr_timedout = 0; - spin_lock_irqsave(hs_lock, flags); + spin_lock_irqsave(ap_lock, flags); list_for_each_entry_safe(scmd, tmp, &host->eh_cmd_q, eh_entry) { struct ata_queued_cmd *qc; @@ -224,15 +224,15 @@ void ata_scsi_error(struct Scsi_Host *host) if (nr_timedout) __ata_port_freeze(ap); - spin_unlock_irqrestore(hs_lock, flags); + spin_unlock_irqrestore(ap_lock, flags); } else - spin_unlock_wait(hs_lock); + spin_unlock_wait(ap_lock); repeat: /* invoke error handler */ if (ap->ops->error_handler) { /* fetch & clear EH info */ - spin_lock_irqsave(hs_lock, flags); + spin_lock_irqsave(ap_lock, flags); memset(&ap->eh_context, 0, sizeof(ap->eh_context)); ap->eh_context.i = ap->eh_info; @@ -241,7 +241,7 @@ void ata_scsi_error(struct Scsi_Host *host) ap->flags |= ATA_FLAG_EH_IN_PROGRESS; ap->flags &= ~ATA_FLAG_EH_PENDING; - spin_unlock_irqrestore(hs_lock, flags); + spin_unlock_irqrestore(ap_lock, flags); /* invoke EH. if unloading, just finish failed qcs */ if (!(ap->flags & ATA_FLAG_UNLOADING)) @@ -253,14 +253,14 @@ void ata_scsi_error(struct Scsi_Host *host) * recovered the port but before this point. Repeat * EH in such case. */ - spin_lock_irqsave(hs_lock, flags); + spin_lock_irqsave(ap_lock, flags); if (ap->flags & ATA_FLAG_EH_PENDING) { if (--repeat_cnt) { ata_port_printk(ap, KERN_INFO, "EH pending after completion, " "repeating EH (cnt=%d)\n", repeat_cnt); - spin_unlock_irqrestore(hs_lock, flags); + spin_unlock_irqrestore(ap_lock, flags); goto repeat; } ata_port_printk(ap, KERN_ERR, "EH pending after %d " @@ -270,14 +270,14 @@ void ata_scsi_error(struct Scsi_Host *host) /* this run is complete, make sure EH info is clear */ memset(&ap->eh_info, 0, sizeof(ap->eh_info)); - /* Clear host_eh_scheduled while holding hs_lock such + /* Clear host_eh_scheduled while holding ap_lock such * that if exception occurs after this point but * before EH completion, SCSI midlayer will * re-initiate EH. */ host->host_eh_scheduled = 0; - spin_unlock_irqrestore(hs_lock, flags); + spin_unlock_irqrestore(ap_lock, flags); } else { WARN_ON(ata_qc_from_tag(ap, ap->active_tag) == NULL); ap->ops->eng_timeout(ap); @@ -289,7 +289,7 @@ void ata_scsi_error(struct Scsi_Host *host) scsi_eh_flush_done_q(&ap->eh_done_q); /* clean up */ - spin_lock_irqsave(hs_lock, flags); + spin_lock_irqsave(ap_lock, flags); if (ap->flags & ATA_FLAG_LOADING) { ap->flags &= ~ATA_FLAG_LOADING; @@ -306,7 +306,7 @@ void ata_scsi_error(struct Scsi_Host *host) ap->flags &= ~ATA_FLAG_EH_IN_PROGRESS; wake_up_all(&ap->eh_wait_q); - spin_unlock_irqrestore(hs_lock, flags); + spin_unlock_irqrestore(ap_lock, flags); DPRINTK("EXIT\n"); } @@ -326,17 +326,17 @@ void ata_port_wait_eh(struct ata_port *ap) DEFINE_WAIT(wait); retry: - spin_lock_irqsave(&ap->host_set->lock, flags); + spin_lock_irqsave(ap->lock, flags); while (ap->flags & (ATA_FLAG_EH_PENDING | ATA_FLAG_EH_IN_PROGRESS)) { prepare_to_wait(&ap->eh_wait_q, &wait, TASK_UNINTERRUPTIBLE); - spin_unlock_irqrestore(&ap->host_set->lock, flags); + spin_unlock_irqrestore(ap->lock, flags); schedule(); - spin_lock_irqsave(&ap->host_set->lock, flags); + spin_lock_irqsave(ap->lock, flags); } finish_wait(&ap->eh_wait_q, &wait); - spin_unlock_irqrestore(&ap->host_set->lock, flags); + spin_unlock_irqrestore(ap->lock, flags); /* make sure SCSI EH is complete */ if (scsi_host_in_recovery(ap->host)) { @@ -368,7 +368,6 @@ void ata_port_wait_eh(struct ata_port *ap) static void ata_qc_timeout(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; - struct ata_host_set *host_set = ap->host_set; u8 host_stat = 0, drv_stat; unsigned long flags; @@ -376,7 +375,7 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc) ap->hsm_task_state = HSM_ST_IDLE; - spin_lock_irqsave(&host_set->lock, flags); + spin_lock_irqsave(ap->lock, flags); switch (qc->tf.protocol) { @@ -405,7 +404,7 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc) break; } - spin_unlock_irqrestore(&host_set->lock, flags); + spin_unlock_irqrestore(ap->lock, flags); ata_eh_qc_complete(qc); @@ -592,9 +591,9 @@ void ata_eh_freeze_port(struct ata_port *ap) if (!ap->ops->error_handler) return; - spin_lock_irqsave(&ap->host_set->lock, flags); + spin_lock_irqsave(ap->lock, flags); __ata_port_freeze(ap); - spin_unlock_irqrestore(&ap->host_set->lock, flags); + spin_unlock_irqrestore(ap->lock, flags); } /** @@ -613,14 +612,14 @@ void ata_eh_thaw_port(struct ata_port *ap) if (!ap->ops->error_handler) return; - spin_lock_irqsave(&ap->host_set->lock, flags); + spin_lock_irqsave(ap->lock, flags); ap->flags &= ~ATA_FLAG_FROZEN; if (ap->ops->thaw) ap->ops->thaw(ap); - spin_unlock_irqrestore(&ap->host_set->lock, flags); + spin_unlock_irqrestore(ap->lock, flags); DPRINTK("ata%u port thawed\n", ap->id); } @@ -636,11 +635,11 @@ static void __ata_eh_qc_complete(struct ata_queued_cmd *qc) struct scsi_cmnd *scmd = qc->scsicmd; unsigned long flags; - spin_lock_irqsave(&ap->host_set->lock, flags); + spin_lock_irqsave(ap->lock, flags); qc->scsidone = ata_eh_scsidone; __ata_qc_complete(qc); WARN_ON(ata_tag_valid(qc->tag)); - spin_unlock_irqrestore(&ap->host_set->lock, flags); + spin_unlock_irqrestore(ap->lock, flags); scsi_eh_finish_cmd(scmd, &ap->eh_done_q); } @@ -694,7 +693,7 @@ static void ata_eh_detach_dev(struct ata_device *dev) ata_dev_disable(dev); - spin_lock_irqsave(&ap->host_set->lock, flags); + spin_lock_irqsave(ap->lock, flags); dev->flags &= ~ATA_DFLAG_DETACH; @@ -703,7 +702,7 @@ static void ata_eh_detach_dev(struct ata_device *dev) ap->flags |= ATA_FLAG_SCSI_HOTPLUG; } - spin_unlock_irqrestore(&ap->host_set->lock, flags); + spin_unlock_irqrestore(ap->lock, flags); } static void ata_eh_clear_action(struct ata_device *dev, @@ -749,10 +748,10 @@ static void ata_eh_about_to_do(struct ata_port *ap, struct ata_device *dev, { unsigned long flags; - spin_lock_irqsave(&ap->host_set->lock, flags); + spin_lock_irqsave(ap->lock, flags); ata_eh_clear_action(dev, &ap->eh_info, action); ap->flags |= ATA_FLAG_RECOVERED; - spin_unlock_irqrestore(&ap->host_set->lock, flags); + spin_unlock_irqrestore(ap->lock, flags); } /** @@ -1625,9 +1624,9 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap, break; } - spin_lock_irqsave(&ap->host_set->lock, flags); + spin_lock_irqsave(ap->lock, flags); ap->flags |= ATA_FLAG_SCSI_HOTPLUG; - spin_unlock_irqrestore(&ap->host_set->lock, flags); + spin_unlock_irqrestore(ap->lock, flags); } } diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 9698949fa52..d86abed6200 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -752,7 +752,7 @@ void ata_scsi_slave_destroy(struct scsi_device *sdev) if (!ap->ops->error_handler) return; - spin_lock_irqsave(&ap->host_set->lock, flags); + spin_lock_irqsave(ap->lock, flags); dev = __ata_scsi_find_dev(ap, sdev); if (dev && dev->sdev) { /* SCSI device already in CANCEL state, no need to offline it */ @@ -760,7 +760,7 @@ void ata_scsi_slave_destroy(struct scsi_device *sdev) dev->flags |= ATA_DFLAG_DETACH; ata_port_schedule_eh(ap); } - spin_unlock_irqrestore(&ap->host_set->lock, flags); + spin_unlock_irqrestore(ap->lock, flags); } /** @@ -2684,7 +2684,7 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) ap = ata_shost_to_port(shost); spin_unlock(shost->host_lock); - spin_lock(&ap->host_set->lock); + spin_lock(ap->lock); ata_scsi_dump_cdb(ap, cmd); @@ -2696,7 +2696,7 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) done(cmd); } - spin_unlock(&ap->host_set->lock); + spin_unlock(ap->lock); spin_lock(shost->host_lock); return rc; } @@ -2858,7 +2858,7 @@ static void ata_scsi_remove_dev(struct ata_device *dev) * increments reference counts regardless of device state. */ mutex_lock(&ap->host->scan_mutex); - spin_lock_irqsave(&ap->host_set->lock, flags); + spin_lock_irqsave(ap->lock, flags); /* clearing dev->sdev is protected by host_set lock */ sdev = dev->sdev; @@ -2882,7 +2882,7 @@ static void ata_scsi_remove_dev(struct ata_device *dev) } } - spin_unlock_irqrestore(&ap->host_set->lock, flags); + spin_unlock_irqrestore(ap->lock, flags); mutex_unlock(&ap->host->scan_mutex); if (sdev) { @@ -2926,9 +2926,9 @@ void ata_scsi_hotplug(void *data) if (!(dev->flags & ATA_DFLAG_DETACHED)) continue; - spin_lock_irqsave(&ap->host_set->lock, flags); + spin_lock_irqsave(ap->lock, flags); dev->flags &= ~ATA_DFLAG_DETACHED; - spin_unlock_irqrestore(&ap->host_set->lock, flags); + spin_unlock_irqrestore(ap->lock, flags); ata_scsi_remove_dev(dev); } @@ -2981,7 +2981,7 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel, (lun != SCAN_WILD_CARD && lun != 0)) return -EINVAL; - spin_lock_irqsave(&ap->host_set->lock, flags); + spin_lock_irqsave(ap->lock, flags); if (id == SCAN_WILD_CARD) { ap->eh_info.probe_mask |= (1 << ATA_MAX_DEVICES) - 1; @@ -2999,7 +2999,7 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel, if (rc == 0) ata_port_schedule_eh(ap); - spin_unlock_irqrestore(&ap->host_set->lock, flags); + spin_unlock_irqrestore(ap->lock, flags); return rc; } diff --git a/include/linux/libata.h b/include/linux/libata.h index 6b3c3af2c75..20b1cf527c6 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -483,6 +483,7 @@ struct ata_eh_context { struct ata_port { struct Scsi_Host *host; /* our co-allocated scsi host */ const struct ata_port_operations *ops; + spinlock_t *lock; unsigned long flags; /* ATA_FLAG_xxx */ unsigned int id; /* unique id req'd by scsi midlyr */ unsigned int port_no; /* unique port #; from zero */ -- cgit v1.2.3 From 99ba9e093d058f6dff54f475136018e2e281d50f Mon Sep 17 00:00:00 2001 From: Brian King Date: Mon, 12 Jun 2006 14:54:17 -0500 Subject: [PATCH] libata: Add ata_scsi_dev_disabled Separate out parts of ata_scsi_find_dev to be reused in future SAS/SATA patches. Acked-by: Jeff Garzik Signed-off-by: Brian King Signed-off-by: Jeff Garzik --- drivers/scsi/libata-scsi.c | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index d86abed6200..93d18a74c40 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -2373,6 +2373,36 @@ static struct ata_device * __ata_scsi_find_dev(struct ata_port *ap, return ata_find_dev(ap, scsidev->id); } +/** + * ata_scsi_dev_enabled - determine if device is enabled + * @dev: ATA device + * + * Determine if commands should be sent to the specified device. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + * + * RETURNS: + * 0 if commands are not allowed / 1 if commands are allowed + */ + +static int ata_scsi_dev_enabled(struct ata_device *dev) +{ + if (unlikely(!ata_dev_enabled(dev))) + return 0; + + if (!atapi_enabled || (dev->ap->flags & ATA_FLAG_NO_ATAPI)) { + if (unlikely(dev->class == ATA_DEV_ATAPI)) { + ata_dev_printk(dev, KERN_WARNING, + "WARNING: ATAPI is %s, device ignored.\n", + atapi_enabled ? "not supported with this driver" : "disabled"); + return 0; + } + } + + return 1; +} + /** * ata_scsi_find_dev - lookup ata_device from scsi_cmnd * @ap: ATA port to which the device is attached @@ -2394,18 +2424,9 @@ ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev) { struct ata_device *dev = __ata_scsi_find_dev(ap, scsidev); - if (unlikely(!dev || !ata_dev_enabled(dev))) + if (unlikely(!dev || !ata_scsi_dev_enabled(dev))) return NULL; - if (!atapi_enabled || (ap->flags & ATA_FLAG_NO_ATAPI)) { - if (unlikely(dev->class == ATA_DEV_ATAPI)) { - ata_dev_printk(dev, KERN_WARNING, - "WARNING: ATAPI is %s, device ignored.\n", - atapi_enabled ? "not supported with this driver" : "disabled"); - return NULL; - } - } - return dev; } -- cgit v1.2.3 From 0517587e5896cef1d5f99d3b24f5f2ca15d952ad Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 22 Jun 2006 13:29:52 -0700 Subject: [PATCH] USB: get USB suspend to work again Yeah, it's a hack, but it is only temporary until Alan's patches reworking this area make it in. We really should not care what devices below us are doing, especially when we do not really know what type of devices they are. This patch relies on the fact that the endpoint devices do not have a driver assigned to us. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/usb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 51531075130..fb488c8a860 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -991,6 +991,8 @@ void usb_buffer_unmap_sg (struct usb_device *dev, unsigned pipe, static int verify_suspended(struct device *dev, void *unused) { + if (dev->driver == NULL) + return 0; return (dev->power.power_state.event == PM_EVENT_ON) ? -EBUSY : 0; } -- cgit v1.2.3 From 5d9fd169c9fbdaecdc430431e59bf94ff40b93d3 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 22 Jun 2006 17:17:32 -0700 Subject: [PATCH] Driver core: fix locking issues with the devices that are attached to classes Doh, that was foolish... Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index d0f84ff7877..27c2176895d 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -356,6 +356,13 @@ int device_add(struct device *dev) if (parent) klist_add_tail(&dev->knode_parent, &parent->klist_children); + if (dev->class) { + /* tie the class to the device */ + down(&dev->class->sem); + list_add_tail(&dev->node, &dev->class->devices); + up(&dev->class->sem); + } + /* notify platform of device entry */ if (platform_notify) platform_notify(dev); @@ -455,6 +462,9 @@ void device_del(struct device * dev) sysfs_remove_link(&dev->kobj, "device"); sysfs_remove_link(&dev->parent->kobj, class_name); kfree(class_name); + down(&dev->class->sem); + list_del_init(&dev->node); + up(&dev->class->sem); } device_remove_file(dev, &dev->uevent_attr); @@ -601,11 +611,6 @@ struct device *device_create(struct class *class, struct device *parent, if (retval) goto error; - /* tie the class to the device */ - down(&class->sem); - list_add_tail(&dev->node, &class->devices); - up(&class->sem); - return dev; error: @@ -636,9 +641,7 @@ void device_destroy(struct class *class, dev_t devt) } up(&class->sem); - if (dev) { - list_del_init(&dev->node); + if (dev) device_unregister(dev); - } } EXPORT_SYMBOL_GPL(device_destroy); -- cgit v1.2.3 From 0dd4b21f517e138ea113db255645fbae1bf5eef3 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Fri, 23 Jun 2006 02:29:08 -0400 Subject: [libata] conversion to new debug scheme, part 1 of $N The first 25% of libata-core.c converted to the new debugging scheme. Signed-off-by: (with addition of ATA_MSG_WARN to standard msg_enable by me) Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 73 +++++++++++++++++++++++++++++----------------- 1 file changed, 47 insertions(+), 26 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 24d340aeb51..6c66877be2b 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -418,7 +418,7 @@ static const char *sata_spd_string(unsigned int spd) void ata_dev_disable(struct ata_device *dev) { - if (ata_dev_enabled(dev)) { + if (ata_dev_enabled(dev) && ata_msg_drv(dev->ap)) { ata_dev_printk(dev, KERN_WARNING, "disabled\n"); dev->class++; } @@ -777,8 +777,11 @@ void ata_std_dev_select (struct ata_port *ap, unsigned int device) void ata_dev_select(struct ata_port *ap, unsigned int device, unsigned int wait, unsigned int can_sleep) { - VPRINTK("ENTER, ata%u: device %u, wait %u\n", - ap->id, device, wait); + if (ata_msg_probe(ap)) { + ata_port_printk(ap, KERN_INFO, "ata_dev_select: ENTER, ata%u: " + "device %u, wait %u\n", + ap->id, device, wait); + } if (wait) ata_wait_idle(ap); @@ -946,7 +949,8 @@ void ata_port_flush_task(struct ata_port *ap) * Cancel and flush. */ if (!cancel_delayed_work(&ap->port_task)) { - DPRINTK("flush #2\n"); + if (ata_msg_ctl(ap)) + ata_port_printk(ap, KERN_DEBUG, "%s: flush #2\n", __FUNCTION__); flush_workqueue(ata_wq); } @@ -954,7 +958,8 @@ void ata_port_flush_task(struct ata_port *ap) ap->flags &= ~ATA_FLAG_FLUSH_PORT_TASK; spin_unlock_irqrestore(ap->lock, flags); - DPRINTK("EXIT\n"); + if (ata_msg_ctl(ap)) + ata_port_printk(ap, KERN_DEBUG, "%s: EXIT\n", __FUNCTION__); } void ata_qc_complete_internal(struct ata_queued_cmd *qc) @@ -1074,7 +1079,8 @@ unsigned ata_exec_internal(struct ata_device *dev, else ata_qc_complete(qc); - ata_dev_printk(dev, KERN_WARNING, + if (ata_msg_warn(ap)) + ata_dev_printk(dev, KERN_WARNING, "qc timeout (cmd 0x%x)\n", command); } @@ -1086,7 +1092,9 @@ unsigned ata_exec_internal(struct ata_device *dev, ap->ops->post_internal_cmd(qc); if (qc->flags & ATA_QCFLAG_FAILED && !qc->err_mask) { - ata_dev_printk(dev, KERN_WARNING, "zero err_mask for failed " + if (ata_msg_warn(ap)) + ata_dev_printk(dev, KERN_WARNING, + "zero err_mask for failed " "internal command, assuming AC_ERR_OTHER\n"); qc->err_mask |= AC_ERR_OTHER; } @@ -1184,7 +1192,9 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, const char *reason; int rc; - DPRINTK("ENTER, host %u, dev %u\n", ap->id, dev->devno); + if (ata_msg_ctl(ap)) + ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER, host %u, dev %u\n", + __FUNCTION__, ap->id, dev->devno); ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */ @@ -1253,7 +1263,8 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, return 0; err_out: - ata_dev_printk(dev, KERN_WARNING, "failed to IDENTIFY " + if (ata_msg_warn(ap)) + ata_dev_printk(dev, KERN_WARNING, "failed to IDENTIFY " "(%s, err_mask=0x%x)\n", reason, err_mask); return rc; } @@ -1306,18 +1317,21 @@ int ata_dev_configure(struct ata_device *dev, int print_info) unsigned int xfer_mask; int i, rc; - if (!ata_dev_enabled(dev)) { - DPRINTK("ENTER/EXIT (host %u, dev %u) -- nodev\n", - ap->id, dev->devno); + if (!ata_dev_enabled(dev) && ata_msg_info(ap)) { + ata_dev_printk(dev, KERN_INFO, "%s: ENTER/EXIT (host %u, dev %u) -- nodev\n", + __FUNCTION__, ap->id, dev->devno); return 0; } - DPRINTK("ENTER, host %u, dev %u\n", ap->id, dev->devno); + if (ata_msg_probe(ap)) + ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER, host %u, dev %u\n", + __FUNCTION__, ap->id, dev->devno); /* print device capabilities */ - if (print_info) - ata_dev_printk(dev, KERN_DEBUG, "cfg 49:%04x 82:%04x 83:%04x " + if (ata_msg_probe(ap)) + ata_dev_printk(dev, KERN_DEBUG, "%s: cfg 49:%04x 82:%04x 83:%04x " "84:%04x 85:%04x 86:%04x 87:%04x 88:%04x\n", + __FUNCTION__, id[49], id[82], id[83], id[84], id[85], id[86], id[87], id[88]); @@ -1337,7 +1351,8 @@ int ata_dev_configure(struct ata_device *dev, int print_info) /* find max transfer mode; for printk only */ xfer_mask = ata_id_xfermask(id); - ata_dump_id(id); + if (ata_msg_probe(ap)) + ata_dump_id(id); /* ATA-specific feature tests */ if (dev->class == ATA_DEV_ATA) { @@ -1358,7 +1373,7 @@ int ata_dev_configure(struct ata_device *dev, int print_info) ata_dev_config_ncq(dev, ncq_desc, sizeof(ncq_desc)); /* print device info to dmesg */ - if (print_info) + if (ata_msg_info(ap)) ata_dev_printk(dev, KERN_INFO, "ATA-%d, " "max %s, %Lu sectors: %s %s\n", ata_id_major_version(id), @@ -1381,7 +1396,7 @@ int ata_dev_configure(struct ata_device *dev, int print_info) } /* print device info to dmesg */ - if (print_info) + if (ata_msg_info(ap)) ata_dev_printk(dev, KERN_INFO, "ATA-%d, " "max %s, %Lu sectors: CHS %u/%u/%u\n", ata_id_major_version(id), @@ -1392,7 +1407,8 @@ int ata_dev_configure(struct ata_device *dev, int print_info) if (dev->id[59] & 0x100) { dev->multi_count = dev->id[59] & 0xff; - DPRINTK("ata%u: dev %u multi count %u\n", + if (ata_msg_info(ap)) + ata_dev_printk(dev, KERN_INFO, "ata%u: dev %u multi count %u\n", ap->id, dev->devno, dev->multi_count); } @@ -1405,8 +1421,9 @@ int ata_dev_configure(struct ata_device *dev, int print_info) rc = atapi_cdb_len(id); if ((rc < 12) || (rc > ATAPI_CDB_LEN)) { - ata_dev_printk(dev, KERN_WARNING, - "unsupported CDB len\n"); + if (ata_msg_warn(ap)) + ata_dev_printk(dev, KERN_WARNING, + "unsupported CDB len\n"); rc = -EINVAL; goto err_out_nosup; } @@ -1418,7 +1435,7 @@ int ata_dev_configure(struct ata_device *dev, int print_info) } /* print device info to dmesg */ - if (print_info) + if (ata_msg_info(ap)) ata_dev_printk(dev, KERN_INFO, "ATAPI, max %s%s\n", ata_mode_string(xfer_mask), cdb_intr_string); @@ -1432,7 +1449,7 @@ int ata_dev_configure(struct ata_device *dev, int print_info) /* limit bridge transfers to udma5, 200 sectors */ if (ata_dev_knobble(dev)) { - if (print_info) + if (ata_msg_info(ap)) ata_dev_printk(dev, KERN_INFO, "applying bridge limits\n"); dev->udma_mask &= ATA_UDMA5; @@ -1442,11 +1459,15 @@ int ata_dev_configure(struct ata_device *dev, int print_info) if (ap->ops->dev_config) ap->ops->dev_config(ap, dev); - DPRINTK("EXIT, drv_stat = 0x%x\n", ata_chk_status(ap)); + if (ata_msg_probe(ap)) + ata_dev_printk(dev, KERN_DEBUG, "%s: EXIT, drv_stat = 0x%x\n", + __FUNCTION__, ata_chk_status(ap)); return 0; err_out_nosup: - DPRINTK("EXIT, err\n"); + if (ata_msg_probe(ap)) + ata_dev_printk(dev, KERN_DEBUG, + "%s: EXIT, err\n", __FUNCTION__); return rc; } @@ -5192,7 +5213,7 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host, #elif defined(ATA_DEBUG) ap->msg_enable = ATA_MSG_DRV | ATA_MSG_INFO | ATA_MSG_CTL | ATA_MSG_WARN | ATA_MSG_ERR; #else - ap->msg_enable = ATA_MSG_DRV | ATA_MSG_ERR; + ap->msg_enable = ATA_MSG_DRV | ATA_MSG_ERR | ATA_MSG_WARN; #endif INIT_WORK(&ap->port_task, NULL, NULL); -- cgit v1.2.3 From 5b057c6b1a25d57edf2b4d1e956e50936480a9ff Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Fri, 23 Jun 2006 02:06:41 -0700 Subject: [NET]: Avoid allocating skb in skb_pad First of all it is unnecessary to allocate a new skb in skb_pad since the existing one is not shared. More importantly, our hard_start_xmit interface does not allow a new skb to be allocated since that breaks requeueing. This patch uses pskb_expand_head to expand the existing skb and linearize it if needed. Actually, someone should sift through every instance of skb_pad on a non-linear skb as they do not fit the reasons why this was originally created. Incidentally, this fixes a minor bug when the skb is cloned (tcpdump, TCP, etc.). As it is skb_pad will simply write over a cloned skb. Because of the position of the write it is unlikely to cause problems but still it's best if we don't do it. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- drivers/net/3c527.c | 3 +-- drivers/net/82596.c | 3 +-- drivers/net/a2065.c | 3 +-- drivers/net/ariadne.c | 3 +-- drivers/net/arm/ether1.c | 3 +-- drivers/net/arm/ether3.c | 3 +-- drivers/net/atarilance.c | 3 +-- drivers/net/cassini.c | 3 +-- drivers/net/declance.c | 3 +-- drivers/net/depca.c | 7 ++----- drivers/net/eepro.c | 3 +-- drivers/net/eexpress.c | 3 +-- drivers/net/epic100.c | 7 ++----- drivers/net/eth16i.c | 3 +-- drivers/net/hp100.c | 7 ++----- drivers/net/lance.c | 3 +-- drivers/net/lasi_82596.c | 3 +-- drivers/net/lp486e.c | 3 +-- drivers/net/myri10ge/myri10ge.c | 3 +-- drivers/net/pcmcia/fmvj18x_cs.c | 3 +-- drivers/net/pcmcia/xirc2ps_cs.c | 3 +-- drivers/net/r8169.c | 3 +-- drivers/net/seeq8005.c | 3 +-- drivers/net/sis190.c | 3 +-- drivers/net/sk98lin/skge.c | 2 +- drivers/net/skge.c | 3 +-- drivers/net/smc9194.c | 3 +-- drivers/net/sonic.c | 3 +-- drivers/net/starfire.c | 3 +-- drivers/net/via-rhine.c | 7 ++----- drivers/net/wireless/ray_cs.c | 3 +-- drivers/net/wireless/wavelan_cs.c | 7 ++----- drivers/net/yellowfin.c | 12 +++++------- drivers/net/znet.c | 3 +-- include/linux/skbuff.h | 11 +++++------ net/core/skbuff.c | 36 ++++++++++++++++++++++++++---------- 36 files changed, 74 insertions(+), 103 deletions(-) diff --git a/drivers/net/3c527.c b/drivers/net/3c527.c index 1b1cb002607..157eda57392 100644 --- a/drivers/net/3c527.c +++ b/drivers/net/3c527.c @@ -1031,8 +1031,7 @@ static int mc32_send_packet(struct sk_buff *skb, struct net_device *dev) return 1; } - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) { + if (skb_padto(skb, ETH_ZLEN)) { netif_wake_queue(dev); return 0; } diff --git a/drivers/net/82596.c b/drivers/net/82596.c index da0c878dcba..8a9f7d61b9b 100644 --- a/drivers/net/82596.c +++ b/drivers/net/82596.c @@ -1070,8 +1070,7 @@ static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev) skb->len, (unsigned int)skb->data)); if (skb->len < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) + if (skb_padto(skb, ETH_ZLEN)) return 0; length = ETH_ZLEN; } diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c index 79bb56b8dce..71165ac0257 100644 --- a/drivers/net/a2065.c +++ b/drivers/net/a2065.c @@ -573,8 +573,7 @@ static int lance_start_xmit (struct sk_buff *skb, struct net_device *dev) if (len < ETH_ZLEN) { len = ETH_ZLEN; - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) + if (skb_padto(skb, ETH_ZLEN)) return 0; } diff --git a/drivers/net/ariadne.c b/drivers/net/ariadne.c index d1b6b1f794e..a9bb7a4aff9 100644 --- a/drivers/net/ariadne.c +++ b/drivers/net/ariadne.c @@ -607,8 +607,7 @@ static int ariadne_start_xmit(struct sk_buff *skb, struct net_device *dev) /* FIXME: is the 79C960 new enough to do its own padding right ? */ if (skb->len < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) + if (skb_padto(skb, ETH_ZLEN)) return 0; len = ETH_ZLEN; } diff --git a/drivers/net/arm/ether1.c b/drivers/net/arm/ether1.c index 36475eb2727..312955d07b2 100644 --- a/drivers/net/arm/ether1.c +++ b/drivers/net/arm/ether1.c @@ -700,8 +700,7 @@ ether1_sendpacket (struct sk_buff *skb, struct net_device *dev) } if (skb->len < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) + if (skb_padto(skb, ETH_ZLEN)) goto out; } diff --git a/drivers/net/arm/ether3.c b/drivers/net/arm/ether3.c index f1d5b1027ff..081074180e6 100644 --- a/drivers/net/arm/ether3.c +++ b/drivers/net/arm/ether3.c @@ -518,8 +518,7 @@ ether3_sendpacket(struct sk_buff *skb, struct net_device *dev) length = (length + 1) & ~1; if (length != skb->len) { - skb = skb_padto(skb, length); - if (skb == NULL) + if (skb_padto(skb, length)) goto out; } diff --git a/drivers/net/atarilance.c b/drivers/net/atarilance.c index 442b2cbeb58..91783a8008b 100644 --- a/drivers/net/atarilance.c +++ b/drivers/net/atarilance.c @@ -804,8 +804,7 @@ static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev ) ++len; if (len > skb->len) { - skb = skb_padto(skb, len); - if (skb == NULL) + if (skb_padto(skb, len)) return 0; } diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c index 39f36aa05aa..565a54f1d06 100644 --- a/drivers/net/cassini.c +++ b/drivers/net/cassini.c @@ -2915,8 +2915,7 @@ static int cas_start_xmit(struct sk_buff *skb, struct net_device *dev) */ static int ring; - skb = skb_padto(skb, cp->min_frame_size); - if (!skb) + if (skb_padto(skb, cp->min_frame_size)) return 0; /* XXX: we need some higher-level QoS hooks to steer packets to diff --git a/drivers/net/declance.c b/drivers/net/declance.c index f130bdab3fd..d3d958e7ac5 100644 --- a/drivers/net/declance.c +++ b/drivers/net/declance.c @@ -885,8 +885,7 @@ static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev) len = skblen; if (len < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) + if (skb_padto(skb, ETH_ZLEN)) return 0; len = ETH_ZLEN; } diff --git a/drivers/net/depca.c b/drivers/net/depca.c index 0941d40f046..e946c43d3b1 100644 --- a/drivers/net/depca.c +++ b/drivers/net/depca.c @@ -938,11 +938,8 @@ static int depca_start_xmit(struct sk_buff *skb, struct net_device *dev) if (skb->len < 1) goto out; - if (skb->len < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) - goto out; - } + if (skb_padto(skb, ETH_ZLEN)) + goto out; netif_stop_queue(dev); diff --git a/drivers/net/eepro.c b/drivers/net/eepro.c index a806dfe54d2..e70f172699d 100644 --- a/drivers/net/eepro.c +++ b/drivers/net/eepro.c @@ -1154,8 +1154,7 @@ static int eepro_send_packet(struct sk_buff *skb, struct net_device *dev) printk(KERN_DEBUG "%s: entering eepro_send_packet routine.\n", dev->name); if (length < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) + if (skb_padto(skb, ETH_ZLEN)) return 0; length = ETH_ZLEN; } diff --git a/drivers/net/eexpress.c b/drivers/net/eexpress.c index 82bd356e4f3..a74b2071575 100644 --- a/drivers/net/eexpress.c +++ b/drivers/net/eexpress.c @@ -677,8 +677,7 @@ static int eexp_xmit(struct sk_buff *buf, struct net_device *dev) #endif if (buf->len < ETH_ZLEN) { - buf = skb_padto(buf, ETH_ZLEN); - if (buf == NULL) + if (skb_padto(buf, ETH_ZLEN)) return 0; length = ETH_ZLEN; } diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c index 8d680ce600d..724d7dc35fa 100644 --- a/drivers/net/epic100.c +++ b/drivers/net/epic100.c @@ -1027,11 +1027,8 @@ static int epic_start_xmit(struct sk_buff *skb, struct net_device *dev) u32 ctrl_word; unsigned long flags; - if (skb->len < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) - return 0; - } + if (skb_padto(skb, ETH_ZLEN)) + return 0; /* Caution: the write order is important here, set the field with the "ownership" bit last. */ diff --git a/drivers/net/eth16i.c b/drivers/net/eth16i.c index b67545be2ca..4bf76f86d8e 100644 --- a/drivers/net/eth16i.c +++ b/drivers/net/eth16i.c @@ -1064,8 +1064,7 @@ static int eth16i_tx(struct sk_buff *skb, struct net_device *dev) unsigned long flags; if (length < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) + if (skb_padto(skb, ETH_ZLEN)) return 0; length = ETH_ZLEN; } diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c index 247c8ca8603..dd1dc32dc98 100644 --- a/drivers/net/hp100.c +++ b/drivers/net/hp100.c @@ -1487,11 +1487,8 @@ static int hp100_start_xmit_bm(struct sk_buff *skb, struct net_device *dev) if (skb->len <= 0) return 0; - if (skb->len < ETH_ZLEN && lp->chip == HP100_CHIPID_SHASTA) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) - return 0; - } + if (lp->chip == HP100_CHIPID_SHASTA && skb_padto(skb, ETH_ZLEN)) + return 0; /* Get Tx ring tail pointer */ if (lp->txrtail->next == lp->txrhead) { diff --git a/drivers/net/lance.c b/drivers/net/lance.c index bb5ad479210..c1c3452c90c 100644 --- a/drivers/net/lance.c +++ b/drivers/net/lance.c @@ -968,8 +968,7 @@ static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev) /* The old LANCE chips doesn't automatically pad buffers to min. size. */ if (chip_table[lp->chip_version].flags & LANCE_MUST_PAD) { if (skb->len < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) + if (skb_padto(skb, ETH_ZLEN)) goto out; lp->tx_ring[entry].length = -ETH_ZLEN; } diff --git a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c index 957888de3d7..1ab09447baa 100644 --- a/drivers/net/lasi_82596.c +++ b/drivers/net/lasi_82596.c @@ -1083,8 +1083,7 @@ static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev) skb->len, skb->data)); if (length < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) + if (skb_padto(skb, ETH_ZLEN)) return 0; length = ETH_ZLEN; } diff --git a/drivers/net/lp486e.c b/drivers/net/lp486e.c index 94d5ea1ce8b..bf3f343ae71 100644 --- a/drivers/net/lp486e.c +++ b/drivers/net/lp486e.c @@ -877,8 +877,7 @@ static int i596_start_xmit (struct sk_buff *skb, struct net_device *dev) { length = skb->len; if (length < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) + if (skb_padto(skb, ETH_ZLEN)) return 0; length = ETH_ZLEN; } diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 5a74f63618b..b983e1e0434 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -1939,8 +1939,7 @@ again: /* pad frames to at least ETH_ZLEN bytes */ if (unlikely(skb->len < ETH_ZLEN)) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) { + if (skb_padto(skb, ETH_ZLEN)) { /* The packet is gone, so we must * return 0 */ mgp->stats.tx_dropped += 1; diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index 09b11761cdf..ea93b8f1860 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c @@ -831,8 +831,7 @@ static int fjn_start_xmit(struct sk_buff *skb, struct net_device *dev) if (length < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) + if (skb_padto(skb, ETH_ZLEN)) return 0; length = ETH_ZLEN; } diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index e80d1e3aec6..9bae77ce131 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -1374,8 +1374,7 @@ do_start_xmit(struct sk_buff *skb, struct net_device *dev) */ if (pktlen < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) + if (skb_padto(skb, ETH_ZLEN)) return 0; pktlen = ETH_ZLEN; } diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 9945cc6b8d9..985afe0e627 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -2222,8 +2222,7 @@ static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev) len = skb->len; if (unlikely(len < ETH_ZLEN)) { - skb = skb_padto(skb, ETH_ZLEN); - if (!skb) + if (skb_padto(skb, ETH_ZLEN)) goto err_update_stats; len = ETH_ZLEN; } diff --git a/drivers/net/seeq8005.c b/drivers/net/seeq8005.c index bcef03feb2f..efd0f235020 100644 --- a/drivers/net/seeq8005.c +++ b/drivers/net/seeq8005.c @@ -396,8 +396,7 @@ static int seeq8005_send_packet(struct sk_buff *skb, struct net_device *dev) unsigned char *buf; if (length < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) + if (skb_padto(skb, ETH_ZLEN)) return 0; length = ETH_ZLEN; } diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c index 31dd3f036fa..df39f344765 100644 --- a/drivers/net/sis190.c +++ b/drivers/net/sis190.c @@ -1156,8 +1156,7 @@ static int sis190_start_xmit(struct sk_buff *skb, struct net_device *dev) dma_addr_t mapping; if (unlikely(skb->len < ETH_ZLEN)) { - skb = skb_padto(skb, ETH_ZLEN); - if (!skb) { + if (skb_padto(skb, ETH_ZLEN)) { tp->stats.tx_dropped++; goto out; } diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c index 38a26df4095..f3efbd177ae 100644 --- a/drivers/net/sk98lin/skge.c +++ b/drivers/net/sk98lin/skge.c @@ -1525,7 +1525,7 @@ struct sk_buff *pMessage) /* pointer to send-message */ ** This is to resolve faulty padding by the HW with 0xaa bytes. */ if (BytesSend < C_LEN_ETHERNET_MINSIZE) { - if ((pMessage = skb_padto(pMessage, C_LEN_ETHERNET_MINSIZE)) == NULL) { + if (skb_padto(pMessage, C_LEN_ETHERNET_MINSIZE)) { spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags); return 0; } diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 536dd1cf7f7..19a4a16055d 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -2310,8 +2310,7 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev) u64 map; unsigned long flags; - skb = skb_padto(skb, ETH_ZLEN); - if (!skb) + if (skb_padto(skb, ETH_ZLEN)) return NETDEV_TX_OK; if (!spin_trylock_irqsave(&skge->tx_lock, flags)) diff --git a/drivers/net/smc9194.c b/drivers/net/smc9194.c index 6cf16f322ad..8b0321f1976 100644 --- a/drivers/net/smc9194.c +++ b/drivers/net/smc9194.c @@ -523,8 +523,7 @@ static int smc_wait_to_send_packet( struct sk_buff * skb, struct net_device * de length = skb->len; if (length < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) { + if (skb_padto(skb, ETH_ZLEN)) { netif_wake_queue(dev); return 0; } diff --git a/drivers/net/sonic.c b/drivers/net/sonic.c index 90b818a8de6..cab0dd95849 100644 --- a/drivers/net/sonic.c +++ b/drivers/net/sonic.c @@ -231,8 +231,7 @@ static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev) length = skb->len; if (length < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) + if (skb_padto(skb, ETH_ZLEN)) return 0; length = ETH_ZLEN; } diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index 9b7805be21d..c158eedc781 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c @@ -1349,8 +1349,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev) #if defined(ZEROCOPY) && defined(HAS_BROKEN_FIRMWARE) if (skb->ip_summed == CHECKSUM_HW) { - skb = skb_padto(skb, (skb->len + PADDING_MASK) & ~PADDING_MASK); - if (skb == NULL) + if (skb_padto(skb, (skb->len + PADDING_MASK) & ~PADDING_MASK)) return NETDEV_TX_OK; } #endif /* ZEROCOPY && HAS_BROKEN_FIRMWARE */ diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c index fdc21037f6d..c80a4f1d5f7 100644 --- a/drivers/net/via-rhine.c +++ b/drivers/net/via-rhine.c @@ -1284,11 +1284,8 @@ static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev) /* Calculate the next Tx descriptor entry. */ entry = rp->cur_tx % TX_RING_SIZE; - if (skb->len < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) - return 0; - } + if (skb_padto(skb, ETH_ZLEN)) + return 0; rp->tx_skbuff[entry] = skb; diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 879eb427607..a915fe6c6aa 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -924,8 +924,7 @@ static int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev) if (length < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) + if (skb_padto(skb, ETH_ZLEN)) return 0; length = ETH_ZLEN; } diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c index f7724eb2fa7..561250f73fd 100644 --- a/drivers/net/wireless/wavelan_cs.c +++ b/drivers/net/wireless/wavelan_cs.c @@ -3194,11 +3194,8 @@ wavelan_packet_xmit(struct sk_buff * skb, * and we don't have the Ethernet specific requirement of beeing * able to detect collisions, therefore in theory we don't really * need to pad. Jean II */ - if (skb->len < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) - return 0; - } + if (skb_padto(skb, ETH_ZLEN)) + return 0; wv_packet_write(dev, skb->data, skb->len); diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c index fd0f43b7db5..ecec8e5db78 100644 --- a/drivers/net/yellowfin.c +++ b/drivers/net/yellowfin.c @@ -862,13 +862,11 @@ static int yellowfin_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Fix GX chipset errata. */ if (cacheline_end > 24 || cacheline_end == 0) { len = skb->len + 32 - cacheline_end + 1; - if (len != skb->len) - skb = skb_padto(skb, len); - } - if (skb == NULL) { - yp->tx_skbuff[entry] = NULL; - netif_wake_queue(dev); - return 0; + if (skb_padto(skb, len)) { + yp->tx_skbuff[entry] = NULL; + netif_wake_queue(dev); + return 0; + } } } yp->tx_skbuff[entry] = skb; diff --git a/drivers/net/znet.c b/drivers/net/znet.c index 3ac047bc727..a7c089df66e 100644 --- a/drivers/net/znet.c +++ b/drivers/net/znet.c @@ -544,8 +544,7 @@ static int znet_send_packet(struct sk_buff *skb, struct net_device *dev) printk(KERN_DEBUG "%s: ZNet_send_packet.\n", dev->name); if (length < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) + if (skb_padto(skb, ETH_ZLEN)) return 0; length = ETH_ZLEN; } diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 66f8819f956..f8c7eb79a27 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -345,7 +345,7 @@ extern struct sk_buff *skb_realloc_headroom(struct sk_buff *skb, extern struct sk_buff *skb_copy_expand(const struct sk_buff *skb, int newheadroom, int newtailroom, gfp_t priority); -extern struct sk_buff * skb_pad(struct sk_buff *skb, int pad); +extern int skb_pad(struct sk_buff *skb, int pad); #define dev_kfree_skb(a) kfree_skb(a) extern void skb_over_panic(struct sk_buff *skb, int len, void *here); @@ -1122,16 +1122,15 @@ static inline int skb_cow(struct sk_buff *skb, unsigned int headroom) * * Pads up a buffer to ensure the trailing bytes exist and are * blanked. If the buffer already contains sufficient data it - * is untouched. Returns the buffer, which may be a replacement - * for the original, or NULL for out of memory - in which case - * the original buffer is still freed. + * is untouched. Otherwise it is extended. Returns zero on + * success. The skb is freed on error. */ -static inline struct sk_buff *skb_padto(struct sk_buff *skb, unsigned int len) +static inline int skb_padto(struct sk_buff *skb, unsigned int len) { unsigned int size = skb->len; if (likely(size >= len)) - return skb; + return 0; return skb_pad(skb, len-size); } diff --git a/net/core/skbuff.c b/net/core/skbuff.c index bb7210f4005..fe63d4efbd4 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -781,24 +781,40 @@ struct sk_buff *skb_copy_expand(const struct sk_buff *skb, * filled. Used by network drivers which may DMA or transfer data * beyond the buffer end onto the wire. * - * May return NULL in out of memory cases. + * May return error in out of memory cases. The skb is freed on error. */ -struct sk_buff *skb_pad(struct sk_buff *skb, int pad) +int skb_pad(struct sk_buff *skb, int pad) { - struct sk_buff *nskb; + int err; + int ntail; /* If the skbuff is non linear tailroom is always zero.. */ - if (skb_tailroom(skb) >= pad) { + if (!skb_cloned(skb) && skb_tailroom(skb) >= pad) { memset(skb->data+skb->len, 0, pad); - return skb; + return 0; } - - nskb = skb_copy_expand(skb, skb_headroom(skb), skb_tailroom(skb) + pad, GFP_ATOMIC); + + ntail = skb->data_len + pad - (skb->end - skb->tail); + if (likely(skb_cloned(skb) || ntail > 0)) { + err = pskb_expand_head(skb, 0, ntail, GFP_ATOMIC); + if (unlikely(err)) + goto free_skb; + } + + /* FIXME: The use of this function with non-linear skb's really needs + * to be audited. + */ + err = skb_linearize(skb); + if (unlikely(err)) + goto free_skb; + + memset(skb->data + skb->len, 0, pad); + return 0; + +free_skb: kfree_skb(skb); - if (nskb) - memset(nskb->data+nskb->len, 0, pad); - return nskb; + return err; } /* Trims skb to length len. It can change skb pointers. -- cgit v1.2.3 From 102128e3a27821bdcbacb10f4f2bba253f587ba4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Stelmach?= Date: Thu, 22 Jun 2006 01:37:19 -0700 Subject: [IPV6]: Fix source address selection. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two additional labels (RFC 3484, sec. 10.3) for IPv6 addreses are defined to make a distinction between global unicast addresses and Unique Local Addresses (fc00::/7, RFC 4193) and Teredo (2001::/32, RFC 4380). It is necessary to avoid attempts of connection that would either fail (eg. fec0:: to 2001:feed::) or be sub-optimal (2001:0:: to 2001:feed::). Signed-off-by: Åukasz Stelmach Signed-off-by: YOSHIFUJI Hideaki Signed-off-by: David S. Miller --- net/ipv6/addrconf.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index c2c26fa0943..6b361fc3e14 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -862,6 +862,8 @@ static int inline ipv6_saddr_label(const struct in6_addr *addr, int type) * 2002::/16 2 * ::/96 3 * ::ffff:0:0/96 4 + * fc00::/7 5 + * 2001::/32 6 */ if (type & IPV6_ADDR_LOOPBACK) return 0; @@ -869,8 +871,12 @@ static int inline ipv6_saddr_label(const struct in6_addr *addr, int type) return 3; else if (type & IPV6_ADDR_MAPPED) return 4; + else if (addr->s6_addr32[0] == htonl(0x20010000)) + return 6; else if (addr->s6_addr16[0] == htons(0x2002)) return 2; + else if ((addr->s6_addr[0] & 0xfe) == 0xfc) + return 5; return 1; } -- cgit v1.2.3 From 5e2707fa3aed8c24075087cbaea2628725adbe55 Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Thu, 22 Jun 2006 01:41:18 -0700 Subject: [IPV6] ADDRCONF: Fix default source address selection without CONFIG_IPV6_PRIVACY We need to update hiscore.rule even if we don't enable CONFIG_IPV6_PRIVACY, because we have more less significant rule; longest match. Signed-off-by: YOSHIFUJI Hideaki Signed-off-by: David S. Miller --- net/ipv6/addrconf.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 6b361fc3e14..4da664538f5 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -1075,6 +1075,9 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev, if (hiscore.attrs & IPV6_SADDR_SCORE_PRIVACY) continue; } +#else + if (hiscore.rule < 7) + hiscore.rule++; #endif /* Rule 8: Use longest matching prefix */ if (hiscore.rule < 8) { -- cgit v1.2.3 From d4828d85d188dc70ed172802e798d3978bb6e29e Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 22 Jun 2006 02:28:18 -0700 Subject: [NET]: Prevent transmission after dev_deactivate The dev_deactivate function has bit-rotted since the introduction of lockless drivers. In particular, the spin_unlock_wait call at the end has no effect on the xmit routine of lockless drivers. With a little bit of work, we can make it much more useful by providing the guarantee that when it returns, no more calls to the xmit routine of the underlying driver will be made. The idea is simple. There are two entry points in to the xmit routine. The first comes from dev_queue_xmit. That one is easily stopped by using synchronize_rcu. This works because we set the qdisc to noop_qdisc before the synchronize_rcu call. That in turn causes all subsequent packets sent to dev_queue_xmit to be dropped. The synchronize_rcu call also ensures all outstanding calls leave their critical section. The other entry point is from qdisc_run. Since we now have a bit that indicates whether it's running, all we have to do is to wait until the bit is off. I've removed the loop to wait for __LINK_STATE_SCHED to clear. This is useless because netif_wake_queue can cause it to be set again. It is also harmless because we've disarmed qdisc_run. I've also removed the spin_unlock_wait on xmit_lock because its only purpose of making sure that all outstanding xmit_lock holders have exited is also given by dev_watchdog_down. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/core/dev.c | 6 +++--- net/sched/sch_generic.c | 12 +++++++++--- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index ab39fe17cb5..29e3888102b 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1295,7 +1295,7 @@ int dev_queue_xmit(struct sk_buff *skb) /* Disable soft irqs for various locks below. Also * stops preemption for RCU. */ - local_bh_disable(); + rcu_read_lock_bh(); /* Updates of qdisc are serialized by queue_lock. * The struct Qdisc which is pointed to by qdisc is now a @@ -1369,13 +1369,13 @@ int dev_queue_xmit(struct sk_buff *skb) } rc = -ENETDOWN; - local_bh_enable(); + rcu_read_unlock_bh(); out_kfree_skb: kfree_skb(skb); return rc; out: - local_bh_enable(); + rcu_read_unlock_bh(); return rc; } diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index d7aca8ef524..7aad0121232 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -181,9 +181,13 @@ requeue: void __qdisc_run(struct net_device *dev) { + if (unlikely(dev->qdisc == &noop_qdisc)) + goto out; + while (qdisc_restart(dev) < 0 && !netif_queue_stopped(dev)) /* NOTHING */; +out: clear_bit(__LINK_STATE_QDISC_RUNNING, &dev->state); } @@ -583,10 +587,12 @@ void dev_deactivate(struct net_device *dev) dev_watchdog_down(dev); - while (test_bit(__LINK_STATE_SCHED, &dev->state)) - yield(); + /* Wait for outstanding dev_queue_xmit calls. */ + synchronize_rcu(); - spin_unlock_wait(&dev->_xmit_lock); + /* Wait for outstanding qdisc_run calls. */ + while (test_bit(__LINK_STATE_QDISC_RUNNING, &dev->state)) + yield(); } void dev_init_scheduler(struct net_device *dev) -- cgit v1.2.3 From 7967168cefdbc63bf332d6b1548eca7cd65ebbcc Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 22 Jun 2006 02:40:14 -0700 Subject: [NET]: Merge TSO/UFO fields in sk_buff Having separate fields in sk_buff for TSO/UFO (tso_size/ufo_size) is not going to scale if we add any more segmentation methods (e.g., DCCP). So let's merge them. They were used to tell the protocol of a packet. This function has been subsumed by the new gso_type field. This is essentially a set of netdev feature bits (shifted by 16 bits) that are required to process a specific skb. As such it's easy to tell whether a given device can process a GSO skb: you just have to and the gso_type field and the netdev's features field. I've made gso_type a conjunction. The idea is that you have a base type (e.g., SKB_GSO_TCPV4) that can be modified further to support new features. For example, if we add a hardware TSO type that supports ECN, they would declare NETIF_F_TSO | NETIF_F_TSO_ECN. All TSO packets with CWR set would have a gso_type of SKB_GSO_TCPV4 | SKB_GSO_TCPV4_ECN while all other TSO packets would be SKB_GSO_TCPV4. This means that only the CWR packets need to be emulated in software. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- drivers/net/8139cp.c | 2 +- drivers/net/bnx2.c | 4 ++-- drivers/net/chelsio/sge.c | 4 ++-- drivers/net/e1000/e1000_main.c | 10 ++++----- drivers/net/forcedeth.c | 4 ++-- drivers/net/ixgb/ixgb_main.c | 4 ++-- drivers/net/loopback.c | 4 ++-- drivers/net/myri10ge/myri10ge.c | 4 ++-- drivers/net/r8169.c | 2 +- drivers/net/s2io.c | 16 +++++++------- drivers/net/sky2.c | 4 ++-- drivers/net/tg3.c | 4 ++-- drivers/net/typhoon.c | 2 +- drivers/s390/net/qeth_eddp.c | 12 +++++------ drivers/s390/net/qeth_main.c | 4 ++-- drivers/s390/net/qeth_tso.h | 2 +- include/linux/netdevice.h | 14 ++++++++++-- include/linux/skbuff.h | 12 ++++++++--- include/net/tcp.h | 4 ++-- net/bridge/br_forward.c | 4 ++-- net/bridge/br_netfilter.c | 2 +- net/core/skbuff.c | 16 ++++++++------ net/ipv4/ip_output.c | 16 ++++++++------ net/ipv4/tcp.c | 4 ++-- net/ipv4/tcp_input.c | 2 +- net/ipv4/tcp_output.c | 47 ++++++++++++++++++++++++----------------- net/ipv6/ip6_output.c | 7 +++--- 27 files changed, 120 insertions(+), 90 deletions(-) diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index a26077a175a..0cdc830449d 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c @@ -797,7 +797,7 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev) entry = cp->tx_head; eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0; if (dev->features & NETIF_F_TSO) - mss = skb_shinfo(skb)->tso_size; + mss = skb_shinfo(skb)->gso_size; if (skb_shinfo(skb)->nr_frags == 0) { struct cp_desc *txd = &cp->tx_ring[entry]; diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 702d546567a..7635736cc79 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -1640,7 +1640,7 @@ bnx2_tx_int(struct bnx2 *bp) skb = tx_buf->skb; #ifdef BCM_TSO /* partial BD completions possible with TSO packets */ - if (skb_shinfo(skb)->tso_size) { + if (skb_shinfo(skb)->gso_size) { u16 last_idx, last_ring_idx; last_idx = sw_cons + @@ -4428,7 +4428,7 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) (TX_BD_FLAGS_VLAN_TAG | (vlan_tx_tag_get(skb) << 16)); } #ifdef BCM_TSO - if ((mss = skb_shinfo(skb)->tso_size) && + if ((mss = skb_shinfo(skb)->gso_size) && (skb->len > (bp->dev->mtu + ETH_HLEN))) { u32 tcp_opt_len, ip_tcp_len; diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c index 4391bf4bf57..53efff6da78 100644 --- a/drivers/net/chelsio/sge.c +++ b/drivers/net/chelsio/sge.c @@ -1418,7 +1418,7 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev) struct cpl_tx_pkt *cpl; #ifdef NETIF_F_TSO - if (skb_shinfo(skb)->tso_size) { + if (skb_shinfo(skb)->gso_size) { int eth_type; struct cpl_tx_pkt_lso *hdr; @@ -1433,7 +1433,7 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev) hdr->ip_hdr_words = skb->nh.iph->ihl; hdr->tcp_hdr_words = skb->h.th->doff; hdr->eth_type_mss = htons(MK_ETH_TYPE_MSS(eth_type, - skb_shinfo(skb)->tso_size)); + skb_shinfo(skb)->gso_size)); hdr->len = htonl(skb->len - sizeof(*hdr)); cpl = (struct cpl_tx_pkt *)hdr; sge->stats.tx_lso_pkts++; diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index a373ccb308d..32b7d444b37 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -2394,7 +2394,7 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring, uint8_t ipcss, ipcso, tucss, tucso, hdr_len; int err; - if (skb_shinfo(skb)->tso_size) { + if (skb_shinfo(skb)->gso_size) { if (skb_header_cloned(skb)) { err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); if (err) @@ -2402,7 +2402,7 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring, } hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2)); - mss = skb_shinfo(skb)->tso_size; + mss = skb_shinfo(skb)->gso_size; if (skb->protocol == htons(ETH_P_IP)) { skb->nh.iph->tot_len = 0; skb->nh.iph->check = 0; @@ -2519,7 +2519,7 @@ e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring, * tso gets written back prematurely before the data is fully * DMA'd to the controller */ if (!skb->data_len && tx_ring->last_tx_tso && - !skb_shinfo(skb)->tso_size) { + !skb_shinfo(skb)->gso_size) { tx_ring->last_tx_tso = 0; size -= 4; } @@ -2757,7 +2757,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) } #ifdef NETIF_F_TSO - mss = skb_shinfo(skb)->tso_size; + mss = skb_shinfo(skb)->gso_size; /* The controller does a simple calculation to * make sure there is enough room in the FIFO before * initiating the DMA for each buffer. The calc is: @@ -2807,7 +2807,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) #ifdef NETIF_F_TSO /* Controller Erratum workaround */ if (!skb->data_len && tx_ring->last_tx_tso && - !skb_shinfo(skb)->tso_size) + !skb_shinfo(skb)->gso_size) count++; #endif diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 191383d461d..21be4fa071b 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -1495,8 +1495,8 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev) np->tx_skbuff[nr] = skb; #ifdef NETIF_F_TSO - if (skb_shinfo(skb)->tso_size) - tx_flags_extra = NV_TX2_TSO | (skb_shinfo(skb)->tso_size << NV_TX2_TSO_SHIFT); + if (skb_shinfo(skb)->gso_size) + tx_flags_extra = NV_TX2_TSO | (skb_shinfo(skb)->gso_size << NV_TX2_TSO_SHIFT); else #endif tx_flags_extra = (skb->ip_summed == CHECKSUM_HW ? (NV_TX2_CHECKSUM_L3|NV_TX2_CHECKSUM_L4) : 0); diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index 57006fb8840..8bb32f94699 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c @@ -1173,7 +1173,7 @@ ixgb_tso(struct ixgb_adapter *adapter, struct sk_buff *skb) uint16_t ipcse, tucse, mss; int err; - if(likely(skb_shinfo(skb)->tso_size)) { + if(likely(skb_shinfo(skb)->gso_size)) { if (skb_header_cloned(skb)) { err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); if (err) @@ -1181,7 +1181,7 @@ ixgb_tso(struct ixgb_adapter *adapter, struct sk_buff *skb) } hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2)); - mss = skb_shinfo(skb)->tso_size; + mss = skb_shinfo(skb)->gso_size; skb->nh.iph->tot_len = 0; skb->nh.iph->check = 0; skb->h.th->check = ~csum_tcpudp_magic(skb->nh.iph->saddr, diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index b79d6e8d304..43fef7de8cb 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -74,7 +74,7 @@ static void emulate_large_send_offload(struct sk_buff *skb) struct iphdr *iph = skb->nh.iph; struct tcphdr *th = (struct tcphdr*)(skb->nh.raw + (iph->ihl * 4)); unsigned int doffset = (iph->ihl + th->doff) * 4; - unsigned int mtu = skb_shinfo(skb)->tso_size + doffset; + unsigned int mtu = skb_shinfo(skb)->gso_size + doffset; unsigned int offset = 0; u32 seq = ntohl(th->seq); u16 id = ntohs(iph->id); @@ -139,7 +139,7 @@ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev) #endif #ifdef LOOPBACK_TSO - if (skb_shinfo(skb)->tso_size) { + if (skb_shinfo(skb)->gso_size) { BUG_ON(skb->protocol != htons(ETH_P_IP)); BUG_ON(skb->nh.iph->protocol != IPPROTO_TCP); diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index b983e1e0434..dbdf189436f 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -1879,7 +1879,7 @@ again: #ifdef NETIF_F_TSO if (skb->len > (dev->mtu + ETH_HLEN)) { - mss = skb_shinfo(skb)->tso_size; + mss = skb_shinfo(skb)->gso_size; if (mss != 0) max_segments = MYRI10GE_MAX_SEND_DESC_TSO; } @@ -2112,7 +2112,7 @@ abort_linearize: } idx = (idx + 1) & tx->mask; } while (idx != last_idx); - if (skb_shinfo(skb)->tso_size) { + if (skb_shinfo(skb)->gso_size) { printk(KERN_ERR "myri10ge: %s: TSO but wanted to linearize?!?!?\n", mgp->dev->name); diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 985afe0e627..12d1cb289bb 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -2172,7 +2172,7 @@ static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb, static inline u32 rtl8169_tso_csum(struct sk_buff *skb, struct net_device *dev) { if (dev->features & NETIF_F_TSO) { - u32 mss = skb_shinfo(skb)->tso_size; + u32 mss = skb_shinfo(skb)->gso_size; if (mss) return LargeSend | ((mss & MSSMask) << MSSShift); diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 11daed495b9..3defe5d4f7d 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -3959,8 +3959,8 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) txdp->Control_1 = 0; txdp->Control_2 = 0; #ifdef NETIF_F_TSO - mss = skb_shinfo(skb)->tso_size; - if (mss) { + mss = skb_shinfo(skb)->gso_size; + if (skb_shinfo(skb)->gso_type == SKB_GSO_TCPV4) { txdp->Control_1 |= TXD_TCP_LSO_EN; txdp->Control_1 |= TXD_TCP_LSO_MSS(mss); } @@ -3980,10 +3980,10 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) } frg_len = skb->len - skb->data_len; - if (skb_shinfo(skb)->ufo_size) { + if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4) { int ufo_size; - ufo_size = skb_shinfo(skb)->ufo_size; + ufo_size = skb_shinfo(skb)->gso_size; ufo_size &= ~7; txdp->Control_1 |= TXD_UFO_EN; txdp->Control_1 |= TXD_UFO_MSS(ufo_size); @@ -4009,7 +4009,7 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) txdp->Host_Control = (unsigned long) skb; txdp->Control_1 |= TXD_BUFFER0_SIZE(frg_len); - if (skb_shinfo(skb)->ufo_size) + if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4) txdp->Control_1 |= TXD_UFO_EN; frg_cnt = skb_shinfo(skb)->nr_frags; @@ -4024,12 +4024,12 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) (sp->pdev, frag->page, frag->page_offset, frag->size, PCI_DMA_TODEVICE); txdp->Control_1 = TXD_BUFFER0_SIZE(frag->size); - if (skb_shinfo(skb)->ufo_size) + if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4) txdp->Control_1 |= TXD_UFO_EN; } txdp->Control_1 |= TXD_GATHER_CODE_LAST; - if (skb_shinfo(skb)->ufo_size) + if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4) frg_cnt++; /* as Txd0 was used for inband header */ tx_fifo = mac_control->tx_FIFO_start[queue]; @@ -4043,7 +4043,7 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) if (mss) val64 |= TX_FIFO_SPECIAL_FUNC; #endif - if (skb_shinfo(skb)->ufo_size) + if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4) val64 |= TX_FIFO_SPECIAL_FUNC; writeq(val64, &tx_fifo->List_Control); diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index fba1e4d4d83..d3577871be2 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -1160,7 +1160,7 @@ static unsigned tx_le_req(const struct sk_buff *skb) count = sizeof(dma_addr_t) / sizeof(u32); count += skb_shinfo(skb)->nr_frags * count; - if (skb_shinfo(skb)->tso_size) + if (skb_shinfo(skb)->gso_size) ++count; if (skb->ip_summed == CHECKSUM_HW) @@ -1232,7 +1232,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) } /* Check for TCP Segmentation Offload */ - mss = skb_shinfo(skb)->tso_size; + mss = skb_shinfo(skb)->gso_size; if (mss != 0) { /* just drop the packet if non-linear expansion fails */ if (skb_header_cloned(skb) && diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index b2ddd4522a8..e3e380f90f8 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -3780,7 +3780,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) #if TG3_TSO_SUPPORT != 0 mss = 0; if (skb->len > (tp->dev->mtu + ETH_HLEN) && - (mss = skb_shinfo(skb)->tso_size) != 0) { + (mss = skb_shinfo(skb)->gso_size) != 0) { int tcp_opt_len, ip_tcp_len; if (skb_header_cloned(skb) && @@ -3905,7 +3905,7 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev) #if TG3_TSO_SUPPORT != 0 mss = 0; if (skb->len > (tp->dev->mtu + ETH_HLEN) && - (mss = skb_shinfo(skb)->tso_size) != 0) { + (mss = skb_shinfo(skb)->gso_size) != 0) { int tcp_opt_len, ip_tcp_len; if (skb_header_cloned(skb) && diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c index d9258d42090..e49e8b520c2 100644 --- a/drivers/net/typhoon.c +++ b/drivers/net/typhoon.c @@ -340,7 +340,7 @@ enum state_values { #endif #if defined(NETIF_F_TSO) -#define skb_tso_size(x) (skb_shinfo(x)->tso_size) +#define skb_tso_size(x) (skb_shinfo(x)->gso_size) #define TSO_NUM_DESCRIPTORS 2 #define TSO_OFFLOAD_ON TYPHOON_OFFLOAD_TCP_SEGMENT #else diff --git a/drivers/s390/net/qeth_eddp.c b/drivers/s390/net/qeth_eddp.c index 0bab60a2030..38aad832145 100644 --- a/drivers/s390/net/qeth_eddp.c +++ b/drivers/s390/net/qeth_eddp.c @@ -420,7 +420,7 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx, } tcph = eddp->skb->h.th; while (eddp->skb_offset < eddp->skb->len) { - data_len = min((int)skb_shinfo(eddp->skb)->tso_size, + data_len = min((int)skb_shinfo(eddp->skb)->gso_size, (int)(eddp->skb->len - eddp->skb_offset)); /* prepare qdio hdr */ if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2){ @@ -515,20 +515,20 @@ qeth_eddp_calc_num_pages(struct qeth_eddp_context *ctx, struct sk_buff *skb, QETH_DBF_TEXT(trace, 5, "eddpcanp"); /* can we put multiple skbs in one page? */ - skbs_per_page = PAGE_SIZE / (skb_shinfo(skb)->tso_size + hdr_len); + skbs_per_page = PAGE_SIZE / (skb_shinfo(skb)->gso_size + hdr_len); if (skbs_per_page > 1){ - ctx->num_pages = (skb_shinfo(skb)->tso_segs + 1) / + ctx->num_pages = (skb_shinfo(skb)->gso_segs + 1) / skbs_per_page + 1; ctx->elements_per_skb = 1; } else { /* no -> how many elements per skb? */ - ctx->elements_per_skb = (skb_shinfo(skb)->tso_size + hdr_len + + ctx->elements_per_skb = (skb_shinfo(skb)->gso_size + hdr_len + PAGE_SIZE) >> PAGE_SHIFT; ctx->num_pages = ctx->elements_per_skb * - (skb_shinfo(skb)->tso_segs + 1); + (skb_shinfo(skb)->gso_segs + 1); } ctx->num_elements = ctx->elements_per_skb * - (skb_shinfo(skb)->tso_segs + 1); + (skb_shinfo(skb)->gso_segs + 1); } static inline struct qeth_eddp_context * diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index 9e671a48cd2..56009d76832 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c @@ -4417,7 +4417,7 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) struct qeth_eddp_context *ctx = NULL; int tx_bytes = skb->len; unsigned short nr_frags = skb_shinfo(skb)->nr_frags; - unsigned short tso_size = skb_shinfo(skb)->tso_size; + unsigned short tso_size = skb_shinfo(skb)->gso_size; int rc; QETH_DBF_TEXT(trace, 6, "sendpkt"); @@ -4453,7 +4453,7 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) queue = card->qdio.out_qs [qeth_get_priority_queue(card, skb, ipv, cast_type)]; - if (skb_shinfo(skb)->tso_size) + if (skb_shinfo(skb)->gso_size) large_send = card->options.large_send; /*are we able to do TSO ? If so ,prepare and send it from here */ diff --git a/drivers/s390/net/qeth_tso.h b/drivers/s390/net/qeth_tso.h index 24ef40ca956..593f298142c 100644 --- a/drivers/s390/net/qeth_tso.h +++ b/drivers/s390/net/qeth_tso.h @@ -51,7 +51,7 @@ qeth_tso_fill_header(struct qeth_card *card, struct sk_buff *skb) hdr->ext.hdr_version = 1; hdr->ext.hdr_len = 28; /*insert non-fix values */ - hdr->ext.mss = skb_shinfo(skb)->tso_size; + hdr->ext.mss = skb_shinfo(skb)->gso_size; hdr->ext.dg_hdr_len = (__u16)(iph->ihl*4 + tcph->doff*4); hdr->ext.payload_len = (__u16)(skb->len - hdr->ext.dg_hdr_len - sizeof(struct qeth_hdr_tso)); diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index cead6be467e..fa5671307b9 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -308,9 +308,12 @@ struct net_device #define NETIF_F_HW_VLAN_RX 256 /* Receive VLAN hw acceleration */ #define NETIF_F_HW_VLAN_FILTER 512 /* Receive filtering on VLAN */ #define NETIF_F_VLAN_CHALLENGED 1024 /* Device cannot handle VLAN packets */ -#define NETIF_F_TSO 2048 /* Can offload TCP/IP segmentation */ #define NETIF_F_LLTX 4096 /* LockLess TX */ -#define NETIF_F_UFO 8192 /* Can offload UDP Large Send*/ + + /* Segmentation offload features */ +#define NETIF_F_GSO_SHIFT 16 +#define NETIF_F_TSO (SKB_GSO_TCPV4 << NETIF_F_GSO_SHIFT) +#define NETIF_F_UFO (SKB_GSO_UDPV4 << NETIF_F_GSO_SHIFT) #define NETIF_F_GEN_CSUM (NETIF_F_NO_CSUM | NETIF_F_HW_CSUM) #define NETIF_F_ALL_CSUM (NETIF_F_IP_CSUM | NETIF_F_GEN_CSUM) @@ -979,6 +982,13 @@ extern void dev_seq_stop(struct seq_file *seq, void *v); extern void linkwatch_run_queue(void); +static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb) +{ + int feature = skb_shinfo(skb)->gso_type << NETIF_F_GSO_SHIFT; + return skb_shinfo(skb)->gso_size && + (dev->features & feature) != feature; +} + #endif /* __KERNEL__ */ #endif /* _LINUX_DEV_H */ diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index f8c7eb79a27..97b0d2d1a6b 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -134,9 +134,10 @@ struct skb_frag_struct { struct skb_shared_info { atomic_t dataref; unsigned short nr_frags; - unsigned short tso_size; - unsigned short tso_segs; - unsigned short ufo_size; + unsigned short gso_size; + /* Warning: this field is not always filled in (UFO)! */ + unsigned short gso_segs; + unsigned short gso_type; unsigned int ip6_frag_id; struct sk_buff *frag_list; skb_frag_t frags[MAX_SKB_FRAGS]; @@ -168,6 +169,11 @@ enum { SKB_FCLONE_CLONE, }; +enum { + SKB_GSO_TCPV4 = 1 << 0, + SKB_GSO_UDPV4 = 1 << 1, +}; + /** * struct sk_buff - socket buffer * @next: Next buffer in list diff --git a/include/net/tcp.h b/include/net/tcp.h index 5f4eb5c7968..b197a9e615c 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -569,13 +569,13 @@ struct tcp_skb_cb { */ static inline int tcp_skb_pcount(const struct sk_buff *skb) { - return skb_shinfo(skb)->tso_segs; + return skb_shinfo(skb)->gso_segs; } /* This is valid iff tcp_skb_pcount() > 1. */ static inline int tcp_skb_mss(const struct sk_buff *skb) { - return skb_shinfo(skb)->tso_size; + return skb_shinfo(skb)->gso_size; } static inline void tcp_dec_pcount_approx(__u32 *count, diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index 0dca027ceb8..8be9f2123e5 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c @@ -34,8 +34,8 @@ static inline unsigned packet_length(const struct sk_buff *skb) int br_dev_queue_push_xmit(struct sk_buff *skb) { - /* drop mtu oversized packets except tso */ - if (packet_length(skb) > skb->dev->mtu && !skb_shinfo(skb)->tso_size) + /* drop mtu oversized packets except gso */ + if (packet_length(skb) > skb->dev->mtu && !skb_shinfo(skb)->gso_size) kfree_skb(skb); else { #ifdef CONFIG_BRIDGE_NETFILTER diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 3e41f9d6d51..8298a5179ae 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c @@ -761,7 +761,7 @@ static int br_nf_dev_queue_xmit(struct sk_buff *skb) { if (skb->protocol == htons(ETH_P_IP) && skb->len > skb->dev->mtu && - !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size)) + !skb_shinfo(skb)->gso_size) return ip_fragment(skb, br_dev_queue_push_xmit); else return br_dev_queue_push_xmit(skb); diff --git a/net/core/skbuff.c b/net/core/skbuff.c index fe63d4efbd4..368d98578c1 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -172,9 +172,9 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask, shinfo = skb_shinfo(skb); atomic_set(&shinfo->dataref, 1); shinfo->nr_frags = 0; - shinfo->tso_size = 0; - shinfo->tso_segs = 0; - shinfo->ufo_size = 0; + shinfo->gso_size = 0; + shinfo->gso_segs = 0; + shinfo->gso_type = 0; shinfo->ip6_frag_id = 0; shinfo->frag_list = NULL; @@ -238,8 +238,9 @@ struct sk_buff *alloc_skb_from_cache(kmem_cache_t *cp, atomic_set(&(skb_shinfo(skb)->dataref), 1); skb_shinfo(skb)->nr_frags = 0; - skb_shinfo(skb)->tso_size = 0; - skb_shinfo(skb)->tso_segs = 0; + skb_shinfo(skb)->gso_size = 0; + skb_shinfo(skb)->gso_segs = 0; + skb_shinfo(skb)->gso_type = 0; skb_shinfo(skb)->frag_list = NULL; out: return skb; @@ -528,8 +529,9 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old) #endif skb_copy_secmark(new, old); atomic_set(&new->users, 1); - skb_shinfo(new)->tso_size = skb_shinfo(old)->tso_size; - skb_shinfo(new)->tso_segs = skb_shinfo(old)->tso_segs; + skb_shinfo(new)->gso_size = skb_shinfo(old)->gso_size; + skb_shinfo(new)->gso_segs = skb_shinfo(old)->gso_segs; + skb_shinfo(new)->gso_type = skb_shinfo(old)->gso_type; } /** diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 8538aac3d14..7624fd1d8f9 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -210,8 +210,7 @@ static inline int ip_finish_output(struct sk_buff *skb) return dst_output(skb); } #endif - if (skb->len > dst_mtu(skb->dst) && - !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size)) + if (skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->gso_size) return ip_fragment(skb, ip_finish_output2); else return ip_finish_output2(skb); @@ -362,7 +361,7 @@ packet_routed: } ip_select_ident_more(iph, &rt->u.dst, sk, - (skb_shinfo(skb)->tso_segs ?: 1) - 1); + (skb_shinfo(skb)->gso_segs ?: 1) - 1); /* Add an IP checksum. */ ip_send_check(iph); @@ -744,7 +743,8 @@ static inline int ip_ufo_append_data(struct sock *sk, (length - transhdrlen)); if (!err) { /* specify the length of each IP datagram fragment*/ - skb_shinfo(skb)->ufo_size = (mtu - fragheaderlen); + skb_shinfo(skb)->gso_size = mtu - fragheaderlen; + skb_shinfo(skb)->gso_type = SKB_GSO_UDPV4; __skb_queue_tail(&sk->sk_write_queue, skb); return 0; @@ -1087,14 +1087,16 @@ ssize_t ip_append_page(struct sock *sk, struct page *page, inet->cork.length += size; if ((sk->sk_protocol == IPPROTO_UDP) && - (rt->u.dst.dev->features & NETIF_F_UFO)) - skb_shinfo(skb)->ufo_size = (mtu - fragheaderlen); + (rt->u.dst.dev->features & NETIF_F_UFO)) { + skb_shinfo(skb)->gso_size = mtu - fragheaderlen; + skb_shinfo(skb)->gso_type = SKB_GSO_UDPV4; + } while (size > 0) { int i; - if (skb_shinfo(skb)->ufo_size) + if (skb_shinfo(skb)->gso_size) len = size; else { diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 74998f25007..062dd1a0d8a 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -571,7 +571,7 @@ new_segment: skb->ip_summed = CHECKSUM_HW; tp->write_seq += copy; TCP_SKB_CB(skb)->end_seq += copy; - skb_shinfo(skb)->tso_segs = 0; + skb_shinfo(skb)->gso_segs = 0; if (!copied) TCP_SKB_CB(skb)->flags &= ~TCPCB_FLAG_PSH; @@ -818,7 +818,7 @@ new_segment: tp->write_seq += copy; TCP_SKB_CB(skb)->end_seq += copy; - skb_shinfo(skb)->tso_segs = 0; + skb_shinfo(skb)->gso_segs = 0; from += copy; copied += copy; diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index e08245bdda3..94fe5b1f9dc 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -1073,7 +1073,7 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ else pkt_len = (end_seq - TCP_SKB_CB(skb)->seq); - if (tcp_fragment(sk, skb, pkt_len, skb_shinfo(skb)->tso_size)) + if (tcp_fragment(sk, skb, pkt_len, skb_shinfo(skb)->gso_size)) break; pcount = tcp_skb_pcount(skb); } diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 07bb5a2b375..bdd71db8bf9 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -515,15 +515,17 @@ static void tcp_set_skb_tso_segs(struct sock *sk, struct sk_buff *skb, unsigned /* Avoid the costly divide in the normal * non-TSO case. */ - skb_shinfo(skb)->tso_segs = 1; - skb_shinfo(skb)->tso_size = 0; + skb_shinfo(skb)->gso_segs = 1; + skb_shinfo(skb)->gso_size = 0; + skb_shinfo(skb)->gso_type = 0; } else { unsigned int factor; factor = skb->len + (mss_now - 1); factor /= mss_now; - skb_shinfo(skb)->tso_segs = factor; - skb_shinfo(skb)->tso_size = mss_now; + skb_shinfo(skb)->gso_segs = factor; + skb_shinfo(skb)->gso_size = mss_now; + skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; } } @@ -914,7 +916,7 @@ static int tcp_init_tso_segs(struct sock *sk, struct sk_buff *skb, unsigned int if (!tso_segs || (tso_segs > 1 && - skb_shinfo(skb)->tso_size != mss_now)) { + tcp_skb_mss(skb) != mss_now)) { tcp_set_skb_tso_segs(sk, skb, mss_now); tso_segs = tcp_skb_pcount(skb); } @@ -1724,8 +1726,9 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) tp->snd_una == (TCP_SKB_CB(skb)->end_seq - 1)) { if (!pskb_trim(skb, 0)) { TCP_SKB_CB(skb)->seq = TCP_SKB_CB(skb)->end_seq - 1; - skb_shinfo(skb)->tso_segs = 1; - skb_shinfo(skb)->tso_size = 0; + skb_shinfo(skb)->gso_segs = 1; + skb_shinfo(skb)->gso_size = 0; + skb_shinfo(skb)->gso_type = 0; skb->ip_summed = CHECKSUM_NONE; skb->csum = 0; } @@ -1930,8 +1933,9 @@ void tcp_send_fin(struct sock *sk) skb->csum = 0; TCP_SKB_CB(skb)->flags = (TCPCB_FLAG_ACK | TCPCB_FLAG_FIN); TCP_SKB_CB(skb)->sacked = 0; - skb_shinfo(skb)->tso_segs = 1; - skb_shinfo(skb)->tso_size = 0; + skb_shinfo(skb)->gso_segs = 1; + skb_shinfo(skb)->gso_size = 0; + skb_shinfo(skb)->gso_type = 0; /* FIN eats a sequence byte, write_seq advanced by tcp_queue_skb(). */ TCP_SKB_CB(skb)->seq = tp->write_seq; @@ -1963,8 +1967,9 @@ void tcp_send_active_reset(struct sock *sk, gfp_t priority) skb->csum = 0; TCP_SKB_CB(skb)->flags = (TCPCB_FLAG_ACK | TCPCB_FLAG_RST); TCP_SKB_CB(skb)->sacked = 0; - skb_shinfo(skb)->tso_segs = 1; - skb_shinfo(skb)->tso_size = 0; + skb_shinfo(skb)->gso_segs = 1; + skb_shinfo(skb)->gso_size = 0; + skb_shinfo(skb)->gso_type = 0; /* Send it off. */ TCP_SKB_CB(skb)->seq = tcp_acceptable_seq(sk, tp); @@ -2047,8 +2052,9 @@ struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst, TCP_SKB_CB(skb)->seq = tcp_rsk(req)->snt_isn; TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq + 1; TCP_SKB_CB(skb)->sacked = 0; - skb_shinfo(skb)->tso_segs = 1; - skb_shinfo(skb)->tso_size = 0; + skb_shinfo(skb)->gso_segs = 1; + skb_shinfo(skb)->gso_size = 0; + skb_shinfo(skb)->gso_type = 0; th->seq = htonl(TCP_SKB_CB(skb)->seq); th->ack_seq = htonl(tcp_rsk(req)->rcv_isn + 1); if (req->rcv_wnd == 0) { /* ignored for retransmitted syns */ @@ -2152,8 +2158,9 @@ int tcp_connect(struct sock *sk) TCP_SKB_CB(buff)->flags = TCPCB_FLAG_SYN; TCP_ECN_send_syn(sk, tp, buff); TCP_SKB_CB(buff)->sacked = 0; - skb_shinfo(buff)->tso_segs = 1; - skb_shinfo(buff)->tso_size = 0; + skb_shinfo(buff)->gso_segs = 1; + skb_shinfo(buff)->gso_size = 0; + skb_shinfo(buff)->gso_type = 0; buff->csum = 0; TCP_SKB_CB(buff)->seq = tp->write_seq++; TCP_SKB_CB(buff)->end_seq = tp->write_seq; @@ -2257,8 +2264,9 @@ void tcp_send_ack(struct sock *sk) buff->csum = 0; TCP_SKB_CB(buff)->flags = TCPCB_FLAG_ACK; TCP_SKB_CB(buff)->sacked = 0; - skb_shinfo(buff)->tso_segs = 1; - skb_shinfo(buff)->tso_size = 0; + skb_shinfo(buff)->gso_segs = 1; + skb_shinfo(buff)->gso_size = 0; + skb_shinfo(buff)->gso_type = 0; /* Send it off, this clears delayed acks for us. */ TCP_SKB_CB(buff)->seq = TCP_SKB_CB(buff)->end_seq = tcp_acceptable_seq(sk, tp); @@ -2293,8 +2301,9 @@ static int tcp_xmit_probe_skb(struct sock *sk, int urgent) skb->csum = 0; TCP_SKB_CB(skb)->flags = TCPCB_FLAG_ACK; TCP_SKB_CB(skb)->sacked = urgent; - skb_shinfo(skb)->tso_segs = 1; - skb_shinfo(skb)->tso_size = 0; + skb_shinfo(skb)->gso_segs = 1; + skb_shinfo(skb)->gso_size = 0; + skb_shinfo(skb)->gso_type = 0; /* Use a previous sequence. This should cause the other * end to send an ack. Don't queue or clone SKB, just diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index d29620f4910..abb94de3376 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -148,7 +148,7 @@ static int ip6_output2(struct sk_buff *skb) int ip6_output(struct sk_buff *skb) { - if ((skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->ufo_size) || + if ((skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->gso_size) || dst_allfrag(skb->dst)) return ip6_fragment(skb, ip6_output2); else @@ -833,8 +833,9 @@ static inline int ip6_ufo_append_data(struct sock *sk, struct frag_hdr fhdr; /* specify the length of each IP datagram fragment*/ - skb_shinfo(skb)->ufo_size = (mtu - fragheaderlen) - - sizeof(struct frag_hdr); + skb_shinfo(skb)->gso_size = mtu - fragheaderlen - + sizeof(struct frag_hdr); + skb_shinfo(skb)->gso_type = SKB_GSO_UDPV4; ipv6_select_ident(skb, &fhdr); skb_shinfo(skb)->ip6_frag_id = fhdr.identification; __skb_queue_tail(&sk->sk_write_queue, skb); -- cgit v1.2.3 From f6a78bfcb141f963187464bac838d46a81c3882a Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 22 Jun 2006 02:57:17 -0700 Subject: [NET]: Add generic segmentation offload This patch adds the infrastructure for generic segmentation offload. The idea is to tap into the potential savings of TSO without hardware support by postponing the allocation of segmented skb's until just before the entry point into the NIC driver. The same structure can be used to support software IPv6 TSO, as well as UFO and segmentation offload for other relevant protocols, e.g., DCCP. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- include/linux/netdevice.h | 8 ++- net/core/dev.c | 127 ++++++++++++++++++++++++++++++++++++++++++++-- net/sched/sch_generic.c | 19 +++++-- 3 files changed, 143 insertions(+), 11 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index fa5671307b9..b4eae18390c 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -405,6 +405,9 @@ struct net_device struct list_head qdisc_list; unsigned long tx_queue_len; /* Max frames per queue allowed */ + /* Partially transmitted GSO packet. */ + struct sk_buff *gso_skb; + /* ingress path synchronizer */ spinlock_t ingress_lock; struct Qdisc *qdisc_ingress; @@ -539,6 +542,7 @@ struct packet_type { struct net_device *, struct packet_type *, struct net_device *); + struct sk_buff *(*gso_segment)(struct sk_buff *skb, int sg); void *af_packet_priv; struct list_head list; }; @@ -689,7 +693,8 @@ extern int dev_change_name(struct net_device *, char *); extern int dev_set_mtu(struct net_device *, int); extern int dev_set_mac_address(struct net_device *, struct sockaddr *); -extern void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev); +extern int dev_hard_start_xmit(struct sk_buff *skb, + struct net_device *dev); extern void dev_init(void); @@ -963,6 +968,7 @@ extern int netdev_max_backlog; extern int weight_p; extern int netdev_set_master(struct net_device *dev, struct net_device *master); extern int skb_checksum_help(struct sk_buff *skb, int inward); +extern struct sk_buff *skb_gso_segment(struct sk_buff *skb, int sg); #ifdef CONFIG_BUG extern void netdev_rx_csum_fault(struct net_device *dev); #else diff --git a/net/core/dev.c b/net/core/dev.c index 29e3888102b..d293e0f90a0 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -116,6 +116,7 @@ #include #include #include +#include /* * The list of packet types we will receive (as opposed to discard) @@ -1048,7 +1049,7 @@ static inline void net_timestamp(struct sk_buff *skb) * taps currently in use. */ -void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev) +static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev) { struct packet_type *ptype; @@ -1186,6 +1187,40 @@ out: return ret; } +/** + * skb_gso_segment - Perform segmentation on skb. + * @skb: buffer to segment + * @sg: whether scatter-gather is supported on the target. + * + * This function segments the given skb and returns a list of segments. + */ +struct sk_buff *skb_gso_segment(struct sk_buff *skb, int sg) +{ + struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT); + struct packet_type *ptype; + int type = skb->protocol; + + BUG_ON(skb_shinfo(skb)->frag_list); + BUG_ON(skb->ip_summed != CHECKSUM_HW); + + skb->mac.raw = skb->data; + skb->mac_len = skb->nh.raw - skb->data; + __skb_pull(skb, skb->mac_len); + + rcu_read_lock(); + list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type) & 15], list) { + if (ptype->type == type && !ptype->dev && ptype->gso_segment) { + segs = ptype->gso_segment(skb, sg); + break; + } + } + rcu_read_unlock(); + + return segs; +} + +EXPORT_SYMBOL(skb_gso_segment); + /* Take action when hardware reception checksum errors are detected. */ #ifdef CONFIG_BUG void netdev_rx_csum_fault(struct net_device *dev) @@ -1222,6 +1257,86 @@ static inline int illegal_highdma(struct net_device *dev, struct sk_buff *skb) #define illegal_highdma(dev, skb) (0) #endif +struct dev_gso_cb { + void (*destructor)(struct sk_buff *skb); +}; + +#define DEV_GSO_CB(skb) ((struct dev_gso_cb *)(skb)->cb) + +static void dev_gso_skb_destructor(struct sk_buff *skb) +{ + struct dev_gso_cb *cb; + + do { + struct sk_buff *nskb = skb->next; + + skb->next = nskb->next; + nskb->next = NULL; + kfree_skb(nskb); + } while (skb->next); + + cb = DEV_GSO_CB(skb); + if (cb->destructor) + cb->destructor(skb); +} + +/** + * dev_gso_segment - Perform emulated hardware segmentation on skb. + * @skb: buffer to segment + * + * This function segments the given skb and stores the list of segments + * in skb->next. + */ +static int dev_gso_segment(struct sk_buff *skb) +{ + struct net_device *dev = skb->dev; + struct sk_buff *segs; + + segs = skb_gso_segment(skb, dev->features & NETIF_F_SG && + !illegal_highdma(dev, skb)); + if (unlikely(IS_ERR(segs))) + return PTR_ERR(segs); + + skb->next = segs; + DEV_GSO_CB(skb)->destructor = skb->destructor; + skb->destructor = dev_gso_skb_destructor; + + return 0; +} + +int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + if (likely(!skb->next)) { + if (netdev_nit) + dev_queue_xmit_nit(skb, dev); + + if (!netif_needs_gso(dev, skb)) + return dev->hard_start_xmit(skb, dev); + + if (unlikely(dev_gso_segment(skb))) + goto out_kfree_skb; + } + + do { + struct sk_buff *nskb = skb->next; + int rc; + + skb->next = nskb->next; + nskb->next = NULL; + rc = dev->hard_start_xmit(nskb, dev); + if (unlikely(rc)) { + skb->next = nskb; + return rc; + } + } while (skb->next); + + skb->destructor = DEV_GSO_CB(skb)->destructor; + +out_kfree_skb: + kfree_skb(skb); + return 0; +} + #define HARD_TX_LOCK(dev, cpu) { \ if ((dev->features & NETIF_F_LLTX) == 0) { \ netif_tx_lock(dev); \ @@ -1266,6 +1381,10 @@ int dev_queue_xmit(struct sk_buff *skb) struct Qdisc *q; int rc = -ENOMEM; + /* GSO will handle the following emulations directly. */ + if (netif_needs_gso(dev, skb)) + goto gso; + if (skb_shinfo(skb)->frag_list && !(dev->features & NETIF_F_FRAGLIST) && __skb_linearize(skb)) @@ -1290,6 +1409,7 @@ int dev_queue_xmit(struct sk_buff *skb) if (skb_checksum_help(skb, 0)) goto out_kfree_skb; +gso: spin_lock_prefetch(&dev->queue_lock); /* Disable soft irqs for various locks below. Also @@ -1346,11 +1466,8 @@ int dev_queue_xmit(struct sk_buff *skb) HARD_TX_LOCK(dev, cpu); if (!netif_queue_stopped(dev)) { - if (netdev_nit) - dev_queue_xmit_nit(skb, dev); - rc = 0; - if (!dev->hard_start_xmit(skb, dev)) { + if (!dev_hard_start_xmit(skb, dev)) { HARD_TX_UNLOCK(dev); goto out; } diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 7aad0121232..74d4a1dceee 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -96,8 +96,11 @@ static inline int qdisc_restart(struct net_device *dev) struct sk_buff *skb; /* Dequeue packet */ - if ((skb = q->dequeue(q)) != NULL) { + if (((skb = dev->gso_skb)) || ((skb = q->dequeue(q)))) { unsigned nolock = (dev->features & NETIF_F_LLTX); + + dev->gso_skb = NULL; + /* * When the driver has LLTX set it does its own locking * in start_xmit. No need to add additional overhead by @@ -134,10 +137,8 @@ static inline int qdisc_restart(struct net_device *dev) if (!netif_queue_stopped(dev)) { int ret; - if (netdev_nit) - dev_queue_xmit_nit(skb, dev); - ret = dev->hard_start_xmit(skb, dev); + ret = dev_hard_start_xmit(skb, dev); if (ret == NETDEV_TX_OK) { if (!nolock) { netif_tx_unlock(dev); @@ -171,7 +172,10 @@ static inline int qdisc_restart(struct net_device *dev) */ requeue: - q->ops->requeue(skb, q); + if (skb->next) + dev->gso_skb = skb; + else + q->ops->requeue(skb, q); netif_schedule(dev); return 1; } @@ -593,6 +597,11 @@ void dev_deactivate(struct net_device *dev) /* Wait for outstanding qdisc_run calls. */ while (test_bit(__LINK_STATE_QDISC_RUNNING, &dev->state)) yield(); + + if (dev->gso_skb) { + kfree_skb(dev->gso_skb); + dev->gso_skb = NULL; + } } void dev_init_scheduler(struct net_device *dev) -- cgit v1.2.3 From f4c50d990dcf11a296679dc05de3873783236711 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 22 Jun 2006 03:02:40 -0700 Subject: [NET]: Add software TSOv4 This patch adds the GSO implementation for IPv4 TCP. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- include/linux/skbuff.h | 1 + include/net/protocol.h | 1 + include/net/tcp.h | 2 + net/core/skbuff.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++++ net/ipv4/af_inet.c | 51 ++++++++++++++++++++ net/ipv4/tcp.c | 62 ++++++++++++++++++++++++ 6 files changed, 243 insertions(+) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 97b0d2d1a6b..a45bba9b8cb 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1297,6 +1297,7 @@ extern void skb_split(struct sk_buff *skb, struct sk_buff *skb1, const u32 len); extern void skb_release_data(struct sk_buff *skb); +extern struct sk_buff *skb_segment(struct sk_buff *skb, int sg); static inline void *skb_header_pointer(const struct sk_buff *skb, int offset, int len, void *buffer) diff --git a/include/net/protocol.h b/include/net/protocol.h index bcaee39bd2f..3b6dc15c68a 100644 --- a/include/net/protocol.h +++ b/include/net/protocol.h @@ -36,6 +36,7 @@ struct net_protocol { int (*handler)(struct sk_buff *skb); void (*err_handler)(struct sk_buff *skb, u32 info); + struct sk_buff *(*gso_segment)(struct sk_buff *skb, int sg); int no_policy; }; diff --git a/include/net/tcp.h b/include/net/tcp.h index b197a9e615c..ca3d38dfc00 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1086,6 +1086,8 @@ extern struct request_sock_ops tcp_request_sock_ops; extern int tcp_v4_destroy_sock(struct sock *sk); +extern struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int sg); + #ifdef CONFIG_PROC_FS extern int tcp4_proc_init(void); extern void tcp4_proc_exit(void); diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 368d98578c1..8e5044ba3ab 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -1842,6 +1842,132 @@ unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len) EXPORT_SYMBOL_GPL(skb_pull_rcsum); +/** + * skb_segment - Perform protocol segmentation on skb. + * @skb: buffer to segment + * @sg: whether scatter-gather can be used for generated segments + * + * This function performs segmentation on the given skb. It returns + * the segment at the given position. It returns NULL if there are + * no more segments to generate, or when an error is encountered. + */ +struct sk_buff *skb_segment(struct sk_buff *skb, int sg) +{ + struct sk_buff *segs = NULL; + struct sk_buff *tail = NULL; + unsigned int mss = skb_shinfo(skb)->gso_size; + unsigned int doffset = skb->data - skb->mac.raw; + unsigned int offset = doffset; + unsigned int headroom; + unsigned int len; + int nfrags = skb_shinfo(skb)->nr_frags; + int err = -ENOMEM; + int i = 0; + int pos; + + __skb_push(skb, doffset); + headroom = skb_headroom(skb); + pos = skb_headlen(skb); + + do { + struct sk_buff *nskb; + skb_frag_t *frag; + int hsize, nsize; + int k; + int size; + + len = skb->len - offset; + if (len > mss) + len = mss; + + hsize = skb_headlen(skb) - offset; + if (hsize < 0) + hsize = 0; + nsize = hsize + doffset; + if (nsize > len + doffset || !sg) + nsize = len + doffset; + + nskb = alloc_skb(nsize + headroom, GFP_ATOMIC); + if (unlikely(!nskb)) + goto err; + + if (segs) + tail->next = nskb; + else + segs = nskb; + tail = nskb; + + nskb->dev = skb->dev; + nskb->priority = skb->priority; + nskb->protocol = skb->protocol; + nskb->dst = dst_clone(skb->dst); + memcpy(nskb->cb, skb->cb, sizeof(skb->cb)); + nskb->pkt_type = skb->pkt_type; + nskb->mac_len = skb->mac_len; + + skb_reserve(nskb, headroom); + nskb->mac.raw = nskb->data; + nskb->nh.raw = nskb->data + skb->mac_len; + nskb->h.raw = nskb->nh.raw + (skb->h.raw - skb->nh.raw); + memcpy(skb_put(nskb, doffset), skb->data, doffset); + + if (!sg) { + nskb->csum = skb_copy_and_csum_bits(skb, offset, + skb_put(nskb, len), + len, 0); + continue; + } + + frag = skb_shinfo(nskb)->frags; + k = 0; + + nskb->ip_summed = CHECKSUM_HW; + nskb->csum = skb->csum; + memcpy(skb_put(nskb, hsize), skb->data + offset, hsize); + + while (pos < offset + len) { + BUG_ON(i >= nfrags); + + *frag = skb_shinfo(skb)->frags[i]; + get_page(frag->page); + size = frag->size; + + if (pos < offset) { + frag->page_offset += offset - pos; + frag->size -= offset - pos; + } + + k++; + + if (pos + size <= offset + len) { + i++; + pos += size; + } else { + frag->size -= pos + size - (offset + len); + break; + } + + frag++; + } + + skb_shinfo(nskb)->nr_frags = k; + nskb->data_len = len - hsize; + nskb->len += nskb->data_len; + nskb->truesize += nskb->data_len; + } while ((offset += len) < skb->len); + + return segs; + +err: + while ((skb = segs)) { + segs = skb->next; + kfree(skb); + } + return ERR_PTR(err); +} + +EXPORT_SYMBOL_GPL(skb_segment); + void __init skb_init(void) { skbuff_head_cache = kmem_cache_create("skbuff_head_cache", diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 0a277453526..461216b4794 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -68,6 +68,7 @@ */ #include +#include #include #include #include @@ -1096,6 +1097,54 @@ int inet_sk_rebuild_header(struct sock *sk) EXPORT_SYMBOL(inet_sk_rebuild_header); +static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int sg) +{ + struct sk_buff *segs = ERR_PTR(-EINVAL); + struct iphdr *iph; + struct net_protocol *ops; + int proto; + int ihl; + int id; + + if (!pskb_may_pull(skb, sizeof(*iph))) + goto out; + + iph = skb->nh.iph; + ihl = iph->ihl * 4; + if (ihl < sizeof(*iph)) + goto out; + + if (!pskb_may_pull(skb, ihl)) + goto out; + + skb->h.raw = __skb_pull(skb, ihl); + iph = skb->nh.iph; + id = ntohs(iph->id); + proto = iph->protocol & (MAX_INET_PROTOS - 1); + segs = ERR_PTR(-EPROTONOSUPPORT); + + rcu_read_lock(); + ops = rcu_dereference(inet_protos[proto]); + if (ops && ops->gso_segment) + segs = ops->gso_segment(skb, sg); + rcu_read_unlock(); + + if (IS_ERR(segs)) + goto out; + + skb = segs; + do { + iph = skb->nh.iph; + iph->id = htons(id++); + iph->tot_len = htons(skb->len - skb->mac_len); + iph->check = 0; + iph->check = ip_fast_csum(skb->nh.raw, iph->ihl); + } while ((skb = skb->next)); + +out: + return segs; +} + #ifdef CONFIG_IP_MULTICAST static struct net_protocol igmp_protocol = { .handler = igmp_rcv, @@ -1105,6 +1154,7 @@ static struct net_protocol igmp_protocol = { static struct net_protocol tcp_protocol = { .handler = tcp_v4_rcv, .err_handler = tcp_v4_err, + .gso_segment = tcp_tso_segment, .no_policy = 1, }; @@ -1150,6 +1200,7 @@ static int ipv4_proc_init(void); static struct packet_type ip_packet_type = { .type = __constant_htons(ETH_P_IP), .func = ip_rcv, + .gso_segment = inet_gso_segment, }; static int __init inet_init(void) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 062dd1a0d8a..0e029c4e290 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -258,6 +258,7 @@ #include #include #include +#include #include #include @@ -2144,6 +2145,67 @@ int compat_tcp_getsockopt(struct sock *sk, int level, int optname, EXPORT_SYMBOL(compat_tcp_getsockopt); #endif +struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int sg) +{ + struct sk_buff *segs = ERR_PTR(-EINVAL); + struct tcphdr *th; + unsigned thlen; + unsigned int seq; + unsigned int delta; + unsigned int oldlen; + unsigned int len; + + if (!pskb_may_pull(skb, sizeof(*th))) + goto out; + + th = skb->h.th; + thlen = th->doff * 4; + if (thlen < sizeof(*th)) + goto out; + + if (!pskb_may_pull(skb, thlen)) + goto out; + + oldlen = ~htonl(skb->len); + __skb_pull(skb, thlen); + + segs = skb_segment(skb, sg); + if (IS_ERR(segs)) + goto out; + + len = skb_shinfo(skb)->gso_size; + delta = csum_add(oldlen, htonl(thlen + len)); + + skb = segs; + th = skb->h.th; + seq = ntohl(th->seq); + + do { + th->fin = th->psh = 0; + + if (skb->ip_summed == CHECKSUM_NONE) { + th->check = csum_fold(csum_partial( + skb->h.raw, thlen, csum_add(skb->csum, delta))); + } + + seq += len; + skb = skb->next; + th = skb->h.th; + + th->seq = htonl(seq); + th->cwr = 0; + } while (skb->next); + + if (skb->ip_summed == CHECKSUM_NONE) { + delta = csum_add(oldlen, htonl(skb->tail - skb->h.raw)); + th->check = csum_fold(csum_partial( + skb->h.raw, thlen, csum_add(skb->csum, delta))); + } + +out: + return segs; +} + extern void __skb_cb_too_small_for_tcp(int, int); extern struct tcp_congestion_ops tcp_reno; -- cgit v1.2.3 From 37c3185a02d4b85fbe134bf5204535405dd2c957 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 22 Jun 2006 03:07:29 -0700 Subject: [NET]: Added GSO toggle This patch adds a generic segmentation offload toggle that can be turned on/off for each net device. For now it only supports in TCPv4. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- include/linux/ethtool.h | 2 ++ include/linux/netdevice.h | 1 + include/net/sock.h | 4 ++++ net/bridge/br_if.c | 17 +++++++++++------ net/core/ethtool.c | 29 +++++++++++++++++++++++++++++ 5 files changed, 47 insertions(+), 6 deletions(-) diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index cf2abeca92a..c6310aef5ab 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -411,6 +411,8 @@ struct ethtool_ops { #define ETHTOOL_GPERMADDR 0x00000020 /* Get permanent hardware address */ #define ETHTOOL_GUFO 0x00000021 /* Get UFO enable (ethtool_value) */ #define ETHTOOL_SUFO 0x00000022 /* Set UFO enable (ethtool_value) */ +#define ETHTOOL_GGSO 0x00000023 /* Get GSO enable (ethtool_value) */ +#define ETHTOOL_SGSO 0x00000024 /* Set GSO enable (ethtool_value) */ /* compatibility with older code */ #define SPARC_ETH_GSET ETHTOOL_GSET diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index b4eae18390c..bc747e5d713 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -308,6 +308,7 @@ struct net_device #define NETIF_F_HW_VLAN_RX 256 /* Receive VLAN hw acceleration */ #define NETIF_F_HW_VLAN_FILTER 512 /* Receive filtering on VLAN */ #define NETIF_F_VLAN_CHALLENGED 1024 /* Device cannot handle VLAN packets */ +#define NETIF_F_GSO 2048 /* Enable software GSO. */ #define NETIF_F_LLTX 4096 /* LockLess TX */ /* Segmentation offload features */ diff --git a/include/net/sock.h b/include/net/sock.h index d10dfecb6cb..a897f05de3b 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1030,9 +1030,13 @@ static inline void sk_setup_caps(struct sock *sk, struct dst_entry *dst) { __sk_dst_set(sk, dst); sk->sk_route_caps = dst->dev->features; + if (sk->sk_route_caps & NETIF_F_GSO) + sk->sk_route_caps |= NETIF_F_TSO; if (sk->sk_route_caps & NETIF_F_TSO) { if (sock_flag(sk, SOCK_NO_LARGESEND) || dst->header_len) sk->sk_route_caps &= ~NETIF_F_TSO; + else + sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM; } } diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index fdec773f5b5..07956ecf545 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -376,15 +376,20 @@ void br_features_recompute(struct net_bridge *br) features = br->feature_mask & ~NETIF_F_ALL_CSUM; list_for_each_entry(p, &br->port_list, list) { - if (checksum & NETIF_F_NO_CSUM && - !(p->dev->features & NETIF_F_NO_CSUM)) + unsigned long feature = p->dev->features; + + if (checksum & NETIF_F_NO_CSUM && !(feature & NETIF_F_NO_CSUM)) checksum ^= NETIF_F_NO_CSUM | NETIF_F_HW_CSUM; - if (checksum & NETIF_F_HW_CSUM && - !(p->dev->features & NETIF_F_HW_CSUM)) + if (checksum & NETIF_F_HW_CSUM && !(feature & NETIF_F_HW_CSUM)) checksum ^= NETIF_F_HW_CSUM | NETIF_F_IP_CSUM; - if (!(p->dev->features & NETIF_F_IP_CSUM)) + if (!(feature & NETIF_F_IP_CSUM)) checksum = 0; - features &= p->dev->features; + + if (feature & NETIF_F_GSO) + feature |= NETIF_F_TSO; + feature |= NETIF_F_GSO; + + features &= feature; } br->dev->features = features | checksum | NETIF_F_LLTX; diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 33ce7ed6afc..27ce1683caf 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -614,6 +614,29 @@ static int ethtool_set_ufo(struct net_device *dev, char __user *useraddr) return dev->ethtool_ops->set_ufo(dev, edata.data); } +static int ethtool_get_gso(struct net_device *dev, char __user *useraddr) +{ + struct ethtool_value edata = { ETHTOOL_GGSO }; + + edata.data = dev->features & NETIF_F_GSO; + if (copy_to_user(useraddr, &edata, sizeof(edata))) + return -EFAULT; + return 0; +} + +static int ethtool_set_gso(struct net_device *dev, char __user *useraddr) +{ + struct ethtool_value edata; + + if (copy_from_user(&edata, useraddr, sizeof(edata))) + return -EFAULT; + if (edata.data) + dev->features |= NETIF_F_GSO; + else + dev->features &= ~NETIF_F_GSO; + return 0; +} + static int ethtool_self_test(struct net_device *dev, char __user *useraddr) { struct ethtool_test test; @@ -905,6 +928,12 @@ int dev_ethtool(struct ifreq *ifr) case ETHTOOL_SUFO: rc = ethtool_set_ufo(dev, useraddr); break; + case ETHTOOL_GGSO: + rc = ethtool_get_gso(dev, useraddr); + break; + case ETHTOOL_SGSO: + rc = ethtool_set_gso(dev, useraddr); + break; default: rc = -EOPNOTSUPP; } -- cgit v1.2.3 From 09b8f7a93efd4b2c4ef391e2fbf076f28c6d36d6 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 22 Jun 2006 03:08:03 -0700 Subject: [IPSEC]: Handle GSO packets This patch segments GSO packets received by the IPsec stack. This can happen when a NIC driver injects GSO packets into the stack which are then forwarded to another host. The primary application of this is going to be Xen where its backend driver may inject GSO packets into dom0. Of course this also can be used by other virtualisation schemes such as VMWare or UML since the tap device could be modified to inject GSO packets received through splice. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/ipv4/xfrm4_output.c | 54 +++++++++++++++++++++++++++++++++++++++++-------- net/ipv6/xfrm6_output.c | 39 +++++++++++++++++++++++++++++++++-- 2 files changed, 83 insertions(+), 10 deletions(-) diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c index ac9d91d4bb0..193363e2293 100644 --- a/net/ipv4/xfrm4_output.c +++ b/net/ipv4/xfrm4_output.c @@ -9,6 +9,8 @@ */ #include +#include +#include #include #include #include @@ -97,16 +99,10 @@ error_nolock: goto out_exit; } -static int xfrm4_output_finish(struct sk_buff *skb) +static int xfrm4_output_finish2(struct sk_buff *skb) { int err; -#ifdef CONFIG_NETFILTER - if (!skb->dst->xfrm) { - IPCB(skb)->flags |= IPSKB_REROUTED; - return dst_output(skb); - } -#endif while (likely((err = xfrm4_output_one(skb)) == 0)) { nf_reset(skb); @@ -119,7 +115,7 @@ static int xfrm4_output_finish(struct sk_buff *skb) return dst_output(skb); err = nf_hook(PF_INET, NF_IP_POST_ROUTING, &skb, NULL, - skb->dst->dev, xfrm4_output_finish); + skb->dst->dev, xfrm4_output_finish2); if (unlikely(err != 1)) break; } @@ -127,6 +123,48 @@ static int xfrm4_output_finish(struct sk_buff *skb) return err; } +static int xfrm4_output_finish(struct sk_buff *skb) +{ + struct sk_buff *segs; + +#ifdef CONFIG_NETFILTER + if (!skb->dst->xfrm) { + IPCB(skb)->flags |= IPSKB_REROUTED; + return dst_output(skb); + } +#endif + + if (!skb_shinfo(skb)->gso_size) + return xfrm4_output_finish2(skb); + + skb->protocol = htons(ETH_P_IP); + segs = skb_gso_segment(skb, 0); + kfree_skb(skb); + if (unlikely(IS_ERR(segs))) + return PTR_ERR(segs); + + do { + struct sk_buff *nskb = segs->next; + int err; + + segs->next = NULL; + err = xfrm4_output_finish2(segs); + + if (unlikely(err)) { + while ((segs = nskb)) { + nskb = segs->next; + segs->next = NULL; + kfree_skb(segs); + } + return err; + } + + segs = nskb; + } while (segs); + + return 0; +} + int xfrm4_output(struct sk_buff *skb) { return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL, skb->dst->dev, diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c index 16e84254a25..48fccb1eca0 100644 --- a/net/ipv6/xfrm6_output.c +++ b/net/ipv6/xfrm6_output.c @@ -94,7 +94,7 @@ error_nolock: goto out_exit; } -static int xfrm6_output_finish(struct sk_buff *skb) +static int xfrm6_output_finish2(struct sk_buff *skb) { int err; @@ -110,7 +110,7 @@ static int xfrm6_output_finish(struct sk_buff *skb) return dst_output(skb); err = nf_hook(PF_INET6, NF_IP6_POST_ROUTING, &skb, NULL, - skb->dst->dev, xfrm6_output_finish); + skb->dst->dev, xfrm6_output_finish2); if (unlikely(err != 1)) break; } @@ -118,6 +118,41 @@ static int xfrm6_output_finish(struct sk_buff *skb) return err; } +static int xfrm6_output_finish(struct sk_buff *skb) +{ + struct sk_buff *segs; + + if (!skb_shinfo(skb)->gso_size) + return xfrm6_output_finish2(skb); + + skb->protocol = htons(ETH_P_IP); + segs = skb_gso_segment(skb, 0); + kfree_skb(skb); + if (unlikely(IS_ERR(segs))) + return PTR_ERR(segs); + + do { + struct sk_buff *nskb = segs->next; + int err; + + segs->next = NULL; + err = xfrm6_output_finish2(segs); + + if (unlikely(err)) { + while ((segs = nskb)) { + nskb = segs->next; + segs->next = NULL; + kfree_skb(segs); + } + return err; + } + + segs = nskb; + } while (segs); + + return 0; +} + int xfrm6_output(struct sk_buff *skb) { return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb, NULL, skb->dst->dev, -- cgit v1.2.3 From c8a553ad7f0bf943047943a758cf07017819cb3c Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Thu, 22 Jun 2006 14:28:09 -0700 Subject: [TCP]: Move inclusion of to correct place in The new header shouldn't be included from the !__KERNEL__ portion of tcp.h Signed-off-by: David Woodhouse Signed-off-by: David S. Miller --- include/linux/tcp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 420a689c3fb..8ebf497907f 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -18,7 +18,6 @@ #define _LINUX_TCP_H #include -#include #include struct tcphdr { @@ -161,6 +160,7 @@ struct tcp_info #ifdef __KERNEL__ #include +#include #include #include #include -- cgit v1.2.3 From f4b8ea7849544114e9d3d682df4d400180854677 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 22 Jun 2006 16:00:11 -0700 Subject: [NET]: fix net-core kernel-doc Warning(/var/linsrc/linux-2617-g4//include/linux/skbuff.h:304): No description found for parameter 'dma_cookie' Warning(/var/linsrc/linux-2617-g4//include/net/sock.h:1274): No description found for parameter 'copied_early' Warning(/var/linsrc/linux-2617-g4//net/core/dev.c:3309): No description found for parameter 'chan' Warning(/var/linsrc/linux-2617-g4//net/core/dev.c:3309): No description found for parameter 'event' Signed-off-by: Randy Dunlap Signed-off-by: David S. Miller --- include/linux/skbuff.h | 2 ++ include/net/sock.h | 1 + net/core/dev.c | 4 ++-- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index a45bba9b8cb..16eef03ce0e 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -215,6 +215,8 @@ enum { * @nf_bridge: Saved data about a bridged frame - see br_netfilter.c * @tc_index: Traffic control index * @tc_verd: traffic control verdict + * @dma_cookie: a cookie to one of several possible DMA operations + * done by skb DMA functions * @secmark: security marking */ diff --git a/include/net/sock.h b/include/net/sock.h index a897f05de3b..2d8d6adf161 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1269,6 +1269,7 @@ sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb) * sk_eat_skb - Release a skb if it is no longer needed * @sk: socket to eat this skb from * @skb: socket buffer to eat + * @copied_early: flag indicating whether DMA operations copied this data early * * This routine must be called with interrupts disabled or with the socket * locked so that the sk_buff queue operation is ok. diff --git a/net/core/dev.c b/net/core/dev.c index d293e0f90a0..9b8f0f22c81 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3418,8 +3418,8 @@ static void net_dma_rebalance(void) /** * netdev_dma_event - event callback for the net_dma_client * @client: should always be net_dma_client - * @chan: - * @event: + * @chan: DMA channel for the event + * @event: event type */ static void netdev_dma_event(struct dma_client *client, struct dma_chan *chan, enum dma_event event) -- cgit v1.2.3 From ca6bb5d7ab22ac79f608fe6cbc6b12de6a5a19f0 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Thu, 22 Jun 2006 16:07:52 -0700 Subject: [NET]: Require CAP_NET_ADMIN to create tuntap devices. The tuntap driver allows an admin to create persistent devices and assign ownership of them to individual users. Unfortunately, relaxing the permissions on the /dev/net/tun device node so that they can actually use those devices will _also_ allow those users to create arbitrary new devices of their own. This patch corrects that, and adjusts the recommended permissions for the device node accordingly. Signed-off-By: David Woodhouse Signed-off-by: David S. Miller --- Documentation/networking/tuntap.txt | 11 +++++++---- drivers/net/tun.c | 3 +++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Documentation/networking/tuntap.txt b/Documentation/networking/tuntap.txt index 76750fb9151..839cbb71388 100644 --- a/Documentation/networking/tuntap.txt +++ b/Documentation/networking/tuntap.txt @@ -39,10 +39,13 @@ Copyright (C) 1999-2000 Maxim Krasnyansky mknod /dev/net/tun c 10 200 Set permissions: - e.g. chmod 0700 /dev/net/tun - if you want the device only accessible by root. Giving regular users the - right to assign network devices is NOT a good idea. Users could assign - bogus network interfaces to trick firewalls or administrators. + e.g. chmod 0666 /dev/net/tun + There's no harm in allowing the device to be accessible by non-root users, + since CAP_NET_ADMIN is required for creating network devices or for + connecting to network devices which aren't owned by the user in question. + If you want to create persistent devices and give ownership of them to + unprivileged users, then you need the /dev/net/tun device to be usable by + those users. Driver module autoloading diff --git a/drivers/net/tun.c b/drivers/net/tun.c index a1ed2d98374..6c62d5c8826 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -490,6 +490,9 @@ static int tun_set_iff(struct file *file, struct ifreq *ifr) err = -EINVAL; + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + /* Set dev type */ if (ifr->ifr_flags & IFF_TUN) { /* TUN device */ -- cgit v1.2.3 From 1ad5544098a69d7dc1fa508cbb17e13a7a952fd8 Mon Sep 17 00:00:00 2001 From: Rachita Kothiyal Date: Fri, 23 Jun 2006 02:02:56 -0700 Subject: [PATCH] Fix cdrom being confused on using kdump I have seen the cdrom drive appearing confused on using kdump on certain x86_64 systems. During the booting up of the second kernel, the following message would keep flooding the console, and the booting would not proceed any further. hda: cdrom_pc_intr: The drive appears confused (ireason = 0x01) In this patch, whenever we are hitting a confused state in the interrupt handler with the DRQ set, we end the request and return ide_stopped. Using this I dont see the status error. Signed-off-by: Rachita Kothiyal Acked-by: Jens Axboe Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/ide-cd.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index b4a41d6d071..abb83d95df5 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -1451,9 +1451,12 @@ static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive) } else { confused: printk (KERN_ERR "%s: cdrom_pc_intr: The drive " - "appears confused (ireason = 0x%02x)\n", + "appears confused (ireason = 0x%02x). " + "Trying to recover by ending request.\n", drive->name, ireason); rq->flags |= REQ_FAILED; + cdrom_end_request(drive, 0); + return ide_stopped; } /* Now we wait for another interrupt. */ -- cgit v1.2.3 From 454e2398be9b9fa30433fccc548db34d19aa9958 Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 23 Jun 2006 02:02:57 -0700 Subject: [PATCH] VFS: Permit filesystem to override root dentry on mount Extend the get_sb() filesystem operation to take an extra argument that permits the VFS to pass in the target vfsmount that defines the mountpoint. The filesystem is then required to manually set the superblock and root dentry pointers. For most filesystems, this should be done with simple_set_mnt() which will set the superblock pointer and then set the root dentry to the superblock's s_root (as per the old default behaviour). The get_sb() op now returns an integer as there's now no need to return the superblock pointer. This patch permits a superblock to be implicitly shared amongst several mount points, such as can be done with NFS to avoid potential inode aliasing. In such a case, simple_set_mnt() would not be called, and instead the mnt_root and mnt_sb would be set directly. The patch also makes the following changes: (*) the get_sb_*() convenience functions in the core kernel now take a vfsmount pointer argument and return an integer, so most filesystems have to change very little. (*) If one of the convenience function is not used, then get_sb() should normally call simple_set_mnt() to instantiate the vfsmount. This will always return 0, and so can be tail-called from get_sb(). (*) generic_shutdown_super() now calls shrink_dcache_sb() to clean up the dcache upon superblock destruction rather than shrink_dcache_anon(). This is required because the superblock may now have multiple trees that aren't actually bound to s_root, but that still need to be cleaned up. The currently called functions assume that the whole tree is rooted at s_root, and that anonymous dentries are not the roots of trees which results in dentries being left unculled. However, with the way NFS superblock sharing are currently set to be implemented, these assumptions are violated: the root of the filesystem is simply a dummy dentry and inode (the real inode for '/' may well be inaccessible), and all the vfsmounts are rooted on anonymous[*] dentries with child trees. [*] Anonymous until discovered from another tree. (*) The documentation has been adjusted, including the additional bit of changing ext2_* into foo_* in the documentation. [akpm@osdl.org: convert ipath_fs, do other stuff] Signed-off-by: David Howells Acked-by: Al Viro Cc: Nathan Scott Cc: Roland Dreier Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/filesystems/Locking | 7 +- Documentation/filesystems/porting | 7 +- Documentation/filesystems/vfs.txt | 4 +- arch/ia64/kernel/perfmon.c | 7 +- arch/powerpc/platforms/cell/spufs/inode.c | 6 +- drivers/infiniband/core/uverbs_main.c | 7 +- drivers/infiniband/hw/ipath/ipath_fs.c | 13 ++-- drivers/isdn/capi/capifs.c | 6 +- drivers/misc/ibmasm/ibmasmfs.c | 7 +- drivers/oprofile/oprofilefs.c | 6 +- drivers/usb/core/inode.c | 6 +- drivers/usb/gadget/inode.c | 6 +- fs/9p/vfs_super.c | 21 +++--- fs/adfs/super.c | 7 +- fs/affs/super.c | 7 +- fs/afs/super.c | 24 ++++--- fs/autofs/init.c | 6 +- fs/autofs4/init.c | 6 +- fs/befs/linuxvfs.c | 7 +- fs/bfs/inode.c | 6 +- fs/binfmt_misc.c | 6 +- fs/block_dev.c | 6 +- fs/cifs/cifsfs.c | 10 +-- fs/coda/inode.c | 6 +- fs/configfs/mount.c | 6 +- fs/cramfs/inode.c | 7 +- fs/dcache.c | 40 ----------- fs/debugfs/inode.c | 8 +-- fs/devfs/base.c | 8 +-- fs/devpts/inode.c | 6 +- fs/efs/super.c | 6 +- fs/eventpoll.c | 13 ++-- fs/ext2/super.c | 6 +- fs/ext3/super.c | 6 +- fs/freevxfs/vxfs_super.c | 7 +- fs/fuse/inode.c | 8 +-- fs/hfs/super.c | 7 +- fs/hfsplus/super.c | 8 ++- fs/hostfs/hostfs_kern.c | 8 +-- fs/hpfs/super.c | 7 +- fs/hppfs/hppfs_kern.c | 8 +-- fs/hugetlbfs/inode.c | 6 +- fs/inotify_user.c | 6 +- fs/isofs/inode.c | 7 +- fs/jffs/inode-v23.c | 7 +- fs/jffs2/super.c | 49 ++++++++------ fs/jfs/super.c | 7 +- fs/libfs.c | 12 ++-- fs/minix/inode.c | 7 +- fs/msdos/namei.c | 9 +-- fs/namespace.c | 9 +++ fs/ncpfs/inode.c | 6 +- fs/nfs/inode.c | 96 +++++++++++++++----------- fs/nfsd/nfsctl.c | 6 +- fs/ntfs/super.c | 7 +- fs/ocfs2/dlm/dlmfs.c | 6 +- fs/ocfs2/super.c | 12 ++-- fs/openpromfs/inode.c | 6 +- fs/pipe.c | 9 ++- fs/proc/root.c | 6 +- fs/qnx4/inode.c | 7 +- fs/ramfs/inode.c | 13 ++-- fs/reiserfs/super.c | 9 +-- fs/romfs/inode.c | 7 +- fs/smbfs/inode.c | 6 +- fs/super.c | 109 +++++++++++++++++------------- fs/sysfs/mount.c | 6 +- fs/sysv/super.c | 13 ++-- fs/udf/super.c | 6 +- fs/ufs/super.c | 6 +- fs/vfat/namei.c | 9 +-- fs/xfs/linux-2.6/xfs_super.c | 8 ++- include/linux/dcache.h | 1 - include/linux/fs.h | 25 ++++--- include/linux/ramfs.h | 4 +- ipc/mqueue.c | 8 +-- kernel/cpuset.c | 8 +-- kernel/futex.c | 8 +-- mm/shmem.c | 6 +- net/socket.c | 7 +- net/sunrpc/rpc_pipe.c | 6 +- security/inode.c | 8 +-- security/selinux/selinuxfs.c | 7 +- 83 files changed, 482 insertions(+), 431 deletions(-) diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index 1045da582b9..3abf08f1b14 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking @@ -142,15 +142,16 @@ see also dquot_operations section. --------------------------- file_system_type --------------------------- prototypes: - struct super_block *(*get_sb) (struct file_system_type *, int, - const char *, void *); + struct int (*get_sb) (struct file_system_type *, int, + const char *, void *, struct vfsmount *); void (*kill_sb) (struct super_block *); locking rules: may block BKL get_sb yes yes kill_sb yes yes -->get_sb() returns error or a locked superblock (exclusive on ->s_umount). +->get_sb() returns error or 0 with locked superblock attached to the vfsmount +(exclusive on ->s_umount). ->kill_sb() takes a write-locked superblock, does all shutdown work on it, unlocks and drops the reference. diff --git a/Documentation/filesystems/porting b/Documentation/filesystems/porting index 2f388460cbe..5531694059a 100644 --- a/Documentation/filesystems/porting +++ b/Documentation/filesystems/porting @@ -50,10 +50,11 @@ Turn your foo_read_super() into a function that would return 0 in case of success and negative number in case of error (-EINVAL unless you have more informative error value to report). Call it foo_fill_super(). Now declare -struct super_block foo_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +int foo_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, ext2_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, foo_fill_super, + mnt); } (or similar with s/bdev/nodev/ or s/bdev/single/, depending on the kind of diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index 3a2e5520c1e..dd7d0dcedc8 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt @@ -113,8 +113,8 @@ members are defined: struct file_system_type { const char *name; int fs_flags; - struct super_block *(*get_sb) (struct file_system_type *, int, - const char *, void *); + struct int (*get_sb) (struct file_system_type *, int, + const char *, void *, struct vfsmount *); void (*kill_sb) (struct super_block *); struct module *owner; struct file_system_type * next; diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index 077f21216b6..2359e2809f5 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c @@ -595,10 +595,11 @@ pfm_get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, } -static struct super_block * -pfmfs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) +static int +pfmfs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, + struct vfsmount *mnt) { - return get_sb_pseudo(fs_type, "pfm:", NULL, PFMFS_MAGIC); + return get_sb_pseudo(fs_type, "pfm:", NULL, PFMFS_MAGIC, mnt); } static struct file_system_type pfm_fs_type = { diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index 1987697b23a..7b4572805db 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c @@ -436,11 +436,11 @@ spufs_fill_super(struct super_block *sb, void *data, int silent) return spufs_create_root(sb, data); } -static struct super_block * +static int spufs_get_sb(struct file_system_type *fstype, int flags, - const char *name, void *data) + const char *name, void *data, struct vfsmount *mnt) { - return get_sb_single(fstype, flags, data, spufs_fill_super); + return get_sb_single(fstype, flags, data, spufs_fill_super, mnt); } static struct file_system_type spufs_type = { diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index 5ec2d49e9bb..e57d3c50f75 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c @@ -821,11 +821,12 @@ static void ib_uverbs_remove_one(struct ib_device *device) kref_put(&uverbs_dev->ref, ib_uverbs_release_dev); } -static struct super_block *uverbs_event_get_sb(struct file_system_type *fs_type, int flags, - const char *dev_name, void *data) +static int uverbs_event_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data, + struct vfsmount *mnt) { return get_sb_pseudo(fs_type, "infinibandevent:", NULL, - INFINIBANDEVENTFS_MAGIC); + INFINIBANDEVENTFS_MAGIC, mnt); } static struct file_system_type uverbs_event_fs = { diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c index e274120567e..63de3046aff 100644 --- a/drivers/infiniband/hw/ipath/ipath_fs.c +++ b/drivers/infiniband/hw/ipath/ipath_fs.c @@ -542,13 +542,14 @@ bail: return ret; } -static struct super_block *ipathfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, - void *data) +static int ipathfs_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data, struct vfsmount *mnt) { - ipath_super = get_sb_single(fs_type, flags, data, - ipathfs_fill_super); - return ipath_super; + int ret = get_sb_single(fs_type, flags, data, + ipathfs_fill_super, mnt); + if (ret >= 0) + ipath_super = mnt->mnt_sb; + return ret; } static void ipathfs_kill_super(struct super_block *s) diff --git a/drivers/isdn/capi/capifs.c b/drivers/isdn/capi/capifs.c index 0a37aded4b5..9ea6bd0ddc3 100644 --- a/drivers/isdn/capi/capifs.c +++ b/drivers/isdn/capi/capifs.c @@ -121,10 +121,10 @@ fail: return -ENOMEM; } -static struct super_block *capifs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int capifs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_single(fs_type, flags, data, capifs_fill_super); + return get_sb_single(fs_type, flags, data, capifs_fill_super, mnt); } static struct file_system_type capifs_fs_type = { diff --git a/drivers/misc/ibmasm/ibmasmfs.c b/drivers/misc/ibmasm/ibmasmfs.c index 26a230b6ff8..4a35caff5d0 100644 --- a/drivers/misc/ibmasm/ibmasmfs.c +++ b/drivers/misc/ibmasm/ibmasmfs.c @@ -90,10 +90,11 @@ static void ibmasmfs_create_files (struct super_block *sb, struct dentry *root); static int ibmasmfs_fill_super (struct super_block *sb, void *data, int silent); -static struct super_block *ibmasmfs_get_super(struct file_system_type *fst, - int flags, const char *name, void *data) +static int ibmasmfs_get_super(struct file_system_type *fst, + int flags, const char *name, void *data, + struct vfsmount *mnt) { - return get_sb_single(fst, flags, data, ibmasmfs_fill_super); + return get_sb_single(fst, flags, data, ibmasmfs_fill_super, mnt); } static struct super_operations ibmasmfs_s_ops = { diff --git a/drivers/oprofile/oprofilefs.c b/drivers/oprofile/oprofilefs.c index b62da9b0cbf..71c2da277d6 100644 --- a/drivers/oprofile/oprofilefs.c +++ b/drivers/oprofile/oprofilefs.c @@ -272,10 +272,10 @@ static int oprofilefs_fill_super(struct super_block * sb, void * data, int silen } -static struct super_block *oprofilefs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int oprofilefs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_single(fs_type, flags, data, oprofilefs_fill_super); + return get_sb_single(fs_type, flags, data, oprofilefs_fill_super, mnt); } diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c index 3cf945cc5b9..95f5ad923b0 100644 --- a/drivers/usb/core/inode.c +++ b/drivers/usb/core/inode.c @@ -543,10 +543,10 @@ static void fs_remove_file (struct dentry *dentry) /* --------------------------------------------------------------------- */ -static struct super_block *usb_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int usb_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_single(fs_type, flags, data, usbfs_fill_super); + return get_sb_single(fs_type, flags, data, usbfs_fill_super, mnt); } static struct file_system_type usb_fs_type = { diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index aef0722b8f1..3bdc5e3ba23 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c @@ -2070,11 +2070,11 @@ enomem0: } /* "mount -t gadgetfs path /dev/gadget" ends up here */ -static struct super_block * +static int gadgetfs_get_sb (struct file_system_type *t, int flags, - const char *path, void *opts) + const char *path, void *opts, struct vfsmount *mnt) { - return get_sb_single (t, flags, opts, gadgetfs_fill_super); + return get_sb_single (t, flags, opts, gadgetfs_fill_super, mnt); } static void diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index 61c599b4a1e..872943004e5 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c @@ -99,12 +99,13 @@ v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses, * @flags: mount flags * @dev_name: device name that was mounted * @data: mount options + * @mnt: mountpoint record to be instantiated * */ -static struct super_block *v9fs_get_sb(struct file_system_type - *fs_type, int flags, - const char *dev_name, void *data) +static int v9fs_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data, + struct vfsmount *mnt) { struct super_block *sb = NULL; struct v9fs_fcall *fcall = NULL; @@ -123,17 +124,19 @@ static struct super_block *v9fs_get_sb(struct file_system_type v9ses = kzalloc(sizeof(struct v9fs_session_info), GFP_KERNEL); if (!v9ses) - return ERR_PTR(-ENOMEM); + return -ENOMEM; if ((newfid = v9fs_session_init(v9ses, dev_name, data)) < 0) { dprintk(DEBUG_ERROR, "problem initiating session\n"); - sb = ERR_PTR(newfid); + retval = newfid; goto out_free_session; } sb = sget(fs_type, NULL, v9fs_set_super, v9ses); - if (IS_ERR(sb)) + if (IS_ERR(sb)) { + retval = PTR_ERR(sb); goto out_close_session; + } v9fs_fill_super(sb, v9ses, flags); inode = v9fs_get_inode(sb, S_IFDIR | mode); @@ -184,19 +187,19 @@ static struct super_block *v9fs_get_sb(struct file_system_type goto put_back_sb; } - return sb; + return simple_set_mnt(mnt, sb); out_close_session: v9fs_session_close(v9ses); out_free_session: kfree(v9ses); - return sb; + return retval; put_back_sb: /* deactivate_super calls v9fs_kill_super which will frees the rest */ up_write(&sb->s_umount); deactivate_super(sb); - return ERR_PTR(retval); + return retval; } /** diff --git a/fs/adfs/super.c b/fs/adfs/super.c index 252abda0d20..1b58a9b7f6a 100644 --- a/fs/adfs/super.c +++ b/fs/adfs/super.c @@ -470,10 +470,11 @@ error: return -EINVAL; } -static struct super_block *adfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int adfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, adfs_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, adfs_fill_super, + mnt); } static struct file_system_type adfs_fs_type = { diff --git a/fs/affs/super.c b/fs/affs/super.c index 4d7e5b19e5c..6a52e787540 100644 --- a/fs/affs/super.c +++ b/fs/affs/super.c @@ -524,10 +524,11 @@ affs_statfs(struct super_block *sb, struct kstatfs *buf) return 0; } -static struct super_block *affs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int affs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, affs_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, affs_fill_super, + mnt); } static struct file_system_type affs_fs_type = { diff --git a/fs/afs/super.c b/fs/afs/super.c index 53c56e7231a..82468df0ba5 100644 --- a/fs/afs/super.c +++ b/fs/afs/super.c @@ -38,9 +38,9 @@ struct afs_mount_params { static void afs_i_init_once(void *foo, kmem_cache_t *cachep, unsigned long flags); -static struct super_block *afs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, - void *data); +static int afs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, + void *data, struct vfsmount *mnt); static struct inode *afs_alloc_inode(struct super_block *sb); @@ -294,10 +294,11 @@ static int afs_fill_super(struct super_block *sb, void *data, int silent) * get an AFS superblock * - TODO: don't use get_sb_nodev(), but rather call sget() directly */ -static struct super_block *afs_get_sb(struct file_system_type *fs_type, - int flags, - const char *dev_name, - void *options) +static int afs_get_sb(struct file_system_type *fs_type, + int flags, + const char *dev_name, + void *options, + struct vfsmount *mnt) { struct afs_mount_params params; struct super_block *sb; @@ -311,7 +312,7 @@ static struct super_block *afs_get_sb(struct file_system_type *fs_type, ret = afscm_start(); if (ret < 0) { _leave(" = %d", ret); - return ERR_PTR(ret); + return ret; } /* parse the options */ @@ -348,18 +349,19 @@ static struct super_block *afs_get_sb(struct file_system_type *fs_type, goto error; } sb->s_flags |= MS_ACTIVE; + simple_set_mnt(mnt, sb); afs_put_volume(params.volume); afs_put_cell(params.default_cell); - _leave(" = %p", sb); - return sb; + _leave(" = 0 [%p]", 0, sb); + return 0; error: afs_put_volume(params.volume); afs_put_cell(params.default_cell); afscm_stop(); _leave(" = %d", ret); - return ERR_PTR(ret); + return ret; } /* end afs_get_sb() */ /*****************************************************************************/ diff --git a/fs/autofs/init.c b/fs/autofs/init.c index b977ece69f0..aca12375240 100644 --- a/fs/autofs/init.c +++ b/fs/autofs/init.c @@ -14,10 +14,10 @@ #include #include "autofs_i.h" -static struct super_block *autofs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int autofs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_nodev(fs_type, flags, data, autofs_fill_super); + return get_sb_nodev(fs_type, flags, data, autofs_fill_super, mnt); } static struct file_system_type autofs_fs_type = { diff --git a/fs/autofs4/init.c b/fs/autofs4/init.c index acecec8578c..5d9193332be 100644 --- a/fs/autofs4/init.c +++ b/fs/autofs4/init.c @@ -14,10 +14,10 @@ #include #include "autofs_i.h" -static struct super_block *autofs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int autofs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_nodev(fs_type, flags, data, autofs4_fill_super); + return get_sb_nodev(fs_type, flags, data, autofs4_fill_super, mnt); } static struct file_system_type autofs_fs_type = { diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index 68ebd10f345..6ed07a5f10c 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c @@ -899,11 +899,12 @@ befs_statfs(struct super_block *sb, struct kstatfs *buf) return 0; } -static struct super_block * +static int befs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, - void *data) + void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, befs_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, befs_fill_super, + mnt); } static struct file_system_type befs_fs_type = { diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c index 55a7a78332f..e7da03f63a5 100644 --- a/fs/bfs/inode.c +++ b/fs/bfs/inode.c @@ -410,10 +410,10 @@ out: return -EINVAL; } -static struct super_block *bfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int bfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, bfs_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, bfs_fill_super, mnt); } static struct file_system_type bfs_fs_type = { diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index 599f36fd0f6..07a4996cca3 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c @@ -739,10 +739,10 @@ static int bm_fill_super(struct super_block * sb, void * data, int silent) return err; } -static struct super_block *bm_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int bm_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_single(fs_type, flags, data, bm_fill_super); + return get_sb_single(fs_type, flags, data, bm_fill_super, mnt); } static struct linux_binfmt misc_format = { diff --git a/fs/block_dev.c b/fs/block_dev.c index 44aaba202f7..028d9fb9c2d 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -300,10 +300,10 @@ static struct super_operations bdev_sops = { .clear_inode = bdev_clear_inode, }; -static struct super_block *bd_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int bd_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_pseudo(fs_type, "bdev:", &bdev_sops, 0x62646576); + return get_sb_pseudo(fs_type, "bdev:", &bdev_sops, 0x62646576, mnt); } static struct file_system_type bd_type = { diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index c262d8874ce..08b35801dfe 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -460,9 +460,9 @@ struct super_operations cifs_super_ops = { .remount_fs = cifs_remount, }; -static struct super_block * +static int cifs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { int rc; struct super_block *sb = sget(fs_type, NULL, set_anon_super, NULL); @@ -470,7 +470,7 @@ cifs_get_sb(struct file_system_type *fs_type, cFYI(1, ("Devname: %s flags: %d ", dev_name, flags)); if (IS_ERR(sb)) - return sb; + return PTR_ERR(sb); sb->s_flags = flags; @@ -478,10 +478,10 @@ cifs_get_sb(struct file_system_type *fs_type, if (rc) { up_write(&sb->s_umount); deactivate_super(sb); - return ERR_PTR(rc); + return rc; } sb->s_flags |= MS_ACTIVE; - return sb; + return simple_set_mnt(mnt, sb); } static ssize_t cifs_file_writev(struct file *file, const struct iovec *iov, diff --git a/fs/coda/inode.c b/fs/coda/inode.c index ada1a81df6b..cba70201567 100644 --- a/fs/coda/inode.c +++ b/fs/coda/inode.c @@ -307,10 +307,10 @@ static int coda_statfs(struct super_block *sb, struct kstatfs *buf) /* init_coda: used by filesystems.c to register coda */ -static struct super_block *coda_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int coda_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_nodev(fs_type, flags, data, coda_fill_super); + return get_sb_nodev(fs_type, flags, data, coda_fill_super, mnt); } struct file_system_type coda_fs_type = { diff --git a/fs/configfs/mount.c b/fs/configfs/mount.c index f920d30478e..94dab7bdd85 100644 --- a/fs/configfs/mount.c +++ b/fs/configfs/mount.c @@ -103,10 +103,10 @@ static int configfs_fill_super(struct super_block *sb, void *data, int silent) return 0; } -static struct super_block *configfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int configfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_single(fs_type, flags, data, configfs_fill_super); + return get_sb_single(fs_type, flags, data, configfs_fill_super, mnt); } static struct file_system_type configfs_fs_type = { diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c index 9efcc3a164e..37a91a153aa 100644 --- a/fs/cramfs/inode.c +++ b/fs/cramfs/inode.c @@ -528,10 +528,11 @@ static struct super_operations cramfs_ops = { .statfs = cramfs_statfs, }; -static struct super_block *cramfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int cramfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, cramfs_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, cramfs_fill_super, + mnt); } static struct file_system_type cramfs_fs_type = { diff --git a/fs/dcache.c b/fs/dcache.c index 59dbc92c207..313b54b2b8f 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -687,46 +687,6 @@ void shrink_dcache_parent(struct dentry * parent) prune_dcache(found, parent->d_sb); } -/** - * shrink_dcache_anon - further prune the cache - * @head: head of d_hash list of dentries to prune - * - * Prune the dentries that are anonymous - * - * parsing d_hash list does not hlist_for_each_entry_rcu() as it - * done under dcache_lock. - * - */ -void shrink_dcache_anon(struct super_block *sb) -{ - struct hlist_node *lp; - struct hlist_head *head = &sb->s_anon; - int found; - do { - found = 0; - spin_lock(&dcache_lock); - hlist_for_each(lp, head) { - struct dentry *this = hlist_entry(lp, struct dentry, d_hash); - if (!list_empty(&this->d_lru)) { - dentry_stat.nr_unused--; - list_del_init(&this->d_lru); - } - - /* - * move only zero ref count dentries to the end - * of the unused list for prune_dcache - */ - if (!atomic_read(&this->d_count)) { - list_add_tail(&this->d_lru, &dentry_unused); - dentry_stat.nr_unused++; - found++; - } - } - spin_unlock(&dcache_lock); - prune_dcache(found, sb); - } while(found); -} - /* * Scan `nr' dentries and return the number which remain. * diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index b55b4ea9a67..440128ebef3 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -111,11 +111,11 @@ static int debug_fill_super(struct super_block *sb, void *data, int silent) return simple_fill_super(sb, DEBUGFS_MAGIC, debug_files); } -static struct super_block *debug_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, - void *data) +static int debug_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, + void *data, struct vfsmount *mnt) { - return get_sb_single(fs_type, flags, data, debug_fill_super); + return get_sb_single(fs_type, flags, data, debug_fill_super, mnt); } static struct file_system_type debug_fs_type = { diff --git a/fs/devfs/base.c b/fs/devfs/base.c index 52f5059c4f3..51a97f13274 100644 --- a/fs/devfs/base.c +++ b/fs/devfs/base.c @@ -2549,11 +2549,11 @@ static int devfs_fill_super(struct super_block *sb, void *data, int silent) return -EINVAL; } /* End Function devfs_fill_super */ -static struct super_block *devfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, - void *data) +static int devfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, + void *data, struct vfsmount *mnt) { - return get_sb_single(fs_type, flags, data, devfs_fill_super); + return get_sb_single(fs_type, flags, data, devfs_fill_super, mnt); } static struct file_system_type devfs_fs_type = { diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c index 14c5620b5ca..f7aef5bb584 100644 --- a/fs/devpts/inode.c +++ b/fs/devpts/inode.c @@ -130,10 +130,10 @@ fail: return -ENOMEM; } -static struct super_block *devpts_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int devpts_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_single(fs_type, flags, data, devpts_fill_super); + return get_sb_single(fs_type, flags, data, devpts_fill_super, mnt); } static struct file_system_type devpts_fs_type = { diff --git a/fs/efs/super.c b/fs/efs/super.c index dff623e3ddb..1ba5e14f879 100644 --- a/fs/efs/super.c +++ b/fs/efs/super.c @@ -18,10 +18,10 @@ static int efs_statfs(struct super_block *s, struct kstatfs *buf); static int efs_fill_super(struct super_block *s, void *d, int silent); -static struct super_block *efs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int efs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, efs_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, efs_fill_super, mnt); } static struct file_system_type efs_fs_type = { diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 2695337d4d6..08e7e6a555c 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -268,9 +268,9 @@ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events, int maxevents, long timeout); static int eventpollfs_delete_dentry(struct dentry *dentry); static struct inode *ep_eventpoll_inode(void); -static struct super_block *eventpollfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, - void *data); +static int eventpollfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, + void *data, struct vfsmount *mnt); /* * This semaphore is used to serialize ep_free() and eventpoll_release_file(). @@ -1595,11 +1595,12 @@ eexit_1: } -static struct super_block * +static int eventpollfs_get_sb(struct file_system_type *fs_type, int flags, - const char *dev_name, void *data) + const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_pseudo(fs_type, "eventpoll:", NULL, EVENTPOLLFS_MAGIC); + return get_sb_pseudo(fs_type, "eventpoll:", NULL, EVENTPOLLFS_MAGIC, + mnt); } diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 7e30bae174e..a4dfffac596 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c @@ -1087,10 +1087,10 @@ static int ext2_statfs (struct super_block * sb, struct kstatfs * buf) return 0; } -static struct super_block *ext2_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int ext2_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, ext2_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, ext2_fill_super, mnt); } #ifdef CONFIG_QUOTA diff --git a/fs/ext3/super.c b/fs/ext3/super.c index f8a5266ea1f..657f8e73b62 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -2646,10 +2646,10 @@ out: #endif -static struct super_block *ext3_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int ext3_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, ext3_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, ext3_fill_super, mnt); } static struct file_system_type ext3_fs_type = { diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c index b44c916d24a..d76eeaafbde 100644 --- a/fs/freevxfs/vxfs_super.c +++ b/fs/freevxfs/vxfs_super.c @@ -241,10 +241,11 @@ out: /* * The usual module blurb. */ -static struct super_block *vxfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int vxfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, vxfs_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, vxfs_fill_super, + mnt); } static struct file_system_type vxfs_fs_type = { diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 7627022446b..c91f0a50aad 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -569,11 +569,11 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) return err; } -static struct super_block *fuse_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, - void *raw_data) +static int fuse_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, + void *raw_data, struct vfsmount *mnt) { - return get_sb_nodev(fs_type, flags, raw_data, fuse_fill_super); + return get_sb_nodev(fs_type, flags, raw_data, fuse_fill_super, mnt); } static struct file_system_type fuse_fs_type = { diff --git a/fs/hfs/super.c b/fs/hfs/super.c index 1181d116117..ee5b80a409e 100644 --- a/fs/hfs/super.c +++ b/fs/hfs/super.c @@ -413,10 +413,11 @@ bail: return res; } -static struct super_block *hfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int hfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, + struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, hfs_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, hfs_fill_super, mnt); } static struct file_system_type hfs_fs_type = { diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index 7843f792a4b..0ed8b7e8e87 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c @@ -450,10 +450,12 @@ static void hfsplus_destroy_inode(struct inode *inode) #define HFSPLUS_INODE_SIZE sizeof(struct hfsplus_inode_info) -static struct super_block *hfsplus_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int hfsplus_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, + struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, hfsplus_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, hfsplus_fill_super, + mnt); } static struct file_system_type hfsplus_fs_type = { diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index bf0f8e16e43..04035e08f5c 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -993,11 +993,11 @@ static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent) return(err); } -static struct super_block *hostfs_read_sb(struct file_system_type *type, - int flags, const char *dev_name, - void *data) +static int hostfs_read_sb(struct file_system_type *type, + int flags, const char *dev_name, + void *data, struct vfsmount *mnt) { - return(get_sb_nodev(type, flags, data, hostfs_fill_sb_common)); + return get_sb_nodev(type, flags, data, hostfs_fill_sb_common, mnt); } static struct file_system_type hostfs_type = { diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c index d72d8c87c99..3b25cf3e2e6 100644 --- a/fs/hpfs/super.c +++ b/fs/hpfs/super.c @@ -662,10 +662,11 @@ bail0: return -EINVAL; } -static struct super_block *hpfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int hpfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, hpfs_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, hpfs_fill_super, + mnt); } static struct file_system_type hpfs_fs_type = { diff --git a/fs/hppfs/hppfs_kern.c b/fs/hppfs/hppfs_kern.c index 5e6363be246..ec43c22bc9c 100644 --- a/fs/hppfs/hppfs_kern.c +++ b/fs/hppfs/hppfs_kern.c @@ -769,11 +769,11 @@ static int hppfs_fill_super(struct super_block *sb, void *d, int silent) return(err); } -static struct super_block *hppfs_read_super(struct file_system_type *type, - int flags, const char *dev_name, - void *data) +static int hppfs_read_super(struct file_system_type *type, + int flags, const char *dev_name, + void *data, struct vfsmount *mnt) { - return(get_sb_nodev(type, flags, data, hppfs_fill_super)); + return get_sb_nodev(type, flags, data, hppfs_fill_super, mnt); } static struct file_system_type hppfs_type = { diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 3a5b4e92345..4665c26171f 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -723,10 +723,10 @@ void hugetlb_put_quota(struct address_space *mapping) } } -static struct super_block *hugetlbfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int hugetlbfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_nodev(fs_type, flags, data, hugetlbfs_fill_super); + return get_sb_nodev(fs_type, flags, data, hugetlbfs_fill_super, mnt); } static struct file_system_type hugetlbfs_fs_type = { diff --git a/fs/inotify_user.c b/fs/inotify_user.c index 9e9931e2bad..f2386442ade 100644 --- a/fs/inotify_user.c +++ b/fs/inotify_user.c @@ -672,11 +672,11 @@ out: return ret; } -static struct super_block * +static int inotify_get_sb(struct file_system_type *fs_type, int flags, - const char *dev_name, void *data) + const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_pseudo(fs_type, "inotify", NULL, 0xBAD1DEA); + return get_sb_pseudo(fs_type, "inotify", NULL, 0xBAD1DEA, mnt); } static struct file_system_type inotify_fs_type = { diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index 70adbb98bad..17268da63a4 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -1399,10 +1399,11 @@ struct inode *isofs_iget(struct super_block *sb, return inode; } -static struct super_block *isofs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int isofs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, isofs_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, isofs_fill_super, + mnt); } static struct file_system_type iso9660_fs_type = { diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c index 020cc097c53..dd93a091ad6 100644 --- a/fs/jffs/inode-v23.c +++ b/fs/jffs/inode-v23.c @@ -1785,10 +1785,11 @@ static struct super_operations jffs_ops = .remount_fs = jffs_remount, }; -static struct super_block *jffs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int jffs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, jffs_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, jffs_fill_super, + mnt); } static struct file_system_type jffs_fs_type = { diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c index 9d0521451f5..2378a662c25 100644 --- a/fs/jffs2/super.c +++ b/fs/jffs2/super.c @@ -111,9 +111,10 @@ static int jffs2_sb_set(struct super_block *sb, void *data) return 0; } -static struct super_block *jffs2_get_sb_mtd(struct file_system_type *fs_type, - int flags, const char *dev_name, - void *data, struct mtd_info *mtd) +static int jffs2_get_sb_mtd(struct file_system_type *fs_type, + int flags, const char *dev_name, + void *data, struct mtd_info *mtd, + struct vfsmount *mnt) { struct super_block *sb; struct jffs2_sb_info *c; @@ -121,19 +122,20 @@ static struct super_block *jffs2_get_sb_mtd(struct file_system_type *fs_type, c = kmalloc(sizeof(*c), GFP_KERNEL); if (!c) - return ERR_PTR(-ENOMEM); + return -ENOMEM; memset(c, 0, sizeof(*c)); c->mtd = mtd; sb = sget(fs_type, jffs2_sb_compare, jffs2_sb_set, c); if (IS_ERR(sb)) - goto out_put; + goto out_error; if (sb->s_root) { /* New mountpoint for JFFS2 which is already mounted */ D1(printk(KERN_DEBUG "jffs2_get_sb_mtd(): Device %d (\"%s\") is already mounted\n", mtd->index, mtd->name)); + ret = simple_set_mnt(mnt, sb); goto out_put; } @@ -161,44 +163,47 @@ static struct super_block *jffs2_get_sb_mtd(struct file_system_type *fs_type, /* Failure case... */ up_write(&sb->s_umount); deactivate_super(sb); - return ERR_PTR(ret); + return ret; } sb->s_flags |= MS_ACTIVE; - return sb; + return simple_set_mnt(mnt, sb); +out_error: + ret = PTR_ERR(sb); out_put: kfree(c); put_mtd_device(mtd); - return sb; + return ret; } -static struct super_block *jffs2_get_sb_mtdnr(struct file_system_type *fs_type, - int flags, const char *dev_name, - void *data, int mtdnr) +static int jffs2_get_sb_mtdnr(struct file_system_type *fs_type, + int flags, const char *dev_name, + void *data, int mtdnr, + struct vfsmount *mnt) { struct mtd_info *mtd; mtd = get_mtd_device(NULL, mtdnr); if (!mtd) { D1(printk(KERN_DEBUG "jffs2: MTD device #%u doesn't appear to exist\n", mtdnr)); - return ERR_PTR(-EINVAL); + return -EINVAL; } - return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd); + return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd, mnt); } -static struct super_block *jffs2_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, - void *data) +static int jffs2_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, + void *data, struct vfsmount *mnt) { int err; struct nameidata nd; int mtdnr; if (!dev_name) - return ERR_PTR(-EINVAL); + return -EINVAL; D1(printk(KERN_DEBUG "jffs2_get_sb(): dev_name \"%s\"\n", dev_name)); @@ -220,7 +225,7 @@ static struct super_block *jffs2_get_sb(struct file_system_type *fs_type, mtd = get_mtd_device(NULL, mtdnr); if (mtd) { if (!strcmp(mtd->name, dev_name+4)) - return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd); + return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd, mnt); put_mtd_device(mtd); } } @@ -233,7 +238,7 @@ static struct super_block *jffs2_get_sb(struct file_system_type *fs_type, if (!*endptr) { /* It was a valid number */ D1(printk(KERN_DEBUG "jffs2_get_sb(): mtd%%d, mtdnr %d\n", mtdnr)); - return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr); + return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr, mnt); } } } @@ -247,7 +252,7 @@ static struct super_block *jffs2_get_sb(struct file_system_type *fs_type, err, nd.dentry->d_inode)); if (err) - return ERR_PTR(err); + return err; err = -EINVAL; @@ -269,11 +274,11 @@ static struct super_block *jffs2_get_sb(struct file_system_type *fs_type, mtdnr = iminor(nd.dentry->d_inode); path_release(&nd); - return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr); + return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr, mnt); out: path_release(&nd); - return ERR_PTR(err); + return err; } static void jffs2_put_super (struct super_block *sb) diff --git a/fs/jfs/super.c b/fs/jfs/super.c index db6f41d6dd6..18a28137b90 100644 --- a/fs/jfs/super.c +++ b/fs/jfs/super.c @@ -565,10 +565,11 @@ static void jfs_unlockfs(struct super_block *sb) } } -static struct super_block *jfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int jfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, jfs_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, jfs_fill_super, + mnt); } static int jfs_sync_fs(struct super_block *sb, int wait) diff --git a/fs/libfs.c b/fs/libfs.c index 7145ba7a48d..7d70efa46da 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -196,9 +196,9 @@ struct inode_operations simple_dir_inode_operations = { * Common helper for pseudo-filesystems (sockfs, pipefs, bdev - stuff that * will never be mountable) */ -struct super_block * -get_sb_pseudo(struct file_system_type *fs_type, char *name, - struct super_operations *ops, unsigned long magic) +int get_sb_pseudo(struct file_system_type *fs_type, char *name, + struct super_operations *ops, unsigned long magic, + struct vfsmount *mnt) { struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL); static struct super_operations default_ops = {.statfs = simple_statfs}; @@ -207,7 +207,7 @@ get_sb_pseudo(struct file_system_type *fs_type, char *name, struct qstr d_name = {.name = name, .len = strlen(name)}; if (IS_ERR(s)) - return s; + return PTR_ERR(s); s->s_flags = MS_NOUSER; s->s_maxbytes = ~0ULL; @@ -232,12 +232,12 @@ get_sb_pseudo(struct file_system_type *fs_type, char *name, d_instantiate(dentry, root); s->s_root = dentry; s->s_flags |= MS_ACTIVE; - return s; + return simple_set_mnt(mnt, s); Enomem: up_write(&s->s_umount); deactivate_super(s); - return ERR_PTR(-ENOMEM); + return -ENOMEM; } int simple_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) diff --git a/fs/minix/inode.c b/fs/minix/inode.c index 2dcccf1d1b7..14f24dfbfe3 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c @@ -559,10 +559,11 @@ void minix_truncate(struct inode * inode) V2_minix_truncate(inode); } -static struct super_block *minix_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int minix_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, minix_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, minix_fill_super, + mnt); } static struct file_system_type minix_fs_type = { diff --git a/fs/msdos/namei.c b/fs/msdos/namei.c index 5b76ccd19e3..9e44158a754 100644 --- a/fs/msdos/namei.c +++ b/fs/msdos/namei.c @@ -661,11 +661,12 @@ static int msdos_fill_super(struct super_block *sb, void *data, int silent) return 0; } -static struct super_block *msdos_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, - void *data) +static int msdos_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, + void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, msdos_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, msdos_fill_super, + mnt); } static struct file_system_type msdos_fs_type = { diff --git a/fs/namespace.c b/fs/namespace.c index bf478addb85..c13072a5f1e 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -86,6 +86,15 @@ struct vfsmount *alloc_vfsmnt(const char *name) return mnt; } +int simple_set_mnt(struct vfsmount *mnt, struct super_block *sb) +{ + mnt->mnt_sb = sb; + mnt->mnt_root = dget(sb->s_root); + return 0; +} + +EXPORT_SYMBOL(simple_set_mnt); + void free_vfsmnt(struct vfsmount *mnt) { kfree(mnt->mnt_devname); diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index a1f3e972c6e..8db033fab3f 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c @@ -957,10 +957,10 @@ out: return result; } -static struct super_block *ncp_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int ncp_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_nodev(fs_type, flags, data, ncp_fill_super); + return get_sb_nodev(fs_type, flags, data, ncp_fill_super, mnt); } static struct file_system_type ncp_fs_type = { diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index d0b991a9232..ff645a961bc 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -1690,8 +1690,8 @@ static int nfs_compare_super(struct super_block *sb, void *data) return !nfs_compare_fh(&old->fh, &server->fh); } -static struct super_block *nfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *raw_data) +static int nfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt) { int error; struct nfs_server *server = NULL; @@ -1699,14 +1699,14 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type, struct nfs_fh *root; struct nfs_mount_data *data = raw_data; - s = ERR_PTR(-EINVAL); + error = -EINVAL; if (data == NULL) { dprintk("%s: missing data argument\n", __FUNCTION__); - goto out_err; + goto out_err_noserver; } if (data->version <= 0 || data->version > NFS_MOUNT_VERSION) { dprintk("%s: bad mount version\n", __FUNCTION__); - goto out_err; + goto out_err_noserver; } switch (data->version) { case 1: @@ -1718,7 +1718,7 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type, dprintk("%s: mount structure version %d does not support NFSv3\n", __FUNCTION__, data->version); - goto out_err; + goto out_err_noserver; } data->root.size = NFS2_FHSIZE; memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE); @@ -1727,24 +1727,24 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type, dprintk("%s: mount structure version %d does not support strong security\n", __FUNCTION__, data->version); - goto out_err; + goto out_err_noserver; } case 5: memset(data->context, 0, sizeof(data->context)); } #ifndef CONFIG_NFS_V3 /* If NFSv3 is not compiled in, return -EPROTONOSUPPORT */ - s = ERR_PTR(-EPROTONOSUPPORT); + error = -EPROTONOSUPPORT; if (data->flags & NFS_MOUNT_VER3) { dprintk("%s: NFSv3 not compiled into kernel\n", __FUNCTION__); - goto out_err; + goto out_err_noserver; } #endif /* CONFIG_NFS_V3 */ - s = ERR_PTR(-ENOMEM); + error = -ENOMEM; server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL); if (!server) - goto out_err; + goto out_err_noserver; /* Zero out the NFS state stuff */ init_nfsv4_state(server); server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL); @@ -1754,7 +1754,7 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type, root->size = data->root.size; else root->size = NFS2_FHSIZE; - s = ERR_PTR(-EINVAL); + error = -EINVAL; if (root->size > sizeof(root->data)) { dprintk("%s: invalid root filehandle\n", __FUNCTION__); goto out_err; @@ -1770,15 +1770,20 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type, } /* Fire up rpciod if not yet running */ - s = ERR_PTR(rpciod_up()); - if (IS_ERR(s)) { - dprintk("%s: couldn't start rpciod! Error = %ld\n", - __FUNCTION__, PTR_ERR(s)); + error = rpciod_up(); + if (error < 0) { + dprintk("%s: couldn't start rpciod! Error = %d\n", + __FUNCTION__, error); goto out_err; } s = sget(fs_type, nfs_compare_super, nfs_set_super, server); - if (IS_ERR(s) || s->s_root) + if (IS_ERR(s)) { + error = PTR_ERR(s); + goto out_err_rpciod; + } + + if (s->s_root) goto out_rpciod_down; s->s_flags = flags; @@ -1787,15 +1792,22 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type, if (error) { up_write(&s->s_umount); deactivate_super(s); - return ERR_PTR(error); + return error; } s->s_flags |= MS_ACTIVE; - return s; + return simple_set_mnt(mnt, s); + out_rpciod_down: rpciod_down(); + kfree(server); + return simple_set_mnt(mnt, s); + +out_err_rpciod: + rpciod_down(); out_err: kfree(server); - return s; +out_err_noserver: + return error; } static void nfs_kill_super(struct super_block *s) @@ -2032,8 +2044,8 @@ nfs_copy_user_string(char *dst, struct nfs_string *src, int maxlen) return dst; } -static struct super_block *nfs4_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *raw_data) +static int nfs4_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt) { int error; struct nfs_server *server; @@ -2043,16 +2055,16 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type, if (data == NULL) { dprintk("%s: missing data argument\n", __FUNCTION__); - return ERR_PTR(-EINVAL); + return -EINVAL; } if (data->version <= 0 || data->version > NFS4_MOUNT_VERSION) { dprintk("%s: bad mount version\n", __FUNCTION__); - return ERR_PTR(-EINVAL); + return -EINVAL; } server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL); if (!server) - return ERR_PTR(-ENOMEM); + return -ENOMEM; /* Zero out the NFS state stuff */ init_nfsv4_state(server); server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL); @@ -2074,33 +2086,41 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type, /* We now require that the mount process passes the remote address */ if (data->host_addrlen != sizeof(server->addr)) { - s = ERR_PTR(-EINVAL); + error = -EINVAL; goto out_free; } if (copy_from_user(&server->addr, data->host_addr, sizeof(server->addr))) { - s = ERR_PTR(-EFAULT); + error = -EFAULT; goto out_free; } if (server->addr.sin_family != AF_INET || server->addr.sin_addr.s_addr == INADDR_ANY) { dprintk("%s: mount program didn't pass remote IP address!\n", __FUNCTION__); - s = ERR_PTR(-EINVAL); + error = -EINVAL; goto out_free; } /* Fire up rpciod if not yet running */ - s = ERR_PTR(rpciod_up()); - if (IS_ERR(s)) { - dprintk("%s: couldn't start rpciod! Error = %ld\n", - __FUNCTION__, PTR_ERR(s)); + error = rpciod_up(); + if (error < 0) { + dprintk("%s: couldn't start rpciod! Error = %d\n", + __FUNCTION__, error); goto out_free; } s = sget(fs_type, nfs4_compare_super, nfs_set_super, server); - - if (IS_ERR(s) || s->s_root) + if (IS_ERR(s)) { + error = PTR_ERR(s); goto out_free; + } + + if (s->s_root) { + kfree(server->mnt_path); + kfree(server->hostname); + kfree(server); + return simple_set_mnt(mnt, s); + } s->s_flags = flags; @@ -2108,17 +2128,17 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type, if (error) { up_write(&s->s_umount); deactivate_super(s); - return ERR_PTR(error); + return error; } s->s_flags |= MS_ACTIVE; - return s; + return simple_set_mnt(mnt, s); out_err: - s = (struct super_block *)p; + error = PTR_ERR(p); out_free: kfree(server->mnt_path); kfree(server->hostname); kfree(server); - return s; + return error; } static void nfs4_kill_super(struct super_block *sb) diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 3ef017b3b5b..a1810e6a93e 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -494,10 +494,10 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent) return simple_fill_super(sb, 0x6e667364, nfsd_files); } -static struct super_block *nfsd_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int nfsd_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_single(fs_type, flags, data, nfsd_fill_super); + return get_sb_single(fs_type, flags, data, nfsd_fill_super, mnt); } static struct file_system_type nfsd_fs_type = { diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c index 27833f6df49..d5d5e969294 100644 --- a/fs/ntfs/super.c +++ b/fs/ntfs/super.c @@ -3093,10 +3093,11 @@ struct kmem_cache *ntfs_index_ctx_cache; /* Driver wide mutex. */ DEFINE_MUTEX(ntfs_lock); -static struct super_block *ntfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int ntfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, ntfs_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, ntfs_fill_super, + mnt); } static struct file_system_type ntfs_fs_type = { diff --git a/fs/ocfs2/dlm/dlmfs.c b/fs/ocfs2/dlm/dlmfs.c index 7e88e24b347..7273d9fa6ba 100644 --- a/fs/ocfs2/dlm/dlmfs.c +++ b/fs/ocfs2/dlm/dlmfs.c @@ -574,10 +574,10 @@ static struct inode_operations dlmfs_file_inode_operations = { .getattr = simple_getattr, }; -static struct super_block *dlmfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int dlmfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_nodev(fs_type, flags, data, dlmfs_fill_super); + return get_sb_nodev(fs_type, flags, data, dlmfs_fill_super, mnt); } static struct file_system_type dlmfs_fs_type = { diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 949b3dac30f..788b8b50dc4 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -672,12 +672,14 @@ read_super_error: return status; } -static struct super_block *ocfs2_get_sb(struct file_system_type *fs_type, - int flags, - const char *dev_name, - void *data) +static int ocfs2_get_sb(struct file_system_type *fs_type, + int flags, + const char *dev_name, + void *data, + struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, ocfs2_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, ocfs2_fill_super, + mnt); } static struct file_system_type ocfs2_fs_type = { diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c index 0f14276a2e5..464e2bce020 100644 --- a/fs/openpromfs/inode.c +++ b/fs/openpromfs/inode.c @@ -1054,10 +1054,10 @@ out_no_root: return -ENOMEM; } -static struct super_block *openprom_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int openprom_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_single(fs_type, flags, data, openprom_fill_super); + return get_sb_single(fs_type, flags, data, openprom_fill_super, mnt); } static struct file_system_type openprom_fs_type = { diff --git a/fs/pipe.c b/fs/pipe.c index 5acd8954aaa..20352573e02 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -979,12 +979,11 @@ no_files: * any operations on the root directory. However, we need a non-trivial * d_name - pipe: will go nicely and kill the special-casing in procfs. */ - -static struct super_block * -pipefs_get_sb(struct file_system_type *fs_type, int flags, - const char *dev_name, void *data) +static int pipefs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, + struct vfsmount *mnt) { - return get_sb_pseudo(fs_type, "pipe:", NULL, PIPEFS_MAGIC); + return get_sb_pseudo(fs_type, "pipe:", NULL, PIPEFS_MAGIC, mnt); } static struct file_system_type pipe_fs_type = { diff --git a/fs/proc/root.c b/fs/proc/root.c index c3fd3611112..9995356ce73 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -26,10 +26,10 @@ struct proc_dir_entry *proc_net, *proc_net_stat, *proc_bus, *proc_root_fs, *proc struct proc_dir_entry *proc_sys_root; #endif -static struct super_block *proc_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int proc_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_single(fs_type, flags, data, proc_fill_super); + return get_sb_single(fs_type, flags, data, proc_fill_super, mnt); } static struct file_system_type proc_fs_type = { diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c index 2ecd46f85e9..e6cca5cd4b4 100644 --- a/fs/qnx4/inode.c +++ b/fs/qnx4/inode.c @@ -561,10 +561,11 @@ static void destroy_inodecache(void) "qnx4_inode_cache: not all structures were freed\n"); } -static struct super_block *qnx4_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int qnx4_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, qnx4_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, qnx4_fill_super, + mnt); } static struct file_system_type qnx4_fs_type = { diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c index 14bd2246fb6..b9677335cc8 100644 --- a/fs/ramfs/inode.c +++ b/fs/ramfs/inode.c @@ -185,16 +185,17 @@ static int ramfs_fill_super(struct super_block * sb, void * data, int silent) return 0; } -struct super_block *ramfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +int ramfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_nodev(fs_type, flags, data, ramfs_fill_super); + return get_sb_nodev(fs_type, flags, data, ramfs_fill_super, mnt); } -static struct super_block *rootfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int rootfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_nodev(fs_type, flags|MS_NOUSER, data, ramfs_fill_super); + return get_sb_nodev(fs_type, flags|MS_NOUSER, data, ramfs_fill_super, + mnt); } static struct file_system_type ramfs_fs_type = { diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index cae2abbc0c7..f3ff41d3398 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -2249,11 +2249,12 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type, #endif -static struct super_block *get_super_block(struct file_system_type *fs_type, - int flags, const char *dev_name, - void *data) +static int get_super_block(struct file_system_type *fs_type, + int flags, const char *dev_name, + void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, reiserfs_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, reiserfs_fill_super, + mnt); } static int __init init_reiserfs_fs(void) diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c index 9b9eda7b335..4d6cd662106 100644 --- a/fs/romfs/inode.c +++ b/fs/romfs/inode.c @@ -607,10 +607,11 @@ static struct super_operations romfs_ops = { .remount_fs = romfs_remount, }; -static struct super_block *romfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int romfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, romfs_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, romfs_fill_super, + mnt); } static struct file_system_type romfs_fs_type = { diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c index fdeabc0a34f..4a37c2bbfa3 100644 --- a/fs/smbfs/inode.c +++ b/fs/smbfs/inode.c @@ -782,10 +782,10 @@ out: return error; } -static struct super_block *smb_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int smb_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_nodev(fs_type, flags, data, smb_fill_super); + return get_sb_nodev(fs_type, flags, data, smb_fill_super, mnt); } static struct file_system_type smb_fs_type = { diff --git a/fs/super.c b/fs/super.c index 9d5c2add722..324c2d232f5 100644 --- a/fs/super.c +++ b/fs/super.c @@ -231,7 +231,7 @@ void generic_shutdown_super(struct super_block *sb) if (root) { sb->s_root = NULL; shrink_dcache_parent(root); - shrink_dcache_anon(sb); + shrink_dcache_sb(sb); dput(root); fsync_super(sb); lock_super(sb); @@ -676,9 +676,10 @@ static void bdev_uevent(struct block_device *bdev, enum kobject_action action) } } -struct super_block *get_sb_bdev(struct file_system_type *fs_type, +int get_sb_bdev(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, - int (*fill_super)(struct super_block *, void *, int)) + int (*fill_super)(struct super_block *, void *, int), + struct vfsmount *mnt) { struct block_device *bdev; struct super_block *s; @@ -686,7 +687,7 @@ struct super_block *get_sb_bdev(struct file_system_type *fs_type, bdev = open_bdev_excl(dev_name, flags, fs_type); if (IS_ERR(bdev)) - return (struct super_block *)bdev; + return PTR_ERR(bdev); /* * once the super is inserted into the list by sget, s_umount @@ -697,15 +698,17 @@ struct super_block *get_sb_bdev(struct file_system_type *fs_type, s = sget(fs_type, test_bdev_super, set_bdev_super, bdev); mutex_unlock(&bdev->bd_mount_mutex); if (IS_ERR(s)) - goto out; + goto error_s; if (s->s_root) { if ((flags ^ s->s_flags) & MS_RDONLY) { up_write(&s->s_umount); deactivate_super(s); - s = ERR_PTR(-EBUSY); + error = -EBUSY; + goto error_bdev; } - goto out; + + close_bdev_excl(bdev); } else { char b[BDEVNAME_SIZE]; @@ -716,18 +719,21 @@ struct super_block *get_sb_bdev(struct file_system_type *fs_type, if (error) { up_write(&s->s_umount); deactivate_super(s); - s = ERR_PTR(error); - } else { - s->s_flags |= MS_ACTIVE; - bdev_uevent(bdev, KOBJ_MOUNT); + goto error; } + + s->s_flags |= MS_ACTIVE; + bdev_uevent(bdev, KOBJ_MOUNT); } - return s; + return simple_set_mnt(mnt, s); -out: +error_s: + error = PTR_ERR(s); +error_bdev: close_bdev_excl(bdev); - return s; +error: + return error; } EXPORT_SYMBOL(get_sb_bdev); @@ -744,15 +750,16 @@ void kill_block_super(struct super_block *sb) EXPORT_SYMBOL(kill_block_super); -struct super_block *get_sb_nodev(struct file_system_type *fs_type, +int get_sb_nodev(struct file_system_type *fs_type, int flags, void *data, - int (*fill_super)(struct super_block *, void *, int)) + int (*fill_super)(struct super_block *, void *, int), + struct vfsmount *mnt) { int error; struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL); if (IS_ERR(s)) - return s; + return PTR_ERR(s); s->s_flags = flags; @@ -760,10 +767,10 @@ struct super_block *get_sb_nodev(struct file_system_type *fs_type, if (error) { up_write(&s->s_umount); deactivate_super(s); - return ERR_PTR(error); + return error; } s->s_flags |= MS_ACTIVE; - return s; + return simple_set_mnt(mnt, s); } EXPORT_SYMBOL(get_sb_nodev); @@ -773,94 +780,102 @@ static int compare_single(struct super_block *s, void *p) return 1; } -struct super_block *get_sb_single(struct file_system_type *fs_type, +int get_sb_single(struct file_system_type *fs_type, int flags, void *data, - int (*fill_super)(struct super_block *, void *, int)) + int (*fill_super)(struct super_block *, void *, int), + struct vfsmount *mnt) { struct super_block *s; int error; s = sget(fs_type, compare_single, set_anon_super, NULL); if (IS_ERR(s)) - return s; + return PTR_ERR(s); if (!s->s_root) { s->s_flags = flags; error = fill_super(s, data, flags & MS_SILENT ? 1 : 0); if (error) { up_write(&s->s_umount); deactivate_super(s); - return ERR_PTR(error); + return error; } s->s_flags |= MS_ACTIVE; } do_remount_sb(s, flags, data, 0); - return s; + return simple_set_mnt(mnt, s); } EXPORT_SYMBOL(get_sb_single); struct vfsmount * -do_kern_mount(const char *fstype, int flags, const char *name, void *data) +vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data) { - struct file_system_type *type = get_fs_type(fstype); - struct super_block *sb = ERR_PTR(-ENOMEM); struct vfsmount *mnt; - int error; char *secdata = NULL; + int error; if (!type) return ERR_PTR(-ENODEV); + error = -ENOMEM; mnt = alloc_vfsmnt(name); if (!mnt) goto out; if (data) { secdata = alloc_secdata(); - if (!secdata) { - sb = ERR_PTR(-ENOMEM); + if (!secdata) goto out_mnt; - } error = security_sb_copy_data(type, data, secdata); - if (error) { - sb = ERR_PTR(error); + if (error) goto out_free_secdata; - } } - sb = type->get_sb(type, flags, name, data); - if (IS_ERR(sb)) + error = type->get_sb(type, flags, name, data, mnt); + if (error < 0) goto out_free_secdata; - error = security_sb_kern_mount(sb, secdata); + + error = security_sb_kern_mount(mnt->mnt_sb, secdata); if (error) goto out_sb; - mnt->mnt_sb = sb; - mnt->mnt_root = dget(sb->s_root); - mnt->mnt_mountpoint = sb->s_root; + + mnt->mnt_mountpoint = mnt->mnt_root; mnt->mnt_parent = mnt; - up_write(&sb->s_umount); + up_write(&mnt->mnt_sb->s_umount); free_secdata(secdata); - put_filesystem(type); return mnt; out_sb: - up_write(&sb->s_umount); - deactivate_super(sb); - sb = ERR_PTR(error); + dput(mnt->mnt_root); + up_write(&mnt->mnt_sb->s_umount); + deactivate_super(mnt->mnt_sb); out_free_secdata: free_secdata(secdata); out_mnt: free_vfsmnt(mnt); out: + return ERR_PTR(error); +} + +EXPORT_SYMBOL_GPL(vfs_kern_mount); + +struct vfsmount * +do_kern_mount(const char *fstype, int flags, const char *name, void *data) +{ + struct file_system_type *type = get_fs_type(fstype); + struct vfsmount *mnt; + if (!type) + return ERR_PTR(-ENODEV); + mnt = vfs_kern_mount(type, flags, name, data); put_filesystem(type); - return (struct vfsmount *)sb; + return mnt; } EXPORT_SYMBOL_GPL(do_kern_mount); struct vfsmount *kern_mount(struct file_system_type *type) { - return do_kern_mount(type->name, 0, type->name, NULL); + return vfs_kern_mount(type, 0, type->name, NULL); } EXPORT_SYMBOL(kern_mount); diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index f1117e885bd..40190c48927 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c @@ -66,10 +66,10 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent) return 0; } -static struct super_block *sysfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int sysfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_single(fs_type, flags, data, sysfs_fill_super); + return get_sb_single(fs_type, flags, data, sysfs_fill_super, mnt); } static struct file_system_type sysfs_fs_type = { diff --git a/fs/sysv/super.c b/fs/sysv/super.c index e92b991e6dd..876639b9332 100644 --- a/fs/sysv/super.c +++ b/fs/sysv/super.c @@ -506,16 +506,17 @@ failed: /* Every kernel module contains stuff like this. */ -static struct super_block *sysv_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int sysv_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, sysv_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, sysv_fill_super, + mnt); } -static struct super_block *v7_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int v7_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, v7_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, v7_fill_super, mnt); } static struct file_system_type sysv_fs_type = { diff --git a/fs/udf/super.c b/fs/udf/super.c index e45789fe38e..2250774a831 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -94,10 +94,10 @@ static unsigned int udf_count_free(struct super_block *); static int udf_statfs(struct super_block *, struct kstatfs *); /* UDF filesystem type */ -static struct super_block *udf_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int udf_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, udf_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, udf_fill_super, mnt); } static struct file_system_type udf_fstype = { diff --git a/fs/ufs/super.c b/fs/ufs/super.c index db98a4c71e6..768fb8d9e67 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -1311,10 +1311,10 @@ out: #endif -static struct super_block *ufs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int ufs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, ufs_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, ufs_fill_super, mnt); } static struct file_system_type ufs_fs_type = { diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c index a56cec3be5f..9a8f48bae95 100644 --- a/fs/vfat/namei.c +++ b/fs/vfat/namei.c @@ -1023,11 +1023,12 @@ static int vfat_fill_super(struct super_block *sb, void *data, int silent) return 0; } -static struct super_block *vfat_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, - void *data) +static int vfat_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, + void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, vfat_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, vfat_fill_super, + mnt); } static struct file_system_type vfat_fs_type = { diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index f2a0778536f..d03c89a3665 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -853,14 +853,16 @@ fail_vfsop: return -error; } -STATIC struct super_block * +STATIC int xfs_fs_get_sb( struct file_system_type *fs_type, int flags, const char *dev_name, - void *data) + void *data, + struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, xfs_fs_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, xfs_fs_fill_super, + mnt); } STATIC struct super_operations xfs_super_operations = { diff --git a/include/linux/dcache.h b/include/linux/dcache.h index 46d0e079735..0dd1610a94a 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -217,7 +217,6 @@ extern struct dentry * d_alloc_anon(struct inode *); extern struct dentry * d_splice_alias(struct inode *, struct dentry *); extern void shrink_dcache_sb(struct super_block *); extern void shrink_dcache_parent(struct dentry *); -extern void shrink_dcache_anon(struct super_block *); extern int d_invalidate(struct dentry *); /* only used at mount-time */ diff --git a/include/linux/fs.h b/include/linux/fs.h index 73c7d6f04b3..3e50dd24af8 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1269,23 +1269,26 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent, struct file_system_type { const char *name; int fs_flags; - struct super_block *(*get_sb) (struct file_system_type *, int, - const char *, void *); + int (*get_sb) (struct file_system_type *, int, + const char *, void *, struct vfsmount *); void (*kill_sb) (struct super_block *); struct module *owner; struct file_system_type * next; struct list_head fs_supers; }; -struct super_block *get_sb_bdev(struct file_system_type *fs_type, +extern int get_sb_bdev(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, - int (*fill_super)(struct super_block *, void *, int)); -struct super_block *get_sb_single(struct file_system_type *fs_type, + int (*fill_super)(struct super_block *, void *, int), + struct vfsmount *mnt); +extern int get_sb_single(struct file_system_type *fs_type, int flags, void *data, - int (*fill_super)(struct super_block *, void *, int)); -struct super_block *get_sb_nodev(struct file_system_type *fs_type, + int (*fill_super)(struct super_block *, void *, int), + struct vfsmount *mnt); +extern int get_sb_nodev(struct file_system_type *fs_type, int flags, void *data, - int (*fill_super)(struct super_block *, void *, int)); + int (*fill_super)(struct super_block *, void *, int), + struct vfsmount *mnt); void generic_shutdown_super(struct super_block *sb); void kill_block_super(struct super_block *sb); void kill_anon_super(struct super_block *sb); @@ -1296,8 +1299,10 @@ struct super_block *sget(struct file_system_type *type, int (*test)(struct super_block *,void *), int (*set)(struct super_block *,void *), void *data); -struct super_block *get_sb_pseudo(struct file_system_type *, char *, - struct super_operations *ops, unsigned long); +extern int get_sb_pseudo(struct file_system_type *, char *, + struct super_operations *ops, unsigned long, + struct vfsmount *mnt); +extern int simple_set_mnt(struct vfsmount *mnt, struct super_block *sb); int __put_super(struct super_block *sb); int __put_super_and_need_restart(struct super_block *sb); void unnamed_dev_init(void); diff --git a/include/linux/ramfs.h b/include/linux/ramfs.h index 78ecfa28b1c..00b340ba661 100644 --- a/include/linux/ramfs.h +++ b/include/linux/ramfs.h @@ -2,8 +2,8 @@ #define _LINUX_RAMFS_H struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev); -struct super_block *ramfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data); +extern int ramfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt); #ifndef CONFIG_MMU extern unsigned long ramfs_nommu_get_unmapped_area(struct file *file, diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 1511714a958..0a2a24b6ebe 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -205,11 +205,11 @@ static int mqueue_fill_super(struct super_block *sb, void *data, int silent) return 0; } -static struct super_block *mqueue_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, - void *data) +static int mqueue_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, + void *data, struct vfsmount *mnt) { - return get_sb_single(fs_type, flags, data, mqueue_fill_super); + return get_sb_single(fs_type, flags, data, mqueue_fill_super, mnt); } static void init_once(void *foo, kmem_cache_t * cachep, unsigned long flags) diff --git a/kernel/cpuset.c b/kernel/cpuset.c index ab81fdd4572..77f45ffd5ea 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -392,11 +392,11 @@ static int cpuset_fill_super(struct super_block *sb, void *unused_data, return 0; } -static struct super_block *cpuset_get_sb(struct file_system_type *fs_type, - int flags, const char *unused_dev_name, - void *data) +static int cpuset_get_sb(struct file_system_type *fs_type, + int flags, const char *unused_dev_name, + void *data, struct vfsmount *mnt) { - return get_sb_single(fs_type, flags, data, cpuset_fill_super); + return get_sb_single(fs_type, flags, data, cpuset_fill_super, mnt); } static struct file_system_type cpuset_fs_type = { diff --git a/kernel/futex.c b/kernel/futex.c index 5699c512057..e1a380c77a5 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -1056,11 +1056,11 @@ asmlinkage long sys_futex(u32 __user *uaddr, int op, int val, (unsigned long)uaddr2, val2, val3); } -static struct super_block * -futexfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int futexfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, + struct vfsmount *mnt) { - return get_sb_pseudo(fs_type, "futex", NULL, 0xBAD1DEA); + return get_sb_pseudo(fs_type, "futex", NULL, 0xBAD1DEA, mnt); } static struct file_system_type futex_fs_type = { diff --git a/mm/shmem.c b/mm/shmem.c index 1e43c8a865b..7617bb1c6bf 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -2233,10 +2233,10 @@ static struct vm_operations_struct shmem_vm_ops = { }; -static struct super_block *shmem_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int shmem_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_nodev(fs_type, flags, data, shmem_fill_super); + return get_sb_nodev(fs_type, flags, data, shmem_fill_super, mnt); } static struct file_system_type tmpfs_fs_type = { diff --git a/net/socket.c b/net/socket.c index 02948b622bd..565f5e8d119 100644 --- a/net/socket.c +++ b/net/socket.c @@ -335,10 +335,11 @@ static struct super_operations sockfs_ops = { .statfs = simple_statfs, }; -static struct super_block *sockfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int sockfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_pseudo(fs_type, "socket:", &sockfs_ops, SOCKFS_MAGIC); + return get_sb_pseudo(fs_type, "socket:", &sockfs_ops, SOCKFS_MAGIC, + mnt); } static struct vfsmount *sock_mnt __read_mostly; diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index cc673dd8433..8241fa72680 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -815,11 +815,11 @@ out: return -ENOMEM; } -static struct super_block * +static int rpc_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_single(fs_type, flags, data, rpc_fill_super); + return get_sb_single(fs_type, flags, data, rpc_fill_super, mnt); } static struct file_system_type rpc_pipe_fs_type = { diff --git a/security/inode.c b/security/inode.c index 0f77b022366..e6fc29ac856 100644 --- a/security/inode.c +++ b/security/inode.c @@ -135,11 +135,11 @@ static int fill_super(struct super_block *sb, void *data, int silent) return simple_fill_super(sb, SECURITYFS_MAGIC, files); } -static struct super_block *get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, - void *data) +static int get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, + void *data, struct vfsmount *mnt) { - return get_sb_single(fs_type, flags, data, fill_super); + return get_sb_single(fs_type, flags, data, fill_super, mnt); } static struct file_system_type fs_type = { diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 2e73d3279f2..7029bbc9bef 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -1345,10 +1345,11 @@ err: goto out; } -static struct super_block *sel_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int sel_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, + struct vfsmount *mnt) { - return get_sb_single(fs_type, flags, data, sel_fill_super); + return get_sb_single(fs_type, flags, data, sel_fill_super, mnt); } static struct file_system_type sel_fs_type = { -- cgit v1.2.3 From 726c334223180e3c0197cc980a432681370d4baf Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 23 Jun 2006 02:02:58 -0700 Subject: [PATCH] VFS: Permit filesystem to perform statfs with a known root dentry Give the statfs superblock operation a dentry pointer rather than a superblock pointer. This complements the get_sb() patch. That reduced the significance of sb->s_root, allowing NFS to place a fake root there. However, NFS does require a dentry to use as a target for the statfs operation. This permits the root in the vfsmount to be used instead. linux/mount.h has been added where necessary to make allyesconfig build successfully. Interest has also been expressed for use with the FUSE and XFS filesystems. Signed-off-by: David Howells Acked-by: Al Viro Cc: Nathan Scott Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/filesystems/Locking | 2 +- Documentation/filesystems/vfs.txt | 2 +- arch/alpha/kernel/osf_sys.c | 2 +- arch/mips/kernel/sysirix.c | 12 ++++++------ arch/parisc/hpux/sys_hpux.c | 10 +++++----- arch/sparc64/solaris/fs.c | 4 ++-- fs/adfs/super.c | 8 ++++---- fs/affs/super.c | 5 +++-- fs/befs/linuxvfs.c | 5 +++-- fs/bfs/inode.c | 3 ++- fs/cifs/cifsfs.c | 3 ++- fs/coda/inode.c | 6 +++--- fs/coda/upcall.c | 4 ++-- fs/compat.c | 8 ++++---- fs/cramfs/inode.c | 4 +++- fs/efs/super.c | 6 +++--- fs/ext2/super.c | 5 +++-- fs/ext3/super.c | 5 +++-- fs/fat/inode.c | 8 ++++---- fs/freevxfs/vxfs_super.c | 13 +++++++------ fs/fuse/inode.c | 3 ++- fs/hfs/super.c | 4 +++- fs/hfsplus/super.c | 4 +++- fs/hostfs/hostfs_kern.c | 4 ++-- fs/hpfs/super.c | 3 ++- fs/hppfs/hppfs_kern.c | 2 +- fs/hugetlbfs/inode.c | 4 ++-- fs/isofs/inode.c | 6 ++++-- fs/jffs/inode-v23.c | 4 ++-- fs/jffs2/fs.c | 4 ++-- fs/jffs2/os-linux.h | 2 +- fs/jfs/super.c | 4 ++-- fs/libfs.c | 4 ++-- fs/minix/inode.c | 10 +++++----- fs/ncpfs/inode.c | 5 +++-- fs/nfs/inode.c | 5 +++-- fs/nfsd/nfs4xdr.c | 2 +- fs/nfsd/vfs.c | 2 +- fs/ntfs/super.c | 7 ++++--- fs/ocfs2/super.c | 10 +++++----- fs/open.c | 26 +++++++++++++------------- fs/qnx4/inode.c | 6 ++++-- fs/reiserfs/super.c | 8 ++++---- fs/romfs/inode.c | 4 ++-- fs/smbfs/inode.c | 6 +++--- fs/smbfs/proc.c | 4 ++-- fs/smbfs/proto.h | 2 +- fs/super.c | 2 +- fs/sysv/inode.c | 3 ++- fs/udf/super.c | 6 ++++-- fs/ufs/super.c | 3 ++- fs/xfs/linux-2.6/xfs_super.c | 4 ++-- include/linux/coda_psdev.h | 2 +- include/linux/fs.h | 6 +++--- include/linux/mount.h | 5 +++++ include/linux/security.h | 14 +++++++------- kernel/acct.c | 2 +- mm/shmem.c | 4 ++-- security/dummy.c | 2 +- security/selinux/hooks.c | 6 +++--- 60 files changed, 175 insertions(+), 144 deletions(-) diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index 3abf08f1b14..d31efbbdfe5 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking @@ -99,7 +99,7 @@ prototypes: int (*sync_fs)(struct super_block *sb, int wait); void (*write_super_lockfs) (struct super_block *); void (*unlockfs) (struct super_block *); - int (*statfs) (struct super_block *, struct kstatfs *); + int (*statfs) (struct dentry *, struct kstatfs *); int (*remount_fs) (struct super_block *, int *, char *); void (*clear_inode) (struct inode *); void (*umount_begin) (struct super_block *); diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index dd7d0dcedc8..9d3aed628bc 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt @@ -211,7 +211,7 @@ struct super_operations { int (*sync_fs)(struct super_block *sb, int wait); void (*write_super_lockfs) (struct super_block *); void (*unlockfs) (struct super_block *); - int (*statfs) (struct super_block *, struct kstatfs *); + int (*statfs) (struct dentry *, struct kstatfs *); int (*remount_fs) (struct super_block *, int *, char *); void (*clear_inode) (struct inode *); void (*umount_begin) (struct super_block *); diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index 31afe3d91ac..e15dcf4f3dc 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -244,7 +244,7 @@ do_osf_statfs(struct dentry * dentry, struct osf_statfs __user *buffer, unsigned long bufsiz) { struct kstatfs linux_stat; - int error = vfs_statfs(dentry->d_inode->i_sb, &linux_stat); + int error = vfs_statfs(dentry, &linux_stat); if (!error) error = linux_to_osf_statfs(&linux_stat, buffer, bufsiz); return error; diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c index 5407b784cd0..19e1ef43eb4 100644 --- a/arch/mips/kernel/sysirix.c +++ b/arch/mips/kernel/sysirix.c @@ -694,7 +694,7 @@ asmlinkage int irix_statfs(const char __user *path, if (error) goto out; - error = vfs_statfs(nd.dentry->d_inode->i_sb, &kbuf); + error = vfs_statfs(nd.dentry, &kbuf); if (error) goto dput_and_out; @@ -732,7 +732,7 @@ asmlinkage int irix_fstatfs(unsigned int fd, struct irix_statfs __user *buf) goto out; } - error = vfs_statfs(file->f_dentry->d_inode->i_sb, &kbuf); + error = vfs_statfs(file->f_dentry, &kbuf); if (error) goto out_f; @@ -1360,7 +1360,7 @@ asmlinkage int irix_statvfs(char __user *fname, struct irix_statvfs __user *buf) error = user_path_walk(fname, &nd); if (error) goto out; - error = vfs_statfs(nd.dentry->d_inode->i_sb, &kbuf); + error = vfs_statfs(nd.dentry, &kbuf); if (error) goto dput_and_out; @@ -1406,7 +1406,7 @@ asmlinkage int irix_fstatvfs(int fd, struct irix_statvfs __user *buf) error = -EBADF; goto out; } - error = vfs_statfs(file->f_dentry->d_inode->i_sb, &kbuf); + error = vfs_statfs(file->f_dentry, &kbuf); if (error) goto out_f; @@ -1611,7 +1611,7 @@ asmlinkage int irix_statvfs64(char __user *fname, struct irix_statvfs64 __user * error = user_path_walk(fname, &nd); if (error) goto out; - error = vfs_statfs(nd.dentry->d_inode->i_sb, &kbuf); + error = vfs_statfs(nd.dentry, &kbuf); if (error) goto dput_and_out; @@ -1658,7 +1658,7 @@ asmlinkage int irix_fstatvfs64(int fd, struct irix_statvfs __user *buf) error = -EBADF; goto out; } - error = vfs_statfs(file->f_dentry->d_inode->i_sb, &kbuf); + error = vfs_statfs(file->f_dentry, &kbuf); if (error) goto out_f; diff --git a/arch/parisc/hpux/sys_hpux.c b/arch/parisc/hpux/sys_hpux.c index 05273ccced0..cb69727027a 100644 --- a/arch/parisc/hpux/sys_hpux.c +++ b/arch/parisc/hpux/sys_hpux.c @@ -145,7 +145,7 @@ static int hpux_ustat(dev_t dev, struct hpux_ustat __user *ubuf) s = user_get_super(dev); if (s == NULL) goto out; - err = vfs_statfs(s, &sbuf); + err = vfs_statfs(s->s_root, &sbuf); drop_super(s); if (err) goto out; @@ -186,12 +186,12 @@ struct hpux_statfs { int16_t f_pad; }; -static int vfs_statfs_hpux(struct super_block *sb, struct hpux_statfs *buf) +static int vfs_statfs_hpux(struct dentry *dentry, struct hpux_statfs *buf) { struct kstatfs st; int retval; - retval = vfs_statfs(sb, &st); + retval = vfs_statfs(dentry, &st); if (retval) return retval; @@ -219,7 +219,7 @@ asmlinkage long hpux_statfs(const char __user *path, error = user_path_walk(path, &nd); if (!error) { struct hpux_statfs tmp; - error = vfs_statfs_hpux(nd.dentry->d_inode->i_sb, &tmp); + error = vfs_statfs_hpux(nd.dentry, &tmp); if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) error = -EFAULT; path_release(&nd); @@ -237,7 +237,7 @@ asmlinkage long hpux_fstatfs(unsigned int fd, struct hpux_statfs __user * buf) file = fget(fd); if (!file) goto out; - error = vfs_statfs_hpux(file->f_dentry->d_inode->i_sb, &tmp); + error = vfs_statfs_hpux(file->f_dentry, &tmp); if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) error = -EFAULT; fput(file); diff --git a/arch/sparc64/solaris/fs.c b/arch/sparc64/solaris/fs.c index 4885ca6cbc7..0f0eb6aa1c4 100644 --- a/arch/sparc64/solaris/fs.c +++ b/arch/sparc64/solaris/fs.c @@ -356,7 +356,7 @@ static int report_statvfs(struct vfsmount *mnt, struct inode *inode, u32 buf) int error; struct sol_statvfs __user *ss = A(buf); - error = vfs_statfs(mnt->mnt_sb, &s); + error = vfs_statfs(mnt->mnt_root, &s); if (!error) { const char *p = mnt->mnt_sb->s_type->name; int i = 0; @@ -392,7 +392,7 @@ static int report_statvfs64(struct vfsmount *mnt, struct inode *inode, u32 buf) int error; struct sol_statvfs64 __user *ss = A(buf); - error = vfs_statfs(mnt->mnt_sb, &s); + error = vfs_statfs(mnt->mnt_root, &s); if (!error) { const char *p = mnt->mnt_sb->s_type->name; int i = 0; diff --git a/fs/adfs/super.c b/fs/adfs/super.c index 1b58a9b7f6a..ba1c88af49f 100644 --- a/fs/adfs/super.c +++ b/fs/adfs/super.c @@ -196,17 +196,17 @@ static int adfs_remount(struct super_block *sb, int *flags, char *data) return parse_options(sb, data); } -static int adfs_statfs(struct super_block *sb, struct kstatfs *buf) +static int adfs_statfs(struct dentry *dentry, struct kstatfs *buf) { - struct adfs_sb_info *asb = ADFS_SB(sb); + struct adfs_sb_info *asb = ADFS_SB(dentry->d_sb); buf->f_type = ADFS_SUPER_MAGIC; buf->f_namelen = asb->s_namelen; - buf->f_bsize = sb->s_blocksize; + buf->f_bsize = dentry->d_sb->s_blocksize; buf->f_blocks = asb->s_size; buf->f_files = asb->s_ids_per_zone * asb->s_map_size; buf->f_bavail = - buf->f_bfree = adfs_map_free(sb); + buf->f_bfree = adfs_map_free(dentry->d_sb); buf->f_ffree = (long)(buf->f_bfree * buf->f_files) / (long)buf->f_blocks; return 0; diff --git a/fs/affs/super.c b/fs/affs/super.c index 6a52e787540..8765cba35bb 100644 --- a/fs/affs/super.c +++ b/fs/affs/super.c @@ -18,7 +18,7 @@ extern struct timezone sys_tz; -static int affs_statfs(struct super_block *sb, struct kstatfs *buf); +static int affs_statfs(struct dentry *dentry, struct kstatfs *buf); static int affs_remount (struct super_block *sb, int *flags, char *data); static void @@ -508,8 +508,9 @@ affs_remount(struct super_block *sb, int *flags, char *data) } static int -affs_statfs(struct super_block *sb, struct kstatfs *buf) +affs_statfs(struct dentry *dentry, struct kstatfs *buf) { + struct super_block *sb = dentry->d_sb; int free; pr_debug("AFFS: statfs() partsize=%d, reserved=%d\n",AFFS_SB(sb)->s_partition_size, diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index 6ed07a5f10c..08201fab26c 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c @@ -49,7 +49,7 @@ static int befs_nls2utf(struct super_block *sb, const char *in, int in_len, char **out, int *out_len); static void befs_put_super(struct super_block *); static int befs_remount(struct super_block *, int *, char *); -static int befs_statfs(struct super_block *, struct kstatfs *); +static int befs_statfs(struct dentry *, struct kstatfs *); static int parse_options(char *, befs_mount_options *); static const struct super_operations befs_sops = { @@ -880,8 +880,9 @@ befs_remount(struct super_block *sb, int *flags, char *data) } static int -befs_statfs(struct super_block *sb, struct kstatfs *buf) +befs_statfs(struct dentry *dentry, struct kstatfs *buf) { + struct super_block *sb = dentry->d_sb; befs_debug(sb, "---> befs_statfs()"); diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c index e7da03f63a5..cf74f3d4d96 100644 --- a/fs/bfs/inode.c +++ b/fs/bfs/inode.c @@ -203,8 +203,9 @@ static void bfs_put_super(struct super_block *s) s->s_fs_info = NULL; } -static int bfs_statfs(struct super_block *s, struct kstatfs *buf) +static int bfs_statfs(struct dentry *dentry, struct kstatfs *buf) { + struct super_block *s = dentry->d_sb; struct bfs_sb_info *info = BFS_SB(s); u64 id = huge_encode_dev(s->s_bdev->bd_dev); buf->f_type = BFS_MAGIC; diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 08b35801dfe..7520f468715 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -166,8 +166,9 @@ cifs_put_super(struct super_block *sb) } static int -cifs_statfs(struct super_block *sb, struct kstatfs *buf) +cifs_statfs(struct dentry *dentry, struct kstatfs *buf) { + struct super_block *sb = dentry->d_sb; int xid; int rc = -EOPNOTSUPP; struct cifs_sb_info *cifs_sb; diff --git a/fs/coda/inode.c b/fs/coda/inode.c index cba70201567..87f1dc8aa24 100644 --- a/fs/coda/inode.c +++ b/fs/coda/inode.c @@ -36,7 +36,7 @@ /* VFS super_block ops */ static void coda_clear_inode(struct inode *); static void coda_put_super(struct super_block *); -static int coda_statfs(struct super_block *sb, struct kstatfs *buf); +static int coda_statfs(struct dentry *dentry, struct kstatfs *buf); static kmem_cache_t * coda_inode_cachep; @@ -278,13 +278,13 @@ struct inode_operations coda_file_inode_operations = { .setattr = coda_setattr, }; -static int coda_statfs(struct super_block *sb, struct kstatfs *buf) +static int coda_statfs(struct dentry *dentry, struct kstatfs *buf) { int error; lock_kernel(); - error = venus_statfs(sb, buf); + error = venus_statfs(dentry, buf); unlock_kernel(); diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c index 1bae99650a9..b040eba13a7 100644 --- a/fs/coda/upcall.c +++ b/fs/coda/upcall.c @@ -611,7 +611,7 @@ int venus_pioctl(struct super_block *sb, struct CodaFid *fid, return error; } -int venus_statfs(struct super_block *sb, struct kstatfs *sfs) +int venus_statfs(struct dentry *dentry, struct kstatfs *sfs) { union inputArgs *inp; union outputArgs *outp; @@ -620,7 +620,7 @@ int venus_statfs(struct super_block *sb, struct kstatfs *sfs) insize = max_t(unsigned int, INSIZE(statfs), OUTSIZE(statfs)); UPARG(CODA_STATFS); - error = coda_upcall(coda_sbp(sb), insize, &outsize, inp); + error = coda_upcall(coda_sbp(dentry->d_sb), insize, &outsize, inp); if (!error) { sfs->f_blocks = outp->coda_statfs.stat.f_blocks; diff --git a/fs/compat.c b/fs/compat.c index b1f64786a61..7e7e5bc4f3c 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -197,7 +197,7 @@ asmlinkage long compat_sys_statfs(const char __user *path, struct compat_statfs error = user_path_walk(path, &nd); if (!error) { struct kstatfs tmp; - error = vfs_statfs(nd.dentry->d_inode->i_sb, &tmp); + error = vfs_statfs(nd.dentry, &tmp); if (!error) error = put_compat_statfs(buf, &tmp); path_release(&nd); @@ -215,7 +215,7 @@ asmlinkage long compat_sys_fstatfs(unsigned int fd, struct compat_statfs __user file = fget(fd); if (!file) goto out; - error = vfs_statfs(file->f_dentry->d_inode->i_sb, &tmp); + error = vfs_statfs(file->f_dentry, &tmp); if (!error) error = put_compat_statfs(buf, &tmp); fput(file); @@ -265,7 +265,7 @@ asmlinkage long compat_sys_statfs64(const char __user *path, compat_size_t sz, s error = user_path_walk(path, &nd); if (!error) { struct kstatfs tmp; - error = vfs_statfs(nd.dentry->d_inode->i_sb, &tmp); + error = vfs_statfs(nd.dentry, &tmp); if (!error) error = put_compat_statfs64(buf, &tmp); path_release(&nd); @@ -286,7 +286,7 @@ asmlinkage long compat_sys_fstatfs64(unsigned int fd, compat_size_t sz, struct c file = fget(fd); if (!file) goto out; - error = vfs_statfs(file->f_dentry->d_inode->i_sb, &tmp); + error = vfs_statfs(file->f_dentry, &tmp); if (!error) error = put_compat_statfs64(buf, &tmp); fput(file); diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c index 37a91a153aa..8a9d5d3b326 100644 --- a/fs/cramfs/inode.c +++ b/fs/cramfs/inode.c @@ -322,8 +322,10 @@ out: return -EINVAL; } -static int cramfs_statfs(struct super_block *sb, struct kstatfs *buf) +static int cramfs_statfs(struct dentry *dentry, struct kstatfs *buf) { + struct super_block *sb = dentry->d_sb; + buf->f_type = CRAMFS_MAGIC; buf->f_bsize = PAGE_CACHE_SIZE; buf->f_blocks = CRAMFS_SB(sb)->blocks; diff --git a/fs/efs/super.c b/fs/efs/super.c index 1ba5e14f879..8ac2462ae5d 100644 --- a/fs/efs/super.c +++ b/fs/efs/super.c @@ -15,7 +15,7 @@ #include #include -static int efs_statfs(struct super_block *s, struct kstatfs *buf); +static int efs_statfs(struct dentry *dentry, struct kstatfs *buf); static int efs_fill_super(struct super_block *s, void *d, int silent); static int efs_get_sb(struct file_system_type *fs_type, @@ -322,8 +322,8 @@ out_no_fs: return -EINVAL; } -static int efs_statfs(struct super_block *s, struct kstatfs *buf) { - struct efs_sb_info *sb = SUPER_INFO(s); +static int efs_statfs(struct dentry *dentry, struct kstatfs *buf) { + struct efs_sb_info *sb = SUPER_INFO(dentry->d_sb); buf->f_type = EFS_SUPER_MAGIC; /* efs magic number */ buf->f_bsize = EFS_BLOCKSIZE; /* blocksize */ diff --git a/fs/ext2/super.c b/fs/ext2/super.c index a4dfffac596..a6c4d6e0232 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c @@ -39,7 +39,7 @@ static void ext2_sync_super(struct super_block *sb, struct ext2_super_block *es); static int ext2_remount (struct super_block * sb, int * flags, char * data); -static int ext2_statfs (struct super_block * sb, struct kstatfs * buf); +static int ext2_statfs (struct dentry * dentry, struct kstatfs * buf); void ext2_error (struct super_block * sb, const char * function, const char * fmt, ...) @@ -1038,8 +1038,9 @@ restore_opts: return err; } -static int ext2_statfs (struct super_block * sb, struct kstatfs * buf) +static int ext2_statfs (struct dentry * dentry, struct kstatfs * buf) { + struct super_block *sb = dentry->d_sb; struct ext2_sb_info *sbi = EXT2_SB(sb); unsigned long overhead; int i; diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 657f8e73b62..e08b6439617 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -58,7 +58,7 @@ static int ext3_sync_fs(struct super_block *sb, int wait); static const char *ext3_decode_error(struct super_block * sb, int errno, char nbuf[16]); static int ext3_remount (struct super_block * sb, int * flags, char * data); -static int ext3_statfs (struct super_block * sb, struct kstatfs * buf); +static int ext3_statfs (struct dentry * dentry, struct kstatfs * buf); static void ext3_unlockfs(struct super_block *sb); static void ext3_write_super (struct super_block * sb); static void ext3_write_super_lockfs(struct super_block *sb); @@ -2318,8 +2318,9 @@ restore_opts: return err; } -static int ext3_statfs (struct super_block * sb, struct kstatfs * buf) +static int ext3_statfs (struct dentry * dentry, struct kstatfs * buf) { + struct super_block *sb = dentry->d_sb; struct ext3_sb_info *sbi = EXT3_SB(sb); struct ext3_super_block *es = sbi->s_es; unsigned long overhead; diff --git a/fs/fat/inode.c b/fs/fat/inode.c index c1ce284f8a9..7c35d582ec1 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -539,18 +539,18 @@ static int fat_remount(struct super_block *sb, int *flags, char *data) return 0; } -static int fat_statfs(struct super_block *sb, struct kstatfs *buf) +static int fat_statfs(struct dentry *dentry, struct kstatfs *buf) { - struct msdos_sb_info *sbi = MSDOS_SB(sb); + struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb); /* If the count of free cluster is still unknown, counts it here. */ if (sbi->free_clusters == -1) { - int err = fat_count_free_clusters(sb); + int err = fat_count_free_clusters(dentry->d_sb); if (err) return err; } - buf->f_type = sb->s_magic; + buf->f_type = dentry->d_sb->s_magic; buf->f_bsize = sbi->cluster_size; buf->f_blocks = sbi->max_cluster - FAT_START_ENT; buf->f_bfree = sbi->free_clusters; diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c index d76eeaafbde..b74b791fc23 100644 --- a/fs/freevxfs/vxfs_super.c +++ b/fs/freevxfs/vxfs_super.c @@ -40,6 +40,7 @@ #include #include #include +#include #include "vxfs.h" #include "vxfs_extern.h" @@ -55,7 +56,7 @@ MODULE_ALIAS("vxfs"); /* makes mount -t vxfs autoload the module */ static void vxfs_put_super(struct super_block *); -static int vxfs_statfs(struct super_block *, struct kstatfs *); +static int vxfs_statfs(struct dentry *, struct kstatfs *); static int vxfs_remount(struct super_block *, int *, char *); static struct super_operations vxfs_super_ops = { @@ -90,12 +91,12 @@ vxfs_put_super(struct super_block *sbp) /** * vxfs_statfs - get filesystem information - * @sbp: VFS superblock + * @dentry: VFS dentry to locate superblock * @bufp: output buffer * * Description: * vxfs_statfs fills the statfs buffer @bufp with information - * about the filesystem described by @sbp. + * about the filesystem described by @dentry. * * Returns: * Zero. @@ -107,12 +108,12 @@ vxfs_put_super(struct super_block *sbp) * This is everything but complete... */ static int -vxfs_statfs(struct super_block *sbp, struct kstatfs *bufp) +vxfs_statfs(struct dentry *dentry, struct kstatfs *bufp) { - struct vxfs_sb_info *infp = VXFS_SBI(sbp); + struct vxfs_sb_info *infp = VXFS_SBI(dentry->d_sb); bufp->f_type = VXFS_SUPER_MAGIC; - bufp->f_bsize = sbp->s_blocksize; + bufp->f_bsize = dentry->d_sb->s_blocksize; bufp->f_blocks = infp->vsi_raw->vs_dsize; bufp->f_bfree = infp->vsi_raw->vs_free; bufp->f_bavail = 0; diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index c91f0a50aad..a13c0f52905 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -236,8 +236,9 @@ static void convert_fuse_statfs(struct kstatfs *stbuf, struct fuse_kstatfs *attr /* fsid is left zero */ } -static int fuse_statfs(struct super_block *sb, struct kstatfs *buf) +static int fuse_statfs(struct dentry *dentry, struct kstatfs *buf) { + struct super_block *sb = dentry->d_sb; struct fuse_conn *fc = get_fuse_conn_super(sb); struct fuse_req *req; struct fuse_statfs_out outarg; diff --git a/fs/hfs/super.c b/fs/hfs/super.c index ee5b80a409e..d9227bf14e8 100644 --- a/fs/hfs/super.c +++ b/fs/hfs/super.c @@ -80,8 +80,10 @@ static void hfs_put_super(struct super_block *sb) * * changed f_files/f_ffree to reflect the fs_ablock/free_ablocks. */ -static int hfs_statfs(struct super_block *sb, struct kstatfs *buf) +static int hfs_statfs(struct dentry *dentry, struct kstatfs *buf) { + struct super_block *sb = dentry->d_sb; + buf->f_type = HFS_SUPER_MAGIC; buf->f_bsize = sb->s_blocksize; buf->f_blocks = (u32)HFS_SB(sb)->fs_ablocks * HFS_SB(sb)->fs_div; diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index 0ed8b7e8e87..0a92fa2336a 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c @@ -212,8 +212,10 @@ static void hfsplus_put_super(struct super_block *sb) sb->s_fs_info = NULL; } -static int hfsplus_statfs(struct super_block *sb, struct kstatfs *buf) +static int hfsplus_statfs(struct dentry *dentry, struct kstatfs *buf) { + struct super_block *sb = dentry->d_sb; + buf->f_type = HFSPLUS_SUPER_MAGIC; buf->f_bsize = sb->s_blocksize; buf->f_blocks = HFSPLUS_SB(sb).total_blocks << HFSPLUS_SB(sb).fs_shift; diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index 04035e08f5c..8e0d37743e7 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -239,7 +239,7 @@ static int read_inode(struct inode *ino) return(err); } -int hostfs_statfs(struct super_block *sb, struct kstatfs *sf) +int hostfs_statfs(struct dentry *dentry, struct kstatfs *sf) { /* do_statfs uses struct statfs64 internally, but the linux kernel * struct statfs still has 32-bit versions for most of these fields, @@ -252,7 +252,7 @@ int hostfs_statfs(struct super_block *sb, struct kstatfs *sf) long long f_files; long long f_ffree; - err = do_statfs(HOSTFS_I(sb->s_root->d_inode)->host_filename, + err = do_statfs(HOSTFS_I(dentry->d_sb->s_root->d_inode)->host_filename, &sf->f_bsize, &f_blocks, &f_bfree, &f_bavail, &f_files, &f_ffree, &sf->f_fsid, sizeof(sf->f_fsid), &sf->f_namelen, sf->f_spare); diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c index 3b25cf3e2e6..f798480a363 100644 --- a/fs/hpfs/super.c +++ b/fs/hpfs/super.c @@ -135,8 +135,9 @@ static unsigned count_bitmaps(struct super_block *s) return count; } -static int hpfs_statfs(struct super_block *s, struct kstatfs *buf) +static int hpfs_statfs(struct dentry *dentry, struct kstatfs *buf) { + struct super_block *s = dentry->d_sb; struct hpfs_sb_info *sbi = hpfs_sb(s); lock_kernel(); diff --git a/fs/hppfs/hppfs_kern.c b/fs/hppfs/hppfs_kern.c index ec43c22bc9c..3a9bdf58166 100644 --- a/fs/hppfs/hppfs_kern.c +++ b/fs/hppfs/hppfs_kern.c @@ -616,7 +616,7 @@ static const struct file_operations hppfs_dir_fops = { .fsync = hppfs_fsync, }; -static int hppfs_statfs(struct super_block *sb, struct kstatfs *sf) +static int hppfs_statfs(struct dentry *dentry, struct kstatfs *sf) { sf->f_blocks = 0; sf->f_bfree = 0; diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 4665c26171f..678fc72c364 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -467,9 +467,9 @@ static int hugetlbfs_set_page_dirty(struct page *page) return 0; } -static int hugetlbfs_statfs(struct super_block *sb, struct kstatfs *buf) +static int hugetlbfs_statfs(struct dentry *dentry, struct kstatfs *buf) { - struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(sb); + struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(dentry->d_sb); buf->f_type = HUGETLBFS_MAGIC; buf->f_bsize = HPAGE_SIZE; diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index 17268da63a4..3f9c8ba1fa1 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -56,7 +56,7 @@ static void isofs_put_super(struct super_block *sb) } static void isofs_read_inode(struct inode *); -static int isofs_statfs (struct super_block *, struct kstatfs *); +static int isofs_statfs (struct dentry *, struct kstatfs *); static kmem_cache_t *isofs_inode_cachep; @@ -901,8 +901,10 @@ out_freesbi: return -EINVAL; } -static int isofs_statfs (struct super_block *sb, struct kstatfs *buf) +static int isofs_statfs (struct dentry *dentry, struct kstatfs *buf) { + struct super_block *sb = dentry->d_sb; + buf->f_type = ISOFS_SUPER_MAGIC; buf->f_bsize = sb->s_blocksize; buf->f_blocks = (ISOFS_SB(sb)->s_nzones diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c index dd93a091ad6..9e46ea6da75 100644 --- a/fs/jffs/inode-v23.c +++ b/fs/jffs/inode-v23.c @@ -377,9 +377,9 @@ jffs_new_inode(const struct inode * dir, struct jffs_raw_inode *raw_inode, /* Get statistics of the file system. */ static int -jffs_statfs(struct super_block *sb, struct kstatfs *buf) +jffs_statfs(struct dentry *dentry, struct kstatfs *buf) { - struct jffs_control *c = (struct jffs_control *) sb->s_fs_info; + struct jffs_control *c = (struct jffs_control *) dentry->d_sb->s_fs_info; struct jffs_fmcontrol *fmc; lock_kernel(); diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index 7b6c24b14f8..2900ec3ec3a 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c @@ -192,9 +192,9 @@ int jffs2_setattr(struct dentry *dentry, struct iattr *iattr) return rc; } -int jffs2_statfs(struct super_block *sb, struct kstatfs *buf) +int jffs2_statfs(struct dentry *dentry, struct kstatfs *buf) { - struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); + struct jffs2_sb_info *c = JFFS2_SB_INFO(dentry->d_sb); unsigned long avail; buf->f_type = JFFS2_SUPER_MAGIC; diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h index cd4021bcb94..6b522356540 100644 --- a/fs/jffs2/os-linux.h +++ b/fs/jffs2/os-linux.h @@ -175,7 +175,7 @@ void jffs2_clear_inode (struct inode *); void jffs2_dirty_inode(struct inode *inode); struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_inode *ri); -int jffs2_statfs (struct super_block *, struct kstatfs *); +int jffs2_statfs (struct dentry *, struct kstatfs *); void jffs2_write_super (struct super_block *); int jffs2_remount_fs (struct super_block *, int *, char *); int jffs2_do_fill_super(struct super_block *sb, void *data, int silent); diff --git a/fs/jfs/super.c b/fs/jfs/super.c index 18a28137b90..73d2aba084c 100644 --- a/fs/jfs/super.c +++ b/fs/jfs/super.c @@ -139,9 +139,9 @@ static void jfs_destroy_inode(struct inode *inode) kmem_cache_free(jfs_inode_cachep, ji); } -static int jfs_statfs(struct super_block *sb, struct kstatfs *buf) +static int jfs_statfs(struct dentry *dentry, struct kstatfs *buf) { - struct jfs_sb_info *sbi = JFS_SBI(sb); + struct jfs_sb_info *sbi = JFS_SBI(dentry->d_sb); s64 maxinodes; struct inomap *imap = JFS_IP(sbi->ipimap)->i_imap; diff --git a/fs/libfs.c b/fs/libfs.c index 7d70efa46da..1b115638178 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -20,9 +20,9 @@ int simple_getattr(struct vfsmount *mnt, struct dentry *dentry, return 0; } -int simple_statfs(struct super_block *sb, struct kstatfs *buf) +int simple_statfs(struct dentry *dentry, struct kstatfs *buf) { - buf->f_type = sb->s_magic; + buf->f_type = dentry->d_sb->s_magic; buf->f_bsize = PAGE_CACHE_SIZE; buf->f_namelen = NAME_MAX; return 0; diff --git a/fs/minix/inode.c b/fs/minix/inode.c index 14f24dfbfe3..a6fb509b734 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c @@ -19,7 +19,7 @@ static void minix_read_inode(struct inode * inode); static int minix_write_inode(struct inode * inode, int wait); -static int minix_statfs(struct super_block *sb, struct kstatfs *buf); +static int minix_statfs(struct dentry *dentry, struct kstatfs *buf); static int minix_remount (struct super_block * sb, int * flags, char * data); static void minix_delete_inode(struct inode *inode) @@ -296,11 +296,11 @@ out_bad_sb: return -EINVAL; } -static int minix_statfs(struct super_block *sb, struct kstatfs *buf) +static int minix_statfs(struct dentry *dentry, struct kstatfs *buf) { - struct minix_sb_info *sbi = minix_sb(sb); - buf->f_type = sb->s_magic; - buf->f_bsize = sb->s_blocksize; + struct minix_sb_info *sbi = minix_sb(dentry->d_sb); + buf->f_type = dentry->d_sb->s_magic; + buf->f_bsize = dentry->d_sb->s_blocksize; buf->f_blocks = (sbi->s_nzones - sbi->s_firstdatazone) << sbi->s_log_zone_size; buf->f_bfree = minix_count_free_blocks(sbi); buf->f_bavail = buf->f_bfree; diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index 8db033fab3f..90d2ea28f33 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c @@ -39,7 +39,7 @@ static void ncp_delete_inode(struct inode *); static void ncp_put_super(struct super_block *); -static int ncp_statfs(struct super_block *, struct kstatfs *); +static int ncp_statfs(struct dentry *, struct kstatfs *); static kmem_cache_t * ncp_inode_cachep; @@ -724,13 +724,14 @@ static void ncp_put_super(struct super_block *sb) kfree(server); } -static int ncp_statfs(struct super_block *sb, struct kstatfs *buf) +static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf) { struct dentry* d; struct inode* i; struct ncp_inode_info* ni; struct ncp_server* s; struct ncp_volume_info vi; + struct super_block *sb = dentry->d_sb; int err; __u8 dh; diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index ff645a961bc..937fbfc381b 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -65,7 +65,7 @@ static int nfs_write_inode(struct inode *,int); static void nfs_delete_inode(struct inode *); static void nfs_clear_inode(struct inode *); static void nfs_umount_begin(struct super_block *); -static int nfs_statfs(struct super_block *, struct kstatfs *); +static int nfs_statfs(struct dentry *, struct kstatfs *); static int nfs_show_options(struct seq_file *, struct vfsmount *); static int nfs_show_stats(struct seq_file *, struct vfsmount *); static void nfs_zap_acl_cache(struct inode *); @@ -534,8 +534,9 @@ nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data, int silent) } static int -nfs_statfs(struct super_block *sb, struct kstatfs *buf) +nfs_statfs(struct dentry *dentry, struct kstatfs *buf) { + struct super_block *sb = dentry->d_sb; struct nfs_server *server = NFS_SB(sb); unsigned char blockbits; unsigned long blockres; diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index de3998f15f1..5446a0861d1 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -1310,7 +1310,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, if ((bmval0 & (FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_TOTAL)) || (bmval1 & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE | FATTR4_WORD1_SPACE_TOTAL))) { - status = vfs_statfs(dentry->d_inode->i_sb, &statfs); + status = vfs_statfs(dentry, &statfs); if (status) goto out_nfserr; } diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 1d65f13f458..245eaa1fb59 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -1737,7 +1737,7 @@ int nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct kstatfs *stat) { int err = fh_verify(rqstp, fhp, 0, MAY_NOP); - if (!err && vfs_statfs(fhp->fh_dentry->d_inode->i_sb,stat)) + if (!err && vfs_statfs(fhp->fh_dentry,stat)) err = nfserr_io; return err; } diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c index d5d5e969294..0e14acea3f8 100644 --- a/fs/ntfs/super.c +++ b/fs/ntfs/super.c @@ -2601,10 +2601,10 @@ static unsigned long __get_nr_free_mft_records(ntfs_volume *vol, /** * ntfs_statfs - return information about mounted NTFS volume - * @sb: super block of mounted volume + * @dentry: dentry from mounted volume * @sfs: statfs structure in which to return the information * - * Return information about the mounted NTFS volume @sb in the statfs structure + * Return information about the mounted NTFS volume @dentry in the statfs structure * pointed to by @sfs (this is initialized with zeros before ntfs_statfs is * called). We interpret the values to be correct of the moment in time at * which we are called. Most values are variable otherwise and this isn't just @@ -2617,8 +2617,9 @@ static unsigned long __get_nr_free_mft_records(ntfs_volume *vol, * * Return 0 on success or -errno on error. */ -static int ntfs_statfs(struct super_block *sb, struct kstatfs *sfs) +static int ntfs_statfs(struct dentry *dentry, struct kstatfs *sfs) { + struct super_block *sb = dentry->d_sb; s64 size; ntfs_volume *vol = NTFS_SB(sb); ntfs_inode *mft_ni = NTFS_I(vol->mft_ino); diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 788b8b50dc4..cdf73393f09 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -100,7 +100,7 @@ static int ocfs2_initialize_mem_caches(void); static void ocfs2_free_mem_caches(void); static void ocfs2_delete_osb(struct ocfs2_super *osb); -static int ocfs2_statfs(struct super_block *sb, struct kstatfs *buf); +static int ocfs2_statfs(struct dentry *dentry, struct kstatfs *buf); static int ocfs2_sync_fs(struct super_block *sb, int wait); @@ -857,7 +857,7 @@ static void ocfs2_put_super(struct super_block *sb) mlog_exit_void(); } -static int ocfs2_statfs(struct super_block *sb, struct kstatfs *buf) +static int ocfs2_statfs(struct dentry *dentry, struct kstatfs *buf) { struct ocfs2_super *osb; u32 numbits, freebits; @@ -866,9 +866,9 @@ static int ocfs2_statfs(struct super_block *sb, struct kstatfs *buf) struct buffer_head *bh = NULL; struct inode *inode = NULL; - mlog_entry("(%p, %p)\n", sb, buf); + mlog_entry("(%p, %p)\n", dentry->d_sb, buf); - osb = OCFS2_SB(sb); + osb = OCFS2_SB(dentry->d_sb); inode = ocfs2_get_system_file_inode(osb, GLOBAL_BITMAP_SYSTEM_INODE, @@ -891,7 +891,7 @@ static int ocfs2_statfs(struct super_block *sb, struct kstatfs *buf) freebits = numbits - le32_to_cpu(bm_lock->id1.bitmap1.i_used); buf->f_type = OCFS2_SUPER_MAGIC; - buf->f_bsize = sb->s_blocksize; + buf->f_bsize = dentry->d_sb->s_blocksize; buf->f_namelen = OCFS2_MAX_FILENAME_LEN; buf->f_blocks = ((sector_t) numbits) * (osb->s_clustersize >> osb->sb->s_blocksize_bits); diff --git a/fs/open.c b/fs/open.c index 4f178acd4c0..a37ff861108 100644 --- a/fs/open.c +++ b/fs/open.c @@ -31,18 +31,18 @@ #include -int vfs_statfs(struct super_block *sb, struct kstatfs *buf) +int vfs_statfs(struct dentry *dentry, struct kstatfs *buf) { int retval = -ENODEV; - if (sb) { + if (dentry) { retval = -ENOSYS; - if (sb->s_op->statfs) { + if (dentry->d_sb->s_op->statfs) { memset(buf, 0, sizeof(*buf)); - retval = security_sb_statfs(sb); + retval = security_sb_statfs(dentry); if (retval) return retval; - retval = sb->s_op->statfs(sb, buf); + retval = dentry->d_sb->s_op->statfs(dentry, buf); if (retval == 0 && buf->f_frsize == 0) buf->f_frsize = buf->f_bsize; } @@ -52,12 +52,12 @@ int vfs_statfs(struct super_block *sb, struct kstatfs *buf) EXPORT_SYMBOL(vfs_statfs); -static int vfs_statfs_native(struct super_block *sb, struct statfs *buf) +static int vfs_statfs_native(struct dentry *dentry, struct statfs *buf) { struct kstatfs st; int retval; - retval = vfs_statfs(sb, &st); + retval = vfs_statfs(dentry, &st); if (retval) return retval; @@ -95,12 +95,12 @@ static int vfs_statfs_native(struct super_block *sb, struct statfs *buf) return 0; } -static int vfs_statfs64(struct super_block *sb, struct statfs64 *buf) +static int vfs_statfs64(struct dentry *dentry, struct statfs64 *buf) { struct kstatfs st; int retval; - retval = vfs_statfs(sb, &st); + retval = vfs_statfs(dentry, &st); if (retval) return retval; @@ -130,7 +130,7 @@ asmlinkage long sys_statfs(const char __user * path, struct statfs __user * buf) error = user_path_walk(path, &nd); if (!error) { struct statfs tmp; - error = vfs_statfs_native(nd.dentry->d_inode->i_sb, &tmp); + error = vfs_statfs_native(nd.dentry, &tmp); if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) error = -EFAULT; path_release(&nd); @@ -149,7 +149,7 @@ asmlinkage long sys_statfs64(const char __user *path, size_t sz, struct statfs64 error = user_path_walk(path, &nd); if (!error) { struct statfs64 tmp; - error = vfs_statfs64(nd.dentry->d_inode->i_sb, &tmp); + error = vfs_statfs64(nd.dentry, &tmp); if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) error = -EFAULT; path_release(&nd); @@ -168,7 +168,7 @@ asmlinkage long sys_fstatfs(unsigned int fd, struct statfs __user * buf) file = fget(fd); if (!file) goto out; - error = vfs_statfs_native(file->f_dentry->d_inode->i_sb, &tmp); + error = vfs_statfs_native(file->f_dentry, &tmp); if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) error = -EFAULT; fput(file); @@ -189,7 +189,7 @@ asmlinkage long sys_fstatfs64(unsigned int fd, size_t sz, struct statfs64 __user file = fget(fd); if (!file) goto out; - error = vfs_statfs64(file->f_dentry->d_inode->i_sb, &tmp); + error = vfs_statfs64(file->f_dentry, &tmp); if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) error = -EFAULT; fput(file); diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c index e6cca5cd4b4..2f24c46f72a 100644 --- a/fs/qnx4/inode.c +++ b/fs/qnx4/inode.c @@ -128,7 +128,7 @@ static struct inode *qnx4_alloc_inode(struct super_block *sb); static void qnx4_destroy_inode(struct inode *inode); static void qnx4_read_inode(struct inode *); static int qnx4_remount(struct super_block *sb, int *flags, char *data); -static int qnx4_statfs(struct super_block *, struct kstatfs *); +static int qnx4_statfs(struct dentry *, struct kstatfs *); static struct super_operations qnx4_sops = { @@ -282,8 +282,10 @@ unsigned long qnx4_block_map( struct inode *inode, long iblock ) return block; } -static int qnx4_statfs(struct super_block *sb, struct kstatfs *buf) +static int qnx4_statfs(struct dentry *dentry, struct kstatfs *buf) { + struct super_block *sb = dentry->d_sb; + lock_kernel(); buf->f_type = sb->s_magic; diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index f3ff41d3398..00f1321e920 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -60,7 +60,7 @@ static int is_any_reiserfs_magic_string(struct reiserfs_super_block *rs) } static int reiserfs_remount(struct super_block *s, int *flags, char *data); -static int reiserfs_statfs(struct super_block *s, struct kstatfs *buf); +static int reiserfs_statfs(struct dentry *dentry, struct kstatfs *buf); static int reiserfs_sync_fs(struct super_block *s, int wait) { @@ -1938,15 +1938,15 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) return errval; } -static int reiserfs_statfs(struct super_block *s, struct kstatfs *buf) +static int reiserfs_statfs(struct dentry *dentry, struct kstatfs *buf) { - struct reiserfs_super_block *rs = SB_DISK_SUPER_BLOCK(s); + struct reiserfs_super_block *rs = SB_DISK_SUPER_BLOCK(dentry->d_sb); buf->f_namelen = (REISERFS_MAX_NAME(s->s_blocksize)); buf->f_bfree = sb_free_blocks(rs); buf->f_bavail = buf->f_bfree; buf->f_blocks = sb_block_count(rs) - sb_bmap_nr(rs) - 1; - buf->f_bsize = s->s_blocksize; + buf->f_bsize = dentry->d_sb->s_blocksize; /* changed to accommodate gcc folks. */ buf->f_type = REISERFS_SUPER_MAGIC; return 0; diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c index 4d6cd662106..283fbc6b8ee 100644 --- a/fs/romfs/inode.c +++ b/fs/romfs/inode.c @@ -179,12 +179,12 @@ outnobh: /* That's simple too. */ static int -romfs_statfs(struct super_block *sb, struct kstatfs *buf) +romfs_statfs(struct dentry *dentry, struct kstatfs *buf) { buf->f_type = ROMFS_MAGIC; buf->f_bsize = ROMBSIZE; buf->f_bfree = buf->f_bavail = buf->f_ffree; - buf->f_blocks = (romfs_maxsize(sb)+ROMBSIZE-1)>>ROMBSBITS; + buf->f_blocks = (romfs_maxsize(dentry->d_sb)+ROMBSIZE-1)>>ROMBSBITS; buf->f_namelen = ROMFS_MAXFN; return 0; } diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c index 4a37c2bbfa3..506ff87c1d4 100644 --- a/fs/smbfs/inode.c +++ b/fs/smbfs/inode.c @@ -48,7 +48,7 @@ static void smb_delete_inode(struct inode *); static void smb_put_super(struct super_block *); -static int smb_statfs(struct super_block *, struct kstatfs *); +static int smb_statfs(struct dentry *, struct kstatfs *); static int smb_show_options(struct seq_file *, struct vfsmount *); static kmem_cache_t *smb_inode_cachep; @@ -641,13 +641,13 @@ out_no_server: } static int -smb_statfs(struct super_block *sb, struct kstatfs *buf) +smb_statfs(struct dentry *dentry, struct kstatfs *buf) { int result; lock_kernel(); - result = smb_proc_dskattr(sb, buf); + result = smb_proc_dskattr(dentry, buf); unlock_kernel(); diff --git a/fs/smbfs/proc.c b/fs/smbfs/proc.c index b1b878b8173..c3495059889 100644 --- a/fs/smbfs/proc.c +++ b/fs/smbfs/proc.c @@ -3226,9 +3226,9 @@ smb_proc_settime(struct dentry *dentry, struct smb_fattr *fattr) } int -smb_proc_dskattr(struct super_block *sb, struct kstatfs *attr) +smb_proc_dskattr(struct dentry *dentry, struct kstatfs *attr) { - struct smb_sb_info *server = SMB_SB(sb); + struct smb_sb_info *server = SMB_SB(dentry->d_sb); int result; char *p; long unit; diff --git a/fs/smbfs/proto.h b/fs/smbfs/proto.h index 47664597e6b..972ed7dad38 100644 --- a/fs/smbfs/proto.h +++ b/fs/smbfs/proto.h @@ -29,7 +29,7 @@ extern int smb_proc_getattr(struct dentry *dir, struct smb_fattr *fattr); extern int smb_proc_setattr(struct dentry *dir, struct smb_fattr *fattr); extern int smb_proc_setattr_unix(struct dentry *d, struct iattr *attr, unsigned int major, unsigned int minor); extern int smb_proc_settime(struct dentry *dentry, struct smb_fattr *fattr); -extern int smb_proc_dskattr(struct super_block *sb, struct kstatfs *attr); +extern int smb_proc_dskattr(struct dentry *dentry, struct kstatfs *attr); extern int smb_proc_read_link(struct smb_sb_info *server, struct dentry *d, char *buffer, int len); extern int smb_proc_symlink(struct smb_sb_info *server, struct dentry *d, const char *oldpath); extern int smb_proc_link(struct smb_sb_info *server, struct dentry *dentry, struct dentry *new_dentry); diff --git a/fs/super.c b/fs/super.c index 324c2d232f5..057b5325b7e 100644 --- a/fs/super.c +++ b/fs/super.c @@ -486,7 +486,7 @@ asmlinkage long sys_ustat(unsigned dev, struct ustat __user * ubuf) s = user_get_super(new_decode_dev(dev)); if (s == NULL) goto out; - err = vfs_statfs(s, &sbuf); + err = vfs_statfs(s->s_root, &sbuf); drop_super(s); if (err) goto out; diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c index 3ff89cc5833..58b2d22142b 100644 --- a/fs/sysv/inode.c +++ b/fs/sysv/inode.c @@ -85,8 +85,9 @@ static void sysv_put_super(struct super_block *sb) kfree(sbi); } -static int sysv_statfs(struct super_block *sb, struct kstatfs *buf) +static int sysv_statfs(struct dentry *dentry, struct kstatfs *buf) { + struct super_block *sb = dentry->d_sb; struct sysv_sb_info *sbi = SYSV_SB(sb); buf->f_type = sb->s_magic; diff --git a/fs/udf/super.c b/fs/udf/super.c index 2250774a831..44fe2cb0bbb 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -91,7 +91,7 @@ static void udf_load_partdesc(struct super_block *, struct buffer_head *); static void udf_open_lvid(struct super_block *); static void udf_close_lvid(struct super_block *); static unsigned int udf_count_free(struct super_block *); -static int udf_statfs(struct super_block *, struct kstatfs *); +static int udf_statfs(struct dentry *, struct kstatfs *); /* UDF filesystem type */ static int udf_get_sb(struct file_system_type *fs_type, @@ -1779,8 +1779,10 @@ udf_put_super(struct super_block *sb) * Written, tested, and released. */ static int -udf_statfs(struct super_block *sb, struct kstatfs *buf) +udf_statfs(struct dentry *dentry, struct kstatfs *buf) { + struct super_block *sb = dentry->d_sb; + buf->f_type = UDF_SUPER_MAGIC; buf->f_bsize = sb->s_blocksize; buf->f_blocks = UDF_SB_PARTLEN(sb, UDF_SB_PARTITION(sb)); diff --git a/fs/ufs/super.c b/fs/ufs/super.c index 768fb8d9e67..fe5ab2aa289 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -1113,8 +1113,9 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data) return 0; } -static int ufs_statfs (struct super_block *sb, struct kstatfs *buf) +static int ufs_statfs (struct dentry *dentry, struct kstatfs *buf) { + struct super_block *sb = dentry->d_sb; struct ufs_sb_private_info * uspi; struct ufs_super_block_first * usb1; struct ufs_super_block * usb; diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index d03c89a3665..4fb0fc65af3 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -684,10 +684,10 @@ xfs_fs_sync_super( STATIC int xfs_fs_statfs( - struct super_block *sb, + struct dentry *dentry, struct kstatfs *statp) { - return -bhv_vfs_statvfs(vfs_from_sb(sb), statp, NULL); + return -bhv_vfs_statvfs(vfs_from_sb(dentry->d_sb), statp, NULL); } STATIC int diff --git a/include/linux/coda_psdev.h b/include/linux/coda_psdev.h index d539262a8f8..98f6c52c152 100644 --- a/include/linux/coda_psdev.h +++ b/include/linux/coda_psdev.h @@ -70,7 +70,7 @@ int venus_pioctl(struct super_block *sb, struct CodaFid *fid, unsigned int cmd, struct PioctlData *data); int coda_downcall(int opcode, union outputArgs *out, struct super_block *sb); int venus_fsync(struct super_block *sb, struct CodaFid *fid); -int venus_statfs(struct super_block *sb, struct kstatfs *sfs); +int venus_statfs(struct dentry *dentry, struct kstatfs *sfs); /* messages between coda filesystem in kernel and Venus */ diff --git a/include/linux/fs.h b/include/linux/fs.h index 3e50dd24af8..c823a3815e2 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1096,7 +1096,7 @@ struct super_operations { int (*sync_fs)(struct super_block *sb, int wait); void (*write_super_lockfs) (struct super_block *); void (*unlockfs) (struct super_block *); - int (*statfs) (struct super_block *, struct kstatfs *); + int (*statfs) (struct dentry *, struct kstatfs *); int (*remount_fs) (struct super_block *, int *, char *); void (*clear_inode) (struct inode *); void (*umount_begin) (struct super_block *); @@ -1325,7 +1325,7 @@ extern struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int); extern void mnt_set_mountpoint(struct vfsmount *, struct dentry *, struct vfsmount *); -extern int vfs_statfs(struct super_block *, struct kstatfs *); +extern int vfs_statfs(struct dentry *, struct kstatfs *); /* /sys/fs */ extern struct subsystem fs_subsys; @@ -1746,7 +1746,7 @@ extern int dcache_dir_close(struct inode *, struct file *); extern loff_t dcache_dir_lseek(struct file *, loff_t, int); extern int dcache_readdir(struct file *, void *, filldir_t); extern int simple_getattr(struct vfsmount *, struct dentry *, struct kstat *); -extern int simple_statfs(struct super_block *, struct kstatfs *); +extern int simple_statfs(struct dentry *, struct kstatfs *); extern int simple_link(struct dentry *, struct inode *, struct dentry *); extern int simple_unlink(struct inode *, struct dentry *); extern int simple_rmdir(struct inode *, struct dentry *); diff --git a/include/linux/mount.h b/include/linux/mount.h index b7472ae91fa..60718f12caa 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h @@ -17,6 +17,11 @@ #include #include +struct super_block; +struct vfsmount; +struct dentry; +struct namespace; + #define MNT_NOSUID 0x01 #define MNT_NODEV 0x02 #define MNT_NOEXEC 0x04 diff --git a/include/linux/security.h b/include/linux/security.h index 47722d35553..383c320fc83 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -171,9 +171,9 @@ struct swap_info_struct; * Deallocate and clear the sb->s_security field. * @sb contains the super_block structure to be modified. * @sb_statfs: - * Check permission before obtaining filesystem statistics for the @sb - * filesystem. - * @sb contains the super_block structure for the filesystem. + * Check permission before obtaining filesystem statistics for the @mnt + * mountpoint. + * @dentry is a handle on the superblock for the filesystem. * Return 0 if permission is granted. * @sb_mount: * Check permission before an object specified by @dev_name is mounted on @@ -1127,7 +1127,7 @@ struct security_operations { int (*sb_copy_data)(struct file_system_type *type, void *orig, void *copy); int (*sb_kern_mount) (struct super_block *sb, void *data); - int (*sb_statfs) (struct super_block * sb); + int (*sb_statfs) (struct dentry *dentry); int (*sb_mount) (char *dev_name, struct nameidata * nd, char *type, unsigned long flags, void *data); int (*sb_check_sb) (struct vfsmount * mnt, struct nameidata * nd); @@ -1450,9 +1450,9 @@ static inline int security_sb_kern_mount (struct super_block *sb, void *data) return security_ops->sb_kern_mount (sb, data); } -static inline int security_sb_statfs (struct super_block *sb) +static inline int security_sb_statfs (struct dentry *dentry) { - return security_ops->sb_statfs (sb); + return security_ops->sb_statfs (dentry); } static inline int security_sb_mount (char *dev_name, struct nameidata *nd, @@ -2162,7 +2162,7 @@ static inline int security_sb_kern_mount (struct super_block *sb, void *data) return 0; } -static inline int security_sb_statfs (struct super_block *sb) +static inline int security_sb_statfs (struct dentry *dentry) { return 0; } diff --git a/kernel/acct.c b/kernel/acct.c index b327f4d2010..6802020e0ce 100644 --- a/kernel/acct.c +++ b/kernel/acct.c @@ -118,7 +118,7 @@ static int check_free_space(struct file *file) spin_unlock(&acct_globals.lock); /* May block */ - if (vfs_statfs(file->f_dentry->d_inode->i_sb, &sbuf)) + if (vfs_statfs(file->f_dentry, &sbuf)) return res; suspend = sbuf.f_blocks * SUSPEND; resume = sbuf.f_blocks * RESUME; diff --git a/mm/shmem.c b/mm/shmem.c index 7617bb1c6bf..10020d8b407 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -1654,9 +1654,9 @@ static ssize_t shmem_file_sendfile(struct file *in_file, loff_t *ppos, return desc.error; } -static int shmem_statfs(struct super_block *sb, struct kstatfs *buf) +static int shmem_statfs(struct dentry *dentry, struct kstatfs *buf) { - struct shmem_sb_info *sbinfo = SHMEM_SB(sb); + struct shmem_sb_info *sbinfo = SHMEM_SB(dentry->d_sb); buf->f_type = TMPFS_MAGIC; buf->f_bsize = PAGE_CACHE_SIZE; diff --git a/security/dummy.c b/security/dummy.c index 6de4a4a5eb1..c98d553984e 100644 --- a/security/dummy.c +++ b/security/dummy.c @@ -191,7 +191,7 @@ static int dummy_sb_kern_mount (struct super_block *sb, void *data) return 0; } -static int dummy_sb_statfs (struct super_block *sb) +static int dummy_sb_statfs (struct dentry *dentry) { return 0; } diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 524915dfda6..093efba4d9b 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1903,13 +1903,13 @@ static int selinux_sb_kern_mount(struct super_block *sb, void *data) return superblock_has_perm(current, sb, FILESYSTEM__MOUNT, &ad); } -static int selinux_sb_statfs(struct super_block *sb) +static int selinux_sb_statfs(struct dentry *dentry) { struct avc_audit_data ad; AVC_AUDIT_DATA_INIT(&ad,FS); - ad.u.fs.dentry = sb->s_root; - return superblock_has_perm(current, sb, FILESYSTEM__GETATTR, &ad); + ad.u.fs.dentry = dentry->d_sb->s_root; + return superblock_has_perm(current, dentry->d_sb, FILESYSTEM__GETATTR, &ad); } static int selinux_mount(char * dev_name, -- cgit v1.2.3 From d6938d1b2768fbf94d1091207d334ef7df786e5a Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 23 Jun 2006 02:02:59 -0700 Subject: [PATCH] XFS: Use the dentry passed to statfs() to limit the scope of the results Enable XFS to limit the statfs() results to the project quota covering the dentry used as a base for call. Signed-off-by: David Howells Signed-off-by: Nathan Scott Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/xfs/linux-2.6/xfs_super.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 4fb0fc65af3..9bdef9d5190 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -687,7 +687,8 @@ xfs_fs_statfs( struct dentry *dentry, struct kstatfs *statp) { - return -bhv_vfs_statvfs(vfs_from_sb(dentry->d_sb), statp, NULL); + return -bhv_vfs_statvfs(vfs_from_sb(dentry->d_sb), statp, + vn_from_inode(dentry->d_inode)); } STATIC int -- cgit v1.2.3 From 6f0419e06a3b151ab616a31accdabef41dc2d1b0 Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Fri, 23 Jun 2006 02:03:00 -0700 Subject: [PATCH] for_each_possible_cpu: xfs for_each_cpu() actually iterates across all possible CPUs. We've had mistakes in the past where people were using for_each_cpu() where they should have been iterating across only online or present CPUs. This is inefficient and possibly buggy. We're renaming for_each_cpu() to for_each_possible_cpu() to avoid this in the future. This patch replaces for_each_cpu with for_each_possible_cpu. in xfs. Signed-off-by: KAMEZAWA Hiroyuki Acked-by: Nathan Scott Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/xfs/linux-2.6/xfs_stats.c | 4 ++-- fs/xfs/linux-2.6/xfs_sysctl.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/xfs/linux-2.6/xfs_stats.c b/fs/xfs/linux-2.6/xfs_stats.c index 1f0589a05ec..e480b610205 100644 --- a/fs/xfs/linux-2.6/xfs_stats.c +++ b/fs/xfs/linux-2.6/xfs_stats.c @@ -62,7 +62,7 @@ xfs_read_xfsstats( while (j < xstats[i].endpoint) { val = 0; /* sum over all cpus */ - for_each_cpu(c) + for_each_possible_cpu(c) val += *(((__u32*)&per_cpu(xfsstats, c) + j)); len += sprintf(buffer + len, " %u", val); j++; @@ -70,7 +70,7 @@ xfs_read_xfsstats( buffer[len++] = '\n'; } /* extra precision counters */ - for_each_cpu(i) { + for_each_possible_cpu(i) { xs_xstrat_bytes += per_cpu(xfsstats, i).xs_xstrat_bytes; xs_write_bytes += per_cpu(xfsstats, i).xs_write_bytes; xs_read_bytes += per_cpu(xfsstats, i).xs_read_bytes; diff --git a/fs/xfs/linux-2.6/xfs_sysctl.c b/fs/xfs/linux-2.6/xfs_sysctl.c index 4af97682bec..af246532fbf 100644 --- a/fs/xfs/linux-2.6/xfs_sysctl.c +++ b/fs/xfs/linux-2.6/xfs_sysctl.c @@ -38,7 +38,7 @@ xfs_stats_clear_proc_handler( if (!ret && write && *valp) { printk("XFS Clearing xfsstats\n"); - for_each_cpu(c) { + for_each_possible_cpu(c) { preempt_disable(); /* save vn_active, it's a universal truth! */ vn_active = per_cpu(xfsstats, c).vn_active; -- cgit v1.2.3 From cb2b95e1c6b56e3d2369d3a5f4bc97f4fa180683 Mon Sep 17 00:00:00 2001 From: Andy Whitcroft Date: Fri, 23 Jun 2006 02:03:01 -0700 Subject: [PATCH] zone handle unaligned zone boundaries The buddy allocator has a requirement that boundaries between contigious zones occur aligned with the the MAX_ORDER ranges. Where they do not we will incorrectly merge pages cross zone boundaries. This can lead to pages from the wrong zone being handed out. Originally the buddy allocator would check that buddies were in the same zone by referencing the zone start and end page frame numbers. This was removed as it became very expensive and the buddy allocator already made the assumption that zones boundaries were aligned. It is clear that not all configurations and architectures are honouring this alignment requirement. Therefore it seems safest to reintroduce support for non-aligned zone boundaries. This patch introduces a new check when considering a page a buddy it compares the zone_table index for the two pages and refuses to merge the pages where they do not match. The zone_table index is unique for each node/zone combination when FLATMEM/DISCONTIGMEM is enabled and for each section/zone combination when SPARSEMEM is enabled (a SPARSEMEM section is at least a MAX_ORDER size). Signed-off-by: Andy Whitcroft Cc: Dave Hansen Cc: Mel Gorman Cc: Yasunori Goto Cc: KAMEZAWA Hiroyuki Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/mm.h | 7 +++++-- mm/page_alloc.c | 17 +++++++++++------ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index e2fa375e478..697c6bf248c 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -465,10 +465,13 @@ static inline unsigned long page_zonenum(struct page *page) struct zone; extern struct zone *zone_table[]; +static inline int page_zone_id(struct page *page) +{ + return (page->flags >> ZONETABLE_PGSHIFT) & ZONETABLE_MASK; +} static inline struct zone *page_zone(struct page *page) { - return zone_table[(page->flags >> ZONETABLE_PGSHIFT) & - ZONETABLE_MASK]; + return zone_table[page_zone_id(page)]; } static inline unsigned long page_to_nid(struct page *page) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 253a450c400..fd631c2536a 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -286,22 +286,27 @@ __find_combined_index(unsigned long page_idx, unsigned int order) * we can do coalesce a page and its buddy if * (a) the buddy is not in a hole && * (b) the buddy is in the buddy system && - * (c) a page and its buddy have the same order. + * (c) a page and its buddy have the same order && + * (d) a page and its buddy are in the same zone. * * For recording whether a page is in the buddy system, we use PG_buddy. * Setting, clearing, and testing PG_buddy is serialized by zone->lock. * * For recording page's order, we use page_private(page). */ -static inline int page_is_buddy(struct page *page, int order) +static inline int page_is_buddy(struct page *page, struct page *buddy, + int order) { #ifdef CONFIG_HOLES_IN_ZONE - if (!pfn_valid(page_to_pfn(page))) + if (!pfn_valid(page_to_pfn(buddy))) return 0; #endif - if (PageBuddy(page) && page_order(page) == order) { - BUG_ON(page_count(page) != 0); + if (page_zone_id(page) != page_zone_id(buddy)) + return 0; + + if (PageBuddy(buddy) && page_order(buddy) == order) { + BUG_ON(page_count(buddy) != 0); return 1; } return 0; @@ -352,7 +357,7 @@ static inline void __free_one_page(struct page *page, struct page *buddy; buddy = __page_find_buddy(page, page_idx, order); - if (!page_is_buddy(buddy, order)) + if (!page_is_buddy(page, buddy, order)) break; /* Move the buddy up one level. */ list_del(&buddy->lru); -- cgit v1.2.3 From 4da5eda0dca9730f59f391230304526ab4bffec7 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Fri, 23 Jun 2006 02:03:04 -0700 Subject: [PATCH] Page Migration: Make do_swap_page redo the fault It is better to redo the complete fault if do_swap_page() finds that the page is not in PageSwapCache() because the page migration code may have replaced the swap pte already with a pte pointing to valid memory. do_swap_page() may interpret an invalid swap entry without this patch because we do not reload the pte if we are looping back. The page migration code may already have reused the swap entry referenced by our local swp_entry. Signed-off-by: Christoph Lameter Cc: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memory.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/mm/memory.c b/mm/memory.c index 0ec7bc64427..7e3683fd4f3 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1879,7 +1879,6 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, goto out; entry = pte_to_swp_entry(orig_pte); -again: page = lookup_swap_cache(entry); if (!page) { swapin_readahead(entry, address, vma); @@ -1903,12 +1902,6 @@ again: mark_page_accessed(page); lock_page(page); - if (!PageSwapCache(page)) { - /* Page migration has occured */ - unlock_page(page); - page_cache_release(page); - goto again; - } /* * Back out if somebody else already faulted in this pte. -- cgit v1.2.3 From 729bd0b74ce9ac6c829109052fcd565f5c366ca5 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Fri, 23 Jun 2006 02:03:05 -0700 Subject: [PATCH] slab: extract cache_free_alien from __cache_free Move alien object freeing to cache_free_alien() to reduce #ifdef clutter in __cache_free(). Signed-off-by: Pekka Enberg Acked-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/slab.c | 77 ++++++++++++++++++++++++++++++++++----------------------------- 1 file changed, 42 insertions(+), 35 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index f1b644eb39d..bf05ea900ce 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -1024,6 +1024,40 @@ static void drain_alien_cache(struct kmem_cache *cachep, } } } + +static inline int cache_free_alien(struct kmem_cache *cachep, void *objp) +{ + struct slab *slabp = virt_to_slab(objp); + int nodeid = slabp->nodeid; + struct kmem_list3 *l3; + struct array_cache *alien = NULL; + + /* + * Make sure we are not freeing a object from another node to the array + * cache on this cpu. + */ + if (likely(slabp->nodeid == numa_node_id())) + return 0; + + l3 = cachep->nodelists[numa_node_id()]; + STATS_INC_NODEFREES(cachep); + if (l3->alien && l3->alien[nodeid]) { + alien = l3->alien[nodeid]; + spin_lock(&alien->lock); + if (unlikely(alien->avail == alien->limit)) { + STATS_INC_ACOVERFLOW(cachep); + __drain_alien_cache(cachep, alien, nodeid); + } + alien->entry[alien->avail++] = objp; + spin_unlock(&alien->lock); + } else { + spin_lock(&(cachep->nodelists[nodeid])->list_lock); + free_block(cachep, &objp, 1, nodeid); + spin_unlock(&(cachep->nodelists[nodeid])->list_lock); + } + return 1; +} + #else #define drain_alien_cache(cachep, alien) do { } while (0) @@ -1038,6 +1072,11 @@ static inline void free_alien_cache(struct array_cache **ac_ptr) { } +static inline int cache_free_alien(struct kmem_cache *cachep, void *objp) +{ + return 0; +} + #endif static int cpuup_callback(struct notifier_block *nfb, @@ -3087,41 +3126,9 @@ static inline void __cache_free(struct kmem_cache *cachep, void *objp) check_irq_off(); objp = cache_free_debugcheck(cachep, objp, __builtin_return_address(0)); - /* Make sure we are not freeing a object from another - * node to the array cache on this cpu. - */ -#ifdef CONFIG_NUMA - { - struct slab *slabp; - slabp = virt_to_slab(objp); - if (unlikely(slabp->nodeid != numa_node_id())) { - struct array_cache *alien = NULL; - int nodeid = slabp->nodeid; - struct kmem_list3 *l3; - - l3 = cachep->nodelists[numa_node_id()]; - STATS_INC_NODEFREES(cachep); - if (l3->alien && l3->alien[nodeid]) { - alien = l3->alien[nodeid]; - spin_lock(&alien->lock); - if (unlikely(alien->avail == alien->limit)) { - STATS_INC_ACOVERFLOW(cachep); - __drain_alien_cache(cachep, - alien, nodeid); - } - alien->entry[alien->avail++] = objp; - spin_unlock(&alien->lock); - } else { - spin_lock(&(cachep->nodelists[nodeid])-> - list_lock); - free_block(cachep, &objp, 1, nodeid); - spin_unlock(&(cachep->nodelists[nodeid])-> - list_lock); - } - return; - } - } -#endif + if (cache_free_alien(cachep, objp)) + return; + if (likely(ac->avail < ac->limit)) { STATS_INC_FREEHIT(cachep); ac->entry[ac->avail++] = objp; -- cgit v1.2.3 From f886ed443fedb109e2062988bf120a531f0ec80a Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 23 Jun 2006 02:03:06 -0700 Subject: [PATCH] PG_uncached is ia64 only As Nick points out, only ia64 uses PG_uncached. So we can push it up into the higher bits of the lower half of page->flags and make room for another flag on 32-bit machines. Cc: "Luck, Tony" Cc: Jesse Barnes Cc: Jes Sorensen Cc: Nick Piggin Cc: Andy Whitcroft Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/page-flags.h | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index d276a4e2f82..0c076d58c67 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h @@ -7,6 +7,8 @@ #include #include +#include + #include /* @@ -88,7 +90,17 @@ #define PG_nosave_free 18 /* Free, should not be written */ #define PG_buddy 19 /* Page is free, on buddy lists */ -#define PG_uncached 20 /* Page has been mapped as uncached */ + +#if (BITS_PER_LONG > 32) +/* + * 64-bit-only flags build down from bit 31 + * + * 32 bit -------------------------------| FIELDS | FLAGS | + * 64 bit | FIELDS | ?????? FLAGS | + * 63 32 0 + */ +#define PG_uncached 31 /* Page has been mapped as uncached */ +#endif /* * Global page accounting. One instance per CPU. Only unsigned longs are -- cgit v1.2.3 From 4776874ff096cd410382c0eca5d75f69c9dfa58f Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Fri, 23 Jun 2006 02:03:07 -0700 Subject: [PATCH] slab: page mapping cleanup Clean up slab allocator page mapping a bit. The memory allocated for a slab is physically contiguous so it is okay to assume struct pages are too so kill the long-standing comment. Furthermore, rename set_slab_attr to slab_map_pages and add a comment explaining why its needed. Signed-off-by: Pekka Enberg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/slab.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index bf05ea900ce..a94cf0fea8a 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -2499,23 +2499,28 @@ static void slab_put_obj(struct kmem_cache *cachep, struct slab *slabp, slabp->inuse--; } -static void set_slab_attr(struct kmem_cache *cachep, struct slab *slabp, - void *objp) +/* + * Map pages beginning at addr to the given cache and slab. This is required + * for the slab allocator to be able to lookup the cache and slab of a + * virtual address for kfree, ksize, kmem_ptr_validate, and slab debugging. + */ +static void slab_map_pages(struct kmem_cache *cache, struct slab *slab, + void *addr) { - int i; + int nr_pages; struct page *page; - /* Nasty!!!!!! I hope this is OK. */ - page = virt_to_page(objp); + page = virt_to_page(addr); - i = 1; + nr_pages = 1; if (likely(!PageCompound(page))) - i <<= cachep->gfporder; + nr_pages <<= cache->gfporder; + do { - page_set_cache(page, cachep); - page_set_slab(page, slabp); + page_set_cache(page, cache); + page_set_slab(page, slab); page++; - } while (--i); + } while (--nr_pages); } /* @@ -2587,7 +2592,7 @@ static int cache_grow(struct kmem_cache *cachep, gfp_t flags, int nodeid) goto opps1; slabp->nodeid = nodeid; - set_slab_attr(cachep, slabp, objp); + slab_map_pages(cachep, slabp, objp); cache_init_objs(cachep, slabp, ctor_flags); -- cgit v1.2.3 From 3c5a87f476bed45616e7e543dcaea4440c77bf93 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Fri, 23 Jun 2006 02:03:08 -0700 Subject: [PATCH] migration: remove unnecessary PageSwapCache checks Remove two unnecessary PageSwapCache checks. The page refcount is raised and therefore page migration cannot occur in both functions. Signed-off-by: Christoph Lameter Cc: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/shmem.c | 8 -------- mm/swapfile.c | 7 ------- 2 files changed, 15 deletions(-) diff --git a/mm/shmem.c b/mm/shmem.c index 10020d8b407..84b5cf9b63c 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -1081,14 +1081,6 @@ repeat: page_cache_release(swappage); goto repeat; } - if (!PageSwapCache(swappage)) { - /* Page migration has occured */ - shmem_swp_unmap(entry); - spin_unlock(&info->lock); - unlock_page(swappage); - page_cache_release(swappage); - goto repeat; - } if (PageWriteback(swappage)) { shmem_swp_unmap(entry); spin_unlock(&info->lock); diff --git a/mm/swapfile.c b/mm/swapfile.c index e5fd5385f0c..47a6812f5f8 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -716,7 +716,6 @@ static int try_to_unuse(unsigned int type) */ swap_map = &si->swap_map[i]; entry = swp_entry(type, i); -again: page = read_swap_cache_async(entry, NULL, 0); if (!page) { /* @@ -751,12 +750,6 @@ again: wait_on_page_locked(page); wait_on_page_writeback(page); lock_page(page); - if (!PageSwapCache(page)) { - /* Page migration has occured */ - unlock_page(page); - page_cache_release(page); - goto again; - } wait_on_page_writeback(page); /* -- cgit v1.2.3 From 02b694dea473ad3db1e2d1b14c1fef8fbd92e5e6 Mon Sep 17 00:00:00 2001 From: Yasunori Goto Date: Fri, 23 Jun 2006 02:03:08 -0700 Subject: [PATCH] wait_table and zonelist initializing for memory hotadd: change name of wait_table_size() This is just to rename from wait_table_size() to wait_table_hash_nr_entries(). Signed-off-by: Yasunori Goto Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/mmzone.h | 4 ++-- mm/page_alloc.c | 12 +++++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 9742e3c1622..652673ea92f 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -197,7 +197,7 @@ struct zone { /* * wait_table -- the array holding the hash table - * wait_table_size -- the size of the hash table array + * wait_table_hash_nr_entries -- the size of the hash table array * wait_table_bits -- wait_table_size == (1 << wait_table_bits) * * The purpose of all these is to keep track of the people @@ -220,7 +220,7 @@ struct zone { * free_area_init_core() performs the initialization of them. */ wait_queue_head_t * wait_table; - unsigned long wait_table_size; + unsigned long wait_table_hash_nr_entries; unsigned long wait_table_bits; /* diff --git a/mm/page_alloc.c b/mm/page_alloc.c index fd631c2536a..27320a0542d 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1727,7 +1727,7 @@ void __init build_all_zonelists(void) */ #define PAGES_PER_WAITQUEUE 256 -static inline unsigned long wait_table_size(unsigned long pages) +static inline unsigned long wait_table_hash_nr_entries(unsigned long pages) { unsigned long size = 1; @@ -2019,13 +2019,15 @@ void zone_wait_table_init(struct zone *zone, unsigned long zone_size_pages) * The per-page waitqueue mechanism uses hashed waitqueues * per zone. */ - zone->wait_table_size = wait_table_size(zone_size_pages); - zone->wait_table_bits = wait_table_bits(zone->wait_table_size); + zone->wait_table_hash_nr_entries = + wait_table_hash_nr_entries(zone_size_pages); + zone->wait_table_bits = + wait_table_bits(zone->wait_table_hash_nr_entries); zone->wait_table = (wait_queue_head_t *) - alloc_bootmem_node(pgdat, zone->wait_table_size + alloc_bootmem_node(pgdat, zone->wait_table_hash_nr_entries * sizeof(wait_queue_head_t)); - for(i = 0; i < zone->wait_table_size; ++i) + for(i = 0; i < zone->wait_table_hash_nr_entries; ++i) init_waitqueue_head(zone->wait_table + i); } -- cgit v1.2.3 From 86356ab147669bd3bcb2149fd9561d1280835c24 Mon Sep 17 00:00:00 2001 From: Yasunori Goto Date: Fri, 23 Jun 2006 02:03:09 -0700 Subject: [PATCH] wait_table and zonelist initializing for memory hotadd: change to meminit for build_zonelist Change definitions of some functions and data from __init to __meminit. These functions and data can be used after bootup by this patch to be used for hot-add codes. Signed-off-by: Yasunori Goto Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/bootmem.h | 4 ++-- mm/page_alloc.c | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h index da2d107fe2c..22866fa2d96 100644 --- a/include/linux/bootmem.h +++ b/include/linux/bootmem.h @@ -91,8 +91,8 @@ static inline void *alloc_remap(int nid, unsigned long size) } #endif -extern unsigned long __initdata nr_kernel_pages; -extern unsigned long __initdata nr_all_pages; +extern unsigned long nr_kernel_pages; +extern unsigned long nr_all_pages; extern void *__init alloc_large_system_hash(const char *tablename, unsigned long bucketsize, diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 27320a0542d..5ae75bead4d 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -83,8 +83,8 @@ EXPORT_SYMBOL(zone_table); static char *zone_names[MAX_NR_ZONES] = { "DMA", "DMA32", "Normal", "HighMem" }; int min_free_kbytes = 1024; -unsigned long __initdata nr_kernel_pages; -unsigned long __initdata nr_all_pages; +unsigned long __meminitdata nr_kernel_pages; +unsigned long __meminitdata nr_all_pages; #ifdef CONFIG_DEBUG_VM static int page_outside_zone_boundaries(struct zone *zone, struct page *page) @@ -1517,7 +1517,7 @@ void show_free_areas(void) * * Add all populated zones of a node to the zonelist. */ -static int __init build_zonelists_node(pg_data_t *pgdat, +static int __meminit build_zonelists_node(pg_data_t *pgdat, struct zonelist *zonelist, int nr_zones, int zone_type) { struct zone *zone; @@ -1553,7 +1553,7 @@ static inline int highest_zone(int zone_bits) #ifdef CONFIG_NUMA #define MAX_NODE_LOAD (num_online_nodes()) -static int __initdata node_load[MAX_NUMNODES]; +static int __meminitdata node_load[MAX_NUMNODES]; /** * find_next_best_node - find the next node that should appear in a given node's fallback list * @node: node whose fallback list we're appending @@ -1568,7 +1568,7 @@ static int __initdata node_load[MAX_NUMNODES]; * on them otherwise. * It returns -1 if no node is found. */ -static int __init find_next_best_node(int node, nodemask_t *used_node_mask) +static int __meminit find_next_best_node(int node, nodemask_t *used_node_mask) { int n, val; int min_val = INT_MAX; @@ -1614,7 +1614,7 @@ static int __init find_next_best_node(int node, nodemask_t *used_node_mask) return best_node; } -static void __init build_zonelists(pg_data_t *pgdat) +static void __meminit build_zonelists(pg_data_t *pgdat) { int i, j, k, node, local_node; int prev_node, load; @@ -1666,7 +1666,7 @@ static void __init build_zonelists(pg_data_t *pgdat) #else /* CONFIG_NUMA */ -static void __init build_zonelists(pg_data_t *pgdat) +static void __meminit build_zonelists(pg_data_t *pgdat) { int i, j, k, node, local_node; @@ -2071,7 +2071,7 @@ static __meminit void init_currently_empty_zone(struct zone *zone, * - mark all memory queues empty * - clear the memory bitmaps */ -static void __init free_area_init_core(struct pglist_data *pgdat, +static void __meminit free_area_init_core(struct pglist_data *pgdat, unsigned long *zones_size, unsigned long *zholes_size) { unsigned long j; @@ -2159,7 +2159,7 @@ static void __init alloc_node_mem_map(struct pglist_data *pgdat) #endif /* CONFIG_FLAT_NODE_MEM_MAP */ } -void __init free_area_init_node(int nid, struct pglist_data *pgdat, +void __meminit free_area_init_node(int nid, struct pglist_data *pgdat, unsigned long *zones_size, unsigned long node_start_pfn, unsigned long *zholes_size) { -- cgit v1.2.3 From 718127cc3170454f4aa274fdd2f1e01574fecd66 Mon Sep 17 00:00:00 2001 From: Yasunori Goto Date: Fri, 23 Jun 2006 02:03:10 -0700 Subject: [PATCH] wait_table and zonelist initializing for memory hotadd: add return code for init_current_empty_zone When add_zone() is called against empty zone (not populated zone), we have to initialize the zone which didn't initialize at boot time. But, init_currently_empty_zone() may fail due to allocation of wait table. So, this patch is to catch its error code. Changes against wait_table is in the next patch. Signed-off-by: KAMEZAWA Hiroyuki Signed-off-by: Yasunori Goto Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/mmzone.h | 3 +++ mm/memory_hotplug.c | 15 +++++++++++++-- mm/page_alloc.c | 11 ++++++++--- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 652673ea92f..e82fc1a52cd 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -333,6 +333,9 @@ void wakeup_kswapd(struct zone *zone, int order); int zone_watermark_ok(struct zone *z, int order, unsigned long mark, int classzone_idx, int alloc_flags); +extern int init_currently_empty_zone(struct zone *zone, unsigned long start_pfn, + unsigned long size); + #ifdef CONFIG_HAVE_MEMORY_PRESENT void memory_present(int nid, unsigned long start, unsigned long end); #else diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 70df5c0d957..71da5c98c9c 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -26,7 +26,7 @@ extern void zonetable_add(struct zone *zone, int nid, int zid, unsigned long pfn, unsigned long size); -static void __add_zone(struct zone *zone, unsigned long phys_start_pfn) +static int __add_zone(struct zone *zone, unsigned long phys_start_pfn) { struct pglist_data *pgdat = zone->zone_pgdat; int nr_pages = PAGES_PER_SECTION; @@ -34,8 +34,15 @@ static void __add_zone(struct zone *zone, unsigned long phys_start_pfn) int zone_type; zone_type = zone - pgdat->node_zones; + if (!populated_zone(zone)) { + int ret = 0; + ret = init_currently_empty_zone(zone, phys_start_pfn, nr_pages); + if (ret < 0) + return ret; + } memmap_init_zone(nr_pages, nid, zone_type, phys_start_pfn); zonetable_add(zone, nid, zone_type, phys_start_pfn, nr_pages); + return 0; } extern int sparse_add_one_section(struct zone *zone, unsigned long start_pfn, @@ -50,7 +57,11 @@ static int __add_section(struct zone *zone, unsigned long phys_start_pfn) if (ret < 0) return ret; - __add_zone(zone, phys_start_pfn); + ret = __add_zone(zone, phys_start_pfn); + + if (ret < 0) + return ret; + return register_new_memory(__pfn_to_section(phys_start_pfn)); } diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 5ae75bead4d..4bc66f6b771 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -2050,8 +2050,9 @@ static __meminit void zone_pcp_init(struct zone *zone) zone->name, zone->present_pages, batch); } -static __meminit void init_currently_empty_zone(struct zone *zone, - unsigned long zone_start_pfn, unsigned long size) +__meminit int init_currently_empty_zone(struct zone *zone, + unsigned long zone_start_pfn, + unsigned long size) { struct pglist_data *pgdat = zone->zone_pgdat; @@ -2063,6 +2064,8 @@ static __meminit void init_currently_empty_zone(struct zone *zone, memmap_init(size, pgdat->node_id, zone_idx(zone), zone_start_pfn); zone_init_free_lists(pgdat, zone, zone->spanned_pages); + + return 0; } /* @@ -2077,6 +2080,7 @@ static void __meminit free_area_init_core(struct pglist_data *pgdat, unsigned long j; int nid = pgdat->node_id; unsigned long zone_start_pfn = pgdat->node_start_pfn; + int ret; pgdat_resize_init(pgdat); pgdat->nr_zones = 0; @@ -2118,7 +2122,8 @@ static void __meminit free_area_init_core(struct pglist_data *pgdat, continue; zonetable_add(zone, nid, j, zone_start_pfn, size); - init_currently_empty_zone(zone, zone_start_pfn, size); + ret = init_currently_empty_zone(zone, zone_start_pfn, size); + BUG_ON(ret); zone_start_pfn += size; } } -- cgit v1.2.3 From cca448fe92246fb59efe55ba2e048ded0971a9af Mon Sep 17 00:00:00 2001 From: Yasunori Goto Date: Fri, 23 Jun 2006 02:03:10 -0700 Subject: [PATCH] wait_table and zonelist initializing for memory hotadd: wait_table initialization Wait_table is initialized according to zone size at boot time. But, we cannot know the maixmum zone size when memory hotplug is enabled. It can be changed.... And resizing of wait_table is hard. So kernel allocate and initialzie wait_table as its maximum size. Signed-off-by: KAMEZAWA Hiroyuki Signed-off-by: Yasunori Goto Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/page_alloc.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 53 insertions(+), 6 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 4bc66f6b771..62564e27b44 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1727,6 +1727,7 @@ void __init build_all_zonelists(void) */ #define PAGES_PER_WAITQUEUE 256 +#ifndef CONFIG_MEMORY_HOTPLUG static inline unsigned long wait_table_hash_nr_entries(unsigned long pages) { unsigned long size = 1; @@ -1745,6 +1746,29 @@ static inline unsigned long wait_table_hash_nr_entries(unsigned long pages) return max(size, 4UL); } +#else +/* + * A zone's size might be changed by hot-add, so it is not possible to determine + * a suitable size for its wait_table. So we use the maximum size now. + * + * The max wait table size = 4096 x sizeof(wait_queue_head_t). ie: + * + * i386 (preemption config) : 4096 x 16 = 64Kbyte. + * ia64, x86-64 (no preemption): 4096 x 20 = 80Kbyte. + * ia64, x86-64 (preemption) : 4096 x 24 = 96Kbyte. + * + * The maximum entries are prepared when a zone's memory is (512K + 256) pages + * or more by the traditional way. (See above). It equals: + * + * i386, x86-64, powerpc(4K page size) : = ( 2G + 1M)byte. + * ia64(16K page size) : = ( 8G + 4M)byte. + * powerpc (64K page size) : = (32G +16M)byte. + */ +static inline unsigned long wait_table_hash_nr_entries(unsigned long pages) +{ + return 4096UL; +} +#endif /* * This is an integer logarithm so that shifts can be used later @@ -2010,10 +2034,11 @@ void __init setup_per_cpu_pageset(void) #endif static __meminit -void zone_wait_table_init(struct zone *zone, unsigned long zone_size_pages) +int zone_wait_table_init(struct zone *zone, unsigned long zone_size_pages) { int i; struct pglist_data *pgdat = zone->zone_pgdat; + size_t alloc_size; /* * The per-page waitqueue mechanism uses hashed waitqueues @@ -2023,12 +2048,32 @@ void zone_wait_table_init(struct zone *zone, unsigned long zone_size_pages) wait_table_hash_nr_entries(zone_size_pages); zone->wait_table_bits = wait_table_bits(zone->wait_table_hash_nr_entries); - zone->wait_table = (wait_queue_head_t *) - alloc_bootmem_node(pgdat, zone->wait_table_hash_nr_entries - * sizeof(wait_queue_head_t)); + alloc_size = zone->wait_table_hash_nr_entries + * sizeof(wait_queue_head_t); + + if (system_state == SYSTEM_BOOTING) { + zone->wait_table = (wait_queue_head_t *) + alloc_bootmem_node(pgdat, alloc_size); + } else { + /* + * This case means that a zone whose size was 0 gets new memory + * via memory hot-add. + * But it may be the case that a new node was hot-added. In + * this case vmalloc() will not be able to use this new node's + * memory - this wait_table must be initialized to use this new + * node itself as well. + * To use this new node's memory, further consideration will be + * necessary. + */ + zone->wait_table = (wait_queue_head_t *)vmalloc(alloc_size); + } + if (!zone->wait_table) + return -ENOMEM; for(i = 0; i < zone->wait_table_hash_nr_entries; ++i) init_waitqueue_head(zone->wait_table + i); + + return 0; } static __meminit void zone_pcp_init(struct zone *zone) @@ -2055,8 +2100,10 @@ __meminit int init_currently_empty_zone(struct zone *zone, unsigned long size) { struct pglist_data *pgdat = zone->zone_pgdat; - - zone_wait_table_init(zone, size); + int ret; + ret = zone_wait_table_init(zone, size); + if (ret) + return ret; pgdat->nr_zones = zone_idx(zone) + 1; zone->zone_start_pfn = zone_start_pfn; -- cgit v1.2.3 From 6811378e7d8b9aa4fca2a1ca73d24c9d67c9cb12 Mon Sep 17 00:00:00 2001 From: Yasunori Goto Date: Fri, 23 Jun 2006 02:03:11 -0700 Subject: [PATCH] wait_table and zonelist initializing for memory hotadd: update zonelists In current code, zonelist is considered to be build once, no modification. But MemoryHotplug can add new zone/pgdat. It must be updated. This patch modifies build_all_zonelists(). By this, build_all_zonelist() can reconfig pgdat's zonelists. To update them safety, this patch use stop_machine_run(). Other cpus don't touch among updating them by using it. In old version (V2 of node hotadd), kernel updated them after zone initialization. But present_page of its new zone is still 0, because online_page() is not called yet at this time. Build_zonelists() checks present_pages to find present zone. It was too early. So, I changed it after online_pages(). Signed-off-by: Yasunori Goto Signed-off-by: KAMEZAWA Hiroyuki Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memory_hotplug.c | 12 ++++++++++++ mm/page_alloc.c | 26 +++++++++++++++++++++----- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 71da5c98c9c..1b1ac3db218 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -127,6 +127,7 @@ int online_pages(unsigned long pfn, unsigned long nr_pages) unsigned long flags; unsigned long onlined_pages = 0; struct zone *zone; + int need_zonelists_rebuild = 0; /* * This doesn't need a lock to do pfn_to_page(). @@ -139,6 +140,14 @@ int online_pages(unsigned long pfn, unsigned long nr_pages) grow_pgdat_span(zone->zone_pgdat, pfn, pfn + nr_pages); pgdat_resize_unlock(zone->zone_pgdat, &flags); + /* + * If this zone is not populated, then it is not in zonelist. + * This means the page allocator ignores this zone. + * So, zonelist must be updated after online. + */ + if (!populated_zone(zone)) + need_zonelists_rebuild = 1; + for (i = 0; i < nr_pages; i++) { struct page *page = pfn_to_page(pfn + i); online_page(page); @@ -149,5 +158,8 @@ int online_pages(unsigned long pfn, unsigned long nr_pages) setup_per_zone_pages_min(); + if (need_zonelists_rebuild) + build_all_zonelists(); + return 0; } diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 62564e27b44..9dfbe6b7d1c 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -1704,14 +1705,29 @@ static void __meminit build_zonelists(pg_data_t *pgdat) #endif /* CONFIG_NUMA */ -void __init build_all_zonelists(void) +/* return values int ....just for stop_machine_run() */ +static int __meminit __build_all_zonelists(void *dummy) { - int i; + int nid; + for_each_online_node(nid) + build_zonelists(NODE_DATA(nid)); + return 0; +} + +void __meminit build_all_zonelists(void) +{ + if (system_state == SYSTEM_BOOTING) { + __build_all_zonelists(0); + cpuset_init_current_mems_allowed(); + } else { + /* we have to stop all cpus to guaranntee there is no user + of zonelist */ + stop_machine_run(__build_all_zonelists, NULL, NR_CPUS); + /* cpuset refresh routine should be here */ + } - for_each_online_node(i) - build_zonelists(NODE_DATA(i)); printk("Built %i zonelists\n", num_online_nodes()); - cpuset_init_current_mems_allowed(); + } /* -- cgit v1.2.3 From 67de648211fa041fe08a0c25241a4980bbb90698 Mon Sep 17 00:00:00 2001 From: Andy Whitcroft Date: Fri, 23 Jun 2006 02:03:12 -0700 Subject: [PATCH] squash duplicate page_to_pfn and pfn_to_page We have architectures where the size of page_to_pfn and pfn_to_page are significant enough to overall image size that they wish to push them out of line. However, in the process we have grown a second copy of the implementation of each of these routines for each memory model. Share the implmentation exposing it either inline or out-of-line as required. Signed-off-by: Andy Whitcroft Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-generic/memory_model.h | 27 +++++++++++++++------------ mm/page_alloc.c | 32 ++------------------------------ 2 files changed, 17 insertions(+), 42 deletions(-) diff --git a/include/asm-generic/memory_model.h b/include/asm-generic/memory_model.h index 0cfb086dd37..8078cbd2c01 100644 --- a/include/asm-generic/memory_model.h +++ b/include/asm-generic/memory_model.h @@ -23,29 +23,23 @@ #endif /* CONFIG_DISCONTIGMEM */ -#ifdef CONFIG_OUT_OF_LINE_PFN_TO_PAGE -struct page; -/* this is useful when inlined pfn_to_page is too big */ -extern struct page *pfn_to_page(unsigned long pfn); -extern unsigned long page_to_pfn(struct page *page); -#else /* * supports 3 memory models. */ #if defined(CONFIG_FLATMEM) -#define pfn_to_page(pfn) (mem_map + ((pfn) - ARCH_PFN_OFFSET)) -#define page_to_pfn(page) ((unsigned long)((page) - mem_map) + \ +#define __pfn_to_page(pfn) (mem_map + ((pfn) - ARCH_PFN_OFFSET)) +#define __page_to_pfn(page) ((unsigned long)((page) - mem_map) + \ ARCH_PFN_OFFSET) #elif defined(CONFIG_DISCONTIGMEM) -#define pfn_to_page(pfn) \ +#define __pfn_to_page(pfn) \ ({ unsigned long __pfn = (pfn); \ unsigned long __nid = arch_pfn_to_nid(pfn); \ NODE_DATA(__nid)->node_mem_map + arch_local_page_offset(__pfn, __nid);\ }) -#define page_to_pfn(pg) \ +#define __page_to_pfn(pg) \ ({ struct page *__pg = (pg); \ struct pglist_data *__pgdat = NODE_DATA(page_to_nid(__pg)); \ (unsigned long)(__pg - __pgdat->node_mem_map) + \ @@ -57,18 +51,27 @@ extern unsigned long page_to_pfn(struct page *page); * Note: section's mem_map is encorded to reflect its start_pfn. * section[i].section_mem_map == mem_map's address - start_pfn; */ -#define page_to_pfn(pg) \ +#define __page_to_pfn(pg) \ ({ struct page *__pg = (pg); \ int __sec = page_to_section(__pg); \ __pg - __section_mem_map_addr(__nr_to_section(__sec)); \ }) -#define pfn_to_page(pfn) \ +#define __pfn_to_page(pfn) \ ({ unsigned long __pfn = (pfn); \ struct mem_section *__sec = __pfn_to_section(__pfn); \ __section_mem_map_addr(__sec) + __pfn; \ }) #endif /* CONFIG_FLATMEM/DISCONTIGMEM/SPARSEMEM */ + +#ifdef CONFIG_OUT_OF_LINE_PFN_TO_PAGE +struct page; +/* this is useful when inlined pfn_to_page is too big */ +extern struct page *pfn_to_page(unsigned long pfn); +extern unsigned long page_to_pfn(struct page *page); +#else +#define page_to_pfn __page_to_pfn +#define pfn_to_page __pfn_to_page #endif /* CONFIG_OUT_OF_LINE_PFN_TO_PAGE */ #endif /* __ASSEMBLY__ */ diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 9dfbe6b7d1c..5af33186a25 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -2879,42 +2879,14 @@ void *__init alloc_large_system_hash(const char *tablename, } #ifdef CONFIG_OUT_OF_LINE_PFN_TO_PAGE -/* - * pfn <-> page translation. out-of-line version. - * (see asm-generic/memory_model.h) - */ -#if defined(CONFIG_FLATMEM) -struct page *pfn_to_page(unsigned long pfn) -{ - return mem_map + (pfn - ARCH_PFN_OFFSET); -} -unsigned long page_to_pfn(struct page *page) -{ - return (page - mem_map) + ARCH_PFN_OFFSET; -} -#elif defined(CONFIG_DISCONTIGMEM) struct page *pfn_to_page(unsigned long pfn) { - int nid = arch_pfn_to_nid(pfn); - return NODE_DATA(nid)->node_mem_map + arch_local_page_offset(pfn,nid); + return __pfn_to_page(pfn); } unsigned long page_to_pfn(struct page *page) { - struct pglist_data *pgdat = NODE_DATA(page_to_nid(page)); - return (page - pgdat->node_mem_map) + pgdat->node_start_pfn; -} -#elif defined(CONFIG_SPARSEMEM) -struct page *pfn_to_page(unsigned long pfn) -{ - return __section_mem_map_addr(__pfn_to_section(pfn)) + pfn; -} - -unsigned long page_to_pfn(struct page *page) -{ - long section_id = page_to_section(page); - return page - __section_mem_map_addr(__nr_to_section(section_id)); + return __page_to_pfn(page); } -#endif /* CONFIG_FLATMEM/DISCONTIGMME/SPARSEMEM */ EXPORT_SYMBOL(pfn_to_page); EXPORT_SYMBOL(page_to_pfn); #endif /* CONFIG_OUT_OF_LINE_PFN_TO_PAGE */ -- cgit v1.2.3 From fadd8fbd153c12963f8fe3c9ef7f8967f286f98b Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Fri, 23 Jun 2006 02:03:13 -0700 Subject: [PATCH] support for panic at OOM This patch adds panic_on_oom sysctl under sys.vm. When sysctl vm.panic_on_oom = 1, the kernel panics intead of killing rogue processes. And if vm.panic_on_oom is 0 the kernel will do oom_kill() in the same way as it does today. Of course, the default value is 0 and only root can modifies it. In general, oom_killer works well and kill rogue processes. So the whole system can survive. But there are environments where panic is preferable rather than kill some processes. Signed-off-by: KAMEZAWA Hiroyuki Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/sysctl/vm.txt | 13 +++++++++++++ include/linux/sysctl.h | 1 + kernel/sysctl.c | 9 +++++++++ mm/oom_kill.c | 3 +++ 4 files changed, 26 insertions(+) diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt index a46c10fcddf..2dc246af488 100644 --- a/Documentation/sysctl/vm.txt +++ b/Documentation/sysctl/vm.txt @@ -29,6 +29,7 @@ Currently, these files are in /proc/sys/vm: - drop-caches - zone_reclaim_mode - zone_reclaim_interval +- panic_on_oom ============================================================== @@ -178,3 +179,15 @@ Time is set in seconds and set by default to 30 seconds. Reduce the interval if undesired off node allocations occur. However, too frequent scans will have a negative impact onoff node allocation performance. +============================================================= + +panic_on_oom + +This enables or disables panic on out-of-memory feature. If this is set to 1, +the kernel panics when out-of-memory happens. If this is set to 0, the kernel +will kill some rogue process, called oom_killer. Usually, oom_killer can kill +rogue processes and system will survive. If you want to panic the system +rather than killing rogue processes, set this to 1. + +The default value is 0. + diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index cee944dbdcd..c7132029af0 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -186,6 +186,7 @@ enum VM_PERCPU_PAGELIST_FRACTION=30,/* int: fraction of pages in each percpu_pagelist */ VM_ZONE_RECLAIM_MODE=31, /* reclaim local zone memory before going off node */ VM_ZONE_RECLAIM_INTERVAL=32, /* time period to wait after reclaim failure */ + VM_PANIC_ON_OOM=33, /* panic at out-of-memory */ }; diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 0d656e61621..072ac446810 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -59,6 +59,7 @@ extern int proc_nr_files(ctl_table *table, int write, struct file *filp, extern int C_A_D; extern int sysctl_overcommit_memory; extern int sysctl_overcommit_ratio; +extern int sysctl_panic_on_oom; extern int max_threads; extern int sysrq_enabled; extern int core_uses_pid; @@ -701,6 +702,14 @@ static ctl_table vm_table[] = { .mode = 0644, .proc_handler = &proc_dointvec, }, + { + .ctl_name = VM_PANIC_ON_OOM, + .procname = "panic_on_oom", + .data = &sysctl_panic_on_oom, + .maxlen = sizeof(sysctl_panic_on_oom), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, { .ctl_name = VM_OVERCOMMIT_RATIO, .procname = "overcommit_ratio", diff --git a/mm/oom_kill.c b/mm/oom_kill.c index 042e6436c3e..f9bb3cf3238 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -22,6 +22,7 @@ #include #include +int sysctl_panic_on_oom; /* #define DEBUG */ /** @@ -344,6 +345,8 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, int order) break; case CONSTRAINT_NONE: + if (sysctl_panic_on_oom) + panic("out of memory. panic_on_oom is selected\n"); retry: /* * Rambo mode: Shoot down a process and hope it solves whatever -- cgit v1.2.3 From 6937a25cff818d32d0f9ff58a518c9ab96760aeb Mon Sep 17 00:00:00 2001 From: Dave Peterson Date: Fri, 23 Jun 2006 02:03:13 -0700 Subject: [PATCH] mm: fix typos in comments in mm/oom_kill.c This fixes a few typos in the comments in mm/oom_kill.c. Signed-off-by: David S. Peterson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/oom_kill.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mm/oom_kill.c b/mm/oom_kill.c index f9bb3cf3238..d46ed0f1dc0 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -26,7 +26,7 @@ int sysctl_panic_on_oom; /* #define DEBUG */ /** - * oom_badness - calculate a numeric value for how bad this task has been + * badness - calculate a numeric value for how bad this task has been * @p: task struct of which task we should calculate * @uptime: current uptime in seconds * @@ -201,7 +201,7 @@ static struct task_struct *select_bad_process(unsigned long *ppoints) continue; /* - * This is in the process of releasing memory so for wait it + * This is in the process of releasing memory so wait for it * to finish before killing some other task by mistake. */ releasing = test_tsk_thread_flag(p, TIF_MEMDIE) || @@ -307,7 +307,7 @@ static int oom_kill_process(struct task_struct *p, unsigned long points, } /** - * oom_kill - kill the "best" process when we run out of memory + * out_of_memory - kill the "best" process when we run out of memory * * If we run out of memory, we have the choice between either * killing a random task (bad), letting the system crash (worse) -- cgit v1.2.3 From e8f03d02080b25f53cd6bba8dc3a297803f18c01 Mon Sep 17 00:00:00 2001 From: Andreas Dilger Date: Fri, 23 Jun 2006 02:03:14 -0700 Subject: [PATCH] reserve space for swap label Reserve space in the swap disk header for a LABEL and UUID to be specified. This has been possible with util-linux-2.12b (via e2fsprogs 1.36 libblkid), and is used by at least FC3 and later. The kernel doesn't really care about this, but the space shouldn't accidentally be used by something else either. Also make the on-disk structures be fixed-size types, instead of "int", though I don't know of any architecture in use where an "int" isn't the same size as a "__u32" (all current kernel arches have it as "unsigned int"). Signed-off-by: Andreas Dilger Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/swap.h | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/include/linux/swap.h b/include/linux/swap.h index aca9bfae208..cd28ad206da 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -48,12 +48,14 @@ union swap_header { char magic[10]; /* SWAP-SPACE or SWAPSPACE2 */ } magic; struct { - char bootbits[1024]; /* Space for disklabel etc. */ - unsigned int version; - unsigned int last_page; - unsigned int nr_badpages; - unsigned int padding[125]; - unsigned int badpages[1]; + char bootbits[1024]; /* Space for disklabel etc. */ + __u32 version; + __u32 last_page; + __u32 nr_badpages; + unsigned char sws_uuid[16]; + unsigned char sws_volume[16]; + __u32 padding[117]; + __u32 badpages[1]; } info; }; -- cgit v1.2.3 From a43a8c39bbb493c9e93f6764b350de2e33e18e92 Mon Sep 17 00:00:00 2001 From: "Chen, Kenneth W" Date: Fri, 23 Jun 2006 02:03:15 -0700 Subject: [PATCH] tightening hugetlb strict accounting Current hugetlb strict accounting for shared mapping always assume mapping starts at zero file offset and reserves pages between zero and size of the file. This assumption often reserves (or lock down) a lot more pages then necessary if application maps at none zero file offset. libhugetlbfs is one example that requires proper reservation on shared mapping starts at none zero offset. This patch extends the reservation and hugetlb strict accounting to support any arbitrary pair of (offset, len), resulting a much more robust and accurate scheme. More importantly, it won't lock down any hugetlb pages outside file mapping. Signed-off-by: Ken Chen Acked-by: Adam Litke Cc: David Gibson Cc: William Lee Irwin III Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/hugetlbfs/inode.c | 21 ++-- include/linux/hugetlb.h | 8 +- mm/hugetlb.c | 282 +++++++++++++++++++++++++++--------------------- 3 files changed, 173 insertions(+), 138 deletions(-) diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 678fc72c364..e6410d8edd0 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -59,7 +59,6 @@ static void huge_pagevec_release(struct pagevec *pvec) static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma) { struct inode *inode = file->f_dentry->d_inode; - struct hugetlbfs_inode_info *info = HUGETLBFS_I(inode); loff_t len, vma_len; int ret; @@ -87,9 +86,10 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma) if (!(vma->vm_flags & VM_WRITE) && len > inode->i_size) goto out; - if (vma->vm_flags & VM_MAYSHARE) - if (hugetlb_extend_reservation(info, len >> HPAGE_SHIFT) != 0) - goto out; + if (vma->vm_flags & VM_MAYSHARE && + hugetlb_reserve_pages(inode, vma->vm_pgoff >> (HPAGE_SHIFT-PAGE_SHIFT), + len >> HPAGE_SHIFT)) + goto out; ret = 0; hugetlb_prefault_arch_hook(vma->vm_mm); @@ -195,12 +195,8 @@ static void truncate_hugepages(struct inode *inode, loff_t lstart) const pgoff_t start = lstart >> HPAGE_SHIFT; struct pagevec pvec; pgoff_t next; - int i; + int i, freed = 0; - hugetlb_truncate_reservation(HUGETLBFS_I(inode), - lstart >> HPAGE_SHIFT); - if (!mapping->nrpages) - return; pagevec_init(&pvec, 0); next = start; while (1) { @@ -221,10 +217,12 @@ static void truncate_hugepages(struct inode *inode, loff_t lstart) truncate_huge_page(page); unlock_page(page); hugetlb_put_quota(mapping); + freed++; } huge_pagevec_release(&pvec); } BUG_ON(!lstart && mapping->nrpages); + hugetlb_unreserve_pages(inode, start, freed); } static void hugetlbfs_delete_inode(struct inode *inode) @@ -366,6 +364,7 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb, uid_t uid, inode->i_mapping->a_ops = &hugetlbfs_aops; inode->i_mapping->backing_dev_info =&hugetlbfs_backing_dev_info; inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; + INIT_LIST_HEAD(&inode->i_mapping->private_list); info = HUGETLBFS_I(inode); mpol_shared_policy_init(&info->policy, MPOL_DEFAULT, NULL); switch (mode & S_IFMT) { @@ -538,7 +537,6 @@ static struct inode *hugetlbfs_alloc_inode(struct super_block *sb) hugetlbfs_inc_free_inodes(sbinfo); return NULL; } - p->prereserved_hpages = 0; return &p->vfs_inode; } @@ -781,8 +779,7 @@ struct file *hugetlb_zero_setup(size_t size) goto out_file; error = -ENOMEM; - if (hugetlb_extend_reservation(HUGETLBFS_I(inode), - size >> HPAGE_SHIFT) != 0) + if (hugetlb_reserve_pages(inode, 0, size >> HPAGE_SHIFT)) goto out_inode; d_instantiate(dentry, inode); diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index 4c5e610fe44..c25a38d8f60 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -23,6 +23,8 @@ int hugetlb_report_node_meminfo(int, char *); unsigned long hugetlb_total_pages(void); int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long address, int write_access); +int hugetlb_reserve_pages(struct inode *inode, long from, long to); +void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed); extern unsigned long max_huge_pages; extern const unsigned long hugetlb_zero, hugetlb_infinity; @@ -139,8 +141,6 @@ struct hugetlbfs_sb_info { struct hugetlbfs_inode_info { struct shared_policy policy; - /* Protected by the (global) hugetlb_lock */ - unsigned long prereserved_hpages; struct inode vfs_inode; }; @@ -157,10 +157,6 @@ static inline struct hugetlbfs_sb_info *HUGETLBFS_SB(struct super_block *sb) extern const struct file_operations hugetlbfs_file_operations; extern struct vm_operations_struct hugetlb_vm_ops; struct file *hugetlb_zero_setup(size_t); -int hugetlb_extend_reservation(struct hugetlbfs_inode_info *info, - unsigned long atleast_hpages); -void hugetlb_truncate_reservation(struct hugetlbfs_inode_info *info, - unsigned long atmost_hpages); int hugetlb_get_quota(struct address_space *mapping); void hugetlb_put_quota(struct address_space *mapping); diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 832f676ca03..df499973255 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -22,7 +22,7 @@ #include "internal.h" const unsigned long hugetlb_zero = 0, hugetlb_infinity = ~0UL; -static unsigned long nr_huge_pages, free_huge_pages, reserved_huge_pages; +static unsigned long nr_huge_pages, free_huge_pages, resv_huge_pages; unsigned long max_huge_pages; static struct list_head hugepage_freelists[MAX_NUMNODES]; static unsigned int nr_huge_pages_node[MAX_NUMNODES]; @@ -123,39 +123,13 @@ static int alloc_fresh_huge_page(void) static struct page *alloc_huge_page(struct vm_area_struct *vma, unsigned long addr) { - struct inode *inode = vma->vm_file->f_dentry->d_inode; struct page *page; - int use_reserve = 0; - unsigned long idx; spin_lock(&hugetlb_lock); - - if (vma->vm_flags & VM_MAYSHARE) { - - /* idx = radix tree index, i.e. offset into file in - * HPAGE_SIZE units */ - idx = ((addr - vma->vm_start) >> HPAGE_SHIFT) - + (vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT)); - - /* The hugetlbfs specific inode info stores the number - * of "guaranteed available" (huge) pages. That is, - * the first 'prereserved_hpages' pages of the inode - * are either already instantiated, or have been - * pre-reserved (by hugetlb_reserve_for_inode()). Here - * we're in the process of instantiating the page, so - * we use this to determine whether to draw from the - * pre-reserved pool or the truly free pool. */ - if (idx < HUGETLBFS_I(inode)->prereserved_hpages) - use_reserve = 1; - } - - if (!use_reserve) { - if (free_huge_pages <= reserved_huge_pages) - goto fail; - } else { - BUG_ON(reserved_huge_pages == 0); - reserved_huge_pages--; - } + if (vma->vm_flags & VM_MAYSHARE) + resv_huge_pages--; + else if (free_huge_pages <= resv_huge_pages) + goto fail; page = dequeue_huge_page(vma, addr); if (!page) @@ -165,96 +139,11 @@ static struct page *alloc_huge_page(struct vm_area_struct *vma, set_page_refcounted(page); return page; - fail: - WARN_ON(use_reserve); /* reserved allocations shouldn't fail */ +fail: spin_unlock(&hugetlb_lock); return NULL; } -/* hugetlb_extend_reservation() - * - * Ensure that at least 'atleast' hugepages are, and will remain, - * available to instantiate the first 'atleast' pages of the given - * inode. If the inode doesn't already have this many pages reserved - * or instantiated, set aside some hugepages in the reserved pool to - * satisfy later faults (or fail now if there aren't enough, rather - * than getting the SIGBUS later). - */ -int hugetlb_extend_reservation(struct hugetlbfs_inode_info *info, - unsigned long atleast) -{ - struct inode *inode = &info->vfs_inode; - unsigned long change_in_reserve = 0; - int ret = 0; - - spin_lock(&hugetlb_lock); - read_lock_irq(&inode->i_mapping->tree_lock); - - if (info->prereserved_hpages >= atleast) - goto out; - - /* Because we always call this on shared mappings, none of the - * pages beyond info->prereserved_hpages can have been - * instantiated, so we need to reserve all of them now. */ - change_in_reserve = atleast - info->prereserved_hpages; - - if ((reserved_huge_pages + change_in_reserve) > free_huge_pages) { - ret = -ENOMEM; - goto out; - } - - reserved_huge_pages += change_in_reserve; - info->prereserved_hpages = atleast; - - out: - read_unlock_irq(&inode->i_mapping->tree_lock); - spin_unlock(&hugetlb_lock); - - return ret; -} - -/* hugetlb_truncate_reservation() - * - * This returns pages reserved for the given inode to the general free - * hugepage pool. If the inode has any pages prereserved, but not - * instantiated, beyond offset (atmost << HPAGE_SIZE), then release - * them. - */ -void hugetlb_truncate_reservation(struct hugetlbfs_inode_info *info, - unsigned long atmost) -{ - struct inode *inode = &info->vfs_inode; - struct address_space *mapping = inode->i_mapping; - unsigned long idx; - unsigned long change_in_reserve = 0; - struct page *page; - - spin_lock(&hugetlb_lock); - read_lock_irq(&inode->i_mapping->tree_lock); - - if (info->prereserved_hpages <= atmost) - goto out; - - /* Count pages which were reserved, but not instantiated, and - * which we can now release. */ - for (idx = atmost; idx < info->prereserved_hpages; idx++) { - page = radix_tree_lookup(&mapping->page_tree, idx); - if (!page) - /* Pages which are already instantiated can't - * be unreserved (and in fact have already - * been removed from the reserved pool) */ - change_in_reserve++; - } - - BUG_ON(reserved_huge_pages < change_in_reserve); - reserved_huge_pages -= change_in_reserve; - info->prereserved_hpages = atmost; - - out: - read_unlock_irq(&inode->i_mapping->tree_lock); - spin_unlock(&hugetlb_lock); -} - static int __init hugetlb_init(void) { unsigned long i; @@ -334,7 +223,7 @@ static unsigned long set_max_huge_pages(unsigned long count) return nr_huge_pages; spin_lock(&hugetlb_lock); - count = max(count, reserved_huge_pages); + count = max(count, resv_huge_pages); try_to_free_low(count); while (count < nr_huge_pages) { struct page *page = dequeue_huge_page(NULL, 0); @@ -361,11 +250,11 @@ int hugetlb_report_meminfo(char *buf) return sprintf(buf, "HugePages_Total: %5lu\n" "HugePages_Free: %5lu\n" - "HugePages_Rsvd: %5lu\n" + "HugePages_Rsvd: %5lu\n" "Hugepagesize: %5lu kB\n", nr_huge_pages, free_huge_pages, - reserved_huge_pages, + resv_huge_pages, HPAGE_SIZE/1024); } @@ -754,3 +643,156 @@ void hugetlb_change_protection(struct vm_area_struct *vma, flush_tlb_range(vma, start, end); } +struct file_region { + struct list_head link; + long from; + long to; +}; + +static long region_add(struct list_head *head, long f, long t) +{ + struct file_region *rg, *nrg, *trg; + + /* Locate the region we are either in or before. */ + list_for_each_entry(rg, head, link) + if (f <= rg->to) + break; + + /* Round our left edge to the current segment if it encloses us. */ + if (f > rg->from) + f = rg->from; + + /* Check for and consume any regions we now overlap with. */ + nrg = rg; + list_for_each_entry_safe(rg, trg, rg->link.prev, link) { + if (&rg->link == head) + break; + if (rg->from > t) + break; + + /* If this area reaches higher then extend our area to + * include it completely. If this is not the first area + * which we intend to reuse, free it. */ + if (rg->to > t) + t = rg->to; + if (rg != nrg) { + list_del(&rg->link); + kfree(rg); + } + } + nrg->from = f; + nrg->to = t; + return 0; +} + +static long region_chg(struct list_head *head, long f, long t) +{ + struct file_region *rg, *nrg; + long chg = 0; + + /* Locate the region we are before or in. */ + list_for_each_entry(rg, head, link) + if (f <= rg->to) + break; + + /* If we are below the current region then a new region is required. + * Subtle, allocate a new region at the position but make it zero + * size such that we can guarentee to record the reservation. */ + if (&rg->link == head || t < rg->from) { + nrg = kmalloc(sizeof(*nrg), GFP_KERNEL); + if (nrg == 0) + return -ENOMEM; + nrg->from = f; + nrg->to = f; + INIT_LIST_HEAD(&nrg->link); + list_add(&nrg->link, rg->link.prev); + + return t - f; + } + + /* Round our left edge to the current segment if it encloses us. */ + if (f > rg->from) + f = rg->from; + chg = t - f; + + /* Check for and consume any regions we now overlap with. */ + list_for_each_entry(rg, rg->link.prev, link) { + if (&rg->link == head) + break; + if (rg->from > t) + return chg; + + /* We overlap with this area, if it extends futher than + * us then we must extend ourselves. Account for its + * existing reservation. */ + if (rg->to > t) { + chg += rg->to - t; + t = rg->to; + } + chg -= rg->to - rg->from; + } + return chg; +} + +static long region_truncate(struct list_head *head, long end) +{ + struct file_region *rg, *trg; + long chg = 0; + + /* Locate the region we are either in or before. */ + list_for_each_entry(rg, head, link) + if (end <= rg->to) + break; + if (&rg->link == head) + return 0; + + /* If we are in the middle of a region then adjust it. */ + if (end > rg->from) { + chg = rg->to - end; + rg->to = end; + rg = list_entry(rg->link.next, typeof(*rg), link); + } + + /* Drop any remaining regions. */ + list_for_each_entry_safe(rg, trg, rg->link.prev, link) { + if (&rg->link == head) + break; + chg += rg->to - rg->from; + list_del(&rg->link); + kfree(rg); + } + return chg; +} + +static int hugetlb_acct_memory(long delta) +{ + int ret = -ENOMEM; + + spin_lock(&hugetlb_lock); + if ((delta + resv_huge_pages) <= free_huge_pages) { + resv_huge_pages += delta; + ret = 0; + } + spin_unlock(&hugetlb_lock); + return ret; +} + +int hugetlb_reserve_pages(struct inode *inode, long from, long to) +{ + long ret, chg; + + chg = region_chg(&inode->i_mapping->private_list, from, to); + if (chg < 0) + return chg; + ret = hugetlb_acct_memory(chg); + if (ret < 0) + return ret; + region_add(&inode->i_mapping->private_list, from, to); + return 0; +} + +void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed) +{ + long chg = region_truncate(&inode->i_mapping->private_list, offset); + hugetlb_acct_memory(freed - chg); +} -- cgit v1.2.3 From e1b6aa6f1404f162697650df2cdb6c374b1d6a5b Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 23 Jun 2006 02:03:17 -0700 Subject: [PATCH] slab: clean up kmem_getpages The last ifdef addition hit the ugliness treshold on this functions, so: - rename the variable i to nr_pages so it's somewhat descriptive - remove the addr variable and do the page_address call at the very end - instead of ifdef'ing the whole alloc_pages_node call just make the __GFP_COMP addition to flags conditional - rewrite the __GFP_COMP comment to make sense Signed-off-by: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/slab.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index a94cf0fea8a..7bd19639efd 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -1489,31 +1489,29 @@ __initcall(cpucache_init); static void *kmem_getpages(struct kmem_cache *cachep, gfp_t flags, int nodeid) { struct page *page; - void *addr; + int nr_pages; int i; - flags |= cachep->gfpflags; #ifndef CONFIG_MMU - /* nommu uses slab's for process anonymous memory allocations, so - * requires __GFP_COMP to properly refcount higher order allocations" + /* + * Nommu uses slab's for process anonymous memory allocations, and thus + * requires __GFP_COMP to properly refcount higher order allocations */ - page = alloc_pages_node(nodeid, (flags | __GFP_COMP), cachep->gfporder); -#else - page = alloc_pages_node(nodeid, flags, cachep->gfporder); + flags |= __GFP_COMP; #endif + flags |= cachep->gfpflags; + + page = alloc_pages_node(nodeid, flags, cachep->gfporder); if (!page) return NULL; - addr = page_address(page); - i = (1 << cachep->gfporder); + nr_pages = (1 << cachep->gfporder); if (cachep->flags & SLAB_RECLAIM_ACCOUNT) - atomic_add(i, &slab_reclaim_pages); - add_page_state(nr_slab, i); - while (i--) { - __SetPageSlab(page); - page++; - } - return addr; + atomic_add(nr_pages, &slab_reclaim_pages); + add_page_state(nr_slab, nr_pages); + for (i = 0; i < nr_pages; i++) + __SetPageSlab(page + i); + return page_address(page); } /* -- cgit v1.2.3 From 7a7c381d25067b9a2bfe025dfcb16459daec0373 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 23 Jun 2006 02:03:17 -0700 Subject: [PATCH] slab: stop using list_for_each Use the _entry variant everywhere to clean the code up a tiny bit. Signed-off-by: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/slab.c | 38 +++++++++++--------------------------- 1 file changed, 11 insertions(+), 27 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index 7bd19639efd..54bd2eb3f2f 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -1950,8 +1950,7 @@ kmem_cache_create (const char *name, size_t size, size_t align, void (*dtor)(void*, struct kmem_cache *, unsigned long)) { size_t left_over, slab_size, ralign; - struct kmem_cache *cachep = NULL; - struct list_head *p; + struct kmem_cache *cachep = NULL, *pc; /* * Sanity checks... these are all serious usage bugs. @@ -1971,8 +1970,7 @@ kmem_cache_create (const char *name, size_t size, size_t align, mutex_lock(&cache_chain_mutex); - list_for_each(p, &cache_chain) { - struct kmem_cache *pc = list_entry(p, struct kmem_cache, next); + list_for_each_entry(pc, &cache_chain, next) { mm_segment_t old_fs = get_fs(); char tmp; int res; @@ -3690,7 +3688,7 @@ void drain_array(struct kmem_cache *cachep, struct kmem_list3 *l3, */ static void cache_reap(void *unused) { - struct list_head *walk; + struct kmem_cache *searchp; struct kmem_list3 *l3; int node = numa_node_id(); @@ -3701,13 +3699,11 @@ static void cache_reap(void *unused) return; } - list_for_each(walk, &cache_chain) { - struct kmem_cache *searchp; + list_for_each_entry(searchp, &cache_chain, next) { struct list_head *p; int tofree; struct slab *slabp; - searchp = list_entry(walk, struct kmem_cache, next); check_irq_on(); /* @@ -3835,7 +3831,6 @@ static void s_stop(struct seq_file *m, void *p) static int s_show(struct seq_file *m, void *p) { struct kmem_cache *cachep = p; - struct list_head *q; struct slab *slabp; unsigned long active_objs; unsigned long num_objs; @@ -3856,15 +3851,13 @@ static int s_show(struct seq_file *m, void *p) check_irq_on(); spin_lock_irq(&l3->list_lock); - list_for_each(q, &l3->slabs_full) { - slabp = list_entry(q, struct slab, list); + list_for_each_entry(slabp, &l3->slabs_full, list) { if (slabp->inuse != cachep->num && !error) error = "slabs_full accounting error"; active_objs += cachep->num; active_slabs++; } - list_for_each(q, &l3->slabs_partial) { - slabp = list_entry(q, struct slab, list); + list_for_each_entry(slabp, &l3->slabs_partial, list) { if (slabp->inuse == cachep->num && !error) error = "slabs_partial inuse accounting error"; if (!slabp->inuse && !error) @@ -3872,8 +3865,7 @@ static int s_show(struct seq_file *m, void *p) active_objs += slabp->inuse; active_slabs++; } - list_for_each(q, &l3->slabs_free) { - slabp = list_entry(q, struct slab, list); + list_for_each_entry(slabp, &l3->slabs_free, list) { if (slabp->inuse && !error) error = "slabs_free/inuse accounting error"; num_slabs++; @@ -3966,7 +3958,7 @@ ssize_t slabinfo_write(struct file *file, const char __user * buffer, { char kbuf[MAX_SLABINFO_WRITE + 1], *tmp; int limit, batchcount, shared, res; - struct list_head *p; + struct kmem_cache *cachep; if (count > MAX_SLABINFO_WRITE) return -EINVAL; @@ -3985,10 +3977,7 @@ ssize_t slabinfo_write(struct file *file, const char __user * buffer, /* Find the cache in the chain of caches. */ mutex_lock(&cache_chain_mutex); res = -EINVAL; - list_for_each(p, &cache_chain) { - struct kmem_cache *cachep; - - cachep = list_entry(p, struct kmem_cache, next); + list_for_each_entry(cachep, &cache_chain, next) { if (!strcmp(cachep->name, kbuf)) { if (limit < 1 || batchcount < 1 || batchcount > limit || shared < 0) { @@ -4090,7 +4079,6 @@ static void show_symbol(struct seq_file *m, unsigned long address) static int leaks_show(struct seq_file *m, void *p) { struct kmem_cache *cachep = p; - struct list_head *q; struct slab *slabp; struct kmem_list3 *l3; const char *name; @@ -4115,14 +4103,10 @@ static int leaks_show(struct seq_file *m, void *p) check_irq_on(); spin_lock_irq(&l3->list_lock); - list_for_each(q, &l3->slabs_full) { - slabp = list_entry(q, struct slab, list); + list_for_each_entry(slabp, &l3->slabs_full, list) handle_slab(n, cachep, slabp); - } - list_for_each(q, &l3->slabs_partial) { - slabp = list_entry(q, struct slab, list); + list_for_each_entry(slabp, &l3->slabs_partial, list) handle_slab(n, cachep, slabp); - } spin_unlock_irq(&l3->list_lock); } name = cachep->name; -- cgit v1.2.3 From d6277db4ab271862ed599da08d78961c70f00002 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 23 Jun 2006 02:03:18 -0700 Subject: [PATCH] swsusp: rework memory shrinker MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rework the swsusp's memory shrinker in the following way: - Simplify balance_pgdat() by removing all of the swsusp-related code from it. - Make shrink_all_memory() use shrink_slab() and a new function shrink_all_zones() which calls shrink_active_list() and shrink_inactive_list() directly for each zone in a way that's optimized for suspend. In shrink_all_memory() we try to free exactly as many pages as the caller asks for, preferably in one shot, starting from easier targets.  If slab caches are huge, they are most likely to have enough pages to reclaim.  The inactive lists are next (the zones with more inactive pages go first) etc. Each time shrink_all_memory() attempts to shrink the active and inactive lists for each zone in 5 passes.  In the first pass, only the inactive lists are taken into consideration.  In the next two passes the active lists are also shrunk, but mapped pages are not reclaimed.  In the last two passes the active and inactive lists are shrunk and mapped pages are reclaimed as well. The aim of this is to alter the reclaim logic to choose the best pages to keep on resume and improve the responsiveness of the resumed system. Signed-off-by: Rafael J. Wysocki Signed-off-by: Con Kolivas Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/power/swsusp.c | 10 ++- mm/vmscan.c | 219 +++++++++++++++++++++++++++++++++++++------------- 2 files changed, 172 insertions(+), 57 deletions(-) diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c index c4016cbbd3e..f9238faf76e 100644 --- a/kernel/power/swsusp.c +++ b/kernel/power/swsusp.c @@ -175,6 +175,12 @@ void free_all_swap_pages(int swap, struct bitmap_page *bitmap) */ #define SHRINK_BITE 10000 +static inline unsigned long __shrink_memory(long tmp) +{ + if (tmp > SHRINK_BITE) + tmp = SHRINK_BITE; + return shrink_all_memory(tmp); +} int swsusp_shrink_memory(void) { @@ -195,12 +201,12 @@ int swsusp_shrink_memory(void) if (!is_highmem(zone)) tmp -= zone->free_pages; if (tmp > 0) { - tmp = shrink_all_memory(SHRINK_BITE); + tmp = __shrink_memory(tmp); if (!tmp) return -ENOMEM; pages += tmp; } else if (size > image_size / PAGE_SIZE) { - tmp = shrink_all_memory(SHRINK_BITE); + tmp = __shrink_memory(size - (image_size / PAGE_SIZE)); pages += tmp; } printk("\b%c", p[i++%4]); diff --git a/mm/vmscan.c b/mm/vmscan.c index 440a733fe2e..46be8a02280 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -61,6 +61,8 @@ struct scan_control { * In this context, it doesn't matter that we scan the * whole list at once. */ int swap_cluster_max; + + int swappiness; }; /* @@ -741,7 +743,7 @@ static void shrink_active_list(unsigned long nr_pages, struct zone *zone, * A 100% value of vm_swappiness overrides this algorithm * altogether. */ - swap_tendency = mapped_ratio / 2 + distress + vm_swappiness; + swap_tendency = mapped_ratio / 2 + distress + sc->swappiness; /* * Now use this metric to decide whether to start moving mapped @@ -957,6 +959,7 @@ unsigned long try_to_free_pages(struct zone **zones, gfp_t gfp_mask) .may_writepage = !laptop_mode, .swap_cluster_max = SWAP_CLUSTER_MAX, .may_swap = 1, + .swappiness = vm_swappiness, }; inc_page_state(allocstall); @@ -1021,10 +1024,6 @@ out: * For kswapd, balance_pgdat() will work across all this node's zones until * they are all at pages_high. * - * If `nr_pages' is non-zero then it is the number of pages which are to be - * reclaimed, regardless of the zone occupancies. This is a software suspend - * special. - * * Returns the number of pages which were actually freed. * * There is special handling here for zones which are full of pinned pages. @@ -1042,10 +1041,8 @@ out: * the page allocator fallback scheme to ensure that aging of pages is balanced * across the zones. */ -static unsigned long balance_pgdat(pg_data_t *pgdat, unsigned long nr_pages, - int order) +static unsigned long balance_pgdat(pg_data_t *pgdat, int order) { - unsigned long to_free = nr_pages; int all_zones_ok; int priority; int i; @@ -1055,7 +1052,8 @@ static unsigned long balance_pgdat(pg_data_t *pgdat, unsigned long nr_pages, struct scan_control sc = { .gfp_mask = GFP_KERNEL, .may_swap = 1, - .swap_cluster_max = nr_pages ? nr_pages : SWAP_CLUSTER_MAX, + .swap_cluster_max = SWAP_CLUSTER_MAX, + .swappiness = vm_swappiness, }; loop_again: @@ -1082,31 +1080,26 @@ loop_again: all_zones_ok = 1; - if (nr_pages == 0) { - /* - * Scan in the highmem->dma direction for the highest - * zone which needs scanning - */ - for (i = pgdat->nr_zones - 1; i >= 0; i--) { - struct zone *zone = pgdat->node_zones + i; + /* + * Scan in the highmem->dma direction for the highest + * zone which needs scanning + */ + for (i = pgdat->nr_zones - 1; i >= 0; i--) { + struct zone *zone = pgdat->node_zones + i; - if (!populated_zone(zone)) - continue; + if (!populated_zone(zone)) + continue; - if (zone->all_unreclaimable && - priority != DEF_PRIORITY) - continue; + if (zone->all_unreclaimable && priority != DEF_PRIORITY) + continue; - if (!zone_watermark_ok(zone, order, - zone->pages_high, 0, 0)) { - end_zone = i; - goto scan; - } + if (!zone_watermark_ok(zone, order, zone->pages_high, + 0, 0)) { + end_zone = i; + goto scan; } - goto out; - } else { - end_zone = pgdat->nr_zones - 1; } + goto out; scan: for (i = 0; i <= end_zone; i++) { struct zone *zone = pgdat->node_zones + i; @@ -1133,11 +1126,9 @@ scan: if (zone->all_unreclaimable && priority != DEF_PRIORITY) continue; - if (nr_pages == 0) { /* Not software suspend */ - if (!zone_watermark_ok(zone, order, - zone->pages_high, end_zone, 0)) - all_zones_ok = 0; - } + if (!zone_watermark_ok(zone, order, zone->pages_high, + end_zone, 0)) + all_zones_ok = 0; zone->temp_priority = priority; if (zone->prev_priority > priority) zone->prev_priority = priority; @@ -1162,8 +1153,6 @@ scan: total_scanned > nr_reclaimed + nr_reclaimed / 2) sc.may_writepage = 1; } - if (nr_pages && to_free > nr_reclaimed) - continue; /* swsusp: need to do more work */ if (all_zones_ok) break; /* kswapd: all done */ /* @@ -1179,7 +1168,7 @@ scan: * matches the direct reclaim path behaviour in terms of impact * on zone->*_priority. */ - if ((nr_reclaimed >= SWAP_CLUSTER_MAX) && !nr_pages) + if (nr_reclaimed >= SWAP_CLUSTER_MAX) break; } out: @@ -1261,7 +1250,7 @@ static int kswapd(void *p) } finish_wait(&pgdat->kswapd_wait, &wait); - balance_pgdat(pgdat, 0, order); + balance_pgdat(pgdat, order); } return 0; } @@ -1290,35 +1279,154 @@ void wakeup_kswapd(struct zone *zone, int order) #ifdef CONFIG_PM /* - * Try to free `nr_pages' of memory, system-wide. Returns the number of freed - * pages. + * Helper function for shrink_all_memory(). Tries to reclaim 'nr_pages' pages + * from LRU lists system-wide, for given pass and priority, and returns the + * number of reclaimed pages + * + * For pass > 3 we also try to shrink the LRU lists that contain a few pages + */ +static unsigned long shrink_all_zones(unsigned long nr_pages, int pass, + int prio, struct scan_control *sc) +{ + struct zone *zone; + unsigned long nr_to_scan, ret = 0; + + for_each_zone(zone) { + + if (!populated_zone(zone)) + continue; + + if (zone->all_unreclaimable && prio != DEF_PRIORITY) + continue; + + /* For pass = 0 we don't shrink the active list */ + if (pass > 0) { + zone->nr_scan_active += (zone->nr_active >> prio) + 1; + if (zone->nr_scan_active >= nr_pages || pass > 3) { + zone->nr_scan_active = 0; + nr_to_scan = min(nr_pages, zone->nr_active); + shrink_active_list(nr_to_scan, zone, sc); + } + } + + zone->nr_scan_inactive += (zone->nr_inactive >> prio) + 1; + if (zone->nr_scan_inactive >= nr_pages || pass > 3) { + zone->nr_scan_inactive = 0; + nr_to_scan = min(nr_pages, zone->nr_inactive); + ret += shrink_inactive_list(nr_to_scan, zone, sc); + if (ret >= nr_pages) + return ret; + } + } + + return ret; +} + +/* + * Try to free `nr_pages' of memory, system-wide, and return the number of + * freed pages. + * + * Rather than trying to age LRUs the aim is to preserve the overall + * LRU order by reclaiming preferentially + * inactive > active > active referenced > active mapped */ unsigned long shrink_all_memory(unsigned long nr_pages) { - pg_data_t *pgdat; - unsigned long nr_to_free = nr_pages; + unsigned long lru_pages, nr_slab; unsigned long ret = 0; - unsigned retry = 2; - struct reclaim_state reclaim_state = { - .reclaimed_slab = 0, + int pass; + struct reclaim_state reclaim_state; + struct zone *zone; + struct scan_control sc = { + .gfp_mask = GFP_KERNEL, + .may_swap = 0, + .swap_cluster_max = nr_pages, + .may_writepage = 1, + .swappiness = vm_swappiness, }; current->reclaim_state = &reclaim_state; -repeat: - for_each_online_pgdat(pgdat) { - unsigned long freed; - freed = balance_pgdat(pgdat, nr_to_free, 0); - ret += freed; - nr_to_free -= freed; - if ((long)nr_to_free <= 0) + lru_pages = 0; + for_each_zone(zone) + lru_pages += zone->nr_active + zone->nr_inactive; + + nr_slab = read_page_state(nr_slab); + /* If slab caches are huge, it's better to hit them first */ + while (nr_slab >= lru_pages) { + reclaim_state.reclaimed_slab = 0; + shrink_slab(nr_pages, sc.gfp_mask, lru_pages); + if (!reclaim_state.reclaimed_slab) break; + + ret += reclaim_state.reclaimed_slab; + if (ret >= nr_pages) + goto out; + + nr_slab -= reclaim_state.reclaimed_slab; } - if (retry-- && ret < nr_pages) { - blk_congestion_wait(WRITE, HZ/5); - goto repeat; + + /* + * We try to shrink LRUs in 5 passes: + * 0 = Reclaim from inactive_list only + * 1 = Reclaim from active list but don't reclaim mapped + * 2 = 2nd pass of type 1 + * 3 = Reclaim mapped (normal reclaim) + * 4 = 2nd pass of type 3 + */ + for (pass = 0; pass < 5; pass++) { + int prio; + + /* Needed for shrinking slab caches later on */ + if (!lru_pages) + for_each_zone(zone) { + lru_pages += zone->nr_active; + lru_pages += zone->nr_inactive; + } + + /* Force reclaiming mapped pages in the passes #3 and #4 */ + if (pass > 2) { + sc.may_swap = 1; + sc.swappiness = 100; + } + + for (prio = DEF_PRIORITY; prio >= 0; prio--) { + unsigned long nr_to_scan = nr_pages - ret; + + sc.nr_mapped = read_page_state(nr_mapped); + sc.nr_scanned = 0; + + ret += shrink_all_zones(nr_to_scan, prio, pass, &sc); + if (ret >= nr_pages) + goto out; + + reclaim_state.reclaimed_slab = 0; + shrink_slab(sc.nr_scanned, sc.gfp_mask, lru_pages); + ret += reclaim_state.reclaimed_slab; + if (ret >= nr_pages) + goto out; + + if (sc.nr_scanned && prio < DEF_PRIORITY - 2) + blk_congestion_wait(WRITE, HZ / 10); + } + + lru_pages = 0; } + + /* + * If ret = 0, we could not shrink LRUs, but there may be something + * in slab caches + */ + if (!ret) + do { + reclaim_state.reclaimed_slab = 0; + shrink_slab(nr_pages, sc.gfp_mask, lru_pages); + ret += reclaim_state.reclaimed_slab; + } while (ret < nr_pages && reclaim_state.reclaimed_slab > 0); + +out: current->reclaim_state = NULL; + return ret; } #endif @@ -1416,6 +1524,7 @@ static int __zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order) .swap_cluster_max = max_t(unsigned long, nr_pages, SWAP_CLUSTER_MAX), .gfp_mask = gfp_mask, + .swappiness = vm_swappiness, }; disable_swap_token(); -- cgit v1.2.3 From 762834e8bf46bf41ce9034d062a7c1f8563175f3 Mon Sep 17 00:00:00 2001 From: Yasunori Goto Date: Fri, 23 Jun 2006 02:03:19 -0700 Subject: [PATCH] Unify pxm_to_node() and node_to_pxm() Consolidate the various arch-specific implementations of pxm_to_node() and node_to_pxm() into a single generic version. Signed-off-by: Yasunori Goto Cc: "Luck, Tony" Cc: Andi Kleen Cc: Dave Hansen Cc: "Brown, Len" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/Kconfig | 6 ++++++ arch/i386/kernel/srat.c | 19 ++-------------- arch/ia64/hp/common/sba_iommu.c | 2 +- arch/ia64/kernel/acpi.c | 24 +++++++-------------- arch/ia64/pci/pci.c | 2 +- arch/ia64/sn/kernel/setup.c | 4 ++-- arch/x86_64/mm/srat.c | 33 +--------------------------- drivers/acpi/Kconfig | 2 +- drivers/acpi/numa.c | 48 +++++++++++++++++++++++++++++++++++++++++ include/acpi/acpi_numa.h | 23 ++++++++++++++++++++ include/asm-x86_64/numa.h | 1 - include/linux/acpi.h | 9 ++++++++ 12 files changed, 102 insertions(+), 71 deletions(-) create mode 100644 include/acpi/acpi_numa.h diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index 8dfa3054f10..15d23da2455 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig @@ -173,6 +173,12 @@ config ACPI_SRAT bool default y depends on NUMA && (X86_SUMMIT || X86_GENERICARCH) + select ACPI_NUMA + +config HAVE_ARCH_PARSE_SRAT + bool + default y + depends on ACPI_SRAT config X86_SUMMIT_NUMA bool diff --git a/arch/i386/kernel/srat.c b/arch/i386/kernel/srat.c index 52b3ed5d2cb..989c85255db 100644 --- a/arch/i386/kernel/srat.c +++ b/arch/i386/kernel/srat.c @@ -39,7 +39,6 @@ #define NODE_ARRAY_OFFSET(x) ((x) % 8) /* 8 bits/char */ #define BMAP_SET(bmap, bit) ((bmap)[NODE_ARRAY_INDEX(bit)] |= 1 << NODE_ARRAY_OFFSET(bit)) #define BMAP_TEST(bmap, bit) ((bmap)[NODE_ARRAY_INDEX(bit)] & (1 << NODE_ARRAY_OFFSET(bit))) -#define MAX_PXM_DOMAINS 256 /* 1 byte and no promises about values */ /* bitmap length; _PXM is at most 255 */ #define PXM_BITMAP_LEN (MAX_PXM_DOMAINS / 8) static u8 pxm_bitmap[PXM_BITMAP_LEN]; /* bitmap of proximity domains */ @@ -213,19 +212,11 @@ static __init void node_read_chunk(int nid, struct node_memory_chunk_s *memory_c node_end_pfn[nid] = memory_chunk->end_pfn; } -static u8 pxm_to_nid_map[MAX_PXM_DOMAINS];/* _PXM to logical node ID map */ - -int pxm_to_node(int pxm) -{ - return pxm_to_nid_map[pxm]; -} - /* Parse the ACPI Static Resource Affinity Table */ static int __init acpi20_parse_srat(struct acpi_table_srat *sratp) { u8 *start, *end, *p; int i, j, nid; - u8 nid_to_pxm_map[MAX_NUMNODES];/* logical node ID to _PXM map */ start = (u8 *)(&(sratp->reserved) + 1); /* skip header */ p = start; @@ -235,10 +226,6 @@ static int __init acpi20_parse_srat(struct acpi_table_srat *sratp) memset(node_memory_chunk, 0, sizeof(node_memory_chunk)); memset(zholes_size, 0, sizeof(zholes_size)); - /* -1 in these maps means not available */ - memset(pxm_to_nid_map, -1, sizeof(pxm_to_nid_map)); - memset(nid_to_pxm_map, -1, sizeof(nid_to_pxm_map)); - num_memory_chunks = 0; while (p < end) { switch (*p) { @@ -278,9 +265,7 @@ static int __init acpi20_parse_srat(struct acpi_table_srat *sratp) nodes_clear(node_online_map); for (i = 0; i < MAX_PXM_DOMAINS; i++) { if (BMAP_TEST(pxm_bitmap, i)) { - nid = num_online_nodes(); - pxm_to_nid_map[i] = nid; - nid_to_pxm_map[nid] = i; + int nid = acpi_map_pxm_to_node(i); node_set_online(nid); } } @@ -288,7 +273,7 @@ static int __init acpi20_parse_srat(struct acpi_table_srat *sratp) /* set cnode id in memory chunk structure */ for (i = 0; i < num_memory_chunks; i++) - node_memory_chunk[i].nid = pxm_to_nid_map[node_memory_chunk[i].pxm]; + node_memory_chunk[i].nid = pxm_to_node(node_memory_chunk[i].pxm); printk("pxm bitmap: "); for (i = 0; i < sizeof(pxm_bitmap); i++) { diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c index bdccd0b1eb6..3ce443e6c01 100644 --- a/arch/ia64/hp/common/sba_iommu.c +++ b/arch/ia64/hp/common/sba_iommu.c @@ -1958,7 +1958,7 @@ sba_map_ioc_to_node(struct ioc *ioc, acpi_handle handle) if (pxm < 0) return; - node = pxm_to_nid_map[pxm]; + node = pxm_to_node(pxm); if (node >= MAX_NUMNODES || !node_online(node)) return; diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index 58c93a30348..d1c52cf6788 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -415,9 +415,6 @@ static int __initdata srat_num_cpus; /* number of cpus */ static u32 __devinitdata pxm_flag[PXM_FLAG_LEN]; #define pxm_bit_set(bit) (set_bit(bit,(void *)pxm_flag)) #define pxm_bit_test(bit) (test_bit(bit,(void *)pxm_flag)) -/* maps to convert between proximity domain and logical node ID */ -int __devinitdata pxm_to_nid_map[MAX_PXM_DOMAINS]; -int __initdata nid_to_pxm_map[MAX_NUMNODES]; static struct acpi_table_slit __initdata *slit_table; static int get_processor_proximity_domain(struct acpi_table_processor_affinity *pa) @@ -533,22 +530,17 @@ void __init acpi_numa_arch_fixup(void) * MCD - This can probably be dropped now. No need for pxm ID to node ID * mapping with sparse node numbering iff MAX_PXM_DOMAINS <= MAX_NUMNODES. */ - /* calculate total number of nodes in system from PXM bitmap */ - memset(pxm_to_nid_map, -1, sizeof(pxm_to_nid_map)); - memset(nid_to_pxm_map, -1, sizeof(nid_to_pxm_map)); nodes_clear(node_online_map); for (i = 0; i < MAX_PXM_DOMAINS; i++) { if (pxm_bit_test(i)) { - int nid = num_online_nodes(); - pxm_to_nid_map[i] = nid; - nid_to_pxm_map[nid] = i; + int nid = acpi_map_pxm_to_node(i); node_set_online(nid); } } /* set logical node id in memory chunk structure */ for (i = 0; i < num_node_memblks; i++) - node_memblk[i].nid = pxm_to_nid_map[node_memblk[i].nid]; + node_memblk[i].nid = pxm_to_node(node_memblk[i].nid); /* assign memory bank numbers for each chunk on each node */ for_each_online_node(i) { @@ -562,7 +554,7 @@ void __init acpi_numa_arch_fixup(void) /* set logical node id in cpu structure */ for (i = 0; i < srat_num_cpus; i++) - node_cpuid[i].nid = pxm_to_nid_map[node_cpuid[i].nid]; + node_cpuid[i].nid = pxm_to_node(node_cpuid[i].nid); printk(KERN_INFO "Number of logical nodes in system = %d\n", num_online_nodes()); @@ -575,11 +567,11 @@ void __init acpi_numa_arch_fixup(void) for (i = 0; i < slit_table->localities; i++) { if (!pxm_bit_test(i)) continue; - node_from = pxm_to_nid_map[i]; + node_from = pxm_to_node(i); for (j = 0; j < slit_table->localities; j++) { if (!pxm_bit_test(j)) continue; - node_to = pxm_to_nid_map[j]; + node_to = pxm_to_node(j); node_distance(node_from, node_to) = slit_table->entry[i * slit_table->localities + j]; } @@ -785,9 +777,9 @@ int acpi_map_cpu2node(acpi_handle handle, int cpu, long physid) /* * Assuming that the container driver would have set the proximity - * domain and would have initialized pxm_to_nid_map[pxm_id] && pxm_flag + * domain and would have initialized pxm_to_node(pxm_id) && pxm_flag */ - node_cpuid[cpu].nid = (pxm_id < 0) ? 0 : pxm_to_nid_map[pxm_id]; + node_cpuid[cpu].nid = (pxm_id < 0) ? 0 : pxm_to_node(pxm_id); node_cpuid[cpu].phys_id = physid; #endif @@ -966,7 +958,7 @@ acpi_map_iosapic(acpi_handle handle, u32 depth, void *context, void **ret) if (pxm < 0) return AE_OK; - node = pxm_to_nid_map[pxm]; + node = pxm_to_node(pxm); if (node >= MAX_NUMNODES || !node_online(node) || cpus_empty(node_to_cpumask(node))) diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index ab829a22f8a..cf7751b99d1 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -352,7 +352,7 @@ pci_acpi_scan_root(struct acpi_device *device, int domain, int bus) pxm = acpi_get_pxm(controller->acpi_handle); #ifdef CONFIG_NUMA if (pxm >= 0) - controller->node = pxm_to_nid_map[pxm]; + controller->node = pxm_to_node(pxm); #endif acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_window, diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c index 30988dfbddf..93577abae36 100644 --- a/arch/ia64/sn/kernel/setup.c +++ b/arch/ia64/sn/kernel/setup.c @@ -139,7 +139,7 @@ static int __init pxm_to_nasid(int pxm) int i; int nid; - nid = pxm_to_nid_map[pxm]; + nid = pxm_to_node(pxm); for (i = 0; i < num_node_memblks; i++) { if (node_memblk[i].nid == nid) { return NASID_GET(node_memblk[i].start_paddr); @@ -704,7 +704,7 @@ void __init build_cnode_tables(void) * cnode == node for all C & M bricks. */ for_each_online_node(node) { - nasid = pxm_to_nasid(nid_to_pxm_map[node]); + nasid = pxm_to_nasid(node_to_pxm(node)); sn_cnodeid_to_nasid[node] = nasid; physical_node_map[nasid] = node; } diff --git a/arch/x86_64/mm/srat.c b/arch/x86_64/mm/srat.c index 474df22c6ed..502fce65e96 100644 --- a/arch/x86_64/mm/srat.c +++ b/arch/x86_64/mm/srat.c @@ -30,7 +30,6 @@ static struct acpi_table_slit *acpi_slit; static nodemask_t nodes_parsed __initdata; -static nodemask_t nodes_found __initdata; static struct bootnode nodes[MAX_NUMNODES] __initdata; static struct bootnode nodes_add[MAX_NUMNODES] __initdata; static int found_add_area __initdata; @@ -38,33 +37,14 @@ int hotadd_percent __initdata = 0; #ifndef RESERVE_HOTADD #define hotadd_percent 0 /* Ignore all settings */ #endif -static u8 pxm2node[256] = { [0 ... 255] = 0xff }; /* Too small nodes confuse the VM badly. Usually they result from BIOS bugs. */ #define NODE_MIN_SIZE (4*1024*1024) -static int node_to_pxm(int n); - -int pxm_to_node(int pxm) -{ - if ((unsigned)pxm >= 256) - return -1; - /* Extend 0xff to (int)-1 */ - return (signed char)pxm2node[pxm]; -} - static __init int setup_node(int pxm) { - unsigned node = pxm2node[pxm]; - if (node == 0xff) { - if (nodes_weight(nodes_found) >= MAX_NUMNODES) - return -1; - node = first_unset_node(nodes_found); - node_set(node, nodes_found); - pxm2node[pxm] = node; - } - return pxm2node[pxm]; + return acpi_map_pxm_to_node(pxm); } static __init int conflicting_nodes(unsigned long start, unsigned long end) @@ -440,17 +420,6 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end) return 0; } -static int node_to_pxm(int n) -{ - int i; - if (pxm2node[n] == n) - return n; - for (i = 0; i < 256; i++) - if (pxm2node[i] == n) - return i; - return 0; -} - void __init srat_reserve_add_area(int nodeid) { if (found_add_area && nodes_add[nodeid].end) { diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index c24652d31bf..230c5385223 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -162,7 +162,7 @@ config ACPI_THERMAL config ACPI_NUMA bool "NUMA support" depends on NUMA - depends on (IA64 || X86_64) + depends on (X86 || IA64) default y if IA64_GENERIC || IA64_SGI_SN2 config ACPI_ASUS diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index 64b98e82feb..e2c1a16078c 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c @@ -36,12 +36,60 @@ #define _COMPONENT ACPI_NUMA ACPI_MODULE_NAME("numa") +static nodemask_t nodes_found_map = NODE_MASK_NONE; +#define PXM_INVAL -1 +#define NID_INVAL -1 + +/* maps to convert between proximity domain and logical node ID */ +int __cpuinitdata pxm_to_node_map[MAX_PXM_DOMAINS] + = { [0 ... MAX_PXM_DOMAINS - 1] = NID_INVAL }; +int __cpuinitdata node_to_pxm_map[MAX_NUMNODES] + = { [0 ... MAX_NUMNODES - 1] = PXM_INVAL }; + extern int __init acpi_table_parse_madt_family(enum acpi_table_id id, unsigned long madt_size, int entry_id, acpi_madt_entry_handler handler, unsigned int max_entries); +int __cpuinit pxm_to_node(int pxm) +{ + if (pxm < 0) + return NID_INVAL; + return pxm_to_node_map[pxm]; +} + +int __cpuinit node_to_pxm(int node) +{ + if (node < 0) + return PXM_INVAL; + return node_to_pxm_map[node]; +} + +int __cpuinit acpi_map_pxm_to_node(int pxm) +{ + int node = pxm_to_node_map[pxm]; + + if (node < 0){ + if (nodes_weight(nodes_found_map) >= MAX_NUMNODES) + return NID_INVAL; + node = first_unset_node(nodes_found_map); + pxm_to_node_map[pxm] = node; + node_to_pxm_map[node] = pxm; + node_set(node, nodes_found_map); + } + + return node; +} + +void __cpuinit acpi_unmap_pxm_to_node(int node) +{ + int pxm = node_to_pxm_map[node]; + pxm_to_node_map[pxm] = NID_INVAL; + node_to_pxm_map[node] = PXM_INVAL; + node_clear(node, nodes_found_map); +} + void __init acpi_table_print_srat_entry(acpi_table_entry_header * header) { diff --git a/include/acpi/acpi_numa.h b/include/acpi/acpi_numa.h new file mode 100644 index 00000000000..1049f2a0a6d --- /dev/null +++ b/include/acpi/acpi_numa.h @@ -0,0 +1,23 @@ +#ifndef __ACPI_NUMA_H +#define __ACPI_NUMA_H + +#ifdef CONFIG_ACPI_NUMA +#include + +/* Proximity bitmap length */ +#if MAX_NUMNODES > 256 +#define MAX_PXM_DOMAINS MAX_NUMNODES +#else +#define MAX_PXM_DOMAINS (256) /* Old pxm spec is defined 8 bit */ +#endif + +extern int __cpuinitdata pxm_to_node_map[MAX_PXM_DOMAINS]; +extern int __cpuinitdata node_to_pxm_map[MAX_NUMNODES]; + +extern int __cpuinit pxm_to_node(int); +extern int __cpuinit node_to_pxm(int); +extern int __cpuinit acpi_map_pxm_to_node(int); +extern void __cpuinit acpi_unmap_pxm_to_node(int); + +#endif /* CONFIG_ACPI_NUMA */ +#endif /* __ACP_NUMA_H */ diff --git a/include/asm-x86_64/numa.h b/include/asm-x86_64/numa.h index 1cc92fe0250..933ff11ece1 100644 --- a/include/asm-x86_64/numa.h +++ b/include/asm-x86_64/numa.h @@ -8,7 +8,6 @@ struct bootnode { }; extern int compute_hash_shift(struct bootnode *nodes, int numnodes); -extern int pxm_to_node(int nid); #define ZONE_ALIGN (1UL << (MAX_ORDER+PAGE_SHIFT)) diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 1cf0b91d05b..90d6df1551e 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -37,6 +37,7 @@ #include #include #include +#include #include @@ -407,10 +408,18 @@ void acpi_table_print_madt_entry (acpi_table_entry_header *madt); void acpi_table_print_srat_entry (acpi_table_entry_header *srat); /* the following four functions are architecture-dependent */ +#ifdef CONFIG_HAVE_ARCH_PARSE_SRAT +#define NR_NODE_MEMBLKS MAX_NUMNODES +#define acpi_numa_slit_init(slit) do {} while (0) +#define acpi_numa_processor_affinity_init(pa) do {} while (0) +#define acpi_numa_memory_affinity_init(ma) do {} while (0) +#define acpi_numa_arch_fixup() do {} while (0) +#else void acpi_numa_slit_init (struct acpi_table_slit *slit); void acpi_numa_processor_affinity_init (struct acpi_table_processor_affinity *pa); void acpi_numa_memory_affinity_init (struct acpi_table_memory_affinity *ma); void acpi_numa_arch_fixup(void); +#endif #ifdef CONFIG_ACPI_HOTPLUG_CPU /* Arch dependent functions for cpu hotplug support */ -- cgit v1.2.3 From 833423143c3a7c6545e409d65febd0d92deb351b Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Fri, 23 Jun 2006 02:03:20 -0700 Subject: [PATCH] mm: introduce remap_vmalloc_range() Add remap_vmalloc_range, vmalloc_user, and vmalloc_32_user so that drivers can have a nice interface for remapping vmalloc memory. Signed-off-by: Nick Piggin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/vmalloc.h | 8 ++++ mm/vmalloc.c | 122 +++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 128 insertions(+), 2 deletions(-) diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h index 1d5577b2b75..f6024ab4eff 100644 --- a/include/linux/vmalloc.h +++ b/include/linux/vmalloc.h @@ -4,10 +4,13 @@ #include #include /* pgprot_t */ +struct vm_area_struct; + /* bits in vm_struct->flags */ #define VM_IOREMAP 0x00000001 /* ioremap() and friends */ #define VM_ALLOC 0x00000002 /* vmalloc() */ #define VM_MAP 0x00000004 /* vmap()ed pages */ +#define VM_USERMAP 0x00000008 /* suitable for remap_vmalloc_range */ /* bits [20..32] reserved for arch specific ioremap internals */ /* @@ -32,9 +35,11 @@ struct vm_struct { * Highlevel APIs for driver use */ extern void *vmalloc(unsigned long size); +extern void *vmalloc_user(unsigned long size); extern void *vmalloc_node(unsigned long size, int node); extern void *vmalloc_exec(unsigned long size); extern void *vmalloc_32(unsigned long size); +extern void *vmalloc_32_user(unsigned long size); extern void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot); extern void *__vmalloc_area(struct vm_struct *area, gfp_t gfp_mask, pgprot_t prot); @@ -45,6 +50,9 @@ extern void vfree(void *addr); extern void *vmap(struct page **pages, unsigned int count, unsigned long flags, pgprot_t prot); extern void vunmap(void *addr); + +extern int remap_vmalloc_range(struct vm_area_struct *vma, void *addr, + unsigned long pgoff); /* * Lowlevel-APIs (not for driver use!) diff --git a/mm/vmalloc.c b/mm/vmalloc.c index c0504f1e34e..35f8553f893 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -256,6 +256,19 @@ struct vm_struct *get_vm_area_node(unsigned long size, unsigned long flags, int return __get_vm_area_node(size, flags, VMALLOC_START, VMALLOC_END, node); } +/* Caller must hold vmlist_lock */ +static struct vm_struct *__find_vm_area(void *addr) +{ + struct vm_struct *tmp; + + for (tmp = vmlist; tmp != NULL; tmp = tmp->next) { + if (tmp->addr == addr) + break; + } + + return tmp; +} + /* Caller must hold vmlist_lock */ struct vm_struct *__remove_vm_area(void *addr) { @@ -498,10 +511,32 @@ EXPORT_SYMBOL(__vmalloc); */ void *vmalloc(unsigned long size) { - return __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL); + return __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL); } EXPORT_SYMBOL(vmalloc); +/** + * vmalloc_user - allocate virtually contiguous memory which has + * been zeroed so it can be mapped to userspace without + * leaking data. + * + * @size: allocation size + */ +void *vmalloc_user(unsigned long size) +{ + struct vm_struct *area; + void *ret; + + ret = __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO, PAGE_KERNEL); + write_lock(&vmlist_lock); + area = __find_vm_area(ret); + area->flags |= VM_USERMAP; + write_unlock(&vmlist_lock); + + return ret; +} +EXPORT_SYMBOL(vmalloc_user); + /** * vmalloc_node - allocate memory on a specific node * @@ -516,7 +551,7 @@ EXPORT_SYMBOL(vmalloc); */ void *vmalloc_node(unsigned long size, int node) { - return __vmalloc_node(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL, node); + return __vmalloc_node(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL, node); } EXPORT_SYMBOL(vmalloc_node); @@ -556,6 +591,28 @@ void *vmalloc_32(unsigned long size) } EXPORT_SYMBOL(vmalloc_32); +/** + * vmalloc_32_user - allocate virtually contiguous memory (32bit + * addressable) which is zeroed so it can be + * mapped to userspace without leaking data. + * + * @size: allocation size + */ +void *vmalloc_32_user(unsigned long size) +{ + struct vm_struct *area; + void *ret; + + ret = __vmalloc(size, GFP_KERNEL | __GFP_ZERO, PAGE_KERNEL); + write_lock(&vmlist_lock); + area = __find_vm_area(ret); + area->flags |= VM_USERMAP; + write_unlock(&vmlist_lock); + + return ret; +} +EXPORT_SYMBOL(vmalloc_32_user); + long vread(char *buf, char *addr, unsigned long count) { struct vm_struct *tmp; @@ -630,3 +687,64 @@ finished: read_unlock(&vmlist_lock); return buf - buf_start; } + +/** + * remap_vmalloc_range - map vmalloc pages to userspace + * + * @vma: vma to cover (map full range of vma) + * @addr: vmalloc memory + * @pgoff: number of pages into addr before first page to map + * @returns: 0 for success, -Exxx on failure + * + * This function checks that addr is a valid vmalloc'ed area, and + * that it is big enough to cover the vma. Will return failure if + * that criteria isn't met. + * + * Similar to remap_pfn_range (see mm/memory.c) + */ +int remap_vmalloc_range(struct vm_area_struct *vma, void *addr, + unsigned long pgoff) +{ + struct vm_struct *area; + unsigned long uaddr = vma->vm_start; + unsigned long usize = vma->vm_end - vma->vm_start; + int ret; + + if ((PAGE_SIZE-1) & (unsigned long)addr) + return -EINVAL; + + read_lock(&vmlist_lock); + area = __find_vm_area(addr); + if (!area) + goto out_einval_locked; + + if (!(area->flags & VM_USERMAP)) + goto out_einval_locked; + + if (usize + (pgoff << PAGE_SHIFT) > area->size - PAGE_SIZE) + goto out_einval_locked; + read_unlock(&vmlist_lock); + + addr += pgoff << PAGE_SHIFT; + do { + struct page *page = vmalloc_to_page(addr); + ret = vm_insert_page(vma, uaddr, page); + if (ret) + return ret; + + uaddr += PAGE_SIZE; + addr += PAGE_SIZE; + usize -= PAGE_SIZE; + } while (usize > 0); + + /* Prevent "things" like memory migration? VM_flags need a cleanup... */ + vma->vm_flags |= VM_RESERVED; + + return ret; + +out_einval_locked: + read_unlock(&vmlist_lock); + return -EINVAL; +} +EXPORT_SYMBOL(remap_vmalloc_range); + -- cgit v1.2.3 From 929f97276bcf7f4a95272ed08a85339b98ba210d Mon Sep 17 00:00:00 2001 From: Dean Nelson Date: Fri, 23 Jun 2006 02:03:21 -0700 Subject: [PATCH] change gen_pool allocator to not touch managed memory Modify the gen_pool allocator (lib/genalloc.c) to utilize a bitmap scheme instead of the buddy scheme. The purpose of this change is to eliminate the touching of the actual memory being allocated. Since the change modifies the interface, a change to the uncached allocator (arch/ia64/kernel/uncached.c) is also required. Both Andrey Volkov and Jes Sorenson have expressed a desire that the gen_pool allocator not write to the memory being managed. See the following: http://marc.theaimsgroup.com/?l=linux-kernel&m=113518602713125&w=2 http://marc.theaimsgroup.com/?l=linux-kernel&m=113533568827916&w=2 Signed-off-by: Dean Nelson Cc: Andrey Volkov Acked-by: Jes Sorensen Cc: "Luck, Tony" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ia64/kernel/uncached.c | 200 +++++++++++++++--------------- arch/ia64/sn/kernel/sn2/cache.c | 15 ++- include/linux/genalloc.h | 35 +++--- lib/genalloc.c | 263 ++++++++++++++++++---------------------- 4 files changed, 252 insertions(+), 261 deletions(-) diff --git a/arch/ia64/kernel/uncached.c b/arch/ia64/kernel/uncached.c index fcd2bad0286..5f03b9e524d 100644 --- a/arch/ia64/kernel/uncached.c +++ b/arch/ia64/kernel/uncached.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001-2005 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2001-2006 Silicon Graphics, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License @@ -29,15 +29,8 @@ #include #include -#define DEBUG 0 -#if DEBUG -#define dprintk printk -#else -#define dprintk(x...) do { } while (0) -#endif - -void __init efi_memmap_walk_uc (efi_freemem_callback_t callback); +extern void __init efi_memmap_walk_uc(efi_freemem_callback_t, void *); #define MAX_UNCACHED_GRANULES 5 static int allocated_granules; @@ -60,6 +53,7 @@ static void uncached_ipi_visibility(void *data) static void uncached_ipi_mc_drain(void *data) { int status; + status = ia64_pal_mc_drain(); if (status) printk(KERN_WARNING "ia64_pal_mc_drain() failed with %i on " @@ -67,30 +61,35 @@ static void uncached_ipi_mc_drain(void *data) } -static unsigned long -uncached_get_new_chunk(struct gen_pool *poolp) +/* + * Add a new chunk of uncached memory pages to the specified pool. + * + * @pool: pool to add new chunk of uncached memory to + * @nid: node id of node to allocate memory from, or -1 + * + * This is accomplished by first allocating a granule of cached memory pages + * and then converting them to uncached memory pages. + */ +static int uncached_add_chunk(struct gen_pool *pool, int nid) { struct page *page; - void *tmp; int status, i; - unsigned long addr, node; + unsigned long c_addr, uc_addr; if (allocated_granules >= MAX_UNCACHED_GRANULES) - return 0; + return -1; + + /* attempt to allocate a granule's worth of cached memory pages */ - node = poolp->private; - page = alloc_pages_node(node, GFP_KERNEL | __GFP_ZERO, + page = alloc_pages_node(nid, GFP_KERNEL | __GFP_ZERO, IA64_GRANULE_SHIFT-PAGE_SHIFT); + if (!page) + return -1; - dprintk(KERN_INFO "get_new_chunk page %p, addr %lx\n", - page, (unsigned long)(page-vmem_map) << PAGE_SHIFT); + /* convert the memory pages from cached to uncached */ - /* - * Do magic if no mem on local node! XXX - */ - if (!page) - return 0; - tmp = page_address(page); + c_addr = (unsigned long)page_address(page); + uc_addr = c_addr - PAGE_OFFSET + __IA64_UNCACHED_OFFSET; /* * There's a small race here where it's possible for someone to @@ -100,76 +99,90 @@ uncached_get_new_chunk(struct gen_pool *poolp) for (i = 0; i < (IA64_GRANULE_SIZE / PAGE_SIZE); i++) SetPageUncached(&page[i]); - flush_tlb_kernel_range(tmp, tmp + IA64_GRANULE_SIZE); + flush_tlb_kernel_range(uc_addr, uc_adddr + IA64_GRANULE_SIZE); status = ia64_pal_prefetch_visibility(PAL_VISIBILITY_PHYSICAL); - - dprintk(KERN_INFO "pal_prefetch_visibility() returns %i on cpu %i\n", - status, raw_smp_processor_id()); - if (!status) { status = smp_call_function(uncached_ipi_visibility, NULL, 0, 1); if (status) - printk(KERN_WARNING "smp_call_function failed for " - "uncached_ipi_visibility! (%i)\n", status); + goto failed; } + preempt_disable(); + if (ia64_platform_is("sn2")) - sn_flush_all_caches((unsigned long)tmp, IA64_GRANULE_SIZE); + sn_flush_all_caches(uc_addr, IA64_GRANULE_SIZE); else - flush_icache_range((unsigned long)tmp, - (unsigned long)tmp+IA64_GRANULE_SIZE); + flush_icache_range(uc_addr, uc_addr + IA64_GRANULE_SIZE); + + /* flush the just introduced uncached translation from the TLB */ + local_flush_tlb_all(); + + preempt_enable(); ia64_pal_mc_drain(); status = smp_call_function(uncached_ipi_mc_drain, NULL, 0, 1); if (status) - printk(KERN_WARNING "smp_call_function failed for " - "uncached_ipi_mc_drain! (%i)\n", status); + goto failed; - addr = (unsigned long)tmp - PAGE_OFFSET + __IA64_UNCACHED_OFFSET; + /* + * The chunk of memory pages has been converted to uncached so now we + * can add it to the pool. + */ + status = gen_pool_add(pool, uc_addr, IA64_GRANULE_SIZE, nid); + if (status) + goto failed; allocated_granules++; - return addr; + return 0; + + /* failed to convert or add the chunk so give it back to the kernel */ +failed: + for (i = 0; i < (IA64_GRANULE_SIZE / PAGE_SIZE); i++) + ClearPageUncached(&page[i]); + + free_pages(c_addr, IA64_GRANULE_SHIFT-PAGE_SHIFT); + return -1; } /* * uncached_alloc_page * + * @starting_nid: node id of node to start with, or -1 + * * Allocate 1 uncached page. Allocates on the requested node. If no * uncached pages are available on the requested node, roundrobin starting - * with higher nodes. + * with the next higher node. */ -unsigned long -uncached_alloc_page(int nid) +unsigned long uncached_alloc_page(int starting_nid) { - unsigned long maddr; + unsigned long uc_addr; + struct gen_pool *pool; + int nid; - maddr = gen_pool_alloc(uncached_pool[nid], PAGE_SIZE); + if (unlikely(starting_nid >= MAX_NUMNODES)) + return 0; - dprintk(KERN_DEBUG "uncached_alloc_page returns %lx on node %i\n", - maddr, nid); + if (starting_nid < 0) + starting_nid = numa_node_id(); + nid = starting_nid; - /* - * If no memory is availble on our local node, try the - * remaining nodes in the system. - */ - if (!maddr) { - int i; - - for (i = MAX_NUMNODES - 1; i >= 0; i--) { - if (i == nid || !node_online(i)) - continue; - maddr = gen_pool_alloc(uncached_pool[i], PAGE_SIZE); - dprintk(KERN_DEBUG "uncached_alloc_page alternate search " - "returns %lx on node %i\n", maddr, i); - if (maddr) { - break; - } - } - } + do { + if (!node_online(nid)) + continue; + pool = uncached_pool[nid]; + if (pool == NULL) + continue; + do { + uc_addr = gen_pool_alloc(pool, PAGE_SIZE); + if (uc_addr != 0) + return uc_addr; + } while (uncached_add_chunk(pool, nid) == 0); + + } while ((nid = (nid + 1) % MAX_NUMNODES) != starting_nid); - return maddr; + return 0; } EXPORT_SYMBOL(uncached_alloc_page); @@ -177,21 +190,22 @@ EXPORT_SYMBOL(uncached_alloc_page); /* * uncached_free_page * + * @uc_addr: uncached address of page to free + * * Free a single uncached page. */ -void -uncached_free_page(unsigned long maddr) +void uncached_free_page(unsigned long uc_addr) { - int node; - - node = paddr_to_nid(maddr - __IA64_UNCACHED_OFFSET); + int nid = paddr_to_nid(uc_addr - __IA64_UNCACHED_OFFSET); + struct gen_pool *pool = uncached_pool[nid]; - dprintk(KERN_DEBUG "uncached_free_page(%lx) on node %i\n", maddr, node); + if (unlikely(pool == NULL)) + return; - if ((maddr & (0XFUL << 60)) != __IA64_UNCACHED_OFFSET) - panic("uncached_free_page invalid address %lx\n", maddr); + if ((uc_addr & (0XFUL << 60)) != __IA64_UNCACHED_OFFSET) + panic("uncached_free_page invalid address %lx\n", uc_addr); - gen_pool_free(uncached_pool[node], maddr, PAGE_SIZE); + gen_pool_free(pool, uc_addr, PAGE_SIZE); } EXPORT_SYMBOL(uncached_free_page); @@ -199,43 +213,39 @@ EXPORT_SYMBOL(uncached_free_page); /* * uncached_build_memmap, * + * @uc_start: uncached starting address of a chunk of uncached memory + * @uc_end: uncached ending address of a chunk of uncached memory + * @arg: ignored, (NULL argument passed in on call to efi_memmap_walk_uc()) + * * Called at boot time to build a map of pages that can be used for * memory special operations. */ -static int __init -uncached_build_memmap(unsigned long start, unsigned long end, void *arg) +static int __init uncached_build_memmap(unsigned long uc_start, + unsigned long uc_end, void *arg) { - long length = end - start; - int node; - - dprintk(KERN_ERR "uncached_build_memmap(%lx %lx)\n", start, end); + int nid = paddr_to_nid(uc_start - __IA64_UNCACHED_OFFSET); + struct gen_pool *pool = uncached_pool[nid]; + size_t size = uc_end - uc_start; touch_softlockup_watchdog(); - memset((char *)start, 0, length); - node = paddr_to_nid(start - __IA64_UNCACHED_OFFSET); - - for (; start < end ; start += PAGE_SIZE) { - dprintk(KERN_INFO "sticking %lx into the pool!\n", start); - gen_pool_free(uncached_pool[node], start, PAGE_SIZE); + if (pool != NULL) { + memset((char *)uc_start, 0, size); + (void) gen_pool_add(pool, uc_start, size, nid); } - return 0; } -static int __init uncached_init(void) { - int i; +static int __init uncached_init(void) +{ + int nid; - for (i = 0; i < MAX_NUMNODES; i++) { - if (!node_online(i)) - continue; - uncached_pool[i] = gen_pool_create(0, IA64_GRANULE_SHIFT, - &uncached_get_new_chunk, i); + for_each_online_node(nid) { + uncached_pool[nid] = gen_pool_create(PAGE_SHIFT, nid); } - efi_memmap_walk_uc(uncached_build_memmap); - + efi_memmap_walk_uc(uncached_build_memmap, NULL); return 0; } diff --git a/arch/ia64/sn/kernel/sn2/cache.c b/arch/ia64/sn/kernel/sn2/cache.c index bc3cfa17cd0..2862cb33026 100644 --- a/arch/ia64/sn/kernel/sn2/cache.c +++ b/arch/ia64/sn/kernel/sn2/cache.c @@ -3,11 +3,12 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2001-2003 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2001-2003, 2006 Silicon Graphics, Inc. All rights reserved. * */ #include #include +#include /** * sn_flush_all_caches - flush a range of address from all caches (incl. L4) @@ -17,18 +18,24 @@ * Flush a range of addresses from all caches including L4. * All addresses fully or partially contained within * @flush_addr to @flush_addr + @bytes are flushed - * from the all caches. + * from all caches. */ void sn_flush_all_caches(long flush_addr, long bytes) { - flush_icache_range(flush_addr, flush_addr+bytes); + unsigned long addr = flush_addr; + + /* SHub1 requires a cached address */ + if (is_shub1() && (addr & RGN_BITS) == RGN_BASE(RGN_UNCACHED)) + addr = (addr - RGN_BASE(RGN_UNCACHED)) + RGN_BASE(RGN_KERNEL); + + flush_icache_range(addr, addr + bytes); /* * The last call may have returned before the caches * were actually flushed, so we call it again to make * sure. */ - flush_icache_range(flush_addr, flush_addr+bytes); + flush_icache_range(addr, addr + bytes); mb(); } EXPORT_SYMBOL(sn_flush_all_caches); diff --git a/include/linux/genalloc.h b/include/linux/genalloc.h index 7fd0576a445..690c42803d2 100644 --- a/include/linux/genalloc.h +++ b/include/linux/genalloc.h @@ -4,37 +4,32 @@ * Uses for this includes on-device special memory, uncached memory * etc. * - * This code is based on the buddy allocator found in the sym53c8xx_2 - * driver, adapted for general purpose use. - * * This source code is licensed under the GNU General Public License, * Version 2. See the file COPYING for more details. */ -#include -#define ALLOC_MIN_SHIFT 5 /* 32 bytes minimum */ /* - * Link between free memory chunks of a given size. + * General purpose special memory pool descriptor. */ -struct gen_pool_link { - struct gen_pool_link *next; +struct gen_pool { + rwlock_t lock; + struct list_head chunks; /* list of chunks in this pool */ + int min_alloc_order; /* minimum allocation order */ }; /* - * Memory pool descriptor. + * General purpose special memory pool chunk descriptor. */ -struct gen_pool { +struct gen_pool_chunk { spinlock_t lock; - unsigned long (*get_new_chunk)(struct gen_pool *); - struct gen_pool *next; - struct gen_pool_link *h; - unsigned long private; - int max_chunk_shift; + struct list_head next_chunk; /* next chunk in pool */ + unsigned long start_addr; /* starting address of memory chunk */ + unsigned long end_addr; /* ending address of memory chunk */ + unsigned long bits[0]; /* bitmap for allocating memory chunk */ }; -unsigned long gen_pool_alloc(struct gen_pool *poolp, int size); -void gen_pool_free(struct gen_pool *mp, unsigned long ptr, int size); -struct gen_pool *gen_pool_create(int nr_chunks, int max_chunk_shift, - unsigned long (*fp)(struct gen_pool *), - unsigned long data); +extern struct gen_pool *gen_pool_create(int, int); +extern int gen_pool_add(struct gen_pool *, unsigned long, size_t, int); +extern unsigned long gen_pool_alloc(struct gen_pool *, size_t); +extern void gen_pool_free(struct gen_pool *, unsigned long, size_t); diff --git a/lib/genalloc.c b/lib/genalloc.c index 9ce0a6a3b85..71338b48e88 100644 --- a/lib/genalloc.c +++ b/lib/genalloc.c @@ -4,10 +4,6 @@ * Uses for this includes on-device special memory, uncached memory * etc. * - * This code is based on the buddy allocator found in the sym53c8xx_2 - * driver Copyright (C) 1999-2001 Gerard Roudier , - * and adapted for general purpose use. - * * Copyright 2005 (C) Jes Sorensen * * This source code is licensed under the GNU General Public License, @@ -15,172 +11,155 @@ */ #include -#include -#include -#include -#include -#include -#include -#include #include -#include - -struct gen_pool *gen_pool_create(int nr_chunks, int max_chunk_shift, - unsigned long (*fp)(struct gen_pool *), - unsigned long data) +/* + * Create a new special memory pool. + * + * @min_alloc_order: log base 2 of number of bytes each bitmap bit represents + * @nid: node id of the node the pool structure should be allocated on, or -1 + */ +struct gen_pool *gen_pool_create(int min_alloc_order, int nid) { - struct gen_pool *poolp; - unsigned long tmp; - int i; - - /* - * This is really an arbitrary limit, +10 is enough for - * IA64_GRANULE_SHIFT, aka 16MB. If anyone needs a large limit - * this can be increased without problems. - */ - if ((max_chunk_shift > (PAGE_SHIFT + 10)) || - ((max_chunk_shift < ALLOC_MIN_SHIFT) && max_chunk_shift)) - return NULL; - - if (!max_chunk_shift) - max_chunk_shift = PAGE_SHIFT; - - poolp = kmalloc(sizeof(struct gen_pool), GFP_KERNEL); - if (!poolp) - return NULL; - memset(poolp, 0, sizeof(struct gen_pool)); - poolp->h = kmalloc(sizeof(struct gen_pool_link) * - (max_chunk_shift - ALLOC_MIN_SHIFT + 1), - GFP_KERNEL); - if (!poolp->h) { - printk(KERN_WARNING "gen_pool_alloc() failed to allocate\n"); - kfree(poolp); - return NULL; - } - memset(poolp->h, 0, sizeof(struct gen_pool_link) * - (max_chunk_shift - ALLOC_MIN_SHIFT + 1)); - - spin_lock_init(&poolp->lock); - poolp->get_new_chunk = fp; - poolp->max_chunk_shift = max_chunk_shift; - poolp->private = data; - - for (i = 0; i < nr_chunks; i++) { - tmp = poolp->get_new_chunk(poolp); - printk(KERN_INFO "allocated %lx\n", tmp); - if (!tmp) - break; - gen_pool_free(poolp, tmp, (1 << poolp->max_chunk_shift)); - } + struct gen_pool *pool; - return poolp; + pool = kmalloc_node(sizeof(struct gen_pool), GFP_KERNEL, nid); + if (pool != NULL) { + rwlock_init(&pool->lock); + INIT_LIST_HEAD(&pool->chunks); + pool->min_alloc_order = min_alloc_order; + } + return pool; } EXPORT_SYMBOL(gen_pool_create); /* - * Simple power of two buddy-like generic allocator. - * Provides naturally aligned memory chunks. + * Add a new chunk of memory to the specified pool. + * + * @pool: pool to add new memory chunk to + * @addr: starting address of memory chunk to add to pool + * @size: size in bytes of the memory chunk to add to pool + * @nid: node id of the node the chunk structure and bitmap should be + * allocated on, or -1 */ -unsigned long gen_pool_alloc(struct gen_pool *poolp, int size) +int gen_pool_add(struct gen_pool *pool, unsigned long addr, size_t size, + int nid) { - int j, i, s, max_chunk_size; - unsigned long a, flags; - struct gen_pool_link *h = poolp->h; + struct gen_pool_chunk *chunk; + int nbits = size >> pool->min_alloc_order; + int nbytes = sizeof(struct gen_pool_chunk) + + (nbits + BITS_PER_BYTE - 1) / BITS_PER_BYTE; - max_chunk_size = 1 << poolp->max_chunk_shift; + chunk = kmalloc_node(nbytes, GFP_KERNEL, nid); + if (unlikely(chunk == NULL)) + return -1; - if (size > max_chunk_size) - return 0; + memset(chunk, 0, nbytes); + spin_lock_init(&chunk->lock); + chunk->start_addr = addr; + chunk->end_addr = addr + size; - size = max(size, 1 << ALLOC_MIN_SHIFT); - i = fls(size - 1); - s = 1 << i; - j = i -= ALLOC_MIN_SHIFT; - - spin_lock_irqsave(&poolp->lock, flags); - while (!h[j].next) { - if (s == max_chunk_size) { - struct gen_pool_link *ptr; - spin_unlock_irqrestore(&poolp->lock, flags); - ptr = (struct gen_pool_link *)poolp->get_new_chunk(poolp); - spin_lock_irqsave(&poolp->lock, flags); - h[j].next = ptr; - if (h[j].next) - h[j].next->next = NULL; - break; - } - j++; - s <<= 1; - } - a = (unsigned long) h[j].next; - if (a) { - h[j].next = h[j].next->next; - /* - * This should be split into a seperate function doing - * the chunk split in order to support custom - * handling memory not physically accessible by host - */ - while (j > i) { - j -= 1; - s >>= 1; - h[j].next = (struct gen_pool_link *) (a + s); - h[j].next->next = NULL; - } - } - spin_unlock_irqrestore(&poolp->lock, flags); - return a; + write_lock(&pool->lock); + list_add(&chunk->next_chunk, &pool->chunks); + write_unlock(&pool->lock); + + return 0; } -EXPORT_SYMBOL(gen_pool_alloc); +EXPORT_SYMBOL(gen_pool_add); /* - * Counter-part of the generic allocator. + * Allocate the requested number of bytes from the specified pool. + * Uses a first-fit algorithm. + * + * @pool: pool to allocate from + * @size: number of bytes to allocate from the pool */ -void gen_pool_free(struct gen_pool *poolp, unsigned long ptr, int size) +unsigned long gen_pool_alloc(struct gen_pool *pool, size_t size) { - struct gen_pool_link *q; - struct gen_pool_link *h = poolp->h; - unsigned long a, b, flags; - int i, s, max_chunk_size; - - max_chunk_size = 1 << poolp->max_chunk_shift; + struct list_head *_chunk; + struct gen_pool_chunk *chunk; + unsigned long addr, flags; + int order = pool->min_alloc_order; + int nbits, bit, start_bit, end_bit; - if (size > max_chunk_size) - return; - - size = max(size, 1 << ALLOC_MIN_SHIFT); - i = fls(size - 1); - s = 1 << i; - i -= ALLOC_MIN_SHIFT; - - a = ptr; + if (size == 0) + return 0; - spin_lock_irqsave(&poolp->lock, flags); - while (1) { - if (s == max_chunk_size) { - ((struct gen_pool_link *)a)->next = h[i].next; - h[i].next = (struct gen_pool_link *)a; - break; + nbits = (size + (1UL << order) - 1) >> order; + + read_lock(&pool->lock); + list_for_each(_chunk, &pool->chunks) { + chunk = list_entry(_chunk, struct gen_pool_chunk, next_chunk); + + end_bit = (chunk->end_addr - chunk->start_addr) >> order; + end_bit -= nbits + 1; + + spin_lock_irqsave(&chunk->lock, flags); + bit = -1; + while (bit + 1 < end_bit) { + bit = find_next_zero_bit(chunk->bits, end_bit, bit + 1); + if (bit >= end_bit) + break; + + start_bit = bit; + if (nbits > 1) { + bit = find_next_bit(chunk->bits, bit + nbits, + bit + 1); + if (bit - start_bit < nbits) + continue; + } + + addr = chunk->start_addr + + ((unsigned long)start_bit << order); + while (nbits--) + __set_bit(start_bit++, &chunk->bits); + spin_unlock_irqrestore(&chunk->lock, flags); + read_unlock(&pool->lock); + return addr; } - b = a ^ s; - q = &h[i]; + spin_unlock_irqrestore(&chunk->lock, flags); + } + read_unlock(&pool->lock); + return 0; +} +EXPORT_SYMBOL(gen_pool_alloc); - while (q->next && q->next != (struct gen_pool_link *)b) - q = q->next; - if (!q->next) { - ((struct gen_pool_link *)a)->next = h[i].next; - h[i].next = (struct gen_pool_link *)a; +/* + * Free the specified memory back to the specified pool. + * + * @pool: pool to free to + * @addr: starting address of memory to free back to pool + * @size: size in bytes of memory to free + */ +void gen_pool_free(struct gen_pool *pool, unsigned long addr, size_t size) +{ + struct list_head *_chunk; + struct gen_pool_chunk *chunk; + unsigned long flags; + int order = pool->min_alloc_order; + int bit, nbits; + + nbits = (size + (1UL << order) - 1) >> order; + + read_lock(&pool->lock); + list_for_each(_chunk, &pool->chunks) { + chunk = list_entry(_chunk, struct gen_pool_chunk, next_chunk); + + if (addr >= chunk->start_addr && addr < chunk->end_addr) { + BUG_ON(addr + size > chunk->end_addr); + spin_lock_irqsave(&chunk->lock, flags); + bit = (addr - chunk->start_addr) >> order; + while (nbits--) + __clear_bit(bit++, &chunk->bits); + spin_unlock_irqrestore(&chunk->lock, flags); break; } - q->next = q->next->next; - a = a & b; - s <<= 1; - i++; } - spin_unlock_irqrestore(&poolp->lock, flags); + BUG_ON(nbits > 0); + read_unlock(&pool->lock); } EXPORT_SYMBOL(gen_pool_free); -- cgit v1.2.3 From 612d6c19db2fd0dc97b0fa370613ecd4a305ffc3 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Fri, 23 Jun 2006 02:03:22 -0700 Subject: [PATCH] radix-tree: direct data The ability to have height 0 radix trees (a direct pointer to the data item rather than going through a full node->slot) quietly disappeared with old-2.6-bkcvs commit ffee171812d51652f9ba284302d9e5c5cc14bdfd. On 64-bit machines this causes nearly 600 bytes to be used for every <= 4K file in pagecache. Re-introduce this feature, root tags stored in spare ->gfp_mask bits. Simplify radix_tree_delete's complex tag clearing arrangement (which would become even more complex) by just falling back to tag clearing functions (the pagecache radix-tree never uses this path anyway, so the icache savings will mean it's actually a speedup). On my 4GB G5, this saves 8MB RAM per kernel kernel source+object tree in pagecache. Pagecache lookup, insertion, and removal speed for small files will also be improved. This makes RCU radix tree harder, but it's worth it. Signed-off-by: Nick Piggin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/radix-tree.h | 5 +- lib/radix-tree.c | 192 ++++++++++++++++++++++++++------------------- 2 files changed, 114 insertions(+), 83 deletions(-) diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h index dd83cca2800..9158a68140c 100644 --- a/include/linux/radix-tree.h +++ b/include/linux/radix-tree.h @@ -23,6 +23,9 @@ #include #include +#define RADIX_TREE_MAX_TAGS 2 + +/* root tags are stored in gfp_mask, shifted by __GFP_BITS_SHIFT */ struct radix_tree_root { unsigned int height; gfp_t gfp_mask; @@ -45,8 +48,6 @@ do { \ (root)->rnode = NULL; \ } while (0) -#define RADIX_TREE_MAX_TAGS 2 - int radix_tree_insert(struct radix_tree_root *, unsigned long, void *); void *radix_tree_lookup(struct radix_tree_root *, unsigned long); void **radix_tree_lookup_slot(struct radix_tree_root *, unsigned long); diff --git a/lib/radix-tree.c b/lib/radix-tree.c index 7097bb239e4..35a2d93b352 100644 --- a/lib/radix-tree.c +++ b/lib/radix-tree.c @@ -74,6 +74,11 @@ struct radix_tree_preload { }; DEFINE_PER_CPU(struct radix_tree_preload, radix_tree_preloads) = { 0, }; +static inline gfp_t root_gfp_mask(struct radix_tree_root *root) +{ + return root->gfp_mask & __GFP_BITS_MASK; +} + /* * This assumes that the caller has performed appropriate preallocation, and * that the caller has pinned this thread of control to the current CPU. @@ -82,9 +87,10 @@ static struct radix_tree_node * radix_tree_node_alloc(struct radix_tree_root *root) { struct radix_tree_node *ret; + gfp_t gfp_mask = root_gfp_mask(root); - ret = kmem_cache_alloc(radix_tree_node_cachep, root->gfp_mask); - if (ret == NULL && !(root->gfp_mask & __GFP_WAIT)) { + ret = kmem_cache_alloc(radix_tree_node_cachep, gfp_mask); + if (ret == NULL && !(gfp_mask & __GFP_WAIT)) { struct radix_tree_preload *rtp; rtp = &__get_cpu_var(radix_tree_preloads); @@ -152,6 +158,27 @@ static inline int tag_get(struct radix_tree_node *node, unsigned int tag, return test_bit(offset, node->tags[tag]); } +static inline void root_tag_set(struct radix_tree_root *root, unsigned int tag) +{ + root->gfp_mask |= (1 << (tag + __GFP_BITS_SHIFT)); +} + + +static inline void root_tag_clear(struct radix_tree_root *root, unsigned int tag) +{ + root->gfp_mask &= ~(1 << (tag + __GFP_BITS_SHIFT)); +} + +static inline void root_tag_clear_all(struct radix_tree_root *root) +{ + root->gfp_mask &= __GFP_BITS_MASK; +} + +static inline int root_tag_get(struct radix_tree_root *root, unsigned int tag) +{ + return root->gfp_mask & (1 << (tag + __GFP_BITS_SHIFT)); +} + /* * Returns 1 if any slot in the node has this tag set. * Otherwise returns 0. @@ -182,7 +209,6 @@ static int radix_tree_extend(struct radix_tree_root *root, unsigned long index) { struct radix_tree_node *node; unsigned int height; - char tags[RADIX_TREE_MAX_TAGS]; int tag; /* Figure out what the height should be. */ @@ -195,16 +221,6 @@ static int radix_tree_extend(struct radix_tree_root *root, unsigned long index) goto out; } - /* - * Prepare the tag status of the top-level node for propagation - * into the newly-pushed top-level node(s) - */ - for (tag = 0; tag < RADIX_TREE_MAX_TAGS; tag++) { - tags[tag] = 0; - if (any_tag_set(root->rnode, tag)) - tags[tag] = 1; - } - do { if (!(node = radix_tree_node_alloc(root))) return -ENOMEM; @@ -214,7 +230,7 @@ static int radix_tree_extend(struct radix_tree_root *root, unsigned long index) /* Propagate the aggregated tag info into the new root */ for (tag = 0; tag < RADIX_TREE_MAX_TAGS; tag++) { - if (tags[tag]) + if (root_tag_get(root, tag)) tag_set(node, tag, 0); } @@ -243,8 +259,7 @@ int radix_tree_insert(struct radix_tree_root *root, int error; /* Make sure the tree is high enough. */ - if ((!index && !root->rnode) || - index > radix_tree_maxindex(root->height)) { + if (index > radix_tree_maxindex(root->height)) { error = radix_tree_extend(root, index); if (error) return error; @@ -255,7 +270,7 @@ int radix_tree_insert(struct radix_tree_root *root, shift = (height-1) * RADIX_TREE_MAP_SHIFT; offset = 0; /* uninitialised var warning */ - do { + while (height > 0) { if (slot == NULL) { /* Have to add a child node. */ if (!(slot = radix_tree_node_alloc(root))) @@ -273,16 +288,21 @@ int radix_tree_insert(struct radix_tree_root *root, slot = node->slots[offset]; shift -= RADIX_TREE_MAP_SHIFT; height--; - } while (height > 0); + } if (slot != NULL) return -EEXIST; - BUG_ON(!node); - node->count++; - node->slots[offset] = item; - BUG_ON(tag_get(node, 0, offset)); - BUG_ON(tag_get(node, 1, offset)); + if (node) { + node->count++; + node->slots[offset] = item; + BUG_ON(tag_get(node, 0, offset)); + BUG_ON(tag_get(node, 1, offset)); + } else { + root->rnode = item; + BUG_ON(root_tag_get(root, 0)); + BUG_ON(root_tag_get(root, 1)); + } return 0; } @@ -295,9 +315,13 @@ static inline void **__lookup_slot(struct radix_tree_root *root, struct radix_tree_node **slot; height = root->height; + if (index > radix_tree_maxindex(height)) return NULL; + if (height == 0 && root->rnode) + return (void **)&root->rnode; + shift = (height-1) * RADIX_TREE_MAP_SHIFT; slot = &root->rnode; @@ -368,8 +392,8 @@ void *radix_tree_tag_set(struct radix_tree_root *root, if (index > radix_tree_maxindex(height)) return NULL; - shift = (height - 1) * RADIX_TREE_MAP_SHIFT; slot = root->rnode; + shift = (height - 1) * RADIX_TREE_MAP_SHIFT; while (height > 0) { int offset; @@ -383,6 +407,10 @@ void *radix_tree_tag_set(struct radix_tree_root *root, height--; } + /* set the root's tag bit */ + if (slot && !root_tag_get(root, tag)) + root_tag_set(root, tag); + return slot; } EXPORT_SYMBOL(radix_tree_tag_set); @@ -405,9 +433,8 @@ void *radix_tree_tag_clear(struct radix_tree_root *root, unsigned long index, unsigned int tag) { struct radix_tree_path path[RADIX_TREE_MAX_PATH], *pathp = path; - struct radix_tree_node *slot; + struct radix_tree_node *slot = NULL; unsigned int height, shift; - void *ret = NULL; height = root->height; if (index > radix_tree_maxindex(height)) @@ -432,20 +459,24 @@ void *radix_tree_tag_clear(struct radix_tree_root *root, height--; } - ret = slot; - if (ret == NULL) + if (slot == NULL) goto out; - do { + while (pathp->node) { if (!tag_get(pathp->node, tag, pathp->offset)) goto out; tag_clear(pathp->node, tag, pathp->offset); if (any_tag_set(pathp->node, tag)) goto out; pathp--; - } while (pathp->node); + } + + /* clear the root's tag bit */ + if (root_tag_get(root, tag)) + root_tag_clear(root, tag); + out: - return ret; + return slot; } EXPORT_SYMBOL(radix_tree_tag_clear); @@ -458,9 +489,8 @@ EXPORT_SYMBOL(radix_tree_tag_clear); * * Return values: * - * 0: tag not present - * 1: tag present, set - * -1: tag present, unset + * 0: tag not present or not set + * 1: tag set */ int radix_tree_tag_get(struct radix_tree_root *root, unsigned long index, unsigned int tag) @@ -473,6 +503,13 @@ int radix_tree_tag_get(struct radix_tree_root *root, if (index > radix_tree_maxindex(height)) return 0; + /* check the root's tag bit */ + if (!root_tag_get(root, tag)) + return 0; + + if (height == 0) + return 1; + shift = (height - 1) * RADIX_TREE_MAP_SHIFT; slot = root->rnode; @@ -494,7 +531,7 @@ int radix_tree_tag_get(struct radix_tree_root *root, int ret = tag_get(slot, tag, offset); BUG_ON(ret && saw_unset_tag); - return ret ? 1 : -1; + return ret; } slot = slot->slots[offset]; shift -= RADIX_TREE_MAP_SHIFT; @@ -514,8 +551,11 @@ __lookup(struct radix_tree_root *root, void **results, unsigned long index, unsigned long i; height = root->height; - if (height == 0) + if (height == 0) { + if (root->rnode && index == 0) + results[nr_found++] = root->rnode; goto out; + } shift = (height-1) * RADIX_TREE_MAP_SHIFT; slot = root->rnode; @@ -603,10 +643,16 @@ __lookup_tag(struct radix_tree_root *root, void **results, unsigned long index, unsigned int height = root->height; struct radix_tree_node *slot; + if (height == 0) { + if (root->rnode && index == 0) + results[nr_found++] = root->rnode; + goto out; + } + shift = (height - 1) * RADIX_TREE_MAP_SHIFT; slot = root->rnode; - while (height > 0) { + do { unsigned long i = (index >> shift) & RADIX_TREE_MAP_MASK; for ( ; i < RADIX_TREE_MAP_SIZE; i++) { @@ -637,7 +683,7 @@ __lookup_tag(struct radix_tree_root *root, void **results, unsigned long index, } shift -= RADIX_TREE_MAP_SHIFT; slot = slot->slots[i]; - } + } while (height > 0); out: *next_index = index; return nr_found; @@ -665,6 +711,10 @@ radix_tree_gang_lookup_tag(struct radix_tree_root *root, void **results, unsigned long cur_index = first_index; unsigned int ret = 0; + /* check the root's tag bit */ + if (!root_tag_get(root, tag)) + return 0; + while (ret < max_items) { unsigned int nr_found; unsigned long next_index; /* Index of next search */ @@ -689,7 +739,7 @@ EXPORT_SYMBOL(radix_tree_gang_lookup_tag); static inline void radix_tree_shrink(struct radix_tree_root *root) { /* try to shrink tree height */ - while (root->height > 1 && + while (root->height > 0 && root->rnode->count == 1 && root->rnode->slots[0]) { struct radix_tree_node *to_free = root->rnode; @@ -717,12 +767,8 @@ static inline void radix_tree_shrink(struct radix_tree_root *root) void *radix_tree_delete(struct radix_tree_root *root, unsigned long index) { struct radix_tree_path path[RADIX_TREE_MAX_PATH], *pathp = path; - struct radix_tree_path *orig_pathp; - struct radix_tree_node *slot; + struct radix_tree_node *slot = NULL; unsigned int height, shift; - void *ret = NULL; - char tags[RADIX_TREE_MAX_TAGS]; - int nr_cleared_tags; int tag; int offset; @@ -730,11 +776,17 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index) if (index > radix_tree_maxindex(height)) goto out; + slot = root->rnode; + if (height == 0 && root->rnode) { + root_tag_clear_all(root); + root->rnode = NULL; + goto out; + } + shift = (height - 1) * RADIX_TREE_MAP_SHIFT; pathp->node = NULL; - slot = root->rnode; - for ( ; height > 0; height--) { + do { if (slot == NULL) goto out; @@ -744,44 +796,22 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index) pathp->node = slot; slot = slot->slots[offset]; shift -= RADIX_TREE_MAP_SHIFT; - } + height--; + } while (height > 0); - ret = slot; - if (ret == NULL) + if (slot == NULL) goto out; - orig_pathp = pathp; - /* * Clear all tags associated with the just-deleted item */ - nr_cleared_tags = 0; for (tag = 0; tag < RADIX_TREE_MAX_TAGS; tag++) { - tags[tag] = 1; - if (tag_get(pathp->node, tag, pathp->offset)) { - tag_clear(pathp->node, tag, pathp->offset); - if (!any_tag_set(pathp->node, tag)) { - tags[tag] = 0; - nr_cleared_tags++; - } - } - } - - for (pathp--; nr_cleared_tags && pathp->node; pathp--) { - for (tag = 0; tag < RADIX_TREE_MAX_TAGS; tag++) { - if (tags[tag]) - continue; - - tag_clear(pathp->node, tag, pathp->offset); - if (any_tag_set(pathp->node, tag)) { - tags[tag] = 1; - nr_cleared_tags--; - } - } + if (tag_get(pathp->node, tag, pathp->offset)) + radix_tree_tag_clear(root, index, tag); } /* Now free the nodes we do not need anymore */ - for (pathp = orig_pathp; pathp->node; pathp--) { + while (pathp->node) { pathp->node->slots[pathp->offset] = NULL; pathp->node->count--; @@ -793,11 +823,15 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index) /* Node with zero slots in use so free it */ radix_tree_node_free(pathp->node); + + pathp--; } - root->rnode = NULL; + root_tag_clear_all(root); root->height = 0; + root->rnode = NULL; + out: - return ret; + return slot; } EXPORT_SYMBOL(radix_tree_delete); @@ -808,11 +842,7 @@ EXPORT_SYMBOL(radix_tree_delete); */ int radix_tree_tagged(struct radix_tree_root *root, unsigned int tag) { - struct radix_tree_node *rnode; - rnode = root->rnode; - if (!rnode) - return 0; - return any_tag_set(rnode, tag); + return root_tag_get(root, tag); } EXPORT_SYMBOL(radix_tree_tagged); -- cgit v1.2.3 From cfd9b7df4abd3257c9e381b0e445817b26a51c0c Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Fri, 23 Jun 2006 02:03:22 -0700 Subject: [PATCH] radix-tree: small Reduce radix tree node memory usage by about a factor of 4 for small files (< 64K). There are pointer traversal and memory usage costs for large files with dense pagecache. Signed-off-by: Nick Piggin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/radix-tree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/radix-tree.c b/lib/radix-tree.c index 35a2d93b352..7cbdada5104 100644 --- a/lib/radix-tree.c +++ b/lib/radix-tree.c @@ -33,7 +33,7 @@ #ifdef __KERNEL__ -#define RADIX_TREE_MAP_SHIFT 6 +#define RADIX_TREE_MAP_SHIFT (CONFIG_BASE_SMALL ? 4 : 6) #else #define RADIX_TREE_MAP_SHIFT 3 /* For more stressful testing */ #endif -- cgit v1.2.3 From b344e05c585406904c70865e531e02467c4c7931 Mon Sep 17 00:00:00 2001 From: Hua Zhong Date: Fri, 23 Jun 2006 02:03:23 -0700 Subject: [PATCH] likely cleanup: remove unlikely in sys_mprotect() With likely/unlikely profiling on my not-so-busy-typical-developmentsystem there are 5k misses vs 2k hits. So I guess we should remove the unlikely. Signed-off-by: Hua Zhong Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/mprotect.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mm/mprotect.c b/mm/mprotect.c index 4c14d4289b6..5faf01ad3ef 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c @@ -205,8 +205,7 @@ sys_mprotect(unsigned long start, size_t len, unsigned long prot) /* * Does the application expect PROT_READ to imply PROT_EXEC: */ - if (unlikely((prot & PROT_READ) && - (current->personality & READ_IMPLIES_EXEC))) + if ((prot & PROT_READ) && (current->personality & READ_IMPLIES_EXEC)) prot |= PROT_EXEC; vm_flags = calc_vm_prot_bits(prot); -- cgit v1.2.3 From 58ce1fd5805647a58a050bbbbd2252ea5ecb47b3 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Fri, 23 Jun 2006 02:03:24 -0700 Subject: [PATCH] slab: redzone double-free detection At present our slab debugging tells us that it detected a double-free or corruption - it does not distinguish between them. Sometimes it's useful to be able to differentiate between these two types of information. Add double-free detection to redzone verification when freeing an object. As explained by Manfred, when we are freeing an object, both redzones should be RED_ACTIVE. However, if both are RED_INACTIVE, we are trying to free an object that was already free'd. Signed-off-by: Manfred Spraul Signed-off-by: Pekka Enberg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/slab.c | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index 54bd2eb3f2f..2046da2aa46 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -2636,6 +2636,28 @@ static void kfree_debugcheck(const void *objp) } } +static inline void verify_redzone_free(struct kmem_cache *cache, void *obj) +{ + unsigned long redzone1, redzone2; + + redzone1 = *dbg_redzone1(cache, obj); + redzone2 = *dbg_redzone2(cache, obj); + + /* + * Redzone is ok. + */ + if (redzone1 == RED_ACTIVE && redzone2 == RED_ACTIVE) + return; + + if (redzone1 == RED_INACTIVE && redzone2 == RED_INACTIVE) + slab_error(cache, "double free detected"); + else + slab_error(cache, "memory outside object was overwritten"); + + printk(KERN_ERR "%p: redzone 1:0x%lx, redzone 2:0x%lx.\n", + obj, redzone1, redzone2); +} + static void *cache_free_debugcheck(struct kmem_cache *cachep, void *objp, void *caller) { @@ -2659,15 +2681,7 @@ static void *cache_free_debugcheck(struct kmem_cache *cachep, void *objp, slabp = page_get_slab(page); if (cachep->flags & SLAB_RED_ZONE) { - if (*dbg_redzone1(cachep, objp) != RED_ACTIVE || - *dbg_redzone2(cachep, objp) != RED_ACTIVE) { - slab_error(cachep, "double free, or memory outside" - " object was overwritten"); - printk(KERN_ERR "%p: redzone 1:0x%lx, " - "redzone 2:0x%lx.\n", - objp, *dbg_redzone1(cachep, objp), - *dbg_redzone2(cachep, objp)); - } + verify_redzone_free(cachep, objp); *dbg_redzone1(cachep, objp) = RED_INACTIVE; *dbg_redzone2(cachep, objp) = RED_INACTIVE; } -- cgit v1.2.3 From 4c91c3648c620003cb7b21b8858f36cd6132e168 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Fri, 23 Jun 2006 02:03:25 -0700 Subject: [PATCH] buglet in radix_tree_tag_set The comment states: 'Setting a tag on a not-present item is a BUG.' Hence if 'index' is larger than the maxindex; the item _cannot_ be presen; it should also be a BUG. Also, this allows the following statement (assume a fresh tree): radix_tree_tag_set(root, 16, 1); to fail silently, but when preceded by: radix_tree_insert(root, 32, item); it would BUG, because the height has been extended by the insert. In neither case was 16 present. Signed-off-by: Peter Zijlstra Acked-by: Nick Piggin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/radix-tree.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/radix-tree.c b/lib/radix-tree.c index 7cbdada5104..b32efae7688 100644 --- a/lib/radix-tree.c +++ b/lib/radix-tree.c @@ -389,8 +389,7 @@ void *radix_tree_tag_set(struct radix_tree_root *root, struct radix_tree_node *slot; height = root->height; - if (index > radix_tree_maxindex(height)) - return NULL; + BUG_ON(index > radix_tree_maxindex(height)); slot = root->rnode; shift = (height - 1) * RADIX_TREE_MAP_SHIFT; -- cgit v1.2.3 From 111ebb6e6f7bd7de6d722c5848e95621f43700d9 Mon Sep 17 00:00:00 2001 From: OGAWA Hirofumi Date: Fri, 23 Jun 2006 02:03:26 -0700 Subject: [PATCH] writeback: fix range handling When a writeback_control's `start' and `end' fields are used to indicate a one-byte-range starting at file offset zero, the required values of .start=0,.end=0 mean that the ->writepages() implementation has no way of telling that it is being asked to perform a range request. Because we're currently overloading (start == 0 && end == 0) to mean "this is not a write-a-range request". To make all this sane, the patch changes range of writeback_control. So caller does: If it is calling ->writepages() to write pages, it sets range (range_start/end or range_cyclic) always. And if range_cyclic is true, ->writepages() thinks the range is cyclic, otherwise it just uses range_start and range_end. This patch does, - Add LLONG_MAX, LLONG_MIN, ULLONG_MAX to include/linux/kernel.h -1 is usually ok for range_end (type is long long). But, if someone did, range_end += val; range_end is "val - 1" u64val = range_end >> bits; u64val is "~(0ULL)" or something, they are wrong. So, this adds LLONG_MAX to avoid nasty things, and uses LLONG_MAX for range_end. - All callers of ->writepages() sets range_start/end or range_cyclic. - Fix updates of ->writeback_index. It seems already bit strange. If it starts at 0 and ended by check of nr_to_write, this last index may reduce chance to scan end of file. So, this updates ->writeback_index only if range_cyclic is true or whole-file is scanned. Signed-off-by: OGAWA Hirofumi Cc: Nathan Scott Cc: Anton Altaparmakov Cc: Steven French Cc: "Vladimir V. Saveliev" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/cifs/file.c | 24 +++++++++++------------- fs/fs-writeback.c | 4 ++++ fs/mpage.c | 22 ++++++++++------------ fs/sync.c | 2 +- include/linux/kernel.h | 3 +++ include/linux/writeback.h | 5 +++-- mm/filemap.c | 6 +++--- mm/page-writeback.c | 3 +++ mm/vmscan.c | 2 ++ 9 files changed, 40 insertions(+), 31 deletions(-) diff --git a/fs/cifs/file.c b/fs/cifs/file.c index e2b4ce1dad6..487ea8b3baa 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -1079,9 +1079,9 @@ static int cifs_writepages(struct address_space *mapping, unsigned int bytes_written; struct cifs_sb_info *cifs_sb; int done = 0; - pgoff_t end = -1; + pgoff_t end; pgoff_t index; - int is_range = 0; + int range_whole = 0; struct kvec iov[32]; int len; int n_iov = 0; @@ -1122,16 +1122,14 @@ static int cifs_writepages(struct address_space *mapping, xid = GetXid(); pagevec_init(&pvec, 0); - if (wbc->sync_mode == WB_SYNC_NONE) + if (wbc->range_cyclic) { index = mapping->writeback_index; /* Start from prev offset */ - else { - index = 0; - scanned = 1; - } - if (wbc->start || wbc->end) { - index = wbc->start >> PAGE_CACHE_SHIFT; - end = wbc->end >> PAGE_CACHE_SHIFT; - is_range = 1; + end = -1; + } else { + index = wbc->range_start >> PAGE_CACHE_SHIFT; + end = wbc->range_end >> PAGE_CACHE_SHIFT; + if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX) + range_whole = 1; scanned = 1; } retry: @@ -1167,7 +1165,7 @@ retry: break; } - if (unlikely(is_range) && (page->index > end)) { + if (!wbc->range_cyclic && page->index > end) { done = 1; unlock_page(page); break; @@ -1271,7 +1269,7 @@ retry: index = 0; goto retry; } - if (!is_range) + if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0)) mapping->writeback_index = index; FreeXid(xid); diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index f3fbe2d030f..6db95cf3aaa 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -461,6 +461,8 @@ void sync_inodes_sb(struct super_block *sb, int wait) { struct writeback_control wbc = { .sync_mode = wait ? WB_SYNC_ALL : WB_SYNC_HOLD, + .range_start = 0, + .range_end = LLONG_MAX, }; unsigned long nr_dirty = read_page_state(nr_dirty); unsigned long nr_unstable = read_page_state(nr_unstable); @@ -559,6 +561,8 @@ int write_inode_now(struct inode *inode, int sync) struct writeback_control wbc = { .nr_to_write = LONG_MAX, .sync_mode = WB_SYNC_ALL, + .range_start = 0, + .range_end = LLONG_MAX, }; if (!mapping_cap_writeback_dirty(inode->i_mapping)) diff --git a/fs/mpage.c b/fs/mpage.c index 9bf2eb30e6f..1e4598247d0 100644 --- a/fs/mpage.c +++ b/fs/mpage.c @@ -707,9 +707,9 @@ mpage_writepages(struct address_space *mapping, struct pagevec pvec; int nr_pages; pgoff_t index; - pgoff_t end = -1; /* Inclusive */ + pgoff_t end; /* Inclusive */ int scanned = 0; - int is_range = 0; + int range_whole = 0; if (wbc->nonblocking && bdi_write_congested(bdi)) { wbc->encountered_congestion = 1; @@ -721,16 +721,14 @@ mpage_writepages(struct address_space *mapping, writepage = mapping->a_ops->writepage; pagevec_init(&pvec, 0); - if (wbc->sync_mode == WB_SYNC_NONE) { + if (wbc->range_cyclic) { index = mapping->writeback_index; /* Start from prev offset */ + end = -1; } else { - index = 0; /* whole-file sweep */ - scanned = 1; - } - if (wbc->start || wbc->end) { - index = wbc->start >> PAGE_CACHE_SHIFT; - end = wbc->end >> PAGE_CACHE_SHIFT; - is_range = 1; + index = wbc->range_start >> PAGE_CACHE_SHIFT; + end = wbc->range_end >> PAGE_CACHE_SHIFT; + if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX) + range_whole = 1; scanned = 1; } retry: @@ -759,7 +757,7 @@ retry: continue; } - if (unlikely(is_range) && page->index > end) { + if (!wbc->range_cyclic && page->index > end) { done = 1; unlock_page(page); continue; @@ -810,7 +808,7 @@ retry: index = 0; goto retry; } - if (!is_range) + if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0)) mapping->writeback_index = index; if (bio) mpage_bio_submit(WRITE, bio); diff --git a/fs/sync.c b/fs/sync.c index aab5ffe77e9..955aef04da2 100644 --- a/fs/sync.c +++ b/fs/sync.c @@ -100,7 +100,7 @@ asmlinkage long sys_sync_file_range(int fd, loff_t offset, loff_t nbytes, } if (nbytes == 0) - endbyte = -1; + endbyte = LLONG_MAX; else endbyte--; /* inclusive */ diff --git a/include/linux/kernel.h b/include/linux/kernel.h index f4fc576ed4c..25fccd859fb 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -24,6 +24,9 @@ extern const char linux_banner[]; #define LONG_MAX ((long)(~0UL>>1)) #define LONG_MIN (-LONG_MAX - 1) #define ULONG_MAX (~0UL) +#define LLONG_MAX ((long long)(~0ULL>>1)) +#define LLONG_MIN (-LLONG_MAX - 1) +#define ULLONG_MAX (~0ULL) #define STACK_MAGIC 0xdeadbeef diff --git a/include/linux/writeback.h b/include/linux/writeback.h index 56f92fcbe94..9e38b566d0e 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h @@ -50,14 +50,15 @@ struct writeback_control { * a hint that the filesystem need only write out the pages inside that * byterange. The byte at `end' is included in the writeout request. */ - loff_t start; - loff_t end; + loff_t range_start; + loff_t range_end; unsigned nonblocking:1; /* Don't get stuck on request queues */ unsigned encountered_congestion:1; /* An output: a queue is full */ unsigned for_kupdate:1; /* A kupdate writeback */ unsigned for_reclaim:1; /* Invoked from the page allocator */ unsigned for_writepages:1; /* This is a writepages() call */ + unsigned range_cyclic:1; /* range_start is cyclic */ }; /* diff --git a/mm/filemap.c b/mm/filemap.c index fd57442186c..3342067ca43 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -190,8 +190,8 @@ int __filemap_fdatawrite_range(struct address_space *mapping, loff_t start, struct writeback_control wbc = { .sync_mode = sync_mode, .nr_to_write = mapping->nrpages * 2, - .start = start, - .end = end, + .range_start = start, + .range_end = end, }; if (!mapping_cap_writeback_dirty(mapping)) @@ -204,7 +204,7 @@ int __filemap_fdatawrite_range(struct address_space *mapping, loff_t start, static inline int __filemap_fdatawrite(struct address_space *mapping, int sync_mode) { - return __filemap_fdatawrite_range(mapping, 0, 0, sync_mode); + return __filemap_fdatawrite_range(mapping, 0, LLONG_MAX, sync_mode); } int filemap_fdatawrite(struct address_space *mapping) diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 75d7f48b79b..8ccf6f1b147 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -204,6 +204,7 @@ static void balance_dirty_pages(struct address_space *mapping) .sync_mode = WB_SYNC_NONE, .older_than_this = NULL, .nr_to_write = write_chunk, + .range_cyclic = 1, }; get_dirty_limits(&wbs, &background_thresh, @@ -331,6 +332,7 @@ static void background_writeout(unsigned long _min_pages) .older_than_this = NULL, .nr_to_write = 0, .nonblocking = 1, + .range_cyclic = 1, }; for ( ; ; ) { @@ -407,6 +409,7 @@ static void wb_kupdate(unsigned long arg) .nr_to_write = 0, .nonblocking = 1, .for_kupdate = 1, + .range_cyclic = 1, }; sync_supers(); diff --git a/mm/vmscan.c b/mm/vmscan.c index 46be8a02280..bc5d4f43036 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -339,6 +339,8 @@ pageout_t pageout(struct page *page, struct address_space *mapping) struct writeback_control wbc = { .sync_mode = WB_SYNC_NONE, .nr_to_write = SWAP_CLUSTER_MAX, + .range_start = 0, + .range_end = LLONG_MAX, .nonblocking = 1, .for_reclaim = 1, }; -- cgit v1.2.3 From 7352349a19e84b28f10668eca9cbb6bbbfa9d38e Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Fri, 23 Jun 2006 02:03:27 -0700 Subject: [PATCH] page migration cleanup: rename "ignrefs" to "migration" migrate is a better name since it is only used by page migration. Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/rmap.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/mm/rmap.c b/mm/rmap.c index 1963e269314..10806b7af40 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -578,7 +578,7 @@ void page_remove_rmap(struct page *page) * repeatedly from either try_to_unmap_anon or try_to_unmap_file. */ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma, - int ignore_refs) + int migration) { struct mm_struct *mm = vma->vm_mm; unsigned long address; @@ -602,7 +602,7 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma, */ if ((vma->vm_flags & VM_LOCKED) || (ptep_clear_flush_young(vma, address, pte) - && !ignore_refs)) { + && !migration)) { ret = SWAP_FAIL; goto out_unmap; } @@ -736,7 +736,7 @@ static void try_to_unmap_cluster(unsigned long cursor, pte_unmap_unlock(pte - 1, ptl); } -static int try_to_unmap_anon(struct page *page, int ignore_refs) +static int try_to_unmap_anon(struct page *page, int migration) { struct anon_vma *anon_vma; struct vm_area_struct *vma; @@ -747,7 +747,7 @@ static int try_to_unmap_anon(struct page *page, int ignore_refs) return ret; list_for_each_entry(vma, &anon_vma->head, anon_vma_node) { - ret = try_to_unmap_one(page, vma, ignore_refs); + ret = try_to_unmap_one(page, vma, migration); if (ret == SWAP_FAIL || !page_mapped(page)) break; } @@ -764,7 +764,7 @@ static int try_to_unmap_anon(struct page *page, int ignore_refs) * * This function is only called from try_to_unmap for object-based pages. */ -static int try_to_unmap_file(struct page *page, int ignore_refs) +static int try_to_unmap_file(struct page *page, int migration) { struct address_space *mapping = page->mapping; pgoff_t pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); @@ -778,7 +778,7 @@ static int try_to_unmap_file(struct page *page, int ignore_refs) spin_lock(&mapping->i_mmap_lock); vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) { - ret = try_to_unmap_one(page, vma, ignore_refs); + ret = try_to_unmap_one(page, vma, migration); if (ret == SWAP_FAIL || !page_mapped(page)) goto out; } @@ -863,16 +863,16 @@ out: * SWAP_AGAIN - we missed a mapping, try again later * SWAP_FAIL - the page is unswappable */ -int try_to_unmap(struct page *page, int ignore_refs) +int try_to_unmap(struct page *page, int migration) { int ret; BUG_ON(!PageLocked(page)); if (PageAnon(page)) - ret = try_to_unmap_anon(page, ignore_refs); + ret = try_to_unmap_anon(page, migration); else - ret = try_to_unmap_file(page, ignore_refs); + ret = try_to_unmap_file(page, migration); if (!page_mapped(page)) ret = SWAP_SUCCESS; -- cgit v1.2.3 From 1d8b85ccf1ed53a71b092fb5d807edf1ea7dabdd Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Fri, 23 Jun 2006 02:03:28 -0700 Subject: [PATCH] page migration cleanup: group functions Reorder functions in migrate.c. Group all migration functions for struct address_space_operations together. Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/migrate.c | 142 ++++++++++++++++++++++++++++++----------------------------- 1 file changed, 72 insertions(+), 70 deletions(-) diff --git a/mm/migrate.c b/mm/migrate.c index 1c25040693d..49e71ddb679 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -119,15 +119,6 @@ int putback_lru_pages(struct list_head *l) return count; } -/* - * Non migratable page - */ -int fail_migrate_page(struct page *newpage, struct page *page) -{ - return -EIO; -} -EXPORT_SYMBOL(fail_migrate_page); - /* * swapout a single page * page is locked upon entry, unlocked on exit @@ -297,6 +288,17 @@ void migrate_page_copy(struct page *newpage, struct page *page) } EXPORT_SYMBOL(migrate_page_copy); +/************************************************************ + * Migration functions + ***********************************************************/ + +/* Always fail migration. Used for mappings that are not movable */ +int fail_migrate_page(struct page *newpage, struct page *page) +{ + return -EIO; +} +EXPORT_SYMBOL(fail_migrate_page); + /* * Common logic to directly migrate a single page suitable for * pages that do not use PagePrivate. @@ -329,6 +331,67 @@ int migrate_page(struct page *newpage, struct page *page) } EXPORT_SYMBOL(migrate_page); +/* + * Migration function for pages with buffers. This function can only be used + * if the underlying filesystem guarantees that no other references to "page" + * exist. + */ +int buffer_migrate_page(struct page *newpage, struct page *page) +{ + struct address_space *mapping = page->mapping; + struct buffer_head *bh, *head; + int rc; + + if (!mapping) + return -EAGAIN; + + if (!page_has_buffers(page)) + return migrate_page(newpage, page); + + head = page_buffers(page); + + rc = migrate_page_remove_references(newpage, page, 3); + + if (rc) + return rc; + + bh = head; + do { + get_bh(bh); + lock_buffer(bh); + bh = bh->b_this_page; + + } while (bh != head); + + ClearPagePrivate(page); + set_page_private(newpage, page_private(page)); + set_page_private(page, 0); + put_page(page); + get_page(newpage); + + bh = head; + do { + set_bh_page(bh, newpage, bh_offset(bh)); + bh = bh->b_this_page; + + } while (bh != head); + + SetPagePrivate(newpage); + + migrate_page_copy(newpage, page); + + bh = head; + do { + unlock_buffer(bh); + put_bh(bh); + bh = bh->b_this_page; + + } while (bh != head); + + return 0; +} +EXPORT_SYMBOL(buffer_migrate_page); + /* * migrate_pages * @@ -528,67 +591,6 @@ next: return nr_failed + retry; } -/* - * Migration function for pages with buffers. This function can only be used - * if the underlying filesystem guarantees that no other references to "page" - * exist. - */ -int buffer_migrate_page(struct page *newpage, struct page *page) -{ - struct address_space *mapping = page->mapping; - struct buffer_head *bh, *head; - int rc; - - if (!mapping) - return -EAGAIN; - - if (!page_has_buffers(page)) - return migrate_page(newpage, page); - - head = page_buffers(page); - - rc = migrate_page_remove_references(newpage, page, 3); - - if (rc) - return rc; - - bh = head; - do { - get_bh(bh); - lock_buffer(bh); - bh = bh->b_this_page; - - } while (bh != head); - - ClearPagePrivate(page); - set_page_private(newpage, page_private(page)); - set_page_private(page, 0); - put_page(page); - get_page(newpage); - - bh = head; - do { - set_bh_page(bh, newpage, bh_offset(bh)); - bh = bh->b_this_page; - - } while (bh != head); - - SetPagePrivate(newpage); - - migrate_page_copy(newpage, page); - - bh = head; - do { - unlock_buffer(bh); - put_bh(bh); - bh = bh->b_this_page; - - } while (bh != head); - - return 0; -} -EXPORT_SYMBOL(buffer_migrate_page); - /* * Migrate the list 'pagelist' of pages to a certain destination. * -- cgit v1.2.3 From e7340f73307abed9283d0a07570d06e228c205dd Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Fri, 23 Jun 2006 02:03:29 -0700 Subject: [PATCH] page migration cleanup: remove useless definitions Remove the export for migrate_page_remove_references() and migrate_page_copy() that are unlikely to be used directly by filesystems implementing migration. The export was useful when buffer_migrate_page() lived in fs/buffer.c but it has now been moved to migrate.c in the migration reorg. Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/migrate.h | 2 -- mm/migrate.c | 6 ++---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/include/linux/migrate.h b/include/linux/migrate.h index 6789c4940c9..e8d3b08cc35 100644 --- a/include/linux/migrate.h +++ b/include/linux/migrate.h @@ -7,8 +7,6 @@ extern int isolate_lru_page(struct page *p, struct list_head *pagelist); extern int putback_lru_pages(struct list_head *l); extern int migrate_page(struct page *, struct page *); -extern void migrate_page_copy(struct page *, struct page *); -extern int migrate_page_remove_references(struct page *, struct page *, int); extern int migrate_pages(struct list_head *l, struct list_head *t, struct list_head *moved, struct list_head *failed); extern int migrate_pages_to(struct list_head *pagelist, diff --git a/mm/migrate.c b/mm/migrate.c index 49e71ddb679..be3f141e53a 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -169,7 +169,7 @@ retry: * Remove references for a page and establish the new page with the correct * basic settings to be able to stop accesses to the page. */ -int migrate_page_remove_references(struct page *newpage, +static int migrate_page_remove_references(struct page *newpage, struct page *page, int nr_refs) { struct address_space *mapping = page_mapping(page); @@ -246,12 +246,11 @@ int migrate_page_remove_references(struct page *newpage, return 0; } -EXPORT_SYMBOL(migrate_page_remove_references); /* * Copy the page to its new location */ -void migrate_page_copy(struct page *newpage, struct page *page) +static void migrate_page_copy(struct page *newpage, struct page *page) { copy_highpage(newpage, page); @@ -286,7 +285,6 @@ void migrate_page_copy(struct page *newpage, struct page *page) if (PageWriteback(newpage)) end_page_writeback(newpage); } -EXPORT_SYMBOL(migrate_page_copy); /************************************************************ * Migration functions -- cgit v1.2.3 From 5b5c7120e2154239837fad5e3c7b7b781092b19c Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Fri, 23 Jun 2006 02:03:29 -0700 Subject: [PATCH] page migration cleanup: drop nr_refs in remove_references() Drop nr_refs parameter from migrate_page_remove_references() The nr_refs parameter is not really useful since the number of remaining references is always 1 for anonymous pages without a mapping 2 for pages with a mapping 3 for pages with a mapping and PagePrivate set. Remove the early check for the number of references since we are checking page_mapcount() earlier. Ultimately only the refcount matters after the tree_lock has been obtained. Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/migrate.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/mm/migrate.c b/mm/migrate.c index be3f141e53a..2803a6698dd 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -168,19 +168,19 @@ retry: /* * Remove references for a page and establish the new page with the correct * basic settings to be able to stop accesses to the page. + * + * The number of remaining references must be: + * 1 for anonymous pages without a mapping + * 2 for pages with a mapping + * 3 for pages with a mapping and PagePrivate set. */ static int migrate_page_remove_references(struct page *newpage, - struct page *page, int nr_refs) + struct page *page) { struct address_space *mapping = page_mapping(page); struct page **radix_pointer; - /* - * Avoid doing any of the following work if the page count - * indicates that the page is in use or truncate has removed - * the page. - */ - if (!mapping || page_mapcount(page) + nr_refs != page_count(page)) + if (!mapping) return -EAGAIN; /* @@ -218,7 +218,8 @@ static int migrate_page_remove_references(struct page *newpage, &mapping->page_tree, page_index(page)); - if (!page_mapping(page) || page_count(page) != nr_refs || + if (!page_mapping(page) || + page_count(page) != 2 + !!PagePrivate(page) || *radix_pointer != page) { write_unlock_irq(&mapping->tree_lock); return -EAGAIN; @@ -309,7 +310,7 @@ int migrate_page(struct page *newpage, struct page *page) BUG_ON(PageWriteback(page)); /* Writeback must be complete */ - rc = migrate_page_remove_references(newpage, page, 2); + rc = migrate_page_remove_references(newpage, page); if (rc) return rc; @@ -348,7 +349,7 @@ int buffer_migrate_page(struct page *newpage, struct page *page) head = page_buffers(page); - rc = migrate_page_remove_references(newpage, page, 3); + rc = migrate_page_remove_references(newpage, page); if (rc) return rc; -- cgit v1.2.3 From c3fcf8a5daacf350f0632e1379414c01f34eeea3 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Fri, 23 Jun 2006 02:03:32 -0700 Subject: [PATCH] page migration cleanup: extract try_to_unmap from migration functions Extract try_to_unmap and rename remove_references -> move_mapping try_to_unmap() may significantly change the page state by for example setting the dirty bit. It is therefore best to unmap in migrate_pages() before calling any migration functions. migrate_page_remove_references() will then only move the new page in place of the old page in the mapping. Rename the function to migrate_page_move_mapping(). This allows us to get rid of the special unmapping for the fallback path. Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/migrate.c | 76 +++++++++++++++++++++++++----------------------------------- 1 file changed, 31 insertions(+), 45 deletions(-) diff --git a/mm/migrate.c b/mm/migrate.c index 2803a6698dd..8095c607a49 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -166,15 +166,14 @@ retry: } /* - * Remove references for a page and establish the new page with the correct - * basic settings to be able to stop accesses to the page. + * Replace the page in the mapping. * * The number of remaining references must be: * 1 for anonymous pages without a mapping * 2 for pages with a mapping * 3 for pages with a mapping and PagePrivate set. */ -static int migrate_page_remove_references(struct page *newpage, +static int migrate_page_move_mapping(struct page *newpage, struct page *page) { struct address_space *mapping = page_mapping(page); @@ -183,35 +182,6 @@ static int migrate_page_remove_references(struct page *newpage, if (!mapping) return -EAGAIN; - /* - * Establish swap ptes for anonymous pages or destroy pte - * maps for files. - * - * In order to reestablish file backed mappings the fault handlers - * will take the radix tree_lock which may then be used to stop - * processses from accessing this page until the new page is ready. - * - * A process accessing via a swap pte (an anonymous page) will take a - * page_lock on the old page which will block the process until the - * migration attempt is complete. At that time the PageSwapCache bit - * will be examined. If the page was migrated then the PageSwapCache - * bit will be clear and the operation to retrieve the page will be - * retried which will find the new page in the radix tree. Then a new - * direct mapping may be generated based on the radix tree contents. - * - * If the page was not migrated then the PageSwapCache bit - * is still set and the operation may continue. - */ - if (try_to_unmap(page, 1) == SWAP_FAIL) - /* A vma has VM_LOCKED set -> permanent failure */ - return -EPERM; - - /* - * Give up if we were unable to remove all mappings. - */ - if (page_mapcount(page)) - return -EAGAIN; - write_lock_irq(&mapping->tree_lock); radix_pointer = (struct page **)radix_tree_lookup_slot( @@ -310,7 +280,7 @@ int migrate_page(struct page *newpage, struct page *page) BUG_ON(PageWriteback(page)); /* Writeback must be complete */ - rc = migrate_page_remove_references(newpage, page); + rc = migrate_page_move_mapping(newpage, page); if (rc) return rc; @@ -349,7 +319,7 @@ int buffer_migrate_page(struct page *newpage, struct page *page) head = page_buffers(page); - rc = migrate_page_remove_references(newpage, page); + rc = migrate_page_move_mapping(newpage, page); if (rc) return rc; @@ -481,6 +451,33 @@ redo: newpage = lru_to_page(to); lock_page(newpage); + /* + * Establish swap ptes for anonymous pages or destroy pte + * maps for files. + * + * In order to reestablish file backed mappings the fault handlers + * will take the radix tree_lock which may then be used to stop + * processses from accessing this page until the new page is ready. + * + * A process accessing via a swap pte (an anonymous page) will take a + * page_lock on the old page which will block the process until the + * migration attempt is complete. At that time the PageSwapCache bit + * will be examined. If the page was migrated then the PageSwapCache + * bit will be clear and the operation to retrieve the page will be + * retried which will find the new page in the radix tree. Then a new + * direct mapping may be generated based on the radix tree contents. + * + * If the page was not migrated then the PageSwapCache bit + * is still set and the operation may continue. + */ + rc = -EPERM; + if (try_to_unmap(page, 1) == SWAP_FAIL) + /* A vma has VM_LOCKED set -> permanent failure */ + goto unlock_both; + + rc = -EAGAIN; + if (page_mapped(page)) + goto unlock_both; /* * Pages are properly locked and writeback is complete. * Try to migrate the page. @@ -501,17 +498,6 @@ redo: goto unlock_both; } - /* Make sure the dirty bit is up to date */ - if (try_to_unmap(page, 1) == SWAP_FAIL) { - rc = -EPERM; - goto unlock_both; - } - - if (page_mapcount(page)) { - rc = -EAGAIN; - goto unlock_both; - } - /* * Default handling if a filesystem does not provide * a migration function. We can only migrate clean -- cgit v1.2.3 From 2d1db3b1170db4e8bf0531dd636742269c2cf579 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Fri, 23 Jun 2006 02:03:33 -0700 Subject: [PATCH] page migration cleanup: pass "mapping" to migration functions Change handling of address spaces. Pass a pointer to the address space in which the page is migrated to all migration function. This avoids repeatedly having to retrieve the address space pointer from the page and checking it for validity. The old page mapping will change once migration has gone to a certain step, so it is less confusing to have the pointer always available. Move the setting of the mapping and index for the new page into migrate_pages(). Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/fs.h | 6 +++-- include/linux/migrate.h | 6 +++-- mm/migrate.c | 70 ++++++++++++++++++++++++------------------------- 3 files changed, 42 insertions(+), 40 deletions(-) diff --git a/include/linux/fs.h b/include/linux/fs.h index c823a3815e2..e917403f4d5 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -376,7 +376,8 @@ struct address_space_operations { struct page* (*get_xip_page)(struct address_space *, sector_t, int); /* migrate the contents of a page to the specified target */ - int (*migratepage) (struct page *, struct page *); + int (*migratepage) (struct address_space *, + struct page *, struct page *); }; struct backing_dev_info; @@ -1772,7 +1773,8 @@ extern void simple_release_fs(struct vfsmount **mount, int *count); extern ssize_t simple_read_from_buffer(void __user *, size_t, loff_t *, const void *, size_t); #ifdef CONFIG_MIGRATION -extern int buffer_migrate_page(struct page *, struct page *); +extern int buffer_migrate_page(struct address_space *, + struct page *, struct page *); #else #define buffer_migrate_page NULL #endif diff --git a/include/linux/migrate.h b/include/linux/migrate.h index e8d3b08cc35..287c47b5e5d 100644 --- a/include/linux/migrate.h +++ b/include/linux/migrate.h @@ -6,12 +6,14 @@ #ifdef CONFIG_MIGRATION extern int isolate_lru_page(struct page *p, struct list_head *pagelist); extern int putback_lru_pages(struct list_head *l); -extern int migrate_page(struct page *, struct page *); +extern int migrate_page(struct address_space *, + struct page *, struct page *); extern int migrate_pages(struct list_head *l, struct list_head *t, struct list_head *moved, struct list_head *failed); extern int migrate_pages_to(struct list_head *pagelist, struct vm_area_struct *vma, int dest); -extern int fail_migrate_page(struct page *, struct page *); +extern int fail_migrate_page(struct address_space *, + struct page *, struct page *); extern int migrate_prep(void); diff --git a/mm/migrate.c b/mm/migrate.c index 8095c607a49..f65e69d9452 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -173,15 +173,11 @@ retry: * 2 for pages with a mapping * 3 for pages with a mapping and PagePrivate set. */ -static int migrate_page_move_mapping(struct page *newpage, - struct page *page) +static int migrate_page_move_mapping(struct address_space *mapping, + struct page *newpage, struct page *page) { - struct address_space *mapping = page_mapping(page); struct page **radix_pointer; - if (!mapping) - return -EAGAIN; - write_lock_irq(&mapping->tree_lock); radix_pointer = (struct page **)radix_tree_lookup_slot( @@ -197,15 +193,8 @@ static int migrate_page_move_mapping(struct page *newpage, /* * Now we know that no one else is looking at the page. - * - * Certain minimal information about a page must be available - * in order for other subsystems to properly handle the page if they - * find it through the radix tree update before we are finished - * copying the page. */ get_page(newpage); - newpage->index = page->index; - newpage->mapping = page->mapping; if (PageSwapCache(page)) { SetPageSwapCache(newpage); set_page_private(newpage, page_private(page)); @@ -262,7 +251,8 @@ static void migrate_page_copy(struct page *newpage, struct page *page) ***********************************************************/ /* Always fail migration. Used for mappings that are not movable */ -int fail_migrate_page(struct page *newpage, struct page *page) +int fail_migrate_page(struct address_space *mapping, + struct page *newpage, struct page *page) { return -EIO; } @@ -274,13 +264,14 @@ EXPORT_SYMBOL(fail_migrate_page); * * Pages are locked upon entry and exit. */ -int migrate_page(struct page *newpage, struct page *page) +int migrate_page(struct address_space *mapping, + struct page *newpage, struct page *page) { int rc; BUG_ON(PageWriteback(page)); /* Writeback must be complete */ - rc = migrate_page_move_mapping(newpage, page); + rc = migrate_page_move_mapping(mapping, newpage, page); if (rc) return rc; @@ -305,21 +296,18 @@ EXPORT_SYMBOL(migrate_page); * if the underlying filesystem guarantees that no other references to "page" * exist. */ -int buffer_migrate_page(struct page *newpage, struct page *page) +int buffer_migrate_page(struct address_space *mapping, + struct page *newpage, struct page *page) { - struct address_space *mapping = page->mapping; struct buffer_head *bh, *head; int rc; - if (!mapping) - return -EAGAIN; - if (!page_has_buffers(page)) - return migrate_page(newpage, page); + return migrate_page(mapping, newpage, page); head = page_buffers(page); - rc = migrate_page_move_mapping(newpage, page); + rc = migrate_page_move_mapping(mapping, newpage, page); if (rc) return rc; @@ -448,9 +436,6 @@ redo: goto next; } - newpage = lru_to_page(to); - lock_page(newpage); - /* * Establish swap ptes for anonymous pages or destroy pte * maps for files. @@ -473,11 +458,18 @@ redo: rc = -EPERM; if (try_to_unmap(page, 1) == SWAP_FAIL) /* A vma has VM_LOCKED set -> permanent failure */ - goto unlock_both; + goto unlock_page; rc = -EAGAIN; if (page_mapped(page)) - goto unlock_both; + goto unlock_page; + + newpage = lru_to_page(to); + lock_page(newpage); + /* Prepare mapping for the new page.*/ + newpage->index = page->index; + newpage->mapping = page->mapping; + /* * Pages are properly locked and writeback is complete. * Try to migrate the page. @@ -494,7 +486,8 @@ redo: * own migration function. This is the most common * path for page migration. */ - rc = mapping->a_ops->migratepage(newpage, page); + rc = mapping->a_ops->migratepage(mapping, + newpage, page); goto unlock_both; } @@ -524,7 +517,7 @@ redo: */ if (!page_has_buffers(page) || try_to_release_page(page, GFP_KERNEL)) { - rc = migrate_page(newpage, page); + rc = migrate_page(mapping, newpage, page); goto unlock_both; } @@ -553,12 +546,17 @@ unlock_page: unlock_page(page); next: - if (rc == -EAGAIN) { - retry++; - } else if (rc) { - /* Permanent failure */ - list_move(&page->lru, failed); - nr_failed++; + if (rc) { + if (newpage) + newpage->mapping = NULL; + + if (rc == -EAGAIN) + retry++; + else { + /* Permanent failure */ + list_move(&page->lru, failed); + nr_failed++; + } } else { if (newpage) { /* Successful migration. Return page to LRU */ -- cgit v1.2.3 From 8351a6e4785218a2b03c142be92926baff95ba5c Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Fri, 23 Jun 2006 02:03:33 -0700 Subject: [PATCH] page migration cleanup: move fallback handling into special function Move the fallback code into a new fallback function and make the function behave like any other migration function. This requires retaking the lock if pageout() drops it. Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/migrate.c | 90 ++++++++++++++++++++++++++---------------------------------- 1 file changed, 39 insertions(+), 51 deletions(-) diff --git a/mm/migrate.c b/mm/migrate.c index f65e69d9452..5a340f4ca21 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -349,6 +349,42 @@ int buffer_migrate_page(struct address_space *mapping, } EXPORT_SYMBOL(buffer_migrate_page); +static int fallback_migrate_page(struct address_space *mapping, + struct page *newpage, struct page *page) +{ + /* + * Default handling if a filesystem does not provide + * a migration function. We can only migrate clean + * pages so try to write out any dirty pages first. + */ + if (PageDirty(page)) { + switch (pageout(page, mapping)) { + case PAGE_KEEP: + case PAGE_ACTIVATE: + return -EAGAIN; + + case PAGE_SUCCESS: + /* Relock since we lost the lock */ + lock_page(page); + /* Must retry since page state may have changed */ + return -EAGAIN; + + case PAGE_CLEAN: + ; /* try to migrate the page below */ + } + } + + /* + * Buffers may be managed in a filesystem specific way. + * We must have no buffers or drop them. + */ + if (page_has_buffers(page) && + !try_to_release_page(page, GFP_KERNEL)) + return -EAGAIN; + + return migrate_page(mapping, newpage, page); +} + /* * migrate_pages * @@ -478,7 +514,7 @@ redo: if (!mapping) goto unlock_both; - if (mapping->a_ops->migratepage) { + if (mapping->a_ops->migratepage) /* * Most pages have a mapping and most filesystems * should provide a migration function. Anonymous @@ -488,56 +524,8 @@ redo: */ rc = mapping->a_ops->migratepage(mapping, newpage, page); - goto unlock_both; - } - - /* - * Default handling if a filesystem does not provide - * a migration function. We can only migrate clean - * pages so try to write out any dirty pages first. - */ - if (PageDirty(page)) { - switch (pageout(page, mapping)) { - case PAGE_KEEP: - case PAGE_ACTIVATE: - goto unlock_both; - - case PAGE_SUCCESS: - unlock_page(newpage); - goto next; - - case PAGE_CLEAN: - ; /* try to migrate the page below */ - } - } - - /* - * Buffers are managed in a filesystem specific way. - * We must have no buffers or drop them. - */ - if (!page_has_buffers(page) || - try_to_release_page(page, GFP_KERNEL)) { - rc = migrate_page(mapping, newpage, page); - goto unlock_both; - } - - /* - * On early passes with mapped pages simply - * retry. There may be a lock held for some - * buffers that may go away. Later - * swap them out. - */ - if (pass > 4) { - /* - * Persistently unable to drop buffers..... As a - * measure of last resort we fall back to - * swap_page(). - */ - unlock_page(newpage); - newpage = NULL; - rc = swap_page(page); - goto next; - } + else + rc = fallback_migrate_page(mapping, newpage, page); unlock_both: unlock_page(newpage); -- cgit v1.2.3 From 0697212a411c1dae03c27845f2de2f3adb32c331 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Fri, 23 Jun 2006 02:03:35 -0700 Subject: [PATCH] Swapless page migration: add R/W migration entries Implement read/write migration ptes We take the upper two swapfiles for the two types of migration ptes and define a series of macros in swapops.h. The VM is modified to handle the migration entries. migration entries can only be encountered when the page they are pointing to is locked. This limits the number of places one has to fix. We also check in copy_pte_range and in mprotect_pte_range() for migration ptes. We check for migration ptes in do_swap_cache and call a function that will then wait on the page lock. This allows us to effectively stop all accesses to apge. Migration entries are created by try_to_unmap if called for migration and removed by local functions in migrate.c From: Hugh Dickins Several times while testing swapless page migration (I've no NUMA, just hacking it up to migrate recklessly while running load), I've hit the BUG_ON(!PageLocked(p)) in migration_entry_to_page. This comes from an orphaned migration entry, unrelated to the current correctly locked migration, but hit by remove_anon_migration_ptes as it checks an address in each vma of the anon_vma list. Such an orphan may be left behind if an earlier migration raced with fork: copy_one_pte can duplicate a migration entry from parent to child, after remove_anon_migration_ptes has checked the child vma, but before it has removed it from the parent vma. (If the process were later to fault on this orphaned entry, it would hit the same BUG from migration_entry_wait.) This could be fixed by locking anon_vma in copy_one_pte, but we'd rather not. There's no such problem with file pages, because vma_prio_tree_add adds child vma after parent vma, and the page table locking at each end is enough to serialize. Follow that example with anon_vma: add new vmas to the tail instead of the head. (There's no corresponding problem when inserting migration entries, because a missed pte will leave the page count and mapcount high, which is allowed for. And there's no corresponding problem when migrating via swap, because a leftover swap entry will be correctly faulted. But the swapless method has no refcounting of its entries.) From: Ingo Molnar pte_unmap_unlock() takes the pte pointer as an argument. From: Hugh Dickins Several times while testing swapless page migration, gcc has tried to exec a pointer instead of a string: smells like COW mappings are not being properly write-protected on fork. The protection in copy_one_pte looks very convincing, until at last you realize that the second arg to make_migration_entry is a boolean "write", and SWP_MIGRATION_READ is 30. Anyway, it's better done like in change_pte_range, using is_write_migration_entry and make_migration_entry_read. From: Hugh Dickins Remove unnecessary obfuscation from sys_swapon's range check on swap type, which blew up causing memory corruption once swapless migration made MAX_SWAPFILES no longer 2 ^ MAX_SWAPFILES_SHIFT. Signed-off-by: Hugh Dickins Acked-by: Martin Schwidefsky Signed-off-by: Hugh Dickins Signed-off-by: Christoph Lameter Signed-off-by: Ingo Molnar From: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/swap.h | 7 +++ include/linux/swapops.h | 53 ++++++++++++++++++++ mm/memory.c | 18 ++++++- mm/migrate.c | 128 +++++++++++++++++++++++++++++++++++++++++++++++- mm/mprotect.c | 23 +++++++-- mm/rmap.c | 38 ++++++++------ mm/swapfile.c | 20 +++----- 7 files changed, 255 insertions(+), 32 deletions(-) diff --git a/include/linux/swap.h b/include/linux/swap.h index cd28ad206da..7cee73ef4f1 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -28,7 +28,14 @@ static inline int current_is_kswapd(void) * the type/offset into the pte as 5/27 as well. */ #define MAX_SWAPFILES_SHIFT 5 +#ifndef CONFIG_MIGRATION #define MAX_SWAPFILES (1 << MAX_SWAPFILES_SHIFT) +#else +/* Use last two entries for page migration swap entries */ +#define MAX_SWAPFILES ((1 << MAX_SWAPFILES_SHIFT)-2) +#define SWP_MIGRATION_READ MAX_SWAPFILES +#define SWP_MIGRATION_WRITE (MAX_SWAPFILES + 1) +#endif /* * Magic header for a swap area. The first part of the union is diff --git a/include/linux/swapops.h b/include/linux/swapops.h index 87b9d14c710..ec639aa3a1d 100644 --- a/include/linux/swapops.h +++ b/include/linux/swapops.h @@ -67,3 +67,56 @@ static inline pte_t swp_entry_to_pte(swp_entry_t entry) BUG_ON(pte_file(__swp_entry_to_pte(arch_entry))); return __swp_entry_to_pte(arch_entry); } + +#ifdef CONFIG_MIGRATION +static inline swp_entry_t make_migration_entry(struct page *page, int write) +{ + BUG_ON(!PageLocked(page)); + return swp_entry(write ? SWP_MIGRATION_WRITE : SWP_MIGRATION_READ, + page_to_pfn(page)); +} + +static inline int is_migration_entry(swp_entry_t entry) +{ + return unlikely(swp_type(entry) == SWP_MIGRATION_READ || + swp_type(entry) == SWP_MIGRATION_WRITE); +} + +static inline int is_write_migration_entry(swp_entry_t entry) +{ + return unlikely(swp_type(entry) == SWP_MIGRATION_WRITE); +} + +static inline struct page *migration_entry_to_page(swp_entry_t entry) +{ + struct page *p = pfn_to_page(swp_offset(entry)); + /* + * Any use of migration entries may only occur while the + * corresponding page is locked + */ + BUG_ON(!PageLocked(p)); + return p; +} + +static inline void make_migration_entry_read(swp_entry_t *entry) +{ + *entry = swp_entry(SWP_MIGRATION_READ, swp_offset(*entry)); +} + +extern void migration_entry_wait(struct mm_struct *mm, pmd_t *pmd, + unsigned long address); +#else + +#define make_migration_entry(page, write) swp_entry(0, 0) +#define is_migration_entry(swp) 0 +#define migration_entry_to_page(swp) NULL +static inline void make_migration_entry_read(swp_entry_t *entryp) { } +static inline void migration_entry_wait(struct mm_struct *mm, pmd_t *pmd, + unsigned long address) { } +static inline int is_write_migration_entry(swp_entry_t entry) +{ + return 0; +} + +#endif + diff --git a/mm/memory.c b/mm/memory.c index 7e3683fd4f3..11673c5d2c2 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -434,7 +434,9 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm, /* pte contains position in swap or file, so copy. */ if (unlikely(!pte_present(pte))) { if (!pte_file(pte)) { - swap_duplicate(pte_to_swp_entry(pte)); + swp_entry_t entry = pte_to_swp_entry(pte); + + swap_duplicate(entry); /* make sure dst_mm is on swapoff's mmlist. */ if (unlikely(list_empty(&dst_mm->mmlist))) { spin_lock(&mmlist_lock); @@ -443,6 +445,16 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm, &src_mm->mmlist); spin_unlock(&mmlist_lock); } + if (is_write_migration_entry(entry) && + is_cow_mapping(vm_flags)) { + /* + * COW mappings require pages in both parent + * and child to be set to read. + */ + make_migration_entry_read(&entry); + pte = swp_entry_to_pte(entry); + set_pte_at(src_mm, addr, src_pte, pte); + } } goto out_set_pte; } @@ -1879,6 +1891,10 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, goto out; entry = pte_to_swp_entry(orig_pte); + if (is_migration_entry(entry)) { + migration_entry_wait(mm, pmd, address); + goto out; + } page = lookup_swap_cache(entry); if (!page) { swapin_readahead(entry, address, vma); diff --git a/mm/migrate.c b/mm/migrate.c index 5a340f4ca21..0a011e421bb 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -23,7 +24,6 @@ #include #include #include -#include #include "internal.h" @@ -119,6 +119,132 @@ int putback_lru_pages(struct list_head *l) return count; } +static inline int is_swap_pte(pte_t pte) +{ + return !pte_none(pte) && !pte_present(pte) && !pte_file(pte); +} + +/* + * Restore a potential migration pte to a working pte entry + */ +static void remove_migration_pte(struct vm_area_struct *vma, unsigned long addr, + struct page *old, struct page *new) +{ + struct mm_struct *mm = vma->vm_mm; + swp_entry_t entry; + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + pte_t *ptep, pte; + spinlock_t *ptl; + + pgd = pgd_offset(mm, addr); + if (!pgd_present(*pgd)) + return; + + pud = pud_offset(pgd, addr); + if (!pud_present(*pud)) + return; + + pmd = pmd_offset(pud, addr); + if (!pmd_present(*pmd)) + return; + + ptep = pte_offset_map(pmd, addr); + + if (!is_swap_pte(*ptep)) { + pte_unmap(ptep); + return; + } + + ptl = pte_lockptr(mm, pmd); + spin_lock(ptl); + pte = *ptep; + if (!is_swap_pte(pte)) + goto out; + + entry = pte_to_swp_entry(pte); + + if (!is_migration_entry(entry) || migration_entry_to_page(entry) != old) + goto out; + + inc_mm_counter(mm, anon_rss); + get_page(new); + pte = pte_mkold(mk_pte(new, vma->vm_page_prot)); + if (is_write_migration_entry(entry)) + pte = pte_mkwrite(pte); + set_pte_at(mm, addr, ptep, pte); + page_add_anon_rmap(new, vma, addr); +out: + pte_unmap_unlock(ptep, ptl); +} + +/* + * Get rid of all migration entries and replace them by + * references to the indicated page. + * + * Must hold mmap_sem lock on at least one of the vmas containing + * the page so that the anon_vma cannot vanish. + */ +static void remove_migration_ptes(struct page *old, struct page *new) +{ + struct anon_vma *anon_vma; + struct vm_area_struct *vma; + unsigned long mapping; + + mapping = (unsigned long)new->mapping; + + if (!mapping || (mapping & PAGE_MAPPING_ANON) == 0) + return; + + /* + * We hold the mmap_sem lock. So no need to call page_lock_anon_vma. + */ + anon_vma = (struct anon_vma *) (mapping - PAGE_MAPPING_ANON); + spin_lock(&anon_vma->lock); + + list_for_each_entry(vma, &anon_vma->head, anon_vma_node) + remove_migration_pte(vma, page_address_in_vma(new, vma), + old, new); + + spin_unlock(&anon_vma->lock); +} + +/* + * Something used the pte of a page under migration. We need to + * get to the page and wait until migration is finished. + * When we return from this function the fault will be retried. + * + * This function is called from do_swap_page(). + */ +void migration_entry_wait(struct mm_struct *mm, pmd_t *pmd, + unsigned long address) +{ + pte_t *ptep, pte; + spinlock_t *ptl; + swp_entry_t entry; + struct page *page; + + ptep = pte_offset_map_lock(mm, pmd, address, &ptl); + pte = *ptep; + if (!is_swap_pte(pte)) + goto out; + + entry = pte_to_swp_entry(pte); + if (!is_migration_entry(entry)) + goto out; + + page = migration_entry_to_page(entry); + + get_page(page); + pte_unmap_unlock(ptep, ptl); + wait_on_page_locked(page); + put_page(page); + return; +out: + pte_unmap_unlock(ptep, ptl); +} + /* * swapout a single page * page is locked upon entry, unlocked on exit diff --git a/mm/mprotect.c b/mm/mprotect.c index 5faf01ad3ef..14f93e62270 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c @@ -19,7 +19,8 @@ #include #include #include - +#include +#include #include #include #include @@ -28,12 +29,13 @@ static void change_pte_range(struct mm_struct *mm, pmd_t *pmd, unsigned long addr, unsigned long end, pgprot_t newprot) { - pte_t *pte; + pte_t *pte, oldpte; spinlock_t *ptl; pte = pte_offset_map_lock(mm, pmd, addr, &ptl); do { - if (pte_present(*pte)) { + oldpte = *pte; + if (pte_present(oldpte)) { pte_t ptent; /* Avoid an SMP race with hardware updated dirty/clean @@ -43,7 +45,22 @@ static void change_pte_range(struct mm_struct *mm, pmd_t *pmd, ptent = pte_modify(ptep_get_and_clear(mm, addr, pte), newprot); set_pte_at(mm, addr, pte, ptent); lazy_mmu_prot_update(ptent); +#ifdef CONFIG_MIGRATION + } else if (!pte_file(oldpte)) { + swp_entry_t entry = pte_to_swp_entry(oldpte); + + if (is_write_migration_entry(entry)) { + /* + * A protection check is difficult so + * just be safe and disable write + */ + make_migration_entry_read(&entry); + set_pte_at(mm, addr, pte, + swp_entry_to_pte(entry)); + } +#endif } + } while (pte++, addr += PAGE_SIZE, addr != end); pte_unmap_unlock(pte - 1, ptl); } diff --git a/mm/rmap.c b/mm/rmap.c index 10806b7af40..3b8ce86daa3 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -103,7 +103,7 @@ int anon_vma_prepare(struct vm_area_struct *vma) spin_lock(&mm->page_table_lock); if (likely(!vma->anon_vma)) { vma->anon_vma = anon_vma; - list_add(&vma->anon_vma_node, &anon_vma->head); + list_add_tail(&vma->anon_vma_node, &anon_vma->head); allocated = NULL; } spin_unlock(&mm->page_table_lock); @@ -127,7 +127,7 @@ void __anon_vma_link(struct vm_area_struct *vma) struct anon_vma *anon_vma = vma->anon_vma; if (anon_vma) { - list_add(&vma->anon_vma_node, &anon_vma->head); + list_add_tail(&vma->anon_vma_node, &anon_vma->head); validate_anon_vma(vma); } } @@ -138,7 +138,7 @@ void anon_vma_link(struct vm_area_struct *vma) if (anon_vma) { spin_lock(&anon_vma->lock); - list_add(&vma->anon_vma_node, &anon_vma->head); + list_add_tail(&vma->anon_vma_node, &anon_vma->head); validate_anon_vma(vma); spin_unlock(&anon_vma->lock); } @@ -620,17 +620,27 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma, if (PageAnon(page)) { swp_entry_t entry = { .val = page_private(page) }; - /* - * Store the swap location in the pte. - * See handle_pte_fault() ... - */ - BUG_ON(!PageSwapCache(page)); - swap_duplicate(entry); - if (list_empty(&mm->mmlist)) { - spin_lock(&mmlist_lock); - if (list_empty(&mm->mmlist)) - list_add(&mm->mmlist, &init_mm.mmlist); - spin_unlock(&mmlist_lock); + + if (PageSwapCache(page)) { + /* + * Store the swap location in the pte. + * See handle_pte_fault() ... + */ + swap_duplicate(entry); + if (list_empty(&mm->mmlist)) { + spin_lock(&mmlist_lock); + if (list_empty(&mm->mmlist)) + list_add(&mm->mmlist, &init_mm.mmlist); + spin_unlock(&mmlist_lock); + } + } else { + /* + * Store the pfn of the page in a special migration + * pte. do_swap_page() will wait until the migration + * pte is removed and then restart fault handling. + */ + BUG_ON(!migration); + entry = make_migration_entry(page, pte_write(pteval)); } set_pte_at(mm, address, pte, swp_entry_to_pte(entry)); BUG_ON(pte_file(*pte)); diff --git a/mm/swapfile.c b/mm/swapfile.c index 47a6812f5f8..e3b1362372c 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -395,6 +395,9 @@ void free_swap_and_cache(swp_entry_t entry) struct swap_info_struct * p; struct page *page = NULL; + if (is_migration_entry(entry)) + return; + p = swap_info_get(entry); if (p) { if (swap_entry_free(p, swp_offset(entry)) == 1) { @@ -1400,19 +1403,7 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags) if (!(p->flags & SWP_USED)) break; error = -EPERM; - /* - * Test if adding another swap device is possible. There are - * two limiting factors: 1) the number of bits for the swap - * type swp_entry_t definition and 2) the number of bits for - * the swap type in the swap ptes as defined by the different - * architectures. To honor both limitations a swap entry - * with swap offset 0 and swap type ~0UL is created, encoded - * to a swap pte, decoded to a swp_entry_t again and finally - * the swap type part is extracted. This will mask all bits - * from the initial ~0UL that can't be encoded in either the - * swp_entry_t or the architecture definition of a swap pte. - */ - if (type > swp_type(pte_to_swp_entry(swp_entry_to_pte(swp_entry(~0UL,0))))) { + if (type >= MAX_SWAPFILES) { spin_unlock(&swap_lock); goto out; } @@ -1702,6 +1693,9 @@ int swap_duplicate(swp_entry_t entry) unsigned long offset, type; int result = 0; + if (is_migration_entry(entry)) + return 1; + type = swp_type(entry); if (type >= nr_swapfiles) goto bad_file; -- cgit v1.2.3 From d75a0fcda2cfc71b50e16dc89e0c32c57d427e85 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Fri, 23 Jun 2006 02:03:36 -0700 Subject: [PATCH] Swapless page migration: rip out swap based logic Rip the page migration logic out. Remove all code that has to do with swapping during page migration. This also guts the ability to migrate pages to swap. No one used that so lets let it go for good. Page migration should be a bit broken after this patch. Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/rmap.h | 1 - mm/migrate.c | 75 +++------------------------------------------------- mm/rmap.c | 38 -------------------------- mm/swapfile.c | 9 ------- 4 files changed, 3 insertions(+), 120 deletions(-) diff --git a/include/linux/rmap.h b/include/linux/rmap.h index 2d4c81a220d..bf97b090001 100644 --- a/include/linux/rmap.h +++ b/include/linux/rmap.h @@ -91,7 +91,6 @@ static inline void page_dup_rmap(struct page *page) */ int page_referenced(struct page *, int is_locked); int try_to_unmap(struct page *, int ignore_refs); -void remove_from_swap(struct page *page); /* * Called from mm/filemap_xip.c to unmap empty zero page diff --git a/mm/migrate.c b/mm/migrate.c index 0a011e421bb..81721a061d5 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -70,10 +70,6 @@ int isolate_lru_page(struct page *page, struct list_head *pagelist) */ int migrate_prep(void) { - /* Must have swap device for migration */ - if (nr_swap_pages <= 0) - return -ENODEV; - /* * Clear the LRU lists so pages can be isolated. * Note that pages may be moved off the LRU after we have @@ -245,52 +241,6 @@ out: pte_unmap_unlock(ptep, ptl); } -/* - * swapout a single page - * page is locked upon entry, unlocked on exit - */ -static int swap_page(struct page *page) -{ - struct address_space *mapping = page_mapping(page); - - if (page_mapped(page) && mapping) - if (try_to_unmap(page, 1) != SWAP_SUCCESS) - goto unlock_retry; - - if (PageDirty(page)) { - /* Page is dirty, try to write it out here */ - switch(pageout(page, mapping)) { - case PAGE_KEEP: - case PAGE_ACTIVATE: - goto unlock_retry; - - case PAGE_SUCCESS: - goto retry; - - case PAGE_CLEAN: - ; /* try to free the page below */ - } - } - - if (PagePrivate(page)) { - if (!try_to_release_page(page, GFP_KERNEL) || - (!mapping && page_count(page) == 1)) - goto unlock_retry; - } - - if (remove_mapping(mapping, page)) { - /* Success */ - unlock_page(page); - return 0; - } - -unlock_retry: - unlock_page(page); - -retry: - return -EAGAIN; -} - /* * Replace the page in the mapping. * @@ -517,8 +467,7 @@ static int fallback_migrate_page(struct address_space *mapping, * Two lists are passed to this function. The first list * contains the pages isolated from the LRU to be migrated. * The second list contains new pages that the pages isolated - * can be moved to. If the second list is NULL then all - * pages are swapped out. + * can be moved to. * * The function returns after 10 attempts or if no pages * are movable anymore because to has become empty @@ -574,29 +523,11 @@ redo: * Only wait on writeback if we have already done a pass where * we we may have triggered writeouts for lots of pages. */ - if (pass > 0) { + if (pass > 0) wait_on_page_writeback(page); - } else { + else if (PageWriteback(page)) goto unlock_page; - } - - /* - * Anonymous pages must have swap cache references otherwise - * the information contained in the page maps cannot be - * preserved. - */ - if (PageAnon(page) && !PageSwapCache(page)) { - if (!add_to_swap(page, GFP_KERNEL)) { - rc = -ENOMEM; - goto unlock_page; - } - } - - if (!to) { - rc = swap_page(page); - goto next; - } /* * Establish swap ptes for anonymous pages or destroy pte diff --git a/mm/rmap.c b/mm/rmap.c index 3b8ce86daa3..a53a10b93ec 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -205,44 +205,6 @@ out: return anon_vma; } -#ifdef CONFIG_MIGRATION -/* - * Remove an anonymous page from swap replacing the swap pte's - * through real pte's pointing to valid pages and then releasing - * the page from the swap cache. - * - * Must hold page lock on page and mmap_sem of one vma that contains - * the page. - */ -void remove_from_swap(struct page *page) -{ - struct anon_vma *anon_vma; - struct vm_area_struct *vma; - unsigned long mapping; - - if (!PageSwapCache(page)) - return; - - mapping = (unsigned long)page->mapping; - - if (!mapping || (mapping & PAGE_MAPPING_ANON) == 0) - return; - - /* - * We hold the mmap_sem lock. So no need to call page_lock_anon_vma. - */ - anon_vma = (struct anon_vma *) (mapping - PAGE_MAPPING_ANON); - spin_lock(&anon_vma->lock); - - list_for_each_entry(vma, &anon_vma->head, anon_vma_node) - remove_vma_swap(vma, page); - - spin_unlock(&anon_vma->lock); - delete_from_swap_cache(page); -} -EXPORT_SYMBOL(remove_from_swap); -#endif - /* * At what user virtual address is page expected in vma? */ diff --git a/mm/swapfile.c b/mm/swapfile.c index e3b1362372c..fbceed67a07 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -618,15 +618,6 @@ static int unuse_mm(struct mm_struct *mm, return 0; } -#ifdef CONFIG_MIGRATION -int remove_vma_swap(struct vm_area_struct *vma, struct page *page) -{ - swp_entry_t entry = { .val = page_private(page) }; - - return unuse_vma(vma, entry, page); -} -#endif - /* * Scan swap_map from current position to next entry still in use. * Recycle to start on reaching the end, returning 0 when empty. -- cgit v1.2.3 From 6c5240ae7f48c83fcaa8e24fa63e7eb09aba5651 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Fri, 23 Jun 2006 02:03:37 -0700 Subject: [PATCH] Swapless page migration: modify core logic Use the migration entries for page migration This modifies the migration code to use the new migration entries. It now becomes possible to migrate anonymous pages without having to add a swap entry. We add a couple of new functions to replace migration entries with the proper ptes. We cannot take the tree_lock for migrating anonymous pages anymore. However, we know that we hold the only remaining reference to the page when the page count reaches 1. Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/Kconfig | 4 ++-- mm/migrate.c | 53 +++++++++++++++++++++-------------------------------- 2 files changed, 23 insertions(+), 34 deletions(-) diff --git a/mm/Kconfig b/mm/Kconfig index 332f5c29b53..66e65ab3942 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -138,8 +138,8 @@ config SPLIT_PTLOCK_CPUS # config MIGRATION bool "Page migration" - def_bool y if NUMA - depends on SWAP && NUMA + def_bool y + depends on NUMA help Allows the migration of the physical location of pages of processes while the virtual addresses are not changed. This is useful for diff --git a/mm/migrate.c b/mm/migrate.c index 81721a061d5..8f91463eab4 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -254,14 +254,20 @@ static int migrate_page_move_mapping(struct address_space *mapping, { struct page **radix_pointer; + if (!mapping) { + /* Anonymous page */ + if (page_count(page) != 1) + return -EAGAIN; + return 0; + } + write_lock_irq(&mapping->tree_lock); radix_pointer = (struct page **)radix_tree_lookup_slot( &mapping->page_tree, page_index(page)); - if (!page_mapping(page) || - page_count(page) != 2 + !!PagePrivate(page) || + if (page_count(page) != 2 + !!PagePrivate(page) || *radix_pointer != page) { write_unlock_irq(&mapping->tree_lock); return -EAGAIN; @@ -271,10 +277,12 @@ static int migrate_page_move_mapping(struct address_space *mapping, * Now we know that no one else is looking at the page. */ get_page(newpage); +#ifdef CONFIG_SWAP if (PageSwapCache(page)) { SetPageSwapCache(newpage); set_page_private(newpage, page_private(page)); } +#endif *radix_pointer = newpage; __put_page(page); @@ -308,7 +316,9 @@ static void migrate_page_copy(struct page *newpage, struct page *page) set_page_dirty(newpage); } +#ifdef CONFIG_SWAP ClearPageSwapCache(page); +#endif ClearPageActive(page); ClearPagePrivate(page); set_page_private(page, 0); @@ -353,16 +363,6 @@ int migrate_page(struct address_space *mapping, return rc; migrate_page_copy(newpage, page); - - /* - * Remove auxiliary swap entries and replace - * them with real ptes. - * - * Note that a real pte entry will allow processes that are not - * waiting on the page lock to use the new page via the page tables - * before the new page is unlocked. - */ - remove_from_swap(newpage); return 0; } EXPORT_SYMBOL(migrate_page); @@ -530,23 +530,7 @@ redo: goto unlock_page; /* - * Establish swap ptes for anonymous pages or destroy pte - * maps for files. - * - * In order to reestablish file backed mappings the fault handlers - * will take the radix tree_lock which may then be used to stop - * processses from accessing this page until the new page is ready. - * - * A process accessing via a swap pte (an anonymous page) will take a - * page_lock on the old page which will block the process until the - * migration attempt is complete. At that time the PageSwapCache bit - * will be examined. If the page was migrated then the PageSwapCache - * bit will be clear and the operation to retrieve the page will be - * retried which will find the new page in the radix tree. Then a new - * direct mapping may be generated based on the radix tree contents. - * - * If the page was not migrated then the PageSwapCache bit - * is still set and the operation may continue. + * Establish migration ptes or remove ptes */ rc = -EPERM; if (try_to_unmap(page, 1) == SWAP_FAIL) @@ -569,9 +553,9 @@ redo: */ mapping = page_mapping(page); if (!mapping) - goto unlock_both; + rc = migrate_page(mapping, newpage, page); - if (mapping->a_ops->migratepage) + else if (mapping->a_ops->migratepage) /* * Most pages have a mapping and most filesystems * should provide a migration function. Anonymous @@ -584,10 +568,15 @@ redo: else rc = fallback_migrate_page(mapping, newpage, page); -unlock_both: + if (!rc) + remove_migration_ptes(page, newpage); + unlock_page(newpage); unlock_page: + if (rc) + remove_migration_ptes(page, page); + unlock_page(page); next: -- cgit v1.2.3 From 442c9137de8d769053e81d325709dca72f0b5e44 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Fri, 23 Jun 2006 02:03:38 -0700 Subject: [PATCH] More page migration: do not inc/dec rss counters If we install a migration entry then the rss not really decreases since the page is just moved somewhere else. We can save ourselves the work of decrementing and later incrementing which will just eventually cause cacheline bouncing. Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/migrate.c | 1 - mm/rmap.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/mm/migrate.c b/mm/migrate.c index 8f91463eab4..96b9546e69e 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -164,7 +164,6 @@ static void remove_migration_pte(struct vm_area_struct *vma, unsigned long addr, if (!is_migration_entry(entry) || migration_entry_to_page(entry) != old) goto out; - inc_mm_counter(mm, anon_rss); get_page(new); pte = pte_mkold(mk_pte(new, vma->vm_page_prot)); if (is_write_migration_entry(entry)) diff --git a/mm/rmap.c b/mm/rmap.c index a53a10b93ec..05d6d73a692 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -595,6 +595,7 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma, list_add(&mm->mmlist, &init_mm.mmlist); spin_unlock(&mmlist_lock); } + dec_mm_counter(mm, anon_rss); } else { /* * Store the pfn of the page in a special migration @@ -606,7 +607,6 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma, } set_pte_at(mm, address, pte, swp_entry_to_pte(entry)); BUG_ON(pte_file(*pte)); - dec_mm_counter(mm, anon_rss); } else dec_mm_counter(mm, file_rss); -- cgit v1.2.3 From 04e62a29bf157ce1edd168f2b71b533c80d13628 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Fri, 23 Jun 2006 02:03:38 -0700 Subject: [PATCH] More page migration: use migration entries for file pages This implements the use of migration entries to preserve ptes of file backed pages during migration. Processes can therefore be migrated back and forth without loosing their connection to pagecache pages. Note that we implement the migration entries only for linear mappings. Nonlinear mappings still require the unmapping of the ptes for migration. And another writepage() ugliness shows up. writepage() can drop the page lock. Therefore we have to remove migration ptes before calling writepages() in order to avoid having migration entries point to unlocked pages. Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/swap.h | 15 ------ mm/migrate.c | 127 ++++++++++++++++++++++++++++++++++++++++----------- mm/rmap.c | 11 +++++ mm/vmscan.c | 14 +++++- 4 files changed, 124 insertions(+), 43 deletions(-) diff --git a/include/linux/swap.h b/include/linux/swap.h index 7cee73ef4f1..1cf234e8df5 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -186,20 +186,6 @@ extern unsigned long shrink_all_memory(unsigned long nr_pages); extern int vm_swappiness; extern int remove_mapping(struct address_space *mapping, struct page *page); -/* possible outcome of pageout() */ -typedef enum { - /* failed to write page out, page is locked */ - PAGE_KEEP, - /* move page to the active list, page is locked */ - PAGE_ACTIVATE, - /* page has been sent to the disk successfully, page is unlocked */ - PAGE_SUCCESS, - /* page is clean and locked */ - PAGE_CLEAN, -} pageout_t; - -extern pageout_t pageout(struct page *page, struct address_space *mapping); - #ifdef CONFIG_NUMA extern int zone_reclaim_mode; extern int zone_reclaim_interval; @@ -259,7 +245,6 @@ extern int remove_exclusive_swap_page(struct page *); struct backing_dev_info; extern spinlock_t swap_lock; -extern int remove_vma_swap(struct vm_area_struct *vma, struct page *page); /* linux/mm/thrash.c */ extern struct mm_struct * swap_token_mm; diff --git a/mm/migrate.c b/mm/migrate.c index 96b9546e69e..b5000d46389 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "internal.h" @@ -123,7 +124,7 @@ static inline int is_swap_pte(pte_t pte) /* * Restore a potential migration pte to a working pte entry */ -static void remove_migration_pte(struct vm_area_struct *vma, unsigned long addr, +static void remove_migration_pte(struct vm_area_struct *vma, struct page *old, struct page *new) { struct mm_struct *mm = vma->vm_mm; @@ -133,6 +134,10 @@ static void remove_migration_pte(struct vm_area_struct *vma, unsigned long addr, pmd_t *pmd; pte_t *ptep, pte; spinlock_t *ptl; + unsigned long addr = page_address_in_vma(new, vma); + + if (addr == -EFAULT) + return; pgd = pgd_offset(mm, addr); if (!pgd_present(*pgd)) @@ -169,19 +174,47 @@ static void remove_migration_pte(struct vm_area_struct *vma, unsigned long addr, if (is_write_migration_entry(entry)) pte = pte_mkwrite(pte); set_pte_at(mm, addr, ptep, pte); - page_add_anon_rmap(new, vma, addr); + + if (PageAnon(new)) + page_add_anon_rmap(new, vma, addr); + else + page_add_file_rmap(new); + + /* No need to invalidate - it was non-present before */ + update_mmu_cache(vma, addr, pte); + lazy_mmu_prot_update(pte); + out: pte_unmap_unlock(ptep, ptl); } /* - * Get rid of all migration entries and replace them by - * references to the indicated page. - * + * Note that remove_file_migration_ptes will only work on regular mappings, + * Nonlinear mappings do not use migration entries. + */ +static void remove_file_migration_ptes(struct page *old, struct page *new) +{ + struct vm_area_struct *vma; + struct address_space *mapping = page_mapping(new); + struct prio_tree_iter iter; + pgoff_t pgoff = new->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); + + if (!mapping) + return; + + spin_lock(&mapping->i_mmap_lock); + + vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) + remove_migration_pte(vma, old, new); + + spin_unlock(&mapping->i_mmap_lock); +} + +/* * Must hold mmap_sem lock on at least one of the vmas containing * the page so that the anon_vma cannot vanish. */ -static void remove_migration_ptes(struct page *old, struct page *new) +static void remove_anon_migration_ptes(struct page *old, struct page *new) { struct anon_vma *anon_vma; struct vm_area_struct *vma; @@ -199,12 +232,23 @@ static void remove_migration_ptes(struct page *old, struct page *new) spin_lock(&anon_vma->lock); list_for_each_entry(vma, &anon_vma->head, anon_vma_node) - remove_migration_pte(vma, page_address_in_vma(new, vma), - old, new); + remove_migration_pte(vma, old, new); spin_unlock(&anon_vma->lock); } +/* + * Get rid of all migration entries and replace them by + * references to the indicated page. + */ +static void remove_migration_ptes(struct page *old, struct page *new) +{ + if (PageAnon(new)) + remove_anon_migration_ptes(old, new); + else + remove_file_migration_ptes(old, new); +} + /* * Something used the pte of a page under migration. We need to * get to the page and wait until migration is finished. @@ -424,30 +468,59 @@ int buffer_migrate_page(struct address_space *mapping, } EXPORT_SYMBOL(buffer_migrate_page); -static int fallback_migrate_page(struct address_space *mapping, - struct page *newpage, struct page *page) +/* + * Writeback a page to clean the dirty state + */ +static int writeout(struct address_space *mapping, struct page *page) { + struct writeback_control wbc = { + .sync_mode = WB_SYNC_NONE, + .nr_to_write = 1, + .range_start = 0, + .range_end = LLONG_MAX, + .nonblocking = 1, + .for_reclaim = 1 + }; + int rc; + + if (!mapping->a_ops->writepage) + /* No write method for the address space */ + return -EINVAL; + + if (!clear_page_dirty_for_io(page)) + /* Someone else already triggered a write */ + return -EAGAIN; + /* - * Default handling if a filesystem does not provide - * a migration function. We can only migrate clean - * pages so try to write out any dirty pages first. + * A dirty page may imply that the underlying filesystem has + * the page on some queue. So the page must be clean for + * migration. Writeout may mean we loose the lock and the + * page state is no longer what we checked for earlier. + * At this point we know that the migration attempt cannot + * be successful. */ - if (PageDirty(page)) { - switch (pageout(page, mapping)) { - case PAGE_KEEP: - case PAGE_ACTIVATE: - return -EAGAIN; + remove_migration_ptes(page, page); - case PAGE_SUCCESS: - /* Relock since we lost the lock */ - lock_page(page); - /* Must retry since page state may have changed */ - return -EAGAIN; + rc = mapping->a_ops->writepage(page, &wbc); + if (rc < 0) + /* I/O Error writing */ + return -EIO; - case PAGE_CLEAN: - ; /* try to migrate the page below */ - } - } + if (rc != AOP_WRITEPAGE_ACTIVATE) + /* unlocked. Relock */ + lock_page(page); + + return -EAGAIN; +} + +/* + * Default handling if a filesystem does not provide a migration function. + */ +static int fallback_migrate_page(struct address_space *mapping, + struct page *newpage, struct page *page) +{ + if (PageDirty(page)) + return writeout(mapping, page); /* * Buffers may be managed in a filesystem specific way. diff --git a/mm/rmap.c b/mm/rmap.c index 05d6d73a692..882a85826bb 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -596,6 +596,7 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma, spin_unlock(&mmlist_lock); } dec_mm_counter(mm, anon_rss); +#ifdef CONFIG_MIGRATION } else { /* * Store the pfn of the page in a special migration @@ -604,12 +605,22 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma, */ BUG_ON(!migration); entry = make_migration_entry(page, pte_write(pteval)); +#endif } set_pte_at(mm, address, pte, swp_entry_to_pte(entry)); BUG_ON(pte_file(*pte)); } else +#ifdef CONFIG_MIGRATION + if (migration) { + /* Establish migration entry for a file page */ + swp_entry_t entry; + entry = make_migration_entry(page, pte_write(pteval)); + set_pte_at(mm, address, pte, swp_entry_to_pte(entry)); + } else +#endif dec_mm_counter(mm, file_rss); + page_remove_rmap(page); page_cache_release(page); diff --git a/mm/vmscan.c b/mm/vmscan.c index bc5d4f43036..71a02e29503 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -290,11 +290,23 @@ static void handle_write_error(struct address_space *mapping, unlock_page(page); } +/* possible outcome of pageout() */ +typedef enum { + /* failed to write page out, page is locked */ + PAGE_KEEP, + /* move page to the active list, page is locked */ + PAGE_ACTIVATE, + /* page has been sent to the disk successfully, page is unlocked */ + PAGE_SUCCESS, + /* page is clean and locked */ + PAGE_CLEAN, +} pageout_t; + /* * pageout is called by shrink_page_list() for each dirty page. * Calls ->writepage(). */ -pageout_t pageout(struct page *page, struct address_space *mapping) +static pageout_t pageout(struct page *page, struct address_space *mapping) { /* * If the page is dirty, only perform writeback if that write -- cgit v1.2.3 From 8d3c138b77f195ca0eee6fb639ae73f5ea9edb6b Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Fri, 23 Jun 2006 02:03:39 -0700 Subject: [PATCH] page migration: Update documentation Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/vm/page_migration | 91 +++++++++++++++-------------------------- 1 file changed, 33 insertions(+), 58 deletions(-) diff --git a/Documentation/vm/page_migration b/Documentation/vm/page_migration index 0dd4ef30c36..0a5d5fb1885 100644 --- a/Documentation/vm/page_migration +++ b/Documentation/vm/page_migration @@ -62,15 +62,15 @@ A. In kernel use of migrate_pages() It also prevents the swapper or other scans to encounter the page. -2. Generate a list of newly allocates page. These pages will contain the +2. Generate a list of newly allocates pages. These pages will contain the contents of the pages from the first list after page migration is complete. 3. The migrate_pages() function is called which attempts to do the migration. It returns the moved pages in the list specified as the third parameter and the failed - migrations in the fourth parameter. The first parameter - will contain the pages that could still be retried. + migrations in the fourth parameter. When the function + returns the first list will contain the pages that could still be retried. 4. The leftover pages of various types are returned to the LRU using putback_to_lru_pages() or otherwise @@ -93,83 +93,58 @@ Steps: 2. Insure that writeback is complete. -3. Make sure that the page has assigned swap cache entry if - it is an anonyous page. The swap cache reference is necessary - to preserve the information contain in the page table maps while - page migration occurs. - -4. Prep the new page that we want to move to. It is locked +3. Prep the new page that we want to move to. It is locked and set to not being uptodate so that all accesses to the new page immediately lock while the move is in progress. -5. All the page table references to the page are either dropped (file - backed pages) or converted to swap references (anonymous pages). - This should decrease the reference count. +4. The new page is prepped with some settings from the old page so that + accesses to the new page will discover a page with the correct settings. + +5. All the page table references to the page are converted + to migration entries or dropped (nonlinear vmas). + This decrease the mapcount of a page. If the resulting + mapcount is not zero then we do not migrate the page. + All user space processes that attempt to access the page + will now wait on the page lock. 6. The radix tree lock is taken. This will cause all processes trying - to reestablish a pte to block on the radix tree spinlock. + to access the page via the mapping to block on the radix tree spinlock. 7. The refcount of the page is examined and we back out if references remain otherwise we know that we are the only one referencing this page. 8. The radix tree is checked and if it does not contain the pointer to this - page then we back out because someone else modified the mapping first. - -9. The mapping is checked. If the mapping is gone then a truncate action may - be in progress and we back out. - -10. The new page is prepped with some settings from the old page so that - accesses to the new page will be discovered to have the correct settings. + page then we back out because someone else modified the radix tree. -11. The radix tree is changed to point to the new page. +9. The radix tree is changed to point to the new page. -12. The reference count of the old page is dropped because the radix tree - reference is gone. +10. The reference count of the old page is dropped because the radix tree + reference is gone. A reference to the new page is established because + the new page is referenced to by the radix tree. -13. The radix tree lock is dropped. With that lookups become possible again - and other processes will move from spinning on the tree lock to sleeping on - the locked new page. +11. The radix tree lock is dropped. With that lookups in the mapping + become possible again. Processes will move from spinning on the tree_lock + to sleeping on the locked new page. -14. The page contents are copied to the new page. +12. The page contents are copied to the new page. -15. The remaining page flags are copied to the new page. +13. The remaining page flags are copied to the new page. -16. The old page flags are cleared to indicate that the page does - not use any information anymore. +14. The old page flags are cleared to indicate that the page does + not provide any information anymore. -17. Queued up writeback on the new page is triggered. +15. Queued up writeback on the new page is triggered. -18. If swap pte's were generated for the page then replace them with real - ptes. This will reenable access for processes not blocked by the page lock. +16. If migration entries were page then replace them with real ptes. Doing + so will enable access for user space processes not already waiting for + the page lock. 19. The page locks are dropped from the old and new page. - Processes waiting on the page lock can continue. + Processes waiting on the page lock will redo their page faults + and will reach the new page. 20. The new page is moved to the LRU and can be scanned by the swapper etc again. -TODO list ---------- - -- Page migration requires the use of swap handles to preserve the - information of the anonymous page table entries. This means that swap - space is reserved but never used. The maximum number of swap handles used - is determined by CHUNK_SIZE (see mm/mempolicy.c) per ongoing migration. - Reservation of pages could be avoided by having a special type of swap - handle that does not require swap space and that would only track the page - references. Something like that was proposed by Marcelo Tosatti in the - past (search for migration cache on lkml or linux-mm@kvack.org). - -- Page migration unmaps ptes for file backed pages and requires page - faults to reestablish these ptes. This could be optimized by somehow - recording the references before migration and then reestablish them later. - However, there are several locking challenges that have to be overcome - before this is possible. - -- Page migration generates read ptes for anonymous pages. Dirty page - faults are required to make the pages writable again. It may be possible - to generate a pte marked dirty if it is known that the page is dirty and - that this process has the only reference to that page. - -Christoph Lameter, March 8, 2006. +Christoph Lameter, May 8, 2006. -- cgit v1.2.3 From ddc2e812d592457747c4367fb73edcaa8e1e49ff Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Fri, 23 Jun 2006 02:03:40 -0700 Subject: [PATCH] slab: verify pointers before free Passing an invalid pointer to kfree() and kmem_cache_free() is likely to cause bad memory corruption or even take down the whole system because the bad pointer is likely reused immediately due to the per-CPU caches. Until now, we don't do any verification for this if CONFIG_DEBUG_SLAB is disabled. As suggested by Linus, add PageSlab check to page_to_cache() and page_to_slab() to verify pointers passed to kfree(). Also, move the stronger check from cache_free_debugcheck() to kmem_cache_free() to ensure the passed pointer actually belongs to the cache we're about to free the object. For page_to_cache() and page_to_slab(), the assertions should have virtually no extra cost (two instructions, no data cache pressure) and for kmem_cache_free() the overhead should be minimal. Signed-off-by: Pekka Enberg Cc: Manfred Spraul Cc: Christoph Lameter Cc: Linus Torvalds Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/slab.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index 2046da2aa46..e3260db04b9 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -592,6 +592,7 @@ static inline struct kmem_cache *page_get_cache(struct page *page) { if (unlikely(PageCompound(page))) page = (struct page *)page_private(page); + BUG_ON(!PageSlab(page)); return (struct kmem_cache *)page->lru.next; } @@ -604,6 +605,7 @@ static inline struct slab *page_get_slab(struct page *page) { if (unlikely(PageCompound(page))) page = (struct page *)page_private(page); + BUG_ON(!PageSlab(page)); return (struct slab *)page->lru.prev; } @@ -2669,15 +2671,6 @@ static void *cache_free_debugcheck(struct kmem_cache *cachep, void *objp, kfree_debugcheck(objp); page = virt_to_page(objp); - if (page_get_cache(page) != cachep) { - printk(KERN_ERR "mismatch in kmem_cache_free: expected " - "cache %p, got %p\n", - page_get_cache(page), cachep); - printk(KERN_ERR "%p is %s.\n", cachep, cachep->name); - printk(KERN_ERR "%p is %s.\n", page_get_cache(page), - page_get_cache(page)->name); - WARN_ON(1); - } slabp = page_get_slab(page); if (cachep->flags & SLAB_RED_ZONE) { @@ -3393,6 +3386,8 @@ void kmem_cache_free(struct kmem_cache *cachep, void *objp) { unsigned long flags; + BUG_ON(virt_to_cache(objp) != cachep); + local_irq_save(flags); __cache_free(cachep, objp); local_irq_restore(flags); -- cgit v1.2.3 From 30c253e6da655d73eb8bfe2adca9b8f4d82fb81e Mon Sep 17 00:00:00 2001 From: Andy Whitcroft Date: Fri, 23 Jun 2006 02:03:41 -0700 Subject: [PATCH] sparsemem: record nid during memory present Record the node id as we mark sections for instantiation. Use this nid during instantiation to direct allocations. Signed-off-by: Andy Whitcroft Cc: Mike Kravetz Cc: Dave Hansen Cc: Mel Gorman Cc: Bob Picco Cc: Jack Steiner Cc: Yasunori Goto Cc: Martin Bligh Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/mmzone.h | 5 +++++ mm/sparse.c | 22 ++++++++++++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index e82fc1a52cd..d6120fa6911 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -509,6 +509,10 @@ struct mem_section { * pages. However, it is stored with some other magic. * (see sparse.c::sparse_init_one_section()) * + * Additionally during early boot we encode node id of + * the location of the section here to guide allocation. + * (see sparse.c::memory_present()) + * * Making it a UL at least makes someone do a cast * before using it wrong. */ @@ -548,6 +552,7 @@ extern int __section_nr(struct mem_section* ms); #define SECTION_HAS_MEM_MAP (1UL<<1) #define SECTION_MAP_LAST_BIT (1UL<<2) #define SECTION_MAP_MASK (~(SECTION_MAP_LAST_BIT-1)) +#define SECTION_NID_SHIFT 2 static inline struct page *__section_mem_map_addr(struct mem_section *section) { diff --git a/mm/sparse.c b/mm/sparse.c index 100040c0dfb..e0a3fe48aa3 100644 --- a/mm/sparse.c +++ b/mm/sparse.c @@ -99,6 +99,22 @@ int __section_nr(struct mem_section* ms) return (root_nr * SECTIONS_PER_ROOT) + (ms - root); } +/* + * During early boot, before section_mem_map is used for an actual + * mem_map, we use section_mem_map to store the section's NUMA + * node. This keeps us from having to use another data structure. The + * node information is cleared just before we store the real mem_map. + */ +static inline unsigned long sparse_encode_early_nid(int nid) +{ + return (nid << SECTION_NID_SHIFT); +} + +static inline int sparse_early_nid(struct mem_section *section) +{ + return (section->section_mem_map >> SECTION_NID_SHIFT); +} + /* Record a memory area against a node. */ void memory_present(int nid, unsigned long start, unsigned long end) { @@ -113,7 +129,8 @@ void memory_present(int nid, unsigned long start, unsigned long end) ms = __nr_to_section(section); if (!ms->section_mem_map) - ms->section_mem_map = SECTION_MARKED_PRESENT; + ms->section_mem_map = sparse_encode_early_nid(nid) | + SECTION_MARKED_PRESENT; } } @@ -164,6 +181,7 @@ static int sparse_init_one_section(struct mem_section *ms, if (!valid_section(ms)) return -EINVAL; + ms->section_mem_map &= ~SECTION_MAP_MASK; ms->section_mem_map |= sparse_encode_mem_map(mem_map, pnum); return 1; @@ -172,8 +190,8 @@ static int sparse_init_one_section(struct mem_section *ms, static struct page *sparse_early_mem_map_alloc(unsigned long pnum) { struct page *map; - int nid = early_pfn_to_nid(section_nr_to_pfn(pnum)); struct mem_section *ms = __nr_to_section(pnum); + int nid = sparse_early_nid(ms); map = alloc_remap(nid, sizeof(struct page) * PAGES_PER_SECTION); if (map) -- cgit v1.2.3 From bd96b9eb7cfd6ab24ba244360a09980a720874d2 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Fri, 23 Jun 2006 02:03:42 -0700 Subject: [PATCH] mm: fix swap unused warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If CONFIG_SWAP is not defined we get: mm/vmscan.c: In function ‘remove_mapping’: mm/vmscan.c:387: warning: unused variable ‘swap’ Convert defines in swap.h into blank inline functions to fix this warning and be consistent. Signed-off-by: Con Kolivas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/swap.h | 64 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 53 insertions(+), 11 deletions(-) diff --git a/include/linux/swap.h b/include/linux/swap.h index 1cf234e8df5..f1a827a972e 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -282,18 +282,60 @@ static inline void disable_swap_token(void) #define free_pages_and_swap_cache(pages, nr) \ release_pages((pages), (nr), 0); -#define show_swap_cache_info() /*NOTHING*/ -#define free_swap_and_cache(swp) /*NOTHING*/ -#define swap_duplicate(swp) /*NOTHING*/ -#define swap_free(swp) /*NOTHING*/ -#define read_swap_cache_async(swp,vma,addr) NULL -#define lookup_swap_cache(swp) NULL -#define valid_swaphandles(swp, off) 0 +static inline void show_swap_cache_info(void) +{ +} + +static inline void free_swap_and_cache(swp_entry_t swp) +{ +} + +static inline int swap_duplicate(swp_entry_t swp) +{ + return 0; +} + +static inline void swap_free(swp_entry_t swp) +{ +} + +static inline struct page *read_swap_cache_async(swp_entry_t swp, + struct vm_area_struct *vma, unsigned long addr) +{ + return NULL; +} + +static inline struct page *lookup_swap_cache(swp_entry_t swp) +{ + return NULL; +} + +static inline int valid_swaphandles(swp_entry_t entry, unsigned long *offset) +{ + return 0; +} + #define can_share_swap_page(p) (page_mapcount(p) == 1) -#define move_to_swap_cache(p, swp) 1 -#define move_from_swap_cache(p, i, m) 1 -#define __delete_from_swap_cache(p) /*NOTHING*/ -#define delete_from_swap_cache(p) /*NOTHING*/ + +static inline int move_to_swap_cache(struct page *page, swp_entry_t entry) +{ + return 1; +} + +static inline int move_from_swap_cache(struct page *page, unsigned long index, + struct address_space *mapping) +{ + return 1; +} + +static inline void __delete_from_swap_cache(struct page *page) +{ +} + +static inline void delete_from_swap_cache(struct page *page) +{ +} + #define swap_token_default_timeout 0 static inline int remove_exclusive_swap_page(struct page *p) -- cgit v1.2.3 From 9637a5efd4fbe36164c5ce7f6a0ee68b2bf22b7f Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 23 Jun 2006 02:03:43 -0700 Subject: [PATCH] add page_mkwrite() vm_operations method Add a new VMA operation to notify a filesystem or other driver about the MMU generating a fault because userspace attempted to write to a page mapped through a read-only PTE. This facility permits the filesystem or driver to: (*) Implement storage allocation/reservation on attempted write, and so to deal with problems such as ENOSPC more gracefully (perhaps by generating SIGBUS). (*) Delay making the page writable until the contents have been written to a backing cache. This is useful for NFS/AFS when using FS-Cache/CacheFS. It permits the filesystem to have some guarantee about the state of the cache. (*) Account and limit number of dirty pages. This is one piece of the puzzle needed to make shared writable mapping work safely in FUSE. Needed by cachefs (Or is it cachefiles? Or fscache? ). At least four other groups have stated an interest in it or a desire to use the functionality it provides: FUSE, OCFS2, NTFS and JFFS2. Also, things like EXT3 really ought to use it to deal with the case of shared-writable mmap encountering ENOSPC before we permit the page to be dirtied. From: Peter Zijlstra get_user_pages(.write=1, .force=1) can generate COW hits on read-only shared mappings, this patch traps those as mkpage_write candidates and fails to handle them the old way. Signed-off-by: David Howells Cc: Miklos Szeredi Cc: Joel Becker Cc: Mark Fasheh Cc: Anton Altaparmakov Cc: David Woodhouse Cc: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/mm.h | 4 +++ mm/memory.c | 100 ++++++++++++++++++++++++++++++++++++++++------------- mm/mmap.c | 12 +++++-- mm/mprotect.c | 11 ++++-- 4 files changed, 99 insertions(+), 28 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index 697c6bf248c..3b09444121d 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -199,6 +199,10 @@ struct vm_operations_struct { void (*close)(struct vm_area_struct * area); struct page * (*nopage)(struct vm_area_struct * area, unsigned long address, int *type); int (*populate)(struct vm_area_struct * area, unsigned long address, unsigned long len, pgprot_t prot, unsigned long pgoff, int nonblock); + + /* notification that a previously read-only page is about to become + * writable, if an error is returned it will cause a SIGBUS */ + int (*page_mkwrite)(struct vm_area_struct *vma, struct page *page); #ifdef CONFIG_NUMA int (*set_policy)(struct vm_area_struct *vma, struct mempolicy *new); struct mempolicy *(*get_policy)(struct vm_area_struct *vma, diff --git a/mm/memory.c b/mm/memory.c index 11673c5d2c2..247b5c312b9 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1457,25 +1457,60 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, { struct page *old_page, *new_page; pte_t entry; - int ret = VM_FAULT_MINOR; + int reuse, ret = VM_FAULT_MINOR; old_page = vm_normal_page(vma, address, orig_pte); if (!old_page) goto gotten; - if (PageAnon(old_page) && !TestSetPageLocked(old_page)) { - int reuse = can_share_swap_page(old_page); - unlock_page(old_page); - if (reuse) { - flush_cache_page(vma, address, pte_pfn(orig_pte)); - entry = pte_mkyoung(orig_pte); - entry = maybe_mkwrite(pte_mkdirty(entry), vma); - ptep_set_access_flags(vma, address, page_table, entry, 1); - update_mmu_cache(vma, address, entry); - lazy_mmu_prot_update(entry); - ret |= VM_FAULT_WRITE; - goto unlock; + if (unlikely((vma->vm_flags & (VM_SHARED|VM_WRITE)) == + (VM_SHARED|VM_WRITE))) { + if (vma->vm_ops && vma->vm_ops->page_mkwrite) { + /* + * Notify the address space that the page is about to + * become writable so that it can prohibit this or wait + * for the page to get into an appropriate state. + * + * We do this without the lock held, so that it can + * sleep if it needs to. + */ + page_cache_get(old_page); + pte_unmap_unlock(page_table, ptl); + + if (vma->vm_ops->page_mkwrite(vma, old_page) < 0) + goto unwritable_page; + + page_cache_release(old_page); + + /* + * Since we dropped the lock we need to revalidate + * the PTE as someone else may have changed it. If + * they did, we just return, as we can count on the + * MMU to tell us if they didn't also make it writable. + */ + page_table = pte_offset_map_lock(mm, pmd, address, + &ptl); + if (!pte_same(*page_table, orig_pte)) + goto unlock; } + + reuse = 1; + } else if (PageAnon(old_page) && !TestSetPageLocked(old_page)) { + reuse = can_share_swap_page(old_page); + unlock_page(old_page); + } else { + reuse = 0; + } + + if (reuse) { + flush_cache_page(vma, address, pte_pfn(orig_pte)); + entry = pte_mkyoung(orig_pte); + entry = maybe_mkwrite(pte_mkdirty(entry), vma); + ptep_set_access_flags(vma, address, page_table, entry, 1); + update_mmu_cache(vma, address, entry); + lazy_mmu_prot_update(entry); + ret |= VM_FAULT_WRITE; + goto unlock; } /* @@ -1535,6 +1570,10 @@ oom: if (old_page) page_cache_release(old_page); return VM_FAULT_OOM; + +unwritable_page: + page_cache_release(old_page); + return VM_FAULT_SIGBUS; } /* @@ -2083,18 +2122,31 @@ retry: /* * Should we do an early C-O-W break? */ - if (write_access && !(vma->vm_flags & VM_SHARED)) { - struct page *page; + if (write_access) { + if (!(vma->vm_flags & VM_SHARED)) { + struct page *page; - if (unlikely(anon_vma_prepare(vma))) - goto oom; - page = alloc_page_vma(GFP_HIGHUSER, vma, address); - if (!page) - goto oom; - copy_user_highpage(page, new_page, address); - page_cache_release(new_page); - new_page = page; - anon = 1; + if (unlikely(anon_vma_prepare(vma))) + goto oom; + page = alloc_page_vma(GFP_HIGHUSER, vma, address); + if (!page) + goto oom; + copy_user_highpage(page, new_page, address); + page_cache_release(new_page); + new_page = page; + anon = 1; + + } else { + /* if the page will be shareable, see if the backing + * address space wants to know that the page is about + * to become writable */ + if (vma->vm_ops->page_mkwrite && + vma->vm_ops->page_mkwrite(vma, new_page) < 0 + ) { + page_cache_release(new_page); + return VM_FAULT_SIGBUS; + } + } } page_table = pte_offset_map_lock(mm, pmd, address, &ptl); diff --git a/mm/mmap.c b/mm/mmap.c index e6ee12344b1..6446c6134b0 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1065,7 +1065,8 @@ munmap_back: vma->vm_start = addr; vma->vm_end = addr + len; vma->vm_flags = vm_flags; - vma->vm_page_prot = protection_map[vm_flags & 0x0f]; + vma->vm_page_prot = protection_map[vm_flags & + (VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)]; vma->vm_pgoff = pgoff; if (file) { @@ -1089,6 +1090,12 @@ munmap_back: goto free_vma; } + /* Don't make the VMA automatically writable if it's shared, but the + * backer wishes to know when pages are first written to */ + if (vma->vm_ops && vma->vm_ops->page_mkwrite) + vma->vm_page_prot = + protection_map[vm_flags & (VM_READ|VM_WRITE|VM_EXEC)]; + /* We set VM_ACCOUNT in a shared mapping's vm_flags, to inform * shmem_zero_setup (perhaps called through /dev/zero's ->mmap) * that memory reservation must be checked; but that reservation @@ -1921,7 +1928,8 @@ unsigned long do_brk(unsigned long addr, unsigned long len) vma->vm_end = addr + len; vma->vm_pgoff = pgoff; vma->vm_flags = flags; - vma->vm_page_prot = protection_map[flags & 0x0f]; + vma->vm_page_prot = protection_map[flags & + (VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)]; vma_link(mm, vma, prev, rb_link, rb_parent); out: mm->total_vm += len >> PAGE_SHIFT; diff --git a/mm/mprotect.c b/mm/mprotect.c index 14f93e62270..638edabaff7 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c @@ -123,6 +123,7 @@ mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev, unsigned long oldflags = vma->vm_flags; long nrpages = (end - start) >> PAGE_SHIFT; unsigned long charged = 0; + unsigned int mask; pgprot_t newprot; pgoff_t pgoff; int error; @@ -149,8 +150,6 @@ mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev, } } - newprot = protection_map[newflags & 0xf]; - /* * First try to merge with previous and/or next vma. */ @@ -177,6 +176,14 @@ mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev, } success: + /* Don't make the VMA automatically writable if it's shared, but the + * backer wishes to know when pages are first written to */ + mask = VM_READ|VM_WRITE|VM_EXEC|VM_SHARED; + if (vma->vm_ops && vma->vm_ops->page_mkwrite) + mask &= ~VM_SHARED; + + newprot = protection_map[newflags & mask]; + /* * vm_flags and vm_page_prot are protected by the mmap_sem * held in write mode. -- cgit v1.2.3 From 70af7c5c6492ef6ad137dbff6c4568c73edbcaf0 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Fri, 23 Jun 2006 02:03:44 -0700 Subject: [PATCH] swapoff: use atomic_inc_not_zero() on mm_users Now that we have atomic_inc_not_zero, it's more elegant for try_to_unuse to use that on mm_users: doesn't actually matter at present, but safer to be sure that once mm_users has gone to 0, nothing raises it for an instant. Signed-off-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/swapfile.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/mm/swapfile.c b/mm/swapfile.c index fbceed67a07..f2824c3c31b 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -772,10 +772,8 @@ static int try_to_unuse(unsigned int type) while (*swap_map > 1 && !retval && (p = p->next) != &start_mm->mmlist) { mm = list_entry(p, struct mm_struct, mmlist); - if (atomic_inc_return(&mm->mm_users) == 1) { - atomic_dec(&mm->mm_users); + if (!atomic_inc_not_zero(&mm->mm_users)) continue; - } spin_unlock(&mmlist_lock); mmput(prev_mm); prev_mm = mm; -- cgit v1.2.3 From 185606fc6a120dbebffa6d06a559c20ec2b20034 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Fri, 23 Jun 2006 02:03:45 -0700 Subject: [PATCH] remove unused o_flags from do_shmat Remove the unused variable o_flags from do_shmat. Signed-off-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- ipc/shm.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/ipc/shm.c b/ipc/shm.c index 4f133d24030..fe7ae73b698 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -698,7 +698,6 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr) int err; unsigned long flags; unsigned long prot; - unsigned long o_flags; int acc_mode; void *user_addr; @@ -725,11 +724,9 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr) if (shmflg & SHM_RDONLY) { prot = PROT_READ; - o_flags = O_RDONLY; acc_mode = S_IRUGO; } else { prot = PROT_READ | PROT_WRITE; - o_flags = O_RDWR; acc_mode = S_IRUGO | S_IWUGO; } if (shmflg & SHM_EXEC) { -- cgit v1.2.3 From 668e0d8f1a02fd75f1c1e8142a6b08455914242c Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Fri, 23 Jun 2006 02:03:45 -0700 Subject: [PATCH] fix update_mmu_cache in fremap.c There are two calls to update_mmu_cache in fremap.c, both defective. The one in install_page needs to be accompanied by lazy_mmu_prot_update (some other cleanup time, move that into ia64 update_mmu_cache itself); and the one in install_file_pte should be removed since the pte is not present. Signed-off-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/fremap.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/mm/fremap.c b/mm/fremap.c index 9f381e58bf4..21b7d0cbc98 100644 --- a/mm/fremap.c +++ b/mm/fremap.c @@ -83,6 +83,7 @@ int install_page(struct mm_struct *mm, struct vm_area_struct *vma, page_add_file_rmap(page); pte_val = *pte; update_mmu_cache(vma, addr, pte_val); + lazy_mmu_prot_update(pte_val); err = 0; unlock: pte_unmap_unlock(pte, ptl); @@ -114,7 +115,13 @@ int install_file_pte(struct mm_struct *mm, struct vm_area_struct *vma, set_pte_at(mm, addr, pte, pgoff_to_pte(pgoff)); pte_val = *pte; - update_mmu_cache(vma, addr, pte_val); + /* + * We don't need to run update_mmu_cache() here because the "file pte" + * being installed by install_file_pte() is not a real pte - it's a + * non-present entry (like a swap entry), noting what file offset should + * be mapped there when there's a fault (in a non-linear vma where + * that's not obvious). + */ pte_unmap_unlock(pte, ptl); err = 0; out: -- cgit v1.2.3 From e0a42726794f71336ff4b26084d453dd597471ce Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Fri, 23 Jun 2006 02:03:46 -0700 Subject: [PATCH] mm/slab.c: fix early init assumption The SLAB bootstrap code assumes that the first two kmalloc caches created (the INDEX_AC and INDEX_L3 kmalloc caches) wont be off-slab. But due to AC and L3 structure size increase in lockdep, one of them ended up being off-slab, and subsequently crashing with: Unable to handle kernel NULL pointer dereference at 0000000000000000 RIP: [] kmem_cache_alloc+0x26/0x7d The fix is to introduce a bootstrap flag and to use it to prevent off-slab caches being created so early during bootup. (The calculation for off-slab caches is quite complex so i didnt want to complicate things with introducing yet another INDEX_ calculation, the flag approach is simpler and smaller.) Signed-off-by: Ingo Molnar Cc: Manfred Spraul Cc: Pekka Enberg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/slab.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index e3260db04b9..664c3a10acf 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -331,6 +331,8 @@ static __always_inline int index_of(const size_t size) return 0; } +static int slab_early_init = 1; + #define INDEX_AC index_of(sizeof(struct arraycache_init)) #define INDEX_L3 index_of(sizeof(struct kmem_list3)) @@ -1376,6 +1378,8 @@ void __init kmem_cache_init(void) NULL, NULL); } + slab_early_init = 0; + while (sizes->cs_size != ULONG_MAX) { /* * For performance, all the general caches are L1 aligned. @@ -2106,8 +2110,12 @@ kmem_cache_create (const char *name, size_t size, size_t align, #endif #endif - /* Determine if the slab management is 'on' or 'off' slab. */ - if (size >= (PAGE_SIZE >> 3)) + /* + * Determine if the slab management is 'on' or 'off' slab. + * (bootstrapping cannot cope with offslab caches so don't do + * it too early on.) + */ + if ((size >= (PAGE_SIZE >> 3)) && !slab_early_init) /* * Size is large, assume best to place the slab management obj * off-slab (should allow better packing of objs). -- cgit v1.2.3 From bd1e22b8e0a90f9a91e4c27db14ca15773659bf7 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 23 Jun 2006 02:03:47 -0700 Subject: [PATCH] initialise total_memory() earlier Initialise total_memory earlier in boot. Because if for some reason we run page reclaim early in boot, we don't want total_memory to be zero when we use it as a divisor. And rename total_memory to vm_total_pages to avoid naming clashes with architectures. Cc: Yasunori Goto Cc: KAMEZAWA Hiroyuki Cc: Martin Bligh Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/swap.h | 1 + mm/page_alloc.c | 6 +++--- mm/vmscan.c | 5 ++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/linux/swap.h b/include/linux/swap.h index f1a827a972e..dc3f3aa0c83 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -185,6 +185,7 @@ extern unsigned long try_to_free_pages(struct zone **, gfp_t); extern unsigned long shrink_all_memory(unsigned long nr_pages); extern int vm_swappiness; extern int remove_mapping(struct address_space *mapping, struct page *page); +extern long vm_total_pages; #ifdef CONFIG_NUMA extern int zone_reclaim_mode; diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 5af33186a25..71a0b2a23f5 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1725,9 +1725,9 @@ void __meminit build_all_zonelists(void) stop_machine_run(__build_all_zonelists, NULL, NR_CPUS); /* cpuset refresh routine should be here */ } - - printk("Built %i zonelists\n", num_online_nodes()); - + vm_total_pages = nr_free_pagecache_pages(); + printk("Built %i zonelists. Total pages: %ld\n", + num_online_nodes(), vm_total_pages); } /* diff --git a/mm/vmscan.c b/mm/vmscan.c index 71a02e29503..72babac71de 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -110,7 +110,7 @@ struct shrinker { * From 0 .. 100. Higher means more swappy. */ int vm_swappiness = 60; -static long total_memory; +long vm_total_pages; /* The total number of pages which the VM controls */ static LIST_HEAD(shrinker_list); static DECLARE_RWSEM(shrinker_rwsem); @@ -743,7 +743,7 @@ static void shrink_active_list(unsigned long nr_pages, struct zone *zone, * how much memory * is mapped. */ - mapped_ratio = (sc->nr_mapped * 100) / total_memory; + mapped_ratio = (sc->nr_mapped * 100) / vm_total_pages; /* * Now decide how much we really want to unmap some pages. The @@ -1482,7 +1482,6 @@ static int __init kswapd_init(void) pgdat->kswapd = find_task_by_pid(pid); read_unlock(&tasklist_lock); } - total_memory = nr_free_pagecache_pages(); hotcpu_notifier(cpu_callback, 0); return 0; } -- cgit v1.2.3 From 5a4d43615921575b0c8299a5407ce4836e4138fd Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Fri, 23 Jun 2006 02:03:47 -0700 Subject: [PATCH] update vm_total_pages at memory hotadd Signed-off-by: KAMEZAWA Hiroyuki Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memory_hotplug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 1b1ac3db218..841a077d5ae 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -160,6 +160,6 @@ int online_pages(unsigned long pfn, unsigned long nr_pages) if (need_zonelists_rebuild) build_all_zonelists(); - + vm_total_pages = nr_free_pagecache_pages(); return 0; } -- cgit v1.2.3 From 800590f523bf3bde9fa6c8e4d6763e4bf6a2c8ec Mon Sep 17 00:00:00 2001 From: Paul Drynoff Date: Fri, 23 Jun 2006 02:03:48 -0700 Subject: [PATCH] slab: kmalloc, kzalloc comments cleanup and fix - Move comments for kmalloc to right place, currently it near __do_kmalloc - Comments for kzalloc - More detailed comments for kmalloc - Appearance of "kmalloc" and "kzalloc" man pages after "make mandocs" [rdunlap@xenotime.net: simplification] Signed-off-by: Paul Drynoff Acked-by: Randy Dunlap Cc: Pekka Enberg Cc: Manfred Spraul Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/DocBook/kernel-api.tmpl | 1 + include/linux/slab.h | 50 +++++++++++++++++++++++++++++++++++ mm/slab.c | 20 ++------------ 3 files changed, 53 insertions(+), 18 deletions(-) diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl index ca02e04a906..6dab3dd3699 100644 --- a/Documentation/DocBook/kernel-api.tmpl +++ b/Documentation/DocBook/kernel-api.tmpl @@ -117,6 +117,7 @@ X!Ilib/string.c Memory Management in Linux The Slab Cache +!Iinclude/linux/slab.h !Emm/slab.c User Space Memory Access diff --git a/include/linux/slab.h b/include/linux/slab.h index 9dc93163e06..45ad55b70d1 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -86,6 +86,51 @@ extern void *__kmalloc_track_caller(size_t, gfp_t, void*); __kmalloc_track_caller(size, flags, __builtin_return_address(0)) #endif +/** + * kmalloc - allocate memory + * @size: how many bytes of memory are required. + * @flags: the type of memory to allocate. + * + * kmalloc is the normal method of allocating memory + * in the kernel. + * + * The @flags argument may be one of: + * + * %GFP_USER - Allocate memory on behalf of user. May sleep. + * + * %GFP_KERNEL - Allocate normal kernel ram. May sleep. + * + * %GFP_ATOMIC - Allocation will not sleep. + * For example, use this inside interrupt handlers. + * + * %GFP_HIGHUSER - Allocate pages from high memory. + * + * %GFP_NOIO - Do not do any I/O at all while trying to get memory. + * + * %GFP_NOFS - Do not make any fs calls while trying to get memory. + * + * Also it is possible to set different flags by OR'ing + * in one or more of the following additional @flags: + * + * %__GFP_COLD - Request cache-cold pages instead of + * trying to return cache-warm pages. + * + * %__GFP_DMA - Request memory from the DMA-capable zone. + * + * %__GFP_HIGH - This allocation has high priority and may use emergency pools. + * + * %__GFP_HIGHMEM - Allocated memory may be from highmem. + * + * %__GFP_NOFAIL - Indicate that this allocation is in no way allowed to fail + * (think twice before using). + * + * %__GFP_NORETRY - If memory is not immediately available, + * then give up at once. + * + * %__GFP_NOWARN - If allocation fails, don't issue any warnings. + * + * %__GFP_REPEAT - If allocation fails initially, try once more before failing. + */ static inline void *kmalloc(size_t size, gfp_t flags) { if (__builtin_constant_p(size)) { @@ -111,6 +156,11 @@ found: extern void *__kzalloc(size_t, gfp_t); +/** + * kzalloc - allocate memory. The memory is set to zero. + * @size: how many bytes of memory are required. + * @flags: the type of memory to allocate (see kmalloc). + */ static inline void *kzalloc(size_t size, gfp_t flags) { if (__builtin_constant_p(size)) { diff --git a/mm/slab.c b/mm/slab.c index 664c3a10acf..98ac20bc0de 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -3277,26 +3277,10 @@ EXPORT_SYMBOL(kmalloc_node); #endif /** - * kmalloc - allocate memory + * __do_kmalloc - allocate memory * @size: how many bytes of memory are required. - * @flags: the type of memory to allocate. + * @flags: the type of memory to allocate (see kmalloc). * @caller: function caller for debug tracking of the caller - * - * kmalloc is the normal method of allocating memory - * in the kernel. - * - * The @flags argument may be one of: - * - * %GFP_USER - Allocate memory on behalf of user. May sleep. - * - * %GFP_KERNEL - Allocate normal kernel ram. May sleep. - * - * %GFP_ATOMIC - Allocation will not sleep. Use inside interrupt handlers. - * - * Additionally, the %GFP_DMA flag may be set to indicate the memory - * must be suitable for DMA. This can mean different things on different - * platforms. For example, on i386, it means that the memory must come - * from the first 16MB. */ static __always_inline void *__do_kmalloc(size_t size, gfp_t flags, void *caller) -- cgit v1.2.3 From 485bb99b49a173a22a0bbf4e189465414947ecac Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 23 Jun 2006 02:03:49 -0700 Subject: [PATCH] kernel-doc for mm/filemap.c mm/filemap.c: - add lots of kernel-doc; - fix some typos and kernel-doc errors; - drop some blank lines between function close and EXPORT_SYMBOL(); Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/filemap.c | 173 +++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 120 insertions(+), 53 deletions(-) diff --git a/mm/filemap.c b/mm/filemap.c index 3342067ca43..368678c2d53 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -171,15 +171,17 @@ static int sync_page(void *word) } /** - * filemap_fdatawrite_range - start writeback against all of a mapping's - * dirty pages that lie within the byte offsets + * __filemap_fdatawrite_range - start writeback on mapping dirty pages in range * @mapping: address space structure to write * @start: offset in bytes where the range starts * @end: offset in bytes where the range ends (inclusive) * @sync_mode: enable synchronous operation * + * Start writeback against all of a mapping's dirty pages that lie + * within the byte offsets inclusive. + * * If sync_mode is WB_SYNC_ALL then this is a "data integrity" operation, as - * opposed to a regular memory * cleansing writeback. The difference between + * opposed to a regular memory cleansing writeback. The difference between * these two operations is that if a dirty page/buffer is encountered, it must * be waited upon, and not just skipped over. */ @@ -219,7 +221,10 @@ static int filemap_fdatawrite_range(struct address_space *mapping, loff_t start, return __filemap_fdatawrite_range(mapping, start, end, WB_SYNC_ALL); } -/* +/** + * filemap_flush - mostly a non-blocking flush + * @mapping: target address_space + * * This is a mostly non-blocking flush. Not suitable for data-integrity * purposes - I/O may not be started against all dirty pages. */ @@ -229,7 +234,12 @@ int filemap_flush(struct address_space *mapping) } EXPORT_SYMBOL(filemap_flush); -/* +/** + * wait_on_page_writeback_range - wait for writeback to complete + * @mapping: target address_space + * @start: beginning page index + * @end: ending page index + * * Wait for writeback to complete against pages indexed by start->end * inclusive */ @@ -276,7 +286,13 @@ int wait_on_page_writeback_range(struct address_space *mapping, return ret; } -/* +/** + * sync_page_range - write and wait on all pages in the passed range + * @inode: target inode + * @mapping: target address_space + * @pos: beginning offset in pages to write + * @count: number of bytes to write + * * Write and wait upon all the pages in the passed range. This is a "data * integrity" operation. It waits upon in-flight writeout before starting and * waiting upon new writeout. If there was an IO error, return it. @@ -305,7 +321,13 @@ int sync_page_range(struct inode *inode, struct address_space *mapping, } EXPORT_SYMBOL(sync_page_range); -/* +/** + * sync_page_range_nolock + * @inode: target inode + * @mapping: target address_space + * @pos: beginning offset in pages to write + * @count: number of bytes to write + * * Note: Holding i_mutex across sync_page_range_nolock is not a good idea * as it forces O_SYNC writers to different parts of the same file * to be serialised right until io completion. @@ -329,10 +351,11 @@ int sync_page_range_nolock(struct inode *inode, struct address_space *mapping, EXPORT_SYMBOL(sync_page_range_nolock); /** - * filemap_fdatawait - walk the list of under-writeback pages of the given - * address space and wait for all of them. - * + * filemap_fdatawait - wait for all under-writeback pages to complete * @mapping: address space structure to wait for + * + * Walk the list of under-writeback pages of the given address space + * and wait for all of them. */ int filemap_fdatawait(struct address_space *mapping) { @@ -368,7 +391,12 @@ int filemap_write_and_wait(struct address_space *mapping) } EXPORT_SYMBOL(filemap_write_and_wait); -/* +/** + * filemap_write_and_wait_range - write out & wait on a file range + * @mapping: the address_space for the pages + * @lstart: offset in bytes where the range starts + * @lend: offset in bytes where the range ends (inclusive) + * * Write out and wait upon file offsets lstart->lend, inclusive. * * Note that `lend' is inclusive (describes the last byte to be written) so @@ -394,8 +422,14 @@ int filemap_write_and_wait_range(struct address_space *mapping, return err; } -/* - * This function is used to add newly allocated pagecache pages: +/** + * add_to_page_cache - add newly allocated pagecache pages + * @page: page to add + * @mapping: the page's address_space + * @offset: page index + * @gfp_mask: page allocation mode + * + * This function is used to add newly allocated pagecache pages; * the page is new, so we can just run SetPageLocked() against it. * The other page state flags were set by rmqueue(). * @@ -422,7 +456,6 @@ int add_to_page_cache(struct page *page, struct address_space *mapping, } return error; } - EXPORT_SYMBOL(add_to_page_cache); int add_to_page_cache_lru(struct page *page, struct address_space *mapping, @@ -489,8 +522,7 @@ void fastcall wait_on_page_bit(struct page *page, int bit_nr) EXPORT_SYMBOL(wait_on_page_bit); /** - * unlock_page() - unlock a locked page - * + * unlock_page - unlock a locked page * @page: the page * * Unlocks the page and wakes up sleepers in ___wait_on_page_locked(). @@ -513,8 +545,9 @@ void fastcall unlock_page(struct page *page) } EXPORT_SYMBOL(unlock_page); -/* - * End writeback against a page. +/** + * end_page_writeback - end writeback against a page + * @page: the page */ void end_page_writeback(struct page *page) { @@ -527,10 +560,11 @@ void end_page_writeback(struct page *page) } EXPORT_SYMBOL(end_page_writeback); -/* - * Get a lock on the page, assuming we need to sleep to get it. +/** + * __lock_page - get a lock on the page, assuming we need to sleep to get it + * @page: the page to lock * - * Ugly: running sync_page() in state TASK_UNINTERRUPTIBLE is scary. If some + * Ugly. Running sync_page() in state TASK_UNINTERRUPTIBLE is scary. If some * random driver's requestfn sets TASK_RUNNING, we could busywait. However * chances are that on the second loop, the block layer's plug list is empty, * so sync_page() will then return in state TASK_UNINTERRUPTIBLE. @@ -544,8 +578,12 @@ void fastcall __lock_page(struct page *page) } EXPORT_SYMBOL(__lock_page); -/* - * a rather lightweight function, finding and getting a reference to a +/** + * find_get_page - find and get a page reference + * @mapping: the address_space to search + * @offset: the page index + * + * A rather lightweight function, finding and getting a reference to a * hashed page atomically. */ struct page * find_get_page(struct address_space *mapping, unsigned long offset) @@ -559,11 +597,14 @@ struct page * find_get_page(struct address_space *mapping, unsigned long offset) read_unlock_irq(&mapping->tree_lock); return page; } - EXPORT_SYMBOL(find_get_page); -/* - * Same as above, but trylock it instead of incrementing the count. +/** + * find_trylock_page - find and lock a page + * @mapping: the address_space to search + * @offset: the page index + * + * Same as find_get_page(), but trylock it instead of incrementing the count. */ struct page *find_trylock_page(struct address_space *mapping, unsigned long offset) { @@ -576,12 +617,10 @@ struct page *find_trylock_page(struct address_space *mapping, unsigned long offs read_unlock_irq(&mapping->tree_lock); return page; } - EXPORT_SYMBOL(find_trylock_page); /** * find_lock_page - locate, pin and lock a pagecache page - * * @mapping: the address_space to search * @offset: the page index * @@ -617,12 +656,10 @@ repeat: read_unlock_irq(&mapping->tree_lock); return page; } - EXPORT_SYMBOL(find_lock_page); /** * find_or_create_page - locate or add a pagecache page - * * @mapping: the page's address_space * @index: the page's index into the mapping * @gfp_mask: page allocation mode @@ -663,7 +700,6 @@ repeat: page_cache_release(cached_page); return page; } - EXPORT_SYMBOL(find_or_create_page); /** @@ -729,9 +765,16 @@ unsigned find_get_pages_contig(struct address_space *mapping, pgoff_t index, return i; } -/* +/** + * find_get_pages_tag - find and return pages that match @tag + * @mapping: the address_space to search + * @index: the starting page index + * @tag: the tag index + * @nr_pages: the maximum number of pages + * @pages: where the resulting pages are placed + * * Like find_get_pages, except we only return pages which are tagged with - * `tag'. We update *index to index the next page for the traversal. + * @tag. We update @index to index the next page for the traversal. */ unsigned find_get_pages_tag(struct address_space *mapping, pgoff_t *index, int tag, unsigned int nr_pages, struct page **pages) @@ -750,7 +793,11 @@ unsigned find_get_pages_tag(struct address_space *mapping, pgoff_t *index, return ret; } -/* +/** + * grab_cache_page_nowait - returns locked page at given index in given cache + * @mapping: target address_space + * @index: the page index + * * Same as grab_cache_page, but do not wait if the page is unavailable. * This is intended for speculative data generators, where the data can * be regenerated if the page couldn't be grabbed. This routine should @@ -779,19 +826,25 @@ grab_cache_page_nowait(struct address_space *mapping, unsigned long index) } return page; } - EXPORT_SYMBOL(grab_cache_page_nowait); -/* +/** + * do_generic_mapping_read - generic file read routine + * @mapping: address_space to be read + * @_ra: file's readahead state + * @filp: the file to read + * @ppos: current file position + * @desc: read_descriptor + * @actor: read method + * * This is a generic file read routine, and uses the - * mapping->a_ops->readpage() function for the actual low-level - * stuff. + * mapping->a_ops->readpage() function for the actual low-level stuff. * * This is really ugly. But the goto's actually try to clarify some * of the logic when it comes to error handling etc. * - * Note the struct file* is only passed for the use of readpage. It may be - * NULL. + * Note the struct file* is only passed for the use of readpage. + * It may be NULL. */ void do_generic_mapping_read(struct address_space *mapping, struct file_ra_state *_ra, @@ -1004,7 +1057,6 @@ out: if (filp) file_accessed(filp); } - EXPORT_SYMBOL(do_generic_mapping_read); int file_read_actor(read_descriptor_t *desc, struct page *page, @@ -1045,7 +1097,13 @@ success: return size; } -/* +/** + * __generic_file_aio_read - generic filesystem read routine + * @iocb: kernel I/O control block + * @iov: io vector request + * @nr_segs: number of segments in the iovec + * @ppos: current file position + * * This is the "read()" routine for all filesystems * that can use the page cache directly. */ @@ -1124,7 +1182,6 @@ __generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov, out: return retval; } - EXPORT_SYMBOL(__generic_file_aio_read); ssize_t @@ -1135,7 +1192,6 @@ generic_file_aio_read(struct kiocb *iocb, char __user *buf, size_t count, loff_t BUG_ON(iocb->ki_pos != pos); return __generic_file_aio_read(iocb, &local_iov, 1, &iocb->ki_pos); } - EXPORT_SYMBOL(generic_file_aio_read); ssize_t @@ -1151,7 +1207,6 @@ generic_file_read(struct file *filp, char __user *buf, size_t count, loff_t *ppo ret = wait_on_sync_kiocb(&kiocb); return ret; } - EXPORT_SYMBOL(generic_file_read); int file_send_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size) @@ -1192,7 +1247,6 @@ ssize_t generic_file_sendfile(struct file *in_file, loff_t *ppos, return desc.written; return desc.error; } - EXPORT_SYMBOL(generic_file_sendfile); static ssize_t @@ -1228,11 +1282,15 @@ asmlinkage ssize_t sys_readahead(int fd, loff_t offset, size_t count) } #ifdef CONFIG_MMU -/* +static int FASTCALL(page_cache_read(struct file * file, unsigned long offset)); +/** + * page_cache_read - adds requested page to the page cache if not already there + * @file: file to read + * @offset: page index + * * This adds the requested page to the page cache if it isn't already there, * and schedules an I/O to read in its contents from disk. */ -static int FASTCALL(page_cache_read(struct file * file, unsigned long offset)); static int fastcall page_cache_read(struct file * file, unsigned long offset) { struct address_space *mapping = file->f_mapping; @@ -1259,7 +1317,12 @@ static int fastcall page_cache_read(struct file * file, unsigned long offset) #define MMAP_LOTSAMISS (100) -/* +/** + * filemap_nopage - read in file data for page fault handling + * @area: the applicable vm_area + * @address: target address to read in + * @type: returned with VM_FAULT_{MINOR,MAJOR} if not %NULL + * * filemap_nopage() is invoked via the vma operations vector for a * mapped memory region to read in file data during a page fault. * @@ -1462,7 +1525,6 @@ page_not_uptodate: page_cache_release(page); return NULL; } - EXPORT_SYMBOL(filemap_nopage); static struct page * filemap_getpage(struct file *file, unsigned long pgoff, @@ -1716,7 +1778,13 @@ repeat: return page; } -/* +/** + * read_cache_page - read into page cache, fill it if needed + * @mapping: the page's address_space + * @index: the page index + * @filler: function to perform the read + * @data: destination for read data + * * Read into the page cache. If a page already exists, * and PageUptodate() is not set, try to fill the page. */ @@ -1754,7 +1822,6 @@ retry: out: return page; } - EXPORT_SYMBOL(read_cache_page); /* @@ -1854,7 +1921,7 @@ __filemap_copy_from_user_iovec(char *vaddr, /* * Performs necessary checks before doing a write * - * Can adjust writing position aor amount of bytes to write. + * Can adjust writing position or amount of bytes to write. * Returns appropriate error code that caller should return or * zero in case that write should be allowed. */ -- cgit v1.2.3 From d501e62bc7796e90b0312648e23ac39490dfbf87 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Fri, 23 Jun 2006 02:03:50 -0700 Subject: [PATCH] Delete unused definitions of kvaddr_to_nid Signed-off-by: Ralf Baechle Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-mips/mmzone.h | 1 - include/asm-parisc/mmzone.h | 5 ----- include/asm-x86_64/mmzone.h | 1 - 3 files changed, 7 deletions(-) diff --git a/include/asm-mips/mmzone.h b/include/asm-mips/mmzone.h index dc231c89bef..f53ec54c92f 100644 --- a/include/asm-mips/mmzone.h +++ b/include/asm-mips/mmzone.h @@ -10,7 +10,6 @@ #ifdef CONFIG_DISCONTIGMEM -#define kvaddr_to_nid(kvaddr) pa_to_nid(__pa(kvaddr)) #define pfn_to_nid(pfn) pa_to_nid((pfn) << PAGE_SHIFT) #endif /* CONFIG_DISCONTIGMEM */ diff --git a/include/asm-parisc/mmzone.h b/include/asm-parisc/mmzone.h index ceb9b73199d..c87813662d4 100644 --- a/include/asm-parisc/mmzone.h +++ b/include/asm-parisc/mmzone.h @@ -14,11 +14,6 @@ extern struct node_map_data node_data[]; #define NODE_DATA(nid) (&node_data[nid].pg_data) -/* - * Given a kernel address, find the home node of the underlying memory. - */ -#define kvaddr_to_nid(kaddr) pfn_to_nid(__pa(kaddr) >> PAGE_SHIFT) - #define node_start_pfn(nid) (NODE_DATA(nid)->node_start_pfn) #define node_end_pfn(nid) \ ({ \ diff --git a/include/asm-x86_64/mmzone.h b/include/asm-x86_64/mmzone.h index 70bb9969766..c38ebdf6f42 100644 --- a/include/asm-x86_64/mmzone.h +++ b/include/asm-x86_64/mmzone.h @@ -42,7 +42,6 @@ static inline __attribute__((pure)) int phys_to_nid(unsigned long addr) #ifdef CONFIG_DISCONTIGMEM #define pfn_to_nid(pfn) phys_to_nid((unsigned long)(pfn) << PAGE_SHIFT) -#define kvaddr_to_nid(kaddr) phys_to_nid(__pa(kaddr)) extern int pfn_valid(unsigned long pfn); #endif -- cgit v1.2.3 From 8f9de51a4a98ba32f839903b7d009788bc2c295d Mon Sep 17 00:00:00 2001 From: Kirill Korotaev Date: Fri, 23 Jun 2006 02:03:50 -0700 Subject: [PATCH] printk() should not be called under zone->lock This patch fixes printk() under zone->lock in show_free_areas(). It can be unsafe to call printk() under this lock, since caller can try to allocate/free some memory and selfdeadlock on this lock. I found allocations/freeing mem both in netconsole and serial console. This issue was faced in reallity when meminfo was periodically printed for debug purposes and netconsole was used. Signed-off-by: Kirill Korotaev Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/page_alloc.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 71a0b2a23f5..423db0db7c0 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1491,7 +1491,7 @@ void show_free_areas(void) } for_each_zone(zone) { - unsigned long nr, flags, order, total = 0; + unsigned long nr[MAX_ORDER], flags, order, total = 0; show_node(zone); printk("%s: ", zone->name); @@ -1502,11 +1502,12 @@ void show_free_areas(void) spin_lock_irqsave(&zone->lock, flags); for (order = 0; order < MAX_ORDER; order++) { - nr = zone->free_area[order].nr_free; - total += nr << order; - printk("%lu*%lukB ", nr, K(1UL) << order); + nr[order] = zone->free_area[order].nr_free; + total += nr[order] << order; } spin_unlock_irqrestore(&zone->lock, flags); + for (order = 0; order < MAX_ORDER; order++) + printk("%lu*%lukB ", nr[order], K(1UL) << order); printk("= %lukB\n", K(total)); } -- cgit v1.2.3 From e24f0b8f76cc3dd96f36f5b6a9f020f6c3fce198 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Fri, 23 Jun 2006 02:03:51 -0700 Subject: [PATCH] page migration: simplify migrate_pages() Currently migrate_pages() is mess with lots of goto. Extract two functions from migrate_pages() and get rid of the gotos. Plus we can just unconditionally set the locked bit on the new page since we are the only one holding a reference. Locking is to stop others from accessing the page once we establish references to the new page. Remove the list_del from move_to_lru in order to have finer control over list processing. [akpm@osdl.org: add debug check] Signed-off-by: Christoph Lameter Cc: Hugh Dickins Cc: Jes Sorensen Cc: KAMEZAWA Hiroyuki Cc: Lee Schermerhorn Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/migrate.c | 218 +++++++++++++++++++++++++++++++---------------------------- 1 file changed, 115 insertions(+), 103 deletions(-) diff --git a/mm/migrate.c b/mm/migrate.c index b5000d46389..09038163bfe 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -84,7 +84,6 @@ int migrate_prep(void) static inline void move_to_lru(struct page *page) { - list_del(&page->lru); if (PageActive(page)) { /* * lru_cache_add_active checks that @@ -110,6 +109,7 @@ int putback_lru_pages(struct list_head *l) int count = 0; list_for_each_entry_safe(page, page2, l, lru) { + list_del(&page->lru); move_to_lru(page); count++; } @@ -533,12 +533,109 @@ static int fallback_migrate_page(struct address_space *mapping, return migrate_page(mapping, newpage, page); } +/* + * Move a page to a newly allocated page + * The page is locked and all ptes have been successfully removed. + * + * The new page will have replaced the old page if this function + * is successful. + */ +static int move_to_new_page(struct page *newpage, struct page *page) +{ + struct address_space *mapping; + int rc; + + /* + * Block others from accessing the page when we get around to + * establishing additional references. We are the only one + * holding a reference to the new page at this point. + */ + if (TestSetPageLocked(newpage)) + BUG(); + + /* Prepare mapping for the new page.*/ + newpage->index = page->index; + newpage->mapping = page->mapping; + + mapping = page_mapping(page); + if (!mapping) + rc = migrate_page(mapping, newpage, page); + else if (mapping->a_ops->migratepage) + /* + * Most pages have a mapping and most filesystems + * should provide a migration function. Anonymous + * pages are part of swap space which also has its + * own migration function. This is the most common + * path for page migration. + */ + rc = mapping->a_ops->migratepage(mapping, + newpage, page); + else + rc = fallback_migrate_page(mapping, newpage, page); + + if (!rc) + remove_migration_ptes(page, newpage); + else + newpage->mapping = NULL; + + unlock_page(newpage); + + return rc; +} + +/* + * Obtain the lock on page, remove all ptes and migrate the page + * to the newly allocated page in newpage. + */ +static int unmap_and_move(struct page *newpage, struct page *page, int force) +{ + int rc = 0; + + if (page_count(page) == 1) + /* page was freed from under us. So we are done. */ + goto ret; + + rc = -EAGAIN; + if (TestSetPageLocked(page)) { + if (!force) + goto ret; + lock_page(page); + } + + if (PageWriteback(page)) { + if (!force) + goto unlock; + wait_on_page_writeback(page); + } + + /* + * Establish migration ptes or remove ptes + */ + if (try_to_unmap(page, 1) != SWAP_FAIL) { + if (!page_mapped(page)) + rc = move_to_new_page(newpage, page); + } else + /* A vma has VM_LOCKED set -> permanent failure */ + rc = -EPERM; + + if (rc) + remove_migration_ptes(page, page); +unlock: + unlock_page(page); +ret: + if (rc != -EAGAIN) { + list_del(&newpage->lru); + move_to_lru(newpage); + } + return rc; +} + /* * migrate_pages * * Two lists are passed to this function. The first list * contains the pages isolated from the LRU to be migrated. - * The second list contains new pages that the pages isolated + * The second list contains new pages that the isolated pages * can be moved to. * * The function returns after 10 attempts or if no pages @@ -550,7 +647,7 @@ static int fallback_migrate_page(struct address_space *mapping, int migrate_pages(struct list_head *from, struct list_head *to, struct list_head *moved, struct list_head *failed) { - int retry; + int retry = 1; int nr_failed = 0; int pass = 0; struct page *page; @@ -561,118 +658,33 @@ int migrate_pages(struct list_head *from, struct list_head *to, if (!swapwrite) current->flags |= PF_SWAPWRITE; -redo: - retry = 0; - - list_for_each_entry_safe(page, page2, from, lru) { - struct page *newpage = NULL; - struct address_space *mapping; - - cond_resched(); - - rc = 0; - if (page_count(page) == 1) - /* page was freed from under us. So we are done. */ - goto next; - - if (to && list_empty(to)) - break; - - /* - * Skip locked pages during the first two passes to give the - * functions holding the lock time to release the page. Later we - * use lock_page() to have a higher chance of acquiring the - * lock. - */ - rc = -EAGAIN; - if (pass > 2) - lock_page(page); - else - if (TestSetPageLocked(page)) - goto next; - - /* - * Only wait on writeback if we have already done a pass where - * we we may have triggered writeouts for lots of pages. - */ - if (pass > 0) - wait_on_page_writeback(page); - else - if (PageWriteback(page)) - goto unlock_page; - - /* - * Establish migration ptes or remove ptes - */ - rc = -EPERM; - if (try_to_unmap(page, 1) == SWAP_FAIL) - /* A vma has VM_LOCKED set -> permanent failure */ - goto unlock_page; + for(pass = 0; pass < 10 && retry; pass++) { + retry = 0; - rc = -EAGAIN; - if (page_mapped(page)) - goto unlock_page; + list_for_each_entry_safe(page, page2, from, lru) { - newpage = lru_to_page(to); - lock_page(newpage); - /* Prepare mapping for the new page.*/ - newpage->index = page->index; - newpage->mapping = page->mapping; + if (list_empty(to)) + break; - /* - * Pages are properly locked and writeback is complete. - * Try to migrate the page. - */ - mapping = page_mapping(page); - if (!mapping) - rc = migrate_page(mapping, newpage, page); + cond_resched(); - else if (mapping->a_ops->migratepage) - /* - * Most pages have a mapping and most filesystems - * should provide a migration function. Anonymous - * pages are part of swap space which also has its - * own migration function. This is the most common - * path for page migration. - */ - rc = mapping->a_ops->migratepage(mapping, - newpage, page); - else - rc = fallback_migrate_page(mapping, newpage, page); - - if (!rc) - remove_migration_ptes(page, newpage); - - unlock_page(newpage); - -unlock_page: - if (rc) - remove_migration_ptes(page, page); + rc = unmap_and_move(lru_to_page(to), page, pass > 2); - unlock_page(page); - -next: - if (rc) { - if (newpage) - newpage->mapping = NULL; - - if (rc == -EAGAIN) + switch(rc) { + case -EAGAIN: retry++; - else { + break; + case 0: + list_move(&page->lru, moved); + break; + default: /* Permanent failure */ list_move(&page->lru, failed); nr_failed++; + break; } - } else { - if (newpage) { - /* Successful migration. Return page to LRU */ - move_to_lru(newpage); - } - list_move(&page->lru, moved); } } - if (retry && pass++ < 10) - goto redo; if (!swapwrite) current->flags &= ~PF_SWAPWRITE; -- cgit v1.2.3 From aaa994b300a172afafab47938804836b923e5ef7 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Fri, 23 Jun 2006 02:03:52 -0700 Subject: [PATCH] page migration: handle freeing of pages in migrate_pages() Do not leave pages on the lists passed to migrate_pages(). Seems that we will not need any postprocessing of pages. This will simplify the handling of pages by the callers of migrate_pages(). Signed-off-by: Christoph Lameter Cc: Hugh Dickins Cc: Jes Sorensen Cc: KAMEZAWA Hiroyuki Cc: Lee Schermerhorn Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/migrate.h | 7 +++---- mm/mempolicy.c | 8 +------- mm/migrate.c | 48 +++++++++++++++++++++++------------------------- 3 files changed, 27 insertions(+), 36 deletions(-) diff --git a/include/linux/migrate.h b/include/linux/migrate.h index 287c47b5e5d..83af25949fa 100644 --- a/include/linux/migrate.h +++ b/include/linux/migrate.h @@ -8,8 +8,7 @@ extern int isolate_lru_page(struct page *p, struct list_head *pagelist); extern int putback_lru_pages(struct list_head *l); extern int migrate_page(struct address_space *, struct page *, struct page *); -extern int migrate_pages(struct list_head *l, struct list_head *t, - struct list_head *moved, struct list_head *failed); +extern int migrate_pages(struct list_head *l, struct list_head *t); extern int migrate_pages_to(struct list_head *pagelist, struct vm_area_struct *vma, int dest); extern int fail_migrate_page(struct address_space *, @@ -22,8 +21,8 @@ extern int migrate_prep(void); static inline int isolate_lru_page(struct page *p, struct list_head *list) { return -ENOSYS; } static inline int putback_lru_pages(struct list_head *l) { return 0; } -static inline int migrate_pages(struct list_head *l, struct list_head *t, - struct list_head *moved, struct list_head *failed) { return -ENOSYS; } +static inline int migrate_pages(struct list_head *l, struct list_head *t) + { return -ENOSYS; } static inline int migrate_pages_to(struct list_head *pagelist, struct vm_area_struct *vma, int dest) { return 0; } diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 8778f58880c..244f3f130e4 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -603,11 +603,8 @@ int migrate_to_node(struct mm_struct *mm, int source, int dest, int flags) check_range(mm, mm->mmap->vm_start, TASK_SIZE, &nmask, flags | MPOL_MF_DISCONTIG_OK, &pagelist); - if (!list_empty(&pagelist)) { + if (!list_empty(&pagelist)) err = migrate_pages_to(&pagelist, NULL, dest); - if (!list_empty(&pagelist)) - putback_lru_pages(&pagelist); - } return err; } @@ -773,9 +770,6 @@ long do_mbind(unsigned long start, unsigned long len, err = -EIO; } - if (!list_empty(&pagelist)) - putback_lru_pages(&pagelist); - up_write(&mm->mmap_sem); mpol_free(new); return err; diff --git a/mm/migrate.c b/mm/migrate.c index 09038163bfe..d3a1810a4c9 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -624,6 +624,15 @@ unlock: unlock_page(page); ret: if (rc != -EAGAIN) { + /* + * A page that has been migrated has all references + * removed and will be freed. A page that has not been + * migrated will have kepts its references and be + * restored. + */ + list_del(&page->lru); + move_to_lru(page); + list_del(&newpage->lru); move_to_lru(newpage); } @@ -640,12 +649,12 @@ ret: * * The function returns after 10 attempts or if no pages * are movable anymore because to has become empty - * or no retryable pages exist anymore. + * or no retryable pages exist anymore. All pages will be + * retruned to the LRU or freed. * - * Return: Number of pages not migrated when "to" ran empty. + * Return: Number of pages not migrated. */ -int migrate_pages(struct list_head *from, struct list_head *to, - struct list_head *moved, struct list_head *failed) +int migrate_pages(struct list_head *from, struct list_head *to) { int retry = 1; int nr_failed = 0; @@ -675,11 +684,9 @@ int migrate_pages(struct list_head *from, struct list_head *to, retry++; break; case 0: - list_move(&page->lru, moved); break; default: /* Permanent failure */ - list_move(&page->lru, failed); nr_failed++; break; } @@ -689,6 +696,7 @@ int migrate_pages(struct list_head *from, struct list_head *to, if (!swapwrite) current->flags &= ~PF_SWAPWRITE; + putback_lru_pages(from); return nr_failed + retry; } @@ -702,11 +710,10 @@ int migrate_pages_to(struct list_head *pagelist, struct vm_area_struct *vma, int dest) { LIST_HEAD(newlist); - LIST_HEAD(moved); - LIST_HEAD(failed); int err = 0; unsigned long offset = 0; int nr_pages; + int nr_failed = 0; struct page *page; struct list_head *p; @@ -740,26 +747,17 @@ redo: if (nr_pages > MIGRATE_CHUNK_SIZE) break; } - err = migrate_pages(pagelist, &newlist, &moved, &failed); + err = migrate_pages(pagelist, &newlist); - putback_lru_pages(&moved); /* Call release pages instead ?? */ - - if (err >= 0 && list_empty(&newlist) && !list_empty(pagelist)) - goto redo; -out: - /* Return leftover allocated pages */ - while (!list_empty(&newlist)) { - page = list_entry(newlist.next, struct page, lru); - list_del(&page->lru); - __free_page(page); + if (err >= 0) { + nr_failed += err; + if (list_empty(&newlist) && !list_empty(pagelist)) + goto redo; } - list_splice(&failed, pagelist); - if (err < 0) - return err; +out: /* Calculate number of leftover pages */ - nr_pages = 0; list_for_each(p, pagelist) - nr_pages++; - return nr_pages; + nr_failed++; + return nr_failed; } -- cgit v1.2.3 From 95a402c3847cc16f4ba03013cd01404fa0f14c2e Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Fri, 23 Jun 2006 02:03:53 -0700 Subject: [PATCH] page migration: use allocator function for migrate_pages() Instead of passing a list of new pages, pass a function to allocate a new page. This allows the correct placement of MPOL_INTERLEAVE pages during page migration. It also further simplifies the callers of migrate pages. migrate_pages() becomes similar to migrate_pages_to() so drop migrate_pages_to(). The batching of new page allocations becomes unnecessary. Signed-off-by: Christoph Lameter Cc: Hugh Dickins Cc: Jes Sorensen Cc: KAMEZAWA Hiroyuki Cc: Lee Schermerhorn Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/migrate.h | 11 ++--- mm/mempolicy.c | 23 +++++++++- mm/migrate.c | 115 ++++++++++++++---------------------------------- 3 files changed, 59 insertions(+), 90 deletions(-) diff --git a/include/linux/migrate.h b/include/linux/migrate.h index 83af25949fa..5b95d6568dc 100644 --- a/include/linux/migrate.h +++ b/include/linux/migrate.h @@ -3,14 +3,15 @@ #include +typedef struct page *new_page_t(struct page *, unsigned long private); + #ifdef CONFIG_MIGRATION extern int isolate_lru_page(struct page *p, struct list_head *pagelist); extern int putback_lru_pages(struct list_head *l); extern int migrate_page(struct address_space *, struct page *, struct page *); -extern int migrate_pages(struct list_head *l, struct list_head *t); -extern int migrate_pages_to(struct list_head *pagelist, - struct vm_area_struct *vma, int dest); +extern int migrate_pages(struct list_head *l, new_page_t x, unsigned long); + extern int fail_migrate_page(struct address_space *, struct page *, struct page *); @@ -21,8 +22,8 @@ extern int migrate_prep(void); static inline int isolate_lru_page(struct page *p, struct list_head *list) { return -ENOSYS; } static inline int putback_lru_pages(struct list_head *l) { return 0; } -static inline int migrate_pages(struct list_head *l, struct list_head *t) - { return -ENOSYS; } +static inline int migrate_pages(struct list_head *l, new_page_t x, + unsigned long private) { return -ENOSYS; } static inline int migrate_pages_to(struct list_head *pagelist, struct vm_area_struct *vma, int dest) { return 0; } diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 244f3f130e4..f432642e9e6 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -87,6 +87,7 @@ #include #include #include +#include #include #include @@ -587,6 +588,11 @@ static void migrate_page_add(struct page *page, struct list_head *pagelist, isolate_lru_page(page, pagelist); } +static struct page *new_node_page(struct page *page, unsigned long node) +{ + return alloc_pages_node(node, GFP_HIGHUSER, 0); +} + /* * Migrate pages from one node to a target node. * Returns error or the number of pages not migrated. @@ -604,7 +610,8 @@ int migrate_to_node(struct mm_struct *mm, int source, int dest, int flags) flags | MPOL_MF_DISCONTIG_OK, &pagelist); if (!list_empty(&pagelist)) - err = migrate_pages_to(&pagelist, NULL, dest); + err = migrate_pages(&pagelist, new_node_page, dest); + return err; } @@ -691,6 +698,12 @@ int do_migrate_pages(struct mm_struct *mm, } +static struct page *new_vma_page(struct page *page, unsigned long private) +{ + struct vm_area_struct *vma = (struct vm_area_struct *)private; + + return alloc_page_vma(GFP_HIGHUSER, vma, page_address_in_vma(page, vma)); +} #else static void migrate_page_add(struct page *page, struct list_head *pagelist, @@ -703,6 +716,11 @@ int do_migrate_pages(struct mm_struct *mm, { return -ENOSYS; } + +static struct page *new_vma_page(struct page *page, unsigned long private) +{ + return NULL; +} #endif long do_mbind(unsigned long start, unsigned long len, @@ -764,7 +782,8 @@ long do_mbind(unsigned long start, unsigned long len, err = mbind_range(vma, start, end, new); if (!list_empty(&pagelist)) - nr_failed = migrate_pages_to(&pagelist, vma, -1); + nr_failed = migrate_pages(&pagelist, new_vma_page, + (unsigned long)vma); if (!err && nr_failed && (flags & MPOL_MF_STRICT)) err = -EIO; diff --git a/mm/migrate.c b/mm/migrate.c index d3a1810a4c9..251a8d15825 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -28,9 +28,6 @@ #include "internal.h" -/* The maximum number of pages to take off the LRU for migration */ -#define MIGRATE_CHUNK_SIZE 256 - #define lru_to_page(_head) (list_entry((_head)->prev, struct page, lru)) /* @@ -587,18 +584,23 @@ static int move_to_new_page(struct page *newpage, struct page *page) * Obtain the lock on page, remove all ptes and migrate the page * to the newly allocated page in newpage. */ -static int unmap_and_move(struct page *newpage, struct page *page, int force) +static int unmap_and_move(new_page_t get_new_page, unsigned long private, + struct page *page, int force) { int rc = 0; + struct page *newpage = get_new_page(page, private); + + if (!newpage) + return -ENOMEM; if (page_count(page) == 1) /* page was freed from under us. So we are done. */ - goto ret; + goto move_newpage; rc = -EAGAIN; if (TestSetPageLocked(page)) { if (!force) - goto ret; + goto move_newpage; lock_page(page); } @@ -622,7 +624,7 @@ static int unmap_and_move(struct page *newpage, struct page *page, int force) remove_migration_ptes(page, page); unlock: unlock_page(page); -ret: + if (rc != -EAGAIN) { /* * A page that has been migrated has all references @@ -632,29 +634,33 @@ ret: */ list_del(&page->lru); move_to_lru(page); - - list_del(&newpage->lru); - move_to_lru(newpage); } + +move_newpage: + /* + * Move the new page to the LRU. If migration was not successful + * then this will free the page. + */ + move_to_lru(newpage); return rc; } /* * migrate_pages * - * Two lists are passed to this function. The first list - * contains the pages isolated from the LRU to be migrated. - * The second list contains new pages that the isolated pages - * can be moved to. + * The function takes one list of pages to migrate and a function + * that determines from the page to be migrated and the private data + * the target of the move and allocates the page. * * The function returns after 10 attempts or if no pages * are movable anymore because to has become empty * or no retryable pages exist anymore. All pages will be * retruned to the LRU or freed. * - * Return: Number of pages not migrated. + * Return: Number of pages not migrated or error code. */ -int migrate_pages(struct list_head *from, struct list_head *to) +int migrate_pages(struct list_head *from, + new_page_t get_new_page, unsigned long private) { int retry = 1; int nr_failed = 0; @@ -671,15 +677,14 @@ int migrate_pages(struct list_head *from, struct list_head *to) retry = 0; list_for_each_entry_safe(page, page2, from, lru) { - - if (list_empty(to)) - break; - cond_resched(); - rc = unmap_and_move(lru_to_page(to), page, pass > 2); + rc = unmap_and_move(get_new_page, private, + page, pass > 2); switch(rc) { + case -ENOMEM: + goto out; case -EAGAIN: retry++; break; @@ -692,72 +697,16 @@ int migrate_pages(struct list_head *from, struct list_head *to) } } } - + rc = 0; +out: if (!swapwrite) current->flags &= ~PF_SWAPWRITE; putback_lru_pages(from); - return nr_failed + retry; -} -/* - * Migrate the list 'pagelist' of pages to a certain destination. - * - * Specify destination with either non-NULL vma or dest_node >= 0 - * Return the number of pages not migrated or error code - */ -int migrate_pages_to(struct list_head *pagelist, - struct vm_area_struct *vma, int dest) -{ - LIST_HEAD(newlist); - int err = 0; - unsigned long offset = 0; - int nr_pages; - int nr_failed = 0; - struct page *page; - struct list_head *p; - -redo: - nr_pages = 0; - list_for_each(p, pagelist) { - if (vma) { - /* - * The address passed to alloc_page_vma is used to - * generate the proper interleave behavior. We fake - * the address here by an increasing offset in order - * to get the proper distribution of pages. - * - * No decision has been made as to which page - * a certain old page is moved to so we cannot - * specify the correct address. - */ - page = alloc_page_vma(GFP_HIGHUSER, vma, - offset + vma->vm_start); - offset += PAGE_SIZE; - } - else - page = alloc_pages_node(dest, GFP_HIGHUSER, 0); - - if (!page) { - err = -ENOMEM; - goto out; - } - list_add_tail(&page->lru, &newlist); - nr_pages++; - if (nr_pages > MIGRATE_CHUNK_SIZE) - break; - } - err = migrate_pages(pagelist, &newlist); - - if (err >= 0) { - nr_failed += err; - if (list_empty(&newlist) && !list_empty(pagelist)) - goto redo; - } -out: + if (rc) + return rc; - /* Calculate number of leftover pages */ - list_for_each(p, pagelist) - nr_failed++; - return nr_failed; + return nr_failed + retry; } + -- cgit v1.2.3 From 742755a1d8ce2b548428f7aacf1758b4bba50080 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Fri, 23 Jun 2006 02:03:55 -0700 Subject: [PATCH] page migration: sys_move_pages(): support moving of individual pages move_pages() is used to move individual pages of a process. The function can be used to determine the location of pages and to move them onto the desired node. move_pages() returns status information for each page. long move_pages(pid, number_of_pages_to_move, addresses_of_pages[], nodes[] or NULL, status[], flags); The addresses of pages is an array of void * pointing to the pages to be moved. The nodes array contains the node numbers that the pages should be moved to. If a NULL is passed instead of an array then no pages are moved but the status array is updated. The status request may be used to determine the page state before issuing another move_pages() to move pages. The status array will contain the state of all individual page migration attempts when the function terminates. The status array is only valid if move_pages() completed successfullly. Possible page states in status[]: 0..MAX_NUMNODES The page is now on the indicated node. -ENOENT Page is not present -EACCES Page is mapped by multiple processes and can only be moved if MPOL_MF_MOVE_ALL is specified. -EPERM The page has been mlocked by a process/driver and cannot be moved. -EBUSY Page is busy and cannot be moved. Try again later. -EFAULT Invalid address (no VMA or zero page). -ENOMEM Unable to allocate memory on target node. -EIO Unable to write back page. The page must be written back in order to move it since the page is dirty and the filesystem does not provide a migration function that would allow the moving of dirty pages. -EINVAL A dirty page cannot be moved. The filesystem does not provide a migration function and has no ability to write back pages. The flags parameter indicates what types of pages to move: MPOL_MF_MOVE Move pages that are only mapped by the process. MPOL_MF_MOVE_ALL Also move pages that are mapped by multiple processes. Requires sufficient capabilities. Possible return codes from move_pages() -ENOENT No pages found that would require moving. All pages are either already on the target node, not present, had an invalid address or could not be moved because they were mapped by multiple processes. -EINVAL Flags other than MPOL_MF_MOVE(_ALL) specified or an attempt to migrate pages in a kernel thread. -EPERM MPOL_MF_MOVE_ALL specified without sufficient priviledges. or an attempt to move a process belonging to another user. -EACCES One of the target nodes is not allowed by the current cpuset. -ENODEV One of the target nodes is not online. -ESRCH Process does not exist. -E2BIG Too many pages to move. -ENOMEM Not enough memory to allocate control array. -EFAULT Parameters could not be accessed. A test program for move_pages() may be found with the patches on ftp.kernel.org:/pub/linux/kernel/people/christoph/pmig/patches-2.6.17-rc4-mm3 From: Christoph Lameter Detailed results for sys_move_pages() Pass a pointer to an integer to get_new_page() that may be used to indicate where the completion status of a migration operation should be placed. This allows sys_move_pags() to report back exactly what happened to each page. Wish there would be a better way to do this. Looks a bit hacky. Signed-off-by: Christoph Lameter Cc: Hugh Dickins Cc: Jes Sorensen Cc: KAMEZAWA Hiroyuki Cc: Lee Schermerhorn Cc: Andi Kleen Cc: Michael Kerrisk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/vm/page_migration | 29 ++--- arch/ia64/kernel/entry.S | 2 +- include/asm-ia64/unistd.h | 2 +- include/linux/migrate.h | 2 +- include/linux/syscalls.h | 5 + kernel/sys_ni.c | 1 + mm/mempolicy.c | 4 +- mm/migrate.c | 268 +++++++++++++++++++++++++++++++++++++++- 8 files changed, 288 insertions(+), 25 deletions(-) diff --git a/Documentation/vm/page_migration b/Documentation/vm/page_migration index 0a5d5fb1885..99f89aa1016 100644 --- a/Documentation/vm/page_migration +++ b/Documentation/vm/page_migration @@ -26,8 +26,13 @@ a process are located. See also the numa_maps manpage in the numactl package. Manual migration is useful if for example the scheduler has relocated a process to a processor on a distant node. A batch scheduler or an administrator may detect the situation and move the pages of the process -nearer to the new processor. At some point in the future we may have -some mechanism in the scheduler that will automatically move the pages. +nearer to the new processor. The kernel itself does only provide +manual page migration support. Automatic page migration may be implemented +through user space processes that move pages. A special function call +"move_pages" allows the moving of individual pages within a process. +A NUMA profiler may f.e. obtain a log showing frequent off node +accesses and may use the result to move pages to more advantageous +locations. Larger installations usually partition the system using cpusets into sections of nodes. Paul Jackson has equipped cpusets with the ability to @@ -62,22 +67,14 @@ A. In kernel use of migrate_pages() It also prevents the swapper or other scans to encounter the page. -2. Generate a list of newly allocates pages. These pages will contain the - contents of the pages from the first list after page migration is - complete. +2. We need to have a function of type new_page_t that can be + passed to migrate_pages(). This function should figure out + how to allocate the correct new page given the old page. 3. The migrate_pages() function is called which attempts - to do the migration. It returns the moved pages in the - list specified as the third parameter and the failed - migrations in the fourth parameter. When the function - returns the first list will contain the pages that could still be retried. - -4. The leftover pages of various types are returned - to the LRU using putback_to_lru_pages() or otherwise - disposed of. The pages will still have the refcount as - increased by isolate_lru_pages() if putback_to_lru_pages() is not - used! The kernel may want to handle the various cases of failures in - different ways. + to do the migration. It will call the function to allocate + the new page for each page that is considered for + moving. B. How migrate_pages() works ---------------------------- diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index bcb80ca5cf4..32c999f58d1 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S @@ -1584,7 +1584,7 @@ sys_call_table: data8 sys_keyctl data8 sys_ioprio_set data8 sys_ioprio_get // 1275 - data8 sys_ni_syscall + data8 sys_move_pages data8 sys_inotify_init data8 sys_inotify_add_watch data8 sys_inotify_rm_watch diff --git a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h index 632f2eedf72..bb0eb727dcd 100644 --- a/include/asm-ia64/unistd.h +++ b/include/asm-ia64/unistd.h @@ -265,7 +265,7 @@ #define __NR_keyctl 1273 #define __NR_ioprio_set 1274 #define __NR_ioprio_get 1275 -/* 1276 is available for reuse (was briefly sys_set_zone_reclaim) */ +#define __NR_move_pages 1276 #define __NR_inotify_init 1277 #define __NR_inotify_add_watch 1278 #define __NR_inotify_rm_watch 1279 diff --git a/include/linux/migrate.h b/include/linux/migrate.h index 5b95d6568dc..5dba23a1c0d 100644 --- a/include/linux/migrate.h +++ b/include/linux/migrate.h @@ -3,7 +3,7 @@ #include -typedef struct page *new_page_t(struct page *, unsigned long private); +typedef struct page *new_page_t(struct page *, unsigned long private, int **); #ifdef CONFIG_MIGRATION extern int isolate_lru_page(struct page *p, struct list_head *pagelist); diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index bd67a4413df..7e3f2349091 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -516,6 +516,11 @@ asmlinkage long sys_set_mempolicy(int mode, unsigned long __user *nmask, asmlinkage long sys_migrate_pages(pid_t pid, unsigned long maxnode, const unsigned long __user *from, const unsigned long __user *to); +asmlinkage long sys_move_pages(pid_t pid, unsigned long nr_pages, + const void __user * __user *pages, + const int __user *nodes, + int __user *status, + int flags); asmlinkage long sys_mbind(unsigned long start, unsigned long len, unsigned long mode, unsigned long __user *nmask, diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c index 5433195040f..597229749de 100644 --- a/kernel/sys_ni.c +++ b/kernel/sys_ni.c @@ -87,6 +87,7 @@ cond_syscall(sys_inotify_init); cond_syscall(sys_inotify_add_watch); cond_syscall(sys_inotify_rm_watch); cond_syscall(sys_migrate_pages); +cond_syscall(sys_move_pages); cond_syscall(sys_chown16); cond_syscall(sys_fchown16); cond_syscall(sys_getegid16); diff --git a/mm/mempolicy.c b/mm/mempolicy.c index f432642e9e6..05b84acf0bb 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -588,7 +588,7 @@ static void migrate_page_add(struct page *page, struct list_head *pagelist, isolate_lru_page(page, pagelist); } -static struct page *new_node_page(struct page *page, unsigned long node) +static struct page *new_node_page(struct page *page, unsigned long node, int **x) { return alloc_pages_node(node, GFP_HIGHUSER, 0); } @@ -698,7 +698,7 @@ int do_migrate_pages(struct mm_struct *mm, } -static struct page *new_vma_page(struct page *page, unsigned long private) +static struct page *new_vma_page(struct page *page, unsigned long private, int **x) { struct vm_area_struct *vma = (struct vm_area_struct *)private; diff --git a/mm/migrate.c b/mm/migrate.c index 251a8d15825..033a12f4c94 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include "internal.h" @@ -62,9 +64,8 @@ int isolate_lru_page(struct page *page, struct list_head *pagelist) } /* - * migrate_prep() needs to be called after we have compiled the list of pages - * to be migrated using isolate_lru_page() but before we begin a series of calls - * to migrate_pages(). + * migrate_prep() needs to be called before we start compiling a list of pages + * to be migrated using isolate_lru_page(). */ int migrate_prep(void) { @@ -588,7 +589,8 @@ static int unmap_and_move(new_page_t get_new_page, unsigned long private, struct page *page, int force) { int rc = 0; - struct page *newpage = get_new_page(page, private); + int *result = NULL; + struct page *newpage = get_new_page(page, private, &result); if (!newpage) return -ENOMEM; @@ -642,6 +644,12 @@ move_newpage: * then this will free the page. */ move_to_lru(newpage); + if (result) { + if (rc) + *result = rc; + else + *result = page_to_nid(newpage); + } return rc; } @@ -710,3 +718,255 @@ out: return nr_failed + retry; } +#ifdef CONFIG_NUMA +/* + * Move a list of individual pages + */ +struct page_to_node { + unsigned long addr; + struct page *page; + int node; + int status; +}; + +static struct page *new_page_node(struct page *p, unsigned long private, + int **result) +{ + struct page_to_node *pm = (struct page_to_node *)private; + + while (pm->node != MAX_NUMNODES && pm->page != p) + pm++; + + if (pm->node == MAX_NUMNODES) + return NULL; + + *result = &pm->status; + + return alloc_pages_node(pm->node, GFP_HIGHUSER, 0); +} + +/* + * Move a set of pages as indicated in the pm array. The addr + * field must be set to the virtual address of the page to be moved + * and the node number must contain a valid target node. + */ +static int do_move_pages(struct mm_struct *mm, struct page_to_node *pm, + int migrate_all) +{ + int err; + struct page_to_node *pp; + LIST_HEAD(pagelist); + + down_read(&mm->mmap_sem); + + /* + * Build a list of pages to migrate + */ + migrate_prep(); + for (pp = pm; pp->node != MAX_NUMNODES; pp++) { + struct vm_area_struct *vma; + struct page *page; + + /* + * A valid page pointer that will not match any of the + * pages that will be moved. + */ + pp->page = ZERO_PAGE(0); + + err = -EFAULT; + vma = find_vma(mm, pp->addr); + if (!vma) + goto set_status; + + page = follow_page(vma, pp->addr, FOLL_GET); + err = -ENOENT; + if (!page) + goto set_status; + + if (PageReserved(page)) /* Check for zero page */ + goto put_and_set; + + pp->page = page; + err = page_to_nid(page); + + if (err == pp->node) + /* + * Node already in the right place + */ + goto put_and_set; + + err = -EACCES; + if (page_mapcount(page) > 1 && + !migrate_all) + goto put_and_set; + + err = isolate_lru_page(page, &pagelist); +put_and_set: + /* + * Either remove the duplicate refcount from + * isolate_lru_page() or drop the page ref if it was + * not isolated. + */ + put_page(page); +set_status: + pp->status = err; + } + + if (!list_empty(&pagelist)) + err = migrate_pages(&pagelist, new_page_node, + (unsigned long)pm); + else + err = -ENOENT; + + up_read(&mm->mmap_sem); + return err; +} + +/* + * Determine the nodes of a list of pages. The addr in the pm array + * must have been set to the virtual address of which we want to determine + * the node number. + */ +static int do_pages_stat(struct mm_struct *mm, struct page_to_node *pm) +{ + down_read(&mm->mmap_sem); + + for ( ; pm->node != MAX_NUMNODES; pm++) { + struct vm_area_struct *vma; + struct page *page; + int err; + + err = -EFAULT; + vma = find_vma(mm, pm->addr); + if (!vma) + goto set_status; + + page = follow_page(vma, pm->addr, 0); + err = -ENOENT; + /* Use PageReserved to check for zero page */ + if (!page || PageReserved(page)) + goto set_status; + + err = page_to_nid(page); +set_status: + pm->status = err; + } + + up_read(&mm->mmap_sem); + return 0; +} + +/* + * Move a list of pages in the address space of the currently executing + * process. + */ +asmlinkage long sys_move_pages(pid_t pid, unsigned long nr_pages, + const void __user * __user *pages, + const int __user *nodes, + int __user *status, int flags) +{ + int err = 0; + int i; + struct task_struct *task; + nodemask_t task_nodes; + struct mm_struct *mm; + struct page_to_node *pm = NULL; + + /* Check flags */ + if (flags & ~(MPOL_MF_MOVE|MPOL_MF_MOVE_ALL)) + return -EINVAL; + + if ((flags & MPOL_MF_MOVE_ALL) && !capable(CAP_SYS_NICE)) + return -EPERM; + + /* Find the mm_struct */ + read_lock(&tasklist_lock); + task = pid ? find_task_by_pid(pid) : current; + if (!task) { + read_unlock(&tasklist_lock); + return -ESRCH; + } + mm = get_task_mm(task); + read_unlock(&tasklist_lock); + + if (!mm) + return -EINVAL; + + /* + * Check if this process has the right to modify the specified + * process. The right exists if the process has administrative + * capabilities, superuser privileges or the same + * userid as the target process. + */ + if ((current->euid != task->suid) && (current->euid != task->uid) && + (current->uid != task->suid) && (current->uid != task->uid) && + !capable(CAP_SYS_NICE)) { + err = -EPERM; + goto out2; + } + + task_nodes = cpuset_mems_allowed(task); + + /* Limit nr_pages so that the multiplication may not overflow */ + if (nr_pages >= ULONG_MAX / sizeof(struct page_to_node) - 1) { + err = -E2BIG; + goto out2; + } + + pm = vmalloc((nr_pages + 1) * sizeof(struct page_to_node)); + if (!pm) { + err = -ENOMEM; + goto out2; + } + + /* + * Get parameters from user space and initialize the pm + * array. Return various errors if the user did something wrong. + */ + for (i = 0; i < nr_pages; i++) { + const void *p; + + err = -EFAULT; + if (get_user(p, pages + i)) + goto out; + + pm[i].addr = (unsigned long)p; + if (nodes) { + int node; + + if (get_user(node, nodes + i)) + goto out; + + err = -ENODEV; + if (!node_online(node)) + goto out; + + err = -EACCES; + if (!node_isset(node, task_nodes)) + goto out; + + pm[i].node = node; + } + } + /* End marker */ + pm[nr_pages].node = MAX_NUMNODES; + + if (nodes) + err = do_move_pages(mm, pm, flags & MPOL_MF_MOVE_ALL); + else + err = do_pages_stat(mm, pm); + + if (err >= 0) + /* Return status information */ + for (i = 0; i < nr_pages; i++) + if (put_user(pm[i].status, status + i)) + err = -EFAULT; + +out: + vfree(pm); +out2: + mmput(mm); + return err; +} +#endif + -- cgit v1.2.3 From b63d64a324056cf3c2f7a1a1fe8134100edbb058 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Fri, 23 Jun 2006 02:03:56 -0700 Subject: [PATCH] sys_move_pages: x86_64 support sys_move_pages support for x86_64 Signed-off-by: Christoph Lameter Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-x86_64/unistd.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h index 0aff22bdbb2..94387c915e5 100644 --- a/include/asm-x86_64/unistd.h +++ b/include/asm-x86_64/unistd.h @@ -617,10 +617,12 @@ __SYSCALL(__NR_tee, sys_tee) __SYSCALL(__NR_sync_file_range, sys_sync_file_range) #define __NR_vmsplice 278 __SYSCALL(__NR_vmsplice, sys_vmsplice) +#define __NR_move_pages 279 +__SYSCALL(__NR_move_pages, sys_move_pages) #ifdef __KERNEL__ -#define __NR_syscall_max __NR_vmsplice +#define __NR_syscall_max __NR_move_pages #ifndef __NO_STUBS -- cgit v1.2.3 From 1b2db9fb7adc4d67d9ce7d16ce79c41ee84730fe Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Fri, 23 Jun 2006 02:03:56 -0700 Subject: [PATCH] sys_move_pages: 32bit support (i386, x86_64) sys_move_pages() support for 32bit (i386 plus x86_64 compat layer) Add support for move_pages() on i386 and also add the compat functions necessary to run 32 bit binaries on x86_64. Add compat_sys_move_pages to the x86_64 32bit binary layer. Note that it is not up to date so I added the missing pieces. Not sure if this is done the right way. [akpm@osdl.org: compile fix] Signed-off-by: Christoph Lameter Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/syscall_table.S | 1 + arch/x86_64/ia32/ia32entry.S | 1 + include/asm-i386/unistd.h | 3 ++- include/linux/syscalls.h | 5 +++++ kernel/compat.c | 23 +++++++++++++++++++++++ kernel/sys_ni.c | 1 + 6 files changed, 33 insertions(+), 1 deletion(-) diff --git a/arch/i386/kernel/syscall_table.S b/arch/i386/kernel/syscall_table.S index af56987f69b..dd63d477539 100644 --- a/arch/i386/kernel/syscall_table.S +++ b/arch/i386/kernel/syscall_table.S @@ -316,3 +316,4 @@ ENTRY(sys_call_table) .long sys_sync_file_range .long sys_tee /* 315 */ .long sys_vmsplice + .long sys_move_pages diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S index 5a92fed2d1d..4ec594ab1a9 100644 --- a/arch/x86_64/ia32/ia32entry.S +++ b/arch/x86_64/ia32/ia32entry.S @@ -696,4 +696,5 @@ ia32_sys_call_table: .quad sys_sync_file_range .quad sys_tee .quad compat_sys_vmsplice + .quad compat_sys_move_pages ia32_syscall_end: diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h index de2ccc149e3..fc1c8ddae14 100644 --- a/include/asm-i386/unistd.h +++ b/include/asm-i386/unistd.h @@ -322,10 +322,11 @@ #define __NR_sync_file_range 314 #define __NR_tee 315 #define __NR_vmsplice 316 +#define __NR_move_pages 317 #ifdef __KERNEL__ -#define NR_syscalls 317 +#define NR_syscalls 318 /* * user-visible error numbers are in the range -1 - -128: see diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 7e3f2349091..e42738c6916 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -521,6 +521,11 @@ asmlinkage long sys_move_pages(pid_t pid, unsigned long nr_pages, const int __user *nodes, int __user *status, int flags); +asmlinkage long compat_sys_move_pages(pid_t pid, unsigned long nr_page, + void __user *pages, + const int __user *nodes, + int __user *status, + int flags); asmlinkage long sys_mbind(unsigned long start, unsigned long len, unsigned long mode, unsigned long __user *nmask, diff --git a/kernel/compat.c b/kernel/compat.c index c1601a84f8d..ccea93e2895 100644 --- a/kernel/compat.c +++ b/kernel/compat.c @@ -21,6 +21,7 @@ #include #include #include +#include #include @@ -934,3 +935,25 @@ asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp) return ret; } + +#ifdef CONFIG_NUMA +asmlinkage long compat_sys_move_pages(pid_t pid, unsigned long nr_pages, + void __user *pages32, + const int __user *nodes, + int __user *status, + int flags) +{ + const void __user * __user *pages; + int i; + + pages = compat_alloc_user_space(nr_pages * sizeof(void *)); + for (i = 0; i < nr_pages; i++) { + compat_uptr_t p; + + if (get_user(p, (compat_uptr_t *)(pages32 + i)) || + put_user(compat_ptr(p), pages + i)) + return -EFAULT; + } + return sys_move_pages(pid, nr_pages, pages, nodes, status, flags); +} +#endif diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c index 597229749de..6991bece67e 100644 --- a/kernel/sys_ni.c +++ b/kernel/sys_ni.c @@ -133,3 +133,4 @@ cond_syscall(sys_mincore); cond_syscall(sys_madvise); cond_syscall(sys_mremap); cond_syscall(sys_remap_file_pages); +cond_syscall(compat_sys_move_pages); -- cgit v1.2.3 From 9216dfad4fc97ab639ef0885efc713f3d7a20d5b Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Fri, 23 Jun 2006 02:03:57 -0700 Subject: [PATCH] move_pages: fix 32 -> 64 bit compat function The definition of the third parameter is a pointer to an array of virtual addresses which give us some trouble. The existing code calculated the wrong address in the array since I used void to avoid having to specify a type. I now use the correct type "compat_uptr_t __user *" in the definition of the function in kernel/compat.c. However, I used __u32 in syscalls.h. Would have to include compat.h there in order to provide the same definition which would generate an ugly include situation. On both ia64 and x86_64 compat_uptr_t is u32. So this works although parameter declarations differ. Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/syscalls.h | 2 +- kernel/compat.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index e42738c6916..33785b79d54 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -522,7 +522,7 @@ asmlinkage long sys_move_pages(pid_t pid, unsigned long nr_pages, int __user *status, int flags); asmlinkage long compat_sys_move_pages(pid_t pid, unsigned long nr_page, - void __user *pages, + __u32 __user *pages, const int __user *nodes, int __user *status, int flags); diff --git a/kernel/compat.c b/kernel/compat.c index ccea93e2895..2f672332430 100644 --- a/kernel/compat.c +++ b/kernel/compat.c @@ -938,7 +938,7 @@ asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp) #ifdef CONFIG_NUMA asmlinkage long compat_sys_move_pages(pid_t pid, unsigned long nr_pages, - void __user *pages32, + compat_uptr_t __user *pages32, const int __user *nodes, int __user *status, int flags) @@ -950,7 +950,7 @@ asmlinkage long compat_sys_move_pages(pid_t pid, unsigned long nr_pages, for (i = 0; i < nr_pages; i++) { compat_uptr_t p; - if (get_user(p, (compat_uptr_t *)(pages32 + i)) || + if (get_user(p, pages32 + i) || put_user(compat_ptr(p), pages + i)) return -EFAULT; } -- cgit v1.2.3 From 03e68060636e05989ea94bcb671ab633948f328c Mon Sep 17 00:00:00 2001 From: James Morris Date: Fri, 23 Jun 2006 02:03:58 -0700 Subject: [PATCH] lsm: add task_setioprio hook Implement an LSM hook for setting a task's IO priority, similar to the hook for setting a tasks's nice value. A previous version of this LSM hook was included in an older version of multiadm by Jan Engelhardt, although I don't recall it being submitted upstream. Also included is the corresponding SELinux hook, which re-uses the setsched permission in the proccess class. Signed-off-by: James Morris Acked-by: Stephen Smalley Cc: Jan Engelhardt Cc: Chris Wright Cc: Jens Axboe Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ioprio.c | 6 ++++++ include/linux/security.h | 16 ++++++++++++++++ security/dummy.c | 6 ++++++ security/selinux/hooks.c | 6 ++++++ 4 files changed, 34 insertions(+) diff --git a/fs/ioprio.c b/fs/ioprio.c index ca77008146c..7fa76ed53c1 100644 --- a/fs/ioprio.c +++ b/fs/ioprio.c @@ -24,15 +24,21 @@ #include #include #include +#include static int set_task_ioprio(struct task_struct *task, int ioprio) { + int err; struct io_context *ioc; if (task->uid != current->euid && task->uid != current->uid && !capable(CAP_SYS_NICE)) return -EPERM; + err = security_task_setioprio(task, ioprio); + if (err) + return err; + task_lock(task); task->ioprio = ioprio; diff --git a/include/linux/security.h b/include/linux/security.h index 383c320fc83..65b32a0c620 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -577,6 +577,11 @@ struct swap_info_struct; * @p contains the task_struct of process. * @nice contains the new nice value. * Return 0 if permission is granted. + * @task_setioprio + * Check permission before setting the ioprio value of @p to @ioprio. + * @p contains the task_struct of process. + * @ioprio contains the new ioprio value + * Return 0 if permission is granted. * @task_setrlimit: * Check permission before setting the resource limits of the current * process for @resource to @new_rlim. The old resource limit values can @@ -1210,6 +1215,7 @@ struct security_operations { int (*task_getsid) (struct task_struct * p); int (*task_setgroups) (struct group_info *group_info); int (*task_setnice) (struct task_struct * p, int nice); + int (*task_setioprio) (struct task_struct * p, int ioprio); int (*task_setrlimit) (unsigned int resource, struct rlimit * new_rlim); int (*task_setscheduler) (struct task_struct * p, int policy, struct sched_param * lp); @@ -1836,6 +1842,11 @@ static inline int security_task_setnice (struct task_struct *p, int nice) return security_ops->task_setnice (p, nice); } +static inline int security_task_setioprio (struct task_struct *p, int ioprio) +{ + return security_ops->task_setioprio (p, ioprio); +} + static inline int security_task_setrlimit (unsigned int resource, struct rlimit *new_rlim) { @@ -2478,6 +2489,11 @@ static inline int security_task_setnice (struct task_struct *p, int nice) return 0; } +static inline int security_task_setioprio (struct task_struct *p, int ioprio) +{ + return 0; +} + static inline int security_task_setrlimit (unsigned int resource, struct rlimit *new_rlim) { diff --git a/security/dummy.c b/security/dummy.c index c98d553984e..879a98523b1 100644 --- a/security/dummy.c +++ b/security/dummy.c @@ -516,6 +516,11 @@ static int dummy_task_setnice (struct task_struct *p, int nice) return 0; } +static int dummy_task_setioprio (struct task_struct *p, int ioprio) +{ + return 0; +} + static int dummy_task_setrlimit (unsigned int resource, struct rlimit *new_rlim) { return 0; @@ -972,6 +977,7 @@ void security_fixup_ops (struct security_operations *ops) set_to_dummy_if_null(ops, task_getsid); set_to_dummy_if_null(ops, task_setgroups); set_to_dummy_if_null(ops, task_setnice); + set_to_dummy_if_null(ops, task_setioprio); set_to_dummy_if_null(ops, task_setrlimit); set_to_dummy_if_null(ops, task_setscheduler); set_to_dummy_if_null(ops, task_getscheduler); diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 093efba4d9b..9dcf298921d 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2645,6 +2645,11 @@ static int selinux_task_setnice(struct task_struct *p, int nice) return task_has_perm(current,p, PROCESS__SETSCHED); } +static int selinux_task_setioprio(struct task_struct *p, int ioprio) +{ + return task_has_perm(current, p, PROCESS__SETSCHED); +} + static int selinux_task_setrlimit(unsigned int resource, struct rlimit *new_rlim) { struct rlimit *old_rlim = current->signal->rlim + resource; @@ -4383,6 +4388,7 @@ static struct security_operations selinux_ops = { .task_getsid = selinux_task_getsid, .task_setgroups = selinux_task_setgroups, .task_setnice = selinux_task_setnice, + .task_setioprio = selinux_task_setioprio, .task_setrlimit = selinux_task_setrlimit, .task_setscheduler = selinux_task_setscheduler, .task_getscheduler = selinux_task_getscheduler, -- cgit v1.2.3 From e7834f8fccd791225a1cf91c2c3e740ad8e2e145 Mon Sep 17 00:00:00 2001 From: David Quigley Date: Fri, 23 Jun 2006 02:03:59 -0700 Subject: [PATCH] SELinux: add security hooks to {get,set}affinity This patch adds LSM hooks into the setaffinity and getaffinity functions to enable security modules to control these operations between tasks with task_setscheduler and task_getscheduler LSM hooks. Signed-off-by: David Quigley Acked-by: Stephen Smalley Signed-off-by: James Morris Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/sched.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/kernel/sched.c b/kernel/sched.c index c13f1bd2df7..87665132cec 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -3886,6 +3886,10 @@ long sched_setaffinity(pid_t pid, cpumask_t new_mask) !capable(CAP_SYS_NICE)) goto out_unlock; + retval = security_task_setscheduler(p, 0, NULL); + if (retval) + goto out_unlock; + cpus_allowed = cpuset_cpus_allowed(p); cpus_and(new_mask, new_mask, cpus_allowed); retval = set_cpus_allowed(p, new_mask); @@ -3954,7 +3958,10 @@ long sched_getaffinity(pid_t pid, cpumask_t *mask) if (!p) goto out_unlock; - retval = 0; + retval = security_task_getscheduler(p); + if (retval) + goto out_unlock; + cpus_and(*mask, p->cpus_allowed, cpu_online_map); out_unlock: -- cgit v1.2.3 From 22fb52dd736a62e24c44c50739007496265dc38c Mon Sep 17 00:00:00 2001 From: David Quigley Date: Fri, 23 Jun 2006 02:04:00 -0700 Subject: [PATCH] SELinux: add security hook call to mediate attach_task (kernel/cpuset.c) Add a security hook call to enable security modules to control the ability to attach a task to a cpuset. While limited control over this operation is possible via permission checks on the pseudo fs interface, those checks are not sufficient to control access to the target task, which is looked up in this function. The existing task_setscheduler hook is re-used for this operation since this falls under the same class of operations. Signed-off-by: David Quigley Acked-by: Stephen Smalley Signed-off-by: James Morris Acked-by: Paul Jackson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/cpuset.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 77f45ffd5ea..b602f73fb38 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -1177,6 +1178,7 @@ static int attach_task(struct cpuset *cs, char *pidbuf, char **ppathbuf) cpumask_t cpus; nodemask_t from, to; struct mm_struct *mm; + int retval; if (sscanf(pidbuf, "%d", &pid) != 1) return -EIO; @@ -1205,6 +1207,12 @@ static int attach_task(struct cpuset *cs, char *pidbuf, char **ppathbuf) get_task_struct(tsk); } + retval = security_task_setscheduler(tsk, 0, NULL); + if (retval) { + put_task_struct(tsk); + return retval; + } + mutex_lock(&callback_mutex); task_lock(tsk); -- cgit v1.2.3 From 35601547baf92d984b6e59cf3583649da04baea5 Mon Sep 17 00:00:00 2001 From: David Quigley Date: Fri, 23 Jun 2006 02:04:01 -0700 Subject: [PATCH] SELinux: add task_movememory hook This patch adds new security hook, task_movememory, to be called when memory owened by a task is to be moved (e.g. when migrating pages to a this hook is identical to the setscheduler implementation, but a separate hook introduced to allow this check to be specialized in the future if necessary. Since the last posting, the hook has been renamed following feedback from Christoph Lameter. Signed-off-by: David Quigley Acked-by: Stephen Smalley Signed-off-by: James Morris Cc: Christoph Lameter Cc: Andi Kleen Acked-by: Chris Wright Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/security.h | 15 +++++++++++++++ security/dummy.c | 6 ++++++ security/selinux/hooks.c | 6 ++++++ 3 files changed, 27 insertions(+) diff --git a/include/linux/security.h b/include/linux/security.h index 65b32a0c620..d2c17bd91a2 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -601,6 +601,10 @@ struct swap_info_struct; * @p. * @p contains the task_struct for process. * Return 0 if permission is granted. + * @task_movememory + * Check permission before moving memory owned by process @p. + * @p contains the task_struct for process. + * Return 0 if permission is granted. * @task_kill: * Check permission before sending signal @sig to @p. @info can be NULL, * the constant 1, or a pointer to a siginfo structure. If @info is 1 or @@ -1220,6 +1224,7 @@ struct security_operations { int (*task_setscheduler) (struct task_struct * p, int policy, struct sched_param * lp); int (*task_getscheduler) (struct task_struct * p); + int (*task_movememory) (struct task_struct * p); int (*task_kill) (struct task_struct * p, struct siginfo * info, int sig); int (*task_wait) (struct task_struct * p); @@ -1865,6 +1870,11 @@ static inline int security_task_getscheduler (struct task_struct *p) return security_ops->task_getscheduler (p); } +static inline int security_task_movememory (struct task_struct *p) +{ + return security_ops->task_movememory (p); +} + static inline int security_task_kill (struct task_struct *p, struct siginfo *info, int sig) { @@ -2512,6 +2522,11 @@ static inline int security_task_getscheduler (struct task_struct *p) return 0; } +static inline int security_task_movememory (struct task_struct *p) +{ + return 0; +} + static inline int security_task_kill (struct task_struct *p, struct siginfo *info, int sig) { diff --git a/security/dummy.c b/security/dummy.c index 879a98523b1..c3c5493581e 100644 --- a/security/dummy.c +++ b/security/dummy.c @@ -537,6 +537,11 @@ static int dummy_task_getscheduler (struct task_struct *p) return 0; } +static int dummy_task_movememory (struct task_struct *p) +{ + return 0; +} + static int dummy_task_wait (struct task_struct *p) { return 0; @@ -981,6 +986,7 @@ void security_fixup_ops (struct security_operations *ops) set_to_dummy_if_null(ops, task_setrlimit); set_to_dummy_if_null(ops, task_setscheduler); set_to_dummy_if_null(ops, task_getscheduler); + set_to_dummy_if_null(ops, task_movememory); set_to_dummy_if_null(ops, task_wait); set_to_dummy_if_null(ops, task_kill); set_to_dummy_if_null(ops, task_prctl); diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 9dcf298921d..79c16e31c88 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2679,6 +2679,11 @@ static int selinux_task_getscheduler(struct task_struct *p) return task_has_perm(current, p, PROCESS__GETSCHED); } +static int selinux_task_movememory(struct task_struct *p) +{ + return task_has_perm(current, p, PROCESS__SETSCHED); +} + static int selinux_task_kill(struct task_struct *p, struct siginfo *info, int sig) { u32 perm; @@ -4392,6 +4397,7 @@ static struct security_operations selinux_ops = { .task_setrlimit = selinux_task_setrlimit, .task_setscheduler = selinux_task_setscheduler, .task_getscheduler = selinux_task_getscheduler, + .task_movememory = selinux_task_movememory, .task_kill = selinux_task_kill, .task_wait = selinux_task_wait, .task_prctl = selinux_task_prctl, -- cgit v1.2.3 From 86c3a7645c05a7d06b72653aa4b2bea4e7229d1b Mon Sep 17 00:00:00 2001 From: David Quigley Date: Fri, 23 Jun 2006 02:04:02 -0700 Subject: [PATCH] SELinux: add security_task_movememory calls to mm code This patch inserts security_task_movememory hook calls into memory management code to enable security modules to mediate this operation between tasks. Since the last posting, the hook has been renamed following feedback from Christoph Lameter. Signed-off-by: David Quigley Acked-by: Stephen Smalley Signed-off-by: James Morris Cc: Andi Kleen Acked-by: Christoph Lameter Acked-by: Chris Wright Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/mempolicy.c | 5 +++++ mm/migrate.c | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 05b84acf0bb..ec4a1a950df 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -88,6 +88,7 @@ #include #include #include +#include #include #include @@ -942,6 +943,10 @@ asmlinkage long sys_migrate_pages(pid_t pid, unsigned long maxnode, goto out; } + err = security_task_movememory(task); + if (err) + goto out; + err = do_migrate_pages(mm, &old, &new, capable(CAP_SYS_NICE) ? MPOL_MF_MOVE_ALL : MPOL_MF_MOVE); out: diff --git a/mm/migrate.c b/mm/migrate.c index 033a12f4c94..1c2a71aa05c 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "internal.h" @@ -905,6 +906,11 @@ asmlinkage long sys_move_pages(pid_t pid, unsigned long nr_pages, goto out2; } + err = security_task_movememory(task); + if (err) + goto out2; + + task_nodes = cpuset_mems_allowed(task); /* Limit nr_pages so that the multiplication may not overflow */ -- cgit v1.2.3 From a8a77573c9e5345bcf6a963858745cd83c923f44 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 23 Jun 2006 02:04:03 -0700 Subject: [PATCH] frv: __user infrastructure Add general annotations to the FRV arch for sparse. Signed-off-by: Al Viro Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/frv/kernel/uaccess.c | 6 ++--- include/asm-frv/uaccess.h | 64 +++++++++++++++++++++++++++-------------------- 2 files changed, 40 insertions(+), 30 deletions(-) diff --git a/arch/frv/kernel/uaccess.c b/arch/frv/kernel/uaccess.c index 9b751c0f0e8..9fb771a20df 100644 --- a/arch/frv/kernel/uaccess.c +++ b/arch/frv/kernel/uaccess.c @@ -17,7 +17,7 @@ /* * copy a null terminated string from userspace */ -long strncpy_from_user(char *dst, const char *src, long count) +long strncpy_from_user(char *dst, const char __user *src, long count) { unsigned long max; char *p, ch; @@ -70,9 +70,9 @@ EXPORT_SYMBOL(strncpy_from_user); * * Return 0 on exception, a value greater than N if too long */ -long strnlen_user(const char *src, long count) +long strnlen_user(const char __user *src, long count) { - const char *p; + const char __user *p; long err = 0; char ch; diff --git a/include/asm-frv/uaccess.h b/include/asm-frv/uaccess.h index a1d14043886..3d90e1018ee 100644 --- a/include/asm-frv/uaccess.h +++ b/include/asm-frv/uaccess.h @@ -22,7 +22,7 @@ #define HAVE_ARCH_UNMAPPED_AREA /* we decide where to put mmaps */ -#define __ptr(x) ((unsigned long *)(x)) +#define __ptr(x) ((unsigned long __force *)(x)) #define VERIFY_READ 0 #define VERIFY_WRITE 1 @@ -64,7 +64,7 @@ static inline int ___range_ok(unsigned long addr, unsigned long size) #define __range_ok(addr,size) ___range_ok((unsigned long) (addr), (unsigned long) (size)) -#define access_ok(type,addr,size) (__range_ok((addr), (size)) == 0) +#define access_ok(type,addr,size) (__range_ok((void __user *)(addr), (size)) == 0) #define __access_ok(addr,size) (__range_ok((addr), (size)) == 0) /* @@ -97,6 +97,7 @@ extern unsigned long search_exception_table(unsigned long); int __pu_err = 0; \ \ typeof(*(ptr)) __pu_val = (x); \ + __chk_user_ptr(ptr); \ \ switch (sizeof (*(ptr))) { \ case 1: \ @@ -120,7 +121,7 @@ extern unsigned long search_exception_table(unsigned long); #define put_user(x, ptr) \ ({ \ - typeof(&*ptr) _p = (ptr); \ + typeof(*(ptr)) __user *_p = (ptr); \ int _e; \ \ _e = __range_ok(_p, sizeof(*_p)); \ @@ -175,33 +176,44 @@ do { \ */ #define __get_user(x, ptr) \ ({ \ - typeof(*(ptr)) __gu_val = 0; \ int __gu_err = 0; \ + __chk_user_ptr(ptr); \ \ switch (sizeof(*(ptr))) { \ - case 1: \ - __get_user_asm(__gu_err, *(u8*)&__gu_val, ptr, "ub", "=r"); \ + case 1: { \ + unsigned char __gu_val; \ + __get_user_asm(__gu_err, __gu_val, ptr, "ub", "=r"); \ + (x) = *(__force __typeof__(*(ptr)) *) &__gu_val; \ break; \ - case 2: \ - __get_user_asm(__gu_err, *(u16*)&__gu_val, ptr, "uh", "=r"); \ + } \ + case 2: { \ + unsigned short __gu_val; \ + __get_user_asm(__gu_err, __gu_val, ptr, "uh", "=r"); \ + (x) = *(__force __typeof__(*(ptr)) *) &__gu_val; \ break; \ - case 4: \ - __get_user_asm(__gu_err, *(u32*)&__gu_val, ptr, "", "=r"); \ + } \ + case 4: { \ + unsigned int __gu_val; \ + __get_user_asm(__gu_err, __gu_val, ptr, "", "=r"); \ + (x) = *(__force __typeof__(*(ptr)) *) &__gu_val; \ break; \ - case 8: \ - __get_user_asm(__gu_err, *(u64*)&__gu_val, ptr, "d", "=e"); \ + } \ + case 8: { \ + unsigned long long __gu_val; \ + __get_user_asm(__gu_err, __gu_val, ptr, "d", "=e"); \ + (x) = *(__force __typeof__(*(ptr)) *) &__gu_val; \ break; \ + } \ default: \ __gu_err = __get_user_bad(); \ break; \ } \ - (x) = __gu_val; \ __gu_err; \ }) #define get_user(x, ptr) \ ({ \ - typeof(&*ptr) _p = (ptr); \ + const typeof(*(ptr)) __user *_p = (ptr);\ int _e; \ \ _e = __range_ok(_p, sizeof(*_p)); \ @@ -248,19 +260,20 @@ do { \ /* * */ +#define ____force(x) (__force void *)(void __user *)(x) #ifdef CONFIG_MMU extern long __memset_user(void *dst, unsigned long count); extern long __memcpy_user(void *dst, const void *src, unsigned long count); -#define clear_user(dst,count) __memset_user((dst), (count)) -#define __copy_from_user_inatomic(to, from, n) __memcpy_user((to), (from), (n)) -#define __copy_to_user_inatomic(to, from, n) __memcpy_user((to), (from), (n)) +#define clear_user(dst,count) __memset_user(____force(dst), (count)) +#define __copy_from_user_inatomic(to, from, n) __memcpy_user((to), ____force(from), (n)) +#define __copy_to_user_inatomic(to, from, n) __memcpy_user(____force(to), (from), (n)) #else -#define clear_user(dst,count) (memset((dst), 0, (count)), 0) -#define __copy_from_user_inatomic(to, from, n) (memcpy((to), (from), (n)), 0) -#define __copy_to_user_inatomic(to, from, n) (memcpy((to), (from), (n)), 0) +#define clear_user(dst,count) (memset(____force(dst), 0, (count)), 0) +#define __copy_from_user_inatomic(to, from, n) (memcpy((to), ____force(from), (n)), 0) +#define __copy_to_user_inatomic(to, from, n) (memcpy(____force(to), (from), (n)), 0) #endif @@ -278,7 +291,7 @@ __copy_from_user(void *to, const void __user *from, unsigned long n) return __copy_from_user_inatomic(to, from, n); } -static inline long copy_from_user(void *to, const void *from, unsigned long n) +static inline long copy_from_user(void *to, const void __user *from, unsigned long n) { unsigned long ret = n; @@ -291,16 +304,13 @@ static inline long copy_from_user(void *to, const void *from, unsigned long n) return ret; } -static inline long copy_to_user(void *to, const void *from, unsigned long n) +static inline long copy_to_user(void __user *to, const void *from, unsigned long n) { return likely(__access_ok(to, n)) ? __copy_to_user(to, from, n) : n; } -#define copy_to_user_ret(to,from,n,retval) ({ if (copy_to_user(to,from,n)) return retval; }) -#define copy_from_user_ret(to,from,n,retval) ({ if (copy_from_user(to,from,n)) return retval; }) - -extern long strncpy_from_user(char *dst, const char *src, long count); -extern long strnlen_user(const char *src, long count); +extern long strncpy_from_user(char *dst, const char __user *src, long count); +extern long strnlen_user(const char __user *src, long count); #define strlen_user(str) strnlen_user(str, 32767) -- cgit v1.2.3 From 3f4cd389c3564caf1eec70957fcbd9d88c995d45 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 23 Jun 2006 02:04:03 -0700 Subject: [PATCH] frv: basic __iomem annotations Add annotations to the FRV I/O handling functions for sparse. Signed-off-by: Al Viro Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/frv/mm/kmap.c | 6 +++--- include/asm-frv/io.h | 38 +++++++++++++++++++------------------- include/asm-frv/mb-regs.h | 27 +++++++++++++++++++-------- 3 files changed, 41 insertions(+), 30 deletions(-) diff --git a/arch/frv/mm/kmap.c b/arch/frv/mm/kmap.c index c54f18e65ea..40b62c5c295 100644 --- a/arch/frv/mm/kmap.c +++ b/arch/frv/mm/kmap.c @@ -31,15 +31,15 @@ * Map some physical address range into the kernel address space. */ -void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag) +void __iomem *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag) { - return (void *)physaddr; + return (void __iomem *)physaddr; } /* * Unmap a ioremap()ed region again */ -void iounmap(void *addr) +void iounmap(void volatile __iomem *addr) { } diff --git a/include/asm-frv/io.h b/include/asm-frv/io.h index b56eba59e3c..f49398a8297 100644 --- a/include/asm-frv/io.h +++ b/include/asm-frv/io.h @@ -40,13 +40,13 @@ static inline unsigned long _swapl(unsigned long v) //#define __iormb() asm volatile("membar") //#define __iowmb() asm volatile("membar") -#define __raw_readb(addr) __builtin_read8((void *) (addr)) -#define __raw_readw(addr) __builtin_read16((void *) (addr)) -#define __raw_readl(addr) __builtin_read32((void *) (addr)) +#define __raw_readb __builtin_read8 +#define __raw_readw __builtin_read16 +#define __raw_readl __builtin_read32 -#define __raw_writeb(datum, addr) __builtin_write8((void *) (addr), datum) -#define __raw_writew(datum, addr) __builtin_write16((void *) (addr), datum) -#define __raw_writel(datum, addr) __builtin_write32((void *) (addr), datum) +#define __raw_writeb(datum, addr) __builtin_write8(addr, datum) +#define __raw_writew(datum, addr) __builtin_write16(addr, datum) +#define __raw_writel(datum, addr) __builtin_write32(addr, datum) static inline void io_outsb(unsigned int addr, const void *buf, int len) { @@ -128,12 +128,12 @@ static inline void memcpy_toio(volatile void __iomem *dst, const void *src, int static inline uint8_t inb(unsigned long addr) { - return __builtin_read8((void *)addr); + return __builtin_read8((void __iomem *)addr); } static inline uint16_t inw(unsigned long addr) { - uint16_t ret = __builtin_read16((void *)addr); + uint16_t ret = __builtin_read16((void __iomem *)addr); if (__is_PCI_IO(addr)) ret = _swapw(ret); @@ -143,7 +143,7 @@ static inline uint16_t inw(unsigned long addr) static inline uint32_t inl(unsigned long addr) { - uint32_t ret = __builtin_read32((void *)addr); + uint32_t ret = __builtin_read32((void __iomem *)addr); if (__is_PCI_IO(addr)) ret = _swapl(ret); @@ -153,21 +153,21 @@ static inline uint32_t inl(unsigned long addr) static inline void outb(uint8_t datum, unsigned long addr) { - __builtin_write8((void *)addr, datum); + __builtin_write8((void __iomem *)addr, datum); } static inline void outw(uint16_t datum, unsigned long addr) { if (__is_PCI_IO(addr)) datum = _swapw(datum); - __builtin_write16((void *)addr, datum); + __builtin_write16((void __iomem *)addr, datum); } static inline void outl(uint32_t datum, unsigned long addr) { if (__is_PCI_IO(addr)) datum = _swapl(datum); - __builtin_write32((void *)addr, datum); + __builtin_write32((void __iomem *)addr, datum); } #define inb_p(addr) inb(addr) @@ -189,12 +189,12 @@ static inline void outl(uint32_t datum, unsigned long addr) static inline uint8_t readb(const volatile void __iomem *addr) { - return __builtin_read8((volatile uint8_t __force *) addr); + return __builtin_read8((__force void volatile __iomem *) addr); } static inline uint16_t readw(const volatile void __iomem *addr) { - uint16_t ret = __builtin_read16((volatile uint16_t __force *)addr); + uint16_t ret = __builtin_read16((__force void volatile __iomem *)addr); if (__is_PCI_MEM(addr)) ret = _swapw(ret); @@ -203,7 +203,7 @@ static inline uint16_t readw(const volatile void __iomem *addr) static inline uint32_t readl(const volatile void __iomem *addr) { - uint32_t ret = __builtin_read32((volatile uint32_t __force *)addr); + uint32_t ret = __builtin_read32((__force void volatile __iomem *)addr); if (__is_PCI_MEM(addr)) ret = _swapl(ret); @@ -217,7 +217,7 @@ static inline uint32_t readl(const volatile void __iomem *addr) static inline void writeb(uint8_t datum, volatile void __iomem *addr) { - __builtin_write8((volatile uint8_t __force *) addr, datum); + __builtin_write8(addr, datum); if (__is_PCI_MEM(addr)) __flush_PCI_writes(); } @@ -227,7 +227,7 @@ static inline void writew(uint16_t datum, volatile void __iomem *addr) if (__is_PCI_MEM(addr)) datum = _swapw(datum); - __builtin_write16((volatile uint16_t __force *) addr, datum); + __builtin_write16(addr, datum); if (__is_PCI_MEM(addr)) __flush_PCI_writes(); } @@ -237,7 +237,7 @@ static inline void writel(uint32_t datum, volatile void __iomem *addr) if (__is_PCI_MEM(addr)) datum = _swapl(datum); - __builtin_write32((volatile uint32_t __force *) addr, datum); + __builtin_write32(addr, datum); if (__is_PCI_MEM(addr)) __flush_PCI_writes(); } @@ -271,7 +271,7 @@ static inline void __iomem *ioremap_fullcache(unsigned long physaddr, unsigned l return __ioremap(physaddr, size, IOMAP_FULL_CACHING); } -extern void iounmap(void __iomem *addr); +extern void iounmap(void volatile __iomem *addr); static inline void __iomem *ioport_map(unsigned long port, unsigned int nr) { diff --git a/include/asm-frv/mb-regs.h b/include/asm-frv/mb-regs.h index 93fa732fb0c..219e5f926f1 100644 --- a/include/asm-frv/mb-regs.h +++ b/include/asm-frv/mb-regs.h @@ -16,6 +16,17 @@ #include #include +#ifndef __ASSEMBLY__ +/* gcc builtins, annotated */ + +unsigned long __builtin_read8(volatile void __iomem *); +unsigned long __builtin_read16(volatile void __iomem *); +unsigned long __builtin_read32(volatile void __iomem *); +void __builtin_write8(volatile void __iomem *, unsigned char); +void __builtin_write16(volatile void __iomem *, unsigned short); +void __builtin_write32(volatile void __iomem *, unsigned long); +#endif + #define __region_IO KERNEL_IO_START /* the region from 0xe0000000 to 0xffffffff has suitable * protection laid over the top for use in memory-mapped * I/O @@ -59,7 +70,7 @@ #define __region_PCI_MEM (__region_CS2 + 0x08000000UL) #define __flush_PCI_writes() \ do { \ - __builtin_write8((volatile void *) __region_PCI_MEM, 0); \ + __builtin_write8((volatile void __iomem *) __region_PCI_MEM, 0); \ } while(0) #define __is_PCI_IO(addr) \ @@ -83,15 +94,15 @@ extern int __nongprelbss mb93090_mb00_detected; #define __set_LEDS(X) \ do { \ if (mb93090_mb00_detected) \ - __builtin_write32((void *) __addr_LEDS(), ~(X)); \ + __builtin_write32((void __iomem *) __addr_LEDS(), ~(X)); \ } while (0) #else #define __set_LEDS(X) #endif #define __addr_LCD() (__region_CS2 + 0x01200008UL) -#define __get_LCD(B) __builtin_read32((volatile void *) (B)) -#define __set_LCD(B,X) __builtin_write32((volatile void *) (B), (X)) +#define __get_LCD(B) __builtin_read32((volatile void __iomem *) (B)) +#define __set_LCD(B,X) __builtin_write32((volatile void __iomem *) (B), (X)) #define LCD_D 0x000000ff /* LCD data bus */ #define LCD_RW 0x00000100 /* LCD R/W signal */ @@ -161,11 +172,11 @@ do { \ #define __get_CLKIN() 66000000UL #define __addr_LEDS() (__region_CS2 + 0x00000023UL) -#define __set_LEDS(X) __builtin_write8((volatile void *) __addr_LEDS(), (X)) +#define __set_LEDS(X) __builtin_write8((volatile void __iomem *) __addr_LEDS(), (X)) #define __addr_FPGATR() (__region_CS2 + 0x00000030UL) -#define __set_FPGATR(X) __builtin_write32((volatile void *) __addr_FPGATR(), (X)) -#define __get_FPGATR() __builtin_read32((volatile void *) __addr_FPGATR()) +#define __set_FPGATR(X) __builtin_write32((volatile void __iomem *) __addr_FPGATR(), (X)) +#define __get_FPGATR() __builtin_read32((volatile void __iomem *) __addr_FPGATR()) #define MB93093_FPGA_FPGATR_AUDIO_CLK 0x00000003 @@ -180,7 +191,7 @@ do { \ #define MB93093_FPGA_SWR_PUSHSWMASK (0x1F<<26) #define MB93093_FPGA_SWR_PUSHSW4 (1<<29) -#define __addr_FPGA_SWR ((volatile void *)(__region_CS2 + 0x28UL)) +#define __addr_FPGA_SWR ((volatile void __iomem *)(__region_CS2 + 0x28UL)) #define __get_FPGA_PUSHSW1_5() (__builtin_read32(__addr_FPGA_SWR) & MB93093_FPGA_SWR_PUSHSWMASK) -- cgit v1.2.3 From 9e4d11f8630d5350adc5d4d65180e69991c498f8 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 23 Jun 2006 02:04:04 -0700 Subject: [PATCH] frv: signal annotations Add annotations to the FRV signal handling for sparse. Signed-off-by: Al Viro Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/frv/kernel/signal.c | 20 ++++++++++---------- include/asm-frv/signal.h | 6 +++--- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/arch/frv/kernel/signal.c b/arch/frv/kernel/signal.c index 679c1d5cc95..dd5e6fdd85f 100644 --- a/arch/frv/kernel/signal.c +++ b/arch/frv/kernel/signal.c @@ -98,7 +98,7 @@ int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss) struct sigframe { - void (*pretcode)(void); + __sigrestore_t pretcode; int sig; struct sigcontext sc; unsigned long extramask[_NSIG_WORDS-1]; @@ -107,10 +107,10 @@ struct sigframe struct rt_sigframe { - void (*pretcode)(void); + __sigrestore_t pretcode; int sig; - struct siginfo *pinfo; - void *puc; + struct siginfo __user *pinfo; + void __user *puc; struct siginfo info; struct ucontext uc; uint32_t retcode[2]; @@ -284,7 +284,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set) * setlos #__NR_sigreturn,gr7 * tira gr0,0 */ - if (__put_user((void (*)(void))frame->retcode, &frame->pretcode) || + if (__put_user((__sigrestore_t)frame->retcode, &frame->pretcode) || __put_user(0x8efc0000|__NR_sigreturn, &frame->retcode[0]) || __put_user(0xc0700000, &frame->retcode[1])) goto give_sigsegv; @@ -300,7 +300,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set) if (get_personality & FDPIC_FUNCPTRS) { struct fdpic_func_descriptor __user *funcptr = - (struct fdpic_func_descriptor *) ka->sa.sa_handler; + (struct fdpic_func_descriptor __user *) ka->sa.sa_handler; __get_user(__frame->pc, &funcptr->text); __get_user(__frame->gr15, &funcptr->GOT); } else { @@ -359,8 +359,8 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, /* Create the ucontext. */ if (__put_user(0, &frame->uc.uc_flags) || - __put_user(0, &frame->uc.uc_link) || - __put_user((void*)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp) || + __put_user(NULL, &frame->uc.uc_link) || + __put_user((void __user *)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp) || __put_user(sas_ss_flags(__frame->sp), &frame->uc.uc_stack.ss_flags) || __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size)) goto give_sigsegv; @@ -382,7 +382,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, * setlos #__NR_sigreturn,gr7 * tira gr0,0 */ - if (__put_user((void (*)(void))frame->retcode, &frame->pretcode) || + if (__put_user((__sigrestore_t)frame->retcode, &frame->pretcode) || __put_user(0x8efc0000|__NR_rt_sigreturn, &frame->retcode[0]) || __put_user(0xc0700000, &frame->retcode[1])) goto give_sigsegv; @@ -398,7 +398,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, __frame->gr9 = (unsigned long) &frame->info; if (get_personality & FDPIC_FUNCPTRS) { - struct fdpic_func_descriptor *funcptr = + struct fdpic_func_descriptor __user *funcptr = (struct fdpic_func_descriptor __user *) ka->sa.sa_handler; __get_user(__frame->pc, &funcptr->text); __get_user(__frame->gr15, &funcptr->GOT); diff --git a/include/asm-frv/signal.h b/include/asm-frv/signal.h index 67366894780..dcc1b359291 100644 --- a/include/asm-frv/signal.h +++ b/include/asm-frv/signal.h @@ -114,13 +114,13 @@ struct old_sigaction { __sighandler_t sa_handler; old_sigset_t sa_mask; unsigned long sa_flags; - void (*sa_restorer)(void); + __sigrestore_t sa_restorer; }; struct sigaction { __sighandler_t sa_handler; unsigned long sa_flags; - void (*sa_restorer)(void); + __sigrestore_t sa_restorer; sigset_t sa_mask; /* mask last for extensibility */ }; @@ -146,7 +146,7 @@ struct sigaction { #endif /* __KERNEL__ */ typedef struct sigaltstack { - void *ss_sp; + void __user *ss_sp; int ss_flags; size_t ss_size; } stack_t; -- cgit v1.2.3 From 7ab76d722a0d64369080ec96f0fd9fca2138e3c5 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 23 Jun 2006 02:04:05 -0700 Subject: [PATCH] frv: sysctl __user annotations Add __user annotations to FRV-specific sysctl stuff. Signed-off-by: Al Viro Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/frv/kernel/pm.c | 40 ++++++++++++++++++++-------------------- arch/frv/kernel/sysctl.c | 4 ++-- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/arch/frv/kernel/pm.c b/arch/frv/kernel/pm.c index f0b8fff3e73..43ce28a13a5 100644 --- a/arch/frv/kernel/pm.c +++ b/arch/frv/kernel/pm.c @@ -137,7 +137,7 @@ unsigned long sleep_phys_sp(void *sp) #define CTL_PM_P0 4 #define CTL_PM_CM 5 -static int user_atoi(char *ubuf, size_t len) +static int user_atoi(char __user *ubuf, size_t len) { char buf[16]; unsigned long ret; @@ -159,7 +159,7 @@ static int user_atoi(char *ubuf, size_t len) * Send us to sleep. */ static int sysctl_pm_do_suspend(ctl_table *ctl, int write, struct file *filp, - void *buffer, size_t *lenp, loff_t *fpos) + void __user *buffer, size_t *lenp, loff_t *fpos) { int retval, mode; @@ -215,7 +215,7 @@ static int try_set_cmode(int new_cmode) static int cmode_procctl(ctl_table *ctl, int write, struct file *filp, - void *buffer, size_t *lenp, loff_t *fpos) + void __user *buffer, size_t *lenp, loff_t *fpos) { int new_cmode; @@ -227,9 +227,9 @@ static int cmode_procctl(ctl_table *ctl, int write, struct file *filp, return try_set_cmode(new_cmode)?:*lenp; } -static int cmode_sysctl(ctl_table *table, int *name, int nlen, - void *oldval, size_t *oldlenp, - void *newval, size_t newlen, void **context) +static int cmode_sysctl(ctl_table *table, int __user *name, int nlen, + void __user *oldval, size_t __user *oldlenp, + void __user *newval, size_t newlen, void **context) { if (oldval && oldlenp) { size_t oldlen; @@ -240,7 +240,7 @@ static int cmode_sysctl(ctl_table *table, int *name, int nlen, if (oldlen != sizeof(int)) return -EINVAL; - if (put_user(clock_cmode_current, (unsigned int *)oldval) || + if (put_user(clock_cmode_current, (unsigned __user *)oldval) || put_user(sizeof(int), oldlenp)) return -EFAULT; } @@ -250,7 +250,7 @@ static int cmode_sysctl(ctl_table *table, int *name, int nlen, if (newlen != sizeof(int)) return -EINVAL; - if (get_user(new_cmode, (int *)newval)) + if (get_user(new_cmode, (int __user *)newval)) return -EFAULT; return try_set_cmode(new_cmode)?:1; @@ -318,7 +318,7 @@ static int try_set_cm(int new_cm) } static int p0_procctl(ctl_table *ctl, int write, struct file *filp, - void *buffer, size_t *lenp, loff_t *fpos) + void __user *buffer, size_t *lenp, loff_t *fpos) { int new_p0; @@ -330,9 +330,9 @@ static int p0_procctl(ctl_table *ctl, int write, struct file *filp, return try_set_p0(new_p0)?:*lenp; } -static int p0_sysctl(ctl_table *table, int *name, int nlen, - void *oldval, size_t *oldlenp, - void *newval, size_t newlen, void **context) +static int p0_sysctl(ctl_table *table, int __user *name, int nlen, + void __user *oldval, size_t __user *oldlenp, + void __user *newval, size_t newlen, void **context) { if (oldval && oldlenp) { size_t oldlen; @@ -343,7 +343,7 @@ static int p0_sysctl(ctl_table *table, int *name, int nlen, if (oldlen != sizeof(int)) return -EINVAL; - if (put_user(clock_p0_current, (unsigned int *)oldval) || + if (put_user(clock_p0_current, (unsigned __user *)oldval) || put_user(sizeof(int), oldlenp)) return -EFAULT; } @@ -353,7 +353,7 @@ static int p0_sysctl(ctl_table *table, int *name, int nlen, if (newlen != sizeof(int)) return -EINVAL; - if (get_user(new_p0, (int *)newval)) + if (get_user(new_p0, (int __user *)newval)) return -EFAULT; return try_set_p0(new_p0)?:1; @@ -362,7 +362,7 @@ static int p0_sysctl(ctl_table *table, int *name, int nlen, } static int cm_procctl(ctl_table *ctl, int write, struct file *filp, - void *buffer, size_t *lenp, loff_t *fpos) + void __user *buffer, size_t *lenp, loff_t *fpos) { int new_cm; @@ -374,9 +374,9 @@ static int cm_procctl(ctl_table *ctl, int write, struct file *filp, return try_set_cm(new_cm)?:*lenp; } -static int cm_sysctl(ctl_table *table, int *name, int nlen, - void *oldval, size_t *oldlenp, - void *newval, size_t newlen, void **context) +static int cm_sysctl(ctl_table *table, int __user *name, int nlen, + void __user *oldval, size_t __user *oldlenp, + void __user *newval, size_t newlen, void **context) { if (oldval && oldlenp) { size_t oldlen; @@ -387,7 +387,7 @@ static int cm_sysctl(ctl_table *table, int *name, int nlen, if (oldlen != sizeof(int)) return -EINVAL; - if (put_user(clock_cm_current, (unsigned int *)oldval) || + if (put_user(clock_cm_current, (unsigned __user *)oldval) || put_user(sizeof(int), oldlenp)) return -EFAULT; } @@ -397,7 +397,7 @@ static int cm_sysctl(ctl_table *table, int *name, int nlen, if (newlen != sizeof(int)) return -EINVAL; - if (get_user(new_cm, (int *)newval)) + if (get_user(new_cm, (int __user *)newval)) return -EFAULT; return try_set_cm(new_cm)?:1; diff --git a/arch/frv/kernel/sysctl.c b/arch/frv/kernel/sysctl.c index 408b0f382b4..b908863d659 100644 --- a/arch/frv/kernel/sysctl.c +++ b/arch/frv/kernel/sysctl.c @@ -49,7 +49,7 @@ static void frv_change_dcache_mode(unsigned long newmode) * handle requests to dynamically switch the write caching mode delivered by /proc */ static int procctl_frv_cachemode(ctl_table *table, int write, struct file *filp, - void *buffer, size_t *lenp, loff_t *ppos) + void __user *buffer, size_t *lenp, loff_t *ppos) { unsigned long hsr0; char buff[8]; @@ -123,7 +123,7 @@ static int procctl_frv_cachemode(ctl_table *table, int write, struct file *filp, */ #ifdef CONFIG_MMU static int procctl_frv_pin_cxnr(ctl_table *table, int write, struct file *filp, - void *buffer, size_t *lenp, loff_t *ppos) + void __user *buffer, size_t *lenp, loff_t *ppos) { pid_t pid; char buff[16], *p; -- cgit v1.2.3 From 530018bf3d93e04533eec9c6516e3ce8f5310e13 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 23 Jun 2006 02:04:05 -0700 Subject: [PATCH] frv: binfmt_elf_fdpic __user annotations Add __user annotations to binfmt_elf_fdpic. Signed-off-by: Al Viro Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/binfmt_elf_fdpic.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index a2e48c999c2..eba4e23b9ca 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c @@ -435,9 +435,10 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm, struct elf_fdpic_params *interp_params) { unsigned long sp, csp, nitems; - elf_caddr_t *argv, *envp; + elf_caddr_t __user *argv, *envp; size_t platform_len = 0, len; - char *k_platform, *u_platform, *p; + char *k_platform; + char __user *u_platform, *p; long hwcap; int loop; @@ -462,12 +463,11 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm, if (k_platform) { platform_len = strlen(k_platform) + 1; sp -= platform_len; + u_platform = (char __user *) sp; if (__copy_to_user(u_platform, k_platform, platform_len) != 0) return -EFAULT; } - u_platform = (char *) sp; - #if defined(__i386__) && defined(CONFIG_SMP) /* in some cases (e.g. Hyper-Threading), we want to avoid L1 evictions * by the processes running on the same package. One thing we can do @@ -490,7 +490,7 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm, sp = (sp - len) & ~7UL; exec_params->map_addr = sp; - if (copy_to_user((void *) sp, exec_params->loadmap, len) != 0) + if (copy_to_user((void __user *) sp, exec_params->loadmap, len) != 0) return -EFAULT; current->mm->context.exec_fdpic_loadmap = (unsigned long) sp; @@ -501,7 +501,7 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm, sp = (sp - len) & ~7UL; interp_params->map_addr = sp; - if (copy_to_user((void *) sp, interp_params->loadmap, len) != 0) + if (copy_to_user((void __user *) sp, interp_params->loadmap, len) != 0) return -EFAULT; current->mm->context.interp_fdpic_loadmap = (unsigned long) sp; @@ -527,7 +527,7 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm, /* put the ELF interpreter info on the stack */ #define NEW_AUX_ENT(nr, id, val) \ do { \ - struct { unsigned long _id, _val; } *ent = (void *) csp; \ + struct { unsigned long _id, _val; } __user *ent = (void __user *) csp; \ __put_user((id), &ent[nr]._id); \ __put_user((val), &ent[nr]._val); \ } while (0) @@ -564,13 +564,13 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm, /* allocate room for argv[] and envv[] */ csp -= (bprm->envc + 1) * sizeof(elf_caddr_t); - envp = (elf_caddr_t *) csp; + envp = (elf_caddr_t __user *) csp; csp -= (bprm->argc + 1) * sizeof(elf_caddr_t); - argv = (elf_caddr_t *) csp; + argv = (elf_caddr_t __user *) csp; /* stack argc */ csp -= sizeof(unsigned long); - __put_user(bprm->argc, (unsigned long *) csp); + __put_user(bprm->argc, (unsigned long __user *) csp); BUG_ON(csp != sp); @@ -581,7 +581,7 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm, current->mm->arg_start = current->mm->start_stack - (MAX_ARG_PAGES * PAGE_SIZE - bprm->p); #endif - p = (char *) current->mm->arg_start; + p = (char __user *) current->mm->arg_start; for (loop = bprm->argc; loop > 0; loop--) { __put_user((elf_caddr_t) p, argv++); len = strnlen_user(p, PAGE_SIZE * MAX_ARG_PAGES); @@ -1025,7 +1025,7 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params, /* clear the bit between beginning of mapping and beginning of PT_LOAD */ if (prot & PROT_WRITE && disp > 0) { kdebug("clear[%d] ad=%lx sz=%lx", loop, maddr, disp); - clear_user((void *) maddr, disp); + clear_user((void __user *) maddr, disp); maddr += disp; } @@ -1059,7 +1059,7 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params, if (prot & PROT_WRITE && excess1 > 0) { kdebug("clear[%d] ad=%lx sz=%lx", loop, maddr + phdr->p_filesz, excess1); - clear_user((void *) maddr + phdr->p_filesz, excess1); + clear_user((void __user *) maddr + phdr->p_filesz, excess1); } #else -- cgit v1.2.3 From 53470aaa02ef3c83187f1ffe0d2cb647274fe397 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 23 Jun 2006 02:04:06 -0700 Subject: [PATCH] frv: misc __user annotations Signed-off-by: Al Viro Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/frv/kernel/irq.c | 6 +++--- arch/frv/kernel/process.c | 2 +- arch/frv/kernel/sys_frv.c | 2 +- include/asm-frv/checksum.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/frv/kernel/irq.c b/arch/frv/kernel/irq.c index 11fa326a8f6..8b112b36191 100644 --- a/arch/frv/kernel/irq.c +++ b/arch/frv/kernel/irq.c @@ -625,7 +625,7 @@ static struct proc_dir_entry * irq_dir [NR_IRQS]; #define HEX_DIGITS 8 -static unsigned int parse_hex_value (const char *buffer, +static unsigned int parse_hex_value (const char __user *buffer, unsigned long count, unsigned long *ret) { unsigned char hexnum [HEX_DIGITS]; @@ -672,7 +672,7 @@ static int prof_cpu_mask_read_proc (char *page, char **start, off_t off, return sprintf (page, "%08lx\n", *mask); } -static int prof_cpu_mask_write_proc (struct file *file, const char *buffer, +static int prof_cpu_mask_write_proc (struct file *file, const char __user *buffer, unsigned long count, void *data) { unsigned long *mask = (unsigned long *) data, full_count = count, err; @@ -711,7 +711,7 @@ void init_irq_proc (void) int i; /* create /proc/irq */ - root_irq_dir = proc_mkdir("irq", 0); + root_irq_dir = proc_mkdir("irq", NULL); /* create /proc/irq/prof_cpu_mask */ entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir); diff --git a/arch/frv/kernel/process.c b/arch/frv/kernel/process.c index 0fff8a61ef2..489e6c489cb 100644 --- a/arch/frv/kernel/process.c +++ b/arch/frv/kernel/process.c @@ -246,7 +246,7 @@ int copy_thread(int nr, unsigned long clone_flags, /* * sys_execve() executes a new program. */ -asmlinkage int sys_execve(char *name, char **argv, char **envp) +asmlinkage int sys_execve(char __user *name, char __user * __user *argv, char __user * __user *envp) { int error; char * filename; diff --git a/arch/frv/kernel/sys_frv.c b/arch/frv/kernel/sys_frv.c index 931aa6d895e..c4d4348c9e8 100644 --- a/arch/frv/kernel/sys_frv.c +++ b/arch/frv/kernel/sys_frv.c @@ -32,7 +32,7 @@ * sys_pipe() is the normal C calling standard for creating * a pipe. It's not the way unix traditionally does this, though. */ -asmlinkage long sys_pipe(unsigned long * fildes) +asmlinkage long sys_pipe(unsigned long __user * fildes) { int fd[2]; int error; diff --git a/include/asm-frv/checksum.h b/include/asm-frv/checksum.h index 10236f6802d..42bf0db2287 100644 --- a/include/asm-frv/checksum.h +++ b/include/asm-frv/checksum.h @@ -43,7 +43,7 @@ unsigned int csum_partial_copy(const char *src, char *dst, int len, int sum); * here even more important to align src and dst on a 32-bit (or even * better 64-bit) boundary */ -extern unsigned int csum_partial_copy_from_user(const char *src, char *dst, +extern unsigned int csum_partial_copy_from_user(const char __user *src, char *dst, int len, int sum, int *csum_err); #define csum_partial_copy_nocheck(src, dst, len, sum) \ -- cgit v1.2.3 From 576132b42647e3facd28e3148a20307fadfd9afc Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 23 Jun 2006 02:04:07 -0700 Subject: [PATCH] frv: misc sparse annotations Signed-off-by: Al Viro Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/frv/kernel/irq-routing.c | 8 ++++---- arch/frv/mb93090-mb00/pci-irq.c | 10 +++++----- include/asm-frv/highmem.h | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/arch/frv/kernel/irq-routing.c b/arch/frv/kernel/irq-routing.c index d4776d1f4e8..b90b70a761d 100644 --- a/arch/frv/kernel/irq-routing.c +++ b/arch/frv/kernel/irq-routing.c @@ -112,7 +112,7 @@ struct irq_source frv_cpuuart[2] = { #define __CPUUART(X, A) \ [X] = { \ .muxname = "uart", \ - .muxdata = (volatile void __iomem *) A, \ + .muxdata = (volatile void __iomem *)(unsigned long)A,\ .irqmask = 1 << IRQ_CPU_UART##X, \ .doirq = frv_cpuuart_doirq, \ } @@ -136,7 +136,7 @@ struct irq_source frv_cpudma[8] = { #define __CPUDMA(X, A) \ [X] = { \ .muxname = "dma", \ - .muxdata = (volatile void __iomem *) A, \ + .muxdata = (volatile void __iomem *)(unsigned long)A,\ .irqmask = 1 << IRQ_CPU_DMA##X, \ .doirq = frv_cpudma_doirq, \ } @@ -164,7 +164,7 @@ struct irq_source frv_cputimer[3] = { #define __CPUTIMER(X) \ [X] = { \ .muxname = "timer", \ - .muxdata = 0, \ + .muxdata = NULL, \ .irqmask = 1 << IRQ_CPU_TIMER##X, \ .doirq = frv_cputimer_doirq, \ } @@ -187,7 +187,7 @@ struct irq_source frv_cpuexternal[8] = { #define __CPUEXTERNAL(X) \ [X] = { \ .muxname = "ext", \ - .muxdata = 0, \ + .muxdata = NULL, \ .irqmask = 1 << IRQ_CPU_EXTERNAL##X, \ .doirq = frv_cpuexternal_doirq, \ } diff --git a/arch/frv/mb93090-mb00/pci-irq.c b/arch/frv/mb93090-mb00/pci-irq.c index c4a1144c98b..45ae39d84b6 100644 --- a/arch/frv/mb93090-mb00/pci-irq.c +++ b/arch/frv/mb93090-mb00/pci-irq.c @@ -32,11 +32,11 @@ */ static const uint8_t __initdata pci_bus0_irq_routing[32][4] = { - [0 ] { IRQ_FPGA_MB86943_PCI_INTA }, - [16] { IRQ_FPGA_RTL8029_INTA }, - [17] { IRQ_FPGA_PCI_INTC, IRQ_FPGA_PCI_INTD, IRQ_FPGA_PCI_INTA, IRQ_FPGA_PCI_INTB }, - [18] { IRQ_FPGA_PCI_INTB, IRQ_FPGA_PCI_INTC, IRQ_FPGA_PCI_INTD, IRQ_FPGA_PCI_INTA }, - [19] { IRQ_FPGA_PCI_INTA, IRQ_FPGA_PCI_INTB, IRQ_FPGA_PCI_INTC, IRQ_FPGA_PCI_INTD }, + [0 ] = { IRQ_FPGA_MB86943_PCI_INTA }, + [16] = { IRQ_FPGA_RTL8029_INTA }, + [17] = { IRQ_FPGA_PCI_INTC, IRQ_FPGA_PCI_INTD, IRQ_FPGA_PCI_INTA, IRQ_FPGA_PCI_INTB }, + [18] = { IRQ_FPGA_PCI_INTB, IRQ_FPGA_PCI_INTC, IRQ_FPGA_PCI_INTD, IRQ_FPGA_PCI_INTA }, + [19] = { IRQ_FPGA_PCI_INTA, IRQ_FPGA_PCI_INTB, IRQ_FPGA_PCI_INTC, IRQ_FPGA_PCI_INTD }, }; void __init pcibios_irq_init(void) diff --git a/include/asm-frv/highmem.h b/include/asm-frv/highmem.h index cfbf7d3a1fe..e2247c22a63 100644 --- a/include/asm-frv/highmem.h +++ b/include/asm-frv/highmem.h @@ -134,7 +134,7 @@ static inline void *kmap_atomic(struct page *page, enum km_type type) default: BUG(); - return 0; + return NULL; } } -- cgit v1.2.3 From be2338f3ceb6d80170ebb495190d6aee79d8c7e3 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 23 Jun 2006 02:04:07 -0700 Subject: [PATCH] frv: wrong syscall The FRV arch should use fstatat64 not newfstatat. Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/frv/kernel/entry.S | 2 +- include/asm-frv/unistd.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/frv/kernel/entry.S b/arch/frv/kernel/entry.S index a9b59527a74..81d94e41a18 100644 --- a/arch/frv/kernel/entry.S +++ b/arch/frv/kernel/entry.S @@ -1474,7 +1474,7 @@ sys_call_table: .long sys_mknodat .long sys_fchownat .long sys_futimesat - .long sys_newfstatat /* 300 */ + .long sys_fstatat64 /* 300 */ .long sys_unlinkat .long sys_renameat .long sys_linkat diff --git a/include/asm-frv/unistd.h b/include/asm-frv/unistd.h index 7c2e712c3b7..91a171decfc 100644 --- a/include/asm-frv/unistd.h +++ b/include/asm-frv/unistd.h @@ -306,7 +306,7 @@ #define __NR_mknodat 297 #define __NR_fchownat 298 #define __NR_futimesat 299 -#define __NR_newfstatat 300 +#define __NR_fstatat64 300 #define __NR_unlinkat 301 #define __NR_renameat 302 #define __NR_linkat 303 -- cgit v1.2.3 From 0c426f26cce71626ed39cd7b9496ea7f460ea9d0 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 23 Jun 2006 02:04:08 -0700 Subject: [PATCH] ext2 XIP won't build without MMU Disable Ext2 XIP if the kernel is configured in no-MMU mode as the former won't build. Signed-off-by: Al Viro Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/Kconfig b/fs/Kconfig index 20f9b557732..2aa4624cc01 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -53,7 +53,7 @@ config EXT2_FS_SECURITY config EXT2_FS_XIP bool "Ext2 execute in place support" - depends on EXT2_FS + depends on EXT2_FS && MMU help Execute in place can be used on memory-backed block devices. If you enable this option, you can select to mount block devices which are -- cgit v1.2.3 From ffca11104c06aff1641b9787f9e5b1099187ff83 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 23 Jun 2006 02:04:09 -0700 Subject: [PATCH] frv: initrd is grossly broken on frv (never built) The FRV arch doesn't currently support initrd, so it should be disabled automatically for the moment. Signed-off-by: Al Viro Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index ae0949b3394..93d94749310 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -402,6 +402,7 @@ config BLK_DEV_RAM_SIZE config BLK_DEV_INITRD bool "Initial RAM filesystem and RAM disk (initramfs/initrd) support" + depends on BROKEN || !FRV help The initial RAM filesystem is a ramfs which is loaded by the boot loader (loadlin or lilo) and that is mounted as root -- cgit v1.2.3 From 7f788435568795c4cd29301bb4ccf7aff54f5051 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 23 Jun 2006 02:04:09 -0700 Subject: [PATCH] frv: NULL noise removal in frv xchg() Clean up the FRV arch's xchg() function. Signed-off-by: Al Viro Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-frv/atomic.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/asm-frv/atomic.h b/include/asm-frv/atomic.h index 9a4ff03c396..066386ac238 100644 --- a/include/asm-frv/atomic.h +++ b/include/asm-frv/atomic.h @@ -227,7 +227,7 @@ extern unsigned long atomic_test_and_XOR_mask(unsigned long mask, volatile unsig break; \ \ default: \ - __xg_orig = 0; \ + __xg_orig = (__typeof__(__xg_orig))0; \ asm volatile("break"); \ break; \ } \ @@ -247,7 +247,7 @@ extern uint32_t __xchg_32(uint32_t i, volatile void *v); switch (sizeof(__xg_orig)) { \ case 4: __xg_orig = (__typeof__(*(ptr))) __xchg_32((uint32_t) x, __xg_ptr); break; \ default: \ - __xg_orig = 0; \ + __xg_orig = (__typeof__(__xg_orig))0; \ asm volatile("break"); \ break; \ } \ -- cgit v1.2.3 From a73df4dfdb0e01a1cbf119416a00e520a5e22306 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 23 Jun 2006 02:04:10 -0700 Subject: [PATCH] frv: ieee1394 is borken on frv The ieee1394 assumes it may make direct use of ->count in the semaphore structure. Signed-off-by: Al Viro Signed-off-by: David Howells Cc: Stefan Richter Cc: Ben Collins Cc: Jody McIntyre Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ieee1394/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ieee1394/Kconfig b/drivers/ieee1394/Kconfig index 186737539cf..79b81be6797 100644 --- a/drivers/ieee1394/Kconfig +++ b/drivers/ieee1394/Kconfig @@ -4,7 +4,7 @@ menu "IEEE 1394 (FireWire) support" config IEEE1394 tristate "IEEE 1394 (FireWire) support" - depends on PCI || BROKEN + depends on (PCI || BROKEN) && (BROKEN || !FRV) select NET help IEEE 1394 describes a high performance serial bus, which is also -- cgit v1.2.3 From 5e591a55576b60156ac3dbc5087660ed82646d66 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 23 Jun 2006 02:04:11 -0700 Subject: [PATCH] frv: Add missing qualifier to memcpy_fromio() prototype The memcpy_fromio() function should have a const qualifier on its source pointer. Signed-off-by: Al Viro Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-frv/io.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/asm-frv/io.h b/include/asm-frv/io.h index f49398a8297..7765f552889 100644 --- a/include/asm-frv/io.h +++ b/include/asm-frv/io.h @@ -116,7 +116,7 @@ static inline void memset_io(volatile void __iomem *addr, unsigned char val, int memset((void __force *) addr, val, count); } -static inline void memcpy_fromio(void *dst, volatile void __iomem *src, int count) +static inline void memcpy_fromio(void *dst, const volatile void __iomem *src, int count) { memcpy(dst, (void __force *) src, count); } -- cgit v1.2.3 From 8ccd05670309084c2dd2003b6840a4becb5acca0 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 23 Jun 2006 02:04:12 -0700 Subject: [PATCH] frv: trivial cleanups in frv_ksyms.c Remove duplicate EXPORT_SYMBOL annotations from the FRV arch. Signed-off-by: Al Viro Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/frv/kernel/frv_ksyms.c | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/arch/frv/kernel/frv_ksyms.c b/arch/frv/kernel/frv_ksyms.c index 0f273a7aca5..dee637fffda 100644 --- a/arch/frv/kernel/frv_ksyms.c +++ b/arch/frv/kernel/frv_ksyms.c @@ -26,16 +26,6 @@ extern long __memset_user(void *dst, const void *src, size_t count); EXPORT_SYMBOL(__ioremap); EXPORT_SYMBOL(iounmap); -EXPORT_SYMBOL(strnlen); -EXPORT_SYMBOL(strrchr); -EXPORT_SYMBOL(strstr); -EXPORT_SYMBOL(strchr); -EXPORT_SYMBOL(strcat); -EXPORT_SYMBOL(strlen); -EXPORT_SYMBOL(strcmp); -EXPORT_SYMBOL(strncmp); -EXPORT_SYMBOL(strncpy); - EXPORT_SYMBOL(ip_fast_csum); #if 0 @@ -44,8 +34,6 @@ EXPORT_SYMBOL(local_bh_count); #endif EXPORT_SYMBOL(kernel_thread); -EXPORT_SYMBOL(enable_irq); -EXPORT_SYMBOL(disable_irq); EXPORT_SYMBOL(__res_bus_clock_speed_HZ); EXPORT_SYMBOL(__page_offset); EXPORT_SYMBOL(__memcpy_user); @@ -62,18 +50,12 @@ EXPORT_SYMBOL(memory_end); EXPORT_SYMBOL(__debug_bug_trap); -/* Networking helper routines. */ -EXPORT_SYMBOL(csum_partial_copy); - /* The following are special because they're not called explicitly (the C compiler generates them). Fortunately, their interface isn't gonna change any time soon now, so it's OK to leave it out of version control. */ EXPORT_SYMBOL(memcpy); EXPORT_SYMBOL(memset); -EXPORT_SYMBOL(memcmp); -EXPORT_SYMBOL(memscan); -EXPORT_SYMBOL(memmove); EXPORT_SYMBOL(__outsl_ns); EXPORT_SYMBOL(__insl_ns); -- cgit v1.2.3 From c52c17622e27876c2395f59cfe342497a399de41 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 23 Jun 2006 02:04:13 -0700 Subject: [PATCH] frv: clean frv unistd.h Remove _syscall invocations that aren't used in the kernel. Signed-off-by: Al Viro Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-frv/unistd.h | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/include/asm-frv/unistd.h b/include/asm-frv/unistd.h index 91a171decfc..b80dbd83947 100644 --- a/include/asm-frv/unistd.h +++ b/include/asm-frv/unistd.h @@ -460,24 +460,7 @@ type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg * some others too. */ #define __NR__exit __NR_exit -static inline _syscall0(int,pause) -static inline _syscall0(int,sync) -static inline _syscall0(pid_t,setsid) -static inline _syscall3(int,write,int,fd,const char *,buf,off_t,count) -static inline _syscall3(int,read,int,fd,char *,buf,off_t,count) -static inline _syscall3(off_t,lseek,int,fd,off_t,offset,int,count) -static inline _syscall1(int,dup,int,fd) static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp) -static inline _syscall3(int,open,const char *,file,int,flag,int,mode) -static inline _syscall1(int,close,int,fd) -static inline _syscall1(int,_exit,int,exitcode) -static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options) -static inline _syscall1(int,delete_module,const char *,name) - -static inline pid_t wait(int * wait_stat) -{ - return waitpid(-1,wait_stat,0); -} #endif /* __KERNEL_SYSCALLS__ */ -- cgit v1.2.3 From f2c780c1fdbe5008c902c2d7e37242ac5e60f0b9 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Fri, 23 Jun 2006 02:04:13 -0700 Subject: [PATCH] Au1550/1200: add missing PSC #define's, make OSS driver use the proper ones Add missing PSC #define's required for the drivers using PSC on DBAu1550 board (also fixing Au1550 PSC3 address) and all Au1200-based boards as well. Make the OSS driver use the correct PSC definitions fo each board. Signed-off-by: Sergei Shtylyov Cc: Ralf Baechle Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-mips/mach-au1x00/au1xxx_psc.h | 9 ++++++++- include/asm-mips/mach-db1x00/db1x00.h | 12 ++++++++++++ sound/oss/au1550_ac97.c | 2 +- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/include/asm-mips/mach-au1x00/au1xxx_psc.h b/include/asm-mips/mach-au1x00/au1xxx_psc.h index 5c3e2a38ce1..d7cbacdd21f 100644 --- a/include/asm-mips/mach-au1x00/au1xxx_psc.h +++ b/include/asm-mips/mach-au1x00/au1xxx_psc.h @@ -39,7 +39,12 @@ #define PSC0_BASE_ADDR 0xb1a00000 #define PSC1_BASE_ADDR 0xb1b00000 #define PSC2_BASE_ADDR 0xb0a00000 -#define PSC3_BASE_ADDR 0xb0d00000 +#define PSC3_BASE_ADDR 0xb0b00000 +#endif + +#ifdef CONFIG_SOC_AU1200 +#define PSC0_BASE_ADDR 0xb1a00000 +#define PSC1_BASE_ADDR 0xb1b00000 #endif /* The PSC select and control registers are common to @@ -227,6 +232,8 @@ typedef struct psc_i2s { #define PSC_I2SCFG_DD_DISABLE (1 << 27) #define PSC_I2SCFG_DE_ENABLE (1 << 26) #define PSC_I2SCFG_SET_WS(x) (((((x) / 2) - 1) & 0x7f) << 16) +#define PSC_I2SCFG_WS(n) ((n & 0xFF) << 16) +#define PSC_I2SCFG_WS_MASK (PSC_I2SCFG_WS(0x3F)) #define PSC_I2SCFG_WI (1 << 15) #define PSC_I2SCFG_DIV_MASK (3 << 13) diff --git a/include/asm-mips/mach-db1x00/db1x00.h b/include/asm-mips/mach-db1x00/db1x00.h index 8fbb4b42a8b..0f5f4c29f4e 100644 --- a/include/asm-mips/mach-db1x00/db1x00.h +++ b/include/asm-mips/mach-db1x00/db1x00.h @@ -30,8 +30,20 @@ #ifdef CONFIG_MIPS_DB1550 + +#define DBDMA_AC97_TX_CHAN DSCR_CMD0_PSC1_TX +#define DBDMA_AC97_RX_CHAN DSCR_CMD0_PSC1_RX +#define DBDMA_I2S_TX_CHAN DSCR_CMD0_PSC3_TX +#define DBDMA_I2S_RX_CHAN DSCR_CMD0_PSC3_RX + +#define SPI_PSC_BASE PSC0_BASE_ADDR +#define AC97_PSC_BASE PSC1_BASE_ADDR +#define SMBUS_PSC_BASE PSC2_BASE_ADDR +#define I2S_PSC_BASE PSC3_BASE_ADDR + #define BCSR_KSEG1_ADDR 0xAF000000 #define NAND_PHYS_ADDR 0x20000000 + #else #define BCSR_KSEG1_ADDR 0xAE000000 #endif diff --git a/sound/oss/au1550_ac97.c b/sound/oss/au1550_ac97.c index c1168fae6be..9011abe241a 100644 --- a/sound/oss/au1550_ac97.c +++ b/sound/oss/au1550_ac97.c @@ -57,9 +57,9 @@ #include #include #include -#include #include #include +#include #undef OSS_DOCUMENTED_MIXER_SEMANTICS -- cgit v1.2.3 From 7dbdf43cfa635ddc3701cc8d1eab07597cd731c0 Mon Sep 17 00:00:00 2001 From: Yoichi Yuasa Date: Fri, 23 Jun 2006 02:04:14 -0700 Subject: [PATCH] mips: fix number of mremap arguments mremap syscall takes 5 arguments. Fixed by Ralf Baechle. Signed-off-by: Ralf Baechle Signed-off-by: Yoichi Yuasa Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/mips/kernel/scall32-o32.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S index a0ac0e5f61a..2d2fdf77e30 100644 --- a/arch/mips/kernel/scall32-o32.S +++ b/arch/mips/kernel/scall32-o32.S @@ -497,7 +497,7 @@ einval: li v0, -EINVAL sys sys_sched_get_priority_min 1 sys sys_sched_rr_get_interval 2 /* 4165 */ sys sys_nanosleep, 2 - sys sys_mremap, 4 + sys sys_mremap, 5 sys sys_accept 3 sys sys_bind 3 sys sys_connect 3 /* 4170 */ -- cgit v1.2.3 From c22ce143d15eb288543fe9873e1c5ac1c01b69a1 Mon Sep 17 00:00:00 2001 From: Hiro Yoshioka Date: Fri, 23 Jun 2006 02:04:16 -0700 Subject: [PATCH] x86: cache pollution aware __copy_from_user_ll() Use the x86 cache-bypassing copy instructions for copy_from_user(). Some performance data are Total of GLOBAL_POWER_EVENTS (CPU cycle samples) 2.6.12.4.orig 1921587 2.6.12.4.nt 1599424 1599424/1921587=83.23% (16.77% reduction) BSQ_CACHE_REFERENCE (L3 cache miss) 2.6.12.4.orig 57427 2.6.12.4.nt 20858 20858/57427=36.32% (63.7% reduction) L3 cache miss reduction of __copy_from_user_ll samples % 37408 65.1412 vmlinux __copy_from_user_ll 23 0.1103 vmlinux __copy_user_zeroing_intel_nocache 23/37408=0.061% (99.94% reduction) Top 5 of 2.6.12.4.nt Counted GLOBAL_POWER_EVENTS events (time during which processor is not stopped) with a unit mask of 0x01 (mandatory) count 100000 samples % app name symbol name 128392 8.0274 vmlinux __copy_user_zeroing_intel_nocache 64206 4.0143 vmlinux journal_add_journal_head 59746 3.7355 vmlinux do_get_write_access 47674 2.9807 vmlinux journal_put_journal_head 46021 2.8774 vmlinux journal_dirty_metadata pattern9-0-cpu4-0-09011728/summary.out Counted BSQ_CACHE_REFERENCE events (cache references seen by the bus unit) with a unit mask of 0x3f (multiple flags) count 3000 samples % app name symbol name 69755 4.2861 vmlinux __copy_user_zeroing_intel_nocache 55685 3.4215 vmlinux journal_add_journal_head 52371 3.2179 vmlinux __find_get_block 45504 2.7960 vmlinux journal_put_journal_head 36005 2.2123 vmlinux journal_stop pattern9-0-cpu4-0-09011744/summary.out Counted BSQ_CACHE_REFERENCE events (cache references seen by the bus unit) with a unit mask of 0x200 (read 3rd level cache miss) count 3000 samples % app name symbol name 1147 5.4994 vmlinux journal_add_journal_head 881 4.2240 vmlinux journal_dirty_data 872 4.1809 vmlinux blk_rq_map_sg 734 3.5192 vmlinux journal_commit_transaction 617 2.9582 vmlinux radix_tree_delete pattern9-0-cpu4-0-09011731/summary.out iozone results are original 2.6.12.4 CPU time = 207.768 sec cache aware CPU time = 184.783 sec (three times run) 184.783/207.768=88.94% (11.06% reduction) original: pattern9-0-cpu4-0-08191720/iozone.out: CPU Utilization: Wall time 45.997 CPU time 64.527 CPU utilization 140.28 % pattern9-0-cpu4-0-08191741/iozone.out: CPU Utilization: Wall time 46.878 CPU time 71.933 CPU utilization 153.45 % pattern9-0-cpu4-0-08191743/iozone.out: CPU Utilization: Wall time 45.152 CPU time 71.308 CPU utilization 157.93 % cache awre: pattern9-0-cpu4-0-09011728/iozone.out: CPU Utilization: Wall time 44.842 CPU time 62.465 CPU utilization 139.30 % pattern9-0-cpu4-0-09011731/iozone.out: CPU Utilization: Wall time 44.718 CPU time 59.273 CPU utilization 132.55 % pattern9-0-cpu4-0-09011744/iozone.out: CPU Utilization: Wall time 44.367 CPU time 63.045 CPU utilization 142.10 % Signed-off-by: Hiro Yoshioka Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/lib/usercopy.c | 137 ++++++++++++++++++++++++++++++++++++++++++--- include/asm-i386/uaccess.h | 33 +++++++++++ include/linux/uaccess.h | 22 ++++++++ mm/filemap.c | 4 +- mm/filemap.h | 6 +- 5 files changed, 189 insertions(+), 13 deletions(-) create mode 100644 include/linux/uaccess.h diff --git a/arch/i386/lib/usercopy.c b/arch/i386/lib/usercopy.c index 4cf981d70f4..6979297ce27 100644 --- a/arch/i386/lib/usercopy.c +++ b/arch/i386/lib/usercopy.c @@ -425,15 +425,121 @@ __copy_user_zeroing_intel(void *to, const void __user *from, unsigned long size) : "eax", "edx", "memory"); return size; } + +/* + * Non Temporal Hint version of __copy_user_zeroing_intel. It is cache aware. + * hyoshiok@miraclelinux.com + */ + +static unsigned long __copy_user_zeroing_intel_nocache(void *to, + const void __user *from, unsigned long size) +{ + int d0, d1; + + __asm__ __volatile__( + " .align 2,0x90\n" + "0: movl 32(%4), %%eax\n" + " cmpl $67, %0\n" + " jbe 2f\n" + "1: movl 64(%4), %%eax\n" + " .align 2,0x90\n" + "2: movl 0(%4), %%eax\n" + "21: movl 4(%4), %%edx\n" + " movnti %%eax, 0(%3)\n" + " movnti %%edx, 4(%3)\n" + "3: movl 8(%4), %%eax\n" + "31: movl 12(%4),%%edx\n" + " movnti %%eax, 8(%3)\n" + " movnti %%edx, 12(%3)\n" + "4: movl 16(%4), %%eax\n" + "41: movl 20(%4), %%edx\n" + " movnti %%eax, 16(%3)\n" + " movnti %%edx, 20(%3)\n" + "10: movl 24(%4), %%eax\n" + "51: movl 28(%4), %%edx\n" + " movnti %%eax, 24(%3)\n" + " movnti %%edx, 28(%3)\n" + "11: movl 32(%4), %%eax\n" + "61: movl 36(%4), %%edx\n" + " movnti %%eax, 32(%3)\n" + " movnti %%edx, 36(%3)\n" + "12: movl 40(%4), %%eax\n" + "71: movl 44(%4), %%edx\n" + " movnti %%eax, 40(%3)\n" + " movnti %%edx, 44(%3)\n" + "13: movl 48(%4), %%eax\n" + "81: movl 52(%4), %%edx\n" + " movnti %%eax, 48(%3)\n" + " movnti %%edx, 52(%3)\n" + "14: movl 56(%4), %%eax\n" + "91: movl 60(%4), %%edx\n" + " movnti %%eax, 56(%3)\n" + " movnti %%edx, 60(%3)\n" + " addl $-64, %0\n" + " addl $64, %4\n" + " addl $64, %3\n" + " cmpl $63, %0\n" + " ja 0b\n" + " sfence \n" + "5: movl %0, %%eax\n" + " shrl $2, %0\n" + " andl $3, %%eax\n" + " cld\n" + "6: rep; movsl\n" + " movl %%eax,%0\n" + "7: rep; movsb\n" + "8:\n" + ".section .fixup,\"ax\"\n" + "9: lea 0(%%eax,%0,4),%0\n" + "16: pushl %0\n" + " pushl %%eax\n" + " xorl %%eax,%%eax\n" + " rep; stosb\n" + " popl %%eax\n" + " popl %0\n" + " jmp 8b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" + " .align 4\n" + " .long 0b,16b\n" + " .long 1b,16b\n" + " .long 2b,16b\n" + " .long 21b,16b\n" + " .long 3b,16b\n" + " .long 31b,16b\n" + " .long 4b,16b\n" + " .long 41b,16b\n" + " .long 10b,16b\n" + " .long 51b,16b\n" + " .long 11b,16b\n" + " .long 61b,16b\n" + " .long 12b,16b\n" + " .long 71b,16b\n" + " .long 13b,16b\n" + " .long 81b,16b\n" + " .long 14b,16b\n" + " .long 91b,16b\n" + " .long 6b,9b\n" + " .long 7b,16b\n" + ".previous" + : "=&c"(size), "=&D" (d0), "=&S" (d1) + : "1"(to), "2"(from), "0"(size) + : "eax", "edx", "memory"); + return size; +} + #else + /* * Leave these declared but undefined. They should not be any references to * them */ -unsigned long -__copy_user_zeroing_intel(void *to, const void __user *from, unsigned long size); -unsigned long -__copy_user_intel(void __user *to, const void *from, unsigned long size); +unsigned long __copy_user_zeroing_intel(void *to, const void __user *from, + unsigned long size); +unsigned long __copy_user_intel(void __user *to, const void *from, + unsigned long size); +unsigned long __copy_user_zeroing_intel_nocache(void *to, + const void __user *from, unsigned long size); #endif /* CONFIG_X86_INTEL_USERCOPY */ /* Generic arbitrary sized copy. */ @@ -515,8 +621,8 @@ do { \ : "memory"); \ } while (0) - -unsigned long __copy_to_user_ll(void __user *to, const void *from, unsigned long n) +unsigned long __copy_to_user_ll(void __user *to, const void *from, + unsigned long n) { BUG_ON((long) n < 0); #ifndef CONFIG_X86_WP_WORKS_OK @@ -576,8 +682,8 @@ survive: } EXPORT_SYMBOL(__copy_to_user_ll); -unsigned long -__copy_from_user_ll(void *to, const void __user *from, unsigned long n) +unsigned long __copy_from_user_ll(void *to, const void __user *from, + unsigned long n) { BUG_ON((long)n < 0); if (movsl_is_ok(to, from, n)) @@ -588,6 +694,21 @@ __copy_from_user_ll(void *to, const void __user *from, unsigned long n) } EXPORT_SYMBOL(__copy_from_user_ll); +unsigned long __copy_from_user_ll_nocache(void *to, const void __user *from, + unsigned long n) +{ + BUG_ON((long)n < 0); +#ifdef CONFIG_X86_INTEL_USERCOPY + if ( n > 64 && cpu_has_xmm2) + n = __copy_user_zeroing_intel_nocache(to, from, n); + else + __copy_user_zeroing(to, from, n); +#else + __copy_user_zeroing(to, from, n); +#endif + return n; +} + /** * copy_to_user: - Copy a block of data into user space. * @to: Destination address, in user space. diff --git a/include/asm-i386/uaccess.h b/include/asm-i386/uaccess.h index 1ec65523ea5..82af28a943a 100644 --- a/include/asm-i386/uaccess.h +++ b/include/asm-i386/uaccess.h @@ -390,6 +390,8 @@ unsigned long __must_check __copy_to_user_ll(void __user *to, const void *from, unsigned long n); unsigned long __must_check __copy_from_user_ll(void *to, const void __user *from, unsigned long n); +unsigned long __must_check __copy_from_user_ll_nocache(void *to, + const void __user *from, unsigned long n); /* * Here we special-case 1, 2 and 4-byte copy_*_user invocations. On a fault @@ -478,12 +480,43 @@ __copy_from_user_inatomic(void *to, const void __user *from, unsigned long n) return __copy_from_user_ll(to, from, n); } +#define ARCH_HAS_NOCACHE_UACCESS + +static __always_inline unsigned long __copy_from_user_inatomic_nocache(void *to, + const void __user *from, unsigned long n) +{ + if (__builtin_constant_p(n)) { + unsigned long ret; + + switch (n) { + case 1: + __get_user_size(*(u8 *)to, from, 1, ret, 1); + return ret; + case 2: + __get_user_size(*(u16 *)to, from, 2, ret, 2); + return ret; + case 4: + __get_user_size(*(u32 *)to, from, 4, ret, 4); + return ret; + } + } + return __copy_from_user_ll_nocache(to, from, n); +} + static __always_inline unsigned long __copy_from_user(void *to, const void __user *from, unsigned long n) { might_sleep(); return __copy_from_user_inatomic(to, from, n); } + +static __always_inline unsigned long +__copy_from_user_nocache(void *to, const void __user *from, unsigned long n) +{ + might_sleep(); + return __copy_from_user_inatomic_nocache(to, from, n); +} + unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n); unsigned long __must_check copy_from_user(void *to, diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h new file mode 100644 index 00000000000..391e7ed1eb3 --- /dev/null +++ b/include/linux/uaccess.h @@ -0,0 +1,22 @@ +#ifndef __LINUX_UACCESS_H__ +#define __LINUX_UACCESS_H__ + +#include + +#ifndef ARCH_HAS_NOCACHE_UACCESS + +static inline unsigned long __copy_from_user_inatomic_nocache(void *to, + const void __user *from, unsigned long n) +{ + return __copy_from_user_inatomic(to, from, n); +} + +static inline unsigned long __copy_from_user_nocache(void *to, + const void __user *from, unsigned long n) +{ + return __copy_from_user(to, from, n); +} + +#endif /* ARCH_HAS_NOCACHE_UACCESS */ + +#endif /* __LINUX_UACCESS_H__ */ diff --git a/mm/filemap.c b/mm/filemap.c index 368678c2d53..807a463fd5e 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -38,7 +39,6 @@ */ #include /* for generic_osync_inode */ -#include #include static ssize_t @@ -1902,7 +1902,7 @@ __filemap_copy_from_user_iovec(char *vaddr, int copy = min(bytes, iov->iov_len - base); base = 0; - left = __copy_from_user_inatomic(vaddr, buf, copy); + left = __copy_from_user_inatomic_nocache(vaddr, buf, copy); copied += copy; bytes -= copy; vaddr += copy; diff --git a/mm/filemap.h b/mm/filemap.h index 13793ba0ce1..5683cde2205 100644 --- a/mm/filemap.h +++ b/mm/filemap.h @@ -13,7 +13,7 @@ #include #include #include -#include +#include size_t __filemap_copy_from_user_iovec(char *vaddr, @@ -34,13 +34,13 @@ filemap_copy_from_user(struct page *page, unsigned long offset, int left; kaddr = kmap_atomic(page, KM_USER0); - left = __copy_from_user_inatomic(kaddr + offset, buf, bytes); + left = __copy_from_user_inatomic_nocache(kaddr + offset, buf, bytes); kunmap_atomic(kaddr, KM_USER0); if (left != 0) { /* Do it the slow way */ kaddr = kmap(page); - left = __copy_from_user(kaddr + offset, buf, bytes); + left = __copy_from_user_nocache(kaddr + offset, buf, bytes); kunmap(page); } return bytes - left; -- cgit v1.2.3 From a0b4da91f4c5710b9c20219a19e905145647b48b Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Fri, 23 Jun 2006 02:04:17 -0700 Subject: [PATCH] arch/i386/kernel/apic.c: make modern_apic() static Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/apic.c | 2 +- include/asm-i386/apic.h | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c index 3d4b2f3d116..261796ff83c 100644 --- a/arch/i386/kernel/apic.c +++ b/arch/i386/kernel/apic.c @@ -62,7 +62,7 @@ int apic_verbosity; static void apic_pm_activate(void); -int modern_apic(void) +static int modern_apic(void) { unsigned int lvr, version; /* AMD systems use old APIC versions, so check the CPU */ diff --git a/include/asm-i386/apic.h b/include/asm-i386/apic.h index cc9b940fb7e..1d8362cb2c5 100644 --- a/include/asm-i386/apic.h +++ b/include/asm-i386/apic.h @@ -138,8 +138,6 @@ void switch_ipi_to_APIC_timer(void *cpumask); extern int timer_over_8254; -extern int modern_apic(void); - #else /* !CONFIG_X86_LOCAL_APIC */ static inline void lapic_shutdown(void) { } -- cgit v1.2.3 From 87af2ffd4ccd0e6a2ff316fd008a9bedb4a4cb66 Mon Sep 17 00:00:00 2001 From: Andreas Mohr Date: Fri, 23 Jun 2006 02:04:17 -0700 Subject: [PATCH] i386 apm.c optimization - avoid expensive modulo (integer division) which happened since APM_MAX_EVENTS is 20 (non-power-of-2) - kill compiler warnings by initializing two variables - add __read_mostly to some important static variables that are read often (by idle loop etc.) - constify several structures Signed-off-by: Andreas Mohr Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/apm.c | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c index df0e1745f18..9e819eb6822 100644 --- a/arch/i386/kernel/apm.c +++ b/arch/i386/kernel/apm.c @@ -374,14 +374,14 @@ static struct { unsigned short segment; } apm_bios_entry; static int clock_slowed; -static int idle_threshold = DEFAULT_IDLE_THRESHOLD; -static int idle_period = DEFAULT_IDLE_PERIOD; +static int idle_threshold __read_mostly = DEFAULT_IDLE_THRESHOLD; +static int idle_period __read_mostly = DEFAULT_IDLE_PERIOD; static int set_pm_idle; static int suspends_pending; static int standbys_pending; static int ignore_sys_suspend; static int ignore_normal_resume; -static int bounce_interval = DEFAULT_BOUNCE_INTERVAL; +static int bounce_interval __read_mostly = DEFAULT_BOUNCE_INTERVAL; #ifdef CONFIG_APM_RTC_IS_GMT # define clock_cmos_diff 0 @@ -390,8 +390,8 @@ static int bounce_interval = DEFAULT_BOUNCE_INTERVAL; static long clock_cmos_diff; static int got_clock_diff; #endif -static int debug; -static int smp; +static int debug __read_mostly; +static int smp __read_mostly; static int apm_disabled = -1; #ifdef CONFIG_SMP static int power_off; @@ -403,8 +403,8 @@ static int realmode_power_off = 1; #else static int realmode_power_off; #endif -static int exit_kapmd; -static int kapmd_running; +static int exit_kapmd __read_mostly; +static int kapmd_running __read_mostly; #ifdef CONFIG_APM_ALLOW_INTS static int allow_ints = 1; #else @@ -416,15 +416,15 @@ static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue); static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue); static struct apm_user * user_list; static DEFINE_SPINLOCK(user_list_lock); -static struct desc_struct bad_bios_desc = { 0, 0x00409200 }; +static const struct desc_struct bad_bios_desc = { 0, 0x00409200 }; -static char driver_version[] = "1.16ac"; /* no spaces */ +static const char driver_version[] = "1.16ac"; /* no spaces */ /* * APM event names taken from the APM 1.2 specification. These are * the message codes that the BIOS uses to tell us about events */ -static char * apm_event_name[] = { +static const char * const apm_event_name[] = { "system standby", "system suspend", "normal resume", @@ -616,7 +616,7 @@ static u8 apm_bios_call(u32 func, u32 ebx_in, u32 ecx_in, * @ecx_in: ECX register value for BIOS call * @eax: EAX register on return from the BIOS call * - * Make a BIOS call that does only returns one value, or just status. + * Make a BIOS call that returns one value only, or just status. * If there is an error, then the error code is returned in AH * (bits 8-15 of eax) and this function returns non-zero. This is * used for simpler BIOS operations. This call may hold interrupts @@ -822,7 +822,7 @@ static void apm_do_busy(void) #define IDLE_CALC_LIMIT (HZ * 100) #define IDLE_LEAKY_MAX 16 -static void (*original_pm_idle)(void); +static void (*original_pm_idle)(void) __read_mostly; /** * apm_cpu_idle - cpu idling for APM capable Linux @@ -1063,7 +1063,8 @@ static int apm_engage_power_management(u_short device, int enable) static int apm_console_blank(int blank) { - int error, i; + int error = APM_NOT_ENGAGED; /* silence gcc */ + int i; u_short state; static const u_short dev[3] = { 0x100, 0x1FF, 0x101 }; @@ -1104,7 +1105,8 @@ static int queue_empty(struct apm_user *as) static apm_event_t get_queued_event(struct apm_user *as) { - as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS; + if (++as->event_tail >= APM_MAX_EVENTS) + as->event_tail = 0; return as->events[as->event_tail]; } @@ -1118,13 +1120,16 @@ static void queue_event(apm_event_t event, struct apm_user *sender) for (as = user_list; as != NULL; as = as->next) { if ((as == sender) || (!as->reader)) continue; - as->event_head = (as->event_head + 1) % APM_MAX_EVENTS; + if (++as->event_head >= APM_MAX_EVENTS) + as->event_head = 0; + if (as->event_head == as->event_tail) { static int notified; if (notified++ == 0) printk(KERN_ERR "apm: an event queue overflowed\n"); - as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS; + if (++as->event_tail >= APM_MAX_EVENTS) + as->event_tail = 0; } as->events[as->event_head] = event; if ((!as->suser) || (!as->writer)) @@ -1282,7 +1287,7 @@ static void standby(void) static apm_event_t get_event(void) { int error; - apm_event_t event; + apm_event_t event = APM_NO_EVENTS; /* silence gcc */ apm_eventinfo_t info; static int notified; -- cgit v1.2.3 From 27b07da7332f03a935cd13b6a6beb780bf19e7a4 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Fri, 23 Jun 2006 02:04:18 -0700 Subject: [PATCH] Don't trigger full rebuild via CONFIG_MTRR Only drm, framebuffer, mtrr parts + misc files here and there. Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/cpu/common.c | 1 + arch/i386/power/cpu.c | 1 + include/asm-i386/mtrr.h | 4 ++++ include/asm-i386/processor.h | 8 -------- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c index a06a49075f1..f2a2b0ac9a1 100644 --- a/arch/i386/kernel/cpu/common.c +++ b/arch/i386/kernel/cpu/common.c @@ -11,6 +11,7 @@ #include #include #include +#include #ifdef CONFIG_X86_LOCAL_APIC #include #include diff --git a/arch/i386/power/cpu.c b/arch/i386/power/cpu.c index 79b2370c7fa..63d25ca6306 100644 --- a/arch/i386/power/cpu.c +++ b/arch/i386/power/cpu.c @@ -10,6 +10,7 @@ #include #include #include +#include static struct saved_context saved_context; diff --git a/include/asm-i386/mtrr.h b/include/asm-i386/mtrr.h index 5a46de08efe..07f063ae26e 100644 --- a/include/asm-i386/mtrr.h +++ b/include/asm-i386/mtrr.h @@ -76,6 +76,8 @@ extern int mtrr_add_page (unsigned long base, unsigned long size, extern int mtrr_del (int reg, unsigned long base, unsigned long size); extern int mtrr_del_page (int reg, unsigned long base, unsigned long size); extern void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi); +extern void mtrr_ap_init(void); +extern void mtrr_bp_init(void); # else static __inline__ int mtrr_add (unsigned long base, unsigned long size, unsigned int type, char increment) @@ -100,6 +102,8 @@ static __inline__ int mtrr_del_page (int reg, unsigned long base, static __inline__ void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi) {;} +#define mtrr_ap_init() do {} while (0) +#define mtrr_bp_init() do {} while (0) # endif #endif diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h index 4df3818e412..5116465272e 100644 --- a/include/asm-i386/processor.h +++ b/include/asm-i386/processor.h @@ -728,14 +728,6 @@ extern unsigned long boot_option_idle_override; extern void enable_sep_cpu(void); extern int sysenter_setup(void); -#ifdef CONFIG_MTRR -extern void mtrr_ap_init(void); -extern void mtrr_bp_init(void); -#else -#define mtrr_ap_init() do {} while (0) -#define mtrr_bp_init() do {} while (0) -#endif - #ifdef CONFIG_X86_MCE extern void mcheck_init(struct cpuinfo_x86 *c); #else -- cgit v1.2.3 From ba528f2854e8632c8d04ddcd45f06c47bc7188b0 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Fri, 23 Jun 2006 02:04:19 -0700 Subject: [PATCH] fix x86 microcode driver handling of multiple matching revisions When multiple updates matching a given CPU are found in the update file, the action taken by the microcode update driver was inappropriate: - when lower revision microcode was found before matching or higher revision one, the driver would needlessly complain that it would not downgrade the CPU - when microcode matching the currently installed revision was found before newer revision code, no update would actually take place To change this behavior, the driver now concludes about possibly updates and issues messages only when the entire input was parsed. Additionally, this adds back (in different places, and conditionalized upon a new module option) some messages removed by a previous patch. Signed-off-by: Jan Beulich Cc: "Siddha, Suresh B" Cc: Tigran Aivazian Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/microcode.c | 73 +++++++++++++++++++++++++++++--------------- 1 file changed, 49 insertions(+), 24 deletions(-) diff --git a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c index e7c138f66c5..0a865889b2a 100644 --- a/arch/i386/kernel/microcode.c +++ b/arch/i386/kernel/microcode.c @@ -91,7 +91,10 @@ MODULE_DESCRIPTION("Intel CPU (IA-32) Microcode Update Driver"); MODULE_AUTHOR("Tigran Aivazian "); MODULE_LICENSE("GPL"); -#define MICROCODE_VERSION "1.14" +static int verbose; +module_param(verbose, int, 0644); + +#define MICROCODE_VERSION "1.14a" #define DEFAULT_UCODE_DATASIZE (2000) /* 2000 bytes */ #define MC_HEADER_SIZE (sizeof (microcode_header_t)) /* 48 bytes */ @@ -122,14 +125,15 @@ static unsigned int user_buffer_size; /* it's size */ typedef enum mc_error_code { MC_SUCCESS = 0, - MC_NOTFOUND = 1, - MC_MARKED = 2, - MC_ALLOCATED = 3, + MC_IGNORED = 1, + MC_NOTFOUND = 2, + MC_MARKED = 3, + MC_ALLOCATED = 4, } mc_error_code_t; static struct ucode_cpu_info { unsigned int sig; - unsigned int pf; + unsigned int pf, orig_pf; unsigned int rev; unsigned int cksum; mc_error_code_t err; @@ -164,6 +168,7 @@ static void collect_cpu_info (void *unused) rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]); uci->pf = 1 << ((val[1] >> 18) & 7); } + uci->orig_pf = uci->pf; } wrmsr(MSR_IA32_UCODE_REV, 0, 0); @@ -197,21 +202,34 @@ static inline void mark_microcode_update (int cpu_num, microcode_header_t *mc_he pr_debug(" Checksum 0x%x\n", cksum); if (mc_header->rev < uci->rev) { - printk(KERN_ERR "microcode: CPU%d not 'upgrading' to earlier revision" - " 0x%x (current=0x%x)\n", cpu_num, mc_header->rev, uci->rev); - goto out; + if (uci->err == MC_NOTFOUND) { + uci->err = MC_IGNORED; + uci->cksum = mc_header->rev; + } else if (uci->err == MC_IGNORED && uci->cksum < mc_header->rev) + uci->cksum = mc_header->rev; } else if (mc_header->rev == uci->rev) { - /* notify the caller of success on this cpu */ - uci->err = MC_SUCCESS; - goto out; + if (uci->err < MC_MARKED) { + /* notify the caller of success on this cpu */ + uci->err = MC_SUCCESS; + } + } else if (uci->err != MC_ALLOCATED || mc_header->rev > uci->mc->hdr.rev) { + pr_debug("microcode: CPU%d found a matching microcode update with " + " revision 0x%x (current=0x%x)\n", cpu_num, mc_header->rev, uci->rev); + uci->cksum = cksum; + uci->pf = pf; /* keep the original mc pf for cksum calculation */ + uci->err = MC_MARKED; /* found the match */ + for_each_online_cpu(cpu_num) { + if (ucode_cpu_info + cpu_num != uci + && ucode_cpu_info[cpu_num].mc == uci->mc) { + uci->mc = NULL; + break; + } + } + if (uci->mc != NULL) { + vfree(uci->mc); + uci->mc = NULL; + } } - - pr_debug("microcode: CPU%d found a matching microcode update with " - " revision 0x%x (current=0x%x)\n", cpu_num, mc_header->rev, uci->rev); - uci->cksum = cksum; - uci->pf = pf; /* keep the original mc pf for cksum calculation */ - uci->err = MC_MARKED; /* found the match */ -out: return; } @@ -253,10 +271,8 @@ static int find_matching_ucodes (void) for_each_online_cpu(cpu_num) { struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; - if (uci->err != MC_NOTFOUND) /* already found a match or not an online cpu*/ - continue; - if (sigmatch(mc_header.sig, uci->sig, mc_header.pf, uci->pf)) + if (sigmatch(mc_header.sig, uci->sig, mc_header.pf, uci->orig_pf)) mark_microcode_update(cpu_num, &mc_header, mc_header.sig, mc_header.pf, mc_header.cksum); } @@ -295,9 +311,8 @@ static int find_matching_ucodes (void) } for_each_online_cpu(cpu_num) { struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; - if (uci->err != MC_NOTFOUND) /* already found a match or not an online cpu*/ - continue; - if (sigmatch(ext_sig.sig, uci->sig, ext_sig.pf, uci->pf)) { + + if (sigmatch(ext_sig.sig, uci->sig, ext_sig.pf, uci->orig_pf)) { mark_microcode_update(cpu_num, &mc_header, ext_sig.sig, ext_sig.pf, ext_sig.cksum); } } @@ -368,6 +383,13 @@ static void do_update_one (void * unused) struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; if (uci->mc == NULL) { + if (verbose) { + if (uci->err == MC_SUCCESS) + printk(KERN_INFO "microcode: CPU%d already at revision 0x%x\n", + cpu_num, uci->rev); + else + printk(KERN_INFO "microcode: No new microcode data for CPU%d\n", cpu_num); + } return; } @@ -426,6 +448,9 @@ out_free: ucode_cpu_info[j].mc = NULL; } } + if (ucode_cpu_info[i].err == MC_IGNORED && verbose) + printk(KERN_WARNING "microcode: CPU%d not 'upgrading' to earlier revision" + " 0x%x (current=0x%x)\n", i, ucode_cpu_info[i].cksum, ucode_cpu_info[i].rev); } out: return error; -- cgit v1.2.3 From b88d4f1d390a6a232938d27d551f24cf08a2c7e0 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Fri, 23 Jun 2006 02:04:20 -0700 Subject: [PATCH] i386: break out of recursion in stackframe walk If CONFIG_FRAME_POINTERS is enabled, and one does a dump_stack() during early SMP init, an infinite stackdump and a bootup hang happens: [] show_trace+0xd/0xf [] dump_stack+0x15/0x17 [] save_trace+0xc3/0xce [] mark_lock+0x8c/0x4fe [] __lockdep_acquire+0x44e/0xaa5 [] lockdep_acquire+0x68/0x84 [] _spin_lock+0x21/0x2f [] prepare_set+0xd/0x5d [] generic_set_all+0x1d/0x201 [] mtrr_ap_init+0x23/0x3b [] identify_cpu+0x2a7/0x2af [] smp_store_cpu_info+0x2f/0xb4 [] start_secondary+0xb5/0x3ec [] end_of_stack_stop_unwind_function+0x1/0x4 [] end_of_stack_stop_unwind_function+0x1/0x4 [] end_of_stack_stop_unwind_function+0x1/0x4 [] end_of_stack_stop_unwind_function+0x1/0x4 [] end_of_stack_stop_unwind_function+0x1/0x4 [] end_of_stack_stop_unwind_function+0x1/0x4 [] end_of_stack_stop_unwind_function+0x1/0x4 [] end_of_stack_stop_unwind_function+0x1/0x4 [...] Due to "end_of_stack_stop_unwind_function" recursing back to itself in the EBP stackframe-walker. So avoid this type of recursion when walking the stack . Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/traps.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index 0e498369f35..df9d210626a 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -149,6 +149,12 @@ static inline unsigned long print_context_stack(struct thread_info *tinfo, while (valid_stack_ptr(tinfo, (void *)ebp)) { addr = *(unsigned long *)(ebp + 4); printed = print_addr_and_symbol(addr, log_lvl, printed); + /* + * break out of recursive entries (such as + * end_of_stack_stop_unwind_function): + */ + if (ebp == *(unsigned long *)ebp) + break; ebp = *(unsigned long *)ebp; } #else -- cgit v1.2.3 From a03a3e287b119c7bcbcff1d68f81864ce33b1ad2 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Fri, 23 Jun 2006 02:04:20 -0700 Subject: [PATCH] Don't trigger full rebuild via CONFIG_X86_MCE Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/cpu/common.c | 1 + arch/i386/power/cpu.c | 1 + include/asm-i386/mce.h | 5 +++++ include/asm-i386/processor.h | 6 ------ 4 files changed, 7 insertions(+), 6 deletions(-) create mode 100644 include/asm-i386/mce.h diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c index f2a2b0ac9a1..44f2c5f2dda 100644 --- a/arch/i386/kernel/cpu/common.c +++ b/arch/i386/kernel/cpu/common.c @@ -12,6 +12,7 @@ #include #include #include +#include #ifdef CONFIG_X86_LOCAL_APIC #include #include diff --git a/arch/i386/power/cpu.c b/arch/i386/power/cpu.c index 63d25ca6306..e6517915fe3 100644 --- a/arch/i386/power/cpu.c +++ b/arch/i386/power/cpu.c @@ -11,6 +11,7 @@ #include #include #include +#include static struct saved_context saved_context; diff --git a/include/asm-i386/mce.h b/include/asm-i386/mce.h new file mode 100644 index 00000000000..7cc1a973bf0 --- /dev/null +++ b/include/asm-i386/mce.h @@ -0,0 +1,5 @@ +#ifdef CONFIG_X86_MCE +extern void mcheck_init(struct cpuinfo_x86 *c); +#else +#define mcheck_init(c) do {} while(0) +#endif diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h index 5116465272e..0c83cf12eec 100644 --- a/include/asm-i386/processor.h +++ b/include/asm-i386/processor.h @@ -728,10 +728,4 @@ extern unsigned long boot_option_idle_override; extern void enable_sep_cpu(void); extern int sysenter_setup(void); -#ifdef CONFIG_X86_MCE -extern void mcheck_init(struct cpuinfo_x86 *c); -#else -#define mcheck_init(c) do {} while(0) -#endif - #endif /* __ASM_I386_PROCESSOR_H */ -- cgit v1.2.3 From afa024c3dbccf026e45121f4b9de54cda48edbea Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Jun 2006 02:04:21 -0700 Subject: [PATCH] x86: call eisa_set_level_irq() in pbibios_lookup_irq() Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/pci/irq.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c index 06dab00aaad..49b9fea518c 100644 --- a/arch/i386/pci/irq.c +++ b/arch/i386/pci/irq.c @@ -880,6 +880,7 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign) ((!(pci_probe & PCI_USE_PIRQ_MASK)) || ((1 << irq) & mask)) ) { DBG(" -> got IRQ %d\n", irq); msg = "Found"; + eisa_set_level_irq(irq); } else if (newirq && r->set && (dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) { DBG(" -> assigning IRQ %d", newirq); if (r->set(pirq_router_dev, dev, pirq, newirq)) { -- cgit v1.2.3 From 1b61b910e99059abdd54c93aa70e84e076e33d16 Mon Sep 17 00:00:00 2001 From: Zhang Yanmin Date: Fri, 23 Jun 2006 02:04:22 -0700 Subject: [PATCH] x86: kernel irq balance doesn't work On i386, kernel irq balance doesn't work. 1) In function do_irq_balance, after kernel finds the min_loaded cpu but before calling set_pending_irq to really pin the selected_irq to the target cpu, kernel does a cpus_and with irq_affinity[selected_irq]. Later on, when the irq is acked, kernel would calls move_native_irq=>desc->handler->set_affinity to change the irq affinity. However, every function pointed by hw_interrupt_type->set_affinity(unsigned int irq, cpumask_t cpumask) always changes irq_affinity[irq] to cpumask. Next time when recalling do_irq_balance, it has to do cpu_ands again with irq_affinity[selected_irq], but irq_affinity[selected_irq] already becomes one cpu selected by the first irq balance. 2) Function balance_irq in file arch/i386/kernel/io_apic.c has the same issue. [akpm@osdl.org: cleanups] Signed-off-by: Zhang Yanmin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/io_apic.c | 31 ++++++++++++++++++++----------- include/linux/irq.h | 8 ++++++++ kernel/irq/proc.c | 3 +++ 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index d70f2ade5cd..a62df3e764c 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c @@ -267,7 +267,7 @@ static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t cpumask) # include /* kmalloc() */ # include /* time_after() */ -# ifdef CONFIG_BALANCED_IRQ_DEBUG +#ifdef CONFIG_BALANCED_IRQ_DEBUG # define TDprintk(x...) do { printk("<%ld:%s:%d>: ", jiffies, __FILE__, __LINE__); printk(x); } while (0) # define Dprintk(x...) do { TDprintk(x); } while (0) # else @@ -275,10 +275,15 @@ static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t cpumask) # define Dprintk(x...) # endif - #define IRQBALANCE_CHECK_ARCH -999 -static int irqbalance_disabled = IRQBALANCE_CHECK_ARCH; -static int physical_balance = 0; +#define MAX_BALANCED_IRQ_INTERVAL (5*HZ) +#define MIN_BALANCED_IRQ_INTERVAL (HZ/2) +#define BALANCED_IRQ_MORE_DELTA (HZ/10) +#define BALANCED_IRQ_LESS_DELTA (HZ) + +static int irqbalance_disabled __read_mostly = IRQBALANCE_CHECK_ARCH; +static int physical_balance __read_mostly; +static long balanced_irq_interval __read_mostly = MAX_BALANCED_IRQ_INTERVAL; static struct irq_cpu_info { unsigned long * last_irq; @@ -297,12 +302,14 @@ static struct irq_cpu_info { #define CPU_TO_PACKAGEINDEX(i) (first_cpu(cpu_sibling_map[i])) -#define MAX_BALANCED_IRQ_INTERVAL (5*HZ) -#define MIN_BALANCED_IRQ_INTERVAL (HZ/2) -#define BALANCED_IRQ_MORE_DELTA (HZ/10) -#define BALANCED_IRQ_LESS_DELTA (HZ) +static cpumask_t balance_irq_affinity[NR_IRQS] = { + [0 ... NR_IRQS-1] = CPU_MASK_ALL +}; -static long balanced_irq_interval = MAX_BALANCED_IRQ_INTERVAL; +void set_balance_irq_affinity(unsigned int irq, cpumask_t mask) +{ + balance_irq_affinity[irq] = mask; +} static unsigned long move(int curr_cpu, cpumask_t allowed_mask, unsigned long now, int direction) @@ -340,7 +347,7 @@ static inline void balance_irq(int cpu, int irq) if (irqbalance_disabled) return; - cpus_and(allowed_mask, cpu_online_map, irq_affinity[irq]); + cpus_and(allowed_mask, cpu_online_map, balance_irq_affinity[irq]); new_cpu = move(cpu, allowed_mask, now, 1); if (cpu != new_cpu) { set_pending_irq(irq, cpumask_of_cpu(new_cpu)); @@ -529,7 +536,9 @@ tryanotherirq: } } - cpus_and(allowed_mask, cpu_online_map, irq_affinity[selected_irq]); + cpus_and(allowed_mask, + cpu_online_map, + balance_irq_affinity[selected_irq]); target_cpu_mask = cpumask_of_cpu(min_loaded); cpus_and(tmp, target_cpu_mask, allowed_mask); diff --git a/include/linux/irq.h b/include/linux/irq.h index 42c9cd56286..e8a07e75e4f 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -164,6 +164,14 @@ static inline void set_irq_info(int irq, cpumask_t mask) #endif // CONFIG_SMP +#ifdef CONFIG_IRQBALANCE +extern void set_balance_irq_affinity(unsigned int irq, cpumask_t mask); +#else +static inline void set_balance_irq_affinity(unsigned int irq, cpumask_t mask) +{ +} +#endif + extern int no_irq_affinity; extern int noirqdebug_setup(char *str); diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c index d03b5eef8ce..afacd6f585f 100644 --- a/kernel/irq/proc.c +++ b/kernel/irq/proc.c @@ -24,6 +24,8 @@ static struct proc_dir_entry *smp_affinity_entry[NR_IRQS]; #ifdef CONFIG_GENERIC_PENDING_IRQ void proc_set_irq_affinity(unsigned int irq, cpumask_t mask_val) { + set_balance_irq_affinity(irq, mask_val); + /* * Save these away for later use. Re-progam when the * interrupt is pending @@ -33,6 +35,7 @@ void proc_set_irq_affinity(unsigned int irq, cpumask_t mask_val) #else void proc_set_irq_affinity(unsigned int irq, cpumask_t mask_val) { + set_balance_irq_affinity(irq, mask_val); irq_affinity[irq] = mask_val; irq_desc[irq].handler->set_affinity(irq, mask_val); } -- cgit v1.2.3 From 21528454f6dd18231ae20102f98aa8f51b6ec1b9 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert <76306.1226@compuserve.com> Date: Fri, 23 Jun 2006 02:04:23 -0700 Subject: [PATCH] i386: let usermode execute the "enter" instruction The i386 page fault handler does not allow enough slack when checking for userspace access below the current stack pointer. This prevents use of the enter instruction by user code. Fix this by allowing enough slack for "enter $65535,$31" to execute. Problem reported by Tomasz Malesinski Tested using this program, based on the original from Tomasz: .file "ovflow.S" .version "01.01" gcc2_compiled.: .section .rodata .LC0: .string "asdf\n" .text .align 4 .globl main .type main,@function main: nest_level=0 .rept 30 enter $0,$nest_level nest_level=nest_level+1 .endr enter $65535,$30 enter $65535,$31 addl $-12,%esp pushl $.LC0 call printf addl $16,%esp .L2: .rept 32 leave .endr ret .Lfe1: .size main,.Lfe1-main .ident "GCC: (GNU) 2.95.4 20011002 (Debian prerelease)" Signed-off-by: Chuck Ebbert <76306.1226@compuserve.com> Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/mm/fault.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c index 7f0fcf219a2..f38085ff3c3 100644 --- a/arch/i386/mm/fault.c +++ b/arch/i386/mm/fault.c @@ -380,12 +380,12 @@ fastcall void __kprobes do_page_fault(struct pt_regs *regs, goto bad_area; if (error_code & 4) { /* - * accessing the stack below %esp is always a bug. - * The "+ 32" is there due to some instructions (like - * pusha) doing post-decrement on the stack and that - * doesn't show up until later.. + * Accessing the stack below %esp is always a bug. + * The large cushion allows instructions like enter + * and pusha to work. ("enter $65535,$31" pushes + * 32 pointers and then decrements %esp by 65535.) */ - if (address + 32 < regs->esp) + if (address + 65536 + 32 * sizeof(unsigned long) < regs->esp) goto bad_area; } if (expand_stack(vma, address)) -- cgit v1.2.3 From acae9d32436122959667470b84da517d7b1b9c2d Mon Sep 17 00:00:00 2001 From: Andreas Mohr Date: Fri, 23 Jun 2006 02:04:25 -0700 Subject: [PATCH] x86: make using_apic_timer __read_mostly Signed-off-by: Andreas Mohr Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/apic.c | 2 +- arch/x86_64/kernel/apic.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c index 261796ff83c..5ab59c12335 100644 --- a/arch/i386/kernel/apic.c +++ b/arch/i386/kernel/apic.c @@ -113,7 +113,7 @@ void __init apic_intr_init(void) } /* Using APIC to generate smp_local_timer_interrupt? */ -int using_apic_timer = 0; +int using_apic_timer __read_mostly = 0; static int enabled_via_apicbase; diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c index 100a30c4004..29ef99001e0 100644 --- a/arch/x86_64/kernel/apic.c +++ b/arch/x86_64/kernel/apic.c @@ -51,7 +51,7 @@ int disable_apic_timer __initdata; static cpumask_t timer_interrupt_broadcast_ipi_mask; /* Using APIC to generate smp_local_timer_interrupt? */ -int using_apic_timer = 0; +int using_apic_timer __read_mostly = 0; static void apic_pm_activate(void); -- cgit v1.2.3 From cefc01130ba2bb0a81abda14b3f00fcc2e70dd43 Mon Sep 17 00:00:00 2001 From: Andreas Mohr Date: Fri, 23 Jun 2006 02:04:26 -0700 Subject: [PATCH] x86: cyrix code CONFIG_PCI fix / add __initdata PCI code was outside of CONFIG_PCI, add __initdata at cyrix_55x0 (since accessed within __init function only). Signed-off-by: Andreas Mohr Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/cpu/cyrix.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/i386/kernel/cpu/cyrix.c b/arch/i386/kernel/cpu/cyrix.c index 00f2e058797..fc32c8028e2 100644 --- a/arch/i386/kernel/cpu/cyrix.c +++ b/arch/i386/kernel/cpu/cyrix.c @@ -184,7 +184,7 @@ static void __init geode_configure(void) #ifdef CONFIG_PCI -static struct pci_device_id cyrix_55x0[] = { +static struct pci_device_id __initdata cyrix_55x0[] = { { PCI_DEVICE(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5510) }, { PCI_DEVICE(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5520) }, { }, @@ -272,14 +272,15 @@ static void __init init_cyrix(struct cpuinfo_x86 *c) printk(KERN_INFO "Working around Cyrix MediaGX virtual DMA bugs.\n"); isa_dma_bridge_buggy = 2; -#endif - c->x86_cache_size=16; /* Yep 16K integrated cache thats it */ - + + /* * The 5510/5520 companion chips have a funky PIT. */ if (pci_dev_present(cyrix_55x0)) pit_latch_buggy = 1; +#endif + c->x86_cache_size=16; /* Yep 16K integrated cache thats it */ /* GXm supports extended cpuid levels 'ala' AMD */ if (c->cpuid_level == 2) { -- cgit v1.2.3 From 7b0c2d92180dbd9c7cd0c4b9bd38b06bb0f12843 Mon Sep 17 00:00:00 2001 From: Andreas Mohr Date: Fri, 23 Jun 2006 02:04:26 -0700 Subject: [PATCH] x86: make i387 mxcsr_feature_mask __read_mostly Signed-off-by: Andreas Mohr Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/i387.c | 2 +- arch/x86_64/kernel/i387.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/i386/kernel/i387.c b/arch/i386/kernel/i387.c index d75524758da..c4351972d9a 100644 --- a/arch/i386/kernel/i387.c +++ b/arch/i386/kernel/i387.c @@ -25,7 +25,7 @@ #define HAVE_HWFP 1 #endif -static unsigned long mxcsr_feature_mask = 0xffffffff; +static unsigned long mxcsr_feature_mask __read_mostly = 0xffffffff; void mxcsr_feature_mask_init(void) { diff --git a/arch/x86_64/kernel/i387.c b/arch/x86_64/kernel/i387.c index a5d7e16b928..44ddb1ec808 100644 --- a/arch/x86_64/kernel/i387.c +++ b/arch/x86_64/kernel/i387.c @@ -24,7 +24,7 @@ #include #include -unsigned int mxcsr_feature_mask = 0xffffffff; +unsigned int mxcsr_feature_mask __read_mostly = 0xffffffff; void mxcsr_feature_mask_init(void) { -- cgit v1.2.3 From 9f22271898707aed2f84cc75ab3bd109173cdbbf Mon Sep 17 00:00:00 2001 From: Andreas Mohr Date: Fri, 23 Jun 2006 02:04:27 -0700 Subject: [PATCH] make ACPI errata __read_mostly Signed-off-by: Andreas Mohr Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/acpi/processor_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 713b763884a..ab00afec26f 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -110,7 +110,7 @@ static struct file_operations acpi_processor_info_fops = { }; struct acpi_processor *processors[NR_CPUS]; -struct acpi_processor_errata errata; +struct acpi_processor_errata errata __read_mostly; /* -------------------------------------------------------------------------- Errata Handling -- cgit v1.2.3 From a0de1f0a5038a957d50893db7a0d47e385fb2915 Mon Sep 17 00:00:00 2001 From: Andreas Mohr Date: Fri, 23 Jun 2006 02:04:28 -0700 Subject: [PATCH] x86: constify arch/i386/pci/irq.c constify structs and add one __initdata. Signed-off-by: Andreas Mohr Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/pci/irq.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c index 49b9fea518c..8ce69508f3c 100644 --- a/arch/i386/pci/irq.c +++ b/arch/i386/pci/irq.c @@ -198,14 +198,14 @@ static void write_config_nybble(struct pci_dev *router, unsigned offset, unsigne */ static int pirq_ali_get(struct pci_dev *router, struct pci_dev *dev, int pirq) { - static unsigned char irqmap[16] = { 0, 9, 3, 10, 4, 5, 7, 6, 1, 11, 0, 12, 0, 14, 0, 15 }; + static const unsigned char irqmap[16] = { 0, 9, 3, 10, 4, 5, 7, 6, 1, 11, 0, 12, 0, 14, 0, 15 }; return irqmap[read_config_nybble(router, 0x48, pirq-1)]; } static int pirq_ali_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) { - static unsigned char irqmap[16] = { 0, 8, 0, 2, 4, 5, 7, 6, 0, 1, 3, 9, 11, 0, 13, 15 }; + static const unsigned char irqmap[16] = { 0, 8, 0, 2, 4, 5, 7, 6, 0, 1, 3, 9, 11, 0, 13, 15 }; unsigned int val = irqmap[irq]; if (val) { @@ -256,13 +256,13 @@ static int pirq_via_set(struct pci_dev *router, struct pci_dev *dev, int pirq, i */ static int pirq_via586_get(struct pci_dev *router, struct pci_dev *dev, int pirq) { - static unsigned int pirqmap[4] = { 3, 2, 5, 1 }; + static const unsigned int pirqmap[4] = { 3, 2, 5, 1 }; return read_config_nybble(router, 0x55, pirqmap[pirq-1]); } static int pirq_via586_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) { - static unsigned int pirqmap[4] = { 3, 2, 5, 1 }; + static const unsigned int pirqmap[4] = { 3, 2, 5, 1 }; write_config_nybble(router, 0x55, pirqmap[pirq-1], irq); return 1; } @@ -274,13 +274,13 @@ static int pirq_via586_set(struct pci_dev *router, struct pci_dev *dev, int pirq */ static int pirq_ite_get(struct pci_dev *router, struct pci_dev *dev, int pirq) { - static unsigned char pirqmap[4] = { 1, 0, 2, 3 }; + static const unsigned char pirqmap[4] = { 1, 0, 2, 3 }; return read_config_nybble(router,0x43, pirqmap[pirq-1]); } static int pirq_ite_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) { - static unsigned char pirqmap[4] = { 1, 0, 2, 3 }; + static const unsigned char pirqmap[4] = { 1, 0, 2, 3 }; write_config_nybble(router, 0x43, pirqmap[pirq-1], irq); return 1; } @@ -505,7 +505,7 @@ static int pirq_bios_set(struct pci_dev *router, struct pci_dev *dev, int pirq, static __init int intel_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) { - static struct pci_device_id pirq_440gx[] = { + static struct pci_device_id __initdata pirq_440gx[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_0) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_2) }, { }, -- cgit v1.2.3 From 110cb1d2e343443c4a4b5f7e081928aa4da90f93 Mon Sep 17 00:00:00 2001 From: Andreas Mohr Date: Fri, 23 Jun 2006 02:04:28 -0700 Subject: [PATCH] x86: use proper defines for i8259A I/O Use proper defines instead of open-coded values. Signed-off-by: Andreas Mohr Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/i8259.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c index 323ef8ab324..b7636b96e10 100644 --- a/arch/i386/kernel/i8259.c +++ b/arch/i386/kernel/i8259.c @@ -271,8 +271,8 @@ static int i8259A_shutdown(struct sys_device *dev) * the kernel initialization code can get it * out of. */ - outb(0xff, 0x21); /* mask all of 8259A-1 */ - outb(0xff, 0xA1); /* mask all of 8259A-1 */ + outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */ + outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-1 */ return 0; } -- cgit v1.2.3 From 19964fecf25c17f865dec07ae242b1a40ea93f16 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert <76306.1226@compuserve.com> Date: Fri, 23 Jun 2006 02:04:29 -0700 Subject: [PATCH] i386: fix get_segment_eip() with vm86 segments We need to check for vm86 mode first before looking at selector privilege bits. Segment limit is always base + 64k and only the low 16 bits of EIP are significant in vm86 mode. Signed-off-by: Chuck Ebbert <76306.1226@compuserve.com> Cc: Andi Kleen Cc: Zachary Amsden Cc: Rohit Seth Acked-by: Ananth N Mavinakayanahalli Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/mm/fault.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c index f38085ff3c3..bd6fe96cc16 100644 --- a/arch/i386/mm/fault.c +++ b/arch/i386/mm/fault.c @@ -77,12 +77,15 @@ static inline unsigned long get_segment_eip(struct pt_regs *regs, unsigned seg = regs->xcs & 0xffff; u32 seg_ar, seg_limit, base, *desc; + /* Unlikely, but must come before segment checks. */ + if (unlikely(regs->eflags & VM_MASK)) { + base = seg << 4; + *eip_limit = base + 0xffff; + return base + (eip & 0xffff); + } + /* The standard kernel/user address space limit. */ *eip_limit = (seg & 3) ? USER_DS.seg : KERNEL_DS.seg; - - /* Unlikely, but must come before segment checks. */ - if (unlikely((regs->eflags & VM_MASK) != 0)) - return eip + (seg << 4); /* By far the most common cases. */ if (likely(seg == __USER_CS || seg == __KERNEL_CS)) -- cgit v1.2.3 From 6444541671bd821b950dbaafee70d65188198aa6 Mon Sep 17 00:00:00 2001 From: Zachary Amsden Date: Fri, 23 Jun 2006 02:04:30 -0700 Subject: [PATCH] i386: don't try kprobes for v8086 mode Never allow int3 traps from V8086 mode to enter the kprobes handler. Signed-off-by: Zachary Amsden Cc: Prasanna S Panchamukhi Cc: Ananth N Mavinakayanahalli Cc: Anil S Keshavamurthy Cc: Chuck Ebbert <76306.1226@compuserve.com> Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/kprobes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c index 38806f42784..395a9a6dff8 100644 --- a/arch/i386/kernel/kprobes.c +++ b/arch/i386/kernel/kprobes.c @@ -607,7 +607,7 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, struct die_args *args = (struct die_args *)data; int ret = NOTIFY_DONE; - if (args->regs && user_mode(args->regs)) + if (args->regs && user_mode_vm(args->regs)) return ret; switch (val) { -- cgit v1.2.3 From 722f4f5b2600b8930b63a096e48b878cd6e0e15a Mon Sep 17 00:00:00 2001 From: Roman Zippel Date: Fri, 23 Jun 2006 02:04:31 -0700 Subject: [PATCH] x86: fix __range_ok constraint An immediate operand can't be the destination of the cmpl instruction, so exclude it. Signed-off-by: Roman Zippel Cc: Mattia Dongili Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-i386/uaccess.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/asm-i386/uaccess.h b/include/asm-i386/uaccess.h index 82af28a943a..8462f8e0e65 100644 --- a/include/asm-i386/uaccess.h +++ b/include/asm-i386/uaccess.h @@ -58,7 +58,7 @@ extern struct movsl_mask { __chk_user_ptr(addr); \ asm("addl %3,%1 ; sbbl %0,%0; cmpl %1,%4; sbbl $0,%0" \ :"=&r" (flag), "=r" (sum) \ - :"1" (addr),"g" ((int)(size)),"g" (current_thread_info()->addr_limit.seg)); \ + :"1" (addr),"g" ((int)(size)),"rm" (current_thread_info()->addr_limit.seg)); \ flag; }) /** -- cgit v1.2.3 From 7e04a1183eac3e6b3570a154c8677fd9184b51e7 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert <76306.1226@compuserve.com> Date: Fri, 23 Jun 2006 02:04:31 -0700 Subject: [PATCH] i386: extra checks in show_registers() Sometimes thread_info and task_struct get out-of-sync with each other. Printing task.thread_info in show_registers() can help spot this. And when task_struct is corrupt then task.comm can contain garbage, so only print as many characters as it can hold. Signed-off-by: Chuck Ebbert <76306.1226@compuserve.com> Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/traps.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index df9d210626a..dcc14477af1 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -274,8 +274,9 @@ void show_registers(struct pt_regs *regs) regs->esi, regs->edi, regs->ebp, esp); printk(KERN_EMERG "ds: %04x es: %04x ss: %04x\n", regs->xds & 0xffff, regs->xes & 0xffff, ss); - printk(KERN_EMERG "Process %s (pid: %d, threadinfo=%p task=%p)", - current->comm, current->pid, current_thread_info(), current); + printk(KERN_EMERG "Process %.*s (pid: %d, ti=%p task=%p task.ti=%p)", + TASK_COMM_LEN, current->comm, current->pid, + current_thread_info(), current, current->thread_info); /* * When in-kernel, we also print out the stack and code at the * time of the fault.. -- cgit v1.2.3 From 224f611c1639cb6c134a934dae7f7b9f0ac3b540 Mon Sep 17 00:00:00 2001 From: Michal Ludvig Date: Fri, 23 Jun 2006 02:04:32 -0700 Subject: [PATCH] x86: VIA C7 CPU flags New CPU flags for next generation of crypto engine as found in VIA C7 processors. Signed-off-by: Michal Ludvig Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/cpu/proc.c | 2 +- include/asm-i386/cpufeature.h | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c index f94cdb7aca5..a19fcb262db 100644 --- a/arch/i386/kernel/cpu/proc.c +++ b/arch/i386/kernel/cpu/proc.c @@ -52,7 +52,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) /* VIA/Cyrix/Centaur-defined */ NULL, NULL, "rng", "rng_en", NULL, NULL, "ace", "ace_en", - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "ace2", "ace2_en", "phe", "phe_en", "pmm", "pmm_en", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, diff --git a/include/asm-i386/cpufeature.h b/include/asm-i386/cpufeature.h index b44bfc6239c..3ecedbafa8c 100644 --- a/include/asm-i386/cpufeature.h +++ b/include/asm-i386/cpufeature.h @@ -88,6 +88,12 @@ #define X86_FEATURE_XSTORE_EN (5*32+ 3) /* on-CPU RNG enabled */ #define X86_FEATURE_XCRYPT (5*32+ 6) /* on-CPU crypto (xcrypt insn) */ #define X86_FEATURE_XCRYPT_EN (5*32+ 7) /* on-CPU crypto enabled */ +#define X86_FEATURE_ACE2 (5*32+ 8) /* Advanced Cryptography Engine v2 */ +#define X86_FEATURE_ACE2_EN (5*32+ 9) /* ACE v2 enabled */ +#define X86_FEATURE_PHE (5*32+ 10) /* PadLock Hash Engine */ +#define X86_FEATURE_PHE_EN (5*32+ 11) /* PHE enabled */ +#define X86_FEATURE_PMM (5*32+ 12) /* PadLock Montgomery Multiplier */ +#define X86_FEATURE_PMM_EN (5*32+ 13) /* PMM enabled */ /* More extended AMD flags: CPUID level 0x80000001, ecx, word 6 */ #define X86_FEATURE_LAHF_LM (6*32+ 0) /* LAHF/SAHF in long mode */ @@ -121,6 +127,12 @@ #define cpu_has_xstore_enabled boot_cpu_has(X86_FEATURE_XSTORE_EN) #define cpu_has_xcrypt boot_cpu_has(X86_FEATURE_XCRYPT) #define cpu_has_xcrypt_enabled boot_cpu_has(X86_FEATURE_XCRYPT_EN) +#define cpu_has_ace2 boot_cpu_has(X86_FEATURE_ACE2) +#define cpu_has_ace2_enabled boot_cpu_has(X86_FEATURE_ACE2_EN) +#define cpu_has_phe boot_cpu_has(X86_FEATURE_PHE) +#define cpu_has_phe_enabled boot_cpu_has(X86_FEATURE_PHE_EN) +#define cpu_has_pmm boot_cpu_has(X86_FEATURE_PMM) +#define cpu_has_pmm_enabled boot_cpu_has(X86_FEATURE_PMM_EN) #endif /* __ASM_I386_CPUFEATURE_H */ -- cgit v1.2.3 From 30343d6c3d4e3fe961369e7be19935683e808c88 Mon Sep 17 00:00:00 2001 From: Kirill Smelkov Date: Fri, 23 Jun 2006 02:04:33 -0700 Subject: [PATCH] x86: compile fix for asm-i386/alternatives.h compile fix: needs for 'u8' -- just look at struct alt_instr. My module includes as the first header, and as of 2.6.17 this leads to compilation errors. Signed-off-by: Kirill Smelkov Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-i386/alternative.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/asm-i386/alternative.h b/include/asm-i386/alternative.h index e201decea0c..d79e9ee10fd 100644 --- a/include/asm-i386/alternative.h +++ b/include/asm-i386/alternative.h @@ -3,6 +3,8 @@ #ifdef __KERNEL__ +#include + struct alt_instr { u8 *instr; /* original instruction */ u8 *replacement; -- cgit v1.2.3 From 82dcaafc92fdfbe2c1d6c50b9f5e17d533caf950 Mon Sep 17 00:00:00 2001 From: Mathieu Chouquet-Stringer Date: Fri, 23 Jun 2006 02:04:40 -0700 Subject: [PATCH] Remove duplicate symbol exports on Alpha WARNING: vmlinux: 'enable_irq' exported twice. Previous export was in vmlinux WARNING: vmlinux: 'disable_irq' exported twice. Previous export was in vmlinux WARNING: vmlinux: 'disable_irq_nosync' exported twice. Previous export was in vmlinux WARNING: vmlinux: 'probe_irq_mask' exported twice. Previous export was in vmlinux WARNING: vmlinux: 'sys_open' exported twice. Previous export was in vmlinux WARNING: vmlinux: 'sys_read' exported twice. Previous export was in vmlinux WARNING: vmlinux: 'strstr' exported twice. Previous export was in vmlinux WARNING: vmlinux: 'memscan' exported twice. Previous export was in vmlinux WARNING: vmlinux: 'memcmp' exported twice. Previous export was in vmlinux WARNING: vmlinux: 'strnlen' exported twice. Previous export was in vmlinux WARNING: vmlinux: 'strncmp' exported twice. Previous export was in vmlinux WARNING: vmlinux: 'strcmp' exported twice. Previous export was in vmlinux Signed-off-by: Mathieu Chouquet-Stringer Cc: Richard Henderson Cc: Ivan Kokshaysky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/alpha/kernel/alpha_ksyms.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c index 2b245ad731e..d3848c5b0d2 100644 --- a/arch/alpha/kernel/alpha_ksyms.c +++ b/arch/alpha/kernel/alpha_ksyms.c @@ -53,10 +53,6 @@ extern void __divqu (void); extern void __remqu (void); EXPORT_SYMBOL(alpha_mv); -EXPORT_SYMBOL(enable_irq); -EXPORT_SYMBOL(disable_irq); -EXPORT_SYMBOL(disable_irq_nosync); -EXPORT_SYMBOL(probe_irq_mask); EXPORT_SYMBOL(screen_info); EXPORT_SYMBOL(perf_irq); EXPORT_SYMBOL(callback_getenv); @@ -68,19 +64,13 @@ EXPORT_SYMBOL(alpha_using_srm); /* platform dependent support */ EXPORT_SYMBOL(strcat); -EXPORT_SYMBOL(strcmp); EXPORT_SYMBOL(strcpy); EXPORT_SYMBOL(strlen); -EXPORT_SYMBOL(strncmp); EXPORT_SYMBOL(strncpy); -EXPORT_SYMBOL(strnlen); EXPORT_SYMBOL(strncat); -EXPORT_SYMBOL(strstr); EXPORT_SYMBOL(strchr); EXPORT_SYMBOL(strrchr); -EXPORT_SYMBOL(memcmp); EXPORT_SYMBOL(memmove); -EXPORT_SYMBOL(memscan); EXPORT_SYMBOL(__memcpy); EXPORT_SYMBOL(__memset); EXPORT_SYMBOL(__memsetw); @@ -122,11 +112,9 @@ EXPORT_SYMBOL(alpha_write_fp_reg_s); /* In-kernel system calls. */ EXPORT_SYMBOL(kernel_thread); -EXPORT_SYMBOL(sys_open); EXPORT_SYMBOL(sys_dup); EXPORT_SYMBOL(sys_exit); EXPORT_SYMBOL(sys_write); -EXPORT_SYMBOL(sys_read); EXPORT_SYMBOL(sys_lseek); EXPORT_SYMBOL(execve); EXPORT_SYMBOL(sys_setsid); -- cgit v1.2.3 From ce4ab0012b32c1a4a1d6e934aeb73bf3151c48d9 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Fri, 23 Jun 2006 02:04:44 -0700 Subject: [PATCH] swsusp: add architecture special saveable pages support 1. Add architecture specific pages save/restore support. Next two patches will use this to save/restore 'ACPI NVS' pages. 2. Allow reserved pages 'nosave'. This could avoid save/restore BIOS reserved pages. Signed-off-by: Shaohua Li Cc: Pavel Machek Cc: "Rafael J. Wysocki" Cc: Nigel Cunningham Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/suspend.h | 1 + kernel/power/power.h | 4 ++ kernel/power/snapshot.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++- kernel/power/swsusp.c | 18 ++------ 4 files changed, 118 insertions(+), 15 deletions(-) diff --git a/include/linux/suspend.h b/include/linux/suspend.h index 96e31aa64cc..e82cb10fb3e 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h @@ -71,6 +71,7 @@ struct saved_context; void __save_processor_state(struct saved_context *ctxt); void __restore_processor_state(struct saved_context *ctxt); unsigned long get_safe_page(gfp_t gfp_mask); +int swsusp_add_arch_pages(unsigned long start, unsigned long end); /* * XXX: We try to keep some more pages free so that I/O operations succeed diff --git a/kernel/power/power.h b/kernel/power/power.h index f06f12f2176..c81f0ed3eeb 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h @@ -105,6 +105,10 @@ extern struct bitmap_page *alloc_bitmap(unsigned int nr_bits); extern unsigned long alloc_swap_page(int swap, struct bitmap_page *bitmap); extern void free_all_swap_pages(int swap, struct bitmap_page *bitmap); +extern unsigned int count_special_pages(void); +extern int save_special_mem(void); +extern int restore_special_mem(void); + extern int swsusp_check(void); extern int swsusp_shrink_memory(void); extern void swsusp_free(void); diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index 3eeedbb13b7..7f511d89c66 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c @@ -39,6 +39,88 @@ static unsigned int nr_copy_pages; static unsigned int nr_meta_pages; static unsigned long *buffer; +struct arch_saveable_page { + unsigned long start; + unsigned long end; + char *data; + struct arch_saveable_page *next; +}; +static struct arch_saveable_page *arch_pages; + +int swsusp_add_arch_pages(unsigned long start, unsigned long end) +{ + struct arch_saveable_page *tmp; + + while (start < end) { + tmp = kzalloc(sizeof(struct arch_saveable_page), GFP_KERNEL); + if (!tmp) + return -ENOMEM; + tmp->start = start; + tmp->end = ((start >> PAGE_SHIFT) + 1) << PAGE_SHIFT; + if (tmp->end > end) + tmp->end = end; + tmp->next = arch_pages; + start = tmp->end; + arch_pages = tmp; + } + return 0; +} + +static unsigned int count_arch_pages(void) +{ + unsigned int count = 0; + struct arch_saveable_page *tmp = arch_pages; + while (tmp) { + count++; + tmp = tmp->next; + } + return count; +} + +static int save_arch_mem(void) +{ + char *kaddr; + struct arch_saveable_page *tmp = arch_pages; + int offset; + + pr_debug("swsusp: Saving arch specific memory"); + while (tmp) { + tmp->data = (char *)__get_free_page(GFP_ATOMIC); + if (!tmp->data) + return -ENOMEM; + offset = tmp->start - (tmp->start & PAGE_MASK); + /* arch pages might haven't a 'struct page' */ + kaddr = kmap_atomic_pfn(tmp->start >> PAGE_SHIFT, KM_USER0); + memcpy(tmp->data + offset, kaddr + offset, + tmp->end - tmp->start); + kunmap_atomic(kaddr, KM_USER0); + + tmp = tmp->next; + } + return 0; +} + +static int restore_arch_mem(void) +{ + char *kaddr; + struct arch_saveable_page *tmp = arch_pages; + int offset; + + while (tmp) { + if (!tmp->data) + continue; + offset = tmp->start - (tmp->start & PAGE_MASK); + kaddr = kmap_atomic_pfn(tmp->start >> PAGE_SHIFT, KM_USER0); + memcpy(kaddr + offset, tmp->data + offset, + tmp->end - tmp->start); + kunmap_atomic(kaddr, KM_USER0); + free_page((long)tmp->data); + tmp->data = NULL; + tmp = tmp->next; + } + return 0; +} + #ifdef CONFIG_HIGHMEM unsigned int count_highmem_pages(void) { @@ -150,8 +232,35 @@ int restore_highmem(void) } return 0; } +#else +static unsigned int count_highmem_pages(void) {return 0;} +static int save_highmem(void) {return 0;} +static int restore_highmem(void) {return 0;} #endif +unsigned int count_special_pages(void) +{ + return count_arch_pages() + count_highmem_pages(); +} + +int save_special_mem(void) +{ + int ret; + ret = save_arch_mem(); + if (!ret) + ret = save_highmem(); + return ret; +} + +int restore_special_mem(void) +{ + int ret; + ret = restore_arch_mem(); + if (!ret) + ret = restore_highmem(); + return ret; +} + static int pfn_is_nosave(unsigned long pfn) { unsigned long nosave_begin_pfn = __pa(&__nosave_begin) >> PAGE_SHIFT; @@ -177,7 +286,6 @@ static int saveable(struct zone *zone, unsigned long *zone_pfn) return 0; page = pfn_to_page(pfn); - BUG_ON(PageReserved(page) && PageNosave(page)); if (PageNosave(page)) return 0; if (PageReserved(page) && pfn_is_nosave(pfn)) diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c index f9238faf76e..78b6e71b081 100644 --- a/kernel/power/swsusp.c +++ b/kernel/power/swsusp.c @@ -62,16 +62,6 @@ unsigned long image_size = 500 * 1024 * 1024; int in_suspend __nosavedata = 0; -#ifdef CONFIG_HIGHMEM -unsigned int count_highmem_pages(void); -int save_highmem(void); -int restore_highmem(void); -#else -static int save_highmem(void) { return 0; } -static int restore_highmem(void) { return 0; } -static unsigned int count_highmem_pages(void) { return 0; } -#endif - /** * The following functions are used for tracing the allocated * swap pages, so that they can be freed in case of an error. @@ -192,7 +182,7 @@ int swsusp_shrink_memory(void) printk("Shrinking memory... "); do { - size = 2 * count_highmem_pages(); + size = 2 * count_special_pages(); size += size / 50 + count_data_pages(); size += (size + PBES_PER_PAGE - 1) / PBES_PER_PAGE + PAGES_FOR_IO; @@ -234,7 +224,7 @@ int swsusp_suspend(void) goto Enable_irqs; } - if ((error = save_highmem())) { + if ((error = save_special_mem())) { printk(KERN_ERR "swsusp: Not enough free pages for highmem\n"); goto Restore_highmem; } @@ -245,7 +235,7 @@ int swsusp_suspend(void) /* Restore control flow magically appears here */ restore_processor_state(); Restore_highmem: - restore_highmem(); + restore_special_mem(); device_power_up(); Enable_irqs: local_irq_enable(); @@ -271,7 +261,7 @@ int swsusp_resume(void) */ swsusp_free(); restore_processor_state(); - restore_highmem(); + restore_special_mem(); touch_softlockup_watchdog(); device_power_up(); local_irq_enable(); -- cgit v1.2.3 From b6370d96e09944c6e3ae8d5743ca8a8ab1f79f6c Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Fri, 23 Jun 2006 02:04:45 -0700 Subject: [PATCH] swsusp: i386 mark special saveable/unsaveable pages Pages (Reserved/ACPI NVS/ACPI Data) below max_low_pfn will be saved/restored by S4 currently. We should mark 'Reserved' pages not saveable. Pages (Reserved/ACPI NVS/ACPI Data) above max_low_pfn will not be saved/restored by S4 currently. We should save the 'ACPI NVS/ACPI Data' pages. Signed-off-by: Shaohua Li Cc: Pavel Machek Cc: "Rafael J. Wysocki" Cc: Nigel Cunningham Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/setup.c | 106 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index dd6b0e3386c..e6023970aa4 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c @@ -48,6 +48,7 @@ #include #include #include +#include #include + + Audit Interfaces +!Ekernel/audit.c +!Ikernel/auditsc.c +!Ikernel/auditfilter.c + + + + Accounting Framework +!Ikernel/acct.c + + Power Management !Ekernel/power/pm.c diff --git a/kernel/auditsc.c b/kernel/auditsc.c index b097ccb4eb7..9ebd96fda29 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -1558,6 +1558,7 @@ int __audit_ipc_obj(struct kern_ipc_perm *ipcp) * @uid: msgq user id * @gid: msgq group id * @mode: msgq mode (permissions) + * @ipcp: in-kernel IPC permissions * * Returns 0 for success or NULL context or < 0 on error. */ -- cgit v1.2.3 From f5befceb5cfecba49fdf61f8e0eb4d453200eac9 Mon Sep 17 00:00:00 2001 From: Brent Casavant Date: Fri, 23 Jun 2006 02:05:52 -0700 Subject: [PATCH] SGI IOC4: Detect IO card variant There are three different IO cards which an SGI IOC4 controller may find itself on. One of these variants does not bring out the IDE and serial signals, so we need to disable attaching the corresponding IOC4 subdrivers to such cards. Cleans up message clutter emitted during device probing. Signed-off-by: Brent Casavant Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/pci/sgiioc4.c | 6 +++++ drivers/serial/ioc4_serial.c | 9 +++++++ drivers/sn/ioc4.c | 64 ++++++++++++++++++++++++++++++++++++++++---- include/linux/ioc4.h | 5 ++++ 4 files changed, 79 insertions(+), 5 deletions(-) diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c index 27c9eb989a9..e125032bb40 100644 --- a/drivers/ide/pci/sgiioc4.c +++ b/drivers/ide/pci/sgiioc4.c @@ -723,6 +723,12 @@ static ide_pci_device_t sgiioc4_chipsets[] __devinitdata = { int ioc4_ide_attach_one(struct ioc4_driver_data *idd) { + /* PCI-RT does not bring out IDE connection. + * Do not attach to this particular IOC4. + */ + if (idd->idd_variant == IOC4_VARIANT_PCI_RT) + return 0; + return pci_init_sgiioc4(idd->idd_pdev, &sgiioc4_chipsets[idd->idd_pci_id->driver_data]); } diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c index c620209d7b9..717e47bbd78 100644 --- a/drivers/serial/ioc4_serial.c +++ b/drivers/serial/ioc4_serial.c @@ -2646,7 +2646,10 @@ static int ioc4_serial_remove_one(struct ioc4_driver_data *idd) struct ioc4_port *port; struct ioc4_soft *soft; + /* If serial driver did not attach, don't try to detach */ control = idd->idd_serial_data; + if (!control) + return 0; for (port_num = 0; port_num < IOC4_NUM_SERIAL_PORTS; port_num++) { for (port_type = UART_PORT_MIN; @@ -2778,6 +2781,12 @@ ioc4_serial_attach_one(struct ioc4_driver_data *idd) DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __FUNCTION__, idd->idd_pdev, idd->idd_pci_id)); + /* PCI-RT does not bring out serial connections. + * Do not attach to this particular IOC4. + */ + if (idd->idd_variant == IOC4_VARIANT_PCI_RT) + return 0; + /* request serial registers */ tmp_addr1 = idd->idd_bar0 + IOC4_SERIAL_OFFSET; diff --git a/drivers/sn/ioc4.c b/drivers/sn/ioc4.c index cdeff909403..8256a97eb50 100644 --- a/drivers/sn/ioc4.c +++ b/drivers/sn/ioc4.c @@ -160,9 +160,6 @@ ioc4_clock_calibrate(struct ioc4_driver_data *idd) writel(0, &idd->idd_misc_regs->int_out.raw); mmiowb(); - printk(KERN_INFO - "%s: Calibrating PCI bus speed " - "for pci_dev %s ... ", __FUNCTION__, pci_name(idd->idd_pdev)); /* Set up square wave */ int_out.raw = 0; int_out.fields.count = IOC4_CALIBRATE_COUNT; @@ -206,11 +203,16 @@ ioc4_clock_calibrate(struct ioc4_driver_data *idd) /* Bounds check the result. */ if (period > IOC4_CALIBRATE_LOW_LIMIT || period < IOC4_CALIBRATE_HIGH_LIMIT) { - printk("failed. Assuming PCI clock ticks are %d ns.\n", + printk(KERN_INFO + "IOC4 %s: Clock calibration failed. Assuming" + "PCI clock is %d ns.\n", + pci_name(idd->idd_pdev), IOC4_CALIBRATE_DEFAULT / IOC4_EXTINT_COUNT_DIVISOR); period = IOC4_CALIBRATE_DEFAULT; } else { - printk("succeeded. PCI clock ticks are %ld ns.\n", + printk(KERN_DEBUG + "IOC4 %s: PCI clock is %ld ns.\n", + pci_name(idd->idd_pdev), period / IOC4_EXTINT_COUNT_DIVISOR); } @@ -222,6 +224,51 @@ ioc4_clock_calibrate(struct ioc4_driver_data *idd) idd->count_period = period; } +/* There are three variants of IOC4 cards: IO9, IO10, and PCI-RT. + * Each brings out different combinations of IOC4 signals, thus. + * the IOC4 subdrivers need to know to which we're attached. + * + * We look for the presence of a SCSI (IO9) or SATA (IO10) controller + * on the same PCI bus at slot number 3 to differentiate IO9 from IO10. + * If neither is present, it's a PCI-RT. + */ +static unsigned int +ioc4_variant(struct ioc4_driver_data *idd) +{ + struct pci_dev *pdev = NULL; + int found = 0; + + /* IO9: Look for a QLogic ISP 12160 at the same bus and slot 3. */ + do { + pdev = pci_get_device(PCI_VENDOR_ID_QLOGIC, + PCI_DEVICE_ID_QLOGIC_ISP12160, pdev); + if (pdev && + idd->idd_pdev->bus->number == pdev->bus->number && + 3 == PCI_SLOT(pdev->devfn)) + found = 1; + pci_dev_put(pdev); + } while (pdev && !found); + if (NULL != pdev) + return IOC4_VARIANT_IO9; + + /* IO10: Look for a Vitesse VSC 7174 at the same bus and slot 3. */ + pdev = NULL; + do { + pdev = pci_get_device(PCI_VENDOR_ID_VITESSE, + PCI_DEVICE_ID_VITESSE_VSC7174, pdev); + if (pdev && + idd->idd_pdev->bus->number == pdev->bus->number && + 3 == PCI_SLOT(pdev->devfn)) + found = 1; + pci_dev_put(pdev); + } while (pdev && !found); + if (NULL != pdev) + return IOC4_VARIANT_IO10; + + /* PCI-RT: No SCSI/SATA controller will be present */ + return IOC4_VARIANT_PCI_RT; +} + /* Adds a new instance of an IOC4 card */ static int ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) @@ -286,6 +333,13 @@ ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) /* Failsafe portion of per-IOC4 initialization */ + /* Detect card variant */ + idd->idd_variant = ioc4_variant(idd); + printk(KERN_INFO "IOC4 %s: %s card detected.\n", pci_name(pdev), + idd->idd_variant == IOC4_VARIANT_IO9 ? "IO9" : + idd->idd_variant == IOC4_VARIANT_PCI_RT ? "PCI-RT" : + idd->idd_variant == IOC4_VARIANT_IO10 ? "IO10" : "unknown"); + /* Initialize IOC4 */ pci_read_config_dword(idd->idd_pdev, PCI_COMMAND, &pcmd); pci_write_config_dword(idd->idd_pdev, PCI_COMMAND, diff --git a/include/linux/ioc4.h b/include/linux/ioc4.h index 3dd18b785eb..de73a3289cc 100644 --- a/include/linux/ioc4.h +++ b/include/linux/ioc4.h @@ -147,6 +147,10 @@ struct ioc4_misc_regs { #define IOC4_GPCR_EDGE_6 0x40 #define IOC4_GPCR_EDGE_7 0x80 +#define IOC4_VARIANT_IO9 0x0900 +#define IOC4_VARIANT_PCI_RT 0x0901 +#define IOC4_VARIANT_IO10 0x1000 + /* One of these per IOC4 */ struct ioc4_driver_data { struct list_head idd_list; @@ -156,6 +160,7 @@ struct ioc4_driver_data { struct __iomem ioc4_misc_regs *idd_misc_regs; unsigned long count_period; void *idd_serial_data; + unsigned int idd_variant; }; /* One per submodule */ -- cgit v1.2.3 From cb259f07b1daacafac3b12ecd7f180faf7e506b0 Mon Sep 17 00:00:00 2001 From: bjdouma Date: Fri, 23 Jun 2006 02:05:53 -0700 Subject: [PATCH] two additions to ./linux/Documentation/ioctl-number.txt Cc: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/ioctl-number.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/ioctl-number.txt b/Documentation/ioctl-number.txt index 171a44ebd93..1543802ef53 100644 --- a/Documentation/ioctl-number.txt +++ b/Documentation/ioctl-number.txt @@ -85,7 +85,9 @@ Code Seq# Include File Comments 'C' all linux/soundcard.h 'D' all asm-s390/dasd.h +'E' all linux/input.h 'F' all linux/fb.h +'H' all linux/hiddev.h 'I' all linux/isdn.h 'J' 00-1F drivers/scsi/gdth_ioctl.h 'K' all linux/kd.h -- cgit v1.2.3 From 54e73770357142e297c916c7865f5fca7499f69c Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Fri, 23 Jun 2006 02:05:54 -0700 Subject: [PATCH] list: introduce list_replace() helper list_replace() is similar to list_replace_rcu(), but unlike list_replace_rcu() it could be used when list_empty(old) == 1 doesn't use barriers Signed-off-by: Oleg Nesterov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/list.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/include/linux/list.h b/include/linux/list.h index 76f05718342..a02642e4710 100644 --- a/include/linux/list.h +++ b/include/linux/list.h @@ -197,12 +197,35 @@ static inline void list_del_rcu(struct list_head *entry) entry->prev = LIST_POISON2; } +/** + * list_replace - replace old entry by new one + * @old : the element to be replaced + * @new : the new element to insert + * Note: if 'old' was empty, it will be overwritten. + */ +static inline void list_replace(struct list_head *old, + struct list_head *new) +{ + new->next = old->next; + new->next->prev = new; + new->prev = old->prev; + new->prev->next = new; +} + +static inline void list_replace_init(struct list_head *old, + struct list_head *new) +{ + list_replace(old, new); + INIT_LIST_HEAD(old); +} + /* * list_replace_rcu - replace old entry by new one * @old : the element to be replaced * @new : the new element to insert * * The old entry will be replaced with the new entry atomically. + * Note: 'old' should not be empty. */ static inline void list_replace_rcu(struct list_head *old, struct list_head *new) -- cgit v1.2.3 From 626ab0e69d376fa07599af669af8ba92d58e87c1 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Fri, 23 Jun 2006 02:05:55 -0700 Subject: [PATCH] list: use list_replace_init() instead of list_splice_init() list_splice_init(list, head) does unneeded job if it is known that list_empty(head) == 1. We can use list_replace_init() instead. Signed-off-by: Oleg Nesterov Acked-by: David S. Miller Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/mm/pageattr.c | 8 ++++---- block/ll_rw_blk.c | 5 ++--- fs/aio.c | 4 ++-- kernel/timer.c | 8 ++++---- kernel/workqueue.c | 4 ++-- net/core/dev.c | 6 +++--- net/core/link_watch.c | 5 ++--- 7 files changed, 19 insertions(+), 21 deletions(-) diff --git a/arch/i386/mm/pageattr.c b/arch/i386/mm/pageattr.c index 92c3d9f0e73..0887b34bc59 100644 --- a/arch/i386/mm/pageattr.c +++ b/arch/i386/mm/pageattr.c @@ -209,19 +209,19 @@ int change_page_attr(struct page *page, int numpages, pgprot_t prot) } void global_flush_tlb(void) -{ - LIST_HEAD(l); +{ + struct list_head l; struct page *pg, *next; BUG_ON(irqs_disabled()); spin_lock_irq(&cpa_lock); - list_splice_init(&df_list, &l); + list_replace_init(&df_list, &l); spin_unlock_irq(&cpa_lock); flush_map(); list_for_each_entry_safe(pg, next, &l, lru) __free_page(pg); -} +} #ifdef CONFIG_DEBUG_PAGEALLOC void kernel_map_pages(struct page *page, int numpages, int enable) diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 7eb36c53f4b..465b54312c5 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -3359,12 +3359,11 @@ EXPORT_SYMBOL(end_that_request_chunk); */ static void blk_done_softirq(struct softirq_action *h) { - struct list_head *cpu_list; - LIST_HEAD(local_list); + struct list_head *cpu_list, local_list; local_irq_disable(); cpu_list = &__get_cpu_var(blk_cpu_done); - list_splice_init(cpu_list, &local_list); + list_replace_init(cpu_list, &local_list); local_irq_enable(); while (!list_empty(&local_list)) { diff --git a/fs/aio.c b/fs/aio.c index e41e932ba48..8c34a62df7d 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -777,11 +777,11 @@ out: static int __aio_run_iocbs(struct kioctx *ctx) { struct kiocb *iocb; - LIST_HEAD(run_list); + struct list_head run_list; assert_spin_locked(&ctx->ctx_lock); - list_splice_init(&ctx->run_list, &run_list); + list_replace_init(&ctx->run_list, &run_list); while (!list_empty(&run_list)) { iocb = list_entry(run_list.next, struct kiocb, ki_run_list); diff --git a/kernel/timer.c b/kernel/timer.c index 9e49deed468..3bf0e9ed2db 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -419,10 +419,10 @@ static inline void __run_timers(tvec_base_t *base) spin_lock_irq(&base->lock); while (time_after_eq(jiffies, base->timer_jiffies)) { - struct list_head work_list = LIST_HEAD_INIT(work_list); + struct list_head work_list; struct list_head *head = &work_list; int index = base->timer_jiffies & TVR_MASK; - + /* * Cascade timers: */ @@ -431,8 +431,8 @@ static inline void __run_timers(tvec_base_t *base) (!cascade(base, &base->tv3, INDEX(1))) && !cascade(base, &base->tv4, INDEX(2))) cascade(base, &base->tv5, INDEX(3)); - ++base->timer_jiffies; - list_splice_init(base->tv1.vec + index, &work_list); + ++base->timer_jiffies; + list_replace_init(base->tv1.vec + index, &work_list); while (!list_empty(head)) { void (*fn)(unsigned long); unsigned long data; diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 880fb415a8f..740c5abceb0 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -531,11 +531,11 @@ int current_is_keventd(void) static void take_over_work(struct workqueue_struct *wq, unsigned int cpu) { struct cpu_workqueue_struct *cwq = per_cpu_ptr(wq->cpu_wq, cpu); - LIST_HEAD(list); + struct list_head list; struct work_struct *work; spin_lock_irq(&cwq->lock); - list_splice_init(&cwq->worklist, &list); + list_replace_init(&cwq->worklist, &list); while (!list_empty(&list)) { printk("Taking work for %s\n", wq->name); diff --git a/net/core/dev.c b/net/core/dev.c index ab39fe17cb5..195a5e96b2d 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2980,7 +2980,7 @@ static void netdev_wait_allrefs(struct net_device *dev) static DEFINE_MUTEX(net_todo_run_mutex); void netdev_run_todo(void) { - struct list_head list = LIST_HEAD_INIT(list); + struct list_head list; /* Need to guard against multiple cpu's getting out of order. */ mutex_lock(&net_todo_run_mutex); @@ -2995,9 +2995,9 @@ void netdev_run_todo(void) /* Snapshot list, allow later requests */ spin_lock(&net_todo_list_lock); - list_splice_init(&net_todo_list, &list); + list_replace_init(&net_todo_list, &list); spin_unlock(&net_todo_list_lock); - + while (!list_empty(&list)) { struct net_device *dev = list_entry(list.next, struct net_device, todo_list); diff --git a/net/core/link_watch.c b/net/core/link_watch.c index 646937cc2d8..0f37266411b 100644 --- a/net/core/link_watch.c +++ b/net/core/link_watch.c @@ -91,11 +91,10 @@ static void rfc2863_policy(struct net_device *dev) /* Must be called with the rtnl semaphore held */ void linkwatch_run_queue(void) { - LIST_HEAD(head); - struct list_head *n, *next; + struct list_head head, *n, *next; spin_lock_irq(&lweventlist_lock); - list_splice_init(&lweventlist, &head); + list_replace_init(&lweventlist, &head); spin_unlock_irq(&lweventlist_lock); list_for_each_safe(n, next, &head) { -- cgit v1.2.3 From 3439dd86e34580384d3b58cf8d54a9283cd7a342 Mon Sep 17 00:00:00 2001 From: Porpoise Date: Fri, 23 Jun 2006 02:05:56 -0700 Subject: [PATCH] When CONFIG_BASE_SMALL=1, cascade() may enter an infinite loop When CONFIG_BASE_SAMLL=1, cascade() in may enter the infinite loop. Because of CONFIG_BASE_SMALL=1(TVR_BITS=6 and TVN_BITS=4), the list base->tv5 may cascade into base->tv5. So, the kernel enters the infinite loop in the function cascade(). I created a test module to verify this bug, and a patch to fix it. #include #include #include #include #if 0 #include #else #define kdb_printf printk #endif #define TVN_BITS (CONFIG_BASE_SMALL ? 4 : 6) #define TVR_BITS (CONFIG_BASE_SMALL ? 6 : 8) #define TVN_SIZE (1 << TVN_BITS) #define TVR_SIZE (1 << TVR_BITS) #define TVN_MASK (TVN_SIZE - 1) #define TVR_MASK (TVR_SIZE - 1) #define TV_SIZE(N) (N*TVN_BITS + TVR_BITS) struct timer_list timer0; struct timer_list dummy_timer1; struct timer_list dummy_timer2; void dummy_timer_fun(unsigned long data) { } unsigned long j=0; void check_timer_base(unsigned long data) { kdb_printf("check_timer_base %08x\n",jiffies); mod_timer(&timer0,(jiffies & (~0xFFF)) + 0x1FFF); } int init_module(void) { init_timer(&timer0); timer0.data = (unsigned long)0; timer0.function = check_timer_base; mod_timer(&timer0,jiffies+1); init_timer(&dummy_timer1); dummy_timer1.data = (unsigned long)0; dummy_timer1.function = dummy_timer_fun; init_timer(&dummy_timer2); dummy_timer2.data = (unsigned long)0; dummy_timer2.function = dummy_timer_fun; j=jiffies; j&=(~((1< Cc: Matt Mackall Signed-off-by: Oleg Nesterov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/timer.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/kernel/timer.c b/kernel/timer.c index 3bf0e9ed2db..f35b3939e93 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -383,23 +383,19 @@ EXPORT_SYMBOL(del_timer_sync); static int cascade(tvec_base_t *base, tvec_t *tv, int index) { /* cascade all the timers from tv up one level */ - struct list_head *head, *curr; + struct timer_list *timer, *tmp; + struct list_head tv_list; + + list_replace_init(tv->vec + index, &tv_list); - head = tv->vec + index; - curr = head->next; /* - * We are removing _all_ timers from the list, so we don't have to - * detach them individually, just clear the list afterwards. + * We are removing _all_ timers from the list, so we + * don't have to detach them individually. */ - while (curr != head) { - struct timer_list *tmp; - - tmp = list_entry(curr, struct timer_list, entry); - BUG_ON(tmp->base != base); - curr = curr->next; - internal_add_timer(base, tmp); + list_for_each_entry_safe(timer, tmp, &tv_list, entry) { + BUG_ON(timer->base != base); + internal_add_timer(base, timer); } - INIT_LIST_HEAD(head); return index; } -- cgit v1.2.3 From 226a6b84aaaf1fac7a5d41cf4e7387fd9ba895d5 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 23 Jun 2006 02:05:58 -0700 Subject: [PATCH] CodingStyle: add typedefs chapter Add a chapter on typedefs, copied from an email from Linus to lkml on Feb. 3, 2006. (Subject: Re: [RFC][PATCH 1/5] Virtualization/containers: startup) Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/CodingStyle | 100 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 88 insertions(+), 12 deletions(-) diff --git a/Documentation/CodingStyle b/Documentation/CodingStyle index ce5d2c038cf..6d2412ec91e 100644 --- a/Documentation/CodingStyle +++ b/Documentation/CodingStyle @@ -155,7 +155,83 @@ problem, which is called the function-growth-hormone-imbalance syndrome. See next chapter. - Chapter 5: Functions + Chapter 5: Typedefs + +Please don't use things like "vps_t". + +It's a _mistake_ to use typedef for structures and pointers. When you see a + + vps_t a; + +in the source, what does it mean? + +In contrast, if it says + + struct virtual_container *a; + +you can actually tell what "a" is. + +Lots of people think that typedefs "help readability". Not so. They are +useful only for: + + (a) totally opaque objects (where the typedef is actively used to _hide_ + what the object is). + + Example: "pte_t" etc. opaque objects that you can only access using + the proper accessor functions. + + NOTE! Opaqueness and "accessor functions" are not good in themselves. + The reason we have them for things like pte_t etc. is that there + really is absolutely _zero_ portably accessible information there. + + (b) Clear integer types, where the abstraction _helps_ avoid confusion + whether it is "int" or "long". + + u8/u16/u32 are perfectly fine typedefs, although they fit into + category (d) better than here. + + NOTE! Again - there needs to be a _reason_ for this. If something is + "unsigned long", then there's no reason to do + + typedef unsigned long myflags_t; + + but if there is a clear reason for why it under certain circumstances + might be an "unsigned int" and under other configurations might be + "unsigned long", then by all means go ahead and use a typedef. + + (c) when you use sparse to literally create a _new_ type for + type-checking. + + (d) New types which are identical to standard C99 types, in certain + exceptional circumstances. + + Although it would only take a short amount of time for the eyes and + brain to become accustomed to the standard types like 'uint32_t', + some people object to their use anyway. + + Therefore, the Linux-specific 'u8/u16/u32/u64' types and their + signed equivalents which are identical to standard types are + permitted -- although they are not mandatory in new code of your + own. + + When editing existing code which already uses one or the other set + of types, you should conform to the existing choices in that code. + + (e) Types safe for use in userspace. + + In certain structures which are visible to userspace, we cannot + require C99 types and cannot use the 'u32' form above. Thus, we + use __u32 and similar types in all structures which are shared + with userspace. + +Maybe there are other cases too, but the rule should basically be to NEVER +EVER use a typedef unless you can clearly match one of those rules. + +In general, a pointer, or a struct that has elements that can reasonably +be directly accessed should _never_ be a typedef. + + + Chapter 6: Functions Functions should be short and sweet, and do just one thing. They should fit on one or two screenfuls of text (the ISO/ANSI screen size is 80x24, @@ -183,7 +259,7 @@ and it gets confused. You know you're brilliant, but maybe you'd like to understand what you did 2 weeks from now. - Chapter 6: Centralized exiting of functions + Chapter 7: Centralized exiting of functions Albeit deprecated by some people, the equivalent of the goto statement is used frequently by compilers in form of the unconditional jump instruction. @@ -220,7 +296,7 @@ out: return result; } - Chapter 7: Commenting + Chapter 8: Commenting Comments are good, but there is also a danger of over-commenting. NEVER try to explain HOW your code works in a comment: it's much better to @@ -240,7 +316,7 @@ When commenting the kernel API functions, please use the kerneldoc format. See the files Documentation/kernel-doc-nano-HOWTO.txt and scripts/kernel-doc for details. - Chapter 8: You've made a mess of it + Chapter 9: You've made a mess of it That's OK, we all do. You've probably been told by your long-time Unix user helper that "GNU emacs" automatically formats the C sources for @@ -288,7 +364,7 @@ re-formatting you may want to take a look at the man page. But remember: "indent" is not a fix for bad programming. - Chapter 9: Configuration-files + Chapter 10: Configuration-files For configuration options (arch/xxx/Kconfig, and all the Kconfig files), somewhat different indentation is used. @@ -313,7 +389,7 @@ support for file-systems, for instance) should be denoted (DANGEROUS), other experimental options should be denoted (EXPERIMENTAL). - Chapter 10: Data structures + Chapter 11: Data structures Data structures that have visibility outside the single-threaded environment they are created and destroyed in should always have @@ -344,7 +420,7 @@ Remember: if another thread can find your data structure, and you don't have a reference count on it, you almost certainly have a bug. - Chapter 11: Macros, Enums and RTL + Chapter 12: Macros, Enums and RTL Names of macros defining constants and labels in enums are capitalized. @@ -399,7 +475,7 @@ The cpp manual deals with macros exhaustively. The gcc internals manual also covers RTL which is used frequently with assembly language in the kernel. - Chapter 12: Printing kernel messages + Chapter 13: Printing kernel messages Kernel developers like to be seen as literate. Do mind the spelling of kernel messages to make a good impression. Do not use crippled @@ -410,7 +486,7 @@ Kernel messages do not have to be terminated with a period. Printing numbers in parentheses (%d) adds no value and should be avoided. - Chapter 13: Allocating memory + Chapter 14: Allocating memory The kernel provides the following general purpose memory allocators: kmalloc(), kzalloc(), kcalloc(), and vmalloc(). Please refer to the API @@ -429,7 +505,7 @@ from void pointer to any other pointer type is guaranteed by the C programming language. - Chapter 14: The inline disease + Chapter 15: The inline disease There appears to be a common misperception that gcc has a magic "make me faster" speedup option called "inline". While the use of inlines can be @@ -457,7 +533,7 @@ something it would have done anyway. - Chapter 15: References + Appendix I: References The C Programming Language, Second Edition by Brian W. Kernighan and Dennis M. Ritchie. @@ -481,4 +557,4 @@ Kernel CodingStyle, by greg@kroah.com at OLS 2002: http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/ -- -Last updated on 30 December 2005 by a community effort on LKML. +Last updated on 30 April 2006. -- cgit v1.2.3 From a5d6839b75ca4a29b5e0a5595914a8715e8f746d Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Fri, 23 Jun 2006 02:05:59 -0700 Subject: [PATCH] drivers/md/raid6algos.c: fix a NULL dereference This patch fixes a NULL dereference spotted by the Coverity checker. Signed-off-by: Adrian Bunk Cc: "H. Peter Anvin" Cc: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/raid6algos.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/md/raid6algos.c b/drivers/md/raid6algos.c index 51c63c0cf1c..92657615657 100644 --- a/drivers/md/raid6algos.c +++ b/drivers/md/raid6algos.c @@ -139,15 +139,14 @@ int __init raid6_select_algo(void) } } - if ( best ) + if (best) { printk("raid6: using algorithm %s (%ld MB/s)\n", best->name, (bestperf*HZ) >> (20-16+RAID6_TIME_JIFFIES_LG2)); - else + raid6_call = *best; + } else printk("raid6: Yikes! No algorithm found!\n"); - raid6_call = *best; - free_pages((unsigned long)syndromes, 1); return best ? 0 : -EINVAL; -- cgit v1.2.3 From 908dcecda1d18803b5823f30e6c47d2882dc0cf1 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Fri, 23 Jun 2006 02:06:00 -0700 Subject: [PATCH] adjust handle_IRR_event() return type Correct the return type of handle_IRQ_event() (inconsistency noticed during Xen development), and remove redundant declarations. The return type adjustment required breaking out the definition of irqreturn_t into a separate header, in order to satisfy current include order dependencies. Signed-off-by: Jan Beulich Cc: Richard Henderson Cc: Ivan Kokshaysky Cc: Russell King Cc: Ian Molton Cc: Mikael Starvik Cc: Yoshinori Sato Cc: Hirokazu Takata Cc: Heiko Carstens Cc: Martin Schwidefsky Cc: William Lee Irwin III Cc: "David S. Miller" Cc: Miles Bader Cc: Geert Uytterhoeven Cc: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-alpha/irq.h | 4 ---- include/asm-arm/irq.h | 4 ---- include/asm-arm26/irq.h | 4 ---- include/asm-h8300/irq.h | 4 ---- include/asm-m68k/irq.h | 4 ---- include/asm-m68knommu/irq.h | 4 ---- include/asm-s390/irq.h | 4 ---- include/asm-sparc/irq.h | 4 ---- include/asm-v850/irq.h | 2 -- include/linux/interrupt.h | 21 +-------------------- include/linux/irq.h | 3 ++- include/linux/irqreturn.h | 25 +++++++++++++++++++++++++ kernel/irq/handle.c | 5 +++-- 13 files changed, 31 insertions(+), 57 deletions(-) create mode 100644 include/linux/irqreturn.h diff --git a/include/asm-alpha/irq.h b/include/asm-alpha/irq.h index f6de033718a..917b9fe372c 100644 --- a/include/asm-alpha/irq.h +++ b/include/asm-alpha/irq.h @@ -92,8 +92,4 @@ extern void enable_irq(unsigned int); struct pt_regs; extern void (*perf_irq)(unsigned long, struct pt_regs *); -struct irqaction; -int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); - - #endif /* _ALPHA_IRQ_H */ diff --git a/include/asm-arm/irq.h b/include/asm-arm/irq.h index 60b5105c9c9..66e67e60bc5 100644 --- a/include/asm-arm/irq.h +++ b/include/asm-arm/irq.h @@ -47,10 +47,6 @@ void disable_irq_wake(unsigned int irq); void enable_irq_wake(unsigned int irq); int setup_irq(unsigned int, struct irqaction *); -struct irqaction; -struct pt_regs; -int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); - extern void migrate_irqs(void); #endif diff --git a/include/asm-arm26/irq.h b/include/asm-arm26/irq.h index 06bd5a543d1..9aaac87efba 100644 --- a/include/asm-arm26/irq.h +++ b/include/asm-arm26/irq.h @@ -44,9 +44,5 @@ extern void enable_irq(unsigned int); int set_irq_type(unsigned int irq, unsigned int type); -int setup_irq(unsigned int, struct irqaction *); -struct pt_regs; -int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); - #endif diff --git a/include/asm-h8300/irq.h b/include/asm-h8300/irq.h index 73065f5bda0..42a3ac424a9 100644 --- a/include/asm-h8300/irq.h +++ b/include/asm-h8300/irq.h @@ -63,8 +63,4 @@ extern void enable_irq(unsigned int); extern void disable_irq(unsigned int); #define disable_irq_nosync(x) disable_irq(x) -struct irqaction; -struct pt_regs; -int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); - #endif /* _H8300_IRQ_H_ */ diff --git a/include/asm-m68k/irq.h b/include/asm-m68k/irq.h index b4f48b2a6a5..9727ca9d9f2 100644 --- a/include/asm-m68k/irq.h +++ b/include/asm-m68k/irq.h @@ -130,8 +130,4 @@ extern volatile unsigned int num_spurious; */ extern irq_node_t *new_irq_node(void); -struct irqaction; -struct pt_regs; -int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); - #endif /* _M68K_IRQ_H_ */ diff --git a/include/asm-m68knommu/irq.h b/include/asm-m68knommu/irq.h index 2b408842a30..c5247516fcf 100644 --- a/include/asm-m68knommu/irq.h +++ b/include/asm-m68knommu/irq.h @@ -87,8 +87,4 @@ extern void (*mach_disable_irq)(unsigned int); #define disable_irq(x) do { } while (0) #define disable_irq_nosync(x) disable_irq(x) -struct irqaction; -struct pt_regs; -int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); - #endif /* _M68K_IRQ_H_ */ diff --git a/include/asm-s390/irq.h b/include/asm-s390/irq.h index 916a1aa0b07..bd1a721f7aa 100644 --- a/include/asm-s390/irq.h +++ b/include/asm-s390/irq.h @@ -21,10 +21,6 @@ enum interruption_class { #define touch_nmi_watchdog() do { } while(0) -struct irqaction; -struct pt_regs; -int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); - #endif /* __KERNEL__ */ #endif diff --git a/include/asm-sparc/irq.h b/include/asm-sparc/irq.h index f2d64537e29..3141ddfea97 100644 --- a/include/asm-sparc/irq.h +++ b/include/asm-sparc/irq.h @@ -181,8 +181,4 @@ extern struct sun4m_intregs *sun4m_interrupts; #define SUN4M_INT_SBUS(x) (1 << (x+7)) #define SUN4M_INT_VME(x) (1 << (x)) -struct irqaction; -struct pt_regs; -int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); - #endif diff --git a/include/asm-v850/irq.h b/include/asm-v850/irq.h index 44431152b36..1bf096db8f4 100644 --- a/include/asm-v850/irq.h +++ b/include/asm-v850/irq.h @@ -62,8 +62,6 @@ extern void disable_irq (unsigned int irq); /* Disable an irq without waiting. */ extern void disable_irq_nosync (unsigned int irq); -extern int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); - #endif /* !__ASSEMBLY__ */ #endif /* __V850_IRQ_H__ */ diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 9e0fefd7884..70741e17011 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -7,32 +7,13 @@ #include #include #include +#include #include #include #include #include #include -/* - * For 2.4.x compatibility, 2.4.x can use - * - * typedef void irqreturn_t; - * #define IRQ_NONE - * #define IRQ_HANDLED - * #define IRQ_RETVAL(x) - * - * To mix old-style and new-style irq handler returns. - * - * IRQ_NONE means we didn't handle it. - * IRQ_HANDLED means that we did have a valid interrupt and handled it. - * IRQ_RETVAL(x) selects on the two depending on x being non-zero (for handled) - */ -typedef int irqreturn_t; - -#define IRQ_NONE (0) -#define IRQ_HANDLED (1) -#define IRQ_RETVAL(x) ((x) != 0) - struct irqaction { irqreturn_t (*handler)(int, void *, struct pt_regs *); unsigned long flags; diff --git a/include/linux/irq.h b/include/linux/irq.h index e8a07e75e4f..676e00dfb21 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -175,7 +176,7 @@ static inline void set_balance_irq_affinity(unsigned int irq, cpumask_t mask) extern int no_irq_affinity; extern int noirqdebug_setup(char *str); -extern fastcall int handle_IRQ_event(unsigned int irq, struct pt_regs *regs, +extern fastcall irqreturn_t handle_IRQ_event(unsigned int irq, struct pt_regs *regs, struct irqaction *action); extern fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs); extern void note_interrupt(unsigned int irq, irq_desc_t *desc, diff --git a/include/linux/irqreturn.h b/include/linux/irqreturn.h new file mode 100644 index 00000000000..881883c2009 --- /dev/null +++ b/include/linux/irqreturn.h @@ -0,0 +1,25 @@ +/* irqreturn.h */ +#ifndef _LINUX_IRQRETURN_H +#define _LINUX_IRQRETURN_H + +/* + * For 2.4.x compatibility, 2.4.x can use + * + * typedef void irqreturn_t; + * #define IRQ_NONE + * #define IRQ_HANDLED + * #define IRQ_RETVAL(x) + * + * To mix old-style and new-style irq handler returns. + * + * IRQ_NONE means we didn't handle it. + * IRQ_HANDLED means that we did have a valid interrupt and handled it. + * IRQ_RETVAL(x) selects on the two depending on x being non-zero (for handled) + */ +typedef int irqreturn_t; + +#define IRQ_NONE (0) +#define IRQ_HANDLED (1) +#define IRQ_RETVAL(x) ((x) != 0) + +#endif diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index 51df337b37d..0f653011710 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c @@ -76,10 +76,11 @@ irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs) /* * Have got an event to handle: */ -fastcall int handle_IRQ_event(unsigned int irq, struct pt_regs *regs, +fastcall irqreturn_t handle_IRQ_event(unsigned int irq, struct pt_regs *regs, struct irqaction *action) { - int ret, retval = 0, status = 0; + irqreturn_t ret, retval = IRQ_NONE; + unsigned int status = 0; if (!(action->flags & SA_INTERRUPT)) local_irq_enable(); -- cgit v1.2.3 From cdaad343b561cdeb38b0578bb038eb5e87ed5551 Mon Sep 17 00:00:00 2001 From: Peter Hagervall Date: Fri, 23 Jun 2006 02:06:04 -0700 Subject: [PATCH] Sparse fixes for synclink_cs Mark a few non-exported functions static. Signed-off-by: Peter Hagervall Cc: Paul Fulghum Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/pcmcia/synclink_cs.c | 54 +++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 07213454c45..0c141c295fb 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -844,7 +844,7 @@ static int bh_action(MGSLPC_INFO *info) return rc; } -void bh_handler(void* Context) +static void bh_handler(void* Context) { MGSLPC_INFO *info = (MGSLPC_INFO*)Context; int action; @@ -888,7 +888,7 @@ void bh_handler(void* Context) __FILE__,__LINE__,info->device_name); } -void bh_transmit(MGSLPC_INFO *info) +static void bh_transmit(MGSLPC_INFO *info) { struct tty_struct *tty = info->tty; if (debug_level >= DEBUG_LEVEL_BH) @@ -900,7 +900,7 @@ void bh_transmit(MGSLPC_INFO *info) } } -void bh_status(MGSLPC_INFO *info) +static void bh_status(MGSLPC_INFO *info) { info->ri_chkcount = 0; info->dsr_chkcount = 0; @@ -2305,7 +2305,7 @@ static int mgslpc_ioctl(struct tty_struct *tty, struct file * file, return ioctl_common(info, cmd, arg); } -int ioctl_common(MGSLPC_INFO *info, unsigned int cmd, unsigned long arg) +static int ioctl_common(MGSLPC_INFO *info, unsigned int cmd, unsigned long arg) { int error; struct mgsl_icount cnow; /* kernel counter temps */ @@ -2877,7 +2877,7 @@ done: return ((count < begin+len-off) ? count : begin+len-off); } -int rx_alloc_buffers(MGSLPC_INFO *info) +static int rx_alloc_buffers(MGSLPC_INFO *info) { /* each buffer has header and data */ info->rx_buf_size = sizeof(RXBUF) + info->max_frame_size; @@ -2900,13 +2900,13 @@ int rx_alloc_buffers(MGSLPC_INFO *info) return 0; } -void rx_free_buffers(MGSLPC_INFO *info) +static void rx_free_buffers(MGSLPC_INFO *info) { kfree(info->rx_buf); info->rx_buf = NULL; } -int claim_resources(MGSLPC_INFO *info) +static int claim_resources(MGSLPC_INFO *info) { if (rx_alloc_buffers(info) < 0 ) { printk( "Cant allocate rx buffer %s\n", info->device_name); @@ -2916,7 +2916,7 @@ int claim_resources(MGSLPC_INFO *info) return 0; } -void release_resources(MGSLPC_INFO *info) +static void release_resources(MGSLPC_INFO *info) { if (debug_level >= DEBUG_LEVEL_INFO) printk("release_resources(%s)\n", info->device_name); @@ -2928,7 +2928,7 @@ void release_resources(MGSLPC_INFO *info) * * Arguments: info pointer to device instance data */ -void mgslpc_add_device(MGSLPC_INFO *info) +static void mgslpc_add_device(MGSLPC_INFO *info) { info->next_device = NULL; info->line = mgslpc_device_count; @@ -2964,7 +2964,7 @@ void mgslpc_add_device(MGSLPC_INFO *info) #endif } -void mgslpc_remove_device(MGSLPC_INFO *remove_info) +static void mgslpc_remove_device(MGSLPC_INFO *remove_info) { MGSLPC_INFO *info = mgslpc_device_list; MGSLPC_INFO *last = NULL; @@ -3257,7 +3257,7 @@ static void loopback_enable(MGSLPC_INFO *info) write_reg(info, CHA + MODE, val); } -void hdlc_mode(MGSLPC_INFO *info) +static void hdlc_mode(MGSLPC_INFO *info) { unsigned char val; unsigned char clkmode, clksubmode; @@ -3497,7 +3497,7 @@ void hdlc_mode(MGSLPC_INFO *info) rx_stop(info); } -void rx_stop(MGSLPC_INFO *info) +static void rx_stop(MGSLPC_INFO *info) { if (debug_level >= DEBUG_LEVEL_ISR) printk("%s(%d):rx_stop(%s)\n", @@ -3510,7 +3510,7 @@ void rx_stop(MGSLPC_INFO *info) info->rx_overflow = 0; } -void rx_start(MGSLPC_INFO *info) +static void rx_start(MGSLPC_INFO *info) { if (debug_level >= DEBUG_LEVEL_ISR) printk("%s(%d):rx_start(%s)\n", @@ -3526,7 +3526,7 @@ void rx_start(MGSLPC_INFO *info) info->rx_enabled = 1; } -void tx_start(MGSLPC_INFO *info) +static void tx_start(MGSLPC_INFO *info) { if (debug_level >= DEBUG_LEVEL_ISR) printk("%s(%d):tx_start(%s)\n", @@ -3564,7 +3564,7 @@ void tx_start(MGSLPC_INFO *info) info->tx_enabled = 1; } -void tx_stop(MGSLPC_INFO *info) +static void tx_stop(MGSLPC_INFO *info) { if (debug_level >= DEBUG_LEVEL_ISR) printk("%s(%d):tx_stop(%s)\n", @@ -3578,7 +3578,7 @@ void tx_stop(MGSLPC_INFO *info) /* Reset the adapter to a known state and prepare it for further use. */ -void reset_device(MGSLPC_INFO *info) +static void reset_device(MGSLPC_INFO *info) { /* power up both channels (set BIT7) */ write_reg(info, CHA + CCR0, 0x80); @@ -3628,7 +3628,7 @@ void reset_device(MGSLPC_INFO *info) write_reg(info, IPC, 0x05); } -void async_mode(MGSLPC_INFO *info) +static void async_mode(MGSLPC_INFO *info) { unsigned char val; @@ -3799,7 +3799,7 @@ void async_mode(MGSLPC_INFO *info) /* Set the HDLC idle mode for the transmitter. */ -void tx_set_idle(MGSLPC_INFO *info) +static void tx_set_idle(MGSLPC_INFO *info) { /* Note: ESCC2 only supports flags and one idle modes */ if (info->idle_mode == HDLC_TXIDLE_FLAGS) @@ -3810,7 +3810,7 @@ void tx_set_idle(MGSLPC_INFO *info) /* get state of the V24 status (input) signals. */ -void get_signals(MGSLPC_INFO *info) +static void get_signals(MGSLPC_INFO *info) { unsigned char status = 0; @@ -3832,7 +3832,7 @@ void get_signals(MGSLPC_INFO *info) /* Set the state of DTR and RTS based on contents of * serial_signals member of device extension. */ -void set_signals(MGSLPC_INFO *info) +static void set_signals(MGSLPC_INFO *info) { unsigned char val; @@ -3856,7 +3856,7 @@ void set_signals(MGSLPC_INFO *info) set_reg_bits(info, CHA + PVR, PVR_DTR); } -void rx_reset_buffers(MGSLPC_INFO *info) +static void rx_reset_buffers(MGSLPC_INFO *info) { RXBUF *buf; int i; @@ -3875,7 +3875,7 @@ void rx_reset_buffers(MGSLPC_INFO *info) * * Returns 1 if frame returned, otherwise 0 */ -int rx_get_frame(MGSLPC_INFO *info) +static int rx_get_frame(MGSLPC_INFO *info) { unsigned short status; RXBUF *buf; @@ -3961,7 +3961,7 @@ int rx_get_frame(MGSLPC_INFO *info) return 1; } -BOOLEAN register_test(MGSLPC_INFO *info) +static BOOLEAN register_test(MGSLPC_INFO *info) { static unsigned char patterns[] = { 0x00, 0xff, 0xaa, 0x55, 0x69, 0x96, 0x0f }; @@ -3987,7 +3987,7 @@ BOOLEAN register_test(MGSLPC_INFO *info) return rc; } -BOOLEAN irq_test(MGSLPC_INFO *info) +static BOOLEAN irq_test(MGSLPC_INFO *info) { unsigned long end_time; unsigned long flags; @@ -4022,7 +4022,7 @@ BOOLEAN irq_test(MGSLPC_INFO *info) return info->irq_occurred ? TRUE : FALSE; } -int adapter_test(MGSLPC_INFO *info) +static int adapter_test(MGSLPC_INFO *info) { if (!register_test(info)) { info->init_error = DiagStatus_AddressFailure; @@ -4044,7 +4044,7 @@ int adapter_test(MGSLPC_INFO *info) return 0; } -void trace_block(MGSLPC_INFO *info,const char* data, int count, int xmit) +static void trace_block(MGSLPC_INFO *info,const char* data, int count, int xmit) { int i; int linecount; @@ -4079,7 +4079,7 @@ void trace_block(MGSLPC_INFO *info,const char* data, int count, int xmit) /* HDLC frame time out * update stats and do tx completion processing */ -void tx_timeout(unsigned long context) +static void tx_timeout(unsigned long context) { MGSLPC_INFO *info = (MGSLPC_INFO*)context; unsigned long flags; -- cgit v1.2.3 From 78ce89c92bc6eaf5933b5664bff64253a7103bd7 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Fri, 23 Jun 2006 02:06:05 -0700 Subject: [PATCH] JBD: split checkpoint lists Split the checkpoint list of the transaction into two lists. In the first list we keep the buffers that need to be submitted for IO. In the second list are kept buffers that were already submitted and we just have to wait for the IO to complete. This should simplify a handling of checkpoint lists a bit and can eventually be also a performance gain. Signed-off-by: Jan Kara Cc: Mark Fasheh Cc: "Stephen C. Tweedie" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/jbd/checkpoint.c | 419 ++++++++++++++++++++++++++++++---------------------- include/linux/jbd.h | 8 +- 2 files changed, 246 insertions(+), 181 deletions(-) diff --git a/fs/jbd/checkpoint.c b/fs/jbd/checkpoint.c index 3f5102b069d..47678a26c13 100644 --- a/fs/jbd/checkpoint.c +++ b/fs/jbd/checkpoint.c @@ -24,29 +24,67 @@ #include /* - * Unlink a buffer from a transaction. + * Unlink a buffer from a transaction checkpoint list. * * Called with j_list_lock held. */ - -static inline void __buffer_unlink(struct journal_head *jh) +static inline void __buffer_unlink_first(struct journal_head *jh) { - transaction_t *transaction; - - transaction = jh->b_cp_transaction; - jh->b_cp_transaction = NULL; + transaction_t *transaction = jh->b_cp_transaction; jh->b_cpnext->b_cpprev = jh->b_cpprev; jh->b_cpprev->b_cpnext = jh->b_cpnext; - if (transaction->t_checkpoint_list == jh) + if (transaction->t_checkpoint_list == jh) { transaction->t_checkpoint_list = jh->b_cpnext; - if (transaction->t_checkpoint_list == jh) - transaction->t_checkpoint_list = NULL; + if (transaction->t_checkpoint_list == jh) + transaction->t_checkpoint_list = NULL; + } +} + +/* + * Unlink a buffer from a transaction checkpoint(io) list. + * + * Called with j_list_lock held. + */ +static inline void __buffer_unlink(struct journal_head *jh) +{ + transaction_t *transaction = jh->b_cp_transaction; + + __buffer_unlink_first(jh); + if (transaction->t_checkpoint_io_list == jh) { + transaction->t_checkpoint_io_list = jh->b_cpnext; + if (transaction->t_checkpoint_io_list == jh) + transaction->t_checkpoint_io_list = NULL; + } +} + +/* + * Move a buffer from the checkpoint list to the checkpoint io list + * + * Called with j_list_lock held + */ +static inline void __buffer_relink_io(struct journal_head *jh) +{ + transaction_t *transaction = jh->b_cp_transaction; + + __buffer_unlink_first(jh); + + if (!transaction->t_checkpoint_io_list) { + jh->b_cpnext = jh->b_cpprev = jh; + } else { + jh->b_cpnext = transaction->t_checkpoint_io_list; + jh->b_cpprev = transaction->t_checkpoint_io_list->b_cpprev; + jh->b_cpprev->b_cpnext = jh; + jh->b_cpnext->b_cpprev = jh; + } + transaction->t_checkpoint_io_list = jh; } /* * Try to release a checkpointed buffer from its transaction. - * Returns 1 if we released it. + * Returns 1 if we released it and 2 if we also released the + * whole transaction. + * * Requires j_list_lock * Called under jbd_lock_bh_state(jh2bh(jh)), and drops it */ @@ -57,12 +95,11 @@ static int __try_to_free_cp_buf(struct journal_head *jh) if (jh->b_jlist == BJ_None && !buffer_locked(bh) && !buffer_dirty(bh)) { JBUFFER_TRACE(jh, "remove from checkpoint list"); - __journal_remove_checkpoint(jh); + ret = __journal_remove_checkpoint(jh) + 1; jbd_unlock_bh_state(bh); journal_remove_journal_head(bh); BUFFER_TRACE(bh, "release"); __brelse(bh); - ret = 1; } else { jbd_unlock_bh_state(bh); } @@ -117,83 +154,54 @@ static void jbd_sync_bh(journal_t *journal, struct buffer_head *bh) } /* - * Clean up a transaction's checkpoint list. - * - * We wait for any pending IO to complete and make sure any clean - * buffers are removed from the transaction. - * - * Return 1 if we performed any actions which might have destroyed the - * checkpoint. (journal_remove_checkpoint() deletes the transaction when - * the last checkpoint buffer is cleansed) + * Clean up transaction's list of buffers submitted for io. + * We wait for any pending IO to complete and remove any clean + * buffers. Note that we take the buffers in the opposite ordering + * from the one in which they were submitted for IO. * * Called with j_list_lock held. */ -static int __cleanup_transaction(journal_t *journal, transaction_t *transaction) +static void __wait_cp_io(journal_t *journal, transaction_t *transaction) { - struct journal_head *jh, *next_jh, *last_jh; + struct journal_head *jh; struct buffer_head *bh; - int ret = 0; - - assert_spin_locked(&journal->j_list_lock); - jh = transaction->t_checkpoint_list; - if (!jh) - return 0; - - last_jh = jh->b_cpprev; - next_jh = jh; - do { - jh = next_jh; + tid_t this_tid; + int released = 0; + + this_tid = transaction->t_tid; +restart: + /* Did somebody clean up the transaction in the meanwhile? */ + if (journal->j_checkpoint_transactions != transaction || + transaction->t_tid != this_tid) + return; + while (!released && transaction->t_checkpoint_io_list) { + jh = transaction->t_checkpoint_io_list; bh = jh2bh(jh); + if (!jbd_trylock_bh_state(bh)) { + jbd_sync_bh(journal, bh); + spin_lock(&journal->j_list_lock); + goto restart; + } if (buffer_locked(bh)) { atomic_inc(&bh->b_count); spin_unlock(&journal->j_list_lock); + jbd_unlock_bh_state(bh); wait_on_buffer(bh); /* the journal_head may have gone by now */ BUFFER_TRACE(bh, "brelse"); __brelse(bh); - goto out_return_1; + spin_lock(&journal->j_list_lock); + goto restart; } - /* - * This is foul + * Now in whatever state the buffer currently is, we know that + * it has been written out and so we can drop it from the list */ - if (!jbd_trylock_bh_state(bh)) { - jbd_sync_bh(journal, bh); - goto out_return_1; - } - - if (jh->b_transaction != NULL) { - transaction_t *t = jh->b_transaction; - tid_t tid = t->t_tid; - - spin_unlock(&journal->j_list_lock); - jbd_unlock_bh_state(bh); - log_start_commit(journal, tid); - log_wait_commit(journal, tid); - goto out_return_1; - } - - /* - * AKPM: I think the buffer_jbddirty test is redundant - it - * shouldn't have NULL b_transaction? - */ - next_jh = jh->b_cpnext; - if (!buffer_dirty(bh) && !buffer_jbddirty(bh)) { - BUFFER_TRACE(bh, "remove from checkpoint"); - __journal_remove_checkpoint(jh); - jbd_unlock_bh_state(bh); - journal_remove_journal_head(bh); - __brelse(bh); - ret = 1; - } else { - jbd_unlock_bh_state(bh); - } - } while (jh != last_jh); - - return ret; -out_return_1: - spin_lock(&journal->j_list_lock); - return 1; + released = __journal_remove_checkpoint(jh); + jbd_unlock_bh_state(bh); + journal_remove_journal_head(bh); + __brelse(bh); + } } #define NR_BATCH 64 @@ -203,9 +211,7 @@ __flush_batch(journal_t *journal, struct buffer_head **bhs, int *batch_count) { int i; - spin_unlock(&journal->j_list_lock); ll_rw_block(SWRITE, *batch_count, bhs); - spin_lock(&journal->j_list_lock); for (i = 0; i < *batch_count; i++) { struct buffer_head *bh = bhs[i]; clear_buffer_jwrite(bh); @@ -221,19 +227,43 @@ __flush_batch(journal_t *journal, struct buffer_head **bhs, int *batch_count) * Return 1 if something happened which requires us to abort the current * scan of the checkpoint list. * - * Called with j_list_lock held. + * Called with j_list_lock held and drops it if 1 is returned * Called under jbd_lock_bh_state(jh2bh(jh)), and drops it */ -static int __flush_buffer(journal_t *journal, struct journal_head *jh, - struct buffer_head **bhs, int *batch_count, - int *drop_count) +static int __process_buffer(journal_t *journal, struct journal_head *jh, + struct buffer_head **bhs, int *batch_count) { struct buffer_head *bh = jh2bh(jh); int ret = 0; - if (buffer_dirty(bh) && !buffer_locked(bh) && jh->b_jlist == BJ_None) { - J_ASSERT_JH(jh, jh->b_transaction == NULL); + if (buffer_locked(bh)) { + atomic_inc(&bh->b_count); + spin_unlock(&journal->j_list_lock); + jbd_unlock_bh_state(bh); + wait_on_buffer(bh); + /* the journal_head may have gone by now */ + BUFFER_TRACE(bh, "brelse"); + __brelse(bh); + ret = 1; + } else if (jh->b_transaction != NULL) { + transaction_t *t = jh->b_transaction; + tid_t tid = t->t_tid; + spin_unlock(&journal->j_list_lock); + jbd_unlock_bh_state(bh); + log_start_commit(journal, tid); + log_wait_commit(journal, tid); + ret = 1; + } else if (!buffer_dirty(bh)) { + J_ASSERT_JH(jh, !buffer_jbddirty(bh)); + BUFFER_TRACE(bh, "remove from checkpoint"); + __journal_remove_checkpoint(jh); + spin_unlock(&journal->j_list_lock); + jbd_unlock_bh_state(bh); + journal_remove_journal_head(bh); + __brelse(bh); + ret = 1; + } else { /* * Important: we are about to write the buffer, and * possibly block, while still holding the journal lock. @@ -246,45 +276,30 @@ static int __flush_buffer(journal_t *journal, struct journal_head *jh, J_ASSERT_BH(bh, !buffer_jwrite(bh)); set_buffer_jwrite(bh); bhs[*batch_count] = bh; + __buffer_relink_io(jh); jbd_unlock_bh_state(bh); (*batch_count)++; if (*batch_count == NR_BATCH) { + spin_unlock(&journal->j_list_lock); __flush_batch(journal, bhs, batch_count); ret = 1; } - } else { - int last_buffer = 0; - if (jh->b_cpnext == jh) { - /* We may be about to drop the transaction. Tell the - * caller that the lists have changed. - */ - last_buffer = 1; - } - if (__try_to_free_cp_buf(jh)) { - (*drop_count)++; - ret = last_buffer; - } } return ret; } /* - * Perform an actual checkpoint. We don't write out only enough to - * satisfy the current blocked requests: rather we submit a reasonably - * sized chunk of the outstanding data to disk at once for - * efficiency. __log_wait_for_space() will retry if we didn't free enough. + * Perform an actual checkpoint. We take the first transaction on the + * list of transactions to be checkpointed and send all its buffers + * to disk. We submit larger chunks of data at once. * - * However, we _do_ take into account the amount requested so that once - * the IO has been queued, we can return as soon as enough of it has - * completed to disk. - * * The journal should be locked before calling this function. */ int log_do_checkpoint(journal_t *journal) { + transaction_t *transaction; + tid_t this_tid; int result; - int batch_count = 0; - struct buffer_head *bhs[NR_BATCH]; jbd_debug(1, "Start checkpoint\n"); @@ -299,79 +314,68 @@ int log_do_checkpoint(journal_t *journal) return result; /* - * OK, we need to start writing disk blocks. Try to free up a - * quarter of the log in a single checkpoint if we can. + * OK, we need to start writing disk blocks. Take one transaction + * and write it. */ + spin_lock(&journal->j_list_lock); + if (!journal->j_checkpoint_transactions) + goto out; + transaction = journal->j_checkpoint_transactions; + this_tid = transaction->t_tid; +restart: /* - * AKPM: check this code. I had a feeling a while back that it - * degenerates into a busy loop at unmount time. + * If someone cleaned up this transaction while we slept, we're + * done (maybe it's a new transaction, but it fell at the same + * address). */ - spin_lock(&journal->j_list_lock); - while (journal->j_checkpoint_transactions) { - transaction_t *transaction; - struct journal_head *jh, *last_jh, *next_jh; - int drop_count = 0; - int cleanup_ret, retry = 0; - tid_t this_tid; - - transaction = journal->j_checkpoint_transactions; - this_tid = transaction->t_tid; - jh = transaction->t_checkpoint_list; - last_jh = jh->b_cpprev; - next_jh = jh; - do { + if (journal->j_checkpoint_transactions == transaction && + transaction->t_tid == this_tid) { + int batch_count = 0; + struct buffer_head *bhs[NR_BATCH]; + struct journal_head *jh; + int retry = 0; + + while (!retry && transaction->t_checkpoint_list) { struct buffer_head *bh; - jh = next_jh; - next_jh = jh->b_cpnext; + jh = transaction->t_checkpoint_list; bh = jh2bh(jh); if (!jbd_trylock_bh_state(bh)) { jbd_sync_bh(journal, bh); - spin_lock(&journal->j_list_lock); retry = 1; break; } - retry = __flush_buffer(journal, jh, bhs, &batch_count, &drop_count); - if (cond_resched_lock(&journal->j_list_lock)) { + retry = __process_buffer(journal, jh, bhs,&batch_count); + if (!retry && lock_need_resched(&journal->j_list_lock)){ + spin_unlock(&journal->j_list_lock); retry = 1; break; } - } while (jh != last_jh && !retry); + } if (batch_count) { + if (!retry) { + spin_unlock(&journal->j_list_lock); + retry = 1; + } __flush_batch(journal, bhs, &batch_count); - retry = 1; } + if (retry) { + spin_lock(&journal->j_list_lock); + goto restart; + } /* - * If someone cleaned up this transaction while we slept, we're - * done - */ - if (journal->j_checkpoint_transactions != transaction) - break; - if (retry) - continue; - /* - * Maybe it's a new transaction, but it fell at the same - * address - */ - if (transaction->t_tid != this_tid) - continue; - /* - * We have walked the whole transaction list without - * finding anything to write to disk. We had better be - * able to make some progress or we are in trouble. + * Now we have cleaned up the first transaction's checkpoint + * list. Let's clean up the second one */ - cleanup_ret = __cleanup_transaction(journal, transaction); - J_ASSERT(drop_count != 0 || cleanup_ret != 0); - if (journal->j_checkpoint_transactions != transaction) - break; + __wait_cp_io(journal, transaction); } +out: spin_unlock(&journal->j_list_lock); result = cleanup_journal_tail(journal); if (result < 0) return result; - return 0; } @@ -455,6 +459,54 @@ int cleanup_journal_tail(journal_t *journal) /* Checkpoint list management */ +/* + * journal_clean_one_cp_list + * + * Find all the written-back checkpoint buffers in the given list and release them. + * + * Called with the journal locked. + * Called with j_list_lock held. + * Returns number of bufers reaped (for debug) + */ + +static int journal_clean_one_cp_list(struct journal_head *jh, int *released) +{ + struct journal_head *last_jh; + struct journal_head *next_jh = jh; + int ret, freed = 0; + + *released = 0; + if (!jh) + return 0; + + last_jh = jh->b_cpprev; + do { + jh = next_jh; + next_jh = jh->b_cpnext; + /* Use trylock because of the ranking */ + if (jbd_trylock_bh_state(jh2bh(jh))) { + ret = __try_to_free_cp_buf(jh); + if (ret) { + freed++; + if (ret == 2) { + *released = 1; + return freed; + } + } + } + /* + * This function only frees up some memory + * if possible so we dont have an obligation + * to finish processing. Bail out if preemption + * requested: + */ + if (need_resched()) + return freed; + } while (jh != last_jh); + + return freed; +} + /* * journal_clean_checkpoint_list * @@ -462,46 +514,44 @@ int cleanup_journal_tail(journal_t *journal) * * Called with the journal locked. * Called with j_list_lock held. - * Returns number of bufers reaped (for debug) + * Returns number of buffers reaped (for debug) */ int __journal_clean_checkpoint_list(journal_t *journal) { transaction_t *transaction, *last_transaction, *next_transaction; int ret = 0; + int released; transaction = journal->j_checkpoint_transactions; - if (transaction == 0) + if (!transaction) goto out; last_transaction = transaction->t_cpprev; next_transaction = transaction; do { - struct journal_head *jh; - transaction = next_transaction; next_transaction = transaction->t_cpnext; - jh = transaction->t_checkpoint_list; - if (jh) { - struct journal_head *last_jh = jh->b_cpprev; - struct journal_head *next_jh = jh; - - do { - jh = next_jh; - next_jh = jh->b_cpnext; - /* Use trylock because of the ranknig */ - if (jbd_trylock_bh_state(jh2bh(jh))) - ret += __try_to_free_cp_buf(jh); - /* - * This function only frees up some memory - * if possible so we dont have an obligation - * to finish processing. Bail out if preemption - * requested: - */ - if (need_resched()) - goto out; - } while (jh != last_jh); - } + ret += journal_clean_one_cp_list(transaction-> + t_checkpoint_list, &released); + /* + * This function only frees up some memory if possible so we + * dont have an obligation to finish processing. Bail out if + * preemption requested: + */ + if (need_resched()) + goto out; + if (released) + continue; + /* + * It is essential that we are as careful as in the case of + * t_checkpoint_list with removing the buffer from the list as + * we can possibly see not yet submitted buffers on io_list + */ + ret += journal_clean_one_cp_list(transaction-> + t_checkpoint_io_list, &released); + if (need_resched()) + goto out; } while (transaction != last_transaction); out: return ret; @@ -516,18 +566,22 @@ out: * buffer updates committed in that transaction have safely been stored * elsewhere on disk. To achieve this, all of the buffers in a * transaction need to be maintained on the transaction's checkpoint - * list until they have been rewritten, at which point this function is + * lists until they have been rewritten, at which point this function is * called to remove the buffer from the existing transaction's - * checkpoint list. + * checkpoint lists. + * + * The function returns 1 if it frees the transaction, 0 otherwise. * * This function is called with the journal locked. * This function is called with j_list_lock held. + * This function is called with jbd_lock_bh_state(jh2bh(jh)) */ -void __journal_remove_checkpoint(struct journal_head *jh) +int __journal_remove_checkpoint(struct journal_head *jh) { transaction_t *transaction; journal_t *journal; + int ret = 0; JBUFFER_TRACE(jh, "entry"); @@ -538,8 +592,10 @@ void __journal_remove_checkpoint(struct journal_head *jh) journal = transaction->t_journal; __buffer_unlink(jh); + jh->b_cp_transaction = NULL; - if (transaction->t_checkpoint_list != NULL) + if (transaction->t_checkpoint_list != NULL || + transaction->t_checkpoint_io_list != NULL) goto out; JBUFFER_TRACE(jh, "transaction has no more buffers"); @@ -565,8 +621,10 @@ void __journal_remove_checkpoint(struct journal_head *jh) /* Just in case anybody was waiting for more transactions to be checkpointed... */ wake_up(&journal->j_wait_logspace); + ret = 1; out: JBUFFER_TRACE(jh, "exit"); + return ret; } /* @@ -628,6 +686,7 @@ void __journal_drop_transaction(journal_t *journal, transaction_t *transaction) J_ASSERT(transaction->t_shadow_list == NULL); J_ASSERT(transaction->t_log_list == NULL); J_ASSERT(transaction->t_checkpoint_list == NULL); + J_ASSERT(transaction->t_checkpoint_io_list == NULL); J_ASSERT(transaction->t_updates == 0); J_ASSERT(journal->j_committing_transaction != transaction); J_ASSERT(journal->j_running_transaction != transaction); diff --git a/include/linux/jbd.h b/include/linux/jbd.h index 6a425e370cb..20eb34403d0 100644 --- a/include/linux/jbd.h +++ b/include/linux/jbd.h @@ -500,6 +500,12 @@ struct transaction_s */ struct journal_head *t_checkpoint_list; + /* + * Doubly-linked circular list of all buffers submitted for IO while + * checkpointing. [j_list_lock] + */ + struct journal_head *t_checkpoint_io_list; + /* * Doubly-linked circular list of temporary buffers currently undergoing * IO in the log [j_list_lock] @@ -849,7 +855,7 @@ extern void journal_commit_transaction(journal_t *); /* Checkpoint list management */ int __journal_clean_checkpoint_list(journal_t *journal); -void __journal_remove_checkpoint(struct journal_head *); +int __journal_remove_checkpoint(struct journal_head *); void __journal_insert_checkpoint(struct journal_head *, transaction_t *); /* Buffer IO */ -- cgit v1.2.3 From 125e18745f16685f69a34fd6130d47598fc4bf54 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Fri, 23 Jun 2006 02:06:06 -0700 Subject: [PATCH] More BUG_ON conversion Signed-off-by: Eric Sesterhenn Signed-off-by: Alexey Dobriyan Cc: Bartlomiej Zolnierkiewicz Cc: Alan Cox Cc: James Bottomley Acked-by: "Salyzyn, Mark" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/frv/kernel/setup.c | 2 +- drivers/ide/ide-cd.c | 3 +-- drivers/ide/ide-dma.c | 6 ++---- drivers/ide/ide-floppy.c | 12 ++++-------- drivers/ide/ide-iops.c | 12 ++++-------- drivers/ide/ide-lib.c | 3 +-- drivers/ide/ide-taskfile.c | 3 +-- drivers/ide/ide.c | 3 +-- drivers/ide/pci/trm290.c | 3 +-- drivers/scsi/53c700.h | 6 ++---- drivers/scsi/aacraid/aachba.c | 15 +++++---------- drivers/scsi/aacraid/commsup.c | 6 ++---- drivers/scsi/arm/queue.c | 6 ++---- drivers/scsi/ibmmca.c | 3 +-- drivers/scsi/ide-scsi.c | 6 ++---- drivers/scsi/megaraid.c | 2 +- kernel/exit.c | 5 ++--- mm/pdflush.c | 3 +-- 18 files changed, 34 insertions(+), 65 deletions(-) diff --git a/arch/frv/kernel/setup.c b/arch/frv/kernel/setup.c index 5908deae960..1f7d65f29e7 100644 --- a/arch/frv/kernel/setup.c +++ b/arch/frv/kernel/setup.c @@ -814,7 +814,7 @@ void __init setup_arch(char **cmdline_p) * - by now the stack is part of the init task */ printk("Memory %08lx-%08lx\n", memory_start, memory_end); - if (memory_start == memory_end) BUG(); + BUG_ON(memory_start == memory_end); init_mm.start_code = (unsigned long) &_stext; init_mm.end_code = (unsigned long) &_etext; diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index abb83d95df5..6de3cd3d6e8 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -1725,8 +1725,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) } } - if (HWGROUP(drive)->handler != NULL) - BUG(); + BUG_ON(HWGROUP(drive)->handler != NULL); ide_set_handler(drive, cdrom_newpc_intr, rq->timeout, NULL); return ide_started; diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index c481be8b807..783a2475ee8 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c @@ -206,8 +206,7 @@ int ide_build_sglist(ide_drive_t *drive, struct request *rq) ide_hwif_t *hwif = HWIF(drive); struct scatterlist *sg = hwif->sg_table; - if ((rq->flags & REQ_DRIVE_TASKFILE) && rq->nr_sectors > 256) - BUG(); + BUG_ON((rq->flags & REQ_DRIVE_TASKFILE) && rq->nr_sectors > 256); ide_map_sg(drive, rq); @@ -947,8 +946,7 @@ void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_p } printk("\n"); - if (!(hwif->dma_master)) - BUG(); + BUG_ON(!hwif->dma_master); } EXPORT_SYMBOL_GPL(ide_setup_dma); diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index a53e3ce4a14..a1179e92496 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -898,8 +898,7 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive) "to send us more data than expected " "- discarding data\n"); idefloppy_discard_data(drive,bcount.all); - if (HWGROUP(drive)->handler != NULL) - BUG(); + BUG_ON(HWGROUP(drive)->handler != NULL); ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, @@ -932,8 +931,7 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive) pc->actually_transferred += bcount.all; pc->current_position += bcount.all; - if (HWGROUP(drive)->handler != NULL) - BUG(); + BUG_ON(HWGROUP(drive)->handler != NULL); ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL); /* And set the interrupt handler again */ return ide_started; } @@ -960,8 +958,7 @@ static ide_startstop_t idefloppy_transfer_pc (ide_drive_t *drive) "issuing a packet command\n"); return ide_do_reset(drive); } - if (HWGROUP(drive)->handler != NULL) - BUG(); + BUG_ON(HWGROUP(drive)->handler != NULL); /* Set the interrupt routine */ ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL); /* Send the actual packet */ @@ -1017,8 +1014,7 @@ static ide_startstop_t idefloppy_transfer_pc1 (ide_drive_t *drive) * 40 and 50msec work well. idefloppy_pc_intr will not be actually * used until after the packet is moved in about 50 msec. */ - if (HWGROUP(drive)->handler != NULL) - BUG(); + BUG_ON(HWGROUP(drive)->handler != NULL); ide_set_handler(drive, &idefloppy_pc_intr, /* service routine for packet command */ floppy->ticks, /* wait this long before "failing" */ diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index b72dde70840..97a49e77a8f 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -939,8 +939,7 @@ void ide_execute_command(ide_drive_t *drive, task_ioreg_t cmd, ide_handler_t *ha spin_lock_irqsave(&ide_lock, flags); - if(hwgroup->handler) - BUG(); + BUG_ON(hwgroup->handler); hwgroup->handler = handler; hwgroup->expiry = expiry; hwgroup->timer.expires = jiffies + timeout; @@ -981,8 +980,7 @@ static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive) printk("%s: ATAPI reset complete\n", drive->name); } else { if (time_before(jiffies, hwgroup->poll_timeout)) { - if (HWGROUP(drive)->handler != NULL) - BUG(); + BUG_ON(HWGROUP(drive)->handler != NULL); ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL); /* continue polling */ return ide_started; @@ -1021,8 +1019,7 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive) if (!OK_STAT(tmp = hwif->INB(IDE_STATUS_REG), 0, BUSY_STAT)) { if (time_before(jiffies, hwgroup->poll_timeout)) { - if (HWGROUP(drive)->handler != NULL) - BUG(); + BUG_ON(HWGROUP(drive)->handler != NULL); ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL); /* continue polling */ return ide_started; @@ -1138,8 +1135,7 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) hwgroup = HWGROUP(drive); /* We must not reset with running handlers */ - if(hwgroup->handler != NULL) - BUG(); + BUG_ON(hwgroup->handler != NULL); /* For an ATAPI device, first try an ATAPI SRST. */ if (drive->media != ide_disk && !do_not_try_atapi) { diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c index 41d46dbe6c2..16a143133f9 100644 --- a/drivers/ide/ide-lib.c +++ b/drivers/ide/ide-lib.c @@ -164,8 +164,7 @@ u8 ide_rate_filter (u8 mode, u8 speed) // printk("%s: mode 0x%02x, speed 0x%02x\n", __FUNCTION__, mode, speed); /* So that we remember to update this if new modes appear */ - if (mode > 4) - BUG(); + BUG_ON(mode > 4); return min(speed, speed_max[mode]); #else /* !CONFIG_BLK_DEV_IDEDMA */ return min(speed, (u8)XFER_PIO_4); diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index 9233b8109a0..a839b2a8f6f 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -196,8 +196,7 @@ ide_startstop_t set_geometry_intr (ide_drive_t *drive) if (stat & (ERR_STAT|DRQ_STAT)) return ide_error(drive, "set_geometry_intr", stat); - if (HWGROUP(drive)->handler != NULL) - BUG(); + BUG_ON(HWGROUP(drive)->handler != NULL); ide_set_handler(drive, &set_geometry_intr, WAIT_WORSTCASE, NULL); return ide_started; } diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index f5a60912c27..9799aed772e 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -1367,8 +1367,7 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device ide_abort(drive, "drive reset"); - if(HWGROUP(drive)->handler) - BUG(); + BUG_ON(HWGROUP(drive)->handler); /* Ensure nothing gets queued after we drop the lock. Reset will clear the busy */ diff --git a/drivers/ide/pci/trm290.c b/drivers/ide/pci/trm290.c index c26c8ca90dd..fe80295974e 100644 --- a/drivers/ide/pci/trm290.c +++ b/drivers/ide/pci/trm290.c @@ -183,8 +183,7 @@ static void trm290_ide_dma_exec_cmd(ide_drive_t *drive, u8 command) { ide_hwif_t *hwif = HWIF(drive); - if (HWGROUP(drive)->handler != NULL) /* paranoia check */ - BUG(); + BUG_ON(HWGROUP(drive)->handler != NULL); /* paranoia check */ ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); /* issue cmd to drive */ hwif->OUTB(command, IDE_COMMAND_REG); diff --git a/drivers/scsi/53c700.h b/drivers/scsi/53c700.h index d8041952b1b..7f22a06fe5e 100644 --- a/drivers/scsi/53c700.h +++ b/drivers/scsi/53c700.h @@ -474,8 +474,7 @@ NCR_700_readl(struct Scsi_Host *host, __u32 reg) ioread32(hostdata->base + reg); #if 1 /* sanity check the register */ - if((reg & 0x3) != 0) - BUG(); + BUG_ON((reg & 0x3) != 0); #endif return value; @@ -498,8 +497,7 @@ NCR_700_writel(__u32 value, struct Scsi_Host *host, __u32 reg) #if 1 /* sanity check the register */ - if((reg & 0x3) != 0) - BUG(); + BUG_ON((reg & 0x3) != 0); #endif bEBus ? iowrite32be(value, hostdata->base + reg): diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index ea9e038813e..83b5c7d085f 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -396,8 +396,7 @@ static void get_container_name_callback(void *context, struct fib * fibptr) scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL; dprintk((KERN_DEBUG "get_container_name_callback[cpu %d]: t = %ld.\n", smp_processor_id(), jiffies)); - if (fibptr == NULL) - BUG(); + BUG_ON(fibptr == NULL); get_name_reply = (struct aac_get_name_resp *) fib_data(fibptr); /* Failure is irrelevant, using default value instead */ @@ -956,8 +955,7 @@ static void io_callback(void *context, struct fib * fibptr) smp_processor_id(), (unsigned long long)lba, jiffies); } - if (fibptr == NULL) - BUG(); + BUG_ON(fibptr == NULL); if(scsicmd->use_sg) pci_unmap_sg(dev->pdev, @@ -1092,8 +1090,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid) aac_build_sgraw(scsicmd, &readcmd->sg); fibsize = sizeof(struct aac_raw_io) + ((le32_to_cpu(readcmd->sg.count) - 1) * sizeof (struct sgentryraw)); - if (fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr))) - BUG(); + BUG_ON(fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr))); /* * Now send the Fib to the adapter */ @@ -1261,8 +1258,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid) aac_build_sgraw(scsicmd, &writecmd->sg); fibsize = sizeof(struct aac_raw_io) + ((le32_to_cpu(writecmd->sg.count) - 1) * sizeof (struct sgentryraw)); - if (fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr))) - BUG(); + BUG_ON(fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr))); /* * Now send the Fib to the adapter */ @@ -1904,8 +1900,7 @@ static void aac_srb_callback(void *context, struct fib * fibptr) scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL; dev = (struct aac_dev *)scsicmd->device->host->hostdata; - if (fibptr == NULL) - BUG(); + BUG_ON(fibptr == NULL); srbreply = (struct aac_srb_reply *) fib_data(fibptr); diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index d2ef17ea44f..3f27419c66a 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -229,8 +229,7 @@ void aac_fib_init(struct fib *fibptr) static void fib_dealloc(struct fib * fibptr) { struct hw_fib *hw_fib = fibptr->hw_fib; - if(hw_fib->header.StructType != FIB_MAGIC) - BUG(); + BUG_ON(hw_fib->header.StructType != FIB_MAGIC); hw_fib->header.XferState = 0; } @@ -530,8 +529,7 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, } } else down(&fibptr->event_wait); - if(fibptr->done == 0) - BUG(); + BUG_ON(fibptr->done == 0); if((fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT)){ return -ETIMEDOUT; diff --git a/drivers/scsi/arm/queue.c b/drivers/scsi/arm/queue.c index b10750bb5c0..8caa5903ce3 100644 --- a/drivers/scsi/arm/queue.c +++ b/drivers/scsi/arm/queue.c @@ -118,8 +118,7 @@ int __queue_add(Queue_t *queue, Scsi_Cmnd *SCpnt, int head) list_del(l); q = list_entry(l, QE_t, list); - if (BAD_MAGIC(q, QUEUE_MAGIC_FREE)) - BUG(); + BUG_ON(BAD_MAGIC(q, QUEUE_MAGIC_FREE)); SET_MAGIC(q, QUEUE_MAGIC_USED); q->SCpnt = SCpnt; @@ -144,8 +143,7 @@ static Scsi_Cmnd *__queue_remove(Queue_t *queue, struct list_head *ent) */ list_del(ent); q = list_entry(ent, QE_t, list); - if (BAD_MAGIC(q, QUEUE_MAGIC_USED)) - BUG(); + BUG_ON(BAD_MAGIC(q, QUEUE_MAGIC_USED)); SET_MAGIC(q, QUEUE_MAGIC_FREE); list_add(ent, &queue->free); diff --git a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c index 0c6dc31bb14..115f55471ed 100644 --- a/drivers/scsi/ibmmca.c +++ b/drivers/scsi/ibmmca.c @@ -2241,8 +2241,7 @@ static int __ibmmca_host_reset(Scsi_Cmnd * cmd) int host_index; unsigned long imm_command; - if (cmd == NULL) - BUG(); + BUG_ON(cmd == NULL); ticks = IM_RESET_DELAY * HZ; shpnt = cmd->device->host; diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index 39b760a2424..988e6f7af01 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -600,8 +600,7 @@ static ide_startstop_t idescsi_transfer_pc(ide_drive_t *drive) "issuing a packet command\n"); return ide_do_reset (drive); } - if (HWGROUP(drive)->handler != NULL) - BUG(); + BUG_ON(HWGROUP(drive)->handler != NULL); /* Set the interrupt routine */ ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), idescsi_expiry); /* Send the actual packet */ @@ -691,8 +690,7 @@ static ide_startstop_t idescsi_issue_pc (ide_drive_t *drive, idescsi_pc_t *pc) set_bit(PC_DMA_OK, &pc->flags); if (test_bit(IDESCSI_DRQ_INTERRUPT, &scsi->flags)) { - if (HWGROUP(drive)->handler != NULL) - BUG(); + BUG_ON(HWGROUP(drive)->handler != NULL); ide_set_handler(drive, &idescsi_transfer_pc, get_timeout(pc), idescsi_expiry); /* Issue the packet command */ diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index c33857e7b33..5d2cefb5e52 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c @@ -1828,7 +1828,7 @@ mega_build_sglist(adapter_t *adapter, scb_t *scb, u32 *buf, u32 *len) scb->dma_type = MEGA_SGLIST; - if( sgcnt > adapter->sglen ) BUG(); + BUG_ON(sgcnt > adapter->sglen); *len = 0; diff --git a/kernel/exit.c b/kernel/exit.c index e06d0c10a24..a3baf92462b 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -579,7 +579,7 @@ static void exit_mm(struct task_struct * tsk) down_read(&mm->mmap_sem); } atomic_inc(&mm->mm_count); - if (mm != tsk->active_mm) BUG(); + BUG_ON(mm != tsk->active_mm); /* more a memory barrier than a real lock */ task_lock(tsk); tsk->mm = NULL; @@ -1530,8 +1530,7 @@ check_continued: if (options & __WNOTHREAD) break; tsk = next_thread(tsk); - if (tsk->signal != current->signal) - BUG(); + BUG_ON(tsk->signal != current->signal); } while (tsk != current); read_unlock(&tasklist_lock); diff --git a/mm/pdflush.c b/mm/pdflush.c index c4b6d0afd73..df7e50b8f70 100644 --- a/mm/pdflush.c +++ b/mm/pdflush.c @@ -202,8 +202,7 @@ int pdflush_operation(void (*fn)(unsigned long), unsigned long arg0) unsigned long flags; int ret = 0; - if (fn == NULL) - BUG(); /* Hard to diagnose if it's deferred */ + BUG_ON(fn == NULL); /* Hard to diagnose if it's deferred */ spin_lock_irqsave(&pdflush_lock, flags); if (list_empty(&pdflush_list)) { -- cgit v1.2.3 From 98bd34eaf1a7d1f2ed9c4e5d3a9664d3dcdd2159 Mon Sep 17 00:00:00 2001 From: Mike Miller Date: Fri, 23 Jun 2006 02:06:07 -0700 Subject: [PATCH] make kernel warn about incorrectly sized partitions Sometimes partitions claim to be larger than the reported capacity of a disk device. This patch makes the kernel warn about those partitions. We still permit these patitions to be used. Quoting Andries Brouwer : Case 1: The kernel is mistaken about the size of the disk. (There are commands to clip a disk to a certain capacity, there are jumpers to tell a disk that it should report a certain capacity etc. Usually this is because of BIOS bugs. In bad cases the machine will crash in the BIOS and hence fail to boot if the disk reports full capacity.) In such cases actually accessing the blocks of the partition may work fine, or may work fine after running an unclip utility. I wrote "setmax" some years ago precisely for this reason. Case 2: There was a messy partition table (maybe just a rounding error) but the actual filesystem on the partition is contained in the physical disk. Now using the filesystem goes without problem. Case 3: Both partition and filesystem extend beyond the end of the disk. In forensic or debugging situations one often uses a copy of the start of a disk. Now access beyond the end gives an expected I/O error. Signed-off-by: Mike Miller Signed-off-by: Stephen Cameron Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/partitions/check.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/partitions/check.c b/fs/partitions/check.c index cd885b23cb5..2ef313a96b6 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -484,6 +484,10 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev) sector_t from = state->parts[p].from; if (!size) continue; + if (from + size > get_capacity(disk)) { + printk(" %s: p%d exceeds device capacity\n", + disk->disk_name, p); + } add_partition(disk, p, from, size); #ifdef CONFIG_BLK_DEV_MD if (state->parts[p].flags) -- cgit v1.2.3 From eefe85ee350ece1bdf3e9a61e941d3394a528660 Mon Sep 17 00:00:00 2001 From: Constantine Sapuntzakis Date: Fri, 23 Jun 2006 02:06:08 -0700 Subject: [PATCH] drivers/block/loop.c: don't return garbage if LOOP_SET_STATUS not called While writing a version of losetup, I ran into the problem that the loop device was returning total garbage. It turns out the problem was that this losetup was only issuing the LOOP_SET_FD ioctl and not issuing a subsequent LOOP_SET_STATUS ioctl. This losetup didn't have any special status to set, so it left out the call. The deeper cause is that loop_set_fd sets the transfer function to NULL, which causes no transfer to happen lo_do_transfer. This patch fixes the problem by setting transfer to transfer_none in loop_set_fd. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/loop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 9c3b94e8f03..3c74ea729fc 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -818,7 +818,7 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file, lo->lo_device = bdev; lo->lo_flags = lo_flags; lo->lo_backing_file = file; - lo->transfer = NULL; + lo->transfer = transfer_none; lo->ioctl = NULL; lo->lo_sizelimit = 0; lo->old_gfp_mask = mapping_gfp_mask(mapping); -- cgit v1.2.3 From e83319510b04dd51a60da8a0b4ccf8b92b3ab1ad Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Fri, 23 Jun 2006 02:06:09 -0700 Subject: [PATCH] docs: update sparse.txt with CHECK_ENDIAN Update the sparse documentation to omit the -Wbitwise flag example (as it is now passed by default), and document the kernel defines to enable endianness checking. Signed-off-by: Bob Copeland Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/sparse.txt | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/Documentation/sparse.txt b/Documentation/sparse.txt index 3f1c5464b1c..5a311c38dd1 100644 --- a/Documentation/sparse.txt +++ b/Documentation/sparse.txt @@ -1,5 +1,6 @@ Copyright 2004 Linus Torvalds Copyright 2004 Pavel Machek +Copyright 2006 Bob Copeland Using sparse for typechecking ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -41,15 +42,8 @@ sure that bitwise types don't get mixed up (little-endian vs big-endian vs cpu-endian vs whatever), and there the constant "0" really _is_ special. -Use - - make C=[12] CF=-Wbitwise - -or you don't get any checking at all. - - -Where to get sparse -~~~~~~~~~~~~~~~~~~~ +Getting sparse +~~~~~~~~~~~~~~ With git, you can just get it from @@ -57,7 +51,7 @@ With git, you can just get it from and DaveJ has tar-balls at - http://www.codemonkey.org.uk/projects/git-snapshots/sparse/ + http://www.codemonkey.org.uk/projects/git-snapshots/sparse/ Once you have it, just do @@ -65,8 +59,20 @@ Once you have it, just do make make install -as your regular user, and it will install sparse in your ~/bin directory. -After that, doing a kernel make with "make C=1" will run sparse on all the -C files that get recompiled, or with "make C=2" will run sparse on the -files whether they need to be recompiled or not (ie the latter is fast way -to check the whole tree if you have already built it). +as a regular user, and it will install sparse in your ~/bin directory. + +Using sparse +~~~~~~~~~~~~ + +Do a kernel make with "make C=1" to run sparse on all the C files that get +recompiled, or use "make C=2" to run sparse on the files whether they need to +be recompiled or not. The latter is a fast way to check the whole tree if you +have already built it. + +The optional make variable CF can be used to pass arguments to sparse. The +build system passes -Wbitwise to sparse automatically. To perform endianness +checks, you may define __CHECK_ENDIAN__: + + make C=2 CF="-D__CHECK_ENDIAN__" + +These checks are disabled by default as they generate a host of warnings. -- cgit v1.2.3 From bae386f7884aa3720cc7880b36a41a1d2b9c327b Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Mon, 24 Apr 2006 21:12:59 +0200 Subject: [PATCH] iosched: use hlist for request hashtable Use hlist instead of list_head for request hashtable in deadline-iosched and as-iosched. It also can remove the flag to know hashed or unhashed. Signed-off-by: Akinobu Mita Signed-off-by: Jens Axboe block/as-iosched.c | 45 +++++++++++++++++++-------------------------- block/deadline-iosched.c | 39 ++++++++++++++++----------------------- 2 files changed, 35 insertions(+), 49 deletions(-) --- block/as-iosched.c | 45 +++++++++++++++++++-------------------------- block/deadline-iosched.c | 39 ++++++++++++++++----------------------- 2 files changed, 35 insertions(+), 49 deletions(-) diff --git a/block/as-iosched.c b/block/as-iosched.c index 0c750393be4..9b13d72ffef 100644 --- a/block/as-iosched.c +++ b/block/as-iosched.c @@ -96,7 +96,7 @@ struct as_data { struct as_rq *next_arq[2]; /* next in sort order */ sector_t last_sector[2]; /* last REQ_SYNC & REQ_ASYNC sectors */ - struct list_head *hash; /* request hash */ + struct hlist_head *hash; /* request hash */ unsigned long exit_prob; /* probability a task will exit while being waited on */ @@ -165,8 +165,7 @@ struct as_rq { /* * request hash, key is the ending offset (for back merge lookup) */ - struct list_head hash; - unsigned int on_hash; + struct hlist_node hash; /* * expire fifo @@ -282,17 +281,15 @@ static const int as_hash_shift = 6; #define AS_HASH_FN(sec) (hash_long(AS_HASH_BLOCK((sec)), as_hash_shift)) #define AS_HASH_ENTRIES (1 << as_hash_shift) #define rq_hash_key(rq) ((rq)->sector + (rq)->nr_sectors) -#define list_entry_hash(ptr) list_entry((ptr), struct as_rq, hash) static inline void __as_del_arq_hash(struct as_rq *arq) { - arq->on_hash = 0; - list_del_init(&arq->hash); + hlist_del_init(&arq->hash); } static inline void as_del_arq_hash(struct as_rq *arq) { - if (arq->on_hash) + if (!hlist_unhashed(&arq->hash)) __as_del_arq_hash(arq); } @@ -300,10 +297,9 @@ static void as_add_arq_hash(struct as_data *ad, struct as_rq *arq) { struct request *rq = arq->request; - BUG_ON(arq->on_hash); + BUG_ON(!hlist_unhashed(&arq->hash)); - arq->on_hash = 1; - list_add(&arq->hash, &ad->hash[AS_HASH_FN(rq_hash_key(rq))]); + hlist_add_head(&arq->hash, &ad->hash[AS_HASH_FN(rq_hash_key(rq))]); } /* @@ -312,31 +308,29 @@ static void as_add_arq_hash(struct as_data *ad, struct as_rq *arq) static inline void as_hot_arq_hash(struct as_data *ad, struct as_rq *arq) { struct request *rq = arq->request; - struct list_head *head = &ad->hash[AS_HASH_FN(rq_hash_key(rq))]; + struct hlist_head *head = &ad->hash[AS_HASH_FN(rq_hash_key(rq))]; - if (!arq->on_hash) { + if (hlist_unhashed(&arq->hash)) { WARN_ON(1); return; } - if (arq->hash.prev != head) { - list_del(&arq->hash); - list_add(&arq->hash, head); + if (&arq->hash != head->first) { + hlist_del(&arq->hash); + hlist_add_head(&arq->hash, head); } } static struct request *as_find_arq_hash(struct as_data *ad, sector_t offset) { - struct list_head *hash_list = &ad->hash[AS_HASH_FN(offset)]; - struct list_head *entry, *next = hash_list->next; + struct hlist_head *hash_list = &ad->hash[AS_HASH_FN(offset)]; + struct hlist_node *entry, *next; + struct as_rq *arq; - while ((entry = next) != hash_list) { - struct as_rq *arq = list_entry_hash(entry); + hlist_for_each_entry_safe(arq, entry, next, hash_list, hash) { struct request *__rq = arq->request; - next = entry->next; - - BUG_ON(!arq->on_hash); + BUG_ON(hlist_unhashed(&arq->hash)); if (!rq_mergeable(__rq)) { as_del_arq_hash(arq); @@ -1601,8 +1595,7 @@ static int as_set_request(request_queue_t *q, struct request *rq, arq->request = rq; arq->state = AS_RQ_PRESCHED; arq->io_context = NULL; - INIT_LIST_HEAD(&arq->hash); - arq->on_hash = 0; + INIT_HLIST_NODE(&arq->hash); INIT_LIST_HEAD(&arq->fifo); rq->elevator_private = arq; return 0; @@ -1662,7 +1655,7 @@ static void *as_init_queue(request_queue_t *q, elevator_t *e) ad->q = q; /* Identify what queue the data belongs to */ - ad->hash = kmalloc_node(sizeof(struct list_head)*AS_HASH_ENTRIES, + ad->hash = kmalloc_node(sizeof(struct hlist_head)*AS_HASH_ENTRIES, GFP_KERNEL, q->node); if (!ad->hash) { kfree(ad); @@ -1684,7 +1677,7 @@ static void *as_init_queue(request_queue_t *q, elevator_t *e) INIT_WORK(&ad->antic_work, as_work_handler, q); for (i = 0; i < AS_HASH_ENTRIES; i++) - INIT_LIST_HEAD(&ad->hash[i]); + INIT_HLIST_HEAD(&ad->hash[i]); INIT_LIST_HEAD(&ad->fifo_list[REQ_SYNC]); INIT_LIST_HEAD(&ad->fifo_list[REQ_ASYNC]); diff --git a/block/deadline-iosched.c b/block/deadline-iosched.c index c94de8e12fb..e5bccaaed56 100644 --- a/block/deadline-iosched.c +++ b/block/deadline-iosched.c @@ -30,8 +30,7 @@ static const int deadline_hash_shift = 5; #define DL_HASH_FN(sec) (hash_long(DL_HASH_BLOCK((sec)), deadline_hash_shift)) #define DL_HASH_ENTRIES (1 << deadline_hash_shift) #define rq_hash_key(rq) ((rq)->sector + (rq)->nr_sectors) -#define list_entry_hash(ptr) list_entry((ptr), struct deadline_rq, hash) -#define ON_HASH(drq) (drq)->on_hash +#define ON_HASH(drq) (!hlist_unhashed(&(drq)->hash)) struct deadline_data { /* @@ -48,7 +47,7 @@ struct deadline_data { * next in sort order. read, write or both are NULL */ struct deadline_rq *next_drq[2]; - struct list_head *hash; /* request hash */ + struct hlist_head *hash; /* request hash */ unsigned int batching; /* number of sequential requests made */ sector_t last_sector; /* head position */ unsigned int starved; /* times reads have starved writes */ @@ -79,8 +78,7 @@ struct deadline_rq { /* * request hash, key is the ending offset (for back merge lookup) */ - struct list_head hash; - char on_hash; + struct hlist_node hash; /* * expire fifo @@ -100,8 +98,7 @@ static kmem_cache_t *drq_pool; */ static inline void __deadline_del_drq_hash(struct deadline_rq *drq) { - drq->on_hash = 0; - list_del_init(&drq->hash); + hlist_del_init(&drq->hash); } static inline void deadline_del_drq_hash(struct deadline_rq *drq) @@ -117,8 +114,7 @@ deadline_add_drq_hash(struct deadline_data *dd, struct deadline_rq *drq) BUG_ON(ON_HASH(drq)); - drq->on_hash = 1; - list_add(&drq->hash, &dd->hash[DL_HASH_FN(rq_hash_key(rq))]); + hlist_add_head(&drq->hash, &dd->hash[DL_HASH_FN(rq_hash_key(rq))]); } /* @@ -128,26 +124,24 @@ static inline void deadline_hot_drq_hash(struct deadline_data *dd, struct deadline_rq *drq) { struct request *rq = drq->request; - struct list_head *head = &dd->hash[DL_HASH_FN(rq_hash_key(rq))]; + struct hlist_head *head = &dd->hash[DL_HASH_FN(rq_hash_key(rq))]; - if (ON_HASH(drq) && drq->hash.prev != head) { - list_del(&drq->hash); - list_add(&drq->hash, head); + if (ON_HASH(drq) && &drq->hash != head->first) { + hlist_del(&drq->hash); + hlist_add_head(&drq->hash, head); } } static struct request * deadline_find_drq_hash(struct deadline_data *dd, sector_t offset) { - struct list_head *hash_list = &dd->hash[DL_HASH_FN(offset)]; - struct list_head *entry, *next = hash_list->next; + struct hlist_head *hash_list = &dd->hash[DL_HASH_FN(offset)]; + struct hlist_node *entry, *next; + struct deadline_rq *drq; - while ((entry = next) != hash_list) { - struct deadline_rq *drq = list_entry_hash(entry); + hlist_for_each_entry_safe(drq, entry, next, hash_list, hash) { struct request *__rq = drq->request; - next = entry->next; - BUG_ON(!ON_HASH(drq)); if (!rq_mergeable(__rq)) { @@ -625,7 +619,7 @@ static void *deadline_init_queue(request_queue_t *q, elevator_t *e) return NULL; memset(dd, 0, sizeof(*dd)); - dd->hash = kmalloc_node(sizeof(struct list_head)*DL_HASH_ENTRIES, + dd->hash = kmalloc_node(sizeof(struct hlist_head)*DL_HASH_ENTRIES, GFP_KERNEL, q->node); if (!dd->hash) { kfree(dd); @@ -641,7 +635,7 @@ static void *deadline_init_queue(request_queue_t *q, elevator_t *e) } for (i = 0; i < DL_HASH_ENTRIES; i++) - INIT_LIST_HEAD(&dd->hash[i]); + INIT_HLIST_HEAD(&dd->hash[i]); INIT_LIST_HEAD(&dd->fifo_list[READ]); INIT_LIST_HEAD(&dd->fifo_list[WRITE]); @@ -677,8 +671,7 @@ deadline_set_request(request_queue_t *q, struct request *rq, struct bio *bio, RB_CLEAR(&drq->rb_node); drq->request = rq; - INIT_LIST_HEAD(&drq->hash); - drq->on_hash = 0; + INIT_HLIST_NODE(&drq->hash); INIT_LIST_HEAD(&drq->fifo); -- cgit v1.2.3 From a038e2536472b4dd932399b5277e65f188811de5 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Mon, 5 Jun 2006 12:09:01 +0200 Subject: [PATCH] blk_start_queue() must be called with irq disabled - add warning The queue lock can be taken from interrupts so it must always be taken with irq disabling primitives. Some primitives already verify this. blk_start_queue() is called under this lock, so interrupts must be disabled. Also document this requirement clearly in blk_init_queue(), where the queue spinlock is set. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Jens Axboe --- block/ll_rw_blk.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 465b54312c5..17c42ddd31d 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -1663,6 +1663,8 @@ static void blk_unplug_timeout(unsigned long data) **/ void blk_start_queue(request_queue_t *q) { + WARN_ON(!irqs_disabled()); + clear_bit(QUEUE_FLAG_STOPPED, &q->queue_flags); /* @@ -1878,7 +1880,8 @@ EXPORT_SYMBOL(blk_alloc_queue_node); * get dealt with eventually. * * The queue spin lock must be held while manipulating the requests on the - * request queue. + * request queue; this lock will be taken also from interrupt context, so irq + * disabling is needed for it. * * Function returns a pointer to the initialized request queue, or NULL if * it didn't succeed. -- cgit v1.2.3 From fda151d9feafc0e8418f23c716587c44394fcdbf Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 5 Jun 2006 12:09:50 +0200 Subject: [PATCH] blktrace_api.h: endian annotations Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: Jens Axboe --- include/linux/blktrace_api.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/linux/blktrace_api.h b/include/linux/blktrace_api.h index eb1a867ed24..a7e8cef73d1 100644 --- a/include/linux/blktrace_api.h +++ b/include/linux/blktrace_api.h @@ -90,9 +90,9 @@ struct blk_io_trace { * The remap event */ struct blk_io_trace_remap { - u32 device; + __be32 device; u32 __pad; - u64 sector; + __be64 sector; }; enum { @@ -224,7 +224,7 @@ static inline void blk_add_trace_pdu_int(struct request_queue *q, u32 what, struct bio *bio, unsigned int pdu) { struct blk_trace *bt = q->blk_trace; - u64 rpdu = cpu_to_be64(pdu); + __be64 rpdu = cpu_to_be64(pdu); if (likely(!bt)) return; -- cgit v1.2.3 From acf421755593f7d7bd9352d57eda796c6eb4fa43 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 12 Jun 2006 14:20:58 +0200 Subject: [PATCH] remove dead code from elevator switching We already drop the refcount in elevator_exit(), and as we're setting 'e' to NULL, we'll never take that branch anyway. Finally, as 'e' is a local var that isn't referenced afterwards, setting it to NULL is pointless. Signed-off-by: Dave Jones Signed-off-by: Jens Axboe --- block/elevator.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/block/elevator.c b/block/elevator.c index a0afdd317ce..d00b283f31d 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -850,12 +850,9 @@ fail_register: * one again (along with re-adding the sysfs dir) */ elevator_exit(e); - e = NULL; q->elevator = old_elevator; elv_register_queue(q); clear_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags); - if (e) - kobject_put(&e->kobj); return 0; } -- cgit v1.2.3 From 271f18f102c789f59644bb6c53a69da1df72b2f4 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 13 Jun 2006 08:08:38 +0200 Subject: [PATCH] cfq-iosched: Don't set the queue batching limits We cannot update them if the user changes nr_requests, so don't set it in the first place. The gains are pretty questionable as well. The batching loss has been shown to decrease throughput. Signed-off-by: Jens Axboe --- block/cfq-iosched.c | 48 +++--------------------------------------------- 1 file changed, 3 insertions(+), 45 deletions(-) diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index e2e6ad0a158..c88f161d3fb 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -123,8 +123,6 @@ struct cfq_data { */ struct hlist_head *crq_hash; - unsigned int max_queued; - mempool_t *crq_pool; int rq_in_driver; @@ -1910,7 +1908,6 @@ static inline int __cfq_may_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq, struct task_struct *task, int rw) { -#if 1 if ((cfq_cfqq_wait_request(cfqq) || cfq_cfqq_must_alloc(cfqq)) && !cfq_cfqq_must_alloc_slice(cfqq)) { cfq_mark_cfqq_must_alloc_slice(cfqq); @@ -1918,39 +1915,6 @@ __cfq_may_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq, } return ELV_MQUEUE_MAY; -#else - if (!cfqq || task->flags & PF_MEMALLOC) - return ELV_MQUEUE_MAY; - if (!cfqq->allocated[rw] || cfq_cfqq_must_alloc(cfqq)) { - if (cfq_cfqq_wait_request(cfqq)) - return ELV_MQUEUE_MUST; - - /* - * only allow 1 ELV_MQUEUE_MUST per slice, otherwise we - * can quickly flood the queue with writes from a single task - */ - if (rw == READ || !cfq_cfqq_must_alloc_slice(cfqq)) { - cfq_mark_cfqq_must_alloc_slice(cfqq); - return ELV_MQUEUE_MUST; - } - - return ELV_MQUEUE_MAY; - } - if (cfq_class_idle(cfqq)) - return ELV_MQUEUE_NO; - if (cfqq->allocated[rw] >= cfqd->max_queued) { - struct io_context *ioc = get_io_context(GFP_ATOMIC); - int ret = ELV_MQUEUE_NO; - - if (ioc && ioc->nr_batch_requests) - ret = ELV_MQUEUE_MAY; - - put_io_context(ioc); - return ret; - } - - return ELV_MQUEUE_MAY; -#endif } static int cfq_may_queue(request_queue_t *q, int rw, struct bio *bio) @@ -1979,16 +1943,13 @@ static int cfq_may_queue(request_queue_t *q, int rw, struct bio *bio) static void cfq_check_waiters(request_queue_t *q, struct cfq_queue *cfqq) { struct cfq_data *cfqd = q->elevator->elevator_data; - struct request_list *rl = &q->rq; - if (cfqq->allocated[READ] <= cfqd->max_queued || cfqd->rq_starved) { + if (unlikely(cfqd->rq_starved)) { + struct request_list *rl = &q->rq; + smp_mb(); if (waitqueue_active(&rl->wait[READ])) wake_up(&rl->wait[READ]); - } - - if (cfqq->allocated[WRITE] <= cfqd->max_queued || cfqd->rq_starved) { - smp_mb(); if (waitqueue_active(&rl->wait[WRITE])) wake_up(&rl->wait[WRITE]); } @@ -2278,9 +2239,6 @@ static void *cfq_init_queue(request_queue_t *q, elevator_t *e) cfqd->queue = q; - cfqd->max_queued = q->nr_requests / 4; - q->nr_batching = cfq_queued; - init_timer(&cfqd->idle_slice_timer); cfqd->idle_slice_timer.function = cfq_idle_slice_timer; cfqd->idle_slice_timer.data = (unsigned long) cfqd; -- cgit v1.2.3 From b31dc66a54ad986b6b73bdc49c8efc17cbad1833 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 13 Jun 2006 08:26:10 +0200 Subject: [PATCH] Kill PF_SYNCWRITE flag A process flag to indicate whether we are doing sync io is incredibly ugly. It also causes performance problems when one does a lot of async io and then proceeds to sync it. Part of the io will go out as async, and the other part as sync. This causes a disconnect between the previously submitted io and the synced io. For io schedulers such as CFQ, this will cause us lost merges and suboptimal behaviour in scheduling. Remove PF_SYNCWRITE completely from the fsync/msync paths, and let the O_DIRECT path just directly indicate that the writes are sync by using WRITE_SYNC instead. Signed-off-by: Jens Axboe --- block/as-iosched.c | 2 +- block/cfq-iosched.c | 4 +--- block/ll_rw_blk.c | 3 +++ drivers/usb/gadget/file_storage.c | 2 -- fs/buffer.c | 2 -- fs/direct-io.c | 18 ++++++++---------- fs/fs-writeback.c | 2 -- include/linux/blkdev.h | 2 ++ include/linux/sched.h | 11 +++++------ mm/msync.c | 3 --- 10 files changed, 20 insertions(+), 29 deletions(-) diff --git a/block/as-iosched.c b/block/as-iosched.c index 9b13d72ffef..56c99fa037d 100644 --- a/block/as-iosched.c +++ b/block/as-iosched.c @@ -1339,7 +1339,7 @@ static void as_add_request(request_queue_t *q, struct request *rq) arq->state = AS_RQ_NEW; if (rq_data_dir(arq->request) == READ - || current->flags&PF_SYNCWRITE) + || (arq->request->flags & REQ_RW_SYNC)) arq->is_sync = 1; else arq->is_sync = 0; diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index c88f161d3fb..4c4e9cc3ae2 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -277,8 +277,6 @@ static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *, unsigned int, unsi static void cfq_dispatch_insert(request_queue_t *, struct cfq_rq *); static struct cfq_queue *cfq_get_queue(struct cfq_data *cfqd, unsigned int key, struct task_struct *tsk, gfp_t gfp_mask); -#define process_sync(tsk) ((tsk)->flags & PF_SYNCWRITE) - /* * lots of deadline iosched dupes, can be abstracted later... */ @@ -334,7 +332,7 @@ static int cfq_queue_empty(request_queue_t *q) static inline pid_t cfq_queue_pid(struct task_struct *task, int rw) { - if (rw == READ || process_sync(task)) + if (rw == READ || rw == WRITE_SYNC) return task->pid; return CFQ_KEY_ASYNC; diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 17c42ddd31d..2270bb45138 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -2827,6 +2827,9 @@ static void init_request_from_bio(struct request *req, struct bio *bio) if (unlikely(bio_barrier(bio))) req->flags |= (REQ_HARDBARRIER | REQ_NOMERGE); + if (bio_sync(bio)) + req->flags |= REQ_RW_SYNC; + req->errors = 0; req->hard_sector = req->sector = bio->bi_sector; req->hard_nr_sectors = req->nr_sectors = bio_sectors(bio); diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index 6f887478b14..a43dc908ac5 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -1906,7 +1906,6 @@ static int fsync_sub(struct lun *curlun) inode = filp->f_dentry->d_inode; mutex_lock(&inode->i_mutex); - current->flags |= PF_SYNCWRITE; rc = filemap_fdatawrite(inode->i_mapping); err = filp->f_op->fsync(filp, filp->f_dentry, 1); if (!rc) @@ -1914,7 +1913,6 @@ static int fsync_sub(struct lun *curlun) err = filemap_fdatawait(inode->i_mapping); if (!rc) rc = err; - current->flags &= ~PF_SYNCWRITE; mutex_unlock(&inode->i_mutex); VLDBG(curlun, "fdatasync -> %d\n", rc); return rc; diff --git a/fs/buffer.c b/fs/buffer.c index 23f1f3a6807..373bb6292bd 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -331,7 +331,6 @@ long do_fsync(struct file *file, int datasync) goto out; } - current->flags |= PF_SYNCWRITE; ret = filemap_fdatawrite(mapping); /* @@ -346,7 +345,6 @@ long do_fsync(struct file *file, int datasync) err = filemap_fdatawait(mapping); if (!ret) ret = err; - current->flags &= ~PF_SYNCWRITE; out: return ret; } diff --git a/fs/direct-io.c b/fs/direct-io.c index b05d1b21877..538fb0418fb 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c @@ -162,7 +162,7 @@ static int dio_refill_pages(struct dio *dio) NULL); /* vmas */ up_read(¤t->mm->mmap_sem); - if (ret < 0 && dio->blocks_available && (dio->rw == WRITE)) { + if (ret < 0 && dio->blocks_available && (dio->rw & WRITE)) { struct page *page = ZERO_PAGE(dio->curr_user_address); /* * A memory fault, but the filesystem has some outstanding @@ -535,7 +535,7 @@ static int get_more_blocks(struct dio *dio) map_bh->b_state = 0; map_bh->b_size = fs_count << dio->inode->i_blkbits; - create = dio->rw == WRITE; + create = dio->rw & WRITE; if (dio->lock_type == DIO_LOCKING) { if (dio->block_in_file < (i_size_read(dio->inode) >> dio->blkbits)) @@ -867,7 +867,7 @@ do_holes: loff_t i_size_aligned; /* AKPM: eargh, -ENOTBLK is a hack */ - if (dio->rw == WRITE) { + if (dio->rw & WRITE) { page_cache_release(page); return -ENOTBLK; } @@ -1045,7 +1045,7 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode, } } /* end iovec loop */ - if (ret == -ENOTBLK && rw == WRITE) { + if (ret == -ENOTBLK && (rw & WRITE)) { /* * The remaining part of the request will be * be handled by buffered I/O when we return @@ -1089,7 +1089,7 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode, if (dio->is_async) { int should_wait = 0; - if (dio->result < dio->size && rw == WRITE) { + if (dio->result < dio->size && (rw & WRITE)) { dio->waiter = current; should_wait = 1; } @@ -1142,7 +1142,7 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode, ret = transferred; /* We could have also come here on an AIO file extend */ - if (!is_sync_kiocb(iocb) && rw == WRITE && + if (!is_sync_kiocb(iocb) && (rw & WRITE) && ret >= 0 && dio->result == dio->size) /* * For AIO writes where we have completed the @@ -1194,7 +1194,7 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, int acquire_i_mutex = 0; if (rw & WRITE) - current->flags |= PF_SYNCWRITE; + rw = WRITE_SYNC; if (bdev) bdev_blkbits = blksize_bits(bdev_hardsect_size(bdev)); @@ -1270,7 +1270,7 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, * even for AIO, we need to wait for i/o to complete before * returning in this case. */ - dio->is_async = !is_sync_kiocb(iocb) && !((rw == WRITE) && + dio->is_async = !is_sync_kiocb(iocb) && !((rw & WRITE) && (end > i_size_read(inode))); retval = direct_io_worker(rw, iocb, inode, iov, offset, @@ -1284,8 +1284,6 @@ out: mutex_unlock(&inode->i_mutex); else if (acquire_i_mutex) mutex_lock(&inode->i_mutex); - if (rw & WRITE) - current->flags &= ~PF_SYNCWRITE; return retval; } EXPORT_SYMBOL(__blockdev_direct_IO); diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 6db95cf3aaa..031b27a4bc9 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -623,7 +623,6 @@ int generic_osync_inode(struct inode *inode, struct address_space *mapping, int int need_write_inode_now = 0; int err2; - current->flags |= PF_SYNCWRITE; if (what & OSYNC_DATA) err = filemap_fdatawrite(mapping); if (what & (OSYNC_METADATA|OSYNC_DATA)) { @@ -636,7 +635,6 @@ int generic_osync_inode(struct inode *inode, struct address_space *mapping, int if (!err) err = err2; } - current->flags &= ~PF_SYNCWRITE; spin_lock(&inode_lock); if ((inode->i_state & I_DIRTY) && diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 3457e7b9736..482a21d6762 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -241,6 +241,7 @@ enum rq_flag_bits { __REQ_PM_RESUME, /* resume request */ __REQ_PM_SHUTDOWN, /* shutdown request */ __REQ_ORDERED_COLOR, /* is before or after barrier */ + __REQ_RW_SYNC, /* request is sync (O_DIRECT) */ __REQ_NR_BITS, /* stops here */ }; @@ -270,6 +271,7 @@ enum rq_flag_bits { #define REQ_PM_RESUME (1 << __REQ_PM_RESUME) #define REQ_PM_SHUTDOWN (1 << __REQ_PM_SHUTDOWN) #define REQ_ORDERED_COLOR (1 << __REQ_ORDERED_COLOR) +#define REQ_RW_SYNC (1 << __REQ_RW_SYNC) /* * State information carried for REQ_PM_SUSPEND and REQ_PM_RESUME diff --git a/include/linux/sched.h b/include/linux/sched.h index a9d23c7d1b2..38b4791e6a5 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -941,12 +941,11 @@ static inline void put_task_struct(struct task_struct *t) #define PF_KSWAPD 0x00040000 /* I am kswapd */ #define PF_SWAPOFF 0x00080000 /* I am in swapoff */ #define PF_LESS_THROTTLE 0x00100000 /* Throttle me less: I clean memory */ -#define PF_SYNCWRITE 0x00200000 /* I am doing a sync write */ -#define PF_BORROWED_MM 0x00400000 /* I am a kthread doing use_mm */ -#define PF_RANDOMIZE 0x00800000 /* randomize virtual address space */ -#define PF_SWAPWRITE 0x01000000 /* Allowed to write to swap */ -#define PF_SPREAD_PAGE 0x04000000 /* Spread page cache over cpuset */ -#define PF_SPREAD_SLAB 0x08000000 /* Spread some slab caches over cpuset */ +#define PF_BORROWED_MM 0x00200000 /* I am a kthread doing use_mm */ +#define PF_RANDOMIZE 0x00400000 /* randomize virtual address space */ +#define PF_SWAPWRITE 0x00800000 /* Allowed to write to swap */ +#define PF_SPREAD_PAGE 0x01000000 /* Spread page cache over cpuset */ +#define PF_SPREAD_SLAB 0x02000000 /* Spread some slab caches over cpuset */ #define PF_MEMPOLICY 0x10000000 /* Non-default NUMA mempolicy */ /* diff --git a/mm/msync.c b/mm/msync.c index bc6c9537636..d083544df21 100644 --- a/mm/msync.c +++ b/mm/msync.c @@ -170,8 +170,6 @@ asmlinkage long sys_msync(unsigned long start, size_t len, int flags) * just ignore them, but return -ENOMEM at the end. */ down_read(¤t->mm->mmap_sem); - if (flags & MS_SYNC) - current->flags |= PF_SYNCWRITE; vma = find_vma(current->mm, start); if (!vma) { error = -ENOMEM; @@ -228,7 +226,6 @@ asmlinkage long sys_msync(unsigned long start, size_t len, int flags) } } while (vma && !done); out_unlock: - current->flags &= ~PF_SYNCWRITE; up_read(¤t->mm->mmap_sem); out: return error; -- cgit v1.2.3 From ad3caddaa1708e506f20b8e25a4a8ae586fc7d5b Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 13 Jun 2006 08:46:57 +0200 Subject: [PATCH] Get rid of struct request request_pm_state member The IDE power management can just use the ->end_io_data member to store it's data. Signed-off-by: Jens Axboe --- drivers/ide/ide-io.c | 91 ++++++++++++++++++++++++++++---------------------- drivers/ide/ide.c | 4 +-- include/linux/blkdev.h | 5 --- 3 files changed, 54 insertions(+), 46 deletions(-) diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index c01615dec20..4f2f138de2c 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -142,38 +142,41 @@ enum { static void ide_complete_power_step(ide_drive_t *drive, struct request *rq, u8 stat, u8 error) { + struct request_pm_state *pm = rq->end_io_data; + if (drive->media != ide_disk) return; - switch (rq->pm->pm_step) { + switch (pm->pm_step) { case ide_pm_flush_cache: /* Suspend step 1 (flush cache) complete */ - if (rq->pm->pm_state == PM_EVENT_FREEZE) - rq->pm->pm_step = ide_pm_state_completed; + if (pm->pm_state == PM_EVENT_FREEZE) + pm->pm_step = ide_pm_state_completed; else - rq->pm->pm_step = idedisk_pm_standby; + pm->pm_step = idedisk_pm_standby; break; case idedisk_pm_standby: /* Suspend step 2 (standby) complete */ - rq->pm->pm_step = ide_pm_state_completed; + pm->pm_step = ide_pm_state_completed; break; case idedisk_pm_idle: /* Resume step 1 (idle) complete */ - rq->pm->pm_step = ide_pm_restore_dma; + pm->pm_step = ide_pm_restore_dma; break; } } static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq) { + struct request_pm_state *pm = rq->end_io_data; ide_task_t *args = rq->special; memset(args, 0, sizeof(*args)); if (drive->media != ide_disk) { /* skip idedisk_pm_idle for ATAPI devices */ - if (rq->pm->pm_step == idedisk_pm_idle) - rq->pm->pm_step = ide_pm_restore_dma; + if (pm->pm_step == idedisk_pm_idle) + pm->pm_step = ide_pm_restore_dma; } - switch (rq->pm->pm_step) { + switch (pm->pm_step) { case ide_pm_flush_cache: /* Suspend step 1 (flush cache) */ if (drive->media != ide_disk) break; @@ -215,7 +218,7 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request * drive->hwif->ide_dma_check(drive); break; } - rq->pm->pm_step = ide_pm_state_completed; + pm->pm_step = ide_pm_state_completed; return ide_stopped; } @@ -362,12 +365,13 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err) } } } else if (blk_pm_request(rq)) { + struct request_pm_state *pm = rq->end_io_data; #ifdef DEBUG_PM printk("%s: complete_power_step(step: %d, stat: %x, err: %x)\n", drive->name, rq->pm->pm_step, stat, err); #endif ide_complete_power_step(drive, rq, stat, err); - if (rq->pm->pm_step == ide_pm_state_completed) + if (pm->pm_step == ide_pm_state_completed) ide_complete_pm_request(drive, rq); return; } @@ -871,6 +875,39 @@ done: return ide_stopped; } +static void ide_check_pm_state(ide_drive_t *drive, struct request *rq) +{ + struct request_pm_state *pm = rq->end_io_data; + + if (blk_pm_suspend_request(rq) && + pm->pm_step == ide_pm_state_start_suspend) + /* Mark drive blocked when starting the suspend sequence. */ + drive->blocked = 1; + else if (blk_pm_resume_request(rq) && + pm->pm_step == ide_pm_state_start_resume) { + /* + * The first thing we do on wakeup is to wait for BSY bit to + * go away (with a looong timeout) as a drive on this hwif may + * just be POSTing itself. + * We do that before even selecting as the "other" device on + * the bus may be broken enough to walk on our toes at this + * point. + */ + int rc; +#ifdef DEBUG_PM + printk("%s: Wakeup request inited, waiting for !BSY...\n", drive->name); +#endif + rc = ide_wait_not_busy(HWIF(drive), 35000); + if (rc) + printk(KERN_WARNING "%s: bus not ready on wakeup\n", drive->name); + SELECT_DRIVE(drive); + HWIF(drive)->OUTB(8, HWIF(drive)->io_ports[IDE_CONTROL_OFFSET]); + rc = ide_wait_not_busy(HWIF(drive), 10000); + if (rc) + printk(KERN_WARNING "%s: drive not ready on wakeup\n", drive->name); + } +} + /** * start_request - start of I/O and command issuing for IDE * @@ -909,33 +946,8 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) if (block == 0 && drive->remap_0_to_1 == 1) block = 1; /* redirect MBR access to EZ-Drive partn table */ - if (blk_pm_suspend_request(rq) && - rq->pm->pm_step == ide_pm_state_start_suspend) - /* Mark drive blocked when starting the suspend sequence. */ - drive->blocked = 1; - else if (blk_pm_resume_request(rq) && - rq->pm->pm_step == ide_pm_state_start_resume) { - /* - * The first thing we do on wakeup is to wait for BSY bit to - * go away (with a looong timeout) as a drive on this hwif may - * just be POSTing itself. - * We do that before even selecting as the "other" device on - * the bus may be broken enough to walk on our toes at this - * point. - */ - int rc; -#ifdef DEBUG_PM - printk("%s: Wakeup request inited, waiting for !BSY...\n", drive->name); -#endif - rc = ide_wait_not_busy(HWIF(drive), 35000); - if (rc) - printk(KERN_WARNING "%s: bus not ready on wakeup\n", drive->name); - SELECT_DRIVE(drive); - HWIF(drive)->OUTB(8, HWIF(drive)->io_ports[IDE_CONTROL_OFFSET]); - rc = ide_wait_not_busy(HWIF(drive), 10000); - if (rc) - printk(KERN_WARNING "%s: drive not ready on wakeup\n", drive->name); - } + if (blk_pm_request(rq)) + ide_check_pm_state(drive, rq); SELECT_DRIVE(drive); if (ide_wait_stat(&startstop, drive, drive->ready_stat, BUSY_STAT|DRQ_STAT, WAIT_READY)) { @@ -950,13 +962,14 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) else if (rq->flags & REQ_DRIVE_TASKFILE) return execute_drive_cmd(drive, rq); else if (blk_pm_request(rq)) { + struct request_pm_state *pm = rq->end_io_data; #ifdef DEBUG_PM printk("%s: start_power_step(step: %d)\n", drive->name, rq->pm->pm_step); #endif startstop = ide_start_power_step(drive, rq); if (startstop == ide_stopped && - rq->pm->pm_step == ide_pm_state_completed) + pm->pm_step == ide_pm_state_completed) ide_complete_pm_request(drive, rq); return startstop; } diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 9799aed772e..59fe358048b 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -1226,7 +1226,7 @@ static int generic_ide_suspend(struct device *dev, pm_message_t state) memset(&args, 0, sizeof(args)); rq.flags = REQ_PM_SUSPEND; rq.special = &args; - rq.pm = &rqpm; + rq.end_io_data = &rqpm; rqpm.pm_step = ide_pm_state_start_suspend; rqpm.pm_state = state.event; @@ -1245,7 +1245,7 @@ static int generic_ide_resume(struct device *dev) memset(&args, 0, sizeof(args)); rq.flags = REQ_PM_RESUME; rq.special = &args; - rq.pm = &rqpm; + rq.end_io_data = &rqpm; rqpm.pm_step = ide_pm_state_start_resume; rqpm.pm_state = PM_EVENT_ON; diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 482a21d6762..371c0ce5f63 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -195,11 +195,6 @@ struct request { unsigned int timeout; int retries; - /* - * For Power Management requests - */ - struct request_pm_state *pm; - /* * completion callback. end_io_data should be folded in with waiting */ -- cgit v1.2.3 From 8f34ee75decb80007ba77bba5a7384eadff4866d Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 13 Jun 2006 09:02:34 +0200 Subject: [PATCH] Rearrange a few struct request members This saves 8 bytes of data in 64-bit archs. Signed-off-by: Jens Axboe --- include/linux/blkdev.h | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 371c0ce5f63..aafe82788b4 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -151,11 +151,9 @@ struct request { void *elevator_private; void *completion_data; - unsigned short ioprio; - int rq_status; /* should split this into a few status bits */ - struct gendisk *rq_disk; int errors; + struct gendisk *rq_disk; unsigned long start_time; /* Number of scatter-gather DMA addr+len pairs after @@ -170,8 +168,9 @@ struct request { */ unsigned short nr_hw_segments; + unsigned short ioprio; + int tag; - char *buffer; int ref_count; request_queue_t *q; @@ -179,6 +178,7 @@ struct request { struct completion *waiting; void *special; + char *buffer; /* * when request is used as a packet command carrier @@ -187,9 +187,8 @@ struct request { unsigned char cmd[BLK_MAX_CDB]; unsigned int data_len; - void *data; - unsigned int sense_len; + void *data; void *sense; unsigned int timeout; -- cgit v1.2.3 From b17fd9bceb99610f6dc7998c9a4ed6b71520be2b Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 19 Jun 2006 10:06:48 +0200 Subject: [PATCH] Make CFQ the default IO scheduler Signed-off-by: Jens Axboe --- block/Kconfig.iosched | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/Kconfig.iosched b/block/Kconfig.iosched index f3b7753aac9..48d090e266f 100644 --- a/block/Kconfig.iosched +++ b/block/Kconfig.iosched @@ -40,7 +40,7 @@ config IOSCHED_CFQ choice prompt "Default I/O scheduler" - default DEFAULT_AS + default DEFAULT_CFQ help Select the I/O scheduler which will be used by default for all block devices. -- cgit v1.2.3 From 35e6077cb16f93517ba5a51ba849b186d2474d60 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 14 Jun 2006 09:10:45 +0200 Subject: [PATCH] cfq-iosched: correctly set ioprio on both targets Patch originally from Vasily Tarasov If you set io-priority of process 1 using sys_ioprio_set system call by another process 2 (like ionice do), then cfq_init_prio_data() function sets priority of process 2 (current) on queue of process 1 and clears the flag, that designates change of ioprio. So the process 1 will work like with priority of process 2. I propose not to call cfq_init_prio_data() on io-priority change, but only mark queue as queue with changed prority. Every time when new request comes cfq-scheduler checks for this flag and atomaticaly changes priority of queue to new value. Signed-off-by: Jens Axboe --- block/cfq-iosched.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 4c4e9cc3ae2..84b75f88c27 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -1388,10 +1388,9 @@ static inline void changed_ioprio(struct cfq_io_context *cic) } } cfqq = cic->cfqq[SYNC]; - if (cfqq) { + if (cfqq) cfq_mark_cfqq_prio_changed(cfqq); - cfq_init_prio_data(cfqq); - } + spin_unlock(cfqd->queue->queue_lock); } } -- cgit v1.2.3 From caaa5f9f0a75d1dc5e812e69afdbb8720e077fd3 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 16 Jun 2006 11:23:00 +0200 Subject: [PATCH] cfq-iosched: many performance fixes This is a collection of patches that greatly improve CFQ performance in some circumstances. - Change the idling logic to only kick in after a request is done and we are deciding what to do. Before the idling included the request service time, so it was hard to adjust. Now it's true think/idle time. - Take advantage of TCQ/NCQ/queueing for seeky sync workloads, but keep it in control for sync and sequential (or close to) workloads. - Expire queues immediately and move on to other busy queues, if we are not going to idle after the current one finishes. - Don't rearm idle timer if there are no busy queues. Just leave the system idle. Signed-off-by: Jens Axboe --- block/cfq-iosched.c | 116 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 76 insertions(+), 40 deletions(-) diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 84b75f88c27..13c4793fdf5 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -26,7 +26,7 @@ static const int cfq_back_penalty = 2; /* penalty of a backwards seek */ static const int cfq_slice_sync = HZ / 10; static int cfq_slice_async = HZ / 25; static const int cfq_slice_async_rq = 2; -static int cfq_slice_idle = HZ / 70; +static int cfq_slice_idle = HZ / 125; #define CFQ_IDLE_GRACE (HZ / 10) #define CFQ_SLICE_SCALE (5) @@ -906,6 +906,8 @@ static struct cfq_queue *cfq_set_active_queue(struct cfq_data *cfqd) return cfqq; } +#define CIC_SEEKY(cic) ((cic)->seek_mean > (128 * 1024)) + static int cfq_arm_slice_timer(struct cfq_data *cfqd, struct cfq_queue *cfqq) { @@ -939,7 +941,7 @@ static int cfq_arm_slice_timer(struct cfq_data *cfqd, struct cfq_queue *cfqq) * fair distribution of slice time for a process doing back-to-back * seeks. so allow a little bit of time for him to submit a new rq */ - if (sample_valid(cic->seek_samples) && cic->seek_mean > 131072) + if (sample_valid(cic->seek_samples) && CIC_SEEKY(cic)) sl = 2; mod_timer(&cfqd->idle_slice_timer, jiffies + sl); @@ -1038,8 +1040,10 @@ static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd) */ if (!RB_EMPTY(&cfqq->sort_list)) goto keep_queue; - else if (cfq_cfqq_class_sync(cfqq) && - time_before(now, cfqq->slice_end)) { + else if (cfq_cfqq_dispatched(cfqq)) { + cfqq = NULL; + goto keep_queue; + } else if (cfq_cfqq_class_sync(cfqq)) { if (cfq_arm_slice_timer(cfqd, cfqq)) return NULL; } @@ -1088,8 +1092,7 @@ __cfq_dispatch_requests(struct cfq_data *cfqd, struct cfq_queue *cfqq, } while (dispatched < max_dispatch); /* - * if slice end isn't set yet, set it. if at least one request was - * sync, use the sync time slice value + * if slice end isn't set yet, set it. */ if (!cfqq->slice_end) cfq_set_prio_slice(cfqd, cfqq); @@ -1100,7 +1103,8 @@ __cfq_dispatch_requests(struct cfq_data *cfqd, struct cfq_queue *cfqq, */ if ((!cfq_cfqq_sync(cfqq) && cfqd->dispatch_slice >= cfq_prio_to_maxrq(cfqd, cfqq)) || - cfq_class_idle(cfqq)) + cfq_class_idle(cfqq) || + !cfq_cfqq_idle_window(cfqq)) cfq_slice_expired(cfqd, 0); return dispatched; @@ -1109,10 +1113,11 @@ __cfq_dispatch_requests(struct cfq_data *cfqd, struct cfq_queue *cfqq, static int cfq_forced_dispatch_cfqqs(struct list_head *list) { - int dispatched = 0; struct cfq_queue *cfqq, *next; struct cfq_rq *crq; + int dispatched; + dispatched = 0; list_for_each_entry_safe(cfqq, next, list, cfq_list) { while ((crq = cfqq->next_crq)) { cfq_dispatch_insert(cfqq->cfqd->queue, crq); @@ -1120,6 +1125,7 @@ cfq_forced_dispatch_cfqqs(struct list_head *list) } BUG_ON(!list_empty(&cfqq->fifo)); } + return dispatched; } @@ -1146,7 +1152,8 @@ static int cfq_dispatch_requests(request_queue_t *q, int force) { struct cfq_data *cfqd = q->elevator->elevator_data; - struct cfq_queue *cfqq; + struct cfq_queue *cfqq, *prev_cfqq; + int dispatched; if (!cfqd->busy_queues) return 0; @@ -1154,10 +1161,17 @@ cfq_dispatch_requests(request_queue_t *q, int force) if (unlikely(force)) return cfq_forced_dispatch(cfqd); - cfqq = cfq_select_queue(cfqd); - if (cfqq) { + dispatched = 0; + prev_cfqq = NULL; + while ((cfqq = cfq_select_queue(cfqd)) != NULL) { int max_dispatch; + /* + * Don't repeat dispatch from the previous queue. + */ + if (prev_cfqq == cfqq) + break; + cfq_clear_cfqq_must_dispatch(cfqq); cfq_clear_cfqq_wait_request(cfqq); del_timer(&cfqd->idle_slice_timer); @@ -1166,10 +1180,19 @@ cfq_dispatch_requests(request_queue_t *q, int force) if (cfq_class_idle(cfqq)) max_dispatch = 1; - return __cfq_dispatch_requests(cfqd, cfqq, max_dispatch); + dispatched += __cfq_dispatch_requests(cfqd, cfqq, max_dispatch); + + /* + * If the dispatch cfqq has idling enabled and is still + * the active queue, break out. + */ + if (cfq_cfqq_idle_window(cfqq) && cfqd->active_queue) + break; + + prev_cfqq = cfqq; } - return 0; + return dispatched; } /* @@ -1375,24 +1398,28 @@ static inline void changed_ioprio(struct cfq_io_context *cic) { struct cfq_data *cfqd = cic->key; struct cfq_queue *cfqq; - if (cfqd) { - spin_lock(cfqd->queue->queue_lock); - cfqq = cic->cfqq[ASYNC]; - if (cfqq) { - struct cfq_queue *new_cfqq; - new_cfqq = cfq_get_queue(cfqd, CFQ_KEY_ASYNC, - cic->ioc->task, GFP_ATOMIC); - if (new_cfqq) { - cic->cfqq[ASYNC] = new_cfqq; - cfq_put_queue(cfqq); - } - } - cfqq = cic->cfqq[SYNC]; - if (cfqq) - cfq_mark_cfqq_prio_changed(cfqq); - spin_unlock(cfqd->queue->queue_lock); + if (unlikely(!cfqd)) + return; + + spin_lock(cfqd->queue->queue_lock); + + cfqq = cic->cfqq[ASYNC]; + if (cfqq) { + struct cfq_queue *new_cfqq; + new_cfqq = cfq_get_queue(cfqd, CFQ_KEY_ASYNC, cic->ioc->task, + GFP_ATOMIC); + if (new_cfqq) { + cic->cfqq[ASYNC] = new_cfqq; + cfq_put_queue(cfqq); + } } + + cfqq = cic->cfqq[SYNC]; + if (cfqq) + cfq_mark_cfqq_prio_changed(cfqq); + + spin_unlock(cfqd->queue->queue_lock); } /* @@ -1461,8 +1488,7 @@ retry: * set ->slice_left to allow preemption for a new process */ cfqq->slice_left = 2 * cfqd->cfq_slice_idle; - if (!cfqd->hw_tag) - cfq_mark_cfqq_idle_window(cfqq); + cfq_mark_cfqq_idle_window(cfqq); cfq_mark_cfqq_prio_changed(cfqq); cfq_init_prio_data(cfqq); } @@ -1653,7 +1679,8 @@ cfq_update_idle_window(struct cfq_data *cfqd, struct cfq_queue *cfqq, { int enable_idle = cfq_cfqq_idle_window(cfqq); - if (!cic->ioc->task || !cfqd->cfq_slice_idle || cfqd->hw_tag) + if (!cic->ioc->task || !cfqd->cfq_slice_idle || + (cfqd->hw_tag && CIC_SEEKY(cic))) enable_idle = 0; else if (sample_valid(cic->ttime_samples)) { if (cic->ttime_mean > cfqd->cfq_slice_idle) @@ -1683,7 +1710,7 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq, return 0; if (!cfqq) - return 1; + return 0; if (cfq_class_idle(cfqq)) return 1; @@ -1715,7 +1742,7 @@ static void cfq_preempt_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq) cfqq->slice_left = cfq_prio_to_slice(cfqd, cfqq) / 2; cfqq->slice_end = cfqq->slice_left + jiffies; - __cfq_slice_expired(cfqd, cfqq, 1); + cfq_slice_expired(cfqd, 1); __cfq_set_active_queue(cfqd, cfqq); } @@ -1834,11 +1861,23 @@ static void cfq_completed_request(request_queue_t *q, struct request *rq) cfqq->service_last = now; cfq_resort_rr_list(cfqq, 0); } - cfq_schedule_dispatch(cfqd); } - if (cfq_crq_is_sync(crq)) + if (sync) crq->io_context->last_end_request = now; + + /* + * If this is the active queue, check if it needs to be expired, + * or if we want to idle in case it has no pending requests. + */ + if (cfqd->active_queue == cfqq) { + if (time_after(now, cfqq->slice_end)) + cfq_slice_expired(cfqd, 0); + else if (sync && RB_EMPTY(&cfqq->sort_list)) { + if (!cfq_arm_slice_timer(cfqd, cfqq)) + cfq_schedule_dispatch(cfqd); + } + } } static struct request * @@ -2106,11 +2145,8 @@ static void cfq_idle_slice_timer(unsigned long data) * only expire and reinvoke request handler, if there are * other queues with pending requests */ - if (!cfqd->busy_queues) { - cfqd->idle_slice_timer.expires = min(now + cfqd->cfq_slice_idle, cfqq->slice_end); - add_timer(&cfqd->idle_slice_timer); + if (!cfqd->busy_queues) goto out_cont; - } /* * not expired and it has a request pending, let it dispatch -- cgit v1.2.3 From fd61af0384014ca29428ace7c17a978b755aeddd Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 16 Jun 2006 15:35:39 +0200 Subject: [PATCH] cfq-iosched: rq update fixes - Remember to set ->last_sector so that the cfq_choose_req() logic works correctly. - Remove redundant call to cfq_choose_req() Signed-off-by: Jens Axboe --- block/cfq-iosched.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 13c4793fdf5..940364edf2b 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -952,11 +952,15 @@ static void cfq_dispatch_insert(request_queue_t *q, struct cfq_rq *crq) { struct cfq_data *cfqd = q->elevator->elevator_data; struct cfq_queue *cfqq = crq->cfq_queue; + struct request *rq; cfqq->next_crq = cfq_find_next_crq(cfqd, cfqq, crq); cfq_remove_request(crq->request); cfqq->on_dispatch[cfq_crq_is_sync(crq)]++; elv_dispatch_sort(q, crq->request); + + rq = list_entry(q->queue_head.prev, struct request, queuelist); + cfqd->last_sector = rq->sector + rq->nr_sectors; } /* @@ -1767,11 +1771,7 @@ static void cfq_crq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq, struct cfq_rq *crq) { - struct cfq_io_context *cic; - - cfqq->next_crq = cfq_choose_req(cfqd, cfqq->next_crq, crq); - - cic = crq->io_context; + struct cfq_io_context *cic = crq->io_context; /* * we never wait for an async request and we don't allow preemption -- cgit v1.2.3 From 9e94cd4fd1812bab45237f998b3c6fa1b24023fd Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 20 Jun 2006 15:01:12 +0200 Subject: [PATCH] splice: retrieve mapping after locking the page Otherwise we could be racing with truncate/mapping removal. Problem found/fixed by Nick Piggin , logic rewritten by me. Signed-off-by: Jens Axboe --- fs/splice.c | 46 +++++++++++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/fs/splice.c b/fs/splice.c index a285fd746dc..05fd2787be9 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -55,31 +55,43 @@ static int page_cache_pipe_buf_steal(struct pipe_inode_info *pipe, struct pipe_buffer *buf) { struct page *page = buf->page; - struct address_space *mapping = page_mapping(page); + struct address_space *mapping; lock_page(page); - WARN_ON(!PageUptodate(page)); + mapping = page_mapping(page); + if (mapping) { + WARN_ON(!PageUptodate(page)); - /* - * At least for ext2 with nobh option, we need to wait on writeback - * completing on this page, since we'll remove it from the pagecache. - * Otherwise truncate wont wait on the page, allowing the disk - * blocks to be reused by someone else before we actually wrote our - * data to them. fs corruption ensues. - */ - wait_on_page_writeback(page); + /* + * At least for ext2 with nobh option, we need to wait on + * writeback completing on this page, since we'll remove it + * from the pagecache. Otherwise truncate wont wait on the + * page, allowing the disk blocks to be reused by someone else + * before we actually wrote our data to them. fs corruption + * ensues. + */ + wait_on_page_writeback(page); - if (PagePrivate(page)) - try_to_release_page(page, mapping_gfp_mask(mapping)); + if (PagePrivate(page)) + try_to_release_page(page, mapping_gfp_mask(mapping)); - if (!remove_mapping(mapping, page)) { - unlock_page(page); - return 1; + /* + * If we succeeded in removing the mapping, set LRU flag + * and return good. + */ + if (remove_mapping(mapping, page)) { + buf->flags |= PIPE_BUF_FLAG_LRU; + return 0; + } } - buf->flags |= PIPE_BUF_FLAG_LRU; - return 0; + /* + * Raced with truncate or failed to remove page from current + * address space, unlock and return failure. + */ + unlock_page(page); + return 1; } static void page_cache_pipe_buf_release(struct pipe_inode_info *pipe, -- cgit v1.2.3 From dd67d051529387f6e44d22d1d5540ef281965fdd Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 21 Jun 2006 09:36:18 +0200 Subject: [PATCH] rbtree: support functions used by the io schedulers They all duplicate macros to check for empty root and/or node, and clearing a node. So put those in rbtree.h. Signed-off-by: Jens Axboe --- block/as-iosched.c | 17 +++++++---------- block/cfq-iosched.c | 22 ++++++++-------------- block/deadline-iosched.c | 13 +++++-------- include/linux/rbtree.h | 4 ++++ 4 files changed, 24 insertions(+), 32 deletions(-) diff --git a/block/as-iosched.c b/block/as-iosched.c index 56c99fa037d..1ec5df46670 100644 --- a/block/as-iosched.c +++ b/block/as-iosched.c @@ -347,9 +347,6 @@ static struct request *as_find_arq_hash(struct as_data *ad, sector_t offset) /* * rb tree support functions */ -#define RB_EMPTY(root) ((root)->rb_node == NULL) -#define ON_RB(node) (rb_parent(node) != node) -#define RB_CLEAR(node) (rb_set_parent(node, node)) #define rb_entry_arq(node) rb_entry((node), struct as_rq, rb_node) #define ARQ_RB_ROOT(ad, arq) (&(ad)->sort_list[(arq)->is_sync]) #define rq_rb_key(rq) (rq)->sector @@ -418,13 +415,13 @@ static void as_add_arq_rb(struct as_data *ad, struct as_rq *arq) static inline void as_del_arq_rb(struct as_data *ad, struct as_rq *arq) { - if (!ON_RB(&arq->rb_node)) { + if (!RB_EMPTY_NODE(&arq->rb_node)) { WARN_ON(1); return; } rb_erase(&arq->rb_node, ARQ_RB_ROOT(ad, arq)); - RB_CLEAR(&arq->rb_node); + RB_CLEAR_NODE(&arq->rb_node); } static struct request * @@ -545,7 +542,7 @@ static struct as_rq *as_find_next_arq(struct as_data *ad, struct as_rq *last) struct rb_node *rbprev = rb_prev(&last->rb_node); struct as_rq *arq_next, *arq_prev; - BUG_ON(!ON_RB(&last->rb_node)); + BUG_ON(!RB_EMPTY_NODE(&last->rb_node)); if (rbprev) arq_prev = rb_entry_arq(rbprev); @@ -1122,7 +1119,7 @@ static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq) struct request *rq = arq->request; const int data_dir = arq->is_sync; - BUG_ON(!ON_RB(&arq->rb_node)); + BUG_ON(!RB_EMPTY_NODE(&arq->rb_node)); as_antic_stop(ad); ad->antic_status = ANTIC_OFF; @@ -1247,7 +1244,7 @@ static int as_dispatch_request(request_queue_t *q, int force) */ if (reads) { - BUG_ON(RB_EMPTY(&ad->sort_list[REQ_SYNC])); + BUG_ON(RB_EMPTY_ROOT(&ad->sort_list[REQ_SYNC])); if (writes && ad->batch_data_dir == REQ_SYNC) /* @@ -1271,7 +1268,7 @@ static int as_dispatch_request(request_queue_t *q, int force) if (writes) { dispatch_writes: - BUG_ON(RB_EMPTY(&ad->sort_list[REQ_ASYNC])); + BUG_ON(RB_EMPTY_ROOT(&ad->sort_list[REQ_ASYNC])); if (ad->batch_data_dir == REQ_SYNC) { ad->changed_batch = 1; @@ -1591,7 +1588,7 @@ static int as_set_request(request_queue_t *q, struct request *rq, if (arq) { memset(arq, 0, sizeof(*arq)); - RB_CLEAR(&arq->rb_node); + RB_CLEAR_NODE(&arq->rb_node); arq->request = rq; arq->state = AS_RQ_PRESCHED; arq->io_context = NULL; diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 940364edf2b..e25223e147a 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -60,11 +60,6 @@ static DEFINE_SPINLOCK(cfq_exit_lock); /* * rb-tree defines */ -#define RB_EMPTY(node) ((node)->rb_node == NULL) -#define RB_CLEAR(node) do { \ - memset(node, 0, sizeof(*node)); \ -} while (0) -#define RB_CLEAR_ROOT(root) ((root)->rb_node = NULL) #define rb_entry_crq(node) rb_entry((node), struct cfq_rq, rb_node) #define rq_rb_key(rq) (rq)->sector @@ -559,7 +554,7 @@ static inline void cfq_del_crq_rb(struct cfq_rq *crq) rb_erase(&crq->rb_node, &cfqq->sort_list); - if (cfq_cfqq_on_rr(cfqq) && RB_EMPTY(&cfqq->sort_list)) + if (cfq_cfqq_on_rr(cfqq) && RB_EMPTY_ROOT(&cfqq->sort_list)) cfq_del_cfqq_rr(cfqd, cfqq); } @@ -914,7 +909,7 @@ static int cfq_arm_slice_timer(struct cfq_data *cfqd, struct cfq_queue *cfqq) struct cfq_io_context *cic; unsigned long sl; - WARN_ON(!RB_EMPTY(&cfqq->sort_list)); + WARN_ON(!RB_EMPTY_ROOT(&cfqq->sort_list)); WARN_ON(cfqq != cfqd->active_queue); /* @@ -1042,7 +1037,7 @@ static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd) * if queue has requests, dispatch one. if not, check if * enough slice is left to wait for one */ - if (!RB_EMPTY(&cfqq->sort_list)) + if (!RB_EMPTY_ROOT(&cfqq->sort_list)) goto keep_queue; else if (cfq_cfqq_dispatched(cfqq)) { cfqq = NULL; @@ -1066,7 +1061,7 @@ __cfq_dispatch_requests(struct cfq_data *cfqd, struct cfq_queue *cfqq, { int dispatched = 0; - BUG_ON(RB_EMPTY(&cfqq->sort_list)); + BUG_ON(RB_EMPTY_ROOT(&cfqq->sort_list)); do { struct cfq_rq *crq; @@ -1090,7 +1085,7 @@ __cfq_dispatch_requests(struct cfq_data *cfqd, struct cfq_queue *cfqq, cfqd->active_cic = crq->io_context; } - if (RB_EMPTY(&cfqq->sort_list)) + if (RB_EMPTY_ROOT(&cfqq->sort_list)) break; } while (dispatched < max_dispatch); @@ -1480,7 +1475,6 @@ retry: INIT_HLIST_NODE(&cfqq->cfq_hash); INIT_LIST_HEAD(&cfqq->cfq_list); - RB_CLEAR_ROOT(&cfqq->sort_list); INIT_LIST_HEAD(&cfqq->fifo); cfqq->key = key; @@ -1873,7 +1867,7 @@ static void cfq_completed_request(request_queue_t *q, struct request *rq) if (cfqd->active_queue == cfqq) { if (time_after(now, cfqq->slice_end)) cfq_slice_expired(cfqd, 0); - else if (sync && RB_EMPTY(&cfqq->sort_list)) { + else if (sync && RB_EMPTY_ROOT(&cfqq->sort_list)) { if (!cfq_arm_slice_timer(cfqd, cfqq)) cfq_schedule_dispatch(cfqd); } @@ -2059,7 +2053,7 @@ cfq_set_request(request_queue_t *q, struct request *rq, struct bio *bio, crq = mempool_alloc(cfqd->crq_pool, gfp_mask); if (crq) { - RB_CLEAR(&crq->rb_node); + RB_CLEAR_NODE(&crq->rb_node); crq->rb_key = 0; crq->request = rq; INIT_HLIST_NODE(&crq->hash); @@ -2151,7 +2145,7 @@ static void cfq_idle_slice_timer(unsigned long data) /* * not expired and it has a request pending, let it dispatch */ - if (!RB_EMPTY(&cfqq->sort_list)) { + if (!RB_EMPTY_ROOT(&cfqq->sort_list)) { cfq_mark_cfqq_must_dispatch(cfqq); goto out_kick; } diff --git a/block/deadline-iosched.c b/block/deadline-iosched.c index e5bccaaed56..4469dd84623 100644 --- a/block/deadline-iosched.c +++ b/block/deadline-iosched.c @@ -159,9 +159,6 @@ deadline_find_drq_hash(struct deadline_data *dd, sector_t offset) /* * rb tree support functions */ -#define RB_EMPTY(root) ((root)->rb_node == NULL) -#define ON_RB(node) (rb_parent(node) != node) -#define RB_CLEAR(node) (rb_set_parent(node, node)) #define rb_entry_drq(node) rb_entry((node), struct deadline_rq, rb_node) #define DRQ_RB_ROOT(dd, drq) (&(dd)->sort_list[rq_data_dir((drq)->request)]) #define rq_rb_key(rq) (rq)->sector @@ -220,9 +217,9 @@ deadline_del_drq_rb(struct deadline_data *dd, struct deadline_rq *drq) dd->next_drq[data_dir] = rb_entry_drq(rbnext); } - BUG_ON(!ON_RB(&drq->rb_node)); + BUG_ON(!RB_EMPTY_NODE(&drq->rb_node)); rb_erase(&drq->rb_node, DRQ_RB_ROOT(dd, drq)); - RB_CLEAR(&drq->rb_node); + RB_CLEAR_NODE(&drq->rb_node); } static struct request * @@ -496,7 +493,7 @@ static int deadline_dispatch_requests(request_queue_t *q, int force) */ if (reads) { - BUG_ON(RB_EMPTY(&dd->sort_list[READ])); + BUG_ON(RB_EMPTY_ROOT(&dd->sort_list[READ])); if (writes && (dd->starved++ >= dd->writes_starved)) goto dispatch_writes; @@ -512,7 +509,7 @@ static int deadline_dispatch_requests(request_queue_t *q, int force) if (writes) { dispatch_writes: - BUG_ON(RB_EMPTY(&dd->sort_list[WRITE])); + BUG_ON(RB_EMPTY_ROOT(&dd->sort_list[WRITE])); dd->starved = 0; @@ -668,7 +665,7 @@ deadline_set_request(request_queue_t *q, struct request *rq, struct bio *bio, drq = mempool_alloc(dd->drq_pool, gfp_mask); if (drq) { memset(drq, 0, sizeof(*drq)); - RB_CLEAR(&drq->rb_node); + RB_CLEAR_NODE(&drq->rb_node); drq->request = rq; INIT_HLIST_NODE(&drq->hash); diff --git a/include/linux/rbtree.h b/include/linux/rbtree.h index f37006f2166..8d5382e62c0 100644 --- a/include/linux/rbtree.h +++ b/include/linux/rbtree.h @@ -132,6 +132,10 @@ static inline void rb_set_color(struct rb_node *rb, int color) #define RB_ROOT (struct rb_root) { NULL, } #define rb_entry(ptr, type, member) container_of(ptr, type, member) +#define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL) +#define RB_EMPTY_NODE(node) (rb_parent(node) != node) +#define RB_CLEAR_NODE(node) (rb_set_parent(node, node)) + extern void rb_insert_color(struct rb_node *, struct rb_root *); extern void rb_erase(struct rb_node *, struct rb_root *); -- cgit v1.2.3 From 8269730b389d4793348d521140f9c76fb1828249 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Wed, 21 Jun 2006 14:48:09 +0200 Subject: [BLOCK] Fix bounce limit address check Do a safer check for when to enable DMA. Currently we enable ISA DMA for cases that do not need it, resulting in OOM conditions when ZONE_DMA runs out of space. Signed-off-by: Jens Axboe --- block/ll_rw_blk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 2270bb45138..0603ab2f369 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -638,7 +638,7 @@ void blk_queue_bounce_limit(request_queue_t *q, u64 dma_addr) /* Assume anything <= 4GB can be handled by IOMMU. Actually some IOMMUs can handle everything, but I don't know of a way to test this here. */ - if (bounce_pfn < (0xffffffff>>PAGE_SHIFT)) + if (bounce_pfn < (min_t(u64,0xffffffff,BLK_BOUNCE_HIGH) >> PAGE_SHIFT)) dma = 1; q->bounce_pfn = max_low_pfn; #else -- cgit v1.2.3 From 138a0128c01899ee8492858a50856b90d0d9d815 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 23 Jun 2006 03:31:19 -0700 Subject: [PATCH] cpufreq build fix drivers/cpufreq/cpufreq_ondemand.c: In function 'do_dbs_timer': drivers/cpufreq/cpufreq_ondemand.c:374: warning: implicit declaration of function 'lock_cpu_hotplug' drivers/cpufreq/cpufreq_ondemand.c:381: warning: implicit declaration of function 'unlock_cpu_hotplug' drivers/cpufreq/cpufreq_conservative.c: In function 'do_dbs_timer': drivers/cpufreq/cpufreq_conservative.c:425: warning: implicit declaration of function 'lock_cpu_hotplug' drivers/cpufreq/cpufreq_conservative.c:432: warning: implicit declaration of function 'unlock_cpu_hotplug' Cc: Dave Jones Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/cpufreq/cpufreq_conservative.c | 1 + drivers/cpufreq/cpufreq_ondemand.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index 8878a154ed4..b3ebc8f0197 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 4d308410b60..693e540481b 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From a5cf4b9a02cb9b8ac16eaafb0fcd7fd24215146e Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 23 Jun 2006 04:01:35 -0700 Subject: [PATCH] s390_hypfs filesystem: get_sb_single() fix Update hypfs for dhowells API changes. Cc: Pekka Enberg Cc: Ingo Oeser Cc: Joern Engel Cc: Martin Schwidefsky Cc: Michael Holzheu Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/s390/hypfs/inode.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c index bab560a1357..18c091925ea 100644 --- a/arch/s390/hypfs/inode.c +++ b/arch/s390/hypfs/inode.c @@ -302,11 +302,10 @@ err_alloc: return rc; } -static struct super_block *hypfs_get_super(struct file_system_type *fst, - int flags, const char *devname, - void *data) +static int hypfs_get_super(struct file_system_type *fst, int flags, + const char *devname, void *data, struct vfsmount *mnt) { - return get_sb_single(fst, flags, data, hypfs_fill_super); + return get_sb_single(fst, flags, data, hypfs_fill_super, mnt); } static void hypfs_kill_super(struct super_block *sb) -- cgit v1.2.3 From 95eaa5fa8eb2c345244acd5f65b200b115ae8c65 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Fri, 23 Jun 2006 11:40:53 -0400 Subject: [PATCH] fix silly ARM non-EABI build error My bad. Signed-off-by: Nicolas Pitre Signed-off-by: Linus Torvalds --- arch/arm/kernel/signal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index e9fe7803336..f094277485c 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c @@ -687,7 +687,7 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall) * syscall solves that issue and works for * all those cases. */ - swival = swival - __NR_SYSCAll_BASE + __NR_OABI_SYSCALL_BASE; + swival = swival - __NR_SYSCALL_BASE + __NR_OABI_SYSCALL_BASE; put_user(regs->ARM_pc, &usp[0]); /* swi __NR_restart_syscall */ -- cgit v1.2.3 From 236ee8c33277ab48671995f26dc68a4639936418 Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Fri, 23 Jun 2006 13:49:25 -0700 Subject: [IA64] fix ia64 build (fadt_descriptor) arch/ia64/kernel/acpi.c got forgotten when include/acpi/actbl.h got a cleanup. Signed-off-by: Tony Luck --- arch/ia64/kernel/acpi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index 6ea642beaae..ca16d9556bd 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -618,7 +618,7 @@ EXPORT_SYMBOL(acpi_unregister_gsi); static int __init acpi_parse_fadt(unsigned long phys_addr, unsigned long size) { struct acpi_table_header *fadt_header; - struct fadt_descriptor_rev2 *fadt; + struct fadt_descriptor *fadt; if (!phys_addr || !size) return -EINVAL; @@ -627,7 +627,7 @@ static int __init acpi_parse_fadt(unsigned long phys_addr, unsigned long size) if (fadt_header->revision != 3) return -ENODEV; /* Only deal with ACPI 2.0 FADT */ - fadt = (struct fadt_descriptor_rev2 *)fadt_header; + fadt = (struct fadt_descriptor *)fadt_header; if (!(fadt->iapc_boot_arch & BAF_8042_KEYBOARD_CONTROLLER)) acpi_kbd_controller_present = 0; -- cgit v1.2.3 From d384ea691fe4ea8c2dd5b9b8d9042eb181776f18 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Sat, 24 Jun 2006 00:33:08 -0400 Subject: [PATCH] fix typo in acpi video brightness changes. Prevent possible null dereference due to misplaced ; Signed-off-by: Dave Jones Signed-off-by: Linus Torvalds --- drivers/acpi/video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 86531ab4ee5..e7e9a693953 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -1645,7 +1645,7 @@ static int acpi_video_bus_put_devices(struct acpi_video_bus *video) printk(KERN_WARNING PREFIX "hhuuhhuu bug in acpi video driver.\n"); - if (data->brightness); + if (data->brightness) kfree(data->brightness->levels); kfree(data->brightness); kfree(data); -- cgit v1.2.3